}, 'reload-construction-queue');
+server.post<{params: {queueId: string}}, void>('/training/:queueId/cancel', async req => {
+ const acct = await accountRepo.validate(req.authInfo.accountId, req.authInfo.token);
+ const city = await cityRepo.getUsersCity(acct.id);
+
+ if(!validator.isUUID(req.params.queueId)) {
+ throw new BadInputError('Invalid queue ID', ERROR_CODE.INVALID_BUILD_QUEUE);
+ }
+
+ const queue = await cityRepo.unitTrainigQueue.FindOne({owner: city.owner, id: req.params.queueId});
+ if(!queue) {
+ throw new NotFoundError('That queue does not exist', ERROR_CODE.INVALID_BUILD_QUEUE);
+ }
+
+ const [, unit] = await Promise.all([
+ cityRepo.unitTrainigQueue.Delete({
+ owner: city.owner,
+ id: req.params.queueId
+ }),
+ cityRepo.unitRepository.FindOne({slug: queue.unit_type})
+ ]);
+
+ // now that it's deleted we can give the player back some percentage
+ // of resources based on how close they are to completion.
+ const diff = (queue.due - Date.now()) / (queue.due - queue.created);
+ // force a 20% loss minimum
+ const finalDiff = diff < 0.2 ? 0.2 : diff;
+
+ const costReturn: Partial<City> = {
+ id: city.id,
+ credits: city.credits + Math.floor(unit.credits * queue.amount * diff),
+ food: city.food + Math.floor(unit.food * queue.amount * diff),
+ population: city.population + Math.floor(unit.population * queue.amount),
+ soldiers: city.soldiers + Math.floor(unit.soldiers * queue.amount),
+ attackers: city.attackers + Math.floor(unit.attackers * queue.amount),
+ defenders: city.defenders + Math.floor(unit.attackers * queue.amount)
+ };
+
+ console.log('update', costReturn)
+
+ await cityRepo.save(costReturn);
+
+}, 'reload-unit-training');
+
server.get<void, string>('/server-stats', async req => {
const date = new Date();
return `
<tr>
<th align="left">Unit Type</th>
<th align="left">Amount Expected</th>
- <th>Progress</th>
+ <th colspan="2">Progress</th>
</tr>
${sortedTrainingQueue.map(queue => {
if(queue.unit_type === 'empty') {
<tr>
<td>${queue.display}</td>
<td>${queue.amount}</td>
- <td>
- <span title="${Math.ceil(due.diff(created).as('minutes')).toLocaleString()} minutes remaining">
- ${progressBar(now, duration)}<br>
- </span>
+ <td>${progressBar(now, duration)}</td>
+ <td width="50">
+ <a href="#" hx-post="/training/${queue.id}/cancel" hx-trigger="click" class="danger-text close" title="Cancel Unit Training">×</a>
</td>
</tr>
`;