TicTacToeWS.java (20696B)
1 /* 2 * Implements the Tic Tac Toe Web Service. 3 */ 4 package com.tttws; 5 6 import jakarta.jws.WebMethod; 7 import jakarta.jws.WebParam; 8 import jakarta.jws.WebService; 9 import jakarta.jws.soap.SOAPBinding; 10 11 /* 12 * Tic Tac Toe Web Service 13 */ 14 15 /** 16 * 17 * @author petar 18 */ 19 20 @WebService(serviceName = "TicTacToeWebService") 21 @SOAPBinding(style = SOAPBinding.Style.RPC) 22 public class TicTacToeWS { 23 24 private final TTT_MySQL dao; 25 26 /** 27 * Web Service constructor 28 */ 29 public TicTacToeWS() { 30 dao = new TTT_MySQL("localhost", "root", "", "tictactoe"); 31 } 32 33 /** 34 * Used to login to the system 35 * @param username the username of the user logging in. 36 * @param password the password of the user logging in. 37 * @return either 0 if incorrect details, an integer greater than 0 (which is the users id) if correct details, -1 if there is a general error. 38 */ 39 @WebMethod(operationName = "login") 40 public int login(@WebParam(name = "username") String username, @WebParam(name = "password") String password) { 41 try { 42 String sqlCmd = "SELECT autokey FROM users WHERE username = '" + username; 43 sqlCmd += "' AND password = SHA1('" + password + "') AND isactive = 1;"; 44 String result = dao.retrieve(sqlCmd); 45 if("ERROR".equals(result)) { 46 return 0; 47 } else { 48 return Integer.parseInt(result); 49 } 50 } catch(Exception e) { 51 System.out.println("Error is : " + e.getMessage()); 52 return -1; 53 } 54 } 55 56 /** 57 * Used to register a new user on the system. 58 * @param username the username of the new user. 59 * @param password the password of the new user. 60 * @param name - the name of the new user. 61 * @param surname the surname of the new user. 62 * @return The user provides their username, password, name and surname. If successful, the method returns the users id on the system (the autokey 63 * field from the users table). If unsuccessful, it returns either “ERROR-REPEAT” if a user with that username already exists, “ERROR-INSERT” if the 64 * method could not add the data to the users table, “ERROR-RETRIEVE “ if the method cannot retrieve the newly inserted data from the users table, or 65 * “ERROR-DB” if the method cannot find the DB. 66 */ 67 @WebMethod(operationName = "register") 68 public String register(@WebParam(name = "username") String username, @WebParam(name = "password") String password, @WebParam(name = "name") String name, @WebParam(name = "surname") String surname) { 69 String sqlCmd = ""; 70 71 sqlCmd = "SELECT COUNT(*) FROM users WHERE username = '" + username + "';"; 72 try { 73 String result = ""; 74 result = dao.retrieve(sqlCmd); 75 if(result.equals("0")) { 76 sqlCmd = "INSERT INTO users VALUES (default, '"; 77 sqlCmd += name + "', '" + surname + "', '" + username + "', SHA1('"; 78 sqlCmd += password + "'), 1, default);"; 79 System.out.println(sqlCmd); 80 try { 81 result = dao.insert(sqlCmd); 82 if(!"INSERTED 1 ROWS.".equals(result)) { 83 return "ERROR-INSERT"; 84 } else { 85 sqlCmd = "SELECT autokey FROM users WHERE username = '" + username; 86 sqlCmd += "' AND password = SHA1('" + password + "') AND isactive = 1;"; 87 88 try { 89 result = dao.retrieve(sqlCmd); 90 return result; 91 } catch(Exception g) { 92 return "ERROR-RETRIEVE"; 93 } 94 } 95 } catch(Exception e) { 96 return "ERROR-DB"; 97 } 98 } else { 99 return "ERROR-REPEAT"; 100 } 101 } catch(Exception u) { 102 return "ERROR-DB"; 103 } 104 } 105 106 /** 107 * Used to create a new game. 108 * @param uid the user id of the user creating the new game. 109 * @return either the id of the new game (returned as a string), or "ERROR-NOTFOUND", "ERROR-RETRIEVE", or "ERROR-INSERT" if the game couldn't be created, or "ERROR-DB" if unable to talk to the DB or DBMS. 110 */ 111 @WebMethod(operationName = "newGame") 112 public String newGame(@WebParam(name = "uid") int uid) { 113 String sqlCmd = "INSERT INTO games VALUES(default, " + uid + ", NULL, -1, default);"; 114 try { 115 String result = dao.insert(sqlCmd); 116 if(result.equals("INSERTED 1 ROWS.")) { 117 sqlCmd = "SELECT autokey FROM games WHERE gamestate = -1 AND p1 = " + uid + " AND p2 IS NULL ORDER BY autokey DESC LIMIT 1;"; 118 try { 119 result = dao.retrieve(sqlCmd); 120 if(result.length() > 0) { 121 return result; 122 } else { 123 return "ERROR-NOTFOUND"; 124 } 125 } catch(Exception g) { 126 return "ERROR-RETRIEVE"; 127 } 128 } else { 129 return "ERROR-INSERT"; 130 } 131 } catch(Exception e) { 132 return "ERROR-DB"; 133 } 134 } 135 136 /** 137 * Used to join an existing game. 138 * @param uid the user id of the person joining the game. 139 * @param gid the game id of the game the player wants to join. 140 * @return 1 (as a string) if able to join, 0 (as a string) if unable to join, or "ERROR-DB" if unable to talk to the DB or DBMS. 141 */ 142 @WebMethod(operationName = "joinGame") 143 public String joinGame(@WebParam(name = "uid") int uid, @WebParam(name = "gid") int gid) { 144 String sqlCmd = "UPDATE games SET p2 = " + uid + ", gamestate = 0 WHERE autokey = " + gid + ";"; 145 try { 146 String result = dao.update(sqlCmd); 147 if(result.equals("UPDATED 1 ROWS.")) { 148 return "1"; 149 } else { 150 return "0"; 151 } 152 } catch(Exception e) { 153 return "ERROR-DB"; 154 } 155 } 156 157 /** 158 * Returns the current board as a formatted string. 159 * @param gid the game id of the game whose board we want to see. 160 * @return Used to return all moves taken to date for a particular game. If successful, the method returns the moves taken as a string as follows {pId, x, y} for each row, each row separated by \n. The moves are returned in order of play (i.e. first move will be first row returned etc.). Using this we can evaluate how many moves have been taken (i.e. the number of rows), the last player to take a move (pId of the final row), plus all the moves taken to date. 161 * The method returns "ERROR-NOMOVES" if no moves have yet been made for that game, or "ERROR-DB" if unable to talk to the DB or DBMS. 162 */ 163 @WebMethod(operationName = "getBoard") 164 public String getBoard(@WebParam(name = "gid") int gid) { 165 String sqlCmd = "SELECT pId, x, y FROM moves WHERE gId = " + gid + " ORDER BY played ASC;"; 166 try { 167 String result = dao.retrieve(sqlCmd); 168 if(result.length() > 0) { 169 return result; 170 } else { 171 return "ERROR-NOMOVES"; 172 } 173 } catch(Exception e) { 174 return "ERROR-DB"; 175 } 176 } 177 178 /** 179 * Returns the state of the game. 180 * @param gid the game id of the game whose state we wish to check. 181 * @return -1 (as a string) if waiting for a second player to join, 0 (as a string) if the game is in progress, 1 (as a string) if player 1 has won, 182 * 2 (as a string) if player 2 has won, 3 (as a string) if a draw, or "ERROR-NOGAME" if a game matching the game id cannot be found, or "ERROR-DB" if 183 * unable to talk to the DB or DBMS. 184 */ 185 @WebMethod(operationName = "getGameState") 186 public String getGameState(@WebParam(name = "gid") int gid) { 187 String sqlCmd = "SELECT gamestate FROM games WHERE autokey = " + gid + ";"; 188 try { 189 String result = dao.retrieve(sqlCmd); 190 if(result.length() > 0) { 191 return result; 192 } else { 193 return "ERROR-NOGAME"; 194 } 195 } catch(Exception e) { 196 return "ERROR-DB"; 197 } 198 } 199 200 /** 201 * Sets the state of a game. 202 * @param gid the game id of the game whose state we wish to set. 203 * @param gstate the state we wish to set the game to. 204 * @return 1 (as a string) if successful, "ERROR-NOGAME" if unable to find a game matching gid, "ERROR-DB" if unable to talk the the DB or DBMS. 205 */ 206 @WebMethod(operationName = "setGameState") 207 public String setGameState(@WebParam(name = "gid") int gid, @WebParam(name = "gstate") int gstate) { 208 String sqlCmd = "UPDATE games SET gamestate = " + gstate + " WHERE autokey = " + gid + ";"; 209 try { 210 String result = dao.update(sqlCmd); 211 if(result.equals("UPDATED 1 ROWS.")) { 212 return "1"; 213 } else { 214 return "ERROR-NOGAME"; 215 } 216 } catch(Exception e) { 217 return "ERROR-DB"; 218 } 219 } 220 221 /** 222 * Checks a particular square in a game to see if it has been or can be taken. 223 * @param x the columns position of the square. 224 * @param y the row position of the square. 225 * @param gid the game we are playing/checking. 226 * @return 1 (as a string) if the square is taken, 0 (as a string) if the square is available, "ERROR-DB" if there is a problem talking to the DB or DBMS. 227 */ 228 @WebMethod(operationName = "checkSquare") 229 public String checkSquare(@WebParam(name = "x") int x, @WebParam(name = "y") int y, @WebParam(name = "gid") int gid) { 230 String sqlCmd = "SELECT COUNT(*) FROM moves WHERE x = " + x + " AND y = " + y + " AND "; 231 sqlCmd += " gId = " + gid + ";"; 232 try { 233 String result = dao.retrieve(sqlCmd); 234 return result; 235 } catch (Exception e) { 236 return "ERROR-DB"; 237 } 238 } 239 240 /** 241 * Takes a square in a particular game for a particular player. 242 * @param x the column position of the square. 243 * @param y the row position of the square. 244 * @param gid the game we are playing. 245 * @param pid the user id of the player taking the square. 246 * @return 1 (as a string) if successful, 0 (as a string) if unsuccessful, "ERROR-TAKEN" if the square is unavailable, "ERROR-DB" if there is a problem 247 * talking to the DB or DBMS, "ERROR" if there is a general error. 248 */ 249 @WebMethod(operationName = "takeSquare") 250 public String takeSquare(@WebParam(name = "x") int x, @WebParam(name = "y") int y, @WebParam(name = "gid") int gid, @WebParam(name = "pid") int pid) { 251 int count = Integer.parseInt(checkSquare(x, y, gid)); 252 String flag = ""; 253 switch(count) { 254 case 1: 255 flag = "ERROR-TAKEN"; 256 break; 257 case 0: 258 String sqlCmd = "INSERT INTO moves VALUES(default, " + pid + ", " + x + ", " + y; 259 sqlCmd += ", default, " + gid + ");"; 260 try { 261 String result = dao.insert(sqlCmd); 262 if(result.equals("INSERTED 1 ROWS.")) { 263 flag = "1"; 264 } else { 265 flag = "0"; 266 } 267 } catch(Exception e) { 268 flag = "ERROR-DB"; 269 } 270 break; 271 default: 272 flag = "ERROR"; 273 } 274 return flag; 275 } 276 277 /** 278 * Used to see if the game is over or not, and who has won if it is over. 279 * @param gid the game id of the game we are checking. 280 * @return 0 (as a string) if the game hasn’t been won but can continue to be played, 1 (as a string) if player 1 has won, 281 * 2 (as a string) if player 2 has won, or 3 (as a string) if the game is a draw. The method will return “ERROR-RETRIEVE” if there is an issue 282 * getting details about the game, “ERROR-NOGAME” if no game can be found matching the gid, “ERROR-DB” if there is a problem accessing the DB or DBMS. 283 */ 284 @WebMethod(operationName = "checkWin") 285 public String checkWin(@WebParam(name = "gid") int gid) { 286 String result = getBoard(gid); 287 int winner = 0; 288 if(result.length() > 0) { 289 String[] rows = result.split("\n"); 290 int num_moves = rows.length; 291 int[][] table = new int[3][3]; 292 for(int a = 0; a < 3; a++) { 293 for(int b = 0; b < 3; b++) { 294 table[a][b] = 0; 295 } 296 } 297 for(int i = 0; i < num_moves; i++) { 298 String[] cells = rows[i].split(","); 299 int pid = Integer.parseInt(cells[0]); 300 int x = Integer.parseInt(cells[1]); 301 int y = Integer.parseInt(cells[2]); 302 table[x][y] = pid; 303 } 304 305 //check rows and cols 306 for(int t = 0; t < 3; t++) { 307 if(table[t][0] == table[t][1] && table[t][1] == table[t][2] && table[t][0] != 0) { 308 winner = table[t][0]; 309 } 310 if(table[0][t] == table[1][t] && table[1][t] == table[2][t] && table[0][t] != 0) { 311 winner = table[0][t]; 312 } 313 } 314 315 //Check diagonals 316 if(table[0][0] == table[1][1] && table[1][1] == table[2][2] && table[0][0] != 0) { 317 winner = table[0][0]; 318 } 319 if(table[0][2] == table[1][1] && table[1][1] == table[2][0] && table[0][2] != 0) { 320 winner = table[0][2]; 321 } 322 323 if(winner > 0) { 324 try { 325 // check is winner p1 or p2; 326 String sqlCmd = "SELECT * FROM games WHERE autokey = " + gid + ";"; 327 String gDetails = dao.retrieve(sqlCmd); 328 if(gDetails.length() > 0) { 329 String[] details = gDetails.split(","); 330 if(details.length > 0) { 331 int p1 = Integer.parseInt(details[1]); 332 int p2 = Integer.parseInt(details[2]); 333 if(winner == p1) { 334 return "1"; 335 } else { 336 return "2"; 337 } 338 } else { 339 return "ERROR-RETRIEVE"; 340 } 341 } else { 342 return "ERROR-RETRIEVE"; 343 } 344 } catch(Exception e) { 345 return "ERROR-DB"; 346 } 347 } else { 348 if(num_moves < 9) { 349 return "0"; 350 } else { 351 return "3"; 352 } 353 } 354 } else { 355 return "ERROR-NOGAME"; 356 } 357 } 358 359 /** 360 * Used to remove un-started games from the DB. 361 * @param gid the game id of the game you wish to remove. 362 * @param uid the user id of the person making the request (can only delete games you created). 363 * @return If the game has already started or the user is not the creator of the game, the method returns “ERROR-GAMESTARTED”, 364 * otherwise it returns 1 (as a string). The method returns “ERROR-DB” if it cannot access the DBMS. 365 */ 366 @WebMethod(operationName = "deleteGame") 367 public String deleteGame(@WebParam(name = "gid") int gid, @WebParam(name = "uid") int uid) { 368 String sqlCmd = "SELECT COUNT(*) FROM games WHERE autokey = " + gid + " AND p1 = "; 369 sqlCmd += uid + " AND p2 IS NULL;"; 370 try { 371 String result = dao.retrieve(sqlCmd); 372 if(result.equals("1")) { 373 sqlCmd = "DELETE FROM moves WHERE gID = " + gid + ";"; // delete moves first 374 result = dao.remove(sqlCmd); // run the SQL statement 375 sqlCmd = "DELETE FROM games WHERE autokey = " + gid + ";"; 376 result = dao.remove(sqlCmd); 377 return "1"; 378 } else { 379 return "ERROR-GAMESTARTED"; 380 } 381 } catch(Exception e) { 382 return "ERROR-DB"; 383 } 384 } 385 386 /** 387 * Used to show games you have created but that have not yet started. 388 * @param uid the user id of the player making the request. 389 * @return If the method is successful it returns a string as follows {{g.autokey, u.username, g.started}\n}*. If unsuccessful, the method returns 390 * “ERROR-NOGAMES” if it can find no games, or “ERROR-DB” if it cannot access the DBMS. 391 */ 392 @WebMethod(operationName = "showMyOpenGames") 393 public String showMyOpenGames(@WebParam(name = "uid") int uid) { 394 String sqlCmd = "SELECT g.autokey, u.username, g.started FROM games g, users u WHERE g.p1 = " + uid + " AND g.p2 IS NULL AND g.p1 = u.autokey ORDER BY g.started ASC;"; 395 try { 396 String result = dao.retrieve(sqlCmd); 397 if(result.length() > 0) { 398 return result; 399 } else { 400 return "ERROR-NOGAMES"; 401 } 402 } catch(Exception e) { 403 return "ERROR-DB"; 404 } 405 } 406 407 /** 408 * Retrieves all games the user has played/is playing. 409 * @param uid the user id of the player making the request. 410 * @return If successful it returns a string as follows {{g.autokey, h.username, o.username, g.started}\n}*. h.username and o.username are the 411 * usernames of player 1 and player 2 respectively. If unsuccessful, the method returns “ERROR-NOGAMES” if it can find no games, or “ERROR-DB” 412 * if it cannot access the DBMS. 413 */ 414 @WebMethod(operationName = "showAllMyGames") 415 public String showAllMyGames(@WebParam(name = "uid") int uid) { 416 String sqlCmd = "SELECT g.autokey, h.username, o.username, g.started FROM games g, users h, users o WHERE (g.p1 = " + uid + " OR g.p2 = " + uid + ") AND g.p1 = h.autokey AND g.p2 = o.autokey ORDER BY g.started ASC;"; 417 try { 418 String result = dao.retrieve(sqlCmd); 419 if(result.length() > 0) { 420 return result; 421 } else { 422 return "ERROR-NOGAMES"; 423 } 424 } catch(Exception e) { 425 return "ERROR-DB"; 426 } 427 } 428 429 /** 430 * Used to generate the content for a league table. 431 * @return If successful it returns a string as follows {{g.autokey, h.username, o.username, g.gamestate, g.started}\n}*. h.username and o.username 432 * are the usernames of player 1 and player 2 respectively. If unsuccessful, the method returns “ERROR-NOGAMES” if it can find no games, or “ERROR-DB” 433 * if it cannot access the DBMS. 434 */ 435 @WebMethod(operationName = "leagueTable") 436 public String leagueTable() { 437 String sqlCmd = "SELECT g.autokey, h.username, o.username, g.gamestate, g.started FROM games g, users h, users o WHERE g.p1 = h.autokey AND g.p2 = o.autokey ORDER BY g.started ASC;"; 438 try { 439 String result = dao.retrieve(sqlCmd); 440 if(result.length() > 0) { 441 return result; 442 } else { 443 return "ERROR-NOGAMES"; 444 } 445 } catch(Exception e) { 446 return "ERROR-DB"; 447 } 448 } 449 450 /** 451 * The list of open games (those with a p1 but no p2). 452 * @return If successful it returns a string as follows {{g.autokey, h.username, g.started}\n}*. h.username is the usernames of the player who started 453 * the game. If unsuccessful, the method returns “ERROR-NOGAMES” if it can find no games, or “ERROR-DB” if it cannot access the DBMS. 454 */ 455 @WebMethod(operationName = "showOpenGames") 456 public String showOpenGames() { 457 String sqlCmd = "SELECT g.autokey, h.username, g.started FROM games g, users h WHERE g.p2 IS NULL AND g.p1 = h.autokey ORDER BY g.started ASC;"; 458 try { 459 String result = dao.retrieve(sqlCmd); 460 if(result.length() > 0) { 461 return result; 462 } else { 463 return "ERROR-NOGAMES"; 464 } 465 } catch(Exception e) { 466 return "ERROR-DB"; 467 } 468 } 469 470 /** 471 * Closes the connection to the database (before exiting the application). 472 */ 473 @WebMethod(operationName = "closeConnection") 474 public void closeConnection() { 475 dao.close(); 476 } 477 }