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:flutter/services.dart';
import 'package:google_mobile_ads/google_mobile_ads.dart'; import 'package:google_mobile_ads/google_mobile_ads.dart';
import 'package:asciineverdie/src/core/engine/iap_service.dart';
/// 광고 타입 /// 광고 타입
enum AdType { enum AdType {
/// 부활용 리워드 광고 (30초) /// 부활용 리워드 광고 (30초)
@@ -105,9 +107,6 @@ class AdService {
bool _isInitialized = false; bool _isInitialized = false;
/// 디버그 모드에서 광고 활성화 여부
bool _debugAdEnabled = true;
/// 로드된 리워드 광고 /// 로드된 리워드 광고
RewardedAd? _rewardedAd; 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) /// - 비모바일 플랫폼 (macOS, Windows, Linux, Web)
/// - 디버그 모드에서 광고 비활성화 /// - IAP로 광고 제거 구매 완료 (디버그 시뮬레이션 포함)
bool get _shouldSkipAd { bool get _shouldSkipAd {
// 웹에서는 항상 스킵 // 웹에서는 항상 스킵
if (kIsWeb) return true; if (kIsWeb) return true;
@@ -168,8 +158,9 @@ class AdService {
if (!Platform.isAndroid && !Platform.isIOS) { if (!Platform.isAndroid && !Platform.isIOS) {
return true; return true;
} }
// 디버그 모드에서 광고 비활성화 시 스킵 // IAP 광고 제거 구매 시 스킵 (디버그 시뮬레이션 포함)
return kDebugMode && !_debugAdEnabled; if (IAPService.instance.isAdRemovalPurchased) return true;
return false;
} }
// =========================================================================== // ===========================================================================
@@ -195,7 +186,9 @@ class AdService {
}, },
onAdFailedToLoad: (error) { onAdFailedToLoad: (error) {
_isLoadingRewardedAd = false; _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(); // 다음 광고 미리 로드 _loadRewardedAd(); // 다음 광고 미리 로드
// 보상 수령 여부에 따라 결과 반환 // 보상 수령 여부에 따라 결과 반환
if (!completer.isCompleted) { if (!completer.isCompleted) {
completer.complete(rewarded ? AdResult.completed : AdResult.cancelled); completer.complete(
rewarded ? AdResult.completed : AdResult.cancelled,
);
} }
}, },
onAdFailedToShowFullScreenContent: (ad, error) { onAdFailedToShowFullScreenContent: (ad, error) {

View File

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

View File

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

View File

@@ -187,17 +187,6 @@ class StatCalculator {
return bonus > 0 ? bonus : 1.0; 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 패시브) /// 연속 공격 가능 여부 (Refactor Monk 패시브)
bool hasMultiAttack(ClassTraits klass) { bool hasMultiAttack(ClassTraits klass) {
return klass.hasPassive(ClassPassiveType.multiAttack); return klass.hasPassive(ClassPassiveType.multiAttack);