-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver.js
More file actions
151 lines (127 loc) · 4.32 KB
/
Copy pathserver.js
File metadata and controls
151 lines (127 loc) · 4.32 KB
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
// Express app
var _ = require('lodash');
var path = require('path');
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var cors = require('cors');
var geoip = require('geoip-lite');
var favicon = require('serve-favicon');
// Static assets to be served:
app.use(favicon(path.join(__dirname,'static','favicon.ico')));
app.use(express.static(path.join(__dirname, 'static')));
// Set up middleware:
app.use(bodyParser.urlencoded({ extended: false })); // parse application/x-www-form-urlencoded
app.use(bodyParser.json()); // for parsing application/json
app.use(cors()) // might need configuring, specific domains etc.
// Set up storage:
var storage = require('node-persist');
storage.initSync();
// Load scores data from disk if nothing persisted:
if (typeof storage.getItemSync('scores') === 'undefined') {
fs = require('fs');
fs.readFile('data/scores.json', 'utf-8', function(err,data) {
storage.setItemSync('scores', data);
});
console.log("Loaded JSON scores.");
}
else {
console.log("Persisted:", storage.getItemSync('scores'));
}
// Retrieve array of x highest scoring game objects:
function getHighscores(number = 3) {
let scores = JSON.parse(storage.getItemSync('scores'));
return _.chain(scores)
.filter(score => score.tiles === 19)
.map(score => _.pick(score, ['timestamp', 'country', 'name', 'score']))
.sortBy('score')
.reverse()
.take(number)
.value();
}
// Convert ip to country code:
function getCountry(ip) {
var geo = geoip.lookup(ip);
return geo && geo.country; // async?
}
// Parse the incoming data object and prepare fields for database:
function prepRequestObject(req) {
// Validate fields?
return {
gameid: req.body.gameID,
timestamp: req.body.timestamp,
ip: req.body.ip,
country: /^\d+\.\d+\.\d+\.\d+}$/.test(req.body.ip) && getCountry(req.body.ip) || 'unknown',
name: req.body.name,
tiles: parseInt(req.body.tiles), // should be 1 or 19
score: parseInt(req.body.score)
};
}
// Overwrite scores object both in-memory and to file on disk:
function writeScores() {
}
/* ROUTES
*============================================================================*/
// Client GETs all scores:
app.get('/api/scores/:num', function(req, res) {
let highscores = getHighscores(req.params.num);
if (highscores) {
res.status(200).json(highscores); // is-cacheable header?
}
});
// Client PUTs a new record:
app.put('/api/scores', function(req, res) {
console.log("PUTting");
var ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress;
console.log(ip, req.ip); // ::1, ::1
let newscore = prepRequestObject(req);
console.log(newscore);
// Fetch db scores:
let scores = JSON.parse(storage.getItemSync('scores'));
console.log(scores.length + " scores retrieved.");
// Append new record:
scores.push(newscore);
// Save into db:
console.log(scores.length + " scores being saved."); // should be 1 more
storage.setItemSync('scores', JSON.stringify(scores)); // SHOULD ALSO WRITE TO FILE HERE?
console.log(scores);
// Return status code / message:
res.status(200).send('Thanks');
});
// Client POSTs update to a score:
app.post('/api/scores', function(req, res) {
console.log("POSTing");
let updatedscore = prepRequestObject(req);
console.log(updatedscore);
// Check game was finished:
if (updatedscore.tiles >= 3) { // === 19
// Fetch all db scores:
let scores = JSON.parse(storage.getItemSync('scores'));
console.log(scores.length + " scores retrieved.");
// Find record by gameid and update it:
scores = scores.map(function(entry) {
return (entry.gameid == updatedscore.gameid) ? updatedscore : entry;
}); // Done!
// Save into db:
console.log(scores.length + " scores being saved."); // should be equal
storage.setItemSync('scores', JSON.stringify(scores)); // SHOULD ALSO WRITE TO FILE HERE?
console.log(scores);
// Return status code / message:
res.status(200).send('Thanks');
}
});
// Reset API data store:
app.get('/api/reset', function(req, res) {
storage.setItemSync('scores', null);
console.log("Reset db");
});
// Serve static game page:
app.get('/', function(req, res) {
console.log("Express serving index.html");
//res.render('/index.html');
res.sendFile(path.join(__dirname + '/static/index.html'));
});
// Serve:
const port = process.env.PORT || 3000;
app.listen(port);
console.log('Magic happens on port ' + port);