Skip to content

Commit e9043ca

Browse files
saturnismlesv
authored andcommitted
AppEngine Channel Example with Tic Tac Toe + Java (#191)
* Moving https://code.google.com/archive/p/java-channel-tic-tac-toe/ to GitHub * Applied Style * fixed checkstyle
1 parent a14bd02 commit e9043ca

File tree

12 files changed

+948
-0
lines changed

12 files changed

+948
-0
lines changed

appengine/channel/pom.xml

+111
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
<!--
2+
Copyright 2015 Google Inc. All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
-->
16+
<project>
17+
<modelVersion>4.0.0</modelVersion>
18+
<packaging>war</packaging>
19+
<version>1.0-SNAPSHOT</version>
20+
<groupId>com.example.appengine</groupId>
21+
<artifactId>appengine-channel</artifactId>
22+
<parent>
23+
<groupId>com.google.cloud</groupId>
24+
<artifactId>doc-samples</artifactId>
25+
<version>1.0.0</version>
26+
<relativePath>../..</relativePath>
27+
</parent>
28+
<properties>
29+
<objectify.version>5.1.5</objectify.version>
30+
</properties>
31+
<!-- [START set_versions] -->
32+
<prerequisites>
33+
<maven>3.3.9</maven>
34+
</prerequisites>
35+
<!-- [END set_versions] -->
36+
<dependencies>
37+
<dependency>
38+
<groupId>com.google.appengine</groupId>
39+
<artifactId>appengine-api-1.0-sdk</artifactId>
40+
<version>${appengine.sdk.version}</version>
41+
</dependency>
42+
<dependency>
43+
<groupId>javax.servlet</groupId>
44+
<artifactId>servlet-api</artifactId>
45+
<version>2.5</version>
46+
<type>jar</type>
47+
<scope>provided</scope>
48+
</dependency>
49+
<dependency>
50+
<groupId>org.json</groupId>
51+
<artifactId>json</artifactId>
52+
<version>20160212</version>
53+
</dependency>
54+
<dependency>
55+
<groupId>com.googlecode.objectify</groupId>
56+
<artifactId>objectify</artifactId>
57+
<version>${objectify.version}</version>
58+
</dependency>
59+
60+
<!-- Test Dependencies -->
61+
<dependency>
62+
<groupId>junit</groupId>
63+
<artifactId>junit</artifactId>
64+
<version>4.10</version>
65+
<scope>test</scope>
66+
</dependency>
67+
<dependency>
68+
<groupId>org.mockito</groupId>
69+
<artifactId>mockito-all</artifactId>
70+
<version>1.10.19</version>
71+
<scope>test</scope>
72+
</dependency>
73+
<dependency>
74+
<groupId>com.google.appengine</groupId>
75+
<artifactId>appengine-testing</artifactId>
76+
<version>${appengine.sdk.version}</version>
77+
<scope>test</scope>
78+
</dependency>
79+
<dependency>
80+
<groupId>com.google.appengine</groupId>
81+
<artifactId>appengine-api-stubs</artifactId>
82+
<version>${appengine.sdk.version}</version>
83+
<scope>test</scope>
84+
</dependency>
85+
<dependency>
86+
<groupId>com.google.appengine</groupId>
87+
<artifactId>appengine-tools-sdk</artifactId>
88+
<version>${appengine.sdk.version}</version>
89+
<scope>test</scope>
90+
</dependency>
91+
<dependency>
92+
<groupId>com.google.truth</groupId>
93+
<artifactId>truth</artifactId>
94+
<version>0.28</version>
95+
<scope>test</scope>
96+
</dependency>
97+
</dependencies>
98+
<build>
99+
<!-- for hot reload of the web application -->
100+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes
101+
</outputDirectory>
102+
<plugins>
103+
<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
104+
<plugin>
105+
<groupId>com.google.appengine</groupId>
106+
<artifactId>appengine-maven-plugin</artifactId>
107+
<version>${appengine.sdk.version}</version>
108+
</plugin>
109+
</plugins>
110+
</build>
111+
</project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine.channel;
18+
19+
import com.google.appengine.api.channel.ChannelMessage;
20+
import com.google.appengine.api.channel.ChannelService;
21+
import com.google.appengine.api.channel.ChannelServiceFactory;
22+
import com.googlecode.objectify.annotation.Entity;
23+
import com.googlecode.objectify.annotation.Id;
24+
import org.json.JSONObject;
25+
26+
import java.util.HashMap;
27+
import java.util.Map;
28+
import java.util.UUID;
29+
import java.util.regex.Pattern;
30+
31+
@Entity
32+
public class Game {
33+
static final Pattern[] XWins =
34+
{Pattern.compile("XXX......"), Pattern.compile("...XXX..."), Pattern.compile("......XXX"),
35+
Pattern.compile("X..X..X.."), Pattern.compile(".X..X..X."),
36+
Pattern.compile("..X..X..X"), Pattern.compile("X...X...X"),
37+
Pattern.compile("..X.X.X..")};
38+
static final Pattern[] OWins =
39+
{Pattern.compile("OOO......"), Pattern.compile("...OOO..."), Pattern.compile("......OOO"),
40+
Pattern.compile("O..O..O.."), Pattern.compile(".O..O..O."),
41+
Pattern.compile("..O..O..O"), Pattern.compile("O...O...O"),
42+
Pattern.compile("..O.O.O..")};
43+
44+
@Id
45+
public String id;
46+
private String userX;
47+
private String userO;
48+
private String board;
49+
private Boolean moveX;
50+
private String winner;
51+
private String winningBoard;
52+
53+
Game() {
54+
}
55+
56+
Game(String userX, String userO, String board, boolean moveX) {
57+
this.id = UUID.randomUUID().toString();
58+
this.userX = userX;
59+
this.userO = userO;
60+
this.board = board;
61+
this.moveX = moveX;
62+
}
63+
64+
public String getId() {
65+
return id;
66+
}
67+
68+
public void setId(String id) {
69+
this.id = id;
70+
}
71+
72+
public String getUserX() {
73+
return userX;
74+
}
75+
76+
public String getUserO() {
77+
return userO;
78+
}
79+
80+
public void setUserO(String userO) {
81+
this.userO = userO;
82+
}
83+
84+
public String getBoard() {
85+
return board;
86+
}
87+
88+
public void setBoard(String board) {
89+
this.board = board;
90+
}
91+
92+
public boolean getMoveX() {
93+
return moveX;
94+
}
95+
96+
public void setMoveX(boolean moveX) {
97+
this.moveX = moveX;
98+
}
99+
100+
public String getMessageString() {
101+
Map<String, String> state = new HashMap<String, String>();
102+
state.put("userX", userX);
103+
if (userO == null) {
104+
state.put("userO", "");
105+
} else {
106+
state.put("userO", userO);
107+
}
108+
state.put("board", board);
109+
state.put("moveX", moveX.toString());
110+
state.put("winner", winner);
111+
if (winner != null && winner != "") {
112+
state.put("winningBoard", winningBoard);
113+
}
114+
JSONObject message = new JSONObject(state);
115+
return message.toString();
116+
}
117+
118+
public String getChannelKey(String user) {
119+
return user + id;
120+
}
121+
122+
private void sendUpdateToUser(String user) {
123+
if (user != null) {
124+
ChannelService channelService = ChannelServiceFactory.getChannelService();
125+
String channelKey = getChannelKey(user);
126+
channelService.sendMessage(new ChannelMessage(channelKey, getMessageString()));
127+
}
128+
}
129+
130+
public void sendUpdateToClients() {
131+
sendUpdateToUser(userX);
132+
sendUpdateToUser(userO);
133+
}
134+
135+
public void checkWin() {
136+
final Pattern[] wins;
137+
if (moveX) {
138+
wins = XWins;
139+
} else {
140+
wins = OWins;
141+
}
142+
143+
for (Pattern winPattern : wins) {
144+
if (winPattern.matcher(board).matches()) {
145+
if (moveX) {
146+
winner = userX;
147+
} else {
148+
winner = userO;
149+
}
150+
winningBoard = winPattern.toString();
151+
}
152+
}
153+
}
154+
155+
public boolean makeMove(int position, String user) {
156+
String currentMovePlayer;
157+
char value;
158+
if (getMoveX()) {
159+
value = 'X';
160+
currentMovePlayer = getUserX();
161+
} else {
162+
value = 'O';
163+
currentMovePlayer = getUserO();
164+
}
165+
166+
if (currentMovePlayer.equals(user)) {
167+
char[] boardBytes = getBoard().toCharArray();
168+
boardBytes[position] = value;
169+
setBoard(new String(boardBytes));
170+
checkWin();
171+
setMoveX(!getMoveX());
172+
sendUpdateToClients();
173+
return true;
174+
}
175+
176+
return false;
177+
}
178+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine.channel;
18+
19+
import com.google.appengine.api.channel.ChannelService;
20+
import com.google.appengine.api.channel.ChannelServiceFactory;
21+
import com.google.appengine.api.users.UserService;
22+
import com.google.appengine.api.users.UserServiceFactory;
23+
import com.googlecode.objectify.Objectify;
24+
import com.googlecode.objectify.ObjectifyService;
25+
26+
import java.io.IOException;
27+
import javax.servlet.http.HttpServlet;
28+
import javax.servlet.http.HttpServletRequest;
29+
import javax.servlet.http.HttpServletResponse;
30+
31+
public class GetTokenServlet extends HttpServlet {
32+
@Override
33+
public void doPost(HttpServletRequest req, HttpServletResponse resp)
34+
throws IOException {
35+
UserService userService = UserServiceFactory.getUserService();
36+
String gameId = req.getParameter("gamekey");
37+
Objectify ofy = ObjectifyService.ofy();
38+
Game game = ofy.load().type(Game.class).id(gameId).safe();
39+
40+
String currentUserId = userService.getCurrentUser().getUserId();
41+
if (currentUserId.equals(game.getUserX()) || currentUserId.equals(game.getUserO())) {
42+
String channelKey = game.getChannelKey(currentUserId);
43+
ChannelService channelService = ChannelServiceFactory.getChannelService();
44+
resp.setContentType("text/plain");
45+
resp.getWriter().println(channelService.createChannel(channelKey));
46+
return;
47+
}
48+
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
49+
}
50+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2016 Google Inc. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.example.appengine.channel;
18+
19+
import com.google.appengine.api.users.UserService;
20+
import com.google.appengine.api.users.UserServiceFactory;
21+
import com.googlecode.objectify.Objectify;
22+
import com.googlecode.objectify.ObjectifyService;
23+
24+
import java.io.IOException;
25+
import javax.servlet.http.HttpServlet;
26+
import javax.servlet.http.HttpServletRequest;
27+
import javax.servlet.http.HttpServletResponse;
28+
29+
public class MoveServlet extends HttpServlet {
30+
@Override
31+
public void doPost(HttpServletRequest req, HttpServletResponse resp)
32+
throws IOException {
33+
UserService userService = UserServiceFactory.getUserService();
34+
String gameId = req.getParameter("gamekey");
35+
int piece = new Integer(req.getParameter("i"));
36+
Objectify ofy = ObjectifyService.ofy();
37+
Game game = ofy.load().type(Game.class).id(gameId).safe();
38+
39+
String currentUserId = userService.getCurrentUser().getUserId();
40+
if (!game.makeMove(piece, currentUserId)) {
41+
resp.setStatus(HttpServletResponse.SC_FORBIDDEN);
42+
} else {
43+
ofy.save().entity(game).now();
44+
}
45+
}
46+
}

0 commit comments

Comments
 (0)