Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 4 additions & 8 deletions FullStackCodingBot/FullStackCodingBot.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@
E4336F6326F083C30049A5D8 /* CoreDataManagerType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */; };
E4336F6826F1AB8B0049A5D8 /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */; };
E4336F6A26F1B7500049A5D8 /* GameStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6926F1B7500049A5D8 /* GameStorage.swift */; };
E4336F6C26F1BC1A0049A5D8 /* StorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */; };
E4336F6C26F1BC1A0049A5D8 /* StorageProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4336F6B26F1BC1A0049A5D8 /* StorageProtocols.swift */; };
E43B64A226ABD81C001D9896 /* GameBackgroundView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */; };
E43B64A426AC2384001D9896 /* TimeBarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E43B64A326AC2384001D9896 /* TimeBarView.swift */; };
E45B0AB82692929F006FDE3D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E45B0AB72692929F006FDE3D /* Assets.xcassets */; };
Expand Down Expand Up @@ -143,7 +143,6 @@
E4DD682126A138D900B9F9CE /* GameKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4DD682026A138D900B9F9CE /* GameKit.framework */; };
E4DF613B26A845670061F6E9 /* AdStorageType.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DF613A26A845670061F6E9 /* AdStorageType.swift */; };
E4DF613D26A845DA0061F6E9 /* AdStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DF613C26A845DA0061F6E9 /* AdStorage.swift */; };
E4DF613F26A847330061F6E9 /* AdViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DF613E26A847330061F6E9 /* AdViewModel.swift */; };
E4DF614126A92CE00061F6E9 /* ShopItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DF614026A92CE00061F6E9 /* ShopItem.swift */; };
E4DF614326A93FFB0061F6E9 /* ShopCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4DF614226A93FFB0061F6E9 /* ShopCell.swift */; };
E4F4304226C37A9B00F046E9 /* GameOverDialogView.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4F4304126C37A9B00F046E9 /* GameOverDialogView.swift */; };
Expand Down Expand Up @@ -248,7 +247,7 @@
E4336F6226F083C30049A5D8 /* CoreDataManagerType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManagerType.swift; sourceTree = "<group>"; };
E4336F6726F1AB8B0049A5D8 /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = "<group>"; };
E4336F6926F1B7500049A5D8 /* GameStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameStorage.swift; sourceTree = "<group>"; };
E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageType.swift; sourceTree = "<group>"; };
E4336F6B26F1BC1A0049A5D8 /* StorageProtocols.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StorageProtocols.swift; sourceTree = "<group>"; };
E43B64A126ABD81C001D9896 /* GameBackgroundView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameBackgroundView.swift; sourceTree = "<group>"; };
E43B64A326AC2384001D9896 /* TimeBarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimeBarView.swift; sourceTree = "<group>"; };
E45B0AAB2692929D006FDE3D /* Full Stack.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Full Stack.app"; sourceTree = BUILT_PRODUCTS_DIR; };
Expand Down Expand Up @@ -300,7 +299,6 @@
E4DD682026A138D900B9F9CE /* GameKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System/Library/Frameworks/GameKit.framework; sourceTree = SDKROOT; };
E4DF613A26A845670061F6E9 /* AdStorageType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdStorageType.swift; sourceTree = "<group>"; };
E4DF613C26A845DA0061F6E9 /* AdStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdStorage.swift; sourceTree = "<group>"; };
E4DF613E26A847330061F6E9 /* AdViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AdViewModel.swift; sourceTree = "<group>"; };
E4DF614026A92CE00061F6E9 /* ShopItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopItem.swift; sourceTree = "<group>"; };
E4DF614226A93FFB0061F6E9 /* ShopCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopCell.swift; sourceTree = "<group>"; };
E4F4304126C37A9B00F046E9 /* GameOverDialogView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GameOverDialogView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -488,7 +486,6 @@
E4779C6826983F8000B92D24 /* GameOverViewModel.swift */,
E41C85DC269C50F0008F2E91 /* PauseViewModel.swift */,
71DF65542692FD1400557693 /* CommonViewModel.swift */,
E4DF613E26A847330061F6E9 /* AdViewModel.swift */,
715C1C9726BD09950025C681 /* StoryViewModel.swift */,
7166B23C26C253A800E098BE /* HowToPlayViewModel.swift */,
);
Expand Down Expand Up @@ -649,7 +646,7 @@
isa = PBXGroup;
children = (
E4336F5A26F0638A0049A5D8 /* Storage.swift */,
E4336F6B26F1BC1A0049A5D8 /* StorageType.swift */,
E4336F6B26F1BC1A0049A5D8 /* StorageProtocols.swift */,
E4336F6526F08AD80049A5D8 /* RealDataStorage */,
E4336F6626F08AF10049A5D8 /* BackUpManager */,
);
Expand Down Expand Up @@ -1098,7 +1095,7 @@
E4150EA426BE9A540041DD32 /* Line.swift in Sources */,
E4BF710926B00EF600E8645F /* FeverTimeBarView.swift in Sources */,
E4DF614326A93FFB0061F6E9 /* ShopCell.swift in Sources */,
E4336F6C26F1BC1A0049A5D8 /* StorageType.swift in Sources */,
E4336F6C26F1BC1A0049A5D8 /* StorageProtocols.swift in Sources */,
E41C85DD269C50F0008F2E91 /* PauseViewModel.swift in Sources */,
E41C85DF269C5149008F2E91 /* PauseButtonController.swift in Sources */,
E418F36F26DC8D4800F35AFB /* UnitInfo - keyColor.swift in Sources */,
Expand All @@ -1115,7 +1112,6 @@
719AB9DE26B7ADF2001B5913 /* SettingViewController.swift in Sources */,
71DF65552692FD1400557693 /* CommonViewModel.swift in Sources */,
715C1C9826BD09950025C681 /* StoryViewModel.swift in Sources */,
E4DF613F26A847330061F6E9 /* AdViewModel.swift in Sources */,
710D0D442693EA6900244A16 /* GameViewModel.swift in Sources */,
71DF65492692F97900557693 /* ItemViewModel.swift in Sources */,
E4C2C34F26A292BB007BDF81 /* ReplicateAnimationView.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ private extension AppDelegate {
switch hasLaunchedOnce {

case true:
let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator, storage: storage!, settings: settings)
let mainViewModel = MainViewModel(sceneCoordinator: sceneCoordinator,
storage: storage! as (RewardManagable & GameDataManagable),
settings: settings)
let mainScene = MainScene.main(mainViewModel)
return mainScene

case false:
let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, storage: storage!, settings: settings)
let storyViewModel = StoryViewModel(sceneCoordinator: sceneCoordinator, settings: settings)
let storyScene = GameHelperScene.story(storyViewModel)
return storyScene

Expand Down
81 changes: 44 additions & 37 deletions FullStackCodingBot/FullStackCodingBot/Service/Storage/Storage.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import RxSwift
import GoogleMobileAds

final class Storage {

private var gameStorage: GameStorageType
private var adStorage: AdStorageType
private var backUpCenter: BackUpCenterType
Expand All @@ -16,7 +15,9 @@ final class Storage {
self.adStorage = adStorage
self.backUpCenter = backUpCenter
}

}

extension Storage: GameDataManagable {
func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable<Bool> {
Observable.create { [unowned self] observer in
self.backUpCenter.load(with: uuid, isFirstLaunched)
Expand All @@ -34,33 +35,18 @@ final class Storage {
return Disposables.create()
}
}
}

extension Storage: StorageType {
func availableRewards() -> Observable<[ShopItem]> {
return adStorage.availableItems()
}

func availableMoney() -> Observable<Int> {
return gameStorage.availableMoney()
}

func setNewRewardsIfPossible() -> Observable<Bool> {
return adStorage.setNewRewardsIfPossible(with: .none)
}

func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int {
if let finishedAd = finishedAd {
adStorage.adDidFinished(finishedAd)
} else {
adStorage.giftTaken()
}
let reward = ShopSetting.reward()
gameStorage.raiseMoney(by: reward)
backUpCenter.save(gameData: .none, gameStorage.myMoney(), .none)
return reward
func save() {
let currentData = NetworkDTO(units: gameStorage.itemList(),
money: gameStorage.myMoney(),
score: gameStorage.myHighScore(),
ads: adStorage.currentInformation(),
date: Date())
backUpCenter.save(gameData: currentData)
}

}

extension Storage: GameItemManagable {
func itemList() -> [Unit] {
return gameStorage.itemList()
}
Expand All @@ -70,28 +56,49 @@ extension Storage: StorageType {
backUpCenter.save(gameData: newUnit, gameStorage.myMoney(), .none)
return newUnit
}

func myHighScore() -> Int {
return gameStorage.myHighScore()
}

extension Storage: GameMoneyManagable {
func availableMoney() -> Observable<Int> {
return gameStorage.availableMoney()
}

func raiseMoney(by amount: Int) {
gameStorage.raiseMoney(by: amount)
backUpCenter.save(gameData: .none, gameStorage.myMoney(), .none)
}
}

extension Storage: HighScoreManagable {
func myHighScore() -> Int {
return gameStorage.myHighScore()
}

func updateHighScore(new score: Int) -> Bool {
let isUpdatable = gameStorage.updateHighScore(new: score)
if isUpdatable { backUpCenter.save(gameData: .none, .none, score) }
return isUpdatable
}
}

extension Storage: RewardManagable {
func availableRewards() -> Observable<[ShopItem]> {
return adStorage.availableItems()
}

func save() {
let currentData = NetworkDTO(units: gameStorage.itemList(),
money: gameStorage.myMoney(),
score: gameStorage.myHighScore(),
ads: adStorage.currentInformation(),
date: Date())
backUpCenter.save(gameData: currentData)
func setNewRewardsIfPossible() -> Observable<Bool> {
return adStorage.setNewRewardsIfPossible(with: .none)
}

func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int {
if let finishedAd = finishedAd {
adStorage.adDidFinished(finishedAd)
} else {
adStorage.giftTaken()
}
let reward = ShopSetting.reward()
gameStorage.raiseMoney(by: reward)
backUpCenter.save(gameData: .none, gameStorage.myMoney(), .none)
return reward
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,30 @@ import Foundation
import RxSwift
import GoogleMobileAds

protocol StorageType {

typealias StorageType = GameDataManagable & GameItemManagable & GameMoneyManagable & HighScoreManagable & RewardManagable

protocol GameDataManagable {
func initializeData(using uuid: String?, isFirstLaunched: Bool) -> Observable<Bool>

// Shop
func availableRewards() -> Observable<[ShopItem]>
func availableMoney() -> Observable<Int> // + Item
func setNewRewardsIfPossible() -> Observable<Bool>
func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int

// Item
func save()
}

protocol GameItemManagable {
func itemList() -> [Unit]
func raiseLevel(of unit: Unit, using money: Int) -> Unit

// Game
func myHighScore() -> Int

// GameOver
}

protocol GameMoneyManagable {
func availableMoney() -> Observable<Int>
func raiseMoney(by amount: Int)
}

protocol HighScoreManagable {
func myHighScore() -> Int
func updateHighScore(new score: Int) -> Bool

// Background
func save()
}

protocol RewardManagable {
func availableRewards() -> Observable<[ShopItem]>
func setNewRewardsIfPossible() -> Observable<Bool>
func rewardNeedsToBeGiven(with finishedAd: GADRewardedAd?) -> Int
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,8 @@ import Foundation
class CommonViewModel: NSObject {

let sceneCoordinator: SceneCoordinatorType
let storage: StorageType

init(sceneCoordinator: SceneCoordinatorType, storage: StorageType) {
init(sceneCoordinator: SceneCoordinatorType) {
self.sceneCoordinator = sceneCoordinator
self.storage = storage
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import GameKit

final class GameOverViewModel: CommonViewModel {

private let storage: HighScoreManagable & GameMoneyManagable
private var gameStoryManager: GameStoryManager
private(set) var newScript = BehaviorRelay<Script?>(value: nil)
private(set) var rankInfo = BehaviorRelay<String>(value: "")
Expand All @@ -27,15 +28,16 @@ final class GameOverViewModel: CommonViewModel {
}()

init(sceneCoordinator: SceneCoordinatorType,
storage: StorageType,
storage: HighScoreManagable & GameMoneyManagable,
finalScore: Int,
newGameStatus: BehaviorRelay<GameStatus>,
gameStoryManager: GameStoryManager = GameStoryManager()) {
self.storage = storage
self.scoreInfo.accept(finalScore)
self.moneyInfo.accept(finalScore/10)
self.newGameStatus = newGameStatus
self.gameStoryManager = gameStoryManager
super.init(sceneCoordinator: sceneCoordinator, storage: storage)
super.init(sceneCoordinator: sceneCoordinator)
}

func execute() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import Action
final class GameViewModel: CommonViewModel {

// Helper Objects
private let storage: HighScoreManagable & GameItemManagable
private var gameSoundStation: GameSoundEffectStation
private var gameUnitManager: GameUnitManagerType
private var timeManager: TimeManagerType
Expand Down Expand Up @@ -33,15 +34,16 @@ final class GameViewModel: CommonViewModel {
}

init(sceneCoordinator: SceneCoordinatorType,
storage: StorageType,
storage: HighScoreManagable & GameItemManagable,
pauseAction: CocoaAction? = nil,
gameUnitManager: GameUnitManagerType,
timeManager: TimeManagerType = TimeManager(),
gameSoundStation: GameSoundEffectStation = GameSoundEffectStation()) {
self.storage = storage
self.gameUnitManager = gameUnitManager
self.timeManager = timeManager
self.gameSoundStation = gameSoundStation
super.init(sceneCoordinator: sceneCoordinator, storage: storage)
super.init(sceneCoordinator: sceneCoordinator)
}
}

Expand Down Expand Up @@ -204,15 +206,18 @@ private extension GameViewModel {
@discardableResult
private func toGameOverScene() -> Completable {
let currentScore = try? currentScore.value()
let gameOverViewModel = GameOverViewModel(sceneCoordinator: sceneCoordinator, storage: storage, finalScore: currentScore ?? 0, newGameStatus: newGameStatus)
let gameOverViewModel = GameOverViewModel(sceneCoordinator: sceneCoordinator,
storage: storage as! (GameMoneyManagable & HighScoreManagable),
finalScore: currentScore ?? 0,
newGameStatus: newGameStatus)
let gameOverScene = GameScene.gameOver(gameOverViewModel)
return self.sceneCoordinator.transition(to: gameOverScene, using: .pop, with: StoryboardType.game, animated: true)
}

@discardableResult
private func toPauseScene() -> Completable {
let currentScore = try? currentScore.value()
let pauseViewModel = PauseViewModel(sceneCoordinator: sceneCoordinator, storage: storage, currentScore: currentScore ?? 0, newGameStatus: newGameStatus)
let pauseViewModel = PauseViewModel(sceneCoordinator: sceneCoordinator, currentScore: currentScore ?? 0, newGameStatus: newGameStatus)
let pauseScene = GameScene.pause(pauseViewModel)
return self.sceneCoordinator.transition(to: pauseScene, using: .fullScreen, with: StoryboardType.game, animated: false)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ final class HowToPlayViewModel: CommonViewModel {
let currentPage = BehaviorRelay<Int>(value: 0)
let currentManual = BehaviorRelay<Manual>(value: Manual.all[0])

init(sceneCoordinator: SceneCoordinatorType, storage: StorageType, cancelAction: CocoaAction? = nil) {
init(sceneCoordinator: SceneCoordinatorType, cancelAction: CocoaAction? = nil) {
self.cancelAction = CocoaAction {
if let action = cancelAction {
action.execute(())
}
return sceneCoordinator.close(animated: true).asObservable().map { _ in }
}
super.init(sceneCoordinator: sceneCoordinator, storage: storage)
super.init(sceneCoordinator: sceneCoordinator)
}

func moveToPage(from direction: DirectionType) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ import Action

final class ItemViewModel: CommonViewModel {

private let storage: GameItemManagable & GameMoneyManagable

var defaultUnit: Unit {
return storage.itemList().first!
}
Expand All @@ -25,17 +27,18 @@ final class ItemViewModel: CommonViewModel {
private let soundEffectStation: SingleSoundEffectStation

init(sceneCoordinator: SceneCoordinatorType,
storage: StorageType,
storage: GameItemManagable & GameMoneyManagable,
cancelAction: CocoaAction? = nil,
soundEffectType: MainSoundEffect = .upgrade) {
self.storage = storage
self.cancelAction = CocoaAction {
if let action = cancelAction {
action.execute(())
}
return sceneCoordinator.close(animated: true).asObservable().map { _ in }
}
self.soundEffectStation = SingleSoundEffectStation(soundEffectType: soundEffectType)
super.init(sceneCoordinator: sceneCoordinator, storage: storage)
super.init(sceneCoordinator: sceneCoordinator)
}

func checkLevelUpPrice() {
Expand Down
Loading