Implement fuel consumption mechanic
Front-end only for now
This commit is contained in:
parent
d664fc00ef
commit
848f2c37dc
|
@ -67,7 +67,7 @@ if(!(planet instanceof SystemManager)) {
|
|||
</div>
|
||||
</div>
|
||||
{resourceArray.map(res =>
|
||||
<div class="resourcebar-item resourcebar-iterable"
|
||||
<div class="resourcebar-item resourcebar-iterable" id={`resource-${res.id}`}
|
||||
data-res-type={resourceTypes.find(x => x.id === res.id)?.type ?? "solid"}
|
||||
data-res-id={res.id}
|
||||
data-res-amount={res.amount}
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
import { APIRoute } from "astro";
|
||||
import parseParams from "../../../lib/utils/parseParams";
|
||||
import locationManager, { Sector } from "../../../lib/classes/managers/LocationManager";
|
||||
import SystemManager from "../../../lib/classes/managers/SystemManager";
|
||||
import { Planet } from "../../../lib/classes/managers/PlanetManager";
|
||||
import getDistanceBetween from "../../../lib/utils/getDistanceBetween";
|
||||
|
||||
export const GET: APIRoute = async({ request }) => {
|
||||
const URLParams = parseParams(request.url);
|
||||
if(!URLParams.source || !URLParams.destination) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 400,
|
||||
message: "Bad Request",
|
||||
error: "Missing parameters"
|
||||
}), { status: 400 }
|
||||
);
|
||||
}
|
||||
|
||||
const source = locationManager.findId(URLParams.source);
|
||||
if(source === null) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 404,
|
||||
message: "Not Found",
|
||||
error: "Source not found"
|
||||
}), { status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
let destination: Planet | SystemManager | Sector | null = locationManager.findId(URLParams.destination);
|
||||
if(destination === null) destination = locationManager.getSector(URLParams.destination) ?? null;
|
||||
if(destination === null) {
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 404,
|
||||
message: "Not Found",
|
||||
error: "Destination not found"
|
||||
}), { status: 404 }
|
||||
);
|
||||
}
|
||||
|
||||
return new Response(
|
||||
JSON.stringify({
|
||||
code: 200,
|
||||
message: "OK",
|
||||
distance: getDistanceBetween(source, destination)
|
||||
}), { status: 200 }
|
||||
)
|
||||
}
|
|
@ -11,6 +11,7 @@ import { getName } from '../../lib/utils/langDriver';
|
|||
const { token, user, lang } = Astro.locals;
|
||||
const active: SystemManager | Planet = Astro.locals.active;
|
||||
|
||||
const activeId = active instanceof SystemManager ? active.data._id : active._id;
|
||||
const ships = await getAllShips();
|
||||
const url = Astro.url.origin;
|
||||
|
||||
|
@ -82,10 +83,10 @@ for(const f of fleet) {
|
|||
if(source !== null) {
|
||||
if(source instanceof SystemManager) {
|
||||
if(source.data.ownedBy.id.equals(user.id)) own++;
|
||||
else enemy++;
|
||||
else if(!f.returning) enemy++;
|
||||
} else {
|
||||
if(source.system.data.ownedBy.id.equals(user.id)) own++;
|
||||
else enemy++;
|
||||
else if(!f.returning) enemy++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -152,14 +153,14 @@ const sectorsList = galaxies.map(galaxy => {
|
|||
</div>
|
||||
</label>
|
||||
<div class="fleet-send-container">
|
||||
<form method="post">
|
||||
<form method="post" id="send-fleet">
|
||||
<h1>Sending fleet from {active instanceof SystemManager ? active.data.name : active.name}</h1>
|
||||
<hr />
|
||||
<h2>Ships</h2>
|
||||
<div class="fleet-send-ships">
|
||||
{active.ships.ships.map(ship => <div class="fleet-ship-card">
|
||||
<h3>{getName(lang, 'ships', ship.data.id)} - {ship.amount}</h3>
|
||||
<input type="number" value="0" min="0" max={ship.amount} id={ship.data.id} name={`ship-amount-${ship.data.id}`} />
|
||||
<input type="number" value="0" min="0" max={ship.amount} id={ship.data.id} name={`ship-amount-${ship.data.id}`} class="ship-amount-inputs" />
|
||||
</div>)}
|
||||
</div>
|
||||
<hr />
|
||||
|
@ -171,24 +172,37 @@ const sectorsList = galaxies.map(galaxy => {
|
|||
<label for="spy"><input type="radio" name="mission" value="SPY" id="spy" />Spying</label>
|
||||
<label><input type="checkbox" name="toSystem" />Send to system</label>
|
||||
<hr />
|
||||
<h2>Send to:</h2>
|
||||
<h2>Send to</h2>
|
||||
<div class="fleet-destination">
|
||||
<div>
|
||||
<h3>Galaxy</h3>
|
||||
<select id="destination-galaxy" name="destination-galaxy">
|
||||
{galaxies.map(galaxy => <option value={galaxy._id.toString()}>{galaxy.name}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Sector</h3>
|
||||
<select id="destination-sector" name="destination-sector"></select>
|
||||
</div>
|
||||
<div>
|
||||
<h3>System</h3>
|
||||
<select id="destination-system" name="destination-system"></select>
|
||||
<div id="destination-system-error"></div>
|
||||
</div>
|
||||
<div>
|
||||
<h3>Planet</h3>
|
||||
<select id="destination-planet" name="destination-planet"></select>
|
||||
<div id="destination-planet-error"></div>
|
||||
</div>
|
||||
</div>
|
||||
<hr />
|
||||
<h2>Cargo</h2>
|
||||
<div class="cargo-container">
|
||||
<div id="cargo-available">
|
||||
Solid: <span id="available-solid">0</span><br />
|
||||
Liquid: <span id="available-liquid">0</span><br />
|
||||
Gas: <span id="available-gas">0</span><br />
|
||||
</div>
|
||||
<div class="cargo-container" id="cargo-container">
|
||||
<div class="cargo-item">
|
||||
<select name="cargo[0][id]" class="select">
|
||||
<option value="coal">Coal</option>
|
||||
|
@ -207,6 +221,15 @@ const sectorsList = galaxies.map(galaxy => {
|
|||
</div>
|
||||
<div id="cargo-add-new">Add new +</div>
|
||||
<hr />
|
||||
<h2>Fuel consumption</h2>
|
||||
<div>Base usage from ships: <span id="fuel-consumption">0</span></div>
|
||||
<div>Distance: <span id="fuel-consumption-distance">0</span></div>
|
||||
<div><span id="fuel-consumption-required">0</span> hydrogen will be added to cargo as fuel</div>
|
||||
<hr />
|
||||
<h2>Estimates</h2>
|
||||
<div>Fleet will arrive at destination at: <span id="arrival-time"></span></div>
|
||||
<div>Fleet will return at: <span id="return-time"></span></div>
|
||||
<hr />
|
||||
<button type="submit">Send fleet</button>
|
||||
</form>
|
||||
</div>
|
||||
|
@ -318,6 +341,12 @@ label {
|
|||
color: black;
|
||||
}
|
||||
|
||||
.fleet-destination {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
column-gap: 5%;
|
||||
}
|
||||
|
||||
.fleet-destination select {
|
||||
width: 10rem;
|
||||
height: 3rem;
|
||||
|
@ -337,7 +366,7 @@ label {
|
|||
color: black;
|
||||
}
|
||||
</style>
|
||||
<script define:vars={{ lang, sectorsList, url }}>
|
||||
<script define:vars={{ lang, sectorsList, url, ships, activeId }}>
|
||||
const revertButtons = document.querySelectorAll('.revert');
|
||||
const destinationGalaxy = document.getElementById('destination-galaxy');
|
||||
const destinationSector = document.getElementById('destination-sector');
|
||||
|
@ -345,8 +374,10 @@ label {
|
|||
const destinationPlanet = document.getElementById('destination-planet');
|
||||
const toSystemCheckbox = document.querySelector('input[name="toSystem"]');
|
||||
const sendAllButtons = document.querySelectorAll('.cargo-sendall');
|
||||
const shipInputs = document.querySelectorAll('.ship-amount-inputs');
|
||||
const sendFleetForm = document.getElementById('send-fleet');
|
||||
|
||||
if(!revertButtons || !destinationGalaxy || !destinationSector || !destinationSystem || !destinationPlanet || !toSystemCheckbox || !sendAllButtons) {
|
||||
if(!revertButtons || !destinationGalaxy || !destinationSector || !destinationSystem || !destinationPlanet || !toSystemCheckbox || !sendAllButtons || !shipInputs || !sendFleetForm) {
|
||||
console.error('Could not find all elements');
|
||||
return;
|
||||
};
|
||||
|
@ -449,12 +480,17 @@ label {
|
|||
opt.innerText = 'No planets';
|
||||
destinationPlanet.appendChild(opt);
|
||||
}
|
||||
|
||||
destinationPlanet.dispatchEvent(new Event('change'));
|
||||
});
|
||||
|
||||
destinationPlanet.addEventListener('change', calculateDistance);
|
||||
|
||||
destinationGalaxy.dispatchEvent(new Event('change'));
|
||||
|
||||
toSystemCheckbox.addEventListener('change', () => {
|
||||
destinationPlanet.disabled = toSystemCheckbox.checked;
|
||||
calculateDistance();
|
||||
});
|
||||
|
||||
sendAllButtons.forEach(button => {
|
||||
|
@ -495,6 +531,169 @@ label {
|
|||
cargoContainer.appendChild(cargoItem);
|
||||
});
|
||||
|
||||
shipInputs.forEach(input => {
|
||||
input.addEventListener('input', () => {
|
||||
const fuelConsumption = Array.from(shipInputs).reduce((acc, cur) => {
|
||||
const ship = ships.find(ship => ship.id === cur.id);
|
||||
if(!ship) return acc;
|
||||
|
||||
return acc + ship.fuelConsumption * parseInt(cur.value);
|
||||
}, 0);
|
||||
|
||||
document.getElementById('fuel-consumption').innerText = fuelConsumption;
|
||||
|
||||
const availableSolid = Array.from(shipInputs).reduce((acc, cur) => {
|
||||
const ship = ships.find(ship => ship.id === cur.id);
|
||||
if(!ship) return acc;
|
||||
|
||||
return acc + ship.capacity.solid * parseInt(cur.value);
|
||||
}, 0);
|
||||
const availableLiquid = Array.from(shipInputs).reduce((acc, cur) => {
|
||||
const ship = ships.find(ship => ship.id === cur.id);
|
||||
if(!ship) return acc;
|
||||
|
||||
return acc + ship.capacity.liquid * parseInt(cur.value);
|
||||
}, 0);
|
||||
const availableGas = Array.from(shipInputs).reduce((acc, cur) => {
|
||||
const ship = ships.find(ship => ship.id === cur.id);
|
||||
if(!ship) return acc;
|
||||
|
||||
return acc + ship.capacity.gas * parseInt(cur.value);
|
||||
}, 0);
|
||||
|
||||
document.getElementById('available-solid').innerText = availableSolid;
|
||||
document.getElementById('available-liquid').innerText = availableLiquid;
|
||||
document.getElementById('available-gas').innerText = availableGas;
|
||||
|
||||
calculateRequiredFuel();
|
||||
});
|
||||
});
|
||||
|
||||
sendFleetForm.addEventListener('submit', evt => {
|
||||
evt.preventDefault();
|
||||
|
||||
// at least one ship
|
||||
if(Array.from(shipInputs).reduce((acc, cur) => acc + parseInt(cur.value), 0) === 0) {
|
||||
alert('You need to send at least one ship');
|
||||
return;
|
||||
}
|
||||
|
||||
// source === destination
|
||||
const destinationId = document.querySelector('input[name="toSystem"]').checked ? document.getElementById('destination-system').value : document.getElementById('destination-planet').value;
|
||||
if(destinationId === activeId) {
|
||||
alert('Source and destination cannot be the same');
|
||||
return;
|
||||
}
|
||||
|
||||
// check fuel
|
||||
const requiredFuel = parseInt(document.getElementById('fuel-consumption-required').innerText);
|
||||
const storedFuel = parseInt(document.getElementById('resource-hydrogen').dataset.resAmount);
|
||||
|
||||
if(storedFuel < requiredFuel) {
|
||||
alert('Not enough fuel in storage');
|
||||
return;
|
||||
}
|
||||
|
||||
const cargoSolidStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
|
||||
const resId = cur.children.item(0).value;
|
||||
if(resId === "coal" || resId === "iron" || resId === "gold") {
|
||||
const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
|
||||
return acc + amount;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
const cargoLiquidStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
|
||||
const resId = cur.children.item(0).value;
|
||||
if(resId === "water" || resId === "sulfuric-acid" || resId === "liquid-nitrogen") {
|
||||
const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
|
||||
return acc + amount;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
const cargoGasStored = Array.from(document.getElementById('cargo-container').children).reduce((acc, cur) => {
|
||||
const resId = cur.children.item(0).value;
|
||||
if(resId === "hydrogen" || resId === "oxygen" || resId === "helium-3") {
|
||||
const amount = cur.children.item(1).value === "" ? 0 : parseInt(cur.children.item(1).value);
|
||||
return acc + amount;
|
||||
}
|
||||
return acc;
|
||||
}, 0);
|
||||
|
||||
const cargoSolidCapacity = document.getElementById('available-solid').innerText;
|
||||
const cargoLiquidCapacity = document.getElementById('available-liquid').innerText;
|
||||
const cargoGasCapacity = document.getElementById('available-gas').innerText;
|
||||
|
||||
if(cargoSolidStored > cargoSolidCapacity) {
|
||||
alert('Not enough solid capacity in ships');
|
||||
return;
|
||||
}
|
||||
|
||||
if(cargoLiquidStored > cargoLiquidCapacity) {
|
||||
alert('Not enough liquid capacity in ships');
|
||||
return;
|
||||
}
|
||||
|
||||
if(cargoGasStored > cargoGasCapacity) {
|
||||
alert('Not enough gas capacity in ships');
|
||||
return;
|
||||
}
|
||||
|
||||
if((cargoGasStored + requiredFuel) > cargoGasCapacity) {
|
||||
alert('Not enough gas capacity in ships for fuel');
|
||||
return;
|
||||
}
|
||||
|
||||
// add hydrogen to cargo
|
||||
// const hydrogenInCargo = Array.from(document.getElementById('cargo-container').children).find(c => c.children.item(0).value === "hydrogen")?.children.item(1).value ?? 0;
|
||||
// const formData = new FormData(evt.target);
|
||||
|
||||
sendFleetForm.submit();
|
||||
});
|
||||
|
||||
async function calculateDistance() {
|
||||
const source = activeId;
|
||||
const destination = document.querySelector('input[name="toSystem"]').checked ? document.getElementById('destination-system').value : document.getElementById('destination-planet').value;
|
||||
|
||||
if(!source || !destination) return;
|
||||
|
||||
const response = await fetch(`${url}/api/fleet/getDistance?source=${source}&destination=${destination}`);
|
||||
const data = await response.json();
|
||||
|
||||
if(data.error) {
|
||||
document.getElementById('fuel-consumption-distance').innerText = "Error";
|
||||
return;
|
||||
}
|
||||
|
||||
const distance = data.distance;
|
||||
|
||||
document.getElementById('fuel-consumption-distance').innerText = distance;
|
||||
document.getElementById('arrival-time').innerText = new Date(new Date().getTime() + distance * 1000).toLocaleString();
|
||||
document.getElementById('return-time').innerText = new Date(new Date().getTime() + distance * 1000 * 2).toLocaleString();
|
||||
|
||||
calculateRequiredFuel();
|
||||
}
|
||||
|
||||
function calculateRequiredFuel() {
|
||||
const fuelConsumption = parseInt(document.getElementById('fuel-consumption').innerText);
|
||||
const distance = parseInt(document.getElementById('fuel-consumption-distance').innerText);
|
||||
|
||||
if(isNaN(fuelConsumption) || isNaN(distance)) {
|
||||
document.getElementById('fuel-consumption-required').innerText = "Error";
|
||||
return;
|
||||
}
|
||||
|
||||
if(distance === 0) {
|
||||
document.getElementById('fuel-consumption-required').innerText = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const requiredFuel = Math.ceil(Math.log(fuelConsumption * distance) / Math.log(1.01));
|
||||
|
||||
document.getElementById('fuel-consumption-required').innerText = requiredFuel;
|
||||
}
|
||||
|
||||
function handleAllClick(button) {
|
||||
const avaliableResources = [];
|
||||
for(const resItem of document.querySelectorAll('.resourcebar-item')) {
|
||||
|
|
|
@ -20,4 +20,5 @@ export default interface DBShip {
|
|||
attack: number;
|
||||
};
|
||||
speed: number;
|
||||
fuelConsumption: number;
|
||||
}
|
Loading…
Reference in New Issue