OmniAICreator/Qiita-1.07M huggingface dataset:
Pythonで毎日AtCoder #26

### はじめに
[前回](https://qiita.com/taxfree_python/items/b6675a4858d613027ffd)
25日目

### #25
今日はDFSなるものの[入門問題](https://atcoder.jp/contests/atc001/tasks/dfs_a)を解きます。[こちらの記事](https://qiita.com/gh_takumi/items/79537ade8d2539d89bd2)を参考にしました。

DFSは、深さ優先探索の略です。似ている名前に幅優先探索(BFS)があります。DFSは名前の通り今いるグラフの点から行ける点に進んでいく感じです。[詳しい解説](https://qiita.com/drken/items/4a7869c5e304883f539b)

今回の問題はsがどこにあるか指定されていません。ですので、まずは、's'の場所を探します。's'を見つけたら、stackにsの座標を追加します(型はlistではなくcollections.dequeです)。stackは最後に入れた要素が最初に取り出されます。
次に、visited_listのsの座標を1にします。1の意味は0 or 1で探索済かどうかを判断しているます。このvisited_listが探索済な点の集合になります。
ここからがdfsの中身になります。

1. stackが空になるまでwhileします。
2. 新しいh,w(現在地)をstackからpopで取り出します
3. もしh,wが'g'なら'Yes'を返して終了します。
4. h,wが'g'でないなら、それぞれの方向に進みます。この問題は[1, 0], [-1, 0], [0, 1], [0, -1]方向。
5. 現在地+それぞれの方向で進んだ先の座標を表現します。
6. もし進んだ先が問題の外になる場合は考えないので、continueします。
7. もし進んだ先が'#'でないand未探索な点ならvisited_list[座標]を1にして、新しい座標をstackに追加します

```python
from collections import deque

h_in, w_in = map(int,input().split())
c = [input() for _ in range(h_in)]

for n1,c_w in enumerate(c):
    for n2,c1 in enumerate(c_w):
        if c1 == "s":
            s_h = n1
            s_w = n2

stack = deque([[s_h,s_w]])

visited_list = [[0]*w_in for _ in range(h_in)]
visited_list[s_h][s_w] = 1

def dfs(town, visited_list, stack):
    while len(stack) > 0:
        h, w = stack.pop()
        if town[h][w] == "g":
            return "Yes"
        for j, k in ([1, 0], [-1, 0], [0, 1], [0, -1]):
            new_h, new_w = h+j, w+k
            if new_h < 0 or new_h >= h_in or new_w < 0 or new_w >= w_in:
                continue
            if town[new_h][new_w] != "#" and visited_list[new_h][new_w] == 0:
                visited_list[new_h][new_w] = 1
                stack.append([new_h, new_w])

    return "No"

print(dfs(c,visited_list,stack))
```

### まとめ
グラフの問題が出た時点でスルーしてたのですがしっかり勉強して解けるようになりたいです。一問だけでは定着しないので、精進していきます。では、また。おやすみなさい
D言語で解く AtCoder Beginner Contest 161 (A〜D)

[AtCoder Beginner Contest 161](https://atcoder.jp/contests/abc161)に参加したのでその記録です

各提出の冒頭でこんな感じのテンプレート使ってます

```d:tempalte.d
import std.stdio,std.math,std.string,std.conv,std.typecons,std.format;
import std.algorithm,std.range,std.array;

T[] readarr(T=long)(){return readln.chomp.split.to!(T[]);}
void scan(T...)(ref T args){auto input=readln.chomp.split;foreach(i,t;T)args[i]=input[i].to!t;}

//END OF TEMPLATE
```

#A - ABC Swap
[問題文](https://atcoder.jp/contests/abc161/tasks/abc161_a)

言うに及ばず

```d:a.d
void main(){
    long x,y,z;
    scan(x,y,z);
    writefln("%s %s %s",z,x,y);
}
```

#B - Popular Vote
[問題文](https://atcoder.jp/contests/abc161/tasks/abc161_b)

```d:b.d
void main(){
    ulong m,n;
    ulong[] a;
    scan(n,m);
    a=readarr!ulong;
    auto sum=a.csum;
    (a.filter!(x=>x.to!real>=sum.to!real/(4*m).to!real
        ).array.length>=m?"Yes":"No").writeln;
}

auto csum(ulong[] a){
    ulong tmp;
    foreach(t;a)tmp+=t;
    return tmp;
}
```
本当は`auto sum=a.fold!"a+b"`とできればどれだけ簡単なことか
AtCoderのバージョンでは`fold`が使えないのです。クソが

**と思っていたら**`std.algorithm.sum`とかいう**合計を求めてくれる関数**があった。知らなかった...

#C - Replacing Integer
[問題文](https://atcoder.jp/contests/abc161/tasks/abc161_c)
n+1回目の操作によってできるxの数列を$ \\{ x_n \\} $とすると、$x_1=N,\ x_{n+1}=|x_n-K|$
であるから、最小の$x_n$は`N % K`か`abs(N % K - K)`のどちらかです。

```d:c.d
void main(){
    long n,k;
    scan(n,k);
    min(n%k,abs(n%k-k)).writeln;
}
```

#D - Lunlun Number
[問題文](https://atcoder.jp/contests/abc161/tasks/abc161_d)
幅優先探索を使いました。D言語のQueueって`std.container`読んでもイマイチよくわからないんですよね`DList`使ってあとは勝手に書けってこと？

```d:d.d
void main(){
    ulong k;
    k.scan;
    k.solve.writeln;
}
 
struct Queue{
    public:
    char[][] list;
    auto enq(char c){list~=[c];}
    auto enq(char[] c){list~=c;}
    auto deq(){auto d=list[0];list=list.length==1?[]:list[1..$];return d;}
}
 
char[] co(char c){
    if(c=='0')
        return ['0','1'];
    if('1'<=c&&c<='8')
        return [to!char(c-1),c,to!char(c+1)];
    if(c=='9')
        return ['8','9'];
    assert(0);
}
 
auto solve(ulong k){
    Queue q;
    foreach(c;'1'.to!char..('9'+1).to!char)q.enq(c);
    foreach(i;0..k-1){
        auto tmp=q.deq;
        foreach(s;tmp[$-1].co)
            q.enq(tmp~s);
    }
    return q.deq;
}
```
まずキューに1から9までの数を順にエンキューします(1桁の整数は全てルンルン数です)。
その後、2桁のルンルン数を作っていきます。leading zeroなしなので、十の位は1から9までです。
`char[] co(char)`は、0から9までの「数字」に対して、差が1以下の「数字」を小さい順に返す関数です。キューの中身(1〜9)を順番に

- デキューして取っておく(`tmp=q.deq`)
- tmpの末尾にco(tmp)の返り値をそれぞれくっつけ、順にエンキューする

ということを繰り返すと、キューの中身は10,11,12,21,22,23,32,33,34,...,98,99となります。
以降も同じように続けるとルンルン数が小さい順に生成されていきます。
この作業を`K-1`回続け、最後にもう一回デキューした内容がK番目のルンルン数です。

#E - Yutori
次回か次次回くらいには解けるようにしたいです

#感想
始まる15分前くらいまで寝てたので、頭が働かずC問題までに時間がかかった
`sum`のこととかもあり、ちゃんとPhobosを読み直そうと思った。
競プロ界の鉄板本とも呼ばれる蟻本を買ったのですが、かなりイイです（あれがないとD問題とか思いつかない）
まだ最初の方しか読んでないので、来週の162までにもう少し読み進めておくつもりです
Arduinoに内臓されている電圧計を使ってみよう。

arduinoIDEの使い方でArduinoには電圧計が内臓されているという話をしたと思います。
今回は内蔵されている電圧計を使ってみたいとおもいます。
arduinoに内臓されている電圧計はADCと呼ばれています。
#使用するもの
●可変抵抗
●ジャンパー線
●arduino
#配線
![arduino_variabl_resister.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/528717/ca32d8e0-92ce-ae6b-032a-b9a3acff2689.jpeg)
可変抵抗の両端は固定の抵抗値
真ん中の端子と端の端子間の抵抗値が変化するようになっています。
分圧された電圧が真ん中のピンに出力されることになっています（よくわからない人は読み飛ばしてください）

#プログラミング
```C++:arduino_ADCtest.ino
void setup(){
Serial.begin(9600);
}

void loop(){
Serial.println(analogRead(A0));
delay(1000);
}
```
解説：
**Serial.begin(9600);**
シリアルモニターを使うためのおまじないです。

**analogRead(A0)**
に接続されている電圧計の値を読み取ります。

**Serial.println(○);**
シリアルモニターに○を表示します。
#確認
シリアルモニターをひらいてください。
可変抵抗を回すとシリアルモニター上に0から1023までの値が表示されると思います。
なんで0から1023までなのか、それは難しい話になりますので気になる方は「ADC仕組み」で調べてみてください。気にならない方はそうゆう物だと思ってください。
AtCoderの入力、出力

AtCoderでC++やPythonでコードを書く際に、標準入力の処理に戸惑うので、整理

# 入力
## C++

有限個の場合

```
int a,b,c;
cin>>a>>b>>c;
```

可変の場合：vectorを使う

```
#define rep(i,n) for (int i = 0; i < (n); ++i)
vector<int> a(n);
rep(i,n) cin >> a[i];
```

## Python3
有限個の場合

```
a,b,c = map(int, input().split()))
```

可変の場合：listを使う

```
a = list(map(int, input().split()))
```


# 出力
## C++

出力1

```
cout<<a<<" "<<b<<" "<<c<<endl;
```

出力2

```
printf("%d %d %d", a,b,c);
```

## python3

```
print(c,a,b)
```


# その他TIPS
・割り算は掛け算に変換する。C++やJavaは除算の切り捨てが発生するため、WA(Wrong Answer)の温床になりやすい。

# 再帰になれるために
DFS(Depth First Search,深さ優先探索)をする場合に、再帰の考え方が必要になる（スタックでもいいが）

問題
https://atcoder.jp/contests/abc165/tasks/abc165_c

＜参考になった考え方＞
再帰で意識すべきポイント１
再帰の1stepで何をしたら次に繋げられるか
ポイント２
終了条件をどうするか

# RE(ランタイムエラー)になったときの、エラー箇所特定
>【よくある質問】REの原因がわかりません => C/C++言語におけるmain関数の型、戻り値。ゼロ除算。配列の範囲外アクセス、などがあります。http://arc007.contest.atcoder.jp/faq#about_RE 

今回は、Vectorの確保がでかすぎてエラーになっていた。

```
printf("1 1");return 0;
```
printfの中身は、適当な出力結果。これをREになる手前に挿入すると、回答がWA(Wrong Answer)になるため、どこでREになっているか追える。

# 連想配列(map)で、全キーに対して順番に処理したい

http://vivi.dyndns.org/tech/cpp/map.html

```
std::map<std::string, int> mp
    いろんな値を設定;
    for(auto itr = mp.begin(); itr != mp.end(); ++itr) {
        std::cout << "key = " << itr->first           // キーを表示
                        << ", val = " << itr->second << "\n";    // 値を表示
    }
```

https://atcoder.jp/contests/abc166/tasks/abc166_e
連想配列を使う問題で利用した。

## その他参考
std::mapまとめ
https://qiita.com/_EnumHack/items/f462042ec99a31881a81

# ++iとi++の違い
https://stackoverflow.com/questions/24853/c-what-is-the-difference-between-i-and-i

```
a = ++i; //i=i+1してから、a=iする。
a = i++; //a=iしてから、i=i+1する。
```

# long long を printf で表示する
%lldや%llxを使用する
http://nanoappli.com/blog/archives/3229

10^18 < LONG LONG < 10^19
10^9 < INT < 10^10

# 少数の掛け算はするな！
FROM ABC_169_C
誤差が発生するため。整数に直してから実施すること
https://drken1215.hatenablog.com/entry/2020/05/31/224300

もしくは少数のまま扱う場合は、long double型を使うこと。

# 参考
AtCoderで青色（8割以上のIT企業でアルゴリズム力はカンスト）になったので青になるまでに必要そうなことをまとめる
https://qiita.com/kami634/items/e452f804ba9d585a8b57
GitHubとVSCODEの連携方法
https://qiita.com/yu0313/items/4f95fc0b7e544c42e107
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【初級編：競プロを始めよう】
https://qiita.com/e869120/items/f1c6f98364d1443148b3
AtCoderで初めて色がつくまでの話(茶色) レートが中々上がらなかった原因
https://tech-blog.s-yoshiki.com/2018/11/778/
DFS (深さ優先探索) 超入門！ 〜 グラフ・アルゴリズムの世界への入口 〜【前編】
https://qiita.com/drken/items/4a7869c5e304883f539b
競プロ「これだけ5問！」
https://the-zeng.com/select5/

【競プロ】AtCoder早解きテクニック10選 (灰 ~ 緑コーダー向け)
https://qiita.com/xryuseix/items/7e9b4c6f12d001a0c0db


C++ 素因数分解して約数の個数を求める
https://pomupomu.hatenadiary.jp/entry/2019/01/03/114653

最速の素数判定プログラム C# Java C++
https://qiita.com/asksaito/items/76b71602dd956b79dbf7
パーセプトロン

# パーセプトロン
複数の信号を入力として受け取り、１つの信号を出力する論理回路

<img width="272" alt="スクリーンショット 2020-04-04 22.39.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/202da340-57c7-7ffd-5689-24c9d55f1b28.png">

```math
\begin{align}
y
 =
  \begin{cases}
    0 & ( \ w_1x_1 + w_2x_2 \leqq \theta \ ) \\
    1 & ( \ w_1x_1 + w_2x_2 \gt \theta \ )
  \end{cases}
\end{align} 
```

|記号|意味|
|---|---|
|$x_1, x_2$|入力信号|
|$w_1, w_2$|入力への重み。各入力の重要性をコントロール|
|$y$|出力信号|
|$○$|ニューロン、ノード|
|$\rightarrow$|エッジ。ノード間を結ぶ|
|$\theta$|閾値、またはバイアス。越えると１を出力（発火）する|

しかし、単純なパーセプトロンの場合、XORゲートが表現できない

<img width="348" alt="スクリーンショット 2020-04-04 23.44.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/38149922-bea0-8f5e-ef52-7aa72303665c.png">

では、どうするか？　
その解は多層パーセプトロン

# 多層パーセプトロン
AND、NAND、OR、を組み合わせて XORゲートを作る

<img width="482" alt="スクリーンショット 2020-04-04 23.49.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/b6121fe8-6dc3-ed01-baa6-5d6e591d7942.png">

<img width="538" alt="スクリーンショット 2020-04-04 23.50.15.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/5fc95a9d-fb62-6884-14db-4f62a88d60a0.png">

<img width="524" alt="スクリーンショット 2020-04-04 23.52.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/153a83cc-ab22-e2fd-d19e-4bdf6efd74cf.png">

<img width="472" alt="スクリーンショット 2020-04-04 23.53.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569644/c8fca39a-3e51-191d-d49e-7b1d47961933.png">

# まとめ
- パーセプトロンは入出力を備えたアルゴリズム
- パーセプトロンでは「重み」と「バイアス」をパラメータとして設定する
- XORゲートは単層パーセプトロンでは設定できない
- 単層のパーセプトロンで表現できるのは線形領域だけ
- 多層パーセプトロンを用いればXORゲートを表現できる
- 多層パーセプトロンは非線形な領域を表現できる

# 参照
[ゼロから作るDeep Learning](https://www.amazon.co.jp/%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E4%BD%9C%E3%82%8BDeep-Learning-%E2%80%95Python%E3%81%A7%E5%AD%A6%E3%81%B6%E3%83%87%E3%82%A3%E3%83%BC%E3%83%97%E3%83%A9%E3%83%BC%E3%83%8B%E3%83%B3%E3%82%B0%E3%81%AE%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%A3%85-%E6%96%8E%E8%97%A4-%E5%BA%B7%E6%AF%85/dp/4873117585)
tmuxinator(v0.7) での can't find pane エラー

# この記事が紹介すること
- tmuxinator 0.7で発生する can't find pane エラー
- paneが展開されない
- 原因は~/.tmux.conf内部の記載

# 発生確認バージョン
- Ubuntu 16.04 (nVidiaGPUを使うためにバージョン落として使っている人注意）
- tmux 1.9
- tmuxinator 0.7

# 原因
- tmux.conf内で下記の項目が設定されているとエラー

```
set-option -g base-index 1
set-window-option -g pane-base-index 1
```

# リポジトリでのissue
- [can't find pane#137 Closed] (https://github.com/tmuxinator/tmuxinator/issues/137)

# 参考
下記のバージョンではFIXされています。
- tmux 2.5
- tmuxinator 1.14

# 参考リンク
下記リンクの症状とは別です
- [tmuxinator で can't find pane エラーでペイン分割を自動でやってくれないとき](https://qiita.com/qurage/items/43084674b6fb7d5d9e09)
ZEIT NOW を使うときのメモ

動画の解説は[こちら](https://youtu.be/ESTysFaJ4Ds)
# 初期設定

```terminal
$ npm install -g yarn
$ yarn global add now
$ now login
$ now
```

こんな感じでURLが発行されるので、クリックするとWebサイトが立ち上がります。
[![コロナに負けるな2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216701/32777848-f3aa-a4d8-c685-d946b92809e0.gif)](https://youtu.be/ESTysFaJ4Ds)

## 2回目以降 
### テスト環境にデプロイ
``` terminal
$ now
```

### 本番環境にデプロイ
``` terminal
$ now --prod
```

## デプロイしたURLを購入したドメインに紐付け
[ZEIT NOW](https://zeit.co/)にログインすると、デプロイできていることを確認できます。タイトルをクリックし、SettingのページのDomeinsを見ると、ドメインが設定できる部分があります。購入したドメインを入力すると、エラーが出ますので、その指示通りに購入したドメインのサイトで設定するだけ。
<img width="1280" alt="スクリーンショット 2020-04-03 午前11.45.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216701/2b12a1f7-082f-0e3b-a2c6-f6cf72c861ff.png">

以上！　簡単！！
DDDって遊戯王にあったよね

#　初めて聞いた「DDD」
仕事場でDDDという単語を初めて聞きました。
学生時代はデュエリストだったので、頭の中ではディファレント・ディメンジョン...なんちゃらと自然に考えており幼い頃親しんだものはずっと頭のどこかに残っているんだなと実感しました。

## DDDとは
DDDは何の略かというと「Domain-driven design」の略
日本語訳すると「ドメイン駆動設計」のことを指していました。

2003年にエリック・エヴァンス氏が書籍にて提唱した開発手法のことです。
簡単にい言うと「顧客と開発者が業務を戦略的に理解し、共通の言葉を使いながらシステムを発展させる手法」とのこと

言葉の意味自体はわかるが、実際の開発現場でどのように運用されているのか想像がつかないので
以下の参考文献を読んで理解を深めたいと思う。

###　参考文献
[ドメイン駆動設計のメリットと始め方 ～ 1章「DDDへの誘い」](https://codezine.jp/article/detail/9546)
[ドメイン駆動設計は何を解決しようとしているのか[DDD]](https://qiita.com/little_hand_s/items/721afcbc555444663247)
[ドメイン駆動設計の定義についてEric Evansはなんと言っているのか[DDD]](https://little-hands.hatenablog.com/entry/2017/09/27/014403)
Protocol Buffersのメッセージ定義からHTMLのフォームを生成してみる実験

# はじめに

HTMLでフォームを作るのは技術的には簡単なのですが、何度もやることになると作業の重複が多くなって疲れるかと思います。ここではProtocol Buffersを用いてフォームの表示と処理の自動化を試みてみます。実運用するには足りない点も多々ありますので、一つの実験として読んでみて頂ければと思います。

コードは https://github.com/yt76/pbforms にあるので、cloneして(もしくはcloneしたつもりになって)お読みください。　

# Protocol Buffersによるフォームの定義

例えば、名前(string)と年齢(int32)と同意の有無(bool)を取得したいとします。このメッセージを my_form.proto というファイルにあるように次の内容で定義します。

```
    message MyForm {
       optional string name = 1;
       optional int32 age = 2;
       optional bool agree = 3;
    }
```

これをコンパイルし、

```
    $ protoc myform.proto --go_out=forms/
```

それを使うサーバーをビルドし

```
    $ go build server/server.go
```

実行し

```
    $ ./server
    Serving at 8080
```

ブラウザでアクセスすると

![pbf1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193078/853e4fe7-3e86-0e40-adf4-10e2621cb20e.png)

適当に埋めて

![pbf2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193078/3a68d278-4be2-4ae1-e91d-21d63f173371.png)

送信を押すと

![pbf3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/193078/996416fb-c161-459f-1332-63f56fa00b7a.png)

内容がProtocol Buffersのテキスト形式で表示されます。実際のプログラム上ではこの各フィールドの値をデータベースに詰めることになりそうですが、このテキスト形式もしくはProtocol Buffersのバイナリ形式でそのまま保存したりRPCに投げることでProtocol Buffersの機能を使ったデータ操作をするなんてのも可能かと思います。

# 実装

実装といっても大したことはしてなくて、Goのリフレクションで各フィールドの名前と型を取り出してそれに応じたHTMLを生成し、POSTのハンドラ内ではフィールドの値を戻すといった感じです。

```
    // コンストラクタ内
    form := forms.MyForm{}
    sv.writer = pbforms.NewFormWriter(form)
    sv.reader = pbforms.NewFormWrite()


    // GETのハンドラ
    fmt.Fprintf(w, "<html><body>\n")
    // <form method="post" action="/">…</form>が生成される
    sv.writer.Write("/", w)
    fmt.Fprintf(w, "</body></html>\n")

    // POSTのハンドラ
    f := forms.MyForm{}
    // r *http.Requestでformの値からfを埋める
    sv.reader.Parse(r, &f)

```

# 最後に

* すぐに思いつく改善点としては見栄えの改善ですが、適当なCSSのクラスを出力してあとからJavaScriptで外側のHTMLのスタイルに書き換えるという手でなんとかなりそうです。
* ここではstringとintとboolをHTML formのtextとcheckboxに対応させましたが、その他の要素もProtocol Buffersの様々な機能を使えばそんなに無理せずに対応できる？
* フォーム上にNameとかAgeとかフィールド名をそのまま出してしまってるので、別途メッセージカタログ(国際化もできればなお良い)的なものが必要ですね。

ネット上には様々なフォームがあって、その中には技術の粋をつくした一品物から何かのコピペで済ましたい安易なものまで色々とありますが、適当なレベルのところまではこの記事で紹介したようなものを多少改善すれば間に合うのではないかなと考えてます。
【今日のアブストラクト】BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding【論文 DeepL 翻訳】


1 日 1 回 論文の Abstract を DeepL 翻訳の力を借りて読んでいきます.

この記事は自分用のメモみたいなものです.
ほぼ [DeepL](https://www.deepl.com/home) 翻訳でお送りします.
間違いがあれば指摘していだだけると嬉しいです.

翻訳元
[BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding](https://arxiv.org/abs/1810.04805)

# Abstract

### 訳文

BERT は Bidirectional Encoder Representations from Transformers の略で, この新しい言語表現モデルを紹介する. 最近の言語表現モデルとは異なり, BERT はすべての層で左と右の両方の文脈に共同で条件付けを行うことで, ラベル付けされていないテキストから深い双方向性表現を事前に訓練するように設計されている. その結果, 事前訓練された BERT モデルは, わずか $1$ つの追加出力層で微調整することができ, タスク固有のアーキテクチャを実質的に変更することなく, 質問回答や言語推論などの幅広いタスクのための最先端のモデルを作成することができる.
BERT は, 概念的にシンプルで経験的に強力である. GLUE スコアを $80.5\%$ ($7.7\%$ポイントの絶対的改善), MultiNLI 精度を $86.7\%$ ($4.6\%$の絶対的改善), SQuAD v1.1 質問応答テスト F1 を $93.2$ ($1.5$ ポイントの絶対的改善), SQuAD v2.0 テスト F1 を $83.1$ ($5.1$ ポイントの絶対的改善) に押し上げるなど, $11$ の自然言語処理タスクで新たな最先端の結果を得ている.


### 原文

We introduce a new language representation model called BERT, which stands for Bidirectional Encoder Representations from Transformers. Unlike recent language representation models, BERT is designed to pre-train deep bidirectional representations from unlabeled text by jointly conditioning on both left and right context in all layers. As a result, the pre-trained BERT model can be fine-tuned with just one additional output layer to create state-of-the-art models for a wide range of tasks, such as question answering and language inference, without substantial task-specific architecture modifications.
BERT is conceptually simple and empirically powerful. It obtains new state-of-the-art results on eleven natural language processing tasks, including pushing the GLUE score to 80.5% (7.7% point absolute improvement), MultiNLI accuracy to 86.7% (4.6% absolute improvement), SQuAD v1.1 question answering Test F1 to 93.2 (1.5 point absolute improvement) and SQuAD v2.0 Test F1 to 83.1 (5.1 point absolute improvement).
ElectronでのWebフォントのキャッシュについて


## モチベーション

Electronで作るアプリでも、Google FontのようなWebフォントが使いたい。この場合、どうやって指定するのが良いのか？例えば、指定の仕方として次の候補が考えられる

- 方法１：Web fontをダウンロードしてアプリに同梱する。使用するときはＣＳＳの`@font-face`で`src: url('./font/FONTNAME);`などの様に同梱したファイルを相対パスで指定。
- 方法2：レンダラープロセスのHTMLのheadにて`<link href="https://fonts.googleapis.com/css2?family=FONTNAME&display=swap" rel="stylesheet">`で読み込む
- 方法3：CSSの先頭で、`@import url('https://fonts.googleapis.com/css2?family=FONTNAME');`で読み込む

この中で、Electronアプリとしてベターなものはどれだろう。

## Electronアプリに求めるもの

上の「ベター」とは、そもそもElectronでアプリ化する時点で、次ことを要求しているのではないだろうか

- ローカルＰＣでの起動を目的としている。
- **オフラインでの使用も視野に入れている**

オフラインを想定した時、最初は方法1（ダウンロードして同梱）しか解が無いと思っていた。ただ、フォントの同梱は、次の問題もある

- フォントの再配布に関するライセンスの問題（Ｇｏｏｇｌｅ ｆｏｎｔは再配布ＯＫ）
- アプリのパッケージサイズが大きくなる
- アプリの見た目（テーマ）をＣＳＳでカスタマイズやユーザー定義できるようにしたい場合、未同梱のＷｅｂフォントを使うにはどうするか

ただでさえファイルサイズが大きいと揶揄されるＥｌｅｃｔｒｏｎアプリがさらに大きくなるのは困る人も多そう。

また、リッチテキストエディタやビューアなどを作っている時は、三番目のテーマのＣＳＳカスタマイズなどもやりたいでしょう（少なくとも私の開発しているエディタではやってみたい）。すると、フォントの同梱では必ずしも解決しない。さらに、このテーマのカスタマイズに関しては、方法2(linkタグで指定)を行うのは、カスタマイズに合わせてDOMを操作しないといけないので、あまり好ましくない。

となると、消去法で方法3が残る。

## ElectronアプリでもWebフォントのキャッシュが効く？！

方法3（CSS中で`@import`）でWebフォントを指定する場合、初回起動時にオフラインだと確かにフォントが読み込めず、代替フォントでの表示になってしまいます。ただ、（初回に限らず）オンラインで一度でもWebフォントを読み込めた場合は、Electronアプリでもフォントのキャッシュが残るようで、以後の起動ではオフラインでもWebフォントが使えるようです。そして、OSの再起動をしてもこのキャッシュが有効のまま生きています。

とりあえず動作確認した環境

- Windows10 (1909）
- Mac OS 10.14.6

ただし、フォントをキャッシュしている仕組みは理解していません。OSのキャッシュなのか、Chromiumのキャッシュなのか、Chromeのキャッシュと共通なのか、アプリごとに独立したキャッシュになっているのか。OS再起動ではどうなるのか。詳しい人がいたら教えてほしいです。

## 結局

この時代、完全にオフラインではなく、オンラインの状態での起動もあり得る、と割り切れるなら、Electronアプリにおいて`@import`でWebフォントを読み込ませてしまっても大丈夫かもしれません。

皆さんがどうしているか、是非コメント欄にでも情報共有いただけると勉強になります。
Windows10にXampp環境を入れてphpspreadsheetが使えるまで

#Windows10でphpspreadsheetの導入

##1.Xamppのインストール
　下記からインストーラーをダウンロード
　https://www.apachefriends.org/jp/download.html
　※インストール先はc:\にした
　c:\にxamppフォルダができる。
　ちなみに、localhostのルートディレクトリは\xampp\htdocs

##2.composerのインストール
　下記参照
　https://qiita.com/mikoski01/items/266469535e860312145d
　php のバージョン云々を聞いてくるけど、Xamppにインストール済みのものと一致していればOKかな？(適当)
  PHPのパスを聞いてくるけどXamppでOK


##3.phpspreadsheetのインストール
　プロンプトから適当なディレクトリに移動して、以下をコマンドを実行。

```Bash

c:¥User> composer require phpoffice/phpspreadsheet
Using version ^1.11 for phpoffice/phpspreadsheet
./composer.json has been updated
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 4 installs, 0 updates, 0 removals
  - Installing psr/simple-cache (1.0.1): Downloading (100%)
  - Installing markbaker/matrix (1.2.0): Downloading (100%)
  - Installing markbaker/complex (1.4.8): Downloading (100%)
  - Installing phpoffice/phpspreadsheet (1.11.0): Downloading (100%)
phpoffice/phpspreadsheet suggests installing mpdf/mpdf (Option for rendering PDF with PDF Writer)
phpoffice/phpspreadsheet suggests installing dompdf/dompdf (Option for rendering PDF with PDF Writer)
phpoffice/phpspreadsheet suggests installing tecnickcom/tcpdf (Option for rendering PDF with PDF Writer)
phpoffice/phpspreadsheet suggests installing jpgraph/jpgraph (Option for rendering charts, or including charts with PDF or HTML Writers)
Writing lock file
Generating autoload files
1 package you are using is looking for funding.
Use the `composer fund` command to find out more!

C:¥User>
```
　カレントディレクトリに「vendor」フォルダとcomposer.jsonができていればOK
　jsonファイル内にphpspreadsheetの記述があるはず。
　
　phpから呼び出す場合には、上でできたvendor内の「autoload.php」を使用したいphpファイル内で読み込む。

```php
require_once("/Users/vendor/autoload.php");
```


　これで使える筈


　環境によっては、xamppのApacheサーバーが使用するポート(大体80?)がwindowsのほかのアプリと競合して動かないこともあるらしい。
Pythonで毎日AtCoder #46

### はじめに
[前回](https://qiita.com/taxfree_python/items/49bb8475455c4134e4ba)

### #46
[ABC131-D](https://atcoder.jp/contests/abc131/tasks/abc131_d)

**考えたこと**
$B_i$でsortして仕事を終らせるのに必要な時間を計算していきます。制限時間を越えたらflagを変えます。

```python
n = int(input())
ab = [list(map(int,input().split())) for _ in range(n)]

ab.sort(key=lambda x: x[1])
t = 0
flag = True
for i in range(n):
    t += ab[i][0]
    if t > ab[i][1]:
        flag = False
if flag:
    print('Yes')
else:
    print('No')
```

[ARC093-C](https://atcoder.jp/contests/arc093/tasks/arc093_a)

**考えたこと**
Nの大きさ的に$O(N^2)$は通せません。なので、うまく$O(N)$くらいにします。スタートとゴールの座標は0なので、左右に0を追加します。dを$|a[i+1]-a[i]|、0\leq i \leq N$、dの総和$sum(d)$をsとします。すると、観光スポット$i$をスキップしたときは、$s+|a[i+1]-a[i-1]|-(|a[i]-a[i-1]|+|a[i+1]-a[i]|$となります。

```python
n = int(input())
a = list(map(int,input().split()))

a.insert(0,0)
a.append(0)
d = [abs(a[i]-a[i+1]) for i in range(n+1)]
s = sum(d)
for i in range(1,n+1):
    print(s+abs(a[i-1]-a[i+1])-(abs(a[i-1]-a[i])+abs(a[i]-a[i+1])))
```

### まとめ
2問目は少し考えてしまった。Nが大きいから計算量を減らさないといけないのは気付いたけど、減らし方がうまくできなかった。ではまた、おやすみなさい。
AnsibleでQNAPを管理する(前準備)

時間ができたので、QNAPを初期化して、最初からやってみる。

# QNAPのインストール
最初にこの画面が出るところから。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/bdbda598-5c45-08f9-1596-83ea62d3aeb8.png)

名前とパスワードを設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/a6108db4-70d2-8a38-8856-c6a3c88e95de.png)

時刻の設定。画面は設定前だけど、NTPサーバーはデフォルトではなくISPのものに設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/01624d8f-0459-dd8b-32be-b464a73cb99d.png)

IPアドレスはDHCPで。とはいってもサーバーのIPが変わるといろいろ面倒なので、ルーターのDHCPサーバー側でMACアドレス指定で固定アドレスを振ることにしてある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/dda8cbcd-fda8-1c1b-cf45-7ef416e6d558.png)

NFSをどうしようか悩むんだけど、UIDのマッピングがなかなか大変なことになりそうなので、CIFSだけでよしとする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/1490c36b-2441-fee9-47ae-d836020df65c.png)

これでOKすると完了。しばらく待つ。

# コントロールパネルで

コントロールパネルが出るようになったら、HDDをマウントしてボリュームを作成する。RAID組むわけでもなし、静的ボリュームでいいよもう。なお、HDD1はSSD, HDD2はHDD。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/6f6220d5-2ce9-46ad-0d72-6c1afb79a722.png)

次に、AppCenterでPython3をインストールする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/2345fc13-818c-f4bc-9cd6-53222c76d794.png)

最後に、SSHを有効にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/365182/55cb88d5-3f48-f6d0-a88b-2f29cffb02df.png)

# おまけ
不思議なことにもうひと手間、SSHでQNAPに入ってやらなくてはならないことがある。

```
[~] # chmod 755 /share/CACHEDEV1_DATA/.qpkg/Python3/src/bin/*
```
【自分用】4/25 php + dockerの環境構築途中まで

#今日のエラー
`docker exec -it php php artisan ui vue --auth`に対して

```
Command "ui" is not defined. 
```

`composer fund`で調べたら下記のエラー

```
Composer could not find a composer.json file in /Users/user/projects/phpForEveryone
To initialize a project, please create a composer.json file as described in the https://getcomposer.org/ "Getting Started" section
```

再起動して`docker run --rm -v /Users/user/projects/phpForEveryone/src:/app composer require laravel/ui`
をもう一度打ったら直った。インターネット接続が不安定のせいでこのコマンドがうまくいっていないのかも...

nmpが入っていないというエラー→nodebrewとnodeをインストールしたら治った。

下記コマンドでpathが合わなくてその下のエラーを出した
→Dockerfileの`WORKDIR /var/www/html/laravel`をコメントアウトしたら治った
`docker run --rm -v /Users/user/projects/phpForEveryone/src:/usr/src/app -w /usr/src/app node npm run dev `

```
npm ERR! code ENOENT
npm ERR! syscall open
npm ERR! path /Users/user/projects/phpForEveryone/package.json
npm ERR! errno -2
npm ERR! enoent ENOENT: no such file or directory, open '/Users/user/projects/phpForEveryone/package.json'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent 

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/user/.npm/_logs/2020-04-24T18_09_30_348Z-debug.log
```

`docker-compose exec php php artisan migrate `のコマンドで下記のエラー

```
  Illuminate\Database\QueryException 

  SQLSTATE[HY000] [2002] Connection refused (SQL: select * from information_schema.tables where table_schema = laravel_test and table_name = migrations and table_type = 'BASE TABLE')

```

→.envで`DB_HOST=127.0.0.1`を`DB_HOST=mysql`と変更
参考は下記
https://qiita.com/wallkickers/items/47efb41dd200722a98fe
nuxt.js の header に出てくるCSSを削除してページのサイズを小さくする

# モチベーション

デフォルト設定のまま nuxt.js を使っていると以下のようにCSSが大量にHTMLページ内に書き込まれてしまう。
これからCSSの埋め込みを削除し、別のファイルやCDNから読み込むようにしたい。

理由はAWSとかを使っていると通信量で課金されるので、HTMLファイルのロードの度にかかるコストを抑えたいため。
検証バージョンは nuxt.js の 2.12.2。

```html:bootstrap-vueを選択した場合のindex.htmlから抜粋
<!doctype html>
<html data-n-head-ssr>
  <head >
    <meta data-n-head="ssr" charset="utf-8"><meta data-n-head="ssr" name="viewport" content="width=device-width, initial-scale=1"><meta data-n-head="ssr" data-hid="description" name="description" content=""><link data-n-head="ssr" rel="icon" type="image/x-icon" href="/favicon.ico"><link rel="preload" href="/_nuxt/runtime.js" as="script"><link rel="preload" href="/_nuxt/commons.app.js" as="script"><link rel="preload" href="/_nuxt/vendors.app.js" as="script"><link rel="preload" href="/_nuxt/app.js" as="script"><style data-vue-ssr-id="71f83a6d:0">/*!
 * Bootstrap v4.4.1 (https://getbootstrap.com/)
 * Copyright 2011-2019 The Bootstrap Authors
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 */
（攻略。 以下、BootstrapのCSSが埋め込まれている)
```

# 解決策

`nuxt.config.js` 内の `build:extractCSS` を `true` にする。

- https://ja.nuxtjs.org/api/configuration-build/#extractcss

```nuxt.config.js
  build: {
    extractCSS: true,
  }
```

# 感想

- nuxt.js 1日目。 どうにもこの辺りのことを整理しないと前に進めない性分なので、飲み込みが遅い…
- やりたいことは明確で、extractCSSだと分かれば一発で分かったが、どのように検索していいかわからなかったのでものすごい時間がかかった。
    - 失敗例: `app.html` の変数 `HEAD` が [ここで定義されているのを見てここの style を空にしようと試みたり](https://github.com/nuxt/nuxt.js/blob/ef7a42649dcee7e65886b2db1a329deecd93aff2/lib/core/meta.js#L40-L45)……

以下に同じような出来事にあった人向けに検索用ワードを貼っておきます。

- nuxt.js CSS 埋め込み 短い 短くする 切り出す 外部ファイル extract 書き出さない ページサイズ 大きすぎる 小さくする 小さい
【覚えておくと便利!!!】Eclipseにおける継承クラスの簡易作成

## 1.事前知識
- [【最新】UbuntuでJavaの環境を構築する方法](https://qiita.com/ryome/items/37c53e9638a9c6ea146a)

- [【初心者でもできる‼】Windows10にJava環境を作る方法（JDK14.0.1）](https://qiita.com/ryome/items/30135570954e36196821)

- [【わかりやすく解説‼】Javaのインスタンスの使い方](https://qiita.com/ryome/items/62ba0d8395af6698053a)

- [【初心者でもできる‼】Windows10にEclipseをインストールする方法（Java環境構築）](https://qiita.com/ryome/items/b47c5acdaa52cffbec58)

事前知識として、上記リンクの内容が必要です。


## 2.スーパークラスからサブクラスの簡易作成

![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/dd8bfac5-0e19-e969-0e80-af6aa184bc66.png)
1. `[ファイル(F)]→[新規(N)]→[クラス]` を選択する。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/65e16506-f497-439f-5171-dc247b6ac7f1.png)
2. `参照` ボタンをクリックする。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/dbe9cb75-4bf8-579f-48e9-527bdac305d5.png)
3. `継承したいクラス` を選択し、`OK` ボタンをクリックする。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/44ba1465-0a99-6daf-d0e4-4faf78ef4ab2.png)
4. `スーパークラス` を確認し、`完了` ボタンをクリックする。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/9cfe0033-7595-ff69-7726-6ba7a6fa3d17.png)
5. `サブクラス` の作成が確認できたら成功。

## 2.サブクラスからスーパークラスの簡易作成
![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/906be963-85c3-6bf8-2310-04fd1728263c.png)
1. `サブクラス` にするファイル内で `右クリック` し、 `[リファクタリング(T)]→[スーパークラスの抽出(T)]` を選択する。
![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/84317fac-e84d-6d33-62f8-4ceb4403486c.png)
2. `スーパークラス名` を入力し、 `完了` ボタンをクリックする。
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/8bf61536-ede7-0314-4a86-7576a7cf56a5.png)
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/9b305008-623e-227e-d4e1-78232b4b5360.png)
5. `サブクラス` と `スーパークラス` の作成が確認できたら成功。

## 3.おまけ：System.out.println()の簡易作成

![09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/63ac35ef-982b-e438-53f9-6f1465edad62.png)
1. `sysout` と入力し、キーボードの `Ctrl` + `Space` を押す。
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/bfa59bad-837a-b53a-5bff-9dba9eab0a19.png)
2. `System.out.println()` の作成が確認できたら成功。

## 3.関連
- [【覚えておくと便利!!!】Eclipseにおけるコンストラクタとgetter/setterの簡易作成](https://qiita.com/ryome/items/6c487ccc0c39847cd55f)
- [【初心者でもできる‼】Javadocの書き方](https://qiita.com/ryome/items/4f2d5928c8aaf195f407)
- [【わかりやすく解説‼】Javaのカプセル化の使い方](https://qiita.com/ryome/items/fc44dfad297b35bf7559)
- [【わかりやすく解説‼】Javaのオーバーロードの使い方](https://qiita.com/ryome/items/f1ca8cc7538f4c6d26c0)
- [【わかりやすく解説‼】Javaの継承の使い方【オーバーライドの解説あり】](https://qiita.com/ryome/items/97b82c5519e39d3f21c1)
ポートの存在意義

# ポートって何？
１つのサーバーと複数のサーバーを繋ぐためにあるものです。
分かりにくいと思うので具体例を示しながら説明していきます。
サーバーって何？と思った方は先にこちらの記事を読んでください。
[サーバって何なの？](https://qiita.com/Nyanmaru-12/items/c1f7ed517227206d347a)
### 具体例
サーバーといってもいろいろな種類があります。
WEBサーバーだったり、データベースサーバーだったり、メールサーバーなど。
本来であれば、それぞれの機能ごとにサーバーを用意しますが、
そのようなことをしなくても、１つのサーバーで複数の機能を展開できます。
**その仕組みがポート**なのです。
つまりこれからはどのIPアドレスのどのポートに接続するかを考えなくてはなりません。
例：WEBサーバーの８０というポートに接続する。
※余談ですが、WEBサーバーなら「８０」、メールサーバーなら「３３０６」など決まっているものもあります。既に利用されているポートは利用できません。
##ポートのおさらい
WEBサーバーを例にしてまとめてみます。
WEBサーバーは以下の手順で通信しています。
①８０ポートでHTTPリクエストを受け付ける
②要求されたものを探したり、処理を行う。
③リクエストしてきたものに対してのコンピューターに返答する。
 **HTTPとはページ内で必要なCSS、JSなどのファイルをWEBサーバーにリクエストするためのフォーマット**みたいなものです。このフォーマットでリクエストしないと正しく受け取ってくれないみたいなイメージでいいと思います。
vtkOpenFOAMReaderまとめ（随時更新）

# vtkOpenFOAMReaderについて

Class Reference
https://vtk.org/doc/release/7.1/html/classvtkOpenFOAMReader.html

pythonで実際に動かした場合の挙動を少しづつまとめていきます

### 環境

python 3.7
vtk 8.1.2


``` python:確認方法
import Vtk
print(vtk.vtkVersion.GetVTKSourceVersion())
>> vtk version 8.1.2
```


### 初期化

``` python
import vtk
filename = "a.foam"

reader = vtk.vtkOpenFOAMReader()
reader.SetFileName(filename)
reader.Update()
print(reader)
```

printの出力例

``` python
vtkOpenFOAMReader (0x7fedd2c95be0)
  Debug: Off
  Modified Time: 105700
  Reference Count: 2
  Registered Events: (none)
  Executive: 0x7fedd2caf9b0
  ErrorCode: Undefined error: 0
  Information: 0x7fedd2cd3f90
  AbortExecute: Off
  Progress: 1
  Progress Text: (None)
  File Name: a.foam
  Refresh: 0
  CreateCellToPoint: 1
  CacheMesh: 1
  DecomposePolyhedra: 1
  PositionsIsIn13Format: 1
  ReadZones: 0
  SkipZeroTime: 0
  ListTimeStepsByControlDict: 0
  AddDimensionsToArrayNames: 0
  Reader instance 0x7fedd2cbeb70: 
    Debug: Off
    Modified Time: 106395
    Reference Count: 1
    Registered Events: (none)

```


### DisableAllCellArrays() / EnableAllCellArrays()

CellArrayのオンオフ

### GetNumberOfCellArrays()

オブジェクトに含まれている物理変数の種類の数を返す
例：U,p を変数に含む ->  2

``` python
reader.GetNumberOfCellArrays()
>> 2
```

### GetCellArrayStatus(name:string)
指定した文字列に該当する**CellArray**が存在するかを返す

``` python
reader.GetCellArrayStatus("hoge")
>> 0
reader.GetCellArrayStatus("p")
>> 1
```

### GetCellArrayName(index:int)

indexの番号に対応する物理変数の名前を返す

``` python

reader.GetCellArrayName(0)
>> 'U'
reader.GetCellArrayName(1)
>> 'p'
reader.GetCellArrayName(1000)
>> None
```

オブジェクトに含まれている物理変数(**CellArray**)の一覧を表示

``` python
for index in range(reader.GetNumberOfCellArrays()):
    nname = reader.GetCellArrayName(index)
    print(nname)
>> U p ...
```

### GetNumberOfPatchArrays()

OpenFOAMのパッチの数+1を返す
+1は**internalMesh**を含むため

``` python
reader.GetNumberOfPatchArrays()
>> e.g. 5
```

### GetPatchArrayName(index:int)
パッチ名とinternalMeshを返す

``` python
reader.GetPatchArrayName(0)
>> 'internalMesh'
reader.GetPatchArrayName(1)
>> e.g. 'walls'
```
【ポエム】エンジニアは、制約の中で、目的のために、手段を選ぶ　ことからスタートする

※ 本記事は ポエム です。紹介させていただいている記事の良し悪しを述べてはいません。

# はじめに

> **文章をデザインに合わせる** ということをやって下さい。
> どういうことかと言うと、 **文章の内容よりもデザインを重視** するのです。
> 　　　　　　　　　from [【デザイン】読まれないビジネス文章は、無価値 - Qiita](https://qiita.com/enjoy_omame/items/b77a63cdb207b9f1a476)

この表現に、 <font color="LightGray">~~ポエムを詠むほど~~</font> エンジニアとして、**強く感情を揺さぶられました。** 

**非常に強い拒絶感** と、 **ほんの少しの共感** です。

　

では、伝えたいことを変えずに、感情が揺さぶられない表現を考えてみます。

> **文章を <font color="red">フォーマット内で最適化する</font>** ということをやって下さい。
> どういうことかと言うと、 **文章の内容よりもデザインを重視** するのです。

エンジニアとして、 **強い共感** と **ほんの少しの拒絶感** に
変わったのではないでしょうか？

　

本記事は、前者の表現が、なぜ、エンジニアとしての感情を揺さぶったか、についてのポエムです。

# エンジニアは、制約の中で、目的のために、手段を選ぶ　ことからスタートする

エンジニアはシステムを作ります。

システムを作るためには、環境が必要です。

環境には、機能があり、制約があります。

優秀なエンジニアは、目的を達成するために、制約の中で最適な手段を選びます。

　

制約の中で最適な手段を選ぶことは、エンジニアに必要な要素の一つです。

手段を選ばない（誰でもできる手段）でシステムが作れるのであれば、

それは、エンジニアの仕事ではなく、ワーカーの仕事です。

　

文章を書いて伝えることも似ています。

文章を書くときにも、環境（紙、Word、SNSなど）による制約があります。

SNSという制約の上で、読みやすい文章を書くためには、

オーファンなどの、制約に応じた工夫が効果的です。

　

伝えることが目的の文章で、制約に応じたデザインを重視することは、

エンジニアとして共感します。


# エンジニアは、目的のために、手段を提供し、制約を作り　苦悩する

システムを作るのは、システムを使うユーザの目的を達成する手段を作るためです。

つまり、ユーザの目的を達成するための環境を提供します。

環境には、機能があり、制約があります。

エンジニアは、機能を提供するために、制約を作ります。

　

制約の少ないシステムを作るためには、コストがかかります。

優秀なエンジニアは、目的に応じて、適切な制約を作り、コストを下げます。

　

しかし、システムは、当初と異なる目的のための手段として使われることがあります。

優秀なエンジニアが作ったシステムでも、当初の目的と異なる目的でシステムが使われると、

適切な制約ではなくなり、コストが増加します。

　

システムの、目的と手段の乖離に、エンジニアは苦悩します。


# エンジニアは、制約よりも、目的のための、手段を選ぶ　ことに価値を置く

制約の中で手段を選びながら、目的のために制約を作りながら、

最適なシステムを作成したいと考えているエンジニアは、

システムの制約よりも、目的のために手段を選ぶことに価値を見出します。

　

文章を書いて伝えることも似ています。

文章を書くときにも、環境（紙、Word、SNSなど）による制約があります。

SNSという制約の上で、書かれている文章に対して、

オーファンなどの、制約に特化した工夫の価値は、高くありません。

　

伝えることが目的の文章で、制約に応じたデザインに価値を置くことは、

エンジニアとして拒絶感があります。

# さいごに

$ Qiitaでは、\Hugeレイアウトにこだわる場合は、\normalsize画像を用いることが一般的です。 $
$ しかし、Qiita では、\Large式を書くために使われるTeX記法を用いる\normalsizeことで、画面サイズによらず、$
$ オーファンを消すことができるし、\large文字サイズ\normalsizeや\bf書体\rmを変えることができます。$

``` math
中央寄せも実現できます。
```

あなたは、以下のQiitaの記事の草をみて、どのように感じますか？

 - **[【Qiitaポートフォリオ】@j5c8k6m8の活動【毎日自動更新】](https://qiita.com/j5c8k6m8/items/45dc28d8204827d1212b)**
【Ruby on Rails Tutorial】Oops VFS connection does not exist　と表示される。【再起動実施済】

#プレビュー画面が表示されない

AWSのcloud9でRuby on Rails Tutorialを実施していたところ、プレビュー画面で以下となった。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594264/59b28533-9cf2-55cc-c607-b0ffcba8af4f.png)

##実施したこと
調べてみたところ、EC2サービスを再起動すれば、表示されるとのこと。
AWSのEC2からインスタンスを表示し、再起動を実施。
rails server コマンドを実施し、プレビュー画面が表示されるか確認するとまだ表示されない・・。


##原因
どうやらブラウザが原因のよう。
[brave](https://brave.com/)という広告ブロック機能が搭載されたブラウザ（報酬でBATという仮想通貨がもらえる！）
を利用していたため、制限されてしまっていた。
右上のライオンマークから「Shields　有効このサイトに対して」を無効にしたところ、直った。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/594264/2247fe10-cc66-d703-0e3d-08eba7d438da.png)

こんなしょうもないことで詰まるのはよくないので、今後はChromeを使おう・・・。
コロナ＋リモートワークのお陰で、自分のＩＴスキルが伸び始めたという話

#コロナのお陰で・・・

コロナのお陰といっていいのか、最近はリモートワークをしないという日常は無くなってしまった。
（逆に言えば、毎日、詰込みのエレベータに乗り、混雑した食堂で並ぶ日々は
いったい何だったのだろうかと思う。。。）

こんなにも、世界が変わるというのは、本当に夢見心地な感じだが、
慣れと言うものは不思議なもので、だんだんそれが当たり前になってくるから
不思議だ・・・

#最近の自分

こちらの記事に最近、DJANGOに取り組むことを宣言したのであるが、
DJANGOを触り始めて、今更ながら2年前に買ったpythonの本が
ようやく、しっくりと噛みしめて、理解できるようになってきた。

こういうのは、自分の脳の成長と関係しているようだが、
最近のコロナのお陰で、世界が変わってきたのと同調するかのごとく、
自分の頭の中に、すっと入ってきた感じがする。

#DJANGOの世界

　DJANGOの世界に入れば入るで、訳の分からないエラーには
どんどん出会うものである。
　しかしながら、メジャーな言語で開発をすることで、
良かったと思えることは、たいてい出会ったエラー内容を
GOOGLEで調べると、何がしか簡単に答えが見つかることだ。

　最初は、やみくもにGITHUBのソースを適当に探してきて、
動かそうとするのであるが、DJANGOと言うもの自体が
MANAGE.PYというファイルをベースにして、
それに対して、MIGRATEや、RUNSERVERと言ったコマンドを与える。

ここがflaskと違う点で、MANAGE.PY自体が完全に
アプリケーションを構成するフレームワークになっているのだ。

この感覚が最初は理解できなかったので、どれがMAIN関数なの？
っていうアホな状態からスタートした。

　最初はAPPSTARTをさせるまで、何がこれから始まるのか
まったく分からなかった。
　だって、appstartをやって作られるアプリケーションというのが、
そもそも最初に作ったPROJECTと、よく似たフォルダ体系だったし
URLS.PYなどのファイルも良く似ているので、
　プロジェクトと、アプリケーションの概念が、まったく分からなかった。

　あとはURLS.PYというのは、URLのルーティングとVIEWの関数を
１ｖｓ１で対応付けたりするものだが、これも全メソッドに対して、
宣言しないといけないことが分かるのに、時間がかかってしまった。

　URLにも階層があって、その階層をプロジェクト→アプリケーションに
委ねていくというのが、なかなか最初はピンとこなかった。

　次にMODEL.PY。こいつも度肝を抜かれる。
　もともとDJANGOの中に、MODELというクラスが作られていて、
そいつが勝手に、SQLなどのデータベースと、ゴニョゴニョやっている。
　
　それをオーバーライドするのかと思ったら、ちょっと違っていて
モデルオブジェクトを引数として、新しいクラスを作るみたいだ。。。
（感覚的には、クラスを継承してオーバーライドしているようなものだが）

　そいつをやることで、xxx.objects.メソッド　で
データベースにガッツリ勝手にアクセスしてくれるので、
わざわざSQLを覚えて、ゴリゴリすることも無くなってしまう。
（最初にここから入ることは、かなり危険な感じがする。
C#で言えば、いきなりLINQをやっているという感覚だが）

　あとはFORM.PY
　これはHTML5のFORMオブジェクトの化身だ。
　とても気持ち悪い感じがする。

　TEMPLATEフォルダと、それに付随するHTMLはJINNJAなので、
先にFLASKをかじっていたので、すんなりと移行できた。

　一番最後のVIEW.PY
　こいつが実は一番偉いんですね。
　VIEW.PYにごりごりと処理を書くのは、辞めた方がいいように思う。
　
　かといって、フォルダの中にあるファイル名が、ある程度DJANGOでは
決まっているので、この中にルールに従わないような名前のモジュールを
突っ込むのも、部屋を乱すみたいで辞めた方がいいような気がする。
　
#当面の課題

　さて、当面の課題であるが、DJANGOを触っていて気づくのは、
　これはバックエンド側の負担が結構でかいと思う。

　なにせ、その気になれば、フロントエンド側のJavascript処理を一切書かずに、
DJANGOで全部かけてしまうから・・・
　しかしながら、これだと完全にバックエンドサーバーへのGET送信が続いて
常時アクセスされた状態になってしまう。

　あとCSVをインポートしたりする処理と、SQLのマイグレーションで迷う。

　フロントエンド側にCSVや、JSONで渡して、JSでソートや検索をすれば、
いちいちサーバー側でモデルのSQL処理をするなどの、負担をかけないで良いから・・・

#VUE.JSの登場

　ここで一気に浮上してきたのが、VUE.JSだ。
　なにせ、VUE.JSは、このDJANGOとはまったく正反対の位置にあるのだから。

　それはいいかえると、フロントエンジニアの逆襲！
　PYTHONやRUBY,PHPなどが使えないエンジニア
　逆にJSしか使えないエンジニア
　これらの独壇場であるのだから・・・

　ちょっとだけ、苦し紛れな感じがするのが、やはりJAVASCRIPT自体が
オブジェクト指向のかじりかけなので、この部分で苦労すると思う。

　なにか、VBAのクラスモジュールを苦し紛れに触っている感じになる。

　しかしながら、他の2強のJSフレームワーク(ANGULAR,REACT)の学習コストに比べると
かなり軽いと聞く・・・

　そういう訳で、VUE.JSに立ち向かうかどうかで、非常に悩んでいる。
（まるで新しいトレンドに乗っかって、若者に付き合うのか、悩んでいる
アラフィフのオッサン、そんな感じである。）

　これからは、デザインで魅せるＷＥＢなのか、最低限のマナー程度のビジュアル
（といってもブートストラップ程度は使うだろうけど）にするのかが
悩みどころである。

　だんだんと、本質的な部分において、フロントエンドとバックエンドの
分散思考をとらないと、どうしても処理速度が満足できない
いまのＷＥＢアプリ社会の、課題と言うものが見え隠れしている。
（そして、AJAXなどの非同期通信といった、キーワードは
オブジェクト思考とはまた別の切り口の、頭の回路形成が求められる）

　そんなわけで、ちょっとコロナと関係ないが、
リモートワークのお陰で、いろいろ自宅での勉強が増えて、
ＩＴエンジニアとしての、知識もかなり増えてきた感じがする。

#最後に

　DJANGOアプリの構築については、sendexさんの動画が一番よく分かった。
　https://pythonprogramming.net/django-web-development-with-python-intro/
[随時更新]PostmarketOS関連メモ

最終更新日 2020/5/20

#インストール
[kapper1224さんのブログ](http://kapper1224.sblo.jp/)と[公式wiki](https://wiki.postmarketos.org/wiki/Main_Page)を参考に。  
但し公式wikiは関連項目がなってないので、検索を多用する必要がある。他に頼りになる情報源は[公式Gitabの主にIssue](https://gitlab.com/postmarketOS)と[OSAKANA TAROさん](https://blog.osakana.net/)あたりか。
この記事ではNexus7 2012 grouperを使用。

#Phosh関連 2020/04/22現在
Plasma-mobileなどよりは早いが、全体的に重い。タップ操作などへのインタラクションがない。タップして成功していると40秒ほどで立ちあがる、タップ失敗は反応が何もないのでただ待つ事になる。

##最重要
[Terminalが消えるバグ](https://forum.pine64.org/showthread.php?tid=9442)がある。必ずgnome-terminal他の動作するTerminalをインストールする。
公式にもある通り、パスワードに数字以外を使うとロック解除ができずに詰む。

##Bluetooth
GUIのSettingはまともに動作しない。
Terminalから

```shell
sudo apk add bluez-depricated
sudo /etc/init.d/bluetooth start
sudo hciconfig hci0 up
sudo blutoothctl
```

その後は[ArchLinuxのWiki](https://wiki.archlinux.jp/index.php/Bluetooth#CLI_.E3.81.AB.E3.82.88.E3.82.8B.E8.A8.AD.E5.AE.9A)と同じ。

#日本語関連
`apk search font`あたりで、とりあえず`sudo apk add font-ipa`あたりか。

#アプリ関連
[アプ](https://wiki.postmarketos.org/wiki/Category:Apps)などのカテゴリに意外に情報がある。
##ブラウザ関連
ほとんどのブラウザは初期設定では、起動直後もしくはWebページ描写中にエラーもなく消える。
Firefoxは[こちらの設定](https://wiki.postmarketos.org/wiki/Firefox)で動作確認。一応はMOZ_ENABLE_WAYLAND=1だけで動くことは動く。
Dilloはそのままで起動したが、仮想キーボードからの入力に異常がある。

#Anbox
[公式wiki](https://wiki.postmarketos.org/wiki/Anbox)にもあるが、Armv7では利用不能。但し気付かずに利用しようとしたが、エラーが異なっていたのでバグバグの模様。

#qemu関連
一部のグラボでは`pmbootstrap qemu`に`--display=gtk`オプションが必要。chroot内のqemuのドライバ不足が原因のため、`--host-qemu`でも良い。
マウスの矢印の当たり判定は矢印の先でも中でもなく、矢印の上方向。

#設定ファイル
$HOME/.config/pmbootstrap.cfgにも勝手に作成された。動作からドキュメントに見付からない設定ファイルが想定できたので、helpers/envkernel.shを読んで発見。ドキュメントもgoogle検索もあまりあてにならず、ソースを読まないとどうにもならない。

#電源関連
Powerボタンからの通常電源オフは出来ない。上部に電源マークがあるり、そこから可能。但し電源オフの確認はない。バッテリー関係の表示はあてにならない。Androidでは1日以上持つバッテリーが2時間程度で切れる。Nexus7で切れた場合はお約束の過放電からの再充電になる。外出しての使用は不可能だろう。切れる場合には徐々に画面が暗くなる。

#調査中
sudo使い過ぎ。設定でもっと減らせるはず。
xorg-server-xwaylandが初期では入ってない？<ソースを確認したら入ってた。
全体的にwaylandとxwayland関連が怪しい。[このへん](https://gitlab.com/postmarketOS/pmaports/-/issues/460)の[issue](https://gitlab.com/postmarketOS/pmaports/-/issues/484)か。
GDK_BACKEND=waylandからのgtk3アプリでも起動不能が多い。
ターミナル関連もまともに動かせていない。
termiteは問題なく動作する、やはりxwayland関連が怪しいか。
[phosh: incorrect keyboard input in Xwayland apps](https://gitlab.com/postmarketOS/pmaports/-/issues/460)
termiteでも標準キーボードでコントロールキーの入力が出来ない。上下ホーム等の一部キーはABCモードの右下から配列にいける。CUIのみで使うにもキーボード関連の調査が必要だろう。

#感想
##利点
現状移植などは頑張っているように見える。Ubuntu touchよりサポート機種やUIの選択肢も多く関係者の努力を感じる。
公式のやり方に従う、公式に近い環境で利用する限りにおいては、さほどの問題を感じず楽しく使える。
開発状況やサポート等も活発に見える。

##欠点
Pythonをメインにしている時点でイヤな予感がしていたが、設定や構成ファイルの置き方など、設計段階から場当たり的に感じる。整理されて、あるべき場所に置かれていない。分散していて探すにはソースを読むしかない。
pmbootstrap等もcomplectしている。巨大なブラックボックスであり、途中まで途中からなど諸々の処理がない。これはArch LinuxやあるいはAlpine Linuxなどのシンプル路線と反対の発想である。
予め考えられたオプションのみを正とし、とりあえず呼び出し先にオプションを渡してくれるなどの処置をしてくれない。
以上から開発者側の正しさを利用者に押し付けている印象が強い。またソースレベルからの改変が必要になり、非常に遊びにくい。

##結論
インストールまでが面白く推奨できる使い方で、実際に携帯等に使用するのは技術者でも面倒そうだ。
巨大な技術的負債により、何か少しの事で今迄のモバイル用Linuxと同じ道を辿ってしまう懸念がある。
Circle CIでWebpackのビルドがタイムアウトしたときの対処法（TerserPluginのparalell設定）

はい。
タイトルに答え書いてます！

# TL;DR
- CircleCIでWebpackのビルドプロセスが落ちており原因がCPUかメモリーっぽいとき
- JSの縮小化処理で使ってる`terser-webpack-plugin`の`paralell`に並列数を明示的に指定すれば解決する！（かもしれない）
- ここに書いてる :arrow_right: 
https://webpack.js.org/plugins/terser-webpack-plugin/#parallel

# 問題
- Circle CIで実行してたwebpackのビルドが頻繁に落ちるようになった

```sh
#!/bin/bash -eo pipefail
yarn build
yarn run v1.22.0
$ APP_STAGE=$ENV_NAME run-s clean copy-assets build:webpack
$ rimraf build
$ cpx "src/assets/**/*" ./build
$ webpack --config webpack/config.base.js --mode production
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade caniuse-lite browserslist`
Browserslist: caniuse-lite is outdated. Please run next command `yarn upgrade`

Too long with no output (exceeded 10m0s): context deadline exceeded
```
こんな感じで普通に10分のデフォルトタイムアウトで落ちる

- Circle CIにSSHでログインして手でビルドコマンド叩くと数十秒で正常に終わる
- topコマンドなどで確かめるとnodeのプロセスはかなり動いてCPUに負荷がかかっており、loadaverageも高まっているので思い処理だというのは分かる。
- なぜ手動だといけるのか。。。


# 調査、検証
## タイムアウトを伸ばす
- 言うて動くときは動くのでギリギリ10分超えたのではないか
     - ->えーいとりあえず伸ばしてみよう
     - ->30分まで伸ばす
     - 終わらない :innocent: 

## いろんなもののバージョンを上げてみよう
- 何かのバグにはまってて実は最新版なら解消されてる説
- 上げたもの
  - webpack 4.29.5 -> 4.42.0
     - 結果： 効果なし
  - node 10系 -> 12系
     - docker imageを更新
     - 結果： 動いた！何回かやっても問題なし！:tada:

## 解決？
  - と思ったら数日後また同じエラーが戻ってきた。。なぜ、、、

## Webpackチューニング調査
- 挙動的にはどう考えてもWebpackの処理の重さが原因だ
- 巷に溢れてるチューニング施策を探して実施してみよう、、！
- 色々調べて見た結果。。。

## 解決策発見！
- どうやら重いのはJS縮小化の処理くさい
    - 縮小化で使われている`terser-webpack-plugin`に`paralell`オプションがある。
    - CircleCI上でtop見た時にかなりの数のnodeプロセス動いてたんで、並列で動いていると勝手に勘違いしていたのですが、どうやらそういうわけではない。

- ・・・というか、もろ[ここ](https://webpack.js.org/plugins/terser-webpack-plugin/#parallel)に書いてるのですが、**CircleCIのような実際のCPU数が提供されないような環境ではparalell数を直指定する必要がある**とのこと。
- `paralell: true`ではだめです。あくまで数指定。

```
⚠️ If you use Circle CI or any other environment that doesn't provide real available count of CPUs 
then you need to setup explicitly number of CPUs to avoid `Error: Call retries were exceeded`
```
というわけでこんな感じの設定をWebpackの設定ファイルにterser-webpack-pluginの設定を追加すれば良いです。
*※webpack4以降ではmode=productionでビルドすれば特に縮小化の設定はいらないわけですが、実際`terser-webpack-plugin`が動いているようでオプション設定したい場合はこのような指定が必要です。*

```js
const TerserPlugin = require('terser-webpack-plugin')

module.exports = {
  optimization: {
    minimize: true,
    minimizer: [
      new TerserPlugin({
        parallel: 6 // 6は適当です。環境に応じて変えてください。
      })
    ]
  }
}
```

プロセッサの数はCircleCI上でこれらのコマンドで調べられるので参考にすればよいですが、かなり多く出ると思うのでWebpackのビルドくらいなら使い切るほど指定する必要も無いとは思います。（規模による）

```sh
# CPU ごとのコアの数
grep cpu.cores /proc/cpuinfo | sort -u
# 論理プロセッサーの数
grep processor /proc/cpuinfo | wc -l
```
https://webpack.js.org/plugins/terser-webpack-plugin/#parallel

# まとめ
ぐぐっても全然解決策が引っかからず途方にくれたので、少しでも同じ問題に当たった人の助けになればと思い雑に書き残しました。
freee for kintone と マネーフォワード クラウド for kintone を比較してみた

kintone向けサービスがすでに用意されているメジャーな会計サービスを、kintone連携部分に焦点をあてて比較してみた。
※会計サービス自体は使ったことないのでよくわかりません。。。
※あくまでもkintone連携のあたりを調べてみた結果です。
※情報荒いです。

# freee for kintone
https://support.freee.co.jp/hc/ja/articles/360031354191

- クラウド会計ソフト freee とkintone をつなぐサービス
- freee のプロフェッショナルプラン・エンタープライズプラン契約者は無料で使える
- freee には、会計ソフト以外に人事労務ソフトもある
- kintone連携は2019/7からサービス開始

## 利用料金
- 会計freee のプロフェッショナルプラン・エンタープライズプラン契約者は無料で使える
    - [法人向けプランの利用料金](https://www.freee.co.jp/houjin/price/) 
        - プロフェッショナルプランまたはエンタープライズプランは高い…
        - 個人事業主向けプランもNG

## 拡張性
- API情報が公開されているので、自力でいろいろ作れる（ [freee Developers Community](https://developer.freee.co.jp/)）
- [スタートガイド](https://developer.freee.co.jp/getting-started)から開発用環境を申し込みできる
- **プロフェッショナルプラン/エンタープライズプラン** を使わない規模のお客様の場合、freee for kintone は使えないので自力で **頑張って作るしかない**
- [アプリストア](https://app.secure.freee.co.jp/)にいろいろなアプリ（他サービスとつなぐための機能）が公開されているので、いろいろなサービスとつなげたい場合はよさそう
    - LINEやSlackとつなぐとか。人事労務freeeも使うなら[cybozu.comとユーザー連携](https://app.secure.freee.co.jp/applications/5519)もできる。

## 参考になりそうな話
- [kintoneとfreeeの連携を成功させる鍵は「krewData」だった](https://ascii.jp/elem/000/004/003/4003241/)
- [会計 freee の料金プラン詳細](https://support.freee.co.jp/hc/ja/articles/202849000)

# マネーフォワード クラウド for kintone
https://biz.moneyforward.com/invoice/integrations/kintone

- **マネーフォワードクラウド請求書** と kintoneをつなぐ部分（プラグイン）が**セット**になったサービス
- マネーフォワードには、請求書以外にも会計・確定申告、経費、給与、勤怠など様々なサービスがある。
- kintone連携は[2020/2からサービス開始](https://corp.moneyforward.com/news/release/service/20200227-mf-press/)

## 利用料金
- [180,000円／年（2020/4現在）](https://biz.moneyforward.com/invoice/integrations/kintone)
- for kintoneで使えるマネーフォワードクラウド請求書が、[通常プラン](https://biz.moneyforward.com/invoice/price)のどのプランにあたるのかはよくわからず…

## 拡張性
- [いろいろ連携](https://biz.moneyforward.com/invoice/integrations)したらよいみたい
- [API](https://biz.moneyforward.com/invoice/developer)も用意されている
    - 開発者用環境はないようなので、まずマネーフォワードクラウド請求書のアカウントを用意する必要がある
Ruby on Rails + MySQL のローカル環境を  Docker で構築をする

# はじめに

RailsのアプリをDockerで環境構築したのでその時のことを書いていきます。

今回は既に作ってある Rails アプリに Docker を導入していきます。

Rails + MySQLの構成を docker-compose で立ち上げるところまでしていきます

## Docker導入の準備

### 1. Rails 用の Dockerfile を作成する

Rails アプリのディレクトリに Dockerfile を作ります。
プロジェクト名は sample_app としました。

~~~
sample_app user$ touch Dockerfile
~~~

Dockerfile に書き込んでいきます。

~~~Docker:Dockerfile
FROM ruby:3.0.0
RUN curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - \
    && echo "deb https://dl.yarnpkg.com/debian/ stable main" | tee /etc/apt/sources.list.d/yarn.list
RUN apt-get update -qq && apt-get install -y build-essential nodejs yarn
RUN mkdir /app
WORKDIR /app
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN gem install bundler
RUN bundle install
COPY . /app
~~~

以下、ざっとこの Dockerfile の流れです


 ` FROM ruby:3.0.0` 
→ 今回は Ruby の3.0.0のバージョンを使います。
これでコンテナ内で Ruby の3.0.0バージョンが使えるようになります。

`curl -sS https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key add - ...(以下省略)`
→ yarn(Rails6では必要)をインストールするための準備です。


`RUN apt-get update -qq && apt-get install -y build-essential nodejs yarn`
→ Railsを動かすために必要なものをコンテナ内にインストールします。

`RUN mkdir /app`
→ コンテナ内ににappという名前でディレクトリを作ります。


`WORKDIR /app`
→ WORKDIRコマンドでディレクトリを指定することで、それ以降の命令は全てそのフォルダ内で実行されることになります。

`COPY Gemfile /app/Gemfile`
`COPY Gemfile.lock /app/Gemfile.lock`
→ホストのGemfileとGemfile.lockをコンテナ内のappディレクトリにコピーします。

`RUN gem install bundler`
→コンテナに bundler をインストールします。

`RUN bundle install`
→コンテナ内で Gemfile に書かれた gem をインストールします。

`COPY . /app`
→ホストの Rails のフォルダをコンテナの app ディレクトリにコピーします。

### 2. docker-compose.ymlを作成する

docker-compose.yml を書いていきます。

~~~yml:docker-compose.yml
version: '3'
services:  
  db:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: password #適宜自分のMySQLのパスワードにしてください
    volumes:
     - mysql-db:/var/lib/mysql
  web:
    build: .
    command: bundle exec rails s -b 0.0.0.0
    volumes:
      - .:/app
    ports:
      - "3000:3000"
    depends_on:
      - db
volumes:
  mysql-db:
    driver: local
~~~



### 3. docker-compose でRailsを起動する。

docker-comoseコマンドでRailsを起動します。
以下を順に実行しましょう。

~~~
# Docker イメージをビルドします。
sample_app$ docker-compose build

# DBが作られていないので rails db:createが必要です
sample_app$ docker-compose run web rails db:create

# migrate もします。
sample_app$ docker-compose run web rails db:migrate

# 起動
sample_app$ docker-compose up
~~~

### 4. その他のコマンド

~~~
# -d をつけるとバックグラウンドで起動できる
sample_app$ docker-compose up -d
~~~

~~~
# アプリを止めるときは
sample_app$ docker-compose stop
~~~

~~~
# 再起動するとき
sample_app$ docker-compose start
~~~

~~~
# アプリの停止 + コンテナの削除
sample_app$ docker-compose down
~~~

~~~
# -v をつけると volume も削除できる(今回で言うとDB)
sample_app$ docker-compose down
~~~

~~~
# console を開きたいとき
sample_app$ docker-compose run web rails c
~~~


#おわりに
Dockerを使えると環境構築が楽で良いですね