You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

279 lines
8.6 KiB

1 month ago
<?php
namespace App\Support;
final class SignupOptionCatalog
{
/**
* @return array<string, array{zh-CN: string, en: string}>
*/
public static function degrees(): array
{
return [
'associate' => ['zh-CN' => '大专', 'en' => 'Associate Degree'],
'bachelor' => ['zh-CN' => '本科', 'en' => "Bachelor’s Degree"],
'master' => ['zh-CN' => '硕士', 'en' => "Master’s Degree"],
'doctorate' => ['zh-CN' => '博士', 'en' => 'Doctorate'],
'other' => ['zh-CN' => '其他', 'en' => 'Other'],
];
}
/**
* @return array<string, array{zh-CN: string, en: string}>
*/
public static function locationCountries(): array
{
return [
'cn' => ['zh-CN' => '中国', 'en' => 'China'],
'overseas' => ['zh-CN' => '海外', 'en' => 'Outside China'],
];
}
/**
* @return array<string, array{zh-CN: string, en: string}>
*/
public static function eventLocations(): array
{
return [
'shanghai' => ['zh-CN' => '上海', 'en' => 'Shanghai'],
'suzhou' => ['zh-CN' => '苏州', 'en' => 'Suzhou'],
'shenzhen' => ['zh-CN' => '深圳', 'en' => 'Shenzhen'],
];
}
/**
* @return array<string, array{zh-CN: string, en: string}>
*/
public static function audiencePurposes(): array
{
return [
'networking' => ['zh-CN' => '项目交流', 'en' => 'Project Networking'],
'collaboration' => ['zh-CN' => '产业合作', 'en' => 'Industry Collaboration'],
'investment' => ['zh-CN' => '投资对接', 'en' => 'Investor Meetings'],
'study' => ['zh-CN' => '学习参访', 'en' => 'Study Visit'],
'media' => ['zh-CN' => '媒体报道', 'en' => 'Media Coverage'],
'other' => ['zh-CN' => '其他', 'en' => 'Other'],
];
}
/**
* @return array<string, string>
*/
public static function legacyMap(string $kind): array
{
return match ($kind) {
'degree' => [
'大专' => 'associate',
'本科' => 'bachelor',
'硕士' => 'master',
'博士' => 'doctorate',
'其他' => 'other',
],
'location_country' => [
'中国' => 'cn',
'海外' => 'overseas',
],
'event_location' => [
'上海' => 'shanghai',
'苏州' => 'suzhou',
'深圳' => 'shenzhen',
4 weeks ago
'上海赛区' => 'shanghai',
'苏州赛区' => 'suzhou',
'深圳赛区' => 'shenzhen',
'Shanghai' => 'shanghai',
'Suzhou' => 'suzhou',
'Shenzhen' => 'shenzhen',
1 month ago
],
'purpose', 'audience_purpose' => [
'项目交流' => 'networking',
'产业合作' => 'collaboration',
'投资对接' => 'investment',
'学习参访' => 'study',
'媒体报道' => 'media',
'其他' => 'other',
],
default => [],
};
}
public static function normalize(string $kind, ?string $raw): ?string
{
if ($raw === null) {
return null;
}
$value = trim($raw);
if ($value === '') {
return '';
}
$map = self::legacyMap($kind);
4 weeks ago
if (isset($map[$value])) {
return $map[$value];
}
$lower = mb_strtolower($value);
foreach ($map as $alias => $code) {
if (mb_strtolower((string) $alias) === $lower) {
return $code;
}
}
$catalog = self::catalogForKind($kind);
if ($catalog !== null) {
foreach ($catalog as $code => $labels) {
if (mb_strtolower($code) === $lower) {
return $code;
}
if (mb_strtolower((string) ($labels['en'] ?? '')) === $lower) {
return $code;
}
if ((string) ($labels['zh-CN'] ?? '') === $value) {
return $code;
}
}
}
return $value;
}
/**
* 同一选项的全部等价写法(编码 / 中文 / 英文),用于评审筛查等精确匹配。
*
* @return list<string>
*/
public static function aliases(string $kind, string $raw): array
{
$value = trim($raw);
$normalized = self::normalize($kind, $value);
if ($normalized === null || $normalized === '') {
return $value !== '' ? [$value] : [];
}
$out = [$normalized];
if ($value !== '') {
$out[] = $value;
}
$catalog = self::catalogForKind($kind) ?? [];
if (isset($catalog[$normalized])) {
$zh = trim((string) ($catalog[$normalized]['zh-CN'] ?? ''));
$en = trim((string) ($catalog[$normalized]['en'] ?? ''));
if ($zh !== '') {
$out[] = $zh;
if ($kind === 'event_location' && ! str_contains($zh, '赛区')) {
$out[] = $zh.'赛区';
}
}
if ($en !== '') {
$out[] = $en;
}
}
foreach (self::legacyMap($kind) as $alias => $code) {
if ($code === $normalized) {
$out[] = (string) $alias;
}
}
return array_values(array_unique(array_filter(
array_map(static fn ($v) => trim((string) $v), $out),
static fn ($v) => $v !== '',
)));
}
1 month ago
4 weeks ago
/**
* @param iterable<int|string, mixed> $values
* @return list<string>
*/
public static function expandAliases(string $kind, iterable $values): array
{
$out = [];
foreach ($values as $value) {
foreach (self::aliases($kind, trim((string) $value)) as $alias) {
$out[$alias] = true;
}
}
return array_keys($out);
}
public static function same(string $kind, ?string $left, ?string $right): bool
{
$a = self::normalize($kind, $left);
$b = self::normalize($kind, $right);
if ($a === null || $a === '' || $b === null || $b === '') {
return false;
}
return $a === $b;
}
/**
* @return array<string, array{zh-CN: string, en: string}>|null
*/
private static function catalogForKind(string $kind): ?array
{
return match ($kind) {
'degree' => self::degrees(),
'location_country' => self::locationCountries(),
'event_location' => self::eventLocations(),
'purpose', 'audience_purpose' => self::audiencePurposes(),
default => null,
};
1 month ago
}
/**
* @param array<string, array{zh-CN: string, en: string}> $catalog
* @return list<string>
*/
public static function codes(array $catalog): array
{
return array_keys($catalog);
}
/**
* @param array<string, array{zh-CN: string, en: string}> $catalog
* @return list<string>
*/
public static function acceptedValues(array $catalog, string $kind): array
{
return array_values(array_unique([
...self::codes($catalog),
...array_keys(self::legacyMap($kind)),
]));
}
/**
* @param array<string, array{zh-CN: string, en: string}> $catalog
*/
public static function label(array $catalog, string $code, string $locale = PortalLocale::ZH): string
{
$normalized = self::normalize(
$catalog === self::degrees() ? 'degree'
: ($catalog === self::locationCountries() ? 'location_country'
: ($catalog === self::eventLocations() ? 'event_location' : 'purpose')),
$code
) ?? $code;
$row = $catalog[$normalized] ?? null;
if ($row === null) {
return $code;
}
return $locale === PortalLocale::EN
? ($row['en'] ?? $row['zh-CN'])
: ($row['zh-CN'] ?? $row['en'] ?? $code);
}
/**
* @param array<string, array{zh-CN: string, en: string}> $catalog
* @return list<array{value: string, label: string, label_i18n: array{en: string}}>
*/
public static function schemaOptions(array $catalog): array
{
$out = [];
foreach ($catalog as $code => $labels) {
$out[] = [
'value' => $code,
'label' => $labels['zh-CN'],
'label_i18n' => ['en' => $labels['en']],
];
}
return $out;
}
}