third place fix und polymarket

This commit is contained in:
2026-06-27 14:03:11 -05:00
parent a721de5b23
commit 2b3cadfcb5
4 changed files with 361 additions and 43 deletions

View File

@@ -132,17 +132,19 @@ function classifyGroups(states: Map<GroupId, GroupThirdState>): {
// einer FERTIGEN Gruppe (played === 3), ob es in ALLEN noch möglichen
// Restspiel-Konstellationen von maximal 7 anderen Dritten überholt werden kann.
export function securelyQualifiedThirdTeams(matches: Match[], teams: Team[]): Set<string> {
console.log("[3RD-DISPLAY] ThirdPlace ✓-haekchen = securelyQualifiedThirdTeams (team-level, zaehlt GD)",
"| ThirdPlace GRUENER name = CSS .team-complete (played===3, KEIN Sicherheitsindikator)",
"| Bracket fix = thirdSlotIsSecure -> classifyGroups -> lockedIn (group-level, NUR Punkte, KEIN GD)");
console.log("[3RD-SOURCE] securelyQualifiedThirdTeams aufgerufen (teams)");
const states = buildThirdStates(matches, teams);
const secureTeams = new Set<string>();
const { lockedIn } = classifyGroups(states);
for (const g of GROUP_IDS) {
const st = states.get(g)!;
// Nur fertige Gruppen mit eindeutigem Dritten
if (!st.finished || !st.third || st.possibleTeamIds.size !== 1) continue;
const my = st.third;
// Zähle, wie viele andere Gruppen einen Dritten stellen KÖNNEN,
// der definitiv BESSER ist als dieses Team (Worst-Case für uns: deren Best-Case vs. unser festes Ergebnis).
let couldBeBetter = 0;
for (const og of GROUP_IDS) {
if (og === g) continue;
@@ -152,13 +154,35 @@ export function securelyQualifiedThirdTeams(matches: Match[], teams: Team[]): Se
else if (os.third.points === my.points && os.third.goalDiff > my.goalDiff) couldBeBetter++;
else if (os.third.points === my.points && os.third.goalDiff === my.goalDiff && os.third.goalsFor > my.goalsFor) couldBeBetter++;
} else {
// Offene Gruppe: kann deren Dritter uns im Best-Case überholen?
if (os.maxPoints > my.points) couldBeBetter++;
else if (os.maxPoints === my.points && !os.finished) couldBeBetter++; // TD/GF offen → potentiell besser
else if (os.maxPoints === my.points && !os.finished) couldBeBetter++;
}
}
if (couldBeBetter <= 7) secureTeams.add(my.teamId);
const team = teams.find(t => t.id === my.teamId);
const isSecure = couldBeBetter <= 7;
if (isSecure) secureTeams.add(my.teamId);
// Diagnose-Log für Iran und Grenzfälle
const targetTeams = new Set(["IRN", "KOR", "ALG", "CRO"]); // Team-Codes
if (team && targetTeams.has(team.code)) {
console.log("[3RD-TEAM-SECURE]",
"team:", team.name, "| group:", g,
"| punkte:", my.points, "| gd:", my.goalDiff,
"| couldBeBetter:", couldBeBetter,
"| gruppe lockedIn:", lockedIn.has(g),
"| als sicher markiert:", isSecure);
}
}
const iranTeam = teams.find(t => t.code === "IRN");
if (iranTeam) {
console.log("[3RD-IRAN-DISPLAY]",
"secureTeams enthaelt Iran:", secureTeams.has(iranTeam.id),
"| secureGroups (lockedIn) enthaelt G:", lockedIn.has("G"),
"| haekchen gezeigt:", secureTeams.has(iranTeam.id) ? "ja" : "nein",
"| name gruen (CSS team-complete, played===3):", "immer bei finished gruppe",
"| im baum fix:", lockedIn.has("G") ? "ja (thirdSlotIsSecure via classifyGroups/POINTS)" : "nein");
}
return secureTeams;
@@ -167,43 +191,41 @@ export function securelyQualifiedThirdTeams(matches: Match[], teams: Team[]): Se
// Liefert die Gruppen, deren Dritter mathematisch sicher unter den Top 8 ist.
// (Gruppen-Ebene — für Fix-Markierung im Baum, nicht für Team-Häkchen.)
export function securelyQualifiedThirdGroups(matches: Match[], teams: Team[]): GroupId[] {
console.log("[3RD-SOURCE] securelyQualifiedThirdGroups aufgerufen (groups)");
const states = buildThirdStates(matches, teams);
const { lockedIn } = classifyGroups(states);
const { lockedIn, lockedOut, contested } = classifyGroups(states);
console.log("[3RD-CLASSIFY] lockedIn:", [...lockedIn].join(","),
"| lockedOut:", [...lockedOut].join(","),
"| contested:", [...contested].join(","));
return [...lockedIn];
}
// Prüft, ob ein bestimmter Dritten-Slot (Gegner des Siegers von `winnerGroup`)
// in ALLEN noch möglichen Konstellationen identisch bleibt.
export function thirdSlotIsSecure(winnerGroup: GroupId, matches: Match[], teams: Team[]): boolean {
console.log("[3RD-SOURCE] thirdSlotIsSecure aufgerufen (slot-fix via classifyGroups)");
const states = buildThirdStates(matches, teams);
const { lockedIn, contested } = classifyGroups(states);
if (lockedIn.size > 8) {
console.log("[3RD-SECURE] false: >8 lockedIn | wg:", winnerGroup, "| lockedIn:", [...lockedIn].join(","));
return false;
}
if (lockedIn.size > 8) return false;
if (lockedIn.size === 8) {
const assignment = resolveAnnexC([...lockedIn]);
if (!assignment) { console.log("[3RD-SECURE] false: no annex with 8 locked | wg:", winnerGroup); return false; }
if (!assignment) return false;
const ag = assignment[winnerGroup];
if (!ag) { console.log("[3RD-SECURE] false: no assignedGroup (8 locked) | wg:", winnerGroup); return false; }
if (!ag) return false;
const ss = states.get(ag);
if (!ss) return false;
const result = ss.finished && ss.third != null && ss.possibleTeamIds.size === 1;
console.log("[3RD-SECURE] final (8 locked):", result, "| wg:", winnerGroup, "| stableGroup:", ag);
return result;
}
if (lockedIn.size + contested.size < 8) {
console.log("[3RD-SECURE] false: <8 possible | wg:", winnerGroup, "| lockedIn:", lockedIn.size, "| contested:", contested.size);
return false;
}
if (lockedIn.size + contested.size < 8) return false;
const contestedArr = [...contested];
const need = 8 - lockedIn.size;
const combos = combinations(contestedArr.length, need);
if (combos > 200) { console.log("[3RD-SECURE] false: >200 combos | wg:", winnerGroup); return false; }
if (combos > 200) return false;
let stableGroup: GroupId | null = null;
for (const indices of enumerateCombinations(contestedArr.length, need)) {
@@ -212,16 +234,15 @@ export function thirdSlotIsSecure(winnerGroup: GroupId, matches: Match[], teams:
const assignment = resolveAnnexC(qGroups);
if (!assignment) continue;
const ag = assignment[winnerGroup];
if (!ag) { console.log("[3RD-SECURE] false: no assignedGroup | wg:", winnerGroup); return false; }
if (!ag) return false;
if (stableGroup === null) stableGroup = ag;
else if (stableGroup !== ag) { console.log("[3RD-SECURE] false: unstable slot | wg:", winnerGroup); return false; }
else if (stableGroup !== ag) return false;
}
if (stableGroup === null) { console.log("[3RD-SECURE] false: stableGroup=null | wg:", winnerGroup); return false; }
if (stableGroup === null) return false;
const ss = states.get(stableGroup);
if (!ss) return false;
const result = ss.finished && ss.third != null && ss.possibleTeamIds.size === 1;
console.log("[3RD-SECURE] final:", result, "| wg:", winnerGroup, "| stableGroup:", stableGroup);
return result;
}