1.1 --- a/freemarkerdor/pom.xml Fri Jan 01 20:53:17 2010 +0100
1.2 +++ b/freemarkerdor/pom.xml Thu Jan 07 23:20:33 2010 +0100
1.3 @@ -71,6 +71,12 @@
1.4 <artifactId>freemarker</artifactId>
1.5 <version>2.3.8</version>
1.6 </dependency>
1.7 + <dependency>
1.8 + <groupId>${project.groupId}</groupId>
1.9 + <artifactId>statistics</artifactId>
1.10 + <version>1.0</version>
1.11 + <scope>test</scope>
1.12 + </dependency>
1.13 </dependencies>
1.14 <build>
1.15 <plugins>
1.16 @@ -126,3 +132,4 @@
1.17
1.18
1.19
1.20 +
2.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Fri Jan 01 20:53:17 2010 +0100
2.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/UI.java Thu Jan 07 23:20:33 2010 +0100
2.3 @@ -38,6 +38,7 @@
2.4 import cz.xelfi.quoridor.IllegalPositionException;
2.5 import java.io.IOException;
2.6 import java.io.InputStream;
2.7 +import java.io.StringWriter;
2.8 import java.net.URI;
2.9 import java.util.Date;
2.10 import java.util.HashMap;
2.11 @@ -87,6 +88,7 @@
2.12 version = p.getProperty("version", "unknown"); // NOI18N
2.13 }
2.14 private static WebResource base;
2.15 + private static WebResource stat;
2.16
2.17 @Context
2.18 private HttpHeaders headers;
2.19 @@ -163,6 +165,7 @@
2.20 }
2.21 String txt = wr.accept(MediaType.TEXT_PLAIN).get(String.class);
2.22 Board b = Board.valueOf(txt);
2.23 +// Board b = new Board(txt);
2.24 ResponseBuilder resp = Response.ok();
2.25 CacheControl cc = new CacheControl();
2.26 cc.setNoCache(true);
2.27 @@ -220,16 +223,38 @@
2.28
2.29 Document doc = url.accept(MediaType.TEXT_XML).get(Document.class);
2.30 Board b;
2.31 + String t = doc.getElementsByTagName("board").item(0).getTextContent();
2.32 try {
2.33 b = Board.valueOf(doc.getElementsByTagName("board").item(0).getTextContent());
2.34 - } catch (IllegalPositionException ex) {
2.35 + } catch (Exception ex) {
2.36 +// b = new Board(t);
2.37 +// } catch (IllegalStateException ex) {
2.38 Exceptions.printStackTrace(ex);
2.39 b = Board.empty();
2.40 }
2.41 - v = viewable("game.fmt", doc, "message", msg, "format", format, "board", b);
2.42 + String bCode = null;
2.43 + try{
2.44 + bCode = stat.path("openings").path(b.getCode()+".check").queryParam("loginID", user.getId()).accept(MediaType.TEXT_PLAIN).get(String.class);
2.45 + }catch(Exception e){
2.46 + bCode = null;
2.47 + }
2.48 + if(bCode == null || "".equals(bCode))
2.49 + v = viewable("game.fmt", doc, "message", msg, "format", format, "board", b,"textPicture", boardToPicture(b));
2.50 + else
2.51 + v = viewable("game.fmt", doc, "message", msg, "format", format, "board", b,"textPicture", boardToPicture(b),"bCode", bCode);
2.52 return resp.entity(v).build();
2.53 }
2.54
2.55 + private static String boardToPicture(Board b) {
2.56 + StringWriter w = new StringWriter();
2.57 + try {
2.58 + b.write(w);
2.59 + } catch (IOException ex) {
2.60 + return ex.toString();
2.61 + }
2.62 + return w.toString();
2.63 + }
2.64 +
2.65 @GET
2.66 @Path("games/{id}/move")
2.67 @Produces(MediaType.TEXT_HTML)
2.68 @@ -346,7 +371,72 @@
2.69
2.70 return welcome(10);
2.71 }
2.72 +
2.73 + @GET
2.74 + @Path("elo")
2.75 + @Produces(MediaType.TEXT_HTML)
2.76 + public Response getEloList(){
2.77 + Viewable v = checkLogin();
2.78 + if (v != null) {
2.79 + return Response.status(Response.Status.FORBIDDEN).entity(v).build();
2.80 + }
2.81 + final Document got = stat.path("elo").path("list").accept(MediaType.TEXT_XML).get(Document.class);
2.82 + return Response.ok(viewable("elo.fmt", got)).build();
2.83 + }
2.84
2.85 + @GET
2.86 + @Path("openings")
2.87 + @Produces(MediaType.TEXT_HTML)
2.88 + public Response getOpeningRoot(){
2.89 + return getOpeningNode("ROOT");
2.90 + }
2.91 +
2.92 + @GET
2.93 + @Path("openings/{code}")
2.94 + @Produces(MediaType.TEXT_HTML)
2.95 + public Response getOpeningNode(@PathParam("code") String code){
2.96 + Viewable v = checkLogin();
2.97 + if (v != null) {
2.98 + return Response.status(Response.Status.FORBIDDEN).entity(v).build();
2.99 + }
2.100 + final Document got = stat.path("openings").path(code).queryParam("loginID", user.getId()).accept(MediaType.TEXT_XML).get(Document.class);
2.101 + Board b;
2.102 + try {
2.103 + b = Board.valueOf(got.getElementsByTagName("nodeCode").item(0).getTextContent());
2.104 + } catch (Exception ex) {
2.105 + Exceptions.printStackTrace(ex);
2.106 + b = Board.empty();
2.107 + }
2.108 + return Response.ok(viewable("openings.fmt", got, "whitefences",b.getPlayers().get(0).getFences(),"blackfences",b.getPlayers().get(1).getFences())).build();
2.109 + }
2.110 +
2.111 + @GET
2.112 + @Path("openings/{code}/{status}")
2.113 + @Produces(MediaType.TEXT_HTML)
2.114 + public Response getOpeningNodeGames(@PathParam("code") String code, @PathParam("status") String status){
2.115 + Viewable v = checkLogin();
2.116 + if (v != null) {
2.117 + return Response.status(Response.Status.FORBIDDEN).entity(v).build();
2.118 + }
2.119 + final Document got = stat.path("openings").path(code).path(status).queryParam("loginID", user.getId()).accept(MediaType.TEXT_XML).get(Document.class);
2.120 + return Response.ok(viewable("opening_games.fmt", got,"code",code,"color",status)).build();
2.121 + }
2.122 +
2.123 + @GET
2.124 + @Path("openings/{code}.png")
2.125 + @Produces("image/png")
2.126 + public Response getOpeningBoardImage(
2.127 + @PathParam("code") String code,
2.128 + @QueryParam("fieldSize") @DefaultValue("40") int fieldSize
2.129 + ) throws IllegalPositionException {
2.130 + Board b = Board.valueOf(code);
2.131 + ResponseBuilder resp = Response.ok();
2.132 + CacheControl cc = new CacheControl();
2.133 + cc.setNoCache(true);
2.134 + resp.cacheControl(cc);
2.135 + return resp.entity(BoardImage.draw(b, fieldSize)).build();
2.136 + }
2.137 +
2.138 //
2.139 // start the server
2.140 //
2.141 @@ -357,12 +447,13 @@
2.142 port = Integer.parseInt(args[0]);
2.143 }
2.144 String remoteAPI = args.length >= 2 ? args[1] : null;
2.145 + String remoteStatistics = args.length >= 3 ? args[2] : null;
2.146
2.147 Locale.setDefault(Locale.ROOT);
2.148
2.149 - Callable<Void> r = startServers(port, remoteAPI);
2.150 + Callable<Void> r = startServers(port, remoteAPI, remoteStatistics);
2.151
2.152 - if (args.length < 2 || !args[args.length - 1].equals("--kill")) {
2.153 + if (args.length < 3 || !args[args.length - 1].equals("--kill")) {
2.154 System.out.println("Hit enter to stop it...");
2.155 System.in.read();
2.156 } else {
2.157 @@ -374,8 +465,9 @@
2.158 System.exit(0);
2.159 }
2.160
2.161 - static Callable<Void> startServers(int port, String remoteAPI) throws Exception {
2.162 + static Callable<Void> startServers(int port, String remoteAPI, String remoteStatistics) throws Exception {
2.163 Client client = new Client();
2.164 + Client client1 = new Client();
2.165
2.166 final HttpServer apiServer;
2.167 if (remoteAPI == null) {
2.168 @@ -385,6 +477,12 @@
2.169 apiServer = null;
2.170 }
2.171
2.172 + if (remoteStatistics == null) {
2.173 + throw new IllegalArgumentException("Provide URL to API server"); // NOI18N
2.174 + } else {
2.175 + stat = client1.resource(new URI("http://localhost:9444"));
2.176 + }
2.177 +
2.178 ResourceConfig rc = new PackagesResourceConfig(
2.179 "cz.xelfi.quoridor.freemarkerdor"
2.180 );
3.1 --- a/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/W3CDocumentReader.java Fri Jan 01 20:53:17 2010 +0100
3.2 +++ b/freemarkerdor/src/main/java/cz/xelfi/quoridor/freemarkerdor/W3CDocumentReader.java Thu Jan 07 23:20:33 2010 +0100
3.3 @@ -1,6 +1,27 @@
3.4 /*
3.5 - * To change this template, choose Tools | Templates
3.6 - * and open the template in the editor.
3.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3.8 + *
3.9 + * The contents of this file are subject to the terms of either the GNU
3.10 + * General Public License Version 2 only ("GPL") or the Common
3.11 + * Development and Distribution License("CDDL") (collectively, the
3.12 + * "License"). You may not use this file except in compliance with the
3.13 + * License. You can obtain a copy of the License at
3.14 + * http://www.netbeans.org/cddl-gplv2.html
3.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
3.16 + * specific language governing permissions and limitations under the
3.17 + * License. When distributing the software, include this License Header
3.18 + * Notice in each file and include the License file at
3.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
3.20 + * particular file as subject to the "Classpath" exception as provided
3.21 + * by Sun in the GPL Version 2 section of the License file that
3.22 + * accompanied this code. If applicable, add the following below the
3.23 + * License Header, with the fields enclosed by brackets [] replaced by
3.24 + * your own identifying information:
3.25 + * "Portions Copyrighted [year] [name of copyright owner]"
3.26 + *
3.27 + * Contributor(s):
3.28 + *
3.29 + * Portions Copyrighted 2009 Jaroslav Tulach
3.30 */
3.31
3.32 package cz.xelfi.quoridor.freemarkerdor;
4.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle.properties Fri Jan 01 20:53:17 2010 +0100
4.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle.properties Thu Jan 07 23:20:33 2010 +0100
4.3 @@ -77,3 +77,10 @@
4.4 cs=\u010Cesky
4.5 LOCALE=en
4.6 CHANGE_LANGUAGE=Change!
4.7 +
4.8 +ELO_LIST=Elo rating
4.9 +ELO=Elo
4.10 +GAMES=Games
4.11 +OPENINGS=Openings
4.12 +WHITE_WON=White won
4.13 +BLACK_WON=Black won
5.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle_cs.properties Fri Jan 01 20:53:17 2010 +0100
5.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/Bundle_cs.properties Thu Jan 07 23:20:33 2010 +0100
5.3 @@ -89,3 +89,10 @@
5.4 LANGUAGE=Jazyk:
5.5 CHANGE_LANGUAGE=Zm\u011Bnit!
5.6 LOCALE=cs
5.7 +
5.8 +ELO_LIST=Elo rating
5.9 +ELO=Elo
5.10 +GAMES=Hry
5.11 +OPENINGS=Zah\u00E1jen\u00ED
5.12 +WHITE_WON=B\u00EDl\u00FD vyhr\u00E1l
5.13 +BLACK_WON=\u010Cern\u00FD vyhr\u00E1l
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
6.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/elo.fmt Thu Jan 07 23:20:33 2010 +0100
6.3 @@ -0,0 +1,43 @@
6.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
6.5 +<html>
6.6 + <head>
6.7 + <title>${bundle.ELO_LIST}</title>
6.8 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
6.9 + </head>
6.10 + <body bgcolor="white">
6.11 + <h3><a href="/">${bundle.TITLE_PLAIN}</a></h3>
6.12 + <h4>${bundle.ELO_LIST}</h4>
6.13 + <table border="1">
6.14 + <thead>
6.15 + <tr>
6.16 + <th>#</th>
6.17 + <th>${bundle.NAME}</th>
6.18 + <th>${bundle.ELO}</th>
6.19 + <th>${bundle.GAMES}</th>
6.20 + </tr>
6.21 + </thead>
6.22 + <tbody>
6.23 + <#assign cElo = 10000>
6.24 + <#assign index = 0>
6.25 + <#assign cIndex = index>
6.26 + <#list doc.eloList.elolist.* as item>
6.27 +
6.28 + <#assign index = index + 1>
6.29 + <#if cElo = item.@elo?number>
6.30 + <#else>
6.31 + <#assign cIndex = index>
6.32 + </#if>
6.33 + <#assign cElo = item.@elo?number>
6.34 +
6.35 + <tr>
6.36 + <td>${cIndex}</td>
6.37 + <td>${item.@player}</td>
6.38 + <td>${item.@elo?number}</td>
6.39 + <td>${item.@games}</td>
6.40 + </tr>
6.41 +
6.42 + </#list>
6.43 + </tbody>
6.44 + </table>
6.45 + </body>
6.46 +</html>
6.47 \ No newline at end of file
7.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Fri Jan 01 20:53:17 2010 +0100
7.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/game.fmt Thu Jan 07 23:20:33 2010 +0100
7.3 @@ -50,6 +50,7 @@
7.4 if (dir == 'W') r.x = -1;
7.5 return r;
7.6 }
7.7 + <#if board.currentPlayer??>
7.8 function paintPlayer() {
7.9 var fifth = fieldSize / 5;
7.10 var m1 = deltas(document.getElementById("pdir1").value.charAt(0));
7.11 @@ -72,7 +73,11 @@
7.12 var playerPos = {
7.13 x: ${board.currentPlayer.column},
7.14 y: ${board.currentPlayer.row}
7.15 - };
7.16 + };
7.17 + <#else>
7.18 + function paintPlayer() {
7.19 + }
7.20 + </#if>
7.21 </script>
7.22 </head>
7.23 <body bgcolor="white">
7.24 @@ -177,7 +182,7 @@
7.25 </#if>
7.26 <p>
7.27 <#if format?? && format = "text">
7.28 - <pre>${doc.game.board}</pre>
7.29 + <pre>${textPicture}</pre>
7.30 ${bundle.BOARD_VIEW}
7.31 <a href="/games/${doc.game.id.@id}?format=small">${bundle.BOARD_SMALL}</a>
7.32 <a href="/games/${doc.game.id.@id}?format=image">${bundle.BOARD_IMAGE}</a>
7.33 @@ -227,7 +232,9 @@
7.34 <a href="/games/${doc.game.id.@id}?move=${item.@index}">${item.@move}</a>
7.35 </#if>
7.36 </#macro>
7.37 -
7.38 + <#if (bCode??) >
7.39 + <h3><a href="/openings/${bCode}">${bundle.OPENINGS}</a></h3>
7.40 + </#if>
7.41 <h3><a href="/games/${doc.game.id.@id}?move=0">${bundle.MOVES}</a></h3>
7.42
7.43 <table border="0">
8.1 --- a/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt Fri Jan 01 20:53:17 2010 +0100
8.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/index.fmt Thu Jan 07 23:20:33 2010 +0100
8.3 @@ -167,6 +167,8 @@
8.4 </p>
8.5 </#if>
8.6
8.7 + <h5><a href="/elo">${bundle.ELO_LIST}</a></h5>
8.8 + <h5><a href="/openings">${bundle.OPENINGS}</a></h5>
8.9 <h5>${bundle.OPTIONS}</h5>
8.10
8.11 <form action="/options">
9.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
9.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/opening_games.fmt Thu Jan 07 23:20:33 2010 +0100
9.3 @@ -0,0 +1,36 @@
9.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
9.5 +<html>
9.6 + <head>
9.7 + <title>${bundle.OPENINGS} - ${bundle.GAMES}</title>
9.8 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
9.9 + </head>
9.10 + <body bgcolor="white">
9.11 + <h3><a href="/">${bundle.TITLE_PLAIN}</a></h3>
9.12 + <h4>${bundle.OPENINGS} - ${bundle.GAMES}</h4>
9.13 +
9.14 + <#macro before t>
9.15 + <#assign seconds = (t / 1000)?long/>
9.16 + <#assign minutes= (seconds / 60)?long/>
9.17 + <#assign hours= (minutes / 60)?long/>
9.18 + <#assign days= (hours / 24)?long/>
9.19 + <!--millis: ${t}, seconds: ${seconds}, minutes: ${minutes} hours: ${hours}, days: ${days} -->
9.20 + ${bundle("LastMove", t?int, seconds?int, minutes?int, hours?int, days?int)}
9.21 + </#macro>
9.22 + <#macro game game>
9.23 + ${bundle("gameWhiteBlack", game.@white?string, game.@black?string)}
9.24 + <a href="/games/${game.@id}/"><@before (now - game.@modified?number)?long/></a>
9.25 + <#if game.@comments?number != 0>
9.26 + ${bundle("comments", game.@comments?number)}
9.27 + </#if>
9.28 + </#macro>
9.29 +
9.30 + <ol>
9.31 + <#list doc.gameIds.* as g>
9.32 + <li>
9.33 + <@game g/>
9.34 + </li>
9.35 + </#list>
9.36 + </ol>
9.37 + <h4><a href="/openings/${code}">${bundle.OPENINGS}</a></h4>
9.38 + </body>
9.39 +</html>
9.40 \ No newline at end of file
10.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
10.2 +++ b/freemarkerdor/src/main/resources/cz/xelfi/quoridor/freemarkerdor/UI/openings.fmt Thu Jan 07 23:20:33 2010 +0100
10.3 @@ -0,0 +1,97 @@
10.4 +<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
10.5 +<html>
10.6 + <head>
10.7 + <title>${bundle.OPENINGS}</title>
10.8 + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
10.9 + </head>
10.10 + <body bgcolor="white">
10.11 + <h3><a href="/">${bundle.TITLE_PLAIN}</a></h3>
10.12 + <h4><a href="/openings">${bundle.OPENINGS}</a></h4>
10.13 + <p>
10.14 + <b>${bundle.WHITE}:</b> ${bundle("FENCES_LEFT", whitefences?number)}<br>
10.15 + <b>${bundle.BLACK}:</b> ${bundle("FENCES_LEFT", blackfences?number)}<br>
10.16 + </p>
10.17 + <div style="position: relative; height:180px;">
10.18 + <img style="position: absolute; left: 0; right: 0;"
10.19 + width="180" height="180 "
10.20 + src="/openings/${doc.openingNodeView.@code}.png?fieldSize=20"
10.21 + alt="${bundle.BOARD_TEXT}"
10.22 + >
10.23 + <div id="fence" style="position: absolute; left: 0; right: 0;"></div>
10.24 + <div id="player" style="position: absolute; left: 0; right: 0;"></div>
10.25 + </div>
10.26 +
10.27 + <#macro move item>
10.28 + <a href="/openings/${item.code}/">${item.move}</a>
10.29 + </#macro>
10.30 + <#macro games cnt gId status code>
10.31 + <#if (cnt?number = 0)>
10.32 + ${cnt?number}
10.33 + </#if>
10.34 + <#if (cnt?number = 1)>
10.35 + <a href="/games/${gId.@id}/">${cnt?number}</a>
10.36 + </#if>
10.37 + <#if (cnt?number > 1)>
10.38 + <a href="/openings/${code}/${status}">${cnt?number}</a>
10.39 + </#if>
10.40 + </#macro>
10.41 + <#if (doc.openingNodeView.children.*?size > 0)>
10.42 + <table border="1">
10.43 + <thead>
10.44 + <tr>
10.45 + <th>${bundle.MOVENUMBER}</th>
10.46 + <th>${bundle.WHITE_WON}</th>
10.47 + <th>${bundle.BLACK_WON}</th>
10.48 + </tr>
10.49 + </thead>
10.50 + <tbody>
10.51 + <#list doc.openingNodeView.children.* as item>
10.52 + <tr>
10.53 + <td><@move item/></td>
10.54 + <td><@games item.whiteWon item.whiteGame 'white' item.code/></td>
10.55 + <td><@games item.blackWon item.blackGame 'black' item.code/></td>
10.56 + </tr>
10.57 + </#list>
10.58 + </tbody>
10.59 + </table>
10.60 + </#if>
10.61 +
10.62 + <#macro before t>
10.63 + <#assign seconds = (t / 1000)?long/>
10.64 + <#assign minutes= (seconds / 60)?long/>
10.65 + <#assign hours= (minutes / 60)?long/>
10.66 + <#assign days= (hours / 24)?long/>
10.67 + <!--millis: ${t}, seconds: ${seconds}, minutes: ${minutes} hours: ${hours}, days: ${days} -->
10.68 + ${bundle("LastMove", t?int, seconds?int, minutes?int, hours?int, days?int)}
10.69 + </#macro>
10.70 + <#macro game game>
10.71 + ${bundle("gameWhiteBlack", game.@white?string, game.@black?string)}
10.72 + <a href="/games/${game.@id}/"><@before (now - game.@modified?number)?long/></a>
10.73 + <#if game.@status = "whiteWon">
10.74 + ${bundle.WHITE_WON}
10.75 + </#if>
10.76 + <#if game.@status = "blackWon">
10.77 + ${bundle.BLACK_WON}
10.78 + </#if>
10.79 + <#if game.@comments?number != 0>
10.80 + ${bundle("comments", game.@comments?number)}
10.81 + </#if>
10.82 + </#macro>
10.83 +
10.84 + <#if (doc.openingNodeView.@whiteCount?number + doc.openingNodeView.@blackCount?number > 0)>
10.85 + <h3>${bundle.GAMES}</h3>
10.86 + <ol>
10.87 + <#list doc.openingNodeView.whiteGames.* as g>
10.88 + <li>
10.89 + <@game g/>
10.90 + </li>
10.91 + </#list>
10.92 + <#list doc.openingNodeView.blackGames.* as g>
10.93 + <li>
10.94 + <@game g/>
10.95 + </li>
10.96 + </#list>
10.97 + </ol>
10.98 + </#if>
10.99 + </body>
10.100 +</html>
10.101 \ No newline at end of file
11.1 --- a/freemarkerdor/src/test/java/cz/xelfi/quoridor/freemarkerdor/UITest.java Fri Jan 01 20:53:17 2010 +0100
11.2 +++ b/freemarkerdor/src/test/java/cz/xelfi/quoridor/freemarkerdor/UITest.java Thu Jan 07 23:20:33 2010 +0100
11.3 @@ -33,6 +33,7 @@
11.4 import com.sun.jersey.core.util.MultivaluedMapImpl;
11.5 import com.sun.net.httpserver.HttpServer;
11.6 import cz.xelfi.quoridor.webidor.resources.Quoridor;
11.7 +import cz.xelfi.quoridor.statistics.resources.Statistics;
11.8 import java.awt.Image;
11.9 import java.io.File;
11.10 import java.io.FileOutputStream;
11.11 @@ -59,9 +60,11 @@
11.12 public class UITest extends Object {
11.13 private static File dir;
11.14 private static HttpServer stopAPI;
11.15 + private static HttpServer stopStatistics;
11.16 private static Callable<Void> stop;
11.17 private WebResource webResource;
11.18 private WebResource apiResource;
11.19 + private WebResource statResource;
11.20
11.21 public UITest() throws Exception {
11.22 }
11.23 @@ -74,7 +77,8 @@
11.24 dir.mkdirs();
11.25 System.setProperty("quoridor.dir", dir.getPath());
11.26 stopAPI = Quoridor.start(9990);
11.27 - stop = UI.startServers(9991, "http://localhost:9990");
11.28 + stopStatistics = Quoridor.start(9992);
11.29 + stop = UI.startServers(9991, "http://localhost:9990", "http://localhost:9992");
11.30
11.31 File passwd = new File(dir, "passwd");
11.32 FileOutputStream os = new FileOutputStream(passwd);
11.33 @@ -88,6 +92,7 @@
11.34 Client client = new Client();
11.35 webResource = client.resource(new URI("http://localhost:9991/"));
11.36 apiResource = client.resource(new URI("http://localhost:9990/"));
11.37 + statResource = client.resource(new URI("http://localhost:9992/"));
11.38 }
11.39
11.40 @AfterClass
11.41 @@ -126,6 +131,12 @@
11.42 assertTrue(serviceWadl.length() > 0);
11.43 }
11.44
11.45 + @Test public void testStatWadl() {
11.46 + String serviceWadl = statResource.path("application.wadl").
11.47 + accept(MediaTypes.WADL).get(String.class);
11.48 + assertTrue(serviceWadl.length() > 0);
11.49 + }
11.50 +
11.51 @Test public void testGetIndexPage() throws Exception {
11.52 String logJarda = apiResource.path("login").
11.53 queryParam("name", "Jarda").
12.1 --- a/pom.xml Fri Jan 01 20:53:17 2010 +0100
12.2 +++ b/pom.xml Thu Jan 07 23:20:33 2010 +0100
12.3 @@ -37,10 +37,11 @@
12.4 <module>quoridor</module>
12.5 <module>visidor</module>
12.6 <module>webidor</module>
12.7 + <module>statistics</module>
12.8 <module>freemarkerdor</module>
12.9 <module>emailer</module>
12.10 </modules>
12.11 <name>Quoridor related projects</name>
12.12 <description>Master project that agregates all quoridor related functionality.
12.13 </description>
12.14 -</project>
12.15 \ No newline at end of file
12.16 +</project>
13.1 --- a/quoridor/src/main/java/cz/xelfi/quoridor/Board.java Fri Jan 01 20:53:17 2010 +0100
13.2 +++ b/quoridor/src/main/java/cz/xelfi/quoridor/Board.java Thu Jan 07 23:20:33 2010 +0100
13.3 @@ -32,7 +32,6 @@
13.4 import java.io.IOException;
13.5 import java.io.Reader;
13.6 import java.io.StringReader;
13.7 -import java.io.StringWriter;
13.8 import java.io.Writer;
13.9 import java.util.ArrayList;
13.10 import java.util.Arrays;
13.11 @@ -42,6 +41,7 @@
13.12 import java.util.HashSet;
13.13 import java.util.List;
13.14 import java.util.Set;
13.15 +import java.util.TreeSet;
13.16 import java.util.regex.Matcher;
13.17 import java.util.regex.Pattern;
13.18
13.19 @@ -352,13 +352,8 @@
13.20 * @return board object, if the string can be read
13.21 * @throws IllegalPositionException if the string does not represent the board
13.22 */
13.23 - public static Board valueOf(String board) throws IllegalPositionException {
13.24 - try {
13.25 - return read(new StringReader(board));
13.26 - } catch (IOException ex) {
13.27 - // shall not happen, StringReader does not throw IOException
13.28 - throw (IllegalPositionException)new IllegalPositionException(ex.getMessage()).initCause(ex);
13.29 - }
13.30 + public static Board valueOf(String board) {
13.31 + return new Board(board);
13.32 }
13.33
13.34 private static int assertChar(String s, int pos, char... ch) throws IOException {
13.35 @@ -697,16 +692,9 @@
13.36 */
13.37 @Override
13.38 public String toString() {
13.39 - StringWriter w = new StringWriter();
13.40 - try {
13.41 - write(w);
13.42 - } catch (IOException ex) {
13.43 - return ex.toString();
13.44 - }
13.45 - return w.toString();
13.46 + return getCode();
13.47 }
13.48
13.49 -
13.50 //
13.51 // Validation methods
13.52 //
13.53 @@ -863,4 +851,92 @@
13.54 return 17 * y + x;
13.55 }
13.56
13.57 + Board(String hashCode) throws IllegalStateException{
13.58 + this.fences = new HashSet<Fence>();
13.59 + if((hashCode != null) && (hashCode.length() > 6)){
13.60 + char[]c = hashCode.toCharArray();
13.61 + this.players = Collections.unmodifiableList (Arrays.asList (new Player[] {
13.62 + new Player ((c[0]-'A')*2, (c[1]-'0')*2, c[2]-'a', Player.Direction.NORTH),
13.63 + new Player ((c[3]-'A')*2, (c[4]-'0')*2, c[5]-'a', Player.Direction.SOUTH),
13.64 + }));
13.65 + if(c[6]=='w'){
13.66 + this.turn = 0;
13.67 + this.winner = null;
13.68 + }else if(c[6]=='b'){
13.69 + this.turn = 1;
13.70 + this.winner = null;
13.71 + }else if(c[6]=='W'){
13.72 + this.turn = 0;
13.73 + this.winner = this.players.get(0);
13.74 + }else if(c[6]=='B'){
13.75 + this.turn = 1;
13.76 + this.winner = this.players.get(1);
13.77 + }else{
13.78 + this.turn = 0;
13.79 + this.winner = null;
13.80 + }
13.81 + for(int i=7; i<c.length;i+=2){
13.82 + int f = Integer.parseInt(hashCode.substring(i, i+2),16);
13.83 + Fence.Orientation o = Fence.Orientation.HORIZONTAL;
13.84 + if(f > 64){
13.85 + o = Fence.Orientation.VERTICAL;
13.86 + f -= 64;
13.87 + }
13.88 + fences.add(new Fence((f/8)*2+1, (f%8)*2+1,o));
13.89 + }
13.90 + }else{
13.91 + this.players = Collections.unmodifiableList (Arrays.asList (new Player[] {
13.92 + new Player (8,0,10,Player.Direction.NORTH),
13.93 + new Player (8,16,10,Player.Direction.SOUTH),
13.94 + }));
13.95 + this.winner = null;
13.96 + this.turn = 0;
13.97 + }
13.98 + try {
13.99 + this.occupied = computeOccupied (players, fences);
13.100 + } catch (IllegalPositionException ex) {
13.101 + throw new IllegalStateException (ex.getMessage ());
13.102 + }
13.103 + }
13.104 +
13.105 + public final String getCode() {
13.106 + Board b = this;
13.107 + StringBuilder sb = new StringBuilder();
13.108 + for(Player p: b.getPlayers()){
13.109 + sb.append((char)(p.getColumn() + 'A'));
13.110 + sb.append((char)(p.getRow() + '0'));
13.111 + sb.append((char)(p.getFences() + 'a'));
13.112 + }
13.113 + Player winner = b.getWinner();
13.114 + if(winner == null){
13.115 + if(b.players.indexOf(b.getCurrentPlayer())==0)
13.116 + sb.append('w');
13.117 + else if(b.players.indexOf(b.getCurrentPlayer())==1)
13.118 + sb.append('b');
13.119 + else
13.120 + sb.append('n');
13.121 + }else{
13.122 + if(b.players.indexOf(winner)==0)
13.123 + sb.append('W');
13.124 + else if(b.players.indexOf(winner)==1)
13.125 + sb.append('B');
13.126 + else
13.127 + sb.append('N');
13.128 + }
13.129 +
13.130 + TreeSet<Integer> fences = new TreeSet<Integer>();
13.131 + for(Fence f: b.getFences()){
13.132 + int a = (f.getColumn() - 'A')*8 + (f.getRow()-1);
13.133 + if(f.getOrientation().equals(Fence.Orientation.VERTICAL))
13.134 + a+=64;
13.135 + fences.add(a);
13.136 + }
13.137 + for(int f: fences){
13.138 + if(f<16)
13.139 + sb.append('0');
13.140 + sb.append(Integer.toHexString(f));
13.141 + }
13.142 + return sb.toString();
13.143 + }
13.144 +
13.145 }
14.1 --- a/quoridor/src/main/java/cz/xelfi/quoridor/Move.java Fri Jan 01 20:53:17 2010 +0100
14.2 +++ b/quoridor/src/main/java/cz/xelfi/quoridor/Move.java Thu Jan 07 23:20:33 2010 +0100
14.3 @@ -199,5 +199,26 @@
14.4 return hash;
14.5 }
14.6
14.7 + public Move getMirrorMove(){
14.8 + if(fence != null){
14.9 + return new Move(new Fence(16-fence.getX(), fence.getY(), fence.getOrientation()));
14.10 + }
14.11 + if(direction == null)
14.12 + return new Move();
14.13 + int dirSize = direction.length;
14.14 + Direction[] mirrorDirection = new Direction[dirSize];
14.15 + for(int i = 0; i < dirSize; i++){
14.16 + if(direction[i].equals(Direction.NORTH))
14.17 + mirrorDirection[i] = Direction.NORTH;
14.18 + else if(direction[i].equals(Direction.SOUTH))
14.19 + mirrorDirection[i] = Direction.SOUTH;
14.20 + else if(direction[i].equals(Direction.EAST))
14.21 + mirrorDirection[i] = Direction.WEST;
14.22 + else if(direction[i].equals(Direction.WEST))
14.23 + mirrorDirection[i] = Direction.EAST;
14.24 + }
14.25 + return new Move(mirrorDirection);
14.26 + }
14.27 +
14.28
14.29 }
15.1 --- a/quoridor/src/test/java/cz/xelfi/quoridor/BoardCase.java Fri Jan 01 20:53:17 2010 +0100
15.2 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/BoardCase.java Thu Jan 07 23:20:33 2010 +0100
15.3 @@ -27,6 +27,8 @@
15.4
15.5 import cz.xelfi.quoridor.Fence.Orientation;
15.6 import cz.xelfi.quoridor.Player.Direction;
15.7 +import java.io.IOException;
15.8 +import java.io.StringReader;
15.9 import java.util.List;
15.10 import junit.framework.TestCase;
15.11
15.12 @@ -200,6 +202,7 @@
15.13 "\n" +
15.14 " [S] \n";
15.15
15.16 + b = picture2board(b).toString();
15.17 Board begin = Board.valueOf(b);
15.18
15.19 try {
15.20 @@ -497,4 +500,8 @@
15.21 assertFalse(f4.equals(f5));
15.22 assertFalse(f3.equals(f5));
15.23 }
15.24 + static Board picture2board(String text) throws IOException, IllegalPositionException {
15.25 + StringReader sr = new StringReader(text);
15.26 + return Board.read(sr);
15.27 + }
15.28 }
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/SerializeCodeTest.java Thu Jan 07 23:20:33 2010 +0100
16.3 @@ -0,0 +1,73 @@
16.4 +/*
16.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
16.6 + *
16.7 + * The contents of this file are subject to the terms of either the GNU
16.8 + * General Public License Version 2 only ("GPL") or the Common
16.9 + * Development and Distribution License("CDDL") (collectively, the
16.10 + * "License"). You may not use this file except in compliance with the
16.11 + * License. You can obtain a copy of the License at
16.12 + * http://www.netbeans.org/cddl-gplv2.html
16.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16.14 + * specific language governing permissions and limitations under the
16.15 + * License. When distributing the software, include this License Header
16.16 + * Notice in each file and include the License file at
16.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
16.18 + * particular file as subject to the "Classpath" exception as provided
16.19 + * by Sun in the GPL Version 2 section of the License file that
16.20 + * accompanied this code. If applicable, add the following below the
16.21 + * License Header, with the fields enclosed by brackets [] replaced by
16.22 + * your own identifying information:
16.23 + * "Portions Copyrighted [year] [name of copyright owner]"
16.24 + *
16.25 + * Contributor(s):
16.26 + *
16.27 + * Portions Copyrighted 2009 Jaroslav Tulach
16.28 + */
16.29 +package cz.xelfi.quoridor;
16.30 +
16.31 +import cz.xelfi.quoridor.Player.Direction;
16.32 +import java.io.IOException;
16.33 +
16.34 +/** Basic tests in simple configuration.
16.35 + *
16.36 + * @author Jaroslav Tulach
16.37 + */
16.38 +public class SerializeCodeTest extends BoardCase {
16.39 + public SerializeCodeTest (String testName) {
16.40 + super (testName);
16.41 + }
16.42 +
16.43 + @Override
16.44 + protected Board move(Board b, int player, Direction... where) throws IllegalPositionException {
16.45 + try {
16.46 + Board read = reread(b);
16.47 + return read.move(read.getPlayers().get(player), where);
16.48 + } catch (IOException ex) {
16.49 + throw new IllegalStateException(ex);
16.50 + }
16.51 + }
16.52 + protected Board fence(Board b, int player, char x, int y, Fence.Orientation orie)
16.53 + throws IllegalPositionException {
16.54 + try {
16.55 + Board read = reread(b);
16.56 + return read.fence(read.getPlayers().get(player), x, y, orie);
16.57 + } catch (IOException ex) {
16.58 + throw new IllegalStateException(ex);
16.59 + }
16.60 + }
16.61 +
16.62 + @Override
16.63 + protected Board apply(Board b, Move move) throws IllegalPositionException {
16.64 + try {
16.65 + Board read = reread(b);
16.66 + return read.apply(move);
16.67 + } catch (IOException ex) {
16.68 + throw new IllegalStateException(ex);
16.69 + }
16.70 + }
16.71 +
16.72 + private Board reread(Board b) throws IOException, IllegalPositionException {
16.73 + return Board.valueOf(b.getCode());
16.74 + }
16.75 +
16.76 +}
17.1 --- a/quoridor/src/test/java/cz/xelfi/quoridor/SerializeTest.java Fri Jan 01 20:53:17 2010 +0100
17.2 +++ b/quoridor/src/test/java/cz/xelfi/quoridor/SerializeTest.java Thu Jan 07 23:20:33 2010 +0100
17.3 @@ -27,7 +27,6 @@
17.4
17.5 import cz.xelfi.quoridor.Player.Direction;
17.6 import java.io.IOException;
17.7 -import java.io.StringReader;
17.8 import java.io.StringWriter;
17.9
17.10 /** Basic tests in simple configuration.
17.11 @@ -72,7 +71,8 @@
17.12 StringWriter w = new StringWriter();
17.13 b.write(w);
17.14 w.close();
17.15 - return Board.valueOf(w.toString());
17.16 + return picture2board(w.toString());
17.17 + //return Board.valueOf(w.toString());
17.18 }
17.19
17.20 }
18.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
18.2 +++ b/statistics/all-zip.xml Thu Jan 07 23:20:33 2010 +0100
18.3 @@ -0,0 +1,19 @@
18.4 +<?xml version="1.0" encoding="UTF-8"?>
18.5 +<assembly>
18.6 + <id>all</id>
18.7 + <formats>
18.8 + <format>zip</format>
18.9 + </formats>
18.10 + <dependencySets>
18.11 + <dependencySet>
18.12 + <useProjectArtifact>false</useProjectArtifact>
18.13 + <outputDirectory>lib</outputDirectory>
18.14 + </dependencySet>
18.15 + </dependencySets>
18.16 + <files>
18.17 + <file>
18.18 + <source>target/statistics-${version}.jar</source>
18.19 + <outputDirectory>/</outputDirectory>
18.20 + </file>
18.21 + </files>
18.22 +</assembly>
19.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
19.2 +++ b/statistics/pom.xml Thu Jan 07 23:20:33 2010 +0100
19.3 @@ -0,0 +1,141 @@
19.4 +<?xml version="1.0" encoding="UTF-8"?>
19.5 +<project xmlns="http://maven.apache.org/POM/4.0.0"
19.6 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
19.7 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
19.8 + <modelVersion>4.0.0</modelVersion>
19.9 + <parent>
19.10 + <artifactId>all-quoridor</artifactId>
19.11 + <groupId>org.apidesign</groupId>
19.12 + <version>1.0</version>
19.13 + </parent>
19.14 + <groupId>org.apidesign</groupId>
19.15 + <artifactId>statistics</artifactId>
19.16 + <packaging>jar</packaging>
19.17 + <version>1.0</version>
19.18 + <name>Game Statistics</name>
19.19 + <url>http://maven.apache.org</url>
19.20 + <repositories>
19.21 + <repository>
19.22 + <id>maven2-repository.dev.java.net</id>
19.23 + <name>Java.net Repository for Maven</name>
19.24 + <url>http://download.java.net/maven/2/</url>
19.25 + <layout>default</layout>
19.26 + </repository>
19.27 + <repository>
19.28 + <id>maven-repository.dev.java.net</id>
19.29 + <name>Java.net Maven 1 Repository (legacy)</name>
19.30 + <url>http://download.java.net/maven/1</url>
19.31 + <layout>legacy</layout>
19.32 + </repository>
19.33 + </repositories>
19.34 + <dependencies>
19.35 +
19.36 + <dependency>
19.37 + <groupId>junit</groupId>
19.38 + <artifactId>junit</artifactId>
19.39 + <version>4.5</version>
19.40 + <scope>test</scope>
19.41 + </dependency>
19.42 + <dependency>
19.43 + <groupId>com.sun.jersey</groupId>
19.44 + <artifactId>jersey-core</artifactId>
19.45 + <version>1.1.0-ea</version>
19.46 + </dependency>
19.47 + <dependency>
19.48 + <groupId>com.sun.jersey</groupId>
19.49 + <artifactId>jersey-server</artifactId>
19.50 + <version>1.1.0-ea</version>
19.51 + </dependency>
19.52 + <dependency>
19.53 + <groupId>com.sun.jersey</groupId>
19.54 + <artifactId>jersey-json</artifactId>
19.55 + <version>1.1.0-ea</version>
19.56 + <type>jar</type>
19.57 + <exclusions>
19.58 + <exclusion>
19.59 + <artifactId>jaxb-api</artifactId>
19.60 + <groupId>javax.xml.bind</groupId>
19.61 + </exclusion>
19.62 + <exclusion>
19.63 + <artifactId>stax-api</artifactId>
19.64 + <groupId>stax</groupId>
19.65 + </exclusion>
19.66 + </exclusions>
19.67 + </dependency>
19.68 + <dependency>
19.69 + <groupId>com.sun.jersey.test.framework</groupId>
19.70 + <artifactId>jersey-test-framework</artifactId>
19.71 + <version>1.1.0-ea</version>
19.72 + <scope>test</scope>
19.73 + </dependency>
19.74 + <dependency>
19.75 + <groupId>org.apidesign</groupId>
19.76 + <artifactId>quoridor</artifactId>
19.77 + <version>1.0</version>
19.78 + <type>jar</type>
19.79 + </dependency>
19.80 + <dependency>
19.81 + <groupId>${project.groupId}</groupId>
19.82 + <artifactId>webidor</artifactId>
19.83 + <version>1.11</version>
19.84 + </dependency>
19.85 + </dependencies>
19.86 + <build>
19.87 + <plugins>
19.88 + <plugin>
19.89 + <groupId>org.apache.maven.plugins</groupId>
19.90 + <artifactId>maven-compiler-plugin</artifactId>
19.91 + <version>2.0.2</version>
19.92 + <configuration>
19.93 + <source>1.6</source>
19.94 + <target>1.6</target>
19.95 + </configuration>
19.96 + </plugin>
19.97 + <plugin>
19.98 + <groupId>org.codehaus.mojo</groupId>
19.99 + <artifactId>exec-maven-plugin</artifactId>
19.100 + <configuration>
19.101 + <mainClass>cz.xelfi.quoridor.statistics.resources.Statistics</mainClass>
19.102 + </configuration>
19.103 + </plugin>
19.104 + <plugin>
19.105 + <artifactId>maven-assembly-plugin</artifactId>
19.106 + <version>2.2-beta-2</version>
19.107 + <executions>
19.108 + <execution>
19.109 + <id>create-executable-jar</id>
19.110 + <phase>package</phase>
19.111 + <goals>
19.112 + <goal>single</goal>
19.113 + </goals>
19.114 + <configuration>
19.115 + <descriptors>
19.116 + <descriptor>all-zip.xml</descriptor>
19.117 + </descriptors>
19.118 + <finalName>statistics-${version}</finalName>
19.119 + </configuration>
19.120 + </execution>
19.121 + </executions>
19.122 + </plugin>
19.123 + <plugin>
19.124 + <groupId>org.apache.maven.plugins</groupId>
19.125 + <artifactId>maven-jar-plugin</artifactId>
19.126 + <configuration>
19.127 + <archive>
19.128 + <manifest>
19.129 + <addClasspath>true</addClasspath>
19.130 + <classpathPrefix>lib/</classpathPrefix>
19.131 + <mainClass>cz.xelfi.quoridor.statistics.resources.Statistics</mainClass>
19.132 + </manifest>
19.133 + </archive>
19.134 + </configuration>
19.135 + </plugin>
19.136 + </plugins>
19.137 + </build>
19.138 + <description>Server with API for games statistics</description>
19.139 +</project>
19.140 +
19.141 +
19.142 +
19.143 +
19.144 +
20.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
20.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/EloEntry.java Thu Jan 07 23:20:33 2010 +0100
20.3 @@ -0,0 +1,82 @@
20.4 +/*
20.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
20.6 + *
20.7 + * The contents of this file are subject to the terms of either the GNU
20.8 + * General Public License Version 2 only ("GPL") or the Common
20.9 + * Development and Distribution License("CDDL") (collectively, the
20.10 + * "License"). You may not use this file except in compliance with the
20.11 + * License. You can obtain a copy of the License at
20.12 + * http://www.netbeans.org/cddl-gplv2.html
20.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
20.14 + * specific language governing permissions and limitations under the
20.15 + * License. When distributing the software, include this License Header
20.16 + * Notice in each file and include the License file at
20.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
20.18 + * particular file as subject to the "Classpath" exception as provided
20.19 + * by Sun in the GPL Version 2 section of the License file that
20.20 + * accompanied this code. If applicable, add the following below the
20.21 + * License Header, with the fields enclosed by brackets [] replaced by
20.22 + * your own identifying information:
20.23 + * "Portions Copyrighted [year] [name of copyright owner]"
20.24 + *
20.25 + * Contributor(s):
20.26 + *
20.27 + * Portions Copyrighted 2010 Martin Rexa
20.28 + */
20.29 +
20.30 +package cz.xelfi.quoridor.statistics;
20.31 +
20.32 +import javax.xml.bind.annotation.XmlAttribute;
20.33 +import java.util.Comparator;
20.34 +/**
20.35 + *
20.36 + * @author Martin Rexa
20.37 + */
20.38 +public class EloEntry {
20.39 + String player;
20.40 + double elo;
20.41 + int games;
20.42 +
20.43 + public static final Comparator<EloEntry> BEST_FIRST = new BestFirst();
20.44 +
20.45 + EloEntry(){
20.46 + super();
20.47 + }
20.48 +
20.49 + EloEntry(String player, double elo, int games){
20.50 + super();
20.51 + this.player = player;
20.52 + this.elo = elo;
20.53 + this.games = games;
20.54 + }
20.55 +
20.56 + @XmlAttribute
20.57 + public String getPlayer(){
20.58 + return player;
20.59 + }
20.60 +
20.61 + @XmlAttribute
20.62 + public Double getElo(){
20.63 + return elo;
20.64 + }
20.65 +
20.66 + @XmlAttribute
20.67 + public Integer getGames(){
20.68 + return games;
20.69 + }
20.70 +
20.71 + public String toString(){
20.72 + return "Player: " + player + ", ELO: " + elo + ", Games: " + games;
20.73 + }
20.74 +
20.75 + private static final class BestFirst implements Comparator<EloEntry> {
20.76 + public int compare(EloEntry e1, EloEntry e2) {
20.77 + if(e1.elo > e2.elo)
20.78 + return -1;
20.79 + else if(e1.elo < e2.elo)
20.80 + return 1;
20.81 + else return e1.player.compareTo(e2.player);
20.82 + }
20.83 + }
20.84 +
20.85 +}
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/EloList.java Thu Jan 07 23:20:33 2010 +0100
21.3 @@ -0,0 +1,104 @@
21.4 +/*
21.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
21.6 + *
21.7 + * The contents of this file are subject to the terms of either the GNU
21.8 + * General Public License Version 2 only ("GPL") or the Common
21.9 + * Development and Distribution License("CDDL") (collectively, the
21.10 + * "License"). You may not use this file except in compliance with the
21.11 + * License. You can obtain a copy of the License at
21.12 + * http://www.netbeans.org/cddl-gplv2.html
21.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
21.14 + * specific language governing permissions and limitations under the
21.15 + * License. When distributing the software, include this License Header
21.16 + * Notice in each file and include the License file at
21.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
21.18 + * particular file as subject to the "Classpath" exception as provided
21.19 + * by Sun in the GPL Version 2 section of the License file that
21.20 + * accompanied this code. If applicable, add the following below the
21.21 + * License Header, with the fields enclosed by brackets [] replaced by
21.22 + * your own identifying information:
21.23 + * "Portions Copyrighted [year] [name of copyright owner]"
21.24 + *
21.25 + * Contributor(s):
21.26 + *
21.27 + * Portions Copyrighted 2010 Martin Rexa
21.28 + */
21.29 +
21.30 +package cz.xelfi.quoridor.statistics;
21.31 +
21.32 +import java.util.Map;
21.33 +import java.util.HashMap;
21.34 +import java.util.List;
21.35 +import java.util.Collections;
21.36 +import java.util.ArrayList;
21.37 +import javax.xml.bind.annotation.XmlElement;
21.38 +import javax.xml.bind.annotation.XmlElementWrapper;
21.39 +import javax.xml.bind.annotation.XmlRootElement;
21.40 +import javax.xml.bind.annotation.XmlAccessType;
21.41 +import javax.xml.bind.annotation.XmlAccessorType;
21.42 +/**
21.43 + *
21.44 + * @author Martin Rexa
21.45 + */
21.46 +@XmlRootElement
21.47 +@XmlAccessorType(XmlAccessType.FIELD)
21.48 +public class EloList {
21.49 + static int INITIAL_ELO = 1250;
21.50 + static int MAX_ELO_DIFF = 400;
21.51 + static int KVAL_START = 25;
21.52 + static int KVAL_FOLLOW = 10;
21.53 + static int KVAL_LIMIT = 30;
21.54 +
21.55 + private Map<String, Double> players;
21.56 + private Map<String, Integer> playerGames;
21.57 +
21.58 + public EloList () {
21.59 + players = new HashMap<String, Double>();
21.60 + playerGames = new HashMap<String, Integer>();
21.61 + }
21.62 +
21.63 + @XmlElementWrapper(name="elolist")
21.64 + @XmlElement(name="item")
21.65 + public List<EloEntry> getFinalList(){
21.66 + List<EloEntry> finalList = new ArrayList<EloEntry>();
21.67 + for (Map.Entry<String, Double> player : players.entrySet()){
21.68 + finalList.add(new EloEntry(player.getKey(), player.getValue(), playerGames.get(player.getKey())));
21.69 + }
21.70 + Collections.sort(finalList, EloEntry.BEST_FIRST);
21.71 + return finalList;
21.72 + }
21.73 +
21.74 + public EloList putResult(String winner, String looser){
21.75 + double wElo = getElo(winner);
21.76 + double lElo = getElo(looser);
21.77 +
21.78 + double eloDiff = wElo - lElo;
21.79 + if(eloDiff < - MAX_ELO_DIFF)
21.80 + eloDiff = - MAX_ELO_DIFF;
21.81 + if(eloDiff > MAX_ELO_DIFF)
21.82 + eloDiff = MAX_ELO_DIFF;
21.83 +
21.84 + double wDiff = Math.round(100 * getKVal(winner) * (1 - (1 / (1 + Math.pow(10, -eloDiff / MAX_ELO_DIFF)))));
21.85 + wDiff /= 100.0;
21.86 + double lDiff = Math.round(100 * getKVal(looser) * (0 - (1 / (1 + Math.pow(10, eloDiff / MAX_ELO_DIFF)))));
21.87 + lDiff /= 100.0;
21.88 +
21.89 + players.put(winner, wElo + wDiff);
21.90 + players.put(looser, lElo + lDiff);
21.91 + return this;
21.92 + }
21.93 +
21.94 + public double getElo(String player){
21.95 + Double elo = players.get(player);
21.96 + return (elo == null) ? INITIAL_ELO : elo;
21.97 + }
21.98 +
21.99 + private int getKVal(String player){
21.100 + Integer games = playerGames.get(player);
21.101 + int g = (games == null) ? 0 : games;
21.102 + // Side effect, method should not be called more times for the same game/player
21.103 + playerGames.put(player, g + 1);
21.104 + return g < KVAL_LIMIT ? KVAL_START : KVAL_FOLLOW;
21.105 + }
21.106 +
21.107 +}
22.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
22.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/JAXBContextResolver.java Thu Jan 07 23:20:33 2010 +0100
22.3 @@ -0,0 +1,58 @@
22.4 +/*
22.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
22.6 + *
22.7 + * The contents of this file are subject to the terms of either the GNU
22.8 + * General Public License Version 2 only ("GPL") or the Common
22.9 + * Development and Distribution License("CDDL") (collectively, the
22.10 + * "License"). You may not use this file except in compliance with the
22.11 + * License. You can obtain a copy of the License at
22.12 + * http://www.netbeans.org/cddl-gplv2.html
22.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
22.14 + * specific language governing permissions and limitations under the
22.15 + * License. When distributing the software, include this License Header
22.16 + * Notice in each file and include the License file at
22.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
22.18 + * particular file as subject to the "Classpath" exception as provided
22.19 + * by Sun in the GPL Version 2 section of the License file that
22.20 + * accompanied this code. If applicable, add the following below the
22.21 + * License Header, with the fields enclosed by brackets [] replaced by
22.22 + * your own identifying information:
22.23 + * "Portions Copyrighted [year] [name of copyright owner]"
22.24 + *
22.25 + * Contributor(s):
22.26 + *
22.27 + * Portions Copyrighted 2010 Martin Rexa
22.28 + */
22.29 +package cz.xelfi.quoridor.statistics;
22.30 +
22.31 +import com.sun.jersey.api.json.JSONConfiguration;
22.32 +import com.sun.jersey.api.json.JSONJAXBContext;
22.33 +import java.util.Arrays;
22.34 +import java.util.HashSet;
22.35 +import java.util.Set;
22.36 +import javax.ws.rs.ext.ContextResolver;
22.37 +import javax.ws.rs.ext.Provider;
22.38 +import javax.xml.bind.JAXBContext;
22.39 +
22.40 +/**
22.41 + *
22.42 + * @author Martin Rexa
22.43 + */
22.44 +@Provider
22.45 +public final class JAXBContextResolver implements ContextResolver<JAXBContext> {
22.46 +
22.47 + private final JAXBContext context;
22.48 +
22.49 + private final Set<Class> types;
22.50 +
22.51 + private final Class[] cTypes = {EloList.class, EloEntry.class, OpeningNodeView.class, OpeningNodeViewEntry.class};
22.52 +
22.53 + public JAXBContextResolver() throws Exception {
22.54 + this.types = new HashSet(Arrays.asList(cTypes));
22.55 + this.context = new JSONJAXBContext(JSONConfiguration.natural().build(), cTypes);
22.56 + }
22.57 +
22.58 + public JAXBContext getContext(Class<?> objectType) {
22.59 + return (types.contains(objectType)) ? context : null;
22.60 + }
22.61 +}
22.62 \ No newline at end of file
23.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
23.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/OpeningNodeView.java Thu Jan 07 23:20:33 2010 +0100
23.3 @@ -0,0 +1,129 @@
23.4 +/*
23.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
23.6 + *
23.7 + * The contents of this file are subject to the terms of either the GNU
23.8 + * General Public License Version 2 only ("GPL") or the Common
23.9 + * Development and Distribution License("CDDL") (collectively, the
23.10 + * "License"). You may not use this file except in compliance with the
23.11 + * License. You can obtain a copy of the License at
23.12 + * http://www.netbeans.org/cddl-gplv2.html
23.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
23.14 + * specific language governing permissions and limitations under the
23.15 + * License. When distributing the software, include this License Header
23.16 + * Notice in each file and include the License file at
23.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
23.18 + * particular file as subject to the "Classpath" exception as provided
23.19 + * by Sun in the GPL Version 2 section of the License file that
23.20 + * accompanied this code. If applicable, add the following below the
23.21 + * License Header, with the fields enclosed by brackets [] replaced by
23.22 + * your own identifying information:
23.23 + * "Portions Copyrighted [year] [name of copyright owner]"
23.24 + *
23.25 + * Contributor(s):
23.26 + *
23.27 + * Portions Copyrighted 2010 Martin Rexa
23.28 + */
23.29 +
23.30 +package cz.xelfi.quoridor.statistics;
23.31 +
23.32 +import cz.xelfi.quoridor.webidor.GameId;
23.33 +import cz.xelfi.quoridor.webidor.GameStatus;
23.34 +import cz.xelfi.quoridor.Move;
23.35 +import java.util.Set;
23.36 +import java.util.HashSet;
23.37 +import java.util.Map;
23.38 +import java.util.HashMap;
23.39 +import java.util.List;
23.40 +import java.util.ArrayList;
23.41 +import javax.xml.bind.annotation.XmlElement;
23.42 +import javax.xml.bind.annotation.XmlElementWrapper;
23.43 +import javax.xml.bind.annotation.XmlRootElement;
23.44 +//import javax.xml.bind.annotation.XmlAccessType;
23.45 +//import javax.xml.bind.annotation.XmlAccessorType;
23.46 +import javax.xml.bind.annotation.XmlAttribute;
23.47 +
23.48 +/**
23.49 + *
23.50 + * @author Martin Rexa
23.51 + */
23.52 +
23.53 +@XmlRootElement
23.54 +//@XmlAccessorType(XmlAccessType.FIELD)
23.55 +public class OpeningNodeView {
23.56 + @XmlAttribute
23.57 + String code;
23.58 + @XmlElementWrapper(name="whiteGames")
23.59 + @XmlElement(name="gameId")
23.60 + List<GameId> whiteGames;
23.61 + @XmlElementWrapper(name="blackGames")
23.62 + @XmlElement(name="gameId")
23.63 + List<GameId> blackGames;
23.64 + Map<Move, OpeningNodeViewEntry> entries;
23.65 + boolean empty;
23.66 +
23.67 + public OpeningNodeView(){
23.68 + }
23.69 +
23.70 + public OpeningNodeView(String code){
23.71 + this.code = code;
23.72 + entries = new HashMap<Move, OpeningNodeViewEntry>();
23.73 + whiteGames = new ArrayList<GameId>();
23.74 + blackGames = new ArrayList<GameId>();
23.75 + empty = true;
23.76 + }
23.77 +
23.78 + @XmlElement
23.79 + public String getNodeCode(){
23.80 + return code;
23.81 + }
23.82 +
23.83 + public void processGame(Move m, String code, GameId gId){
23.84 + OpeningNodeViewEntry e = entries.get(m);
23.85 + if(e == null){
23.86 + e = new OpeningNodeViewEntry(m,code);
23.87 + entries.put(m, e);
23.88 + }
23.89 + e.processGame(gId);
23.90 + empty = false;
23.91 + }
23.92 +
23.93 + @XmlElementWrapper(name="children")
23.94 + @XmlElement(name="item")
23.95 + public Set<OpeningNodeViewEntry> getChildren(){
23.96 + Set<OpeningNodeViewEntry> result = new HashSet<OpeningNodeViewEntry>();
23.97 + for(Map.Entry<Move, OpeningNodeViewEntry> e: entries.entrySet()){
23.98 + result.add(e.getValue());
23.99 + }
23.100 + return result;
23.101 + }
23.102 +
23.103 +
23.104 + public void addFinishedGame(GameId gId){
23.105 + if(gId.getStatus().equals(GameStatus.whiteWon))
23.106 + whiteGames.add(gId);
23.107 + if(gId.getStatus().equals(GameStatus.blackWon))
23.108 + blackGames.add(gId);
23.109 + empty = false;
23.110 + }
23.111 +
23.112 + @XmlAttribute
23.113 + public int getWhiteCount(){
23.114 + return whiteGames.size();
23.115 + }
23.116 +
23.117 + @XmlAttribute
23.118 + public int getBlackCount(){
23.119 + return blackGames.size();
23.120 + }
23.121 +
23.122 +
23.123 + @XmlAttribute
23.124 + public boolean getChildrenNotEmpty(){
23.125 + return !entries.isEmpty();
23.126 + }
23.127 +
23.128 + public boolean isEmpty(){
23.129 + return this.empty;
23.130 + }
23.131 +
23.132 +}
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/OpeningNodeViewEntry.java Thu Jan 07 23:20:33 2010 +0100
24.3 @@ -0,0 +1,86 @@
24.4 +/*
24.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
24.6 + *
24.7 + * The contents of this file are subject to the terms of either the GNU
24.8 + * General Public License Version 2 only ("GPL") or the Common
24.9 + * Development and Distribution License("CDDL") (collectively, the
24.10 + * "License"). You may not use this file except in compliance with the
24.11 + * License. You can obtain a copy of the License at
24.12 + * http://www.netbeans.org/cddl-gplv2.html
24.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
24.14 + * specific language governing permissions and limitations under the
24.15 + * License. When distributing the software, include this License Header
24.16 + * Notice in each file and include the License file at
24.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
24.18 + * particular file as subject to the "Classpath" exception as provided
24.19 + * by Sun in the GPL Version 2 section of the License file that
24.20 + * accompanied this code. If applicable, add the following below the
24.21 + * License Header, with the fields enclosed by brackets [] replaced by
24.22 + * your own identifying information:
24.23 + * "Portions Copyrighted [year] [name of copyright owner]"
24.24 + *
24.25 + * Contributor(s):
24.26 + *
24.27 + * Portions Copyrighted 2010 Martin Rexa
24.28 + */
24.29 +
24.30 +package cz.xelfi.quoridor.statistics;
24.31 +
24.32 +import cz.xelfi.quoridor.Move;
24.33 +import cz.xelfi.quoridor.webidor.GameId;
24.34 +import cz.xelfi.quoridor.webidor.GameStatus;
24.35 +import javax.xml.bind.annotation.XmlAccessType;
24.36 +import javax.xml.bind.annotation.XmlAccessorType;
24.37 +
24.38 +/**
24.39 + *
24.40 + * @author Martin Rexa
24.41 + */
24.42 +@XmlAccessorType(XmlAccessType.FIELD)
24.43 +public class OpeningNodeViewEntry extends Object{
24.44 + String move;
24.45 + String code;
24.46 + GameId gameId;
24.47 + GameId whiteGame;
24.48 + GameId blackGame;
24.49 + int whiteWon;
24.50 + int blackWon;
24.51 +
24.52 + public OpeningNodeViewEntry(){
24.53 + }
24.54 +
24.55 + public OpeningNodeViewEntry(Move m, String code){
24.56 + move = m.toString();
24.57 + this.code = code;
24.58 + }
24.59 +
24.60 + public void processGame(GameId gId){
24.61 + gameId = gId;
24.62 + if(gId.getStatus().equals(GameStatus.whiteWon)){
24.63 + whiteWon++;
24.64 + whiteGame = gId;
24.65 + }
24.66 + if(gId.getStatus().equals(GameStatus.blackWon)){
24.67 + blackWon++;
24.68 + blackGame = gId;
24.69 + }
24.70 + }
24.71 +
24.72 + @Override
24.73 + public boolean equals(Object obj){
24.74 + if (obj == null) {
24.75 + return false;
24.76 + }
24.77 + if (getClass() != obj.getClass()) {
24.78 + return false;
24.79 + }
24.80 + final OpeningNodeViewEntry other = (OpeningNodeViewEntry) obj;
24.81 + return this.move.equals(other.move);
24.82 + }
24.83 +
24.84 + @Override
24.85 + public String toString(){
24.86 + return move+": "+whiteWon+"/"+blackWon;
24.87 + }
24.88 +
24.89 +}
25.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
25.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/OpeningTree.java Thu Jan 07 23:20:33 2010 +0100
25.3 @@ -0,0 +1,107 @@
25.4 +/*
25.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
25.6 + *
25.7 + * The contents of this file are subject to the terms of either the GNU
25.8 + * General Public License Version 2 only ("GPL") or the Common
25.9 + * Development and Distribution License("CDDL") (collectively, the
25.10 + * "License"). You may not use this file except in compliance with the
25.11 + * License. You can obtain a copy of the License at
25.12 + * http://www.netbeans.org/cddl-gplv2.html
25.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
25.14 + * specific language governing permissions and limitations under the
25.15 + * License. When distributing the software, include this License Header
25.16 + * Notice in each file and include the License file at
25.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
25.18 + * particular file as subject to the "Classpath" exception as provided
25.19 + * by Sun in the GPL Version 2 section of the License file that
25.20 + * accompanied this code. If applicable, add the following below the
25.21 + * License Header, with the fields enclosed by brackets [] replaced by
25.22 + * your own identifying information:
25.23 + * "Portions Copyrighted [year] [name of copyright owner]"
25.24 + *
25.25 + * Contributor(s):
25.26 + *
25.27 + * Portions Copyrighted 2010 Martin Rexa
25.28 + */
25.29 +
25.30 +package cz.xelfi.quoridor.statistics;
25.31 +
25.32 +import cz.xelfi.quoridor.Board;
25.33 +import cz.xelfi.quoridor.Move;
25.34 +import cz.xelfi.quoridor.webidor.Game;
25.35 +import cz.xelfi.quoridor.webidor.CommentedMove;
25.36 +import cz.xelfi.quoridor.IllegalPositionException;
25.37 +import java.util.Map;
25.38 +import java.util.HashMap;
25.39 +
25.40 +/**
25.41 + *
25.42 + * @author Martin Rexa
25.43 + */
25.44 +public class OpeningTree {
25.45 + Map<String, OpeningTreeNode> nodes = new HashMap<String, OpeningTreeNode>();
25.46 + OpeningTreeNode root;
25.47 +
25.48 + public OpeningTree(){
25.49 + root = new OpeningTreeNode("ROOT");
25.50 + nodes.put("ROOT", root);
25.51 + }
25.52 +
25.53 + public OpeningTreeNode getRoot(){
25.54 + return root;
25.55 + }
25.56 +
25.57 + public OpeningTreeNode getNode(String hashCode){
25.58 + return nodes.get(hashCode);
25.59 + }
25.60 +
25.61 + public void processGame(Game game) throws IllegalPositionException{
25.62 + OpeningTreeNode node = root;
25.63 + OpeningTreeNode parentNode;
25.64 + OpeningTreeNode mirrorNode = root;
25.65 + OpeningTreeNode mirrorParentNode;
25.66 + Board board = Board.empty();
25.67 + Board mirrorBoard = Board.empty();
25.68 + root.addGame(game);
25.69 + for(CommentedMove move: game.getMoves()){
25.70 + if(!move.getMove().equals(Move.RESIGN)){
25.71 + parentNode = node;
25.72 + mirrorParentNode = mirrorNode;
25.73 + board = board.apply(move.getMove());
25.74 + mirrorBoard = mirrorBoard.apply(move.getMove().getMirrorMove());
25.75 + String hashCode = board.getCode();
25.76 + String mirrorHashCode = mirrorBoard.getCode();
25.77 + node = nodes.get(hashCode);
25.78 + if(node == null){
25.79 + node = new OpeningTreeNode(hashCode);
25.80 + nodes.put(hashCode, node);
25.81 + }
25.82 + node.addGame(game);
25.83 + mirrorNode = nodes.get(mirrorHashCode);
25.84 + if(mirrorHashCode.equals(hashCode)){
25.85 + if(mirrorNode == null){
25.86 + mirrorNode = node;
25.87 + }
25.88 + }else{
25.89 + if(mirrorNode == null){
25.90 + mirrorNode = new OpeningTreeNode(mirrorHashCode);
25.91 + nodes.put(mirrorHashCode, mirrorNode);
25.92 + }
25.93 + mirrorNode.addGame(game);
25.94 + }
25.95 + if(parentNode != null)
25.96 + parentNode.addChild(move.getMove(),node);
25.97 + if(mirrorParentNode != null){
25.98 + if(parentNode.equals(mirrorParentNode) && node.equals(mirrorNode))
25.99 + ;
25.100 + else
25.101 + mirrorParentNode.addChild(move.getMove().getMirrorMove(),mirrorNode);
25.102 + }
25.103 + }
25.104 + }
25.105 + node.addFinishedGame(game);
25.106 + if(!node.equals(mirrorNode))
25.107 + mirrorNode.addFinishedGame(game);
25.108 + }
25.109 +
25.110 +}
26.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
26.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/OpeningTreeNode.java Thu Jan 07 23:20:33 2010 +0100
26.3 @@ -0,0 +1,138 @@
26.4 +/*
26.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
26.6 + *
26.7 + * The contents of this file are subject to the terms of either the GNU
26.8 + * General Public License Version 2 only ("GPL") or the Common
26.9 + * Development and Distribution License("CDDL") (collectively, the
26.10 + * "License"). You may not use this file except in compliance with the
26.11 + * License. You can obtain a copy of the License at
26.12 + * http://www.netbeans.org/cddl-gplv2.html
26.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
26.14 + * specific language governing permissions and limitations under the
26.15 + * License. When distributing the software, include this License Header
26.16 + * Notice in each file and include the License file at
26.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
26.18 + * particular file as subject to the "Classpath" exception as provided
26.19 + * by Sun in the GPL Version 2 section of the License file that
26.20 + * accompanied this code. If applicable, add the following below the
26.21 + * License Header, with the fields enclosed by brackets [] replaced by
26.22 + * your own identifying information:
26.23 + * "Portions Copyrighted [year] [name of copyright owner]"
26.24 + *
26.25 + * Contributor(s):
26.26 + *
26.27 + * Portions Copyrighted 2010 Martin Rexa
26.28 + */
26.29 +
26.30 +package cz.xelfi.quoridor.statistics;
26.31 +
26.32 +import cz.xelfi.quoridor.webidor.Game;
26.33 +import cz.xelfi.quoridor.webidor.GameId;
26.34 +import cz.xelfi.quoridor.webidor.GameStatus;
26.35 +import cz.xelfi.quoridor.webidor.User;
26.36 +import cz.xelfi.quoridor.Move;
26.37 +import java.util.HashMap;
26.38 +import java.util.Map;
26.39 +import java.util.List;
26.40 +import java.util.ArrayList;
26.41 +import javax.xml.bind.annotation.XmlAttribute;
26.42 +
26.43 +/**
26.44 + *
26.45 + * @author Martin Rexa
26.46 + */
26.47 +public class OpeningTreeNode {
26.48 + @XmlAttribute
26.49 + String hashCode;
26.50 + List<GameId> gameIds;
26.51 + List<GameId> finishedGames;
26.52 + Map<Move, OpeningTreeNode> children;
26.53 +
26.54 + public OpeningTreeNode(){
26.55 + }
26.56 +
26.57 + public OpeningTreeNode(String hashCode){
26.58 + this.hashCode = hashCode;
26.59 + gameIds = new ArrayList<GameId>();
26.60 + finishedGames = new ArrayList<GameId>();
26.61 + children = new HashMap<Move,OpeningTreeNode>();
26.62 + }
26.63 +
26.64 + public OpeningTreeNode addGame(Game game){
26.65 + gameIds.add(game.getId());
26.66 + return this;
26.67 + }
26.68 +
26.69 + public OpeningTreeNode addFinishedGame(Game game){
26.70 + finishedGames.add(game.getId());
26.71 + return this;
26.72 + }
26.73 +
26.74 + public OpeningTreeNode addGameId(GameId gameId){
26.75 + gameIds.add(gameId);
26.76 + return this;
26.77 + }
26.78 +
26.79 + public OpeningTreeNode addChild(Move move, OpeningTreeNode child){
26.80 + children.put(move, child);
26.81 + return this;
26.82 + }
26.83 +
26.84 + public OpeningNodeView getView(User user){
26.85 + return getView(user.getId());
26.86 + }
26.87 +
26.88 + public OpeningNodeView getView(String userId){
26.89 + OpeningNodeView view = new OpeningNodeView(hashCode);
26.90 + for(Map.Entry<Move, OpeningTreeNode> e: children.entrySet()){
26.91 + for(GameId gId: e.getValue().gameIds){
26.92 + if(User.canSee(gId, userId)){
26.93 + view.processGame(e.getKey(), e.getValue().hashCode, gId);
26.94 + }
26.95 + }
26.96 + }
26.97 + for(GameId gId: finishedGames){
26.98 + view.addFinishedGame(gId);
26.99 + }
26.100 + return view;
26.101 + }
26.102 +
26.103 + public List<GameId> filterGames(String userId, GameStatus status){
26.104 + List<GameId> result = new ArrayList<GameId>();
26.105 + for(GameId gId: gameIds){
26.106 + if(User.canSee(gId, userId))
26.107 + if(gId.getStatus().equals(status))
26.108 + result.add(gId);
26.109 + }
26.110 + return result;
26.111 + }
26.112 +
26.113 + public List<GameId> getGameIds(){
26.114 + return gameIds;
26.115 + }
26.116 +
26.117 +// @XmlAttribute
26.118 +// @XmlElement
26.119 + public String getHashCode(){
26.120 + return this.hashCode;
26.121 + }
26.122 +
26.123 +
26.124 + @Override
26.125 + public boolean equals(Object obj) {
26.126 + if (obj == null) {
26.127 + return false;
26.128 + }
26.129 + if (getClass() != obj.getClass()) {
26.130 + return false;
26.131 + }
26.132 + OpeningTreeNode other = (OpeningTreeNode)obj;
26.133 + return hashCode.equals(other.hashCode);
26.134 + }
26.135 +
26.136 + @Override
26.137 + public int hashCode() {
26.138 + return hashCode.hashCode();
26.139 + }
26.140 +
26.141 +}
27.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
27.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/resources/Elo.java Thu Jan 07 23:20:33 2010 +0100
27.3 @@ -0,0 +1,75 @@
27.4 +/*
27.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
27.6 + *
27.7 + * The contents of this file are subject to the terms of either the GNU
27.8 + * General Public License Version 2 only ("GPL") or the Common
27.9 + * Development and Distribution License("CDDL") (collectively, the
27.10 + * "License"). You may not use this file except in compliance with the
27.11 + * License. You can obtain a copy of the License at
27.12 + * http://www.netbeans.org/cddl-gplv2.html
27.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
27.14 + * specific language governing permissions and limitations under the
27.15 + * License. When distributing the software, include this License Header
27.16 + * Notice in each file and include the License file at
27.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
27.18 + * particular file as subject to the "Classpath" exception as provided
27.19 + * by Sun in the GPL Version 2 section of the License file that
27.20 + * accompanied this code. If applicable, add the following below the
27.21 + * License Header, with the fields enclosed by brackets [] replaced by
27.22 + * your own identifying information:
27.23 + * "Portions Copyrighted [year] [name of copyright owner]"
27.24 + *
27.25 + * Contributor(s):
27.26 + *
27.27 + * Portions Copyrighted 2010 Martin Rexa
27.28 + */
27.29 +
27.30 +package cz.xelfi.quoridor.statistics.resources;
27.31 +
27.32 +import cz.xelfi.quoridor.statistics.EloList;
27.33 +import cz.xelfi.quoridor.webidor.Game;
27.34 +import cz.xelfi.quoridor.webidor.GameId;
27.35 +import cz.xelfi.quoridor.webidor.GameStatus;
27.36 +import javax.ws.rs.GET;
27.37 +import javax.ws.rs.Path;
27.38 +import javax.ws.rs.PathParam;
27.39 +import javax.ws.rs.Produces;
27.40 +import javax.ws.rs.core.MediaType;
27.41 +
27.42 +/**
27.43 + *
27.44 + * @author Martin Rexa
27.45 + */
27.46 +public final class Elo {
27.47 + private EloList list;
27.48 +
27.49 + public Elo(){
27.50 + list = new EloList();
27.51 + }
27.52 +
27.53 + public void processGame(Game game){
27.54 + GameId gId = game.getId();
27.55 + GameStatus status = gId.getStatus();
27.56 + if(status.equals(GameStatus.whiteWon)){
27.57 + list.putResult(gId.getWhite(), gId.getBlack());
27.58 + }else if(status.equals(GameStatus.blackWon)){
27.59 + list.putResult(gId.getBlack(), gId.getWhite());
27.60 + }
27.61 + }
27.62 +
27.63 + @GET
27.64 + @Path("list")
27.65 + @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
27.66 + public EloList getList(){
27.67 + return list;
27.68 + }
27.69 +
27.70 + @GET
27.71 + @Path("{username}")
27.72 + @Produces(MediaType.TEXT_PLAIN)
27.73 + public String getElo(@PathParam("username") String id){
27.74 + list.getElo(id);
27.75 + return Double.toString(list.getElo(id));
27.76 + }
27.77 +
27.78 +}
28.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
28.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/resources/Openings.java Thu Jan 07 23:20:33 2010 +0100
28.3 @@ -0,0 +1,107 @@
28.4 +/*
28.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
28.6 + *
28.7 + * The contents of this file are subject to the terms of either the GNU
28.8 + * General Public License Version 2 only ("GPL") or the Common
28.9 + * Development and Distribution License("CDDL") (collectively, the
28.10 + * "License"). You may not use this file except in compliance with the
28.11 + * License. You can obtain a copy of the License at
28.12 + * http://www.netbeans.org/cddl-gplv2.html
28.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
28.14 + * specific language governing permissions and limitations under the
28.15 + * License. When distributing the software, include this License Header
28.16 + * Notice in each file and include the License file at
28.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
28.18 + * particular file as subject to the "Classpath" exception as provided
28.19 + * by Sun in the GPL Version 2 section of the License file that
28.20 + * accompanied this code. If applicable, add the following below the
28.21 + * License Header, with the fields enclosed by brackets [] replaced by
28.22 + * your own identifying information:
28.23 + * "Portions Copyrighted [year] [name of copyright owner]"
28.24 + *
28.25 + * Contributor(s):
28.26 + *
28.27 + * Portions Copyrighted 2010 Martin Rexa
28.28 + */
28.29 +
28.30 +package cz.xelfi.quoridor.statistics.resources;
28.31 +
28.32 +import cz.xelfi.quoridor.IllegalPositionException;
28.33 +import cz.xelfi.quoridor.webidor.Game;
28.34 +import cz.xelfi.quoridor.webidor.GameId;
28.35 +import cz.xelfi.quoridor.statistics.OpeningTree;
28.36 +import cz.xelfi.quoridor.statistics.OpeningTreeNode;
28.37 +import cz.xelfi.quoridor.statistics.OpeningNodeView;
28.38 +import cz.xelfi.quoridor.webidor.GameStatus;
28.39 +import java.util.List;
28.40 +import javax.ws.rs.GET;
28.41 +import javax.ws.rs.Path;
28.42 +import javax.ws.rs.PathParam;
28.43 +import javax.ws.rs.Produces;
28.44 +import javax.ws.rs.QueryParam;
28.45 +import javax.ws.rs.DefaultValue;
28.46 +import javax.ws.rs.core.MediaType;
28.47 +
28.48 +/**
28.49 + *
28.50 + * @author Martin Rexa
28.51 + */
28.52 +public class Openings {
28.53 + OpeningTree tree;
28.54 +
28.55 + public Openings(){
28.56 + tree = new OpeningTree();
28.57 + }
28.58 +
28.59 + public void processGame(Game game) {
28.60 + try{
28.61 + tree.processGame(game);
28.62 + }catch (IllegalPositionException e){
28.63 + e.printStackTrace();
28.64 + }
28.65 + }
28.66 +
28.67 + @GET
28.68 + @Path("{nodeId}")
28.69 + @Produces({ MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
28.70 + public OpeningNodeView getNode(@QueryParam("loginID") @DefaultValue("") String loginId,
28.71 + @PathParam("nodeId") String nodeId){
28.72 + OpeningTreeNode node = tree.getNode(nodeId);
28.73 + if(node == null)
28.74 + node = tree.getRoot();
28.75 + return node.getView(loginId);
28.76 + }
28.77 +
28.78 + @GET
28.79 + @Path("{nodeId}.check")
28.80 + @Produces({ MediaType.TEXT_PLAIN })
28.81 + public String checkNode(@QueryParam("loginID") @DefaultValue("") String loginId,
28.82 + @PathParam("nodeId") String nodeId){
28.83 + OpeningTreeNode node = tree.getNode(nodeId);
28.84 + if(node == null)
28.85 + return "";
28.86 + if(node.getView(loginId).isEmpty())
28.87 + return "";
28.88 + else
28.89 + return nodeId;
28.90 + }
28.91 +
28.92 + @GET
28.93 + @Path("{nodeId}/{status}")
28.94 + @Produces({MediaType.APPLICATION_JSON, MediaType.TEXT_XML })
28.95 + public List<GameId> listGames(
28.96 + @DefaultValue("") @QueryParam("loginID") String loginId,
28.97 + @PathParam("nodeId") String nodeId,
28.98 + @DefaultValue("") @PathParam("status") String status
28.99 + ) {
28.100 + OpeningTreeNode node = tree.getNode(nodeId);
28.101 + if(node == null)
28.102 + return null;
28.103 + if("white".equals(status))
28.104 + return node.filterGames(loginId, GameStatus.whiteWon);
28.105 + else if("black".equals(status))
28.106 + return node.filterGames(loginId, GameStatus.blackWon);
28.107 + else
28.108 + return null;
28.109 + }
28.110 +}
29.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
29.2 +++ b/statistics/src/main/java/cz/xelfi/quoridor/statistics/resources/Statistics.java Thu Jan 07 23:20:33 2010 +0100
29.3 @@ -0,0 +1,156 @@
29.4 +/*
29.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
29.6 + *
29.7 + * The contents of this file are subject to the terms of either the GNU
29.8 + * General Public License Version 2 only ("GPL") or the Common
29.9 + * Development and Distribution License("CDDL") (collectively, the
29.10 + * "License"). You may not use this file except in compliance with the
29.11 + * License. You can obtain a copy of the License at
29.12 + * http://www.netbeans.org/cddl-gplv2.html
29.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
29.14 + * specific language governing permissions and limitations under the
29.15 + * License. When distributing the software, include this License Header
29.16 + * Notice in each file and include the License file at
29.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
29.18 + * particular file as subject to the "Classpath" exception as provided
29.19 + * by Sun in the GPL Version 2 section of the License file that
29.20 + * accompanied this code. If applicable, add the following below the
29.21 + * License Header, with the fields enclosed by brackets [] replaced by
29.22 + * your own identifying information:
29.23 + * "Portions Copyrighted [year] [name of copyright owner]"
29.24 + *
29.25 + * Contributor(s):
29.26 + *
29.27 + * Portions Copyrighted 2010 Martin Rexa
29.28 + */
29.29 +
29.30 +package cz.xelfi.quoridor.statistics.resources;
29.31 +
29.32 +import com.sun.jersey.api.container.httpserver.HttpServerFactory;
29.33 +import com.sun.jersey.api.core.PackagesResourceConfig;
29.34 +import com.sun.jersey.api.core.ResourceConfig;
29.35 +import com.sun.jersey.spi.resource.Singleton;
29.36 +import com.sun.net.httpserver.HttpServer;
29.37 +import java.io.File;
29.38 +import java.io.IOException;
29.39 +import java.util.Comparator;
29.40 +import java.util.List;
29.41 +import java.util.Collections;
29.42 +import java.net.ServerSocket;
29.43 +import javax.ws.rs.Path;
29.44 +import cz.xelfi.quoridor.webidor.resources.Games;
29.45 +import cz.xelfi.quoridor.webidor.Game;
29.46 +
29.47 +/**
29.48 + *
29.49 + * @author Martin Rexa
29.50 + */
29.51 +@Path("/")
29.52 +@Singleton
29.53 +public class Statistics {
29.54 + static final Comparator<Game> OLDEST_FIRST = new OldestFirst();
29.55 + static Elo elo;
29.56 + static Openings openings;
29.57 +
29.58 + @Path("elo")
29.59 + public Elo getElo() {
29.60 + return elo;
29.61 + }
29.62 +
29.63 + @Path("openings")
29.64 + public Openings getOpenings() {
29.65 + return openings;
29.66 + }
29.67 +
29.68 + public static void main( String[] args ) throws IOException, InterruptedException
29.69 + {
29.70 + int port = 9444;
29.71 + // timeout between reprocessing games in miliseconds
29.72 +// long timeout = 1000 * 60 * 60;
29.73 + long timeout = 1000 * 10;
29.74 +
29.75 + try {
29.76 + port = Integer.parseInt(args[0]);
29.77 + } catch (Exception ex) {
29.78 + // OK
29.79 + }
29.80 +
29.81 + if (System.getProperty("quoridor.dir") == null) {
29.82 + File home = new File(System.getProperty("user.home"));
29.83 + File quoridor = new File(home, ".quoridor");
29.84 + System.setProperty("quoridor.dir", quoridor.getPath());
29.85 + }
29.86 +
29.87 + processGames();
29.88 + HttpServer s = start(port);
29.89 + System.out.println("Statistics started at port " + port);
29.90 + Object monitor = new Object();
29.91 + for(;;){
29.92 + synchronized (monitor) {
29.93 + monitor.wait(timeout);
29.94 + }
29.95 + processGames();
29.96 + }
29.97 + }
29.98 +
29.99 + public static HttpServer start(int port) throws IOException {
29.100 + if (port == -1) {
29.101 + ServerSocket ss = new ServerSocket(0);
29.102 + port =ss.getLocalPort();
29.103 + ss.close();
29.104 + }
29.105 + final String baseUri = "http://localhost:" + port + "/";
29.106 +
29.107 + if (System.getProperty("quoridor.dir") == null) {
29.108 + File home = new File(System.getProperty("user.home"));
29.109 + File quoridor = new File(home, ".quoridor");
29.110 + System.setProperty("quoridor.dir", quoridor.getPath());
29.111 + }
29.112 +
29.113 + ResourceConfig rc = new PackagesResourceConfig("cz.xelfi.quoridor.statistics");
29.114 + HttpServer server = HttpServerFactory.create(baseUri, rc);
29.115 + server.start();
29.116 + return server;
29.117 + }
29.118 +
29.119 + public static void processGames(){
29.120 + Elo eloTmp = new Elo();
29.121 + Openings openingsTmp = new Openings();
29.122 +
29.123 + final String prop = System.getProperty("quoridor.dir"); // NOI18N
29.124 + if (prop == null) {
29.125 + throw new IllegalStateException("quoridor.dir property must be specified"); // NOI18N
29.126 + }
29.127 + File path = new File(prop);
29.128 + path.mkdirs();
29.129 + File fGames = new File(path, "games");
29.130 + //fGames.mkdirs();
29.131 + Games games = new Games(fGames, null);
29.132 + List<Game> lGames = games.getGames();
29.133 + Collections.sort(lGames, OLDEST_FIRST);
29.134 +
29.135 + // process games
29.136 + for(Game g: lGames){
29.137 + if(g.getId().isFinished()){
29.138 + eloTmp.processGame(g);
29.139 + openingsTmp.processGame(g);
29.140 + }
29.141 + }
29.142 +
29.143 + elo = eloTmp;
29.144 + openings = openingsTmp;
29.145 + }
29.146 +
29.147 + private static final class OldestFirst implements Comparator<Game> {
29.148 + public int compare(Game g1, Game g2) {
29.149 + if(g1.getId() == g2.getId())
29.150 + return 0;
29.151 + long diff = g2.getId().getModified() - g1.getId().getModified();
29.152 + if (diff != 0) {
29.153 + return diff < 0 ? -1 : 1;
29.154 + }
29.155 + return g1.getId().getId().compareTo(g2.getId().getId());
29.156 + }
29.157 + }
29.158 +
29.159 +}
30.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
30.2 +++ b/statistics/src/test/java/cz/xelfi/quoridor/statistics/EloTest.java Thu Jan 07 23:20:33 2010 +0100
30.3 @@ -0,0 +1,53 @@
30.4 +/*
30.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
30.6 + *
30.7 + * The contents of this file are subject to the terms of either the GNU
30.8 + * General Public License Version 2 only ("GPL") or the Common
30.9 + * Development and Distribution License("CDDL") (collectively, the
30.10 + * "License"). You may not use this file except in compliance with the
30.11 + * License. You can obtain a copy of the License at
30.12 + * http://www.netbeans.org/cddl-gplv2.html
30.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
30.14 + * specific language governing permissions and limitations under the
30.15 + * License. When distributing the software, include this License Header
30.16 + * Notice in each file and include the License file at
30.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
30.18 + * particular file as subject to the "Classpath" exception as provided
30.19 + * by Sun in the GPL Version 2 section of the License file that
30.20 + * accompanied this code. If applicable, add the following below the
30.21 + * License Header, with the fields enclosed by brackets [] replaced by
30.22 + * your own identifying information:
30.23 + * "Portions Copyrighted [year] [name of copyright owner]"
30.24 + *
30.25 + * Contributor(s):
30.26 + *
30.27 + * Portions Copyrighted 2010 Martin Rexa
30.28 + */
30.29 +
30.30 +package cz.xelfi.quoridor.statistics;
30.31 +
30.32 +import org.junit.Test;
30.33 +import static org.junit.Assert.*;
30.34 +
30.35 +/**
30.36 + *
30.37 + * @author Martin Rexa
30.38 + */
30.39 +public class EloTest extends Object {
30.40 +
30.41 + public EloTest() throws Exception {
30.42 + }
30.43 +
30.44 + @Test public void testEloList() throws Exception {
30.45 + EloList eloList = new EloList();
30.46 + eloList.putResult("p1", "p2");
30.47 + assertFalse("empty list", eloList.getFinalList().isEmpty());
30.48 + eloList.putResult("p3", "p4");
30.49 + assertTrue("wrong list", eloList.getFinalList().get(0).getElo().equals(eloList.getFinalList().get(1).getElo()));
30.50 + eloList.putResult("p2", "p1");
30.51 + eloList.putResult("p2", "p1");
30.52 + eloList.putResult("p2", "p1");
30.53 + assertTrue("wrong list", eloList.getFinalList().get(0).player.equals("p2"));
30.54 + }
30.55 +
30.56 +}
31.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
31.2 +++ b/statistics/src/test/java/cz/xelfi/quoridor/statistics/OpeningsTest.java Thu Jan 07 23:20:33 2010 +0100
31.3 @@ -0,0 +1,129 @@
31.4 +/*
31.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
31.6 + *
31.7 + * The contents of this file are subject to the terms of either the GNU
31.8 + * General Public License Version 2 only ("GPL") or the Common
31.9 + * Development and Distribution License("CDDL") (collectively, the
31.10 + * "License"). You may not use this file except in compliance with the
31.11 + * License. You can obtain a copy of the License at
31.12 + * http://www.netbeans.org/cddl-gplv2.html
31.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
31.14 + * specific language governing permissions and limitations under the
31.15 + * License. When distributing the software, include this License Header
31.16 + * Notice in each file and include the License file at
31.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
31.18 + * particular file as subject to the "Classpath" exception as provided
31.19 + * by Sun in the GPL Version 2 section of the License file that
31.20 + * accompanied this code. If applicable, add the following below the
31.21 + * License Header, with the fields enclosed by brackets [] replaced by
31.22 + * your own identifying information:
31.23 + * "Portions Copyrighted [year] [name of copyright owner]"
31.24 + *
31.25 + * Contributor(s):
31.26 + *
31.27 + * Portions Copyrighted 2010 Martin Rexa
31.28 + */
31.29 +
31.30 +package cz.xelfi.quoridor.statistics;
31.31 +
31.32 +import cz.xelfi.quoridor.Fence.Orientation;
31.33 +import org.junit.Test;
31.34 +import static org.junit.Assert.*;
31.35 +import cz.xelfi.quoridor.Move;
31.36 +import cz.xelfi.quoridor.webidor.Game;
31.37 +import java.util.Map;
31.38 +
31.39 +/**
31.40 + *
31.41 + * @author Martin Rexa
31.42 + */
31.43 +public class OpeningsTest extends Object {
31.44 +
31.45 + public OpeningsTest() throws Exception {
31.46 + }
31.47 +
31.48 + @Test public void testMirrorMoves() throws Exception {
31.49 + assertEquals("bad symetric move", Move.NORTH.getMirrorMove(), Move.NORTH);
31.50 + assertEquals("bad symetric move", Move.SOUTH.getMirrorMove(), Move.SOUTH);
31.51 + assertEquals("bad symetric move", Move.WEST.getMirrorMove(), Move.EAST);
31.52 + assertEquals("bad symetric move", Move.EAST.getMirrorMove(), Move.WEST);
31.53 + assertEquals("bad symetric move", Move.fence('A', 1, Orientation.HORIZONTAL).getMirrorMove(), Move.fence('H', 1, Orientation.HORIZONTAL));
31.54 + assertEquals("bad symetric move", Move.fence('D', 3, Orientation.VERTICAL).getMirrorMove(), Move.fence('E', 3, Orientation.VERTICAL));
31.55 + }
31.56 +
31.57 + @Test public void testMirrorJump() throws Exception {
31.58 + Game g = new Game("w","b");
31.59 + g.apply("w", Move.NORTH, new java.util.Date());
31.60 + g.apply("b", Move.SOUTH, new java.util.Date());
31.61 + g.apply("w", Move.NORTH, new java.util.Date());
31.62 + g.apply("b", Move.SOUTH, new java.util.Date());
31.63 + g.apply("w", Move.NORTH, new java.util.Date());
31.64 + g.apply("b", Move.SOUTH, new java.util.Date());
31.65 + g.apply("w", Move.NORTH, new java.util.Date());
31.66 + g.apply("b", Move.EAST, new java.util.Date());
31.67 + g.apply("w", Move.NORTH, new java.util.Date());
31.68 + g.apply("b", Move.valueOf("WW"), new java.util.Date());
31.69 + g.apply("w", Move.RESIGN, new java.util.Date());
31.70 + OpeningTree t = new OpeningTree();
31.71 + t.processGame(g);
31.72 + OpeningTreeNode n = t.root;
31.73 + n = n.children.get(Move.NORTH);
31.74 + n = n.children.get(Move.SOUTH);
31.75 + n = n.children.get(Move.NORTH);
31.76 + n = n.children.get(Move.SOUTH);
31.77 + n = n.children.get(Move.NORTH);
31.78 + n = n.children.get(Move.SOUTH);
31.79 + n = n.children.get(Move.NORTH);
31.80 + n = n.children.get(Move.WEST);
31.81 + n = n.children.get(Move.NORTH);
31.82 + n = n.children.get(Move.valueOf("EE"));
31.83 + assertEquals("bad number of children", n.children.size(), 0);
31.84 + for(Map.Entry e: n.children.entrySet()){
31.85 + System.out.println(e.getKey());
31.86 + }
31.87 + }
31.88 +
31.89 + @Test public void testOpeningTreeNodes() throws Exception {
31.90 + OpeningTree t = new OpeningTree();
31.91 + assertEquals("bad number of nodes", t.nodes.size(), 1);
31.92 + Game g = new Game("w","b");
31.93 + g.apply("w", Move.NORTH, new java.util.Date());
31.94 + g.apply("b", Move.SOUTH, new java.util.Date());
31.95 + g.apply("w", Move.EAST, new java.util.Date());
31.96 + g.apply("b", Move.EAST, new java.util.Date());
31.97 + g.apply("w", Move.WEST, new java.util.Date());
31.98 + g.apply("b", Move.WEST, new java.util.Date());
31.99 + g.apply("w", Move.RESIGN, new java.util.Date());
31.100 + t.processGame(g);
31.101 + assertEquals("bad number of nodes", t.nodes.size(), 9);
31.102 + g = new Game("w","b");
31.103 + g.apply("w", Move.NORTH, new java.util.Date());
31.104 + g.apply("b", Move.SOUTH, new java.util.Date());
31.105 + g.apply("w", Move.fence('A', 1, Orientation.HORIZONTAL), new java.util.Date());
31.106 + g.apply("b", Move.fence('C', 1, Orientation.VERTICAL), new java.util.Date());
31.107 + g.apply("w", Move.RESIGN, new java.util.Date());
31.108 + t.processGame(g);
31.109 + assertEquals("bad number of nodes", t.nodes.size(), 13);
31.110 + g = new Game("w","b");
31.111 + g.apply("w", Move.NORTH, new java.util.Date());
31.112 + g.apply("b", Move.SOUTH, new java.util.Date());
31.113 + g.apply("w", Move.fence('C', 1, Orientation.VERTICAL), new java.util.Date());
31.114 + g.apply("b", Move.fence('A', 1, Orientation.HORIZONTAL), new java.util.Date());
31.115 + g.apply("w", Move.RESIGN, new java.util.Date());
31.116 + t.processGame(g);
31.117 + assertEquals("bad number of nodes", t.nodes.size(), 15);
31.118 + OpeningTreeNode n = t.root;
31.119 + n = n.children.get(Move.NORTH);
31.120 + n = n.children.get(Move.SOUTH);
31.121 + OpeningTreeNode n1 = n;
31.122 + n = n.children.get(Move.WEST);
31.123 + n = n.children.get(Move.WEST);
31.124 + n = n.children.get(Move.EAST);
31.125 + n = n.children.get(Move.EAST);
31.126 + assertEquals("different nodes", n.hashCode, n1.hashCode);
31.127 + n = n.children.get(Move.fence('F', 1, Orientation.VERTICAL));
31.128 + n = n.children.get(Move.fence('H', 1, Orientation.HORIZONTAL));
31.129 + assertEquals("bad number of children", n.children.size(), 0);
31.130 + }
31.131 +
31.132 +}
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/statistics/src/test/java/cz/xelfi/quoridor/statistics/resources/StatisticsTest.java Thu Jan 07 23:20:33 2010 +0100
32.3 @@ -0,0 +1,131 @@
32.4 +/*
32.5 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
32.6 + *
32.7 + * The contents of this file are subject to the terms of either the GNU
32.8 + * General Public License Version 2 only ("GPL") or the Common
32.9 + * Development and Distribution License("CDDL") (collectively, the
32.10 + * "License"). You may not use this file except in compliance with the
32.11 + * License. You can obtain a copy of the License at
32.12 + * http://www.netbeans.org/cddl-gplv2.html
32.13 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
32.14 + * specific language governing permissions and limitations under the
32.15 + * License. When distributing the software, include this License Header
32.16 + * Notice in each file and include the License file at
32.17 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
32.18 + * particular file as subject to the "Classpath" exception as provided
32.19 + * by Sun in the GPL Version 2 section of the License file that
32.20 + * accompanied this code. If applicable, add the following below the
32.21 + * License Header, with the fields enclosed by brackets [] replaced by
32.22 + * your own identifying information:
32.23 + * "Portions Copyrighted [year] [name of copyright owner]"
32.24 + *
32.25 + * Contributor(s):
32.26 + *
32.27 + * Portions Copyrighted 2010 Martin Rexa
32.28 + */
32.29 +
32.30 +package cz.xelfi.quoridor.statistics.resources;
32.31 +
32.32 +import com.sun.jersey.api.client.Client;
32.33 +import com.sun.jersey.api.client.WebResource;
32.34 +import com.sun.jersey.core.header.MediaTypes;
32.35 +import com.sun.net.httpserver.HttpServer;
32.36 +import java.io.File;
32.37 +import java.io.FileOutputStream;
32.38 +import java.io.IOException;
32.39 +import java.net.URI;
32.40 +import java.util.Locale;
32.41 +import javax.ws.rs.core.MediaType;
32.42 +import org.junit.AfterClass;
32.43 +import org.junit.Before;
32.44 +import org.junit.BeforeClass;
32.45 +import org.junit.Test;
32.46 +import static org.junit.Assert.*;
32.47 +import cz.xelfi.quoridor.statistics.EloList;
32.48 +/**
32.49 + *
32.50 + * @author Martin Rexa
32.51 + */
32.52 +public class StatisticsTest {
32.53 + private static File dir;
32.54 + private static File fGames;
32.55 + private static HttpServer stopAPI;
32.56 + private WebResource apiResource;
32.57 +
32.58 + public StatisticsTest() throws Exception {
32.59 + }
32.60 +
32.61 + @BeforeClass
32.62 + public static void localeEnglish() throws Exception {
32.63 + Locale.setDefault(Locale.ENGLISH);
32.64 + dir = File.createTempFile("quoridor", ".dir");
32.65 + dir.delete();
32.66 + dir.mkdirs();
32.67 + fGames = new File(dir, "games");
32.68 + fGames.mkdirs();
32.69 +
32.70 + System.setProperty("quoridor.dir", dir.getPath());
32.71 + stopAPI = Statistics.start(9990);
32.72 +
32.73 + File passwd = new File(dir, "passwd");
32.74 + FileOutputStream os = new FileOutputStream(passwd);
32.75 + os.write("test=pes\nJarda=darda\n".getBytes("UTF-8"));
32.76 + os.close();
32.77 + }
32.78 +
32.79 + @Before
32.80 + public void setUp() throws Exception {
32.81 + Client client = new Client();
32.82 + apiResource = client.resource(new URI("http://localhost:9990/"));
32.83 + }
32.84 +
32.85 + @AfterClass
32.86 + public static void cleanUpAll() throws Exception {
32.87 + deleteRec(dir);
32.88 + if (stopAPI != null) {
32.89 + stopAPI.stop(0);
32.90 + }
32.91 + }
32.92 +
32.93 + static void deleteRec(File dir) throws IOException {
32.94 + if (dir == null) {
32.95 + return;
32.96 + }
32.97 + File[] arr = dir.listFiles();
32.98 + if (arr != null) {
32.99 + for (File f : arr) {
32.100 + deleteRec(f);
32.101 + }
32.102 + }
32.103 + dir.delete();
32.104 + }
32.105 +
32.106 + @Test public void testApplicationWadl() {
32.107 + String serviceWadl = apiResource.path("application.wadl").
32.108 + accept(MediaTypes.WADL).get(String.class);
32.109 + assertTrue(serviceWadl.length() > 0);
32.110 + }
32.111 +
32.112 + @Test public void testEloList() throws Exception {
32.113 + createFile(fGames, "g1", "# white: W\n# black: B\n# status: IN_PROGRESS\nN S\n\n");
32.114 + createFile(fGames, "g2", "# white: W\n# black: B\n# status: blackWon\nRESIGN\n\n");
32.115 + createFile(fGames, "g3", "# white: W\n# black: B\n# status: blackWon\nRESIGN\n\n");
32.116 + createFile(fGames, "g4", "# white: W\n# black: B\n# status: blackWon\nRESIGN\n\n");
32.117 + Statistics.processGames();
32.118 +
32.119 + EloList eloList = apiResource.path("elo").path("list").accept(MediaType.TEXT_XML).get(EloList.class);
32.120 +// assertFalse(eloList.getFinalList().isEmpty());
32.121 +// System.out.println("ELO LIST");
32.122 +// for (EloEntry entry : eloList.getFinalList()){
32.123 +// System.out.println(entry);
32.124 +// }
32.125 + }
32.126 +
32.127 + private void createFile(File dir, String filename, String content) throws Exception{
32.128 + File f = new File(dir, filename);
32.129 + FileOutputStream os = new FileOutputStream(f);
32.130 + os.write(content.getBytes("UTF-8"));
32.131 + os.close();
32.132 + }
32.133 +
32.134 +}
33.1 --- a/visidor/src/main/java/cz/xelfi/quoridor/visidor/Viewer.java Fri Jan 01 20:53:17 2010 +0100
33.2 +++ b/visidor/src/main/java/cz/xelfi/quoridor/visidor/Viewer.java Thu Jan 07 23:20:33 2010 +0100
33.3 @@ -1,8 +1,28 @@
33.4 /*
33.5 - * To change this template, choose Tools | Templates
33.6 - * and open the template in the editor.
33.7 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
33.8 + *
33.9 + * The contents of this file are subject to the terms of either the GNU
33.10 + * General Public License Version 2 only ("GPL") or the Common
33.11 + * Development and Distribution License("CDDL") (collectively, the
33.12 + * "License"). You may not use this file except in compliance with the
33.13 + * License. You can obtain a copy of the License at
33.14 + * http://www.netbeans.org/cddl-gplv2.html
33.15 + * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
33.16 + * specific language governing permissions and limitations under the
33.17 + * License. When distributing the software, include this License Header
33.18 + * Notice in each file and include the License file at
33.19 + * nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
33.20 + * particular file as subject to the "Classpath" exception as provided
33.21 + * by Sun in the GPL Version 2 section of the License file that
33.22 + * accompanied this code. If applicable, add the following below the
33.23 + * License Header, with the fields enclosed by brackets [] replaced by
33.24 + * your own identifying information:
33.25 + * "Portions Copyrighted [year] [name of copyright owner]"
33.26 + *
33.27 + * Contributor(s):
33.28 + *
33.29 + * Portions Copyrighted 2009 Jaroslav Tulach
33.30 */
33.31 -
33.32 package cz.xelfi.quoridor.visidor;
33.33
33.34 import cz.xelfi.quoridor.Board;
34.1 --- a/webidor/pom.xml Fri Jan 01 20:53:17 2010 +0100
34.2 +++ b/webidor/pom.xml Thu Jan 07 23:20:33 2010 +0100
34.3 @@ -1,5 +1,7 @@
34.4 <?xml version="1.0" encoding="UTF-8"?>
34.5 -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
34.6 +<project xmlns="http://maven.apache.org/POM/4.0.0"
34.7 + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
34.8 + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
34.9 <modelVersion>4.0.0</modelVersion>
34.10 <parent>
34.11 <artifactId>all-quoridor</artifactId>
35.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Fri Jan 01 20:53:17 2010 +0100
35.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/Game.java Thu Jan 07 23:20:33 2010 +0100
35.3 @@ -82,10 +82,19 @@
35.4
35.5 @XmlAttribute
35.6 final String getCurrentPlayer() {
35.7 - if (board.getCurrentPlayer() == board.getPlayers().get(0)) {
35.8 - return id.getWhite();
35.9 - } else {
35.10 - return id.getBlack();
35.11 + Player w = board.getWinner();
35.12 + if(w==null){
35.13 + if (board.getCurrentPlayer() == board.getPlayers().get(0)) {
35.14 + return id.getWhite();
35.15 + } else {
35.16 + return id.getBlack();
35.17 + }
35.18 + }else{
35.19 + if (w == board.getPlayers().get(0)) {
35.20 + return id.getWhite();
35.21 + } else {
35.22 + return id.getBlack();
35.23 + }
35.24 }
35.25 }
35.26
35.27 @@ -191,11 +200,13 @@
35.28 @Override
35.29 public Board unmarshal(String v) throws Exception {
35.30 return v == null ? null : Board.valueOf(v);
35.31 +// return v == null ? null : new Board(v);
35.32 }
35.33
35.34 @Override
35.35 public String marshal(Board v) throws Exception {
35.36 return v == null ? null : v.toString();
35.37 +// return v == null ? null : Board.board2HashCode(v);
35.38 }
35.39
35.40 }
36.1 --- a/webidor/src/main/java/cz/xelfi/quoridor/webidor/User.java Fri Jan 01 20:53:17 2010 +0100
36.2 +++ b/webidor/src/main/java/cz/xelfi/quoridor/webidor/User.java Thu Jan 07 23:20:33 2010 +0100
36.3 @@ -90,6 +90,23 @@
36.4 return permissions.contains(permission);
36.5 }
36.6
36.7 + public static boolean canSee(GameId gId, String userId) {
36.8 + if (!gId.isFinished()) {
36.9 + return true;
36.10 + }
36.11 + if (userId.equals(gId.getWhite())) {
36.12 + return true;
36.13 + }
36.14 + if (userId.equals(gId.getBlack())) {
36.15 + return true;
36.16 + }
36.17 + return false;
36.18 + }
36.19 +
36.20 + public boolean canSee(GameId gId){
36.21 + return canSee(gId, id);
36.22 + }
36.23 +
36.24 public String getId() {
36.25 return id;
36.26 }
37.1 --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/FinishedGameTest.java Fri Jan 01 20:53:17 2010 +0100
37.2 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/FinishedGameTest.java Thu Jan 07 23:20:33 2010 +0100
37.3 @@ -184,4 +184,45 @@
37.4 assertFalse("is finished", end.getId().getStatus().isInProgress());
37.5 }
37.6
37.7 + @Test public void testResignBGame() throws Exception {
37.8 + String logJarda = webResource.path("login").
37.9 + queryParam("name", "Jarda").
37.10 + queryParam("password", "heslo").
37.11 + accept(MediaType.TEXT_PLAIN).
37.12 + put(String.class);
37.13 + String logJirka = webResource.path("login").
37.14 + queryParam("name", "Jirka").
37.15 + queryParam("password", "pesko").
37.16 + accept(MediaType.TEXT_PLAIN).
37.17 + put(String.class);
37.18 +
37.19 + GameId s = webResource.path("games").queryParam("white", "Jarda")
37.20 + .queryParam("loginID", logJarda)
37.21 + .queryParam("black", "Jirka").post(GameId.class);
37.22 +
37.23 + assertTrue("In progress", s.getStatus().isInProgress());
37.24 +
37.25 + webResource.path("games/" + s.getId()).
37.26 + queryParam("loginID", logJarda).
37.27 + queryParam("player", "Jarda").
37.28 + queryParam("move", "N").put(GameId.class);
37.29 + webResource.path("games/" + s.getId()).
37.30 + queryParam("loginID", logJirka).
37.31 + queryParam("player", "Jirka").
37.32 + queryParam("move", "RESIGN").put(GameId.class);
37.33 +
37.34 +
37.35 + try {
37.36 + Game end = webResource.path("games/" + s.getId()).accept(MediaType.TEXT_XML).get(Game.class);
37.37 + fail("Should not be able to get game when finished");
37.38 + } catch (UniformInterfaceException ex) {
37.39 + // OK
37.40 + }
37.41 + Game end = webResource.path("games/" + s.getId()).queryParam("loginID", logJarda).accept(MediaType.TEXT_XML).get(Game.class);
37.42 + assertEquals("WhiteWins", GameStatus.whiteWon, end.getId().getStatus());
37.43 + assertEquals("Jarda wins", "Jarda", end.getCurrentPlayer());
37.44 +
37.45 + assertFalse("is finished", end.getId().getStatus().isInProgress());
37.46 + }
37.47 +
37.48 }
38.1 --- a/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Fri Jan 01 20:53:17 2010 +0100
38.2 +++ b/webidor/src/test/java/cz/xelfi/quoridor/webidor/QuoridorTest.java Thu Jan 07 23:20:33 2010 +0100
38.3 @@ -26,6 +26,8 @@
38.4
38.5 package cz.xelfi.quoridor.webidor;
38.6
38.7 +import cz.xelfi.quoridor.IllegalPositionException;
38.8 +import java.io.StringWriter;
38.9 import com.sun.jersey.api.client.GenericType;
38.10 import com.sun.jersey.api.client.UniformInterfaceException;
38.11 import com.sun.jersey.core.header.MediaTypes;
38.12 @@ -38,6 +40,7 @@
38.13 import java.io.FileOutputStream;
38.14 import java.io.FileReader;
38.15 import java.io.IOException;
38.16 +import java.io.StringReader;
38.17 import java.util.List;
38.18 import java.util.Map;
38.19 import javax.ws.rs.core.MediaType;
38.20 @@ -201,17 +204,33 @@
38.21
38.22 class GMap extends GenericType<Map<String,Object>>{}
38.23 String text = webResource.path("games").path(s.getId()).accept(MediaType.TEXT_PLAIN).get(String.class);
38.24 + text = (boardToPicture(Board.valueOf(text)));
38.25 if (text.indexOf("-----") == -1) {
38.26 fail("Expecting board:\n" + text);
38.27 }
38.28 Game readGame = webResource.path("games").path(s.getId()).accept(MediaType.TEXT_XML).get(Game.class);
38.29 String sGame = webResource.path("games").path(s.getId()).accept(MediaType.TEXT_XML).get(String.class);
38.30 assertNotNull("Game really returned", readGame);
38.31 - assertEquals("Same game as in text representation", readGame.getBoard(), Board.valueOf(text));
38.32 - assertEquals("It is same as text of our game", readGame.getBoard().toString(), text);
38.33 +// assertEquals("Same game as in text representation", readGame.getBoard(), Board.valueOf(text));
38.34 + assertEquals("Same game as in text representation", readGame.getBoard(), picture2board(text));
38.35 +// assertEquals("It is same as text of our game", readGame.getBoard().toString(), text);
38.36 + assertEquals("It is same as text of our game", boardToPicture(readGame.getBoard()), text);
38.37
38.38 assertEquals(Move.NORTH, readGame.getMoves().get(0).getMove());
38.39 assertEquals(Move.SOUTH, readGame.getMoves().get(1).getMove());
38.40 }
38.41 + private static String boardToPicture(Board b) {
38.42 + StringWriter w = new StringWriter();
38.43 + try {
38.44 + b.write(w);
38.45 + } catch (IOException ex) {
38.46 + return ex.toString();
38.47 + }
38.48 + return w.toString();
38.49 + }
38.50
38.51 + private static Board picture2board(String text) throws IOException, IllegalPositionException {
38.52 + StringReader sr = new StringReader(text);
38.53 + return Board.read(sr);
38.54 + }
38.55 }