--- /dev/null
+from __future__ import print_function
+import sys
+from ortools.constraint_solver import pywrapcp
+
+def print_solution(sol):
+ for i in range(num_matches):
+ home_team = collector.Value(sol, home_teams[i])
+ away_team = collector.Value(sol, away_teams[i])
+ matchnum = collector.Value(sol, matchnums[i])
+ #print("%2d. %d vs. %d (matchnum %d)" % (i, home_team, away_team, matchnum))
+ print("%2d. %d vs. %d (matchnum %2d, excitedness %d)" % (i, home_team, away_team, matchnum, excitedness[matchnum]))
+
+# Creates the solver.
+solver = pywrapcp.Solver("schedule_shifts")
+
+num_teams = 6
+num_matches = (num_teams * (num_teams - 1)) // 2
+
+# Create supermatch variables.
+matchnums = []
+for match_idx in range(num_matches):
+ matchnums.append(solver.IntVar(0, num_matches - 1, "matchnum(%i)" % (match_idx)))
+solver.Add(solver.AllDifferent(matchnums));
+
+# Create list of matches.
+match_num = 0
+excitedness = []
+home_teams_for_match_num = []
+away_teams_for_match_num = []
+for team_idx_1 in range(num_teams):
+ for team_idx_2 in range(num_teams):
+ if team_idx_2 > team_idx_1:
+ home_teams_for_match_num.append(team_idx_1)
+ away_teams_for_match_num.append(team_idx_2)
+ if team_idx_2 - team_idx_1 == 1:
+ excitedness.append(5)
+ elif team_idx_2 - team_idx_1 == 2:
+ excitedness.append(2)
+ else:
+ excitedness.append(0)
+ print("matchnum ", match_num , " plays: ", team_idx_1, " - ", team_idx_2, " excited: " , excitedness[match_num])
+ match_num = match_num + 1
+
+# Create match variables.
+home_teams = []
+away_teams = []
+for match_idx in range(num_matches):
+ home_teams.append(solver.IntVar(0, num_teams - 1, "home_team_on_match(%i)" % (match_idx)))
+ away_teams.append(solver.IntVar(0, num_teams - 1, "away_team_on_match(%i)" % (match_idx)))
+matches_flat = home_teams + away_teams
+
+for match_num in range(num_matches):
+ # home_teams_var[i] = home_teams[match_num_var[i]]
+ #solver.Add(matchnums[match_num].IndexOf(home_teams) == team_idx_1) # home_teams[matchnums[match_num]] == team_idx_1
+ #solver.Add(matchnums[match_num].IndexOf(away_teams) == team_idx_2)
+ solver.Add(home_teams[match_num] == solver.Element(home_teams_for_match_num, matchnums[match_num]))
+ solver.Add(away_teams[match_num] == solver.Element(away_teams_for_match_num, matchnums[match_num]))
+
+## A team can never play two matches in a row
+for match_idx in range(num_matches - 1):
+ solver.Add(home_teams[match_idx] != home_teams[match_idx + 1])
+ solver.Add(away_teams[match_idx] != home_teams[match_idx + 1])
+ solver.Add(home_teams[match_idx] != away_teams[match_idx + 1])
+ solver.Add(away_teams[match_idx] != away_teams[match_idx + 1])
+
+# More waiting time is good
+tired_matches = []
+for match_idx in range(num_matches - 2):
+ home_tired = (
+ (home_teams[match_idx] == home_teams[match_idx + 2]) +
+ (home_teams[match_idx] == away_teams[match_idx + 2]))
+ away_tired = (
+ (away_teams[match_idx] == home_teams[match_idx + 2]) +
+ (away_teams[match_idx] == away_teams[match_idx + 2]))
+ tired_matches.append(home_tired)
+ tired_matches.append(away_tired)
+
+ # double-tired is not cool
+ if match_idx < num_matches - 4:
+ home_doubletired = home_tired * (
+ (home_teams[match_idx] == home_teams[match_idx + 4]) +
+ (home_teams[match_idx] == away_teams[match_idx + 4]))
+ away_doubletired = away_tired * (
+ (away_teams[match_idx] == home_teams[match_idx + 4]) +
+ (away_teams[match_idx] == away_teams[match_idx + 4]))
+ tired_matches.append(home_doubletired * 100)
+ tired_matches.append(away_doubletired * 100)
+
+sum_tiredness = solver.Sum(tired_matches)
+
+## TFK can not play the first match
+solver.Add(home_teams[0] != 0)
+solver.Add(away_teams[0] != 0)
+solver.Add(home_teams[1] != 0)
+solver.Add(away_teams[1] != 0)
+
+# Group final comes last
+solver.Add(home_teams[num_matches - 1] == 0)
+solver.Add(away_teams[num_matches - 1] == 1)
+
+# Put the more excitedness last
+sum_excitedness = solver.Sum([(matchnums[match_num].IndexOf(excitedness) * match_num) for match_num in range(num_matches)])
+objective = solver.Maximize(sum_excitedness - 10 * sum_tiredness, 1)
+
+# TODO: AllowedAssignments
+# TODO: multiple fields/groups, objectives of getting TV time (esp. for interesting matches)
+# TODO: objective on getting more interesting matches last
+
+db = solver.Phase(matchnums, solver.CHOOSE_FIRST_UNBOUND,
+ solver.ASSIGN_MIN_VALUE)
+search_log = solver.SearchLog(1000000, objective)
+#global_limit = solver.TimeLimit(1000)
+global_limit = solver.TimeLimit(100000000)
+
+## Create the solution collector.
+#solution = solver.Assignment()
+#solution.Add(matches_flat)
+#solution.Add(matchnums)
+#
+##collector = solver.AllSolutionCollector(solution)
+##collector = solver.LastSolutionCollector(solution)
+#collector = solver.FirstSolutionCollector(solution)
+#
+#solver.Solve(db, [collector, search_log, objective, global_limit])
+#print("Solutions found:", collector.SolutionCount())
+#print("Time:", solver.WallTime(), "ms")
+#print()
+## Display a few solutions picked at random.
+#a_few_solutions = [0]
+#for sol in a_few_solutions:
+# print_solution(sol)
+#
+#os.exit(0)
+
+###All
+solver.NewSearch(db, [search_log, objective, global_limit])
+num_solutions = 0
+while solver.NextSolution():
+ #print("objective = ", sum_excitedness.Value())
+ for i in range(num_matches):
+ home_team = home_teams[i].Value()
+ away_team = away_teams[i].Value()
+ matchnum = matchnums[i].Value()
+
+ tiredness = 0
+ if i >= 2:
+ if home_team == home_teams[i - 2].Value():
+ tiredness = tiredness + 1
+ if home_team == away_teams[i - 2].Value():
+ tiredness = tiredness + 1
+ if away_team == home_teams[i - 2].Value():
+ tiredness = tiredness + 1
+ if away_team == away_teams[i - 2].Value():
+ tiredness = tiredness + 1
+
+ print("%2d. %d vs. %d (matchnum %2d, excitedness %d, tiredness %d)" % (i, home_team, away_team, matchnum, excitedness[matchnum], tiredness))
+
+ print()
+ num_solutions += 1
+solver.EndSearch()