OSDN Git Service

分岐係数込みの判定式(33)の値が誤っていたので修正
[kcd/KCD.git] / KCD / ShipViewController.swift
1 //
2 //  ShipViewController.swift
3 //  KCD
4 //
5 //  Created by Hori,Masaki on 2016/12/25.
6 //  Copyright © 2016年 Hori,Masaki. All rights reserved.
7 //
8
9 import Cocoa
10
11 private enum ViewType: Int {
12     
13     case exp
14     
15     case power
16     
17     case power2
18     
19     case power3
20 }
21
22 /// 2018.02.24
23 /// #keyPath(Ship.master_ship.soku)がkeyであるNSSortDescriptorが含まれるとクラッシュする可能性があるため
24 /// 新設した#keyPath(Ship.soku)をkeyにするように書き換える
25 private func exchangeSortKey(original: [NSSortDescriptor]) -> [NSSortDescriptor] {
26     
27     return original
28         .map { sortDesc -> NSSortDescriptor in
29             
30             if sortDesc.key == #keyPath(Ship.master_ship.soku) {
31                 
32                 return NSSortDescriptor(key: #keyPath(Ship.soku), ascending: sortDesc.ascending)
33             }
34             
35             return sortDesc
36     }
37 }
38
39 final class ShipViewController: MainTabVIewItemViewController {
40     
41     @objc let managedObjectContext = ServerDataStore.default.context
42     
43     @IBOutlet private var shipController: NSArrayController!
44     @IBOutlet private var expTableView: NSScrollView!
45     @IBOutlet private var powerTableView: NSScrollView!
46     @IBOutlet private var power2TableView: NSScrollView!
47     @IBOutlet private var power3TableView: NSScrollView!
48     @IBOutlet private weak var standardDeviationField: NSTextField!
49     
50     private var sortDescriptorsObservation: NSKeyValueObservation?
51     private var arrangedObjectsObservation: NSKeyValueObservation?
52     
53     private var notificationObserver = NotificationObserver()
54     
55     override var nibName: NSNib.Name {
56         
57         return .nibName(instanceOf: self)
58     }
59     
60     override var hasShipTypeSelector: Bool { return true }
61     override var selectedShipType: ShipTabType {
62         
63         didSet {
64             
65             shipController.filterPredicate = shipTypePredicte(for: selectedShipType)
66             shipController.rearrangeObjects()
67         }
68     }
69     
70     @objc var standardDeviation: Double {
71         
72         guard let ships = shipController.arrangedObjects as? [Ship], !ships.isEmpty else {
73             
74             return 0.0
75         }
76         guard let avg = shipController.value(forKeyPath: "arrangedObjects.@avg.lv") as? Double else {
77             
78             return 0.0
79         }
80         
81         let total = ships.reduce(0.0) {
82             
83             let delta = Double($1.lv) - avg
84             
85             return $0 + delta * delta
86         }
87         
88         return sqrt(total / Double(ships.count))
89     }
90     
91 //    @objc dynamic var sortDescriptors: [NSSortDescriptor] {
92 //        get { return UserDefaults.standard[.shipviewSortDescriptors] }
93 //        set { UserDefaults.standard[.shipviewSortDescriptors] = sortDescriptors }
94 //    }
95     
96     private weak var currentTableView: NSView?
97     
98     override func viewDidLoad() {
99         
100         super.viewDidLoad()
101         
102         currentTableView = expTableView
103         
104         do {
105             
106             try shipController.fetch(with: nil, merge: true)
107             
108         } catch {
109             
110             fatalError("ShipViewController: can not fetch. \(error)")
111             
112         }
113         
114         shipController.sortDescriptors = exchangeSortKey(original: UserDefaults.standard[.shipviewSortDescriptors])
115
116         sortDescriptorsObservation = shipController.observe(\NSArrayController.sortDescriptors) { [weak self] _, _ in
117
118             UserDefaults.standard[.shipviewSortDescriptors] = self?.shipController.sortDescriptors ?? []
119         }
120         arrangedObjectsObservation = shipController.observe(\NSArrayController.arrangedObjects) { [weak self] _, _ in
121             
122             self?.notifyChangeValue(forKey: #keyPath(standardDeviation))
123         }
124         
125         let tableViews = [expTableView, powerTableView, power2TableView, power3TableView]
126         tableViews
127             .forEach {
128                 
129                 notificationObserver
130                     .addObserver(forName: NSScrollView.didEndLiveScrollNotification, object: $0, queue: .main) {
131                         
132                         guard let target = $0.object as? NSScrollView else {
133                             
134                             return
135                         }
136                         
137                         let visibleRect = target.documentVisibleRect
138                         tableViews
139                             .filter { $0 != target }
140                             .forEach { $0?.documentView?.scrollToVisible(visibleRect) }
141                 }
142         }
143         #if DEBUG
144             standardDeviationField.isHidden = false
145         #endif
146     }
147     
148     private func showView(with type: ViewType) {
149         
150         let newSelection: NSView = {
151             
152             switch type {
153                 
154             case .exp: return expTableView
155                 
156             case .power: return powerTableView
157                 
158             case .power2: return power2TableView
159                 
160             case .power3: return power3TableView
161                 
162             }
163         }()
164         
165         if currentTableView == newSelection {
166             
167             return
168         }
169         
170         guard let tableView = currentTableView else {
171             
172             return
173         }
174         
175         newSelection.frame = tableView.frame
176         newSelection.autoresizingMask = tableView.autoresizingMask
177         view.replaceSubview(tableView, with: newSelection)
178         view.window?.makeFirstResponder(newSelection)
179         currentTableView = newSelection
180     }
181     
182     private func tag(_ sender: AnyObject?) -> Int {
183         
184         switch sender {
185             
186         case let segmented as NSSegmentedControl:
187             let cell = segmented.cell as? NSSegmentedCell
188             
189             return cell?.tag(forSegment: segmented.selectedSegment) ?? -1
190             
191         case let control as NSControl:
192             
193             return control.tag
194             
195         default:
196             
197             return -1
198             
199         }
200     }
201     
202     @IBAction func changeView(_ sender: AnyObject?) {
203         
204         ViewType(rawValue: tag(sender)).map(showView)
205     }
206 }
207
208 extension ShipViewController: NSTableViewDelegate {
209     
210     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
211         
212         guard let identifier = tableColumn?.identifier else {
213             
214             return nil
215         }
216         
217         return tableView.makeView(withIdentifier: identifier, owner: nil)
218     }
219 }