Skip to content

Commit

Permalink
Merge pull request #4 from chickensoft-games/fix/callbacks
Browse files Browse the repository at this point in the history
fix: ensure correct callback behavior with reusable states
  • Loading branch information
jolexxa authored Jul 26, 2023
2 parents 13cbb60 + a9f2af9 commit f0a27ee
Show file tree
Hide file tree
Showing 42 changed files with 1,025 additions and 382 deletions.
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,3 @@ obj/
.generated/
.vs/
.DS_Store
*.g.puml
8 changes: 4 additions & 4 deletions Chickensoft.LogicBlocks.Example/VendingMachine.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ public abstract record State(Context Context) : StateLogic(Context) {
public record Idle : State,
IGet<Input.SelectionEntered>, IGet<Input.PaymentReceived> {
public Idle(Context context) : base(context) {
context.OnEnter<Idle>((previous) => context.Output(
OnEnter<Idle>((previous) => context.Output(
new Output.ClearTransactionTimeOutTimer()
));
}
Expand Down Expand Up @@ -55,7 +55,7 @@ public TransactionActive(
Price = price;
AmountReceived = amountReceived;

Context.OnEnter<TransactionActive>(
OnEnter<TransactionActive>(
(previous) => Context.Output(
new Output.RestartTransactionTimeOutTimer()
)
Expand Down Expand Up @@ -97,7 +97,7 @@ public record Started : TransactionActive,
public Started(
Context context, ItemType type, int price, int amountReceived
) : base(context, type, price, amountReceived) {
context.OnEnter<Started>(
OnEnter<Started>(
(previous) => context.Output(new Output.TransactionStarted())
);
}
Expand Down Expand Up @@ -128,7 +128,7 @@ public Vending(Context context, ItemType type, int price) :
Type = type;
Price = price;

context.OnEnter<Vending>(
OnEnter<Vending>(
(previous) => Context.Output(new Output.BeginVending())
);
}
Expand Down
32 changes: 32 additions & 0 deletions Chickensoft.LogicBlocks.Example/VendingMachine.g.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@startuml VendingMachine
state "VendingMachine State" as Chickensoft_LogicBlocks_Example_VendingMachine_State {
state "Idle" as Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle {
Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : OnEnterClearTransactionTimeOutTimer
Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : OnPaymentReceivedMakeChange
}
state "TransactionActive" as Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive {
state "Started" as Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started {
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started : OnEnterTransactionStarted
}
state "PaymentPending" as Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_PaymentPending
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive : OnEnterRestartTransactionTimeOutTimer
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive : OnPaymentReceivedMakeChange, TransactionCompleted
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive : OnTransactionTimedOutMakeChange
}
state "Vending" as Chickensoft_LogicBlocks_Example_VendingMachine_State_Vending {
Chickensoft_LogicBlocks_Example_VendingMachine_State_Vending : OnEnterBeginVending
}
}

Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : PaymentReceived
Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : SelectionEntered
Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle --> Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started : SelectionEntered
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : TransactionTimedOut
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive --> Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_PaymentPending : PaymentReceived
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Vending : PaymentReceived
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : SelectionEntered
Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started --> Chickensoft_LogicBlocks_Example_VendingMachine_State_TransactionActive_Started : SelectionEntered
Chickensoft_LogicBlocks_Example_VendingMachine_State_Vending --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle : VendingCompleted

[*] --> Chickensoft_LogicBlocks_Example_VendingMachine_State_Idle
@enduml
2 changes: 1 addition & 1 deletion Chickensoft.LogicBlocks.Generator.Tests/GeneratorTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public void GeneratesUml() {

result.Outputs["ToasterOven.puml.g.cs"].ShouldBe("""
@startuml ToasterOven
state "ToasterOven" as State {
state "ToasterOven State" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State {
state "Heating" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Heating {
state "Toasting" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting {
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting : OnEnter → SetTimer
Expand Down
21 changes: 10 additions & 11 deletions Chickensoft.LogicBlocks.Generator.Tests/test_cases/Heater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,26 +52,25 @@ public Heating(Context context, double targetTemp) : base(
) {
var tempSensor = context.Get<ITemperatureSensor>();

context.OnEnter<Heating>(
OnEnter<Heating>(
(previous) => tempSensor.OnTemperatureChanged += OnTemperatureChanged
);

context.OnExit<Heating>(
OnExit<Heating>(
(next) => tempSensor.OnTemperatureChanged -= OnTemperatureChanged
);
}

State IGet<Input.TurnOff>.On(Input.TurnOff input)
=> new Off(Context, TargetTemp);
public State On(Input.TurnOff input) => new Off(Context, TargetTemp);

State IGet<Input.AirTempSensorChanged>.On(
Input.AirTempSensorChanged input
) => input.AirTemp >= TargetTemp
? new Idle(Context, TargetTemp)
: this;
public State On(Input.AirTempSensorChanged input) =>
input.AirTemp >= TargetTemp
? new Idle(Context, TargetTemp)
: this;

State IGet<Input.TargetTempChanged>.On(Input.TargetTempChanged input)
=> this with { TargetTemp = input.Temp };
public State On(Input.TargetTempChanged input) => this with {
TargetTemp = input.Temp
};

private void OnTemperatureChanged(double airTemp) {
Context.Input(new Input.AirTempSensorChanged(airTemp));
Expand Down
17 changes: 17 additions & 0 deletions Chickensoft.LogicBlocks.Generator.Tests/test_cases/Heater.g.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
@startuml Heater
state "Heater State" as Chickensoft_LogicBlocks_Generator_Tests_Heater_State {
state "Off" as Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Off
state "Idle" as Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Idle
state "Heating" as Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating {
Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating : OnTemperatureChanged() → AirTempChanged
}
}

Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating : AirTempSensorChanged
Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating : TargetTempChanged
Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Idle : AirTempSensorChanged
Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Off : TurnOff
Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Off --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Heating : TurnOn

[*] --> Chickensoft_LogicBlocks_Generator_Tests_Heater_State_Off
@enduml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
@startuml LightSwitch
state "LightSwitch State" as Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State {
state "On" as Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_On
state "Off" as Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_Off
}

Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_Off --> Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_On : Toggle
Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_On --> Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_Off : Toggle

[*] --> Chickensoft_LogicBlocks_Generator_Tests_LightSwitch_State_Off
@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ public record StartToasting(int ToastColor) : Input;
public abstract record State(Context Context) : StateLogic(Context) {
public record Heating : State, IGet<Input.OpenDoor> {
public Heating(Context context) : base(context) {
Context.OnEnter<Heating>(
OnEnter<Heating>(
(previous) => Context.Output(new Output.TurnHeaterOn())
);
Context.OnExit<Heating>(
OnExit<Heating>(
(next) => Context.Output(new Output.TurnHeaterOff())
);
}
Expand All @@ -32,10 +32,10 @@ public record Toasting : Heating, IGet<Input.StartBaking> {
public Toasting(Context context, int toastColor) : base(context) {
ToastColor = toastColor;

Context.OnEnter<Toasting>(
OnEnter<Toasting>(
(previous) => Context.Output(new Output.SetTimer(ToastColor))
);
Context.OnExit<Toasting>(
OnExit<Toasting>(
(next) => Context.Output(new Output.ResetTimer())
);
}
Expand All @@ -51,10 +51,10 @@ public record Baking : Heating, IGet<Input.StartToasting> {
public Baking(Context context, int temperature) : base(context) {
Temperature = temperature;

Context.OnEnter<Baking>(
OnEnter<Baking>(
(previous) => Context.Output(new Output.SetTemperature(Temperature))
);
Context.OnExit<Baking>(
OnExit<Baking>(
(next) => Context.Output(new Output.SetTemperature(0))
);
}
Expand All @@ -66,10 +66,10 @@ public Baking(Context context, int temperature) : base(context) {

public record DoorOpen : State, IGet<Input.CloseDoor> {
public DoorOpen(Context context) : base(context) {
Context.OnEnter<DoorOpen>(
OnEnter<DoorOpen>(
(previous) => Context.Output(new Output.TurnLampOn())
);
Context.OnExit<DoorOpen>(
OnExit<DoorOpen>(
(next) => Context.Output(new Output.TurnLampOff())
);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
@startuml ToasterOven
state "ToasterOven State" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State {
state "Heating" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Heating {
state "Toasting" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting {
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting : OnEnterSetTimer
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting : OnExitResetTimer
}
state "Baking" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Baking {
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Baking : OnEnterSetTemperature
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Baking : OnExitSetTemperature
}
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Heating : OnEnterTurnHeaterOn
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Heating : OnExitTurnHeaterOff
}
state "DoorOpen" as Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_DoorOpen {
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_DoorOpen : OnEnterTurnLampOn
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_DoorOpen : OnExitTurnLampOff
}
}

Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Baking --> Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting : StartToasting
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_DoorOpen --> Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting : CloseDoor
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Heating --> Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_DoorOpen : OpenDoor
Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting --> Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Baking : StartBaking

[*] --> Chickensoft_LogicBlocks_Generator_Tests_ToasterOven_State_Toasting
@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ public abstract record Output {
public record OutputA : Output;
public record OutputEnterA : Output;
public record OutputExitA : Output;
public record OutputSomething : Output;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
@startuml PartialLogic
state "PartialLogic State" as Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State {
state "A" as Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A {
Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A : DoSomething() → OutputSomething
Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A : OnEnterOutputEnterA
Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A : OnExitOutputExitA
Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A : OnOneOutputA
}
state "B" as Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_B
}

Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_A --> Chickensoft_LogicBlocks_Generator_Tests_PartialLogic_State_B : One
@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@ public partial class PartialLogic :
public abstract partial record State : StateLogic {
public partial record A : State, IGet<Input.One> {
public A(Context context) : base(context) {
Context.OnEnter<A>(
OnEnter<A>(
(previous) => Context.Output(new Output.OutputEnterA())
);
Context.OnExit<A>(
OnExit<A>(
(next) => Context.Output(new Output.OutputExitA())
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public State On(Input.One input) {
Context.Output(new Output.OutputA());
return new B(Context);
}

public void DoSomething() => Context.Output(new Output.OutputSomething());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<NoWarn>NU5128</NoWarn>

<Title>LogicBlocks Generator</Title>
<Version>1.3.0</Version>
<Version>2.0.0-beta.1</Version>
<Description></Description>
<Copyright>© 2023 Chickensoft Games</Copyright>
<Authors>Chickensoft</Authors>
Expand Down
Loading

0 comments on commit f0a27ee

Please sign in to comment.