teamy, 2 => pary, 1 => ind) - l. uczestników - suma WK - ranga turnieju (0 => K, 1 => Ok, 2 => R, 3 => O, 4 => O*, 5 => O**, 6 => O***, 7 => O****) (opcjonalny, jeśli podano ręczne minPKL i wagę) - l. rozdań => 40? (opcjonalny, jeśli podano ręczne minPKL i wagę) - ręczne minPKL za pierwsze (opcjonalny) - ręczna waga (opcjonalny) - ręczny współczynnik zawodniczy (opcjonalny) - ręczne progi (opcjonalne) { "type": 2, "contestants": 20, "title_sum": 230, "tournament_rank": 3, "over39_boards": 0, "manual": { "min_points": 50, "tournament_weight": 50, "players_coefficient": 0.1, "points_cutoffs": [[0.1, 0.9], [0.5, 0.0]] } } */ class ParametersException extends Exception {}; function safe_ceil($value, $precision = 1e-6) { $ceilValue = ceil($value); return (abs($value - $ceilValue) < (1-$precision)) ? $ceilValue : round($value); } function recursive_ksort(&$array, $flags = SORT_REGULAR) { if (!is_array($array)) return false; ksort($array, $flags); foreach ($array as &$arr) { recursive_ksort($arr, $flags); } return true; } function ensure_parameters($parameters, $params) { foreach ($params as $param) { if (!isset($parameters[$param])) { throw new ParametersException('Missing parameter: ' . $param); } if (!is_numeric($parameters[$param])) { throw new ParametersException('Parameter: ' . $param . ' is not a numeric value (' . $parameters[$param] . ')'); } } } function check_values($parameters, $params) { foreach ($params as $param => $test) { if (!$test($parameters[$param])) { throw new ParametersException('Parameter: ' . $param . ' has incorrect value (' . $parameters[$param] . ')'); } } } function check_parameters($parameters) { ensure_parameters($parameters, array('type', 'contestants', 'title_sum')); check_values($parameters, array( 'type' => function($r) { return ctype_digit($r) && intval($r) > 0; }, 'contestants' => function($r) { return ctype_digit($r) && intval($r) > 0; }, 'title_sum' => function($r) { return floatval($r) >= 0; } )); if (isset($parameters['players'])) { check_values($parameters, array( 'players' => function($r) { return ctype_digit($r) && intval($r) > 0; } )); } if (!isset($parameters['manual']) || !isset($parameters['manual']['min_points']) || !isset($parameters['manual']['tournament_weight'])) { ensure_parameters($parameters, array('tournament_rank', 'over39_boards')); check_values($parameters, array( 'tournament_rank' => function($r) { return ctype_digit($r) && intval($r) >= 0 && intval($r) <= 7; }, 'over39_boards' => function($r) { return ctype_digit($r) && intval($r) >= 0 && intval($r) <= 1; } )); } else { check_values($parameters['manual'], array( 'min_points' => function($r) { return ctype_digit($r) && intval($r) >= 0; }, 'tournament_weight' => function($r) { return ctype_digit($r) && intval($r) > 0; } )); } if (isset($parameters['manual']) && isset($parameters['manual']['players_coefficient'])) { check_values($parameters['manual'], array( 'players_coefficient' => function($r) { return floatval($r) >= 0; } )); } } function parse_parameters($parameters) { $return = array(); $return['type'] = intval($parameters['type']); if ($return['type'] == 3 || $return['type'] > 4) { throw new ParametersException('Parameter: type has incorrect value (' . $return['type'] . ')'); } $return['contestants'] = intval($parameters['contestants']); $return['players'] = isset($parameters['players']) ? intval($parameters['players']) : intval($parameters['contestants']) * $return['type']; $return['title_sum'] = floatval($parameters['title_sum']); $weights = array( array(1, 2, 4, 5, 7, 10, 15, 25), array(2, 3, 5, 7, 10, 15, 25, 40) ); $return['tournament_weight'] = (isset($parameters['manual']) && isset($parameters['manual']['tournament_weight'])) ? intval($parameters['manual']['tournament_weight']) : $weights[intval($parameters['over39_boards'])][intval($parameters['tournament_rank'])]; $min_points = array( array(0, 0, 0, 0, 50, 75, 150, 200), array(0, 0, 0, 0, 70, 100, 200, 300) ); $return['min_points'] = (isset($parameters['manual']) && isset($parameters['manual']['min_points'])) ? intval($parameters['manual']['min_points']) : $min_points[intval($parameters['over39_boards'])][intval($parameters['tournament_rank'])]; $return['players_coefficient'] = (isset($parameters['manual']) && isset($parameters['manual']['players_coefficient'])) ? intval($parameters['manual']['players_coefficient']) : 0.05; $return['points_cutoffs'] = (isset($parameters['manual']) && isset($parameters['manual']['points_cutoffs']) && is_array($parameters['manual']['points_cutoffs'])) ? $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) ); recursive_ksort($return['points_cutoffs']); if ($return['points_cutoffs'][0][0] != 0.0) { array_unshift($return['points_cutoffs'], array(0.0, 1.0)); } if ($return['points_cutoffs'][count($return['points_cutoffs'])-1][1] != 0.0) { array_push($return['points_cutoffs'], array(1.0, 0.0)); } return $return; } function get_position_percentage_from_position($position, $contestants) { return ($position - 1) / $contestants; } function get_percentage_from_position($position, $contestants, $cutoffs) { $position_percentage = get_position_percentage_from_position($position, $contestants); for ($prev = 0; $prev < count($cutoffs) - 1; $prev++) { $next = $prev + 1; if (($cutoffs[$prev][0] <= $position_percentage) && ($cutoffs[$next][0] >= $position_percentage)) { $result = ($position_percentage - $cutoffs[$prev][0]) * ($cutoffs[$prev][1] - $cutoffs[$next][1]) / ($cutoffs[$prev][0] - $cutoffs[$next][0]) + $cutoffs[$prev][1]; return $result; } } return 0.0; } function calculate_points($parameters) { $max_points = safe_ceil(max( $parameters['min_points'], (1 + 0.25 * ($parameters['type'] > 2)) * (max(0.15, $parameters['title_sum'] / $parameters['players']) * $parameters['tournament_weight'] + $parameters['players_coefficient'] * $parameters['contestants'] * $parameters['type']) )); $min_points = 1; $result = array("sum" => 0); for ($place = 1; $place <= $parameters['contestants']; $place++) { $percentage = get_percentage_from_position($place, $parameters['contestants'], $parameters['points_cutoffs']); $points = safe_ceil(floatval($max_points) * $percentage); $result[$place] = max($min_points, intval($points)); $result['sum'] += $parameters['type'] * $result[$place]; } return $result; } function run($parameters) { try { check_parameters($parameters); $parameters = parse_parameters($parameters); $result = calculate_points($parameters); return $result; } catch (ParametersException $e) { http_response_code(400); die($e->getMessage()); } catch (Exception $e) { http_response_code(500); die($e->getMessage()); } } /*if ($_SERVER['REQUEST_METHOD'] != 'POST') { http_response_code(405); die('API only accepts POST requests'); } else {*/ print(json_encode(run($_REQUEST))); //} ?>