/
MashkoA
/
web-nodejs
Обзор
Документация
Войти
/
MashkoA
/
web-nodejs
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
backend/src/services/lab8/task2.service.js
334 строки
10 KB
vSUS1w8OErscaPzljeOMKk86GKFCBmeQUlgjKJCmRenysib5Ll
lab12 obn
29 май 2026, 08:10
29 май 2026, 08:10
c6dc639
Код
Авторство
О чём код?
// backend/src/services/lab8/task2.service.js import fs from 'fs/promises'; import path from 'path'; import { fileURLToPath } from 'url'; const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // Пути к файлам const dataDir = path.join(__dirname, '..', '..', '..', 'data', 'lab8', 'task2'); const cupFilePath = path.join(dataDir, 'cup.txt'); const groupsFilePath = path.join(dataDir, 'groups.json'); const stadiumsFilePath = path.join(dataDir, 'stadium.json'); const cupFileUrl = 'https://raw.githubusercontent.com/openfootball/worldcup/master/2022--qatar/cup.txt'; class Task2Service { /** * Загружает файл с результатами матчей */ async downloadCupFile() { try { await fs.mkdir(dataDir, { recursive: true }); const response = await fetch(cupFileUrl); if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`); } const data = await response.text(); await fs.writeFile(cupFilePath, data, 'utf8'); console.log('Файл успешно загружен, размер:', data.length, 'символов'); return true; } catch (error) { console.error('Ошибка при загрузке файла:', error.message); return false; } } /** * Читает и парсит файл с результатами матчей */ async parseCupFile() { try { const data = await fs.readFile(cupFilePath, 'utf8'); const lines = data.split('\n').filter(line => line.trim()); console.log('Всего строк в файле:', lines.length); const groups = {}; const stadiums = {}; let currentGroup = null; for (const line of lines) { const trimmedLine = line.trim(); // Определяем группу if (trimmedLine.startsWith('Group')) { currentGroup = trimmedLine.split(' ')[1]; groups[currentGroup] = { group: currentGroup, teams: {}, matches: [] }; console.log('Найдена группа:', currentGroup); continue; } // Пропускаем пустые строки и заголовки if (!trimmedLine || trimmedLine.includes('===') || !currentGroup || trimmedLine.startsWith('Matchday') || trimmedLine.includes('World Cup')) { continue; } // Парсим матч const match = this.parseMatchLine(trimmedLine, currentGroup); if (match) { console.log('Найден матч:', match.team1, 'vs', match.team2); groups[currentGroup].matches.push(match); // Обновляем статистику команд this.updateTeamStats(groups[currentGroup].teams, match); // Обновляем статистику стадионов this.updateStadiumStats(stadiums, match); } } console.log('Всего групп обработано:', Object.keys(groups).length); console.log('Всего стадионов найдено:', Object.keys(stadiums).length); return { groups, stadiums }; } catch (error) { if (error.code === 'ENOENT') { throw new Error('Файл с результатами матчей не найден. Сначала загрузите данные.'); } throw error; } } /** * Парсит строку с информацией о матче */ parseMatchLine(line, group) { // Упрощенное регулярное выражение для формата: // "(1) Sun Nov/20 19:00 Qatar 0-2 (0-2) Ecuador @ Al Bayt Stadium, Al Khor" const matchRegex = /^\(\d+\)\s+(\w+\s+\w+\/\d+\s+\d+:\d+)\s+([^@]+)@\s+([^,]+),/; const match = line.match(matchRegex); if (!match) { console.log('Не удалось распарсить строку:', line); return null; } const [, date, teamsPart, stadium] = match; // Парсим команды и счет const teamsRegex = /([a-zA-Z\s]+)\s+(\d+)-(\d+)\s+\([^)]+\)\s+([a-zA-Z\s]+)/; const teamsMatch = teamsPart.trim().match(teamsRegex); if (!teamsMatch) { console.log('Не удалось распарсить команды и счет:', teamsPart); return null; } const [, team1, score1, score2, team2] = teamsMatch; return { date: date.trim(), stadium: stadium.trim(), team1: team1.trim(), team2: team2.trim(), score1: parseInt(score1), score2: parseInt(score2), group: group }; } /** * Обновляет статистику команд */ updateTeamStats(teams, match) { const { team1, team2, score1, score2 } = match; // Инициализируем команды если их нет if (!teams[team1]) { teams[team1] = this.initTeamStats(team1); } if (!teams[team2]) { teams[team2] = this.initTeamStats(team2); } // Обновляем статистику для команды 1 teams[team1].played++; teams[team1].goalsFor += score1; teams[team1].goalsAgainst += score2; teams[team1].goalDifference = teams[team1].goalsFor - teams[team1].goalsAgainst; // Обновляем статистику для команды 2 teams[team2].played++; teams[team2].goalsFor += score2; teams[team2].goalsAgainst += score1; teams[team2].goalDifference = teams[team2].goalsFor - teams[team2].goalsAgainst; // Определяем результат матча if (score1 > score2) { teams[team1].won++; teams[team1].points += 3; teams[team2].lost++; } else if (score1 < score2) { teams[team2].won++; teams[team2].points += 3; teams[team1].lost++; } else { teams[team1].drawn++; teams[team2].drawn++; teams[team1].points += 1; teams[team2].points += 1; } } /** * Инициализирует статистику команды */ initTeamStats(teamName) { return { team: teamName, played: 0, won: 0, drawn: 0, lost: 0, goalsFor: 0, goalsAgainst: 0, goalDifference: 0, points: 0 }; } /** * Обновляет статистику стадионов */ updateStadiumStats(stadiums, match) { const { stadium, team1, team2, score1, score2, date } = match; if (!stadiums[stadium]) { stadiums[stadium] = { stadium: stadium, matches: [] }; } stadiums[stadium].matches.push({ date: date, team1: team1, team2: team2, score: `${score1}-${score2}`, group: match.group }); } /** * Сохраняет данные в JSON файлы */ async saveProcessedData(groups, stadiums) { // Преобразуем объекты в массивы и сортируем const groupsArray = Object.values(groups).map(group => ({ ...group, teams: Object.values(group.teams).sort((a, b) => b.points - a.points || b.goalDifference - a.goalDifference) })); const stadiumsArray = Object.values(stadiums); await fs.writeFile(groupsFilePath, JSON.stringify(groupsArray, null, 2), 'utf8'); await fs.writeFile(stadiumsFilePath, JSON.stringify(stadiumsArray, null, 2), 'utf8'); const totalMatches = groupsArray.reduce((total, group) => total + group.matches.length, 0); console.log('Сохранено данных:', { groups: groupsArray.length, stadiums: stadiumsArray.length, matches: totalMatches }); return { groups: groupsArray.length, stadiums: stadiumsArray.length, matches: totalMatches }; } /** * Загружает данные из сохраненных JSON файлов */ async loadProcessedData() { try { const groupsData = await fs.readFile(groupsFilePath, 'utf8'); const stadiumsData = await fs.readFile(stadiumsFilePath, 'utf8'); return { groups: JSON.parse(groupsData), stadiums: JSON.parse(stadiumsData) }; } catch (error) { if (error.code === 'ENOENT') { throw new Error('Обработанные данные не найдены. Сначала обработайте данные матчей.'); } throw error; } } /** * Основной метод обработки данных */ async processWorldCupData() { // Проверяем, есть ли уже загруженный файл try { await fs.access(cupFilePath); console.log('Файл уже существует, используем локальную копию'); } catch (error) { // Файла нет, загружаем console.log('Файл не найден, начинаем загрузку...'); const downloaded = await this.downloadCupFile(); if (!downloaded) { throw new Error('Не удалось загрузить файл с результатами матчей'); } } // Парсим данные console.log('Начинаем парсинг данных...'); const { groups, stadiums } = await this.parseCupFile(); // Сохраняем результаты console.log('Сохраняем обработанные данные...'); const stats = await this.saveProcessedData(groups, stadiums); return { success: true, message: 'Данные успешно обработаны и сохранены', stats: stats }; } /** * Получает данные по группам */ async getGroupsData() { const data = await this.loadProcessedData(); return data.groups; } /** * Получает данные по стадионам */ async getStadiumsData() { const data = await this.loadProcessedData(); return data.stadiums; } /** * Получает конкретную группу */ async getGroup(groupName) { const groups = await this.getGroupsData(); return groups.find(group => group.group === groupName); } /** * Получает конкретный стадион */ async getStadium(stadiumName) { const stadiums = await this.getStadiumsData(); return stadiums.find(stadium => stadium.stadium === stadiumName); } } export default new Task2Service();