202 lines
7.3 KiB
JavaScript
202 lines
7.3 KiB
JavaScript
/* ============================================================
|
||
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");
|
||
|
||
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;
|
||
}
|
||
|
||
/* ════════════════════════════════════════════
|
||
Max erlaubte Rarity je Spielerlevel
|
||
(gleiche Logik wie booster.route.js)
|
||
════════════════════════════════════════════ */
|
||
function getMaxRarity(playerLevel) {
|
||
if (playerLevel < 10) return 2;
|
||
if (playerLevel < 20) return 3;
|
||
if (playerLevel < 30) return 4;
|
||
if (playerLevel < 40) return 5;
|
||
return 6;
|
||
}
|
||
|
||
/* ════════════════════════════════════════════
|
||
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;
|