refactor(service): 서비스 로직 정리

- ad_service: 광고 서비스 코드 정리
- debug_settings_service: 디버그 설정 간소화
- stat_calculator: 스탯 계산 로직 정리
- character_roll_service: 캐릭터 롤 로직 수정
This commit is contained in:
JiWoong Sul
2026-01-19 19:40:54 +09:00
parent 0cccc17f1f
commit 71740abe8f
4 changed files with 21 additions and 67 deletions

View File

@@ -5,6 +5,8 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:asciineverdie/src/core/engine/iap_service.dart';
/// 광고 타입
enum AdType {
/// 부활용 리워드 광고 (30초)
@@ -105,9 +107,6 @@ class AdService {
bool _isInitialized = false;
/// 디버그 모드에서 광고 활성화 여부
bool _debugAdEnabled = true;
/// 로드된 리워드 광고
RewardedAd? _rewardedAd;
@@ -144,23 +143,14 @@ class AdService {
}
// ===========================================================================
// 디버그 설
// 광고 스킵 판
// ===========================================================================
/// 디버그 모드 광고 활성화 여부
bool get debugAdEnabled => _debugAdEnabled;
/// 디버그 모드 광고 토글
set debugAdEnabled(bool value) {
_debugAdEnabled = value;
debugPrint('[AdService] Debug ad enabled: $value');
}
/// 광고를 스킵할지 여부
///
/// 스킵 조건:
/// - 비모바일 플랫폼 (macOS, Windows, Linux, Web)
/// - 디버그 모드에서 광고 비활성화
/// - IAP로 광고 제거 구매 완료 (디버그 시뮬레이션 포함)
bool get _shouldSkipAd {
// 웹에서는 항상 스킵
if (kIsWeb) return true;
@@ -168,8 +158,9 @@ class AdService {
if (!Platform.isAndroid && !Platform.isIOS) {
return true;
}
// 디버그 모드에서 광고 비활성화 시 스킵
return kDebugMode && !_debugAdEnabled;
// IAP 광고 제거 구매 시 스킵 (디버그 시뮬레이션 포함)
if (IAPService.instance.isAdRemovalPurchased) return true;
return false;
}
// ===========================================================================
@@ -195,7 +186,9 @@ class AdService {
},
onAdFailedToLoad: (error) {
_isLoadingRewardedAd = false;
debugPrint('[AdService] Rewarded ad failed to load: ${error.message}');
debugPrint(
'[AdService] Rewarded ad failed to load: ${error.message}',
);
},
),
);
@@ -249,7 +242,9 @@ class AdService {
_loadRewardedAd(); // 다음 광고 미리 로드
// 보상 수령 여부에 따라 결과 반환
if (!completer.isCompleted) {
completer.complete(rewarded ? AdResult.completed : AdResult.cancelled);
completer.complete(
rewarded ? AdResult.completed : AdResult.cancelled,
);
}
},
onAdFailedToShowFullScreenContent: (ad, error) {

View File

@@ -143,11 +143,10 @@ class CharacterRollService {
_rollsRemaining--;
_saveRollsRemaining();
// 무료 유저: 새 굴리기마다 되돌리기 기회 1회 부여 (광고 시청 필요)
// 유료 유저: 세션당 최대 횟수 유지
if (!_isPaidUser && _undoRemaining < maxUndoFreeUser) {
_undoRemaining = maxUndoFreeUser;
}
// 매 굴림마다 되돌리기 횟수 리셋
// - 유료 유저: 3회
// - 무료 유저: 1회 (광고 시청 필요)
_undoRemaining = _isPaidUser ? maxUndoPaidUser : maxUndoFreeUser;
debugPrint('[CharacterRollService] Rolled: remaining=$_rollsRemaining, '
'history=${_rollHistory.length}, undo=$_undoRemaining');

View File

@@ -1,7 +1,6 @@
import 'package:flutter/foundation.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:asciineverdie/src/core/engine/ad_service.dart';
import 'package:asciineverdie/src/core/engine/iap_service.dart';
/// 디버그 설정 서비스 (Phase 8)
@@ -23,7 +22,6 @@ class DebugSettingsService {
// 상수
// ===========================================================================
static const String _keyAdEnabled = 'debug_ad_enabled';
static const String _keyIapSimulated = 'debug_iap_simulated';
static const String _keyOfflineHours = 'debug_offline_hours';
@@ -36,9 +34,6 @@ class DebugSettingsService {
bool _isInitialized = false;
/// 광고 활성화 여부 (디버그 모드 전용)
bool _adEnabled = true;
/// IAP 구매 시뮬레이션 여부 (디버그 모드 전용)
bool _iapSimulated = false;
@@ -58,7 +53,6 @@ class DebugSettingsService {
}
final prefs = await SharedPreferences.getInstance();
_adEnabled = prefs.getBool(_keyAdEnabled) ?? true;
_iapSimulated = prefs.getBool(_keyIapSimulated) ?? false;
_offlineHours = prefs.getInt(_keyOfflineHours) ?? 0;
@@ -66,13 +60,14 @@ class DebugSettingsService {
_syncToServices();
_isInitialized = true;
debugPrint('[DebugSettings] Initialized: ad=$_adEnabled, '
'iap=$_iapSimulated, offline=$_offlineHours');
debugPrint(
'[DebugSettings] Initialized: '
'iap=$_iapSimulated, offline=$_offlineHours',
);
}
/// 설정을 다른 서비스에 동기화
void _syncToServices() {
AdService.instance.debugAdEnabled = _adEnabled;
IAPService.instance.debugIAPSimulated = _iapSimulated;
}
@@ -83,29 +78,6 @@ class DebugSettingsService {
/// 디버그 모드 활성화 여부
bool get isDebugMode => kDebugMode;
// ===========================================================================
// 광고 설정
// ===========================================================================
/// 광고 활성화 여부
///
/// - true: 실제 광고 표시
/// - false: 광고 버튼 클릭 시 바로 보상 지급
bool get adEnabled => _adEnabled;
/// 광고 활성화 토글
Future<void> setAdEnabled(bool value) async {
if (!kDebugMode) return;
_adEnabled = value;
AdService.instance.debugAdEnabled = value;
final prefs = await SharedPreferences.getInstance();
await prefs.setBool(_keyAdEnabled, value);
debugPrint('[DebugSettings] Ad enabled: $value');
}
// ===========================================================================
// IAP 설정
// ===========================================================================
@@ -171,7 +143,6 @@ class DebugSettingsService {
Future<void> resetAll() async {
if (!kDebugMode) return;
await setAdEnabled(true);
await setIapSimulated(false);
await setOfflineHours(0);

View File

@@ -187,17 +187,6 @@ class StatCalculator {
return bonus > 0 ? bonus : 1.0;
}
/// 사망 시 보존할 장비 개수 (Coredump Undead 패시브)
///
/// [race] 종족 특성
/// Returns: 보존 장비 개수
int calculateDeathEquipmentPreserve(RaceTraits race) {
if (race.hasPassive(PassiveType.deathEquipmentPreserve)) {
return race.getPassiveValue(PassiveType.deathEquipmentPreserve).round();
}
return 0;
}
/// 연속 공격 가능 여부 (Refactor Monk 패시브)
bool hasMultiAttack(ClassTraits klass) {
return klass.hasPassive(ClassPassiveType.multiAttack);