I'm trying to figure out BetterRest app challenge #3.
Goal is to do away with the calculate button and have the app always display the recommended bedtime.
My solution was to add an action to the cups per day Picker that calls the calculate bedtime function.
When I run the app and change the cups of coffee from the default the action to call the calculate bedtime function doesn't work.
Any assistance would be appreciated.
import CoreML
import SwiftUI
struct ContentView: View {
static var defaultWakeTime: Date {
var components = DateComponents()
components.hour = 7
components.minute = 0
return Calendar.current.date(from: components) ?? Date.now
}
static var defaultBedTime: Date {
var components = DateComponents()
components.hour = 19
components.minute = 0
return Calendar.current.date(from: components) ?? Date.now
}
@State private var wakeUp = defaultWakeTime
@State private var sleepAmount = 8.0
@State private var coffeeAmount = 1
@State private var alertTitle = ""
@State private var alertMessage = ""
@State private var showingAlert = false
@State private var recommendedBedTime = defaultBedTime
var body: some View {
NavigationView {
Form {
Section {
Text("When do you want to wake up?")
.font(.headline)
DatePicker("Please enter a time", selection: $wakeUp, displayedComponents: .hourAndMinute)
.labelsHidden()
}
Section {
Text("Desired amount of sleep")
.font(.headline)
Stepper("\(sleepAmount.formatted()) hours", value: $sleepAmount, in: 4...12, step: 0.25)
}
Section {
Text("Daily coffee intake")
.font(.headline)
Picker("Cups per day", selection: $coffeeAmount) {
ForEach(1..<21) { number in
Button("\(number)", action: calculateBedTime)
}
}
}
Section {
Text("Your ideal bedtime is: \(recommendedBedTime.formatted(date: .omitted, time: .shortened))")
}
}.navigationTitle("BetterRest")
.toolbar {
Button("Calculate", action: calculateBedTime)
}
.alert(alertTitle, isPresented: $showingAlert) {
Button("OK") { }
} message: {
Text(alertMessage)
}
}
}
func calculateBedTime() {
do {
let config = MLModelConfiguration()
let model = try SleepCalculator(configuration: config)
let components = Calendar.current.dateComponents([.hour, .minute], from: wakeUp)
let hour = (components.hour ?? 0) * 60 * 60
let minute = (components.minute ?? 0) * 60
let prediction = try model.prediction(wake: Double(hour + minute), estimatedSleep: sleepAmount, coffee: Double(coffeeAmount))
let sleepTime = wakeUp - prediction.actualSleep
recommendedBedTime = sleepTime
alertTitle = "Your ideal bedtime is…"
alertMessage = sleepTime.formatted(date: .omitted, time: .shortened)
} catch {
alertTitle = "Error"
alertMessage = "Sorry, there was a problem calculating your bedtime."
}
showingAlert = true
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}