OmniAICreator/Qiita-1.07M huggingface dataset:
laravel のログイン機能をnameでログインへ変更する機能

##### 以下の手順で上手く行きました。

```
1

2014_10_12_000000_create_users_table.php

$table->string('name')->unique();

2
LoginController.php

public function username()		
{	
 return 'name';	
}		

3

login.blade.php

<div class="form-group{{ $errors->has('name') ? ' has-error' : '' }}">	

    <label for="email" class="col-md-4 control-label">Name</label>
			
    <div class="col-md-6">										

    <input id="name" type="name" class="form-control" name="name" value="{{ old('name') }}" required autofocus	    
@if ($errors->has('name'))	

            <span class="help-block">	
                <strong>{{ $errors->first('name') }}</strong>	
            </span>	

        @endif	

    </div>

</div>	

```

# 動作確認OK

# 拍手！

# 以上
今日のコミット一覧をシンプルに出力する

```sh
$ git log --oneline --branches --since=midnight --format='%ad %s' --date=iso \
| grep --color=none  `date '+%Y-%m-%d'` \
| sed -e 's/2020-[0-9]*-[0-9]* //g' \
| sed -e 's/ +0900//g'

17:52:21 ✨ xxxを作成
14:56:56 ✨ xxxの情報を返すように
12:11:18 👍 xxxを調整
```

`--since=midnight` で本日のコミットを出力できたりするのだが、前の日のコミットに `fixup` したりするものも
出力してしまうのが少し気になったので、 grepで絞り込んでいる

あとは日付とオフセットの情報もいらないので、sedで除外
よく使う、好きなGem

好きなGemをまとめます。

##better-errors、binding_of_caller
エラー画面がわかりやすくなって、デバッグが捗ります。

##annotate
スキーマ情報を、model内にコメントとして書き出してくれます

##letter_opener_web
ローカル環境で送信したメールをブラウザ上で確認できるようになります。

##dotenv-rails
環境変数を楽に扱えるようになります

##paranoia
論理削除の実装が楽になるgemです

##gon
Rubyの変数、配列、ハッシュなどをJavaScriptに簡単に引き渡すことができるようになります。

##rails-i18n
エラーメッセージ等を日本語化するために使います

##kaminari
ページネーションを楽に実装することができます

##carrierwave、mini_magick
画像をリサイズしてアップロードし、DBと紐付けて管理することができるようになります

##好きになれなかったGem達
###devise
一番有名な認証用Gemです。
カスタマイズがしづらくて、結局あとあと工数が膨らみそうな印象を受けました。使ってない機能がたくさんあったりするのも気持ち悪い感じがするので、私には合わない感じがしました

###guard-livereload
HTMLやCSS等を更新した時に、ブラウザをオートリロードするためのGemです。
デフォルトの設定で、SCSSファイル更新時のオートリロードできなかったのと、数年前からアップデートされていない感じがしたので使うのをやめました。
今は`browser-sync`でオートリロードしてます。
[Railsでファイル変更時のオートリロードを実現](https://qiita.com/d0ne1s/items/a973d7b5701f050d8992)

###rails-erd
ER図を自動生成してくれるGemです。
便利ではあったものの、開発が止まっていて、Rails6に対応していなかったので、使わないことにしました。
Macからssh接続でvirtualbox上のcentos6に接続する

#環境
ゲストOS　：　CentOS６
ホストOS　：　MacOS　Catalina

#流れ
##①virtualboxの設定でネットワークを開く
・以下で設定。
割り当て　：　ホストオンリーアダプター
・名前の確認
名前：vboxnet0
<img width="771" alt="スクリーンショット 2020-01-16 17.48.26.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444064/ba106340-d448-5629-609c-355cb404b12c.png">

##②centosを起動
##③centos上のネットワークを確認
centos上で`ip a`でネットワークの確認。
私の設定の場合、①の設定によりeth2が追加されたことを確認したが、eth2にipアドレスが設定されていなかった。
なぜeth1でなく、eth2であったのかは不明。。

```
> ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
------省略---------
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    inet 10.0.2.15/24 brd 10.0.2.255 scope global eth0
    inet6 fe80::a00:27ff:fe84:eb71/64 scope link 
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
 ↑ipアドレスの記載なし
```

##④eth2にIPアドレスを設定する。
手動で設定していく。
⑴/etc/sysconfig/network-scripts/以下にeth2用の設定ファイルを追加する。/etc/sysconfig/network-scripts/ifcfg-eth0はあるものの/etc/sysconfig/network-scripts/ifcfg-eth2がなかったため、ifcfg-eth0ファイルをコピーした。

```
> cd /etc/sysconfig/network-scripts/
> ls
ifcfg-eth0      ifdown-ippp    ifup-aliases    ifup-ppp
ifdown-ipv6     ifup-bnep      ifup-routes     ifdown-isdn
ifup-eth        ifup-sit       ifdown-post     ifup-ippp
ifup-tunnel     ifdown-ppp     ifup-ipv6       ifup-wireless
ifcfg-lo        ifdown-routes  ifup-isdn       init.ipv6-global
ifdown          ifdown-sit     ifup-plip       net.hotplug
ifdown-bnep     ifdown-tunnel  ifup-plusb      network-functions
ifdown-eth      ifup           ifup-post       network-functions-ipv6
↑　ifcfg-eth2のファイルがない。

> cp ifcfg-eth0 ifcfg-eth2

```

⑵macのネットワーク状況を確認。
ターミナル からifconfigで、virtualboxのネットワークで設定した名前（vboxnet0）のネットワークアドレスを確認。IPアドレスとサブネットマスクから導きました。
IPアドレスが192.168.56.1/24であった場合、192.168.56.0がネットワークアドレスになる。


⑶先ほどコピーしたifcfg-eth2のファイルを正しい内容に変更。
このままでは、ifcfg-eth0のファイルと全く同じなので！

```:変更前
DEVICE=eth0
HWADDR=＊＊＊＊＊＊＊＊＊＊＊＊
TYPE=Ethernet
UUID=＊＊＊＊＊＊＊＊＊＊＊＊
ONBOOT=yes
NM_CONTROLLED=yes
BOOTPROTO=dhcp
```

↓以下に変更

```:変更後
DEVICE=eth2
# HWADDR=＊＊＊＊＊＊＊＊＊＊＊＊　コメントアウト
TYPE=Ethernet
# UUID=＊＊＊＊＊＊＊＊＊＊＊＊　コメントアウト
ONBOOT=yes
NM_CONTROLLED=ye
BOOTPROTO=none　←dhcpから変更
IPADDR=192.168.56.2　←追加
PREFIX=24　←追加
```
・DEVICEはeth2に指定（ここは、先ほど`ip a`でeth2が新しく追加されていたので、それに合わせる）
もし`ip a`でeth1などが出力さていたなら、出力されたデバイス名を記入する
・BOOTPROTOをdhcpからnoneに変更することで自動でipアドレスが割り振られないようにする。
・IPADDRに⑵で確認したネットワークアドレスに割り振り可能なアドレスを追加する。macで192.168.56.1を使用していたため、192.168.56.2に設定。
PREFIXは⑵で確認した数値と同じに設定。

##⑤ネットワークを再起動して、ターミナル から接続完了！

```:centos6
service network restart
```

```:ターミナル 
ssh root@192.168.56.2
```

#今回の設定について
・ホストオンリーアダプターについて
virualboxでホストオンリーアダプターを追加することでNICを増やした。ホストオンリーアダプターはホストOS（MacOS)とゲストOS（CentOS6）のみをつなげる設定で、外部に接続はできない。
・今回した接続方法
ホストOS側のNIC（今回の例で言えば、192.168.56.1）とゲストOS側のNIC（今回の例で言えば、192.168.56.2）を接続した。
【初心者】Java　クラスフィールド・メソッド／カプセル化（ゲッター・セッター）【備忘録２５】

##クラスフィールド・クラスメソッド
###クラスフィールド
インスタンスフィールドがありましたが、クラスに属するクラスフィールド
というものもある。具体例としては、インスタンスがいくつ生成されたのか数える
countというものがある。
【例】

```java
class Person{
 public static int count = 0;
 //...略

Person(String firstName,...);{
 Person.count++;
... //↑こうすることで、インスタンスが生成されるたびに１ずつ足されていく。
```

###クラスメソッド

```java
class Person{
 public static int count = 0;
 //...略
 public static void printCount(){
  System.out.println("合計" + Person.count + "人です");
 }
}
```
クラスメソッドは、インスタンスの生成がない場合でも呼び出すことが可能。

```java
//<Main.java>にて
class Main{
 public static void main(String[]args){
  Person.printCount();
  Person person1 = new Person( //...略 );
  Person.printCount();
 }
}
```
出力：
合計0人です
合計1人です

※クラスフィールドもクラスメソッドも「static」が付くので注意！

