add different score modes
This commit is contained in:
parent
90590d334e
commit
abf6e6aa02
6 changed files with 101 additions and 30 deletions
|
|
@ -3,6 +3,9 @@ import Protocol from './Protocol.js'
|
||||||
import Time from './Time.js'
|
import Time from './Time.js'
|
||||||
import Util from './Util.js'
|
import Util from './Util.js'
|
||||||
|
|
||||||
|
const SCORE_MODE_FINAL = 0
|
||||||
|
const SCORE_MODE_ANY = 1
|
||||||
|
|
||||||
// Map<gameId, GameObject>
|
// Map<gameId, GameObject>
|
||||||
const GAMES = {}
|
const GAMES = {}
|
||||||
|
|
||||||
|
|
@ -10,13 +13,14 @@ function exists(gameId) {
|
||||||
return (!!GAMES[gameId]) || false
|
return (!!GAMES[gameId]) || false
|
||||||
}
|
}
|
||||||
|
|
||||||
function __createGameObject(id, rng, puzzle, players, evtInfos) {
|
function __createGameObject(id, rng, puzzle, players, evtInfos, scoreMode) {
|
||||||
return {
|
return {
|
||||||
id: id,
|
id: id,
|
||||||
rng: rng,
|
rng: rng,
|
||||||
puzzle: puzzle,
|
puzzle: puzzle,
|
||||||
players: players,
|
players: players,
|
||||||
evtInfos: evtInfos,
|
evtInfos: evtInfos,
|
||||||
|
scoreMode: scoreMode,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,8 +38,8 @@ function __createPlayerObject(id, ts) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function newGame({id, rng, puzzle, players, evtInfos}) {
|
function newGame({id, rng, puzzle, players, evtInfos, scoreMode}) {
|
||||||
const game = __createGameObject(id, rng, puzzle, players, evtInfos)
|
const game = __createGameObject(id, rng, puzzle, players, evtInfos, scoreMode)
|
||||||
setGame(id, game)
|
setGame(id, game)
|
||||||
return game
|
return game
|
||||||
}
|
}
|
||||||
|
|
@ -158,6 +162,10 @@ function setImageUrl(gameId, imageUrl) {
|
||||||
GAMES[gameId].puzzle.info.imageUrl = imageUrl
|
GAMES[gameId].puzzle.info.imageUrl = imageUrl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getScoreMode(gameId) {
|
||||||
|
return GAMES[gameId].scoreMode || SCORE_MODE_FINAL
|
||||||
|
}
|
||||||
|
|
||||||
function isFinished(gameId) {
|
function isFinished(gameId) {
|
||||||
return getFinishedTileCount(gameId) === getTileCount(gameId)
|
return getFinishedTileCount(gameId) === getTileCount(gameId)
|
||||||
}
|
}
|
||||||
|
|
@ -654,8 +662,23 @@ function handleInput(gameId, playerId, input, ts) {
|
||||||
// Snap the tile to the final destination
|
// Snap the tile to the final destination
|
||||||
moveTilesDiff(gameId, tileIdxs, diff)
|
moveTilesDiff(gameId, tileIdxs, diff)
|
||||||
finishTiles(gameId, tileIdxs)
|
finishTiles(gameId, tileIdxs)
|
||||||
changePlayer(gameId, playerId, { points: getPlayerPoints(gameId, playerId) + tileIdxs.length })
|
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
|
|
||||||
|
if (getScoreMode(gameId) === SCORE_MODE_FINAL) {
|
||||||
|
changePlayer(gameId, playerId, {
|
||||||
|
points: getPlayerPoints(gameId, playerId) + tileIdxs.length,
|
||||||
|
})
|
||||||
|
_playerChange()
|
||||||
|
} else if (getScoreMode(gameId) === SCORE_MODE_ANY) {
|
||||||
|
changePlayer(gameId, playerId, {
|
||||||
|
points: getPlayerPoints(gameId, playerId) + 1,
|
||||||
|
})
|
||||||
|
_playerChange()
|
||||||
|
} else {
|
||||||
|
// no score mode... should never occur, because there is a
|
||||||
|
// fallback to SCORE_MODE_FINAL in getScoreMode function
|
||||||
|
}
|
||||||
|
|
||||||
// check if the puzzle is finished
|
// check if the puzzle is finished
|
||||||
if (getFinishedTileCount(gameId) === getTileCount(gameId)) {
|
if (getFinishedTileCount(gameId) === getTileCount(gameId)) {
|
||||||
changeData(gameId, { finished: ts })
|
changeData(gameId, { finished: ts })
|
||||||
|
|
@ -685,6 +708,12 @@ function handleInput(gameId, playerId, input, ts) {
|
||||||
const zIndex = getMaxZIndexByTileIdxs(gameId, tileIdxs)
|
const zIndex = getMaxZIndexByTileIdxs(gameId, tileIdxs)
|
||||||
setTilesZIndex(gameId, tileIdxs, zIndex)
|
setTilesZIndex(gameId, tileIdxs, zIndex)
|
||||||
_tileChanges(tileIdxs)
|
_tileChanges(tileIdxs)
|
||||||
|
if (getScoreMode(gameId) === SCORE_MODE_ANY) {
|
||||||
|
changePlayer(gameId, playerId, {
|
||||||
|
points: getPlayerPoints(gameId, playerId) + 1,
|
||||||
|
})
|
||||||
|
_playerChange()
|
||||||
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
|
|
@ -751,4 +780,6 @@ export default {
|
||||||
getStartTs,
|
getStartTs,
|
||||||
getFinishTs,
|
getFinishTs,
|
||||||
handleInput,
|
handleInput,
|
||||||
|
SCORE_MODE_FINAL,
|
||||||
|
SCORE_MODE_ANY,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,7 @@ function encodeGame(data) {
|
||||||
data.puzzle,
|
data.puzzle,
|
||||||
data.players,
|
data.players,
|
||||||
data.evtInfos,
|
data.evtInfos,
|
||||||
|
data.scoreMode,
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -182,6 +183,7 @@ function decodeGame(data) {
|
||||||
puzzle: data[3],
|
puzzle: data[3],
|
||||||
players: data[4],
|
players: data[4],
|
||||||
evtInfos: data[5],
|
evtInfos: data[5],
|
||||||
|
scoreMode: data[6],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import GameCommon from '../common/GameCommon.js';
|
||||||
import Time from '../common/Time.js'
|
import Time from '../common/Time.js'
|
||||||
|
|
||||||
const Upload = {
|
const Upload = {
|
||||||
|
|
@ -105,12 +106,22 @@ export default {
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h1>New game</h1>
|
<h1>New game</h1>
|
||||||
<div>
|
<table>
|
||||||
<label>Pieces: </label>
|
<tr>
|
||||||
<input type="text" v-model="tiles" />
|
<td><label>Pieces: </label></td>
|
||||||
</div>
|
<td><input type="text" v-model="tiles" /></td>
|
||||||
<div>
|
</tr>
|
||||||
<label>Image: </label>
|
<tr>
|
||||||
|
<td><label>Scoring: </label></td>
|
||||||
|
<td>
|
||||||
|
<label><input type="radio" v-model="scoreMode" value="1" /> Any (Score when pieces are connected to each other or on final location)</label>
|
||||||
|
<br />
|
||||||
|
<label><input type="radio" v-model="scoreMode" value="0" /> Final (Score when pieces are put to their final location)</label>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label>Image: </label></td>
|
||||||
|
<td>
|
||||||
<span v-if="image">
|
<span v-if="image">
|
||||||
<img :src="image.url" style="width: 150px;" />
|
<img :src="image.url" style="width: 150px;" />
|
||||||
or
|
or
|
||||||
|
|
@ -120,8 +131,14 @@ export default {
|
||||||
<upload @uploaded="mediaImgUploaded($event)" accept="image/*" label="Upload an image" />
|
<upload @uploaded="mediaImgUploaded($event)" accept="image/*" label="Upload an image" />
|
||||||
(or select from below)
|
(or select from below)
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td colspan="2">
|
||||||
<span class="btn" :class="" @click="onNewGameClick">Start new game</span>
|
<span class="btn" :class="" @click="onNewGameClick">Start new game</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
<h1>Image lib</h1>
|
<h1>Image lib</h1>
|
||||||
<div>
|
<div>
|
||||||
|
|
@ -137,6 +154,7 @@ export default {
|
||||||
return {
|
return {
|
||||||
tiles: 1000,
|
tiles: 1000,
|
||||||
image: '',
|
image: '',
|
||||||
|
scoreMode: GameCommon.SCORE_MODE_ANY,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
|
@ -157,7 +175,11 @@ export default {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
'Content-Type': 'application/json'
|
'Content-Type': 'application/json'
|
||||||
},
|
},
|
||||||
body: JSON.stringify({tiles: this.tiles, image: this.image}),
|
body: JSON.stringify({
|
||||||
|
tiles: this.tiles,
|
||||||
|
image: this.image,
|
||||||
|
scoreMode: parseInt(this.scoreMode, 10),
|
||||||
|
}),
|
||||||
})
|
})
|
||||||
if (res.status === 200) {
|
if (res.status === 200) {
|
||||||
const game = await res.json()
|
const game = await res.json()
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,10 @@ h1, h2, h3, h4 {
|
||||||
a { color: var(--link-color); text-decoration: none; }
|
a { color: var(--link-color); text-decoration: none; }
|
||||||
a:hover { color: var(--link-hover-color); }
|
a:hover { color: var(--link-hover-color); }
|
||||||
|
|
||||||
|
td, th {
|
||||||
|
vertical-align: top;
|
||||||
|
}
|
||||||
|
|
||||||
.scores {
|
.scores {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
|
|
|
||||||
|
|
@ -48,12 +48,13 @@ function loadGame(gameId) {
|
||||||
},
|
},
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
evtInfos: {}
|
evtInfos: {},
|
||||||
|
scoreMode: game.scoreMode || GameCommon.SCORE_MODE_FINAL,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const changedGames = {}
|
const changedGames = {}
|
||||||
async function createGameObject(gameId, targetTiles, image, ts) {
|
async function createGameObject(gameId, targetTiles, image, ts, scoreMode) {
|
||||||
const seed = Util.hash(gameId + ' ' + ts)
|
const seed = Util.hash(gameId + ' ' + ts)
|
||||||
const rng = new Rng(seed)
|
const rng = new Rng(seed)
|
||||||
return GameCommon.__createGameObject(
|
return GameCommon.__createGameObject(
|
||||||
|
|
@ -64,12 +65,13 @@ async function createGameObject(gameId, targetTiles, image, ts) {
|
||||||
},
|
},
|
||||||
await createPuzzle(rng, targetTiles, image, ts),
|
await createPuzzle(rng, targetTiles, image, ts),
|
||||||
[],
|
[],
|
||||||
{}
|
{},
|
||||||
|
scoreMode
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
async function createGame(gameId, targetTiles, image, ts) {
|
async function createGame(gameId, targetTiles, image, ts, scoreMode) {
|
||||||
GameLog.create(gameId)
|
GameLog.create(gameId)
|
||||||
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts)
|
GameLog.log(gameId, Protocol.LOG_HEADER, 1, targetTiles, image, ts, scoreMode)
|
||||||
|
|
||||||
const seed = Util.hash(gameId + ' ' + ts)
|
const seed = Util.hash(gameId + ' ' + ts)
|
||||||
const rng = new Rng(seed)
|
const rng = new Rng(seed)
|
||||||
|
|
@ -82,6 +84,7 @@ async function createGame(gameId, targetTiles, image, ts) {
|
||||||
puzzle: await createPuzzle(rng, targetTiles, image, ts),
|
puzzle: await createPuzzle(rng, targetTiles, image, ts),
|
||||||
players: [],
|
players: [],
|
||||||
evtInfos: {},
|
evtInfos: {},
|
||||||
|
scoreMode,
|
||||||
})
|
})
|
||||||
|
|
||||||
changedGames[gameId] = true
|
changedGames[gameId] = true
|
||||||
|
|
@ -130,6 +133,7 @@ function persistGame(gameId) {
|
||||||
},
|
},
|
||||||
puzzle: game.puzzle,
|
puzzle: game.puzzle,
|
||||||
players: game.players,
|
players: game.players,
|
||||||
|
scoreMode: game.scoreMode,
|
||||||
}))
|
}))
|
||||||
log.info(`[INFO] persisted game ${game.id}`)
|
log.info(`[INFO] persisted game ${game.id}`)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import {
|
||||||
GAME_DIR,
|
GAME_DIR,
|
||||||
TEMPLATE_DIR,
|
TEMPLATE_DIR,
|
||||||
} from './Dirs.js'
|
} from './Dirs.js'
|
||||||
|
import GameCommon from '../common/GameCommon.js'
|
||||||
|
|
||||||
const log = logger('index.js')
|
const log = logger('index.js')
|
||||||
|
|
||||||
|
|
@ -85,7 +86,13 @@ app.post('/newgame', bodyParser.json(), async (req, res) => {
|
||||||
const gameId = Util.uniqId()
|
const gameId = Util.uniqId()
|
||||||
if (!Game.exists(gameId)) {
|
if (!Game.exists(gameId)) {
|
||||||
const ts = Time.timestamp()
|
const ts = Time.timestamp()
|
||||||
await Game.createGame(gameId, req.body.tiles, req.body.image, ts)
|
await Game.createGame(
|
||||||
|
gameId,
|
||||||
|
req.body.tiles,
|
||||||
|
req.body.image,
|
||||||
|
ts,
|
||||||
|
req.body.scoreMode
|
||||||
|
)
|
||||||
}
|
}
|
||||||
res.send({ url: `/g/${gameId}` })
|
res.send({ url: `/g/${gameId}` })
|
||||||
})
|
})
|
||||||
|
|
@ -151,11 +158,12 @@ wss.on('message', async ({socket, data}) => {
|
||||||
throw `[gamelog ${gameId} does not exist... ]`
|
throw `[gamelog ${gameId} does not exist... ]`
|
||||||
}
|
}
|
||||||
const log = GameLog.get(gameId)
|
const log = GameLog.get(gameId)
|
||||||
let game = await Game.createGameObject(
|
const game = await Game.createGameObject(
|
||||||
gameId,
|
gameId,
|
||||||
log[0][2],
|
log[0][2],
|
||||||
log[0][3],
|
log[0][3],
|
||||||
log[0][4]
|
log[0][4],
|
||||||
|
log[0][5] || GameCommon.SCORE_MODE_FINAL
|
||||||
)
|
)
|
||||||
notify(
|
notify(
|
||||||
[Protocol.EV_SERVER_INIT_REPLAY, Util.encodeGame(game), log],
|
[Protocol.EV_SERVER_INIT_REPLAY, Util.encodeGame(game), log],
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue