diff --git a/packages/server/data/migrations/20200120224032_game.js b/packages/server/data/migrations/20200120224032_game.js index 67c6a0e..16916df 100644 --- a/packages/server/data/migrations/20200120224032_game.js +++ b/packages/server/data/migrations/20200120224032_game.js @@ -1,49 +1,81 @@ -const winType = [ - 'B+R', 'B+', 'B+T', - 'W+R', 'W+', 'W+T', - '0', 'Void', '?' -] +const winType = ["B+R", "B+", "B+T", "W+R", "W+", "W+T", "0", "Void", "?"]; const rankArray = [ - 'D9', 'D8', 'D7', 'D6', 'D5', 'D4', 'D3', 'D2', 'D1', - 'K1', 'K2', 'K3', 'K4', 'K5', 'K6', 'K7', 'K8', 'K9', 'K10', - 'K11', 'K12', 'K13', 'K14', 'K15', 'K16', 'K17', 'K18', 'K19', 'K20', - 'K21', 'K22', 'K23', 'K24', 'K25', 'K26', 'K27', 'K28', 'K29', 'K30', 'UR' -] + "D9", + "D8", + "D7", + "D6", + "D5", + "D4", + "D3", + "D2", + "D1", + "K1", + "K2", + "K3", + "K4", + "K5", + "K6", + "K7", + "K8", + "K9", + "K10", + "K11", + "K12", + "K13", + "K14", + "K15", + "K16", + "K17", + "K18", + "K19", + "K20", + "K21", + "K22", + "K23", + "K24", + "K25", + "K26", + "K27", + "K28", + "K29", + "K30", + "UR", +]; -exports.up = function(knex) { - return knex.schema.createTable("game", table => { - table.increments('id').primary(); - table.datetime('date'); - table.float('komi').default(6.5); - table.integer('handicap').default(0); - table.integer('board_size').default(19); - table.boolean('open').default(true); +exports.up = function (knex) { + return knex.schema.createTable("game", (table) => { + table.increments("id").primary(); + table.datetime("date"); + table.float("komi").default(6.5); + table.integer("handicap").default(0); + table.integer("board_size").default(19); + table.boolean("open").default(true); - table.string('application'); - table.string('application_version'); + table.string("application"); + table.string("application_version"); table.timestamps(true, true); - table.string('player_black'); - table.string('player_white'); - table.enu('player_black_rank', rankArray).default('UR'); - table.enu('player_white_rank', rankArray).default('UR'); - - table.string('event'); - table.string('name'); - table.string('description'); - table.integer('round'); - - table.enu('win_type', winType); - table.float('score'); - table.integer('captures_black'); - table.integer('captures_white'); + table.string("player_black"); + table.string("player_white"); + table.enu("player_black_rank", rankArray).default("UR"); + table.enu("player_white_rank", rankArray).default("UR"); - table.integer('user_black').references('id').inTable('user'); - table.integer('user_white').references('id').inTable('user'); - table.integer('room').references('id').inTable('room'); - table.integer('time_setting').references('id').inTable('time_setting'); - }) + table.string("event"); + table.string("name"); + table.string("description"); + table.integer("round"); + + table.enu("win_type", winType); + table.float("score"); + table.integer("captures_black"); + table.integer("captures_white"); + + table.integer("user_black").references("id").inTable("user"); + table.integer("user_white").references("id").inTable("user"); + table.integer("room").references("id").inTable("room"); + table.integer("time_setting").references("id").inTable("time_setting"); + }); }; -exports.down = knex => knex.schema.dropTableIfExists("game"); \ No newline at end of file +exports.down = (knex) => knex.schema.dropTableIfExists("game"); diff --git a/packages/server/data/migrations/20200120230921_move.js b/packages/server/data/migrations/20200120230921_move.js index c5543d0..19c197e 100644 --- a/packages/server/data/migrations/20200120230921_move.js +++ b/packages/server/data/migrations/20200120230921_move.js @@ -1,17 +1,18 @@ -const players = ['white', 'black'] +const players = ["white", "black"]; -exports.up = knex => { - return knex.schema.createTable("move", table => { - table.increments('id').primary(); - table.enu('player', players).notNullable(); - table.integer('point_x').notNullable(); - table.integer('point_y').notNullable(); - table.integer('number').notNullable(); - table.boolean('game_record').notNullable().default(true); +exports.up = (knex) => { + return knex.schema.createTable("move", (table) => { + table.increments("id").primary(); + table.enu("player", players).notNullable(); + table.integer("point_x").notNullable(); + table.integer("point_y").notNullable(); + table.integer("number").notNullable(); + table.boolean("game_record").notNullable().default(true); + table.boolean("placement").notNullable().default(false); - table.integer('game').references('id').inTable('game').notNullable(); - table.integer('prior_move').references('id').inTable('move'); + table.integer("game").references("id").inTable("game").notNullable(); + table.integer("prior_move").references("id").inTable("move"); }); }; -exports.down = knex => knex.schema.dropTableIfExists("move"); +exports.down = (knex) => knex.schema.dropTableIfExists("move"); diff --git a/packages/server/data/queries/game.js b/packages/server/data/queries/game.js index 4cdf503..4b5a701 100644 --- a/packages/server/data/queries/game.js +++ b/packages/server/data/queries/game.js @@ -70,17 +70,23 @@ const findGameByRoom = async (roomId) => { const insertGame = async (game) => {}; -const endGame = async ({ id }) => { - const game = await knex(game).where({ id: id }).update( - { - win_type: winType, - score: score, - captures_black: capturesBlack, - captures_white: capturesWhite, - } - // ["id"] - ); - return game; +const endGame = async ({ id, winType, score, bCaptures, wCaptures }) => { + try { + const game = await knex + .from("game") + .returning(gameDetailSelect) + .where({ id: id }) + .update({ + win_type: winType, + score: score, + captures_black: bCaptures, + captures_white: wCaptures, + open: false, + }); + return game; + } catch (e) { + return e; + } }; module.exports = { diff --git a/packages/server/data/queries/move.js b/packages/server/data/queries/move.js index cbe69fe..a8c79eb 100644 --- a/packages/server/data/queries/move.js +++ b/packages/server/data/queries/move.js @@ -1,36 +1,47 @@ -const knex = require('../db'); +const knex = require("../db"); const findGameRecord = async (gameId) => { - return await knex('move') - .where({ 'game': gameId, 'game_record': true }) - .select('player', 'point_x', 'point_y', 'number') - .orderBy('number') - .then(record => record.map(({player, point_x, point_y}) => ({player, pos: { x: point_x, y: point_y } }) )) + return await knex("move") + .where({ game: gameId, game_record: true }) + .select("player", "point_x", "point_y", "number", "prior_move", "placement") + .orderBy("number") + .then((record) => + record.map(({ player, point_x, point_y }) => ({ + player, + pos: { x: point_x, y: point_y }, + })) + ); // .then(res => res) -} +}; // id: 1, player: 'black', point_x: 3, point_y: 3, number: 1, game_record: true, game: 1, prior_move: null const addMove = async ({ gameId, player, x, y, gameRecord, priorMove }) => { + // ! priorMove must be FK not move number const number = priorMove + 1; let result; - try { - result = await knex('move') - .returning('*') - .insert({ game: gameId, player, point_x: x, point_y: y, number, game_record: gameRecord, prior_move: priorMove }) - .then(res => res); - } - catch (e) { - result = e - } - finally { + try { + result = await knex("move") + .returning("*") + .insert({ + game: gameId, + player, + point_x: x, + point_y: y, + number, + game_record: gameRecord, + prior_move: priorMove, + }) + .then((res) => res); + } catch (e) { + result = e; + } finally { console.log(result); return result; } - -} +}; module.exports = { findGameRecord, - addMove -} \ No newline at end of file + addMove, +}; diff --git a/packages/server/services/Game.js b/packages/server/services/Game.js index ac257aa..dcdae92 100644 --- a/packages/server/services/Game.js +++ b/packages/server/services/Game.js @@ -181,13 +181,18 @@ const Game = ({ gameData = {}, gameRecord = [] } = {}) => { this.kos = []; }, }; - if (gameRecord.length) { // play through all the moves - return gameRecord.reduce( + const game = gameRecord.reduce( (game, move) => game.makeMove(move), Game({ gameData }).initGame() ); + // ? why is this being wrapped? + if (gameData && gameData.gameData && gameData.gameData.winner) { + const { winner, score } = gameData.gameData; + return game.manualEnd({ winner, score }); + } + return game; } return { winner: gameData.winner || null, @@ -389,6 +394,14 @@ const Game = ({ gameData = {}, gameRecord = [] } = {}) => { this.playerState.bScore - (this.playerState.wScore + this.komi); return { ...this, score, winner: score > 0 ? 1 : -1 }; }, + + // for playing historic games + manualEnd: function ({ winner, score }) { + this.turn = 0; + this.winner = winner; + this.score = score; + return this; + }, }; }; diff --git a/packages/server/services/gameServices.js b/packages/server/services/gameServices.js index c85a83f..d0c9d4d 100644 --- a/packages/server/services/gameServices.js +++ b/packages/server/services/gameServices.js @@ -11,7 +11,6 @@ const GameService = ({ moveQueries, gameQueries }) => { initGame({ id, gameRecord = [], ...gameData }) { if (gamesInProgress[id]) return this.getDataForUI(id); if (gameRecord.length) { - console.log("here"); gamesInProgress[id] = Game({ gameData, gameRecord }); } else { gamesInProgress[id] = Game({ gameData }).initGame(); @@ -73,6 +72,7 @@ const GameService = ({ moveQueries, gameQueries }) => { }, resign: ({ id, player }) => { + // add resign gamesQueries return gamesInProgress[id].submitResign(player).getMeta(); }, @@ -108,9 +108,19 @@ const GameService = ({ moveQueries, gameQueries }) => { async endGame({ id }) { gamesInProgress[id] = gamesInProgress[id].endGame(); + const { winner, score, playerState } = gamesInProgress[id]; + const { bCaptures, wCaptures } = playerState; + const winType = winner > 0 ? "B+" : "W+"; try { if (gameQueries) { - // TODO add end game query + const result = await gameQueries.endGame({ + id, + winType, + score, + bCaptures, + wCaptures, + }); + console.log(result); } } catch (e) { console.log(e); diff --git a/packages/server/socket.js b/packages/server/socket.js index 82a2fbd..c308053 100644 --- a/packages/server/socket.js +++ b/packages/server/socket.js @@ -24,8 +24,22 @@ io.on("connection", async (socket) => { socket.on("connect_game", (data) => { const game = `game-${data.game.id}`; socket.join(game, async () => { + const gameData = await gameQueries.findGameById(data.game.id); + const convertWinType = (winType) => { + if (winType.includes("B")) return 1; + if (winType.includes("W")) return -1; + if (winType.includes("0")) return "D"; + return "?"; + }; + gameData.winner = gameData.win_type + ? convertWinType(gameData.win_type) + : 0; const gameRecord = await moveQueries.findGameRecord(data.game.id); - await gameServices.initGame({ id: data.game.id, gameRecord }); + await gameServices.initGame({ + id: data.game.id, + gameRecord, + gameData, + }); const { board, ...meta } = await gameServices.getDataForUI( data.game.id );