###nullを使ったfullNameの書き換え
以前の記事で作成したfullNameの中身は「firstName + lastName」としてましたが
middleNameを追加で入れたい場合の書き方を具体例で書いてみます↓
（middleNameを持っていないインスタンスもあるため、条件分岐で示す）

※何もしていない状態だと、通常middleName(String型)の箇所には「null」が入っている。
（intの場合は0 / doubleの場合は0.0 / booleanの場合はfalse）

```java
class Person{
...
 public String fullName(){
  if (this.middleName == null){
   return this.firstName + " " + this.lastName;
  }else{
   return this.firstname + " " + this.middleName + " " + this.lastName;
  }
}
...
```

##カプセル化
定義したものを触って壊されないようにしておく時に使用する仕組みのこと。
パソコンの内部のようなイメージ。
今までは「public」と書いていたが「private」と書くようにする。
※privateなフィールドにはMainクラスから変更などのアクセスができなくなる。

###ゲッター
privateにした上で、クラス外から安全に値を取得するために
フィールドの値を返す仕組みのこと。「getフィールド名」と書く。

###セッター
privateに設定後、クラス外で値を変更したい際に使う仕組み。「setフィールド名」と書く。

```java
//<Person.java>にて...コンストラクタを書いた後↓
...
 public String getMiddleName() {
  return this.middleName;
 }
//まず、ゲッターを定義した後にセッターを定義
 public void setMiddleName(String middleName) {
  this.middleName=middleName;
 }
...
```

```java
//<Main.java>にて...Person person1 = new Person("山田","花子"...);と書かれている場合。
...
person1.setMiddleName("Claire"); //変更したい場合。

System.out.println("ミドルネームを" + person1.getMiddleName() + "に変更しました");
```

##復習課題に取り掛かってみて
・ゲッターを定義する場合

```java
public String getName(){
 return this.name;
```
上記の際に()を忘れてしまうのでしっかり見直す。覚えなおす。

###今後
一度ここまでのオブジェクト指向を自分で書けるように進歩するために
Progateや他サイトを使いながら書き方を復習しようと思う。
そこでなにか疑問や、わかったところなどあればまた書いてみようと思う。
bootstrap-selectのshow/hide

# 検証時の環境

- bootstrap 4.1.3
- jQuery 3.3.1
- Chrome 79.0

# 背景

画面ロード時に，状態に応じてbootstrap-selectの表示/非表示を切り替えたく，

```javascript
$('#select').show();
```

のようにしていましたが，反映されたりされなかったりでした．

# 結果

以下にたどり着きました．
https://stackoverflow.com/questions/44511501/how-do-i-hide-a-bootstrap-select

「bootstrap-selectは内部的に複数のbuttonに変換されるので親要素に対して適用すべし」とのことなので，適用しました．
いまのところうまくいっている様子です．
【初心者向け】Showing All Issues "アプリ名" requires a provisioning profile. Select a provisioning profile in the Signing & Capabilities editor.が出た時の対処法。

# 解決法
プロビジョニングファイルが設定されていない。
Xcodeのプロジェクトファイルにある、
Signing & Capabilities
→Automatically manage singing
にチェックを入れてTeamの設定をするだけで解決します。
![スクリーンショット 2020-01-16 11.37.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246169/e49ab374-6876-b947-eb26-11140a6c0608.png)
vue-chartjsで棒グラフの左に追加した時にアニメーションが変にならないようにする


