Improve randomisation of answers
This commit is contained in:
@@ -480,9 +480,10 @@ amateurfunk-anki [--data DIR] [--out DIR] [--seed STR] [--epoch INT]
|
||||
- `--seed STR` — deterministic seed for answer shuffling. Omit it
|
||||
for the normal study-deck behavior: a fresh seed is generated for
|
||||
each build, so answers are reshuffled every time decks are rebuilt.
|
||||
- `--epoch INT` — override the package timestamp epoch. By default we
|
||||
derive it from the manifest's `fetched_at`; this flag is mainly for
|
||||
tests and explicit rebuilds.
|
||||
- `--epoch INT` — override the package and note-modification timestamp
|
||||
epoch. By default we use the current rebuild time so Anki recognizes
|
||||
reshuffled notes as newer on re-import; this flag is mainly for tests
|
||||
and explicit reproducible builds.
|
||||
|
||||
Exit codes: `0` success, `1` configuration / catalog / build error.
|
||||
There is no Stage-2 equivalent of the fetcher's `EXIT_BAD_STATE` —
|
||||
@@ -602,13 +603,14 @@ same `.apkg` bytes out. Determinism rests on three things:
|
||||
2. **Stable shuffle.** `randomized_answers()` builds a per-question
|
||||
`random.Random` seeded from SHA-256 of
|
||||
`f"{cli_seed}:{question_number}"`.
|
||||
3. **Stable timestamps.** Every `now` value in the collection (the
|
||||
`mod` columns, the JSON config blob timestamps) is fixed to
|
||||
`build_epoch` — derived from the manifest's `fetched_at`, or
|
||||
overridden via `--epoch`. ZIP member timestamps are also fixed
|
||||
via `ZipInfo(name, zip_datetime(build_epoch))`. Without this
|
||||
last step, the inner SQLite would be identical but the
|
||||
archive's per-entry mtimes would still vary between runs.
|
||||
3. **Controlled timestamps.** Every `now` value in the collection (the
|
||||
`mod` columns and JSON config blob timestamps) uses `build_epoch`.
|
||||
A normal rebuild sets it to the current time because the fresh
|
||||
shuffle changes note HTML and Anki only updates an existing note
|
||||
when the imported copy is newer. `--epoch` fixes it explicitly for
|
||||
reproducible builds. ZIP member timestamps use the same value via
|
||||
`ZipInfo(name, zip_datetime(build_epoch))`; otherwise the inner
|
||||
SQLite could be identical while the archive bytes still differed.
|
||||
|
||||
The combined effect: two runs with the same `data/`, `--seed`, and
|
||||
timestamp inputs produce byte-identical sha256 on each `.apkg`.
|
||||
|
||||
Reference in New Issue
Block a user