Browse Source

Add forecast data, filtering and variation

Joachim M. Giæver 4 years ago
parent
commit
680204ab8f

+ 3 - 0
.gitmodules

@@ -0,0 +1,3 @@
+[submodule "sami-markdown"]
+	path = sami-markdown
+	url = git.giaever.org@git.giaever.org:joachimmg/sami-markdown.git

+ 1133 - 2
README.md

@@ -1,3 +1,1134 @@
-# yr-forecast
 
-Read forecast data from Yr.no. To use this you must credit by using the ```$f->getCredit()``` tag.
+Sami Markdown Extension
+===
+
+# Table of content    
+1. [App](#app "App")
+	1. [Yr](#appyr "App\Yr")
+		1. [Forecast](#appyrforecast "App\Yr\Forecast")
+			1. [Location](#location-appyrforecast "App\Yr\Forecast\Location") Get information about the location,such as name, timezone and geodata
+			2. [Tabular](#appyrforecasttabular "App\Yr\Forecast\Tabular")
+				1. [Time](#appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time")
+					1. [AbstractUnit](#abstractunit-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\AbstractUnit") Time-object entity should inherit this
+					2. [DiffInterface](#diffinterface-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\DiffInterface") Defines that an entity can be checked for differencesagains another entity.
+					3. [Pressure](#pressure-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\Pressure") Airpressure
+					4. [Symbol](#symbol-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\Symbol") Contains the sky data, e.g «Clody» etc
+					5. [Temperature](#temperature-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\Temperature") Temperature
+					6. [WindDirection](#winddirection-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\WindDirection") Wind direction
+					7. [WindSpeed](#windspeed-appyrforecasttabulartime "App\Yr\Forecast\Tabular\Time\WindSpeed") Wind speed
+				2. [Statistics](#statistics-appyrforecasttabular "App\Yr\Forecast\Tabular\Statistics") Make simple statistic on analysed time objects,such as highest/lowest wind speed and temperature,average wind speed and temperature etc.
+				3. [Time](#time-appyrforecasttabular "App\Yr\Forecast\Tabular\Time") Forecast data witin a time period
+				4. [Variations](#variations-appyrforecasttabular "App\Yr\Forecast\Tabular\Variations") Removes superfluous forecast data in an Time-objectonly storing changes.
+			3. [Tabular](#tabular-appyrforecast "App\Yr\Forecast\Tabular") Holds the forecast data in Time-objects.
+		2. [Forecast](#forecast-appyr "App\Yr\Forecast") Read forecast data from Yr.no for a specific location.
+
+
+---
+Documentation
+---
+
+# App
+
+ * [App\Yr](#appyr "Namespace: App\Yr")
+ * [App\Yr\Forecast](#appyrforecast "Namespace: App\Yr\Forecast")
+ * [App\Yr\Forecast\Tabular](#appyrforecasttabular "Namespace: App\Yr\Forecast\Tabular")
+ * [App\Yr\Forecast\Tabular\Time](#appyrforecasttabulartime "Namespace: App\Yr\Forecast\Tabular\Time")
+
+# App\Yr
+
+## Classes
+
+### Forecast `App\Yr`
+
+
+* Class is final
+
+Read forecast data from Yr.no for a specific location.
+
+Disclaimer: To use this package you are required
+to print the credits from the method ```getCredit()```
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecast)||public| |
+|[getLocation](#getlocation-appyrforecast)|[Location](#location-appyrforecast)|public| Returns the location data for the forecast|
+|[getCredit](#getcredit-appyrforecast)|array|final public| Return the credit to Yr.no, Meterogical Institute and NRK|
+|[getSunrise](#getsunrise-appyrforecast)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Returns the time when the sun rise for the location|
+|[getSunset](#getsunset-appyrforecast)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Returns the time when the sun sets for the location|
+|[getLinks](#getlinks-appyrforecast)|[enerator](https://www.google.no/search?q=Generator)|public| Returns links for forecasts in other formats|
+|[getLastUpdate](#getlastupdate-appyrforecast)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Return the time when this forecast was last update|
+|[getNextUpdate](#getnextupdate-appyrforecast)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Return the time when this forecast will update next|
+|[getTabular](#gettabular-appyrforecast)|[Tabular](#tabular-appyrforecast)|public| Get the forecast data|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast`
+```php
+public function __construct(string $url);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|string|$url|The XML url to load data from|
+---
+
+
+##### getLocation `App\Yr\Forecast`
+```php
+public function getLocation();
+```
+ Returns the location data for the forecast
+
+
+Returns: [Location](#location-appyrforecast)
+
+---
+
+
+##### getCredit `App\Yr\Forecast`
+```php
+final public function getCredit();
+```
+ Return the credit to Yr.no, Meterogical Institute and NRK
+
+
+Returns: array
+
+---
+
+
+##### getSunrise `App\Yr\Forecast`
+```php
+public function getSunrise();
+```
+ Returns the time when the sun rise for the location
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getSunset `App\Yr\Forecast`
+```php
+public function getSunset();
+```
+ Returns the time when the sun sets for the location
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getLinks `App\Yr\Forecast`
+```php
+public function getLinks();
+```
+ Returns links for forecasts in other formats
+
+
+Returns: [enerator](https://www.google.no/search?q=Generator)
+
+---
+
+
+##### getLastUpdate `App\Yr\Forecast`
+```php
+public function getLastUpdate();
+```
+ Return the time when this forecast was last update
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getNextUpdate `App\Yr\Forecast`
+```php
+public function getNextUpdate();
+```
+ Return the time when this forecast will update next
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getTabular `App\Yr\Forecast`
+```php
+public function getTabular();
+```
+ Get the forecast data
+
+
+Returns: [Tabular](#tabular-appyrforecast)
+
+---
+
+# App\Yr\Forecast
+
+## Classes
+
+### Location `App\Yr\Forecast`
+
+
+* Class is final
+
+Get information about the location,
+such as name, timezone and geodata
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecastlocation)||public| |
+|[getName](#getname-appyrforecastlocation)|string|public| Get the location name, e.g «Tromsø»|
+|[getType](#gettype-appyrforecastlocation)|string|public| Get the location type, e.g «City - large town»|
+|[getCountry](#getcountry-appyrforecastlocation)|string|public| Get the location country|
+|[getTimeZone](#gettimezone-appyrforecastlocation)|[ateTimeZone](https://www.google.no/search?q=DateTimeZone)|public| Get the location timezone|
+|[getGeoData](#getgeodata-appyrforecastlocation)|array|public| Returns the geodata, in the format```[     'lat' => (float),     'lng' => (float),     'alt' => (float),]```|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Location`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|The xml-part containing the location data|
+---
+
+
+##### getName `App\Yr\Forecast\Location`
+```php
+public function getName();
+```
+ Get the location name, e.g «Tromsø»
+
+
+Returns: string
+
+---
+
+
+##### getType `App\Yr\Forecast\Location`
+```php
+public function getType();
+```
+ Get the location type, e.g «City - large town»
+
+
+Returns: string
+
+---
+
+
+##### getCountry `App\Yr\Forecast\Location`
+```php
+public function getCountry();
+```
+ Get the location country
+
+
+Returns: string
+
+---
+
+
+##### getTimeZone `App\Yr\Forecast\Location`
+```php
+public function getTimeZone();
+```
+ Get the location timezone
+
+
+Returns: [ateTimeZone](https://www.google.no/search?q=DateTimeZone)
+
+---
+
+
+##### getGeoData `App\Yr\Forecast\Location`
+```php
+public function getGeoData();
+```
+ Returns the geodata, in the format
+```[
+     'lat' => (float),
+     'lng' => (float),
+     'alt' => (float),
+]```
+
+
+Returns: array
+
+---
+
+
+### Tabular `App\Yr\Forecast`
+
+
+* Class implements[IteratorAggregate](https://www.google.no/search?q=IteratorAggregate)
+
+Holds the forecast data in Time-objects.
+
+Use the ```getBetween``` option to limit the results.
+
+Class also makes a simple statistic on the forecast
+for the periode and a variation that will exclude
+repetitive forecast data.
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabular)||public| |
+|[addTime](#addtime-appyrforecasttabular)|[Tabular](#tabular-appyrforecast)|protected| Add a Time-object to the tabular|
+|[getStatistics](#getstatistics-appyrforecasttabular)|[Statistics](#statistics-appyrforecasttabular)|public| Get statistics for the Time-object collection|
+|[getVariations](#getvariations-appyrforecasttabular)|[Variations](#variations-appyrforecasttabular)|public| Remove superfluous weather data.|
+|[getBetween](#getbetween-appyrforecasttabular)|[Tabular](#tabular-appyrforecast)|public| Filter data between a certain periode, e.g```$forcast->between( $forcast->getSunset(), $forecast->getSunrise()->add(     new \DateInterval('P1D') ));```to only show from sunset today unti sunrise tomorrow|
+|[getIterator](#getiterator-appyrforecasttabular)|[enerator](https://www.google.no/search?q=Generator)|public| {@inheritDoc}|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular`
+```php
+public function __construct(SimpleXMLElement null $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement null|$xml|The xml part holding the time objects, can be null|
+---
+
+
+##### addTime `App\Yr\Forecast\Tabular`
+```php
+protected function addTime(Time $time);
+```
+ Add a Time-object to the tabular
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[Time](#tabular-appyrforecast)|$time|*None*|
+
+Returns: [Tabular](#tabular-appyrforecast)
+
+---
+
+
+##### getStatistics `App\Yr\Forecast\Tabular`
+```php
+public function getStatistics();
+```
+ Get statistics for the Time-object collection
+
+
+Returns: [Statistics](#statistics-appyrforecasttabular)
+
+---
+
+
+##### getVariations `App\Yr\Forecast\Tabular`
+```php
+public function getVariations();
+```
+ Remove superfluous weather data.
+
+Checks if the data in the Time-object differs from
+the current Time-object and returns the unique data
+
+
+Returns: [Variations](#variations-appyrforecasttabular)
+
+---
+
+
+##### getBetween `App\Yr\Forecast\Tabular`
+```php
+public function getBetween(DateTimeInterface $from, DateTimeInterface $until);
+```
+ Filter data between a certain periode, e.g
+```
+$forcast->between(
+ $forcast->getSunset(),
+ $forecast->getSunrise()->add(
+     new \DateInterval('P1D')
+ )
+);```
+to only show from sunset today unti sunrise tomorrow
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|DateTimeInterface|$from|*None*|
+|DateTimeInterface|$until|*None*|
+
+Returns: [Tabular](#tabular-appyrforecast)
+
+---
+
+
+##### getIterator `App\Yr\Forecast\Tabular`
+```php
+public function getIterator();
+```
+ {@inheritDoc}
+
+
+Returns: [enerator](https://www.google.no/search?q=Generator)
+
+---
+
+# App\Yr\Forecast\Tabular
+
+## Classes
+
+### Statistics `App\Yr\Forecast\Tabular`
+
+Make simple statistic on analysed time objects,
+such as highest/lowest wind speed and temperature,
+average wind speed and temperature etc.
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabularstatistics)||public| |
+|[analyse](#analyse-appyrforecasttabularstatistics)|[Statistics](#statistics-appyrforecasttabular)|public| Analyse a single Time-object|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Statistics`
+```php
+public function __construct();
+```
+---
+
+
+##### analyse `App\Yr\Forecast\Tabular\Statistics`
+```php
+public function analyse(Time $t);
+```
+ Analyse a single Time-object
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[Time](#tabular-appyrforecast)|$t|The time object.|
+
+Returns: [Statistics](#statistics-appyrforecasttabular)
+
+---
+
+
+### Time `App\Yr\Forecast\Tabular`
+
+
+* Class is final
+* Class implements[IteratorAggregate](https://www.google.no/search?q=IteratorAggregate)
+
+Forecast data witin a time period
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartime)||public| |
+|[getPeriod](#getperiod-appyrforecasttabulartime)|int|public| Returns the which index in the forecastits for.|
+|[getFrom](#getfrom-appyrforecasttabulartime)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Returns the time this forecast is from|
+|[getUntil](#getuntil-appyrforecasttabulartime)|[ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)|public| Returns the time this forecast is to/until.|
+|[getSymbol](#getsymbol-appyrforecasttabulartime)|[Symbol](#symbol-appyrforecasttabulartime)|public| Returns the «symbol» (e.g Clody etc)|
+|[getWindDirection](#getwinddirection-appyrforecasttabulartime)|[WindDirection](#winddirection-appyrforecasttabulartime)|public| Returns the wind direction|
+|[getWindSpeed](#getwindspeed-appyrforecasttabulartime)|[WindSpeed](#windspeed-appyrforecasttabulartime)|public| Returns the wind speed|
+|[getTemperature](#gettemperature-appyrforecasttabulartime)|[Temperature](#temperature-appyrforecasttabulartime)|public| Returns the temperature|
+|[getPressure](#getpressure-appyrforecasttabulartime)|[Pressure](#pressure-appyrforecasttabulartime)|public| Returns the pressure|
+|[getIterator](#getiterator-appyrforecasttabulartime)|[enerator](https://www.google.no/search?q=Generator)|public| {@inheritDoc}|
+|[__toString](#__tostring-appyrforecasttabulartime)|string|public| |
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|The xml holding the time-object|
+---
+
+
+##### getPeriod `App\Yr\Forecast\Tabular\Time`
+```php
+public function getPeriod();
+```
+ Returns the which index in the forecast
+its for.
+
+
+Returns: int
+
+---
+
+
+##### getFrom `App\Yr\Forecast\Tabular\Time`
+```php
+public function getFrom();
+```
+ Returns the time this forecast is from
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getUntil `App\Yr\Forecast\Tabular\Time`
+```php
+public function getUntil();
+```
+ Returns the time this forecast is to/until.
+
+
+Returns: [ateTimeImmutable](https://www.google.no/search?q=DateTimeImmutable)
+
+---
+
+
+##### getSymbol `App\Yr\Forecast\Tabular\Time`
+```php
+public function getSymbol();
+```
+ Returns the «symbol» (e.g Clody etc)
+
+
+Returns: [Symbol](#symbol-appyrforecasttabulartime)
+
+---
+
+
+##### getWindDirection `App\Yr\Forecast\Tabular\Time`
+```php
+public function getWindDirection();
+```
+ Returns the wind direction
+
+
+Returns: [WindDirection](#winddirection-appyrforecasttabulartime)
+
+---
+
+
+##### getWindSpeed `App\Yr\Forecast\Tabular\Time`
+```php
+public function getWindSpeed();
+```
+ Returns the wind speed
+
+
+Returns: [WindSpeed](#windspeed-appyrforecasttabulartime)
+
+---
+
+
+##### getTemperature `App\Yr\Forecast\Tabular\Time`
+```php
+public function getTemperature();
+```
+ Returns the temperature
+
+
+Returns: [Temperature](#temperature-appyrforecasttabulartime)
+
+---
+
+
+##### getPressure `App\Yr\Forecast\Tabular\Time`
+```php
+public function getPressure();
+```
+ Returns the pressure
+
+
+Returns: [Pressure](#pressure-appyrforecasttabulartime)
+
+---
+
+
+##### getIterator `App\Yr\Forecast\Tabular\Time`
+```php
+public function getIterator();
+```
+ {@inheritDoc}
+
+
+Returns: [enerator](https://www.google.no/search?q=Generator)
+
+---
+
+
+##### __toString `App\Yr\Forecast\Tabular\Time`
+```php
+public function __toString();
+```
+
+Returns: string
+
+---
+
+
+### Variations `App\Yr\Forecast\Tabular`
+
+Removes superfluous forecast data in an Time-object
+only storing changes.
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabularvariations)||public| |
+|[getData](#getdata-appyrforecasttabularvariations)|array|public| Returns the changes in the forecast|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Variations`
+```php
+public function __construct(array $t);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|array|$t|Array of Time-objects|
+---
+
+
+##### getData `App\Yr\Forecast\Tabular\Variations`
+```php
+public function getData(callable $filterFn = null);
+```
+ Returns the changes in the forecast
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|callable|$filterFn|*None*|
+
+Returns: array
+
+---
+
+# App\Yr\Forecast\Tabular\Time
+
+## Classes
+
+### AbstractUnit `App\Yr\Forecast\Tabular\Time`
+
+
+* Class is abstact
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Time-object entity should inherit this
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimeabstractunit)||public| |
+|[getValue](#getvalue-appyrforecasttabulartimeabstractunit)|float|public| Get the value|
+|[getUnit](#getunit-appyrforecasttabulartimeabstractunit)|string|public| Return the unit (e.g «degree»)|
+|[diff](#diff-appyrforecasttabulartimeabstractunit)|int|public| Check for differences with another DiffInterface.|
+|[__toString](#__tostring-appyrforecasttabulartimeabstractunit)|string|public| |
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\AbstractUnit`
+```php
+public function __construct(float $value, string $unit);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|float|$value|The value|
+|string|$unit|The unit|
+---
+
+
+##### getValue `App\Yr\Forecast\Tabular\Time\AbstractUnit`
+```php
+public function getValue();
+```
+ Get the value
+
+
+Returns: float
+
+---
+
+
+##### getUnit `App\Yr\Forecast\Tabular\Time\AbstractUnit`
+```php
+public function getUnit();
+```
+ Return the unit (e.g «degree»)
+
+
+Returns: string
+
+---
+
+
+##### diff `App\Yr\Forecast\Tabular\Time\AbstractUnit`
+```php
+public function diff(DiffInterface $d);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$d|*None*|
+
+Returns: int
+
+---
+
+
+##### __toString `App\Yr\Forecast\Tabular\Time\AbstractUnit`
+```php
+public function __toString();
+```
+
+Returns: string
+
+---
+
+
+### Pressure `App\Yr\Forecast\Tabular\Time`
+
+
+* Class extends [App\Yr\Forecast\Tabular\Time\AbstractUnit](#abstractunit-appyrforecasttabulartime)
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Airpressure
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimepressure)||public| |
+|[isLowPressure](#islowpressure-appyrforecasttabulartimepressure)|bool|public| Check if the pressure is below normal pressure|
+|[isHighPressure](#ishighpressure-appyrforecasttabulartimepressure)|bool|public| Check if the pressure is above normal pressure|
+|[diff](#diff-appyrforecasttabulartimepressure)|int|public| Check for differences with another DiffInterface.|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\Pressure`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|XML containing the pressure|
+---
+
+
+##### isLowPressure `App\Yr\Forecast\Tabular\Time\Pressure`
+```php
+public function isLowPressure();
+```
+ Check if the pressure is below normal pressure
+
+
+Returns: bool
+
+---
+
+
+##### isHighPressure `App\Yr\Forecast\Tabular\Time\Pressure`
+```php
+public function isHighPressure();
+```
+ Check if the pressure is above normal pressure
+
+
+Returns: bool
+
+---
+
+
+##### diff `App\Yr\Forecast\Tabular\Time\Pressure`
+```php
+public function diff(DiffInterface $d);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$d|*None*|
+
+Returns: int
+
+---
+
+
+### Symbol `App\Yr\Forecast\Tabular\Time`
+
+
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Contains the sky data, e.g «Clody» etc
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimesymbol)||public| |
+|[getNumber](#getnumber-appyrforecasttabulartimesymbol)|int|public| Retuns the type identifier|
+|[getName](#getname-appyrforecasttabulartimesymbol)|string|public| Returns the name, e.g «clody».|
+|[getVar](#getvar-appyrforecasttabulartimesymbol)|string|public| Return the var-variable|
+|[diff](#diff-appyrforecasttabulartimesymbol)|int|public| Check for differences with another DiffInterface.|
+|[__toString](#__tostring-appyrforecasttabulartimesymbol)|string|public| |
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|XML containing the symbol data|
+---
+
+
+##### getNumber `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function getNumber();
+```
+ Retuns the type identifier
+
+
+Returns: int
+
+---
+
+
+##### getName `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function getName();
+```
+ Returns the name, e.g «clody».
+
+
+Returns: string
+
+---
+
+
+##### getVar `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function getVar();
+```
+ Return the var-variable
+
+
+Returns: string
+
+---
+
+
+##### diff `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function diff(DiffInterface $s);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$s|*None*|
+
+Returns: int
+
+---
+
+
+##### __toString `App\Yr\Forecast\Tabular\Time\Symbol`
+```php
+public function __toString();
+```
+
+Returns: string
+
+---
+
+
+### Temperature `App\Yr\Forecast\Tabular\Time`
+
+
+* Class extends [App\Yr\Forecast\Tabular\Time\AbstractUnit](#abstractunit-appyrforecasttabulartime)
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Temperature
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimetemperature)||public| |
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\Temperature`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|XML containing the temperature|
+---
+
+
+### WindDirection `App\Yr\Forecast\Tabular\Time`
+
+
+* Class extends [App\Yr\Forecast\Tabular\Time\AbstractUnit](#abstractunit-appyrforecasttabulartime)
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Wind direction
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimewinddirection)||public| |
+|[getName](#getname-appyrforecasttabulartimewinddirection)|string|public| Returns the wind direction in full,e.g «Northeast».|
+|[diff](#diff-appyrforecasttabulartimewinddirection)|int|public| Check for differences with another DiffInterface.|
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\WindDirection`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|XML element containing the wind direction|
+---
+
+
+##### getName `App\Yr\Forecast\Tabular\Time\WindDirection`
+```php
+public function getName();
+```
+ Returns the wind direction in full,
+e.g «Northeast».
+
+
+Returns: string
+
+---
+
+
+##### diff `App\Yr\Forecast\Tabular\Time\WindDirection`
+```php
+public function diff(DiffInterface $d);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$d|*None*|
+
+Returns: int
+
+---
+
+
+### WindSpeed `App\Yr\Forecast\Tabular\Time`
+
+
+* Class extends [App\Yr\Forecast\Tabular\Time\AbstractUnit](#abstractunit-appyrforecasttabulartime)
+* Class implements[App\Yr\Forecast\Tabular\Time\DiffInterface](#diffinterface-appyrforecasttabulartime)
+
+Wind speed
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[__construct](#__construct-appyrforecasttabulartimewindspeed)||public| |
+|[convertTo](#convertto-appyrforecasttabulartimewindspeed)|int|public| Convert the wind speed to a different unit|
+|[getName](#getname-appyrforecasttabulartimewindspeed)|string|public| Returns the wind name, e.g «light breeze»|
+|[diff](#diff-appyrforecasttabulartimewindspeed)|int|public| Check for differences with another DiffInterface.|
+|[__toString](#__tostring-appyrforecasttabulartimewindspeed)|string|public| |
+
+#### Method details
+
+##### __construct `App\Yr\Forecast\Tabular\Time\WindSpeed`
+```php
+public function __construct(SimpleXMLElement $xml);
+```
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|SimpleXMLElement|$xml|XML containing the wind spedd|
+---
+
+
+##### convertTo `App\Yr\Forecast\Tabular\Time\WindSpeed`
+```php
+public function convertTo(string $unit);
+```
+ Convert the wind speed to a different unit
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|string|$unit|The unit to convert to, eg UNIT_FTS|
+
+Returns: int
+
+---
+
+
+##### getName `App\Yr\Forecast\Tabular\Time\WindSpeed`
+```php
+public function getName();
+```
+ Returns the wind name, e.g «light breeze»
+
+
+Returns: string
+
+---
+
+
+##### diff `App\Yr\Forecast\Tabular\Time\WindSpeed`
+```php
+public function diff(DiffInterface $e);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$e|*None*|
+
+Returns: int
+
+---
+
+
+##### __toString `App\Yr\Forecast\Tabular\Time\WindSpeed`
+```php
+public function __toString();
+```
+
+Returns: string
+
+---
+
+## Interfaces
+
+### DiffInterface `App\Yr\Forecast\Tabular\Time`
+
+Defines that an entity can be checked for differences
+agains another entity.
+
+#### Methods
+
+|Name|Return|Access|Description|
+|:---|:---|:---|:---|
+|[diff](#diff-appyrforecasttabulartimediffinterface)|int|public| Check for differences with another DiffInterface.|
+
+#### Method details
+
+##### diff `App\Yr\Forecast\Tabular\Time\DiffInterface`
+```php
+public function diff(DiffInterface $e);
+```
+ Check for differences with another DiffInterface.
+
+The method should check that the objects is the same.
+
+
+Parameters
+
+| Type | Variable | Description |
+|---|---|---|
+|[DiffInterface](#time-appyrforecasttabular)|$e|The object to check agains|
+
+Returns: int
+
+---
+
+
+ - Genetated using Sami and the [Sami/Twig Markdown Extension](https://git.giaever.org/joachimmg/sami-markdown)
+

+ 12 - 3
index.php

@@ -7,9 +7,18 @@ $url = 'https://www.yr.no/place/Norway/Troms/Tromsø/Tromsø/forecast_hour_by_ho
 $forecast = new App\Yr\Forecast($url);
 
 echo '<pre>';
-var_dump($forecast->getLocation());
-foreach ($forecast->getTabular()->getBetween(
+$range = $forecast->getTabular()->getBetween(
     $forecast->getSunset(), $forecast->getSunrise()->add(new \DateInterval('P1D'))
-) as $time)
+);
+
+foreach ($range as $time)
     echo $time . "\n";
+
+echo "\n<hr />\n";
+foreach ($range->getVariations()->getData() as $data) 
+    echo sprintf("%s: %s\n", $data['time']->getFrom()->format("H:i"), join(", ", $data['entities']));
+
+echo "\n";
+foreach ($forecast->getCredit() as $c)
+    echo $c . "\n";
 ?>

+ 1 - 0
sami-markdown

@@ -0,0 +1 @@
+Subproject commit ea769268e2a2cc9598f83cf8f46484b7ec87d67f

+ 56 - 4
src/Yr/Forecast.php

@@ -5,19 +5,41 @@ namespace App\Yr;
 use App\Yr\Forecast\Location;
 use App\Yr\Forecast\Tabular;
 
+/**
+ * Read forecast data from Yr.no for a specific location.
+ *
+ * Disclaimer: To use this package you are required
+ * to print the credits from the method ```getCredit()```
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ * @version 1.0
+ */
 final class Forecast {
     private $xml;
     private $location;
 
+    /**
+     * @param string $url The XML url to load data from
+     */
     public function __construct(string $url) {
         $this->xml = simplexml_load_file($url);
         $this->location = new Location($this->xml->location);
     }
 
+    /**
+     * Returns the location data for the forecast
+     *
+     * @return App\Forecast\Location
+     */
     public function getLocation(): Location {
         return $this->location;
     }
 
+    /**
+     * Return the credit to Yr.no, Meterogical Institute and NRK
+     *
+     * @return array
+     */
     final public function getCredit(): array {
         return [
             'text' => (string)$this->xml->credit->link->attributes()['text'],
@@ -25,14 +47,29 @@ final class Forecast {
         ];
     }
 
+    /**
+     * Returns the time when the sun rise for the location
+     *
+     * @return \DateTimeImmutable
+     */
     public function getSunrise(): \DateTimeImmutable {
-        return (new \DateTimeImmutable($this->xml->sun['rise']));
+        return new \DateTimeImmutable((string)$this->xml->sun['rise']);
     }
 
+    /**
+     * Returns the time when the sun sets for the location
+     *
+     * @return DateTimeImmutable
+     */
     public function getSunset(): \DateTimeImmutable {
-        return (new \DateTimeImmutable($this->xml->sun['seẗ́']));
+        return new \DateTimeImmutable((string)$this->xml->sun['set']);
     }
 
+    /**
+     * Returns links for forecasts in other formats
+     *
+     * @return \Generator
+     */
     public function getLinks(): \Generator {
         foreach ($this->xml->links->children() as $link)
             yield [
@@ -41,14 +78,29 @@ final class Forecast {
             ];
     }
 
+    /**
+     * Return the time when this forecast was last update
+     *
+     * @return \DateTimeImmutable
+     */
     public function getLastUpdate(): \DateTimeImmutable {
-        return new DateTimeImmutable($this->xml->meta->lastupdate);
+        return new DateTimeImmutable((string)$this->xml->meta->lastupdate);
     }
 
+    /**
+     * Return the time when this forecast will update next
+     *
+     * @return \DateTimeImmutable
+     */
     public function getNextUpdate(): \DateTimeImmutable {
-        return new DateTimeImmutable($this->xml->meta->nextupdate);
+        return new DateTimeImmutable((string)$this->xml->meta->nextupdate);
     }
 
+    /**
+     * Get the forecast data
+     *
+     * @return Tabular
+     */
     public function getTabular(): Tabular {
         return new Tabular($this->xml->forecast->tabular);
     }

+ 59 - 0
src/Yr/Forecast/Location.php

@@ -2,6 +2,12 @@
 
 namespace App\Yr\Forecast;
 
+/**
+ * Get information about the location,
+ * such as name, timezone and geodata
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 final class Location {
     private $name;
     private $type;
@@ -9,6 +15,9 @@ final class Location {
     private $tz;
     private $loc = [];
 
+    /**
+     * @param \SimpleXMLElement $xml The xml-part containing the location data
+     */
     public function __construct(\SimpleXMLElement $xml) {
         $this->name = (string)$xml->name;
         $this->type = (string)$xml->type;
@@ -20,6 +29,56 @@ final class Location {
             'alt' => (float)$xml->location['altitude']
         ];
     }
+
+    /**
+     * Get the location name, e.g «Tromsø»
+     *
+     * @return string
+     */
+    public function getName(): string {
+        return $this->name;
+    }
+
+    /**
+     * Get the location type, e.g «City - large town»
+     *
+     * @return string
+     */
+    public function getType(): string {
+        return $this->type;
+    }
+
+    /**
+     * Get the location country
+     *
+     * @return string
+     */
+    public function getCountry(): string {
+        return $this->country;
+    }
+
+    /**
+     * Get the location timezone
+     *
+     * @return \DateTimeZone
+     */
+    public function getTimeZone(): \DateTimeZone {
+        return new \DateTimeZone($this->tz);
+    }
+
+    /**
+     * Returns the geodata, in the format
+     * ```[
+     *      'lat' => (float),
+     *      'lng' => (float),
+     *      'alt' => (float),
+     * ]```
+     *
+     * @return array
+     */
+    public function getGeoData(): array {
+        return $this->loc;
+    }
 }
 
 ?>

+ 54 - 1
src/Yr/Forecast/Tabular.php

@@ -4,12 +4,27 @@ namespace App\Yr\Forecast;
 
 use App\Yr\Forecast\Tabular\Statistics;
 use App\Yr\Forecast\Tabular\Time;
+use App\Yr\Forecast\Tabular\Variations;
 
+/**
+ * Holds the forecast data in Time-objects. 
+ *
+ * Use the ```getBetween``` option to limit the results.
+ *
+ * Class also makes a simple statistic on the forecast
+ * for the periode and a variation that will exclude
+ * repetitive forecast data.
+ *
+ * @author Joachim M. Giæver (joachim[]giaver.org)
+ */
 class Tabular implements \IteratorAggregate {
 
     private $time = [];
     private $stats;
 
+    /**
+     * @param \SimpleXMLElement $xml The xml part holding the time objects, can be null
+     */
     public function __construct(?\SimpleXMLElement $xml) {
         $this->stats = new Statistics();
 
@@ -18,16 +33,51 @@ class Tabular implements \IteratorAggregate {
                 $this->addTime(new Time($time));
     }
 
+    /**
+     * Add a Time-object to the tabular
+     *
+     * @return Tabular
+     */
     protected function addTime(Time $time): self {
         $this->time[] = $time;
         $this->stats->analyse($time);
         return $this;
     }
 
-    public function getStatistics(): array {
+    /**
+     * Get statistics for the Time-object collection
+     *
+     * @return Statistics
+     */
+    public function getStatistics(): Statistics {
         return $this->stats;
     }
 
+    /**
+     * Remove superfluous weather data.
+     *
+     * Checks if the data in the Time-object differs from
+     * the current Time-object and returns the unique data
+     *
+     * @return Variations
+     */
+    public function getVariations(): Variations {
+        return new Variations($this->time);
+    }
+
+    /**
+     * Filter data between a certain periode, e.g
+     * ```
+     * $forcast->between(
+     *  $forcast->getSunset(),
+     *  $forecast->getSunrise()->add(
+     *      new \DateInterval('P1D')
+     *  )
+     * );```
+     * to only show from sunset today unti sunrise tomorrow
+     *
+     * @return Tabular with new collection
+     */
     public function getBetween(\DateTimeInterface $from, \DateTimeInterface $until): self {
         $n = new Tabular(null);
 
@@ -38,6 +88,9 @@ class Tabular implements \IteratorAggregate {
         return $n;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public function getIterator(): \Generator {
         foreach ($this->time as $time)
             yield $time;

+ 41 - 1
src/Yr/Forecast/Tabular/Statistics.php

@@ -2,6 +2,17 @@
 
 namespace App\Yr\Forecast\Tabular;
 
+use App\Yr\Forecast\Tabular\Time\AbstractUnit;
+use App\Yr\Forecast\Tabular\Time\Temperature;
+use App\Yr\Forecast\Tabular\Time\WindSpeed;
+
+/**
+ * Make simple statistic on analysed time objects,
+ * such as highest/lowest wind speed and temperature,
+ * average wind speed and temperature etc.
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class Statistics {
     private $temp = [];
     private $wind = [];
@@ -15,8 +26,37 @@ class Statistics {
         ];
     }
 
-    public function analyse(Time $t) {
+    /**
+     * Analyse a single Time-object
+     *
+     * @param Time $t The time object.
+     * @return Statistics
+     */
+    public function analyse(Time $t): self {
+        $this->analyseHihgLow($t->getTemperature());
+        $this->analyseHihgLow($t->getWindSpeed());
+        $this->temp['mean'] += $t->getTemperature()->getValue();
+        $this->wind['mean'] += $t->getWindSpeed()->getValue();
+        return $this;
+    }
+
+    private function analyseHihgLow(AbstractUnit $au): self {
+        $unit = null;
+
+        if ($au instanceof Temperature)
+            $unit = &$this->temp;
+        elseif ($au instanceof WindSpeed)
+            $unit = &$this->wind;
+        else
+            return $this;
+
+        if ($unit['low'] == null || $au->getValue() < $unit['low']->getValue())
+            $unit['low'] = $au;
+
+        if ($unit['high'] == null || $au->getValue() < $unit['high']->getValue())
+            $unit['high'] = $au;
 
+        return $this;
     }
 }
 ?>

+ 52 - 1
src/Yr/Forecast/Tabular/Time.php

@@ -8,6 +8,12 @@ use App\Yr\Forecast\Tabular\Time\Temperature;
 use App\Yr\Forecast\Tabular\Time\WindDirection;
 use App\Yr\Forecast\Tabular\Time\WindSpeed;
 
+/**
+ * Forecast data witin a time period
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
+
 final class Time implements \IteratorAggregate {
 
     private $from;
@@ -16,6 +22,9 @@ final class Time implements \IteratorAggregate {
     private $symbol;
     private $windDirection;
 
+    /**
+     * @param \SimpleXMLElement $xml The xml holding the time-object
+     */
     public function __construct(\SimpleXMLElement $xml) {
         $this->from = new \DateTimeImmutable($xml['from']);
         $this->until = new \DateTimeImmutable($xml['to']);
@@ -27,38 +36,80 @@ final class Time implements \IteratorAggregate {
         $this->pressure = new Pressure($xml->pressure);
     }
 
+    /**
+     * Returns the which index in the forecast
+     * its for. 
+     */
     public function getPeriod(): int {
         return $this->period;
     }
 
+    /**
+     * Returns the time this forecast is from
+     *
+     * @return \DateTimeImmutable
+     */
     public function getFrom(): \DateTimeImmutable {
         return $this->from;
     }
 
+    /**
+     * Returns the time this forecast is to/until.
+     *
+     * @return \DateTimeImmutable
+     */
     public function getUntil(): \DateTimeImmutable {
         return $this->until;
     }
 
+    /**
+     * Returns the «symbol» (e.g Clody etc)
+     *
+     * @return Symbol
+     */
     public function getSymbol(): Symbol {
         return $this->symbol;
     }
 
+    /**
+     * Returns the wind direction
+     *
+     * @return WindDirection
+     */
     public function getWindDirection(): WindDirection {
-        return $this->getWindDirection();
+        return $this->windDirection;
     }
 
+    /**
+     * Returns the wind speed
+     *
+     * @return WindSpeed
+     */
     public function getWindSpeed(): WindSpeed {
         return $this->windSpeed;
     }
 
+    /**
+     * Returns the temperature
+     *
+     * @return Temperature
+     */
     public function getTemperature(): Temperature {
         return $this->temperature;
     }
 
+    /**
+     * Returns the pressure
+     *
+     * @return Pressure
+     */
     public function getPressure(): Pressure {
         return $this->pressure;
     }
 
+    /**
+     * {@inheritDoc}
+     */
     public function getIterator(): \Generator {
         foreach ([
             $this->getSymbol(),

+ 23 - 7
src/Yr/Forecast/Tabular/Time/AbstractUnit.php

@@ -2,34 +2,50 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Time-object entity should inherit this
+ */
 abstract class AbstractUnit implements DiffInterface {
     const DEFAULT_VARIANCE = 2;
 
     private $value;
     private $unit;
 
+    /**
+     * @param float The value
+     * @param float The unit
+     */
     public function __construct(float $value, string $unit) {
         $this->value = $value;
         $this->unit = $unit;
     }
 
+    /**
+     * Get the value
+     *
+     * @return float
+     */
     public function getValue(): float {
         return $this->value;
     }
 
+    /**
+     * Return the unit (e.g «degree»)
+     *
+     * @return string
+     */
     public function getUnit(): string {
         return $this->unit;
     }
 
-    public function setThresholdValue(int $t): self {
-        $this->threshold = $t;
-    }
-
-    public function diff(DiffInterface $d): bool {
+    /**
+     * {@inheritDoc}
+     */
+    public function diff(DiffInterface $d): int {
         if ($d instanceof $this)
-            return abs($this->value - $d->getValue()) > static::DEFAULT_VARIANCE;
+            return $this->value - $d->getValue();
 
-        return false;
+        return 0;
     }
 
     public function __toString(): string {

+ 0 - 25
src/Yr/Forecast/Tabular/Time/DiffEntity.php

@@ -1,25 +0,0 @@
-<?php
-
-namespace App\Yr\Forecast\Tabular\Time;
-
-class DiffEntity implements DiffInterface {
-
-    private $time;
-    private $entity;
-
-    public function __construct(Time $t, DiffInterface $d) {
-        $this->time = $t;
-        $this->entity = $d;
-    }
-
-    public function getOccuringTime(): \DateTimeInterface {
-        return $time->getFrom();
-    }
-
-    public function diff(DiffInterface $d): bool {
-        if ($d instanceof get_class($this->entity))
-            return $this->entity->diff($d);
-
-        return false;
-    }
-}

+ 11 - 1
src/Yr/Forecast/Tabular/Time/DiffInterface.php

@@ -2,7 +2,17 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Defines that an entity can be checked for differences
+ * agains another entity.
+ */
 interface DiffInterface {
-    public function diff(DiffInterface $e): bool;
+    /**
+     * Check for differences with another DiffInterface.
+     * The method should check that the objects is the same.
+     *
+     * @param DiffInterface $e The object to check agains
+     */
+    public function diff(DiffInterface $e): int;
 }
 

+ 38 - 1
src/Yr/Forecast/Tabular/Time/Pressure.php

@@ -2,13 +2,50 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
-
+/**
+ * Airpressure
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class Pressure extends AbstractUnit {
+    const NORMAL_PRESSURE = 1015.0;
+
+    /**
+     * @param \SimpleXMLElement $xml XML containing the pressure
+     */
     public function __construct(\SimpleXMLElement $xml) {
         parent::__construct(
             (float)$xml['value'],
             (string)$xml['unit']
         );
     }
+
+    /**
+     * Check if the pressure is below normal pressure
+     *
+     * @return bool
+     */
+    public function isLowPressure(): bool {
+        return $this->getValue() < self::NORMAL_PRESSURE;
+    }
+
+    /**
+     * Check if the pressure is above normal pressure
+     *
+     * @return bool
+     */
+    public function isHighPressure(): bool {
+        return $this->getValue() > self::NORMAL_PRESSURE;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public function diff(DiffInterface $d): int {
+        if ($diff = parent::diff($d))
+            return $this->isLowPressure() == $d->isLowPressure() ? 0 : 1;
+
+        return 0;
+    }
 }
 

+ 29 - 3
src/Yr/Forecast/Tabular/Time/Symbol.php

@@ -2,6 +2,11 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Contains the sky data, e.g «Clody» etc
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class Symbol implements DiffInterface {
 
     private $number;
@@ -9,6 +14,9 @@ class Symbol implements DiffInterface {
     private $name;
     private $var;
 
+    /**
+     * @param \SimpleXMLElement $xml XML containing the symbol data
+     */
     public function __construct(\SimpleXMLElement $xml) {
         $this->number = (int)$xml['number'];
         $this->numberEx = (int)$xml['numberEx'];
@@ -16,23 +24,41 @@ class Symbol implements DiffInterface {
         $this->var = (string)$xml['var'];
     }
 
+    /**
+     * Retuns the type identifier
+     *
+     * @return int
+     */
     public function getNumber(): int {
         return $this->number;
     }
 
+    /**
+     * Returns the name, e.g «clody».
+     *
+     * @return string
+     */
     public function getName(): string {
         return $this->name;
     }
 
+    /**
+     * Return the var-variable
+     *
+     * @return string
+     */
     public function getVar(): string {
         return $this->var;
     }
 
-    public function diff(DiffInterface $s): bool {
+    /**
+     * {@inheritDoc}
+     */
+    public function diff(DiffInterface $s): int {
         if ($s instanceof Symbol)
-            return $this->number != $s->getNumber();
+            return $this->number - $s->getNumber();
 
-        return false;
+        return 0;
     }
 
     public function __toString(): string {

+ 10 - 0
src/Yr/Forecast/Tabular/Time/Temperature.php

@@ -2,7 +2,17 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Temperature
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class Temperature extends AbstractUnit {
+    const DEFAULT_VARIANCE = 2;
+
+    /**
+     * @param \SimpleXMLElement $xml XML containing the temperature
+     */
     public function __construct(\SimpleXMLElement $xml) {
         parent::__construct(
             (float)$xml['value'],

+ 24 - 6
src/Yr/Forecast/Tabular/Time/WindDirection.php

@@ -2,9 +2,18 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Wind direction
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class WindDirection extends AbstractUnit{
+    const DEFAULT_VARIANCE = 22.5;
     private $name;
 
+    /**
+     * @param \SimpleXMLElement $xml XML element containing the wind direction
+     */
     public function __construct(\SimpleXMLElement $xml) {
         parent::__construct(
             (float)$xml['deg'],
@@ -14,14 +23,23 @@ class WindDirection extends AbstractUnit{
         $this->name = (string)$xml['name'];
     }
 
-    public function diff(DiffInterface $d): bool {
-        if (parent::diff($d))
-            return $this->getUnit() != $f->getUnit();
-        return false;
-    }
-
+    /**
+     * Returns the wind direction in full,
+     * e.g «Northeast».
+     *
+     * @return string
+     */
     public function getName(): string {
         return $this->name;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function diff(DiffInterface $d): int {
+        if ($diff = parent::diff($d))
+            return $diff > static::DEFAULT_VARIANCE ? 1 : 0;
+        return 0;
+    }
+
 }

+ 25 - 0
src/Yr/Forecast/Tabular/Time/WindSpeed.php

@@ -2,6 +2,11 @@
 
 namespace App\Yr\Forecast\Tabular\Time;
 
+/**
+ * Wind speed
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
 class WindSpeed extends AbstractUnit {
     const DEFAULT_VARIANCE = (4.9 / 3.5);
 
@@ -12,6 +17,9 @@ class WindSpeed extends AbstractUnit {
 
     private $name;
 
+    /**
+     * @param \SimpleXMLElement $xml XML containing the wind spedd
+     */
     public function __construct(\SimpleXMLElement $xml){
         parent::__construct(
             (float)$xml['mps'], self::UNIT_MPS
@@ -20,6 +28,11 @@ class WindSpeed extends AbstractUnit {
         $this->name = (string)$xml['name'];
     }
 
+    /**
+     * Convert the wind speed to a different unit
+     *
+     * @param string $unit The unit to convert to, eg UNIT_FTS
+     */
     public function convertTo(string $unit): int {
         switch ($unit) {
         case self::UNIT_KNOTS:
@@ -31,10 +44,22 @@ class WindSpeed extends AbstractUnit {
         }
     }
 
+    /**
+     * Returns the wind name, e.g «light breeze»
+     */
     public function getName(): string {
         return $this->name;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    public function diff(DiffInterface $e): int {
+        if (parent::diff($e))
+            return ($this->getName() != $e->getName()) ? 1 : 0;
+        return 0;
+    }
+
     public function __toString(): string {
         return sprintf(
             '%s (%s)', parent::__toString(), $this->name

+ 55 - 0
src/Yr/Forecast/Tabular/Variations.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace App\Yr\Forecast\Tabular;
+
+/**
+ * Removes superfluous forecast data in an Time-object
+ * only storing changes.
+ *
+ * @author Joachim M. Giæver (joachim[]giaever.org)
+ */
+class Variations {
+
+    private $data = [];
+
+    /**
+     * @param array $t Array of Time-objects
+     */
+    public function __construct(array $t) {
+        if (!current($t) instanceof Time)
+            return;
+
+        foreach ($t as $time)
+            $this->determineVariance($time);
+    }
+
+    private function determineVariance(Time $t) {
+        $var = [
+            'time' => $t,
+            'entities' => iterator_to_array($t->getIterator())
+        ];
+
+        if (empty($this->data))
+            $this->data[] = $var;
+        else {
+            foreach (array_reverse($this->data) as $entry) {
+                foreach ($entry['entities'] as $entity) {
+                    foreach ($var['entities'] as $key => $ventity)
+                        if ($ventity instanceof $entity && !$ventity->diff($entity))
+                            unset($var['entities'][$key]);
+                }
+            }
+            if (!empty($var['entities']))
+                $this->data[] = $var;
+        }
+    }
+
+    /**
+     * Returns the changes in the forecast
+     *
+     * @return array 
+     */
+    public function getData(callable $filterFn = null): array {
+        return $this->data;
+    }
+}