You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
13 KiB
224 lines
13 KiB
// |
|
// 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<ChartViewModel> = { |
|
return BehaviorRelay<ChartViewModel>(value: defaultVM) |
|
}() |
|
// 底部数据 |
|
let formRealy = BehaviorRelay<HealthFormModel?>(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) |
|
} |
|
|
|
} |
|
|
|
|