Question: Recursive object construction

Task: to create a tournament bracket according to the double elimination system. For the upper bracket, there were no problems, since the teams that won in the first round meet in the second, and so on. But for the lower bracket, in addition to the games among the losers in the first round, you need to add games among the losers in the second round of the upper bracket.
For example, given an array of lower bracket games:
const games = [
  { id: 1, home_name: "Team 1", visitor_name: "Team 3", home_score: 1, visitor_score: 0, round: 2 },
  { id: 2, home_name: "Team 6", visitor_name: "Team 7", home_score: 1, visitor_score: 0, round: 2 },
  { id: 3, home_name: "Team 1", visitor_name: "Team 6", home_score: 0, visitor_score: 1, round: 3 },
  { id: 4, home_name: "Team 4", visitor_name: "Team 5", home_score: 1, visitor_score: 0, round: 3 },
  { id: 5, home_name: "Team 6", visitor_name: "Team 4", home_score: 1, visitor_score: 0, round: 4 },
];

To display the structure of the lower bracket, you need to get the following object:
{
 name: "Team 6",
 children: [
  {
   name: "Team 4",
   children: [{ name: "Team 4" }, { name: "Team 5" }],
  },
  {
   name: "Team 6",
   children: [
    { name: "Team 1", children: [{ name: "Team 1" }, { name: "Team 3" }] },
    { name: "Team 6", children: [{ name: "Team 6" }, { name: "Team 7" }] },
   ],
  },
 ],
}

In the parent object "Team 6" is the winner of the lower bracket, this can be understood from the last (4) round played between Team 4 and Team 6, in turn Team 4 is determined by the game between Team 4 and Team 5 in round 3.
What the lower bracket will look like for these games:

How to get such an object from the games array? The number of games may vary depending on the number of teams.


Answer:
You could use a plain object to collect subtrees keyed by the winning team's name, starting out with an empty object. Then iterate the games in order of round and look up the two team's subtrees from that object (with a default {name} object). Then construct the children property from that and wrap it into a new root node. Register that node in the collection of subtrees.
Finally retain the last object that was created which will have the whole tree:


function getTree(games) {
    // Ensure the data is sorted by round -- if this is already ensured by caller, then you can drop this statement:
    games = [...games].sort((a, b) => a.round - b.round);
    
    const nodes = {}; // This will collect the subtrees, keyed by the winning team's name.
    let winner;
    for (const {home_name, home_score, visitor_name} of games) {
        const name = home_score ? home_name : visitor_name;
        winner = nodes[name] = {
            name,
            children: [
                nodes[home_name] ?? { name: home_name }, 
                nodes[visitor_name] ?? { name: visitor_name }
            ]
        };
    }
    return winner;
}

const games = [
  { id: 1, home_name: "Team 1", visitor_name: "Team 3", home_score: 1, visitor_score: 0, round: 2 },
  { id: 2, home_name: "Team 6", visitor_name: "Team 7", home_score: 1, visitor_score: 0, round: 2 },
  { id: 3, home_name: "Team 1", visitor_name: "Team 6", home_score: 0, visitor_score: 1, round: 3 },
  { id: 4, home_name: "Team 4", visitor_name: "Team 5", home_score: 1, visitor_score: 0, round: 3 },
  { id: 5, home_name: "Team 6", visitor_name: "Team 4", home_score: 1, visitor_score: 0, round: 4 },
];
console.log(getTree(games));