compare versions
Compare veresions and update sets -> Cards
This commit is contained in:
@@ -0,0 +1,38 @@
|
||||
const { setAmountOwned } = require('../models/collectionModel');
|
||||
|
||||
async function updateAmountOwned(req, res) {
|
||||
try {
|
||||
const { card_id, set_id, rarity_id, amount_owned } = req.body;
|
||||
|
||||
if (
|
||||
card_id == null ||
|
||||
set_id == null ||
|
||||
rarity_id == null ||
|
||||
amount_owned == null
|
||||
) {
|
||||
return res.status(400).json({ error: 'Missing required fields' });
|
||||
}
|
||||
|
||||
if (amount_owned < 0) {
|
||||
return res.status(400).json({ error: 'Amount cannot be negative' });
|
||||
}
|
||||
|
||||
const result = await setAmountOwned({
|
||||
card_id,
|
||||
set_id,
|
||||
rarity_id,
|
||||
amount_owned
|
||||
});
|
||||
|
||||
res.json({
|
||||
message: 'Amount updated',
|
||||
...result
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error updating amount:', err);
|
||||
res.status(500).json({ error: 'Failed to update amount owned' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { updateAmountOwned };
|
||||
@@ -1,23 +1,17 @@
|
||||
const {
|
||||
upsertCard
|
||||
} = require('../models/cardModel');
|
||||
const {
|
||||
upsertRarity,
|
||||
getRarityId
|
||||
} = require('../models/rarityModel');
|
||||
const {upsertCard} = require('../models/cardModel');
|
||||
const {upsertRarity,getRarityId} = require('../models/rarityModel');
|
||||
const { upsertSet } = require('../models/setModel');
|
||||
const { insertCardSetRarity } = require('../models/cardSetRarityModel');
|
||||
const { insertCardImage } = require('../models/cardImageModel');
|
||||
const { fetchAllCards } = require('../services/ygoproService');
|
||||
const { fetchAllCards, fetchAllSets } = require('../services/ygoproService');
|
||||
const db = require('../config/db');
|
||||
|
||||
const BATCH_SIZE = 50;
|
||||
|
||||
async function importSets(req, res) {
|
||||
try {
|
||||
async function importSetsInternal() {
|
||||
const sets = await fetchAllSets();
|
||||
let added = 0;
|
||||
|
||||
// Parallelized batch insert
|
||||
for (let i = 0; i < sets.length; i += BATCH_SIZE) {
|
||||
const batch = sets.slice(i, i + BATCH_SIZE);
|
||||
await Promise.all(batch.map(async (set) => {
|
||||
@@ -26,52 +20,50 @@ async function importSets(req, res) {
|
||||
}));
|
||||
}
|
||||
|
||||
res.json({
|
||||
return {
|
||||
added,
|
||||
total: sets.length
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Express handler for /sets endpoint
|
||||
async function importSets(req, res) {
|
||||
try {
|
||||
const result = await importSetsInternal();
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error('Error importing sets:', err);
|
||||
res.status(500).json({ error: 'Failed to import sets' });
|
||||
}
|
||||
}
|
||||
|
||||
async function importCards(req, res) {
|
||||
async function importCardsInternal() {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const cards = await fetchAllCards();
|
||||
const totalCards = cards.length;
|
||||
|
||||
let addedCards = 0, addedImages = 0, addedRarities = 0;
|
||||
|
||||
// Cache sets and rarities to reduce repeated DB lookups
|
||||
const rarityCache = {};
|
||||
const setCache = {};
|
||||
|
||||
// Preload sets into cache
|
||||
const [setsRows] = await db.execute('SELECT id, set_code FROM sets');
|
||||
const [setsRows] = await db.execute('SELECT id, set_name FROM sets');
|
||||
for (const row of setsRows) {
|
||||
setCache[row.set_code] = row.id;
|
||||
setCache[row.set_name] = row.id;
|
||||
}
|
||||
|
||||
// Preload rarities into cache
|
||||
const [rarityRows] = await db.execute('SELECT id, rarity_name FROM rarities');
|
||||
for (const row of rarityRows) {
|
||||
rarityCache[row.rarity_name] = row.id;
|
||||
}
|
||||
|
||||
// Process cards in batches
|
||||
for (let i = 0; i < totalCards; i += BATCH_SIZE) {
|
||||
const batch = cards.slice(i, i + BATCH_SIZE);
|
||||
|
||||
// Wrap batch in a transaction
|
||||
const conn = await db.getConnection();
|
||||
try {
|
||||
await conn.beginTransaction();
|
||||
|
||||
await Promise.all(batch.map(async (card) => {
|
||||
// Upsert card
|
||||
await conn.execute(`
|
||||
INSERT INTO cards
|
||||
(id, name, card_type, frame_type, level, race, attribute, link_val, tcg_date, ocg_date)
|
||||
@@ -100,10 +92,8 @@ async function importCards(req, res) {
|
||||
]);
|
||||
addedCards++;
|
||||
|
||||
// Process rarities and card_sets_rarity
|
||||
if (Array.isArray(card.card_sets)) {
|
||||
for (const set of card.card_sets) {
|
||||
// Upsert rarity if not cached
|
||||
if (!rarityCache[set.set_rarity]) {
|
||||
await conn.execute(`
|
||||
INSERT INTO rarities (rarity_name, rarity_code)
|
||||
@@ -115,9 +105,7 @@ async function importCards(req, res) {
|
||||
addedRarities++;
|
||||
}
|
||||
const rarity_id = rarityCache[set.set_rarity];
|
||||
|
||||
// Get set_id from cache
|
||||
const set_id = setCache[set.set_code];
|
||||
const set_id = setCache[set.set_name];
|
||||
if (set_id) {
|
||||
await conn.execute(`
|
||||
INSERT INTO card_sets_rarity (card_id, set_id, rarity_id, card_set_code)
|
||||
@@ -128,7 +116,6 @@ async function importCards(req, res) {
|
||||
}
|
||||
}
|
||||
|
||||
// Process card images
|
||||
if (Array.isArray(card.card_images)) {
|
||||
for (const img of card.card_images) {
|
||||
await conn.execute(`
|
||||
@@ -148,25 +135,30 @@ async function importCards(req, res) {
|
||||
conn.release();
|
||||
}
|
||||
|
||||
// Release batch memory
|
||||
batch.length = 0;
|
||||
}
|
||||
|
||||
const endTime = Date.now();
|
||||
const durationSeconds = ((endTime - startTime) / 1000).toFixed(2);
|
||||
const durationSeconds = ((Date.now() - startTime) / 1000).toFixed(2);
|
||||
|
||||
res.json({
|
||||
return {
|
||||
total_cards: totalCards,
|
||||
cards_added: addedCards,
|
||||
images_added: addedImages,
|
||||
rarities_added: addedRarities,
|
||||
duration_seconds: parseFloat(durationSeconds)
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
// Express handler for /cards
|
||||
async function importCards(req, res) {
|
||||
try {
|
||||
const result = await importCardsInternal();
|
||||
res.json(result);
|
||||
} catch (err) {
|
||||
console.error('Error importing cards:', err);
|
||||
res.status(500).json({ error: 'Failed to import cards' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { importCards, importSets };
|
||||
|
||||
module.exports = { importCards, importCardsInternal, importSets, importSetsInternal };
|
||||
@@ -0,0 +1,42 @@
|
||||
const { fetchDatabaseVersion } = require('../services/ygoproService');
|
||||
const { getLocalDBVersion, setLocalDBVersion } = require('../models/dbVersionModel');
|
||||
const { importSetsInternal } = require('./importController');
|
||||
const { importCardsInternal } = require('./importController');
|
||||
|
||||
async function importFullDatabase(req, res) {
|
||||
const startTime = Date.now();
|
||||
|
||||
try {
|
||||
const remoteVersion = await fetchDatabaseVersion();
|
||||
const localVersion = await getLocalDBVersion();
|
||||
|
||||
if (localVersion && localVersion.database_version === remoteVersion.database_version) {
|
||||
return res.json({
|
||||
message: 'Database is already up to date.',
|
||||
version: remoteVersion.database_version
|
||||
});
|
||||
}
|
||||
|
||||
const setsStats = await importSetsInternal();
|
||||
|
||||
const cardsStats = await importCardsInternal();
|
||||
|
||||
await setLocalDBVersion(remoteVersion.database_version, remoteVersion.last_update);
|
||||
|
||||
const totalDuration = ((Date.now() - startTime) / 1000).toFixed(2);
|
||||
|
||||
res.json({
|
||||
message: 'Database import completed successfully.',
|
||||
version: remoteVersion.database_version,
|
||||
sets: setsStats,
|
||||
cards: cardsStats,
|
||||
duration_seconds: parseFloat(totalDuration)
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.error('Error in full database import:', err);
|
||||
res.status(500).json({ error: 'Failed to import database' });
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { importFullDatabase };
|
||||
@@ -11,3 +11,6 @@ const PORT = process.env.PORT || 3000;
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on http://localhost:${PORT}`);
|
||||
});
|
||||
|
||||
const collectionRoutes = require('./routes/collectionRoutes');
|
||||
app.use('/collection', collectionRoutes);
|
||||
@@ -0,0 +1,14 @@
|
||||
const db = require('../config/db');
|
||||
|
||||
async function setAmountOwned({ card_id, set_id, rarity_id, amount_owned }) {
|
||||
await db.execute(`
|
||||
INSERT INTO card_sets_rarity (card_id, set_id, rarity_id, amount_owned)
|
||||
VALUES (?, ?, ?, ?)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
amount_owned = VALUES(amount_owned)
|
||||
`, [card_id, set_id, rarity_id, amount_owned]);
|
||||
|
||||
return { card_id, set_id, rarity_id, amount_owned };
|
||||
}
|
||||
|
||||
module.exports = { setAmountOwned };
|
||||
@@ -0,0 +1,17 @@
|
||||
const db = require('../config/db');
|
||||
|
||||
async function getLocalDBVersion() {
|
||||
const [rows] = await db.execute(
|
||||
'SELECT database_version, last_update FROM db_version ORDER BY last_update DESC LIMIT 1'
|
||||
);
|
||||
return rows.length ? rows[0] : null;
|
||||
}
|
||||
|
||||
async function setLocalDBVersion(version, date) {
|
||||
await db.execute(
|
||||
'INSERT INTO db_version (database_version, last_update) VALUES (?, ?)',
|
||||
[version ?? null, date ?? null]
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = { getLocalDBVersion, setLocalDBVersion };
|
||||
@@ -0,0 +1,7 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { updateAmountOwned } = require('../controllers/collectionController');
|
||||
|
||||
router.put('/amount', updateAmountOwned);
|
||||
|
||||
module.exports = router;
|
||||
@@ -1,8 +1,10 @@
|
||||
const express = require('express');
|
||||
const router = express.Router();
|
||||
const { importSets, importCards} = require('../controllers/importController');
|
||||
const { importFullDatabase } = require('../controllers/newVersionController');
|
||||
|
||||
router.post('/sets', importSets);
|
||||
router.post('/cards', importCards);
|
||||
router.post('/full-import', importFullDatabase);
|
||||
|
||||
module.exports = router;
|
||||
@@ -22,12 +22,29 @@ async function fetchAllSets() {
|
||||
async function fetchAllCards() {
|
||||
try {
|
||||
const response = await axios.get(`${API_BASE}/cardinfo.php?misc=yes`);
|
||||
return response.data.data; // array of card objects
|
||||
return response.data.data;
|
||||
} catch (err) {
|
||||
console.error('Error fetching cards from YGOPRODeck:', err.message);
|
||||
throw err;
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchDatabaseVersion() {
|
||||
const response = await axios.get(`${API_BASE}/checkDBVer.php`);
|
||||
const data = response.data;
|
||||
|
||||
module.exports = { fetchAllCards, fetchAllSets };
|
||||
// Handle array response from API
|
||||
const versionInfo = Array.isArray(data) ? data[0] : data;
|
||||
|
||||
if (!versionInfo || !versionInfo.database_version || !versionInfo.last_update) {
|
||||
throw new Error('Invalid database version response from YGOPRODeck API');
|
||||
}
|
||||
|
||||
return {
|
||||
database_version: versionInfo.database_version,
|
||||
last_update: versionInfo.last_update
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
module.exports = { fetchAllCards, fetchAllSets, fetchDatabaseVersion };
|
||||
Reference in New Issue
Block a user