Advanced version of the chess game chess
authorJaroslav Tulach <jaroslav.tulach@apidesign.org>
Tue, 24 Sep 2013 22:20:24 +0200
branchchess
changeset 49945fbfff28f3
parent 48 4dbbfc8310b0
child 50 49011b4a2689
Advanced version of the chess game
chess/nbactions-bck2brwsr.xml
chess/nbactions-iOSDeploy.xml
chess/nbactions.xml
chess/pom.xml
chess/src/main/assembly/bck2brwsr.xml
chess/src/main/java/com/oracle/chess/client/htmljava/BoardModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/Color.java
chess/src/main/java/com/oracle/chess/client/htmljava/Communication.java
chess/src/main/java/com/oracle/chess/client/htmljava/GamesModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/LoadMain.java
chess/src/main/java/com/oracle/chess/client/htmljava/Main.java
chess/src/main/java/com/oracle/chess/client/htmljava/MsgType.java
chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java
chess/src/main/java/com/oracle/chess/client/htmljava/SettingsModel.java
chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java
chess/src/main/webapp/pages/DukeHTML.png
chess/src/main/webapp/pages/css/bootstrap.css
chess/src/main/webapp/pages/css/chess-phone-large.css
chess/src/main/webapp/pages/css/chess-phone-small.css
chess/src/main/webapp/pages/css/chess-tablet-large.css
chess/src/main/webapp/pages/css/chess-tablet-small.css
chess/src/main/webapp/pages/css/chess.css
chess/src/main/webapp/pages/css/spinner.css
chess/src/main/webapp/pages/index.html
chess/src/main/webapp/pages/sounds/check.mp3
chess/src/main/webapp/pages/sounds/checkmate.mp3
chess/src/main/webapp/pages/sounds/move.mp3
chess/src/test/java/com/oracle/chess/client/htmljava/BoardModelTest.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/chess/nbactions-bck2brwsr.xml	Tue Sep 24 22:20:24 2013 +0200
     1.3 @@ -0,0 +1,39 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<!--
     1.6 +
     1.7 +    The MIT License (MIT)
     1.8 +
     1.9 +    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    1.10 +
    1.11 +    Permission is hereby granted, free of charge, to any person obtaining a copy
    1.12 +    of this software and associated documentation files (the "Software"), to deal
    1.13 +    in the Software without restriction, including without limitation the rights
    1.14 +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    1.15 +    copies of the Software, and to permit persons to whom the Software is
    1.16 +    furnished to do so, subject to the following conditions:
    1.17 +
    1.18 +    The above copyright notice and this permission notice shall be included in
    1.19 +    all copies or substantial portions of the Software.
    1.20 +
    1.21 +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    1.22 +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    1.23 +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    1.24 +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    1.25 +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    1.26 +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    1.27 +    THE SOFTWARE.
    1.28 +
    1.29 +-->
    1.30 +<actions>
    1.31 +    <action>
    1.32 +        <actionName>run</actionName>
    1.33 +        <goals>
    1.34 +            <goal>package</goal>
    1.35 +            <goal>bck2brwsr:brwsr</goal>
    1.36 +        </goals>
    1.37 +        <properties>
    1.38 +            <skipTests>true</skipTests>
    1.39 +            <bck2brwsr.obfuscationlevel>NONE</bck2brwsr.obfuscationlevel>
    1.40 +        </properties>
    1.41 +    </action>
    1.42 +</actions>
     2.1 --- a/chess/nbactions-iOSDeploy.xml	Tue Sep 24 21:08:15 2013 +0200
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,51 +0,0 @@
     2.4 -<?xml version="1.0" encoding="UTF-8"?>
     2.5 -<!--
     2.6 -
     2.7 -    The MIT License (MIT)
     2.8 -
     2.9 -    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    2.10 -
    2.11 -    Permission is hereby granted, free of charge, to any person obtaining a copy
    2.12 -    of this software and associated documentation files (the "Software"), to deal
    2.13 -    in the Software without restriction, including without limitation the rights
    2.14 -    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    2.15 -    copies of the Software, and to permit persons to whom the Software is
    2.16 -    furnished to do so, subject to the following conditions:
    2.17 -
    2.18 -    The above copyright notice and this permission notice shall be included in
    2.19 -    all copies or substantial portions of the Software.
    2.20 -
    2.21 -    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    2.22 -    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    2.23 -    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    2.24 -    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    2.25 -    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    2.26 -    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    2.27 -    THE SOFTWARE.
    2.28 -
    2.29 --->
    2.30 -<actions>
    2.31 -    <action>
    2.32 -        <actionName>run</actionName>
    2.33 -        <goals>
    2.34 -            <goal>package</goal>
    2.35 -            <goal>ios-maven-plugin:0.2:deploy</goal>
    2.36 -        </goals>
    2.37 -        <properties>
    2.38 -            <skipTests>true</skipTests>
    2.39 -        </properties>
    2.40 -    </action>
    2.41 -    <action>
    2.42 -        <actionName>debug</actionName>
    2.43 -        <goals>
    2.44 -            <goal>package</goal>
    2.45 -            <goal>org.netbeans.ios:ios-maven-plugin:0.2:deploy</goal>
    2.46 -        </goals>
    2.47 -        <properties>
    2.48 -            <skipTests>true</skipTests>
    2.49 -            <jpda.listen>true</jpda.listen>
    2.50 -            <jpdaAddress>${jpda.address}</jpdaAddress>
    2.51 -            <runMode>Debug</runMode>
    2.52 -        </properties>
    2.53 -    </action>
    2.54 -</actions>
    2.55 \ No newline at end of file
     3.1 --- a/chess/nbactions.xml	Tue Sep 24 21:08:15 2013 +0200
     3.2 +++ b/chess/nbactions.xml	Tue Sep 24 22:20:24 2013 +0200
     3.3 @@ -47,7 +47,7 @@
     3.4          <displayName>Build IPA</displayName>
     3.5          <goals>
     3.6              <goal>package</goal>
     3.7 -            <goal>org.netbeans.ios:ios-maven-plugin:0.2-SNAPSHOT:build-IPA</goal>
     3.8 +            <goal>ios:build-IPA</goal>
     3.9          </goals>
    3.10          <properties>
    3.11              <skipTests>true</skipTests>
    3.12 @@ -60,8 +60,8 @@
    3.13          <displayName>Debug IPA</displayName>
    3.14          <goals>
    3.15              <goal>package</goal>
    3.16 -            <goal>org.netbeans.ios:ios-maven-plugin:0.2-SNAPSHOT:ipaddress</goal>
    3.17 -            <goal>org.netbeans.ios:ios-maven-plugin:0.2-SNAPSHOT:build-IPA</goal>
    3.18 +            <goal>ios:ipaddress</goal>
    3.19 +            <goal>ios:build-IPA</goal>
    3.20          </goals>
    3.21          <properties>
    3.22              <skipTests>true</skipTests>            
     4.1 --- a/chess/pom.xml	Tue Sep 24 21:08:15 2013 +0200
     4.2 +++ b/chess/pom.xml	Tue Sep 24 22:20:24 2013 +0200
     4.3 @@ -1,28 +1,21 @@
     4.4  <?xml version="1.0" encoding="UTF-8"?>
     4.5  <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     4.6    <modelVersion>4.0.0</modelVersion>
     4.7 -  <parent>
     4.8 +    <parent>
     4.9      <artifactId>demo</artifactId>
    4.10      <groupId>org.apidesign.html</groupId>
    4.11 -    <version>1.0-SNAPSHOT</version>
    4.12 -  </parent>
    4.13 +        <version>1.0-SNAPSHOT</version>
    4.14 +    </parent>
    4.15  
    4.16 -  <groupId>org.apidesign.html.demo</groupId>
    4.17 -  <artifactId>chess</artifactId>
    4.18 +  <groupId>com.oracle.chess</groupId>
    4.19 +  <artifactId>ChessHTMLJavaClient</artifactId>
    4.20    <version>1.0-SNAPSHOT</version>
    4.21    <packaging>jar</packaging>
    4.22  
    4.23 -  <name>ChessGame</name>
    4.24 +  <name>Chess_HTML_Java_Client</name>
    4.25  
    4.26    <repositories>
    4.27        <repository>
    4.28 -          <id>java.net</id>
    4.29 -          <name>Java.net</name>
    4.30 -          <url>https://maven.java.net/content/repositories/releases/</url>
    4.31 -          <snapshots>
    4.32 -          </snapshots>
    4.33 -      </repository>
    4.34 -      <repository>
    4.35            <id>netbeans</id>
    4.36            <name>NetBeans</name>
    4.37            <url>http://bits.netbeans.org/maven2/</url>
    4.38 @@ -30,13 +23,6 @@
    4.39    </repositories>
    4.40    <pluginRepositories>
    4.41        <pluginRepository>
    4.42 -          <id>java.net</id>
    4.43 -          <name>Java.net</name>
    4.44 -          <url>https://maven.java.net/content/repositories/releases/</url>
    4.45 -          <snapshots>
    4.46 -          </snapshots>
    4.47 -      </pluginRepository>
    4.48 -      <pluginRepository>
    4.49            <id>ios</id>
    4.50            <name>NetBeans iOS Maven Plugin</name>
    4.51            <url>http://beetle.cz.oracle.com/~jtulach/maven/</url>
    4.52 @@ -47,8 +33,12 @@
    4.53  
    4.54    <properties>
    4.55      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    4.56 -    <net.java.html.version>0.4</net.java.html.version>
    4.57      <netbeans.compile.on.save>none</netbeans.compile.on.save>
    4.58 +    <net.java.html.version>0.6</net.java.html.version>
    4.59 +    <bck2brwsr.version>0.8</bck2brwsr.version>
    4.60 +    <bck2brwsr.launcher.version>0.8</bck2brwsr.launcher.version>
    4.61 +    <bck2brwsr.obfuscationlevel>MINIMAL</bck2brwsr.obfuscationlevel>
    4.62 +    <brwsr.startpage>pages/index.html</brwsr.startpage>
    4.63    </properties>
    4.64    <build>
    4.65        <plugins>
    4.66 @@ -68,7 +58,7 @@
    4.67                <configuration>
    4.68                    <archive>
    4.69                        <manifest>
    4.70 -                          <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
    4.71 +                          <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
    4.72                            <addClasspath>true</addClasspath>
    4.73                            <classpathPrefix>lib/</classpathPrefix>
    4.74                        </manifest>
    4.75 @@ -86,7 +76,7 @@
    4.76                            <value>${basedir}/src/main/webapp/</value>
    4.77                        </systemProperty>
    4.78                    </systemProperties>
    4.79 -                  <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
    4.80 +                  <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
    4.81                </configuration>
    4.82            </plugin>      
    4.83            <plugin>
    4.84 @@ -106,7 +96,21 @@
    4.85                        </configuration>
    4.86                    </execution>
    4.87                </executions>                
    4.88 -          </plugin>      
    4.89 +          </plugin>
    4.90 +         <plugin>
    4.91 +            <artifactId>ios-maven-plugin</artifactId>
    4.92 +            <groupId>org.netbeans.ios</groupId>
    4.93 +            <version>0.4</version>
    4.94 +            <configuration>
    4.95 +               <targetDevices>1</targetDevices>
    4.96 +               <deploymentTarget>6.1</deploymentTarget>
    4.97 +               <bundleId>JavaOneChess</bundleId>
    4.98 +               <provisioningProfile></provisioningProfile>
    4.99 +               <supportedInterfaceOrientations>UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationPortrait,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortraitUpsideDown</supportedInterfaceOrientations>
   4.100 +               <prerenderedIcons>false</prerenderedIcons>
   4.101 +               <iPadSupportedInterfaceOrientations>UIInterfaceOrientationLandscapeLeft,UIInterfaceOrientationPortrait,UIInterfaceOrientationLandscapeRight,UIInterfaceOrientationPortraitUpsideDown</iPadSupportedInterfaceOrientations>
   4.102 +            </configuration>
   4.103 +         </plugin>
   4.104        </plugins>
   4.105    </build>
   4.106    <dependencies>
   4.107 @@ -121,66 +125,132 @@
   4.108          <version>${net.java.html.version}</version>
   4.109      </dependency>
   4.110      <dependency>
   4.111 -        <groupId>org.apidesign.html</groupId>
   4.112 -        <artifactId>ko-fx</artifactId>
   4.113 -        <version>${net.java.html.version}</version>
   4.114 -        <scope>runtime</scope>
   4.115 -    </dependency>
   4.116 -    <dependency>
   4.117 -        <groupId>org.apidesign.html</groupId>
   4.118 -        <artifactId>boot-fx</artifactId>
   4.119 -        <version>${net.java.html.version}</version>
   4.120 -        <scope>runtime</scope>
   4.121 -    </dependency>
   4.122 -    <dependency>
   4.123        <groupId>org.testng</groupId>
   4.124        <artifactId>testng</artifactId>
   4.125        <version>6.7</version>
   4.126        <scope>test</scope>
   4.127      </dependency>
   4.128 +    <dependency>
   4.129 +      <groupId>org.apidesign.html</groupId>
   4.130 +      <artifactId>net.java.html.sound</artifactId>
   4.131 +      <version>${net.java.html.version}</version>
   4.132 +      <type>jar</type>
   4.133 +    </dependency>
   4.134 +    <dependency>
   4.135 +      <groupId>org.apidesign.bck2brwsr</groupId>
   4.136 +      <artifactId>core</artifactId>
   4.137 +      <version>${bck2brwsr.version}</version>
   4.138 +      <scope>provided</scope>
   4.139 +      <type>jar</type>
   4.140 +    </dependency>
   4.141    </dependencies>
   4.142    <profiles>
   4.143        <profile>
   4.144 -          <id>iOSDeploy</id>
   4.145 +          <id>fxbrwsr</id>
   4.146            <activation>
   4.147 -              <os>
   4.148 -                  <name>Mac OS X</name>
   4.149 -              </os>
   4.150 +              <activeByDefault>true</activeByDefault>
   4.151            </activation>
   4.152 -          <build>
   4.153 -              <plugins>
   4.154 -                  <plugin>
   4.155 -                      <groupId>org.netbeans.ios</groupId>
   4.156 -                      <artifactId>ios-maven-plugin</artifactId>
   4.157 -                      <version>0.2</version>
   4.158 -                      <configuration>
   4.159 -                          <jarfile>${project.build.directory}/${project.build.finalName}.jar</jarfile>
   4.160 -                          <title>${project.name}</title>
   4.161 -                          <mainclass>org.apidesign.html.demo.chess.Main</mainclass>
   4.162 -                          <resourcesDir>src/main/webapp/</resourcesDir>
   4.163 -                      </configuration>
   4.164 -                  </plugin>
   4.165 -                  <plugin>
   4.166 -                      <groupId>org.apache.maven.plugins</groupId>
   4.167 -                      <artifactId>maven-jar-plugin</artifactId>
   4.168 -                      <version>2.4</version>
   4.169 -                      <configuration>
   4.170 -                          <archive>
   4.171 -                              <manifest>
   4.172 -                                  <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
   4.173 -                                  <addClasspath>true</addClasspath>
   4.174 -                                  <classpathPrefix>lib/</classpathPrefix>
   4.175 -                              </manifest>
   4.176 -                          </archive>
   4.177 -                      </configuration>
   4.178 -                  </plugin>
   4.179 -              </plugins>
   4.180 -          </build>
   4.181            <dependencies>
   4.182                <dependency>
   4.183                    <groupId>org.apidesign.html</groupId>
   4.184                    <artifactId>ko-fx</artifactId>
   4.185                    <version>${net.java.html.version}</version>
   4.186 +                  <scope>runtime</scope>
   4.187 +              </dependency>
   4.188 +              <dependency>
   4.189 +                  <groupId>org.apidesign.html</groupId>
   4.190 +                  <artifactId>boot-fx</artifactId>
   4.191 +                  <version>${net.java.html.version}</version>
   4.192 +                  <scope>runtime</scope>
   4.193 +              </dependency>
   4.194 +              <dependency>
   4.195 +                  <groupId>org.apidesign.html</groupId>
   4.196 +                  <artifactId>ko-ws-tyrus</artifactId>
   4.197 +                  <scope>runtime</scope>
   4.198 +                  <version>${net.java.html.version}</version>
   4.199 +              </dependency>
   4.200 +          </dependencies>
   4.201 +      </profile>
   4.202 +      <profile>
   4.203 +          <id>bck2brwsr</id>
   4.204 +          <activation>
   4.205 +              <property>
   4.206 +                  <name>brwsr</name>
   4.207 +                  <value>bck2brwsr</value>
   4.208 +              </property>
   4.209 +          </activation>
   4.210 +          <build>
   4.211 +              <plugins>
   4.212 +                  <plugin>
   4.213 +                      <groupId>org.apidesign.bck2brwsr</groupId>
   4.214 +                      <artifactId>bck2brwsr-maven-plugin</artifactId>
   4.215 +                      <version>${bck2brwsr.launcher.version}</version>
   4.216 +                      <executions>
   4.217 +                          <execution>
   4.218 +                              <goals>
   4.219 +                                  <goal>brwsr</goal>
   4.220 +                              </goals>
   4.221 +                          </execution>
   4.222 +                      </executions>
   4.223 +                      <configuration>
   4.224 +                          <directory>${basedir}/src/main/webapp/</directory>
   4.225 +                          <startpage>${brwsr.startpage}</startpage>
   4.226 +                          <launcher>${brwsr}</launcher>
   4.227 +                          <javascript>${project.build.directory}/bck2brwsr.js</javascript>
   4.228 +                          <obfuscation>${bck2brwsr.obfuscationlevel}</obfuscation>
   4.229 +                      </configuration>
   4.230 +                  </plugin>
   4.231 +                  <plugin>
   4.232 +                      <groupId>org.apache.maven.plugins</groupId>
   4.233 +                      <artifactId>maven-compiler-plugin</artifactId>
   4.234 +                      <configuration>
   4.235 +                          <compilerArguments>
   4.236 +                              <!--
   4.237 +                              <bootclasspath>netbeans.ignore.jdk.bootclasspath</bootclasspath>
   4.238 +                              -->
   4.239 +                          </compilerArguments>
   4.240 +                      </configuration>
   4.241 +                  </plugin>
   4.242 +                  <plugin>
   4.243 +                      <artifactId>maven-assembly-plugin</artifactId>
   4.244 +                      <version>2.4</version>
   4.245 +                      <executions>
   4.246 +                          <execution>
   4.247 +                              <id>distro-assembly</id>
   4.248 +                              <phase>package</phase>
   4.249 +                              <goals>
   4.250 +                                  <goal>single</goal>
   4.251 +                              </goals>
   4.252 +                              <configuration>
   4.253 +                                  <descriptors>
   4.254 +                                      <descriptor>src/main/assembly/bck2brwsr.xml</descriptor>
   4.255 +                                  </descriptors>
   4.256 +                              </configuration>
   4.257 +                          </execution>
   4.258 +                      </executions>                
   4.259 +                  </plugin>      
   4.260 +              </plugins>
   4.261 +          </build>
   4.262 +          <dependencies>
   4.263 +              <dependency>
   4.264 +                  <groupId>org.apidesign.bck2brwsr</groupId>
   4.265 +                  <artifactId>emul</artifactId>
   4.266 +                  <version>${bck2brwsr.version}</version>
   4.267 +                  <classifier>rt</classifier>
   4.268 +              </dependency>
   4.269 +              <dependency>
   4.270 +                  <groupId>org.apidesign.bck2brwsr</groupId>
   4.271 +                  <artifactId>ko-bck2brwsr</artifactId>
   4.272 +                  <version>${bck2brwsr.version}</version>
   4.273 +                  <scope>runtime</scope>
   4.274 +              </dependency>
   4.275 +              <dependency>
   4.276 +                  <groupId>org.apidesign.bck2brwsr</groupId>
   4.277 +                  <artifactId>vm4brwsr</artifactId>
   4.278 +                  <classifier>js</classifier>
   4.279 +                  <type>zip</type>
   4.280 +                  <version>${bck2brwsr.version}</version>
   4.281 +                  <scope>provided</scope>
   4.282                </dependency>
   4.283            </dependencies>
   4.284        </profile>
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/chess/src/main/assembly/bck2brwsr.xml	Tue Sep 24 22:20:24 2013 +0200
     5.3 @@ -0,0 +1,79 @@
     5.4 +<?xml version="1.0"?>
     5.5 +<!--
     5.6 +
     5.7 +    The MIT License (MIT)
     5.8 +
     5.9 +    Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    5.10 +
    5.11 +    Permission is hereby granted, free of charge, to any person obtaining a copy
    5.12 +    of this software and associated documentation files (the "Software"), to deal
    5.13 +    in the Software without restriction, including without limitation the rights
    5.14 +    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    5.15 +    copies of the Software, and to permit persons to whom the Software is
    5.16 +    furnished to do so, subject to the following conditions:
    5.17 +
    5.18 +    The above copyright notice and this permission notice shall be included in
    5.19 +    all copies or substantial portions of the Software.
    5.20 +
    5.21 +    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    5.22 +    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    5.23 +    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    5.24 +    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    5.25 +    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    5.26 +    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    5.27 +    THE SOFTWARE.
    5.28 +
    5.29 +-->
    5.30 +<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    5.31 +  xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
    5.32 +  
    5.33 +  <id>bck2brwsr</id>
    5.34 +  <formats>
    5.35 +      <format>zip</format>
    5.36 +  </formats>
    5.37 +  <baseDirectory>public_html</baseDirectory>
    5.38 +  <dependencySets>
    5.39 +    <dependencySet>
    5.40 +        <useProjectArtifact>false</useProjectArtifact>
    5.41 +        <scope>runtime</scope>
    5.42 +        <outputDirectory>lib</outputDirectory>
    5.43 +        <includes>
    5.44 +            <include>*:jar</include>
    5.45 +            <include>*:rt</include>
    5.46 +        </includes>
    5.47 +    </dependencySet>
    5.48 +    <dependencySet>
    5.49 +        <useProjectArtifact>false</useProjectArtifact>
    5.50 +        <scope>provided</scope>
    5.51 +        <includes>
    5.52 +            <include>*:js</include>
    5.53 +        </includes>
    5.54 +        <unpack>true</unpack>
    5.55 +        <outputDirectory>/</outputDirectory>
    5.56 +    </dependencySet>
    5.57 +  </dependencySets> 
    5.58 +  <fileSets>
    5.59 +      <fileSet>
    5.60 +          <directory>src/main/webapp/pages</directory>
    5.61 +          <outputDirectory>/</outputDirectory>
    5.62 +          <excludes>
    5.63 +              <exclude>*.png</exclude>
    5.64 +          </excludes>
    5.65 +          <filtered>true</filtered>
    5.66 +      </fileSet>
    5.67 +      <fileSet>
    5.68 +          <directory>src/main/webapp/pages</directory>
    5.69 +          <outputDirectory>/</outputDirectory>
    5.70 +          <includes>
    5.71 +              <include>*.png</include>
    5.72 +          </includes>
    5.73 +          <filtered>false</filtered>
    5.74 +      </fileSet>
    5.75 +  </fileSets>
    5.76 +  <files>
    5.77 +    <file>
    5.78 +      <source>${project.build.directory}/${project.build.finalName}.jar</source>
    5.79 +      <outputDirectory>/</outputDirectory>
    5.80 +    </file>
    5.81 +  </files>
    5.82 +</assembly>
    5.83 \ No newline at end of file
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/BoardModel.java	Tue Sep 24 22:20:24 2013 +0200
     6.3 @@ -0,0 +1,451 @@
     6.4 +/**
     6.5 + * The MIT License (MIT)
     6.6 + *
     6.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     6.8 + *
     6.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    6.10 + * of this software and associated documentation files (the "Software"), to deal
    6.11 + * in the Software without restriction, including without limitation the rights
    6.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    6.13 + * copies of the Software, and to permit persons to whom the Software is
    6.14 + * furnished to do so, subject to the following conditions:
    6.15 + *
    6.16 + * The above copyright notice and this permission notice shall be included in
    6.17 + * all copies or substantial portions of the Software.
    6.18 + *
    6.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    6.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    6.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    6.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    6.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    6.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    6.25 + * THE SOFTWARE.
    6.26 + */
    6.27 +package com.oracle.chess.client.htmljava;
    6.28 +
    6.29 +import com.oracle.chess.client.htmljava.Communication.AlertType;
    6.30 +import java.util.Arrays;
    6.31 +import java.util.Collections;
    6.32 +import java.util.List;
    6.33 +import java.util.Timer;
    6.34 +import java.util.TimerTask;
    6.35 +import net.java.html.json.ComputedProperty;
    6.36 +import net.java.html.json.Function;
    6.37 +import net.java.html.json.Model;
    6.38 +import net.java.html.json.ModelOperation;
    6.39 +import net.java.html.json.OnPropertyChange;
    6.40 +import net.java.html.json.Property;
    6.41 +import net.java.html.sound.AudioClip;
    6.42 +
    6.43 +@Model(className="Board", properties={
    6.44 +    @Property(name = "player", type = String.class),
    6.45 +    @Property(name = "gameId", type = String.class),
    6.46 +    @Property(name = "whitePlayer", type = String.class),
    6.47 +    @Property(name = "blackPlayer", type = String.class),
    6.48 +    @Property(name = "alert", type = Alert.class),
    6.49 +    @Property(name = "alertMessage", type = String.class),
    6.50 +    @Property(name = "status", type = String.class),
    6.51 +    @Property(name = "rows", type = Row.class, array = true),
    6.52 +    @Property(name = "turn", type = Color.class),
    6.53 +    @Property(name = "moves", type = Move.class, array = true),
    6.54 +    @Property(name = "pendingMove", type = Move.class),
    6.55 +    @Property(name = "active", type = boolean.class),
    6.56 +})
    6.57 +public class BoardModel {
    6.58 +    @ComputedProperty static String title(String status, String gameId) {
    6.59 +        String t = status != null ? status : gameId;
    6.60 +        if (t != null && t.length() > 10) {
    6.61 +            return t.substring(0, 10);
    6.62 +        }
    6.63 +        return t;
    6.64 +    }
    6.65 +
    6.66 +    @ModelOperation static void updateSummary(Board b, String summary) {
    6.67 +        if (summary != null) {
    6.68 +            b.setStatus(summary);
    6.69 +        }
    6.70 +    }
    6.71 +    
    6.72 +    @ComputedProperty static boolean myTurn(String player, String whitePlayer, String blackPlayer, Color turn) {
    6.73 +        if (turn != null && player != null) switch (turn) {
    6.74 +            case B: return player.equals(blackPlayer);
    6.75 +            case W: return player.equals(whitePlayer);
    6.76 +        }
    6.77 +        return false;
    6.78 +    }
    6.79 +    
    6.80 +    @ComputedProperty static boolean justObserving(String player) {
    6.81 +        return player == null;
    6.82 +    }
    6.83 +    
    6.84 +    private static final AudioClip MOVE = AudioClip.create("sounds/move.mp3");
    6.85 +    @OnPropertyChange("moves") static void playMove() {
    6.86 +        MOVE.play();
    6.87 +    }
    6.88 +
    6.89 +    private static final AudioClip CHECK = AudioClip.create("sounds/check.mp3");
    6.90 +    private static final AudioClip CHECKMATE = AudioClip.create("sounds/checkmate.mp3");
    6.91 +    @OnPropertyChange("alert") static void warnCheckAndMate(Board b) {
    6.92 +        if (b.getAlert() == null) {
    6.93 +            return;
    6.94 +        }
    6.95 +        if (b.getAlert().getType() == AlertType.CHECK) {
    6.96 +            CHECK.play();
    6.97 +        }
    6.98 +        if (b.getAlert().getType() == AlertType.CHECKMATE) {
    6.99 +            CHECKMATE.play();
   6.100 +        }
   6.101 +    }
   6.102 +    
   6.103 +    @Function static void selected(Board b, Square data) {
   6.104 +        if (!b.isMyTurn()) {
   6.105 +            b.setAlertMessage("Not your turn!");
   6.106 +            return;
   6.107 +        }
   6.108 +        
   6.109 +        Square previoslySelected = findSelectedSquare(b);
   6.110 +        if (previoslySelected == null) {
   6.111 +            if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
   6.112 +                data.setSelected(true);
   6.113 +                Rules.computeAccessible(b, data);
   6.114 +            }
   6.115 +        } else {
   6.116 +            if (previoslySelected == data) {
   6.117 +                data.setSelected(false);
   6.118 +                Rules.computeAccessible(b, null);
   6.119 +                return;
   6.120 +            }
   6.121 +            if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
   6.122 +                previoslySelected.setSelected(false);
   6.123 +                data.setSelected(true);
   6.124 +                Rules.computeAccessible(b, data);
   6.125 +                return;
   6.126 +            }
   6.127 +            if (data.isAccessible()) {
   6.128 +                previoslySelected.setSelected(false);
   6.129 +
   6.130 +                Move newMove = new Move();
   6.131 +                newMove.setFrom(previoslySelected.getPosition());
   6.132 +                newMove.setTo(data.getPosition());
   6.133 +                newMove.setRound(b.getMoves().size() / 2 + 1);
   6.134 +                newMove.setPiece(previoslySelected.getPiece());
   6.135 +                newMove.setTurn(previoslySelected.getPieceColor());
   6.136 +                newMove.setTakes(data.getPiece() != null);
   6.137 +                b.getMoves().add(newMove);
   6.138 +                b.setPendingMove(newMove);
   6.139 +
   6.140 +                data.setPending(true);
   6.141 +                data.setPieceColor(previoslySelected.getPieceColor());
   6.142 +                data.setPiece(previoslySelected.getPiece());
   6.143 +                b.setTurn(null);
   6.144 +                previoslySelected.setPiece(null);
   6.145 +                previoslySelected.setPieceColor(null);
   6.146 +                Rules.computeAccessible(b, null);
   6.147 +
   6.148 +                Request sm = new Request();
   6.149 +                sm.setMsg(MsgType.SendMove);
   6.150 +                sm.setGameId(b.getGameId());
   6.151 +                sm.setFrom(newMove.getFrom().getLocation());
   6.152 +                sm.setTo(newMove.getTo().getLocation());
   6.153 +                sm.setColor(newMove.getTurn());
   6.154 +                final UI ui = UIModel.findUI(b);
   6.155 +                if (ui != null) {
   6.156 +                    ui.sendMsg(sm);
   6.157 +                }
   6.158 +            }
   6.159 +        }
   6.160 +    }
   6.161 +    
   6.162 +    static class NextMove extends TimerTask {
   6.163 +        private static final Timer T = new Timer("Animate moves");
   6.164 +        private final Board b;
   6.165 +        private final Move m;
   6.166 +
   6.167 +        public NextMove(Board b, Move m) {
   6.168 +            this.b = b;
   6.169 +            this.m = m;
   6.170 +            T.schedule(this, 1000);
   6.171 +        }
   6.172 +        
   6.173 +        
   6.174 +        @Override
   6.175 +        public void run() {
   6.176 +            b.showPosition(m);
   6.177 +        }
   6.178 +    }
   6.179 +    
   6.180 +    @ModelOperation @Function static void showPosition(Board b, Move data) {
   6.181 +        Rules.initBoard(b);
   6.182 +        boolean found = false;
   6.183 +        for (Move m : b.getMoves()) {
   6.184 +            if (found) {
   6.185 +                b.setTurn(null);
   6.186 +                new NextMove(b, m);
   6.187 +                return;
   6.188 +            }
   6.189 +            Square from = findSquare(b, (char)m.getFrom().getX(), m.getFrom().getY());
   6.190 +            Square to = findSquare(b, (char)m.getTo().getX(), m.getTo().getY());
   6.191 +            to.setPiece(from.getPiece());
   6.192 +            to.setPieceColor(from.getPieceColor());
   6.193 +            from.setPiece(null);
   6.194 +            from.setPieceColor(null);
   6.195 +            if (m == data) {
   6.196 +                found = true;
   6.197 +            }
   6.198 +        }
   6.199 +        b.setTurn(b.getMoves().size() % 2 == 0 ? Color.W : Color.B);
   6.200 +    }
   6.201 +    
   6.202 +    
   6.203 +
   6.204 +    @Function static void rotateBoard(Board b) {
   6.205 +        Collections.reverse(b.getRows());
   6.206 +        for (Row r : b.getRows()) {
   6.207 +            Collections.reverse(r.getColumns());
   6.208 +        }
   6.209 +        Square sq = findSelectedSquare(b);
   6.210 +        if (sq != null) {
   6.211 +            sq.setSelected(false);
   6.212 +            Rules.computeAccessible(b, null);
   6.213 +        }
   6.214 +    }
   6.215 +    
   6.216 +    @ComputedProperty static boolean whiteTurn(Color turn) {
   6.217 +        return turn == Color.W;
   6.218 +    }
   6.219 +
   6.220 +    @ComputedProperty static boolean blackTurn(Color turn) {
   6.221 +        return turn == Color.B;
   6.222 +    }
   6.223 +    
   6.224 +    @ComputedProperty static List<String> columnNames(List<Row> rows) {
   6.225 +        boolean whiteDown = rows.isEmpty() || rows.get(0).getY() == 8;
   6.226 +        String[] arr = new String[8];
   6.227 +        for (int i = 0; i < 8; i++) {
   6.228 +            String s;
   6.229 +            if (whiteDown) {
   6.230 +                s = "" + (char)('A' + i);
   6.231 +            } else {
   6.232 +                s = "" + (char)('H' - i);
   6.233 +            }
   6.234 +            arr[i] = s;
   6.235 +        }
   6.236 +        return Arrays.asList(arr);
   6.237 +    }
   6.238 +    
   6.239 +    static Square findSquare(Board b, char column, int row) {
   6.240 +        for (Row r : b.getRows()) {
   6.241 +            for (Square square : r.getColumns()) {
   6.242 +                if (square.getPosition().getX() == column && square.getPosition().getY() == row) {
   6.243 +                    return square;
   6.244 +                }
   6.245 +            }
   6.246 +        }
   6.247 +        return null;
   6.248 +    }
   6.249 +
   6.250 +    private static Square findSquare(Board b, Position to) {
   6.251 +        return findSquare(b, (char)to.getX(), to.getY());
   6.252 +    }
   6.253 +    
   6.254 +    static Square findSelectedSquare(Board b) {
   6.255 +        for (Row row : b.getRows()) {
   6.256 +            for (Square square : row.getColumns()) {
   6.257 +                if (square.isSelected()) {
   6.258 +                    return square;
   6.259 +                }
   6.260 +            }
   6.261 +        }
   6.262 +        return null;
   6.263 +    }
   6.264 +
   6.265 +    static void moveResponse(final Board b, final String errMsg, final List<String> whites, final List<String> blacks, final Color turn,
   6.266 +        Alert alert
   6.267 +    ) {
   6.268 +        if (errMsg != null) {
   6.269 +            b.getMoves().remove(b.getPendingMove());
   6.270 +            b.setPendingMove(null);
   6.271 +            b.setAlertMessage(errMsg);
   6.272 +        } else {
   6.273 +            b.setTurn(turn);
   6.274 +            b.setAlertMessage(null);
   6.275 +        }
   6.276 +        b.setAlert(alert);
   6.277 +        Rules.initBoard(b, whites, blacks, turn);
   6.278 +    }
   6.279 +
   6.280 +    static void moveUpdate(final Board b, final Move move, final List<String> whites, final List<String> blacks, final Color turn, Alert alert) {
   6.281 +        final Square from = BoardModel.findSquare(b, move.getFrom());
   6.282 +        final Square to = BoardModel.findSquare(b, move.getTo());
   6.283 +        move.setPiece(from.getPiece());
   6.284 +        move.setTurn(from.getPieceColor());
   6.285 +        if (to.getPiece() != null) {
   6.286 +            move.setTakes(true);
   6.287 +        }
   6.288 +        b.setAlert(alert);
   6.289 +        b.setAlertMessage(alert == null ? null : alert.getMessage());
   6.290 +        move.setRound(b.getMoves().size() / 2 + 1);
   6.291 +        b.getMoves().add(move);
   6.292 +        Rules.initBoard(b, whites, blacks, turn);
   6.293 +    }
   6.294 +
   6.295 +    @Model(className="Row", properties = {
   6.296 +        @Property(name = "columns", type = Square.class, array = true)
   6.297 +    })
   6.298 +    static class RowsImpl {
   6.299 +        @ComputedProperty static int y(List<Square> columns) {
   6.300 +            return columns.isEmpty() ? 0 : columns.get(0).getY();
   6.301 +        }
   6.302 +    }
   6.303 +    
   6.304 +    enum PieceType {
   6.305 +        PAWN(5), ROCK(2), KNIGHT(4), BISHOP(3), QUEEN(1), KING(0);
   6.306 +
   6.307 +        final int entityIndex;
   6.308 +        
   6.309 +        PieceType(int ei) {
   6.310 +            this.entityIndex = ei;
   6.311 +        }
   6.312 +
   6.313 +        static PieceType fromNotation(char notation) {
   6.314 +            switch (notation) {
   6.315 +                case 'R': return ROCK;
   6.316 +                case 'N': return KNIGHT;
   6.317 +                case 'B': return BISHOP;
   6.318 +                case 'Q': return QUEEN;
   6.319 +                case 'K': return KING;
   6.320 +                case 'P': return PAWN;
   6.321 +            }
   6.322 +            throw new IllegalStateException("Unexpected: " + notation);
   6.323 +        }
   6.324 +        
   6.325 +        String computeEntity(Color color) {
   6.326 +            if (color == null) {
   6.327 +                color = Color.W;
   6.328 +            }
   6.329 +            int base;
   6.330 +            switch (color) {
   6.331 +                case W: base = 12; break;
   6.332 +                case B: base = 18; break;
   6.333 +                default:
   6.334 +                    throw new AssertionError();
   6.335 +            }
   6.336 +            return "&#98" + String.valueOf(base + entityIndex) + ";";
   6.337 +        }
   6.338 +    }
   6.339 +    
   6.340 +    @Model(className="Position", properties = {
   6.341 +        @Property(name = "x", type = char.class),
   6.342 +        @Property(name = "y", type = int.class),
   6.343 +    })
   6.344 +    static class PositionImpl {
   6.345 +        @ComputedProperty static String location(int x, int y) {
   6.346 +            return "" + (char)(x - 'A' + 'a') + y;
   6.347 +        }
   6.348 +    }
   6.349 +    
   6.350 +    @Model(className="Square", properties = {
   6.351 +        @Property(name = "position", type = Position.class),
   6.352 +        @Property(name = "color", type = Color.class),
   6.353 +        @Property(name = "piece", type = PieceType.class),
   6.354 +        @Property(name = "pieceColor", type = Color.class),
   6.355 +        @Property(name = "selected", type = boolean.class),
   6.356 +        @Property(name = "accessible", type = boolean.class),
   6.357 +        @Property(name = "pending", type = boolean.class),
   6.358 +    })
   6.359 +    static class SquareModel {
   6.360 +        @ComputedProperty static String pieceEntity(
   6.361 +            PieceType piece, Color pieceColor
   6.362 +        ) {
   6.363 +            if (piece == null) {
   6.364 +                return "";
   6.365 +            }
   6.366 +            return piece.computeEntity(pieceColor);
   6.367 +        }
   6.368 +        
   6.369 +        @ComputedProperty static String squareColor(
   6.370 +            Color color, boolean selected, boolean accessible, boolean pending
   6.371 +        ) {
   6.372 +            if (selected) {
   6.373 +                return "selected";
   6.374 +            }
   6.375 +            if (accessible) {
   6.376 +                return "accessible";
   6.377 +            }
   6.378 +            if (pending) {
   6.379 +                return "pending";
   6.380 +            }
   6.381 +            
   6.382 +            if (color == null) {
   6.383 +                return "";
   6.384 +            } else {
   6.385 +                if (color == Color.W) {
   6.386 +                    return "white";
   6.387 +                } else {
   6.388 +                    return "black";
   6.389 +                }
   6.390 +            }
   6.391 +        }
   6.392 +        
   6.393 +        @ComputedProperty static char x(Position position) {
   6.394 +            return position == null ? 'A' : position.getX();
   6.395 +        }
   6.396 +
   6.397 +        @ComputedProperty static int y(Position position) {
   6.398 +            return position == null ? 1 : position.getY();
   6.399 +        }
   6.400 +    }
   6.401 +    
   6.402 +    @Model(className = "Move", properties = {
   6.403 +        @Property(name = "round", type = int.class),
   6.404 +        @Property(name = "turn", type = Color.class),
   6.405 +        @Property(name = "piece", type = PieceType.class),
   6.406 +        @Property(name = "from", type = Position.class),
   6.407 +        @Property(name = "to", type = Position.class),
   6.408 +        @Property(name = "promoted", type = PieceType.class),
   6.409 +        @Property(name = "takes", type = boolean.class),
   6.410 +        @Property(name = "check", type = boolean.class),
   6.411 +    })
   6.412 +    static class MoveImpl {
   6.413 +        @ComputedProperty static boolean whiteMove(Color turn) {
   6.414 +            return turn == Color.W;
   6.415 +        }
   6.416 +        
   6.417 +        @ComputedProperty static String html(
   6.418 +            Position from, Position to, boolean takes, PieceType piece, Color turn
   6.419 +        ) {
   6.420 +            if (from == null || to == null) {
   6.421 +                return "";
   6.422 +            }
   6.423 +            StringBuilder sb = new StringBuilder();
   6.424 +            if (piece != null && piece != PieceType.PAWN) {
   6.425 +                sb.append(piece.computeEntity(turn));
   6.426 +            }
   6.427 +            
   6.428 +            sb.append(from.getLocation());
   6.429 +            if (takes) {
   6.430 +                sb.append("x");
   6.431 +            }
   6.432 +            sb.append(to.getLocation());
   6.433 +            return sb.toString();
   6.434 +        }
   6.435 +
   6.436 +        static Move valueOf(String move) {
   6.437 +            move = move.toUpperCase();
   6.438 +            Move m = new Move();
   6.439 +            {
   6.440 +                Position p = new Position();
   6.441 +                p.setX(move.charAt(0));
   6.442 +                p.setY(move.charAt(1) - '0');
   6.443 +                m.setFrom(p);
   6.444 +            }
   6.445 +            {
   6.446 +                Position p = new Position();
   6.447 +                p.setX(move.charAt(2));
   6.448 +                p.setY(move.charAt(3) - '0');
   6.449 +                m.setTo(p);
   6.450 +            }
   6.451 +            return m;
   6.452 +        }
   6.453 +    }
   6.454 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/Color.java	Tue Sep 24 22:20:24 2013 +0200
     7.3 @@ -0,0 +1,32 @@
     7.4 +/**
     7.5 + * The MIT License (MIT)
     7.6 + *
     7.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     7.8 + *
     7.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    7.10 + * of this software and associated documentation files (the "Software"), to deal
    7.11 + * in the Software without restriction, including without limitation the rights
    7.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    7.13 + * copies of the Software, and to permit persons to whom the Software is
    7.14 + * furnished to do so, subject to the following conditions:
    7.15 + *
    7.16 + * The above copyright notice and this permission notice shall be included in
    7.17 + * all copies or substantial portions of the Software.
    7.18 + *
    7.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    7.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    7.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    7.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    7.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    7.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    7.25 + * THE SOFTWARE.
    7.26 + */
    7.27 +package com.oracle.chess.client.htmljava;
    7.28 +
    7.29 +/**
    7.30 + *
    7.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    7.32 + */
    7.33 +public enum Color {
    7.34 +    W, B;
    7.35 +}
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/Communication.java	Tue Sep 24 22:20:24 2013 +0200
     8.3 @@ -0,0 +1,110 @@
     8.4 +/**
     8.5 + * The MIT License (MIT)
     8.6 + *
     8.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     8.8 + *
     8.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    8.10 + * of this software and associated documentation files (the "Software"), to deal
    8.11 + * in the Software without restriction, including without limitation the rights
    8.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    8.13 + * copies of the Software, and to permit persons to whom the Software is
    8.14 + * furnished to do so, subject to the following conditions:
    8.15 + *
    8.16 + * The above copyright notice and this permission notice shall be included in
    8.17 + * all copies or substantial portions of the Software.
    8.18 + *
    8.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    8.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    8.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    8.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    8.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    8.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    8.25 + * THE SOFTWARE.
    8.26 + */
    8.27 +package com.oracle.chess.client.htmljava;
    8.28 +
    8.29 +import net.java.html.json.ComputedProperty;
    8.30 +import net.java.html.json.Model;
    8.31 +import net.java.html.json.Property;
    8.32 +
    8.33 +
    8.34 +/** Communication protocols to talk to the server.
    8.35 + *
    8.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    8.37 + */
    8.38 +final class Communication {
    8.39 +    @Model(className = "Request", properties = {
    8.40 +        @Property(name = "msg", type = MsgType.class),
    8.41 +        @Property(name = "username", type = String.class),
    8.42 +        @Property(name = "password", type = String.class),
    8.43 +        @Property(name = "gameId", type = String.class),
    8.44 +        @Property(name = "color", type = Color.class),
    8.45 +        @Property(name = "from", type = String.class),
    8.46 +        @Property(name = "to", type = String.class),
    8.47 +        @Property(name = "observer", type = boolean.class),
    8.48 +    })
    8.49 +    static class RequestModel {
    8.50 +    }
    8.51 +
    8.52 +    @Model(className = "BoardRep", properties = {
    8.53 +        @Property(name = "whites", type = String.class, array = true),
    8.54 +        @Property(name = "blacks", type = String.class, array = true),
    8.55 +    })
    8.56 +    static class BoardRepModel {
    8.57 +    }
    8.58 +
    8.59 +    @Model(className = "Response", properties = {
    8.60 +        @Property(name = "msg", type = String.class),
    8.61 +        @Property(name = "games", array = true, type = Game.class),
    8.62 +        @Property(name = "board", type = BoardRep.class),
    8.63 +        @Property(name = "turn", type = Color.class),
    8.64 +        @Property(name = "color", type = Color.class),
    8.65 +        @Property(name = "gameId", type = String.class),
    8.66 +        @Property(name = "error", type = Err.class),
    8.67 +        @Property(name = "alert", type = Alert.class),
    8.68 +        @Property(name = "status", type = String.class),
    8.69 +        @Property(name = "summary", type = String.class),
    8.70 +        @Property(name = "moves", type = String.class, array = true),
    8.71 +        @Property(name = "from", type = String.class),
    8.72 +        @Property(name = "to", type = String.class),
    8.73 +        @Property(name = "check", type = CheckResult.class),
    8.74 +        @Property(name = "whitePlayer", type = String.class),
    8.75 +        @Property(name = "blackPlayer", type = String.class),
    8.76 +    })
    8.77 +    static class ResponseModel {
    8.78 +        @ComputedProperty static Color nextTurn(Color turn, Alert alert) {
    8.79 +            if (alert == null || !alert.getType().isTerminal()) {
    8.80 +                return turn;
    8.81 +            } else {
    8.82 +                return null;
    8.83 +            }
    8.84 +        }
    8.85 +    }
    8.86 +
    8.87 +    static enum CheckResult {
    8.88 +        VALID, INVALID, NOT_REGISTERED
    8.89 +    };
    8.90 +    
    8.91 +    @Model(className = "Err", properties = {
    8.92 +        @Property(name = "code", type = int.class),
    8.93 +        @Property(name = "message", type = String.class),
    8.94 +    })
    8.95 +    static class ErrorModel {
    8.96 +    }
    8.97 +
    8.98 +    @Model(className = "Alert", properties = {
    8.99 +        @Property(name = "type", type = AlertType.class),
   8.100 +        @Property(name = "message", type = String.class),
   8.101 +    })
   8.102 +    static class AlertModel {
   8.103 +    }
   8.104 +
   8.105 +    static enum AlertType {
   8.106 +        CHECKMATE, CHECK, DRAW;
   8.107 +
   8.108 +        public boolean isTerminal() {
   8.109 +            return this == CHECKMATE || this == DRAW;
   8.110 +        }
   8.111 +    };
   8.112 +    
   8.113 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/GamesModel.java	Tue Sep 24 22:20:24 2013 +0200
     9.3 @@ -0,0 +1,86 @@
     9.4 +/**
     9.5 + * The MIT License (MIT)
     9.6 + *
     9.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
     9.8 + *
     9.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
    9.10 + * of this software and associated documentation files (the "Software"), to deal
    9.11 + * in the Software without restriction, including without limitation the rights
    9.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
    9.13 + * copies of the Software, and to permit persons to whom the Software is
    9.14 + * furnished to do so, subject to the following conditions:
    9.15 + *
    9.16 + * The above copyright notice and this permission notice shall be included in
    9.17 + * all copies or substantial portions of the Software.
    9.18 + *
    9.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    9.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    9.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    9.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    9.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    9.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    9.25 + * THE SOFTWARE.
    9.26 + */
    9.27 +package com.oracle.chess.client.htmljava;
    9.28 +
    9.29 +import java.util.List;
    9.30 +import net.java.html.json.ComputedProperty;
    9.31 +import net.java.html.json.Model;
    9.32 +import net.java.html.json.ModelOperation;
    9.33 +import net.java.html.json.Property;
    9.34 +
    9.35 +/**
    9.36 + *
    9.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
    9.38 + */
    9.39 +@Model(className = "Games", properties = {
    9.40 +    @Property(name = "own", array = true, type = Game.class),
    9.41 +    @Property(name = "other", array = true, type = Game.class),
    9.42 +    @Property(name = "selectedColor", type = String.class),
    9.43 +})
    9.44 +class GamesModel {
    9.45 +    @Model(className = "Game", properties = {
    9.46 +        @Property(name = "gameId", type=String.class),
    9.47 +        @Property(name = "summary", type=String.class),
    9.48 +        @Property(name = "open", type=boolean.class),
    9.49 +        @Property(name = "whitePlayer", type=String.class),
    9.50 +        @Property(name = "blackPlayer", type=String.class)
    9.51 +    })
    9.52 +    static class GameImpl {
    9.53 +        @ComputedProperty static String description(String gameId, String summary) {
    9.54 +            return summary != null ? summary : gameId;
    9.55 +        }
    9.56 +        
    9.57 +        @ComputedProperty static boolean pendingPlayer(String whitePlayer, String blackPlayer) {
    9.58 +            return whitePlayer == null || blackPlayer == null;
    9.59 +        }
    9.60 +    }
    9.61 +    
    9.62 +    
    9.63 +    @ComputedProperty static boolean anyOwnGame(List<Game> own) {
    9.64 +        return !own.isEmpty();
    9.65 +    }
    9.66 +
    9.67 +    @ComputedProperty static boolean anyOtherGame(List<Game> other) {
    9.68 +        return !other.isEmpty();
    9.69 +    }
    9.70 +    
    9.71 +    @ModelOperation static void listGames(Games g, List<Game> games, String username) {
    9.72 +        g.getOwn().clear();
    9.73 +        g.getOther().clear();
    9.74 +        int cnt = 0;
    9.75 +        final int maxGames = 30;
    9.76 +        for (Game game : games) {
    9.77 +            if (
    9.78 +                username.equals(game.getWhitePlayer()) || 
    9.79 +                username.equals(game.getBlackPlayer())
    9.80 +            ) {
    9.81 +                g.getOwn().add(game);
    9.82 +            } else {
    9.83 +                if (cnt++ < maxGames) {
    9.84 +                    g.getOther().add(game);
    9.85 +                }
    9.86 +            }
    9.87 +        }
    9.88 +    }
    9.89 +}
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/LoadMain.java	Tue Sep 24 22:20:24 2013 +0200
    10.3 @@ -0,0 +1,41 @@
    10.4 +/**
    10.5 + * The MIT License (MIT)
    10.6 + *
    10.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    10.8 + *
    10.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   10.10 + * of this software and associated documentation files (the "Software"), to deal
   10.11 + * in the Software without restriction, including without limitation the rights
   10.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   10.13 + * copies of the Software, and to permit persons to whom the Software is
   10.14 + * furnished to do so, subject to the following conditions:
   10.15 + *
   10.16 + * The above copyright notice and this permission notice shall be included in
   10.17 + * all copies or substantial portions of the Software.
   10.18 + *
   10.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   10.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   10.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   10.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   10.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   10.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   10.25 + * THE SOFTWARE.
   10.26 + */
   10.27 +package com.oracle.chess.client.htmljava;
   10.28 +
   10.29 +
   10.30 +public final class LoadMain {
   10.31 +    private LoadMain() {
   10.32 +    }
   10.33 +    
   10.34 +    /**
   10.35 +     * Called when the page is ready.
   10.36 +     */
   10.37 +    static {
   10.38 +        try {
   10.39 +            UIModel.initialize();
   10.40 +        } catch (Throwable ex) {
   10.41 +            ex.printStackTrace();
   10.42 +        }
   10.43 +    }
   10.44 +}
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/Main.java	Tue Sep 24 22:20:24 2013 +0200
    11.3 @@ -0,0 +1,42 @@
    11.4 +/**
    11.5 + * The MIT License (MIT)
    11.6 + *
    11.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    11.8 + *
    11.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   11.10 + * of this software and associated documentation files (the "Software"), to deal
   11.11 + * in the Software without restriction, including without limitation the rights
   11.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   11.13 + * copies of the Software, and to permit persons to whom the Software is
   11.14 + * furnished to do so, subject to the following conditions:
   11.15 + *
   11.16 + * The above copyright notice and this permission notice shall be included in
   11.17 + * all copies or substantial portions of the Software.
   11.18 + *
   11.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   11.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   11.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   11.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   11.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   11.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   11.25 + * THE SOFTWARE.
   11.26 + */
   11.27 +package com.oracle.chess.client.htmljava;
   11.28 +
   11.29 +import net.java.html.boot.BrowserBuilder;
   11.30 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
   11.31 +
   11.32 +public final class Main {
   11.33 +    private Main() {
   11.34 +    }
   11.35 +
   11.36 +    @JavaScriptOnly(name = "main", value = "null")
   11.37 +    public static void main(String... args) throws Exception {
   11.38 +        BrowserBuilder.newBrowser().
   11.39 +            loadPage("pages/index.html").
   11.40 +            loadClass(UIModel.class).
   11.41 +            invoke("initialize", args).
   11.42 +            showAndWait();
   11.43 +        System.exit(0);
   11.44 +    }
   11.45 +}
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/MsgType.java	Tue Sep 24 22:20:24 2013 +0200
    12.3 @@ -0,0 +1,40 @@
    12.4 +/**
    12.5 + * The MIT License (MIT)
    12.6 + *
    12.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    12.8 + *
    12.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   12.10 + * of this software and associated documentation files (the "Software"), to deal
   12.11 + * in the Software without restriction, including without limitation the rights
   12.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   12.13 + * copies of the Software, and to permit persons to whom the Software is
   12.14 + * furnished to do so, subject to the following conditions:
   12.15 + *
   12.16 + * The above copyright notice and this permission notice shall be included in
   12.17 + * all copies or substantial portions of the Software.
   12.18 + *
   12.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   12.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   12.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   12.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   12.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   12.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   12.25 + * THE SOFTWARE.
   12.26 + */
   12.27 +package com.oracle.chess.client.htmljava;
   12.28 +
   12.29 +/**
   12.30 + *
   12.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   12.32 + */
   12.33 + enum MsgType {
   12.34 +    CreateGame, QueryGames, SendMove, JoinGame, UpdateGame, CheckCredentials;
   12.35 +
   12.36 +    static MsgType forResponse(String msg) {
   12.37 +        if (msg.endsWith("Rsp")) {
   12.38 +            msg = msg.substring(0, msg.length() - 3);
   12.39 +        }
   12.40 +        return MsgType.valueOf(msg);
   12.41 +    }
   12.42 +    
   12.43 +}
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java	Tue Sep 24 22:20:24 2013 +0200
    13.3 @@ -0,0 +1,314 @@
    13.4 +/**
    13.5 + * The MIT License (MIT)
    13.6 + *
    13.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    13.8 + *
    13.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   13.10 + * of this software and associated documentation files (the "Software"), to deal
   13.11 + * in the Software without restriction, including without limitation the rights
   13.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   13.13 + * copies of the Software, and to permit persons to whom the Software is
   13.14 + * furnished to do so, subject to the following conditions:
   13.15 + *
   13.16 + * The above copyright notice and this permission notice shall be included in
   13.17 + * all copies or substantial portions of the Software.
   13.18 + *
   13.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   13.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   13.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   13.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   13.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   13.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   13.25 + * THE SOFTWARE.
   13.26 + */
   13.27 +package com.oracle.chess.client.htmljava;
   13.28 +
   13.29 +import java.util.ArrayList;
   13.30 +import java.util.List;
   13.31 +
   13.32 +/** Common chess rules.
   13.33 + *
   13.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   13.35 + */
   13.36 +class Rules {
   13.37 +    static void computeAccessible(Board b, Square s) {
   13.38 +        for (Row r : b.getRows()) {
   13.39 +            for (Square ts : r.getColumns()) {
   13.40 +                ts.setAccessible(false);
   13.41 +            }
   13.42 +        }
   13.43 +        if (s == null) {
   13.44 +            return;
   13.45 +        }
   13.46 +        
   13.47 +        switch (s.getPiece()) {
   13.48 +            case BISHOP: 
   13.49 +                moveBishop(b, s);
   13.50 +                break;
   13.51 +            case KING:
   13.52 +                computeAccessible(b, s, 1, 1, 1);
   13.53 +                computeAccessible(b, s, 1, -1, 1);
   13.54 +                computeAccessible(b, s, -1, -1, 1);
   13.55 +                computeAccessible(b, s, -1, 1, 1);
   13.56 +                computeAccessible(b, s, 1, 0, 1);
   13.57 +                computeAccessible(b, s, 0, -1, 1);
   13.58 +                computeAccessible(b, s, 0, 1, 1);
   13.59 +                computeAccessible(b, s, -1, 0, 1);
   13.60 +                checkRochade(b, s);
   13.61 +                break;
   13.62 +            case ROCK:
   13.63 +                moveRock(b, s);
   13.64 +                break;
   13.65 +            case QUEEN:
   13.66 +                moveRock(b, s);
   13.67 +                moveBishop(b, s);
   13.68 +                break;
   13.69 +            case KNIGHT:
   13.70 +                computeAccessible(b, s, 2, 1, 1);
   13.71 +                computeAccessible(b, s, 2, -1, 1);
   13.72 +                computeAccessible(b, s, -2, -1, 1);
   13.73 +                computeAccessible(b, s, -2, 1, 1);
   13.74 +                computeAccessible(b, s, 1, 2, 1);
   13.75 +                computeAccessible(b, s, -1, 2, 1);
   13.76 +                computeAccessible(b, s, -1, -2, 1);
   13.77 +                computeAccessible(b, s, 1, -2, 1);
   13.78 +                break;
   13.79 +            case PAWN:
   13.80 +                pawns(b, s);
   13.81 +                break;
   13.82 +        }
   13.83 +    }
   13.84 +
   13.85 +    private static void moveRock(Board b, Square s) {
   13.86 +        computeAccessible(b, s, 1, 0, 8);
   13.87 +        computeAccessible(b, s, 0, -1, 8);
   13.88 +        computeAccessible(b, s, -1, 0, 8);
   13.89 +        computeAccessible(b, s, 0, 1, 8);
   13.90 +    }
   13.91 +
   13.92 +    private static void moveBishop(Board b, Square s) {
   13.93 +        computeAccessible(b, s, 1, 1, 8);
   13.94 +        computeAccessible(b, s, 1, -1, 8);
   13.95 +        computeAccessible(b, s, -1, -1, 8);
   13.96 +        computeAccessible(b, s, -1, 1, 8);
   13.97 +    }
   13.98 +    
   13.99 +    private static void computeAccessible(
  13.100 +        Board b, Square s, int dx, int dy,
  13.101 +        int limit
  13.102 +    ) {
  13.103 +        int x = s.getX();
  13.104 +        int y = s.getY();
  13.105 +        
  13.106 +        while (limit-- > 0) {
  13.107 +            x += dx;
  13.108 +            y += dy;
  13.109 +            Square next = BoardModel.findSquare(b, (char)x, y);
  13.110 +            if (next == null) {
  13.111 +                break;
  13.112 +            }
  13.113 +            if (next.getPieceColor() == s.getPieceColor()) {
  13.114 +                break;
  13.115 +            }
  13.116 +            next.setAccessible(true);
  13.117 +            if (next.getPieceColor() != null) {
  13.118 +                break;
  13.119 +            }
  13.120 +        }
  13.121 +    }
  13.122 +    
  13.123 +    private static void pawns(Board b, Square s) {
  13.124 +        final boolean white = s.getPieceColor() == Color.W;
  13.125 +        int dy = white ? 1 : -1;
  13.126 +        Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
  13.127 +        if (step != null && step.getPiece() == null) {
  13.128 +            step.setAccessible(true);
  13.129 +            if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
  13.130 +                Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
  13.131 +                if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
  13.132 +                    nextSTep.setAccessible(true);
  13.133 +                }
  13.134 +            }
  13.135 +        }
  13.136 +        Color opposite = white ? Color.B : Color.W;
  13.137 +        Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
  13.138 +        if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
  13.139 +            takeLeft.setAccessible(true);
  13.140 +        }
  13.141 +        Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
  13.142 +        if (takeRight != null && takeRight.getPieceColor() == opposite) {
  13.143 +            takeRight.setAccessible(true);
  13.144 +        }
  13.145 +        if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
  13.146 +            int enPassantFrom = white ? 7 : 2;
  13.147 +            int enPassantTo = white ? 5 : 4;
  13.148 +            if (!b.getMoves().isEmpty()) {
  13.149 +                Move last = b.getMoves().get(b.getMoves().size() - 1);
  13.150 +                if (
  13.151 +                    last.getPiece() == BoardModel.PieceType.PAWN &&
  13.152 +                    last.getFrom().getY() == enPassantFrom &&
  13.153 +                    last.getTo().getY() == enPassantTo
  13.154 +                ) {
  13.155 +                    if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
  13.156 +                        takeLeft.setAccessible(true);
  13.157 +                    }
  13.158 +                    if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
  13.159 +                        takeRight.setAccessible(true);
  13.160 +                    }
  13.161 +                }
  13.162 +            }
  13.163 +        }
  13.164 +    }
  13.165 +
  13.166 +    static Board createBoard() {
  13.167 +        Board b = new Board();
  13.168 +        initBoardField(b);
  13.169 +        initBoard(b);
  13.170 +        return b;
  13.171 +    }
  13.172 +
  13.173 +    private static void initBoardField(Board b) {
  13.174 +        List<Row> addRows = new ArrayList<>(8);
  13.175 +        for (int i = 8; i > 0; i--) {
  13.176 +            Square[] arr = new Square[8];
  13.177 +            for (char j = 'A'; j <= 'H'; j++) {
  13.178 +                arr[j - 'A'] = new Square(
  13.179 +                    new Position(j, i),
  13.180 +                    (i + j) % 2 == 1 ? Color.W : Color.B,
  13.181 +                    null, null, // figure
  13.182 +                    false, false, false
  13.183 +                );
  13.184 +            }
  13.185 +            addRows.add(new Row(arr));
  13.186 +        }
  13.187 +        b.getRows().addAll(addRows);
  13.188 +    }
  13.189 +    
  13.190 +    static void initBoard(Board b) {
  13.191 +        initBoard(b, true);
  13.192 +    }
  13.193 +    private static void initBoard(Board b, boolean init) {
  13.194 +        if (init) {
  13.195 +            b.setTurn(Color.W);
  13.196 +        }
  13.197 +        if (b.getRows().isEmpty()) {
  13.198 +            for (int i = 8; i > 0; i--) {
  13.199 +                Row r = b.getRows().get(8 - i);
  13.200 +                for (char j = 'A'; j <= 'H'; j++) {
  13.201 +                    Square s = r.getColumns().get(j - 'A');
  13.202 +                    s.setAccessible(false);
  13.203 +                    s.setPending(false);
  13.204 +                    r.getColumns().set(j - 'A', s);
  13.205 +                    initialPosition(s, init);
  13.206 +                }
  13.207 +            }
  13.208 +        } else {
  13.209 +            for (Row r : b.getRows()) {
  13.210 +                for (Square square : r.getColumns()) {
  13.211 +                    square.setAccessible(false);
  13.212 +                    square.setPending(false);
  13.213 +                    square.setPiece(null);
  13.214 +                    square.setPieceColor(null);
  13.215 +                    square.setSelected(false);
  13.216 +                    initialPosition(square, init);
  13.217 +                }
  13.218 +            }
  13.219 +        }
  13.220 +        b.setPendingMove(null);
  13.221 +    }
  13.222 +
  13.223 +    private static void initialPosition(Square s, boolean init) {
  13.224 +        int row = s.getPosition().getY();
  13.225 +        char column = s.getPosition().getX();
  13.226 +        s.setPiece(null);
  13.227 +        s.setPieceColor(null);
  13.228 +        if (init) {
  13.229 +            if (row == 2) {
  13.230 +                s.setPiece(BoardModel.PieceType.PAWN);
  13.231 +                s.setPieceColor(Color.W);
  13.232 +            } else if (row == 7) {
  13.233 +                s.setPiece(BoardModel.PieceType.PAWN);
  13.234 +                s.setPieceColor(Color.B);
  13.235 +            } else if (row == 8 || row == 1) {
  13.236 +                s.setPieceColor(row == 1 ? Color.W : Color.B);
  13.237 +                BoardModel.PieceType t;
  13.238 +                switch (column) {
  13.239 +                    case 'A':
  13.240 +                    case 'H':
  13.241 +                        t = BoardModel.PieceType.ROCK;
  13.242 +                        break;
  13.243 +                    case 'B':
  13.244 +                    case 'G':
  13.245 +                        t = BoardModel.PieceType.KNIGHT;
  13.246 +                        break;
  13.247 +                    case 'C':
  13.248 +                    case 'F':
  13.249 +                        t = BoardModel.PieceType.BISHOP;
  13.250 +                        break;
  13.251 +                    case 'D':
  13.252 +                        t = BoardModel.PieceType.QUEEN;
  13.253 +                        break;
  13.254 +                    default:
  13.255 +                        t = BoardModel.PieceType.KING;
  13.256 +                        break;
  13.257 +                }
  13.258 +                s.setPiece(t);
  13.259 +            }
  13.260 +        }
  13.261 +    }
  13.262 +
  13.263 +    static void initBoard(
  13.264 +        Board board, List<String> whites, List<String> blacks, Color turn
  13.265 +    ) {
  13.266 +        initBoard(board, false);
  13.267 +        for (String w : whites) {
  13.268 +            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
  13.269 +            w = w.toUpperCase();
  13.270 +            char column = w.charAt(1);
  13.271 +            int row = (w.charAt(2) - '0');
  13.272 +            
  13.273 +            Square s = BoardModel.findSquare(board, column, row);
  13.274 +            s.setPieceColor(Color.W);
  13.275 +            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
  13.276 +        }
  13.277 +        for (String w : blacks) {
  13.278 +            assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
  13.279 +            w = w.toUpperCase();
  13.280 +            char column = w.charAt(1);
  13.281 +            int row = (w.charAt(2) - '0');
  13.282 +            
  13.283 +            Square s = BoardModel.findSquare(board, column, row);
  13.284 +            s.setPieceColor(Color.B);
  13.285 +            s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
  13.286 +        }
  13.287 +        board.setTurn(turn);
  13.288 +    }
  13.289 +
  13.290 +    private static void checkRochade(Board b, Square s) {
  13.291 +        if (s.getPosition().getX() == 'E') {
  13.292 +            int y = s.getPosition().getY();
  13.293 +            final Square gRow = BoardModel.findSquare(b, 'G', y);
  13.294 +            if (
  13.295 +                BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK 
  13.296 +                &&
  13.297 +                BoardModel.findSquare(b, 'F', y).getPiece() == null
  13.298 +                &&
  13.299 +                gRow.getPiece() == null
  13.300 +            ) {
  13.301 +                gRow.setAccessible(true);
  13.302 +            }
  13.303 +            final Square cRow = BoardModel.findSquare(b, 'C', y);
  13.304 +            if (
  13.305 +                BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK 
  13.306 +                &&
  13.307 +                BoardModel.findSquare(b, 'B', y).getPiece() == null
  13.308 +                &&
  13.309 +                BoardModel.findSquare(b, 'D', y).getPiece() == null
  13.310 +                &&
  13.311 +                cRow.getPiece() == null
  13.312 +            ) {
  13.313 +                cRow.setAccessible(true);
  13.314 +            }
  13.315 +        }
  13.316 +    }
  13.317 +}
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/SettingsModel.java	Tue Sep 24 22:20:24 2013 +0200
    14.3 @@ -0,0 +1,82 @@
    14.4 +/**
    14.5 + * The MIT License (MIT)
    14.6 + *
    14.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    14.8 + *
    14.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   14.10 + * of this software and associated documentation files (the "Software"), to deal
   14.11 + * in the Software without restriction, including without limitation the rights
   14.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   14.13 + * copies of the Software, and to permit persons to whom the Software is
   14.14 + * furnished to do so, subject to the following conditions:
   14.15 + *
   14.16 + * The above copyright notice and this permission notice shall be included in
   14.17 + * all copies or substantial portions of the Software.
   14.18 + *
   14.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   14.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   14.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   14.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   14.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   14.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   14.25 + * THE SOFTWARE.
   14.26 + */
   14.27 +package com.oracle.chess.client.htmljava;
   14.28 +
   14.29 +import java.io.File;
   14.30 +import java.io.FileInputStream;
   14.31 +import java.io.FileOutputStream;
   14.32 +import java.io.IOException;
   14.33 +import java.util.Properties;
   14.34 +import net.java.html.json.ComputedProperty;
   14.35 +import net.java.html.json.Model;
   14.36 +import net.java.html.json.ModelOperation;
   14.37 +import net.java.html.json.Property;
   14.38 +
   14.39 +/**
   14.40 + *
   14.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   14.42 + */
   14.43 +@Model(className = "Settings", properties = {
   14.44 +    @Property(name = "username", type = String.class),
   14.45 +    @Property(name = "password", type = String.class),
   14.46 +    @Property(name = "url", type = String.class),
   14.47 +})
   14.48 +class SettingsModel {
   14.49 +    private static final String SETTINGS = ".j1chess/html.properties";
   14.50 +    private static final String DEFAULT_URL = "ws://localhost:8080/chess/chessserver";
   14.51 +    
   14.52 +    @ComputedProperty static boolean validCredentials(String username, String password) {
   14.53 +        return username != null && password != null && !username.isEmpty() && !password.isEmpty();
   14.54 +    }
   14.55 +    
   14.56 +    @ModelOperation static void read(Settings s) {
   14.57 +        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   14.58 +        try (FileInputStream is = new FileInputStream(prefs)) {
   14.59 +            Properties p = new Properties();
   14.60 +            p.load(is);
   14.61 +            
   14.62 +            s.setUsername(p.getProperty("username", ""));
   14.63 +            s.setPassword(p.getProperty("password", ""));
   14.64 +            s.setUrl(p.getProperty("url", DEFAULT_URL));
   14.65 +        } catch (Throwable ex) {
   14.66 +            s.setUsername("");
   14.67 +            s.setPassword("");
   14.68 +            s.setUrl(DEFAULT_URL);
   14.69 +        }
   14.70 +    }
   14.71 +    
   14.72 +    @ModelOperation static void write(Settings s, UI ui) {
   14.73 +        File prefs = new File(System.getProperty("user.home"), SETTINGS);
   14.74 +        prefs.getParentFile().mkdirs();
   14.75 +        try (FileOutputStream os = new FileOutputStream(prefs)) {
   14.76 +            Properties p = new Properties();
   14.77 +            p.setProperty("username", s.getUsername());
   14.78 +            p.setProperty("password", s.getPassword());
   14.79 +            p.setProperty("url", s.getUrl());
   14.80 +            p.store(os, "Java One Chess Preferences for HTML/Java Client");
   14.81 +        } catch (Throwable ex) {
   14.82 +            ui.setStatus("Cannot save preferences: " + ex.getMessage());
   14.83 +        }
   14.84 +    }
   14.85 +}
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java	Tue Sep 24 22:20:24 2013 +0200
    15.3 @@ -0,0 +1,315 @@
    15.4 +/**
    15.5 + * The MIT License (MIT)
    15.6 + *
    15.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    15.8 + *
    15.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   15.10 + * of this software and associated documentation files (the "Software"), to deal
   15.11 + * in the Software without restriction, including without limitation the rights
   15.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   15.13 + * copies of the Software, and to permit persons to whom the Software is
   15.14 + * furnished to do so, subject to the following conditions:
   15.15 + *
   15.16 + * The above copyright notice and this permission notice shall be included in
   15.17 + * all copies or substantial portions of the Software.
   15.18 + *
   15.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   15.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   15.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   15.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   15.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   15.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   15.25 + * THE SOFTWARE.
   15.26 + */
   15.27 +package com.oracle.chess.client.htmljava;
   15.28 +
   15.29 +import java.io.IOException;
   15.30 +import java.net.URISyntaxException;
   15.31 +import java.util.HashSet;
   15.32 +import java.util.List;
   15.33 +import java.util.Set;
   15.34 +import java.util.logging.Level;
   15.35 +import java.util.logging.Logger;
   15.36 +import net.java.html.json.ComputedProperty;
   15.37 +import net.java.html.json.Function;
   15.38 +import net.java.html.json.Model;
   15.39 +import net.java.html.json.ModelOperation;
   15.40 +import net.java.html.json.OnPropertyChange;
   15.41 +import net.java.html.json.OnReceive;
   15.42 +import net.java.html.json.Property;
   15.43 +
   15.44 +/**
   15.45 + *
   15.46 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   15.47 + */
   15.48 +@Model(className = "UI", properties = {
   15.49 +    @Property(name = "status", type = String.class),
   15.50 +    @Property(name = "selectedGameId", type = String.class),
   15.51 +    @Property(name = "boards", type = Board.class, array = true),
   15.52 +    @Property(name = "viewGames", type = Games.class),
   15.53 +    @Property(name = "settings", type = Settings.class),
   15.54 +    @Property(name = "connected", type = boolean.class),
   15.55 +    @Property(name = "disconnected", type = boolean.class),
   15.56 +})
   15.57 +public class UIModel {
   15.58 +    private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
   15.59 +    
   15.60 +    @ComputedProperty static boolean settingsActive(String selectedGameId) {
   15.61 +        return selectedGameId == null;
   15.62 +    }
   15.63 +    
   15.64 +    @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
   15.65 +        return selectedGameId == null && connected;
   15.66 +    }
   15.67 +    
   15.68 +    @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
   15.69 +        Board active = null;
   15.70 +        for (Board b : boards) {
   15.71 +            b.setActive(false);
   15.72 +            if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
   15.73 +                b.setActive(true);
   15.74 +                active = b;
   15.75 +            }
   15.76 +        }
   15.77 +        return active;
   15.78 +    }
   15.79 +    
   15.80 +    @Function static void activateGame(UI m, Board data) {
   15.81 +        m.setSelectedGameId(data.getGameId());
   15.82 +    }
   15.83 +
   15.84 +    @Function static void activateSettings(UI m) {
   15.85 +        m.setSelectedGameId(null);
   15.86 +        refreshGames(m);
   15.87 +    }
   15.88 +    
   15.89 +    @Function static void createGame(UI u) {
   15.90 +        u.setStatus("Creating new game...");
   15.91 +        Request r = new Request();
   15.92 +        r.setMsg(MsgType.CreateGame);
   15.93 +        r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
   15.94 +        u.sendMsg(r);
   15.95 +    }
   15.96 +
   15.97 +    @ModelOperation @Function static void refreshGames(UI u) {
   15.98 +        u.setStatus("Refreshing games...");
   15.99 +        Request r = new Request();
  15.100 +        r.setMsg(MsgType.QueryGames);
  15.101 +        u.sendMsg(r);
  15.102 +    }
  15.103 +    
  15.104 +    @ModelOperation static void sendMsg(UI ui, Request r) {
  15.105 +        final Settings sttngs = ui.getSettings();
  15.106 +        
  15.107 +        String url = sttngs.getUrl();
  15.108 +        r.setUsername(sttngs.getUsername());
  15.109 +        r.setPassword(sttngs.getPassword());
  15.110 +        
  15.111 +        LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
  15.112 +        ui.queryServer(url, r);
  15.113 +    }
  15.114 +    
  15.115 +    
  15.116 +    @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError") 
  15.117 +    static void queryServer(UI ui, Response r) {
  15.118 +        LOG.log(Level.INFO, "Received {0}", r);
  15.119 +        if (r == null) {
  15.120 +            ui.setDisconnected(false);
  15.121 +            verifyLogin(ui);
  15.122 +            return;
  15.123 +        }
  15.124 +        SWITCH: switch (MsgType.forResponse(r.getMsg())) {
  15.125 +            case CheckCredentials: {
  15.126 +                switch (r.getCheck()) {
  15.127 +                    case NOT_REGISTERED:
  15.128 +                    case VALID:
  15.129 +                        ui.setConnected(true);
  15.130 +                        ui.refreshGames();
  15.131 +                        ui.setStatus("Connected.");
  15.132 +                        return;
  15.133 +                    case INVALID:
  15.134 +                        ui.setStatus("Password is invalid");
  15.135 +                        break;
  15.136 +                }
  15.137 +                disconnect(ui);
  15.138 +            }
  15.139 +                
  15.140 +            case QueryGames:
  15.141 +                ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
  15.142 +                ui.setStatus("");
  15.143 +                break;
  15.144 +            case CreateGame: {
  15.145 +                ui.setStatus("Game " + r + " created");
  15.146 +                final Board b = Rules.createBoard();
  15.147 +                Rules.initBoard(
  15.148 +                    b, r.getBoard().getWhites(),
  15.149 +                    r.getBoard().getBlacks(),
  15.150 +                    r.getTurn()
  15.151 +                );
  15.152 +                b.setGameId(r.getGameId());
  15.153 +                b.setWhitePlayer(r.getWhitePlayer());
  15.154 +                b.setBlackPlayer(r.getBlackPlayer());
  15.155 +                b.setPlayer(ui.getSettings().getUsername());
  15.156 +                b.updateSummary(r.getSummary());
  15.157 +                ui.getBoards().add(b);
  15.158 +                ui.setSelectedGameId(r.getGameId());
  15.159 +                UIModel.refreshGames(ui);
  15.160 +                break;
  15.161 +            }
  15.162 +            case SendMove: {
  15.163 +                if (r.getBoard() == null) {
  15.164 +                    throw new NullPointerException("No board in " + r);
  15.165 +                }
  15.166 +                final Board b = findBoard(ui, r.getGameId());
  15.167 +                if (b == null) {
  15.168 +                    break;
  15.169 +                }
  15.170 +                b.updateSummary(r.getSummary());
  15.171 +                final String errMsg = r.getError() == null ? null : r.getError().getMessage();
  15.172 +                final List<String> whites = r.getBoard().getWhites();
  15.173 +                final List<String> blacks = r.getBoard().getBlacks();
  15.174 +                final Color turn = r.getNextTurn();
  15.175 +                BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
  15.176 +                break;
  15.177 +            }
  15.178 +            case JoinGame: {
  15.179 +                Board b;
  15.180 +                if ((b = findBoard(ui, r.getGameId())) != null) {
  15.181 +                    b.setWhitePlayer(r.getWhitePlayer());
  15.182 +                    b.setBlackPlayer(r.getBlackPlayer());
  15.183 +                    b.setPlayer(ui.getSettings().getUsername());
  15.184 +                    b.updateSummary(r.getSummary());
  15.185 +                    ui.setSelectedGameId(r.getGameId());
  15.186 +                    break SWITCH;
  15.187 +                }
  15.188 +                ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
  15.189 +                b = Rules.createBoard();
  15.190 +                Rules.initBoard(
  15.191 +                    b, r.getBoard().getWhites(),
  15.192 +                    r.getBoard().getBlacks(),
  15.193 +                    r.getTurn()
  15.194 +                );
  15.195 +                b.setGameId(r.getGameId());
  15.196 +                b.setWhitePlayer(r.getWhitePlayer());
  15.197 +                b.setBlackPlayer(r.getBlackPlayer());
  15.198 +                b.setPlayer(ui.getSettings().getUsername());
  15.199 +                b.updateSummary(r.getSummary());
  15.200 +                if (r.getColor() == Color.B) {
  15.201 +                    BoardModel.rotateBoard(b);
  15.202 +                }
  15.203 +                if (r.getMoves() != null) {
  15.204 +                    for (String move : r.getMoves()) {
  15.205 +                        Move m = BoardModel.MoveImpl.valueOf(move);
  15.206 +                        b.getMoves().add(m);
  15.207 +                    }
  15.208 +                } else {
  15.209 +                    b.getMoves().clear();
  15.210 +                }
  15.211 +                ui.setSelectedGameId(b.getGameId());
  15.212 +                ui.getBoards().add(b);
  15.213 +                break;
  15.214 +            }
  15.215 +            case UpdateGame: {
  15.216 +                final Board b = findBoard(ui, r.getGameId());
  15.217 +                if (b == null) {
  15.218 +                    break;
  15.219 +                }
  15.220 +                b.updateSummary(r.getSummary());
  15.221 +                final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
  15.222 +                final List<String> whites = r.getBoard().getWhites();
  15.223 +                final List<String> blacks = r.getBoard().getBlacks();
  15.224 +                final Color turn = r.getNextTurn();
  15.225 +                BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
  15.226 +            }
  15.227 +        }
  15.228 +    }
  15.229 +
  15.230 +
  15.231 +    private static Board findBoard(UI ui, String gameId) {
  15.232 +        for (Board tmp : ui.getBoards()) {
  15.233 +            if (tmp.getGameId().equals(gameId)) {
  15.234 +                return tmp;
  15.235 +            }
  15.236 +        }
  15.237 +        return null;
  15.238 +    }
  15.239 +    
  15.240 +    
  15.241 +    static void wasAnError(UI ui, Exception t) {
  15.242 +        if (t == null) {
  15.243 +            ui.setConnected(false);
  15.244 +            ui.setDisconnected(true);
  15.245 +            ui.setStatus("Disconnected.");
  15.246 +        } else {
  15.247 +            ui.setStatus("Error: " + t.getLocalizedMessage());
  15.248 +        }
  15.249 +    }
  15.250 +    
  15.251 +    @Function static void joinGame(UI u, Game data) {
  15.252 +        Request r = new Request();
  15.253 +        r.setMsg(MsgType.JoinGame);
  15.254 +        r.setObserver(false);
  15.255 +        r.setGameId(data.getGameId());
  15.256 +        u.sendMsg(r);
  15.257 +    }
  15.258 +
  15.259 +    @Function static void observeGame(UI u, Game data) {
  15.260 +        Request r = new Request();
  15.261 +        r.setMsg(MsgType.JoinGame);
  15.262 +        r.setObserver(true);
  15.263 +        r.setGameId(data.getGameId());
  15.264 +        u.sendMsg(r);
  15.265 +    }
  15.266 +
  15.267 +    private static final Set<UI> ACTIVE = new HashSet<>();
  15.268 +    @OnPropertyChange("connected") static void clearGames(UI m) {
  15.269 +        if (m.isDisconnected()) {
  15.270 +            m.getBoards().clear();
  15.271 +            ACTIVE.remove(m);
  15.272 +        } else {
  15.273 +            ACTIVE.add(m);
  15.274 +        }
  15.275 +    }
  15.276 +    
  15.277 +    static UI findUI(Board b) {
  15.278 +        for (UI ui : ACTIVE) {
  15.279 +            if (ui.getBoards().contains(b)) {
  15.280 +                return ui;
  15.281 +            }
  15.282 +        }
  15.283 +        return null;
  15.284 +    }
  15.285 +    
  15.286 +    @Function static void leave(UI ui, Board data) {
  15.287 +        ui.getBoards().remove(data);
  15.288 +        ui.setSelectedGameId(null);
  15.289 +    }
  15.290 +    
  15.291 +    @Function static void disconnect(UI ui) {
  15.292 +        ui.queryServer(ui.getSettings().getUrl(), null);
  15.293 +        ui.setStatus("Disconnecting...");
  15.294 +    }
  15.295 +
  15.296 +    private static void verifyLogin(UI ui) {
  15.297 +        ui.setStatus("Verifying user credentials...");
  15.298 +        Request r = new Request();
  15.299 +        r.setMsg(MsgType.CheckCredentials);
  15.300 +        ui.sendMsg(r);
  15.301 +    }
  15.302 +    
  15.303 +    @Function static void reconnect(UI ui) {
  15.304 +        final Settings s = ui.getSettings();
  15.305 +        ui.setStatus("Connecting to the server...");
  15.306 +        ui.queryServer(s.getUrl(), null);
  15.307 +        s.write(ui);
  15.308 +    }
  15.309 +    
  15.310 +    public static void initialize(String... args) throws URISyntaxException, IOException {
  15.311 +        UI ui = new UI();
  15.312 +        ui.getSettings().read();
  15.313 +        ui.setStatus("Ready.");
  15.314 +        ui.setDisconnected(true);
  15.315 +        ui.applyBindings();
  15.316 +    }
  15.317 +
  15.318 +}
    16.1 Binary file chess/src/main/webapp/pages/DukeHTML.png has changed
    17.1 --- a/chess/src/main/webapp/pages/css/bootstrap.css	Tue Sep 24 21:08:15 2013 +0200
    17.2 +++ b/chess/src/main/webapp/pages/css/bootstrap.css	Tue Sep 24 22:20:24 2013 +0200
    17.3 @@ -1119,7 +1119,7 @@
    17.4  input,
    17.5  textarea,
    17.6  .uneditable-input {
    17.7 -  width: 206px;
    17.8 +  width: 300px;
    17.9  }
   17.10  
   17.11  textarea {
   17.12 @@ -1205,7 +1205,7 @@
   17.13    *margin-top: 4px;
   17.14    /* For IE7, add top margin to align select with labels */
   17.15  
   17.16 -  line-height: 30px;
   17.17 +    vertical-align: middle;
   17.18  }
   17.19  
   17.20  select {
   17.21 @@ -1775,6 +1775,7 @@
   17.22    -webkit-border-radius: 4px 0 0 4px;
   17.23       -moz-border-radius: 4px 0 0 4px;
   17.24            border-radius: 4px 0 0 4px;
   17.25 +    color: black;
   17.26  }
   17.27  
   17.28  .input-append input + .btn-group .btn:last-child,
   17.29 @@ -3218,7 +3219,7 @@
   17.30    line-height: 20px;
   17.31    color: #333333;
   17.32    text-align: center;
   17.33 -  text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
   17.34 +  text-shadow: none;
   17.35    vertical-align: middle;
   17.36    cursor: pointer;
   17.37    background-color: #f5f5f5;
   17.38 @@ -3966,7 +3967,7 @@
   17.39  }
   17.40  
   17.41  .nav > li > a {
   17.42 -  display: block;
   17.43 +  display: inline-block;
   17.44  }
   17.45  
   17.46  .nav > li > a:hover,
   17.47 @@ -4625,7 +4626,7 @@
   17.48  
   17.49  .navbar .nav > li > a {
   17.50    float: none;
   17.51 -  padding: 10px 15px 10px;
   17.52 +  padding: 10px 23px 10px;
   17.53    color: #777777;
   17.54    text-decoration: none;
   17.55    text-shadow: 0 1px 0 #ffffff;
   17.56 @@ -5646,7 +5647,7 @@
   17.57    display: inline-block;
   17.58    padding: 2px 4px;
   17.59    font-size: 11.844px;
   17.60 -  font-weight: bold;
   17.61 +  font-weight: normal;
   17.62    line-height: 14px;
   17.63    color: #ffffff;
   17.64    text-shadow: 0 -1px 0 rgba(0, 0, 0, 0.25);
    18.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    18.2 +++ b/chess/src/main/webapp/pages/css/chess-phone-large.css	Tue Sep 24 22:20:24 2013 +0200
    18.3 @@ -0,0 +1,32 @@
    18.4 +/**
    18.5 + * The MIT License (MIT)
    18.6 + *
    18.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    18.8 + *
    18.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   18.10 + * of this software and associated documentation files (the "Software"), to deal
   18.11 + * in the Software without restriction, including without limitation the rights
   18.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   18.13 + * copies of the Software, and to permit persons to whom the Software is
   18.14 + * furnished to do so, subject to the following conditions:
   18.15 + *
   18.16 + * The above copyright notice and this permission notice shall be included in
   18.17 + * all copies or substantial portions of the Software.
   18.18 + *
   18.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   18.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   18.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   18.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   18.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   18.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   18.25 + * THE SOFTWARE.
   18.26 + */
   18.27 +table.board td {
   18.28 +    padding: 4px;
   18.29 +    width: 28px;
   18.30 +    height: 28px;
   18.31 +    font-size: 2em;
   18.32 +}
   18.33 +h1 {
   18.34 +    font-size: 15px;
   18.35 +}
   18.36 \ No newline at end of file
    19.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    19.2 +++ b/chess/src/main/webapp/pages/css/chess-phone-small.css	Tue Sep 24 22:20:24 2013 +0200
    19.3 @@ -0,0 +1,32 @@
    19.4 +/**
    19.5 + * The MIT License (MIT)
    19.6 + *
    19.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    19.8 + *
    19.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   19.10 + * of this software and associated documentation files (the "Software"), to deal
   19.11 + * in the Software without restriction, including without limitation the rights
   19.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   19.13 + * copies of the Software, and to permit persons to whom the Software is
   19.14 + * furnished to do so, subject to the following conditions:
   19.15 + *
   19.16 + * The above copyright notice and this permission notice shall be included in
   19.17 + * all copies or substantial portions of the Software.
   19.18 + *
   19.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   19.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   19.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   19.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   19.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   19.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   19.25 + * THE SOFTWARE.
   19.26 + */
   19.27 +table.board td {
   19.28 +    padding: 4px;
   19.29 +    width: 24px;
   19.30 +    height: 24px;
   19.31 +    font-size: 1.6em;
   19.32 +}
   19.33 +h1 {
   19.34 +    font-size: 12px;
   19.35 +}
   19.36 \ No newline at end of file
    20.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    20.2 +++ b/chess/src/main/webapp/pages/css/chess-tablet-large.css	Tue Sep 24 22:20:24 2013 +0200
    20.3 @@ -0,0 +1,32 @@
    20.4 +/**
    20.5 + * The MIT License (MIT)
    20.6 + *
    20.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    20.8 + *
    20.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   20.10 + * of this software and associated documentation files (the "Software"), to deal
   20.11 + * in the Software without restriction, including without limitation the rights
   20.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   20.13 + * copies of the Software, and to permit persons to whom the Software is
   20.14 + * furnished to do so, subject to the following conditions:
   20.15 + *
   20.16 + * The above copyright notice and this permission notice shall be included in
   20.17 + * all copies or substantial portions of the Software.
   20.18 + *
   20.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   20.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   20.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   20.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   20.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   20.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   20.25 + * THE SOFTWARE.
   20.26 + */
   20.27 +table.board td {
   20.28 +    padding: 8px;
   20.29 +    width: 42px;
   20.30 +    height: 42px;
   20.31 +    font-size: 3em;
   20.32 +}
   20.33 +h1 {
   20.34 +    font-size: 22px;
   20.35 +}
   20.36 \ No newline at end of file
    21.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    21.2 +++ b/chess/src/main/webapp/pages/css/chess-tablet-small.css	Tue Sep 24 22:20:24 2013 +0200
    21.3 @@ -0,0 +1,32 @@
    21.4 +/**
    21.5 + * The MIT License (MIT)
    21.6 + *
    21.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    21.8 + *
    21.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   21.10 + * of this software and associated documentation files (the "Software"), to deal
   21.11 + * in the Software without restriction, including without limitation the rights
   21.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   21.13 + * copies of the Software, and to permit persons to whom the Software is
   21.14 + * furnished to do so, subject to the following conditions:
   21.15 + *
   21.16 + * The above copyright notice and this permission notice shall be included in
   21.17 + * all copies or substantial portions of the Software.
   21.18 + *
   21.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   21.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   21.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   21.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   21.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   21.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   21.25 + * THE SOFTWARE.
   21.26 + */
   21.27 +table.board td {
   21.28 +    padding: 6px;
   21.29 +    width: 34px;
   21.30 +    height: 34px;
   21.31 +    font-size: 2.4em;
   21.32 +}
   21.33 +h1 {
   21.34 +    font-size: 18px;
   21.35 +}
   21.36 \ No newline at end of file
    22.1 --- a/chess/src/main/webapp/pages/css/chess.css	Tue Sep 24 21:08:15 2013 +0200
    22.2 +++ b/chess/src/main/webapp/pages/css/chess.css	Tue Sep 24 22:20:24 2013 +0200
    22.3 @@ -22,42 +22,103 @@
    22.4   * THE SOFTWARE.
    22.5   */
    22.6  /** main chess style **/
    22.7 +#apptitle {
    22.8 +    font-size: 20px;
    22.9 +}
   22.10  .log {
   22.11 -	overflow-x: hidden;
   22.12 -	overflow-y: scroll;
   22.13 -	max-height: 450px;
   22.14 -	border:1px solid #eeeeee;
   22.15 -	background-color: white;
   22.16 +    margin-bottom: 10px;
   22.17 +}
   22.18 +table.board td {
   22.19 +    border: 1px solid black;
   22.20 +    padding:10px;
   22.21 +    width: 56px;
   22.22 +    height: 56px;
   22.23 +    vertical-align: middle;
   22.24 +    text-align: center;
   22.25 +    font-size:4em;
   22.26 +}
   22.27 +table.board td.row-label, table.board td.col-label {
   22.28 +    font-size: 2em;
   22.29 +    border:none;
   22.30 +    width:20px;   
   22.31 +}
   22.32 +table.board td.col-label {
   22.33 +    height:20px;
   22.34  }
   22.35  .container {
   22.36 -	margin:10px;
   22.37 +    margin:10px;
   22.38  }
   22.39 -stable.board {
   22.40 -	width: 100%;
   22.41 -}
   22.42 -table.board {
   22.43 -	font-size:4em;
   22.44 -}
   22.45 -table.board td {
   22.46 -	border: 1px solid black;
   22.47 -	padding:10px;
   22.48 -	width:55px;
   22.49 -	height:55px;
   22.50 -	vertical-align: middle;
   22.51 -	text-align: center;
   22.52 -}
   22.53 +
   22.54  table.board td.white {
   22.55 -	background-color: white;
   22.56 +    background-color: #D0D0D0;
   22.57  }
   22.58  table.board td.black {
   22.59 -	background-color:  	#B0B0B0;
   22.60 +    background-color: #A0A0A0;
   22.61  }
   22.62  table.board td.selected {
   22.63 -	background-color:  	#B000B0;
   22.64 +    background-color:  	#bce8f1;
   22.65  }
   22.66  table.board td.accessible {
   22.67 -	background-color:  	#00B0B0;
   22.68 +    background-color:  	#a9dba9;
   22.69 +}
   22.70 +table.board td.pending {
   22.71 +    background-color:  	#dbc59e;
   22.72  }
   22.73  .figure {
   22.74 -	cursor: pointer;
   22.75 -}
   22.76 \ No newline at end of file
   22.77 +    cursor: pointer;
   22.78 +}
   22.79 +.but-orientation {
   22.80 +    margin-top:20px;
   22.81 +}
   22.82 +h3.log-h {
   22.83 +    border-top:1px solid silver;
   22.84 +}
   22.85 +.badge-status {
   22.86 +    display:inline-block;
   22.87 +    margin-left:20px;
   22.88 +    padding:5px;
   22.89 +    font-size:1em;
   22.90 +    text-shadow: none;
   22.91 +}
   22.92 +.badge-white-turn {
   22.93 +    font-size: 1em;
   22.94 +    padding:4px;
   22.95 +    background-color: white;
   22.96 +    color:black;
   22.97 +    text-shadow: none;
   22.98 +    border:1px solid black;
   22.99 +    font-weight: normal;
  22.100 +    display: inline-block;
  22.101 +    margin-left: 38px;
  22.102 +}
  22.103 +.badge-black-turn {
  22.104 +    font-size: 1em;
  22.105 +    padding:4px;
  22.106 +    background-color: black;
  22.107 +    color:white;
  22.108 +    text-shadow: none;
  22.109 +    border:1px solid black;
  22.110 +    font-weight: normal;
  22.111 +    display: inline-block;
  22.112 +    margin-left: 38px;
  22.113 +}
  22.114 +.btn {text-shadow: none;}
  22.115 +.select {line-height: inherit;}
  22.116 +.uneditable-input {
  22.117 +    margin-left: 0;
  22.118 +    color: black;
  22.119 +}
  22.120 +span.myturn {
  22.121 +    display: inline-block;
  22.122 +    position:relative;
  22.123 +    left:23px;
  22.124 +    padding:3px;
  22.125 +}
  22.126 +.whitePiece {
  22.127 +    text-shadow: -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
  22.128 +    color: white;
  22.129 +}
  22.130 +h1 {
  22.131 +    font-size: 29px;
  22.132 +    line-height: initial;
  22.133 +}
    23.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    23.2 +++ b/chess/src/main/webapp/pages/css/spinner.css	Tue Sep 24 22:20:24 2013 +0200
    23.3 @@ -0,0 +1,114 @@
    23.4 +/**
    23.5 + * The MIT License (MIT)
    23.6 + *
    23.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    23.8 + *
    23.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   23.10 + * of this software and associated documentation files (the "Software"), to deal
   23.11 + * in the Software without restriction, including without limitation the rights
   23.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   23.13 + * copies of the Software, and to permit persons to whom the Software is
   23.14 + * furnished to do so, subject to the following conditions:
   23.15 + *
   23.16 + * The above copyright notice and this permission notice shall be included in
   23.17 + * all copies or substantial portions of the Software.
   23.18 + *
   23.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   23.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   23.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   23.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   23.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   23.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   23.25 + * THE SOFTWARE.
   23.26 + */
   23.27 +/** chess cube style **/
   23.28 +
   23.29 +#chesscube {
   23.30 +    margin: 1em auto;
   23.31 +    -webkit-perspective: 1200px;
   23.32 +    perspective: 1200px;
   23.33 +    position: fixed; 
   23.34 +    z-index: -100;
   23.35 +    bottom:100px;
   23.36 +    right: 100px; 
   23.37 +    width: 160px; 
   23.38 +    height: 160px;    
   23.39 +    transition: opacity 1s;
   23.40 +}
   23.41 +
   23.42 +#spinner div {
   23.43 +    position: fixed;
   23.44 +    width: 160px;
   23.45 +    height: 160px;
   23.46 +    border: 1px solid #ccc;
   23.47 +    background: rgba(255,255,155,0.8);
   23.48 +    text-align: center;
   23.49 +    line-height: 160px;
   23.50 +    font-size: 120px;                
   23.51 +    -webkit-box-shadow: inset 0 0 40px rgba(0,0,0,0.4);
   23.52 +    box-shadow: inset 0 0 40px rgba(0,0,0,0.4);
   23.53 +}
   23.54 +
   23.55 +#spinner div:nth-child(1) {
   23.56 +    -webkit-transform: translateZ(80px);
   23.57 +    transform: translateZ(80px);
   23.58 +}
   23.59 +#spinner div:nth-child(2) {
   23.60 +    -webkit-transform: rotateY(90deg) translateZ(80px);
   23.61 +    transform: rotateY(90deg) translateZ(80px);
   23.62 +}
   23.63 +#spinner div:nth-child(3) {
   23.64 +    -webkit-transform: rotateY(90deg) rotateX(90deg) translateZ(80px);
   23.65 +    transform: rotateY(90deg) rotateX(90deg) translateZ(80px);
   23.66 +}
   23.67 +#spinner div:nth-child(4) {
   23.68 +    -webkit-transform: rotateY(180deg) rotateZ(90deg) translateZ(80px);
   23.69 +    transform: rotateY(180deg) rotateZ(90deg) translateZ(80px);
   23.70 +}
   23.71 +#spinner div:nth-child(5) {
   23.72 +    -webkit-transform: rotateY(-90deg) rotateZ(90deg) translateZ(80px);
   23.73 +    transform: rotateY(-90deg) rotateZ(90deg) translateZ(80px);
   23.74 +}
   23.75 +#spinner div:nth-child(6) {
   23.76 +    -webkit-transform: rotateX(-90deg) translateZ(80px);
   23.77 +    transform: rotateX(-90deg) translateZ(80px);
   23.78 +}
   23.79 +
   23.80 +@-webkit-keyframes spincube {
   23.81 +    from,to  {                                                    }            
   23.82 +    16%      { -webkit-transform: rotateY(-90deg);                }
   23.83 +    33%      { -webkit-transform: rotateY(-90deg) rotateZ(90deg); }
   23.84 +    50%      { -webkit-transform: rotateY(180deg) rotateZ(90deg); }
   23.85 +    66%      { -webkit-transform: rotateY(90deg) rotateX(90deg);  }
   23.86 +    83%      { -webkit-transform: rotateX(90deg);                 }
   23.87 +}
   23.88 +
   23.89 +@keyframes spincube {
   23.90 +    from,to  {                                                    }            
   23.91 +    16%      { transform: rotateY(-90deg);                }
   23.92 +    33%      { transform: rotateY(-90deg) rotateZ(90deg); }
   23.93 +    50%      { transform: rotateY(180deg) rotateZ(90deg); }
   23.94 +    66%      { transform: rotateY(90deg) rotateX(90deg);  }
   23.95 +    83%      { transform: rotateX(90deg);                 }
   23.96 +}
   23.97 +
   23.98 +#spinner {
   23.99 +    -webkit-animation-name: spincube;
  23.100 +    -webkit-animation-timing-function: ease-in-out;
  23.101 +    -webkit-animation-iteration-count: infinite;
  23.102 +    -webkit-animation-duration: 12s;
  23.103 +    -webkit-transform-style: preserve-3d;
  23.104 +    -webkit-transform-origin: 80px 80px 0;
  23.105 +    animation-name: spincube;
  23.106 +    animation-timing-function: ease-in-out;
  23.107 +    animation-iteration-count: infinite;
  23.108 +    animation-duration: 12s;
  23.109 +    transform-style: preserve-3d;
  23.110 +    transform-origin: 80px 80px 0;
  23.111 +}
  23.112 +
  23.113 +@media (max-width: 767px) {
  23.114 +    #chesscube {
  23.115 +        opacity: 0;
  23.116 +    }
  23.117 +}
    24.1 --- a/chess/src/main/webapp/pages/index.html	Tue Sep 24 21:08:15 2013 +0200
    24.2 +++ b/chess/src/main/webapp/pages/index.html	Tue Sep 24 22:20:24 2013 +0200
    24.3 @@ -25,107 +25,186 @@
    24.4  -->
    24.5  <!DOCTYPE html>
    24.6  <html lang="en">
    24.7 -<head>
    24.8 -	<meta charset="utf-8">
    24.9 -	<title>Chess Client</title>
   24.10 -	<meta name="viewport" content="width=device-width, initial-scale=1.0">
   24.11 -	<meta name="description" content="">
   24.12 -	<meta name="author" content="">
   24.13 +    <head>
   24.14 +        <meta charset="utf-8">
   24.15 +        <title>Chess Client</title>
   24.16 +        <meta name="viewport" content="width=device-width, initial-scale=1.0">
   24.17 +        <meta name="description" content="">
   24.18 +        <meta name="author" content="">
   24.19  
   24.20 -	<!-- Le styles -->
   24.21 -	<link href="./css/bootstrap.css" rel="stylesheet">
   24.22 -	<link href="./css/bootstrap-responsive.css" rel="stylesheet">
   24.23 -	<link href="./css/chess.css" rel="stylesheet">
   24.24 -</head>
   24.25 -<body>
   24.26 -	<div class="navbar">
   24.27 -		<div class="navbar-inner">
   24.28 -			<a class="brand" href="#">Chess Game</a>
   24.29 -			<ul class="nav">
   24.30 -				<li class="active"><a href="#">My Game</a></li>
   24.31 -				<li><a href="#">New game</a></li>
   24.32 -				<li><a href="#">View games</a></li>
   24.33 -				<li><a href="#">Blah..</a></li>
   24.34 -			</ul>
   24.35 -			<form class="navbar-search pull-right">
   24.36 -				<input type="text" class="search-query" placeholder="Search">
   24.37 -			</form>
   24.38 -		</div>
   24.39 -	</div>
   24.40 -	<div class="container-fluid">
   24.41 -		<div class="row-fluid">
   24.42 -			<div class="span9">
   24.43 -				<h1>My game</h1>
   24.44 -                <div data-bind="visible: blackTurn">Black's turn</div>
   24.45 -				<table class="board">
   24.46 -                    <tbody data-bind="foreach: rows">
   24.47 -                        <tr >
   24.48 -                            <!-- ko foreach: columns -->
   24.49 -                            <td data-bind="click: $root.selected, css: squareColor" >
   24.50 -                                <span data-bind='html: pieceEntity'></span>
   24.51 -                            </td>
   24.52 -                            <!-- /ko -->
   24.53 -                        </tr>
   24.54 -                    </tbody>
   24.55 -				</table>
   24.56 -                <div data-bind="visible: whiteTurn">White's turn</div>
   24.57 -			</div>
   24.58 -			<div class="span2 offset1">
   24.59 -				<h2>Game Log</h2>
   24.60 -				<div class="log">
   24.61 -					<table class="table table-striped log-table">
   24.62 -						<thead>
   24.63 -							<tr>
   24.64 -								<th>#</th>
   24.65 -								<th>Move</th>
   24.66 -							</tr>
   24.67 -						</thead>
   24.68 -						<tbody>
   24.69 -							<tr>
   24.70 -								<td>10</td>
   24.71 -								<td>Move</td>
   24.72 -							</tr>
   24.73 -							<tr>
   24.74 -								<td>9</td>
   24.75 -								<td>Move</td>
   24.76 -							</tr>
   24.77 -							<tr>
   24.78 -								<td>8</td>
   24.79 -								<td>Move</td>
   24.80 -							</tr>
   24.81 -							<tr>
   24.82 -								<td>7</td>
   24.83 -								<td>Move</td>
   24.84 -							</tr>
   24.85 -							<tr>
   24.86 -								<td>6</td>
   24.87 -								<td>Move</td>
   24.88 -							</tr>
   24.89 -							<tr>
   24.90 -								<td>5</td>
   24.91 -								<td>Move</td>
   24.92 -							</tr>
   24.93 -							<tr>
   24.94 -								<td>4</td>
   24.95 -								<td>Move</td>
   24.96 -							</tr>
   24.97 -							<tr>
   24.98 -								<td>3</td>
   24.99 -								<td>Move</td>
  24.100 -							</tr>
  24.101 -							<tr>
  24.102 -								<td>2</td>
  24.103 -								<td>Move</td>
  24.104 -							</tr>
  24.105 -							<tr>
  24.106 -								<td>1</td>
  24.107 -								<td>Move</td>
  24.108 -							</tr>
  24.109 -						</tbody>
  24.110 -					</table>
  24.111 -				</div>
  24.112 -			</div>
  24.113 -		</div>
  24.114 -	</div>
  24.115 -</body>
  24.116 -</html>
  24.117 \ No newline at end of file
  24.118 +        <!-- Le styles -->
  24.119 +        <link href="./css/bootstrap.css" rel="stylesheet">
  24.120 +        <link href="./css/bootstrap-responsive.css" rel="stylesheet">
  24.121 +        <link href="./css/chess.css" rel="stylesheet">
  24.122 +        <!-- Target tablets -->
  24.123 +        <link href="./css/chess-tablet-large.css" media="(min-width:560px) and (max-width:710px)" rel="stylesheet" />
  24.124 +        <link href="./css/chess-tablet-small.css" media="(min-width:460px) and (max-width:560px)" rel="stylesheet" />
  24.125 +        <!-- Target phones -->
  24.126 +        <link href="./css/chess-phone-large.css" media="(min-width:370px) and (max-width:460px)" rel="stylesheet" />
  24.127 +        <link href="./css/chess-phone-small.css" media="(max-width:370px)" rel="stylesheet" />
  24.128 +        <link href="./css/spinner.css" rel="stylesheet">
  24.129 +    </head>
  24.130 +    <body>
  24.131 +        <div class="navbar">
  24.132 +            <div class="navbar-inner">
  24.133 +                <a id="apptitle" class="brand" data-bind="css: { active: settingsActive }, click: activateSettings" href="#">JavaOne Chess</a>
  24.134 +                <ul class="nav" data-bind="foreach: boards">
  24.135 +                    <li data-bind="css: { active: active }, click: $root.activateGame">
  24.136 +                        <span data-bind="visible: myTurn" class="badge badge-warning myturn">&rarrhk;</span> 
  24.137 +                        <span data-bind="visible: justObserving" class="badge myturn">&infin;</span> 
  24.138 +                        <a href="#" data-bind="text: title"></a>
  24.139 +                    </li>
  24.140 +                </ul>
  24.141 +            </div>
  24.142 +        </div>
  24.143 +        <div data-bind="template: { name: 'render-games', data: viewGames }"></div>
  24.144 +        <div data-bind="template: { name: 'render-settings', data: settings, if : settingsActive }"></div>
  24.145 +        <div data-bind="template: { name: 'render-board', data: selectedBoard, if : selectedBoard }"></div>
  24.146 +
  24.147 +        <script type="text/html" id="render-board">
  24.148 +            <div class="container-fluid">
  24.149 +                <div class="row-fluid">
  24.150 +                    <div class="span12">
  24.151 +                        <h1><span data-bind="text: status"></span></h1>
  24.152 +                        <p style="position: relative; left: 0px; top: 0px; height: 25px">
  24.153 +                            <span data-bind="visible: blackTurn" class="badge badge-black-turn">Black's turn</span>
  24.154 +                            <span data-bind="visible: whiteTurn" class="badge badge-white-turn">White's turn</span>
  24.155 +                            <span data-bind="text: alertMessage" class="badge badge-warning badge-status"></span>
  24.156 +                        </p>
  24.157 +                        <p>
  24.158 +                        <table class="board">
  24.159 +                            <tbody>
  24.160 +                                <!-- ko foreach: rows -->
  24.161 +                                <tr>
  24.162 +                                    <td class="row-label">
  24.163 +                                        <span data-bind='text: y'></span>
  24.164 +                                    </td>
  24.165 +                                    <!-- ko foreach: columns -->
  24.166 +                                    <td data-bind="click: $parents[1].selected, css: squareColor" >
  24.167 +                                        <span data-bind='html: pieceEntity, css: { blackPiece: pieceColor() === "B", whitePiece: pieceColor() === "W" }' class="figure"></span>
  24.168 +                                    </td>
  24.169 +                                    <!-- /ko -->
  24.170 +                                </tr>
  24.171 +                                <!-- /ko -->
  24.172 +                                <tr>
  24.173 +                                    <td class="col-label"></td>
  24.174 +                                    <!-- ko foreach: columnNames -->
  24.175 +                                    <td class="row-label">
  24.176 +                                        <span data-bind='text: $data'></span>
  24.177 +                                    </td>
  24.178 +                                    <!-- /ko -->
  24.179 +                                </tr>
  24.180 +                            </tbody>
  24.181 +                        </table>
  24.182 +                        <button data-bind="click: rotateBoard" class="but-orientation">Rotate Board</button>
  24.183 +                        <button data-bind="click: $root.leave" class="but-orientation">Leave Game</button>
  24.184 +                        </p>
  24.185 +                    </div>
  24.186 +                </div>
  24.187 +                <div class="row-fluid">
  24.188 +                    <div class="span12 log-div">
  24.189 +                        <h3 class="log-h">Game Log</h3>
  24.190 +                        <div class="log">                            
  24.191 +                            <div data-bind="foreach: moves">
  24.192 +                                <span>
  24.193 +                                    <!-- ko if: whiteMove -->
  24.194 +                                    <span data-bind="text: round" class="badge"></span> 
  24.195 +                                    <!-- /ko -->
  24.196 +                                    <a href="#" data-bind="html: html, click: $parent.showPosition"></a>,&nbsp;
  24.197 +                                </span>
  24.198 +                            </div>                            
  24.199 +                        </div>
  24.200 +                    </div>
  24.201 +                </div>
  24.202 +            </div>
  24.203 +        </script>
  24.204 +
  24.205 +        <script type="text/html" id="render-settings">
  24.206 +            <div class="container-fluid">
  24.207 +                <h3>Connection Settings</h3>
  24.208 +                <p>
  24.209 +                    Status: <span data-bind="text: $root.status"></span>
  24.210 +                </p>
  24.211 +                <p>
  24.212 +                    Name:
  24.213 +                    <input type="text" data-bind="value: username, enable: $root.disconnected, valueUpdate: 'afterkeydown'" 
  24.214 +                    class="input-small" placeholder="Name"></input>
  24.215 +                    Password:
  24.216 +                    <input type="password" data-bind="value: password, enable: $root.disconnected, valueUpdate: 'afterkeydown'" 
  24.217 +                    class="input-small" placeholder="Password"></input>
  24.218 +                </p>
  24.219 +                <br/>
  24.220 +                <p>
  24.221 +                    Chess server URL: 
  24.222 +                    <input data-bind="value: url, enable: $root.disconnected" class="inpu-xlarge"></input>
  24.223 +                </p>            
  24.224 +                <p>
  24.225 +                    <button data-bind="click: $root.reconnect, enable: ($root.disconnected() && validCredentials()) ">Connect</button>
  24.226 +                    <button data-bind="click: $root.disconnect, enable: $root.connected">Disconnect</button>
  24.227 +                </p>
  24.228 +            </div>
  24.229 +            <div id="chesscube">
  24.230 +                <div id="spinner">
  24.231 +                    <div>&#9812;</div>
  24.232 +                    <div>&#9819;</div>
  24.233 +                    <div>&#9814;</div>
  24.234 +                    <div>&#9821;</div>
  24.235 +                    <div>&#9816;</div>
  24.236 +                    <div>&#9823;</div>
  24.237 +                </div>
  24.238 +            </div>
  24.239 +        </script>
  24.240 +
  24.241 +        <script type="text/html" id="render-games">
  24.242 +            <div class="container-fluid">
  24.243 +                <div data-bind="visible: $root.viewGamesActive ">
  24.244 +                    <h3>List of Games</h3>
  24.245 +                    <p>
  24.246 +                        <a href="#" data-bind="click: $root.refreshGames">Refresh</a>
  24.247 +                    </p>
  24.248 +                    <!-- ko if: anyOwnGame -->
  24.249 +                    <h5>Own Games</h5>
  24.250 +                    <div data-bind="foreach: own">
  24.251 +                        <div class="input-append">
  24.252 +                        <input type="text" data-bind="value: description" disabled></input>
  24.253 +                        <button class="btn" data-bind="click: $root.joinGame">
  24.254 +                            <span data-bind="ifnot: pendingPlayer">Show</span>
  24.255 +                            <span data-bind="if: pendingPlayer">Challenge Yourself</span>
  24.256 +                        </button>
  24.257 +                        </div>
  24.258 +                        <br/>
  24.259 +                    </div>
  24.260 +                    <!-- /ko -->
  24.261 +                    <h5>Other Games</h5>
  24.262 +                    <div data-bind="foreach: other">
  24.263 +                        <div class="input-append">
  24.264 +                        <input type="text" data-bind="value: description" disabled></input>
  24.265 +                        <!-- ko if: open -->
  24.266 +                        <button class="btn btn-success" data-bind="click: $root.joinGame">Join</button>
  24.267 +                        <!-- /ko -->
  24.268 +                        <button class="btn" data-bind="click: $root.observeGame">Observe</button>
  24.269 +                        </div>
  24.270 +                        <br/>
  24.271 +                    </div>
  24.272 +                    <h3>New game</h3>
  24.273 +                    <div class="input-append" class="select">
  24.274 +                        <select data-bind="value: selectedColor">
  24.275 +                            <option value="W">White</option>
  24.276 +                            <option value="B">Black</option>
  24.277 +                        </select>
  24.278 +                        <button data-bind="click: $root.createGame" class="btn btn-success" >Create Game!</button>
  24.279 +                    </div>
  24.280 +                </div>
  24.281 +            </div>
  24.282 +        </script>
  24.283 +        <center data-bind="visible: false">
  24.284 +            <img src="DukeHTML.png" width="320" height="200" alt="Loading...">
  24.285 +            <h3>Initializing the virtual machine...</h3>
  24.286 +        </center>
  24.287 +        <script type="text/javascript" src="bck2brwsr.js"></script>
  24.288 +        <script>
  24.289 +            var vm = bck2brwsr('${project.build.finalName}.jar');
  24.290 +            vm.loadClass('com.oracle.chess.client.htmljava.LoadMain');
  24.291 +        </script>
  24.292 +    </body>
  24.293 +</html>
    25.1 Binary file chess/src/main/webapp/pages/sounds/check.mp3 has changed
    26.1 Binary file chess/src/main/webapp/pages/sounds/checkmate.mp3 has changed
    27.1 Binary file chess/src/main/webapp/pages/sounds/move.mp3 has changed
    28.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    28.2 +++ b/chess/src/test/java/com/oracle/chess/client/htmljava/BoardModelTest.java	Tue Sep 24 22:20:24 2013 +0200
    28.3 @@ -0,0 +1,537 @@
    28.4 +/**
    28.5 + * The MIT License (MIT)
    28.6 + *
    28.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
    28.8 + *
    28.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
   28.10 + * of this software and associated documentation files (the "Software"), to deal
   28.11 + * in the Software without restriction, including without limitation the rights
   28.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   28.13 + * copies of the Software, and to permit persons to whom the Software is
   28.14 + * furnished to do so, subject to the following conditions:
   28.15 + *
   28.16 + * The above copyright notice and this permission notice shall be included in
   28.17 + * all copies or substantial portions of the Software.
   28.18 + *
   28.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   28.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   28.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
   28.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   28.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   28.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   28.25 + * THE SOFTWARE.
   28.26 + */
   28.27 +package com.oracle.chess.client.htmljava;
   28.28 +
   28.29 +import com.oracle.chess.client.htmljava.BoardModel.PieceType;
   28.30 +import java.util.Arrays;
   28.31 +import java.util.Collections;
   28.32 +import java.util.List;
   28.33 +import static org.testng.Assert.*;
   28.34 +import org.testng.annotations.Test;
   28.35 +
   28.36 +/**
   28.37 + *
   28.38 + * @author Jaroslav Tulach <jtulach@netbeans.org>
   28.39 + */
   28.40 +public class BoardModelTest {
   28.41 +    
   28.42 +    public BoardModelTest() {
   28.43 +    }
   28.44 +    
   28.45 +    @Test public void whiteRockLeftBottom() {
   28.46 +        Board b = Rules.createBoard();
   28.47 +        Row bottom = b.getRows().get(7);
   28.48 +        Square left = bottom.getColumns().get(0);
   28.49 +        assertEquals(left.getPiece(), PieceType.ROCK, "Rock is on bottom left square");
   28.50 +        assertEquals(left.getPieceColor(), Color.W, "It is white");
   28.51 +        assertEquals(left.getColor(), Color.B, "Square is black");
   28.52 +    }
   28.53 +
   28.54 +    @Test public void e2e4e7e6() {
   28.55 +        Board b = Rules.createBoard();
   28.56 +        b.setGameId("myId");
   28.57 +        setPlayer(b, Color.W);
   28.58 +        assertEquals(b.getTurn(), Color.W);
   28.59 +        
   28.60 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
   28.61 +        assertNotNull(e2);
   28.62 +        BoardModel.selected(b, e2);
   28.63 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
   28.64 +        
   28.65 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
   28.66 +        assertNotNull(e4);
   28.67 +        
   28.68 +        BoardModel.selected(b, e4);
   28.69 +        
   28.70 +        assertTrue(e4.isPending(), "e4 marked as pending move");
   28.71 +        assertNull(e2.getPiece(), "No pawn at e2");
   28.72 +
   28.73 +        // ignore all other figures than the two pawns
   28.74 +        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
   28.75 +            Collections.singletonList("Pe7"), Color.B, null
   28.76 +        );
   28.77 +
   28.78 +        assertFalse(e4.isPending(), "e4 now the move is real");
   28.79 +        assertNull(e2.getPiece(), "No pawn at e2");
   28.80 +        assertEquals(e4.getPiece(), BoardModel.PieceType.PAWN, "Pawn moved successfully");
   28.81 +        assertNull(BoardModel.findSelectedSquare(b), "No square selected");
   28.82 +        
   28.83 +        BoardModel.selected(b, e4);
   28.84 +        assertNull(BoardModel.findSelectedSquare(b), "No square selected, it is blacks turn");
   28.85 +
   28.86 +        List<Move> mvs1 = b.getMoves();
   28.87 +        assertEquals(1, mvs1.size(), "First move was made: " + mvs1);
   28.88 +        Move firstMove = mvs1.get(0);
   28.89 +        assertEquals(firstMove.getPiece(), PieceType.PAWN, "Moving with pawn");
   28.90 +        assertEquals(firstMove.getRound(), 1, "First round of moves");
   28.91 +        assertEquals(firstMove.getTurn(), Color.W, "Moved by white");
   28.92 +        assertTrue(firstMove.isWhiteMove(), "Really moved by white");
   28.93 +        
   28.94 +        assertTrue(b.isBlackTurn(), "black's turn");
   28.95 +        
   28.96 +        
   28.97 +        Square e7 = BoardModel.findSquare(b, 'E', 7);
   28.98 +        BoardModel.selected(b, e7);
   28.99 +        assertNull(BoardModel.findSelectedSquare(b), "Can't select anything when I am white player");
  28.100 +        
  28.101 +        Move blackMv = BoardModel.MoveImpl.valueOf("E7E6");
  28.102 +        BoardModel.moveUpdate(b, blackMv, 
  28.103 +            Collections.singletonList("PE4"), 
  28.104 +            Collections.singletonList("PE6"), 
  28.105 +            Color.W, null
  28.106 +        );
  28.107 +        
  28.108 +        assertNull(e7.getPiece(), "Piece has been moved");
  28.109 +        
  28.110 +        List<Move> mvs = b.getMoves();
  28.111 +        assertEquals(2, mvs.size(), "There are two moves now: " + mvs);
  28.112 +        Move secondMove = mvs.get(1);
  28.113 +        assertEquals(secondMove.getPiece(), PieceType.PAWN, "Moving with pawn");
  28.114 +        assertEquals(secondMove.getRound(), 1, "Still 1st round of moves");
  28.115 +        assertEquals(secondMove.getTurn(), Color.B, "Moved by black");
  28.116 +        assertFalse(secondMove.isWhiteMove(), "Really moved by black");
  28.117 +    }
  28.118 +
  28.119 +    @Test public void unselect() {
  28.120 +        Board b = Rules.createBoard();
  28.121 +        b.setGameId("myId");
  28.122 +        setPlayer(b, Color.W);
  28.123 +        assertEquals(b.getTurn(), Color.W);
  28.124 +        
  28.125 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.126 +        assertNotNull(e2);
  28.127 +        BoardModel.selected(b, e2);
  28.128 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  28.129 +        
  28.130 +        BoardModel.selected(b, e2);
  28.131 +        assertNull(BoardModel.findSelectedSquare(b), "E2 is unselected");
  28.132 +        
  28.133 +        for (Row row : b.getRows()) {
  28.134 +            for (Square s : row.getColumns()) {
  28.135 +                assertFalse(s.isAccessible(), "No square is accessible anymore: " + s);
  28.136 +            }
  28.137 +        }
  28.138 +    }
  28.139 +    
  28.140 +    @Test public void discaredMove() {
  28.141 +        Board b = Rules.createBoard();
  28.142 +        b.setGameId("myId");
  28.143 +        setPlayer(b, Color.W);
  28.144 +        assertEquals(b.getTurn(), Color.W);
  28.145 +        
  28.146 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.147 +        assertNotNull(e2);
  28.148 +        BoardModel.selected(b, e2);
  28.149 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
  28.150 +        
  28.151 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  28.152 +        assertNotNull(e4);
  28.153 +        
  28.154 +        BoardModel.selected(b, e4);
  28.155 +        
  28.156 +        assertTrue(e4.isPending(), "e4 marked as pending move");
  28.157 +        assertNull(e2.getPiece(), "No pawn at e2");
  28.158 +        
  28.159 +        assertEquals(b.getMoves().size(), 1, "One move recorded");
  28.160 +        assertEquals(b.getMoves().get(0), b.getPendingMove(), "Pending move is waiting");
  28.161 +
  28.162 +        // ignore all other figures than the two pawns
  28.163 +        BoardModel.moveResponse(b, "No way, can't play like this", Collections.singletonList("PE2"), 
  28.164 +            Collections.singletonList("Pe7"), Color.W, null
  28.165 +        );
  28.166 +        
  28.167 +        assertEquals(b.getAlertMessage(), "No way, can't play like this");
  28.168 +        assertNull(e4.getPiece(), "No piece on e4");
  28.169 +        assertEquals(e2.getPiece(), PieceType.PAWN, "Pawn is back");
  28.170 +        
  28.171 +        assertEquals(b.getMoves().size(), 0, "Move was discarded");
  28.172 +        assertNull(b.getPendingMove(), "No pending moves");
  28.173 +    }
  28.174 +    
  28.175 +    @Test public void cantSelectEmptySquare() {
  28.176 +        Board b = Rules.createBoard();
  28.177 +        Square e3 = BoardModel.findSquare(b, 'E', 3);
  28.178 +        assertNotNull(e3);
  28.179 +        BoardModel.selected(b, e3);
  28.180 +        assertNull(BoardModel.findSelectedSquare(b), "No square is selected");
  28.181 +    }
  28.182 +
  28.183 +    @Test public void cantTakeOwnPiece() {
  28.184 +        Board b = Rules.createBoard();
  28.185 +        setPlayer(b, Color.W);
  28.186 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  28.187 +        assertNotNull(e1);
  28.188 +        BoardModel.selected(b, e1);
  28.189 +        assertEquals(BoardModel.findSelectedSquare(b), e1, "E1 is selected");
  28.190 +        
  28.191 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.192 +        assertNotNull(e2);
  28.193 +        
  28.194 +        BoardModel.selected(b, e2);
  28.195 +        
  28.196 +        assertNotNull(e1.getPiece(), "King remains at e1");
  28.197 +        assertEquals(e2.getPiece(), BoardModel.PieceType.PAWN, "Pawn remains");
  28.198 +        assertEquals(BoardModel.findSelectedSquare(b), e2, "e2 now selected");
  28.199 +        
  28.200 +    }
  28.201 +    
  28.202 +    @Test public void knightMustMoveToF3() {
  28.203 +        Board b = Rules.createBoard();
  28.204 +        setPlayer(b, Color.W);
  28.205 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  28.206 +        BoardModel.selected(b, g1);
  28.207 +        
  28.208 +        Square f3 = BoardModel.findSquare(b, 'F', 3);
  28.209 +        assertTrue(f3.isAccessible(), "This is a field where knight can move");
  28.210 +
  28.211 +        Square g3 = BoardModel.findSquare(b, 'G', 3);
  28.212 +        assertFalse(g3.isAccessible(), "Not a place for knight");
  28.213 +
  28.214 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.215 +        assertFalse(e2.isAccessible(), "Not a place either, occupied");
  28.216 +
  28.217 +        BoardModel.selected(b, g3);
  28.218 +        
  28.219 +        assertNull(g3.getPiece(), "No figure was moved");
  28.220 +        assertTrue(g1.isSelected(), "Original square still selected");
  28.221 +        
  28.222 +        BoardModel.selected(b, f3);
  28.223 +        
  28.224 +        assertEquals(f3.getPiece(), PieceType.KNIGHT, "Moved");
  28.225 +        assertFalse(g3.isSelected(), "No longer selected");
  28.226 +    }
  28.227 +    
  28.228 +    @Test public void pawnCanTakeToSide() {
  28.229 +        Board b = Rules.createBoard();
  28.230 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.231 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  28.232 +        Square d7 = BoardModel.findSquare(b, 'D', 7);
  28.233 +        Square d5 = BoardModel.findSquare(b, 'D', 5);
  28.234 +        
  28.235 +        BoardModel.selected(b, e2);
  28.236 +        BoardModel.selected(b, e4);
  28.237 +        
  28.238 +        // ignore all other figures than the two pawns
  28.239 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  28.240 +            Collections.singletonList("PD7"), Color.B, null
  28.241 +        );
  28.242 +        
  28.243 +        setPlayer(b, Color.B);
  28.244 +        
  28.245 +        BoardModel.selected(b, d7);
  28.246 +        BoardModel.selected(b, d5);
  28.247 +        
  28.248 +        // ignore all other figures than the two pawns
  28.249 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  28.250 +            Collections.singletonList("PD5"), Color.W, null
  28.251 +        );
  28.252 +        
  28.253 +        setPlayer(b, Color.W);
  28.254 +        
  28.255 +        BoardModel.selected(b, e4);
  28.256 +        assertTrue(d5.isAccessible(), "Can take on d5");
  28.257 +        BoardModel.selected(b, d5);
  28.258 +        assertNull(e4.getPiece(), "No pawn on e4");
  28.259 +        assertEquals(d5.getPieceColor(), Color.W, "White Pawn on d5");
  28.260 +    }
  28.261 +    
  28.262 +    @Test public void pawnCanJumpOnAnother() {
  28.263 +        Board b = Rules.createBoard();
  28.264 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.265 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  28.266 +        Square d7 = BoardModel.findSquare(b, 'D', 7);
  28.267 +        Square d5 = BoardModel.findSquare(b, 'D', 5);
  28.268 +        Square e7 = BoardModel.findSquare(b, 'E', 7);
  28.269 +        Square e6 = BoardModel.findSquare(b, 'E', 6);
  28.270 +        Square e5 = BoardModel.findSquare(b, 'E', 5);
  28.271 +        
  28.272 +        BoardModel.selected(b, e2);
  28.273 +        BoardModel.selected(b, e4);
  28.274 +        
  28.275 +        // ignore all other figures than the three pawns
  28.276 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  28.277 +            Arrays.asList("PD7", "PE7"), Color.B, null
  28.278 +        );
  28.279 +        
  28.280 +        setPlayer(b, Color.B);
  28.281 +        
  28.282 +        BoardModel.selected(b, d7);
  28.283 +        BoardModel.selected(b, d5);
  28.284 +        
  28.285 +        // ignore all other figures than the three pawns
  28.286 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE4"), 
  28.287 +            Arrays.asList("PD5", "PE7"), Color.W, null
  28.288 +        );
  28.289 +        
  28.290 +        setPlayer(b, Color.W);
  28.291 +        
  28.292 +        BoardModel.selected(b, e4);
  28.293 +        BoardModel.selected(b, e5);
  28.294 +        
  28.295 +        // ignore all other figures than the three pawns
  28.296 +        BoardModel.moveResponse(b, null, Collections.singletonList("PE5"), 
  28.297 +            Arrays.asList("PD5", "PE7"), Color.B, null
  28.298 +        );
  28.299 +        
  28.300 +        setPlayer(b, Color.B);
  28.301 +        
  28.302 +        BoardModel.selected(b, e7);
  28.303 +        assertTrue(e6.isAccessible(), "Can move by one piece");
  28.304 +        assertFalse(e5.isAccessible(), "Can't move where other pawn is");
  28.305 +    }
  28.306 +    
  28.307 +    @Test public void showFirstMove() {
  28.308 +        Board b = Rules.createBoard();
  28.309 +        setPlayer(b, Color.W);
  28.310 +        Square e2 = BoardModel.findSquare(b, 'E', 2);
  28.311 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  28.312 +        Square d7 = BoardModel.findSquare(b, 'D', 7);
  28.313 +        Square d5 = BoardModel.findSquare(b, 'D', 5);
  28.314 +        
  28.315 +        BoardModel.selected(b, e2);
  28.316 +        BoardModel.selected(b, e4);
  28.317 +        
  28.318 +        // ignore all other figures than the two pawns
  28.319 +        BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"), 
  28.320 +            Collections.singletonList("PD7"), Color.B, null
  28.321 +        );
  28.322 +        
  28.323 +        Move blackMv = BoardModel.MoveImpl.valueOf("D7D5");
  28.324 +        BoardModel.moveUpdate(b, blackMv, 
  28.325 +            Collections.singletonList("PE4"), 
  28.326 +            Collections.singletonList("PD5"), 
  28.327 +            Color.W, null
  28.328 +        );
  28.329 +        
  28.330 +
  28.331 +        assertEquals(b.getMoves().size(), 2, "Two moves");
  28.332 +        BoardModel.showPosition(b, b.getMoves().get(0));
  28.333 +        
  28.334 +        assertEquals(b.getRows().size(), 8, "Still eight rows");
  28.335 +        assertEquals(b.getRows().get(0).getColumns().size(), 8, "Eight columns");
  28.336 +        
  28.337 +        assertNull(e2.getPiece(), "e2 is empty");
  28.338 +        assertEquals(e4.getPiece(), PieceType.PAWN, "e4 has pawn");
  28.339 +        assertEquals(d7.getPiece(), PieceType.PAWN, "d7 has pawn");
  28.340 +        assertNull(d5.getPiece(), "Second move is not made");
  28.341 +        assertNull(b.getTurn(), "Nobody to make a move");
  28.342 +    }
  28.343 +    
  28.344 +    @Test public void initialPositionReadFromAServer() {
  28.345 +        List<String> blacks = Arrays.asList(
  28.346 +            "Pa7",
  28.347 +            "Pb7",
  28.348 +            "Pc7",
  28.349 +            "Pd7",
  28.350 +            "Pe7",
  28.351 +            "Pf7",
  28.352 +            "Pg7",
  28.353 +            "Ph7",
  28.354 +            "Ra8",
  28.355 +            "Nb8",
  28.356 +            "Bc8",
  28.357 +            "Qd8",
  28.358 +            "Ke8",
  28.359 +            "Bf8",
  28.360 +            "Ng8",
  28.361 +            "Rh8"
  28.362 +        );
  28.363 +        List<String> whites = Arrays.asList(
  28.364 +            "Ra1",
  28.365 +            "Nb1",
  28.366 +            "Bc1",
  28.367 +            "Qd1",
  28.368 +            "Ke1",
  28.369 +            "Bf1",
  28.370 +            "Ng1",
  28.371 +            "Rh1",
  28.372 +            "Pa2",
  28.373 +            "Pb2",
  28.374 +            "Pc2",
  28.375 +            "Pd2",
  28.376 +            "Pe2",
  28.377 +            "Pf2",
  28.378 +            "Pg2",
  28.379 +            "Ph2"
  28.380 +        );
  28.381 +        
  28.382 +        Board b = Rules.createBoard();
  28.383 +        Rules.initBoard(b, whites, blacks, Color.W);
  28.384 +        
  28.385 +        Board b2 = Rules.createBoard();
  28.386 +        Rules.initBoard(b2);
  28.387 +        
  28.388 +        for (int i = 0; i < 7; i++) {
  28.389 +            for (int j = 0; j < 7; j++) {
  28.390 +                Square s = b.getRows().get(i).getColumns().get(j);
  28.391 +                Square s2 = b2.getRows().get(i).getColumns().get(j);
  28.392 +                
  28.393 +                assertEquals(s.getPiece(), s2.getPiece(), "Same piece at " + i + "/" + j);
  28.394 +                assertEquals(s.getPieceColor(), s2.getPieceColor(), "Same piece color at " + i + "/" + j);
  28.395 +            }
  28.396 +        }
  28.397 +    }
  28.398 +    
  28.399 +    @Test public void allowSmallRochade() {
  28.400 +        Board b = Rules.createBoard();
  28.401 +        setPlayer(b, Color.W);
  28.402 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  28.403 +        f1.setPiece(null);
  28.404 +        f1.setPieceColor(null);
  28.405 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  28.406 +        g1.setPiece(null);
  28.407 +        g1.setPieceColor(null);
  28.408 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  28.409 +        
  28.410 +        BoardModel.selected(b, e1);
  28.411 +        assertTrue(g1.isAccessible(), "Can do 0-0");
  28.412 +    }
  28.413 +    
  28.414 +    @Test public void allowSmallRochadeForBlack() {
  28.415 +        Board b = Rules.createBoard();
  28.416 +        setPlayer(b, Color.B);
  28.417 +        b.setTurn(Color.B);
  28.418 +        Square f8 = BoardModel.findSquare(b, 'F', 8);
  28.419 +        f8.setPiece(null);
  28.420 +        f8.setPieceColor(null);
  28.421 +        Square g8 = BoardModel.findSquare(b, 'G', 8);
  28.422 +        g8.setPiece(null);
  28.423 +        g8.setPieceColor(null);
  28.424 +        Square e8 = BoardModel.findSquare(b, 'E', 8);
  28.425 +        
  28.426 +        BoardModel.selected(b, e8);
  28.427 +        assertTrue(g8.isAccessible(), "Can do 0-0");
  28.428 +    }
  28.429 +    
  28.430 +    @Test public void disallowSmallRochadeWhenNoRock() {
  28.431 +        Board b = Rules.createBoard();
  28.432 +        setPlayer(b, Color.W);
  28.433 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  28.434 +        f1.setPiece(null);
  28.435 +        f1.setPieceColor(null);
  28.436 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  28.437 +        g1.setPiece(null);
  28.438 +        g1.setPieceColor(null);
  28.439 +        Square h1 = BoardModel.findSquare(b, 'H', 1);
  28.440 +        h1.setPiece(null);
  28.441 +        h1.setPieceColor(null);
  28.442 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  28.443 +        
  28.444 +        BoardModel.selected(b, e1);
  28.445 +        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is no rock");
  28.446 +    }
  28.447 +    
  28.448 +    @Test public void disallowSmallRochadeWhenBishop() {
  28.449 +        Board b = Rules.createBoard();
  28.450 +        setPlayer(b, Color.W);
  28.451 +        Square g1 = BoardModel.findSquare(b, 'G', 1);
  28.452 +        g1.setPiece(null);
  28.453 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  28.454 +        
  28.455 +        BoardModel.selected(b, e1);
  28.456 +        assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is bishop");
  28.457 +    }
  28.458 +
  28.459 +    @Test public void disallowSmallRochadeWhenKnight() {
  28.460 +        Board b = Rules.createBoard();
  28.461 +        setPlayer(b, Color.W);
  28.462 +        Square f1 = BoardModel.findSquare(b, 'F', 1);
  28.463 +        f1.setPiece(null);
  28.464 +        Square e1 = BoardModel.findSquare(b, 'E', 1);
  28.465 +        
  28.466 +        BoardModel.selected(b, e1);
  28.467 +        assertFalse(f1.isAccessible(), "Cannot do 0-0 when there is knight");
  28.468 +    }
  28.469 +    
  28.470 +    @Test public void allowBigRochadeForBlack() {
  28.471 +        Board b = Rules.createBoard();
  28.472 +        setPlayer(b, Color.B);
  28.473 +        b.setTurn(Color.B);
  28.474 +        Square b8 = BoardModel.findSquare(b, 'B', 8);
  28.475 +        b8.setPiece(null);
  28.476 +        b8.setPieceColor(null);
  28.477 +        Square c8 = BoardModel.findSquare(b, 'C', 8);
  28.478 +        c8.setPiece(null);
  28.479 +        c8.setPieceColor(null);
  28.480 +        Square d8 = BoardModel.findSquare(b, 'D', 8);
  28.481 +        d8.setPiece(null);
  28.482 +        d8.setPieceColor(null);
  28.483 +        Square e8 = BoardModel.findSquare(b, 'E', 8);
  28.484 +        
  28.485 +        BoardModel.selected(b, e8);
  28.486 +        assertTrue(c8.isAccessible(), "Can do 0-0-0");
  28.487 +    }
  28.488 +    
  28.489 +    @Test public void enPassant() {
  28.490 +        Board b = Rules.createBoard();
  28.491 +        setPlayer(b, Color.B);
  28.492 +        b.setTurn(Color.B);
  28.493 +
  28.494 +        Square e7 = BoardModel.findSquare(b, 'E', 7);
  28.495 +        Square e4 = BoardModel.findSquare(b, 'E', 4);
  28.496 +        movePiece(e7, e4);
  28.497 +        
  28.498 +        Move move = new Move();
  28.499 +        move.setFrom(position('D', 2));
  28.500 +        move.setTo(position('D', 4));
  28.501 +        move.setPiece(PieceType.PAWN);
  28.502 +        b.getMoves().add(move);
  28.503 +        
  28.504 +        Square d2 = BoardModel.findSquare(b, 'D', 2);
  28.505 +        Square d4 = BoardModel.findSquare(b, 'D', 4);
  28.506 +        movePiece(d2, d4);
  28.507 +        
  28.508 +        BoardModel.selected(b, e4);
  28.509 +        
  28.510 +        Square e3 = BoardModel.findSquare(b, 'E', 3);
  28.511 +        assertTrue(e3.isAccessible(), "Obviously can move to e3");
  28.512 +        
  28.513 +        Square d3 = BoardModel.findSquare(b, 'D', 3);
  28.514 +        assertTrue(d3.isAccessible(), "Can also take on d3");
  28.515 +    }
  28.516 +
  28.517 +    private void movePiece(Square from, Square to) {
  28.518 +        to.setPiece(from.getPiece());
  28.519 +        to.setPieceColor(from.getPieceColor());
  28.520 +        from.setPiece(null);
  28.521 +        from.setPieceColor(null);
  28.522 +    }
  28.523 +
  28.524 +    private Position position(char c, int i) {
  28.525 +        Position p = new Position();
  28.526 +        p.setX(c);
  28.527 +        p.setY(i);
  28.528 +        return p;
  28.529 +    }
  28.530 +    
  28.531 +    private static void setPlayer(Board b, Color c) {
  28.532 +        b.setWhitePlayer("x");
  28.533 +        b.setBlackPlayer("y");
  28.534 +        if (c == Color.B) {
  28.535 +            b.setPlayer("y");
  28.536 +        } else {
  28.537 +            b.setPlayer("x");
  28.538 +        }
  28.539 +    }
  28.540 +}