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

179 lines
6.3 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");
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!) ── */
if (owned.amount - amount <= 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]
);
}
/* ── 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. Ausgabe-Karte bestimmen ── */
const targetRarity = parseInt(inputCard.rarity) + 1;
const maxRarity = getMaxRarity(playerLevel);
const outputRarity = Math.min(targetRarity, maxRarity);
// Karte mit outputRarity suchen (nicht dieselbe Karte)
const [pool] = await db.query(
"SELECT id, name, image, rarity, attack, defends, cooldown FROM cards WHERE rarity = ? AND id != ?",
[outputRarity, card_id]
);
// Fallback: gleiche Rarity falls keine höhere vorhanden
const [fallbackPool] = await db.query(
"SELECT id, name, image, rarity, attack, defends, cooldown FROM cards WHERE rarity = ?",
[parseInt(inputCard.rarity)]
);
const finalPool = pool.length ? pool : fallbackPool;
if (!finalPool.length) {
return res.status(500).json({ error: "Keine passende Karte gefunden." });
}
const reward = finalPool[Math.floor(Math.random() * finalPool.length)];
/* ── 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;