Run golder using sub-process
This commit is contained in:
@@ -178,6 +178,14 @@ extension String {
|
||||
return dateFormatter.date(from: self)
|
||||
}
|
||||
|
||||
public var modelDate: Date? {
|
||||
// ex) 20230628 120657
|
||||
let dateFormatter = DateFormatter()
|
||||
dateFormatter.timeZone = TimeZone(abbreviation: "KST")
|
||||
dateFormatter.dateFormat = "yyyyMMdd HHmmss"
|
||||
return dateFormatter.date(from: self)
|
||||
}
|
||||
|
||||
public var hasComma: Bool {
|
||||
return nil != rangeOfCharacter(from: commaCharSet)
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// IndexResult.swift
|
||||
// KissIndexResult.swift
|
||||
// KissMe
|
||||
//
|
||||
// Created by ened-book-m1 on 2023/06/20.
|
||||
81
KissMe/Sources/Index/Runner.swift
Normal file
81
KissMe/Sources/Index/Runner.swift
Normal file
@@ -0,0 +1,81 @@
|
||||
//
|
||||
// Runner.swift
|
||||
// KissMe
|
||||
//
|
||||
// Created by ened-book-m1 on 2023/06/30.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
|
||||
public protocol Runner {
|
||||
associatedtype KResult: Decodable
|
||||
|
||||
var currentDirectoryUrl: URL { get }
|
||||
var executableUrl: URL { get }
|
||||
|
||||
var outputUrl: URL? { get }
|
||||
var errorUrl: URL? { get }
|
||||
|
||||
func run() async throws
|
||||
}
|
||||
|
||||
|
||||
extension Runner {
|
||||
|
||||
var currentDirectoryUrl: URL { URL.currentDirectory() }
|
||||
|
||||
/*
|
||||
func run() async throws {
|
||||
return try await withUnsafeThrowingContinuation { continuation in
|
||||
let model = args[0]
|
||||
|
||||
let outputUrl = KissGolder.matrixLogFile(date: date)
|
||||
FileManager.default.createFile(atPath: outputUrl.path, contents: nil)
|
||||
let output = FileHandle(forWritingAtPath: outputUrl.path)
|
||||
|
||||
if let outputUrl = outputUrl {
|
||||
|
||||
}
|
||||
|
||||
let task = Process()
|
||||
task.currentDirectoryURL = currentDirectoryUrl
|
||||
task.executableURL = executableUrl
|
||||
task.arguments = args
|
||||
task.standardOutput = output
|
||||
task.standardError = FileHandle.standardError
|
||||
|
||||
printError("curPath: \(task.currentDirectoryPath)")
|
||||
printError("runPath: \(runUrl.path)")
|
||||
printError("args: \(args)")
|
||||
|
||||
do {
|
||||
try task.run()
|
||||
task.waitUntilExit()
|
||||
} catch {
|
||||
printError("run error \(error)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
|
||||
try? output?.close()
|
||||
|
||||
guard let data = try? Data(contentsOf: outputUrl) else {
|
||||
continuation.resume(throwing: GeneralError.emptyData(model))
|
||||
return
|
||||
}
|
||||
if data.isEmpty {
|
||||
continuation.resume(throwing: GeneralError.emptyData(model))
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let matrixResult = try JSONDecoder().decode(KissMatrixResult.self, from: data)
|
||||
continuation.resume(returning: matrixResult)
|
||||
} catch {
|
||||
printError("jsonError \(model)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -6,11 +6,245 @@
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import KissMe
|
||||
|
||||
|
||||
class KissMatrix {
|
||||
class KissGolder {
|
||||
|
||||
func run() {
|
||||
print("hello..")
|
||||
|
||||
func printUsage() {
|
||||
let appName = (CommandLine.arguments[0] as NSString).lastPathComponent
|
||||
printError("\(appName) [sim|run] golder.json")
|
||||
}
|
||||
|
||||
guard CommandLine.argc >= 3 else {
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
|
||||
let mode = RunMode(rawValue: CommandLine.arguments[1])
|
||||
|
||||
let golderJson = CommandLine.arguments[2]
|
||||
guard let model = loadModel(golderJson) else { return }
|
||||
printError("Loaded \(golderJson)")
|
||||
|
||||
|
||||
switch mode {
|
||||
case .runner:
|
||||
runInterval(model: model)
|
||||
case .simulator:
|
||||
runSimulator(model: model)
|
||||
default: break
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func runInterval(model: Model) {
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
Task {
|
||||
while true {
|
||||
let date = Date().addingTimeInterval(-59)
|
||||
if let endDate = model.endDate, date > endDate {
|
||||
break
|
||||
}
|
||||
|
||||
guard let (runUrl, args) = model.build(date: date, mode: .runner) else {
|
||||
printError("Cannot get command from \(model.name)")
|
||||
break
|
||||
}
|
||||
|
||||
do {
|
||||
let result = try await self.runMatrix(runUrl, args: args, date: date)
|
||||
runStrategy(result, date: date)
|
||||
} catch {
|
||||
printError(error)
|
||||
}
|
||||
|
||||
try await Task.sleep(nanoseconds: 1_000_000_000 * UInt64(model.balanceInterval))
|
||||
}
|
||||
|
||||
semaphore.signal()
|
||||
}
|
||||
semaphore.wait()
|
||||
}
|
||||
|
||||
|
||||
private func runSimulator(model: Model) {
|
||||
guard let startDate = model.startDate else {
|
||||
printError("No startDate to simulate!")
|
||||
return
|
||||
}
|
||||
guard let endDate = model.endDate else {
|
||||
printError("No endDate to simulate!")
|
||||
return
|
||||
}
|
||||
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
Task {
|
||||
do {
|
||||
var date = startDate
|
||||
while date <= endDate {
|
||||
guard let (runUrl, args) = model.build(date: date, mode: .simulator) else {
|
||||
printError("Cannot get command from \(model.name)")
|
||||
return
|
||||
}
|
||||
|
||||
let result = try await self.runMatrix(runUrl, args: args, date: date)
|
||||
runStrategy(result, date: date)
|
||||
|
||||
date.addTimeInterval(TimeInterval(model.balanceInterval))
|
||||
}
|
||||
} catch {
|
||||
printError(error)
|
||||
}
|
||||
|
||||
semaphore.signal()
|
||||
}
|
||||
semaphore.wait()
|
||||
}
|
||||
|
||||
|
||||
private func runMatrix(_ runUrl: URL, args: [String], date: Date) async throws -> KissMatrixResult {
|
||||
return try await withUnsafeThrowingContinuation { continuation in
|
||||
let model = args[0]
|
||||
|
||||
let outputUrl = KissGolder.matrixLogFile(date: date)
|
||||
FileManager.default.createFile(atPath: outputUrl.path, contents: nil)
|
||||
let output = FileHandle(forWritingAtPath: outputUrl.path)
|
||||
|
||||
let task = Process()
|
||||
task.currentDirectoryURL = URL.currentDirectory()
|
||||
task.executableURL = runUrl
|
||||
task.arguments = args
|
||||
task.standardOutput = output
|
||||
task.standardError = FileHandle.standardError
|
||||
task.qualityOfService = .default
|
||||
|
||||
printError("curPath: \(task.currentDirectoryPath)")
|
||||
printError("runPath: \(runUrl.path)")
|
||||
printError("args: \(args)")
|
||||
|
||||
do {
|
||||
try task.run()
|
||||
task.waitUntilExit()
|
||||
} catch {
|
||||
printError("run error \(error)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
|
||||
try? output?.close()
|
||||
|
||||
guard let data = try? Data(contentsOf: outputUrl) else {
|
||||
continuation.resume(throwing: GeneralError.emptyData(model))
|
||||
return
|
||||
}
|
||||
if data.isEmpty {
|
||||
continuation.resume(throwing: GeneralError.emptyData(model))
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let matrixResult = try JSONDecoder().decode(KissMatrixResult.self, from: data)
|
||||
continuation.resume(returning: matrixResult)
|
||||
} catch {
|
||||
printError("jsonError \(model)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private func loadModel(_ jsonFile: String) -> Model? {
|
||||
do {
|
||||
let configUrl = URL.currentDirectory().appending(path: jsonFile)
|
||||
let data = try Data(contentsOf: configUrl, options: .uncached)
|
||||
let model = try JSONDecoder().decode(Model.self, from: data)
|
||||
return model
|
||||
} catch {
|
||||
printError(error)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static private func matrixLogFile(date: Date) -> URL {
|
||||
let subPath = "log/matrix"
|
||||
let subFile = "\(subPath)/\(date.yyyyMMdd_HHmmssSSSS_forFile).log"
|
||||
|
||||
let fileUrl = URL.currentDirectory().appending(path: subFile)
|
||||
createSubpath(subPath)
|
||||
return fileUrl
|
||||
}
|
||||
|
||||
|
||||
static func createSubpath(_ name: String) {
|
||||
let subPath = URL.currentDirectory().appending(path: name)
|
||||
try? FileManager.default.createDirectory(at: subPath, withIntermediateDirectories: true)
|
||||
}
|
||||
|
||||
|
||||
private func runStrategy(_ result: KissMatrixResult, date: Date) {
|
||||
// TODO: work
|
||||
printError("<<< RUN >>> ---------------- strategy \(result.output.count) \(date.yyyyMMdd_HHmmss_forTime)")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum RunMode: String {
|
||||
case simulator = "sim"
|
||||
case runner = "run"
|
||||
}
|
||||
|
||||
|
||||
struct Model: Decodable {
|
||||
/// Matrix 이름
|
||||
let name: String
|
||||
/// Matrix 에 대한 설명
|
||||
let memo: String
|
||||
/// Matrix 를 수행하는 Runner app
|
||||
let runner: String
|
||||
/// model.json 설정
|
||||
let model: String
|
||||
/// Matrix 를 수행하는 Interval (초)
|
||||
let balanceInterval: Int
|
||||
/// Matrix 를 수행시작하는 시간. (설정되지 않으면 현재 시점부터)
|
||||
let startDate: Date?
|
||||
/// Matrix 를 종료하는 시간
|
||||
let endDate: Date?
|
||||
|
||||
func build(date: Date, mode: RunMode) -> (URL, [String])? {
|
||||
let command = URL.currentDirectory().appending(path: runner)
|
||||
|
||||
let day = date.yyyyMMdd
|
||||
let time = date.HHmmss
|
||||
let args: [String] = [mode.rawValue, model, day, time]
|
||||
|
||||
return (command, args)
|
||||
}
|
||||
|
||||
private enum CodingKeys: String, CodingKey, CaseIterable {
|
||||
case name
|
||||
case memo
|
||||
case runner
|
||||
case model
|
||||
case balanceInterval
|
||||
case startDate
|
||||
case endDate
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
self.name = try container.decode(String.self, forKey: .name)
|
||||
self.memo = try container.decode(String.self, forKey: .memo)
|
||||
self.runner = try container.decode(String.self, forKey: .runner)
|
||||
self.model = try container.decode(String.self, forKey: .model)
|
||||
self.balanceInterval = try container.decode(Int.self, forKey: .balanceInterval)
|
||||
|
||||
let startDate = try? container.decodeIfPresent(String.self, forKey: .startDate)
|
||||
self.startDate = startDate?.modelDate
|
||||
|
||||
let endDate = try? container.decodeIfPresent(String.self, forKey: .endDate)
|
||||
self.endDate = endDate?.modelDate
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,4 +7,4 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
KissMatrix().run()
|
||||
KissGolder().run()
|
||||
|
||||
@@ -9,49 +9,13 @@ import Foundation
|
||||
import KissMe
|
||||
|
||||
|
||||
enum RunMode: String {
|
||||
case simulator = "sim"
|
||||
case runner = "run"
|
||||
}
|
||||
|
||||
|
||||
struct Model: Codable {
|
||||
let indexSets: [IndexSet]
|
||||
|
||||
struct IndexSet: Codable {
|
||||
let name: String
|
||||
let memo: String
|
||||
let config: String?
|
||||
let runner: String
|
||||
let weight: Double
|
||||
|
||||
func build(date: Date) -> (URL, [String])? {
|
||||
guard let _ = name.kmiIndex else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let command = URL.currentDirectory().appending(path: runner)
|
||||
|
||||
let day = date.yyyyMMdd
|
||||
let time = date.HHmmss
|
||||
var args: [String] = [name, day, time]
|
||||
|
||||
if let config = config {
|
||||
args.append(config)
|
||||
}
|
||||
return (command, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class KissMatrix {
|
||||
|
||||
func run() {
|
||||
|
||||
func printUsage() {
|
||||
let appName = (CommandLine.arguments[0] as NSString).lastPathComponent
|
||||
print("\(appName) [sim|run] model.json [yyyyMMdd] [HHmmss]")
|
||||
printError("\(appName) [sim|run] model.json [yyyyMMdd] [HHmmss]")
|
||||
}
|
||||
|
||||
guard CommandLine.argc >= 3 else {
|
||||
@@ -71,12 +35,12 @@ class KissMatrix {
|
||||
return
|
||||
}
|
||||
guard let (year, month, day) = CommandLine.arguments[3].yyyyMMdd else {
|
||||
print("Invalid [yyyyMMdd] argument")
|
||||
printError("Invalid [yyyyMMdd] argument")
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
guard let (hour, min, sec) = CommandLine.arguments[4].HHmmss else {
|
||||
print("Invalid [HHmmss] argument")
|
||||
printError("Invalid [HHmmss] argument")
|
||||
printUsage()
|
||||
return
|
||||
}
|
||||
@@ -92,23 +56,23 @@ class KissMatrix {
|
||||
|
||||
let modelJson = CommandLine.arguments[2]
|
||||
guard let model = loadModel(modelJson) else { return }
|
||||
print("Loaded \(model.indexSets.count) index set from \(modelJson)")
|
||||
printError("Loaded \(model.indexSets.count) index set from \(modelJson)")
|
||||
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
Task {
|
||||
let results = try await withThrowingTaskGroup(of: KissIndexResult?.self, returning: [KissIndexResult].self) { taskGroup in
|
||||
for indexSet in model.indexSets {
|
||||
guard let (runUrl, args) = indexSet.build(date: runDate) else {
|
||||
print("Cannot get command from \(indexSet.name)")
|
||||
printError("Cannot get command from \(indexSet.name)")
|
||||
continue
|
||||
}
|
||||
|
||||
taskGroup.addTask {
|
||||
do {
|
||||
let result = try await self.runIndex(runUrl, args: args)
|
||||
let result = try await self.runIndex(runUrl, args: args, date: runDate)
|
||||
return result
|
||||
} catch {
|
||||
print(error)
|
||||
printError(error)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
@@ -122,18 +86,19 @@ class KissMatrix {
|
||||
}
|
||||
|
||||
mergeResult(results)
|
||||
|
||||
semaphore.signal()
|
||||
}
|
||||
semaphore.wait()
|
||||
}
|
||||
|
||||
|
||||
private func runIndex(_ runUrl: URL, args: [String]) async throws -> KissIndexResult {
|
||||
private func runIndex(_ runUrl: URL, args: [String], date: Date) async throws -> KissIndexResult {
|
||||
assert(args.count >= 3)
|
||||
return try await withUnsafeThrowingContinuation { continuation in
|
||||
let kmi = args[0]
|
||||
|
||||
let outputUrl = KissMatrix.indexLogFile(kmi)
|
||||
let outputUrl = KissMatrix.indexLogFile(kmi, date: date)
|
||||
FileManager.default.createFile(atPath: outputUrl.path, contents: nil)
|
||||
let output = FileHandle(forWritingAtPath: outputUrl.path)
|
||||
|
||||
@@ -143,17 +108,17 @@ class KissMatrix {
|
||||
task.arguments = args
|
||||
task.standardOutput = output
|
||||
task.standardError = FileHandle.standardError
|
||||
//task.qualityOfService = .userInitiated
|
||||
task.qualityOfService = .default
|
||||
|
||||
print("curPath: \(task.currentDirectoryPath)")
|
||||
print("runPath: \(runUrl)")
|
||||
print("args: \(args)")
|
||||
printError("curPath: \(task.currentDirectoryPath)")
|
||||
printError("runPath: \(runUrl.path)")
|
||||
printError("args: \(args)")
|
||||
|
||||
do {
|
||||
try task.run()
|
||||
task.waitUntilExit()
|
||||
} catch {
|
||||
print("run error \(error)")
|
||||
printError("run error \(error)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
|
||||
@@ -172,7 +137,7 @@ class KissMatrix {
|
||||
let indexResult = try JSONDecoder().decode(KissIndexResult.self, from: data)
|
||||
continuation.resume(returning: indexResult)
|
||||
} catch {
|
||||
print("jsonError \(kmi)")
|
||||
printError("jsonError \(kmi)")
|
||||
continuation.resume(throwing: error)
|
||||
}
|
||||
}
|
||||
@@ -220,15 +185,14 @@ class KissMatrix {
|
||||
let model = try JSONDecoder().decode(Model.self, from: data)
|
||||
return model
|
||||
} catch {
|
||||
print(error)
|
||||
printError(error)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static func indexLogFile(_ kmi: String) -> URL {
|
||||
static func indexLogFile(_ kmi: String, date: Date) -> URL {
|
||||
let subPath = "log/index"
|
||||
let date = Date()
|
||||
let subFile = "\(subPath)/\(date.yyyyMMdd_HHmmssSSSS_forFile)-\(kmi).log"
|
||||
|
||||
let fileUrl = URL.currentDirectory().appending(path: subFile)
|
||||
@@ -242,3 +206,44 @@ class KissMatrix {
|
||||
try? FileManager.default.createDirectory(at: subPath, withIntermediateDirectories: true)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
enum RunMode: String {
|
||||
case simulator = "sim"
|
||||
case runner = "run"
|
||||
}
|
||||
|
||||
|
||||
struct Model: Decodable {
|
||||
let indexSets: [IndexSet]
|
||||
|
||||
struct IndexSet: Codable {
|
||||
/// Index Set 이름
|
||||
let name: String
|
||||
/// Index Set 에 대한 설명
|
||||
let memo: String
|
||||
/// config.json 설정
|
||||
let config: String?
|
||||
/// Index 수집을 수행하는 Runner app
|
||||
let runner: String
|
||||
/// 보정용 가중치
|
||||
let weight: Double
|
||||
|
||||
func build(date: Date) -> (URL, [String])? {
|
||||
guard let _ = name.kmiIndex else {
|
||||
return nil
|
||||
}
|
||||
|
||||
let command = URL.currentDirectory().appending(path: runner)
|
||||
|
||||
let day = date.yyyyMMdd
|
||||
let time = date.HHmmss
|
||||
var args: [String] = [name, day, time]
|
||||
|
||||
if let config = config {
|
||||
args.append(config)
|
||||
}
|
||||
return (command, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
340A4DBD2A4C34BE005A1FBA /* IndexContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DBC2A4C34BE005A1FBA /* IndexContext.swift */; };
|
||||
340A4DC42A4E4345005A1FBA /* ArrayDecodable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DC32A4E4345005A1FBA /* ArrayDecodable.swift */; };
|
||||
340A4DC82A4E43C5005A1FBA /* GeneralError.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DC72A4E43C5005A1FBA /* GeneralError.swift */; };
|
||||
340A4DCE2A4EA5D8005A1FBA /* Runner.swift in Sources */ = {isa = PBXBuildFile; fileRef = 340A4DCD2A4EA5D8005A1FBA /* Runner.swift */; };
|
||||
341F5EB02A0A80EC00962D48 /* KissMe.docc in Sources */ = {isa = PBXBuildFile; fileRef = 341F5EAF2A0A80EC00962D48 /* KissMe.docc */; };
|
||||
341F5EB62A0A80EC00962D48 /* KissMe.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 341F5EAB2A0A80EC00962D48 /* KissMe.framework */; };
|
||||
341F5EBB2A0A80EC00962D48 /* KissMeTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 341F5EBA2A0A80EC00962D48 /* KissMeTests.swift */; };
|
||||
@@ -40,7 +41,7 @@
|
||||
349C26AB2A1EAE2400F3EC91 /* KissProfile.swift in Sources */ = {isa = PBXBuildFile; fileRef = 349C26AA2A1EAE2400F3EC91 /* KissProfile.swift */; };
|
||||
34D3680F2A2AA0BE005E6756 /* PropertyIterable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34D3680E2A2AA0BE005E6756 /* PropertyIterable.swift */; };
|
||||
34E7B9112A49BD2800B3AB9F /* DomesticIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34E7B9102A49BD2800B3AB9F /* DomesticIndex.swift */; };
|
||||
34F1900C2A41982A0068C697 /* IndexResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F1900B2A41982A0068C697 /* IndexResult.swift */; };
|
||||
34F1900C2A41982A0068C697 /* KissIndexResult.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F1900B2A41982A0068C697 /* KissIndexResult.swift */; };
|
||||
34F1900F2A426D150068C697 /* ShopContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F1900E2A426D150068C697 /* ShopContext.swift */; };
|
||||
34F190112A4394EB0068C697 /* LocalContext.swift in Sources */ = {isa = PBXBuildFile; fileRef = 34F190102A4394EB0068C697 /* LocalContext.swift */; };
|
||||
/* End PBXBuildFile section */
|
||||
@@ -59,6 +60,7 @@
|
||||
340A4DBC2A4C34BE005A1FBA /* IndexContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexContext.swift; sourceTree = "<group>"; };
|
||||
340A4DC32A4E4345005A1FBA /* ArrayDecodable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ArrayDecodable.swift; sourceTree = "<group>"; };
|
||||
340A4DC72A4E43C5005A1FBA /* GeneralError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralError.swift; sourceTree = "<group>"; };
|
||||
340A4DCD2A4EA5D8005A1FBA /* Runner.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Runner.swift; sourceTree = "<group>"; };
|
||||
341F5EAB2A0A80EC00962D48 /* KissMe.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KissMe.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
341F5EAE2A0A80EC00962D48 /* KissMe.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KissMe.h; sourceTree = "<group>"; };
|
||||
341F5EAF2A0A80EC00962D48 /* KissMe.docc */ = {isa = PBXFileReference; lastKnownFileType = folder.documentationcatalog; name = KissMe.docc; path = ../KissMe.docc; sourceTree = "<group>"; };
|
||||
@@ -90,7 +92,7 @@
|
||||
349C26AA2A1EAE2400F3EC91 /* KissProfile.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KissProfile.swift; sourceTree = "<group>"; };
|
||||
34D3680E2A2AA0BE005E6756 /* PropertyIterable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PropertyIterable.swift; sourceTree = "<group>"; };
|
||||
34E7B9102A49BD2800B3AB9F /* DomesticIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DomesticIndex.swift; sourceTree = "<group>"; };
|
||||
34F1900B2A41982A0068C697 /* IndexResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndexResult.swift; sourceTree = "<group>"; };
|
||||
34F1900B2A41982A0068C697 /* KissIndexResult.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KissIndexResult.swift; sourceTree = "<group>"; };
|
||||
34F1900E2A426D150068C697 /* ShopContext.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShopContext.swift; sourceTree = "<group>"; };
|
||||
34F190102A4394EB0068C697 /* LocalContext.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LocalContext.swift; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
@@ -240,7 +242,8 @@
|
||||
34F1900A2A41981A0068C697 /* Index */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
34F1900B2A41982A0068C697 /* IndexResult.swift */,
|
||||
340A4DCD2A4EA5D8005A1FBA /* Runner.swift */,
|
||||
34F1900B2A41982A0068C697 /* KissIndexResult.swift */,
|
||||
);
|
||||
path = Index;
|
||||
sourceTree = "<group>";
|
||||
@@ -367,6 +370,7 @@
|
||||
341F5EFB2A10909D00962D48 /* LoginResult.swift in Sources */,
|
||||
340A4DC42A4E4345005A1FBA /* ArrayDecodable.swift in Sources */,
|
||||
340A4DC82A4E43C5005A1FBA /* GeneralError.swift in Sources */,
|
||||
340A4DCE2A4EA5D8005A1FBA /* Runner.swift in Sources */,
|
||||
341F5F0B2A15115400962D48 /* KissShop.swift in Sources */,
|
||||
3435A7F72A35D82000D604F1 /* DomesticShortSelling.swift in Sources */,
|
||||
341F5F072A14634F00962D48 /* Foundation+Extensions.swift in Sources */,
|
||||
@@ -378,7 +382,7 @@
|
||||
34F1900F2A426D150068C697 /* ShopContext.swift in Sources */,
|
||||
341F5F0F2A15223A00962D48 /* SeibroRequest.swift in Sources */,
|
||||
341F5EF02A0F886600962D48 /* ForeignFutures.swift in Sources */,
|
||||
34F1900C2A41982A0068C697 /* IndexResult.swift in Sources */,
|
||||
34F1900C2A41982A0068C697 /* KissIndexResult.swift in Sources */,
|
||||
341F5EEC2A0F883900962D48 /* ForeignStock.swift in Sources */,
|
||||
34F190112A4394EB0068C697 /* LocalContext.swift in Sources */,
|
||||
341F5EFF2A10955D00962D48 /* OrderRequest.swift in Sources */,
|
||||
|
||||
@@ -51,6 +51,12 @@
|
||||
ReferencedContainer = "container:KissMeGolder.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "sim golder/default.json"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
|
||||
@@ -53,7 +53,7 @@
|
||||
</BuildableProductRunnable>
|
||||
<CommandLineArguments>
|
||||
<CommandLineArgument
|
||||
argument = "sim model/golder.json 20230627 100000"
|
||||
argument = "sim model/default4.json 20230627 100000"
|
||||
isEnabled = "YES">
|
||||
</CommandLineArgument>
|
||||
</CommandLineArguments>
|
||||
|
||||
@@ -10,6 +10,8 @@ THIS_PATH=`dirname "$0"`
|
||||
${THIS_PATH}/build_any.sh KissMeConsole
|
||||
${THIS_PATH}/build_any.sh KissMeIndex
|
||||
${THIS_PATH}/build_any.sh KissMeMatrix
|
||||
${THIS_PATH}/build_any.sh KissMeGolder
|
||||
|
||||
#${THIS_PATH}/build_any.sh KissMeBatch
|
||||
#${THIS_PATH}/build_any.sh KissGram
|
||||
|
||||
|
||||
Reference in New Issue
Block a user