ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
An interactive practice tool for microbiology students learning to calculate the original concentration in CFU/mL from serial dilution plate counts.
EducationJavaScript · CSSGitHub @CalebHendrenOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
An interactive web app for microbiology students to practice calculating original concentrations (CFU/mL) from serial dilution plate counts.
Taken from the repository README
Loading the full README.
Read the full README ↗An interactive web app for microbiology students to practice calculating original concentrations (CFU/mL) from serial dilution plate counts. Built for classroom use in a Preliminary Microbiology course.
Each problem presents four test tubes — Tube 1 holds the original sample, Tubes 2–4 are stepwise dilutions — along with three petri dishes showing colony counts from each dilution. Students work backward from the countable plate (30–300 colonies) through the dilution series to find the concentration in the original tube.
The dilution factors aren't given. Students determine them from the labeled transfer and diluent volumes shown between tubes. For example, transferring 100 µL into 900 µL of diluent is a 1/10 dilution — students need to recognize that themselves.
Students get three attempts per problem (configurable). After a correct answer or three wrong attempts, the app reveals a worked solution showing each stepwise dilution, the cumulative total at each tube, identification of the countable plate, and the final calculation.
# From the repo root, serve over http (modules need it):
python3 -m http.server 8000
# Then open http://localhost:8000
Deploys unchanged to GitHub Pages — push the repo and enable Pages from main.
Open config.js in the repo root. Every classroom-relevant knob lives there:
| Key | What it does |
|---|---|
appTitle | Page title and header. Defaults to "Serial Dilution Practice". |
courseName / instructorName | Optional banner under the subtitle. |
attemptsAllowed | Attempts per problem before the solution reveals. Default 3. |
toleranceFraction | ± acceptance band around the true answer. Default 0.02 (±2%). |
countableRange | The "countable plate" range. Default [30, 300]. |
cleanLogProbability | Fraction of problems where every step is 1/10 or 1/100. Default 0.75. |
factorPool | Dilution factors + weights used in mixed problems. |
volumePool | Plated volumes (mL) + weights. |
unitPool | µL vs mL weighting for the per-problem unit. |
stepVolumes | Realistic [transfer, diluent] pairs for each factor and unit. |
defaultTheme | First-load theme key. See Themes below. |
defaultColorMode | "light", "dark", or "system" (follows OS). |
showCalculatorOnDesktop | Whether the calculator auto-opens on desktop. |
Edit, save, reload — no build step.
Six themes ship out of the box. All meet WCAG 2.1 AA contrast; the two High Contrast themes meet AAA.
| Key | Mode | Notes |
|---|---|---|
light-default | light | Chattanooga State light theme (navy, royal blue, orange), shared with MicroGrade. Shown as "Light" in the picker (default). |
clean-slate | light | Clinical white background, slate text, blue-teal accent. |
hc-light | light | Near-white background, near-black text, deep navy/burgundy. AAA. |
lab-slate | dark | Warm dark blue-gray paper, cream text, muted teal/coral. Paired with light-default. |
midnight | dark | Deep navy, soft sky text, electric teal/amber. Paired with clean-slate. |
hc-dark | dark | Pure black background, pure white text, bright brass focus. AAA. |
Two controls live in the page toolbar:
<select> listing all six themes, grouped Light / Dark.Choices persist via localStorage. With no saved choice, the page follows the OS prefers-color-scheme setting and continues listening for mid-session changes until the student picks a theme manually.
10⁻ⁿ form. Choice is saved across refreshes.CFU/mL = (colonies × reciprocal of total dilution) / volume plated. Hidden by default and not persisted.Designed to meet federal accessibility guidelines for higher education (WCAG 2.1 AA / Section 508):
<header>, <main>, <section> with aria-labelledby).aria-live regions announce attempt count, feedback, solution updates, and theme changes.hc-light and hc-dark exceed 7:1 (WCAG AAA).prefers-reduced-motion support — animations disabled when the OS setting is on.<select> and <button> elements, fully keyboard-operable, with associated labels and aria-pressed.serialdilution/
├── index.html # slim shell — landmarks, controls, module loads
├── config.js # instructor config (edit this)
├── README.md
├── LICENSE
├── styles/
│ ├── tokens.css non-color design tokens
│ ├── themes.css 6 theme variants — color tokens only
│ ├── base.css resets, body, skip link, focus, reduced motion
│ ├── header.css site header + toolbar + theme controls
│ ├── layout.css main grid + .card + problem statement
│ ├── tubes.css dilution tubes row
│ ├── plates.css petri plates row
│ ├── answer.css answer input, attempts dots, feedback
│ ├── buttons.css .btn variants — 44px touch targets
│ ├── solution.css worked solution, dilution table, derivation list, equation reveal
│ ├── calculator.css floating calculator
│ └── responsive.css mobile overrides
└── js/ # ES modules, no build step
├── main.js entry — DOM wiring + init
├── config.js merges user config with defaults
├── state.js shared mutable state
├── storage.js localStorage wrappers
├── utils.js random pickers, gcd, seeded RNG
├── format.js number formatting, parsing, sci notation
├── problem.js problem generation (uses config pools)
├── svg.js tube/arrow/plate SVG generators — themed via CSS vars
├── render.js DOM render for tubes, plates, attempts, feedback
├── equation.js equation reveal panel
├── calculator.js 4-function calculator widget
├── solution.js worked solution renderer
├── answer.js answer parsing + tolerance check
├── lifecycle.js new-problem reset
└── theme.js theme registry, light/dark toggle, persistence
<link>/<script type="module"> only.main.Because ES modules require http(s), the app does not work when opened via file://. Run a local server (python3 -m http.server) during development, or deploy to Pages.
(plate index, count) so the same problem renders identically on re-render but different problems get visually distinct dishes.repeat(7, minmax(0, 1fr))) for tubes + arrow cells, ensuring the arrows sit at the exact midpoint between tubes regardless of label content.[data-theme="..."] on <html> for the named theme plus [data-color-mode="light|dark"] for the resolved mode (the latter drives color-scheme so browser-native widgets match).