Skip to content

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Мислиша — Competition Results Explorer

An interactive web app for the results of Мислиша, Serbia's primary-school math competition. Three fully self-contained HTML pages let anyone search 11,052 participant records and browse school / city / grade analytics — with zero backend.


Status: one-off, actively maintained · Stack: static HTML + vanilla JS + Chart.js (CDN), Python for data prep · Runs at: https://den.tanaev.su/mislisa/

Live pages:

Page URL
Home — „Савремена" generations comparison (default index) https://den.tanaev.su/mislisa/
Searchable results table (11,052 rows, 2025 + 2026) https://den.tanaev.su/mislisa/mislisa2026.html
Analytics dashboard (school/city rankings, heatmap, charts) https://den.tanaev.su/mislisa/mislisa2026-analytics.html
„Савремена" (canonical URL for the home page) https://den.tanaev.su/mislisa/savremena.html

What it does

The official results portal (mislisa.arhimedes.rs) shows one grade at a time inside an iframe, with no search, no cross-year view, and no analytics. This project scrapes all grades and years once, then bakes the data into standalone HTML pages that are fast, searchable, and shareable.

  • Results table — filter by year (2025 / 2026 / both), grade (1–8), and award type; free-text search across student, school, and city; live award-count stats.
  • Analytics — schools and cities ranked by a fair quality index, a top-30 × 8-grade heatmap, and Chart.js breakdowns of awards and score distributions.
  • Home / Савремена — a focused comparison view for the „Савремена" school.

Every page is a single HTML file with the data embedded as JS constants — it works offline (swap the Chart.js CDN link for a local copy) and needs no server, database, or build step.

Architecture

Data is prepared once by a small Python pipeline and embedded into the HTML. There is no runtime backend — the browser just reads in-page constants.

  mislisa.arhimedes.rs  (official results API, no CORS — server-side fetch only)
          │  8 grades × N years
          ▼
  [scrape]   Python + urllib + HTMLParser
          │  → data/mislisa_<year>.json          (raw rows per year)
          ▼
  [combine]  merge years, add `godina` field
          │  → data/mislisa_all.json             (11,052 combined rows)
          ▼
  [analytics] pre-compute school/city/grade rankings + score distributions
          │  → data/mislisa_analytics.json       (all / 2025 / 2026 objects)
          ▼
  [embed]    inject JSON into HTML templates (placeholder + str.replace)
          │  → mislisa2026.html · mislisa2026-analytics.html · savremena.html
          ▼
  [deploy]   scp → reports:/opt/den-tanaev/public/mislisa/
          │
          ▼
       nginx  →  https://den.tanaev.su/mislisa/   (index.html is a symlink → savremena.html)

The data/*.json files are the source of truth for regeneration. The deployed HTML files carry their own copy of that data embedded inline.

Getting started

Just view it — open any HTML file directly in a browser (no server needed):

open /Users/dt/Projects/mislisa/mislisa2026.html
open /Users/dt/Projects/mislisa/mislisa2026-analytics.html

Regenerate the data + pages — requires Python 3 only (standard library; no pip installs). The full scrape → combine → analytics → embed pipeline, with runnable scripts, lives in CLAUDE.md under "How to Regenerate from Scratch". In short:

  1. Scrape each year from the Arhimedes API → data/mislisa_<year>.json
  2. Combine years → data/mislisa_all.json
  3. Compute analytics → data/mislisa_analytics.json
  4. Embed the JSON into the HTML templates (use placeholder + .replace(), not f-strings — see gotcha below)

Adding a new year (e.g. 2027)

Summarized from CLAUDE.md"How to Add a New Year":

  1. Scrape with YEAR = 2027data/mislisa_2027.json
  2. Combine — add 2027 to the years list → rebuilds data/mislisa_all.json
  3. Analytics — add "2027": compute(...) to the result dict
  4. Table HTML — add the year to the switcher/filter pills and refresh the embedded data
  5. Analytics HTML — add "2027": {...} to the embedded AV constant and the year switcher
  6. Deploy the updated HTML files

Project layout

mislisa/
├── README.md                       ← this file (public landing page)
├── CLAUDE.md                       ← deep pipeline notes: schema, regen scripts, gotchas
├── savremena.html                  ← home page („Савремена"); index.html symlinks to it in prod
├── mislisa2026.html                ← searchable results table (~2.0 MB, data embedded)
├── mislisa2026-analytics.html      ← analytics dashboard (~1.5 MB, data embedded)
└── data/
    ├── mislisa_2025.json           ← raw 2025 rows
    ├── mislisa_2026.json           ← raw 2026 rows
    ├── mislisa_all.json            ← combined 11,052 rows (with `godina`)
    └── mislisa_analytics.json      ← pre-computed analytics (all / 2025 / 2026)

Only .DS_Store is gitignored — the data JSON is committed so the pages can be regenerated from a clean clone.

Deploy

Ship the static files to the personal reports host over SSH:

scp /Users/dt/Projects/mislisa/savremena.html \
    /Users/dt/Projects/mislisa/mislisa2026.html \
    /Users/dt/Projects/mislisa/mislisa2026-analytics.html \
    reports:/opt/den-tanaev/public/mislisa/
  • SSH alias reports → the reports server; web root /opt/den-tanaev/public/.
  • nginx serves the mislisa/ directory at https://den.tanaev.su/mislisa/.
  • index.html on the server is a symlink → savremena.html, so /mislisa/ opens the home page.

Ownership

Private personal project, © dt. Backed up to https://github.com/deetan/mislisa (public repo).

About

Serbian math competition results explorer

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages