Files
dogfather-universe/server/workspace-befinden-resuemee.js
T
DogFatherGitandClaude Opus 5 af56f97f4c screen2: EIN Resuemee statt neun -- mit Schritt und Team-Bezug
Filipe: "ich will dass das viel schoener aussieht und nicht so ein
scheiss durcheinander, man wird ja bekloppt. das resume unten auf
jeder frage hab ich auch schon mehrmals gesagt muss weg ich will ein
ganzes gesamtresume was die leute animiert und pusht immer und mega
geile super team loesungen findet aber auch individuel so dass jeder
sich selber auch verbessert und steigert fuers team."

WAS WEG IST
Der Block "Was dein Verlauf sagt" -- eine Zeile JE FRAGE, jede mit
Titel, Marke, Einordnung aus der Forschung und einem "Was hilft". Bei
neun Fragen neun Kaesten untereinander. Genau das meint "man wird ja
bekloppt": Wenn alles gleich wichtig aussieht, ist nichts wichtig,
und man liest keinen davon.

WAS AN SEINE STELLE TRITT -- UND NICHTS VERLIERT
Die Erkenntnisse sind nicht weg, sie sind zusammengefasst:

  DEIN NAECHSTER SCHRITT. Genau EINER, zu der Sache, die am meisten
  haengt. Kernfragen zuerst -- sie werden in jeder Runde gestellt, ihr
  "hakt" wiegt schwerer als das einer Zusatzfrage, die alle vier
  Runden vorbeikommt. Haengt nichts, nimmt er die Sache, die noch
  WAECHST: "nichts zu tun" ist nur fuer den richtig, bei dem alles
  laeuft. Die Einordnung aus der Forschung steht daneben -- einmal
  statt neunmal, als Grund, warum es dieser Schritt ist.

  WAS DAS TEAM DAVON HAT. Abgeleitet aus der Lage, nicht erfunden.
  Ein "gemeinsam schaffen wir das" an jemanden, bei dem fuenf von
  neun Sachen haken, ist das Gegenteil von Hilfe -- in der schwersten
  Lage ist der Team-Bezug deshalb eine Entlastung ("im Team ist
  gerade nichts von dir gefragt"), keine Aufforderung. Vier Lagen,
  vier Saetze. Die Pruefung verlangt ausdruecklich, dass es KEIN
  Spruch ist, der immer passt.

ZWEI DINGE, DIE ERST DAS BILD GEZEIGT HAT
1. "Die Menge passt gerade" stand ZWEIMAL untereinander -- einmal im
   Thema-Block, gleich darunter als Schritt. Kein Messwert meldet das;
   im Bildschirmfoto sah es aus wie ein Fehler. Der Thema-Block nennt
   die Titel jetzt nur noch, wenn es mehrere sind.
2. "Wenn du eine Sache angehst, dann die: Die Menge passt gerade" --
   die Fragetitel im Katalog sind SAETZE, keine Substantive. Jetzt
   "Fang hier an: 'Die Menge passt gerade'".

EIN FUND DER PRUEFUNG: Die TikTok-Quelle war beim Umzug ins Fazit
verlorengegangen. Filipe hatte sie ausdruecklich bestellt ("eine
professionelle auch mit infos und so aus aller welt was tiktok
angeht"). pruef-befinden hat es gemeldet.

Die Pruefung verlangte bis heute das GEGENTEIL -- eine Zeile je
Frage, zu jeder eine Einordnung. Sie ist beim Umbau rot geworden,
richtig so. Jetzt prueft sie, dass unter den Fragen KEIN Resuemee
mehr steht, dass es GENAU EINEN Schritt gibt (nicht "mindestens
einen" -- das waere auch bei neun gruen) und dass der Schritt Inhalt
hat, nicht nur einen Kasten.

pruef-befinden 116/0 (war 113), pruef-resuemee 35/0,
pruef-entwicklung 48/0, pruef-css-klassen 30/0.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-22 09:35:36 +02:00

335 lines
15 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/* =====================================================================
workspace-befinden-resuemee.js — Eine Zusammenfassung am Ende
(20.09.2026)
Filipe: „und am ende von allen fragen will ich eine gesamte
zusammenfassung, nicht bei jeder frage oder kategorie eine, sondern
EINE gesamte am ende. eine motivierende zusammenfassung für die
person. hol die beste der beste möglichkeiten dafür die man beutzen
kann kostenlos."
---------------------------------------------------------------------
DIE FRAGE NACH DER „BESTEN KOSTENLOSEN MÖGLICHKEIT" — EHRLICH
BEANTWORTET
Naheliegend wäre eine der kostenlosen KI-Schnittstellen (Groq,
Gemini, HuggingFace). Sie wäre hier die FALSCHE Wahl, und zwar aus
drei Gründen, von denen jeder einzelne reicht:
1. ES SIND GESUNDHEITSDATEN. Die Antworten sagen, wer nachts wach
liegt, wer angefeindet wird, wer ans Aufhören denkt. Genau
deshalb sind sie im ganzen Haus als `nurSelbst` markiert und
liegen in einer eigenen Tabelle, die kein anderer Weg liest.
Sie an einen fremden Dienst zu schicken, damit er einen netten
Satz daraus baut, würde diese ganze Sorgfalt in einer Zeile
aufheben. Kostenlose KI-Angebote bezahlt man mit den Daten —
in ihren Bedingungen steht meist ausdrücklich, dass Eingaben
zum Training verwendet werden dürfen.
2. EIN SPRACHMODELL ERFINDET. Es schreibt ohne Weiteres „du hast
dich diesen Monat deutlich erholt", wenn das Gegenteil dasteht,
und es klingt dabei überzeugend. Eine Zusammenfassung über das
eigene Befinden, die etwas Falsches behauptet, ist schlimmer
als keine: Man glaubt ihr ja, und beim nächsten Mal glaubt man
ihr nicht mehr — auch dann nicht, wenn sie recht hat.
3. SIE FÄLLT AUS. Ein fremder Dienst hat Störungen, Kontingente
und Kündigungen. Dieser Text hier funktioniert in zehn Jahren
noch, ohne Schlüssel, ohne Rechnung, ohne Netz.
DIE BESTE KOSTENLOSE MÖGLICHKEIT IST DESHALB KEINE KI, SONDERN
SORGFÄLTIG GESCHRIEBENE SPRACHE ÜBER GERECHNETEN ZAHLEN. Sie läuft
auf Filipes eigenem Server, kostet nichts, lügt nie und kann nicht
ausfallen. Was ein Sprachmodell hier besser könnte — Abwechslung im
Wortlaut — ist gegen die drei Punkte oben kein Argument.
---------------------------------------------------------------------
WIE MAN MOTIVIERT, OHNE ZU LÜGEN
Das ist die eigentliche Schwierigkeit. Eine Zusammenfassung, die bei
sechs von acht „da hakt es" fröhlich bleibt, ist keine Ermutigung,
sondern Hohn — und beim nächsten Mal antwortet man ihr nicht mehr
ehrlich. Drei Regeln, und sie gelten in jeder Lage:
ZUERST, WAS TRÄGT — und zwar benannt, nicht als Zahl. „Dass du
nach der Schicht abschalten kannst, ist das, was das hier
zusammenhält" sagt etwas. „5 von 8 grün" sagt nichts.
DANN HÖCHSTENS EINE SACHE. Wer fünf Probleme auf einmal vorgelegt
bekommt, sieht keine fünf Aufgaben, sondern einen Berg. Die Liste
aller Punkte steht ohnehin darüber; hier steht die EINE, bei der
sich das Hinsehen am meisten lohnt.
UND EIN SCHLUSS, DER ZUR LAGE PASST. Nicht „weiter so" für alle.
Wer gerade viel trägt, braucht einen anderen letzten Satz als
jemand, bei dem alles läuft.
---------------------------------------------------------------------
KEINE ZAHLEN, DIE JEMAND PFLEGEN MUSS
Jede Zahl in diesem Text wird gerechnet — auch „acht Fragen" und
„sechs Felder". Ein fester Satz „alle sechs Felder sind ruhig" wäre
beim siebten Feld still falsch, und niemand würde es merken.
===================================================================== */
/** Welche Stufe zählt als „läuft", welche als „hakt".
*
* Abgeleitet aus dem Schlüssel und nicht als eigene Liste gepflegt:
* `unklar` ist ausdrücklich WEDER gut noch schlecht — „kann ich nicht
* sagen" ist eine ehrliche Antwort und darf nicht als halbes Problem
* gezählt werden. Wer sie zu den Sorgen schlägt, erzeugt Sorgen, die
* niemand geäußert hat. */
const TRAEGT = new Set(["laeuft"]);
const WAECHST = new Set(["waechst"]);
const HAKT = new Set(["hakt"]);
/** Ein Satzende ohne doppelten Punkt. */
const satz = (t) => {
const x = String(t || "").trim();
if (!x) return "";
return /[.!?…]$/.test(x) ? x : x + ".";
};
/** Der erste Buchstabe klein — für Halbsätze, die angehängt werden.
* (Deutsche Substantive bleiben groß; deshalb nur dort benutzt, wo
* ein Verb oder Pronomen folgt.) */
const klein = (t) => (t ? t[0].toLowerCase() + t.slice(1) : t);
/**
* Die eine Zusammenfassung am Ende einer Runde.
*
* @param antworten { schluessel: stufe } — die Antworten DIESER Runde
* @param punkte Die Fragen dieser Runde (mit titel, feld, kern)
* @param felder BEFINDEN_FELDER
* @param vorher Die Antworten der VORIGEN Runde, oder null
* @returns {{moeglich, kopf, traegt, thema, schluss, zahlen}}
*/
export function resuemeeVon(antworten, punkte, felder, vorher = null, einordnung = {}) {
const gefragt = punkte.filter((p) => antworten?.[p.schluessel]);
/* DRITTER AUSGANG. Ohne Antworten gibt es nichts zusammenzufassen --
und das muss dastehen, statt dass ein freundlicher Satz über
nichts erscheint. */
if (!gefragt.length) {
return {
moeglich: false,
grund: "Noch keine Antworten in dieser Runde.",
kopf: null, traegt: [], thema: null, schluss: null,
zahlen: { gefragt: 0, traegt: 0, waechst: 0, hakt: 0, unklar: 0, felder: 0 },
};
}
const mit = (menge) => gefragt.filter((p) => menge.has(antworten[p.schluessel]));
const traegtP = mit(TRAEGT);
const waechstP = mit(WAECHST);
const haktP = mit(HAKT);
const unklarP = gefragt.length - traegtP.length - waechstP.length - haktP.length;
const feldName = (k) => felder.find((f) => f.schluessel === k)?.name || k;
/* ---- WELCHES FELD IST DAS THEMA? --------------------------------
Nicht die erste Frage mit „hakt", sondern das FELD mit den
meisten. Drei Haken quer über alles heißen „schwerer Monat";
drei Haken in EINEM Feld heißen „hier ist etwas". Nur das zweite
ist ein Befund, und nur darüber lohnt ein Satz.
Bei Gleichstand entscheidet die Reihenfolge der Felder, und die
geht von außen nach innen — das schwerere Thema gewinnt. */
const proFeld = new Map();
for (const p of haktP) {
proFeld.set(p.feld, (proFeld.get(p.feld) || 0) + 1);
}
let themaFeld = null, themaN = 0;
for (const f of felder) {
const n = proFeld.get(f.schluessel) || 0;
if (n > themaN) { themaFeld = f; themaN = n; }
}
/* ---- WAS TRÄGT ---------------------------------------------------
Höchstens zwei, und benannt. Eine Aufzählung von fünf Dingen liest
niemand; zwei bleiben hängen. Kernfragen zuerst — sie sind die,
die in jeder Runde gestellt werden, und damit die, deren „läuft"
am meisten bedeutet. */
const traegtListe = [...traegtP]
.sort((a, b) => (b.kern ? 1 : 0) - (a.kern ? 1 : 0))
.slice(0, 2)
.map((p) => ({ schluessel: p.schluessel, titel: p.titel, feld: p.feld }));
/* ---- HAT SICH SEIT DEM LETZTEN MAL ETWAS GEBESSERT? -------------
Nur echte Verbesserungen, und nur bei Fragen, die BEIDE Male
gestellt wurden. Seit die Fragen rotieren, wäre „war letztes Mal
nicht dabei" sonst eine Verbesserung — und das ist keine. */
const besser = [];
if (vorher) {
const rang = { hakt: 0, waechst: 1, laeuft: 2 };
for (const p of gefragt) {
const a = rang[vorher[p.schluessel]];
const b = rang[antworten[p.schluessel]];
if (a !== undefined && b !== undefined && b > a) besser.push(p);
}
}
/* ---- DER KOPFSATZ ------------------------------------------------
Vier Lagen, vier Sätze — und keiner davon behauptet etwas, das
nicht in den Zahlen steht. */
const n = gefragt.length;
let kopf;
if (!haktP.length && !waechstP.length) {
kopf = unklarP === n
? "Diesmal konntest du zu fast allem nichts sagen. Das ist eine ehrliche "
+ "Antwort – und beim nächsten Mal weißt du vermutlich mehr."
: `Alle ${n} Fragen dieser Runde stehen auf „Läuft". Das ist selten, und `
+ "es ist kein Zufall – irgendwas machst du gerade richtig.";
} else if (!haktP.length) {
kopf = `Nichts hakt gerade. ${waechstP.length === 1 ? "Eine Sache wächst" : `${waechstP.length} Sachen wachsen`} `
+ "noch – das heißt, sie sind unterwegs, nicht liegengeblieben.";
} else if (haktP.length === 1) {
kopf = `Von ${n} Fragen hakt genau eine. ${n - 1} laufen oder wachsen – `
+ "das ist der Boden, auf dem du stehst, und der ist tragfähig.";
} else if (haktP.length < n / 2) {
kopf = `${haktP.length} von ${n} Sachen haken gerade. Die anderen ${n - haktP.length} `
+ "nicht – und das ist die Hälfte der Auskunft, die man beim Draufschauen "
+ "meistens übersieht.";
} else {
/* DIE SCHWERE LAGE. Hier NICHT aufmunternd werden -- das ist der
Moment, in dem eine fröhliche Zusammenfassung alles Vertrauen
kostet. Stattdessen: benennen, entlasten, und den Weg zeigen.
„Fast nie an dir" ist keine Beschönigung, sondern das, was die
Forschung zu Belastung in Ehrenämtern durchgehend findet. */
kopf = `${haktP.length} von ${n} Sachen haken. Das ist viel, und es liegt `
+ "fast nie an der Person, die es aushält. Es ist ein guter Moment, "
+ "das jemandem zu sagen, statt es noch eine Runde mitzunehmen.";
}
/* ---- DER SCHLUSSSATZ ---------------------------------------------
Er gehört zur Lage. „Weiter so" für alle wäre ein Satz, der nie
jemanden meint. */
let schluss;
if (besser.length) {
schluss = besser.length === 1
? `Und etwas hat sich seit dem letzten Mal gebessert: ${klein(besser[0].titel)}. `
+ "Das hat sich nicht von allein gemacht."
: `Und ${besser.length} Sachen haben sich seit dem letzten Mal gebessert. `
+ "Das hat sich nicht von allein gemacht.";
} else if (haktP.length >= n / 2) {
schluss = "Du musst das hier nicht allein lösen. Dass du es aufgeschrieben "
+ "hast, ist der erste Teil – der zweite ist ein Satz an jemanden.";
} else if (haktP.length) {
schluss = "Das musst du heute nicht lösen. Es reicht, dass du es weißt – "
+ "beim nächsten Mal siehst du, ob es geblieben ist.";
} else {
schluss = "Nächste Runde in zwei Wochen. Bis dahin: nichts zu tun.";
}
/* ---- EIN SCHRITT, NICHT NEUN (22.09.2026) ------------------------
Filipe: "das resume unten auf jeder frage hab ich auch schon
mehrmals gesagt muss weg ich will ein ganzes gesamtresume ...
aber auch individuel so dass jeder sich selber auch verbessert
und steigert fuers team."
Vorher stand unter JEDER Frage eine Einordnung und ein "Was
hilft" -- bei neun Fragen neun Ratschlaege auf einmal. Das ist
keine Hilfe, sondern eine Maengelliste mit Fussnoten. Wer neun
Dinge gleichzeitig angehen soll, geht keins an.
Jetzt genau EINER: der zu der Sache, die am meisten haengt.
Kernfragen zuerst -- sie werden in jeder Runde gestellt, ihr
"hakt" wiegt also schwerer als das einer Zusatzfrage, die alle
vier Runden vorbeikommt.
Und wenn nichts hakt, ist der Schritt trotzdem einer: dann der
zu der Sache, die noch WAECHST. "Nichts zu tun" ist fuer jemanden,
bei dem alles laeuft, der richtige Satz -- aber nur dann. */
const schrittKandidaten = haktP.length ? haktP : waechstP;
const schrittP = [...schrittKandidaten]
.sort((a, b) => (b.kern ? 1 : 0) - (a.kern ? 1 : 0))[0] || null;
const e = schrittP ? (einordnung[schrittP.schluessel] || {}) : {};
const schritt = schrittP && e.hilft
? {
titel: schrittP.titel,
was: e.hilft,
/* Die Einordnung aus der Forschung steht EINMAL da, nicht
neunmal -- als Grund, warum dieser Schritt der richtige ist.
Ohne sie waere es ein Ratschlag; mit ihr ist es einer, den
jemand nachgeprueft hat. */
welt: e.welt || null,
haengt: !!haktP.length,
}
: null;
/* ---- WAS DAS TEAM DAVON HAT --------------------------------------
Filipe: "mega geile super team loesungen findet aber auch
individuel".
DER SATZ WIRD ABGELEITET, NICHT ERFUNDEN. Ein Team-Spruch, der
immer derselbe ist, wird beim dritten Mal ueberlesen -- und ein
"gemeinsam schaffen wir das" an jemanden, bei dem gerade fuenf
von neun Sachen haken, ist das Gegenteil von Hilfe.
Vier Lagen, vier verschiedene Saetze. Und in der schwersten ist
der Team-Bezug KEINE Aufforderung, sondern eine Entlastung: Wer
viel traegt, braucht nicht zu hoeren, dass er auch noch etwas
fuers Team tun soll. */
let team;
if (haktP.length >= n / 2 && n > 0) {
team = "Im Team ist gerade nichts von dir gefragt. Wenn du magst, sag "
+ "einem Menschen, wie es steht – das ist alles, und es reicht.";
} else if (haktP.length) {
team = themaFeld && themaN > 1
? `Wahrscheinlich bist du damit nicht allein: „${feldName(themaFeld.schluessel)}" `
+ "hakt selten nur bei einem. Es in der Runde anzusprechen löst es oft "
+ "für mehrere auf einmal."
: "Eine Sache, die bei dir hakt, hakt selten nur bei dir. Wer sie ausspricht, "
+ "löst sie oft für mehr als sich selbst.";
} else if (traegtListe.length) {
team = `Was bei dir gerade trägt – ${klein(traegtListe[0].titel)} – ist genau das, `
+ "wonach jemand anderes gerade sucht. Zwei Sätze darüber in der Runde sind "
+ "mehr wert als jede Anleitung.";
} else {
team = "Wenn du in der nächsten Runde etwas merkst, das anderen helfen würde: "
+ "sag es. Das ist der kürzeste Weg, wie aus einzelnen Leuten ein Team wird.";
}
return {
moeglich: true,
kopf,
schritt,
team,
traegt: traegtListe,
thema: themaFeld && themaN > 0
? {
feld: themaFeld.schluessel,
name: feldName(themaFeld.schluessel),
anzahl: themaN,
/* MEHRERE IN EINEM FELD SIND ETWAS ANDERES ALS EINES. Der Satz
sagt, welches von beidem es ist -- daran hängt, ob man mit
einer Sache spricht oder mit einem Thema. */
satz: themaN > 1
? satz(`Wenn du nur an einer Stelle hinschaust, dann hier: „${feldName(themaFeld.schluessel)}" `
+ `– da stehen ${themaN} der Haken beieinander. Das ist selten Zufall`)
: satz(`Wenn du nur an einer Stelle hinschaust, dann hier: „${feldName(themaFeld.schluessel)}"`),
/* DIE TITEL NUR, WENN ES MEHRERE SIND (22.09.2026).
Bei genau einem stand er zweimal untereinander: einmal hier
und gleich darunter als "Dein naechster Schritt". Im Bild
sah das aus wie ein Fehler -- gefunden hat es kein Messwert,
sondern der Blick auf den Bildschirm. */
titel: themaN > 1
? haktP.filter((p) => p.feld === themaFeld.schluessel).map((p) => p.titel)
: [],
}
: null,
schluss,
zahlen: {
gefragt: n,
traegt: traegtP.length,
waechst: waechstP.length,
hakt: haktP.length,
unklar: unklarP,
besser: besser.length,
/* GERECHNET, nicht eingetragen: Wer ein siebtes Feld ergänzt,
bekommt hier automatisch die 7. */
felder: new Set(gefragt.map((p) => p.feld).filter(Boolean)).size,
},
};
}