2 * The MIT License (MIT)
4 * Copyright (C) 2013 Jaroslav Tulach <jaroslav.tulach@apidesign.org>
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 package org.apidesign.html.demo.chess;
26 import java.io.IOException;
27 import java.net.URISyntaxException;
28 import java.util.HashSet;
29 import java.util.List;
31 import java.util.logging.Level;
32 import java.util.logging.Logger;
33 import net.java.html.json.ComputedProperty;
34 import net.java.html.json.Function;
35 import net.java.html.json.Model;
36 import net.java.html.json.ModelOperation;
37 import net.java.html.json.OnPropertyChange;
38 import net.java.html.json.OnReceive;
39 import net.java.html.json.Property;
43 * @author Jaroslav Tulach <jtulach@netbeans.org>
45 @Model(className = "UI", properties = {
46 @Property(name = "status", type = String.class),
47 @Property(name = "selectedGameId", type = String.class),
48 @Property(name = "boards", type = Board.class, array = true),
49 @Property(name = "viewGames", type = Games.class),
50 @Property(name = "settings", type = Settings.class),
51 @Property(name = "connected", type = boolean.class),
52 @Property(name = "disconnected", type = boolean.class),
54 public class UIModel {
55 private static final Logger LOG = Logger.getLogger(UIModel.class.getName());
57 @ComputedProperty static boolean settingsActive(String selectedGameId) {
58 return selectedGameId == null;
61 @ComputedProperty static boolean viewGamesActive(String selectedGameId, boolean connected) {
62 return selectedGameId == null && connected;
65 @ComputedProperty static Board selectedBoard(String selectedGameId, List<Board> boards) {
67 for (Board b : boards) {
69 if (selectedGameId != null && selectedGameId.equals(b.getGameId())) {
77 @Function static void activateGame(UI m, Board data) {
78 m.setSelectedGameId(data.getGameId());
81 @Function static void activateSettings(UI m) {
82 m.setSelectedGameId(null);
86 @Function static void createGame(UI u) {
87 u.setStatus("Creating new game...");
88 Request r = new Request();
89 r.setMsg(MsgType.CreateGame);
90 r.setColor(Color.valueOf(u.getViewGames().getSelectedColor()));
94 @ModelOperation @Function static void refreshGames(UI u) {
95 u.setStatus("Refreshing games...");
96 Request r = new Request();
97 r.setMsg(MsgType.QueryGames);
101 @ModelOperation static void sendMsg(UI ui, Request r) {
102 final Settings sttngs = ui.getSettings();
104 String url = sttngs.getUrl();
105 r.setUsername(sttngs.getUsername());
106 r.setPassword(sttngs.getPassword());
108 LOG.log(Level.INFO, "Sending {0} to {1}", new Object[]{r, url});
109 ui.queryServer(url, r);
113 @OnReceive(data = Request.class, url = "{url}", method = "WebSocket", onError = "wasAnError")
114 static void queryServer(UI ui, Response r) {
115 LOG.log(Level.INFO, "Received {0}", r);
117 ui.setDisconnected(false);
121 SWITCH: switch (MsgType.forResponse(r.getMsg())) {
122 case CheckCredentials: {
123 switch (r.getCheck()) {
126 ui.setConnected(true);
128 ui.setStatus("Connected.");
131 ui.setStatus("Password is invalid");
138 ui.getViewGames().listGames(r.getGames(), ui.getSettings().getUsername());
142 ui.setStatus("Game " + r + " created");
143 final Board b = Rules.createBoard();
145 b, r.getBoard().getWhites(),
146 r.getBoard().getBlacks(),
149 b.setGameId(r.getGameId());
150 b.setWhitePlayer(r.getWhitePlayer());
151 b.setBlackPlayer(r.getBlackPlayer());
152 b.setPlayer(ui.getSettings().getUsername());
153 b.updateSummary(r.getSummary());
154 ui.getBoards().add(b);
155 ui.setSelectedGameId(r.getGameId());
156 UIModel.refreshGames(ui);
160 if (r.getBoard() == null) {
161 throw new NullPointerException("No board in " + r);
163 final Board b = findBoard(ui, r.getGameId());
167 b.updateSummary(r.getSummary());
168 final String errMsg = r.getError() == null ? null : r.getError().getMessage();
169 final List<String> whites = r.getBoard().getWhites();
170 final List<String> blacks = r.getBoard().getBlacks();
171 final Color turn = r.getNextTurn();
172 BoardModel.moveResponse(b, errMsg, whites, blacks, turn, r.getAlert());
177 if ((b = findBoard(ui, r.getGameId())) != null) {
178 b.setWhitePlayer(r.getWhitePlayer());
179 b.setBlackPlayer(r.getBlackPlayer());
180 b.setPlayer(ui.getSettings().getUsername());
181 b.updateSummary(r.getSummary());
182 ui.setSelectedGameId(r.getGameId());
185 ui.setStatus("Joining " + r.getGameId() + " as " + r.getColor());
186 b = Rules.createBoard();
188 b, r.getBoard().getWhites(),
189 r.getBoard().getBlacks(),
192 b.setGameId(r.getGameId());
193 b.setWhitePlayer(r.getWhitePlayer());
194 b.setBlackPlayer(r.getBlackPlayer());
195 b.setPlayer(ui.getSettings().getUsername());
196 b.updateSummary(r.getSummary());
197 if (r.getColor() == Color.B) {
198 BoardModel.rotateBoard(b);
200 if (r.getMoves() != null) {
201 for (String move : r.getMoves()) {
202 Move m = BoardModel.MoveImpl.valueOf(move);
206 b.getMoves().clear();
208 ui.setSelectedGameId(b.getGameId());
209 ui.getBoards().add(b);
213 final Board b = findBoard(ui, r.getGameId());
217 b.updateSummary(r.getSummary());
218 final Move move = BoardModel.MoveImpl.valueOf(r.getFrom() + r.getTo());
219 final List<String> whites = r.getBoard().getWhites();
220 final List<String> blacks = r.getBoard().getBlacks();
221 final Color turn = r.getNextTurn();
222 BoardModel.moveUpdate(b, move, whites, blacks, turn, null);
228 private static Board findBoard(UI ui, String gameId) {
229 for (Board tmp : ui.getBoards()) {
230 if (tmp.getGameId().equals(gameId)) {
238 static void wasAnError(UI ui, Exception t) {
240 ui.setConnected(false);
241 ui.setDisconnected(true);
242 ui.setStatus("Disconnected.");
244 ui.setStatus("Error: " + t.getLocalizedMessage());
248 @Function static void joinGame(UI u, Game data) {
249 Request r = new Request();
250 r.setMsg(MsgType.JoinGame);
251 r.setObserver(false);
252 r.setGameId(data.getGameId());
256 @Function static void observeGame(UI u, Game data) {
257 Request r = new Request();
258 r.setMsg(MsgType.JoinGame);
260 r.setGameId(data.getGameId());
264 private static final Set<UI> ACTIVE = new HashSet<>();
265 @OnPropertyChange("connected") static void clearGames(UI m) {
266 if (m.isDisconnected()) {
267 m.getBoards().clear();
274 static UI findUI(Board b) {
275 for (UI ui : ACTIVE) {
276 if (ui.getBoards().contains(b)) {
283 @Function static void leave(UI ui, Board data) {
284 ui.getBoards().remove(data);
285 ui.setSelectedGameId(null);
288 @Function static void disconnect(UI ui) {
289 ui.queryServer(ui.getSettings().getUrl(), null);
290 ui.setStatus("Disconnecting...");
293 private static void verifyLogin(UI ui) {
294 ui.setStatus("Verifying user credentials...");
295 Request r = new Request();
296 r.setMsg(MsgType.CheckCredentials);
300 @Function static void reconnect(UI ui) {
301 final Settings s = ui.getSettings();
302 ui.setStatus("Connecting to the server...");
303 ui.queryServer(s.getUrl(), null);
307 public static void initialize(String... args) throws URISyntaxException, IOException {
309 ui.getSettings().read();
310 ui.setStatus("Ready.");
311 ui.setDisconnected(true);