diff --git a/js/game.js b/js/game.js
index 9c7a756..04b89a0 100644
--- a/js/game.js
+++ b/js/game.js
@@ -4,429 +4,699 @@
* requires sudoku.js, jstorage
*/
-/* defaults settings */
+var game;
+
+// Main
+$(document).ready(function () {
+
+ Game.start();
+ Binds.optionBinds();
+});
+
+// Default settings
var Settings = {
- difficulty: 'medium',
- show_conflicts: false
+
+ difficulty: 'medium',
+ show_conflicts: false
};
-var Game = {
- difficulties: {test_solved: 1, easy: 20, medium: 40, hard: 55, expert: 64},
+// The Game
+var Game = (function () {
+
+ var difficulties = {
+
+ 'test_solved': 1,
+ 'easy': 20,
+ 'medium': 40,
+ 'hard': 55,
+ 'expert': 64
+ };
- grid: {}, user_values: [], game_values: [], time_elapsed: '', s_elapsed: 0,
+ var grid = {};
+ var user_values = [];
+ var game_values = [];
+ var time_elapsed = '';
+ var s_elapsed = 0;
+ var timer = null;
+
+ // Start the game
+ function start () {
+
+ // Initialize a full internal sudoku grid
+ grid = CU.Sudoku.generate();
+
+ // Load previous game, or create a new one
+ var loaded = loadState();
+ if (loaded) {
+ // load previous values into memory
+ grid.rows = game_values;
+ }
+ else {
+ // or create a new game by culling full sudoku grid
+ CU.Sudoku.cull(grid, difficulties[Settings.difficulty]);
+ }
+
+ // Setup display
+ Display.gameTable();
+ if (loaded) {
+
+ // display stored user values
+ Display.loadUserValues();
+ }
+
+ // remove ending screen if visible
+ Display.hideEnding();
+
+ // Start time elapsed display
+ startTimer();
+ }
+
+ function startTimer () {
+
+ // reset timer display
+ Display.resetTimer();
- start: function(){
- this.grid = CU.Sudoku.generate();
- var loaded = this.loadState();
- if(loaded){
- this.grid.rows = this.game_values;
- }else{
- CU.Sudoku.cull(this.grid, this.difficulties[Settings.difficulty]);
- }
- Display.gameTable();
- if(loaded){
- /* insert and display stored user values */
- Display.loadUserValues();
- }
- $('.ending').fadeOut(function(){$(this).remove();});
- $('#timer').html('0:00:00');
- Timer.start(function(arr){
- Display.timer(arr[0]);
- Game.time_elapsed = arr[0];
- Game.s_elapsed = Math.floor(arr[1]/1000);
- $.jStorage.set('s_elapsed', JSON.stringify(Game.s_elapsed));
- }, Game.s_elapsed * 1000);
- },
+ timer = new Timer();
+ timer.start(function (arr) {
- solved: function(){
- Timer.stop();
- Display.end();
- },
+ Display.timer(arr[0]);
+ time_elapsed = arr[0];
+ s_elapsed = Math.floor(arr[1]/1000);
+ $.jStorage.set('s_elapsed', JSON.stringify(s_elapsed));
+ }, s_elapsed * 1000);
+ }
+
+ function stopTimer () {
+
+ if (timer) {
+
+ timer.stop();
+ }
+ }
+
+ function solved () {
+
+ stopTimer();
+ Display.showEnding();
+ }
- saveState: function(){
- this.user_values = this.fillRows();
- this.game_values = this.fillRows();
- var $rows = $('.game-row');
- for(var r = 0; r < 9; r++){
- var $row = $($rows[r]);
- var $cells = $row.children('.cell');
- for(var c = 0; c < 9; c++){
- $cell = $($cells[c]);
- var value = parseInt($cell.text());
- if($cell.is('.game-value')){
- this.game_values[r][c] = value;
- }else if(value > 0){
- this.user_values[r][c] = value;
- }
- }
+ function saveState () {
+
+ user_values = fillRows();
+ game_values = fillRows();
+
+ var $rows = $('.game-row');
+
+ for (var r = 0; r < 9; r++) {
+
+ var $row = $($rows[r]);
+ var $cells = $row.children('.cell');
+
+ for (var c = 0; c < 9; c++) {
+
+ $cell = $($cells[c]);
+ var value = parseInt($cell.text(), 10);
+ if ($cell.is('.game-value')) {
+
+ game_values[r][c] = value;
}
- $.jStorage.set('game_values', JSON.stringify(this.game_values));
- $.jStorage.set('user_values', JSON.stringify(this.user_values));
- },
+ else if (value > 0) {
+
+ user_values[r][c] = value;
+ }
+ }
+ }
+
+ $.jStorage.set('game_values', JSON.stringify(game_values));
+ $.jStorage.set('user_values', JSON.stringify(user_values));
+ }
+
+ function loadState () {
+
+ var _game_values = JSON.parse($.jStorage.get('game_values')) || [];
+ var _user_values = JSON.parse($.jStorage.get('user_values')) || [];
+
+ s_elapsed = 0;
+
+ if (_user_values.length > 0) {
+
+ user_values = _user_values;
+ }
+ else {
+
+ return false;
+ }
+
+ if (_game_values.length > 0) {
+
+ game_values = _game_values;
+ }
+ else {
- loadState: function(){
- var _game_values = JSON.parse($.jStorage.get('game_values')) || [];
- var _user_values = JSON.parse($.jStorage.get('user_values')) || [];
- this.s_elapsed = 0;
- if(_user_values.length > 0){
- this.user_values = _user_values;
- }else{
- return false;
- }
- if(_game_values.length > 0){
- this.game_values = _game_values;
- }else{
- return false;
- }
- this.s_elapsed = JSON.parse($.jStorage.get('s_elapsed')) || 0;
- return true;
+ return false;
+ }
+
+ s_elapsed = JSON.parse($.jStorage.get('s_elapsed')) || 0;
+ return true;
+ }
+
+ function flushState () {
+
+ $.jStorage.set('game_values', JSON.stringify([]));
+ $.jStorage.set('user_values', JSON.stringify([]));
+ $.jStorage.set('s_elapsed', '0');
+ }
+
+ // return zero-filled grid array
+ // used by saveState
+ function fillRows () {
+
+ var rows = [];
+
+ for (var row = 0; row < 9; row++) {
+
+ var cols = [];
+ for (var col = 0; col < 9; col++) {
+
+ cols[col] = 0;
+ }
+
+ rows[row] = cols;
+ }
+
+ return rows;
+ }
+
+ return {
+
+ // get access
+ 'getUserValues': function () {
+
+ return user_values;
},
+ 'getTimeElapsed': function () {
- flushState: function(){
- $.jStorage.set('game_values', JSON.stringify([]));
- $.jStorage.set('user_values', JSON.stringify([]));
- $.jStorage.set('s_elapsed', '0');
+ return time_elapsed;
},
- /**
- * return zero-filled grid array
- * used by saveState
- */
- fillRows: function(){
- var rows = [];
- for(var row = 0; row < 9; row++)
- {
- var cols = [];
- for(var col = 0; col < 9; col++){
- cols[col] = 0;
- }
- rows[row] = cols;
- }
- return rows;
+ // public methods
+ 'flushState': flushState,
+ 'saveState': saveState,
+ 'solved': solved,
+ 'start': start,
+ 'stopTimer': stopTimer,
+
+ // return internal sudoku grid object
+ 'getGrid': function () {
+
+ return grid;
}
-};
+ };
+}());
var Display = {
- /* show game table */
- gameTable: function(){
- $game = $('#game');
- $game.empty();
- var table = $(document.createElement('table'));
- for(var r = 0; r < 9; r++){
- var tr = $(document.createElement('tr')).addClass('game-row');
- for(var c = 0; c < 9; c++){
- var td = $(document.createElement('td')).addClass('cell');
- if(Game.grid.rows[r][c] !== 0){
- td.html(Game.grid.rows[r][c]).addClass('game-value');
- }
- if(r === 0){
- td.addClass('first-row');
- }
- if(c === 0){
- td.addClass('first-col');
- }
- if((c+1) % 3 === 0){
- td.addClass('mini-right');
- }
- if((r+1) % 3 === 0){
- td.addClass('mini-bottom');
- }
- tr.append(td);
- }
- table.append(tr);
+
+ /* show game table */
+ 'gameTable': function () {
+
+ $game = $('#game');
+ $game.empty();
+
+ var $table = $(document.createElement('table'));
+
+ for (var r = 0; r < 9; r++) {
+
+ var $tr = $(document.createElement('tr')).addClass('game-row');
+
+ for (var c = 0; c < 9; c++) {
+
+ var $td = $(document.createElement('td')).addClass('cell');
+ if (Game.getGrid().rows[r][c] !== 0) {
+
+ $td.html(Game.getGrid().rows[r][c]).addClass('game-value');
}
- $game.append(table);
- Binds.tableBinds();
- },
+
+ if (r === 0) {
- loadUserValues: function(){
- for(var r = 0; r < 9; r ++){
- for(var c = 0; c < 9; c++){
- if(Game.user_values[r][c] > 0){
- $(this.getCell(c,r)).html(Game.user_values[r][c]);
- Game.grid.rows[r][c] = Game.user_values[r][c];
- }
- }
- }
- },
+ $td.addClass('first-row');
+ }
+
+ if (c === 0) {
+
+ $td.addClass('first-col');
+ }
+
+ if ((c+1) % 3 === 0) {
+
+ $td.addClass('mini-right');
+ }
+
+ if ((r+1) % 3 === 0) {
+
+ $td.addClass('mini-bottom');
+ }
+
+ $tr.append($td);
+ }
+
+ $table.append($tr);
+ }
- end: function(){
- var dialog = $(document.createElement('div')).addClass('ending').hide();
- var heading = $(document.createElement('h2')).html('Congratulations!');
- var text = $(document.createElement('p')).html('You solved this puzzle in ' + Game.time_elapsed);
- dialog.append(heading);
- dialog.append(text);
- var tweet = $(document.createElement('p'));
- var link = $(document.createElement('a')).addClass('button');
- link.attr('href',
- 'http://twitter.com/home?status=I+finished+a+'+Settings.difficulty+'+sudoku+puzzle+in+'+encodeURI(Game.time_elapsed)+'++Try+and+beat+my+time+at+http%3A%2F%2Fsudokunomi.com');
- link.text('Tweet your time!');
- dialog.append(tweet.append(link));
-
- $('body').append(dialog.fadeIn());
- },
+ $game.append($table);
+ Binds.tableBinds();
+ },
- timer: function(str){
- $('#timer').text(str);
- },
+ 'loadUserValues': function () {
+
+ for (var r = 0; r < 9; r ++) {
+
+ for (var c = 0; c < 9; c++) {
+
+ if (Game.getUserValues()[r][c] > 0) {
+
+ $(this.getCell(c,r)).html(Game.getUserValues()[r][c]);
+ Game.getGrid().rows[r][c] = Game.getUserValues()[r][c];
+ }
+ }
+ }
+ },
- entryDialog: function(cell){
- var $this = $(cell);
- /* dialog to enter value */
- var dialog = $(document.createElement('div')).addClass('input-dialog').hide();
- var form = $(document.createElement('form')).addClass('input-form');
- var input = $('').addClass('input-input');
- dialog.append(form.append(input));
- /* display dialog */
- $('.input-dialog').remove();
- var cords = $this.offset();
- dialog.css('top', (cords.top /*+ $this.height()/2*/));
- dialog.css('left', (cords.left /*+ $this.width()/2*/));
- $('body').append(dialog.fadeTo(200, 0.8));
- $('.input-input').focus();
- $('.input-form').on('submit',function(){
- return false;
- });
- $('.input-input').on('keydown',function(e){
- var keyCode = e.keyCode || e.which;
- var $selected = $('.cell-selected:not(.game-value)');
- var pos = Display.getCellPosition($selected.get(0));
- if((keyCode > 47 && keyCode < 58) || (keyCode > 93 && keyCode < 106)){
- if($selected.length > 0){
- var value = String.fromCharCode((keyCode > 93 ? keyCode - 48 : keyCode));
- Game.grid.setValue(pos[0],pos[1], value);
- $this.html((value === 0 ? '' : value));
- }
- }else{
- Game.grid.setValue(pos[0],pos[1], 0);
- $this.empty();
- }
- Display.killDialog();
- Display.findConflicts();
- Game.saveState();
- });
- },
+ 'showEnding': function () {
+
+ var dialog = $(document.createElement('div')).addClass('ending').hide();
+ var heading = $(document.createElement('h2')).html('Congratulations!');
+ var text = $(document.createElement('p')).html('You solved this puzzle in ' + Game.getTimeElapsed());
+
+ dialog.append(heading);
+ dialog.append(text);
+
+ var tweet = $(document.createElement('p'));
+ var link = $(document.createElement('a')).addClass('button');
+
+ link.attr('href', 'http://twitter.com/home?status=I+finished+a+'+Settings.difficulty+'+sudoku+puzzle+in+'+encodeURI(Game.getTimeElapsed())+'++Try+and+beat+my+time+at+http%3A%2F%2Fsudokunomi.com');
+ link.text('Tweet your time!');
+ dialog.append(tweet.append(link));
+
+ $('body').append(dialog.fadeIn());
+ },
+
+ 'hideEnding': function () {
+
+ $('.ending').fadeOut(function () {
+
+ $(this).remove();
+ });
+ },
+
+ 'timer': function (str) {
+
+ $('#timer').text(str);
+ },
+
+ 'resetTimer': function () {
+
+ this.timer('0:00:00');
+ },
- killDialog: function(){
- $('.input-dialog').fadeOut(200, function(){$(this).remove();});
- },
+ 'entryDialog': function (cell) {
- getCellPosition: function(cell){
- var $this = $(cell);
- var $rows = $('.game-row');
- for(var r = 0; r < 9; r++){
- var $row = $($rows[r]);
- var $cells = $row.children('.cell');
- for(var c = 0; c < 9; c++){
- $cell = $($cells[c]);
- if($cell.get(0) == $this.get(0)){
- return [c,r];
- }
- }
+ var $this = $(cell);
+
+ /* dialog to enter value */
+ var dialog = $(document.createElement('div')).addClass('input-dialog').hide();
+ var form = $(document.createElement('form')).addClass('input-form');
+ var input = $('').addClass('input-input');
+
+ dialog.append(form.append(input));
+
+ /* display dialog */
+ $('.input-dialog').remove();
+ var cords = $this.offset();
+ dialog.css('top', (cords.top /*+ $this.height()/2*/));
+ dialog.css('left', (cords.left /*+ $this.width()/2*/));
+
+ $('body').append(dialog.fadeTo(200, 0.8));
+ $('.input-input').focus();
+ $('.input-form').on('submit', function () {
+
+ return false;
+ });
+
+ $('.input-input').on('keydown', function (e) {
+
+ var keyCode = e.keyCode || e.which;
+ var $selected = $('.cell-selected:not(.game-value)');
+ var pos = Display.getCellPosition($selected.get(0));
+
+ if ((keyCode > 47 && keyCode < 58) || (keyCode > 93 && keyCode < 106)) {
+
+ if($selected.length > 0){
+
+ var value = String.fromCharCode((keyCode > 93 ? keyCode - 48 : keyCode));
+ Game.getGrid().setValue(pos[0],pos[1], value);
+ $this.html((value === 0 ? '' : value));
}
- return false;
- },
+
+ }
+ else {
+
+ Game.getGrid().setValue(pos[0],pos[1], 0);
+ $this.empty();
+ }
+
+ Display.killDialog();
+ Display.findConflicts();
+ Game.saveState();
+ });
+ },
- getCell: function(col,row){
- var $rows = $('.game-row');
- for(var r = 0; r < 9; r++){
- var $row = $($rows[r]);
- var $cells = $row.children('.cell');
- for(var c = 0; c < 9; c++){
- $cell = $($cells[c]);
- if(col == c && row == r){
- return $cell.get(0);
- }
- }
- }
- return false;
- },
+ 'killDialog': function () {
- moveSelect: function(direction){
- var position = [];
- $selected = $('.cell-selected');
- if($selected.length > 0){
- position = this.getCellPosition($('.cell-selected').get(0));
- }else{
- position = [0,0];
- }
- /* kill any open dialog */
- this.killDialog();
- switch(direction){
- case 'up':
- if(position[1] > 0)
- position[1] -= 1;
- break;
- case 'down':
- if(position[1] < 8)
- position[1] += 1;
- break;
- case 'right':
- if(position[0] < 8)
- position[0] += 1;
- break;
- case 'left':
- if(position[0] >0)
- position[0] -= 1;
- break;
- }
- /* remove prev selection */
- $('.cell-selected').removeClass('cell-selected');
- /* apply new selection */
- $(this.getCell(position[0], position[1])).addClass('cell-selected');
- },
+ $('.input-dialog').fadeOut(200, function () {
- /* highlight /all/ conflicting cells */
- findConflicts: function(){
- /* remove previous */
- $('.conflict').removeClass('conflict');
- if(Settings.show_conflicts){
- /* find conflicts */
- var $rows = $('.game-row');
- for(var r = 0; r < 9; r++){
- var $row = $($rows[r]);
- var $cells = $row.children('.cell');
- for(var c = 0; c < 9; c++){
- if(!Game.grid.cellValid(c, r)){
- conflicts = true;
- var $cell = $($cells[c]);
- $cell.addClass('conflict');
- }
- }
- }
- }
- /* check if solved */
- if(Game.grid.gridSolved()){
- Game.solved();
- }
+ $(this).remove();
+ });
+ },
+
+ 'getCellPosition': function (cell){
+
+ var $this = $(cell);
+ var $rows = $('.game-row');
+
+ for (var r = 0; r < 9; r++) {
+
+ var $row = $($rows[r]);
+ var $cells = $row.children('.cell');
+ for (var c = 0; c < 9; c++) {
+
+ $cell = $($cells[c]);
+
+ if ($cell.get(0) == $this.get(0)) {
+
+ return [c,r];
+ }
+ }
}
-};
-
-var Binds = {
- /* binds for after table draw */
- tableBinds: function(){
- $('.cell:not(.game-value)').on('click', function(e){
- Binds.cellClick(this);
- });
- $(document).off('keydown').on('keydown', function (e) {
- if(!$(e.target).is('#options-wrap') && !$(e.target).is('.input-input')){
- var keyCode = e.keyCode || e.which, arrow = {left: 37, up: 38, right: 39, down: 40 };
- var arrows = [37,38,39,40];
- if(arrows.indexOf(keyCode) !== -1){
- e.preventDefault();
- }
- switch (keyCode) {
- case arrow.left:
- Display.moveSelect('left');
- break;
- case arrow.up:
- Display.moveSelect('up');
- break;
- case arrow.right:
- Display.moveSelect('right');
- break;
- case arrow.down:
- Display.moveSelect('down');
- break;
- case 13:
- var $selected = $('.cell-selected');
- if($selected.length > 0){
- Display.entryDialog($selected.get(0));
- }
- return false; /* do not pass enter/return through */
- }
- /* enter cell values from the keyboard */
- if((keyCode > 47 && keyCode < 58) || (keyCode > 93 && keyCode < 106)){
- var $selected = $('.cell-selected:not(.game-value)');
- if($selected.length > 0){
- var value = String.fromCharCode((keyCode > 93 ? keyCode - 48 : keyCode));
- var pos = Display.getCellPosition($selected.get(0));
- Game.grid.setValue(pos[0],pos[1], value);
- $cell.html((value === 0 ? '' : value));
- Display.findConflicts();
- Game.saveState();
- }
- }
- }
- });
- },
- optionBinds: function(){
- $('#opt-newpuzzle').on('click', function(){
- Timer.stop();
- Game.flushState();
- Game.start();
- });
- $('#opt-difficulty').on('change', function(){
- Timer.stop();
- Settings.difficulty = $(this).val();
- Game.flushState();
- Game.start();
- $(this).blur();
- });
- $('#opt-showhints').on('change', function(){
- Settings.show_conflicts = ($(this).is(':checked') ? true : false);
- Display.findConflicts();
- });
- $('#opt-printpuzzle').on('click', function(){window.print();});
- },
+ return false;
+ },
- /* empty cell click */
- cellClick: function(elem){
- $('.cell').removeClass('cell-selected');
- $(elem).addClass('cell-selected');
- Display.entryDialog(elem);
+ 'getCell': function (col, row) {
+
+ var $rows = $('.game-row');
+ for (var r = 0; r < 9; r++) {
+
+ var $row = $($rows[r]);
+ var $cells = $row.children('.cell');
+
+ for (var c = 0; c < 9; c++) {
+
+ $cell = $($cells[c]);
+
+ if (col == c && row == r){
+
+ return $cell.get(0);
+ }
+ }
}
-};
-/* run */
-$(document).ready(function(){
- Game.start();
- Binds.optionBinds();
-});
+ return false;
+ },
-/* utils */
-var Util = {
- /* http://stackoverflow.com/a/1830844/933653 */
- isNumeric: function(n){
- return !isNaN(parseFloat(n)) && isFinite(n);
+ 'moveSelect': function (direction) {
+
+ var position = [];
+
+ var $selected = $('.cell-selected');
+
+ if ($selected.length > 0) {
+
+ position = this.getCellPosition($('.cell-selected').get(0));
}
-}
+ else {
-var Timer = {
- start_time: null,
- id: null,
- callback: null,
-
- msToDuration: function(dur){
- var dur_s = dur / 1000;
- var hours = Math.floor(dur_s / 3600);
- var minutes = Math.floor((dur_s % 3600) / 60);
- var seconds = Math.floor((dur_s % 3600) % 60);
-
- var str = '';
- str += (hours > 0) ? hours + ':' : '0:';
- str += (minutes > 0) ? (minutes < 10 ? '0' + minutes + ':' : minutes + ':') : '00:';
- str += (seconds > 0) ? (seconds < 10 ? '0' + seconds : seconds) : '00';
+ position = [0,0];
+ }
+
+ // kill any open dialog
+ this.killDialog();
+ switch (direction) {
+
+ case 'up':
+
+ if (position[1] > 0) {
+
+ position[1] -= 1;
+ }
+ break;
+
+ case 'down':
+
+ if (position[1] < 8) {
+
+ position[1] += 1;
+ }
+ break;
+
+ case 'right':
+
+ if (position[0] < 8) {
+
+ position[0] += 1;
+ }
+ break;
+
+ case 'left':
+
+ if (position[0] >0) {
+
+ position[0] -= 1;
+ }
+ break;
+ }
+
+ // remove prev selection
+ $('.cell-selected').removeClass('cell-selected');
+
+ // apply new selection
+ $(this.getCell(position[0], position[1])).addClass('cell-selected');
+ },
+
+ // highlight /all/ conflicting cells
+ 'findConflicts': function () {
+
+ // remove previous
+ $('.conflict').removeClass('conflict');
+
+ if (Settings.show_conflicts) {
+
+ // find conflicts
+ var $rows = $('.game-row');
+ for (var r = 0; r < 9; r++) {
+
+ var $row = $($rows[r]);
+ var $cells = $row.children('.cell');
- return str;
- },
+ for (var c = 0; c < 9; c++) {
+
+ if (!Game.getGrid().cellValid(c, r)) {
+
+ conflicts = true;
+ var $cell = $($cells[c]);
+ $cell.addClass('conflict');
+ }
+ }
+ }
+ }
- start: function(callback, offset){
- this.stop();
- this.callback = callback;
- this.start_time = new Date();// - 3540000; test hour roll over
- this.start_time = this.start_time - offset;
- this.id = setInterval(Timer.run, 1000);
- },
- stop: function(){
- if(this.id){
- clearInterval(this.id);
- }
- },
+ // check if solved
+ if (Game.getGrid().gridSolved()) {
+
+ Game.solved();
+ }
+ }
+};
- run: function(){
- var now = new Date();
- Timer.callback([(Timer.msToDuration(now - Timer.start_time)), (now - Timer.start_time)]);
+var Binds = {
+
+ // binds for after table draw
+ 'tableBinds': function () {
+
+ var $selected;
+
+ $('.cell:not(.game-value)').on('click', function (e) {
+
+ Binds.cellClick(this);
+ });
+
+ $(document).off('keydown').on('keydown', function (e) {
+
+ if (!$(e.target).is('#options-wrap') && !$(e.target).is('.input-input')) {
+
+ var keyCode = e.keyCode || e.which, arrow = {left: 37, up: 38, right: 39, down: 40 };
+ var arrows = [37,38,39,40];
+
+ if (arrows.indexOf(keyCode) !== -1) {
+
+ e.preventDefault();
+ }
+
+ switch (keyCode) {
+
+ case arrow.left:
+
+ Display.moveSelect('left');
+ break;
+
+ case arrow.up:
+
+ Display.moveSelect('up');
+ break;
+
+ case arrow.right:
+
+ Display.moveSelect('right');
+ break;
+
+ case arrow.down:
+
+ Display.moveSelect('down');
+ break;
+
+ case 13:
+
+ $selected = $('.cell-selected');
+ if ($selected.length > 0) {
+
+ Display.entryDialog($selected.get(0));
+ }
+ // do not pass enter/return through
+ return false;
+ }
+
+ // enter cell values from the keyboard
+ if ((keyCode > 47 && keyCode < 58) || (keyCode > 93 && keyCode < 106)) {
+
+ $selected = $('.cell-selected:not(.game-value)');
+
+ if ($selected.length > 0) {
+
+ var value = String.fromCharCode((keyCode > 93 ? keyCode - 48 : keyCode));
+ var pos = Display.getCellPosition($selected.get(0));
+ Game.getGrid().setValue(pos[0],pos[1], value);
+ $cell.html((value === 0 ? '' : value));
+ Display.findConflicts();
+ Game.saveState();
+ }
+ }
+ }
+ });
+ },
+
+ 'optionBinds': function () {
+
+ $('#opt-newpuzzle').on('click', function () {
+
+ Game.stopTimer();
+ Game.flushState();
+ Game.start();
+ });
+
+ $('#opt-difficulty').on('change', function () {
+
+ Game.stopTimer();
+ Settings.difficulty = $(this).val();
+ Game.flushState();
+ Game.start();
+ $(this).blur();
+ });
+
+ $('#opt-showhints').on('change', function () {
+
+ Settings.show_conflicts = ($(this).is(':checked') ? true : false);
+ Display.findConflicts();
+ });
+
+ $('#opt-printpuzzle').on('click', function () {
+
+ window.print();
+ });
+ },
+
+ // empty cell click
+ 'cellClick': function (elem) {
+
+ $('.cell').removeClass('cell-selected');
+ $(elem).addClass('cell-selected');
+ Display.entryDialog(elem);
+ }
+};
+
+var Timer = function () {
+
+ var start_time = null;
+ var id = null;
+ var timerCallback = null;
+ var self;
+
+ function msToDuration (dur) {
+
+ var dur_s = dur / 1000;
+ var hours = Math.floor(dur_s / 3600);
+ var minutes = Math.floor((dur_s % 3600) / 60);
+ var seconds = Math.floor((dur_s % 3600) % 60);
+
+ var str = '';
+ str += (hours > 0) ? hours + ':' : '0:';
+ str += (minutes > 0) ? (minutes < 10 ? '0' + minutes + ':' : minutes + ':') : '00:';
+ str += (seconds > 0) ? (seconds < 10 ? '0' + seconds : seconds) : '00';
+
+ return str;
+ }
+
+ function start (callback, offset) {
+
+ stop();
+
+ timerCallback = callback;
+ start_time = new Date();
+ start_time = start_time - offset;
+ id = setInterval(run, 1000);
+ }
+
+ function stop () {
+
+ if (id) {
+
+ clearInterval(id);
+ }
+ }
+
+ function run () {
+
+ var now = new Date();
+ if (timerCallback) {
+
+ timerCallback([(msToDuration(now - start_time)), (now - start_time)]);
+ }
+ }
+
+ return {
+
+ 'start': start,
+ 'stop': stop
+ };
+};
+
+// general utilities
+var Util = (function () {
+
+ return {
+
+ /* http://stackoverflow.com/a/1830844/933653 */
+ 'isNumeric': function (n) {
+
+ return !isNaN(parseFloat(n)) && isFinite(n);
}
-}
\ No newline at end of file
+ };
+})();
\ No newline at end of file