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