binary to decimal
This commit is contained in:
@@ -29,6 +29,10 @@
|
|||||||
--unit-5-light: #f0e7ff;
|
--unit-5-light: #f0e7ff;
|
||||||
--unit-5-dark: #5b21b6;
|
--unit-5-dark: #5b21b6;
|
||||||
|
|
||||||
|
--unit-6: #4f46e5;
|
||||||
|
--unit-6-light: #eef2ff;
|
||||||
|
--unit-6-dark: #3730a3;
|
||||||
|
|
||||||
--correct: #16a34a;
|
--correct: #16a34a;
|
||||||
--correct-light: #dcfce7;
|
--correct-light: #dcfce7;
|
||||||
--incorrect: #dc2626;
|
--incorrect: #dc2626;
|
||||||
@@ -66,6 +70,9 @@
|
|||||||
--color-unit-5: var(--unit-5);
|
--color-unit-5: var(--unit-5);
|
||||||
--color-unit-5-light: var(--unit-5-light);
|
--color-unit-5-light: var(--unit-5-light);
|
||||||
--color-unit-5-dark: var(--unit-5-dark);
|
--color-unit-5-dark: var(--unit-5-dark);
|
||||||
|
--color-unit-6: var(--unit-6);
|
||||||
|
--color-unit-6-light: var(--unit-6-light);
|
||||||
|
--color-unit-6-dark: var(--unit-6-dark);
|
||||||
|
|
||||||
--color-correct: var(--correct);
|
--color-correct: var(--correct);
|
||||||
--color-correct-light: var(--correct-light);
|
--color-correct-light: var(--correct-light);
|
||||||
|
|||||||
25
app/lessons/unit-6-number-system/binary/page.tsx
Normal file
25
app/lessons/unit-6-number-system/binary/page.tsx
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { Breadcrumbs } from "@/components/layout/breadcrumbs";
|
||||||
|
import { BinaryConverterExplorer } from "@/components/explorers/binary-converter-explorer";
|
||||||
|
|
||||||
|
export default function BinaryPage() {
|
||||||
|
return (
|
||||||
|
<div className="space-y-8">
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "Lessons", href: "/lessons" },
|
||||||
|
{ label: "Unit 6: Number System", href: "/lessons/unit-6-number-system" },
|
||||||
|
{ label: "Binary" },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h1 className="text-3xl font-bold tracking-tight">Binary → Decimal Converter</h1>
|
||||||
|
<p className="mt-2 text-muted">Same shape, different base — explore place value in powers of 2.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<BinaryConverterExplorer />
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
41
app/lessons/unit-6-number-system/page.tsx
Normal file
41
app/lessons/unit-6-number-system/page.tsx
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import Link from "next/link";
|
||||||
|
import { curriculum } from "@/lib/curriculum";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
import { Badge } from "@/components/ui/badge";
|
||||||
|
import { Breadcrumbs } from "@/components/layout/breadcrumbs";
|
||||||
|
|
||||||
|
export default function Unit6Overview() {
|
||||||
|
const unit = curriculum[5];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Breadcrumbs
|
||||||
|
items={[
|
||||||
|
{ label: "Lessons", href: "/lessons" },
|
||||||
|
{ label: `Unit 6: ${unit.title}` },
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<div className="mb-10">
|
||||||
|
<Badge variant="unit-6" className="mb-3">Unit 6 — {unit.weeks}</Badge>
|
||||||
|
<h1 className="mb-2 text-3xl font-bold tracking-tight">{unit.title}</h1>
|
||||||
|
<p className="text-muted leading-relaxed">{unit.description}</p>
|
||||||
|
</div>
|
||||||
|
<div className="grid gap-4 sm:grid-cols-2">
|
||||||
|
{unit.topics.map((topic, i) => (
|
||||||
|
<Link key={topic.slug} href={`/lessons/${unit.slug}/${topic.slug}`}>
|
||||||
|
<Card accent="unit-6" hover className="group h-full">
|
||||||
|
<div className="mb-2 flex items-center gap-2">
|
||||||
|
<span className="flex h-7 w-7 items-center justify-center rounded-lg bg-unit-6-light text-xs font-bold text-unit-6-dark shadow-[var(--shadow-sm)]">
|
||||||
|
{i + 1}
|
||||||
|
</span>
|
||||||
|
<span className="text-xs text-muted">Week {topic.week}</span>
|
||||||
|
</div>
|
||||||
|
<h3 className="mb-1 font-semibold">{topic.title}</h3>
|
||||||
|
<p className="text-sm leading-relaxed text-muted">{topic.description}</p>
|
||||||
|
</Card>
|
||||||
|
</Link>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -29,6 +29,11 @@ const unitStyles = {
|
|||||||
unitCard: "border-[#c4b5fd] bg-[#f5f0ff]",
|
unitCard: "border-[#c4b5fd] bg-[#f5f0ff]",
|
||||||
chip: "bg-[#6d28d9]",
|
chip: "bg-[#6d28d9]",
|
||||||
},
|
},
|
||||||
|
"unit-6": {
|
||||||
|
tile: "from-[#818cf8] to-[#3730a3]",
|
||||||
|
unitCard: "border-[#a5b4fc] bg-[#eef2ff]",
|
||||||
|
chip: "bg-[#3730a3]",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
const topicTiles = [
|
const topicTiles = [
|
||||||
|
|||||||
459
binary-to-decimal-converter.html
Normal file
459
binary-to-decimal-converter.html
Normal file
@@ -0,0 +1,459 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Binary to Decimal Converter - Form 1</title>
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
--primary: #4527a0;
|
||||||
|
--accent: #00838f;
|
||||||
|
--soft: #ede7f6;
|
||||||
|
--soft-alt: #d1c4e9;
|
||||||
|
--good: #2e7d32;
|
||||||
|
--good-soft: #e8f5e9;
|
||||||
|
--warn: #c62828;
|
||||||
|
--warn-soft: #ffebee;
|
||||||
|
--ink: #1a1a1a;
|
||||||
|
}
|
||||||
|
* { box-sizing: border-box; }
|
||||||
|
body {
|
||||||
|
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||||
|
line-height: 1.5;
|
||||||
|
max-width: 1100px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 20px;
|
||||||
|
background: #f5f3fa;
|
||||||
|
color: var(--ink);
|
||||||
|
}
|
||||||
|
.app {
|
||||||
|
background: #fff;
|
||||||
|
padding: 28px 34px;
|
||||||
|
border: 2px solid var(--primary);
|
||||||
|
box-shadow: 0 2px 10px rgba(69, 39, 160, 0.08);
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 3px solid var(--primary);
|
||||||
|
padding-bottom: 12px;
|
||||||
|
margin-bottom: 18px;
|
||||||
|
}
|
||||||
|
.header h1 { margin: 0; font-size: 1.6em; color: var(--primary); }
|
||||||
|
.header h2 { margin: 4px 0 0; font-size: 1em; color: var(--accent); font-weight: normal; }
|
||||||
|
h3 {
|
||||||
|
border-bottom: 2px solid var(--primary);
|
||||||
|
padding: 6px 0;
|
||||||
|
margin: 22px 0 10px 0;
|
||||||
|
font-size: 1.1em;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.5px;
|
||||||
|
color: var(--primary);
|
||||||
|
}
|
||||||
|
.input-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 14px;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
}
|
||||||
|
.input-row label {
|
||||||
|
font-weight: bold;
|
||||||
|
color: var(--primary);
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
#binaryInput {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 1.6em;
|
||||||
|
padding: 6px 10px;
|
||||||
|
border: 2px solid var(--primary);
|
||||||
|
color: var(--primary);
|
||||||
|
letter-spacing: 4px;
|
||||||
|
width: 220px;
|
||||||
|
text-align: center;
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
#binaryInput:focus {
|
||||||
|
outline: 2px solid var(--accent);
|
||||||
|
outline-offset: 2px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
font-family: inherit;
|
||||||
|
font-size: 0.95em;
|
||||||
|
padding: 8px 14px;
|
||||||
|
border: 1.5px solid var(--accent);
|
||||||
|
background: #fff;
|
||||||
|
color: var(--accent);
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.4px;
|
||||||
|
}
|
||||||
|
button:hover { background: var(--soft); color: var(--primary); border-color: var(--primary); }
|
||||||
|
button.primary { background: var(--primary); color: #fff; border-color: var(--primary); }
|
||||||
|
button.primary:hover { background: #311b92; color: #fff; }
|
||||||
|
button.warn { color: var(--warn); border-color: var(--warn); }
|
||||||
|
button.warn:hover { background: var(--warn-soft); color: var(--warn); }
|
||||||
|
.preset-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 6px 0 12px;
|
||||||
|
}
|
||||||
|
.preset-row button {
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
letter-spacing: 2px;
|
||||||
|
padding: 4px 10px;
|
||||||
|
font-size: 1em;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.chart-wrapper {
|
||||||
|
border: 2px solid var(--primary);
|
||||||
|
padding: 14px;
|
||||||
|
margin: 12px 0;
|
||||||
|
background: var(--soft);
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
.chart {
|
||||||
|
margin: 0 auto;
|
||||||
|
border-collapse: collapse;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
.chart td {
|
||||||
|
border: 1.5px solid var(--primary);
|
||||||
|
padding: 10px 18px;
|
||||||
|
text-align: center;
|
||||||
|
background: #fff;
|
||||||
|
min-width: 64px;
|
||||||
|
}
|
||||||
|
.chart .row-power { background: var(--soft); color: var(--primary); font-weight: bold; font-size: 1em; }
|
||||||
|
.chart .row-value { background: #fff; color: var(--primary); font-weight: bold; font-size: 1.15em; }
|
||||||
|
.chart .row-digit { background: #fff; font-size: 1.6em; font-weight: bold; }
|
||||||
|
.chart .row-contrib { background: #fafbfc; color: var(--accent); font-weight: bold; font-size: 1.05em; }
|
||||||
|
.chart .row-digit.is-one { background: var(--good-soft); color: var(--good); }
|
||||||
|
.chart .row-contrib.is-one { background: var(--good-soft); color: var(--good); }
|
||||||
|
.chart .row-digit.is-zero { color: #888; }
|
||||||
|
.chart .row-contrib.is-zero { color: #888; }
|
||||||
|
.working-line {
|
||||||
|
text-align: center;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
font-size: 1.2em;
|
||||||
|
margin: 10px 0;
|
||||||
|
color: var(--primary);
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.answer-banner {
|
||||||
|
border: 2px solid var(--good);
|
||||||
|
background: var(--good-soft);
|
||||||
|
color: var(--good);
|
||||||
|
padding: 14px 18px;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 1.4em;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 14px 0 6px;
|
||||||
|
font-family: 'Courier New', monospace;
|
||||||
|
}
|
||||||
|
.answer-banner.hidden {
|
||||||
|
background: var(--soft);
|
||||||
|
color: var(--primary);
|
||||||
|
border-color: var(--primary);
|
||||||
|
}
|
||||||
|
.error-banner {
|
||||||
|
border: 2px solid var(--warn);
|
||||||
|
background: var(--warn-soft);
|
||||||
|
color: var(--warn);
|
||||||
|
padding: 10px 14px;
|
||||||
|
text-align: center;
|
||||||
|
font-weight: bold;
|
||||||
|
margin: 12px 0;
|
||||||
|
}
|
||||||
|
.controls-row {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
margin: 6px 0 0;
|
||||||
|
}
|
||||||
|
.footer-note {
|
||||||
|
margin-top: 18px;
|
||||||
|
padding: 8px 12px;
|
||||||
|
border-left: 4px solid var(--accent);
|
||||||
|
background: var(--soft);
|
||||||
|
color: var(--primary);
|
||||||
|
font-size: 0.92em;
|
||||||
|
}
|
||||||
|
@media print {
|
||||||
|
body { background: #fff !important; color: #000 !important; }
|
||||||
|
.app { border: 1.5px solid #000 !important; box-shadow: none !important; }
|
||||||
|
*, *::before, *::after {
|
||||||
|
background: #fff !important;
|
||||||
|
background-color: #fff !important;
|
||||||
|
color: #000 !important;
|
||||||
|
box-shadow: none !important;
|
||||||
|
}
|
||||||
|
.header, h3, .chart-wrapper, .chart td, .answer-banner, .error-banner, button, .footer-note {
|
||||||
|
border-color: #000 !important;
|
||||||
|
}
|
||||||
|
button { display: none !important; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div class="app">
|
||||||
|
<div class="header">
|
||||||
|
<h1>BINARY → DECIMAL CONVERTER</h1>
|
||||||
|
<h2>Form 1 - Lesson 30 - Same shape, different base</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h3>Type a Binary Number</h3>
|
||||||
|
<div class="input-row">
|
||||||
|
<label for="binaryInput">Binary:</label>
|
||||||
|
<input id="binaryInput" type="text" maxlength="8" autocomplete="off" spellcheck="false" placeholder="e.g. 1011">
|
||||||
|
<button class="primary" id="convertBtn">Convert</button>
|
||||||
|
<button id="clearBtn">Clear</button>
|
||||||
|
<button id="randomBtn">Random</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="preset-row">
|
||||||
|
<button data-preset="101">101</button>
|
||||||
|
<button data-preset="1011">1011</button>
|
||||||
|
<button data-preset="1101">1101</button>
|
||||||
|
<button data-preset="10101">10101</button>
|
||||||
|
<button data-preset="11000">11000</button>
|
||||||
|
<button data-preset="11111">11111</button>
|
||||||
|
<button data-preset="100000">100000</button>
|
||||||
|
<button data-preset="110010">110010</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="errorMsg" class="error-banner" style="display: none;"></div>
|
||||||
|
|
||||||
|
<h3>Place Value Chart (powers of 2)</h3>
|
||||||
|
<div class="chart-wrapper">
|
||||||
|
<table class="chart">
|
||||||
|
<tbody id="chartBody"></tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="workingLine" class="working-line"></div>
|
||||||
|
|
||||||
|
<div id="answerBanner" class="answer-banner hidden">Type a binary number above and press Convert.</div>
|
||||||
|
|
||||||
|
<div class="controls-row">
|
||||||
|
<button id="revealBtn">Hide Answer</button>
|
||||||
|
<button id="hideChartBtn">Hide Chart</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer-note">
|
||||||
|
<strong>For students:</strong> solve on paper <em>first</em> using the chart in your worksheet. Type the binary number here only to <em>check</em>. The lesson is in the chart, not the click.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
(function() {
|
||||||
|
const input = document.getElementById('binaryInput');
|
||||||
|
const convertBtn = document.getElementById('convertBtn');
|
||||||
|
const clearBtn = document.getElementById('clearBtn');
|
||||||
|
const randomBtn = document.getElementById('randomBtn');
|
||||||
|
const revealBtn = document.getElementById('revealBtn');
|
||||||
|
const hideChartBtn = document.getElementById('hideChartBtn');
|
||||||
|
const chartBody = document.getElementById('chartBody');
|
||||||
|
const chartWrapper = document.querySelector('.chart-wrapper');
|
||||||
|
const workingLine = document.getElementById('workingLine');
|
||||||
|
const answerBanner = document.getElementById('answerBanner');
|
||||||
|
const errorMsg = document.getElementById('errorMsg');
|
||||||
|
|
||||||
|
let answerHidden = false;
|
||||||
|
let chartHidden = false;
|
||||||
|
|
||||||
|
function clearError() {
|
||||||
|
errorMsg.style.display = 'none';
|
||||||
|
errorMsg.textContent = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
function showError(msg) {
|
||||||
|
errorMsg.textContent = msg;
|
||||||
|
errorMsg.style.display = 'block';
|
||||||
|
}
|
||||||
|
|
||||||
|
function powerOfTwo(n) {
|
||||||
|
let v = 1;
|
||||||
|
for (let i = 0; i < n; i++) v *= 2;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildChartFor(binaryStr) {
|
||||||
|
const n = binaryStr.length;
|
||||||
|
const powerRow = document.createElement('tr');
|
||||||
|
const valueRow = document.createElement('tr');
|
||||||
|
const digitRow = document.createElement('tr');
|
||||||
|
const contribRow = document.createElement('tr');
|
||||||
|
|
||||||
|
powerRow.className = '';
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const exponent = n - 1 - i;
|
||||||
|
const digit = binaryStr[i];
|
||||||
|
const placeVal = powerOfTwo(exponent);
|
||||||
|
const contrib = parseInt(digit, 10) * placeVal;
|
||||||
|
|
||||||
|
const pTd = document.createElement('td');
|
||||||
|
pTd.className = 'row-power';
|
||||||
|
pTd.innerHTML = '2<sup>' + exponent + '</sup>';
|
||||||
|
powerRow.appendChild(pTd);
|
||||||
|
|
||||||
|
const vTd = document.createElement('td');
|
||||||
|
vTd.className = 'row-value';
|
||||||
|
vTd.textContent = placeVal;
|
||||||
|
valueRow.appendChild(vTd);
|
||||||
|
|
||||||
|
const dTd = document.createElement('td');
|
||||||
|
dTd.className = 'row-digit ' + (digit === '1' ? 'is-one' : 'is-zero');
|
||||||
|
dTd.textContent = digit;
|
||||||
|
digitRow.appendChild(dTd);
|
||||||
|
|
||||||
|
const cTd = document.createElement('td');
|
||||||
|
cTd.className = 'row-contrib ' + (digit === '1' ? 'is-one' : 'is-zero');
|
||||||
|
cTd.textContent = contrib;
|
||||||
|
contribRow.appendChild(cTd);
|
||||||
|
}
|
||||||
|
|
||||||
|
chartBody.innerHTML = '';
|
||||||
|
chartBody.appendChild(powerRow);
|
||||||
|
chartBody.appendChild(valueRow);
|
||||||
|
chartBody.appendChild(digitRow);
|
||||||
|
chartBody.appendChild(contribRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
function renderEmpty() {
|
||||||
|
chartBody.innerHTML = '';
|
||||||
|
const powerRow = document.createElement('tr');
|
||||||
|
const valueRow = document.createElement('tr');
|
||||||
|
const digitRow = document.createElement('tr');
|
||||||
|
const contribRow = document.createElement('tr');
|
||||||
|
for (let exp = 5; exp >= 0; exp--) {
|
||||||
|
const placeVal = powerOfTwo(exp);
|
||||||
|
const pTd = document.createElement('td');
|
||||||
|
pTd.className = 'row-power';
|
||||||
|
pTd.innerHTML = '2<sup>' + exp + '</sup>';
|
||||||
|
powerRow.appendChild(pTd);
|
||||||
|
const vTd = document.createElement('td');
|
||||||
|
vTd.className = 'row-value';
|
||||||
|
vTd.textContent = placeVal;
|
||||||
|
valueRow.appendChild(vTd);
|
||||||
|
const dTd = document.createElement('td');
|
||||||
|
dTd.className = 'row-digit is-zero';
|
||||||
|
dTd.textContent = '_';
|
||||||
|
digitRow.appendChild(dTd);
|
||||||
|
const cTd = document.createElement('td');
|
||||||
|
cTd.className = 'row-contrib is-zero';
|
||||||
|
cTd.textContent = '_';
|
||||||
|
contribRow.appendChild(cTd);
|
||||||
|
}
|
||||||
|
chartBody.appendChild(powerRow);
|
||||||
|
chartBody.appendChild(valueRow);
|
||||||
|
chartBody.appendChild(digitRow);
|
||||||
|
chartBody.appendChild(contribRow);
|
||||||
|
workingLine.textContent = '';
|
||||||
|
setBanner('Type a binary number above and press Convert.', true);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setBanner(text, hidden) {
|
||||||
|
answerBanner.textContent = text;
|
||||||
|
if (hidden) answerBanner.classList.add('hidden');
|
||||||
|
else answerBanner.classList.remove('hidden');
|
||||||
|
}
|
||||||
|
|
||||||
|
function convert() {
|
||||||
|
clearError();
|
||||||
|
const raw = input.value.trim();
|
||||||
|
if (raw.length === 0) {
|
||||||
|
showError('Type a binary number first (only 0s and 1s).');
|
||||||
|
renderEmpty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/^[01]+$/.test(raw)) {
|
||||||
|
showError('Binary numbers use only 0 and 1. Found another digit.');
|
||||||
|
renderEmpty();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (raw.length > 8) {
|
||||||
|
showError('Keep it to 8 digits or fewer for this lesson.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buildChartFor(raw);
|
||||||
|
|
||||||
|
const n = raw.length;
|
||||||
|
let total = 0;
|
||||||
|
const ones = [];
|
||||||
|
const allTerms = [];
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const exponent = n - 1 - i;
|
||||||
|
const digit = parseInt(raw[i], 10);
|
||||||
|
const placeVal = powerOfTwo(exponent);
|
||||||
|
allTerms.push(digit + '×' + placeVal);
|
||||||
|
if (digit === 1) {
|
||||||
|
ones.push(placeVal);
|
||||||
|
total += placeVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
const fullExpansion = allTerms.join(' + ');
|
||||||
|
const onesOnly = ones.length > 0 ? ones.join(' + ') + ' = ' + total : '0';
|
||||||
|
workingLine.innerHTML = fullExpansion + '<br>= ' + onesOnly;
|
||||||
|
|
||||||
|
if (answerHidden) {
|
||||||
|
setBanner(raw + '₂ = ? (press Show Answer)', true);
|
||||||
|
} else {
|
||||||
|
setBanner(raw + '₂ = ' + total + ' in denary', false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input.addEventListener('input', function() {
|
||||||
|
input.value = input.value.replace(/[^01]/g, '');
|
||||||
|
});
|
||||||
|
input.addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter') convert();
|
||||||
|
});
|
||||||
|
|
||||||
|
convertBtn.addEventListener('click', convert);
|
||||||
|
|
||||||
|
clearBtn.addEventListener('click', function() {
|
||||||
|
input.value = '';
|
||||||
|
clearError();
|
||||||
|
renderEmpty();
|
||||||
|
input.focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
randomBtn.addEventListener('click', function() {
|
||||||
|
const len = 3 + Math.floor(Math.random() * 4);
|
||||||
|
let s = '1';
|
||||||
|
for (let i = 1; i < len; i++) {
|
||||||
|
s += (Math.random() < 0.5 ? '0' : '1');
|
||||||
|
}
|
||||||
|
input.value = s;
|
||||||
|
convert();
|
||||||
|
});
|
||||||
|
|
||||||
|
document.querySelectorAll('.preset-row button[data-preset]').forEach(function(btn) {
|
||||||
|
btn.addEventListener('click', function() {
|
||||||
|
input.value = btn.getAttribute('data-preset');
|
||||||
|
convert();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
revealBtn.addEventListener('click', function() {
|
||||||
|
answerHidden = !answerHidden;
|
||||||
|
revealBtn.textContent = answerHidden ? 'Show Answer' : 'Hide Answer';
|
||||||
|
if (input.value.trim().length > 0) convert();
|
||||||
|
});
|
||||||
|
|
||||||
|
hideChartBtn.addEventListener('click', function() {
|
||||||
|
chartHidden = !chartHidden;
|
||||||
|
chartWrapper.style.display = chartHidden ? 'none' : 'block';
|
||||||
|
hideChartBtn.textContent = chartHidden ? 'Show Chart' : 'Hide Chart';
|
||||||
|
});
|
||||||
|
|
||||||
|
renderEmpty();
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
317
components/explorers/binary-converter-explorer.tsx
Normal file
317
components/explorers/binary-converter-explorer.tsx
Normal file
@@ -0,0 +1,317 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState, useMemo, useCallback } from "react";
|
||||||
|
import { Card } from "@/components/ui/card";
|
||||||
|
|
||||||
|
const PRESETS = ["101", "1011", "1101", "10101", "11000", "11111", "100000", "110010"];
|
||||||
|
|
||||||
|
interface Column {
|
||||||
|
exponent: number;
|
||||||
|
placeValue: number;
|
||||||
|
digit: string;
|
||||||
|
contrib: number;
|
||||||
|
isOne: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
function powerOfTwo(n: number) {
|
||||||
|
let v = 1;
|
||||||
|
for (let i = 0; i < n; i++) v *= 2;
|
||||||
|
return v;
|
||||||
|
}
|
||||||
|
|
||||||
|
function buildColumnsFor(binaryStr: string): Column[] {
|
||||||
|
const n = binaryStr.length;
|
||||||
|
const cols: Column[] = [];
|
||||||
|
for (let i = 0; i < n; i++) {
|
||||||
|
const exponent = n - 1 - i;
|
||||||
|
const digit = binaryStr[i];
|
||||||
|
const placeValue = powerOfTwo(exponent);
|
||||||
|
const isOne = digit === "1";
|
||||||
|
cols.push({
|
||||||
|
exponent,
|
||||||
|
placeValue,
|
||||||
|
digit,
|
||||||
|
contrib: parseInt(digit, 10) * placeValue,
|
||||||
|
isOne,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
function emptyColumns(): Column[] {
|
||||||
|
const cols: Column[] = [];
|
||||||
|
for (let exp = 5; exp >= 0; exp--) {
|
||||||
|
cols.push({
|
||||||
|
exponent: exp,
|
||||||
|
placeValue: powerOfTwo(exp),
|
||||||
|
digit: "_",
|
||||||
|
contrib: 0,
|
||||||
|
isOne: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return cols;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function BinaryConverterExplorer() {
|
||||||
|
const [input, setInput] = useState("");
|
||||||
|
const [submitted, setSubmitted] = useState<string | null>(null);
|
||||||
|
const [error, setError] = useState("");
|
||||||
|
const [answerHidden, setAnswerHidden] = useState(false);
|
||||||
|
const [chartHidden, setChartHidden] = useState(false);
|
||||||
|
|
||||||
|
const handleInputChange = (value: string) => {
|
||||||
|
setInput(value.replace(/[^01]/g, ""));
|
||||||
|
setError("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const convert = useCallback((raw?: string) => {
|
||||||
|
const source = (raw ?? input).trim();
|
||||||
|
if (source.length === 0) {
|
||||||
|
setError("Type a binary number first (only 0s and 1s).");
|
||||||
|
setSubmitted(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!/^[01]+$/.test(source)) {
|
||||||
|
setError("Binary numbers use only 0 and 1. Found another digit.");
|
||||||
|
setSubmitted(null);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (source.length > 8) {
|
||||||
|
setError("Keep it to 8 digits or fewer for this lesson.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setError("");
|
||||||
|
setSubmitted(source);
|
||||||
|
}, [input]);
|
||||||
|
|
||||||
|
const applyPreset = (value: string) => {
|
||||||
|
setInput(value);
|
||||||
|
convert(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClear = () => {
|
||||||
|
setInput("");
|
||||||
|
setSubmitted(null);
|
||||||
|
setError("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleRandom = () => {
|
||||||
|
const len = 3 + Math.floor(Math.random() * 4);
|
||||||
|
let s = "1";
|
||||||
|
for (let i = 1; i < len; i++) {
|
||||||
|
s += Math.random() < 0.5 ? "0" : "1";
|
||||||
|
}
|
||||||
|
setInput(s);
|
||||||
|
convert(s);
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns = useMemo(() => {
|
||||||
|
if (!submitted) return emptyColumns();
|
||||||
|
return buildColumnsFor(submitted);
|
||||||
|
}, [submitted]);
|
||||||
|
|
||||||
|
const total = useMemo(() => {
|
||||||
|
if (!submitted) return 0;
|
||||||
|
return columns.reduce((acc, c) => acc + c.contrib, 0);
|
||||||
|
}, [columns, submitted]);
|
||||||
|
|
||||||
|
const fullExpansion = submitted
|
||||||
|
? columns.map((c) => `${c.digit}×${c.placeValue}`).join(" + ")
|
||||||
|
: "";
|
||||||
|
|
||||||
|
const onesOnly = submitted
|
||||||
|
? columns.filter((c) => c.isOne).length > 0
|
||||||
|
? columns.filter((c) => c.isOne).map((c) => c.placeValue).join(" + ") + " = " + total
|
||||||
|
: "0"
|
||||||
|
: "";
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="space-y-4">
|
||||||
|
{/* Input Card */}
|
||||||
|
<Card>
|
||||||
|
<p className="mb-3 text-xs font-bold uppercase tracking-wider text-unit-6">
|
||||||
|
Type a Binary Number
|
||||||
|
</p>
|
||||||
|
<div className="flex flex-wrap items-center gap-3">
|
||||||
|
<label
|
||||||
|
htmlFor="binaryInput"
|
||||||
|
className="text-sm font-bold text-unit-6-dark"
|
||||||
|
>
|
||||||
|
Binary:
|
||||||
|
</label>
|
||||||
|
<input
|
||||||
|
id="binaryInput"
|
||||||
|
type="text"
|
||||||
|
inputMode="numeric"
|
||||||
|
maxLength={8}
|
||||||
|
autoComplete="off"
|
||||||
|
spellCheck={false}
|
||||||
|
placeholder="e.g. 1011"
|
||||||
|
value={input}
|
||||||
|
onChange={(e) => handleInputChange(e.target.value)}
|
||||||
|
onKeyDown={(e) => {
|
||||||
|
if (e.key === "Enter") convert();
|
||||||
|
}}
|
||||||
|
className="w-44 rounded-lg border-2 border-unit-6 bg-surface px-3 py-2 text-center font-mono text-2xl font-bold tracking-[0.3em] text-unit-6 outline-none focus:border-unit-6-dark"
|
||||||
|
aria-label="Binary number input"
|
||||||
|
/>
|
||||||
|
<button
|
||||||
|
onClick={() => convert()}
|
||||||
|
className="rounded-lg bg-unit-6 px-5 py-2.5 text-sm font-bold text-white transition-colors hover:bg-unit-6-dark"
|
||||||
|
>
|
||||||
|
Convert
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleClear}
|
||||||
|
className="rounded-lg border-2 border-border bg-surface px-4 py-2 text-sm font-bold text-muted transition-colors hover:border-unit-6/50 hover:text-unit-6"
|
||||||
|
>
|
||||||
|
Clear
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
onClick={handleRandom}
|
||||||
|
className="rounded-lg border-2 border-border bg-surface px-4 py-2 text-sm font-bold text-muted transition-colors hover:border-unit-6/50 hover:text-unit-6"
|
||||||
|
>
|
||||||
|
Random
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div className="mt-4 flex flex-wrap gap-2">
|
||||||
|
{PRESETS.map((p) => (
|
||||||
|
<button
|
||||||
|
key={p}
|
||||||
|
onClick={() => applyPreset(p)}
|
||||||
|
className="rounded-lg border-2 border-unit-6/30 bg-unit-6-light px-3 py-1 font-mono text-sm font-bold tracking-widest text-unit-6-dark transition-colors hover:border-unit-6 hover:bg-unit-6 hover:text-white"
|
||||||
|
>
|
||||||
|
{p}
|
||||||
|
</button>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{error && (
|
||||||
|
<p className="mt-3 rounded-lg border-2 border-incorrect bg-incorrect-light px-3 py-2 text-center text-sm font-bold text-incorrect">
|
||||||
|
{error}
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Place value chart */}
|
||||||
|
<Card>
|
||||||
|
<div className="mb-3 flex flex-wrap items-center justify-between gap-2">
|
||||||
|
<p className="text-xs font-bold uppercase tracking-wider text-unit-6">
|
||||||
|
Place Value Chart (powers of 2)
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
onClick={() => setChartHidden((v) => !v)}
|
||||||
|
className="rounded-md border border-border bg-surface px-2.5 py-1 text-xs font-semibold text-muted transition-colors hover:border-unit-6/50 hover:text-unit-6"
|
||||||
|
>
|
||||||
|
{chartHidden ? "Show Chart" : "Hide Chart"}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{!chartHidden && (
|
||||||
|
<div className="overflow-x-auto rounded-xl border-2 border-unit-6/30 bg-unit-6-light/40 p-3">
|
||||||
|
<table className="mx-auto border-collapse font-mono">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
{columns.map((c) => (
|
||||||
|
<td
|
||||||
|
key={`p-${c.exponent}`}
|
||||||
|
className="min-w-[64px] border-2 border-unit-6/40 bg-unit-6-light px-4 py-2 text-center text-sm font-bold text-unit-6-dark"
|
||||||
|
>
|
||||||
|
2<sup>{c.exponent}</sup>
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{columns.map((c) => (
|
||||||
|
<td
|
||||||
|
key={`v-${c.exponent}`}
|
||||||
|
className="min-w-[64px] border-2 border-unit-6/40 bg-surface px-4 py-2 text-center text-base font-bold text-unit-6"
|
||||||
|
>
|
||||||
|
{c.placeValue}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{columns.map((c, i) => (
|
||||||
|
<td
|
||||||
|
key={`d-${i}`}
|
||||||
|
className={`min-w-[64px] border-2 border-unit-6/40 px-4 py-2 text-center text-2xl font-extrabold ${
|
||||||
|
c.digit === "1"
|
||||||
|
? "bg-correct-light text-correct"
|
||||||
|
: c.digit === "_"
|
||||||
|
? "bg-surface text-muted/60"
|
||||||
|
: "bg-surface text-muted"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{c.digit}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
{columns.map((c, i) => (
|
||||||
|
<td
|
||||||
|
key={`c-${i}`}
|
||||||
|
className={`min-w-[64px] border-2 border-unit-6/40 px-4 py-2 text-center text-sm font-bold ${
|
||||||
|
c.isOne
|
||||||
|
? "bg-correct-light text-correct"
|
||||||
|
: c.digit === "_"
|
||||||
|
? "bg-[#fafbfc] text-muted/60"
|
||||||
|
: "bg-[#fafbfc] text-muted"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{submitted ? c.contrib : "_"}
|
||||||
|
</td>
|
||||||
|
))}
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
|
{submitted && (
|
||||||
|
<div className="mt-4 text-center font-mono text-base font-bold text-unit-6">
|
||||||
|
<div>{fullExpansion}</div>
|
||||||
|
<div>= {onesOnly}</div>
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Answer banner */}
|
||||||
|
<Card
|
||||||
|
className={`flex min-h-[90px] flex-col items-center justify-center gap-2 text-center ${
|
||||||
|
submitted && !answerHidden
|
||||||
|
? "border-correct bg-correct-light"
|
||||||
|
: "border-unit-6/30 bg-unit-6-light/60"
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{!submitted ? (
|
||||||
|
<p className="font-mono text-base font-bold text-unit-6">
|
||||||
|
Type a binary number above and press Convert.
|
||||||
|
</p>
|
||||||
|
) : answerHidden ? (
|
||||||
|
<p className="font-mono text-lg font-bold text-unit-6">
|
||||||
|
{submitted}<sub>2</sub> = ? (press Show Answer)
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p className="font-mono text-2xl font-extrabold text-correct">
|
||||||
|
{submitted}<sub>2</sub> = {total} in denary
|
||||||
|
</p>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
onClick={() => setAnswerHidden((v) => !v)}
|
||||||
|
className="mt-1 rounded-md border border-border bg-surface px-3 py-1 text-xs font-semibold text-muted transition-colors hover:border-unit-6/50 hover:text-unit-6"
|
||||||
|
>
|
||||||
|
{answerHidden ? "Show Answer" : "Hide Answer"}
|
||||||
|
</button>
|
||||||
|
</Card>
|
||||||
|
|
||||||
|
{/* Footer note */}
|
||||||
|
<Card className="border-l-4 border-l-unit-6 bg-unit-6-light/40">
|
||||||
|
<p className="text-sm text-unit-6-dark">
|
||||||
|
<strong>For students:</strong> solve on paper <em>first</em> using the chart in your worksheet. Type the binary number here only to <em>check</em>. The lesson is in the chart, not the click.
|
||||||
|
</p>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ const unitColorMap = {
|
|||||||
"unit-3": "text-unit-3-dark",
|
"unit-3": "text-unit-3-dark",
|
||||||
"unit-4": "text-unit-4-dark",
|
"unit-4": "text-unit-4-dark",
|
||||||
"unit-5": "text-unit-5-dark",
|
"unit-5": "text-unit-5-dark",
|
||||||
|
"unit-6": "text-unit-6-dark",
|
||||||
};
|
};
|
||||||
|
|
||||||
const unitDotColor = {
|
const unitDotColor = {
|
||||||
@@ -20,6 +21,7 @@ const unitDotColor = {
|
|||||||
"unit-3": "bg-unit-3",
|
"unit-3": "bg-unit-3",
|
||||||
"unit-4": "bg-unit-4",
|
"unit-4": "bg-unit-4",
|
||||||
"unit-5": "bg-unit-5",
|
"unit-5": "bg-unit-5",
|
||||||
|
"unit-6": "bg-unit-6",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function MobileNav() {
|
export function MobileNav() {
|
||||||
|
|||||||
@@ -37,6 +37,12 @@ const unitColorMap = {
|
|||||||
heading: "text-unit-5-dark",
|
heading: "text-unit-5-dark",
|
||||||
hoverBg: "hover:bg-unit-5-light/50",
|
hoverBg: "hover:bg-unit-5-light/50",
|
||||||
},
|
},
|
||||||
|
"unit-6": {
|
||||||
|
active: "bg-unit-6-light text-unit-6-dark border-unit-6/20",
|
||||||
|
dot: "bg-unit-6",
|
||||||
|
heading: "text-unit-6-dark",
|
||||||
|
hoverBg: "hover:bg-unit-6-light/50",
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Sidebar() {
|
export function Sidebar() {
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { type HTMLAttributes } from "react";
|
import { type HTMLAttributes } from "react";
|
||||||
|
|
||||||
type BadgeVariant = "default" | "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5";
|
type BadgeVariant = "default" | "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5" | "unit-6";
|
||||||
|
|
||||||
interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
interface BadgeProps extends HTMLAttributes<HTMLSpanElement> {
|
||||||
variant?: BadgeVariant;
|
variant?: BadgeVariant;
|
||||||
@@ -14,6 +14,7 @@ const variantStyles: Record<BadgeVariant, string> = {
|
|||||||
"unit-3": "border border-unit-3/20 bg-unit-3-light text-unit-3-dark",
|
"unit-3": "border border-unit-3/20 bg-unit-3-light text-unit-3-dark",
|
||||||
"unit-4": "border border-unit-4/20 bg-unit-4-light text-unit-4-dark",
|
"unit-4": "border border-unit-4/20 bg-unit-4-light text-unit-4-dark",
|
||||||
"unit-5": "border border-unit-5/20 bg-unit-5-light text-unit-5-dark",
|
"unit-5": "border border-unit-5/20 bg-unit-5-light text-unit-5-dark",
|
||||||
|
"unit-6": "border border-unit-6/20 bg-unit-6-light text-unit-6-dark",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Badge({ variant = "default", className, children, ...props }: BadgeProps) {
|
export function Badge({ variant = "default", className, children, ...props }: BadgeProps) {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { cn } from "@/lib/utils";
|
|||||||
import { type HTMLAttributes } from "react";
|
import { type HTMLAttributes } from "react";
|
||||||
|
|
||||||
interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
interface CardProps extends HTMLAttributes<HTMLDivElement> {
|
||||||
accent?: "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5";
|
accent?: "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5" | "unit-6";
|
||||||
hover?: boolean;
|
hover?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -12,6 +12,7 @@ const accentStyles = {
|
|||||||
"unit-3": "border-l-4 border-l-unit-3",
|
"unit-3": "border-l-4 border-l-unit-3",
|
||||||
"unit-4": "border-l-4 border-l-unit-4",
|
"unit-4": "border-l-4 border-l-unit-4",
|
||||||
"unit-5": "border-l-4 border-l-unit-5",
|
"unit-5": "border-l-4 border-l-unit-5",
|
||||||
|
"unit-6": "border-l-4 border-l-unit-6",
|
||||||
};
|
};
|
||||||
|
|
||||||
export function Card({
|
export function Card({
|
||||||
|
|||||||
@@ -7,12 +7,12 @@ export interface Topic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface Unit {
|
export interface Unit {
|
||||||
number: 1 | 2 | 3 | 4 | 5;
|
number: 1 | 2 | 3 | 4 | 5 | 6;
|
||||||
slug: string;
|
slug: string;
|
||||||
title: string;
|
title: string;
|
||||||
description: string;
|
description: string;
|
||||||
weeks: string;
|
weeks: string;
|
||||||
color: "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5";
|
color: "unit-1" | "unit-2" | "unit-3" | "unit-4" | "unit-5" | "unit-6";
|
||||||
topics: Topic[];
|
topics: Topic[];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,6 +200,23 @@ export const curriculum: Unit[] = [
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
number: 6,
|
||||||
|
slug: "unit-6-number-system",
|
||||||
|
title: "Number System",
|
||||||
|
description: "Explore how numbers can be written in different bases, beyond the everyday denary system",
|
||||||
|
weeks: "Week 10",
|
||||||
|
color: "unit-6",
|
||||||
|
topics: [
|
||||||
|
{
|
||||||
|
slug: "binary",
|
||||||
|
title: "Binary Numbers",
|
||||||
|
shortTitle: "Binary",
|
||||||
|
week: 10,
|
||||||
|
description: "Place value in base 2 and converting binary numbers to denary (decimal)",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export function getUnit(slug: string): Unit | undefined {
|
export function getUnit(slug: string): Unit | undefined {
|
||||||
@@ -211,13 +228,14 @@ export function getTopic(unitSlug: string, topicSlug: string): Topic | undefined
|
|||||||
return unit?.topics.find((t) => t.slug === topicSlug);
|
return unit?.topics.find((t) => t.slug === topicSlug);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getUnitColor(unitNumber: 1 | 2 | 3 | 4 | 5): string {
|
export function getUnitColor(unitNumber: 1 | 2 | 3 | 4 | 5 | 6): string {
|
||||||
const colors = {
|
const colors = {
|
||||||
1: "unit-1",
|
1: "unit-1",
|
||||||
2: "unit-2",
|
2: "unit-2",
|
||||||
3: "unit-3",
|
3: "unit-3",
|
||||||
4: "unit-4",
|
4: "unit-4",
|
||||||
5: "unit-5",
|
5: "unit-5",
|
||||||
|
6: "unit-6",
|
||||||
};
|
};
|
||||||
return colors[unitNumber];
|
return colors[unitNumber];
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user