OmniAICreator/Qiita-1.07M huggingface dataset:
Raspberry Pi 3 B  Wake on Lan etherwake

箇条書きですみませんが、備忘録として記載しました。

#【僕の環境は以下】
NOOBS_v3_1_1　でラズパイインストールしています。
現在のVer　以下で表示することができます。
$sudo apt-get install lsb-release
$lsb_release -a
以下が表示結果

```
Distributor ID:	Raspbian
Description:	Raspbian GNU/Linux 10 (buster)
Release:	10
Codename:	buster
```


$cat /proc/version　で　kernel ver表示　以下表示結果

```
Linux version 4.19.57-v7+ (dom@buildbot) 
(gcc version 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) 
#1244 SMP Thu Jul 4 18:45:25 BST 2019
```

#【１】ＰＣ　Bios設定
ＰＣにより色々と設定内容が違います。以下は僕のマシン
僕のマシン　2号機　Gateway　2013年10月購入　DX4840-H54E/GL
windows10 Home(windows7からVerup）
まずは　wake　on　lan　Bios設定
以下で設定
Power　Manegament　SetUp
　PowerOn PCIE Device on　Enable
  　Deep Power　Off mode Disable【ここが、ミソ】

1号機　Hp　2019年5月中古購入(Amazon）　HP EliteDesk800 G1 SFF
メモリ:16GB/新品SSD:240GB　でカスタマイズされたもの
Windows 10 Professional 
以下で設定
ＥＳＣキーでＢＩＯＳ設定画面がでる。
Advaced
 Power on Options
   After　Power on loss →on
Power
　S5 Maximum Power Savings →　Disable

#【２】ＰＣ　lan設定
コントロールパネルの
デバイスマネージャでネットワークアダプタの詳細設定で
Wake on Magic Packet を　有効にする。

#【３】ラズパイ　etherwake インストール
$sudo apt-get install etherwake

ためしてみる。

$sudo etherwake XX:XX:XX:XX:XX:XX(mac アドレス)

で立ち上がります。

ちなみに　windowsのmacアドレスは　コマンドプロンプトで
ipconfig/all
とたたいて　表示される物理アドレス

#【４】node.jsで動かしてみる。
1)nodejs　インストール
■Nodejs　Install
$sudo apt-get update
$sudo apt-get install -y nodejs npm
$sudo npm update -g npm

【nodejs,npmを最新とする】
■verを調べる
$sudo node　-v
$sudo npm -v

【node.jsを最新とする】
バージョン管理ツールのインストール
$sudo npm install -g n

$sudo n --stable（推奨版）
$sudo n --latest（最新）

■nodejsを最新版とする
$sudo n latest

■バージョンを推奨版とする。これにしておく。
$sudo n stable

■一応インストールバージョン確認
$sudo n ls

#【５】etherwake.js 作成

$sudo nano ethetwake.js

```node:etherwake.js
exec('sudo etherwake XX:XX:XX:XX:XX:XX', (err, stdout, stderr) => {
  if (err) { console.log(err); }
  console.log(stdout);
});
```

試してみる
＄sudo etherwake.js

これで立ち上がります。
【初心者向け】link_to にどんな引数を与えたらよいか

#詰まったこと
ドロップダウンメニューを使いカテゴリーごとに投稿を見られるようにしたい
~~slimの書き方がわからなかったので詰まってしまいました。~~
link_toの引数をどう与えるかどうかわからない という問題
(初めはslimの書き方が間違っていると思っていたので)

##前提
`@categories = Category.all`で全てのカテゴリーを取り出してeachでcategory変数に入れている。

```ruby:application.html.erb
<ul class="dropdown-menu">
  <% @categories.each do |category| %>
  <li><a href="/categories/<%= category.id%>"><%= category.name %></a></li>
  <% end%>
</ul>
```

##自力でやったダメな例
*href をlink_toに変更しています

```ruby:application.html.slim
ul.dropdown-menu
- @categories.each do |category|
  li= link_to "=category.name", "/categories/=category.id"
```

`li= link_to "=category.name", "/categories/=category.id"`がダメことはわかるが、どのように記述すればいいかわからない


##式展開には ＃{} が必要
式展開には ＃{} が必要と言う記事を参考にして記述してみた

```ruby:application.html.slim
- @categories.each do |category|
  li= link_to "#{category.name}", "/categories/#{category.id}"
```
これで無事に動きました！

#追記

コメント欄に、丁寧に解説していただいた方法があり優れていますのでそちらを参考にしてください！！

```ruby:application.html.slim
link_to category.name, category
```
だけの記述で済むようになります。


##参考にさせていただいた記事
https://chuckwebtips.hatenablog.com/entry/2015/10/29/000000

以上です。誰かのためになれば幸いです。
mbed講座-第0回　mbedとは？

# 講座の内容
* 第0回 - mbedの説明、オフラインコンパイラの導入
* 第1回 - デジタル出力
* 第2回 - デジタル入力
* 第3回 - アナログ出力
* 第4回 - アナログ入力
* 第5回 - PWM出力
* 第6回 - I2C
* 第7回 - SPI
* 第8回 - Serial
* 第9回 - 練習問題

なお、アナログ出力に関しては使用可能なピンが一つしかないうえ、使用用途が限りなく0に近いため省略します。Ethernetも同様です。

# mbedとは?
>mbed（エンベッド）はARM社のプロトタイピング用ワンボードマイコンおよびそのデバイスのプログラミング環境を指す。-Wikipedia

まぁ、これだけじゃわかりませんよね？

![IMG_0115.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/466207/6d0b0c70-f207-f751-c63e-959425469ecf.jpeg)

画像の上にある基板がmbedです。
下はサイズ比較用の消しゴムです。小ささが実感できると思います。
mbedはマイコンの一種で主にロボットなどの制御に使います。
mbedの場合、デジタル入出力、アナログ入出力、PWM出力、I2C、SPI、Serial、Ethernetなど数多くの機能を使うことができます（これらの機能の意味はそれぞれの回で説明します）。

## mbedの利点
*　プログラミングにC++が使える。
*　オンラインのコンパイラによりソフトを入れることなくプログラミングができる。
*　ピン数が多いので多くのアプリケーションに使える。

## mbedの欠点
*　高い（6000円くらい）
*　ライブラリがArduinoほど多くない
*　オンラインコンパイラが使いにくい

ただ、オンラインコンパイラではなくPlatformIOを使うこともできるので３つ目に関してはそこまで大きな欠点ではないと思います。
GoogleNestHubとNode-REDで強制英語リスニング環境を作る

# はじめに
## やりたいこと
* すぐに英語の勉強をサボるので、昔買った英語教材のDUO3.0が家にいる間はエンドレスで流れてほしい
(笑)
* 勉強中のNode-REDとGoogleNestHubも活用したい

## Node-REDのまとめ記事
* [Node-RED系の記事のまとめ](https://qiita.com/kazutxt/items/8c72448eefcba56dabef)

## 動作環境
RaspberryPi : 3
Node-RED: v19.4
raspbian : 9.8

# 本編
## 全体構成
* まず、全体構成は以下のとおりです

![abstract.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/8d83571b-13f1-c091-b56b-2414f526c197.png)

### 前提
* ラズパイとセンサー(HC-SR501 Infrared PIR Motion Sensor)を持っている
* Google Nest Hubを持っている
* DUOの教材を持っていて、セッションごとに音声データを結合して管理している
    * これが一番つらいかな・・・　セッションごとでなくても音声データが取り出せていれば大丈夫です


## フロー
![flow.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/d2ae60fa-5143-81d5-12aa-b3cfc1bf67a5.png)
ファイル場所や認証情報などが含まれるため公開ができません。すみません。
再生中は、別の音声が割り込まないように、一旦状態を取得し、音声が再生されていないことを確認してから動作するようにしています


* 人感センサー
    * GPIOを使って、特定のポートに刺してあるので、その値を指定します
* パラメタ設定
    * センサーの立ち上がり0から1だけに反応
    * 8時から22時までに反応
        * 夜中トイレに立ったときに動いたら困るのでｗ
    * 乱数を使って再生するファイルを決める
* 状態を取得
    * IPをGoogle Nest Hubのものにして、msg.statusをtrueを設定します
* Google Nest Hub (Nextは誤字)
    * node-red-contrib-castを利用
* 再生されていない
    * msg.payload.application[0].statusTextが空かDefault Media Receiverのときに再生可能とする
    * 再生中はファイル名が入るようです。また再生が終わってから少しの間はDefault Media Receierになるっぽいので、これも再生可能状態とみなします
* 再生データのパラメタ
    * msg.data,msg.payload,msg.statusを消します
    * contentTypeにaudio/mp3を指定し、IPなど必要な情報を設定します
* Google Nest Hub (Nextは誤字)
    * node-red-contrib-castを利用
* msg.payload
    * デバッグノードで情報を出力

## イメージ
![disp.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/259228/92171fe8-f466-c3e4-c709-a3b06ab9bdec.jpeg)

## 結果
* ちゃんと音声を読み上げてくれる
* 検証の過程で動画も流せることがわかったので、あとは、レスポンシブルな画面とかを作れるようになったら最強だなぁ

##　最後に
* 英語の成績が上がるかどうかは保証できません(笑)
Redisのキャッシュストア以外の使い方

※というタイトルは正確ではなくて、以下の用途も実際にはRedisの特性の一部を利用します。
Redis自体は主にインメモリデータベースとしての高速性を生かしてWEBアプリケーションのセッションやトークン、RDBクエリのキャッシュとして使われることが多いものの、データ型や付属機能を利用することでランキングの生成やロックマネージャ等に応用できる。

# リアルタイムランキング
SortedSetの機能を使うことで、リアルタイムランキングを作ることができる。
スコア(点数)を伴ったレコードを挿入するだけで、バッチ等の集計処理を挟まなくとも自動的にソートされたランキングデータが生成される。

例えば以下のようなランキングを作りたいとすると

| 順位 | 名前 (value) | 点数 (score) |
| :-- | :----------- | :---------- |
| 1   | smith        | 50.0        |
| 2   | paul         | 20.0        |
| 3   | john         | 10.0        |

SortedSetの機能を利用して以下のようにランキングを作成することができる。

```python
import redis

client = redis.Redis()

RANKING_NAME = 'TEST_RANK'

# ランキングデータを挿入
# zadd(key, value, score)
client.zadd(RANKING_NAME, 'john', 10.0)
client.zadd(RANKING_NAME, 'smith', 50.0)
client.zadd(RANKING_NAME, 'paul', 20.0)

# ランキングを降順で取得
# zrevrange(key, start, end)
client.zrevrange(RANKING_NAME, 0, -1)  # ['smith', 'paul', 'john']

# 新しいデータを挿入後も自動でソートされる
client.zadd(RANKING_NAME, 'george', 100.0)
client.zadd(RANKING_NAME, 'dave', 5.0)
client.zrevrange(RANKING_NAME, 0, -1)  # ['george', 'smith', 'paul', 'john', 'dave']

# 順位を取得
# zrevrank(key, value)
# 0スタートのインデックスが返るので、順位を表示するときは +1をする等
# 昇順はzrank(key, value)
client.zrevrank(RANKING_NAME, 'george')  # 0
client.zrevrank(RANKING_NAME, 'paul')  # 2

# 点数を取得
client.zscore(RANKING_NAME, 'paul')  # 20.0
client.zscore(RANKING_NAME, 'john')  # 10.0


```

※zrank/zrevrankで取得できる順位は昇降順に並び替えたリストの添字で、同点の順位を考慮出来ないので、アプリケーション側で適宜調整する必要があります。


# 分散ロック
setnxの機能を使ってリソースの排他制御を行える。
データベース内であればトランザクションが、アプリケーションサーバ内のプロセスであればmutexが排他制御に利用できるものの、サーバを跨いだプロセス間で制御を行うのは難しい。
Redisのsetnxには同じキーを登録できないという特性があり、登録に成功した場合は1を、失敗した場合は0を返すので、これをロックの獲得状態と見なしてリソースの排他制御に利用できる。

```python
import redis

client = redis.Redis()

# 'LOCK_NAME'をキーに登録
client.setnx('LOCK_NAME', 'hoge')  # True
# 確認
client.get('LOCK_NAME')  # 'hoge'

# 同じキーで登録を試みると失敗する
client.setnx('LOCK_NAME', 'fuga')  # False

# 解放する場合はdelete
client.delete('LOCK_NAME')
```

このままでは明示的にdeleteするまではロックが残り続けてしまうので、登録に成功した場合は併せてexpireを設定したり、valueにロック獲得時間を設定して次回参照時に超過した場合はdeleteする。


# Pubsub
redisを介して1:n n:nのクライアントでメッセージのリアルタイム送受信を行える。
チャネルという単位を通じて送信者(publisher)と購読者(subscriber)の間でメッセージを交換する。
subscriberがpublisherを兼ねることもできれば、対象のチャネルを購読している限りではpublisherが何人ものsubscriberに向けてメッセージを送信することもできる。
簡易なチャットアプリ等で利用できる。

送信側(Publisher)

```python
import redis

client = redis.Redis()
# "test"チャネル に "hoge"メッセージ他を送信
client.publish('test', 'hoge')
client.publish('test', 'fuga')
client.publish('test', 'exit')
```
受信側(Subscriber)

```python
client = redis.Redis()
pubsub = client.pubsub()
# "test"チャネルを購読
pubsub.subscribe('test')

for message in pubsub.listen():
    print message.get('data')
    if message.get('data') == 'exit':
        # 終了メッセージなら購読終了
        pubsub.unsubscribe()
```
Rails resourcesメソッドについて

#resourcesメソッドについて
Railsでよく用いられる７つのアクションに対するルーティングを生成してくれるメソッド。

resourcesメソッドを使わない場合は
以下の様にアクションごとに
  get 'tweets' => 'tweets#index'
  get 'tweets/new' => 'tweets#new'
  post 'tweets' => 'tweets#create'
  delete 'tweets/:id' => 'tweets#destroy'
  patch 'tweets/:id' => 'tweets#update'
  get 'tweets/:id/edit' => 'tweets#edit'
  get 'users/:id' => 'users#show'
  get 'tweets/:id' => 'tweets#show'
を宣言する必要がある。

resourcesメソッドを下記の様に宣言すると
上記の７つ分の宣言と同じ扱いになる。

~~~ruby:routes.rb

Rails.application.routes.draw do
  resources :tweets#コントローラー名
end

Rails.application.routes.draw do
  resources :tweets, only[:index]
end
#オプションを指定し、任意のルーティングのみを作らせることもできる。
~~~

##ネスト
またresoucesメソッドを使うことで
ネスト（入れ子構造）のルーティングを作成することができる。

~~~ruby:routes.rb
resources :tweets do
 resources :comments, only: [:create]
end
~~~

上記のように書くことで、tweetsのルーティングに
commentsへのルーティングを追加することができました。

###ネストする意味
ネストをする必要がよく分からなかったので、
調べた上での自分の認識を書いて置こうと思います。

例えば、一つのツイートに対して、コメントを残すことできる
アプリケーションの場合で考える。

####ネストなしの場合（画像はイメージ）
<img width="389" alt="スクリーンショット 2019-07-20 20.38.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449764/1aafffa1-ef9a-242c-99eb-1423e1f8dc0f.png">

tweetsとcommentsで処理の流れが独立している。
そのためcommentsはtweetsの情報を持つことができないので
どのツイートに対するコメントなのか結びつけができない。

####ネストありの場合（画像はイメージ）
<img width="542" alt="スクリーンショット 2019-07-20 20.41.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449764/9bf176f6-d8af-92e0-ba61-c1004ffe9ec3.png">

ネストをすることで、commentsのルーティングはtweetsのルーティング処理上のcommentsであることを認識することができる。
そのためcommentsはtweetsの情報を受取ることができるので
どのツイートに対するコメントなのか結びつけることができる。
駆け出しVimmerの奮闘記

#環境
- MacOS Mojave versoin:10.14.5
- Macbook Pro

#前置き
最近Vimというエディタの存在を知り、習得したら効率よくコードかける！と思い、始めた。
よく分かってないが、とりあえずターミナルで
```vim ファイル名```
とすれば、勝手にVimで開いてくれた。ここでは、素のVimで自分が覚えたコマンド、覚えたいコマンドを一覧にしておこうと思う、そうつまり自分用ですね。
どんどん追加していく予定です
#2019/7/20
- モード
 - ノーマルモード `esc`または`Ctrl+c`でこのモードになる
 - インサートモード `i`,`Shift+i`でこのモード
 - ビジュアルモード `v`,`Shift+v`,`Ctrl+v`でこの...
 - コマンドモード `:`で...
- ファイル
 - `:w`で保存
 - `:q`で終了
 - `:q!`で強制終了
 - `:wq`で保存して終了
- 移動
 - ノーマルモード(Normal)で`h` `j` `k` `l`、順に左、下、上、右にカーソルを移動
 - Normalで`w` `b` `e`で単語間のジャンプ

etc...
【Houdini】ポイント番号ををVEXでソートする

vexを使ってポイントを任意のルールでソートしようと思ったらちょっと手間取ったのでメモしておきます。

## まずsort SOPで答え合わせ

サークルにscatterしてsortSOPにY軸の値でソートさせたのがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8302/2ea946b3-f25e-4f6e-7ff1-80311cde7b24.png)

## vexでのソート

このようなコードでソートさせました。ランオーバーはdetailです。高級言語のソート関数に相当するものは存在しないので、argsort関数で別の配列にソート済みの並び順を代入することでソート処理の代わりとします。argsort関数は文字コード及び数値の降順でしかソートできないようです。

```c
float pos_arr[] = {}; // y座標の配列
for(int i=0;i<@numpt;i++) {
    vector p = point(0, "P", i);
    push(pos_arr, p.y);
}
int ordering[] = argsort(pos_arr); // 数値が大きい順にポイント番号（ただしくは配列のインデックス番号）を格納する
ordering = reverse(ordering); // 小さい順にしたいので反転する。

// visualizeさせるために適当なアトリビュートに代入する
//（ordering配列のまま処理を進めるだけならばこの処理は必要ない）
for(int i=0;i<@numpt;i++) {
    setpointattrib(0, "sort_index", ordering[i], i);
}
```

sort_indexをvisualizeしたのがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8302/72691f57-16a2-a17f-f881-2ef8270b459f.png)

