def addPlayer(playerID, GamerTag, Joined, missions): now = "%s" % datetime.datetime.now() conn = connectToSource() cursor = conn.cursor() query = sql.SQL("""select missions from players where playerID = %s""") playerneedsUpdate = False try: results = cursor.fetchone() if results[0] != missions: playerneedsUpdate = True except Exception as e: playerneedsUpdate = True query = sql.SQL("""insert into Players (PlayerID,GamerTag,Joined,Missions,firstsummaryupdate,lastsummaryupdate) VALUES (%s,%s,%s,%s,%s,%s) ON CONFLICT (PlayerID) DO UPDATE SET Missions = %s, lastsummaryupdate = %s """) data = (playerID, GamerTag, Joined, missions, now, now, missions, now) try: cursor.execute(query, data) DBG(" DBG: SQLHelper.AddPlayer - Added new player %s" % playerID, 3) except Exception as e: DBG("Failed to UPSERT player %s because %s" % (playerID, e), 2) conn.commit() closeConnection() return playerneedsUpdate
def manualTargetSummary(rootID): ID = rootID.split('-') if len(ID) < 3: DBG("ERROR, malform user ID, could not split. Aborting", 2) return player = fetchPlayer_root('', ID[0], ID[1], ID[2]) if player == {}: DBG("ManualTargetSummary failed! Aborting", 1) return DBG("Manual update of player sumary complete", 1) addPlayer(rootID, player["centre"][0]["codename"], player["centre"][0]["joined"], player["centre"][0]["missions"]) _parseCentresAndAdd(player["centre"], rootID) return player
def getConfigString(string): global config if config == {}: getConfig() if string in config: return config[string] DBG("CONFIG key ['%s'] not found" % string, 2)
def executeQueryIndividual(initTargetID): targetID = findPlayer(initTargetID) if targetID == "0-0-0": DBG("Unable to find a player with ID or name [%s]" % initTargetID, 2) return recentGames(targetID) blobs(targetID) PlaysWhen(targetID) rarestAchievement(targetID) recentAchievement(targetID) placesVisited(targetID)
def _parseCentresAndAdd(centres, playerID): for centre in centres: summaryValue = 0 try: for summary in centre['summary']: if summary[0] == 'Standard': summaryValue = summary[3] break except Exception as e: DBG("ERROR: FetchPlayerUpdatesAndNewPlayers._parseCentresAndAdd failed to find average score for player %s" % (playerID, )) addPlayerArena(playerID, centre['name'], centre['missions'], centre["skillLevelNum"], summaryValue)
def fetchAllAchievements(targetIDs, jobID=None): conn = connectToSource() cursor = conn.cursor() totalToUpdate = len(targetIDs) offset = 0 if jobID == None: jobID = jobStart("Fetch achievements, all known players", 0, "FetchAchievements.fetchAllAchievements", None) startTime = datetime.datetime.now() else: query = """select ID, started,lastheartbeat,resumeindex, methodname from jobslist where finished is null and ID = %s and methodname = 'FetchAchievements.executeFetchAchievements' order by started desc""" cursor.execute(query, (jobID, )) results = cursor.fetchone() if results is None: DBG( "Could not find valid achievement job for ID [%s] , aborting!" % jobID, 1) return if results[2] is not None: startTime = results[2] else: startTime = results[1] if results[3] is not None: offset = results[3] playerCounter = offset totalPlayerCount = len(targetIDs) lastHeartbeat = startTime for ID in targetIDs: __heartbeat(jobID, lastHeartbeat, playerCounter, startTime, totalPlayerCount, ID) fetchIndividualsAchievements(ID) playerCounter = playerCounter + 1 jobEnd(jobID) endTime = datetime.datetime.now() f = open("Stats.txt", "a+") f.write( "Queried {0} players' achievements, operation completed after {1}. \t\n" .format(len(targetIDs), endTime - startTime)) f.close() closeConnection()
def addPlayerAchievementScore(playerID, score): conn = connectToSource() cursor = conn.cursor() query = "select playerID from players where playerID = %s " data = (playerID, ) cursor.execute(query, data) if cursor.fetchone() == None: DBG( "SQLHelper.addPlayerAchievementScore didn't find the player, could not update score", 2) else: #print ("SQLHelper.addPlayerAchievementScore found the player, updating their achievement score") query = "update players set AchievementScore = ? where playerID = ?" cursor.execute(query, (score, playerID)) conn.commit() closeConnection()
def getTop5PlayersRoster(startDate, endDate, ArenaName): conn = connectToSource() cursor = conn.cursor() query = """with AverageScores as ( SELECT Players.PlayerID, avg(Score) as averageScore FROM Participation inner join Players on Participation.PlayerID = Players.PlayerID inner join Games on Participation.GameUUID = Games.GameUUID where GameTimestamp >= %s and GameTimeStamp < %s and games.ArenaName = %s and ( Games.GameName in ('Team','3 Teams','4 Teams', 'Colour Ranked','Individual') or Games.GameName in ('Standard - Solo', 'Standard - Team','Standard [3 Team] (10)','Standard [3 Team] (15)','Standard 2 Team', 'Standard 3 Team','Standard 4 Team','Standard Individual','Standard Multi team','- Standard [2 Team] (15))') ) group by Players.PlayerID ), StarQuality as ( SELECT playerID, gamerTag, avg(starsforgame) as avgQualityPerGame, count(*) as gamesPlayed from public."participationWithStars" where GameTimestamp >= %s and GameTimeStamp < %s and ArenaName = %s group by 1,2 ), GoldenTop3 as ( select PlayerID, ROW_NUMBER() over (order by avgQualityPerGame desc) as playerRank from StarQuality where StarQuality.gamesPlayed >= 3 order by AvgQualityPerGame desc limit 3 ), BestScorer as ( SELECT PlayerID --, GamerTag, round(AverageOpponents,2) as AverageOpponents, gamesPlayed, round(AverageRank,2) as AverageRank, --round((AverageOpponents * 1/(AverageRank/AverageOpponents)),2) as AvgQualityPerGame, --round((AverageOpponents * gamesPlayed * 1/(AverageRank/AverageOpponents)),2) as TotalQualityScore, averageScore, AchievementScore from AverageScores where PlayerID not in (select PlayerID from GoldenTop3) order by averageScore desc limit 1 ), Achievers as ( select playerID, count(*) achievements from PlayerAchievement pa join AllAchievements aa on aa.AchID = pa.AchID where achievedDate is not null and aa.ArenaName = %s group by playerID ), BestAchiever as( SELECT Ach.PlayerID --GamerTag, round(AverageOpponents,2) as AverageOpponents, gamesPlayed, round(AverageRank,2) as AverageRank, --round((AverageOpponents * 1/(AverageRank/AverageOpponents)),2) as AvgQualityPerGame, --round((AverageOpponents * gamesPlayed * 1/(AverageRank/AverageOpponents)),2) as TotalQualityScore, averageScore, AchievementScore from Achievers ach where PlayerID not in (select PlayerID from GoldenTop3) and PlayerID not in (select PlayerID from BestScorer) order by achievements desc limit 1 ) select p.PlayerID , GamerTag, playerRank, 'Top3' as source from GoldenTop3 p join Players pl on pl.PlayerID = p.PlayerID union select p.PlayerID , GamerTag, 4 as playerRank, 'BestScorer' as source from BestScorer p join Players pl on pl.PlayerID = p.PlayerID union select p.PlayerID , GamerTag, 5 as playerRank, 'BestAchiever' as source from BestAchiever p join Players pl on pl.PlayerID = p.PlayerID order by playerRank asc """ data = (startDate, endDate, ArenaName, startDate, endDate, ArenaName, ArenaName) cursor.execute(query, data) rows = cursor.fetchall() if rows == None: DBG( " SQLHelper.getTop5Players didn't find any players. Is there data in all tables?/", 2) else: DBG("SQLHelper.getTop5Players found all 5 players", 3) conn.commit() closeConnection() return rows
def executeBuildMonthlyStars(): cachedconfig = cfg.getConfig() curMonth = cachedconfig["StartDate"][0:7] lastMonth = cachedconfig["LastMonthStart"][0:7] endDate = cachedconfig["EndDate"] arenaName = cachedconfig["SiteNameReal"] SQL = ''' with subsetOfData as ( select playerID , gamerTag , gamemonth , avg(playercount) as AveragePlayerCount , count(*) as GamesPlayed , avg(Starsforgame) as AverageStarQuality , sum(Starsforgame) as TotalStarQuality , avg(rank) as AverageRank from public."participationWithStars" where arenaName = %s -- and GameMonth in (%s,%s) -- group by 1,2,3 ) select r1.PlayerID, r1.GamerTag, round (cast(r1.AverageStarQuality as numeric),2) as AverageStarQuality, round (cast(r1.AverageStarQuality * r1.gamesPlayed as numeric),2) as TotalStarQuality, round (cast(r1.AveragePlayerCount as numeric),2) as AveragePlayerCount, round (cast(r1.AverageRank as numeric),2) as AverageRank, r1.gamesPlayed as GamesPlayed, round (cast(r2.AverageRank - r1.AverageRank as numeric),2) as changeInRank, round (cast(r1.AveragePlayerCount-r2.AveragePlayerCount as numeric),2) as changeInPlayers, round (cast(r1.AverageStarQuality - r2.AverageStarQuality as numeric),2) as changeInStars from subsetOfData r1 left join subsetOfData r2 on r1.PlayerID = r2.PlayerID and r1.GameMonth != r2.GameMonth where r1.GameMonth = %s -- order by AverageStarQuality desc ''' conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL, (arenaName, curMonth, lastMonth, curMonth)) JSON = { 'ScoreTitle': "Star Quality for all known players, between {1} and {0}".format( curMonth, lastMonth), 'ScoreGreaterOrEqualDate': curMonth, 'ScoreLessDate': lastMonth, 'Player': [{ # 'Name' : "C'tri", # 'AverageScore' : -1, # 'MissionsPlayed' : -1, }], } breakdownSQL = """ with data as ( select pl.PlayerID, pl.GamerTag, GameName, GameTimestamp, p.score, ROW_NUMBER() over (partition by GameTimestamp order by GameTimestamp desc, score desc) as rank, count(p.PlayerID) over (partition by GameTimestamp order by GameTimestamp desc) as playerCount, TO_CHAR(GameTimestamp,'YYYY-MM') as GameMonth from Participation p join Games g on p.GameUUID = g.GameUUID join Players pl on p.PlayerID = pl.PlayerID where g.ArenaName = %s ) select gamename, rank, playerCount , round(cast((cast(playerCount as float) * cast(playerCount as float)) / cast(rank as float) as numeric),2) as stars from data where GameMonth = %s and playerID ilike %s order by gametimestamp desc """ SQResults = cursor.fetchall() counter = 0 for result in SQResults: #print (result) ChangeInRank = None ChangeInPlayers = None ChangeInStars = None if result[7] is not None: ChangeInRank = "↑%s" % result[7] if result[7] > 0 else "↓%s" % abs( result[7]) if result[8] is not None: ChangeInPlayers = "↑%s" % result[8] if result[ 8] > 0 else "↓%s" % abs(result[8]) if result[9] is not None: ChangeInStars = "↑%s" % result[9] if result[ 9] > 0 else "↓%s" % abs(result[9]) SQObject = { 'JSID': counter, 'Name': result[1], 'StarQualityPerGame': "%s" % result[2], 'TotalStarQuality': "%s" % result[3], 'AverageOpponents': "%s" % result[4], 'gamesPlayed': result[6], 'AverageRank': "%s" % result[5], 'ChangeInRank': ChangeInRank, 'ChangeInPlayers': ChangeInPlayers, 'ChangeInSQPerGame': ChangeInStars, 'breakdown': [] } cursor.execute(breakdownSQL, (arenaName, curMonth, result[0])) breakdownResults = cursor.fetchall() for breakdownEntry in breakdownResults: SQBreakdown = { "gameName": breakdownEntry[0], "rank": breakdownEntry[1], "totalPlayers": breakdownEntry[2], "starsForGame": "%s" % breakdownEntry[3] } SQObject['breakdown'].append(SQBreakdown) JSON['Player'].append(SQObject) counter = counter + 1 filepart = "StarQuality" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open( "JSONBlobs%s%s%s.json" % (divider, cfg.getConfigString("ID Prefix"), filepart), "w+") f.write(json.dumps(JSON, indent=4)) DBG("Star Quality blobs written!", 3)
def fetchIndividualsAchievements(ID): conn = connectToSource() cursor = conn.cursor() IDpieces = ID.split("-") #step 1 get all known achieveements and put into Key Value pairs #the key is the MD5 function of AchName + ArenaName query = """select md5(concat(achname,arenaname)) as hash,achName,arenaName,achieveddate from allachievements aa join playerachievement pa on aa.achID = pa.achID where playerID = %s""" cursor.execute(query, (ID, )) results = cursor.fetchall() knownAchievements = {} if results is not None and len(results) != 0: #new player handling for knownAchievement in results: knownAchievements[knownAchievement[0]] = knownAchievement #step 2 - get all achievements from IPL allAchievements = fetchPlayerAcheivement_root('', IDpieces[0], IDpieces[1], IDpieces[2]) totalAchievemnts = 0 if allAchievements.__len__() > 0: if '1' in allAchievements["centre"]: DBG( "DBG: FetchAchievements.fetchAllAchivements: ABNORMAL RESPONSE handled for user %s" % (ID), 2) DBG( "DBG: FetchAchievements.fetchAllAchivements: Manually check they don't have multiple sites' achievements", 2) holdingVar = [] holdingVar.append(allAchievements["centre"]['1']) allAchievements["centre"] = holdingVar #print (json.dumps(allAchievements["centre"])) for centre in allAchievements["centre"]: #we don't filter by arena, becuase we do achievement searches seperately, and because IPL has to do all the hard work each request anyway. #this means less requests against IPL if we do achieves globally. #addPlayerAchievementScore(ID,centre["score"]) #print (allAchievements) for achievement in centre["achievements"]: #step3 - for each achievement, hash it, test if we have it #if we have it, test if the player needs updated #if the player needs updated, update #if we don't have it, add it, and update the player. tohash = "%s%s" % (achievement["name"], centre['name']) tohash = tohash.encode(encoding="utf-8") md5value = hashlib.md5(tohash).hexdigest() if md5value in knownAchievements: #seen it before! totest = knownAchievements[md5value][3] if totest == None: totest = "0000-00-00" if achievement["achievedDate"] != "%s" % ( totest ): #player has achieved / learned about this achieve! addPlayerAchievement(md5value, ID, achievement["newAchievement"], achievement["achievedDate"], achievement["progressA"], achievement["progressB"]) DBG( "updated player progress for known achievement %s vs %s" % (achievement["achievedDate"], totest), 3) else: #new achievement! newAchMD5 = addAchievement(achievement["name"], achievement["description"], achievement["image"], centre['name']) addPlayerAchievement(newAchMD5, ID, achievement["newAchievement"], achievement["achievedDate"], achievement["progressA"], achievement["progressB"]) DBG( "updated player progress for NEW achievement: [%s][%s]" % (achievement["name"], centre['name']), 3) totalAchievemnts = totalAchievemnts + len(centre["achievements"]) #print ("Updated %i achievements for player %s. [%i/%i]" % (totalAchievemnts,ID,playerCounter,totalToUpdate)) closeConnection()
def executeBuild(): DBG("Building arena metrics", 3) conn = connectToSource() cursor = conn.cursor() outputObject = {} cfg = ConfigHelper.getConfig() startYear = int(cfg["StartDate"][0:4]) endYear = startYear + 1 startYear = "%s-01-01" % startYear endYear = "%s-01-01" % endYear #topGames #print (" == Which games were played") SQL = """ with gamesbyname as ( select count(*) as gameCount, gamename from games g where arenaName ilike %s and gametimestamp >= %s and gametimestamp < %s group by 2 order by 1 desc ), totalGames as ( select sum(gameCount) totalGames from gamesbyname ) select cast(gamecount as integer), gamename from gamesbyname full outer join totalgames on true where (gamecount / totalgames) > 0.01 union select cast(sum(gamecount) as integer), 'other' from gamesbyname full outer join totalgames on true where (gamecount / totalgames) <= 0.01 order by 1 desc; """ parameters = (cfg['SiteNameReal'], startYear, endYear) conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL, parameters) results = cursor.fetchall() SQLdesc = cursor.description descCount = 0 for desc in SQLdesc: #print("%s %s" % (descCount,desc[0])) descCount = descCount + 1 gamesPlayed = [] for result in results: #print (result) game = {'gameName': result[1], 'timesPlayed': result[0]} gamesPlayed.append(game) outputObject['gamesPlayed'] = gamesPlayed #referrals #print (" == Referrals and Welcomers") SQL = """ with firstGames as ( select gamerTag, p.playerID, min(gametimestamp) as firstGame from players pl join participation p on p.playerID = pl.playerID join games g on p.gameuuid = g.gameuuid group by 2,1 ), playersInGames as ( select count(*) as countOfPlayersInGame, gametimestamp from players pl join participation p on p.playerID = pl.playerID join games g on p.gameuuid = g.gameuuid group by 2 ), gamesWithNewPlayers as ( select count (case when gametimestamp = firstgame then 1 else null end) as newPlayers , count (case when gametimestamp != firstgame then 1 else null end) as existingPlayers , gametimestamp , arenaname from players pl join participation p on p.playerID = pl.playerID join games g on p.gameuuid = g.gameuuid join firstGames fg on pl.playerID = fg.playerID where gametimestamp >= %s /*StartDate*/ and gametimestamp < %s /*EndDate*/ and arenaname ilike %s /*SiteNameReal*/ group by 3,4 order by 3 desc ), referredPlayers as ( select pl.gamertag, g.gametimestamp, firstgame, newplayers, existingplayers, case when firstgame = g.gametimestamp then 'REFERRED!' else 'referee' end as referalRole from players pl join participation p on p.playerID = pl.playerID join games g on p.gameuuid = g.gameuuid join firstGames fg on pl.playerID = fg.playerID join gamesWithNewPlayers gwnp on gwnp.gametimestamp = g.gametimestamp and gwnp.arenaname = g.arenaname where newplayers > 0 and existingPlayers > 0 order by g.gametimestamp desc ) select count(distinct gamerTag), 'new player' as playerRole from referredPlayers where referalrole = 'REFERRED!' union select count (distinct gamerTag), 'veteran' from referredPlayers where referalrole = 'referee' """ parameters = (startYear, endYear, cfg['SiteNameReal']) conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL, parameters) results = cursor.fetchall() SQLdesc = cursor.description descCount = 0 for desc in SQLdesc: #print("%s %s" % (descCount,desc[0])) descCount = descCount + 1 referrals = {"newPlayers": results[0][0], "welcomers": results[1][0]} outputObject['referrals'] = referrals #new and old players #print (" == New and Departed players") SQL = """ with playerMetrics as ( select gamertag , pl.playerID , arenaname , min(gametimestamp) as firstGame , max(gametimestamp) as lastGame from participation p join players pl on p.playerID = pl.playerID join games g on p.gameuuid = g.gameuuid where arenaName ilike %s --arenaName group by gamerTag, pl.playerID, arenaName ), playerMissions as ( select playerID, count(*) as gamesPlayedInPeriod from participation p join games g on p.gameuuid = g.gameuuid where gametimestamp >= %s --startDate and gametimestamp < %s --endDate group by 1 ) select count (case when gamesPlayedInPeriod > 0 then 1 else null end) as totalPlayingPlayers , count (case when firstGame >= to_date(%s,'YYYY-MM-DD') then 1 else null end) as newPlayers , count (case when ((lastGame < to_date(%s,'YYYY-MM-DD') - INTERVAL '%s days' ) and lastGame >= %s ) then 1 else null end ) as churnedPlayers from playerMetrics pm1 join playerMissions pm2 on pm1.playerID = pm2.playerID """ parameters = (cfg['SiteNameReal'], startYear, endYear, startYear, endYear, cfg['ChurnDuration'], startYear) conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL, parameters) results = cursor.fetchall() SQLdesc = cursor.description descCount = 0 for desc in SQLdesc: #print("%s %s" % (descCount,desc[0])) descCount = descCount + 1 playerCounts = { 'activePlayers': results[0][0], 'newPlayers': results[0][1], 'churnedPlayers': results[0][2] } outputObject['playerCounts'] = playerCounts #print(json.dumps(outputObject,indent=4)) #MEMBER PERCENTILES - visits SQL = """with data as (select percent_rank() over (order by count(distinct date_trunc('day',g.gametimestamp))) as percentile ,count(distinct date_trunc('day',g.gametimestamp)) as visits , pl.playerID from players pl join participation p on pl.playerID = p.playerID join games g on g.gameuuid = p.gameuuid where g.arenaname ilike %s and g.gametimestamp >= %s and g.gametimestamp < %s group by pl.playerID ), finalresults as ( select count (case when visits >= 1 and visits < 2 then 1 else null end) as one, count (case when visits >= 2 and visits < 3 then 1 else null end) as twoVisits, count (case when visits >= 3 and visits < 5 then 1 else null end) as LessThanFive, count (case when visits >= 5 and visits < 11 then 1 else null end) as LessThanEleven, count (case when visits >= 11 then 1 else null end) as MoreThanEleven from data ) select * from finalResults """ parameters = [cfg['SiteNameReal'], startYear, endYear] cursor.execute(SQL, parameters) result = cursor.fetchone() visits = [{ "caption": "1 visit", "players": result[0] }, { "caption": "2 visits", "players": result[1] }, { "caption": "3-4 visits", "players": result[2] }, { "caption": "5-10 visits", "players": result[3] }, { "caption": "11+ visits", "players": result[4] }] outputObject['regularsAggregateVisits'] = visits #referrals #print (" == Referrals and Welcomers") #MEMBER PERCENTILES - GAMES SQL = """with data as (select percent_rank() over (order by count(distinct date_trunc('day',g.gametimestamp))) as percentile ,count(distinct date_trunc('day',g.gametimestamp)) as visits , pl.playerID from players pl join participation p on pl.playerID = p.playerID join games g on g.gameuuid = p.gameuuid where g.arenaname ilike %s and g.gametimestamp >= %s and g.gametimestamp < %s group by pl.playerID ), finalresults as ( select count (case when visits >= 1 and visits < 3 then 1 else null end) as max2, count (case when visits >= 3 and visits < 7 then 1 else null end) as max6, count (case when visits >= 7 and visits < 13 then 1 else null end) as max12, count (case when visits >= 13 and visits < 36 then 1 else null end) as max35, count (case when visits >= 36 then 1 else null end) as min36 from data ) select * from finalResults""" parameters = [cfg['SiteNameReal'], startYear, endYear] cursor.execute(SQL, parameters) result = cursor.fetchone() games = [{ "caption": "1-2 games", "players": result[0] }, { "caption": "3-6 games", "players": result[1] }, { "caption": "7-12 games", "players": result[2] }, { "caption": "13-35 games", "players": result[3] }, { "caption": "36+ games", "players": result[4] }] outputObject['regularsAggregateGames'] = games #MEMBER PERCENTILES - RETENTION SQL = """with preData as (select p.playerid , min(g.gametimestamp) as firstSeen , max(g.gametimestamp) as lastSeen , floor(extract(epoch from max(g.gametimestamp) - min(g.gametimestamp))/604800)::int as weeks from games g join participation p on p.gameuuid = g.gameuuid where arenaname ilike %s and g.gametimestamp < %s group by 1 ), data as (select * from preData where lastSeen >= %s ), finalresults as ( select count(case when weeks >= 0 and weeks <= 4 then 1 else null end) as max4 , count(case when weeks > 4 and weeks <= 12 then 1 else null end) as max12 , count(case when weeks > 12 and weeks <= 52 then 1 else null end) as max52 , count(case when weeks > 52 and weeks <= 104 then 1 else null end) as max104 , count(case when weeks > 104 and weeks <= 156 then 1 else null end) as max156 , count(case when weeks > 156 then 1 else null end) as min157 from data ) select * from finalresults""" parameters = [cfg['SiteNameReal'], endYear, startYear] cursor.execute(SQL, parameters) result = cursor.fetchone() retention = [{ "caption": "0-4 weeks", "players": result[0] }, { "caption": "5-12 weeks", "players": result[1] }, { "caption": "13-52 weeks", "players": result[2] }, { "caption": "1-2 years", "players": result[3] }, { "caption": "3-4 years", "players": result[4] }, { "caption": "5+ years", "players": result[5] }] outputObject['regularsAggregateRetention'] = retention filepart = "AnnualMetrics" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open( "JSONBlobs%s%s%s-%s.json" % (divider, cfg["ID Prefix"], filepart, startYear[0:4]), "w+") f.write(json.dumps(outputObject, indent=4)) DBG("Annual metrics complete!", 3)
def findNewPlayers(siteName=None, jobID=None): startTime = datetime.datetime.now() lastHeartbeat = startTime conn = connectToSource() cursor = conn.cursor() conn = connectToSource() cursor = conn.cursor() if siteName is not None: targetID = cfg.findSiteIDFromName(siteName) siteObj = cfg.getSiteWithoutActivatingByID(targetID) sitePrefix = siteObj["ID Prefix"] siteName = siteObj["SiteNameReal"] else: sitePrefix = cfg.getConfigString("ID Prefix") siteName = cfg.getConfigString("SiteNameReal") params = {} params["siteName"] = siteName if jobID is None: jobID = jobStart(" new players at [%s]" % siteName, 0, "FetchPlayerUpdatesAndNewPlayers.findNewPlayers", params) else: jobHeartbeat(jobID, 0) TickerIcon = ["|", "/", "-", '\\'] sitePrefixforSQL = sitePrefix + "%" query = sql.SQL(""" with IDs as ( select cast (split_part(pl.PlayerID,'-',3) as integer) as ID from players pl where playerID like %s order by 1 desc offset 5 ) select max (ID) from IDs """) cursor.execute(query, (sitePrefixforSQL, )) result = cursor.fetchone() if result == None or result[0] == None: MaxPlayer = 199 #LaserForce seems to start numbering players at 100 else: MaxPlayer = result[0] region = sitePrefix.split("-")[0] siteNumber = sitePrefix.split("-")[1] ticker = 0 consecutiveMisses = 0 currentTarget = MaxPlayer - 100 #we've had situations where the system adds user IDs behind the maximum. This is a stopgap dragnet to catch trailing players. AllowedMisses = 100 while consecutiveMisses <= AllowedMisses: heartbeatDelta = (datetime.datetime.now() - lastHeartbeat).total_seconds() if heartbeatDelta > 30: jobHeartbeat(jobID, 0) lastHeartbeat = datetime.datetime.now() conn.commit() player = fetchPlayer_root('', region, siteNumber, currentTarget) if 'centre' in player: codeName = player["centre"][0]["codename"] dateJoined = player["centre"][0]["joined"] missionsPlayed = player["centre"][0]["missions"] skillLevelNum = player["centre"][0]["skillLevelNum"] addPlayer("%s%i" % (sitePrefix, currentTarget), codeName, dateJoined, missionsPlayed) _parseCentresAndAdd( player["centre"], '%s-%s-%s' % (region, siteNumber, currentTarget)) consecutiveMisses = 0 else: DBG( "DBG: FetchPlayerUpdatesAndNewPlayers.findNewPlayers - Missed a player 7-X-%s" % (currentTarget), 3) consecutiveMisses = consecutiveMisses + 1 wpq.updateQ(consecutiveMisses, AllowedMisses, "Seeking new... %s" % TickerIcon[ticker % 4], "ETA ?") currentTarget = currentTarget + 1 ticker = ticker + 1 endTime = datetime.datetime.now() jobEnd(jobID) f = open("Stats.txt", "a+") f.write( "searched for {0} players, operation completed after {1}. \t\n".format( currentTarget - MaxPlayer, endTime - startTime)) wpq.updateQ(1, 1, "Seeking new... %s", "Complete") f.close() conn.commit() closeConnection()
def executeAchievementBuild(): targetArena = cfg.getConfigString("SiteNameReal") query = sql.SQL(''' with PA as ( select pl.PlayerID, GamerTag, sum ( case when achievedDate is null then 0 when achievedDate is not null then 1 end) as AchievementsCompleted from players pl join PlayerAchievement pa on pl.PlayerID = pa.PlayerID join AllAchievements aa on aa.achID = pa.achID where aa.ArenaName = %s or aa.ArenaName = 'Global Achievements' group by pl.PlayerID, GamerTag, AchievementScore ), top15 as ( select * from PA order by AchievementsCompleted desc limit 15 ), CountOfAcqusitions as ( select count(*) acCount, min(pa.achievedDate) earliest, pa.AchID, aa.AchName from PlayerAchievement pa join AllAchievements aa on pa.AchID = aa.AchID where ArenaName = %s and achievedDate is not null group by pa.AchID, aa.AchName ), acquiredAAwithRarity as ( select pa.AchID, acCount, earliest, playerID, AchName from CountOfAcqusitions coa join PlayerAchievement pa on coa.achID = pa.AchID where achievedDate is not null ), finalResults as ( select row_number() over (partition by aa.playerID order by acCount, earliest) rarityIndex, AchName,aa.AchID, acCount, top15.playerID from acquiredAAwithRarity aa join top15 on aa.PlayerID = top15.PlayerID --order by AchievementsCompleted desc, count ) select top15.PlayerID,GamerTag,AchievementsCompleted,AchName,acCount from top15 join finalResults on top15.PlayerID = finalResults.PlayerID where rarityIndex = 1 order by Achievementscompleted desc limit 15 ''') data = (targetArena, targetArena) conn = connectToSource() cursor = conn.cursor() cursor.execute(query, data) JSON = { 'ScoreTitle': "Achievement score & total achievements completed", 'Player': [{ # 'Name' : "C'tri", # 'AchievementScore' : -1, # 'AchievementsCompleted' : -1, }], } for result in cursor.fetchall(): #print (result) JSON['Player'].append({ 'Name': result[1], 'AchievementsCompleted': result[2], 'RarestAchievement': result[3], 'OthersWith': "(%i)" % (result[4]) }) filepart = "Achievements" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open( "JSONBlobs%s%s%s.json" % (divider, cfg.getConfigString("ID Prefix"), filepart), "w+") f.write(json.dumps(JSON, indent=4)) DBG("Achievement score blob written!", 3)
def executeBuildPlayerBlobs(jobID=None, counter=None): cachedconfig = cfg.getConfig() targetIDs = getTop5PlayersRoster(cachedconfig["StartDate"], cachedconfig["EndDate"], cachedconfig["SiteNameReal"]) DBG("Building big 5 player blobs", 3) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) #print ("Player profile blobs written!") JSONobject = {} if len(targetIDs) >= 1: #fetchIndividualWithID(targetIDs[0][0]) JSONobject["GoldenPlayer"] = buildPlayerBlob(cachedconfig["StartDate"], cachedconfig["EndDate"], targetIDs[0][0]) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if len(targetIDs) >= 2: #fetchIndividualWithID(targetIDs[1][0]) JSONobject["SilverPlayer"] = buildPlayerBlob(cachedconfig["StartDate"], cachedconfig["EndDate"], targetIDs[1][0]) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if len(targetIDs) >= 3: #fetchIndividualWithID(targetIDs[2][0]) JSONobject["BronzePlayer"] = buildPlayerBlob(cachedconfig["StartDate"], cachedconfig["EndDate"], targetIDs[2][0]) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if len(targetIDs) >= 4: fetchIndividualWithID(targetIDs[3][0]) JSONobject["OtherPlayer1"] = buildPlayerBlob(cachedconfig["StartDate"], cachedconfig["EndDate"], targetIDs[3][0]) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if jobID is not None and counter is not None: jobHeartbeat(jobID, counter) if len(targetIDs) >= 5: fetchIndividualWithID(targetIDs[4][0]) JSONobject["OtherPlayer2"] = buildPlayerBlob(cachedconfig["StartDate"], cachedconfig["EndDate"], targetIDs[4][0]) if len(targetIDs) < 5: DBGstring = "Big 5 returned %i: " % (len(targetIDs)) for target in targetIDs: DBGstring = DBGstring + "[%i %s]," % (target[2], target[3]) DBG(DBGstring, 2) JSONobject["SiteNameShort"] = cachedconfig["SiteNameShort"] filepart = "playerBlob" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open( "JSONBlobs%s%s%s.json" % (divider, cfg.getConfigString("ID Prefix"), filepart), "w+") f.write(json.dumps(JSONobject, indent=4)) f.close()
def buildPlayerBlob(startDate, endDate, targetID): cachedconfig = cfg.getConfig() infoQuery = """ with StarQuality as ( select playerID , avg(rank) as AverageRank , avg(playercount) as AverageOpponents , round(avg(starsforgame),2) as AvgQualityPerGame , round(sum(starsforgame),2) as TotalQualityScore , count(*) as gamesPlayed from public."participationWithStars" where gametimestamp >= %s and gametimestamp < %s and arenaName = %s and playerID = %s group by playerID ), totalAchievements as ( select sum ( case when achievedDate is null then 0 when achievedDate is not null then 1 end) as AchievementsCompleted, PlayerID from PlayerAchievement pa join AllAchievements aa on pa.AchID = aa.AchID where aa.ArenaName = %s or aa.ArenaName = 'Global Achievements' group by PlayerID ) select Players.PlayerID, GamerTag,players.Level, Missions, round(cast(AverageOpponents as numeric),2) as AverageOpponents, gamesPlayed , AverageRank , AvgQualityPerGame , TotalQualityScore , ta.AchievementsCompleted , ta.PlayerID as TaPID , ph.arenaName , pas.locallevel , arl.rankName from Players join StarQuality sq on sq.playerID = players.playerID join totalAchievements ta on ta.playerID = players.playerID join public."playerHomes" ph on Players.PlayerID = ph.PlayerID and ph.month = %s and ph.arenarow = 1 join PlayerArenaSummary pas on pas.playerID = ph.PlayerID and pas.ArenaName = ph.ArenaName join ArenaRanksLookup arl on arl.ArenaName = pas.ArenaName and arl.ranknumber = pas.localLevel where Players.playerID = %s """ goldenGameQuery = """ with PlayersInGame as ( SELECT Count (Players.GamerTag) as playersInGame, Games.GameUUID as gameID FROM Games join Participation on participation.GameUUID = Games.GameUUID join Players on Participation.PlayerID = Players.PlayerID where games.ArenaName = %s group by Games.GameUUID ), Ranks as ( select GameTimestamp, GameName, Players.PlayerID, GamerTag, Score, Games.GameUUID, ROW_NUMBER() over (partition by GameTimestamp order by score desc) as gamePosition from Games join Participation on Games.GameUUID = Participation.GameUUID join Players on Participation.PlayerID = Players.PlayerID where games.ArenaName = %s ), GoldenGame as ( select r.Score, r.GamerTag,r.GameUUID, GameName, r.PlayerID, gamePosition, playersInGame, GameTimestamp ,round((playersInGame * (playersInGame/gamePosition)),2) as StarQuality from Ranks r join PlayersInGame pig on r.GameUUID = pig.gameID where PlayerID = %s and GameTimestamp >= %s and GameTimeStamp < %s order by StarQuality desc, score desc limit 1 ), Vanquished as ( select g.PlayerID, g.GameTimestamp, g.gamePosition victoryPos, g.GamerTag victorName, g.Score victorScore, g.GameName, g.StarQuality victorStarQuality, r.PlayerID vanquishedID, r.GamerTag vanquishedName ,r.gamePosition as vanquishedPos from Ranks r inner join GoldenGame g on r.gameUUID = g.GameUUID where g.PlayerID != r.PlayerID and g.gamePosition < r.gamePosition ) select * from Vanquished""" goldenAchievementQuery = """ with firstEarned as ( select distinct min (achievedDate) over (partition by AchID) as firstAchieved, AchID from PlayerAchievement where achievedDate is not null ), data as ( select count(*) playersEarned, pa.AchID, achName from PlayerAchievement pa join AllAchievements aa on pa.AchID = aa.AchID where achievedDate is not null group by AchName, pa.AchID ) select PlayerID, data.AchName, Description, fe.firstAchieved, playersEarned from PlayerAchievement pa join data on data.AchID = pa.AchID join firstEarned fe on fe.AchID = data.AchID join AllAchievements aa on pa.AchID = aa.AchID where PlayerID = %s and pa.achievedDate is not null and ArenaName = %s order by playersEarned asc, firstAchieved asc limit 10 """ fallbackInfoQuery = """ with achs as (select count(*) as achCount from playerAchievement pa join allachievements aa on aa.achID = pa.achID where playerID = %s and arenaname = %s and achieveddate is not null) select pl.playerID, Gamertag, '' , pl.missions, '', 0 --monthly missions played , '', 0.00, '', achCount, '', arl.arenaname, ranknumber, rankname from players pl join achs on true join playerarenasummary pas on pas.arenaname = %s and pl.playerID = pas.playerID join arenarankslookup arl on pas.arenaname = arl.arenaname and locallevel = ranknumber where pl.playerID = %s """ conn = connectToSource() cursor = conn.cursor() #DBG("BuildPlayerBlob.buildPlayerBlob start[%s], end[%s], target[%s], arena[%s]" % (cachedconfig["StartDate"],cachedconfig["EndDate"],targetID,cachedconfig["SiteNameReal"]),3) #startDate, endDate, arenaName, startDate, endDate, arenaName, startDate, endDate, arenaName, arenaName, PlayerID endDate = cachedconfig["EndDate"] startDate = cachedconfig["StartDate"] targetArena = cachedconfig["SiteNameReal"] currentMonth = cachedconfig["StartDate"][:7] result = cursor.execute(infoQuery, (startDate, endDate, targetArena, targetID, targetArena, currentMonth, targetID)) row = cursor.fetchone() if row == None: DBG( "BuildPlayerBlob info query returned Null. Did they play any games? SWITCHING TO FALLBACK. [%s]" % (targetID), 1) result = cursor.execute(fallbackInfoQuery, (targetID, targetArena, targetArena, targetID)) row = cursor.fetchone() if row == None: DBG("Fallback infoquery failed. This should not happen, something is wack somewhere. " ) return #print(row) #print ("Players.PlayerID, GamerTag, round(AverageOpponents,2) as AverageOpponents, gamesPlayed, AverageRank") JSONobject = {} JSONobject["PlayerName"] = row[1] JSONobject["HomeArenaTrunc"] = row[11] JSONobject["SkillLevelName"] = row[13] JSONobject["MonthlyGamesPlayed"] = row[5] JSONobject["AllGamesPlayed"] = row[3] JSONobject["StarQuality"] = "%s" % row[7] JSONobject["Achievements"] = row[9] result = cursor.execute( goldenGameQuery, (targetArena, targetArena, targetID, startDate, endDate)) rows = cursor.fetchall() if len(rows) > 0: row = rows[0] #print(row) #print ("g.PlayerID, g.GameTimestamp, victoryPos, victorName, victorScore, g.GameName, victorStarQuality, vanquishedID, vanquishedName , vanquishedPos") ordinalranks = [ "0th", "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th", "10th" ] JSONobject["GGName"] = row[5] JSONobject["GGRank"] = ordinalranks[row[2]] JSONobject["GGStars"] = "%i stars" % row[6] JSONobject["GGVanq1"] = rows[0][8] if len(rows) >= 2: JSONobject["GGVanq2"] = rows[1][8] if len(rows) >= 3: JSONobject["GGVanq3"] = rows[2][8] if len(rows) >= 4: JSONobject["GGVanq4"] = '%i others' % (len(rows) - 3) result = cursor.execute(goldenAchievementQuery, (targetID, targetArena)) row = cursor.fetchone() if row == None: DBG( "BuildPlayerBlob GoldenAchievementQuery query returned Null. Aborting. [%s]" % (targetID), 1) return #print (row) JSONobject["GAName"] = row[1] JSONobject["GADesc"] = row[2] ordinalOthers = [ "No one else has", "Only one other person has", "Only two others have", "%i others have" % row[4] ] JSONobject["GAOthers"] = ordinalOthers[min(row[4] - 1, 3)] return JSONobject
def execute(): SQL = """ with starQuality as ( select playerID, gamertag ,round(avg(starsforgame),2) as avgQualityPerGame ,gamemonth ,count(*)::int as gamesPlayed from public."participationWithStars" where gameTimestamp >= %s and gameTimestamp < %s and arenaName ilike %s group by 1,2,4 ), GoldenTopX as ( select PlayerID, gamertag , ROW_NUMBER() over (partition by gameMonth order by avgQualityPerGame desc) as playerRank , gameMonth from StarQuality where StarQuality.gamesPlayed >= 3 order by AvgQualityPerGame desc --limit 3 ), GoldenTop3 as ( select * from GoldenTopX where playerRank <= 3 ) select * from GoldenTop3 g3 join StarQuality sq on sq.playerID = g3.playerID and sq.gameMonth = g3.gameMonth order by g3.gameMonth asc, g3.playerRank asc """ #--startDate,endDate, siteNameReal, name (sen) (sen) (sen) name cfg = ConfigHelper.getConfig() startYear = int(cfg["StartDate"][0:4]) endYear = startYear + 1 startYear = "%s-01-01" % startYear endYear = "%s-01-01" % endYear #startYear = '2019-08-01' parameters = (startYear, endYear, cfg['SiteNameReal']) conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL, parameters) results = cursor.fetchall() SQLdesc = cursor.description descCount = 0 for desc in SQLdesc: #print("%s %s" % (descCount,desc[0])) descCount = descCount + 1 currentMonth = "" months = [] for result in results: if result[3] != currentMonth: currentMonth = result[3] #print("== New month = [%s]" % (currentMonth,)) month = {} months.append(month) month["month"] = result[3] players = [] month["players"] = players #print(result) player = {} player["playerName"] = result[5] player["gamePlayed"] = result[8] player["averageStars"] = "%s" % (result[6]) players.append(player) playerName = "%s%s" % (result[5], " " * 15) playerName = playerName[0:10] #print("%s %s, %s games played \t %s stars per game (avg) " % (result[1],playerName , result[6], result[8]) ) #print(json.dumps(months,indent=4)) #playerID, rank, month, #ID, gamertag, avgopponents #gamesplayed, averagerank, avgqual #totalqual, avgscore, achievementscore #gamemonth filepart = "AnnualTop3s" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open( "JSONBlobs%s%s%s-%s.json" % (divider, cfg["ID Prefix"], filepart, startYear[0:4]), "w+") f.write(json.dumps(months, indent=4)) DBG("Annual top3s complete!", 3)
def executeMonthlyScoresBuild(): startDate = cfg.getConfigString("StartDate") endDate = cfg.getConfigString("EndDate") LastMonthStart = cfg.getConfigString("LastMonthStart") arenaName = cfg.getConfigString("SiteNameReal") SQL = ''' with data as ( SELECT p.PlayerID, GamerTag, avg(Score) as averageScore, count(GamerTag) as gamesPlayed, to_char(GameTimestamp,'YYYY-MM') as GameMonth FROM Participation p inner join Players pl on p.PlayerID = pl.PlayerID inner join Games g on p.GameUUID = g.GameUUID where to_char(GameTimestamp,'YYYY-MM') in (%s,%s) and ( g.GameName in ('Team','3 Teams','4 Teams', 'Colour Ranked','Individual') or g.GameName in ('Standard - Solo', 'Standard - Team','Standard [3 Team] (10)','Standard [3 Team] (15)','Standard 2 Team', 'Standard 3 Team','Standard 4 Team','Standard Individual','Standard Multi team','- Standard [2 Team] (15))') ) and g.ArenaName = %s GROUP BY p.PlayerID, pl.GamerTag, to_char(GameTimestamp,'YYYY-MM') ) select d1.PlayerID, d1.GamerTag, cast(d1.averageScore as int),d1.gamesPlayed, round(cast(d1.averageScore -d2.averageScore as numeric),2) as changeInScore from data d1 left join data d2 on d1.PlayerID = d2.PlayerID and d1.GameMonth != d2.GameMonth where d1.GameMonth = %s order by averageScore desc; ''' conn = connectToSource() cursor = conn.cursor() cursor.execute(SQL,(startDate[0:7],LastMonthStart[0:7],arenaName,startDate[0:7])) JSON = { 'ScoreTitle' : "Average Scores for known players, in Standard Games, between {1} and {0}" .format(startDate,endDate), 'ScoreGreaterOrEqualDate' : startDate, 'ScoreLessDate' : endDate, 'Player' : [{ # 'Name' : "C'tri", # 'AverageScore' : -1, # 'MissionsPlayed' : -1, }], } for result in cursor.fetchall(): #print (result) changeInScore = None if result[4] is not None: changeInScore = "↑%s" % result[4] if result[4] > 0 else "↓%s" % abs(result[4]) JSON['Player'].append({'Name' : result[1], 'AverageScore' : result[2], 'MissionsPlayed' : result[3], "ChangeInScore": changeInScore}) filepart = "MonthlyScore" if os.name == "nt": divider = "\\" elif os.name == "posix": divider = "/" f = open("JSONBlobs%s%sLatest.json" % (divider,filepart), "w+") f.write(json.dumps(JSON,indent=4)) f = open("JSONBlobs%s%s%s.json" % (divider, cfg.getConfigString("ID Prefix"),filepart), "w+") f.write(json.dumps(JSON,indent=4)) DBG ("Monthly average score blobs written!",3)
def addThread(newThread): global threadQueue threadQueue.put(newThread) t = startInputThread() #screen goes black here. Why? if t is not None: t.name = "inputThread" threads.append(t) heartMonitor = HeartMonitor.startMonitorThreads() threads.append(heartMonitor) DBG("Startup - menu",3) clearScreen() waitingFunction = "" workerStatusQ = workerProgressQueue.getQ() #rendering is done generically, but the wrapper and refresh must be handled by the CmdMenus part. stop = False _overrideFlag = False _lastInput = time.time() while (inputS != "exit" and inputS != "x" and stop != True) and not safeShutdownCheck(threads,_lastInput,_overrideFlag): time.sleep(0.33) print_at(0,0,"LOOP [%s]"% stop) inputS = "" while not feedbackQueue.q.empty(): feedback.append(feedbackQueue.q.get()) while not InputReader.q.empty():