Merge branch 'master' into infoZettel

This commit is contained in:
marko
2024-04-22 19:16:09 +02:00
8 changed files with 641 additions and 343 deletions

View File

@@ -0,0 +1,145 @@
<?php
class Interval
{
function __construct(
$lowerBound,
$upperBound,
bool $lowerClosed = true,
bool $upperClosed = false
) {
$this->lowerBound = $lowerBound;
$this->upperBound = $upperBound;
$this->lowerClosed = $lowerClosed;
$this->upperClosed = $upperClosed;
}
function __toString(): string
{
return ($this->lowerClosed ? "[" : "(") .
$this->lowerBound .
", " .
$this->upperBound .
($this->upperClosed ? "]" : ")");
}
function contains($value)
{
return ($this->lowerClosed
? $this->lowerBound <= $value
: $this->lowerBound < $value) &&
($this->upperClosed
? $value <= $this->upperBound
: $value < $this->upperBound);
}
// private member
//- variables
// upper/lower bounds for the interval
private $lowerBound;
private $upperBound;
// on true the bound is in the interval, otherwise not
private $lowerClosed;
private $upperClosed;
}
// data type for an age class
class AgeGroup
{
// public member
// - functions
function __construct(string $label, Interval $years)
{
$this->label = $label;
$this->years = $years;
}
function __toString(): string
{
return $this->label . " " . $this->years;
}
function years()
{
return $this->years;
}
/** factory method for AgeGroup-s
*
* @param [string] $label string denoting the AgeGroup
* @param [type] $year the year to reference the AgeGroup to
* @return AgeGroup interval of years of the age group
*/
public static function create(string $label, ?int $year = null)
{
// input sanitation
$year =
filterPosInt($year) ?? filterPosInt((new DateTime())->format("Y"));
$lowerYear = null;
$upperYear = null;
// Matching against the different age class formats
// - ..Ux
// - Jg.x-y
// Case Ux
$akUmatchString = "/(.*)U([0-9]+)(.*)/";
$matches = [];
preg_match($akUmatchString, $label, $matches);
// The found match should cover the whole string. Otherwise it isn't applicable.
if ($matches[0] == $label) {
// The x in Ux should be a positive integer.
$ageLimit = filterPosInt($matches[2]);
if ($ageLimit) {
$lowerYear = $year - $ageLimit + 1;
// lowering the lower bound according to the modifiers
if ($matches[3] == "") {
$upperYear = $year - $ageLimit + 2;
} elseif ($matches[3] == "-") {
$upperYear = $year - $ageLimit + 3;
} elseif ($matches[3] == "--") {
$upperYear = $year - $ageLimit + 4;
} elseif (
in_array($matches[1], [
"<=",
"&le;",
"&#x2264;",
"&#8804;",
"",
])
) {
$upperYear = $year;
}
return new AgeGroup(
$label,
new Interval($lowerYear, $upperYear, true, true)
);
}
}
// Case Jg.x-y
$akUmatchString = "/Jg\.(.*)\-{1,2}(.*)/";
$matches = [];
preg_match($akUmatchString, $label, $matches);
// The found match should cover the whole string. Otherwise it isn't applicable.
if ($matches[0] == $label) {
$lowerYear = filterPosInt($matches[1]);
$upperYear = filterPosInt($matches[2]);
return new AgeGroup(
$label,
new Interval($lowerYear, $upperYear, true, true)
);
}
return new AgeGroup(
$label,
new Interval($lowerYear, $upperYear, true, true)
);
}
// private member
// - functions
// - variables
private $label;
private $years;
}

View File

