puzzle/src/server/GameStorage.ts

102 lines
2.5 KiB
TypeScript
Raw Normal View History

2021-04-30 21:00:30 +02:00
import fs from 'fs'
2021-05-29 17:58:05 +02:00
import GameCommon from './../common/GameCommon'
import { Piece, ScoreMode } from './../common/Types'
2021-05-17 00:27:47 +02:00
import Util, { logger } from './../common/Util'
import { Rng } from './../common/Rng'
2021-05-17 00:27:47 +02:00
import { DATA_DIR } from './Dirs'
import Time from './../common/Time'
2021-04-30 21:00:30 +02:00
const log = logger('GameStorage.js')
2021-05-29 17:58:05 +02:00
const dirtyGames: Record<string, boolean> = {}
2021-05-17 00:27:47 +02:00
function setDirty(gameId: string): void {
2021-05-29 17:58:05 +02:00
dirtyGames[gameId] = true
2021-04-30 21:00:30 +02:00
}
2021-05-17 00:27:47 +02:00
function setClean(gameId: string): void {
2021-05-29 17:58:05 +02:00
delete dirtyGames[gameId]
2021-04-30 21:00:30 +02:00
}
2021-05-17 00:27:47 +02:00
function loadGames(): void {
2021-04-30 21:00:30 +02:00
const files = fs.readdirSync(DATA_DIR)
for (const f of files) {
const m = f.match(/^([a-z0-9]+)\.json$/)
if (!m) {
continue
}
const gameId = m[1]
loadGame(gameId)
}
}
2021-05-17 00:27:47 +02:00
function loadGame(gameId: string): void {
2021-04-30 21:00:30 +02:00
const file = `${DATA_DIR}/${gameId}.json`
const contents = fs.readFileSync(file, 'utf-8')
let game
try {
game = JSON.parse(contents)
} catch {
log.log(`[ERR] unable to load game from file ${file}`);
}
if (typeof game.puzzle.data.started === 'undefined') {
game.puzzle.data.started = Math.round(fs.statSync(file).ctimeMs)
}
if (typeof game.puzzle.data.finished === 'undefined') {
2021-05-28 23:01:00 +02:00
const unfinished = game.puzzle.tiles
2021-05-29 15:36:03 +02:00
.map(Util.decodePiece)
2021-05-28 23:01:00 +02:00
.find((t: Piece) => t.owner !== -1)
2021-04-30 21:00:30 +02:00
game.puzzle.data.finished = unfinished ? 0 : Time.timestamp()
}
if (!Array.isArray(game.players)) {
game.players = Object.values(game.players)
}
const gameObject = {
id: game.id,
rng: {
type: game.rng ? game.rng.type : '_fake_',
2021-05-17 00:27:47 +02:00
obj: game.rng ? Rng.unserialize(game.rng.obj) : new Rng(0),
2021-04-30 21:00:30 +02:00
},
puzzle: game.puzzle,
players: game.players,
evtInfos: {},
2021-05-17 02:32:33 +02:00
scoreMode: game.scoreMode || ScoreMode.FINAL,
2021-04-30 21:00:30 +02:00
}
GameCommon.setGame(gameObject.id, gameObject)
}
2021-05-28 23:01:00 +02:00
function persistGames(): void {
2021-05-29 17:58:05 +02:00
for (const gameId of Object.keys(dirtyGames)) {
2021-04-30 21:00:30 +02:00
persistGame(gameId)
}
}
2021-05-28 23:01:00 +02:00
function persistGame(gameId: string): void {
2021-04-30 21:00:30 +02:00
const game = GameCommon.get(gameId)
2021-05-29 17:58:05 +02:00
if (!game) {
log.error(`[ERROR] unable to persist non existing game ${gameId}`)
return
}
if (game.id in dirtyGames) {
2021-04-30 21:00:30 +02:00
setClean(game.id)
}
fs.writeFileSync(`${DATA_DIR}/${game.id}.json`, JSON.stringify({
id: game.id,
rng: {
type: game.rng.type,
obj: Rng.serialize(game.rng.obj),
},
puzzle: game.puzzle,
players: game.players,
scoreMode: game.scoreMode,
}))
log.info(`[INFO] persisted game ${game.id}`)
}
export default {
loadGames,
loadGame,
persistGames,
persistGame,
setDirty,
}