1. System Summary Overview
Letter Train is an educational app that teaches Sinhala letters by letting users trace ideal stroke paths and receive immediate feedback.
The project has three main parts:
- Flutter application (mobile/desktop) that renders the UI, captures strokes, and scores user drawings.
- Web demo (HTML/JS) that showcases the core tracing and rule‑based scoring in the browser.
- ML training code (Python/PyTorch) that trains a sequence model exported to
letter_scorer.tfliteand used in‑app.
2. Flutter App Architecture
Flutter2.1 Entry and App Shell
The app starts with LetterTrainApp, a MaterialApp in lib/app/app.dart, which sets a green seed color and uses MainMenuPage as the home screen.
2.2 Navigation Flow
- MainMenuPage: “Welcome” screen with cards for learning letters and two mini‑game placeholders.
- HomePage: grid of Sinhala letters sourced from
LetterSpecdefinitions. - LetterScreen: wrapper around the drawing canvas for a single letter, with a refresh button and navigation to practice mode and the next letter.
2.3 Letter Definition
Each letter (letterU, letterMa, letterPa, letterGa, letterKa) is defined by:
- title: the Sinhala character.
- svgData: a high‑resolution SVG path for the ideal stroke skeleton.
- startBase / endBase: hint points in SVG coordinates indicating where to start and end tracing.
3. Tracing Canvas & Feedback
Core Logic3.1 Canvas Component
The central widget is LetterPage (letter_canvas.dart), a stateful widget that:
- Parses the letter’s SVG into a Flutter
Pathand fits it into a square drawing area. - Samples the path into hundreds of points to form a “spine” used for distance and direction checks.
- Maintains a list of user strokes (
List<List<Offset>>) captured from pointer events.
A lightweight LetterCanvasController lets parent widgets clear the canvas programmatically.
3.2 Start/End Guidance
- On first stroke, the code checks whether the starting point lies close to the projected
startBasepolyline. - If the start is wrong, it displays “Start here” in red and refuses to begin the stroke.
- At stroke end, it verifies proximity to both the logical path end and the
endBasepolyline; failing that, it vibrates and fully resets the canvas.
3.3 Visual Rendering
- _SkeletonPainter: draws the letter skeleton in light grey, plus green “start here” and red “end here” guides with flags and arrows.
- _DrawPainter: re‑draws user strokes segment‑by‑segment in green when close to the skeleton, red when off‑path.
- A confetti system generates small falling colored rectangles when a letter is fully mastered.
4. Scoring & Modes
UX & Evaluation4.1 Practice Modes
- Guided mode: skeleton visible, stricter thresholds; success unlocks practice mode.
- Practice mode: can hide the skeleton; success transitions to a “done” state with confetti and navigation to the next letter.
4.2 Geometric Scoring
The \_analyze method computes several rule‑based checks:
- Size: bounding box must cover at least 25% of the canvas.
- Direction: sample indices along the path should mostly increase as the user moves.
- Order: stroke points must follow the intended progression along the path.
- Accuracy: mean distance to the skeleton path must stay below a threshold.
- Start/End: proximity to
startGuideandendGuidepolylines is required.
It also computes a base on‑path percentage by comparing segment length near the path to the total drawn length.
4.3 Haptics and Off‑Path Detection
- Every move, the code measures distance from current pen position to the nearest sampled skeleton point.
- Crossing a threshold triggers a heavy impact + vibrate and starts a periodic “buzz” timer whose frequency depends on how far off‑path the user is and how long they stay off.
- Returning within the threshold stops the buzzing.
4.4 User Feedback Text
Based on both rules and ML scores, the app assembles readable feedback:
- Positive: “Great job!”, “Now try without the guide”, “Yay! You completed <letter>.”
- Corrective: combinations of “Make it bigger”, “Trace in the right direction”, “Use the right stroke order”, “Stay on the path”, “Start here”, “End here”, “Trace smoothly”.