refactor: remove patch_detector and use gameVersion field in match_collector
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
import { spawn } from 'child_process';
|
||||
import path from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __filename = fileURLToPath(import.meta.url);
|
||||
const __dirname = path.dirname(__filename);
|
||||
|
||||
// Cache directory - use dev/cdragon by default
|
||||
const cacheDir = process.env.CDRAGON_CACHE_DIR || path.join(__dirname, '..', 'data', 'cdragon');
|
||||
|
||||
// Dev MongoDB credentials (matching docker-compose.yml defaults)
|
||||
const mongoUser = process.env.MONGO_USER || 'root';
|
||||
const mongoPass = process.env.MONGO_PASS || 'password';
|
||||
const mongoHost = process.env.MONGO_HOST || 'localhost:27017';
|
||||
|
||||
// Run patch_detector with the cache directory and dev MongoDB credentials
|
||||
const patchDetector = spawn('npx', ['tsx', '../patch_detector/index.ts'], {
|
||||
cwd: path.join(__dirname, '..'),
|
||||
env: {
|
||||
...process.env,
|
||||
NODE_ENV: 'development',
|
||||
CDRAGON_CACHE_DIR: cacheDir,
|
||||
MONGO_USER: mongoUser,
|
||||
MONGO_PASS: mongoPass,
|
||||
MONGO_HOST: mongoHost
|
||||
},
|
||||
stdio: 'inherit'
|
||||
});
|
||||
|
||||
patchDetector.on('close', (code) => {
|
||||
process.exit(code || 0);
|
||||
});
|
||||
@@ -20,39 +20,69 @@ async function setupDatabase() {
|
||||
|
||||
// Check if data directory exists and has files
|
||||
const dataDir = path.join(__dirname, '../data');
|
||||
const patchFile = path.join(dataDir, "patches.json");
|
||||
if(!fs.existsSync(dataDir) || !fs.existsSync(patchFile)) {
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
console.log('🚫 No data files found. Downloading latest snapshot...');
|
||||
|
||||
// Try to get latest patch version from existing data files or database
|
||||
let latestPatch = await getLatestPatchVersion();
|
||||
|
||||
// If no patch found, download snapshot
|
||||
if (!latestPatch) {
|
||||
if (!fs.existsSync(dataDir)) {
|
||||
fs.mkdirSync(dataDir, { recursive: true });
|
||||
}
|
||||
console.log('🚫 No match data found. Downloading latest snapshot...');
|
||||
await downloadAndExtractSnapshot();
|
||||
|
||||
// Try again after download
|
||||
latestPatch = await getLatestPatchVersion();
|
||||
}
|
||||
|
||||
// Get latest patch version
|
||||
const latestPatch = await getLatestPatchVersion();
|
||||
if (!latestPatch) {
|
||||
console.error('❌ Could not determine latest patch version');
|
||||
console.log('💡 Make sure you have match data files in the data directory');
|
||||
process.exit(1);
|
||||
}
|
||||
console.log(`🎯 Latest patch version: ${latestPatch}`);
|
||||
|
||||
// Check if data directory exists and has files
|
||||
// Support both old format (patch_matches.json) and new platform-specific format (patch_PLATFORM_matches.json)
|
||||
// Also support both "XX.Y" and "XX.Y.Z" patch formats in filenames
|
||||
console.log('🔍 Checking for data files...');
|
||||
const platforms = ['EUW1', 'EUN1', 'NA1', 'KR'];
|
||||
const dataFiles = [
|
||||
{ path: 'patches.json', required: true, description: 'Patches data' }
|
||||
];
|
||||
const dataFiles = [];
|
||||
|
||||
// Check for platform-specific match files
|
||||
// Files may be named with either "16.8" or "16.8.1" format
|
||||
let foundPlatformFiles = [];
|
||||
for (const platform of platforms) {
|
||||
const platformFile = `${latestPatch}_${platform}.json`;
|
||||
const fullPath = path.join(dataDir, platformFile);
|
||||
if (fs.existsSync(fullPath)) {
|
||||
// Try both formats: "16.8_PLATFORM.json" and "16.8.1_PLATFORM.json"
|
||||
const files = fs.readdirSync(dataDir);
|
||||
const matchFile = files.find(f => {
|
||||
const match = f.match(/^(\d+\.\d+(?:\.\d+)?)_([A-Z0-9]+)\.json$/);
|
||||
const patchFromName = match ? match[1].split('.').slice(0, 2).join('.') : null;
|
||||
return match && patchFromName === latestPatch && match[2] === platform;
|
||||
});
|
||||
|
||||
if (matchFile) {
|
||||
foundPlatformFiles.push(platform);
|
||||
dataFiles.push({ path: platformFile, required: false, description: `Match data for ${platform}` });
|
||||
dataFiles.push({ path: matchFile, required: false, description: `Match data for ${platform}` });
|
||||
}
|
||||
}
|
||||
|
||||
// If no platform-specific files found, look for old format
|
||||
if (foundPlatformFiles.length === 0) {
|
||||
dataFiles.push({ path: `${latestPatch}_matches.json`, required: true, description: 'Match data' });
|
||||
// Try to find any match file for this patch
|
||||
const files = fs.readdirSync(dataDir);
|
||||
const matchFile = files.find(f => {
|
||||
const match = f.match(/^(\d+\.\d+(?:\.\d+)?)(?:_matches)?\.json$/);
|
||||
const patchFromName = match ? match[1].split('.').slice(0, 2).join('.') : null;
|
||||
return match && patchFromName === latestPatch;
|
||||
});
|
||||
|
||||
if (matchFile) {
|
||||
dataFiles.push({ path: matchFile, required: true, description: 'Match data' });
|
||||
} else {
|
||||
dataFiles.push({ path: `${latestPatch}_matches.json`, required: true, description: 'Match data' });
|
||||
}
|
||||
}
|
||||
|
||||
let filesExist = true;
|
||||
@@ -91,11 +121,7 @@ async function setupDatabase() {
|
||||
// 4. Wait for MongoDB to be ready
|
||||
await waitForMongoDB();
|
||||
|
||||
// 5. Import patches data
|
||||
console.log('📦 Importing patches data...');
|
||||
await importPatchesData();
|
||||
|
||||
// 6. Check existing matches count and import if needed
|
||||
// 5. Check existing matches count and import if needed
|
||||
console.log('Checking existing matches count...');
|
||||
|
||||
// Check for platform-specific collections or fall back to old format
|
||||
@@ -129,11 +155,7 @@ async function setupDatabase() {
|
||||
}
|
||||
}
|
||||
|
||||
// 7. Fetch CDragon data for the current patch
|
||||
console.log('🎮 Fetching CDragon data...');
|
||||
await fetchCDragonData();
|
||||
|
||||
// 8. Run match collector to generate stats
|
||||
// 7. Run match collector to generate stats (this also handles CDragon caching)
|
||||
console.log('📊 Generating champion stats...');
|
||||
await generateChampionStats();
|
||||
|
||||
@@ -148,48 +170,70 @@ async function setupDatabase() {
|
||||
}
|
||||
|
||||
async function getLatestPatchVersion() {
|
||||
try {
|
||||
const filePath = path.join(__dirname, '../data/patches.json');
|
||||
if(!fs.existsSync(filePath)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Check if it's line-delimited JSON or array format
|
||||
let patchesData;
|
||||
if (fileContent.trim().startsWith('[')) {
|
||||
// Array format
|
||||
patchesData = JSON.parse(fileContent);
|
||||
if (!Array.isArray(patchesData)) {
|
||||
throw new Error('Patches data should be an array');
|
||||
}
|
||||
} else {
|
||||
// Line-delimited JSON format
|
||||
patchesData = fileContent.split('\n')
|
||||
.filter(line => line.trim() !== '')
|
||||
.map(line => JSON.parse(line));
|
||||
}
|
||||
|
||||
// Convert dates to Date objects for proper sorting
|
||||
patchesData = patchesData.map(patch => ({
|
||||
...patch,
|
||||
date: new Date(patch.date.$date || patch.date)
|
||||
}));
|
||||
|
||||
// Sort patches by date (newest first) and get the latest
|
||||
const sortedPatches = patchesData.sort((a, b) => b.date - a.date);
|
||||
const latestPatch = sortedPatches[0];
|
||||
const dataDir = path.join(__dirname, '../data');
|
||||
|
||||
// First, try to get patch from match data files (format: PATCH_PLATFORM.json or PATCH_matches.json)
|
||||
if (fs.existsSync(dataDir)) {
|
||||
const files = fs.readdirSync(dataDir);
|
||||
const patches = new Set();
|
||||
|
||||
if (!latestPatch || !latestPatch.patch) {
|
||||
throw new Error('Could not find patch version in patches data');
|
||||
for (const file of files) {
|
||||
// Match patterns like "16.8.1_EUW1.json" or "15.1_EUW1.json" or "15.1_matches.json" or "15.1.json"
|
||||
// Patch version can be either "XX.Y" or "XX.Y.Z" format
|
||||
const match = file.match(/^(\d+\.\d+(?:\.\d+)?)(?:_[A-Z0-9]+)?(?:_matches)?\.json$/);
|
||||
if (match) {
|
||||
// Normalize to "XX.Y" format (strip the third part if present)
|
||||
const patch = match[1].split('.').slice(0, 2).join('.');
|
||||
patches.add(patch);
|
||||
}
|
||||
}
|
||||
|
||||
if (patches.size > 0) {
|
||||
// Sort patches and return the latest (highest version number)
|
||||
const sortedPatches = Array.from(patches).sort((a, b) => {
|
||||
const [aMajor, aMinor] = a.split('.').map(Number);
|
||||
const [bMajor, bMinor] = b.split('.').map(Number);
|
||||
if (aMajor !== bMajor) return bMajor - aMajor;
|
||||
return bMinor - aMinor;
|
||||
});
|
||||
return sortedPatches[0];
|
||||
}
|
||||
|
||||
return latestPatch.patch;
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to get latest patch version:', error);
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Fallback: try to get from database collections
|
||||
try {
|
||||
const client = new MongoClient(getMongoUri());
|
||||
await client.connect();
|
||||
|
||||
const db = client.db('matches');
|
||||
const collections = await db.listCollections().toArray();
|
||||
const collectionNames = collections.map(c => c.name);
|
||||
|
||||
const patches = new Set();
|
||||
for (const name of collectionNames) {
|
||||
// Collection names are either "patch_platform" or just "patch"
|
||||
const patch = name.split('_')[0];
|
||||
if (patch && /^\d+\.\d+$/.test(patch)) {
|
||||
patches.add(patch);
|
||||
}
|
||||
}
|
||||
|
||||
await client.close();
|
||||
|
||||
if (patches.size > 0) {
|
||||
const sortedPatches = Array.from(patches).sort((a, b) => {
|
||||
const [aMajor, aMinor] = a.split('.').map(Number);
|
||||
const [bMajor, bMinor] = b.split('.').map(Number);
|
||||
if (aMajor !== bMajor) return bMajor - aMajor;
|
||||
return bMinor - aMinor;
|
||||
});
|
||||
return sortedPatches[0];
|
||||
}
|
||||
} catch (error) {
|
||||
// Database not available, continue with other methods
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
async function downloadAndExtractSnapshot() {
|
||||
@@ -256,83 +300,25 @@ async function waitForMongoDB() {
|
||||
}
|
||||
}
|
||||
|
||||
async function importPatchesData() {
|
||||
const client = new MongoClient(getMongoUri());
|
||||
await client.connect();
|
||||
|
||||
try {
|
||||
const filePath = path.join(__dirname, '../data/patches.json');
|
||||
const fileContent = fs.readFileSync(filePath, 'utf8');
|
||||
|
||||
// Check if it's line-delimited JSON or array format
|
||||
let patchesData;
|
||||
if (fileContent.trim().startsWith('[')) {
|
||||
// Array format
|
||||
patchesData = JSON.parse(fileContent);
|
||||
if (!Array.isArray(patchesData)) {
|
||||
throw new Error('Patches data should be an array');
|
||||
}
|
||||
} else {
|
||||
// Line-delimited JSON format
|
||||
patchesData = fileContent.split('\n')
|
||||
.filter(line => line.trim() !== '')
|
||||
.map(line => {
|
||||
const doc = JSON.parse(line);
|
||||
return convertMongoExtendedJson(doc);
|
||||
});
|
||||
}
|
||||
|
||||
// Convert any extended JSON in array format too
|
||||
if (Array.isArray(patchesData)) {
|
||||
patchesData = patchesData.map(doc => convertMongoExtendedJson(doc));
|
||||
}
|
||||
|
||||
// Sort patches by date (newest first)
|
||||
patchesData.sort((a, b) => {
|
||||
const dateA = new Date(a.date || a.date.$date || 0);
|
||||
const dateB = new Date(b.date || b.date.$date || 0);
|
||||
return dateB - dateA; // Descending order (newest first)
|
||||
});
|
||||
|
||||
const db = client.db('patches');
|
||||
const collection = db.collection('patches');
|
||||
|
||||
// Clear existing data
|
||||
await collection.deleteMany({});
|
||||
|
||||
// Insert sorted data
|
||||
const result = await collection.insertMany(patchesData);
|
||||
console.log(`✅ Imported ${result.insertedCount} patches (sorted by date)`);
|
||||
|
||||
// Create index
|
||||
await collection.createIndex({ date: -1 });
|
||||
console.log('✅ Created patches index');
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to import patches:', error);
|
||||
throw error;
|
||||
} finally {
|
||||
await client.close();
|
||||
}
|
||||
}
|
||||
|
||||
async function importMatchesData(patchVersion, foundPlatformFiles = []) {
|
||||
const dataDir = path.join(__dirname, '../data');
|
||||
const files = fs.readdirSync(dataDir);
|
||||
|
||||
try {
|
||||
// If platform-specific files were found, import each one
|
||||
if (foundPlatformFiles.length > 0) {
|
||||
for (const platform of foundPlatformFiles) {
|
||||
// Try both formats: patch_PLATFORM.json and patch_PLATFORM_matches.json
|
||||
let matchesFile = path.join(dataDir, `${patchVersion}_${platform}.json`);
|
||||
const collectionName = `${patchVersion}_${platform}`;
|
||||
// Find the actual file for this platform (could be "16.8_PLATFORM.json" or "16.8.1_PLATFORM.json")
|
||||
const matchFile = files.find(f => {
|
||||
const match = f.match(/^(\d+\.\d+(?:\.\d+)?)_([A-Z0-9]+)\.json$/);
|
||||
const patchFromName = match ? match[1].split('.').slice(0, 2).join('.') : null;
|
||||
return match && patchFromName === patchVersion && match[2] === platform;
|
||||
});
|
||||
|
||||
// Fallback to _matches.json suffix if the direct file doesn't exist
|
||||
if (!fs.existsSync(matchesFile)) {
|
||||
matchesFile = path.join(dataDir, `${patchVersion}_${platform}_matches.json`);
|
||||
}
|
||||
|
||||
if (fs.existsSync(matchesFile)) {
|
||||
if (matchFile) {
|
||||
const matchesFile = path.join(dataDir, matchFile);
|
||||
const collectionName = `${patchVersion}_${platform}`;
|
||||
console.log(`📥 Importing matches for ${platform}...`);
|
||||
execSync(
|
||||
`node ${path.join(__dirname, 'process-matches.js')} ${matchesFile} ${collectionName} 1000`,
|
||||
@@ -348,15 +334,16 @@ async function importMatchesData(patchVersion, foundPlatformFiles = []) {
|
||||
}
|
||||
} else {
|
||||
// Fall back to old format (single file without platform suffix)
|
||||
// Try both formats: patch_matches.json and patch.json
|
||||
let matchesFile = path.join(dataDir, `${patchVersion}_matches.json`);
|
||||
const collectionName = patchVersion;
|
||||
// Find any match file for this patch
|
||||
const matchFile = files.find(f => {
|
||||
const match = f.match(/^(\d+\.\d+(?:\.\d+)?)(?:_matches)?\.json$/);
|
||||
const patchFromName = match ? match[1].split('.').slice(0, 2).join('.') : null;
|
||||
return match && patchFromName === patchVersion;
|
||||
});
|
||||
|
||||
if (!fs.existsSync(matchesFile)) {
|
||||
matchesFile = path.join(dataDir, `${patchVersion}.json`);
|
||||
}
|
||||
|
||||
if (fs.existsSync(matchesFile)) {
|
||||
if (matchFile) {
|
||||
const matchesFile = path.join(dataDir, matchFile);
|
||||
const collectionName = patchVersion;
|
||||
execSync(
|
||||
`node ${path.join(__dirname, 'process-matches.js')} ${matchesFile} ${collectionName} 1000`,
|
||||
{
|
||||
@@ -404,24 +391,6 @@ async function generateChampionStats() {
|
||||
}
|
||||
}
|
||||
|
||||
async function fetchCDragonData() {
|
||||
try {
|
||||
console.log('🔄 Running CDragon fetcher...');
|
||||
|
||||
// Run the fetch-cdragon script
|
||||
const fetchCDragonPath = path.join(__dirname, 'fetch-cdragon.js');
|
||||
execSync(`node ${fetchCDragonPath}`, {
|
||||
stdio: 'inherit',
|
||||
cwd: path.join(__dirname, '..')
|
||||
});
|
||||
|
||||
console.log('✅ CDragon data fetched');
|
||||
} catch (error) {
|
||||
console.error('❌ Failed to fetch CDragon data:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function getMatchCount(patchVersion, platform = null) {
|
||||
const client = new MongoClient(getMongoUri());
|
||||
await client.connect();
|
||||
@@ -582,9 +551,6 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
case 'generate-stats':
|
||||
generateChampionStats().catch(console.error);
|
||||
break;
|
||||
case 'import-patches':
|
||||
importPatchesData().catch(console.error);
|
||||
break;
|
||||
case 'match-count':
|
||||
if (args[1]) {
|
||||
getMatchCount(args[1]).then(count => console.log(`Match count: ${count}`)).catch(console.error);
|
||||
@@ -605,7 +571,6 @@ if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
|
||||
export {
|
||||
setupDatabase,
|
||||
importPatchesData,
|
||||
importMatchesData,
|
||||
generateChampionStats,
|
||||
checkDatabaseStatus,
|
||||
|
||||
Reference in New Issue
Block a user