OSDN Git Service

処理をわかりやすくした
[kcd/KCD.git] / KCD / MissionStatus.swift
1
2 //
3 //  MissionStatus.swift
4 //  KCD
5 //
6 //  Created by Hori,Masaki on 2017/01/23.
7 //  Copyright © 2017年 Hori,Masaki. All rights reserved.
8 //
9
10 import Cocoa
11
12 protocol MissionStatusObserver: class {
13     
14     func didUpdate(state: MissionStatus)
15 }
16
17 protocol DeckMissionObserverDelegate: class {
18     
19     func didChangeState(deck: Deck)
20 }
21
22 final class DeckMissionObserver {
23     
24     private let deck: Deck
25     private var observation: NSKeyValueObservation?
26     
27     weak var delegate: DeckMissionObserverDelegate? {
28         
29         didSet {
30             delegate?.didChangeState(deck: deck)
31         }
32     }
33     
34     init(deck: Deck) {
35         
36         self.deck = deck
37         
38         observation = deck.observe(\Deck.mission_2) { _, _ in
39             self.delegate?.didChangeState(deck: deck)
40         }
41     }
42 }
43
44 final class MissionStatus: NSObject {
45     
46     private enum State: Int {
47         
48         case none = 0
49         case hasMission = 1
50         case finish = 2
51         case earlyReturn = 3
52         
53         case unknown = 999999
54     }
55     
56     static func valid(number: Int) -> Bool {
57         
58         return 2...4 ~= number
59     }
60     
61     let number: Int
62     private let observer: DeckMissionObserver
63     
64     private(set) var name: String?
65     private(set) var time: TimeInterval?
66     
67     private var state: State = .unknown
68     private var rawState: Int = 0 {
69         
70         didSet {
71             state = State(rawValue: rawState) ?? .unknown
72         }
73     }
74     private var missionId: Int = 0
75     private var milliseconds: Int = 0
76     private var fleetName: String = ""
77     
78     private var didNotify = false
79     
80     weak var delegate: MissionStatusObserver?
81     
82     /// CAUTION: 初回起動時/マスタ更新時にはデータがないので失敗する
83     init?(number: Int) {
84         
85         guard MissionStatus.valid(number: number) else { return nil }
86         
87         self.number = number
88         
89         guard let deck = ServerDataStore.default.deck(by: number) else { return nil }
90         self.observer = DeckMissionObserver(deck: deck)
91         
92         super.init()
93         
94         observer.delegate = self
95     }
96     
97     private func updateState() {
98         
99         switch state {
100             
101         case .none, .finish:
102             name = nil
103             time = nil
104             
105         case .hasMission, .earlyReturn:
106             name = ServerDataStore.default.masterMission(by: missionId)?.name ?? "Unknown"
107             
108         case .unknown:
109             Logger.shared.log("unknown State")
110         }
111         
112         delegate?.didUpdate(state: self)
113     }
114 }
115
116 extension MissionStatus: DockInformationUpdater {
117     
118     func update() {
119         
120         defer {
121             delegate?.didUpdate(state: self)
122         }
123         
124         guard let name = name else { return }
125         
126         let compTime = TimeInterval(Int(milliseconds / 1_000))
127         let diff = compTime - Date().timeIntervalSince1970
128         
129         // set to 0. if diff is less than 0.
130         time = max(0, diff)
131         
132         // notify UserNotification.
133         if didNotify { return }
134         if diff >= 1 * 60 { return }
135         
136         let notification = NSUserNotification()
137         let format = LocalizedStrings.missionWillReturnMessage.string
138         notification.title = String(format: format, fleetName)
139         let txtFormat = LocalizedStrings.missionWillReturnInformation.string
140         notification.informativeText = String(format: txtFormat, fleetName, name)
141         
142         if UserDefaults.standard[.playFinishMissionSound] {
143             
144             notification.soundName = NSUserNotificationDefaultSoundName
145         }
146         
147         NSUserNotificationCenter.default.deliver(notification)
148         
149         didNotify = true
150     }
151 }
152
153 extension MissionStatus: DeckMissionObserverDelegate {
154     
155     func didChangeState(deck: Deck) {
156         
157         rawState = deck.mission_0
158         missionId = deck.mission_1
159         milliseconds = deck.mission_2
160         fleetName = deck.name
161         
162         updateState()
163     }
164 }