Skip to content

Commit bfbd314

Browse files
author
Jerjou Cheng
committed
Add GAE standard + firebase tictactoe sample
1 parent 012874e commit bfbd314

File tree

16 files changed

+1128
-0
lines changed

16 files changed

+1128
-0
lines changed
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
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-firebase</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.13</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>20160810</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.12</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.30</version>
95+
<scope>test</scope>
96+
</dependency>
97+
<dependency>
98+
<groupId>com.google.firebase</groupId>
99+
<artifactId>firebase-server-sdk</artifactId>
100+
<version>3.0.1</version>
101+
</dependency>
102+
<dependency>
103+
<groupId>com.google.api-client</groupId>
104+
<artifactId>google-api-client-appengine</artifactId>
105+
<version>1.22.0</version>
106+
</dependency>
107+
</dependencies>
108+
<build>
109+
<!-- for hot reload of the web application -->
110+
<outputDirectory>${project.build.directory}/${project.build.finalName}/WEB-INF/classes
111+
</outputDirectory>
112+
<plugins>
113+
<!-- Parent POM defines ${appengine.sdk.version} (updates frequently). -->
114+
<plugin>
115+
<groupId>com.google.appengine</groupId>
116+
<artifactId>appengine-maven-plugin</artifactId>
117+
<version>${appengine.sdk.version}</version>
118+
</plugin>
119+
</plugins>
120+
</build>
121+
</project>
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
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.firetactoe;
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 DeleteServlet 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("g");
35+
Objectify ofy = ObjectifyService.ofy();
36+
Game game = ofy.load().type(Game.class).id(gameId).safe();
37+
38+
String currentUserId = userService.getCurrentUser().getUserId();
39+
game.deleteChannel(currentUserId);
40+
}
41+
}
Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
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.firetactoe;
18+
19+
import com.google.common.io.CharStreams;
20+
import com.google.firebase.FirebaseApp;
21+
import com.google.firebase.FirebaseOptions;
22+
import com.google.firebase.database.DatabaseReference;
23+
import com.google.firebase.database.FirebaseDatabase;
24+
import com.googlecode.objectify.annotation.Entity;
25+
import com.googlecode.objectify.annotation.Id;
26+
27+
import org.json.JSONObject;
28+
29+
import java.io.FileInputStream;
30+
import java.io.FileNotFoundException;
31+
import java.io.IOException;
32+
import java.io.InputStreamReader;
33+
import java.lang.RuntimeException;
34+
import java.util.HashMap;
35+
import java.util.Map;
36+
import java.util.UUID;
37+
import java.util.regex.Pattern;
38+
39+
@Entity
40+
public class Game {
41+
static final Pattern[] XWins =
42+
{Pattern.compile("XXX......"), Pattern.compile("...XXX..."), Pattern.compile("......XXX"),
43+
Pattern.compile("X..X..X.."), Pattern.compile(".X..X..X."),
44+
Pattern.compile("..X..X..X"), Pattern.compile("X...X...X"),
45+
Pattern.compile("..X.X.X..")};
46+
static final Pattern[] OWins =
47+
{Pattern.compile("OOO......"), Pattern.compile("...OOO..."), Pattern.compile("......OOO"),
48+
Pattern.compile("O..O..O.."), Pattern.compile(".O..O..O."),
49+
Pattern.compile("..O..O..O"), Pattern.compile("O...O...O"),
50+
Pattern.compile("..O.O.O..")};
51+
52+
@Id
53+
public String id;
54+
public String userX;
55+
public String userO;
56+
public String board;
57+
public Boolean moveX;
58+
public String winner;
59+
public String winningBoard;
60+
61+
private static final String SERVICE_ACCOUNT_PATH = "resources/credentials.json";
62+
private static final String FIREBASE_SNIPPET_PATH = "resources/firebase_config.html";
63+
private static String sFirebaseDbUrl;
64+
protected static String sFirebaseSnippet;
65+
66+
static {
67+
try {
68+
sFirebaseSnippet = CharStreams.toString(
69+
new InputStreamReader(new FileInputStream(FIREBASE_SNIPPET_PATH)));
70+
sFirebaseDbUrl = parseFirebaseUrl(sFirebaseSnippet);
71+
72+
FirebaseOptions options = new FirebaseOptions.Builder()
73+
.setServiceAccount(new FileInputStream(SERVICE_ACCOUNT_PATH))
74+
.setDatabaseUrl(sFirebaseDbUrl)
75+
.build();
76+
FirebaseApp.initializeApp(options);
77+
} catch (FileNotFoundException e) {
78+
throw new RuntimeException(e);
79+
} catch (IOException e) {
80+
throw new RuntimeException(e);
81+
}
82+
}
83+
84+
private static String parseFirebaseUrl(String firebaseSnippet) {
85+
int idx = firebaseSnippet.indexOf("databaseURL");
86+
idx = firebaseSnippet.indexOf(':', idx + 11);
87+
int openQuote = firebaseSnippet.indexOf('"', idx);
88+
int closeQuote = firebaseSnippet.indexOf('"', openQuote + 1);
89+
return firebaseSnippet.substring(openQuote + 1, closeQuote);
90+
}
91+
92+
Game() {
93+
}
94+
95+
Game(String userX, String userO, String board, boolean moveX) {
96+
this.id = UUID.randomUUID().toString();
97+
this.userX = userX;
98+
this.userO = userO;
99+
this.board = board;
100+
this.moveX = moveX;
101+
}
102+
103+
public String getId() {
104+
return id;
105+
}
106+
107+
public void setId(String id) {
108+
this.id = id;
109+
}
110+
111+
public String getUserX() {
112+
return userX;
113+
}
114+
115+
public String getUserO() {
116+
return userO;
117+
}
118+
119+
public void setUserO(String userO) {
120+
this.userO = userO;
121+
}
122+
123+
public String getBoard() {
124+
return board;
125+
}
126+
127+
public void setBoard(String board) {
128+
this.board = board;
129+
}
130+
131+
public boolean getMoveX() {
132+
return moveX;
133+
}
134+
135+
public void setMoveX(boolean moveX) {
136+
this.moveX = moveX;
137+
}
138+
139+
public String getMessageString() {
140+
Map<String, String> state = new HashMap<String, String>();
141+
state.put("userX", userX);
142+
if (userO == null) {
143+
state.put("userO", "");
144+
} else {
145+
state.put("userO", userO);
146+
}
147+
state.put("board", board);
148+
state.put("moveX", moveX.toString());
149+
state.put("winner", winner);
150+
if (winner != null && winner != "") {
151+
state.put("winningBoard", winningBoard);
152+
}
153+
JSONObject message = new JSONObject(state);
154+
return message.toString();
155+
}
156+
157+
//[START send_updates]
158+
public String getChannelKey(String user) {
159+
return user + id;
160+
}
161+
162+
public void deleteChannel(String user) {
163+
if (user != null) {
164+
String channelKey = getChannelKey(user);
165+
final FirebaseDatabase database = FirebaseDatabase.getInstance();
166+
DatabaseReference ref = database.getReference("channels");
167+
ref.child(channelKey).setValue(null);
168+
}
169+
}
170+
171+
private void sendUpdateToUser(String user) {
172+
if (user != null) {
173+
String channelKey = getChannelKey(user);
174+
final FirebaseDatabase database = FirebaseDatabase.getInstance();
175+
DatabaseReference ref = database.getReference("channels");
176+
ref.child(channelKey).setValue(this);
177+
}
178+
}
179+
180+
public void sendUpdateToClients() {
181+
sendUpdateToUser(userX);
182+
sendUpdateToUser(userO);
183+
}
184+
//[END send_updates]
185+
186+
public void checkWin() {
187+
final Pattern[] wins;
188+
if (moveX) {
189+
wins = XWins;
190+
} else {
191+
wins = OWins;
192+
}
193+
194+
for (Pattern winPattern : wins) {
195+
if (winPattern.matcher(board).matches()) {
196+
if (moveX) {
197+
winner = userX;
198+
} else {
199+
winner = userO;
200+
}
201+
winningBoard = winPattern.toString();
202+
}
203+
}
204+
}
205+
206+
//[START make_move]
207+
public boolean makeMove(int position, String user) {
208+
String currentMovePlayer;
209+
char value;
210+
if (getMoveX()) {
211+
value = 'X';
212+
currentMovePlayer = getUserX();
213+
} else {
214+
value = 'O';
215+
currentMovePlayer = getUserO();
216+
}
217+
218+
if (currentMovePlayer.equals(user)) {
219+
char[] boardBytes = getBoard().toCharArray();
220+
boardBytes[position] = value;
221+
setBoard(new String(boardBytes));
222+
checkWin();
223+
setMoveX(!getMoveX());
224+
sendUpdateToClients();
225+
return true;
226+
}
227+
228+
return false;
229+
}
230+
//[END make_move]
231+
}

0 commit comments

Comments
 (0)