212 lines
6.5 KiB
JavaScript
212 lines
6.5 KiB
JavaScript
const express = require("express");
|
||
const router = require("express").Router();
|
||
const db = require("../database/database");
|
||
|
||
function requireLogin(req, res, next) {
|
||
if (!req.session?.user) {
|
||
return res.status(401).json({ error: "Nicht eingeloggt" });
|
||
}
|
||
next();
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
HELPER: Timer sicherstellen
|
||
Legt beim allerersten Aufruf einen
|
||
Eintrag an – laeuft dann fuer immer durch.
|
||
Wird NUR durch collect() zurueckgesetzt.
|
||
───────────────────────────────────────── */
|
||
async function ensureTimer(userBuildingId) {
|
||
const [[existing]] = await db.query(
|
||
"SELECT last_collected FROM building_collect_timer WHERE user_building_id = ?",
|
||
[userBuildingId],
|
||
);
|
||
if (!existing) {
|
||
await db.query(
|
||
"INSERT INTO building_collect_timer (user_building_id, last_collected) VALUES (?, NOW())",
|
||
[userBuildingId],
|
||
);
|
||
}
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
HELPER: Produktionsdaten laden
|
||
Gibt immer last_collected aus der DB
|
||
───────────────────────────────────────── */
|
||
async function loadMineData(userId, buildingId) {
|
||
const [rows] = await db.query(
|
||
`
|
||
SELECT
|
||
ub.id AS user_building_id,
|
||
ub.level,
|
||
bp.resource,
|
||
bp.amount,
|
||
bp.cycle_seconds,
|
||
bct.last_collected
|
||
FROM user_buildings ub
|
||
JOIN building_production bp
|
||
ON bp.building_id = ub.building_id
|
||
AND bp.level = ub.level
|
||
JOIN building_collect_timer bct
|
||
ON bct.user_building_id = ub.id
|
||
WHERE ub.user_id = ?
|
||
AND ub.building_id = ?
|
||
`,
|
||
[userId, buildingId],
|
||
);
|
||
return rows;
|
||
}
|
||
|
||
/* ─────────────────────────────────────────
|
||
GET /api/mine/:buildingId/status
|
||
───────────────────────────────────────── */
|
||
router.get("/:buildingId/status", requireLogin, async (req, res) => {
|
||
const userId = req.session.user.id;
|
||
const buildingId = req.params.buildingId;
|
||
|
||
try {
|
||
// user_building holen
|
||
const [[userBuilding]] = await db.query(
|
||
"SELECT id, level FROM user_buildings WHERE user_id = ? AND building_id = ?",
|
||
[userId, buildingId],
|
||
);
|
||
|
||
if (!userBuilding) {
|
||
return res.status(404).json({ error: "Gebaeude nicht gefunden" });
|
||
}
|
||
|
||
// Timer einmalig starten falls noch nie geoeffnet
|
||
await ensureTimer(userBuilding.id);
|
||
|
||
const rows = await loadMineData(userId, buildingId);
|
||
if (!rows.length) {
|
||
return res.status(404).json({
|
||
error: `Keine Produktionsdaten fuer Level ${userBuilding.level} gefunden. Bitte building_production Tabelle pruefen.`,
|
||
});
|
||
}
|
||
|
||
const { cycle_seconds, last_collected, level } = rows[0];
|
||
|
||
const elapsed = Math.floor(
|
||
(Date.now() - new Date(last_collected).getTime()) / 1000,
|
||
);
|
||
const cycles = Math.floor(elapsed / cycle_seconds);
|
||
const nextIn = cycle_seconds - (elapsed % cycle_seconds);
|
||
|
||
const available = rows.map((r) => ({
|
||
resource: r.resource,
|
||
amount: r.amount * cycles,
|
||
}));
|
||
|
||
const production = rows.map((r) => ({
|
||
resource: r.resource,
|
||
amount: r.amount,
|
||
}));
|
||
|
||
res.json({
|
||
level,
|
||
cycles,
|
||
ready: cycles > 0,
|
||
available,
|
||
production,
|
||
last_collected,
|
||
next_cycle_in_seconds: nextIn,
|
||
cycle_seconds,
|
||
});
|
||
} catch (err) {
|
||
console.error(err);
|
||
res.status(500).json({ error: "DB Fehler" });
|
||
}
|
||
});
|
||
|
||
/* ─────────────────────────────────────────
|
||
POST /api/mine/:buildingId/collect
|
||
Ressourcen gutschreiben + Timer reset
|
||
───────────────────────────────────────── */
|
||
router.post("/:buildingId/collect", requireLogin, async (req, res) => {
|
||
const userId = req.session.user.id;
|
||
const buildingId = req.params.buildingId;
|
||
|
||
try {
|
||
// user_building holen
|
||
const [[userBuilding]] = await db.query(
|
||
"SELECT id FROM user_buildings WHERE user_id = ? AND building_id = ?",
|
||
[userId, buildingId],
|
||
);
|
||
|
||
if (!userBuilding) {
|
||
return res.status(404).json({ error: "Gebaeude nicht gefunden" });
|
||
}
|
||
|
||
// Timer sicherstellen (Fallback falls Status nie aufgerufen wurde)
|
||
await ensureTimer(userBuilding.id);
|
||
|
||
const rows = await loadMineData(userId, buildingId);
|
||
if (!rows.length) {
|
||
return res.status(404).json({ error: "Gebaeude nicht gefunden" });
|
||
}
|
||
|
||
const { user_building_id, cycle_seconds, last_collected } = rows[0];
|
||
|
||
const elapsed = Math.floor(
|
||
(Date.now() - new Date(last_collected).getTime()) / 1000,
|
||
);
|
||
const cycles = Math.floor(elapsed / cycle_seconds);
|
||
|
||
if (cycles < 1) {
|
||
const waitSeconds = cycle_seconds - elapsed;
|
||
const minutes = Math.floor(waitSeconds / 60);
|
||
const seconds = waitSeconds % 60;
|
||
return res.json({
|
||
error: "Noch nichts bereit",
|
||
ready_in_seconds: waitSeconds,
|
||
ready_in_display: `${minutes}m ${seconds}s`,
|
||
});
|
||
}
|
||
|
||
// Jede Ressource einzeln gutschreiben
|
||
const allowedResources = [
|
||
"gold",
|
||
"silver",
|
||
"copper",
|
||
"iron",
|
||
"wood",
|
||
"stone",
|
||
"gems",
|
||
];
|
||
|
||
for (const row of rows) {
|
||
if (!allowedResources.includes(row.resource)) continue;
|
||
|
||
const toAdd = row.amount * cycles;
|
||
|
||
await db.query(
|
||
`UPDATE account_currency SET \`${row.resource}\` = \`${row.resource}\` + ? WHERE account_id = ?`,
|
||
[toAdd, userId],
|
||
);
|
||
}
|
||
|
||
// Timer zuruecksetzen: last_collected um genau die abgeschlossenen
|
||
// Zyklen vorruecken – Restsekunden bleiben erhalten, kein Verlust
|
||
const newLastCollected = new Date(
|
||
new Date(last_collected).getTime() + cycles * cycle_seconds * 1000,
|
||
);
|
||
|
||
await db.query(
|
||
"UPDATE building_collect_timer SET last_collected = ? WHERE user_building_id = ?",
|
||
[newLastCollected, user_building_id],
|
||
);
|
||
|
||
const collected = rows.map((r) => ({
|
||
resource: r.resource,
|
||
amount: r.amount * cycles,
|
||
}));
|
||
|
||
res.json({ success: true, cycles, collected });
|
||
} catch (err) {
|
||
console.error(err);
|
||
res.status(500).json({ error: "DB Fehler" });
|
||
}
|
||
});
|
||
|
||
module.exports = router;
|