-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathteam-generator.html
392 lines (342 loc) · 12.4 KB
/
team-generator.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
---
layout: pageLayout
title: Team Generator
description: Make even teams by Gender, Attendance and Level
prefix_location: ../
permalink: team-generator
---
<link href="//fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<style>
@media only screen and (min-width: 993px) {
.card {
/*min-height: 200px ;*/
}
}
h1 img{
float: right;
}
.small{
font-size: 0.8rem;
}
.bigger{
font-size: 1.2rem;
}
.monospace{
font-family: monospace;
}
span.tooltipped{
/*text-decoration: underline;*/
border-bottom: 1px solid grey; /* Or whatever color you want */
text-decoration: none;
}
/* PACE */
/*--------------------------------------------------------------*/
.pace { -webkit-pointer-events: none; pointer-events: none; -webkit-user-select: none; -moz-user-select: none; user-select: none; z-index: 2000; position: fixed; height: 60px; width: 100px; margin: auto; top: 0; left: 0; right: 0; bottom: 0; }
.pace-running #wholebody { opacity:0; }
.pace-done #wholebody { opacity:1; }
.pace-inactive { display: none; }
.pace .pace-activity {
content: "loading";
opacity:1;
border-bottom: 6px solid #000;
border-left: 6px solid rgba(0, 0, 0, 0);
border-right: 6px solid rgba(0, 0, 0, 0);
border-top: 6px solid #000;
-moz-border-radius: 100%;
-webkit-border-radius: 100%; border-radius: 100%; height: 70px; width: 70px; animation: rot 0.6s infinite linear; -webkit-animation: rot 0.6s infinite linear;}
/*text*/
.pace:before {
/*content: 'Loading';*/
font-size: 2em;
display: inline-block;
text-align: center;
position: absolute;
width: 100vw;
margin-left: calc(-50vw + 50px);
margin-top: -100px;
padding-right:35px;
}
.pace:after {
/*content: 'Generating...';*/
font-size: 1.5em;
color:#666;
display: inline-block;
text-align: center;
/*background-color: yellow;*/
position: absolute;
width: 100vw;
margin-left: calc(-50vw + 50px);
margin-top: 50px;
padding-right:35px;
}
/*animation*/
@-webkit-keyframes rot { from { -webkit-transform: rotate(0deg); transform: rotate(0deg) } to { -webkit-transform: rotate(359deg); transform: rotate(359deg) } }
@-moz-keyframes rot { from { -moz-transform: rotate(0deg); transform: rotate(0deg) } to { -moz-transform: rotate(359deg); transform: rotate(359deg) } }
@keyframes rot { from { transform: rotate(0deg); } to { transform: rotate(359deg); } }
/* restore ndashes in lists */
ul.dashed {
padding-left: 16px;
}
ul.dashed li {
margin-left: 15px;
}
ul.dashed li::before {
margin-left: -15px;
content: "– ";
}
</style>
<!--/build-->
</head>
<body id="top" class="scrollspy">
<div class="container">
<h1>Zapadisk Team Generator <small class="grey-text text-darken-1">v2.0</small></h1>
<section id="inputSection">
<h4>List of Players</h4>
<!--<div class="row">-->
<!--<div class="col s7">-->
<p>
Copy here-under your players list in tabular format (spreadsheet)
<br>Columns to be respected:
<br><span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="Any text identifying players">Name</span> |
<span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="Any number evaluating the player skills">Level</span> |
<span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="'F' or 'M'">Gender</span> |
<span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="A number from 0 to 1 indicating the presence of the player on day1">Attendance day1</span> |
<span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="A number from 0 to 1 indicating the presence of the player on day2"><Attendance day2></span> |
<span class="tooltipped monospace" data-position="bottom" data-delay="50" data-tooltip="You can have have as many days as you want"><...></...></span>
</p>
<!--</div>-->
<!--<div class="col s5">-->
<p>
<a class="waves-effect waves-light btn blue-grey" onclick="fillRandom()">Generate Random Players to Test</a>
<!--<a class="waves-effect waves-light btn blue-grey" onclick="fillBuoc()">BUOC</a>-->
</p>
<!--</div>-->
<!--</div>-->
<form class="row paddingTop20" id="playersListForm">
<div class="col s9">
<!--<a class="waves-effect waves-light btn">button</a>-->
<div class="row">
<div class="input-field col s12">
<i class="material-icons prefix">list</i>
<textarea id="textarea1" class="materialize-textarea"></textarea>
<label for="textarea1">Players List (copy/paste from spreadsheet)</label>
</div>
</div>
</div>
<div class="col s3">
<button id="submitButton" class="btn waves-effect waves-light" type="button" name="action">Run
<i class="material-icons right">send</i>
</button>
<h5>Options</h5> <br>
<!--<p class="range-field">
Runs:
<input type="range" id="nruns" min="20" max="500" >
</p>-->
<!--<p class="range-field">
Teams:
<input type="number" id="nteams" min="2" max="10" >
</p>-->
<div class="input-field">
<input value="50" id="nruns" type="text" class="validat" min="1" max="1000">
<label for="nruns">Runs:</label>
</div>
<div class="input-field">
<input value="2" id="nteams" type="text" class="validat" min="2" max="10">
<label for="nteams">Teams:</label>
</div>
<div class="input-field">
<input value="[3, 3, 3, 1]" id="weights" type="text" class="validat">
<label for="weights">Weights:</label>
</div>
</div>
</form>
<div class="paddingTop20">
<h5 class="paddingTop20">What does it do?</h5>
<p>
This tool will split a list of players into the most even teams possible.
<br>This means: having
</p>
<ul class="dashed">
<li>the same number of players each day,</li>
<li>the same number of women and men,</li>
<li>the same mean level of players,</li>
<li>the same number of women and men playing each day.</li>
</ul>
</div>
<div>
<h5 class="paddingTop20">How to use it?</h5>
<div class="row">
<div class="col m7">
<p>
Make a list of your players in an spreadsheet (MS Excel, Google Spreadsheet, LibreOffice…). <br>One line per player, and columns in this order:
</p>
<ol>
<li>The name of the player (any text, <i>e.g.</i> First name, Last name)</li>
<li>The level of the player (any number)</li>
<li>The gender of the player (F or M)</li>
<li>The attendance of the player on day 1 (0–1) <br>(0=not present ; 1=present ; anything between can a percetage or a probability of being present)</li>
<li>The attendance of the player on day 2 (idem)</li>
<li>The attendance of the player on day …</li>
</ol>
<p>
Then copy-paste this in the text area above, without headers.
<br>And then select options:
</p>
<ul class="dashed">
<li>Runs: tests with ~20, recommended >~500 (requires more processor)</li>
<li>Teams: how many teams to you want to generate</li>
<li>Weights: this is the importance accorded to the 4 criteria [attendance, gender, level, gender per day], you can leave defaults.</li>
</ul>
<p>And press "RUN"</p>
</div>
<div class="col m5">
<p><i>e.g.</i></p>
<table class="highlight">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Gender</th>
<th>Day1</th>
<th>Day2</th>
</tr>
</thead>
<tbody>
<tr>
<td>Naëlle Martin</td>
<td>2</td>
<td>F</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>Pablo Jacobs</td>
<td>4</td>
<td>M</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>Céleste Renard</td>
<td>2</td>
<td>M</td>
<td>0</td>
<td>1</td>
</tr>
<tr>
<td>Charlie Lambert</td>
<td>8</td>
<td>F</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>Candice Derauw</td>
<td>10</td>
<td>F</td>
<td>1</td>
<td>1</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div>
<h5 class="paddingTop20">How does it work?</h5>
<ol>
<li>Shuffle the initial players list.</li>
<li>Split the list in even teams.</li>
<li>Compute how different these teams are in one index number.</li>
<li>Make a random swap between 2 players of 2 different teams.</li>
<li>If this swap reduces the difference between the teams then keep it, otherwise revert it.</li>
<li>Do this until nothing improves for a long time.</li>
<!--<li></li>-->
</ol>
<p>
→We reached a local optimum
<br>Do this multiple times (runs) to find several global optimums and local optimums.
<br>And finally do this again until we reach the best local optimum we found so far.
</p>
</div>
<div>
<h5 class="paddingTop20">Tips</h5>
<ul class="dashed">
<li>If you want to generate a strong team and a weak team, instead of mixing levels, you can write a negative number for the 3<sup>rd</sup> weight (<i>e.g.</i> [3, 3, -3, 1])</i></sup></li>
<li>It's possible to force 2 players to be togheter or apart by changing attendance values. (<i>e.g.</i> -1000 and 1000 will force these 2 players to be togheter. 1000 and 1000 will force them to be separate</li>
</ul>
</div>
<!--<div>
<h5 class="paddingTop20>Upcoming changes</h5>
<ul class="dashed">
<li>Allow to change the number of teams (currently fixed to 2)</li>
</ul>
</div>-->
<div>
<h5 class="paddingTop20">Questions & Feedback</h5>
<p class="monospace-font ">
<!--http://robspangler.com/blog/encrypt-mailto-links-to-stop-email-spam/-->
<a href="mailto:mathias@zapadisk.be">Mathias Leroy</a>
</p>
</div>
</section>
<section class="row" id="outputSection">
<div class="col m6">
<h4>List of Players</h4>
<h5>Summary</h5>
<div id="playersSummary">
<!-- filled by JS -->
</div>
<h5>Details</h5>
<table id="table1" class="highlight responsive-tabl">
<thead>
<tr>
<th>Name</th>
<th>Level</th>
<th>Gender</th>
<th>Attendance</th>
</tr>
</thead>
<tbody id="playersRows">
<!-- filled by JS -->
</tbody>
</table>
</div>
<div class="col m6">
<h4>Generated Teams
<!--<div class="col m12 paddingTop20">-->
<button id="resetButton" class="btn waves-effect waves-light" type="button" name="action" onclick="reset();">Reset
<i class="material-icons right">refresh</i>
</button>
<!--</div>-->
</h4>
<div id="teamsDetails">
<!-- filled by JS -->
</div>
<h4>Team Differences</h4>
<h5></h5>
<div id="teamsSummary">
<!-- filled by JS -->
</div>
<div id="multipleRunsSummary">
<!-- filled by JS -->
</div>
</div>
</section>
</div> <!-- /.container -->
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"></script>-->
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/materialize/0.99.0/js/materialize.min.js"></script>
<!--<script src="//cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0-alpha.3/js/materialize.min.js"></script>-->
<script src="//cdnjs.cloudflare.com/ajax/libs/PapaParse/4.3.6/papaparse.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/pace/1.0.2/pace.min.js"></script>
<!--<script src="assets/js/jquery.hypher.min.js"></script>-->
<!--<script src="assets/js/en-us.js"></script>-->
<!--<script src="assets/js/fr.js"></script>-->
<script src="assets/js/tg.js"></script>
<!--
accept >2 teams
test nb de combinaisons avec des petites équipes
optional: combinations estimation >2 teams
optional: capture recapture -> estimer le nb total de possibilités si > 2teams
-->