From 910ccf1804033a940a36273e21d4a586a26a6145 Mon Sep 17 00:00:00 2001 From: syuilo Date: Fri, 9 Mar 2018 18:11:10 +0900 Subject: [PATCH] =?UTF-8?q?=E3=81=AA=E3=82=93=E3=81=8B=E3=82=82=E3=81=86?= =?UTF-8?q?=E3=82=81=E3=81=A3=E3=81=A1=E3=82=83=E5=A4=89=E3=81=88=E3=81=9F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/api/endpoints/othello/games.ts | 41 +- src/api/endpoints/othello/match.ts | 2 +- src/api/models/othello-game.ts | 16 +- src/common/othello/core.ts | 33 +- src/common/othello/maps.ts | 618 ++++++++++-------- .../common/views/components/othello.game.vue | 6 +- .../common/views/components/othello.room.vue | 16 +- 7 files changed, 425 insertions(+), 307 deletions(-) diff --git a/src/api/endpoints/othello/games.ts b/src/api/endpoints/othello/games.ts index dd9fb5ef5..dd3ee523a 100644 --- a/src/api/endpoints/othello/games.ts +++ b/src/api/endpoints/othello/games.ts @@ -6,6 +6,23 @@ module.exports = (params, user) => new Promise(async (res, rej) => { const [my = false, myErr] = $(params.my).optional.boolean().$; if (myErr) return rej('invalid my param'); + // Get 'limit' parameter + const [limit = 10, limitErr] = $(params.limit).optional.number().range(1, 100).$; + if (limitErr) return rej('invalid limit param'); + + // Get 'since_id' parameter + const [sinceId, sinceIdErr] = $(params.since_id).optional.id().$; + if (sinceIdErr) return rej('invalid since_id param'); + + // Get 'until_id' parameter + const [untilId, untilIdErr] = $(params.until_id).optional.id().$; + if (untilIdErr) return rej('invalid until_id param'); + + // Check if both of since_id and until_id is specified + if (sinceId && untilId) { + return rej('cannot set since_id and until_id'); + } + const q = my ? { is_started: true, $or: [{ @@ -17,13 +34,29 @@ module.exports = (params, user) => new Promise(async (res, rej) => { is_started: true }; + + const sort = { + _id: -1 + }; + + if (sinceId) { + sort._id = 1; + q._id = { + $gt: sinceId + }; + } else if (untilId) { + q._id = { + $lt: untilId + }; + } + // Fetch games const games = await Game.find(q, { - sort: { - _id: -1 - } + sort }); // Reponse - res(Promise.all(games.map(async (g) => await pack(g, user)))); + res(Promise.all(games.map(async (g) => await pack(g, user, { + detail: false + })))); }); diff --git a/src/api/endpoints/othello/match.ts b/src/api/endpoints/othello/match.ts index 05b87a541..640be9cb5 100644 --- a/src/api/endpoints/othello/match.ts +++ b/src/api/endpoints/othello/match.ts @@ -38,7 +38,7 @@ module.exports = (params, user) => new Promise(async (res, rej) => { is_ended: false, logs: [], settings: { - map: eighteight, + map: eighteight.data, bw: 'random', is_llotheo: false } diff --git a/src/api/models/othello-game.ts b/src/api/models/othello-game.ts index de7c804c4..7ae48b8aa 100644 --- a/src/api/models/othello-game.ts +++ b/src/api/models/othello-game.ts @@ -28,7 +28,7 @@ export interface IGame { winner_id: mongo.ObjectID; logs: any[]; settings: { - map: Map; + map: string[]; bw: string | number; is_llotheo: boolean; }; @@ -39,8 +39,15 @@ export interface IGame { */ export const pack = ( game: any, - me?: string | mongo.ObjectID | IUser + me?: string | mongo.ObjectID | IUser, + options?: { + detail?: boolean + } ) => new Promise(async (resolve, reject) => { + const opts = Object.assign({ + detail: true + }, options); + let _game: any; // Populate the game if 'game' is ID @@ -69,6 +76,11 @@ export const pack = ( _game.id = _game._id; delete _game._id; + if (opts.detail === false) { + delete _game.logs; + delete _game.settings.map; + } + // Populate user _game.user1 = await packUser(_game.user1_id, meId); _game.user2 = await packUser(_game.user2_id, meId); diff --git a/src/common/othello/core.ts b/src/common/othello/core.ts index b76586031..0b4cb1fc1 100644 --- a/src/common/othello/core.ts +++ b/src/common/othello/core.ts @@ -1,5 +1,3 @@ -import { Map } from './maps'; - export type Color = 'black' | 'white'; export type MapPixel = 'null' | 'empty'; @@ -11,12 +9,14 @@ export type Options = { * オセロエンジン */ export default class Othello { - public map: Map; - public mapData: MapPixel[]; + public map: MapPixel[]; + public mapWidth: number; + public mapHeight: number; public board: Color[]; public turn: Color = 'black'; public opts: Options; + public prevPos = -1; public stats: Array<{ b: number; w: number; @@ -25,18 +25,21 @@ export default class Othello { /** * ゲームを初期化します */ - constructor(map: Map, opts: Options) { - this.map = map; + constructor(map: string[], opts: Options) { this.opts = opts; + this.mapWidth = map[0].length; + this.mapHeight = map.length; + const mapData = map.join(''); + // Parse map data - this.board = this.map.data.split('').map(d => { + this.board = mapData.split('').map(d => { if (d == '-') return null; if (d == 'b') return 'black'; if (d == 'w') return 'white'; return undefined; }); - this.mapData = this.map.data.split('').map(d => { + this.map = mapData.split('').map(d => { if (d == '-' || d == 'b' || d == 'w') return 'empty'; return 'null'; }); @@ -48,8 +51,6 @@ export default class Othello { }]; } - public prevPos = -1; - /** * 黒石の数 */ @@ -79,13 +80,13 @@ export default class Othello { } public transformPosToXy(pos: number): number[] { - const x = pos % this.map.size; - const y = Math.floor(pos / this.map.size); + const x = pos % this.mapWidth; + const y = Math.floor(pos / this.mapHeight); return [x, y]; } public transformXyToPos(x: number, y: number): number { - return x + (y * this.map.size); + return x + (y * this.mapHeight); } /** @@ -145,8 +146,8 @@ export default class Othello { * @param pos 位置 */ public mapDataGet(pos: number): MapPixel { - if (pos < 0 || pos >= this.mapData.length) return 'null'; - return this.mapData[pos]; + if (pos < 0 || pos >= this.map.length) return 'null'; + return this.map[pos]; } /** @@ -188,7 +189,7 @@ export default class Othello { const found = []; while (true) { const [x, y] = fn(i); - if (x < 0 || y < 0 || x >= this.map.size || y >= this.map.size) break; + if (x < 0 || y < 0 || x >= this.mapWidth || y >= this.mapHeight) break; const pos = this.transformXyToPos(x, y); const pixel = this.mapDataGet(pos); if (pixel == 'null') break; diff --git a/src/common/othello/maps.ts b/src/common/othello/maps.ts index 434fd75af..d8f3154a0 100644 --- a/src/common/othello/maps.ts +++ b/src/common/othello/maps.ts @@ -11,438 +11,502 @@ export type Map = { name?: string; category?: string; - size: number; - data: string; + author?: string; + data: string[]; }; export const fourfour: Map = { name: '4x4', category: '4x4', - size: 4, - data: - '----' + - '-wb-' + - '-bw-' + + data: [ + '----', + '-wb-', + '-bw-', '----' + ] }; export const sixsix: Map = { name: '6x6', category: '6x6', - size: 6, - data: - '------' + - '------' + - '--wb--' + - '--bw--' + - '------' + + data: [ + '------', + '------', + '--wb--', + '--bw--', + '------', '------' + ] }; export const roundedSixsix: Map = { name: '6x6 rounded', category: '6x6', - size: 6, - data: - ' ---- ' + - '------' + - '--wb--' + - '--bw--' + - '------' + + author: 'syuilo', + data: [ + ' ---- ', + '------', + '--wb--', + '--bw--', + '------', ' ---- ' + ] }; export const roundedSixsix2: Map = { name: '6x6 rounded 2', category: '6x6', - size: 6, - data: - ' -- ' + - ' ---- ' + - '--wb--' + - '--bw--' + - ' ---- ' + + author: 'syuilo', + data: [ + ' -- ', + ' ---- ', + '--wb--', + '--bw--', + ' ---- ', ' -- ' + ] }; export const eighteight: Map = { name: '8x8', category: '8x8', - size: 8, - data: - '--------' + - '--------' + - '--------' + - '---wb---' + - '---bw---' + - '--------' + - '--------' + + data: [ + '--------', + '--------', + '--------', + '---wb---', + '---bw---', + '--------', + '--------', '--------' + ] }; export const roundedEighteight: Map = { name: '8x8 rounded', category: '8x8', - size: 8, - data: - ' ------ ' + - '--------' + - '--------' + - '---wb---' + - '---bw---' + - '--------' + - '--------' + + author: 'syuilo', + data: [ + ' ------ ', + '--------', + '--------', + '---wb---', + '---bw---', + '--------', + '--------', ' ------ ' + ] }; export const roundedEighteight2: Map = { name: '8x8 rounded 2', category: '8x8', - size: 8, - data: - ' ---- ' + - ' ------ ' + - '--------' + - '---wb---' + - '---bw---' + - '--------' + - ' ------ ' + + author: 'syuilo', + data: [ + ' ---- ', + ' ------ ', + '--------', + '---wb---', + '---bw---', + '--------', + ' ------ ', ' ---- ' + ] }; export const roundedEighteight3: Map = { name: '8x8 rounded 3', category: '8x8', - size: 8, - data: - ' -- ' + - ' ---- ' + - ' ------ ' + - '---wb---' + - '---bw---' + - ' ------ ' + - ' ---- ' + + author: 'syuilo', + data: [ + ' -- ', + ' ---- ', + ' ------ ', + '---wb---', + '---bw---', + ' ------ ', + ' ---- ', ' -- ' + ] }; export const eighteightWithNotch: Map = { name: '8x8 with notch', category: '8x8', - size: 8, - data: - '--- ---' + - '--------' + - '--------' + - ' --wb-- ' + - ' --bw-- ' + - '--------' + - '--------' + + author: 'syuilo', + data: [ + '--- ---', + '--------', + '--------', + ' --wb-- ', + ' --bw-- ', + '--------', + '--------', '--- ---' + ] }; export const eighteightWithSomeHoles: Map = { name: '8x8 with some holes', category: '8x8', - size: 8, - data: - '--- ----' + - '----- --' + - '-- -----' + - '---wb---' + - '---bw- -' + - ' -------' + - '--- ----' + + author: 'syuilo', + data: [ + '--- ----', + '----- --', + '-- -----', + '---wb---', + '---bw- -', + ' -------', + '--- ----', '--------' + ] }; export const circle: Map = { name: 'Circle', category: '8x8', - size: 8, - data: - ' -- ' + - ' ------ ' + - ' ------ ' + - '---wb---' + - '---bw---' + - ' ------ ' + - ' ------ ' + + author: 'syuilo', + data: [ + ' -- ', + ' ------ ', + ' ------ ', + '---wb---', + '---bw---', + ' ------ ', + ' ------ ', ' -- ' + ] }; -export const face: Map = { - name: 'Face', +export const smile: Map = { + name: 'Smile', category: '8x8', - size: 8, - data: - ' ------ ' + - '--------' + - '-- -- --' + - '---wb---' + - '-- bw --' + - '--- ---' + - '--------' + + author: 'syuilo', + data: [ + ' ------ ', + '--------', + '-- -- --', + '---wb---', + '-- bw --', + '--- ---', + '--------', ' ------ ' + ] }; export const window: Map = { name: 'Window', category: '8x8', - size: 8, - data: - '--------' + - '- -- -' + - '- -- -' + - '---wb---' + - '---bw---' + - '- -- -' + - '- -- -' + + author: 'syuilo', + data: [ + '--------', + '- -- -', + '- -- -', + '---wb---', + '---bw---', + '- -- -', + '- -- -', '--------' + ] }; export const reserved: Map = { name: 'Reserved', category: '8x8', - size: 8, - data: - 'w------b' + - '--------' + - '--------' + - '---wb---' + - '---bw---' + - '--------' + - '--------' + + author: 'Aya', + data: [ + 'w------b', + '--------', + '--------', + '---wb---', + '---bw---', + '--------', + '--------', 'b------w' + ] }; export const x: Map = { name: 'X', category: '8x8', - size: 8, - data: - 'w------b' + - '-w----b-' + - '--w--b--' + - '---wb---' + - '---bw---' + - '--b--w--' + - '-b----w-' + + author: 'Aya', + data: [ + 'w------b', + '-w----b-', + '--w--b--', + '---wb---', + '---bw---', + '--b--w--', + '-b----w-', 'b------w' + ] +}; + +export const minesweeper: Map = { + name: 'Minesweeper', + category: '8x8', + author: 'syuilo', + data: [ + 'b-b--w-w', + '-w-wb-b-', + 'w-b--w-b', + '-b-wb-w-', + '-w-bw-b-', + 'b-w--b-w', + '-b-bw-w-', + 'w-w--b-b' + ] }; export const tenthtenth: Map = { name: '10x10', category: '10x10', - size: 10, - data: - '----------' + - '----------' + - '----------' + - '----------' + - '----wb----' + - '----bw----' + - '----------' + - '----------' + - '----------' + + data: [ + '----------', + '----------', + '----------', + '----------', + '----wb----', + '----bw----', + '----------', + '----------', + '----------', '----------' + ] }; export const hole: Map = { name: 'The Hole', category: '10x10', - size: 10, - data: - '----------' + - '----------' + - '--wb--wb--' + - '--bw--bw--' + - '---- ----' + - '---- ----' + - '--wb--wb--' + - '--bw--bw--' + - '----------' + + author: 'syuilo', + data: [ + '----------', + '----------', + '--wb--wb--', + '--bw--bw--', + '---- ----', + '---- ----', + '--wb--wb--', + '--bw--bw--', + '----------', '----------' + ] }; export const grid: Map = { name: 'Grid', category: '10x10', - size: 10, - data: - '----------' + - '- - -- - -' + - '----------' + - '- - -- - -' + - '----wb----' + - '----bw----' + - '- - -- - -' + - '----------' + - '- - -- - -' + + author: 'syuilo', + data: [ + '----------', + '- - -- - -', + '----------', + '- - -- - -', + '----wb----', + '----bw----', + '- - -- - -', + '----------', + '- - -- - -', '----------' + ] }; export const cross: Map = { name: 'Cross', category: '10x10', - size: 10, - data: - ' ---- ' + - ' ---- ' + - ' ---- ' + - '----------' + - '----wb----' + - '----bw----' + - '----------' + - ' ---- ' + - ' ---- ' + + author: 'Aya', + data: [ + ' ---- ', + ' ---- ', + ' ---- ', + '----------', + '----wb----', + '----bw----', + '----------', + ' ---- ', + ' ---- ', ' ---- ' + ] +}; + +export const charX: Map = { + name: 'Char X', + category: '10x10', + author: 'syuilo', + data: [ + '--- ---', + '---- ----', + '----------', + ' -------- ', + ' --wb-- ', + ' --bw-- ', + ' -------- ', + '----------', + '---- ----', + '--- ---' + ] +}; + +export const charY: Map = { + name: 'Char Y', + category: '10x10', + author: 'syuilo', + data: [ + '--- ---', + '---- ----', + '----------', + ' -------- ', + ' --wb-- ', + ' --bw-- ', + ' ------ ', + ' ------ ', + ' ------ ', + ' ------ ' + ] }; export const walls: Map = { name: 'Walls', category: '10x10', - size: 10, - data: - ' bbbbbbbb ' + - 'w--------w' + - 'w--------w' + - 'w--------w' + - 'w---wb---w' + - 'w---bw---w' + - 'w--------w' + - 'w--------w' + - 'w--------w' + + author: 'Aya', + data: [ + ' bbbbbbbb ', + 'w--------w', + 'w--------w', + 'w--------w', + 'w---wb---w', + 'w---bw---w', + 'w--------w', + 'w--------w', + 'w--------w', ' bbbbbbbb ' + ] }; export const checker: Map = { name: 'Checker', category: '10x10', - size: 10, - data: - '----------' + - '----------' + - '----------' + - '---wbwb---' + - '---bwbw---' + - '---wbwb---' + - '---bwbw---' + - '----------' + - '----------' + + author: 'Aya', + data: [ + '----------', + '----------', + '----------', + '---wbwb---', + '---bwbw---', + '---wbwb---', + '---bwbw---', + '----------', + '----------', '----------' + ] }; export const sixeight: Map = { name: '6x8', category: 'special', - size: 8, - data: - ' ------ ' + - ' ------ ' + - ' ------ ' + - ' --wb-- ' + - ' --bw-- ' + - ' ------ ' + - ' ------ ' + - ' ------ ' + data: [ + '------', + '------', + '------', + '--wb--', + '--bw--', + '------', + '------', + '------' + ] }; export const spark: Map = { name: 'Spark', category: 'special', - size: 10, - data: - ' - - ' + - '----------' + - ' -------- ' + - ' -------- ' + - ' ---wb--- ' + - ' ---bw--- ' + - ' -------- ' + - ' -------- ' + - '----------' + + author: 'syuilo', + data: [ + ' - - ', + '----------', + ' -------- ', + ' -------- ', + ' ---wb--- ', + ' ---bw--- ', + ' -------- ', + ' -------- ', + '----------', ' - - ' + ] }; export const islands: Map = { name: 'Islands', category: 'special', - size: 10, - data: - '-------- ' + - '---wb--- ' + - '---bw--- ' + - '-------- ' + - ' - - ' + - ' - - ' + - ' --------' + - ' --------' + - ' --------' + + author: 'syuilo', + data: [ + '-------- ', + '---wb--- ', + '---bw--- ', + '-------- ', + ' - - ', + ' - - ', + ' --------', + ' --------', + ' --------', ' --------' + ] }; export const iphonex: Map = { name: 'iPhone X', category: 'special', - size: 12, - data: - ' -- -- ' + - ' -------- ' + - ' -------- ' + - ' -------- ' + - ' -------- ' + - ' ---wb--- ' + - ' ---bw--- ' + - ' -------- ' + - ' -------- ' + - ' -------- ' + - ' -------- ' + - ' ------ ' + author: 'syuilo', + data: [ + ' -- -- ', + '--------', + '--------', + '--------', + '--------', + '---wb---', + '---bw---', + '--------', + '--------', + '--------', + '--------', + ' ------ ' + ] }; export const bigBoard: Map = { name: 'Big board', category: 'special', - size: 16, - data: - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '-------wb-------' + - '-------bw-------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + - '----------------' + + data: [ + '----------------', + '----------------', + '----------------', + '----------------', + '----------------', + '----------------', + '----------------', + '-------wb-------', + '-------bw-------', + '----------------', + '----------------', + '----------------', + '----------------', + '----------------', + '----------------', '----------------' + ] }; export const twoBoard: Map = { name: 'Two board', category: 'special', - size: 17, - data: - '-------- --------' + - '-------- --------' + - '-------- --------' + - '---wb--- ---wb---' + - '---bw--- ---bw---' + - '-------- --------' + - '-------- --------' + - '-------- --------' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + - ' ' + author: 'Aya', + data: [ + '-------- --------', + '-------- --------', + '-------- --------', + '---wb--- ---wb---', + '---bw--- ---bw---', + '-------- --------', + '-------- --------', + '-------- --------' + ] }; diff --git a/src/web/app/common/views/components/othello.game.vue b/src/web/app/common/views/components/othello.game.vue index ffda68c8d..248528ed4 100644 --- a/src/web/app/common/views/components/othello.game.vue +++ b/src/web/app/common/views/components/othello.game.vue @@ -10,9 +10,9 @@

-
+
@@ -106,6 +106,8 @@ export default Vue.extend({ this.o.put(log.color, log.pos); }); + console.log(this.o); + this.logs = this.game.logs; this.logPos = this.logs.length; }, diff --git a/src/web/app/common/views/components/othello.room.vue b/src/web/app/common/views/components/othello.room.vue index bcae37b22..0fcca8548 100644 --- a/src/web/app/common/views/components/othello.room.vue +++ b/src/web/app/common/views/components/othello.room.vue @@ -4,14 +4,17 @@

ゲームの設定

- + - + + {{ m.name }} + (by {{ m.author }}) + -
-
+
@@ -112,7 +115,7 @@ export default Vue.extend({ }, onMapChange(v) { - this.game.settings.map = Object.entries(maps).find(x => x[1].name == v)[1]; + this.game.settings.map = Object.entries(maps).find(x => x[1].name == v)[1].data; this.connection.send({ type: 'update-settings', settings: this.game.settings @@ -141,6 +144,9 @@ export default Vue.extend({ padding 8px border-bottom dashed 1px #c4cdd4 + > .map + width 300px + > .board display grid grid-gap 4px