OSDN Git Service

staticプロパティをインスタンスプロパティに変更
[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             
31             delegate?.didChangeState(deck: deck)
32         }
33     }
34     
35     init(deck: Deck) {
36         
37         self.deck = deck
38         
39         observation = deck.observe(\Deck.mission_2) { _, _ in
40             
41             self.delegate?.didChangeState(deck: deck)
42         }
43     }
44 }
45
46 final class MissionStatus: NSObject {
47     
48     private enum State: Int {
49         
50         case none = 0
51         
52         case hasMission = 1
53         
54         case finish = 2
55         
56         case earlyReturn = 3
57         
58         case unknown = 999999
59     }
60     
61     static func valid(number: Int) -> Bool {
62         
63         return 2...4 ~= number
64     }
65     
66     let number: Int
67     private let observer: DeckMissionObserver
68     
69     private(set) var name: String?
70     private(set) var time: TimeInterval?
71     
72     private var state: State = .unknown
73     private var rawState: Int = 0 {
74         
75         didSet {
76             
77             state = State(rawValue: rawState) ?? .unknown
78         }
79     }
80     private var missionId: Int = 0
81     private var milliseconds: Int = 0
82     private var fleetName: String = ""
83     
84     private var didNotify = false
85     
86     weak var delegate: MissionStatusObserver?
87     
88     /// CAUTION: 初回起動時/マスタ更新時にはデータがないので失敗する
89     init?(number: Int) {
90         
91         guard MissionStatus.valid(number: number) else {
92             
93             return nil
94         }
95         
96         self.number = number
97         
98         guard let deck = ServerDataStore.default.deck(by: number) else {
99             
100             return nil
101         }
102         
103         self.observer = DeckMissionObserver(deck: deck)
104         
105         super.init()
106         
107         observer.delegate = self
108     }
109     
110     private func updateState() {
111         
112         switch state {
113             
114         case .none, .finish:
115             didNotify = false
116             name = nil
117             time = nil
118             
119         case .hasMission, .earlyReturn:
120             name = ServerDataStore.default.masterMission(by: missionId)?.name ?? "Unknown"
121             
122         case .unknown:
123             Logger.shared.log("unknown State")
124             
125         }
126         
127         delegate?.didUpdate(state: self)
128     }
129 }
130
131 extension MissionStatus: DockInformationUpdater {
132     
133     func update() {
134         
135         defer {
136             
137             delegate?.didUpdate(state: self)
138         }
139         
140         guard let name = name else {
141             
142             return
143         }
144         
145         let compTime = TimeInterval(Int(milliseconds / 1_000))
146         let diff = compTime - Date().timeIntervalSince1970
147         
148         // set to 0. if diff is less than 0.
149         time = max(0, diff)
150         
151         // notify UserNotification.
152         if didNotify {
153             
154             return
155         }
156         if diff >= 1 * 60 {
157             
158             return
159         }
160         
161         let notification = NSUserNotification()
162         let format = LocalizedStrings.missionWillReturnMessage.string
163         notification.title = String(format: format, fleetName)
164         let txtFormat = LocalizedStrings.missionWillReturnInformation.string
165         notification.informativeText = String(format: txtFormat, fleetName, name)
166         
167         if UserDefaults.standard[.playFinishMissionSound] {
168             
169             notification.soundName = NSUserNotificationDefaultSoundName
170         }
171         
172         NSUserNotificationCenter.default.deliver(notification)
173         
174         didNotify = true
175     }
176 }
177
178 extension MissionStatus: DeckMissionObserverDelegate {
179     
180     func didChangeState(deck: Deck) {
181         
182         rawState = deck.mission_0
183         missionId = deck.mission_1
184         milliseconds = deck.mission_2
185         fleetName = deck.name
186         
187         updateState()
188     }
189 }