ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Past-paper tracker for A-level and SQA students — predicts the grade you are on from your own marks against real published grade boundaries, and picks the next three questions to practise. Flask, Postgres, Stripe.
翻譯準備中
取自儲存庫 README
正在載入完整 README。 以下為已儲存的摘錄。
A past-paper tracker that tells A-level and SQA students the grade they are
actually on, and the three questions that would move it.
A student finishes a past paper, writes "62%" at the top, and files it. That
number is close to meaningless. 62% on a brutal 2019 Physics paper and 62% on a
soft 2023 one are not the same performance, and neither tells them what to do
on Tuesday evening.檢視完整 README ↗A past-paper tracker that tells A-level and SQA students the grade they are actually on, and the three questions that would move it.
Live at telosapp.co.uk · Flask · Postgres · Railway · Stripe · installable PWA
A student finishes a past paper, writes "62%" at the top, and files it. That number is close to meaningless. 62% on a brutal 2019 Physics paper and 62% on a soft 2023 one are not the same performance, and neither tells them what to do on Tuesday evening.
Telos records every question separately, converts each attempt to a position on a continuous grade scale using that paper's real published boundaries, and turns the residue into a ranked list of what is costing marks.
Three questions, in order:
| Diagnosis | Which topics are bleeding marks, ranked by what they actually cost |
| Prediction | What grade am I on, with a confidence level and the marks to the next boundary |
| Prescription | What are the three specific questions to do next |
| Qualifications | 67 — 61 graded across AQA, Edexcel, OCR A and SQA, plus 6 admissions tests |
| Grade boundary rows | 1,001 real published boundaries |
| Levels | A-Level, AS-Level, Higher, Advanced Higher, admissions test |
| Components | 219 papers, modules, parts and coursework units |
| Routes | 85 |
| Tables | 33, under 51 numbered migrations |
| Tests | 32 suites, ~987 assertions |
| Code | ~45,000 lines across 253 tracked files |
Coverage is not approximate. test_boundaries.py fails the build if any
graded paper the app offers lacks boundaries — a qualification a student can
select but cannot be graded on is a bug, not a gap.
The exemption for ungraded qualifications is two-sided, so it cannot become a loophole. TMUA and ESAT report a 1–9 scale score and have no A*–E ladder at all, so they are not required to have boundaries — and they are required not to have any. A boundary row for a 1–9 scale test is somebody's invention, and the same test catches it.
The reverse direction is reported but deliberately not failed on: Edexcel publishes boundaries for Further Maths option papers the catalogue does not yet offer. That is real data waiting on a missing feature, so the suite prints it every run rather than hiding it or treating it as an error.
app.py Flask routes, session, entitlement gates (~3,600 lines)
db.py psycopg3 shim — Postgres behind a sqlite3 API
prediction.py grade engine — pure, no Flask, no DB
prescription.py "your next 3 questions" — pure
revision.py spaced repetition — pure
admissions.py equipercentile equating — pure
admissions_papers.py the official ENGAA/NSAA/TMUA papers and keys — pure
sharecards.py server-rendered PNG share cards
brand.py the Telos mark, drawn in code
interview.py Telos Interview — AI mock Oxbridge interviews, own blueprint
paper_templates.py 67 qualifications, 219 components
migrations/ 51 numbered idempotent SQL migrations
tests/ 32 standalone suites
scripts/boundaries/ 36 board-document scripts
prediction.py, prescription.py and revision.py import no Flask and touch
no database. They take plain data and return plain data.
This is the single decision the codebase most depends on. The grade engine has
genuinely intricate rules — recency weighting, difficulty normalisation,
confidence intervals, qualifications whose ladder stops at A instead of A* —
and all of it is testable without a request context, a fixture user, or a
network round trip. test_prediction.py and test_engine_sweep.py between
them exercise every qualification in the catalogue in about a second.
A*=6 A=5 B=4 C=3 D=2 E=1 U=0 with fractional positions between
A grade score of 4.6 means "comfortably into B, most of the way to an A". Each attempt is placed on this scale using the boundaries for that specific paper and series, so paper difficulty normalises out automatically.
Three details that took real care:
a_star
absent means it tops out at A, d present with e absent means it bottoms
out at D — so an AS student is never predicted a grade that cannot appear on
their certificate.MissingBoundaries is
raised and handled. Summer 2020 and 2021 were cancelled in England, so no
boundaries exist; an attempt at those years falls back to the median of the
real years, which is the honest answer.derived_from_course so the
interface can say so rather than implying a precision that is not there.auth.py is the single source of truth for paid access, and nothing grants Pro
on a redirect back from checkout. A customer.subscription.* webhook is the
only thing that writes an entitlement. A user who closes the tab at the wrong
moment, or who edits the success URL by hand, gets exactly what they paid for.
The gate is deliberately generous in the other direction: past_due keeps
access, because Stripe retries a failed card for about two weeks and a student
mid-revision should not be locked out over an expired card. Only canceled and
unpaid cut access.
This was verified end to end in live mode with a real card — charge, webhook, Pro granted, cancel, access removed.
db.py — Postgres behind a sqlite3 APITelos began on SQLite. Rather than rewrite every call site during the Postgres
migration, db.py presents the sqlite3 interface the app already spoke — ?
placeholders, .lastrowid, row objects that index by name — over psycopg3.
It also carries the operational scar tissue that hosting on Neon requires: a serverless Postgres instance sleeps, so a pooled connection can be dead by the time it is handed out. Connections idle longer than a 15-second grace are health-checked before use, and a query that fails on a dead connection is retried exactly once — but only if it had not already done work, so a retry can never replay a partial write.
Free — diagnosis
Pro — prediction and prescription
Everyone
A few decisions worth explaining, and a few scars worth keeping.
40 SQL files, tracked by filename in schema_migrations. The Procfile is a
bare gunicorn line — migrations are run deliberately, by hand, because a
migration that runs automatically on every boot is a migration that will
eventually run during an incident.
They are idempotent because they get re-run. One of them once had a DELETE
scoped more widely than its INSERT and removed 98 rows it had not written on
its second run. The fix — scoping the delete to exactly what the insert
creates — is now the rule the rest follow.
36 scripts under scripts/boundaries/ — extractors, generators and
verifiers. Every extractor
validates each component against its own maximum mark before emitting SQL.
That guard exists because a mis-parsed PDF column silently produces boundaries
that are plausible, wrong, and would quietly mis-grade every student who sat
that paper.
PDF and spreadsheet parsing dependencies are installed for the extraction and
uninstalled afterwards. They are not in requirements.txt — the running
application has no reason to be able to read a PDF.
No pytest. Each suite is a Python file that runs top to bottom, prints
PASS/FAIL per assertion, and exits non-zero on failure; tests/run_all.py
runs all 24. The integration suites create and destroy their own fixture users
through tests/_fixtures.py, which exists because killed runs used to leave
orphans behind that broke the next run.
The suite is also where non-obvious invariants live:
None when there is nothing to compare against, never 0 —
a new account has no trend, and "+0 this week" is a lie told to every user on
their first day.TELOS_STATE.md keeps the full list. Three that generalise:
.btn { display: inline-flex } beats the browser's [hidden] rule.
Buttons meant to be hidden were visible in production. Specificity beat
intent, silently.python -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
railway run .venv\Scripts\python.exe app.py # dev server :5000
railway run .venv\Scripts\python.exe tests\run_all.py # all 24 suites
railway run .venv\Scripts\python.exe migrations\run_migrations.py
railway run injects the environment; see .env.example for the variable
list. Secrets live in Railway and never in the repository.
railway runalso injects the productionCANONICAL_HOST, which 301s the test client.run_all.pystrips it per suite — which is why suites are run through the runner rather than individually.
| Application | Flask 3.1, Flask-Login, gunicorn (threaded workers) |
| Database | Neon Postgres (eu-west-2), psycopg3 with pooling |
| Hosting | Railway, EU West, auto-deploy from main |
| Payments | Stripe — Checkout, Billing Portal, webhooks (live) |
| Resend, DKIM/SPF verified | |
| Images | Pillow — share cards and PWA icons rendered in code |
| Front end | Server-rendered Jinja, hand-written CSS, no framework |
Eight runtime dependencies — the eighth is anthropic, for Telos Interview.
There is no JavaScript build step, no bundler and
no CSS framework — ~5,200 lines of hand-written CSS and 1839 of vanilla JS.
Proprietary — all rights reserved. See LICENSE.
Telos is a commercial service. The source is published so it can be read and evaluated, not so it can be reused: no permission is granted to deploy it, copy it, or run a service derived from it. Quoting excerpts for review or teaching is fine, with attribution.
The grade boundary data is published by AQA, Pearson Edexcel, OCR and SQA. It is factual reference data, it is not mine, and those organisations' own terms govern it.
/terms and /privacy are the service's own documents, and both are public —
somebody deciding whether to sign up, or a parent checking what their child's
revision app collects, should not need an account to read them.
app.py db.py auth.py mailer.py brand.py core application
prediction.py prescription.py revision.py pure engines
admissions.py admissions_papers.py pure engines, admissions
sharecards.py paper_templates.py rendering, catalogue
migrations/ 51 numbered SQL migrations
scripts/boundaries/ 36 board-document scripts
scripts/check_stripe.py read-only Stripe config verification
scripts/build_source_dump.py whole codebase as one annotated file
scripts/upload_admissions_papers.py push the official PDFs to the volume
tests/ 32 suites, ~987 assertions
templates/ 44 Jinja templates, including /terms and /privacy
LICENSE proprietary — all rights reserved
static/ CSS, JS, fonts, PWA manifest, service worker
TELOS_STATE.md living handoff — infrastructure, phases, gotchas
TELOS_ARCHIVE.md the reasoning behind every settled decision