summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoremkael <emkael@tlen.pl>2025-02-13 02:34:02 +0100
committeremkael <emkael@tlen.pl>2025-02-13 02:34:02 +0100
commit113c0b2976e845e401f0b115b87d8114fbb8b8a1 (patch)
treeaabeaad1996f54c42c364fda28c069e7bea852f4
parent06c0a51b191c35905c819ae839dcb357a446e500 (diff)
Adios, magic constants
-rw-r--r--http/api-inc.php199
1 files changed, 176 insertions, 23 deletions
diff --git a/http/api-inc.php b/http/api-inc.php
index 9b5a6ec..449874c 100644
--- a/http/api-inc.php
+++ b/http/api-inc.php
@@ -56,12 +56,90 @@ function run($parameters) {
class ApiPkl {
+ // constants for tournament ranks
+ const RANK_OTXxxxx = 7;
+ const RANK_OTXxxx = 6;
+ const RANK_OTXxx = 5;
+ const RANK_OTXx = 4;
+ const RANK_OTX = 3;
+ const RANK_REGIONAL = 2;
+ const RANK_DISTRICT = 1;
+ const RANK_CLUB = 0;
const RANK_KMP = 101;
const RANK_BNET = 102;
+ // constants for tournament (participant) types
+ const TYPE_INDIVIDUAL = 1;
+ const TYPE_PAIRS = 2;
+ const TYPE_TEAMS = 4;
+
+ // default tournament weights
+ const WEIGHT_CLUB_UNDER40 = 1;
+ const WEIGHT_DISTRICT_UNDER40 = 2;
+ const WEIGHT_REGIONAL_UNDER40 = 4;
+ const WEIGHT_OTX_UNDER40 = 5;
+ const WEIGHT_OTXx_UNDER40 = 7;
+ const WEIGHT_OTXxx_UNDER40 = 10;
+ const WEIGHT_OTXxxx_UNDER40 = 15;
+ const WEIGHT_OTXxxxx_UNDER40 = 25;
+ const WEIGHT_KMP_UNDER40 = 0;
+ const WEIGHT_BNET_UNDER40 = 1;
+ const WEIGHT_CLUB_OVER40 = 2;
+ const WEIGHT_DISTRICT_OVER40 = 3;
+ const WEIGHT_REGIONAL_OVER40 = 5;
+ const WEIGHT_OTX_OVER40 = 7;
+ const WEIGHT_OTXx_OVER40 = 10;
+ const WEIGHT_OTXxx_OVER40 = 15;
+ const WEIGHT_OTXxxx_OVER40 = 25;
+ const WEIGHT_OTXxxxx_OVER40 = 40;
+ const WEIGHT_KMP_OVER40 = 0;
+ const WEIGHT_BNET_OVER40 = 1; // not 2, according to MarcinW
+
+ // points for 1st place
+ const POINTS_CLUB_UNDER40 = 0;
+ const POINTS_DISTRICT_UNDER40 = 0;
+ const POINTS_REGIONAL_UNDER40 = 0;
+ const POINTS_OTX_UNDER40 = 0;
+ const POINTS_OTXx_UNDER40 = 50;
+ const POINTS_OTXxx_UNDER40 = 75;
+ const POINTS_OTXxxx_UNDER40 = 150;
+ const POINTS_OTXxxxx_UNDER40 = 200;
+ const POINTS_KMP_UNDER40 = 0;
+ const POINTS_BNET_UNDER40 = 0;
+ const POINTS_CLUB_OVER40 = 0;
+ const POINTS_DISTRICT_OVER40 = 0;
+ const POINTS_REGIONAL_OVER40 = 0;
+ const POINTS_OTX_OVER40 = 0;
+ const POINTS_OTXx_OVER40 = 70;
+ const POINTS_OTXxx_OVER40 = 100;
+ const POINTS_OTXxxx_OVER40 = 200;
+ const POINTS_OTXxxxx_OVER40 = 300;
+ const POINTS_KMP_OVER40 = 0;
+ const POINTS_BNET_OVER40 = 0;
+
// points for 1st place are 1.25x for teams
const TEAMS_BONUS = 0.25;
+ // coefficient for number of players
+ const PLAYERS_COEFFICIENT = 0.05;
+
+ // points regression cutoff points
+ const POINTS_CUTOFF_1 = 0.02;
+ const POINTS_CUTOFF_1_VALUE = 0.9;
+ const POINTS_CUTOFF_2 = 0.2;
+ const POINTS_CUTOFF_2_VALUE = 0.2;
+ const POINTS_CUTOFF_3 = 0.5;
+ const POINTS_CUTOFF_3_VALUE = 0.0;
+
+ // minimum for title (WK) average
+ const MINIMUM_AVG_TITLE = 0.15;
+
+ // bonus points for top KMP places
+ const KMP_BONUS_MINIMUM_AVG_TITLE = 2.5;
+ const KMP_BONUS_1ST = 5;
+ const KMP_BONUS_2ND = 3;
+ const KMP_BONUS_3RD = 1;
+
protected $parameters;
function __construct($parameters) {
@@ -108,7 +186,21 @@ class ApiPkl {
if (!isset($this->parameters['manual']) || !isset($this->parameters['manual']['tournament_weight'])) {
$this->ensure_parameters(array('tournament_rank', 'over39_boards'));
$this->check_values($this->parameters, array(
- 'tournament_rank' => function($r) { return is_integer_like($r) && ((intval($r) >= 0 && intval($r) <= 7) || in_array(intval($r), array(ApiPkl::RANK_KMP, ApiPkl::RANK_BNET))); },
+ 'tournament_rank' => function($r) {
+ return is_integer_like($r) &&
+ in_array(intval($r), array(
+ ApiPkl::RANK_OTXxxxx,
+ ApiPkl::RANK_OTXxxx,
+ ApiPkl::RANK_OTXxx,
+ ApiPkl::RANK_OTXx,
+ ApiPkl::RANK_OTX,
+ ApiPkl::RANK_REGIONAL,
+ ApiPkl::RANK_DISTRICT,
+ ApiPkl::RANK_CLUB,
+ ApiPkl::RANK_KMP,
+ ApiPkl::RANK_BNET
+ ));
+ },
'over39_boards' => function($r) { return is_integer_like($r) && intval($r) >= 0 && intval($r) <= 1; }
));
} else {
@@ -131,10 +223,12 @@ class ApiPkl {
function parse_parameters() {
$return = array();
$return['type'] = intval($this->parameters['type']);
- if ($return['type'] == 3 || $return['type'] > 4) {
+ if (!in_array($return['type'], array(
+ ApiPkl::TYPE_INDIVIDUAL, ApiPkl::TYPE_PAIRS, ApiPkl::TYPE_TEAMS
+ ))) {
throw new ParametersException('Parameter: type has incorrect value (' . $return['type'] . ')');
}
- if ($return['type'] != 2 && isset($this->parameters['tournament_rank']) && $this->parameters['tournament_rank'] == ApiPkl::RANK_KMP) {
+ if ($return['type'] != ApiPkl::TYPE_PAIRS && isset($this->parameters['tournament_rank']) && $this->parameters['tournament_rank'] == ApiPkl::RANK_KMP) {
throw new ParametersException('Parameter: type has incorrect value (' . $return['type'] . ') for KMP tournament');
}
if (isset($this->parameters['boards'])) {
@@ -144,8 +238,30 @@ class ApiPkl {
$return['players'] = isset($this->parameters['players']) ? intval($this->parameters['players']) : intval($this->parameters['contestants']) * $return['type'];
$return['title_sum'] = isset($this->parameters['title_sum']) ? floatval($this->parameters['title_sum']) : 0.0;
$weights = array(
- array(1, 2, 4, 5, 7, 10, 15, 25, ApiPkl::RANK_KMP => 0, ApiPkl::RANK_BNET => 1),
- array(2, 3, 5, 7, 10, 15, 25, 40, ApiPkl::RANK_KMP => 0, ApiPkl::RANK_BNET => 1) // not 2, according to MarcinW
+ array(
+ ApiPkl::RANK_OTXxxxx => static::WEIGHT_OTXxxxx_UNDER40,
+ ApiPkl::RANK_OTXxxx => static::WEIGHT_OTXxxx_UNDER40,
+ ApiPkl::RANK_OTXxx => static::WEIGHT_OTXxx_UNDER40,
+ ApiPkl::RANK_OTXx => static::WEIGHT_OTXx_UNDER40,
+ ApiPkl::RANK_OTX => static::WEIGHT_OTX_UNDER40,
+ ApiPkl::RANK_REGIONAL => static::WEIGHT_REGIONAL_UNDER40,
+ ApiPkl::RANK_DISTRICT => static::WEIGHT_DISTRICT_UNDER40,
+ ApiPkl::RANK_CLUB => static::WEIGHT_CLUB_UNDER40,
+ ApiPkl::RANK_KMP => static::WEIGHT_KMP_UNDER40,
+ ApiPkl::RANK_BNET => static::WEIGHT_BNET_UNDER40
+ ),
+ array(
+ ApiPkl::RANK_OTXxxxx => static::WEIGHT_OTXxxxx_OVER40,
+ ApiPkl::RANK_OTXxxx => static::WEIGHT_OTXxxx_OVER40,
+ ApiPkl::RANK_OTXxx => static::WEIGHT_OTXxx_OVER40,
+ ApiPkl::RANK_OTXx => static::WEIGHT_OTXx_OVER40,
+ ApiPkl::RANK_OTX => static::WEIGHT_OTX_OVER40,
+ ApiPkl::RANK_REGIONAL => static::WEIGHT_REGIONAL_OVER40,
+ ApiPkl::RANK_DISTRICT => static::WEIGHT_DISTRICT_OVER40,
+ ApiPkl::RANK_CLUB => static::WEIGHT_CLUB_OVER40,
+ ApiPkl::RANK_KMP => static::WEIGHT_KMP_OVER40,
+ ApiPkl::RANK_BNET => static::WEIGHT_BNET_OVER40
+ )
);
$return['tournament_weight'] = 0;
if (isset($this->parameters['manual']) && isset($this->parameters['manual']['tournament_weight'])) {
@@ -156,16 +272,38 @@ class ApiPkl {
}
}
$min_points = array(
- array(0, 0, 0, 0, 50, 75, 150, 200, ApiPkl::RANK_KMP => 0, ApiPkl::RANK_BNET => 0),
- array(0, 0, 0, 0, 70, 100, 200, 300, ApiPkl::RANK_KMP => 0, ApiPkl::RANK_BNET => 0)
+ array(
+ ApiPkl::RANK_OTXxxxx => static::POINTS_OTXxxxx_UNDER40,
+ ApiPkl::RANK_OTXxxx => static::POINTS_OTXxxx_UNDER40,
+ ApiPkl::RANK_OTXxx => static::POINTS_OTXxx_UNDER40,
+ ApiPkl::RANK_OTXx => static::POINTS_OTXx_UNDER40,
+ ApiPkl::RANK_OTX => static::POINTS_OTX_UNDER40,
+ ApiPkl::RANK_REGIONAL => static::POINTS_REGIONAL_UNDER40,
+ ApiPkl::RANK_DISTRICT => static::POINTS_DISTRICT_UNDER40,
+ ApiPkl::RANK_CLUB => static::POINTS_CLUB_UNDER40,
+ ApiPkl::RANK_KMP => static::POINTS_KMP_UNDER40,
+ ApiPkl::RANK_BNET => static::POINTS_BNET_UNDER40
+ ),
+ array(
+ ApiPkl::RANK_OTXxxxx => static::POINTS_OTXxxxx_OVER40,
+ ApiPkl::RANK_OTXxxx => static::POINTS_OTXxxx_OVER40,
+ ApiPkl::RANK_OTXxx => static::POINTS_OTXxx_OVER40,
+ ApiPkl::RANK_OTXx => static::POINTS_OTXx_OVER40,
+ ApiPkl::RANK_OTX => static::POINTS_OTX_OVER40,
+ ApiPkl::RANK_REGIONAL => static::POINTS_REGIONAL_OVER40,
+ ApiPkl::RANK_DISTRICT => static::POINTS_DISTRICT_OVER40,
+ ApiPkl::RANK_CLUB => static::POINTS_CLUB_OVER40,
+ ApiPkl::RANK_KMP => static::POINTS_KMP_OVER40,
+ ApiPkl::RANK_BNET => static::POINTS_BNET_OVER40
+ )
);
$return['min_points'] = (isset($this->parameters['manual']) && isset($this->parameters['manual']['min_points'])) ? intval($this->parameters['manual']['min_points']) : $min_points[intval($this->parameters['over39_boards'])][intval($this->parameters['tournament_rank'])];
- $return['players_coefficient'] = (isset($this->parameters['manual']) && isset($this->parameters['manual']['players_coefficient'])) ? floatval($this->parameters['manual']['players_coefficient']) : 0.05;
+ $return['players_coefficient'] = (isset($this->parameters['manual']) && isset($this->parameters['manual']['players_coefficient'])) ? floatval($this->parameters['manual']['players_coefficient']) : static::PLAYERS_COEFFICIENT;
$return['points_cutoffs'] = (isset($this->parameters['manual']) && isset($this->parameters['manual']['points_cutoffs']) && is_array($this->parameters['manual']['points_cutoffs'])) ? $this->parameters['manual']['points_cutoffs'] : array(
array(0.0, 1.0),
- array(0.02, 0.9),
- array(0.2, 0.2),
- array(0.5, 0.0)
+ array(static::POINTS_CUTOFF_1, static::POINTS_CUTOFF_1_VALUE),
+ array(static::POINTS_CUTOFF_2, static::POINTS_CUTOFF_2_VALUE),
+ array(static::POINTS_CUTOFF_3, static::POINTS_CUTOFF_3_VALUE)
);
recursive_ksort($return['points_cutoffs']);
if ($return['points_cutoffs'][0][0] != 0.0) {
@@ -216,13 +354,13 @@ class ApiPkl {
}
protected function _get_type_multiplier() {
- return (1 + static::TEAMS_BONUS * ($this->parameters['type'] > 2));
+ return (1 + static::TEAMS_BONUS * ($this->parameters['type'] == ApiPkl::TYPE_TEAMS));
}
protected function _get_max_points() {
return safe_ceil(max(
$this->parameters['min_points'],
- $this->_get_type_multiplier() * (max(0.15, $this->parameters['title_sum'] / $this->parameters['players']) * $this->parameters['tournament_weight'] + $this->parameters['players_coefficient'] * $this->parameters['contestants'] * $this->parameters['type'])
+ $this->_get_type_multiplier() * (max(static::MINIMUM_AVG_TITLE, $this->parameters['title_sum'] / $this->parameters['players']) * $this->parameters['tournament_weight'] + $this->parameters['players_coefficient'] * $this->parameters['contestants'] * $this->parameters['type'])
));
}
@@ -249,11 +387,11 @@ class ApiPkl {
$result['points'][$place] = max($min_points, $result['points'][$place-1]-1);
$result['sum'] += $this->parameters['type'] * $result['points'][$place];
}
- if ($this->parameters['title_sum'] / $this->parameters['players'] >= 2.5) {
- $result['points'][1] += 5;
- $result['points'][2] += 3;
- $result['points'][3] += 1;
- $result['sum'] += $this->parameters['type'] * 8;
+ if ($this->parameters['title_sum'] / $this->parameters['players'] >= static::KMP_BONUS_MINIMUM_AVG_TITLE) {
+ $result['points'][1] += static::KMP_BONUS_1ST;
+ $result['points'][2] += static::KMP_BONUS_2ND;
+ $result['points'][3] += static::KMP_BONUS_3RD;
+ $result['sum'] += $this->parameters['type'] * (static::KMP_BONUS_1ST + static::KMP_BONUS_2ND + static::KMP_BONUS_3RD);
}
return $result;
}
@@ -280,13 +418,22 @@ class ApiPklV1 extends ApiPkl {}
class ApiPklV2 extends ApiPklV1 {
+ // get rid of old KMP bonus point values
+ const KMP_BONUS_MINIMUM_AVG_TITLE = 99999;
+ const KMP_BONUS_2ND = 0;
+ const KMP_BONUS_3RD = 0;
+
+ // and (re-)define new bonus for 1st place
+ const KMP_BONUS_1ST = 10;
+
function calculate_kmp_points() {
// the line below works only because you can't play > 39 boards in KMP
// please kill me if it ever changes
- $this->parameters['tournament_weight'] = 4;
+ // (the condition, not the line - that one I've just changed)
+ $this->parameters['tournament_weight'] = static::WEIGHT_REGIONAL_UNDER40;
$this->parameters['min_points'] = 0;
$intermediate = $this->calculate_points();
- $this->parameters['min_points'] = $intermediate['points'][1] + 10;
+ $this->parameters['min_points'] = $intermediate['points'][1] + static::KMP_BONUS_1ST;
return $this->calculate_points();
}
@@ -294,9 +441,13 @@ class ApiPklV2 extends ApiPklV1 {
class ApiPklV3 extends ApiPklV2 {
+ // parameters for multiplication factor
+ const BNET_POINTS_FACTOR_QUOTIENT = 27.0;
+ const BNET_POINTS_FACTOR_CAP = 1.0;
+
protected function _bridgenet_parameters() {
$this->ensure_parameters(array('boards', 'type'));
- if ($this->parameters['type'] == 4) {
+ if ($this->parameters['type'] == ApiPkl::TYPE_TEAMS) {
throw new ParametersException('Parameter: type has incorrect value (' . $this->parameters['type'] . ') for BridgeNET tournament');
}
}
@@ -313,7 +464,7 @@ class ApiPklV3 extends ApiPklV2 {
}
function calculate_bridgenet_points() {
- $factor = min($this->parameters['boards'] / 27.0, 1.0);
+ $factor = min($this->parameters['boards'] / static::BNET_POINTS_FACTOR_QUOTIENT, static::BNET_POINTS_FACTOR_CAP);
return $this->calculate_points(0, $factor);
}
@@ -322,12 +473,14 @@ class ApiPklV3 extends ApiPklV2 {
// 2021.02.10 - do not discard BridgeNET local team tournaments, but check for board count
class ApiPklV3_1 extends ApiPklV3 {
+ const BNET_MINIMUM_BOARD_COUNT = 20;
+
protected function _bridgenet_parameters() {
$this->ensure_parameters(array('boards'));
$this->check_values($this->parameters, array(
'boards' => function($r) { return is_integer_like($r); }
));
- if (intval($this->parameters['boards']) < 20) {
+ if (intval($this->parameters['boards']) < static::BNET_MINIMUM_BOARD_COUNT) {
throw new ParametersException('At least 20 boards must be played in BridgeNET tournaments');
}
}