Baustein 4: Merkkarten mit Wiederholung nach Zeitabstand
- Abgespecktes SM-2 mit drei Bewertungsstufen statt sechs - Abstaende 1, 3, dann Abstand mal Leichtigkeit; gedeckelt bei 180 Tagen - "nochmal" bringt die Karte in derselben Sitzung wieder - Taeglicher Stapel, gedeckelt auf 20 Karten, ueberfaellige zuerst - Fuenf Faecher zur Anzeige, abgeleitet aus dem Abstand - Filter nach Themenblock fuer gezieltes Ueben - Lernmodus fuers Handy: grosse Flaechen, Antippen, Wischen, kein Hover; am Rechner zusaetzlich Leertaste und Tasten 1/2/3 - Tabellen karte und karten_verlauf, jede Bewertung wird mitgeschrieben - Merkkarten zaehlen im Wochenfortschritt mit, gelernt ab Fach 4 - Kopfzeile am Handy einzeilig, Tipp-Hervorhebung abgeschaltet - 29 neue Tests, insgesamt 133 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
103a603eb4
commit
bb592ad2bd
+39
-2
@@ -1,4 +1,4 @@
|
||||
import { index, integer, primaryKey, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
||||
import { index, integer, primaryKey, real, sqliteTable, text, uniqueIndex } from 'drizzle-orm/sqlite-core';
|
||||
|
||||
/** Rollen – bewusst nur zwei. */
|
||||
export const rollen = ['ausbilder', 'azubi'] as const;
|
||||
@@ -89,11 +89,48 @@ export const wochenplanung = sqliteTable(
|
||||
],
|
||||
);
|
||||
|
||||
export const kartenBewertungen = ['sitzt', 'unsicher', 'nochmal'] as const;
|
||||
export type KartenBewertung = (typeof kartenBewertungen)[number];
|
||||
|
||||
export const karte = sqliteTable(
|
||||
'karte',
|
||||
{
|
||||
benutzerId: text('benutzer_id')
|
||||
.notNull()
|
||||
.references(() => benutzer.id, { onDelete: 'cascade' }),
|
||||
karteId: text('karte_id').notNull(),
|
||||
fach: integer('fach').notNull().default(1),
|
||||
faelligAm: text('faellig_am').notNull(),
|
||||
letzteBewertung: text('letzte_bewertung', { enum: kartenBewertungen }),
|
||||
wiederholungen: integer('wiederholungen').notNull().default(0),
|
||||
abstandTage: integer('abstand_tage').notNull().default(0),
|
||||
leichtigkeit: real('leichtigkeit').notNull().default(2.5),
|
||||
zuletztGelerntAm: text('zuletzt_gelernt_am'),
|
||||
},
|
||||
(t) => [primaryKey({ columns: [t.benutzerId, t.karteId] }), index('karte_faellig_idx').on(t.benutzerId, t.faelligAm)],
|
||||
);
|
||||
|
||||
export const kartenVerlauf = sqliteTable(
|
||||
'karten_verlauf',
|
||||
{
|
||||
id: text('id').primaryKey(),
|
||||
benutzerId: text('benutzer_id')
|
||||
.notNull()
|
||||
.references(() => benutzer.id, { onDelete: 'cascade' }),
|
||||
karteId: text('karte_id').notNull(),
|
||||
bewertung: text('bewertung', { enum: kartenBewertungen }).notNull(),
|
||||
bewertetAm: text('bewertet_am').notNull(),
|
||||
},
|
||||
(t) => [index('karten_verlauf_benutzer_idx').on(t.benutzerId, t.bewertetAm)],
|
||||
);
|
||||
|
||||
export type Benutzer = typeof benutzer.$inferSelect;
|
||||
export type Sitzung = typeof sitzung.$inferSelect;
|
||||
export type Ausbildung = typeof ausbildung.$inferSelect;
|
||||
export type HandoutGelesen = typeof handoutGelesen.$inferSelect;
|
||||
export type Wochenplanung = typeof wochenplanung.$inferSelect;
|
||||
export type Karte = typeof karte.$inferSelect;
|
||||
export type KartenVerlauf = typeof kartenVerlauf.$inferSelect;
|
||||
|
||||
/** Wird von der Schema-Abgleichprüfung im Test verwendet. */
|
||||
export const alleTabellen = { benutzer, sitzung, ausbildung, handoutGelesen, wochenplanung };
|
||||
export const alleTabellen = { benutzer, sitzung, ausbildung, handoutGelesen, wochenplanung, karte, kartenVerlauf };
|
||||
|
||||
Reference in New Issue
Block a user