[bknr-cvs] r2336 - in branches/trunk-reorg: bknr/web/src bknr/web/src/web projects/lisp-ecoop/src projects/scrabble/src projects/scrabble/website thirdparty/hunchentoot-0.14.7 thirdparty/parenscript/src thirdparty/slime
hhubner at common-lisp.net
hhubner at common-lisp.net
Thu Jan 17 16:36:33 UTC 2008
Author: hhubner
Date: Thu Jan 17 11:36:28 2008
New Revision: 2336
Added:
branches/trunk-reorg/projects/scrabble/website/scrabble-resizable-attempt.js
Modified:
branches/trunk-reorg/bknr/web/src/bknr-web.asd
branches/trunk-reorg/bknr/web/src/web/handlers.lisp
branches/trunk-reorg/bknr/web/src/web/menu.lisp
branches/trunk-reorg/bknr/web/src/web/templates.lisp
branches/trunk-reorg/bknr/web/src/web/web-utils.lisp
branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd
branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp
branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp
branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp
branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp
branches/trunk-reorg/projects/scrabble/src/web.lisp
branches/trunk-reorg/projects/scrabble/website/scrabble.html
branches/trunk-reorg/projects/scrabble/website/scrabble.js
branches/trunk-reorg/thirdparty/hunchentoot-0.14.7/misc.lisp
branches/trunk-reorg/thirdparty/parenscript/src/js-macrology.lisp
branches/trunk-reorg/thirdparty/slime/slime.el
branches/trunk-reorg/thirdparty/slime/swank.lisp
Log:
Save pending lisp-ecoop and scrabble changes.
Modified: branches/trunk-reorg/bknr/web/src/bknr-web.asd
==============================================================================
--- branches/trunk-reorg/bknr/web/src/bknr-web.asd (original)
+++ branches/trunk-reorg/bknr/web/src/bknr-web.asd Thu Jan 17 11:36:28 2008
@@ -32,7 +32,8 @@
:xhtmlgen
:puri
:bknr-datastore
- :bknr-data-impex)
+ :bknr-data-impex
+ :parenscript)
:components ((:file "packages")
@@ -59,7 +60,6 @@
:depends-on ("parse-xml" "rss")))
:depends-on ("packages"))
- #+notyet
(:module "web" :components ((:file "site")
;; data
(:file "host")
Modified: branches/trunk-reorg/bknr/web/src/web/handlers.lisp
==============================================================================
--- branches/trunk-reorg/bknr/web/src/web/handlers.lisp (original)
+++ branches/trunk-reorg/bknr/web/src/web/handlers.lisp Thu Jan 17 11:36:28 2008
@@ -229,7 +229,7 @@
(setf (session-variable :login-redirect-uri)
(redirect-uri (request-uri req)))
(redirect (website-make-path *website* "login") req))
- (if (member :notrap net.aserve::*debug-current* :test #'eq)
+ (if hunchentoot:*catch-errors-p*
(handle handler req)
(handler-bind ((error #'(lambda (e)
(with-bknr-http-response (*req* :content-type "text/html; charset=UTF-8"
@@ -533,7 +533,7 @@
(defun show-page-with-error-handlers (fn req &key response title)
(unless response
(setf response *response-ok*)) ; can't default because used from macros and *response-ok* is not a constant
- (if (member :notrap net.aserve::*debug-current*)
+ (if hunchentoot:*catch-errors-p*
(with-bknr-http-response (req :content-type "text/html; charset=UTF-8" :response response)
(with-http-body (req *ent*)
(website-show-page *website* fn title)))
Modified: branches/trunk-reorg/bknr/web/src/web/menu.lisp
==============================================================================
--- branches/trunk-reorg/bknr/web/src/web/menu.lisp (original)
+++ branches/trunk-reorg/bknr/web/src/web/menu.lisp Thu Jan 17 11:36:28 2008
@@ -50,7 +50,7 @@
(when title
(html ((:div :class "title") (:princ-safe title))))
(dolist (item (menu-items menu))
- (let ((item-is-active (in-subtree (puri:uri-path (net.aserve:request-uri *req*)) (item-url item))))
+ (let ((item-is-active (in-subtree (request-uri) (item-url item))))
(with-slots (url title active-image inactive-image) item
(let ((link-url (format nil "~A~A" (website-base-href *website*) url)))
(cond
Modified: branches/trunk-reorg/bknr/web/src/web/templates.lisp
==============================================================================
--- branches/trunk-reorg/bknr/web/src/web/templates.lisp (original)
+++ branches/trunk-reorg/bknr/web/src/web/templates.lisp Thu Jan 17 11:36:28 2008
@@ -12,11 +12,11 @@
"/usr/local/share/xml/catalog.ports"))
(eval-when (:load-toplevel :execute)
- (let ((env-catalog (assoc :xmlcatalog ext:*environment-list*)))
+ (let ((env-catalog (sb-ext:posix-getenv "XMLCATALOG")))
(when env-catalog
- (pushnew (cdr env-catalog) *template-dtd-catalog* :test #'equal))))
+ (pushnew env-catalog *template-dtd-catalog* :test #'equal))))
-;; user-error is supposed to be raised when an error is provoced by
+;; user-error is supposed to be raised when an error is provoked by
;; the user (i.e. by supplying invalid form data).
(define-condition user-error (simple-error)
@@ -272,7 +272,7 @@
handler req)))))))
(defun invoke-with-error-handlers (fn handler req)
- (if (member :notrap net.aserve::*debug-current*)
+ (if hunchentoot:*catch-errors-p*
(handler-case
(funcall fn)
(template-not-found (c)
Modified: branches/trunk-reorg/bknr/web/src/web/web-utils.lisp
==============================================================================
--- branches/trunk-reorg/bknr/web/src/web/web-utils.lisp (original)
+++ branches/trunk-reorg/bknr/web/src/web/web-utils.lisp Thu Jan 17 11:36:28 2008
@@ -293,4 +293,4 @@
(princ " />"))))
(defun encode-urlencoded (string)
- (regex-replace-all #?r"\+" (net.aserve::encode-form-urlencoded string) "%20"))
\ No newline at end of file
+ (url-encode string))
\ No newline at end of file
Modified: branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd
==============================================================================
--- branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd (original)
+++ branches/trunk-reorg/projects/lisp-ecoop/src/lisp-ecoop.asd Thu Jan 17 11:36:28 2008
@@ -16,15 +16,22 @@
:description "Website for the LISP ECOOP Workshops"
:long-description ""
- :depends-on (:bknr-modules :cxml :klammerscript)
+ :depends-on (:bknr-datastore
+ :bknr-web
+ :cxml)
:components ((:file "packages")
(:file "config" :depends-on ("packages"))
(:file "macros" :depends-on ("config"))
+ #+(or)
(:file "schedule" :depends-on ("macros"))
+ #+(or)
(:file "participant" :depends-on ("macros" "schedule"))
+ #+(or)
(:file "mail" :depends-on ("participant"))
+ #+(or)
(:file "tags" :depends-on ("participant"))
+ #+(or)
(:file "handlers" :depends-on ("participant"))
- (:file "webserver" :depends-on ("handlers"))
+ (:file "webserver" :depends-on (#+(or) "handlers"))
(:file "init" :depends-on ("webserver"))))
Modified: branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp
==============================================================================
--- branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp (original)
+++ branches/trunk-reorg/projects/lisp-ecoop/src/macros.lisp Thu Jan 17 11:36:28 2008
@@ -1,6 +1,6 @@
(in-package :lisp-ecoop)
-(defvar *dtd* (ext:unix-namestring (merge-pathnames #p"src/lisp-ecoop.dtd" lisp-ecoop.config::*root-directory*)))
+(defvar *dtd* (namestring (merge-pathnames #p"src/lisp-ecoop.dtd" lisp-ecoop.config::*root-directory*)))
(defun compute-slot (class slot)
(destructuring-bind (name access &rest rest &key attribute element &allow-other-keys) slot
Modified: branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp
==============================================================================
--- branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp (original)
+++ branches/trunk-reorg/projects/lisp-ecoop/src/packages.lisp Thu Jan 17 11:36:28 2008
@@ -23,7 +23,6 @@
(defpackage :lisp-ecoop
(:use :cl
:cl-user
- :ext
:cl-interpol
:cl-ppcre
:bknr.utils
@@ -34,8 +33,7 @@
:bknr.images
:bknr.impex
:lisp-ecoop.config
- :net.aserve
- :net.post-office
+ :hunchentoot
:xhtml-generator)
(:shadowing-import-from :cl-interpol #:quote-meta-chars)
(:export #:participant
@@ -70,16 +68,14 @@
:cl-user
:cl-ppcre
:cl-interpol
- :ext
:bknr.web
:bknr.utils
:bknr.datastore
:bknr.user
:bknr.images
- :net.aserve
+ :hunchentoot
:xhtml-generator
:lisp-ecoop.config
:lisp-ecoop)
(:shadowing-import-from :cl-interpol #:quote-meta-chars)
- (:shadowing-import-from :acl-compat.mp #:process-kill #:process-wait)
(:export #:hello))
\ No newline at end of file
Modified: branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp
==============================================================================
--- branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp (original)
+++ branches/trunk-reorg/projects/lisp-ecoop/src/schedule.lisp Thu Jan 17 11:36:28 2008
@@ -34,6 +34,8 @@
())
(defun parse-time-spec (string)
+ (error "cannot parse time ~A yet" string)
+ #+(or)
(or (ignore-errors (parse-integer string))
(ext:parse-time string :default-zone -2))) ; XXX deal with time zone correctly!
Modified: branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp
==============================================================================
--- branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp (original)
+++ branches/trunk-reorg/projects/lisp-ecoop/src/webserver.lisp Thu Jan 17 11:36:28 2008
@@ -5,9 +5,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+#+(or)
(defun make-daily-statistics ()
(bknr.stats::make-yesterdays-stats :delete-events t :remove-referer-hosts '("lisp-ecoop.bknr.net")))
+#+(or)
(defun publish-lisp-ecoop (&key (port *webserver-port*) (listeners 20) (base-href *base-path*))
(unless (bknr.cron:cron-job-with-name "daily webserver statistics")
@@ -34,3 +36,11 @@
:javascript-urls (list (format nil "~Astatic/javascript.js" base-href)))
(start :port port :listeners listeners))
+
+(defun start-webserver (&key (port 9000))
+ (when (and (boundp '*server*) *server*)
+ (stop-server *server*))
+ (setq *dispatch-table*
+ (list 'dispatch-easy-handlers
+ (create-folder-dispatcher-and-handler "/" *website-directory*)))
+ (setq *server* (start-server :port port)))
\ No newline at end of file
Modified: branches/trunk-reorg/projects/scrabble/src/web.lisp
==============================================================================
--- branches/trunk-reorg/projects/scrabble/src/web.lisp (original)
+++ branches/trunk-reorg/projects/scrabble/src/web.lisp Thu Jan 17 11:36:28 2008
@@ -46,6 +46,7 @@
(defmethod encode-json ((tile blank-tile) stream)
(encode-json-plist (append (list :letter nil
+ :letter-name nil
:value 0)
(awhen (used-for tile)
(list :used-for it)))
Added: branches/trunk-reorg/projects/scrabble/website/scrabble-resizable-attempt.js
==============================================================================
--- (empty file)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble-resizable-attempt.js Thu Jan 17 11:36:28 2008
@@ -0,0 +1,615 @@
+// -*- JavaScript -*-
+
+var boardScoring = [["triple-word",null,null,"double-letter",null,null,null,"triple-word",
+ null,null,null,"double-letter",null,null,"triple-word"],
+ [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"double-word",null],
+ [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-word",null,null],
+ ["double-letter",null,null,"double-word",null,null,null,"double-letter",
+ null,null,null,"double-word",null,null,"double-letter"],
+ [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
+ null,null,null,null],
+ [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"triple-letter",null],
+ [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-letter",null,null],
+ ["triple-word",null,null,"double-letter",null,null,null,"double-word",
+ null,null,null,"double-letter",null,null,"triple-word"],
+ [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-letter",null,null],
+ [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"triple-letter",null],
+ [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
+ null,null,null,null],
+ ["double-letter",null,null,"double-word",null,null,null,"double-letter",
+ null,null,null,"double-word",null,null,"double-letter"],
+ [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-word",null,null],
+ [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"double-word",null],
+ ["triple-word",null,null,"double-letter",null,null,null,"triple-word",
+ null,null,null,"double-letter",null,null,"triple-word"]];
+
+// Scrabble rule enforcement
+
+function checkMoveLegality(placedTiles)
+{
+ // Given the board and list of placed tiles, either throw an error or
+ // return if the move is legal.
+
+ var positions = map(function (placement) { return [ placement.x, placement.y ] }, placedTiles)
+ .sort(function (a, b) { return (a[0] - b[0]) || (a[1] - b[1])});
+
+ if (filter(partial(operator.ne, positions[0][0]), map(function (position) { return position[0] }, positions)).length
+ && filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
+ throw "not-in-a-row";
+ }
+
+ var startOfPlacement = positions[0];
+ var endOfPlacement = positions[positions.length - 1];
+
+ for (var x = startOfPlacement[0]; x <= endOfPlacement[0]; x++) {
+ for (var y = startOfPlacement[1]; y <= endOfPlacement[1]; y++) {
+ if (!letterAt(x, y) && (findValue(positions, [ x, y ]) == -1)) {
+ throw "placement-with-holes";
+ }
+ }
+ }
+
+ if (findValue(positions, [ 7, 7 ]) == -1) {
+ var found = false;
+ for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
+ for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
+ if (((x > 0) && letterAt(x - 1, y))
+ || ((x < 14) && letterAt(x + 1, y))
+ || ((y > 0) && letterAt(x, y - 1))
+ || ((y < 14) && letterAt(x, y + 1))) {
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ throw "not-touching-other-tile";
+ }
+ }
+}
+
+// Size calculations
+
+var fieldBorderSize = 4;
+var fieldSize = 40;
+var tileBorderSize = 3;
+var tileSize = 34;
+var cellSize = 44;
+
+function calculateFieldSize()
+{
+ // Our maximum field size is 44x44 pixels. If the window is not
+ // high enough to accomodate the board, scale down.
+
+ var requiredHeight = 16 * 44 + 40; // 16 fields (including player tray) + borders
+ var viewportHeight = YAHOO.util.Dom.getViewportHeight();
+ fieldSize = Math.floor((Math.min(requiredHeight, viewportHeight) - 40) / 16);
+ fieldBorderSize = Math.floor(fieldSize / 10);
+ fieldSize -= fieldBorderSize;
+ tileSize = Math.floor(fieldSize * 34 / 40);
+ tileBorderSize = Math.round((fieldSize - tileSize) / 2);
+ cellSize = fieldBorderSize + fieldSize;
+// alert('fieldSize: ' + fieldSize + ' fieldBorderSize: ' + fieldBorderSize
+// + ' tileSize: ' + tileSize + ' tileBorderSize: ' + tileBorderSize);
+}
+
+
+//
+
+function getFieldScore(x, y) {
+ return boardScoring[x][y] || 'standard';
+}
+
+var theirTrays;
+var tray = [];
+
+var gameID = 108;
+var board;
+
+var border = 10;
+
+function makeBoard() {
+ calculateFieldSize();
+ var container = $('playfield');
+ board = [];
+ for (x = 0; x < 15; x++) {
+ board[x] = [];
+ for (y = 0; y < 15; y++) {
+ var element = IMG();
+ element.style.position = 'absolute';
+ element.style.width = fieldSize + 'px';
+ element.style.height = fieldSize + 'px';
+ element.xPos = x;
+ element.yPos = y;
+ var imageName = (x == 7 && y == 7) ? "start-field" : getFieldScore(x, y);
+ element.src = 'images/' + imageName + '.png';
+ setElementPosition(element, { x: border + x * cellSize, y: border + y * cellSize });
+ YAHOO.util.Event.on(element, 'click', emptyTileClicked);
+ board[x][y] = element;
+ }
+ appendChildNodes(container, board[x]);
+ }
+
+ var shuffleButton = DIV(null, "shuffle");
+ shuffleButton.style.color = 'white';
+ shuffleButton.style.position = 'absolute';
+ shuffleButton.onclick = shuffleMyTray;
+ setElementPosition(shuffleButton, { x: border + 480, y: border + 665 });
+ appendChildNodes(container, shuffleButton);
+
+ var gameLog = DIV({ id: 'gameLog' }, "");
+ gameLog.style.position = 'absolute';
+ gameLog.style.width = '280px';
+ gameLog.style.height = '250px';
+ gameLog.style.textAlign = 'left';
+ gameLog.style.overflowY = 'scroll';
+ setElementPosition(gameLog, { x: border + 680, y: border + 400 });
+ appendChildNodes($('playfield'), gameLog);
+
+ var nextTurn = DIV({ id: 'nextTurn' }, "");
+ nextTurn.style.position = 'absolute';
+ nextTurn.style.width = '280px';
+ nextTurn.style.textAlign = 'left';
+ setElementPosition(nextTurn, { x: border + 680, y: border + 665 });
+ appendChildNodes($('playfield'), nextTurn);
+
+ var nextTurn = DIV({ id: 'status' }, "");
+ nextTurn.style.position = 'absolute';
+ nextTurn.style.width = '280px';
+ nextTurn.style.textAlign = 'left';
+ setElementPosition(nextTurn, { x: border + 680, y: border + 680 });
+ appendChildNodes($('playfield'), nextTurn);
+}
+
+function setLetter(x, y, letter, isBlank) {
+ var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
+ image.style.position = 'absolute';
+ image.style.top = '3px';
+ image.style.left = '3px';
+ image.style.width = tileSize + 'px';
+ image.style.height = tileSize + 'px';
+ setElementPosition(image, { x: border + x * cellSize + tileBorderSize,
+ y: border + y * cellSize + tileBorderSize });
+ appendChildNodes($('playfield'), image);
+ board[x][y].letterNode = image;
+ board[x][y].letter = letter;
+}
+
+function removeLastLetterFromMove() {
+}
+
+function letterAt(x, y) {
+ return board[x][y].letter && !board[x][y].justPlaced;
+}
+
+function Cursor()
+{
+ var image = new IMG({ src: 'images/cursor.png' });
+ image.style.position = 'absolute';
+ image.style.top = '-' + tileBorderSize + 'px';
+ image.style.left = '-' + tileBorderSize + 'px';
+
+ appendChildNodes($('playfield'), image);
+ this.image = image;
+ this.x = -1;
+ this.y = -1;
+ this.direction = 0;
+
+ this.set = function(x, y) {
+ this.x = x;
+ this.y = y;
+ this.image.top =
+ this.image.style.visibility = 'visible';
+ board[x][y].cursor = this.image;
+ };
+
+ this.clear = function() {
+ if (this.x != -1) {
+ this.image.style.visibility = 'hidden';
+ board[this.x][this.y].cursor = undefined;
+ this.x = this.y = -1;
+ this.direction = 0;
+ }
+ };
+
+ this.advance = function(isHoriz) {
+ var horizontal = 1;
+ var vertical = 2;
+ var direction = this.direction;
+ if (direction == 0) {
+ // Direction not determined
+ if (isHoriz != undefined) {
+ direction = isHoriz ? horizontal : vertical;
+ } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
+ || ((this.y > 1)
+ && letterAt(this.x, this.y - 1)
+ && !letterAt(this.x, this.y - 2))
+ || ((this.x > 1)
+ && letterAt(this.x - 1, this.y)
+ && letterAt(this.x - 2, this.y))) {
+ direction = vertical;
+ } else {
+ direction = horizontal;
+ }
+ }
+ var x = this.x;
+ var y = this.y;
+ this.clear();
+ this.direction = direction;
+ if (this.direction == horizontal) {
+ x++;
+ } else {
+ y++;
+ }
+ if ((x != 15) && (y != 15)) {
+ this.set(x, y);
+ }
+ };
+}
+
+var cursor = new Cursor;
+
+function emptyTileClicked() {
+ cursor.clear();
+ cursor.set(this.xPos, this.yPos);
+}
+
+var move = [];
+
+function makeMask()
+{
+ var mask = IMG({ src: 'images/mask.png'});
+ mask.style.position = 'absolute';
+ mask.style.top = tileBorderSize + 'px';
+ mask.style.left = tileBorderSize + 'px';
+ mask.style.zIndex = '20';
+ return mask;
+}
+
+function addLetterToMove(x, y, tile) {
+ mask = makeMask();
+ appendChildNodes(board[x][y], mask);
+ board[x][y].letterNode = tile;
+ board[x][y].letter = tile.letter;
+ board[x][y].justPlaced = true;
+ tile.mask = mask;
+ tile.anim = new YAHOO.util.Motion(tile, { points: { to: [ border + x * cellSize + tileBorderSize,
+ border + y * cellSize + tileBorderSize ]}},
+ 0.15,
+ YAHOO.util.Easing.easeBoth);
+ tile.anim.animate();
+
+ move[move.length] = { x: x, y: y, tile: tile };
+ try {
+ checkMoveLegality(move);
+ $('move').onclick = submitMove;
+ $('move').innerHTML = "submit move";
+ displayStatus('');
+ }
+ catch (e) {
+ if (typeof e != 'string') {
+ alert(e.message);
+ } else {
+ displayStatus(e);
+ }
+ $('move').onclick = undefined;
+ $('move').innerHTML = e.toString();
+ }
+}
+
+function confirmMove() {
+ for (var i = 0; i < move.length; i++) {
+ removeElement(move[i].tile.mask);
+ move[i].tile.mask = undefined;
+ }
+ cursor.clear();
+ move = [];
+ $('move').onclick = null;
+ $('move').innerHTML = '';
+
+}
+
+function moveAsString() {
+ // We internally keep the move as array of objects, but send it to the server rather unstructured:
+ var serverMessage = [];
+ for (var i = 0; i < move.length; i++) {
+ serverMessage.push(move[i].x);
+ serverMessage.push(move[i].y);
+ serverMessage.push(move[i].tile.letterName);
+ serverMessage.push(move[i].tile.letterName == undefined);
+ }
+ return serverMessage.toString();
+}
+
+function submitMove()
+{
+ var queryString = MochiKit.Base.queryString({ move: moveAsString(), game: gameID });
+ var res = MochiKit.Async.doXHR("/place-tiles",
+ { method: 'POST',
+ sendContent: queryString,
+ headers: { "Content-Type": "application/x-www-form-urlencoded" } });
+ res.addCallbacks(moveSuccess, moveFailure);
+}
+
+function moveSuccess(result)
+{
+ try {
+ var response;
+ try {
+ response = eval('(' + result.responseText + ')');
+ }
+ catch (e) {
+ alert("invalid JSON reply: " + result.responseText);
+ return;
+ }
+ if (response.error) {
+ alert(response.error);
+ } else {
+ confirmMove();
+ $('playfield')['score-' + response.move.participantLogin].innerHTML = response.move.playerScore.toString();
+ displayMyTray(response.tray);
+ }
+ }
+ catch (e) {
+ alert('error during moveSuccess: ' + e.message);
+ }
+}
+
+function moveFailure(e)
+{
+ alert('failed: ' + e);
+}
+
+function letterKeyPressed(e) {
+ if (e.which == 0 || e.altKey || e.ctrlKey || e.shiftKey) {
+ // not a letter key
+ return;
+ }
+
+ var letter = String.fromCharCode(e.which).toUpperCase();
+
+ var x = cursor.x;
+ var y = cursor.y;
+ var tilePosition = -1;
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == letter) {
+ tilePosition = i;
+ }
+ }
+ if (tilePosition == -1) {
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == undefined) {
+ tilePosition = i;
+ }
+ }
+ }
+ if (tilePosition == -1) {
+ displayStatus('you-dont-have-that-letter', letter);
+ } else {
+ var isHoriz;
+ if (move.length > 0) {
+ isHoriz = (move[0].x != x);
+ }
+ cursor.advance(isHoriz);
+ if (!letterAt(x, y)) {
+ var tile = tray[tilePosition];
+ tray.splice(tilePosition, 1);
+ addLetterToMove(x, y, tile);
+ }
+ }
+}
+
+var leftKey = 37;
+var upKey = 38;
+var rightKey = 39;
+var downKey = 40;
+var backspaceKey = 8;
+
+function functionKeyPressed(type, args, obj) {
+ var x = cursor.x;
+ var y = cursor.y;
+
+ switch (args[0]) {
+ case rightKey:
+ while (x < 14)
+ if (!letterAt(++x, y))
+ break;
+ break;
+ case leftKey:
+ while (x > 0)
+ if (!letterAt(--x, y))
+ break;
+ break;
+ case upKey:
+ while (y > 0)
+ if (!letterAt(x, --y))
+ break;
+ break;
+ case downKey:
+ while (y < 14)
+ if (!letterAt(x, ++y))
+ break;
+ break;
+ case backspaceKey:
+ if (move.length) {
+ removeLastLetterFromMove();
+ }
+ }
+ if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) {
+ cursor.clear();
+ cursor.set(x, y);
+ }
+ YAHOO.util.Event.preventDefault(args[1]);
+}
+
+function clearBoard() {
+ for (x = 0; x < 15; x++) {
+ for (y = 0; y < 15; y++) {
+ var letterNode = board[x][y].letterNode;
+ if (letterNode) {
+ letterNode.anim = new YAHOO.util.Motion(letterNode,
+ { points: { to: [ border + 7 * cellSize + tileBorderSize,
+ border + 7 * cellSize + tileBorderSize ]}},
+ 0.15);
+ letterNode.anim.onComplete.subscribe(function () { removeElement(this); });
+ letterNode.anim.animate();
+ }
+ }
+ }
+}
+
+function trayClick(letter) {
+ this.clicked = !this.clicked;
+ this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
+ this.anim.animate();
+}
+
+function displayMyTray(letters) {
+ map(removeElement, tray);
+ tray = [];
+ for (var i = 0; i < letters.length; i++) {
+ var element = IMG({src: 'images/' + letters[i].letterName + '.png'});
+ element.letter = letters[i].letter;
+ element.letterName = letters[i].letterName;
+ element.style.position = 'absolute';
+ element.style.width = tileSize + 'px';
+ element.style.height = tileSize + 'px';
+ element.style.zIndex = '10';
+ element.onclick = trayClick;
+ setElementPosition(element, { x: border + i * fieldSize,
+ y: border + 15 * cellSize + 10 });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
+}
+
+function shuffleMyTray() {
+ var count = tray.length;
+ var newTray = [];
+ for (var i = 0; i < count; i++) {
+ do {
+ index = Math.floor(Math.random() * count);
+ } while (newTray[index]);
+ newTray[index] = tray[i];
+ newTray[index].anim = new YAHOO.util.Motion(tray[i], { points: { to: [ border + 194 + i * 40,
+ border + 665 ] }},
+ 0.5);
+ newTray[index].anim.animate();
+ newTray[index].clicked = false;
+ }
+ tray = newTray;
+}
+
+var otherPlayerIndex = 0;
+
+function makeTheirTray (participant) {
+ var tileCount = (typeof participant.remainingTiles == 'number') ? participant.remainingTiles : participant.remainingTiles.length;
+
+ var tray = [];
+ for (var i = 0; i < tileCount; i++) {
+ var element = IMG({src: 'images/null.png'});
+ element.style.position = 'absolute';
+ element.style.width = tileSize + 'px';
+ element.style.height = tileSize + 'px';
+ element.style.zIndex = '10';
+ setElementPosition(element, { x: border + 15 * cellSize + 10 + i * fieldSize,
+ y: border + 80 * otherPlayerIndex });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
+
+ var nameTag = DIV(null, participant.name);
+ nameTag.style.position = 'absolute';
+ nameTag.style.width = '200px';
+ nameTag.style.textAlign = 'left';
+ setElementPosition(nameTag, { x: border + 680, y: border + 80 * otherPlayerIndex + 50 });
+ appendChildNodes($('playfield'), nameTag);
+
+ var scoreTag = DIV(null, participant.score);
+ scoreTag.style.position = 'absolute';
+ scoreTag.style.width = '80px';
+ scoreTag.style.textAlign = 'right';
+ setElementPosition(scoreTag, { x: border + 870, y: border + 80 * otherPlayerIndex + 50 });
+ appendChildNodes($('playfield'), scoreTag);
+ $('playfield')['score-' + participant.login] = scoreTag;
+
+ otherPlayerIndex++;
+}
+
+function renderMoveAsText(move)
+{
+ var retval = move.participantLogin;
+ if (move.type == 'move') {
+ retval += " score: " + move.score;
+ for (var i = 0; i < move.words.length; i++) {
+ retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
+ }
+ } else {
+ retval += move.type;
+ }
+
+ return retval;
+}
+
+function displayWhosTurnItIs(name) {
+ replaceChildNodes($('nextTurn'),
+ "Next: " + name);
+}
+
+function drawGameState (gameState) {
+ try {
+ for (var i = 0; i < gameState.board.length; i++) {
+ var x = gameState.board[i][0];
+ var y = gameState.board[i][1];
+ var char = gameState.board[i][2];
+ setLetter(x, y, char, gameState.board[i].length > 3);
+ }
+ var firstParticipant = gameState.participants[0];
+ displayWhosTurnItIs(firstParticipant.name);
+ for (var i = 0; i < gameState.participants.length; i++) {
+ var participant = gameState.participants[i];
+ makeTheirTray(participant);
+ if (typeof participant.remainingTiles != 'number') {
+ displayMyTray(participant.remainingTiles);
+ }
+ }
+ for (var i = 0; i < gameState.moves.length; i++) {
+ appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i])));
+ }
+ }
+ catch (e) {
+ alert('error ' + e + ' in drawGameState');
+ }
+}
+
+function displayStatus(status)
+{
+ replaceChildNodes('status', status);
+}
+
+function init() {
+ makeBoard();
+
+ // does not work for ie (document.body needed)?
+ YAHOO.util.Event.on(window, 'keypress', letterKeyPressed);
+
+ var functionKeyListener = new YAHOO.util.KeyListener(document,
+ { keys: [ leftKey, upKey, rightKey, downKey, backspaceKey ] },
+ { fn: functionKeyPressed, scope: this, correctScope: true });
+ functionKeyListener.enable();
+
+ var moveDisplay = DIV({ id: 'move' }, "");
+ moveDisplay.style.color = 'white';
+ moveDisplay.style.position = 'absolute';
+ setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });
+ appendChildNodes(document.body, moveDisplay);
+ var d = loadJSONDoc("/game/" + gameID);
+ d.addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
+}
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.html
==============================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.html (original)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.html Thu Jan 17 11:36:28 2008
@@ -1,18 +1,18 @@
<html>
- <head>
- <link rel="stylesheet" type="text/css" href="/yui/reset-fonts-grids/reset-fonts-grids.css" />
- <link rel="stylesheet" type="text/css" href="scrabble.css" />
- <script type="text/javascript" src="/yui/yahoo/yahoo-min.js"> </script>
- <script type="text/javascript" src="/yui/event/event-min.js"> </script>
- <script type="text/javascript" src="/yui/dom/dom-min.js"> </script>
- <script type="text/javascript" src="/yui/animation/animation-min.js"> </script>
- <script type="text/javascript" src="/MochiKit/MochiKit.js"> </script>
- <script type="text/javascript" src="scrabble.js"> </script>
- </head>
- <body onload="init()">
- <div id="playfield">
- </div>
- <!-- <div style="position: absolute; right: 20px; top: 20px;"><a style="color: white;" href="/login?login=hans">hans</a></div> -->
- <!-- <div style="position: absolute; right: 20px; top: 40px;"><a style="color: white;" href="/login?login=marna">marna</a></div> -->
- </body>
+ <head>
+ <link rel="stylesheet" type="text/css" href="/yui/reset-fonts-grids/reset-fonts-grids.css" />
+ <link rel="stylesheet" type="text/css" href="scrabble.css" />
+ <script type="text/javascript" src="/yui/yahoo/yahoo-min.js"> </script>
+ <script type="text/javascript" src="/yui/event/event-min.js"> </script>
+ <script type="text/javascript" src="/yui/dom/dom-min.js"> </script>
+ <script type="text/javascript" src="/yui/animation/animation-min.js"> </script>
+ <script type="text/javascript" src="/MochiKit/MochiKit.js"> </script>
+ <script type="text/javascript" src="scrabble.js"> </script>
+ </head>
+ <body onload="init()">
+ <div id="playfield">
+ </div>
+ <div style="position: absolute; right: 20px; top: 20px;"><a style="color: white;" href="/login?login=hans">hans</a></div>
+ <div style="position: absolute; right: 20px; top: 40px;"><a style="color: white;" href="/login?login=marna">marna</a></div>
+ </body>
</html>
Modified: branches/trunk-reorg/projects/scrabble/website/scrabble.js
==============================================================================
--- branches/trunk-reorg/projects/scrabble/website/scrabble.js (original)
+++ branches/trunk-reorg/projects/scrabble/website/scrabble.js Thu Jan 17 11:36:28 2008
@@ -1,386 +1,380 @@
// -*- JavaScript -*-
-var boardScoring = [["triple-word",null,null,"double-letter",null,null,null,"triple-word",
- null,null,null,"double-letter",null,null,"triple-word"],
- [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
- null,null,null,"double-word",null],
- [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
- null,null,null,"double-word",null,null],
- ["double-letter",null,null,"double-word",null,null,null,"double-letter",
- null,null,null,"double-word",null,null,"double-letter"],
- [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
- null,null,null,null],
- [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
- null,null,null,"triple-letter",null],
- [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
- null,null,null,"double-letter",null,null],
- ["triple-word",null,null,"double-letter",null,null,null,"double-word",
- null,null,null,"double-letter",null,null,"triple-word"],
- [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
- null,null,null,"double-letter",null,null],
- [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
- null,null,null,"triple-letter",null],
- [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
- null,null,null,null],
- ["double-letter",null,null,"double-word",null,null,null,"double-letter",
- null,null,null,"double-word",null,null,"double-letter"],
- [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
- null,null,null,"double-word",null,null],
- [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
- null,null,null,"double-word",null],
- ["triple-word",null,null,"double-letter",null,null,null,"triple-word",
- null,null,null,"double-letter",null,null,"triple-word"]];
-
-// for now
-function requestError (error) {
- alert("Request error: " + error.message)
-}
+var scrabbleRules = {
+ boardScoring: [["triple-word",null,null,"double-letter",null,null,null,"triple-word",
+ null,null,null,"double-letter",null,null,"triple-word"],
+ [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"double-word",null],
+ [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-word",null,null],
+ ["double-letter",null,null,"double-word",null,null,null,"double-letter",
+ null,null,null,"double-word",null,null,"double-letter"],
+ [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
+ null,null,null,null],
+ [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"triple-letter",null],
+ [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-letter",null,null],
+ ["triple-word",null,null,"double-letter",null,null,null,"double-word",
+ null,null,null,"double-letter",null,null,"triple-word"],
+ [null,null,"double-letter",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-letter",null,null],
+ [null,"triple-letter",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"triple-letter",null],
+ [null,null,null,null,"double-word",null,null,null,null,null,"double-word",
+ null,null,null,null],
+ ["double-letter",null,null,"double-word",null,null,null,"double-letter",
+ null,null,null,"double-word",null,null,"double-letter"],
+ [null,null,"double-word",null,null,null,"double-letter",null,"double-letter",
+ null,null,null,"double-word",null,null],
+ [null,"double-word",null,null,null,"triple-letter",null,null,null,"triple-letter",
+ null,null,null,"double-word",null],
+ ["triple-word",null,null,"double-letter",null,null,null,"triple-word",
+ null,null,null,"double-letter",null,null,"triple-word"]],
-// Scrabble rule enforcement
+ // Scrabble rule enforcement
-function checkMoveLegality(placedTiles)
-{
+ checkMoveLegality : function (placedTiles) {
// Given the board and list of placed tiles, either throw an error or
// return if the move is legal.
var positions = map(function (placement) { return [ placement.x, placement.y ] }, placedTiles)
- .sort(function (a, b) { return (a[0] - b[0]) || (a[1] - b[1])});
+ .sort(function (a, b) { return (a[0] - b[0]) || (a[1] - b[1])});
if (filter(partial(operator.ne, positions[0][0]), map(function (position) { return position[0] }, positions)).length
- && filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
- throw "not-in-a-row";
+ && filter(partial(operator.ne, positions[0][1]), map(function (position) { return position[1] }, positions)).length) {
+ throw "not-in-a-row";
}
var startOfPlacement = positions[0];
var endOfPlacement = positions[positions.length - 1];
for (var x = startOfPlacement[0]; x <= endOfPlacement[0]; x++) {
- for (var y = startOfPlacement[1]; y <= endOfPlacement[1]; y++) {
- if (!letterAt(x, y) && (findValue(positions, [ x, y ]) == -1)) {
- throw "placement-with-holes";
- }
- }
+ for (var y = startOfPlacement[1]; y <= endOfPlacement[1]; y++) {
+ if (!letterAt(x, y) && (findValue(positions, [ x, y ]) == -1)) {
+ throw "placement-with-holes";
+ }
+ }
}
if (findValue(positions, [ 7, 7 ]) == -1) {
- var found = false;
- for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
- for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
- if (((x > 0) && letterAt(x - 1, y))
- || ((x < 14) && letterAt(x + 1, y))
- || ((y > 0) && letterAt(x, y - 1))
- || ((y < 14) && letterAt(x, y + 1))) {
- found = true;
- }
- }
- }
- if (!found) {
- throw "not-touching-other-tile";
- }
+ var found = false;
+ for (var x = startOfPlacement[0]; !found && (x <= endOfPlacement[0]); x++) {
+ for (var y = startOfPlacement[1]; !found && (y <= endOfPlacement[1]); y++) {
+ if (((x > 0) && letterAt(x - 1, y))
+ || ((x < 14) && letterAt(x + 1, y))
+ || ((y > 0) && letterAt(x, y - 1))
+ || ((y < 14) && letterAt(x, y + 1))) {
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ throw "not-touching-other-tile";
+ }
}
-}
+ },
-//
+ //
-function getFieldScore(x, y) {
+ fieldScore : function(x, y) {
return boardScoring[x][y] || 'standard';
-}
+ }
+};
var theirTrays;
var tray = [];
+var gameID = 108;
var board;
-var border = 10;
-
function makeBoard() {
- var container = $('playfield');
- board = [];
- for (x = 0; x < 15; x++) {
- board[x] = [];
- for (y = 0; y < 15; y++) {
- var element = DIV();
- element.style.position = 'absolute';
- element.style.width = '40px';
- element.style.height = '40px';
- var imageName = (x == 7 && y == 7) ? "start-field" : getFieldScore(x, y);
- element.style.backgroundImage = 'url(images/' + imageName + '.png)';
- element.x = x;
- element.y = y;
- setElementPosition(element, { x: border + x * 44, y: border + y * 44 });
- YAHOO.util.Event.on(element, 'click', emptyTileClicked)
- board[x][y] = element;
- }
- appendChildNodes(container, board[x]);
- }
-
- var shuffleButton = DIV(null, "shuffle");
- shuffleButton.style.color = 'white';
- shuffleButton.style.position = 'absolute';
- shuffleButton.onclick = shuffleMyTray;
- setElementPosition(shuffleButton, { x: border + 480, y: border + 665 });
- appendChildNodes(container, shuffleButton);
-
- var gameLog = DIV({ id: 'gameLog' }, "");
- gameLog.style.position = 'absolute';
- gameLog.style.width = '280px';
- gameLog.style.height = '250px';
- gameLog.style.textAlign = 'left';
- gameLog.style.overflowY = 'scroll';
- setElementPosition(gameLog, { x: border + 680, y: border + 400 });
- appendChildNodes($('playfield'), gameLog);
-
- var nextTurn = DIV({ id: 'nextTurn' }, "");
- nextTurn.style.position = 'absolute';
- nextTurn.style.width = '280px';
- nextTurn.style.textAlign = 'left';
- setElementPosition(nextTurn, { x: border + 680, y: border + 665 });
- appendChildNodes($('playfield'), nextTurn);
-
- var nextTurn = DIV({ id: 'status' }, "");
- nextTurn.style.position = 'absolute';
- nextTurn.style.width = '280px';
- nextTurn.style.textAlign = 'left';
- setElementPosition(nextTurn, { x: border + 680, y: border + 680 });
- appendChildNodes($('playfield'), nextTurn);
+ var container = $('playfield');
+ board = [];
+ for (x = 0; x < 15; x++) {
+ board[x] = [];
+ for (y = 0; y < 15; y++) {
+ var element = DIV();
+ element.style.position = 'absolute';
+ element.style.width = '40px';
+ element.style.height = '40px';
+ var imageName = (x == 7 && y == 7) ? "start-field" : scrabbleRules.fieldScore(x, y);
+ element.style.backgroundImage = 'url(images/' + imageName + '.png)';
+ element.x = x;
+ element.y = y;
+ setElementPosition(element, { x: x * 44, y: y * 44 });
+ YAHOO.util.Event.on(element, 'click', emptyTileClicked)
+ board[x][y] = element;
+ }
+ appendChildNodes(container, board[x]);
+ }
+
+ var shuffleButton = DIV(null, "shuffle");
+ shuffleButton.style.color = 'white';
+ shuffleButton.style.position = 'absolute';
+ shuffleButton.onclick = shuffleMyTray;
+ setElementPosition(shuffleButton, { x: 480, y: 665 });
+ appendChildNodes(container, shuffleButton);
+
+ var gameLog = DIV({ id: 'gameLog' }, "");
+ gameLog.style.position = 'absolute';
+ gameLog.style.width = '280px';
+ gameLog.style.height = '250px';
+ gameLog.style.textAlign = 'left';
+ gameLog.style.overflowY = 'scroll';
+ setElementPosition(gameLog, { x: 680, y: 400 });
+ appendChildNodes($('playfield'), gameLog);
+
+ var nextTurn = DIV({ id: 'nextTurn' }, "");
+ nextTurn.style.position = 'absolute';
+ nextTurn.style.width = '280px';
+ nextTurn.style.textAlign = 'left';
+ setElementPosition(nextTurn, { x: 680, y: 665 });
+ appendChildNodes($('playfield'), nextTurn);
+
+ var nextTurn = DIV({ id: 'status' }, "");
+ nextTurn.style.position = 'absolute';
+ nextTurn.style.width = '280px';
+ nextTurn.style.textAlign = 'left';
+ setElementPosition(nextTurn, { x: 680, y: 680 });
+ appendChildNodes($('playfield'), nextTurn);
}
function setLetter(x, y, letter, isBlank) {
- var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
- image.style.position = 'absolute';
- image.style.top = '3px';
- image.style.left = '3px';
- setElementPosition(image, { x: border + x * 44 + 3, y: border + y * 44 + 3 });
- appendChildNodes($('playfield'), image);
- board[x][y].letterNode = image;
- board[x][y].letter = letter;
-}
-
-function placeLetter(x, y, tile) {
+ var image = IMG({ src: 'images/' + letter + (isBlank ? "-blank" : "") + '.png'});
+ image.style.position = 'absolute';
+ image.style.top = '3px';
+ image.style.left = '3px';
+ setElementPosition(image, { x: x * 44 + 3, y: y * 44 + 3 });
+ appendChildNodes($('playfield'), image);
+ board[x][y].letterNode = image;
+ board[x][y].letter = letter;
}
function removeLastLetterFromMove() {
}
function letterAt(x, y) {
- return board[x][y].letter && !board[x][y].justPlaced;
+ return board[x][y].letter && !board[x][y].justPlaced;
}
function Cursor()
{
- var image = new IMG({ src: 'images/cursor.png' });
- image.style.position = 'absolute';
- image.style.top = '-3px';
- image.style.left = '-3px';
-
- this.image = image;
- this.x = -1;
- this.y = -1;
- this.direction = 0;
-
- this.set = function(x, y) {
- this.x = x;
- this.y = y;
- appendChildNodes(board[x][y], this.image);
- board[x][y].cursor = this.image;
- };
-
- this.clear = function() {
- if (this.x != -1) {
- removeElement(board[this.x][this.y].cursor);
- board[this.x][this.y].cursor = undefined;
- this.x = this.y = -1;
- this.direction = 0;
- }
- };
-
- this.advance = function(isHoriz) {
- var horizontal = 1;
- var vertical = 2;
- var direction = this.direction;
- if (direction == 0) {
- // Direction not determined
- if (isHoriz != undefined) {
- direction = isHoriz ? horizontal : vertical;
- } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
- || ((this.y > 1)
- && letterAt(this.x, this.y - 1)
- && !letterAt(this.x, this.y - 2))
- || ((this.x > 1)
- && letterAt(this.x - 1, this.y)
- && letterAt(this.x - 2, this.y))) {
- direction = vertical;
- } else {
- direction = horizontal;
- }
- }
- var x = this.x;
- var y = this.y;
- this.clear();
- this.direction = direction;
- if (this.direction == horizontal) {
- x++;
- } else {
- y++;
- }
- if ((x != 15) && (y != 15)) {
- this.set(x, y);
- }
- };
+ var image = new IMG({ src: 'images/cursor.png' });
+ image.style.position = 'absolute';
+ image.style.top = '-3px';
+ image.style.left = '-3px';
+
+ this.image = image;
+ this.x = -1;
+ this.y = -1;
+ this.direction = 0;
+
+ this.set = function(x, y) {
+ this.x = x;
+ this.y = y;
+ appendChildNodes(board[x][y], this.image);
+ board[x][y].cursor = this.image;
+ };
+
+ this.clear = function() {
+ if (this.x != -1) {
+ removeElement(board[this.x][this.y].cursor);
+ board[this.x][this.y].cursor = undefined;
+ this.x = this.y = -1;
+ this.direction = 0;
+ }
+ };
+
+ this.advance = function(isHoriz) {
+ var horizontal = 1;
+ var vertical = 2;
+ var direction = this.direction;
+ if (direction == 0) {
+ // Direction not determined
+ if (isHoriz != undefined) {
+ direction = isHoriz ? horizontal : vertical;
+ } else if (((this.y < 14) && letterAt(this.x, this.y + 1))
+ || ((this.y > 1)
+ && letterAt(this.x, this.y - 1)
+ && !letterAt(this.x, this.y - 2))
+ || ((this.x > 1)
+ && letterAt(this.x - 1, this.y)
+ && letterAt(this.x - 2, this.y))) {
+ direction = vertical;
+ } else {
+ direction = horizontal;
+ }
+ }
+ var x = this.x;
+ var y = this.y;
+ this.clear();
+ this.direction = direction;
+ if (this.direction == horizontal) {
+ x++;
+ } else {
+ y++;
+ }
+ if ((x != 15) && (y != 15)) {
+ this.set(x, y);
+ }
+ };
}
var cursor = new Cursor;
function emptyTileClicked() {
- cursor.clear();
- cursor.set(this.x, this.y);
+ cursor.clear();
+ cursor.set(this.x, this.y);
}
var move = [];
function makeMask()
{
- var mask = IMG({ src: 'images/mask.png'});
- mask.style.position = 'absolute';
- mask.style.top = '3px';
- mask.style.left = '3px';
- mask.style.zIndex = '20';
- return mask;
-}
-
-function addLetterToMove(x, y, tile) {
- mask = makeMask();
- appendChildNodes(board[x][y], mask);
- board[x][y].letterNode = tile;
- board[x][y].letter = tile.letter;
- board[x][y].justPlaced = true;
- tile.mask = mask;
- tile.anim = new YAHOO.util.Motion(tile, { points: { to: [ border + x * 44 + 3,
- border + y * 44 + 3 ]}},
- 0.15,
- YAHOO.util.Easing.easeBoth);
- tile.anim.animate();
-
- move[move.length] = { x: x, y: y, tile: tile };
- try {
- checkMoveLegality(move);
- $('move').onclick = submitMove;
- $('move').innerHTML = "submit move";
- displayStatus('');
- }
- catch (e) {
- if (typeof e != 'string') {
- alert(e.message);
- } else {
- displayStatus(e);
- }
- $('move').onclick = undefined;
- $('move').innerHTML = e.toString();
+ var mask = IMG({ src: 'images/mask.png'});
+ mask.style.position = 'absolute';
+ mask.style.top = '3px';
+ mask.style.left = '3px';
+ mask.style.zIndex = '20';
+ return mask;
+}
+
+function addLetterToMove(x, y, tile, letter) {
+ mask = makeMask();
+ appendChildNodes(board[x][y], mask);
+ board[x][y].letterNode = tile;
+ if (!tile.letter) {
+ tile.letter = letter;
+ }
+ board[x][y].justPlaced = true;
+ tile.mask = mask;
+ tile.anim = new YAHOO.util.Motion(tile, { points: { to: [ x * 44 + 3,
+ y * 44 + 3 ]}},
+ 0.15,
+ YAHOO.util.Easing.easeBoth);
+ tile.anim.animate();
+
+ move[move.length] = { x: x, y: y, tile: tile };
+ try {
+ checkMoveLegality(move);
+ $('move').onclick = submitMove;
+ $('move').innerHTML = "submit move";
+ displayStatus('');
+ }
+ catch (e) {
+ if (typeof e != 'string') {
+ alert(e.message);
+ } else {
+ displayStatus(e);
}
+ $('move').onclick = undefined;
+ $('move').innerHTML = e.toString();
+ }
}
function confirmMove() {
- for (var i = 0; i < move.length; i++) {
- removeElement(move[i].tile.mask);
- move[i].tile.mask = undefined;
- }
- cursor.clear();
- move = [];
- $('move').onclick = null;
- $('move').innerHTML = '';
-
+ for (var i = 0; i < move.length; i++) {
+ removeElement(move[i].tile.mask);
+ move[i].tile.mask = undefined;
+ }
+ cursor.clear();
+ move = [];
+ $('move').onclick = null;
+ $('move').innerHTML = '';
+
}
function moveAsString() {
- // We internally keep the move as array of objects, but send it to the server rather unstructured:
- var serverMessage = [];
- for (var i = 0; i < move.length; i++) {
- serverMessage.push(move[i].x);
- serverMessage.push(move[i].y);
- serverMessage.push(move[i].tile.letterName);
- serverMessage.push(move[i].tile.letterName == undefined);
- }
- return serverMessage.toString();
+ // We internally keep the move as array of objects, but send it to the server rather unstructured:
+ var serverMessage = [];
+ for (var i = 0; i < move.length; i++) {
+ serverMessage.push(move[i].x);
+ serverMessage.push(move[i].y);
+ serverMessage.push(move[i].tile.letterName || move[i].tile.letter);
+ serverMessage.push(move[i].tile.letterName == undefined);
+ }
+ return serverMessage.toString();
}
function submitMove()
{
- var queryString = MochiKit.Base.queryString({ move: moveAsString() });
- var res = MochiKit.Async.doXHR("/place-tiles",
- { method: 'POST',
+ var queryString = MochiKit.Base.queryString({ move: moveAsString(), game: gameID });
+ var res = MochiKit.Async.doXHR("/place-tiles",
+ { method: 'POST',
sendContent: queryString,
headers: { "Content-Type": "application/x-www-form-urlencoded" } });
- res.addCallbacks(moveSuccess, moveFailure);
+ res.addCallbacks(moveSuccess, moveFailure);
}
function moveSuccess(result)
{
+ try {
+ var response;
try {
- var response;
- try {
- response = eval('(' + result.responseText + ')');
- }
- catch (e) {
- alert("invalid JSON reply: " + result.responseText);
- return;
- }
- if (response.error) {
- alert(response.error);
- } else {
- confirmMove();
- alert(response.move.playerScore);
- $('playfield')['score-' + response.move.participantLogin].innerHTML = response.move.playerScore.toString();
- displayMyTray(response.tray);
- }
+ response = eval('(' + result.responseText + ')');
}
catch (e) {
- alert('error during moveSuccess: ' + e.message);
+ alert("invalid JSON reply: " + result.responseText);
+ return;
}
+ if (response.error) {
+ alert(response.error);
+ } else {
+ confirmMove();
+ alert(response.move.playerScore);
+ $('playfield')['score-' + response.move.participantLogin].innerHTML = response.move.playerScore.toString();
+ displayMyTray(response.tray);
+ }
+ }
+ catch (e) {
+ alert('error during moveSuccess: ' + e.message);
+ }
}
function moveFailure(e)
{
- alert('failed: ' + e);
+ alert('failed: ' + e);
}
function letterKeyPressed(e) {
- if (e.which == 0 || e.altKey || e.ctrlKey || e.shiftKey) {
- // not a letter key
- return;
+ if (e.which == 0 || e.altKey || e.ctrlKey || e.shiftKey) {
+ // not a letter key
+ return;
+ }
+
+ var letter = String.fromCharCode(e.which).toUpperCase();
+
+ var x = cursor.x;
+ var y = cursor.y;
+ var tilePosition = -1;
+ for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
+ if (tray[i].letter == letter) {
+ tilePosition = i;
}
-
- var letter = String.fromCharCode(e.which).toUpperCase();
-
- var x = cursor.x;
- var y = cursor.y;
- var tilePosition = -1;
+ }
+ if (tilePosition == -1) {
for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
- if (tray[i].letter == letter) {
- tilePosition = i;
- }
- }
- if (tilePosition == -1) {
- for (var i = 0; (tilePosition == -1) && (i < tray.length); i++) {
- if (tray[i].letter == undefined) {
- tilePosition = i;
- }
- }
- }
- if (tilePosition == -1) {
- displayStatus('you-dont-have-that-letter', letter);
- } else {
- var isHoriz;
- if (move.length > 0) {
- isHoriz = (move[0].x != x);
- }
- cursor.advance(isHoriz);
- if (!letterAt(x, y)) {
- var tile = tray[tilePosition];
- tray.splice(tilePosition, 1);
- addLetterToMove(x, y, tile);
- }
+ if (tray[i].letter == undefined) {
+ tilePosition = i;
+ }
+ }
+ }
+ if (tilePosition == -1) {
+ displayStatus('you-dont-have-that-letter', letter);
+ } else {
+ var isHoriz;
+ if (move.length > 0) {
+ isHoriz = (move[0].x != x);
+ }
+ cursor.advance(isHoriz);
+ if (!letterAt(x, y)) {
+ var tile = tray[tilePosition];
+ tray.splice(tilePosition, 1);
+ addLetterToMove(x, y, tile, letter);
}
+ }
}
var leftKey = 37;
@@ -390,439 +384,200 @@
var backspaceKey = 8;
function functionKeyPressed(type, args, obj) {
- var x = cursor.x;
- var y = cursor.y;
+ var x = cursor.x;
+ var y = cursor.y;
- switch (args[0]) {
- case rightKey:
- while (x < 14)
- if (!letterAt(++x, y))
- break;
- break;
- case leftKey:
- while (x > 0)
- if (!letterAt(--x, y))
- break;
- break;
- case upKey:
- while (y > 0)
- if (!letterAt(x, --y))
- break;
- break;
- case downKey:
- while (y < 14)
- if (!letterAt(x, ++y))
- break;
- break;
- case backspaceKey:
- if (move.length) {
- removeLastLetterFromMove();
- }
- }
- if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) {
- cursor.clear();
- cursor.set(x, y);
+ switch (args[0]) {
+ case rightKey:
+ while (x < 14)
+ if (!letterAt(++x, y))
+ break;
+ break;
+ case leftKey:
+ while (x > 0)
+ if (!letterAt(--x, y))
+ break;
+ break;
+ case upKey:
+ while (y > 0)
+ if (!letterAt(x, --y))
+ break;
+ break;
+ case downKey:
+ while (y < 14)
+ if (!letterAt(x, ++y))
+ break;
+ break;
+ case backspaceKey:
+ if (move.length) {
+ removeLastLetterFromMove();
}
- YAHOO.util.Event.preventDefault(args[1]);
+ }
+ if ((x >= 0) && (x <= 14) && (y >= 0) && (y <= 14)) {
+ cursor.clear();
+ cursor.set(x, y);
+ }
+ YAHOO.util.Event.preventDefault(args[1]);
}
function clearBoard() {
- for (x = 0; x < 15; x++) {
- for (y = 0; y < 15; y++) {
- var letterNode = board[x][y].letterNode;
- if (letterNode) {
- letterNode.anim = new YAHOO.util.Motion(letterNode, { points: { to: [ border + 7 * 44 + 3,
- border + 7 * 44 + 3 ]}},
- 0.15);
- letterNode.anim.onComplete.subscribe(function () { removeElement(this); });
- letterNode.anim.animate();
- }
- }
+ for (x = 0; x < 15; x++) {
+ for (y = 0; y < 15; y++) {
+ var letterNode = board[x][y].letterNode;
+ if (letterNode) {
+ letterNode.anim = new YAHOO.util.Motion(letterNode, { points: { to: [ 7 * 44 + 3,
+ 7 * 44 + 3 ]}},
+ 0.15);
+ letterNode.anim.onComplete.subscribe(function () { removeElement(this); });
+ letterNode.anim.animate();
+ }
}
+ }
}
function trayClick(letter) {
- this.clicked = !this.clicked;
- this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
- this.anim.animate();
+ this.clicked = !this.clicked;
+ this.anim = new YAHOO.util.Motion(this, { points: { by: [ 0, (this.clicked ? 15 : -15 ) ]}}, 0.15);
+ this.anim.animate();
}
function displayMyTray(letters) {
- map(removeElement, tray);
- tray = [];
- for (var i = 0; i < letters.length; i++) {
- var element = IMG({src: 'images/' + letters[i].letterName + '.png'});
- element.letter = letters[i].letter;
- element.letterName = letters[i].letterName;
- element.style.position = 'absolute';
- element.style.width = '34px';
- element.style.height = '34px';
- element.style.zIndex = '10';
- element.onclick = trayClick;
- setElementPosition(element, { x: border + i * 40, y: border + 665 });
- tray[i] = element;
- }
- appendChildNodes($('playfield'), tray);
+ map(removeElement, tray);
+ tray = [];
+ for (var i = 0; i < letters.length; i++) {
+ var element = IMG({src: 'images/' + letters[i].letterName + '.png'});
+ element.letter = letters[i].letter;
+ element.letterName = letters[i].letterName;
+ element.style.position = 'absolute';
+ element.style.width = '34px';
+ element.style.height = '34px';
+ element.style.zIndex = '10';
+ element.onclick = trayClick;
+ setElementPosition(element, { x: i * 40, y: 665 });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
}
function shuffleMyTray() {
- var count = tray.length;
- var newTray = [];
- for (var i = 0; i < count; i++) {
- do {
- index = Math.floor(Math.random() * count);
- } while (newTray[index]);
- newTray[index] = tray[i];
- newTray[index].anim = new YAHOO.util.Motion(tray[i], { points: { to: [ border + 194 + i * 40,
- border + 665 ] }},
- 0.5);
- newTray[index].anim.animate();
- newTray[index].clicked = false;
- }
- tray = newTray;
+ var count = tray.length;
+ var newTray = [];
+ for (var i = 0; i < count; i++) {
+ do {
+ index = Math.floor(Math.random() * count);
+ } while (newTray[index]);
+ newTray[index] = tray[i];
+ newTray[index].anim = new YAHOO.util.Motion(tray[i], { points: { to: [ 194 + i * 40,
+ 665 ] }},
+ 0.5);
+ newTray[index].anim.animate();
+ newTray[index].clicked = false;
+ }
+ tray = newTray;
}
var otherPlayerIndex = 0;
function makeTheirTray (participant) {
- var tileCount = (typeof participant.remainingTiles == 'number') ? participant.remainingTiles : participant.remainingTiles.length;
+ var tileCount = (typeof participant.remainingTiles == 'number') ? participant.remainingTiles : participant.remainingTiles.length;
- var tray = [];
- for (var i = 0; i < tileCount; i++) {
- var element = IMG({src: 'images/null.png'});
- element.style.position = 'absolute';
- element.style.width = '34px';
- element.style.height = '34px';
- element.style.zIndex = '10';
- setElementPosition(element, { x: border + 680 + i * 40, y: border + 80 * otherPlayerIndex });
- tray[i] = element;
- }
- appendChildNodes($('playfield'), tray);
-
- var nameTag = DIV(null, participant.name);
- nameTag.style.position = 'absolute';
- nameTag.style.width = '200px';
- nameTag.style.textAlign = 'left';
- setElementPosition(nameTag, { x: border + 680, y: border + 80 * otherPlayerIndex + 50 });
- appendChildNodes($('playfield'), nameTag);
-
- var scoreTag = DIV(null, participant.score);
- scoreTag.style.position = 'absolute';
- scoreTag.style.width = '80px';
- scoreTag.style.textAlign = 'right';
- setElementPosition(scoreTag, { x: border + 870, y: border + 80 * otherPlayerIndex + 50 });
- appendChildNodes($('playfield'), scoreTag);
- $('playfield')['score-' + participant.login] = scoreTag;
+ var tray = [];
+ for (var i = 0; i < tileCount; i++) {
+ var element = IMG({src: 'images/null.png'});
+ element.style.position = 'absolute';
+ element.style.width = '34px';
+ element.style.height = '34px';
+ element.style.zIndex = '10';
+ setElementPosition(element, { x: 680 + i * 40, y: 80 * otherPlayerIndex });
+ tray[i] = element;
+ }
+ appendChildNodes($('playfield'), tray);
+
+ var nameTag = DIV(null, participant.name);
+ nameTag.style.position = 'absolute';
+ nameTag.style.width = '200px';
+ nameTag.style.textAlign = 'left';
+ setElementPosition(nameTag, { x: 680, y: 80 * otherPlayerIndex + 50 });
+ appendChildNodes($('playfield'), nameTag);
+
+ var scoreTag = DIV(null, participant.score);
+ scoreTag.style.position = 'absolute';
+ scoreTag.style.width = '80px';
+ scoreTag.style.textAlign = 'right';
+ setElementPosition(scoreTag, { x: 870, y: 80 * otherPlayerIndex + 50 });
+ appendChildNodes($('playfield'), scoreTag);
+ $('playfield')['score-' + participant.login] = scoreTag;
- otherPlayerIndex++;
+ otherPlayerIndex++;
}
function renderMoveAsText(move)
{
- var retval = move.participantLogin;
- if (move.type == 'move') {
- retval += " score: " + move.score;
- for (var i = 0; i < move.words.length; i++) {
- retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
- }
- } else {
- retval += move.type;
- }
+ var retval = move.participantLogin;
+ if (move.type == 'move') {
+ retval += " score: " + move.score;
+ for (var i = 0; i < move.words.length; i++) {
+ retval += " " + move.words[i][0] + "(" + move.words[i][1] + ")";
+ }
+ } else {
+ retval += move.type;
+ }
- return retval;
+ return retval;
}
function displayWhosTurnItIs(name) {
- replaceChildNodes($('nextTurn'),
- "Next: " + name);
+ replaceChildNodes($('nextTurn'),
+ "Next: " + name);
}
function drawGameState (gameState) {
- try {
- for (var i = 0; i < gameState.board.length; i++) {
- var x = gameState.board[i][0];
- var y = gameState.board[i][1];
- var char = gameState.board[i][2];
- setLetter(x, y, char, gameState.board[i].length > 3);
- }
- var firstParticipant = gameState.participants[0];
- displayWhosTurnItIs(firstParticipant.name);
- for (var i = 0; i < gameState.participants.length; i++) {
- var participant = gameState.participants[i];
- makeTheirTray(participant);
- if (typeof participant.remainingTiles != 'number') {
- displayMyTray(participant.remainingTiles);
- }
- }
- // small "Kilian fix" - probably there is a nicer way to do it...
- if (gameState.moves != null) {
- for (var i = 0; i < gameState.moves.length; i++) {
- appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i])));
- }
- }
- }
- catch (e) {
- alert('error ' + e + ' in drawGameState');
- }
+ try {
+ for (var i = 0; i < gameState.board.length; i++) {
+ var x = gameState.board[i][0];
+ var y = gameState.board[i][1];
+ var char = gameState.board[i][2];
+ setLetter(x, y, char, gameState.board[i].length > 3);
+ }
+ var firstParticipant = gameState.participants[0];
+ displayWhosTurnItIs(firstParticipant.name);
+ for (var i = 0; i < gameState.participants.length; i++) {
+ var participant = gameState.participants[i];
+ makeTheirTray(participant);
+ if (typeof participant.remainingTiles != 'number') {
+ displayMyTray(participant.remainingTiles);
+ }
+ }
+ for (var i = 0; gameState.moves && (i < gameState.moves.length); i++) {
+ appendChildNodes($('gameLog'), DIV(null, renderMoveAsText(gameState.moves[i])));
+ }
+ }
+ catch (e) {
+ alert('error ' + e + ' in drawGameState');
+ }
}
function displayStatus(status)
{
- replaceChildNodes('status', status);
+ replaceChildNodes('status', status);
}
+function init() {
+ makeBoard();
-// Publication
-
-function Publication() {
- this.callbacks = [];
- this.object2callback = {};
-}
-
-function extendWithPublication (obj) {
- var value;
- Publication.call(obj);
- for (p in Publication.prototype) {
- value = Publication.prototype[p];
- if (value instanceof Function)
- obj[p] = value;
- }
-}
-
-Publication.prototype = {
- subscribe : function(fnOrObject, /*optional*/ method) {
- if (!(((fnOrObject instanceof Function) && (method == undefined))
- || ((fnOrObject instanceof Object) && !(fnOrObject instanceof Function)
- && (method instanceof Function))))
- throw new Error("bad args to subscribe. use either subscribe(fn) or subscribe(obj, method)");
- if (this._isAlreadySubscribed(fnOrObject))
- return null;
- var callback = this._makeCallback(fnOrObject, method);
- this._associateObjectWithCallback(fnOrObject, callback);
- this._registerCallback(callback);
- },
- unsubscribe : function(fnOrObject) {
- var callback = this._associatedCallback(fnOrObject);
- this._unregisterCallback(callback);
- },
- unsubscribeAll : function() {
- this.callbacks = [];
- this.object2callback = {};
- },
- publish : function(/*optional*/ message) {
- this.callbacks.forEach(
- function (fn) {
- fn(message);
- });
- },
- _makeCallback : function (fnOrObject, /*optional*/ method) {
- if (fnOrObject instanceof Function) {
- return fnOrObject;
- } else {
- return function (message) { method.call(fnOrObject, message) };
- }
- },
- _associateObjectWithCallback : function (fnOrObject, callback) {
- if (!(fnOrObject instanceof Function)) {
- this.object2callback[fnOrObject] = callback;
- }
- },
- _associatedCallback : function (fnOrObject) {
- if (fnOrObject instanceof Function)
- return fnOrObject;
- else
- return this.callbacks[fnOrObject];
- },
- _registerCallback : function(callback) {
- this.callbacks.push(callback);
- },
- _unregisterCallback : function(callback) {
- this.callbacks = this.callbacks.filter(
- function (c) {
- (c === callback)
- });
- },
- _isAlreadySubscribed : function (fnOrObject) {
- return (this.object2callback[fnOrObject])
- || (this.callbacks.some(function (callback) {callback === fnOrObject}))
- }
-};
-
-// loginManager
-var loginManager = {isLoggedIn:
- function () {
- return this.loginName !== null;
- },
- loggedInAs:
- function () {
- return this.loginName;
- },
- login:
- function (name, pwd) {
- loadJSONDoc("/login?login=" + name + "&password=" + pwd).addCallbacks(
- this._requestLoginName,
- this._requestError);
- },
- logout:
- function () {
- loadJSONDoc("/logout").addCallbacks(
- this._requestLoginName,
- this._requestError);
- },
- publishLoginName:
- function () {
- this._requestLoginName();
- },
- _setLoginName:
- function (loginName) {
- var oldLoginName = loginManager.loginName;
- loginManager.loginName = loginName;
- // if (oldLoginName != loginName)
- // loginManager.publish(loginName);
- loginManager.publish(loginName);
- },
- _requestLoginName:
- function () {
- loadJSONDoc("/logged-in-as").addCallbacks(
- loginManager._setLoginName,
- loginManager._requestError);
- },
- _requestError:
- function (error) {
- alert("Request error: " + error.message)
- }
- };
-extendWithPublication(loginManager);
-
-var loginView = {loginManagerCallback:
- function (loginName) {
- if (loginName)
- loginView.changeForLoggedIn(loginName);
- else
- loginView.changeForLoggedOut();
- },
- show:
- function () {
- var container = $('playfield');
- var form = FORM({id:"loginForm", action:"post", onsubmit:"return false"},
- DIV(
- null,
- LABEL({'for':"username"}, "Username: "),
- INPUT({id:"username", name:"username", size:"20", type:"text"}),
- LABEL({'for':"password"}, "Password: "),
- INPUT({id:"password", name:"password", size:"20", type:"password"}),
- P({id:"message"}),
- BUTTON({id:"button", onlick:"return false"}, "Login")
- ));
- form.style.position = 'absolute';
- setElementPosition(form, { x: 750, y: 200 });
- setElementDimensions(form, {w:200, h:150});
- loginManager.subscribe(loginView, this.loginManagerCallback);
- appendChildNodes(container, form)
- },
- hide:
- function () {
- loginManager.subscribe(loginView, loginView.loginManagerCallback);
- removeElement($('loginForm'));
- },
- changeForLoggedIn:
- function (name) {
- loginView.hide();
- gameListView.show();
- },
- changeForLoggedOut:
- function () {
- $('message').innerHTML = "Enter your username and password to log in.";
- $('button').innerHTML = "Login";
- $('button').onclick = function () { loginManager.login($('username').value, $('password').value)};
- }};
-
-var gameListManager = {logout:
- function () {
- gameListView.hide();
- loginView.show();
- loginManager.logout();
- },
- playGame:
- function (id) {
- var d = loadJSONDoc("/play-game?gameid=" + id);
- d.addCallbacks(
- function () {
- var d = loadJSONDoc("/game");
- d.addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
- gameListView.hide();
- returnToGameListView.show();
- },
- requestError);
- }
- };
-
-var gameListView = {show:
- function () {
- var container = $('playfield');
- var div = DIV({id:"gameListView"});
- div.innerHTML = '<button onclick="gameListManager.logout();">Logout</button><br /><button onclick="gameListManager.playGame(108);">play game 108</button>';
- div.style.position = 'absolute';
- setElementPosition(div, { x: 750, y: 200 });
- setElementDimensions(div, {w:200, h:150});
- appendChildNodes(container, div);
- },
- hide:
- function () {
- removeElement($('gameListView'));
- }};
-
-
-// a stub really
-var returnToGameListView = {show:
- function () {
- var container = $('playfield');
- var button = BUTTON({id:'returnToGameListButton'}, "return to game list");
- button.style.position = 'absolute';
- setElementPosition(button, { x: 750, y: 200 });
- setElementDimensions(button, {w:150, h:30});
- YAHOO.util.Event.on(button, 'click', this.returnToGameList, null, this);
- // loginManager.subscribe(loginView, this.loginManagerCallback);
- appendChildNodes(container, button);
- },
- hide:
- function () {
- removeElement('returnToGameListButton');
- // FIXME for now we reload
- document.location = "scrabble.html";
- },
- returnToGameList:
- function () {
- var d = loadJSONDoc("/leave-game");
- d.addCallbacks(
- function () {
- returnToGameListView.hide();
- gameListView.show();
- },
- requestError)}
- };
-
+ // does not work for ie (document.body needed)?
+ YAHOO.util.Event.on(window, 'keypress', letterKeyPressed);
-function init() {
- makeBoard();
-
- // does not work for ie (document.body needed)?
- YAHOO.util.Event.on(window, 'keypress', letterKeyPressed);
-
- var functionKeyListener = new YAHOO.util.KeyListener(document,
- { keys: [ leftKey, upKey, rightKey, downKey, backspaceKey ] },
- { fn: functionKeyPressed, scope: this, correctScope: true });
- functionKeyListener.enable();
- var moveDisplay = DIV({ id: 'move' }, "");
- moveDisplay.style.color = 'white';
- moveDisplay.style.position = 'absolute';
- setElementPosition(moveDisplay, { x: border + 550, y: border + 665 });
- appendChildNodes(document.body, moveDisplay);
- loginView.show();
- loginManager.subscribe(function (loginName) {
- if (loginName) {
- // loginView.hide();
- }
- });
- loginManager.publishLoginName();
+ var functionKeyListener = new YAHOO.util.KeyListener(document,
+ { keys: [ leftKey, upKey, rightKey, downKey, backspaceKey ] },
+ { fn: functionKeyPressed, scope: this, correctScope: true });
+ functionKeyListener.enable();
+
+ var moveDisplay = DIV({ id: 'move' }, "");
+ moveDisplay.style.color = 'white';
+ moveDisplay.style.position = 'absolute';
+ setElementPosition(moveDisplay, { x: 550, y: 665 });
+ appendChildNodes(document.body, moveDisplay);
+ loadJSONDoc("/game/" + gameID)
+ .addCallbacks(drawGameState, function (error) { alert("Request error: " + error.message); });
}
Modified: branches/trunk-reorg/thirdparty/hunchentoot-0.14.7/misc.lisp
==============================================================================
--- branches/trunk-reorg/thirdparty/hunchentoot-0.14.7/misc.lisp (original)
+++ branches/trunk-reorg/thirdparty/hunchentoot-0.14.7/misc.lisp Thu Jan 17 11:36:28 2008
@@ -180,7 +180,10 @@
(defun enough-url (url url-prefix)
"Returns the relative portion of URL relative to URL-PREFIX, similar
to what ENOUGH-NAMESTRING does for pathnames."
- (subseq url (mismatch url url-prefix)))
+ (let ((start (mismatch url url-prefix)))
+ (if start
+ (subseq url start)
+ "")))
(defun create-folder-dispatcher-and-handler (uri-prefix base-path &optional content-type)
"Creates and returns a dispatch function which will dispatch to a
Modified: branches/trunk-reorg/thirdparty/parenscript/src/js-macrology.lisp
==============================================================================
--- branches/trunk-reorg/thirdparty/parenscript/src/js-macrology.lisp (original)
+++ branches/trunk-reorg/thirdparty/parenscript/src/js-macrology.lisp Thu Jan 17 11:36:28 2008
@@ -4,7 +4,9 @@
;;; literals
(defmacro defpsliteral (name string)
- `(define-ps-special-form ,name (expecting) (list 'js-literal ,string)))
+ `(define-ps-special-form ,name (expecting)
+ (declare (ignore expecting))
+ (list 'js-literal ,string)))
(defpsliteral this "this")
(defpsliteral t "true")
@@ -15,45 +17,54 @@
(defpsliteral undefined "undefined")
(defmacro defpskeyword (name string)
- `(define-ps-special-form ,name (expecting) (list 'js-keyword ,string)))
+ `(define-ps-special-form ,name (expecting)
+ (declare (ignore expecting))
+ (list 'js-keyword ,string)))
(defpskeyword break "break")
(defpskeyword continue "continue")
(define-ps-special-form array (expecting &rest values)
+ (declare (ignore expecting))
(cons 'array-literal (mapcar (lambda (form) (compile-parenscript-form form :expecting :expression))
values)))
(define-ps-special-form aref (expecting array &rest coords)
+ (declare (ignore expecting))
(list 'js-aref (compile-parenscript-form array :expecting :expression)
(mapcar (lambda (form)
(compile-parenscript-form form :expecting :expression))
coords)))
(define-ps-special-form {} (expecting &rest arrows)
+ (declare (ignore expecting))
(cons 'object-literal (loop for (key value) on arrows by #'cddr
collect (cons key (compile-parenscript-form value :expecting :expression)))))
;;; operators
(define-ps-special-form incf (expecting x &optional (delta 1))
+ (declare (ignore expecting))
(if (equal delta 1)
(list 'unary-operator "++" (compile-parenscript-form x :expecting :expression) :prefix t)
(list 'operator '+= (list (compile-parenscript-form x :expecting :expression)
(compile-parenscript-form delta :expecting :expression)))))
(define-ps-special-form decf (expecting x &optional (delta 1))
+ (declare (ignore expecting))
(if (equal delta 1)
(list 'unary-operator "--" (compile-parenscript-form x :expecting :expression) :prefix t)
(list 'operator '-= (list (compile-parenscript-form x :expecting :expression)
(compile-parenscript-form delta :expecting :expression)))))
(define-ps-special-form - (expecting first &rest rest)
+ (declare (ignore expecting))
(if (null rest)
(list 'unary-operator "-" (compile-parenscript-form first :expecting :expression) :prefix t)
(list 'operator '- (mapcar (lambda (val) (compile-parenscript-form val :expecting :expression))
(cons first rest)))))
(define-ps-special-form not (expecting x)
+ (declare (ignore expecting))
(let ((form (compile-parenscript-form x :expecting :expression))
(not-op nil))
(if (and (eql (first form) 'operator)
@@ -72,6 +83,7 @@
(list 'unary-operator "!" form :prefix t))))
(define-ps-special-form ~ (expecting x)
+ (declare (ignore expecting))
(list 'unary-operator "~" (compile-parenscript-form x :expecting :expressin) :prefix t))
(defun flatten-blocks (body)
@@ -97,18 +109,21 @@
;;; function definition
(define-ps-special-form %js-lambda (expecting args &rest body)
+ (declare (ignore expecting))
(list 'js-lambda (mapcar (lambda (arg)
(compile-parenscript-form arg :expecting :symbol))
args)
(compile-parenscript-form `(progn , at body))))
(define-ps-special-form %js-defun (expecting name args &rest body)
+ (declare (ignore expecting))
(list 'js-defun (compile-parenscript-form name :expecting :symbol)
(mapcar (lambda (val) (compile-parenscript-form val :expecting :symbol)) args)
(compile-parenscript-form `(progn , at body))))
;;; object creation
(define-ps-special-form create (expecting &rest args)
+ (declare (ignore expecting))
(list 'js-object (loop for (name val) on args by #'cddr collecting
(let ((name-expr (compile-parenscript-form name :expecting :expression)))
(assert (or (stringp name-expr)
@@ -121,6 +136,7 @@
(list name-expr (compile-parenscript-form val :expecting :expression))))))
(define-ps-special-form %js-slot-value (expecting obj slot)
+ (declare (ignore expecting))
(if (ps::ps-macroexpand slot)
(list 'js-slot-value (compile-parenscript-form obj :expecting :expression) (compile-parenscript-form slot))
(compile-parenscript-form obj :expecting :expression)))
@@ -157,6 +173,7 @@
(compile-parenscript-form else :expecting :expression)))))
(define-ps-special-form switch (expecting test-expr &rest clauses)
+ (declare (ignore expecting))
(let ((clauses (mapcar (lambda (clause)
(let ((val (car clause))
(body (cdr clause)))
@@ -207,9 +224,11 @@
(list 'js-assign lhs rhs)))
(define-ps-special-form setf1% (expecting lhs rhs)
+ (declare (ignore expecting))
(smart-setf (compile-parenscript-form lhs :expecting :expression) (compile-parenscript-form rhs :expecting :expression)))
(define-ps-special-form defvar (expecting name &rest value)
+ (declare (ignore expecting))
(append (list 'js-defvar (compile-parenscript-form name :expecting :symbol))
(when value
(assert (= (length value) 1) () "Wrong number of arguments to defvar: ~s" `(defvar ,name , at value))
@@ -228,6 +247,7 @@
collect (compile-parenscript-form (third decl) :expecting :expression)))
(define-ps-special-form do (expecting decls termination-test &rest body)
+ (declare (ignore expecting))
(let ((vars (make-for-vars decls))
(steps (make-for-steps decls))
(test (compile-parenscript-form `(not ,(first termination-test)) :expecting :expression))
@@ -235,20 +255,24 @@
(list 'js-for vars steps test body)))
(define-ps-special-form doeach (expecting decl &rest body)
+ (declare (ignore expecting))
(list 'js-for-each
(compile-parenscript-form (first decl) :expecting :symbol)
(compile-parenscript-form (second decl) :expecting :expression)
(compile-parenscript-form `(progn , at body))))
(define-ps-special-form while (expecting test &rest body)
+ (declare (ignore expecting))
(list 'js-while (compile-parenscript-form test :expecting :expression)
(compile-parenscript-form `(progn , at body))))
(define-ps-special-form with (expecting expression &rest body)
+ (declare (ignore expecting))
(list 'js-with (compile-parenscript-form expression :expecting :expression)
(compile-parenscript-form `(progn , at body))))
(define-ps-special-form try (expecting form &rest clauses)
+ (declare (ignore expecting))
(let ((catch (cdr (assoc :catch clauses)))
(finally (cdr (assoc :finally clauses))))
(assert (not (cdar catch)) nil "Sorry, currently only simple catch forms are supported.")
@@ -260,23 +284,28 @@
:finally (when finally (compile-parenscript-form `(progn , at finally))))))
(define-ps-special-form regex (expecting regex)
+ (declare (ignore expecting))
(list 'js-regex (string regex)))
;;; TODO instanceof
(define-ps-special-form instanceof (expecting value type)
+ (declare (ignore expecting))
(list 'js-instanceof (compile-parenscript-form value :expecting :expression)
(compile-parenscript-form type :expecting :expression)))
;;; single operations
(mapcar (lambda (op) (eval `(define-ps-special-form ,op (expecting value)
+ (declare (ignore expecting))
(list 'js-named-operator ',op (compile-parenscript-form value)))))
'(throw delete void typeof new))
(define-ps-special-form return (expecting &optional value)
+ (declare (ignore expecting))
(list 'js-return (compile-parenscript-form value :expecting :expression)))
;;; conditional compilation
(define-ps-special-form cc-if (expecting test &rest body)
+ (declare (ignore expecting))
(list 'cc-if test (mapcar #'compile-parenscript-form body)))
;;; standard macros
Modified: branches/trunk-reorg/thirdparty/slime/slime.el
==============================================================================
--- branches/trunk-reorg/thirdparty/slime/slime.el (original)
+++ branches/trunk-reorg/thirdparty/slime/slime.el Thu Jan 17 11:36:28 2008
@@ -6287,7 +6287,9 @@
("*SLIME macroexpansion*" :mode lisp-mode :reusep t) package
(slime-macroexpansion-minor-mode)
(erase-buffer)
- (insert expansion)
+ (save-excursion
+ (insert expansion))
+ (indent-sexp)
(font-lock-fontify-buffer))))))
(defun slime-eval-macroexpand-inplace (expander)
@@ -6316,6 +6318,59 @@
(indent-sexp)
(goto-char point))))))))
+(defun slime-enclosing-macro-context-establishers ()
+ (flet ((establishes-context-p (form-spec)
+ (let ((operator-name (first form-spec)))
+ (when (stringp operator-name)
+ (let ((symbol-name (slime-cl-symbol-name operator-name)))
+ (or (equal symbol-name "macrolet") (equal symbol-name "symbol-macrolet")))))))
+ (multiple-value-bind (form-specs indices points)
+ (slime-enclosing-form-specs)
+ (loop for form-spec in form-specs
+ for index in indices
+ for point in points
+ when (establishes-context-p form-spec)
+ collect form-spec into form-specs* and
+ collect index into indices* and
+ collect point into points*
+ finally (return (values form-specs* indices* points*))))))
+
+(defun slime-collect-macro-context ()
+ (multiple-value-bind (form-specs indices points)
+ (slime-enclosing-macro-context-establishers)
+ (save-excursion
+ (let ((context))
+ (cl-mapc #'(lambda (form-spec index point)
+ (when (= index 2)
+ (destructuring-bind (operator-name) form-spec
+ (goto-char point)
+ (slime-forward-sexp)
+ (forward-char)
+ (push (cons operator-name (slime-parse-sexp-at-point 1 t)) context))))
+ form-specs indices points)
+ context))))
+
+(defun slime-rebuild-macro-context-around-string (string context)
+ (if (null context)
+ string
+ (destructuring-bind (let-operator . bindings) (first context)
+ (format "(%s %s %s)" let-operator bindings
+ (slime-rebuild-macro-context-around-string string (rest context))))))
+
+(defun slime-macroexpand-locally-1 (&optional repeatedly)
+ (interactive "P")
+ (let ((sexp (first (slime-sexp-at-point-for-macroexpansion)))
+ (macro-context (slime-collect-macro-context)))
+ (if repeatedly
+ (slime-eval-macroexpand 'swank:swank-macroexpand-locally
+ (slime-rebuild-macro-context-around-string
+ (format "(swank::macroexpand-locally %s)" sexp)
+ macro-context))
+ (slime-eval-macroexpand 'swank:swank-macroexpand-locally-1
+ (slime-rebuild-macro-context-around-string
+ (format "(swank::macroexpand-locally-1 %s)" sexp)
+ macro-context)))))
+
(defun slime-macroexpand-1 (&optional repeatedly)
"Display the macro expansion of the form at point. The form is
expanded with CL:MACROEXPAND-1 or, if a prefix argument is given, with
Modified: branches/trunk-reorg/thirdparty/slime/swank.lisp
==============================================================================
--- branches/trunk-reorg/thirdparty/slime/swank.lisp (original)
+++ branches/trunk-reorg/thirdparty/slime/swank.lisp Thu Jan 17 11:36:28 2008
@@ -78,7 +78,8 @@
"Abbreviate dotted package names to their last component if T.")
(defvar *swank-io-package*
- (let ((package (make-package :swank-io-package :use '())))
+ (let ((package (or (find-package :swank-io-package)
+ (make-package :swank-io-package :use '()))))
(import '(nil t quote) package)
package))
@@ -2401,6 +2402,22 @@
(let ((*print-readably* nil))
(disassemble (fdefinition (from-string name)))))))
+(defslimefun swank-macroexpand-locally (string)
+ (apply-macro-expander #'eval string))
+
+(defslimefun swank-macroexpand-locally-1 (string)
+ (apply-macro-expander #'eval string))
+
+(defmacro macroexpand-locally (form &environment env)
+ (multiple-value-bind (expansion expanded-p)
+ (macroexpand form env)
+ `(values ',expansion ',expanded-p)))
+
+(defmacro macroexpand-locally-1 (form &environment env)
+ (multiple-value-bind (expansion expanded-p)
+ (macroexpand-1 form env)
+ `(values ',expansion ',expanded-p)))
+
;;;; Simple completion
More information about the Bknr-cvs
mailing list