Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
0.00% covered (danger)
0.00%
0 / 97
0.00% covered (danger)
0.00%
0 / 2
CRAP
0.00% covered (danger)
0.00%
0 / 1
OlzZielsprint
0.00% covered (danger)
0.00%
0 / 97
0.00% covered (danger)
0.00%
0 / 2
132
0.00% covered (danger)
0.00%
0 / 1
 getHtml
0.00% covered (danger)
0.00%
0 / 38
0.00% covered (danger)
0.00%
0 / 1
30
 getRanking
0.00% covered (danger)
0.00%
0 / 59
0.00% covered (danger)
0.00%
0 / 1
42
1<?php
2
3namespace Olz\Components\OlzZielsprint;
4
5use Olz\Components\Common\OlzComponent;
6
7/** @extends OlzComponent<array<string, mixed>> */
8class OlzZielsprint extends OlzComponent {
9    public function getHtml(mixed $args): string {
10        $out = '';
11
12        $ranking = $this->getRanking();
13
14        $out .= "<table>";
15        $out .= "<tr>";
16        $out .= "<th style='border-bottom: 1px solid black; text-align: right;'>Rang&nbsp;</th>";
17        $out .= "<th style='border-bottom: 1px solid black;'>Name</th>";
18        $out .= "<th style='border-bottom: 1px solid black; text-align: right;'>Punkte</th>";
19        $out .= "</tr>";
20        $last_points = null;
21        $last_actual_rank = 1;
22        for ($index = 0; $index < count($ranking); $index++) {
23            $rank = $index + 1;
24            $ranking_entry = $ranking[$index];
25            $person_name = $ranking_entry['person_name'];
26            $points = intval($ranking_entry['points']);
27            $actual_rank = ($last_points === $points)
28                ? $last_actual_rank
29                : $rank;
30
31            $calculation = "{$person_name}\\n---\\n";
32            foreach ($ranking_entry['calculation'] as $event_calculation) {
33                $event_name = $event_calculation['event_name'];
34                $event_points = $event_calculation['points'];
35                $event_max_points = $event_calculation['max_points'];
36                $finish_split = $event_calculation['finish_split'];
37                $finish_minutes = floor(intval($finish_split) / 60);
38                $finish_seconds = str_pad(strval(intval($finish_split) % 60), 2, '0');
39                $pretty_finish_split = "{$finish_minutes}:{$finish_seconds}";
40                $calculation .= "{$event_name}{$event_points} / {$event_max_points} ({$pretty_finish_split})\\n";
41            }
42            $bgcolor = ($index % 2 === 0) ? 'rgba(0,0,0,0.1)' : 'rgba(0,0,0,0)';
43            $out .= "<tr style='background-color:{$bgcolor}; cursor:pointer;' onclick='alert(&quot;{$calculation}&quot;)'>";
44            $out .= "<td style='text-align: right;'>{$actual_rank}.&nbsp;</td>";
45            $out .= "<td>{$person_name}</td>";
46            $out .= "<td style='text-align: right;'>{$points}</td>";
47            $out .= "</tr>";
48            $last_points = $points;
49            $last_actual_rank = $actual_rank;
50        }
51        $out .= "</table>";
52
53        return $out;
54    }
55
56    /**
57     * @return array<array{
58     *   person_id: int,
59     *   person_name: string,
60     *   points: int,
61     *   calculation: array<array{
62     *     event_name: string,
63     *     points: int,
64     *     finish_split: int,
65     *     max_points: int,
66     *   }>
67     * }>
68     */
69    public function getRanking(): array {
70        $year = 2026;
71        $db = $this->dbUtils()->getDb();
72
73        $sql = "
74            SELECT solv_uid, name, date
75            FROM solv_events
76            WHERE
77                date>='{$year}-01-01'
78                AND date<='{$year}-12-31'
79                AND kind='foot'
80            ORDER BY date ASC";
81        $res_events = $db->query($sql);
82        $this->generalUtils()->checkNotBool($res_events, "Query error: {$sql}");
83        $points_by_person = [];
84        while ($row_event = $res_events->fetch_assoc()) {
85            $event_id = intval($row_event['solv_uid']);
86            $sql = "SELECT DISTINCT last_control_code FROM solv_results WHERE event='{$event_id}'";
87            $res_last_control = $db->query($sql);
88            $this->generalUtils()->checkNotBool($res_last_control, "Query error: {$sql}");
89            while ($row_last_control = $res_last_control->fetch_assoc()) {
90                $last_control_code = intval($row_last_control['last_control_code']);
91                // $out .= "<h3>".json_encode($row_event)."</h3>";
92                $sql = "
93                    SELECT person, finish_split
94                    FROM solv_results
95                    WHERE
96                        event='{$event_id}'
97                        AND finish_split > '0'
98                        AND last_control_code = '{$last_control_code}'
99                    ORDER BY finish_split ASC";
100                $res_results = $db->query($sql);
101                $this->generalUtils()->checkNotBool($res_results, "Query error: {$sql}");
102                $num_participants = intval($res_results->num_rows);
103                $last_finish_split = null;
104                $last_actual_points = null;
105                for ($points = $num_participants; $points > 0; $points--) {
106                    $row_results = $res_results->fetch_assoc();
107                    $person_id = intval($row_results['person'] ?? 0);
108                    $finish_split = intval($row_results['finish_split'] ?? PHP_INT_MAX);
109                    $actual_points = ($last_finish_split === $finish_split)
110                        ? $last_actual_points
111                        : $points;
112                    $person_points = $points_by_person[$person_id]
113                        ?? ['points' => 0, 'calculation' => []];
114                    $points_by_person[$person_id]['points'] = $person_points['points'] + $actual_points;
115                    $points_by_person[$person_id]['calculation'][] = [
116                        'event_name' => "{$row_event['name']} ({$last_control_code})",
117                        'points' => $actual_points,
118                        'finish_split' => $finish_split,
119                        'max_points' => $num_participants,
120                    ];
121                    $last_finish_split = $finish_split;
122                    $last_actual_points = $actual_points;
123                    // $out .= "<div>".json_encode($row_results)."</div>";
124                }
125            }
126        }
127        $ranking = [];
128        foreach ($points_by_person as $person_id => $points) {
129            $sql = "
130                SELECT name
131                FROM solv_people
132                WHERE id='{$person_id}'";
133            $res_person = $db->query($sql);
134            $this->generalUtils()->checkNotBool($res_person, "Query error: {$sql}");
135            $row_person = $res_person->fetch_assoc();
136            $person_name = strval($row_person['name'] ?? '?');
137            $ranking[] = [
138                'person_id' => $person_id,
139                'person_name' => $person_name,
140                'points' => $points['points'],
141                'calculation' => $points['calculation'],
142            ];
143        }
144
145        usort($ranking, fn ($a, $b) => $b['points'] - $a['points']);
146
147        return $ranking;
148    }
149}