mirror of
https://github.com/norohind/ED-livery-tracker-advanced.git
synced 2025-04-13 07:47:16 +03:00
WIP
This commit is contained in:
commit
79068e6f37
7
config.py
Normal file
7
config.py
Normal file
@ -0,0 +1,7 @@
|
||||
import os
|
||||
|
||||
postgres_username = os.getenv('DB_USERNAME')
|
||||
postgres_password = os.getenv('DB_PASSWORD')
|
||||
postgres_hostname = os.getenv('DB_HOSTNAME')
|
||||
postgres_port = os.getenv('DB_PORT')
|
||||
postgres_database_name = os.getenv('DB_DATABASE')
|
36
get_livery_content.py
Normal file
36
get_livery_content.py
Normal file
@ -0,0 +1,36 @@
|
||||
from model import model
|
||||
import requests
|
||||
import os
|
||||
import json
|
||||
import datetime
|
||||
|
||||
model.open_model()
|
||||
|
||||
|
||||
def get_onlinestore_data() -> list[dict]:
|
||||
items = list()
|
||||
for item in requests.get("https://api.zaonce.net/3.0/store/product").json():
|
||||
items.append(dict(name=item["title"], cur_price=item["current_price"], orig_price=item["original_price"],
|
||||
image=item["image"]))
|
||||
print(f"Got {len(items)} items")
|
||||
return items
|
||||
|
||||
|
||||
def history_insert() -> None:
|
||||
for file in sorted(os.listdir('history')):
|
||||
with open('history\\' + file, 'r') as open_file:
|
||||
content = json.load(open_file)
|
||||
if 'image' not in content[0].keys():
|
||||
for item in content:
|
||||
item['image'] = ''
|
||||
|
||||
timestamp = datetime.datetime.utcfromtimestamp(int(file.split('.')[0])).strftime('%Y-%m-%dT%H:%M:%SZ')
|
||||
for item in content:
|
||||
item['timestamp'] = timestamp
|
||||
|
||||
model.insert_livery_timestamp(content)
|
||||
|
||||
|
||||
model.insert_livery(get_onlinestore_data())
|
||||
|
||||
model.close_model()
|
4
model/__init__.py
Normal file
4
model/__init__.py
Normal file
@ -0,0 +1,4 @@
|
||||
from model.postgres_model import PostgresModel
|
||||
|
||||
model = PostgresModel()
|
||||
|
25
model/abstract_model.py
Normal file
25
model/abstract_model.py
Normal file
@ -0,0 +1,25 @@
|
||||
import abc
|
||||
|
||||
|
||||
class AbstractModel(abc.ABC):
|
||||
|
||||
@abc.abstractmethod
|
||||
def open_model(self) -> None:
|
||||
raise NotImplemented
|
||||
|
||||
@abc.abstractmethod
|
||||
def close_model(self) -> None:
|
||||
raise NotImplemented
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_activity_changes(self, platform: str, leaderboard_type: str, limit: int, low_timestamp, high_timestamp)\
|
||||
-> list:
|
||||
raise NotImplemented
|
||||
|
||||
@abc.abstractmethod
|
||||
def insert_livery(self, livery_list: list) -> None:
|
||||
raise NotImplemented
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_diff_action_id(self, action_id: int) -> list:
|
||||
raise NotImplemented
|
145
model/postgres_model.py
Normal file
145
model/postgres_model.py
Normal file
@ -0,0 +1,145 @@
|
||||
import json
|
||||
import typing
|
||||
|
||||
import psycopg2.extensions
|
||||
import psycopg2.extras
|
||||
import config
|
||||
|
||||
from . import postgres_sql_requests
|
||||
from .abstract_model import AbstractModel
|
||||
|
||||
|
||||
def errors_catcher(func: callable) -> callable:
|
||||
def decorated(*args, **kwargs):
|
||||
try:
|
||||
result = func(*args, **kwargs)
|
||||
|
||||
except psycopg2.InterfaceError:
|
||||
args[0].open_model()
|
||||
result = func(*args, **kwargs)
|
||||
|
||||
return result
|
||||
|
||||
return decorated
|
||||
|
||||
|
||||
class PostgresModel(AbstractModel):
|
||||
db: psycopg2.extensions.connection
|
||||
|
||||
def open_model(self):
|
||||
self.db: psycopg2.extensions.connection = psycopg2.connect(
|
||||
user=config.postgres_username,
|
||||
password=config.postgres_password,
|
||||
host=config.postgres_hostname,
|
||||
port=config.postgres_port,
|
||||
database=config.postgres_database_name,
|
||||
cursor_factory=psycopg2.extras.DictCursor)
|
||||
|
||||
print(f'Connected to {self.db.dsn}')
|
||||
|
||||
with self.db:
|
||||
with self.db.cursor() as cursor:
|
||||
cursor.execute(postgres_sql_requests.schema_create) # schema creation
|
||||
|
||||
def close_model(self):
|
||||
self.db.close()
|
||||
print(f'Connection to {self.db.dsn} closed successfully')
|
||||
|
||||
@errors_catcher
|
||||
def get_activity_changes(self, platform: str, leaderboard_type: str, limit: int, low_timestamp, high_timestamp)\
|
||||
-> list:
|
||||
|
||||
with self.db:
|
||||
with self.db.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cursor:
|
||||
cursor.execute(postgres_sql_requests.select_activity_pretty_names, {
|
||||
'LB_type': utils.LeaderboardTypes(leaderboard_type.lower()).value,
|
||||
'platform': utils.Platform(platform.upper()).value,
|
||||
'limit': limit,
|
||||
'high_timestamp': high_timestamp,
|
||||
'low_timestamp': low_timestamp
|
||||
})
|
||||
|
||||
result: list = cursor.fetchall()
|
||||
|
||||
return result
|
||||
|
||||
@errors_catcher
|
||||
def insert_livery(self, livery_list: list) -> None:
|
||||
"""
|
||||
Takes livery content as list insert to DB
|
||||
|
||||
:param livery_list: list from get_onlinestore_data
|
||||
:return:
|
||||
"""
|
||||
|
||||
action_id: int # not last, current that we will use
|
||||
|
||||
with self.db.cursor() as cursor:
|
||||
cursor.execute(postgres_sql_requests.select_last_action_id)
|
||||
action_id_fetch_one: typing.Union[None, dict[str, int]] = cursor.fetchone()
|
||||
|
||||
if action_id_fetch_one is None:
|
||||
# i.e. first launch
|
||||
action_id = 1 # yep, not 0
|
||||
|
||||
else:
|
||||
action_id = action_id_fetch_one['action_id'] + 1
|
||||
|
||||
# Patch for additional values
|
||||
for squad in livery_list:
|
||||
squad.update({'action_id': action_id})
|
||||
|
||||
with self.db:
|
||||
with self.db.cursor() as cursor:
|
||||
cursor.executemany(
|
||||
postgres_sql_requests.insert_leader_board,
|
||||
livery_list)
|
||||
|
||||
@errors_catcher
|
||||
def insert_livery_timestamp(self, livery_list: list) -> None:
|
||||
"""
|
||||
Takes livery content with timestamps as list insert to DB. Helpful for historical data
|
||||
|
||||
:param livery_list: list from get_onlinestore_data
|
||||
:return:
|
||||
"""
|
||||
|
||||
action_id: int # not last, current that we will use
|
||||
|
||||
with self.db.cursor() as cursor:
|
||||
cursor.execute(postgres_sql_requests.select_last_action_id)
|
||||
action_id_fetch_one: typing.Union[None, dict[str, int]] = cursor.fetchone()
|
||||
|
||||
if action_id_fetch_one is None:
|
||||
# i.e. first launch
|
||||
action_id = 1 # yep, not 0
|
||||
|
||||
else:
|
||||
action_id = action_id_fetch_one['action_id'] + 1
|
||||
|
||||
# Patch for additional values
|
||||
for squad in livery_list:
|
||||
squad.update({'action_id': action_id})
|
||||
|
||||
with self.db:
|
||||
with self.db.cursor() as cursor:
|
||||
cursor.executemany(
|
||||
postgres_sql_requests.insert_leader_board_timestamp,
|
||||
livery_list)
|
||||
|
||||
@errors_catcher
|
||||
def get_diff_action_id(self, action_id: int) -> list:
|
||||
"""
|
||||
Takes action_id and returns which squadrons has been changed in leaderboard as in action_id and
|
||||
experience they got in compassion to action_id - 1 for the same leaderboard and platform
|
||||
|
||||
:param action_id:
|
||||
:return:
|
||||
"""
|
||||
|
||||
with self.db:
|
||||
with self.db.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cursor:
|
||||
cursor.execute(postgres_sql_requests.select_diff_by_action_id, {'action_id': action_id})
|
||||
result: list = cursor.fetchall()
|
||||
|
||||
return result
|
69
model/postgres_sql_requests.py
Normal file
69
model/postgres_sql_requests.py
Normal file
@ -0,0 +1,69 @@
|
||||
schema_create = """create table if not exists livery (
|
||||
action_id integer,
|
||||
name text,
|
||||
cur_price integer,
|
||||
orig_price integer,
|
||||
image_url text,
|
||||
timestamp timestamp default timezone('utc', now()));
|
||||
|
||||
--create index if not exists idx_action_id_0 on squads_stats_states (action_id);
|
||||
--create index if not exists idx_platform_leaderboard_type_1 on squads_stats_states(platform, leaderboard_type);
|
||||
"""
|
||||
|
||||
select_last_action_id = """select action_id
|
||||
from livery
|
||||
order by action_id desc
|
||||
limit 1;"""
|
||||
|
||||
insert_leader_board = """insert into livery (action_id, name, cur_price, orig_price, image_url)
|
||||
values
|
||||
(%(action_id)s, %(name)s, %(cur_price)s, %(orig_price)s, %(image)s);"""
|
||||
|
||||
insert_leader_board_timestamp = """insert into livery (action_id, name, cur_price, orig_price, image_url, timestamp)
|
||||
values
|
||||
(%(action_id)s, %(name)s, %(cur_price)s, %(orig_price)s, %(image)s, %(timestamp)s);"""
|
||||
|
||||
select_activity_pretty_names = """select
|
||||
sum_score::bigint as "TotalExperience",
|
||||
to_char(timestamp, 'YYYY-MM-DD HH24:MI:SS') as "Timestamp UTC",
|
||||
action_id::bigint as "ActionId",
|
||||
sum_score_old::bigint as "TotalExperienceOld",
|
||||
(sum_score - sum_score_old)::bigint as "Diff"
|
||||
from
|
||||
(
|
||||
select
|
||||
sum_score,
|
||||
min(timestamp) as timestamp,
|
||||
action_id,
|
||||
lag (sum_score, 1) over (order by sum_score) sum_score_old
|
||||
from (
|
||||
select sum(cur_price) as sum_score, min(timestamp) as timestamp, action_id
|
||||
from livery
|
||||
group by action_id
|
||||
) as foo
|
||||
group by sum_score, action_id
|
||||
order by timestamp desc
|
||||
|
||||
) as foo1
|
||||
where (sum_score - sum_score_old) <> 0
|
||||
limit %(limit)s;"""
|
||||
|
||||
select_diff_by_action_id = """select
|
||||
new_livery.name as new_name,
|
||||
old_livery.name as old_name,
|
||||
new_livery.orig_price as new_orig_price,
|
||||
new_livery.cur_price as new_cur_price,
|
||||
old_livery.orig_price as old_orig_price,
|
||||
old_livery.cur_price as old_cur_price,
|
||||
new_livery.cur_price - old_livery.cur_price
|
||||
from (
|
||||
select *
|
||||
from livery
|
||||
where action_id = %(action_id)s) new_livery
|
||||
full join
|
||||
(
|
||||
select *
|
||||
from livery
|
||||
where action_id = %(action_id)s - 1
|
||||
) old_livery
|
||||
on new_livery.name = old_livery.name;"""
|
Loading…
x
Reference in New Issue
Block a user