OmniAICreator/Qiita-1.07M huggingface dataset:
AWS ECS/Fargate 操作覚え書き

バージニア北部+aws/dockerコマンド打てる環境にてECS/Fargate動作確認したメモ書き
ネーミングの一貫性の無さはご愛嬌w

※2018/10/3 追記 : 本題に入る前にECR/ECSの全体的な流れを図にしてみました
　その他諸々情報追加しています

# 全体の流れ

ECR : AWSに自分用のRepositoryを作成するまで
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223740/37708f28-71f8-749c-d18d-ccca32c2d57b.png)

ECS : Clusterを作成し実行環境を構築するまで(ELBについては割愛)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223740/dde1ffae-7474-060b-05ab-45cd80a49de3.png)

これを踏まえて、実際に構築してみましょう
#ECRへのイメージ登録

* レポジトリ作成

> ここでは ecraisi として作成 : XXXXX.dkr.ecr.us-east-1.amazonaws.com/ecraisi
 アクセス許可で対象のIAM への許可を追加しておくこと


docker login コマンドを取得

>$ aws ecr get-login --no-include-email --region us-east-1                                                             
 docker login -u AWS -p eyJwYXl....NDIzMTkxMn0= https://XXXXX.dkr.ecr.us-east-1.amazonaws.com

↑で入手したdocker login コマンドをコピペして実行
> $ sudo docker login -u AWS -p eyJwYXl....NDIzMjM2Mn0= https://XXXXX.dkr.ecr.us-east-1.amazonaws.com

試しに docker.io/nginx をベースにHello world させてみる
> $ sudo docker image pull nginx 

Dockerfileと
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223740/923e0f0e-c91b-002f-a47a-b64824aac7b8.png)
 index.html を作って
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223740/dc926736-020d-c868-3110-9a96d2252a39.png)

build
> $ sudo docker build -t mynginx .

リポジトリecraisi にイメージをプッシュできるように、イメージにタグを付けます
> $ sudo docker image tag mynginx XXXXX.dkr.ecr.us-east-1.amazonaws.com/ecraisi:mynginx

新しく作成した AWS リポジトリにこのイメージをプッシュ
> $ sudo docker image push  XXXXX.dkr.ecr.us-east-1.amazonaws.com/ecraisi:mynginx

ECSのリポジトリに登録されている事を確認しましょう

