dok/routes/combine.route.js
2026-04-14 09:12:29 +01:00

191 lines
6.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ============================================================
routes/combine.route.js
POST /api/cards/combine
Karten kombinieren in der Gaststätte (Gebäude 6)
============================================================ */
const express = require("express");
const router = express.Router();
const db = require("../database/database");
const { getMaxRarity } = require("../utils/rarity");
function requireLogin(req, res, next) {
if (!req.session?.user) return res.status(401).json({ error: "Nicht eingeloggt" });
next();
}
/* ════════════════════════════════════════════
Gaststätte-Level → benötigte Karten für 100%
════════════════════════════════════════════ */
function getRequiredCards(tavernLevel) {
if (tavernLevel < 5) return 10;
if (tavernLevel < 10) return 8;
if (tavernLevel < 15) return 6;
if (tavernLevel < 20) return 5;
return 3;
}
/* ════════════════════════════════════════════
POST /api/cards/combine
Body: { card_id: Number, amount: Number }
════════════════════════════════════════════ */
router.post("/cards/combine", requireLogin, async (req, res) => {
const userId = req.session.user.id;
const { card_id, amount } = req.body;
if (!card_id || !amount || amount < 2) {
return res.status(400).json({ error: "Mindestens 2 Karten erforderlich." });
}
try {
/* ── 1. Spielerlevel holen ── */
const [[account]] = await db.query(
"SELECT level FROM accounts WHERE id = ?",
[userId]
);
const playerLevel = account?.level ?? 1;
/* ── 2. Gaststätte-Level holen (building_id = 6) ── */
const [[tavern]] = await db.query(
"SELECT level FROM user_buildings WHERE user_id = ? AND building_id = 6",
[userId]
);
const tavernLevel = tavern?.level ?? 1;
/* ── 3. Chance berechnen ── */
const required = getRequiredCards(tavernLevel);
const chance = Math.min((amount / required) * 100, 100);
/* ── 4. Besitz prüfen ── */
const [[owned]] = await db.query(
"SELECT amount FROM user_cards WHERE user_id = ? AND card_id = ?",
[userId, card_id]
);
if (!owned || owned.amount < amount) {
return res.status(400).json({ error: "Nicht genügend Karten vorhanden." });
}
/* ── 5. Eingabe-Karte laden (für Rarity) ── */
const [[inputCard]] = await db.query(
"SELECT id, name, rarity FROM cards WHERE id = ?",
[card_id]
);
if (!inputCard) {
return res.status(400).json({ error: "Karte nicht gefunden." });
}
/* ── 6. Karten immer abziehen (Glücksspiel!) ── */
const remainingAfter = owned.amount - amount;
if (remainingAfter <= 0) {
await db.query(
"DELETE FROM user_cards WHERE user_id = ? AND card_id = ?",
[userId, card_id]
);
} else {
await db.query(
"UPDATE user_cards SET amount = amount - ? WHERE user_id = ? AND card_id = ?",
[amount, userId, card_id]
);
}
/* ── 6b. Decks synchronisieren ──────────────────────────────────
Karten die durch Kombination verbraucht wurden, müssen auch aus
allen Decks des Spielers entfernt / reduziert werden.
Sonst steht im Deck mehr als der Spieler tatsächlich besitzt.
────────────────────────────────────────────────────────────────── */
if (remainingAfter <= 0) {
// Keine Exemplare mehr vorhanden → aus allen Decks löschen
await db.query(
`DELETE dc FROM deck_cards dc
JOIN decks d ON d.id = dc.deck_id
WHERE d.user_id = ? AND dc.card_id = ?`,
[userId, card_id]
);
} else {
// Noch welche vorhanden → Deck-Menge auf verbleibende Menge deckeln
await db.query(
`UPDATE deck_cards dc
JOIN decks d ON d.id = dc.deck_id
SET dc.amount = LEAST(dc.amount, ?)
WHERE d.user_id = ? AND dc.card_id = ?`,
[remainingAfter, userId, card_id]
);
}
/* ── 7. Zufallsroll gegen Chance ── */
const roll = Math.random() * 100;
const success = roll <= chance;
if (!success) {
return res.json({
success: false,
chance: Math.round(chance),
message: "Kombinieren fehlgeschlagen die Karten wurden verbraucht.",
});
}
/* ── 8. Gleiche Karte mit Rarity+1 suchen ── */
const targetRarity = parseInt(inputCard.rarity) + 1;
const maxRarity = getMaxRarity(playerLevel);
if (targetRarity > maxRarity) {
return res.status(400).json({
error: `Dein Spielerlevel erlaubt keine Karten über Rarity ${maxRarity}.`,
});
}
const [[reward]] = await db.query(
"SELECT id, name, image, rarity, attack, defends, cooldown FROM cards WHERE name = ? AND rarity = ?",
[inputCard.name, targetRarity]
);
if (!reward) {
return res.status(400).json({
error: `Keine höhere Version von "${inputCard.name}" (Rarity ${targetRarity}) in der Datenbank gefunden.`,
});
}
/* ── 9. Belohnungskarte gutschreiben ── */
await db.query(
`INSERT INTO user_cards (user_id, card_id, amount)
VALUES (?, ?, 1)
ON DUPLICATE KEY UPDATE amount = amount + 1`,
[userId, reward.id]
);
res.json({
success: true,
chance: Math.round(chance),
reward,
message: `Kombinieren erfolgreich! Du erhältst: ${reward.name}`,
});
} catch (err) {
console.error("Combine Fehler:", err);
res.status(500).json({ error: "DB Fehler" });
}
});
/* ════════════════════════════════════════════
GET /api/cards/combine-info
Gaststätte-Level + benötigte Karten für Frontend
════════════════════════════════════════════ */
router.get("/cards/combine-info", requireLogin, async (req, res) => {
const userId = req.session.user.id;
try {
const [[tavern]] = await db.query(
"SELECT level FROM user_buildings WHERE user_id = ? AND building_id = 6",
[userId]
);
const tavernLevel = tavern?.level ?? 1;
const required = getRequiredCards(tavernLevel);
res.json({ tavernLevel, required });
} catch (err) {
console.error(err);
res.status(500).json({ error: "DB Fehler" });
}
});
module.exports = router;