F4E5FF121E17D6850026868C /* GameViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E5FF111E17D6850026868C /* GameViewController.swift */; };
F4E5FF141E17F93B0026868C /* BroserWindowController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4E5FF131E17F93B0026868C /* BroserWindowController.swift */; };
F4E7802E18DC3AF00011BC4C /* LocalData.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F4E7802C18DC3AF00011BC4C /* LocalData.xcdatamodeld */; };
+ F4EE4AD81F18F43700AD92B4 /* DeckBuilderStructure.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4EE4AD71F18F43700AD92B4 /* DeckBuilderStructure.swift */; };
+ F4EE4ADA1F18F66A00AD92B4 /* DeckBuilder.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4EE4AD91F18F66A00AD92B4 /* DeckBuilder.swift */; };
F4EFBCA51E7D757E00DE4A58 /* SwiftyJSON.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F4EFBCA21E7D439A00DE4A58 /* SwiftyJSON.framework */; };
F4EFBCA61E7D757E00DE4A58 /* SwiftyJSON.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = F4EFBCA21E7D439A00DE4A58 /* SwiftyJSON.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
F4F947071D5DBA2D00F95998 /* MapWindowController.xib in Resources */ = {isa = PBXBuildFile; fileRef = F4F947091D5DBA2D00F95998 /* MapWindowController.xib */; };
F4E5FF111E17D6850026868C /* GameViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GameViewController.swift; sourceTree = "<group>"; };
F4E5FF131E17F93B0026868C /* BroserWindowController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BroserWindowController.swift; sourceTree = "<group>"; };
F4E7802D18DC3AF00011BC4C /* LocalData.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = LocalData.xcdatamodel; sourceTree = "<group>"; };
+ F4EE4AD71F18F43700AD92B4 /* DeckBuilderStructure.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeckBuilderStructure.swift; sourceTree = "<group>"; };
+ F4EE4AD91F18F66A00AD92B4 /* DeckBuilder.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DeckBuilder.swift; sourceTree = "<group>"; };
F4EFBCA21E7D439A00DE4A58 /* SwiftyJSON.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftyJSON.framework; path = Carthage/Build/Mac/SwiftyJSON.framework; sourceTree = "<group>"; };
F4F947061D5DBA1A00F95998 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/UITestWindowController.xib; sourceTree = "<group>"; };
F4F947081D5DBA2D00F95998 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MapWindowController.xib; sourceTree = "<group>"; };
F44AA26A1E82AD2E00EED8BE /* NSObjectExtension.swift */,
F44775881EF6AAD900287572 /* SakutekiCalculator.swift */,
F42546911EF8002E00BE297E /* EquitType.swift */,
+ F4EE4AD71F18F43700AD92B4 /* DeckBuilderStructure.swift */,
+ F4EE4AD91F18F66A00AD92B4 /* DeckBuilder.swift */,
F4BEEFE21B0CD39B004702B8 /* Transformar&Formatter */,
F4C118F318A67B05005D5B25 /* CustomHTTPProtocol */,
F47215A11E1F38280083D3BC /* Queue.swift */,
F4E5FF141E17F93B0026868C /* BroserWindowController.swift in Sources */,
F4CF25BA1E34EB6600C02A66 /* BookmarkManager.swift in Sources */,
F44BC7051E2660E4004644E3 /* StoreCreateSlotItemHistoryCommand.swift in Sources */,
+ F4EE4ADA1F18F66A00AD92B4 /* DeckBuilder.swift in Sources */,
F4E5FF061E1523900026868C /* ScreenshotCollectionViewItem.swift in Sources */,
F4D3D9551E8544B90085A389 /* StrengthenListItem.swift in Sources */,
F44BC6DF1E228770004644E3 /* QuestListCommand.swift in Sources */,
F42A8FDE1E40C6DF0099DC1D /* Quest.swift in Sources */,
F4B15CBD1E21BA870078CFFC /* CommandRegister.swift in Sources */,
F4BDEEB01E72D2D700D689AE /* HistoryTableViewController.swift in Sources */,
+ F4EE4AD81F18F43700AD92B4 /* DeckBuilderStructure.swift in Sources */,
F45FBB921E129BAE000E72B9 /* FleetViewController.swift in Sources */,
F4AA59501E1E4D18001667AF /* ShipWindowController.swift in Sources */,
F42CFE181E3C12AA000B4F9B /* ScreenshotInformation.swift in Sources */,
windowManager.openDocument(sender)
}
+ @IBAction func openInDeckBuilder(_ sender: Any?) {
+
+ DeckBuilder().openDeckBuilder()
+ }
+
override func validateMenuItem(_ menuItem: NSMenuItem) -> Bool {
guard let action = menuItem.action else { return false }
switch action {
return true
case Selector.removeDatabaseFile:
return true
+ case #selector(openInDeckBuilder(_:)):
+ return true
default:
return windowManager.validateMenuItem(menuItem)
}
<action selector="openNewBrowser:" target="-1" id="gnv-IH-H9F"/>
</connections>
</menuItem>
+ <menuItem isSeparatorItem="YES" id="Btg-ej-IXz"/>
+ <menuItem title="Open in DeckBuilder" id="oGw-ne-id0">
+ <modifierMask key="keyEquivalentModifierMask"/>
+ <connections>
+ <action selector="openInDeckBuilder:" target="494" id="lsj-Oj-nEf"/>
+ </connections>
+ </menuItem>
<menuItem isSeparatorItem="YES" id="8zj-xF-FZU"/>
<menuItem title="Close" keyEquivalent="w" id="73">
<connections>
guard let shipId = shipId(of: index) else { return nil }
return ship(ofId: shipId)
}
+
+ subscript(_ range: CountableClosedRange<Int>) -> [Ship] {
+ return range.flatMap { self[$0] }
+ }
}
--- /dev/null
+//
+// DeckBuilder.swift
+// KCD
+//
+// Created by Hori,Masaki on 2017/07/14.
+// Copyright © 2017年 Hori,Masaki. All rights reserved.
+//
+
+import Cocoa
+
+class DeckBuilder {
+
+ private let structure: DeckBuilderStructure
+
+ init() {
+
+ structure = DeckBuilder.build()
+ }
+
+ func openDeckBuilder() {
+
+ // use for encodeURIComponent() of Javascript
+ var characterSet = CharacterSet.alphanumerics
+ characterSet.insert(charactersIn: "-_.!~*'()")
+
+ let desc = structure.deckDescription
+ Debug.excute(level: .debug) { print(desc as Any) }
+ let ss = "http://kancolle-calc.net/deckbuilder.html?predeck="
+
+ if let param = desc.addingPercentEncoding(withAllowedCharacters: characterSet),
+ let url = URL(string: ss + param) {
+
+ NSWorkspace.shared().open(url)
+ }
+ }
+
+ private static func build() -> DeckBuilderStructure {
+
+ let fleets = ServerDataStore.default
+ .decksSortedById()
+ .map(buildDeck)
+ let hqLv = ServerDataStore.default.basic()?.level
+
+ return DeckBuilderStructure(hqLv: hqLv, fleets: fleets)
+ }
+
+ private static func buildDeck(deck: Deck) -> DBFleet {
+
+ let ships = deck[0...5].map(buildShip)
+
+ return DBFleet(ships: ships)
+ }
+
+ private static func buildShip(ship: Ship) -> DBShip {
+
+ let items = ship
+ .equippedItem
+ .flatMap { $0 as? SlotItem }
+ .flatMap(buildItem)
+ let exItem = ship.extraItem.map(buildItem)
+
+ return DBShip(id: ship.master_ship.id,
+ lv: ship.lv,
+ luck: ship.lucky_0,
+ items: items,
+ exItem: exItem)
+ }
+
+ private static func buildItem(item: SlotItem) -> DBItem {
+
+ return DBItem(id: item.master_slotItem.id,
+ lv: item.level != 0 ? item.level : nil,
+ aLv: item.alv != 0 ? item.alv : nil)
+ }
+}
--- /dev/null
+//
+// DeckBuilderStructure.swift
+// KCD
+//
+// Created by Hori,Masaki on 2017/07/14.
+// Copyright © 2017年 Hori,Masaki. All rights reserved.
+//
+
+import Foundation
+
+protocol DeckBuilderDescriptable {
+ var deckDescription: String { get }
+}
+
+struct DeckBuilderStructure {
+ let version: Int = 4
+ let hqLv: Int?
+ let fleets: [DBFleet]
+}
+
+struct DBFleet {
+ let ships: [DBShip]
+}
+
+struct DBShip {
+ let id: Int
+ let lv: Int
+ let luck: Int
+ let items: [DBItem]
+ let exItem: DBItem?
+}
+
+struct DBItem {
+ let id: Int
+ let lv: Int?
+ let aLv: Int?
+}
+
+extension DeckBuilderStructure: DeckBuilderDescriptable {
+ var deckDescription: String {
+
+ let verStr = "\"version\":\(version)"
+ let fleetStr = zip(1...4, fleets)
+ .map { "\"f\($0.0)\":{\($0.1.deckDescription)}" }
+ .joined(separator: ",")
+ let hqLvStr = hqLv.map { "\"hqlv\":\($0)" }
+
+ let join = [verStr, fleetStr, hqLvStr]
+ .flatMap { $0 }
+ .joined(separator: ",")
+
+ return "{\(join)}"
+ }
+}
+
+extension DBFleet: DeckBuilderDescriptable {
+ var deckDescription: String {
+
+ return zip(1...6, ships)
+ .map { "\"s\($0.0)\":{\($0.1.deckDescription)}" }
+ .joined(separator: ",")
+ }
+}
+
+extension DBShip: DeckBuilderDescriptable {
+ var deckDescription: String {
+
+ return "\"id\":\"\(id)\",\"lv\":\(lv),\"luck\":\(luck),\"items\":{\(fullItemDesc)}"
+ }
+
+ private var fullItemDesc: String {
+
+ switch (items, exDesc) {
+ case let (items, ex?) where items.isEmpty: return ex
+ case let (_, ex?): return "\(itemsDesc),\(ex)"
+ default: return itemsDesc
+ }
+ }
+
+ private var itemsDesc: String {
+
+ return zip(1...4, items)
+ .map { "\"i\($0.0)\":{\($0.1.deckDescription)}" }
+ .joined(separator: ",")
+ }
+
+ private var exDesc: String? {
+
+ return exItem.map { "\"ix\":{\($0.deckDescription)}" }
+ }
+}
+
+extension DBItem: DeckBuilderDescriptable {
+ var deckDescription: String {
+
+ switch (lv, aLv) {
+ case let (lv?, aLv?): return "\"id\":\(id),\"rf\":\(lv),\"mas\":\(aLv)"
+ case let (lv?, _): return "\"id\":\(id),\"rf\":\(lv)"
+ case let (_, aLv?): return "\"id\":\(id),\"mas\":\(aLv)"
+ default: return "\"id\":\(id)"
+ }
+ }
+}
guard let decks = try? objects(with: Deck.entity, predicate: predicate),
let deck = decks.first
else { return [] }
- return (0..<6).flatMap { deck[$0] }
+ return deck[0...5]
}
func ship(by shipId: Int) -> Ship? {
if shipId < 1 { return nil }
"wbG-TI-Ox5.title" = "判定式 (33) - 4";
"z7j-YG-JPw.title" = "判定式 (33) ...";
-
-
-
-
+"oGw-ne-id0.title" = "デッキビルダーで開く";