@@ -1,96 +1,132 @@
<?php <?php
require_once "participoLib/shiai.php";
class EventPage class EventPage
{ {
public function __construct($eventId = null) public function __construct($eventId = null)
{ {
$this->eventId = filterId($eventId); $this->eventId = filterId($eventId);
} }
public function init() public function init()
{ {
$params = participo::parseParams( $params = participo::parseParams([
['eventId' => function ($param) {return filterId($param); }] "eventId" => function ($param) {
); return filterId($param);
$this->eventId = $params['eventId']; },
]);
$this->eventId = $params["eventId"];
return; return;
} }
public function getHtmlNotFound() public function getHtmlNotFound()
{ {
return '<div>Der Event "' . $this->id . '" existiert leider nicht!</div>' return '<div>Der Event "' .
. '<h2>Anstehende Termine</h2>' $this->id .
. eventPlaner::getHtmlEventTable( '" existiert leider nicht!</div>' .
eventPlaner::getComingWkEvents() "<h2>Anstehende Termine</h2>" .
); eventPlaner::getHtmlEventTable(eventPlaner::getComingWkEvents());
} }
public function getHtml() public function getHtml()
{ {
if (!$this->event()) { if (!$this->event()) {
return $this->getHtmlNotFound(); return $this->getHtmlNotFound();
} }
$html = ''; $html = "";
$html .= $html .=
'<div>' "<div>" .
. '<dl>' "<dl>" .
. '<dt>Termine</dt>' "<dt>Termine</dt>" .
. '<dd> '<dd>
<dl>' <dl>' .
. '<dt>Datum</dt><dd>' . $this->event()->htmlDate() . '</dd>' "<dt>Datum</dt><dd>" .
. '<dt>Deadline zum Einschreiben:</dt><dd>' . $this->event()->htmlDeadline() . '</dd>' $this->event()->htmlDate() .
. '</dl>'; "</dd>" .
// Not all Events have a shiai linked to them "<dt>Deadline zum Einschreiben:</dt><dd>" .
if ($this->event()->shiai()) { $this->event()->htmlDeadline() .
$html .= "</dd>" .
'<dt>Wettkampfdetails</dt><dd>' . $this->event()->shiai()->getHtmlDetails() . '</dd>'; "</dl>";
} // Not all Events have a shiai linked to them
$html .= if ($this->event()->shiai()) {
'<dt>Einschreibungen</dt><dd>' . $this->event()->getHtmlStarterStatistic() . '</dd>' $html .=
. '<dt>Eigene, gemeldete Starter</dt><dd>' . $this->event()->getHtmlStarterList() . '</dd>' "<dt>Wettkampfdetails</dt><dd>" .
. '</dl>' $this->event()
. '</div>'; ->shiai()
->getHtmlDetails() .
"</dd>";
}
$html .=
"<dt>Einschreibungen</dt><dd>" .
$this->event()->getHtmlStarterStatistic() .
"</dd>" .
"<dt>Eigene, gemeldete Starter</dt><dd>" .
$this->event()->getHtmlStarterList() .
"</dd>" .
"</dl>" .
"</div>";
$html .= $html .= "<div>";
'<div>';
foreach ($this->event()->shiai()->ageGroups() as $ageClass => $starterList) { foreach (
$html .= $this->event()
'<dl>' . ->shiai()
'<dt>' . (!empty($ageClass) ? $ageClass : 'keiner Altersklasse zugeordnet') . '</dt>' ->ageGroups()
. '<dd> as $ageClass => $starterList
) {
$html .=
"<dl>" .
"<dt>" .
(!empty($ageClass)
? AgeGroup::create($ageClass)
: "keiner Altersklasse zugeordnet") .
"</dt>" .
'<dd>
<ul>'; <ul>';
foreach ($starterList as $starter) { foreach ($starterList as $starter) {
if (!array_key_exists($starter->getId(), $this->event()->getStarter())) { if (
$html .= !array_key_exists(
'<li>' . $starter->getName() . ', ' . $starter->getFirstname() . ' - ' . $starter->yearOfBirth() . ' $starter->getId(),
$this->event()->getStarter()
)
) {
$html .=
"<li>" .
$starter->getName() .
", " .
$starter->getFirstname() .
" - " .
$starter->yearOfBirth() .
'
</li>'; </li>';
} }
} }
$html .= ' $html .= '
</dd> </dd>
</ul>'; </ul>';
} }
$html .= '</div>'; $html .= "</div>";
return $html; return $html;
} }
public function html() public function html()
{ {
echo($this->getHtml()); echo $this->getHtml();
} }
private function event(bool $forceLoading = false) private function event(bool $forceLoading = false)
{ {
if (!$this->event || $forceLoading) { if (!$this->event || $forceLoading) {
$this->event = Event::loadFromDb($this->eventId); $this->event = Event::loadFromDb($this->eventId);
} }
return $this->event; return $this->event;
} }
private $eventId = null; private $eventId = null;
private $event = null; private $event = null;
} }

View File

