OmniAICreator/Qiita-1.07M huggingface dataset:
ROSのノードを起動させる自分的ベストプラクティス

ROSの開発をやっていると、ターミナルでsshでログインしてroslaunch を実行したりして
ノードを立ち上げるケースが多いかと思います。

開発中だったらその都度それでも良いかと思うのですが、いざ試験を実施するときに、
いちいちsshでログインして。。。と立ち上げるノードが複数デバイスにあったり、
ノードを再起動させたい場合プロセスkillしたりなどなどするのはメンドクサイと思っています。

このようなケースで自分が使っているのがdockerコンテナでよく使っている supervisor です。
supervisor を使用することでOS起動時、docker コンテナ起動時にノードを立ち上げたり、
ブラウザから停止・再起動を行うことができます。

環境としては、以下で使用した[docker環境](https://github.com/shun/docker-ros-mqtt-topic-example) をベースに説明したいと思います。

* [ブラウザからROS Topic、MQTT Topic を送受信しROS nodeと通信する その１](https://qiita.com/shun_xx/items/93c249bda02de0852b61)
* [ブラウザからROS Topic、MQTT Topic を送受信しROS nodeと通信する その２](https://qiita.com/shun_xx/items/dcea947b14f9a632bbdf)

# supervisorをブラウザから制御する

supervisor をブラウザから制御するには以下を設定する必要があります。

```/etc/supervisor/supervisord.conf
[inet_http_server]
port = 0.0.0.0:9001
username = user
password = 123
```

コンテナの外からだったり、別PC上から制御するケースを想定して、0.0.0.0 を設定しています。
ブラウザから上記で設定したURL にアクセスすると、ログインのダイアログが表示されますので、
usernameとpassword を入力すると、以下のような画面が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/65929/018dff91-327f-4e26-2ac6-333be8354eeb.png)

今回の例では、supervisorにrosbridge_server を設定しているので、rosbridge_serverのノードの再起動・停止などを
ブラウザ上からコントロールすることができます。

使用している[docker環境](https://github.com/shun/docker-ros-mqtt-topic-example) では、roscore は別コンテナで起動していますが、roscore を別コンテナで事前に立ち上げなくても、通常のroslaunch と同様にroscore が起動していない or
ROS_MASTER_URI が設定されていなければ、roscoreも自動で立ち上がり、ブラウザ上でノードを停止すればroscoreも終了します。

ノードを立ち上げるsupervisorのスクリプトは以下になります。

```/etc/supervisor/conf.d/rosbridge_server.conf
[program:rosbridge_server]
priority=20
directory=/tmp
command=/usr/local/bin/rosbridge_server
user=root
stopsignal=TERM
autostart=true
autorestart=true
stdout_logfile=/var/log/supervisor/%(program_name)s.log
stderr_logfile=/var/log/supervisor/%(program_name)s.log
```

実際にノードを立ち上げるスクリプトは以下になります。

```/usr/local/bin/rosbridge_server
#!/bin/bash
set -e

source /opt/ros/kinetic/setup.bash
exec roslaunch rosbridge_server rosbridge_websocket.launch
```

起動させるデバイス・ノードが数多くあり、それらをいちいちブラウザ上で操作するのがメンドクサイというレベルになると、
この方法でも辛さがでてくるので、そういったケースになると、次のステップはansible で制御かなーとか思っています。

ここまでお付き合いしていただきありがとうございます。
パス(PATH)を通すとは?

## パス(PATH)を通すとは?

カレントディレクト以外にあるコマンドを実行するとき、パスを指定して実行することができます。しかし、毎回パスを入力するのは面倒です。パスを省略してコマンド入力させる方法があったらどれだけ便利でしょうか。
あらかじめ環境変数PATHにコマンドへのパスを登録すると、パスを省略してコマンド入力した際にパスを補完して実行してくれます。
このパスの登録のことを「PATHを通す」と言います。

## 手順
1. コマンドへのパスを控えておきます。例えば、`~/something/bin`
2. ホームディレクトリ下にある.bashrc (またはCatalina以降では.zshrcファイル)にパスを追記します。`vim ~/.bashrc` として、以下を追記します。`export PATH="$PATH:~/something/bin"`
4. 現在のターミナルのプロセスに反映するために、`source ~/.bashrc` を実行します。あるいは、別ウィンドウを開くことで変更を適用させます。
5. 動作確認として、`$ echo $PATH` を出力させます。さきほど登録したパスが出力されれば成功です。

## 一時的な利用
PATHを通すことで、新しいプロセスを開いたときにもコマンドサーチパスをし維持できます。これに対して、そのプロセスのみのPATHを指定する方法もあります。
`export PATH="$PATH:~/something/bin"` こうすると、プロセスを
閉じるまでの間だけ環境変数PATHに指定されたパスが定義されます。
VSCodeで快適SFTP生活

以前は PhpStorm のデフォルトで使用可能な SFTP を使い、
修正ファイルをVagrantやDocker上の開発環境へ反映、動作確認していました。

今回、この使い方なら VSCode でもできそうと思ったのでやってみました。

## Extension
* `liximomo.sftp`

## 設定
* プロジェクトをVSCodeで開く
* コマンドパレットを表示させる
    * Windows : `Ctrl`+`Shift`+`P`
    * Mac : `Command`+`Shift`+`P`
* コマンドパレットに `>sftp:config` を入力し、エンター
* プロジェクトを選択する
* プロジェクトのルートに `.vscode/sftp.json` が作成される
    * `sftp.json` は環境に合わせて書き換える

| キー | 値 |
| :-- | :-- |
| name | 適当な名前 |
| host | リモートマシンのホスト |
| protocol | `sftp` 固定 |
| port | `22` 固定 |
| username | ssh接続時のユーザー名 |
| remotePath | 反映先のプロジェクトのルートパス |
| uploadOnSave | true（VSCodeで保存したファイルが `remotePath` へ即時反映される） |

* リモートへ反映する際、ssh接続のパスワード入力が求められます
    * エディタ上部に表示されていて一見気付きにくいので注意
* ファイルやディレクトリを右クリックし、選択したファイルをリモートへ反映することもできます
 
```sftp.json
{
    "name": "My Vagrant",
    "host": "192.168.33.10",
    "protocol": "sftp",
    "port": 22,
    "username": "root",
    "remotePath": "/var/www/html/",
    "uploadOnSave": true
}
```

とても簡単な設定！

Sublime Text などのテキストエディタでもこういった拡張、設定は可能です。
お好みのエディタで探してみてはいかがでしょうか。

**Extensions で夢が広がりますね！！**

（元も子もないですが）PhpStorm なら、デフォルトでこういった便利機能は事前に用意されているので、
一つずつ整えていくのが大変！と思った方は、PhpStorm がありかもしれません。

## 併せて
* `.vscode`フォルダは `.gitignore` に追加しちゃいましょう！
年末まで毎日webサイトを作り続ける大学生 〜24日目 Single Column Layoutでサイトを作る〜

##はじめに
こんにちは！最近週末は温泉に通っている@70days_jsです！
webサイト制作でお金を稼ぐために年末まで毎日webサイトを作っております。
ここ数日、2 column layout、3 column layoutと作ってきたので、今日はSingle column layoutのサイトを作ってみました。
何かを参考にしようか迷いましたが、とりあえず最初は自分でということで何もみないで作りました。レスポンシブには対応していません。
扱う技術レベルは低いですが、同じように悩んでる初心者の方を勇気付けられれば幸いです。
今日は24日目。(2019/11/11)
よろしくお願いします。

##サイトURL
- https://sin2cos21.github.io/day24.html

##やったこと

Single Column Layoutでサイトを作りました。

まずは構想を作ります。↓

![スクリーンショット 2019-11-11 23.51.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/bbf7a9c5-9954-8eae-4fcc-b6765b4f21e5.png)

次に手書きでイメージ図を描きます。↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/2162871e-3d5b-8295-d071-17e82558c99c.png)

最後に実際にコーディングして完成です。↓(gif、重くてみられないかも。サイトURLへGO!)
![test.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/9b20691f-9bfa-b9a1-4d54-a4ac256583c2.gif)




今日も特に見せ場はないのですが、とりあえず今回は画像で押してみました。

```html
<main class="wf-sawarabimincho">
        <div id="message">
            <h2>君は準備できているか？</h2>
        </div>

        <div id="photo1" class="photo">
            <div class="photo_message">
                <h3>山にきた。さぁ、始まるぞ。</h3>
            </div>
            <div class="photo_image">
                <img src="day24_image/photo1.jpg" alt="山に来た画像">
            </div>
        </div>
　　　　...
```
こんな感じでmainはmessageから始まって、あとはphoto1のdivを画像分作ります。

cssも簡単に。


```css
#message {
    padding: 300px 0;
}
#message > h2 {
    text-align: center;
    width: 100%;
    font-size: 2em;
    font-weight: 1000;
}

.photo {
    color: rgba(0, 0, 0, .8);
    width: 100%;
    display: flex;
    justify-content: center;
    align-items: center;
    flex-direction: column;
    padding: 100px 0;
}

#photo1 {
    background-color: rgba(255, 255, 255, 1);
}

.wf-sawarabimincho { 
    font-family: "Sawarabi Mincho"; }

.photo_message {
    width: 70%;
    font-size: 1.5em;
}

.photo_image {
    width: 100%;
    text-align: center;
}

.photo_image > img {
    width: 50vw;
}
```

fontは全体を通してgoogleのやつを使っています。あとはこれを５枚分設定すれば完成です。

##感想
デザインの仕方が難しいと思いました。なんというか、デザイン力を鍛えねば・・・。

最後までお読みいただきありがとうございます。明日も投稿しますのでよろしくお願い致します。

##参考
1. 動物 リス ツリー - Pixabayの無料写真 (https://pixabay.com/ja/photos/%E5%8B%95%E7%89%A9-%E3%83%AA%E3%82%B9-%E3%83%84%E3%83%AA%E3%83%BC-%E8%87%AA%E7%84%B6-4605518/)
2. キャンプ キャデラック 1960 - Pixabayの無料写真 (https://pixabay.com/ja/photos/%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97-%E3%82%AD%E3%83%A3%E3%83%87%E3%83%A9%E3%83%83%E3%82%AF-1960-4610085/)
3. キャンプ テント 自然 - Pixabayの無料写真 (https://pixabay.com/ja/photos/%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97-%E3%83%86%E3%83%B3%E3%83%88-%E8%87%AA%E7%84%B6-%E5%A5%B3%E3%81%AE%E5%AD%90-691424/)
4. テント キャンプ 夜 - Pixabayの無料写真 (https://pixabay.com/ja/photos/%E3%83%86%E3%83%B3%E3%83%88-%E3%82%AD%E3%83%A3%E3%83%B3%E3%83%97-%E5%A4%9C-%E3%82%B9%E3%82%BF%E3%83%BC-548022/)
5. 市 泊 暗い - Pixabayの無料写真 (https://pixabay.com/ja/photos/%E5%B8%82-%E6%B3%8A-%E6%9A%97%E3%81%84-%E3%82%A2%E3%83%BC%E3%82%AD%E3%83%86%E3%82%AF%E3%83%81%E3%83%A3-89197/)

今日は画像をたくさんお借りしました。ありがとうございます！
SDL2を少しだけ触ってみた

某技術書典で購入した本にSDL2を使用するページがあったのと多分今後も使うことになると思うので、メモついでに環境構築手順とかを書き残しておこうと思う。


## SDLとは
- Simple DirectMedia Layerの略
- SDL2というのはメジャーバージョンの数字だと思う
- SDL 2.0のライセンスはzlib license(バージョン1.XはLGPLライセンスだったっぽい)
- 音声・入力・グラフィクスあたりの制御をサポートしてくれる
- クロスプラットフォームで複数OSに対応
- Ｃで書かれたオープンソース

昔触ったときは単純にOpenGLの拡張ライブラリに変わる便利系ライブラリという認識だったけど、一概にそうとも言い切れないっぽい。
調べた感じだとVulkanなんかにも対応しているようなので、やっぱり今後もお世話になる気がした。
詳しくは日本語リファレンスがあるのでそちらを参照するといいかも(http://sdl2referencejp.osdn.jp/)


## 開発環境

|||
|---|---|
|OS|Windows10|
|エディタ|Visual Studio 2019|
|SDL|SDL2-2.0.10|

## 環境構築手順

#### ビルド
1. [ソースコード配布ページ](https://libsdl.org/download-2.0.php)からコードをダウンロード(zip落とした)
2. zip解凍してVisualC\SDL.sln開く
3. ソリューションのビルド実行
4. VisualC\Win32\(Debug or Release)フォルダ直下にSDL2.libが生成されているので使用するプロジェクトに突っ込む
5. 該当のプロジェクト側で良い感じに設定する

実際のコードは「SDL2 入門」とかで調べると関数の使い方から何をしているかまで細かく書いてあるのでそっちを参照する感じで。

### わからなかったところ
#### SDLmainとは？
各種セットアップが終わった時点で一旦ビルドをかけてみたところ、エントリーポイントの未定義でおこられた。
SDLビルド時に一緒に出力されたSDL2main.libを追加することで対処できた。
原因としてはSDL_main.hでmainをSDLmainという名前に置き換えるマクロが定義されていて、実際のエントリポイント自体は別ファイルに記述されていた。そのエントリポイントの中身でSDL2main.libに定義されている関数が使用されていたりでエラーを吐いていたっぽい。
じゃあSDL2main.libとはなんなのかという話だが、ユーザー側でWinMain関数を定義しなくてもコードが組めるようになるというもの。要はWindowsに依存しないコードを組める便利なもの。（という認識...）
詳細はSDL_windows_main.cファイルというのがsrc/main/windowsフォルダ直下に存在するので是非目を通して欲しい。

#### サブシステム
SDLはサブシステムという概念が存在していて、上記で紹介した音声や入力、グラフィックなどがそれぞれ該当する

#### SDL_init関数の引数
基本SDL_INIT_EVERYTHINGですべてのサブシステムを初期化してくれるっぽい。
個別に指定することもできるけど今の所使う場面に出会っていないので、特に調べていない。
#### SDL_CreateWindow関数
文字通りウィンドウを作成してくれる

|引数名|概要|
|---|---|
|title|ウィンドウのタイトル|
|x|ウィンドウの座標(Define)|
|y|ウィンドウのY座標(Define)|
|w|ウィンドウの横幅(px)|
|h|ウィンドウの縦幅(px)|
|flags|SDL_WindowFlags|

戻り地 SDL_Window*

#### SDL_CreateRenderer関数
レンダリングコンテキストを作成してくれる

|引数名|概要|
|---|---|
|window|SDL_CreateWindowで作成した戻り値|
|index|ドライバの指定 -1をセットすることでいい感じにやってくれる|
|flags|SDL_RendererFlags|

#### SDL_RenderClear関数
現在のレンダーターゲットを色で塗りつぶして消去する
```SDL_SetRenderDrawColor```で色指定が可能っぽい

#### SDL_RenderPresent関数
レンダリングの結果を画面に反映する
ダブルバッファとかそういうアレだと思っている

### その他参考にしたページ
- http://sdl2referencejp.osdn.jp/
- https://www.slideshare.net/mobile/nyaocat/sdl2
R Studio 利用方法

##### ショートカット一覧
- Shift + Enter<br>
ステップ実行
- Ctrl + 1<br>
ソースエディタへフォーカスを移す
- Ctrl + 2<br>
コンソールへフォーカスを移す
- Ctrl + shift + c<br>
選択範囲全体をコメントアウト、コメントイン

##### デバック時のショートカット一覧
- エディタ画面のSourceボタン<br>
デバックを開始
- browser()処理<br>
ブレークポイント→エディタ画面でブレークを張っても同じ動きの様子
- F10<br>
ステップ実行

---
- R Studio Debug：https://support.rstudio.com/hc/en-us/articles/205612627-Debugging-with-RStudio
- 使い方：http://plaza.umin.ac.jp/~takeshou/R/RStudio1st.html
- 入門：https://kazutan.github.io/JSSP2018_spring/intro_rstudio.html
- デバック方法：https://stats.biopapyrus.jp/r/devel/debug.html
- デバック方法：http://bioinfo-dojo.net/2017/04/21/r-debug/
WebDAVサーバとしてのApacheとnginx

Ubuntu 18.04で試しましたが、他所も同じようなもんだと思います。
# Apache
## 導入
```
sudo apt install apache2
```
RPMとかの人もそんな感じで宜しく。
## 準備
ロックファイル置き場を/var/www/tempにして、/var/www/html/davを/davとして公開するものとします。

```
sudo mkdir -p /var/www/temp /var/www/html/dav
sudo chown www-data:www-data /var/www/temp /var/www/html/dav
```

## 設定
```
cd /etc/apache2/mods-enabled/
sudo ln -s ../mods-available/dav.load dav.load
sudo ln -s ../mods-available/dav_fs.load dav_fs.load 
sudo ln -s ../mods-available/dav_fs.conf dav_fs.conf
```
mods-availableにdav_lockというのもありますがdav_fsを使うなら必要ないそうです。
sites-available/000-default.confの最初のあたりを以下のように変更。

```/etc/apache2/sites-available/000-default.conf:
DavLockDB /var/www/temp/DavLockDB
<VirtualHost *:80>
        <Directory /var/www/html/dav>
                DAV On
        </Directory>
```
セキュリティに関しては状況に応じて宜しくとしか。
そして再起動。

```
sudo service apache2 restart
```
ところがですよ！バグがあってindex.htmlがあるディレクトリでPROPFINDが失敗します。
## 修正
mod_dirにバグがあるとされるので外してしまいます。

```
cd /etc/apache2/mods-enabled/
sudo rm dir.load
sudo rm dir.conf
sudo service apache2 restart
```
# nginx
## 導入
```
sudo apt install nginx nginx-extras
```
nginxでWebDAVするのは色々面倒だと書いてあるのをどっかで読んだのですが、そうでもないです。nginx-extrasが要るだけです。

## 準備
```
sudo mkdir -p /var/www/temp /var/www/html/dav
sudo chown www-data:www-data /var/www/temp /var/www/html/dav
```
## 設定
sites-available/defaultに以下の内容を追加。

```:/etc/nginx/sites-available/default
  location /dav/ {
    client_body_temp_path /var/www/temp;
    dav_methods PUT DELETE MKCOL COPY MOVE;
    dav_ext_methods PROPFIND OPTIONS;
    create_full_put_path on;
    dav_access user:rw group:rw all:rw;
    autoindex on;
    allow all;
  }
```
例によってセキュリティは宜しく。
そして再起動。

```
sudo service nginx restart
```
# 試してみる
curlを使います。

```
sudo apt install curl
```
## ディレクトリを作る
```
curl --request MKCOL http://localhost/dav/tmp/
```
nginxは最後のスラッシュが無いと409 Conflictって言います。なにがConflictだ？
## ファイルを置く
```
curl --request PUT --data "hello" http://localhost/dav/hello.txt
```
## 一覧を取得する
### プロパティを指定しない場合
```
curl --request PROPFIND --header 'Depth:1' http://localhost/dav/
```
デフォルトだと以下のプロパティが含まれます。

||Apache|nginx|
|---|---|---|
|creationdate|有|有|
|displayname|無|有|
|getcontentlanguage|無|空|
|getcontentlength（ディレクトリ）|無|有|
|getcontentlength（ファイル）|有|有|
|getcontenttype|有|空|
|getetag|有|空|
|getlastmodified|有|有|
|href|有|有|
|lockdiscovery|空|空|
|resourcetype（ディレクトリ）|有|有|
|resourcetype（ファイル）|空|空|
|source|無|空|
|status|有|有|
|supportedlock|有|空|
|executable（ディレクトリ）|無|無|
|executable（ファイル）|有|無|
### プロパティを指定する場合
例えば

```
curl --request PROPFIND --header 'Depth:1' --data '<D:propfind xmlns:D="DAV:"><D:prop><D:resourcetype/></D:prop></D:propfind>' http://localhost/dav/
```
Apacheに対して明示的にgetcontentlengthを要求するとディレクトリのstatusが404になります。
正規表現がわからない〜デリミタってなんじゃい〜

```
window.location.href.match(/\/groups\/\d+\/messages/)
```

はて？
正規表現を使っているのはわかるけど、ちょっとよくわからない。
調べているうちにたどり着いた　デリミタ
・・・はて？
というわけで、正規表現について少し調べてみたことをまとめてみました。
初心者の初投稿なのでご意見お待ちしております。

## デリミタってなんじゃい

デリミタ(Delimiter)とは
：データを項目ごとに区切る時の「区切り文字」のこと
（参考：https://wa3.i-3-i.info/word11621.html）

うーん、つまりどういうことだろう。
正規表現の両端を同じ記号で囲むことで、範囲を明示している。
（参考：http://www-creators.com/archives/5272）
つまり、例の場合は `/`で囲むことでその中のものが対象の範囲ですよ！と、そういうことだろうか。
アドレスを表現したいのにバックスラッシュにスラッシュに並んでて初心者にはどうも目が痛いというのが率直な感情です。
慣れるものなんでしょうか。

試しにデリミタを抜いてみる。

```
\/groups\/\d+\/messages
```
うーん。お次はバックスラッシュ。
調べているうちにたどり着いたのは、
①デリメタは `/`（スラッシュ）じゃなくてもいい。
②デリメタで使われた記号を使いたいときは 「エスケープ」 する必要がある。

ふむふむ。ニューワード。

## エスケープ？

エスケープとは
(1) 特別な意味を無効にしてくれる文字のこと。
(2) もしくは徳栄つな意味を付与するための文字のこと。
（参考：https://wa3.i-3-i.info/word11732.html）

ここで使われる「エスケープ」は (1)特別な意味を無効にしてくれる文字のこと。
つまり「デリメタ」として使っているスラッシュから「デリメタ」の意味をとっぱらってくれる意味があるということ。
パスを表現したいので、確かに`/`はすべてデリメタだと判断されては困ります。

ではここで整理してみる。
仮に「デリメタ」と「エスケープ」を抜いてみるとこんな感じになった。

```
/groups/\d+/messages
```
だいぶ見やすく、それっぽくなってきました！
でもまだ見慣れない文字列がいますね。


`\d+`

切り出してみると見たことのある文字列です。
そう、数字を表す正規表現。
`\d`は半角数字を表すのでしたね。
そして`+`は直前のパターンを１回以上繰り返す表現でした。

つまり、`\d+`はなんらかの数字を表しています。

## つまり /\/\ ってこういうこと。

最後の整理です。
まとめると、複雑に思えた文字列もだいぶすっきりしました。

```
/groups/"なんかの数字"/messages
```

立派なパスになりました。
デリミタとエスケープ。
最後に思うのは、パスを表現するときにデリミタにスラッシュを使う理由は何だろう...ということです。
慣習かな？

理解に誤りがございましたらご指摘いただければ大変ありがたいです。
最後までお読みいただきありがとうございました。
非ActiveRecordモデルでDraperを使用する

## 非ActiveRecordモデルのDraper使用
RailsでDecoratorを実装する際に、Draper(https://github.com/drapergem/draper )を使用されている方は多いのではないでしょうか。

今回、いつものようにDraperを使おうと、Decoratorディレクトリにモデル名のファイルを作成し、`@building.decorate`のように呼び出したところ

```
undefined_method: decorate
```
というエラーが発生しました。

### READMEを読む
解決するためにDraperのREADMEを読んでいくと、、、

ありました！最後の方に
>Models get their decorate method from the Draper::Decoratable module, which is included in ActiveRecord::Base and Mongoid::Document by default. If you're using another ORM, or want to decorate plain old Ruby objects, you can include this module manually.

なるほど。今回実装したモデルはActiveRecordではなく、ActiveModelをincludeしたモデルクラスであって、`ActiveRecord::Base`が入っていないために起きたことがわかりました。

このような場合には

```ruby:model.rb
include Draper::Decoratable
```
としてあげることで、Draperが使用できます！

もう上の方に書いてあるとありがたいですが、READMEをしっかりと読むのは大事ですね！
寒くなってきたのでRaspberry Piで自動でACヒーターをON/OFFできるようにしてみた！

# 目的：Raspberry PiでヒーターON/OFFしてみた！
最近、寒くなってきて冷え性には苦しい季節になってきました。
そこで、ある程度の温度に達するとヒーターがONになり、またある程度温まるとOFFになるIoTを実装してみました。

## 用意したもの
- [Raspberry Pi 3 Model B+](http://akizukidenshi.com/catalog/g/gM-13470/)
- [温度センサー](http://osoyoo.com/ja/2017/07/18/dht11-temperature-humidity-sensor-module/)
- [SSR](http://akizukidenshi.com/catalog/g/gK-00203/)
- [ヒーター](https://item.rakuten.co.jp/e-kurashi/17165/)
- AC電源プラグ   (SSRを入れる電源プラグは家にあったものを使用しています。)

## セットアップ
- [GitHub](https://github.com)から引用してきました。
 - https://github.com/szazo/DHT11_Python<br>
   持ってくる理由は1つのプログラムを書き換えるだけで済むからです。<br>
- まず、***Raspberry Piにサンプルプログラムをインストールします。***<br>
  GitHubが入っている事を確認・またはインストール<br>

  ```
  sudo apt-get install git
  ```
- サンプルpythonプログラムインストール

```
  git clone https://github.com/szazo/DHT11_Python.git
```
## 回路図
 - 温度センサーが関係ないやつに例えてます。ごめんなさい。
  - 右から（***GND,  センサーの値を読み取るPIN,  5V***)
 - Heaterは、ACなのでそのままSSRに繋げて電源タップに刺してもらえれば大丈夫です。
  - ***※回路を間違えると温度センサーがめちゃめちゃ熱くなります。気負付けてください。***
![温度センサー回路.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413177/5a99dbea-e403-110f-72fb-74c2b533f1ac.jpeg)



##プログラム(Python)
- [Python3](https://www.python.org/download/releases/3.0/)を使用しました。<br>
DHT11_Pythonの中の[dht11_example.py](https://github.com/szazo/DHT11_Python/blob/master/dht11_example.py)をそのまま引用できます。<br>
今回は、こんなプログラムにしました。

```python:dht11_example.py
# coding: utf-8
import RPi.GPIO as GPIO
import dht11
import time
import datetime

# initialize GPIO
GPIO.setwarnings(False)
# GBCMの番号で指定する事を宣言
GPIO.setmode(GPIO.BCM)
#BCMの17番ピンを出力に設定
GPIO.setup(17,GPIO.OUT)

# read data using pin 14
instance = dht11.DHT11(pin=14)
HotTemp = 20
ColdTemp = 5
sleepSecond = 0

try:
    while True:
        result = instance.read()
        if result.is_valid():
            tmp = result.temperature
            print(tmp)
            if tmp <= ColdTemp:
                # Heater running
                GPIO.output(17,1)
                print("Heater ON")
                sleepSecond = 10
            elif tmp >= HotTemp:
                # Heater stop
                GPIO.output(17,0)
                print("Heater OFF")
                sleepSecond = 10
            else :
                time.sleep(sleepSecond)

except KeyboardInterrupt:
        GPIO.cleanup()
```
***すごくわかりやすいプログラムだと思います。***

##実装
　とりあえず実装してみましょ！

```
sudo python3 dht11_example.py 
```
***動きましたか？***

## 動いていない場合は

- DHT11の[dht11.py](https://github.com/szazo/DHT11_Python/blob/master/dht11.py)の最初の部分に***as GPIO***を書き加えてみてください。

```python:dht11.py
import time
#import RPiにas GPIOを加えます
import RPi as GPIO

class DHT11Result:
    'DHT11 sensor result returned by DHT11.read() method'

    ERR_NO_ERROR = 0
    ERR_MISSING_DATA = 1
    ERR_CRC = 2
```
rails 発展その9 数学処理


## averageメソッド
平均を出すメソッド

```ruby:
  golf.average(:score)
  #=> 小数点まで含んだ平均点
   
``` 


## roundメソッド
四捨五入するメソッド

```ruby:
   10.4.round
  #=> 10
``` 

## countメソッド
数えるメソッド

```ruby:
   ninety.group(:product_id).count
   #=> {91=>2, 92=>1, 93=>4}
   #groupメソッドで指定したカラムの値です。
   #この例ではproduct_idになります。ハッシュの値はgroupメソッドでまとめられたレコード数です。
   
```
FileMakerで工事契約情報を管理する(2)

#目的
前回投稿した「FileMakerで工事契約情報を管理する」の今後の展開の１つ「会計年度で工事一覧を表示する」を追加しました。


#環境
windows10(windows7からのアップグレード)
FileMaker 16 pro

#サンプルファイル
https://www.dropbox.com/s/8pgdtessly0a70i/%E5%B7%A5%E4%BA%8B%E5%A5%91%E7%B4%84%E7%AE%A1%E7%90%86%E3%81%9D%E3%81%AE2.fmp12?dl=0


#0.前提条件
会計年度に表示する工事は下記の条件とします。
- 当初契約日が会計年度終了日以前
- 完成計上日が空白
- 契約解除が空白
また金額工期に関しては、受注計上月が会計年度終了月以前とする。

#作成手順
##1.テーブル、フィールドの作成
###1-1.完成情報テーブル
下記の通りフィールドを作成する。

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213168/0dd0294a-ac6b-a8e7-9399-6a2699341d5e.png)




###1-2.金額工期テーブルに、下記のフィールドを追加する。
- g\_工事台帳\_会計年度\_契約区分\_フィルタ
 - 会計年度に表示する工事をフィルタする（当初契約に絞る）ために使用する。 
- g\_工事台帳\_会計年度\_終了日\_フィルタ
- g\_工事台帳\_会計年度\_開始日\_フィルタ
- g\_工事台帳\_会計年度\_受注計上月\_終了月\_フィルタ
 - 会計年度に表示する金額などは、計上月が年度終了月以前にしたいのでそれをフィルタするために使用する。
- c\_工事台帳\_会計年度\_工期開始\_maxid\_フィルタ
- c\_工事台帳\_会計年度\_工期終了\_maxid\_フィルタ


###1-3.自社情報テーブル作成
会計年度の開始月と終了月を設定するためのテーブル

###1-4.基本情報テーブルに、下記のフィールドを作成する。
- c\_is\_工事台帳\_会計年度フィールド
 - 会計年度に表示する工事は"対象"、それ以外は"対象外"と計算させるためのフィールド
- c\_工事別税抜合計\_工事台帳\_会計年度
- c\_工事別消費税合計\_工事台帳\_会計年度
- c\_工事別税込合計\_工事台帳\_会計年度

###1-5.ユーティリティテーブル作成。
ユーザーごとの情報を保存するためのテーブルとして利用する。
そこに下記のフィールドを作成する。

g\_工事台帳\_会計年度\_会計年度
工事一覧_会計年度レイアウトで会計年度を保存するために使用する。


##2.オカレンスの追加
###2-1.「TO_01_工事台帳」に「TO_01h_工事台帳_完成情報」を作成する。
会計年度の工事を表示するには、完成情報を入力する必要があるため作成する。

###2-2.会計年度の工事を表示するためのオカレンスを作成する。
下記のようになります。
![2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213168/9e3f5fa4-3660-f09f-9fff-7601618fda75.png)


##3.スクリプトの作成
###3-1.工事台帳表示用のスクリプト作成
下記のスクリプトを作成する。詳細はファイル確認ください。
- 工事台帳_会計年度_年度指定検索
- \_工事台帳_会計年度_検索条件設定

###3-2.ファイル起動時のスクリプト作成
下記のスクリプトを作成する。詳細はファイル確認ください。
- initialize

##4.全体の流れ
詳細はファイルを見た方が分かりやすいと思いますので、動作の流れをざっくりまとめます。

1.自社情報テーブルで会計年度開始終了月を設定
2.工事一覧_会計年度レイアウトで表示したい会計年度を入力
3.スクリプト<\_工事台帳_会計年度_検索条件設定>で設定した会計年度開始終了月をもとにリレーションの照合に利用しているグローバルフィールドに適切な日付を設定
4.基本情報テーブルに作成した「c\_is\_工事台帳\_会計年度フィールド」に対象と計算された工事を表示する。
5.金額、工期に関しては受注計上月が会計年度終了月以前の情報が表示される。
CustomeXibを他クラスから参照する方法

他クラスからCustomeXibを参照する方法について備忘録としてここに記す。
まずはファイル構成から
<img width="262" alt="スクリーンショット 2019-11-11 23.19.29.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302540/588dda02-07ad-b1df-e1a9-cafcf6dd73ea.png">

#xibのFilesOwnerとCustomeClassを繋げよう
普段はxibのViewとCustomeClassを繋げているが、
今回は違う方法で試す。
<img width="1106" alt="スクリーンショット 2019-11-11 23.22.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/302540/d49e15ba-b7dd-ccaa-9d86-1c054d167ac3.png">
こうすることでSwiftファイルで部品を繋げることが可能になる。

#CustomeView.Swift

```swift
class CustomeView: UIView {

    @IBOutlet weak var label: UILabel!
    override init(frame: CGRect) {
        super.init(frame: frame)
        let view: UIView = UINib(nibName: "CustomeView", bundle: nil).instantiate(withOwner: self, options: nil).first as! UIView
        self.addSubview(view)
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        let view: UIView = UINib(nibName: "CustomeView", bundle: nil).instantiate(withOwner: self, options: nil).first as! UIView
        self.addSubview(view)
    }
}
```
以上の２つは必須っぽい？

#他クラスからviewを参照する方法
```swift

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
    }
    @IBAction func button(_ sender: Any) {
        self.view()
    }
    
    func view() {
        let view1 = CustomeView.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view1.label.text = "aaa"
        let ttt = createImage(view1)
    }
    func createImage(_ view: UIView) -> UIImage {
        UIGraphicsBeginImageContext(view.bounds.size)
        UIGraphicsBeginImageContextWithOptions(view.bounds.size, view.isOpaque, 0)
        let context = UIGraphicsGetCurrentContext()!
        view.layer.render(in: context)
        let image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        return image
    }
}
```

この部分に注目しての通り参照できてきますね。

```swift
func view() {
        let view1 = CustomeView.init(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
        view1.label.text = "aaa"
        let ttt = createImage(view1)
    }
```

#締め
そもそも論、CustomeView.Swift側で値を入れる方が綺麗？
他に方法があれば是非教えてください！
Twilio SIP registrationのメリットを考えてみる

# Twilio SIP Registrationとは何か
唐突ですがSIP RegistrationはIP電話機を利用するための機能です。
IP電話機(例[Yalink](https://yealink.jp/product_category/ip_phone/))は電源を入れて、ネットワークケーブルを指しただけでは動作しません。　
SIPサーバーに適切な設定が入っており、なおかつIP電話機にそのサーバー接続情報があってはじめて動作します。
TwilioはこのSIPサーバー（と公衆電話網への接続）を提供することにより、IP電話機の利用を非常に簡単にすることに成功しています。

ちなみに[Twilio　Docs](https://jp.twilio.com/docs/voice/api/sip-registration)には以下の説明があります。

`SIP Registration is the process in which a SIP Endpoint sends a SIP REGISTER request to the registrar. The registrar accepts the request and stores the information in the location service of the domain it handles. The registrar acts as the front end to the location service for a SIP Domain, reading and writing bindings between endpoints and a particular user`

SIPレジストレーションは、SIPエンドポイントがSIP REGISTERリクエストをレジストラに送信するプロセスである。
レジストラは要求を受け入れ、処理するドメインのロケーションサービスに情報を格納します。レジストラーは、SIPドメインのロケーション・サービスに対するフロントエンドとして機能し、エンドポイントと特定のユーザーとの間のバインディングの読み取りと書き込みを行います。

全然わからないですね。　(´Д｀)ﾊｧ…

# TwilioのSIP Registrationを利用する・しない場合
TwilioのSIP Registrationを利用すると便利なのですが、利用した場合とそうでない場合を比較してみましょう。

**まず、一般的な構成でSIPの電話機を使うためには何が必要か列挙してみます**
1. PCサーバー（サーバー本体とOSの組み合わせ）, AWSを使えば月５００円程度？上限なし 
2. SIPサーバー機能。入手と設定が簡単なのはIP PBXのAsteriskあたりでしょうか。業務用は上限なし
3. 上記構築、管理コスト
4. 外線発信のための回線契約と接続

SIPサーバーの機能を実現するためには実はそれほど費用はかかりませんが、各種インストール作業及び設定の知識。
加えて管理コストが大きく乗っかってきます。
ベンダーの協力を仰ぐ場合には１００万円単位でお金が必要でしょう。
また回線契約には多くの時間が費やされることは容易に想像できます。

**Twilio SIP Registrationの場合**
1. Twilioアカウント(５分で作れる）
2. SIP電話機とTwilio間の[費用](https://www.twilio.com/voice/pricing/us) USD0.004/分(はじめの100k分）
3. 発信・受信時のコード作成

Twilioの場合は「発信・受信時のコード作成」を除いて非常に簡単にできます。

注) ０３等の外線発信は共通のため費用から除いています

#発信・受信時のコード作成はどうしたらいいのか
実はこれは今までのSIPサーバーに無い部分ではあります。
が、参考文献にあるリンクですでに皆さん書いてあります。なんと親切な！！
ぜひお試しください！

#Memo
最近私が使っているSIPクライアント(詳細は参考文献参照のこと)は[GS Wave](https://www.grandstream.jp/%E3%83%9B%E3%83%BC%E3%83%A0/%E8%A3%BD%E5%93%81%E6%83%85%E5%A0%B1/ip%E9%9B%BB%E8%A9%B1%E6%A9%9F/%E3%82%BD%E3%83%95%E3%83%88%E3%83%95%E3%82%A9%E3%83%B3%E3%82%A2%E3%83%97%E3%83%AA/grandstream-wave/)というアプリです。
グランドストリームという有名なIP電話機を作っているメーカーが出しています。
安定していて設定もそこそこ簡単です。
IP電話機のメーカーが出しているというのが大きいですね。

#参考文献
[SIP Registrationで確実に発信者番号を通知させる](https://qiita.com/mobilebiz/items/4293e35ebb8de9ca8cc3)
[SIPレジストを使って、Twilioで固定電話をつかってみる](https://qiita.com/mobilebiz/items/26f91550556088545c49)
[SIPレジストを使って、Twilio環境だけでSIPソフトフォンを使ってみた](https://qiita.com/moroshi/items/44b71dd2843350813b94)
ConoHaでMinecraftBedrockserverを建てる

[Minecraftの公式サーバー](https://www.minecraft.net/en-us/download/server/bedrock/)をConoHaで建てるための備忘録

# やること
1. ConoHaで新規サーバーを建てる
2. SSH接続する
3. Minecraft公式サーバーをネットからダウンロードする
4. unzipする
5. screenで起動

#Step1　ConoHaで新規サーバーを建てる
[ココ](https://support.conoha.jp/v/addvps/)を参考にサーバーを追加していきます
![2019-11-11 22.55.58 manage.conoha.jp cf7b00c47a50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398204/f66c25df-27e3-46a6-f9d1-b7d134bbdbaa.png)
図では512MBプランを選択していますが足りないので1GBプランのほうがおすすめです

#Step2 SSH接続する
ぶっちゃけ**[ココ](https://support.conoha.jp/v/vps_ssh/?btn_id=v-addvps-related_v-vps_ssh)**見ればなんとかなるので割愛

#Step3 Minecraft公式サーバーをネットからダウンロードする
[minecraft公式サイト](https://www.minecraft.net/en-us/download/server/bedrock/)からUbuntu用のダウンロードリンクをコピーして
wgetでダウンロードする
`wget downloadlink`
#Step4 unzipする
unzipが入ってないのでインストールする
`sudo apt install unzip`
エラー出たら再起動しよう
インストールできたら
`unzip bedrock-server-X.XX.X.XX.zip`
で解凍
ファイル名はtabキーを押すと自動補完してくれるよ（Hacknetやるまで知らなかった）
#step5 screenで起動
[ココ](https://qiita.com/non_cal/items/008ef7e1a8bc03415817)を参考にscreenで起動
`$ LD_LIBRARY_PATH=. screen -S bds ./bedrock_server`
これでSSHを切ってもマイクラにアクセスできます
rails 発展その8 form_forとform_tagの使いわけ

## form_forとform_tagの違い
form_for: 入力フォームにモデルがあれば使用
　　　　　　投稿、入力フォームなど
          paramsに置いてネストされる(2重になる)ため
　　　　　　params.require(:モデル名).permit(:カラム名)を使用
　　　　　　

form_tag: モデルがなく特定のアクションに送りたい場合に使用
　　　　　　検索フォームなど
          paramsに置いてネストされないので
　　　　　　params.permit(:キー名)

### form_for
   投稿、入力フォームなどに使用
　　基本変数を設定し
　　入力フォームと送信ボタンを作成するのが基本です。
  
  ```html:viewの例
     <%= form_for current_user do |f| %>
     <!--上記でf変数を設定-->   
        <div class="col-lg-6">
          <%= f.text_field :full_name, placeholder: "フルネーム", class: "form-control" %>
　　　　　　<!--ここで変数を使用して入力フォームを作成 full_nameカラムに入力できるようにする->
        </div>
      <div class="form-group">
        <%= f.submit "送信", class: "btn btn-primary withripple" %>
　　　　　<!--送信用のボタンを設定-->
      </div>
    <% end %>
　
```

### form_tag
　　検索フォームなどに使用　　
　　入力内容から特定のアクションを行わせたい時に使用する

## require/permitメソッド
   特定の情報だけデータを受け取るように設定するメソッド
   require: モデルを指定
　　permit:  カラムを指定

```ruby:controller
   params.require(:モデル名).permit(:カラム名)
   # form_for用
   params.permit(:キー名)
   # form_tag用　　

# 例
 def user_params
  params.require(:user).permit(:name, :age)
 end
 #userモデルにたいし、nameとageカラムだけ許可
```

## mergeメソッド
  mergeメソッドは2つのハッシュを統合する時に使うメソッドです。
 　別々で入力した内容をまとめたい時など使用
  
  ```ruby
     ha1 = {question: "Who?"}
     ha2 = {group: "camp", name: "abe"}
     ha1.merge(ha2)

#出力結果
#=> {:question=>"Who?", :group=>"camp", :name=>"abe"}
  ```

## placeholder: ''
フォームの中に、''で囲んだ文字をフォームの値が空の時に薄く表示しておくことができます。

```html:sample.html.erb
    <%= f.text_field :nickname, placeholder: 'ニックネームを入力（必須）' %>
```
Django: 文字列からクラスをImportする

# Django 文字列からクラスをImportする。
サンプルの[Repositoryはこちら](https://github.com/Saknowman/django_setting_sample_project/)です。
Repositoryは[APPごとのSetting](#)と兼ねているのでご了承ください。  


Djangoで文字列からクラスをImportしたいときありますよねー。
そういう時は、**django.utils.module_loadingのimport_string**を使います。




```python
from django.utils.module_loading import import_string

cl = import_string('rest_framework.permissions.IsAdminUser')
```

## 使い道
自分はPermissionを文字列の配列でsettings.pyに設定し、RestFrameWorkのViewsetで使いたかったときに使用しました。



```python:project/settings.py
SAMPLE_PERMISSIONS = [
    'rest_framework.permissions.IsAuthenticated',
    'sample_app.permissions.SamplePermission'
]
```



```python:sample_app/views.py
from django.conf import settings
from rest_framework.viewsets import ModelViewSet
from django.utils.module_loading import import_string

from .serializers import SampleSerializer
from .models import Sample


class SampleViewSet(ModelViewSet):
    serializer_class = SampleSerializer
    queryset = Sample.objects.all()
    
    # ここで使用した。
    # IsAuthenticated, SamplePermissionがPermissionsに適用される。
    permission_classes = [
        import_string(permission_class) for permission_class in settings.SAMPLE_PERMISSIONS]

```


こんな風に利用できます。
使う時がたまにあると思うので参考に、

サンプルの[Repositoryはこちら](https://github.com/Saknowman/django_setting_sample_project/)です。
Repositoryは[APPごとのSetting](#)と兼ねているのでご了承ください。  

ではでは、よいDjangoライフを。
AWS#1：覚えた技術を日々書き留める

#AWSとMQTT関連の用語たち

**MQTT**  
2者間の非同期通信をサポートするプロトコル

**JSONペイロード**  
JavaScriptにおけるオブジェクトの表記法を応用したデータ形式

**Thing**  
管理したいデバイスやセンサーをThing(モノ)として登録する。
モノには属性(Attribute)を任意に登録できる

**Certificate**
証明書。モノを認証するための証明書

**Publisher**
データを送る側

**Subscriver**
データを受け取る側
Laravelでブログデザインとアプリ作成してみた

今回シンプルなタスク管理アプリに引き続き、ブログデザインとアプリを作成してみましたので、オープンソースとして共有いたします。

# 目的
・汎用的データ作成
 |- デザイン
 |- ソース

#作成物
![top.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/1f359db1-6a43-1921-8073-10ae7b185505.jpeg)
![app.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393193/66626c8e-8416-57a6-461f-a2fcd47dbf5f.jpeg)

下記に環境移行の手順をまとめます。

# 環境構築
Mac High sierra
Laravel 5.8
VirtialBox+Vagrant+Homestead環境

※こちらはチートシートにまとめてありますので
このURLを参照してください。
　|- [Laravel環境構築 チートシート](https://qiita.com/ProgramingDai/items/6fe5f678bf5a05e27c05)

チートシートの「vagrant ssh」まで完了すれば大丈夫です。

+α　別のVM名で環境構築し、そちらには新規のLaravelをダウンロードしてください。一部取り出したいデータがあるため。

# 1.データクローン
まずどこでもいいので下記コマンドをターミナルに入力してデータをクローンしてください

```console:ターミナル
git clone https://dai570415@bitbucket.org/dai570415/laravel-blog-master.git
```

# 2.クローンデータを解凍して環境に入れる
先ほど環境構築した際に「code」フォルダを作成しているかと思いますので、その中にクローンしてきたファイル（中身のみ）をごそっと入れてください。

下記アドレスにアクセス
`192.168.10.10`

Topページが表示されるはずです。

# 3.DB関係を設定する

マイグレート

```console:ターミナル
$ php artisan migrate

* こちらでDB周りが構築できました
```

# 4.シンボリックリンクを作成

```console:ターミナル
$ php artisan storage:link

* こちらは画像表示させるために必ず必要になるので
おこなっておいてください。
```

(注)
・posts_table
show.blade.phpの詳細記事描画はまだ作成していません。作成次第Git更新します。

・User情報の変更をしたい場合は直接下記アドレスを入れてください。
`192.168.10.10/user/userEdit`
こちらは編集できるAPIのみ実装しています。CSSも当ててない状態。
個人的によく使うpython&pandasでの文字列操作

###CSV ファイルの読み込み
```python:
#ファイルを開く
path=""
filename="hoge"
df = pd.read_csv('{}/{}.csv'.format(path,filename))
```
こちらの方が簡潔で分かりやすため，おすすめです．
@shiracamusさんに教えてもらいました．

```python:
#ファイルを開く
path=""
filename="hoge"
df = pd.read_csv(f'{path}/{filename}.csv')
```

###CSV ファイルとして保存(インデックスなし)
```python:
#ファイルを保存
path=""
filename="hoge"
df.to_csv('{}/{}.csv'.format(path,filename), index=False)
```
同様に，こちらの方が簡潔で分かりやすため，おすすめです．
@shiracamusさんに教えてもらいました．

```python:
#ファイルを保存
path=""
filename="hoge"
df.to_csv(f'{path}/{filename}.csv', index=False)
```

###行数・列数取得
```python:
line = df.shape[0] # 行
row = df.shape[1] # 列
```
    

###i 行 j 列にあるデータを取得する
```python:
hoge = df.iat[i, j]
```
###リストをdfにする(カラムあり)
```python:
list=[hoge1,hoge2,hoge3]
df = pd.DataFrame(list, columns=["hoge"])
```

###dfを連結
```python:
df = pd.concat([df1, df2], axis=1) # 縦:0 横:1
```

###dfからj列の一番最初のデータを取得
```python:
hoge = df.iat[0, j]
```

###dfからj列の一番最後のデータを取得
```python:
line = df.shape[0] # 行
hoge = df.iat[line, j]
```

###indexの設定
```python:
df = df.set_index('列名')
```

###indexの解除
indexは1,2,3・・・に戻り、indexに指定されていた列は元の位置に戻る？

```python:
df = df.reset_index('列名')
```

###str型からdatetime型への変更
新たな列名を指定すれば列の追加、既にある列名の場合は上書き。

```python:
df["列名"] = pd.to_datetime(df["列名"])
```

###datetime型からstr型への変更
新たな列名を指定すれば列の追加、既にある列名の場合は上書き。

```python:
df["列名"] = df["列名"].to_string()
```


###カラムの設定
特になし。

```python:
df.columns=['hoge','hogehoge','hogehogehoge']
```
RedmineのWiki記法(よく使うもの一部)

※この記事は https://kunosu.qrunch.io/entries/CrVd03hOZ97aFxBJ に移動しました。

---

よく使うものまとめ。
公式のWiki記法はこちら→ http://redmine.jp/tech_note/RedmineWikiFormatting/

## 目次の表示

```
{{toc}}
```

## 折りたたむ
`()`はなくてもOK

```
{{collapse(名前)
ここに折りたたみたい文章を書く
}}
```

## Wikiへのリンク

```
[[ページ名]]
```

### ページ名と異なる名前を表示させたいとき

```
[[ページ名|表示される名前]]
```

### 違うプロジェクトのWikiページへのリンク

```
[[プロジェクト名:ページ名]]
```

## 新しいページを作る

1.  リンクを貼りたい場所に `[[ページ名]]` を書き、保存。
1.  書いた場所がクリックできるようになっているので、クリックすると編集画面に移る。
.icloud拡張子のファイルをコマンドで一括ダウンロードする方法

## 結論から
ターミナルで以下のコマンドを実行。

```
find ディレクトリのパス -name "*.icloud" | xargs open -a "Finder"
```

## 説明
「ディレクトリのパス」に指定したディレクトリから再帰的に.icloudファイルを検索して、検索結果のファイルをMac標準のFinderで開くことでローカルにダウンローされます。

### ※注意
あまりにも多くのファイルを一括でダウンロードするとMacが死ぬのでご注意ください。
Rails6 link_to メソットのメモ

# 目的

- 若干理解できていないlink_toメソットについて知る。

# このメソットの概要

1. リンクを作成するメソットである。
2. HTMLのaタグと同じ機能を有する。
3. 引数で表示リンク名とリンク先を指定する。
4. 第一引数をリンクにする文字、第二引数をリンク先のビューファイルのパスとなる。

# 書き方の例

- Railsのビューファイルにリンクを記載する例を記載する。
- 下記にlink_toメソットを使用したリンク先の書き方とaタグを使用したリンク先の書き方を記載する。

    ```html
    # link_to メソット
    <%= link_to("表示名", "ルーティングに記載しているリンク先のURL") %>

    # aタグ
    <a href="/ルーティングに記載しているリンク先のURL">表示名</a>
    ```

# より具体的な例

- RailsのビューファイルにURLが"/about"、表示名が「このアプリについて」と言う条件のリンクを作成する。
- 下記に前述の条件のリンクをlink_toメソットとaタグを使用した全く同じ意味のリンクの書き方を記載する。

    ```html
    # link_to メソット
    <%= link_to("このアプリについて", "/about") %>

    # aタグ
    <a href="/about">このアプリについて</a>
    ```
Yahooブログ終了まであと僅か。cyotek webcopyで保存する方法の紹介。

yahooブログ終了まであと僅かということで、cyotek webcopyを紹介します。

![image1_l.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480821/3f01638b-f78f-62b2-2f7c-82eb2fa021db.jpeg)
今まで、日本でのwebのダウンロードといえば、wgetや、httrackなどが多く見受けられました。しかし、これらのソフトは初心者には取っつきにくかったりします。
このソフトは、窓の杜で紹介されているだけで、日本語のブログで紹介されているのは僅かです。そこで少し紹介したいと思います。
yahooblogは移行ツールが用意されていますが、コメントなどの必要でない情報は移行されません。そのため、今yahooblogを移行しようとしている方にも有益かもしれません。

https://www.cyotek.com/cyotek-webcopy 解説url 　※英語

設定項目は多岐にわたりますが、単なるダウンロードなら簡単な設定で可能です。

1左上の　file　をクリック
2new をクリック
3website の右の空白に、サイトのurlを4入力。
5右上の copy をクリック
6コピーが始まります。デフォルトでは、url以下の階層がすべてコピーされます。

※save folderのパスは、すぐいっぱいになるので。dドライブにしておいたほうがいいと思います。　ctrlとf9を同時に押して、出てきたタブの左の　copy　タブをクリックして、default save folder にパスを書けばずっと設定が反映されます。




cyotekではほかにも便利なツールを作っています。PRODUCTS からご覧ください。
https://www.cyotek.com/
GitHub Actions でステータスバッジを表示する

# はじめに
GitHub Actions v2 でステータスバッジを表示する方法です。
意外と知らない方も多いようですがちゃんと表示できます。

# ステータスバッジとは？
README.md でよく見るこういうやつです。[^1]
<img width="172" alt="actions-workflow-status-badge.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/455401/388b657d-0bf9-c715-d1ab-9d21c29c72eb.png">

# ステータスバッジの表示
基本的にはドキュメントの通りです。
[ワークフローを設定する - GitHub ヘルプ](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/configuring-a-workflow#adding-a-workflow-status-badge-to-your-repository)
[継続的インテグレーションについて - GitHub ヘルプ](https://help.github.com/ja/actions/automating-your-workflow-with-github-actions/about-continuous-integration#status-badges-for-workflow-runs)

README.md に以下のコードを埋め込むと表示できます。

```
![](https://github.com/<OWNER>/<REPOSITORY>/workflows/<WORKFLOW_NAME>/badge.svg)
```

`<WORKFLOW_NAME>` には `name` に設定された名前（空白文字は `%20` に置換）か、ファイル名を指定できます。

## ブランチを指定

`branch` パラメーターを付けることで特定のブランチを指定することが出来ます。

```
![](https://github.com/actions/hello-world/workflows/Greet%20Everyone/badge.svg?branch=feature-1)
```

## イベントを指定

`event` パラメーターを付けることで特定のイベントを指定することが出来ます。

```
![](https://github.com/actions/hello-world/workflows/Greet%20Everyone/badge.svg?event=pull_request)
```
# おわりに
ブランチとイベントの指定は最近追加されたようです。

[^1]: 画像は公式ドキュメントからお借りしました。
Airflowのセンサ(Sensor)入門

# センサ(Sensor)とは
Airflowのオペレータの一種で、何かが起きるまで待つのに使います。


# どんなのがあるの？
いろいろありますが、よく使いそうなのは
* Cloud Pub/Subを待つ(PubSubPullSensor)
* 他のDAGのタスクインスタンスを待つ（ExternalTaskSensor）
* Pythonのcallableを待つ（PythonSensor）
* HTTPリクエストを待つ（HttpSensor）
* ストレージを待つ（GoogleCloudStorageObjectSensor/SFTPSensor/S3KeySensor）
などがあります。

ソースコード中では[ariflow/sensors](https://github.com/apache/airflow/tree/1.10.2/airflow/sensors)ディレクトリと[airflow/contrib/sensors](https://github.com/apache/airflow/tree/1.10.2/airflow/contrib/sensors)ディレクトリにあります。
（1.10.2の場合）

# 動作
Sensorは[BaseSensorOperator](https://github.com/apache/airflow/blob/1.10.2/airflow/sensors/base_sensor_operator.py)クラスを継承し、大雑把には下な感じで動作します。

1. 何かが起きたかチェック（pokeメソッド）
1. 何か起きた（pokeがFalseでない）時は終了
1. 経過時間をチェック。タイムアウトしていれば終了
1. 何も起きず、タイムアウトもしていない時は、さらに一定時間(poke_interval)待つ
1. 繰り返す

## その他のオプション
* soft_fail(True/False)
    * タイムアウトした時のタスクインスタンスの状態
    * Trueでは、timeoutした時にタスクインスタンスがfailしない（skipped）
     * downstreamのタスクインスタンスはスキップされます [（私はハマりました…）](https://qiita.com/kurtosis/items/9ff8d91beb443076424a#%E3%83%8F%E3%83%9E%E3%81%A3%E3%81%9F%E4%BE%8Bsensor%E3%81%AEsoft_fail)
    * Falseでは、timeoutした時にタスクインスタンスがfailする

* mode(poke/reschedule)
    * 待ち方の指定
    * pokeでは、タスクインスタンス内でsleepして待ちます
    * rescheduleでは、Airflowのスケジュールの仕組みで待ちます
    * pokeだと待っている間もスロット（同時実行の制限）専有するので、長く待つ可能性がある時はrescheduleの方が良いらしい
csv大量データをMySQLにインポートする方法（空欄のnull化含む、LOAD DATA INFILE構文の利用）

LOAD DATA INFILE構文を使った、csvをMySQLのテーブルにインポートする方法を解説します。
ここではセールスフォースのレポート機能で出力するcsvを例に進めます。

## セールスフォースでデータをエクスポートする際の形式
文字コードはutf8を選択して、csv形式での出力を設定します。

## MySQLにcsvをLOAD DATA INFILE構文でインポートする
MySqlWorkbenchや、Sequel ProなどのGUIツールを使って、インポートしても良いですが、
LOAD DATA INFILE構文での実行が高速で、持ち回りもできてオススメです。

以下コードになります。

```sql
LOAD DATA
    LOCAL INFILE '{your_local_file_path}/your_file_name.csv'
    INTO TABLE salesforce_data
    FIELDS TERMINATED BY ','
    ENCLOSED BY '"'
    LINES TERMINATED BY '\n'
    IGNORE 1 LINES
SET
    int_field = nullif(state_code, '')
;
```

### コードの解説

#### 区切り文字
カンマ区切りは、
`FIELDS TERMINATED BY ','`
とします。

#### フィールドの括り
""で区切られていますので、
`ENCLOSED BY '"'`
を記述します。

#### 改行コード
セールスフォースでの出力では改行コードはLFがセットされるようですので、
`LINES TERMINATED BY '\n'`
としています。

出力後に加工などして、改行コードが変わってしまった場合は以下のように変更してみてください。

CRでは、
`LINES TERMINATED BY '\r'`
CRLFでは、
`LINES TERMINATED BY '\r\n'`
となります。

#### 無視する行を設定する
フィールド名がcsvの１行目に含まれている場合、
`IGNORE 1 LINES`
を記述しましょう。

#### int型などで空欄をnullにしたい時
int型で、nullを許容しているような時は、以下のようにします。

```sql
SET int_field = nullif(state_code, '')
```
nullを許容していない場合は、0をセットするようにすれば良いかと思います。

## LOAD DATA LOCAL INFILEが実行できない人へ

こちらの記事が参考になるかと思います。

https://yoku0825.blogspot.com/2018/07/mysql-80load-data-local-infile-error.html

MySQL8系を例にしているようですが、おそらくMySQL5系でも同様かと思います。
`--local-infile`は、デフォルトで1がセットされていることも多いようですので、
私の場合は特に問題なく実行することができました。

ファイルパスや改行コードについてはこちらの記事も参考にさせていただきました。

https://qiita.com/n_s_y_m/items/d87e5c991da5ade957c1

## まとめ
MySQLのテーブルへcsvをインポートするときは、GUIツールのimport機能に頼るより、
自身でLOAD DATA INFILE構文を使って投入すると効率的かつ確実かと思います。
（GUIツールの謎のエラーに悩まされたりしない。自分の場合はSequel Proでインポート実行中に決まった箇所で落ちましたが、データは問題なさそうなので原因わからず、、）

Herokuなどの本番環境でも同様に使いやすい方法かと思いますので、MySqlでcsv形式の大量データを投入する際の参考になれば幸いです。
Android visual studi for mac 2019 でnuget でlifecycle extentions

すごいハマったので取り急ぎメモ
現在Androidアプリをvisual studio でC#で実装しているが
iOSアプリで言うところのWillEnterForegroundイベントが取得できない。

https://qiita.com/takusemba/items/92e700ee6c24a3398d03
このページを参考にすると
arch.lifecycle extentions をbuild.gradleで取得するとの記載があるが
visual studio for mac 2019 ではそもそもbuild.gradleが存在しない。
その代わりにデフォでnugetというのが入ってるらしい。

ソリューションエクスプローラからManage nuget Packageを選択し、arch.lifecycle extentions
を探し、1.1.3をインストールしようとしても
失敗しましたと出る。

結局これは
プロジェクト＞右クリック＞ビルド＞全般＞ターゲットフレームワークを8.1oreo
にし1.1.1をインストールしたところできた。
Androidのビルドバージョンとlifecycle extentionsのバージョンの組み合わせを気をつけなければいけないらしい

ちなみに下記のnuget.orgのdependencyが多分それ
https://www.nuget.org/packages/Xamarin.Android.Arch.Lifecycle.Extensions/1.1.1.1


#懸念点
・マニフェストファイルはAndroid9.0になってるけど良いのか？
EloquentでCRUDしよう

#Eloquentって？
Laravelに含まれている*美しくシンプルなアクティブレコードによるデーター操作の実装*です。

と書いてありますが、言ってしまえばデータベースのテーブルの内容をModelとして扱える便利な機能です。

#使い方
##モデルを作る
ここではlaravelの公式を参照してみましょう.

```
php artisan make:model Flight
```
このコマンドでFlightモデルを作ることができます。

```Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    //
}
```
こんな感じのファイルが生成されます。ここで`namespace`は名前空間というもので、今後このFlightモデルを使うときは

```php
App\Flight
```
で使うことができるようになります。

現在のままでは単に空のモデルを作っただけです。そこでflightsテーブルの内容を紐付けてみます。
flightテーブルには

* id
* datetime
* name
* company
* from
* to

というカラムが存在するとします。
飛行機の便みたいなものを想像してください。

紐付けましょう。こうなります。

```Flight.php
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
    /**
     * モデルと関連しているテーブル
     *
     * @var string
     */
    protected $table = 'flights';
}
```

これで完了です。

##Create

それではテーブルにデータを挿入してみましょう。ここでidは主キーかつauto_incrementとします。

```php
$obj = new App\Flight;
$obj->datatime = '2019-01-01';
$obj->name = 'NH01';
$obj->company = 'ANA';
$obj->from = 'NRT';
$obj->to = 'JFK';
$obj->save();
```
これで以下のようなデータが挿入されます。

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|
|1|2019-01-01|NH01|ANA|NRT|JFK|

##Read
次にテーブルからデータを取得しましょう。
ここでは以下のようなテーブルを想定します。

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|
|1|2019-01-01|NH01|ANA|NRT|JFK|
|2|2019-01-02|JL01|JAL|HND|LHR|

例えばID=2のものを取得したいときは以下のように書きます。

```php
$obj = App\Flight::where('id',2);
```
たったこれだけです。
このあと、例えば

```php
echo $obj->name; //「JL01」と出力される
```
のように利用すればOKです。

さらに

```php
$flights = App\Flight:all();
foreach($flights as $flight) {
    echo $flight->company."\n"; //ANA JALと出力される
}
```
みたいなことも可能です。

##Update
続いてアップデートしてみましょう。

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|
|1|2019-01-01|NH01|ANA|NRT|JFK|
|2|2019-01-02|JL01|JAL|HND|LHR|
例えばid=1のtoを変えたい、ときは以下のようにします。

```php
$obj = App\Flight:where('id', 1);
$obj->to = 'DWC';
$obj->save();
```
するとテーブルは以下のようになります。

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|
|1|2019-01-01|NH01|ANA|NRT|JFK|
|2|2019-01-02|JL01|JAL|HND|DWC|

簡単ですね。Createのnewがないだけです。

##Delete
最後に消しましょう。
ここではdatetime >= 2019-01-01を削除します。

```php
$obj = App\Flight::where('datetime','>=', '2019-01-01');
$obj = delete();
```
こうすることで

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|

となります。where句をこのように使うこともできるわけですね。
他にも

```php
$obj = App\Flight::find(1);
$obj = delete();
```

とすることで

|id|datatime|name|company|from|to|
|:-----|:-----|:-----|:-----|:-----|:-----|
|2|2019-01-02|JL01|JAL|HND|DWC|

となります。主キーの場合find句を使えばwhere句よりも楽です。

#終わりに
Eloquentはとても便利なものです。ここに書いてあることはあくまで触りです。
詳しくは
[Laravel 5.7 Eloquent：利用の開始](https://readouble.com/laravel/5.7/ja/eloquent.html)
[Eloquent をおさらい](https://qiita.com/shosho/items/5ca6bdb880b130260586)
を御覧ください。
ShellでWindows PathをLinux Pathに変換(WSL)

## なぜやる
docker-composeのvolumeパラメータは、WSLの形式しか受け付けないから

## どうやる
`sed`コマンドで実現する、テスト用コマンドは下記のようです。

```shell
$ echo "c:/Project/test" \
 | sed -E 's/^(\w+)+/\L\1/g' \
 | sed -e 's/\\/\//g' \
 | sed -e 's/://g' \
 | sed -e '/^\//!s/^/\//g'
/c/Project/test
```
- `sed -E 's/^(\w+)+/\L\1/g'`
  - 頭文字を小文字
- `sed -e 's/\\/\//g'`
  - [\] を [/] に変換
- `sed -e 's/://'`
  - [:] を削除
- `sed -e '/^\//!s/^/\//g'`
  - [/]から始まるではない場合、先頭に[/]を追加
 

## どうつかう
```func.sh
#!bin/bash
  
wsl() { echo "$(echo "$1" | sed -E 's/^(\w+)+/\L\1/g' | sed -e 's/\\/\//g' | sed -e 's/://' | sed -e '/^\//!s/^/\//g')"; }

# quotes are necessary:
r=$(wsl 'C:\Project\test');

echo "$r";
```
```shell
$ sh func.sh
/c/Project/test
```
【Swift】"Add New Constraints"が出来ない時の対応

# 環境
・Xcode11.2
・Swift5.1.2

# 出現パターン
まだ詳しくは分かってません。
.xib上で上下左右とのマージン入力欄と上下左右を選択する部分が非活性になっています。

![スクリーンショット 2019-11-11 18.31.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11800/6231a3a1-fc8c-74b3-2795-d882ec164e98.png)

# 対応策
`Size Inspector` 上で `Translates Mask Into Constraints` から `Automatic` に変更します。

![スクリーンショット 2019-11-12 11.09.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11800/a2d73e5e-e720-d2e8-a2f2-d88986eda970.png)

# 備考
詳しくわかり次第追記します。

何か分かる人がいらっしゃいましたらコメントで教えていただけますと幸いです。
SidekiqとResqueとの互換性 [翻訳]

# SidekiqとResqueとの互換性

最終更新 2019/02/20 編集者 Mike Perham

Resqueを既に使用しているユーザーがSidekiqを簡単に試すことができるように、Sidekiqを可能な限りResqueと互換性のあるものにしようとしています。

- Sidekiqは、Resqueとまったく同じメッセージ形式をRedisで使用するため、同じメッセージを処理することもできます。

- このため、ResqueのクライアントAPIはSidekiqが処理するためのメッセージをRedisにプッシュすることができます。

Sidekiqでは、ワーカーがスレッドセーフである必要があるため、若干異なるワーカーAPIが必要です。
Resqueは、performメソッドがクラスメソッドであると想定しています。これは、Sidekiqのマルチスレッド環境では非常に危険です。（例えば、クラスインスタンス変数が事実上グローバル変数になってしまいます）

Resqueの場合：

```ruby
class MyWorker
  def self.perform(name, count)
    # do something
  end
end
```

Sidekiqの場合：

```ruby
class MyWorker
  include Sidekiq::Worker
  def perform(name, count)
    # do something
  end
end
```

大きな変更ではありませんが、ワーカーの作成がより簡単で直感的になっています。

## クライアントAPI

Sidekiqには、ジョブをキューにプッシュするためのResqueと同一のAPIがあるため、プロジェクトで簡単に検索および置換できます。

Resqueの場合：

```ruby
Resque.enqueue(MyWorker, 'bob', 1)
```

Sidekiqの場合：

```ruby
Sidekiq::Client.enqueue(MyWorker, 'bob', 1)
# 下記のコードと同じです。
MyWorker.perform_async('bob', 1)
```

`Sidekiq::Client` にはResqueの `resque-scheduler` との互換性のための `enqueue_in` もあります。

## パフォーマンス

resqueおよびdelayed_jobはどちらもシングルスレッドプロセス設計を使用しており、これはスレッドベースと比較して非効率です。Sidekiqは通常、桁違いに高速です。

## 機能性

Sidekiqには、そのままの状態でResqueよりも多くの機能が含まれています。例えば、Sidekiqには、resque-scheduler、resque-web、resque_mailer、resque-retryのほとんどの機能がgemに含まれており、それらの機能を使用するためのカスタム構成はほとんど必要ありません。

## プラグイン

Sidekiqは、Resqueのコールバックベースのプラグインをサポートしていません。ジョブの処理に関するコードを実行する独自のフックを登録するための[Middleware](https://github.com/mperham/sidekiq/wiki/Middleware) APIを提供します。

## 制限事項

ResqueクライアントAPIでキューに入れられたジョブには、ペイロードに再試行のためのパラメーターがありません。
これは、失敗したジョブは自動的に再試行されないことを意味します。再試行機能が適切に動作するようにSidekiq APIを使用してコードを移行してください。

## Redis

Resqueでネームスペースを使用している場合は、同じネームスペースを使用するようにSidekiqを構成してください。
そのためには、下記のコードを sidekiq.rb に追加します。

```ruby
# Add gem 'redis-namespace' to your Gemfile too
Sidekiq.configure_client do |config|
  config.redis = { namespace: 'resque' }
end
Sidekiq.configure_server do |config|
  config.redis = { namespace: 'resque' }
end
```
ShellScriptでじゃんけんゲームを作成

## この記事の目的
 - ShellScriptの学習
 - じゃんけんゲームのロジックのサンプルとして共有
 - 他にいいロジックがあるか知りたい
 - じゃんけんゲームを始めて作ったので振り返ってみる

## やりたいこと
 - じゃんけんゲームをShellScript(Bash)で実装
 - 対話式でじゃんけんを行う
 - コンピュータ側の手はランダムで決定
 - 先取制にする（ex.３回戦だったら２勝でじゃんけん終了）

> 参考にさせていただいた問題
  http://g-network.boo.jp/wiki/2018/02/post-909/

### 実行環境
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)

### ソース

```bash
#!/bin/bash
readonly GAME_TIMES=5       #何本勝負か
readonly FIRST_TO_GET_CNT=$((${GAME_TIMES} / 2 + 1)) #先取数

#手の数字を名前に変換する
handcode_to_name () {
  case $1 in
    0) echo “グー” ;;
    1) echo “チョキ” ;;
    2) echo “パー” ;;
  esac
}

game_count=1                #現在何番戦か
player_win_cnt=0            #プレイヤー勝利数
cpu_win_cnt=0               #CPU勝利数
aiko_flg=false              #あいこかどうかのフラグ

#処理開始
echo "じゃんけんを開始します。${GAME_TIMES}本勝負、${FIRST_TO_GET_CNT}勝先取です。"
sleep 2

#勝負本数まで かつ プレイヤー/CPUが勝数先取するまでループする。
while [ ${game_count} -le ${GAME_TIMES} -a \
        ${player_win_cnt} -lt ${FIRST_TO_GET_CNT} -a \
        ${cpu_win_cnt}    -lt ${FIRST_TO_GET_CNT} ]; do
 if ! ${aiko_flg}; then
    echo "${game_count}回戦目です"
    sleep 2
  fi
  echo "数字を選んでください。 0:グー 1:チョキ 2:パー"

  is_vaild_player_hand=false
  loop_cnt=0
  # プレイヤーの手を読み取る
  while [ ! $is_vaild_player_hand -o ${loop_cnt} -eq 0 ]; do
    read input
    if [[ ! ${input} =~ ^[0-2]$ ]]; then
      echo "0 1 2のいずれかの数字を入力してください。"
      is_vaild_player_hand=false
      continue
    fi
    is_vaild_player_hand=true
    loop_cnt=$(( ${loop_cnt} + 1 ))
  done

  player_hand=${input}
  cpu_hand=$(($RANDOM % 3))
  echo
  sleep 2

  # 勝敗判定
  if [ ${player_hand} -eq ${cpu_hand} ]; then
    echo "あなたの手は`handcode_to_name ${player_hand}`でした。"
    echo "コンピュータの手は`handcode_to_name ${cpu_hand}`でした。"
    echo "あいこなので再選択してください。"
    echo
    aiko_flg=true
    continue
  elif [ $(((${player_hand} - ${cpu_hand} + 3) % 3)) -eq 2 ]; then
    echo "あなたの手は`handcode_to_name ${player_hand}`でした。"
    echo "コンピュータの手は`handcode_to_name ${cpu_hand}`でした。"
    echo "あなたの勝ちです"
    player_win_cnt=$((${player_win_cnt} + 1))
    game_count=$((${game_count} + 1))
    aiko_flg=false
  elif [ $(((${player_hand} - ${cpu_hand} + 3) % 3)) -eq 1 ]; then
    echo "あなたの手は`handcode_to_name ${player_hand}`でした。"
    echo "コンピュータの手は`handcode_to_name ${cpu_hand}`でした。"
    echo "あなたの負けです"
    cpu_win_cnt=$((${cpu_win_cnt} + 1))
    game_count=$((${game_count} + 1))
    aiko_flg=false
  fi

  echo "現在${player_win_cnt}勝${cpu_win_cnt}敗"
  echo
  sleep 2
done

echo "あなたは${GAME_TIMES}回中${player_win_cnt}勝ちました。"

#${player_win_cnt} > ${cpu_win_cnt}
if [ ${player_win_cnt} -gt ${cpu_win_cnt} ]; then
  echo "${player_win_cnt}勝${cpu_win_cnt}敗であなたの勝ちです！"
elif [ ${player_win_cnt} -eq ${cpu_win_cnt} ]; then
  echo "${player_win_cnt}勝${cpu_win_cnt}敗で引き分けです"
else
  echo "${player_win_cnt}勝${cpu_win_cnt}敗であなたの負けです..."
fi
```

## 苦労した点や感想など
 - 勝敗判定は(自分の手 - 相手の手 + 3) % 3で実装した[^1]
 - まだ比較演算子の書き方が慣れない...
 - bool値の比較方法と正規表現に苦戦


[^1]: https://qiita.com/mpyw/items/3ffaac0f1b4a7713c869