// Liegestuetze aus Kanalpunkten: was offen ist und was in diesem Stream // schon gemacht wurde. // // Eine Einloesung zaehlt `offen` hoch. Abdu zaehlt auf der Uebersichtsseite // herunter, wenn er sie gemacht hat - das wandert nach `gemacht`. Setzen ist // dagegen eine Korrektur und zaehlt nicht als gemacht: wer einen Tippfehler // behebt, hat dabei keine Liegestuetze gemacht. // // Beides liegt in der Datenbank: was die Zuschauer bezahlt haben, darf ein // Neustart nicht loeschen. `gemacht` beginnt mit jedem neuen Stream bei 0. import type { Db } from '#db/index.ts'; /** Mehr glaubt niemand, und ein Tippfehler mit sechs Nullen soll nicht im Bild stehen. */ export const HOECHSTENS = 99_999; export type LiegestuetzStand = { offen: number; gemacht: number }; export type Liegestuetze = { stand: () => LiegestuetzStand; /** * Zaehlt `offen` um `n` hoch oder (negativ) herunter, nie unter 0. Was * dabei wirklich abgezogen wurde, kommt zu `gemacht`. */ aendern: (n: number) => LiegestuetzStand; /** Setzt `offen` fest. Korrektur, zaehlt nicht als gemacht. */ setzen: (n: number) => LiegestuetzStand; /** Setzt `gemacht` fest. Korrektur. */ gemachtSetzen: (n: number) => LiegestuetzStand; /** Neuer Stream: `gemacht` auf 0, `offen` bleibt. */ neuerStream: () => LiegestuetzStand; }; export function createLiegestuetze(db: Db, name = 'liegestuetze'): Liegestuetze { const lesen = db.prepare('SELECT wert FROM zaehler WHERE name = ?'); const schreiben = db.prepare(` INSERT INTO zaehler (name, wert, geaendert) VALUES (?, ?, ?) ON CONFLICT(name) DO UPDATE SET wert = excluded.wert, geaendert = excluded.geaendert `); const OFFEN = name; const GEMACHT = `${name}-gemacht`; const wert = (n: string): number => (lesen.get(n) as { wert: number } | undefined)?.wert ?? 0; const schreibe = (n: string, w: number): number => { const sauber = Math.min(HOECHSTENS, Math.max(0, Math.trunc(w))); schreiben.run(n, sauber, new Date().toISOString()); return sauber; }; const stand = (): LiegestuetzStand => ({ offen: wert(OFFEN), gemacht: wert(GEMACHT) }); return { stand, aendern(n) { const vorher = wert(OFFEN); const nachher = schreibe(OFFEN, vorher + n); if (nachher < vorher) schreibe(GEMACHT, wert(GEMACHT) + (vorher - nachher)); return stand(); }, setzen(n) { schreibe(OFFEN, n); return stand(); }, gemachtSetzen(n) { schreibe(GEMACHT, n); return stand(); }, neuerStream() { schreibe(GEMACHT, 0); return stand(); }, }; }