@@ -1,313 +1,373 @@
<?php <?php
require_once 'participoLib/participo.php'; require_once "participoLib/participo.php";
require_once "participoLib/ageGroup.php";
/** frame for a shiai /** frame for a shiai
*/ */
class Shiai class Shiai
{ {
private $id = null; //< unique id private $id = null; //< unique id
private $date = null; //< date of the shiai private $date = null; //< date of the shiai
private $name = null; //< name of the shiai as string private $name = null; //< name of the shiai as string
private $ageclasses = null; //< age classes as space separated 'Uxy' in a string private $ageclasses = null; //< age classes as space separated 'Uxy' in a string
private $place = null; //< place of the shiai as string private $place = null; //< place of the shiai as string
private $announcementUrl = null; //< url to the announcement private $announcementUrl = null; //< url to the announcement
private $routeUrl = null; //< url to a routing planner private $routeUrl = null; //< url to a routing planner
private $galleryUrl = null; //< url of the gallery to a gallery of the shiai private $galleryUrl = null; //< url of the gallery to a gallery of the shiai
private $promoImgUrl = null; //< promotional image for the shiai (as url) private $promoImgUrl = null; //< promotional image for the shiai (as url)
/** name of the table in the db holding the Shiai-s /** name of the table in the db holding the Shiai-s
* *
* @var string * @var string
*/ */
private static $tableName = "wettkampfkalender"; private static $tableName = "wettkampfkalender";
public function __construct($id, $date, $name, $ageclasses, $place, $announcementUrl, $routeUrl, $galleryUrl=null, $promoImgUrl=null) public function __construct(
{ $id,
//! @todo input validation and sanitation $date,
$this->id = filterId($id); $name,
$this->date = DateTime::createFromFormat('Y-m-d', $date); $ageclasses,
$this->name = $name; $place,
$this->ageclasses = $ageclasses ? self::akListString2jgArray($ageclasses) : null; $announcementUrl,
$this->place = $place; $routeUrl,
$this->announcementUrl = $announcementUrl; $galleryUrl = null,
$this->routeUrl = $routeUrl; $promoImgUrl = null
$this->galleryUrl = $galleryUrl; ) {
$this->promoImgUrl = $promoImgUrl; //! @todo input validation and sanitation
} $this->id = filterId($id);
$this->date = DateTime::createFromFormat("Y-m-d", $date);
$this->name = $name;
$this->ageclasses = $ageclasses
? self::akListString2jgArray($ageclasses)
: null;
$this->place = $place;
$this->announcementUrl = $announcementUrl;
$this->routeUrl = $routeUrl;
$this->galleryUrl = $galleryUrl;
$this->promoImgUrl = $promoImgUrl;
}
public static function fromArray(array $shiai){ public static function fromArray(array $shiai)
$id = $shiai['id'] ?? null; {
$date = $shiai['date'] ?? null; $id = $shiai["id"] ?? null;
$name = $shiai['name'] ?? null; $date = $shiai["date"] ?? null;
$ageclasses = $shiai['ageclasses'] ?? null; $name = $shiai["name"] ?? null;
$place = $shiai['place'] ?? null; $ageclasses = $shiai["ageclasses"] ?? null;
$announcementUrl = $shiai['announcementUrl'] ?? null; $place = $shiai["place"] ?? null;
$routeUrl = $shiai['routeUrl'] ?? null; $announcementUrl = $shiai["announcementUrl"] ?? null;
// gallery stuff removed for now $routeUrl = $shiai["routeUrl"] ?? null;
// gallery stuff removed for now
return new Shiai($id, $date, $name, $ageclasses, $place, $announcementUrl, $routeUrl); return new Shiai(
} $id,
$date,
$name,
$ageclasses,
$place,
$announcementUrl,
$routeUrl
);
}
public function asArray(){ public function asArray()
return [ {
'id'=>$this->id, return [
'date'=>$this->date->format('Y-m-d'), "id" => $this->id,
'name'=>$this->name, "date" => $this->date->format("Y-m-d"),
// @todo at least in theory this should again hold age categories "name" => $this->name,
'ageclasses'=>implode(" ", $this->ageclasses), // @todo at least in theory this should again hold age categories
'place'=>$this->place, "ageclasses" => implode(" ", $this->ageclasses),
'announcementUrl'=>$this->announcementUrl, "place" => $this->place,
'routeUrl'=>$this->announcementUrl "announcementUrl" => $this->announcementUrl,
]; "routeUrl" => $this->announcementUrl,
} ];
}
public function getId() public function getId()
{ {
return $this->id; return $this->id;
} }
public function getHtmlName() public function getHtmlName()
{ {
$name = ($this->name != null ? $this->name : 'Wettkampf ohne Namen'); $name = $this->name != null ? $this->name : "Wettkampf ohne Namen";
foreach (['meisterschaft', 'turnier', 'randori'] as $fragment) { foreach (["meisterschaft", "turnier", "randori"] as $fragment) {
$name = str_replace($fragment, '&shy;' . $fragment, $name); $name = str_replace($fragment, "&shy;" . $fragment, $name);
} }
return $name; return $name;
} }
public function getHtmlDate() public function getHtmlDate()
{ {
return ($this->date != null ? $this->date->format('Y-m-d') : 'fehlendes Datum'); return $this->date != null
} ? $this->date->format("Y-m-d")
: "fehlendes Datum";
}
public function getAgeClasses() public function getAgeClasses()
{ {
return ($this->ageclasses != null ? $this->ageclasses : '-'); return $this->ageclasses != null ? $this->ageclasses : "-";
} }
public function getPlace() public function getPlace()
{ {
return ($this->place != null ? $this->place : '-'); return $this->place != null ? $this->place : "-";
} }
public function getAnnouncementUrl() public function getAnnouncementUrl()
{ {
return $this->announcementUrl; return $this->announcementUrl;
} }
public function getRouteUrl() public function getRouteUrl()
{ {
return $this->routeUrl; return $this->routeUrl;
} }
public static function loadFromDb(int $id) public static function loadFromDb(int $id)
{ {
$id = filterId($id); $id = filterId($id);
$query = 'SELECT * FROM `cwsvjudo`.`wettkampfkalender` WHERE `lfdeNr` = :id;'; $query =
$params = [':id' => ['value' => $id, 'data_type' => PDO::PARAM_INT]]; "SELECT * FROM `cwsvjudo`.`wettkampfkalender` WHERE `lfdeNr` = :id;";
$response = dbConnector::query($query, $params); $params = [":id" => ["value" => $id, "data_type" => PDO::PARAM_INT]];
$response = dbConnector::query($query, $params);
// ids are considered unique. so every other count then 1 is treated as error to prevent unprivileged access // ids are considered unique. so every other count then 1 is treated as error to prevent unprivileged access
if (count($response) != 1) { if (count($response) != 1) {
return null; return null;
} }
return self::fromDbArray($response[0]); return self::fromDbArray($response[0]);
} }
/** select shiai from the database /** select shiai from the database
* *
* - by default, only coming events will be returned * - by default, only coming events will be returned
*/ */
public static function dbSelect(){ public static function dbSelect()
$query = "SELECT `".self::$tableName."`.* FROM `".self::$tableName."` WHERE `Datum` >= CURDATE();"; {
$response = dbConnector::query($query); $query =
"SELECT `" .
self::$tableName .
"`.* FROM `" .
self::$tableName .
"` WHERE `Datum` >= CURDATE();";
$response = dbConnector::query($query);
return $response; return $response;
} }
public static function fromDbArray($member) public static function fromDbArray($member)
{ {
return new shiai( return new shiai(
$member['lfdeNr'] ?? null, $member["lfdeNr"] ?? null,
$member['Datum'] ?? null, $member["Datum"] ?? null,
$member['Veranstaltung'] ?? '<fehlender Name>', $member["Veranstaltung"] ?? "<fehlender Name>",
$member['Altersklassen'] ?? null, $member["Altersklassen"] ?? null,
$member['Ort'] ?? '<fehlender Ort>', $member["Ort"] ?? "<fehlender Ort>",
$member['Ausschreibung'] ?? null, $member["Ausschreibung"] ?? null,
$member['Routenplaner'] ?? null, $member["Routenplaner"] ?? null,
$member['galleryLink'] ?? null, $member["galleryLink"] ?? null,
$member['promoPic'] ?? null $member["promoPic"] ?? null
); );
} }
/** shiai event as html code for displaying /** shiai event as html code for displaying
* *
* @return html formatted string * @return html formatted string
*/ */
public function getHtml() public function getHtml()
{ {
$retHtml = ''; $retHtml = "";
$retHtml = $retHtml =
'<div>' . "<div>" .
'<h3><a href="' . $this->announcementUrl . '">' . $this->getHtmlName() . '</a></h3>' . '<h3><a href="' .
'<dl>' . $this->announcementUrl .
'<dt>Datum</dt><dd>' . $this->getHtmlDate() . '</dd>' . '">' .
'<dt>Altersklassen</dt><dd>' . $this->getHtmlDescriptiveAgeClasses() . '</dd>' . $this->getHtmlName() .
'<dt>Ort</dt><dd><a href="' . $this->routeUrl . '">' . $this->getPlace() . '</a></dd>' . "</a></h3>" .
'</dl>' . "<dl>" .
'</div>'; "<dt>Datum</dt><dd>" .
return $retHtml; $this->getHtmlDate() .
} "</dd>" .
"<dt>Altersklassen</dt><dd>" .
$this->getHtmlDescriptiveAgeClasses() .
"</dd>" .
'<dt>Ort</dt><dd><a href="' .
$this->routeUrl .
'">' .
$this->getPlace() .
"</a></dd>" .
"</dl>" .
"</div>";
return $retHtml;
}
public function getHtmlDetails() public function getHtmlDetails()
{ {
return return "<dl>" .
'<dl>' '<dt>Name</dt><dd><a href="' .
. '<dt>Name</dt><dd><a href="' . $this->announcementUrl . '">' . $this->getHtmlName() . '</a></dd>' $this->announcementUrl .
. '<dt>Datum</dt><dd>' . $this->getHtmlDate() . '</dd>' '">' .
. '<dt>Altersklassen</dt><dd>' . $this->getHtmlDescriptiveAgeClasses() . '</dd>' $this->getHtmlName() .
. '<dt>Ort</dt><dd><a href="' . $this->routeUrl . '">' . $this->getPlace() . '</a></dd>' . "</a></dd>" .
'</dl>' "<dt>Datum</dt><dd>" .
; $this->getHtmlDate() .
} "</dd>" .
"<dt>Altersklassen</dt><dd>" .
$this->getHtmlDescriptiveAgeClasses() .
"</dd>" .
'<dt>Ort</dt><dd><a href="' .
$this->routeUrl .
'">' .
$this->getPlace() .
"</a></dd>" .
"</dl>";
}
public function getHtmlDescriptiveAgeClasses() public function getHtmlDescriptiveAgeClasses()
{ {
$retList = []; return join(", ", $this->ageclasses);
foreach ($this->ageclasses as $ageclass => $years) { }
$htmlFragment = $ageclass;
$years = $years[0];
if ($years[0] || $years[1]) { /** convert a list of age class formatted strings into a list of intervals of years
$htmlFragment .= '('; *
if ($years[1]) { * @param string $akListString
$htmlFragment .= strval($years[0]) . '-' . strval($years[1]); * @param int $year
} else { * @return list[array(int,int)] list of tupels with lower/upper bound in date year of the age classes
$htmlFragment .= '<=' . strval($years[0]); */
} private static function akListString2jgArray(
$htmlFragment .= ')'; string $akListString,
} ?int $year = null
$retList[] = $htmlFragment; ) {
} $year =
return implode(', ', $retList); filterPosInt($year) ?? filterPosInt((new DateTime())->format("Y"));
}
/** convert a list of age class formatted strings into a list of intervals of years $ageGroups = [];
* foreach (explode(" ", $akListString) as $label) {
* @param string $akListString $ageGroups[$label] = AgeGroup::create($label, $year);
* @param int $year }
* @return list[array(int,int)] list of tupels with lower/upper bound in date year of the age classes
*/
private static function akListString2jgArray(string $akListString, int $year = null)
{
$year = filterPosInt($year) ?? filterPosInt((new DateTime)->format('Y'));
$ret = [];
foreach (explode(' ', $akListString) as $ak) {
$ret[$ak] = self::akString2jgIntervall($ak, $year);
}
return $ret;
}
/** convert age class from formatted string to interval of years return $ageGroups;
* }
* @param [string] $akString
* @param [type] $year
* @return array(int,int) [x,y] with x the lower bound and y the upper bound of the age class in years. Both bounds are still included in the interval.
*/
private static function akString2jgIntervall(string $akString, int $year /*= null*/)
{
// input sanitation
$year = filterPosInt($year) ?? filterPosInt((new DateTime)->format('Y'));
$ret = [null, null]; /** convert age class from formatted string to interval of years
*
* @param [string] $akString
* @param [type] $year
* @return array(int,int) [x,y] with x the lower bound and y the upper bound of the age class in years. Both bounds are still included in the interval.
*/
private static function akString2jgIntervall(string $akString, int $year)
{
/*= null*/ // input sanitation
$year =
filterPosInt($year) ?? filterPosInt((new DateTime())->format("Y"));
// Matching against the different age class formats $ret = [null, null];
// - ..Ux
// - Jg.x-y
// Case Ux // Matching against the different age class formats
$akUmatchString = '/(.*)U(.*)/'; // - ..Ux
// - Jg.x-y
$matches = []; // Case Ux
$akUmatchString = "/(.*)U(.*)/";
preg_match($akUmatchString, $akString, $matches); $matches = [];
// The found match should cover the whole string. Otherwise it isn't applicable.
if ($matches[0] == $akString) {
// The x in Ux should be a positive integer.
$ageLimit = filterPosInt($matches[2]);
if ($ageLimit) {
$ret[0] = $year - $ageLimit + 1;
// lowering the lower bound according to the modifiers
if ($matches[1] == '') {
$ret[1] = $year - $ageLimit + 2;
} elseif ($matches[1] == '-') {
$ret[1] = $year - $ageLimit + 3;
} elseif ($matches[1] == '--') {
$ret[1] = $year - $ageLimit + 4;
} elseif (in_array($matches[1], ['<=', '&le;', '&#x2264;', '&#8804;', '≤'])) {
$ret[1] = $year;
}
return $ret;
}
}
// Case Jg.x-y preg_match($akUmatchString, $akString, $matches);
$akUmatchString = "/Jg\.(.*)\-{1,2}(.*)/"; // The found match should cover the whole string. Otherwise it isn't applicable.
if ($matches[0] == $akString) {
// The x in Ux should be a positive integer.
$ageLimit = filterPosInt($matches[2]);
if ($ageLimit) {
$ret[0] = $year - $ageLimit + 1;
// lowering the lower bound according to the modifiers
if ($matches[1] == "") {
$ret[1] = $year - $ageLimit + 2;
} elseif ($matches[1] == "-") {
$ret[1] = $year - $ageLimit + 3;
} elseif ($matches[1] == "--") {
$ret[1] = $year - $ageLimit + 4;
} elseif (
in_array($matches[1], [
"<=",
"&le;",
"&#x2264;",
"&#8804;",
"",
])
) {
$ret[1] = $year;
}
return $ret;
}
}
$matches = []; // Case Jg.x-y
$akUmatchString = "/Jg\.(.*)\-{1,2}(.*)/";
preg_match($akUmatchString, $akString, $matches); $matches = [];
// The found match should cover the whole string. Otherwise it isn't applicable.
if ($matches[0] == $akString) { preg_match($akUmatchString, $akString, $matches);
$ret[0] = filterPosInt($matches[1]); // The found match should cover the whole string. Otherwise it isn't applicable.
$ret[1] = filterPosInt($matches[2]);
return $ret; if ($matches[0] == $akString) {
} $ret[0] = filterPosInt($matches[1]);
$ret[1] = filterPosInt($matches[2]);
return $ret; return $ret;
} }
/** grouping users kids by ageGroups return $ret;
* }
* @return array(ageGroup => list(users in ageGroup))
*/
public function ageGroups()
{
$kids = participo::getKids();
return self::ageClassGrouping($this->ageclasses, $kids);
}
/** grouping users by given age class /** grouping users kids by ageGroups
* *
* @param array $ageClassList as array string representation of age class => [lower year bound, upper year bound] * @return array(ageGroup => list(users in ageGroup))
* @param array $starterList list of starter (User) */
* @return array of string representation of age class => array of userId=>user in this class public function ageGroups()
*/ {
private static function ageClassGrouping(array $ageClassList, array $starterList) $kids = participo::getKids();
{ return self::ageClassGrouping($this->ageclasses, $kids);
$grouping = []; }
foreach ($ageClassList as $ageClass => $yearBoundaries) {
$grouping[$ageClass] = [];
}
$grouping[null] = [];
foreach ($starterList as $starter) { /** grouping users by given age class
$startersAgeClass = $starter->yearOfBirth() ? self::getAgeClassFromYear($starter->yearOfBirth(), $ageClassList) : null; *
$grouping[$startersAgeClass][$starter->getId()] = $starter; * @param array $ageClassList as array string representation of age class => [lower year bound, upper year bound]
} * @param array $starterList list of starter (User)
return $grouping; * @return array of string representation of age class => array of userId=>user in this class
} */
private static function ageClassGrouping(
array $ageClassList,
array $starterList
) {
$grouping = [];
private static function getAgeClassFromYear(int $year, array $ageClassList) foreach ($ageClassList as $ageClass => $yearBoundaries) {
{ $grouping[$ageClass] = [];
foreach ($ageClassList as $ageClass => $yearBoundaries) { }
if (($yearBoundaries[0] <= $year) && ($year <= $yearBoundaries[1])) { $grouping[null] = [];
return $ageClass;
} foreach ($starterList as $starter) {
} $startersAgeClass = $starter->yearOfBirth()
return null; ? self::getAgeClassFromYear(
} $starter->yearOfBirth(),
$ageClassList
)
: null;
$grouping[$startersAgeClass][$starter->getId()] = $starter;
}
return $grouping;
}
private static function getAgeClassFromYear(int $year, array $ageClassList)
{
foreach ($ageClassList as $label => $ageGroup) {
if ($ageGroup->years()->contains($year)) {
return $label;
}
}
return null;
}
} // end class shiai } // end class shiai

View File

@@ -0,0 +1,26 @@
---
title: Training in den Osterferien
---
- [Training in den Osterferien](#training-in-den-osterferien)
- [Frühjahrskrümelrandori](#frühjahrskrümelrandori)
## Training in den Osterferien
Auch während der gesamten wird wieder trainiert werden können:
- Karfreitag: 29.03.2024
- 16:00--17:45 Uhr (Kinder/Anfänger)
- 17:30--19:15 Uhr (Jugend/Fortgeschrittene)
- Mittwoch: 03.04.2024
- 16:00--17:45 Uhr (alle)
- Da das Dojo anderweitig benötigt wird, werden wir das Training nach draußen verlegen. Bitte an entsprechende Kleidung (insbesondere Schuhe).
- Freitag: 05.04.2024
- 16:00--17:45 Uhr (Kinder/Anfänger)
- 17:30--19:15 Uhr (Jugend/Fortgeschrittene)
## Frühjahrskrümelrandori
Am 2023-04-13 wird das [27. Frühjahrskrümel­randori (U11--)][wk218] stattfinden. Bitte im [Wettkampfplaner][wk218] eintragen wer teilnehmen will und wer nicht.
[wk218]: http://cwsvjudo.bplaced.net/participo/events#218

View File

@@ -0,0 +1,21 @@
---
title: Training am Freitag, 2024-04-05
---
- [Training am Freitag, 2024-04-05](#training-am-freitag-2024-04-05)
- [Frühjahrskrümelrandori](#frühjahrskrümelrandori)
## Training am Freitag, 2024-04-05
Spontan haben die Karateka angefragt, für ihr Trainingslager am Freitag noch einmal in das Dojo zu können und ich habe zugesagt. Für das unser Training bedeutet das:
- Das Training der Kinder/Anfänger wird noch wie gewohnt im Dojo stattfinden, aber überpünktlich bereits *17:30* enden:
- 16:00--*17:30* Uhr (Kinder/Anfänger)
- Bei den Großen wird es dann wie jeden ersten Freitag im Monat den Kraftkreis geben. Bei gutem Wetter draußen, bei schlechtem in einer Kabine:
- 17:30--19:15 Uhr (Kraftkreis)
## Frühjahrskrümelrandori
Am 2023-04-13 wird das [27. Frühjahrskrümel­randori (U11--)][wk218] stattfinden. Bitte im [Wettkampfplaner][wk218] eintragen wer teilnehmen will und wer nicht.
[wk218]: http://cwsvjudo.bplaced.net/participo/events#218

View File

@@ -0,0 +1,5 @@
.PHONY: build
build:
npm install
npm run release

5
submodules/buildVideoJs.sh Executable file
View File

@@ -0,0 +1,5 @@
#! /usr/bin/env bash
cd video.js
npm install
npm run release