Herunterzaehlen mit -1/-5/-10 zaehlt als gemacht, Setzen bleibt eine Korrektur und zaehlt nicht. Der Stand "gemacht" beginnt mit jedem neuen Stream bei 0 (nicht beim Neustart des Hubs mitten im Stream), steht im Overlay unter der offenen Zahl und laesst sich auf der Uebersicht korrigieren. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
64 lines
2.5 KiB
TypeScript
64 lines
2.5 KiB
TypeScript
// 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(); },
|
|
};
|
|
}
|