What a deneme is
One deneme is one scored paper. A TYT paper and an AYT paper from the same exam day are two denemeler. Their nets are never summed. A deneme carries per-subject results. Each result holdsdogru, yanlis, bos, and a net.
The server computes the net from the counts:
- TYT and AYT:
net = dogru − yanlis / 4 - LGS:
net = dogru − yanlis / 3
net and leave the counts out. When the counts are present, the server computes the net and
ignores a claimed one.
A deneme can also carry per-topic rows (“Paragraf: 8 doğru, 3 yanlış, 1 boş”). Topic rows are
optional. They feed the topic performance tables.
Subjects
Subject keys are canonical and exam-prefixed:tyt_matematik, ayt_tarih1, lgs_fen. On write,
the API also accepts display names, aliases, and short codes — Matematik, mat, and MAT all
land on the same key. An unknown subject is a 400, never a silent new subject.
Each result in a response carries the key, a Turkish label (“Matematik”), and a short code
(“MAT”) for dense views.
On AYT, tarih and coğrafya resolve to the -1 papers (ayt_tarih1, ayt_cografya1). Name the
-2 papers as tarih-2 or coğrafya-2.
Record a deneme
POST /api/denemeler records one paper.
totalNet rollup.
GET /api/denemeler lists denemeler, newest first, with an opaque cursor. Pass nextCursor back
as cursor for the next older page. examType narrows to one paper type.
Correct a deneme
PATCH /api/denemeler/:id is a partial update. Header fields overwrite. subjects and topics
upsert by their natural key:
dogru and
keeps the known yanlis, and the server recomputes the net and totalNet.
Set remove: true on a subject or topic row to delete it. examType cannot change — it would
re-key every subject. Delete the deneme and record it again.
DELETE /api/denemeler/:id removes the paper and every row under it. The averages recompute on
the next read.
The overview
GET /api/journey returns the journey tab in one call:
avgNet is the average of the last three denemeler of that exam type. trend compares that
window against the same window shifted one deneme back: up, down, or flat. The same pair
exists per subject.
daysTogether counts from sign-up, first day inclusive. The streak counts days with meaningful
activity: a chat message, a completed study block, a recorded deneme, or a saved check-in (see
Check-ins). current reads 0 once a day has been missed; longest is the
record.
One subject in depth
GET /api/journey/subjects/:subject serves the per-subject screen. The path parameter is the
canonical key:
series, newest first), all-time completed study minutes on the subject, and the topic table.
Each topic row aggregates the window: total questions, correct, accuracy (doğru over all
questions, 0–1), and consistency. Consistency is high when the per-deneme accuracy barely
moves, low when it swings, and null under three denemeler of data. strongTopics and
weakTopics are pre-filtered: strong is accuracy at or over 0.85, weak is under 0.6, and both
need at least three questions of sample.
Study time
GET /api/journey/study?from=2026-05-16&to=2026-08-13 sums completed planner minutes over a date
range. Both dates are local Istanbul dates. The range is capped at 366 days.
days carries every date in the range, zeros included — a heatmap renders straight off it.
bySubject is the distribution for the treemap, largest first, each with its share of the total
in pct. dailyAvgMin averages over the active days, not the calendar: it answers “how much
does a study day hold”.
Only blocks with status: done count, and a block with no length counts zero. To make study time
appear here, complete blocks through the planner (see Planner).
What Lala does with it
Lala reads the journey in every conversation: the newest denemeler, the trend, and the weakest topics. Lala also writes it — a student who reports a result in chat gets it recorded, and a correction (“matematik 18’di aslında”) lands as a patch. Records that Lala creates carrysource: "chat" and createdBy: "lala", so the client can tell them apart from form entries.