NexusDash-izebra/app/reports.py

380 lines
14 KiB
Python
Raw Permalink Normal View History

2022-03-13 02:09:35 +00:00
from flask import render_template, Blueprint, current_app
from flask_user import login_required
from app.models import CharacterInfo, Account, CharacterXML, Reports
2022-03-14 03:10:07 +00:00
from app.luclient import get_lot_name
2022-01-16 18:22:00 +00:00
from app import gm_level, scheduler
2022-03-14 03:10:07 +00:00
from sqlalchemy.orm import load_only
2023-11-18 11:46:50 +00:00
import xmltodict, gzip, json, datetime
2022-01-16 18:22:00 +00:00
reports_blueprint = Blueprint('reports', __name__)
2022-03-13 02:09:35 +00:00
2022-01-16 18:22:00 +00:00
@reports_blueprint.route('/', methods=['GET', 'POST'])
@login_required
@gm_level(3)
def index():
2022-03-14 03:10:07 +00:00
reports_items = Reports.query.distinct(
Reports.date
).filter(
Reports.report_type == "items"
).group_by(Reports.date).options(load_only(Reports.date)).all()
reports_currency = Reports.query.distinct(
Reports.date
).filter(
Reports.report_type == "currency"
).group_by(Reports.date).options(load_only(Reports.date)).all()
reports_uscore = Reports.query.distinct(
Reports.date
).filter(
Reports.report_type == "uscore"
).group_by(Reports.date).options(load_only(Reports.date)).all()
return render_template(
'reports/index.html.j2',
reports_items=reports_items,
reports_currency=reports_currency,
reports_uscore=reports_uscore,
)
2022-01-16 18:22:00 +00:00
2022-03-13 02:09:35 +00:00
2022-01-16 18:22:00 +00:00
@reports_blueprint.route('/items/by_date/<date>', methods=['GET', 'POST'])
@login_required
@gm_level(3)
def items_by_date(date):
2022-03-13 02:09:35 +00:00
data = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "items").first().data
2023-11-18 11:46:50 +00:00
data = gzip.decompress(data)
data = json.loads(data.decode('utf-8'))
return render_template('reports/items/by_date.html.j2', data=data, date=date)
2022-01-16 18:22:00 +00:00
2022-03-13 02:09:35 +00:00
2022-05-14 13:53:23 +00:00
@reports_blueprint.route('/items/graph/<start>/<end>', methods=['GET', 'POST'])
2022-03-14 03:10:07 +00:00
@login_required
@gm_level(3)
2022-05-14 13:53:23 +00:00
def items_graph(start, end):
start_date = datetime.date.today() - datetime.timedelta(weeks=int(start))
end_date = datetime.date.today() - datetime.timedelta(weeks=int(end))
2022-03-14 03:10:07 +00:00
entries = Reports.query.filter(
Reports.report_type == "items"
2022-05-14 13:53:23 +00:00
).filter(Reports.date.between(start_date, end_date)).all()
2022-03-14 03:10:07 +00:00
# transform data for chartjs
labels = []
items = dict()
datasets = []
# get stuff ready
for entry in entries:
2023-11-18 11:46:50 +00:00
entry.data = gzip.decompress(entry.data)
entry.data = json.loads(entry.data.decode('utf-8'))
2022-03-14 03:10:07 +00:00
labels.append(entry.date.strftime("%m/%d/%Y"))
for key in entry.data:
items[key] = get_lot_name(key)
# make it
for key, value in items.items():
2022-06-09 04:09:14 +00:00
if value:
data = []
for entry in entries:
if key in entry.data.keys():
if not isinstance(entry.data[key], int):
data.append(entry.data[key]["item_count"])
else:
data.append(entry.data[key])
else:
data.append(0)
color = "#" + value.encode("utf-8").hex()[1:7]
if max(data) > 10:
datasets.append({
"label": value,
"data": data,
"backgroundColor": color,
"borderColor": color
})
2022-03-14 03:10:07 +00:00
return render_template(
'reports/graph.html.j2',
labels=labels,
datasets=datasets,
2022-05-14 13:53:23 +00:00
name="Item",
start=start,
end=end,
data_type="items",
start_date=start_date,
end_date=end_date
2022-03-14 03:10:07 +00:00
)
2022-05-14 13:53:23 +00:00
@reports_blueprint.route('/currency/by_date/<date>', methods=['GET', 'POST'])
@login_required
@gm_level(3)
def currency_by_date(date):
2022-03-13 02:09:35 +00:00
data = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "currency").first().data
2023-11-18 11:46:50 +00:00
data = gzip.decompress(data)
data = json.loads(data.decode('utf-8'))
return render_template('reports/currency/by_date.html.j2', data=data, date=date)
2022-01-16 18:22:00 +00:00
2022-03-13 02:09:35 +00:00
2022-05-14 13:53:23 +00:00
@reports_blueprint.route('/currency/graph/<start>/<end>', methods=['GET', 'POST'])
2022-03-14 03:10:07 +00:00
@login_required
@gm_level(3)
2022-05-14 13:53:23 +00:00
def currency_graph(start, end):
start_date = datetime.date.today() - datetime.timedelta(weeks=int(start))
end_date = datetime.date.today() - datetime.timedelta(weeks=int(end))
2022-03-14 03:10:07 +00:00
entries = Reports.query.filter(
Reports.report_type == "currency"
2022-05-14 13:53:23 +00:00
).filter(Reports.date.between(start_date, end_date)).all()
2022-03-14 03:10:07 +00:00
characters = CharacterInfo.query.options(load_only(CharacterInfo.name)).all()
labels = []
datasets = []
# get stuff ready
for entry in entries:
2023-11-18 11:46:50 +00:00
entry.data = gzip.decompress(entry.data)
entry.data = json.loads(entry.data.decode('utf-8'))
2022-03-14 03:10:07 +00:00
labels.append(entry.date.strftime("%m/%d/%Y"))
for character in characters:
data = []
for entry in entries:
if character.name in entry.data.keys():
data.append(entry.data[character.name])
else:
data.append(0)
2022-05-14 13:53:23 +00:00
color = "#" + character.name.encode("utf-8").hex()[1:7]
if max(data) > 10000:
datasets.append({
"label": character.name,
"data": data,
"backgroundColor": color,
"borderColor": color
})
2022-03-14 03:10:07 +00:00
return render_template(
'reports/graph.html.j2',
labels=labels,
datasets=datasets,
2022-05-14 13:53:23 +00:00
name="Currency",
start=start,
end=end,
data_type="currency",
start_date=start_date,
end_date=end_date
2022-03-14 03:10:07 +00:00
)
2022-01-17 04:12:23 +00:00
@reports_blueprint.route('/uscore/by_date/<date>', methods=['GET', 'POST'])
@login_required
@gm_level(3)
def uscore_by_date(date):
2022-03-13 02:09:35 +00:00
data = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "uscore").first().data
2023-11-18 11:46:50 +00:00
data = gzip.decompress(data)
data = json.loads(data.decode('utf-8'))
2022-01-17 04:12:23 +00:00
return render_template('reports/uscore/by_date.html.j2', data=data, date=date)
2022-05-14 13:53:23 +00:00
@reports_blueprint.route('/uscore/graph/<start>/<end>', methods=['GET', 'POST'])
2022-03-14 03:10:07 +00:00
@login_required
@gm_level(3)
2022-05-14 13:53:23 +00:00
def uscore_graph(start, end):
start_date = datetime.date.today() - datetime.timedelta(weeks=int(start))
end_date = datetime.date.today() - datetime.timedelta(weeks=int(end))
2022-03-14 03:10:07 +00:00
entries = Reports.query.filter(
Reports.report_type == "uscore"
2022-05-14 13:53:23 +00:00
).filter(Reports.date.between(start_date, end_date)).all()
2022-03-14 03:10:07 +00:00
characters = CharacterInfo.query.options(load_only(CharacterInfo.name)).all()
labels = []
datasets = []
# get stuff ready
for entry in entries:
2023-11-18 11:46:50 +00:00
entry.data = gzip.decompress(entry.data)
entry.data = json.loads(entry.data.decode('utf-8'))
2022-03-14 03:10:07 +00:00
labels.append(entry.date.strftime("%m/%d/%Y"))
for character in characters:
data = []
for entry in entries:
if character.name in entry.data.keys():
data.append(entry.data[character.name])
else:
data.append(0)
2022-05-14 13:53:23 +00:00
color = "#" + character.name.encode("utf-8").hex()[1:7]
if max(data) > 1000:
datasets.append({
"label": character.name,
"data": data,
"backgroundColor": color,
"borderColor": color
})
2022-03-14 03:10:07 +00:00
return render_template(
'reports/graph.html.j2',
labels=labels,
datasets=datasets,
2022-05-14 13:53:23 +00:00
name="U-Score",
start=start,
end=end,
data_type="uscore",
start_date=start_date,
end_date=end_date
2022-03-14 03:10:07 +00:00
)
2022-02-12 06:30:12 +00:00
@scheduler.task("cron", id="gen_item_report", hour=23, timezone="UTC")
2022-01-16 18:22:00 +00:00
def gen_item_report():
2022-02-16 18:09:40 +00:00
with scheduler.app.app_context():
try:
current_app.logger.info("Start Item Report Generation")
date = datetime.date.today().strftime('%Y-%m-%d')
2022-03-13 02:09:35 +00:00
report = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "items").first()
# Only one report per day
2022-03-13 11:27:10 +00:00
if report is not None:
current_app.logger.info(f"Item Report Already Generated for {date}")
return
char_xmls = CharacterXML.query.join(
2022-03-13 02:09:35 +00:00
CharacterInfo,
CharacterInfo.id == CharacterXML.id
).join(
Account,
CharacterInfo.account_id == Account.id
).filter(Account.gm_level < 3).all()
2022-03-13 02:09:35 +00:00
report_data = {}
for char_xml in char_xmls:
2022-06-09 04:09:14 +00:00
name = CharacterInfo.query.filter(CharacterInfo.id == char_xml.id).first().name
try:
character_json = xmltodict.parse(
char_xml.xml_data,
attr_prefix="attr_"
)
for inv in character_json["obj"]["inv"]["items"]["in"]:
2022-03-13 02:09:35 +00:00
if "i" in inv.keys() and type(inv["i"]) == list and (int(inv["attr_t"]) == 0 or int(inv["attr_t"]) == 1):
for item in inv["i"]:
if item["attr_l"] in report_data:
if ("attr_c" in item):
report_data[item["attr_l"]]["item_count"] = report_data[item["attr_l"]]["item_count"] + int(item["attr_c"])
else:
report_data[item["attr_l"]]["item_count"] = report_data[item["attr_l"]]["item_count"] + 1
2022-06-09 04:09:14 +00:00
else:
if ("attr_c" in item):
report_data[item["attr_l"]] = {"item_count": int(item["attr_c"]), "chars": {}}
else:
report_data[item["attr_l"]] = {"item_count": 1, "chars": {}}
2022-06-09 04:09:14 +00:00
if name in report_data[item["attr_l"]]["chars"]:
if ("attr_c" in item):
report_data[item["attr_l"]]["chars"][name] = report_data[item["attr_l"]]["chars"][name] + int(item["attr_c"])
else:
report_data[item["attr_l"]]["chars"][name] = report_data[item["attr_l"]]["chars"][name] + 1
else:
if ("attr_c" in item):
report_data[item["attr_l"]]["chars"][name] = int(item["attr_c"])
else:
report_data[item["attr_l"]]["chars"][name] = 1
except Exception as e:
current_app.logger.error(f"REPORT::ITEMS - ERROR PARSING CHARACTER {char_xml.id}")
current_app.logger.error(f"REPORT::ITEMS - {e}")
new_report = Reports(
2023-11-18 11:46:50 +00:00
data=gzip.compress(json.dumps(report_data).encode('utf-8')),
report_type="items",
date=date
)
new_report.save()
2022-02-16 18:09:40 +00:00
current_app.logger.info(f"Generated Item Report for {date}")
except Exception as e:
current_app.logger.critical(f"REPORT::ITEMS - {e}")
return
2022-02-12 06:30:12 +00:00
@scheduler.task("cron", id="gen_currency_report", hour=23, timezone="UTC")
def gen_currency_report():
2022-02-16 18:09:40 +00:00
with scheduler.app.app_context():
try:
current_app.logger.info("Start Currency Report Generation")
date = datetime.date.today().strftime('%Y-%m-%d')
2022-03-13 02:09:35 +00:00
report = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "currency").first()
# Only one report per day
2022-03-13 11:27:10 +00:00
if report is not None:
current_app.logger.info(f"Currency Report Already Generated for {date}")
return
characters = CharacterXML.query.join(
2022-03-13 02:09:35 +00:00
CharacterInfo,
CharacterInfo.id == CharacterXML.id
).join(
Account,
CharacterInfo.account_id == Account.id
).filter(Account.gm_level < 3).all()
2022-03-13 02:09:35 +00:00
report_data = {}
for character in characters:
try:
character_json = xmltodict.parse(
character.xml_data,
attr_prefix="attr_"
)
2022-03-13 02:09:35 +00:00
report_data[CharacterInfo.query.filter(CharacterInfo.id == character.id).first().name] = int(character_json["obj"]["char"]["attr_cc"])
except Exception as e:
2022-03-13 12:03:50 +00:00
current_app.logger.error(f"REPORT::CURRENCY - ERROR PARSING CHARACTER {character.id}")
current_app.logger.error(f"REPORT::CURRENCY - {e}")
new_report = Reports(
2023-11-18 11:46:50 +00:00
data=gzip.compress(json.dumps(report_data).encode('utf-8')),
report_type="currency",
date=date
)
2022-01-17 00:49:28 +00:00
new_report.save()
2022-02-16 18:09:40 +00:00
current_app.logger.info(f"Generated Currency Report for {date}")
except Exception as e:
current_app.logger.critical(f"REPORT::CURRENCY - {e}")
return
2022-01-17 04:12:23 +00:00
2022-02-12 06:30:12 +00:00
@scheduler.task("cron", id="gen_uscore_report", hour=23, timezone="UTC")
2022-01-17 04:12:23 +00:00
def gen_uscore_report():
2022-02-16 18:09:40 +00:00
with scheduler.app.app_context():
try:
current_app.logger.info("Start U-Score Report Generation")
date = datetime.date.today().strftime('%Y-%m-%d')
2022-03-13 02:09:35 +00:00
report = Reports.query.filter(Reports.date == date).filter(Reports.report_type == "uscore").first()
# Only one report per day
2022-03-13 11:27:10 +00:00
if report is not None:
current_app.logger.info(f"U-Score Report Already Generated for {date}")
return
characters = CharacterXML.query.join(
2022-03-13 02:09:35 +00:00
CharacterInfo,
CharacterInfo.id == CharacterXML.id
).join(
Account,
CharacterInfo.account_id == Account.id
).filter(Account.gm_level < 3).all()
2022-03-13 02:09:35 +00:00
report_data = {}
for character in characters:
try:
character_json = xmltodict.parse(
character.xml_data,
attr_prefix="attr_"
)
2022-03-13 02:09:35 +00:00
report_data[CharacterInfo.query.filter(CharacterInfo.id == character.id).first().name] = int(character_json["obj"]["char"]["attr_ls"])
except Exception as e:
2022-03-13 12:03:50 +00:00
current_app.logger.error(f"REPORT::U-SCORE - ERROR PARSING CHARACTER {character.id}")
current_app.logger.error(f"REPORT::U-SCORE - {e}")
new_report = Reports(
2023-11-18 11:46:50 +00:00
data=gzip.compress(json.dumps(report_data).encode('utf-8')),
report_type="uscore",
date=date
2022-01-17 04:12:23 +00:00
)
new_report.save()
2022-02-16 18:09:40 +00:00
current_app.logger.info(f"Generated U-Score Report for {date}")
except Exception as e:
current_app.logger.critical(f"REPORT::U-SCORE - {e}")
return