Added new tiles and extended model
This commit is contained in:
parent
593972c401
commit
3160d60eaf
22
src/Domain/Model/Battery/BatteryProperties.php
Normal file
22
src/Domain/Model/Battery/BatteryProperties.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Battery;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Energy;
|
||||||
|
|
||||||
|
class BatteryProperties
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Energy $usableCapacity,
|
||||||
|
public readonly Energy $totalCapacity,
|
||||||
|
public readonly CellChemistry $cellChemistry = CellChemistry::LithiumIronPhosphate,
|
||||||
|
public readonly string $model = '4680',
|
||||||
|
public readonly string $manufacturer = 'Tesla',
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->usableCapacity->__toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/Domain/Model/Battery/CellChemistry.php
Normal file
10
src/Domain/Model/Battery/CellChemistry.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Battery;
|
||||||
|
|
||||||
|
enum CellChemistry: string
|
||||||
|
{
|
||||||
|
case LithiumIronPhosphate = 'LFP';
|
||||||
|
case LithiumNickelCobaltAluminumOxide = 'NCA';
|
||||||
|
case LithiumNickelManganeseOxide = 'NMC';
|
||||||
|
}
|
||||||
@ -4,21 +4,8 @@ namespace App\Domain\Model;
|
|||||||
|
|
||||||
class CarModel
|
class CarModel
|
||||||
{
|
{
|
||||||
private ?string $id = null;
|
public function __construct(
|
||||||
|
public string $name,
|
||||||
private string $name;
|
public ?Brand $brand = null,
|
||||||
|
) {}
|
||||||
private int $productionStartYear;
|
|
||||||
|
|
||||||
private ?int $productionEndYear = null;
|
|
||||||
|
|
||||||
private ?string $category = null;
|
|
||||||
|
|
||||||
private ?string $description = null;
|
|
||||||
|
|
||||||
private ?string $image = null;
|
|
||||||
|
|
||||||
private ?Brand $brand = null;
|
|
||||||
|
|
||||||
private array $revisions = [];
|
|
||||||
}
|
}
|
||||||
@ -2,29 +2,31 @@
|
|||||||
|
|
||||||
namespace App\Domain\Model;
|
namespace App\Domain\Model;
|
||||||
|
|
||||||
use App\Domain\Model\Value\Acceleration;
|
|
||||||
use App\Domain\Model\Value\Battery;
|
|
||||||
use App\Domain\Model\Value\Consumption;
|
use App\Domain\Model\Value\Consumption;
|
||||||
use App\Domain\Model\Value\ChargingSpeed;
|
use App\Domain\Model\Value\Date;
|
||||||
use App\Domain\Model\Value\Power;
|
|
||||||
use App\Domain\Model\Value\Range;
|
|
||||||
use App\Domain\Model\Value\TopSpeed;
|
|
||||||
use App\Domain\Model\Value\Price;
|
use App\Domain\Model\Value\Price;
|
||||||
|
use App\Domain\Model\Battery\BatteryProperties;
|
||||||
|
use App\Domain\Model\Charging\ChargingProperties;
|
||||||
|
|
||||||
final readonly class CarRevision
|
final readonly class CarRevision
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public string $name,
|
public string $name,
|
||||||
public int $releaseYear,
|
public ?Date $productionBegin = null,
|
||||||
public ?Power $power = null,
|
public ?Date $productionEnd = null,
|
||||||
public ?Acceleration $acceleration = null,
|
public ?DrivingCharacteristics $drivingCharacteristics = null,
|
||||||
public ?TopSpeed $topSpeed = null,
|
public ?BatteryProperties $battery = null,
|
||||||
public ?Range $range = null,
|
public ?ChargingProperties $chargingProperties = null,
|
||||||
public ?Battery $battery = null,
|
public ?RangeProperties $rangeProperties = null,
|
||||||
public ?Consumption $consumption = null,
|
|
||||||
public ?Price $price = null,
|
public ?Price $catalogPrice = null,
|
||||||
public ?ChargingSpeed $chargingSpeed = null,
|
|
||||||
public ?CarModel $carModel = null,
|
public ?CarModel $carModel = null,
|
||||||
public ?Image $image = null,
|
public ?Image $image = null,
|
||||||
) {}
|
) {
|
||||||
|
if ($this->productionBegin && $this->productionEnd) {
|
||||||
|
if ($this->productionBegin->year > $this->productionEnd->year) {
|
||||||
|
throw new \InvalidArgumentException('Production begin year must be before production end year');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
22
src/Domain/Model/Charging/ChargeCurve.php
Normal file
22
src/Domain/Model/Charging/ChargeCurve.php
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Charging;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Power;
|
||||||
|
|
||||||
|
final readonly class ChargeCurve
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?Power $averagePowerSoc0 = null,
|
||||||
|
public ?Power $averagePowerSoc10 = null,
|
||||||
|
public ?Power $averagePowerSoc20 = null,
|
||||||
|
public ?Power $averagePowerSoc30 = null,
|
||||||
|
public ?Power $averagePowerSoc40 = null,
|
||||||
|
public ?Power $averagePowerSoc50 = null,
|
||||||
|
public ?Power $averagePowerSoc60 = null,
|
||||||
|
public ?Power $averagePowerSoc70 = null,
|
||||||
|
public ?Power $averagePowerSoc80 = null,
|
||||||
|
public ?Power $averagePowerSoc90 = null,
|
||||||
|
public ?Power $averagePowerSoc100 = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
17
src/Domain/Model/Charging/ChargeTimeProperties.php
Normal file
17
src/Domain/Model/Charging/ChargeTimeProperties.php
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Charging;
|
||||||
|
|
||||||
|
final readonly class ChargeTimeProperties
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?int $minutesFrom0To100 = null,
|
||||||
|
public ?int $minutesFrom0To70 = null,
|
||||||
|
public ?int $minutesFrom10To70 = null,
|
||||||
|
public ?int $minutesFrom20To70 = null,
|
||||||
|
public ?int $minutesFrom10To80 = null,
|
||||||
|
public ?int $minutesFrom20To80 = null,
|
||||||
|
public ?int $minutesFrom10To90 = null,
|
||||||
|
public ?int $minutesFrom20To90 = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
16
src/Domain/Model/Charging/ChargingConnectivity.php
Normal file
16
src/Domain/Model/Charging/ChargingConnectivity.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Charging;
|
||||||
|
|
||||||
|
final readonly class ChargingConnectivity
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param ConnectorType[] $connectorTypes
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly ?bool $is400v = null,
|
||||||
|
public readonly ?bool $is800v = null,
|
||||||
|
public readonly ?bool $plugAndCharge = null,
|
||||||
|
public readonly array $connectorTypes = [],
|
||||||
|
) {}
|
||||||
|
}
|
||||||
16
src/Domain/Model/Charging/ChargingProperties.php
Normal file
16
src/Domain/Model/Charging/ChargingProperties.php
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Charging;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Power;
|
||||||
|
|
||||||
|
final readonly class ChargingProperties
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?Power $topChargingSpeed = null,
|
||||||
|
public ?ChargeCurve $chargeCurve = null,
|
||||||
|
public ?ChargeTimeProperties $chargeTimeProperties = null,
|
||||||
|
public ?ChargingConnectivity $chargingConnectivity = null,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
||||||
10
src/Domain/Model/Charging/ConnectorType.php
Normal file
10
src/Domain/Model/Charging/ConnectorType.php
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Charging;
|
||||||
|
|
||||||
|
enum ConnectorType: string
|
||||||
|
{
|
||||||
|
case Type2 = 'Type 2';
|
||||||
|
case CCS = 'CCS';
|
||||||
|
case CHAdeMO = 'CHAdeMO';
|
||||||
|
}
|
||||||
18
src/Domain/Model/DrivingCharacteristics.php
Normal file
18
src/Domain/Model/DrivingCharacteristics.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Power;
|
||||||
|
use App\Domain\Model\Value\Acceleration;
|
||||||
|
use App\Domain\Model\Value\Consumption;
|
||||||
|
use App\Domain\Model\Value\Speed;
|
||||||
|
|
||||||
|
final readonly class DrivingCharacteristics
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?Power $power = null,
|
||||||
|
public ?Acceleration $acceleration = null,
|
||||||
|
public ?Speed $topSpeed = null,
|
||||||
|
public ?Consumption $consumption = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
12
src/Domain/Model/Range/NefzRange.php
Normal file
12
src/Domain/Model/Range/NefzRange.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Range;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Range;
|
||||||
|
|
||||||
|
final readonly class NefzRange
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Range $range,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
18
src/Domain/Model/Range/RealRange.php
Normal file
18
src/Domain/Model/Range/RealRange.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Range;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Range;
|
||||||
|
use App\Domain\Model\Value\Season;
|
||||||
|
use App\Domain\Model\Value\Speed;
|
||||||
|
|
||||||
|
class RealRange
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Range $range,
|
||||||
|
public readonly ?Season $season = null,
|
||||||
|
public readonly ?Speed $averageSpeed = null,
|
||||||
|
)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
12
src/Domain/Model/Range/WltpRange.php
Normal file
12
src/Domain/Model/Range/WltpRange.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Range;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Range;
|
||||||
|
|
||||||
|
final readonly class WltpRange
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public readonly Range $range,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
18
src/Domain/Model/RangeProperties.php
Normal file
18
src/Domain/Model/RangeProperties.php
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model;
|
||||||
|
|
||||||
|
use App\Domain\Model\Range\NefzRange;
|
||||||
|
use App\Domain\Model\Range\WltpRange;
|
||||||
|
|
||||||
|
final readonly class RangeProperties
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param RealRange[] $realRangeTests
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public readonly ?WltpRange $wltp = null,
|
||||||
|
public readonly ?NefzRange $nefz = null,
|
||||||
|
public readonly array $realRangeTests = [],
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@ -1,18 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Domain\Model\Value;
|
|
||||||
|
|
||||||
class Battery
|
|
||||||
{
|
|
||||||
public function __construct(
|
|
||||||
public readonly Energy $usableCapacity,
|
|
||||||
public readonly Energy $totalCapacity,
|
|
||||||
public readonly string $technology = 'Lithium-Ion',
|
|
||||||
) {
|
|
||||||
}
|
|
||||||
|
|
||||||
public function __toString(): string
|
|
||||||
{
|
|
||||||
return $this->usableCapacity->__toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
25
src/Domain/Model/Value/Date.php
Normal file
25
src/Domain/Model/Value/Date.php
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Value;
|
||||||
|
|
||||||
|
final readonly class Date
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?int $month,
|
||||||
|
public ?int $day,
|
||||||
|
public int $year,
|
||||||
|
) {
|
||||||
|
if ($this->month < 1 || $this->month > 12) {
|
||||||
|
throw new \InvalidArgumentException('Month must be between 1 and 12');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($this->day < 1 || $this->day > 31) {
|
||||||
|
throw new \InvalidArgumentException('Day must be between 1 and 31');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __toString(): string
|
||||||
|
{
|
||||||
|
return $this->year . '-' . $this->month . '-' . $this->day;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ class Price
|
|||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly int $price,
|
public readonly int $price,
|
||||||
public readonly Currency $currency,
|
public readonly Currency $currency,
|
||||||
|
public readonly ?bool $includesVat = null,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
public function __toString(): string
|
public function __toString(): string
|
||||||
|
|||||||
11
src/Domain/Model/Value/Season.php
Normal file
11
src/Domain/Model/Value/Season.php
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Model\Value;
|
||||||
|
|
||||||
|
enum Season: string
|
||||||
|
{
|
||||||
|
case Winter = 'Winter';
|
||||||
|
case Spring = 'Spring';
|
||||||
|
case Summer = 'Summer';
|
||||||
|
case Autumn = 'Autumn';
|
||||||
|
}
|
||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Domain\Model\Value;
|
namespace App\Domain\Model\Value;
|
||||||
|
|
||||||
class TopSpeed
|
class Speed
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly int $kmh,
|
public readonly int $kmh,
|
||||||
@ -3,18 +3,30 @@
|
|||||||
namespace App\Domain\Search;
|
namespace App\Domain\Search;
|
||||||
|
|
||||||
use App\Domain\Model\CarRevision;
|
use App\Domain\Model\CarRevision;
|
||||||
|
use App\Domain\Model\DrivingCharacteristics;
|
||||||
use App\Domain\Model\Image;
|
use App\Domain\Model\Image;
|
||||||
use App\Domain\Model\Value\Currency;
|
use App\Domain\Model\Value\Currency;
|
||||||
|
use App\Domain\Model\Value\Date;
|
||||||
use App\Domain\Model\Value\Price;
|
use App\Domain\Model\Value\Price;
|
||||||
use App\Domain\Model\Value\Range;
|
use App\Domain\Model\Value\Range;
|
||||||
use App\Domain\Model\Value\Battery;
|
use App\Domain\Model\Battery\BatteryProperties;
|
||||||
|
use App\Domain\Model\Battery\CellChemistry;
|
||||||
use App\Domain\Model\Value\Power;
|
use App\Domain\Model\Value\Power;
|
||||||
use App\Domain\Model\Value\Acceleration;
|
use App\Domain\Model\Value\Acceleration;
|
||||||
use App\Domain\Model\Value\ChargingSpeed;
|
|
||||||
use App\Domain\Model\Value\Consumption;
|
use App\Domain\Model\Value\Consumption;
|
||||||
use App\Domain\Model\Value\TopSpeed;
|
use App\Domain\Model\Value\Speed;
|
||||||
use App\Domain\Model\Value\Drivetrain;
|
use App\Domain\Model\Value\Drivetrain;
|
||||||
use App\Domain\Model\Value\Energy;
|
use App\Domain\Model\Value\Energy;
|
||||||
|
use App\Domain\Model\Charging\ChargingProperties;
|
||||||
|
use App\Domain\Model\Charging\ChargeCurve;
|
||||||
|
use App\Domain\Model\Charging\ChargeTimeProperties;
|
||||||
|
use App\Domain\Model\Charging\ChargingConnectivity;
|
||||||
|
use App\Domain\Model\Charging\ConnectorType;
|
||||||
|
use App\Domain\Model\RangeProperties;
|
||||||
|
use App\Domain\Model\Range\WltpRange;
|
||||||
|
use App\Domain\Model\Range\NefzRange;
|
||||||
|
use App\Domain\Model\Range\RealRange;
|
||||||
|
use App\Domain\Model\Value\Season;
|
||||||
use App\Domain\Search\Tiles\SectionTile;
|
use App\Domain\Search\Tiles\SectionTile;
|
||||||
use App\Domain\Search\Tiles\SubSectionTile;
|
use App\Domain\Search\Tiles\SubSectionTile;
|
||||||
use App\Domain\Search\Tiles\BrandTile;
|
use App\Domain\Search\Tiles\BrandTile;
|
||||||
@ -29,45 +41,129 @@ use App\Domain\Search\Tiles\AvailabilityTile;
|
|||||||
use App\Domain\Search\Tiles\CarTile;
|
use App\Domain\Search\Tiles\CarTile;
|
||||||
use App\Domain\Search\Tiles\TopSpeedTile;
|
use App\Domain\Search\Tiles\TopSpeedTile;
|
||||||
use App\Domain\Search\Tiles\DrivetrainTile;
|
use App\Domain\Search\Tiles\DrivetrainTile;
|
||||||
|
// New tiles
|
||||||
|
use App\Domain\Search\Tiles\ChargeCurveTile;
|
||||||
|
use App\Domain\Search\Tiles\ChargeTimeTile;
|
||||||
|
use App\Domain\Search\Tiles\ChargingConnectivityTile;
|
||||||
|
use App\Domain\Search\Tiles\BatteryDetailsTile;
|
||||||
|
use App\Domain\Search\Tiles\ProductionPeriodTile;
|
||||||
|
use App\Domain\Search\Tiles\RangeComparisonTile;
|
||||||
|
use App\Domain\Search\Tiles\RealRangeTile;
|
||||||
|
use App\Domain\Search\Tiles\PerformanceOverviewTile;
|
||||||
|
|
||||||
class Engine
|
class Engine
|
||||||
{
|
{
|
||||||
public function search(string $query): TileCollection
|
public function search(string $query): TileCollection
|
||||||
{
|
{
|
||||||
|
// Create comprehensive test data showing all the new features
|
||||||
|
$batteryProperties = new BatteryProperties(
|
||||||
|
usableCapacity: new Energy(77.0),
|
||||||
|
totalCapacity: new Energy(82.0),
|
||||||
|
cellChemistry: CellChemistry::LithiumNickelManganeseOxide,
|
||||||
|
model: 'NCM811',
|
||||||
|
manufacturer: 'LG Energy Solution'
|
||||||
|
);
|
||||||
|
|
||||||
|
$chargeCurve = new ChargeCurve(
|
||||||
|
averagePowerSoc0: new Power(175),
|
||||||
|
averagePowerSoc10: new Power(175),
|
||||||
|
averagePowerSoc20: new Power(170),
|
||||||
|
averagePowerSoc30: new Power(165),
|
||||||
|
averagePowerSoc40: new Power(155),
|
||||||
|
averagePowerSoc50: new Power(145),
|
||||||
|
averagePowerSoc60: new Power(130),
|
||||||
|
averagePowerSoc70: new Power(110),
|
||||||
|
averagePowerSoc80: new Power(85),
|
||||||
|
averagePowerSoc90: new Power(50),
|
||||||
|
averagePowerSoc100: new Power(20)
|
||||||
|
);
|
||||||
|
|
||||||
|
$chargeTimeProperties = new ChargeTimeProperties(
|
||||||
|
minutesFrom0To100: 155,
|
||||||
|
minutesFrom10To80: 28,
|
||||||
|
minutesFrom20To80: 25,
|
||||||
|
minutesFrom10To90: 42
|
||||||
|
);
|
||||||
|
|
||||||
|
$chargingConnectivity = new ChargingConnectivity(
|
||||||
|
is400v: true,
|
||||||
|
is800v: false,
|
||||||
|
plugAndCharge: true,
|
||||||
|
connectorTypes: [ConnectorType::CCS, ConnectorType::Type2]
|
||||||
|
);
|
||||||
|
|
||||||
|
$chargingProperties = new ChargingProperties(
|
||||||
|
topChargingSpeed: new Power(175),
|
||||||
|
chargeCurve: $chargeCurve,
|
||||||
|
chargeTimeProperties: $chargeTimeProperties,
|
||||||
|
chargingConnectivity: $chargingConnectivity
|
||||||
|
);
|
||||||
|
|
||||||
|
$drivingCharacteristics = new DrivingCharacteristics(
|
||||||
|
power: new Power(210),
|
||||||
|
acceleration: new Acceleration(6.6),
|
||||||
|
topSpeed: new Speed(180),
|
||||||
|
consumption: new Consumption(new Energy(17.1))
|
||||||
|
);
|
||||||
|
|
||||||
|
$wltpRange = new WltpRange(new Range(450));
|
||||||
|
$nefzRange = new NefzRange(new Range(485));
|
||||||
|
$realRangeTests = [
|
||||||
|
new RealRange(new Range(380), Season::Winter, new Speed(130)),
|
||||||
|
new RealRange(new Range(420), Season::Summer, new Speed(120)),
|
||||||
|
new RealRange(new Range(365), Season::Winter, new Speed(160))
|
||||||
|
];
|
||||||
|
|
||||||
|
$rangeProperties = new RangeProperties(
|
||||||
|
wltp: $wltpRange,
|
||||||
|
nefz: $nefzRange,
|
||||||
|
realRangeTests: $realRangeTests
|
||||||
|
);
|
||||||
|
|
||||||
$skodaElroq85 = new CarRevision(
|
$skodaElroq85 = new CarRevision(
|
||||||
'Skoda Elroq 85', 2024,
|
name: 'Skoda Enyaq iV 85',
|
||||||
new Power(210),
|
productionBegin: new Date(1, 1, 2020),
|
||||||
new Acceleration(6.6),
|
productionEnd: null, // Still in production
|
||||||
new TopSpeed(180),
|
drivingCharacteristics: $drivingCharacteristics,
|
||||||
new Range(450),
|
battery: $batteryProperties,
|
||||||
new Battery(new Energy(77.0), new Energy(82.0)),
|
chargingProperties: $chargingProperties,
|
||||||
new Consumption(new Energy(171)),
|
rangeProperties: $rangeProperties,
|
||||||
new Price(43900, Currency::euro()),
|
catalogPrice: new Price(43900, Currency::euro()),
|
||||||
new ChargingSpeed(new Power(175), new Power(11)),
|
image: new Image('https://www.scherer-gruppe.de/media/f3b72d42-4b26-4606-8df4-d840efeff017/01_elroc.jpg?w=1920&h=758&action=crop&scale=both&anchor=middlecenter')
|
||||||
image: new Image('https://www.scherer-gruppe.de/media/f3b72d42-4b26-4606-8df4-d840efeff017/01_elroc.jpg?w=1920&h=758&action=crop&scale=both&anchor=middlecenter'),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return new TileCollection([
|
return new TileCollection([
|
||||||
new SectionTile('Skoda Elroq 85', [
|
new SectionTile('Skoda Enyaq iV 85', [
|
||||||
new CarTile($skodaElroq85->image, [
|
new CarTile($skodaElroq85->image, [
|
||||||
new BrandTile('Skoda'),
|
new BrandTile('Skoda'),
|
||||||
new PriceTile(new Price(43900, Currency::euro())),
|
new PriceTile($skodaElroq85->catalogPrice),
|
||||||
new AvailabilityTile('Bestellbar', 'Oktober 2024'),
|
new ProductionPeriodTile($skodaElroq85->productionBegin, $skodaElroq85->productionEnd),
|
||||||
new RangeTile(new Range(450)),
|
|
||||||
]),
|
]),
|
||||||
new SubSectionTile('Performance', [
|
|
||||||
new PowerTile(new Power(210)),
|
|
||||||
new AccelerationTile(new Acceleration(6.6)),
|
|
||||||
new TopSpeedTile(new TopSpeed(180)),
|
|
||||||
new DrivetrainTile(new Drivetrain('rear')),
|
|
||||||
], 'Motor and driving performance specifications'),
|
|
||||||
|
|
||||||
new SubSectionTile('Range & Efficiency', [
|
new SubSectionTile('Performance', [
|
||||||
new RangeTile(new Range(450)),
|
new PowerTile($drivingCharacteristics->power),
|
||||||
new BatteryTile(new Battery(new Energy(77.0), new Energy(82.0))),
|
new AccelerationTile($drivingCharacteristics->acceleration),
|
||||||
new ConsumptionTile(new Consumption(new Energy(171))),
|
new TopSpeedTile($drivingCharacteristics->topSpeed),
|
||||||
new ChargingTile(new ChargingSpeed(new Power(175), new Power(11))),
|
new DrivetrainTile(new Drivetrain('rear')),
|
||||||
], 'Battery capacity, range, and charging capabilities'),
|
new ConsumptionTile($drivingCharacteristics->consumption),
|
||||||
|
], 'Individual performance metrics'),
|
||||||
|
|
||||||
|
new SubSectionTile('Reichweite', [
|
||||||
|
new RangeTile($wltpRange->range),
|
||||||
|
new RangeComparisonTile($skodaElroq85->rangeProperties),
|
||||||
|
new RealRangeTile($realRangeTests),
|
||||||
|
], 'Range data from different sources'),
|
||||||
|
|
||||||
|
new SubSectionTile('Batterie', [
|
||||||
|
new BatteryTile($skodaElroq85->battery),
|
||||||
|
new BatteryDetailsTile($skodaElroq85->battery),
|
||||||
|
], 'Battery capacity and technology'),
|
||||||
|
|
||||||
|
new SubSectionTile('Laden', [
|
||||||
|
new ChargeTimeTile($chargingProperties->chargeTimeProperties),
|
||||||
|
new ChargingConnectivityTile($chargingProperties->chargingConnectivity),
|
||||||
|
new ChargeCurveTile($chargingProperties->chargeCurve),
|
||||||
|
], 'Charging capabilities and compatibility'),
|
||||||
]),
|
]),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
12
src/Domain/Search/Tiles/BatteryDetailsTile.php
Normal file
12
src/Domain/Search/Tiles/BatteryDetailsTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\Battery\BatteryProperties;
|
||||||
|
|
||||||
|
final readonly class BatteryDetailsTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public BatteryProperties $batteryProperties,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Domain\Search\Tiles;
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
use App\Domain\Model\Value\Battery;
|
use App\Domain\Model\Battery\BatteryProperties;
|
||||||
|
|
||||||
class BatteryTile
|
class BatteryTile
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly Battery $battery,
|
public readonly BatteryProperties $battery,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
12
src/Domain/Search/Tiles/ChargeCurveTile.php
Normal file
12
src/Domain/Search/Tiles/ChargeCurveTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\Charging\ChargeCurve;
|
||||||
|
|
||||||
|
final readonly class ChargeCurveTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ChargeCurve $chargeCurve,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
12
src/Domain/Search/Tiles/ChargeTimeTile.php
Normal file
12
src/Domain/Search/Tiles/ChargeTimeTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\Charging\ChargeTimeProperties;
|
||||||
|
|
||||||
|
final readonly class ChargeTimeTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ChargeTimeProperties $chargeTimeProperties,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
12
src/Domain/Search/Tiles/ChargingConnectivityTile.php
Normal file
12
src/Domain/Search/Tiles/ChargingConnectivityTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\Charging\ChargingConnectivity;
|
||||||
|
|
||||||
|
final readonly class ChargingConnectivityTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ChargingConnectivity $chargingConnectivity,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
12
src/Domain/Search/Tiles/PerformanceOverviewTile.php
Normal file
12
src/Domain/Search/Tiles/PerformanceOverviewTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\DrivingCharacteristics;
|
||||||
|
|
||||||
|
final readonly class PerformanceOverviewTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public DrivingCharacteristics $drivingCharacteristics,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
13
src/Domain/Search/Tiles/ProductionPeriodTile.php
Normal file
13
src/Domain/Search/Tiles/ProductionPeriodTile.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\Value\Date;
|
||||||
|
|
||||||
|
final readonly class ProductionPeriodTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public ?Date $productionBegin = null,
|
||||||
|
public ?Date $productionEnd = null,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
12
src/Domain/Search/Tiles/RangeComparisonTile.php
Normal file
12
src/Domain/Search/Tiles/RangeComparisonTile.php
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
use App\Domain\Model\RangeProperties;
|
||||||
|
|
||||||
|
final readonly class RangeComparisonTile
|
||||||
|
{
|
||||||
|
public function __construct(
|
||||||
|
public RangeProperties $rangeProperties,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
13
src/Domain/Search/Tiles/RealRangeTile.php
Normal file
13
src/Domain/Search/Tiles/RealRangeTile.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
|
final readonly class RealRangeTile
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param \App\Domain\Model\Range\RealRange[] $realRangeTests
|
||||||
|
*/
|
||||||
|
public function __construct(
|
||||||
|
public array $realRangeTests,
|
||||||
|
) {}
|
||||||
|
}
|
||||||
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Domain\Search\Tiles;
|
namespace App\Domain\Search\Tiles;
|
||||||
|
|
||||||
use App\Domain\Model\Value\TopSpeed;
|
use App\Domain\Model\Value\Speed;
|
||||||
|
|
||||||
class TopSpeedTile
|
class TopSpeedTile
|
||||||
{
|
{
|
||||||
public function __construct(
|
public function __construct(
|
||||||
public readonly TopSpeed $topSpeed,
|
public readonly Speed $topSpeed,
|
||||||
) {}
|
) {}
|
||||||
}
|
}
|
||||||
21
templates/result/tiles/batterydetails.html.twig
Normal file
21
templates/result/tiles/batterydetails.html.twig
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<div class="tile battery-details-tile">
|
||||||
|
<div class="tile-title">Zellchemie</div>
|
||||||
|
<div class="battery-info" style="margin-top: 12px; text-align: center;">
|
||||||
|
<!-- Chemistry Badge -->
|
||||||
|
{% set chemistryColor = tile.batteryProperties.cellChemistry.value == 'LFP' ? '#28a745' : (tile.batteryProperties.cellChemistry.value == 'NMC' ? '#007acc' : '#6f42c1') %}
|
||||||
|
<div style="margin-bottom: 12px;">
|
||||||
|
<span style="background: {{ chemistryColor }}; color: white; padding: 6px 12px; border-radius: 12px; font-size: 14px; font-weight: bold;">
|
||||||
|
{{ tile.batteryProperties.cellChemistry.value }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Manufacturer & Model -->
|
||||||
|
{% if tile.batteryProperties.manufacturer != 'Tesla' or tile.batteryProperties.model != '4680' %}
|
||||||
|
<div style="font-size: 12px; color: #666;">
|
||||||
|
{{ tile.batteryProperties.manufacturer }}<br>
|
||||||
|
{{ tile.batteryProperties.model }}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">Batterietechnologie</small>
|
||||||
|
</div>
|
||||||
74
templates/result/tiles/chargecurve.html.twig
Normal file
74
templates/result/tiles/chargecurve.html.twig
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<div class="tile charge-curve-tile" style="grid-column: span 3; grid-row: span 2;">
|
||||||
|
<div class="tile-title">Ladekurve</div>
|
||||||
|
<div class="charge-curve-container" style="position: relative; height: 120px; margin-top: 10px;">
|
||||||
|
<svg width="100%" height="100%" viewBox="0 0 300 100" style="overflow: visible;">
|
||||||
|
<!-- Grid lines -->
|
||||||
|
{% for i in 0..10 %}
|
||||||
|
<line x1="{{ i * 30 }}" y1="0" x2="{{ i * 30 }}" y2="100"
|
||||||
|
stroke="#f0f0f0" stroke-width="0.5"/>
|
||||||
|
{% endfor %}
|
||||||
|
{% for i in 0..5 %}
|
||||||
|
<line x1="0" y1="{{ i * 20 }}" x2="300" y2="{{ i * 20 }}"
|
||||||
|
stroke="#f0f0f0" stroke-width="0.5"/>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
|
<!-- Charge curve path -->
|
||||||
|
<path d="M0,{{ 100 - ((tile.chargeCurve.averagePowerSoc0 ? tile.chargeCurve.averagePowerSoc0.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L30,{{ 100 - ((tile.chargeCurve.averagePowerSoc10 ? tile.chargeCurve.averagePowerSoc10.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L60,{{ 100 - ((tile.chargeCurve.averagePowerSoc20 ? tile.chargeCurve.averagePowerSoc20.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L90,{{ 100 - ((tile.chargeCurve.averagePowerSoc30 ? tile.chargeCurve.averagePowerSoc30.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L120,{{ 100 - ((tile.chargeCurve.averagePowerSoc40 ? tile.chargeCurve.averagePowerSoc40.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L150,{{ 100 - ((tile.chargeCurve.averagePowerSoc50 ? tile.chargeCurve.averagePowerSoc50.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L180,{{ 100 - ((tile.chargeCurve.averagePowerSoc60 ? tile.chargeCurve.averagePowerSoc60.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L210,{{ 100 - ((tile.chargeCurve.averagePowerSoc70 ? tile.chargeCurve.averagePowerSoc70.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L240,{{ 100 - ((tile.chargeCurve.averagePowerSoc80 ? tile.chargeCurve.averagePowerSoc80.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L270,{{ 100 - ((tile.chargeCurve.averagePowerSoc90 ? tile.chargeCurve.averagePowerSoc90.kilowatts : 0) / 200 * 80) }}
|
||||||
|
L300,{{ 100 - ((tile.chargeCurve.averagePowerSoc100 ? tile.chargeCurve.averagePowerSoc100.kilowatts : 0) / 200 * 80) }}"
|
||||||
|
fill="none" stroke="#007acc" stroke-width="2" opacity="0.8"/>
|
||||||
|
|
||||||
|
<!-- Peak power indicator -->
|
||||||
|
{% set maxPower = 0 %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc0 and tile.chargeCurve.averagePowerSoc0.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc0.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc10 and tile.chargeCurve.averagePowerSoc10.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc10.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc20 and tile.chargeCurve.averagePowerSoc20.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc20.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc30 and tile.chargeCurve.averagePowerSoc30.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc30.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc40 and tile.chargeCurve.averagePowerSoc40.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc40.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc50 and tile.chargeCurve.averagePowerSoc50.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc50.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc60 and tile.chargeCurve.averagePowerSoc60.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc60.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc70 and tile.chargeCurve.averagePowerSoc70.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc70.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc80 and tile.chargeCurve.averagePowerSoc80.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc80.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc90 and tile.chargeCurve.averagePowerSoc90.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc90.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargeCurve.averagePowerSoc100 and tile.chargeCurve.averagePowerSoc100.kilowatts > maxPower %}
|
||||||
|
{% set maxPower = tile.chargeCurve.averagePowerSoc100.kilowatts %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if maxPower > 0 %}
|
||||||
|
<text x="5" y="15" font-size="10" fill="#666">{{ maxPower|round }}kW</text>
|
||||||
|
{% endif %}
|
||||||
|
<text x="5" y="95" font-size="10" fill="#666">0kW</text>
|
||||||
|
<text x="5" y="105" font-size="8" fill="#999">0%</text>
|
||||||
|
<text x="285" y="105" font-size="8" fill="#999">100%</text>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
<small style="color: #666; font-size: 11px;">Ladeleistung über Batteriestand (SOC)</small>
|
||||||
|
</div>
|
||||||
19
templates/result/tiles/chargetime.html.twig
Normal file
19
templates/result/tiles/chargetime.html.twig
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<div class="tile charge-time-tile">
|
||||||
|
<div class="tile-title">Schnellladen</div>
|
||||||
|
<div class="charge-times" style="margin-top: 12px;">
|
||||||
|
{% if tile.chargeTimeProperties.minutesFrom10To80 %}
|
||||||
|
<div style="text-align: center; margin-bottom: 12px;">
|
||||||
|
<div style="font-weight: bold; font-size: 24px; color: #007acc;">{{ tile.chargeTimeProperties.minutesFrom10To80 }}</div>
|
||||||
|
<small style="color: #666; font-weight: 600;">Minuten 10-80%</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if tile.chargeTimeProperties.minutesFrom20To80 %}
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-weight: bold; font-size: 18px; color: #6c757d;">{{ tile.chargeTimeProperties.minutesFrom20To80 }}</div>
|
||||||
|
<small style="color: #666;">Minuten 20-80%</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">DC Laden</small>
|
||||||
|
</div>
|
||||||
35
templates/result/tiles/chargingconnectivity.html.twig
Normal file
35
templates/result/tiles/chargingconnectivity.html.twig
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<div class="tile charging-connectivity-tile">
|
||||||
|
<div class="tile-title">Ladekompatibilität</div>
|
||||||
|
<div class="connectivity-features" style="margin-top: 8px;">
|
||||||
|
<!-- Voltage Support -->
|
||||||
|
<div style="display: flex; gap: 6px; margin-bottom: 6px;">
|
||||||
|
{% if tile.chargingConnectivity.is400v %}
|
||||||
|
<span style="background: #28a745; color: white; padding: 2px 6px; border-radius: 12px; font-size: 10px; font-weight: bold;">400V</span>
|
||||||
|
{% endif %}
|
||||||
|
{% if tile.chargingConnectivity.is800v %}
|
||||||
|
<span style="background: #007acc; color: white; padding: 2px 6px; border-radius: 12px; font-size: 10px; font-weight: bold;">800V</span>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Plug & Charge -->
|
||||||
|
{% if tile.chargingConnectivity.plugAndCharge %}
|
||||||
|
<div style="margin-bottom: 6px;">
|
||||||
|
<span style="background: rgba(40, 167, 69, 0.1); color: #28a745; padding: 3px 8px; border-radius: 4px; font-size: 11px;">
|
||||||
|
⚡ Plug & Charge
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Connector Types -->
|
||||||
|
{% if tile.chargingConnectivity.connectorTypes|length > 0 %}
|
||||||
|
<div class="connector-types" style="display: flex; gap: 4px; flex-wrap: wrap;">
|
||||||
|
{% for connector in tile.chargingConnectivity.connectorTypes %}
|
||||||
|
<span style="background: rgba(108,117,125,0.1); color: #6c757d; padding: 2px 6px; border-radius: 8px; font-size: 10px; font-weight: 500;">
|
||||||
|
{{ connector.value }}
|
||||||
|
</span>
|
||||||
|
{% endfor %}
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">Ladeschnittstellen & Features</small>
|
||||||
|
</div>
|
||||||
40
templates/result/tiles/performanceoverview.html.twig
Normal file
40
templates/result/tiles/performanceoverview.html.twig
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
<div class="tile performance-overview-tile" style="grid-column: span 3; grid-row: span 2;">
|
||||||
|
<div class="tile-title">Performance-Übersicht</div>
|
||||||
|
<div class="performance-grid" style="display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; margin-top: 12px; height: calc(100% - 40px);">
|
||||||
|
<!-- Power -->
|
||||||
|
{% if tile.drivingCharacteristics.power %}
|
||||||
|
<div style="text-align: center; padding: 12px; background: linear-gradient(135deg, rgba(0,122,204,0.1), rgba(0,122,204,0.05)); border-radius: 8px; display: flex; flex-direction: column; justify-content: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #007acc; margin-bottom: 4px;">{{ tile.drivingCharacteristics.power.kilowatts|round }}</div>
|
||||||
|
<div style="font-size: 12px; color: #666; margin-bottom: 2px;">kW</div>
|
||||||
|
<small style="color: #666; font-weight: 600;">Leistung</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Top Speed -->
|
||||||
|
{% if tile.drivingCharacteristics.topSpeed %}
|
||||||
|
<div style="text-align: center; padding: 12px; background: linear-gradient(135deg, rgba(255,193,7,0.1), rgba(255,193,7,0.05)); border-radius: 8px; display: flex; flex-direction: column; justify-content: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #ffc107; margin-bottom: 4px;">{{ tile.drivingCharacteristics.topSpeed.kmh }}</div>
|
||||||
|
<div style="font-size: 12px; color: #666; margin-bottom: 2px;">km/h</div>
|
||||||
|
<small style="color: #666; font-weight: 600;">Höchstgeschwindigkeit</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Acceleration -->
|
||||||
|
{% if tile.drivingCharacteristics.acceleration %}
|
||||||
|
<div style="text-align: center; padding: 12px; background: linear-gradient(135deg, rgba(40,167,69,0.1), rgba(40,167,69,0.05)); border-radius: 8px; display: flex; flex-direction: column; justify-content: center;">
|
||||||
|
<div style="font-size: 24px; font-weight: bold; color: #28a745; margin-bottom: 4px;">{{ tile.drivingCharacteristics.acceleration.secondsFrom0To100 }}</div>
|
||||||
|
<div style="font-size: 12px; color: #666; margin-bottom: 2px;">sec</div>
|
||||||
|
<small style="color: #666; font-weight: 600;">0-100 km/h</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Consumption -->
|
||||||
|
{% if tile.drivingCharacteristics.consumption %}
|
||||||
|
<div style="text-align: center; padding: 12px; background: linear-gradient(135deg, rgba(111,66,193,0.1), rgba(111,66,193,0.05)); border-radius: 8px; display: flex; flex-direction: column; justify-content: center;">
|
||||||
|
<div style="font-size: 20px; font-weight: bold; color: #6f42c1; margin-bottom: 4px;">{{ tile.drivingCharacteristics.consumption.energyPerKm.kwh|round(1) }}</div>
|
||||||
|
<div style="font-size: 12px; color: #666; margin-bottom: 2px;">kWh/100km</div>
|
||||||
|
<small style="color: #666; font-weight: 600;">Verbrauch</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
38
templates/result/tiles/productionperiod.html.twig
Normal file
38
templates/result/tiles/productionperiod.html.twig
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
<div class="tile production-period-tile">
|
||||||
|
<div class="tile-title">Produktionszeitraum</div>
|
||||||
|
<div class="production-timeline" style="margin-top: 8px;">
|
||||||
|
{% if tile.productionBegin or tile.productionEnd %}
|
||||||
|
<div style="display: flex; align-items: center; gap: 8px;">
|
||||||
|
{% if tile.productionBegin %}
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-weight: bold; font-size: 16px; color: #28a745;">{{ tile.productionBegin.year }}</div>
|
||||||
|
<small style="color: #666;">Start</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if tile.productionBegin and tile.productionEnd %}
|
||||||
|
<div style="flex: 1; height: 2px; background: linear-gradient(to right, #28a745, #dc3545); margin: 0 4px;"></div>
|
||||||
|
{% elseif tile.productionBegin %}
|
||||||
|
<div style="flex: 1; height: 2px; background: linear-gradient(to right, #28a745, #007acc); margin: 0 4px;"></div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if tile.productionEnd %}
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-weight: bold; font-size: 16px; color: #dc3545;">{{ tile.productionEnd.year }}</div>
|
||||||
|
<small style="color: #666;">Ende</small>
|
||||||
|
</div>
|
||||||
|
{% elseif tile.productionBegin %}
|
||||||
|
<div style="text-align: center;">
|
||||||
|
<div style="font-weight: bold; font-size: 16px; color: #007acc;">laufend</div>
|
||||||
|
<small style="color: #666;">aktuell</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
{% else %}
|
||||||
|
<div style="text-align: center; color: #666; font-style: italic;">
|
||||||
|
Zeitraum unbekannt
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">Verfügbarkeit</small>
|
||||||
|
</div>
|
||||||
28
templates/result/tiles/rangecomparison.html.twig
Normal file
28
templates/result/tiles/rangecomparison.html.twig
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
<div class="tile range-comparison-tile">
|
||||||
|
<div class="tile-title">Reichweiten-Vergleich</div>
|
||||||
|
<div class="range-comparison" style="margin-top: 8px;">
|
||||||
|
<!-- WLTP Range -->
|
||||||
|
{% if tile.rangeProperties.wltp %}
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 6px 10px; background: rgba(0,122,204,0.1); border-radius: 6px;">
|
||||||
|
<span style="font-weight: 600; color: #007acc;">WLTP</span>
|
||||||
|
<span style="font-weight: bold; font-size: 18px;">{{ tile.rangeProperties.wltp.range.kilometers }} km</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- NEFZ Range -->
|
||||||
|
{% if tile.rangeProperties.nefz %}
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px; padding: 6px 10px; background: rgba(108,117,125,0.1); border-radius: 6px;">
|
||||||
|
<span style="font-weight: 600; color: #6c757d;">NEFZ</span>
|
||||||
|
<span style="font-weight: bold; font-size: 18px;">{{ tile.rangeProperties.nefz.range.kilometers }} km</span>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
<!-- Real Tests Summary -->
|
||||||
|
{% if tile.rangeProperties.realRangeTests|length > 0 %}
|
||||||
|
<div style="margin-top: 10px; padding: 4px 6px; background: rgba(40,167,69,0.05); border-radius: 4px; text-align: center;">
|
||||||
|
<small style="color: #28a745; font-weight: 600;">{{ tile.rangeProperties.realRangeTests|length }} Real-Tests verfügbar</small>
|
||||||
|
</div>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">Offizielle Testverfahren</small>
|
||||||
|
</div>
|
||||||
18
templates/result/tiles/realrange.html.twig
Normal file
18
templates/result/tiles/realrange.html.twig
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<div class="tile real-range-tile">
|
||||||
|
<div class="tile-title">Praxis-Tests</div>
|
||||||
|
<div class="real-tests" style="margin-top: 8px;">
|
||||||
|
{% for realTest in tile.realRangeTests|slice(0, 3) %}
|
||||||
|
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 6px; padding: 4px 8px; background: rgba(40,167,69,0.1); border-radius: 4px; font-size: 13px;">
|
||||||
|
<span style="color: #28a745;">
|
||||||
|
{% if realTest.season %}{{ realTest.season.value }}{% endif %}
|
||||||
|
{% if realTest.averageSpeed %} • {{ realTest.averageSpeed }}{% endif %}
|
||||||
|
</span>
|
||||||
|
<span style="font-weight: bold;">{{ realTest.range.kilometers }} km</span>
|
||||||
|
</div>
|
||||||
|
{% endfor %}
|
||||||
|
{% if tile.realRangeTests|length > 3 %}
|
||||||
|
<small style="color: #666; font-style: italic; text-align: center; display: block;">+{{ tile.realRangeTests|length - 3 }} weitere</small>
|
||||||
|
{% endif %}
|
||||||
|
</div>
|
||||||
|
<small style="color: #666;">Real-World Reichweite</small>
|
||||||
|
</div>
|
||||||
Loading…
x
Reference in New Issue
Block a user