mine update

This commit is contained in:
Cay 2026-03-16 12:50:00 +00:00
parent d72fcb2fe7
commit 56cfcb2de1

View File

@ -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;