import { Account , AccountConstants , Game , LeaderBoardUsers , PlayerQnA , Question } from '../../projects/shared-library/src/lib/shared/model' ; import { AccountService } from '../services/account.service' ; import { GameService } from '../services/game.service' ; import { LeaderBoardService } from '../services/leaderboard.service' ; import { QuestionService } from '../services/question.service' ; import { Utils } from '../utils/utils' ; import { AccountAtomic } from '../model' ; import * as stringHash from 'string-hash' ; export class GameLeaderBoardStats { static async generateGameStats ( ) { const accountDicts = { } ; const userPromises = [ ] ; try { const games = await GameService . getCompletedGames ( ) ; const questionDict = await GameLeaderBoardStats . loadQuestionDictionary ( ) ; const questionTagDict = await GameLeaderBoardStats . loadQuestionTagDictionary ( ) ; for ( const game of games ) { for ( const userId of Object . keys ( game . stats ) ) { const account = ( accountDicts [ userId ] ) ? accountDicts [ userId ] : new AccountAtomic ( ) ; const categoryTagsObj = GameLeaderBoardStats . getGameQuestionCategoriesAndTags ( game , questionDict , userId , questionTagDict ) ; accountDicts [ userId ] = GameLeaderBoardStats . calculateAllGameUsersStat ( account , userId , game , categoryTagsObj . categoryIds , categoryTagsObj . tagIds ) ; } } for ( const userId of Object . keys ( accountDicts ) ) { const account = accountDicts [ userId ] ; account . id = userId ; userPromises . push ( AccountService . setAccount ( { ... account } ) ) ; } return await Promise . all ( userPromises ) ; } catch ( error ) { return Utils . throwError ( error ) ; } } static async loadQuestionDictionary ( ) { const questionDict = { } ; try { const questions = await QuestionService . getAllQuestions ( ) ; for ( const question of questions ) { if ( question . categoryIds . length > 0 ) { questionDict [ question . id ] = question . categoryIds ; } } return questionDict ; } catch ( error ) { return Utils . throwError ( error ) ; } } static async loadQuestionTagDictionary ( ) { const questionDict = { } ; try { const questions = await QuestionService . getAllQuestions ( ) ; for ( const question of questions ) { if ( question . categoryIds . length > 0 ) { questionDict [ question . id ] = question . tags ; } } return questionDict ; } catch ( error ) { return Utils . throwError ( error ) ; } } private static getGameQuestionCategoriesAndTags ( game , questionDict , userId , questionTagDict ) { const questionCategoriesTags = { categoryIds : [ ] , tagIds : [ ] } ; const questions = game . playerQnAs . filter ( playerQ => playerQ . playerId === userId && playerQ . answerCorrect === true ) ; for ( const question of questions ) { const categoryIds = questionDict [ question . questionId ] ; const tagsIds = questionTagDict [ question . questionId ] ; if ( categoryIds ) { for ( const categoryId of categoryIds ) { if ( categoryId ) { questionCategoriesTags . categoryIds . push ( categoryId ) ; } } } if ( tagsIds ) { for ( const tagId of tagsIds ) { if ( tagId ) { questionCategoriesTags . tagIds . push ( tagId ) ; } } } } return questionCategoriesTags ; } private static calculateAllGameUsersStat ( account , userId , game , categoryIds , tagIds ) { return AccountService . calculateAccountStat ( account , game , categoryIds , userId , true , tagIds ) ; } static async getGameUsers ( game ) { const userPromises = [ ] ; let categoryTagObj = { categoryIds : [ ] , tagIds : [ ] } ; try { for ( const userId of Object . keys ( game . stats ) ) { categoryTagObj = await GameLeaderBoardStats . getUserQuestionCategoryAndTagIds ( game . playerQnAs , userId ) ; userPromises . push ( GameLeaderBoardStats . calculateUserStat ( userId , game , categoryTagObj . categoryIds , categoryTagObj . tagIds ) ) ; } return await Promise . all ( userPromises ) ; } catch ( error ) { return Utils . throwError ( error ) ; } } private static async getUserQuestionCategoryAndTagIds ( gameQuestions , userId ) { try { const categoryTagObj = { categoryIds : [ ] , tagIds : [ ] } ; const questionPromises = [ ] ; gameQuestions = gameQuestions . filter ( gameQuestion => gameQuestion . playerId === userId && gameQuestion . answerCorrect === true ) ; for ( const gameQuestion of gameQuestions ) { questionPromises . push ( QuestionService . getQuestionById ( gameQuestion . questionId ) ) ; } const questionResults = await Promise . all ( questionPromises ) ; for ( const questionResult of questionResults ) { for ( const categoryId of questionResult . categoryIds ) { if ( categoryId ) { categoryTagObj . categoryIds . push ( categoryId ) ; } } for ( const tagId of questionResult . tags ) { if ( tagId ) { categoryTagObj . tagIds . push ( tagId ) ; } } } return categoryTagObj ; } catch ( error ) { return Utils . throwError ( error ) ; } } private static async calculateUserStat ( userId , game , categoryIds , tagIds ) { try { const account = await AccountService . getAccountById ( userId ) ; if ( account && account . id ) { return await AccountService . updateAccountData ( AccountService . calculateAccountStat ( account , game , categoryIds , userId , false , tagIds ) ) ; } return AccountConstants . ACCOUNT_DOES_NOT_EXIST ; } catch ( error ) { return Utils . throwError ( error ) ; } } static async calculateGameLeaderBoardStat ( ) { try { let leaderBoardDict = { } ; const accounts = await AccountService . getAccounts ( ) ; for ( const account of accounts ) { leaderBoardDict = await LeaderBoardService . calculateLeaderBoardStats ( account , leaderBoardDict ) ; } return await GameLeaderBoardStats . setLeaderBoardStat ( leaderBoardDict ) ; } catch ( error ) { return Utils . throwError ( error ) ; } } static async setLeaderBoardStat ( leaderBoardDict ) { try { const promises = [ ] ; const category = await LeaderBoardService . getAllCategories ( ) ; const categoryIds = [ ] ; for ( const data of category ) { categoryIds . push ( data . id . toString ( 10 ) ) ; } for ( const id of Object . keys ( leaderBoardDict ) ) { let idHash = id ; if ( categoryIds . indexOf ( id ) < 0 ) { idHash = await stringHash ( id ) ; } const leaderBoardUsers = leaderBoardDict [ id ] ; for ( const userData of leaderBoardUsers . users ) { promises . push ( LeaderBoardService . setLeaderBoardStatsById ( idHash , { ... userData } ) ) ; } promises . push ( LeaderBoardService . setLeaderBoardStatsData ( id , idHash ) ) ; } return await Promise . all ( promises ) ; } catch ( error ) { return Utils . throwError ( error ) ; } } }