// End of the game: a retrospective front page. It covers both the normal end of // the term and each way of losing power early. import { t, tx, tp, tt, getLang, dateParts, fmt } from "../i18n/i18n.js"; import { buildReview, dateOfDay, indexCards } from "../engine/index.js"; import { lineChart } from "./charts.js"; import { $, esc } from "./desk.js"; const MIN_SPAN = 30; // series id in state.history, label key, show the term average or the final value const CHARTS = [ ["opinion", "ind.opinion", "avg"], ["stability", "ind.stability", "avg"], ["economy", "ind.economy", "avg"], ["debtRatio", "econ.debt", "final"], ]; export function createEndgame(root, { newsName, endgame, cards, onAgain }) { const cardsById = indexCards(cards); root.addEventListener("click", (e) => { if (e.target.closest("button[data-again]")) onAgain(); }); let shown = ""; function chart(state, [id, label, mode], review) { const series = state.history.series[id] ?? []; const value = mode === "avg" ? review.metrics[id] : series.at(-1); const tag = mode === "avg" ? t("end.averages") : t("end.final"); // Zoom on the data (at least MIN_SPAN points tall) so trends are visible; stay within 0-100 // for indicators, and above 0 for debt. const lo = Math.min(...series); const hi = Math.max(...series); const span = Math.max(hi - lo, MIN_SPAN); let min = Math.max(0, (lo + hi) / 2 - span / 2); let max = min + span; if (id !== "debtRatio" && max > 100) { max = 100; min = 100 - span; } return `
${t(label)}${esc(fmt(value, 0))}${tag}
${lineChart(series, { min, max })}
`; } function decision(d) { const card = cardsById.get(d.id); const date = dateParts(dateOfDay(root.dataset.startDate, d.day).iso); return `
  • ${esc(date.day)} ${esc(date.month)} ${esc(date.year)} ${esc(tx(card.title))} ${esc(t("end.chose", { label: tx(card[d.choice].label) }))}
  • `; } function update(state, bal) { if (!state.over) { if (shown) { root.hidden = true; root.innerHTML = ""; shown = ""; } return; } const key = `${state.over.type}:${state.over.day}:${getLang()}`; if (key === shown) return; shown = key; root.dataset.startDate = state.startDate; const review = buildReview(state, bal, cards, endgame); const banner = endgame.over[state.over.type]; const entry = endgame.titles.find((x) => x.id === review.titleId); const date = dateParts(dateOfDay(state.startDate, state.over.day).iso); const lost = state.over.type !== "term"; root.innerHTML = `

    ${esc(tx(newsName))}

    ${esc(t("news.edition", { date: date.full }))}

    ${esc(tx(banner.h))}

    ${esc(tx(banner.d))}

    ${t("end.verdict")}

    ${esc(review.grade)} ${t("end.grade")}

    ${entry ? esc(tt(entry.title, state.pronouns)) : ""}

    ${entry ? esc(tp(tx(entry.verdict), state.pronouns)) : ""}

    ${t("end.score", { n: Math.round(review.score) })}
    ${t("end.served", { days: state.over.day })}

    ${CHARTS.map((c) => chart(state, c, review)).join("")}

    ${t("end.decisions")}

    ${review.topDecisions.length ? `
      ${review.topDecisions.map(decision).join("")}
    ` : `

    ${t("end.noDecisions")}

    `}
    `; root.hidden = false; $(root, "button[data-again]").focus(); } return { update }; }