diff --git a/languages/ru_RU/LC_MESSAGES/sportorg.po b/languages/ru_RU/LC_MESSAGES/sportorg.po
index cf095672..35e0a321 100644
--- a/languages/ru_RU/LC_MESSAGES/sportorg.po
+++ b/languages/ru_RU/LC_MESSAGES/sportorg.po
@@ -636,8 +636,8 @@ msgstr "Режим присвоения"
msgid "by time"
msgstr "по времени"
-msgid "by scores"
-msgstr "по баллам"
+msgid "by scores (rogaine)"
+msgstr "по баллам (рогейн)"
msgid "ardf"
msgstr "ADRF"
@@ -651,6 +651,9 @@ msgstr "фиксированные баллы за КП"
msgid "minute penalty"
msgstr "Штраф за каждую просроченную минуту"
+msgid "maximum overrun time"
+msgstr "Макс. превышение контрольного времени"
+
msgid "no penalty"
msgstr "штраф не начисляется"
@@ -756,6 +759,12 @@ msgstr "Командные результаты"
msgid "Scores"
msgstr "Очки"
+msgid "Points gained"
+msgstr "Набрано очков"
+
+msgid "Penalty for finishing late"
+msgstr "Штраф за превышение"
+
msgid "Penalty calculation"
msgstr "Штраф"
diff --git a/sportorg/gui/dialogs/timekeeping_properties.py b/sportorg/gui/dialogs/timekeeping_properties.py
index 5a1b4705..1e080ac1 100644
--- a/sportorg/gui/dialogs/timekeeping_properties.py
+++ b/sportorg/gui/dialogs/timekeeping_properties.py
@@ -109,12 +109,19 @@ def init_ui(self):
# result processing tab
self.result_proc_tab = QWidget()
self.result_proc_layout = QFormLayout()
+ self.result_processing_group = QGroupBox(translate('Result processing'))
+ self.result_processing_layout = QFormLayout()
self.rp_time_radio = QRadioButton(translate('by time'))
- self.result_proc_layout.addRow(self.rp_time_radio)
+ self.rp_time_radio.toggled.connect(self.rp_result_calculation_mode)
+ self.result_processing_layout.addRow(self.rp_time_radio)
self.rp_ardf_radio = QRadioButton(translate('ardf'))
- self.result_proc_layout.addRow(self.rp_ardf_radio)
- self.rp_scores_radio = QRadioButton(translate('by scores'))
- self.result_proc_layout.addRow(self.rp_scores_radio)
+ self.rp_ardf_radio.toggled.connect(self.rp_result_calculation_mode)
+ self.result_processing_layout.addRow(self.rp_ardf_radio)
+ self.rp_scores_radio = QRadioButton(translate('by scores (rogaine)'))
+ self.rp_scores_radio.toggled.connect(self.rp_result_calculation_mode)
+ self.result_processing_layout.addRow(self.rp_scores_radio)
+ self.result_processing_group.setLayout(self.result_processing_layout)
+ self.result_proc_layout.addRow(self.result_processing_group)
self.rp_scores_group = QGroupBox()
self.rp_scores_layout = QFormLayout(self.rp_scores_group)
@@ -130,6 +137,15 @@ def init_ui(self):
self.rp_scores_layout.addRow(
self.rp_scores_minute_penalty_label, self.rp_scores_minute_penalty_edit
)
+ self.rp_scores_max_overrun_time_label = QLabel(
+ translate('maximum overrun time')
+ )
+ self.rp_scores_max_overrun_time = AdvTimeEdit(
+ max_width=80, display_format='HH:mm:ss'
+ )
+ self.rp_scores_layout.addRow(
+ self.rp_scores_max_overrun_time_label, self.rp_scores_max_overrun_time
+ )
self.rp_scores_allow_duplicates = QCheckBox(translate('allow duplicates'))
self.rp_scores_allow_duplicates.setToolTip(
translate(
@@ -335,6 +351,12 @@ def on_assignment_mode(self):
self.chip_reading_box.setDisabled(mode)
self.chip_duplicate_box.setDisabled(mode)
+ def rp_result_calculation_mode(self):
+ if self.rp_scores_radio.isChecked():
+ self.rp_scores_group.show()
+ else:
+ self.rp_scores_group.hide()
+
def penalty_calculation_mode(self):
if (
self.mr_lap_station_check.isChecked()
@@ -455,6 +477,12 @@ def set_values_from_model(self):
rp_scores_minute_penalty = obj.get_setting(
'result_processing_scores_minute_penalty', 1
)
+ rp_scores_max_overrun_time = OTime(
+ msec=obj.get_setting(
+ 'result_processing_scores_max_overrun_time', 30 * 60 * 1000
+ )
+ )
+
rp_scores_allow_duplicates = obj.get_setting(
'result_processing_scores_allow_duplicates', False
)
@@ -473,6 +501,7 @@ def set_values_from_model(self):
self.rp_fixed_scores_edit.setValue(rp_fixed_scores_value)
self.rp_scores_minute_penalty_edit.setValue(rp_scores_minute_penalty)
+ self.rp_scores_max_overrun_time.setTime(rp_scores_max_overrun_time.to_time())
self.rp_scores_allow_duplicates.setChecked(rp_scores_allow_duplicates)
# penalty calculation
@@ -631,6 +660,10 @@ def apply_changes_impl(self):
rp_fixed_scores_value = self.rp_fixed_scores_edit.value()
rp_scores_minute_penalty = self.rp_scores_minute_penalty_edit.value()
+ rp_scores_max_overrun_time = (
+ self.rp_scores_max_overrun_time.getOTime().to_msec()
+ )
+
rp_scores_allow_duplicates = self.rp_scores_allow_duplicates.isChecked()
obj.set_setting('result_processing_mode', rp_mode)
@@ -639,6 +672,9 @@ def apply_changes_impl(self):
obj.set_setting(
'result_processing_scores_minute_penalty', rp_scores_minute_penalty
)
+ obj.set_setting(
+ 'result_processing_scores_max_overrun_time', rp_scores_max_overrun_time
+ )
obj.set_setting(
'result_processing_scores_allow_duplicates', rp_scores_allow_duplicates
)
diff --git a/sportorg/models/memory.py b/sportorg/models/memory.py
index 0a5524ff..927627cf 100644
--- a/sportorg/models/memory.py
+++ b/sportorg/models/memory.py
@@ -467,7 +467,8 @@ def __init__(self):
self.penalty_laps = 0 # count of penalty legs (marked route)
self.place = 0
self.scores = 0
- self.scores_rogain = 0
+ self.rogaine_score = 0
+ self.rogaine_penalty = 0
self.scores_ardf = 0
self.assigned_rank = Qualification.NOT_QUALIFIED
self.diff: Optional[OTime] = None # readonly
@@ -514,7 +515,7 @@ def __eq__(self, other) -> bool:
else:
return False
else: # process by score (rogain)
- eq = eq and self.scores_rogain == other.scores_rogain
+ eq = eq and self.rogaine_score == other.rogaine_score
if eq and self.get_start_time() and other.get_start_time():
eq = eq and self.get_start_time() == other.get_start_time()
if eq and self.get_finish_time() and other.get_finish_time():
@@ -548,10 +549,10 @@ def __gt__(self, other) -> bool: # greater is worse
else:
return self.scores_ardf < other.scores_ardf
else: # process by score (rogain)
- if self.scores_rogain == other.scores_rogain:
+ if self.rogaine_score == other.rogaine_score:
return self.get_result_otime() > other.get_result_otime()
else:
- return self.scores_rogain < other.scores_rogain
+ return self.rogaine_score < other.rogaine_score
@property
@abstractmethod
@@ -581,7 +582,8 @@ def to_dict(self):
'card_number': self.card_number,
'speed': self.speed, # readonly
'scores': self.scores, # readonly
- 'scores_rogain': self.scores_rogain, # readonly
+ 'rogaine_score': self.rogaine_score, # readonly
+ 'rogaine_penalty': self.rogaine_penalty, # readonly
'scores_ardf': self.scores_ardf, # readonly
'created_at': self.created_at, # readonly
'result': self.get_result(), # readonly
@@ -610,8 +612,10 @@ def update_data(self, data):
self.scores = data['scores']
if 'scores_ardf' in data and data['scores_ardf'] is not None:
self.scores_ardf = data['scores_ardf']
- if 'scores_rogain' in data and data['scores_rogain'] is not None:
- self.scores_rogain = data['scores_rogain']
+ if 'rogaine_score' in data and data['rogaine_score'] is not None:
+ self.rogaine_score = data['rogaine_score']
+ if 'rogaine_penalty' in data and data['rogaine_penalty'] is not None:
+ self.rogaine_penalty = data['rogaine_penalty']
if str(data['place']).isdigit():
self.place = int(data['place'])
self.assigned_rank = Qualification.get_qual_by_code(data['assigned_rank'])
@@ -665,7 +669,7 @@ def get_result(self) -> str:
if race().get_setting('result_processing_mode', 'time') == 'ardf':
ret += f"{self.scores_ardf} {translate('points')} "
elif race().get_setting('result_processing_mode', 'time') == 'scores':
- ret += f"{self.scores_rogain} {translate('points')} "
+ ret += f"{self.rogaine_score} {translate('points')} "
time_accuracy = race().get_setting('time_accuracy', 0)
ret += self.get_result_otime().to_str(time_accuracy)
@@ -684,7 +688,7 @@ def get_result_start_in_comment(self):
if race().get_setting('result_processing_mode', 'time') == 'ardf':
ret += f"{self.scores_ardf} {translate('points')} "
elif race().get_setting('result_processing_mode', 'time') == 'scores':
- ret += f"{self.scores_rogain} {translate('points')} "
+ ret += f"{self.rogaine_score} {translate('points')} "
# time_accuracy = race().get_setting('time_accuracy', 0)
start = hhmmss_to_time(self.person.comment)
@@ -720,7 +724,7 @@ def get_result_relay(self) -> str:
if race().get_setting('result_processing_mode', 'time') == 'ardf':
ret += f"{self.scores_ardf} {translate('points')} "
elif race().get_setting('result_processing_mode', 'time') == 'scores':
- ret += f"{self.scores_rogain} {translate('points')} "
+ ret += f"{self.rogaine_score} {translate('points')} "
time_accuracy = race().get_setting('time_accuracy', 0)
ret += self.get_result_otime_relay().to_str(time_accuracy)
diff --git a/sportorg/models/result/result_calculation.py b/sportorg/models/result/result_calculation.py
index cfb533ba..70962a13 100644
--- a/sportorg/models/result/result_calculation.py
+++ b/sportorg/models/result/result_calculation.py
@@ -73,8 +73,9 @@ def get_group_persons(self, group):
self._group_persons[group] = ret
return ret
- @staticmethod
- def set_places(array):
+ def set_places(self, array):
+ is_rogaine = self.race.get_setting('result_processing_mode', 'time') == 'scores'
+ is_ardf = self.race.get_setting('result_processing_mode', 'time') == 'ardf'
current_place = 1
last_place = 1
last_result = 0
@@ -86,7 +87,10 @@ def set_places(array):
if res.is_status_ok():
current_result = res.get_result_otime()
res.diff = current_result - array[0].get_result_otime()
- res.diff_scores = array[0].scores - res.scores
+ if is_rogaine:
+ res.diff_scores = array[0].rogaine_score - res.rogaine_score
+ elif is_ardf:
+ res.diff_scores = array[0].scores_ardf - res.scores_ardf
# skip if out of competition
if res.person.is_out_of_competition:
diff --git a/sportorg/models/result/result_checker.py b/sportorg/models/result/result_checker.py
index 50ba05db..39c27909 100644
--- a/sportorg/models/result/result_checker.py
+++ b/sportorg/models/result/result_checker.py
@@ -30,8 +30,18 @@ def check_result(self, result: ResultSportident):
result.scores_ardf = self.calculate_scores_ardf(result)
return True
elif race().get_setting('result_processing_mode', 'time') == 'scores':
- # process by score (rogain)
- result.scores_rogain = self.calculate_scores_rogain(result)
+ # process by score (rogaine)
+ allow_duplicates = race().get_setting(
+ 'result_processing_scores_allow_duplicates', False
+ )
+ penalty_step = race().get_setting(
+ 'result_processing_scores_minute_penalty', 1
+ )
+
+ score = self.calculate_rogaine_score(result, allow_duplicates)
+ penalty = self.calculate_rogaine_penalty(result, score, penalty_step)
+ result.rogaine_score = score - penalty
+ result.rogaine_penalty = penalty
return True
course = race().find_course(result)
@@ -73,10 +83,22 @@ def checking(cls, result):
result.status = ResultStatus.MISS_PENALTY_LAP
elif result.person.group and result.person.group.max_time.to_msec():
- if result.get_result_otime() > result.person.group.max_time:
- if race().get_setting('result_processing_mode', 'time') == 'time':
+ rp_mode = race().get_setting('result_processing_mode', 'time')
+ result_time = result.get_result_otime()
+ max_time = result.person.group.max_time
+ if rp_mode in ('time', 'ardf'):
+ if result_time > max_time:
result.status = ResultStatus.OVERTIME
- elif race().get_setting('result_processing_mode', 'time') == 'ardf':
+ elif rp_mode == 'scores':
+ max_overrun_time = OTime(
+ msec=race().get_setting(
+ 'result_processing_scores_max_overrun_time', 0
+ )
+ )
+ if (
+ max_overrun_time.to_msec() > 0
+ and result_time > max_time + max_overrun_time
+ ):
result.status = ResultStatus.OVERTIME
result.status_comment = StatusComments().get_status_default_comment(
@@ -332,19 +354,48 @@ def get_control_score(code):
return int(code) // 10 # score = code / 10
@staticmethod
- def calculate_scores_rogain(result):
- user_array = []
- ret = 0
+ def calculate_rogaine_score(result: Result, allow_duplicates: bool = False) -> int:
+ """
+ Calculates the rogaine score for a given result.
- allow_duplicates = race().get_setting(
- 'result_processing_scores_allow_duplicates', False
- )
+ Parameters:
+ result (Result): The result for which the rogaine score needs to be calculated.
+ allow_duplicates (bool, optional): Whether to allow duplicate control points. Defaults to False.
+
+ Returns:
+ int: The calculated rogaine score.
+
+ If `allow_duplicates` flag is `True`, the function allows duplicate control points
+ to be included in the score calculation.
+ """
+ user_array = []
+ score = 0
for cur_split in result.splits:
code = str(cur_split.code)
if code not in user_array or allow_duplicates:
user_array.append(code)
- ret += ResultChecker.get_control_score(code)
+ score += ResultChecker.get_control_score(code)
+
+ return score
+
+ @staticmethod
+ def calculate_rogaine_penalty(
+ result: Result, score: int, penalty_step: int = 1
+ ) -> int:
+ """
+ Calculates the penalty for a given result based on the participant's excess of a race time.
+
+ Parameters:
+ result (Result): The result for which the penalty needs to be calculated.
+ score (int): The competitor's score.
+ penalty_step (int, optional): The penalty points for each minute late. Defaults to 1.
+
+ Returns:
+ int: The calculated penalty for the result.
+
+ """
+ penalty = 0
if result.person and result.person.group:
user_time = result.get_result_otime()
max_time = result.person.group.max_time
@@ -352,13 +403,12 @@ def calculate_scores_rogain(result):
time_diff = user_time - max_time
seconds_diff = time_diff.to_sec()
minutes_diff = (seconds_diff + 59) // 60 # note, 1:01 = 2 minutes
- penalty_step = race().get_setting(
- 'result_processing_scores_minute_penalty', 1.0
- )
- ret -= minutes_diff * penalty_step
- if ret < 0:
- ret = 0
- return ret
+ penalty = minutes_diff * penalty_step
+
+ # result = score - penalty >= 0
+ penalty = min(penalty, score)
+
+ return penalty
@staticmethod
def calculate_scores_ardf(result):
diff --git a/sportorg/modules/live/orgeo.py b/sportorg/modules/live/orgeo.py
index a9820d2c..f1d20525 100644
--- a/sportorg/modules/live/orgeo.py
+++ b/sportorg/modules/live/orgeo.py
@@ -124,6 +124,10 @@ def _get_person_obj(data, race_data, result=None):
if race_data['settings']['result_processing_mode'] == 'ardf':
obj['score'] = result['scores_ardf']
+ elif race_data['settings']['result_processing_mode'] == 'scores':
+ obj['score'] = result['rogaine_score']
+ if result['rogaine_penalty'] > 0:
+ obj['penalty'] = str(result['rogaine_penalty'])
obj['result_status'] = (
RESULT_STATUS[int(result['status'])]
diff --git a/sportorg/modules/printing/printing.py b/sportorg/modules/printing/printing.py
index 6299d5d8..9af87e9c 100644
--- a/sportorg/modules/printing/printing.py
+++ b/sportorg/modules/printing/printing.py
@@ -3,8 +3,8 @@
import time
from multiprocessing import Process, Queue
-from PySide6.QtCore import QSizeF
-from PySide6.QtGui import QTextDocument
+from PySide6.QtCore import QMarginsF, QSizeF
+from PySide6.QtGui import QPageLayout, QTextDocument
from PySide6.QtPrintSupport import QPrinter
from PySide6.QtWidgets import QApplication
@@ -63,11 +63,13 @@ def run(self):
printer.setFullPage(True)
printer.setPageMargins(
- self.margin_left,
- self.margin_top,
- self.margin_right,
- self.margin_bottom,
- QPrinter.Millimeter,
+ QMarginsF(
+ self.margin_left,
+ self.margin_top,
+ self.margin_right,
+ self.margin_bottom,
+ ),
+ QPageLayout.Unit.Millimeter,
)
page_size = QSizeF()
diff --git a/sportorg/modules/printing/printout_split.py b/sportorg/modules/printing/printout_split.py
index 6f636fba..dd73e8ff 100644
--- a/sportorg/modules/printing/printout_split.py
+++ b/sportorg/modules/printing/printout_split.py
@@ -141,7 +141,7 @@ def print_penalty_line(self, result: Result) -> None:
self.move_cursor(font_size * 1.3)
self.end_page()
- def print_split_normal(self, result):
+ def print_split_normal(self, result: Result):
obj = race()
person = result.person
@@ -164,6 +164,7 @@ def print_split_normal(self, result):
is_relay = group.is_relay()
fn = 'Lucida Console'
+ fs_small = 2.5
fs_main = 3
fs_large = 4
@@ -284,6 +285,21 @@ def print_split_normal(self, result):
fs_main,
)
+ is_rogaine = race().get_setting('result_processing_mode', 'time') == 'scores'
+ if is_rogaine and result.rogaine_penalty > 0:
+ penalty = result.rogaine_penalty
+ total_score = result.rogaine_score + penalty
+ self.print_line(
+ translate('Points gained') + ': ' + str(total_score),
+ fn,
+ fs_main,
+ )
+ self.print_line(
+ translate('Penalty for finishing late') + ': ' + str(penalty),
+ fn,
+ fs_main,
+ )
+
if result.is_status_ok():
self.print_line(
translate('Result')
@@ -325,7 +341,12 @@ def print_split_normal(self, result):
self.print_line(place, fn, fs_main)
# Info about competitors, who can win current person
- if result.is_status_ok() and not is_relay and is_group_existed:
+ if (
+ result.is_status_ok()
+ and not is_relay
+ and not is_rogaine
+ and is_group_existed
+ ):
if obj.get_setting('system_start_source', 'protocol') == 'protocol':
if hasattr(result, 'can_win_count'):
if result.can_win_count > 0:
@@ -376,7 +397,7 @@ def print_split_normal(self, result):
+ ' '
+ cur_res.get_result(),
fn,
- fs_main,
+ fs_main if not is_rogaine else fs_small,
)
self.print_line(obj.data.url, fn, fs_main)
diff --git "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262.html" "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262.html"
index 5ff278c5..ba2b5e42 100644
--- "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262.html"
+++ "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262.html"
@@ -36,6 +36,9 @@
ПРОТОКОЛ РЕЗУЛЬТАТОВ
var selected = {% endraw %}{{selected|tojson}}{%raw %};
racePreparation(race);
+ var isRogaine = race.settings.result_processing_mode === 'scores';
+ var isArdf = race.settings.result_processing_mode === 'ardf';
+
function getResultsByGroup(group, count) {
count = +count || 0;
var isRelay = group.__type ? group.__type === 3 : race.data.race_type === 3;
@@ -53,10 +56,13 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
result: result.result_current,
result_relay: result.result_relay,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -73,6 +79,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
r.speed = '';
r.speed_kmh = '';
r.scores = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -164,8 +173,11 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -224,9 +236,12 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
scores_ardf: result.scores_ardf,
- result: result.result,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
+ result: result.result_current,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -243,6 +258,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
r.speed = '';
r.speed_kmh = '';
r.scores = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -309,8 +327,11 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -320,6 +341,12 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
if (b.place < 1) {
return -1
}
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
+ }
return a.result_msec - b.result_msec;
}
});
@@ -346,10 +373,16 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
results.push(r);
}
} else {
+ var get_score = function(res){
+ if (isRogaine) return res.rogaine_score;
+ if (isArdf) return res.scores_ardf;
+ return 0
+ }
var newplace = 1;
var doubleplace = -1;
var best_result_msec = results[0] ? results[0].result_msec : 0;
var last_result_msec = results[0] ? results[0].result_msec : 0;
+ var best_score = results[0] ? get_score(results[0]) : 0;
var binary_search = function(arr,required){
if (!arr){
return 0;
@@ -373,14 +406,14 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
index++;
elem.index = index;
if (!elem.data.person.is_out_of_competition && elem.place !== 0 && elem.place !== -1) {
- if (last_result_msec < elem.result_msec){
+ if (isRogaine || isArdf || last_result_msec < elem.result_msec){
newplace += 1 + doubleplace;
doubleplace = 0;
last_result_msec = elem.result_msec;
} else {
doubleplace++;
}
- elem.diff = race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? elem.diff_scores : toHHMMSS(elem.result_msec - best_result_msec);
+ elem.diff = isRogaine || isArdf ? best_score - get_score(elem) : toHHMMSS(elem.result_msec - best_result_msec);
elem.place = newplace;
elem.place_show = newplace;
}
@@ -484,10 +517,13 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
{key: 'bib', title: 'Номер', size: 6},
{key: 'penalty_time', title: 'Штраф', size: 9, active: false},
{key: 'penalty_laps', title: 'Штраф', size: 9, active: false},
- {key: 'scores_ardf', title: 'КП', size: 3, active: race.settings.result_processing_mode === 'ardf'},
+ {key: 'scores_ardf', title: 'КП', size: 3, active: isArdf},
+ {key: 'rogaine_points_earned', title: 'Очки', size: 4, active: isRogaine},
+ {key: 'rogaine_penalty', title: 'Штр.', size: 4, active: isRogaine},
+ {key: 'rogaine_score', title: 'Итог', size: 4, active: isRogaine},
{key: 'result', title: 'Результат', size: 17},
{key: 'result_relay', title: 'Ком. рез-т', size: 14},
- {key: 'diff', title: 'Отставание', size: 11, active: race.settings.result_processing_mode !== 'ardf'},
+ {key: 'diff', title: 'Отставание', size: 11, active: !isArdf && !isRogaine},
{key: 'speed', title: 'Темп', size: 8, active: false},
{key: 'speed_kmh', title: 'Скорость', size: 8, active: false},
{key: 'place_show', title: 'Место', size: 6},
@@ -727,7 +763,7 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
}
},
{
- title: 'КП',
+ title: 'ARDF КП',
value: Fields.isActive('scores_ardf'),
change: function (checked) {
Fields.active('scores_ardf', checked);
diff --git "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\201\320\277\320\273\320\270\321\202\321\213.html" "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\201\320\277\320\273\320\270\321\202\321\213.html"
index f8b4b9c2..b08295d8 100644
--- "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\201\320\277\320\273\320\270\321\202\321\213.html"
+++ "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\201\320\277\320\273\320\270\321\202\321\213.html"
@@ -36,6 +36,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
var selected = {% endraw %}{{selected|tojson}}{%raw %};
racePreparation(race);
+ var isRogaine = race.settings.result_processing_mode === 'scores';
+ var isArdf = race.settings.result_processing_mode === 'ardf';
+
function getResultsByGroup(group, count) {
count = +count || 0;
var isRelay = group.__type ? group.__type === 3 : race.data.race_type === 3;
@@ -52,10 +55,14 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
year: result.person.birth_date ? (new Date(result.person.birth_date)).getFullYear() : '',
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
+ scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
result: result.result_current,
result_relay: result.result_relay,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -72,8 +79,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
r.speed = '';
r.speed_kmh = '';
r.scores = '';
- //r.penalty_time = '';
- //r.penalty_laps = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -165,8 +173,11 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -224,9 +235,13 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
year: result.person.birth_date ? (new Date(result.person.birth_date)).getFullYear() : '',
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
- result: result.result,
+ scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
+ result: result.result_current,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -243,8 +258,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
r.speed = '';
r.speed_kmh = '';
r.scores = '';
- //r.penalty_time = '';
- //r.penalty_laps = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -311,8 +327,11 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -322,6 +341,12 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
if (b.place < 1) {
return -1
}
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
+ }
return a.result_msec - b.result_msec;
}
});
@@ -348,10 +373,16 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
results.push(r);
}
} else {
+ var get_score = function(res){
+ if (isRogaine) return res.rogaine_score;
+ if (isArdf) return res.scores_ardf;
+ return 0
+ }
var newplace = 1;
var doubleplace = -1;
var best_result_msec = results[0] ? results[0].result_msec : 0;
var last_result_msec = results[0] ? results[0].result_msec : 0;
+ var best_score = results[0] ? get_score(results[0]) : 0;
var binary_search = function(arr,required){
if (!arr){
return 0;
@@ -375,14 +406,14 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
index++;
elem.index = index;
if (!elem.data.person.is_out_of_competition && elem.place !== 0 && elem.place !== -1) {
- if (last_result_msec < elem.result_msec){
+ if (isRogaine || isArdf || last_result_msec < elem.result_msec){
newplace += 1 + doubleplace;
doubleplace = 0;
last_result_msec = elem.result_msec;
} else {
doubleplace++;
}
- elem.diff = race.settings.result_processing_mode === 'scores' ? elem.diff_scores : toHHMMSS(elem.result_msec - best_result_msec);
+ elem.diff = isRogaine || isArdf ? best_score - get_score(elem) : toHHMMSS(elem.result_msec - best_result_msec);
elem.place = newplace;
elem.place_show = newplace;
}
@@ -486,9 +517,13 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
{key: 'bib', title: 'Номер', size: 6},
{key: 'penalty_time', title: 'Штраф', size: 9, active: false},
{key: 'penalty_laps', title: 'Штраф', size: 9, active: false},
+ {key: 'scores_ardf', title: 'КП', size: 3, active: isArdf},
+ {key: 'rogaine_points_earned', title: 'Очки', size: 4, active: isRogaine},
+ {key: 'rogaine_penalty', title: 'Штр.', size: 4, active: isRogaine},
+ {key: 'rogaine_score', title: 'Итог', size: 4, active: isRogaine},
{key: 'result', title: 'Результат', size: 17},
{key: 'result_relay', title: 'Ком. рез-т', size: 14},
- {key: 'diff', title: 'Отставание', size: 11},
+ {key: 'diff', title: 'Отставание', size: 11, active: !isArdf && !isRogaine},
{key: 'speed', title: 'Темп', size: 8, active: false},
{key: 'speed_kmh', title: 'Скорость', size: 8, active: false},
{key: 'place_show', title: 'Место', size: 6},
@@ -560,7 +595,6 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
} catch (e) {}
function render() {
-
var resultBlock = document.getElementById('results-tables');
resultBlock.innerHTML = '';
Fields.active('group', store.showProtocolByCourse);
@@ -635,7 +669,6 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
}
});
queryString += 'sportorg=1';
-
try {
var href = location.href.split('?')[0];
history.pushState({}, null, href + queryString);
@@ -733,6 +766,14 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
render()
}
},
+ {
+ title: 'ARDF КП',
+ value: Fields.isActive('scores_ardf'),
+ change: function (checked) {
+ Fields.active('scores_ardf', checked);
+ render()
+ }
+ },
{
title: 'Отставание',
value: Fields.isActive('diff'),
diff --git "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\202\320\265\321\200\320\274\320\276\320\277\321\200\320\270\320\275\321\202\320\265\321\200_80_\320\274\320\274.html" "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\202\320\265\321\200\320\274\320\276\320\277\321\200\320\270\320\275\321\202\320\265\321\200_80_\320\274\320\274.html"
index 3d0b96de..663b9a46 100644
--- "a/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\202\320\265\321\200\320\274\320\276\320\277\321\200\320\270\320\275\321\202\320\265\321\200_80_\320\274\320\274.html"
+++ "b/templates/reports/1_\320\277\321\200\320\276\321\202\320\276\320\272\320\276\320\273_\321\200\320\265\320\267\321\203\320\273\321\214\321\202\320\260\321\202\320\276\320\262_\321\202\320\265\321\200\320\274\320\276\320\277\321\200\320\270\320\275\321\202\320\265\321\200_80_\320\274\320\274.html"
@@ -36,6 +36,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
var selected = {% endraw %}{{selected|tojson}}{%raw %};
racePreparation(race);
+ var isRogaine = race.settings.result_processing_mode === 'scores';
+ var isArdf = race.settings.result_processing_mode === 'ardf';
+
function getResultsByGroup(group, count) {
count = +count || 0;
var isRelay = group.__type ? group.__type === 3 : race.data.race_type === 3;
@@ -52,9 +55,13 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
year: result.person.birth_date ? (new Date(result.person.birth_date)).getFullYear() : '',
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
- result: result.result,
+ scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
+ result: result.result_current,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -70,6 +77,9 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
r.scores = '';
r.penalty_time = '';
r.penalty_laps = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -166,8 +176,11 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -242,7 +255,7 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
var Fields = {
fields: [
- {key: 'index', title: '№', size: 4},
+ {key: 'index', title: '№', size: 3},
{key: 'name', title: 'Фамилия, имя', size: 20},
{key: 'org', title: 'Коллектив', size: 20, active: false},
{key: 'year', title: 'ГР', size: 5, active: false},
@@ -250,6 +263,10 @@ ПРОТОКОЛ РЕЗУЛЬТАТОВ
{key: 'bib', title: 'Номер', size: 6, active: false},
{key: 'penalty_time', title: 'Штраф', size: 9, active: false},
{key: 'penalty_laps', title: 'Штраф', size: 9, active: false},
+ {key: 'scores_ardf', title: 'КП', size: 3, active: isArdf},
+ {key: 'rogaine_points_earned', title: 'Очки', size: 4, active: false},
+ {key: 'rogaine_penalty', title: 'Штр.', size: 4, active: false},
+ {key: 'rogaine_score', title: 'Итог', size: 4, active: isRogaine},
{key: 'result', title: 'Результат', size: 10},
{key: 'diff', title: 'Отставание', size: 11, active: false},
{key: 'speed', title: 'Темп', size: 12, active: false},
diff --git a/templates/reports/ENG_1_results.html b/templates/reports/ENG_1_results.html
index 7209dc63..6b4942cb 100644
--- a/templates/reports/ENG_1_results.html
+++ b/templates/reports/ENG_1_results.html
@@ -38,6 +38,9 @@ RESULT LIST
var selected = {% endraw %}{{selected|tojson}}{%raw %};
racePreparation(race);
+ var isRogaine = race.settings.result_processing_mode === 'scores';
+ var isArdf = race.settings.result_processing_mode === 'ardf';
+
function getResultsByGroup(group, count) {
count = +count || 0;
var isRelay = group.__type ? group.__type === 3 : race.data.race_type === 3;
@@ -54,10 +57,14 @@ RESULT LIST
year: result.person.birth_date ? (new Date(result.person.birth_date)).getFullYear() : '',
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
- result: result.result,
+ scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
+ result: result.result_current,
result_relay: result.result_relay,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -71,8 +78,9 @@ RESULT LIST
r.place_show = '';
r.speed = '';
r.scores = '';
- r.penalty_time = '';
- r.penalty_laps = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -169,8 +177,11 @@ RESULT LIST
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -228,9 +239,13 @@ RESULT LIST
year: result.person.birth_date ? (new Date(result.person.birth_date)).getFullYear() : '',
penalty_time: toHHMMSS(result.penalty_time),
penalty_laps: result.penalty_laps,
- result: result.result,
+ scores_ardf: result.scores_ardf,
+ rogaine_score: result.rogaine_score,
+ rogaine_penalty: result.rogaine_penalty,
+ rogaine_points_earned: result.rogaine_score + result.rogaine_penalty,
+ result: result.result_current,
result_msec: result.result_msec,
- diff: race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? result.diff_scores : toHHMMSS(result.diff),
+ diff: isRogaine || isArdf ? result.diff_scores : toHHMMSS(result.diff),
place: result.place,
status: result.status,
scores: result.scores,
@@ -245,8 +260,9 @@ RESULT LIST
r.place_show = '';
r.speed = '';
r.scores = '';
- r.penalty_time = '';
- r.penalty_laps = '';
+ r.rogaine_points_earned = '';
+ r.rogaine_penalty = '';
+ r.rogaine_score = '';
}
// SPLITS
@@ -319,8 +335,11 @@ RESULT LIST
return -1
}
if (a.is_out_of_competition || b.is_out_of_competition) {
- if ((race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf') && a.scores !== b.scores) {
- return a.scores - b.scores;
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
}
return a.result_msec - b.result_msec;
}
@@ -330,6 +349,12 @@ RESULT LIST
if (b.place < 1) {
return -1
}
+ if (isRogaine && a.rogaine_score != b.rogaine_score) {
+ return -(a.rogaine_score - b.rogaine_score);
+ }
+ if (isArdf && a.scores_ardf != b.scores_ardf) {
+ return -(a.scores_ardf - b.scores_ardf);
+ }
return a.result_msec - b.result_msec;
}
});
@@ -356,10 +381,16 @@ RESULT LIST
results.push(r);
}
} else {
- var newplace = 1;
+ var get_score = function(res){
+ if (isRogaine) return res.rogaine_score;
+ if (isArdf) return res.scores_ardf;
+ return 0
+ }
+ var newplace = 1;
var doubleplace = -1;
var best_result_msec = results[0] ? results[0].result_msec : 0;
var last_result_msec = results[0] ? results[0].result_msec : 0;
+ var best_score = results[0] ? get_score(results[0]) : 0;
var binary_search = function(arr,required){
if (!arr){
return 0;
@@ -383,14 +414,14 @@ RESULT LIST
index++;
elem.index = index;
if (!elem.data.person.is_out_of_competition && elem.place !== 0 && elem.place !== -1) {
- if (last_result_msec < elem.result_msec){
+ if (isRogaine || isArdf || last_result_msec < elem.result_msec){
newplace += 1 + doubleplace;
doubleplace = 0;
last_result_msec = elem.result_msec;
} else {
doubleplace++;
}
- elem.diff = race.settings.result_processing_mode === 'scores' || race.settings.result_processing_mode === 'ardf' ? elem.diff_scores : toHHMMSS(elem.result_msec - best_result_msec);
+ elem.diff = isRogaine || isArdf ? best_score - get_score(elem) : toHHMMSS(elem.result_msec - best_result_msec);
elem.place = newplace;
elem.place_show = newplace;
}
@@ -483,9 +514,13 @@ RESULT LIST
{key: 'bib', title: 'Bib', size: 6},
{key: 'penalty_time', title: 'Penalty', size: 9, active: false},
{key: 'penalty_laps', title: 'Penalty,l', size: 9, active: false},
+ {key: 'scores_ardf', title: 'ARDF', size: 4, active: isArdf},
+ {key: 'rogaine_points_earned', title: 'Total', size: 5, active: isRogaine},
+ {key: 'rogaine_penalty', title: 'Pen.', size: 4, active: isRogaine},
+ {key: 'rogaine_score', title: 'Pts', size: 4, active: isRogaine},
{key: 'result', title: 'Result', size: 14},
{key: 'result_relay', title: 'Team result', size: 14},
- {key: 'diff', title: 'Diff', size: 11},
+ {key: 'diff', title: 'Diff', size: 11, active: !isArdf && !isRogaine},
{key: 'speed', title: 'Pace', size: 12, active: false},
{key: 'place_show', title: 'Place', size: 6},
{key: 'scores', title: 'Scores', size: 5, active: false},
diff --git a/templates/split/1_split_printout.html b/templates/split/1_split_printout.html
index 8f21c1d3..c1204db7 100644
--- a/templates/split/1_split_printout.html
+++ b/templates/split/1_split_printout.html
@@ -13,7 +13,7 @@
}
.small-text {
- font-size: 75%;
+ font-size: small;
}
p,
@@ -175,6 +175,10 @@ {{ person.surname }} {{ person.name }} - {{ group.name }}
{% endfor %}
Финиш: {{result.finish_msec|tohhmmss}} {{result.speed}}
+ {% if race['settings'].get('result_processing_mode', 'time') == 'scores' and result.rogaine_penalty > 0 %}
+
Набрано очков: {{result.rogaine_score + result.rogaine_penalty}}
+
Штраф за превышение: {{result.rogaine_penalty}}
+ {% endif%}
{% if race['settings'].get('marked_route_mode', 'off') == 'laps' %}
Штрафных кругов: {{result.penalty_laps}}
{% elif race['settings'].get('marked_route_mode', 'off') == 'time' %}
@@ -191,9 +195,7 @@ {{ person.surname }} {{ person.name }} - {{ group.name }}
Вас уже никто не обгонит!
{% endif %}
{% endif %}
-
{% endif %}
-
{% if result.status != 1 %}
{% for control in course.controls %}
{{control.code}}
@@ -202,7 +204,7 @@ ПЛОХАЯ ОТМЕТКА
{% else %}
ОТМЕТКА - OK
{% endif %}
-
+
{% for item in items %}
{% if item.result.place|int < 11 and item.result.place|int > 0 %}
diff --git a/tests/test_result_checking.py b/tests/test_result_checking.py
index f702a5b2..49e48b3c 100644
--- a/tests/test_result_checking.py
+++ b/tests/test_result_checking.py
@@ -1,13 +1,22 @@
from itertools import zip_longest
from typing import List, Union
+import pytest
+
+from sportorg.common.otime import OTime
from sportorg.models.memory import (
Course,
CourseControl,
+ Group,
Person,
+ Race,
ResultSportident,
Split,
+ create,
+ new_event,
+ race,
)
+from sportorg.models.result.result_checker import ResultChecker
def test_controls_as_int():
@@ -241,14 +250,7 @@ def test_course_free_order():
assert dsq(c, [31, 32, 32, 70])
assert dsq(c, [32, 33, 70])
assert dsq(c, [31, 32, 70])
- assert dsq(
- c,
- [
- 31,
- 32,
- 33,
- ],
- )
+ assert dsq(c, [31, 32, 33])
# Выбор + заданные КП
c = ['*(31,32,33)', '55', '*(31,32,33)']
@@ -362,6 +364,92 @@ def test_course_butterfly():
assert dsq(c, [31, 32, 41, 42, 33, 32, 51, 33, 70])
+@pytest.mark.parametrize(
+ 'controls, expected',
+ [
+ ([], 0),
+ ([31, 32, 33, 34], 12),
+ ([11, 22, 33, 44], 10),
+ ([31, 999, 34], 105),
+ ([31, 31, 33, 31, 33], 6),
+ ],
+)
+def test_calculate_rogaine_score(controls, expected):
+ create_race()
+ race().set_setting('result_processing_score_mode', 'rogain') # wrong spelling
+ res = make_result(controls)
+ assert ResultChecker.calculate_rogaine_score(res) == expected
+
+
+@pytest.mark.parametrize(
+ 'fixed_value, controls, expected',
+ [
+ (1, [], 0),
+ (1, [31, 32, 33, 34], 4),
+ (2, [31, 32, 33, 34], 8),
+ (1, [11, 22, 33, 44], 4),
+ (1, [31, 999, 34], 3),
+ (1, [31, 31, 33, 31, 33], 2),
+ ],
+)
+def test_calculate_fixed_score(fixed_value, controls, expected):
+ create_race()
+ race().set_setting('result_processing_score_mode', 'fixed')
+ race().set_setting('result_processing_fixed_score_value', fixed_value)
+ res = make_result(controls)
+ assert ResultChecker.calculate_rogaine_score(res) == expected
+
+
+@pytest.mark.parametrize(
+ 'score_mode, controls, expected',
+ [
+ ('rogain', [], 0),
+ ('rogain', [31, 31], 6),
+ ('rogain', [31, 32, 33, 34], 12),
+ ('rogain', [31, 31, 33, 31, 33], 15),
+ ('rogain', [11, 22, 33, 44], 10),
+ ('rogain', [11, 22, 33, 22, 44], 12),
+ ('fixed', [], 0),
+ ('fixed', [31, 31], 2),
+ ('fixed', [31, 32, 33, 34], 4),
+ ('fixed', [31, 31, 33, 31, 33], 5),
+ ('fixed', [11, 22, 33, 44], 4),
+ ('fixed', [11, 22, 33, 22, 44], 5),
+ ],
+)
+def test_calculate_score_allow_duplicates(score_mode, controls, expected):
+ create_race()
+ race().set_setting('result_processing_score_mode', score_mode)
+ race().set_setting('result_processing_fixed_score_value', 1)
+ res = make_result(controls)
+ assert ResultChecker.calculate_rogaine_score(res, allow_duplicates=True) == expected
+
+
+# fmt: off
+@pytest.mark.parametrize(
+ 'step, score, max_time, finish, expected',
+ [
+ (1, 5, (0, 1, 0, 0), (0, 0, 59, 59), 0),
+ (1, 5, (0, 1, 0, 0), (0, 1, 0, 0), 0),
+ (1, 5, (0, 1, 0, 0), (0, 1, 0, 1), 1),
+ (1, 5, (0, 1, 0, 0), (0, 1, 0, 30), 1),
+ (1, 5, (0, 1, 0, 0), (0, 1, 1, 0), 1),
+ (1, 5, (0, 1, 0, 0), (0, 1, 1, 1), 2),
+ (1, 5, (0, 1, 0, 0), (0, 1, 5, 1), 5),
+ (1, 5, (0, 1, 0, 0), (0, 1, 6, 1), 5), # penalty does not exceed total score
+ (1, 5, (0, 1, 0, 0), (0, 1, 15, 1), 5), # penalty does not exceed total score
+ ],
+)
+# fmt: on
+def test_calculate_rogaine_penalty(step, score, max_time, finish, expected):
+ create_race()
+ race().set_setting('result_processing_scores_minute_penalty', 1)
+ race().groups[0].max_time = OTime(*max_time)
+ result = race().results[0]
+ result.finish_time = OTime(*finish)
+ assert ResultChecker.calculate_rogaine_penalty(result, score, step) == expected
+
+
def test_non_obvious_behavior():
"""Неочевидное поведение при проверке дистанции. Не всегда это некорректная работа
алгоритма, иногда может возникать из-за недочётов при составлении курсов.
@@ -495,6 +583,19 @@ def check(
return check_result
+def create_race():
+ course = create(Course)
+ group = create(Group, course=course)
+ person = create(Person, group=group)
+ result = ResultSportident()
+ result.person = person
+ new_event([create(Race)])
+ race().courses.append(course)
+ race().groups.append(group)
+ race().persons.append(person)
+ race().results.append(result)
+
+
def make_course(course: List[Union[int, str]]) -> Course:
course_object = Course()
course_object.controls = make_course_controls(course)