Author: scottbw
Date: Fri Mar 2 16:41:18 2012
New Revision: 1296299
URL: http://svn.apache.org/viewvc?rev=1296299&view=rev
Log:
Various improvements to the Sudoku widget to make it more reliable and look a
bit nicer and less like a lump of test code. Also, the widget no longer
auto-launches a new game, which reduces the likelihood of a new game collision.
See WOOKIE-149.
Added:
incubator/wookie/trunk/widgets/sudoku/splash.png (with props)
Modified:
incubator/wookie/trunk/widgets/sudoku/config.xml
incubator/wookie/trunk/widgets/sudoku/icon.png
incubator/wookie/trunk/widgets/sudoku/main.js
incubator/wookie/trunk/widgets/sudoku/style.css
incubator/wookie/trunk/widgets/sudoku/sudoku.html
Modified: incubator/wookie/trunk/widgets/sudoku/config.xml
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/config.xml?rev=1296299&r1=1296298&r2=1296299&view=diff
==============================================================================
--- incubator/wookie/trunk/widgets/sudoku/config.xml (original)
+++ incubator/wookie/trunk/widgets/sudoku/config.xml Fri Mar 2 16:41:18 2012
@@ -17,12 +17,24 @@
-->
<widget xmlns="http://www.w3.org/ns/widgets"
id="http://www.getwookie.org/widgets/sudoku"
- version="1.0" height="380" width="520">
- <name>Wave Test: Sudoku</name>
- <description>Google Wave Sudoku Widget</description>
- <icon src="icon.png"/>
+ version="1.0" height="380" width="480">
+ <name>Sudoku</name>
+ <description>Sudoku</description>
<content src="sudoku.html"/>
<author>Austin Chau</author>
- <license>Unknown (c) Google.com</license>
+ <license>
+Copyright [2007] [Austin Chau]
+Licensed under the Apache License, Version 2.0 (the "License"); you may not
+use this file except in compliance with the License. You may obtain a copy of
+the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+License for the specific language governing permissions and limitations
+under the License
+ </license>
<feature name="http://wave.google.com" required="true"/>
</widget>
Modified: incubator/wookie/trunk/widgets/sudoku/icon.png
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/icon.png?rev=1296299&r1=1296298&r2=1296299&view=diff
==============================================================================
Binary files - no diff available.
Modified: incubator/wookie/trunk/widgets/sudoku/main.js
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/main.js?rev=1296299&r1=1296298&r2=1296299&view=diff
==============================================================================
--- incubator/wookie/trunk/widgets/sudoku/main.js (original)
+++ incubator/wookie/trunk/widgets/sudoku/main.js Fri Mar 2 16:41:18 2012
@@ -20,22 +20,17 @@ window.DEBUG = false;
window.PUZZLE_KEY = 'PUZZLE';
window.SOLUTION_KEY = 'SOLUTION';
window.CELL_STATE_RE = /^cell_([0-9]+)$/;
-window.PENALTY_STATE_RE = /^penalty_(.+)$/;
+window.PENALTY_STATE_RE = /^penalty_(.+)$/;
// sudoku generator object
window.generator = null;
// game data
-window.gameReset = false;
-window.waveReady = false;
window.puzzleArray = [];
window.solutionArray = [];
window.liveGameArray = [];
window.playerRecords = [];
-// viewer data
-window.viewerId = null;
-
// status messages on top
window.messages = [];
window.MAX_MESSAGES = 5;
@@ -44,84 +39,48 @@ function init() {
window.generator = new sudoku.SudokuGenerator();
if (window.DEBUG) {
- jQuery('#debugConsole').css({display: 'block'});
+ $('#debugConsole').css({display: 'block'});
initClickHandlers();
} else {
- jQuery('#debugConsole').css({display: 'none'});
+ $('#debugConsole').css({display: 'none'});
}
- if (window.wave) {
-
+ if (window.wave) {
+ //
+ // Start collaborative play
+ //
wave.setParticipantCallback(function() {
-
- if (wave.getViewer() != null && window.viewerId == null) {
- window.viewerId = wave.getViewer().getDisplayName();
- // init the area heading
updateMessages();
updateRankingDisplay();
- }
- wave.setStateCallback(waveStateChanged);
- });
-
+ });
+ wave.setStateCallback(waveStateChanged);
}
-}
-
-function appendMessage(msg) {
- if (messages.length >= MAX_MESSAGES) {
- messages.pop();
- }
- messages.unshift(msg);
-
- updateMessages();
-}
-
-function updateMessages() {
-
- var html = [];
- html.push('<b>Updates:</b><br><br>');
- html.push(messages.join('<br>'));
-
- jQuery('#messages').html(html.join(''));
-}
+}
-function debug(msg) {
- jQuery('#debug').prepend(msg + '<br/>');
-}
-
-function waveStateChanged() {
- if (!window.wave) {
- return;
- }
-
- if (window.gameReset) {
- var keys = wave.getState().getKeys();
- var done = true;
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- if (window.CELL_STATE_RE.test(key) ||
- window.PENALTY_STATE_RE.test(key)) {
- done = false;
- break;
- }
- }
- if (done) {
- window.gameReset = false;
- initGame();
- return;
- } else {
- return;
- }
+function waveStateChanged() {
+ //
+ // Check if the game has reset by comparing the current solution
+ // in the window with the wave state solution
+ //
+ if (wave.getState().get("SOLUTION") && wave.getState().get("SOLUTION") !=
JSON.stringify(window.solutionArray) ) {
+ debug("game was reset");
+ window.puzzleArray = JSON.parse(get(PUZZLE_KEY));
+ window.solutionArray = JSON.parse(get(SOLUTION_KEY));
+ window.liveGameArray = window.puzzleArray.concat([]); // clone
liveGameArray from puzzleArray
+ showGame();
+
+ } else {
+ //
+ // Check for another player's move
+ //
+ updateGameProgress();
}
-
- if (!window.waveReady) {
- window.waveReady = true;
- initGame();
- return;
- }
-
- updateGameProgress();
}
-
+
+//
+// Update game board with events
+// from wave state
+//
function updateGameProgress() {
var keys = wave.getState().getKeys();
for (var i = 0; i < keys.length; ++i) {
@@ -159,124 +118,46 @@ function updateGameProgress() {
}
}
-function getPlayerRecord(playerName) {
- var ret = null;
-
- for (var i = 0; i < playerRecords.length; i++) {
- var record = playerRecords[i];
- if (record.name == playerName) {
- ret = record;
- break;
- }
- }
-
- return ret;
-}
-
-function newPlayerRecord(playerName) {
- playerRecord = {};
- playerRecord.name = playerName;
- playerRecord.points = 0;
- playerRecord.penalty = 0;
- playerRecords.push(playerRecord);
- return playerRecord;
-}
-
-function addPoint(playerName) {
-
- var playerRecord = getPlayerRecord(playerName);
-
- if (playerRecord == null) {
- playerRecord = newPlayerRecord(playerName);
- }
-
- playerRecord.points++;
-
- updateRankingDisplay();
-}
-
-function updateRankingDisplay() {
-
- // sort player record by points
- playerRecords.sort(function(a, b) {
- return (b.points - b.penalty) - (a.points - a.penalty);
- });
-
- var html = [];
- html.push('<b>Ranking:</b><br><br>');
-
- for (var i = 0; i < playerRecords.length; i++) {
- var playerRecord = playerRecords[i];
- var name = playerRecord.name;
- var total = playerRecord.points - playerRecord.penalty;
- var rank = i + 1;
- html.push('<b>' + rank + '. </b>');
- html.push(name + ' (' + total + ')');
- html.push('<br/>');
- }
-
- jQuery('#rankingDisplay').html(html.join(''));
-}
-
-function initClickHandlers() {
-
- jQuery('#clear').click(function() {
- jQuery('#debug').empty();
- });
-
- jQuery('#reset').click(function() {
- resetAllStates();
- });
-
- jQuery('#print').click(function() {
- printAllStates();
- });
-
-}
-
-function hasExistingGame() {
- var ret = false;
-
- if (get(PUZZLE_KEY) != null) {
- ret = true;
- }
-
- return ret;
-}
-
-function showGame() {
+function showGame() {
+ $('#splash').hide();
displaySudoku(window.puzzleArray.join(''));
updateGameProgress();
- jQuery('#loading').css('display', 'none');
}
-
-function initGame() {
- debug('viewer id: ' + viewerId);
-
- if (hasExistingGame()) {
- debug("has existing game");
- // there is an existing game, read the data in
- window.puzzleArray = JSON.parse(get(PUZZLE_KEY));
- window.solutionArray = JSON.parse(get(SOLUTION_KEY));
- } else {
- debug("generating new game");
- // you are the first player, you need to generate the game!
- var data = generateNewPuzzle();
- window.puzzleArray = data.puzzle;
- window.solutionArray = data.solution;
- set(PUZZLE_KEY, JSON.stringify(window.puzzleArray));
- set(SOLUTION_KEY, JSON.stringify(window.solutionArray));
- }
-
- window.liveGameArray = window.puzzleArray.concat([]); // clone liveGameArray
from puzzleArray
-
- showGame();
-}
-
+
+function newGame(){
+ var data = generateNewPuzzle();
+
+ if (window.wave){
+ //
+ // Create the game data and send it, but don't change our local state
+ //
+ debug("created new game - submitting delta");
+ var delta = {};
+ delta[PUZZLE_KEY] = JSON.stringify(data.puzzle);
+ delta[SOLUTION_KEY] = JSON.stringify(data.solution);
+ //
+ // Clear keys for each cell
+ //
+ for (var i=0;i<81;i++){
+ delta["cell_"+i] = null;
+ }
+ wave.getState().submitDelta(delta);
+ } else {
+ //
+ // In single player mode, just start the game
+ //
+ window.puzzleArray = data.puzzle;
+ window.solutionArray = data.solution;
+ window.liveGameArray = window.puzzleArray.concat([]); // clone
liveGameArray from puzzleArray
+ showGame();
+ }
+}
+
+//
+// Create the puzzle
+//
function generateNewPuzzle() {
-
var data = {};
-
try {
var generator = new sudoku.SudokuGenerator();
var puzzleString = generator.generate();
@@ -290,35 +171,27 @@ function generateNewPuzzle() {
} catch (e) {
data = generateNewPuzzle();
}
-
return data;
}
-function quitGame() {
- displayActualSolution();
-}
-
function cleanup() {
// - hide the sudoku display
// - remove all previous event listeners on all cells
// - remove all css class attr on all cells
- // - hide comment box if it is open
- // - hide timer & reset timer
-
- jQuery('#display').hide();
+
+ $('#display').hide();
for (var i=0;i<81;i++) {
var cellId = '#cell_' + i;
- jQuery(cellId).unbind();
- jQuery(cellId).removeClass('blankCell');
- jQuery(cellId).removeClass('givenCell');
- jQuery(cellId).removeClass('solutionCell');
+ $(cellId).unbind();
+ $(cellId).removeClass('blankCell');
+ $(cellId).removeClass('givenCell');
+ $(cellId).removeClass('solutionCell');
}
}
function isGameOver() {
-
if (liveGameArray.length == 0) {
// the game isn't fully initialized yet
return false;
@@ -328,15 +201,15 @@ function isGameOver() {
}
function onGameOver() {
-
if (confirm('Game over. New game?')) {
// now reset the state callback function
- resetAllStates();
+ resetAllStates();
+ newGame();
}
}
function closeCell(arrayIndex, value, playerName) {
- var cell = jQuery('#cell_' + arrayIndex);
+ var cell = $('#cell_' + arrayIndex);
cell.html(value);
cell.addClass('solutionCell');
@@ -361,23 +234,17 @@ function closeCell(arrayIndex, value, pl
}
function onRightMove(arrayIndex, value) {
-
// update the local live game array
window.liveGameArray[arrayIndex] = value;
-
// report state change to save
// TODO
- set('cell_' + arrayIndex, window.viewerId);
-
- closeCell(arrayIndex, value, window.viewerId);
+ set('cell_' + arrayIndex, getViewer());
+ closeCell(arrayIndex, value, getViewer());
}
function onWrongMove() {
-
- var key = 'penalty_' + window.viewerId; //.replace(/ /g, '*');
-
+ var key = 'penalty_' + getViewer(); //.replace(/ /g, '*');
var value = get(key);
-
if (value == null) {
value = 0
}
@@ -399,8 +266,6 @@ function blurOnCell(inputBox) {
cell.empty();
cell.bind('click', handleCellInput);
}
-
- //checkGame();
}
function getCellValue(arrayIndex) {
@@ -413,19 +278,19 @@ function isInputCorrect(arrayIndex, inpu
function handleCellInput() {
- var arrayIndex = parseInt(jQuery(this).attr('id').replace('cell_', ''));
+ var arrayIndex = parseInt($(this).attr('id').replace('cell_', ''));
debug('ans: ' + getCellValue(arrayIndex));
- jQuery(this).unbind('click');
+ $(this).unbind('click');
//clearAnnounce();
- var cell = jQuery(this);
+ var cell = $(this);
var cellValue = (cell.html() == '')?'':'value=' +cell.html();
- var inputBox = jQuery('<input maxlength=1 ' + cellValue
+ var inputBox = $('<input maxlength=1 ' + cellValue
+ ' type=text id=cellOpenBox>');
cell.html(inputBox);
@@ -473,16 +338,16 @@ function displaySudoku(sudokuStr) {
if (value == 0) {
// this is a blank cell
- jQuery(cellId).click(handleCellInput);
- jQuery(cellId).html('');
+ $(cellId).click(handleCellInput);
+ $(cellId).html('');
} else {
// this is a given cell
- jQuery(cellId).html(value);
+ $(cellId).html(value);
}
}
- jQuery('#display').fadeIn(500);
- jQuery('#quit').show();
+ $('#display').fadeIn(500);
+ $('#info').fadeIn(500);
}
function get(key) {
@@ -494,87 +359,160 @@ function get(key) {
}
function set(key, value) {
- var obj = {};
- obj[key] = value;
- if (window.wave) {
- wave.getState().submitDelta(obj);
- }
-}
-
-function rm(key) {
- var obj = {};
- obj[key] = null;
if (window.wave) {
- wave.getState().submitDelta(obj);
+ wave.getState().submitValue(key,value);
}
}
-function getViewerId() {
- var ret = null;
-
+function getViewer() {
+ var ret = "you";
if (window.wave) {
-
ret = wave.getViewer().getDisplayName();
}
-
return ret;
}
-function printAllStates() {
-
- if (!window.wave) {
- return;
- }
-
- var html = [];
-
- var keys = wave.getState().getKeys();
-
- for (var i = 0; i < keys.length; ++i) {
- var key = keys[i];
- var value = wave.getState().get(key);
-
- html.push(key + ' = ' + value);
- html.push('<br>');
- }
-
- debug(html.join(''));
-}
-
function resetAllStates() {
if (window.wave) {
- var obj = {};
-
// reset all game data
window.puzzleArray = [];
window.solutionArray = [];
window.liveGameArray = [];
window.playerRecords = [];
window.messages = [];
- window.gameReset = true;
-
- obj[window.PUZZLE_KEY] = null;
- obj[window.SOLUTION_KEY] = null;
-
- var keys = wave.getState().getKeys();
-
- for (var i = 0; i < keys.length; i++) {
- var key = keys[i];
- if (window.CELL_STATE_RE.test(key) ||
- window.PENALTY_STATE_RE.test(key)) {
- obj[key] = null;
- }
- }
- debug(JSON.stringify(obj));
-
- wave.getState().submitDelta(obj);
-
// clear info
updateMessages();
updateRankingDisplay();
}
+}
+
+///////////////
+// PLAYERS //
+///////////////
+
+function appendMessage(msg) {
+ if (messages.length >= MAX_MESSAGES) {
+ messages.pop();
+ }
+ messages.unshift(msg);
+ updateMessages();
+}
+
+function updateMessages() {
+ var html = [];
+ html.push('<b>Updates:</b><br><br>');
+ html.push(messages.join('<br>'));
+
+ $('#messages').html(html.join(''));
+}
+
+function newPlayerRecord(playerName) {
+ playerRecord = {};
+ playerRecord.name = playerName;
+ playerRecord.points = 0;
+ playerRecord.penalty = 0;
+ playerRecords.push(playerRecord);
+ return playerRecord;
+}
+
+function addPoint(playerName) {
+ var playerRecord = getPlayerRecord(playerName);
+ if (playerRecord == null) {
+ playerRecord = newPlayerRecord(playerName);
+ }
+ playerRecord.points++;
+ updateRankingDisplay();
+}
+
+function updateRankingDisplay() {
+
+ // sort player record by points
+ playerRecords.sort(function(a, b) {
+ return (b.points - b.penalty) - (a.points - a.penalty);
+ });
+
+ var html = [];
+ html.push('<b>Ranking:</b><br><br>');
+
+ for (var i = 0; i < playerRecords.length; i++) {
+ var playerRecord = playerRecords[i];
+ var name = playerRecord.name;
+ var total = playerRecord.points - playerRecord.penalty;
+ var rank = i + 1;
+ html.push('<b>' + rank + '. </b>');
+ html.push(name + ' (' + total + ')');
+ html.push('<br/>');
+ }
+
+ $('#rankingDisplay').html(html.join(''));
+}
+
+function getPlayerRecord(playerName) {
+ var ret = null;
+
+ for (var i = 0; i < playerRecords.length; i++) {
+ var record = playerRecords[i];
+ if (record.name == playerName) {
+ ret = record;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+///////////////
+// DEBUGGING //
+///////////////
+
+function debug(msg) {
+ $('#debug').prepend(msg + '<br/>');
+}
+
+function initClickHandlers() {
+
+ $('#clear').click(function() {
+ $('#debug').empty();
+ });
+
+ $('#reset').click(function() {
+ resetAllStates();
+ });
+
+ $('#print').click(function() {
+ printAllStates();
+ });
+
+ $('#cheat').click(function() {
+ cheat();
+ });
+}
+
+function cheat(){
+ onGameOver();
+}
+
+function printAllStates() {
+
+ if (!window.wave) {
+ return;
+ }
+
+ var html = [];
+
+ var keys = wave.getState().getKeys();
+
+ for (var i = 0; i < keys.length; ++i) {
+ var key = keys[i];
+ var value = wave.getState().get(key);
+
+ html.push(key + ' = ' + value);
+ html.push('<br>');
+ }
+
+ debug(html.join(''));
}
Added: incubator/wookie/trunk/widgets/sudoku/splash.png
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/splash.png?rev=1296299&view=auto
==============================================================================
Binary file - no diff available.
Propchange: incubator/wookie/trunk/widgets/sudoku/splash.png
------------------------------------------------------------------------------
svn:mime-type = application/octet-stream
Modified: incubator/wookie/trunk/widgets/sudoku/style.css
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/style.css?rev=1296299&r1=1296298&r2=1296299&view=diff
==============================================================================
--- incubator/wookie/trunk/widgets/sudoku/style.css (original)
+++ incubator/wookie/trunk/widgets/sudoku/style.css Fri Mar 2 16:41:18 2012
@@ -16,13 +16,32 @@
*/
body {
font: icon;
- font-size: 15pt !important;
+ font-size: 15pt !important;
+ border: 0px;
+ margin: 0px;
}
#main {
- width: 800px;
+ width: 480px;
+ height: 376px;
text-align: center;
-}
+}
+
+#splash {
+ float:left;
+ width: 376px;
+ height: 376px;
+ text-align: center;
+ background: url('splash.png');
+}
+
+#splash button {
+ margin-top: 200px;
+ font-size: 30px;
+ box-shadow: 0 0 5px rgba(0, 0, 255, 1);
+ -webkit-box-shadow: 0 0 5px rgba(81, 203, 238, 1);
+
+}
#gameDisplay {
float: left;
@@ -31,20 +50,22 @@ body {
#messages {
height: 100px;
border: 0px solid red;
- color: black;
text-align: left;
}
#info {
- width: 300px;
- float: left;
- margin-left: 20px;
+ width: 100px;
+ height: 100%;
+ float: left;
+ background: #555;
+ color: #EEE;
+ margin-left: 0px;
+ padding-left: 4px;
font-size: 13px;
}
#rankingDisplay {
- border: 0px dotted red;
- color: black;
+ color: #EEE;
text-align: left;
padding: 2px;
}
Modified: incubator/wookie/trunk/widgets/sudoku/sudoku.html
URL:
http://svn.apache.org/viewvc/incubator/wookie/trunk/widgets/sudoku/sudoku.html?rev=1296299&r1=1296298&r2=1296299&view=diff
==============================================================================
--- incubator/wookie/trunk/widgets/sudoku/sudoku.html (original)
+++ incubator/wookie/trunk/widgets/sudoku/sudoku.html Fri Mar 2 16:41:18 2012
@@ -28,14 +28,16 @@
<input type=button id=clear value='Clear Debug'/>
<input type=button id=reset value='Reset All States'/>
<input type=button id=print value='Print All States'/>
+ <input type=button id=cheat value='Finish game'/>
<br>
<div id='debug'></div>
</div>
-<br>
<div align="left">
<div id=main>
+ <div id='splash'>
+ <button id='start' onclick="newGame()">Start</button>
+ </div>
<div id='gameDisplay'>
- <div id='loading'><br>loading ... </div>
<div id='display'>
<table cellspacing="0">
<tr>
@@ -180,7 +182,7 @@
<table id="grid8" cellspacing="0">
<tr>
<td id=cell_57></td>
- <td id=cell_58></td>
+ <td id=cell_58></td>
<td id=cell_59></td>
</tr>
<tr>