refactor(model): freezed 패키지 도입으로 보일러플레이트 제거
- ItemStats, CombatStats, EquipmentItem을 freezed로 마이그레이션 - copyWith, toJson/fromJson 자동 생성 - 세이브 파일 호환성 유지
This commit is contained in:
@@ -1,51 +1,38 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'package:asciineverdie/src/core/model/equipment_slot.dart';
|
||||
import 'package:asciineverdie/src/core/model/item_stats.dart';
|
||||
|
||||
part 'equipment_item.freezed.dart';
|
||||
part 'equipment_item.g.dart';
|
||||
|
||||
/// 장비 아이템
|
||||
///
|
||||
/// 개별 장비의 이름, 슬롯, 레벨, 스탯 등을 포함하는 클래스.
|
||||
/// 불변(immutable) 객체로 설계됨.
|
||||
class EquipmentItem {
|
||||
const EquipmentItem({
|
||||
required this.name,
|
||||
required this.slot,
|
||||
required this.level,
|
||||
required this.weight,
|
||||
required this.stats,
|
||||
required this.rarity,
|
||||
});
|
||||
@freezed
|
||||
class EquipmentItem with _$EquipmentItem {
|
||||
const EquipmentItem._();
|
||||
|
||||
/// 아이템 이름 (예: "Flaming Sword of Doom")
|
||||
final String name;
|
||||
const factory EquipmentItem({
|
||||
/// 아이템 이름 (예: "Flaming Sword of Doom")
|
||||
required String name,
|
||||
/// 장착 슬롯
|
||||
@JsonKey(fromJson: _slotFromJson, toJson: _slotToJson)
|
||||
required EquipmentSlot slot,
|
||||
/// 아이템 레벨
|
||||
required int level,
|
||||
/// 무게 (STR 기반 휴대 제한용)
|
||||
required int weight,
|
||||
/// 아이템 스탯 보정치
|
||||
required ItemStats stats,
|
||||
/// 희귀도
|
||||
@JsonKey(fromJson: _rarityFromJson, toJson: _rarityToJson)
|
||||
required ItemRarity rarity,
|
||||
}) = _EquipmentItem;
|
||||
|
||||
/// 장착 슬롯
|
||||
final EquipmentSlot slot;
|
||||
|
||||
/// 아이템 레벨
|
||||
final int level;
|
||||
|
||||
/// 무게 (STR 기반 휴대 제한용)
|
||||
final int weight;
|
||||
|
||||
/// 아이템 스탯 보정치
|
||||
final ItemStats stats;
|
||||
|
||||
/// 희귀도
|
||||
final ItemRarity rarity;
|
||||
|
||||
/// 가중치 (자동 장착 비교용)
|
||||
///
|
||||
/// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
|
||||
int get itemWeight {
|
||||
const baseValue = 10;
|
||||
return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
|
||||
}
|
||||
|
||||
/// 빈 아이템 여부
|
||||
bool get isEmpty => name.isEmpty;
|
||||
|
||||
/// 유효한 아이템 여부
|
||||
bool get isNotEmpty => name.isNotEmpty;
|
||||
factory EquipmentItem.fromJson(Map<String, dynamic> json) =>
|
||||
_$EquipmentItemFromJson(json);
|
||||
|
||||
/// 빈 아이템 생성 (특정 슬롯)
|
||||
factory EquipmentItem.empty(EquipmentSlot slot) {
|
||||
@@ -54,7 +41,7 @@ class EquipmentItem {
|
||||
slot: slot,
|
||||
level: 0,
|
||||
weight: 0,
|
||||
stats: ItemStats.empty,
|
||||
stats: const ItemStats(),
|
||||
rarity: ItemRarity.common,
|
||||
);
|
||||
}
|
||||
@@ -71,59 +58,39 @@ class EquipmentItem {
|
||||
);
|
||||
}
|
||||
|
||||
EquipmentItem copyWith({
|
||||
String? name,
|
||||
EquipmentSlot? slot,
|
||||
int? level,
|
||||
int? weight,
|
||||
ItemStats? stats,
|
||||
ItemRarity? rarity,
|
||||
}) {
|
||||
return EquipmentItem(
|
||||
name: name ?? this.name,
|
||||
slot: slot ?? this.slot,
|
||||
level: level ?? this.level,
|
||||
weight: weight ?? this.weight,
|
||||
stats: stats ?? this.stats,
|
||||
rarity: rarity ?? this.rarity,
|
||||
);
|
||||
/// 가중치 (자동 장착 비교용)
|
||||
///
|
||||
/// 가중치 = 기본값 + (레벨 * 10) + (희귀도 보너스) + (스탯 합계)
|
||||
int get itemWeight {
|
||||
const baseValue = 10;
|
||||
return baseValue + (level * 10) + rarity.weightBonus + stats.totalStatValue;
|
||||
}
|
||||
|
||||
/// JSON으로 직렬화
|
||||
Map<String, dynamic> toJson() {
|
||||
return {
|
||||
'name': name,
|
||||
'slot': slot.name,
|
||||
'level': level,
|
||||
'weight': weight,
|
||||
'stats': stats.toJson(),
|
||||
'rarity': rarity.name,
|
||||
};
|
||||
}
|
||||
/// 빈 아이템 여부
|
||||
bool get isEmpty => name.isEmpty;
|
||||
|
||||
/// JSON에서 역직렬화
|
||||
factory EquipmentItem.fromJson(Map<String, dynamic> json) {
|
||||
final slotName = json['slot'] as String? ?? 'weapon';
|
||||
final rarityName = json['rarity'] as String? ?? 'common';
|
||||
|
||||
return EquipmentItem(
|
||||
name: json['name'] as String? ?? '',
|
||||
slot: EquipmentSlot.values.firstWhere(
|
||||
(s) => s.name == slotName,
|
||||
orElse: () => EquipmentSlot.weapon,
|
||||
),
|
||||
level: json['level'] as int? ?? 0,
|
||||
weight: json['weight'] as int? ?? 0,
|
||||
stats: json['stats'] != null
|
||||
? ItemStats.fromJson(json['stats'] as Map<String, dynamic>)
|
||||
: ItemStats.empty,
|
||||
rarity: ItemRarity.values.firstWhere(
|
||||
(r) => r.name == rarityName,
|
||||
orElse: () => ItemRarity.common,
|
||||
),
|
||||
);
|
||||
}
|
||||
/// 유효한 아이템 여부
|
||||
bool get isNotEmpty => name.isNotEmpty;
|
||||
|
||||
@override
|
||||
String toString() => name.isEmpty ? '(empty)' : name;
|
||||
}
|
||||
|
||||
// JSON 변환 헬퍼 (세이브 파일 호환성 유지)
|
||||
EquipmentSlot _slotFromJson(String? value) {
|
||||
return EquipmentSlot.values.firstWhere(
|
||||
(s) => s.name == value,
|
||||
orElse: () => EquipmentSlot.weapon,
|
||||
);
|
||||
}
|
||||
|
||||
String _slotToJson(EquipmentSlot slot) => slot.name;
|
||||
|
||||
ItemRarity _rarityFromJson(String? value) {
|
||||
return ItemRarity.values.firstWhere(
|
||||
(r) => r.name == value,
|
||||
orElse: () => ItemRarity.common,
|
||||
);
|
||||
}
|
||||
|
||||
String _rarityToJson(ItemRarity rarity) => rarity.name;
|
||||
|
||||
Reference in New Issue
Block a user