bknr-cvs
Threads by month
- ----- 2025 -----
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- 1964 discussions

[bknr-cvs] r2342 - in branches/bos/projects/bos: m2 web worldpay-test
by hhubner@common-lisp.net 18 Jan '08
by hhubner@common-lisp.net 18 Jan '08
18 Jan '08
Author: hhubner
Date: Fri Jan 18 02:53:56 2008
New Revision: 2342
Added:
branches/bos/projects/bos/worldpay-test/bos.web.asd
- copied, changed from r2337, branches/bos/projects/bos/worldpay-test/worldpay-test.asd
branches/bos/projects/bos/worldpay-test/web.lisp
- copied, changed from r2337, branches/bos/projects/bos/web/web.lisp
branches/bos/projects/bos/worldpay-test/webserver.lisp
- copied, changed from r2337, branches/bos/projects/bos/worldpay-test/worldpay-test.lisp
Removed:
branches/bos/projects/bos/web/
branches/bos/projects/bos/worldpay-test/worldpay-test.asd
branches/bos/projects/bos/worldpay-test/worldpay-test.lisp
Modified:
branches/bos/projects/bos/m2/mail-generator.lisp
branches/bos/projects/bos/worldpay-test/allocation-area-handlers.lisp
branches/bos/projects/bos/worldpay-test/boi-handlers.lisp
branches/bos/projects/bos/worldpay-test/cms-links.lisp
branches/bos/projects/bos/worldpay-test/config.lisp
branches/bos/projects/bos/worldpay-test/contract-handlers.lisp
branches/bos/projects/bos/worldpay-test/contract-image-handler.lisp
branches/bos/projects/bos/worldpay-test/contract-rss.lisp
branches/bos/projects/bos/worldpay-test/daily.lisp
branches/bos/projects/bos/worldpay-test/languages-handler.lisp
branches/bos/projects/bos/worldpay-test/map-browser-handler.lisp
branches/bos/projects/bos/worldpay-test/map-handlers.lisp
branches/bos/projects/bos/worldpay-test/news-handlers.lisp
branches/bos/projects/bos/worldpay-test/news-rss.lisp
branches/bos/projects/bos/worldpay-test/news-tags.lisp
branches/bos/projects/bos/worldpay-test/packages.lisp
branches/bos/projects/bos/worldpay-test/poi-handlers.lisp
branches/bos/projects/bos/worldpay-test/reports-xml-handler.lisp
branches/bos/projects/bos/worldpay-test/rss.lisp
branches/bos/projects/bos/worldpay-test/spendenquittung.lisp
branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp
branches/bos/projects/bos/worldpay-test/tags.lisp
branches/bos/projects/bos/worldpay-test/utils.lisp
branches/bos/projects/bos/worldpay-test/web-macros.lisp
branches/bos/projects/bos/worldpay-test/web-utils.lisp
Log:
rename worldpay-test -> bos.web, step 1
Modified: branches/bos/projects/bos/m2/mail-generator.lisp
==============================================================================
--- branches/bos/projects/bos/m2/mail-generator.lisp (original)
+++ branches/bos/projects/bos/m2/mail-generator.lisp Fri Jan 18 02:53:56 2008
@@ -45,7 +45,7 @@
(defun mail-template-directory (language)
"Return the directory where the mail templates are stored"
(merge-pathnames (make-pathname :directory `(:relative "templates" ,(string-downcase language)))
- (symbol-value (find-symbol "*WEBSITE-DIRECTORY*" "WORLDPAY-TEST"))))
+ (symbol-value (find-symbol "*WEBSITE-DIRECTORY*" "BOS.WEB"))))
(defun rest-of-file (file)
(let ((result (make-array (- (file-length file)
Modified: branches/bos/projects/bos/worldpay-test/allocation-area-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/allocation-area-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/allocation-area-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/boi-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/boi-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/boi-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Copied: branches/bos/projects/bos/worldpay-test/bos.web.asd (from r2337, branches/bos/projects/bos/worldpay-test/worldpay-test.asd)
==============================================================================
--- branches/bos/projects/bos/worldpay-test/worldpay-test.asd (original)
+++ branches/bos/projects/bos/worldpay-test/bos.web.asd Fri Jan 18 02:53:56 2008
@@ -38,7 +38,15 @@
(:file "news-tags" :depends-on ("web-utils"))
(:file "news-rss" :depends-on ("web-utils"))
(:file "contract-rss" :depends-on ("web-utils"))
- (:file "worldpay-test" :depends-on ("news-tags" "tags" "map-handlers" "map-browser-handler" "poi-handlers"
- "boi-handlers" "contract-handlers" "sponsor-handlers" "news-handlers"
- "allocation-area-handlers"))
- (:file "daily" :depends-on ("config" "worldpay-test"))))
+ (:file "webserver" :depends-on ("news-tags"
+ "tags"
+ "map-handlers"
+ "map-browser-handler"
+ "poi-handlers"
+ "boi-handlers"
+ "contract-handlers"
+ "sponsor-handlers"
+ "news-handlers"
+ "allocation-area-handlers"))
+ (:file "daily" :depends-on ("config" "webserver"))
+ (:file "startup" :depends-on ("config" "webserver"))))
Modified: branches/bos/projects/bos/worldpay-test/cms-links.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/cms-links.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/cms-links.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/config.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/config.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/config.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
;; Worldpay (headcraft inst id ist 102532
(defparameter *worldpay-installation-id* 103530
Modified: branches/bos/projects/bos/worldpay-test/contract-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/contract-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/contract-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/contract-image-handler.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/contract-image-handler.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/contract-image-handler.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/contract-rss.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/contract-rss.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/contract-rss.lisp Fri Jan 18 02:53:56 2008
@@ -7,7 +7,7 @@
(contract-paidp contract))
(defmethod rss-item-title ((contract contract))
- (format nil (case (intern (worldpay-test::current-website-language))
+ (format nil (case (intern (bos.web::current-website-language))
(de "~A Quadratmeter wurden ~@[von ~A ~]gekauft")
(t "~A square meters bought~@[ by ~A~]"))
(length (contract-m2s contract))
@@ -18,11 +18,11 @@
(defmethod rss-item-link ((contract contract))
#+(or)
- (format nil "http://createrainforest.org/~A/news-extern/~A" (worldpay-test::current-website-language) (store-object-id item)))
+ (format nil "http://createrainforest.org/~A/news-extern/~A" (bos.web::current-website-language) (store-object-id item)))
(defmethod rss-item-guid ((item contract))
#+(or)
- (format nil "http://createrainforest.org/~A/news-extern/~A" (worldpay-test::current-website-language) (store-object-id item)))
+ (format nil "http://createrainforest.org/~A/news-extern/~A" (bos.web::current-website-language) (store-object-id item)))
(defmethod rss-item-pub-date ((contract contract))
(contract-date contract))
Modified: branches/bos/projects/bos/worldpay-test/daily.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/daily.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/daily.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(defun daily-cleanup ()
(format t "; performing daily cleanup run~%")
Modified: branches/bos/projects/bos/worldpay-test/languages-handler.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/languages-handler.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/languages-handler.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/map-browser-handler.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/map-browser-handler.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/map-browser-handler.lisp Fri Jan 18 02:53:56 2008
@@ -1,7 +1,7 @@
; please don't read this code, it is not pretty
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/map-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/map-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/map-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/news-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/news-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/news-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/news-rss.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/news-rss.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/news-rss.lisp Fri Jan 18 02:53:56 2008
@@ -4,19 +4,19 @@
"news")
(defmethod rss-item-published ((item news-item))
- (news-item-published item (worldpay-test::current-website-language)))
+ (news-item-published item (bos.web::current-website-language)))
(defmethod rss-item-title ((item news-item))
- (news-item-title item (worldpay-test::current-website-language)))
+ (news-item-title item (bos.web::current-website-language)))
(defmethod rss-item-description ((item news-item))
- (news-item-text item (worldpay-test::current-website-language)))
+ (news-item-text item (bos.web::current-website-language)))
(defmethod rss-item-link ((item news-item))
- (format nil "http://createrainforest.org/~A/news-extern/~A" (worldpay-test::current-website-language) (store-object-id item)))
+ (format nil "http://createrainforest.org/~A/news-extern/~A" (bos.web::current-website-language) (store-object-id item)))
(defmethod rss-item-guid ((item news-item))
- (format nil "http://createrainforest.org/~A/news-extern/~A" (worldpay-test::current-website-language) (store-object-id item)))
+ (format nil "http://createrainforest.org/~A/news-extern/~A" (bos.web::current-website-language) (store-object-id item)))
(defmethod rss-item-pub-date ((item news-item))
(news-item-time item))
Modified: branches/bos/projects/bos/worldpay-test/news-tags.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/news-tags.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/news-tags.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/packages.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/packages.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/packages.lisp Fri Jan 18 02:53:56 2008
@@ -1,6 +1,6 @@
(in-package :cl-user)
-(defpackage :worldpay-test
+(defpackage :bos.web
(:use :cl
:date-calc
#+cmu :extensions
Modified: branches/bos/projects/bos/worldpay-test/poi-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/poi-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/poi-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/reports-xml-handler.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/reports-xml-handler.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/reports-xml-handler.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
@@ -29,7 +29,7 @@
(not (eql *year* (contract-year contract))))))
(class-instances 'contract))
#'< :key #'contract-date)))
- (setf name (intern (string-upcase name) :worldpay-test))
+ (setf name (intern (string-upcase name) :bos.web))
(apply (or (gethash name *report-generators*)
(error "invalid report name ~A" name))
arguments)))))
Modified: branches/bos/projects/bos/worldpay-test/rss.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/rss.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/rss.lisp Fri Jan 18 02:53:56 2008
@@ -1,6 +1,6 @@
;; 2008-01-15: currently not used in the production core
-(in-package :worldpay-test)
+(in-package :bos.web)
(defmethod rss-item-channel ((item news-item))
"news")
Modified: branches/bos/projects/bos/worldpay-test/spendenquittung.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/spendenquittung.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/spendenquittung.lisp Fri Jan 18 02:53:56 2008
@@ -91,7 +91,7 @@
(with-output-to-string (s)
(pdf:write-document s))))
-(in-package :worldpay-test)
+(in-package :bos.web)
(defvar *mail-sender-name* "BOS Deutschland e.V.")
(defvar *mail-sender-address* "spendenbescheinigung(a)bos-deutschland.de")
Modified: branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/tags.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/tags.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/tags.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/utils.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/utils.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/utils.lisp Fri Jan 18 02:53:56 2008
@@ -1,6 +1,6 @@
;; 2008-01-15: currently not used in the production core
-(in-package :worldpay-test)
+(in-package :bos.web)
;;; date format
Modified: branches/bos/projects/bos/worldpay-test/web-macros.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/web-macros.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/web-macros.lisp Fri Jan 18 02:53:56 2008
@@ -1,4 +1,4 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Modified: branches/bos/projects/bos/worldpay-test/web-utils.lisp
==============================================================================
--- branches/bos/projects/bos/worldpay-test/web-utils.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/web-utils.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
Copied: branches/bos/projects/bos/worldpay-test/web.lisp (from r2337, branches/bos/projects/bos/web/web.lisp)
==============================================================================
--- branches/bos/projects/bos/web/web.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/web.lisp Fri Jan 18 02:53:56 2008
@@ -30,10 +30,10 @@
(defun reinit (&key debug)
(format t "~&; Publishing BOS handlers.~%")
(unpublish :all t)
- (worldpay-test::publish-worldpay-test :website-directory *website-directory*
- :vhosts *vhosts*
- :website-url *website-url*
- :worldpay-test-mode *worldpay-test-mode*)
+ (bos.web::publish-website :website-directory *website-directory*
+ :vhosts *vhosts*
+ :website-url *website-url*
+ :worldpay-test-mode *worldpay-test-mode*)
(format t "~&; Starting aserve~@[ in debug mode~].~%" debug)
(force-output)
(setq *webserver*
Copied: branches/bos/projects/bos/worldpay-test/webserver.lisp (from r2337, branches/bos/projects/bos/worldpay-test/worldpay-test.lisp)
==============================================================================
--- branches/bos/projects/bos/worldpay-test/worldpay-test.lisp (original)
+++ branches/bos/projects/bos/worldpay-test/webserver.lisp Fri Jan 18 02:53:56 2008
@@ -1,5 +1,5 @@
-(in-package :worldpay-test)
+(in-package :bos.web)
(enable-interpol-syntax)
@@ -174,7 +174,7 @@
(find-browser-prefered-language req)
*default-language*)))))
-(defun publish-worldpay-test (&key website-directory website-url (worldpay-test-mode t) (vhosts :wild))
+(defun publish-website (&key website-directory website-url (worldpay-test-mode t) (vhosts :wild))
(setf *website-directory* website-directory)
(when website-url
@@ -219,7 +219,7 @@
("/index" index-handler)
("/" worldpay-template-handler
:destination ,(namestring (merge-pathnames #p"templates/" website-directory))
- :command-packages ((:bos . :worldpay-test)
+ :command-packages ((:bos . :bos.web)
(:bknr . :bknr.web))))
:modules '(user images stats)
:navigation '(("sponsor" . "edit-sponsor/")
1
0
Author: hhubner
Date: Fri Jan 18 02:45:07 2008
New Revision: 2341
Modified:
branches/bos/projects/bos/README
Log:
small corrections to better reflect reality
Modified: branches/bos/projects/bos/README
==============================================================================
--- branches/bos/projects/bos/README (original)
+++ branches/bos/projects/bos/README Fri Jan 18 02:45:07 2008
@@ -6,14 +6,14 @@
- CMUCL 19c installieren, so dass "lisp" im Pfad ist
- - Komplettes cvs auschecken:
- $ cvs -d :ext:bknr.net:/home/bknr/cvs co -d bknr.net .
+ - Komplettes svn auschecken:
+ $ svn co svn+ssh://common-lisp.net/project/bknr/svn/branches/bos/projects/bos bknr-svn
Image bauen
-----------
- Im BOS-Verzeichnis eingeben
- bknr.net/bos$ ./build.sh --clean
+ bknr.net/bos$ ./build.sh
(--clean loescht fasls vor dem Kompilieren.)
- Heraus kommt das Imagefile "bos.core", das auf den Kundenserver
1
0
Author: hhubner
Date: Thu Jan 17 12:09:12 2008
New Revision: 2340
Modified:
branches/bos/projects/bos/m2/map.lisp
Log:
If no background image is available, just skip the :background operation.
Modified: branches/bos/projects/bos/m2/map.lisp
==============================================================================
--- branches/bos/projects/bos/m2/map.lisp (original)
+++ branches/bos/projects/bos/m2/map.lisp Thu Jan 17 12:09:12 2008
@@ -118,8 +118,9 @@
original-image))
(defmethod image-tile-process ((tile image-tile) (operation (eql :background)))
- (with-store-image (original-image (image-tile-original-image tile))
- (copy-image original-image *default-image* 0 0 0 0 (image-width) (image-height))))
+ (when (image-tile-original-image tile)
+ (with-store-image (original-image (image-tile-original-image tile))
+ (copy-image original-image *default-image* 0 0 0 0 (image-width) (image-height)))))
(defmethod image-tile-process ((tile image-tile) (operation (eql :areas)))
(do-rows (y)
1
0
Author: ksprotte
Date: Thu Jan 17 11:52:36 2008
New Revision: 2339
Added:
branches/bos-ksprotte/
- copied from r2338, branches/bos/
Log:
created new test branch for ksprotte
1
0
Author: ksprotte
Date: Thu Jan 17 11:51:11 2008
New Revision: 2338
Removed:
branches/bos-sehr-alt/
Log:
rm branch bos-sehr-alt
1
0
Author: ksprotte
Date: Thu Jan 17 11:39:36 2008
New Revision: 2337
Modified:
branches/bos/projects/bos/m2/packages.lisp
Log:
again prefix rename
Modified: branches/bos/projects/bos/m2/packages.lisp
==============================================================================
--- branches/bos/projects/bos/m2/packages.lisp (original)
+++ branches/bos/projects/bos/m2/packages.lisp Thu Jan 17 11:39:36 2008
@@ -229,9 +229,9 @@
:bos.m2.config
:iterate)
(:import-from :bos.m2 bos.m2::point-in-polygon-p)
- (:export #:allocation-cache-find-exact-match
- #:allocation-cache-add-area
- #:allocation-cache-free-regions-count
- #:allocation-cache-free-regions-pprint
+ (:export #:find-exact-match
+ #:add-area
+ #:free-regions-count
+ #:free-regions-pprint
#:rebuild-cache))
1
0

[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
by hhubner@common-lisp.net 17 Jan '08
by hhubner@common-lisp.net 17 Jan '08
17 Jan '08
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 ,@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 ,@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 ,@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 ,@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 ,@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 ,@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 ,@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
1
0
Author: ksprotte
Date: Thu Jan 17 11:30:34 2008
New Revision: 2335
Modified:
branches/bos/projects/bos/m2/allocation-cache.lisp
branches/bos/projects/bos/m2/allocation.lisp
branches/bos/projects/bos/m2/packages.lisp
Log:
stripped allocation-cache- prefix from some functions
Modified: branches/bos/projects/bos/m2/allocation-cache.lisp
==============================================================================
--- branches/bos/projects/bos/m2/allocation-cache.lisp (original)
+++ branches/bos/projects/bos/m2/allocation-cache.lisp Thu Jan 17 11:30:34 2008
@@ -135,7 +135,7 @@
"Are regions of size N indexed?"
(<= 1 n +threshold+))
-(defun allocation-cache-find-exact-match (n &key remove)
+(defun find-exact-match (n &key remove)
"Will return a free contigous region of size N
as a list of m2 instances. If no such region exactly
matching N can be found, simply returns NIL.
@@ -147,7 +147,7 @@
(remove (index-pop n))
(t (index-lookup n))))
-(defun allocation-cache-add-area (allocation-area)
+(defun add-area (allocation-area)
(dolist (region (free-regions allocation-area)
allocation-area)
(let ((size (length region)))
@@ -155,12 +155,12 @@
(index-push size region)
(incf (ignored-size *allocation-cache*) size)))))
-(defun allocation-cache-free-regions-count ()
+(defun free-regions-count ()
(iter
(for regions in-vector (allocation-cache-index *allocation-cache*))
(summing (length regions))))
-(defun allocation-cache-free-regions-pprint ()
+(defun free-regions-pprint ()
(iter
(for regions in-vector (allocation-cache-index *allocation-cache*))
(for size upfrom 1)
@@ -173,7 +173,7 @@
(setq *allocation-cache* (make-allocation-cache))
(dolist (allocation-area (class-instances 'allocation-area))
(when (allocation-area-active-p allocation-area)
- (allocation-cache-add-area allocation-area))))
+ (add-area allocation-area))))
(defun suggest-free-region-size ()
(iter
Modified: branches/bos/projects/bos/m2/allocation.lisp
==============================================================================
--- branches/bos/projects/bos/m2/allocation.lisp (original)
+++ branches/bos/projects/bos/m2/allocation.lisp Thu Jan 17 11:30:34 2008
@@ -625,7 +625,7 @@
(assert (plusp n))
(unless (in-transaction-p)
(error "find-free-m2s called outside of the allocation transaction"))
- (or (bos.m2.allocation-cache:allocation-cache-find-exact-match n :remove t)
+ (or (bos.m2.allocation-cache:find-exact-match n :remove t)
(some (lambda (area) (allocation-area-find-free-m2s area n))
(active-allocation-areas))
(let ((area (find-inactive-allocation-area)))
Modified: branches/bos/projects/bos/m2/packages.lisp
==============================================================================
--- branches/bos/projects/bos/m2/packages.lisp (original)
+++ branches/bos/projects/bos/m2/packages.lisp Thu Jan 17 11:30:34 2008
@@ -211,6 +211,9 @@
(:shadowing-import-from :cl-interpol #:quote-meta-chars)
(:export #:cert-daemon))
+;;; maybe there is a nicer way to do this
+;;; if you want to test this run ./build.sh at least twice !
+(intern "POINT-IN-POLYGON-P" :bos.m2)
(defpackage :bos.m2.allocation-cache
(:use :cl
1
0
Author: hhubner
Date: Thu Jan 17 10:56:30 2008
New Revision: 2334
Added:
branches/bos/projects/bos/screenrc
Log:
Add screenrc used on the test server
Added: branches/bos/projects/bos/screenrc
==============================================================================
--- (empty file)
+++ branches/bos/projects/bos/screenrc Thu Jan 17 10:56:30 2008
@@ -0,0 +1,20 @@
+multiuser on
+acladd hans
+
+zombie qr
+defscrollback 5000
+startup_message off
+vbell on
+vbellwait 0
+msgminwait 0
+msgwait 0
+
+chdir /home/hans/bknr-svn/projects/bos
+
+screen -t webserver lisp -core bos.core -slime
+#logfile screen.log
+#log on
+screen -t cert-daemon lisp -core bos.core -cert-daemon
+
+msgminwait 1
+msgwait 1
1
0
Author: hhubner
Date: 2008-01-17 10:50:04 -0500 (Thu, 17 Jan 2008)
New Revision: 2332
Modified:
branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp
Log:
Fix message after cert regeneration.
Modified: branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp
===================================================================
--- branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp 2008-01-17 15:24:19 UTC (rev 2331)
+++ branches/bos/projects/bos/worldpay-test/sponsor-handlers.lisp 2008-01-17 15:50:04 UTC (rev 2332)
@@ -324,10 +324,9 @@
(with-query-params (req name address language)
(contract-issue-cert contract name :address address :language language))
(with-bos-cms-page (req :title "Certificate has been recreated")
- (html "The certificates for the sponsor have been re-generated.")
+ (html "The certificates for the sponsor have been re-generated." :br)
(unless (contract-download-only-p contract)
(mail-print-pdf contract)
- (let ((sponsor (contract-sponsor contract)))
- (html "The print certificate has been sent to the relevant BOS office address by email."
- :br
- (cmslink #?"edit-sponsor/$((store-object-id sponsor))" "return to sponsor"))))))
\ No newline at end of file
+ (html "The print certificate has been sent to the relevant BOS office address by email." :br))
+ (let ((sponsor (contract-sponsor contract)))
+ (cmslink #?"edit-sponsor/$((store-object-id sponsor))" "return to sponsor"))))
\ No newline at end of file
1
0