app
Resistor Flash Cards
Public Unreviewedby test5
Interactive flash cards for a circuits class: resistor color codes, SMD markings, formulas, and generated practice problems
main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
<!DOCTYPE html>
<html lang="en"><head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Resistor Flash Cards</title>
<style>
:root {
--bg: #0b0f14; --panel: #121821; --panel2: #18202b; --line: #243040;
--text: #e6edf3; --muted: #93a1b3; --teal: #14b8a6; --blue: #3b82f6; --purple: #8b5cf6;
--good: #22c55e; --bad: #f97316;
}
* { box-sizing: border-box; }
html, body { margin: 0; background: var(--bg); color: var(--text);
font: 15px/1.5 Inter, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; }
.wrap { max-width: 880px; margin: 0 auto; padding: 20px 16px 28px; }
h1 { font-size: 22px; margin: 0 0 4px; letter-spacing: -0.01em; }
.sub { color: var(--muted); margin: 0 0 14px; font-size: 14px; }
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin-bottom: 14px; }
.chip { border: 1px solid var(--line); background: var(--panel); color: var(--muted); border-radius: 999px;
padding: 6px 12px; cursor: pointer; font-size: 13px; user-select: none; }
.chip.on { color: #fff; border-color: transparent;
background: linear-gradient(90deg, var(--teal), var(--blue) 60%, var(--purple)); }
.stage { perspective: 1400px; }
.card { position: relative; min-height: 340px; cursor: pointer; transform-style: preserve-3d;
transition: transform .45s cubic-bezier(.2,.8,.2,1); }
.card.flipped { transform: rotateY(180deg); }
.face { position: absolute; inset: 0; backface-visibility: hidden; -webkit-backface-visibility: hidden;
background: var(--panel); border: 1px solid var(--line); border-radius: 16px; padding: 22px 24px;
display: flex; flex-direction: column; justify-content: center; align-items: center; text-align: center; gap: 12px; }
.face.back { transform: rotateY(180deg); background: var(--panel2); }
.tag { position: absolute; top: 14px; left: 18px; font-size: 12px; color: var(--muted); letter-spacing: .04em; text-transform: uppercase; }
.hint { position: absolute; bottom: 12px; right: 18px; font-size: 12px; color: var(--muted); }
.q { font-size: 20px; font-weight: 600; max-width: 640px; }
.a { font-size: 26px; font-weight: 700; max-width: 640px; }
.a.small { font-size: 18px; font-weight: 500; }
.note { color: var(--muted); font-size: 14px; max-width: 640px; }
.big { font-size: 40px; font-weight: 800; font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; letter-spacing: .04em; }
.mono { font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; }
.bands { display: flex; gap: 6px; flex-wrap: wrap; justify-content: center; }
.band { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 8px; background: #0f141b; border: 1px solid var(--line); font-size: 14px; }
.sw { width: 14px; height: 14px; border-radius: 3px; border: 1px solid rgba(255,255,255,.15); }
svg.res { width: 340px; max-width: 100%; height: auto; }
.bar { display: flex; gap: 10px; align-items: center; margin-top: 14px; flex-wrap: wrap; }
button { border: 1px solid var(--line); background: var(--panel); color: var(--text); border-radius: 10px;
padding: 10px 16px; font-size: 14px; cursor: pointer; min-height: 44px; }
button:hover { border-color: #3a4a60; }
button.primary { background: linear-gradient(90deg, var(--teal), var(--blue)); border-color: transparent; color: #fff; font-weight: 600; }
button.good { border-color: var(--good); color: var(--good); }
button.bad { border-color: var(--bad); color: var(--bad); }
.spacer { flex: 1; }
.prog { color: var(--muted); font-size: 13px; }
.meter { height: 6px; background: var(--panel); border: 1px solid var(--line); border-radius: 999px; overflow: hidden; margin-top: 10px; }
.meter i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, var(--teal), var(--blue), var(--purple)); transition: width .3s; }
.keys { color: var(--muted); font-size: 12px; margin-top: 10px; }
kbd { border: 1px solid var(--line); border-bottom-width: 2px; border-radius: 4px; padding: 0 5px; font-size: 11px; background: var(--panel); }
details { margin-top: 20px; border: 1px solid var(--line); border-radius: 12px; background: var(--panel); padding: 10px 16px; }
summary { cursor: pointer; font-weight: 600; }
table { border-collapse: collapse; width: 100%; margin-top: 10px; font-size: 14px; }
th, td { text-align: left; padding: 6px 8px; border-bottom: 1px solid var(--line); }
th { color: var(--muted); font-weight: 500; }
.done .q { color: var(--teal); }
</style>
</head>
<body>
<div class="wrap">
<h1>Resistor Flash Cards</h1>
<p class="sub">Color codes, SMD markings, formulas, and quick calculations. Click a card to flip it, then mark whether you got it.</p>
<div class="chips" id="chips"><span class="chip on">All</span><span class="chip">Color code</span><span class="chip">Value to bands</span><span class="chip">SMD codes</span><span class="chip">Formulas</span><span class="chip">Calculations</span></div>
<div class="stage">
<div class="card" id="card">
<div class="face front"><span class="tag" id="tagF">SMD codes · 1 of 103</span><div id="front"><div class="big">472</div><div class="q">Value of this SMD marking?</div></div><span class="hint">click or press space to flip</span></div>
<div class="face back"><span class="tag" id="tagB">SMD codes · 1 of 103</span><div id="back"><div class="a">4.7 kΩ</div><div class="note">47 × 10²</div></div></div>
</div>
</div>
<div class="bar">
<button id="prev">Prev</button>
<button id="flip" class="primary">Flip</button>
<button id="next">Next</button>
<span class="spacer"></span>
<button id="again" class="bad">Again</button>
<button id="got" class="good">Got it</button>
<button id="shuffle">Shuffle</button>
</div>
<div class="meter"><i id="meter" style="width: 0%;"></i></div>
<div class="bar"><span class="prog" id="prog">0 of 103 marked "got it", 103 left in the queue</span></div>
<div class="keys"><kbd>space</kbd> flip · <kbd>←</kbd> <kbd>→</kbd> prev / next · <kbd>1</kbd> again · <kbd>2</kbd> got it · <kbd>s</kbd> shuffle</div>
<details>
<summary>Color code cheat sheet</summary>
<table id="cheat"><tbody><tr><th>Color</th><th>Digit</th><th>Multiplier</th><th>Tolerance</th></tr><tr><td><span class="band"><i class="sw" style="background:#111111"></i>Black</span></td><td>0</td><td>×1</td><td></td></tr><tr><td><span class="band"><i class="sw" style="background:#8b4513"></i>Brown</span></td><td>1</td><td>×10</td><td>±1%</td></tr><tr><td><span class="band"><i class="sw" style="background:#e0201a"></i>Red</span></td><td>2</td><td>×100</td><td>±2%</td></tr><tr><td><span class="band"><i class="sw" style="background:#f28c1a"></i>Orange</span></td><td>3</td><td>×1,000</td><td></td></tr><tr><td><span class="band"><i class="sw" style="background:#f2d21a"></i>Yellow</span></td><td>4</td><td>×10,000</td><td></td></tr><tr><td><span class="band"><i class="sw" style="background:#21a04b"></i>Green</span></td><td>5</td><td>×100,000</td><td>±0.5%</td></tr><tr><td><span class="band"><i class="sw" style="background:#2260d8"></i>Blue</span></td><td>6</td><td>×1,000,000</td><td>±0.25%</td></tr><tr><td><span class="band"><i class="sw" style="background:#8a3fd1"></i>Violet</span></td><td>7</td><td>×10,000,000</td><td>±0.1%</td></tr><tr><td><span class="band"><i class="sw" style="background:#8f8f8f"></i>Gray</span></td><td>8</td><td>×100,000,000</td><td>±0.05%</td></tr><tr><td><span class="band"><i class="sw" style="background:#f4f4f4"></i>White</span></td><td>9</td><td>×1,000,000,000</td><td></td></tr><tr><td><span class="band"><i class="sw" style="background:#d4a017"></i>Gold</span></td><td></td><td>×0.1</td><td>±5%</td></tr><tr><td><span class="band"><i class="sw" style="background:#c0c0c0"></i>Silver</span></td><td></td><td>×0.01</td><td>±10%</td></tr></tbody></table>
<p class="note" style="margin-top:10px">Read with the tolerance band (gold, silver, or the band spaced farthest from the others) on the right. 4-band: digit, digit, multiplier, tolerance. 5-band: digit, digit, digit, multiplier, tolerance. 6-band adds a temperature coefficient band.</p>
</details>
</div>
<script>
(function () {
// ---------- reference data ----------
var COLORS = [
{ n: 'Black', hex: '#111111', d: 0, m: 1 },
{ n: 'Brown', hex: '#8b4513', d: 1, m: 10, t: 1 },
{ n: 'Red', hex: '#e0201a', d: 2, m: 100, t: 2 },
{ n: 'Orange', hex: '#f28c1a', d: 3, m: 1e3 },
{ n: 'Yellow', hex: '#f2d21a', d: 4, m: 1e4 },
{ n: 'Green', hex: '#21a04b', d: 5, m: 1e5, t: 0.5 },
{ n: 'Blue', hex: '#2260d8', d: 6, m: 1e6, t: 0.25 },
{ n: 'Violet', hex: '#8a3fd1', d: 7, m: 1e7, t: 0.1 },
{ n: 'Gray', hex: '#8f8f8f', d: 8, m: 1e8, t: 0.05 },
{ n: 'White', hex: '#f4f4f4', d: 9, m: 1e9 },
{ n: 'Gold', hex: '#d4a017', m: 0.1, t: 5 },
{ n: 'Silver', hex: '#c0c0c0', m: 0.01, t: 10 }
];
var BY = {}; COLORS.forEach(function (c) { BY[c.n] = c; });
var E12 = [10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82];
var E24 = [10, 11, 12, 13, 15, 16, 18, 20, 22, 24, 27, 30, 33, 36, 39, 43, 47, 51, 56, 62, 68, 75, 82, 91];
var E96s = [100, 121, 150, 182, 221, 249, 274, 332, 402, 475, 549, 681, 825, 976];
function fmt(ohms) {
var u = 'Ω', v = ohms;
if (ohms >= 1e6) { v = ohms / 1e6; u = 'MΩ'; }
else if (ohms >= 1e3) { v = ohms / 1e3; u = 'kΩ'; }
v = +v.toPrecision(3);
return v + ' ' + u;
}
function esc(s) { return String(s).replace(/[&<>]/g, function (c) { return { '&': '&', '<': '<', '>': '>' }[c]; }); }
function rnd(n) { return Math.floor(Math.random() * n); }
function pick(a) { return a[rnd(a.length)]; }
function shuffleArr(a) { for (var i = a.length - 1; i > 0; i--) { var j = rnd(i + 1); var t = a[i]; a[i] = a[j]; a[j] = t; } return a; }
// ---------- resistor drawing ----------
function resistorSVG(bandColors) {
var n = bandColors.length;
var xs = n === 4 ? [92, 116, 140, 196] : n === 5 ? [84, 106, 128, 150, 200] : [80, 100, 120, 140, 160, 205];
var s = '<svg class="res" viewBox="0 0 340 90" xmlns="http://www.w3.org/2000/svg">';
s += '<line x1="10" y1="45" x2="330" y2="45" stroke="#b8c0cc" stroke-width="5" stroke-linecap="round"/>';
s += '<rect x="60" y="18" width="220" height="54" rx="22" fill="#d9c9a3" stroke="#6b5b3a" stroke-width="2"/>';
s += '<rect x="66" y="22" width="208" height="14" rx="10" fill="rgba(255,255,255,.28)"/>';
bandColors.forEach(function (c, i) {
s += '<rect x="' + xs[i] + '" y="19" width="14" height="52" rx="2" fill="' + BY[c].hex + '" stroke="rgba(0,0,0,.25)"/>';
});
return s + '</svg>';
}
function bandList(names, roles) {
return '<div class="bands">' + names.map(function (n, i) {
return '<span class="band"><i class="sw" style="background:' + BY[n].hex + '"></i>' + n + (roles ? ' <span class="note">' + roles[i] + '</span>' : '') + '</span>';
}).join('') + '</div>';
}
function bandsFor(sig, mult, tol) {
var digits = String(sig).split('').map(function (d) { return COLORS[+d].n; });
var mName = COLORS.filter(function (c) { return c.m === mult; })[0].n;
var tName = COLORS.filter(function (c) { return c.t === tol; })[0].n;
return digits.concat([mName, tName]);
}
function tolRange(ohms, tol) { return fmt(ohms * (1 - tol / 100)) + ' to ' + fmt(ohms * (1 + tol / 100)); }
// ---------- generated decks ----------
function colorCards(count) {
var out = [];
for (var i = 0; i < count; i++) {
var five = i % 3 === 2;
var sig = five ? pick(E96s) : pick(E24);
var mExp = five ? rnd(5) : rnd(6);
var mult = Math.pow(10, mExp);
var tol = five ? 1 : pick([5, 10, 5, 1]);
var ohms = sig * mult;
var bands = bandsFor(sig, mult, tol);
var roles = five ? ['1st digit', '2nd digit', '3rd digit', 'multiplier', 'tolerance'] : ['1st digit', '2nd digit', 'multiplier', 'tolerance'];
out.push({
deck: 'color',
front: resistorSVG(bands) + '<div class="q">What is the value and tolerance?</div>',
back: '<div class="a">' + fmt(ohms) + ' ±' + tol + '%</div>' + bandList(bands, roles) +
'<div class="note">Acceptable range: ' + tolRange(ohms, tol) + '</div>'
});
}
return out;
}
function reverseCards(count) {
var out = [];
for (var i = 0; i < count; i++) {
var sig = pick(E12), mExp = rnd(6), mult = Math.pow(10, mExp), tol = pick([5, 10]);
var ohms = sig * mult, bands = bandsFor(sig, mult, tol);
out.push({
deck: 'reverse',
front: '<div class="big">' + fmt(ohms) + ' ±' + tol + '%</div><div class="q">Name the four color bands.</div>',
back: resistorSVG(bands) + bandList(bands, ['1st digit', '2nd digit', 'multiplier', 'tolerance'])
});
}
return out;
}
function digitCards() {
var out = [];
COLORS.slice(0, 10).forEach(function (c) {
out.push({ deck: 'color',
front: '<div class="bands"><span class="band" style="font-size:20px;padding:10px 18px"><i class="sw" style="width:22px;height:22px;background:' + c.hex + '"></i>' + c.n + '</span></div><div class="q">What digit is this band, and what multiplier?</div>',
back: '<div class="a">Digit ' + c.d + ' · multiplier ×' + (c.m >= 1000 ? c.m.toLocaleString() : c.m) + '</div>' + (c.t ? '<div class="note">As a tolerance band: ±' + c.t + '%</div>' : '') });
});
out.push({ deck: 'color', front: '<div class="q">Gold as a multiplier band? As a tolerance band?</div>', back: '<div class="a">×0.1 · ±5%</div><div class="note">Silver is ×0.01 and ±10%. No tolerance band at all means ±20%.</div>' });
out.push({ deck: 'color', front: '<div class="q">Mnemonic for Black through White?</div>', back: '<div class="a small">Better Be Right Or Your Great Big Venture Goes Wrong</div><div class="note">Black 0, Brown 1, Red 2, Orange 3, Yellow 4, Green 5, Blue 6, Violet 7, Gray 8, White 9</div>' });
out.push({ deck: 'color', front: '<div class="q">Which end of the resistor do you read from?</div>', back: '<div class="a small">Tolerance band (gold or silver, or the band with the wider gap) goes on the RIGHT. Read left to right.</div>' });
out.push({ deck: 'color', front: resistorSVG(['Black']) + '<div class="q">A resistor with a single black band?</div>', back: '<div class="a">0 Ω jumper</div><div class="note">Used as a configurable link on a PCB so the pick-and-place machine can place it like any other part.</div>' });
out.push({ deck: 'color', front: '<div class="q">What does the sixth band on a 6-band resistor mean?</div>', back: '<div class="a small">Temperature coefficient (ppm/°C)</div><div class="note">Brown 100, Red 50, Orange 15, Yellow 25, Blue 10, Violet 5 ppm/°C</div>' });
return out;
}
function smdCards() {
var rows = [
['103', '10 kΩ', '3-digit: two digits then a power of ten. 10 × 10³'],
['472', '4.7 kΩ', '47 × 10²'],
['220', '22 Ω', '22 × 10⁰. Not 220 Ω, a common trap.'],
['221', '220 Ω', '22 × 10¹'],
['1R0', '1.0 Ω', 'R marks the decimal point'],
['4R7', '4.7 Ω', 'R marks the decimal point'],
['R47', '0.47 Ω', 'R marks the decimal point'],
['000', '0 Ω', 'Jumper'],
['1002', '10 kΩ', '4-digit (1% parts): three digits then a power of ten. 100 × 10²'],
['4701', '4.7 kΩ', '470 × 10¹'],
['3301', '3.3 kΩ', '330 × 10¹'],
['01C', '10 kΩ', 'EIA-96: code 01 = 100, letter C = ×100'],
['22A', '165 Ω', 'EIA-96: code 22 = 165, letter A = ×1'],
['01B', '1 kΩ', 'EIA-96: code 01 = 100, letter B = ×10']
];
return rows.map(function (r) {
return { deck: 'smd', front: '<div class="big">' + r[0] + '</div><div class="q">Value of this SMD marking?</div>', back: '<div class="a">' + r[1] + '</div><div class="note">' + esc(r[2]) + '</div>' };
});
}
function formulaCards() {
var rows = [
["Ohm's law", 'V = I·R, so I = V/R and R = V/I'],
['Power dissipated in a resistor', 'P = V·I = I²·R = V²/R'],
['Resistors in series', 'R<sub>total</sub> = R₁ + R₂ + … ; same current through each, voltages add'],
['Resistors in parallel', '1/R<sub>total</sub> = 1/R₁ + 1/R₂ + … ; same voltage across each, currents add'],
['Two resistors in parallel (product over sum)', 'R<sub>total</sub> = R₁·R₂ / (R₁ + R₂)'],
['N equal resistors R in parallel', 'R / N'],
['Voltage divider output', 'V<sub>out</sub> = V<sub>in</sub> · R₂ / (R₁ + R₂), with R₂ across the output'],
['Current divider (two branches)', 'I₁ = I<sub>total</sub> · R₂ / (R₁ + R₂). The current takes the smaller resistance more.'],
["Kirchhoff's voltage law", 'The sum of voltages around any closed loop is zero'],
["Kirchhoff's current law", 'The sum of currents entering a node equals the sum leaving it'],
['Wheatstone bridge balance condition', 'R₁/R₂ = R₃/R₄ (no current through the meter)'],
['Conductance', 'G = 1/R, measured in siemens (S). Parallel conductances add.'],
['Resistance of a wire', 'R = ρ·L / A (resistivity × length ÷ cross-section area)'],
['What does ±5% tolerance mean for 4.7 kΩ?', 'Actual value lies between 4.465 kΩ and 4.935 kΩ'],
['E12 series values', '10, 12, 15, 18, 22, 27, 33, 39, 47, 56, 68, 82 (each ~20% apart, made for ±10% parts)'],
['E24 series values', 'E12 plus 11, 13, 16, 20, 24, 30, 36, 43, 47…: 24 per decade, made for ±5% parts'],
['Why are standard values spaced logarithmically?', 'So adjacent values overlap at their tolerance and every resistance is covered with the fewest parts'],
['Typical power ratings', 'Through-hole: 1/8 W, 1/4 W, 1/2 W. SMD: 0402 ≈ 1/16 W, 0603 ≈ 1/10 W, 0805 ≈ 1/8 W, 1206 ≈ 1/4 W'],
['Derating', 'Above about 70 °C ambient the allowed power drops linearly toward zero at the max temperature. Run resistors at half their rating.'],
['Temperature coefficient, 100 ppm/°C', 'Resistance changes 0.01% per °C. A 10 kΩ part drifts 1 Ω per °C.'],
['Carbon film vs metal film', 'Carbon film: cheap, ±5%, noisier. Metal film: ±1% or better, low noise, low tempco. Default choice for signal work.'],
['Wirewound resistors', 'High power, very precise, but inductive: avoid in high-frequency paths'],
['Potentiometer vs rheostat', 'Potentiometer: three terminals, a variable voltage divider. Rheostat: two terminals, a variable resistance.'],
['Pull-up resistor', 'Ties a signal to V<sub>cc</sub> through a resistor (often 4.7 kΩ to 10 kΩ) so it reads high when nothing drives it'],
['LED current-limiting resistor', 'R = (V<sub>supply</sub> − V<sub>forward</sub>) / I<sub>LED</sub>'],
['Thermal noise (Johnson) of a resistor', 'v<sub>n</sub> = √(4·k·T·R·Δf). Bigger R means more noise.']
];
return rows.map(function (r) { return { deck: 'formula', front: '<div class="q">' + r[0] + '</div>', back: '<div class="a small">' + r[1] + '</div>' }; });
}
function calcCards(count) {
var out = [];
for (var i = 0; i < count; i++) {
var kind = i % 6, r1 = pick(E12) * Math.pow(10, 1 + rnd(3)), r2 = pick(E12) * Math.pow(10, 1 + rnd(3)), v = pick([3.3, 5, 9, 12, 24]);
if (kind === 0) out.push({ deck: 'calc', front: '<div class="q">' + fmt(r1) + ' and ' + fmt(r2) + ' in series?</div>', back: '<div class="a">' + fmt(r1 + r2) + '</div><div class="note">Series resistances add.</div>' });
else if (kind === 1) out.push({ deck: 'calc', front: '<div class="q">Two ' + fmt(r1) + ' resistors in parallel?</div>', back: '<div class="a">' + fmt(r1 / 2) + '</div><div class="note">Equal resistors in parallel: R / N.</div>' });
else if (kind === 2) out.push({ deck: 'calc', front: '<div class="q">' + fmt(r1) + ' and ' + fmt(r2) + ' in parallel?</div>', back: '<div class="a">' + fmt(r1 * r2 / (r1 + r2)) + '</div><div class="note">Product over sum. The result is always smaller than the smaller resistor.</div>' });
else if (kind === 3) out.push({ deck: 'calc', front: '<div class="q">Voltage divider: ' + v + ' V across ' + fmt(r1) + ' (top) and ' + fmt(r2) + ' (bottom). V<sub>out</sub> across the bottom?</div>', back: '<div class="a">' + (+(v * r2 / (r1 + r2)).toPrecision(3)) + ' V</div><div class="note">V<sub>out</sub> = V<sub>in</sub> · R₂ / (R₁ + R₂)</div>' });
else if (kind === 4) { var iA = v / r1; out.push({ deck: 'calc', front: '<div class="q">' + v + ' V across ' + fmt(r1) + '. Current?</div>', back: '<div class="a">' + (iA >= 1e-3 ? +(iA * 1e3).toPrecision(3) + ' mA' : +(iA * 1e6).toPrecision(3) + ' µA') + '</div><div class="note">I = V / R</div>' }); }
else { var p = v * v / r1; out.push({ deck: 'calc', front: '<div class="q">' + v + ' V across ' + fmt(r1) + '. Power dissipated? Is a 1/4 W part OK?</div>', back: '<div class="a">' + (p >= 1 ? +p.toPrecision(3) + ' W' : +(p * 1e3).toPrecision(3) + ' mW') + '</div><div class="note">P = V² / R. ' + (p <= 0.125 ? 'Yes, under half of 1/4 W.' : p <= 0.25 ? 'Marginal: within rating but over half of it.' : 'No, exceeds 1/4 W.') + '</div>' }); }
}
return out;
}
var DECKS = [
{ id: 'all', label: 'All' },
{ id: 'color', label: 'Color code' },
{ id: 'reverse', label: 'Value to bands' },
{ id: 'smd', label: 'SMD codes' },
{ id: 'formula', label: 'Formulas' },
{ id: 'calc', label: 'Calculations' }
];
var ALL = [];
function build() {
ALL = shuffleArr(digitCards().concat(colorCards(18), reverseCards(12), smdCards(), formulaCards(), calcCards(18)));
}
// ---------- state ----------
var deck = 'all', queue = [], idx = 0, flipped = false, done = 0, total = 0;
var card = document.getElementById('card'), front = document.getElementById('front'), back = document.getElementById('back');
var tagF = document.getElementById('tagF'), tagB = document.getElementById('tagB'), prog = document.getElementById('prog'), meter = document.getElementById('meter');
function label(id) { return DECKS.filter(function (d) { return d.id === id; })[0].label; }
function load() {
queue = ALL.filter(function (c) { return deck === 'all' || c.deck === deck; });
idx = 0; done = 0; total = queue.length; render();
}
function render() {
flipped = false; card.classList.remove('flipped');
if (!queue.length) {
card.classList.add('done');
front.innerHTML = '<div class="q">Deck complete. Shuffle to run it again.</div>'; back.innerHTML = '';
tagF.textContent = label(deck); tagB.textContent = '';
} else {
card.classList.remove('done');
var c = queue[idx];
front.innerHTML = c.front; back.innerHTML = c.back;
tagF.textContent = label(c.deck) + ' · ' + (idx + 1) + ' of ' + queue.length; tagB.textContent = tagF.textContent;
}
prog.textContent = done + ' of ' + total + ' marked "got it"' + (queue.length ? ', ' + queue.length + ' left in the queue' : '');
meter.style.width = (total ? Math.round(done / total * 100) : 0) + '%';
fit();
}
function flip() { if (!queue.length) return; flipped = !flipped; card.classList.toggle('flipped', flipped); }
function next() { if (!queue.length) return; idx = (idx + 1) % queue.length; render(); }
function prev() { if (!queue.length) return; idx = (idx - 1 + queue.length) % queue.length; render(); }
function got() { if (!queue.length) return; queue.splice(idx, 1); done++; if (idx >= queue.length) idx = 0; render(); }
function again() { if (queue.length < 2) { flipped = false; card.classList.remove('flipped'); return; } var c = queue.splice(idx, 1)[0]; queue.push(c); if (idx >= queue.length) idx = 0; render(); }
function reshuffle() { build(); load(); }
// ---------- UI wiring ----------
var chips = document.getElementById('chips');
DECKS.forEach(function (d) {
var b = document.createElement('span'); b.className = 'chip' + (d.id === deck ? ' on' : ''); b.textContent = d.label;
b.onclick = function () { deck = d.id; Array.prototype.forEach.call(chips.children, function (x) { x.classList.remove('on'); }); b.classList.add('on'); load(); };
chips.appendChild(b);
});
card.onclick = flip;
document.getElementById('flip').onclick = flip;
document.getElementById('next').onclick = next;
document.getElementById('prev').onclick = prev;
document.getElementById('got').onclick = got;
document.getElementById('again').onclick = again;
document.getElementById('shuffle').onclick = reshuffle;
document.addEventListener('keydown', function (e) {
if (e.target && /input|textarea/i.test(e.target.tagName)) return;
if (e.key === ' ') { e.preventDefault(); flip(); }
else if (e.key === 'ArrowRight') next();
else if (e.key === 'ArrowLeft') prev();
else if (e.key === '1') again();
else if (e.key === '2') got();
else if (e.key === 's' || e.key === 'S') reshuffle();
});
// cheat sheet
var cheat = document.getElementById('cheat');
cheat.innerHTML = '<tr><th>Color</th><th>Digit</th><th>Multiplier</th><th>Tolerance</th></tr>' + COLORS.map(function (c) {
return '<tr><td><span class="band"><i class="sw" style="background:' + c.hex + '"></i>' + c.n + '</span></td><td>' + (c.d === undefined ? '' : c.d) + '</td><td>×' + (c.m >= 1000 ? c.m.toLocaleString() : c.m) + '</td><td>' + (c.t ? '±' + c.t + '%' : '') + '</td></tr>';
}).join('');
// sandboxed-iframe height reporter
function fit() { try { parent.postMessage({ type: 'readme-height', height: document.documentElement.scrollHeight }, '*'); } catch (e) {} }
addEventListener('load', fit);
if (window.ResizeObserver) new ResizeObserver(fit).observe(document.documentElement);
build(); load();
})();
</script>
</body></html>