diff --git a/docs/02-configuration.md b/docs/02-configuration.md index 7416324..691a74b 100644 --- a/docs/02-configuration.md +++ b/docs/02-configuration.md @@ -72,7 +72,7 @@ $api = new OpenWeatherMap('yourapikey', [ > To get to know about all the available methods, make sure to check the documentation [here](https://github.com/programmatordev/php-api-sdk?tab=readme-ov-file#documentation). The following sections have examples of some of the most important methods, -particularly related with the configuration of the client, cache and logger. +particularly related to the configuration of the client, cache and logger. ### `setClientBuilder` diff --git a/docs/03-supported-apis.md b/docs/03-supported-apis.md index 6742d70..a4de66a 100644 --- a/docs/03-supported-apis.md +++ b/docs/03-supported-apis.md @@ -6,6 +6,9 @@ - [getWeatherByDate](#getweatherbydate) - [getWeatherSummaryByDate](#getweathersummarybydate) - [getWeatherOverviewByDate](#getweatheroverviewbydate) + - [AI Assistant](#ai-assistant) + - [startSession](#startsession) + - [resumeSession](#resumesession) - [Weather](#weather) - [getCurrent](#getcurrent) - [getForecast](#getforecast) @@ -84,6 +87,36 @@ Returns a [`WeatherOverview`](05-entities.md#weatheroverview) object: $weatherOverview = $api->oneCall()->getWeatherOverviewByDate(50, 50, new \DateTime('today')); ``` +### AI Assistant + +#### `startSession` + +```php +startSession(string $prompt): Answer +``` + +Start a new session (create a new conversation) with the Weather AI Assistant. + +Returns a [`Answer`](05-entities.md#answer) object: + +```php +$answer = $api->assistant()->startSession('How is the weather today in Lisbon?'); +``` + +#### `resumeSession` + +```php +resumeSession(string $sessionId, string $prompt): Answer +``` + +Resume a session (continue a conversation) with the Weather AI Assistant. + +Returns a [`Answer`](05-entities.md#answer) object: + +```php +$answer = $api->assistant()->resumeSession('session-id', 'Do I need an umbrella?'); +``` + ### Weather #### `getCurrent` @@ -192,7 +225,7 @@ $locations = $api->geocoding()->getByLocationName('lisbon'); getByCoordinate(float $latitude, float $longitude, int $numResults = 5): array ``` -Get name of the location (city name or area name) by using geographical coordinates (latitude, longitude). +Get the name of the location (city name or area name) by using geographical coordinates (latitude, longitude). Returns an array of [`Location`](05-entities.md#location) objects. @@ -261,7 +294,7 @@ withCacheTtl(?int $ttl): self Makes a request and saves into cache for the provided duration in seconds. Semantics of values: -- `0`, the response will not be cached (if the servers specifies no `max-age`). +- `0`, the response will not be cached (if the server specifies no `max-age`). - `null`, the response will be cached for as long as it can (forever). > [!NOTE] diff --git a/docs/05-entities.md b/docs/05-entities.md index fb84b9f..20267d4 100644 --- a/docs/05-entities.md +++ b/docs/05-entities.md @@ -4,6 +4,7 @@ - [Weather](#weather) - [WeatherMoment](#weathermoment) - [WeatherSummary](#weathersummary) + - [WeatherOverview](#weatheroverview) - [WeatherData](#weatherdata) - [MinuteData](#minutedata) - [HourData](#hourdata) @@ -11,10 +12,13 @@ - [Alert](#alert) - [MoonPhase](#moonphase) - [Temperature](#temperature) +- [AI Assistant](#ai-assistant) + - [Answer](#answer) + - [WeatherData](#weatherdata-1) - [Weather](#weather-1) - [Weather](#weather-2) - [WeatherCollection](#weathercollection) - - [WeatherData](#weatherdata) + - [WeatherData](#weatherdata-2) - [Air Pollution](#air-pollution) - [AirPollution](#airpollution) - [AirPollutionCollection](#airpollutioncollection) @@ -171,6 +175,33 @@ - `getMin()`: `?float` - `getMax()`: `?float` +## AI Assistant + +### Answer + +- `getAnswer()`: `string` +- `getSessionId()`: `string` +- `getData()`: [`WeatherData[]`](#weatherdata-1) + +### WeatherData + +- `getLocationName()`: `string` +- `getDateTime()`: `\DateTimeImmutable` +- `getTemperature()`: `float` +- `getTemperatureFeelsLike()`: `float` +- `getAtmosphericPressure()`: `int` +- `getVisibility()`: `?int` +- `getHumidity()`: `int` +- `getDewPoint()`: `float` +- `getUltraVioletIndex()`: `?float` +- `getCloudiness()`: `int` +- `getWind()`: [`Wind`](#wind) +- `getConditions()`: [`Condition[]`](#condition) +- `getRainVolume()`: `?float` +- `getSnowVolume()`: `?float` +- `getSunriseAt()`: `?\DateTimeImmutable` +- `getSunsetAt()`: `?\DateTimeImmutable` + ## Weather ### Weather diff --git a/src/Entity/AirPollution/AirPollutionCollection.php b/src/Entity/AirPollution/AirPollutionCollection.php index c91c222..192834a 100644 --- a/src/Entity/AirPollution/AirPollutionCollection.php +++ b/src/Entity/AirPollution/AirPollutionCollection.php @@ -3,12 +3,10 @@ namespace ProgrammatorDev\OpenWeatherMap\Entity\AirPollution; use ProgrammatorDev\OpenWeatherMap\Entity\Coordinate; -use ProgrammatorDev\OpenWeatherMap\Util\EntityTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\EntityHelper; class AirPollutionCollection { - use EntityTrait; - private int $numResults; private Coordinate $coordinate; @@ -20,7 +18,7 @@ public function __construct(array $data) { $this->numResults = count($data['list']); $this->coordinate = new Coordinate($data['coord']); - $this->data = $this->createEntityList(AirPollutionData::class, $data['list']); + $this->data = EntityHelper::createEntityList(AirPollutionData::class, $data['list']); } public function getNumResults(): int diff --git a/src/Entity/Assistant/Answer.php b/src/Entity/Assistant/Answer.php new file mode 100644 index 0000000..28396e7 --- /dev/null +++ b/src/Entity/Assistant/Answer.php @@ -0,0 +1,40 @@ +answer = $data['answer']; + $this->sessionId = $data['session_id']; + + if (!empty($data['data'])) { + $this->data = EntityHelper::createEntityKeyList(WeatherData::class, $data['data']); + } + } + + public function getAnswer(): string + { + return $this->answer; + } + + public function getSessionId(): string + { + return $this->sessionId; + } + + public function getData(): array + { + return $this->data; + } +} \ No newline at end of file diff --git a/src/Entity/Assistant/WeatherData.php b/src/Entity/Assistant/WeatherData.php new file mode 100644 index 0000000..cd07e37 --- /dev/null +++ b/src/Entity/Assistant/WeatherData.php @@ -0,0 +1,62 @@ +locationName = $locationName; + $this->temperature = $data['temp']; + $this->temperatureFeelsLike = $data['feels_like']; + $this->visibility = $data['visibility']; + $this->sunriseAt = \DateTimeImmutable::createFromFormat('U', $data['sunrise']); + $this->sunsetAt = \DateTimeImmutable::createFromFormat('U', $data['sunset']); + } + + public function getLocationName(): string + { + return $this->locationName; + } + + public function getTemperature(): float + { + return $this->temperature; + } + + public function getTemperatureFeelsLike(): float + { + return $this->temperatureFeelsLike; + } + + public function getVisibility(): int + { + return $this->visibility; + } + + public function getSunriseAt(): \DateTimeImmutable + { + return $this->sunriseAt; + } + + public function getSunsetAt(): \DateTimeImmutable + { + return $this->sunsetAt; + } +} \ No newline at end of file diff --git a/src/Entity/OneCall/BaseWeather.php b/src/Entity/BaseWeather.php similarity index 86% rename from src/Entity/OneCall/BaseWeather.php rename to src/Entity/BaseWeather.php index dfa9f69..a7e897f 100644 --- a/src/Entity/OneCall/BaseWeather.php +++ b/src/Entity/BaseWeather.php @@ -1,15 +1,11 @@ $data['wind_gust'] ?? null ]); - $this->conditions = $this->createEntityList(Condition::class, $data['weather']); + $this->conditions = EntityHelper::createEntityList(Condition::class, $data['weather']); $this->rainVolume = $data['rain']['1h'] ?? $data['rain']['3h'] ?? $data['rain'] ?? null; $this->snowVolume = $data['snow']['1h'] ?? $data['snow']['3h'] ?? $data['snow'] ?? null; } diff --git a/src/Entity/OneCall/DayData.php b/src/Entity/OneCall/DayData.php index fd3adec..e15467b 100644 --- a/src/Entity/OneCall/DayData.php +++ b/src/Entity/OneCall/DayData.php @@ -2,6 +2,8 @@ namespace ProgrammatorDev\OpenWeatherMap\Entity\OneCall; +use ProgrammatorDev\OpenWeatherMap\Entity\BaseWeather; + class DayData extends BaseWeather { private Temperature $temperature; diff --git a/src/Entity/OneCall/HourData.php b/src/Entity/OneCall/HourData.php index fa59ccf..5eaf765 100644 --- a/src/Entity/OneCall/HourData.php +++ b/src/Entity/OneCall/HourData.php @@ -2,6 +2,8 @@ namespace ProgrammatorDev\OpenWeatherMap\Entity\OneCall; +use ProgrammatorDev\OpenWeatherMap\Entity\BaseWeather; + class HourData extends BaseWeather { private float $temperature; diff --git a/src/Entity/OneCall/Weather.php b/src/Entity/OneCall/Weather.php index 945c6ec..09395e1 100644 --- a/src/Entity/OneCall/Weather.php +++ b/src/Entity/OneCall/Weather.php @@ -4,12 +4,10 @@ use ProgrammatorDev\OpenWeatherMap\Entity\Coordinate; use ProgrammatorDev\OpenWeatherMap\Entity\Timezone; -use ProgrammatorDev\OpenWeatherMap\Util\EntityTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\EntityHelper; class Weather { - use EntityTrait; - private Coordinate $coordinate; private Timezone $timezone; @@ -43,14 +41,14 @@ public function __construct(array $data) $this->current = new WeatherData($data['current']); $this->minutelyForecast = isset($data['minutely']) - ? $this->createEntityList(MinuteData::class, $data['minutely']) + ? EntityHelper::createEntityList(MinuteData::class, $data['minutely']) : null; - $this->hourlyForecast = $this->createEntityList(HourData::class, $data['hourly']); - $this->dailyForecast = $this->createEntityList(DayData::class, $data['daily']); + $this->hourlyForecast = EntityHelper::createEntityList(HourData::class, $data['hourly']); + $this->dailyForecast = EntityHelper::createEntityList(DayData::class, $data['daily']); $this->alerts = isset($data['alerts']) - ? $this->createEntityList(Alert::class, $data['alerts']) + ? EntityHelper::createEntityList(Alert::class, $data['alerts']) : null; } diff --git a/src/Entity/OneCall/WeatherData.php b/src/Entity/OneCall/WeatherData.php index 2811290..0154344 100644 --- a/src/Entity/OneCall/WeatherData.php +++ b/src/Entity/OneCall/WeatherData.php @@ -2,6 +2,8 @@ namespace ProgrammatorDev\OpenWeatherMap\Entity\OneCall; +use ProgrammatorDev\OpenWeatherMap\Entity\BaseWeather; + class WeatherData extends BaseWeather { private float $temperature; diff --git a/src/Entity/Weather/WeatherCollection.php b/src/Entity/Weather/WeatherCollection.php index ae7486d..dbb7f3d 100644 --- a/src/Entity/Weather/WeatherCollection.php +++ b/src/Entity/Weather/WeatherCollection.php @@ -3,12 +3,10 @@ namespace ProgrammatorDev\OpenWeatherMap\Entity\Weather; use ProgrammatorDev\OpenWeatherMap\Entity\Location; -use ProgrammatorDev\OpenWeatherMap\Util\EntityTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\EntityHelper; class WeatherCollection { - use EntityTrait; - private int $numResults; private Location $location; @@ -32,7 +30,7 @@ public function __construct(array $data) 'timezone_offset' => $data['city']['timezone'] ]); - $this->data = $this->createEntityList(WeatherData::class, $data['list']); + $this->data = EntityHelper::createEntityList(WeatherData::class, $data['list']); } public function getNumResults(): int diff --git a/src/Entity/Weather/WeatherData.php b/src/Entity/Weather/WeatherData.php index 021c22f..b44f7ed 100644 --- a/src/Entity/Weather/WeatherData.php +++ b/src/Entity/Weather/WeatherData.php @@ -4,12 +4,10 @@ use ProgrammatorDev\OpenWeatherMap\Entity\Condition; use ProgrammatorDev\OpenWeatherMap\Entity\Wind; -use ProgrammatorDev\OpenWeatherMap\Util\EntityTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\EntityHelper; class WeatherData { - use EntityTrait; - private \DateTimeImmutable $dateTime; private float $temperature; @@ -50,7 +48,7 @@ public function __construct(array $data) $this->cloudiness = $data['clouds']['all']; $this->visibility = $data['visibility']; $this->atmosphericPressure = $data['main']['pressure']; - $this->conditions = $this->createEntityList(Condition::class, $data['weather']); + $this->conditions = EntityHelper::createEntityList(Condition::class, $data['weather']); $this->wind = new Wind($data['wind']); $this->precipitationProbability = isset($data['pop']) diff --git a/src/Helper/EntityHelper.php b/src/Helper/EntityHelper.php new file mode 100644 index 0000000..2993ca6 --- /dev/null +++ b/src/Helper/EntityHelper.php @@ -0,0 +1,20 @@ +getConstants(); diff --git a/src/Language/Language.php b/src/Language/Language.php index a92c795..9c914b9 100644 --- a/src/Language/Language.php +++ b/src/Language/Language.php @@ -2,12 +2,10 @@ namespace ProgrammatorDev\OpenWeatherMap\Language; -use ProgrammatorDev\OpenWeatherMap\Util\ReflectionTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\ReflectionHelper; class Language { - use ReflectionTrait; - public const AFRIKAANS = 'af'; public const ALBANIAN = 'al'; public const ARABIC = 'ar'; @@ -57,6 +55,6 @@ class Language public static function getOptions(): array { - return (new Language)->getClassConstants(self::class); + return ReflectionHelper::getClassConstants(self::class); } } \ No newline at end of file diff --git a/src/OpenWeatherMap.php b/src/OpenWeatherMap.php index 04b7d0f..af09872 100644 --- a/src/OpenWeatherMap.php +++ b/src/OpenWeatherMap.php @@ -13,6 +13,7 @@ use ProgrammatorDev\OpenWeatherMap\Exception\UnexpectedErrorException; use ProgrammatorDev\OpenWeatherMap\Language\Language; use ProgrammatorDev\OpenWeatherMap\Resource\AirPollutionResource; +use ProgrammatorDev\OpenWeatherMap\Resource\AssistantResource; use ProgrammatorDev\OpenWeatherMap\Resource\GeocodingResource; use ProgrammatorDev\OpenWeatherMap\Resource\OneCallResource; use ProgrammatorDev\OpenWeatherMap\Resource\WeatherResource; @@ -21,12 +22,12 @@ class OpenWeatherMap extends Api { - private array $options; + public readonly array $options; private OptionsResolver $optionsResolver; public function __construct( - #[\SensitiveParameter] private readonly string $apiKey, + #[\SensitiveParameter] public readonly string $apiKey, array $options = [] ) { @@ -43,6 +44,11 @@ public function oneCall(): OneCallResource return new OneCallResource($this); } + public function assistant(): AssistantResource + { + return new AssistantResource($this); + } + public function weather(): WeatherResource { return new WeatherResource($this); diff --git a/src/Resource/AssistantResource.php b/src/Resource/AssistantResource.php new file mode 100644 index 0000000..7d06c16 --- /dev/null +++ b/src/Resource/AssistantResource.php @@ -0,0 +1,49 @@ +api->setAuthentication(new Header('X-Api-Key', $this->api->apiKey)); + + $data = $this->api->request( + method: Method::POST, + path: '/assistant/session', + body: json_encode(['prompt' => $prompt]) + ); + + return new Answer($data); + } + + /** + * Resume a session (continue a conversation) with the Weather AI Assistant + * + * @throws ClientExceptionInterface + */ + public function resumeSession(string $sessionId, string $prompt): Answer + { + $this->api->setAuthentication(new Header('X-Api-Key', $this->api->apiKey)); + + $data = $this->api->request( + method: Method::POST, + path: $this->api->buildPath('/assistant/session/{sessionId}', [ + 'sessionId' => $sessionId + ]), + body: json_encode(['prompt' => $prompt]) + ); + + return new Answer($data); + } +} \ No newline at end of file diff --git a/src/Resource/GeocodingResource.php b/src/Resource/GeocodingResource.php index 21458bf..dfdcd87 100644 --- a/src/Resource/GeocodingResource.php +++ b/src/Resource/GeocodingResource.php @@ -5,13 +5,11 @@ use ProgrammatorDev\Api\Method; use ProgrammatorDev\OpenWeatherMap\Entity\Geocoding\ZipLocation; use ProgrammatorDev\OpenWeatherMap\Entity\Location; -use ProgrammatorDev\OpenWeatherMap\Util\EntityTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\EntityHelper; use Psr\Http\Client\ClientExceptionInterface; class GeocodingResource extends Resource { - use EntityTrait; - private const NUM_RESULTS = 5; /** @@ -31,7 +29,7 @@ public function getByLocationName(string $locationName, int $numResults = self:: ] ); - return $this->createEntityList(Location::class, $data); + return EntityHelper::createEntityList(Location::class, $data); } /** @@ -70,6 +68,6 @@ public function getByCoordinate(float $latitude, float $longitude, int $numResul ] ); - return $this->createEntityList(Location::class, $data); + return EntityHelper::createEntityList(Location::class, $data); } } \ No newline at end of file diff --git a/src/Test/MockResponse.php b/src/Test/MockResponse.php index 0e5180b..ffcd0c3 100644 --- a/src/Test/MockResponse.php +++ b/src/Test/MockResponse.php @@ -4,6 +4,9 @@ class MockResponse { + public const ASSISTANT_START_SESSION = '{"answer":"Answer text","data":{"Lisbon":{"Current UTC Time":"08 November 2025, 17:16","Current Week Day UTC":"Saturday","clouds":100,"dew_point":272.33,"dt":1762622168,"feels_like":275.34,"humidity":70,"pressure":1010,"sunrise":1762602543,"sunset":1762638067,"temp":277.19,"uvi":1.33,"visibility":10000,"weather":[{"description":"overcast clouds","icon":"04d","id":804,"main":"Clouds"}],"wind_deg":0,"wind_gust":6.17,"wind_speed":2.06}},"session_id":"62168d7b-a58d-4122-95c8-4dff55a57a76"}'; + public const ASSISTANT_RESUME_SESSION = self::ASSISTANT_START_SESSION; + public const ONE_CALL_WEATHER = '{"lat":38.7078,"lon":-9.1366,"timezone":"Europe/Lisbon","timezone_offset":3600,"current":{"dt":1688384139,"sunrise":1688361368,"sunset":1688414697,"temp":25.1,"feels_like":25.21,"pressure":1017,"humidity":59,"dew_point":16.53,"uvi":9.78,"clouds":20,"visibility":10000,"wind_speed":7.2,"wind_deg":10,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}]},"minutely":[{"dt":1688384160,"precipitation":0},{"dt":1688384220,"precipitation":0},{"dt":1688384280,"precipitation":0},{"dt":1688384340,"precipitation":0},{"dt":1688384400,"precipitation":0},{"dt":1688384460,"precipitation":0},{"dt":1688384520,"precipitation":0},{"dt":1688384580,"precipitation":0},{"dt":1688384640,"precipitation":0},{"dt":1688384700,"precipitation":0},{"dt":1688384760,"precipitation":0},{"dt":1688384820,"precipitation":0},{"dt":1688384880,"precipitation":0},{"dt":1688384940,"precipitation":0},{"dt":1688385000,"precipitation":0},{"dt":1688385060,"precipitation":0},{"dt":1688385120,"precipitation":0},{"dt":1688385180,"precipitation":0},{"dt":1688385240,"precipitation":0},{"dt":1688385300,"precipitation":0},{"dt":1688385360,"precipitation":0},{"dt":1688385420,"precipitation":0},{"dt":1688385480,"precipitation":0},{"dt":1688385540,"precipitation":0},{"dt":1688385600,"precipitation":0},{"dt":1688385660,"precipitation":0},{"dt":1688385720,"precipitation":0},{"dt":1688385780,"precipitation":0},{"dt":1688385840,"precipitation":0.1032},{"dt":1688385900,"precipitation":0.115},{"dt":1688385960,"precipitation":0.1276},{"dt":1688386020,"precipitation":0.1402},{"dt":1688386080,"precipitation":0.1528},{"dt":1688386140,"precipitation":0.1654},{"dt":1688386200,"precipitation":0.178},{"dt":1688386260,"precipitation":0.1654},{"dt":1688386320,"precipitation":0.1528},{"dt":1688386380,"precipitation":0.1402},{"dt":1688386440,"precipitation":0.1276},{"dt":1688386500,"precipitation":0.115},{"dt":1688386560,"precipitation":0.1032},{"dt":1688386620,"precipitation":0},{"dt":1688386680,"precipitation":0},{"dt":1688386740,"precipitation":0},{"dt":1688386800,"precipitation":0},{"dt":1688386860,"precipitation":0},{"dt":1688386920,"precipitation":0},{"dt":1688386980,"precipitation":0},{"dt":1688387040,"precipitation":0},{"dt":1688387100,"precipitation":0},{"dt":1688387160,"precipitation":0},{"dt":1688387220,"precipitation":0},{"dt":1688387280,"precipitation":0},{"dt":1688387340,"precipitation":0},{"dt":1688387400,"precipitation":0},{"dt":1688387460,"precipitation":0},{"dt":1688387520,"precipitation":0},{"dt":1688387580,"precipitation":0},{"dt":1688387640,"precipitation":0},{"dt":1688387700,"precipitation":0},{"dt":1688387760,"precipitation":0}],"hourly":[{"dt":1688382000,"temp":25.38,"feels_like":25.44,"pressure":1017,"humidity":56,"dew_point":15.97,"uvi":8.42,"clouds":16,"visibility":10000,"wind_speed":4.94,"wind_deg":327,"wind_gust":6.14,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"pop":0},{"dt":1688385600,"temp":25.1,"feels_like":25.21,"pressure":1017,"humidity":59,"dew_point":16.53,"uvi":9.78,"clouds":20,"visibility":10000,"wind_speed":5.92,"wind_deg":325,"wind_gust":7.02,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"pop":0},{"dt":1688389200,"temp":25.69,"feels_like":25.75,"pressure":1017,"humidity":55,"dew_point":15.98,"uvi":9.92,"clouds":16,"visibility":10000,"wind_speed":6.69,"wind_deg":328,"wind_gust":7.82,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"pop":0},{"dt":1688392800,"temp":26.43,"feels_like":26.43,"pressure":1017,"humidity":50,"dew_point":15.18,"uvi":8.86,"clouds":12,"visibility":10000,"wind_speed":7.32,"wind_deg":331,"wind_gust":8.69,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"pop":0},{"dt":1688396400,"temp":26.82,"feels_like":27.09,"pressure":1017,"humidity":47,"dew_point":14.57,"uvi":6.86,"clouds":8,"visibility":10000,"wind_speed":7.95,"wind_deg":337,"wind_gust":9.66,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688400000,"temp":26.88,"feels_like":26.92,"pressure":1017,"humidity":43,"dew_point":13.26,"uvi":4.61,"clouds":4,"visibility":10000,"wind_speed":8.11,"wind_deg":341,"wind_gust":10.42,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688403600,"temp":26.09,"feels_like":26.09,"pressure":1017,"humidity":45,"dew_point":12.76,"uvi":2.47,"clouds":0,"visibility":10000,"wind_speed":8.65,"wind_deg":344,"wind_gust":11.66,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688407200,"temp":24.67,"feels_like":24.52,"pressure":1017,"humidity":51,"dew_point":13.62,"uvi":0.99,"clouds":0,"visibility":10000,"wind_speed":8.8,"wind_deg":347,"wind_gust":12.69,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688410800,"temp":22.93,"feels_like":22.85,"pressure":1018,"humidity":60,"dew_point":14.39,"uvi":0.26,"clouds":0,"visibility":10000,"wind_speed":8.19,"wind_deg":348,"wind_gust":13.04,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688414400,"temp":21.16,"feels_like":21.13,"pressure":1018,"humidity":69,"dew_point":14.95,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":6.88,"wind_deg":347,"wind_gust":12.91,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688418000,"temp":20,"feels_like":20.04,"pressure":1019,"humidity":76,"dew_point":15.45,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":6.37,"wind_deg":346,"wind_gust":12.91,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688421600,"temp":19.41,"feels_like":19.5,"pressure":1019,"humidity":80,"dew_point":15.55,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.94,"wind_deg":348,"wind_gust":12.71,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688425200,"temp":19.04,"feels_like":19.11,"pressure":1020,"humidity":81,"dew_point":15.48,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.74,"wind_deg":348,"wind_gust":12.82,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688428800,"temp":18.7,"feels_like":18.77,"pressure":1020,"humidity":82,"dew_point":15.32,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.63,"wind_deg":346,"wind_gust":12.84,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688432400,"temp":18.45,"feels_like":18.52,"pressure":1020,"humidity":83,"dew_point":15.27,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.38,"wind_deg":344,"wind_gust":12.56,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688436000,"temp":18.15,"feels_like":18.24,"pressure":1019,"humidity":85,"dew_point":15.27,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.28,"wind_deg":344,"wind_gust":12.34,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688439600,"temp":17.93,"feels_like":18.02,"pressure":1019,"humidity":86,"dew_point":15.38,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.14,"wind_deg":342,"wind_gust":11.93,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688443200,"temp":17.73,"feels_like":17.83,"pressure":1019,"humidity":87,"dew_point":15.36,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.1,"wind_deg":340,"wind_gust":11.84,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688446800,"temp":17.58,"feels_like":17.67,"pressure":1019,"humidity":87,"dew_point":15.24,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":4.88,"wind_deg":339,"wind_gust":11.23,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688450400,"temp":17.79,"feels_like":17.87,"pressure":1019,"humidity":86,"dew_point":15.25,"uvi":0.17,"clouds":0,"visibility":10000,"wind_speed":5.07,"wind_deg":339,"wind_gust":11.53,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688454000,"temp":18.96,"feels_like":18.97,"pressure":1019,"humidity":79,"dew_point":14.99,"uvi":0.75,"clouds":0,"visibility":10000,"wind_speed":5.6,"wind_deg":344,"wind_gust":10.56,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688457600,"temp":20.57,"feels_like":20.48,"pressure":1020,"humidity":69,"dew_point":14.39,"uvi":2.05,"clouds":0,"visibility":10000,"wind_speed":6.35,"wind_deg":344,"wind_gust":9.7,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688461200,"temp":22.34,"feels_like":22.14,"pressure":1020,"humidity":58,"dew_point":13.35,"uvi":4.13,"clouds":0,"visibility":10000,"wind_speed":6.29,"wind_deg":345,"wind_gust":8.74,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688464800,"temp":23.94,"feels_like":23.7,"pressure":1020,"humidity":50,"dew_point":12.37,"uvi":6.49,"clouds":0,"visibility":10000,"wind_speed":6.28,"wind_deg":341,"wind_gust":8.01,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688468400,"temp":25.12,"feels_like":24.86,"pressure":1020,"humidity":45,"dew_point":11.69,"uvi":8.74,"clouds":0,"visibility":10000,"wind_speed":6.67,"wind_deg":336,"wind_gust":7.78,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688472000,"temp":25.82,"feels_like":25.55,"pressure":1019,"humidity":42,"dew_point":11.33,"uvi":10.16,"clouds":0,"visibility":10000,"wind_speed":6.93,"wind_deg":333,"wind_gust":7.78,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688475600,"temp":26.12,"feels_like":26.12,"pressure":1019,"humidity":41,"dew_point":11.21,"uvi":10.23,"clouds":0,"visibility":10000,"wind_speed":7.39,"wind_deg":331,"wind_gust":8.04,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688479200,"temp":26.13,"feels_like":26.13,"pressure":1019,"humidity":41,"dew_point":11.01,"uvi":9.13,"clouds":0,"visibility":10000,"wind_speed":7.75,"wind_deg":332,"wind_gust":8.6,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688482800,"temp":25.79,"feels_like":25.5,"pressure":1019,"humidity":41,"dew_point":10.99,"uvi":7.07,"clouds":0,"visibility":10000,"wind_speed":7.86,"wind_deg":333,"wind_gust":9,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688486400,"temp":25.14,"feels_like":24.83,"pressure":1018,"humidity":43,"dew_point":11.02,"uvi":4.68,"clouds":0,"visibility":10000,"wind_speed":7.9,"wind_deg":334,"wind_gust":9.28,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688490000,"temp":24.33,"feels_like":23.97,"pressure":1018,"humidity":44,"dew_point":10.98,"uvi":2.5,"clouds":0,"visibility":10000,"wind_speed":7.8,"wind_deg":336,"wind_gust":9.64,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688493600,"temp":23.02,"feels_like":22.63,"pressure":1018,"humidity":48,"dew_point":11.18,"uvi":1,"clouds":0,"visibility":10000,"wind_speed":7.77,"wind_deg":339,"wind_gust":10.17,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688497200,"temp":21.59,"feels_like":21.21,"pressure":1019,"humidity":54,"dew_point":11.6,"uvi":0.26,"clouds":0,"visibility":10000,"wind_speed":7.21,"wind_deg":342,"wind_gust":10.42,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688500800,"temp":19.87,"feels_like":19.58,"pressure":1019,"humidity":64,"dew_point":12.66,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":6.25,"wind_deg":340,"wind_gust":11.21,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"pop":0},{"dt":1688504400,"temp":18.72,"feels_like":18.66,"pressure":1019,"humidity":77,"dew_point":14.27,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.96,"wind_deg":341,"wind_gust":12.03,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688508000,"temp":18.26,"feels_like":18.31,"pressure":1020,"humidity":83,"dew_point":15.08,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.73,"wind_deg":340,"wind_gust":12.21,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688511600,"temp":18.1,"feels_like":18.21,"pressure":1019,"humidity":86,"dew_point":15.47,"uvi":0,"clouds":0,"visibility":10000,"wind_speed":5.61,"wind_deg":344,"wind_gust":12.34,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688515200,"temp":18.1,"feels_like":18.24,"pressure":1019,"humidity":87,"dew_point":15.75,"uvi":0,"clouds":1,"visibility":10000,"wind_speed":5.75,"wind_deg":344,"wind_gust":12.19,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688518800,"temp":18.25,"feels_like":18.38,"pressure":1019,"humidity":86,"dew_point":15.67,"uvi":0,"clouds":16,"visibility":10000,"wind_speed":5.71,"wind_deg":346,"wind_gust":11.73,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02n"}],"pop":0},{"dt":1688522400,"temp":18.21,"feels_like":18.31,"pressure":1018,"humidity":85,"dew_point":15.32,"uvi":0,"clouds":14,"visibility":10000,"wind_speed":5.25,"wind_deg":345,"wind_gust":11.6,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02n"}],"pop":0},{"dt":1688526000,"temp":17.82,"feels_like":17.9,"pressure":1018,"humidity":86,"dew_point":15.12,"uvi":0,"clouds":10,"visibility":10000,"wind_speed":4.67,"wind_deg":337,"wind_gust":11.06,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688529600,"temp":17.66,"feels_like":17.73,"pressure":1018,"humidity":86,"dew_point":15.1,"uvi":0,"clouds":9,"visibility":10000,"wind_speed":4.77,"wind_deg":339,"wind_gust":11.79,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688533200,"temp":17.54,"feels_like":17.6,"pressure":1018,"humidity":86,"dew_point":14.95,"uvi":0,"clouds":8,"visibility":10000,"wind_speed":4.65,"wind_deg":336,"wind_gust":10.53,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01n"}],"pop":0},{"dt":1688536800,"temp":17.83,"feels_like":17.86,"pressure":1018,"humidity":84,"dew_point":14.82,"uvi":0.17,"clouds":11,"visibility":10000,"wind_speed":5.08,"wind_deg":337,"wind_gust":11.85,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"pop":0},{"dt":1688540400,"temp":18.98,"feels_like":18.94,"pressure":1019,"humidity":77,"dew_point":14.66,"uvi":0.73,"clouds":71,"visibility":10000,"wind_speed":6.05,"wind_deg":327,"wind_gust":10.65,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"pop":0},{"dt":1688544000,"temp":20.08,"feels_like":19.95,"pressure":1018,"humidity":69,"dew_point":13.96,"uvi":2,"clouds":85,"visibility":10000,"wind_speed":6.22,"wind_deg":352,"wind_gust":10.17,"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"pop":0},{"dt":1688547600,"temp":20.87,"feels_like":20.68,"pressure":1018,"humidity":64,"dew_point":13.5,"uvi":4.03,"clouds":90,"visibility":10000,"wind_speed":6.36,"wind_deg":346,"wind_gust":9.8,"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"pop":0},{"dt":1688551200,"temp":21.11,"feels_like":20.87,"pressure":1018,"humidity":61,"dew_point":13.04,"uvi":5.58,"clouds":92,"visibility":10000,"wind_speed":5.05,"wind_deg":348,"wind_gust":7.7,"weather":[{"id":804,"main":"Clouds","description":"overcast clouds","icon":"04d"}],"pop":0}],"daily":[{"dt":1688385600,"sunrise":1688361368,"sunset":1688414697,"moonrise":1688417100,"moonset":1688359440,"moon_phase":0.5,"summary":"Expect a day of partly cloudy with clear spells","temp":{"day":25.1,"min":18.28,"max":26.88,"night":19.41,"eve":24.67,"morn":18.39},"feels_like":{"day":25.21,"night":19.5,"eve":24.52,"morn":18.5},"pressure":1017,"humidity":59,"dew_point":16.53,"wind_speed":8.8,"wind_deg":347,"wind_gust":13.04,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"clouds":20,"pop":0,"uvi":9.92},{"dt":1688472000,"sunrise":1688447798,"sunset":1688501087,"moonrise":1688506560,"moonset":1688450100,"moon_phase":0.54,"summary":"There will be clear sky today","temp":{"day":25.82,"min":17.58,"max":26.13,"night":18.26,"eve":23.02,"morn":17.79},"feels_like":{"day":25.55,"night":18.31,"eve":22.63,"morn":17.87},"pressure":1019,"humidity":42,"dew_point":11.33,"wind_speed":7.9,"wind_deg":334,"wind_gust":12.84,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"clouds":0,"pop":0,"uvi":10.23},{"dt":1688558400,"sunrise":1688534230,"sunset":1688587476,"moonrise":1688595540,"moonset":1688541240,"moon_phase":0.58,"summary":"Expect a day of partly cloudy with clear spells","temp":{"day":25.2,"min":17.54,"max":25.28,"night":18.64,"eve":22.5,"morn":17.83},"feels_like":{"day":24.98,"night":18.7,"eve":22.32,"morn":17.86},"pressure":1018,"humidity":46,"dew_point":12.27,"wind_speed":7.86,"wind_deg":324,"wind_gust":12.34,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"clouds":71,"pop":0,"uvi":9.93},{"dt":1688644800,"sunrise":1688620663,"sunset":1688673862,"moonrise":1688683980,"moonset":1688632380,"moon_phase":0.62,"summary":"The day will start with partly cloudy through the late morning hours, transitioning to clearing","temp":{"day":25.05,"min":17.57,"max":25.05,"night":19.01,"eve":22.56,"morn":17.59},"feels_like":{"day":24.86,"night":19.06,"eve":22.39,"morn":17.75},"pressure":1016,"humidity":48,"dew_point":12.69,"wind_speed":7.09,"wind_deg":312,"wind_gust":9.69,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"clouds":2,"pop":0,"uvi":8.84},{"dt":1688731200,"sunrise":1688707097,"sunset":1688760247,"moonrise":0,"moonset":1688723400,"moon_phase":0.65,"summary":"There will be clear sky until morning, then partly cloudy","temp":{"day":24.48,"min":17.64,"max":24.48,"night":19.8,"eve":22.83,"morn":17.64},"feels_like":{"day":24.32,"night":20,"eve":22.81,"morn":17.81},"pressure":1017,"humidity":51,"dew_point":13,"wind_speed":5.56,"wind_deg":305,"wind_gust":7.26,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"clouds":15,"pop":0,"uvi":8.73},{"dt":1688817600,"sunrise":1688793533,"sunset":1688846630,"moonrise":1688772060,"moonset":1688814180,"moon_phase":0.69,"summary":"The day will start with partly cloudy through the late morning hours, transitioning to clearing","temp":{"day":24.93,"min":18.43,"max":25.64,"night":20.37,"eve":23.97,"morn":18.43},"feels_like":{"day":24.99,"night":20.47,"eve":23.96,"morn":18.65},"pressure":1019,"humidity":58,"dew_point":15.5,"wind_speed":5.99,"wind_deg":276,"wind_gust":6.46,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"clouds":5,"pop":0,"uvi":9},{"dt":1688904000,"sunrise":1688879970,"sunset":1688933011,"moonrise":1688860020,"moonset":1688904780,"moon_phase":0.73,"summary":"Expect a day of partly cloudy with clear spells","temp":{"day":24.48,"min":18.35,"max":25.38,"night":18.35,"eve":22.97,"morn":19.77},"feels_like":{"day":24.42,"night":18.07,"eve":22.55,"morn":20.15},"pressure":1021,"humidity":55,"dew_point":14.3,"wind_speed":7.17,"wind_deg":330,"wind_gust":10.71,"weather":[{"id":803,"main":"Clouds","description":"broken clouds","icon":"04d"}],"clouds":70,"pop":0,"uvi":9},{"dt":1688990400,"sunrise":1688966408,"sunset":1689019390,"moonrise":1688947980,"moonset":1688995260,"moon_phase":0.75,"summary":"There will be clear sky today","temp":{"day":25.17,"min":16.95,"max":25.65,"night":20.15,"eve":24,"morn":17.24},"feels_like":{"day":25.18,"night":20.1,"eve":23.97,"morn":17.08},"pressure":1021,"humidity":55,"dew_point":15.07,"wind_speed":6.84,"wind_deg":315,"wind_gust":8.77,"weather":[{"id":800,"main":"Clear","description":"clear sky","icon":"01d"}],"clouds":0,"pop":0,"uvi":9}],"alerts":[{"sender_name":"NWS Portland (Northwest Oregon and Southwest Washington)","event":"Heat Advisory","start":1688490000,"end":1688623200,"description":"...HEAT ADVISORY REMAINS IN EFFECT FROM 10 AM TUESDAY TO 11 PM\nPDT WEDNESDAY...\n* WHAT...Maximum temperatures of 92 to 102 degrees expected\nTuesday and Wednesday. Hottest temperatures will be across\ninner portions of the Portland, Vancouver, Hillsboro, and\nSalem metropolitan areas.\n* WHERE...In Oregon, Greater Portland Metro Area and Central\nWillamette Valley. In Washington, Greater Vancouver Area.\n* WHEN...From 10 AM Tuesday to 11 PM PDT Wednesday.\n* IMPACTS...Hot temperatures may cause heat illnesses to occur.\n* ADDITIONAL DETAILS...Temperatures will struggle to fall much\nbelow 70 degrees Tuesday night for the inner urban core of\nPortland.","tags":["Extreme temperature value"]}]}'; public const ONE_CALL_TIMEMACHINE = '{"lat":38.7078,"lon":-9.1366,"timezone":"Europe/Lisbon","timezone_offset":0,"data":[{"dt":1672531200,"sunrise":1672559671,"sunset":1672593902,"temp":17.48,"feels_like":17.16,"pressure":1019,"humidity":72,"dew_point":12.38,"clouds":20,"visibility":9999,"wind_speed":16.54,"wind_deg":337,"wind_gust":16.54,"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02n"}]}]}'; public const ONE_CALL_DAY_SUMMARY = '{"lat":38.7077507,"lon":-9.1365919,"tz":"+00:00","date":"2023-01-01","units":"metric","cloud_cover":{"afternoon":75.0},"humidity":{"afternoon":71.0},"precipitation":{"total":2.53},"temperature":{"min":12.52,"max":18.29,"afternoon":18.26,"night":17.39,"evening":13.9,"morning":17.23},"pressure":{"afternoon":1017.0},"wind":{"max":{"speed":26.38,"direction":225.0}}}'; diff --git a/src/UnitSystem/UnitSystem.php b/src/UnitSystem/UnitSystem.php index b7239d3..593f853 100644 --- a/src/UnitSystem/UnitSystem.php +++ b/src/UnitSystem/UnitSystem.php @@ -2,18 +2,16 @@ namespace ProgrammatorDev\OpenWeatherMap\UnitSystem; -use ProgrammatorDev\OpenWeatherMap\Util\ReflectionTrait; +use ProgrammatorDev\OpenWeatherMap\Helper\ReflectionHelper; class UnitSystem { - use ReflectionTrait; - public const METRIC = 'metric'; public const IMPERIAL = 'imperial'; public const STANDARD = 'standard'; public static function getOptions(): array { - return (new UnitSystem)->getClassConstants(self::class); + return ReflectionHelper::getClassConstants(self::class); } } \ No newline at end of file diff --git a/src/Util/EntityTrait.php b/src/Util/EntityTrait.php deleted file mode 100644 index 24ee6ce..0000000 --- a/src/Util/EntityTrait.php +++ /dev/null @@ -1,13 +0,0 @@ - [ + Answer::class, + MockResponse::ASSISTANT_START_SESSION, + 'assistant', + 'startSession', + ['prompt'] + ]; + yield 'resume session' => [ + Answer::class, + MockResponse::ASSISTANT_RESUME_SESSION, + 'assistant', + 'resumeSession', + ['session-id', 'prompt'] + ]; + } +} \ No newline at end of file diff --git a/tests/Unit/Assistant/AnswerTest.php b/tests/Unit/Assistant/AnswerTest.php new file mode 100644 index 0000000..980c527 --- /dev/null +++ b/tests/Unit/Assistant/AnswerTest.php @@ -0,0 +1,48 @@ + 'Answer text', + 'data' => [ + 'location' => [ + 'clouds' => 100, + 'dew_point' => 10, + 'dt' => 1762622549, + 'feels_like' => 10, + 'humidity' => 10, + 'pressure' => 1000, + 'sunrise' => 1762602543, + 'sunset' => 1762638067, + 'temp' => 10, + 'uvi' => 1, + 'visibility' => 10000, + 'weather' => [ + [ + 'description' => 'description', + 'icon' => '01d', + 'id' => 200, + 'main' => 'name' + ] + ], + 'wind_deg' => 10, + 'wind_speed' => 10, + 'wind_gust' => 10, + ] + ], + 'session_id' => '777f049a-c96b-423f-baef-ca34ff725fe9' + ]); + + $this->assertSame('Answer text', $entity->getAnswer()); + $this->assertSame('777f049a-c96b-423f-baef-ca34ff725fe9', $entity->getSessionId()); + $this->assertContainsOnlyInstancesOf(WeatherData::class, $entity->getData()); + } +} \ No newline at end of file diff --git a/tests/Unit/Assistant/WeatherDataTest.php b/tests/Unit/Assistant/WeatherDataTest.php new file mode 100644 index 0000000..080b3aa --- /dev/null +++ b/tests/Unit/Assistant/WeatherDataTest.php @@ -0,0 +1,54 @@ + 100, + 'dew_point' => 10, + 'dt' => 1762622549, + 'feels_like' => 10, + 'humidity' => 10, + 'pressure' => 1000, + 'sunrise' => 1762602543, + 'sunset' => 1762638067, + 'temp' => 10, + 'uvi' => 1, + 'visibility' => 10000, + 'weather' => [ + [ + 'description' => 'description', + 'icon' => '01d', + 'id' => 200, + 'main' => 'name' + ] + ], + 'wind_deg' => 10, + 'wind_speed' => 10, + 'wind_gust' => 10, + ]); + + $this->assertSame('locationName', $entity->getLocationName()); + $this->assertInstanceOf(\DateTimeImmutable::class, $entity->getDateTime()); + $this->assertSame(1000, $entity->getAtmosphericPressure()); + $this->assertSame(10, $entity->getHumidity()); + $this->assertSame(10.0, $entity->getDewPoint()); + $this->assertSame(1.0, $entity->getUltraVioletIndex()); + $this->assertSame(100, $entity->getCloudiness()); + $this->assertInstanceOf(Wind::class, $entity->getWind()); + $this->assertContainsOnlyInstancesOf(Condition::class, $entity->getConditions()); + $this->assertSame(10.0, $entity->getTemperature()); + $this->assertSame(10.0, $entity->getTemperatureFeelsLike()); + $this->assertSame(10000, $entity->getVisibility()); + $this->assertInstanceOf(\DateTimeImmutable::class, $entity->getSunriseAt()); + $this->assertInstanceOf(\DateTimeImmutable::class, $entity->getSunsetAt()); + } +} \ No newline at end of file