2 // StrengthenListViewController.swift
5 // Created by Hori,Masaki on 2016/12/25.
6 // Copyright © 2016年 Hori,Masaki. All rights reserved.
11 private let resourceName = "EnhancementListItem2"
12 private let resourceExtension = "plist"
15 private struct FilterCategories {
17 static let allType: [EquipmentType] = (1...100).compactMap { EquipmentType(rawValue: $0) }
18 static let canonType: [EquipmentType] = [.smallCaliberMainGun, .mediumCaliberMainGun,
19 .largeCaliberMainGun, .largeCaliberMainGunII]
20 static let torpedoType: [EquipmentType] = [.secondaryGun, .torpedo,
21 .antiAircraftGun, .antiSunmrinerSercher, .submarinTorpedo,
23 static let airplaneType: [EquipmentType] = [.fighter, .bomber, .attacker, .searcher,
24 .airplaneSearcher, .airplaneBomber,
25 .largeAirplane, .airplaneFighter,
26 .landAttecker, .localFighter,
27 .jetFighter, .jetBomber,
28 .jetAttacker, .jetSearcher,
30 static let radarType: [EquipmentType] = [.smallRadar, .largeRadar,
33 static let otherType: [EquipmentType] = {
36 .filter { !canonType.contains($0) }
37 .filter { !torpedoType.contains($0) }
38 .filter { !airplaneType.contains($0) }
39 .filter { !radarType.contains($0) }
42 enum FilterType: Int {
57 let categories: [EquipmentType]
59 init(type: FilterType) {
63 case .all: categories = FilterCategories.allType
65 case .canon: categories = FilterCategories.canonType
67 case .torpedo: categories = FilterCategories.torpedoType
69 case .airplane: categories = FilterCategories.airplaneType
71 case .radar: categories = FilterCategories.radarType
73 case .other: categories = FilterCategories.otherType
79 final class StrengthenListViewController: MainTabVIewItemViewController {
81 @IBOutlet private weak var tableView: NSTableView!
83 @objc dynamic var itemList: Any { return filteredItems as Any }
84 @objc dynamic var offsetDay: Int = 0 {
86 didSet { buildList() }
88 @objc dynamic var filterType: Int = 0 {
92 if let t = FilterCategories.FilterType(rawValue: filterType) {
94 showsTypes = FilterCategories(type: t).categories
98 showsTypes = FilterCategories.allType
104 override var nibName: NSNib.Name {
106 return .nibName(instanceOf: self)
109 private var filteredItems: [StrengthenListItem] = [] {
111 willSet { willChangeValue(forKey: #keyPath(itemList)) }
112 didSet { didChangeValue(forKey: #keyPath(itemList)) }
115 private let itemListBuildNotifier = PeriodicNotifier(hour: 0, minutes: 0)
116 private let plistDownloadNotifier = PeriodicNotifier(hour: 23, minutes: 55)
117 private let downloader = EnhancementListItemDownloader(name: resourceName, extension: resourceExtension)
118 private var equipmentStrengthenList: [EnhancementListItem] = []
119 private var showsTypes: [EquipmentType] = FilterCategories.allType
121 override func viewDidLoad() {
125 if let url = Bundle.main.url(forResource: resourceName, withExtension: resourceExtension),
126 let data = try? Data(contentsOf: url) {
128 guard let array = NSKeyedUnarchiver.unarchiveObject(with: data) as? [EnhancementListItem] else {
130 Logger.shared.log("\(resourceName).\(resourceExtension) not found.")
135 equipmentStrengthenList = array
139 let nc = NotificationCenter.default
140 nc.addObserver(forName: .Periodic, object: itemListBuildNotifier, queue: nil) { [weak self] _ in
145 nc.addObserver(forName: .Periodic, object: plistDownloadNotifier, queue: nil) { [weak self] _ in
147 self?.downloadPList()
157 private func weekdayFiltered() -> [EnhancementListItem] {
164 let currentDay = NSCalendar.current.dateComponents([.weekday], from: Date())
165 var targetWeekday = currentDay.weekday! + offsetDay
166 if targetWeekday > 7 {
171 return equipmentStrengthenList.filter { $0.weekday == targetWeekday }
174 private func convert(items: [EnhancementListItem]) -> [StrengthenListItem] {
176 guard let item = items.first else { return [] }
178 let group: StrengthenListItem = StrengthenListGroupItem(type: item.equipmentType)
179 let items: [StrengthenListItem] = items.map(StrengthenListEnhancementItem.init(item:))
181 return [group] + items
184 private func buildList() {
186 let filtered = weekdayFiltered()
187 filteredItems = filtered
188 .map { $0.equipmentType }
190 .filter { showsTypes.contains($0) }
191 .map { type in filtered.filter { $0.equipmentType == type } }
195 private func downloadPList() {
197 downloader.download { [weak self] items in
199 DispatchQueue.main.async {
201 self?.equipmentStrengthenList = items
207 private func packSecondShipName(_ items: [EnhancementListItem]) -> [String] {
209 return items.flatMap { $0.secondsShipNames }.unique()
212 private func allItemList() -> [EnhancementListItem] {
214 return equipmentStrengthenList
215 .map { $0.identifier }
217 .map { identifier in equipmentStrengthenList.filter { $0.identifier == identifier } }
218 .compactMap { $0.first?.replace(secondsShipNames: packSecondShipName($0)) }
222 extension StrengthenListViewController: NSTableViewDelegate {
224 func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView? {
226 let item = filteredItems[row]
228 return item.cellType.makeCellWithItem(item: item, tableView: tableView, owner: nil)
231 func tableView(_ tableView: NSTableView, isGroupRow row: Int) -> Bool {
233 return filteredItems[row] is StrengthenListGroupItem
236 func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
238 let item = filteredItems[row]
240 return item.cellType.estimateCellHeightForItem(item: item, tableView: tableView)