228 lines
5.8 KiB
Dart
228 lines
5.8 KiB
Dart
import 'package:yumi/shared/business_logic/models/res/login_res.dart';
|
|
import 'package:yumi/shared/business_logic/models/res/sc_cp_rights_config_res.dart';
|
|
|
|
String? scCpRelationLevelTextFromCabin(
|
|
SCCpCabinRes? cabin, {
|
|
String? fallbackText,
|
|
}) {
|
|
if (cabin == null) {
|
|
return _blankAsNull(fallbackText);
|
|
}
|
|
|
|
final currentValue =
|
|
cabin.cpVal?.toDouble() ?? cabin.cpPairUserProfileCO?.cpValue;
|
|
final computedLevel = _currentLevelFromDynamicConfigs(
|
|
cabin.cpCabinConfigCO ?? const <dynamic>[],
|
|
currentValue,
|
|
);
|
|
final computedText = _formattedLevelText(
|
|
level: computedLevel?.level,
|
|
name: computedLevel?.levelName,
|
|
);
|
|
if (computedText != null) {
|
|
return computedText;
|
|
}
|
|
|
|
final currentConfig = _CpRelationLevelSource.fromDynamic(
|
|
cabin.currentCpCabinConfigCO,
|
|
);
|
|
final currentText = _formattedLevelText(
|
|
level: currentConfig.level,
|
|
name: currentConfig.levelName,
|
|
);
|
|
if (currentText != null) {
|
|
return currentText;
|
|
}
|
|
|
|
return _blankAsNull(cabin.cpPairUserProfileCO?.levelText) ??
|
|
_blankAsNull(fallbackText);
|
|
}
|
|
|
|
String? scCpRelationLevelTextFromRightsConfig(
|
|
SCCpRightsConfigRes config, {
|
|
String? fallbackText,
|
|
}) {
|
|
final currentValue = config.intimacyValue?.toDouble();
|
|
final computedLevel = _currentLevelFromRightsLevels(
|
|
config.levels,
|
|
currentValue,
|
|
);
|
|
final computedText = _formattedLevelText(
|
|
level: computedLevel?.level,
|
|
name: computedLevel?.levelName,
|
|
);
|
|
return computedText ?? _blankAsNull(fallbackText);
|
|
}
|
|
|
|
String scCpRelationLevelDisplayText(String? rawText) {
|
|
final text = rawText?.trim() ?? '';
|
|
final level = scCpRelationLevelIndexOrNull(text);
|
|
if (text.isEmpty) {
|
|
return 'Lv.1 Simple Love';
|
|
}
|
|
final compactLevelPattern = RegExp(
|
|
r'^(?:Lv\.?|Level)?\s*\d+$',
|
|
caseSensitive: false,
|
|
);
|
|
if (compactLevelPattern.hasMatch(text) && level == 1) {
|
|
return 'Lv.1 Simple Love';
|
|
}
|
|
return text;
|
|
}
|
|
|
|
int scCpRelationLevelIndex(String? levelText) {
|
|
return scCpRelationLevelIndexOrNull(levelText) ?? 1;
|
|
}
|
|
|
|
int? scCpRelationLevelIndexOrNull(String? levelText) {
|
|
final text = levelText?.trim() ?? '';
|
|
if (text.isEmpty) {
|
|
return null;
|
|
}
|
|
final levelMatch = RegExp(
|
|
r'(?:Lv\.?|Level|等级|级)\s*([1-5])|([1-5])\s*(?:级|Level)',
|
|
caseSensitive: false,
|
|
).firstMatch(text);
|
|
final fallbackMatch = RegExp(r'[1-5]').firstMatch(text);
|
|
final rawLevel =
|
|
levelMatch?.group(1) ?? levelMatch?.group(2) ?? fallbackMatch?.group(0);
|
|
final level = int.tryParse(rawLevel ?? '');
|
|
return level?.clamp(1, 5).toInt();
|
|
}
|
|
|
|
_CpRelationLevelSource? _currentLevelFromDynamicConfigs(
|
|
List<dynamic> configs,
|
|
double? currentValue,
|
|
) {
|
|
final levels =
|
|
configs.map(_CpRelationLevelSource.fromDynamic).where((level) {
|
|
return level.requiredValue != null;
|
|
}).toList()
|
|
..sort(
|
|
(left, right) => left.requiredValue!.compareTo(right.requiredValue!),
|
|
);
|
|
return _currentLevelFromSources(levels, currentValue);
|
|
}
|
|
|
|
_CpRelationLevelSource? _currentLevelFromRightsLevels(
|
|
List<SCCpRightsLevelRes> levels,
|
|
double? currentValue,
|
|
) {
|
|
final sources =
|
|
levels.map(_CpRelationLevelSource.fromRightsLevel).where((level) {
|
|
return level.requiredValue != null;
|
|
}).toList()
|
|
..sort(
|
|
(left, right) => left.requiredValue!.compareTo(right.requiredValue!),
|
|
);
|
|
return _currentLevelFromSources(sources, currentValue);
|
|
}
|
|
|
|
_CpRelationLevelSource? _currentLevelFromSources(
|
|
List<_CpRelationLevelSource> levels,
|
|
double? currentValue,
|
|
) {
|
|
if (levels.isEmpty || currentValue == null) {
|
|
return null;
|
|
}
|
|
_CpRelationLevelSource? currentLevel;
|
|
for (final level in levels) {
|
|
if ((level.requiredValue ?? 0) <= currentValue) {
|
|
currentLevel = level;
|
|
}
|
|
}
|
|
return currentLevel;
|
|
}
|
|
|
|
String? _formattedLevelText({int? level, String? name}) {
|
|
final levelName = name?.trim() ?? '';
|
|
if (level != null && levelName.isNotEmpty) {
|
|
final nameLevel = scCpRelationLevelIndexOrNull(levelName);
|
|
if (nameLevel == level) {
|
|
return levelName;
|
|
}
|
|
return 'Lv.$level $levelName';
|
|
}
|
|
if (level != null) {
|
|
return 'Lv.$level';
|
|
}
|
|
return _blankAsNull(levelName);
|
|
}
|
|
|
|
String? _blankAsNull(String? value) {
|
|
final text = value?.trim() ?? '';
|
|
return text.isEmpty ? null : text;
|
|
}
|
|
|
|
class _CpRelationLevelSource {
|
|
const _CpRelationLevelSource({
|
|
this.level,
|
|
this.levelName,
|
|
this.requiredValue,
|
|
});
|
|
|
|
factory _CpRelationLevelSource.fromRightsLevel(SCCpRightsLevelRes level) {
|
|
return _CpRelationLevelSource(
|
|
level: level.level,
|
|
levelName: level.levelName,
|
|
requiredValue: level.requiredIntimacyValue,
|
|
);
|
|
}
|
|
|
|
factory _CpRelationLevelSource.fromDynamic(dynamic value) {
|
|
final source = value is Map ? value : const <String, dynamic>{};
|
|
return _CpRelationLevelSource(
|
|
level: _asInt(
|
|
_firstValue(source, const ['level', 'cpLevel', 'cabinLevel', 'lv']),
|
|
),
|
|
levelName: _asString(
|
|
_firstValue(source, const [
|
|
'levelName',
|
|
'name',
|
|
'title',
|
|
'cabinName',
|
|
'cpName',
|
|
]),
|
|
),
|
|
requiredValue: _asInt(
|
|
_firstValue(source, const [
|
|
'requiredIntimacyValue',
|
|
'requiredCpValue',
|
|
'requiredCpVal',
|
|
'cpValue',
|
|
'cpVal',
|
|
'intimacyValue',
|
|
]),
|
|
),
|
|
);
|
|
}
|
|
|
|
final int? level;
|
|
final String? levelName;
|
|
final int? requiredValue;
|
|
}
|
|
|
|
dynamic _firstValue(Map source, List<String> keys) {
|
|
for (final key in keys) {
|
|
if (source.containsKey(key) && source[key] != null) {
|
|
return source[key];
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
|
|
String? _asString(dynamic value) {
|
|
final text = value?.toString().trim();
|
|
return text == null || text.isEmpty ? null : text;
|
|
}
|
|
|
|
int? _asInt(dynamic value) {
|
|
if (value is int) {
|
|
return value;
|
|
}
|
|
if (value is num) {
|
|
return value.toInt();
|
|
}
|
|
return int.tryParse(value?.toString() ?? '');
|
|
}
|