Files
Pf2eDataScrapper/Pf2e/Web/Helpers/Format/Formatters.cs
T

197 lines
7.3 KiB
C#

using System.ComponentModel;
using Pf2e.Database.Model;
using Pf2e.Database.Model.Base.Keywords;
using Pf2e.Database.Model.Base.Source;
using Pf2e.Database.Model.Base.Targets;
using Pf2e.Database.Model.Common.I18n;
using Pf2e.Database.Model.Enum;
namespace Pf2e.Web.Helpers.Format;
public static class Formatters
{
/// <summary>
/// Форматтер для перечислений (enum).
/// </summary>
public static readonly ValueFormatter EnumFormatter = new CustomValueFormatter(
(type) => type.IsEnum,
(value) =>
{
Enum enumValue = (Enum)value;
string description = GetEnumDescription(enumValue);
return $"{description} ({enumValue})";
string GetEnumDescription(Enum v)
{
Type type = v.GetType();
string name = Enum.GetName(type, v) ?? v.ToString();
System.Reflection.FieldInfo? field = type.GetField(name);
if (field == null)
return v.ToString();
if (
Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute))
is DescriptionAttribute attr
)
{
return attr.Description;
}
return v.ToString();
}
}
);
/// <summary>
/// Форматтер для примитивных типов и строк.
/// </summary>
public static readonly ValueFormatter PrimitiveFormatter = new CustomValueFormatter(
(type) => type.IsPrimitive || type == typeof(string) || type == typeof(decimal),
(value) => value.ToString() ?? "null"
);
/// <summary>
/// Форматтер для коллекций.
/// </summary>
public static readonly ValueFormatter CollectionFormatter = new CollectionFormatter();
/// <summary>
/// Форматтеры для стандартных типов из базы данных.
/// </summary>
public static readonly List<ValueFormatter> DefaultTypeFormatters =
[
new TypeValueFormatter<LocaleString>(
(value) =>
{
LocaleString localeString = (LocaleString)value;
List<string> items = [];
foreach (LocaleItem item in localeString)
{
items.Add($"{item.Locale}: {item.Value}");
}
return string.Join("<br/>", items);
}
),
// IEntity
new CustomValueFormatter(
(type) => typeof(IEntity).IsAssignableFrom(type),
(value) =>
{
IEntity entity = (IEntity)value;
EntityType entityType = entity.Entity.Type;
string typeName = PgNameHelper.GetPgName(entityType);
string slug = entity.Entity.Slug;
string name = entity.Entity.Name[LocaleType.English];
return $"<a href=\"/{typeName}/{slug}\">{name}</a>";
}
),
// EntitySource
new TypeValueFormatter<EntitySource>(
(value) =>
{
EntitySource entitySource = (EntitySource)value;
string sourceName = entitySource.Source.Name;
string suffix = !string.IsNullOrEmpty(entitySource.Suffix)
? $" ({entitySource.Suffix})"
: "";
string isRemaster = entitySource.IsRemaster ? " [Remaster]" : "";
return $"{sourceName}{suffix}{isRemaster}";
}
),
// Keyword
new TypeValueFormatter<Keyword>(
(value) =>
{
Keyword keyword = (Keyword)value;
string name = keyword.Name[LocaleType.English];
return $"{name}";
}
),
// KeywordAlias
new TypeValueFormatter<KeywordAlias>(
(value) =>
{
KeywordAlias alias = (KeywordAlias)value;
return $"{alias.Value}";
}
),
// ExternalTarget
new TypeValueFormatter<ExternalTarget>(
(value) =>
{
ExternalTarget target = (ExternalTarget)value;
return $"{target.Name} (Icon: {target.Icon}, Prefix: {target.Prefix})";
}
),
// EntityExternal
new TypeValueFormatter<EntityExternal>(
(value) =>
{
EntityExternal entityExternal = (EntityExternal)value;
string targetName = entityExternal.Target?.Name ?? "Unknown";
string externalId = !string.IsNullOrEmpty(entityExternal.ExternalId)
? $" ID: {entityExternal.ExternalId}"
: "";
string suffix = !string.IsNullOrEmpty(entityExternal.Suffix)
? $" Suffix: {entityExternal.Suffix}"
: "";
return $"{targetName}{externalId}{suffix}";
}
),
// Source
new TypeValueFormatter<Source>(
(value) =>
{
Source source = (Source)value;
string releaseDate = source.ReleaseDate?.ToString("yyyy-MM-dd") ?? "Unknown";
return $"{source.Name} (Category: {source.Category}, Release: {releaseDate})";
}
),
];
/// <summary>
/// Набор всех стандартных форматтеров.
/// </summary>
public static readonly List<ValueFormatter> AllFormatters =
[
.. DefaultTypeFormatters,
EnumFormatter,
PrimitiveFormatter,
CollectionFormatter,
];
/// <summary>
/// Добавить пользовательский форматтер в набор всех форматтеров.
/// </summary>
/// <param name="formatter">Добавляемый форматтер.</param>
public static void AddFormatter(ValueFormatter formatter)
{
AllFormatters.Insert(0, formatter);
}
/// <summary>
/// Выбрать подходящий форматтер для типа.
/// </summary>
/// <param name="type">Тип значения.</param>
/// <returns>Форматтер для типа или <c>null</c>, если подходящего не найдено.</returns>
public static ValueFormatter? SelectFormatter(Type type) =>
AllFormatters.FirstOrDefault(f => f.CanFormat(type)) ?? null;
/// <summary>
/// Выбрать подходящий форматтер для значения.
/// </summary>
/// <param name="value">Значение.</param>
/// <returns>Форматтер для значения или <c>null</c>, если значение равно <c>null</c> или подходящего не найдено.</returns>
public static ValueFormatter? SelectFormatter(object? value) =>
value == null ? null : SelectFormatter(value.GetType());
/// <summary>
/// Форматировать значение в строку.
/// </summary>
/// <param name="value">Форматируемое значение.</param>
/// <returns>Строковое представление отформатированного значения.</returns>
public static string Format(object? value) =>
SelectFormatter(value)?.Format(value!) ?? "[not implemented]";
}