mirror of
https://github.com/imayushsaini/Bombsquad-Ballistica-Modded-Server.git
synced 2025-11-14 17:46:03 +00:00
stats.json fix with auto backup
This commit is contained in:
parent
a2c7b303d0
commit
db5782b6f1
1 changed files with 85 additions and 77 deletions
150
dist/ba_root/mods/stats/mystats.py
vendored
150
dist/ba_root/mods/stats/mystats.py
vendored
|
|
@ -1,12 +1,12 @@
|
||||||
damage_data = {}
|
damage_data = {}
|
||||||
#Don't touch the above line
|
# Don't touch the above line
|
||||||
"""
|
"""
|
||||||
mystats module for BombSquad version 1.5.29
|
mystats module for BombSquad version 1.5.29
|
||||||
Provides functionality for dumping player stats to disk between rounds.
|
Provides functionality for dumping player stats to disk between rounds.
|
||||||
"""
|
"""
|
||||||
ranks=[]
|
ranks = []
|
||||||
top3Name=[]
|
top3Name = []
|
||||||
import threading,json,os,urllib.request,ba,_ba,setting
|
import threading, json, os, urllib.request, ba, _ba, setting
|
||||||
from ba._activity import Activity
|
from ba._activity import Activity
|
||||||
from ba._music import setmusic, MusicType
|
from ba._music import setmusic, MusicType
|
||||||
# False-positive from pylint due to our class-generics-filter.
|
# False-positive from pylint due to our class-generics-filter.
|
||||||
|
|
@ -19,10 +19,11 @@ from ba._activitytypes import *
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import custom_hooks
|
import custom_hooks
|
||||||
import datetime
|
import datetime
|
||||||
#variables
|
|
||||||
|
# variables
|
||||||
our_settings = setting.get_settings_data()
|
our_settings = setting.get_settings_data()
|
||||||
# where our stats file and pretty html output will go
|
# where our stats file and pretty html output will go
|
||||||
base_path = os.path.join(_ba.env()['python_directory_user'],"stats" + os.sep)
|
base_path = os.path.join(_ba.env()['python_directory_user'], "stats" + os.sep)
|
||||||
statsfile = base_path + 'stats.json'
|
statsfile = base_path + 'stats.json'
|
||||||
htmlfile = base_path + 'stats_page.html'
|
htmlfile = base_path + 'stats_page.html'
|
||||||
table_style = "{width:100%;border: 3px solid black;border-spacing: 5px;border-collapse:collapse;text-align:center;background-color:#fff}"
|
table_style = "{width:100%;border: 3px solid black;border-spacing: 5px;border-collapse:collapse;text-align:center;background-color:#fff}"
|
||||||
|
|
@ -46,7 +47,7 @@ html_start = f'''<!DOCTYPE html>
|
||||||
<th><b>Games Played</b></th>
|
<th><b>Games Played</b></th>
|
||||||
</tr>
|
</tr>
|
||||||
'''
|
'''
|
||||||
statsDefault={
|
statsDefault = {
|
||||||
"pb-IF4VAk4a": {
|
"pb-IF4VAk4a": {
|
||||||
"rank": 65,
|
"rank": 65,
|
||||||
"name": "pb-IF4VAk4a",
|
"name": "pb-IF4VAk4a",
|
||||||
|
|
@ -63,22 +64,28 @@ statsDefault={
|
||||||
}
|
}
|
||||||
# <th><b>Total Damage</b></th> #removed this line as it isn't crt data
|
# <th><b>Total Damage</b></th> #removed this line as it isn't crt data
|
||||||
|
|
||||||
#useful functions
|
# useful functions
|
||||||
seasonStartDate=None
|
seasonStartDate = None
|
||||||
import shutil,os
|
import shutil, os
|
||||||
|
|
||||||
|
|
||||||
def get_all_stats():
|
def get_all_stats():
|
||||||
global seasonStartDate
|
global seasonStartDate
|
||||||
if os.path.exists(statsfile):
|
if os.path.exists(statsfile):
|
||||||
renameFile=False
|
renameFile = False
|
||||||
with open(statsfile, 'r',encoding='utf8') as f:
|
with open(statsfile, 'r', encoding='utf8') as f:
|
||||||
jsonData=json.loads(f.read())
|
|
||||||
try:
|
try:
|
||||||
stats=jsonData["stats"]
|
jsonData = json.loads(f.read())
|
||||||
|
except:
|
||||||
|
f=open(statsfile+".backup",encoding='utf-8')
|
||||||
|
jsonData=json.load(f)
|
||||||
|
try:
|
||||||
|
stats = jsonData["stats"]
|
||||||
|
|
||||||
seasonStartDate=datetime.datetime.strptime(jsonData["startDate"],"%d-%m-%Y")
|
seasonStartDate = datetime.datetime.strptime(jsonData["startDate"], "%d-%m-%Y")
|
||||||
if (datetime.datetime.now()-seasonStartDate).days >=our_settings["statsResetAfterDays"]:
|
if (datetime.datetime.now() - seasonStartDate).days >= our_settings["statsResetAfterDays"]:
|
||||||
backupStatsFile()
|
backupStatsFile()
|
||||||
seasonStartDate=datetime.datetime.now()
|
seasonStartDate = datetime.datetime.now()
|
||||||
return statsDefault
|
return statsDefault
|
||||||
return stats
|
return stats
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
|
|
@ -87,30 +94,33 @@ def get_all_stats():
|
||||||
else:
|
else:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
def backupStatsFile():
|
|
||||||
shutil.copy(statsfile,statsfile.replace(".json","")+str(seasonStartDate)+".json")
|
|
||||||
|
|
||||||
|
def backupStatsFile():
|
||||||
|
shutil.copy(statsfile, statsfile.replace(".json", "") + str(seasonStartDate) + ".json")
|
||||||
|
|
||||||
|
|
||||||
def dump_stats(s: dict):
|
def dump_stats(s: dict):
|
||||||
global seasonStartDate
|
global seasonStartDate
|
||||||
if seasonStartDate ==None:
|
if seasonStartDate == None:
|
||||||
seasonStartDate=datetime.datetime.now()
|
seasonStartDate = datetime.datetime.now()
|
||||||
s={"startDate":seasonStartDate.strftime("%d-%m-%Y") , "stats":s}
|
s = {"startDate": seasonStartDate.strftime("%d-%m-%Y"), "stats": s}
|
||||||
if os.path.exists(statsfile):
|
if os.path.exists(statsfile):
|
||||||
with open(statsfile, 'w',encoding='utf8') as f:
|
shutil.copyfile(statsfile,statsfile+".backup")
|
||||||
f.write(json.dumps(s, indent=4,ensure_ascii=False))
|
with open(statsfile, 'w', encoding='utf8') as f:
|
||||||
|
f.write(json.dumps(s, indent=4, ensure_ascii=False))
|
||||||
f.close()
|
f.close()
|
||||||
else: print('Stats file not found!')
|
else:
|
||||||
|
print('Stats file not found!')
|
||||||
|
|
||||||
|
|
||||||
def get_stats_by_id(ID: str):
|
def get_stats_by_id(ID: str):
|
||||||
a = get_all_stats()
|
a = get_all_stats()
|
||||||
if ID in a:
|
if ID in a:
|
||||||
return a[ID]
|
return a[ID]
|
||||||
else:
|
else:
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def refreshStats():
|
def refreshStats():
|
||||||
# lastly, write a pretty html version.
|
# lastly, write a pretty html version.
|
||||||
# our stats url could point at something like this...
|
# our stats url could point at something like this...
|
||||||
|
|
@ -120,11 +130,11 @@ def refreshStats():
|
||||||
|
|
||||||
entries = [(a['scores'], a['kills'], a['deaths'], a['games'], a['name'], a['aid']) for a in pStats.values()]
|
entries = [(a['scores'], a['kills'], a['deaths'], a['games'], a['name'], a['aid']) for a in pStats.values()]
|
||||||
# this gives us a list of kills/names sorted high-to-low
|
# this gives us a list of kills/names sorted high-to-low
|
||||||
entries.sort(key=lambda x:x[1] or 0,reverse=True)
|
entries.sort(key=lambda x: x[1] or 0, reverse=True)
|
||||||
rank = 0
|
rank = 0
|
||||||
toppers = {}
|
toppers = {}
|
||||||
toppersIDs=[]
|
toppersIDs = []
|
||||||
_ranks=[]
|
_ranks = []
|
||||||
for entry in entries:
|
for entry in entries:
|
||||||
if True:
|
if True:
|
||||||
rank += 1
|
rank += 1
|
||||||
|
|
@ -135,7 +145,7 @@ def refreshStats():
|
||||||
name = str(entry[4])
|
name = str(entry[4])
|
||||||
aid = str(entry[5])
|
aid = str(entry[5])
|
||||||
if rank < 6: toppersIDs.append(aid)
|
if rank < 6: toppersIDs.append(aid)
|
||||||
#The below kd and avg_score will not be added to website's html document, it will be only added in stats.json
|
# The below kd and avg_score will not be added to website's html document, it will be only added in stats.json
|
||||||
try:
|
try:
|
||||||
kd = str(float(kills) / float(deaths))
|
kd = str(float(kills) / float(deaths))
|
||||||
kd_int = kd.split('.')[0]
|
kd_int = kd.split('.')[0]
|
||||||
|
|
@ -153,39 +163,39 @@ def refreshStats():
|
||||||
if damage_data and aid in damage_data:
|
if damage_data and aid in damage_data:
|
||||||
dmg = damage_data[aid]
|
dmg = damage_data[aid]
|
||||||
dmg = str(str(dmg).split('.')[0] + '.' + str(dmg).split('.')[1][:3])
|
dmg = str(str(dmg).split('.')[0] + '.' + str(dmg).split('.')[1][:3])
|
||||||
else: dmg = 0
|
else:
|
||||||
|
dmg = 0
|
||||||
|
|
||||||
_ranks.append(aid)
|
_ranks.append(aid)
|
||||||
|
|
||||||
pStats[str(aid)]["rank"] = int(rank)
|
pStats[str(aid)]["rank"] = int(rank)
|
||||||
pStats[str(aid)]["scores"] = int(scores)
|
pStats[str(aid)]["scores"] = int(scores)
|
||||||
pStats[str(aid)]["total_damage"] += float(dmg) #not working properly
|
pStats[str(aid)]["total_damage"] += float(dmg) # not working properly
|
||||||
pStats[str(aid)]["games"] = int(games)
|
pStats[str(aid)]["games"] = int(games)
|
||||||
pStats[str(aid)]["kills"] = int(kills)
|
pStats[str(aid)]["kills"] = int(kills)
|
||||||
pStats[str(aid)]["deaths"] = int(deaths)
|
pStats[str(aid)]["deaths"] = int(deaths)
|
||||||
pStats[str(aid)]["kd"] = float(p_kd)
|
pStats[str(aid)]["kd"] = float(p_kd)
|
||||||
pStats[str(aid)]["avg_score"] = float(p_avg_score)
|
pStats[str(aid)]["avg_score"] = float(p_avg_score)
|
||||||
|
|
||||||
# if rank < 201:
|
# if rank < 201:
|
||||||
# #<td>{str(dmg)}</td> #removed this line as it isn't crt data
|
# #<td>{str(dmg)}</td> #removed this line as it isn't crt data
|
||||||
# f.write(f'''
|
# f.write(f'''
|
||||||
# <tr>
|
# <tr>
|
||||||
# <td>{str(rank)}</td>
|
# <td>{str(rank)}</td>
|
||||||
# <td style="text-align:center">{str(name)}</td>
|
# <td style="text-align:center">{str(name)}</td>
|
||||||
# <td>{str(scores)}</td>
|
# <td>{str(scores)}</td>
|
||||||
# <td>{str(kills)}</td>
|
# <td>{str(kills)}</td>
|
||||||
# <td>{str(deaths)}</td>
|
# <td>{str(deaths)}</td>
|
||||||
# <td>{str(games)}</td>
|
# <td>{str(games)}</td>
|
||||||
# </tr>''')
|
# </tr>''')
|
||||||
# f.write('''
|
# f.write('''
|
||||||
# </table>
|
# </table>
|
||||||
# </body>
|
# </body>
|
||||||
# </html>''')
|
# </html>''')
|
||||||
|
|
||||||
|
|
||||||
# f.close()
|
# f.close()
|
||||||
global ranks
|
global ranks
|
||||||
ranks=_ranks
|
ranks = _ranks
|
||||||
|
|
||||||
dump_stats(pStats)
|
dump_stats(pStats)
|
||||||
updateTop3Names(toppersIDs[0:3])
|
updateTop3Names(toppersIDs[0:3])
|
||||||
|
|
@ -193,6 +203,7 @@ def refreshStats():
|
||||||
from playersData import pdata
|
from playersData import pdata
|
||||||
pdata.update_toppers(toppersIDs)
|
pdata.update_toppers(toppersIDs)
|
||||||
|
|
||||||
|
|
||||||
def update(score_set):
|
def update(score_set):
|
||||||
"""
|
"""
|
||||||
Given a Session's ScoreSet, tallies per-account kills
|
Given a Session's ScoreSet, tallies per-account kills
|
||||||
|
|
@ -201,7 +212,6 @@ def update(score_set):
|
||||||
"""
|
"""
|
||||||
# look at score-set entries to tally per-account kills for this round
|
# look at score-set entries to tally per-account kills for this round
|
||||||
|
|
||||||
|
|
||||||
account_kills = {}
|
account_kills = {}
|
||||||
account_deaths = {}
|
account_deaths = {}
|
||||||
account_scores = {}
|
account_scores = {}
|
||||||
|
|
@ -224,6 +234,7 @@ def update(score_set):
|
||||||
if account_scores:
|
if account_scores:
|
||||||
UpdateThread(account_kills, account_deaths, account_scores).start()
|
UpdateThread(account_kills, account_deaths, account_scores).start()
|
||||||
|
|
||||||
|
|
||||||
class UpdateThread(threading.Thread):
|
class UpdateThread(threading.Thread):
|
||||||
def __init__(self, account_kills, account_deaths, account_scores):
|
def __init__(self, account_kills, account_deaths, account_scores):
|
||||||
threading.Thread.__init__(self)
|
threading.Thread.__init__(self)
|
||||||
|
|
@ -235,9 +246,9 @@ class UpdateThread(threading.Thread):
|
||||||
# pull our existing stats from disk
|
# pull our existing stats from disk
|
||||||
import datetime
|
import datetime
|
||||||
try:
|
try:
|
||||||
stats=get_all_stats()
|
stats = get_all_stats()
|
||||||
except:
|
except:
|
||||||
stats={}
|
stats = {}
|
||||||
|
|
||||||
# now add this batch of kills to our persistant stats
|
# now add this batch of kills to our persistant stats
|
||||||
for account_id, kill_count in self._account_kills.items():
|
for account_id, kill_count in self._account_kills.items():
|
||||||
|
|
@ -248,8 +259,6 @@ class UpdateThread(threading.Thread):
|
||||||
# though it may be smart to refresh it periodically since
|
# though it may be smart to refresh it periodically since
|
||||||
# it may change)
|
# it may change)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
stats[account_id] = {'rank': 0,
|
stats[account_id] = {'rank': 0,
|
||||||
'name': "deafult name",
|
'name': "deafult name",
|
||||||
'scores': 0,
|
'scores': 0,
|
||||||
|
|
@ -259,22 +268,22 @@ class UpdateThread(threading.Thread):
|
||||||
'games': 0,
|
'games': 0,
|
||||||
'kd': 0,
|
'kd': 0,
|
||||||
'avg_score': 0,
|
'avg_score': 0,
|
||||||
'last_seen':str(datetime.datetime.now()),
|
'last_seen': str(datetime.datetime.now()),
|
||||||
'aid': str(account_id)}
|
'aid': str(account_id)}
|
||||||
|
|
||||||
#Temporary codes to change 'name_html' to 'name'
|
# Temporary codes to change 'name_html' to 'name'
|
||||||
# if 'name_html' in stats[account_id]:
|
# if 'name_html' in stats[account_id]:
|
||||||
# stats[account_id].pop('name_html')
|
# stats[account_id].pop('name_html')
|
||||||
# stats[account_id]['name'] = 'default'
|
# stats[account_id]['name'] = 'default'
|
||||||
url="http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID="+account_id
|
url = "http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID=" + account_id
|
||||||
data=urllib.request.urlopen(url)
|
data = urllib.request.urlopen(url)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
try:
|
try:
|
||||||
name=json.loads(data.read())["profileDisplayString"]
|
name = json.loads(data.read())["profileDisplayString"]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
stats[account_id]['name']= "???"
|
stats[account_id]['name'] = "???"
|
||||||
else:
|
else:
|
||||||
stats[account_id]['name']= name
|
stats[account_id]['name'] = name
|
||||||
|
|
||||||
# now increment their kills whether they were already there or not
|
# now increment their kills whether they were already there or not
|
||||||
|
|
||||||
|
|
@ -292,32 +301,31 @@ class UpdateThread(threading.Thread):
|
||||||
# aaand that's it! There IS no step 27!
|
# aaand that's it! There IS no step 27!
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
update_time = now.strftime("%S:%M:%H - %d %b %y")
|
update_time = now.strftime("%S:%M:%H - %d %b %y")
|
||||||
#print(f"Added {str(len(self._account_kills))} account's stats entries. || {str(update_time)}")
|
# print(f"Added {str(len(self._account_kills))} account's stats entries. || {str(update_time)}")
|
||||||
refreshStats()
|
refreshStats()
|
||||||
|
|
||||||
|
|
||||||
def getRank(acc_id):
|
def getRank(acc_id):
|
||||||
global ranks
|
global ranks
|
||||||
if ranks==[]:
|
if ranks == []:
|
||||||
refreshStats()
|
refreshStats()
|
||||||
if acc_id in ranks:
|
if acc_id in ranks:
|
||||||
return ranks.index(acc_id)+1
|
return ranks.index(acc_id) + 1
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def updateTop3Names(ids):
|
def updateTop3Names(ids):
|
||||||
global top3Name
|
global top3Name
|
||||||
names=[]
|
names = []
|
||||||
for id in ids:
|
for id in ids:
|
||||||
url="http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID="+id
|
url = "http://bombsquadgame.com/bsAccountInfo?buildNumber=20258&accountID=" + id
|
||||||
data=urllib.request.urlopen(url)
|
data = urllib.request.urlopen(url)
|
||||||
if data is not None:
|
if data is not None:
|
||||||
try:
|
try:
|
||||||
name=json.loads(data.read())["profileDisplayString"]
|
name = json.loads(data.read())["profileDisplayString"]
|
||||||
except ValueError:
|
except ValueError:
|
||||||
names.append("???")
|
names.append("???")
|
||||||
else:
|
else:
|
||||||
names.append(name)
|
names.append(name)
|
||||||
top3Name=names
|
top3Name = names
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue