Adsasd
All checks were successful
Deploy / deploy (push) Successful in 1m5s

This commit is contained in:
2026-07-28 22:30:32 +02:00
parent aa86001760
commit 0e73147886
9 changed files with 853 additions and 11 deletions

View File

@@ -66,6 +66,13 @@ final class AvatarManager
'fixed_colors' => [],
'color_controls' => [],
];
$result['croodles'] = [
'key' => 'croodles',
'label' => Croodles::label(),
'class' => Croodles::class,
'fixed_colors' => [],
'color_controls' => [],
];
}
return $result;
@@ -222,10 +229,24 @@ final class AvatarManager
];
}
$colors = [];
foreach ($styleClass::colorDefinitions() as $field => $definition) {
$colors[$field] = [
'field' => $field,
'label' => (string)($definition['label'] ?? $field),
'value' => (string)($styleConfig[$field] ?? ''),
'default' => (string)($definition['default'] ?? '#c4a484'),
'fill' => (string)($styleConfig[$field . 'Fill'] ?? ''),
'fill_stops' => (string)($styleConfig[$field . 'FillStops'] ?? ''),
'angle' => (string)($styleConfig[$field . 'Angle'] ?? ''),
];
}
$styles[$meta['key']] = [
'key' => $meta['key'],
'label' => $meta['label'],
'components' => $components,
'colors' => $colors,
];
}

259
src/App/Avatar/Croodles.php Normal file
View File

