/* ===================================================================== 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, }, }; }