![IMG3.JPG](https://qiita-image-store.s3.amazonaws.com/0/223740/1c612c7c-451b-ec36-48ba-53df22244dff.jpeg)

# ロードバランサ作成 

*LB新規作成
>-ロードバランサメニューから "NLB"(Network Load Balancer) を作成
  名称は今回 ECSLB としました
-ターゲットグル―プの名称設定 
 ここでは AISITG 、ターゲットの種類=ip、port=80 とします

※"リスナー設定","ターゲットの登録" はこの時点では必要ではないですが
  ECSでクラスタ作成時にプルダウンで選択できるようになるので設定しておく事推奨
※Fargate するならリスナー設定/ターゲットグループはここで一旦削除し、"サービス作成"の段階で
　新規に設定した方が簡単です

※コンテナサービスへのアクセスはロードバランサのDNS名でアクセスします(EIP不要)

#ECS/Fargate 設定

* タスク定義:レポジトリにpushしたdocker image を新規タスクに登録
 (ECRでcontainar登録してなければ後述のECR設定を先に実行)

>-Fargateを選択
 ここではタスク名:MyTask とする
 -コンテナ ecraisi:mynginx を追加
 -ポートマッピングを tcp:80 として設定


![IMG5.JPG](https://qiita-image-store.s3.amazonaws.com/0/223740/8becd554-a04f-86e0-7ec4-539824d4af73.jpeg)

* クラスター作成

>-クラスターを "Networking Only"で作成
 ここではクラスタ名:MyECS としています

![IMG7.JPG](https://qiita-image-store.s3.amazonaws.com/0/223740/4a049969-982b-fed2-896f-9e4a2247a76d.jpeg)

* サービス作成

> クラスタの"サービス"タブから作成
 - FARGATEを選択
 - タスク定義 : MyTask を選択
 - サービス名: MyService 
 - タスクの数を設定 (サービスを削除するときにはタスク数=0にする事)
 - VPC/Subnet/SGを選択
 - ELBは当然NLB選択 > ECSLBを選択
 - 対象コンテナをELBに追加 
 - リスナーポート port=80を選ぶとターゲットグループ名に"AISITG"が自動選択
   (リスナーポート/TG共に削除してあればここで新規登録でOK)

![IMG10.JPG](https://qiita-image-store.s3.amazonaws.com/0/223740/6b41978e-2c86-5de0-a910-dfb7e1722d67.jpeg)


* 確認

>サービスの
”詳細”にロードバランスTG=AISITGとして設定
"タスク"にMyTaskが登録
されているのを確認

数分待ってるとターゲットAISITGに起動したコンテナの各IPが自動的に割り振られますので
http://NLBのFQDN でアクセスできたらできあがり！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223740/d4ab1d15-4c4d-9915-f5cd-87137b0398a9.png)
【AWS+Rails5+mackerel】AMIを使って複製したサーバがmackerelのダッシュボードに表示されない時の対処方法

# やりたいこと
- ALBに紐づけているWEB-APPサーバ1号機のAMIを取得して、2号機を立てたい
    - 1号機はmackerelエージェントをインストール済み
- 2号機にもmackerelエージェントをインストールしたい

# 環境
- AWS
- Ubuntu 16.04
- Rails5.1
- Nginx
- Unicorn

# 発生した事象
AMIから複製したサーバ2号機に、mackerelエージェントをインストールしてもダッシュボードに表示されない。
公式ページの手順に従い、以下のコマンドを実施。

```bash
wget -q -O - https://mackerel.io/file/script/setup-all-apt-v2.sh | MACKEREL_APIKEY='YOUR_APIKEY' sh
```

## 詳細
サーバ2号機のmackerelエージェントの起動ログを確認。

`$ sudo journalctl -u mackerel-agent.service`

以下のエラーが発生しており、mackerelエージェントが起動していない。

```bash
Dec 26 15:02:29 ip-10-100-4-182 systemd[1]: Starting mackerel.io agent...
Dec 26 15:02:29 ip-10-100-4-182 systemd[1]: Started mackerel.io agent.
Dec 26 15:02:29 ip-10-100-4-182 mackerel-agent[31438]: 2017/12/26 15:02:29 INFO <main> Starting mackerel-agent version:0.48.2, rev:549962c, apibase:https://api.mackerelio.com
Dec 26 15:02:29 ip-10-100-4-182 mackerel-agent[31438]: command.Prepare failed: failed to prepare host: custom identifiers mismatch: this host = "hogehoge.ec2.amazonaws.com", the host whose id is "hogehoge" on mackerel.io =
Dec 26 15:02:29 ip-10-100-4-182 mackerel-agent[31438]: exit status 1
Dec 26 15:02:29 ip-10-100-4-182 systemd[1]: mackerel-agent.service: Main process exited, code=exited, status=1/FAILURE
Dec 26 15:02:29 ip-10-100-4-182 systemd[1]: mackerel-agent.service: Unit entered failed state.
Dec 26 15:02:29 ip-10-100-4-182 systemd[1]: mackerel-agent.service: Failed with result 'exit-code'.
```

## 原因
**AMIを使用して複製したため。**

公式ページFAQにも記載があった。
[FAQ・エージェントが起動しない](https://mackerel.io/ja/docs/entry/faq/troubleshoot/agent-not-start)

>Docker ImageやAMIなどによりOSイメージ化した際に/var/lib/mackerel-agent/idもコピーしている場合、このファイルを削除する必要があります。
mackerel-agentは初回起動時にサーバーが発行したIDを/var/lib/mackerel-agent/idに保存します。以後はこのファイルに記載されたIDによりホストの識別を行います。
そのため、/var/lib/mackerel-agent/idがコピーされると実際は複数のホストがMackerel上では同一のホストと認識され、メトリックの投稿や監視が正しく動作しなくなります。

## 対策
- サーバ2号機の`/var/lib/mackerel-agent/id`を削除する。

```bash
$ sudo rm /var/lib/mackerel-agent/id
```

- 設定確認

```bash
$ sudo mackerel-agent configtest
sudo: unable to resolve host ip-10-xxx-xxx-xxx
/etc/mackerel-agent/mackerel-agent.conf Syntax OK
```

- mackerelエージェント再起動

```bash
$ sudo service mackerel-agent restart
```

## 確認
mackerelダッシュボードに表示されれば成功です。
AMIでEC2を複製する際にはご注意ください。
個人開発でサービスがリリースできない原因と反省/対策

ここ1年位、趣味として空いた時間でiOSアプリをつくっており、いわゆる個人開発をしてきた。

仕事終わりや休日などをちょこちょこつかって開発してきたが…**なかなか終わらない**…。なぜだろう…。

いまだリリースできていないので、どうやって開発していれば上手くいったのか?今後どうすればうまくいくのか?というのを書いてみる。


## 1.まず公開するべきだった

**機能を削ってでもまず公開することを考えればよかったと思う。**

公開せずにだらだらと時間が経ってしまうと、モチベーションを維持するのにエネルギーを使ってしまうので良くない。まず公開すると、使って貰う人の反応を見ることもできるし、機能の優先度なども決められるので、効率も上がるだろう。

まず最初に公開することを考えて、あとはそれから、くらいの気持ち。


## 2.期限を決めるべきだった

個人開発だし好きな時に適当にやりたい、と思っていたので、いつまでにつくるかみたいなことを決めていなかったし、進捗管理をしなかった。しかし、もしサービスを公開したいと思っているなら、リリースできないことが結局精神面で首を絞めることになるので、**いつリリースするかは最初に決めておくべきだったと思う**(もしくは、長期休みで作ることができるボリュームにするなど)。

アジャイルで開発し、週次や月次でスプリントを振り返り/再計画すれば、自分のスキルを過信せず、少ないリソースでどう実装を行うかというところが見えてくるはず。仕事みたいになってしまうのは気になるところだが…。最大でも3ヶ月程度で期限を決めておきたいところだなと感じた。


## 3.超MVPをつくるべきだった

**リーンスタートアップでいうところのMVP(実用最小限の製品)をつくるべきだった。**

もちろん想定よりは機能を削ぎ落としたつもりだったのだが、個人開発はとにかく時間がないので、MVPからさらに機能を削ぎ落として`超MVP`をつくるんだ、という意識でいると良かったのかなと思う。

そして、前述の`2`にもかかわってくるが、期限を先に決めた上で、その期限内でできることを実装するという方針でやるとよかったかもしれない。これもアジャイルで進めれば、何を削ぎ落とし、何を実装するべきなのかが開発を進める度に明確になる。間に合わなそうであれば、実装中であっても積極的に損切りして、あとでリリースすることにしたほうが、だらだらやって含み損(リリースできない=>モチベーションダウン)にやられるよりはいいと思う。


## 4.アウトプットをするべきだった

**開発してゆく中で、技術的なことなどを、ブログにアウトプットするべきだった。**

リリースまで何もアウトプットがないと誰も褒めてくれないので、モチベーションが折れやすいのかなと思う。Tips的な記事でも、リアクションをもらうことで継続するエネルギーが得られたかもしれない。普段仕事で書いているコードは月1.x記事くらいはブログを書いているが、それに加えて、個人開発の方も意識して時間をとってアウトプットすればよかったと思う。


## 5.毎日やるべきだった?

自分はリモートワークで仕事をしていて、よく海外をフラフラするのだが、1ヶ月とかの短期で旅行する場合、どうしても遊びを優先させてしまい、仕事以外でのコードを書かない日がけっこうあった。基本的に少しでもいいので毎日コードを書くという方針でやっていたが、こういう例外を許してしまうのはよくないかもしれない。ただ、ライフワークバランスを考えて、どちらが本当に自分にとって有益かというのは悩ましい。


## 上手くいった点

逆に、技術的なところはやってよかったなと思う。

今回は、React Native+Firebaseでつくっていたが、一通りの実装/開発フローを試すことができ、仕事でも(※メリデメ考えた上で)導入/実装できるかなと考えている。Reduxをつかって開発したが、純粋なビジネスロジックに関しては、Webでやっていることをそのまま流用できると実感できたし、仕事で作っていたSPAともベストプラクティスを共有し合うことができて(= 仕事で使ったコードを趣味に、趣味で使ったコードを仕事に)、効率に繋がった。

他のJSアプリでは、NativeScript+Angularを業務で使用したこともあったが、そこでハマったこととの比較(例えばネイティブ言語とのブリッジ)、そして、OSSコミュニティとしての比較などもできてよかった。

また、あえて大きめなboilerplateを使用したのだが、これもいい練習になった。理由としては下記のようなものである。

- エッジの効いた設計で、ライブラリの入れ替えが可能か試したかった
- モダンからレガシーに変わったコードをリファクタリングしたかった
- 仕事では0から設計することが多く、なかなかboilerplateを試すのは勇気がいる

これは両方共想定通り行うことができた。いまのフロントエンドにおいては、パーツを組み合わせて設計するスキルが必要だと考えていて、ある程度巨大なboilerplateを使って中長期で開発すると、既存プロジェクトにおけるライブラリの入れ替えを経験できるので、普段の業務にも活かすことができる。コードは良くない箇所が残っているが、設計思想を含めれば、名刺代わり程度にはなるかなーと思う。

## まとめ

上記を踏まえてやっていきたいです。

※リポジトリは探せばあるので興味ある方は…。

## 参考

- [Ask HN: How do develop a side project when you have a 40hr/week job?](https://news.ycombinator.com/item?id=10644373)
- [エンジニアとして個人でアプリとかいろいろ作って見ようと思ってたけど、振り返ってみるとやべぇ何も作ってねぇってなった時の対処法 - アナログ金木犀](http://motida-japan.hatenablog.com/entry/2015/06/22/120000)
- [個人開発のやっていき方 // Speaker Deck](https://speakerdeck.com/r7kamura/ge-ren-kai-fa-falseyatuteikifang)
- [個人開発を加速させるツール群 // Speaker Deck](https://speakerdeck.com/starhoshi/ge-ren-kai-fa-wojia-su-saseruturuqun)
- [週末在宅ワークの生産性を上げる5つの視点と31の工夫 - Qiita](https://qiita.com/Akira-Isegawa/items/ab7d6b5db65dc830bb62)
Tipnem PHP

#はじめに
はじめまして。[@soralis_nem](http://twitter.com/soralis_nem/)です。
ご縁があり[@44uk_i3](https://twitter.com/44uk_i3)さんの企画[nem Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nem)に参加させていただくことになりました。
すっかり参加していることを忘れてしまい、投稿が遅れてしまい大変申し訳ありませんでした。

#tipnemとは
[@namuyan](http://twitter.com/namuyan_mine/)さんが開発された高性能なtipbotです。
詳しくは[nem Advent Calendar 2017](https://qiita.com/advent-calendar/2017/nem)の12/5日の記事をご覧ください。

#tipnemをphpで
tipnemには高性能なAPIがありますが、httpではなくWebsocketを使っているため特殊です。
なむやんさんはPython版のライブラリは公開しているもののPHP版での扱い方を書いていきます。
本当はライブラリを書きたかったのですが、時間が足りなかったためサンプルコードをのみですが、そのうち公開するのでお楽しみに。


[textalk/websocket](https://github.com/Textalk/websocket-php)を使います。

```json:composer.json
{
	"require": {
		"textalk/websocket": "1.0.*"
	}
}
```
composer installをすればwebsocketが使えるようになります。

```php:sample.php
<?php


require('vendor/autoload.php');
use WebSocket\Client;

$url = "ws://tipnem.tk:8088";
$client = new Client($url);
$client->receive();
while (true) {

	try {
		$uuid = mt_rand(1, 2147483647);
		$req = ["command"=>"bot/info","data"=>[],"uuid"=>$uuid];
		$req = json_encode($req);
		$client->send($req);
		$res =$client->receive();
		$res = json_decode($res); 
		print_r($res);
		break;
	} catch (WebSocket\ConnectionException $e) {
		$client = new Client($url);
	}
}
```

さらっとこんな感じに書くととりあえずは完了です。
あとは仕様をよんで実装していくだけです。

<font color="Red">12/26 20:30追記 コードが間違っていたようなので修正しました</font>

追記
https://github.com/soralis-nem/tipnem4php
にコードを公開しました。
composer require soralis_nem/tipnem4php で利用できます。
DynamicLinkで起動された画面が「最近使ったアプリ」に残らない

# 注意
この情報は、2017/12/26現在のものです。
最新情報はこちらでご確認下さい。
https://firebase.google.com/support/releases

# 現象

- Dynamic Linkで起動された画面がRecentAppsに残らない  
    - 起動した画面で直接履歴ボタンを押した場合、OS5は自アプリがいない状態。OS6以降は存在はする
    - 起動した画面でホームボタン押下後やスリープ復帰後、履歴ボタンを押すと、自アプリがいない(OS5~全て共通)
- アプリをランチャーアイコンから再起動しても残らないまま
- アプリを設定アプリなどで「強制停止」させた後、再び残るようになる

# 調べたこと

「アプリ履歴に残さないフラグ」でも付いてんじゃね？
と思って、下記ログを仕込んでみた。

```MainActivity.java
FirebaseDynamicLinks.getInstance()
      .getDynamicLink(getIntent())
      .addOnSuccessListener(this, new OnSuccessListener<PendingDynamicLinkData>() {
        @Override
        public void onSuccess(PendingDynamicLinkData pendingDynamicLinkData) {
          // Get deep link from result (may be null if no link is found)
          Uri deepLink = null;
          if (pendingDynamicLinkData != null) {
            deepLink = pendingDynamicLinkData.getLink();
          }
          if (deepLink == null) return;

          // Intentフラグを確認するログ
          Intent intent = getIntent();
          if (0 != (intent.getFlags() & Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)) {
            Log.d("DynamicSample", "intent has Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS");
          }
          Log.d("DynamicSample", "getDynamicLink:onSuccess");
          // Handle the deep link. For example, open the linked
          // content, or apply promotional credit to the user's
          // account.
          // ...
          Log.d("DynamicSample", "getDynamicLink:url= " + deepLink.toString());

          // ...
        }
      })
      .addOnFailureListener(this, new OnFailureListener() {
        @Override
        public void onFailure(@NonNull Exception e) {
          Log.d("DynamicSample", "getDynamicLink:onFailure");
          e.printStackTrace();
        }
      });
```

起動はadbコマンドから。

```
$ adb shell am start -a android.intent.action.VIEW -c android.intent.category.BROWSABLE -d <DYNAMIC_URL>
```

で、出てきたLogcat.

```
D/DynamicSample: intent has Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
```

ビンゴ！

# バグなの？仕様なの？

というのは私には分からないので、Firebaseに問い合わせ。
結論。

**仕様です。**

ということだそうです。

※もしかしたら、adbコマンドで起動しているせいだよ、って言われるかと期待していたのですが、仕様、との回答だったので、adbコマンドで無くても、このフラグを付ける処理がFirebaseのSDK自体に入っているのではと思います。

# 対処

アプリを強制停止しないかぎり、ずっと残らないままになるのは困るし、ってことで、以下の対応をしました。

- Dynamic Linkを受け取って対象画面を起動するとき、**別プロセスで起動する**
    具体的には、`Intent.FLAG_ACTIVITY_NEW_DOCUMENT`を付けてやった感じです。

- Dynamic Linkで起動された画面は、`finishAndRemoveTask()`で終了する

ただ、微妙にOS5と、OS7で挙動が違ったり、一瞬、「最近使ったアプリ」に2つ自アプリが存在したり、いろいろとまだしっくりこない点はありますが、「ずっと残らない」よりはマシだろう、と判断して入れています。
C++ Builder 10.2 Tokyo > IDE > エディタに表示される狼煙（のろし）マーク > 消し方

```txt:動作環境
Rad Studio 10.2 Tokyo Update 2
```
### エディタに表示される狼煙マーク

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/9bd98b6a-c0ca-132a-1ae8-0f7f52ebadd4.png)

どうもreturnで戻るときに付くマークのようだ。
余分なマーキングは気になる。

### 消し方

エディタ設定 > 色 > 構造強調表示 > フロー制御強調表示を有効にする
のチェックを外す。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/cb923861-b45e-2edc-18a5-0628683ddf3d.png)

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/9f1aad54-a250-5d20-4471-15f9f8a7bfc2.png)

呪いは解かれた。
Railsでネストされたリソースのform_forを書く

ネストされたリソースに対してform_for

# 課題

Railsのルーティングでよくある

- 管理画面のURLを`/admin/~`にしたい
- 1:NのリソースをURLでも表現したい

といった場合

```ruby
# routes.rb
scope '/admin' do
  resources :topics do
    resources :comments
  end
end
```

これで`/admin/topics/:topic_id/comments`というルーティングが出来るわけですが、Commentモデルのform_forを書こうとした場合に問題が起こります。

```ruby
# View
= form_for @comment
```
これだと `NoMethodError - undefined method 'comments_path'` とエラーになってしまいます。
form_forは引数に渡したオブジェクトから自動でaction属性のURLを生成しますが、ルーティングまでは考慮してくれません。

# 解決方法
ルーティングでネストされたリソースに対してform_forを書くには引数を配列にしてネストを表現します。

```ruby
# View
= form_for [:admin, @topic, @comment]
```
```html
<!-- 出力されるHTML -->
<form action="/admin/topics/1234/comments" method="post">
```
C++ Builder 10.2 Tokyo > IDE > 下に配置 > わずかにずれる 

```txt:動作環境
Rad Studio 10.2 Tokyo Update 2
RAD Studio 10.2 Tokyo Update 3
```

関連: [c++ builder > IDE > 下に配置 > 最後に選択した物に合わせる](https://qiita.com/7of9/items/30d9e5a0ea88727fd10e)

同じことを10.2 Tokyoでも試してみた。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/ce145626-7484-bda2-c222-906db52ffa73.png)

Button1がわずかに上に見える気がする。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/76720671-d14a-d7d1-ad77-9e6427bca8aa.png)

TButtonとTComboBoxの領域の定義が異なるのだろう。


### XE4

XE4でも同じずれがあるようだ。
フラットUIになったことで、ずれに気づきやすくなったようだ。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/511f58c1-0e60-0aa9-3868-7b029aed9f44.png)
SCSSの`&`を使った時の挙動

sassで入れ子の中で`&`を使うと親要素のクラス名を継承できるのですが、
多用するうちにコンパイル後の結果がよくわからなくなるのでメモします。

▼SCSS

```SCSS
.list {
　.item { }

　&::after { }
　
　&__item { }

　& &__item { }
}
```

▼CSS

```CSS
.list .item {}

.list::after {}

.list__item {}　※入れ子にならないので注意

.list .list__item {}　

```
rbenvでruby2.5.0をインストール

ruby2.5.0リリースおめでとうございます。

HomebrewへのPRが早くもMergeされました :tada: 
[ruby-build 20171226 by hsbt · Pull Request #22135 · Homebrew/homebrew-core](https://github.com/Homebrew/homebrew-core/pull/22135)

ということで、さっそくインストール！

まずは`ruby-build`をアップグレード。

```sh
$ brew upgrade ruby-build
Updating Homebrew...
==> Auto-updated Homebrew!
Updated 2 taps (homebrew/core, homebrew/php).

...中略

==> Summary
🍺  /usr/local/Cellar/openssl/1.0.2n: 1,792 files, 12.3MB
==> Installing ruby-build
==> Downloading https://github.com/rbenv/ruby-build/archive/v20171226.tar.gz
==> Downloading from https://codeload.github.com/rbenv/ruby-build/tar.gz/v20171226
######################################################################## 100.0%
==> ./install.sh
🍺  /usr/local/Cellar/ruby-build/20171226: 373 files, 192KB, built in 3 seconds
```

rbenvで2.5.0インストール。

```sh
$ rbenv install 2.5.0
ruby-build: use openssl from homebrew
Downloading ruby-2.5.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.5/ruby-2.5.0.tar.bz2
Installing ruby-2.5.0...
ruby-build: use readline from homebrew
Installed ruby-2.5.0 to /Users/nishihara/.rbenv/versions/2.5.0
```

```sh
$ rbenv local 2.5.0
```

とりあえずlocalで使ってみよう :sunglasses:
Modeler 18.1.1からHive接続してみました。

Modeler18.1からHive接続が可能になっています。SQLプッシュバックにも対応しています。


IBM SPSS Modeler 18.1.1.0 - Detailed System Requirements
https://www.ibm.com/software/reports/compatibility/clarity-reports/report/html/softwareReqsForProduct?deliverableId=087DB540783711E7ACE8EE5CF6073F72&osPlatforms=Linux|Mac%20OS|Windows&duComponentIds=D002|S001&mandatoryCapIds=13&optionalCapIds=7|47|22|72|186|223#!

SDAPのドライバーで接続が可能です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/57da8f35-6103-fcb5-a50b-434fc9284e0f.png)

SDAPとはSPSS Data Access PackのことでModelerにバンドルされたODBCドライバーのことです。

■テスト環境
Modeler 18.1.1
ODBC Driver：IBM SPSS OEM 7.1 Hadoop Hive Wire Protocol 7.10.06.386
Hive:         1.2.1000
Hadoop: HDP-2.6.3.0

以下を導入します。
IBM SPSS Data Access Pack 7.1.2 Multiplatform English (CNKK9EN )

ODBCのデータソースを定義します。

以下のSPSS OEM 7.1 Hadoop Hive Wire Protocolを選択します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/b4b32a4a-5b67-75a5-3c0a-c41cd88b884c.png)

DSNとホスト名、DB名を入力します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/d304e780-7ab0-7f98-e6d3-048cf76ee413.png)

Advanceタブで"Use Native Catalog Functions"にチェックを入れます。ここにチェックが入っているとModelerでテーブルの一覧を取得できます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/f9d33df9-e717-61c5-7cc3-233bb6ef0a39.png)

Modelerからデータソースに接続します。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/f7cdd634-feef-9415-3572-d2c8782453da.png)

接続したデータソースを選択しOKをクリックします
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/d5be6df9-753e-96d0-2526-87845982c9b3.png)

"Use Native Catalog Functions"をつけているとテーブルの一覧が表示されます。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/671456b4-83e3-7a7e-7aea-4b2943c7efa5.png)

SQLプッシュバックもちゃんと動きました。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/15dd00b9-2bbf-5920-725f-943f10d6f594.png)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/223763/03793a06-df5a-54b0-d366-508316d64a19.png)
Amazon Lumberyardのエンジンソースをビルドしてみた

遅くなりましたが、[Lumberyard Advent Calendar 2017](https://qiita.com/advent-calendar/2017/lumberyard) 20日目の記事です。

Amazon Lumberyardのエンジンソースは無料で公開されています。

そこでAmazon Lumberyardのエンジンソースをビルドしてみました！
検証ではmasterブランチ(12/26時点では1.12と同様)にアップされたソースで行っています。


#事前準備

事前に最低50GBの容量は空けてください
※7.94＋18.45＋18.45=44.84GB＋αのソースがダウンロードされるため

#エンジンソースダウンロード

公式の[Github](https://github.com/aws/lumberyard)からエンジンソースを落とします。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/a19a6bc5-88ad-b2ed-1e77-e395e6f9928f.png)

※とりあえず試したい方はzipでダウンロードしましょう

#ビルド

落としたエンジンソースのフォルダを開きます。
中に「git_bootstrap.exe」があるので、それを実行します。
![top.png](https://qiita-image-store.s3.amazonaws.com/0/104377/048b001d-19f0-bc84-e23d-5e611e9c40c8.png)

するとコマンドプロンプトが立ち上がります。Enterキーを押すと残りエンジンソースのダウンロード開始です。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/157c4c5a-ae4d-1c14-23be-b090fe284c66.png)

ここからは完了までは長いのでひたすら待ちます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/85fca1a7-11b0-8666-568e-dbd2aab22215.png)

最後、Moving zipがダウンロードされれば終了です。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/e47ac5f2-e7c0-bf08-a9bc-dc27e6f5abad.png)

終了するといつものLumberyard Setup Assistantが立ち上がるので、あとは必要なSDK等をインストールするだけです。
ここから先は13日目にWheetTweetさんが投稿した[Lumberyardのインストールに関する基礎知識](http://magicbullet.hatenablog.jp/entry/LumberyardAdventCalendar2017_1)に記載されている内容と一緒なので省略します。

全ダウンロード終了すると、SetupAssistant.batが生成されているので、次回以降はこのバッチファイルを実行するとLumberyard Setup Assistantが起動されます

![image.png](https://qiita-image-store.s3.amazonaws.com/0/104377/cb344f83-93f1-a86f-da28-084f49c696fb.png)

#まとめ

ソースコードのビルド自体は手間がそこまで無いため非常に楽です。
是非お試しください！
ATOM VJパッケージ vedaのインストール

# はじめに
 
VEDAはテキストエディターATOM上で glslを書いてVJが出来るATOMプラグインです。
VJ用途でなくても、glslの製作に大いに役立ちます。
MIDIコントローラーつないで、つまみでパラメーターを調整出来るようにすると、glslのデバックが捗ります。

# 公式サイト
* https://veda.gl/

# インストール方法
 https://veda.gl/install/

 python 2やglslangValidatorを入れて
 手順に従ってインストールするだけです。
 ATOMのプラグインインストール後、依存パッケージを入れる必要があるので注意が必要です。
ChromeでSVGが表示されない現象

特定のSVGファイルがChrome（少なくともv51.0.2704.84 から、2017年12月26日現在の最新バージョンである v63.0.3239.108まで）で表示されない現象があるようです。

特定のSVGファイルとは、`image`要素の`xlink：href` 属性が `xlink：href = "data：img/png;` と記述されているものです。

IE,　Edge,　FireFox,　Safariのそれぞれ最新版ではこの現象は確認できませんでした。

## 解決法

テキストエディタでSVGファイルを開き、`xlink：href = "data：img/png;`　(画像赤罫線で囲った箇所)　を`xlink：href = "data：image/png;`と書き換えてやると正しく表示されます。

Photoshop, Illustratorの現行バージョンで書き出しを行うと、Chromeで表示されない`xlink：href = "data：img/png;`の方で書き出されるので注意が必要です。
![xlink：href属性を赤枠のように書き換えよう](https://qiita-image-store.s3.amazonaws.com/0/119598/41db731f-069b-7c31-42ae-352dc013ae6d.png)

Chromiumではこのイシューについて[議論が交わされている](https://bugs.chromium.org/p/chromium/issues/detail?id=620054)ので、いずれChromeのアップデートによって解消するかもしれません。

またSVG `image`要素で外部画像ファイル参照をする理由はこちらのエントリが大変参考になりました。

- [説明つきの画面キャプチャー図をSVGでつくる] (https://qiita.com/j8takagi/items/5d5f5de5c0d8b1bb788e)
- [SVGのimage要素での外部画像ファイル参照をbase64コード（URIスキーマ）に変換する] (https://qiita.com/j8takagi/items/96fe243b99d95f04ff24)

## 参考 

- [SVGs containing PNGs in data URIs sometimes don't display - https://bugs.chromium.org](https://bugs.chromium.org/p/chromium/issues/detail?id=620054) 
- [SVG CSS background image not showing in Chrome - CSS-TRICKS](https://css-tricks.com/forums/topic/svg-css-background-image-not-showing-in-chrome/)
numpy.linspace

```python
B = np.linspace(0,1,11,endpoint=True)
print(B)
print(B[1:])
A = np.linspace(0,1,11,endpoint=False)
print(A)
print(A[1:])
v = A[0]
print(type(v))
A = np.linspace(1000,1001,11,endpoint=False)
print(A)
print(A[1:])
```
```
[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]
[ 0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1. ]
[ 0.          0.09090909  0.18181818  0.27272727  0.36363636  0.45454545
  0.54545455  0.63636364  0.72727273  0.81818182  0.90909091]
[ 0.09090909  0.18181818  0.27272727  0.36363636  0.45454545  0.54545455
  0.63636364  0.72727273  0.81818182  0.90909091]
<type 'numpy.float64'>
[ 1000.          1000.09090909  1000.18181818  1000.27272727  1000.36363636
  1000.45454545  1000.54545455  1000.63636364  1000.72727273  1000.81818182
  1000.90909091]
[ 1000.09090909  1000.18181818  1000.27272727  1000.36363636  1000.45454545
  1000.54545455  1000.63636364  1000.72727273  1000.81818182  1000.90909091]
```
* 0.09090909*11 = 0.99999999

# Refs.
* [numpy.linspace](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.linspace.html)
* [numpy.finfo](https://docs.scipy.org/doc/numpy-1.13.0/reference/generated/numpy.finfo.html)  
https://stackoverflow.com/questions/1658714/range-of-valid-numpy-values
* [isinstance](http://ngi644.net/blog/archives/182)
* [while](https://www.pythonweb.jp/tutorial/for/index1.html)
* [float](http://d.hatena.ne.jp/omiyan/20101221/1292938626)
C++ Builder 10.2 Tokyo > IDE > ブレークポイントで止まらない > 誤操作

```txt:動作環境
Rad Studio 10.2 Tokyo Update 2
```

### 関数最後の閉じ括弧のブレークポイントで止まらない

```Unit1.cpp
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TDateTime dt;
	dt = IncDay(Now(), -7);
}
```

~~Tokyoでは、IncDay()実行の次の行"}"でブレークポイントを設定しても止まらなくなった。~~

**(追記: Tokyoでもきちんと止まります)**

XE4では同じ場所でブレークポイントが有効だった。

このあたりはデバッグ作業の効率にかかわる (関数の処理が最後まで実行された時の各種変数の値を見る場合)。

```Unit1.cpp
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	TDateTime dt;
	dt = IncDay(Now(), -7);
	int nop = 1;
}
```

上記のコードでも関数最後の閉じ括弧ではブレークポイントが有効ではない。
MSP430のIDEで見たような、コードの最適化によるブレークポイントの無効化、とは状況が異なるようだ。

### そもそもブレークポイントで止まらない
(追記 2017/12/26)

```Unit1.cpp
void __fastcall TForm1::Button1Click(TObject *Sender)
{
	ShowMessage(L"TEST");
}
```

上記のShowMessage()の行ですらブレークポイントが止まらない。

デバッグどうするかなぁ。。。

### 誤操作
(追記 2017/12/26)

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/b9d80df5-3fbf-e0c2-938d-a8ddcfe8f4ed.png)

1. デバッガを使わずに実行
2. 実行

「1」を使って実行していれば、ブレークポイントで止まらないのも道理にかなう。
Codeanywhereの無料プランでJupyter Notebookの環境を構築してみた

（2017.12.28 タイトルを少々改編、追記部分の作成）

# きっかけ
* せっかくの年末年始、なにか勉強したい
* 機械学習や深層学習を学びたいからPythonやりたい
* でも年末年始は妻の実家で泊まるゆえ、Wi-Fiの環境は実家にあるけどPCを持っていって堂々と広げて勉強する時間とスペースが無いと思われる
* 就寝前に寝室でスマホを使って何かできれば少しは学習になるかな？
* だったらスマホでコーディングできるCodeanywhereの環境を整えてみようかな
* グラフを表示するところまでやるとなったらJupyter Notebookかな
* リモートでやるの少し怖いけど簡単な勉強用途なら、まあ大丈夫だろうから、Codeanywhereで実行中のJupyter Notebookにスマホでアクセスできないかな

以上が動機。

# Codeanywhere (Free) に登録
難しいことはほぼ無いから大丈夫だと思うが、心配であれば解説記事はネット上にたくさんあるので参照してほしい。

# コンテナを作る
File -> New Connection -> Container から `Blank (ubuntu)` を選択。

# Minicondaのインストール
[こちらのページ](https://conda.io/miniconda.html)から `Linux 64-bit (bash installer)` のリンクを取得し、wgetでダウンロード、実行。

```
$ sudo wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh
$ sudo apt-get install bzip2
$ bash ./Miniconda3-latest-Linux-x86_64.sh
$ rm ./Miniconda3-latest-Linux-x86_64.sh
```

※Blankだとbunzip2が無いという理由でインストール失敗になるのでbzip2をapt-getで入れる。

※CodeanywhereのFreeプランはHDD容量が2GBと大変少ないので、不要になったインストーラは削除しておく。

※Minicondaの場所をbashrcのPATHに追加するか聞かれたら yes と答える。その後、ターミナルから`source ~/.bashrc`を実行する。

# インストールしたものを最新版にアップデートする
```
$ conda update conda
$ conda update --all
$ conda clean --all
```

※CodeanywhereのFreeプランはHDD容量が2GBと大変少ないので、都度 `conda clean --all` を実行して不要なファイルの削除を行う。

※Pythonのプログラミングをするだけなら、ここまででも充分、WebのIDE画面や、スマホ・タブレット（Codeanywhere専用アプリ使用）で行える。

# Python3.4 の環境を作る
記事執筆時点でのMiniconda最新版がインストールするPython3.6では一部のパッケージが大容量すぎて、CodeanywhereのFreeのHDDおよびメモリ容量の制限にひっかかりやすくなる。そのため、バージョンを3.4まで下げた環境を作成する。

```
$ conda create --name (好きな名前) python=3.4
$ conda clean --all
$ source activate (先ほどつけた名前)
```

# Jupyter Notebookのインストール
```
$ conda install jupyter notebook
$ conda clean --all
```

# Jupyter Notebookを利用する
## Jypyter Notebookの起動
```
$ jupyter notebook --ip=0.0.0.0
```

起動に成功すれば `http://0.0.0.0:8888/?token=abcdefg` のようなURLでアクセスできますよ的な表示が出るが、当然だが、Codeanywhere上で起動しているJupyter NotebookにアクセスできるURLではない。

## Codeanywhere上で動作するJupyter Notebookにアクセスする
infoページ（画面左側のコンテナ名を右クリック -> info）に表示されているURLのうち、

`http://port-XX.(コンテナ名やユーザ名などの文字列).codeanyapp.com`

このURLを利用する。 `port-XX` の部分の `XX` を `8888` に変え、URLの後ろに `/?token=abcdefg`（abcdefgは仮。画面に表示されているトークン文字列）をつける。

`http://port-8888.(コンテナ名やユーザ名などの文字列).codeanyapp.com/?token=abcdefg`

このようなURLを普段使いのブラウザのURL欄に指定してアクセスすれば、Jupyter Notebookが表示される。まあ、HTTPなので簡単な学習用途での利用に留めた方が良いとは思うし、不要なときは終了しておくべきだろう。:sweat_smile:

HTTPSで利用したい場合、アプリケーションが3000番ポートを利用するようにしないとらしいので、工夫が要るのだと思うが、まだJupyter Notebookに対して勉強不足なので、対策がわかり次第、追記する。

※Jupyter Notebookの終了はターミナルで Ctrl + C 。

# ここから先...
勉強したいパッケージを `conda install` で導入したい…が…、繰り返しになるが、CodeanywhereのFreeプランはHDD容量が2GB、メモリ容量も256MBとと大変少ないので、あれこれインストールしたくても限度があるので注意。一度に `conda install` せず、順番やインストールするバージョンを考慮した方が良い場合も多々ある。（自分が今回やったときは、Jupyter Notebookを入れたら、せいぜいNumPyくらいしか追加できなかった…グラフが使えない…:cry:）

なお、容量の限度を超えると「Disc quota exceeded」と出て、インストール処理が強制的に終了される。その場合は `conda clean --all` で取り敢えず復旧できるので、環境を再構築する必要は無い。

# 結論
割と苦労したゆえ、これだったら `$7` 払ってFreelancerプランにすべきなんだろうなあ、と。苦笑

とりあえず、この年末年始はNumPyが勉強できれば良いかなってことで。（年末年始に自分がどれだけ使うかを様子見で、とりあえず。）

# 追記
[PaizaCloud](https://paiza.cloud/ja/) を試してみた。Jupyter Notebookで勉強したいだけなら、PaizaCloudでJupyter Notebook環境を作る方が楽だったし、グラフ（matplotlib）も使えた…。:sweat_smile:
pm2-logrotate 使ってみた

# pm2-logrotate 使い方

- node.jsのデーモンツールpm2を使っている前提。
- 軽く使ってみた程度なので使い方を網羅してるとかではない。

## pm2-logrotateとは
コンソールログ(out_file、error_file) → の出力をローテートする機能(と認識している)


## pm2-logrotate 導入

https://www.npmjs.com/package/pm2-logrotate

```
pm2 install pm2-logrotate  
-- v2.4.0(2017/12/26現在)がインストールされた
```

- pm2 がインストールされていると(稼働していると？)自動でpm2-logrotate もインストールと同時に起動する
- max_size(ファイルのサイズ)、Interval(期間)が一致するとファイルが自動で分割されます。
サイズが超過してない人は明日(Interval)まで待ちましょう

(起動イメージ)

```
== pm2-logrotate ==
┌────────────────┬─────────────────────┐
│ key            │ value               │
├────────────────┼─────────────────────┤
│ max_size       │ 10M                 │
│ retain         │ all                 │
│ compress       │ false               │
│ dateFormat     │ YYYY-MM-DD_HH-mm-ss │
│ workerInterval │ 30                  │
│ rotateInterval │ 0 0 * * *           │
│ rotateModule   │ true                │
└────────────────┴─────────────────────┘
┌──────────┬────┬──────┬──────┬────────┬─────────┬────────┬─────┬───────────┬──────┬──────────┐
│ App name │ id │ mode │ pid  │ status │ restart │ uptime │ cpu │ mem       │ user │ watching │
├──────────┼────┼──────┼──────┼────────┼─────────┼────────┼─────┼───────────┼──────┼──────────┤
│ myapp    │ 0  │ fork │ 4478 │ online │ 146     │ 17h    │ 0%  │ 87.7 MB   │ hoge │ disabled │
└──────────┴────┴──────┴──────┴────────┴─────────┴────────┴─────┴───────────┴──────┴──────────┘
┌───────────────┬─────────┬────────────┬────────┬─────────┬─────┬────────────┬──────┐
│ Module        │ version │ target PID │ status │ restart │ cpu │ memory     │ user │
├───────────────┼─────────┼────────────┼────────┼─────────┼─────┼────────────┼──────┤
│ pm2-logrotate │ N/A     │ N/A        │ online │ 0       │ 0%  │ 4.133 MB   │ hoge │
└───────────────┴─────────┴────────────┴────────┴─────────┴─────┴────────────┴──────┘
```
### 設定の確認

```
pm2 get pm2-logrotate
```

### 設定の仕方

- ローテートログファイル名

~~時間までいらなかったので、ファイル名は日付単位にした~~
→ サイズ超過でローテートされて同じファイルに上書きされてたのでやはり元の形に戻す(2018/01/30)
(ソースを見た限り「サイズを見ない」みたいな設定は無さげだったのでやるならソースに手を入れる感じで)
もしくは、max_size が ～G(GB)まで設定できるみたいなので、それを膨大にするのも手

```
pm2 set pm2-logrotate:dateFormat YYYY-MM-DD
```

- ローテートする間隔

デフォルトが「0 0 * * *」とあるのに、公式には「*」が6つで解説されてて、一瞬ん？？？ってなった。
よくよく読めば「(*) 0 0 * * *」一番最初の項が省略可となっていた(デフォルト設定だと1日置きにローテートされる)

- ローテートするファイルサイズしきい値(そのサイズを超えたらローテート)

```
pm2 set pm2-logrotate:max_size 100G
```
無(B),K(KB),M(MB),G(GB) が設定可
[obsolete] C++ Builder 10.2 Tokyo > IDE > To-Doリストの表示 > Alt + v, t, t

```txt:動作環境
Rad Studio 10.2 Tokyo Update 2
```

TODOリストはソフト実装時の作業優先度を整理するためによく使う機能である。
XE4ではショートカットキーが割り当てられていなかった（使いずらい)。

Tokyoでもショートカットキーはないようだ。

TokyoでのTo-Doリスト表示方法は以下のようだ。
[表示] > [ツールウィンドウ] > [To-Doリスト]

### ショートカットキーの検討

Visual Studio 2017 CommunityエディションではTODOリストに対応するもの(タスク一覧)の表示は`Ctrl+\, T`となっている。

Tokyoで同じショートカットキーを追加しようとしたが、その機能がどこにあるか分からない。

## ショートカットキー

メニューを選択することで表示ができる。

- XE4
    - [c++ builder > TODOリスト表示 > Alt, v, l](https://qiita.com/7of9/items/a77ba2751538314598b4)
- 10.2 Tokyo
    - Alt + v, t, t

### 検索用キーワード

- TODOリスト

### IDE Insight search boxを使う
(2018/04/18)

上記のショートカットよりも、IDE Insight search boxを使う方が忘れにくい。

手順は以下に記載している。
[C++ Builder 10.2 Tokyo, XE4 > 構造の記憶を強いるUI > 検索で見つかるUI > 右上の検索ボックス(IDE Insight search box)からの「To-Doリスト表示」](https://qiita.com/7of9/items/c7b6ec29aa2d4a4aa927)
ラズパイでオフィス環境をセンシングしてグラフ化する【センサー値取得編】(3/4)

[ラズパイでオフィス環境をセンシングしてグラフ化する](https://qiita.com/tnagao3000/private/8ccebfb955f42d8138a3)のソフト準備編です。
この記事ではハード編で接続した次の３つのセンサーから値を取ってみます。

- [BME280から値を取る](#bme280%E3%81%8B%E3%82%89%E5%80%A4%E3%82%92%E5%8F%96%E3%82%8B)
- [TSL2561から値を取る](#tsl2561%E3%81%8B%E3%82%89%E5%80%A4%E3%82%92%E5%8F%96%E3%82%8B)
- [MH-Z19から値を取る](#mh-z19%E3%81%8B%E3%82%89%E5%80%A4%E3%82%92%E5%8F%96%E3%82%8B)


## BME280から値を取る
[AdafruitのBME280向けライブラリ](https://github.com/adafruit/Adafruit_Python_BME280)を使わせてもらいます。
使い方は上記のREADMEに記載されていますが、ざっくりと次の通りです。

- AdafruitのGPIOライブラリに依存しているので、最初にそちらをインストールします。
 
```bash
sudo apt-get update
sudo apt-get install build-essential python-pip python-dev python-smbus git
git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
cd Adafruit_Python_GPIO
sudo python setup.py install
```

- BME280向けライブラリをダウンロードしてAdafruit_BME280.py内の [I2Cアドレス](https://github.com/adafruit/Adafruit_Python_BME280/blob/68dda3178bc27c0f8855927197c4273c281a982b/Adafruit_BME280.py#L30) を修正します。

```python:(修正前)
# BME280 default address.
BME280_I2CADDR = 0x77
```

```python:(修正後)
# BME280 default address.
BME280_I2CADDR = 0x76
```

- サンプルを実行してみます。

```bash
pi@raspi-is:/tmp/Adafruit_Python_BME280 $ python ./Adafruit_BME280_Example.py 
Temp      = 27.361 deg C
Pressure  = 1015.87 hPa
Humidity  = 39.26 %
```

## TSL2561から値を取る
[sim0nx/tsl2561](https://github.com/sim0nx/tsl2561) を使わせてもらいます。
使い方は上記のREADMEに記載されていますが、ざっくりと次の通りです。

- インストールします。
 
```bash
pip install tsl2561
```

- サンプルも頂きます。
 
```bash
pi@raspi-is:/tmp $ cat example.py 
from tsl2561 import TSL2561


if __name__ == "__main__":
  tsl = TSL2561(debug=True)
  print(tsl.lux())
```
- サンプルを実行してみます。

```bash
pi@raspi-is:/tmp $ python ./example.py 
394
```

## MH-Z19から値を取る

先人の知見を参考にさせて頂き、そこから最小限のところを抜き出してみました。
https://qiita.com/UedaTakeyuki/items/c5226960a7328155635f
https://github.com/UedaTakeyuki/slider/blob/master/mh_z19.py

- 最小限のところを抜粋

```python:mh.py
# -*- coding: utf-8 -*-
import serial

ser = serial.Serial('/dev/ttyS0',
                    baudrate=9600,
                    bytesize=serial.EIGHTBITS,
                    parity=serial.PARITY_NONE,
                    stopbits=serial.STOPBITS_ONE,
                    timeout=1.0)

ser.write("\xff\x01\x86\x00\x00\x00\x00\x00\x79")
s=ser.read(9)

print ord(s[2])*256 + ord(s[3])
```

- 実行してみます。

```bash
pi@raspi-is:~ $ python mh.py 
796
```

以上で各センサーから値が取れました。

次は [ラズパイでオフィス環境をセンシングしてグラフ化する【簡易グラフ化編】(4/4)](https://qiita.com/tnagao3000/private/b9b9990f8e655b2b7208) です。
Jupyter Notebookの起動

# Mac OSでJupyter notebookを開くには

(インストールについては別途記載予定)

## ターミナルを開き、以下のコマンドを入力します。

```
jupyter notebook
```

ブラウザが開き、jupyterのweb画面が起動すればOKです。
デフォルトで8888ポートを使いますので、起動しない場合はその当たりも確認すること。
rails_adminでenumカラムのselectボックスに選択状態が反映されない


```ruby:config/initializers/rails_admin.rb
module ActiveRecord
  module RailsAdminEnum
    def enum(definitions)
      super
      definitions.each do |name, values|
        define_method("#{ name }_enum") { self.class.send(name.to_s.pluralize).map(&:first) }
      end
    end
  end
end
ActiveRecord::Base.send(:extend, ActiveRecord::RailsAdminEnum)
```

上記を追加すると、

```
<option value="hogehoge">hogehoge</option>
```

のようになって、保存も表示も文字列の方を使うようになって解決した。
最強のCSVファイルの読み込み（自称）～PHP編～


![csv_title.png](https://qiita-image-store.s3.amazonaws.com/0/134637/2b79ca5f-e1ef-28d6-eac8-7e35f1fbd80a.png)


お初にお目にかかります。**みのり**と申します。ｍ（＿＿）ｍ

いつもこちらのサイト様（=Qiita）には、大変お世話になっておりまして、我が家では、**「転ばぬ先のQiita」「一寸先はQiita(?)」**などの家訓が根付いております。

そんな**Geek**の皆さんが集う中にお邪魔して良いのかわからないのですが、
汎用的（この言葉も死語かしらん）に使えそうな（あくまで「使えそう」）部品を恩返し的にご提供できればと思い、ちまちま書いてみた過去の落穂拾い的な駄コードを、恥を忍んでアップしてみようという次第です。

**御用とお急ぎでなかったら、ゆっくりしてってね！**＞定型文

さて、前置きが~~ありえないくらい~~長くなりましたが、業務でもよく使われるのが、**CSVファイルの読み込み**かと思われます。

**CSVファイルからデータを取り込んで、そのままTBに~~ぶち込む~~とかが定番でしょうか。**

そこで、割りと**問題**になるのが、
##
1. CSVファイルの項目が変更（増減等）されて、改修しないとデータを投入している**テーブルとの整合性が取れない**

2. CSVファイルがExcel等で開かれ、**勝手にエンコードが変わって**しまい、システムで読み込めなくなった

3. CSVファイルの行数、ファイルサイズが膨大になり、**ファイルを複数に分割する**ことになり、読み込み部分を改修しなければならなくなった

4. CSVファイル等のパスをコードに直書きしていたら、**CSVファイルの配置場所が変更**になり、コードに手を入れることになった

##
といった点かと思われます。

**4はさすがに無い**としても、1～3は意外と起こりうるケースではないでしょうか。

そこで、こうしたケースは最初から回避してしまうのが吉かと思われますので、上記を満たすコードを**考察**（大袈裟）してみました。

解決策＝**理想郷**（だから、大袈裟）としては、以下の4点です。
##
1. CSVファイルの項目が変更されても、**configファイルのような外部ファイルを手直しするだけ**で、対応可能にする

2. 配置ディレクトリ内のCSVファイルを**何ファイルでも任意の数、読み込める**ようにする

3. 読み込んだCSVファイルの**エンコードを、思惑通りのものに変換**する

4. CSVファイルのパス等は、**configファイルのような外部ファイル**に書いておく

##
あ、なんか忘れていましたが、今回チャレンジしているのは**PHP**です。＞前置きの無駄遣い

ちなみに、**3.のファイルのエンコードの変換**に関しては、こちらを参考にさせて頂いております。

- [CSVアップロードからのMySQLへのデータ挿入 - Qiita](http://qiita.com/mpyw/items/caa2568284b69d270f8b)

こちらはその性質上、手の加えようがないため、ほぼそのまんまです。**実に申し訳ない。。**

さて、このように大変恐縮なシロモノですが、何かのお役に立つようでしたら、**みんな大好きGitHub**にコードを置いてありますので、ご自由にお使い下さい。
- [ぼくのかんがえたさいきょうのしーえすぶいふぁいるよみこみ～PHP篇](https://github.com/minori-sys/example-csvreader-php)

尚、当然の話ですが、CSVで一行目がヘッダー（？）項目でないファイルの場合は、勝手が違いますので、そのままでは使えません。適宜改修して頂けますと幸いです。
（ヘッダーありなしのフラグ作って、真の最強目指せばいいじゃん俺って思いますが、「それはまた、別のお話（懐かしい）」）

ちなみに、以前関わった案件でまさに、これらの要件にぶち当たったために書いたコードが元ネタなのですが、さすがに業務で使用したものをそのまま紹介する訳にはいかないということで、手を入れたら、まったく別モノになりました。

当時はファイルの文字コード等は固定だったため、**3.のファイルのエンコードの変換**等は搭載していなかったのですが、その辺りも入れられて（明らかに人のふんどしで（以下略）、ますます汎用的（だから、死語？）になったかな？と思われます。（自己満足）

目指すゴールが同じでも、別の方法でも実現できる。
プログラミングって素敵（はあと）。

最後になりましたが、Class名などのネーミングセンスが**致命的**なのは、どうか、そっとしておいてあげてください。
また、文章がしらふなのに、酔っ払ったようなテンションなのは、中の人の**「仕様」**です。
→「しらふなのに酔っ払ったテンション」はリアルに中の人が周りに言われ続けている**公式の見解**（？）です。

次回は、こちらを**Ruby**で書き換えてみようと思います。

という訳で、言いたいことは、アレだ。

**お暇なら次回も見てよね（はあと）。**＞定型文ではじまり、定型文でしめる

ちなみに、タイトルの「**最強**」は、もちろん、**ネタ**です。本気で突っ込まないで下さいね。

初めての投稿がこれでよかったのか、今日も悩みの尽きないみのりさんでした。。
C++ Builder 10.2 Tokyo > Error: OleStr型からDate型へのバリアント型変換はできません。

```txt:動作環境
Rad Studio 10.2 Tokyo Update 2
```

[C++ Builder > メモリが足りません (Abnormal Program Termination) > 再現方法](https://qiita.com/7of9/items/5b64b5ad82ce0e2119cf)
をTokyoで実行すると以下のエラーとなった。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/4dcbc1ce-31b6-0eea-ff3a-be18760ba49b.png)

XE4の時の「Abnormal Program Termination」よりもわかりやすいエラーになっている。

一方で、IDEの変更時(例: XE4からTokyo)にエラーメッセージがどう変化するかは注意する点かもしれない。
(エラーメッセージに厳密に対応したソフトでない場合は問題は起きない）。
CygwinにRuby2.5.0をインストールする

#CygwinにRuby2.5.0をmakeしようとするとエラーとなる

2017-12-25にリリースされたRuby2.5.0だがCygwin環境では
make時に以下のエラーとなる。

```
make[1]: ディレクトリ '/usr/local/src/ruby-2.5.0' に入ります
make[1]: 'encs' に対して行うべき事はありません.
make[1]: ディレクトリ '/usr/local/src/ruby-2.5.0' から出ます
Generating RDoc documentation
uh-oh! RDoc had a problem:
cannot load such file -- ripper

run with --debug for full backtrace
make: *** [uncommon.mk:492: rdoc] エラー 1
rm cygruby250.rc

```
とりあえずの回避策として --disable-install-rdoc
をつけてみた。

```
tar xvzf ruby-2.5.0.tar.gz
cd ruby-2.5.0
./configure --with-readline --disable-install-rdoc
make
make install

ruby --version
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-cygwin]
```
Ruby 2.5.1では修正された。
MySQL ver5.7でmysqldumpしようとしてエラーが出たときの対処法


databaseのバッグアップを取ろうとして一旦sqlファイルに落とそうとしたら、MySQLから次のようなエラーが出ました。

```shell
$ mysqldump -uroot -p hogehoge >hogehoge.sql
Enter password:
mysqldump: Couldn't execute 'SHOW VARIABLES LIKE 'gtid\_mode'': Table 'performance_schema.session_variables' doesn't exist (1146)
```

むむむっ！？
エラー文言を読む限り「テーブルの構造が違うぞ」ってことみたいですが、　　
ググったところ、これはMySQL自体をUpgradeすれば解決するようです。

```shell
$ mysql_upgrade -u root -p
Enter password:
Checking if update is needed.
Checking server version.
Running queries to upgrade MySQL server.
Checking system database.
(~~~中略~~~)
Upgrade process completed successfully.
Checking if update is needed.
```
終わったら再トライ。

```shell
$ mysqldump -uroot -p hogehoge >hogehoge.sql
Enter password:
mysqldump: Couldn't execute 'SHOW VARIABLES LIKE 'gtid\_mode'': Native table 'performance_schema'.'session_variables' has the wrong structure (1682)
```

今度もまた似たようなエラーですが今度は`wrong structure`と出ています。　　
とりあえずMySQL Server自体を再起動します。

```
$ mysql.server stop
Shutting down MySQL
.. SUCCESS!

$ mysql.server start
Starting MySQL
. SUCCESS!

$ mysqldump -uroot -p hogehoge >hogehoge.sql
Enter password:
```
今度は無事成功しました。
Google App Maker ー Calculated モデルを使ってスプレッドシートのデータを表示する

App Maker のモデルには Drive Tables の他にも Calculated モデルというのがある。
Drive Tables はデータの保存に使えるが、Calculated は読み取り専用。
使いみちとしては、**任意のデータ**をデータソースに設定できるという点が挙げられる。

App Maker はデータソースを使って画面とデータを紐付けるため、外部データを表示する場合なんかでとても重要になってくる。
スプレッドシートを読み取り専用のDBとして扱うパターンは結構多いはず。

本記事ではスクリプトからデータを作成するパターンと、スプレッドシートからデータを読み込むパターンで、どのように Calculated モデルを作るのかを解説する。


## 前提条件
次のような`Name`と`Email`を持った Calculated モデルを作成しておく。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/f94da512-f6f6-bc5f-c8f7-28ae0b267ebb.png)


## スクリプトからデータを作成
スクリプトでデータを作成していくパターン。
これをそのまま本番でつかうことはあまりないと思うが、基本なので解説しておく。

### データソースの作成
次の画像は UserByScript という名前でデータソースを作った例。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/dc7b05dd-a83b-fc91-558e-73ded394e758.png)


コードは次のように記述する。

```javascript
var records = [];

for (var i = 0; i < 10; i++) {
  var record = app.models.User.newRecord();
  record.Name = '名前'+ i;
  record.Email = 'hogehoge'+ i+ '@example.com';
  records.push(record);
}

return records;
```
ポイントは2点
1. `app.models.{モデル名}.newRecord()` で モデルに対応するレコードを作る
2. 1.のレコードの配列を return する


### Tables ウィジェットで実際に画面に表示したところ
Name と Email が設定されていることが確認できる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/a450c953-9743-dc2b-d21b-a3c1ed7486f5.png)



## スプレッドシートからデータを作成

### データを読み込むスプレッドシートを用意
事前に作成しておく。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/97ffeb4c-4719-5f08-09da-43c329977095.png)


### データソースの作成
次の画像は UserBySpreadSheet という名前でデータソースを作った例。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/4a090e49-923c-f73e-479f-3a0b7c146ac9.png)

コードは次のように記述する。
読み込むデータが違うだけで返却しているのは`スクリプトからデータを作成`した場合と同じになっているのがわかる。

```javascript
var records = [];

var sheets = SpreadsheetApp.openById('1jqeCaq_8Ae1TaFIiNEcfJTQoYBM0z4d3uXLmgtaA_JU');
var sheet = sheets.getSheetByName('user');
var values = sheet.getDataRange().getValues();

var nameColumn, emailColumn;

for(var i = 0, len = values[0].length; i < len; i++){
  if(values[0][i] === 'Name'){
    nameColumn = i;
  }
  if(values[0][i] === 'Email'){
    emailColumn = i;
  }
}

for (var i = 1; i < values.length; i++) {
  var record = app.models.User.newRecord();
  record.Name = values[i][nameColumn];
  record.Email = values[i][emailColumn];
  records.push(record);
}

return records;
```

### Tables ウィジェットで実際に画面に表示したところ
スプレッドシートの Name と Email が設定されていることが確認できる。
![image.png](https://qiita-image-store.s3.amazonaws.com/0/35595/fa3e2b94-72e8-413c-3ed0-c3a8db8f6785.png)



## 参考サイト
[Calculated Models  |  App Maker  |  Google Developers](https://developers.google.com/appmaker/models/calculated)
YamahaRTX1200(RTX1210)でGCPとVPN接続する


#参考にした記事
["RTX1210 で GCP VPN + 2リージョン AD 構成 そして誰もいなくなった](https://www.nire.com/2017/05/gcp-vpn-yamaha-rtx1210/)
このサイトの通りに設定すればうまくいきます。
1200も1210も今のところは区別はないと思います。

#設定例
tunnel select 5
 ipsec tunnel 101
  ipsec sa policy 101 5 esp aes-cbc sha-hmac
  ipsec ike version 5 2
  ipsec ike always-on 5 on
  ipsec ike encryption 5 aes-cbc
  ipsec ike group 5 modp1024
  ipsec ike hash 5 sha
  ipsec ike keepalive log 5 on
  ipsec ike keepalive use 5 on icmp-echo 192.168.200.101 #GCEのping用ホスト
  ipsec ike local address 5 192.168.100.1　#ローカルのIP
  ipsec ike local name 5 8.8.8.8 ipv4-addr　#ルーターのグローバルIP
  ipsec ike nat-traversal 5 on
  ipsec ike pfs 5 on
  ipsec ike pre-shared-key 5 text presharedkey #共有キー（[18.4 事前共有鍵の登録](http://www.rtpro.yamaha.co.jp/RT/manual/rt-common/ipsec/ipsec_ike_pre-shared-key.html)）
  ipsec ike remote address 5 8.8.4.4 #GCPで予約したVPN用のグローバルIP
  ipsec ike remote name 5 8.8.4.4 ipv4-addr #GCPで予約したVPN用のグローバルIP
  ipsec auto refresh 5 on
 ip tunnel tcp mss limit auto
 tunnel enable 5

特殊は使い方でもしていなければ、natはしているはずなので、
nat-traversalはonになるかと思います。

うまくいかないときは
syslog debug onにしてみましょう。
show log rev | grep IKE2
でIKE2がなにかエラーになっているはずですので、
上記の設定から外れてないかチェックします。

#はまった点
以下、私がはまった点を共有します。
##Syslogに「AUTH cannot accept IDr payload」
上記のipsec ike local name 5 8.8.8.8 ipv4-addrにローカルのIPを記載していた。

##NATを忘れてつながらない
nat descriptor masquerade static 1 1 192.168.100.1 udp 500
nat descriptor masquerade static 1 2 192.168.100.1 esp
nat descriptor masquerade static 1 3 192.168.100.1 udp 4500　#なくてもつながりましたが、念のため

#keepalive
icmp-echo以外は接続できているようでも接続が切れてしまいました。
それもまだ日を経ってテストしていないので、微妙です。

#補足
RTX1200のバージョンはRTX1200 Rev.10.01.65です。
grow-loader: methodレベルのcode-splitting -

# grow-loaderってなに

[grow-loader](https://github.com/line/grow-loader)の紹介記事はここにあります。　https://engineering.linecorp.com/ja/blog/detail/235


簡単に言うと、code-splittingは普段component レベル(HOC)でやってますが、grow-loaderを使うと、method レベルまでできて、より簡単に、よりフレキシブルに分割できそうです。

grow-loaderホームページはこちら: https://github.com/line/grow-loader

# 使い方は？

例えばこんなclsss：

```js

class SampleClass {

    method() {
        // ...
    }

    methodBind = () => {
        // ...
    }

    method2(){

    }
}
```

grow-loaderをwebpack configに入れたら、分割したいmethodにdecoratorをつけるだけ

```js

class SampleClass {

    @grow
    method() {
        // ...
    }
    
    @grow
    methodBind = () => {
        // ...
    }

    method2(){

    }
}
```

これえ`method()`と`methodBind()`は切り出される。

```js
const sample = new SampleClass();
console.assert(sample.method === undefined)
console.assert(sample.methodBind === undefined)
console.assert(typeof sample.method2 === 'function')
```

切り出したmethodを使いたかったら、`grow()`を実行する。dynamic importされます。

```js
const sample = new SampleClass();
sample.grow().then(() => {
console.assert(typeof sample.method === 'function')
console.assert(typeof sample.methodBind === 'function')
})
```

# なにが起きてる？

grow-loaderは事前class methodのdecoratorを検知し、methodを切り出して`grow()`をつけてる。
`grow()`の中では`import()`を使い、webpackのdynamic importをそのまま利用する。

# 効果は?

[LINEエンジニアブログ](https://engineering.linecorp.com/ja/blog/detail/235 )によると、ファイルの切り出しにはこまめにしてるので、普通の実装に勝てないが、methodレベルにしてるので、長いページを二段階描画にすることができて結構いい感じになった。

fmfm
Ubuntu 24.04 で Swift を使う

OS　の更新

```bash
sudo apt update
sudo apt upgrade
```

カーネルは　6.8.0-47-generic です。

前提ソフトのインストール

```bash
sudo apt install binutils \
          git \
          gnupg2 \
          libc6-dev \
          libcurl4-openssl-dev \
          libedit2 \
          libgcc-13-dev \
          libncurses-dev \
          libpython3-dev \
          libsqlite3-0 \
          libstdc++-13-dev \
          libxml2-dev \
          libz3-dev \
          pkg-config \
          tzdata \
          unzip \
          zlib1g-dev
```

ダウンロード

```text
wget https://download.swift.org/swift-6.0.1-release/ubuntu2204/swift-6.0.1-RELEASE/swift-6.0.1-RELEASE-ubuntu22.04.tar.gz
```

解凍

```bash
tar xzf swift-6.0.1-RELEASE-ubuntu24.04.tar.gz
```

パスの設定
> 解凍したフォルダに対して　シンボリックリンクを /opt/swift に張る

```bash
export PATH=/opt/swift/usr/bin:"${PATH}"
```

インストールしたら起動の確認

```text
$ swift --version
Swift version 6.0.1 (swift-6.0.1-RELEASE)
Target: x86_64-unknown-linux-gnu
```

簡単な計算

```text
$ swift repl
Welcome to Swift version 6.0.1 (swift-6.0.1-RELEASE).
Type :help for assistance.
  1> 1 + 2 + 3
$R0: Int = 6
  2> :quit
```

## プログラム

```swift:ex01.swift
import Foundation

let d=Date()

print("現在時刻")
print(d)

print(d.timeIntervalSince1970)
print("完了")
```

実行結果

```text
$ swift ex01.swift 
現在時刻
2024-10-17 05:24:02 +0000
1729142642.2236345
完了
```

## テキストファイルの読み込み

```swift:text_read.swift
// -----------------------------------------------------------------
//
//	text_read.swift
//
//						Oct/17/2024
// -----------------------------------------------------------------
import Foundation

let arguments = CommandLine.arguments
let fileName = arguments[1]

let file = FileHandle(forReadingAtPath: fileName)!

let contentData = file.readDataToEndOfFile()

let contentString = String(data: contentData, encoding: .utf8)!

file.closeFile()

print(contentString)
// -----------------------------------------------------------------
```

実行方法

```bash
swift text_read.swift file_example.txt
```

## 参考ページ
[Download Swift](https://swift.org/download/#using-downloads)
[Arch Linux で Swift を使う](https://qiita.com/ekzemplaro/items/aaf16d216e37c35031a6)
Chromeブラウザと英会話しながら形容詞の語順を学んでみる

# 概要
音声合成と音声認識の両技術を活用してChromeブラウザを相手に会話可能なページを作成します。
継続利用可能な役立つページにしたいので会話のテーマは「英語における形容詞の語順」の理解とします。

# TL;DR
1. デモサイトはこちら (Chromeブラウザでアクセスしてね！)
 - https://l-v-yonsama.github.io/learning-english/#/
1. ソースコードはこちら
 - https://github.com/l-v-yonsama/learning-english
1. 利用ＡＰＩはこちら
 - https://developer.mozilla.org/ja/docs/Web/API/Web_Speech_API

# 音声認識について
ＰＣのマイクに向かって喋った言葉を理解してもらう。
Web Speech API インターフェイスの「SpeechRecognitionＸＸＸ」を利用します。

今回利用したのは以下のとおり。

| インターフェース | 説明 |
|:-----------:|:------------|
| SpeechRecognition | 音声認識の親玉（認識言語や認識結果の候補数の設定など）   |
| SpeechGrammarList | 認識させたい単語の列挙 |

```js:speech.js
const SpRec = SpeechRecognition
const SpGrm = SpeechGrammarList

const words = QuestionGenerator.getWords() // 認識させたい単語を全部配列で取得
const grammar = '#JSGF V1.0; grammar words; public <words> = ' + words.join(' | ') + ' ;'

// 認識の準備として各種設定
const speechRecognitionList = new SpGrm()
speechRecognitionList.addFromString(grammar, 1)
SpRec.grammars = speechRecognitionList
SpRec.continuous = false
SpRec.lang = 'en-US'
SpRec.interimResults = false
SpRec.maxAlternatives = 3

SpRec.onstart = function (event) {
  // 認識開始
}
SpRec.onresult = function (event) {
  // 認識結果取得
}
SpRec.onend = function (event) {
  // 認識終了
}

```

# 音声合成について
ＰＣのスピーカーから言葉を発してもらう。
Web Speech API インターフェイスの「SpeechSynthesisＸＸＸ」を利用します。

今回利用したのは以下のとおり。

| インターフェース | 説明 |
|:-----------:|:------------|
| SpeechSynthesis | デバイス上の合成音声に関する情報を検索したり、speech の開始、一時停止、またはその他のコマンドを使用したりする際に使われます  |
| SpeechSynthesisUtterance | 発話内容（言語、音声の高低、音量を含む） |
| SpeechSynthesisVoice | システムがサポートする音声 |

```js:speech.js
// システムがサポートする音声のリストを取得
const voiceList = window.speechSynthesis.getVoices()

// 音声リストの1番目を利用して喋ってもらう
const msg = 'Hello!'
var utterThis = new SpeechSynthesisUtterance(msg)
utterThis.voice = voiceList[0]
window.speechSynthesis.speak(utterThis)

```

# 参考にさせていただいたサイト

1. 音声合成や音声認識を説明するデモ
 - https://github.com/mdn/web-speech-api/


# まとめ
音声合成、音声認識共にAPIの通りに引数を渡すだけで自動的しゃべったり、認識を行なってくれるので簡単に利用することが出来ます。

文頭が「a」の場合、「あ」って発音してもまず認識してもらえませんでした。
同じ「限定詞（determiner）」の「The」「ざ、じ」は大丈夫なんですけどねぇ。。。
ちなみに「**えいー**」って発音すると認識してくれるのですが、それは負けな気がするので「限定詞（determiner）」の部分は認識対象から外しました。
結果、キーボード操作なしの発話だけで操作可能です。
ぜひお試し下さい。

最後まで読んでくれた方ありがとうございます。