visualize のために sort_index アトリビュートを設定しましたが、通常は上記のコードで ordering に相当する配列にソート済みポイント番号が入っているのでそれをそのまま使います。

## さらに別要素でソートする

argsort 関数(および sort SOP)は stable sort といって、評価順位が同じものは元の順序を保ったままのソート実装だそうです。つまり、別の要素で２度目のソートをしても同じ優先順位を持つ部分では１度目のソート順をキープするはずです。

円ではわかりずらいので２ｘ２のグリッドを用意します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8302/d10c843e-7898-ef10-88c6-ed85a0b5c6eb.png)

上段左からグリッド作成時そのまま、SortSOPによるY座標昇順ソート、SortSOPによるX座標降順ソートの順に対応したもの、下段はグリッドそのままをSortSOPによるX座標降順ソートのみ対応したものです。一番右上のグリッドではポイント番号が右方向からかつ上方向からで並んでいるのが確認できます。

これを vex で同等の処理をさせてみます。

```c
float pos_arr[] = {};
int ordering[];
vector p;

// y座標を収集
for(int i=0;i<@numpt;i++) {
    p = point(0, "P", i);
    push(pos_arr, p.y);
}

// y軸で降順ソートして昇順に変換
ordering = reverse(argsort(pos_arr));

// x座標を収集
pos_arr = {};
for(int i=0;i<@numpt;i++) {
    p = point(0, "P", ordering[i]);
    push(pos_arr, p.x);
}
// x軸で降順ソートして昇順に変換
ordering = reverse(argsort(pos_arr));

for(int i=0;i<@numpt;i++) {
    setpointattrib(0, "index", ordering[i], i);
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8302/67bc1a30-c836-7fc1-6150-b6fa74378c9f.png)
求めている状態になりました。

sort SOP のパラメータ設定では対応できない複雑なソートでも、vex であれば対応させられそうです。 

## 実際にポイント番号をソート順に割り振りたい

プログラムでそのまま処理する場合はordering配列をそのまま扱えばいいのですが、実際にポイント番号を入れ替えたい場合は、sort SOPにアトリビュートを元にソートさせてしまった方が簡単です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/8302/49e5d620-66f6-5ef8-4879-18a885e9e7c1.png)

これを vex でやるには、ポイントの位置を入れ替えて、頂点をつなぎなおせば可能な気はします。やってみるか？


## 考察
今回は０から並んだポイント番号をソートさせたので必要なかった(ordering配列が欲しいものそのものだった)ですが、任意の要素をソートさせた場合、reorder関数でソート済みの任意の配列を得る処理が必要です。
参考 [vex : argsort](https://www.sidefx.com/docs/houdini/vex/functions/argsort.html)
【備忘録】オブジェクト指向が明快になるヒント

# まず、こちらをご覧ください。

ツイッターで見つけた**たぬを**さんのこちらの投稿です。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">オブジェクト指向言語における「.」は「の」の意味と覚えとくと分かりやすい。<br><br>「人間の手の指」をバラバラにするとわけわからんだろ？<br><br>だからhuman.hand.fingerって書けるようにするんじゃよ。<br><br>これ、豆な。 <a href="https://t.co/HMRwYJjjK4">https://t.co/HMRwYJjjK4</a></p>&mdash; たぬを@古巣たぬきエンジニア (@se_mimizuku) <a href="https://twitter.com/se_mimizuku/status/1134646828303912961?ref_src=twsrc%5Etfw">2019年6月1日</a></blockquote>



## 感想
私の拙い説明を入れて情報の純度を下げたくない、
ツイッターだと投稿を探しにくいという理由で書いたので、
内容は説明無しに感想だけ書かせて頂きます。

オブジェクト指向が何か？については自分のような
オブジェクト指向のオの字もわかっていない人間だけでなく、
熟練したエンジニア同士でも意見がわかれたりする様なのでこの記事で何がどうとかを断定はしませんが、上記の説明で非常に理解が進みました。

勿論これを知れば学習終わり！ではないのですが、
学習を進める中でかなり助けになっている事を、日々ひしひしと感じます。
【JavaScript】setInterval(kansuu(), 1000);って何で動かないの？

# setIntervalとは
[こちら](http://www.htmq.com/js/setinterval.shtml)に記載があります。
>一定時間が経過するごとに処理を実行する際に使用するものです。

もっとザックリ言えば**自動で処理を繰り返す**時に使います。

## 結構タイポする。
私だけかも知れないんですが、結構タイポするんですよね。
kansuuっていう関数があったとしたら以下のように。

```javascript:machigai.js
setInterval(kansuu(), 1000);
```
1000ミリ秒毎に繰り返しkansuuを実行して欲しいんですが、これじゃあ希望通りに動かないんですよね。

## 正しいコード

```javascript:seikai.js
setInterval(kansuu, 1000);
```
これが希望通り1000ミリ秒毎にkansuuが実行されるコード。

## そういう決まりって覚えれば良いのか？
別にそれでも良いと思います。
でもそれだと何となくよく見るエラーなんて認識になるし、
理解がないから記憶が定着しにくいんですよね。
できれば理由まで知っておくのが吉かと。

## 動かない理由
最初にリファレンスから引用した文章をもう一度。
>一定時間が経過するごとに処理を実行する際に使用するものです。

一定時間が経過するごとに**処理を実行**します。
ここを覚えてください。

### kansuu()の()って何でしたっけ？

そう。関数kansuuの**処理を実行**するための記述。
なので最初のコードはどう認識されているかというと。。。

```javascript:machigai.js
setInterval(kansuuの処理内容, 1000);
```

命令したい「1000ミリ秒毎に繰り返しkansuuを実行」と違うわけですね。だから実行されないという訳です。

## 最後に
やっぱりプログラマーとしては全てのものに理由がある。
これは忘れてはならないと思います。
~~個人的には日常生活でもこれは大事だと思いますが、そこまで言うのは余計なお世話な気が~~

この他にもサーバーの再起動で動作できるようになった、
とか色々何となく理解したつもりの場面はありますが、
全部を言語化できるレベルまで理解したいなあと。
実現可能かはさておき理想は理想として持っておきたいですね。
自分が過去に発表したLT資料まとめ


#１回目 2019年6月15日
ProLabo
https://itpropartners.connpass.com/event/132379/

発表資料
Laravel×React×Next.jsで会計アプリを作ってみた
https://docs.google.com/presentation/d/1z2foBs6q0b7dQ9zvxqVhlsCDKwCBllzEhBsxfqsMDV8/edit?usp=sharing

#2回目 2019年6月27日
Try English LT! for engineers
https://try-english-lt.connpass.com/event/133844/

発表資料
A story about developing a learning English app for engineers
https://docs.google.com/presentation/d/1ueLECpLbZwIbPY3V2tig9NY00EfI_I4Q2u3shGA2ssw/edit?usp=sharing

#3回目 2019年7月20日
ProLabo
https://itpropartners.connpass.com/event/138238/

発表資料
エンジニア向けの英語学習アプリを開発した話
https://docs.google.com/presentation/d/1jvG15nakcHMpCFXQizVCSGyMHAdG7nL6Tvww0w6ytyY/edit?usp=sharing

#4回目 2019年8月28日
集まれSwift好き！Swift愛好会 vol43 @レバレジーズ
https://love-swift.connpass.com/event/141921/

発表資料
エンジニア向けの英語学習アプリを開発した話
https://docs.google.com/presentation/d/1jvG15nakcHMpCFXQizVCSGyMHAdG7nL6Tvww0w6ytyY/edit?usp=sharing

#5回目 2019年9月8日
第2回 Try English LT! for engineers
https://try-english-lt.connpass.com/event/141242/

発表資料
綺麗で読みやすいコードの書き方
how to write clean code
https://docs.google.com/presentation/d/1RRscs5WfCeDKrwhqgSk7dmnpy1j7lW3YeIUT6esDLwo/edit?usp=sharing

#6回目 2019年11月28日
第3回 Try English LT! for engineers
https://try-english-lt.connpass.com/event/152272/

発表資料
Test code of JavaScript
JavaScriptのテストコード
https://docs.google.com/presentation/d/1sQ9hXuTYzDSCaO91KGgSFtN6PVW33t9fCIfyQxd1HDA/edit?usp=sharing

#7回目 2020年7月4日
第5回 Try English LT! for engineers
https://try-english-lt.connpass.com/event/178498/

発表資料
How I work in the global team of the Japanese company
私がどのように日系企業のグローバルチームで働いているか
https://docs.google.com/presentation/d/1cOLJJxVR9TdrOTUHckVySZQ6dmkV-CRP9kbyDdPOw5w/edit?usp=sharing

#8回目 2020年11月1日
第7回 Try English LT! for engineers
https://try-english-lt.connpass.com/event/191090/

発表資料
The story of creating a bubble tea map with React and TypeScript
ReactとTypeScriptでタピオカマップを作った話
https://docs.google.com/presentation/d/1gMzCPNT5gTx4ka0R25G6MstxSgXWukhdbkRcyHReXGs/edit#slide=id.p
Flutter toast プラグイン選定(2019/07/20)

![Screenshot_1563616909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37766/5db02109-4516-9273-7873-e4db9c538089.png)


# 注意
webエンジニアが片手間でflutterでくだらないアプリを作成したときの備忘録です。
アプリのガイドラインに沿わない情報もあるかもですがご容赦ください。

# 2019/07/18時点でのToast pluginの種類

* [toast](https://pub.dev/packages/toast)
* [fluttertoast](https://pub.dev/packages/fluttertoast)
* [flutter_just_toast](https://pub.dev/packages/flutter_just_toast)
* [oktoast](https://pub.dev/packages/oktoast)

[pub.devでtoastで検索する](https://pub.dev/flutter/packages?q=toast)と上位に上記4種類が出てくる。
flutter_just_toastはもう半年以上更新がないのでやめておいたほうが良い。
手軽に使えるのはtoast/fluttertoast、カスタマイズ性が一番高いのはoktoastである。

結論としてoktoastを採用した。

今回は備忘録のために、採用理由と簡単な使い方を記す。

# 採用理由

要件として以下のものがあった。

* 利用できる画面に制限がない
* 画面ごとに出せる
* 連続で表示したかったので、できる限り表示時間を短くしたい
* fontのカスタマイズをしたい

toast/fluttertoastは上2つの要件は満たしているが、

* 表示時間はshort/longの2値からしか選べない
* fontに関しては色、サイズしか選べない

という仕様であるため、採用にはならなかった。
逆に言うとシンプルにtoastを実装したいならtoast/fluttertoastの方が良いだろう。

# 使い方(fluttertoast vs oktoast)

各How to Useより抜粋

## fluttertoast

```dart
import 'package:fluttertoast/fluttertoast.dart';

