1 import _ from "lodash";
2 import { DateTime } from "luxon";
3 import { Account } from "../repository/accounts";
4 import { ArmyQueueWithAttackedOwner } from "../repository/army";
5 import { City, CityRepository } from "../repository/city";
7 const cityRepo = new CityRepository();
9 export function renderOverworldMap(cities: City[], yourCity: City): string {
10 let map: City[][] = new Array(100);
11 for(let i = 0; i < cities.length; ++i) {
12 if(!map[cities[i].location_y]) {
13 map[cities[i].location_y] = new Array(100);
16 map[cities[i].location_y][cities[i].location_x] = cities[i];
19 let rows: string[] = [];
20 for(let y = 0; y < 100; ++y) {
22 for(let x = 0; x < 100; ++x) {
23 if(!map[y] || !map[y][x]) {
24 rows[y] += '<td><div class="empty"></div></td>' ;
27 if(map[y][x].id === yourCity.id)
28 rows[y] += '<td><div class="city yours"></div></td>';
30 rows[y] += `<td><div class="city others" hx-trigger="click" hx-get="/city/${map[y][x].id}" hx-target="#city-offence"></div></td>`;
33 rows[y] += '<td><div class="empty"></div></td>';
40 <div id="city-offence"></div>
41 <div id="outgoing-attacks" hx-trigger="reload-outgoing-attacks, every 600s, load" hx-get="/attacks/outgoing"></div>
42 <table id="overworld-map">
52 export function listOperations(outgoingOps: ArmyQueueWithAttackedOwner[]): string {
54 <h4>Outgoing Attacks</h4>
66 ${outgoingOps.map(op => {
69 <td>${op.attacked_account} - (${op.location_x},${op.location_y})</td>
70 <td>${op.soldiers.toLocaleString()}</td>
71 <td>${op.attackers.toLocaleString()}</td>
72 <td>${op.defenders.toLocaleString()}</td>
73 <td>${op.sp_attackers.toLocaleString()}</td>
74 <td>${op.sp_defenders.toLocaleString()}</td>
75 <td>${ _.round(DateTime.fromMillis(op.due).diffNow().as('hours'), 2)} hours</td>
85 export async function launchOffensive(city: City, owner: Account, yourCity: City, you: Account): Promise<string> {
86 const distance = cityRepo.distanceInHours(city, yourCity);
87 const power = await cityRepo.power({
88 soldiers: yourCity.soldiers,
89 attackers: yourCity.attackers,
90 defenders: yourCity.defenders,
91 sp_attackers: yourCity.sp_attackers,
92 sp_defenders: yourCity.sp_defenders
95 <h3>Viewing (${city.location_x},${city.location_y}) owned by ${owner.username}</h3>
97 <p>This city is ${distance} hours away.</p>
98 <form hx-post="/attack">
99 <input type="hidden" name="city" value="${city.id}">
104 <input type="number" class="potential-attack" name="soldiers" max="${yourCity.soldiers}" value="${yourCity.soldiers}" hx-target="#total-attack-power" hx-post="/attack-power" hx-include=".potential-attack">
105 (${yourCity.soldiers})
111 <input type="number" class="potential-attack" name="attackers" max="${yourCity.attackers}" value="${yourCity.attackers}" hx-target="#total-attack-power" hx-post="/attack-power" hx-include=".potential-attack">
112 (${yourCity.attackers})
118 <input type="number" class="potential-attack" name="defenders" max="${yourCity.defenders}" value="${yourCity.defenders}" hx-target="#total-attack-power" hx-post="/attack-power" hx-include=".potential-attack">
119 (${yourCity.defenders})
125 <input type="number" class="potential-attack" name="sp_attackers" max="${yourCity.sp_attackers}" value="${yourCity.sp_attackers}" hx-target="#total-attack-power" hx-post="/attack-power" hx-include=".potential-attack">
126 (${yourCity.sp_attackers})
130 <th>Sp. Defenders</th>
132 <input type="number" class="potential-attack" name="sp_defenders" max="${yourCity.sp_defenders}" value="${yourCity.sp_defenders}" hx-target="#total-attack-power" hx-post="/attack-power" hx-include=".potential-attack">
133 (${yourCity.sp_defenders})
138 <td id="total-attack-power">${power}</td>
141 <td colspan="2" style="text-align: right">
142 <button type="submit">Attack (${city.location_x},${city.location_y})</button>