// // SleepViewModels.swift // HPlusFit // // Created by lemo. on 2019/10/6. // Copyright © 2019 lemo. All rights reserved. // import UIKit fileprivate struct Metric { static let legends = [ LegendData(docColor: kHexColor(0xF6BF47), name: MultiLanguageKey_FB.awakeFB.localized), LegendData(docColor: kHexColor(0xA4A3FF), name: MultiLanguageKey_FB.shallowSleepFB.localized), LegendData(docColor: kHexColor(0x6E63FF), name: MultiLanguageKey_FB.deepSleepFB.localized) ] } class SleepViewModels: ViewModel { // 图表数据 lazy var relay: BehaviorRelay = { return BehaviorRelay(value: defaultVM) }() // 底部数据 let formRealy = BehaviorRelay(value: nil) // 默认数据 private lazy var defaultVM: ChartViewModel = { let chartViewModel: ChartViewModel = ChartViewModel(leftIcon: nil, title: nil, legends: [], source: [], chartType: .horizontalSegment, maxAxis: 12, xAxis: [], lineColor: kHexColor(0x6161ED), isShowMeasureLine: false, center: nil, centerColor: kHexColor(0xEEA82C), centerUnit: nil) return chartViewModel }() /// 当前时间(默认当前) private var currenTimeStr = DateClass.getCurrentTimeStr(formatStr: "yyyy-MM-dd") private var queryType: DataQueryType = .day override init() { super.init() // 默认加载当天 fbloadSleepData(timeStr: currenTimeStr, queryType: queryType) } /// 加载计步数据 func fbloadSleepData(timeStr: String?, queryType: DataQueryType?) { // 无查询类型默认为上一次查询类型 let tempQueryType = queryType == nil ? self.queryType : queryType! self.queryType = tempQueryType // 查询时间戳 let tempTimeStr = timeStr == nil ? currenTimeStr : timeStr! currenTimeStr = tempTimeStr DataBaseManagerFireBoltt.shared.fbquerySleepModel(dataDate: tempTimeStr, queryType: tempQueryType) { [weak self] (results) in guard let `self` = self else { return } guard let sleepModelArr = results as? [SleepModel], sleepModelArr.count > 0 else { self.relay.accept(self.defaultVM) self.formRealy.accept(nil) return } // 拼接数据模型 var chartViewModel: ChartViewModel! var formModel: HealthFormModel? switch tempQueryType { case .day: let sleepModel = sleepModelArr.first! if sleepModel.totalSleepDuration == 0 { self.relay.accept(self.defaultVM) self.formRealy.accept(nil) return } let source: [ChartViewData] = self.processSleepDetails(model: sleepModel) chartViewModel = ChartViewModel(leftIcon: nil, title: nil, legends: Metric.legends, source: source, chartType: .horizontalSegment, maxAxis: 12, xAxis: ["21:00", "00:00", "03:00", "06:00", "09:00"], lineColor: kHexColor(0x6161ED), isShowMeasureLine: false, center: String(format: "%02d:%02d", sleepModel.totalSleepDuration / 60, sleepModel.totalSleepDuration % 60), centerColor: kHexColor(0x5447F6), centerUnit: MultiLanguageKey_FB.hourFB.localized) // 底部数据总和 // formModel = HealthFormModel(oneValue: String(format: "%02d:%02d", sleepModel.deepSleepDuration / 60, sleepModel.deepSleepDuration % 60), twoValue: String(format: "%02d:%02d", sleepModel.lightSleepDuration / 60, sleepModel.lightSleepDuration % 60), threeValue: String(format: "%02d:%02d", sleepModel.totalSleepDuration / 60, sleepModel.totalSleepDuration % 60), fourValue: String(sleepModel.awakeNumber)) formModel = HealthFormModel(oneValue: String(format: "%02d:%02d", sleepModel.deepSleepDuration / 60, sleepModel.deepSleepDuration % 60), twoValue: String(format: "%02d:%02d", sleepModel.lightSleepDuration / 60, sleepModel.lightSleepDuration % 60), threeValue: String(format: "%02d:%02d", sleepModel.totalSleepDuration / 60, sleepModel.totalSleepDuration % 60), fourValue: String(sleepModel.awakeDuration%60)) case .week: // 获取一周时间戳数组 let weeks = (0...6).map { DateClass.dateStringOffset(from: tempTimeStr, offset: $0) } var sources: [ChartViewData] = [] var maxAxis = 0 var totalDeepSleep = 0 var totalShallowSleep = 0 var totalAwakeSleep = 0 var totalSleep = 0 var totalAwakeNumber = 0 var xAxis: [String] = [] // 边里匹配对应日期数据数组 for dataDate in weeks { let showDate = DateClass.getTimeStrToDate(formatStr: "yyyy-MM-dd", timeStr: dataDate).tranFormDateStr(format: "MM/dd") xAxis.append(showDate) var isMatch = false for sleepModel in sleepModelArr { if dataDate == sleepModel.dataDate && sleepModel.totalSleepDuration > 0 { isMatch = true if sleepModel.totalSleepDuration > maxAxis { maxAxis = sleepModel.totalSleepDuration } totalDeepSleep += sleepModel.deepSleepDuration totalShallowSleep += sleepModel.lightSleepDuration totalAwakeSleep += sleepModel.awakeDuration totalSleep += sleepModel.totalSleepDuration totalAwakeNumber += sleepModel.awakeNumber sources.append(ChartViewData(date: "", number: 0, sum: Float(sleepModel.totalSleepDuration) / 60.0, sleeps: [ sleepData(type: 2, value: Float(sleepModel.deepSleepDuration) / 60.0), sleepData(type: 0, value: Float(sleepModel.awakeDuration) / 60.0), sleepData(type: 1, value: Float(sleepModel.lightSleepDuration) / 60.0) ], fallingsleepTimes: "", awakeTimes: "")) } // 添加空数据 if !isMatch { sources.append(ChartViewData(date: "", number: 0, sum: 0.0, sleeps: [ sleepData(type: 2, value: 0.0), sleepData(type: 0, value: 0.0), sleepData(type: 1, value: 0.0) ], fallingsleepTimes: "", awakeTimes: "")) } } } chartViewModel = ChartViewModel(leftIcon: nil, title: nil, legends: Metric.legends, source:sources, chartType: .segmentBar, maxAxis: maxAxis / 60 + 2, xAxis: xAxis, lineColor: kHexColor(0xEEA82C), center: String(format: "%02d:%02d", totalSleep / 60, totalSleep % 60), centerColor: kHexColor(0x5447F6), centerUnit: "") chartViewModel.points = sources.count // 底部数据总和 formModel = HealthFormModel(oneValue: String(format: "%02d:%02d", totalDeepSleep / 60, totalDeepSleep % 60), twoValue: String(format: "%02d:%02d", totalShallowSleep / 60, totalShallowSleep % 60), threeValue: String(format: "%02d:%02d", totalSleep / 60, totalSleep % 60), fourValue: String(format: "%02d:%02d", totalAwakeSleep / 60, totalAwakeSleep % 60)) case .month: // 获取一个月时间戳数组 let selectDate = DateClass.getTimeStrToDate(formatStr: "yyyy-MM-dd", timeStr: tempTimeStr) let monthSatrtDate = selectDate.startOfCurrentMonth().tranFormDateStr(format: "yyyy-MM-dd") let monthRange = selectDate.getMonthHowManyDay() let months = monthRange.map { DateClass.dateStringOffset(from: monthSatrtDate, offset: $0 - 1) } var sources: [ChartViewData] = [] var maxAxis = 0 var totalDeepSleep = 0 var totalShallowSleep = 0 var totalAwakeSleep = 0 var totalSleep = 0 var totalAwakeNumber = 0 var xAxis: [String] = [] // 边里匹配对应日期数据数组 for (offset, dataDate) in months.enumerated() { // 只展示每周的 if offset == 0 || offset == months.count - 1 || offset == (months.count / 2) { let showDate = DateClass.getTimeStrToDate(formatStr: "yyyy-MM-dd", timeStr: dataDate).tranFormDateStr(format: "dd") xAxis.append(showDate) } var isMatch = false for sleepModel in sleepModelArr { let totalSleepTime = sleepModel.totalSleepDuration if dataDate == sleepModel.dataDate && totalSleepTime > 0 { isMatch = true if totalSleepTime > maxAxis { maxAxis = totalSleepTime } totalDeepSleep += sleepModel.deepSleepDuration totalShallowSleep += sleepModel.lightSleepDuration totalAwakeSleep += sleepModel.awakeDuration totalSleep += sleepModel.totalSleepDuration totalAwakeNumber += sleepModel.awakeNumber sources.append(ChartViewData(date: "", number: 0, sum: Float(sleepModel.totalSleepDuration) / 60.0, sleeps: [ sleepData(type: 2, value: Float(sleepModel.deepSleepDuration) / 60.0), sleepData(type: 0, value: Float(sleepModel.awakeDuration) / 60.0), sleepData(type: 1, value: Float(sleepModel.lightSleepDuration) / 60.0) ], fallingsleepTimes: "", awakeTimes: "")) } // 添加空数据 if !isMatch { sources.append(ChartViewData(date: nil, number: 0, sum: 0.0, sleeps: [ sleepData(type: 2, value: 0.0), sleepData(type: 0, value: 0.0), sleepData(type: 1, value: 0.0) ], fallingsleepTimes: "", awakeTimes: "")) } } } chartViewModel = ChartViewModel(leftIcon: nil, title: nil, legends: Metric.legends, source:sources, chartType: .rectangleSegBar, maxAxis: maxAxis / 60 + 2, xAxis: xAxis, lineColor: kHexColor(0xEEA82C), center: String(format: "%02d:%02d", totalSleep / 60, totalSleep % 60), centerColor: kHexColor(0x5447F6), centerUnit: "") chartViewModel.points = sources.count // 底部数据总和 formModel = HealthFormModel(oneValue: String(format: "%02d:%02d", totalDeepSleep / 60, totalDeepSleep % 60), twoValue: String(format: "%02d:%02d", totalShallowSleep / 60, totalShallowSleep % 60), threeValue: String(format: "%02d:%02d", totalSleep / 60, totalSleep % 60), fourValue: String(format: "%02d:%02d", totalAwakeSleep / 60, totalAwakeSleep % 60)) default: self.relay.accept(self.defaultVM) self.formRealy.accept(nil) return } // 更新数据 self.relay.accept(chartViewModel) self.formRealy.accept(formModel) } } } extension SleepViewModels { /// 处理睡眠详情数据 /// /// - Parameter sleepDetails: 睡眠详情 /// - Returns: 图表模型 private func processSleepDetails(model: SleepModel) -> [ChartViewData] { var chartViewArray: [ChartViewData] = [] let detailsArr: [String] = model.sleepDetails.components(separatedBy: ",") for detail in detailsArr { let comps = detail.components(separatedBy: "|") // 睡眠详情数据(睡眠类型|开始时间戳|持续时长|结束时间戳,..) if comps.count == 4 { // 睡眠类型(转换图表类型) let type = (comps.first! as NSString).integerValue // 开始时间 let startTime = DateClass.timestampToStr(comps[1].integerValue, formatStr: "HH:mm") // 时长 let duration = comps[2].integerValue // 结束时间 let endTime = DateClass.timestampToStr(comps[3].integerValue, formatStr: "HH:mm") // 创建图表数据模型 let chartData = ChartViewData(sleep: sleepData(type: type, value: Float(duration) / 60.0, begin: startTime, end: endTime)) chartViewArray.append(chartData) } } return chartViewArray } private func minToStr(min: Int) -> String { return String(format: "%02d:%02d", min / 60, min % 60) } }