@dcrackel/meyersquaredui
Version:
This template should help get you started developing with Vue 3 in Vite. The template uses Vue 3 `<script setup>` SFCs, check out the [script setup docs](https://v3.vuejs.org/api/sfc-script-setup.html#sfc-script-setup) to learn more.
90 lines (70 loc) • 2.78 kB
JavaScript
// utils/splitBracketByFinal.js
import { roundIndex } from "../layout/roundOrder";
/**
* Splits a DE bracket into left/right halves by finding the Final bout,
* then taking the two semifinal subtrees feeding into it.
*/
export function splitBracketByFinal(bouts) {
const byId = new Map();
const childrenByParent = new Map();
for (const b of bouts) {
if (b?.DEBoutId != null) byId.set(b.DEBoutId, b);
const fromId = b?.DEBoutId;
const toId = b?.DENextBoutId;
if (fromId == null || toId == null) continue;
if (!childrenByParent.has(toId)) childrenByParent.set(toId, []);
childrenByParent.get(toId).push(fromId);
}
const thirdPlaceBout = bouts.find(b => b?.RoundLabel === "Third Place") || null;
// Prefer explicit "Final"; fallback to deepest round
let finalBout =
bouts.find(b => b?.RoundLabel === "Final") ||
[...bouts].sort((a, b) => roundIndex(b?.RoundLabel) - roundIndex(a?.RoundLabel))[0] ||
null;
if (!finalBout || finalBout.DEBoutId == null) {
return { leftBouts: bouts, rightBouts: [], finalBout: null, thirdPlaceBout };
}
const finalId = finalBout.DEBoutId;
const semis = (childrenByParent.get(finalId) || [])
.map(id => byId.get(id))
.filter(Boolean);
// If we can't find two semis (data weird), bail safely
if (semis.length < 2) {
return {
leftBouts: bouts.filter(b => b?.RoundLabel !== "Third Place"),
rightBouts: [],
finalBout,
thirdPlaceBout,
};
}
// Collect subtree for each semi by walking DOWN via childrenByParent
function collectSubtree(rootId, acc) {
const stack = [rootId];
const seen = new Set();
while (stack.length) {
const id = stack.pop();
if (id == null || seen.has(id)) continue;
seen.add(id);
const bout = byId.get(id);
if (bout) acc.push(bout);
const kids = childrenByParent.get(id) || [];
for (const k of kids) stack.push(k);
}
}
const left = [];
const right = [];
// stable pick: top semi goes left, bottom semi goes right (by screen y if present later)
const semiA = semis[0].DEBoutId;
const semiB = semis[1].DEBoutId;
collectSubtree(semiA, left);
collectSubtree(semiB, right);
// remove Final + Third Place from halves
const strip = (arr) =>
arr.filter(b => b?.DEBoutId !== finalId && b?.RoundLabel !== "Third Place");
return {
leftBouts: strip(left),
rightBouts: strip(right),
finalBout,
thirdPlaceBout,
};
}