OSDN Git Service

Doutakuを導入
[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             didNotify = false
103             name = nil
104             time = nil
105             
106         case .hasMission, .earlyReturn:
107             name = ServerDataStore.default.masterMission(by: missionId)?.name ?? "Unknown"
108             
109         case .unknown:
110             Logger.shared.log("unknown State")
111         }
112         
113         delegate?.didUpdate(state: self)
114     }
115 }
116
117 extension MissionStatus: DockInformationUpdater {
118     
119     func update() {
120         
121         defer {
122             delegate?.didUpdate(state: self)
123         }
124         
125         guard let name = name else { return }
126         
127         let compTime = TimeInterval(Int(milliseconds / 1_000))
128         let diff = compTime - Date().timeIntervalSince1970
129         
130         // set to 0. if diff is less than 0.
131         time = max(0, diff)
132         
133         // notify UserNotification.
134         if didNotify { return }
135         if diff >= 1 * 60 { return }
136         
137         let notification = NSUserNotification()
138         let format = LocalizedStrings.missionWillReturnMessage.string
139         notification.title = String(format: format, fleetName)
140         let txtFormat = LocalizedStrings.missionWillReturnInformation.string
141         notification.informativeText = String(format: txtFormat, fleetName, name)
142         
143         if UserDefaults.standard[.playFinishMissionSound] {
144             
145             notification.soundName = NSUserNotificationDefaultSoundName
146         }
147         
148         NSUserNotificationCenter.default.deliver(notification)
149         
150         didNotify = true
151     }
152 }
153
154 extension MissionStatus: DeckMissionObserverDelegate {
155     
156     func didChangeState(deck: Deck) {
157         
158         rawState = deck.mission_0
159         missionId = deck.mission_1
160         milliseconds = deck.mission_2
161         fleetName = deck.name
162         
163         updateState()
164     }
165 }