X-Git-Url: https://git.rapsys.eu/airbundle/blobdiff_plain/f110b8ba20232e0ceeb67390f8e672431868d32d..e1f07d8f8350aed7dba10735f9edcf062ec4cef5:/Entity/Session.php

diff --git a/Entity/Session.php b/Entity/Session.php
index 72d1f33..084580e 100644
--- a/Entity/Session.php
+++ b/Entity/Session.php
@@ -1,7 +1,19 @@
-<?php
+<?php declare(strict_types=1);
+
+/*
+ * this file is part of the rapsys packbundle package.
+ *
+ * (c) raphaël gertz <symfony@rapsys.eu>
+ *
+ * for the full copyright and license information, please view the license
+ * file that was distributed with this source code.
+ */
 
 namespace Rapsys\AirBundle\Entity;
 
+use Doctrine\Common\Collections\ArrayCollection;
+use Doctrine\ORM\Event\PreUpdateEventArgs;
+
 /**
  * Session
  */
@@ -24,7 +36,67 @@ class Session {
 	/**
 	 * @var \DateTime
 	 */
-	private $end;
+	private $start;
+
+	/**
+	 * @var \DateTime
+	 */
+	private $length;
+
+	/**
+	 * @var \DateTime
+	 */
+	private $stop;
+
+	/**
+	 * @var boolean
+	 */
+	private $premium;
+
+	/**
+	 * @var float
+	 */
+	private $rainfall;
+
+	/**
+	 * @var float
+	 */
+	private $rainrisk;
+
+	/**
+	 * @var float
+	 */
+	private $realfeel;
+
+	/**
+	 * @var float
+	 */
+	private $realfeelmin;
+
+	/**
+	 * @var float
+	 */
+	private $realfeelmax;
+
+	/**
+	 * @var float
+	 */
+	private $temperature;
+
+	/**
+	 * @var float
+	 */
+	private $temperaturemin;
+
+	/**
+	 * @var float
+	 */
+	private $temperaturemax;
+
+	/**
+	 * @var \DateTime
+	 */
+	private $locked;
 
 	/**
 	 * @var \DateTime
@@ -37,25 +109,47 @@ class Session {
 	private $updated;
 
 	/**
-	 * @var \Doctrine\Common\Collections\Collection
+	 * @var Application
 	 */
-	private $applications;
+	private $application;
 
 	/**
-	 * @var \Rapsys\AirBundle\Entity\Location
+	 * @var Location
 	 */
 	private $location;
 
 	/**
-	 * @var \Rapsys\AirBundle\Entity\Application
+	 * @var Slot
 	 */
-	private $application;
+	private $slot;
+
+	/**
+	 * @var ArrayCollection
+	 */
+	private $applications;
 
 	/**
 	 * Constructor
 	 */
 	public function __construct() {
-		$this->applications = new \Doctrine\Common\Collections\ArrayCollection();
+		//Set defaults
+		$this->begin = null;
+		$this->start = null;
+		$this->length = null;
+		$this->stop = null;
+		$this->premium = null;
+		$this->rainfall = null;
+		$this->rainrisk = null;
+		$this->realfeel = null;
+		$this->realfeelmin = null;
+		$this->realfeelmax = null;
+		$this->temperature = null;
+		$this->temperaturemin = null;
+		$this->temperaturemax = null;
+		$this->locked = null;
+		$this->created = new \DateTime('now');
+		$this->updated = new \DateTime('now');
+		$this->applications = new ArrayCollection();
 	}
 
 	/**
@@ -63,7 +157,7 @@ class Session {
 	 *
 	 * @return integer
 	 */
-	public function getId() {
+	public function getId(): int {
 		return $this->id;
 	}
 
@@ -74,7 +168,7 @@ class Session {
 	 *
 	 * @return Session
 	 */
-	public function setDate($date) {
+	public function setDate(\DateTime $date): Session {
 		$this->date = $date;
 
 		return $this;
@@ -85,7 +179,7 @@ class Session {
 	 *
 	 * @return \DateTime
 	 */
-	public function getDate() {
+	public function getDate(): \DateTime {
 		return $this->date;
 	}
 
@@ -96,7 +190,7 @@ class Session {
 	 *
 	 * @return Session
 	 */
-	public function setBegin($begin) {
+	public function setBegin(?\DateTime $begin): Session {
 		$this->begin = $begin;
 
 		return $this;
@@ -107,30 +201,305 @@ class Session {
 	 *
 	 * @return \DateTime
 	 */
-	public function getBegin() {
+	public function getBegin(): ?\DateTime {
 		return $this->begin;
 	}
 
 	/**
-	 * Set end
+	 * Get start
+	 *
+	 * @return \DateTime
+	 */
+	public function getStart(): \DateTime {
+		//With start
+		if ($this->start !== null) {
+			return $this->start;
+		}
+
+		//Clone date
+		$this->start = clone $this->date;
+
+		//Check if after slot
+		//XXX: id=4 <=> title=After
+		if ($this->slot->getId() == 4) {
+			//Add one day
+			$this->start->add(new \DateInterval('P1D'));
+		}
+
+		//With begin
+		if ($this->begin !== null) {
+			//Set start time
+			$this->start->setTime(intval($this->begin->format('H')), intval($this->begin->format('i')), intval($this->begin->format('s')));
+		}
+
+		//Return start
+		return $this->start;
+	}
+
+	/**
+	 * Set length
+	 *
+	 * @param \DateTime $length
+	 *
+	 * @return Session
+	 */
+	public function setLength(?\DateTime $length): Session {
+		$this->length = $length;
+
+		return $this;
+	}
+
+	/**
+	 * Get length
+	 *
+	 * @return \DateTime
+	 */
+	public function getLength(): ?\DateTime {
+		return $this->length;
+	}
+
+	/**
+	 * Get stop
+	 *
+	 * @return \DateTime
+	 */
+	public function getStop(): \DateTime {
+		//Check start
+		if ($this->stop !== null) {
+			return $this->stop;
+		}
+
+		//Get start clone
+		$this->stop = clone $this->getStart();
+
+		//With length
+		if ($this->length !== null) {
+			//Set stop time
+			$this->stop->add(new \DateInterval('PT'.$this->length->format('H').'H'.$this->length->format('i').'M'.$this->length->format('s').'S'));
+		}
+
+		//Return date
+		return $this->stop;
+	}
+
+	/**
+	 * Set premium
+	 *
+	 * @param boolean $premium
+	 *
+	 * @return Session
+	 */
+	public function setPremium(bool $premium): Session {
+		$this->premium = $premium;
+
+		return $this;
+	}
+
+	/**
+	 * Get premium
+	 *
+	 * @return bool
+	 */
+	public function getPremium(): bool {
+		return $this->premium;
+	}
+
+	/**
+	 * Set rainfall
+	 *
+	 * @param float $rainfall
+	 *
+	 * @return Session
+	 */
+	public function setRainfall(?float $rainfall): Session {
+		$this->rainfall = $rainfall;
+
+		return $this;
+	}
+
+	/**
+	 * Get rainfall
+	 *
+	 * @return float
+	 */
+	public function getRainfall(): ?float {
+		return $this->rainfall;
+	}
+
+	/**
+	 * Set rainrisk
+	 *
+	 * @param float $rainrisk
+	 *
+	 * @return Session
+	 */
+	public function setRainrisk(?float $rainrisk): Session {
+		$this->rainrisk = $rainrisk;
+
+		return $this;
+	}
+
+	/**
+	 * Get rainrisk
+	 *
+	 * @return float
+	 */
+	public function getRainrisk(): ?float {
+		return $this->rainrisk;
+	}
+
+	/**
+	 * Set realfeel
+	 *
+	 * @param float $realfeel
+	 *
+	 * @return Session
+	 */
+	public function setRealfeel(?float $realfeel): Session {
+		$this->realfeel = $realfeel;
+
+		return $this;
+	}
+
+	/**
+	 * Get realfeel
+	 *
+	 * @return float
+	 */
+	public function getRealfeel(): ?float {
+		return $this->realfeel;
+	}
+
+	/**
+	 * Set realfeelmin
+	 *
+	 * @param float $realfeelmin
+	 *
+	 * @return Session
+	 */
+	public function setRealfeelmin(?float $realfeelmin): Session {
+		$this->realfeelmin = $realfeelmin;
+
+		return $this;
+	}
+
+	/**
+	 * Get realfeelmin
+	 *
+	 * @return float
+	 */
+	public function getRealfeelmin(): ?float {
+		return $this->realfeelmin;
+	}
+
+	/**
+	 * Set realfeelmax
+	 *
+	 * @param float $realfeelmax
+	 *
+	 * @return Session
+	 */
+	public function setRealfeelmax(?float $realfeelmax): Session {
+		$this->realfeelmax = $realfeelmax;
+
+		return $this;
+	}
+
+	/**
+	 * Get realfeelmax
+	 *
+	 * @return float
+	 */
+	public function getRealfeelmax(): ?float {
+		return $this->realfeelmax;
+	}
+
+	/**
+	 * Set temperature
 	 *
-	 * @param \DateTime $end
+	 * @param float $temperature
 	 *
 	 * @return Session
 	 */
-	public function setEnd($end) {
-		$this->end = $end;
+	public function setTemperature(?float $temperature): Session {
+		$this->temperature = $temperature;
 
 		return $this;
 	}
 
 	/**
-	 * Get end
+	 * Get temperature
+	 *
+	 * @return float
+	 */
+	public function getTemperature(): ?float {
+		return $this->temperature;
+	}
+
+	/**
+	 * Set temperaturemin
+	 *
+	 * @param float $temperaturemin
+	 *
+	 * @return Session
+	 */
+	public function setTemperaturemin(?float $temperaturemin): Session {
+		$this->temperaturemin = $temperaturemin;
+
+		return $this;
+	}
+
+	/**
+	 * Get temperaturemin
+	 *
+	 * @return float
+	 */
+	public function getTemperaturemin(): ?float {
+		return $this->temperaturemin;
+	}
+
+	/**
+	 * Set temperaturemax
+	 *
+	 * @param float $temperaturemax
+	 *
+	 * @return Session
+	 */
+	public function setTemperaturemax(?float $temperaturemax): Session {
+		$this->temperaturemax = $temperaturemax;
+
+		return $this;
+	}
+
+	/**
+	 * Get temperaturemax
+	 *
+	 * @return float
+	 */
+	public function getTemperaturemax(): ?float {
+		return $this->temperaturemax;
+	}
+
+	/**
+	 * Set locked
+	 *
+	 * @param \DateTime $locked
+	 *
+	 * @return Session
+	 */
+	public function setLocked(?\DateTime $locked): Session {
+		$this->locked = $locked;
+
+		return $this;
+	}
+
+	/**
+	 * Get locked
 	 *
 	 * @return \DateTime
 	 */
-	public function getEnd() {
-		return $this->end;
+	public function getLocked(): ?\DateTime {
+		return $this->locked;
 	}
 
 	/**
@@ -140,7 +509,7 @@ class Session {
 	 *
 	 * @return Session
 	 */
-	public function setCreated($created) {
+	public function setCreated(\DateTime $created): Session {
 		$this->created = $created;
 
 		return $this;
@@ -151,7 +520,7 @@ class Session {
 	 *
 	 * @return \DateTime
 	 */
-	public function getCreated() {
+	public function getCreated(): \DateTime {
 		return $this->created;
 	}
 
@@ -162,7 +531,7 @@ class Session {
 	 *
 	 * @return Session
 	 */
-	public function setUpdated($updated) {
+	public function setUpdated(\DateTime $updated): Session {
 		$this->updated = $updated;
 
 		return $this;
@@ -173,18 +542,18 @@ class Session {
 	 *
 	 * @return \DateTime
 	 */
-	public function getUpdated() {
+	public function getUpdated(): \DateTime {
 		return $this->updated;
 	}
 
 	/**
 	 * Add application
 	 *
-	 * @param \Rapsys\AirBundle\Entity\Application $application
+	 * @param Application $application
 	 *
 	 * @return Session
 	 */
-	public function addApplication(\Rapsys\AirBundle\Entity\Application $application) {
+	public function addApplication(Application $application): Session {
 		$this->applications[] = $application;
 
 		return $this;
@@ -193,29 +562,29 @@ class Session {
 	/**
 	 * Remove application
 	 *
-	 * @param \Rapsys\AirBundle\Entity\Application $application
+	 * @param Application $application
 	 */
-	public function removeApplication(\Rapsys\AirBundle\Entity\Application $application) {
-		$this->applications->removeElement($application);
+	public function removeApplication(Application $application): bool {
+		return $this->applications->removeElement($application);
 	}
 
 	/**
 	 * Get applications
 	 *
-	 * @return \Doctrine\Common\Collections\Collection
+	 * @return ArrayCollection
 	 */
-	public function getApplications() {
+	public function getApplications(): ArrayCollection {
 		return $this->applications;
 	}
 
 	/**
 	 * Set location
 	 *
-	 * @param \Rapsys\AirBundle\Entity\Location $location
+	 * @param Location $location
 	 *
 	 * @return Session
 	 */
-	public function setLocation(\Rapsys\AirBundle\Entity\Location $location = null) {
+	public function setLocation(Location $location): Session {
 		$this->location = $location;
 
 		return $this;
@@ -224,25 +593,20 @@ class Session {
 	/**
 	 * Get location
 	 *
-	 * @return \Rapsys\AirBundle\Entity\Location
+	 * @return Location
 	 */
-	public function getLocation() {
+	public function getLocation(): Location {
 		return $this->location;
 	}
-	/**
-	 * @var \Rapsys\AirBundle\Entity\Slot
-	 */
-	private $slot;
-
 
 	/**
 	 * Set slot
 	 *
-	 * @param \Rapsys\AirBundle\Entity\Slot $slot
+	 * @param Slot $slot
 	 *
 	 * @return Session
 	 */
-	public function setSlot(\Rapsys\AirBundle\Entity\Slot $slot = null) {
+	public function setSlot(Slot $slot): Session {
 		$this->slot = $slot;
 
 		return $this;
@@ -251,20 +615,20 @@ class Session {
 	/**
 	 * Get slot
 	 *
-	 * @return \Rapsys\AirBundle\Entity\Slot
+	 * @return Slot
 	 */
-	public function getSlot() {
+	public function getSlot(): Slot {
 		return $this->slot;
 	}
 
 	/**
 	 * Set application
 	 *
-	 * @param \Rapsys\AirBundle\Entity\Application $application
+	 * @param Application $application
 	 *
 	 * @return Session
 	 */
-	public function setApplication(\Rapsys\AirBundle\Entity\Application $application = null) {
+	public function setApplication(Application $application): Session {
 		$this->application = $application;
 
 		return $this;
@@ -273,9 +637,168 @@ class Session {
 	/**
 	 * Get application
 	 *
-	 * @return \Rapsys\AirBundle\Entity\Application
+	 * @return Application
 	 */
-	public function getApplication() {
+	public function getApplication(): ?Application {
 		return $this->application;
 	}
+
+	/**
+	 * {@inheritdoc}
+	 */
+	public function preUpdate(PreUpdateEventArgs $eventArgs) {
+		//Check that we have a session instance
+		if (($session = $eventArgs->getEntity()) instanceof Session) {
+			//Set updated value
+			$session->setUpdated(new \DateTime('now'));
+		}
+	}
+
+	/**
+	 * Wether if session is a premium day
+	 *
+	 * Consider as premium a day off for afternoon, the eve for evening and after
+	 * Store computed result in premium member for afternoon and evening
+	 *
+	 * @return bool Whether the date is day off or not
+	 */
+	public function isPremium(): bool {
+		//Without date
+		if (empty($date = $this->date)) {
+			throw new \LogicException('Property date is empty');
+		}
+
+		//Without slot
+		if (empty($slot = $this->slot) || empty($slotTitle = $slot->getTitle())) {
+			throw new \LogicException('Property slot is empty');
+		}
+
+		//With evening and after slot
+		if ($slotTitle == 'Evening' || $slotTitle == 'After') {
+			//Evening and after session is considered premium when the eve is a day off
+			$date = (clone $date)->add(new \DateInterval('P1D'));
+		}
+
+		//Get day number
+		$w = $date->format('w');
+
+		//Check if weekend day
+		if ($w == 0 || $w == 6) {
+			//With afternoon and evening slot
+			if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+				//Save premium
+				$this->premium = true;
+			}
+
+			//Date is weekend day
+			return true;
+		}
+
+		//Get date day
+		$d = $date->format('d');
+
+		//Get date month
+		$m = $date->format('m');
+
+		//Check if fixed holiday
+		if (
+			//Check if 1st january
+			($d == 1 && $m == 1) ||
+			//Check if 1st may
+			($d == 1 && $m == 5) ||
+			//Check if 8st may
+			($d == 8 && $m == 5) ||
+			//Check if 14st july
+			($d == 14 && $m == 7) ||
+			//Check if 15st august
+			($d == 15 && $m == 8) ||
+			//Check if 1st november
+			($d == 1 && $m == 11) ||
+			//Check if 11st november
+			($d == 11 && $m == 11) ||
+			//Check if 25st december
+			($d == 25 && $m == 12)
+		) {
+			//With afternoon and evening slot
+			if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+				//Save premium
+				$this->premium = true;
+			}
+
+			//Date is a fixed holiday
+			return true;
+		}
+
+		//Get eastern
+		$eastern = $this->getEastern($date->format('Y'));
+
+		//Check dynamic holidays
+		if (
+			(clone $eastern)->add(new \DateInterval('P1D')) == $date ||
+			(clone $eastern)->add(new \DateInterval('P39D')) == $date ||
+			(clone $eastern)->add(new \DateInterval('P50D')) == $date
+		) {
+			//With afternoon and evening slot
+			if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+				//Save premium
+				$this->premium = true;
+			}
+
+			//Date is a dynamic holiday
+			return true;
+		}
+
+		//With afternoon and evening slot
+		if ($slotTitle == 'Afternoon' || $slotTitle == 'Evening') {
+			//Save premium
+			$this->premium = false;
+		}
+
+		//Date is not a holiday and week day
+		return false;
+	}
+
+	/**
+	 * Compute eastern for selected year
+	 *
+	 * @param string $year The eastern year
+	 *
+	 * @return DateTime The eastern date
+	 */
+	private function getEastern(string $year): \DateTime {
+		//Set static
+		static $data = null;
+
+		//Check if already computed
+		if (isset($data[$year])) {
+			//Return computed eastern
+			return $data[$year];
+		//Check if data is null
+		} elseif (is_null($data)) {
+			//Init data array
+			$data = [];
+		}
+
+		$d = (19 * ($year % 19) + 24) % 30;
+
+		$e = (2 * ($year % 4) + 4 * ($year % 7) + 6 * $d + 5) % 7;
+
+		$day = 22 + $d + $e;
+
+		$month = 3;
+
+		if ($day > 31) {
+			$day = $d + $e - 9;
+			$month = 4;
+		} elseif ($d == 29 && $e == 6) {
+			$day = 10;
+			$month = 4;
+		} elseif ($d == 28 && $e == 6) {
+			$day = 18;
+			$month = 4;
+		}
+
+		//Store eastern in data
+		return ($data[$year] = new \DateTime(sprintf('%04d-%02d-%02d', $year, $month, $day)));
+	}
 }