FlexSimでロジックを記述する

ヘルプの入手先

使用するコマンドとその使用方法に関するヘルプが必要な場合は、FlexSimの[ヘルプ]メニューからアクセス可能な「コマンドドキュメント」を参照できます。FlexScriptクラスの詳細については、「FlexScriptクラスリファレンス」を参照してください。

FlexScriptとC ++の一般的な規則

独自のロジックを作成する場合に知っておく必要のある一般的な規則を次にいくつか示します。

  • 言語では大文字と小文字が区別されます(「A」と「a」は同じではありません)。
  • 特別なフォーマットは必要ありません(スペース、タブ、改行を使用することをお勧めします)。
  • テキスト文字列は通常、引用符で囲んで入力します(例:"mytext")。
  • 関数呼び出しの後には括弧が続き、関数の引数はカンマで区切られます(例:moveobject(object1,object2))。
  • 行または関数呼び出しの最後は常にセミコロンで終わります。
  • 括弧は、演算および論理ステートメントでの関連付けにも自由に使用できます。
  • ステートメントのブロックを定義するにはカーリーブレースを使用します。
  • 行の残りをコメントアウトするには「//」を使用します。
  • テキストのブロックをコメントアウトするには「/*テキスト*/」を使用します。
  • 名前定義にスペースや特殊文字を使用しないでください(「_」は使用できます)。
  • 式を記述する際には、名前付き変数と明示的な値を区別せずに使用できます。

変数のタイプ

FlexSimでは、さまざまな変数タイプが使用されます。一般的な変数タイプを次にいくつか示します。FlexScriptクラスの一覧については、「FlexScriptクラスリファレンス」を参照してください。

クラス

タイプ 説明
int 整数タイプ
double 倍精度浮動小数点数タイプ
string テキスト文字列
treenode FlexSimノードへの参照
バリアント 数値、文字列、ツリーノード、または配列
Array Variantのコレクション
Object オブジェクトデータを含むツリーノード
Color 色のRGBA成分
Vec3 ベクトルのxyz成分
テーブル 要素のテーブル
List タスクとロジックの同期に使用されるものの動的リスト
var 型推論変数

treenode(またはFlexSimノード)タイプの仕組みの詳細については、「FlexSimツリー構造」を参照してください。

変数の宣言と設定

変数を宣言して設定する方法の例を次にいくつか示します。


		int index = 1;
		double weight = 175.8;
		string category = "groceries";
		treenode nextObj = Model.find("Processor1");
		Variant cellValue = table[2][3];
		var value = 3;
		

クラスオブジェクトの作成

コンストラクターの使用方法の例を次に示します。


		Color myColor = Color(1, 0, 0);   // Makes a red color
		object.location = Vec3(0, 0, 0);  // Sets the object's location to the origin
		

数学演算子

次のリストは、値に対して実行できるさまざまな数学演算を示しています。

演算子 浮動小数点の例(=解) 整数の例(=解)
+ 1.6+4.2(=5.8) 2+3(=5)
- 5.8-4.2(=1.6) 5-2(=3)
* 1.2 * 2.4(=2.88) 3*4(=12)
/ 6.0 / 4.0(= 1.5) 20/7(=2)
%(整数の余り) 34%7(=6)
Math.sqrt() Math.sqrt(5.3)(=2.3)
Math.pow() Math.pow(3.0,2.2)(=11.2) Math.pow(3,2)(=9)
Math.round() Math.round(5.6)(=6)
Math.frac() Math.frac(5.236)(=0.236)
Math.fabs() Math.fabs(-2.3)(=2.3)
Math.fmod()(浮動小数点の余り) Math.fmod(5.3,2)(=1.3)

変数の比較

次の表は、2つの値または変数を比較するさまざまな演算子を示しています。

演算子 例(解)
>(より大きい) 1.7 > 1.7(false)
<(より小さい) -1.7 <1.5(true)
>=(以上) 45 >= 45(true)
<=(以下) 45 <= 32(false)
==(等しい) 45 == 45(true)
!=(等しくない) 45 != 35(true)
文字列の比較 current.name == "Processor5"
ポインターの比較(treenodes、Objects) current == model().find("Processor5")