class _okToastExampleState extends State<okToastExample> {
  @override
  void initState() {
    super.initState();
  }

  showToast() {
    Fluttertoast.showToast(
      msg: "This is Center Short Toast",
      toastLength: Toast.LENGTH_SHORT,
      gravity: ToastGravity.CENTER,
      timeInSecForIos: 1,
      backgroundColor: Colors.red,
      textColor: Colors.white,
      fontSize: 16.0
    );
  }

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      child: Text('Tap!!!'),
      onTap: () {
        showToast();
      },
    );
  }
}
```

これだけで呼び出せるため、シーンを選ばず大変利用しやすい。
toastの方はcontextなども引数に含めないと行けないので、思い付かないが利用シーンを制限されることもあるかもしれない。

## oktoast

```dart
class _okToastExampleState extends State<okToastExample> {
  @override
  void initState() {
    super.initState();
  }

  showOkToast() {
    showToast(
      'oktoast',
      duration: Duration(seconds: 1),
      position: ToastPosition.bottom,
      backgroundColor: Colors.black.withOpacity(0.5),
      radius: 13.0,
      textStyle: TextStyle(
        fontSize: 16.0,
        color: Colors.white,
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return OKToast( //OKToastで囲う
      child: GestureDetector(
        child: Text('Tap!!!'),
        onTap: () {
          showOkToast();
        },
      ),
    );
  }
}
```

oktoastもシンプルにはかけるが、OKToastのwidgetで囲わなくてはならない。
Exampleには"wrap your app with OKToast"とあってMaterialApp全体を囲っているが、個別に囲っても問題ないし、他の複数のwidgetをラップしても問題なく動作する。
fontや表示時間などをカスタマイズしたいときはこれ一択なのでぜひ利用してみてほしい。


# まとめ

* サクッと入れるだけならfluttertoast
* カスタマイズしたいならoktoast
【UiPath】リモートデスクトップ接続の自動化

# 概要
リモートデスクトップ接続の作業を自動化する場合、接続先の画面は基本的には画像認識しかできない。
また、リモートデスクトップ接続の画面は最大化してしまうとうまくロボットが動かないので、サイズを指定して小さい画面にした方が良い。

# rdpファイルを使用する方法
リモートデスクトップ接続するには、rdpファイルを作成しておくと便利。そのrdpファイルを作成する手順を以下に示す。

## rdpファイルの準備
「リモートデスクトップ接続」を起動し、「オプションの表示」を押す。
「画面」タブを開き、スライダーを左に引っ張り、接続時の画面が最大化されないようにする。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/1c6f303b-2773-d2c0-e398-4fba18d48b38.png)

「ローカルリソース」タブの「プリンター」と「クリップボード」にチェックを入れておくと、
接続元に設定されているプリンターで印刷が可能になり、接続元と接続先でクリップボードを共有できるようになる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/410127a0-203e-c3f3-8f19-53d3cd0519be.png)

「全般」タブに戻り、接続先のコンピュータ名とユーザー名を入力する。「資格情報を保存できるようにする」にチェックを入れておくと、接続するたびに資格情報を入力しなくて済むので便利(1回目の接続時には資格情報を確認される)。
最後に「名前を付けて保存」を押し、rdpファイルを保存する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/b83b86a3-8e2f-6756-03d2-17b042ffeca2.png)

## ロボットからのrdpファイルの使用
「プロセスを開始」で直接rdpファイルを指定する。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/374128b8-a72f-8429-57e5-9570b25aa02e.png)

ロボットを実行する前に、一度手動でリモート接続しておくと良い。
接続先によっては下記のような警告画面が出ることがあるが、警告を今後表示させないようにすることができるので、ロボットの手間が減る。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/5f4fa70a-3bbc-6408-cb4d-71d558061bbe.png)

# 接続先での作業の自動化
先に書いたように、リモート接続の画面は、基本的には画像認識しかできない。
そのため、ショートカットキーによる操作や、接続先にbatファイルなどを作っておくなどして、なるべく画面に頼らない操作を心がけると良さそう。

# Windowsリモートデスクトップ接続 拡張機能
リモート接続先もUIを要素認識出来る機能がある。ただし、ライセンス所持者でないと使用できないと思われる。

UiPath Studioに、上記拡張機能をインストールできる。
スタート画面 → ツール → Windowsリモートデスクトップ接続 拡張機能 を選ぶとインストールされる。
![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424975/84086765-3f90-4c6d-f378-d47d95365662.png)

加えて、リモート側にも「UiPath Remote Runtime」というツールのインストールが必要。
https://studio.uipath.com/lang-ja/docs/installing-the-uipath-remote-runtime
インストーラは、UiPathサポートチームへ連絡の上入手するように、と書かれている。
ライセンス購入者であれば、無償で提供されるとのこと。
PIE環境下でアセンブリからグローバル変数を扱う

PIEにおいてはアドレスは相対的に指定する必要があります。
つまりいままでの `mov rax, offset gvar` といった絶対的な指定はできません。
こういったコードをアセンブルするには gcc に対して -no-pie オプションを渡す必要があります。

相対的な指定方法ですが実際にgccの出力を見るのが手っ取り早いです。
例えば以下のようなコードで

```
// main.c
int gvar = 1;

int main() {
    int *p = &gvar;
    return *p;
}
```

グローバル変数 gvar のアドレスをraxレジスタにロードする場合

AT&T記法なら`gcc main.c -O0 -S`

```
leaq    gvar(%rip), %rax
```

Intel記法なら`gcc main.c -O0 -S -masm=intel`

```
lea rax, gvar[rip]
```

つまり rip からの相対的な位置で指定します。
変数のラベルを指定するだけで具体的な値はアセンブラやリンカにおまかせできます。

gvar 変数は data セクションなどに確保されます。

```
	.data
gvar:
	.long	1
```
firestoreで実現するランダムマッチングを考えてみた（未実装）

考えてみただけなのですが、もしご意見等あればコメントいただけると幸いです！自分も正解がよくわからないので議論したいです！

## 前提
- 1：1でランダムマッチングして対戦等を行いたい
- ピーク時は結構リクエストが跳ねて、秒間1000リクエストとかでも対応したい
- クライアントはネイティブアプリ

## テーブル
- waitingUsers: Collection
  - documentID
     - userIDにする
  - status: string
     - 待機状況
     - WAITING, MATCHED
  - updatedAt: timestamp
     - 待機ユーザーの足切り用
  - roomID?: string
     - 参加が決まった部屋のID
- rooms
  - userIDs: array
     - 参加するユーザーのID
  - participants: Collection
     - 参加するクライアント一覧。参加するユーザーが明示的に書き込む。

## シーケンス
~~本当はシーケンス図にしたかったんですが面倒だったので一旦箇条書きです、すみません。~~
PlantUMLでシーケンス図書きました！とりあえず箇条書きも残しておきます。

![ランダムマッチング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74853/8703523e-008d-f625-a806-d86cfd722115.png)

1. マッチングを望むユーザーは `waitingUsers` に `status = WAITING and updatedAt = now` でドキュメントを作成または更新
2. ユーザーは自身のドキュメントを監視（タイムアウトの設定は必要）
3. `waitingUsers` の更新をフックしたCloudFunctionsが起動する（なんかの制限引っかかるか…？）
  1. waitingUsersから `status == WAITING and updatedAt > 1分前(適当)` のデータを取得（limitいる気がする）
  2. ランダムな1件を取得してくる
  3. transactionで下記を実行
     1. 取得したデータと更新をフックしたデータをgetAllする
     2. 各データが `status == WAITING` であることをチェック
         1. だめだったら3−1.からやりなおし
     3. それぞれ `status = MATCHED, roomID = uniqueID` で更新
     4. /rooms/uniqueIDの `userIDs = [userID1, userID2]` で作成
4. マッチングしたユーザーはドキュメントの変更を受け取って、roomIDを取得する
5. roomを取得して、room.participantsを監視
6. room.participantsに自身のユーザー情報を書き込む
7. participantsが2名になったら対戦スタート

## 懸念点
1. CloudFunctionsの呼び出し数上限とかに引っかからないか？
2. ちゃんと10人がWAITINGだったら5組できるのか（理論上は大丈夫なはずだが…）
Firebase HostingでSPAのリロード時にPage Not Foundになる時の対策

Firebase Hostingにcreated-react-appで作成したSPAをホストしたところ、リロード時にPage Not Foundになってしまったので対策をまとめます。

### 追記
`$ firebase init`時に画像のようにSPAのURLの挙動を設定できる設問があるようです。
「Configure as a single-page app...」 の部分です。
<img width="560" alt="スクリーンショット 2019-07-22 1.23.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420203/24f98f2c-6beb-a62d-a1f2-cbf5d18631a7.png">
これを`y` + `Enter`で`firebase.json`ルールを追加してくれるようです。

# Firebase Hosting のデフォルトの挙動
Firebase Hosting はデフォルトでは静的なindex.htmlファイルを読みに行くようです。Reactではreact-routerなどのルーティングライブラリを利用するので実際にはindex.htmlはありません。なのでルートディレクトリ以外でリロードをするとこのように４０４を返してきます。

<img width="411" alt="スクリーンショット 2019-07-20 19.03.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420203/20097aa8-9129-f9ef-8c7c-fcc82b0b7617.png">

# 対策
`firebase.json`ファイルの`hosthing`プロパティに`rewrites`ルールを追加して、公開ディレクトリ配下のアクセスを全てルートのindex.htmlを読みに行くようにします。

### Before
```json:firebase.json
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "build",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
  }
}
```
### After
```json:firebase.json
{
  "firestore": {
    "rules": "firestore.rules",
    "indexes": "firestore.indexes.json"
  },
  "hosting": {
    "public": "build",
    "ignore": ["firebase.json", "**/.*", "**/node_modules/**"],
    "rewrites": [
      {
        "source": "/public/**",
        "destination": "/public.html"
      },
      {
        "source": "**",
        "destination": "/index.html"
      }
    ]
  }
}
```

これで404になることはなくなました。

# 参考

[Page not found when reloading Angular page on Firebase](https://stackoverflow.com/questions/36554897/page-not-found-when-reloading-angular-page-on-firebase/52347687)
Cloud Composer 向けの DAG ファイルの Syntax チェックをローカルで実行する

いちいち `gcloud composer environments storage dags import` して web ui から確認していると日が暮れるので、手元で syntax チェックぐらいはしてから動作確認できるようにしてみた。


## Docker イメージのビルド

Airflow の docker イメージは [https://github.com/puckel/docker-airflow](https://github.com/puckel/docker-airflow) にあった。

Composer 向けに google クライアントなどをいれる必要があったのでカスタム用の Dockerfile を自分で用意した。

```Dockerfile:Dockerfile
# ref. https://github.com/puckel/docker-airflow