[vue-chartjs](https://vue-chartjs.org/)は[Chart.js](https://github.com/chartjs/Chart.js)を[Vue.js](https://vuejs.org/)で使用するためのラッパーです。ちょっと使い方に工夫が必要だったところを見つけたので書いておきます。

工夫が必要だったのは、棒グラフの左にデータを追加した時のアニメーションです。

まずは、きれいに動くようになったアニメーションを見てください。左にデータを5個追加して、その後追加したデータを消しています。
![chartjs_animation_after.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62293/3f03c6fa-b542-83f5-8801-c514fdc824b2.gif)

次に、修正前の、アニメーションがちょっと変な方をみてください。なんか、、よくわからないけど、変ですよね。
![chartjs_animation_before.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/62293/60320013-e558-2fb7-53f5-262be00c8788.gif)

[vue-chartjs](https://vue-chartjs.org/)でグラフを更新したい場合、[vue-chartjs](https://vue-chartjs.org/)のグラフコンポーネントに渡したchartDataを変更すれば自動的に書き換わります。
ですが、アニメーションさせる時に基準にするのがデータの配列のインデックスのようで(下に追記あり)、データの配列の追加や削除をする場合にはアニメーションが変になるらしいです。
配列の一番後ろ（グラフ的には右）に追加や削除をするような場合は問題にならないのですが、配列の先頭（グラフ的には左）に追加する場合は、こうなってしまいます。

解決策として、chartDataを再代入するのではなく、chartDataの要素を変更するようにしました。

つまり、

```js
this.chartData = newChartData;
```

↑こんな感じに再代入する部分を、↓こんなふうに変えます。

```js
this.chartData.labels.unshift('added');
this.chartData.datasets[0].data.unshift(Math.floor(Math.random() * 100));
this.$refs.chart.$data._chart.update();
```

chartDataの要素を変更するだけだと、[vue-chartjs](https://vue-chartjs.org/)的にはchartDataの変更とみなされないので、[Chart.js](https://github.com/chartjs/Chart.js)の更新を明示的に呼んでいます。

サンプルコードは以下をみてください。

<p class="codepen" data-height="265" data-theme-id="dark" data-default-tab="js,result" data-user="akiyah" data-slug-hash="MWYqyNq" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vue-chartjs barchart &amp;quot;add left&amp;quot; animation">
  <span>See the Pen <a href="https://codepen.io/akiyah/pen/MWYqyNq">
  vue-chartjs barchart &quot;add left&quot; animation</a> by mizukoshi akiya (<a href="https://codepen.io/akiyah">@akiyah</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

### 追記

『アニメーションさせる時に基準にするのがデータの配列のインデックスのようで』と書きましたが、少し間違えているようでした。データの配列のインデックスのみを基準にするのであれば、配列の先頭に追加した場合、どうやっても前の配列と比べて対応付けができないですからね。
『chartDataに新しいデータを再代入した場合』に限る話だと思います。chartDataの配列オブジェクトを維持したまま追加や削除をすると、前後での配列の対応付けができていて、アニメーションできるのだと思います。

ちょっとおまけですが、[vue-chartjs](https://vue-chartjs.org/)ではなく[Chart.js](https://github.com/chartjs/Chart.js)で左に追加するサンプルもおいておきます。

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="akiyah" data-slug-hash="qBEMzMZ" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="qBEMzMZ">
  <span>See the Pen <a href="https://codepen.io/akiyah/pen/qBEMzMZ">
  qBEMzMZ</a> by mizukoshi akiya (<a href="https://codepen.io/akiyah">@akiyah</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
babylon.js 最初の一歩: シーンを描画する

WebGL フレームワークに Microsoft の人が作った [babylon.js](https://www.babylonjs.com/) というものがあります。

今回はそれを使ってまず 3D シーンを描画するまでの最初の部分をどう作っていくか紹介します。

今回の完成図↓

<p class="codepen" data-height="265" data-theme-id="default" data-default-tab="js,result" data-user="akai_inu" data-slug-hash="dyPqNXM" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="babylon.js 最初の一歩: シーンを描画する">
  <span>See the Pen <a href="https://codepen.io/akai_inu/pen/dyPqNXM">
  babylon.js 最初の一歩: シーンを描画する</a> by 山岸 "あかいいぬ?" Masaru (<a href="https://codepen.io/akai_inu">@akai_inu</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>


## HTML

```html
<!-- 実際に WebGL を描画するキャンバス -->
<canvas id="renderCanvas"></canvas>

<!-- BabylonJS の最新バージョンへのリンク -->
<script src="https://preview.babylonjs.com/babylon.js"></script>
<!-- 全てのブラウザでポインタイベントに一貫性を持たせるための pep.js のリンク -->
<script src="https://code.jquery.com/pep/0.4.1/pep.js"></script>
```

依存ライブラリに [pep.js](https://github.com/jquery/PEP) というものを要求します。別になくても動作自体はしますが、ないとスマホなどでの操作がおかしくなったりします。

CSS は省略します。

## JavaScript

```js
function main() {
  // canvas DOM 要素を取得する
  const canvas = document.getElementById('renderCanvas');

  // 全ての基礎となる 3D エンジンを生成
  const engine = new BABYLON.Engine(canvas);
  
  function createScene() {
    // 新しいシーンオブジェクトを作成する
    const scene = new BABYLON.Scene(engine);

    // 自由移動出来るカメラを生成
    // ドラッグで視点回転、矢印キーで移動
    const camera = new BABYLON.FreeCamera('camera1', new BABYLON.Vector3(0, 5,-10), scene);

    // カメラの向きを座標0地点にする
    camera.setTarget(BABYLON.Vector3.Zero());

    // canvas 要素をクリックやドラッグなどで操作出来るようにする
    camera.attachControl(canvas, false);

    // 照明を追加
    var light = new BABYLON.HemisphericLight('light1', new BABYLON.Vector3(0,1,0), scene);

    // 球体メッシュを生成
    var sphere = BABYLON.Mesh.CreateSphere('sphere1', 16, 2, scene);

    // 少し上に持ち上げる
    sphere.position.y = 1;

    // 地面メッシュを生成
    var ground = BABYLON.Mesh.CreateGround('ground1', 6, 6, 2, scene);
    
    return scene;
  }
  
  const scene = createScene();

  // 描画ループ関数を定義する
  engine.runRenderLoop(() => {
    scene.render();
  });

  // リサイズ処理
  window.addEventListener('resize', () => {
    engine.resize();
  });
}

// 全ての DOM 要素が読み込み終わってから処理を始める
window.addEventListener('DOMContentLoaded', main);
```

やっていることは単純です。

1. エンジンを生成
2. 3Dシーンを生成
3. シーンにカメラや照明、球体などを追加
4. 描画ループ

という四段階でブラウザ 3D シーンの描画や操作までが可能になっています。シンプルでいいですね。

このサンプルは [doc.babylonjs.com](https://doc.babylonjs.com/) に書かれているものを少し改変したものとなっています。

----

また、 babylon.js は [Playground](https://www.babylonjs-playground.com/) を用意しているので、 CodePen などを使わなくてもより簡単に babylon.js を体験することが可能です。

`createScene` という関数を定義することで、面倒な HTML やリサイズ処理などを省略して書くことが出来ます。

サンプルとして [例えばこちら](https://playground.babylonjs.com/#3I55DK#0) があります。読み込みに少し時間がかかりますが、物理演算を利用した素晴らしいデモが体験できます。
【初心者向け】Could not launch “アプリ名” Verify the Developer App certificate for your account is trusted on your device. が出た時の対処法。

一番最初にXcodeでRunした時にこのようなエラーが出ることがあり、まとまってる記事がなかったので書きました。

```
Could not launch “アプリ名”
Verify the Developer App certificate for your account is trusted on your device. Open Settings on “端末名” and navigate to General -> Device Management, then select your Developer App certificate to trust it.
Internal launch error: process launch failed: Security
```

# 解決法
インストール先の端末で設定を追加する。

 - iOS12
一般→プロファイルとデバイス管理→デベロッパAppを選択→信頼を選択

 - iOS13
一般→デバイス管理→デベロッパAppを選択→信頼を選択

※スクショはiOS12です。

「一般」を選択
![1-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246169/6d77b9ec-75f3-445c-93c3-bf0e0887e997.png)

「プロファイルとデバイス管理」を選択
![2-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246169/88514716-8b69-37fd-eec9-3322d10a2c9d.png)

「デベロッパAppを選択」を選択
![3-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246169/39d7bc5a-217f-3edc-ca87-6d477065186c.png)

「信頼」を選択
![4-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/246169/b69ce5ce-94e1-79f8-ecbe-34c2878145e9.png)
Java 順列の生成

```java
public List<String> permutation(List<String> list, String target, String ans){
  if(target.length() <= 1) {
    list.add(ans + target);
  } else {
    for (int i = 0; i < target.length(); i++) {
      permutation(
        list,
        target.substring(0, i) + target.substring(i + 1),
        ans + target.charAt(i));
    }
  }
  return list;
}
```

[全組み合わせの列挙 Java](https://qiita.com/masakinpo/items/b6ae147d9a61b592240a)
Rustエラーライブラリのトレンド解説（2020年1月版）

# はじめに
この記事は「[Rustのエラーライブラリ利用状況を調べてみた](https://qiita.com/dalance/items/4704b16c0718f6dfb7c0)」の続きです。前回から３ヶ月も経っていませんが、そこそこ大きな変化があったので更新することにしました。

# 2020年1月時点のトレンドグラフ
前回の記事では単に各エラーライブラリの使用数を表にまとめただけでしたが、その後クレートのトレンドグラフを作るcargoサブコマンド[cargo-trend](https://github.com/dalance/cargo-trend)を作ったので、その結果で解説します。
（cargo-trendの紹介は[こちら](https://qiita.com/dalance/items/7a3291b5f89035bc8eaf)）

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/6a0ce5bb-b303-3583-fa52-bde3ea1fc948.png)

縦軸は全クレートに対する割合で、例えば現在のfailureは全クレートの6%程度に使用されています。

冒頭に述べた大きな変化というのはこのfailureの割合が減り始めたということです。
その代わりanyhowとthiserrorが大きくシェアを伸ばしています。
（重なっていて見づらいですが、右下で急上昇中の2つです）

以下は直近1か月で使用率の伸びたクレートトップ5ですが、anyhow/thiserrorの両方が入る結果となりました。

![top5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/84296/5d76bb95-4863-b89a-3bd5-232a149ea844.png)

# anyhowとthiserror
この2つのクレートは昨年11月頃にリリースされました。作者はsynやquoteといったマクロ周りの重要クレートをたくさん作っているdtolnay氏です。出たばかりですがすでにバージョン1.0になっていて、その点でも選びやすい気がします。

2種類あるのは用途が違うためです。ざっくりと言えばanyhowがアプリケーション用、thiserrorがライブラリ用です。
failureでは同じライブラリの使い方を変えることでアプリケーションとライブラリの両方をカバーしていました。
個人的にはこのように別れている方が分かりやすいと思います。

試しに手元のアプリケーションをいくつかanyhowにしてみましたが、ほとんどfailureと同じAPIが提供されているのでuseを書き換えるくらいで簡単に移行できました。

最近cargoのエラーライブラリがfailureからanyhowに変わった（["Migrate from the `failure` crate to `anyhow` #7776"](https://github.com/rust-lang/cargo/pull/7776)）ようですし、今後作るアプリケーションはanyhowで行こうと思います。

# まとめ
まだ当分failureが主流かと思っていましたが、意外と早く世代交代するのかもしれません。
EIZOモニタのカラー調整のメモ

#はじめに
プログラマーは目と腰が大事なのでモニタと椅子は最高グレードのものを使用している。おすすめのモニタ設定を公開します。

#モニタ設定
明るさの数値を小さくし過ぎると逆に目が疲れるので`20`に固定してゲインの数値をすべて`50`以下にした。

```terminal:カラー調整
ブライトネス 20
コントラスト 50
色温度　オフ
ガンマ 2.2

詳細設定
色の濃さ　0
色合い 0
オーバードライブ オフ

ゲイン
R 50
G 40
B 35
```
ROS 1つのノードでパブリッシュとサブスクライブ C++

# 目的
センサーからの情報を常時配信しつつ、センサーの状態を変化させる必要があった。調べてみてもサブスクライブしてメッセージがきたら内容を処理してパブリッシュは多いけど、あまり無かったため投稿しました。

# 動作イメージ

AさんはBさんに対して1秒間隔で常に「Like」と言っている。
![Screenshot from 2020-01-16 11-48-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269060/347a5766-4262-fae0-ed0e-43906e7b5b03.png)

CさんはAさんに対して「Bさんの悪口」を任意のタインミングで言った。心の清らかなAさんは、Cさんに言われたことを鵜呑みして、Bさんに対する言う内容を「Dislike」と変化させた。

![Screenshot from 2020-01-16 11-49-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/269060/1d9a3535-0386-66aa-3ccd-cf26ccc1f047.png)

動作イメージ的にはこんな感じとなります。
ここで重要なのは、Cさんの任意のタイミングでBさんに対するAさんの配信内容を変更するということです。
これによって、起動初期だけでなく、動作中にもAさんの設定を変更することができます。

実際には、
Aさん　センサー
Bさん　センサーデータ配信先
Cさん　センサーのコントロール
という感じとなります。


# 処理
サブスクライブとパブリッシュでそれぞれスレッドを立てて処理を行います。

サブスクライブの内容
トピック名　control　、型　std_msgs/Int8

パブリッシュの内容
トピック名　/pubsub　、型　std_msgs/String

１秒間隔で、/pubsubに「Like」という文字列を配信する。
/controlに data: 0 と配信された場合に「Dislike」に文字列を置き換える。
/controlに data: N (N > 0)と配信された場合は、1秒間にN回の配信を行う。

# コード

メイン

```pubsubtest.cpp
#include "pubsubtest.h"

PubSubTest::PubSubTest(ros::NodeHandle &_nh){
    nh = _nh;
    pub = nh.advertise<std_msgs::String>("pubsub", 1);
    // Publishする間隔の初期値設定
    rate = new ros::Rate(1);

    // サブスクライブのスレッドを用意
    std::thread th([this]() {this->thSub(); });

    // Detachで実行
    th.detach();

    // Publishの処理
    run();
}

void PubSubTest::run(){
    while(ros::ok()){
        std::string s = "Like";
        // メンバ変数selによる場合分け
        switch(sel){
        case -1:
            s = "Dislike";
            break;
        default:
            break;
        }
        std_msgs::String data;
        data.data = s;
        //  文字列のパブリッシュ
        pub.publish(data);
        //  パブリッシュ間隔のためのsleep()
        rate->sleep();
    }
}

void PubSubTest::cbInt8(const std_msgs::Int8 &msg){
    int8_t data = msg.data;
    ROS_INFO("Get Control Data: %d", data);
    if(data > 0){
        // data > 0 以上ならパブリッシュ間隔の変更を行う
        rate = new ros::Rate(data);
    }else{
        // data <= 0 なら メンバ変数にdataを格納
        sel = data;
    }
}

void PubSubTest::thSub(){
    // Callbackの登録
    sub = nh.subscribe("control", 10, &PubSubTest::cbInt8, this);

    // これが無いとサブスクライブをしてくれません。
    ros::spin();
}

int main(int argc, char **argv){
    ros::init(argc, argv, "pubsubtest");
    ros::NodeHandle nh;
    PubSubTest pubsubtest(nh);
    return 0;
}
```

ヘッダー

```pubsubtest.h
#ifndef PUBSUB_TEST_H_
#define PUBSUB_TEST_T_

#include "ros/ros.h"
#include "std_msgs/Int8.h"
#include "std_msgs/String.h"

#include <iostream>
#include <thread>

class PubSubTest
{
private:
    ros::NodeHandle nh;
    ros::Publisher pub;
    ros::Subscriber sub;
    int8_t sel;
    ros::Rate *rate;
public:
    PubSubTest(ros::NodeHandle &_nh);
    // Subscribe Thread Function
    void thSub();
    // Subscribe Function
    void cbInt8(const std_msgs::Int8 &msg);
    // Publish Function
    void run();
};

#endif
```

# まとめ
コントロール用ノード（GUI兼用ノードなどで）で各ノードの設定を制御したい場合などには使えると思います。
nRF52832でsaadcのサンプルコードを実行する

##目次
- [はじめに](#anchor1)
- [セットアップ](#anchor2)
 - [サンプルコードの取得](#an1)
 - [書き込みを行う](#an2)
 - [出力をシリアルモニタで見る](#an3)
-  [プログラムの確認](#anchor3)
-  [最後に](#anchor4)

<a id="anchor1"></a>
##はじめに
SAADCの機能を使うサンプルコードを動かした。この記事は作業の備忘録、そしてエラー原因を共有するために作成した。

<a id="anchor2"></a>
##セットアップ
[Nordic公式サイト](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.sdk5.v13.0.0%2Fnrf_dev_saadc_example.html)を参考にして以下の作業を行った。開発環境はOSX10.15.2、SDKはnRF5 SDK v13.0.0である。

<a id="an1"></a>
###サンプルコードの取得
1.  [本サイト](https://developer.nordicsemi.com/nRF5_SDK/nRF5_SDK_v13.x.x/)の`nRF5_SDK_13.0.0_04a0bfd.zip`をクリックし、ダウンロードする。
2. コンピュータ内で解凍する。

<a id="an2"></a>
###書き込みを行う

1.  ターミナルを起動。
2.  ```cd /nRF5_SDK_13.0.0_04a0bfd/examples/peripheral/saadc/pca10040/blank/armgcc```を実行。
3. ```make flash```を実行。

<a id="an3"></a>
###出力をシリアルモニタで見る

1. `ls /dev/tty.usb*`でデバイス名を確認する。<br>(出力例)`/dev/tty.usbmodem0006827997481`
2.  1.で出力されたデバイス名をコピーする。
3.  `screen (デバイス名) 115200,cs8,-parenb,-cstopb`(デバイス名はペーストする)<br>(入力例)
`screen /dev/tty.usbmodem0006827997481 115200,cs8,-parenb,-cstopb`
4. analog_pin2(P0.28)とGNDを導線で結ぶ。(analog _pin2(P0.28)に0Vを入力ß)
5. 値を確認する。<br>(出力例)<br>
APP:INFO:ADC event number: 48<br>
APP:INFO:18<br>
APP:INFO:18<br>
APP:INFO:18<br>
APP:INFO:18<br>
APP:INFO:18
6. GNDに刺さっていた導線を5Vに差し替える。(analog _pin2(P0.28)に5Vを入力)
7.  値を確認する。<br>(出力例)<br>
APP:INFO:SAADC HAL simple example.<br>
APP:INFO:ADC event number: 0<br>
APP:INFO:562<br>
APP:INFO:563<br>
APP:INFO:563<br>
APP:INFO:562<br>
APP:INFO:562
 
<a id="anchor3"></a>
##プログラムの確認
このプログラムでは基本的にスリープモードに入って電力消費を抑えている。そして、イベントが発生する場合はイベントの割り込みが発生し、スリープから離脱し、各機能の動作が実行される。
###nrf _drv _power _init()
有効な電源モジュールドライバーは、電源システムからのすべての割り込みを処理。
###nrf _pwr _mgmt _init()
power_managementを初期化。
###saadc _init()
saadcの初期化。<br>
saadcチャンネルの有効化。<br>
データをSAMPLES _IN _BUFFERのサイズのバッファーに変換する。

###saadc _sampling _event _init()
PPIモジュールの初期化。<br>
timer _handlerの初期化。<br>
400ms毎にm _timerへ時間を送る。<br>
m _timerへのcompare channnelの割り込み禁止。<br>
m _timerの起動。<br>
m _ppi _channelをPPI channelに割り当てる。<br>
timer _compare _event _addrとsaadc _sample _task _addrをm _ppi _channelに割り当てる。

###saadc _sampling _event _enable()
 m _ppi _channelを有効にする。

<a id="anchor4"></a>
##最後に
Nordic公式サイトではpin2とGND,VCCを接続するように記されている。インターネットで調べると、使用するマイコンのpin2はP0.00と接続されていると書かれている。そのため筆者は一度P0.00とGND,5Vの変化をみたのだが、出力の変化がなかった。ここではSAADCを使うため、analog_pinのpin番号2(P0.28)と接続することに注意されたい。
gitで間違えてmainにpushしてしまった時

# mainにpush...
常に自身のいるブランチを意識していたはずなのに、うっかりやってしまった・・・個人的には焦る瞬間です。この時にはどうすればいいのか・・・間違った対処と正しい対処の二つを書こうと思います。

## 間違った対処(あまりよろしくない)

```
$ git reset --hard
$ git push origin main -f
```

ログを抹消してなかったことにしようとするのを思いつきそうですが、これは自分の作業内容を完全に吹っ飛ばしますし、mainへのpushを-fつけて強制で行うと、もし、自分のローカルmainがリモートにあるmainより古いものだったら、**その古いところまで逆戻りさせることになるので、他の人の作業内容も吹っ飛ぶことになります。**実際自分は五日分の時間を巻き戻しました。運よく、最新のmainを大ベテランの方がローカルに持っていてくれたおかげでことなきを得ましたが、本当に心臓に悪いです。私は若干の吐き気を催しました。mainを最新で持っていたとしても、やった内容が吹き飛ぶのでやるのはよくないです。

## 正しい対処

```
$ git checkout main
$ git pull
$ git checkout -b 取消用のブランチ名


自分の作業内容を元に戻す


$ git push origin 取消用のブランチ名

github上でmergeする
```
で、その後に、gitのコミットの差分状から作業内容を復帰させて、作業ブランチ上で、pushする。

もしくは

```
$ git log

自分の間違えたコミットのIDを見つける

$ git revert 間違えたコミットのID

$ git pull
$ git checkout 本来のpushすべき作業ブランチ
$ git merge master
$ git add .
$ git commit -m "コミットメッセージ"
$ git push origin 本来のpushすべき作業ブランチ
```
git revertは引数に指定したコミットを取消し、addする前まで戻してくれます。念のため、ローカルのmasterをpullで最新にし、作業ブランチでも最新の状態をmergeで反映させてから、本来自分がpushすべきだった作業ブランチへpushします。

# まとめ
revertを使う方法が、gitの方では推奨されているようです。
両者の手法はログを汚すことになりますが、こちらの方が間違いはなく、かつ安心です。そしてすぐに申し訳ありませんと言うということです。
【swift】userDefaultsへの書き込み・読み込みを簡易化する

## 環境
xcode 11.3 
swift 5.1.3
CocoaPods 1.8.4

## 方針
@noby111さんの記事「[Swifterを自分のアプリに組み込む方法](https://qiita.com/noby111/items/532f3d806b19ab46433a)」を参考にしていた時に以下の方法がさらっと用いられていていいなと思ったので、これだけでまとめました。

AppStatusクラスを作って、クラス変数にアクセスする方法でuserDefault内のデータにアクセスできるようにする

```swift:
let appData = AppStatus()

//データの入力
appData.username = "test user"
// データの出力
print(appData.username)
```

```:出力
test user
```

## 実装
AppStatus.swiftファイルを新たに作成し、以下を記述

```swift:AppStatus.swift
import Foundation
import UIKit

class AppStatus {
    var userdefault = UserDefaults.init(suiteName: "app_status")!
    
    // usernameの設定
    var username : String? {
        get {
            if let username : String = userdefault["username"] {
                return username
            } else {
                return nil
            }
        }

        set {
            userdefault["username"] = newValue
        }
    }
}

extension UserDefaults {
    subscript<T: Any>(key: String) -> T? {
        get {
            if let value = object(forKey: key) {
                return value as? T
            } else {
                return nil
            }
        }
        
        set(_newValue) {
            if let newValue = _newValue {
                set(newValue, forKey: key)
            } else {
                removeObject(forKey: key)
            }
            synchronize()
        }
    }
}

```

usernameの部分と型を変更すればuserDefaulに保存可能な任意のデータ型を扱うことができる。
これ便利。

## userDefaultsの使い方
ちなみに、userDefaultとはなんぞや、とかどうやって使うの、とかは以下の記事が参考になりました。

>[qiita : swift4　超初心者向け！"UserDefaults"の使い方とか　忘備録](https://qiita.com/ryomaDsakamoto/items/6c25d8c39c1fe6cf3d7a)

>[qiita : UserDefaultsの使い方](https://qiita.com/yohei_nakamura/items/e6a097db7b117184bebc)
MessageKitをクローンしたがビルドができなかった話

#はじめに

[MessageKit](https://github.com/MessageKit/MessageKit)とはiOSアプリでLINEのようなチャット画面を簡単に作成することができるframeworkであり、cocoapodsでinstallできる。
ただ使い方がよく分からなかったので、クローンしてサンプルプロジェクト(MessageKit/Example/ChatExample.xcworkspace)を触ろうとしたがビルドが通らなかった。

#エラー文

```
.../MessageKit/Example/Pods/Target Support Files/ Pods-ChatExample/Pods-ChatExample.debug.xcconfig: unable open file (in target "ChatExample" in project "ChatExample") (in target 'ChatExample')
```

#解決策
ChatExample.xcworkspaceを削除し、

```
pod install
```

を実行。失敗。エラー文は以下

```
Fetching podspec for `MessageKit` from `../`
[!] CocoaPods could not find compatible versions for pod "InputBarAccessoryView":
  In snapshot (Podfile.lock):
    InputBarAccessoryView (= 4.2.2)

  In Podfile:
    MessageKit (from `../`) was resolved to 3.0.0, which depends on
      InputBarAccessoryView (~> 4.2.2)

None of your spec sources contain a spec satisfying the dependencies: `InputBarAccessoryView (= 4.2.2), InputBarAccessoryView (~> 4.2.2)`.
```

よく分からんが要はキャッシュを手動で更新してやる必要があるらしい。(参考[pod install でライブラリの最新バージョンが入らないときの対処](https://qiita.com/msh5/items/c35717b27975c9e48d15))

```
pod repo update
pod install
```

通った。

#結果

見れた。めでたしめでたし。
<img width="395" alt="スクリーンショット 2020-01-16 17.31.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/262342/c361d011-f791-146b-c877-c5b6a209b0e2.png">
composer 実行時に Allowed memory size エラーで困ったとき

composer update を実行したら、いきなり怒られるようになりました。

```
# composer update

Fatal error: Allowed memory size of 1073741824 bytes exhausted (tried to allocate 16777216 bytes) in phar:///usr/local/bin/composer/src/Composer/DependencyResolver/Solver.php on line 220
```

そんな時は、実行時のメモリ制限を切って対応しましょう。

```
php -d memory_limit=-1 /usr/local/bin/composer update
```

composerコマンドの配備先については、各環境で合わせて下さい。
[Android] ServiceとIntentServiceの違い

##Serivce
Serviceについては以前触れたので、こちらの記事を参照願いたい。

・Service
https://qiita.com/QiitaD/items/5c313076b7b99823ce1a

・IntentService
https://qiita.com/QiitaD/items/96e70cd189d0c4385393

##終了方法
Serviceは終了するときにStopService()かstopSelf()を明示的に書かなければ終了しない。しかし、IntentServiceの場合はそれをする必要がなく、処理が終わったら自動的に終了してくれる。

##スレッド
Serviceは**Activityと同じUIスレッド（メインスレッド）**で動いているが、IntentServiceは**メインスレッドとは別のスレッド（内部のHandlerThread）**で動いている。

そのため例えば、HTTP通信をServiceに任せる時、IntentServiceは非同期処理に向いているので通信できる。しかしServiceクラスで行おうとすると「**NetworkOnMainThreadException**」が発生する。

またIntentServiceはUIスレッドで動いていないので、**Viewを操作できない。**（BroadcastReceiverやCallBackを使わなければならない。）
ネットに転がっているサンプルにはToastをプログラム内に組み込んでいるものもあったが、Toastも出なかった。（Handler使えば可能になるという記事もあった https://qiita.com/wakwak/items/5a03127aba3effa845f8）

##感想
非同期処理関連はService以外にもAsyncTaskがあるのでかなり厄介に感じた。向いてないクラスを使うと、品質を落としかねないので気を付けたい。

##参考URL

・Android 非同期処理についてまとめるメモ
https://qiita.com/tk_daze/items/bc83c69750e5f2e4015c

・IntentService　と　Serviceの違い
https://oc-technote.com/android/intentservice%e3%80%80%e3%81%a8%e3%80%80service%e3%81%ae%e9%81%95%e3%81%84/
rbenv install 2.7.0＠WSL1, Hyper-Vの時間比較メモ

# インストール時間の比較メモ
- ダウンロード含むので厳密な比較になっていない
- CPUコア使い切ってなさそう
- わかってたけどWSL1遅い
    - WSL2で試してみる（そのうち）

### WSL1

```
~$ uname -a
Linux Win10-Ryzen 4.4.0-18362-Microsoft #476-Microsoft Fri Nov 01 16:53:00 PST 2019 x86_64 x86_64 x86_64 GNU/Linux

~$ \time rbenv install 2.7.0
Downloading ruby-2.7.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2
Installing ruby-2.7.0...
Installed ruby-2.7.0 to /home/tetsuya/.rbenv/versions/2.7.0

273.00user 208.20system 4:39.22elapsed 172%CPU (0avgtext+0avgdata 336612maxresident)k
0inputs+0outputs (0major+16970166minor)pagefaults 0swaps
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33946/426fc746-6369-6f6c-19f5-dedca5ca46e6.png)

### Hyper-V
CPU：24コア
メモリ：8GB 固定割り当て

```
~$ uname -a
Linux tetsuyainfra-ubuntu18 5.0.0-37-generic #40~18.04.1-Ubuntu SMP Thu Nov 14 12:06:39 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

~$ \time rbenv install 2.7.0
Downloading ruby-2.7.0.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0.tar.bz2
Installing ruby-2.7.0...
Installed ruby-2.7.0 to /home/tetsuyainfra/.rbenv/versions/2.7.0

277.30user 25.25system 1:26.42elapsed 350%CPU (0avgtext+0avgdata 339192maxresident)k
112928inputs+3534832outputs (396major+12598666minor)pagefaults 0swaps
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33946/0932d011-44bc-a6b2-7a4c-742222587f92.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33946/c63a2432-147a-405f-ecf3-255441f0aa5f.png)
AWS EC2インスタンスの複製をしてみた。その6（備忘録）

前回の続きです。https://qiita.com/Bikeiken-IT/items/6c885d40fd92b1a6dee9

AMIからEC2インスタンスを複製しました。続きまして、Snapshot機能を用いて新しく作成したEC2インスタンスにストレージをアタッチします。

![step33-stop-EC2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/0fa00627-98e0-ec54-ab75-23eec8c763e0.png)
その前に、EC2-test-2のボリューム（ストレージに相当するもの）をデタッチしなければなりません。そのために、EC2-test-2を停止させます。
![step34-stop-EC2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/286c2384-fe54-427d-240d-b09e948e2c0f.png)
インスタンスの状態が"stopped"と表示されていれば、EC2インスタンスは停止しています。
![step35-snapshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/c1635373-fe2f-9ea1-ebb4-cd524e99a703.png)
続いて、Snapshotを作成します。
画面左のスクロールからボリュームを選択してください。
そして、EC2-test-1のボリュームであるtest-1を本来は選択します。（画面上ではtest-2(EC2-test-2)となっています。こちらのミスです。しかし、目的は複製なのでtest-1を選択すべきでした。）
次に、アクションからスナップショットの作成を選択してください。
![step36-snapshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/3b285dea-8601-443e-2952-7814f4bd2744.png)
スナップショットの説明の入力を行い、スナップショットの作成のボタンを押してください。
これでEC2-test-1のボリュームのSnapshotは作成されます。
![step44-attatch-info(to step42).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/71222332-ba8f-272f-f926-2080ea9fc659.png)
その前に、現在のtest-2のあるディレクトリを控えておく必要があります。
画面左のスクロールからボリュームを選択します。test-2を選択すると、説明欄に赤丸で囲った部分が表示されます。
今回の場合は/dev/xvdaです。
Snapshotから作られたボリュームをtest-2にアタッチする際に必要となります。メモ帳などに保存しておくことをおすすめします。
![step37-detatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/bdcd711f-04fd-c099-981b-725afbe0e243.png)
続いて、先ほどSnapshotから作成したEC2-test-1のボリュームをEC2-test-2にアタッチするために、現在EC2-test-2にアタッチされているボリュームをデタッチします。（表現が分かりづらくて申し訳ありません。）
![step38-detatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/6fd9f8ce-f5c6-9d7e-4c07-f12d2d9fb8cb.png)
デタッチするというボタンを押します。これでtest-2のボリュームをデタッチできます。
![step39-volume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/5b536106-08c1-0c43-5a0e-5e5d61c85ccb.png)
次に、先ほど作成したSnapshotからボリュームを作成します。
作成したSnapshotを選択して、アクションからボリュームの作成を選んでください。
![step40-volume.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550376/8811a62a-c2c1-99f2-7929-ee4a5ea02083.png)
デフォルトのままボリュームの作成のボタンを押します。

これでEC2-test-1のスナップショットからボリュームを作成しました。
EC2-test-2のボリュームのデタッチも終えているため、後はスナップショットから作成したボリュームをEC2-test-2にアタッチする工程だけです。

その７に続きます。https://qiita.com/Bikeiken-IT/items/baac8bd1e4cfdfe3af51
Flutter 全面にローディングを表示させるサンプル


# 実現したいこと
なにか処理中で、操作を受け付けれないような状態の時に、
全画面でローディングを表示させるやりかたについて書きたいと思います。

## 動作の様子

ボタンを押すとローディングが表示。２秒後に自動的に閉じます。
<img width="300" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6327/adcfe3f8-bbb2-0ad3-5576-61fd41ac9151.gif">

### 動作コード
こちらに一式用意しています。
https://github.com/quqjp/flutter-test

コード箇所はこちら。
https://github.com/quqjp/flutter-test/tree/master/lib/sample1

## 構成
ローディング表示のWidget OverlayLoadingMolecules を作成。  
組み込む側メインのコードにて、Stack Widget を用いて最前面に配置します。

### ローディングWidget OverlayLoadingMolecules

表示の状態 visible プロパティを持ち表示を外部から制御できるようになっています。
非表示時は、空のContainer()が表示されます。
くるくるローディング表示自体は、CircularProgressIndicator Widget を用いた。

```dart
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

//
// 全面表示のローディング
//
class OverlayLoadingMolecules extends StatelessWidget {
  OverlayLoadingMolecules({@required this.visible});

  //表示状態
  final bool visible;

  @override
  Widget build(BuildContext context) {
    return visible
        ? Container(
            decoration: new BoxDecoration(
              color: Color.fromRGBO(0, 0, 0, 0.6),
            ),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                CircularProgressIndicator(
                    valueColor: new AlwaysStoppedAnimation<Color>(Colors.white))
              ],
            ),
          )
        : Container();
  }
}
```
---

### 組み込む側メインのコード

```dart

//dart package
import 'package:flutter/material.dart';

//third party package

//my package

//same package
import "overlay_loading_molecules.dart";

//
// 全面にローディングを表示させるサンプル
//
class Sample1Page extends StatefulWidget {
  Sample1Page({Key key, this.title}) : super(key: key);

  // タイトル
  final String title;

  @override
  _State createState() => _State();
}

class _State extends State<Sample1Page> {
  //ローディング表示の状態
  bool visibleLoading = false;

  @override
  void initState() {
    super.initState();
  }

  //
  //
  // ボタンハンドラ
  onPressMyButton() async {
    //ローディングを表示
    setState(() {
      visibleLoading = true;
    });

    //２秒待つ
    await Future.delayed(const Duration(milliseconds: 2000), () {});

    //ローディングを非表示
    setState(() {
      visibleLoading = false;
    });
  }

  ///
  ///
  ///
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      //
      body: ClipRect(
        child: Stack(
          fit: StackFit.expand,
          overflow: Overflow.clip,
          children: <Widget>[
            Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                //
                //ローディングを表示させるためのボタン
                RaisedButton(
                  onPressed: onPressMyButton,
                  child: Text('ローディングを表示', style: TextStyle(fontSize: 20)),
                ),
              ],
            ),
            //
            //ローディング
            OverlayLoadingMolecules(visible: visibleLoading)
          ],
        ),
      ),
    );
  }
}
```

## まとめ
flutter で全面にローディングを表示させる方法をまとめました。
flutter初学者のため、アドバイスなどいただけると嬉しいです。
会社のProxy Serverは社員のSSL通信をどこまで把握しているのか

## 調べるにあたった経緯

会社で調べ物をしている最中にふと思った、
「自分がアクセスしているサイトやその通信内容はどこまで会社は知っているんだろうか？」
と。
 ~~決してやましいサイトにアクセスしていたわけじゃないです。~~

 IT系ではない会社にいたときは、簡単に調べて
 「会社にはどんなサイトにアクセスしているかはバレバレなんだろう」
 と漠然とした認識でいましたが、今の私はエンジニアの端くれ。
 仕組みを改めて調べて知っておこうと思い、
 Proxy Serverにたどり着いたので今回はそれを調べてまとめました。

## まずProxy Serverとは

一言でいえば、**社内のパソコンとインターネットをつなぐ関所的**なやつ。

ちなみに必ずしも全ての企業に導入されているわけではなく、
導入の有無やその機能については企業毎に異なります。

### 主な機能

1.クライアントからのインターネットへのアクセスを代理で行う
2.アクセスしたページをキャッシュとして保存し、次回のクライアントの要求に高速で応える
**3.社内のPCからアクセスしたサイトのログ保存＆監視**
**4.有害なサイトをブラックリスト化し、アクセスを禁止する**
5.アクセス先にはプロキシサーバーのグローバルIPアドレスを表示（クライアントのIPアドレスを秘匿）

特に3・4が重要かと思われる ~~（個人的に）~~
では、具体的にログでどこまで通信内容がわかるのか

## Proxy Serverがわかること

### 通常のhttpによる通信

![http.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444546/51537b6c-1a74-824c-b107-e61dc5a04d48.png)
※Qiitaのネットワーク図は適当です

つまり
どのサーバーのどのファイルにアクセスしたか
どんなリクエスト内容かがほぼわかってしまう。

### https（SSL）による通信

![https.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/444546/d40b8d84-30e0-5902-133e-ab903beacadf.png)
※Qiitaのネットワーク図は適当です

どのサーバーにアクセスしたかはわかるが
どんな内容だったかまではわからない。

### やろうと思えばできること

上記のように、http通信などでリクエストパラメーターが平文である場合、
内容を改ざんしてサイト側にリクエストを飛ばすことなどもできてしまう。
今どきはサーバー側で計算すると思われるが、一昔のスマホアプリなどで
apiに投げる値をクライアント側で計算して値を渡す方式で無対策だった場合、
プロキシサーバー側でデータを改ざんして送ることもできたらしい。

## 結論

ProxyServerを導入してる企業では、
通信内容はわからないが、**どのサイトにアクセスしてるかはバレてる。**

## 参考サイト

* [https通信で暗号化したURLアクセスはProxyサーバでどこまで見えるのか？ログを確認](https://blog.putise.com/https%E3%81%A7%E6%9A%97%E5%8F%B7%E5%8C%96%E3%81%95%E3%82%8C%E3%81%9F%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%AFurl%E3%83%91%E3%82%B9%E3%82%82%E8%A6%8B%E3%81%88%E3%81%AA%E3%81%84%E3%81%AE%E3%81%8B/)

* [【図解】httpプロキシサーバの仕組み(http GET/https CONNECTメソッド)や必要性・役割・メリットデメリット・DNSの名前解決の順序](https://milestone-of-se.nesuke.com/nw-basic/grasp-nw/proxy/)

* [プロキシ・サーバー](https://tech.nikkeibp.co.jp/it/article/COLUMN/20060825/246379/)

* [HTTPS通信とプロキシサーバ（CONNECTメソッド）](http://nw.seeeko.com/archives/50879231.html)
Next.jsでFirebase analyticsを使用する場合の注意

## 概要
Next.jsにanalyticsを導入時に起きた問題を投稿します。

## 現象
Next.jsなどでanalyticsを使用する際にサーバー側でエラーが発生する。

## 理由
analyticsの内部でwindowが呼ばれていたため

## 解決法
```js
if (process.browser) {
    firebase.analytics().logEvent(<イベント名>);
}
```
Laravelで現在日時を指定できるプラグインを作った

`Carbon` を正しく使っているプロジェクトに限るけど、現在日時を指定してアプリケーションを動かせるプラグインを作った。
スタンドアロンのサーバ `php artisan serve` を1999年7月31日として実行したい場合は以下のように環境変数で日付を指定できる。

```bash
$ LARAVEL_NOW=1999-7-31 php artisan serve
```

`Carbon` がパースできる書式なら自由に指定できるので、日次バッチを昨日の日付で動かすこともできる。

```bash
# 昨日の日付として動作確認できる！
$ LARAVEL_NOW=yesterday php artisan app:daily-job
```

プラグインの中で `Carbon::setTestNow()` でセットしているだけ。動作確認するときにソースコードを変更せずに外部から指定できるので少し便利になった。

https://github.com/grohiro/laravel-now
Scipy > FortranFile() > big endianでのFortran用データファイルの作成

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2 
32GB RAM 
CentOS Linux release 7.7.1908 (Core)
Python 3.6.8 (default, Aug  7 2019, 17:28:10) 
IPython 7.9.0 -- An enhanced Interactive Python. Type '?' for help.
Scipy v1.4.1
```

### 概要

- big endianでintegerの値を書き出す
- Fortranのunformatted, sequential, big_endianで読める形式にする
    - [WRF / WPS > Fortran90 > metgrid.exeで読込む中間ファイルのReadプログラム](https://qiita.com/7of9/items/f1f0c85432010cea1d3c)
        - のversion


### 実装

np.arrayを使ってendianを指定する方法で成功した。
versionという変数がbig endianのintegerとして書出しできた。

```python: 
import numpy
from scipy.io import FortranFile

frt = FortranFile('SST_met', 'w')
version = 5
frt.write_record(np.array([version], dtype='>i4'))
frt.close()
```
作業ブランチを最新に更新する方法

# Gitを理解するために結構アウトプットしてきたのに
今まで、結構gitに関する自分の覚書だったり、仕組みを理解するための記事だったりをアウトプットしてきたのですが、そも、コンフリクトを起こさないようにするためにはどうしたらいいのかなど、仕組みを理解しても、実践的に扱うことに特化したアウトプットができていなかったのには問題があった。頭でっかちの典型に自分が陥っていたことを踏まえ、反省と習慣化させるために、アウトプットします。

こちらは以前まとめたgitコマンドの記事です。
[機能だけで覚える基本的なGitコマンド　〜ほぼほぼ作業順〜　
](https://qiita.com/Nedward/items/12b6b86a39795aa5201b)

## 朝はmainを頂くことから始める
複数人開発において、gitをいじるのは当然で、きっとリモートのmainは明日になる頃には、自分が昨日いたところから進んでいる可能性がある。

だから、まず、ローカルのmainへ移動、リモートのmainをゲット。

```terminal
$ git switch main
$ git pull origin main
```

加えて、自分の作業ブランチが昨日の段階で切られていた場合、その作業ブランチに対しても、その最新のmasterの内容を反映させてあげてから、自分の今持っている作業に取り掛かることが必要です。

```terminal
$ git switch 作業ブランチ名
$ git merge main
```

これで、安心して自分の作業に戻ることができます。

## 何で朝？それは私の人間性
作業してから後でmasterを反映させるでも問題ないのですが、私のような人間は忘れたり、取り掛かっている作業を終えた達成感で反映させることを吹っ飛ばすとか平気でやってしまう性格なので、いっちゃん先にやる癖をつけた方がいいと思って、朝まずやろう！という風に自分の中で設定しました。

## ミスを無くすために・・・
そもそも、作業ブランチで作業してたらそもそもコンフリクトなんてしないだろ、自分しか触っていないんだから、という視点にだってなれるはず・・・でもなれなかった・・・それはルーティン化にばかり意識していて、仕組みから自身で考察することを疎かにしていたからである。
機械学習超入門　確率モデルと最尤推定編

# はじめに
　このシリーズは、私個人の学習及びその備忘録として記述するものですが、せっかくですので学んだ内容を皆さんとシェアできればと思い投稿させていただいています。
　主に機械学習やディープラーニングを勉強する中で出てくる用語の整理等を行います。
　今回は機械学習のモデルで登場する確率モデルと最尤推定について、その概要をまとめていきます。

## 確率モデル

　確率モデルは、変数xがパラメータθを持つある確率分布```P(x|θ)```から生成されていると仮定したモデルのことを指します。

```math:確率モデル
x ~ P(x|\theta)
```

##### 例）正規分布
　xが連続変数の場合は正規分布となります。

```math:正規分布
N(x|\mu, \sigma^2) = \frac{1}{\sqrt{2\pi \sigma^2}} exp \begin{bmatrix} - \frac{(x-\mu)^2}{2\sigma^2} \end{bmatrix}
```


##### 例）ベルヌーイ分布
　離散変数、特に恋んトスなどのような0か1をとる場合はベルヌーイ分布と呼ばれます。

```math:ベルヌーイ分布
B(x|p) = p^x(1-p)^{1-x}
```


## 尤度（ゆうど）
　ある互いに独立なNこのデータX=(x0, x1, ...)が与えられたとき、以下のように各データの確率関数の値の積をθの関数とすると、これはシータの尤（もっと）もらしさとなり、尤度（ゆうど、Likelihood）と呼びます。

```math:尤度
L(\theta) = \prod_{n}P(x_n|\theta)
```

　尤度は確率モデルで最も重要な量であり、尤度を最大にするようなパラメータθを求めることを最尤推定（さいゆうすいてい、Maximum Likelihood Estimation, MLE）といいます。
　通常は、計算のしやすさなどから下のような対数尤度の形で扱うそうです。

```math:対数尤度
lnL(\theta) = \sum_nlnP(x_n|\theta)
```

##### 例）正規分布の期待値パラメータμの最尤推定
　対数尤度をμについて偏微分し、値が0になる方程式を解くことで求められます（結果的に、期待値パラメータμの最尤推定はすべてのｘの平均値となります）。

```math:正規分布の期待値パラメータμの最尤推定
lnL(\theta) = - \frac{N}{2}ln2\pi\sigma^2 - \frac{1}{2\sigma^2}\sum_n(x_n-\mu)^2\\
\frac{\delta}{\delta_p}lnL(\theta) = - \frac{1}{\sigma^2}\sum_n(x_n - \mu) = 0 \\
\mu = \frac{1}{N}\sum_nx_n = \bar{x} 
```

##### 例）ベルヌーイ分布のpの最尤推定
　同様にベルヌーイ分布についてもpの最尤推定を解くと次のようになります。ここで、x=1の個数をMとすると

```math:ベルヌーイ分布の最尤推定
\sum_nx_n = M \\
lnL(\theta) = \sum_nx_nlnp + (1 - x_n)ln (1 - p) \\
=Nlnp + (N - M)ln(1 - p) \\
\frac{\delta}{\delta_p}lnL(\theta) = - \frac{M}{p} + \frac{N -M}{1 -p} = 0 \\
p = \frac{M}{N}
```
となり、pはx=1の回数の割合という結果になります。


## おわりに
　このシリーズはこのくらいのボリューム感で必要な部分だけをおさえていこうと思います。
　次回は確率的勾配降下法についてまとめていこうと思いますので、ぜひそちらもご覧ください。
　それでは最後までご閲覧頂き、ありがとうございました。
swift version切り替える

Swiftバージョンを切り替える方法をメモします。

## swiftenvのインストール

https://swiftenv.fuller.li/en/latest/installation.html

git cloneとHomebrewでのインストール方法を記載してくれています。
今回はHomebrewでインストール。

まずは、インストール

```
brew install kylef/formulae/swiftenv`
```

次に.bash_profileにパスの追加

```
echo 'if which swiftenv > /dev/null; then eval "$(swiftenv init -)"; fi' >> ~/.bash_profile`
```

ローカルのSwiftバージョン確認

```
$ swiftenv versions
* system
  5.1.3
```

## ローカルのSwiftバージョンの変更

Swift バージョンのインストール

```
$ swiftenv install 5.0.1
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  305M  100  305M    0     0  2036k      0  0:02:33  0:02:33 --:--:-- 3658k
Password:
installer: Package name is Swift Open Source Xcode Toolchain
installer: Installing at base path /
installer: The install was successful.
5.0.1 has been installed.
```

新しいSwiftバージョンをインストールしたら、こちらのコマンドの実行が必要のよう。

```
$ swiftenv rehash
```

ローカルのSwiftバージョン確認

```
swiftenv versions
* 5.0.1
  5.1.3
```

無事に目的のSwift バージョンに切り替わってました:clap:

メモ：
Carthageが利用するSwiftバージョンが切り替わらない...誰か解る人いたら教えてください。

https://github.com/kylef/swiftenv/issues/145
I2Cケーブルにカテゴリー6AのLANケーブル使ってみたらノイズの影響受けにくくなった話


## 背景

ホビーユースの基板ではセンサーと基板間の通信にI2Cを使ったものがあります。I2Cは手軽で良いのですが、本来は基板内やボックス内での通信を念頭に置いたもので、数メートルのI2Cケーブルを引き回すというのは本来の使い方とは異なるようです。
ただ、それでも使いたい場合もあると思います。近くになにもノイズ源がなければ、２mくらいまではあまり問題なく通信できると思いますが、例えば最近流行りのIoT用途だと、機器周辺の温湿度などを計測することもあり、機器の動力線などノイズ源が近くに通ってると一発でノイズが乗ります。その場合の対策を考えてみました。

ちなみに使った基板はSeeed社が開発しソラコムが販売する[Wio LTE JP Version](https://soracom.jp/products/module/wio_lte/)
![Kobito.dt5860.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/7ec54604-11e5-8fe8-8b15-35c0e3252297.png "Kobito.dt5860.png")

センサーは[SHT35（温度・湿度）](https://www.switch-science.com/catalog/5337/)と[BMP280（気圧）](https://www.switch-science.com/catalog/3373/)です。いずれもI2Cで通信します。






## ノイズ源の対策

まずはノイズを発生している動力線は強力なノイズ源となります。いろいろ調べているとアルミや銅がノイズを遮断する機能があるとわかりました。ちなみに、このアルミをアースする必要性ですが、アースするとかなり強力なノイズ遮断能力を発揮しますが、アースしなくても結構遮断してくれます。

つかったのはこれ
![Kobito.9HszMB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/6f8f3221-a120-4995-2997-27fc01b91efa.png "Kobito.9HszMB.png")

これで動力線の、信号線と近くなる付近を巻いて、そこからノイズが出ないようにします。
この時点で効果が感じられ、I2Cの線が50cm程度であればノイズが乗ることなく通信できました。ただ2mとか5mとかになると、やっぱりノイズが乗りました。

ちなみにアルミテープで巻いた後は上から絶縁テープで巻いてアルミが表面に出ないようにしておかないと、最悪、基板や端子などに触れてショートするかもしれませんのでご注意ください。

![Kobito.LvH0P4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/4eda14d4-d807-b271-33b6-bfdba22a0627.png "Kobito.LvH0P4.png")

上の写真は、アルミテープで巻いた上から途中まで絶縁テープを巻いたところ。

## 信号線の対策

私は基板にSeeed社が開発したWio LTEを使っていました。これはGroveという規格？のコネクタになっており、ネットで購入できるものは50cmか20cmでした。これを今までは4芯の信号線を使って延長していました。

しかしノイズが乗ってセンサーとの通信が途切れたりするため、なにかノイズに強い線が無いか探していたところ、LANケーブル、とくにカテゴリー6AのLANケーブルが強いということがわかりました。さっそく近くの100満ボルトに行ってかったものがこちら。

![Kobito.SMNcZs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/3282e342-057d-46f9-d1eb-242d92d7ad25.png "Kobito.SMNcZs.png")

[製品サイトはこちら](https://www.harmonet.co.jp/harmonet-products/t6as.html)

ご覧の通り、2本づつ４組ある線がそれぞれアルミでシールドしてあり、さらに外側を銅でシールドしてあります。
![Kobito.WwZcmQ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/2339fd11-1e5f-83db-4746-b1c8297e7438.png "Kobito.WwZcmQ.png")

これの両端を切ってGroveの線にハンダ付けしました。つなぐ線はどういう組み合わせでもいいのですが、両端が同じ組み合わせになるようにします。ちなみにこれ、写真で見ると所々ヒゲが出てますね...

~~注意点として、必ずストレートケーブルを買ってください。クロスだと最悪基板かセンサーが壊れると思います。~~

訂正： ケーブルのクロス・ストレートは特に気にしなくても大丈夫です。 @n2naokunさん、コメントいただきありがとうございます！

![Kobito.agExlB.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/de375d3e-fbf3-85e1-2fbf-d5452b23c5d6.png "Kobito.agExlB.png")

ハンダに関しては不慣れだったので、こちらのサイトでやり方を勉強してからやりました。
[ハンダで配線同士を接続する方法](https://www.diylabo.jp/basic/basic-39.html)

スリーブがあればいいのですが、なかったので絶縁テープで巻いてインシュロックで固定しました。
この写真はインシュロック固定前ですが。

![Kobito.FmWDyT.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/13835/e3303776-d444-5055-ce5b-a8888e8e0344.png "Kobito.FmWDyT.png")

これ使ってみたところ、5m以下であれば先ほどのアルミテープでノイズ対策した動力線の近くを通っても問題なく通信できました。10mは無理だったので、まあ5m以下でやってみるのがいいかと思います。1,2mならかなりノイズに強いと思います。
仮想マシン環境のIaCについて知りたかった

## はじめに

AnsibleやChefでInfrastructure as Code(IaC)に触れて、Amazon Web Service(AWS)のリソースもコード化したいのでまとめました。
アプリケーション開発者だけど初期にはインフラも触れないと困る人用です。
過不足があればプルリク、コメントよろしくお願いします。

---

## コード化対象について

IaCでコード化の対象とするもの。

|        要素        | 概要                                                |
|:----------------:|:--------------------------------------------------|
|   Application    | 業務機能を提供するソフトウェア。主に自分たちが開発するもの。IaCではデプロイ対象として関係する。 |
|    Middleware    | デバイスドライバやDB接続ドライバなど。Webサーバーなどのアプリケーション基盤も含める。     |
| Operating System | 仮想マシンのOS。                                         |
|     Hardware     | 仮想のハードウェア。VirtualBoxインスタンスやAWSのEC2インスタンスなど。       |
[IaCの対象]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/96f2ec21-340b-c04b-5e9d-97734a12a51a.png)

---

## ターゲット：アプリケーション

主に品質管理、ライブラリ管理タスクが該当します。
このあたりはアプリケーション開発者でもよく知っている範囲ではないでしょうか。
IDEを使わない開発環境ではローカルで自動化していると思います。
DockerやVagrantなどを利用して一部をパッケージングしていることも。

* 継続的インテグレーション(CI)/継続的デリバリー(CD)のタスク（パイプライン）
    * フォーマッタの実行(コーディング規約の強制)
    * 静的コード解析の実行(code inspection)
    * テストビルド
    * 自動化されたテスト実行(単体テスト、結合テスト、自動化できるUIテスト)
    * カバレッジチェック
    * ステージング
        * マージ
        * ビルド
        * デプロイ
    * プロダクション
        * マージ
        * ビルド
        * デプロイ

### コード化するためのツール（例）

* シェルスクリプト
* CI/CDサーバー
    * [Circle CI](https://circleci.com/ja/)
    * [AWS CodePipeline](https://aws.amazon.com/jp/codepipeline/)
    * [Jenkins](https://jenkins.io/)

---

## ターゲット：ミドルウェア

構成管理（プロビジョニング）タスクが該当します。

* インストール（or アップデート）
* 初期化
* 設定
* バックアップ設定

### コード化するためのツール（例）

* シェルスクリプト
* プロビジョニングツール
    * [Ansible](https://www.ansible.com/)
    * [Chef](https://www.chef.io/)
    * [Puppet](https://puppet.com/)

---

## ターゲット：オペレーティングシステム

リソース管理、構成管理（プロビジョニング）タスクが該当します。

* インストール（or アップデート）
* 初期化
* 設定
* バックアップ設定

### コード化するためのツール（例）

* シェルスクリプト
* プロビジョニングツール
    * [Ansible](https://www.ansible.com/)
    * [Chef](https://www.chef.io/)
    * [Puppet](https://puppet.com/)
* インストールスクリプト
    * キックスタート(Linux)

---

## ターゲット：ハードウェア

リソース管理タスクが該当します。
ローカルでいえばVagrantを使ってる

* 作成
* 拡張
* 設定

### コード化するためのツール（例）

* シェルスクリプト
* リソース管理ツール
    * [AWS CloudFormation](https://aws.amazon.com/jp/cloudformation/)
    * [troposphere](https://github.com/cloudtools/troposphere)
    * [Serverless Framework](https://serverless.com/)
    * [Terraform](https://www.terraform.io/)
    * [Former2](https://former2.com/)

---

## おわりに

できるだけ２度同じ作業をしなくて良いようにしたいですね。
シェルスクリプトはとりあえずの手段ですが、小さくはじめるにはいいかも。
要領をつかんだら適切なツールに移行しましょう。

いじょ