変数の関連付け

次の表は、いくつかの比較を関連付けるためのさまざまな演算を示しています。

演算子
&&(論理AND) x>5 && y<10
||(論理OR) x==32 || y>45
! (論理NOT) !(x==32 || y>45)
Math.min() Math.min(x, y)
Math.max() Math.max(x, y)

変数の設定と変更

変数を設定および変更する方法を次の表に示します。

演算子
= x = x + 2;
+= x += 2;(x = x + 2と同じ)
-= x -= 2;(x = x - 2と同じ)
*= x *= 2;(x = x * 2と同じ)
/= x /= 2;(x = x / 2と同じ)
++ x ++;(x = x + 1と同じ)
-- x --;(x = x - 1と同じ)

コマンドの実行

FlexSimでのコマンドの実行は次の部分で構成されます。最初にコマンドの名前を入力し、その後に開き括弧を入力します。次にコマンドの各パラメータを入力し、パラメータが複数ある場合はカンマで区切ります。各パラメータには、変数、変数の式、またはコマンド自体を指定できます。最後に閉じ括弧とセミコロンを入力します。コマンドとその機能およびパラメータリストの詳細については、FlexSimの[ヘルプ]メニューにある「コマンド」ドキュメントを参照してください。

構文

commandname(parameter1,parameter2,parameter3...);

getstat(current, "Content", STAT_CURRENT);

ドット構文

treenode、Object、Variant(いくつか例を挙げると)などのクラスでは、ドット構文を使ってメソッドを呼び出したり、プロパティ、変数、属性、ラベル(該当する場合)にアクセスしたりできます。

構文

object.method(parameter1,parameter2,parameter3...);


		current.setLocation(1, 1, 1);
		treenode lastItem = current.last;
		treenode item3 = current.subnodes[3];
		int quantity = current.quantity; //Accesses label named 'quantity'
		

制御フロー

FlexScriptには、いくつかの制御フロー構造が含まれています。これらはコード内に配置できるステートメントであり、複数の可能なパスのうち、コードの実行でどのパスを使用するかを制御するために使用します。制御フローステートメントでは、コード実行の分岐、ルーピング、一時停止、再開が可能です。

ifステートメント

ifステートメントを使用すると、式がtrueであるかfalseであるかに応じて異なるコードを実行できます。この構造体のelse部分は任意です。

次の構造体を使用します。


		if (test expression)
		{
			code block
		}
		else
		{
			code block
		}
		

例:


		if (item.subnodes.length == 2)
		{
			item.color = Color.red;
		}
		else
		{
			item.color = Color.black;
		}
		

whileループ

whileループは、評価式がfalseになるまでコードブロックをループし続けます。

次の構造体を使用します。


		while (test expression)
		{
			code block
		}
		

例:


		while (current.subnodes.length > 2)
		{
			current.last.destroy();
		}
		

forループ

forループはwhileループに似ていますが、通常、コードブロックを何回ループするかが正確にわかっている場合に使用されます。開始式はループを初期化するために1回のみ実行されます。評価式は各ループの最初に実行され、whileループと同様に、この式がfalseになるとすぐにループが停止します。計数式は各ループの最後に実行され、通常は何らかの変数を増加させて1つのループの終了を示します。

次の構造体を使用します。


		for(start expression; test expression; increment expression)
		{
			code block
		}
		

例:


		for (int index = 1; index <= current.subnodes.length; index++)
		{
			current.subnodes[index].as(Object).color = Color.blue;
		}
		

switchステートメント

switchステートメントを使用すると、スイッチをオンにする変数に応じて、実行する可能性があるいくつかのコードの中から1つを選択して実行できます。スイッチ変数は整数型である必要があります。次の例では、タイプ1のアイテムの色を黄色に、タイプ5を赤色に、その他のすべてのタイプを緑色に設定します。

次の構造体を使用します。


		switch (switchvariable)
		{
			case casenum:
			{
				code block;
				break;
			}
			default:
			{
				code block;
				break;
			}
		}
		

