【第2回】コードを使い実践的な処理を実装してみよう

#はじめに

前回 (https://qiita.com/Go_Miyake/items/91c2a530f501d162c81a) では録画機能を使ってChromeアイコンをクリックするロボットの動作を作成しました。

今回はより実践的なトピックとして、コマンドの記述を行いながら、ロボットがスタックする（=停止して動かなくなる）状況を防ぐエラーハンドリングの実装について記載します。


#事前準備

ロボットの実行を失敗させるため、前回タスクバーに追加したChromeアイコンを削除（タスクバーのピン留めを外す）します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/d4c0644b-4691-e072-e7b2-50c6ac82ebf9.png)
↓
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/269c9019-9ef9-b071-0618-595769c3c169.png)


#ロボットの実行
前回録画により自動生成されたスクリプトを再度実行します。

```javascript
Click image template="comp0617-1"
Wait "2100"
```
1. 画面上部「実行」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/d3f8fa44-050b-494a-b616-254f8f2a979c.png)

2. HCR開発画面が非表示になる
3. クリック対象のブラウザアイコンがデスクトップ上に無いため（削除したため）ロボットが「待ち」の状態になる（=スタックした状態）
5. マウスかタッチパッドを触ってロボットを「停止」させる（もしくは30秒待つ）
6. Click “image” template…の行で停止している事を確認（黄色でハイライトされています）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/469db9d8-afe1-acf6-bf14-4b269fa4f27e.png)


7. 「停止」ボタンをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/05832995-669c-4c82-b2be-0aab576a95da.png)

8. 実行ログに以下のメッセージが出ている事を確認
>Jun 18, 2018 4:25:44 PM WARNING: WaitForが終了コード1で失敗しました: コンポーネントが画面に見つかりませんでした。      ファイル:Script1.tpr、行:1: Click "image" template="comp0617-1" 
>Jun 18, 2018 4:25:44 PM INFO: スクリプトは after 41 秒後に停止しました: GUIから手動停止       ファイル:Script1.tpr、行:1: Click image template="comp0617-1"

![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/5914c2ee-fdd2-d3f8-dacd-3e59fc211c17.png)

#なぜロボットが動かないのか
上記事前準備にてChromeアイコンを削除したため、イメージテンプレートにマッチする対象物が画面上に無いためです。HeartCore Robo実行時にロボットが止まる場合の原因の殆どがこれに該当します。

イメージテンプレート：
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/a9f0b80d-709b-c649-0a0d-af79d35f0a37.png)

Clickコマンドは「画面上にイメージテンプレートが存在する」場合を前提として動作します。「画面上にイメージテンプレートが無い場合」のハンドルが出来ません。

```javascript
Click “image” template=“<イメージテンプレート>”
```

#ロボットがスタックする状況を防ぐためのハンドリング（ComparetoコマンドとIf..Elseの使用）
HeartCore Roboには、パターンマッチング結果のチェックコマンドが用意されています。チェックコマンド"Compareto"と"If..Else"文を組み合わせて、ハンドリングを実装します。

この記事では以下のハンドリングを実装します。

- 画面上イメージテンプレートがある場合→対象をクリック
- 画面上にイメージテンプレートが無い場合→処理を修了


1. Click “image”.. 行の冒頭にスラッシュ2個を追加する（コメントアウト）
2. Wait...行を削除する（Waitについては後述）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/39d9a97b-7ba1-af02-12fb-fb526f043247.png)

3. コメントアウト行の下の空白部分を右クリック > コマンドを作成 > Click -File > Comparetoを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/4fa524de-d111-ff62-545d-70d92dba308b.png)

*HeartCore Roboコマンドの殆どは、画面上右クリックのメニュー選択から追加出来ます。*

４. Comparetoコマンドのプロパティ画面が起動
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/7619426f-1246-5045-64ab-249277b12157.png)

*HeartCore Roboコマンドの殆どはプロパティ画面でパラメーター調整が可能です。*

５. イメージテンプレートエリアのプラスボタンをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/a57db4a5-8296-c19e-38fe-6dd86d1a6dec.png)

6.　前回録画機能で取得したイメージ（.pngファイル）が格納されているフォルダ（Clickコマンド内template=”<イメージテンプレート>”と同じ名前のフォルダ）をダイアログから選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/1276b549-a2d8-e5f3-d456-f823b161e72b.png)

7.　「イメージコレクション」として選択された事を確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/3a40541a-225e-25fe-3973-7b6309461fcf.png)

8.　「イメージコレクション」左の右向き三角形をクリック > フォルダ内に格納されているイメージファイルをクリックすると「テンプレートプレビュー」が表示されて、「比較」ボタンがアクティブになった事を確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/674eb957-5441-f461-54a5-0d6a00a953a6.png)
　↓
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/054e2704-e7f5-1d5f-4164-1acf95367981.png)

9.　「比較」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/d59999be-ea5c-fb8a-0000-7975f229ccc6.png)

**_「比較」ボタンがシュミレーターとして開発時に頻繁に使用することになります_**

10.　「検索一致なし」と現れるのを確認 > OKを押してダイアログを閉じる
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/8a53a272-accd-9ba7-ba36-1cdf9f8345b8.png)

*「検索一致なし」と出た場合には、現行のデスクトップ上では選択したイメージテンプレートにマッチする対象が無い状況を示します。*

12.　プロパティ画面のOKを押して閉じます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/49ff2c3f-82d4-9c4d-2e25-06129a087b78.png)

13.　Comparetoコマンドがスクリプト画面に追加されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/c78de548-a31f-56c6-6211-22208be3ad3c.png)


# Comparetoコマンドについて
Comparetoは開発において頻度の高いコマンドの一つです。

```javascript
Compareto template="<イメージテンプレート>" method="search2"
```
コマンドの解説：
「イメージテンプレートとデスクトップをイメージマッチングして以下を実行せよ」という命令
- 対象物の有無チェック
- 対象物のXY座標取得
- マッチングした件数取得

*method="search2"はマッチング方法を「イメージ（画像）」であることを明示するパラメータです。他のマッチング方法（色・OCR）については別の回で解説します*

留意すべきは、Comparetoコマンド単体の実行では対象物クリックなどの画面上でのアクションは発生しません。後続にCompareto結果をハンドルするためのIf..Else文の追加が必要になります。

# Compareto結果をハンドルするためのIf..Else文を追加する

Comparetoコマンド実行後には、「対象物の有無チェック」の結果がシステム変数に保持されています。このシステム変数をエラーハンドリングとして使用します。

HeartCore Robo　におけるパターンマッチングの"成功"”失敗”結果は以下となります。

- 成功の場合:エラーコードが「０（ゼロ）」としてシステム変数に格納される
- 失敗の場合:エラーコードが「０（ゼロ）以外の値」としてシステム変数に格納される

1.　Comparetoコマンド行の直下で右クリック > コードテンプレート > If/else文 > ’if-else’文テストの成功と失敗を選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/24f0aaf6-7531-323b-98c2-1e8f646a4d21.png)

2.　If/Else文が追加された事を確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/fb6da6fd-ad4e-3c50-0df3-3f640acc9b92.png)


# If...Else文について
HeartCore Roboは、一般的なプログラムと同様に、If...Elseを使っての条件分岐処理が可能です。

```javascript
if (<条件式>) {
    <条件式がTRUEの場合の記述>
} else {
    <条件式がFALSEの場合の記述>
}
```

今回追加された記述:

```javascript
if ({_EXIT_CODE} == 0) {
    
} else {
    
}
```

の条件式の部分
>{_EXIT_CODE} == 0

"｛_EXIT_CODE｝"と中括弧｛｝で囲まれている部分が、上記の**「対象物の有無チェック」の結果がシステム変数に保持されています**に該当します。

HeartCore Roboでは、システム・ユーザー変数ともに全て｛｝で囲んで使用します。システム変数は変数前にアンダースコア(_)が付いています。詳細についてはFAQ内「Q: 変数は定義出来るのか」を参考にして下さい。
https://qiita.com/Go_Miyake/items/69fe8c3f4468544e3d0e

# If..Else内で「対象物の有無チェック」結果の成功処理を追加してみる

まず、イメージマッチングが成功した場合にはテンプレート上のクリックポイント（後述）をクリックする処理を追加します。

1.　IfとElseの間の空白行で右クリック > コードテンプレートを挿入 > 前回のイメージ検索のクリックポイントをクリックするを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/2ac3b6cf-e2f3-5c36-dd9a-e8465eaf9343.png)

2.　Mouse click…コマンドが追加された事を確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/e72bbdb2-0274-d598-833b-00a6ecf82ac9.png)

追加されたコマンド：

```javascript
 Mouse click to=x:{_COMPARETO_CLICK_X},y:{_COMPARETO_CLICK_Y}
```
「イメージテンプレートにマッチした画面上の対象物にマウスを動かして、イメージテンプレート上のクリックポイントをクリック」という命令になります。ここでも{中括弧}で囲まれたシステム変数が使用されています。

# If..Else内で「対象物の有無チェック」結果の失敗処理を追加してみる
今回のサンプルでは、イメージマッチングが失敗した場合に、エラーメッセージを出力させた上で全体の処理を終えるハンドリングを追加します。

*注：
実際のロボット設計においては、マッチングが失敗した場合の処理をユーザーと決定する必要があります（例：そのままロボットを終了させて失敗の旨を管理者にメールを送る、繰り返し処理内での該当箇所だけフラグを立てて後続処理を継続させる、etc..）*

