1 import _ from "lodash";
2 import { CityWithLocation } from "../repository/city";
3 import { UnitTrainingQueueWithName } from "../repository/training-queue";
4 import { Unit } from "../repository/unit";
5 import { DateTime } from "luxon";
7 const emptyQueue: UnitTrainingQueueWithName = {
17 function progressBar(current: number, max: number): string {
18 const percent = Math.ceil((current/max) * 100);
20 <div class="progress-bar unit-training" style="background: background: var(--green-bg);
21 background: linear-gradient(90deg, var(--green-bg) 0%, var(--green-bg) ${percent}%, #000 ${percent}%); border-color: var(--green-border);">
27 export function renderUnitTraining(city: CityWithLocation, units: Unit[], trainingQueues: UnitTrainingQueueWithName[]): string {
28 const unit = _.keyBy(units, 'slug');
29 const sortedTrainingQueue = trainingQueues.sort((a, b) => {
33 <div hx-trigger="reload-unit-training, every 600s" hx-get="/poll/unit-training">
34 <h2 data-augmented-ui="tl-clip bl-clip none">Unit Training</h2>
40 <th width="200">Cost</th>
44 <td>${city.soldiers}</td>
46 <form hx-post="/units" hx-swap="innerHTML" hx-target="#notifications">
47 <input type="number" name="amount" size="6" max="${city.population}" hx-trigger="keyup" hx-post="/cost/training" hx-target="#${unit.soldiers.slug}-cost" hx-swap="innerHTML">
48 <input type="hidden" name="type" value="${unit.soldiers.slug}">
49 <button type="submit" ${city.population ? '' : 'disabled'}>Train</button>
52 <td id="${unit.soldiers.slug}-cost"></span>
56 <td>${city.attackers}</td>
58 <form hx-post="/units" hx-swap="innerHTML" hx-target="#notifications">
59 <input type="number" name="amount" size="6" max="${city.soldiers}" hx-trigger="keyup" hx-post="/cost/training" hx-target="#${unit.attackers.slug}-cost" hx-swap="innerHTML">
60 <input type="hidden" name="type" value="${unit.attackers.slug}">
61 <button type="submit" ${city.soldiers ? '' : 'disabled'}>Train</button>
64 <td id="${unit.attackers.slug}-cost"></span>
68 <td>${city.defenders}</td>
70 <form hx-post="/units" hx-swap="innerHTML" hx-target="#notifications">
71 <input type="number" name="amount" size="6" max="${city.soldiers}" hx-trigger="keyup" hx-post="/cost/training" hx-target="#${unit.defenders.slug}-cost" hx-swap="innerHTML">
72 <input type="hidden" name="type" value="${unit.defenders.slug}">
73 <button type="submit" ${city.soldiers ? '' : 'disabled'}>Train</button>
76 <td id="${unit.defenders.slug}-cost"></td>
79 <th>Special Attackers</th>
80 <td>${city.sp_attackers}</td>
82 <form hx-post="/units" hx-swap="innerHTML" hx-target="#notifications">
83 <input type="number" name="amount" size="6" max="${city.attackers}" hx-trigger="keyup" hx-post="/cost/training" hx-target="#${unit.sp_attackers.slug}-cost" hx-swap="innerHTML">
84 <input type="hidden" name="type" value="${unit.sp_attackers.slug}">
85 <button type="submit" ${city.attackers ? '': 'disabled'}>Train</button>
87 <span id="${unit.sp_attackers.slug}-cost"></span>
89 <td id="${unit.sp_attackers.slug}-cost"></td>
92 <th>Special Defenders</th>
93 <td>${city.sp_defenders}</td>
95 <form hx-post="/units" hx-swap="innerHTML" hx-target="#notifications">
96 <input type="number" name="amount" size="6" max="${city.defenders}" hx-trigger="keyup" hx-post="/cost/training" hx-target="#${unit.sp_defenders.slug}-cost" hx-swap="innerHTML">
97 <input type="hidden" name="type" value="${unit.sp_defenders.slug}">
98 <button type="submit" ${city.defenders ? '': 'disabled'}>Train</button>
101 <td id="${unit.sp_defenders.slug}-cost"></td>
106 const finalTrainingQueue = sortedTrainingQueue;
107 if(finalTrainingQueue.length < city.max_training_queue) {
108 while(finalTrainingQueue.length < city.max_construction_queue) {
109 finalTrainingQueue.push(emptyQueue);
115 <h2 data-augmented-ui="tl-clip bl-clip none">Training Queues</h2>
118 <th align="left">Unit Type</th>
119 <th align="left">Amount Expected</th>
120 <th colspan="2">Progress</th>
122 ${sortedTrainingQueue.map(queue => {
123 if(queue.unit_type === 'empty') {
125 <td colspan="4">You have sufficient queue capacity to train more units.</td>
129 const created = DateTime.fromMillis(queue.created);
130 const due = DateTime.fromMillis(queue.due);
131 const now = Date.now() - queue.created;
132 const duration = queue.due - queue.created;
136 <td>${queue.display}</td>
137 <td>${queue.amount}</td>
138 <td>${progressBar(now, duration)}</td>
140 <a href="#" hx-post="/training/${queue.id}/cancel" hx-trigger="click" class="danger-text close" title="Cancel Unit Training">×</a>
150 return html + queues;