@@ -0,0 +1,259 @@
<?php
declare(strict_types=1);
namespace App\Avatar;
final class Croodles
{
public static function key(): string
{
return 'croodles';
}
public static function label(): string
{
return 'Croodles';
}
public static function defaultSeed(): string
{
return 'papa-kind-treff';
}
public static function defaultConfig(): array
{
return array_merge([
'beardVariant' => '',
'eyesVariant' => '',
'headVariant' => '',
'mouthVariant' => '',
'mustacheVariant' => '',
'noseVariant' => '',
'topVariant' => '',
'baseColor' => '',
'eyepatchColor' => '',
'glassesColor' => '',
'topColor' => '',
'backgroundColor' => '',
], self::colorCompanionDefaults());
}
public static function options(): array
{
return [
'beardVariant' => ['' => 'Keine'] + self::variantOptions(5),
'eyesVariant' => ['' => 'Keine'] + self::variantOptions(16),
'headVariant' => ['' => 'Keine'] + self::variantOptions(8),
'mouthVariant' => ['' => 'Keine'] + self::variantOptions(18),
'mustacheVariant' => ['' => 'Keine'] + self::variantOptions(4),
'noseVariant' => ['' => 'Keine'] + self::variantOptions(9),
'topVariant' => ['' => 'Keine'] + self::variantOptions(29),
];
}
public static function componentDefinitions(): array
{
return [
'headVariant' => ['label' => 'Kopf'],
'eyesVariant' => ['label' => 'Augen'],
'noseVariant' => ['label' => 'Nase'],
'mouthVariant' => ['label' => 'Mund'],
'topVariant' => ['label' => 'Top'],
'beardVariant' => ['label' => 'Bart'],
'mustacheVariant' => ['label' => 'Schnurrbart'],
];
}
public static function colorDefinitions(): array
{
return [
'baseColor' => ['label' => 'Basisfarbe', 'default' => '#e7ba9a'],
'eyepatchColor' => ['label' => 'Augenklappe', 'default' => '#283341'],
'glassesColor' => ['label' => 'Brille', 'default' => '#283341'],
'topColor' => ['label' => 'Top-Farbe', 'default' => '#4f6ea8'],
'backgroundColor' => ['label' => 'Hintergrund', 'default' => '#f2eadf'],
];
}
public static function normalizeSeed(string $seed): string
{
$seed = strtolower(trim($seed));
$seed = preg_replace('/[^a-z0-9]+/', '-', $seed) ?: '';
$seed = trim($seed, '-');
if ($seed === '') {
$seed = self::defaultSeed();
}
return substr($seed, 0, 100);
}
public static function normalizeConfig(array $input): array
{
$defaults = self::defaultConfig();
$normalized = [];
foreach ($defaults as $key => $defaultValue) {
if (array_key_exists($key, self::colorDefinitions())) {
$normalized[$key] = self::normalizeColor((string)($input[$key] ?? $defaultValue));
continue;
}
if (str_ends_with($key, 'Fill')) {
$normalized[$key] = self::normalizeFill((string)($input[$key] ?? $defaultValue));
continue;
}
if (str_ends_with($key, 'FillStops')) {
$normalized[$key] = self::normalizeFillStops($input[$key] ?? $defaultValue);
continue;
}
if (str_ends_with($key, 'Angle')) {
$normalized[$key] = self::normalizeAngle($input[$key] ?? $defaultValue);
continue;
}
$normalized[$key] = self::normalizeVariant((string)($input[$key] ?? $defaultValue));
}
return $normalized;
}
public static function buildQuery(string $seed, array $config): array
{
$config = self::normalizeConfig($config);
$query = ['seed' => self::normalizeSeed($seed)];
$componentFields = array_keys(self::componentDefinitions());
foreach ($componentFields as $field) {
$probability = preg_replace('/Variant$/', 'Probability', $field);
if ($config[$field] === '') {
$query[$probability] = '0';
continue;
}
$query[$field] = $config[$field];
$query[$probability] = '100';
}
foreach (array_keys(self::colorDefinitions()) as $field) {
if ($config[$field] !== '') {
$query[$field] = $config[$field];
foreach (self::colorCompanionFields($field) as $companionField) {
if ($config[$companionField] !== '') {
$query[$companionField] = $config[$companionField];
}
}
}
}
return $query;
}
public static function queryToConfig(array $query): array
{
$config = self::defaultConfig();
foreach (array_keys(self::componentDefinitions()) as $field) {
$config[$field] = self::normalizeVariant((string)($query[$field] ?? ''));
$probability = (int)($query[preg_replace('/Variant$/', 'Probability', $field)] ?? 100);
if ($probability <= 0) {
$config[$field] = '';
}
}
foreach (array_keys(self::colorDefinitions()) as $field) {
$config[$field] = self::normalizeColor((string)($query[$field] ?? ''));
foreach (self::colorCompanionFields($field) as $companionField) {
$config[$companionField] = (string)($query[$companionField] ?? '');
}
}
return self::normalizeConfig($config);
}
public static function fallbackSvg(string $seed, string $label = 'Avatar'): string
{
return Lorelei::fallbackSvg($seed, $label);
}
private static function normalizeVariant(string $value): string
{
$value = strtolower(trim($value));
if ($value === '') {
return '';
}
return preg_match('/^variant\d{2}$/', $value) === 1 ? $value : '';
}
private static function normalizeColor(string $value): string
{
$value = strtolower(trim($value));
if ($value === '') {
return '';
}
return preg_match('/^#[0-9a-f]{6}$/', $value) === 1 ? $value : '';
}
private static function normalizeFill(string $value): string
{
$value = strtolower(trim($value));
if ($value === '') {
return '';
}
return in_array($value, ['solid', 'linear', 'radial'], true) ? $value : '';
}
private static function normalizeFillStops(mixed $value): string
{
if ($value === '' || $value === null) {
return '';
}
$number = max(2, min(8, (int)$value));
return (string)$number;
}
private static function normalizeAngle(mixed $value): string
{
if ($value === '' || $value === null) {
return '';
}
$number = max(-360, min(360, (int)$value));
return (string)$number;
}
private static function colorCompanionDefaults(): array
{
$defaults = [];
foreach (array_keys(self::colorDefinitions()) as $field) {
foreach (self::colorCompanionFields($field) as $companionField) {
$defaults[$companionField] = '';
}
}
return $defaults;
}
private static function colorCompanionFields(string $field): array
{
return [
$field . 'Fill',
$field . 'FillStops',
$field . 'Angle',
];
}
private static function variantOptions(int $count): array
{
$options = [];
for ($index = 1; $index <= $count; $index++) {
$key = sprintf('variant%02d', $index);
$options[$key] = 'Variante ' . $index;
}
return $options;
}
}

View File

