update
This commit is contained in:
@@ -94,11 +94,9 @@ const aktuelleFrage = slot.aktuelleFrage // ankert Bewertung/Diskussion
|
||||
const letztesFeedback = slot.letztesFeedback // Kontext für die Diskussion über eine Bewertung
|
||||
const scoreVorFrage = slot.scoreVorFrage // Score, als die Frage gestellt wurde → driftfreies (Re-)Bewerten
|
||||
const streakVorFrage = slot.streakVorFrage // Streak, als die Frage gestellt wurde (driftfrei)
|
||||
// Transient (pro Instanz): Eingabe-Entwurf, Lade-Spinner, Prefetch.
|
||||
// Transient (pro Instanz): Eingabe-Entwurf, Lade-Spinner.
|
||||
const pruefInput = ref('')
|
||||
const pruefLoading = ref(false)
|
||||
const naechsteFrage = ref(null) // im Hintergrund vorbereitete nächste Frage (Prefetch)
|
||||
let prefetchPromise = null // laufender Hintergrund-Abruf (verhindert Doppel-Prefetch)
|
||||
|
||||
const pruefMessagesEl = ref(null)
|
||||
const pruefInputEl = ref(null)
|
||||
@@ -164,72 +162,80 @@ function gestellteFragen() {
|
||||
return new Set(pruefMessages.value.filter((m) => m.kind === 'frage').map((m) => normFrage(m.content)))
|
||||
}
|
||||
|
||||
// Holt eine Frage; bis zu 3 Versuche, eine NICHT wiederholte zu bekommen. Sonst best-effort die letzte.
|
||||
async function frageHolen() {
|
||||
const gestellt = gestellteFragen()
|
||||
let letzte = null
|
||||
for (let i = 0; i < 3; i++) {
|
||||
const res = await pruefeBaustein({
|
||||
topic: props.topic, baustein: props.baustein, section: props.section,
|
||||
provider: props.provider, aktion: 'frage', messages: pruefDialog(),
|
||||
})
|
||||
letzte = res.frage
|
||||
if (!gestellt.has(normFrage(res.frage))) return res.frage
|
||||
}
|
||||
return letzte
|
||||
// --- Fragen-Pool: ZIEL vorgenerierte, geprüfte, unbeantwortete Fragen je Baustein (im Slot) ---
|
||||
const POOL_ZIEL = 5
|
||||
const pool = slot.pool
|
||||
const inflight = slot.inflight
|
||||
let poolMiss = 0 // aufeinanderfolgende Dubletten/Fehler — Cap gegen Endlosschleife (kleine Bausteine)
|
||||
|
||||
function istBekannt(text) {
|
||||
const n = normFrage(text)
|
||||
return !n || gestellteFragen().has(n) || pool.value.some((f) => normFrage(f) === n)
|
||||
}
|
||||
|
||||
// Nächste Frage im Hintergrund vorbereiten (überbrückt die Wartezeit). Ohne pruefLoading/pruefRun.
|
||||
function prefetchFrage() {
|
||||
if (naechsteFrage.value || prefetchPromise) return
|
||||
prefetchPromise = frageHolen()
|
||||
.then((text) => { naechsteFrage.value = text })
|
||||
.catch(() => {})
|
||||
.finally(() => { prefetchPromise = null })
|
||||
}
|
||||
|
||||
// Erste Frage (Phase idle): frisch generieren, dann die nächste vorbereiten.
|
||||
function frageAnfordern() {
|
||||
if (pruefLoading.value) return
|
||||
pruefSenden({ aktion: 'frage' }, (res) => {
|
||||
frageZeigen(res.frage)
|
||||
prefetchFrage()
|
||||
async function frageEinzeln() {
|
||||
const res = await pruefeBaustein({
|
||||
topic: props.topic, baustein: props.baustein, section: props.section,
|
||||
provider: props.provider, aktion: 'frage', messages: pruefDialog(),
|
||||
})
|
||||
return res.frage
|
||||
}
|
||||
|
||||
// „Nächste Frage": vorgemerkte sofort zeigen, sonst auf den Prefetch warten, sonst frisch holen.
|
||||
// Pool parallel auf ZIEL auffüllen; jede Auflösung dedupt + füllt nach.
|
||||
function poolFuellen() {
|
||||
while (pool.value.length + inflight.value < POOL_ZIEL && poolMiss < 6) {
|
||||
inflight.value++
|
||||
frageEinzeln()
|
||||
.then((text) => {
|
||||
if (text && !istBekannt(text)) { pool.value.push(text); poolMiss = 0 }
|
||||
else poolMiss++
|
||||
})
|
||||
.catch(() => { poolMiss++ })
|
||||
.finally(() => { inflight.value--; poolFuellen() })
|
||||
}
|
||||
}
|
||||
|
||||
// Eine Frage aus dem Pool nehmen; ist er leer, auf die erste eintreffende warten.
|
||||
async function poolNehmen() {
|
||||
if (!pool.value.length) {
|
||||
pruefLoading.value = true
|
||||
try {
|
||||
while (!pool.value.length && (inflight.value > 0 || poolMiss < 6)) {
|
||||
if (!inflight.value) poolFuellen()
|
||||
await new Promise((r) => setTimeout(r, 120))
|
||||
}
|
||||
} finally { pruefLoading.value = false }
|
||||
}
|
||||
return pool.value.length ? pool.value.shift() : null
|
||||
}
|
||||
|
||||
// Erste Frage (Phase idle): ZIEL parallel anstoßen, schnellste zuerst zeigen.
|
||||
async function frageAnfordern() {
|
||||
if (pruefLoading.value) return
|
||||
poolMiss = 0
|
||||
poolFuellen()
|
||||
const text = await poolNehmen()
|
||||
if (text) {
|
||||
frageZeigen(text)
|
||||
nextTick(() => pruefInputEl.value?.focus())
|
||||
} else {
|
||||
pruefMessages.value.push({ role: 'assistant', kind: 'fehler', content: 'Keine Frage — bitte erneut.' })
|
||||
}
|
||||
poolFuellen()
|
||||
}
|
||||
|
||||
// „Nächste Frage": sofort aus dem Pool, dann nachfüllen.
|
||||
async function naechsteFrageZeigen() {
|
||||
if (pruefLoading.value) return
|
||||
if (!naechsteFrage.value && prefetchPromise) {
|
||||
pruefLoading.value = true
|
||||
try { await prefetchPromise } finally { pruefLoading.value = false }
|
||||
}
|
||||
if (naechsteFrage.value) {
|
||||
const text = naechsteFrage.value
|
||||
naechsteFrage.value = null
|
||||
const text = await poolNehmen()
|
||||
if (text) {
|
||||
frageZeigen(text)
|
||||
pruefScroll()
|
||||
nextTick(() => pruefInputEl.value?.focus())
|
||||
prefetchFrage()
|
||||
return
|
||||
}
|
||||
// Fallback: kein Cache → frisch holen (mit Dedup).
|
||||
pruefLoading.value = true
|
||||
try {
|
||||
const text = await frageHolen()
|
||||
if (text) {
|
||||
frageZeigen(text)
|
||||
pruefScroll()
|
||||
nextTick(() => pruefInputEl.value?.focus())
|
||||
prefetchFrage()
|
||||
} else {
|
||||
pruefMessages.value.push({ role: 'assistant', kind: 'fehler', content: 'Keine neue Frage — bitte erneut.' })
|
||||
}
|
||||
} catch {
|
||||
pruefMessages.value.push({ role: 'assistant', kind: 'fehler', content: 'Hat nicht geklappt — bitte erneut.' })
|
||||
} finally {
|
||||
pruefLoading.value = false
|
||||
} else {
|
||||
pruefMessages.value.push({ role: 'assistant', kind: 'fehler', content: 'Keine neue Frage — bitte erneut.' })
|
||||
}
|
||||
poolFuellen()
|
||||
}
|
||||
|
||||
function nachfragen() {
|
||||
|
||||
Reference in New Issue
Block a user