1. Qiita
  2. 投稿
  3. Bluemix

目からウロコ!Node-REDのデザインパターン10選

  • 308
    いいね
  • 0
    コメント

私がNode-REDを使い始めて4カ月が経ちました。開発をしていると、Node-REDには単にノードを横に繋いでゆくだけではなく、ノードの接続関係を活用したデザインパターンが沢山あることに気が付きました。

本記事では、Node-REDを今まで以上に活用できるデザインパターン10個を、ご紹介します。最後のソースコードは、Bluemix上のNode-REDはもちろん、ローカルPCにインストールしたNode-REDでも動作しますので、貼り付けて遊んでみてください。

Node-REDとは

Node-REDは、機能毎に用意されたノードをマウスで繋ぐ操作で、簡単にアプリケーションを作成できる開発環境です。当初はIoT向けに開発されましたが、ウェブアプリケーション開発等、幅広い用途で利用できます。

デザインパターンとは

一般的にデザインパターンとは、Java等のオブジェクト指向言語を使いこなしてゆくと辿り着く、開発や変更の効率が良い設計パターンを指します。学生の時、興味深いパターンが何個か学び、特にMediatorやSingletonパターンは目から鱗でした。

Node-REDにおけるデザインパターン

Node-REDは、複雑な処理をカプセル化したノードが沢山用意されているため、ノードを繫ぐだけで簡単に一連の処理を実現できます。しかし、ノードを一方向に繋ぐのみでは、Node-REDの利点を活用しきれていないと考えます。
「処理のロジックを、ノードの接続関係で記述する」と視点を変えると、様々なデザインパターンのアイデアが沸いてきました。デザインパターンを用いると、一連の処理を理解しやすくなり、リリース後の修正も効率的に行えるようになります。

1. Store & Searchパターン

データの格納と検索を行うパターンです。

store_search_pattern.png

Node-REDは、IoT端末から受け取ったデータの処理向けに開発されたため、Store & Searchパターンは一番メジャーなパターンであると思います。
Storeパターンは、IoT端末等から取得したデータをデータベースに格納します。この時、JavaScriptを記述するノードを介して、格納するデータを選択したり、データを格納する列名を指定したりできます。
Searchパターンは、Storeパターンを用いて格納したデータを検索するパターンです。

2. UI & APIパターン

ブラウザ上でAPI問合せに用いる入力値を受け付け、APIを問合せた結果を表示するパターンです。

ui_api_pattern.png

UIパターンは、入力フォーム表示用処理、API問合せ結果表示用処理の2つの処理で構成されています。入力フォームのHTMLは、ブラウザ上でユーザから受け取った値をGETのパラメータとして、API問合せ結果表示用処理に引き継ぎます。API問合せ結果表示用処理は、パラメータの値を用いてウェブAPIを問合せ、その結果を表示用HTMLに組み込んで出力します。UIパターンは、ウェブAPIを問合せるUIを作成したい時に覚えておくと便利です。
APIパターンは、Node-RED上で扱うデータを、ウェブAPIとして問合せできるようにするためのパターンです。処理をウェブAPIとして作成しておくと、UIパターンからの問合せはもちろん、他の開発言語で開発したウェブアプリケーションからNode-RED上の処理を呼び出すことが容易となります。例えば、JavaのUI開発フレームワークVaadinでUIを開発し、内部ロジックはNode-REDでウェブAPIとして開発するという手法は、とても開発効率が良くオススメです。

3. Timeoutパターン

ノードの処理に時間がかかった場合、タイムアウトさせるパターンです。

timeout_pattern.png

Node-REDでDBやウェブAPIに問合せた際、応答が返って来ず、処理が進まないことがあります。この現象は、ウェブアプリケーションの際に致命的です。もし処理が終端のHTTP応答ノードまで到達しなかった場合、ユーザのブラウザはローディング状態になってしまい、ユーザは長時間待たされてしまいます。その時は、Timeoutパターンを用いて、指定秒数でタイムアウトし、「タイムアウトしました」というエラーを返す方が、ユーザに親切です。

4. whileパターン

ノードの接続のみで、while文を実現するパターンです。

while_pattern.png

Java等でwhile文を用いる場合は、変数i=0で初期化、条件文でループ回数指定、i++でインクリメントという3つの手順を行います。Node-REDにおけるwhileパターンは、同様の手順を行う初期化ノード、条件文ノード、インクリメントノードの3ノードから構成されます。whileパターンを用いると、ループ構造の把握が容易となり、リリース後にループ回数を変更する修正も迅速に行えます。ちなみにNode-REDにて、ループ処理を行う場合は、大抵8の字型の接続となりますので、すぐにループ処理を見つけることができます。

5. Sequenceパターン

複数のノードから得た処理結果を、集計するパターンです。

sequence_pattern.png

処理ノードはmsg.payloadを介して1つの値を出力すると、設計がシンプルとなります。しかし、複数のノードから取得した値を集計したい場合、単純にノードを横に繫いでしまうととmsg.payloadの値は上書きされてしまいます。Sequenceパターンでは、ノードからmsg.payloadを介して受け取った値を一旦、msg.tmp等の別変数に退避しておき、後続のノードがmsg.payloadに値を格納できるようにします。ノードから値を受け取る処理が全て終了した後、別変数に退避しておいた値を呼び出すことで、集計処理を実現します。

6. Aggregatorパターン

Sequenceパターンと同じく、複数のノードから得た処理結果を、集計するパターンです。

aggregator_pattern.png

Sequenceパターンは、ノードを横に繋いでいくのみであるため、処理ノードか、値を別変数に退避するノードかをノードの接続を見ただけでは、すぐ識別できません。Aggregatorパターンでは、集計ノードへ2つのノードが直接値を渡しているため、ノードの接続を見るだけで直観的に処理を把握できます。また、別の利点として、複数のウェブAPIに問合せた結果を集計するようなケースにて、並列してウェブAPIへリクエストできるため、処理時間を短縮できる特徴もあります。

7. Separatorパターン

1つのノードから2つの異なる値を出力するパターンです。

separator_pattern.png

Aggregatorパターンは「2入力」を実現するパターンであるのに対し、Separatorパターンは「2出力」を実現するパターンです。JavaScriptを記述するノードにて、サイズ2の配列をreturnし、出力数を指定するのみで実現できます。

8. MapReduceパターン

SeparatorパターンとAggregatorパターンを組み合わせて、MapReduceの処理を実現するパターンです。

mapreduce_pattern.png

Map処理は、Separatorパターンを用いて記述します。Map処理を行うノードは、入力値に対してWordCount等の処理を行い、Keyを基にKey-Valueペアの出力先を決定します。一方、Reduce処理は、Aggregatorパターンを用いて記述します。Reduce処理を行うノードは、事前に指定したMap数分の入力が来た後、同じKeyを持つValueのデータに対して集計等の処理を行います。Java等でMapReduce処理を記述すると、多重ループ等が原因で複雑になりがちですが、Node-REDではMapReduceの処理フローをノードの接続としてグラフィカルに記述できるため、簡単に作成でき、理解も容易です。

9. Matcherパターン

ノードのネットワーク構造を探索して、条件に一致するか判定するパターンです。

