-
Notifications
You must be signed in to change notification settings - Fork 16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat: recovery features #423
Changes from 4 commits
6b8b857
01fcc9f
dd9a44a
28f89e3
ebbb042
5bf49ab
c42a88a
1c907ef
9806c1a
7d14da2
a14b4fd
3a42de5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,71 @@ | ||
""" | ||
Parse backup memory CSV file of BSM SPORTident station generated by SI Config Plus | ||
|
||
-- Format: | ||
CSV, separator ";" | ||
Needed positions: card number (2), start (15), finish (21), splits (44): count of punches, (code + time) * n | ||
|
||
No;Read on;SIID;Start no;Clear CN;Clear DOW;Clear time;Clear_r CN;Clear_r DOW;Clear_r time;Check CN;Check DOW;Check time | ||
;Start CN;Start DOW;Start time;Start_r CN;Start_r DOW;Start_r time;Finish CN;Finish DOW;Finish time;Finish_r CN;Finish_r | ||
DOW;Finish_r time;Class;First name;Last name;Club;Country;Email;Date of birth;Sex;Phone;Street;ZIP;City;Hardware version | ||
;Software version;Battery date;Battery voltage;Clear count;Character set;SEL_FEEDBACK;No. of records;Record 1 CN;Record | ||
1 DOW;Record 1 time;Record 2 CN;Record 2 DOW;Record 2 time;Record 3 CN; | ||
|
||
-- Example: | ||
440;2023-12-17 11:59:02;2007313;;2;Su; 12:40:50;;;;2;Su; 12:40:50;;;;;;;1;Su; 14:50:45;;;;;2007313;SPORTident Ru;;;;;;;; | ||
;;;;;;;;;10;34;Su; 12:41:33;49;Su; 12:54:39;43;Su; 13:22:28;39;Su; 13:51:28;42;Su; 14:02:34;46;Su; 14:15:04;40;Su; 14:31 | ||
:03;47;Su; 14:39:54;37;Su; 14:47:02;90;Su; 14:49:21; | ||
|
||
""" | ||
from sportorg.common.otime import OTime | ||
from sportorg.gui.dialogs.file_dialog import get_open_file_name | ||
from sportorg.language import translate | ||
from sportorg.models.memory import ResultSportident, Split, race | ||
from sportorg.modules.sportident.fix_time_sicard_5 import fix_time | ||
from sportorg.utils.time import hhmmss_to_time | ||
|
||
POS_CARD = 2 | ||
POS_START = 15 | ||
POS_FINISH = 21 | ||
POS_COUNT = 44 | ||
race = race() | ||
|
||
|
||
def recovery(): | ||
file_name = get_open_file_name( | ||
translate('Open SPORTident master station backup file'), | ||
translate('CSV file (*.csv)'), | ||
False, | ||
) | ||
|
||
text_file = open(file_name, 'r') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Лучше сделать так. Ты же здесь файл даже не закрываешь) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ОК, согласен, можно было бы и закрыть файл ) Переделаю на Path |
||
lines = text_file.readlines() | ||
|
||
separator = ';' | ||
|
||
zero_time_val = race.get_setting('system_zero_time', (8, 0, 0)) | ||
zero_time = OTime( | ||
hour=zero_time_val[0], minute=zero_time_val[1], sec=zero_time_val[2] | ||
) | ||
|
||
for line in lines: | ||
tokens = line.split(separator) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. лучше использовать модуль csv в питоне, он вообще в питоне из коробки доступен) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. принято |
||
if tokens[0] == 'No' or len(tokens) < 45: | ||
continue | ||
|
||
res = ResultSportident() | ||
res.card_number = int(tokens[POS_CARD]) | ||
res.start_time = hhmmss_to_time(tokens[POS_START]) | ||
res.finish_time = hhmmss_to_time(tokens[POS_FINISH]) | ||
|
||
punch_count = int(tokens[POS_COUNT]) | ||
existing_punches = (len(tokens) - POS_COUNT - 1) // 3 | ||
|
||
for i in range(min(punch_count, existing_punches)): | ||
punch = Split() | ||
punch.code = tokens[POS_COUNT + 3 * i + 1] | ||
punch.time = hhmmss_to_time(tokens[POS_COUNT + 3 * i + 3]) | ||
res.splits.append(punch) | ||
|
||
fix_time(res, zero_time) | ||
race.results.append(res) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
""" | ||
Parse SportOrg HTML report (containing full json) | ||
|
||
""" | ||
import os.path | ||
import string | ||
from io import open | ||
from random import choices | ||
from tempfile import gettempdir | ||
|
||
from sportorg.gui.dialogs.file_dialog import get_open_file_name | ||
from sportorg.gui.dialogs.sportorg_import_dialog import SportOrgImportDialog | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. тут тоже самое. Надо инверсию зависимостей или передать готовые значения There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ок |
||
from sportorg.language import translate | ||
from sportorg.modules.backup.json import get_races_from_file | ||
|
||
|
||
def recovery(): | ||
file_name = get_open_file_name( | ||
translate('Open SportOrg HTML file'), | ||
translate('SportOrg HTML report (*.html)'), | ||
False, | ||
) | ||
|
||
text_file = open(file_name, 'r', encoding='utf-8') | ||
lines = text_file.readlines() | ||
|
||
for line in lines: | ||
if line.find("var race = {\"courses\":") > -1: | ||
json = line.strip()[11:-1] | ||
|
||
# save json to tmp file and op[en with standard import action | ||
tmp_filename = os.path.join( | ||
gettempdir(), | ||
'sportorg_' + ''.join(choices(string.ascii_letters, k=10)) + '.json', | ||
) | ||
temp_file = open(tmp_filename, 'w') | ||
temp_file.write(json) | ||
temp_file.close() | ||
|
||
with open(tmp_filename) as f: | ||
attr = get_races_from_file(f) | ||
SportOrgImportDialog(*attr).exec_() |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
""" | ||
Parse backup SI log generated in C:\\Program Files (x86)\\SportOrg\\log | ||
|
||
-- Format: | ||
|
||
start | ||
[SI_CARD] | ||
[START] - 0:00:00 if not exist | ||
[FINISH] - 0:00:00 if not exist | ||
split_start | ||
[CODE_1] [TIME_1] | ||
... | ||
[CODE_N] [TIME_N] | ||
split_end | ||
end | ||
|
||
-- Example: | ||
|
||
start | ||
8013787 | ||
00:00:00 | ||
11:39:25 | ||
split_start | ||
57 11:43:05 | ||
69 11:37:59 | ||
90 11:39:07 | ||
split_end | ||
end | ||
|
||
""" | ||
from sportorg.common.otime import OTime | ||
from sportorg.gui.dialogs.file_dialog import get_open_file_name | ||
from sportorg.language import translate | ||
from sportorg.models.memory import ResultSportident, Split, race | ||
from sportorg.modules.sportident.fix_time_sicard_5 import fix_time | ||
from sportorg.utils.time import hhmmss_to_time | ||
|
||
race = race() | ||
|
||
|
||
def recovery(): | ||
zero_time_val = race.get_setting('system_zero_time', (8, 0, 0)) | ||
zero_time = OTime( | ||
hour=zero_time_val[0], minute=zero_time_val[1], sec=zero_time_val[2] | ||
) | ||
|
||
file_name = get_open_file_name( | ||
translate('Open SportOrg SI log file'), | ||
translate('SportOrg SI log (*.log)'), | ||
False, | ||
) | ||
|
||
text_file = open(file_name, 'r') | ||
lines = text_file.readlines() | ||
|
||
cur_res = ResultSportident() | ||
read_num = False | ||
read_start = False | ||
read_spl = False | ||
read_finish = False | ||
|
||
for line in lines: | ||
line = line.strip() | ||
if read_num: | ||
cur_res.card_number = int(line) | ||
read_start = True | ||
read_num = False | ||
elif read_start: | ||
cur_res.start_time = hhmmss_to_time(line) | ||
read_start = False | ||
read_finish = True | ||
elif read_finish: | ||
cur_res.finish_time = hhmmss_to_time(line) | ||
read_finish = False | ||
elif line == 'end': | ||
fix_time(cur_res, zero_time) | ||
race.results.append(cur_res) | ||
cur_res = ResultSportident() | ||
elif line == 'start': | ||
read_num = True | ||
elif line == 'split_start': | ||
read_spl = True | ||
elif line == 'split_end': | ||
read_spl = False | ||
elif read_spl: | ||
spl = Split() | ||
spl.code = line.split(' ')[0] | ||
spl.time = hhmmss_to_time(line.split(' ')[1]) | ||
cur_res.splits.append(spl) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
from sportorg.common.otime import OTime | ||
|
||
DEF_START_TIME = OTime(hour=8) | ||
|
||
|
||
def if_si_card_5(card_number): | ||
return card_number < 1000000 | ||
|
||
|
||
def _fix_time(time, zero_time): | ||
""" | ||
takes nearest to zero time, assuming, that original time is in only 12h format (SPORTident SICard 5) | ||
exclude 00:00:00, meaning no time | ||
00:15:18 (10:00:00) -> 12:15:18 | ||
00:15:18 (14:00:00) -> 00:15:18 | ||
11:15:18 (10:00:00) -> 11:15:18 | ||
11:15:18 (17:00:00) -> 23:15:18 | ||
22:15:18 (10:00:00) -> 10:15:18 | ||
22:15:18 (11:00:00) -> 22:15:18 | ||
""" | ||
origin_time = time | ||
|
||
if time == OTime(0): | ||
return time | ||
|
||
time_12h = OTime(hour=12) | ||
|
||
if time >= time_12h: | ||
time -= time_12h | ||
|
||
if zero_time > time: | ||
if zero_time - time < time_12h: | ||
time += time_12h | ||
|
||
return time | ||
|
||
|
||
# fix time in result for SI Card 5 (12h format) | ||
def fix_time(res, zero_time=DEF_START_TIME): | ||
if if_si_card_5(res.card_number): | ||
res.finish_time = _fix_time(res.finish_time, zero_time) | ||
res.start_time = _fix_time(res.start_time, zero_time) | ||
|
||
for i in range(len(res.splits)): | ||
res.splits[i].time = _fix_time(res.splits[i].time, zero_time) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
эта функция не должна быть в modules. Лучше передай в recovery готовый путь. Должна быть правильная работа с зависимостями
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ОК, хорошо, буду передавать путь