Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
0.00% |
0 / 134 |
|
0.00% |
0 / 7 |
CRAP | |
0.00% |
0 / 1 |
| OlzAnniversaryParams | n/a |
0 / 0 |
n/a |
0 / 0 |
0 | n/a |
0 / 0 |
|||
| OlzAnniversary | |
0.00% |
0 / 134 |
|
0.00% |
0 / 7 |
342 | |
0.00% |
0 / 1 |
| hasAccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getSearchTitle | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getSearchResultsWhenHasAccess | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
| getHtmlWhenHasAccess | |
0.00% |
0 / 14 |
|
0.00% |
0 / 1 |
2 | |||
| getRunsHtml | |
0.00% |
0 / 92 |
|
0.00% |
0 / 1 |
72 | |||
| getElevationStravaHtml | |
0.00% |
0 / 21 |
|
0.00% |
0 / 1 |
30 | |||
| getZielsprintHtml | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
2 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace Olz\Anniversary\Components\OlzAnniversary; |
| 4 | |
| 5 | use Doctrine\Common\Collections\Criteria; |
| 6 | use Olz\Anniversary\Components\OlzAnniversaryRocket\OlzAnniversaryRocket; |
| 7 | use Olz\Components\Common\OlzEditableText\OlzEditableText; |
| 8 | use Olz\Components\Common\OlzRootComponent; |
| 9 | use Olz\Components\OlzZielsprint\OlzZielsprint; |
| 10 | use Olz\Components\Page\OlzFooter\OlzFooter; |
| 11 | use Olz\Components\Page\OlzHeader\OlzHeader; |
| 12 | use Olz\Entity\Anniversary\RunRecord; |
| 13 | use Olz\Entity\StravaLink; |
| 14 | use Olz\Repository\Snippets\PredefinedSnippet; |
| 15 | use Olz\Utils\HttpParams; |
| 16 | |
| 17 | /** @extends HttpParams<array{}> */ |
| 18 | class OlzAnniversaryParams extends HttpParams { |
| 19 | } |
| 20 | |
| 21 | /** @extends OlzRootComponent<array<string, mixed>> */ |
| 22 | class OlzAnniversary extends OlzRootComponent { |
| 23 | public function hasAccess(): bool { |
| 24 | return true; |
| 25 | } |
| 26 | |
| 27 | public function getSearchTitle(): string { |
| 28 | return 'Jubiläumsjahr'; |
| 29 | } |
| 30 | |
| 31 | public function getSearchResultsWhenHasAccess(array $terms): array { |
| 32 | return []; |
| 33 | } |
| 34 | |
| 35 | public static string $title = "🎉 20 Jahre OL Zimmerberg 🥳"; |
| 36 | public static string $description = "Alle Aktivitäten und Informationen zum Jubiläumsjahr 2026."; |
| 37 | |
| 38 | public function getHtmlWhenHasAccess(mixed $args): string { |
| 39 | $this->httpUtils()->validateGetParams(OlzAnniversaryParams::class); |
| 40 | |
| 41 | $out = OlzHeader::render([ |
| 42 | 'title' => self::$title, |
| 43 | 'description' => self::$description, |
| 44 | 'norobots' => true, |
| 45 | ]); |
| 46 | $out .= <<<ZZZZZZZZZZ |
| 47 | <div class='content-full olz-anniversary'> |
| 48 | <h1>🎉 20 Jahre OL Zimmerberg 🥳</h1> |
| 49 | <br> |
| 50 | {$this->getRunsHtml()} |
| 51 | {$this->getElevationStravaHtml()} |
| 52 | <br> |
| 53 | {$this->getZielsprintHtml()} |
| 54 | </div> |
| 55 | ZZZZZZZZZZ; |
| 56 | |
| 57 | $out .= OlzFooter::render(); |
| 58 | return $out; |
| 59 | } |
| 60 | |
| 61 | protected function getRunsHtml(): string { |
| 62 | $code_href = $this->envUtils()->getCodeHref(); |
| 63 | $user = $this->authUtils()->getCurrentUser(); |
| 64 | $out = '<h2>🏃 Höhenmeter-Challenge ⛰️</h2>'; |
| 65 | if (!$user) { |
| 66 | $out .= "<p>😕 Du musst <a href='#login-dialog'>eingeloggt</a> sein, um an der Höhenmeter-Challenge teilzunehmen.</p>"; |
| 67 | return $out; |
| 68 | } |
| 69 | |
| 70 | $out .= OlzEditableText::render(['snippet' => PredefinedSnippet::AnniversaryHoehenmeter]); |
| 71 | |
| 72 | $stats = $this->anniversaryUtils()->getElevationStats(); |
| 73 | |
| 74 | $done_wid = \number_format(max(0, $stats['completion'] * 100), 2); |
| 75 | $diff_wid = log10(abs($stats['diffDays']) + 1) * 25; |
| 76 | $rocket = OlzAnniversaryRocket::render(); |
| 77 | $out .= <<<ZZZZZZZZZZ |
| 78 | <div class='elevation-stats'> |
| 79 | <div class='done-range'></div> |
| 80 | <div class='done-bar' style='width: {$done_wid}%;'></div> |
| 81 | <div class='rocket test-flaky' style='left: {$done_wid}%;'>{$rocket}</div> |
| 82 | <div class='diff-range'></div> |
| 83 | <div class='diff-bar {$stats['diffKind']}' style='width: {$diff_wid}%;'></div> |
| 84 | <div class='marker' style='left: 12.72%;'></div> |
| 85 | <div class='marker' style='left: 27.42%;'></div> |
| 86 | <div class='marker' style='left: 42.47%;'></div> |
| 87 | <div class='marker' style='left: 50%;'></div> |
| 88 | <div class='marker' style='left: 57.53%;'></div> |
| 89 | <div class='marker' style='left: 72.58%;'></div> |
| 90 | <div class='marker' style='left: 87.28%;'></div> |
| 91 | <div class='marker-text' style='left: 12.72%;'>-1 Monat</div> |
| 92 | <div class='marker-text' style='left: 27.42%;'>-1 Woche</div> |
| 93 | <div class='marker-text' style='left: 42.47%;'>-1 Tag</div> |
| 94 | <div class='marker-text' style='left: 57.53%;'>+1 Tag</div> |
| 95 | <div class='marker-text' style='left: 72.58%;'>+1 Woche</div> |
| 96 | <div class='marker-text' style='left: 87.28%;'>+1 Monat</div> |
| 97 | </div> |
| 98 | ZZZZZZZZZZ; |
| 99 | |
| 100 | $out .= "<h3>Aktivitäten in den letzten 24 Stunden</h3>"; |
| 101 | $out .= <<<'ZZZZZZZZZZ' |
| 102 | <div class='activities-table activities-24h'> |
| 103 | <table> |
| 104 | <tr class='header'> |
| 105 | <td>Datum</td> |
| 106 | <td>Person</td> |
| 107 | <td>Quelle</td> |
| 108 | <td>Distanz</td> |
| 109 | <td>Höhenmeter</td> |
| 110 | <td>Steigung</td> |
| 111 | <td>Art</td> |
| 112 | </tr> |
| 113 | ZZZZZZZZZZ; |
| 114 | $runs_repo = $this->entityManager()->getRepository(RunRecord::class); |
| 115 | $iso_now = $this->dateUtils()->getIsoNow(); |
| 116 | $minus_one_day = \DateInterval::createFromDateString("-24 hours"); |
| 117 | $one_day_ago = (new \DateTime($iso_now))->add($minus_one_day); |
| 118 | $runs = $runs_repo->matching(Criteria::create() |
| 119 | ->where(Criteria::expr()->andX( |
| 120 | Criteria::expr()->gt('run_at', $one_day_ago), |
| 121 | Criteria::expr()->eq('on_off', 1), |
| 122 | )) |
| 123 | ->orderBy(['run_at' => 'DESC']) |
| 124 | ->setFirstResult(0) |
| 125 | ->setMaxResults(1000)); |
| 126 | foreach ($runs as $run) { |
| 127 | $id = $run->getId(); |
| 128 | $json_id = json_encode($id); |
| 129 | $date = $run->getRunAt()->format('d.m.Y H:i'); |
| 130 | $info = json_decode($run->getInfo(), true) ?? null; |
| 131 | $run_user = $run->getUser(); |
| 132 | $name = "?"; |
| 133 | $sport_type = "?"; |
| 134 | if ($run_user) { |
| 135 | $last_name = substr($run_user->getLastName(), 0, 1)."."; |
| 136 | $name = "{$run_user->getFirstName()} {$last_name}"; |
| 137 | } else { |
| 138 | if (is_array($info)) { |
| 139 | $name = "{$info['athlete']['firstname']} {$info['athlete']['lastname']}"; |
| 140 | $sport_type = "{$info['type']} / {$info['sport_type']}"; |
| 141 | } |
| 142 | } |
| 143 | $source_short = mb_split('-', $run->getSource())[0] ?? '?'; |
| 144 | $distance_km = number_format($run->getDistanceMeters() / 1000, 2); |
| 145 | $inclination_percent = $run->getDistanceMeters() |
| 146 | ? number_format($run->getElevationMeters() * 100 / $run->getDistanceMeters(), 2) |
| 147 | : 'NaN'; |
| 148 | $out .= <<<ZZZZZZZZZZ |
| 149 | <tr> |
| 150 | <td>{$date}</td> |
| 151 | <td>{$name}</td> |
| 152 | <td>{$source_short}</td> |
| 153 | <td class='number'>{$distance_km}km</td> |
| 154 | <td class='number'><b>{$run->getElevationMeters()}m</b></td> |
| 155 | <td class='number'>{$inclination_percent}%</td> |
| 156 | <td>{$sport_type}</td> |
| 157 | </tr> |
| 158 | ZZZZZZZZZZ; |
| 159 | } |
| 160 | $out .= "</table></div>"; |
| 161 | |
| 162 | $out .= <<<ZZZZZZZZZZ |
| 163 | <h3> |
| 164 | Deine Aktivitäten (ohne Strava) |
| 165 | <button |
| 166 | id='create-run-button' |
| 167 | class='btn btn-secondary' |
| 168 | onclick='return olz.initOlzEditRunModal()' |
| 169 | > |
| 170 | <img src='{$code_href}assets/icns/new_white_16.svg' class='noborder' /> |
| 171 | Aktivität manuell hinzufügen |
| 172 | </button> |
| 173 | </h3> |
| 174 | ZZZZZZZZZZ; |
| 175 | $out .= <<<'ZZZZZZZZZZ' |
| 176 | <div class='activities-table activities-manual'> |
| 177 | <table> |
| 178 | <tr class='header'> |
| 179 | <td></td> |
| 180 | <td>Datum</td> |
| 181 | <td>Quelle</td> |
| 182 | <td>Distanz</td> |
| 183 | <td>Höhenmeter</td> |
| 184 | <td>Steigung</td> |
| 185 | </tr> |
| 186 | ZZZZZZZZZZ; |
| 187 | $runs_repo = $this->entityManager()->getRepository(RunRecord::class); |
| 188 | $runs = $runs_repo->findBy( |
| 189 | ['user' => $user, 'on_off' => 1], |
| 190 | ['run_at' => 'DESC'], |
| 191 | ); |
| 192 | foreach ($runs as $run) { |
| 193 | $id = $run->getId(); |
| 194 | $json_id = json_encode($id); |
| 195 | $date = $run->getRunAt()->format('d.m.Y H:i:s'); |
| 196 | $edit_button = $run->getSource() === 'manuell' ? <<<ZZZZZZZZZZ |
| 197 | <button |
| 198 | id='edit-run-{$id}-button' |
| 199 | class='btn btn-secondary-outline btn-sm edit-run-list-button' |
| 200 | onclick='return olz.olzAnniversaryEditRun({$json_id})' |
| 201 | > |
| 202 | <img src='{$code_href}assets/icns/edit_16.svg' class='noborder' /> |
| 203 | </button> |
| 204 | ZZZZZZZZZZ : ''; |
| 205 | $distance_km = number_format($run->getDistanceMeters() / 1000, 2); |
| 206 | $inclination_percent = number_format($run->getElevationMeters() * 100 / $run->getDistanceMeters(), 2); |
| 207 | $out .= <<<ZZZZZZZZZZ |
| 208 | <tr> |
| 209 | <td>{$edit_button}</td> |
| 210 | <td>{$date}</td> |
| 211 | <td>{$run->getSource()}</td> |
| 212 | <td class='number'>{$distance_km}km</td> |
| 213 | <td class='number'><b>{$run->getElevationMeters()}m</b></td> |
| 214 | <td class='number'>{$inclination_percent}%</td> |
| 215 | </tr> |
| 216 | ZZZZZZZZZZ; |
| 217 | } |
| 218 | $out .= "</table></div>"; |
| 219 | return $out; |
| 220 | } |
| 221 | |
| 222 | protected function getElevationStravaHtml(): string { |
| 223 | $user = $this->authUtils()->getCurrentUser(); |
| 224 | if (!$user || !$this->authUtils()->hasPermission('anniversary', $user)) { |
| 225 | return ''; |
| 226 | } |
| 227 | $strava_link_repo = $this->entityManager()->getRepository(StravaLink::class); |
| 228 | $strava_links = $strava_link_repo->findBy(['user' => $user]); |
| 229 | $num_strava_links = count($strava_links); |
| 230 | $redirect_url = "{$this->envUtils()->getBaseHref()}{$this->envUtils()->getCodeHref()}2026"; |
| 231 | $strava_url = $this->stravaUtils()->getRegistrationUrl(['read', 'activity:read'], $redirect_url); |
| 232 | $out = "<div class='admin-only'><div class='admin-only-text'>Nur für Organisatoren sichtbar</div>"; |
| 233 | if ($num_strava_links === 0) { |
| 234 | $out .= "<p>😕 Kein Strava-Konto verlinkt. <a href='{$strava_url}' class='linkext'>Jetzt mit Strava verbinden!</a></p>"; |
| 235 | } else { |
| 236 | $out .= "<p>✅ Du bist mit diesen {$num_strava_links} Strava-Konten verbunden:</p><ul>"; |
| 237 | foreach ($strava_links as $strava_link) { |
| 238 | $athlete_id = $strava_link->getStravaUser(); |
| 239 | $athlete_url = "https://www.strava.com/athletes/{$athlete_id}"; |
| 240 | $date = $strava_link->getLinkedAt()?->format('d.m.Y H:i:s'); |
| 241 | $out .= "<li><a href='{$athlete_url}'>{$athlete_id}</a> (erstellt: {$date})</li>"; |
| 242 | } |
| 243 | $out .= "</ul>"; |
| 244 | $out .= "<p><a href='{$strava_url}'>Mit Strava verbinden</a></p>"; |
| 245 | } |
| 246 | $out .= '</div>'; |
| 247 | return $out; |
| 248 | } |
| 249 | |
| 250 | protected function getZielsprintHtml(): string { |
| 251 | $out = '<h2>🏁 Zielsprint-Challenge 🏃</h2>'; |
| 252 | $out .= OlzEditableText::render(['snippet' => PredefinedSnippet::AnniversaryZielsprint]); |
| 253 | $out .= OlzZielsprint::render(); |
| 254 | return $out; |
| 255 | } |
| 256 | } |