GS2 States Language 정의 확장
GS2 States Language를 CDK로 정의하기 위한 확장 구문에 대하여
GSL은 가독성과 표현력이 뛰어난 스테이트 머신 정의 언어이지만, IDE의 입력 지원이나 학습 비용의 관점에서는 뛰어나다고 하기 어려운 측면이 있습니다. 다양한 프로그래밍 언어를 사용하여 GSL을 정의하는 방법으로 CDK를 이용할 수 있습니다.
스테이트 머신 정의 시작
스테이트 머신 정의를 시작하려면 다음 구문을 사용합니다.
class TestStateMachine extends io.gs2.cdk.stateMachine.integration.StateMachineDefinition {
public TestStateMachine() {
// 여기에 스테이트 정의를 기술
}
} class TestStateMachine extends \Gs2Cdk\StateMachine\Integration\StateMachineDefinition {
public function __construct() {
parent::__construct();
// 여기에 스테이트 정의를 기술
}
} class TestStateMachine(gs2_cdk.state_machine.StateMachineDefinition):
def __init__(self):
# 여기에 스테이트 정의를 기술 class TestStateMachine extends StateMachineDefinition {
constructor() {
super();
// 여기에 스테이트 정의를 기술
}
} public class TestStateMachine : Gs2Cdk.Gs2StateMachine.Integration.StateMachineDefinition
{
public TestStateMachine()
{
// 여기에 스테이트 정의를 기술
}
}스테이트 머신 정의
stateMachine(
"MainStateMachine", // 스테이트 머신의 이름
new IVariable[]{
new IntType("turn")
} // 스테이트 머신이 받는 파라미터
)
.entryPoint(task1.getName()) // 스테이트 머신의 첫 번째 스테이트 이름
.task(
task1,
task2,
error // 스테이트의 종류
); $this->stateMachine(
"MainStateMachine", // 스테이트 머신의 이름
[
new IntType("turn"),
] // 스테이트 머신이 받는 파라미터
)
->entryPoint($task1->getName()) // 스테이트 머신의 첫 번째 스테이트 이름
->task(
$task1,
$task2,
$error // 스테이트의 종류
); self.state_machine(
name="MainStateMachine", # 스테이트 머신의 이름
variables=[
self.int_type("turn"),
], # 스테이트 머신이 받는 파라미터
).entry_point(
task_name=task1.name, # 스테이트 머신의 첫 번째 스테이트 이름
).task(
task1,
task2,
error, # 스테이트의 종류
) this.stateMachine(
"MainStateMachine", // 스테이트 머신의 이름
[
this.intType("turn"),
] // 스테이트 머신이 받는 파라미터
)
.entryPoint(task1.name) // 스테이트 머신의 첫 번째 스테이트 이름
.task(
task1,
task2,
error // 스테이트의 종류
) StateMachine(
"MainStateMachine", // 스테이트 머신의 이름
new IVariable[] {
IntType("turn")
} // 스테이트 머신이 받는 파라미터
)
.EntryPoint(task1.Name) // 스테이트 머신의 첫 번째 스테이트 이름
.Task(
task1,
task2,
error // 스테이트의 종류
);스테이트 정의
Task
var task1 = scriptTask(
"Task1", // 스테이트 이름
new IVariable[0], // 스테이트가 받는 파라미터 목록
"""
result = 'Pass'
""" // 스테이트로 전환되었을 때 실행할 Lua 스크립트
)
.result(
"Pass", // 스크립트가 발행하는 결과(Pass)
new HashMap<>(), // 다음 스테이트에 전달할 파라미터
task2.getName() // Pass가 발행된 경우 전환할 스테이트 이름
)
.result(
"Error", // 스크립트가 발행하는 결과(Error)
Map.of(
new StringType("reason"), // 다음 스테이트에 전달할 파라미터의 이름과 타입
"reason" // 파라미터에 전달할 Lua 변수명
),
error.getName() // Error가 발행된 경우 전환할 스테이트 이름
); $task1 = $this->scriptTask(
"Task1", // 스테이트 이름
[], // 스테이트가 받는 파라미터 목록
"result = 'Pass'" // 스테이트로 전환되었을 때 실행할 Lua 스크립트
)
->result(
"Pass", // 스크립트가 발행하는 결과(Pass)
[], // 다음 스테이트에 전달할 파라미터
$task2->getName() // Pass가 발행된 경우 전환할 스테이트 이름
)
->result(
"Error", // 스크립트가 발행하는 결과(Error)
[
[
new StringType('reason'), // 다음 스테이트에 전달할 파라미터의 이름과 타입
'reason' // 파라미터에 전달할 Lua 변수명
],
],
$error->getName() // Error가 발행된 경우 전환할 스테이트 이름
); task1 = self.script_task(
name="Task1", # 스테이트 이름
arguments=[], # 스테이트가 받는 파라미터 목록
script="""
result = 'Pass'
""", # 스테이트로 전환되었을 때 실행할 Lua 스크립트
).result(
result_name="Pass", # 스크립트가 발행하는 결과(Pass)
emit_event_argument_variable_names={}, # 다음 스테이트에 전달할 파라미터
next_task_name=task2.name, # Pass가 발행된 경우 전환할 스테이트 이름
).result(
result_name="Error", # 스크립트가 발행하는 결과(Error)
emit_event_argument_variable_names={
self.string_type("reason"): # 다음 스테이트에 전달할 파라미터의 이름과 타입
"reason", # 파라미터에 전달할 Lua 변수명
},
next_task_name=error.name, # Error가 발행된 경우 전환할 스테이트 이름
) let task1 = this.scriptTask(
"Task1", // 스테이트 이름
[], // 스테이트가 받는 파라미터 목록
`
result = 'Pass'
` // 스테이트로 전환되었을 때 실행할 Lua 스크립트
)
.result(
"Pass", // 스크립트가 발행하는 결과(Pass)
new Map(), // 다음 스테이트에 전달할 파라미터
task2.getName() // Pass가 발행된 경우 전환할 스테이트 이름
)
.result(
"Error", // 스크립트가 발행하는 결과(Error)
new Map([
[
new StringType("reason"), // 다음 스테이트에 전달할 파라미터의 이름과 타입
"reason" // 파라미터에 전달할 Lua 변수명
]
]),
error.getName() // Error가 발행된 경우 전환할 스테이트 이름
); var task1 = ScriptTask(
"Task1", // 스테이트 이름
new IVariable[0], // 스테이트가 받는 파라미터 목록
@"
result = 'Pass'
" // 스테이트로 전환되었을 때 실행할 Lua 스크립트
)
.Result(
"Pass", // 스크립트가 발행하는 결과(Pass)
new Dictionary<IVariable, string>(), // 다음 스테이트에 전달할 파라미터
task2.Name // Pass가 발행된 경우 전환할 스테이트 이름
)
.Result(
"Error", // 스크립트가 발행하는 결과(Error)
new Dictionary<IVariable, string> {
{
new StringType("reason"), // 다음 스테이트에 전달할 파라미터의 이름과 타입
"reason" // 파라미터에 전달할 Lua 변수명
}
},
error.Name // Error가 발행된 경우 전환할 스테이트 이름
);SubStateMachineTask
var task3 = subStateMachineTask(
"ChoiceSkill", // 스테이트 이름
"ChoiceSkill", // 전환할 서브 스테이트 머신 이름
new InParam[] {
this.inParam(
this.intType("turn"), // 현재 실행 중인 스테이트 머신의 상태 변수 이름
this.intType("turn") // 서브 스테이트 머신의 첫 번째 스테이트에 파라미터로 전달할 인수 이름
)
},
new OutParam[] {
this.outParam(
this.intType("choiceSkill"), // 서브 스테이트 머신으로부터 결과로 받는 상태 변수 이름
this.intType("choiceSkill") // 서브 스테이트 머신에서 돌아온 후의 스테이트에 파라미터로 전달할 인수 이름
)
},
"InGame" // 서브 스테이트 머신에서 돌아온 후 전환할 스테이트 이름
) $task3 = $this->subStateMachineTask(
"ChoiceSkill", // 스테이트 이름
"ChoiceSkill", // 전환할 서브 스테이트 머신 이름
[
$this->inParam(
$this->intType("turn"), // 현재 실행 중인 스테이트 머신의 상태 변수 이름
$this->intType("turn") // 서브 스테이트 머신의 첫 번째 스테이트에 파라미터로 전달할 인수 이름
)
],
[
$this->outParam(
$this->intType("choiceSkill"), // 서브 스테이트 머신으로부터 결과로 받는 상태 변수 이름
$this->intType("choiceSkill") // 서브 스테이트 머신에서 돌아온 후의 스테이트에 파라미터로 전달할 인수 이름
)
],
"InGame" // 서브 스테이트 머신에서 돌아온 후 전환할 스테이트 이름
) task3 = self.sub_state_machine_task(
name='ChoiceSkill', # 스테이트 이름
sub_state_machine_name="ChoiceSkill", # 전환할 서브 스테이트 머신 이름
in_params=[
self.in_param(
self.int_type("turn"), # 현재 실행 중인 스테이트 머신의 상태 변수 이름
self.int_type("turn") # 서브 스테이트 머신의 첫 번째 스테이트에 파라미터로 전달할 인수 이름
),
],
out_params=[
self.out_param(
self.int_type("choiceSkill"), # 서브 스테이트 머신으로부터 결과로 받는 상태 변수 이름
self.int_type("choiceSkill") # 서브 스테이트 머신에서 돌아온 후의 스테이트에 파라미터로 전달할 인수 이름
),
],
next_task_name="InGame", # 서브 스테이트 머신에서 돌아온 후 전환할 스테이트 이름
) let task3 = this.subStateMachineTask(
"ChoiceSkill", // 스테이트 이름
"ChoiceSkill", // 전환할 서브 스테이트 머신 이름
[
this.inParam(
this.intType("turn"), // 현재 실행 중인 스테이트 머신의 상태 변수 이름
this.intType("turn") // 서브 스테이트 머신의 첫 번째 스테이트에 파라미터로 전달할 인수 이름
),
],
[
this.outParam(
this.intType("choiceSkill"), // 서브 스테이트 머신으로부터 결과로 받는 상태 변수 이름
this.intType("choiceSkill") // 서브 스테이트 머신에서 돌아온 후의 스테이트에 파라미터로 전달할 인수 이름
),
],
"InGame" // 서브 스테이트 머신에서 돌아온 후 전환할 스테이트 이름
) var task3 = SubStateMachineTask(
"ChoiceSkill", // 스테이트 이름
"ChoiceSkill", // 전환할 서브 스테이트 머신 이름
new InParam[] {
InParam(
IntType("turn"), // 현재 실행 중인 스테이트 머신의 상태 변수 이름
IntType("turn") // 서브 스테이트 머신의 첫 번째 스테이트에 파라미터로 전달할 인수 이름
)
},
new OutParam[] {
OutParam(
IntType("choiceSkill"), // 서브 스테이트 머신으로부터 결과로 받는 상태 변수 이름
IntType("choiceSkill") // 서브 스테이트 머신에서 돌아온 후의 스테이트에 파라미터로 전달할 인수 이름
)
},
"InGame" // 서브 스테이트 머신에서 돌아온 후 전환할 스테이트 이름
)WaitTask
var task4 = this.waitTask(
"WaitChoiceSkill" // 스테이트 이름
).result(
"ChoiceSkill", // 대기할 이벤트의 이름
new HashMap<>() {{ // 대기할 이벤트의 파라미터
put(
stringType("skill"), // 전환 대상 스테이트에 전달할 파라미터의 타입과 이름
"skill" // 이벤트에서 받는 파라미터의 이름
);
}},
"ChoiceSkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
).result(
"ReLotterySkill", // 대기할 이벤트의 이름
new HashMap<>(), // 대기할 이벤트의 파라미터
"ReLotterySkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
) $task4 = $this->waitTask(
"WaitChoiceSkill" // 스테이트 이름
)->result(
"ChoiceSkill", // 대기할 이벤트의 이름
[ // 대기할 이벤트의 파라미터
[
$this->stringType("skill"), // 전환 대상 스테이트에 전달할 파라미터의 타입과 이름
"skill" // 이벤트에서 받는 파라미터의 이름
]
],
"ChoiceSkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
)->result(
"ReLotterySkill", // 대기할 이벤트의 이름
[], // 대기할 이벤트의 파라미터
"ReLotterySkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
) task4 = self.wait_task(
name="WaitChoiceSkill", # 스테이트 이름
).result(
result_name="ChoiceSkill", # 대기할 이벤트의 이름
emit_event_argument_variable_names={ # 대기할 이벤트의 파라미터
self.string_type("skill"): # 전환 대상 스테이트에 전달할 파라미터의 타입과 이름
"skill", # 이벤트에서 받는 파라미터의 이름
},
next_task_name="ChoiceSkill", # 이 이벤트를 받았을 때 전환할 스테이트 이름
).result(
result_name="ReLotterySkill", # 대기할 이벤트의 이름
emit_event_argument_variable_names={ # 대기할 이벤트의 파라미터
},
next_task_name="ReLotterySkill", # 이 이벤트를 받았을 때 전환할 스테이트 이름
) let task4 = this.waitTask(
"WaitChoiceSkill" // 스테이트 이름
).result(
"ChoiceSkill", // 대기할 이벤트의 이름
new Map<IVariable, string>() // 대기할 이벤트의 파라미터
.set(
this.stringType("skill"), // 전환 대상 스테이트에 전달할 파라미터의 타입과 이름
"skill" // 이벤트에서 받는 파라미터의 이름
),
"ChoiceSkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
).result(
"ReLotterySkill", // 대기할 이벤트의 이름
new Map<IVariable, string>(), // 대기할 이벤트의 파라미터
"ReLotterySkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
) var task4 = this.WaitTask(
"WaitChoiceSkill" // 스테이트 이름
).Result(
"ChoiceSkill", // 대기할 이벤트의 이름
new Dictionary<IVariable, string>{{ // 대기할 이벤트의 파라미터
StringType("skill"), // 전환 대상 스테이트에 전달할 파라미터의 타입과 이름
"skill" // 이벤트에서 받는 파라미터의 이름
}},
"ChoiceSkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
).Result(
"ReLotterySkill", // 대기할 이벤트의 이름
new Dictionary<IVariable, string>(), // 대기할 이벤트의 파라미터
"ReLotterySkill" // 이 이벤트를 받았을 때 전환할 스테이트 이름
)PassTask
var task2 = passTask(
"Task2" // 스테이트 이름
); $task2 = $this->passTask(
"Task2" // 스테이트 이름
); task2 = self.pass_task(
name="Task2" # 스테이트 이름
) let task2 = this.passTask(
"Task2" // 스테이트 이름
); var task2 = PassTask(
"Task2" // 스테이트 이름
);ErrorTask
var error = errorTask(
"Error" // 스테이트 이름
); $error = $this->errorTask(
"Error" // 스테이트 이름
); error = self.error_task(
name="Error" # 스테이트 이름
) let error = this.errorTask(
"Error" // 스테이트 이름
); var error = ErrorTask(
"Error" // 스테이트 이름
);스택에 등록
new io.gs2.cdk.stateMachine.model.Namespace(
this, // Stack 객체
"state-machine-0001" // GS2-StateMachine의 네임스페이스 이름
).stateMachine(
new io.gs2.cdk.script.model.Namespace(
this, // Stack 객체
"script-0001" // GS2-Script의 네임스페이스 이름
),
new TestStateMachine() // StateMachineDefinition 객체
); (new \Gs2Cdk\StateMachine\Model\Namespace_(
$this, // Stack 객체
"state-machine-0001" // GS2-StateMachine의 네임스페이스 이름
))->stateMachine(
new \Gs2Cdk\Script\Model\Namespace_(
$this, // Stack 객체
"script-0001" // GS2-Script의 네임스페이스 이름
),
new TestStateMachine() // StateMachineDefinition 객체
); gs2_cdk.state_machine.Namespace(
self, # Stack 객체
name='state-machine-0001', # GS2-StateMachine의 네임스페이스 이름
).state_machine(
script_namespace=gs2_cdk.script.Namespace(
self, # Stack 객체
name='script-0001', # GS2-Script의 네임스페이스 이름
),
definition=TestStateMachine(), # StateMachineDefinition 객체
) new StateMachineNamespace(
this, // Stack 객체
"state-machine-0001" // GS2-StateMachine의 네임스페이스 이름
).stateMachine(
new ScriptNamespace(
this, // Stack 객체
"script-0001" // GS2-Script의 네임스페이스 이름
),
new TestStateMachine() // StateMachineDefinition 객체
); new Gs2Cdk.Gs2StateMachine.Model.Namespace(
this, // Stack 객체
"state-machine-0001" // GS2-StateMachine의 네임스페이스 이름
).StateMachine(
Gs2Cdk.Gs2Script.Model.Namespace(
this, // Stack 객체
"script-0001" // GS2-Script의 네임스페이스 이름
),
new TestStateMachine() // StateMachineDefinition 객체
);전체 샘플
class TestStateMachine extends StateMachineDefinition {
public TestStateMachine() {
ErrorTask error = errorTask("Error");
PassTask task2 = passTask("Task2");
Task task1 = scriptTask(
"Task1",
new IVariable[0],
"""
result = 'Pass'
"""
)
.result("Pass", new HashMap<>(), task2.getName())
.result("Error", Map.of(new StringType("reason"), "reason"), error.getName());
stateMachine(
"MainStateMachine",
new IVariable[]{new IntType("turn")}
)
.entryPoint(task1.getName())
.task(task1, task2, error);
}
}
class TestStateMachineStack extends Stack {
public TestStateMachineStack() {
super();
new io.gs2.cdk.stateMachine.model.Namespace(this, "state-machine-0001")
.stateMachine(
new io.gs2.cdk.script.model.Namespace(this, "script-0001"),
new TestStateMachine()
);
}
} class TestStateMachine extends StateMachineDefinition {
public function __construct() {
parent::__construct();
$error = $this->errorTask("Error");
$task2 = $this->passTask("Task2");
$task1 = $this->scriptTask(
"Task1",
[],
"result = 'Pass'"
)
->result("Pass", [], $task2->getName())
->result("Error", [[new StringType('reason'), 'reason']], $error->getName());
$this->stateMachine(
"MainStateMachine",
[new IntType("turn")]
)
->entryPoint($task1->getName())
->task($task1, $task2, $error);
}
}
class TestStateMachineStack extends Stack {
public function __construct() {
parent::__construct();
(new \Gs2Cdk\StateMachine\Model\Namespace_($this, "state-machine-0001"))
->stateMachine(
new \Gs2Cdk\Script\Model\Namespace_($this, "script-0001"),
new TestStateMachine()
);
}
} class TestStateMachine(gs2_cdk.state_machine.StateMachineDefinition):
def __init__(self):
task2 = self.pass_task("Task2")
error = self.error_task("Error")
task1 = self.script_task(
name="Task1",
arguments=[],
script="""
result = 'Pass'
""",
).result(
result_name="Pass",
emit_event_argument_variable_names={},
next_task_name=task2.name,
).result(
result_name="Error",
emit_event_argument_variable_names={
self.string_type("reason"): "reason",
},
next_task_name=error.name,
)
self.state_machine(
name="MainStateMachine",
variables=[
self.int_type("turn"),
],
).entry_point(
task_name=task1.name,
).task(
task1,
task2,
error,
)
class TestStateMachineStack(gs2_cdk.Stack):
def __init__(self):
super().__init__()
gs2_cdk.state_machine.Namespace(
self,
name='state-machine-0001',
).state_machine(
script_namespace=gs2_cdk.script.Namespace(
self,
name='script-0001',
),
definition=TestStateMachine(),
) class TestStateMachine extends StateMachineDefinition {
constructor() {
super();
let error = this.errorTask("Error");
let task2 = this.passTask("Task2");
let task1 = this.scriptTask(
"Task1",
[],
`
result = 'Pass'
`
)
.result("Pass", new Map(), task2.getName())
.result("Error", new Map([[new StringType("reason"), "reason"]]), error.getName());
this.stateMachine(
"MainStateMachine",
[new IntType("turn")]
)
.entryPoint(task1.getName())
.task(task1, task2, error);
}
}
class TestStateMachineStack extends Stack {
constructor() {
super();
new StateMachineNamespace(
this,
"state-machine-0001"
).stateMachine(
new ScriptNamespace(
this,
"script-0001"
),
new TestStateMachine()
);
}
} public class TestStateMachine : StateMachineDefinition
{
public TestStateMachine()
{
var error = ErrorTask("Error");
var task2 = PassTask("Task2");
Task task1 = ScriptTask(
"Task1",
new IVariable[0],
@"
result = 'Pass'
"
)
.Result("Pass", new Dictionary<IVariable, string>(), task2.Name)
.Result("Error", new Dictionary<IVariable, string> { { new StringType("reason"), "reason" } }, error.Name);
StateMachine(
"MainStateMachine",
new IVariable[] { IntType("turn") }
)
.EntryPoint(task1.Name)
.Task(task1, task2, error);
}
}
public class TestStateMachineStack : Stack
{
public TestStateMachineStack()
{
new Gs2Cdk.Gs2StateMachine.Model.Namespace(
this,
"state-machine-0001"
)
.StateMachine(
new Gs2Cdk.Gs2Script.Model.Namespace(
this,
"script-0001"
),
new TestStateMachine()
);
}
}