FROM puckel/docker-airflow:latest

USER root

# Install additional packages required by composer
RUN pip install google-cloud-bigquery \
      google-cloud-storage \
      google-cloud-container \
      google-api-python-client \
      grpcio \
      kubernetes \
      pandas_gbq

# Install additional packages required by us
RUN pip install "slackclient<2.0.0"

USER airflow
```

```
docker build --rm -t docker-airflow-custom .
```

## Airflow の起動

単純に起動してみると `GOOGLE_DEFAULT_APPLICATIONS` や `GOOGLE_CLOUD_PROJECT` が欲しいと言われるので、その辺りを設定しつつ、`dags` ファイルをおいているディレクトリをマウントして airflow を起動。

Web UI が立ち上がる（が、そこは本質ではなく、DBの初期化をした状態で置いておきたいだけ）

```
docker run -p 8080:8080 -e GOOGLE_CLOUD_PROJECT=<YOUR_PROJECT> \
  -v $HOME/.config:/usr/local/airflow/.config \
  -v <YOUR_DAGS_DIR>:/usr/local/airflow/dags \
  --rm -it docker-airflow-custom
```

FYI: デーモンとして起動したい場合は `-d` オプションをつけてください。
FYI: Airflow サーバ起動時にも１発 Syntax チェックは走ります。

## DAGのSyntaxチェック

あとは起動したコンテナに入って `/entrypoint.sh python` で dag の python スクリプトを叩けば Syntax チェックになる。

```
docker exec -it $(docker ps | grep docker-airflow-custom | awk '{print $1}') \
  /entrypoint.sh python -W ignore::UserWarning dags/<YOUR_DAG.py>
