import _ from 'lodash' ; import moment from 'moment-timezone' ; import { EventEmitter } from 'events' ; import log from '../util/Logger' ; import NI from '../util/NetworkInterface' ; import * as queries from '../scripts/setQueries' ; import { IGGSet , IGGSetData , IGGSetOptions , IGGSetDataFull , IGGSetSlotAttendeeData , IGGSetSlotEntrantData } from '../interfaces/IGGSet' ; import { IPlayerLite } from '../interfaces/IPlayerLite' ; import { IGame , IGameDataFull } from '../interfaces/IGame' ; import { IAttendee } from '../interfaces/IAttendee' ; import { IEntrant } from '../interfaces/IEntrant' ; import { Game } from './Game' ; import { Attendee } from './Attendee' ; import { Entrant } from './Entrant' ; import { PlayerLite } from './PlayerLite' ; const DISPLAY_SCORE_REGEX = new RegExp ( /^([\S\s]*) ([0-9]{1,3}) - ([\S\s]*) ([0-9]{1,3})$/ ) ; export class GGSet extends EventEmitter implements IGGSet { public static parseDisplayScore ( displayScore ) { const parsed = DISPLAY_SCORE_REGEX . exec ( displayScore ) ; let tag1 , score1 , tag2 , score2 ; if ( parsed ) { tag1 = parsed [ 1 ] ; score1 = + parsed [ 2 ] ; tag2 = parsed [ 3 ] ; score2 = + parsed [ 4 ] ; } return { tag1 : tag1 || null , tag2 : tag2 || null , score1 : score1 || 0 , score2 : score2 || 0 } ; } public static async get ( id ) { log . info ( 'Getting set with id %s' , id ) ; const data = await NI . query ( queries . set , { id : id . toString ( ) } ) ; return GGSet . parseFull ( data ) ; } public static parse ( data ) { const displayScoreParsed = GGSet . parseDisplayScore ( data . displayScore ! ) ; const p1 = PlayerLite . parse ( displayScoreParsed . tag1 , data . slots [ 0 ] ) ; const p2 = PlayerLite . parse ( displayScoreParsed . tag2 , data . slots [ 1 ] ) ; return new GGSet ( + data . id , data . eventId , data . phaseGroupId , data . displayScore , data . fullRoundText , data . round , data . startedAt , data . completedAt , data . winnerId , data . totalGames , data . state , p1 , p2 , displayScoreParsed . score1 , displayScoreParsed . score2 ) ; } public static parseFull ( data ) { return GGSet . parse ( data . set ) ; } public static filterOutDQs ( sets ) { log . debug ( 'GGSet.filterOutDQs called' ) ; const displayScores = sets . map ( set => set . getDisplayScore ( ) ) ; return displayScores . includes ( 'DQ' ) ? sets . filter ( set => set . getDisplayScore ( ) !== 'DQ' ) : sets ; } public static filterOutByes ( sets ) { log . debug ( 'GGSet.filterOutByes called' ) ; const displayScores = sets . map ( set => set . getDisplayScore ( ) ) ; return displayScores . includes ( 'BYE' ) ? sets . filter ( set => set . getDisplayScore ( ) !== 'BYE' ) : sets ; } public static filterOutResets ( sets ) { log . debug ( 'GGSet.filterOutResets called' ) ; const fullRoundTexts = sets . map ( set => set . getFullRoundText ( ) ) ; return fullRoundTexts . includes ( 'Grand Final Reset' ) ? sets . filter ( set => set . getFullRoundText ( ) !== 'Grand Final Reset' ) : sets ; } public static filterForCompleteSets ( sets ) { log . debug ( 'GGSet.filterForCompleteSets called' ) ; return sets . filter ( set => set . getIsComplete ( ) ) ; } public static filterForIncompleteSets ( sets ) { log . debug ( 'GGSet.filterForCompleteSets called' ) ; return sets . filter ( set => ! set . getIsComplete ( ) ) ; } public static filterForXMinutesBack ( sets , minutesBack ) { log . debug ( 'GGSet.filterForCompleteSets called' ) ; const now = moment ( ) ; const filtered = sets . filter ( set => { const then = moment ( set . getCompletedAt ( ) as Date ) ; const diff = moment . duration ( now . diff ( then ) ) ; const diffMinutes = diff . minutes ( ) ; if ( diff . hours ( ) > 0 || diff . days ( ) > 0 || diff . months ( ) > 0 || diff . years ( ) > 0 ) return false ; else return diffMinutes <= minutesBack && diffMinutes >= 0 && set . getIsComplete ( ) ; } ) ; return filtered ; } public static getDefaultSetOptions ( ) { return { page : null , perPage : null , sortBy : null , filters : null } ; } public id : number ; public eventId : number | null ; public phaseGroupId : number | null ; public displayScore : string | null ; public fullRoundText : string | null ; public round : number | null ; public startedAt : number | null ; public completedAt : number | null ; public winnerId : number | null ; public totalGames : number | null ; public state : number | null ; public player1 : IPlayerLite ; public player2 : IPlayerLite ; public score1 : number | null ; public score2 : number | null ; constructor ( id , eventId , phaseGroupId , displayScore , fullRoundText , round , startedAt , completedAt , winnerId , totalGames , state , player1 , player2 , score1 , score2 ) { super ( ) ; this . id = id ; this . eventId = eventId ; this . phaseGroupId = phaseGroupId ; this . displayScore = displayScore ; this . fullRoundText = fullRoundText ; this . round = round ; this . startedAt = startedAt ; this . completedAt = completedAt ; this . winnerId = winnerId ; this . totalGames = totalGames ; this . state = state ; this . player1 = player1 ; this . player2 = player2 ; this . score1 = score1 ; this . score2 = score2 ; } public getId ( ) { return this . id ; } public getEventId ( ) { return this . eventId ; } public getPhaseGroupId ( ) { return this . phaseGroupId ; } public getDisplayScore ( ) { return this . displayScore ; } public getFullRoundText ( ) { return this . fullRoundText ; } public getRound ( ) { return this . round ; } public getState ( ) { return this . state ; } public getPlayer1 ( ) { return this . player1 ; } public getPlayer1Tag ( ) { return this . player1 . tag ; } public getPlayer1AttendeeIds ( ) { return this . player1 . attendeeIds ; } public getPlayer1PlayerId ( ) { return this . player1 . entrantId ; } public getPlayer2 ( ) { return this . player2 ; } public getPlayer2Tag ( ) { return this . player2 . tag ; } public getPlayer2AttendeeIds ( ) { return this . player2 . attendeeIds ; } public getPlayer2PlayerId ( ) { return this . player2 . entrantId ; } public getStartedAtTimestamp ( ) { return this . startedAt ; } public getCompletedAtTimestamp ( ) { return this . completedAt ; } public getStartedAt ( ) { if ( this . startedAt ) return moment . unix ( this . startedAt ) . toDate ( ) ; else return null ; } public getCompletedAt ( ) { if ( this . completedAt ) return moment . unix ( this . completedAt ) . toDate ( ) ; else return null ; } public getWinnerId ( ) { return this . winnerId ? this . winnerId : null ; } public getLoserId ( ) { switch ( this . winnerId ) { case this . player1 . entrantId : return this . player2 . entrantId ? this . player2 . entrantId : null ; case this . player2 . entrantId : return this . player1 . entrantId ? this . player1 . entrantId : null ; default : return null ; } } public getIsComplete ( ) { return this . completedAt ? true : false ; } public getCompletedTime ( ) { if ( this . completedAt ) return moment . unix ( this . completedAt ) . toDate ( ) ; else return null ; } public getPlayer1Score ( ) { if ( this . score1 ) return this . score1 ; else return 0 ; } public getPlayer2Score ( ) { if ( this . score2 ) return this . score2 ; else return 0 ; } public getWinner ( ) { if ( this . winnerId && this . player2 . entrantId && this . player1 . entrantId ) switch ( this . winnerId ) { case this . player1 . entrantId : return this . player1 ; case this . player2 . entrantId : return this . player2 ; default : throw new Error ( `Winner ID ${ this . winnerId } does not match either player ID: 
					[${ [ this . player1 . entrantId , this . player2 . entrantId ] . join ( ',' ) }]` ) ; } else throw new Error ( `Set (${ this . id }) must be complete to get the Winning Player` ) ; } public getLoser ( ) { if ( this . winnerId && this . player1 . entrantId && this . player2 . entrantId ) switch ( this . winnerId ) { case this . player1 . entrantId : return this . player2 ; case this . player2 . entrantId : return this . player1 ; default : throw new Error ( `Loser ID does not match either player ID: [${ [ this . player1 . entrantId , this . player2 . entrantId ] . join ( ',' ) }]` ) ; } else throw new Error ( `Set (${ this . id }) must be complete to get the Losing Player` ) ; } public getBestOfCount ( ) { return this . totalGames || 0 ; } public getWinnerScore ( ) { if ( ! this . completedAt ) throw new Error ( 'Cannot get winner score of incomplete set' ) ; else if ( this . score1 == null || this . score2 == null ) { if ( this . score1 == null ) return this . score2 ! ; else return this . score2 ! ; } else return this . score1 > this . score2 ? this . score1 : this . score2 ; } public getLoserScore ( ) { if ( ! this . completedAt ) throw new Error ( 'Cannot get loser score of incomplete set' ) ; else if ( this . score1 == null || this . score2 == null ) return 0 ; else return this . score1 < this . score2 ? this . score1 : this . score2 ; } public async getGames ( ) { log . info ( 'Gettings Games for set (%s)' , this . id ) ; const data = await NI . query ( queries . games , { id : this . id } ) ; return Game . parseFull ( data ) ; } public async getAttendees ( ) { log . info ( 'Getting Attendees who participated in Set [%s]' , this . id ) ; const data = await NI . query ( queries . attendees , { id : this . id } ) ; const entrants = data . set . slots . map ( slot => slot . entrant ) . filter ( entrant => entrant != null ) ; const participants = _ . flatten ( entrants . map ( entrant => entrant ! . participants ) ) . filter ( participant => participant != null ) ; const attendees = participants . map ( participant => Attendee . parse ( participant ! ) ) ; return attendees ; } public async getEntrants ( ) { log . info ( 'Getting Entrants who participated in Set [%s]' , this . id ) ; const data = await NI . query ( queries . entrants , { id : this . id } ) ; const entrantData = data . set . slots . map ( slot => slot . entrant ) . filter ( entrant => entrant != null ) ; const entrants = entrantData . map ( entrant => Entrant . parse ( entrant ! ) ) ; return entrants ; } }