forked from rabernathy/TonderGame
-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.html
543 lines (464 loc) · 34 KB
/
index.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
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Tonder</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="game">
<div id="phone">
<div id="header">
<h1>tonder</h1>
<button id="info-button">i</button>
</div>
<div id="card-container">
<div class="card">
<div class="card-portrait">
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="357" viewBox="0 0 300.01532 334.77891" version="1"><path class="bg" fill="#fff" d="M0-1h301v336H0z"/><g class="hair_back" fill="red"><path d="M208 163c0 78-26 141-59 141-32 0-58-63-58-141 0-77 8-126 58-128 53-1 59 51 59 128z"/><path d="M62 184c-4 11-8 59-18 71 18 5 29-9 29-9s2 16-4 26c14 3 26-16 26-16 2 6 2 15-1 24 15-4 20-18 20-18-1 6 2 14 4 20l11-11c3 11 6 7 12 12l9-13 9 13c6-5 9-1 12-12l11 11c2-6 5-14 4-20 0 0 5 14 20 18-3-9-3-18-1-24 0 0 12 19 26 16-6-10-4-26-4-26s11 14 29 9c-11-12-13-61-17-72l-89-10z"/><path d="M100 33c-1 9 3 16 8 23 0 0-17-7-29-1-10 5-29 29-33 27 8 5 12 3 18 4 0 0-21 13-23 26-2 14-9 32-9 32 5-1 11-4 15-9 0 0-3 34 12 40 60 34 178 30 197-24 0-15-10-26-10-26 10 2 17 5 23 1 0 0-14-16-20-27-6-12-26-16-26-16 10-1 19-5 25-13 0 0-18-2-25-9s-17-11-27-10c-8 0-13 2-16 5 0-6-4-12-13-16-11-7-21 3-34 3-14 0-33-10-33-10z"/><path d="M272 231c-31-13-30-35-35-52l-88-77-88 77c-4 17-4 39-34 52 0 0 23 38 119 36 97 3 126-36 126-36z"/><path d="M61 191h-1c1 39-7 76-14 99l21 8 6-27 1 30c51 15 106 18 159 0l1-30 7 27c7-2 13-5 20-9-10-20-17-52-19-84 5-12-87-37-89-39s-93 18-92 25z"/><path d="M61 183s2 2 0 8c-1 5-14 7-20 19-4 10 10 12 6 21-3 11-12 5-15 17-2 11 10 11 9 18s-6 4-7 12c0 6 7 14 7 14 0-5 7-13 13-14 3 7 3 10-1 17 8 1 17-8 19-17-1 8 0 21 11 21-2-8 7-17 7-17s-4 15 9 19l50 5h1l50-5c13-4 9-19 9-19s9 9 7 17c11 0 12-13 11-21 2 9 11 18 19 17-4-7-4-10-1-17 7 1 13 9 13 14 0 0 8-8 7-14 0-8-5-5-6-12s10-7 8-18c-3-12-11-6-15-17-3-9 11-11 6-21-6-12-18-14-20-19-2-6 0-8 0-8l-88 10-89-10z"/><path d="M60 176s-23 68-9 107c15 42 47 52 47 52 58-14 38-13 101 0 0 0 34-10 50-52 14-39-10-107-10-107l-89-55c-1 3-90 55-90 55z"/><path d="M131 27a130 130 0 0 0-88 38h17L31 81l-6 9 18 2-24 14-3 9 17 7-20 10v16l8 4-8 9 1 14 11 4-7 11 3 11 11-2-5 12 6 10 12-5-3 15 8 7 10-6-1 13 6 3 9-7 1 13 9 3 8-6 5 11 10 3 6-8 4 11 7 1 4-7 12 9h12l21-2 4-10 7 8 8-2 2-11 9 7 6-2v-12l10 8 6-3 3-15 13 5 10-7-1-13 13 1 9-10-6-13 14-2 4-10-13-9 17-9 1-17-14-7 14-1v-13l-28-20 26 8-6-18-26-11 23 4a85 85 0 0 0-41-40c-33-15-55 4-55 4s-10-28-43-32h-8z"/><path d="M152 27c-8 0-16 4-21 11-5-4-10-6-16-6-12 0-23 8-26 21l-6-1c-13 0-24 11-24 25l1 4c-14 1-24 13-24 28 0 6 1 12 5 17-6 5-9 12-9 20 0 13 10 24 22 24 20-41 173-51 185 11 5 0 10-4 10-10 9-2 15-11 15-21l-2-10c3-3 5-8 5-14s-3-12-8-16l1-7c0-12-8-22-19-22h-1l1-4c0-12-9-21-19-21l-8 1c-1-12-11-22-23-22-5 0-10 2-15 6-5-9-14-14-24-14z"/><path class="band" d="M247 163c-74-2-74 0-194 0 0-57 44-102 97-102 54 0 97 45 97 102z"/></g><path class="shirt" d="M150 267c-36 0-65 29-67 64v3h134v1c0-37-30-68-67-68z" fill="#0075bd"/><path class="skin" d="M151 77a91 91 0 0 0-91 87 22 22 0 0 0-20 22 22 22 0 0 0 22 22 22 22 0 0 0 6-1 91 91 0 0 0 65 51v12a37 28 0 0 0-19 25 37 28 0 0 0 37 28 37 28 0 0 0 36-28 37 28 0 0 0-18-25v-12a91 91 0 0 0 64-51 22 22 0 0 0 5 1 22 22 0 0 0 22-22 22 22 0 0 0-18-22 91 91 0 0 0-91-87z" fill="#ffc152"/><path class="nose" d="M150 160c8 0 21 21 16 29-4 7-28 7-32 0-5-8 7-29 16-29z" fill="#e69a11"/><g class="eyes"><g transform="translate(0 -1)"><circle r="10" cy="162" cx="112"/><circle cx="187" cy="162" r="10"/></g><g transform="translate(-518 7)" stroke="#000"><circle r="10" cy="155" cx="630"/><path d="M696 163c0-9 6-16 14-16s14 7 14 16" fill="none" stroke-width="3" stroke-linecap="round"/></g></g><g class="mouth" stroke="#000" stroke-width="3" stroke-linecap="round"><path d="M173 207c0 10-11 18-23 18s-23-8-23-18" fill="none"/><path d="M172 207c0 10-10 18-22 18-13 0-23-8-23-18z" fill="#fff" fill-rule="evenodd"/></g><g class="earrings" fill="#00a708"><g transform="translate(-516 6)"><circle cx="574" cy="214" r="10"/><circle r="10" cy="214" cx="758"/></g><path d="M51 225l8-16 9 16-9 16zm181 0l9-16 9 16-9 16z"/><g transform="translate(-518 8)"><ellipse cx="577" cy="202" rx="5" ry="12"/><ellipse cy="202" cx="760" rx="5" ry="12"/></g></g><g class="hair_front" fill="#00f"><path d="M150 65c-54 0-98 44-98 98l1 3c3 0 8-1 12 2 0 0 31-16 55-37 18-15 28-31 31-35l1 1c2 4 13 19 30 34 24 21 56 37 56 37 3-2 6-2 9-2v-3c0-54-43-98-97-98z"/><path d="M150 68a95 95 0 0 0-94 97s14 2 16 11c4-21 12-43 25-60l-8 20c9 4 19 6 29 8l6-23v24c17 3 36 3 53 1v-26l6 25c11-1 22-4 33-7l-7-19c8 12 14 25 18 39l6 19c0-9 9-11 13-13 0-35-22-72-54-87-13-6-27-9-42-9z"/><path d="M152 71c-22 0-37 6-45 15a88 88 0 0 0-47 78v1c3 3 5 2 8-3 6-10 12-37 37-53v1c10 23 27 37 27 37s8-9 8-12c1 10 12 18 12 18s12-8 12-18c0 3 7 12 7 12s18-14 27-37c24 16 30 42 36 52 2 5 4 6 8 3v-1c0-32-18-60-44-75-6-11-22-18-46-18z"/><path d="M153 43a27 27 0 0 0-20 9 24 24 0 0 0-15-5 24 24 0 0 0-23 18 21 21 0 0 0-6-1 21 21 0 0 0-22 22 21 21 0 0 0 0 3 24 24 0 0 0-22 24 24 24 0 0 0 5 14 21 21 0 0 0-8 17 21 21 0 0 0 20 21 10 10 0 0 0 10 6 10 10 0 0 0 10-10 10 10 0 0 0-2-5 21 21 0 0 0 4-12 21 21 0 0 0 0-2 13 13 0 0 0 11-11 19 19 0 0 0 3 0 19 19 0 0 0 18-14 15 15 0 0 0 4 1 15 15 0 0 0 12-6 19 19 0 0 0 15 6 19 19 0 0 0 16-10 15 15 0 0 0 15 14 15 15 0 0 0 9-3 19 19 0 0 0 17 9 19 19 0 0 0 15 17 18 18 0 0 0 0 2 18 18 0 0 0 5 13 9 9 0 0 0-1 5 9 9 0 0 0 9 9 9 9 0 0 0 9-9 18 18 0 0 0 14-18 18 18 0 0 0-2-8 16 16 0 0 0 5-12 16 16 0 0 0-7-14 18 18 0 0 0 1-6 18 18 0 0 0-18-18 18 18 0 0 0-1 0 18 18 0 0 0 1-4 18 18 0 0 0-18-18 18 18 0 0 0-7 2 21 21 0 0 0-21-19 21 21 0 0 0-13 5 27 27 0 0 0-22-12z"/><path d="M218 191s10-8 5-38c-3-24-30-45-30-45s4 2-9 16c-13 15-30 15-30 15 8-14 7-24 7-35 0 0-7 18-18 25-11 8-29 10-29 10 9-9 15-19 12-32 0 0-8 23-20 32-11 10-22 12-22 12-7 14-9 28-1 43 0 0-26-9-28-30a95 95 0 1 1 190 0c-3 20-27 27-27 27z"/><path d="M113 66l-22-3-5 20-23 3c-1 1 2 23 2 23l-14 12c-1 1 1 18 1 18l-10 15c-1 2 8 14 8 14l-11 12 3 18 8 9 2 21 25 9-4-23 11-14-8-18 14-5-7-16h16v-17l17-2 5-15 18 1 4-18 20 6 11-20 26 7 3 17 17 4 3 19 13 7-1 18c12-3 15-3 21 6 12-56-28-106-78-108l-19-14-16 8-17-9c-1-1-13 15-13 15z"/><path d="M149 65c-18 0-37 5-54 19-45 36-45 81-36 120 9 36 48 62 55 67-6-10-1-95 30-125 33-33 53-33 57-33 20 16 27 41 32 50 3 5 5 6 8 3v-1c0-31-16-57-40-73 0-14-24-27-52-27zm-35 206l1 1-1-1z"/><path d="M148 67c-52 0-94 42-94 94v4l3-1 2 1c-1 9 0 18 3 26 3 27-11 46-11 46s32-3 35-53c3-70 45-85 58-88a118 118 0 0 1 9 0c14 3 55 19 59 88 2 50 34 53 34 53s-14-19-11-46c1-9 5-17 5-27h2l1-3c0-52-43-94-95-94z"/><path d="M150 65a103 103 0 0 0-46 194c-16-29-28-63-20-108 39-3 63-11 93-54 0 0 36 24 41 64 7 47-11 83-20 97a103 103 0 0 0-48-193z"/><path d="M151 69c-52 0-99 47-93 94l2 2c-3 57 14 87 37 120 0 0-21-63-1-124 13-37 46-60 55-65 9 5 42 28 55 65 21 61-1 124-1 124 23-33 40-63 38-120l1-1v-1c6-47-40-94-93-94z"/><path d="M151 75c-50 0-91 40-91 89 3 4 5 2 7-3 6-10 13-37 38-53 26 5 64 6 93 1 23 17 30 43 35 52 3 5 5 7 8 3v-7c-5-47-44-82-90-82z"/></g><g class="glasses" fill="none" stroke="#0075bd" stroke-width="5" stroke-linejoin="round"><path d="M140 161a35 24 0 0 1-35 24 35 24 0 0 1-35-24 35 24 0 0 1 35-24 35 24 0 0 1 35 24zm89 0a35 24 0 0 1-34 24 35 24 0 0 1-35-24 35 24 0 0 1 35-24 35 24 0 0 1 34 24zM140 161h20"/><path d="M82 144c-8 0-14 7-14 15v6c0 8 6 14 14 14h44c8 0 14-6 14-14v-6c0-8-6-15-14-15H82zm93 0c-8 0-14 7-14 15v6c0 8 6 14 14 14h43c8 0 14-6 14-14v-6c0-8-6-15-14-15h-43zm-33 19h15-15z"/><path d="M109 140c-13 0-27 1-40 3 0 0-10 46 37 46 45 1 34-46 34-46-10-2-21-3-31-3zm84 0l-30 3s-12 47 34 46c46 0 36-46 36-46-13-2-26-3-40-3zm-50 13h16-16z"/></g><path class="nope" transform="translate(-5 0)" d="M197.3 6.3c-6 0-11 3-13 9l-13 30c-3 7 1 16 8 18l89 37c7 3 16 0 19-7l12-30c3-8 0-16-8-19l-89-37zm0 5l3 1 89 37c5 2 7 7 5 12l-12 30c-2 5-7 7-12 5l-89-37c-5-2-7-7-5-12l12-30c2-4 5-6 9-6zm74 43l18 8-2 5-11-5-2 5 10 4-2 5-10-4-2.1 5.6 11 4.4-2 5-18-7zm-23-9l10 4c10.8 5.5 6.5 19.6-6 17l-5-2-3.5 8.7-6.5-2.7zm4 7l-3 7c7.8 4.7 12.4-3.5 3-7zm-22.5-9.6c-3.4-1.3-8.5 1.6-10 5-1.4 3.4.1 9 3.5 10.6 3.5 1.6 9.3-.8 10.9-4.4 1.5-3.7-.6-9.7-4.4-11.2zm2.5-5.4c4 2 6.6 4.6 8 8 2.4 7.3-1 16.5-8 19-3.4 1.3-7 1.3-11 0-4-2-6.7-4.7-8-8-1.4-3.4-1.4-7 0-11 2-4 4.6-6.7 8-8 3.3-1.4 7-1.4 11 0zm-39-15l7 3 2 21 7-17 6 2-10 25-7-3-3-21-7 18-6-3z" fill="#ff6a6a"/><path class="like" d="M16 43.9c-7 3-10 12-7 19l12 30c3 7 11 11 19 8l89-37c7-3 11-12 8-19l-13-30c-3-7-11-11-18-8l-90 37zm2 5l89-37c5-2 10 0 12 5l13 30c2 5 0 10-5 12l-89 37c-5 2-10 0-12-5l-13-30c-2-5 0-10 5-12zm72-19l19-7 2 5-12 5 2 5 11-5 2 5-11 5 3 6 12-5 2 5-19 8-11-27zm-29 12l7-3 4 10 6-14 8-3-7 18 20 8-9 4-15-6 4 10-7 3-11-27zm-14 6l7-3 12 27-7 3-12-27zm-23 10l7-3 9 21 12-5 2 6-19 8-11-27z" fill="#4ccc92"/>
</svg>
</div>
<div class="card-info">
<span class="name">Katie, 26</span>
<span class="job">Software Engineer</span>
</div>
</div>
</div>
<div id="footer">
<div id="action-buttons">
<button id="no-button"><svg xmlns="http://www.w3.org/2000/svg" width="150" height="135" viewBox="0 0 140 127" version="1"><path d="M26 1c-4 0-7 2-10 5-7 6-6 17 2 25l29 29-29 29c-8 8-9 19-2 25 6 7 17 6 25-2l29-29 30 29c7 8 18 9 24 2 7-6 6-17-1-25L93 60l30-29c7-8 8-19 1-25-2-3-6-5-10-5-5 0-10 2-14 6L70 37 41 7c-4-4-10-6-15-6z" fill="#ff6a6a"/></svg></button>
<button id="yes-button"><svg xmlns="http://www.w3.org/2000/svg" width="150" height="135" viewBox="0 0 140 127" version="1"><path d="M35 0C3 0-18 39 22 75c18 16 34 33 48 52 12-16 34-40 48-52 40-36 19-75-13-75-19 0-29 14-35 25C65 14 54 0 35 0z" fill="#4ccc92"/></svg></button>
</div>
</div>
<div id="meter">
<div></div>
</div>
<div id="helpPopup" class="popup">
<div class="dialog">
<h3>Attention <span class="glitched">tonder</span> User</h3>
<p>We are currently experiencing a glitch in which certain users <span class="glitched">cannot be "liked".</span></p>
<p>You can help debug! Simply try to <span class="liked">like</span> users until you can identify the <em>common attribute</em> shared by all the <span class="glitched">glitched users</span>.</p>
<p>Once you've discovered the bug, just <span class="glitched">pass</span> on the glitched users and <span class="liked">like</span> at least 10 other users.</p>
<p><em>Tip:</em> We suspect that the glitch has to do with one of the following: facial expression, accessories, hair length, name, age, or job.</p>
<div style="text-align: center"><button id="ok-button">OK</button></div>
</div>
</div>
<div id="winPopup" class="popup">
<div class="dialog">
<h3>Great Work!</h3>
<p>Thanks for identifying the glitch! Now that we know that it only affects users <span id="glitchFactor">with long hair</span>, it should be easy to fix.</p>
<p>Unfortunately, we've heard reports of <span class="glitched">another glitch</span> affecting a different subset of users. Can you help us with that one?</p>
<div style="text-align: center"><button id="replay-button">PLAY AGAIN</button></div>
</div>
</div>
</div>
</div>
<script>
(function() {
function rand(min, max) {
return min + Math.random() * (max - min);
}
function randInt(min, max) {
return Math.floor(rand(min, max));
}
function randFrom(array) {
return array[Math.floor(Math.random() * array.length)];
}
function getColor(h, l, sd) {
if (h === undefined || h < 0) h = rand(1, 360);
if (l === undefined || l < 0) l = rand(0, 100);
var s = l + ((sd === undefined)? 10 : sd);
return 'hsl(' + h + ',' + s + '%,' + l + '%)';
}
function Card(element) {
this.element = element;
this.x = this.y = -1;
this.status = "neutral";
this.svg = element.getElementsByTagName("svg")[0];
this.qualities = {};
this.features = {
"hair_front": {},
"hair_back": {},
"eyes": {onPercent: 0.3, optional: false },
"mouth": {onPercent: 0.3, optional: false },
"earrings": {onPercent: 0.75, optional: true },
"glasses": {onPercent: 0.25, optional: true },
"like": {},
"nope": {}
};
for (var key in this.features) {
var group = this.svg.getElementsByClassName(key)[0];
this.features[key].group = group;
this.features[key].count = group.children.length;
}
this.refresh = function() {
this.qualities = {}; // reset all
var qualitiesToChoose = ["hair", "eyes", "mouth", "earrings", "glasses", "name", "age", "job"];
// If we have a target quality, make sure it's chosen with a 50% chance first
if (currentFactor) {
var on = Math.random() >= 0.5;
var index = qualitiesToChoose.indexOf(currentFactor);
if (index > -1) {
this.choose(currentFactor, on);
qualitiesToChoose.splice(index, 1);
}
this.isBugged = on;
//console.log(currentFactor, this.isBugged, this.qualities[currentFactor]);
}
// Then choose all the other qualities
for (var i = 0; i < qualitiesToChoose.length; i++) {
this.choose(qualitiesToChoose[i]);
}
this.setColors();
};
this.showFeature = function(feature, i) {
if (i === undefined) i = this.qualities[feature];
if (feature == "hair") {
this.showFeature("hair_front", i[0]);
this.showFeature("hair_back", i[1]);
return;
}
var group = this.features[feature].group;
for (var j = 0; j < group.children.length; j++) {
group.children[j].style.display = (j == i)? "block" : "none";
}
};
this.choose = function(quality, on) {
var f = "choose" + quality.charAt(0).toUpperCase() + quality.substr(1);
if (this[f]) this[f](on);
else if (this.features[quality]) this.chooseFeature(quality, on);
};
this.chooseHair = function(on) {
var shorts = Card.shortHairs;
var longs = Card.longHairs;
var meds = Card.longHairs;
if (on === true) this.qualities.hair = randFrom(longs);
else if (on === false) this.qualities.hair = randFrom(shorts);
else {
var hair, n = 0;
// Choose any random hair that matches existing features (e.g. glasses)
while (n++ < 1000) {
var i = randInt(0, shorts.length + longs.length + meds.length);
if (i < shorts.length) hair = shorts[i];
else if (i - shorts.length < longs.length) hair = longs[i - shorts.length];
else hair = meds[i - shorts.length - longs.length];
// Check for conflicts
if (this.qualities.glasses > -1 && !this.glassesAllowed(hair)) continue;
else if (this.qualities.earrings > -1 && !this.earringsAllowed(hair)) continue;
break;
}
this.qualities.hair = hair;
}
this.showFeature("hair");
};
this.chooseFeature = function(feature, on) {
var info = this.features[feature];
if (this[feature+"Allowed"] && !this[feature+"Allowed"]()) {
// If we're not allowed to have this feature on based on others, on can't be true
on = false;
} else if (on === undefined) {
// Else if on wasn't specified, choose it randomly
on = (Math.random() < info.onPercent);
}
var offIndex = (info.optional)? -1 : 0;
if (on) {
this.qualities[feature] = randInt(offIndex + 1, info.count);
} else {
this.qualities[feature] = offIndex;
}
this.showFeature(feature);
};
this.showNameAndAge = function() {
var name = this.qualities.name || "";
var age = this.qualities.age || "";
this.element.getElementsByClassName("name")[0].textContent = name + ", " + age;
};
this.showJob = function() {
this.element.getElementsByClassName("job")[0].textContent = this.qualities.job;
};
this.chooseName = function(on) {
if (typeof Card.vowelNames == "string") Card.vowelNames = Card.vowelNames.split(",");
if (typeof Card.consonantNames == "string") Card.consonantNames = Card.consonantNames.split(",");
if (on === true) this.qualities.name = randFrom(Card.vowelNames);
else if (on === false) this.qualities.name = randFrom(Card.consonantNames);
else {
var i = randInt(0, Card.vowelNames.length + Card.consonantNames.length);
if (i < Card.vowelNames.length) this.qualities.name = Card.vowelNames[i];
else this.qualities.name = Card.consonantNames[i - Card.vowelNames.length];
}
this.showNameAndAge();
};
this.chooseAge = function(on) {
var age = randInt(20, 31);
var evenAge = (age % 2)? age + 1 : age;
if (on === true) this.qualities.age = evenAge;
else if (on === false) this.qualities.age = evenAge - 1;
else this.qualities.age = age;
this.showNameAndAge();
};
this.chooseJob = function(on) {
if (typeof Card.oneWordJobs == "string") Card.oneWordJobs = Card.oneWordJobs.split(",");
if (typeof Card.twoWordJobs == "string") Card.twoWordJobs = Card.twoWordJobs.split(",");
if (on === true) this.qualities.job = randFrom(Card.twoWordJobs);
else if (on === false) this.qualities.job = randFrom(Card.oneWordJobs);
else {
var i = randInt(0, Card.oneWordJobs.length + Card.twoWordJobs.length);
if (i < Card.oneWordJobs.length) this.qualities.job = Card.oneWordJobs[i];
else this.qualities.job = Card.twoWordJobs[i - Card.oneWordJobs.length];
}
this.showJob();
};
// Check whether the passed in hair (or the currently set hair) allows earrings
this.earringsAllowed = function(hair) {
if (!hair) hair = this.qualities.hair;
if (hair) {
var disallowFs = [7, 8, 9];
var allowBs = [-1, 0, 2, 8];
return (disallowFs.indexOf(hair[0]) == -1 && ~allowBs.indexOf(hair[1]));
} else return true;
};
this.glassesAllowed = function(hair) {
if (!hair) hair = this.qualities.hair;
return (!hair || hair[0] != 6);
};
this.setColor = function(element, color, setStroke) {
if (typeof element === "string") {
if (this.features[element]) element = this.features[element].group;
else element = this.svg.getElementsByClassName(element)[0];
}
element.setAttribute(setStroke? "stroke" : "fill", color);
};
this.setColors = function() {
// Ensure we don't use the same bg color twice in a row
if (!Card.prevHue) Card.prevHue = 0;
var bgHue = Card.prevHue;
while (Math.abs(bgHue - Card.prevHue) < 20) {
bgHue = rand(100, 270);
}
Card.prevHue = bgHue;
this.setColor("bg", getColor(bgHue, 75, -20));
var skinHue = rand(10, 30);
if (skinHue < 0) skinHue += 360;
var skinL = rand(35, 85);
// Hacks to give people with the black hair style darker skin
if (this.qualities.hair[1] == 7) skinL = rand(35, 50);
this.setColor('skin', getColor(skinHue, skinL));
this.setColor('nose', getColor(skinHue, skinL * 0.85));
this.setColor("mouth", getColor(skinHue * 0.5, skinL * 0.7), true);
var hairHue = rand(0, 30);
var hairL = rand(10, skinL - 20);
var hairColor = getColor(hairHue, hairL, rand(20, 30));
this.setColor("hair_back", hairColor);
this.setColor("hair_front", hairColor);
var shirtColor = getColor(bgHue, 40, 0);
this.setColor('shirt', shirtColor);
this.setColor('earrings', getColor(bgHue, 40, 20));
this.setColor("glasses", getColor(bgHue, rand(10, 40), 20), true);
this.setColor('band', shirtColor);
};
this.moveTo = function(x, y) {
this.x = x;
this.y = y;
};
this.moveOffscreen = function(left) {
this.targetX = this.element.offsetWidth * (left? -1.5 : 1.5);
};
this.resetPosition = function() {
this.x = this.y = -1;
this.targetX = NaN;
this.targetY = NaN;
};
this.moveToCenter = function() {
this.targetX = -1;
this.targetY = -1;
};
this.update = function() {
var w = this.element.offsetWidth;
var s = w / 20;
if (this.showBuggedNope) s /= 2;
movingCard = !isNaN(this.targetX) || !isNaN(this.targetY);
if (!isNaN(this.targetX)) {
if (Math.abs(this.targetX - this.x) > s) {
this.x += Math.sign(this.targetX - this.x) * s;
} else {
this.x = this.targetX;
this.targetX = NaN;
}
}
if (!isNaN(this.targetY)) {
if (Math.abs(this.targetY - this.y) > s) {
this.y = Math.sign(this.targetY - this.y) * s;
} else {
this.y = this.targetY;
this.targetY = NaN;
}
}
this.updatePosition();
};
this.updatePosition = function() {
var w = this.element.offsetWidth;
if (!dragging && Math.abs(this.x) > w * 1.25) {
this.reset();
return;
}
this.element.style.left = this.x + 'px';
this.element.style.top = this.y + 'px';
var r = -this.x / w * 15;
this.element.style.transform = "rotate("+ r + "deg)";
this.status = "neutral";
if (this.x / w > 0.5) this.status = "liked";
if (this.x / w < -0.5) this.status = "noped";
this.features.like.group.style.display = (this.status == "liked" && !this.showBuggedNope)? "block" : "none";
this.features.nope.group.style.display = (this.status == "noped" || this.showBuggedNope)? "block" : "none";
};
this.reset = function() {
// Move to back
switchCards();
this.resetPosition();
this.showBuggedNope = false;
this.refresh();
};
this.refresh();
}
Card.shortHairs = [[2,-1],[3,-1],[4,-1],[6,-1],[8,-1],[10,-1],[1,2],[2,2],[4,2],[6,2],[7,2],[8,2],[1,8],[3,8],[4,8],[5,8],[7,8],[10,8]];
Card.medHairs = [[9,2],[9,8]];
Card.longHairs = [[0,0],[1,0],[4,0],[6,0],[7,0],[9,0],[10,0],[0,1],[1,1],[4,1],[6,1],[7,1],[8,1],[0,3],[1,3],[4,3],[6,3],[7,3],[8,3],[0,4],[1,4],[4,4],[6,4],[8,4],[9,4],[0,5],[4,5],[5,5],[7,5],[8,5],[9,5],[0,6],[1,6],[4,6],[6,6],[8,6],[9,6],[1,7],[2,7],[4,7],[5,7]];
Card.vowelNames = "Ashley,Emily,Amanda,Elizabeth,Alexis,Amber,Alyssa,Alexandra,Anna,Olivia,Allison,Abigail,Erin,Andrea,Emma,Erica,Amy,Angela,Alexandria,Alicia,Erika,Aaliyah,Annita,Annette,Aundrea,Ella,Evon,Alyce,Evie,Ina,Erline,Yvette";
Card.consonantNames = "Jessica,Sarah,Samantha,Brittany,Taylor,Megan,Hannah,Kayla,Lauren,Stephanie,Rachel,Jennifer,Nicole,Victoria,Courtney,Danielle,Rebecca,Jasmine,Brianna,Katherine,Madison,Morgan,Melissa,Michelle,Kelsey,Chelsea,Kimberly,Tiffany,Mary,Christina,Sara,Shelby,Heather,Haley,Maria,Kaitlyn,Laura,Natalie,Jordan,Brooke,Julia,Vanessa,Sydney,Kelly,Kristen,Katelyn,Marissa,Crystal,Paige,Cassandra,Gabrielle,Katie,Caitlin,Lindsey,Destiny,Kathryn,Jacqueline,Shannon,Jenna,Savannah,Mariah,Sierra,Briana,Miranda,Jamie,Catherine,Brittney,Breanna,Grace,Monica,Sabrina,Madeline,Caroline,Molly,Mackenzie,Leah,Diana,Whitney,Cheyenne,Makayla,Jada,Lisandra,Shellie,Xiomara,Charleen,Danika,Leota,Destiny,Francie,Dominque,Lakia,Sherry,Shirlee,Zelda,Venice,Colette,Leisha,Hayley,Sylvia,Jacki,Lanelle,Selena,Jalisa,Maisie,Vernita,Catarina,Delila,Virgina,Leanne,Carolyn,Latrice,Lucia,Mariela,Concetta,Zena,Noemi,Leanora,Suzie";
Card.oneWordJobs = "Accountant,Actor,Acupuncturist,Administrator,Anaesthetist,Anthropologist,Archaeologist,Architect,Archivist,Aromatherapist,Artist,Athlete,Astrologer,Astronomer,Auctioneer,Author,Baker,Blacksmith,Bodyguard,Bookkeeper,Bookmaker,Brewer,Bricklayer,Broadcaster,Builder,Butcher,Caretaker,Carpenter,Cartoonist,Cashier,Chauffeur,Chef,Chemist,Chiropodist,Chiropractor,Choreographer,Clairvoyant,Cleaner,Clockmaker,Coastguard,Comedian,Composer,Conservationist,Cook,Coroner,Counsellor,Courier,Craftsperson,Curator,Dancer,Decorator,Dentist,Designer,Dietician,Diplomat,Director,Diver,Doctor,Dressmaker,Economist,Editor,Electrician,Engineer,Farmer,Firefighter,Fisher,Fundraiser,Gamekeeper,Gardener,Genealogist,Hairdresser,Herbalist,Historian,Homemaker,Horticulturalist,Housekeeper,Hypnotherapist,Illustrator,Interpreter,Inventor,Jockey,Journalist,Judge,Lawyer,Lecturer,Librarian,Lifeguard,Locksmith,Machinist,Magician,Magistrate,Manicurist,Mathematician,Meteorologist,Model,Musician,Nurse,Optician,Osteopath,Paramedic,Pathologist,Pawnbroker,Pharmacist,Photographer,Physiotherapist,Pilot,Plumber,Politician,Printer,Producer,Professor,Psychiatrist,Psychologist,Publisher,Receptionist,Reporter,Researcher,Roofer,Sailor,Salesperson,Scientist,Sculptor,Secretary,Singer,Shoemaker,Soldier,Stockbroker,Surgeon,Surveyor,Tailor,Tattooist,Unemployed,Veterinarian,Waiter";
Card.twoWordJobs = "Advertising Executive,Air Traffic Controller,Aircraft Engineer,Antique Dealer,Art Critic,Art Dealer,Art Historian,Assembly Line Worker,Au Pair,Bank Clerk,Bank Manager,Bartender,Bus Driver,Business Consultant,Business Owner,Cabin Crew,Cabinet Maker,Camera Operator,Car Dealer,Carwash Attendant,Care Assistant,Catering Staff,Childcare Worker,Circus Performer,Civil Servant,Clerical Assistant,Community Worker,Company Director,Computer Analyst,Computer Engineer,Computer Programmer,Construction Worker,Costume Designer,Crane Driver,Customs Officer,Data Analyst,Delivery Driver,Dental Hygienist,Disc Jockey,Driving Instructor,Estate Agent,Events Organiser,Factory Worker,Fashion Designer,Film Director,Financial Advisor,Fitness Instructor,Flower Arranger,Garden Designer,Grave Digger,Game Developer,Game Programmer,Graphic Designer,Game Designer,Immigration Officer,Insurance Consultant,Interior Designer,IT Consultant,Jewellery Maker,Laboratory Technician,Landscape Gardener,Legal Secretary,Lighthouse Keeper,Literary Agent,Local Government,Bus Driver,Make-up Artist,Management Consultant,Managing Director,Market Trader,Marketing Director,Massage Therapist,Medical Student,Merchant Navy Personnel,Occupational Therapist,Park Ranger,Party Planner,Police Officer,Pop Star,Postal Delivery Worker,Prison Officer,Private Investigator,Property Developer,Racecar Driver,Radio Personality,Security Guard,Ship Builder,Shop Assistant,Social Worker,Software Consultant,Software Developer,Software Architect,Song Writer,Speech Therapist,Sports Coach,Tarot Reader,Tax Inspector,Taxi Driver,Primary School Teacher,Middle School Teacher,High School Teacher,Teaching Assistant,Television Host,Tour Guide,Train Driver,Travel Agent,Window Cleaner,College Student,Graduate Student";
var meter = document.getElementById("meter");
var segment = meter.children[0];
for (var i = 0; i < 9; i++) {
var clone = segment.cloneNode(false);
meter.appendChild(clone);
}
var card1 = document.querySelector('.card');
var card2 = card1.cloneNode(true);
card1.parentNode.appendChild(card2);
var cards = [new Card(card1), new Card(card2)];
var currentCard = cards[1];
var dragging = false;
var startX, startY;
var movingCard = false;
for (var i = 0; i < cards.length; i++) {
var element = cards[i].element;
element.addEventListener('mousedown', function(card, e) {
currentCard = card;
dragging = true;
startX = e.pageX;
startY = e.pageY;
}.bind(null, cards[i]));
}
function switchCards() {
var newCard = (currentCard == cards[0])? cards[1] : cards[0];
newCard.element.parentNode.appendChild(newCard.element); // move it to the front
currentCard = newCard;
}
function setIndicator(success) {
var segments = meter.children;
for (var i = 0; i < segments.length - 1; i++) {
segments[i].className = segments[i+1].className;
}
segments[segments.length-1].className = (success)? "good" : "bad";
}
function clearIndicators() {
var segments = meter.children;
for (var i = 0; i < segments.length - 1; i++) {
segments[i].className = "";
}
}
function recordLike(success) {
if (success) successfulLikes ++;
else successfulLikes = 0;
setIndicator(success);
if (successfulLikes >= meter.children.length) {
// win!
wins++;
winPopup.style.display = "block";
var text = {
"glasses": "wearing glasses",
"eyes": "who are winking",
"earrings": "wearing earrings",
"mouth": "who smile a lot",
"name": "whose names that start with a vowel",
"hair": "with long hair",
"job": "with multi-word job titles",
"age": "with even-numbered ages"
};
document.getElementById("glitchFactor").textContent = text[currentFactor];
}
}
function tryLike(card) {
if (card.isBugged) {
card.showBuggedNope = true;
card.moveOffscreen(true);
recordLike(false);
} else {
card.moveOffscreen(false);
recordLike(true);
}
}
document.onmouseup = function(e) {
if (dragging && currentCard) {
if (currentCard.status == "neutral") currentCard.moveToCenter();
else if (currentCard.status == "liked") tryLike(currentCard);
else currentCard.moveOffscreen(true);
}
dragging = false;
};
document.onmousemove = function(e) {
if (dragging && currentCard) {
var x = e.pageX - startX;
var y = e.pageY - startY;
currentCard.moveTo(x, y);
}
};
document.getElementById("no-button").onclick = function(e) {
if (currentCard && !movingCard) currentCard.moveOffscreen(true);
};
document.getElementById("yes-button").onclick = function(e) {
if (currentCard && !movingCard) tryLike(currentCard);
};
var helpPopup = document.getElementById('helpPopup');
var winPopup = document.getElementById('winPopup');
winPopup.style.display = "none";
document.getElementById("ok-button").onclick = function(e) {
helpPopup.style.display = "none";
};
document.getElementById("replay-button").onclick = function(e) {
startGame();
winPopup.style.display = "none";
};
document.getElementById("info-button").onclick = function(e) {
helpPopup.style.display = "block";
};
var factors = ["eyes", "glasses", "earrings", "mouth", "name", "hair", "job", "age"];
var remainingFactors = [];
var successfulLikes = 0;
var wins = 0;
var currentFactor = null;
function startGame() {
if (!remainingFactors.length) remainingFactors = factors.slice();
var i;
if (wins == 0) i = randInt(0, 2);
else if (wins == 1) i = randInt(0, 4);
else i = randInt(0, remainingFactors.length);
currentFactor = remainingFactors.splice(i, 1)[0];
for (var i = 0; i < cards.length; i++) {
cards[i].refresh(currentFactor);
}
successfulLikes = 0;
clearIndicators();
}
function loop() {
for (var i = 0; i < cards.length; i++) {
cards[i].update();
};
}
startGame();
setInterval(loop, 1000 / 60);
})();
</script>
</body>
</html>