```
基本的なRegex(正規表現)について

Regexの基本を勉強したので、忘れないように自分にとって分かりやすく箇条書きでまとめました。

# Regexとは
Regex(正規表現)とは、いくつかの文字列をひとつのそれで表現する方法のことです。
この方法を用いることで、膨大な情報量があるネットの世界から簡単に見つけたい文字列を探し出すことができるようになります。


# いろいろなメタ文字の使い方
Regexでは多くの特殊文字を使用していきますが、それらを「メタ文字」と呼んでいます。
ひとつずつ見ていきましょう。

注意：長いので「検索ワード」を「ワード」、「検索結果」を「結果」と表現しています。

# 「 ▪️ 」
- なんでもいい一文字を検索する際に使用
- 例：　ワード「君は▪️です。」 → 結果「君は鬼です。」「君は神です。」
- 「\▪️」で、メタ文字自体を検索可能


# 「 ^ 」
- 行の先頭にのみ存在する文字列を検索
- 例：　ワード「^こんにちは」 → 結果「こんにちは、世界」「こんにちはは日本語です。」
- 「^^」で文字自体を検索可能


# 「 $ 」
- 行の末尾にのみ存在する文字列を検索
- 例：　ワード「こんにちは$」 → 結果「みなさんこんにちは」「やっほー、こんにちは」
- 「$$」で文字自体を検索可能

# 「 * 」
- 直前の文字が０個以上連続する文字列を検索
- 例：　ワード「ばー*か」 → 結果「ばか」「ばーーーーか」


# 「 + 」
- 直前の文字が１個以上連続する文字列を検索
- 例：　ワード「ばー+か」 → 結果「ばーーーーか」

# 「 ? 」
- 直前の文字が０個または１個である文字列を検索
- 例　：ワード「ばー?か」 → 結果「ばか」「ばーか」
- スペースの有無が不明な時によく利用される

# 「 | 」
- いずれかの文字列を検索
- 例：　ワード「Python|Ruby|HTML」 → 結果「Python」「Ruby」「HTML」のいずれかの文字列が存在する文
    
# 「 [ ] 」
- 指定した文字のどれかで検索
- 例：　ワード「今日の天気は[晴雨雪]です。」 → 結果「今日の天気は晴です。」「今日の天気は雨です。」「今日の天気は雪です。」
- 連続したアルファベットや数字を入れたい場合、[A-Z][0-9]と書ける


# 「 ( ) 」
- グループ化する
- 例1：　ワード「(きら)+ーん」 → 結果「きらきらきらーん」
- 例2：　ワード「(僕｜私)は嬉しい。」 → 結果「僕は嬉しい。」「私は嬉しい。」
 
# メタ文字を組み合わせてみる
組み合わせてより複雑な検索をかけることもできます。

# 「 ^$ 」
- 行の先頭かつ末尾にのみ存在する文字列を検索
- 例：　ワード「^こんにちは$」 → 結果「こんにちは」

# 「 ▪️* 」
- なんでもいい文字の連続
- 例：　ワード「あなたが好き▪️*。」 → 結果「あなたが好き。」「あなたが好きかもしれない。」

# まとめ
すごい機能であるという実感はまだわきませんが、とりあえず便利そうだということは理解しました。
新強震モニタから地震情報を掻っ攫う方法

# この記事について
個人メモです。
この記事の情報を利用したことにより、損害が発生しても筆者は一切の責任を負えませんのでご注意ください！
あくまでも自己責任でお願い致します🙏

## リクエスト先
> 2019-10-03 追記 : URLに変更がありましたので更新しました。

`GET http://www.kmoni.bosai.go.jp/webservice/hypo/eew/${timestamp}.json`
`${timestamp}`部分は、`YYYYMMDDhhmmss`フォーマットです。

> 例: 2019年7月20日 18時01分53秒 → `20190720180153`

### リクエスト時の注意
**未来の時刻でリクエストしても、404エラーが返らないので注意。**
余裕を持って、現在時刻の2秒前を取得したほうが良さそうです。

## レスポンス
変な使い方をしなければ、ほとんど200 OKが返ってきます。
ボディ部分はJSON形式です。

### 生JSON
```json
{
  "result": {
    "status": "success",
    "message": "データがありません",
    "is_auth": true
  },
  "report_time": "",
  "region_code": "",
  "request_time": "20190720175242",
  "region_name": "",
  "longitude": "",
  "is_cancel": "",
  "depth": "",
  "calcintensity": "",
  "is_final": "",
  "is_training": "",
  "latitude": "",
  "origin_time": "",
  "security": {
    "realm": "/webservice/hypo/eew/",
    "hash": "5ca8b8104e01ceef0f061ad597606cbd87b492db"
  },
  "magunitude": "",
  "report_num": "",
  "request_hypo_type": "eew",
  "report_id": ""
}
```

