TheXeos commited on
Commit
0643cfc
·
1 Parent(s): 91e9556

Initial commit

Browse files
Files changed (2) hide show
  1. Dockerfile +9 -0
  2. main.py +137 -0
Dockerfile ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ FROM python:3.9
2
+
3
+ COPY requirements.txt .
4
+
5
+ RUN pip install --no-cache-dir --upgrade -r requirements.txt
6
+
7
+ COPY . .
8
+
9
+ CMD ["python main.py"]
main.py ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import random
2
+ import pandas as pd
3
+ from datetime import datetime
4
+
5
+
6
+ class Model:
7
+ """
8
+ Class containing the info of a model.
9
+
10
+ :param name: Name of the model
11
+ :param elo: Elo rating of the model
12
+ :param games_played: Number of games played by the model (useful if we implement sigma uncertainty)
13
+ """
14
+ def __init__(self, name, elo=1200, games_played=0):
15
+ self.name = name
16
+ self.elo = elo
17
+ self.games_played = games_played
18
+
19
+
20
+ class Matchmaking:
21
+ """
22
+ Class managing the matchmaking between the models.
23
+
24
+ :param models: List of models
25
+ :param queue: Temporary list of models used for the matching process
26
+ :param k: Dev coefficient
27
+ :param max_diff: Maximum difference considered between two models' elo
28
+ :param matches: Dictionary containing the match history (to later upload as CSV)
29
+ """
30
+ def __init__(self, models):
31
+ self.models = models
32
+ self.queue = self.models.copy()
33
+ self.k = 20
34
+ self.max_diff = 500
35
+ self.matches = {
36
+ "model1": [],
37
+ "model2": [],
38
+ "result": [],
39
+ "datetime": []
40
+ }
41
+
42
+ def run(self):
43
+ """
44
+ Run the matchmaking process.
45
+ Add models to the queue, shuffle it, and match the models one by one to models with close ratings.
46
+ Compute the new elo for each model after each match and add the match to the match history.
47
+ """
48
+ for i in range(10):
49
+ self.queue = self.models.copy()
50
+ random.shuffle(self.queue)
51
+ while len(self.queue) > 1:
52
+ model1 = self.queue.pop(0)
53
+ model2 = self.queue.pop(self.find_n_closest_indexes(model1, 10))
54
+ result = match(model1, model2)
55
+ self.compute_elo(model1, model2, result)
56
+ self.matches["model1"].append(model1.name)
57
+ self.matches["model2"].append(model2.name)
58
+ self.matches["result"].append(result)
59
+ self.matches["datetime"].append(datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f"))
60
+
61
+ def compute_elo(self, model1, model2, result):
62
+ """ Compute the new elo for each model based on a match result. """
63
+ delta = model1.elo - model2.elo
64
+ win_probability = 1 / (1 + 10 ** (-delta / 500))
65
+ model1.elo += self.k * (result - win_probability)
66
+ model2.elo -= self.k * (result - win_probability)
67
+
68
+ def find_n_closest_indexes(self, model, n) -> int:
69
+ """
70
+ Get a model index with a fairly close rating. If no model is found, return the last model in the queue.
71
+ We don't always pick the closest rating to add variety to the matchups.
72
+
73
+ :param model: Model to compare
74
+ :param n: Number of close models from which to pick a candidate
75
+ :return: id of the chosen candidate
76
+ """
77
+ indexes = []
78
+ closest_diffs = [9999999] * n
79
+ for i, m in enumerate(self.queue):
80
+ if m.name == model.name:
81
+ continue
82
+ diff = abs(m.elo - model.elo)
83
+ if diff < max(closest_diffs):
84
+ closest_diffs.append(diff)
85
+ closest_diffs.sort()
86
+ closest_diffs.pop()
87
+ indexes.append(i)
88
+ random.shuffle(indexes)
89
+ return indexes[0]
90
+
91
+ def to_csv(self):
92
+ """ Save the match history as a CSV file to the hub. """
93
+ df = pd.DataFrame(columns=['name', 'elo'])
94
+ for model in self.models:
95
+ df = pd.concat([df, pd.DataFrame([[model.name, model.elo]], columns=['name', 'elo'])])
96
+ df.to_csv('elo.csv', index=False)
97
+ df_matches = pd.DataFrame(self.matches)
98
+ df_matches.to_csv(f"matches/{datetime.now().strftime('%Y-%m-%d_%H-%M-%S_%f')}.csv", index=False)
99
+
100
+
101
+ def match(model1, model2) -> float:
102
+ """
103
+ !!! Current code is placeholder !!!
104
+ TODO: Launch a Unity process with the 2 models and get the result of the match
105
+
106
+ :param model1: First Model object
107
+ :param model2: Second Model object
108
+ :return: match result (0: model1 lost, 0.5: draw, 1: model1 won)
109
+ """
110
+ result = random.randint(0, 2) / 2
111
+ return result
112
+
113
+
114
+ def get_models_list() -> list:
115
+ """
116
+ !!! Current code is placeholder !!!
117
+ TODO: Create a list of Model objects from the models found on the hub
118
+
119
+ :return: list of Model objects
120
+ """
121
+ models = []
122
+ data = pd.read_csv("example.csv")
123
+ for i, row in data.iterrows():
124
+ models.append(Model(row["name"], row["elo"]))
125
+ return models
126
+
127
+
128
+ def init_matchmaking():
129
+ models = get_models_list()
130
+ matchmaking = Matchmaking(models)
131
+ matchmaking.run()
132
+ matchmaking.to_csv()
133
+
134
+
135
+ if __name__ == "__main__":
136
+ print("It's running!")
137
+ # init_matchmaking()