using System;
using System.Globalization;
using UnityEngine;
namespace DanroJump.Settings
{
///
/// Тип значения сервисной настройки.
///
public enum ServiceSettingValueType
{
Bool,
Int,
Float,
String,
Button,
Option
}
///
/// Универсальное значение сервисной настройки с явным типом.
///
[Serializable]
public struct ServiceSettingValue : IEquatable
{
///
/// Активный тип значения.
///
public ServiceSettingValueType type;
///
/// Значение для bool-настроек.
///
public bool boolValue;
///
/// Значение для int и option-настроек.
///
public int intValue;
///
/// Значение для float-настроек.
///
public float floatValue;
///
/// Значение для string-настроек.
///
public string stringValue;
///
/// Создает bool-значение.
///
public static ServiceSettingValue Bool(bool value)
{
return new ServiceSettingValue { type = ServiceSettingValueType.Bool, boolValue = value };
}
///
/// Создает int-значение.
///
public static ServiceSettingValue Int(int value)
{
return new ServiceSettingValue { type = ServiceSettingValueType.Int, intValue = value };
}
///
/// Создает float-значение.
///
public static ServiceSettingValue Float(float value)
{
return new ServiceSettingValue { type = ServiceSettingValueType.Float, floatValue = value };
}
///
/// Создает string-значение.
///
public static ServiceSettingValue String(string value)
{
return new ServiceSettingValue { type = ServiceSettingValueType.String, stringValue = value ?? string.Empty };
}
///
/// Создает marker-значение для кнопки действия.
///
public static ServiceSettingValue Button()
{
return new ServiceSettingValue { type = ServiceSettingValueType.Button };
}
///
/// Создает option-значение по индексу варианта.
///
public static ServiceSettingValue Option(int optionIndex)
{
return new ServiceSettingValue { type = ServiceSettingValueType.Option, intValue = optionIndex };
}
///
/// Упаковывает значение в компактный строковый формат для JSON.
///
public ServiceSettingValueCompact ToCompact()
{
return new ServiceSettingValueCompact
{
type = (int)type,
value = type switch
{
ServiceSettingValueType.Bool => boolValue ? "1" : "0",
ServiceSettingValueType.Int => intValue.ToString(CultureInfo.InvariantCulture),
ServiceSettingValueType.Float => floatValue.ToString("R", CultureInfo.InvariantCulture),
ServiceSettingValueType.String => stringValue ?? string.Empty,
ServiceSettingValueType.Button => string.Empty,
ServiceSettingValueType.Option => intValue.ToString(CultureInfo.InvariantCulture),
_ => string.Empty
}
};
}
///
/// Восстанавливает typed-значение из компактного JSON-представления.
///
public static ServiceSettingValue FromCompact(ServiceSettingValueCompact compact)
{
var valueType = Enum.IsDefined(typeof(ServiceSettingValueType), compact.type)
? (ServiceSettingValueType)compact.type
: ServiceSettingValueType.String;
return valueType switch
{
ServiceSettingValueType.Bool => Bool(compact.value == "1" ||
bool.TryParse(compact.value, out var boolValue) && boolValue),
ServiceSettingValueType.Int => Int(ParseInt(compact.value)),
ServiceSettingValueType.Float => Float(ParseFloat(compact.value)),
ServiceSettingValueType.String => String(compact.value),
ServiceSettingValueType.Button => Button(),
ServiceSettingValueType.Option => Option(ParseInt(compact.value)),
_ => String(compact.value)
};
}
///
/// Сравнивает значения настроек с учетом типа и приблизительного float-сравнения.
///
public bool Equals(ServiceSettingValue other)
{
return type == other.type &&
boolValue == other.boolValue &&
intValue == other.intValue &&
Mathf.Approximately(floatValue, other.floatValue) &&
stringValue == other.stringValue;
}
///
/// Сравнивает значение с boxed-объектом.
///
public override bool Equals(object obj)
{
return obj is ServiceSettingValue other && Equals(other);
}
///
/// Возвращает hash code для использования значения в словарях и наборах.
///
public override int GetHashCode()
{
return HashCode.Combine(type, boolValue, intValue, floatValue, stringValue);
}
///
/// Возвращает строковое представление активного typed-значения.
///
public override string ToString()
{
return type switch
{
ServiceSettingValueType.Bool => boolValue.ToString(),
ServiceSettingValueType.Int => intValue.ToString(CultureInfo.InvariantCulture),
ServiceSettingValueType.Float => floatValue.ToString(CultureInfo.InvariantCulture),
ServiceSettingValueType.String => stringValue ?? string.Empty,
ServiceSettingValueType.Button => string.Empty,
ServiceSettingValueType.Option => intValue.ToString(CultureInfo.InvariantCulture),
_ => string.Empty
};
}
///
/// Безопасно читает int из invariant-строки.
///
private static int ParseInt(string value)
{
return int.TryParse(value, NumberStyles.Integer, CultureInfo.InvariantCulture, out var result)
? result
: 0;
}
///
/// Безопасно читает float из invariant-строки.
///
private static float ParseFloat(string value)
{
return float.TryParse(value, NumberStyles.Float, CultureInfo.InvariantCulture, out var result)
? result
: 0f;
}
}
///
/// Компактное сериализуемое представление значения настройки.
///
[Serializable]
public struct ServiceSettingValueCompact
{
///
/// Числовой код типа значения.
///
public int type;
///
/// Значение, упакованное в строку для JSON.
///
public string value;
}
}