Store a lot less state
This commit is contained in:
parent
3507385d6c
commit
3913522cc3
3 changed files with 49 additions and 70 deletions
|
|
@ -36,12 +36,17 @@ let doesLightHavePowerAfterInteractions light interactions =
|
||||||
|> Seq.tryLast
|
|> Seq.tryLast
|
||||||
|> Option.defaultValue false
|
|> Option.defaultValue false
|
||||||
|
|
||||||
let tryGetLastRemoteInteraction interactions =
|
let tryGetLastBedroomRemoteInteraction interactions =
|
||||||
interactions
|
interactions
|
||||||
|> Seq.indexed
|
|> Seq.indexed
|
||||||
|> Seq.choose (fun interaction ->
|
|> Seq.choose (fun (index, interaction) ->
|
||||||
match interaction with
|
match interaction with
|
||||||
| index, Interaction.RemoteInteraction remoteInteraction -> Some(index, remoteInteraction)
|
| Interaction.RemoteInteraction remoteInteraction ->
|
||||||
|
match remoteInteraction with
|
||||||
|
| RemotePressedOnButton
|
||||||
|
| RemotePressedOffButton
|
||||||
|
| RemotePressedLeftButton -> Some(index, remoteInteraction)
|
||||||
|
| RemotePressedRightButton -> None
|
||||||
| _ -> None)
|
| _ -> None)
|
||||||
|> Seq.tryLast
|
|> Seq.tryLast
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,13 +41,13 @@ type NightLightTests() =
|
||||||
|> Prop.label fakeHome.Label
|
|> Prop.label fakeHome.Label
|
||||||
|> Prop.trivial (fakeHome.LightsThatAreOn.Length = 0)
|
|> Prop.trivial (fakeHome.LightsThatAreOn.Length = 0)
|
||||||
|
|
||||||
[<Property(Arbitrary = [| typeof<ArbitraryInteractions> |])>]
|
[<Property(Arbitrary = [| typeof<ArbitraryInteractions> |], MaxTest = 500)>]
|
||||||
let ``All lights should either be off or have a brightness that fits its color`` (interactions: Interaction list) =
|
let ``All lights should either be off or have a brightness that fits its color`` (interactions: Interaction list) =
|
||||||
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
|
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
|
||||||
let time = getTimeAfterInteractions interactions |> _.TimeOfDay
|
let time = getTimeAfterInteractions interactions |> _.TimeOfDay
|
||||||
|
|
||||||
let alarm =
|
let alarm =
|
||||||
hasNewDayStartedSince interactions (tryGetLastRemoteInteraction interactions)
|
hasNewDayStartedSince interactions (tryGetLastBedroomRemoteInteraction interactions)
|
||||||
&& startOfDay <= time
|
&& startOfDay <= time
|
||||||
&& time <= endOfAlarm
|
&& time <= endOfAlarm
|
||||||
|
|
||||||
|
|
@ -81,7 +81,7 @@ type NightLightTests() =
|
||||||
|> Prop.label fakeHome.Label
|
|> Prop.label fakeHome.Label
|
||||||
|> Prop.trivial (fakeHome.LightsThatAreOn.Length = 0)
|
|> Prop.trivial (fakeHome.LightsThatAreOn.Length = 0)
|
||||||
|
|
||||||
[<Property(Arbitrary = [| typeof<ArbitraryInteractions> |])>]
|
[<Property(Arbitrary = [| typeof<ArbitraryInteractions> |], MaxTest = 500)>]
|
||||||
let ``All lights with power should have the correct state`` (interactions: Interaction list) =
|
let ``All lights with power should have the correct state`` (interactions: Interaction list) =
|
||||||
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
|
let fakeHome = createFakeHomeWithNightLightAndInteract interactions
|
||||||
|
|
||||||
|
|
@ -90,19 +90,7 @@ type NightLightTests() =
|
||||||
|> Seq.filter (fun (light, _) -> doesLightHavePowerAfterInteractions light interactions)
|
|> Seq.filter (fun (light, _) -> doesLightHavePowerAfterInteractions light interactions)
|
||||||
|> Seq.toList
|
|> Seq.toList
|
||||||
|
|
||||||
let lastBedroomRemoteInteraction =
|
let lastBedroomRemoteInteraction = tryGetLastBedroomRemoteInteraction interactions
|
||||||
interactions
|
|
||||||
|> Seq.indexed
|
|
||||||
|> Seq.choose (fun (index, interaction) ->
|
|
||||||
match interaction with
|
|
||||||
| Interaction.RemoteInteraction remoteInteraction ->
|
|
||||||
match remoteInteraction with
|
|
||||||
| RemotePressedOnButton
|
|
||||||
| RemotePressedOffButton
|
|
||||||
| RemotePressedLeftButton -> Some(index, remoteInteraction)
|
|
||||||
| RemotePressedRightButton -> None
|
|
||||||
| _ -> None)
|
|
||||||
|> Seq.tryLast
|
|
||||||
|
|
||||||
let newDayStartedSinceBedroomRemote =
|
let newDayStartedSinceBedroomRemote =
|
||||||
hasNewDayStartedSince interactions lastBedroomRemoteInteraction
|
hasNewDayStartedSince interactions lastBedroomRemoteInteraction
|
||||||
|
|
|
||||||
|
|
@ -24,64 +24,43 @@ let internal generateZigbeeCommandsToFixLight (light: Light) (desiredLightSettin
|
||||||
type internal NightLightState =
|
type internal NightLightState =
|
||||||
{ Time: DateTime
|
{ Time: DateTime
|
||||||
Alarm: bool
|
Alarm: bool
|
||||||
LightToLightSettings: Map<Light, LightSettings> }
|
LightToManualState: Map<Light, State> }
|
||||||
|
|
||||||
let internal createOrUpdateNightLightState
|
let internal computeLightSettings (light: Light) (nightLightState: NightLightState) =
|
||||||
(time: DateTime)
|
let partOfDay = getPartOfDay nightLightState.Time
|
||||||
(alarm: bool)
|
|
||||||
(maybeOldLightToLightSettings: Map<Light, LightSettings> option)
|
|
||||||
=
|
|
||||||
let partOfDay = getPartOfDay time
|
|
||||||
|
|
||||||
let lightToLightSettings =
|
|
||||||
lights
|
|
||||||
|> Seq.map (fun light ->
|
|
||||||
let color, brightness =
|
let color, brightness =
|
||||||
getDesiredMood (lightProps light).Room partOfDay
|
getDesiredMood (lightProps light).Room partOfDay
|
||||||
|> getDesiredColorAndBrightness (lightProps light).Bulb
|
|> getDesiredColorAndBrightness (lightProps light).Bulb
|
||||||
|
|
||||||
let previousState =
|
|
||||||
maybeOldLightToLightSettings
|
|
||||||
|> Option.map (fun lightToLightSettings -> lightToLightSettings[light].State)
|
|
||||||
|> Option.defaultValue On
|
|
||||||
|
|
||||||
light,
|
|
||||||
{ Color = color
|
{ Color = color
|
||||||
Brightness =
|
Brightness =
|
||||||
if alarm && (light = RightBedroomLamp || light = LeftBedroomLamp) then
|
if nightLightState.Alarm && (light = RightBedroomLamp || light = LeftBedroomLamp) then
|
||||||
brightness.Scale(getAlarmWeight time)
|
brightness.Scale(getAlarmWeight nightLightState.Time)
|
||||||
else
|
else
|
||||||
brightness
|
brightness
|
||||||
State =
|
State =
|
||||||
if alarm && (light = RightBedroomLamp || light = LeftBedroomLamp) then
|
if nightLightState.Alarm && (light = RightBedroomLamp || light = LeftBedroomLamp) then
|
||||||
On
|
On
|
||||||
else
|
else
|
||||||
previousState })
|
nightLightState.LightToManualState[light] }
|
||||||
|> Map.ofSeq
|
|
||||||
|
|
||||||
{ Time = time
|
|
||||||
Alarm = alarm
|
|
||||||
LightToLightSettings = lightToLightSettings }
|
|
||||||
|
|
||||||
let internal withStateFor (light: Light) (state: State) (oldNightLightState: NightLightState) =
|
let internal withStateFor (light: Light) (state: State) (oldNightLightState: NightLightState) =
|
||||||
let oldState = oldNightLightState.LightToLightSettings[light]
|
{ oldNightLightState with
|
||||||
|
LightToManualState = Map.add light state oldNightLightState.LightToManualState }
|
||||||
createOrUpdateNightLightState
|
|
||||||
oldNightLightState.Time
|
|
||||||
oldNightLightState.Alarm
|
|
||||||
(Map.add light { oldState with State = state } oldNightLightState.LightToLightSettings
|
|
||||||
|> Some)
|
|
||||||
|
|
||||||
let internal withAlarmOff (oldNightLightState: NightLightState) =
|
let internal withAlarmOff (oldNightLightState: NightLightState) =
|
||||||
createOrUpdateNightLightState oldNightLightState.Time false (Some oldNightLightState.LightToLightSettings)
|
{ oldNightLightState with
|
||||||
|
Alarm = false }
|
||||||
|
|
||||||
let internal generateZigbeeCommandsForDifference (maybeBefore: NightLightState option) (after: NightLightState) =
|
let internal generateZigbeeCommandsForDifference (maybeBefore: NightLightState option) (after: NightLightState) =
|
||||||
after.LightToLightSettings
|
lights
|
||||||
|> Seq.collect (fun (KeyValue(light, newState)) ->
|
|> Seq.collect (fun light ->
|
||||||
let oldState = maybeBefore |> Option.map _.LightToLightSettings[light]
|
let oldLightSettings = maybeBefore |> Option.map (computeLightSettings light)
|
||||||
|
let newLightSettings = after |> computeLightSettings light
|
||||||
|
|
||||||
if oldState <> Some newState then
|
if oldLightSettings <> Some newLightSettings then
|
||||||
generateZigbeeCommandsToFixLight light after.LightToLightSettings[light]
|
generateZigbeeCommandsToFixLight light newLightSettings
|
||||||
else
|
else
|
||||||
Seq.empty)
|
Seq.empty)
|
||||||
|
|
||||||
|
|
@ -101,7 +80,10 @@ type NightLightStateMachine private (maybeState: NightLightState option) =
|
||||||
|
|
||||||
this,
|
this,
|
||||||
match maybeLight with
|
match maybeLight with
|
||||||
| Some light -> generateZigbeeCommandsToFixLight light currentState.LightToLightSettings[light]
|
| Some light ->
|
||||||
|
currentState
|
||||||
|
|> computeLightSettings light
|
||||||
|
|> generateZigbeeCommandsToFixLight light
|
||||||
| None -> Seq.empty
|
| None -> Seq.empty
|
||||||
| ButtonPress action ->
|
| ButtonPress action ->
|
||||||
let newNightLightState =
|
let newNightLightState =
|
||||||
|
|
@ -123,7 +105,6 @@ type NightLightStateMachine private (maybeState: NightLightState option) =
|
||||||
|> withStateFor LeftBedroomLamp On
|
|> withStateFor LeftBedroomLamp On
|
||||||
| PressedRight ->
|
| PressedRight ->
|
||||||
currentState
|
currentState
|
||||||
|> withAlarmOff
|
|
||||||
|> withStateFor LivingRoomWallLamp Off
|
|> withStateFor LivingRoomWallLamp Off
|
||||||
|> withStateFor LivingRoomFloorLamp Off
|
|> withStateFor LivingRoomFloorLamp Off
|
||||||
|
|
||||||
|
|
@ -143,7 +124,12 @@ type NightLightStateMachine private (maybeState: NightLightState option) =
|
||||||
|| maybeCurrentState |> Option.map _.Alarm |> Option.defaultValue false
|
|| maybeCurrentState |> Option.map _.Alarm |> Option.defaultValue false
|
||||||
|
|
||||||
let newNightLightState =
|
let newNightLightState =
|
||||||
createOrUpdateNightLightState newTime alarm (maybeCurrentState |> Option.map _.LightToLightSettings)
|
{ Time = newTime
|
||||||
|
Alarm = alarm
|
||||||
|
LightToManualState =
|
||||||
|
maybeCurrentState
|
||||||
|
|> Option.map _.LightToManualState
|
||||||
|
|> Option.defaultValue (lights |> Seq.map (fun light -> light, On) |> Map.ofSeq) }
|
||||||
|
|
||||||
return
|
return
|
||||||
NightLightStateMachine(Some newNightLightState),
|
NightLightStateMachine(Some newNightLightState),
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue