+ return subrank_partitions(games, goals_parts, start_rank, tiebreakers, rank);
+ }
+
+ // OK, it's a tie. Give them all the same rank.
+ let result = [];
+ for (let i = 0; i < teams.length; ++i) {
+ result.push(teams[i]);
+ result[i].rank = start_rank;
+ }
+ return result;
+};
+
+// Same, but with the simplified rules for ranking thirds. games isn't used and can be empty.
+function rank_thirds(games, teams, start_rank, tiebreakers) {
+ if (teams.length <= 1) {
+ // Only one team, so trivial.
+ teams[0].rank = start_rank;
+ return teams;
+ }
+
+ // Rule #1: Partition the teams by score.
+ let score_parts = partition(teams, function(a, b) { return b.pts - a.pts });
+ if (score_parts.length > 1) {
+ tiebreakers.push(explain_tiebreaker(score_parts, 'most games won'));
+ return subrank_partitions(games, score_parts, start_rank, tiebreakers, rank_thirds);
+ }
+
+ // Rule #2: Goal difference against common opponents.
+ let gd_parts = partition(teams, function(a, b) { return b.gd - a.gd });
+ if (gd_parts.length > 1) {
+ tiebreakers.push(explain_tiebreaker(gd_parts, 'goal difference'));
+ return subrank_partitions(games, gd_parts, start_rank, tiebreakers, rank_thirds);
+ }
+
+ // Rule #3: Goals scored.
+ let goal_parts = partition(teams, function(a, b) { return b.goals - a.goals });
+ if (goal_parts.length > 1) {
+ tiebreakers.push(explain_tiebreaker(goal_parts, 'goals scored'));
+ return subrank_partitions(games, goal_parts, start_rank, tiebreakers, rank_thirds);