Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/id 204 post trip process #24

Merged
merged 5 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 30 additions & 28 deletions app/Domain/Trip/Enum/TripEventEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,35 +14,34 @@ enum TripEventEnum: String
case SPEEDING = 'speeding';
case TOO_SLOW = 'too_slow';
case HARSH_BRAKING = 'harsh braking';
case BREAKING_STOP_SHORT = 'breaking_stop_short';
case PERFECECT_BREAK = 'perfect_break';
case INEFFICIENT_BREAK = 'inefficient_break';
case BREAKING_AND_GAS = 'breaking_and_gas';
case MISSED_GEAR = 'missed_gear';
case PERFECT_GEAR = 'perfect_gear';
case INEFFICIENT_GEAR = 'inefficient_gear';
case LATE_SHIFT_GEAR = 'late_shift_gear';
case MISSED_SHIFT_GEAR = 'missed_shift_gear';
case HARSH_STEERING = 'harsh_steering';
case INEFFICIENT_STEERING = 'inefficient_steering';

case SYSTEM_START = "System Start";
case SYSTEM_END = "System End";
public function requiredDataField(): array
{
return match($this) {
self::SPEEDING => ['speed', 'speed_limit'],
default => [],
};
}

public function getEventTitle(mixed $value = null): string
{
return match ($this) {
self::CROSSED_LINE => 'Crossed Line',
self::COLLISION => 'Collision',
self::CROSSED_LINE => 'Lane departure detected',
self::COLLISION => 'Collision detected',
self::SPEEDING => $this->getSpeedingEventTitle($value),
self::HARSH_BRAKING => 'Harsh Braking',
self::BREAKING_STOP_SHORT => 'Stop Short',
self::PERFECECT_BREAK => 'Perfect Break',
self::INEFFICIENT_BREAK => 'Inefficient Break',
self::MISSED_GEAR => 'Missed Gear',
self::PERFECT_GEAR => 'Perfect Gear',
self::INEFFICIENT_GEAR => 'Inefficient Gear',
self::HARSH_STEERING => 'Harsh Steering',
self::INEFFICIENT_STEERING => 'Inefficient Steering',
self::SYSTEM_START => 'System Start',
self::SYSTEM_END => 'System End',
self::HARSH_BRAKING => 'Abrupt Braking Occurrence',
self::BREAKING_AND_GAS => 'Incorrect Throttle and Brake usage',
self::LATE_SHIFT_GEAR => 'Delayed Gear engagement',
self::MISSED_SHIFT_GEAR => 'Gear Shift Omitted',
self::MISSED_GEAR => 'Gear Engagement Omitted',
self::HARSH_STEERING => 'Aggressive Steering Maneuver',
self::INEFFICIENT_STEERING => 'Suboptimal Steering Maneuver',

default => throw new \Exception('Unexpected match value'),
};
Expand All @@ -52,6 +51,8 @@ private function getSpeedingEventTitle(mixed $value): string
{
$value = $value['speed'] - $value['speed_limit'];

$value = round($value);

return 'Over the speed limit +' . $value . ' km/h';
}

Expand All @@ -77,28 +78,29 @@ public function getEventSeverity(mixed $value = null): SeverityEnum
self::COLLISION => SeverityEnum::HIGH,
self::SPEEDING => $this->getSpeedSeverity($value),
self::HARSH_BRAKING => SeverityEnum::MEDIUM,
self::BREAKING_STOP_SHORT => SeverityEnum::HIGH,
self::PERFECECT_BREAK => SeverityEnum::LOW,
self::INEFFICIENT_BREAK => SeverityEnum::MEDIUM,
self::BREAKING_AND_GAS => SeverityEnum::HIGH,
self::LATE_SHIFT_GEAR => SeverityEnum::MEDIUM,
self::MISSED_SHIFT_GEAR => SeverityEnum::MEDIUM,
self::MISSED_GEAR => SeverityEnum::MEDIUM,
self::PERFECT_GEAR => SeverityEnum::LOW,
self::INEFFICIENT_GEAR => SeverityEnum::MEDIUM,
self::HARSH_STEERING => SeverityEnum::MEDIUM,
self::INEFFICIENT_STEERING => SeverityEnum::MEDIUM,
self::SYSTEM_START => SeverityEnum::LOW,
self::SYSTEM_END => SeverityEnum::LOW,
default => throw new \Exception('Unexpected match value'),
};
}

