diff options
-rw-r--r-- | augment.py | 12 |
1 files changed, 11 insertions, 1 deletions
@@ -8,6 +8,7 @@ tabelle = [] | |||
8 | with open('data.json') as f: | 8 | with open('data.json') as f: |
9 | data = json.load(f) | 9 | data = json.load(f) |
10 | 10 | ||
11 | # Augment example orte with Raucher flag | ||
11 | ident = 0 | 12 | ident = 0 |
12 | for o in data["orte"]: | 13 | for o in data["orte"]: |
13 | o["id"] = ident | 14 | o["id"] = ident |
@@ -15,6 +16,7 @@ for o in data["orte"]: | |||
15 | o["teams"] = [] | 16 | o["teams"] = [] |
16 | ident += 1 | 17 | ident += 1 |
17 | 18 | ||
19 | # Augment example teams with weekday, league and Raucher flag | ||
18 | ident = 0 | 20 | ident = 0 |
19 | for t in data["teams"]: | 21 | for t in data["teams"]: |
20 | 22 | ||
@@ -59,7 +61,7 @@ for league in range(league_count): | |||
59 | 61 | ||
60 | print( "Max Spieltage: ", max_spieltage) | 62 | print( "Max Spieltage: ", max_spieltage) |
61 | 63 | ||
62 | # Fill Tabelle with our demo data | 64 | # Generate all pairings with our demo data, making up wildcards as we go |
63 | ident = 0 | 65 | ident = 0 |
64 | for league in range(league_count): | 66 | for league in range(league_count): |
65 | league_teams = [t for t in data["teams"] if t["liga"] == league] | 67 | league_teams = [t for t in data["teams"] if t["liga"] == league] |
@@ -80,6 +82,7 @@ for league in range(league_count): | |||
80 | ident += 1 | 82 | ident += 1 |
81 | game_count += 1 | 83 | game_count += 1 |
82 | 84 | ||
85 | # For leagues with fewer Spieltage, fill up the remainder with wildcard games | ||
83 | while game_count < max_spieltage / 2: | 86 | while game_count < max_spieltage / 2: |
84 | tabelle.append({"team_a": team_a["id"], "team_b": -1, "liga": league, "ort": -1, "tag": -1, "id": ident}) | 87 | tabelle.append({"team_a": team_a["id"], "team_b": -1, "liga": league, "ort": -1, "tag": -1, "id": ident}) |
85 | ident += 1 | 88 | ident += 1 |
@@ -87,11 +90,13 @@ for league in range(league_count): | |||
87 | ident += 1 | 90 | ident += 1 |
88 | game_count += 1 | 91 | game_count += 1 |
89 | 92 | ||
93 | # To ensure that Rueckspiele only happen in Rueckrunde, this is the threshold | ||
90 | rueckrundenstart = max_spieltage // 2 | 94 | rueckrundenstart = max_spieltage // 2 |
91 | 95 | ||
92 | from ortools.sat.python import cp_model | 96 | from ortools.sat.python import cp_model |
93 | model = cp_model.CpModel() | 97 | model = cp_model.CpModel() |
94 | 98 | ||
99 | # Create variables in our solver's model to hold all the possible Spieltage | ||
95 | variables = {game["id"]: model.new_int_var(0, max_spieltage - 1, f"game{game['id']}") for game in tabelle} | 100 | variables = {game["id"]: model.new_int_var(0, max_spieltage - 1, f"game{game['id']}") for game in tabelle} |
96 | 101 | ||
97 | # Make sure each team only plays once each spieltag | 102 | # Make sure each team only plays once each spieltag |
@@ -158,6 +163,8 @@ for team in data["teams"]: | |||
158 | 163 | ||
159 | violations.append(is_consecutive) | 164 | violations.append(is_consecutive) |
160 | 165 | ||
166 | # Most probably this constraint can't be fully satisfied, so just | ||
167 | # ask the solver to minimize clusters of Heimspiele for a team | ||
161 | model.minimize(sum(violations)) | 168 | model.minimize(sum(violations)) |
162 | 169 | ||
163 | print ("All set, solving") | 170 | print ("All set, solving") |
@@ -172,12 +179,15 @@ from sys import exit | |||
172 | if status == cp_model.INFEASIBLE: | 179 | if status == cp_model.INFEASIBLE: |
173 | exit(-1) | 180 | exit(-1) |
174 | 181 | ||
182 | # Distribute Spieltage back to the games so we can sort them | ||
175 | for game in tabelle: | 183 | for game in tabelle: |
176 | game["spieltag"] = solver.value(variables[game["id"]]) | 184 | game["spieltag"] = solver.value(variables[game["id"]]) |
177 | 185 | ||
178 | # tabelle.sort(key=lambda game: game["spieltag"]) | 186 | # tabelle.sort(key=lambda game: game["spieltag"]) |
179 | 187 | ||
180 | # PRINT OUT RESULTS AS TABLE | 188 | # PRINT OUT RESULTS AS TABLE |
189 | |||
190 | # helper table for quicker lookup of teams and orte by their id | ||
181 | all_teams = {team["id"]: team for team in data["teams"]} | 191 | all_teams = {team["id"]: team for team in data["teams"]} |
182 | all_teams[-1] = {"name": "*"} | 192 | all_teams[-1] = {"name": "*"} |
183 | all_orte = {ort["id"]: ort for ort in data["orte"]} | 193 | all_orte = {ort["id"]: ort for ort in data["orte"]} |