1.　Elseの後の空白行で右クリック > Click – File > Exitを選択
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/bb950a24-ef1f-f6e3-421e-20d55f508c14.png)

2.　プロパティ画面 > 終了コードに”1” > 終了範囲にチェックを付けて“process”を選択 > 説明にチェックを付けて”ブラウザアイコンが見つかりませんでした”と入力 > OK
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/8a5daae2-d9cf-0673-2022-8040cc0e8fee.png)

3.　Exit..コマンドが追加されたことを確認 
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/09e48e81-09c1-7fd7-76d5-194c78120ac5.png)

追加されたコマンド

```javascript
Exit “1” scope=“process” desc=“<メッセージ>”
```
「指定したスコープ(プログラム全体・ファイル・サブプロシージャ・ for文) 内の処理を中断、任意でメッセージを出力せよ」という命令というなります。

この時点でロボットスクリプトは下記の通りです。
*注：Compareto行の”<イメージテンプレート>”は開発環境・日時によって変動します*

```Javascript
//Click image template="comp0617-1"
Compareto "comp0617-1" method="search2"

if ({_EXIT_CODE} == 0) {
    Mouse click to=x:{_COMPARETO_CLICK_X},y:{_COMPARETO_CLICK_Y}
     
} else {
    Exit "1" scope="process" desc="ブラウザアイコンが見つかりませんでした"
    
}

Report "Results.xml"
```

# エラーハンドリングを実装したロボットを実行してみる

これまでのスクリプトを実行して、エラーハンドリングが行われるかを確認してみます。

事前準備として、実行前に「イメージドクター」という機能を一旦無効化します。
スクリプト > イメージドクターの有効化 > チェックを外す

![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/5e08a30e-9b2c-0df8-494a-f0a2f24e3870.png)

この機能については実行時にイメージマッチングに失敗した際にその場でのリカバリやデバッグを可能にします。今回のサンプルでは、エラーを敢えて起こすのでこの機能は使用しません。詳細については別の回でカバーします。

1. 「実行」をクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/ab692887-2137-3939-a8dd-89dddf980b59.png)

2. HeartCore Robo開発画面が非表示になる
3. すぐにHeartCore Robo開発が戻る
4. 実行ログにはComparetoの結果失敗と、Else以下で定義した「Exit」により終了した旨のメッセージが表示されている

![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/6e51fbea-1f1f-b41f-6279-eb45fa4f4820.png)

> Jun 19, 2018 1:57:45 PM WARNING: CompareToは、終了コード1で失敗しました: 'search2'比較メソッドは失敗を報告しました。      ファイル:Script1.tpr、行:2: Compareto "comp0617-1\image1.png" method="search2"
Jun 19, 2018 1:57:45 PM INFO: スクリプトは after 0 秒後にExitで終了されました (コード=1): ブラウザアイコンが見つかりませんでした      ファイル:Script1.tpr、行:7: Exit "1" scope="process" desc="ブラウザアイコンが見つかりませんでした" 

ここでのポイントは、該当イメージが見当たらないためロボットがスタックする（=停止して動かなくなる）状態に陥る事無く、イメージマッチングの結果、画面上には該当する対象が無いために処理を終えたという状態にハンドル出来ました。

4.次に再度タスクバーにChromeアイコンを追加（ピン留め）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/69854fbc-c1aa-48a2-2639-a5e9c106719e.png)

5.再度実行ボタンをクリック
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/ab692887-2137-3939-a8dd-89dddf980b59.png)

6.Chromeが起動、実行ログには以下の様なログが出力されていることを確認
![image.png](https://qiita-image-store.s3.amazonaws.com/0/254242/b03c93ee-d1db-d77d-cbab-dc6732b98819.png)

>Jun 19, 2018 2:01:41 PM INFO: 結果を<プロジェクトフォルダ>\reports\Script1.tpr_1529845300854.ba804\Results.xmlに保存しています (   ファイル:Script1.tpr、行:11: Report "Results.xml") 
Jun 19, 2018 2:01:44 PM INFO: スクリプトは after 3 秒後に終了コード0で終了しました。(スクリプトの最後に到達)


# まとめ
HeartCore Robo　のコマンドは右クリックによる、コマンドテンプレートの追加とプロパティ画面による調整が可能である事がわかりました。

また、画面とイメージテンプレートのパターンマッチングの際のエラーハンドリングは

*Compareto...
If...Else...*

の組み合わせでエラーハンドリングが出来る事がわかりました。この方法でロボットがスタックする状況を防止出来ます。

#次回について
次回はさらに実践的な

- イメージテンプレートの変更方法
- 変数の使用
- ログ出力
- ロボットによるキーボード操作

について解説します。