@@ -22,7 +22,7 @@ final class Lorelei
public static function defaultConfig(): array
{
return [
return array_merge([
'eyesVariant' => '',
'eyebrowsVariant' => '',
'mouthVariant' => '',
@@ -30,7 +30,18 @@ final class Lorelei
'hairVariant' => '',
'beardVariant' => '',
'earringsVariant' => '',
];
'earringsColor' => '',
'eyebrowsColor' => '',
'eyesColor' => '',
'frecklesColor' => '',
'glassesColor' => '',
'hairColor' => '',
'hairAccessoriesColor' => '',
'mouthColor' => '',
'noseColor' => '',
'skinColor' => '',
'backgroundColor' => '',
], self::colorCompanionDefaults());
}
public static function options(): array
@@ -59,6 +70,23 @@ final class Lorelei
];
}
public static function colorDefinitions(): array
{
return [
'earringsColor' => ['label' => 'Ohrringe', 'default' => '#d6b36b'],
'eyebrowsColor' => ['label' => 'Augenbrauen', 'default' => '#4a3227'],
'eyesColor' => ['label' => 'Augen', 'default' => '#2a2522'],
'frecklesColor' => ['label' => 'Sommersprossen', 'default' => '#b67852'],
'glassesColor' => ['label' => 'Brille', 'default' => '#26313f'],
'hairColor' => ['label' => 'Haare', 'default' => '#4b3128'],
'hairAccessoriesColor' => ['label' => 'Haar-Accessoires', 'default' => '#b96f54'],
'mouthColor' => ['label' => 'Mund', 'default' => '#9f5a56'],
'noseColor' => ['label' => 'Nase', 'default' => '#a56f58'],
'skinColor' => ['label' => 'Haut', 'default' => '#e7ba9a'],
'backgroundColor' => ['label' => 'Hintergrund', 'default' => '#f5efe5'],
];
}
public static function legacyColumnsFromConfig(string $seed, array $config): array
{
$config = self::normalizeConfig($config);
@@ -107,6 +135,22 @@ final class Lorelei
$normalized = [];
foreach ($defaults as $key => $defaultValue) {
if (array_key_exists($key, self::colorDefinitions())) {
$normalized[$key] = self::normalizeColor((string)($input[$key] ?? $defaultValue));
continue;
}
if (str_ends_with($key, 'Fill')) {
$normalized[$key] = self::normalizeFill((string)($input[$key] ?? $defaultValue));
continue;
}
if (str_ends_with($key, 'FillStops')) {
$normalized[$key] = self::normalizeFillStops($input[$key] ?? $defaultValue);
continue;
}
if (str_ends_with($key, 'Angle')) {
$normalized[$key] = self::normalizeAngle($input[$key] ?? $defaultValue);
continue;
}
$normalized[$key] = self::normalizeVariant((string)($input[$key] ?? $defaultValue));
}
@@ -149,6 +193,17 @@ final class Lorelei
$query[$params['probability']] = '100';
}
foreach (array_keys(self::colorDefinitions()) as $field) {
if ($config[$field] !== '') {
$query[$field] = $config[$field];
foreach (self::colorCompanionFields($field) as $companionField) {
if ($config[$companionField] !== '') {
$query[$companionField] = $config[$companionField];
}
}
}
}
return $query;
}
@@ -182,6 +237,13 @@ final class Lorelei
$config['hairVariant'] = '';
}
foreach (array_keys(self::colorDefinitions()) as $field) {
$config[$field] = self::normalizeColor((string)($query[$field] ?? ''));
foreach (self::colorCompanionFields($field) as $companionField) {
$config[$companionField] = (string)($query[$companionField] ?? '');
}
}
return self::normalizeConfig($config);
}
@@ -240,4 +302,65 @@ final class Lorelei
return preg_match('/^(variant\d{2}|happy\d{2}|sad\d{2})$/', $value) === 1 ? $value : '';
}
private static function normalizeColor(string $value): string
{
$value = strtolower(trim($value));
if ($value === '') {
return '';
}
return preg_match('/^#[0-9a-f]{6}$/', $value) === 1 ? $value : '';
}
private static function normalizeFill(string $value): string
{
$value = strtolower(trim($value));
if ($value === '') {
return '';
}
return in_array($value, ['solid', 'linear', 'radial'], true) ? $value : '';
}
private static function normalizeFillStops(mixed $value): string
{
if ($value === '' || $value === null) {
return '';
}
$number = max(2, min(8, (int)$value));
return (string)$number;
}
private static function normalizeAngle(mixed $value): string
{
if ($value === '' || $value === null) {
return '';
}
$number = max(-360, min(360, (int)$value));
return (string)$number;
}
private static function colorCompanionDefaults(): array
{
$defaults = [];
foreach (array_keys(self::colorDefinitions()) as $field) {
foreach (self::colorCompanionFields($field) as $companionField) {
$defaults[$companionField] = '';
}
}
return $defaults;
}
private static function colorCompanionFields(string $field): array
{
return [
$field . 'Fill',
$field . 'FillStops',
$field . 'Angle',
];
}
}