Skip to content

Commit c32fa0c

Browse files
committed
implement state machine and transitions; extend base machine and add base alphabet
1 parent 63ca3e3 commit c32fa0c

File tree

8 files changed

+214
-30
lines changed

8 files changed

+214
-30
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package com.recom.statemachine;
2+
3+
import lombok.NonNull;
4+
import lombok.RequiredArgsConstructor;
5+
6+
@RequiredArgsConstructor
7+
abstract public class BaseAlphabet<MACHINE extends BaseStateMachine> {
8+
9+
@NonNull
10+
protected final MACHINE machine;
11+
12+
13+
}

libs/statemachine/src/main/java/com/recom/statemachine/BaseStateMachine.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,42 @@
11
package com.recom.statemachine;
22

33
import lombok.Getter;
4+
import lombok.Locked;
45
import lombok.NonNull;
56
import lombok.Setter;
67
import org.springframework.lang.Nullable;
78

89
import java.time.Duration;
910
import java.time.Instant;
1011

11-
abstract public class BaseStateMachine<STATES extends Enum, TRANSITIONS extends BaseTransition<? extends BaseStateMachine, STATES>, EVENT extends BaseFSMEvent> {
12+
abstract public class BaseStateMachine<
13+
STATES extends Enum,
14+
TRANSITIONS extends BaseTransition<? extends BaseStateMachine<STATES, TRANSITIONS, ALPHABET, EVENT>>,
15+
ALPHABET extends BaseAlphabet<? extends BaseStateMachine<STATES, TRANSITIONS, ALPHABET, EVENT>>,
16+
EVENT extends BaseFSMEvent
17+
> {
1218

1319
@Getter
1420
@Setter
1521
@Nullable
1622
protected STATES currentMachineState;
1723
protected TRANSITIONS transitions;
24+
protected ALPHABET alphabet;
1825
@NonNull
1926
private Instant lastEvent = Instant.now();
2027

2128
protected BaseStateMachine() {
2229
currentMachineState = null;
2330
transitions = initTransitions();
31+
alphabet = initAlphabet();
2432
}
2533

2634
@NonNull
2735
protected abstract TRANSITIONS initTransitions();
2836

37+
@NonNull
38+
protected abstract ALPHABET initAlphabet();
39+
2940
private boolean triggerReRun = false;
3041

3142
public abstract void start();
@@ -48,6 +59,7 @@ protected void triggerReRun() {
4859
triggerReRun = true;
4960
}
5061

62+
@Locked
5163
public void nextEvent(@NonNull final EVENT event) throws IllegalStateException {
5264
do {
5365
triggerReRun = false;

libs/statemachine/src/main/java/com/recom/statemachine/BaseTransition.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import lombok.RequiredArgsConstructor;
55

66
@RequiredArgsConstructor
7-
abstract public class BaseTransition<MACHINE extends BaseStateMachine, STATES extends Enum> {
7+
abstract public class BaseTransition<MACHINE extends BaseStateMachine> {
88

99
protected final MACHINE machine;
1010

@@ -13,4 +13,8 @@ protected IllegalStateException getFsmIsNotStarted() {
1313
return new IllegalStateException("FSM is not started");
1414
}
1515

16+
protected IllegalStateException exceptWithDefault() {
17+
return new IllegalStateException("Unexpected value: " + machine.getCurrentMachineState());
18+
}
19+
1620
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.recom.statemachine.game;
2+
3+
import com.recom.model.HeartbeatModel;
4+
import com.recom.statemachine.BaseAlphabet;
5+
import lombok.NonNull;
6+
7+
class GameAlphabet extends BaseAlphabet<GameMachine> {
8+
9+
public GameAlphabet(@NonNull final GameMachine gameMachine) {
10+
super(gameMachine);
11+
}
12+
13+
public boolean map_is_not_ready_ISH(@NonNull final GameEvent event) {
14+
return event instanceof HeartbeatModel heartbeat && machine.gameMapService.provideGameMap(heartbeat.getMapName()).isEmpty();
15+
}
16+
17+
public boolean map_is_ready_ISH(@NonNull final GameEvent event) {
18+
return event instanceof HeartbeatModel heartbeat && machine.gameMapService.provideGameMap(heartbeat.getMapName()).isPresent();
19+
}
20+
21+
public boolean scan_sector_ISH(@NonNull final GameEvent event) {
22+
return false;
23+
}
24+
25+
public boolean map_is_scanned_completely_ISH(@NonNull final GameEvent event) {
26+
return false;
27+
}
28+
29+
public boolean request_map_meta_ISH(@NonNull final GameEvent event) {
30+
return false;
31+
}
32+
33+
public boolean map_meta_is_created_ISH(@NonNull final GameEvent event) {
34+
return false;
35+
}
36+
37+
public boolean map_meta_not_created_ISH(@NonNull final GameEvent event) {
38+
return false;
39+
}
40+
41+
}

services/recom-backend/src/main/java/com/recom/statemachine/game/GameMachine.java

Lines changed: 40 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.recom.statemachine.game;
22

3-
import com.recom.model.HeartbeatModel;
43
import com.recom.service.map.GameMapService;
54
import com.recom.service.messagebus.MessageBusService;
65
import com.recom.statemachine.BaseStateMachine;
@@ -10,69 +9,88 @@
109
import java.time.Duration;
1110

1211
@RequiredArgsConstructor
13-
public class GameMachine extends BaseStateMachine<GameStates, GameTransitions, GameEvent> {
12+
public class GameMachine extends BaseStateMachine<GameStates, GameTransitions, GameAlphabet, GameEvent> {
1413

1514
@NonNull
16-
private final GameMapService gameMapService;
15+
final GameMapService gameMapService;
1716
@NonNull
18-
private final MessageBusService messageBusService;
17+
final private MessageBusService messageBusService;
1918

2019
@NonNull
2120
@Override
2221
protected GameTransitions initTransitions() {
2322
return new GameTransitions(this);
2423
}
2524

25+
@NonNull
26+
@Override
27+
protected GameAlphabet initAlphabet() {
28+
return new GameAlphabet(this);
29+
}
30+
2631
@Override
2732
public void start() {
2833
currentMachineState = GameStates.CHECK_MAP;
34+
transitions.start();
2935
trackEventTime();
3036
}
3137

3238
@Override
3339
public void stop() {
34-
currentMachineState = GameStates.STOPPED;
40+
transitions.end();
3541
trackEventTime();
3642
}
3743

3844
@Override
3945
protected void handleEvent(
4046
@NonNull final GameEvent event,
4147
@NonNull final Duration deltaTime
42-
4348
) throws IllegalStateException {
4449
switch (currentMachineState) {
4550
case CHECK_MAP:
46-
if (event instanceof HeartbeatModel heartbeat) {
47-
if (gameMapService.provideGameMap(heartbeat.getMapName()).isPresent()) {
48-
transitions.map_is_ready();
49-
triggerReRun();
50-
} else {
51-
transitions.map_is_not_ready();
52-
triggerReRun();
53-
}
51+
if (alphabet.map_is_not_ready_ISH(event)) {
52+
transitions.map_is_not_ready();
53+
triggerReRun();
54+
} else if (alphabet.map_is_ready_ISH(event)) {
55+
transitions.map_is_ready();
56+
triggerReRun();
5457
}
5558
break;
5659
case SCAN_MAP:
60+
if (alphabet.map_is_scanned_completely_ISH(event)) {
61+
transitions.map_is_scanned_completely();
62+
triggerReRun();
63+
} else if (alphabet.scan_sector_ISH(event)) {
64+
transitions.scan_sector();
65+
triggerReRun();
66+
} else if (alphabet.request_map_meta_ISH(event)) {
67+
transitions.request_map_meta();
68+
triggerReRun();
69+
}
5770

5871
// 1. request map_meta_creation if not exists
5972
// 2. wait for map_meta_creation in state
6073
// 3. trigger map_meta_is_created
6174

6275
// messageBusService.sendMessage();
6376
break;
64-
case IN_GAME:
77+
case REQUEST_MAP_META:
78+
if (alphabet.map_meta_is_created_ISH(event)) {
79+
transitions.map_meta_is_created();
80+
triggerReRun();
81+
} else if (alphabet.map_meta_not_created_ISH(event)) {
82+
transitions.map_meta_not_created();
83+
triggerReRun();
84+
}
6585
break;
86+
case IN_GAME:
87+
break; // nothing to do yet here
6688
case STOPPED:
67-
// fsm is stopped
68-
break;
89+
throw new IllegalStateException("FSM is stopped");
6990
case null:
70-
// fsm is not started
71-
break;
91+
throw new IllegalStateException("FSM is not started");
7292
default:
73-
// unknown state
74-
throw new IllegalStateException("Unexpected value: " + currentMachineState);
75-
// break;
93+
throw new IllegalStateException("Unknown state in FSM detected: " + currentMachineState);
7694
}
7795
}
7896

services/recom-backend/src/main/java/com/recom/statemachine/game/GameMachine.puml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,10 @@ CHECK_MAP --> SCAN_MAP :map_is_not_ready
1111
CHECK_MAP --> IN_GAME :map_is_ready
1212

1313
SCAN_MAP --> REQUEST_MAP_META :request_map_meta
14-
REQUEST_MAP_META --> SCAN_MAP :map_meta_created
14+
REQUEST_MAP_META --> SCAN_MAP :map_meta_is_created
1515
REQUEST_MAP_META --> REQUEST_MAP_META :map_meta_not_created
1616
SCAN_MAP --> SCAN_MAP :scan_sector
17-
SCAN_MAP --> IN_GAME :map_is_scanned
17+
SCAN_MAP --> IN_GAME :map_is_scanned_completely
1818

1919

2020

@@ -33,7 +33,10 @@ __**ALPHABET**__
3333
| map_is_not_ready | ... |
3434
| create_map | ... |
3535
| scan_sector | ... |
36-
| map_is_scanned | ... |
36+
| map_is_scanned_completely | ... |
37+
| request_map_meta | ... |
38+
| map_meta_not_created | ... |
39+
| map_meta_is_created | ... |
3740
endlegend
3841

3942
@enduml

services/recom-backend/src/main/java/com/recom/statemachine/game/GameStates.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
public enum GameStates {
44

55
CHECK_MAP,
6+
REQUEST_MAP_META,
67
SCAN_MAP,
78
IN_GAME,
89
STOPPED

0 commit comments

Comments
 (0)