This repository has been archived by the owner on Dec 10, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathroutes.js
247 lines (223 loc) · 8.48 KB
/
routes.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
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
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
'use strict';
var config = require('./config'),
sqlite3 = require('sqlite3'),
db = new sqlite3.Database(config.dbfile);
// given an array of fixtures rows, calculates the totals
function pointsTotals(fixtures) {
var totals = {
homePoints: 0,
awayPoints: 0,
maxPoints: 0,
};
fixtures.forEach(function (fixture) {
if (typeof fixture.pointsAvailable === 'number') {
totals.maxPoints += fixture.pointsAvailable;
if (!fixture.inProgress
&& typeof fixture.homeScore === 'number'
&& typeof fixture.awayScore === 'number') {
if (fixture.homeScore > fixture.awayScore) {
totals.homePoints += fixture.pointsAvailable;
} else if (fixture.homeScore < fixture.awayScore) {
totals.awayPoints += fixture.pointsAvailable;
} else {
totals.homePoints += fixture.pointsAvailable / 2;
totals.awayPoints += fixture.pointsAvailable / 2;
}
}
}
});
totals.availablePoints = totals.maxPoints - totals.homePoints - totals.awayPoints;
return totals;
}
// given fixturesByDay, works out the 'current day'
// -- either the last day with any fixtures with final scores, or the first day
function currentDay(fixturesByDay, days) {
days = days || Object.keys(fixturesByDay);
if (days.length === 1) {
return days[0];
}
return days.filter(function (day) {
return fixturesByDay[day].some(function (fixture) { // do any fixtures have a final score?
return typeof fixture.homeScore === 'number' && typeof fixture.awayScore === 'number';
});
}, fixturesByDay).pop() || days[0];
}
// fetch a tournament's fixtures and render it using some view
function tournamentFixtures(req, res, view) {
var tournament,
fixturesByDay = {};
db.get('SELECT * FROM tournaments WHERE id = $id',
{
$id: req.params.id
},
function (err, row) {
if (err || !row) {
res.status(404).send('Tournament does not exist');
} else {
tournament = row;
db.each('SELECT * FROM fixtures WHERE tournament = $tournament ORDER BY time',
{
$tournament: req.params.id
},
function (err, row) {
if (!err) {
if (!fixturesByDay[row.day]) {
fixturesByDay[row.day] = [];
}
fixturesByDay[row.day].push(row);
}
},
function (err, rows) {
var days = Object.keys(fixturesByDay);
days = days.sort(function (a, b) { // sort based on the first two letters of the day name
var idealList = ['Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'];
return idealList.indexOf(a.substring(0, 2)) - idealList.indexOf(b.substring(0, 2));
});
res.render(view, {
tournament: tournament,
fixturesByDay: fixturesByDay,
daysInOrder: days,
multipleDays: days.length > 1,
currentDay: currentDay(fixturesByDay, days),
});
});
}
});
}
// tournaments administration page
exports.tournaments = function (req, res) {
db.all('SELECT * FROM Tournaments ORDER BY id DESC', function (err, rows) {
if (err) {
res.status(500);
} else {
res.render('admin-tournaments', { messages: req.flash(), tournaments: rows });
}
});
};
// add new tournament
exports.tournamentsAdd = function (req, res) {
if (req.body.name && req.body.home && req.body.away) {
db.run('INSERT INTO Tournaments (name, home, away) VALUES ($name, $home, $away)', {
$name: req.body.name,
$home: req.body.home,
$away: req.body.away,
}, function () {
req.flash('successMessage', 'Tournament added');
res.redirect('/tournaments');
});
} else {
req.flash('errorMessage', 'Sorry, please fill in all the fields');
res.redirect('/tournaments');
}
};
// add new fixture
exports.fixturesAdd = function (req, res) {
if (req.params.id) {
db.run('INSERT INTO Fixtures (tournament) VALUES ($id)', {
$id: req.params.id,
}, function () {
res.redirect('/tournaments/' + req.params.id);
});
}
};
// update some scores for a tournament
exports.fixturesUpdate = function (io) { // higher order function
return function (req, res) {
var changes = {},
totalsBefore = {}, // used to check whether the changes cause the tournament score to change
totalsAfter = {};
db.serialize(function () {
// calculate initial points totals
db.all(
'SELECT pointsAvailable, homeScore, awayScore, inProgress FROM Fixtures WHERE tournament = $id',
{
$id: req.params.id
},
function (err, fixtures) {
totalsBefore = pointsTotals(fixtures);
}
);
// update database
db.parallelize(function () {
Object.keys(req.body).forEach(function (field) {
var identifiers = field.split('-'); // ['name', '3']
switch (identifiers[0]) {
case 'day':
case 'sport':
case 'name':
case 'location':
case 'time':
case 'pointsAvailable':
case 'home':
case 'homeScore':
case 'awayScore':
case 'away':
case 'inProgress':
db.run(
'UPDATE Fixtures SET ' + identifiers[0] + ' = $value WHERE id = $id',
{
$value: req.body[field],
$id: identifiers[1]
}
);
changes[field] = req.body[field];
break;
}
});
});
if (req.query.ajax) {
res.json(changes);
} else {
res.redirect('/tournaments/' + req.params.id);
}
// recalculate points totals
db.all(
'SELECT pointsAvailable, homeScore, awayScore, inProgress FROM Fixtures WHERE tournament = $id',
{
$id: req.params.id
},
function (err, fixtures) {
totalsAfter = pointsTotals(fixtures);
if (totalsBefore.homePoints !== totalsAfter.homePoints
|| totalsBefore.awayPoints !== totalsAfter.awayPoints) {
io.sockets.emit('score change', changes);
} else {
io.sockets.emit('update', changes);
}
}
);
});
};
};
// fixtures administration page for a tournament
exports.tournament = function (req, res) {
tournamentFixtures(req, res, 'admin-fixtures');
};
// embeddable fixtures HTML fragment for a tournament
exports.fixturesHTML = function (req, res) {
tournamentFixtures(req, res, 'fixtures-container');
};
// fetch, and render as JSON, fixtures for a tournament
exports.fixturesJSON = function (req, res) {
db.all('SELECT * FROM Fixtures WHERE tournament = $id',
{
$id: req.params.id
},
function (err, rows) {
if (!err) {
res.json(rows);
}
});
};
// fetch, and render as JSON, points totals for a tournament
exports.totalsJSON = function (req, res) {
db.all('SELECT pointsAvailable, homeScore, awayScore, inProgress FROM Fixtures WHERE tournament = $id',
{
$id: req.params.id
},
function (err, fixtures) {
if (!err) {
res.json(pointsTotals(fixtures));
}
});
};