TenantAtlas/app/Support/Ui/OperatorExplanation/OperatorExplanationPattern.php
2026-03-24 12:23:07 +01:00

136 lines
5.0 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Support\Ui\OperatorExplanation;
use App\Support\Badges\BadgeCatalog;
use App\Support\Badges\BadgeDomain;
use InvalidArgumentException;
final readonly class OperatorExplanationPattern
{
/**
* @param array<int, CountDescriptor> $countDescriptors
*/
public function __construct(
public ExplanationFamily $family,
public string $headline,
public string $executionOutcome,
public string $executionOutcomeLabel,
public string $evaluationResult,
public TrustworthinessLevel $trustworthinessLevel,
public string $reliabilityStatement,
public ?string $coverageStatement,
public ?string $dominantCauseCode,
public ?string $dominantCauseLabel,
public ?string $dominantCauseExplanation,
public string $nextActionCategory,
public string $nextActionText,
public array $countDescriptors = [],
public bool $diagnosticsAvailable = false,
public ?string $diagnosticsSummary = null,
) {
if (trim($this->headline) === '') {
throw new InvalidArgumentException('Operator explanation patterns require a headline.');
}
if (trim($this->executionOutcome) === '' || trim($this->executionOutcomeLabel) === '') {
throw new InvalidArgumentException('Operator explanation patterns require an execution outcome and label.');
}
if (trim($this->evaluationResult) === '') {
throw new InvalidArgumentException('Operator explanation patterns require an evaluation result state.');
}
if (trim($this->reliabilityStatement) === '') {
throw new InvalidArgumentException('Operator explanation patterns require a reliability statement.');
}
if (trim($this->nextActionCategory) === '' || trim($this->nextActionText) === '') {
throw new InvalidArgumentException('Operator explanation patterns require a next action category and text.');
}
foreach ($this->countDescriptors as $descriptor) {
if (! $descriptor instanceof CountDescriptor) {
throw new InvalidArgumentException('Operator explanation count descriptors must contain CountDescriptor instances.');
}
}
}
public function evaluationResultLabel(): string
{
return BadgeCatalog::spec(BadgeDomain::OperatorExplanationEvaluationResult, $this->evaluationResult)->label;
}
public function trustworthinessLabel(): string
{
return BadgeCatalog::spec(BadgeDomain::OperatorExplanationTrustworthiness, $this->trustworthinessLevel)->label;
}
/**
* @return array{
* family: string,
* headline: string,
* executionOutcome: string,
* executionOutcomeLabel: string,
* evaluationResult: string,
* evaluationResultLabel: string,
* trustworthinessLevel: string,
* reliabilityLevel: string,
* trustworthinessLabel: string,
* reliabilityStatement: string,
* coverageStatement: ?string,
* dominantCause: array{
* code: ?string,
* label: ?string,
* explanation: ?string
* },
* nextAction: array{
* category: string,
* text: string
* },
* countDescriptors: array<int, array{
* label: string,
* value: int,
* role: string,
* qualifier: ?string,
* visibilityTier: string
* }>,
* diagnosticsAvailable: bool,
* diagnosticsSummary: ?string
* }
*/
public function toArray(): array
{
return [
'family' => $this->family->value,
'headline' => $this->headline,
'executionOutcome' => $this->executionOutcome,
'executionOutcomeLabel' => $this->executionOutcomeLabel,
'evaluationResult' => $this->evaluationResult,
'evaluationResultLabel' => $this->evaluationResultLabel(),
'trustworthinessLevel' => $this->trustworthinessLevel->value,
'reliabilityLevel' => $this->trustworthinessLevel->value,
'trustworthinessLabel' => $this->trustworthinessLabel(),
'reliabilityStatement' => $this->reliabilityStatement,
'coverageStatement' => $this->coverageStatement,
'dominantCause' => [
'code' => $this->dominantCauseCode,
'label' => $this->dominantCauseLabel,
'explanation' => $this->dominantCauseExplanation,
],
'nextAction' => [
'category' => $this->nextActionCategory,
'text' => $this->nextActionText,
],
'countDescriptors' => array_map(
static fn (CountDescriptor $descriptor): array => $descriptor->toArray(),
$this->countDescriptors,
),
'diagnosticsAvailable' => $this->diagnosticsAvailable,
'diagnosticsSummary' => $this->diagnosticsSummary,
];
}
}