OmniAICreator/Qiita-1.07M huggingface dataset:
360°映像・画像の編集・制作の準備

#はじめに
こんにちは。[UT-virtual Advent Calendar 2019](https://qiita.com/advent-calendar/2019/ut-virtual) 昨日に引き続き360°の映像系の話をしていきたいと思います。
[昨日の記事](https://qiita.com/wappaboy/items/5d359829d30283d24d89)を読んでもらうとわかると思うのですがさらっと画像の用意の話をしていると思います。そこで今回はそうした画像・動画の用意の方法について説明したいと思います。
2019年11月に、サークルのイベント企画を全天球カメラで記録した映像の編集の時に気になった部分の説明をしていきます。

## 制作段階での各種バージョン・使ったもの
|編集アプリ| バージョン|
|---|---|
|AfterEffects|16.1.2|
|Premiere|13.1.4|
|DaVinciResolve|16.1.1|

|撮影機材|全天球変換アプリ|バージョン|
|---|---|---|
|InstaEVO|Insta360studio2019|3.4.1|
|Galaxy Gear 360|Gear 360|1.0.3213.0|
|RICOH THETA V|RICOH THETA for Mac|3.11.1|

#準備の準備
カメラから動画データを移します
InstaEVOのみmicroSD単体での動画ファイル移行が可能でした。
Galaxy Gear 360・RICOH THETA VはmicroSD単体ではうまくいかず本体とケーブルで接続することでうまくデータを移行することができました。
###ファイルフォーマット
各カメラこのようなフォーマットで書き出されます


|撮影機材|動画形式|内容|
|---|:----:|---|
|InstaEVO 注:画像は180°3D|insv|![1576753636553@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552069/7a21fca3-8b76-706f-8838-c1a05bfe43a2.jpeg)|
|Galaxy Gear 360|MP4|![1576753761804@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552069/333f60d9-f7a3-c1eb-d082-c96bfeccdaef.jpeg)|
|RICOH THETA V|MP4|![1576754044757.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552069/fa296953-4126-23ec-246b-948a0e507daf.jpeg)|

#編集準備・基本的映像処理
次に横長の映像変えます。
右目・左目で各2:1で構成され3Dだと上下(2Dだと2:1のまま)に分けられたものを**エイレクタンギュラー**と言います。
基本的にUnityでも動画編集ソフトでもこの形式じゃないと都合が悪かったりします。
この書き出しは各メーカーのアプリを使って行ってください。
<details><summary>AdobeアプリならMP4のまま動画編集が可能だが</summary>AdobeのアプリケーションならMP4の動画形式であれば編集上はVR設定をしてしまえばVR映像として繋がっているかのように編集が可能です。しかし、書き出しする際、VR設定のまま書き出してもVR映像としてエクイレクタンギュラーに書き出すことはできず、もとの映像と同じ形のまま書き出されてしまいます。</details>
また、各種の動画形式を選んでエクイレクタンギュラーとして書き出すことができるサービスは今の所ありません。（もしあったら教えてください）
####ダウンロードサイトリンク
|[THETA](https://support.theta360.com/ja/download/)|[Gear360](https://www.galaxymobile.jp/support/model/SM-R210NZWAXJP/)|[Insta360](https://www.insta360.com/download)|
|---|---|---|

###それでは編集・実装していきましょう。
 [unity(昨日の記事)](https://qiita.com/wappaboy/items/5d359829d30283d24d89)

<details><summary>Adobeアプリ Premiere・AfterEffects</summary>
<dt>新しくシーケンスを作る<dt>
<dd>プロジェクトウィンドウで右クリック→新規項目＞シーケンス...<dd><dd>画質:比率が合うものを選択<dd>
<dt>シーケンス変更</dt><dd>シーケンス>シーケンス設定…<dd><dd>VRプロパティからエイレタンギュラーなら写真の状態で![1576755627969@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/552069/0a046f65-dba7-dbbd-4e25-f6e970efffa4.jpeg)
もしエクイレクタンギュラー以外であれば自動検出されるVRプロパティを確認してください</dd></details>

<details><summary>DaVinciResolve</summary>
1.動画素材を並べる
<dt>Fusionでエフェクトを当てる</dt>
<dd>LatLong Patcherをあてると自動的に検出され360°映像として処理される</dd><dd>(Effect>Tools>3D>VR>LatLong Patcher)</dd></details>
#####[参考動画](https://youtu.be/WUKYVKCRNHM)
#最後に
編集画面では全球を見ることができなくなかなか編集しづらい上、動画データが普段のものより扱いづらい360°動画ですが短い作品でも楽しめるのでどんどん使ってみてください。
今回はしょぼフェスというイベントに出すためにUnityからQuestに入れても盛り上げれるようにと映像データを編集してみました。結局ハンドトラッキングが使えるようになって、Unity上でやろうとしていたことができるようになってしまったのですが...
まだまだ盛り上げっていきそうなVR、これからも**楽しんでいきましょー**
【Python】*args **kwrgs って何だろう

## 01.本記事に書くこと
- 関数のパラメータに定義する`*`や`**`の意味と、その使い方


時間が経ってしまっても素早く思い出せるように、ここに整理したいと思います。

## 02.`*`と`**`は可変長引数を受け取るパラメータにつけるものである
関数のパラメータに`*args`や`**kwargs`と書いてあるコードを見かけた。
これは可変長引数を受け取るパラメータに記述されるもので、関数呼び出し時にパラメータに渡す引数の数を、固定ではなく任意の数にできるようになる。

可変長引数とは、通常１つしか引数が指定できないところ、任意数の引数を指定できるようにしたもの。

*〜普通はダンボール１つにつき１つの品物しか入れられない。
しかし、可変長引数ならば１つのダンボールにつき、いくらでも品物を入れることができる上に、それらは１枚のプチプチでパックされる。〜*



```python:例
def kansu(*args):
    print(f'{args}を受け取った!')

kansu('Apple', 'Banana', 100) 
# ('Apple', 'Banana', 100)を受け取った!
```
パラメータは`args`１つだけに対して、３つの引数を渡しているが、エラーなく動作している。

身近な例でいうと、`print()関数`や`.format()メソッド`でも可変長引数が用いられている。

```python:いくらでも引数を渡せる
print('a','b','c') # a b c
```

又、`args`や`kwargs`という名前は慣習的に用いられるものなので、好きな名前でも動作する。

```python
def x(*z):
    y = []
    for i in z:
        y.append(i*10)
    print(y)
    
x(1,2,3,4,5,6,7,8)
# [10, 20, 30, 40, 50, 60, 70, 80]
```

## 03.`*`が１つの時と２つの時の違い
可変長引数には２種類あり、それぞれ引数の渡し方や、受け取り方が異なる。


１．可変長位置引数を受け取るパラメータ <- `*args`
　　　任意の数の引数をタプルで受け取る（引数を渡さなければ空のタプルになる）
　　　位置引数で渡す

　　　　*〜全品物を１枚のプチプチでパックしてダンボールへ〜*

２．可変長キーワード引数を受け取るパラメータ <- `*kwargs`
　　　任意の数の`キーワード=値`という形の引数を辞書型(`key value`)で受け取る
　　　（引数を渡さなければ空の辞書になる）
　　　キーワード引数で渡す

　　　　*〜全品物にポストイットで名前をつけた上、全品物を１枚のプチプチでパックしてダンボールへ〜*


## 04.可変長`位置`引数を受けとるパラメータの使い方
引数に`*`をつけることで、パラメータが可変長位置引数を受け取るようになる。
つまり、任意の数の引数を受け取る。
関数のパラメータのどこに可変長位置引数を定義するかによって、その関数の使い方が変わってくる。

```python:1.最後のパラメータが可変長
def myfunction(x, y, *z):
    print(f'{x} - {y} - {z}')

myfunction(2, 3, 5, 6, 7)  #  2 - 3 - (5, 6, 7)
```
１つ目、２つ目の引数はそれぞれ`x`,`y`に対応している。
それ以降の引数は`z`に対応しており、タプルで格納される。


```python:2.途中のパラメータが可変長
def myfunction(x, *y, z):
    print(f'{x} - {y} - {z}')

myfunction(2, 3, 5, 6, 7) # TypeError: myfunction() missing 1 required keyword-only argument: 'z'
```
パラメータ`z`に何の引数も渡されていないため、エラーを吐く。この場合、`z`はキーワード専用引数になるので、デフォルト値を設定してあげたり、呼び出す時にキーワード引数として使わなければならない。

```python:2-1.デフォルト値を設定
def myfunction(x, *y, z=0):
    print(f'{x} - {y} - {z}')

myfunction(2, 3, 5, 6, 7) # 2 - (3, 5, 6, 7) - 0
```
```python:2-2.キーワード引数として使う
def myfunction(x, *y, z):
    print(f'{x} - {y} - {z}')

myfunction(2, 3, 5, 6, 7, z=0) # 2 - (3, 5, 6, 7) - 0
```

## 05.可変長`キーワード`引数の使い方
引数に`**`のつけることで、パラメータが可変長キーワード引数を受け取る。
つまり、任意の数の`キーワード=値`を受け取り、キーワードと引数は、それぞれを辞書型の`keｙ`と`value`に対応する。
関数のパラメータのどこに`**`を定義するかによって、その関数の使い方が変わってくる。


```python:1.最後のパラメータを可変長キーワード引数にする
def myfunction(param1, param2, **param):
    print(f'{param1} | {param2} | {param}')

myfunction(2, 3, param3=4, param4=5, param5=6)  # 2 | 3 | {'param3': 4, 'param4': 5, 'param5': 6}
```
可変長キーワード引数で得た値は辞書型になる。

```python:2.途中のパラメータを可変長キーワード引数にする
def myfunction(param1, **param, param2):
    print(f'{param1} | {param2} | {param}')
```
結果はシンタックスエラー
可変長キーワード引数を途中に定義することは許できない。

## 06.２つの可変長引数を併用する場合
可変長位置引数を受け取るパラメータの後においた通常のパラメータは、キーワード専用引数になる。

```python
def Test(a, *b, c): # cはキーワード専用
  pass
```

可変長キーワード引数を受け取るパラメータの後に、通常のパラメータはおけない。

```python:05-2.再掲
def myfunction(param1, **param, param2):
    print(f'{param1} | {param2} | {param}')
```

よって併用する場合は、以下のような順番にしなければならない。

```
1.位置引数とキーワード引数の両者を受け取るパラメータ
2.可変長位置引数を受け取るパラメータ　
3.キーワード専用引数を受け取るパラメータ
4.可変長キーワード引数を受け取るパラメータ
```
Pythonで入力された整数を素因数分解 ver.1

#はじめに
　以前作成した「[Pythonで入力された数字が素数か判定するプログラム](https://qiita.com/totusuna/items/9ae6ada058fa4e9cd6f9)」に、合成数だった場合に素因数分解を行ってくれる機能を追加してみました。

#プログラムの原理
　小学生の時に習った素因数分解のやり方を思い出して、小さい素数から順に割り続ける方針にしました。
　具体的には、SymPyのprimerangeを用いて素数リストを作成し、そのリストから割り切れる数で割り続けます。そして、素数リストの最後まで割り算を行ったら終了としました。

#実際のプログラム
```Python
from sympy import primerange
inn = n = int(input("素数か確かめたい数を入力してください。>> "))
primlist = list(primerange(2,(inn+1) / 2)) #1
yaku = []

for i in primlist:
    while n % i == 0: #2
        n /= i
        yaku.append(i) #3

if not yaku: #4
    print(n, "は素数です。")
else:
    print(inn, "は合成数で、素因数分解すると",yaku, "です。")
```

###大まかな流れ
1. 素数リストを (n+1)/2 まで作成
2. 素数リストの中から割り切れる数を探し、割り切れなくなるまで整数 n を割り続ける。
3. 割るたびに yaku というリストに割った素数を追加していく。
4. yaku に何も入っていなければ素数と表示する。なにか入っていれば素因数分解した結果を表示。

###実際にやっていること
1. #1で、前回同様Sympyを用いて作成。
2. #2で、while構文を用いることで、ifを使わずに直ぐに割り続ける動作に入れるようしてあります。
3. #3で、.append(i) とすることで yaku に割った素数の i を追加します。
4. #4で、yaku に数が入っていれば、合成数であるということに注目しました。具体的には if 構文を用いて、if **not** yaku とすることで yaku に何も入っていない際に、if より下の処理に入ります。

###苦労した点
　はじめにプログラムした際、primerange()で作成する素数リストの範囲を、前回と同じ「primerange(2, int(n**(1/2)) + 1)」としていました。すると、入力された整数が "2×素数" の場合に2のみが yaku に追加されて正確に素因数分解できない問題が発生しました。 具体的には14 (2×7) のような数字を入力した際に結果として『14 は合成数で、素因数分解すると [2] です。』と出てしまいました。
　そのため素数リストの範囲を「primerange(2, (inn+1) /2)」に設定しました。こうすることで先程の問題の解決としました。この際、inn に +1 をすることで "2×素数" の整数でも素数リストが素数まで作られるようになっています。具体的には14を入力した際にprimerange(2, 7.5)となるため、primelistの中身が [2, 3, 5, 7]となります。もし+1をしないと、primerange(2, 7)となるため、primelistの中身が [2, 3, 5]となってしまい、7が素因数分解の結果に入らないことになり、正確な素因数分解ができなくなります。


#反省点
　素数リストの作成の範囲が広すぎるために、入力される整数が大きくなる(7桁以上)と、とたんに計算速度が落ちます。そのため範囲の設定や素因数分解の方式を少し改善したい思います。
最後まで読んで下さいまして有難うございました。
VirusTotalに聞いてみたい

小ネタ

#はじめに
Webアクセスログを眺めていると、ふと**VirusTotalではこのＵＲＬはどうなんだろう？**と思いませんか？

そんな時でもSplunkはあなたの味方です

**APIを叩けばいいじゃない**というかたはそっと見守ってください。

**[APPあります](https://splunkbase.splunk.com/app/4283/)**
そうですよね、また車輪を再開発してしまった・・・

#とりあえず
ハッシュ値とかドメインはそのまま放り込めばいいから、いいですよね

例えば、
`c58f07f84d6aae485416683e5515b39bc39349e69bc14629440e693da23d6c4d`
のハッシュを検索するURLを作ろうとするなら

`| eval link="https://www.virustotal.com/gui/file/".hash_value."/detection"`
とかしてlinkが作れたりします。
ドメインも
`|eval link="https://www.virustotal.com/gui/domain/".domain_value."/details"`
と簡単

でもURLの時ってそのまま放り込めない。

#解決策
```Splunk:SPL
 | makeresults 
 | eval _raw="http://www.yahoo.com/" 
 | eval hash=sha256(_raw) 
 | appendpipe 
     [ eval hash="ed91698b5823a5e4424726955dd3fd437d9cfdc46f7b8988cded5da779cc7483"]
 `comment("the hash is VT link hash")`
```

https://www.virustotal.com/gui/url/ed91698b5823a5e4424726955dd3fd437d9cfdc46f7b8988cded5da779cc7483/detection

`sha256()`に放り込むと大丈夫です。ただ癖があって
`http://`から始まって、`/`までかファイル名まで、が基本。
試してみると
`http://www.yahoo.com`でハッシュをとると検索結果がでない、とかあります。
そうなると*workflow*なんかは二つ作ったほうがいいと思います。
フルパスと、ドメイン名だけの場合と。

#まとめ
繰り返しになりますが、これは**ふとアクセスが気になった**場合に活用できるかな〜と思います。
_cURL_用のリストをつくるんだ、とかいろいろ応用は効くかもしれませんね。
削除したデータを復旧する(絶対に)

# 0. 概要
年末の忙しい時期にハードディスクのデータが全て消えるという体験はしたことがありますか？
先輩として忠告しておくと凄い悲しい気持ちになります。

そこで、頭記にもある意気込みでデータ復旧をしていったので、備忘録として残しておきます。

# 1. 前提条件
まず置かれている状況。
## 1.1. 状況
初めに、`rm -rf *`を実行します。
目的とするソースコードやファイルが全て消えたことを確認してからがスタートラインです。

この状況から概ね以下の方法をとるでしょう。
 - 急いで`やってしまったマシン`をシャットダウンする
 - 他のPCでLinuxのライブUSBを作成
 - LinuxのライブUSBで`やってしまったマシン`を起動する
 - ライブOSから`やってしまったマシン`のディスクを`fdisk -l`で見て確認
 - 後は、`TestDisk`や`ext4magic`、`foremost`、`extundelete`を駆使してファイルを復旧

普通なら、ここまですれば凡そのファイルは復旧されます。
しかしながら、この場合でも頑なに復旧を拒まれる場合があります。

## 1.2. 条件
ここで現状の条件をまとめておくと、

 - `TestDisk`や`ext4magic`、`foremost`、`extundelete`でファイルを復旧できない
 - ディスク自体は物理的に破損していない
 - ハードウェアRaid 1+0
 - ext4のファイルシステム
 - 問題発生後すぐにシャットダウンしたのでinodeが切れているだけで論理的にはファイルが残っていそう
 - データ復旧業者に断られる

最後は、データ復旧業者にお願いしたところ`TestDisk`や`ext4magic`、`foremost`、`extundelete`で復旧出来ない場合は、相当やってしまっているので無理ですと言われ、
どうしてもお願いしますと価格交渉したところ、最低でも100万円からですと言われました。


# 2. データを復旧する
まず物理的に逝ったわけではなく、インデックスが外れてしまっただけで目的とするファイルはディスク中の情報の海にいると仮定します。
そこでまずは、RAIDがややこしいのダンプして1つのファイルにします。その次にファイルを復旧させていきたいと思います。

## dump
以下でダンプをする。

```
# 対象のディスクを確認する
$ sudo fdisk -l
> sda1
# ダンプする
$ dd if=/dev/sda1 of=./dump.img bs=512M
```

これで1つのファイルになった。

今回、復旧させたいのは主にソースコード。
そして、そのソースコードは多分、このダンプファイルのどこかにいる。

## recover
ダンプファイルが1テラくらいあり、どこに何のデータがあるかなんてまるで見当もつかない。
そこで、ソースコードの1部を想像して、あるテキストのバイナリコードがあるところを引っ張ってくるようにする。
そう、Grepを使う。

```
grep -i -a -B[size before] -A[size after] 'SEARCH_TEXT' DEVICE > OUTPUT_PATH
```

`-i`はケースセンシティブにしない(大文字小文字を区別しない)
`-a`はバイナリサーチ

例えば、`python`であれば`#!/usr/bin/python`なんて書かれていたりする。
その場合は、こんな感じで使う。

```
grep -i -a -B10 -A1000 '#!/usr/bin/python' /dev/sda1 > ./backup.txt
```

これで地道にソースコードを追っていった結果、部分的に復旧することが出来た。
なお、画像なら画像のヘッダーを同様に検索にかければよい。

因みに`\r`->`^M`で検索を掛ければ大体のテキストを持ってこれる。

部分的にデータは引っ掛かるものの、この部分データから1つのファイルに成型していくのが、地獄の作業。

一先ず、この方法でかけらでも復旧できないようなら諦めた方が良さそう。
<b>データは消さないに限る。</b>
プログラム初心者はQiitaの初心者投稿がタメになる件

#できる人の話はレベルが高すぎる
初心者にとっては、できる人の前提知識すら持たないので、質問サイトなどで回答者として活躍するエンジニアの回答のレベルが抽象的すぎて理解できないことが多くあった。

#同じ初心者がいることの安心感
この記事に「初心者」タグをたくさんつけてみたが、これだけ初心者に関する記事を投稿する土壌がQiitaにはある。
見てみると、まさに自分と「同じ目線」の投稿者が多く、それはレベルが低いところからの解説であることが多いので理解しやすい傾向があった。

#めげずに勉強する気になれる
正直、「こんな初歩的な質問で申し訳ない」というメンタリティに自分自身がなることが多くて、質問を躊躇し孤独にググることが続いた。もちろん、ググることは大切だ。それでもわからなければすぐに質問することは大事。しかし場所は棒エンジニア質問サイトよりも、初心者向けQittaでサーチするなりしたほうが良い場合もあるということに気がついたのでした。
オペレーションミスを防ぐWordMoveのforbid設定

以前に「[WordPressを使ったサイト制作標準フロー](https://qiita.com/koji-yamauchi/items/394c8e111dcd14a5d311)」の中でWordMoveを紹介しましたが、コマンド操作ミスで大事故になる危険性があります。

例えば、本番環境に修正したテーマを適用する際に下記のように行いますが

```
wordmove push -e production -t
```

打ち間違えで、

```
wordmove push -e production -u
```

だったり、

```
wordmove push -e production -d
```

のように一文字間違えるだけでアップロードファイルを上書きしたりデータベースをまるっと上書きしてしまう可能性があります。

そのような操作ミスを防ぐためにWordMoveバージョン3から `forbid` という設定項目が追加されました。
例えば設定ファイルで下記のように記述すると、production環境へのデータベース、プラグイン、アップロードファイルのpushを禁止できます。（禁止したい項目を `true` とする）

```
production:
  forbid:
    push:
      db: true
      plugins: true
      themes: false
      languages: false
      uploads: true
      mu-plugins: false
    pull:
      db: false
      plugins: false
      themes: false
      languages: false
      uploads: false
      mu-plugins: false
```

これでwordmoveコマンドを実行するときのストレスが少し緩和されますね。

ただし、2019年12月時点の `vccw-3.21.1` ではWordMove2.4.0がインストールされますのでZIPファイルのダウンロードと解凍後に `provision/playbooks/commands.yml`
のバージョンを `4.0.1` に書き換える必要があります。

```
    - name: Install Wordmove
      become: no
      gem:
        name: "wordmove"
        user_install: yes
        version: "4.0.1"
      ignore_errors: yes
```

このあとに、 `vagrant up` すれば WordMove 4.0.1 がインストールされたWordPressの環境が構築できます。
【2019年12月版】Gmail のエイリアス機能でメール通知を Slack にゆるくまとめてみた

# Gmail の特定のエイリアスだけ Slack に転送する方法です。

Slack の "転送先アドレスを取得" すれば、`Slackbot`宛てですがメールでSlackにメッセージを投げることができます。

今回は Gmail の特定のエイリアスのアドレスだけを Slackbot 宛てにメールを転送する方法です。

Gmailの`エイリアス`とは、みなさまご存知かと思いますが、自分のメールアドレスのアカウント部分に `+` にキーワードを続けて、メールアドレスに"タグ付け"のようなことができる機能です。
例えば、自分のGmailアドレスが`abcdefg@gmail.com`として、これに `abcdefg+xyz@gmail.com`とか`abcdefg+facebook@gmail.com` などと `+キーワード`を付けてもちゃんと`abcdefg@gmail.com`のアドレスと同様に受信できる、というものです。
それでいて送信先は`abcdefg+xyz@gmail.com`とか`abcdefg+facebook@gmail.com`のままなので、細かく管理すれば`From`を見なくても**送信元が特定できます**。(いつだったか、これで迷惑メールのアドレスの流出元を追跡している人がいましたね。)
**Gmail一つで送信先をいくらでも作れる**というこの機能で、チャチャっとメールの振り分けをしてしまおう、と言うのが今回のキモです。

無料でなおかつ数ステップで設定可能なので、ゆっくり設定してる暇ないけどとりあえずSlackで通知をまとめて受けておきたい、という時におすすめな方法です。

## 0. 自分だけのワークスペースを作る

先に述べたとおり、転送先のアドレスに送られてきたメールは`Slackbot`宛てですので全館放送となってしまいます。
個人だけで通知受け取れればOKのような`メンバーに迷惑かけたくない場合`は自分一人だけのワークスペースを作成しておくのがオススメです。

## 1. Slack の転送用アドレスを取得

ここでは MacOSのデスクトップ版 Slack アプリで手順を説明します。

Slackのワークスペースの`環境設定`メニューを開き、"メッセージ＆メディア"をクリックします。

<img width="963" alt="スクリーンショット 2019-12-19 20.07.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/8907d4bc-9921-d9e2-dc33-86f2582fb016.png">

この画面の下の方に、"転送先メールアドレスを取得する"のボタンがあります。

<img width="685" alt="スクリーンショット 2019-12-19 20.09.09.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/8742b2ff-fdbb-5c60-c0d8-f9d778be92b2.png">

これをクリックして`転送用メールアドレス`をゲットしましょう。

Slackでの作業は以上です！

## 2. Gmail での設定

あとは、特定のエイリアスアドレスでメールが届いた時に、Slackの`転送先アドレス`にメールが転送されるように設定するだけです。

### 2-1. 転送先アドレスの追加

Gmail の設定から"転送先アドレスの追加"を行います。

Gmail画面の設定メニューから"メール転送とPOP/IMAP"をクリックしてください。

![転送アドレス設定 - gmail com - Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/3293c9cf-046c-e18b-aecb-942cf6f0f1f2.png)

上記 "転送" の欄から "転送先アドレスを追加" をクリックして、先ほど取得したSlackの`転送先アドレス`を追加します。

わかりにくいですが、追加後のオプションでも `転送を無効にする` のままでOKです。
ここは全体の設定で転送はフィルタによって実行されます、ということなのでしょう。。。

### 2-2. フィルタの追加

それでは**特定エイリアスに届いたメール**にフィルターを設定します。

Gmail の設定画面から "フィルタとブロック中のアドレス"を開き、新規にフィルタを追加します。

![検索結果 - gmail com - Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/6a0ec92a-7bcb-d715-ddc0-a1130ae343e4.png)

で、`To`の欄に転送したいエイリアスのメールアドレスを入力します。ここで、Toに複数のメールアドレスを設定したい場合は、` | `(パイプ)もしくは` OR `で接続しないとダメ、というのがキモです。
` | `か` OR `でキーワードの"OR検索"になりますが、小文字の`or` ではうまくいきませんでした。。。
"続行"をクリックします。

![確認ダイアログ - gmail com - Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/8dc19482-e935-871a-7021-6329b33a4c16.png)

で、ORの代わりに`|`を使うと、確認ダイアログが表示されます。`|`は有効な演算子ですので気にせずOKです。

![アクション設定 - gmail com - Gmail.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/335150/f3ddbbcf-9d99-6dc2-4561-91841b74dd5e.png)

あとは転送の実行を指示するだけです。お好みで既読にしたり受信トレイをスキップしたり、タグをつけたり、やっちゃってください。

## 3. エイリアス付きのGmailアドレスで通知を送る

通知を出す方のアプリで、上記で設定したエイリアス付きの Gmail のアドレスに通知を送る設定を行ってください。

以上です〜！
年末まで毎日webサイトを作り続ける大学生 〜62日目 インベーダーゲーム 当たり判定の完成!〜

##はじめに
こんにちは！@70days_jsです。

55日目,61日目にインベーダーゲームを作ろうとしてできませんでした。
それが、ついに、今日！
一応完成しました！

とはいえ、ビームを出したら敵が消えて、敵が下まで到達するとゲームオーバーになるというシンプルゲームです。
バグ検証はしていないので、もしかしたら変な動作をするところがあるかもしれません。
あらかじめご了承ください。

62日目。(2019/12/19)
よろしくお願いします。

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

##やったこと
インベーダーゲームがついに完成しました。（gif)↓
![test3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/516248/54ef5cd4-3a4a-670a-ae74-7419cd50281c.gif)


コードは昨日の記事([年末まで毎日webサイトを作り続ける大学生 〜61日目 インベーダーゲームのリベンジ〜](https://qiita.com/70days_js/items/c41beb596a40fd631f54))とほぼ同じなので、変更点だけ書いていきます。

主な変更点は、当たり判定と、上まで行ったビームの削除、ゲームオーバーの機能です。

当たり判定↓

```javascript
//関数定義
function hit(beam, enemies) {
  for (var i = 0; enemies.length > i; i++) {
    let oneEnemy = enemies[i];
    if (
      (oneEnemy.x < beam.x &&
        oneEnemy.x + enemyWidth > beam.x &&
        oneEnemy.y + enemyHeight > beam.y) ||
      (oneEnemy.x > beam.x && oneEnemy.x < beam.x + oWidth)
    ) {
      enemies.splice(i, 1);
      return true;
    }
  }
}

//ここで使っています↓
 if (beams) {
    for (var i = 0; beams.length > i; i++) {
      let oneBeam = beams[i];
      oneBeam.render();
      let hitOrNoHit = hit(oneBeam, enemies);//ここでhit関数を使う
      if (hitOrNoHit) beams.splice(i, 1);
      if (oneBeam.y + oHeight < 0) beams.splice(i, 1);
      console.log(oneBeam.y);
    }
  }
```

hit関数はもしビームと敵が被ったらtrueを返すようになっているので、trueが返ったらビームを消すようにしています。
敵の削除はhit関数の中で行なっています。
今回オブジェクトは機体とビームと敵の三つ用意したんですが、当たり判定はどれにも属さないと思いメソッドではなく関数にしました。
ただ、今回作ったものは再利用性がないので改善しないとですね。

次に上まで行ったビームの削除ですが、昨日の段階でゲームをし続けるとものすごく重くなっていたのは、この上まで行ったビームを削除してないからだということがわかりました。↓

```javascript
 if (beams) {
    for (var i = 0; beams.length > i; i++) {
      let oneBeam = beams[i];
      oneBeam.render();
      let hitOrNoHit = hit(oneBeam, enemies);
      if (hitOrNoHit) beams.splice(i, 1);
      if (oneBeam.y + oHeight < 0) beams.splice(i, 1);//←上までいったビームの削除！
      console.log(oneBeam.y);
    }
  }
```

最後にゲームオーバーの機能です。↓

```javascript
    //ゲームオーバー
    if (enemy.y >= h - machineHeight) {
      clearInterval(enemyCreate);
      enemies.length = 0;
      beams.length = 0;
      alert("GAME OVER!!!");
    }
```

setInterval()で一秒ごとに敵を作り続けているのでまずそれをclearInterval()消して、↓

>let enemyCreate = setInterval(function() {
  let enemy = new Enemy(ctx);
  enemies.push(enemy);
}, 1000);

敵とビームを入れている配列のlengthを0にします。
今日初めて知ったのですが、配列はlengthを0にすると要素を空にしたのと同じことになるようです。
削除(splice)するか迷いましたが、あとでもう一回する機能をつけるときのことを考え、空にするだけにしました。
そして最後にアラートでGAME OVER!!!と出てゲーム終了です。

##感想
やー、55日目に失敗してから絶対インベーダーゲームは作りきると決めたので、できてよかったです。
作ると宣言してまだ作れてないものはあとオセロが残っていますね。
年末までに作れるようになんとか頑張ります。今年もあとちょっとだ！

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

##参考
[配列を空にするにはlength=0で十分。（配列とかおれおれAdvent Calendar2018 – 02日目） | Ginpen.com](https://ginpen.com/2018/12/02/use-length-0-to-clear-array/)

大変勉強になりました。ありがとうございます！
「スタートアップ×React LT大会 Coral Developers Night」に参加してきた

# はじめに
[スタートアップ×React LT大会 Coral Developers Night](https://coralcapital.connpass.com/event/156933/)に参加してきたのでそのことについてまとめます。タイトルの通り今回は**React**に関するLTを聴いてきました。

# 株式会社justInCase 「LT１」
アトミックデザインについての技術紹介でした。以下のツールを主に使っているそうです。

- [ant.design](https://ant.design/)
- [styled-components](https://www.styled-components.com/)

デザイナーとの連携もant.designの機能ベースで進めるとのこと。

# 水上 駿 / DIGGLE株式会社 「[Immutable JS](https://github.com/immutable-js/immutable-js)を使ったスケーラブルなReactアプリケーション開発」

オブジェクトの値が不変で扱うことのできるImmutable JSについての紹介をされました。Immutable JSはListという形を扱い、Setという重複のない集合を扱うことなどのことができるそうです。
オブジェクトが不変であることで誰かが破壊的な変更をするという事故もなくなるので、開発の余計な工数が減るというメリットがあるとのこと。

# 髙橋 耕太郎 / 株式会社Handii 「Reactの非同期処理のこれからを考える」

[redux-saga](https://github.com/redux-saga/redux-saga/blob/master/README_ja.md)の話でした。このsagaを使うことでComponentとタスクを分離して書くことができる。このsagaは公式のライブラリが充実している。しかしsagaは影響と副作用を一気に引き受けるので扱いが難しいという問題もあるとのこと。
また、今後は[hooksでの非同期処理](https://github.com/rehooks/awesome-react-hooks)も検討しているとのことでした。

# 森脇 和也 / 株式会社空 「スタートアップでReactを使うってどうなの？ 」

タイトルの通りReactをスタートアップの事業で用いたという話です。ここのLTで重要となったワードは[PMF](https://liginc.co.jp/437563)という言葉で、なにの課題を解決したいのかを第一に考えるのが大事とのこと。

# 株式会社justInCase 「LT２」

フロントエンドのデプロイの話と、Reactアプリの多言語化対応の話でした。多言語対応には[validator.js](https://www.npmjs.com/package/validator)と[react-intl](https://github.com/formatjs/react-intl)を用いて行ったとのこと。

# ゲストLT１「yarn upgaradeも怖くないテストをつくる」

ライブラリを常に最新の状態でも怖くないように、テストを継続的に行うという話でした。そのためにロジックとビューを分離させるようなコードの書き方をするなどの工夫を行っているとのこと。

# ゲストLT2「俺のお気に入りhooksランキング」

- useArray
- useDebouncedQuery
- useFetch系
- useInterSectionObserver
- useToast, Drawer, ModalができるuseContext

# さいごに
資料はおそらく後日イベントページに反映されるのでは？と思っています。
初心者によるプログラミング学習ログ 188日目

# 100日チャレンジ188日目

twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。

100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。

188日目は

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>188日目<br><br>udemyでwebサイトコーディング<br>同じく、bootstrapもちょっとやった<a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a> <a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1207389375312482304?ref_src=twsrc%5Etfw">December 18, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
【ExcelVBA】「変数が定義されていません」でコンパイルできない

# はじめに

これまでに幾つかの「コンパイルできない現象」を記事としてまとめてきましたが、今回新たなパターンを見つけたので記事としてまとめてみました。

* 「コンパイルできない現象」の例
 * [【ExcelVBA】DictionaryのItemにユーザー定義型を指定できない](https://qiita.com/nkojima/items/dad1a4b34ddeff2da59a)
 * [【ExcelVBA】「定数式が必要です」でコンパイルできない](https://qiita.com/nkojima/items/a64d0415a6a0224bf3fd)
 * [【ExcelVBA】「修飾子が不正です」でコンパイルできない](https://qiita.com/nkojima/items/b526bd18f7540fa8bcff)


# 現象

* 自作した関数（Function）をコピペして、その関数を若干修正した時に「変数が定義されていません」というエラーが発生しました。
 * コピー元の関数ではコンパイルエラーは発生しませんでした。
* 関数を定義した標準モジュールの先頭には`Option Explicit`ステートメントが書かれており、変数の宣言が強制された状態でした。
 * 関数のコード量は10行程度で、変数や定数は全て定義されていました。
* `Option Explicit`ステートメントを外すとコンパイルエラーは出なくなるものの、関数の結果が想定しているものとは異なるものになりました。
 * 以下のサンプルコードの場合、戻り値の型（Long）の変数の初期値である0が返されます。

![compile_error_vba.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312166/2789a5d9-211f-56ad-6821-97effa9469ef.png)

# 原因

* コンパイルエラーの原因は「**関数名（CalcTaxIncluded）と戻り値の変数名（CalcTaxInclude）が異なっている**」ことが原因でした。
 * コンパイルエラーのメッセージとは異なり、「変数が定義されていない」ことが原因ではありませんでした...

```vb:サンプルコード
Option Explicit

' 消費税率
Const TAX_RATE As Integer = 10

'--------------------------------------------------------------------------------
' 消費税の税込み価格を返す。
'
' taxExcluded：税抜き価格。
' return：消費税の税込み価格。
'--------------------------------------------------------------------------------
Function CalcTaxIncluded(taxExcluded As Long) As Long
    CalcTaxInclude = taxExcluded / 100 * (100 + TAX_RATE)    ' "CalcTaxIncluded"ではなく"CalcTaxInclude"になっている！
End Function
```

# まとめ

* VBAのコンパイルエラーのメッセージは、直接的な原因が分かりづらいケースが多くて困ります...
* 本来はシンタックスエラーになるべきなのに、`Option Explicit`ステートメントを外すとコンパイル出来てしまうのが恐ろしい...
 * おまけに中途半端に関数を実行できてしまうので、これが思わぬ副作用を生む可能性がありそうです。
* サブプロシージャや関数の粒度を小さく保つことで、コードの可読性を高めるだけでなく、今回のようなケースで原因を追求しやすくなる（＝保守性が高まる）ということを身をもって学びました。
 * この点については、JavaやC#など他の言語でも全く同じですね。
配列とハッシュ

# 配列とハッシュ
日々のRubyの学習で学んだことを備忘録としてつぶやいていきます。


## 配列

### 配列とは？
通常の変数を１つの箱と捉えれば、配列は、仕切りがある箱のようなもの。
配列を用いることで１つの変数で複数の値を管理することができる。
配列は、要素を**順番で管理**する。
◯番目といった順番を表す数字のことを**インデックス**と言う。

**インデックスは０番目から始めることに注意！！**




### 配列の書き方

```ary.rb
ary = ["10","20","30"]
# ３つの値を１つの変数に格納している
```



## ハッシュ


### ハッシュとは？
ハッシュも配列と同じで、複数の値を一括で管理したいときに使われる。
配列は、順番で管理していたことに対し、ハッシュは、名前で管理することができる。
ハッシュとは、**キー名: 値**の形式で値を取ってくることができる。


### ハッシュの書き方

```hash.rb
hash = {name: "reo", age: 20, country: "japan"}
# キー名: バリューの形式で値を格納している
```

## 配列のハッシュの知識を組み合わせたコード

```work.rb
students = [
  {name: "田中", Japanese: 85, Math: 62, English: 77},
  {name: "佐藤", Japanese: 90, Math: 40, English: 98},
  {name: "ボブ", Japanese:  2, Math: 50, English: 100}
]

students.each do |student|
  line = "--------------"
  puts line
  sum = student[:Japanese] + student[:Math] + student[:English]
  puts "解答者: #{student[:name]}さん
        国語:   #{student[:Japanese]}点
        数学:   #{student[:Math]}点
        英語:   #{student[:English]}点
        合計:   #{sum}点"
end
```



``` :ターミナル出力結果
-----------------
解答者：田中さん
国語：85点
数学：62点
英語：77点
合計：224点
-----------------
解答者：佐藤さん
国語：90点
数学：40点
英語：98点
合計：228点
-----------------
解答者：ボブさん
国語：2点
数学：50点
英語：100点
合計：152点
```
PythonとSQLiteで実現するローカルでお手軽SQL環境作成術

# はじめに
- ローカルにあるCSV(or TSV)ファイル、キー列でJOINしたり重複確認とかしたいなぁ...
- でも自由気ままに使えるDBなんてないし...
- そこまででかいデータでもないんだから、お手軽な方法ないかしら...

このようなことでお悩みのあなたへ、SQLiteというDBを使って、ローカルで簡単にDBを立ててデータをインポートしSQLを発行できる方法をご案内します。

**※テキストファイルをインポートする方法については以下の記事にてご紹介！**
[PythonでCSV,TSVファイルをSQLiteにインポートする方法](https://qiita.com/mu-tech/items/4deacbd844cda61fa9e6)

# SQLiteってなに？
![sqlite-183454_640.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/550851/ff378a8a-eec7-fc35-5ef5-790b2b515490.png)

- インストールも簡単で軽量なDBMS
- 組み込み系デバイスにも頻出。IoTと相性Good
- DjangoなどのWeb用DBとしても用いられることも
- PostgreSQLやMySQLといったメジャーなDBMSとは期待される役割が違う
- **Pythonに標準装備されている**

そう！このSQLiteはPythonをインストールした時点ですでに使えるのです。
というわけで、ここからはPythonを使ってローカルにお手軽DBを作ってSQLを打ち放題にする方法をご紹介します！
（以下はPython3.7がローカルにあることを前提とします。Python3系であれば使えるはず）

# 基本的な使い方
## 作成からアクセスまで
まずはDBの作成からアクセス、切断までの操作方法一覧。

```connect.py
import sqlite3

# 接続先となるDBの名前。'/home/user/database.db'といった表現方法も可能。
dbname = 'database.db'

# コネクタ作成。dbnameの名前を持つDBへ接続する。
conn = sqlite3.connect(dbname)
cur = conn.cursor()

# ここから好きなだけクエリを打つ
cur.execute('create table students(id integer, name text);')

# 処理をコミット
conn.commit()

# 接続を切断
conn.close()
```

DBにアクセスしたとき、もし指し先にDBファイルがなかった場合自動でDBが作成されます。

「DBが作成される」とはSQLite用のバイナリファイルが作成されるということを意味します。つまり接続先となるDBはただのファイルであり、接続先の表現方法はパスでそのファイルの位置を表現するということになります。

これはファイルをそのまま移動(mv)や複製(cp)すれば、どこでもデータを持ち運べるということでもあります。

拡張子は自由ですが、ここでは慣例で".db"を使っています。

## テーブル操作方法

```ctl1.py
# CREATE TABLE
cur.execute('create table students(id integer, name text, class text)')

# 列追加
cur.execute('alter table students add column blood_type text')

# 行追加
cur.execute("insert into students values(1, 'Mike', 'Moon', 'B')")

# 連続したレコードの追加
students_data = [(2, 'Bob', 'Song', 'A'),
                (3, 'Gonzalez', 'Star', None)]
cur.executemany("insert into students values (?, ?, ?, ?)", students_data)

# テーブル消去
cur.execute("drop table students")
```

executemanyメソッドは便利です。上のサンプルではタプルの入った一次元配列ですが、二次元配列でも同様にインサートできます。
（Python上での処理結果をそのまま流し込むのにも使えそう）


```ctl2.py
# 値の取得方法1
table = cur.execute('select * from students')
data = table.fetchall()
print(data)

# 値の取得方法2
for data in cur.execute('select * from students'):
    print(data)
```

テーブルのデータを取得したいときは、selectしたあとfetchall()をします。イテレータとしても使えます。

取り出した値はタプルあるいはタプルを要素とした配列になっています。



# CSV,TSVファイルをインポートする方法
以下をご覧ください！
[PythonでCSV,TSVファイルをSQLiteにインポートする方法](https://qiita.com/mu-tech/items/4deacbd844cda61fa9e6)


おしまい。

# 参考文献
- [SQLite 公式Webサイト](https://www.sqlite.org/index.html)
- [SQLite データベースに対する DB-API 2.0 インタフェース(=Python側の公式ドキュメント)](https://docs.python.org/ja/3/library/sqlite3.html)
- [SQLite が認識できる SQL(=SQLiteの位置付けについての記事)](https://prev.net-newbie.com/sqlite/lang.html)
- [SQLiteの適切な使い方(=SQLiteのより詳細な仕様)](https://sites.google.com/site/kandamotohiro/sqlite/sqlitewhentouse)
- [PythonでCSV,TSVファイルをSQLiteにインポートする方法](https://qiita.com/mu-tech/items/4deacbd844cda61fa9e6)
jqueryでDOM操作

#要素の取得

通常のjsだと

```
document.getElementById('id');
document.querySelector('要素名');
```

取得するものがidなのかクラスなのか、要素なのか、属性なのかで文が変わってくるが、jqueryなら

```
$('#id');
$('.class');
$('要素');
$('要素[属性= "値"]');
```

のように短くシンプルな記述で取得できる。

他の記述も短く書けて

```
#javascript
btn = document.getElementById('btn');
btn.classList.add('red');

#jquery
$('#btn').addClass('red');
```

のように短く記述できる。

またプロパティやバリューの値の取得もでき、

```
$('form').prop('checked');
#チェックボックスのチェックが入ったらつくプロパティ

$('form').attr('value');
#value="値"の値をとる
```

他には

```
$('form').on('submit',function(e){処理内容});
```

でformの送信ボタンが押されたら処理を行う。みたいなのも簡単にかける。
コーディングガイドラインとQC

今後の制作においての基盤を作りたい。やりたいことをまとめたい。そんなメモ。

#ガイドライン

##CSS
CSSのコーディング記法をBEMに統一。
既にファイル構成はflocssにしているが、命名規則までは上手く統一できていない。
再利用性が高い作りをしているわけでもないので、今後のためにもFLOCSS+BEMという作りで制作を行いたい。


■参考記事
・CSS設計を勉強するならまずこれを見たら良いかも
https://qiita.com/sueshin/items/c80151181d06649e2ff6

・一番詳しいCSS設計規則BEMのマニュアル
https://qiita.com/Takuan_Oishii/items/0f0d2c5dc33a9b2d9cb1


・脱・CSS無法地帯。FLOCSSで指針のある設計を。
https://qiita.com/sueshin/items/dcbaf3d8a0adb6b087db


##画像命名規則
作業者によってばらつきが出る。
ある程度規則は決めているが、中々統一しにくい。

■参考記事
・画像ファイルの命名規則
https://qiita.com/okamoai/items/82eff25436fbbafaa063

・よく使っている画像の命名規則
https://qiita.com/manabuyasuda/items/675586be79c4a8eebbfc



#QC
ブラウザチェック、実機検証などレビュー時やリリース前に第三者の確認をはさみたい。
あまりに小規模なものは必要ないかもしれないが、凡ミスを防ぎたい。凡ミスを防ぎたい。

##チェックシート
今後の新人教育のためにも、ある程度何に気をつけるべきかをまとめておきたい。
凡ミスを防ぐ手立てをあまり考えられてないので、
・環境構築
・ページ作成前
・ページ作成後
の3つに分けてチェックシートを作りたいと思う

■参考記事
Webコーディング後にチェック（テスト）しておくべき20のチェックポイント！
https://haniwaman.com/coding-test/

Webサイトの品質をアップさせる99のチェック項目
https://baigie.me/sogitani/2012/06/99chec/

Webサイト品質管理のチェック項目リスト
https://webtan.impress.co.jp/e/2010/04/23/7317



##分報・気づきシート

「分報」なるものがある。文字通り分単位で報告を行うという意味だが、
リアルタイムで状況や問題を書くことによって、課題解決がスムーズに行われるらしい。
そういうのもやりたい。
リアルタイムではなくても、気づきシートみたいなものに逐一技術的な何かしらを描いて欲しい。
・トラブルシューティング
・このプラグインいいよ
・このライブラリ使ってみたい
・こんな問題起きたんすけどどうしたらいいすか
etc...
早いスパンで共有を行えるようにしたい。技術共有があまり上手くいっていないので。

■参考記事
Slackで「分報」を導入したらめっちゃ作業効率があがった
https://note.com/reoleo/n/n102308f5b4e3


技術的なものに捉われがちだが、こういったルール策定やリスクヘッジ的なものが疎かになりがちなので、2020年はもっとしっかりここら辺を固めていきたい。
とりあえずつかってみようぜDockerを

# はじめに

[いなたつアドカレ](https://qiita.com/advent-calendar/2019/allinatatsu)の十九日目の記事です。

もうあと1週間を切りましたね。。。

ネタも切れてますが。。。。

先日Dockerの簡単な導入をハンズオンで開催したので、その資料を供養しようかと、、、

# 雰囲気ですら理解せずに使ってみる
コンテナとか仮想でうんたらとかとりあえずおいといて使ってみようよの会ですね。


## dockerの愉快なコマンドたち
- docker run 
    - コンテナを引っ張ってきて起動するコマンド
- docker exec
    - コンテナ内でコマンドを実行するコマンド
- docker ps
    - コンテナの起動状況を確認するコマンド
- docker stop
    - コンテナを止めるコマンド(ころころする)
- docker rm
    - コンテナを削除するコマンド(成仏してクレメンス)
- docker start
    - コンテナを蘇生するコマンド(ザオリク？ドラクエしらねぇ)

`$ docker stop [CONTAINER_NAME]`でコンテナさんの命を断ちます、しかし、この世界は蘇生ができる世界なので成仏するまでは復活する可能性があります。
しかし`$ docker rm [CONTAINER_NAME]`でお亡くなりになっているコンテナさんに成仏していただくことができます。
そして、お亡くなりになっているコンテナに`$ docker start [CONTAINER_NAME]`をすることで、蘇生できます。

### docker run　のオプション
- iオプション -i
    - ホスト -> コンテナ の入出力をつなげる
- tオプション -t
    - コンテナ -> ホスト の入出力をつなげる
- dオプション -d
    - バックグラウンド実行
- vオプション -v
    - ファイルを共有する
- pオプション -p
    - ポートをつなげる
- wオプション -w
    - 作業ディレクトリを指定する
- nameオプション --name
    - コンテナに名前をつける
- rmオプション --rm
    - コンテナをstopしたら自動でrmする

**オプションitdはハッピーセット**

### docker run の実際の例
```
$ docker run -itd --name python -v $(PWD):/py -p 8000:8000 -w="/py" python

$ docker run -itd --name [CONTAINER NAME] -v $(PWD):[CONTAINER DIRCTORY] -p [LOCAL PORT]:[CONTAINER PORT] -w="[CONTAINER DIRCTORY]" [IMAGE NAME]
```

$(PWD) はローカルのカレントディレクトリを展開(pwdコマンドの実行)

## docker-compose
docker-compose.ymlにコンテナの概要を記述し、Dockerファイルを用いてコンテナの詳細を定義する。
とりあえず触ってみようか

### こまんど

- docker-compose run CONTAINER_NAME COMMAND
    - 指定したコンテナでコマンドを実行する (up より前に)
- docker-compose up
    - コンテナを全て起動する、ログ一生吐き続けるので -d をつけよう
- docker-compose exec CONTAINER_NAME COMMAND
    - 指定したコンテナでコマンドを実行する (up より後に)
- docker-compose down
    - docker-composeで管理している全てのコンテナに対してstopとrmをする
- docker-compose ps 
    - コンテナの状態の確認
- docker-compose logs CONTAINER_NAME
    - 指定コンテナのログをみる


### つかう

- docker-compose up -d
- docker-compose ps
- docker-compose exec nginx bash
- docker-compose down

# おまけ

便利なやつ

- docker stop \$(docker ps -a -q) && docker rm \$(docker ps -a -q)
    - 全てのコンテナを亡きものにする、ころころして成仏していただく
デザインパターンについて

デザインパターン概要
基本原則：
❶変わるものを変わらないものから分離
❷プログラムはインターフェイスに対して行う
❸継承より集約
❹委譲、委譲、委譲
❺必要になるまで作るな（YAGNI）

その後の変更や追加、修正が容易、安全、迅速に行えるように設計すること。

●TemplateMethodパターン
変わるものを、変わらないものから分離するため、
抽象基底クラスを抽出し、基底クラスのメソッドを、サブクラスでオーバーライドさせる方法。
動作は同じだが、種類が違うものに応用できる。abcモジュールで実装可能。
例：種類の違うファイルの出力形式を合わせる。
デメリット：サブクラスが基底クラスに依存してしまう。
↓
●Strategyパターン
strategy(変化する部分、行動、アルゴリズム)を関数として抽出し、基底クラスから呼び出すという形。
TemplateMethodパターンでは種類を分離したが、strategyでは種類と行動を分離する。
これにより、承継による依存度が薄くなる。

●Observerパターン
何かが変更になった際に、オブザーバーに通知する際のデザイン。
変更になった時だけでなく、変更が間違っていた時には通知しない実装も必要。
例：FXでティックが変更になった際に、チャートが更新される仕組み。

●Compositeパターン
複合物、容器と中身を同一視するパターン。
例：ファイル管理
ファイルやディレクトリは同じ、削除メソッドを持っている。
削除メソッド抽出して、新しくシンボリックリンクを追加できるようにする。

●Iteratorパターン
Pythonで言うところのリスト。イテレータ。リスト状に格納して、順番に取り出すことができる。

●Commandパターン
ボタンとボタンが押された時の動作を分離させる。

●Adapterパターン
継承と委譲の２パターンがあり、二つのクラスやインターフェイスの間に入って、二つの機能をつなぐ。

●Proxyパターン
本体とは別に、本体と同じ機能を備えたクラスを作成する。

●Decoratorパターン
アイスクリームのトッピングのように何重にも動作を付け加えていく。

●Singletonパターン
唯一のインスタンスになるデザイン。

●FactoryMethodパターン
Creatorと呼ばれる実行クラスと、concrete creatorと呼ばれる種類を変えるクラスでできている。
Creatorクラスを、concreatorクラスに承継させることで、種類の違う動作をさせる点は、
templatemethodパターンの一種である。
また、承継させるだけでなく、引数としてクラスを呼び出すことで、さらに対応範囲が広がる。
↓
●AbustructFactoryパターン
Factorymethodパターンから、動作の部分を分離させ、種類ごとにクラスわけすることで、
メインクラスから、各種類のクラスを呼び出せるようにした。
Strategyパターンの一種。

●Builderパターン
作業工程をクラスや多くの引数を使って、一気に動作させるのではなく、
クラス内に分離したメソッドに分けて、一つ一つ指示しながら、完成させていくパターン
例：部品が多いオーダーメイドなPCの組み立てなど

●Interpriterパターン
抽象構文木を使うパターン。行動と要素を分類して、順次実行していく。

●Prototypeパターン
型を作って、同じものを量産していく。

●Bridgeパターン
同じ機能を必要としているクラスに対して、機能を重複して足すのではなく、
機能と実装を分離させる。

●Visitorパターン
処理をオブジェクトに任せて、そのオブジェクトを呼び出す。

●Chain of Responsibilityパターン
処理できるものに処理を任せるパターン

●Facadeパターン
多くのクラスが作られる大規模アプリケーションなどで、それらのクラスを統制するクラスを
玄関として作り、そこから各クラスを操作するパターン。

●Mediatorパターン
多くのオブジェクトが複雑に関係している場合に、間に入って、上手いことするやつ。

●Mementoパターン
処理手順のある段階の状態（インスタンス）を記録しておき、
そこに戻ったり、そこから次の処理を開始したりする。

●Stateパターン
状態によって、振る舞いが変化するクラス。
ifを使った場合わけではなく、場合わけをクラスによって行う。

●Flyweightパターン
以前実行して取得したインスタンスを使い回す。
MySQL - の付いたデータベースの削除　

今更ながら、データベースの整理をしていて - の付いたデータベースを削除する際にあれ？となったので。。。


```ターミナル.
#mysql にログインします。rootの部分はユーザー名
$ mysql -u root




#データベースの確認
mysql> show databases;

+-----------------------------------+
| Database                          |
+-----------------------------------+
| information_schema                |
| mysql_development                 |
| mysql_test                        |
| mysql-app_development             |
| mysql-app_test                    |
+-----------------------------------+





#通常の削除
mysql> drop database mysql_development;

実行結果
=> Query OK, 0 rows affected (0.00 sec)





# - の付いたデータベースの場合は
mysql> drop database mysql-app_development;

実行結果
=> ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '-app_test' at line 1

エラーになってしまう。。。。






#　- の付いたデータベースを削除する際は ` (バッククオートで囲う)

 `  は　shift+@　で入力

mysql> drop database `mysql-app_development`;

実行結果
=> Query OK, 0 rows affected (0.00 sec)



```
Pythonは楽ですわ

#Pythonその４アドベントカレンダー1９日目投稿致します。昨日は薬の副作用で書けませんでした。申し訳ございません。
##Pythonを初心者に勧めるわけ
なぜなら簡単にプログラムが書けるからです。
最初からJavaやC＃だとクラスの概念から教えることになるので一番大変です。
自分も実は23の頃クラスが書けなくて悩んだ時期がありました。
今では難なくかけるのにねｗｗｗ。
##初心者はなぜブロック言語に頼るのか
それは正直言うとコードに違和感があるからです。
自分たちは正直一番最初がCOBOLだっただけにコードが怖かったら正直何もできませんでした。
実際自分は一回落ちこぼれになりました。
それからですね書くことが重要だと思うようになったのは。
ブロックプログラミングは比較的楽にかけますが。
壊れてしまったときに何も対応できません。
Micro::Pythonを教えたいという方には必ず伝えることがあります。
<strong>必ずPython本一冊は写経しろ!!</Strong>
それはなぜかと言うとソースが壊れたときに直せるからです。
自分もMashupAwardでPepper賞頂いた経験があるのですが実はPython書けませんでした。
Choregrapheって実はPythonのブロックプログラミングをソフトなんですわ。
相方にPythonianがいたので直してもらいました。
ここで最初にPythonに触れたわけです。
今ではサクッと書いちゃう人間になったわけですが。
##サクッとかけると何がいいのか
実はサクッとかけると実は色んなことが自動化できます。
Excelに自動的に物を書いてみたり自動的にニュースを取得したり緊急情報の取得をするのに役に立ちます。
実は今回のアーバンデータチャレンジのアイデア部門で出すものですが実際にアプリ化する予定です。
自動取得の部分にはPython使うと決めてます。
他の言語だとめんどいからじゃないです。
一番使いやすいから。
C#も好きなんだけどPythonもjQuery・RIOT・ECMAScript・PHPもねって感じですね。
Pythonでプログラミングして解雇された人の話を見ましたが正直言っとくとやって正解なんです。
<strong>だけどおおっぴらにしちゃだめ。自分だけにとどめときましょう。会社に腹は立つでしょうけど所詮我々は1サラリーマンでしかないんだから。</strong>
とかいておきます。
今だったら一般職に言っただバリバリ書いてだんまりで提供しちゃうでしょうけど。
俺は一般職にはもう戻りませんよ。
お金にならないもん。
技術あってなんぼですから。

そういえば隠れPythonプログラマに言いたい来年こそはハッカソンに来てほしい。
特に<strong>田村淳さん隠れてないで来年の中京テレビハッカソンに来てください。</strong>
実は大ぴらにもうWebで書いちゃったんだから正直ハッカソンに来てよと言いたいです。
ほんま隠れPythonian本当に多いので一回ハッカソンに出ると人生変わるかもよ。
と書いておきます。

では。
脱jQuery化を試みて失敗した話

各種ブラウザで使えるJavascriptが統一されてきたこともあり、ここらで自分が管理しているサイトからjQueryを除いてみようと思い試行錯誤をしていたが、結局諦めた。
これから同じような事をする人の参考になればと思い軽く情報共有しようと思う。

# 書き換え可能なもの

DOMの生成完了

```js
//jquery
 $(document).ready(() => {})
//native
 document.addEventListener("DOMContentLoaded", () => {});
```

セレクタ(単数/複数)

```js
//jquery
$('.className').each((index, elem) => {
//native
document.querySelector('.className')
document.querySelectorAll('.selected input').forEach((el, index) => {
```

属性情報の追加/取得

```js
//jquery
$(elem).attr('attribute','value');
$(elem).attr('attribute');
//native
elem.setAttribute('attribute','value');
elem.getAttribute('attribute');
```

親要素のクラスを追加/除去
classListで要素に付与されているクラスのリストが取得可能

```js
//jquery
$(elem).parent().addClass("className");
$(elem).parent().removeClass("className");
//native
elem.parentElement.classList.add('className');
elem.parentElement.classList.remove('className')
```

イベントリスナ

```js
//jquery
$('hoge').click(() => {});
//native
document.querySelector('hoge').addEventListener('click', () => {}); //クラスが一つ
document.querySelectorAll('hoge').forEach((elem) => { //クラスが複数
  elem.addEventListener('click', () => {});
});
```
domが単数の場合と複数の場合を意識してコードを書かないといけないため結構面倒くさい。

# 困難なもの

・あるポジションまでAnimationで移動したい時

```js
//jquery
const position = $("#id").offset().top;
$('html').animate({ scrollTop: position }, 'fast');
//native
const position = document.querySelector('#id').offsetTop;
window.scrollTo({
  top: position,
  behavior: "smooth"
});
```

一応アニメーションでのスクロール自体は実現することができるが、behaviorがsmoothかinstantぐらいの指定しかないため、気持ちの良いアニメーションを実現する事ができない。かといって自前でscroll書くのは結構大変で上手く書かないとコードも汚れる。

・script付きのhtmlを埋め込み実行

```js
const html = '<div>...</div><script>...(some_js_execution)</script>'
//jquery
$('#id').html(html); // Scriptが実行される
//native
$('#id').innerHTML = html; // Scriptが実行されない
```

innerHTMLでは内部にscriptタグがある場合実行できない。ソーシャルボタンを設置する場合は大抵scriptタグがコピーされるソースの中に埋め込まれているので、動的な埋め込みが困難となる。jQueryではcreateElementをしてHTMLのDOMを生成してScriptタグを埋め込むという内部操作でScriptの実行を行っていたが、それを自前で書くのは面倒である。

## まとめ
DOMの操作自体は比較的簡単に書けるが、複数DOMの操作は煩雑であった。また細かいAnimation制御ができなかったり、htmlとinnerHTMLなどのように微妙な違いが存在するものもあるので手軽に脱jQueryという訳には行かない事が分かった。

結局まだjqueryが役立つシーンは多いと思われる。Webサイト/Webアプリケーションのjavascriptの使用具合により
native javascriptのみ -> zepto + javascript -> jquery + javascript -> vue.js, react -> react + redux
ぐらいな感じで使い分けていくのが現状のベストプラクティスかなと個人的には思う。
Ubuntu 16.04 に サポートされていない古いJDKを入れる プロキシ環境対応

# 目的

- Ubuntu16.04には現在JDK8かJDK9の二つがサポートされているが、古いバージョンのJDKをプロキシ環境下で入れる方法をまとめる
- 今回は例としてJDK7を導入する。

# 実施概要

1. PPAリポジトリよりJDK7用のリストを取得
1. インストール可能なパッケージの一覧を取得
1. JDK7の本体を取得
1. JDKのバージョン切り替え

# 実施詳細
1. 環境変数にプロキシアドレスを入力
    1. 下記コマンドを実行して環境変数にプロキシのアドレスを入力する。

        ```terminal
        $ export http_proxy="プロキシアドレス"
        $ export https_proxy="プロキシアドレス"
        ```

1. PPAリポジトリよりJDK7用のリストを取得
    1. 下記コマンドを実行してJDK7をインストールするリストを取得する。(オプション`-E`を付けることにより環境変数に格納した値を使用して実行することが可能になる)

        ```terminal
        $ sudo -E add-apt-repository ppa:openjdk-r/ppa
        ・
        ・
        ・
        >Reading package lists... Done
        ```

1. インストール可能なパッケージの一覧を取得
    1. 下記コマンドを実行してインストール可能パッケージ一覧を取得する。
    
        ```terminal
        $ sudo apt-get update
        ・
        ・
        ・
        >Reading package lists... Done
        ```

1. JDK7の本体を取得

    ```terminal
    $ sudo apt-get install openjdk-7-jdk
    ```

1. バージョンの切り替え
    1. 複数のJDKバージョンをインストールしているときはJDKのバージョン切り替えを行う(下記の出力があったら、チェンジしたいJDKのバージョンの行の最初に記載されている数字を入力してEnter、今回はJDK7にしたいため1を入力後Enter)

        ```terminal
        $ sudo update-alternatives --config java
        >There are 2 choices for the alternative java (providing /usr/bin/java).
        >Selection    Path                                            Priority   Status
        >------------------------------------------------------------
        >* 0            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      auto mode
        >1            /usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java   1071      manual mode
        >2            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java   1081      manual mode
        >Press <enter> to keep the current choice[*], or type selection number: 
        ```

1. バージョンの確認
    1. 下記コマンドを実行してJDKのバージョンを確認する。(下記の様になっていればOK)

        ```terminal
        $ java -version
        >java version "1.7.0_95"
        >OpenJDK Runtime Environment (IcedTea 2.6.4) (7u95-2.6.4-3)
        >OpenJDK 64-Bit Server VM (build 24.95-b01, mixed mode)
        ```
phpのenctype= multipart/form-data での文字化け

画像を載せるのに
formにenctype= multipart/form-dataを追加したところ
他の文字が文字化けしてしまいます。
print_r(mb_get_info());で確認したところ

```
Array ( 
[internal_encoding] => UTF-8 
[http_output] => UTF-8
[http_output_conv_mimetypes] => ^(text/|application/xhtml\+xml) 
[func_overload] => 0 
[func_overload_list] => no overload 
[mail_charset] => ISO-2022-JP
 [mail_header_encoding] => BASE64 
[mail_body_encoding] => 7bit 
[illegal_chars] => 0 
[encoding_translation] => On 
[language] => Japanese 
[detect_order] => 
Array ( 
[0] => ASCII 
[1] => JIS 
[2] => UTF-8
[3] => EUC-JP 
[4] => SJIS ) 
[substitute_character] => 63 [strict_detection] => Off )
```

で問題なさそうです。encoding_translationをOffなどにしても直りませんでした。
mb_convert_encoding($_POST["name"], "UTF-8", "HTML-ENTITIES")
やASCIIからの変換を試して見ても直りませんでした。
どうやったら解決できそうですかね。

解決しました。
なぜか、ISO-8859-1 文字列になっていたみたいで、utf8_decode()を使い、utf8への変換が出来ました。
wslでubuntu その２

#概要

wslでubuntuやってみた。

#gccをインストール

```
sudo apt install build-essential
```


#サンプルコード

gcc -no-pie fizzbuzz.S

```
.code32
.text
.global main

main:
    mov     $1, %esi
loop:
    mov     %esi, %eax
    mov     $15, %ebx
    div     %bl
    cmp     $0, %ah
    jz      loop15
    mov     %esi, %eax
    mov     $5, %ebx
    div     %bl
    cmp     $0, %ah
    jz      loop5
    mov     %esi, %eax
    mov     $3, %ebx
    div     %bl
    cmp     $0, %ah
    jz      loop3
    mov     $fmt, %edi
loop2:  
    mov     $0, %eax
    push    %esi
    call    printf
    pop     %esi
loop1:
    add     $1, %esi
    cmp     $101, %esi
    jnz     loop
    ret

loop15:
    mov     $fizzbuzz, %edi
    jmp     loop2
loop5:
    mov     $buzz, %edi
    jmp     loop2
loop3:
    mov     $fizz, %edi
    jmp     loop2

.data
fmt:
    .asciz  "%d "
num:
    .asciz  "%i "
fizz:
    .asciz  "Fizz "
buzz:
    .asciz  "Buzz "
fizzbuzz:
    .asciz  "FizzBuzz " 
```


以上。
goでブラウザ上で動くターミナルエミュレータを作った話



# 作ったもの

ブラウザ上で動くターミナルエミュレータを作りました。

![shell-server.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/124378/67315f4e-980b-ccfa-cf3e-e17261a0161d.gif)


# 構成

サーバーサイドはgoで実装し、クライアントサイドはtypescriptで実装しました。
入出力はwebsocketでやり取りします。

# 実装の概要

## ptyを作成してbashと接続する。

ターミナルエミュレーターが端末上で動くプログラムと入出力をやり取りする場合には、pty(仮想端末)と言われるものを使います。[^1]
ptyはopenpty()関数を使うことによって作成します。
goにはopenptyに対応する関数は見つからなかったので、cgoを使って呼び出します。
openptyを呼ぶと、amasterとaslaveという２つの値が得られるので、
aslaveの方を端末上で動くプログラムの標準入出力に割り当て、amasterの方にブラウザから受け取った入力を入れます。

```golang

var amaster C.int
var aslave C.int
if errno := C.openpty((*C.int)(unsafe.Pointer(&amaster)), (*C.int)(unsafe.Pointer(&aslave)), nil, nil, nil); errno != 0 {
	panic(fmt.Sprintf("errorno: %d\n", errno))
}
sysattr := syscall.SysProcAttr{Setsid: true}
attr := syscall.ProcAttr{
	Files: []uintptr{uintptr(aslave), uintptr(aslave), uintptr(aslave)},
	Env:   []string{"TERM=vt100"},
	Sys:   &sysattr,
}
pid, err := syscall.ForkExec("/usr/bin/bash", []string{}, &attr)
if err != nil {
	panic(err)
}
```

この状態でamasterの方に書き込めば、シェルに値が送られ、
またシェルの結果をamasterから読み込むことができます。

amasterへ読み書きするにはos.NewFileをつかって行えます

```golang
file := os.NewFile(uintptr(amaster), "ptymaster")
file.Write([]byte("ls"))
```

## 各種キーをシェルに送る

各種キーでアルファベットなどはそのまま対応するASCIIコードをamasterに入力してやればいいです。
ブラウザ側で
Backspaceキーが押されたときはBS(0x08)、
Enterキーが押されたときはCR(0x13)をおくればよいです。


## Crtlキーに対応する
Ctrl+なにかのキーの場合は該当するASCIIコードから0x40を引いた値を送ってやります。
（例：Ctrl+Cだと0x03になる）
実際にシグナルを送る部分はptyがいい感じにやってくれてるらしく、これを実装するだけでCtrl+Cを押すと現在実行中のプログラムが終了するようになります。

## 特殊文字とエスケープシーケンスを扱う

ただこれだけだと、ただ文字は追記されるだけで、BSで文字を削除することすらできません。
既に入力した文字を削除する場合、別の場所に文字を表示したい場合などは、特別な文字が送られてくるのでクライアント側でうまく扱ってやる必要があります。

とりあえず以下の特殊文字を実装するとそれっぽくなります。

- CR(0x13) カーソルを行頭に戻します
- LF(0x10) カーソルを次の行に移動します
- BS(0x08) カーソルを一文字分左に移動します

とりあえずここまで実装すればタブ補完上下キーによる履歴表示あたりは動くはずです。

もう少し凝ったものを動かしたい場合、エスケープシーケンスを実装する必要があります。
エスケープシーケンスとは、複数の文字の組み合わせで端末を制御するものです。
筆者は以下のサイトを参考にいい感じに実装しました。

http://bkclass.web.fc2.com/doc_vt100.html
https://www.vt100.net/docs/vt510-rm/chapter4.html
https://en.wikipedia.org/wiki/ANSI_escape_code

# 終わりに

コードは公開してあるので興味ある方はどうぞ。
https://github.com/sdkawata/shell-server
（セキュリティ的な安全確認はしてないので、グローバルからアクセスできない場所で動かしてください）



[^1]: ptyとは何かというと説明が難しい（というか筆者もよくわかってない）ですが、色々と機能のついたパイプのようなものと思っておくのがいいと思います。具体的にどんな機能がついているかについては　https://qiita.com/angel_p_57/items/ff1c0d054714b7982ca50 が参考になります。
Makeを研究に使う

## TL;DR

- 機械学習の研究をするときに`make`を使うと再現性が担保出来て便利
- `make`は各ファイル依存関係との作り方を指定すると自動で欲しいファイルを作ってくれるので、「このファイルどうやって作ったんだっけ？」ってならない
- `make`に詳しい人のアドバイスがほしいです！


## 背景

機械学習を使った研究では、元データ（公開されてるデータセットなど）、前処理したデータ、生成物など様々なファイルを扱います。そして、研究が進むにつれ、不必要なファイルや、生成方法が変わったファイルなどが生まれてきます。これらのファイルが、いつどの様に生成されたものかを管理しないと、実験の再現性がなくなり、論文を執筆する際に非常に困ります（数回やりました）。

そこで最近、`make`を使って実験を行うことで最大限の再現性を確保する様にしてます。今回は、研究に`make`を使う際の注意点やコツなどをまとめていきます。

**同時に、普段`make`を使っている方々からアドバイスがほしいです！**

## Makeの仕組み

`make`を使うにはそのディレクトリに`Makefile`という名前のファイルがおいておきます。その中には生成したいファイル（`target`）、依存ファイル（`prereq`）と、その生成方法をまとめて書きます。すると、欲しいファイルを指定すると自動的にその依存関係を解消し指定したファイルを作成してくれます。

#### シンプルな例

```Makefile:Makefile
fogefoge.txt:
    echo "Hello World" > $@

hugahuga.txt: fogefoge.txt
    cat $< | tr '[A-Z]' '[a-z]' > $@
```

ここで、`fogefoge.txt`は`hugahuga.txt`（`target`）の`prereq`になっています（`$@`と`$<`はそれぞれ`target`と`prereq`に置換されます）。
おなじdirectory内で

```shell
$ make fugafuga.txt
```
とすれば、自動的に`hugahuga.txt`が作成されます。

#### 自然言語処理の例
生コーパスをtokenizeして全てlower caseにしたあと、そのコーパス上でfasttextを学習する場合を考えます。
`data/input/rawcorpus.txt`に生コーパスが置かれているとします。

`Makefile`を

```Makefile:Makefile
data/output/preprocessed.txt: data/input/rawcorpus.txt
    mkdir -p $$(dirname $@)
    cat $<| mecab -Owakati| tr '[A-Z]' '[a-z]' > $@

data/output/fasttext.bin: data/output/preprocessed.txt
    fasttext skipgram -input $< -output $@
```
とすれば

```
$ make data/output/fasttext.bin
```
と実行するだけで、データの前処理から分散表現の学習まで自動でやってくれます。
後で、前処理ってどうやってたっけ？と思っても`Makefile`を見返せば明白です。

実際の研究ではさらに様々なファイルを扱うので、それら全ての生成方法を覚えておくのはほぼ不可能になると思います。そういったときに強力なツールです。

## 良かった点

####  各ファイルの意味を覚えておく必要がなくなった

2日前に書いたコードは他人が書いたコードと同じくらい読めなくなる記憶力の持ち主なので、研究が進むに連れて膨大に増えていくファイルの生成経緯を覚えておく必要がなくなったのは大きかったです。

#### この実験再現するのかな？と不安にならずに実験できる（精神的な安定）

これまでに実験が再現せず困ったことがあるので、これはすごく大きかったです。ただし、`make`を使っておけば再現性が完全に確保されるわけではなく、環境（バージョン）やランダム初期値の差なども考慮する必要があります。

#### Linuxのコマンドに慣れた

`make`ではlinuxのコマンドでのファイルの生成方法を記述するので、自然とlinuxコマンドを書く機会が増えました。これまではpythonのスクリプトを書いていた処理も、linuxコマンドに置換され、全体的に見やすくなりました。

## 悪かった（不満な）点

#### `Makefile`のシンタックスが気持ち悪すぎる

ゾットするくらい気持ち悪いので、`make`と似た機能のシンタックスがまともなツールがあったら教えてほしいです（懇願）。

#### 複数のワイルドカードが使えない

少しずつ設定を変えて実験を行うときに、`make`の`target`と`prereq`の記述にワイルドカードが使えると便利です。しかし、`make`では複数のワイルドカードが許されないのでループなどを使って書いています。

## まだどうしたらいいかわからない点

#### どこまでmakeで書くか？ 

研究をすすめる上で、どこまでの処理を`make`で管理するかが悩みです。論文に挿入するtexのテーブル生成まで`Makefile`内に書く人もいるようですが、表の形は論文全体の体裁を整えるために提出直前まで変更することが多いので、`Makefile`を書き換えている暇はない気もします。（計画的に論文執筆ができれば大丈夫？）

## まとめ

「研究に`make`を使うと良いよ」という記事を書こうと思ったら、「`make`の使い方教えて下さい！」という記事になってしまいました。
`make`の使い方教えて下さい。