matcher_pattern.png

JavaScriptを記述するノードは、値をreturnしないと後続ノードの処理を実行しないという動きをします。Matcherパターンの条件ノードは、この特徴を生かし、入力値がノードの条件を満たす場合のみ、次のノードに処理を引き継ぎます。Matcherパターンでは、処理全体として満たしたい条件を、条件ノードのネットワーク構造として作成しておきます。判定したいデータを入力すると、そのネットワーク構造を探索し、ネットワーク構造から値が出てきた場合、条件に一致していることが分かります。
図の例では、Matcherパターンを用いて、入力した英文の文型を判定しています。内部では、品詞を判定する条件ノードから成るネットワーク構造を通過させることで、SV、SVC、SVO、SVOO、SVOCのどの文型に該当するかを判定しています。この処理は一度、品詞を判定するノードを作成しておけば、リリース後に品詞の並びを変える必要があっても、ノード接続を変える操作だけで修正が完結します。Node-REDは、iPadやAndroidタブレットでノードの接続を変更できるため、例えば通勤電車の中等、どこでも修正作業が行えます。

10. Stateパターン

状態遷移を扱うパターンです。

state_pattern.png

Stateパターンは、状態を表す状態ノードと、遷移先を表すSwitchノードから構成されます。状態ノードは、その状態に必要な処理を行い、Switchノードに判定したい値を引き継ぎます。その後、Switchノードは引き継いだ値の内容に従い判定し、次の状態ノードへ処理を移します。Java等で状態遷移を記述する場合は、状態遷移表を活用する等の方法を用いますが、コードから遷移の全体像を理解するは困難です。Node-REDを用いることで、状態の遷移が一目瞭然となります。

最後に

本記事を通して、新たな発見が得られれば幸いです。面白い他のデザインパターンや、もっと良いコードに気づいた方は、ご連絡ください。皆で議論し、新たなデザインパターンを見つけてゆけたら、良いなと考えています。

※本デザインパターンの内容は、RedConnectの技術サイトでも紹介されました。

ソースコード

Node-REDは、開発環境の右上メニュー->Import->Clipboardからソースコードを貼り付けることができます。

Store & Searchパターン

[{"id":"58f0c78.fa70f38","type":"comment","z":"d4f1d484.2b0e28","name":"Store pattern","info":"","x":139.67855072021484,"y":136.9643678665161,"wires":[]},{"id":"ac5df1bd.53a21","type":"function","z":"d4f1d484.2b0e28","name":"格納するデータを選択","func":"msg.payload = {DATA: new Date(msg.payload).toString()};\nreturn msg;","outputs":1,"noerr":0,"x":327.42858505249023,"y":182.9643850326538,"wires":[["bc71d473.438e28"]]},{"id":"bc71d473.438e28","type":"dashDB out","z":"d4f1d484.2b0e28","service":"dashDB-qu","table":"TMP","name":"DBへ格納","x":505.4285888671875,"y":182.96438694000244,"wires":[]},{"id":"4ad682a0.b5297c","type":"inject","z":"d4f1d484.2b0e28","name":"検索要求","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":152.1785888671875,"y":325.2143850326538,"wires":[["663e23c1.99c1dc"]]},{"id":"afccc742.503338","type":"inject","z":"d4f1d484.2b0e28","name":"入力データ","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":154.42858505249023,"y":182.9643850326538,"wires":[["ac5df1bd.53a21"]]},{"id":"663e23c1.99c1dc","type":"dashDB in","z":"d4f1d484.2b0e28","service":"dashDB-qu","query":"SELECT * FROM TMP;","params":"","name":"DBを検索","x":295.1785888671875,"y":325.2143850326538,"wires":[["1301aa90.ecfe55"]]},{"id":"1301aa90.ecfe55","type":"debug","z":"d4f1d484.2b0e28","name":"検索結果を出力","active":true,"console":"false","complete":"payload","x":462.17859649658203,"y":325.2143850326538,"wires":[]},{"id":"3b24f16a.c4db0e","type":"comment","z":"d4f1d484.2b0e28","name":"Search pattern","info":"","x":144.67858123779297,"y":276.96437549591064,"wires":[]},{"id":"9efbd918.610428","type":"comment","z":"d4f1d484.2b0e28","name":"↑格納したデータを検索","info":"","x":369.67859649658203,"y":366.5477056503296,"wires":[]},{"id":"42d56d7b.bd2a94","type":"comment","z":"d4f1d484.2b0e28","name":"↑IoT端末等からデータを取得","info":"","x":237.4285430908203,"y":225.46437644958496,"wires":[]},{"id":"d987c196.26784","type":"inject","z":"d4f1d484.2b0e28","name":"表削除","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":146.2499885559082,"y":89.39282989501953,"wires":[["7ab2ca59.854d34"]]},{"id":"7ab2ca59.854d34","type":"dashDB in","z":"d4f1d484.2b0e28","service":"dashDB-qu","query":"DROP TABLE TMP;","params":"","name":"DROP TABLE","x":294.2499885559082,"y":89.39282989501953,"wires":[["a0547bb4.5fab88"]]},{"id":"a0547bb4.5fab88","type":"debug","z":"d4f1d484.2b0e28","name":"[]が出力されれば成功","active":true,"console":"false","complete":"payload","x":500.2499885559082,"y":89.39282989501953,"wires":[]},{"id":"8bead6df.741528","type":"inject","z":"d4f1d484.2b0e28","name":"表作成","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":145,"y":42.14285659790039,"wires":[["3449d1ee.cbb62e"]]},{"id":"3449d1ee.cbb62e","type":"dashDB in","z":"d4f1d484.2b0e28","service":"dashDB-qu","query":"CREATE TABLE TMP (DATA VARCHAR(255));","params":"","name":"CREATE TABLE","x":300,"y":42.14285659790039,"wires":[["93dc73d3.6c239"]]},{"id":"93dc73d3.6c239","type":"debug","z":"d4f1d484.2b0e28","name":"[]が出力されれば成功","active":true,"console":"false","complete":"payload","x":499,"y":42.14285659790039,"wires":[]}]

UI & APIパターン

[{"id":"3675bb25.c98a44","type":"comment","z":"d4f1d484.2b0e28","name":"UI pattern","info":"","x":129.4008445739746,"y":410.96428298950195,"wires":[]},{"id":"9f7d159f.6082e8","type":"http in","z":"d4f1d484.2b0e28","name":"","url":"/output","method":"get","swaggerDoc":"","x":135.67858123779297,"y":539.1587057113647,"wires":[["15ee7da3.ea1182"]]},{"id":"15ee7da3.ea1182","type":"function","z":"d4f1d484.2b0e28","name":"API問合せ用URL作成","func":"msg.url = msg.req.host + \"/api?q=\" + encodeURI(msg.payload.q);\nreturn msg;","outputs":1,"noerr":0,"x":313.24999237060547,"y":539.2538747787476,"wires":[["b6619f87.499e6"]]},{"id":"b6619f87.499e6","type":"http request","z":"d4f1d484.2b0e28","name":"API問合せ","method":"GET","ret":"obj","url":"","x":488.53580474853516,"y":538.5872087478638,"wires":[["c58cb91a.3a7348"]]},{"id":"6260006b.9da","type":"http response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":590.7738914489746,"y":636.6824054718018,"wires":[]},{"id":"c58cb91a.3a7348","type":"change","z":"d4f1d484.2b0e28","name":"headers削除","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":299.96350479125977,"y":636.7300310134888,"wires":[["1e70abb0.e18f54"]]},{"id":"1e70abb0.e18f54","type":"template","z":"d4f1d484.2b0e28","name":"出力HTML","field":"payload","format":"html","template":"<HTML><BODY>\nテーブルの行数は{{payload.1}}です。\n</BODY></HTML>","x":448.6785888671875,"y":636.8253183364868,"wires":[["6260006b.9da"]]},{"id":"fbe35ede.041ca","type":"http response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":485.9169235229492,"y":456.96418952941895,"wires":[]},{"id":"f2694ba7.0d96b8","type":"http in","z":"d4f1d484.2b0e28","name":"","url":"/input","method":"get","swaggerDoc":"","x":132.58342742919922,"y":456.964204788208,"wires":[["302a43fd.cfd5bc"]]},{"id":"302a43fd.cfd5bc","type":"template","z":"d4f1d484.2b0e28","name":"入力フォームHTML","field":"payload","format":"html","template":"<HTML><BODY><FORM method='GET' action='output'>\nテーブル名:<INPUT type='text' name='q' value='TMP'>\n<INPUT type='submit'>\n</FORM></BODY></HTML>","x":308.2501106262207,"y":456.6308391094208,"wires":[["fbe35ede.041ca"]]},{"id":"fc025f83.03fda","type":"http in","z":"d4f1d484.2b0e28","name":"","url":"/api","method":"get","swaggerDoc":"","x":128.0395851135254,"y":779.4920873641968,"wires":[["c132f98c.3ecd08"]]},{"id":"e3c106e6.1c3ef8","type":"http response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":557.9286231994629,"y":779.2063293457031,"wires":[]},{"id":"43292e38.bcd6d","type":"comment","z":"d4f1d484.2b0e28","name":"API pattern","info":"","x":135.40087890625,"y":732.3809695243835,"wires":[]},{"id":"dda5c57a.225a38","type":"comment","z":"d4f1d484.2b0e28","name":"↓下のAPIに問合わせ、結果取得","info":"","x":533.6508865356445,"y":498.1310005187988,"wires":[]},{"id":"2ed4fa3d.d12b06","type":"comment","z":"d4f1d484.2b0e28","name":"API問合せでヘッダが書換わるため削除↑","info":"","x":221.1508331298828,"y":679.3809394836426,"wires":[]},{"id":"268a49c.fd975b6","type":"comment","z":"d4f1d484.2b0e28","name":"↓ブラウザ上で値(検索ワード等)を受付け、下のGET実行","info":"","x":462.40087890625,"y":414.7976396083832,"wires":[]},{"id":"8b1381be.74ec8","type":"comment","z":"d4f1d484.2b0e28","name":"↑API取得結果をブラウザ上に表示","info":"","x":526.4842071533203,"y":678.880937576294,"wires":[]},{"id":"b8e79c46.47186","type":"comment","z":"d4f1d484.2b0e28","name":"パラメータの値からAPI問合せ用URL作成↓","info":"","x":224.65087890625,"y":498.4643135070801,"wires":[]},{"id":"e4473af4.1bb8c8","type":"comment","z":"d4f1d484.2b0e28","name":"↑ユーザが入力した値を用いて検索","info":"","x":496.87316131591797,"y":821.4841232299805,"wires":[]},{"id":"c132f98c.3ecd08","type":"template","z":"d4f1d484.2b0e28","name":"SQL文作成","field":"payload","format":"handlebars","template":"SELECT COUNT(*) FROM {{payload.q}};","x":267.71427154541016,"y":779.4285669326782,"wires":[["e8426a37.17bd98"]]},{"id":"e8426a37.17bd98","type":"dashDB in","z":"d4f1d484.2b0e28","service":"dashDB-qu","query":"","params":"","name":"DBを検索","x":414.1508026123047,"y":778.8730506896973,"wires":[["e3c106e6.1c3ef8"]]}]

Timeoutパターン