## レスポンスデータの説明

型はJavaScript準拠です。
表を見やすくするため、順番を変更しています。

### よく使うであろうデータ

| 要素名 |  型 | 説明･備考 | 例 |
|---|---|---| --- |
|`result.message`|string|地震発生時は空文字列になり、それ以外のときは`"データがありません"`となる。|`""`|
|`report_time`|string|情報更新時刻(`YYYY/MM/DD hh:mm:dd`形式)|`"2019/07/15 01:30:59"`|
|`report_id`|string|地震ID|`"20190715013049"`|
|`origin_time`|string|地震発生時刻|`"20190715013043"`|
|`report_num`|string|第n報|`"2"`|
|`region_name`|string|震源地|`"千葉県北東部"`|
|`latitude`|string|緯度(北緯)|`"35.7"`|
|`longitude`|string|経度(東経)|`"140.7"`|
|`depth`|string|震源の深さ|`"20km"`|
|`calcintensity`|string|最大震度|`"5弱"`|
|`magunitude`|string|マグニチュード|`"3.8"`|
|`is_final`|boolean|最終報か否か|`false`|
|`is_cancel`|boolean|キャンセル報か否か(未利用?)|`false`|
|`is_training`|boolean|訓練報か否か|`false`|

### その他
使い所が不明なデータを記載しています。

