diff --git a/routes/mine_route.js b/routes/mine_route.js index 1d24c33..2fa85a3 100644 --- a/routes/mine_route.js +++ b/routes/mine_route.js @@ -1,50 +1,86 @@ -const express = require("express"); -const router = express.Router(); +const express = require("express"); +const router = require("express").Router(); const db = require("../database/database"); const auth = require("../middleware/auth"); +/* ───────────────────────────────────────── + 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 - Liefert Level, verfügbare Ressourcen - und Countdown bis zum nächsten Zyklus ───────────────────────────────────────── */ router.get("/:buildingId/status", auth, async (req, res) => { const userId = req.session.user.id; const buildingId = req.params.buildingId; try { - const [rows] = await db.query( - ` - SELECT - ub.id AS user_building_id, - ub.level, - bp.resource, - bp.amount, - bp.cycle_seconds, - COALESCE(bct.last_collected, NOW()) AS last_collected - FROM user_buildings ub - JOIN building_production bp - ON bp.building_id = ub.building_id - AND bp.level = ub.level - LEFT JOIN building_collect_timer bct - ON bct.user_building_id = ub.id - WHERE ub.user_id = ? - AND ub.building_id = ? - `, + // 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: "Gebäude nicht gefunden" }); + return res.status(404).json({ error: "Gebaeude nicht gefunden" }); } 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 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, @@ -59,6 +95,7 @@ router.get("/:buildingId/status", auth, async (req, res) => { last_collected, next_cycle_in_seconds: nextIn, }); + } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); @@ -67,44 +104,35 @@ router.get("/:buildingId/status", auth, async (req, res) => { /* ───────────────────────────────────────── POST /api/mine/:buildingId/collect - Schreibt Ressourcen gut, setzt Timer + Ressourcen gutschreiben + Timer reset ───────────────────────────────────────── */ router.post("/:buildingId/collect", auth, async (req, res) => { const userId = req.session.user.id; const buildingId = req.params.buildingId; try { - const [rows] = await db.query( - ` - SELECT - ub.id AS user_building_id, - ub.level, - bp.resource, - bp.amount, - bp.cycle_seconds, - COALESCE(bct.last_collected, NOW()) AS last_collected - FROM user_buildings ub - JOIN building_production bp - ON bp.building_id = ub.building_id - AND bp.level = ub.level - LEFT JOIN building_collect_timer bct - ON bct.user_building_id = ub.id - WHERE ub.user_id = ? - AND ub.building_id = ? - `, + // 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: "Gebäude nicht gefunden" }); + 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); + 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; @@ -121,27 +149,20 @@ router.post("/:buildingId/collect", auth, async (req, res) => { for (const row of rows) { const toAdd = row.amount * cycles; await db.query( - ` - INSERT INTO account_currency (account_id, \`${row.resource}\`) - VALUES (?, ?) - ON DUPLICATE KEY UPDATE \`${row.resource}\` = \`${row.resource}\` + ? - `, + "INSERT INTO account_currency (account_id, `" + row.resource + "`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `" + row.resource + "` = `" + row.resource + "` + ?", [userId, toAdd, toAdd] ); } - // Timer vorsetzen — Rest-Sekunden bleiben erhalten, kein Verlust + // 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( - ` - INSERT INTO building_collect_timer (user_building_id, last_collected) - VALUES (?, ?) - ON DUPLICATE KEY UPDATE last_collected = ? - `, - [user_building_id, newLastCollected, newLastCollected] + "UPDATE building_collect_timer SET last_collected = ? WHERE user_building_id = ?", + [newLastCollected, user_building_id] ); const collected = rows.map((r) => ({ @@ -149,15 +170,12 @@ router.post("/:buildingId/collect", auth, async (req, res) => { amount: r.amount * cycles, })); - res.json({ - success: true, - cycles, - collected, - }); + res.json({ success: true, cycles, collected }); + } catch (err) { console.error(err); res.status(500).json({ error: "DB Fehler" }); } }); -module.exports = router; +module.exports = router; \ No newline at end of file