Skip to content

Commit

Permalink
Refactor bestOf logic
Browse files Browse the repository at this point in the history
  • Loading branch information
cp-mayank committed Nov 15, 2024
1 parent 4ef0dc0 commit b28600d
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 61 deletions.
3 changes: 1 addition & 2 deletions data/lib/api/tournament/tournament_model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,7 @@ enum TournamentType {
miniRobin(2, minTeamReq: 3),
boxLeague(3, minTeamReq: 4),
doubleOut(4, minTeamReq: 4),
superOver(5, minTeamReq: 2),
bestOf(6, minTeamReq: 2),
bestOfThree(6, minTeamReq: 2),
custom(7, minTeamReq: 2);

final int value;
Expand Down
3 changes: 1 addition & 2 deletions data/lib/api/tournament/tournament_model.g.dart

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 2 additions & 4 deletions khelo/assets/locales/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -301,16 +301,14 @@
"tournament_type_mini_robin": "Mini Robin",
"tournament_type_box_league": "Box League",
"tournament_type_double_out": "Double Out",
"tournament_type_super_over": "Super Over",
"tournament_type_best_of": "Best Of",
"tournament_type_best_of_three": "Best Of three",
"tournament_type_custom": "Custom",

"tournament_type_knock_out_description": "Teams face off in a single elimination, with the loser immediately knocked out.\nMinimum {count} teams required.",
"tournament_type_mini_robin_description": "A smaller round-robin format where each team plays once against all others.\nMinimum {count} teams required.",
"tournament_type_box_league_description": "Teams are divided into groups, with top teams advancing to the knockout stage.\nMinimum {count} teams required.",
"tournament_type_double_out_description": "Teams get two chances before being knocked out, with a winners and losers bracket.\nMinimum {count} teams required.",
"tournament_type_super_over_description": "A knockout format with a super over to decide tied matches.\nMinimum {count} teams required.",
"tournament_type_best_of_description": "Teams play a series of matches, and the first to win the majority is the champion.\nMinimum {count} teams required.",
"tournament_type_best_of_three__description": "Teams play a series of matches, and the first to win the majority is the champion.\nMinimum {count} teams required.",
"tournament_type_custom_description": "Fully flexible, create a structure that suits your needs.\nMinimum {count} teams required.",

"add_team_screen_title": "Add Team",
Expand Down
13 changes: 5 additions & 8 deletions khelo/lib/domain/extensions/enum_extensions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -302,10 +302,8 @@ extension TournamentTypeString on TournamentType {
return context.l10n.tournament_type_box_league;
case TournamentType.doubleOut:
return context.l10n.tournament_type_double_out;
case TournamentType.superOver:
return context.l10n.tournament_type_super_over;
case TournamentType.bestOf:
return context.l10n.tournament_type_best_of;
case TournamentType.bestOfThree:
return context.l10n.tournament_type_best_of_three;
case TournamentType.custom:
return context.l10n.tournament_type_custom;
}
Expand All @@ -321,10 +319,9 @@ extension TournamentTypeString on TournamentType {
return context.l10n.tournament_type_box_league_description(minTeamReq);
case TournamentType.doubleOut:
return context.l10n.tournament_type_double_out_description(minTeamReq);
case TournamentType.superOver:
return context.l10n.tournament_type_super_over_description(minTeamReq);
case TournamentType.bestOf:
return context.l10n.tournament_type_best_of_description(minTeamReq);
case TournamentType.bestOfThree:
return context.l10n
.tournament_type_best_of_three__description(minTeamReq);
case TournamentType.custom:
return context.l10n.tournament_type_custom_description(minTeamReq);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ class _TournamentDetailScreenState
if (state.tournament == null) {
return;
}
if (state.tournament!.teams.length >= state.tournament!.type.minTeamReq) {
if (state.tournament!.teams.length == state.tournament!.type.minTeamReq) {
await AppRoute.matchSelection(tournamentId: state.tournament!.id)
.push(context);
} else {
Expand Down
96 changes: 52 additions & 44 deletions khelo/lib/ui/flow/tournament/match_selection/match_scheduler.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,8 @@ class MatchScheduler {
return scheduleBoxLeagueMatches();
case TournamentType.doubleOut:
return scheduleDoubleOutMatches();
case TournamentType.superOver:
return scheduleSuperOverMatches();
case TournamentType.bestOf:
return scheduleBestOfMatches();
case TournamentType.bestOfThree:
return scheduleBestOfThreeMatches();
case TournamentType.custom:
return scheduledMatches;
}
Expand Down Expand Up @@ -340,86 +338,96 @@ class MatchScheduler {
return additionalScheduledMatches;
}

GroupedMatchMap scheduleSuperOverMatches() {
return {};
}

GroupedMatchMap scheduleBestOfMatches() {
GroupedMatchMap scheduleBestOfThreeMatches() {
final GroupedMatchMap additionalScheduledMatches = scheduledMatches;
final List<TeamModel> teamPool = List.from(teams);

final roundOne = additionalScheduledMatches[MatchGroup.round]?[1] ?? [];
final roundTwo = additionalScheduledMatches[MatchGroup.round]?[2] ?? [];

final winnersRoundOne = scheduleBestOfBracketTeams(roundOne, teamPool, 3);

if (winnersRoundOne.isNotEmpty && roundTwo.isNotEmpty) {
scheduleBestOfBracketTeams(roundTwo, winnersRoundOne, 3);
}
scheduleBestOfThreeBracketTeams(roundOne, teamPool, 3);

final rounds = {1: roundOne};
if (roundTwo.isNotEmpty) {
rounds.addAll({2: roundTwo});
}

additionalScheduledMatches.addAll({MatchGroup.round: rounds});

return additionalScheduledMatches;
}

List<TeamModel> scheduleBestOfBracketTeams(
List<TeamModel> scheduleBestOfThreeBracketTeams(
List<MatchModel> roundMatches,
List<TeamModel> teams,
int bestOfCount,
) {
final List<TeamModel> winners = [];

final teamPairs = createTeamPairsForBestOf(teams);
final teamPairs = createTeamPairsForBestOfThree(teams);

for (var pair in teamPairs) {
int teamAWins = 0;
int teamBWins = 0;

for (int matchNumber = 1; matchNumber <= bestOfCount; matchNumber++) {
final match = createBestOfMatch(pair.first, pair.last, 1, matchNumber);
roundMatches.add(match);

final winnerTeam = match.teams
.firstWhereOrNull(
(element) => element.team.id == match.matchResult!.teamId)
?.team;
for (int matchNumber = 1; matchNumber <= 3; matchNumber++) {
final existingMatch = roundMatches.firstWhereOrNull(
(match) =>
match.teams.map((team) => team.team.id).contains(pair.first.id) &&
match.teams.map((team) => team.team.id).contains(pair.last.id) &&
match.match_group_number == matchNumber,
);

if (existingMatch == null) {
if (matchNumber == 1) {
final newMatch =
createBestOfThreeMatch(pair.first, pair.last, 1, matchNumber);
roundMatches.add(newMatch);
}
continue;
}

if (winnerTeam == pair.first) {
teamAWins++;
} else if (winnerTeam == pair.last) {
teamBWins++;
final winner = existingMatch.matchResult?.teamId != null &&
existingMatch.matchResult?.winType != WinnerByType.tie
? existingMatch.teams
.firstWhereOrNull(
(team) => team.team.id == existingMatch.matchResult?.teamId)
?.team
: null;

if (winner != null) {
if (winner.id == pair.first.id) teamAWins++;
if (winner.id == pair.last.id) teamBWins++;

if (teamAWins >= bestOfCount / 2) {
winners.add(pair.first);
break;
} else if (teamBWins >= bestOfCount / 2) {
winners.add(pair.last);
break;
}
}

if (teamAWins > bestOfCount / 2) {
winners.add(pair.first);
break;
} else if (teamBWins > bestOfCount / 2) {
winners.add(pair.last);
break;
if (existingMatch.matchResult?.winType == WinnerByType.tie) {
continue;
}
}

if (teamAWins > teamBWins) {
winners.add(pair.first);
} else if (teamBWins > teamAWins) {
winners.add(pair.last);
}
}

return winners;
}

List<List<TeamModel>> createTeamPairsForBestOf(List<TeamModel> teams) {
List<List<TeamModel>> createTeamPairsForBestOfThree(List<TeamModel> teams) {
List<List<TeamModel>> pairs = [];

for (int i = 0; i < teams.length; i++) {
for (int j = i + 1; j < teams.length; j++) {
pairs.add([teams[i], teams[j]]);
}
}

return pairs;
}

MatchModel createBestOfMatch(
MatchModel createBestOfThreeMatch(
TeamModel teamA,
TeamModel teamB,
int roundNumber,
Expand Down

0 comments on commit b28600d

Please sign in to comment.