import fs from 'fs' import Excel from './excel' import Draw from '../models/draw' import MatchList from '../models/matchList' import PlayerList from '../models/playerList' import moment from 'moment' import { normalize } from './helpers' import { session } from '../index' function initials (player) { const fnInitials = player.firstName .split('-') .map(element=>element .split(' ') .map(element => element[0]+'.') .join(' ') ).join('-') const fnInitialsDP = player.firstNameDP .split('-') .map(element=>element .split(' ') .map(element => element[0]+'.') .join(' ') ).join('-') return player.doubles ? `${player.name} ${fnInitials} / ${player.nameDP} ${fnInitialsDP}` : `${name} ${fnInitials}` } async function getDraws (req, res) { try { const draws = await Draw.find() return res.json(draws) } catch (error) { return res.status(400).json({ msg: error.toString() }) } } async function getDraw (req, res) { try { const key = req.query.drawId ? { _id: req.query.drawId } : {} const draw = await MatchList.findOne(key).sort({ imported: -1 }) return res.json(draw) } catch (error) { return res.status(400).json({ msg: error.toString() }) } } async function downloadDraw (req, res) { try { const { drawId } = req.params const filename = `DisplayDraw-${drawId}-${moment().format('YYYYMMDDTHHmmss')}.xls` const drawFile = fs.createWriteStream(`swisstennis_files/${filename}`) const drawDisplay = await session.get(`https://comp.swisstennis.ch/advantage/servlet/DisplayDraw.xls?eventId=${drawId}&lang=D`, {stream: true}) await drawDisplay.pipe(drawFile) const streamDone = new Promise((resolve, reject) => { drawFile.on('finish', resolve) drawFile.on('error', reject) }) await streamDone const stats = fs.statSync(`swisstennis_files/${filename}`) return res.json({ filename, size: stats.size, mtime: stats.mtime }) } catch (error) { return res.status(400).json({ msg: error.toString() }) } } async function parseDraw (req,res) { try { console.log('Parsing file', req.params.filename) const filePath = `swisstennis_files/${req.params.filename}` const dateString = req.params.filename.match(/(\d{4}\d{2}\d{2}T\d{2}\d{2}\d{2})/)[1] const fileDate = moment(dateString) const stat = fs.statSync(filePath) const fileNewer = await Draw.find({ imported: { $gte: fileDate } }) if (fileNewer.length) { throw Error('File has to be newer.') } console.log('About to read the draw.') const worksheets = await Excel.readWorkbook(`swisstennis_files/${req.params.filename}`) const worksheet = worksheets.Tableaux if (worksheet[0].length !== 1 || worksheet[1].length !== 1 || worksheet[2].length !== 1 || worksheet[3].length !== 0) { throw Error(`Wrong file structure.`) } const category = normalize(worksheet[2][0]) const doubles = !!category.match(/DM.*|[MW]D.*/) const drawSize = ( worksheet.length - 4 + 1 ) / 2 // 4 header lines, 1 empty line between each player (n-1) const draw = worksheet.slice(4) const rounds = Math.log2(drawSize) const playerList = await PlayerList.findOne().sort({imported: -1}).populate('players') const players = playerList.players.filter(player => player.category === category) const matchList = await MatchList.findOne().sort({imported: -1}).populate('matches') const matches = matchList.matches const drawMatches = [] for (var round = 0; round < rounds; round += 1) { const matchPositionOffset = Math.pow(2, round) const playerOffset = 2 * matchPositionOffset const roundOffset = playerOffset/2 - 1 const matchIncrement = 2 * playerOffset for (var seq = 0; seq < drawSize / Math.pow(2, round + 1); seq += 1) { const matchPosition = roundOffset + seq * matchIncrement // Data from spreadsheet cells const player1String = normalize(draw[matchPosition][round]) const player2String = normalize(draw[matchPosition + playerOffset][round]) const winnerString = normalize(draw[matchPositionOffset + matchPosition][round + 1]) const timePlaceResultString = normalize(draw[matchPositionOffset + matchPosition + 1][round + 1]) const drawPlayerRegex = /^(?:\((\d+)\))?\s*\(([RN]\d\s?(?:\d+)?|NC)\) (.+)$/ const drawDoubleRegex = /^(?:\((\d+)\))?\s*\(([RN]\d\s?(?:\d+)?|NC)\/([RN]\d\s?(?:\d+)?|NC)\) ([^\/]+)\s*\/\s*([^\/]+)$/ const player1Match = doubles ? player1String.match(drawDoubleRegex) : player1String.match(drawDoubleRegex) const player2Match = doubles ? player2String.match(drawDoubleRegex) : player2String.match(drawDoubleRegex) console.log(player1Match, player2Match) const player1 = (round === 0) ? players.find(player => player1Match && (category === player.category) && (player1Match[3] === player.fullName)) : players.find(player => (category === player.category) && (player1String === initials(player))) const player2 = (round === 0) ? players.find(player => player2Match && (category === player.category) && (player2Match[3] === player.fullName)) : players.find(player => (category === player.category) && (player2String === initials(player))) const timePlace = timePlaceResultString.match(/^(\d{2}\/\d{2}\/\d{2})?\s+(\d{2}:\d{2})?\s*\(([^\)]+)\)?$/) const result = normalize(draw[matchPosition + playerOffset/2 + 1][round + 1]).match(/^((?:WO)?\s*(?:\d+\/\d+\s*)*)$/) const winner = winnerString const idString = (player1 && player2) const match = { created: new Date(), idString: '', category, place: timePlace && timePlace[3] || null, date: timePlace && timePlace[1] && timePlace[2] && moment(`${timePlace[1]} ${timePlace[2]}`, 'DD/MM/YY HH:mm') || null, round: round + 1, player1: player1 && player1._id || null, player2: player2 && player2._id || null, winner: winner || null, result: result && result[0] || null, doubles } drawMatches.push(match) } } console.log('matches:', drawMatches.length) return res.json({ drawMatches }) } catch (error) { res.status(400).json({ msg: error.toString() }) } } async function deleteDraw (req, res) { try { const { drawId } = req.params if (!drawId) { throw Error('No drawId given.') } const draw = await MatchList.findOne({ _id: drawId }) if (!draw) { throw Error('Draw not found.') } draw.remove() return res.json({ _id: drawId }) } catch (error) { return res.status(400).json({ msg: error.toString() }) } } export default { getDraws, getDraw, downloadDraw, parseDraw, deleteDraw }