Inspiration

As maimai players, we constantly face the same question: "I want to improve at slides — what songs should I practice?" The game gives you difficulty ratings but no insight into why a chart is hard or what specific skills it demands. We wanted a tool that could read a chart and tell you exactly what you're up against.

What it does

Upload any maimai DX chart file and the analyzer returns:

  • Skill tags — Slide-Heavy, Stream, Trill, Stamina, Tech/Crossover, Hand-Alternation, or Balanced
  • Difficulty — read directly from the in-game level tag embedded in the chart file
  • Similar songs — matched from a pre-built database of 1,400+ charts so you can find practice material

You can also browse the full song library by tag to build your own training playlist.

How we built it

The pipeline has three stages:

1. Parsing — We use MaiConverter to decode the simai chart format into note events. Many modern charts use notation the library can't handle, so we wrote a regex-based fallback parser that extracts tap, hold, and slide counts directly from raw text, and computes duration accurately using the divisor markers ({N}) embedded in the simai format.

2. Tagging — For the 1,400-song database we use a zero-cost rule-based tagger: slide ratio, note density, BPM, and duration map to skill labels. For a single uploaded chart, we call Claude claude-sonnet-4-6 which reads both the raw chart text and the computed statistics to produce a more nuanced analysis.

3. Matching — Songs are stored in a SQLite database with their tags and difficulty. Similar songs are retrieved by tag overlap. Cover art is extracted from the chart packages, resized to 256×256 thumbnails, and served as static files.

The frontend is a React + Vite single-page app. Uploading a chart triggers an animated state machine: idle → analyzing → results, with a split-panel layout showing your chart's tags on the left and similar songs on the right.

Challenges we faced

Simai format fragmentation — The maimai chart format has evolved over many game versions with no formal spec. We encountered UTF-8 BOMs, Windows line endings, empty metadata fields that crash the parser, and modern slide notation (8-6-1[4:1], 6bx) that MaiConverter 0.14.5 simply rejects. The fallback parser handles all of these cases.

Difficulty accuracy — Our first density-based formula wildly underestimated hard charts. The real fix was reading the &lv_5= and &lv_6= tags already embedded in every maidata.txt — the game itself tells you the difficulty, we just needed to parse it.

Batch processing at scale — Tagging 1,400+ charts one at a time with an LLM would cost ~$10 and take hours. We replaced that with the rule-based tagger and ProcessPoolExecutor for multi-core parsing, dropping the full batch run to a few minutes at zero API cost.

Built With

Share this project:

Updates

Submission history