109 lines
3.6 KiB
Swift
109 lines
3.6 KiB
Swift
//
|
|
// KissIndex+0005.swift
|
|
// KissMeIndex
|
|
//
|
|
// Created by ened-book-m1 on 2023/06/20.
|
|
//
|
|
|
|
import Foundation
|
|
import KissMe
|
|
|
|
|
|
extension KissIndex {
|
|
|
|
func indexSet_0005(date: Date, config: String?, kmi: KissIndexType) {
|
|
let belongs: [BelongClassCode] = [.averageVolume, .volumeIncreaseRate, .averageVolumeTurnoverRate, .transactionValue, .averageTransactionValueTurnoverRate]
|
|
|
|
do {
|
|
var scoreMap = [String: Double]()
|
|
|
|
for belong in belongs {
|
|
let topUrl = try KissIndex.pickNearTopProductsUrl(belong, date: date)
|
|
let data = try [VolumeRankResult.OutputDetail].readCsv(fromFile: topUrl, verifyHeader: true)
|
|
|
|
for (index, item) in data.enumerated() {
|
|
let score = Double(30 - index)
|
|
if let _ = scoreMap[item.shortProductNo] {
|
|
scoreMap[item.shortProductNo]! += score
|
|
}
|
|
else {
|
|
scoreMap[item.shortProductNo] = score
|
|
}
|
|
}
|
|
}
|
|
|
|
normalizeAndWrite(scoreMap: scoreMap, includeName: true, kmi: kmi)
|
|
}
|
|
catch {
|
|
writeError(error, kmi: kmi)
|
|
}
|
|
}
|
|
|
|
|
|
private static func pickNearTopProductsUrl(_ belong: BelongClassCode, date: Date) throws -> URL {
|
|
let subPath = "data/top30/\(date.yyyyMMdd)"
|
|
let dayFile = "top30-\(belong.fileBelong)-\(date.yyyyMMdd)-"
|
|
|
|
guard let enumerator = FileManager.subPathFiles(subPath) else {
|
|
throw GeneralError.noCsvFile
|
|
}
|
|
|
|
let dateHHmmss = date.HHmmss
|
|
var csvUrls = [URL]()
|
|
for case let fileUrl as URL in enumerator {
|
|
guard fileUrl.pathExtension == "csv" else {
|
|
continue
|
|
}
|
|
|
|
let dayPrefixFile = fileUrl.lastPathComponent.prefix(dayFile.utf8.count)
|
|
let hourOfFile = fileUrl.lastPathComponent.suffix(10).split(separator: ".")
|
|
if dayPrefixFile == dayFile, hourOfFile.count == 2 {
|
|
let hourFrag = String(hourOfFile[0])
|
|
if hourFrag <= dateHHmmss {
|
|
csvUrls.append(fileUrl)
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Sorted by near date
|
|
csvUrls.sort(by: { dateHHmmss.diffSecondsTwoCsvHHmmss($0.lastPathComponent) < dateHHmmss.diffSecondsTwoCsvHHmmss($1.lastPathComponent) })
|
|
|
|
//csvUrls.forEach( { print($0) })
|
|
guard let nearestFile = csvUrls.first else {
|
|
throw GeneralError.noCsvFile
|
|
}
|
|
|
|
//print("nearest file: \(nearestFile) at \(date.yyyyMMdd_HHmmss_forTime)")
|
|
return nearestFile
|
|
}
|
|
}
|
|
|
|
|
|
extension String {
|
|
var csvHHmmssBySeconds: TimeInterval? {
|
|
let csvTopProductsFrags = split(separator: "-")
|
|
guard csvTopProductsFrags.count == 4 else {
|
|
return nil
|
|
}
|
|
guard csvTopProductsFrags[0] == "top30" else {
|
|
return nil
|
|
}
|
|
let hourNames = csvTopProductsFrags[3].split(separator: ".")
|
|
guard hourNames.count == 2, let (hour, min, sec) = String(hourNames[0]).HHmmss else {
|
|
return nil
|
|
}
|
|
return TimeInterval(hour * 60 * 60 + min * 60 + sec)
|
|
}
|
|
|
|
var HHmmssBySeconds: TimeInterval? {
|
|
guard let (hour, min, sec) = HHmmss else {
|
|
return nil
|
|
}
|
|
return TimeInterval(hour * 60 * 60 + min * 60 + sec)
|
|
}
|
|
|
|
func diffSecondsTwoCsvHHmmss(_ another: String) -> TimeInterval {
|
|
(csvHHmmssBySeconds ?? 0) - (another.csvHHmmssBySeconds ?? 0)
|
|
}
|
|
}
|