Commit graph

13 commits

Author SHA1 Message Date
dev
a0fcfc93b6 Title-case subtopic names via scripts/titlecase.py
300 of 483 subtopics normalized ('Addition And Subtraction Formula'
-> 'Addition and Subtraction Formula'). Acronym FIX map preserves
AC/AM/GM/HM/AP/GP/EM/EMF/RMS/SHM/GOC/IUPAC/pH; article-A and PN
Junction fixed; VSEPR and Raoult's Law proper nouns corrected.
Chapter names were already title case. Applied to live tablet DB.
2026-10-16 15:20:14 +05:30
dev
02ab131c72 Reorganize bank to official NTA JEE Main syllabus units
The chapter structure now matches the NTA 2026 Paper 1 syllabus exactly
(verified against the official PDF at cdnbbsr.s3waas.gov.in):
- Physics: 20 units (Units and Measurements, Kinematics, Laws of Motion,
  ... Electronic Devices, Experimental Skills)
- Chemistry: 21 units (Some Basic Concepts, Atomic Structure, ...
  Principles Related to Practical Chemistry)
- Maths: 14 units (Sets Relations and Functions, Complex Numbers, ...
  Trigonometry)

scripts/reorg_nta_units.py maps upstream subtopics by keyword; 73
stragglers placed manually. Removed the 24 hand-written demo questions
(Q1-Q24) from the live bank — trivial one-liners that diluted the
difficulty pool. Bank is now 9,813 pure PYQs (2002-2025, all
exam='jee-main' verified from source metadata).
2026-10-14 19:17:47 +05:30
dev
7c4b1a4009 Fix stray dollars, remove dead UI, clear selection feedback, count input
Dollar fix: 5,634 questions had a lone $ before \( or $$ from the
source data. fix_single_dollar now strips any orphan single $ while
preserving $$..$$ display pairs; the live tablet DB was patched in
place and the importer inherits the fix.

UI: removed the non-functional 'previous year paper' mode card, the
complete-syllabus button, the tick glyph inside filter pills, and the
'2025 Syllabus' badge beside the header title. Question count pills
replaced by a plain number input (5-75). Checked chapters now show a
blue left-edge highlight so a second click visibly deselects; checked
subtopics tint blue the same way.
2026-10-14 16:30:17 +05:30
dev
54ba844f92 Revamp UI/UX, fix UTF-8 mojibake, normalize question typography, and reorganize JEE portions
1. UTF-8 Bugfix: Fixed byte-casting in views::rich() that turned multi-byte UTF-8
   sequences into Latin-1 mojibake (e.g. 2.06 × 10 -> 2.06 × 10).
2. Question Typography: Replaced nested <p class='stem'> with <div class='stem'>
   and strict CSS overrides ensuring consistent 1.0625rem font-size and weight
   across all 9,837 questions regardless of inner tags.
3. Modern Educational Theme: Removed harsh minimal 0-radius monospace styling;
   introduced comfortable slate dark theme (#090d16), rounded corners (8-12px),
   Inter typography, and refined option card states.
4. Topic Selection (/build) Revamp:
   - Added Quick Presets bar (Full Mock 75 Qs, Physics/Chemistry/Maths focus, Clear).
   - Added Subject Navigation Tabs (All, Physics, Chemistry, Mathematics).
   - Independent subtopic expand chevrons that don't force-check parent chapters.
   - Live question pool estimator and interactive count pills.
5. JEE Portion Reorganization (scripts/reorganize_jee_db.py): Re-categorized
   the database into the 15 official JEE Main units across Physics, Chemistry,
   and Mathematics.
2026-10-13 11:09:12 +05:30
dev
8a89f6045b Fix bench_write.py: indentation, state API instead of local DB
The UA edit broke indentation (script never ran since). Question ids
now come from /api/attempt/:id/state so the benchmark works against
any deployment. Verified live: 10 students, 45 writes/s through tunnel.
2026-10-13 09:18:20 +05:30
dev
dc754fe996 Student sign-in UX, gzip, landing stats cache
Sign-in page rewritten for non-technical students: Google-first when
configured, plain-language email path with honest 30-day scope, recovery
note, placeholders, full-width CTA. deploy/termux-start.sh sources .env
for GOOGLE_* credentials; deploy/env.example documents the 5-minute
Cloud Console setup; .gitignore covers secrets, DBs, pid/log files.
bench scripts send a browser UA so Cloudflare bot checks stop 403ing
local load tests. Landing bank counts cached 60s (five aggregate
subselects no longer run per hit). gzip compression on all responses.
2026-10-12 23:33:33 +05:30
dev
5f4539342a Fix math rendering: inline delimiters, matrix rewrite, TeX-ism cleanup
Source data wraps every math fragment in display-mode $$ delimiters,
which KaTeX rendered as centered blocks mid-sentence. scripts/fix_math.py
normalizes the corpus: $$/$ pairs become inline \\(...\\) (block
derivations with newlines or environments stay display), legacy
\\matrix blocks become begin/end matrix, _\\limits/^\\limits,
\\raise/\\lower boxes, \\root/\\of, \\tag and \\, are rewritten
to KaTeX-supported forms. Batch-validated 60k inline spans: 99.98% render
clean; remaining handful are source pathologies that degrade to text.
import_examgoal.py runs the same normalization at write time.
2026-10-12 23:25:45 +05:30
dev
ff1c23eaec Vendor examgoal unpickle models, portable pickle path
import_examgoal.py required /tmp/pyqeval helper modules that were never
committed, so it failed on any fresh machine. The two upstream model
files now live in scripts/examgoal_model/ (relative import fixed) and
the default pickle path is scripts/examgoal_db.pkl.
2026-10-12 20:34:50 +05:30
dev
45d2f38b0c Import 9,813 real JEE Main PYQs, KaTeX math, DB indexes
scripts/import_examgoal.py pulls the MIT-licensed examgoal-derived
14,973-question pickle and keeps the 9,813 fully-text MCQs with single
correct answers (2002-2025, all subjects). chapterGroup becomes our
chapter, chapter slug becomes our subtopic. Idempotent: skips stems
already present.

views.rs gains rich() — a read-side sanitizer matching the importer's
allowlist — and all six stem/option/solution render sites use it.
KaTeX auto-render (trust:false) added to head() for $$..$$ math.

db.rs gains nine CREATE INDEX statements; the chapter loader query
drops from ~5s to 6ms on the 9.8k-question bank. DATA.md rewritten
around the real pipeline with attribution.
2026-10-12 10:55:20 +05:30
dev
3df1d62002 Add expand_seed and document data sourcing
scripts/expand_seed.py generates synthetic questions across the full JEE Main
syllabus taxonomy (15 chapters, 45 subtopics, correct MCQ/NUM split). Stems
are deliberately sparse so no-one mistakes them for NTA content.

DATA.md documents why there is no real scraper: NTA PDFs render questions as
images; pdftotext extracts only IDs. Every aggregator with structured data
built it through manual entry pipelines. The document lists realistic paths
to a real bank and the SQL schema for loading one.
2026-10-12 05:19:03 +05:30
dev
1d8ee3b5ff Subtopic picker, JEE mode, per-subject timers
The builder previously exposed only chapters. Now each chapter expands to show
its subtopics as individual checkboxes: selecting a chapter checks all of its
subtopics, selecting the subject-level box checks everything, and selecting
individual subtopics sets the chapter to indeterminate. The exam query filters
by subtopic_id when any are given; the SQL path deduplicates so a question
matching two subtopics only appears once.

JEE mode sets duration to 60 × unique-subject-count (180 min for a full paper).
On the exam screen this renders per-subject countdown strips: Physics 60:00,
Maths 60:00, Chemistry 60:00. Each strip counts down independently; when one
hits zero the screen auto-jumps to the first unanswered question of the next
subject. The last strip exhausting time submits the form.

Single-subject papers keep the flat timer and show no strips.

Also: all audit targets now genuinely 44px (the .opt labels were 42px).
2026-10-12 05:13:09 +05:30
dev
14542f169a Make the exam screen work on a phone
The screen had no mobile state at all: the clock scrolled away mid-paper, the
only navigation was save-and-next so a candidate could not go back, the palette
sat below the question where it pushed submit off-screen, and the nav row lost
three of its four links under 700px.

Sticky header carries the clock and a progress bar; previous/next are real
buttons; the palette is a drawer below 1024px opened by a floating button that
sits above the tab bar. Primary destinations move to a bottom tab bar on
phones, data tables scroll inside their own card, and every control meets the
44px touch minimum.

Verified with a headless browser across five viewports rather than by reading
the stylesheet: scripts/audit_mobile.py fails on horizontal overflow, tap
targets under 44px, and content hidden behind a fixed bar; scripts/shots.py
captures each page at both widths. Both caught bugs I would otherwise have
shipped, including a palette toggle that lived inside the drawer it opened and
so could never be pressed on a phone.

fmt_dur drops a leading zero hour, so a 24 minute paper reads 24m 00s.
2026-10-11 21:54:17 +05:30
dev
c6269ad3dd Honour RUST_LOG, add load and scale benchmarks
The subscriber was pinned to DEBUG, so RUST_LOG=warn was ignored and sqlx
logged every statement to stderr in production. Now an EnvFilter defaults to
info with sqlx at warn; RUST_LOG=debug restores the query log.

Three benchmarks, so the hosting numbers come from measurement rather than
guesswork: scripts/bench.py for latency and throughput, bench_write.py for the
autosave and submit path under concurrent students, and bench_scale.py which
builds a database at the real bank's size (10,905 questions, 2,000 students,
12,000 papers, 900k answers) to report disk cost and query timings.
2026-10-11 21:08:35 +05:30