374 lines
11 KiB
PHP
374 lines
11 KiB
PHP
<?php
|
|
require_once "participoLib/participo.php";
|
|
require_once "participoLib/ageGroup.php";
|
|
|
|
/** frame for a shiai
|
|
*/
|
|
class Shiai
|
|
{
|
|
private $id = null; //< unique id
|
|
private $date = null; //< date of the shiai
|
|
private $name = null; //< name of the shiai as string
|
|
private $ageclasses = null; //< age classes as space separated 'Uxy' in a string
|
|
private $place = null; //< place of the shiai as string
|
|
private $announcementUrl = null; //< url to the announcement
|
|
private $routeUrl = null; //< url to a routing planner
|
|
private $galleryUrl = null; //< url of the gallery to a gallery of the shiai
|
|
private $promoImgUrl = null; //< promotional image for the shiai (as url)
|
|
|
|
/** name of the table in the db holding the Shiai-s
|
|
*
|
|
* @var string
|
|
*/
|
|
private static $tableName = "wettkampfkalender";
|
|
|
|
public function __construct(
|
|
$id,
|
|
$date,
|
|
$name,
|
|
$ageclasses,
|
|
$place,
|
|
$announcementUrl,
|
|
$routeUrl,
|
|
$galleryUrl = null,
|
|
$promoImgUrl = null
|
|
) {
|
|
//! @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)
|
|
{
|
|
$id = $shiai["id"] ?? null;
|
|
$date = $shiai["date"] ?? null;
|
|
$name = $shiai["name"] ?? null;
|
|
$ageclasses = $shiai["ageclasses"] ?? null;
|
|
$place = $shiai["place"] ?? null;
|
|
$announcementUrl = $shiai["announcementUrl"] ?? null;
|
|
$routeUrl = $shiai["routeUrl"] ?? null;
|
|
// gallery stuff removed for now
|
|
|
|
return new Shiai(
|
|
$id,
|
|
$date,
|
|
$name,
|
|
$ageclasses,
|
|
$place,
|
|
$announcementUrl,
|
|
$routeUrl
|
|
);
|
|
}
|
|
|
|
public function asArray()
|
|
{
|
|
return [
|
|
"id" => $this->id,
|
|
"date" => $this->date->format("Y-m-d"),
|
|
"name" => $this->name,
|
|
// @todo at least in theory this should again hold age categories
|
|
"ageclasses" => implode(" ", $this->ageclasses),
|
|
"place" => $this->place,
|
|
"announcementUrl" => $this->announcementUrl,
|
|
"routeUrl" => $this->announcementUrl,
|
|
];
|
|
}
|
|
|
|
public function getId()
|
|
{
|
|
return $this->id;
|
|
}
|
|
|
|
public function getHtmlName()
|
|
{
|
|
$name = $this->name != null ? $this->name : "Wettkampf ohne Namen";
|
|
foreach (["meisterschaft", "turnier", "randori"] as $fragment) {
|
|
$name = str_replace($fragment, "­" . $fragment, $name);
|
|
}
|
|
return $name;
|
|
}
|
|
|
|
public function getHtmlDate()
|
|
{
|
|
return $this->date != null
|
|
? $this->date->format("Y-m-d")
|
|
: "fehlendes Datum";
|
|
}
|
|
|
|
public function getAgeClasses()
|
|
{
|
|
return $this->ageclasses != null ? $this->ageclasses : "-";
|
|
}
|
|
|
|
public function getPlace()
|
|
{
|
|
return $this->place != null ? $this->place : "-";
|
|
}
|
|
|
|
public function getAnnouncementUrl()
|
|
{
|
|
return $this->announcementUrl;
|
|
}
|
|
|
|
public function getRouteUrl()
|
|
{
|
|
return $this->routeUrl;
|
|
}
|
|
|
|
public static function loadFromDb(int $id)
|
|
{
|
|
$id = filterId($id);
|
|
|
|
$query =
|
|
"SELECT * FROM `cwsvjudo`.`wettkampfkalender` WHERE `lfdeNr` = :id;";
|
|
$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
|
|
if (count($response) != 1) {
|
|
return null;
|
|
}
|
|
return self::fromDbArray($response[0]);
|
|
}
|
|
|
|
/** select shiai from the database
|
|
*
|
|
* - by default, only coming events will be returned
|
|
*/
|
|
public static function dbSelect()
|
|
{
|
|
$query =
|
|
"SELECT `" .
|
|
self::$tableName .
|
|
"`.* FROM `" .
|
|
self::$tableName .
|
|
"` WHERE `Datum` >= CURDATE();";
|
|
$response = dbConnector::query($query);
|
|
|
|
return $response;
|
|
}
|
|
|
|
public static function fromDbArray($member)
|
|
{
|
|
return new shiai(
|
|
$member["lfdeNr"] ?? null,
|
|
$member["Datum"] ?? null,
|
|
$member["Veranstaltung"] ?? "<fehlender Name>",
|
|
$member["Altersklassen"] ?? null,
|
|
$member["Ort"] ?? "<fehlender Ort>",
|
|
$member["Ausschreibung"] ?? null,
|
|
$member["Routenplaner"] ?? null,
|
|
$member["galleryLink"] ?? null,
|
|
$member["promoPic"] ?? null
|
|
);
|
|
}
|
|
|
|
/** shiai event as html code for displaying
|
|
*
|
|
* @return html formatted string
|
|
*/
|
|
public function getHtml()
|
|
{
|
|
$retHtml = "";
|
|
$retHtml =
|
|
"<div>" .
|
|
'<h3><a href="' .
|
|
$this->announcementUrl .
|
|
'">' .
|
|
$this->getHtmlName() .
|
|
"</a></h3>" .
|
|
"<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>" .
|
|
"</div>";
|
|
return $retHtml;
|
|
}
|
|
|
|
public function getHtmlDetails()
|
|
{
|
|
return "<dl>" .
|
|
'<dt>Name</dt><dd><a href="' .
|
|
$this->announcementUrl .
|
|
'">' .
|
|
$this->getHtmlName() .
|
|
"</a></dd>" .
|
|
"<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()
|
|
{
|
|
return join(", ", $this->ageclasses);
|
|
}
|
|
|
|
/** convert a list of age class formatted strings into a list of intervals of years
|
|
*
|
|
* @param string $akListString
|
|
* @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"));
|
|
|
|
$ageGroups = [];
|
|
foreach (explode(" ", $akListString) as $label) {
|
|
$ageGroups[$label] = AgeGroup::create($label, $year);
|
|
}
|
|
|
|
return $ageGroups;
|
|
}
|
|
|
|
/** 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"));
|
|
|
|
$ret = [null, null];
|
|
|
|
// Matching against the different age class formats
|
|
// - ..Ux
|
|
// - Jg.x-y
|
|
|
|
// Case Ux
|
|
$akUmatchString = "/(.*)U(.*)/";
|
|
|
|
$matches = [];
|
|
|
|
preg_match($akUmatchString, $akString, $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], [
|
|
"<=",
|
|
"≤",
|
|
"≤",
|
|
"≤",
|
|
"≤",
|
|
])
|
|
) {
|
|
$ret[1] = $year;
|
|
}
|
|
return $ret;
|
|
}
|
|
}
|
|
|
|
// Case Jg.x-y
|
|
$akUmatchString = "/Jg\.(.*)\-{1,2}(.*)/";
|
|
|
|
$matches = [];
|
|
|
|
preg_match($akUmatchString, $akString, $matches);
|
|
// The found match should cover the whole string. Otherwise it isn't applicable.
|
|
|
|
if ($matches[0] == $akString) {
|
|
$ret[0] = filterPosInt($matches[1]);
|
|
$ret[1] = filterPosInt($matches[2]);
|
|
|
|
return $ret;
|
|
}
|
|
|
|
return $ret;
|
|
}
|
|
|
|
/** grouping users kids by ageGroups
|
|
*
|
|
* @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
|
|
*
|
|
* @param array $ageClassList as array string representation of age class => [lower year bound, upper year bound]
|
|
* @param array $starterList list of starter (User)
|
|
* @return array of string representation of age class => array of userId=>user in this class
|
|
*/
|
|
private static function ageClassGrouping(
|
|
array $ageClassList,
|
|
array $starterList
|
|
) {
|
|
$grouping = [];
|
|
|
|
foreach ($ageClassList as $ageClass => $yearBoundaries) {
|
|
$grouping[$ageClass] = [];
|
|
}
|
|
$grouping[null] = [];
|
|
|
|
foreach ($starterList as $starter) {
|
|
$startersAgeClass = $starter->yearOfBirth()
|
|
? 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
|