Skip to content

Instantly share code, notes, and snippets.

@icefo
Last active April 16, 2017 08:49
Show Gist options
  • Save icefo/ac86e563ed4e69a26b1c89290825128e to your computer and use it in GitHub Desktop.
Save icefo/ac86e563ed4e69a26b1c89290825128e to your computer and use it in GitHub Desktop.
from datetime import datetime, timedelta
import random
from collections import OrderedDict, Counter
from pprint import pprint
from os import urandom
import os
from itertools import tee, islice, chain
class StudentClass:
def __init__(self, grade, class_section, class_id, spectacle_group):
self.grade = grade # 1,2,3,4
self.class_section = class_section # Classiques, Socios, Scientos
self.id = class_id # A,B,C,D...
self.spectacle_group = spectacle_group # 1/2/3
if spectacle_group == 1:
self.time_slots = [ # start time (datetime object), end time (datetime object), activity, place
[datetime(2017, 4, 12, 8, 30), datetime(2017, 4, 12, 9, 0), 'Jeu', ''],
[datetime(2017, 4, 12, 9, 0), datetime(2017, 4, 12, 9, 5), 'Pause', ''],
[datetime(2017, 4, 12, 9, 5), datetime(2017, 4, 12, 9, 35), 'Jeu', ''],
[datetime(2017, 4, 12, 9, 35), datetime(2017, 4, 12, 9, 40), 'Pause', ''],
[datetime(2017, 4, 12, 9, 40), datetime(2017, 4, 12, 10, 10), 'Jeu', ''],
[datetime(2017, 4, 12, 10, 10), datetime(2017, 4, 12, 10, 50), 'Pause', ''],
[datetime(2017, 4, 12, 10, 50), datetime(2017, 4, 12, 11, 50), 'Spectacle', 'Aula'],
]
elif spectacle_group == 2:
self.time_slots = [ # start time (datetime object), end time (datetime object), activity, place
[datetime(2017, 4, 12, 8, 30), datetime(2017, 4, 12, 9, 0), 'Jeu', ''],
[datetime(2017, 4, 12, 9, 0), datetime(2017, 4, 12, 9, 5), 'Pause', ''],
[datetime(2017, 4, 12, 9, 5), datetime(2017, 4, 12, 9, 35), 'Jeu', ''],
[datetime(2017, 4, 12, 9, 35), datetime(2017, 4, 12, 9, 40), 'Pause', ''],
[datetime(2017, 4, 12, 9, 40), datetime(2017, 4, 12, 10, 40), 'Spectacle', 'Aula'],
[datetime(2017, 4, 12, 10, 40), datetime(2017, 4, 12, 10, 55), 'Pause', ''],
[datetime(2017, 4, 12, 10, 55), datetime(2017, 4, 12, 11, 25), 'Jeu', ''],
]
elif spectacle_group == 3:
self.time_slots = [ # start time (datetime object), end time (datetime object), activity, place
[datetime(2017, 4, 12, 8, 30), datetime(2017, 4, 12, 9, 30), 'Spectacle', 'Aula'],
[datetime(2017, 4, 12, 9, 30), datetime(2017, 4, 12, 9, 40), 'Pause', ''],
[datetime(2017, 4, 12, 9, 40), datetime(2017, 4, 12, 10, 10), 'Jeu', ''],
[datetime(2017, 4, 12, 10, 10), datetime(2017, 4, 12, 10, 15), 'Pause', ''],
[datetime(2017, 4, 12, 10, 15), datetime(2017, 4, 12, 10, 45), 'Jeu', ''],
[datetime(2017, 4, 12, 10, 45), datetime(2017, 4, 12, 10, 55), 'Pause', ''],
[datetime(2017, 4, 12, 10, 55), datetime(2017, 4, 12, 11, 25), 'Jeu', ''],
]
# c'est vraiment important faire en sorte que les différents groupes jouent aux jeux en même temps afin de remplire les
# salles au maximum afin d'en utiliser moins. On peut utiliser des temps de pause variable pour y arriver comme ici.
def previous_and_next(some_iterable):
# stakeoverflow blackmagic
prevs, items, nexts = tee(some_iterable, 3)
prevs = chain([None], prevs)
nexts = chain(islice(nexts, 1, None), [None])
return zip(prevs, items, nexts)
previous_used_room_count = 70
previous_bad_points = 100
previous_max_min_difference = 30
while True:
seed = urandom(50)
# permet de rejouer une programmation qui est bien. Sinon c'est le hasard qui choisit.
# seed = b"'>\x15e\x7f\r\xdb\x03\xb4/\x0cZ\xf2\xed\xb0\xaa\xbc\x88\xa4W\xc8\xe7[\x0cM\xc5\xc1}\x85\x89\x05\x8a\xd6\xd9\xc4\x0f\x87\xa25\x11\xa4Y\x15\xae?\x11n\xd6\xc5\xa3"
random.seed(seed)
# classer les premières en fonction du nombre d'élèves des autres sections pour que ce soit plus moins équitable
class_list = [
StudentClass(1, 'Socios', 'G', 2),
StudentClass(1, 'Socios', 'H', 2),
StudentClass(1, 'Socios', 'I', 2),
StudentClass(1, 'Socios', 'J', 2),
StudentClass(1, 'Socios', 'K', 2),
StudentClass(1, 'Socios', 'L', 2),
StudentClass(1, 'Scientos', 'A', 2),
StudentClass(1, 'Scientos', 'B', 2),
StudentClass(1, 'Scientos', 'C', 2),
StudentClass(1, 'Scientos', 'D', 2),
StudentClass(1, 'Scientos', 'E', 2),
StudentClass(1, 'Scientos', 'F', 2),
StudentClass(2, 'Classiques', 'A', 1),
StudentClass(2, 'Classiques', 'B', 1),
StudentClass(2, 'Classiques', 'I', 2),
StudentClass(2, 'Classiques', 'J', 2),
StudentClass(2, 'Classiques', 'K', 2),
StudentClass(2, 'Socios', 'F', 1),
StudentClass(2, 'Socios', 'G', 1),
StudentClass(2, 'Socios', 'H', 1),
StudentClass(2, 'Scientos', 'C', 1),
StudentClass(2, 'Scientos', 'D', 1),
StudentClass(2, 'Scientos', 'E', 1),
StudentClass(3, 'Classiques', 'A', 1),
StudentClass(3, 'Classiques', 'H', 1),
StudentClass(3, 'Classiques', 'I', 3),
StudentClass(3, 'Classiques', 'J', 3),
StudentClass(3, 'Classiques', 'K', 3),
StudentClass(3, 'Socios', 'E', 3),
StudentClass(3, 'Socios', 'F', 3),
StudentClass(3, 'Socios', 'G', 1),
StudentClass(3, 'Scientos', 'B', 1),
StudentClass(3, 'Scientos', 'C', 1),
StudentClass(3, 'Scientos', 'D', 1),
StudentClass(4, 'Classiques', 'A', 3),
StudentClass(4, 'Classiques', 'G', 3),
StudentClass(4, 'Classiques', 'H', 3),
StudentClass(4, 'Classiques', 'I', 3),
StudentClass(4, 'Classiques', 'J', 3),
StudentClass(4, 'Socios', 'E', 3),
StudentClass(4, 'Socios', 'F', 3),
StudentClass(4, 'Scientos', 'B', 3),
StudentClass(4, 'Scientos', 'C', 3),
StudentClass(4, 'Scientos', 'D', 3),
]
number_of_classes = len(class_list)
game_list = [
# Name of the game, Can be played by multiples classes at the same time, list of the classes that are playing
['Les énigmes du père Fouras', True, []],
['Le Manoir', False, [], 'Lieu du Manoir'],
['Black out', False, [], 'Lieu du Black out'],
['Articule', True, []],
['Mime à la chaine', True, []],
['Boulet et la planche', False, [], 'Lieu Boulet et la planche'],
['Parcours du combattant', False, [], 'Parcours du combattant'],
['Les Noeuds', True, []], # Make sure that the section that follows is not the same
['Salle des illusions', True, []],
["Toile d'araignée", False, [], "Lieu toile d'araignée"],
['Infrarouge', False, [], 'Lieu Infrarouge'],
['Grimpe Infernale', False, [], 'Salle de sport 2']
]
number_of_games = len(game_list)
# Vérifier que ces salles sont vraiment utilisables et qu'elles existent
place_dict = OrderedDict()
# nom, nom, list_of_classes
for i in range(114, 125):
place_dict[str(i)] = [i, []]
del place_dict['116']
for i in range(214, 225):
place_dict[str(i)] = [i, []]
del place_dict['216']
for i in range(314, 325):
place_dict[str(i)] = [i, []]
del place_dict['316']
class_id_list = list(range(number_of_classes))
counter = 0
while len(class_id_list) > 0:
random_id_index = random.randrange(0, len(class_id_list))
one_class = class_list[class_id_list[random_id_index]]
games_played_by_the_class = []
for time_slot in one_class.time_slots:
if time_slot[2] != 'Spectacle' and time_slot[2] != 'Pause' and time_slot[3] != '':
games_played_by_the_class.append(time_slot[2])
for time_slot in one_class.time_slots:
if time_slot[2] != 'Spectacle' and time_slot[2] != 'Pause' and time_slot[3] == '': # check if time slot is empty
game_id = random.randrange(0, number_of_games)
game = game_list[game_id]
if game[0] not in games_played_by_the_class:
if game[1] is False:
ok = True
temp_section_list = []
for la_class in game[2]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_section_list.append(la_class.class_section)
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
temp_section_counter = Counter(temp_section_list) # see python doc for explanation
if temp_section_counter[one_class.class_section] == 2 or \
(temp_section_counter[one_class.class_section] == 1 and temp_section_counter.most_common()[0][1] == 2):
ok = False
if game[0] == 'Grimpe Infernale' and ok and one_class.grade < 3:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = game[3]
games_played_by_the_class.append(game[0])
game[2].append(one_class)
try:
place_dict[game[3]][1].append(one_class)
except KeyError:
place_dict[game[3]] = [game[0], [one_class]]
else:
ok = False
for room_id, room_infos in place_dict.items():
# try to fill rooms first, if not possible switch to less than ideal scenario
if counter <= 1000:
if game[0] == room_infos[0] and len(room_infos[1]) < 4:
ok = True
temp_list=[]
for la_class in room_infos[1]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_list.append((la_class.class_section, a[0], a[1]))
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
if game[0] == 'Les Noeuds' and ok:
temp_list.append((one_class.class_section, time_slot[0], time_slot[1]))
temp_list.sort(key=lambda get_start_time: get_start_time[1])
counter_1 = 0
for previous, item, next_item in previous_and_next(temp_list):
if previous is not None and previous[0] == item[0]:
ok = False
if next_item is not None and next_item[0] == item[0]:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
break
elif game[0] == room_infos[0] and len(room_infos[1]) == 4:
ok = False
add_room = True
for room_id_1, room_infos_1 in place_dict.items():
if game[0] == room_infos_1[0] and len(room_infos_1[1]) < 4:
add_room = False
break
if add_room:
for room_id_1, room_infos_1 in place_dict.items():
if isinstance(room_infos_1[0], int):
time_slot[2] = game[0]
time_slot[3] = room_id_1
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id_1][0] = game[0]
place_dict[room_id_1][1].append(one_class)
ok = True
break
elif isinstance(room_infos[0], int) and \
game[0] not in frozenset((value[0] for value in place_dict.values())):
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
ok = True
elif 1000 < counter <= 2000:
if game[0] == room_infos[0] and len(room_infos[1]) < 4:
ok = True
temp_list=[]
for la_class in room_infos[1]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_list.append((la_class.class_section, a[0], a[1]))
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
if game[0] == 'Les Noeuds' and ok:
temp_list.append((one_class.class_section, time_slot[0], time_slot[1]))
temp_list.sort(key=lambda get_start_time: get_start_time[1])
counter_1 = 0
for previous, item, next_item in previous_and_next(temp_list):
if previous is not None and previous[0] == item[0]:
ok = False
if next_item is not None and next_item[0] == item[0]:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
place_dict[room_id][2] = None
break
elif game[0] == room_infos[0] and len(room_infos[1]) == 4:
ok = False
add_room = True
for room_id_1, room_infos_1 in place_dict.items():
if game[0] == room_infos_1[0] and len(room_infos_1[1]) < 4:
add_room = False
break
if add_room:
for room_id_1, room_infos_1 in place_dict.items():
if isinstance(room_infos_1[0], int):
time_slot[2] = game[0]
time_slot[3] = room_id_1
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id_1][0] = game[0]
place_dict[room_id_1][1].append(one_class)
ok = True
break
elif 2000 < counter <= 3000:
if game[0] == room_infos[0] and len(room_infos[1]) < 3:
ok = True
temp_list = []
for la_class in room_infos[1]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_list.append((la_class.class_section, a[0], a[1]))
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
if game[0] == 'Les Noeuds' and ok:
temp_list.append((one_class.class_section, time_slot[0], time_slot[1]))
temp_list.sort(key=lambda get_start_time: get_start_time[1])
counter_1 = 0
for previous, item, next_item in previous_and_next(temp_list):
if previous is not None and previous[0] == item[0]:
ok = False
if next_item is not None and next_item[0] == item[0]:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
break
elif game[0] == room_infos[0] and len(room_infos[1]) >= 3:
ok = False
add_room = True
for room_id_1, room_infos_1 in place_dict.items():
if game[0] == room_infos_1[0] and len(room_infos_1[1]) < 3:
add_room = False
break
if add_room:
for room_id_1, room_infos_1 in place_dict.items():
if isinstance(room_infos_1[0], int):
time_slot[2] = game[0]
time_slot[3] = room_id_1
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id_1][0] = game[0]
place_dict[room_id_1][1].append(one_class)
ok = True
break
elif 3000 < counter <= 4000:
if game[0] == room_infos[0] and len(room_infos[1]) < 3:
ok = True
temp_list = []
for la_class in room_infos[1]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_list.append((la_class.class_section, a[0], a[1]))
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
if game[0] == 'Les Noeuds' and ok:
temp_list.append((one_class.class_section, time_slot[0], time_slot[1]))
temp_list.sort(key=lambda get_start_time: get_start_time[1])
counter_1 = 0
for previous, item, next_item in previous_and_next(temp_list):
if previous is not None and previous[0] == item[0]:
ok = False
if next_item is not None and next_item[0] == item[0]:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
place_dict[room_id][2] = None
break
elif game[0] == room_infos[0] and len(room_infos[1]) >= 3:
ok = False
add_room = True
for room_id_1, room_infos_1 in place_dict.items():
if game[0] == room_infos_1[0] and len(room_infos_1[1]) < 3:
add_room = False
break
if add_room:
for room_id_1, room_infos_1 in place_dict.items():
if isinstance(room_infos_1[0], int):
time_slot[2] = game[0]
time_slot[3] = room_id_1
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id_1][0] = game[0]
place_dict[room_id_1][1].append(one_class)
ok = True
break
elif counter > 4000:
if game[0] == room_infos[0] and len(room_infos[1]) < 2:
ok = True
temp_list = []
for la_class in room_infos[1]:
for a in la_class.time_slots:
if a[2] == game[0]:
temp_list.append((la_class.class_section, a[0], a[1]))
if a[0] <= time_slot[0] <= a[1] or a[0] <= time_slot[1] <= a[1]:
ok = False
if game[0] == 'Les Noeuds' and ok:
temp_list.append((one_class.class_section, time_slot[0], time_slot[1]))
temp_list.sort(key=lambda get_start_time: get_start_time[1])
counter_1 = 0
for previous, item, next_item in previous_and_next(temp_list):
if previous is not None and previous[0] == item[0]:
ok = False
if next_item is not None and next_item[0] == item[0]:
ok = False
if ok:
time_slot[2] = game[0]
time_slot[3] = room_id
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id][0] = game[0]
place_dict[room_id][1].append(one_class)
place_dict[room_id][2] = None
break
elif game[0] == room_infos[0] and len(room_infos[1]) >= 2:
ok = False
add_room = True
for room_id_1, room_infos_1 in place_dict.items():
if game[0] == room_infos_1[0] and len(room_infos_1[1]) < 2:
add_room = False
break
if add_room:
for room_id_1, room_infos_1 in place_dict.items():
if isinstance(room_infos_1[0], int):
time_slot[2] = game[0]
time_slot[3] = room_id_1
games_played_by_the_class.append(game[0])
game[2].append(one_class)
place_dict[room_id_1][0] = game[0]
place_dict[room_id_1][1].append(one_class)
ok = True
break
if len(games_played_by_the_class) == 3:
del class_id_list[random_id_index]
# for classy in class_list:
# print()
# for time_slot in classy.time_slots:
# print(time_slot)
#
# pprint(place_dict)
# print(len(class_id_list))
counter = 0
counter += 1
#
# for game in game_list:
# print()
# for classy in game[2]:
# for time_slot in classy.time_slots:
# if time_slot[2] == game[0]:
# print(time_slot, classy.grade, classy.class_section, classy.id)
used_room_count = 0
bad_points = 0
game_dict_counter = {}
for place, classes in place_dict.items():
temp_list = []
for classy in classes[1]:
for time_slot in classy.time_slots:
if time_slot[3] == place:
temp_list.append(time_slot)
try:
game_dict_counter[time_slot[2]] += 1
except KeyError:
game_dict_counter[time_slot[2]] = 1
temp_list.sort(key=lambda hey: hey[0])
counter = 0
for item in temp_list:
# print(item)
# print(temp_list)
if counter:
if item[0] - temp_list[counter-1][1] > timedelta(minutes=10):
# print(place, item[0], temp_list[counter-1][1])
bad_points += 1
counter += 1
if classes[1]:
used_room_count += 1
played_game_counter = [game_dict_counter['Articule'], game_dict_counter['Les Noeuds'],
game_dict_counter['Les énigmes du père Fouras'], game_dict_counter['Mime à la chaine'],
game_dict_counter['Salle des illusions']]
max_min_difference = max(played_game_counter) - min(played_game_counter)
if used_room_count < previous_used_room_count: # and max_min_difference <= previous_max_min_difference:
# for classy in class_list:
# cal = Calendar()
# for time_slot in classy.time_slots:
# if len(time_slot[3]) == 2:
# time_slot[3] = '0' + time_slot[3]
# event = Event(name=time_slot[2], begin=time_slot[0],
# end=time_slot[1], location=time_slot[3])
# cal.events.append(event)
# with open(os.path.join('/home/adrien/Documents/ecole/jdm/calendar/classe',
# str(classy.grade) + str(classy.id) + ' ' + classy.class_section + '.ics'), 'w') as f:
# f.writelines(cal)
# for place, classes in place_dict.items():
# temp_list = []
# cal = Calendar()
# for classy in classes[1]:
# for time_slot in classy.time_slots:
# if time_slot[3] == place:
# temp_list.append((time_slot, classy.grade, classy.class_section, classy.id))
# temp_list.sort(key=lambda hey: hey[0][0])
# for a in temp_list:
# event = Event(name=str(a[1]) + str(a[3]) + ' ' + a[2] + ' ' + a[0][2],
# begin=a[0][0], end=a[0][1], location=a[0][3])
# cal.events.append(event)
# with open(os.path.join('/home/adrien/Documents/ecole/jdm/calendar/salle',
# str(place) + '.ics'), 'w') as f:
# f.writelines(cal)
for classy in class_list:
print('\n', classy.grade, classy.class_section, classy.id)
for time_slot in classy.time_slots:
time_slot[0] = time_slot[0].strftime('%H:%M')
time_slot[1] = time_slot[1].strftime('%H:%M')
if len(time_slot[3]) == 2:
time_slot[3] = '0' + time_slot[3]
print(time_slot)
for place, classes in place_dict.items():
print('\n', place)
temp_list = []
for classy in classes[1]:
for time_slot in classy.time_slots:
if time_slot[3] == place:
temp_list.append((time_slot, classy.grade, classy.class_section, classy.id))
temp_list.sort(key=lambda hey: hey[0][0])
for a in temp_list:
print(a)
print('classes utilisée', previous_used_room_count, used_room_count)
print('bad points', previous_bad_points, bad_points)
print('max min différence', previous_max_min_difference, max_min_difference)
pprint(game_dict_counter)
print(seed)
previous_used_room_count = used_room_count
previous_bad_points = bad_points
previous_max_min_difference = max_min_difference
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment