diff options
author | emkael <emkael@tlen.pl> | 2025-02-13 02:34:02 +0100 |
---|---|---|
committer | emkael <emkael@tlen.pl> | 2025-02-13 02:34:02 +0100 |
commit | 113c0b2976e845e401f0b115b87d8114fbb8b8a1 (patch) | |
tree | aabeaad1996f54c42c364fda28c069e7bea852f4 | |
parent | 06c0a51b191c35905c819ae839dcb357a446e500 (diff) |
Adios, magic constants
-rw-r--r-- | http/api-inc.php | 199 |
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'); } } |