private function getSpeedSeverity(mixed $value): SeverityEnum
{
if (!is_array($value) && is_string($value)) {
$value = json_decode($value, true);
}

$value = $value['speed'] - $value['speed_limit'];

return match (true) {
$value > 0 && $value <= 10 => SeverityEnum::LOW,
$value > 0 && $value <= 10 => SeverityEnum::MEDIUM,
$value > 10 && $value <= 20 => SeverityEnum::MEDIUM,
$value > 20 => SeverityEnum::HIGH,
$value < 0 => SeverityEnum::LOW,
default => throw new \Exception('Unexpected match value'),
};
}
Expand Down
10 changes: 4 additions & 6 deletions app/Domain/Trip/Enum/TripStatisticParserEnum.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,20 @@ public function getEventEnums(): array
return match ($this) {
self::SPEED_PROFILE => [
TripEventEnum::SPEEDING,
TripEventEnum::HARSH_BRAKING,
],
self::BREAK_PROFILE => [
TripEventEnum::HARSH_BRAKING,
TripEventEnum::BREAKING_STOP_SHORT,
TripEventEnum::PERFECECT_BREAK,
TripEventEnum::INEFFICIENT_BREAK,
TripEventEnum::BREAKING_AND_GAS,
],
self::STEERING_PROFILE => [
TripEventEnum::HARSH_STEERING,
TripEventEnum::INEFFICIENT_STEERING,
// TripEventEnum::COLLISION,
],
self::GEAR_PROFILE => [
TripEventEnum::MISSED_GEAR,
TripEventEnum::PERFECT_GEAR,
TripEventEnum::INEFFICIENT_GEAR,
TripEventEnum::LATE_SHIFT_GEAR,
TripEventEnum::MISSED_SHIFT_GEAR
],
default => throw new \Exception('Unexpected match value'),
};
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace App\Domain\Trip\Helper;
namespace App\Domain\Trip\Helper\Parsers;

use App\Domain\Trip\Enum\TripStatisticParserEnum;
use App\Domain\Trip\Model\Trip;
Expand Down
116 changes: 116 additions & 0 deletions app/Domain/Trip/Helper/Parsers/Profile/AbstractProfileParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
<?php

namespace App\Domain\Trip\Helper\Parsers\Profile;

use App\Domain\Trip\Enum\TripEventEnum;
use App\Domain\Trip\Enum\TripStatisticParserEnum;
use App\Domain\Trip\Model\Trip;
use App\Domain\Trip\Model\TripEvent;
use App\Domain\Trip\Model\TripStatistic;
use App\Domain\Trip\ValueObject\Statistic\Profile\TimelineValueObject;
use App\Domain\Trip\ValueObject\Statistic\ProfileStatisticValueObject;
use App\Domain\Trip\ValueObject\Statistic\ProfileValueObject;
use Illuminate\Database\Eloquent\Collection;

abstract class AbstractProfileParser
{
protected TripStatistic $profile;

public function __construct(
protected Trip $trip,
) {
$this->profile = $this->getTripStatistic();

$data = $this->profile->data ?? [];
foreach ($data as $key => $value) {
$this->{$key} = $value;
}
}

abstract public function parse(Trip $trip): void;

abstract protected function getParserEnum(): TripStatisticParserEnum;

/**
* @return ProfileStatisticValueObject[]
*/
abstract protected function getProfileTitle(): string;

abstract protected function getProfileStatistics(): array;

public function getProfile(): ProfileValueObject
{
return new ProfileValueObject(
title: $this->getProfileTitle(),
statistics: $this->getProfileStatistics(),
events: $this->getTimeLineEvents()->getProfileEvents()
);
}

protected function getTripStatistic(bool $override = false): TripStatistic
{
$profile = $this->trip->statistics()->where('parser', $this->getParserEnum())->first();
if ($profile instanceof TripStatistic) {
if ($override) {
$profile->delete();
} else {
return $profile;
}
}

return new TripStatistic([
'parser' => $this->getParserEnum(),
'trip_id' => $this->trip->id,
]);
}

protected function getEvents(): Collection
{
return $this->trip
->events()
->where('is_processed', true)
->whereIn('type', $this->getParserEnum()->getEventEnums())
->get();
}

private function fakeData(Collection &$events): void
{
foreach (TripEventEnum::values() as $event) {
$event = TripEventEnum::from($event);
if (!in_array($event, $this->getParserEnum()->getEventEnums())) {
continue;
}

for($i = 0; $i < rand(2, 5); $i++) {
$data = [];
if ($event === TripEventEnum::SPEEDING) {
$data = [
'speed' => rand(0, 100),
'speed_limit' => rand(0, 100),
];
}

$events->push(new TripEvent([
'type' => $event,
'trip_id' => $this->trip->id,
'distance' => rand(0, 100),
'data' => $data,
]));
}
}
}

protected function getTimeLineEvents(): TimelineValueObject
{
$events = $this->getEvents();

// $this->fakeData($events);

return new TimelineValueObject($events);
}

protected function countEvents(TripEventEnum $event): int
{
return $this->getEvents()->where('type', $event)->count();
}
}
40 changes: 40 additions & 0 deletions app/Domain/Trip/Helper/Parsers/Profile/BreakingProfileParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace App\Domain\Trip\Helper\Parsers\Profile;