例:


		switch (item.type)
		{
			case 1:
			{
				item.color = Color.yellow;
				break;
			}
			case 5:
			{
				item.color = Color.red;
				break;
			}
			default:
			{
				item.color = Color.green;
				break;
			}
		}
		

リダイレクション

前述の各フロー構造体は、実行中にcontinue、break、またはreturnのいずれかのステートメントを使用してリダイレクトできます。次に、これらの各ステートメントの動作について説明します。

構造体 例:
continue; forループとwhileループでのみ有効です。ループの現在の反復を停止し、ループ内の次の反復に進みます。forループでは、続行前にカウンターがインクリメントされます。
break; for、while、switchステートメントでのみ有効です。現在のfor、whileまたはswitchブロックから抜け出し、このブロックの直後の行に進みます。ネストされたステートメントの場合は、単に現在のステートメントから抜け出し、ネスト元のステートメントに進みます。
return 0; 現在のメソッドから完全に戻り、このメソッドを呼び出したコードの次の行に進みます。FlexScriptコマンド(ピックリストとトリガーを含む)はどれもVariant型を返すため、return文の後に値が必要です。「return;」という入力は有効ではありません。

コルーチンとawaitステートメント

FlexScriptは、awaitキーワードを使用するコルーチンもサポートします。コルーチンは、メソッドまたは関数がシミュレーション時間をスパニングできる仕組みです。コルーチンの最も基本的な例は、単純な遅延時間の待機です。

print("time before delay: ", time());
await Delay.seconds(5);
print("time after delay: ", time());

上のコードは、現在時刻を出力コンソールに出力した後、5秒待ち(コルーチンは5シミュレーション秒間一時停止する)、その後再び現在時刻を出力します。時刻は5シミュレーション秒増えます。コルーチンが一時停止している間、ローカル変数はすべて保持されます。

キーワードawaitを含み、次の構文を持つFlexScript関数はコルーチンになります。

await someexpression;
//or...
typename result = await someexpression;
//or...
result = await someexpression;

例を示します。

await current.event("OnEntry"); // wait for current's OnEntry event to fired

Variant pulled = await List("List1").pull("", 1, 1, current); // pull a value from List1 and wait for the pull operation to complete

await Delay.minutes(5); // suspend the coroutine for 5 simulated minutes
		

awaitステートメントの述語(awaitキーワードの後の式)は待機可能(awaitable)であることが必要です。つまり、述語のタイプは、ユーザーがそのタイプのインスタンスを待機できるように特別に設定されている必要があります。待機可能なタイプは、具体的には次のようにわずかです。

コルーチンを使用すると、処理全体を単一のコードブロックとしてモデリングできます。処理の実行の開始、一時停止、再開をいくつもの方法で行うことができます。一定の遅延時間の間、実行を一時停止することもできれば、特定の要件を満たすまで一時停止することもできます。たとえば、リストから値をプルするまで待つ、あるいはオブジェクト上でイベントが起動されるまで待つ、といった処理が可能です。これらのさまざまな機能を組み合わせることによって、処理の定義が驚くほど柔軟になります。

オプションのチェーン処理

FlexScriptでは、?.の構文を使用して、オプションのチェーン処理と呼ばれるコンセプトがサポートされています。これが必要になるのは、コードの評価でnull値が発生する可能性があるときです。指定した式の結果がnull値で、ドット構文を使用して式のクラスメンバーにアクセスすると、デフォルトでFlexSimにより例外がスローされます。


	treenode nullNode = 0;
	return nullNode.last; // exception
	

この例外を回避するには、コードで多数のifステートメントの使用が必要になることがあります。その代わりに、オプションのチェーン処理を使用してクラスメンバーにアクセスできます。


	treenode nullNode = 0;
	return nullNode?.last; // returns null (no exception)
	

所有するオブジェクトがnullのとき、?.lastアクセサーは例外をスローせず、単にnullを返します。これにより、複数のアクセサーをごく簡単に、ifステートメントでガードする必要なしにチェーンできるため、この方法をオプションのチェーン処理と呼びます。コードはnullポインターを見つけたとき、単にベイルアウトを行い、nullを返します。


	treenode nullNode = 0;
	return nullNode?.first?.first?.first; // returns null (no exception)