Implement love command

This commit is contained in:
2023-05-27 08:20:56 +09:00
parent fa6c18a99c
commit 3740b38fc8
8 changed files with 134 additions and 28 deletions

View File

@@ -31,10 +31,3 @@ extension Date {
ProcessInfo.processInfo.systemUptime
}
}
extension Array {
func write(toCSV: URL) where Element == Encodable {
// TODO: later
}
}

View File

@@ -113,7 +113,7 @@ extension KissAccount {
return
}
// TODO: work
// TODO:
}
@@ -123,6 +123,6 @@ extension KissAccount {
return
}
// TODO: work
// TODO:
}
}

View File

@@ -7,4 +7,4 @@
import Foundation
// TODO: WORK
// TODO: ...

View File

@@ -7,4 +7,4 @@
import Foundation
// TODO: WORK
// TODO: ...

View File

@@ -7,4 +7,4 @@
import Foundation
// TODO: WORK
// TODO: ...

View File

@@ -78,9 +78,13 @@ extension KissProfile {
}
public struct Love: Codable {
let key: String
let iscd: String
let name: String
public let isin: String
public let name: String
public init(isin: String, name: String) {
self.isin = isin
self.name = name
}
}
private var profileJsonUrl: URL {
@@ -126,16 +130,44 @@ extension KissProfile {
}
}
public func removeLove(_ love: Love, for key: String) -> Bool {
public func removeLove(isin: String, for key: String) -> KissProfile.Love? {
profileLock.lock()
defer {
profileLock.unlock()
}
if let index = profile.loves[key]?.firstIndex(where: { $0.iscd == love.iscd }) {
profile.loves[key]?.remove(at: index)
if let index = profile.loves[key]?.firstIndex(where: { $0.isin == isin }) {
return profile.loves[key]?.remove(at: index)
}
return nil
}
public func setLove(_ love: Love, index: Int, for key: String) -> Bool {
profileLock.lock()
defer {
profileLock.unlock()
}
if let array = profile.loves[key], index < array.count {
profile.loves[key]?[index] = love
return true
}
return false
}
public func getLoves() -> [String: [Love]] {
profileLock.lock()
defer {
profileLock.unlock()
}
return profile.loves
}
public func getLoves(for key: String) -> [Love]? {
profileLock.lock()
defer {
profileLock.unlock()
}
return profile.loves[key]
}
}

View File

@@ -172,6 +172,15 @@ extension KissConsole {
//return products.filter { $0.key.decomposedStringWithCanonicalMapping.contains(similarName) }
}
private func getProductName(isin: String) -> String? {
productsLock.lock()
defer {
productsLock.unlock()
}
return products.compactMap { $0.value.first(where: { $0.isinCode == isin })?.itemName }.first
}
private func loadShop(_ profile: Bool = false) {
let appTime1 = Date.appTime
guard let stringCsv = try? String(contentsOfFile: shopProducts.path) else {
@@ -290,9 +299,13 @@ extension KissConsole {
private func onBuy(_ args: [String]) async {
guard args.count == 3,
let price = Int(args[1]),
let quantity = Int(args[2]) else {
guard args.count == 3 else {
return
}
guard let price = Int(args[1]) else {
return
}
guard let quantity = Int(args[2]) else {
return
}
@@ -308,6 +321,8 @@ extension KissConsole {
orderQuantity: quantity, orderPrice: price)
do {
let result = try await account?.orderStock(contract: contract)
// TODO:
print(result)
} catch {
print("\(error)")
@@ -446,17 +461,83 @@ extension KissConsole {
private func onLoves() async {
guard let account = account else { return }
let loves = account.getLoves()
for tab in loves.sorted(by: { $0.key < $1.key }) {
printLoveTab(tab.key, loves: tab.value)
}
}
private func printLoveTab(_ key: String, loves: [KissProfile.Love]) {
print("Page: \(key)")
for item in loves {
print(" \(item.isin) \(item.name)")
}
}
private func onLove(_ args: [String]) async {
guard let account = account else { return }
guard args.count > 0 else {
print("Invalid love\nlove ")
return
}
if args.count == 1 {
let key = args[0]
guard let loves = account.getLoves(for: key) else { return }
printLoveTab(key, loves: loves)
}
else if args.count == 2 {
let keys = args[0].split(separator: ".").map { String($0) }
let isin = args[1]
if keys.count == 2 {
/// key index Love
///
let key = keys[0]
let index = keys[1]
if let loves = account.getLoves(for: key), let index = Int(index) {
if index < loves.count {
guard let name = getProductName(isin: isin) else {
print("No product about isin: \(isin)")
return
}
if account.setLove(KissProfile.Love(isin: isin, name: name), index: index, for: key) {
print("Success \(name)")
account.saveProfile()
}
else {
print("Invalid index: \(index) for \(key)")
}
}
}
}
else {
/// key Love
///
guard let name = getProductName(isin: isin) else {
print("No product about isin: \(isin)")
return
}
account.addLove(KissProfile.Love(isin: isin, name: name), for: keys[0])
print("Success \(name)")
account.saveProfile()
}
}
}
private func onHate(_ args: [String]) async {
guard let account = account else { return }
guard args.count > 1 else {
print("Invalid hate")
return
}
let key = args[0]
let isin = args[1]
if let love = account.removeLove(isin: isin, for: key) {
print("Success \(love.name)")
}
}
}

View File

@@ -13,8 +13,8 @@ KissMeConsole 에서 유효한 command line 명령어는 다음과 같습니다.
command | 설명
------- | ---
`quit` | 종료
`login mock` | Mock 서버로 로그인, mock-server.json 을 credential 로 사용.
`login real` | Real 서버로 로그인, real-server.json 을 credential 로 사용.
`login mock` | Mock 서버로 로그인. mock-server.json 을 credential 로 사용.
`login real` | Real 서버로 로그인. real-server.json 을 credential 로 사용.
`logout` | 접속한 서버에서 로그아웃
`top` | 상위 거래량 30종목 (평균거래량)
WIP `buy (ISCD) (수량)` | 구매
@@ -22,12 +22,12 @@ WIP `sell (ISCD) (수량)` | 판매
WIP `cancel (ISCD)` | 주문 취소
`open bag` | 보유 종목 열람
`load shop` | data/shop-products.csv 로부터 전체 상품을 로딩
`update shop` | 금융위원회_KRX상장종목정보 로부터 전체 상품을 얻어서 data/shop-products.csv 로 저장
`update shop` | **금융위원회_KRX상장종목정보** 로부터 전체 상품을 얻어서 data/shop-products.csv 로 저장
`look (상품명)` | (상품명) 에 해당되는 ISCD 를 표시함
WIP `showcase` | 추천 상품을 제안함
WIP `loves` | 관심 종목 전체를 열람. profile.json 에 저장된 관심 종목을 표시함.
WIP `love (탭).(번호) (ISCD)` | 관심 종목에 추가함. (번호) 를 지정하지 않으면 (탭) 마지막에 추가함.
WIP `hate (탭).(번호) (ISCD)` | 관심 종목에서 삭제함.
`loves` | 관심 종목 전체를 열람. profile.json 에 저장된 관심 종목을 표시함.
`love (탭).(번호) (ISCD)` | 관심 종목에 추가함. (번호) 를 지정하지 않으면 (탭) 마지막에 추가함.
`hate (탭) (ISCD)` | 관심 종목에서 삭제함.
# KissCredential