use App\Domain\Trip\Enum\TripEventEnum;
use App\Domain\Trip\Enum\TripStatisticParserEnum;
use App\Domain\Trip\Model\Trip;
use App\Domain\Trip\ValueObject\Statistic\ProfileEventValueObject;
use App\Domain\Trip\ValueObject\Statistic\ProfileStatisticValueObject;

class BreakingProfileParser extends AbstractProfileParser
{
protected function getParserEnum(): TripStatisticParserEnum
{
return TripStatisticParserEnum::BREAK_PROFILE;
}

protected function getProfileTitle(): string
{
return 'Breaking';
}

protected function getProfileStatistics(): array
{
return [
new ProfileStatisticValueObject(
title: 'Abrupt Braking',
value: $this->countEvents(TripEventEnum::HARSH_BRAKING)
),
new ProfileStatisticValueObject(
title: 'Incorrect paddle usage',
value: $this->countEvents(TripEventEnum::BREAKING_AND_GAS)
),
];
}

public function parse(Trip $trip): void
{
}
}
40 changes: 40 additions & 0 deletions app/Domain/Trip/Helper/Parsers/Profile/GearProfileParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace App\Domain\Trip\Helper\Parsers\Profile;

use App\Domain\Trip\Enum\TripEventEnum;
use App\Domain\Trip\Enum\TripStatisticParserEnum;
use App\Domain\Trip\Model\Trip;
use App\Domain\Trip\ValueObject\Statistic\ProfileEventValueObject;
use App\Domain\Trip\ValueObject\Statistic\ProfileStatisticValueObject;

class GearProfileParser extends AbstractProfileParser
{
protected function getParserEnum(): TripStatisticParserEnum
{
return TripStatisticParserEnum::GEAR_PROFILE;
}

protected function getProfileTitle(): string
{
return 'Gear';
}

protected function getProfileStatistics(): array
{
return [
new ProfileStatisticValueObject(
title: 'Engagement Omitted',
value: $this->countEvents(TripEventEnum::MISSED_GEAR)
),
new ProfileStatisticValueObject(
title: 'Late Shift',
value: $this->countEvents(TripEventEnum::LATE_SHIFT_GEAR)
)
];
}

public function parse(Trip $trip): void
{
}
}
51 changes: 51 additions & 0 deletions app/Domain/Trip/Helper/Parsers/Profile/SpeedProfileParser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace App\Domain\Trip\Helper\Parsers\Profile;

use App\Domain\Trip\Enum\TripStatisticParserEnum;
use App\Domain\Trip\Model\Trip;
use App\Domain\Trip\ValueObject\Statistic\ProfileEventValueObject;
use App\Domain\Trip\ValueObject\Statistic\ProfileStatisticValueObject;

class SpeedProfileParser extends AbstractProfileParser
{
protected int $averageSpeed = 0;

protected function getParserEnum(): TripStatisticParserEnum
{
return TripStatisticParserEnum::SPEED_PROFILE;
}

protected function getProfileTitle(): string
{
return 'Speed';
}

protected function getProfileStatistics(): array
{
return [
new ProfileStatisticValueObject(
title: 'Average speed',
value: $this->averageSpeed,
unit: 'km/h'
)
];
}

public function parse(Trip $trip): void
{
$statistic = $this->getTripStatistic(true);

$statistic->data = [
'averageSpeed' => $trip->data()->avg('speed'),
];

$statistic->save();
}

public function getAverageSpeed(): int
{
return $this->averageSpeed;
}

}
Loading
Loading