var title = "Diligence" var glyphs = "http://michaelmcelroy.net/glyphs/png.php?text=Diligence&size=36&foreground_color=001122&background_color=EEEEEE&transparent_color=EEEEEE&code=33567b92a093262ab6ee03211280c203" // Diligence // 2009 December 6 // Copyrighted in 2009 by Michael McElroy of MichaelMcElroy.NET // 2009-01-01: 9786031307360658579094567235194172886917753829676676022856475893171872547929897555158444081671999176 // 2009-12-06: 0708093374021390517843345679944025835263765805867641076544548041534060337928514278476031485380444941 /* defined in page.js var $ = function (id) { return (document . getElementById (id)); }; */ var interrupt = function (e) { detent = true; if (typeof (e) == "undefined") e = window . event; var number = e . keyCode; var cancel = false; if ((48 <= number) && (number <= 57)) {game . select_digit (number - 48); cancel = true;} if ((96 <= number) && (number <= 105)) {game . select_digit (number - 96); cancel = true;} if ((number == 8) || (number == 46)) {game . remove_digit (); cancel = true;} if (cancel) { try {e . stopPropagation ();} catch (exception) {} try {e . preventDefault ();} catch (exception) {} } return; }; var remove_subnodes = function (node) { while (node . hasChildNodes ()) {node . removeChild (node . firstChild);} return; }; var import_javascript = function (javascript) { if ($ ("mm_socket") == null) { var division = document . createElement ("div"); division . id = "mm_socket"; document . body . appendChild (division); } script = document . createElement ("script"); script . type = "text/javascript"; script . src = javascript; remove_subnodes ($ ("mm_socket")); $ ("mm_socket") . appendChild (script); return; }; var set_solution = function (solution) { game . solution = solution; game . render (); return; }; var reset = function () { game . reset (); game . render (); return; }; var Diligence = function () { this . mask = "yyyymmdd"; this . date = ""; this . date_offset = 5; this . block_count = 100; this . block_count_per_line = 20; this . block_height = 32; this . block_width = 32; this . button_count = 10; this . button_spacing = 1; this . line_spacing = 1; this . digits_padding = 16; this . date_padding = 16; this . correct_color = "#335533"; this . incorrect_color = "#773333"; this . corrected_color = "#333377"; this . mask_color = "#BB7733"; this . mask_hyphen_color = "#CC8844"; this . date_color = "#777777"; this . date_hyphen_color = "#888888"; this . next_color = "#BB9933"; this . button_color = "#001122"; this . solution = null; this . current_count = 0; // number of digits that the player is expected to know this . start_count = 1; // number of digits the player is expected to memorize on the first day -- changing this would affect anyone currently playing the game this . digits = ""; this . guess = null; // holds the most recently entered digit if the digit is incorrect this . missed = new Array (); // index -> true if the digit was missed this . divisions = new Array (); // cache -- use 'this . division (id)' to access the elements this . initialize = function () { var picture = document . createElement ("img"); var caches = new Array ("digit-0", "digit-1", "digit-2", "digit-3", "digit-4", "digit-5", "digit-6", "digit-7", "digit-8", "digit-9", "letter-y", "letter-m", "letter-d", "hyphen"); try {window . document . addEventListener ("keydown", interrupt, false);} catch (exception) {} try {window . document . attachEvent ("onkeydown", interrupt);} catch (exception) {} picture . src = glyphs; picture . style . cursor = "pointer"; picture . style . marginBottom = "16px"; picture . onclick = function () {window . location . assign (".");}; this . division ("container") . appendChild (picture); this . division ("container") . appendChild (this . division ("date")); this . division ("container") . appendChild (this . division ("digits")); this . division ("container") . appendChild (this . division ("buttons")); this . division ("container") . appendChild (this . division ("about")); this . division ("container") . appendChild (this . division ("instructions")); this . division ("container") . appendChild (this . division ("help")); this . division ("container") . style . position = "relative"; this . division ("container") . style . marginBottom = "32px"; for (var index = 0; index < caches . length; index = index + 1) { this . division ("container") . appendChild (this . division ("cache_" + index)); this . division ("cache_" + index) . style . height = "0px"; this . division ("cache_" + index) . style . width = "0px"; this . division ("cache_" + index) . style . backgroundImage = "url(./pictures/" + caches [index] + ".png)"; } this . division ("date") . style . height = ((this . date_padding * 0) + ((this . block_height + this . line_spacing) * 1) - this . line_spacing) + "px"; this . division ("date") . style . width = ((this . date_padding * 2) + (this . block_width * this . block_count_per_line)) + "px"; this . division ("date") . style . position = "relative"; this . division ("date") . style . border = "#EEEEEE 2px solid"; this . division ("date") . style . backgroundColor = "#EEEEEE"; this . division ("date") . style . marginBottom = "16px"; this . division ("date") . style . display = "block"; this . division ("date") . style . overflow = "hidden"; this . division ("digits") . style . height = ((this . digits_padding * 2) + ((this . block_height + this . line_spacing) * Math . ceil (this . block_count / this . block_count_per_line)) - this . line_spacing) + "px"; this . division ("digits") . style . width = ((this . digits_padding * 2) + (this . block_width * this . block_count_per_line)) + "px"; this . division ("digits") . style . position = "relative"; this . division ("digits") . style . border = "#DDDDDD 2px solid"; this . division ("digits") . style . backgroundColor = "#FFFFFF"; this . division ("digits") . style . display = "none"; this . division ("digits") . style . overflow = "hidden"; this . division ("buttons") . style . height = (this . block_height * 1) + "px"; this . division ("buttons") . style . width = ((this . block_width * this . button_count) + (this . button_spacing * (this . button_count - 1))) + "px"; this . division ("buttons") . style . marginTop = "16px"; this . division ("buttons") . style . marginLeft = "auto"; this . division ("buttons") . style . marginRight = "auto"; this . division ("buttons") . style . position = "relative"; this . division ("buttons") . style . display = "none"; for (var index = 0; index < 10; index = index + 1) { var row = Math . floor (index / this . block_count_per_line); var column = index % this . block_count_per_line; this . division ("date") . appendChild (this . division ("date_" + index)); this . division ("date_" + index) . style . height = this . block_height + "px"; this . division ("date_" + index) . style . width = this . block_width + "px"; this . division ("date_" + index) . style . backgroundColor = "#FFFFFF"; this . division ("date_" + index) . style . color = "#FFFFFF"; this . division ("date_" + index) . style . position = "absolute"; this . division ("date_" + index) . style . cursor = "pointer"; this . division ("date_" + index) . style . top = ((this . block_height + this . line_spacing) * row) + "px"; this . division ("date_" + index) . style . left = (this . date_padding + this . block_width * (this . date_offset + column)) + "px"; this . division ("date_" + index) . appendChild (this . division ("date_highlight_" + index)); this . division ("date_highlight_" + index) . style . position = "absolute"; this . division ("date_highlight_" + index) . style . top = "0px"; this . division ("date_highlight_" + index) . style . left = "0px"; this . division ("date_highlight_" + index) . style . height = Math . floor (this . block_height / 2) + "px"; this . division ("date_highlight_" + index) . style . width = (this . block_width) + "px"; this . division ("date_highlight_" + index) . style . backgroundColor = "#FFFFFF"; this . division ("date_highlight_" + index) . style . opacity = "0.10"; if (index > 7) {this . division ("digit_" + index) . style . display = "none";} this . missed [index] = false; } for (var index = 0; index < this . block_count; index = index + 1) { var row = Math . floor (index / this . block_count_per_line); var column = index % this . block_count_per_line; this . division ("digits") . appendChild (this . division ("digit_" + index)); this . division ("digit_" + index) . style . height = this . block_height + "px"; this . division ("digit_" + index) . style . width = this . block_width + "px"; this . division ("digit_" + index) . style . backgroundColor = "#FFFFFF"; this . division ("digit_" + index) . style . color = "#FFFFFF"; this . division ("digit_" + index) . style . position = "absolute"; this . division ("digit_" + index) . style . cursor = "pointer"; this . division ("digit_" + index) . style . top = (this . digits_padding + (this . block_height + this . line_spacing) * row) + "px"; this . division ("digit_" + index) . style . left = (this . digits_padding + this . block_width * column) + "px"; this . division ("digit_" + index) . appendChild (this . division ("digit_highlight_" + index)); this . division ("digit_highlight_" + index) . style . position = "absolute"; this . division ("digit_highlight_" + index) . style . top = "0px"; this . division ("digit_highlight_" + index) . style . left = "0px"; this . division ("digit_highlight_" + index) . style . height = Math . floor (this . block_height / 2) + "px"; this . division ("digit_highlight_" + index) . style . width = (this . block_width) + "px"; this . division ("digit_highlight_" + index) . style . backgroundColor = "#FFFFFF"; this . division ("digit_highlight_" + index) . style . opacity = "0.10"; if (index > 7) {this . division ("digit_" + index) . style . display = "none";} this . missed [index] = false; } for (var index = 0; index < this . button_count; index = index + 1) { this . division ("buttons") . appendChild (this . division ("button_" + index)); this . division ("button_" + index) . mm_value = index; this . division ("button_" + index) . mm_game = this; this . division ("button_" + index) . style . height = this . block_height + "px"; this . division ("button_" + index) . style . width = this . block_width + "px"; this . division ("button_" + index) . style . backgroundColor = this . button_color; this . division ("button_" + index) . style . color = "#FFFFFF"; this . division ("button_" + index) . style . position = "absolute"; this . division ("button_" + index) . style . cursor = "pointer"; this . division ("button_" + index) . style . top = "0px"; this . division ("button_" + index) . style . left = ((this . block_width + this . button_spacing) * index) + "px"; this . division ("button_" + index) . style . backgroundImage = "url(./pictures/digit-" + index + ".png)"; this . division ("button_" + index) . onclick = function () {this . mm_game . select_digit (this . mm_value);}; this . division ("button_" + index) . appendChild (this . division ("button_highlight_" + index)); this . division ("button_highlight_" + index) . style . position = "absolute"; this . division ("button_highlight_" + index) . style . top = "0px"; this . division ("button_highlight_" + index) . style . left = "0px"; this . division ("button_highlight_" + index) . style . height = Math . floor (this . block_height / 2) + "px"; this . division ("button_highlight_" + index) . style . width = (this . block_width) + "px"; this . division ("button_highlight_" + index) . style . backgroundColor = "#FFFFFF"; this . division ("button_highlight_" + index) . style . opacity = "0.1"; } this . division ("about") . style . display = "block"; this . division ("about") . style . width = "400px"; this . division ("about") . style . padding = "16px"; this . division ("about") . style . backgroundColor = "#DDDDDD"; this . division ("about") . style . textAlign = "justify"; this . division ("about") . style . fontSize = "14px"; this . division ("about") . style . marginTop = "16px"; this . division ("about") . style . marginLeft = "auto"; this . division ("about") . style . marginRight = "auto"; this . division ("about") . appendChild (document . createTextNode ("Diligence is a game where the goal is to memorize 100 digits over 100 days. To start a new game, enter today's date using the number keys on your keyboard. To continue a game, enter the date of the day that you started the game.")); this . division ("instructions") . style . display = "none"; this . division ("instructions") . style . width = "500px"; this . division ("instructions") . style . padding = "16px"; this . division ("instructions") . style . backgroundColor = "#DDDDDD"; this . division ("instructions") . style . textAlign = "justify"; this . division ("instructions") . style . fontSize = "14px"; this . division ("instructions") . style . marginTop = "16px"; this . division ("instructions") . style . marginLeft = "auto"; this . division ("instructions") . style . marginRight = "auto"; this . division ("instructions") . appendChild (document . createTextNode ("As you are enter the numbers that you have memorized, the digits will be highlighted with one of three colors; green for correct digits, blue for corrected digits, and red for incorrect digits.")); this . division ("help") . style . display = "none"; this . division ("help") . style . width = "500px"; this . division ("help") . style . padding = "16px"; this . division ("help") . style . backgroundColor = "#DDDDDD"; this . division ("help") . style . textAlign = "center"; this . division ("help") . style . fontSize = "14px"; this . division ("help") . style . marginTop = "16px"; this . division ("help") . style . marginLeft = "auto"; this . division ("help") . style . marginRight = "auto"; this . division ("help") . style . fontSize = "14px"; return; }; this . reset = function () { this . date = ""; return; }; this . date_is_valid = function (date) { var valid = false; var today = new Date (); today = today . getFullYear () + "-" + (((today . getMonth () + 1) < 10) ? "0" : "") + (today . getMonth () + 1) + "-" + ((today . getDate () < 10) ? "0" : "") + today . getDate (); if (date >= "2009-01-01") { if (date <= today) { var pieces = date . split ("-"); var date_a = new Date (pieces [0], pieces [1] - 1, pieces [2]); var date_b = date_a . getFullYear () + "-" + (((date_a . getMonth () + 1) < 10) ? "0" : "") + (date_a . getMonth () + 1) + "-" + ((date_a . getDate () < 10) ? "0" : "") + date_a . getDate (); valid = date == date_b; } } return (valid); }; this . age = function (date) { var age = 0; var today = new Date (); today = today . getFullYear () + "-" + (((today . getMonth () + 1) < 10) ? "0" : "") + (today . getMonth () + 1) + "-" + ((today . getDate () < 10) ? "0" : "") + today . getDate (); while ((date < today) && (age < this . block_count)) { var pieces = date . split ("-"); var date_a = new Date (pieces [0], pieces [1] - 1, pieces [2] - 0 + 1); var date_b = date_a . getFullYear () + "-" + (((date_a . getMonth () + 1) < 10) ? "0" : "") + (date_a . getMonth () + 1) + "-" + ((date_a . getDate () < 10) ? "0" : "") + date_a . getDate (); date = date_b; age = age + 1; } return (age); }; this . select_digit = function (digit) { if (this . solution == null) { this . date = this . date + digit; if (this . date . length == 8) { var copy = this . date . substring (0, 4) + "-" + this . date . substring (4, 6) + "-" + this . date . substring (6, 8); if (this . date_is_valid (copy)) { var difference = this . age (copy); this . current_count = difference + this . start_count - 1; window . setTimeout ('import_javascript ("./api/solution.js.php?date=' + copy + '&count=' + this . block_count + '");', 250); } else { window . setTimeout ('reset ();', 250); } } } else { if (this . digits . length < this . current_count) { if ((this . digits + digit) == this . solution . substring (0, this . digits . length + 1)) { this . digits = this . digits + digit; this . guess = null; } else { this . guess = digit; this . missed [this . digits . length] = true; } } } this . render (); return; }; this . remove_digit = function () { if (this . solution == null) { if (this . date . length > 0) { this . date = this . date . substring (0, this . date . length - 1); } } this . render (); return; }; this . render = function (target) { if (typeof (target) != "undefined") {target . appendChild (this . divisions ["container"]);} if (this . solution == null) { var map = new Array (0, 1, 2, 3, 5, 6, 8, 9); var index = 0; var limit = this . date . length; while (index < limit) { var character = this . date . substring (index, index + 1); this . division ("date_" + map [index]) . style . display = "block"; this . division ("date_" + map [index]) . style . backgroundImage = "url(./pictures/digit-" + character + ".png)"; this . division ("date_" + map [index]) . style . backgroundColor = this . mask_color; index = index + 1; } index = index; limit = this . mask . length; while (index < limit) { var character = this . mask . substring (index, index + 1); this . division ("date_" + map [index]) . style . display = "block"; this . division ("date_" + map [index]) . style . backgroundImage = "url(./pictures/letter-" + character + ".png)"; this . division ("date_" + map [index]) . style . backgroundColor = this . date_color; index = index + 1; } this . division ("date_" + 4) . style . display = "block"; this . division ("date_" + 4) . style . backgroundImage = "url(./pictures/hyphen.png)"; this . division ("date_" + 4) . style . backgroundColor = (this . date . length >= 4) ? this . mask_hyphen_color : this . date_hyphen_color; this . division ("date_" + 7) . style . display = "block"; this . division ("date_" + 7) . style . backgroundImage = "url(./pictures/hyphen.png)"; this . division ("date_" + 7) . style . backgroundColor = (this . date . length >= 6) ? this . mask_hyphen_color : this . date_hyphen_color; this . division ("about") . style . display = "block"; this . division ("instructions") . style . display = "none"; } else { var index = 0; var limit = this . digits . length; while (index < limit) { this . division ("digit_" + index) . style . display = "block"; this . division ("digit_" + index) . style . backgroundImage = "url(./pictures/digit-" + this . digits . substring (index, index + 1) + ".png)"; this . division ("digit_" + index) . style . backgroundColor = this . missed [index] ? this . corrected_color : this . correct_color; index = index + 1; } if (this . guess != null) { this . division ("digit_" + index) . style . display = "block"; this . division ("digit_" + index) . style . backgroundImage = "url(./pictures/digit-" + this . guess + ".png)"; this . division ("digit_" + index) . style . backgroundColor = this . incorrect_color; index = index + 1; } if (this . digits . length == this . current_count) { this . division ("buttons") . style . display = "none"; this . division ("help") . style . display = "block"; remove_subnodes (this . division ("help")); if (this . current_count < this . block_count) { index = index; limit = index + ((this . current_count == 0) ? this . start_count : 1); while (index < limit) { this . division ("digit_" + index) . style . display = "block"; this . division ("digit_" + index) . style . backgroundImage = "url(./pictures/digit-" + this . solution . substring (index, index + 1) + ".png)"; this . division ("digit_" + index) . style . backgroundColor = this . next_color; index = index + 1; } this . division ("help") . appendChild (document . createTextNode ("the next number to memorize is highlighted in yellow")); this . division ("help") . appendChild (document . createElement ("br")); this . division ("help") . appendChild (document . createElement ("br")); this . division ("help") . appendChild (document . createTextNode ("return tomorrow for the following digit")); } else { this . division ("help") . appendChild (document . createElement ("br")); this . division ("help") . appendChild (document . createTextNode ("thank you for playing -- use today's date to start a new round")); this . division ("help") . appendChild (document . createElement ("br")); this . division ("help") . appendChild (document . createElement ("br")); } } index = index; limit = this . block_count; while (index < limit) { this . division ("digit_" + index) . style . display = "none"; this . division ("digit_" + index) . style . backgroundImage = ""; index = index + 1; } this . division ("digits") . style . display = "block"; this . division ("about") . style . display = "none"; this . division ("instructions") . style . display = (this . digits . length < this . current_count) ? "block" : "none"; } return; }; this . division = function (id) { if ((this . divisions [id] == null) || (typeof (this . divisions [id]) == "undefined")) { // find the division in the HTM this . divisions [id] = $ (id); } if ((this . divisions [id] == null) || (typeof (this . divisions [id]) == "undefined")) { // create the division this . divisions [id] = document . createElement ("div"); this . divisions [id] . id = id; } return (this . divisions [id]); } };