-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfrontend.js
511 lines (442 loc) · 18.8 KB
/
frontend.js
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
var database;
var horses;
var weeds;
var minds_eye;
/* Tracks the player's guess as it's made */
var current_guess = {
horse: '',
weed: '',
mind: '',
remaining: 3
}
/* Descriptive strings relating to my mind's eye. */
/* As quixotic as it is mysterious */
var minds_eye_messages = ["was fabricated within my mind's eye.",
"was found deep within my mind's eye.",
"was brought to you by my mind's eye.",
"was produced entirely by my mind's eye.",
"was neither, it was my mind's eye.",
"exists only within my mind's eye.",
"was a vision seen only by my mind's eye.",
"was constructed in the foundry of my mind's eye.",
"was all in my mind's eye, dawg.",
"can only be found inside my mind's eye.",
"was a forgery by my mind's eye."];
$(document).ready(function() {
// $.ajax({
// type: "GET",
// url:"database.csv",
// dataType: "text",
// success: function(raw_database) {initialize(raw_database);}
// });
$.mobile.loading().hide();
initialize(uglyHardcodedDatabase());
});
/*
* Pre-game initialization. Loads databases, starts page content generation.
*
* @param {string} raw_database - Raw string-format CSV database.
*/
function initialize(raw_database) {
database = parseCSV(raw_database);
if(database.length > 0) {
horses = database[0];
horses.shift();
weeds = database[4];
weeds.shift();
minds_eye = database[8];
minds_eye.shift();
presentOptions();
$('#restart').on('tap', function() {
window.location.reload(false);
});
} else {
dbErrorFallback();
}
}
/*
* Fallback routine if database loading fails.
* (i.e. if database is busy or can't be found)
* Current strategy: Wait a little and reload the page.
*/
function dbErrorFallback() {
$('#wrapper').append("Looks like the database is busy. Hold on, let me try something...");
setTimeout(function() {
window.location.reload(false);
}, 3000);
}
/*
* Animate the player's three choices onto the page,
* along with relevant controls.
*/
function presentOptions() {
/* Get random candidates and insert in the DOM */
var triple = shuffle(getTriple());
triple.forEach(function(item) {
$('#choices').prepend("<tr height=100 hidden><td class='candidate' width=200 align=center>" + item + "</td></tr>");
});
$('tr').append("<td align=center hidden><button class='horse guess'></button><div class='guesshelp' hidden>HORSE</div></td>");
$('tr').append("<td align=center hidden><button class='weed guess'></button><div class='guesshelp' hidden>WEED</div></td>");
$('tr').append("<td align=center hidden><button class='mind guess'></button><div class='guesshelp' hidden>MIND'S EYE</div></td>");
/* Guess-button functionality. */
$('.guess').on('tap', function() {
makeGuess($(this));
}).on('mouseenter', function() {
$(this).siblings('.guesshelp').finish().slideDown(100);
}).on('mouseleave', function() {
$(this).siblings('.guesshelp').slideUp(500);
});
/* Fade the three candidates in recursively */
function fadeCandidates() {
var next = $('tr:hidden:first');
if(next.length > 0)
next.fadeIn(1000, fadeCandidates);
else
fadeGuesses();
}
/* Fade in and expand the guess controls */
function fadeGuesses() {
$('.guess').parent(':hidden').fadeIn(800).promise().done(function() {
$(this).animate({width: '66px'}, 800);
$('#choices').animate({left: '-=15%'}, 800, fadeTagline);
});
}
/* Build and fade in tagline */
function fadeTagline() {
var tagline = $('#tagline');
tagline.append(randElement(minds_eye_messages));
tagline.append(" Take your pick.");
tagline.fadeIn(2000, fadeFootnote);
}
/* Finally, fade in the footnote */
function fadeFootnote() {
$('#footnote').fadeIn(2000);
}
/* Start animation process */
/* Each phase is called as a collback from the previous phase */
fadeCandidates();
}
/*
* Handle player's guess action. Called on guess-button presses.
*
* Removes any invalidated guess controls and logs the players guess.
* Additionally, if only one guess remains, that guess is made for the player.
*
* @param {selector} button - jQuery selector of the button that's been pressed.
*/
function makeGuess(button) {
var candidate = button.parent().siblings('.candidate').text();
var guess = '';
/* Fade out guess tooltips and any irrelevant guess controls */
$('.guesshelp').slideUp(200);
button.parent().siblings(':not(.candidate)').fadeOut(200);
if(button.hasClass('horse')) {
guess = 'horse';
current_guess.horse = candidate;
$('.horse').fadeOut(200);
} else if(button.hasClass('weed')) {
guess = 'weed';
current_guess.weed = candidate;
$('.weed').fadeOut(200);
} else if(button.hasClass('mind')) {
guess = 'mind';
current_guess.mind = candidate;
$('.mind').fadeOut(200);
}
/* Decrement guess counter after animations are done */
$('.guess').promise().done(function() {
current_guess.remaining--;
/* If only one guess remains, make it automatically */
/* If no guesses remain, go to validation phase */
if(current_guess.remaining == 1)
makeGuess($('.guess:visible:not(:animated):first'));
else if(current_guess.remaining == 0)
validateGuesses();
});
}
/*
* Once the player has made their guesses, check each against the database.
*/
function validateGuesses() {
if($.inArray(current_guess.horse, horses) != -1)
correctGuess('horse');
else
wrongGuess('horse');
if($.inArray(current_guess.weed, weeds) != -1)
correctGuess('weed');
else
wrongGuess('weed');
if($.inArray(current_guess.mind, minds_eye) != -1)
correctGuess('mind');
else
wrongGuess('mind');
/* Post player's guesses back to the server, for stats */
postGuess();
/* Fade in restart button */
$('#restartwrapper').fadeIn(3000);
}
/*
* The player has guessed correctly on one of the items. Good job!
* Updates page to reflect this turn of events.
*
* @param {string} guess - Guess category (horse, weed, mind)
*/
function correctGuess(guess) {
var item, message;
/* Get corresponding update info based on the guess category */
switch(guess) {
case 'horse':
item = current_guess.horse;
message = "was of course a horse.";
break;
case 'weed':
item = current_guess.weed;
message = "was indeed a weed.";
break;
case 'mind':
item = current_guess.mind;
message = randElement(minds_eye_messages);
break;
}
var row = $('tr:contains(' + item + ')');
/* Insert into DOM */
row.append("<td class='correct' align=left hidden> " + message + "</td>");
row.children('.correct').fadeIn(2000);
buildChart(row, item);
}
/*
* The player has guessed incorrectly on one of the items. Dag, yo!
* Updates page to reflect this tragedy.
*
* @param {string} guess - Guess category (horse, weed, mind)
*/
function wrongGuess(guess) {
var item, message, offset;
/* Get update info based on guess category */
switch(guess) {
case 'horse':
item = current_guess.horse;
message = "was not a horse,";
offset = 1;
break;
case 'weed':
item = current_guess.weed;
message = "was not a weed,";
offset = 2;
break;
case 'mind':
item = current_guess.mind;
message = "was not from my mind's eye,";
offset = 3;
break;
}
var row = $('tr:contains(' + item + ')');
var actual = getCategory(item);
/* Get update info based on actual category */
switch(actual) {
case 'horse':
message += " it was actually a horse.";
break;
case 'weed':
message += " it was in fact a weed.";
break;
case 'mind':
message += " it was in reality engineered by my mind's eye.";
break;
}
/* Insert into DOM */
row.append("<td class='wrong' align=left hidden> " + message + "</td>");
row.children('.wrong').fadeIn(2000);
buildChart(row, item);
}
/*
* Builds a pie chart displaying the guessing statistics for a candidate
* and inserts it into the DOM.
*
* @param {selector} row - Table row containing the candidate.
* @param {string} candidate - Candidate to get stats for.
*/
function buildChart(row, candidate) {
var width = 400;
var height = 150;
var radius = 40;
var colors = [ '#0072aa', '#c7990b', '#960570'];
var textOffset = 7;
var index, offset;
var category = getCategory(candidate);
switch(category) {
case 'horse':
index = $.inArray(candidate, horses) + 1;
offset = 0;
break;
case 'weed':
index = $.inArray(candidate, weeds) + 1;
offset = 4;
break;
case 'mind':
index = $.inArray(candidate, minds_eye) + 1;
offset = 8;
break;
}
var statVals = [ +database[offset+1][index],
+database[offset+2][index],
+database[offset+3][index]];
var totalVal = statVals[0] + statVals[1] + statVals[2];
if(totalVal == 0) {
return;
}
var stats = [{"label": "HORSE", "value": statVals[0], "percent": statVals[0]/totalVal},
{"label": "WEED", "value": statVals[1], "percent": statVals[1]/totalVal},
{"label": "MIND'S EYE", "value": statVals[2], "percent": statVals[2]/totalVal}];
var cell = row.children('.candidate');
var arc = d3.svg.arc()
.outerRadius(radius)
.innerRadius(0);
var pie = d3.layout.pie()
.sort(null)
.value(function(d) {
return d.value;
});
var svg = d3.selectAll(cell.toArray())
.append('svg:svg')
.data([stats])
.attr('width', width)
.attr('height', height)
.append('svg:g')
.attr('transform', 'translate(' + width/2 + ', ' + height/2 + ')');
var slices = svg.selectAll('g.slice')
.data(pie)
.enter()
.append('svg:g')
.attr('class', 'slice');
slices.append('svg:path')
.attr('fill', function(d, i) { return colors[i]; })
.attr('d', arc);
slices.append('svg:text')
.attr('transform', function(d) {
var x, y, r;
r = radius + textOffset;
x = r * Math.cos((d.startAngle + d.endAngle - Math.PI) / 2);
y = r * Math.sin((d.startAngle + d.endAngle - Math.PI) / 2);
return 'translate(' + x + ', ' + y + ')';
})
.attr('text-anchor', function(d) {
return ((d.startAngle + d.endAngle)/2 < Math.PI ? 'beginning' : 'end');
})
.text(function(d, i) {
var label = stats[i].label + " - " + Math.round(stats[i].percent * 100) + "%";
return (stats[i].value > 0 ? label : '');
})
.attr('class', 'slicelabel');
$('.slicelabel').hide();
$('.slice').children('path').on('mouseenter', function() {
$(this).siblings('.slicelabel').finish().fadeIn(100);
}).on('mouseleave', function() {
$(this).siblings('.slicelabel').fadeOut(500);
});
cell.children('svg').css({
'top': cell.position().top - (radius/2),
'left': cell.position().left - (3*width/4)
}).hide().fadeIn(2000);
}
/*
* Get the actual category of a candidate item.
*
* @param {string} candidate - Name of a candidate.
*
* @return {string} - Category of the candidate.
*/
function getCategory(candidate) {
if($.inArray(candidate, horses) != -1)
return "horse";
else if($.inArray(candidate, weeds) != -1)
return "weed";
else if($.inArray(candidate, minds_eye) != -1)
return "mind";
}
/*
* Randomly selects three candidates to present to the player - a horse, a weed,
* and something out of my mind's eye, as mysterious as it is enigmatic.
*
* @return {string array} - An array of three strings, one of each category.
*/
function getTriple() {
triple = [randElement(horses), randElement(weeds), randElement(minds_eye)];
return triple;
}
/*
* Parse a raw CSV database string into a two-dimensional array.
*
* @param {string} raw_database - CSV database, in string format.
*
* @return {array} - CSV database, in array format.
*/
function parseCSV(raw_database) {
arrays = $.csv.toArrays(raw_database);
return arrays;
}
/*
* Post the player's guess to the server, for use in later statistical analysis.
*/
function postGuess() {
// $.ajax({
// type: 'POST',
// url: 'dbmod.py',
// data: current_guess,
// //contentType: "application/json; charset=utf-8",
// //dataType: "json",
// success: function(data) { console.log(data); },
// error: function(data) { console.log("failure!"); console.log(data); }
// });
}
/*
* Pick a random element out of an array.
*
* @param {array} array - An array.
*
* @return - An element of the array.
*
* Sometimes I wonder if comprehensive documentation is really worth it, y'know?
*/
function randElement(array) {
var element = '';
while(element == '') {
element = array[Math.floor(Math.random() * array.length)];
}
return element;
}
/*
* Shuffle an array.
*
* @param {array} array - An array.
*
* @return {array} - The input array, with elements in random order.
*/
function shuffle(array) {
var counter = array.length;
var t, i;
while(counter > 0) {
i = Math.floor(Math.random() * counter--);
t = array[counter];
array[counter] = array[i];
array[i] = t;
}
return array;
}
/*
* Just returns a hardcoded database for testing purposes.
*
* So, typically we'd want to load the database from the server,
* where it's typically located at database.csv. But most browsers (including
* the one I'm using for testing) disallow websites or files from accessing
* other files. Good for security, bad for testing. This just provides a raw
* database string for testing, removing the need for accessing outside files.
* I've commented out the code that loads the database from the server (and
* likewise posts results back). Make sure this gets removed and the
* aforementioned code gets uncommented before deployment.
*
* @return {string} - Hardcoded snapshot of the database, circa August 01, 2014.
*/
function uglyHardcodedDatabase() {
return "Horse Names,Admiral's Voyage,Alpha,American Flag,Atomic Rain,Backtalk,Best Present Ever,Bodemeister,Cajun Beat,California Chrome,Celtic Ash,Chocolate Candy,Colorado King,Commando,Creative Cause,Daddy Long Legs,Daddy Nose Best,Dance With Fate,Danza,Delhi,Discreet Marq,Done Talking,Dunkirk,Eight Thirty,El Padrino,Falling Sky,Flying Private,Frac Daddy,Freesian Fire,Genie,Gentle Savage,Ghost Zapper,Gold Coin,Golden Soul,Greek Money,Harry's Holiday,Highest Honors,Ice Box,Indian Blessing,Intense Holiday,June Cleaver,Kauai King,Kid Cruz,Kiss Moon,Kona Gold,Lady Secret,Lemon Punch,Liaison,Luv Gov,Magical Band,Magic Hour,Matterhorn,Midnight Hawk,Midnight Interlude,Midnight Taboo,Mind Bender,Mind's Eyes,Mister Hot Stuff,Misty Morn,Moccasin,Mucho Macho Man,Optimizer,Orb,Papa Clem,Papa Jerry,Peter Pan,Please Explain,Prime Directive,Rachel Alexandra,Rousing Sermon,Sabercat,Sacred Light,Samraat,Scottish Chieftan,Scrimshaw,Sizzling Gold,Somali Lemonade,Star Shoot,Stay Thirsty,St. Liam,Stop Time,Sugar Shock,Summer Bird,Summer Tan,Sunshine Forever,Sweet Vendetta,Take The Points,Terrain,The Bard,The Green Monkey,Thor's Echo,Thunder Gulch,Token Special,Twenty Grand,Twilight Ridge,Twinspired,Union Rags,Westside Bernie,Wicked Strong,Wildcat Red,Wild Rush\nH-Guess,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,1,1,2,3,0,0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,1,1,1,1,0,2,0,0,0,0,0,0,0,1,0,0,2,0,0,1,0,0,0,0,1,0,1,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,1\nW-Guess,1,0,1,0,0,1,0,0,0,1,0,1,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,1,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,2,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,0,1,0,0,1,0,0,0,0,0\nME-Guess,0,1,1,1,0,0,1,0,0,0,1,1,0,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,2,0,0,1,1,0,1,1,1,0,0,0,0,0,0,1,1,1,1,0,1,1,0,0,2,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,2,1,0,0,1,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,2,0,1,0,0,0,0\nWeed Names,Accidental Tourist,Ace of Spades,Air Force One,Allen Wrench,American Dream,Armageddon,Aruel,Asteroid,Atmosphere,Beehive,Big Bud,Bio-Jesus,Black Domina,Blue Bayou,Blue Moon,Brain Child,Buddha's Sister,Cherry Pie,Chocolope,Cracker Jack,Dairy Queen,Don Cristo,Double Dream,Dr. Grinspoon,Dutch Treat,Early Garage,Early Girl,Edelweiss,El Jeffe,Emperor's Cut,Galactic Jack,Glass Slipper,God's Gift,Godzilla,Grand Hustle,Grand Platinum,Gun,Hawaiian Fire,Holy Grail,Hubba Bubba,Incredible Hulk,Jack's Cleaner,Jane Doe,Jilly Bean,Johnnie Walker,Johnny's Tonic,Joker's Revenge,King Henry,King Louis,King's Bread,L.A. Confidential,Life Saver,Liquid Butter,Little Devil,Loud Dream,Louis XIII,Low Rider,Lucky Charms,Medicine Man,MK Ultra,Morning Glory,Morning Star,Motorcity Whip,Mr. Nice Guy,Muchacho Man,Neville's Maze,Nevil's Wreck,Orange Moon,Outlaw,Pennies From Heaven,Pennywise,Polite With a Punch,Private Reserve,Professor Chaos,Purple Arrow,Qrazy Train,Rare Darkness,Rated R,Red Bull,Richie Rich,Rocklock,Royal Dwarf,Sapphire Star,Shark Shock,Shipwreck,Smoke on the Water,Soul Shine,Sour Grapes,Sunny Side Up,Sunset Sherbert,Sweet Tooth,Tasmanian Devil,Uncle Pete,Watermelon Tormaline,Whitaker Blues,White Gold,White Rhino,White Russian,Willies Wonder,Yumboldt\nH-Guess,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,1,0,0,2,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,1,0,1,0,0,0,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,1,2,0,0,0,1,0,0,1,1,0,0,1,0,0,0,2\nW-Guess,1,1,0,0,1,1,0,0,1,0,0,1,0,0,0,2,0,1,1,2,0,0,2,2,1,0,0,1,1,1,2,1,1,1,1,1,0,0,0,0,1,0,1,3,1,0,1,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,1,0,0,1,1,1,0,0,0,1,0,0,0,0,0,1,1,0,1,0,0,1,0,0,1,0,0,0,0,0,0\nME-Guess,0,0,0,0,0,0,0,0,0,0,3,0,0,1,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,3,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,3,0,0,0,0,0,0,0,0,0,0,0,0\nMind's Eye,Accho,Adios Amigos,Albany New York,Apples and Oranges,Apricot,Autumn Haze,Avalanche,Backlot Tour,Ballyhoo,Beethoven's Bust,Bob's Your Uncle,Boogeyman,Buried Treasure,Burnt Toast,Cannery Row,Captain America,Chardonnay,Charm Bracelet,Cliff's Surprise,Court Jester,Crystal Ship,Detour,Dollar Bill,Dolphin's Fin,Double Barrel,Double Jeopardy,Dust-up,Earth Worm,Executive Suite,Fog,Fortunate Son,Galaxy,General Patton,Ghost Town,Giddy Up and Go,Grape Nuts,Grey Flannel,Gupta,High Tide,Hummer,Irish Eyes,Jazz Age,Joni Mitchell,Lemonade,Let's Hear It for the Boy,Lieutenant Dan,Long Tall Sally,Low Tide,Macho Nacho,Milk & Cookies,Miranda's Miracle,Monkey Wrench,Muldoon,Par Excellence,Pepper,Poseidon's Trident,Quote-Unquote,Sacrificial Lamb,Sealed With a Kiss,Space Needle,Stealth Bomber,Strange Dawn,Ukulele,Uncle Ben,Undeterred Goon,Unlawful Entry,Upstart,Up Up and Away,Waikiki Wave,Weekender,Holy Roller,Inclement Weather,Pop Rox,Masquerade,Monkey's Uncle,Bible Thumper,Shazam,Photon Torpedo,Devil's Workshop,Frankenbutter,Dung Beetle,Black Astronaut,Bowtie Rasta,Carbon Credit,High Fructose Porn Syrup,Tiny Tim,Free Raisin,Chrysalis,Porkchop Parody,White Man's Burden,Red Menace,Bletchley Park,High as Balls,What a Crowd,Boob Glue,Culture Shock,Marriage Sow,Ka-ching!,Alien Visitation,Police Brutality\nH-Guess,1,1,0,0,1,0,0,0,0,0,1,0,0,1,0,0,2,0,0,0,1,1,0,0,0,3,0,0,0,0,0,1,1,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,1,0,2,0,0,0,0,3,0,0,0,1,0,0,0,1,1,0,0,0,0,1,0,2,0,0,0,0,2,0,0,0,0,0,1,0,0,0,1,0,0,1,0,0,0,0\nW-Guess,0,1,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,0,0,0,0,0,1,0,0,0,2,0,0,0,0,1,1,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,1,0\nME-Guess,0,0,0,1,1,0,0,0,0,0,0,1,0,0,0,3,0,0,0,0,0,0,1,0,0,0,1,1,0,1,0,0,0,1,0,0,1,1,1,0,0,0,0,0,1,1,1,0,0,0,0,0,1,0,0,0,0,0,0,0,2,0,0,1,1,0,1,0,0,0,0,1,0,0,0,0,0,1,1,1,2,0,0,0,0,0,1,1,0,1,0,0,1,1,0,0,0,0,2,2";
}