1.1 --- a/chess/pom.xml Tue Sep 24 22:28:31 2013 +0200
1.2 +++ b/chess/pom.xml Tue Sep 24 22:37:17 2013 +0200
1.3 @@ -7,8 +7,8 @@
1.4 <version>1.0-SNAPSHOT</version>
1.5 </parent>
1.6
1.7 - <groupId>com.oracle.chess</groupId>
1.8 - <artifactId>ChessHTMLJavaClient</artifactId>
1.9 + <groupId>org.apidesign.html.demo</groupId>
1.10 + <artifactId>chessdemo</artifactId>
1.11 <version>1.0-SNAPSHOT</version>
1.12 <packaging>jar</packaging>
1.13
1.14 @@ -58,7 +58,7 @@
1.15 <configuration>
1.16 <archive>
1.17 <manifest>
1.18 - <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
1.19 + <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
1.20 <addClasspath>true</addClasspath>
1.21 <classpathPrefix>lib/</classpathPrefix>
1.22 </manifest>
1.23 @@ -76,7 +76,7 @@
1.24 <value>${basedir}/src/main/webapp/</value>
1.25 </systemProperty>
1.26 </systemProperties>
1.27 - <mainClass>com.oracle.chess.client.htmljava.Main</mainClass>
1.28 + <mainClass>org.apidesign.html.demo.chess.Main</mainClass>
1.29 </configuration>
1.30 </plugin>
1.31 <plugin>
2.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/BoardModel.java Tue Sep 24 22:28:31 2013 +0200
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,451 +0,0 @@
2.4 -/**
2.5 - * The MIT License (MIT)
2.6 - *
2.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
2.8 - *
2.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
2.10 - * of this software and associated documentation files (the "Software"), to deal
2.11 - * in the Software without restriction, including without limitation the rights
2.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
2.13 - * copies of the Software, and to permit persons to whom the Software is
2.14 - * furnished to do so, subject to the following conditions:
2.15 - *
2.16 - * The above copyright notice and this permission notice shall be included in
2.17 - * all copies or substantial portions of the Software.
2.18 - *
2.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
2.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
2.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
2.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
2.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
2.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
2.25 - * THE SOFTWARE.
2.26 - */
2.27 -package com.oracle.chess.client.htmljava;
2.28 -
2.29 -import com.oracle.chess.client.htmljava.Communication.AlertType;
2.30 -import java.util.Arrays;
2.31 -import java.util.Collections;
2.32 -import java.util.List;
2.33 -import java.util.Timer;
2.34 -import java.util.TimerTask;
2.35 -import net.java.html.json.ComputedProperty;
2.36 -import net.java.html.json.Function;
2.37 -import net.java.html.json.Model;
2.38 -import net.java.html.json.ModelOperation;
2.39 -import net.java.html.json.OnPropertyChange;
2.40 -import net.java.html.json.Property;
2.41 -import net.java.html.sound.AudioClip;
2.42 -
2.43 -@Model(className="Board", properties={
2.44 - @Property(name = "player", type = String.class),
2.45 - @Property(name = "gameId", type = String.class),
2.46 - @Property(name = "whitePlayer", type = String.class),
2.47 - @Property(name = "blackPlayer", type = String.class),
2.48 - @Property(name = "alert", type = Alert.class),
2.49 - @Property(name = "alertMessage", type = String.class),
2.50 - @Property(name = "status", type = String.class),
2.51 - @Property(name = "rows", type = Row.class, array = true),
2.52 - @Property(name = "turn", type = Color.class),
2.53 - @Property(name = "moves", type = Move.class, array = true),
2.54 - @Property(name = "pendingMove", type = Move.class),
2.55 - @Property(name = "active", type = boolean.class),
2.56 -})
2.57 -public class BoardModel {
2.58 - @ComputedProperty static String title(String status, String gameId) {
2.59 - String t = status != null ? status : gameId;
2.60 - if (t != null && t.length() > 10) {
2.61 - return t.substring(0, 10);
2.62 - }
2.63 - return t;
2.64 - }
2.65 -
2.66 - @ModelOperation static void updateSummary(Board b, String summary) {
2.67 - if (summary != null) {
2.68 - b.setStatus(summary);
2.69 - }
2.70 - }
2.71 -
2.72 - @ComputedProperty static boolean myTurn(String player, String whitePlayer, String blackPlayer, Color turn) {
2.73 - if (turn != null && player != null) switch (turn) {
2.74 - case B: return player.equals(blackPlayer);
2.75 - case W: return player.equals(whitePlayer);
2.76 - }
2.77 - return false;
2.78 - }
2.79 -
2.80 - @ComputedProperty static boolean justObserving(String player) {
2.81 - return player == null;
2.82 - }
2.83 -
2.84 - private static final AudioClip MOVE = AudioClip.create("sounds/move.mp3");
2.85 - @OnPropertyChange("moves") static void playMove() {
2.86 - MOVE.play();
2.87 - }
2.88 -
2.89 - private static final AudioClip CHECK = AudioClip.create("sounds/check.mp3");
2.90 - private static final AudioClip CHECKMATE = AudioClip.create("sounds/checkmate.mp3");
2.91 - @OnPropertyChange("alert") static void warnCheckAndMate(Board b) {
2.92 - if (b.getAlert() == null) {
2.93 - return;
2.94 - }
2.95 - if (b.getAlert().getType() == AlertType.CHECK) {
2.96 - CHECK.play();
2.97 - }
2.98 - if (b.getAlert().getType() == AlertType.CHECKMATE) {
2.99 - CHECKMATE.play();
2.100 - }
2.101 - }
2.102 -
2.103 - @Function static void selected(Board b, Square data) {
2.104 - if (!b.isMyTurn()) {
2.105 - b.setAlertMessage("Not your turn!");
2.106 - return;
2.107 - }
2.108 -
2.109 - Square previoslySelected = findSelectedSquare(b);
2.110 - if (previoslySelected == null) {
2.111 - if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
2.112 - data.setSelected(true);
2.113 - Rules.computeAccessible(b, data);
2.114 - }
2.115 - } else {
2.116 - if (previoslySelected == data) {
2.117 - data.setSelected(false);
2.118 - Rules.computeAccessible(b, null);
2.119 - return;
2.120 - }
2.121 - if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
2.122 - previoslySelected.setSelected(false);
2.123 - data.setSelected(true);
2.124 - Rules.computeAccessible(b, data);
2.125 - return;
2.126 - }
2.127 - if (data.isAccessible()) {
2.128 - previoslySelected.setSelected(false);
2.129 -
2.130 - Move newMove = new Move();
2.131 - newMove.setFrom(previoslySelected.getPosition());
2.132 - newMove.setTo(data.getPosition());
2.133 - newMove.setRound(b.getMoves().size() / 2 + 1);
2.134 - newMove.setPiece(previoslySelected.getPiece());
2.135 - newMove.setTurn(previoslySelected.getPieceColor());
2.136 - newMove.setTakes(data.getPiece() != null);
2.137 - b.getMoves().add(newMove);
2.138 - b.setPendingMove(newMove);
2.139 -
2.140 - data.setPending(true);
2.141 - data.setPieceColor(previoslySelected.getPieceColor());
2.142 - data.setPiece(previoslySelected.getPiece());
2.143 - b.setTurn(null);
2.144 - previoslySelected.setPiece(null);
2.145 - previoslySelected.setPieceColor(null);
2.146 - Rules.computeAccessible(b, null);
2.147 -
2.148 - Request sm = new Request();
2.149 - sm.setMsg(MsgType.SendMove);
2.150 - sm.setGameId(b.getGameId());
2.151 - sm.setFrom(newMove.getFrom().getLocation());
2.152 - sm.setTo(newMove.getTo().getLocation());
2.153 - sm.setColor(newMove.getTurn());
2.154 - final UI ui = UIModel.findUI(b);
2.155 - if (ui != null) {
2.156 - ui.sendMsg(sm);
2.157 - }
2.158 - }
2.159 - }
2.160 - }
2.161 -
2.162 - static class NextMove extends TimerTask {
2.163 - private static final Timer T = new Timer("Animate moves");
2.164 - private final Board b;
2.165 - private final Move m;
2.166 -
2.167 - public NextMove(Board b, Move m) {
2.168 - this.b = b;
2.169 - this.m = m;
2.170 - T.schedule(this, 1000);
2.171 - }
2.172 -
2.173 -
2.174 - @Override
2.175 - public void run() {
2.176 - b.showPosition(m);
2.177 - }
2.178 - }
2.179 -
2.180 - @ModelOperation @Function static void showPosition(Board b, Move data) {
2.181 - Rules.initBoard(b);
2.182 - boolean found = false;
2.183 - for (Move m : b.getMoves()) {
2.184 - if (found) {
2.185 - b.setTurn(null);
2.186 - new NextMove(b, m);
2.187 - return;
2.188 - }
2.189 - Square from = findSquare(b, (char)m.getFrom().getX(), m.getFrom().getY());
2.190 - Square to = findSquare(b, (char)m.getTo().getX(), m.getTo().getY());
2.191 - to.setPiece(from.getPiece());
2.192 - to.setPieceColor(from.getPieceColor());
2.193 - from.setPiece(null);
2.194 - from.setPieceColor(null);
2.195 - if (m == data) {
2.196 - found = true;
2.197 - }
2.198 - }
2.199 - b.setTurn(b.getMoves().size() % 2 == 0 ? Color.W : Color.B);
2.200 - }
2.201 -
2.202 -
2.203 -
2.204 - @Function static void rotateBoard(Board b) {
2.205 - Collections.reverse(b.getRows());
2.206 - for (Row r : b.getRows()) {
2.207 - Collections.reverse(r.getColumns());
2.208 - }
2.209 - Square sq = findSelectedSquare(b);
2.210 - if (sq != null) {
2.211 - sq.setSelected(false);
2.212 - Rules.computeAccessible(b, null);
2.213 - }
2.214 - }
2.215 -
2.216 - @ComputedProperty static boolean whiteTurn(Color turn) {
2.217 - return turn == Color.W;
2.218 - }
2.219 -
2.220 - @ComputedProperty static boolean blackTurn(Color turn) {
2.221 - return turn == Color.B;
2.222 - }
2.223 -
2.224 - @ComputedProperty static List<String> columnNames(List<Row> rows) {
2.225 - boolean whiteDown = rows.isEmpty() || rows.get(0).getY() == 8;
2.226 - String[] arr = new String[8];
2.227 - for (int i = 0; i < 8; i++) {
2.228 - String s;
2.229 - if (whiteDown) {
2.230 - s = "" + (char)('A' + i);
2.231 - } else {
2.232 - s = "" + (char)('H' - i);
2.233 - }
2.234 - arr[i] = s;
2.235 - }
2.236 - return Arrays.asList(arr);
2.237 - }
2.238 -
2.239 - static Square findSquare(Board b, char column, int row) {
2.240 - for (Row r : b.getRows()) {
2.241 - for (Square square : r.getColumns()) {
2.242 - if (square.getPosition().getX() == column && square.getPosition().getY() == row) {
2.243 - return square;
2.244 - }
2.245 - }
2.246 - }
2.247 - return null;
2.248 - }
2.249 -
2.250 - private static Square findSquare(Board b, Position to) {
2.251 - return findSquare(b, (char)to.getX(), to.getY());
2.252 - }
2.253 -
2.254 - static Square findSelectedSquare(Board b) {
2.255 - for (Row row : b.getRows()) {
2.256 - for (Square square : row.getColumns()) {
2.257 - if (square.isSelected()) {
2.258 - return square;
2.259 - }
2.260 - }
2.261 - }
2.262 - return null;
2.263 - }
2.264 -
2.265 - static void moveResponse(final Board b, final String errMsg, final List<String> whites, final List<String> blacks, final Color turn,
2.266 - Alert alert
2.267 - ) {
2.268 - if (errMsg != null) {
2.269 - b.getMoves().remove(b.getPendingMove());
2.270 - b.setPendingMove(null);
2.271 - b.setAlertMessage(errMsg);
2.272 - } else {
2.273 - b.setTurn(turn);
2.274 - b.setAlertMessage(null);
2.275 - }
2.276 - b.setAlert(alert);
2.277 - Rules.initBoard(b, whites, blacks, turn);
2.278 - }
2.279 -
2.280 - static void moveUpdate(final Board b, final Move move, final List<String> whites, final List<String> blacks, final Color turn, Alert alert) {
2.281 - final Square from = BoardModel.findSquare(b, move.getFrom());
2.282 - final Square to = BoardModel.findSquare(b, move.getTo());
2.283 - move.setPiece(from.getPiece());
2.284 - move.setTurn(from.getPieceColor());
2.285 - if (to.getPiece() != null) {
2.286 - move.setTakes(true);
2.287 - }
2.288 - b.setAlert(alert);
2.289 - b.setAlertMessage(alert == null ? null : alert.getMessage());
2.290 - move.setRound(b.getMoves().size() / 2 + 1);
2.291 - b.getMoves().add(move);
2.292 - Rules.initBoard(b, whites, blacks, turn);
2.293 - }
2.294 -
2.295 - @Model(className="Row", properties = {
2.296 - @Property(name = "columns", type = Square.class, array = true)
2.297 - })
2.298 - static class RowsImpl {
2.299 - @ComputedProperty static int y(List<Square> columns) {
2.300 - return columns.isEmpty() ? 0 : columns.get(0).getY();
2.301 - }
2.302 - }
2.303 -
2.304 - enum PieceType {
2.305 - PAWN(5), ROCK(2), KNIGHT(4), BISHOP(3), QUEEN(1), KING(0);
2.306 -
2.307 - final int entityIndex;
2.308 -
2.309 - PieceType(int ei) {
2.310 - this.entityIndex = ei;
2.311 - }
2.312 -
2.313 - static PieceType fromNotation(char notation) {
2.314 - switch (notation) {
2.315 - case 'R': return ROCK;
2.316 - case 'N': return KNIGHT;
2.317 - case 'B': return BISHOP;
2.318 - case 'Q': return QUEEN;
2.319 - case 'K': return KING;
2.320 - case 'P': return PAWN;
2.321 - }
2.322 - throw new IllegalStateException("Unexpected: " + notation);
2.323 - }
2.324 -
2.325 - String computeEntity(Color color) {
2.326 - if (color == null) {
2.327 - color = Color.W;
2.328 - }
2.329 - int base;
2.330 - switch (color) {
2.331 - case W: base = 12; break;
2.332 - case B: base = 18; break;
2.333 - default:
2.334 - throw new AssertionError();
2.335 - }
2.336 - return "b" + String.valueOf(base + entityIndex) + ";";
2.337 - }
2.338 - }
2.339 -
2.340 - @Model(className="Position", properties = {
2.341 - @Property(name = "x", type = char.class),
2.342 - @Property(name = "y", type = int.class),
2.343 - })
2.344 - static class PositionImpl {
2.345 - @ComputedProperty static String location(int x, int y) {
2.346 - return "" + (char)(x - 'A' + 'a') + y;
2.347 - }
2.348 - }
2.349 -
2.350 - @Model(className="Square", properties = {
2.351 - @Property(name = "position", type = Position.class),
2.352 - @Property(name = "color", type = Color.class),
2.353 - @Property(name = "piece", type = PieceType.class),
2.354 - @Property(name = "pieceColor", type = Color.class),
2.355 - @Property(name = "selected", type = boolean.class),
2.356 - @Property(name = "accessible", type = boolean.class),
2.357 - @Property(name = "pending", type = boolean.class),
2.358 - })
2.359 - static class SquareModel {
2.360 - @ComputedProperty static String pieceEntity(
2.361 - PieceType piece, Color pieceColor
2.362 - ) {
2.363 - if (piece == null) {
2.364 - return "";
2.365 - }
2.366 - return piece.computeEntity(pieceColor);
2.367 - }
2.368 -
2.369 - @ComputedProperty static String squareColor(
2.370 - Color color, boolean selected, boolean accessible, boolean pending
2.371 - ) {
2.372 - if (selected) {
2.373 - return "selected";
2.374 - }
2.375 - if (accessible) {
2.376 - return "accessible";
2.377 - }
2.378 - if (pending) {
2.379 - return "pending";
2.380 - }
2.381 -
2.382 - if (color == null) {
2.383 - return "";
2.384 - } else {
2.385 - if (color == Color.W) {
2.386 - return "white";
2.387 - } else {
2.388 - return "black";
2.389 - }
2.390 - }
2.391 - }
2.392 -
2.393 - @ComputedProperty static char x(Position position) {
2.394 - return position == null ? 'A' : position.getX();
2.395 - }
2.396 -
2.397 - @ComputedProperty static int y(Position position) {
2.398 - return position == null ? 1 : position.getY();
2.399 - }
2.400 - }
2.401 -
2.402 - @Model(className = "Move", properties = {
2.403 - @Property(name = "round", type = int.class),
2.404 - @Property(name = "turn", type = Color.class),
2.405 - @Property(name = "piece", type = PieceType.class),
2.406 - @Property(name = "from", type = Position.class),
2.407 - @Property(name = "to", type = Position.class),
2.408 - @Property(name = "promoted", type = PieceType.class),
2.409 - @Property(name = "takes", type = boolean.class),
2.410 - @Property(name = "check", type = boolean.class),
2.411 - })
2.412 - static class MoveImpl {
2.413 - @ComputedProperty static boolean whiteMove(Color turn) {
2.414 - return turn == Color.W;
2.415 - }
2.416 -
2.417 - @ComputedProperty static String html(
2.418 - Position from, Position to, boolean takes, PieceType piece, Color turn
2.419 - ) {
2.420 - if (from == null || to == null) {
2.421 - return "";
2.422 - }
2.423 - StringBuilder sb = new StringBuilder();
2.424 - if (piece != null && piece != PieceType.PAWN) {
2.425 - sb.append(piece.computeEntity(turn));
2.426 - }
2.427 -
2.428 - sb.append(from.getLocation());
2.429 - if (takes) {
2.430 - sb.append("x");
2.431 - }
2.432 - sb.append(to.getLocation());
2.433 - return sb.toString();
2.434 - }
2.435 -
2.436 - static Move valueOf(String move) {
2.437 - move = move.toUpperCase();
2.438 - Move m = new Move();
2.439 - {
2.440 - Position p = new Position();
2.441 - p.setX(move.charAt(0));
2.442 - p.setY(move.charAt(1) - '0');
2.443 - m.setFrom(p);
2.444 - }
2.445 - {
2.446 - Position p = new Position();
2.447 - p.setX(move.charAt(2));
2.448 - p.setY(move.charAt(3) - '0');
2.449 - m.setTo(p);
2.450 - }
2.451 - return m;
2.452 - }
2.453 - }
2.454 -}
3.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Color.java Tue Sep 24 22:28:31 2013 +0200
3.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
3.3 @@ -1,32 +0,0 @@
3.4 -/**
3.5 - * The MIT License (MIT)
3.6 - *
3.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
3.8 - *
3.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
3.10 - * of this software and associated documentation files (the "Software"), to deal
3.11 - * in the Software without restriction, including without limitation the rights
3.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
3.13 - * copies of the Software, and to permit persons to whom the Software is
3.14 - * furnished to do so, subject to the following conditions:
3.15 - *
3.16 - * The above copyright notice and this permission notice shall be included in
3.17 - * all copies or substantial portions of the Software.
3.18 - *
3.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
3.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
3.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
3.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
3.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
3.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
3.25 - * THE SOFTWARE.
3.26 - */
3.27 -package com.oracle.chess.client.htmljava;
3.28 -
3.29 -/**
3.30 - *
3.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
3.32 - */
3.33 -public enum Color {
3.34 - W, B;
3.35 -}
4.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Communication.java Tue Sep 24 22:28:31 2013 +0200
4.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
4.3 @@ -1,110 +0,0 @@
4.4 -/**
4.5 - * The MIT License (MIT)
4.6 - *
4.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
4.8 - *
4.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
4.10 - * of this software and associated documentation files (the "Software"), to deal
4.11 - * in the Software without restriction, including without limitation the rights
4.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
4.13 - * copies of the Software, and to permit persons to whom the Software is
4.14 - * furnished to do so, subject to the following conditions:
4.15 - *
4.16 - * The above copyright notice and this permission notice shall be included in
4.17 - * all copies or substantial portions of the Software.
4.18 - *
4.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
4.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
4.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
4.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
4.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
4.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
4.25 - * THE SOFTWARE.
4.26 - */
4.27 -package com.oracle.chess.client.htmljava;
4.28 -
4.29 -import net.java.html.json.ComputedProperty;
4.30 -import net.java.html.json.Model;
4.31 -import net.java.html.json.Property;
4.32 -
4.33 -
4.34 -/** Communication protocols to talk to the server.
4.35 - *
4.36 - * @author Jaroslav Tulach <jtulach@netbeans.org>
4.37 - */
4.38 -final class Communication {
4.39 - @Model(className = "Request", properties = {
4.40 - @Property(name = "msg", type = MsgType.class),
4.41 - @Property(name = "username", type = String.class),
4.42 - @Property(name = "password", type = String.class),
4.43 - @Property(name = "gameId", type = String.class),
4.44 - @Property(name = "color", type = Color.class),
4.45 - @Property(name = "from", type = String.class),
4.46 - @Property(name = "to", type = String.class),
4.47 - @Property(name = "observer", type = boolean.class),
4.48 - })
4.49 - static class RequestModel {
4.50 - }
4.51 -
4.52 - @Model(className = "BoardRep", properties = {
4.53 - @Property(name = "whites", type = String.class, array = true),
4.54 - @Property(name = "blacks", type = String.class, array = true),
4.55 - })
4.56 - static class BoardRepModel {
4.57 - }
4.58 -
4.59 - @Model(className = "Response", properties = {
4.60 - @Property(name = "msg", type = String.class),
4.61 - @Property(name = "games", array = true, type = Game.class),
4.62 - @Property(name = "board", type = BoardRep.class),
4.63 - @Property(name = "turn", type = Color.class),
4.64 - @Property(name = "color", type = Color.class),
4.65 - @Property(name = "gameId", type = String.class),
4.66 - @Property(name = "error", type = Err.class),
4.67 - @Property(name = "alert", type = Alert.class),
4.68 - @Property(name = "status", type = String.class),
4.69 - @Property(name = "summary", type = String.class),
4.70 - @Property(name = "moves", type = String.class, array = true),
4.71 - @Property(name = "from", type = String.class),
4.72 - @Property(name = "to", type = String.class),
4.73 - @Property(name = "check", type = CheckResult.class),
4.74 - @Property(name = "whitePlayer", type = String.class),
4.75 - @Property(name = "blackPlayer", type = String.class),
4.76 - })
4.77 - static class ResponseModel {
4.78 - @ComputedProperty static Color nextTurn(Color turn, Alert alert) {
4.79 - if (alert == null || !alert.getType().isTerminal()) {
4.80 - return turn;
4.81 - } else {
4.82 - return null;
4.83 - }
4.84 - }
4.85 - }
4.86 -
4.87 - static enum CheckResult {
4.88 - VALID, INVALID, NOT_REGISTERED
4.89 - };
4.90 -
4.91 - @Model(className = "Err", properties = {
4.92 - @Property(name = "code", type = int.class),
4.93 - @Property(name = "message", type = String.class),
4.94 - })
4.95 - static class ErrorModel {
4.96 - }
4.97 -
4.98 - @Model(className = "Alert", properties = {
4.99 - @Property(name = "type", type = AlertType.class),
4.100 - @Property(name = "message", type = String.class),
4.101 - })
4.102 - static class AlertModel {
4.103 - }
4.104 -
4.105 - static enum AlertType {
4.106 - CHECKMATE, CHECK, DRAW;
4.107 -
4.108 - public boolean isTerminal() {
4.109 - return this == CHECKMATE || this == DRAW;
4.110 - }
4.111 - };
4.112 -
4.113 -}
5.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/GamesModel.java Tue Sep 24 22:28:31 2013 +0200
5.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
5.3 @@ -1,86 +0,0 @@
5.4 -/**
5.5 - * The MIT License (MIT)
5.6 - *
5.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
5.8 - *
5.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
5.10 - * of this software and associated documentation files (the "Software"), to deal
5.11 - * in the Software without restriction, including without limitation the rights
5.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
5.13 - * copies of the Software, and to permit persons to whom the Software is
5.14 - * furnished to do so, subject to the following conditions:
5.15 - *
5.16 - * The above copyright notice and this permission notice shall be included in
5.17 - * all copies or substantial portions of the Software.
5.18 - *
5.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
5.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
5.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
5.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
5.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
5.25 - * THE SOFTWARE.
5.26 - */
5.27 -package com.oracle.chess.client.htmljava;
5.28 -
5.29 -import java.util.List;
5.30 -import net.java.html.json.ComputedProperty;
5.31 -import net.java.html.json.Model;
5.32 -import net.java.html.json.ModelOperation;
5.33 -import net.java.html.json.Property;
5.34 -
5.35 -/**
5.36 - *
5.37 - * @author Jaroslav Tulach <jtulach@netbeans.org>
5.38 - */
5.39 -@Model(className = "Games", properties = {
5.40 - @Property(name = "own", array = true, type = Game.class),
5.41 - @Property(name = "other", array = true, type = Game.class),
5.42 - @Property(name = "selectedColor", type = String.class),
5.43 -})
5.44 -class GamesModel {
5.45 - @Model(className = "Game", properties = {
5.46 - @Property(name = "gameId", type=String.class),
5.47 - @Property(name = "summary", type=String.class),
5.48 - @Property(name = "open", type=boolean.class),
5.49 - @Property(name = "whitePlayer", type=String.class),
5.50 - @Property(name = "blackPlayer", type=String.class)
5.51 - })
5.52 - static class GameImpl {
5.53 - @ComputedProperty static String description(String gameId, String summary) {
5.54 - return summary != null ? summary : gameId;
5.55 - }
5.56 -
5.57 - @ComputedProperty static boolean pendingPlayer(String whitePlayer, String blackPlayer) {
5.58 - return whitePlayer == null || blackPlayer == null;
5.59 - }
5.60 - }
5.61 -
5.62 -
5.63 - @ComputedProperty static boolean anyOwnGame(List<Game> own) {
5.64 - return !own.isEmpty();
5.65 - }
5.66 -
5.67 - @ComputedProperty static boolean anyOtherGame(List<Game> other) {
5.68 - return !other.isEmpty();
5.69 - }
5.70 -
5.71 - @ModelOperation static void listGames(Games g, List<Game> games, String username) {
5.72 - g.getOwn().clear();
5.73 - g.getOther().clear();
5.74 - int cnt = 0;
5.75 - final int maxGames = 30;
5.76 - for (Game game : games) {
5.77 - if (
5.78 - username.equals(game.getWhitePlayer()) ||
5.79 - username.equals(game.getBlackPlayer())
5.80 - ) {
5.81 - g.getOwn().add(game);
5.82 - } else {
5.83 - if (cnt++ < maxGames) {
5.84 - g.getOther().add(game);
5.85 - }
5.86 - }
5.87 - }
5.88 - }
5.89 -}
6.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/LoadMain.java Tue Sep 24 22:28:31 2013 +0200
6.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
6.3 @@ -1,41 +0,0 @@
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 -
6.30 -public final class LoadMain {
6.31 - private LoadMain() {
6.32 - }
6.33 -
6.34 - /**
6.35 - * Called when the page is ready.
6.36 - */
6.37 - static {
6.38 - try {
6.39 - UIModel.initialize();
6.40 - } catch (Throwable ex) {
6.41 - ex.printStackTrace();
6.42 - }
6.43 - }
6.44 -}
7.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Main.java Tue Sep 24 22:28:31 2013 +0200
7.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
7.3 @@ -1,42 +0,0 @@
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 -import net.java.html.boot.BrowserBuilder;
7.30 -import org.apidesign.bck2brwsr.core.JavaScriptOnly;
7.31 -
7.32 -public final class Main {
7.33 - private Main() {
7.34 - }
7.35 -
7.36 - @JavaScriptOnly(name = "main", value = "null")
7.37 - public static void main(String... args) throws Exception {
7.38 - BrowserBuilder.newBrowser().
7.39 - loadPage("pages/index.html").
7.40 - loadClass(UIModel.class).
7.41 - invoke("initialize", args).
7.42 - showAndWait();
7.43 - System.exit(0);
7.44 - }
7.45 -}
8.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/MsgType.java Tue Sep 24 22:28:31 2013 +0200
8.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
8.3 @@ -1,40 +0,0 @@
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 -/**
8.30 - *
8.31 - * @author Jaroslav Tulach <jtulach@netbeans.org>
8.32 - */
8.33 - enum MsgType {
8.34 - CreateGame, QueryGames, SendMove, JoinGame, UpdateGame, CheckCredentials;
8.35 -
8.36 - static MsgType forResponse(String msg) {
8.37 - if (msg.endsWith("Rsp")) {
8.38 - msg = msg.substring(0, msg.length() - 3);
8.39 - }
8.40 - return MsgType.valueOf(msg);
8.41 - }
8.42 -
8.43 -}
9.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/Rules.java Tue Sep 24 22:28:31 2013 +0200
9.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
9.3 @@ -1,314 +0,0 @@
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.ArrayList;
9.30 -import java.util.List;
9.31 -
9.32 -/** Common chess rules.
9.33 - *
9.34 - * @author Jaroslav Tulach <jtulach@netbeans.org>
9.35 - */
9.36 -class Rules {
9.37 - static void computeAccessible(Board b, Square s) {
9.38 - for (Row r : b.getRows()) {
9.39 - for (Square ts : r.getColumns()) {
9.40 - ts.setAccessible(false);
9.41 - }
9.42 - }
9.43 - if (s == null) {
9.44 - return;
9.45 - }
9.46 -
9.47 - switch (s.getPiece()) {
9.48 - case BISHOP:
9.49 - moveBishop(b, s);
9.50 - break;
9.51 - case KING:
9.52 - computeAccessible(b, s, 1, 1, 1);
9.53 - computeAccessible(b, s, 1, -1, 1);
9.54 - computeAccessible(b, s, -1, -1, 1);
9.55 - computeAccessible(b, s, -1, 1, 1);
9.56 - computeAccessible(b, s, 1, 0, 1);
9.57 - computeAccessible(b, s, 0, -1, 1);
9.58 - computeAccessible(b, s, 0, 1, 1);
9.59 - computeAccessible(b, s, -1, 0, 1);
9.60 - checkRochade(b, s);
9.61 - break;
9.62 - case ROCK:
9.63 - moveRock(b, s);
9.64 - break;
9.65 - case QUEEN:
9.66 - moveRock(b, s);
9.67 - moveBishop(b, s);
9.68 - break;
9.69 - case KNIGHT:
9.70 - computeAccessible(b, s, 2, 1, 1);
9.71 - computeAccessible(b, s, 2, -1, 1);
9.72 - computeAccessible(b, s, -2, -1, 1);
9.73 - computeAccessible(b, s, -2, 1, 1);
9.74 - computeAccessible(b, s, 1, 2, 1);
9.75 - computeAccessible(b, s, -1, 2, 1);
9.76 - computeAccessible(b, s, -1, -2, 1);
9.77 - computeAccessible(b, s, 1, -2, 1);
9.78 - break;
9.79 - case PAWN:
9.80 - pawns(b, s);
9.81 - break;
9.82 - }
9.83 - }
9.84 -
9.85 - private static void moveRock(Board b, Square s) {
9.86 - computeAccessible(b, s, 1, 0, 8);
9.87 - computeAccessible(b, s, 0, -1, 8);
9.88 - computeAccessible(b, s, -1, 0, 8);
9.89 - computeAccessible(b, s, 0, 1, 8);
9.90 - }
9.91 -
9.92 - private static void moveBishop(Board b, Square s) {
9.93 - computeAccessible(b, s, 1, 1, 8);
9.94 - computeAccessible(b, s, 1, -1, 8);
9.95 - computeAccessible(b, s, -1, -1, 8);
9.96 - computeAccessible(b, s, -1, 1, 8);
9.97 - }
9.98 -
9.99 - private static void computeAccessible(
9.100 - Board b, Square s, int dx, int dy,
9.101 - int limit
9.102 - ) {
9.103 - int x = s.getX();
9.104 - int y = s.getY();
9.105 -
9.106 - while (limit-- > 0) {
9.107 - x += dx;
9.108 - y += dy;
9.109 - Square next = BoardModel.findSquare(b, (char)x, y);
9.110 - if (next == null) {
9.111 - break;
9.112 - }
9.113 - if (next.getPieceColor() == s.getPieceColor()) {
9.114 - break;
9.115 - }
9.116 - next.setAccessible(true);
9.117 - if (next.getPieceColor() != null) {
9.118 - break;
9.119 - }
9.120 - }
9.121 - }
9.122 -
9.123 - private static void pawns(Board b, Square s) {
9.124 - final boolean white = s.getPieceColor() == Color.W;
9.125 - int dy = white ? 1 : -1;
9.126 - Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
9.127 - if (step != null && step.getPiece() == null) {
9.128 - step.setAccessible(true);
9.129 - if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
9.130 - Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
9.131 - if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
9.132 - nextSTep.setAccessible(true);
9.133 - }
9.134 - }
9.135 - }
9.136 - Color opposite = white ? Color.B : Color.W;
9.137 - Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
9.138 - if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
9.139 - takeLeft.setAccessible(true);
9.140 - }
9.141 - Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
9.142 - if (takeRight != null && takeRight.getPieceColor() == opposite) {
9.143 - takeRight.setAccessible(true);
9.144 - }
9.145 - if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
9.146 - int enPassantFrom = white ? 7 : 2;
9.147 - int enPassantTo = white ? 5 : 4;
9.148 - if (!b.getMoves().isEmpty()) {
9.149 - Move last = b.getMoves().get(b.getMoves().size() - 1);
9.150 - if (
9.151 - last.getPiece() == BoardModel.PieceType.PAWN &&
9.152 - last.getFrom().getY() == enPassantFrom &&
9.153 - last.getTo().getY() == enPassantTo
9.154 - ) {
9.155 - if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
9.156 - takeLeft.setAccessible(true);
9.157 - }
9.158 - if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
9.159 - takeRight.setAccessible(true);
9.160 - }
9.161 - }
9.162 - }
9.163 - }
9.164 - }
9.165 -
9.166 - static Board createBoard() {
9.167 - Board b = new Board();
9.168 - initBoardField(b);
9.169 - initBoard(b);
9.170 - return b;
9.171 - }
9.172 -
9.173 - private static void initBoardField(Board b) {
9.174 - List<Row> addRows = new ArrayList<>(8);
9.175 - for (int i = 8; i > 0; i--) {
9.176 - Square[] arr = new Square[8];
9.177 - for (char j = 'A'; j <= 'H'; j++) {
9.178 - arr[j - 'A'] = new Square(
9.179 - new Position(j, i),
9.180 - (i + j) % 2 == 1 ? Color.W : Color.B,
9.181 - null, null, // figure
9.182 - false, false, false
9.183 - );
9.184 - }
9.185 - addRows.add(new Row(arr));
9.186 - }
9.187 - b.getRows().addAll(addRows);
9.188 - }
9.189 -
9.190 - static void initBoard(Board b) {
9.191 - initBoard(b, true);
9.192 - }
9.193 - private static void initBoard(Board b, boolean init) {
9.194 - if (init) {
9.195 - b.setTurn(Color.W);
9.196 - }
9.197 - if (b.getRows().isEmpty()) {
9.198 - for (int i = 8; i > 0; i--) {
9.199 - Row r = b.getRows().get(8 - i);
9.200 - for (char j = 'A'; j <= 'H'; j++) {
9.201 - Square s = r.getColumns().get(j - 'A');
9.202 - s.setAccessible(false);
9.203 - s.setPending(false);
9.204 - r.getColumns().set(j - 'A', s);
9.205 - initialPosition(s, init);
9.206 - }
9.207 - }
9.208 - } else {
9.209 - for (Row r : b.getRows()) {
9.210 - for (Square square : r.getColumns()) {
9.211 - square.setAccessible(false);
9.212 - square.setPending(false);
9.213 - square.setPiece(null);
9.214 - square.setPieceColor(null);
9.215 - square.setSelected(false);
9.216 - initialPosition(square, init);
9.217 - }
9.218 - }
9.219 - }
9.220 - b.setPendingMove(null);
9.221 - }
9.222 -
9.223 - private static void initialPosition(Square s, boolean init) {
9.224 - int row = s.getPosition().getY();
9.225 - char column = s.getPosition().getX();
9.226 - s.setPiece(null);
9.227 - s.setPieceColor(null);
9.228 - if (init) {
9.229 - if (row == 2) {
9.230 - s.setPiece(BoardModel.PieceType.PAWN);
9.231 - s.setPieceColor(Color.W);
9.232 - } else if (row == 7) {
9.233 - s.setPiece(BoardModel.PieceType.PAWN);
9.234 - s.setPieceColor(Color.B);
9.235 - } else if (row == 8 || row == 1) {
9.236 - s.setPieceColor(row == 1 ? Color.W : Color.B);
9.237 - BoardModel.PieceType t;
9.238 - switch (column) {
9.239 - case 'A':
9.240 - case 'H':
9.241 - t = BoardModel.PieceType.ROCK;
9.242 - break;
9.243 - case 'B':
9.244 - case 'G':
9.245 - t = BoardModel.PieceType.KNIGHT;
9.246 - break;
9.247 - case 'C':
9.248 - case 'F':
9.249 - t = BoardModel.PieceType.BISHOP;
9.250 - break;
9.251 - case 'D':
9.252 - t = BoardModel.PieceType.QUEEN;
9.253 - break;
9.254 - default:
9.255 - t = BoardModel.PieceType.KING;
9.256 - break;
9.257 - }
9.258 - s.setPiece(t);
9.259 - }
9.260 - }
9.261 - }
9.262 -
9.263 - static void initBoard(
9.264 - Board board, List<String> whites, List<String> blacks, Color turn
9.265 - ) {
9.266 - initBoard(board, false);
9.267 - for (String w : whites) {
9.268 - assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
9.269 - w = w.toUpperCase();
9.270 - char column = w.charAt(1);
9.271 - int row = (w.charAt(2) - '0');
9.272 -
9.273 - Square s = BoardModel.findSquare(board, column, row);
9.274 - s.setPieceColor(Color.W);
9.275 - s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
9.276 - }
9.277 - for (String w : blacks) {
9.278 - assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
9.279 - w = w.toUpperCase();
9.280 - char column = w.charAt(1);
9.281 - int row = (w.charAt(2) - '0');
9.282 -
9.283 - Square s = BoardModel.findSquare(board, column, row);
9.284 - s.setPieceColor(Color.B);
9.285 - s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
9.286 - }
9.287 - board.setTurn(turn);
9.288 - }
9.289 -
9.290 - private static void checkRochade(Board b, Square s) {
9.291 - if (s.getPosition().getX() == 'E') {
9.292 - int y = s.getPosition().getY();
9.293 - final Square gRow = BoardModel.findSquare(b, 'G', y);
9.294 - if (
9.295 - BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK
9.296 - &&
9.297 - BoardModel.findSquare(b, 'F', y).getPiece() == null
9.298 - &&
9.299 - gRow.getPiece() == null
9.300 - ) {
9.301 - gRow.setAccessible(true);
9.302 - }
9.303 - final Square cRow = BoardModel.findSquare(b, 'C', y);
9.304 - if (
9.305 - BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK
9.306 - &&
9.307 - BoardModel.findSquare(b, 'B', y).getPiece() == null
9.308 - &&
9.309 - BoardModel.findSquare(b, 'D', y).getPiece() == null
9.310 - &&
9.311 - cRow.getPiece() == null
9.312 - ) {
9.313 - cRow.setAccessible(true);
9.314 - }
9.315 - }
9.316 - }
9.317 -}
10.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/SettingsModel.java Tue Sep 24 22:28:31 2013 +0200
10.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
10.3 @@ -1,82 +0,0 @@
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 -import java.io.File;
10.30 -import java.io.FileInputStream;
10.31 -import java.io.FileOutputStream;
10.32 -import java.io.IOException;
10.33 -import java.util.Properties;
10.34 -import net.java.html.json.ComputedProperty;
10.35 -import net.java.html.json.Model;
10.36 -import net.java.html.json.ModelOperation;
10.37 -import net.java.html.json.Property;
10.38 -
10.39 -/**
10.40 - *
10.41 - * @author Jaroslav Tulach <jtulach@netbeans.org>
10.42 - */
10.43 -@Model(className = "Settings", properties = {
10.44 - @Property(name = "username", type = String.class),
10.45 - @Property(name = "password", type = String.class),
10.46 - @Property(name = "url", type = String.class),
10.47 -})
10.48 -class SettingsModel {
10.49 - private static final String SETTINGS = ".j1chess/html.properties";
10.50 - private static final String DEFAULT_URL = "ws://localhost:8080/chess/chessserver";
10.51 -
10.52 - @ComputedProperty static boolean validCredentials(String username, String password) {
10.53 - return username != null && password != null && !username.isEmpty() && !password.isEmpty();
10.54 - }
10.55 -
10.56 - @ModelOperation static void read(Settings s) {
10.57 - File prefs = new File(System.getProperty("user.home"), SETTINGS);
10.58 - try (FileInputStream is = new FileInputStream(prefs)) {
10.59 - Properties p = new Properties();
10.60 - p.load(is);
10.61 -
10.62 - s.setUsername(p.getProperty("username", ""));
10.63 - s.setPassword(p.getProperty("password", ""));
10.64 - s.setUrl(p.getProperty("url", DEFAULT_URL));
10.65 - } catch (Throwable ex) {
10.66 - s.setUsername("");
10.67 - s.setPassword("");
10.68 - s.setUrl(DEFAULT_URL);
10.69 - }
10.70 - }
10.71 -
10.72 - @ModelOperation static void write(Settings s, UI ui) {
10.73 - File prefs = new File(System.getProperty("user.home"), SETTINGS);
10.74 - prefs.getParentFile().mkdirs();
10.75 - try (FileOutputStream os = new FileOutputStream(prefs)) {
10.76 - Properties p = new Properties();
10.77 - p.setProperty("username", s.getUsername());
10.78 - p.setProperty("password", s.getPassword());
10.79 - p.setProperty("url", s.getUrl());
10.80 - p.store(os, "Java One Chess Preferences for HTML/Java Client");
10.81 - } catch (Throwable ex) {
10.82 - ui.setStatus("Cannot save preferences: " + ex.getMessage());
10.83 - }
10.84 - }
10.85 -}
11.1 --- a/chess/src/main/java/com/oracle/chess/client/htmljava/UIModel.java Tue Sep 24 22:28:31 2013 +0200
11.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
11.3 @@ -1,315 +0,0 @@
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 java.io.IOException;
11.30 -import java.net.URISyntaxException;
11.31 -import java.util.HashSet;
11.32 -import java.util.List;
11.33 -import java.util.Set;
11.34 -import java.util.logging.Level;
11.35 -import java.util.logging.Logger;
11.36 -import net.java.html.json.ComputedProperty;
11.37 -import net.java.html.json.Function;
11.38 -import net.java.html.json.Model;
11.39 -import net.java.html.json.ModelOperation;
11.40 -import net.java.html.json.OnPropertyChange;
11.41 -import net.java.html.json.OnReceive;
11.42 -import net.java.html.json.Property;
11.43 -
11.44 -/**
11.45 - *
11.46 - * @author Jaroslav Tulach <jtulach@netbeans.org>
11.47 - */
11.48 -@Model(className = "UI", properties = {
11.49 - @Property(name = "status", type = String.class),
11.50 - @Property(name = "selectedGameId", type = String.class),
11.51 - @Property(name = "boards", type = Board.class, array = true),
11.52 - @Property(name = "viewGames", type = Games.class),
11.53 - @Property(name = "settings", type = Settings.class),
11.54 - @Property(name = "connected", type = boolean.class),
11.55 - @Property(name = "disconnected", type = boolean.class),
11.56 -})
11.57 -public class UIModel {
11.58 - private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
11.59 -
11.60 - @ComputedProperty static boolean settingsActive(String selectedGameId) {
11.61 - return selectedGameId == null;
11.62 - }
11.63 -
11.64 - @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
11.65 - return selectedGameId == null && connected;
11.66 - }
11.67 -
11.68 - @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
11.69 - Board active = null;
11.70 - for (Board b : boards) {
11.71 - b.setActive(false);
11.72 - if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
11.73 - b.setActive(true);
11.74 - active = b;
11.75 - }
11.76 - }
11.77 - return active;
11.78 - }
11.79 -
11.80 - @Function static void activateGame(UI m, Board data) {
11.81 - m.setSelectedGameId(data.getGameId());
11.82 - }
11.83 -
11.84 - @Function static void activateSettings(UI m) {
11.85 - m.setSelectedGameId(null);
11.86 - refreshGames(m);
11.87 - }
11.88 -
11.89 - @Function static void createGame(UI u) {
11.90 - u.setStatus("Creating new game...");
11.91 - Request r = new Request();
11.92 - r.setMsg(MsgType.CreateGame);
11.93 - r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
11.94 - u.sendMsg(r);
11.95 - }
11.96 -
11.97 - @ModelOperation @Function static void refreshGames(UI u) {
11.98 - u.setStatus("Refreshing games...");
11.99 - Request r = new Request();
11.100 - r.setMsg(MsgType.QueryGames);
11.101 - u.sendMsg(r);
11.102 - }
11.103 -
11.104 - @ModelOperation static void sendMsg(UI ui, Request r) {
11.105 - final Settings sttngs = ui.getSettings();
11.106 -
11.107 - String url = sttngs.getUrl();
11.108 - r.setUsername(sttngs.getUsername());
11.109 - r.setPassword(sttngs.getPassword());
11.110 -
11.111 - LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
11.112 - ui.queryServer(url, r);
11.113 - }
11.114 -
11.115 -
11.116 - @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError")
11.117 - static void queryServer(UI ui, Response r) {
11.118 - LOG.log(Level.INFO, "Received {0}", r);
11.119 - if (r == null) {
11.120 - ui.setDisconnected(false);
11.121 - verifyLogin(ui);
11.122 - return;
11.123 - }
11.124 - SWITCH: switch (MsgType.forResponse(r.getMsg())) {
11.125 - case CheckCredentials: {
11.126 - switch (r.getCheck()) {
11.127 - case NOT_REGISTERED:
11.128 - case VALID:
11.129 - ui.setConnected(true);
11.130 - ui.refreshGames();
11.131 - ui.setStatus("Connected.");
11.132 - return;
11.133 - case INVALID:
11.134 - ui.setStatus("Password is invalid");
11.135 - break;
11.136 - }
11.137 - disconnect(ui);
11.138 - }
11.139 -
11.140 - case QueryGames:
11.141 - ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
11.142 - ui.setStatus("");
11.143 - break;
11.144 - case CreateGame: {
11.145 - ui.setStatus("Game " + r + " created");
11.146 - final Board b = Rules.createBoard();
11.147 - Rules.initBoard(
11.148 - b, r.getBoard().getWhites(),
11.149 - r.getBoard().getBlacks(),
11.150 - r.getTurn()
11.151 - );
11.152 - b.setGameId(r.getGameId());
11.153 - b.setWhitePlayer(r.getWhitePlayer());
11.154 - b.setBlackPlayer(r.getBlackPlayer());
11.155 - b.setPlayer(ui.getSettings().getUsername());
11.156 - b.updateSummary(r.getSummary());
11.157 - ui.getBoards().add(b);
11.158 - ui.setSelectedGameId(r.getGameId());
11.159 - UIModel.refreshGames(ui);
11.160 - break;
11.161 - }
11.162 - case SendMove: {
11.163 - if (r.getBoard() == null) {
11.164 - throw new NullPointerException("No board in " + r);
11.165 - }
11.166 - final Board b = findBoard(ui, r.getGameId());
11.167 - if (b == null) {
11.168 - break;
11.169 - }
11.170 - b.updateSummary(r.getSummary());
11.171 - final String errMsg = r.getError() == null ? null : r.getError().getMessage();
11.172 - final List<String> whites = r.getBoard().getWhites();
11.173 - final List<String> blacks = r.getBoard().getBlacks();
11.174 - final Color turn = r.getNextTurn();
11.175 - BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
11.176 - break;
11.177 - }
11.178 - case JoinGame: {
11.179 - Board b;
11.180 - if ((b = findBoard(ui, r.getGameId())) != null) {
11.181 - b.setWhitePlayer(r.getWhitePlayer());
11.182 - b.setBlackPlayer(r.getBlackPlayer());
11.183 - b.setPlayer(ui.getSettings().getUsername());
11.184 - b.updateSummary(r.getSummary());
11.185 - ui.setSelectedGameId(r.getGameId());
11.186 - break SWITCH;
11.187 - }
11.188 - ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
11.189 - b = Rules.createBoard();
11.190 - Rules.initBoard(
11.191 - b, r.getBoard().getWhites(),
11.192 - r.getBoard().getBlacks(),
11.193 - r.getTurn()
11.194 - );
11.195 - b.setGameId(r.getGameId());
11.196 - b.setWhitePlayer(r.getWhitePlayer());
11.197 - b.setBlackPlayer(r.getBlackPlayer());
11.198 - b.setPlayer(ui.getSettings().getUsername());
11.199 - b.updateSummary(r.getSummary());
11.200 - if (r.getColor() == Color.B) {
11.201 - BoardModel.rotateBoard(b);
11.202 - }
11.203 - if (r.getMoves() != null) {
11.204 - for (String move : r.getMoves()) {
11.205 - Move m = BoardModel.MoveImpl.valueOf(move);
11.206 - b.getMoves().add(m);
11.207 - }
11.208 - } else {
11.209 - b.getMoves().clear();
11.210 - }
11.211 - ui.setSelectedGameId(b.getGameId());
11.212 - ui.getBoards().add(b);
11.213 - break;
11.214 - }
11.215 - case UpdateGame: {
11.216 - final Board b = findBoard(ui, r.getGameId());
11.217 - if (b == null) {
11.218 - break;
11.219 - }
11.220 - b.updateSummary(r.getSummary());
11.221 - final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
11.222 - final List<String> whites = r.getBoard().getWhites();
11.223 - final List<String> blacks = r.getBoard().getBlacks();
11.224 - final Color turn = r.getNextTurn();
11.225 - BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
11.226 - }
11.227 - }
11.228 - }
11.229 -
11.230 -
11.231 - private static Board findBoard(UI ui, String gameId) {
11.232 - for (Board tmp : ui.getBoards()) {
11.233 - if (tmp.getGameId().equals(gameId)) {
11.234 - return tmp;
11.235 - }
11.236 - }
11.237 - return null;
11.238 - }
11.239 -
11.240 -
11.241 - static void wasAnError(UI ui, Exception t) {
11.242 - if (t == null) {
11.243 - ui.setConnected(false);
11.244 - ui.setDisconnected(true);
11.245 - ui.setStatus("Disconnected.");
11.246 - } else {
11.247 - ui.setStatus("Error: " + t.getLocalizedMessage());
11.248 - }
11.249 - }
11.250 -
11.251 - @Function static void joinGame(UI u, Game data) {
11.252 - Request r = new Request();
11.253 - r.setMsg(MsgType.JoinGame);
11.254 - r.setObserver(false);
11.255 - r.setGameId(data.getGameId());
11.256 - u.sendMsg(r);
11.257 - }
11.258 -
11.259 - @Function static void observeGame(UI u, Game data) {
11.260 - Request r = new Request();
11.261 - r.setMsg(MsgType.JoinGame);
11.262 - r.setObserver(true);
11.263 - r.setGameId(data.getGameId());
11.264 - u.sendMsg(r);
11.265 - }
11.266 -
11.267 - private static final Set<UI> ACTIVE = new HashSet<>();
11.268 - @OnPropertyChange("connected") static void clearGames(UI m) {
11.269 - if (m.isDisconnected()) {
11.270 - m.getBoards().clear();
11.271 - ACTIVE.remove(m);
11.272 - } else {
11.273 - ACTIVE.add(m);
11.274 - }
11.275 - }
11.276 -
11.277 - static UI findUI(Board b) {
11.278 - for (UI ui : ACTIVE) {
11.279 - if (ui.getBoards().contains(b)) {
11.280 - return ui;
11.281 - }
11.282 - }
11.283 - return null;
11.284 - }
11.285 -
11.286 - @Function static void leave(UI ui, Board data) {
11.287 - ui.getBoards().remove(data);
11.288 - ui.setSelectedGameId(null);
11.289 - }
11.290 -
11.291 - @Function static void disconnect(UI ui) {
11.292 - ui.queryServer(ui.getSettings().getUrl(), null);
11.293 - ui.setStatus("Disconnecting...");
11.294 - }
11.295 -
11.296 - private static void verifyLogin(UI ui) {
11.297 - ui.setStatus("Verifying user credentials...");
11.298 - Request r = new Request();
11.299 - r.setMsg(MsgType.CheckCredentials);
11.300 - ui.sendMsg(r);
11.301 - }
11.302 -
11.303 - @Function static void reconnect(UI ui) {
11.304 - final Settings s = ui.getSettings();
11.305 - ui.setStatus("Connecting to the server...");
11.306 - ui.queryServer(s.getUrl(), null);
11.307 - s.write(ui);
11.308 - }
11.309 -
11.310 - public static void initialize(String... args) throws URISyntaxException, IOException {
11.311 - UI ui = new UI();
11.312 - ui.getSettings().read();
11.313 - ui.setStatus("Ready.");
11.314 - ui.setDisconnected(true);
11.315 - ui.applyBindings();
11.316 - }
11.317 -
11.318 -}
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/BoardModel.java Tue Sep 24 22:37:17 2013 +0200
12.3 @@ -0,0 +1,451 @@
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 org.apidesign.html.demo.chess;
12.28 +
12.29 +import java.util.Arrays;
12.30 +import java.util.Collections;
12.31 +import java.util.List;
12.32 +import java.util.Timer;
12.33 +import java.util.TimerTask;
12.34 +import net.java.html.json.ComputedProperty;
12.35 +import net.java.html.json.Function;
12.36 +import net.java.html.json.Model;
12.37 +import net.java.html.json.ModelOperation;
12.38 +import net.java.html.json.OnPropertyChange;
12.39 +import net.java.html.json.Property;
12.40 +import net.java.html.sound.AudioClip;
12.41 +import org.apidesign.html.demo.chess.Communication.AlertType;
12.42 +
12.43 +@Model(className="Board", properties={
12.44 + @Property(name = "player", type = String.class),
12.45 + @Property(name = "gameId", type = String.class),
12.46 + @Property(name = "whitePlayer", type = String.class),
12.47 + @Property(name = "blackPlayer", type = String.class),
12.48 + @Property(name = "alert", type = Alert.class),
12.49 + @Property(name = "alertMessage", type = String.class),
12.50 + @Property(name = "status", type = String.class),
12.51 + @Property(name = "rows", type = Row.class, array = true),
12.52 + @Property(name = "turn", type = Color.class),
12.53 + @Property(name = "moves", type = Move.class, array = true),
12.54 + @Property(name = "pendingMove", type = Move.class),
12.55 + @Property(name = "active", type = boolean.class),
12.56 +})
12.57 +public class BoardModel {
12.58 + @ComputedProperty static String title(String status, String gameId) {
12.59 + String t = status != null ? status : gameId;
12.60 + if (t != null && t.length() > 10) {
12.61 + return t.substring(0, 10);
12.62 + }
12.63 + return t;
12.64 + }
12.65 +
12.66 + @ModelOperation static void updateSummary(Board b, String summary) {
12.67 + if (summary != null) {
12.68 + b.setStatus(summary);
12.69 + }
12.70 + }
12.71 +
12.72 + @ComputedProperty static boolean myTurn(String player, String whitePlayer, String blackPlayer, Color turn) {
12.73 + if (turn != null && player != null) switch (turn) {
12.74 + case B: return player.equals(blackPlayer);
12.75 + case W: return player.equals(whitePlayer);
12.76 + }
12.77 + return false;
12.78 + }
12.79 +
12.80 + @ComputedProperty static boolean justObserving(String player) {
12.81 + return player == null;
12.82 + }
12.83 +
12.84 + private static final AudioClip MOVE = AudioClip.create("sounds/move.mp3");
12.85 + @OnPropertyChange("moves") static void playMove() {
12.86 + MOVE.play();
12.87 + }
12.88 +
12.89 + private static final AudioClip CHECK = AudioClip.create("sounds/check.mp3");
12.90 + private static final AudioClip CHECKMATE = AudioClip.create("sounds/checkmate.mp3");
12.91 + @OnPropertyChange("alert") static void warnCheckAndMate(Board b) {
12.92 + if (b.getAlert() == null) {
12.93 + return;
12.94 + }
12.95 + if (b.getAlert().getType() == AlertType.CHECK) {
12.96 + CHECK.play();
12.97 + }
12.98 + if (b.getAlert().getType() == AlertType.CHECKMATE) {
12.99 + CHECKMATE.play();
12.100 + }
12.101 + }
12.102 +
12.103 + @Function static void selected(Board b, Square data) {
12.104 + if (!b.isMyTurn()) {
12.105 + b.setAlertMessage("Not your turn!");
12.106 + return;
12.107 + }
12.108 +
12.109 + Square previoslySelected = findSelectedSquare(b);
12.110 + if (previoslySelected == null) {
12.111 + if (data.getPiece() != null && data.getPieceColor() == b.getTurn()) {
12.112 + data.setSelected(true);
12.113 + Rules.computeAccessible(b, data);
12.114 + }
12.115 + } else {
12.116 + if (previoslySelected == data) {
12.117 + data.setSelected(false);
12.118 + Rules.computeAccessible(b, null);
12.119 + return;
12.120 + }
12.121 + if (data.getPiece() != null && data.getPieceColor() == previoslySelected.getPieceColor()) {
12.122 + previoslySelected.setSelected(false);
12.123 + data.setSelected(true);
12.124 + Rules.computeAccessible(b, data);
12.125 + return;
12.126 + }
12.127 + if (data.isAccessible()) {
12.128 + previoslySelected.setSelected(false);
12.129 +
12.130 + Move newMove = new Move();
12.131 + newMove.setFrom(previoslySelected.getPosition());
12.132 + newMove.setTo(data.getPosition());
12.133 + newMove.setRound(b.getMoves().size() / 2 + 1);
12.134 + newMove.setPiece(previoslySelected.getPiece());
12.135 + newMove.setTurn(previoslySelected.getPieceColor());
12.136 + newMove.setTakes(data.getPiece() != null);
12.137 + b.getMoves().add(newMove);
12.138 + b.setPendingMove(newMove);
12.139 +
12.140 + data.setPending(true);
12.141 + data.setPieceColor(previoslySelected.getPieceColor());
12.142 + data.setPiece(previoslySelected.getPiece());
12.143 + b.setTurn(null);
12.144 + previoslySelected.setPiece(null);
12.145 + previoslySelected.setPieceColor(null);
12.146 + Rules.computeAccessible(b, null);
12.147 +
12.148 + Request sm = new Request();
12.149 + sm.setMsg(MsgType.SendMove);
12.150 + sm.setGameId(b.getGameId());
12.151 + sm.setFrom(newMove.getFrom().getLocation());
12.152 + sm.setTo(newMove.getTo().getLocation());
12.153 + sm.setColor(newMove.getTurn());
12.154 + final UI ui = UIModel.findUI(b);
12.155 + if (ui != null) {
12.156 + ui.sendMsg(sm);
12.157 + }
12.158 + }
12.159 + }
12.160 + }
12.161 +
12.162 + static class NextMove extends TimerTask {
12.163 + private static final Timer T = new Timer("Animate moves");
12.164 + private final Board b;
12.165 + private final Move m;
12.166 +
12.167 + public NextMove(Board b, Move m) {
12.168 + this.b = b;
12.169 + this.m = m;
12.170 + T.schedule(this, 1000);
12.171 + }
12.172 +
12.173 +
12.174 + @Override
12.175 + public void run() {
12.176 + b.showPosition(m);
12.177 + }
12.178 + }
12.179 +
12.180 + @ModelOperation @Function static void showPosition(Board b, Move data) {
12.181 + Rules.initBoard(b);
12.182 + boolean found = false;
12.183 + for (Move m : b.getMoves()) {
12.184 + if (found) {
12.185 + b.setTurn(null);
12.186 + new NextMove(b, m);
12.187 + return;
12.188 + }
12.189 + Square from = findSquare(b, (char)m.getFrom().getX(), m.getFrom().getY());
12.190 + Square to = findSquare(b, (char)m.getTo().getX(), m.getTo().getY());
12.191 + to.setPiece(from.getPiece());
12.192 + to.setPieceColor(from.getPieceColor());
12.193 + from.setPiece(null);
12.194 + from.setPieceColor(null);
12.195 + if (m == data) {
12.196 + found = true;
12.197 + }
12.198 + }
12.199 + b.setTurn(b.getMoves().size() % 2 == 0 ? Color.W : Color.B);
12.200 + }
12.201 +
12.202 +
12.203 +
12.204 + @Function static void rotateBoard(Board b) {
12.205 + Collections.reverse(b.getRows());
12.206 + for (Row r : b.getRows()) {
12.207 + Collections.reverse(r.getColumns());
12.208 + }
12.209 + Square sq = findSelectedSquare(b);
12.210 + if (sq != null) {
12.211 + sq.setSelected(false);
12.212 + Rules.computeAccessible(b, null);
12.213 + }
12.214 + }
12.215 +
12.216 + @ComputedProperty static boolean whiteTurn(Color turn) {
12.217 + return turn == Color.W;
12.218 + }
12.219 +
12.220 + @ComputedProperty static boolean blackTurn(Color turn) {
12.221 + return turn == Color.B;
12.222 + }
12.223 +
12.224 + @ComputedProperty static List<String> columnNames(List<Row> rows) {
12.225 + boolean whiteDown = rows.isEmpty() || rows.get(0).getY() == 8;
12.226 + String[] arr = new String[8];
12.227 + for (int i = 0; i < 8; i++) {
12.228 + String s;
12.229 + if (whiteDown) {
12.230 + s = "" + (char)('A' + i);
12.231 + } else {
12.232 + s = "" + (char)('H' - i);
12.233 + }
12.234 + arr[i] = s;
12.235 + }
12.236 + return Arrays.asList(arr);
12.237 + }
12.238 +
12.239 + static Square findSquare(Board b, char column, int row) {
12.240 + for (Row r : b.getRows()) {
12.241 + for (Square square : r.getColumns()) {
12.242 + if (square.getPosition().getX() == column && square.getPosition().getY() == row) {
12.243 + return square;
12.244 + }
12.245 + }
12.246 + }
12.247 + return null;
12.248 + }
12.249 +
12.250 + private static Square findSquare(Board b, Position to) {
12.251 + return findSquare(b, (char)to.getX(), to.getY());
12.252 + }
12.253 +
12.254 + static Square findSelectedSquare(Board b) {
12.255 + for (Row row : b.getRows()) {
12.256 + for (Square square : row.getColumns()) {
12.257 + if (square.isSelected()) {
12.258 + return square;
12.259 + }
12.260 + }
12.261 + }
12.262 + return null;
12.263 + }
12.264 +
12.265 + static void moveResponse(final Board b, final String errMsg, final List<String> whites, final List<String> blacks, final Color turn,
12.266 + Alert alert
12.267 + ) {
12.268 + if (errMsg != null) {
12.269 + b.getMoves().remove(b.getPendingMove());
12.270 + b.setPendingMove(null);
12.271 + b.setAlertMessage(errMsg);
12.272 + } else {
12.273 + b.setTurn(turn);
12.274 + b.setAlertMessage(null);
12.275 + }
12.276 + b.setAlert(alert);
12.277 + Rules.initBoard(b, whites, blacks, turn);
12.278 + }
12.279 +
12.280 + static void moveUpdate(final Board b, final Move move, final List<String> whites, final List<String> blacks, final Color turn, Alert alert) {
12.281 + final Square from = BoardModel.findSquare(b, move.getFrom());
12.282 + final Square to = BoardModel.findSquare(b, move.getTo());
12.283 + move.setPiece(from.getPiece());
12.284 + move.setTurn(from.getPieceColor());
12.285 + if (to.getPiece() != null) {
12.286 + move.setTakes(true);
12.287 + }
12.288 + b.setAlert(alert);
12.289 + b.setAlertMessage(alert == null ? null : alert.getMessage());
12.290 + move.setRound(b.getMoves().size() / 2 + 1);
12.291 + b.getMoves().add(move);
12.292 + Rules.initBoard(b, whites, blacks, turn);
12.293 + }
12.294 +
12.295 + @Model(className="Row", properties = {
12.296 + @Property(name = "columns", type = Square.class, array = true)
12.297 + })
12.298 + static class RowsImpl {
12.299 + @ComputedProperty static int y(List<Square> columns) {
12.300 + return columns.isEmpty() ? 0 : columns.get(0).getY();
12.301 + }
12.302 + }
12.303 +
12.304 + enum PieceType {
12.305 + PAWN(5), ROCK(2), KNIGHT(4), BISHOP(3), QUEEN(1), KING(0);
12.306 +
12.307 + final int entityIndex;
12.308 +
12.309 + PieceType(int ei) {
12.310 + this.entityIndex = ei;
12.311 + }
12.312 +
12.313 + static PieceType fromNotation(char notation) {
12.314 + switch (notation) {
12.315 + case 'R': return ROCK;
12.316 + case 'N': return KNIGHT;
12.317 + case 'B': return BISHOP;
12.318 + case 'Q': return QUEEN;
12.319 + case 'K': return KING;
12.320 + case 'P': return PAWN;
12.321 + }
12.322 + throw new IllegalStateException("Unexpected: " + notation);
12.323 + }
12.324 +
12.325 + String computeEntity(Color color) {
12.326 + if (color == null) {
12.327 + color = Color.W;
12.328 + }
12.329 + int base;
12.330 + switch (color) {
12.331 + case W: base = 12; break;
12.332 + case B: base = 18; break;
12.333 + default:
12.334 + throw new AssertionError();
12.335 + }
12.336 + return "b" + String.valueOf(base + entityIndex) + ";";
12.337 + }
12.338 + }
12.339 +
12.340 + @Model(className="Position", properties = {
12.341 + @Property(name = "x", type = char.class),
12.342 + @Property(name = "y", type = int.class),
12.343 + })
12.344 + static class PositionImpl {
12.345 + @ComputedProperty static String location(int x, int y) {
12.346 + return "" + (char)(x - 'A' + 'a') + y;
12.347 + }
12.348 + }
12.349 +
12.350 + @Model(className="Square", properties = {
12.351 + @Property(name = "position", type = Position.class),
12.352 + @Property(name = "color", type = Color.class),
12.353 + @Property(name = "piece", type = PieceType.class),
12.354 + @Property(name = "pieceColor", type = Color.class),
12.355 + @Property(name = "selected", type = boolean.class),
12.356 + @Property(name = "accessible", type = boolean.class),
12.357 + @Property(name = "pending", type = boolean.class),
12.358 + })
12.359 + static class SquareModel {
12.360 + @ComputedProperty static String pieceEntity(
12.361 + PieceType piece, Color pieceColor
12.362 + ) {
12.363 + if (piece == null) {
12.364 + return "";
12.365 + }
12.366 + return piece.computeEntity(pieceColor);
12.367 + }
12.368 +
12.369 + @ComputedProperty static String squareColor(
12.370 + Color color, boolean selected, boolean accessible, boolean pending
12.371 + ) {
12.372 + if (selected) {
12.373 + return "selected";
12.374 + }
12.375 + if (accessible) {
12.376 + return "accessible";
12.377 + }
12.378 + if (pending) {
12.379 + return "pending";
12.380 + }
12.381 +
12.382 + if (color == null) {
12.383 + return "";
12.384 + } else {
12.385 + if (color == Color.W) {
12.386 + return "white";
12.387 + } else {
12.388 + return "black";
12.389 + }
12.390 + }
12.391 + }
12.392 +
12.393 + @ComputedProperty static char x(Position position) {
12.394 + return position == null ? 'A' : position.getX();
12.395 + }
12.396 +
12.397 + @ComputedProperty static int y(Position position) {
12.398 + return position == null ? 1 : position.getY();
12.399 + }
12.400 + }
12.401 +
12.402 + @Model(className = "Move", properties = {
12.403 + @Property(name = "round", type = int.class),
12.404 + @Property(name = "turn", type = Color.class),
12.405 + @Property(name = "piece", type = PieceType.class),
12.406 + @Property(name = "from", type = Position.class),
12.407 + @Property(name = "to", type = Position.class),
12.408 + @Property(name = "promoted", type = PieceType.class),
12.409 + @Property(name = "takes", type = boolean.class),
12.410 + @Property(name = "check", type = boolean.class),
12.411 + })
12.412 + static class MoveImpl {
12.413 + @ComputedProperty static boolean whiteMove(Color turn) {
12.414 + return turn == Color.W;
12.415 + }
12.416 +
12.417 + @ComputedProperty static String html(
12.418 + Position from, Position to, boolean takes, PieceType piece, Color turn
12.419 + ) {
12.420 + if (from == null || to == null) {
12.421 + return "";
12.422 + }
12.423 + StringBuilder sb = new StringBuilder();
12.424 + if (piece != null && piece != PieceType.PAWN) {
12.425 + sb.append(piece.computeEntity(turn));
12.426 + }
12.427 +
12.428 + sb.append(from.getLocation());
12.429 + if (takes) {
12.430 + sb.append("x");
12.431 + }
12.432 + sb.append(to.getLocation());
12.433 + return sb.toString();
12.434 + }
12.435 +
12.436 + static Move valueOf(String move) {
12.437 + move = move.toUpperCase();
12.438 + Move m = new Move();
12.439 + {
12.440 + Position p = new Position();
12.441 + p.setX(move.charAt(0));
12.442 + p.setY(move.charAt(1) - '0');
12.443 + m.setFrom(p);
12.444 + }
12.445 + {
12.446 + Position p = new Position();
12.447 + p.setX(move.charAt(2));
12.448 + p.setY(move.charAt(3) - '0');
12.449 + m.setTo(p);
12.450 + }
12.451 + return m;
12.452 + }
12.453 + }
12.454 +}
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Color.java Tue Sep 24 22:37:17 2013 +0200
13.3 @@ -0,0 +1,32 @@
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 org.apidesign.html.demo.chess;
13.28 +
13.29 +/**
13.30 + *
13.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
13.32 + */
13.33 +public enum Color {
13.34 + W, B;
13.35 +}
14.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
14.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Communication.java Tue Sep 24 22:37:17 2013 +0200
14.3 @@ -0,0 +1,110 @@
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 org.apidesign.html.demo.chess;
14.28 +
14.29 +import net.java.html.json.ComputedProperty;
14.30 +import net.java.html.json.Model;
14.31 +import net.java.html.json.Property;
14.32 +
14.33 +
14.34 +/** Communication protocols to talk to the server.
14.35 + *
14.36 + * @author Jaroslav Tulach <jtulach@netbeans.org>
14.37 + */
14.38 +final class Communication {
14.39 + @Model(className = "Request", properties = {
14.40 + @Property(name = "msg", type = MsgType.class),
14.41 + @Property(name = "username", type = String.class),
14.42 + @Property(name = "password", type = String.class),
14.43 + @Property(name = "gameId", type = String.class),
14.44 + @Property(name = "color", type = Color.class),
14.45 + @Property(name = "from", type = String.class),
14.46 + @Property(name = "to", type = String.class),
14.47 + @Property(name = "observer", type = boolean.class),
14.48 + })
14.49 + static class RequestModel {
14.50 + }
14.51 +
14.52 + @Model(className = "BoardRep", properties = {
14.53 + @Property(name = "whites", type = String.class, array = true),
14.54 + @Property(name = "blacks", type = String.class, array = true),
14.55 + })
14.56 + static class BoardRepModel {
14.57 + }
14.58 +
14.59 + @Model(className = "Response", properties = {
14.60 + @Property(name = "msg", type = String.class),
14.61 + @Property(name = "games", array = true, type = Game.class),
14.62 + @Property(name = "board", type = BoardRep.class),
14.63 + @Property(name = "turn", type = Color.class),
14.64 + @Property(name = "color", type = Color.class),
14.65 + @Property(name = "gameId", type = String.class),
14.66 + @Property(name = "error", type = Err.class),
14.67 + @Property(name = "alert", type = Alert.class),
14.68 + @Property(name = "status", type = String.class),
14.69 + @Property(name = "summary", type = String.class),
14.70 + @Property(name = "moves", type = String.class, array = true),
14.71 + @Property(name = "from", type = String.class),
14.72 + @Property(name = "to", type = String.class),
14.73 + @Property(name = "check", type = CheckResult.class),
14.74 + @Property(name = "whitePlayer", type = String.class),
14.75 + @Property(name = "blackPlayer", type = String.class),
14.76 + })
14.77 + static class ResponseModel {
14.78 + @ComputedProperty static Color nextTurn(Color turn, Alert alert) {
14.79 + if (alert == null || !alert.getType().isTerminal()) {
14.80 + return turn;
14.81 + } else {
14.82 + return null;
14.83 + }
14.84 + }
14.85 + }
14.86 +
14.87 + static enum CheckResult {
14.88 + VALID, INVALID, NOT_REGISTERED
14.89 + };
14.90 +
14.91 + @Model(className = "Err", properties = {
14.92 + @Property(name = "code", type = int.class),
14.93 + @Property(name = "message", type = String.class),
14.94 + })
14.95 + static class ErrorModel {
14.96 + }
14.97 +
14.98 + @Model(className = "Alert", properties = {
14.99 + @Property(name = "type", type = AlertType.class),
14.100 + @Property(name = "message", type = String.class),
14.101 + })
14.102 + static class AlertModel {
14.103 + }
14.104 +
14.105 + static enum AlertType {
14.106 + CHECKMATE, CHECK, DRAW;
14.107 +
14.108 + public boolean isTerminal() {
14.109 + return this == CHECKMATE || this == DRAW;
14.110 + }
14.111 + };
14.112 +
14.113 +}
15.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
15.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/GamesModel.java Tue Sep 24 22:37:17 2013 +0200
15.3 @@ -0,0 +1,86 @@
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 org.apidesign.html.demo.chess;
15.28 +
15.29 +import java.util.List;
15.30 +import net.java.html.json.ComputedProperty;
15.31 +import net.java.html.json.Model;
15.32 +import net.java.html.json.ModelOperation;
15.33 +import net.java.html.json.Property;
15.34 +
15.35 +/**
15.36 + *
15.37 + * @author Jaroslav Tulach <jtulach@netbeans.org>
15.38 + */
15.39 +@Model(className = "Games", properties = {
15.40 + @Property(name = "own", array = true, type = Game.class),
15.41 + @Property(name = "other", array = true, type = Game.class),
15.42 + @Property(name = "selectedColor", type = String.class),
15.43 +})
15.44 +class GamesModel {
15.45 + @Model(className = "Game", properties = {
15.46 + @Property(name = "gameId", type=String.class),
15.47 + @Property(name = "summary", type=String.class),
15.48 + @Property(name = "open", type=boolean.class),
15.49 + @Property(name = "whitePlayer", type=String.class),
15.50 + @Property(name = "blackPlayer", type=String.class)
15.51 + })
15.52 + static class GameImpl {
15.53 + @ComputedProperty static String description(String gameId, String summary) {
15.54 + return summary != null ? summary : gameId;
15.55 + }
15.56 +
15.57 + @ComputedProperty static boolean pendingPlayer(String whitePlayer, String blackPlayer) {
15.58 + return whitePlayer == null || blackPlayer == null;
15.59 + }
15.60 + }
15.61 +
15.62 +
15.63 + @ComputedProperty static boolean anyOwnGame(List<Game> own) {
15.64 + return !own.isEmpty();
15.65 + }
15.66 +
15.67 + @ComputedProperty static boolean anyOtherGame(List<Game> other) {
15.68 + return !other.isEmpty();
15.69 + }
15.70 +
15.71 + @ModelOperation static void listGames(Games g, List<Game> games, String username) {
15.72 + g.getOwn().clear();
15.73 + g.getOther().clear();
15.74 + int cnt = 0;
15.75 + final int maxGames = 30;
15.76 + for (Game game : games) {
15.77 + if (
15.78 + username.equals(game.getWhitePlayer()) ||
15.79 + username.equals(game.getBlackPlayer())
15.80 + ) {
15.81 + g.getOwn().add(game);
15.82 + } else {
15.83 + if (cnt++ < maxGames) {
15.84 + g.getOther().add(game);
15.85 + }
15.86 + }
15.87 + }
15.88 + }
15.89 +}
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/LoadMain.java Tue Sep 24 22:37:17 2013 +0200
16.3 @@ -0,0 +1,41 @@
16.4 +/**
16.5 + * The MIT License (MIT)
16.6 + *
16.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
16.8 + *
16.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
16.10 + * of this software and associated documentation files (the "Software"), to deal
16.11 + * in the Software without restriction, including without limitation the rights
16.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
16.13 + * copies of the Software, and to permit persons to whom the Software is
16.14 + * furnished to do so, subject to the following conditions:
16.15 + *
16.16 + * The above copyright notice and this permission notice shall be included in
16.17 + * all copies or substantial portions of the Software.
16.18 + *
16.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
16.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16.25 + * THE SOFTWARE.
16.26 + */
16.27 +package org.apidesign.html.demo.chess;
16.28 +
16.29 +
16.30 +public final class LoadMain {
16.31 + private LoadMain() {
16.32 + }
16.33 +
16.34 + /**
16.35 + * Called when the page is ready.
16.36 + */
16.37 + static {
16.38 + try {
16.39 + UIModel.initialize();
16.40 + } catch (Throwable ex) {
16.41 + ex.printStackTrace();
16.42 + }
16.43 + }
16.44 +}
17.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
17.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Main.java Tue Sep 24 22:37:17 2013 +0200
17.3 @@ -0,0 +1,42 @@
17.4 +/**
17.5 + * The MIT License (MIT)
17.6 + *
17.7 + * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
17.8 + *
17.9 + * Permission is hereby granted, free of charge, to any person obtaining a copy
17.10 + * of this software and associated documentation files (the "Software"), to deal
17.11 + * in the Software without restriction, including without limitation the rights
17.12 + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17.13 + * copies of the Software, and to permit persons to whom the Software is
17.14 + * furnished to do so, subject to the following conditions:
17.15 + *
17.16 + * The above copyright notice and this permission notice shall be included in
17.17 + * all copies or substantial portions of the Software.
17.18 + *
17.19 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17.20 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17.21 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17.22 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17.23 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
17.24 + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
17.25 + * THE SOFTWARE.
17.26 + */
17.27 +package org.apidesign.html.demo.chess;
17.28 +
17.29 +import net.java.html.boot.BrowserBuilder;
17.30 +import org.apidesign.bck2brwsr.core.JavaScriptOnly;
17.31 +
17.32 +public final class Main {
17.33 + private Main() {
17.34 + }
17.35 +
17.36 + @JavaScriptOnly(name = "main", value = "null")
17.37 + public static void main(String... args) throws Exception {
17.38 + BrowserBuilder.newBrowser().
17.39 + loadPage("pages/index.html").
17.40 + loadClass(UIModel.class).
17.41 + invoke("initialize", args).
17.42 + showAndWait();
17.43 + System.exit(0);
17.44 + }
17.45 +}
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/MsgType.java Tue Sep 24 22:37:17 2013 +0200
18.3 @@ -0,0 +1,40 @@
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 +package org.apidesign.html.demo.chess;
18.28 +
18.29 +/**
18.30 + *
18.31 + * @author Jaroslav Tulach <jtulach@netbeans.org>
18.32 + */
18.33 + enum MsgType {
18.34 + CreateGame, QueryGames, SendMove, JoinGame, UpdateGame, CheckCredentials;
18.35 +
18.36 + static MsgType forResponse(String msg) {
18.37 + if (msg.endsWith("Rsp")) {
18.38 + msg = msg.substring(0, msg.length() - 3);
18.39 + }
18.40 + return MsgType.valueOf(msg);
18.41 + }
18.42 +
18.43 +}
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/Rules.java Tue Sep 24 22:37:17 2013 +0200
19.3 @@ -0,0 +1,314 @@
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 +package org.apidesign.html.demo.chess;
19.28 +
19.29 +import java.util.ArrayList;
19.30 +import java.util.List;
19.31 +
19.32 +/** Common chess rules.
19.33 + *
19.34 + * @author Jaroslav Tulach <jtulach@netbeans.org>
19.35 + */
19.36 +class Rules {
19.37 + static void computeAccessible(Board b, Square s) {
19.38 + for (Row r : b.getRows()) {
19.39 + for (Square ts : r.getColumns()) {
19.40 + ts.setAccessible(false);
19.41 + }
19.42 + }
19.43 + if (s == null) {
19.44 + return;
19.45 + }
19.46 +
19.47 + switch (s.getPiece()) {
19.48 + case BISHOP:
19.49 + moveBishop(b, s);
19.50 + break;
19.51 + case KING:
19.52 + computeAccessible(b, s, 1, 1, 1);
19.53 + computeAccessible(b, s, 1, -1, 1);
19.54 + computeAccessible(b, s, -1, -1, 1);
19.55 + computeAccessible(b, s, -1, 1, 1);
19.56 + computeAccessible(b, s, 1, 0, 1);
19.57 + computeAccessible(b, s, 0, -1, 1);
19.58 + computeAccessible(b, s, 0, 1, 1);
19.59 + computeAccessible(b, s, -1, 0, 1);
19.60 + checkRochade(b, s);
19.61 + break;
19.62 + case ROCK:
19.63 + moveRock(b, s);
19.64 + break;
19.65 + case QUEEN:
19.66 + moveRock(b, s);
19.67 + moveBishop(b, s);
19.68 + break;
19.69 + case KNIGHT:
19.70 + computeAccessible(b, s, 2, 1, 1);
19.71 + computeAccessible(b, s, 2, -1, 1);
19.72 + computeAccessible(b, s, -2, -1, 1);
19.73 + computeAccessible(b, s, -2, 1, 1);
19.74 + computeAccessible(b, s, 1, 2, 1);
19.75 + computeAccessible(b, s, -1, 2, 1);
19.76 + computeAccessible(b, s, -1, -2, 1);
19.77 + computeAccessible(b, s, 1, -2, 1);
19.78 + break;
19.79 + case PAWN:
19.80 + pawns(b, s);
19.81 + break;
19.82 + }
19.83 + }
19.84 +
19.85 + private static void moveRock(Board b, Square s) {
19.86 + computeAccessible(b, s, 1, 0, 8);
19.87 + computeAccessible(b, s, 0, -1, 8);
19.88 + computeAccessible(b, s, -1, 0, 8);
19.89 + computeAccessible(b, s, 0, 1, 8);
19.90 + }
19.91 +
19.92 + private static void moveBishop(Board b, Square s) {
19.93 + computeAccessible(b, s, 1, 1, 8);
19.94 + computeAccessible(b, s, 1, -1, 8);
19.95 + computeAccessible(b, s, -1, -1, 8);
19.96 + computeAccessible(b, s, -1, 1, 8);
19.97 + }
19.98 +
19.99 + private static void computeAccessible(
19.100 + Board b, Square s, int dx, int dy,
19.101 + int limit
19.102 + ) {
19.103 + int x = s.getX();
19.104 + int y = s.getY();
19.105 +
19.106 + while (limit-- > 0) {
19.107 + x += dx;
19.108 + y += dy;
19.109 + Square next = BoardModel.findSquare(b, (char)x, y);
19.110 + if (next == null) {
19.111 + break;
19.112 + }
19.113 + if (next.getPieceColor() == s.getPieceColor()) {
19.114 + break;
19.115 + }
19.116 + next.setAccessible(true);
19.117 + if (next.getPieceColor() != null) {
19.118 + break;
19.119 + }
19.120 + }
19.121 + }
19.122 +
19.123 + private static void pawns(Board b, Square s) {
19.124 + final boolean white = s.getPieceColor() == Color.W;
19.125 + int dy = white ? 1 : -1;
19.126 + Square step = BoardModel.findSquare(b, (char)s.getX(), s.getY() + dy);
19.127 + if (step != null && step.getPiece() == null) {
19.128 + step.setAccessible(true);
19.129 + if ((s.getY() == 2 && white) || (s.getY() == 7 && !white)) {
19.130 + Square nextSTep = BoardModel.findSquare(b, (char)s.getX(), step.getY() + dy);
19.131 + if (nextSTep != null && step.getPiece() == null && nextSTep.getPiece() == null) {
19.132 + nextSTep.setAccessible(true);
19.133 + }
19.134 + }
19.135 + }
19.136 + Color opposite = white ? Color.B : Color.W;
19.137 + Square takeLeft = BoardModel.findSquare(b, (char)(s.getX() - 1), s.getY() + dy);
19.138 + if (takeLeft != null && takeLeft.getPieceColor() == opposite) {
19.139 + takeLeft.setAccessible(true);
19.140 + }
19.141 + Square takeRight = BoardModel.findSquare(b, (char)(s.getX() + 1), s.getY() + dy);
19.142 + if (takeRight != null && takeRight.getPieceColor() == opposite) {
19.143 + takeRight.setAccessible(true);
19.144 + }
19.145 + if ((white && s.getY() == 5) || (!white && s.getY() == 4)) {
19.146 + int enPassantFrom = white ? 7 : 2;
19.147 + int enPassantTo = white ? 5 : 4;
19.148 + if (!b.getMoves().isEmpty()) {
19.149 + Move last = b.getMoves().get(b.getMoves().size() - 1);
19.150 + if (
19.151 + last.getPiece() == BoardModel.PieceType.PAWN &&
19.152 + last.getFrom().getY() == enPassantFrom &&
19.153 + last.getTo().getY() == enPassantTo
19.154 + ) {
19.155 + if (takeLeft != null && last.getFrom().getX() == s.getX() - 1) {
19.156 + takeLeft.setAccessible(true);
19.157 + }
19.158 + if (takeRight != null && last.getFrom().getX() == s.getX() + 1) {
19.159 + takeRight.setAccessible(true);
19.160 + }
19.161 + }
19.162 + }
19.163 + }
19.164 + }
19.165 +
19.166 + static Board createBoard() {
19.167 + Board b = new Board();
19.168 + initBoardField(b);
19.169 + initBoard(b);
19.170 + return b;
19.171 + }
19.172 +
19.173 + private static void initBoardField(Board b) {
19.174 + List<Row> addRows = new ArrayList<>(8);
19.175 + for (int i = 8; i > 0; i--) {
19.176 + Square[] arr = new Square[8];
19.177 + for (char j = 'A'; j <= 'H'; j++) {
19.178 + arr[j - 'A'] = new Square(
19.179 + new Position(j, i),
19.180 + (i + j) % 2 == 1 ? Color.W : Color.B,
19.181 + null, null, // figure
19.182 + false, false, false
19.183 + );
19.184 + }
19.185 + addRows.add(new Row(arr));
19.186 + }
19.187 + b.getRows().addAll(addRows);
19.188 + }
19.189 +
19.190 + static void initBoard(Board b) {
19.191 + initBoard(b, true);
19.192 + }
19.193 + private static void initBoard(Board b, boolean init) {
19.194 + if (init) {
19.195 + b.setTurn(Color.W);
19.196 + }
19.197 + if (b.getRows().isEmpty()) {
19.198 + for (int i = 8; i > 0; i--) {
19.199 + Row r = b.getRows().get(8 - i);
19.200 + for (char j = 'A'; j <= 'H'; j++) {
19.201 + Square s = r.getColumns().get(j - 'A');
19.202 + s.setAccessible(false);
19.203 + s.setPending(false);
19.204 + r.getColumns().set(j - 'A', s);
19.205 + initialPosition(s, init);
19.206 + }
19.207 + }
19.208 + } else {
19.209 + for (Row r : b.getRows()) {
19.210 + for (Square square : r.getColumns()) {
19.211 + square.setAccessible(false);
19.212 + square.setPending(false);
19.213 + square.setPiece(null);
19.214 + square.setPieceColor(null);
19.215 + square.setSelected(false);
19.216 + initialPosition(square, init);
19.217 + }
19.218 + }
19.219 + }
19.220 + b.setPendingMove(null);
19.221 + }
19.222 +
19.223 + private static void initialPosition(Square s, boolean init) {
19.224 + int row = s.getPosition().getY();
19.225 + char column = s.getPosition().getX();
19.226 + s.setPiece(null);
19.227 + s.setPieceColor(null);
19.228 + if (init) {
19.229 + if (row == 2) {
19.230 + s.setPiece(BoardModel.PieceType.PAWN);
19.231 + s.setPieceColor(Color.W);
19.232 + } else if (row == 7) {
19.233 + s.setPiece(BoardModel.PieceType.PAWN);
19.234 + s.setPieceColor(Color.B);
19.235 + } else if (row == 8 || row == 1) {
19.236 + s.setPieceColor(row == 1 ? Color.W : Color.B);
19.237 + BoardModel.PieceType t;
19.238 + switch (column) {
19.239 + case 'A':
19.240 + case 'H':
19.241 + t = BoardModel.PieceType.ROCK;
19.242 + break;
19.243 + case 'B':
19.244 + case 'G':
19.245 + t = BoardModel.PieceType.KNIGHT;
19.246 + break;
19.247 + case 'C':
19.248 + case 'F':
19.249 + t = BoardModel.PieceType.BISHOP;
19.250 + break;
19.251 + case 'D':
19.252 + t = BoardModel.PieceType.QUEEN;
19.253 + break;
19.254 + default:
19.255 + t = BoardModel.PieceType.KING;
19.256 + break;
19.257 + }
19.258 + s.setPiece(t);
19.259 + }
19.260 + }
19.261 + }
19.262 +
19.263 + static void initBoard(
19.264 + Board board, List<String> whites, List<String> blacks, Color turn
19.265 + ) {
19.266 + initBoard(board, false);
19.267 + for (String w : whites) {
19.268 + assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
19.269 + w = w.toUpperCase();
19.270 + char column = w.charAt(1);
19.271 + int row = (w.charAt(2) - '0');
19.272 +
19.273 + Square s = BoardModel.findSquare(board, column, row);
19.274 + s.setPieceColor(Color.W);
19.275 + s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
19.276 + }
19.277 + for (String w : blacks) {
19.278 + assert w.length() == 3 : "Expecting three letter string: '" + w + "'";
19.279 + w = w.toUpperCase();
19.280 + char column = w.charAt(1);
19.281 + int row = (w.charAt(2) - '0');
19.282 +
19.283 + Square s = BoardModel.findSquare(board, column, row);
19.284 + s.setPieceColor(Color.B);
19.285 + s.setPiece(BoardModel.PieceType.fromNotation(w.charAt(0)));
19.286 + }
19.287 + board.setTurn(turn);
19.288 + }
19.289 +
19.290 + private static void checkRochade(Board b, Square s) {
19.291 + if (s.getPosition().getX() == 'E') {
19.292 + int y = s.getPosition().getY();
19.293 + final Square gRow = BoardModel.findSquare(b, 'G', y);
19.294 + if (
19.295 + BoardModel.findSquare(b, 'H', y).getPiece() == BoardModel.PieceType.ROCK
19.296 + &&
19.297 + BoardModel.findSquare(b, 'F', y).getPiece() == null
19.298 + &&
19.299 + gRow.getPiece() == null
19.300 + ) {
19.301 + gRow.setAccessible(true);
19.302 + }
19.303 + final Square cRow = BoardModel.findSquare(b, 'C', y);
19.304 + if (
19.305 + BoardModel.findSquare(b, 'A', y).getPiece() == BoardModel.PieceType.ROCK
19.306 + &&
19.307 + BoardModel.findSquare(b, 'B', y).getPiece() == null
19.308 + &&
19.309 + BoardModel.findSquare(b, 'D', y).getPiece() == null
19.310 + &&
19.311 + cRow.getPiece() == null
19.312 + ) {
19.313 + cRow.setAccessible(true);
19.314 + }
19.315 + }
19.316 + }
19.317 +}
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/SettingsModel.java Tue Sep 24 22:37:17 2013 +0200
20.3 @@ -0,0 +1,82 @@
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 +package org.apidesign.html.demo.chess;
20.28 +
20.29 +import java.io.File;
20.30 +import java.io.FileInputStream;
20.31 +import java.io.FileOutputStream;
20.32 +import java.io.IOException;
20.33 +import java.util.Properties;
20.34 +import net.java.html.json.ComputedProperty;
20.35 +import net.java.html.json.Model;
20.36 +import net.java.html.json.ModelOperation;
20.37 +import net.java.html.json.Property;
20.38 +
20.39 +/**
20.40 + *
20.41 + * @author Jaroslav Tulach <jtulach@netbeans.org>
20.42 + */
20.43 +@Model(className = "Settings", properties = {
20.44 + @Property(name = "username", type = String.class),
20.45 + @Property(name = "password", type = String.class),
20.46 + @Property(name = "url", type = String.class),
20.47 +})
20.48 +class SettingsModel {
20.49 + private static final String SETTINGS = ".j1chess/html.properties";
20.50 + private static final String DEFAULT_URL = "ws://localhost:8080/chess/chessserver";
20.51 +
20.52 + @ComputedProperty static boolean validCredentials(String username, String password) {
20.53 + return username != null && password != null && !username.isEmpty() && !password.isEmpty();
20.54 + }
20.55 +
20.56 + @ModelOperation static void read(Settings s) {
20.57 + File prefs = new File(System.getProperty("user.home"), SETTINGS);
20.58 + try (FileInputStream is = new FileInputStream(prefs)) {
20.59 + Properties p = new Properties();
20.60 + p.load(is);
20.61 +
20.62 + s.setUsername(p.getProperty("username", ""));
20.63 + s.setPassword(p.getProperty("password", ""));
20.64 + s.setUrl(p.getProperty("url", DEFAULT_URL));
20.65 + } catch (Throwable ex) {
20.66 + s.setUsername("");
20.67 + s.setPassword("");
20.68 + s.setUrl(DEFAULT_URL);
20.69 + }
20.70 + }
20.71 +
20.72 + @ModelOperation static void write(Settings s, UI ui) {
20.73 + File prefs = new File(System.getProperty("user.home"), SETTINGS);
20.74 + prefs.getParentFile().mkdirs();
20.75 + try (FileOutputStream os = new FileOutputStream(prefs)) {
20.76 + Properties p = new Properties();
20.77 + p.setProperty("username", s.getUsername());
20.78 + p.setProperty("password", s.getPassword());
20.79 + p.setProperty("url", s.getUrl());
20.80 + p.store(os, "Java One Chess Preferences for HTML/Java Client");
20.81 + } catch (Throwable ex) {
20.82 + ui.setStatus("Cannot save preferences: " + ex.getMessage());
20.83 + }
20.84 + }
20.85 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/chess/src/main/java/org/apidesign/html/demo/chess/UIModel.java Tue Sep 24 22:37:17 2013 +0200
21.3 @@ -0,0 +1,315 @@
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 +package org.apidesign.html.demo.chess;
21.28 +
21.29 +import java.io.IOException;
21.30 +import java.net.URISyntaxException;
21.31 +import java.util.HashSet;
21.32 +import java.util.List;
21.33 +import java.util.Set;
21.34 +import java.util.logging.Level;
21.35 +import java.util.logging.Logger;
21.36 +import net.java.html.json.ComputedProperty;
21.37 +import net.java.html.json.Function;
21.38 +import net.java.html.json.Model;
21.39 +import net.java.html.json.ModelOperation;
21.40 +import net.java.html.json.OnPropertyChange;
21.41 +import net.java.html.json.OnReceive;
21.42 +import net.java.html.json.Property;
21.43 +
21.44 +/**
21.45 + *
21.46 + * @author Jaroslav Tulach <jtulach@netbeans.org>
21.47 + */
21.48 +@Model(className = "UI", properties = {
21.49 + @Property(name = "status", type = String.class),
21.50 + @Property(name = "selectedGameId", type = String.class),
21.51 + @Property(name = "boards", type = Board.class, array = true),
21.52 + @Property(name = "viewGames", type = Games.class),
21.53 + @Property(name = "settings", type = Settings.class),
21.54 + @Property(name = "connected", type = boolean.class),
21.55 + @Property(name = "disconnected", type = boolean.class),
21.56 +})
21.57 +public class UIModel {
21.58 + private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
21.59 +
21.60 + @ComputedProperty static boolean settingsActive(String selectedGameId) {
21.61 + return selectedGameId == null;
21.62 + }
21.63 +
21.64 + @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
21.65 + return selectedGameId == null && connected;
21.66 + }
21.67 +
21.68 + @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
21.69 + Board active = null;
21.70 + for (Board b : boards) {
21.71 + b.setActive(false);
21.72 + if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
21.73 + b.setActive(true);
21.74 + active = b;
21.75 + }
21.76 + }
21.77 + return active;
21.78 + }
21.79 +
21.80 + @Function static void activateGame(UI m, Board data) {
21.81 + m.setSelectedGameId(data.getGameId());
21.82 + }
21.83 +
21.84 + @Function static void activateSettings(UI m) {
21.85 + m.setSelectedGameId(null);
21.86 + refreshGames(m);
21.87 + }
21.88 +
21.89 + @Function static void createGame(UI u) {
21.90 + u.setStatus("Creating new game...");
21.91 + Request r = new Request();
21.92 + r.setMsg(MsgType.CreateGame);
21.93 + r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
21.94 + u.sendMsg(r);
21.95 + }
21.96 +
21.97 + @ModelOperation @Function static void refreshGames(UI u) {
21.98 + u.setStatus("Refreshing games...");
21.99 + Request r = new Request();
21.100 + r.setMsg(MsgType.QueryGames);
21.101 + u.sendMsg(r);
21.102 + }
21.103 +
21.104 + @ModelOperation static void sendMsg(UI ui, Request r) {
21.105 + final Settings sttngs = ui.getSettings();
21.106 +
21.107 + String url = sttngs.getUrl();
21.108 + r.setUsername(sttngs.getUsername());
21.109 + r.setPassword(sttngs.getPassword());
21.110 +
21.111 + LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
21.112 + ui.queryServer(url, r);
21.113 + }
21.114 +
21.115 +
21.116 + @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError")
21.117 + static void queryServer(UI ui, Response r) {
21.118 + LOG.log(Level.INFO, "Received {0}", r);
21.119 + if (r == null) {
21.120 + ui.setDisconnected(false);
21.121 + verifyLogin(ui);
21.122 + return;
21.123 + }
21.124 + SWITCH: switch (MsgType.forResponse(r.getMsg())) {
21.125 + case CheckCredentials: {
21.126 + switch (r.getCheck()) {
21.127 + case NOT_REGISTERED:
21.128 + case VALID:
21.129 + ui.setConnected(true);
21.130 + ui.refreshGames();
21.131 + ui.setStatus("Connected.");
21.132 + return;
21.133 + case INVALID:
21.134 + ui.setStatus("Password is invalid");
21.135 + break;
21.136 + }
21.137 + disconnect(ui);
21.138 + }
21.139 +
21.140 + case QueryGames:
21.141 + ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
21.142 + ui.setStatus("");
21.143 + break;
21.144 + case CreateGame: {
21.145 + ui.setStatus("Game " + r + " created");
21.146 + final Board b = Rules.createBoard();
21.147 + Rules.initBoard(
21.148 + b, r.getBoard().getWhites(),
21.149 + r.getBoard().getBlacks(),
21.150 + r.getTurn()
21.151 + );
21.152 + b.setGameId(r.getGameId());
21.153 + b.setWhitePlayer(r.getWhitePlayer());
21.154 + b.setBlackPlayer(r.getBlackPlayer());
21.155 + b.setPlayer(ui.getSettings().getUsername());
21.156 + b.updateSummary(r.getSummary());
21.157 + ui.getBoards().add(b);
21.158 + ui.setSelectedGameId(r.getGameId());
21.159 + UIModel.refreshGames(ui);
21.160 + break;
21.161 + }
21.162 + case SendMove: {
21.163 + if (r.getBoard() == null) {
21.164 + throw new NullPointerException("No board in " + r);
21.165 + }
21.166 + final Board b = findBoard(ui, r.getGameId());
21.167 + if (b == null) {
21.168 + break;
21.169 + }
21.170 + b.updateSummary(r.getSummary());
21.171 + final String errMsg = r.getError() == null ? null : r.getError().getMessage();
21.172 + final List<String> whites = r.getBoard().getWhites();
21.173 + final List<String> blacks = r.getBoard().getBlacks();
21.174 + final Color turn = r.getNextTurn();
21.175 + BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
21.176 + break;
21.177 + }
21.178 + case JoinGame: {
21.179 + Board b;
21.180 + if ((b = findBoard(ui, r.getGameId())) != null) {
21.181 + b.setWhitePlayer(r.getWhitePlayer());
21.182 + b.setBlackPlayer(r.getBlackPlayer());
21.183 + b.setPlayer(ui.getSettings().getUsername());
21.184 + b.updateSummary(r.getSummary());
21.185 + ui.setSelectedGameId(r.getGameId());
21.186 + break SWITCH;
21.187 + }
21.188 + ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
21.189 + b = Rules.createBoard();
21.190 + Rules.initBoard(
21.191 + b, r.getBoard().getWhites(),
21.192 + r.getBoard().getBlacks(),
21.193 + r.getTurn()
21.194 + );
21.195 + b.setGameId(r.getGameId());
21.196 + b.setWhitePlayer(r.getWhitePlayer());
21.197 + b.setBlackPlayer(r.getBlackPlayer());
21.198 + b.setPlayer(ui.getSettings().getUsername());
21.199 + b.updateSummary(r.getSummary());
21.200 + if (r.getColor() == Color.B) {
21.201 + BoardModel.rotateBoard(b);
21.202 + }
21.203 + if (r.getMoves() != null) {
21.204 + for (String move : r.getMoves()) {
21.205 + Move m = BoardModel.MoveImpl.valueOf(move);
21.206 + b.getMoves().add(m);
21.207 + }
21.208 + } else {
21.209 + b.getMoves().clear();
21.210 + }
21.211 + ui.setSelectedGameId(b.getGameId());
21.212 + ui.getBoards().add(b);
21.213 + break;
21.214 + }
21.215 + case UpdateGame: {
21.216 + final Board b = findBoard(ui, r.getGameId());
21.217 + if (b == null) {
21.218 + break;
21.219 + }
21.220 + b.updateSummary(r.getSummary());
21.221 + final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
21.222 + final List<String> whites = r.getBoard().getWhites();
21.223 + final List<String> blacks = r.getBoard().getBlacks();
21.224 + final Color turn = r.getNextTurn();
21.225 + BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
21.226 + }
21.227 + }
21.228 + }
21.229 +
21.230 +
21.231 + private static Board findBoard(UI ui, String gameId) {
21.232 + for (Board tmp : ui.getBoards()) {
21.233 + if (tmp.getGameId().equals(gameId)) {
21.234 + return tmp;
21.235 + }
21.236 + }
21.237 + return null;
21.238 + }
21.239 +
21.240 +
21.241 + static void wasAnError(UI ui, Exception t) {
21.242 + if (t == null) {
21.243 + ui.setConnected(false);
21.244 + ui.setDisconnected(true);
21.245 + ui.setStatus("Disconnected.");
21.246 + } else {
21.247 + ui.setStatus("Error: " + t.getLocalizedMessage());
21.248 + }
21.249 + }
21.250 +
21.251 + @Function static void joinGame(UI u, Game data) {
21.252 + Request r = new Request();
21.253 + r.setMsg(MsgType.JoinGame);
21.254 + r.setObserver(false);
21.255 + r.setGameId(data.getGameId());
21.256 + u.sendMsg(r);
21.257 + }
21.258 +
21.259 + @Function static void observeGame(UI u, Game data) {
21.260 + Request r = new Request();
21.261 + r.setMsg(MsgType.JoinGame);
21.262 + r.setObserver(true);
21.263 + r.setGameId(data.getGameId());
21.264 + u.sendMsg(r);
21.265 + }
21.266 +
21.267 + private static final Set<UI> ACTIVE = new HashSet<>();
21.268 + @OnPropertyChange("connected") static void clearGames(UI m) {
21.269 + if (m.isDisconnected()) {
21.270 + m.getBoards().clear();
21.271 + ACTIVE.remove(m);
21.272 + } else {
21.273 + ACTIVE.add(m);
21.274 + }
21.275 + }
21.276 +
21.277 + static UI findUI(Board b) {
21.278 + for (UI ui : ACTIVE) {
21.279 + if (ui.getBoards().contains(b)) {
21.280 + return ui;
21.281 + }
21.282 + }
21.283 + return null;
21.284 + }
21.285 +
21.286 + @Function static void leave(UI ui, Board data) {
21.287 + ui.getBoards().remove(data);
21.288 + ui.setSelectedGameId(null);
21.289 + }
21.290 +
21.291 + @Function static void disconnect(UI ui) {
21.292 + ui.queryServer(ui.getSettings().getUrl(), null);
21.293 + ui.setStatus("Disconnecting...");
21.294 + }
21.295 +
21.296 + private static void verifyLogin(UI ui) {
21.297 + ui.setStatus("Verifying user credentials...");
21.298 + Request r = new Request();
21.299 + r.setMsg(MsgType.CheckCredentials);
21.300 + ui.sendMsg(r);
21.301 + }
21.302 +
21.303 + @Function static void reconnect(UI ui) {
21.304 + final Settings s = ui.getSettings();
21.305 + ui.setStatus("Connecting to the server...");
21.306 + ui.queryServer(s.getUrl(), null);
21.307 + s.write(ui);
21.308 + }
21.309 +
21.310 + public static void initialize(String... args) throws URISyntaxException, IOException {
21.311 + UI ui = new UI();
21.312 + ui.getSettings().read();
21.313 + ui.setStatus("Ready.");
21.314 + ui.setDisconnected(true);
21.315 + ui.applyBindings();
21.316 + }
21.317 +
21.318 +}
22.1 --- a/chess/src/test/java/com/oracle/chess/client/htmljava/BoardModelTest.java Tue Sep 24 22:28:31 2013 +0200
22.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
22.3 @@ -1,537 +0,0 @@
22.4 -/**
22.5 - * The MIT License (MIT)
22.6 - *
22.7 - * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
22.8 - *
22.9 - * Permission is hereby granted, free of charge, to any person obtaining a copy
22.10 - * of this software and associated documentation files (the "Software"), to deal
22.11 - * in the Software without restriction, including without limitation the rights
22.12 - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
22.13 - * copies of the Software, and to permit persons to whom the Software is
22.14 - * furnished to do so, subject to the following conditions:
22.15 - *
22.16 - * The above copyright notice and this permission notice shall be included in
22.17 - * all copies or substantial portions of the Software.
22.18 - *
22.19 - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22.20 - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22.21 - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22.22 - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22.23 - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22.24 - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22.25 - * THE SOFTWARE.
22.26 - */
22.27 -package com.oracle.chess.client.htmljava;
22.28 -
22.29 -import com.oracle.chess.client.htmljava.BoardModel.PieceType;
22.30 -import java.util.Arrays;
22.31 -import java.util.Collections;
22.32 -import java.util.List;
22.33 -import static org.testng.Assert.*;
22.34 -import org.testng.annotations.Test;
22.35 -
22.36 -/**
22.37 - *
22.38 - * @author Jaroslav Tulach <jtulach@netbeans.org>
22.39 - */
22.40 -public class BoardModelTest {
22.41 -
22.42 - public BoardModelTest() {
22.43 - }
22.44 -
22.45 - @Test public void whiteRockLeftBottom() {
22.46 - Board b = Rules.createBoard();
22.47 - Row bottom = b.getRows().get(7);
22.48 - Square left = bottom.getColumns().get(0);
22.49 - assertEquals(left.getPiece(), PieceType.ROCK, "Rock is on bottom left square");
22.50 - assertEquals(left.getPieceColor(), Color.W, "It is white");
22.51 - assertEquals(left.getColor(), Color.B, "Square is black");
22.52 - }
22.53 -
22.54 - @Test public void e2e4e7e6() {
22.55 - Board b = Rules.createBoard();
22.56 - b.setGameId("myId");
22.57 - setPlayer(b, Color.W);
22.58 - assertEquals(b.getTurn(), Color.W);
22.59 -
22.60 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.61 - assertNotNull(e2);
22.62 - BoardModel.selected(b, e2);
22.63 - assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
22.64 -
22.65 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.66 - assertNotNull(e4);
22.67 -
22.68 - BoardModel.selected(b, e4);
22.69 -
22.70 - assertTrue(e4.isPending(), "e4 marked as pending move");
22.71 - assertNull(e2.getPiece(), "No pawn at e2");
22.72 -
22.73 - // ignore all other figures than the two pawns
22.74 - BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"),
22.75 - Collections.singletonList("Pe7"), Color.B, null
22.76 - );
22.77 -
22.78 - assertFalse(e4.isPending(), "e4 now the move is real");
22.79 - assertNull(e2.getPiece(), "No pawn at e2");
22.80 - assertEquals(e4.getPiece(), BoardModel.PieceType.PAWN, "Pawn moved successfully");
22.81 - assertNull(BoardModel.findSelectedSquare(b), "No square selected");
22.82 -
22.83 - BoardModel.selected(b, e4);
22.84 - assertNull(BoardModel.findSelectedSquare(b), "No square selected, it is blacks turn");
22.85 -
22.86 - List<Move> mvs1 = b.getMoves();
22.87 - assertEquals(1, mvs1.size(), "First move was made: " + mvs1);
22.88 - Move firstMove = mvs1.get(0);
22.89 - assertEquals(firstMove.getPiece(), PieceType.PAWN, "Moving with pawn");
22.90 - assertEquals(firstMove.getRound(), 1, "First round of moves");
22.91 - assertEquals(firstMove.getTurn(), Color.W, "Moved by white");
22.92 - assertTrue(firstMove.isWhiteMove(), "Really moved by white");
22.93 -
22.94 - assertTrue(b.isBlackTurn(), "black's turn");
22.95 -
22.96 -
22.97 - Square e7 = BoardModel.findSquare(b, 'E', 7);
22.98 - BoardModel.selected(b, e7);
22.99 - assertNull(BoardModel.findSelectedSquare(b), "Can't select anything when I am white player");
22.100 -
22.101 - Move blackMv = BoardModel.MoveImpl.valueOf("E7E6");
22.102 - BoardModel.moveUpdate(b, blackMv,
22.103 - Collections.singletonList("PE4"),
22.104 - Collections.singletonList("PE6"),
22.105 - Color.W, null
22.106 - );
22.107 -
22.108 - assertNull(e7.getPiece(), "Piece has been moved");
22.109 -
22.110 - List<Move> mvs = b.getMoves();
22.111 - assertEquals(2, mvs.size(), "There are two moves now: " + mvs);
22.112 - Move secondMove = mvs.get(1);
22.113 - assertEquals(secondMove.getPiece(), PieceType.PAWN, "Moving with pawn");
22.114 - assertEquals(secondMove.getRound(), 1, "Still 1st round of moves");
22.115 - assertEquals(secondMove.getTurn(), Color.B, "Moved by black");
22.116 - assertFalse(secondMove.isWhiteMove(), "Really moved by black");
22.117 - }
22.118 -
22.119 - @Test public void unselect() {
22.120 - Board b = Rules.createBoard();
22.121 - b.setGameId("myId");
22.122 - setPlayer(b, Color.W);
22.123 - assertEquals(b.getTurn(), Color.W);
22.124 -
22.125 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.126 - assertNotNull(e2);
22.127 - BoardModel.selected(b, e2);
22.128 - assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
22.129 -
22.130 - BoardModel.selected(b, e2);
22.131 - assertNull(BoardModel.findSelectedSquare(b), "E2 is unselected");
22.132 -
22.133 - for (Row row : b.getRows()) {
22.134 - for (Square s : row.getColumns()) {
22.135 - assertFalse(s.isAccessible(), "No square is accessible anymore: " + s);
22.136 - }
22.137 - }
22.138 - }
22.139 -
22.140 - @Test public void discaredMove() {
22.141 - Board b = Rules.createBoard();
22.142 - b.setGameId("myId");
22.143 - setPlayer(b, Color.W);
22.144 - assertEquals(b.getTurn(), Color.W);
22.145 -
22.146 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.147 - assertNotNull(e2);
22.148 - BoardModel.selected(b, e2);
22.149 - assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
22.150 -
22.151 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.152 - assertNotNull(e4);
22.153 -
22.154 - BoardModel.selected(b, e4);
22.155 -
22.156 - assertTrue(e4.isPending(), "e4 marked as pending move");
22.157 - assertNull(e2.getPiece(), "No pawn at e2");
22.158 -
22.159 - assertEquals(b.getMoves().size(), 1, "One move recorded");
22.160 - assertEquals(b.getMoves().get(0), b.getPendingMove(), "Pending move is waiting");
22.161 -
22.162 - // ignore all other figures than the two pawns
22.163 - BoardModel.moveResponse(b, "No way, can't play like this", Collections.singletonList("PE2"),
22.164 - Collections.singletonList("Pe7"), Color.W, null
22.165 - );
22.166 -
22.167 - assertEquals(b.getAlertMessage(), "No way, can't play like this");
22.168 - assertNull(e4.getPiece(), "No piece on e4");
22.169 - assertEquals(e2.getPiece(), PieceType.PAWN, "Pawn is back");
22.170 -
22.171 - assertEquals(b.getMoves().size(), 0, "Move was discarded");
22.172 - assertNull(b.getPendingMove(), "No pending moves");
22.173 - }
22.174 -
22.175 - @Test public void cantSelectEmptySquare() {
22.176 - Board b = Rules.createBoard();
22.177 - Square e3 = BoardModel.findSquare(b, 'E', 3);
22.178 - assertNotNull(e3);
22.179 - BoardModel.selected(b, e3);
22.180 - assertNull(BoardModel.findSelectedSquare(b), "No square is selected");
22.181 - }
22.182 -
22.183 - @Test public void cantTakeOwnPiece() {
22.184 - Board b = Rules.createBoard();
22.185 - setPlayer(b, Color.W);
22.186 - Square e1 = BoardModel.findSquare(b, 'E', 1);
22.187 - assertNotNull(e1);
22.188 - BoardModel.selected(b, e1);
22.189 - assertEquals(BoardModel.findSelectedSquare(b), e1, "E1 is selected");
22.190 -
22.191 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.192 - assertNotNull(e2);
22.193 -
22.194 - BoardModel.selected(b, e2);
22.195 -
22.196 - assertNotNull(e1.getPiece(), "King remains at e1");
22.197 - assertEquals(e2.getPiece(), BoardModel.PieceType.PAWN, "Pawn remains");
22.198 - assertEquals(BoardModel.findSelectedSquare(b), e2, "e2 now selected");
22.199 -
22.200 - }
22.201 -
22.202 - @Test public void knightMustMoveToF3() {
22.203 - Board b = Rules.createBoard();
22.204 - setPlayer(b, Color.W);
22.205 - Square g1 = BoardModel.findSquare(b, 'G', 1);
22.206 - BoardModel.selected(b, g1);
22.207 -
22.208 - Square f3 = BoardModel.findSquare(b, 'F', 3);
22.209 - assertTrue(f3.isAccessible(), "This is a field where knight can move");
22.210 -
22.211 - Square g3 = BoardModel.findSquare(b, 'G', 3);
22.212 - assertFalse(g3.isAccessible(), "Not a place for knight");
22.213 -
22.214 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.215 - assertFalse(e2.isAccessible(), "Not a place either, occupied");
22.216 -
22.217 - BoardModel.selected(b, g3);
22.218 -
22.219 - assertNull(g3.getPiece(), "No figure was moved");
22.220 - assertTrue(g1.isSelected(), "Original square still selected");
22.221 -
22.222 - BoardModel.selected(b, f3);
22.223 -
22.224 - assertEquals(f3.getPiece(), PieceType.KNIGHT, "Moved");
22.225 - assertFalse(g3.isSelected(), "No longer selected");
22.226 - }
22.227 -
22.228 - @Test public void pawnCanTakeToSide() {
22.229 - Board b = Rules.createBoard();
22.230 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.231 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.232 - Square d7 = BoardModel.findSquare(b, 'D', 7);
22.233 - Square d5 = BoardModel.findSquare(b, 'D', 5);
22.234 -
22.235 - BoardModel.selected(b, e2);
22.236 - BoardModel.selected(b, e4);
22.237 -
22.238 - // ignore all other figures than the two pawns
22.239 - BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
22.240 - Collections.singletonList("PD7"), Color.B, null
22.241 - );
22.242 -
22.243 - setPlayer(b, Color.B);
22.244 -
22.245 - BoardModel.selected(b, d7);
22.246 - BoardModel.selected(b, d5);
22.247 -
22.248 - // ignore all other figures than the two pawns
22.249 - BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
22.250 - Collections.singletonList("PD5"), Color.W, null
22.251 - );
22.252 -
22.253 - setPlayer(b, Color.W);
22.254 -
22.255 - BoardModel.selected(b, e4);
22.256 - assertTrue(d5.isAccessible(), "Can take on d5");
22.257 - BoardModel.selected(b, d5);
22.258 - assertNull(e4.getPiece(), "No pawn on e4");
22.259 - assertEquals(d5.getPieceColor(), Color.W, "White Pawn on d5");
22.260 - }
22.261 -
22.262 - @Test public void pawnCanJumpOnAnother() {
22.263 - Board b = Rules.createBoard();
22.264 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.265 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.266 - Square d7 = BoardModel.findSquare(b, 'D', 7);
22.267 - Square d5 = BoardModel.findSquare(b, 'D', 5);
22.268 - Square e7 = BoardModel.findSquare(b, 'E', 7);
22.269 - Square e6 = BoardModel.findSquare(b, 'E', 6);
22.270 - Square e5 = BoardModel.findSquare(b, 'E', 5);
22.271 -
22.272 - BoardModel.selected(b, e2);
22.273 - BoardModel.selected(b, e4);
22.274 -
22.275 - // ignore all other figures than the three pawns
22.276 - BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
22.277 - Arrays.asList("PD7", "PE7"), Color.B, null
22.278 - );
22.279 -
22.280 - setPlayer(b, Color.B);
22.281 -
22.282 - BoardModel.selected(b, d7);
22.283 - BoardModel.selected(b, d5);
22.284 -
22.285 - // ignore all other figures than the three pawns
22.286 - BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
22.287 - Arrays.asList("PD5", "PE7"), Color.W, null
22.288 - );
22.289 -
22.290 - setPlayer(b, Color.W);
22.291 -
22.292 - BoardModel.selected(b, e4);
22.293 - BoardModel.selected(b, e5);
22.294 -
22.295 - // ignore all other figures than the three pawns
22.296 - BoardModel.moveResponse(b, null, Collections.singletonList("PE5"),
22.297 - Arrays.asList("PD5", "PE7"), Color.B, null
22.298 - );
22.299 -
22.300 - setPlayer(b, Color.B);
22.301 -
22.302 - BoardModel.selected(b, e7);
22.303 - assertTrue(e6.isAccessible(), "Can move by one piece");
22.304 - assertFalse(e5.isAccessible(), "Can't move where other pawn is");
22.305 - }
22.306 -
22.307 - @Test public void showFirstMove() {
22.308 - Board b = Rules.createBoard();
22.309 - setPlayer(b, Color.W);
22.310 - Square e2 = BoardModel.findSquare(b, 'E', 2);
22.311 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.312 - Square d7 = BoardModel.findSquare(b, 'D', 7);
22.313 - Square d5 = BoardModel.findSquare(b, 'D', 5);
22.314 -
22.315 - BoardModel.selected(b, e2);
22.316 - BoardModel.selected(b, e4);
22.317 -
22.318 - // ignore all other figures than the two pawns
22.319 - BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"),
22.320 - Collections.singletonList("PD7"), Color.B, null
22.321 - );
22.322 -
22.323 - Move blackMv = BoardModel.MoveImpl.valueOf("D7D5");
22.324 - BoardModel.moveUpdate(b, blackMv,
22.325 - Collections.singletonList("PE4"),
22.326 - Collections.singletonList("PD5"),
22.327 - Color.W, null
22.328 - );
22.329 -
22.330 -
22.331 - assertEquals(b.getMoves().size(), 2, "Two moves");
22.332 - BoardModel.showPosition(b, b.getMoves().get(0));
22.333 -
22.334 - assertEquals(b.getRows().size(), 8, "Still eight rows");
22.335 - assertEquals(b.getRows().get(0).getColumns().size(), 8, "Eight columns");
22.336 -
22.337 - assertNull(e2.getPiece(), "e2 is empty");
22.338 - assertEquals(e4.getPiece(), PieceType.PAWN, "e4 has pawn");
22.339 - assertEquals(d7.getPiece(), PieceType.PAWN, "d7 has pawn");
22.340 - assertNull(d5.getPiece(), "Second move is not made");
22.341 - assertNull(b.getTurn(), "Nobody to make a move");
22.342 - }
22.343 -
22.344 - @Test public void initialPositionReadFromAServer() {
22.345 - List<String> blacks = Arrays.asList(
22.346 - "Pa7",
22.347 - "Pb7",
22.348 - "Pc7",
22.349 - "Pd7",
22.350 - "Pe7",
22.351 - "Pf7",
22.352 - "Pg7",
22.353 - "Ph7",
22.354 - "Ra8",
22.355 - "Nb8",
22.356 - "Bc8",
22.357 - "Qd8",
22.358 - "Ke8",
22.359 - "Bf8",
22.360 - "Ng8",
22.361 - "Rh8"
22.362 - );
22.363 - List<String> whites = Arrays.asList(
22.364 - "Ra1",
22.365 - "Nb1",
22.366 - "Bc1",
22.367 - "Qd1",
22.368 - "Ke1",
22.369 - "Bf1",
22.370 - "Ng1",
22.371 - "Rh1",
22.372 - "Pa2",
22.373 - "Pb2",
22.374 - "Pc2",
22.375 - "Pd2",
22.376 - "Pe2",
22.377 - "Pf2",
22.378 - "Pg2",
22.379 - "Ph2"
22.380 - );
22.381 -
22.382 - Board b = Rules.createBoard();
22.383 - Rules.initBoard(b, whites, blacks, Color.W);
22.384 -
22.385 - Board b2 = Rules.createBoard();
22.386 - Rules.initBoard(b2);
22.387 -
22.388 - for (int i = 0; i < 7; i++) {
22.389 - for (int j = 0; j < 7; j++) {
22.390 - Square s = b.getRows().get(i).getColumns().get(j);
22.391 - Square s2 = b2.getRows().get(i).getColumns().get(j);
22.392 -
22.393 - assertEquals(s.getPiece(), s2.getPiece(), "Same piece at " + i + "/" + j);
22.394 - assertEquals(s.getPieceColor(), s2.getPieceColor(), "Same piece color at " + i + "/" + j);
22.395 - }
22.396 - }
22.397 - }
22.398 -
22.399 - @Test public void allowSmallRochade() {
22.400 - Board b = Rules.createBoard();
22.401 - setPlayer(b, Color.W);
22.402 - Square f1 = BoardModel.findSquare(b, 'F', 1);
22.403 - f1.setPiece(null);
22.404 - f1.setPieceColor(null);
22.405 - Square g1 = BoardModel.findSquare(b, 'G', 1);
22.406 - g1.setPiece(null);
22.407 - g1.setPieceColor(null);
22.408 - Square e1 = BoardModel.findSquare(b, 'E', 1);
22.409 -
22.410 - BoardModel.selected(b, e1);
22.411 - assertTrue(g1.isAccessible(), "Can do 0-0");
22.412 - }
22.413 -
22.414 - @Test public void allowSmallRochadeForBlack() {
22.415 - Board b = Rules.createBoard();
22.416 - setPlayer(b, Color.B);
22.417 - b.setTurn(Color.B);
22.418 - Square f8 = BoardModel.findSquare(b, 'F', 8);
22.419 - f8.setPiece(null);
22.420 - f8.setPieceColor(null);
22.421 - Square g8 = BoardModel.findSquare(b, 'G', 8);
22.422 - g8.setPiece(null);
22.423 - g8.setPieceColor(null);
22.424 - Square e8 = BoardModel.findSquare(b, 'E', 8);
22.425 -
22.426 - BoardModel.selected(b, e8);
22.427 - assertTrue(g8.isAccessible(), "Can do 0-0");
22.428 - }
22.429 -
22.430 - @Test public void disallowSmallRochadeWhenNoRock() {
22.431 - Board b = Rules.createBoard();
22.432 - setPlayer(b, Color.W);
22.433 - Square f1 = BoardModel.findSquare(b, 'F', 1);
22.434 - f1.setPiece(null);
22.435 - f1.setPieceColor(null);
22.436 - Square g1 = BoardModel.findSquare(b, 'G', 1);
22.437 - g1.setPiece(null);
22.438 - g1.setPieceColor(null);
22.439 - Square h1 = BoardModel.findSquare(b, 'H', 1);
22.440 - h1.setPiece(null);
22.441 - h1.setPieceColor(null);
22.442 - Square e1 = BoardModel.findSquare(b, 'E', 1);
22.443 -
22.444 - BoardModel.selected(b, e1);
22.445 - assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is no rock");
22.446 - }
22.447 -
22.448 - @Test public void disallowSmallRochadeWhenBishop() {
22.449 - Board b = Rules.createBoard();
22.450 - setPlayer(b, Color.W);
22.451 - Square g1 = BoardModel.findSquare(b, 'G', 1);
22.452 - g1.setPiece(null);
22.453 - Square e1 = BoardModel.findSquare(b, 'E', 1);
22.454 -
22.455 - BoardModel.selected(b, e1);
22.456 - assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is bishop");
22.457 - }
22.458 -
22.459 - @Test public void disallowSmallRochadeWhenKnight() {
22.460 - Board b = Rules.createBoard();
22.461 - setPlayer(b, Color.W);
22.462 - Square f1 = BoardModel.findSquare(b, 'F', 1);
22.463 - f1.setPiece(null);
22.464 - Square e1 = BoardModel.findSquare(b, 'E', 1);
22.465 -
22.466 - BoardModel.selected(b, e1);
22.467 - assertFalse(f1.isAccessible(), "Cannot do 0-0 when there is knight");
22.468 - }
22.469 -
22.470 - @Test public void allowBigRochadeForBlack() {
22.471 - Board b = Rules.createBoard();
22.472 - setPlayer(b, Color.B);
22.473 - b.setTurn(Color.B);
22.474 - Square b8 = BoardModel.findSquare(b, 'B', 8);
22.475 - b8.setPiece(null);
22.476 - b8.setPieceColor(null);
22.477 - Square c8 = BoardModel.findSquare(b, 'C', 8);
22.478 - c8.setPiece(null);
22.479 - c8.setPieceColor(null);
22.480 - Square d8 = BoardModel.findSquare(b, 'D', 8);
22.481 - d8.setPiece(null);
22.482 - d8.setPieceColor(null);
22.483 - Square e8 = BoardModel.findSquare(b, 'E', 8);
22.484 -
22.485 - BoardModel.selected(b, e8);
22.486 - assertTrue(c8.isAccessible(), "Can do 0-0-0");
22.487 - }
22.488 -
22.489 - @Test public void enPassant() {
22.490 - Board b = Rules.createBoard();
22.491 - setPlayer(b, Color.B);
22.492 - b.setTurn(Color.B);
22.493 -
22.494 - Square e7 = BoardModel.findSquare(b, 'E', 7);
22.495 - Square e4 = BoardModel.findSquare(b, 'E', 4);
22.496 - movePiece(e7, e4);
22.497 -
22.498 - Move move = new Move();
22.499 - move.setFrom(position('D', 2));
22.500 - move.setTo(position('D', 4));
22.501 - move.setPiece(PieceType.PAWN);
22.502 - b.getMoves().add(move);
22.503 -
22.504 - Square d2 = BoardModel.findSquare(b, 'D', 2);
22.505 - Square d4 = BoardModel.findSquare(b, 'D', 4);
22.506 - movePiece(d2, d4);
22.507 -
22.508 - BoardModel.selected(b, e4);
22.509 -
22.510 - Square e3 = BoardModel.findSquare(b, 'E', 3);
22.511 - assertTrue(e3.isAccessible(), "Obviously can move to e3");
22.512 -
22.513 - Square d3 = BoardModel.findSquare(b, 'D', 3);
22.514 - assertTrue(d3.isAccessible(), "Can also take on d3");
22.515 - }
22.516 -
22.517 - private void movePiece(Square from, Square to) {
22.518 - to.setPiece(from.getPiece());
22.519 - to.setPieceColor(from.getPieceColor());
22.520 - from.setPiece(null);
22.521 - from.setPieceColor(null);
22.522 - }
22.523 -
22.524 - private Position position(char c, int i) {
22.525 - Position p = new Position();
22.526 - p.setX(c);
22.527 - p.setY(i);
22.528 - return p;
22.529 - }
22.530 -
22.531 - private static void setPlayer(Board b, Color c) {
22.532 - b.setWhitePlayer("x");
22.533 - b.setBlackPlayer("y");
22.534 - if (c == Color.B) {
22.535 - b.setPlayer("y");
22.536 - } else {
22.537 - b.setPlayer("x");
22.538 - }
22.539 - }
22.540 -}
23.1 --- a/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java Tue Sep 24 22:28:31 2013 +0200
23.2 +++ b/chess/src/test/java/org/apidesign/html/demo/chess/BoardModelTest.java Tue Sep 24 22:37:17 2013 +0200
23.3 @@ -23,8 +23,13 @@
23.4 */
23.5 package org.apidesign.html.demo.chess;
23.6
23.7 -import org.apidesign.html.demo.chess.BoardModel.ColorType;
23.8 +import org.apidesign.html.demo.chess.Color;
23.9 +import org.apidesign.html.demo.chess.Rules;
23.10 +import org.apidesign.html.demo.chess.BoardModel;
23.11 import org.apidesign.html.demo.chess.BoardModel.PieceType;
23.12 +import java.util.Arrays;
23.13 +import java.util.Collections;
23.14 +import java.util.List;
23.15 import static org.testng.Assert.*;
23.16 import org.testng.annotations.Test;
23.17
23.18 @@ -36,11 +41,21 @@
23.19
23.20 public BoardModelTest() {
23.21 }
23.22 -
23.23 +
23.24 + @Test public void whiteRockLeftBottom() {
23.25 + Board b = Rules.createBoard();
23.26 + Row bottom = b.getRows().get(7);
23.27 + Square left = bottom.getColumns().get(0);
23.28 + assertEquals(left.getPiece(), PieceType.ROCK, "Rock is on bottom left square");
23.29 + assertEquals(left.getPieceColor(), Color.W, "It is white");
23.30 + assertEquals(left.getColor(), Color.B, "Square is black");
23.31 + }
23.32
23.33 @Test public void e2e4e7e6() {
23.34 - Board b = BoardModel.createBoard();
23.35 - assertEquals(b.getTurn(), ColorType.WHITE);
23.36 + Board b = Rules.createBoard();
23.37 + b.setGameId("myId");
23.38 + setPlayer(b, Color.W);
23.39 + assertEquals(b.getTurn(), Color.W);
23.40
23.41 Square e2 = BoardModel.findSquare(b, 'E', 2);
23.42 assertNotNull(e2);
23.43 @@ -52,26 +67,113 @@
23.44
23.45 BoardModel.selected(b, e4);
23.46
23.47 + assertTrue(e4.isPending(), "e4 marked as pending move");
23.48 + assertNull(e2.getPiece(), "No pawn at e2");
23.49 +
23.50 + // ignore all other figures than the two pawns
23.51 + BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"),
23.52 + Collections.singletonList("Pe7"), Color.B, null
23.53 + );
23.54 +
23.55 + assertFalse(e4.isPending(), "e4 now the move is real");
23.56 assertNull(e2.getPiece(), "No pawn at e2");
23.57 assertEquals(e4.getPiece(), BoardModel.PieceType.PAWN, "Pawn moved successfully");
23.58 assertNull(BoardModel.findSelectedSquare(b), "No square selected");
23.59
23.60 BoardModel.selected(b, e4);
23.61 assertNull(BoardModel.findSelectedSquare(b), "No square selected, it is blacks turn");
23.62 +
23.63 + List<Move> mvs1 = b.getMoves();
23.64 + assertEquals(1, mvs1.size(), "First move was made: " + mvs1);
23.65 + Move firstMove = mvs1.get(0);
23.66 + assertEquals(firstMove.getPiece(), PieceType.PAWN, "Moving with pawn");
23.67 + assertEquals(firstMove.getRound(), 1, "First round of moves");
23.68 + assertEquals(firstMove.getTurn(), Color.W, "Moved by white");
23.69 + assertTrue(firstMove.isWhiteMove(), "Really moved by white");
23.70
23.71 assertTrue(b.isBlackTurn(), "black's turn");
23.72
23.73
23.74 Square e7 = BoardModel.findSquare(b, 'E', 7);
23.75 BoardModel.selected(b, e7);
23.76 - assertEquals(BoardModel.findSelectedSquare(b), e7);
23.77 + assertNull(BoardModel.findSelectedSquare(b), "Can't select anything when I am white player");
23.78
23.79 - BoardModel.selected(b, BoardModel.findSquare(b, 'E', 6));
23.80 + Move blackMv = BoardModel.MoveImpl.valueOf("E7E6");
23.81 + BoardModel.moveUpdate(b, blackMv,
23.82 + Collections.singletonList("PE4"),
23.83 + Collections.singletonList("PE6"),
23.84 + Color.W, null
23.85 + );
23.86 +
23.87 assertNull(e7.getPiece(), "Piece has been moved");
23.88 +
23.89 + List<Move> mvs = b.getMoves();
23.90 + assertEquals(2, mvs.size(), "There are two moves now: " + mvs);
23.91 + Move secondMove = mvs.get(1);
23.92 + assertEquals(secondMove.getPiece(), PieceType.PAWN, "Moving with pawn");
23.93 + assertEquals(secondMove.getRound(), 1, "Still 1st round of moves");
23.94 + assertEquals(secondMove.getTurn(), Color.B, "Moved by black");
23.95 + assertFalse(secondMove.isWhiteMove(), "Really moved by black");
23.96 + }
23.97 +
23.98 + @Test public void unselect() {
23.99 + Board b = Rules.createBoard();
23.100 + b.setGameId("myId");
23.101 + setPlayer(b, Color.W);
23.102 + assertEquals(b.getTurn(), Color.W);
23.103 +
23.104 + Square e2 = BoardModel.findSquare(b, 'E', 2);
23.105 + assertNotNull(e2);
23.106 + BoardModel.selected(b, e2);
23.107 + assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
23.108 +
23.109 + BoardModel.selected(b, e2);
23.110 + assertNull(BoardModel.findSelectedSquare(b), "E2 is unselected");
23.111 +
23.112 + for (Row row : b.getRows()) {
23.113 + for (Square s : row.getColumns()) {
23.114 + assertFalse(s.isAccessible(), "No square is accessible anymore: " + s);
23.115 + }
23.116 + }
23.117 + }
23.118 +
23.119 + @Test public void discaredMove() {
23.120 + Board b = Rules.createBoard();
23.121 + b.setGameId("myId");
23.122 + setPlayer(b, Color.W);
23.123 + assertEquals(b.getTurn(), Color.W);
23.124 +
23.125 + Square e2 = BoardModel.findSquare(b, 'E', 2);
23.126 + assertNotNull(e2);
23.127 + BoardModel.selected(b, e2);
23.128 + assertEquals(BoardModel.findSelectedSquare(b), e2, "E2 is selected");
23.129 +
23.130 + Square e4 = BoardModel.findSquare(b, 'E', 4);
23.131 + assertNotNull(e4);
23.132 +
23.133 + BoardModel.selected(b, e4);
23.134 +
23.135 + assertTrue(e4.isPending(), "e4 marked as pending move");
23.136 + assertNull(e2.getPiece(), "No pawn at e2");
23.137 +
23.138 + assertEquals(b.getMoves().size(), 1, "One move recorded");
23.139 + assertEquals(b.getMoves().get(0), b.getPendingMove(), "Pending move is waiting");
23.140 +
23.141 + // ignore all other figures than the two pawns
23.142 + BoardModel.moveResponse(b, "No way, can't play like this", Collections.singletonList("PE2"),
23.143 + Collections.singletonList("Pe7"), Color.W, null
23.144 + );
23.145 +
23.146 + assertEquals(b.getAlertMessage(), "No way, can't play like this");
23.147 + assertNull(e4.getPiece(), "No piece on e4");
23.148 + assertEquals(e2.getPiece(), PieceType.PAWN, "Pawn is back");
23.149 +
23.150 + assertEquals(b.getMoves().size(), 0, "Move was discarded");
23.151 + assertNull(b.getPendingMove(), "No pending moves");
23.152 }
23.153
23.154 @Test public void cantSelectEmptySquare() {
23.155 - Board b = BoardModel.createBoard();
23.156 + Board b = Rules.createBoard();
23.157 Square e3 = BoardModel.findSquare(b, 'E', 3);
23.158 assertNotNull(e3);
23.159 BoardModel.selected(b, e3);
23.160 @@ -79,7 +181,8 @@
23.161 }
23.162
23.163 @Test public void cantTakeOwnPiece() {
23.164 - Board b = BoardModel.createBoard();
23.165 + Board b = Rules.createBoard();
23.166 + setPlayer(b, Color.W);
23.167 Square e1 = BoardModel.findSquare(b, 'E', 1);
23.168 assertNotNull(e1);
23.169 BoardModel.selected(b, e1);
23.170 @@ -97,7 +200,8 @@
23.171 }
23.172
23.173 @Test public void knightMustMoveToF3() {
23.174 - Board b = BoardModel.createBoard();
23.175 + Board b = Rules.createBoard();
23.176 + setPlayer(b, Color.W);
23.177 Square g1 = BoardModel.findSquare(b, 'G', 1);
23.178 BoardModel.selected(b, g1);
23.179
23.180 @@ -122,7 +226,7 @@
23.181 }
23.182
23.183 @Test public void pawnCanTakeToSide() {
23.184 - Board b = BoardModel.createBoard();
23.185 + Board b = Rules.createBoard();
23.186 Square e2 = BoardModel.findSquare(b, 'E', 2);
23.187 Square e4 = BoardModel.findSquare(b, 'E', 4);
23.188 Square d7 = BoardModel.findSquare(b, 'D', 7);
23.189 @@ -130,13 +234,307 @@
23.190
23.191 BoardModel.selected(b, e2);
23.192 BoardModel.selected(b, e4);
23.193 +
23.194 + // ignore all other figures than the two pawns
23.195 + BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
23.196 + Collections.singletonList("PD7"), Color.B, null
23.197 + );
23.198 +
23.199 + setPlayer(b, Color.B);
23.200 +
23.201 BoardModel.selected(b, d7);
23.202 BoardModel.selected(b, d5);
23.203
23.204 + // ignore all other figures than the two pawns
23.205 + BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
23.206 + Collections.singletonList("PD5"), Color.W, null
23.207 + );
23.208 +
23.209 + setPlayer(b, Color.W);
23.210 +
23.211 BoardModel.selected(b, e4);
23.212 assertTrue(d5.isAccessible(), "Can take on d5");
23.213 BoardModel.selected(b, d5);
23.214 assertNull(e4.getPiece(), "No pawn on e4");
23.215 - assertEquals(d5.getPieceColor(), ColorType.WHITE, "White Pawn on d5");
23.216 + assertEquals(d5.getPieceColor(), Color.W, "White Pawn on d5");
23.217 + }
23.218 +
23.219 + @Test public void pawnCanJumpOnAnother() {
23.220 + Board b = Rules.createBoard();
23.221 + Square e2 = BoardModel.findSquare(b, 'E', 2);
23.222 + Square e4 = BoardModel.findSquare(b, 'E', 4);
23.223 + Square d7 = BoardModel.findSquare(b, 'D', 7);
23.224 + Square d5 = BoardModel.findSquare(b, 'D', 5);
23.225 + Square e7 = BoardModel.findSquare(b, 'E', 7);
23.226 + Square e6 = BoardModel.findSquare(b, 'E', 6);
23.227 + Square e5 = BoardModel.findSquare(b, 'E', 5);
23.228 +
23.229 + BoardModel.selected(b, e2);
23.230 + BoardModel.selected(b, e4);
23.231 +
23.232 + // ignore all other figures than the three pawns
23.233 + BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
23.234 + Arrays.asList("PD7", "PE7"), Color.B, null
23.235 + );
23.236 +
23.237 + setPlayer(b, Color.B);
23.238 +
23.239 + BoardModel.selected(b, d7);
23.240 + BoardModel.selected(b, d5);
23.241 +
23.242 + // ignore all other figures than the three pawns
23.243 + BoardModel.moveResponse(b, null, Collections.singletonList("PE4"),
23.244 + Arrays.asList("PD5", "PE7"), Color.W, null
23.245 + );
23.246 +
23.247 + setPlayer(b, Color.W);
23.248 +
23.249 + BoardModel.selected(b, e4);
23.250 + BoardModel.selected(b, e5);
23.251 +
23.252 + // ignore all other figures than the three pawns
23.253 + BoardModel.moveResponse(b, null, Collections.singletonList("PE5"),
23.254 + Arrays.asList("PD5", "PE7"), Color.B, null
23.255 + );
23.256 +
23.257 + setPlayer(b, Color.B);
23.258 +
23.259 + BoardModel.selected(b, e7);
23.260 + assertTrue(e6.isAccessible(), "Can move by one piece");
23.261 + assertFalse(e5.isAccessible(), "Can't move where other pawn is");
23.262 + }
23.263 +
23.264 + @Test public void showFirstMove() {
23.265 + Board b = Rules.createBoard();
23.266 + setPlayer(b, Color.W);
23.267 + Square e2 = BoardModel.findSquare(b, 'E', 2);
23.268 + Square e4 = BoardModel.findSquare(b, 'E', 4);
23.269 + Square d7 = BoardModel.findSquare(b, 'D', 7);
23.270 + Square d5 = BoardModel.findSquare(b, 'D', 5);
23.271 +
23.272 + BoardModel.selected(b, e2);
23.273 + BoardModel.selected(b, e4);
23.274 +
23.275 + // ignore all other figures than the two pawns
23.276 + BoardModel.moveResponse(b, null, Collections.singletonList("Pe4"),
23.277 + Collections.singletonList("PD7"), Color.B, null
23.278 + );
23.279 +
23.280 + Move blackMv = BoardModel.MoveImpl.valueOf("D7D5");
23.281 + BoardModel.moveUpdate(b, blackMv,
23.282 + Collections.singletonList("PE4"),
23.283 + Collections.singletonList("PD5"),
23.284 + Color.W, null
23.285 + );
23.286 +
23.287 +
23.288 + assertEquals(b.getMoves().size(), 2, "Two moves");
23.289 + BoardModel.showPosition(b, b.getMoves().get(0));
23.290 +
23.291 + assertEquals(b.getRows().size(), 8, "Still eight rows");
23.292 + assertEquals(b.getRows().get(0).getColumns().size(), 8, "Eight columns");
23.293 +
23.294 + assertNull(e2.getPiece(), "e2 is empty");
23.295 + assertEquals(e4.getPiece(), PieceType.PAWN, "e4 has pawn");
23.296 + assertEquals(d7.getPiece(), PieceType.PAWN, "d7 has pawn");
23.297 + assertNull(d5.getPiece(), "Second move is not made");
23.298 + assertNull(b.getTurn(), "Nobody to make a move");
23.299 + }
23.300 +
23.301 + @Test public void initialPositionReadFromAServer() {
23.302 + List<String> blacks = Arrays.asList(
23.303 + "Pa7",
23.304 + "Pb7",
23.305 + "Pc7",
23.306 + "Pd7",
23.307 + "Pe7",
23.308 + "Pf7",
23.309 + "Pg7",
23.310 + "Ph7",
23.311 + "Ra8",
23.312 + "Nb8",
23.313 + "Bc8",
23.314 + "Qd8",
23.315 + "Ke8",
23.316 + "Bf8",
23.317 + "Ng8",
23.318 + "Rh8"
23.319 + );
23.320 + List<String> whites = Arrays.asList(
23.321 + "Ra1",
23.322 + "Nb1",
23.323 + "Bc1",
23.324 + "Qd1",
23.325 + "Ke1",
23.326 + "Bf1",
23.327 + "Ng1",
23.328 + "Rh1",
23.329 + "Pa2",
23.330 + "Pb2",
23.331 + "Pc2",
23.332 + "Pd2",
23.333 + "Pe2",
23.334 + "Pf2",
23.335 + "Pg2",
23.336 + "Ph2"
23.337 + );
23.338 +
23.339 + Board b = Rules.createBoard();
23.340 + Rules.initBoard(b, whites, blacks, Color.W);
23.341 +
23.342 + Board b2 = Rules.createBoard();
23.343 + Rules.initBoard(b2);
23.344 +
23.345 + for (int i = 0; i < 7; i++) {
23.346 + for (int j = 0; j < 7; j++) {
23.347 + Square s = b.getRows().get(i).getColumns().get(j);
23.348 + Square s2 = b2.getRows().get(i).getColumns().get(j);
23.349 +
23.350 + assertEquals(s.getPiece(), s2.getPiece(), "Same piece at " + i + "/" + j);
23.351 + assertEquals(s.getPieceColor(), s2.getPieceColor(), "Same piece color at " + i + "/" + j);
23.352 + }
23.353 + }
23.354 + }
23.355 +
23.356 + @Test public void allowSmallRochade() {
23.357 + Board b = Rules.createBoard();
23.358 + setPlayer(b, Color.W);
23.359 + Square f1 = BoardModel.findSquare(b, 'F', 1);
23.360 + f1.setPiece(null);
23.361 + f1.setPieceColor(null);
23.362 + Square g1 = BoardModel.findSquare(b, 'G', 1);
23.363 + g1.setPiece(null);
23.364 + g1.setPieceColor(null);
23.365 + Square e1 = BoardModel.findSquare(b, 'E', 1);
23.366 +
23.367 + BoardModel.selected(b, e1);
23.368 + assertTrue(g1.isAccessible(), "Can do 0-0");
23.369 + }
23.370 +
23.371 + @Test public void allowSmallRochadeForBlack() {
23.372 + Board b = Rules.createBoard();
23.373 + setPlayer(b, Color.B);
23.374 + b.setTurn(Color.B);
23.375 + Square f8 = BoardModel.findSquare(b, 'F', 8);
23.376 + f8.setPiece(null);
23.377 + f8.setPieceColor(null);
23.378 + Square g8 = BoardModel.findSquare(b, 'G', 8);
23.379 + g8.setPiece(null);
23.380 + g8.setPieceColor(null);
23.381 + Square e8 = BoardModel.findSquare(b, 'E', 8);
23.382 +
23.383 + BoardModel.selected(b, e8);
23.384 + assertTrue(g8.isAccessible(), "Can do 0-0");
23.385 + }
23.386 +
23.387 + @Test public void disallowSmallRochadeWhenNoRock() {
23.388 + Board b = Rules.createBoard();
23.389 + setPlayer(b, Color.W);
23.390 + Square f1 = BoardModel.findSquare(b, 'F', 1);
23.391 + f1.setPiece(null);
23.392 + f1.setPieceColor(null);
23.393 + Square g1 = BoardModel.findSquare(b, 'G', 1);
23.394 + g1.setPiece(null);
23.395 + g1.setPieceColor(null);
23.396 + Square h1 = BoardModel.findSquare(b, 'H', 1);
23.397 + h1.setPiece(null);
23.398 + h1.setPieceColor(null);
23.399 + Square e1 = BoardModel.findSquare(b, 'E', 1);
23.400 +
23.401 + BoardModel.selected(b, e1);
23.402 + assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is no rock");
23.403 + }
23.404 +
23.405 + @Test public void disallowSmallRochadeWhenBishop() {
23.406 + Board b = Rules.createBoard();
23.407 + setPlayer(b, Color.W);
23.408 + Square g1 = BoardModel.findSquare(b, 'G', 1);
23.409 + g1.setPiece(null);
23.410 + Square e1 = BoardModel.findSquare(b, 'E', 1);
23.411 +
23.412 + BoardModel.selected(b, e1);
23.413 + assertFalse(g1.isAccessible(), "Cannot do 0-0 when there is bishop");
23.414 + }
23.415 +
23.416 + @Test public void disallowSmallRochadeWhenKnight() {
23.417 + Board b = Rules.createBoard();
23.418 + setPlayer(b, Color.W);
23.419 + Square f1 = BoardModel.findSquare(b, 'F', 1);
23.420 + f1.setPiece(null);
23.421 + Square e1 = BoardModel.findSquare(b, 'E', 1);
23.422 +
23.423 + BoardModel.selected(b, e1);
23.424 + assertFalse(f1.isAccessible(), "Cannot do 0-0 when there is knight");
23.425 + }
23.426 +
23.427 + @Test public void allowBigRochadeForBlack() {
23.428 + Board b = Rules.createBoard();
23.429 + setPlayer(b, Color.B);
23.430 + b.setTurn(Color.B);
23.431 + Square b8 = BoardModel.findSquare(b, 'B', 8);
23.432 + b8.setPiece(null);
23.433 + b8.setPieceColor(null);
23.434 + Square c8 = BoardModel.findSquare(b, 'C', 8);
23.435 + c8.setPiece(null);
23.436 + c8.setPieceColor(null);
23.437 + Square d8 = BoardModel.findSquare(b, 'D', 8);
23.438 + d8.setPiece(null);
23.439 + d8.setPieceColor(null);
23.440 + Square e8 = BoardModel.findSquare(b, 'E', 8);
23.441 +
23.442 + BoardModel.selected(b, e8);
23.443 + assertTrue(c8.isAccessible(), "Can do 0-0-0");
23.444 + }
23.445 +
23.446 + @Test public void enPassant() {
23.447 + Board b = Rules.createBoard();
23.448 + setPlayer(b, Color.B);
23.449 + b.setTurn(Color.B);
23.450 +
23.451 + Square e7 = BoardModel.findSquare(b, 'E', 7);
23.452 + Square e4 = BoardModel.findSquare(b, 'E', 4);
23.453 + movePiece(e7, e4);
23.454 +
23.455 + Move move = new Move();
23.456 + move.setFrom(position('D', 2));
23.457 + move.setTo(position('D', 4));
23.458 + move.setPiece(PieceType.PAWN);
23.459 + b.getMoves().add(move);
23.460 +
23.461 + Square d2 = BoardModel.findSquare(b, 'D', 2);
23.462 + Square d4 = BoardModel.findSquare(b, 'D', 4);
23.463 + movePiece(d2, d4);
23.464 +
23.465 + BoardModel.selected(b, e4);
23.466 +
23.467 + Square e3 = BoardModel.findSquare(b, 'E', 3);
23.468 + assertTrue(e3.isAccessible(), "Obviously can move to e3");
23.469 +
23.470 + Square d3 = BoardModel.findSquare(b, 'D', 3);
23.471 + assertTrue(d3.isAccessible(), "Can also take on d3");
23.472 + }
23.473 +
23.474 + private void movePiece(Square from, Square to) {
23.475 + to.setPiece(from.getPiece());
23.476 + to.setPieceColor(from.getPieceColor());
23.477 + from.setPiece(null);
23.478 + from.setPieceColor(null);
23.479 + }
23.480 +
23.481 + private Position position(char c, int i) {
23.482 + Position p = new Position();
23.483 + p.setX(c);
23.484 + p.setY(i);
23.485 + return p;
23.486 + }
23.487 +
23.488 + private static void setPlayer(Board b, Color c) {
23.489 + b.setWhitePlayer("x");
23.490 + b.setBlackPlayer("y");
23.491 + if (c == Color.B) {
23.492 + b.setPlayer("y");
23.493 + } else {
23.494 + b.setPlayer("x");
23.495 + }
23.496 }
23.497 }