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