OSDN Git Service

洋上補給の補強増設用のショートネームをつけた
[kcd/KCD.git] / KCD / StrengthenListViewController.swift
1 //
2 //  StrengthenListViewController.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 let resourceName = "EnhancementListItem2"
12 private let resourceExtension = "plist"
13
14
15 private struct FilterCategories {
16     
17     static let allType: [EquipmentType] = (1...100).flatMap { EquipmentType(rawValue: $0) }
18     static let canonType: [EquipmentType] = [.smallCaliberMainGun, .mediumCaliberMainGun,
19                                              .largeCaliberMainGun, .largeCaliberMainGunII]
20     static let torpedoType: [EquipmentType] = [.secondaryGun, .torpedo,
21                                                .antiAircraftGun, .antiSunmrinerSercher, .submarinTorpedo,
22                                                .largeSonar]
23     static let airplaneType: [EquipmentType] = [.fighter, .bomber, .attacker, .searcher,
24                                                 .airplaneSearcher, .airplaneBomber,
25                                                 .largeAirplane, .airplaneFighter,
26                                                 .landAttecker, .localFighter,
27                                                 .jetFighter, .jetBomber,
28                                                 .jetAttacker, .jetSearcher,
29                                                 .searcherII]
30     static let radarType: [EquipmentType] = [.smallRadar, .largeRadar,
31                                              .sonar, .depthCharge,
32                                              .submarineEquipment]
33     static let otherType: [EquipmentType] = {
34         return allType
35             .filter { !canonType.contains($0) }
36             .filter { !torpedoType.contains($0) }
37             .filter { !airplaneType.contains($0) }
38             .filter { !radarType.contains($0) }
39     }()
40     
41     enum FilterType: Int {
42         
43         case all = 0
44         case canon
45         case torpedo
46         case airplane
47         case radar
48         case other
49     }
50     
51     let categories: [EquipmentType]
52     
53     init(type: FilterType) {
54         
55         switch type {
56         case .all: categories = FilterCategories.allType
57         case .canon: categories = FilterCategories.canonType
58         case .torpedo: categories = FilterCategories.torpedoType
59         case .airplane: categories = FilterCategories.airplaneType
60         case .radar: categories = FilterCategories.radarType
61         case .other: categories = FilterCategories.otherType
62         }
63     }
64 }
65
66 final class StrengthenListViewController: MainTabVIewItemViewController {
67     
68     @IBOutlet private weak var tableView: NSTableView!
69     
70     @objc dynamic var itemList: Any { return filteredItems as Any }
71     @objc dynamic var offsetDay: Int = 0 {
72         
73         didSet { buildList() }
74     }
75     @objc dynamic var filterType: Int = 0 {
76         
77         didSet {
78             if let t = FilterCategories.FilterType(rawValue: filterType) {
79                 
80                 showsTypes = FilterCategories(type: t).categories
81                 
82             } else {
83                 
84                 showsTypes = FilterCategories.allType
85             }
86             buildList()
87         }
88     }
89     
90     override var nibName: NSNib.Name {
91         
92         return .nibName(instanceOf: self)
93     }
94     
95     private var filteredItems: [StrengthenListItem] = [] {
96         
97         willSet { willChangeValue(forKey: #keyPath(itemList)) }
98         didSet { didChangeValue(forKey: #keyPath(itemList)) }
99     }
100     
101     private let itemListBuildNotifier = PeriodicNotifier(hour: 0, minutes: 0)
102     private let plistDownloadNotifier = PeriodicNotifier(hour: 23, minutes: 55)
103     private let downloader = EnhancementListItemDownloader(name: resourceName, extension: resourceExtension)
104     private var equipmentStrengthenList: [EnhancementListItem] = []
105     private var showsTypes: [EquipmentType] = FilterCategories.allType
106     
107     override func viewDidLoad() {
108         
109         super.viewDidLoad()
110         
111         if let url = Bundle.main.url(forResource: resourceName, withExtension: resourceExtension),
112             let data = try? Data(contentsOf: url) {
113             
114             guard let array = NSKeyedUnarchiver.unarchiveObject(with: data) as? [EnhancementListItem] else {
115                 
116                 return Logger.shared.log("\(resourceName).\(resourceExtension) not found.")
117             }
118             
119             equipmentStrengthenList = array
120             buildList()
121         }
122         
123         let nc = NotificationCenter.default
124         nc.addObserver(forName: .Periodic, object: itemListBuildNotifier, queue: nil) { [weak self] _ in
125             
126             self?.buildList()
127         }
128         
129         nc.addObserver(forName: .Periodic, object: plistDownloadNotifier, queue: nil) { [weak self] _ in
130             
131             self?.downloadPList()
132         }
133         
134         #if DEBUG
135 //          downloadPList()
136         #else
137             downloadPList()
138         #endif
139     }
140     
141     private func weekdayFiltered() -> [EnhancementListItem] {
142         
143         if offsetDay == -1 { return allItemList() }
144         
145         let currentDay = NSCalendar.current.dateComponents([.weekday], from: Date())
146         var targetWeekday = currentDay.weekday! + offsetDay
147         if targetWeekday > 7 { targetWeekday = 1 }
148         
149         return equipmentStrengthenList.filter { $0.weekday == targetWeekday }
150     }
151     
152     private func convert(items: [EnhancementListItem]) -> [StrengthenListItem] {
153         
154         guard let item = items.first else { return [] }
155         
156         let group: StrengthenListItem = StrengthenListGroupItem(type: item.equipmentType)
157         let items: [StrengthenListItem] = items.map(StrengthenListEnhancementItem.init(item:))
158         
159         return [group] + items
160     }
161     
162     private func buildList() {
163         
164         let filtered = weekdayFiltered()
165         filteredItems = filtered
166             .map { $0.equipmentType }
167             .unique()
168             .filter { showsTypes.contains($0) }
169             .map { type in filtered.filter { $0.equipmentType == type } }
170             .flatMap(convert)
171     }
172     
173     private func downloadPList() {
174         
175         downloader.download { [weak self] items in
176             
177             DispatchQueue.main.async {
178                 
179                 self?.equipmentStrengthenList = items
180                 self?.buildList()
181             }
182         }
183     }
184     
185     private func packSecondShipName(_ items: [EnhancementListItem]) -> [String] {
186         
187         return items.flatMap { $0.secondsShipNames }.unique()
188     }
189     
190     private func allItemList() -> [EnhancementListItem] {
191         
192         return equipmentStrengthenList
193             .map { $0.identifier }
194             .unique()
195             .map { identifier in equipmentStrengthenList.filter { $0.identifier == identifier } }
196             .flatMap { $0.first?.replace(secondsShipNames: packSecondShipName($0)) }
197     }
198 }
199
200 extension StrengthenListViewController: NSTableViewDelegate {
201     
202     func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
203         
204         let item = filteredItems[row]
205         return item.cellType.makeCellWithItem(item: item, tableView: tableView, owner: nil)
206     }
207     
208     func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
209         
210         return filteredItems[row] is StrengthenListGroupItem
211     }
212     
213     func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
214         
215         let item = filteredItems[row]
216         
217         return item.cellType.estimateCellHeightForItem(item: item, tableView: tableView)
218     }
219 }