| 要素名 | 説明･備考 |
|---|---|---|
|`result.status`|リクエスト結果、常に`"success"`|
|`result.is_auth`|不明 常に`true`|
|`region_code`|不明 常に`""`|
|`request_time`|リクエスト時に指定した時刻と同じ|
|`security.realm`|不明 常に`"/webservice/hypo/eew/"`|
|`security.hash`|不明 恐らくチェックサム？|
|`request_hypo_type`|不明 常に`"eew"`|
|`alertflg`|地震発生時のみに出現 `予報` `警報` のみ観測。[気象庁のページに解説あり](https://www.data.jma.go.jp/svd/eew/data/nc/shikumi/shousai.html#2) |

## サンプルコード(まだ)

## 関連リンク
- NHK地震情報の非公式APIドキュメント → [NHKの地震情報を掻っ攫う方法](https://qiita.com/ot1r/items/aff63d49273ef8be5993)

##追記
GETリクエスト時の時間は[http://www.kmoni.bosai.go.jp/webservice/server/pros/latest.json](http://www.kmoni.bosai.go.jp/webservice/server/pros/latest.json)から受けたデータをアレコレして地震のjsonをリクエストしている。詳しくは[http://www.kmoni.bosai.go.jp/kyoshin_monitor/static/eqmonitor/memberview/js/EqMonitorCtrl.js](http://www.kmoni.bosai.go.jp/kyoshin_monitor/static/eqmonitor/memberview/js/EqMonitorCtrl.js)を見ればわかると思う
Pythonで引数と戻り値を理解する

##はじめに

[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしている坂口です。
今週はProgateでPythonを学習したので、Pythonを使って引数と戻り値が何かをアウトプットします。

##引数

引数は、関数のすぐ後ろの（）に入れる値で、関数に渡される情報です。
例えで言うと、レストランで行う料理のオーダーのようなものです。
また、引数は1つとは限りません。必要であれば、2つでも3つでも設定することができます。
また、因数には仮引数と実引数が存在します。

##コード例

```Python:
def restaurant(menu):
    if (menu == "curry"):
        print("curry")
    elif(menu == "spaghetti"):
        print("spaghetti")
    else:
        print("それ以外")
        
menu("curry")
```

結果は、curryが表示されます。
このコードでは、menuが仮引数、curryとspaghettiが実引数です。

##戻り値

戻り値の定義は、関数から出力される値です。
レストランの例えで言うと、オーダーを受けて出てきた料理のようなものです。
returnを利用すると、戻り値を使って関数から値を返すことができます。

##コード例

```Python:
def price(a,b):
    c = a + b
    return c
 
print(price(600,700))
```

結果は1300と表示されます。
もしもこのコードでreturn cがなければ、結果はNoneになります。
a + bの計算をしても、returnを使って戻り値を返してやらなかったために、この関数からは何も生まれていないということを表しています。
計算結果を出すには、return cを用いて戻り値を返すことが必要だということです。

##まとめ
今回はPythonを使って、引数と戻り値を説明しました。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください。よろしくお願いいたします。
MacでGazeboを動かす

# 目的
MacでGazeboを動かした際の備忘録です

# 準備

公式サイトのインストール手順通りにインストールします。
Mac以外は対応する手順を参照すれば良さそうです。

> [Install Gazebo on Mac (using homebrew)](http://gazebosim.org/tutorials?tut=install_on_mac&cat=install)

```
$ curl -ssL http://get.gazebosim.org | sh
$ gazebo
```

gazeboが起動すればOK

# 参考
[Install Gazebo on Mac (using homebrew)](http://gazebosim.org/tutorials?tut=install_on_mac&cat=install)
[Gazeboの今更な紹介とMac OSX (10.10.4) にGazebo (Version 6) をインストール](http://ros-robot.blogspot.com/2015/08/gazebomac-osx-10104-gazebo-version-6.html)
[how to run gazebo docker container in Mac](https://answers.ros.org/question/316092/how-to-run-gazebo-docker-container-in-mac/)
なるはや Vue SPA入門：ライフサイクル

Vue CLI3 で作成した SPA（Single Page Application）プロジェクト上で、段階的に Vue.js を学んで行きましょう。

[目次はこちら](https://qiita.com/tsubo/items/24df49ef2f1ba87984d1)

今回はライフサイクル編です。

## 前提事項

[Vuex編](https://qiita.com/tsubo/items/af3886cdbeb6781e7d52) が完了していること。 

## ライフサイクル

![lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14476/f8635ee9-d5b8-c195-6c3a-6e45c32e3264.png)

上記が Vue が生成されてから破棄されるまでの流れ図になります。赤い四角がライフサイクルフックと呼ばれる関数です。

ライフサイクルの主なイベントは以下の４つです

1. Vue インスタンスの作成
 - beforeCreate: インスタンス作成前
 - created: インスタンス作成後
2. DOM へのマウント
 - beforeMount: DOM へのマウント前
 - mounted: DOM へのマウント後
3. 画面、データの更新
 - beforeUpdate: 更新前
 - updated: 更新後
4. Vue インスタンスの破棄
 - beforeDestroy: インスタンス破棄前
 - destroyed: インスタンス破棄後

## ライフサイクルフック

前回作成した `Counter.vue` にライフサイクルフックを追加してみます。

```js:Counter.vue
export default {
  beforeCreate() {
    console.log("beforeCreate");
  },
  created() {
    console.log("created");
  },
  beforeMount() {
    console.log("beforeMount");
  },
  mounted() {
    console.log("mounted");
  },
  beforeUpdate() {
    console.log("beforeUpdate");
  },
  updated() {
    console.log("updated");
  },
  beforeDestroy() {
    console.log("beforeDestroy");
  },
  destroyed() {
    console.log("destroyed");
  },
  //...
}
```

## 動作確認

![lifecycle.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14476/13bfe1d1-7d29-5d8d-64b2-239a836fe74d.png)

Counter ページを開いて、Console ログを確認してみましょう。`+` ボタン、`-` ボタンを押した時のログも確認してみてください。

## 次回

[API コール](https://qiita.com/tsubo/items/d741b52e5fea4aba2147)
Google Colaboratoryで動画処理(初級編)

Google Colaboratoryでは、`ffmpeg`や`PIL(Pillow)`、Google Driveの機能を利用できるので、研究用の動画解析/編集を簡単に実行できる。ローカルマシンのマシンパワーを消費することもないし、他の人と共同作業したり出力結果を共有することも可能で、なかなかに良い。

# 事前準備
## 動画ファイルをGoogle Driveにアップロードする
動画ファイルをGoogle Driveにアップロードする。今回は「マイドライブ/videoexp/SampleVideo_1280x720_5mb.mp4」というファイル名でアップロードした。

<img width="994" alt="Screen Shot 2019-07-20 at 17.27.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14097/8950c2fb-db77-99b6-0fae-eb19cd5351c6.png">

今回の動画ファイルは[Sample Videos](https://sample-videos.com)から拝借した。

# Google Driveをマウントする
```
from google.colab import drive
drive.mount('/content/gdrive')
```

# ffmpegを使って、画像に変換する
ffmpegを使って、動画ファイルから画像を抽出する。抽出の際にはフレームレート(fps)を指定する。fpsは目的に応じて調整する。ここでは1fps(1秒に1フレーム)を指定している。fpsが大きくなればなるほど出力結果はスムーズになるが、その分処理の時間とファイルサイズが増大する。

```python
import os

src_img_dir = "/content/gdrive/My Drive/videoexp/src"

if not os.path.exists(src_img_dir):
    os.makedirs(src_img_dir)

!ffmpeg -i "/content/gdrive/My Drive/videoexp/SampleVideo_1280x720_5mb.mp4" -vf fps=1 "$src_img_dir/%04d.jpg"
```

抽出された画像を`src`ディレクトリに保存するようにしている。Google Driveでsrcディレクトリを開けば、抽出された画像の内容を確認することができる。

<img width="2152" alt="Screen Shot 2019-07-20 at 17.37.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14097/94824205-a868-6c28-9df3-70a5f012bf6b.png">

# 抽出された画像の一覧を取得する
```python 
import glob

src_files = glob.glob("{}/*.jpg".format(src_img_dir))
src_files.sort()

print(len(src_files), "image files")
```

# 一枚ずつ画像処理を行う
得られた各フレームの画像に対して、一枚ずつ処理をしていく。
ここではPILを使って「画像の右上にフレーム番号を書く」という処理を実行している。

```python 
from PIL import Image
from PIL import ImageDraw

dst_img_dir = "/content/gdrive/My Drive/videoexp/dst"
if not os.path.exists(dst_img_dir):
    os.makedirs(dst_img_dir)

for i, file in enumerate(src_files):
  im = Image.open(file)
  draw = ImageDraw.Draw(im)
  draw.text((10,10), "{0:04d}".format(i), fill="#ff0")
  dst_file = "{dir}/{index:04d}.jpg".format(dir=dst_img_dir,index=i)
  im.save(dst_file)
```

処理後の画像はdstディレクトリに出力されている。動画に変換する前にここで処理内容を確認できる。

<img width="1876" alt="Screen Shot 2019-07-20 at 18.06.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14097/898b3a04-9051-2cfb-b89d-c9cf100d23b8.png">


# 処理後の画像から動画を作る
最後に処理後の画像を動画に戻す。
ffmpegを使って、処理後の画像が納められているディレクトリ(dst)にある画像から動画ファイル(out.mp4)を作成する。
この際のフレームレートは、動画から画像を抽出した際に用いたフレームレートと一致させる必要がある。

```
!ffmpeg -framerate 1 -i "$dst_img_dir/%04d.jpg" "/content/gdrive/My Drive/videoexp/out.mp4"
```
bootstrapのNavbarのハンバーガーメニューが閉じない[原因はTurbolinks]

# 環境
rails 5.2
# 問題
navbarのハンバーガーメニューを開き、リンクを踏んだ後に、展開されたメニューが閉じずに残っている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348384/8156274a-6a31-23b1-46b8-2a09ec9a4fdb.png)

この状態でどの展開されたメニュー以外の場所をクリックしてもメニューが収納されない。
リロードしたときにのみ、メニューが収納される。

# 解決策
悪さをしているTurbolinksを無効化する。

```
<%= link_to "メニュー1", "#", data: {"turbolinks" => false}, class: "nav-link" %>
```

# 原因
Rails4からデフォルトで導入されているturbolinksが原因。
https://qiita.com/ryichiki/items/157b0f4288ce605de2a2
こちらの記事が参考になる（というか今回の問題に関してほぼ答えを言っているのだが）

簡単に言うと、
headタグの内のcss,jsが、リンク前と後で同じファイルであれば再利用して、body内のHTMLだけを置き換えるという処理。これにより、画面の表示を高速化する。

# しかし疑問が...
ハンバーガーメニューが展開される仕組みは、ハンバーガーアイコンをクリックしたときに、nav-openというclassがhtmlタグに付与されるから。これは、JQueryによって処理されている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348384/58262ff0-88c8-0355-1d7c-ab94796676a6.png)

世の中の多くのturbolinksでviewが動かないんです！という記事は、「TurbolinksによってjQueryのreadyが発火しないから」という原因に帰着させているものが多い。しかし今回は、jQueryが動かないことが原因ではない。
原因は、
**ページ遷移したあとも、nav-open classがhtmlタグに付与され続けるから。**

これは、turbolinksで更新されるのがbodyタグの中のHTMLであることに由来している。
今回nav-open classがついているのは最上位のhtmlタグであるため更新されずに残り続けてしまっている。
【Git】push declined due to email privacy restrictionsへの対処法

# 概要
GitHubで、Push時にメールアドレスで引っかかってエラーが発生した。

## エラー文
```
$ git push origin master
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (8/8), done.
Writing objects: 100% (9/9), 1.62 KiB | 1.62 MiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
remote: Resolving deltas: 100% (1/1), done.
remote: error: GH007: Your push would publish a private email address.
remote: You can make your email public or disable this protection by visiting:
remote: http://github.com/settings/emails
To github.com:~~~/~~~.git
 ! [remote rejected] master -> master (push declined due to email privacy restrictions)
```

# エラーの内容
Eメールのプライバシー制限に引っかかってPushが拒否された（直訳）

# 原因と解決策
gitを使用するコミットユーザーのEmailに、Githubで非公開にしているメールアドレスを指定していたため。
Settings > Emails > Keep my email addresses private にチェックが入っていると、Githubでメールアドレスが非公開になっている。

その場合は、コミットユーザーのEmailに、代わりのものを使用する。
Settings > Emails > Primary email address の部分に、
[数字]+[ユーザー名]@users.noreply.github.com というものがあるので、それを指定してあげれば良い。

```
$ git config --global user.email [数字]+[ユーザー名]@users.noreply.github.com
```

# 追記
（19/07/20 22:10追記）
初期値では、「Block command line pushes that expose my email」がオフになっているようです。
これをオフにしている状態であれば、プライベートのメールアドレスもコミットユーザーのメールアドレスとしてPushできます。
（Pushはできますが警告が表示されます）
ご教授いただきありがとうございます！
仙台CTF2018 For.2 実行履歴の調査 100

#問題

http://ctf.sectanlab.jp/2018/challenges

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/453654e0-0e1d-d198-8f3d-44644926d043.png)

#解いてみた

ファイルをダウンロードして解凍します。

Prefetchフォルダが入ってました。

PC-Cleaner.exeのプリフェッチを見ればいいので確認したところPC-CLEANER.EXE-0FC5C951.pfというファイルを発見しました。

WinPrefetchViewを使って内容を確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/da9fa45d-35d0-4d1b-8298-8457fe3a3a38.png)

実行時間が書かれているのでこれが答えです。
仙台CTF2018 For.1 ダウンロード元URLの特定 100

#問題

http://ctf.sectanlab.jp/2018/challenges

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/23f52ccf-071e-cf62-352b-e7c44fc8a5dd.png)

#解いてみた

ZIPファイルをダウンロードして中身をみるとexeファイルが入ってました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/7203b3bf-230a-cf65-4027-169a73b6d200.png)

bintextを使って中身のテキストを見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/ce635ddb-1cbd-a158-924f-905082cd31a7.png)

exeファイルのURLが入ってたんで、これを入力すると正解でした。

ちょっと後ろに「HTTP/1.0 200 OK」とか書かれているものの、なんでこれがダウンロード元なのかわかりませんでした。
ここからダウンロードしたというのはどうやったらわかるんでしょう？
STM32マイコン体験セミナー（グラフィック描画編）TouchGFX Designer 2019年5月13日実施

TouchGFX DesignerのハンズオンはSTM32F746DiscoveryKitを使用して行われました。(2019年5月13日）
![IMG_9860.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/501d3daa-4d63-47ae-b084-521936475578.jpeg)

過去にSTemWinを使用したハンズオンが行われておりました。
https://www.stmcu.jp/design/document/training-materials_j/51206/

今回は約2時間でここまで作る事が可能です。
そして、コードの記述一切無しでGUIが完成します。
AndroidStudioやXcodeを使っている人は容易に使いこなせると思います。
ハンズオンでは、ここからIARを使ったコードの追加等を行います。
(残念ながら32KBを超えてしまうので評価版か正式ライセンス必須です）
![TouchGFX.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/ab68e6a7-0b33-d74c-b4b2-16edef63f98b.jpeg)
![IMG_9861.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/d11826ce-8627-854d-c336-632f199c20f5.jpeg)
こちらのYoutubeも必見です。
https://www.youtube.com/channel/UCPmAQbY9KbHqdQ_GwUGg1bA
STM32マイコン体験セミナー（高性能マイコン編）STM32H755ZI　DualCore STM32H7　2019年7月17日

・STM32マイコン体験セミナー（高性能マイコン編）が行われました(7月17日）

早速デュアルコアのSTM32H755ZIを使ったセミナーです。
![IMG_0140.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/58cfe3c3-57b2-6140-95ea-2ba09333847b.jpeg)

![IMG_0137.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/387b770e-1041-0c8b-fee2-6f8981a4ce77.jpeg)

NUCLEO-H755ZI-Q
https://www.st.com/content/st_com/ja/products/evaluation-tools/product-evaluation-tools/mcu-mpu-eval-tools/stm32-mcu-mpu-eval-tools/stm32-nucleo-boards/nucleo-h755zi-q.html

CPUのコア選択が出てきますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b8b70413-c23e-c1bb-7185-5bc0d96864c4.png)

デュアルコアを稼動させるにはIAR　Ewarmの最新版でないといけません。
エラーが出てしまいます。
CubeIDEの対応は2019年年末予定(予定）

無事デュアルコアで実行
![IMG_0139.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/386357e5-5c84-832a-7c02-125ef18bad70.jpeg)

ここを直さないと文鎮化します(まもなく修正版が出るので今だけ必要だと思います）
荒木さんのPDFをそのまま引用します。
• 重要SystemClock_configの以下の箇所を修正します

```
/** Supply configuration update enable
*/
//HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
HAL_PWREx_ConfigSupply(PWR_DIRECT_SMPS_SUPPLY);
/** Configure the main internal regulator output voltage
*/
__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);

```
• STM32CubeMXのバグで生成しなおすたびに修正の必要があります

(C)STMicro　荒木さん
![IMG_0141.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/285344/b0d71618-baea-c596-4581-16c84e07bb3b.jpeg)
[Swift] 辛くならないイニシャライズ

# プロパティをそれぞれ代入するのは辛い

辛いイニシャライズがあります。

例えば

```swift
class Person {
    var name: String?
    var sex: String?
    init() {}
}

let person = Person()
person.name = "alex"
person.sex = "male"
```

最初に`Person`インスタンスを作ってプロパティを代入していくパターン。プロパティに初期値（ここではnil)を設定してあとで代入します。
例では`name`, `sex` プロパティをそれぞれ代入していますがすべての値を確実に代入するかは開発者の責任になってしまいます。

## 解決策
すべてのプロパティをセットするにはイニシャライザを作りましょう

```swift
class Person {
    let name: String // not optional!
    let sex: String // not optional!
    init(name: String, sex: String) {
        self.name = name
        self.sex = sex
    }
}

let person = Person(name: "alex", sex: "male")

```

# 値があとから設定されるとき

でもすべてのほしい値が一度に手に入るとは限らないですよね。
ある人物が病院の受付をする場合を想定します。
`name`と`sex`の値は事前にわかっていますが、受付番号は病院に行かなければ受け取れません。

```swift
class Person {
    let name: String
    let sex: String
　　 var orderId: Int?
    init(name: String, sex: String) {
        self.name = name
        self.sex = sex
    }
}
let person = Person(name: "alex", sex: "male")
person.orderId = Hosptal.order(person) // あとから設定
```

## 解決策

新しい型をつくりましょう。

```swift
class Person {
    let name: String
    let sex: String
    init(name: String, sex: String) {
        self.name = name
        self.sex = sex
    }
}

class Patient {
   let name: String
   let sex: String
   let orderId: Int
    init(name: String, sex: String, orderId: Int) {
        self.name = name
        self.sex = sex
        self.orderId = orderId
    }
}

let person = Person(name: "alex", sex: "male")
let patient = Patient(name: person.name, sex: person.sex, Hosptal.order(person)) 

```

以上です。
メモ：sikuliXで資料の印刷自動化（２）

# やったこと
仕事で複数種類セットの資料を複数人分印刷することがとても多いので、印刷作業を自動化。↓のような資料を20～30人分印刷したりとか。。。ペーパーレス化はまだですか。。。地球環境が。。。
資料1.pdf
資料2.docx
資料3.pptx
資料4.pptx
資料5.docx
参考資料1.pptx

#メイン
フォルダの中に印刷したい資料一式を保存する。p_numとpathを適宜設定。
現状は、全部のファイルを両面、ホッチキス２箇所にしか設定できない。
CSVからファイル名や各印刷設定項目読み込んで印刷したかったけど、やたら文字コードでエラーが出るので、また今度やることにした。

```python:print.py
# coding: utf-8
import csv
import sys
import glob
#pythonのライブラリに、自作のスクリプト（Pptx,Pdf,Docx）を追加する。
sys.path.append(r"C:\Users\namae\Documents\Pptx.sikuli")
sys.path.append(r"C:\Users\namae\Documents\Docx.sikuli")
sys.path.append(r"C:\Users\namae\Documents\Pdf.sikuli")
import Pptx
import Docx
import Pdf

Settings.MoveMouseDelay = 0
p_num = 1#印刷部数
path = r"C:\Users\namae\Desktop\test"
path_list= glob.glob(path + os.sep + "*.*")

#拡張子によって印刷
for f_path in path_list:
    if ".docx" in f_path:
        docx = Docx.Docx()
        docx.print_docu(f_path,p_num)
    elif ".pptx" in f_path:
        pptx = Pptx.Pptx()
        pptx.print_docu(f_path,p_num)
    elif ".pdf" in f_path:
        pdf = Pdf.Pdf()
        pdf.print_docu(f_path,p_num)
    else:
        continue
    

```

#ファイルの種類ごとのクラス
sikuliはスクリプトごとにフォルダが作成され、キャプチャ画像なんかもスクリプトと同一のフォルダに格納される。スクリプトやキャプチャ画像がごっちゃになるので、メインプログラムでは、ファイルの拡張子（pdf,pptx,docx）に対応したスクリプトをインポートするようにした。適当にクラスとして作ってみた。
なぜかprocess.kill()で各ワードやパワポを終了できず（Windows10）、仕方なくGUIの閉じるをクリックする操作を追記している。

```python:Pdf.py
# coding: utf-8
import subprocess
from sikuli import *

class Pdf:#PptxもDocxも同じ
    #パスとセッティングのリストを入力する。
    def print_docu(self,f_path,p_num):
        process = subprocess.Popen([f_path], shell=True)
        #このなかで印刷やら部数やら両面やらをGUIで設定して印刷する手順を記述
```

フォルダ構成（印刷資料一式は↓とは別のフォルダに）

```
.
├── Pdf/
│   └── Pdf.py
├── Pptx/
│   └── Pptx.py
├── Docx/
│   └── Docx.py
└── print/
    └── print.py
```
Flutterの開発環境をMacで作成してみる（エミュレータで動かすところまで）

#はじめに
初めましてmasaです。
Androidのプラットフォームエンジニアをやってます。
最近端末を作る仕事も減ってきたので別の技術に手を出してみようかと思い、目についたFlutterの勉強をしてみました。
本投稿は勉強した内容の備忘録となります。
基本的に下記のインストールガイドに従い進めていきます。
[Flutter MacOS install](https://flutter.dev/docs/get-started/install/macos "Flutter")

#環境
MacBook Pro 2018
macOS Mojave 10.14.5
Xcode 10.2.1
Android Studio 3.4.2

#目次
1.Flutter SDKのインストール
2.Flutter doctorの実行
3.アプリの作成
4.iOSのアプリ起動
5.Androidのアプリ起動

#Flutter SDKのインストール
インストールガイドに従いFlutter SDKのzipを取得し任意の場所に展開します。
その後展開した場所をPATHに追加します。
私の場合は下記を.bashrc等に記載してターミナル起動時にパスが通るようにしてます。

```
export PATH=$PATH:Flutter SDKを展開したディレクトリ/bin
```

下記のコマンドでバージョンが表示されればパスが通っています。

```
$ flutter --version
```

インストールガイドにあるflutter precacheはネットワークが途切れるような環境でないため実行しませんでした。

#Flutter doctorの実行
インストール後はflutter doctorというコマンドを使用し、必要なツールや設定を行なっていきます。
最終的には下記まで設定したところエミュレータでアプリを動かすことはできました。
<img width="851" alt="flutter doctor.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456358/07cc983e-55f7-5230-cd8d-9b3000ffcd4a.png">

iOS toolsは実機でアプリを動かす際に必要なツール類だったので今回は入れてません。
またエディタに関するアドオンも入れてません。

#アプリの作成
任意のディレクトリで下記のコマンドを実行します。
my_appはアプリ名なので任意の名前でも大丈夫です。

```
$ flutter create my_app
```

コマンド実行後はmy_appディレクトリが作成されその中にプロジェクト一式が作成された状態になります。

#iOSのアプリ起動
インストールガイドに従い下記のコマンドを実行します。
Xcodeは一つしか入れてないのでxcode-selectは実行してません。
複数バージョンを入れている方はxcode-selectで使用するXcodeを選択する必要があるようです。

```
$ sudo xcodebuild -license
```

アプリを動かすため下記のコマンドでシミュレータを起動します。

```
$ open -a Simulator
```

シミュレータが起動したら事前に作成したアプリのディレクトリに移動し下記のコマンドを実行します。

```
$ flutter run
```

アプリが起動するとこんな画面が表示され動作確認ができます。
<img width="338" alt="iosエミュレータ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456358/e64d079a-7527-0870-1a51-9b423fe9400b.png">

#Androidのアプリ起動
インストールガイドに従いAndroidのエミュレータを起動します。
私の場合Android Studio->Configure->AVD Managerから起動しました。
エミュレータ起動後はiOSのアプリ起動と同様に下記のコマンドでアプリを動かします。

```
$ flutter run
```

アプリが動作するとこんな画面になります。
<img width="404" alt="Androidエミュレータ.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456358/bc80f107-d8f4-9e33-6855-094f202cef71.png">

ただ、Androidのアプリ起動は安定していないのか一度失敗しました。
その時は数分経っても起動しないためターミナルを再起動し再度flutter runを実行したところアプリが起動することを確認できました。
また、接続後も下記のようなメッセージが表示されエミュレータとの接続が切れてしまうことがありました。
`lost connection to device. flutter`

#終わりに
とりあえずエミュレータでのHello worldまでやってみました。
Flutter doctorのコマンドで必要な設定を確認できるため、あまり迷う事なく環境構築できました。
また、iOSとAndroidを同じプロジェクトで管理できるのはやはり便利。
ただエミュレータとの接続やアプリの起動で何度かうまくいかない事もあり、まだまだ安定していない印象もあります。
これ以上勉強するか若干悩み始めてしまう...