summaryrefslogtreecommitdiff
path: root/http/api.php
diff options
context:
space:
mode:
Diffstat (limited to 'http/api.php')
-rw-r--r--http/api.php208
1 files changed, 208 insertions, 0 deletions
diff --git a/http/api.php b/http/api.php
new file mode 100644
index 0000000..bccd5d3
--- /dev/null
+++ b/http/api.php
@@ -0,0 +1,208 @@
+<?php
+
+/*
+Parametry:
+ - rodzaj turnieju (4 => 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'])) ? floatval($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));
+ }
+ foreach ($return['points_cutoffs'] as $cutoff) {
+ if (($cutoff[0] < 0.0) || ($cutoff[0] > 1.0)) {
+ throw new ParametersException('Cutoff points need to be between 0.0 and 1.0: ' . $cutoff[0]);
+ }
+ if (($cutoff[1] < 0.0) || ($cutoff[1] > 1.0)) {
+ throw new ParametersException('Cutoff values need to be between 1.0 and 0.0: ' . $cutoff[1]);
+ }
+ }
+ for ($prev = 0; $prev < count($return['points_cutoffs']) - 1; $prev++) {
+ $next = $prev + 1;
+ if ($return['points_cutoffs'][$prev][0] >= $return['points_cutoffs'][$next][0]) {
+ throw new ParametersException(
+ 'Cutoff points need to be ascending: ' . $return['points_cutoffs'][$prev][0] . ', ' . $return['points_cutoffs'][$next][0]);
+ }
+ if ($return['points_cutoffs'][$prev][1] < $return['points_cutoffs'][$next][1]) {
+ throw new ParametersException(
+ 'Cutoff values need to be non-ascending: ' . $return['points_cutoffs'][$prev][1] . ', ' . $return['points_cutoffs'][$next][1]);
+ }
+ }
+ 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)));
+//}
+
+?>