OmniAICreator/Qiita-1.07M huggingface dataset:
CircleCIでdotfilesリポジトリのコード品質管理する

最近は投稿していなかったので、久しぶりとなります。
2013~2016年はゲームプログラマーでしたが、2017年からサーバーサイド業務するようになりました。
ここ一年半はvim設定ファイルのカスタマイズに熱を入れてましたね。

### dotfilesの設定ファイルが増えてきたのでコード品質を維持したい
vim設定ファイルが1000行を超えて肥大化、shellファイル、zsh設定のファイルが増えてきたのでコード品質を保つ必要があるなと思いました。
今まではローカルのDockerコンテナを起動してパッケージが正常にインストールできているかテストしていました。
簡単な修正ならローカルのコンテナで確認せず、リモートで確認できたら便利だなと思いました。
CircleCIがお手軽そうなのでこちらを使います。（無料プラン）

## 出来たこと
#### コミット単位でコード品質を可視化できるようになった！
CircleCIの設定は2~3時間ででき、思ったより簡単にできました！
ビルド成功させるまでに10時間ぐらいかかりました。今まではエラーが出ても手作業でコマンド実行していた箇所を修正する必要がありました。
緑のチェックがビルド成功で赤のバツが失敗です。黄色がビルド中。
リポジトリ　https://github.com/rainbow23/dotfiles
![Screen Shot 2019-01-14 at 22.18.40.png](https://qiita-image-store.s3.amazonaws.com/0/12294/71705a80-6f2a-55ac-5cd1-11f0bad5e739.png)

#### CircleCI管理画面
ビルドも５分くらいでPC環境のビルドより少し早い
![Screen Shot 2019-01-14 at 22.18.54.png](https://qiita-image-store.s3.amazonaws.com/0/12294/9d43dd13-8094-0ce6-a218-307bbda9f355.png)

## 準備
#### dockerイメージの用意
dotfilesリポジトリで必要なパッケージが含まれたDockerfileを作成
vim8, tmux, zsh等が動作する環境。
パスワードなしでSudoできるユーザーも作成している
https://github.com/rainbow23/dotfiles/blob/develop/docker/base/Dockerfile

#### CircleCIからDockerイメージを使えるようにDockerHubにpushする
https://hub.docker.com/r/rainbow23/base_dotfiles

#### CircleCI設定ファイルを作る
https://github.com/rainbow23/dotfiles/blob/develop/.circleci/config.yml
`- image: rainbow23/base_dotfiles:latest`がDockerHubにアップロードしたDockerイメージ
`- run: `の後ろにテストしたいファイルを記述 runにある5つのシェルが全て成功したらCircleCIのビルド成功になります。

```　.circleci/config.yml
version: 2
jobs:
  build:
    docker:
      # specify the version
      - image: rainbow23/base_dotfiles:latest
    working_directory: /home/rainbow23/dotfiles
    steps:
      - checkout
      #deploy
      - run: ./symlink.sh
      # install
      - run: ./install_python.sh
      - run: ./install_vim.sh
      - run: ./install_tools.sh
      - run: ./gitclone_list.sh
```
CircleCI管理画面でconfig.ymlのrunで記載したシェルファイルの実行結果が見れます。
![Screen Shot 2019-01-14 at 23.11.45.png](https://qiita-image-store.s3.amazonaws.com/0/12294/8d9876d0-b5aa-c9a8-1b1d-6b470383d841.png)


## まとめ
コミットごとにリポジトリのコード品質が可視化できたのでよかったです。
これから各ファイルをフォルダに整理する予定なのでデグレードしていないか確認できるのが嬉しいですね。
次回はvimの便利プラグインの記事を書く予定です。
M5StackでBLE忘れ物防止タグを作成する

# はじめに
M5Stackを入手してサンプルコード等を色々見ていたのですが、ライブラリを使うとBLEデバイスが簡単に作れそうだったので、お試しで作ってみました。

#開発環境
Visual Studio Code+PlatfomIOを使っています。
ライブラリは"M5Stack", "ESP32 BLE Arduino"をインストールします。

#コード作成
今回、M5Stackをペリフェラルとして使用するため、"ESP32 BLE Arduino"のサンプルコードの"BLE_uart", "BLE_server"あたりのコードを参考にしました。
作成したコードはGitHubにおいています。
<https://github.com/SatoshiTakahama/M5StackBLEtag>

#動作確認
動作確認のためにセントラル側が必要になるのですが、今回、スマホ(Android)上のブラウザ(Chrome)から、WebBluetoothを実行することによりセントラル側としました。
以下のページに、WebBluetoothのサンプルコードがあるのですが、
<https://googlechrome.github.io/samples/web-bluetooth/index.html>
ここから、Link Lossを選択し、
<https://googlechrome.github.io/samples/web-bluetooth/link-loss.html>
"Get Bluetooth Device Alart level"のボタンを押下すると、周囲にあるデバイスが表示されるので"M5StackTag"を選択し、"ペア設定"のボタンを押下します。
次に、セットするAlart levelを選択してから"Set Alart level"のボタンを押下すると、M5Stackが忘れ物防止タグとしての動作を開始します。この状態で、Link Loss(Disconnect)が発生すると、M5Stackのスピーカーが鳴りだします。以下は、動作確認したときのスマホの画面です。
![Screenshot_20190114-230516.png](https://qiita-image-store.s3.amazonaws.com/0/215278/32823b54-a603-32d1-d98d-610900caba53.png)
railsでmigrationする

備忘録として記事を書く
##データベースの作成
configファイルのdatabase.ymlにデータベース情報が入っているので編集する。
編集した後

```terminal
$  rake db:create
```
を行うとデータベースが作成される。

##テーブルの作成

```terminal
$ rails g migration Createテーブル名
```
上記のコマンドを入力すると、db/migrate/にファイルが生成される。
このファイルを編集していく。

```20190114081919_create_テーブル名.rb
class Createテーブル名 < ActiveRecord::Migration
  def change
    create_table :テーブル名 do |t|
    	t.string :type #string型
    	t.string :title, null: false #string型　null値はだめ
        t.integer :number ,default: 0 # int型　デフォルトで0を代入
        t.float : float_num #float型
        t.text :body #text型
    end
  end
end
```

保存した後に

```terminal
$ rake db:migrate
```

###カラム名を変更する

```terminal
$  rails g migration rename_カラム名_columns_to_テーブル名
```

作成されたmigrationファイルを編集する

```migration.rb
rename_column :テーブル名, :カラム名, :変更後カラム名
```
保存した後に

```terminal
$ rake db:migrate
```

##まとめ
他のmigrationを利用するときに、どんどん追記していきます.
【PHP】microtimeでミリ秒を取得するときの注意点

## はじめに
- やりたかったこと  
「20XX-XX-XXXX XX:XX:XX.SSS」みたいに現在日時を取得したかった（ミリ秒の部分は必ず3桁にしたかった）
- 結果  
なぜか桁数が崩れたりしてた


## microtime関数でミリ秒取得する処理
```php
$a = microtime(true);      // 「タイムスタンプ.マイクロ秒数」を取得します。例）1547472200.102094
$array = explode(".", $a); // $array[0] = "1547472200" $array[1] = "102094"
$msec = substr ( $array[1] , 0 , 3 ); //  ミリ秒取得
```
検索して見つけたコードを見つけてそのまま使ってました。
この場合、戻り値がfloatとなり、小数点以下がマイクロ秒数となります。
あとはsubstrをつかって、小数点以降の3桁を取得すればミリ秒が取得できます。

が・・・

## microtime関数の注意点
phpマニュアルちゃんと見れば気づくんですが、
この関数は引数がtrueだとfloat型で返すようになります。

つまり、

```php
$a = microtime(true);      // 「タイムスタンプ.マイクロ秒数」を取得します。例）1547472200.10
$array = explode(".", $a); // $array[0] = "1547472200" $array[1] = "10"
```

というパターンも起こりえます。
桁数に指定がなければこれでいいですが、
これだとミリ秒を絶対3桁で取得したい場合、substrつかっても3桁にはならないですよね。

きっちり3桁の文字列にして返したい場合は右を0埋めするとか

```php
$a = microtime(true);
$array = explode('.', $a);
$msec = str_pad(substr($array[1],0,3) , 3, "0");
```
Dateのformatで「v」を指定してあげるとかが考えられます。(PHP7.0以降)

```php
// DateTimeオブジェクト使うやり方
$datetime = new DateTime();
$msec = $datetime->format('v');
```
※ただし、formatで「v」を指定するとミリ秒が0になります。

## 最後に
他にもっといい方法があると思いますが、今回はこういう実装をしてました。
そもそもミリ秒をきっちり3桁になるように取得するという処理がよくつかわれるものなのか疑問ですが・・・
みなさんもプログラムを書くときには型に気を付けましょう・・・
PHPの高速化についての調査

PHPの高速化が気になってしまったので調べてみた。

プログラミングでは、実行速度を向上させたいときJITコンパイラを使う。

#JITとは

JITコンパイルは「Just In Time」の略語で
コードが実行されるその時にコンパイルする。
これにより実行速度向上を図れる。

PHPではJIT技術はまだ直接採用されておらず、
JIT技術を採用したPHP実行環境としてHHVM（HipHop Virtual Machine）がある。

ちなみにHHVMはFacebookが開発しておりC++で実装されているようです。

HHVMはPHP5のコードを動かすことで高速化の恩恵を得ていたが
PHP7ではHHVMを利用することは推奨されていないようです。

これは、PHP7で十分速いのでHHVMを使用するメリットが無いからでしょう。

#速度検証実験

[PHP 7.0 vs. HHVM 3.10 Performance Tests](https://www.phoronix.com/scan.php?page=article&item=php7-hhvm310-perf)
にてPHP5.5、PHP5.6、PHP7.0、HHMV3.10の比較実験が紹介されている。

この結果だとPHP7.0が実行速度の面では最速という事実がわかる。
しかし、メモリの使用量に関してはまだHHVMが少なく
HHVMに軍配が上がるといったところだ。

しかし、PHP7.0は過去のヴァージョンよりも速度、メモリの使用量共に
優れているので最新版を使用するのがベストであろう。

現時点では、PHP8.0でJITが実装されるのではないかと期待されているので
さらなる高速化が将来できるかもしれない。

#文献
[PHP 7.0 vs. HHVM 3.10 Performance Tests](https://www.phoronix.com/scan.php?page=article&item=php7-hhvm310-perf)
[PHP7 と HHVM/Hack 言語って何が違うの？](https://www.infiniteloop.co.jp/blog/2018/07/difference-between-php7-and-hhvm-hack/)
MIMEタイプMediaタイプContentタイプ の違いをきちんと理解する

MIMEタイプ?? Mediaタイプ?? Contentタイプ?? 　同じような意味でよく理解できていないので違いとかを詳しく調べてみました。
# MIMEタイプとMediaタイプ違いは？

MIMEタイプとMediaタイプは同じ意味合いで、
> ファイルやインターネット上で転送されるコンテンツの形式を表現する識別子である
[Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%87%E3%82%A3%E3%82%A2%E3%82%BF%E3%82%A4%E3%83%97)

という理解で問題なさそうです。

Mediaタイプの登録申請について書かれた[ドキュメント](https://tools.ietf.org/html/rfc1590
)を見てみると `These types, previously called "MIME Types", are now called "Media Types".`とあるので、昔はMIMEタイプと呼ばれていたのが、いまはMediaタイプと呼ばれるように変わったようです。
今だよくMIMEタイプと呼ばれることもありますが、Mediaタイプと呼ぶのが公式なようでした。歴史的な経緯を書いた正式なドキュメントは見つけられなかったのですが、MIMEタイプはMultipurpose Internet Mail Extensionsの略でメール規格を拡張するものであったのが、
HTTPなど多目的に使われるようになり、いまはMediaタイプと呼び名が変わったのではないかと思います。


## Contentタイプ と MIMEタイプ（Mediaタイプ）の違いは？
ContentタイプはHTTPヘーダーのフィールド名です。MIMEタイプを指定するために使用され、以下のようなフォーマットでHTTPのヘッダーに追加されます。

```
Content-Type: text/html; charset=utf-8
Content-Type: multipart/form-data; boundary=something
```
用途として分かりやすいのは、ブラウザーがURLにアクセスした際に、MIMEタイプによってコンテンツの処理が変わります。`text/html`であればブラウザーでHTMとしてレンダリングしたり、`application/pdf`であればPDF表示用にユーザーが登録しているPDFリーダーを起動したりします。

# Mediaタイプはどんな種類があるの？
Mediaタイプは`トップレベルタイプ名 / サブタイプ名`で登録されています。

* トップレベルタイプには`application、audio、example、font、image、message、model、multipart、text、video`があります。

* サブタイプ名が`vnd`で始まるのはベンダー特有のタイプで例えば、マイクロソフトワードの`.docx`形式は`application/vnd.openxmlformats-officedocument.wordprocessingml.document`で登録されていました。

* サブタイプ名が`prs`で始まるのは、市販されていないもので、個人的な用途？で使われるようです。良い例がなかったのですが、NTTコミュニケーションの[メールサーバー](https://www.ntt.com/business/services/cloud/rental-server/biz/function/mimetype.html)には`application/prs.cww`というのが登録されているようです。サブタイプ名を調べてみると[CU-Writer](http://www.fileformat.info/info/mimetype/application/prs.cww/index.htm)というソフトで申請されているようですがちょっとなんのソフトか分かりませんでした。

# メディアタイプって誰が決めてるの？

IPアドレスとかプロトコル番号の管理をしているIANAさんです。

メディアタイプの一覧はIANAさんが公開していますね。
https://www.iana.org/assignments/media-types/media-types.xhtml
最近のアップデートが2019-01-08なので結構アクティブに更新されているみたい。

# どうやったらメディアタイプって登録できるの？

申請することは一生なさそうですが、以下のフォーマットで申請した後に[色々とレビュー](https://tools.ietf.org/html/rfc1590)を経た上で正式に認定されなければいけないようです。

```
==================================================================

      To:  IANA@isi.edu
      Subject:  Registration of new Media Type content-type/subtype

      Media Type name:

      (If the above is not an existing top-level Media Type, please
      explain why an existing type cannot be used.)

      Media subtype name:

      Required parameters:

      Optional parameters:

      Encoding considerations:

      Security considerations:

      Published specification:

      (The published specification must be an Internet RFC or RFC-to-be
      if a new top-level type is being defined, and must be a publicly
      available specification in any case.)

      Person & email address to contact for further information:

      ==================================================================
```
Windowsタスクスケジューラでスタートアップ起動しない場合の対処法

タスクスケジューラのタスクを登録する際、トリガーに「スタートアップ時」を指定したが、なぜか実行されない。再起動時には動作し、シャットダウン時には動作しなかったのではまった時のメモ。

#使用した環境
 - Windows10 Pro 64bit
 - バージョン 10.0.17134
 - ビルド 17134
 
#ポイント
- 原因は「高速スタートアップ」
- 無効化することで現象改善
- タスクの実行履歴には起動したログなし（失敗ログもなし）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/340432/04379900-64d5-2e17-4220-3abfe2f6dff3.png)


#参考リンク
https://social.technet.microsoft.com/Forums/ie/ja-JP/2b2c316d-ffb2-4db4-afc8-833e36c90a6c/12479124731246312473124651247212517125401252112398124731247912?forum=w8itpro

https://answers.microsoft.com/ja-jp/windows/forum/all/%E3%82%BF%E3%82%B9%E3%82%AF%E3%83%9E%E3%83%8D/a60f70ca-e7df-47b1-a22c-a0d0560daf98

#エピソード
もともとやりたかったことは、システム起動時にIPアドレスをLINEに飛ばすこと。プログラム自体は動作し、タスクを手動で実行すると動作する。トリガーの設定を定時実行にした場合は意図した通り動作するので、なぜ動作しないのかはまった。再起動では動作するので、再起動とシャットダウンのキーワードも入れて検索していたら上記参考資料のページを見て解決。
DebianのCloud Imageの作り方

Debianの公式のCloud Imageは https://cdimage.debian.org/cdimage/openstack/ で配布されているが、自分でカスタマイズしたものを使いたい。毎回忘れて作り方を調べているので作り方をここに記す。

OpenStack用のCloud Imageの作り方は https://docs.openstack.org/ja/image-guide/create-images-automatically.html にまとまっているが、今回はやりたいことができて一番シンプルなopenstack-debian-imagesを使う。

# どうカスタマイズするか

* KVM上で動かすので`qemu-guest-agent`を入れる
* `fish`をログインシェルにする
* ログイン画面にIPアドレスを表示する

# やり方

Debianが動いているマシンにopenstack-debian-imagesをインストールする。

```shell-session
# apt install -y openstack-debian-images
```

`openstack-debian-images`では`hook-script`としてビルド時に実行されるスクリプトを指定できる。`/root/hook-script.sh`として次のファイルを用意しておく。実行権限をつけるのも忘れずに。

```shell
#!/bin/bash

set -e

# ログイン画面にIPアドレスを表示
cat << 'EOS' > ${BODI_CHROOT_PATH}/etc/issue
Debian GNU/Linux 9 \n \l
eth0: \4{eth0}, \6{eth0}
EOS

# ログインシェルをfishに変更
chroot ${BODI_CHROOT_PATH} chsh -s /usr/bin/fish debian
```

このファイルをもとに次のコマンドでCloud Imageをビルドする[^1]。他に入れたいパッケージがある場合は`--extra-packages`に指定する。

[^1]: manでは`--release`に指定できるのはwheezyかjessieだけと書いてあるが、少なくとのバージョン1.20~deb9u2ではソースコードを見る限りwheezyとjessieに加えて、stretchとbusterも指定できるようである。

```shell-session
# build-openstack-debian-image --release stretch \
  --hook-script /root/hook-script.sh \
  --extra-packages qemu-guest-agent,less,vim,bzip2,curl,wget,fish,man
```

完成。
ドラゴンボールの孫悟空の言葉に変換するLineBotをつくってみた

## はじめに
孫悟空の言葉遣いって独特ですよね。
そんな悟空の言葉に変換するLINEBotを作りました。
悟空になりたいときに使ってみてください。

以下のサイトで孫悟空のしゃべり方(野沢けぇ)について解説しています。今回はこちらをDialogFlowに実装します。
http://junk.hatenablog.jp/entry/2018/02/15/034507

ほんじゃ、いっちょやってみっかぁ！

## 開発言語
・Javascript

## 準備
アカウントを用意します。
・Dialogflow Console
  https://console.dialogflow.com/

・LINE Developers(プロバイダーリスト)
  https://developers.line.biz/console/

## LINEとDialogflowの連携
こちらの記事を参考にしました。
https://qiita.com/poruruba/items/09563e251adef1e1e8af
DialogFlowのFulfillmentに悟空語(野沢けぇ)を実装します。

## DialogFlowのFulfillmentの中身
全探索で、条件を満たす場合に変換します。もっと賢い方法があれば教えてください。

```javascript:gokuu.js
function nozawa(agent) {
    let temp;
    let list = [];
    let i = 0;
    let j = 0;
//Lineから受け取ったパラメータをeventに保存する
    let event = agent.parameters['any'];
//string型からstr型を要素とする配列へ変換する
    for(i = 0; i < event.length; i++){
        temp = event.substr(i, 1);
        list.push(temp);
    }
//for文を回すときにout of rangeを防ぐために'ん'を追加する
    list.push('ん');

    let a1 = [['あ', 'ア'], ['か', 'カ'], ['さ', 'サ'], ['た', 'タ'], ['な', 'ナ'], ['は', 'ハ'], ['ま', 'マ'], ['ら', 'ラ'],
            ['が', 'ガ'], ['ざ', 'ザ'], ['だ', 'ダ'], ['ば', 'バ'], ['ぱ', 'パ']];
    let a2 = [['や', 'ヤ'], ['わ', 'ワ']];
    let ie = ['い', 'え', 'イ', 'エ'];
    let e = [['え', 'エ'], ['け', 'ケ'], ['せ', 'セ'], ['て', 'テ'], ['ね', 'ネ'], ['へ', 'へ'], ['め', 'メ'], ['れ', 'レ'], 
            ['げ', 'ゲ'], ['ぜ', 'ゼ'], ['で', 'デ'], ['べ', 'ベ'], ['ぺ', 'ペ']];

//for文で探索し、条件を満たすときに野沢けぇへ変換する
    for(i = 0; i < list.length; i++){
        for(j = 0; j < a1.length; j++){
            if((list[i] == a1[j][0] || list[i] == a1[j][1]) && (list[i+1] == ie[0] || list[i+1] == ie[1] || list[i+1] == ie[2] || list[i+1] == ie[3])){
            list[i] = e[j][0];
            list[i+1] = 'ぇ';
            }
        }
        for(j = 0; j < a2.length; j++){
            if((list[i] == a2[j][0] || list[i] == a2[j][1]) && (list[i+1] == ie[0] || list[i+1] == ie[1] || list[i+1] == ie[2] || list[i+1] == ie[3])){
            list[i] = e[j][0];
            list[i+1] = 'ぇ';
            }
        }
        for(j = 0; j < e.length; j++){
            if((list[i] == e[j][0] || list[i] == e[j][1]) && (list[i+1] == ie[0] || list[i+1] == ie[1] || list[i+1] == ie[2] || list[i+1] == ie[3])){
            list[i+1] = 'ぇ';
            }
        }
        for(j = 0; j < e.length; j++){
            if((list[i] == e[j][0] || list[i] == e[j][1]) && list[i+1] == 'ー'){
            list[i+1] = 'ぇ';
            }
        }
    }
//'ん'を削除する
    list.pop();
//str型の配列からstring型へ結合する
    let list_changed = list.join('');
//Lineへ出力する
    agent.add(list_changed);
}
```

## 使い方
ひらがなとカタカナに対応しています。漢字は変換できません。今後の課題です。
LINEで「孫悟空Bot」と検索してみてください。孫悟空Botが追加できます。

## デモ
![47994.jpg](https://qiita-image-store.s3.amazonaws.com/0/315028/1a24c515-0dd9-7272-310b-12cb2089d3de.jpeg)

## まとめ
まだまだプロトタイプです。例えるならば、亀仙人のもとで修行を積んでいる頃の悟空でしょうか。
https://qiita.com/kotauchisunsun/items/8334728ab66b3cc3e55f
こちらの記事のやり方も実践していきたいです。根本的な手法が異なるので構想を練り直すのも一つの手です。
機械学習は素材が必要なので、孫悟空の素材が十分あれば作れそうですね。
ksnctf 22 Square Cipher 60pt

#問題

https://ksnctf.sweetduet.info/problem/22

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/d573c4c8-d44e-1efe-b95f-e1ae219d8272.png)


#解いてみた

Square（正方形）と言ってる割にかなり縦長。
と思って数えてみたら縦横どちらも31文字でした。

base64風ではあるものの以下の理由から違うようです。

- どの行末にも=がない。（必ずあるわけではないが31個もあれば1つくらいありそう。）
- 数字が1つもない。（これもかならずあるわけではないけど、かなりの確率。）

FLAGとかの文字から法則を探そうと思っても特に見つかりませんでした。

とっかかりとして大文字か小文字かくらいしかなくて、最初の行と最後の行、最初の文字と最後の文字が全部小文字になってるのもなんかありそう。
なので大文字を抽出してみても特に文章になったりはしてませんでした。

場所が関係しているのかもしれないので、Excelに貼って大文字だけ色を付けてみました。

```
=EXACT(Sheet1!A1,UPPER(Sheet1!A1))
```

計算式はこれで大文字ならTrue、小文字ならFalse。
そのあとにTrueに色を付ければできます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/99624ac5-62e1-f03e-c7a8-70308d5b15a0.png)

いい感じにQRコードになりました。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/17681/d598a181-6d5d-25fd-352a-0df5fe83cff5.png)
gitのブランチを正規表現でマッチしたものだけ一括削除

gitの機能として、複数ブランチの一括削除はできない。

なので、わたしは正規表現で、ブランチ名をマッチさせて、マッチしたブランチを確認した上で、削除するようにしている。
それのbashscriptが下記の通りで、わたしは、~/.bash_profile に追加して利用している。

# script (bash)

```bash: 

function rmbranch () {
    if [ -z "$1" ] ; then
        echo -e "ブランチ名を正規表現で入力してください. \nex)\n\$ rmbranch feature/practice.+"
        return 1
    fi

    rmTargets=`git branch | egrep "$1"`

    if [ -z "$rmTargets" ] ; then
        echo "削除対象ブランチがないため処理を終了します."
        return 0
    fi

    echo "削除対象ブランチ:"
    echo $rmTargets
    echo "----------------------------"
    echo "ブランチ削除を実行しますか?"
    echo "  実行する場合は y、実行をキャンセルする場合は n と入力して下さい."
    read input

    if [ -z $input ] ; then

        echo "  y または n を入力して下さい."
        rmbranch

    elif [ $input = 'yes' ] || [ $input = 'YES' ] || [ $input = 'y' ] ; then

        echo "  削除を実行します."
        git branch | egrep "$1" | xargs git branch -D

    elif [ $input = 'no' ] || [ $input = 'NO' ] || [ $input = 'n' ] ; then

       echo "  処理をキャンセルしました."
       return 1

    else

        echo "  y または n を入力して下さい."
        rmbranch

    fi

    return 0
}
```

# 使い方

例えば、ブランチがこんな感じになっていたとして、 

```terminal:terminal
$ git branch
  feature/practice1
  feature/practice2
  feature/practice3
  feature/practice4
  feature/practice5
* master
```

先頭が `feature/practice` のブランチを全て削除する場合は、下記のように `rmbranch feature/practice.+` とターミナルで入力する。

```terminal:terminal
$ rmbranch feature/practice.+
```

すると、削除対象のブランチが表示される。

```terminal:terminal
削除対象ブランチ:
feature/practice1 feature/practice2 feature/practice3 feature/practice4 feature/practice5
----------------------------
ブランチ削除を実行しますか?
  実行する場合は y、実行をキャンセルする場合は n と入力して下さい.
```

ここで、`y` を入力すると、削除対象ブランチが削除される。

```terminal:terminal
$ rmbranch feature/practice.+
削除対象ブランチ:
feature/practice1 feature/practice2 feature/practice3 feature/practice4 feature/practice5
----------------------------
ブランチ削除を実行しますか?
  実行する場合は y、実行をキャンセルする場合は n と入力して下さい.
y
  削除を実行します.
Deleted branch feature/practice1 (was e83a435).
Deleted branch feature/practice2 (was e83a435).
Deleted branch feature/practice3 (was e83a435).
Deleted branch feature/practice4 (was e83a435).
Deleted branch feature/practice5 (was e83a435).
```


`n` を入力すると、ブランチは削除されない。

```terminal:terminal
# n を入力した場合

$ rmbranch feature/practice.+
削除対象ブランチ:
feature/practice1 feature/practice2 feature/practice3 feature/practice4 feature/practice5
----------------------------
ブランチ削除を実行しますか?
  実行する場合は y、実行をキャンセルする場合は n と入力して下さい.
n
  処理をキャンセルしました.
```
JavaScriptでObjectをマージしたい

#どんな時
 - フレームワークのコンポーネントで、初期値を与える処理をしたい場合。
 - CLASSのconstructorの処理

#何を使うの？
`Object.assign()`を使用する。
＊当然ながら、IEでは使えない.

## 構文
`Object.assign(target, ...sources)`

## 正確にはmergeではないです。
列挙可能なプロパティの値を、ソースObjからターゲットObjにコピーする。
戻り値は、ターゲットObj。

#コード例

##マージのような事
```javascript

const obj01={a:'aaa'};
const obj02={b:'bbb'};

// targetObjの中身は、obj01とobj02のプロパティ。
const targetObj = Object.assign( obj01, obj02);
```

##オブジェクトのコピーのようなこともできます。
```javascript
const objA = {a:'aaa'};
//copyオブジェクトにはobjAのプロパティがコピーされている。
const copy = Object.assign( {}, objA);
```

#参考

https://iwb.jp/javascript-class-constructor-object-assign/
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Object/assign
https://qiita.com/SE-studying-now/items/ecdbc0317ba1806aed61
会社にSlackを導入した話

エンジニア界隈の巷でよく聞くようになったSlack。
私はそのSlcakというものの便利さに感銘を受けました。
そして会社のお偉いさんに言って社内に導入してみたというお話。

自社開発をしているエンジニア会社ですが、今では社員の6割が利用してくれて、これからもどんどん口コミで利用者が増えていくと思います。
そして、とても便利なものが使えて感謝してくれる人が増えてきてとても嬉しいです。

# Slackとは
組織内でのコラボレーション、コミュニケーション促進の為に作られたツールです。
情報が一元化されて、メールやgoogleドライブ等あたふたといろんなアプリを開く必要がなくなります。

https://slack.com/intl/ja-jp/

# 想定読者
- Slackが企業にどんなことをもたらすか知りたい方
- 上から急に言われてこれからSlack使っていこうとしている方
- Slackでなくとも「ツール」や「新しいモノ」を会社に提案・導入させようと思っている方

企業に新しいツールを導入した際にどんな反応がでるか。
どういう風に提案していったか。
自身の経験談を記載していこうと思います。

# なぜ私が導入しようと思ったか
- 今までメールでのやりとりが主だったためコミュニケーションにスピード感がなかった
- 会社の体制上、各自作業場がバラバラでコミュニケーションの機会が少なかった
- メールが単純にめんどくさい

企業の利益のために！！会社のために！！というより、自身が単純にコミュニケーションにわざわざメールを使わないといけないのが面倒に感じた点が大きかったです(LINEに慣れている世代というのもあり)

# 導入の手順
自分が実際に導入した手順です。最初からこの流れで行こうと計画を立てて実施しました。
キーワードは「お偉いさんをまず味方につけること」と「実績を作ること」です。

 1. Slackについて情報収集
 2. 実際にワークスペースを作成
 3. 身近な人にまず導入してもらう
 4. 所属長に提案し部署内展開
 5. 各部署の部長に提案し、他部署に展開
 7. 経営層に提案し理解してもらう
 8. 全社展開
 9. 社内イベントでプレゼン

# 導入時に立ちはだかった壁
- 個人ですべて自分が資料作成、展開をしたため負荷が高かった
- 「チャット」に理解を示さない若くない世代
- セキュリティ問題
- それ導入する意味あるの？ととりあえず批判する層

# 反省点

まず一番がすべて自分でやろうとしたことです。
新しいことを始めるということは誰も知識がない状態で、どうしても有識者が自分だけになってしまいます。
そのため、資料作り方針決め等すべて自分で対応してしまったことです。
今ではチーム運営により作業分担はしていますが、最初からチーム運営すればよかったと反省。

# 導入した結果

- スピーディーなコミュニケーションができるようになった
- どうでもいい雑談も増え、社内の交流が増えた
- 今まで知らなかった社員とも仲良くなれた
- 技術情報など情報の可視化ができた

利用する人たちからはすごく使いやすい！との感想を頂き、実際の業務でも効率化ができているようです。一番良かったのが他の社員との距離を縮められたこと、今まで関わりがなかった人と仲良くなれた事ですね。

# 現在の利用率（週間アクティブユーザー）
![image.png](https://qiita-image-store.s3.amazonaws.com/0/339804/a15281dc-22f3-9699-ae13-2c23a445a914.png)


# まとめ

新しいツールやモノを導入する際にはどうしても理解を示してくれない層がいるのは事実です。
社内に導入してコミュニケーションを効率化させるという目的でしたが、いつのまにか物事に価値を見い出し、その価値を他人を説明していくというビジネスの根幹も学べたと思います。

Slack自体も社員に気持ちよく使っていただき、今や欠かせないツールとなってきました。

この記事を読んだみなさんも是非、Slcakを導入して社内の無駄なメール作業なくし業務改善をし、はやくお家に帰ってゆっくりと充実した人生を送って欲しいなと思います。
Python で jinja2 を使う

# はじめに

jinja2 によるテンプレートを作って、
変数を渡してファイルをベースにレンダリングするまでをまとめとく。
テンプレートファイルの参照方法はいくつかあるが、
ここではEnvironmentを使ってテンプレートを参照する。

# 手順

## パッケージを入れる

```bash
pip install jinja2
```

## a.py を書く

```python
#!/usr/bin/env python
# coding: utf-8
import jinja2
loader = jinja2.FileSystemLoader(searchpath="./")
env = jinja2.Environment(loader=loader)
template = env.get_template('a.txt.j2')
output = template.render(name='John Doe')
print(output)
```

## a.txt.j2 を書く

```jinja2
Hello {{ name }}!
```

## 出力結果

```console
$ cat a.py
#!/usr/bin/env python
# coding: utf-8
import jinja2
loader = jinja2.FileSystemLoader(searchpath="./")
env = jinja2.Environment(loader=loader)
template = env.get_template('a.txt.j2')
output = template.render(name='John Doe')
print(output)
$ cat a.txt.j2
Hello {{ name }}!
$ python a.py
Hello John Doe!
```

# その他

Environment でブロックの開始・終了を制御できそうなので、
テンプレートのレンダリング結果をもとにさらにレンダリングといったこともできそう。

# 参考文献

* http://jinja.pocoo.org/docs/2.10/
* http://jinja.pocoo.org/docs/2.10/intro/#basic-api-usage
* http://jinja.pocoo.org/docs/2.10/api/#loaders
* https://stackoverflow.com/questions/38642557/how-to-load-jinja-template-directly-from-filesystem
Hyper-VにUbuntuのインストールでハマった点

Hyper-VにUbuntuのインストールでハマった点

Windows8 Proのライセンスを持っていたことに気が付き、自宅PCをWindows 10 Proにアップグレードしました。ProということでHyper-V機能を利用してみました。
VMWareやVirtualBoxを利用したことはあってもHyper-Vは初めてです。また、普段はCentOSを利用しているということもあり、Hyper-VとUbuntuの導入で戸惑った点をあわせてメモしておきます。
Hyper-Vの初心者のためよく理解できていないところもありますが、誤りなどあればご指摘ください。

**ハマった点**

* Ubuntuそのものにログインできない
* ホストOSからログインできない 
 
## 環境
* Windows 10 Pro(バージョン 1809)
* Hyper-V
* Ubuntu 18.04.1 LTS(ゲストOS)

## インストール
Ubuntuのインストールはクイック作成機能(2018/9提供機能)を利用しました。
「クイック作成」と呼ぶくらいなのでVMの構築作業は簡単で、数ステップで以下の画面になります。
![00-0.png](https://qiita-image-store.s3.amazonaws.com/0/333432/bb0f8637-5d2f-d792-6c08-1a1b468467ec.png)

[接続]ボタンを押すとUbuntuのインストーラが起動されウィザードでシステム設定します。

* 言語を選択
* キーボード設定
* 地域設定
* ユーザID/パスワードとホスト名の設定
 
![00-02.png](https://qiita-image-store.s3.amazonaws.com/0/333432/efeee3e4-07df-4ba1-3f5a-6bad61963430.png)

ここでは、個人用のテスト環境のため**「自動的にログインする」**を設定しました。


## Ubuntuへのログイン
Ubuntuのインストール後、仮想マシン画面にログイン画面らしきものが表示されます。
![00-03.png](https://qiita-image-store.s3.amazonaws.com/0/333432/4589e801-e332-0c0f-0e32-a468eb13f7fe.png)

さきほど設定したユーザ名とパスワードを入れると、なぜか「セッションの接続が解除されました」と表示されログインに失敗します。
![I3-2100 上の Ubuntu 18.04.1 LTS  - 仮想マシン接続 2019_01_14 20_34_55.png](https://qiita-image-store.s3.amazonaws.com/0/333432/f286c6bf-a552-e55e-90d1-3372d0202e59.png)

インストール時にパスワードの入力ミスをしても、このようなメッセージなるとは考えにくいながら、何度も再インストールを繰り返すうちに分かったこと。

* **「ログイン時にパスワードを要求する」**の場合は問題なくログインできる
* **「自動的にログインする」**の場合でも、赤丸で示す「基本セッション」ボタンを押せばログインできる
![00-04.png](https://qiita-image-store.s3.amazonaws.com/0/333432/2335bed1-de33-e9d5-7735-3b23df6b6761.png)


## ログイン後

ようやくログインできたものの、「クイック作成」で作成されたUbuntuはスタンドアロンの利用を想定しているのか、インストール直後はホストOSからすぐに呼び出せる状態ではありません。

* sshデーモンが起動されていない
* IPアドレスの確認コマンドがない

そのため、ホストOSから利用できるように設定を変更します。

### sshデーモンの導入
Ubuntuからローカルホストにsshで接続を試みるとエラーとなります。試しに、ターミナルからsshdと実行するとインストールされていないことがわかります。

```TeX
Command 'sshd' not found, but can be installed with:
sudo apt install open-ssh server
```

任天堂ソフトのチュートリアルのように丁寧にインストール方法までを教えてくれるので、その通りに実行するとsshサーバのインストールと起動が完了します。

### IPアドレスの確認
Windows 10 ホスト側からsshでログインするためにUbuntuに割り当てられたIPアドレスを調べます。ここでifconfigコマンドを実行しますが、これもインストールされていません。

```TeX
Command 'ifconifg' not found, but can be installed with:
sudo apt install net-tools
```

同様にチュートリアルが出てきますが、面倒なのでGUIからIPアドレスを確認することにしました。GUIの右上のネットワークアイコンからIPアドレスを確認できます。

Wired Connected > Wired Settings
NetworkコントロールパネルのWiredの歯車マークを選択
![2-1.png](https://qiita-image-store.s3.amazonaws.com/0/333432/f1f1557a-4f47-0e36-2c1e-204241c7f76f.png)

### ホストOSからログインする
これでホストOSからログインできるようになりました。
![3.png](https://qiita-image-store.s3.amazonaws.com/0/333432/13d2362f-0495-bcd2-d980-a1e35510bcb4.png)

やはり、UbuntuのGUI上のターミナルを利用するより反応が快適です。

## 最後に
Hyper-Vは数クリックでUbuntuを導入でき、最初からマウス統合機能がインストールされているのは便利だと感じました。ただ、SSHデーモン機能などは機能は標準でインストールして欲しかったと思うのが正直な感想でした。
また、これから導入しようと思っていたpython3はインストール済みで、標準インストールの選択基準がわからない:frowning2:
ngrokを使った開発方法（Actions on Google Node編）

本当ならば一年ぐらい前に書くべきだった記事を今更書きます。(ずっと存在忘れてました)


Actions on Googleで開発するときの難点の一つとして、
Firebase functions側のデプロイ速度が遅いことが挙げられます。

一歩動けば、バグを産み落とすような人（私）にとっては、この更新速度は非常に辛いところがあります。

この点において、Firebase functionsのserve機能とngrokを用いれば、
Dialogflowからトンネリングすることで、ローカルにおいたソースコードにアクセスすることが可能です。
つまり、これらを用いれば**ソースコード側の様子を即時反映で確認できる**ということです。

以下、この記事はその方法について書きました。

# ①Firebase側でリンクをゲットする
[firebaseインストールやその方法](https://firebase.google.com/docs/cli/?hl=ja)については省きますが、
以下を参考に当該プロジェクトのfunctionsをserveします。

```
dev$ firebase login
dev$ firebase use --add
dev$ firebase serve --only functions
```
すると、以下画面のように出力されるので、`赤枠のリンクの部分`をコピーします。
![スクリーンショット 2019-01-14 21.22.50.png](https://qiita-image-store.s3.amazonaws.com/0/133465/12d3df79-1839-439f-397f-9d368551966a.png)

たぶん、以下のような感じだと思う

```
http://localhost:5000/<ProjectID>/us-central1/<exportsに指定した文字列> 
```


# ②ngrok側でリンクをゲットする
ngrokのダウンロードやインストールは他の方の記事や以下のドキュメントを確認いただけますと幸いです。
https://ngrok.com/download

以下のコマンドでngrokを起動します。

```
ngrok http 5000
```

このとき、以下画像のように出力されるので、
赤枠の`https://<魔法の文字列>.ngrok.io`箇所をコピーします
![スクリーンショット 2019-01-14 21.12.38.png](https://qiita-image-store.s3.amazonaws.com/0/133465/d80a6ea0-1bfc-0f1f-c00b-ddcb451253a4.png)

たぶん、以下のような感じだと思う

```
https://<魔法の文字列>.ngrok.io
```

# ③リンク合体します

ngrokで得られたリンクとfirebase serveで得られたリンクを合体させます。

 -  firebase部分の`http://localhost:5000/`箇所を削り、
 -  ngrokで得られたリンクの`https://<魔法の文字列>.ngrok.io`箇所を置換します。

![Slice 1.png](https://qiita-image-store.s3.amazonaws.com/0/133465/7f3a64fd-403c-c187-dd21-3a087e28ed6f.png)


そうすると以下のようなリンクになる。

```
https://<魔法の文字列>.ngrok.io/<ProjectID>/us-central1/<exportsに指定した文字列> 
https://<魔法の文字列>.ngrok.io/dottassociate/us-central1/dottassociate // 今回の場合
```

# ④Dialogflow側に指定します。
③リンクを以下画像の様に Fulfillment > Webhook > URLに指定し、Dialogflow側でSaveします。

![スクリーンショット 2019-01-14 21.39.53.png](https://qiita-image-store.s3.amazonaws.com/0/133465/ddaba1f5-8099-6831-3e60-a55c4b73657c.png)


そうすると、Actions Simulatorで確認すると、指定したローカルを叩くと思います〜！

なお、ngrok無料版は8時間が上限で、これが切れたら再度ngrokを起動してください。

以上です∠( ﾟдﾟ)／
Railsチュートリアルでつまずく、Bundler　version　のエラー解消方法

Rails 初学者が最初につまずくであろう、Railsチュートリアル。

私もその内の一人でした。

この記事では、Railsチュートリアルで私がつまずいた箇所、またそのエラーをどのように対処したのかを

皆さんに共有したいと思います。

（参考までに、私の使用したRuby On Railsはversion4.2です。）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/330360/3b93ec6c-4ca5-334e-af30-aceca4a57cc5.png)

私がつまずいたエラーは、アプリを作成し終え、自分のアプリをherokuにpushし、

デプロイ(Webサイトに公開)しようとした際に起こりました。
（入力したコマンドはこちら：git push heroku master）

そうすると、上図の赤字ようなエラーが出てきました。

エラー内容
**You must use bundle 2 or greater with this lockfile.**

(・・・なんだ、Budlerのバージョンを2以上にすればいいのか、簡単じゃん。)

そして、Bundler version を確認してみると・・・・
　
**Bundler version　2.0.1！！！**


( ,,`･ω･´)ﾝﾝﾝ？ versionは2以上になってるじゃないか、となるわけです。

そこで、このコマンドを入力すると、

heroku buildpacks:set https://github.com/bundler/heroku-buildpack-bundler2

無事デプロイできました！

私と同じ箇所でつまずいている人の助けになれば嬉しいです！！
SCSSで「&」でセレクタを参照する

ど忘れして時間をつかってしまったので、投稿します。

# いつ使うの？
SCSSでネストさせながらstyleを記述した際に、親セレクタを参照したいときがあります。

  - 親セレクタの一部を子セレクタの一部にしたい
  - 連結セレクタを作りたい
  - 疑似要素を書きたい
  - 親セレクタを追加したい
etc

##もう少し具体的な場面
 - ABテストをしたい
 - 特定ブラウザや条件での出し分けを実現したい
 
＊親要素を変更すると、上記は簡単に実現できます。ただ、CSSとしては詳細度の問題があるので、恒常的に使用するのはあまり推奨はしないです。


# 何を使うの
「&」になります


#コード例
##scssコード
```scss


.parent {
  .hoge{ // 子孫セレクタ
    color: red;
  }
  &Hoge{ // セレクタ名を連結
    color: blue;
  }
  &__element{ // BEM
    color: green;
  }
  &:after{ // 疑似要素を書く
    display: block;
  }
  .piyo &.aaa{ // 親セレクタを追加（後方参照）
    color: red;
  }
  
  &,
  &__elm{ //親と同じstyleを追加する
    color: red;
  }
}
```
## コンパイル後
```CSS
.parent .hoge {
  color: red;
}
.parentHoge {
  color: blue;
}
.parent__element {
  color: green;
}
.parent::after {
  display: block;
}
.piyo .parent.aaa {
  color: red;
}
.parent, .parent__elm {
  color: red;
}
```

# 参考
https://sass-lang.com/documentation/file.SASS_REFERENCE.html#parent-selector
https://qiita.com/noqua/items/adc24c28c13e9b74d3ad
https://qiita.com/yoshida-hi/items/4caa37028080872cdc1a

---
以上になります。
有難うございました。
【PHP】CSV, JSON, XML形式のファイルを読み込む方法

各形式のファイルを読み込む方法をまとめました。
今回はさらっと流しているだけなので、エラー処理や文字化け処理は行っていません。

返されるデータは、CSVは配列、JSONとXMLはオブジェクトとして扱っています。

# ファイル構成
```sh
FilrLoad
  ├── csvFileLoad.php
  ├── item_data.csv
  ├── item_data.json
  ├── item_data.xml
  ├── jsonFileLoad.php
  └── xmlFileLoad.php
```
# CSV
ファイルシステム関数のfopenもありますが、SplFileObjectクラスを使うのが便利そうです。
> [php.net〜SplFileObjectクラス](http://php.net/manual/ja/class.splfileobject.php)

```item_data.csv
1,apple,100
2,orange,80
3,peach,130
```

```csvFileLoad.php
<?php 
// ファイルを読み込みのみでオープンする
// ファイルポインタをファイルの先頭にセットする
$handle = fopen('item_data.csv', 'r');

// 読み込んだ行を分割し配列にして返す
// 配列を各変数に代入し、出力する
while (($row = fgetcsv($handle, 4096)) !== false) {
    list($item_id, $item_name, $item_price) = $row;
    echo $item_id.','.$item_name.','.$item_price.'<br>'."\n";
}

fclose($handle);

// SplFileObjectクラスを使用する
$file = new SplFileObject('item_data.csv');

// フラグをセットする
// CSV列として行を読み込む
$file->setFlags(SplFileObject::READ_CSV);
foreach ($file as $row) {
    list($item_id, $item_name, $item_price) = $row;
    echo $item_id.','.$item_name.','.$item_price.'<br>'."\n";
}

// 出力結果
// 1,apple,100
// 2,orange,80
// 3,peach,130
```

# JSON
```item_data.json
{"Items":
  [
    {
      "item_id": 1,
      "item_name": "apple",
      "item_price": 100
    },
    {
      "item_id": 2,
      "item_name": "orange",
      "item_price": 80
    },
    {
      "item_id": 3,
      "item_name": "peach",
      "item_price": 130
    }
  ]
}
```

```jsonFileLoad.php
<?php 
// ファイルの内容を全て文字列に読み込む
$json_data = file_get_contents('item_data.json');
// JSONエンコードされた文字列を受け取り、オブジェクトに変換する
$all_data = json_decode($json_data);

foreach ($all_data as $data) {
    foreach ($data as $line) {
        echo $line->item_id.','.$line->item_name.','.$line->item_price.'<br>'."\n";
    }
}

// 出力結果
// 1,apple,100
// 2,orange,80
// 3,peach,130
```

# XML
```item_data.xml
<?xml version="1.0"?>
<items>
  <item>
    <item_id>1</item_id>
    <item_name>apple</item_name>
    <item_price>100</item_price>
  </item>
  <item>
    <item_id>2</item_id>
    <item_name>orange</item_name>
    <item_price>80</item_price>
  </item>
  <item>
    <item_id>3</item_id>
    <item_name>peach</item_name>
    <item_price>130</item_price>
  </item>
</items>
```

```xmlFileLoad.php
<?php
// XMLファイルをパースし、オブジェクトに代入する
$handle = simplexml_load_file('item_data.xml');
foreach ($handle->item as $item) {
  echo $item->item_id.','.$item->item_name.','.$item->item_price.'<br>'."\n";
}

// 出力結果
// 1,apple,100
// 2,orange,80
// 3,peach,130
```
Docker-Composeを用いたMySQL5.7環境構築

# Docker-Composeとは？
複数のコンテナをyaml形式のファイルで一括管理できる優れもの。

公式ドキュメント
http://docs.docker.jp/compose/toc.html

# サンプルコード&解説

### ファイル構造
docker-compose.ymlにコンテナの設定について記載されている。
dataにはストレージとして使用するコンテナのDockerfileが、
initにはDBの初期データ（.sql）が配置されている。

```
.
├── README.md
├── data
│   └── Dockerfile
├── docker-compose.yml
└── init
    └── Member.sql
```

### docker-compose.yml
db-storageがData Volumeコンテナ。
データを保持するためだけのコンテナである。
DBのイメージはmysql:5.7を使用。
先ほどのストレージコンテナ上のボリュームをマウントしている。
また、イメージの/docker-entrypoint-initdb.dにsqlファイルを配置するとコンテナ起動時に実行される為、初期データ作成用のsqlファイルを配置している。


```
version: '3'
services:
  db-storage:
    build: ./data
    volumes:
      - /var/lib/mysql
  db:
    image: mysql:5.7
    ports:
      - 3306:3306
    environment:
        MYSQL_ALLOW_EMPTY_PASSWORD: "yes"
        MYSQL_DATABASE: sample
        MYSQL_USER: example
        MYSQL_PASSWORD: example
    volumes:
      - ./init:/docker-entrypoint-initdb.d
    volumes_from:
      - db-storage
```

### ./data/Dockerfile
Data VolumeコンテナのDockerfile。
busyboxというイメージをしている。
centosやubuntuでも問題ないが、busyboxの方がOSとして軽量なため、
今回のようなデータ保持の為のコンテナにはbusyboxを使用した方が良い。

```
FROM busybox

VOLUME /var/lib/mysql

CMD ["bin/true"]
```

### ./init/Member.sql
初期データ作成用のsqlファイル。

```
USE sample;

CREATE TABLE member
(
    id INT(10),
    name VARCHAR(40),
    age INT(10),
    sex VARCHAR(40)
);

INSERT INTO member
    (id, name, age, sex)
VALUES
    (1, "Nagaoka", 20, "man");
INSERT INTO member
    (id, name, age, sex)
VALUES
    (2, "Tanaka", 30, "man");
INSERT INTO member
    (id, name, age, sex)
VALUES
    (3, "Matsumoto", 25, "woman");
```

# 使用例

```
$ docker-compose up -d
Creating mysql_db-storage_1_6c5a6bdc1e4e ... done
Creating mysql_db_1_b086ce193c2a         ... done
```

```
$ mysql -u root -p --host=127.0.0.1
mysql: [Warning] World-writable config file '/usr/local/etc/my.cnf' is ignored.
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.24 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>
```

```
mysql> select * from sample.member;
+------+-----------+------+-------+
| id   | name      | age  | sex   |
+------+-----------+------+-------+
|    1 | Nagaoka   |   20 | man   |
|    2 | Tanaka    |   30 | man   |
|    3 | Matsumoto |   25 | woman |
+------+-----------+------+-------+
3 rows in set (0.00 sec)
```

# 参考

MySQL公式Dockerイメージ
https://hub.docker.com/_/mysql/
備忘録：今さらRedisを調べた

Redisについて勉強したので個人的な備忘録としてまとめます。

## 勉強しようと思ったきっかけ
たまたま触る機会があったプロジェクトでRedisを利用してあり、なにこれDBとは違うモノなの？？みたいな状態になったので調べました。
備忘録として残そうと思います。

## Redisってなに（今更
[公式](https://redis.io/)を翻訳してみると…
> Redisはオープンソース（BSDライセンス）のインメモリデータ構造ストアで、データベース、キャッシュ、メッセージブローカーとして使用されます。文字列、ハッシュ、リスト、セット、範囲クエリを含むソートセット、ビットマップ、ハイパーログ、半径クエリを含む地理空間インデックス、ストリームなどのデータ構造をサポートします。Redisには、レプリケーション、Luaスクリプティング、LRU排除、トランザクション、およびさまざまなレベルのディスク上の永続性があり、Redis Sentinelを介した高可用性とRedis Clusterによる自動パーティショニングを提供します。

やばい…わからない。。。

さらに調べてみます。
ああっ、[AWS様のドキュメント](https://aws.amazon.com/jp/redis/)がある！
AWSの説明のほうがわかりやすくて助かった
> Redis とは
Redis は、データベース、キャッシュ、メッセージブローカー、キューとして使用できるオープンソースの高速インメモリ型 key-value データストアです。ゲーム、アドテクノロジー、金融サービス、医療、IoT の分野のリアルタイムアプリケーションでミリ秒未満の応答時間を実現し、1 秒間に数百万件のリクエストを処理できます。Redis は、キャッシュ、セッション管理、リアルタイム分析、地理空間、チャットとメッセージング、メディアストリーミング、ゲームのリーダーボードでよく利用されています。

うんうん。わかりやすいぞ

## ざっくりわかったこと
Redisは高速性を要する場合のデータストアとして利用される。キャッシュとかセッションストアとかで使われる。
リアルタイム分析に向いていると。なるほどー！
しかもインメモリだけど、永続化する仕組みまであるのか。すごい。

要件によってはDB用意しなくても事足りる場合もあるのかな…？
[冒頭を確認してね] CentOS7 で Python3 の仮想環境として virtualenv を入れる

@k8uwall さんのコメントで、
CentOS7であっても、そもそもPython3.6ならvenv使えると気づいたので、
[別の投稿](https://qiita.com/kumarstack55/private/d7d26b3be80d774fdebf)でまとめなおしたのでそちらを参照すべき。

この投稿は候補参照性で残すけれど、消してもいいくらい。

-----

# はじめに

* CentOS7 で Python パッケージを隔離した区画でコードを実行したい。

# 前提知識

* CentOS7 を最小構成で入れると Python 2.7 が入ってくる。
* CentOS7 は base リポジトリから virtualenv がある。
* epel に Python 3.6 がある。

# 方針

pyenv 等、他の仮想環境の選択肢があるが、virtualenv + python3.6 の環境を作る。

# 手順

## 仮想環境を作る

```bash
yum install python-virtualenv -y
yum install epel-release -y
yum install python36 -y
virtualenv -p /usr/bin/python36 $HOME/.venv
```

## 仮想環境を有効にする

```bash
source $HOME/.venv/bin/activate
```

## 仮想環境を終了する

```bash
deactivate
```

# おまけ

virtualenv の公式の記載通り、 venv は Python 3.3 から標準なので、
CentOS7 のように Python2 を考えなくてよい環境なら venv でいいんじゃないか。
OSX / Windows 界隈は未調査。

# 参考文献

* https://virtualenv.pypa.io/en/latest/
pickadate.jsの年プルダウンの初期値設定方法

pickadate.jsで表示されるポップアップの年プルダウンの初期値設定が難しかったので備忘で残します。

# やりたいこと
ポップアップ表示された時の年プルダウンの初期選択値を過去の年にしたい。
（デフォルトだと現在の年になります）
<img width="666" alt="スクリーンショット 2019-01-14 21.12.08.png" src="https://qiita-image-store.s3.amazonaws.com/0/319350/783bdcae-29f6-da0c-ad4a-9fe840d6ae6d.png">

# pickadate.jsのバージョン
v3.5.6

# 解決方法
pickadate.jsに手を入れちゃいました（もっといい方法ありそうな気がする...）
## 1.L77付近からnowを消す

```js:picker.date.js（修正前）
    calendar.
        set( 'min', settings.min ).
        set( 'max', settings.max ).
        set( 'now' )
```

```js:picker.date.js（修正後）
    calendar.
        set( 'min', settings.min ).
        set( 'max', settings.max )
```

## 2.L73付近に「calendar.item.now = settings.now」を追加

```js:picker.date.js
    // The component's item object.
    calendar.item = {}

    calendar.item.clear = null
    calendar.item.disable = ( settings.disable || [] ).slice( 0 )
    calendar.item.now = settings.now //　←　これだけ追加
    calendar.item.enable = -(function( collectionDisabled ) {
        return collectionDisabled[ 0 ] === true ? collectionDisabled.shift() : -1
    })( calendar.item.disable )
```

## 3.pickadateを使用する際のオプションにnowを追加する

```coffeescript:new_user_create.coffee
options = {
  now: moment().add(-49,'year').toDate() # ←　これだけ追加
  max: moment().toDate(),
  selectYears: true
}
$('#birthday').pickadate(options)
```

上記の例では、現在から４９年前を初期選択させます。
以上で以下になります。
<img width="666" alt="スクリーンショット 2019-01-14 21.29.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/319350/f1a40329-53d4-4318-637f-8de7324eb458.png">
UnityEditor上のモーション作成、編集アセットUMotionProの良い点とかを書く

# 概要
Unityでのワークフローとして、モデリングやアニメーションはDCCツール(Blenderとか)上で全部作って、UnityEditorに取り込んで使う。というのが前提になっています。
ただ、UnityEditor上でアニメーションを作ったり編集したりする、という需要は結構あります。
もっと言うとモーションキャプチャデータを後編集する時にMotionBuilderを買うお金は無いけどなんとかしたい、みたいな切羽詰まった需要があります。

そういったUnityEditor内でのモーション作成、編集アセットとして人気なのが

- Very Animation https://assetstore.unity.com/packages/tools/animation/very-animation-96826
- UMotionPro https://assetstore.unity.com/packages/tools/animation/umotion-pro-animation-editor-95991

の2種です。日本国内だと作者が日本人（日本語のマニュアルがある！！！）という事もあり、前者のVery Animationの使用例が多いです。

でもUMotionProも結構強力なので、便利だなあと思った事を書きます。


# 強力なIKセットアップとIK Pinned
UMotionProは機能制限版の無料アセットであるUMotionFreeが体験版的に使われています。

ただ、このUMotionFreeは **UMotionProの強力な部分が全部使用不可** なので、この無料版使って「うわ使えねえ…それに比べてVeryAnimation良い…」 

となりがちです。

特にこのUMotionProはIKセットアップの自動生成と、IK Pinned(足滑り等の防止に使うやつ)がめちゃくちゃ強力なので、それが無料版では試せなくてつらいです。

UMotionPro使っていると「基本的にIKベースで作っていって、FKで微調整したデータもIKモードに変換する」というクセが付くくらいにはIKが優秀です。

# MotionBuilderとかでお馴染みの「補正用レイヤー」でモーション編集できる

この動画を見たら強力さが分かると思います。既存の（特にモーションキャプチャデータ）のゴミ取りとか、めり込んだ腕の補正とか、捻れた足首の補正とかを頑張って直す時、「補正用レイヤー」を追加して、レイヤーウェイトも操作しつつ、めり込み補正専用のFKアニメーションを追加したり出来ます。

https://www.youtube.com/watch?v=TPzCp6Ezy4o

これと同じ事をMotionBuilderでやってる人は結構居ると思うんですがどうかな…UMotionProはほんの数千円ですよ。
.animだけじゃなくてFBX形式でもアニメーションをエクスポート出来るので、再度DCCツールに持って行く事も可能です。


# ここが弱いよUMotionPro
あくまでHumanoidアニメーションに特化してます。

具体的に言うと、「髪の毛を綺麗にFKで揺らす」とか、「Blendshapeの表情付けを楽にする」みたいな機能は無いです。表情未サポートが痛いところですね…

（ただ、4本腕のキャラの腕4個それぞれにIKを自前セットアップ出来たりするので、刺さる人には刺さると思います！）

更に言うとVRMファイルは未サポートです。中身をFBX化して.animだけ使って転用するみたいなつらいワークフローになります。

VeryAnimationの方が、全部入り的にアニメーションを触れるので、キャラ物だったらVeryAnimationで良いかもしれません。 **MotionBuilderを買えないけどモーキャプデータを編集したい人** とか、一定の量のモーションを量産する人とか、オブジェクト絡みのモーションを作る人とかにはUMotionPro結構良いと思います。
pickleやjsonで日本語をそのままファイル出力したい

pythonにおいてjsonデータや各変数の外部出力・保存には標準モジュールのpickleやjsonが用意されていますが、日本語などの表示は以下のようになります。  

```.py
data = {'ar': 'عربى', 'en': 'english', 'jp': '日本語', 'ko': '한국어'}
import pickle
with open('data.txt', 'wb') as f:
    pickle.dump(data, f)
```
```.sh
$ cat data.txt
{"ar": "\u0639\u0631\u0628\u0649", "en": "english", "jp": "\u65e5\u672c\u8a9e", "ko": "\ud55c\uad6d\uc5b4"}
```

jsonの場合は  

```.py
data = {'ar': 'عربى', 'en': 'english', 'jp': '日本語', 'ko': '한국어'}
import json
with open('data.txt', 'w') as f:
    json.dump(data, f)
```
```.sh
$ cat data.txt
▒}q(XarqعربىqXenqXenglishqXjpqX 日本語qXkoqX    한국어u.
```

これらは本来のロードして再利用という用途に問題はありませんが、ファイル単位でサクッと確認できないのが難点です。
追記：`$ python -m pickle data.txt`で覗けます。LouiS0616様より

個人的には毎回手間だったので、モジュールを作りました。 `pip install ppickle`でインストールできます。  

```.py
data = {'ar': 'عربى', 'en': 'english', 'jp': '日本語', 'ko': '한국어'}
import ppickle
ppickle.dump('data.txt', data) # 保存
loaded = ppickle.load('data.txt') # 呼び出し
print(loaded['jp']) # 日本語
print(loaded == data) # True
```
```.sh
$ cat data.txt
{'ar': 'عربى', 'en': 'english', 'jp': '日本語', 'ko': '한국어'}
```
このように見た目通りがそのままファイルに保存されるようになります。

コア機能はcodecs、pprint、astを組み合わた9行で再現できます。pipの方は、loadできない形は書き出す時点で弾いたり、受け入れ可能な型を増やりと洗練したいと思っています。

```ppickle.py
import codecs
import ast
from pprint import pformat

def dump(filename, data):
    with codecs.open(filename, 'w', 'utf-8') as f:
        f.write(stringed_data)

def load(filename):
    with codecs.open(filename, 'r', 'utf-8') as f:
        return ast.literal_eval(f.read())
```

現状listやdictしか受け入れられませんが、確認用に書き出す・ログ出力する際は中身がintがstrか空白あるかなどの確認できるよう元々リストで囲ってから出していたので、個人的には必要十分です。以上です。（絶対車輪の再開発だと思いますが、見つけられませんでした）
自分が使っているベジエ曲線のつなぎ方

現在の方法
![CurveLeap.png](https://qiita-image-store.s3.amazonaws.com/0/269835/3132a1ab-5cdc-da77-a188-d0a30318d10b.png)
黒線は直線部分で
赤線がベジエ曲線の部分です。
点と点の中間を利用してつないでいます。
こうすることで、つなぎ目がまっすぐになります。
よりいい方法がありましたら、コメントなどでお知らせください
Firebase + Nuxt.js + node の Dockerfile 2019年1月14日時点

## 踏み抜いた箇所
- `node:6-alpine` では `async` が使えない。  
- `node:alpine` `node:11-alpine` では `node-gyp` のビルドが通らない。

## Dockerfile
```Dockerfile
FROM node:8-alpine

RUN apk add --no-cache make gcc g++ python && \
  npm install --production --silent && \
  apk del make gcc g++ python
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY ./package.json $WORKDIR
COPY ./package-lock.json $WORKDIR
RUN npm install

COPY . $WORKDIR
RUN npm run build
ENV HOST 0.0.0.0
EXPOSE 3000

CMD [ "npm", "start" ]
```
結構古い仕組みのインフラへ部分的にCIを導入


CIから一部ファイルを同期しつつ、開発用のアクセス制限などをする

## CIからFTPで同期する

dry-runとか同期のオプションとか思い出しつつ。。

今日からはじめるCI/CD ─ CircleCI + Deployerでテストとデプロイを自動化しよう！【休日個人開発】 - エンジニアHub｜若手Webエンジニアのキャリアを考える！
https://employment.en-japan.com/engineerhub/entry/2018/03/20/110000

CircleCI
https://circleci.com/gh/bonk/tomoichiba/tree/feature%2F1

lftp コマンドの mirror で有用なオプション（といくつかの注意点） - 約束の地
https://obel.hatenablog.jp/entry/20170905/1504587026

Deploying WordPress themes via GitHub with CircleCI - SprintlySprintly
https://sprint.ly/blog/deploying-wordpress-themes-via-github-circleci/

Git + CI + lftp で自動アップロードする方法 - HAM MEDIA MEMO
https://h2ham.net/lftp-git

lftpのインストールとファイルアップロード方法 - ブロックチェーンエンジニアとして生きる
https://tomokazu-kozuma.com/how-to-install-and-use-lftp/

soci/config.yml at master · SOCI/soci
https://github.com/SOCI/soci/blob/master/.circleci/config.yml

gulp ftp - Google 検索
https://www.google.com/search?q=gulp+ftp&oq=gulp+ftp&aqs=chrome..69i57j0l5.3803j0j4&sourceid=chrome&ie=UTF-8

gulp-deploy-ftp - npm
https://www.npmjs.com/package/gulp-deploy-ftp

gulpでFTPアップロード|Ewig Leere(Lab)
https://lab.ewigleere.net/blog/blog_entry/201809/gulp_ftp_deploy-20180919.html

ftp-deploy - npm
https://www.npmjs.com/package/ftp-deploy

simonh1000/ftp-deploy: Node.js module to ftp a folder somewhere
https://github.com/simonh1000/ftp-deploy

ftp-deploy/test_script.js at master · simonh1000/ftp-deploy
https://github.com/simonh1000/ftp-deploy/blob/master/test/test_script.js

trs/ftp-srv: Modern FTP Server
https://github.com/trs/ftp-srv

## アクセスコントロールファイル

有効なディレクティブなどを探りつつ試す

htaccess files directories - Google 検索
https://www.google.com/search?num=100&ei=IpggXLSsK4Oy0PEPntG38AM&q=htaccess+files+directories&oq=htaccess+files+directories&gs_l=psy-ab.3..0i30j0i8i30.21885.27314..27539...1.0..0.290.3150.0j15j3......0....1..gws-wiz.......0j0i71j0i4j0i4i30j0i5i30j0i19j0i30i19j0i8i30i19j0i5i30i19j0i8i13i30i19j0i13i5i30i19.NF17gudWArk

特定のファイル・ディレクトリのアクセスを拒否する-独学!未経験からWebデザイナーになる!!
https://www.be-webdesigner.com/technotes/server/htaccess/access_deny.htm

HTML - 【htaccess】サブディレクトリの内容をルートで表示させたい｜teratail
https://teratail.com/questions/28883

Apache の環境変数 - Apache HTTP サーバ
http://www.ma.kagu.tus.ac.jp/manual/ja/env.html
SRE_5章（トイルの撲滅）

# 5章 トイルの撲滅

## 5.1 トイルの定義

* 行わなければならない管理上の業務はトイルではなく、オーバーヘッド。チームミーティング、ゴールの設定・評価、人事事務作業等はオーバーヘッドにあたる
* 以下、当てはまるものが多ければトイルといえる
  * **手作業であること**
  * **繰り返されること** 
  * **自動化できること** 
  * **戦術的であること**：割込み作業。ページャーのアラートへの対応はトイルにあたる 
  * **長期的な価値を持たないこと** 
  * **サービスの成長に対してO(n)であること**

## 5.2 トイルは少ないほうが良い理由

* トイルは、確認せずに放っておくと全員の時間を100%使ってしまう傾向にあるため、GoogleではSREチームのトイル作業時間は50%以下としている

## 5.3 エンジニアリングであるための条件

* エンジニアリングの作業は、新しいことをするものであり、本質的に人間の判断を必要とする
* 典型的なSRE活動はおおむね以下のように分類できる
  * **ソフトウェアエンジニアリング**：コードの作成・修正を含む作業。関連する設計やドキュメントの作業もある
  * **システムエンジニアリング**：プロダクションシステムの設計・設定の変更、システムに関するドキュメント作成がふくまれ、1回の作業で改善効果が持続するような方法で行われる
  * **トイル**：サービスを稼働させることに直結する作業で、繰り返されたり、手作業だったりするもの
  * **オーバーヘッド**：サービスを稼働させることに直結はしない管理的作業

## 5.4 トイルは常に悪なのか？

* 多少のトイルはやむを得ない。トイルが少量であるならば問題ない
* トイルを大量に処理せねばならなくなるとつらい。以下のようなことは考えておくべき
  * **キャリアの停滞**：プロジェクトに使う時間があまりに少なくなると、キャリアアップが遅くなる
  * **モラルの低下**：あまりに多すぎるトイルは燃え尽き、倦怠、不満につながる
* トイルに時間を使いすぎると、SREの組織には以下のダメージが生じる
  * **混乱の発生**：SREはエンジニア組織であるよう皆は努力している。トイルをしすぎると、その努力を台無しにし、SREの職務について誤解を与えてしまう
  * **進捗速度の低下**
  * **習慣づけ**：あまりにトイルに取り組みすぎると、開発側からもっと依頼されてしまうかもしれない
  * **摩擦の発生**：自分はよくても、他のメンバーが大量のトイルに対して快く思っていない可能性がある
  * **信義違反**：トイルばかりだと、新規採用者、SRE新規参画者を欺くこととなる

## 5.5 まとめ

* イノベーションを増やし、トイルを減らそう
JavaScriptでMediaQueryをトリガーにしたい場合は「MediaQueryList」を利用する

始めての投稿になります。
よろしくお願いします。

---

# いつ使う？
JavaScriptで`Media Queries`を使用したいとき。
  - UIを変更したい
  - レイアウトを変更したい（CSSだけでは実現できない）

# 使い方
 - MediaQueryListオブジェクトを作る
 - 実行したい処理を作る
 - 予約する
 
# 例
```JavaScript
// MediaQueryの文字列（例：'(max-width: 414px)'）を引数にして、objを受け取る
const mql = window.matchMedia(MediaQuery); 

//コールバック
const callback = (event)=>{
***
}

// MediaQueryのイベントからコールバックを実行する。
mql.addListener(callback); 
```

# その他
MediaQueryListはいくつかプロパティをもっています。
例えば`matches`はビューポートの状態に応じてBooleanを返します。

## コールバックの例
```JavaScript
const callback = (event) = {
  if(event.matches) {
    // trueの場合の処理
  } else {
    // falseの場合の処理
  }
}
```

# 参考

MediaQueryList
https://developer.mozilla.org/ja/docs/Web/API/MediaQueryList

window.matchMedia をそろそろ活用してもいい頃
https://qiita.com/amamamaou/items/a29b29f5267196a5e4ea

---
以上になります。
有難うございました。
atcoder ABC107

Cは数学的な問題であり、解法が浮かばなかった。Dはやっていない
https://atcoder.jp/contests/abc107

#C問題
数直線上で、原点からスタートし、K個の座標に達するmでにかかる距離の最小値を求める問題。ロウソクの位置は単調増加なので、k個到達する時、左端をi個目ととすると右端は必ずi+K-1になる。よって、0番目からN-k番目までについて左端から右端に向かうパターンと右端から左端に行くパターン両方求めて、最小値を更新していくことで、答えが求まる。
【Rails】中間テーブルの作り方　hiddenTag

マッチングアプリを作っているのですが、
中間テーブルを作るときに、かなりハマったので、メモします。

やりたい事
===
matchingモデルとuserモデルの中間テーブルを作りたい

困った事
===
マッチングテーブルは作れた（保存）ができたが、
同時に中間テーブルが作れなかった。

内容
===
```ruby:matching.rb
  has_many :matching_users
  has_many :users, through: :matching_users
```
```ruby:user.rb
  has_many :matching_users
  has_many :matchings, through: :matching_users
```
```ruby:matching_user.rb
  belongs_to :matching, optional: true
  belongs_to :user, optional: true
```
```ruby:matching.controller
  def new
    @matching = Matching.new
    @matching.users << current_user
  end

  def create
    @matching = Matching.new(matching_params)
    @matching.save
  end

  def matching_params
    params.require(:matching).permit(user_ids: [])
  end
```
```ruby:matching.controller
= form_with model: @relationship, id: :relationship_js do |f|
  = hidden_field_tag :following_id, user.id
  = fields_for @matching do |m|
    = m.hidden_field :user_ids, value: [user.id]
  = button_tag type: 'submit', class:"relationship-button" do
    = fa_icon "heart", class: "heart-icon", text: "ありがとう"
※relationshipは関係ないです。
```
ここまでは、できたのだが、fields_forのやり方など、色々試したが、全く反応しなかった。。
丸９時間くらいかかって、修正点にたどり着きました。

```ruby:matching.controller
= form_with model: @relationship, id: :relationship_js do |f|
  = hidden_field_tag :following_id, user.id
  = fields_for @matching do |m|
    %input{name: "matching[user_ids][]", type: "hidden", value: "#{current_user.id}",}
    %input{name: 'matching[user_ids][]', type: 'hidden', value: "#{user.id}"}
  = button_tag type: 'submit', class:"relationship-button" do
    = fa_icon "heart", class: "heart-icon", text: "ありがとう"
```
hidden_fieldがダメだったみたいです。
詳細わかる方はご教授頂けますと幸いです。
コーヒーブレイク!!

# コーヒーブレイク
以前、[WINEの評価をするサイト](https://qiita.com/tanakadaichi_1989/items/c655d93a1fae56f2be07)と、[Flask+KerasでWEBサイト](https://qiita.com/KeisukeToyota/items/c1c626c9efc816932a96)と構築するものを発見した。

では、今回、WINEの評価するサイトを、WEB化してみようと思った。

まず、WINEを評価するサイトのwine.pyの

```
#10段階評価したいワインの成分を設定
sample = [7.9, 0.35, 0.46, 5, 0.078, 15, 37, 0.9973, 3.35, 0.86, 12.8]
print("\n")
print("--サンプルワインのデータ--")
```

上記のサンプルデータ周りを最後まで削除し、その代わりにモデルを保存する処理を追加する

```
model.save('model.h5') # 追加部分
```

これで準備は完了。`python wine.py`でモデルを生成。
その上で、predict.pyや、app.pyなどを修正し、実行したところ、うまく行った‼

とりあえず、こんなことをすれば、こんな感じになるんだ。
と言うのが1つ確立できた。

もう少し、Pythonも勉強しないとな、、、。
だが、連携部分は大筋理解できたので、あとはモデルを作って、実際にVPNのレンタルサーバでやってみるか。

まずは、軽いやつでGPUなしバージョンでやってみたい‼
これなら、夏までに行けそう‼がんばるぞ!!!

# 後述
と言いながら、実は、最近、**AmazonPrime**の**[ELEMENTARY](https://en.wikipedia.org/wiki/Elementary_(TV_series))**にハマっている、、、
現在、AmazonPrimeで見れるのはシーズン5まで。いつもの癖で一気観をしてしまっている、、、こちらの進捗がおぼつかない、、、
[Lucy, Liu](https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%82%B7%E3%83%BC%E3%83%BB%E3%83%AA%E3%83%A5%E3%83%BC)が素敵だ!!