[{"id":"efd2874f.102d78","type":"comment","z":"d4f1d484.2b0e28","name":"Timeout pattern","info":"","x":121,"y":991,"wires":[]},{"id":"55fe0f56.aa01f","type":"comment","z":"d4f1d484.2b0e28","name":"5秒以内に検索が完了したら、ブラウザ上に検索結果を表示↓","info":"","x":251.50000762939453,"y":1040.999979019165,"wires":[]},{"id":"9f162cbb.60e9d","type":"comment","z":"d4f1d484.2b0e28","name":"検索が5秒以上かかったら、ブラウザ上に「タイムアウトしました」と表示↑","info":"","x":286,"y":1269.8333740234375,"wires":[]},{"id":"1cc5725.fe33a8e","type":"http in","z":"d4f1d484.2b0e28","name":"","url":"/output","method":"get","swaggerDoc":"","x":114,"y":1088,"wires":[["ae6de02b.51922","570e59a7.a8f1a8"]]},{"id":"ae6de02b.51922","type":"function","z":"d4f1d484.2b0e28","name":"API問合せ用URL作成","func":"msg.url = msg.req.host + \"/api?q=\" + encodeURI(msg.payload.q);\nreturn msg;","outputs":1,"noerr":0,"x":291.5714111328125,"y":1088.0951690673828,"wires":[["c15452cb.3eabb"]]},{"id":"c15452cb.3eabb","type":"http request","z":"d4f1d484.2b0e28","name":"API問合せ","method":"GET","ret":"obj","url":"","x":466.8572235107422,"y":1087.428503036499,"wires":[["a1c844c3.5e37b8"]]},{"id":"3a14a3b7.c5eb5c","type":"http response","z":"d4f1d484.2b0e28","name":"HTTP応答","x":603.0953102111816,"y":1185.523699760437,"wires":[]},{"id":"a1c844c3.5e37b8","type":"change","z":"d4f1d484.2b0e28","name":"headers削除","rules":[{"t":"delete","p":"headers"}],"action":"","property":"","from":"","to":"","reg":false,"x":312.2849235534668,"y":1185.571325302124,"wires":[["43ea4055.bc15c"]]},{"id":"43ea4055.bc15c","type":"template","z":"d4f1d484.2b0e28","name":"出力HTML","field":"payload","format":"html","template":"<HTML><BODY>\nテーブルの行数は{{payload.1}}です。\n</BODY></HTML>","x":461.00000762939453,"y":1185.666612625122,"wires":[["3a14a3b7.c5eb5c"]]},{"id":"570e59a7.a8f1a8","type":"delay","z":"d4f1d484.2b0e28","name":"5秒間待機","pauseType":"delay","timeout":"5","timeoutUnits":"seconds","rate":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":248.32141876220703,"y":1228.8412942886353,"wires":[["4eb3d9c9.b14c28"]]},{"id":"4eb3d9c9.b14c28","type":"template","z":"d4f1d484.2b0e28","name":"タイムアウト表示HTML","field":"payload","format":"html","template":"<HTML><BODY>\nタイムアウトしました。\n</BODY></HTML>","x":428.32141876220703,"y":1228.8412942886353,"wires":[["3a14a3b7.c5eb5c"]]}]

whileパターン

[{"id":"7a1c913a.85e37","type":"template","z":"bb0998cf.44f668","name":"i=0","field":"i","format":"handlebars","template":"0","x":320,"y":3680,"wires":[["4047b441.bfb84c"]]},{"id":"4047b441.bfb84c","type":"switch","z":"bb0998cf.44f668","name":"i<4","property":"i","rules":[{"t":"lt","v":"4"},{"t":"else"}],"checkall":"true","outputs":2,"x":458,"y":3680,"wires":[["43f621ff.bc09e"],["dcb4322f.234bd"]]},{"id":"2a1ad095.d5e53","type":"function","z":"bb0998cf.44f668","name":"i++","func":"msg.i++;\n\nreturn msg;","outputs":1,"noerr":0,"x":564,"y":3585,"wires":[["4047b441.bfb84c"]]},{"id":"44dbc2cb.bb243c","type":"debug","z":"bb0998cf.44f668","name":"終了","active":true,"console":"false","complete":"payload","x":805,"y":3731,"wires":[]},{"id":"83af8aec.7c5078","type":"debug","z":"bb0998cf.44f668","name":"\"i回目\"を出力","active":true,"console":"false","complete":"payload","x":821.3999633789062,"y":3681.066650390625,"wires":[]},{"id":"822328ae.7ddcd8","type":"inject","z":"bb0998cf.44f668","name":"開始","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":201.89581298828125,"y":3679.888916015625,"wires":[["7a1c913a.85e37"]]},{"id":"a144ddbc.5ebb2","type":"comment","z":"bb0998cf.44f668","name":"while pattern","info":"","x":193.16665649414062,"y":3584.5556116104126,"wires":[]},{"id":"705c90e.f8fa37","type":"comment","z":"bb0998cf.44f668","name":"↓4回出力される","info":"","x":841.9999389648438,"y":3639.166615486145,"wires":[]},{"id":"8e84d3d2.717b3","type":"comment","z":"bb0998cf.44f668","name":"whileの条件文↑","info":"","x":410.66666412353516,"y":3720.6666402816772,"wires":[]},{"id":"56a6728c.a9598c","type":"comment","z":"bb0998cf.44f668","name":"インクリメントさせる値iを初期化↓","info":"","x":248.16665649414062,"y":3637.1667013168335,"wires":[]},{"id":"c68932e9.3976d","type":"comment","z":"bb0998cf.44f668","name":"←値iをインクリメント","info":"","x":736.4999694824219,"y":3585.3333740234375,"wires":[]},{"id":"dcb4322f.234bd","type":"template","z":"bb0998cf.44f668","name":"ループ後の処理","field":"payload","format":"handlebars","template":"ループ終了","x":613.2380752563477,"y":3730.869017601013,"wires":[["44dbc2cb.bb243c"]]},{"id":"43f621ff.bc09e","type":"template","z":"bb0998cf.44f668","name":"文字列\"i回目\"を生成","field":"payload","format":"handlebars","template":"{{i}}回目","x":624.9999694824219,"y":3681,"wires":[["83af8aec.7c5078","2a1ad095.d5e53"]]}]

Sequenceパターン

[{"id":"79318ef6.86ce7","type":"comment","name":"Sequence pattern","info":"","x":157.92858123779297,"y":1925.464274406433,"z":"d4f1d484.2b0e28","wires":[]},{"id":"98e06bb0.671f98","type":"function","name":"payload=451","func":"msg.payload = 451;\n\nreturn msg;","outputs":1,"noerr":0,"x":397.5952453613281,"y":1969.7976484298706,"z":"d4f1d484.2b0e28","wires":[["a589e119.5a762"]]},{"id":"11977bd5.ee6884","type":"function","name":"tmpとpayloadの合計算出","func":"msg.payload = msg.tmp + msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":592.5952453613281,"y":2052.7976484298706,"z":"d4f1d484.2b0e28","wires":[["2e654056.d19ac"]]},{"id":"2f1d71c.fd0e28e","type":"function","name":"payload=326","func":"msg.payload = 326;\n\nreturn msg;","outputs":1,"noerr":0,"x":397.5952453613281,"y":2052.7976484298706,"z":"d4f1d484.2b0e28","wires":[["11977bd5.ee6884"]]},{"id":"2e654056.d19ac","type":"debug","name":"777を出力","active":true,"console":"false","complete":"payload","x":777.5952453613281,"y":2052.7976484298706,"z":"d4f1d484.2b0e28","wires":[]},{"id":"8e353c9e.71cac","type":"inject","name":"2値の和を求める計算実行","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":205.59524536132812,"y":1969.7976484298706,"z":"d4f1d484.2b0e28","wires":[["98e06bb0.671f98"]]},{"id":"a589e119.5a762","type":"function","name":"tmp=payload","func":"msg.tmp = msg.payload;\n\nreturn msg;","outputs":1,"noerr":0,"x":556.5952453613281,"y":1969.7976484298706,"z":"d4f1d484.2b0e28","wires":[["2f1d71c.fd0e28e"]]},{"id":"bdfd8572.420278","type":"comment","name":"↓値を別の変数tmpへ退避","info":"","x":622.0951766967773,"y":1925.297646522522,"z":"d4f1d484.2b0e28","wires":[]},{"id":"f3c44263.0c3bc","type":"comment","name":"↓1つ目の値","info":"","x":394.09525299072266,"y":1926.1309614181519,"z":"d4f1d484.2b0e28","wires":[]},{"id":"9c2a1dca.63d5e","type":"comment","name":"↑2つ目の値","info":"","x":396.59523010253906,"y":2096.4642181396484,"z":"d4f1d484.2b0e28","wires":[]},{"id":"1cfe4562.e301bb","type":"comment","name":"↑退避した値tmpとpayloadの和を計算","info":"","x":692.0952377319336,"y":2096.464339733124,"z":"d4f1d484.2b0e28","wires":[]}]

Aggregatorパターン

[{"id":"fe9c117e.0163f","type":"comment","name":"Aggregator pattern","info":"","x":161.42858123779297,"y":2204.630959510803,"z":"d4f1d484.2b0e28","wires":[]},{"id":"9e0268f7.61fd98","type":"function","name":"payload=451","func":"msg.payload = 451;\n\nreturn msg;","outputs":1,"noerr":0,"x":432.26187896728516,"y":2288.131070137024,"z":"d4f1d484.2b0e28","wires":[["af493597.50b6c8"]]},{"id":"af493597.50b6c8","type":"function","name":"2つのpayloadの合計算出","func":"// 入力数を減らす\ncontext.global.n--;\n\n// msg.payloadのデータを格納\ncontext.global.data[context.global.n] = msg.payload;\n\n// 定義した入力数が来たら、集計処理を行い、msg.payloadを返す\nif (context.global.n === 0)\n{   // msg.payloadの合計値を算出\n    var sum = 0;\n    for (var i = 0; i < context.global.data.length; i++)\n    {\n        sum += context.global.data[i];\n    }\n    msg.payload = sum;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":640.2619247436523,"y":2311.131094932556,"z":"d4f1d484.2b0e28","wires":[["c2d9368.f3d26c8"]]},{"id":"72d62625.8d29d8","type":"function","name":"payload=326","func":"msg.payload = 326;\n\nreturn msg;","outputs":1,"noerr":0,"x":431.26190185546875,"y":2336.13108253479,"z":"d4f1d484.2b0e28","wires":[["af493597.50b6c8"]]},{"id":"c2d9368.f3d26c8","type":"debug","name":"777を出力","active":true,"console":"false","complete":"payload","x":822.2619018554688,"y":2312.13108253479,"z":"d4f1d484.2b0e28","wires":[]},{"id":"a8ee0b2c.5711f8","type":"function","name":"並列数=2","func":"context.global.n = 2;\ncontext.global.data = new Array(2);\n\nreturn msg;","outputs":1,"noerr":0,"x":271.26190185546875,"y":2313.13108253479,"z":"d4f1d484.2b0e28","wires":[["9e0268f7.61fd98","72d62625.8d29d8"]]},{"id":"39431b6c.c6bce4","type":"comment","name":"↓1つ目の値","info":"","x":431.0083923339844,"y":2249.7051458358765,"z":"d4f1d484.2b0e28","wires":[]},{"id":"1f653d.ffe09ac3","type":"inject","name":"2値の和を求める計算実行","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":205.31793975830078,"y":2249.8241748809814,"z":"d4f1d484.2b0e28","wires":[["a8ee0b2c.5711f8"]]},{"id":"1c32a960.e3cd57","type":"comment","name":"↑2つ目の値","info":"","x":429.8417434692383,"y":2376.7050580978394,"z":"d4f1d484.2b0e28","wires":[]},{"id":"f30cf9d4.0cf308","type":"comment","name":"グローバル変数に並列数を定義↑","info":"","x":201.7702865600586,"y":2356.2525358200073,"z":"d4f1d484.2b0e28","wires":[]},{"id":"bee9177f.4116e8","type":"comment","name":"↑並列数分の入力が来た後、和を計算","info":"","x":743.3417587280273,"y":2353.5384435653687,"z":"d4f1d484.2b0e28","wires":[]}]

Separatorパターン

[{"id":"1419e877.ebe618","type":"inject","name":"実行","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":155.0952377319336,"y":2485.79771900177,"z":"d4f1d484.2b0e28","wires":[["8f4d7d43.70b28"]]},{"id":"8f4d7d43.70b28","type":"function","name":"1つ目に451、2つ目に326を出力","func":"msg.payload = 451;\nvar msg2 = {};\nmsg2.payload = 326;\n\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":349.0952377319336,"y":2485.79771900177,"z":"d4f1d484.2b0e28","wires":[["a69d939d.59627"],["ace2220e.531de"]]},{"id":"a69d939d.59627","type":"debug","name":"451を出力","active":true,"console":"false","complete":"payload","x":562.0952377319336,"y":2458.79771900177,"z":"d4f1d484.2b0e28","wires":[]},{"id":"ace2220e.531de","type":"debug","name":"326を出力","active":true,"console":"false","complete":"payload","x":560.0952377319336,"y":2511.79771900177,"z":"d4f1d484.2b0e28","wires":[]},{"id":"b1c243df.4e3dc","type":"comment","name":"Separator pattern","info":"","x":157.42858123779297,"y":2441.2976331710815,"z":"d4f1d484.2b0e28","wires":[]},{"id":"fba005.ff045ff8","type":"comment","name":"↑1ノードから異なる2値を出力","info":"","x":349.0083770751953,"y":2530.223530769348,"z":"d4f1d484.2b0e28","wires":[]}]

MapReduceパターン

[{"id":"42f22b03.bd0dd4","type":"inject","z":"d4f1d484.2b0e28","name":"WordCount実行","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":169.98413848876953,"y":2499.5753602981567,"wires":[["b48a3afc.4b75c8"]]},{"id":"1f8c6771.e07399","type":"function","z":"d4f1d484.2b0e28","name":"Map処理","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":469.98413848876953,"y":2534.575316429138,"wires":[["9fe7f7de.601808"],["8582eef5.7a7d1"]]},{"id":"9fe7f7de.601808","type":"function","z":"d4f1d484.2b0e28","name":"Reduce処理","func":"// 入力数を減らす\ncontext.global.n1--;\n\n// msg.payloadのデータを格納\ncontext.global.data1[context.global.n1] = msg.payload;\n\n// 定義した入力数が来たら、集計処理を行い、msg.payloadを返す\nif (context.global.n1 === 0)\n{   // msg.payloadの合計値を算出\n    var tmp = [];\n    for (var i=0; i<context.global.data1.length; i++)\n    {\n        var input = context.global.data1[i];\n        for (var j=0; j<input.length; j++)\n        {\n            var key = input[j][0];\n            var value = input[j][1];\n            if (key in tmp)\n            {\n                tmp[key] += value;\n            } else {\n                tmp[key] = value;\n            }\n        }\n    }\n    \n    var output = [];\n    for (var key in tmp)\n    {\n        output.push([key, tmp[key]]);\n    }\n    msg.payload = output;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":677.9841384887695,"y":2549.575316429138,"wires":[["9c431c80.63bce"]]},{"id":"9c431c80.63bce","type":"debug","z":"d4f1d484.2b0e28","name":"結果出力","active":true,"console":"false","complete":"payload","x":817.9841384887695,"y":2549.575316429138,"wires":[]},{"id":"b48a3afc.4b75c8","type":"function","z":"d4f1d484.2b0e28","name":"Map数=3","func":"var map = 3; // Map数を定義\n\ncontext.global.n1 = map;\ncontext.global.data1 = new Array(map);\n\ncontext.global.n2 = map;\ncontext.global.data2 = new Array(map);\n\nreturn msg;","outputs":1,"noerr":0,"x":156.98413848876953,"y":2580.575316429138,"wires":[["b309b836.4cf648","3d3d88ef.c2c278","fe5a1ff0.01a5e"]]},{"id":"b309b836.4cf648","type":"template","z":"d4f1d484.2b0e28","name":"This is a pen.","field":"payload","format":"html","template":"This is a pen.","x":325.98413848876953,"y":2534.575316429138,"wires":[["1f8c6771.e07399"]]},{"id":"8582eef5.7a7d1","type":"function","z":"d4f1d484.2b0e28","name":"Reduce処理","func":"// 入力数を減らす\ncontext.global.n2--;\n\n// msg.payloadのデータを格納\ncontext.global.data2[context.global.n2] = msg.payload;\n\n// 定義した入力数が来たら、集計処理を行い、msg.payloadを返す\nif (context.global.n2 === 0)\n{   // msg.payloadの合計値を算出\n    var tmp = [];\n    for (var i=0; i<context.global.data2.length; i++)\n    {\n        var input = context.global.data2[i];\n        for (var j=0; j<input.length; j++)\n        {\n            var key = input[j][0];\n            var value = input[j][1];\n            if (key in tmp)\n            {\n                tmp[key] += value;\n            } else {\n                tmp[key] = value;\n            }\n        }\n    }\n    \n    var output = [];\n    for (var key in tmp)\n    {\n        output.push([key, tmp[key]]);\n    }\n    msg.payload = output;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":679.9841384887695,"y":2601.575316429138,"wires":[["1b1d3a66.e4e2c6"]]},{"id":"1b1d3a66.e4e2c6","type":"debug","z":"d4f1d484.2b0e28","name":"結果出力","active":true,"console":"false","complete":"payload","x":818.9841384887695,"y":2601.575316429138,"wires":[]},{"id":"b931daa2.46ce28","type":"function","z":"d4f1d484.2b0e28","name":"Map処理","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":470.98413848876953,"y":2580.575316429138,"wires":[["9fe7f7de.601808"],["8582eef5.7a7d1"]]},{"id":"83ed63.ff7c12a","type":"function","z":"d4f1d484.2b0e28","name":"Map処理","func":"var input = msg.payload.toLowerCase()\n                       .replace( /\\.$/, \"\")\n                       .split(/ |, /);\n// Map\nvar key_value = [];\nfor (var i=0; i<input.length; i++)\n{\n    var key = input[i];\n    if (key in key_value)\n    {\n        key_value[key]++;\n    } else {\n        key_value[key] = 1;\n    }\n}\n\n// Shuffle\nvar key1_value = [];\nvar key2_value = [];\nfor (var key in key_value)\n{\n    if ('a'<=key[0] && key[0]<='m')\n    {\n        key1_value.push([key, key_value[key]]);\n    } else {\n        key2_value.push([key, key_value[key]]);\n    }\n}\n\nmsg.payload = key1_value;\nvar msg2 = {};\nmsg2.payload = key2_value;\nreturn [msg, msg2];","outputs":"2","noerr":0,"x":471.98413848876953,"y":2626.575316429138,"wires":[["9fe7f7de.601808"],["8582eef5.7a7d1"]]},{"id":"3d3d88ef.c2c278","type":"template","z":"d4f1d484.2b0e28","name":"Give me a pen.","field":"payload","format":"html","template":"Give me a pen.","x":320.98413848876953,"y":2580.575316429138,"wires":[["b931daa2.46ce28"]]},{"id":"fe5a1ff0.01a5e","type":"template","z":"d4f1d484.2b0e28","name":"This pen is small.","field":"payload","format":"html","template":"This pen is small.","x":313.98413848876953,"y":2626.575316429138,"wires":[["83ed63.ff7c12a"]]},{"id":"f78466af.087b98","type":"comment","z":"d4f1d484.2b0e28","name":"MapReduce pattern","info":"","x":156.98413848876953,"y":2455.575316429138,"wires":[]},{"id":"42607f4e.bd9f8","type":"comment","z":"d4f1d484.2b0e28","name":"Map数を定義↑","info":"","x":140.89732360839844,"y":2623.001223564148,"wires":[]},{"id":"c5857142.3a7a9","type":"comment","z":"d4f1d484.2b0e28","name":"↓処理対象の入力データ","info":"","x":394.06397247314453,"y":2493.001136779785,"wires":[]},{"id":"4f68dbe2.b09724","type":"comment","z":"d4f1d484.2b0e28","name":"↑単語をkey、出現回数をvalueとし、Reduce処理に渡す","info":"","x":628.3972625732422,"y":2668.426999092102,"wires":[]},{"id":"a8da3026.5725d","type":"comment","z":"d4f1d484.2b0e28","name":"↓同じ単語の出現回数の和を求める","info":"","x":766.5639495849609,"y":2507.093747138977,"wires":[]},{"id":"9a92b61d.656d48","type":"comment","z":"d4f1d484.2b0e28","name":"Map数分の入力後、","info":"","x":722.4841384887695,"y":2475.4919862747192,"wires":[]}]

Matcherパターン

[{"id":"7687ce5.f89783","type":"comment","z":"5e4dc05d.a1b24","name":"Matcher pattern","info":"","x":242.1428680419922,"y":1595,"wires":[]},{"id":"b6a262bc.495da","type":"inject","z":"5e4dc05d.a1b24","name":"The man walked.","topic":"","payload":"The man walked.","payloadType":"string","repeat":"","crontab":"","once":false,"x":268.9120903015137,"y":1671.5384359359741,"wires":[["1924ffc2.e6db"]]},{"id":"c7a58590.385a78","type":"function","z":"5e4dc05d.a1b24","name":"名詞","func":"var words = [\"man\", \"her\", \"he\", \"him\", \"e-mail\", \"book\", \"i\", \"we\", \"she\",\"this\", \"pen\", \"chocolate\", \"me\", \"ladder\", \"wall\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":696.1428375244141,"y":1651,"wires":[["1728a714.e8d759"]]},{"id":"1924ffc2.e6db","type":"function","z":"5e4dc05d.a1b24","name":"文字列を配列化","func":"msg.payload = msg.payload.toLowerCase()\n                         .replace( /\\.$/, \"\")\n                         .split(/ |, /);\nreturn msg;","outputs":1,"noerr":0,"x":468.1428680419922,"y":1595,"wires":[["c7a58590.385a78","c192fb64.3e6d08"]]},{"id":"dc6551e9.239ab","type":"inject","z":"5e4dc05d.a1b24","name":"He looks tired.","topic":"","payload":"He looks tired.","payloadType":"string","repeat":"","crontab":"","once":false,"x":263.3736763000488,"y":1729.0768766403198,"wires":[["1924ffc2.e6db"]]},{"id":"585038d7.a7afc8","type":"inject","z":"5e4dc05d.a1b24","name":"I bought a book.","topic":"","payload":"I bought a book.","payloadType":"string","repeat":"","crontab":"","once":false,"x":270.9121513366699,"y":1789.5385160446167,"wires":[["1924ffc2.e6db"]]},{"id":"f026e64.f0fd918","type":"function","z":"5e4dc05d.a1b24","name":"冠詞","func":"var words = [\"the\", \"a\", \"an\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":636.1428604125977,"y":1785.000012397766,"wires":[["379c9674.c8636a"]]},{"id":"1728a714.e8d759","type":"function","z":"5e4dc05d.a1b24","name":"動詞","func":"var words = [\"walked\", \"believe\", \"send\", \"bought\", \"looks\", \"is\", \"give\", \"leaning\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":490.14286041259766,"y":1727.000012397766,"wires":[["e7510579.18aef8","a88b7b5f.577488","f026e64.f0fd918","2808b0e2.d7f75","379c9674.c8636a","98b13a81.674ec8"]]},{"id":"e7510579.18aef8","type":"template","z":"5e4dc05d.a1b24","name":"第1文型SV","field":"payload2","format":"handlebars","template":"第1文型SV","x":969.1428985595703,"y":1669,"wires":[["ca202d62.35dfd"]]},{"id":"912cace1.6ed35","type":"template","z":"5e4dc05d.a1b24","name":"第2文型SVC","field":"payload2","format":"handlebars","template":"第2文型SVC","x":972.1428985595703,"y":1725,"wires":[["ca202d62.35dfd"]]},{"id":"a88b7b5f.577488","type":"function","z":"5e4dc05d.a1b24","name":"形容詞","func":"var words = [\"tall\", \"innocent\", \"tired\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":824.1428604125977,"y":1725.000012397766,"wires":[["912cace1.6ed35"]]},{"id":"95aa6b7c.6a5598","type":"inject","z":"5e4dc05d.a1b24","name":"I send her an e-mail.","topic":"","payload":"I send her an e-mail.","payloadType":"string","repeat":"","crontab":"","once":false,"x":284.47625255584717,"y":1848.8462619781494,"wires":[["1924ffc2.e6db"]]},{"id":"f96a1b74.0695e8","type":"inject","z":"5e4dc05d.a1b24","name":"I believe him innocent.","topic":"","payload":"I believe him innocent.","payloadType":"string","repeat":"","crontab":"","once":false,"x":291.6814155578613,"y":1904.4615726470947,"wires":[["1924ffc2.e6db"]]},{"id":"50b8bf36.af474","type":"template","z":"5e4dc05d.a1b24","name":"第3文型SVO","field":"payload2","format":"handlebars","template":"第3文型SVO","x":971.1428985595703,"y":1786,"wires":[["ca202d62.35dfd"]]},{"id":"43aedca2.bc5124","type":"template","z":"5e4dc05d.a1b24","name":"第4文型SVOO","field":"payload2","format":"handlebars","template":"第4文型SVOO","x":975.1428604125977,"y":1845.000012397766,"wires":[["ca202d62.35dfd"]]},{"id":"bef90a4e.4106f8","type":"template","z":"5e4dc05d.a1b24","name":"第5文型SVOC","field":"payload2","format":"handlebars","template":"第5文型SVOC","x":975.1428604125977,"y":1902.000012397766,"wires":[["ca202d62.35dfd"]]},{"id":"379c9674.c8636a","type":"function","z":"5e4dc05d.a1b24","name":"名詞","func":"var words = [\"man\", \"her\", \"he\", \"him\", \"e-mail\", \"book\", \"i\", \"we\", \"she\",\"this\", \"pen\", \"chocolate\", \"me\", \"ladder\", \"wall\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":824.1428604125977,"y":1786.000012397766,"wires":[["50b8bf36.af474"]]},{"id":"c192fb64.3e6d08","type":"function","z":"5e4dc05d.a1b24","name":"冠詞","func":"var words = [\"the\", \"a\", \"an\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":490.1428680419922,"y":1651,"wires":[["c7a58590.385a78"]]},{"id":"2808b0e2.d7f75","type":"function","z":"5e4dc05d.a1b24","name":"冠詞","func":"var words = [\"the\", \"a\", \"an\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":485.1428680419922,"y":1832,"wires":[["98b13a81.674ec8"]]},{"id":"98b13a81.674ec8","type":"function","z":"5e4dc05d.a1b24","name":"名詞","func":"var words = [\"man\", \"her\", \"he\", \"him\", \"e-mail\", \"book\", \"i\", \"we\", \"she\",\"this\", \"pen\", \"chocolate\", \"me\", \"ladder\", \"wall\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":634.1428604125977,"y":1833.000012397766,"wires":[["d11f2b1.f2ee0d8","6d503b99.92afc4","dbf80aa8.2407f8"]]},{"id":"d11f2b1.f2ee0d8","type":"function","z":"5e4dc05d.a1b24","name":"冠詞","func":"var words = [\"the\", \"a\", \"an\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":486.14286041259766,"y":1916.000012397766,"wires":[["6d503b99.92afc4"]]},{"id":"6d503b99.92afc4","type":"function","z":"5e4dc05d.a1b24","name":"名詞","func":"var words = [\"man\", \"her\", \"he\", \"him\", \"e-mail\", \"book\", \"i\", \"we\", \"she\",\"this\", \"pen\", \"chocolate\", \"me\", \"ladder\", \"wall\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":632.1428604125977,"y":1916.000012397766,"wires":[["43aedca2.bc5124"]]},{"id":"dbf80aa8.2407f8","type":"function","z":"5e4dc05d.a1b24","name":"形容詞","func":"var words = [\"tall\", \"innocent\", \"tired\"];\nvar tmp = msg.payload;\n\nif (words.indexOf(tmp[0]) >= 0)\n{\n    tmp.shift(); // 配列の先頭を削除\n    msg.payload = tmp;\n\n    return msg;\n}","outputs":1,"noerr":0,"x":834.1428375244141,"y":1902,"wires":[["bef90a4e.4106f8"]]},{"id":"72a20087.8d5e","type":"debug","z":"5e4dc05d.a1b24","name":"文型を出力","active":true,"console":"false","complete":"payload2","x":1178.0387725830078,"y":1850.5556640625,"wires":[]},{"id":"ca202d62.35dfd","type":"function","z":"5e4dc05d.a1b24","name":"全て探索済?","func":"var input = msg.payload;\n\nif (input.length === 0)\n{\n    return msg;    \n}\n","outputs":1,"noerr":0,"x":1169.884864807129,"y":1667.8633785247803,"wires":[["72a20087.8d5e"]]},{"id":"b949bd7e.46b64","type":"comment","z":"5e4dc05d.a1b24","name":"全ノードを探索している場合のみ、次のノードに渡す↓","info":"","x":1008.3464660644531,"y":1626.128547668457,"wires":[]},{"id":"caf9b247.35065","type":"comment","z":"5e4dc05d.a1b24","name":"↑先頭の単語の品詞が一致した場合、単語を削除し次のノードに渡す","info":"","x":648.8148651123047,"y":1957.1712636947632,"wires":[]},{"id":"7ff77a03.800884","type":"comment","z":"5e4dc05d.a1b24","name":"↑文型を判定する文字列","info":"","x":294.47298431396484,"y":1945.8632011413574,"wires":[]},{"id":"bdf91fcc.4206e","type":"comment","z":"5e4dc05d.a1b24","name":"↑判定した文型","info":"","x":1003.1908950805664,"y":1943.487506866455,"wires":[]}]

Stateパターン

[{"id":"3318e7e6.cce718","type":"switch","z":"5e4dc05d.a1b24","name":"1文字判定","property":"c","rules":[{"t":"regex","v":"\\+|\\-"},{"t":"regex","v":"\\d"},{"t":"eq","v":"."}],"checkall":"true","outputs":3,"x":443.6581726074219,"y":1120.6715087890625,"wires":[["1ac45ea9.e53ba1"],["3fd52c9e.c02ad4"],["5a961aa8.a569e4"]]},{"id":"8ffd81f1.70028","type":"inject","z":"5e4dc05d.a1b24","name":"0101","topic":"","payload":"0101","payloadType":"string","repeat":"","crontab":"","once":false,"x":236.30752563476562,"y":1119.4175281524658,"wires":[["1ac45ea9.e53ba1"]]},{"id":"1ac45ea9.e53ba1","type":"function","z":"5e4dc05d.a1b24","name":"状態a","func":"var input = msg.payload;\nvar len = input.length;\n\nif (msg.i == null)\n{\n    msg.i = 0;\n} else {\n    msg.i++;\n}\n\nmsg.c = input.charAt(msg.i);\nmsg.state = msg.i + \"回目: 状態=a, 文字=\" + msg.c;\n\nif (msg.i < len)\n{\n    return msg;\n}","outputs":1,"noerr":0,"x":400.71014404296875,"y":996.8587646484375,"wires":[["3318e7e6.cce718","ff5f8c7.f00a07"]]},{"id":"3fd52c9e.c02ad4","type":"function","z":"5e4dc05d.a1b24","name":"状態b","func":"var input = msg.payload;\nvar len = input.length;\n\nif (msg.i == null)\n{\n    msg.i = 0;\n} else {\n    msg.i++;\n}\n\nmsg.c = input.charAt(msg.i);\nmsg.state = msg.i + \"回目: 状態=b, 文字=\" + msg.c;\n\nif (msg.i < len)\n{\n    return msg;\n}","outputs":1,"noerr":0,"x":732.2685241699219,"y":997.4957275390625,"wires":[["a9be3bfd.5641c8","87629f53.789d6"]]},{"id":"b2e36234.4d1ca","type":"function","z":"5e4dc05d.a1b24","name":"状態c","func":"var input = msg.payload;\nvar len = input.length;\n\nif (msg.i == null)\n{\n    msg.i = 0;\n} else {\n    msg.i++;\n}\n\nmsg.c = input.charAt(msg.i);\nmsg.state = msg.i + \"回目: 状態=c, 文字=\" + msg.c;\n\nif (msg.i < len)\n{\n    return msg;\n}","outputs":1,"noerr":0,"x":488.1517028808594,"y":1217.9888916015625,"wires":[["fa4d1888.05b2e8","7f91b75.f806e48"]]},{"id":"119a07f.fee65f8","type":"function","z":"5e4dc05d.a1b24","name":"状態d","func":"var input = msg.payload;\nvar len = input.length;\n\nif (msg.i == null)\n{\n    msg.i = 0;\n} else {\n    msg.i++;\n}\n\nmsg.c = input.charAt(msg.i);\nmsg.state = msg.i + \"回目: 状態=d, 文字=\" + msg.c;\n\nif (msg.i < len)\n{\n    return msg;\n}","outputs":1,"noerr":0,"x":1012.4892883300781,"y":1084.2862548828125,"wires":[["c054e9a8.3fab18","e0f463be.1f0ba"]]},{"id":"7ff57b7c.800a84","type":"inject","z":"5e4dc05d.a1b24","name":"-1","topic":"","payload":"-1","payloadType":"string","repeat":"","crontab":"","once":false,"x":238.12570190429688,"y":1176.2861804962158,"wires":[["1ac45ea9.e53ba1"]]},{"id":"f993c065.066c4","type":"inject","z":"5e4dc05d.a1b24","name":"12.2","topic":"","payload":"12.2","payloadType":"string","repeat":"","crontab":"","once":false,"x":238.1257095336914,"y":1238.1046161651611,"wires":[["1ac45ea9.e53ba1"]]},{"id":"925dff15.6da2","type":"inject","z":"5e4dc05d.a1b24","name":"4.5.1","topic":"","payload":"4.5.1","payloadType":"string","repeat":"","crontab":"","once":false,"x":237.25555419921875,"y":1296.3514070510864,"wires":[["1ac45ea9.e53ba1"]]},{"id":"969fdc24.69602","type":"debug","z":"5e4dc05d.a1b24","name":"検査結果表示","active":true,"console":"false","complete":"payload","x":1146.7226257324219,"y":1337.4444580078125,"wires":[]},{"id":"5a961aa8.a569e4","type":"template","z":"5e4dc05d.a1b24","name":"不合格の文字列","field":"payload","format":"handlebars","template":"不合格の文字列","x":1155.2939147949219,"y":1286.7789306640625,"wires":[["969fdc24.69602"]]},{"id":"a9be3bfd.5641c8","type":"debug","z":"5e4dc05d.a1b24","name":"状態表示","active":true,"console":"false","complete":"state","x":888.6581115722656,"y":997.3380298614502,"wires":[]},{"id":"ff5f8c7.f00a07","type":"debug","z":"5e4dc05d.a1b24","name":"状態表示","active":true,"console":"false","complete":"state","x":553.9915161132812,"y":997.3385009765625,"wires":[]},{"id":"7f91b75.f806e48","type":"debug","z":"5e4dc05d.a1b24","name":"状態表示","active":true,"console":"false","complete":"state","x":637.6581726074219,"y":1218.3385009765625,"wires":[]},{"id":"87629f53.789d6","type":"switch","z":"5e4dc05d.a1b24","name":"1文字判定","property":"c","rules":[{"t":"regex","v":"\\+|\\-"},{"t":"regex","v":"\\d"},{"t":"eq","v":"."}],"checkall":"true","outputs":3,"x":754.6581726074219,"y":1120.6715259552002,"wires":[["5a961aa8.a569e4"],["3fd52c9e.c02ad4"],["b2e36234.4d1ca"]]},{"id":"fa4d1888.05b2e8","type":"switch","z":"5e4dc05d.a1b24","name":"1文字判定","property":"c","rules":[{"t":"regex","v":"\\+|\\-"},{"t":"regex","v":"\\d"},{"t":"eq","v":"."}],"checkall":"true","outputs":3,"x":533.6581726074219,"y":1338.6715087890625,"wires":[["5a961aa8.a569e4"],["119a07f.fee65f8"],["5a961aa8.a569e4"]]},{"id":"c054e9a8.3fab18","type":"switch","z":"5e4dc05d.a1b24","name":"1文字判定","property":"c","rules":[{"t":"regex","v":"\\+|\\-"},{"t":"regex","v":"\\d"},{"t":"eq","v":"."}],"checkall":"true","outputs":3,"x":1052.6581726074219,"y":1205.6715087890625,"wires":[["5a961aa8.a569e4"],["119a07f.fee65f8"],["5a961aa8.a569e4"]]},{"id":"e0f463be.1f0ba","type":"debug","z":"5e4dc05d.a1b24","name":"状態表示","active":true,"console":"false","complete":"state","x":1161.6581726074219,"y":1084.6715087890625,"wires":[]},{"id":"95c14cbc.6a3eb","type":"inject","z":"5e4dc05d.a1b24","name":"451+","topic":"","payload":"45+1","payloadType":"string","repeat":"","crontab":"","once":false,"x":235.65817260742188,"y":1354.6715087890625,"wires":[["1ac45ea9.e53ba1"]]},{"id":"58eb4834.a714b8","type":"comment","z":"5e4dc05d.a1b24","name":"State pattern","info":"","x":217,"y":953,"wires":[]},{"id":"b07b3995.4f84c8","type":"comment","z":"5e4dc05d.a1b24","name":"文字列を検査するための状態遷移","info":"","x":433.5,"y":952.4287109375,"wires":[]},{"id":"8f5096d8.70af68","type":"comment","z":"5e4dc05d.a1b24","name":"検査する文字列","info":"","x":227,"y":1074,"wires":[]}]