You've already forked computing-box
chore(assets): reorganise project files and add exported pages
- Move Bootstrap Studio design file into assets/bootstrap - Rename and relocate screenshots into assets/screenshot with kebab-case names - Add generated export HTML pages for simulators and site content - Preserve existing content with no functional changes to simulators Signed-off-by: Alexander Davis <alex@adcm.uk>
This commit is contained in:
210
export/assets/js/binary.js
Normal file
210
export/assets/js/binary.js
Normal file
@@ -0,0 +1,210 @@
|
||||
// ** Check if the filename contains "binary" **
|
||||
if (window.location.pathname.includes('binary')) {
|
||||
|
||||
let denary = 0;
|
||||
let bits = {
|
||||
'-128': false,
|
||||
'1': false,
|
||||
'2': false,
|
||||
'4': false,
|
||||
'8': false,
|
||||
'16': false,
|
||||
'32': false,
|
||||
'64': false,
|
||||
'128': false
|
||||
};
|
||||
|
||||
let bitValues = [];
|
||||
const twosComplementCheck = document.getElementById("blbN128");
|
||||
|
||||
// ** Initialize the bit values on page load **
|
||||
function initialize() {
|
||||
setBitValues(); // Set the bit values dynamically
|
||||
resetBinarySimulator(); // Reset the simulator to the initial state
|
||||
}
|
||||
|
||||
// ** Dynamically set bit values based on 2's complement mode **
|
||||
function setBitValues() {
|
||||
bitValues = twosComplementCheck
|
||||
? [-128, 64, 32, 16, 8, 4, 2, 1]
|
||||
: [128, 64, 32, 16, 8, 4, 2, 1];
|
||||
}
|
||||
|
||||
// ** Helper function to toggle power for a specific bit **
|
||||
function togglePower(bitValue, isActive) {
|
||||
const bitId = bitValue < 0 ? `N${Math.abs(bitValue)}` : bitValue;
|
||||
const bulb = document.getElementById(`blb${bitId}`);
|
||||
const switchBtn = document.getElementById(`swt${bitId}`);
|
||||
if (bulb && switchBtn) {
|
||||
bulb.classList.toggle('poweredOn', isActive);
|
||||
bulb.classList.toggle('poweredOff', !isActive);
|
||||
switchBtn.classList.toggle('btnActive', isActive);
|
||||
}
|
||||
}
|
||||
|
||||
// ** Reset all bits and denary **
|
||||
function resetBinarySimulator() {
|
||||
Object.keys(bits).forEach(bit => {
|
||||
togglePower(parseInt(bit, 10), false);
|
||||
bits[bit] = false;
|
||||
});
|
||||
denary = 0;
|
||||
updateBinary();
|
||||
}
|
||||
|
||||
// ** Toggle a specific bit **
|
||||
function changeBit(bitValue) {
|
||||
const key = getBitKey(bitValue);
|
||||
const isActive = bits[key];
|
||||
togglePower(bitValue, !isActive);
|
||||
bits[key] = !isActive;
|
||||
denary += isActive ? -bitValue : bitValue;
|
||||
updateBinary();
|
||||
}
|
||||
|
||||
// ** Update binary string and denary display **
|
||||
function updateBinary() {
|
||||
const binary = bitValues.map(bit => (bits[getBitKey(bit)] ? '1' : '0')).join('');
|
||||
document.getElementById("denaryNumber").innerText = denary;
|
||||
document.getElementById("binaryNumber").innerText = binary;
|
||||
}
|
||||
|
||||
// ** Parse a custom binary string and set bits accordingly **
|
||||
function customBinaryParser(binaryPattern) {
|
||||
resetBinarySimulator();
|
||||
binaryPattern = binaryPattern.padStart(8, '0'); // Ensure 8-bit format
|
||||
binaryPattern.split('').forEach((bit, index) => {
|
||||
if (bit === '1') {
|
||||
changeBit(bitValues[index]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ** Parse a custom denary value and set bits accordingly **
|
||||
function customDenaryParser(customDenary) {
|
||||
const min = twosComplementCheck ? -128 : 0;
|
||||
const max = twosComplementCheck ? 127 : 255;
|
||||
|
||||
if (customDenary === null) {
|
||||
customDenary = 0; // Default to 0 if user cancels input
|
||||
}
|
||||
|
||||
if (customDenary < min || customDenary > max) {
|
||||
alert(`Invalid input! Please enter a denary value between ${min} and ${max}.`);
|
||||
return requestDenary(); // Prompt user again
|
||||
}
|
||||
|
||||
resetBinarySimulator();
|
||||
if (twosComplementCheck && customDenary < 0) {
|
||||
let absDenary = Math.abs(customDenary);
|
||||
if (customDenary === -128) {
|
||||
changeBit(-128);
|
||||
} else {
|
||||
bitValues.forEach(bit => {
|
||||
if (absDenary >= Math.abs(bit)) {
|
||||
changeBit(bit);
|
||||
absDenary -= Math.abs(bit);
|
||||
}
|
||||
});
|
||||
twosComplementFlip();
|
||||
}
|
||||
} else {
|
||||
bitValues.forEach(bit => {
|
||||
if (customDenary >= Math.abs(bit)) {
|
||||
changeBit(bit);
|
||||
customDenary -= Math.abs(bit);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// ** Handle logical binary shifting (left or right) **
|
||||
function shiftBinary(direction) {
|
||||
const binaryString = document.getElementById("binaryNumber").innerText;
|
||||
let shiftedBinary;
|
||||
if (direction === 'left') {
|
||||
shiftedBinary = binaryString.slice(1) + '0';
|
||||
} else if (direction === 'right') {
|
||||
shiftedBinary = '0' + binaryString.slice(0, -1);
|
||||
}
|
||||
customBinaryParser(shiftedBinary);
|
||||
}
|
||||
|
||||
// ** Handle arithmetic shifting for 2's complement **
|
||||
function shiftTwosComplement(direction) {
|
||||
const binaryString = document.getElementById("binaryNumber").innerText;
|
||||
let shiftedBinary;
|
||||
if (direction === 'left') {
|
||||
shiftedBinary = binaryString.slice(1) + '0';
|
||||
} else if (direction === 'right') {
|
||||
shiftedBinary = binaryString[0] + binaryString.slice(0, -1);
|
||||
}
|
||||
customBinaryParser(shiftedBinary);
|
||||
}
|
||||
|
||||
// ** Flip binary bits for 2's complement **
|
||||
function twosComplementFlip() {
|
||||
let binary = document.getElementById("binaryNumber").innerText;
|
||||
const flippedBinary = binary.split('').map(bit => (bit === '1' ? '0' : '1')).join('');
|
||||
const result = addBinaryNumbers(flippedBinary, '00000001');
|
||||
customBinaryParser(result.binaryResult);
|
||||
}
|
||||
|
||||
// ** Add two binary numbers **
|
||||
function addBinaryNumbers(binary1, binary2) {
|
||||
let carry = 0;
|
||||
let result = '';
|
||||
for (let i = 7; i >= 0; i--) {
|
||||
const bit1 = parseInt(binary1[i], 10) || 0;
|
||||
const bit2 = parseInt(binary2[i], 10) || 0;
|
||||
const sum = bit1 + bit2 + carry;
|
||||
result = (sum % 2) + result;
|
||||
carry = Math.floor(sum / 2);
|
||||
}
|
||||
return { binaryResult: result.slice(-8), overflow: carry ? '1' : '0' };
|
||||
}
|
||||
|
||||
// ** Helper to normalize bit keys **
|
||||
function getBitKey(bitValue) {
|
||||
return bitValue < 0 ? `N${Math.abs(bitValue)}` : bitValue.toString();
|
||||
}
|
||||
|
||||
// ** Request binary input from user **
|
||||
function requestBinary() {
|
||||
let binary;
|
||||
do {
|
||||
binary = prompt("Please enter an 8-bit Binary Value (only 0s and 1s are allowed):");
|
||||
if (binary === null) {
|
||||
binary = "00000000"; // Default to 0 if user cancels input
|
||||
break;
|
||||
}
|
||||
if (!/^[01]{1,8}$/.test(binary)) {
|
||||
alert("Invalid input! Binary values must be up to 8 digits long and only contain 0 or 1.");
|
||||
}
|
||||
} while (!/^[01]{1,8}$/.test(binary));
|
||||
customBinaryParser(binary);
|
||||
}
|
||||
|
||||
// ** Request denary input from user **
|
||||
function requestDenary() {
|
||||
let customDenary;
|
||||
const min = twosComplementCheck ? -128 : 0;
|
||||
const max = twosComplementCheck ? 127 : 255;
|
||||
|
||||
do {
|
||||
customDenary = prompt(`Enter a Denary Value (${min} to ${max}):`);
|
||||
if (customDenary === null) {
|
||||
customDenary = 0; // Default to 0 if user cancels input
|
||||
break;
|
||||
}
|
||||
customDenary = parseInt(customDenary, 10);
|
||||
if (isNaN(customDenary) || customDenary < min || customDenary > max) {
|
||||
alert(`Invalid input! Please enter a denary value between ${min} and ${max}.`);
|
||||
}
|
||||
} while (isNaN(customDenary) || customDenary < min || customDenary > max);
|
||||
customDenaryParser(customDenary);
|
||||
}
|
||||
|
||||
// ** On page load, initialize the simulator **
|
||||
document.addEventListener("DOMContentLoaded", initialize);
|
||||
}
|
||||
61
export/assets/js/boldAndDark.js
Normal file
61
export/assets/js/boldAndDark.js
Normal file
@@ -0,0 +1,61 @@
|
||||
(function() {
|
||||
"use strict"; // Start of use strict
|
||||
|
||||
function initParallax() {
|
||||
|
||||
if (!('requestAnimationFrame' in window)) return;
|
||||
if (/Mobile|Android/.test(navigator.userAgent)) return;
|
||||
|
||||
var parallaxItems = document.querySelectorAll('[data-bss-parallax]');
|
||||
|
||||
if (!parallaxItems.length) return;
|
||||
|
||||
var defaultSpeed = 0.5;
|
||||
var visible = [];
|
||||
var scheduled;
|
||||
|
||||
window.addEventListener('scroll', scroll);
|
||||
window.addEventListener('resize', scroll);
|
||||
|
||||
scroll();
|
||||
|
||||
function scroll() {
|
||||
|
||||
visible.length = 0;
|
||||
|
||||
for (var i = 0; i < parallaxItems.length; i++) {
|
||||
var rect = parallaxItems[i].getBoundingClientRect();
|
||||
var speed = parseFloat(parallaxItems[i].getAttribute('data-bss-parallax-speed'), 10) || defaultSpeed;
|
||||
|
||||
if (rect.bottom > 0 && rect.top < window.innerHeight) {
|
||||
visible.push({
|
||||
speed: speed,
|
||||
node: parallaxItems[i]
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cancelAnimationFrame(scheduled);
|
||||
|
||||
if (visible.length) {
|
||||
scheduled = requestAnimationFrame(update);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function update() {
|
||||
|
||||
for (var i = 0; i < visible.length; i++) {
|
||||
var node = visible[i].node;
|
||||
var speed = visible[i].speed;
|
||||
|
||||
node.style.transform = 'translate3d(0, ' + (-window.scrollY * speed) + 'px, 0)';
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
initParallax();
|
||||
})(); // End of use strict
|
||||
|
||||
113
export/assets/js/hexColours.js
Normal file
113
export/assets/js/hexColours.js
Normal file
@@ -0,0 +1,113 @@
|
||||
const LIGHT_MULTIPLIER = 100 / 15;
|
||||
const COLORS = ['R', 'G', 'B'];
|
||||
const PLACES = [1, 16];
|
||||
|
||||
let denary = 0;
|
||||
let redDenary = 0;
|
||||
let greenDenary = 0;
|
||||
let blueDenary = 0;
|
||||
let redBinary = "";
|
||||
let greenBinary = "";
|
||||
let blueBinary = "";
|
||||
let hexadecimal = "";
|
||||
|
||||
const places = {
|
||||
R16: 0, R1: 0,
|
||||
G16: 0, G1: 0,
|
||||
B16: 0, B1: 0
|
||||
};
|
||||
|
||||
function resetColours() {
|
||||
COLORS.forEach(color => {
|
||||
PLACES.forEach(place => {
|
||||
resetPlace(color, place);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function resetPlace(color, place) {
|
||||
const placeKey = `${color}${place}`;
|
||||
places[placeKey] = 0;
|
||||
const light = (LIGHT_MULTIPLIER * places[placeKey]) / 100;
|
||||
document.getElementById(`blb${placeKey}`).style.opacity = light;
|
||||
updateColours();
|
||||
}
|
||||
|
||||
function togglePlace(color, place, direction) {
|
||||
const placeKey = `${color}${place}`;
|
||||
const currentValue = places[placeKey];
|
||||
if ((direction === 'up' && currentValue < 15) || (direction === 'down' && currentValue > 0)) {
|
||||
places[placeKey] += direction === 'up' ? 1 : -1;
|
||||
const light = (LIGHT_MULTIPLIER * places[placeKey]) / 100;
|
||||
document.getElementById(`blb${placeKey}`).style.opacity = light;
|
||||
updateColours();
|
||||
}
|
||||
}
|
||||
|
||||
function updateColours() {
|
||||
redDenary = (places.R16 * 16) + places.R1;
|
||||
greenDenary = (places.G16 * 16) + places.G1;
|
||||
blueDenary = (places.B16 * 16) + places.B1;
|
||||
|
||||
denary = `${redDenary}, ${greenDenary}, ${blueDenary}`;
|
||||
hexadecimal = `#${convertToHex(places.R16)}${convertToHex(places.R1)}${convertToHex(places.G16)}${convertToHex(places.G1)}${convertToHex(places.B16)}${convertToHex(places.B1)}`;
|
||||
|
||||
redBinary = `${convertToBinary(places.R16)}${convertToBinary(places.R1)}`;
|
||||
greenBinary = `${convertToBinary(places.G16)}${convertToBinary(places.G1)}`;
|
||||
blueBinary = `${convertToBinary(places.B16)}${convertToBinary(places.B1)}`;
|
||||
|
||||
document.getElementById("denaryNumber").innerHTML = denary;
|
||||
document.getElementById("hexadecimalNumber").innerHTML = hexadecimal;
|
||||
document.getElementById("colouredHex").style.backgroundColor = hexadecimal;
|
||||
document.getElementById("invertedHex").style.backgroundColor = invertedHex();
|
||||
document.getElementById("redBinaryNumber").innerHTML = redBinary;
|
||||
document.getElementById("blueBinaryNumber").innerHTML = blueBinary;
|
||||
document.getElementById("greenBinaryNumber").innerHTML = greenBinary;
|
||||
}
|
||||
|
||||
function invertedHex() {
|
||||
return `#${convertToHex(15 - places.R16)}${convertToHex(15 - places.R1)}${convertToHex(15 - places.G16)}${convertToHex(15 - places.G1)}${convertToHex(15 - places.B16)}${convertToHex(15 - places.B1)}`;
|
||||
}
|
||||
|
||||
function convertToHex(num) {
|
||||
return num < 10 ? num.toString() : String.fromCharCode(55 + num); // 55 = ASCII offset for A (65) - 10
|
||||
}
|
||||
|
||||
function convertToBinary(num) {
|
||||
return num.toString(2).padStart(4, '0');
|
||||
}
|
||||
|
||||
function updateHex(customHex) {
|
||||
if (!customHex) {
|
||||
resetColours();
|
||||
} else {
|
||||
if (customHex.charAt(0) === "#") customHex = customHex.slice(1);
|
||||
if (isHex(customHex) && customHex.length === 6) {
|
||||
customHex.split('').forEach((digit, i) => {
|
||||
const color = COLORS[Math.floor(i / 2)];
|
||||
const place = i % 2 === 0 ? 16 : 1;
|
||||
const placeKey = `${color}${place}`;
|
||||
places[placeKey] = parseInt(digit, 16);
|
||||
const light = (LIGHT_MULTIPLIER * places[placeKey]) / 100;
|
||||
document.getElementById(`blb${placeKey}`).style.opacity = light;
|
||||
});
|
||||
updateColours();
|
||||
} else {
|
||||
alert("Invalid Entry");
|
||||
resetColours();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function isHex(str) {
|
||||
return /^[0-9A-Fa-f]+$/.test(str);
|
||||
}
|
||||
|
||||
function requestHex() {
|
||||
const customHex = prompt("Please enter your Hex Value");
|
||||
updateHex(customHex);
|
||||
}
|
||||
|
||||
function invertHex() {
|
||||
updateHex(invertedHex());
|
||||
}
|
||||
63
export/assets/js/hexadecimal.js
Normal file
63
export/assets/js/hexadecimal.js
Normal file
@@ -0,0 +1,63 @@
|
||||
// Ensure the script only runs if the URL path contains "hexadecimal"
|
||||
if (window.location.pathname.includes('hexadecimal')) {
|
||||
|
||||
const isGCSE = window.location.pathname.includes('gcse-hexadecimal');
|
||||
const hexLength = isGCSE ? 2 : 4;
|
||||
const binaryLength = isGCSE ? 8 : 16;
|
||||
const maxDenary = isGCSE ? 255 : 65535;
|
||||
|
||||
const placeValues = { 1: 0, 16: 0, 256: 0, 4096: 0 };
|
||||
const sliders = {};
|
||||
const columnValues = isGCSE ? [16, 1] : [4096, 256, 16, 1];
|
||||
|
||||
// Attach event listeners for sliders
|
||||
['slider1', 'slider16', 'slider256', 'slider4096'].forEach((sliderId) => {
|
||||
const slider = document.getElementById(sliderId);
|
||||
if (slider) {
|
||||
sliders[sliderId] = slider;
|
||||
slider.addEventListener("input", (e) => {
|
||||
e.stopPropagation(); // Prevent event propagation to Bootstrap
|
||||
updatePlace(parseInt(sliderId.replace('slider', ''), 10));
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
function updatePlace(place) {
|
||||
if (sliders[`slider${place}`]) {
|
||||
placeValues[place] = parseInt(sliders[`slider${place}`].value, 10);
|
||||
updateNumbers();
|
||||
}
|
||||
}
|
||||
|
||||
function updateNumbers() {
|
||||
let denary = 0;
|
||||
let binary = '';
|
||||
let hexadecimal = '';
|
||||
|
||||
columnValues.forEach((column) => {
|
||||
const value = placeValues[column];
|
||||
denary += value * column;
|
||||
binary += convertToBinary(value);
|
||||
hexadecimal += convertToHex(value);
|
||||
});
|
||||
|
||||
binary = binary.slice(-binaryLength).padStart(binaryLength, '0');
|
||||
hexadecimal = hexadecimal.slice(-hexLength).padStart(hexLength, '0');
|
||||
|
||||
document.getElementById("binaryNumber").innerText = binary;
|
||||
document.getElementById("denaryNumber").innerText = denary;
|
||||
document.getElementById("hexadecimalNumber").innerText = hexadecimal;
|
||||
}
|
||||
|
||||
function convertToBinary(num) {
|
||||
return num.toString(2).padStart(4, '0');
|
||||
}
|
||||
|
||||
function convertToHex(num) {
|
||||
return num.toString(16).toUpperCase();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
updateNumbers();
|
||||
});
|
||||
}
|
||||
105
export/assets/js/logicGates.js
Normal file
105
export/assets/js/logicGates.js
Normal file
@@ -0,0 +1,105 @@
|
||||
let inputs = {
|
||||
input1: false,
|
||||
input2: false
|
||||
};
|
||||
|
||||
let gateValue = false;
|
||||
|
||||
// ** Toggle input (handles both input1 and input2) **
|
||||
function toggleInput(inputNumber) {
|
||||
const inputKey = `input${inputNumber}`;
|
||||
inputs[inputKey] = !inputs[inputKey];
|
||||
updateInputState(`swtInput${inputNumber}`, inputs[inputKey]);
|
||||
updateGate();
|
||||
}
|
||||
|
||||
// ** Update the gate's state based on the current inputs and gate type **
|
||||
function updateGate() {
|
||||
const pageHeading = document.getElementById("pageHeading").textContent;
|
||||
gateValue = evaluateGate(pageHeading);
|
||||
updateGateLight(pageHeading, gateValue);
|
||||
}
|
||||
|
||||
// ** Evaluate the gate logic **
|
||||
function evaluateGate(pageHeading) {
|
||||
const { input1, input2 } = inputs;
|
||||
|
||||
switch (pageHeading) {
|
||||
case "AND Gate":
|
||||
return input1 && input2;
|
||||
case "OR Gate":
|
||||
return input1 || input2;
|
||||
case "NOT Gate":
|
||||
return !input1; // NOT gate only uses Input1
|
||||
case "NAND Gate":
|
||||
return !(input1 && input2); // Correct NAND logic
|
||||
case "NOR Gate":
|
||||
return !(input1 || input2);
|
||||
case "XOR Gate":
|
||||
return input1 !== input2; // XOR is true if inputs are different
|
||||
case "XNOR Gate":
|
||||
return input1 === input2; // XNOR is true if inputs are the same
|
||||
default:
|
||||
console.error("Unknown Gate Type");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// ** Update the lightbulb based on the gate's value **
|
||||
function updateGateLight(pageHeading, value) {
|
||||
const lightBulbId = getLightBulbId(pageHeading);
|
||||
const lightBulb = document.getElementById(lightBulbId);
|
||||
if (lightBulb) {
|
||||
lightBulb.classList.toggle("poweredOn", value);
|
||||
lightBulb.classList.toggle("poweredOff", !value);
|
||||
}
|
||||
}
|
||||
|
||||
// ** Get the correct lightbulb ID based on the gate type **
|
||||
function getLightBulbId(pageHeading) {
|
||||
switch (pageHeading) {
|
||||
case "AND Gate":
|
||||
return "blbAndGate";
|
||||
case "OR Gate":
|
||||
return "blbOrGate";
|
||||
case "NOT Gate":
|
||||
return "blbNotGate";
|
||||
case "NAND Gate":
|
||||
return "blbNandGate";
|
||||
case "NOR Gate":
|
||||
return "blbNorGate";
|
||||
case "XOR Gate":
|
||||
return "blbXorGate";
|
||||
case "XNOR Gate":
|
||||
return "blbXnorGate";
|
||||
default:
|
||||
console.error("Unknown Gate Type");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// ** Update the toggle switch to reflect its active/inactive state **
|
||||
function updateInputState(switchId, isActive) {
|
||||
const toggleSwitch = document.getElementById(switchId);
|
||||
if (toggleSwitch) {
|
||||
toggleSwitch.classList.toggle("btnActive", isActive);
|
||||
}
|
||||
}
|
||||
|
||||
// ** Reset the gate to its default state **
|
||||
function resetGate() {
|
||||
inputs.input1 = false;
|
||||
inputs.input2 = false;
|
||||
updateInputState("swtInput1", inputs.input1);
|
||||
updateInputState("swtInput2", inputs.input2);
|
||||
|
||||
const pageHeading = document.getElementById("pageHeading").textContent;
|
||||
|
||||
if (pageHeading === "NOT Gate") {
|
||||
// For NOT Gate, the light should be on by default
|
||||
gateValue = true;
|
||||
updateGateLight(pageHeading, gateValue);
|
||||
} else {
|
||||
updateGate();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user