third place fix und polymarket
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user