-
Notifications
You must be signed in to change notification settings - Fork 0
/
recorder.js
115 lines (103 loc) · 3.63 KB
/
recorder.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
const fs = require('fs');
const {gzip} = require('node-gzip');
const logger = require('./winston');
const {SquareState} = require('./util')
const {SquareType} = require('./config');
function copySquareState(square) {
let unit = square.getUnit();
let units = unit ? [Object.assign({}, unit, {id: undefined})] : [];
return new SquareState(Object.assign({}, square, {units}));
}
function recordInitial(room) {
if (room.recorded) {
room.lastSquareStates = room.squareStates.map(row => row.map(square => copySquareState(square)));
let initialState = room.lastSquareStates.map(row => row.map(square => square));
room.record = {initial: initialState, ticks: [], startTime: new Date()};
}
}
function hasUnitChanged(unit, lastUnit) {
if (unit === null && lastUnit === null) {
return false;
} else if (unit === null) {
return true;
} else if (lastUnit === null) {
return true;
} else {
let changes = ['playerId', 'type', 'count'].filter(attr => (unit[attr] !== lastUnit[attr]));
return changes.length ? true : false;
}
}
function hasSquareChanged(square, lastSquare) {
let changes = ['type', 'baseId', 'baseHP', 'isFog'].filter(attr => (square[attr] !== lastSquare[attr]));
if (changes.length) {
return true;
}
return hasUnitChanged(square.getUnit(), lastSquare.getUnit());
}
function recordUpdate(room) {
if (room.recorded && room.record) {
let changedSquares = [];
let lastSquareStates = room.lastSquareStates;
room.squareStates.forEach((row, y) => {
row.forEach((square, x) => {
let lastSquare = lastSquareStates[y][x];
if (hasSquareChanged(square, lastSquare)) {
square = copySquareState(square);
square.y = y;
square.x = x;
changedSquares.push(square);
lastSquareStates[y][x] = square;
}
});
});
room.record.ticks.push({
squares: changedSquares,
shards: Object.assign({}, room.shards),
flags: Object.assign({}, room.flags)
});
}
}
function finishRecordAndSave(room, collection) {
if (room.recorded && room.record) {
let record = room.record;
record.result = Object.assign({}, room.gameWonStatus);
let savePath = writeRecordToFile(record, room.gameId);
writeRecordToDatabase(room.gameId, room.playerIds, record.startTime, savePath, collection);
delete room.record;
delete room.gameId;
}
}
let recordDir = './records';
try {
fs.mkdirSync(recordDir);
} catch (err) {} // folder already exists
function writeRecordToFile(record, gameId) {
let path = `${recordDir}/${gameId}.json.gz`;
gzip(JSON.stringify(record)).then(compressed => {
fs.writeFile(path, compressed, err => {
if (err) {
logger.error(err);
} else {
logger.info(`Saved game ${gameId} to ${path}`);
}
});
});
return path;
}
function writeRecordToDatabase(gameId, playerIds, startTime, savePath, collection) {
let entry = {
gameId: gameId,
playerIds: playerIds,
path: savePath,
startTime: startTime,
endTime: new Date()
}
collection.insertOne(entry)
.then(result => {
logger.info(`Inserted game ${gameId} with players ${JSON.stringify(playerIds)} into the database`);
})
.catch(err => {
logger.error(err);
});
}
module.exports = {recordInitial, recordUpdate, finishRecordAndSave};