ESP32-S3 Bench Guide
ESP32‑S3 N16R8 벤치 가이드: 실시간 핀아웃, 강의, 시뮬레이터 및 벤치 로그
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Fair presentation-day sign-ups for any class. Students rank the days they'd prefer, and
everyone gets a day as high on their own list as possible. When more students want a day
than it has seats, a fair random draw decides — not who clicked first. Under the hood it's
deferred acceptance (the kind of matching school-choice systems use), via the peer-reviewed
matching package.
Any professor with a school email can use it — no setup on their end:README 전문 보기 ↗Students rank the days they'd prefer, and everyone gets a day as high on their own list as
possible. When more students want a day than it has seats, a fair random draw decides — not
who clicked first. Under the hood it's deferred acceptance (the kind of matching
school-choice systems use), via the peer-reviewed
matching package.
That lottery is the standard, and most professors never change it. Under Schedule → How the schedule is made there are three others: a fresh draw for each day, most first choices (as many students as possible get their first choice), and first come, first served (by when each student first ranked). Each one's page for students says how it works, including whether ranking early helps.
Any professor with a school email can use it — no setup on their end:
Each professor sees only their own sheets. Nothing is lost by accident: a new class list is shown for review before it replaces the old one, every delete offers an Undo, every sheet keeps earlier versions (daily, and before anything is deleted or replaced) that can be restored without erasing newer rankings, professors can download or email themselves a backup any time (one is emailed when they close sign-ups), and a deleted sheet can be brought back for 30 days. Students' rankings save as they drag, and an old browser tab can never overwrite a newer ranking.
Everything the site and its Chrome extension do is in this repository:
matching_engine.py), the
database tables (schema.sql), and vercel.json. What isn't here is only what can't be:
the settings with passwords and keys (environment variables, listed below), the database
itself, and the paid display fonts, which their license doesn't let us publish (the site
falls back to free fonts without them).extension/ (Chrome Web Store id hafmidgmpikkkjphmcbnggidbaeoiapd). Its build
is reproducible: tools/build_extension.py store makes the same zip, byte for byte, from the
same code. Every change is built in public by
GitHub Actions,
which prints each file's fingerprint (the zip is kept with that run for 90 days). Each
version uploaded to the store is tagged helper-v<version>, and its zip, built from that
tag, is kept for good under
Releases with its sha256. To
check any copy, the store's included, against the code:
python tools/verify_extension.py <the .zip or .crx> --ref helper-v1.0.6./healthz).tests/, run on every change (above) against both SQLite and Postgres,
and the browser walk-throughs below.You'll make four free accounts: GitHub (holds the code), Supabase (the database), WorkOS (emails the sign-in codes), and Vercel (runs the site), plus, optionally, a Gmail account (emails professors their backups, and stands in if WorkOS is down). Nothing costs money.
Create a repository and push this folder to it. Public or private both work — nothing secret lives in the code. From this folder:
git init
git add . && git commit -m "Scheduler"
gh repo create scheduler --public --source . --push
(Use --private instead if you'd rather keep the code to yourself.)
.gitignore keeps local data (local.db), secrets (.env), and the virtualenv out of the
repository. Nothing secret lives in the code — every password goes in Vercel's settings (step 4).
scheduler@ or / break the connection string.)[YOUR-PASSWORD] with your
password. This is your DATABASE_URL.
schema.sql into Supabase's SQL Editor yourself.)Supabase will say the tables have "RLS enabled, no policies." That's on purpose: it shuts Supabase's automatic public API out of the data. The app connects directly, as the owner.
WorkOS's "Magic Auth" emails a 6-digit code from [email protected]; the site checks
the code itself. It's free for the first million users a month, needs no domain of your
own, and has no low daily ceiling. WorkOS keeps a record of each address it emails a code
to; the site deletes it once that person signs in, or within a day.
workos.dev and is only for testing).Scheduler: it's how the emails are signed.sk_live_). Either paste it on the
site's /owner page under Sign-in email once the site is running (it's checked with
WorkOS, stored encrypted, and takes effect at once), or set it as WORKOS_API_KEY in
Vercel (which then takes precedence; Vercel settings need a redeploy).Optional, a mailbox of the site's own (Gmail). It emails professors a backup when they
close sign-ups, sends you /owner's usage alerts, and sends the codes itself whenever
WorkOS can't. Without it, professors download backups instead.
[email protected].SMTP_PASSWORD.Go to vercel.com and sign up with GitHub (the free Hobby plan).
Add New → Project, and import your scheduler repository.
Project Name becomes your address: <name>.vercel.app. scheduler.vercel.app is
taken, so use something like scheduler-edu → scheduler-edu.vercel.app.
Open Environment Variables and add these before clicking Deploy:
| Name | Value |
|---|---|
SECRET_KEY | a long random string — run python3 -c "import secrets; print(secrets.token_hex(32))" |
DATABASE_URL | the Supabase connection string from step 2 |
WORKOS_API_KEY | the WorkOS secret key from step 3 (or leave it out and paste the key on /owner) |
SMTP_HOST | smtp.gmail.com (only with the optional Gmail account) |
SMTP_PORT | 587 (likewise) |
SMTP_USER | the Gmail address (likewise) |
SMTP_PASSWORD | its app password (likewise) |
OWNER_EMAIL | your own school email |
CRON_SECRET | another random string (same command as SECRET_KEY) |
Optional: INSTRUCTOR_EMAIL_DOMAINS (who can make accounts; default .edu),
EMAIL_DAILY_LIMIT (default 1000 with WorkOS, 90 with Gmail alone), APP_NAME
(default Scheduler), CONTACT_EMAIL
(an address for questions about the site, shown on the Privacy page),
DEFAULT_TIMEZONE (default America/Chicago; each professor's own time zone is picked up
from their browser when they sign in), BUILT_BY / BUILT_BY_EMAIL / BUILT_BY_URL (the
credit at the foot of every page; set BUILT_BY to to hide it), (where
the footer says the code is), ( turns off the spoo.me short links),
/ (another copy of Scheduler Helper, for
testing), (/: offer it for any school's Canvas; unset,
once the store has 1.1.0), and / /
("Connect Canvas", once a school issues a developer key). lists them all.
https://<your-address>/healthz — it should say "ok": true (and the commit it runs).https://<your-address>/owner shows the site's status (totals only — see Privacy below)./cron/daily.If a required setting is missing, every page shows an "Almost there" notice naming it.
.edu can sign
in. To let in a school with a different ending, add it to INSTRUCTOR_EMAIL_DOMAINS
(comma-separated, e.g. .edu,.ac.uk).EMAIL_DAILY_LIMIT sign-in emails a day (with
Gmail alone keep it under Gmail's 100–500). Students stay signed in for 90 days, so a class
of 50 uses about 50–60 emails once. /owner shows the day's count./owner (without any student data)./owner, switch an account off by its email address. That instructor can't
sign in and their students' links stop working; nothing is deleted.Vercel calls /cron/daily once a day (see vercel.json). It takes a restore point of every
sheet that changed, clears out expired codes and old logs, and — just by running — keeps
Supabase's free plan from pausing the database after a week of no activity.
/owner shows totals only — no names, no sheets, no students. (As the
person running the database you could read it directly in Supabase; the site gives you no
way to, and the privacy page tells users so.)HttpOnly/Secure/SameSite cookies, no caching of pages, and HTTPS.python3 -m venv .venv
.venv/bin/pip install -r requirements-dev.txt
.venv/bin/python app.py
Then open http://127.0.0.1:5050. With no settings, it uses a local SQLite file
(local.db) and shows sign-in codes on screen instead of emailing them. Copy .env.example
to .env to try real settings locally.
Run the tests (they also run against Postgres if TEST_PG_BIN points at a folder with
initdb and pg_ctl, as they do on GitHub):
.venv/bin/python -m pytest
tools/e2e_*.mjs drive a real Chrome, with Scheduler Helper loaded, through the Canvas
step against a stand-in Canvas: adding the helper from the page, signing in to Canvas,
picking a course, and deleting the helper after. They need Node, Chrome, the stand-in
Canvas, and a local Scheduler that knows it (each file's top says how to start them):
.venv/bin/python tools/fake_canvas.py
CANVAS_DEV_HOST=127.0.0.1:5077 .venv/bin/python -m flask --app app run --port 5070
node tools/e2e_canvas_helper.mjs
| File | What it does |
|---|---|
app.py | Entry point Vercel runs; security headers, error pages, public pages, the daily job |
teach.py | Instructor pages: sign-in, dashboard, everything you do to a sheet |
student.py | Student pages for one sheet, under /c/<sheet id> |
owner.py | The site owner's status page |
sheets.py | Sheet data, backups, restore points |
roster.py | Reading class lists from Canvas exports, spreadsheets, and pasted text |
signin.py | Emailed codes, PINs, and rate limits |
auth.py | Who's signed in; ending a student's sign-in from the professor's side |
matching_engine.py | The assignment algorithms (can't-do days, students who didn't rank, a fixed random draw per sheet) |
db.py, schema.sql | Database access and tables (same SQL on SQLite and Postgres) |
maintenance.py | The daily job |
settings.py | Every setting, read from environment variables |
deadlines.py | Deadlines, and the emails to professors about how sign-ups are going |
shortlink.py | A class's short link (spoo.me, no ads), checked daily |
helperstore.py | Which helper version the Chrome Web Store has (Chrome's own update service), so any school is offered it once it reads any |
extension/ | Scheduler Helper, the Chrome extension |
tools/build_extension.py, tools/verify_extension.py | Build the helper's zip (reproducibly), and check any copy against the code |
tools/fake_canvas.py, tools/e2e_*.mjs | The stand-in Canvas and the browser walk-throughs |
canvas_import.py, canvasdir.py, canvas_oauth.py | Taking a class list from the helper; which school's Canvas a professor uses; "Connect Canvas" |
-SOURCE_URLSHORT_LINKS0CANVAS_HELPER_IDSCANVAS_HELPER_STORE_URLCANVAS_HELPER_ANY_SCHOOL10CANVAS_OAUTH_HOSTCANVAS_OAUTH_CLIENT_IDCANVAS_OAUTH_CLIENT_SECRET.env.exampleThe emails to professors about how sign-ups are going, and backups by email, need the
optional Gmail account (SMTP_*); without it they aren't sent.
Click Deploy.
compose.py, usage.py, util.py | Emails opened in the professor's own mail app; usage totals for /owner; small helpers |
sitesecrets.py | Keys pasted on /owner, stored encrypted |
templates/, public/static/ | The pages, styles, and scripts (no inline scripts, per the CSP) |
.github/workflows/ci.yml | The public build: tests on SQLite and Postgres, and the helper's zip with its fingerprints |
.github/workflows/helper-release.yml | Each helper version's zip, built from its tag, kept under Releases |
docs/ | Publishing the helper on the Chrome Web Store; asking a school for Canvas access |