OmniAICreator/Qiita-1.07M huggingface dataset:
EC2にSSH接続できない問題を復旧

# 初めまして
いつもお世話になってるQiitaの皆様、色々な情報をご掲載いただきありがとうございます。
今回Qiitaに初めて投稿させていただきます。
どうぞよろしくお願いいたします。

# 障害内容
開発用の AWS EC2インスタンスにSSH接続できない

# 発生原因
先日メンテナンス時に /etc/passwd 内の一部ユーザに設定されている
ホームディレクトリ位置を変更した事がわかりました。

ディレクトリ位置変更でSSH接続に使用する秘密鍵の参照位置が変わり
鍵ファイルを見つけることができず認証が失敗しておりました。

# 復旧対応
指定ユーザのホームディレクトリ位置をメンテナンス前の状態に戻すように対応。

# 復旧の流れ
1. 復旧用のインスタンスを新規作成
2. 障害インスタンスの停止、ボリュームのデタッチ
3. 復旧インスタンスに上記ボリュームをアタッチ
4. 復旧インスタンスの起動、ログイン
5. 復旧インスタンスにマウント
6. 復旧インスタンスで修正作業
7. 復旧インスタンスからアンマウント
8. 復旧インスタンスの停止、ボリュームのデタッチ
9. 障害インスタンスに修正したボリュームをアタッチ
10. 再起動

# 復旧作業 (詳細)
### 1. 復旧用のインスタンスを新規作成
AWS EC2のコンソールからインスタンスを1点新規作成します。
障害インスタンスのOSはAmazon Linux 2のため同じOSを設定しました。
また、インスタンスの種類やストレージ容量は t2.nano 8GB にしています。

### 2. 障害インスタンスの停止、ボリュームのデタッチ
インスタンスを停止させてEC2 ボリュームのコンソールに移動します。
対象のボリュームに掲載されているアタッチ済み情報のインスタンスIDと障害インスタンスのIDが一致していることを確認します。

:exclamation:**(重要)このとき「ボリュームID」と「アタッチのパス」をメモ等に記録して下さい。 　**
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72175/5f213aab-de74-bcd5-0ce2-01d734332ace.png)

上記完了後にボリュームを選択してアクションからデタッチをします。

### 3. 復旧インスタンスに上記ボリュームをアタッチ
デタッチ済みのボリュームを選択してアクションからボリュームのアタッチを選択します。
インスタンス名とデバイスを指定する画面でインスタンス名: 復旧用のインスタンス
デバイス: /dev/sdf を指定します。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72175/12e34cab-75d0-21ce-8c88-f220caa8f815.png)

### 4. 復旧インスタンスの起動、ログイン
復旧用インスタンスを起動してSSH接続をします。
接続後、rootユーザにスイッチします。

### 5. 復旧インスタンスにマウント
llコマンドにて先ほどアタッチした/dev/sdf内容を確認します。

```bash:コマンド
ll /dev/ | grep sdf
```

```bash:コマンド結果
lrwxrwxrwx 1 root root           4  2月 20 12:36 sdf -> xvdf
lrwxrwxrwx 1 root root           5  2月 20 12:36 sdf1 -> xvdf1
```

下記コマンドでマウントまでの作業を行います。

```bash:コマンド
mkdir /mnt/data
mount /dev/sdf1 /mnt/data
```

### 6. 復旧インスタンスで修正作業
マウント作業を行うと /mnt/data のディレクトリ内が障害インスタンスのボリュームになっています。
今回修正を行うファイルは /mnt/data/etc/passwd のためvi コマンドで開いて修正をおこないます。

```bash:参考コマンド
vi /mnt/data/etc/passwd
```

### 7. 復旧インスタンスからアンマウント
下記コマンドにて障害インスタンスのボリュームをアンマウントします。

```bash:コマンド
umount /dev/sdf1
```

### 8. 復旧インスタンスの停止、ボリュームのデタッチ
復旧インスタンスを停止します。
停止後、EC2 ボリュームのコンソールに移動します。
(2)の工程でメモした「ボリュームID」のボリュームを見つけて選択後、アクションからデタッチします。
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72175/0854b919-56d5-85cb-9b83-1de1e6063b0e.png)

### 9. 障害インスタンスに修正したボリュームをアタッチ
上記ボリュームを障害インスタンスにアタッチします。
デバイスは(2)の工程でメモした「アタッチのパス」を入力してください。
今回 /dev/xvda になります。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/72175/dc98b3e0-3dca-ca97-f26c-4e7986887d7d.png)

### 10. 再起動
障害インスタンスを再起動して、SSH接続が正常にできることを確認します。
Githubのfolk、clone、コミット、pushについて

Githubの基本的な使い方が理解できたのでまとめていこうと思います。

## リポジトリとは
リポジトリとは「貯蔵庫」という意味で、過去のもの含め、一連のファイルが保存されている場所のことを言います。
よく聞くワードとしては「リモートリポジトリ」と「ローカルリポジトリ」という言葉ですが、これはどこの貯蔵庫を指しているかという話です。
リモートリポジトリとはネットワーク上にあるリポジトリで、ローカルリポジトリが自分のPCにあるリポジトリを指します。
複数人で作業するときは、共通の「リモートリポジトリ」が1つあり、ローカルリポジトリが人数分あるイメージになります。

## フォークとは
フォークとは「分岐」という意味があります。
誰かのリポジトリを「分岐」して自分のリモートリポジトリに追加することをフォークと呼びます。
通常、誰かのリポジトリをそのまま操作することはなく、リモートリポジトリにフォークして、操作していきます。


## クローンとは
クローンとは、自分のローカルリポジトリにリモートリポジトリのデータをコピーしてくることを言います。
リモートリポジトリとローカルリポジトリは一緒に動くことが求められる（貢献することが求められる）ので、フォークではなく「クローン」という言い方になります。
フォークしてきた誰かのリポジトリをクローンすることで、ローカルリポジトリでファイルを操作することが可能になります。

## コミットとは
コミットとは、開発の中で新しいバージョンを作成することをいいます。
開発では連続して新しいコードを書いていくわけですが、その中のきりが良いところで新しいバージョンとしてコミットしておくと、
新しいバージョンができ、例えばそこに戻ってコードを書いたり差分を比べたりすることができるようになります。
コミットは保存しただけでは行われず、一度「ステージングエリア」に上げた後、コミットメッセージと一緒にコミットすることで行うことができます。

## ブランチとは
ブランチとは、作っているメインの開発から「枝分かれ」を作って、コミットを作ることをいいます。
デバッグや新規機能の開発など、メインのブランチ（masterブランチ）から離れたところで作業する必要がある場合にブランチを作成します。

## マージとは
マージとは、作ったブランチを他のブランチに統合することを言います。
開発として先に勧めていくブランチの場合は、マージしていくことになります。

## プッシュとは
プッシュとは、ローカルで作成したデータをリモートリポジトリにだしていく事を言います。
プッシュすることで、オンライン上に自分の変更をアップロードすることができます。
しかし、それを勝手にしていると、みんなが書いた好き勝手なコードがリモートリポジトリに並ぶことになります。
それを防ぐために、プルリクエストがあります。

## プルとは
プルとは、リモートリポジトリの変更をローカルに反映させることを言います。
ローカルの開発環境は、リモートと同じでなければなりません（クローン）。
そのため、プッシュする際、もし最新版がリモートリポジトリに上がっていれば、一度プルしてから、プッシュすることとなります。

## プルリクエストとは
プルリクエストとは、プッシュする前に第三者の承認を挟むことを言います。
「プル」してもらうためのリクエストなので、プルリクエストです。


また一つ学びました。
Pythonのラムダ式

## Pythonのラムダ式
今回はpythonです

```Lambda.py
# hatching from Java
class Lambda ():

    def __init__ (self):
        print()

    # return only odd number by function
    def test(data):
        list = []
        for v in data:
            if v % 2 == 0:
                list.append(v)
        return list

    # same function by different method
    def test2(data):
        return [v for v in data if v % 2 == 0]

    # execute
    if __name__ == '__main__':

        # def data
        data = list(range(10))+

        # [0, 2, 4, 6, 8]
        print('use function')
        print(test(data))

        # [0, 2, 4, 6, 8]
        print('use function another')
        print(test2(data))

        # <filter object at 0x00000143D3A05608>
        print('use filter & lambda')
        print(filter(lambda v: v % 2 == 0, data))
        # 0 2 4 6 8
        for v in filter(lambda v: v % 2 == 0, data):
            print(v)

```

## やっぱラムダ式最高だわ
備忘録がてら解説書きます

## 普通のfor文
```for.py
    # return only odd number by function
    def test(data):
        list = []
        for v in data:
            if v % 2 == 0:
                list.append(v)
        return list
```
Javaの拡張for文と同じですね
for文の中でif文で、Listにaddしています
偶数のみを詰めて返却するメソッドになっています
javaだとこうですね ちょっと端折りますが

```for.java
		List<Integer> list = new LinkedList<>();
		for (int i : Arrays.asList(0, 1, 2, 3)) {
			if (i % 2 == 0) {
				list.add(i);
			}
		}
```

## どうにか1行で書いてみる
Javaの場合
もうこの時点でラムダに頼らざるを得ません

```forline.java
		Arrays.asList(0, 1, 2, 3).stream()
				.filter(v -> v % 2 == 0)
				.forEach(System.out::println);
```

Pythonなら、for文1行で書けるし、付属的にif文を付け加えられる

```forline.py
    def test2(data):
        return [v for v in data if v % 2 == 0]
```
しかもこれって、streamのcollect(Collectors.toList())した後みたいに
配列で返してくれるんですよね
ラムダを使わずしてこの破壊力、さすがpython

## filterとやら
Javaのstreamにしかみえませんねぇ
文法は
`filter(ラムダで書いた条件, 繰り返す対象)`
Javaのstreamでいうなら
`filter(v -> v == 0)`
みたいに条件に書く部分が第一引数で、そもそも配列などの捜査対象が第二引数ですね

```filter.py
filter(lambda v: v % 2 == 0, data)
```

dataが繰り返し対象のリストです
ラムダはJavaでいうFunction、引数と内部実装を書くものなので
勿論こういうこともできます

```lambda.py
# 引数vが入ってきて、偶数のみを返す関数
stream = lambda v: v % 2 == 0

# 作ったstreamって関数の条件で、dataを絞る
filter(stream, data)

# このままだとコンソールに<filter object at 0x000002BC0F2D25C8>って出る
print(filter(stream, data))

# こうだとちゃんとリストの中身が出力されるよん
for v in filter(stream, data):
    print(v)
```

最後の方でなんか変な感じになってますね
`list.forEach(System.out::println)`みたいな、voidメソッドとしてのforを1行で書けないものですかね?

メソッドを何発もチェーンできるstreamAPIはそれはそれで優秀ですけど、調子に乗ると可読性も低くなりますし

素でこのくらい強いやつのがなんだかんだはかどりそうですね
【Rails】bundle install したときに vender/bundle にインストールされるのをデフォルトに戻す

# はじめに
Railsで開発している時、エラーを解決しようとガチャガチャやった後、`bundle install`したらなぜかプロジェクト下の vender/bundle に gem がインストールされるようになってしまいました。とりあえず前の状態に戻したいと思い、原因と解決法を探りました。

# bundle install --path vender/bundle
調べてみると、むしろ`bundle install --path vender/bundle`を推奨する記事が散見されましたが、下記の記事のようにこの慣習に疑問を呈している記事もありました。

[bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう](https://qiita.com/jnchito/items/99b1dbea1767a5095d85)

# デフォルトに戻す
ググると以下のような方法をすぐに見つけました。

> Bundlerがどこからgemを探すかは、プロジェクトルートの下の.bundle/configに設定ファイルがあります。これを消すことで、新たな場所にbundle installできるようになります。

https://teratail.com/questions/16066

しかし、私の場合この方法では症状解決しませんでした。
そこで、もう一度`bundle install`しプロジェクト下に作成された .bundle/config ファイルを確認しました。

```.bundle/config
---
BUNDLE_WITHOUT: "production"
```

…特に`path`オプションに関連するものはありませんでした。

そこで`bundler config`でどのようなオプションが設定されているかを確認しました。

```
$ bundler config
Settings are listed in order of priority. The top value will be used.
without
Settings are listed in order of priority. The top value will be used.
path
Set for the current user (/Users/punkshiraishi/.bundle/config): "vendor/bundle"
```

これで path オプションが /Users/[ユーザ名]/.bundle/config で設定されていることが分かったので開いてみると

```/Users/[ユーザ名]/.bundle/config
---
BUNDLE_WITHOUT: "production"
BUNDLE_PATH: vendor/bundle
```
ありました！
この`BUNDLE_PATH: vendor/bundle`を削除し、`bundle install`することで、使用中の Ruby 直下に gem がインストールされるようになりました！

更に調べてみると bundler のオプションは

- Railsプロジェクト下の .bundle/config
- 環境変数
- ユーザのホームディレクトリ下の .bundle/config

の３つにあるということが分かりました。プロジェクト直下の .bundle/config を削除しても設定が戻らないという方は上記も調べてみると良いかもしれません。

# 参考
- [bundle install時に--path vendor/bundleを付ける必要性は本当にあるのか、もう一度よく考えてみよう](https://qiita.com/jnchito/items/99b1dbea1767a5095d85)
- [Bundlerでビルドオプションを指定する](https://qiita.com/thunders/items/101c6b329830fb1fb27d)
スクリプトでPuppetMasterのRagdoll作成

#概要
スクリプトでPuppetMasterのRagdollを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286581/b8d29d3e-ef91-25f7-976c-1beaea163dd3.png)
※コレをスクリプトでやります。

#実装
```cs
using UnityEngine;
using RootMotion.Dynamics;

public class Set : MonoBehaviour
{
    [SerializeField] GameObject Obj;

    void Start()
    {
        var anim = Obj.GetComponent<Animator>();

        var r = new BipedRagdollReferences();
        r.root = Obj.transform;
        r.hips = anim.GetBoneTransform(HumanBodyBones.Hips);
        r.spine = anim.GetBoneTransform(HumanBodyBones.Spine);
        r.chest = anim.GetBoneTransform(HumanBodyBones.Chest);
        r.head = anim.GetBoneTransform(HumanBodyBones.Head);
        r.leftUpperLeg = anim.GetBoneTransform(HumanBodyBones.LeftUpperLeg);
        r.leftLowerLeg = anim.GetBoneTransform(HumanBodyBones.LeftLowerLeg);
        r.leftFoot = anim.GetBoneTransform(HumanBodyBones.LeftFoot);
        r.rightUpperLeg = anim.GetBoneTransform(HumanBodyBones.RightUpperLeg);
        r.rightLowerLeg = anim.GetBoneTransform(HumanBodyBones.RightLowerLeg);
        r.rightFoot = anim.GetBoneTransform(HumanBodyBones.RightFoot);
        r.leftUpperArm = anim.GetBoneTransform(HumanBodyBones.LeftUpperArm);
        r.leftLowerArm = anim.GetBoneTransform(HumanBodyBones.LeftLowerArm);
        r.leftHand = anim.GetBoneTransform(HumanBodyBones.LeftHand);
        r.rightUpperArm = anim.GetBoneTransform(HumanBodyBones.RightUpperArm);
        r.rightLowerArm = anim.GetBoneTransform(HumanBodyBones.RightLowerArm);
        r.rightHand = anim.GetBoneTransform(HumanBodyBones.RightHand);

        BipedRagdollCreator.Create(r, BipedRagdollCreator.Options.Default);
    }
}
```

#参考
https://www.youtube.com/watch?v=y-luLRVmL7E&feature=emb_title
Linux カーネルにおけるInstruction Pointer (=プログラムカウンタ)取得方法

Linuxカーネル・ドライバにおいて、Instruction Pointer (=プログラムカウンタ)を取得したい場合、linux/kernel.hで定義された`_THIS_IP_`マクロを使います

定義は下記のとおり。

```
#define _THIS_IP_  ({ __label__ __here; __here: (unsigned long)&&__here; })
```

# LinuxカーネルにおけるInstruction Pointerの簡単な歴史

かつては各アーキテクチャで独自に`current_text_addr()`を定義していたのですが、v4.20あたりでそれらが全て撤廃され、linux/kernel.hにある`_THIS_IP_`を使うように統一されたようです。

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?h=v5.6-rc2&id=de0d22e50cd3d57277f073ccf65d57aa519d6888

このときのpatchを見ると、各アーキテクチャのアセンブラによるプログラムカウンタの取得方法が見れておもしろいです。
アセンブラを書いたことがある人なら当たり前の話なのですが、プロセッサのプログラムカウンタを保持するレジスタは、アーキテクチャ毎に異なります。そのため、アーキテクチャ毎に個別の実装を用意するというのは、理にかなっているような気がします。ではなぜ、マクロ1本に統一されたのか？

# なんだこのマクロは?

まずマクロがまったく理解できなかったのでググってみたところ、stackoverflowで優しいお兄様方が解説してくれていました。さすがです。

https://stackoverflow.com/questions/13902431/this-ip-macro-in-linux-kernel

要約すると、

* `__label__ __here;`はローカルラベル名の宣言
* `__here:`はローカルラベル
* `&&__here;`は上記ローカルラベルのアドレス (unsigned long型にキャストされている)

ということのようです。カッコ()の中が1行だとわかりにくいので改行を入れると、

```
{
	__label__ __here;
__here:
	(unsigned long)&&__here;
}
```

となり、1行目がローカルラベル名の宣言、2行目がラベルです。
ローカルラベルは、どうやらGCCで使えるものらしいです。
https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Local-Labels.html

ブロック内でのみ参照できるラベルということですね。

3行目の'&&'はラベルのアドレスを示すための特別な演算子です(参考:https://docs.oracle.com/cd/E19205-01/821-0386/bjabt/index.html)


このマクロを埋め込んだ位置では、ブロック内のローカルラベルとして`__here`が貼られ、そのラベルのアドレスを取得することが、詰まるところ現在のプログラムの位置(=プログラムカウンタ)となるわけです。
よって、プログラムの現在の位置を、アセンブラに頼らずC言語のみで表現できるため、カーネル内でも`_THIS_IP_`マクロ1本に統一できたというわけです。(なお、gccを使う限りはLinuxに限らず様々な環境に移植可能なはずです。)

# そしてC言語ようわからんという愚痴

問題はこの外側について。正直よくわからない。通常、ブロック文{}は式として使用できない。試しに、下記のようなコードを書くとコンパイルエラーになる。

```
int i = {1;};
```

ところが、ブロック文をカッコ()で括るとなぜかコンパイルが通る。

```
int i = ({1;});
```

このとき、カッコ()式の値はブロック{}文の最後に書いた式を評価した時の値が使用される。試しに下記のコードをgccでコンパイルして実行してみると、コンソールにはブロック文最後の式dの値(=5)が表示される。

```
#include <stdio.h>
int main(void)
{
        int a = ({
                int a = 2;
                int b = 3;
                int c = 4;
                int d = 5;
                a;
                b;
                c;
                d;
        });
        printf("%d\n", a); 
        return 0;
}
```

これは文法的にどうなんだ。。。

以上、かれこれ10年以上はC言語を扱ってるのに未だに文法的に知らない・読めないものが出てくることに対する無力感から、備忘録としてまとめました。...精進します。

でも**C言語は綺麗じゃない**と思う。だって'&&'、お前ずっと二項演算子として俺と付き合ってたはずだよな...？
('&&'もGCCの拡張ですかね https://gcc.gnu.org/onlinedocs/gcc-5.2.0/gcc/Labels-as-Values.html#Labels-as-Values)
【メモ】画像圧縮コマンド

# 画像圧縮を行う理由
画像を扱う系のサイトの場合、スピードが遅くなりがち
参考：[speed check](https://developers.google.com/speed/pagespeed/insights/)

WEBP等を利用する手もあるが、根本的に画像圧縮を行わないと改善速度は上がらなさそう

# 画像圧縮コマンド
```jpegoptim -s -m70 */*/*.jpg```
**guetzli**もあるが、かなり重たいので、当分は**jpegoptim**でいいかな

**-s**はメタ情報削除
**-mXX**は圧縮クオリティ（-m70ぐらいで100~300KBぐらいにしてくれる感じ）

# 紹介
- [SnapU｜天気・気温に合わせた服装コーディネートサイト](https://snapu.tokyo)
google images download で101件以上画像を取得できない問題を調べた

以下を参考にしてサンプル画像大量ゲットできました

[google image downloadが動かなかったのでその対応](https://qiita.com/taedookim/items/63759e79426514c8a729)

よーしおじさん教師データつくっちゃうぞ、100件だと心もとないから1000件くらい画像ほしいな

ということでデバッグ~~しました~~しています

#だめぽ

とりあえずきちんとデバッグしてみたんですが、この問題はいくつかの問題が重なっていて

* 普通に読みに行くのと、chromedriverで取得するのとでは取得できるhtmlのエンコード状態が異なることによるエラー
    * 100件以下の場合、101件以上の場合で挙動を分けることで解決
* chromedriverでchromeを自動操縦するとき、画面をスクロールさせてどんどん新しい画像を読んでいくんだけど、3回めのlazy loadで「結果をもっと表示」ボタンが出る。このボタンを押すコードがあるがgoogle側の仕様変更により動作していなかった
    * DOM要素の指定を適切にすることで解決
* 画像検索のHTMLには検索結果の諸情報がjavascriptの配列の形式で格納されており、google images download はそれをjsonデコードしているが、google側の仕様（変更かどうかわからんが）、lazy loadを行った際の元画像URLはjs上で管理され、HTMLにはサムネイルしか描写されないので、最大限にlazy loadを行ったところで、HTMLソースだけを解析しても最初の100件ぶんしか元画像は取れない
    * やろうとすればできそうな気もするけど、相当大変そう

ということで、なんか無理っぽいという結論がでたのでいったんペンディングにします　101件以上ほしい場合は他をあたったほうがよさそうですね

とりま、詳しいことがわかっただけでもよしとしましょう
機械学習と数理最適化

#機械学習と数理最適化

「コンビニのお店×商品ごとに**需要予測**がしたいんです」
　→　機械学習/統計モデリングっぽい話
　　　現象の予測・解明

「コンビニのお店×商品ごとに需要予測に基づいて**利益の最大化**をしたいんです」
　→　数理最適化っぽい話
　　　利益の最大化(現象が解明した後にKPIの最大化・最小化)


機械学習と数理最適化の間：バンビット問題（強化学習）というのもある

#意思決定のステップとアナリティクスの到達段階
データサイエンス/AI/アナリティクスといってもレベルは様々である

意思決定のステップ
　①集計（何が起きるのか）
　②説明（何故起きたのか）
　③予測（何が起きるのか）
　④意思決定（何をすればいいのか）
　⑤行動（実際の行動）

アナリティクスの到達段階
　①記述的アナリティクス
　②診断的アナリティクス
　③予測的アナリティクス
　④処方的アナリティクス（AIによる意思決定支援）
　⑤処方的アナリティクス（AIによる意思決定）

一般的に　
　①集計（何が起きるのか）　DWH/BIツールで行う
　　①記述的アナリティクス

　②説明（何故起きたのか）や③予測（何が起きるのか）までを機械学習/統計解析が行う
　　①記述的アナリティクス
　　②診断的アナリティクス
　　③予測的アナリティクス

　④意思決定（何をすればいいのか）や⑤行動（実際の行動）を数理最適化によって行う
　　①記述的アナリティクス
　　②診断的アナリティクス
　　③予測的アナリティクス
　　④処方的アナリティクス（AIによる意思決定支援）
　　⑤処方的アナリティクス（AIによる意思決定）


#機械学習vs数理最適化

|タスク|システムへの入力|システムのメカニズム|システムの出力|典型的な技術|
|:-----------------:|:------------------:|:------------------:|:------------------:|:------------------:|
|予測・推定|⭕️|不明→推定　|⭕️|機械学習・統計学|
|最適化|最良のものは不明→探索|⭕️|最小化・最大化したい|数理最適化|

#どこまでできるか？

||説明|予測|意思決定支援|意思決定|
|:--------:|:------------:|:--------:|:--------:|:--------:|
|株トレード（DayTrading）|○|○|○|○（HFT）|
|スーパーの購買計画|○|○（需要予測）|○（最適購買）|○|
|建築機材のレンタル|○|○（需要予測）|○（支店間の機材配備の最適化）|○/?(支店間のインセンティブの対立)|
|コモディティトレード|○|○（価格予測）|○（売買タイミング示唆）|？（政治リスクの評価）|
|農業|○|○（収穫予想）|○(肥料最適化)/?(販売計画)|？|
|M&A|○|？（高い個別性）|?|?|

課題・オペレーション依存になりやすい

# 数理最適化で解決できる課題の例

・広告割り当て問題　→　広告効果の最大化（CVR・ CTR）
・車両配送計画立案　→　（一回の荷物の重量・最適なルートなど）
・工場の生産計画　→　原材料と生産量の調整・他の工場との連携など
・行政の施設配置問題　→　（学校とか）
・戦争　→　（効率のいい攻撃）
・ポートフォリオ　→　（リスクリターンのバランス・同じリターンでもリスクが減らせる）
・シフト作成　→　（役割と負担の調整）

#参考
　DWHとBIツール
　　https://it-trend.jp/bi/article/bi_dwh
  
　python3
　　numpy pulp

　勉強の仕方
　　　応用に約立つ５０の最適化問題（本）
jenkinsのビルドjobでforce pushされても最新ブランチを取り込めるようにする

jenkinsのビルドジョブで指定されたブランチをpull後アプリビルドするというのはよくある流れだと思います。
pullする際、現在のブランチがforce pushされているとコンフリクトが発生してジョブがエラー停止することがあります。

```
$ git pull // ここでエラー
$ bash ./build.sh
```

↓これで最新版を取り込みつつエラーを回避できます。

```
$ git fetch
$ git reset --hard @{u}
```

@{u}は @{upstream} の略で現在のブランチの上流ブランチを表します。
https://git-scm.com/docs/gitrevisions#gitrevisions-emltbranchnamegtupstreamemegemmasterupstreamememuem
「スタックとキュー」 アルゴリズムとデータ構造を復習(1) 

スタックとキューを配列をC++で実装してみました
キューは頑張って循環キューにしました。

```cpp:StackClass
class Stack {
    typedef int element_type;
private:
    static int MAX_LENGTH;
    element_type* data;
    int head;

public:
    Stack() {
      this->data = new int[MAX_LENGTH];
      this->head = 0;
    }
    element_type pop() {
      if (this->head == 0) {
        printf("Stack Underflow");
        exit(1);
      }
      this->head--;
      return this->data[this->head];
    }

    void push(element_type value) {
      if (this->head == this->MAX_LENGTH) {
        printf("Stack Overflow");
        exit(1);
      }
      this->data[this->head] = value;
      this->head ++;
      return;
    }
};

int Stack::MAX_LENGTH = 128;

```

```cpp:QueueClass
class Queue {
    typedef int element_type;
private:
    static int MAX_LENGTH;
    element_type* data;
    int head, tail;

public:
    Queue() {
      this->data = new int[MAX_LENGTH];
      this->head = 0;
      this->tail = 0;
    }
    element_type dequeue() {
      if (this->tail == this->head) {
        printf("Empty");
        exit(1);
      }
      element_type value = this->data[this->head];
      
      this->head++;
      if (this->head == this->MAX_LENGTH) {
        this->head = 0;
      }
      return value;
    }

    void enqueue(element_type value) {
      prev_tail = this->tail;
      
      this->tail++;
      if (this->tail == this->MAX_LENGTH) {
        this->tail = 0
      }
      if (this->tail == this->head) {
        printf("Overflow");
        exit(1);
      }

      this->data[prev_tail] = value;
      return;
    }
};

int Stack::MAX_LENGTH = 128;
```

キューは頑張って循環キューにしたのですが、配列でキューやる時って、キューいっぱいの状態って、1データ分余っちゃうのしょうがないんでしたっけ??そんな風に昔授業で言っていた気がする。
次はリンクドリストで実装してみたいと思います。
SwiftUIのプレビューデバイスを設定する方法


# SwiftUIのプレビューデバイスを設定する方法
SwiftUIで開発している時、特定の端末または複数の端末でプレビューをみたい時がありますよね。そんな願いを叶える方法です。（SwiftUIチュートリアルをやったことある人は知っているはず）

次のコード内の２つ目のstructのSwiftUIView_Previewsがプレビューに関するコードです。この部分にコードを加えて、プレビューデバイスを設定します。

```SwiftUIView.swift
import SwiftUI

struct SwiftUIView: View {
    var body: some View {
        Text("Hello, World!")
    }
}

/// 以下のコードがプレビューに関するコード
struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
    }
}
```
## １ 特定の端末のプレビューデバイスを設定する
### 1-1 実装方法
```SwiftUIView.swift
struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        SwiftUIView()
            /// 以下の行を追加
            .previewDevice(PreviewDevice(rawValue: "iPhone X"))
    }
}
```
### 1-2 実行結果
<img width="1058" alt="スクリーンショット 2020-02-20 21.58.11.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424734/a48ecd46-94e8-2d57-9b42-7f3f98642d7a.png">
### 1-3 解説
.previewDeviceのrawValueに端末を指定すれば、プレビューデバイスを設定できます。設定できるデバイス例 → [3 設定できる端末例](#3-設定できる端末例)
## 2 複数の端末のプレビューデバイスを設定する
### 2-1 実装方法
```SwiftUIView.swift
struct SwiftUIView_Previews: PreviewProvider {
    static var previews: some View {
        /// 以下の行を追加
        ForEach(["iPhone SE", "iPhone XS Max", "iPhone X"], id: \.self) { deviceName in
            SwiftUIView()
                /// 以下の2行を追加
                .previewDevice(PreviewDevice(rawValue: deviceName))
                .previewDisplayName(deviceName)
        }
    }
}
```
### 2-2 実行結果
<img width="1058" alt="スクリーンショット 2020-02-20 21.44.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/424734/f5c3ae1b-9ec7-0727-8ad3-8a9a496a0de1.png">
### 2-3 解説
ForEachに端末の配列を渡して、反復処理の実行ごとに.previewDeviceのrawValueに端末を指定し、プレビューを表示させています。なお、「id: \.self」は配列の要素が一意であることをSwiftUIに知らせるためのもので必須です。
.previewDisplayName(deviceName)では右側のプレビューで表示される端末の下の端末名を指定しています。これを設定しないと、全て「Preview」と表示されます。複数の端末のプレビューデバイスを設定する際は必要だと思います。

## 3 設定できる端末例
```端末一覧（iPhoneのみ）.swift
"iPhone 7"
"iPhone 7 Plus"
"iPhone 8"
"iPhone 8 Plus"
"iPhone SE"
"iPhone X"
"iPhone Xs"
"iPhone Xs Max"
"iPhone Xʀ"
```
## 4 プレビューデバイスを設定を設定していない場合は？
TARGETSのDeployment Info内のDeviceからXcodeが自動選択しているようです。
## 5 参考ページ
[AppleDevelopper](https://developer.apple.com/documentation/swiftui/securefield/3289399-previewdevice)（.previewDeviceについて）
[Hacking with Swift](https://www.hackingwithswift.com/quick-start/swiftui/how-to-create-views-in-a-loop-using-foreach)（id: .selfについて）
ダイソーのBluetoothボタンでポモドーロ

# 概要
ダイソーのBluetoothボタンを使って、ポモドーロテクニック用の25分タイマーをセットできるようにした。

# はじめに
### 背景その１
前回、ダイソーのBluetoothボタンを使ってタイムトラッキングする仕組みを作った。

[IoTボタンを安く手に入れてノーコードでWeb APIを叩く方法 - Qiita](https://qiita.com/optimisuke/items/a9f4dc65559a7a5eadef)

ポモドーロテクニックに興味あったので、その機能も追加してみた。機能といっても、タイマー追加するだけやけど。

ポモドーロテクニックは、時間を区切って仕事してこまめに休憩とると集中できるよ的なテクニック。たぶん。

### 背景その２
何度か、ポモドーロやってみようと思ったことあるけど、本気では実行にうつしたことなかった。

ポモドーロのためのツールに求める要件は、以下の通り。

- パソコン作業だけじゃなくて実験とかアナログな仕事中でも使える
- 他の人のじゃまにならなず（音がでない）に自分だけ気づける
- 気が散らない

スマホアプリでやってもいいかもしれんけど、30分おきにスマホみるのって気が散る気がしてた。アナログとデジタルのちょうど良いところないかなぁと思ってたので試してみることにした。

# 実装
前回同様、MacroDroidっての使った。

アラームを設定する機能を発見。タイマーはなぜかない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/9dc99cfc-e864-1bcd-776f-fa15873cf075.png)

その時間の25分後にアラームするように設定した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/0edc32e2-d5ee-277c-407a-d017a0e6fbfa.png)

試してみると、こんな感じでアラームが設定される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/763e4e25-0a64-7e6a-db63-597b5bb30692.png)

アラーム止める方の設定画面は、ラベル指定するだけ。
これは、うまく動作しなかった。アラーム画面を表示するところまでは遷移してくれるから、そんなに不便はしなさそうだけど。なんで動作しないんやろう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/eee9b06c-3009-2cd8-5920-5d9a22c6c17a.png)

ここらへん、軽く読んだけど、デバイス依存あるんかな。あきらめた。
[Issue with disabling alarm action - MacroDroid Forums](https://www.tapatalk.com/groups/macrodroid/issue-with-disabling-alarm-action-t3208.html)
[action to dismiss alarm - MacroDroid Forums](https://www.tapatalk.com/groups/macrodroid/action-to-dismiss-alarm-t4759.html)

最終的に、作業開始するときの設定がこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/4ef5f6e7-b52f-75de-aa7c-7082de001393.png)

作業終了するときの設定がこんな感じ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184221/69266e36-8461-7a07-0008-be8d44c0afc5.png)

# 評価
わるくない。いい感じ。「もう25分たったのかー、少し休憩するか」ってなる。
バックグラウンド動作が不安定な気もする。Huaweiと相性悪いのかも。もうちょい、長いこと確認せなあかんかなぁ。

# おわりに
ポモドーロよさげ。本気でやるには息苦しい気もするから、適度にゆるく続けたい。
まだ、作業前に押すの忘れるから、もうちょい習慣化したい。
MacroDroid、アプリ作らずにプロトタイピング的なことできていい感じ。
Laravelでミニブログを作ろう #1

laravelの使い方を一通り習ったので、laravelを使って（競プロの勉強の合間に）ちょこちょこミニブログを作っていくことにします。
作成していく過程で最近学習したAWSだったりCircle CIだったりの復習をしていければと考えてます。
（果たして完成するまでに何ヶ月かかるのか）

# 要件定義

### アプリの概要
Markdown記法で記事が書けるミニブログ
### 主要な機能
- 記事の作成、編集、更新、削除、下書き（ユーザーは複数人登録できる）
- 画像投稿
- タグ付け機能（記事を作成したユーザー以外もタグ付けできる）
- いいね機能
- Markdownエディタ
- レスポンシブデザイン
- 管理人機能（ユーザー一覧、ユーザー詳細表示）

### 技術要件
- フロント
  - Vue.js （いいね機能、タグ付け機能の実装のため）
  - Scss
- バックエンド
  - php
  - laravel
- サーバー
  - nginx
- DB
  -  mysql 5.7(ローカル)
  -  RDS(AWS)
- インフラ
  -  AWS
    - ECS/ECR
    - RDS(mysql)
    - EC2
    - S3
    - VPC
    - Route53
    - ALB
    - ACM
- Terraform（AWSをコード化）
- heroku（多分AWS版のアプリ完成した後、herokuに移行すると思います。お金無いので）
- CircleCI

その他Googleアナリティクスの導入

（非技術要件も定義できれば尚良いんですが...）

# 作成手順
環境設定（Dockerfile→Circle CI,PHPUnit（テスト）,Terraform等）→laravelでアプリの中身を作り上げていく→デプロイ　の流れ

# laravelのインストール

rootディレクトリに移動してlaravelをインストールします

```
$ composer create-project laravel/laravel larablog 
```

```
─── laravel(ルートディレクトリ)
    ├── larablog       ・・・今回のアプリ
        ├── app 
        ├── bootstrap
        .
        .
        .
```

次回からDockerfileを書いていきます
PHP 文字列を時刻に変換 

###使う機会があったのでメモしておきます。

指定の時間からある日時を足し引きしたい場合

```php:qiita.php
$str = "10";
$int = intval($str);
$datetime = "2020/02/20 13:00:00";

//10秒前　2020-02-20 12:59:50
echo date("Y-m-d H:i:s",strtotime($datetime . "-" . $str . "second"));
echo "<br>";
//10分後 2020-02-20 13:10:00
echo date("Y-m-d H:i:s",strtotime($datetime . "+" . $int . "minute"));
echo "<br>";
//10時間前 2020-02-20 03:00:00
echo date("Y-m-d H:i:s",strtotime($datetime . "-" . $str . "hour"));
echo "<br>";
//10日後 2020-03-01 13:00:00
echo date("Y-m-d H:i:s",strtotime($datetime . "+" . $int . "day"));
echo "<br>";
//10週間前 2019-12-12 13:00:00
echo date("Y-m-d H:i:s",strtotime($datetime . "-" . $str . "week"));
echo "<br>";
//10ヶ月後 2020-12-20 13:00:00
echo date("Y-m-d H:i:s",strtotime($datetime . "+" . $int . "month"));
echo "<br>";
//10年前 2010-02-20 13:00:00
echo date("Y-m-d H:i:s",strtotime($datetime . "-" . $str . "year"));
echo "<br>";

```
アニメーションが終了してから プロパティーの値を変更したくても変わらない

`FillBehavior = "Stop"` を 追加する。

```xaml:sample
	<DoubleAnimation Storyboard.TargetName="hoge" Storyboard.TargetProperty="Opacity"
		 From="0" To="1" Duration="00:00:00.300" FillBehavior = "Stop" />
```
awkのフィールド操作Tips

### 空白を整理する
```
$ echo ' 1  2 3   4  ' | awk '{$1=$1; print}'
1 2 3 4
```

### 任意のフィールドを削除する
```
$ seq 1 5 | xargs | awk '{$1=""; $0=$0; $1=$1; print}'
2 3 4 5
```

### フィールドの末尾を削る
```
$ seq 1 5 | xargs | awk '{NF=NF-2; print}'
1 2 3
```

### フィールドを付け足す
```
$ seq 1 5 | xargs | awk '{$0=$0FS 6; print}'
1 2 3 4 5 6
```

### フィールドを挿入する
```
$ seq 1 5 | xargs | awk '{$3=$3FS 6; $0=$0; print}'
1 2 3 4 5 6
```
【試験合格記】AWS 認定 DevOps エンジニア – プロフェッショナル

お疲れさまです。
表題の試験に合格したため記録として残したいと思います。

# 結果
合格(760点)

|分野|名称|割合|
|:-----------------|:-------------------|:-------------------|
|1|SDLC の自動化|22%|
|2|構成管理およびInfrastructure as Code|19%|
|3|監視およびロギング|15%|
|4|ポリシーと標準の自動化|10%|
|5|インシデントおよびイベントへの対応|18%|
|6|高可用性、フォールトトレランス、およびディザスタリカバリ|16%|

# 所有資格
AWSに限っては下記の通りです。
SAPからだいぶ間が空きましたが、ようやく旧ホルダー名称である5冠達成で語感が良くなりましたね。

| 資格名       |取得年月日 |
|:-----------------|:-------------------|
|AWS Certified Solutions Architect - Associate (SAA)|2018-06-14|
|AWS Certified SysOps Administrator - Associate (SOA)|2018-06-22|
|AWS Certified Developer - Associate (DVA)|2018-06-25|
|AWS Certified Solutions Architect - Professional (SAP)|2018-07-19|
|AWS Certified DevOps Engineer - Professional (DOP)| 2020-02-19| 

# 事前知識
インフラ寄りの技術者かつまぁまぁ早いうちにパブリッククラウドの世界に身を投じていたため、AWSにフィットさせることができていました。
あとは実際にAWS環境で設計〜運用まで1サイクル回した経験も地力がついた要因だったと思います。

# 所感
試験に備えて準備した勉強箇所(Linux academy, Udemy)をことごとく外していて正答の確証があった問題は2割程度でした。
内容について詳しく書くことは避けますが、全体的にサービス間のパイプラインを使っていかにスマートな問題解決のアーキテクチャを選択できるか、が主軸にあったように感じました。
半分涙目になりながら170分間戦い抜いたことでボーナスポイントが加算されたのだと考えます。

# 受験者に向けたアドバイス
- CodePipeline, CodeBuild, CodeDeployを使って何ができるかを理解すること
- Elastic Beanstalkのダウンタイムを避けるための運用はどうすればいいか理解すること
- gitのあるべき運用方法を実業務に近い形で理解しておくこと
- SAPと同様に可用性を担保するための工夫をパターン別で把握しておくこと
- DynamoDBを多少触っておくこと

# まとめ
やはりSAPよりは人道的な設問および選択肢が多かったため、プロフェッショナルの中ではDOPがおすすめです。
そしてDOPを取得することで開発者がAWSを使うために、サービスの取捨選択をどうすればいいのかが学べるため出題範囲を学習するだけでも得るものはあると思いました。

個人の目標としては年内に11冠を達成したいので、次はスペシャリティ取得を目指して引き続きがんばります。
イベントレポート（Developers.IO 2019）

AWS関連のイベント、セミナーに参加してきましたので、自分に対する備忘も兼ねて要点を纏めておきたいと思います。

・参加イベント
[【11/1（金）東京】国内最大規模の技術フェス！Developers.IO 2019 東京開催！AWS、機械学習、サーバーレス、SaaSからマネジメントまで60を越えるセッション数！](https://dev.classmethod.jp/news/developers-io-2019-tokyo/)


毎年開催されているクラスメソッド様のイベントです。
徐々に規模拡大されているようで、今年は1000人以上も参加者がいたそうです。
私は今の現場でCDKを使い始めたこともあって、CloudFormationやCDKなど、IoC関連のセッションをメインに聞いてきました。

# 各セッション内容纏め
## 1. AWSのすべてをコードで管理する方法〜その理想と現実〜(濱田孝治氏)
　　https://dev.classmethod.jp/cloud/aws/aws-all-iac/

### IaCを理解する
* IACは状態を定義（CLIは処理を定義）
* 手法	CloudFormation、Terraform、CDK
* CloudFormationのテンプレートについて
　⇒JSONは古いので、YAMLに変える
　　リソース記述順は関係ない（Parameter、Resources、Outputsは必須）
* CDKは入門編（Workshop）で学習可能

### CLIで実行する
* CLIでCloudFormationを実行する（運用効率化）
　⇒create-stack使わない、deployを使う
　　⇒deployはチェンジセット必ず作成、チェックバリデーションもしてくれる
　　　⇒--no-execute-changesetを使う
* 本当にあった怖い話
　同じスタック名で作成してスタック消える
　⇒対策はチェンジセット見る
* 実行はCLI、結果確認はGUIで良い

### 複数リソースを作成する
* 典型的な一式を作ると1000行超える
* スタックの分け方
  ⇒VPCとセキュリティグループは分ける（セキュリティグループは変更多いのでIaCでなくてもよい）
* スタック間でリソースを参照する方法
　⇒クロススタック参照
　　⇒注意点は参照しているスタックがある場合、削除できない
　　　⇒例）ECSのTaskをServiceがクロススタック参照する形だと運用破綻
* ダイナミック参照
　　⇒SystemsManagerのパラメータストア
　　　⇒DBのパスワードなど
* シェルで頑張る
　⇒ECRのURIなど（CloudFormationでoutputできない）

### 運用上のつらみ
* スタックの作成が終わらない
　⇒EC2に割り当たっているセキュリティグループを削除しようとすると返ってこない
　　サービス定義が誤ったECSの作成
* 新機能に対応しない
* 循環参照
* Conditionsに頼らない
　⇒条件分岐はテンプレートに適さない
　　⇒テンプレートを分けるなどで対応する方がよい
* CloudFormation以外でリソース更新される
　⇒スタック更新が正常に働かなくなる
　　⇒Drift Detection（ドリフト検出）で対応
　　　⇒AWS Configで自動Drift検知も（cloudformation-stack-drift-detection-check）

### パイプラインでインフラ構築
* 実行場所
　⇒個人のクライアントPC、適当なEC2インスタンス、リポジトリからのパイプライン実行

* パイプライン実行例
　⇒CodeCommitにテンプレート
　　⇒CodeBuild　チェンジセットまで
　　　⇒確認、問題なければCodeBuild スタック作成

## 1. Amazon CultureとAWSの設計思想 ～マイクロサービスアーキテクチャとアジャイル開発～
AWS亀田治伸 氏
https://dev.classmethod.jp/report/report-developers-io-2019-tokyo-amazon-culture/



## AWS CDKの基本と実例
加藤諒氏

* AWS構築の歴史
1.手順書(AMC、LambdaのIAMロール自動作成など
2.スクリプト
3.プロビジョニングツール(CloudFormation、Terraform、DOMs、GoFormation、CDK)
4.CDK

* AWS CDKのメリット
コードで書けると嬉しいのか？
⇒型があり、IDEの支援が受けられる
CDKによる抽象化
cdk.jsonに環境ごとのパラメータを設定できる(--context)
* AWS CDKでテストを行うべき理由
CDKは頻繁にアップデートされる
CloudFormationコードが変更されたかの検知をしたい

* テストの種類
Snapshot Tests・・・生成されるCloudFormation差分を確認
Fine-grained tests・・・意図したCloudFormationリソースが存在するか
ValidationTest


## 最近のAuroraのアップデート使いこなし術 〜 ServerlessやMulti-Masterどんな時に利用する？ 〜
大栗宗氏
### Auroraとは
大量アクセスのスループットが向上する方針で開発
### Aurora Serverless
DBインスタンスを意識せずに自動でスケーリングする形態
通常のAuroraより割高

###最近のAuroraアップデート
・Custom Endpoint
バッチアクセスとスループットが求められるアクセスのリソース分離
・GlobalDatabase
リージョン外にレプリケーションする機能
・Aurora Serverless Data API
インターネットからAPIでAurora ServerlessにAPIアクセスする
IAM機能でセキュリティ担保
HTTPだがトランザクション可能
VPC Lambdaが高速になったため、利用用途がなくなってきている
・Multi-Master Cluster
楽観的な同時実行制御
書き込み競合は発生する

# 所感、自身の仕事に活かせたことなど
インフラのセッションにメインで参加してきましたが、
初心者でも分かるように丁寧に説明してくれています。
インフラエンジニア初心者にもお勧めできるイベントかなと思います。
来年もぜひ参加したいイベントです。
自身の仕事に活かせたこととしては下記が挙げられます。
・CloudFormationをCLIで実行(deployコマンド --no-execute-changeset付き)
・DBのパスワードなどはSSMのパラメータストアで定義する
・cdk.jsonに環境差分を書く
・Python自動テストの利用（これは要検討）
[EC-CUBE4]cronによる定期実行処理

# 概要
EC-CUBEで定期実行処理を行う際のcronの設定を記載する。
行うことは以下の通り。
- cronで定期実行するCommand処理を作成
- crontabへの設定

**前提条件**
dockerでローカル開発環境が構築されていること。
[公式ドキュメント　Docker Composeを使用してインストールする](https://doc4.ec-cube.net/quickstart_install#docker-compose%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%97%E3%81%A6%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B)

# 1. 定期実行用のCommandファイルを作成

## 1-1.Customizeディレクトリ内に処理を実装

サンプルとして現在時刻をファイルに書き出す処理を記載する。
app/CustomizeフォルダにCommandフォルダを作成し、SampleCommand.phpファイルを作成する。
書き出し先のファイル：`app/Customize/Command/text.txt`

```app/Customize/Command/SampleCommand.php

<?php

namespace Customize\Command;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;

/**
 * sample cron.
 */
class SampleCommand extends Command
{
    protected static $defaultName = 'eccube:customize:sample';

    protected function execute(InputInterface $input, OutputInterface $output)
    {

        $file = "/var/www/html/app/Customize/Command/text.txt";
        $now = date('Y/m/d H:i:s');
        $text = $now ."\n";
        file_put_contents($file, $text, FILE_APPEND); 
        
    }
}
```
不要なコードがある気がするが、一旦はこれで。

## 1-2. 単体で実行処理をして確認

```
## dockerコンテナ内のbin/consoleを実行
$ docker container exec -it "コンテナ名" bin/console eccube:customize:sample
```

`app/Customize/Command/text.txt`　に現在時刻が書き出されていればOK。


# 2.cronの設定、開始

## 2-1. cronの設定

```
## コンテナ内に入る
$ docker container exec -it "コンテナ名"

## crontab -eを開く
root@xxxxx:/var/www/html # crontab -e

## エディタ内で以下を設定
## 毎分、eccube:customize:sampleを実行する
* * * * * /usr/local/bin/php  /var/www/html/bin/console eccube:customize:sample
```

・記述
<img width="602" alt="スクリーンショット 2020-02-20 21.42.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248644/c27f3150-398b-8b9f-7030-80bfdd98b857.png">


* crontab -eでエラーが発生した場合  

```
## エラー

### commandがない
root@xxxxx:/var/www/html# crontab -e
bash: crontab: command not found

### cronがインストールできない
# apt-get install cron
Reading package lists... Done
Building dependency tree
Reading state information... Done
E: Unable to locate package cron
```

docker環境内ではcronを実行する環境が整っていない可能性があるので、コンテナ内で以下のコマンドを実行する。
※本来はDockefileなどに記載しておくのがいいかも。

```
## crontab -e　が使えるように設定する
root@xxxxx:/var/www/html # apt-get update
root@xxxxx:/var/www/html # apt-get install cron
```

## 2-2. cronを開始

`service cron start`でcronを動かす。

```
root@xxxxx:/var/www/html# service cron start
[ ok ] Starting periodic command scheduler: cron.
```

cronの状態

```
## cronが動作している場合
root@xxxxx:/var/www/html# service cron status
[ ok ] cron is running.

## cronが動作していない
root@xxxxx:/var/www/html# service cron status
[FAIL] cron is not running ... failed!
```

## 結果表示

`app/Customize/Command/text.txt`ファイルに現在時刻が1分毎に追加されてくれば完了。

<img width="241" alt="スクリーンショット 2020-02-20 19.43.12.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/248644/d185a77b-e644-bdce-41b1-2fa3fc6c41a3.png">
複数テーブルに存在するカラムのi18n定義を共通化する

複数テーブルに共通して存在するカラム（ex. `created_at`, `updated_at`）を各テーブルで定義するのは冗長でめんどくさい。

```ruby:config/locales/translation_ja.yml

ja:
  activerecord:
    attributes:
      user:
        name: ユーザ名
        created_at: 登録日時
        updated_at: 更新日時
      event:
        name: イベント名
        created_at: 登録日時
        updated_at: 更新日時
```
		
こんな風に書かなくても、`ja/activerecord/attributes`ではなく、`ja`直下の`ja/attributes`で定義すれば使い回すことができる。

```ruby:config/locales/translation_ja.yml

ja:
  attributes:
    created_at: 登録日時
    updated_at: 更新日時
```

```ruby

<%= User.human_attribute_name(:created_at) %>

=> '登録日時'
```
flutterのInkwellでリップルエフェクトを実現しようとして詰まった

# Containerに色を付けたら、内部のInkwellの波紋表現が表示されなくなった

flutterの標準的なWidgetである"Container"。これのBoxDecorationを使えば、簡単にContainerの色や形を変えることが出来る。

```dart
Container(
   decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(10)
        ),
   child: Text("テスト文字列"),
)
```
![Screenshot_1582200738 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/d430d581-f652-7462-f4b5-e5c2c625f3f2.png)

InkWellはマテリアルコンポーネントの一つで、触ると波紋状のエフェクトが出る今風のデザインだ。

```dart

InkWell(
   child: Text("テスト文字列"),
   onTap:(){},
)
```
![Screenshot_1582201236 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/2276a20d-6b7c-870d-6650-585076ee97c5.png)

単体ではうまく機能したが、いざContainerにInkWellをぶち込んで見ると、なぜかRippleEffectが表示されない

```dart
Container(
   decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(10)
        ),
   child: InkWell(
          child: Text("テスト文字列"),
          onTap: (){},
   ),
)
```

どうやらリップルエフェクトを合成するとき、なぜか外側のContainerの色が優先されるらしい。

##解決法
###その1
BoxDecorationのBackgroundBlendModeを変更してみる


```dart

Container(
   decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(10),
          backgroundBlendMode: BlendMode.color,
        ),
   child: InkWell(
          child: Text("テスト文字列"),
          onTap: (){},
   ),
)
```

これはうまく行かない。一応波紋は出るが、さらに外側の背景の色も混ざってコンテナの色がおかしくなる。
![Screenshot_1582200767 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/bfab3760-5fb8-bbf6-fb40-8cb7de9997dd.png)

Container()をInk()に変える

```dart

Ink(
   decoration: BoxDecoration(
          color: Colors.blue,
          borderRadius: BorderRadius.circular(10),
        ),
   child: InkWell(
          child: Text("テスト文字列"),
          onTap: (){},
   ),
)
```

これでうまくいった。
![Screenshot_1582200936 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520648/59f766f0-cd7c-5db8-a98f-9f56e59ac0c5.png)

###その他
backgroundBlendModeはたくさん設定があるのでそれを使えば普通にうまく行った可能性はある。
でもめんどくさかったので……
Dockerインストール時のエラー【caskroom/cask was moved. Tap homebrew/cask-cask instead】の対処法


## 結論：エラーは無視でOK

少し前までは```brew install caskroom/cask/brew-cask```を実行する必要が合ったみたいですが、現在、2020年2月時点でははcaskはbrewに標準で組み込まれているため実行しなくても良いです。
無視して、下記のコマンドを入力しエンター。

```
brew cask install docker
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/568461/913a46fa-2803-045e-01d9-71e6a0da7345.png)


成功です。
OpenCsvでCsvBindByName指定で定義順に出力するには？

# はじめに

CSVフォーマットよく使うんですけど、実は罠が多いですよね。
なので自分でコーディングしないでライブラリを利用するのが大事なんですが、java用のopencsvを使うとヘッダに合わせてデータを読んでくれて便利なんです。
しかし、そのまま出力しようとすると、なんということでしょう。カラム名順にソートして出力してくれます。
世界中の人がそれで困っているようなのですが、簡潔に解決できましたので共有します。


## コード

```kotlin
inline fun <reified T : Any> writeCsv(filename: String, data: List<T>): Unit {
    FileWriter(filename).use { fileWriter ->
        StatefulBeanToCsvBuilder<T>(fileWriter)
            .withMappingStrategy(
                HeaderColumnNameMappingStrategy<T>()
                    .apply {
                        type = T::class.java
                        val headers = FieldUtils.getAllFields(type)
                            .map {
                                it.getAnnotation(CsvBindByName::class.java).column
                            }
                        setColumnOrderOnWrite(compareBy { headers.indexOf(it) })
                    })
            .build()
            .write(data)
    }
}
```

## 解説

HeaderColumnNameMappingStrategyが元のヘッダのカラム名でマッピングして読み込むためのものなのですが、実はそいつにsetColumnOrderOnWriteがいまして、それで出力順を変更できます。
しかし、文字列になってからなので文字列でしかこれだけだとソートできません。
なので、カラム名を定義順に取得しなおします。
その後、ソートを定義順にしてやれば出来上がりです。

## 参考リンク

https://stackoverflow.com/questions/45203867/opencsv-how-to-create-csv-file-from-pojo-with-custom-column-headers-and-custom
SQL Server:インデックスの変更を安全に行う方法

#背景
SQL Serverでは、インデックスにカラム追加をするコマンド用意されていません。
[ドキュメント](https://docs.microsoft.com/ja-jp/sql/relational-databases/indexes/modify-an-index?view=sql-server-ver15)にも、以下の記載があります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148310/d9f819d6-0dd3-51f2-b279-19130578578b.png)

したがって、

```sql
create index IX_Table1 on Table1 (
  col1,
  col2
)
```
上記のインデックスにcol3を追加したい場合は、以下のようにDROP+CREATEする必要があります。


```sql
drop index IX_Table1 on Table1

create index IX_Table1 on Table1 (
  col1,
  col2,
  col3
)
```

ただし、この方法だと一時的に必要なインデックスが無くなってしまいます。
そのため、プロダクション環境で大量にクエリ実行されている状況だとCPU負荷の高騰につながる危険性があります。

他の方法としては、インデックスを別名で作って、古いインデックスをDROPするという方法もあります。

```sql
create index IX_Table1_2 on Table1 (
  col1,
  col2,
  col3
)

drop index IX_Table1 on Table1
```
この方法だと、必要なインデックスが無くなることは無いため、一時的なパフォーマンス劣化は防ぐことができます。
ただし、インデックス名が変わってしまうため、ヒント句でインデックスを直接指定したクエリが実行されているとエラーになってしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/148310/26ed2146-1860-d9e2-5d3e-f535647d809d.png)

そのため、影響範囲の事前調査が必要となる場合があり、面倒です。

以下のように、最初の案を明示的なトランザクションで囲ってあげれば、インデックスヒントを使っていたとしてもエラーになることはありませんが、create indexが終わるまでブロックされ続けてしまいます。したがって、テーブルのレコードサイズが大きい場合はブロッキング時間が数分～数十分になってしまうこともありますのであまり良い方法とはいえません。

```sql
begin tran
  drop index IX_Table1 on Table1

  create index IX_Table1 on Table1 (
    col1,
    col2,
    col3
  )
commit tran
```


#解決方法

```sql
--まず、新しいインデックスを作成する
create index IX_Table1_2 on Table1 (
  col1,
  col2,
  col3
) with(online=on) --enterprise edition または sql database ならオンライン操作可能

--次に、同一トランザクション内で、不要インデックスのDROPと、新しいインデックスを同じ名前にrenameする処理を実施
begin tran
  drop index IX_Table1 on Table1
  exec sp_rename 'Table1.IX_Table1_2', 'IX_Table1'
commit tran
```
上記クエリだと、drop indexもsp_renameも、レコードサイズに関係なく一瞬で完了する処理のため、わずかな時間だけロックを保持するものの、インデックスの名前を同じに保ったまま、インデックスを構成するカラムを変更することができます。

※参考として、秒間300アクセス程度のテーブルに対して今回の方法を実施したところ、うまくいきました。
ただし、数秒以上かかるクエリでアクセスされているとブロッキングが発生する可能性が高いため注意が必要です。
だれもが複数（大量）の『csv・txt・cgi』を簡単に結合できる時代なのに…

>__だれもが大量の『csv・txt・cgi』を簡単に結合することができる時代なのに…
危うく手作業でコピペする所だった、、、__
>というお話です。

いきなりですが・・・

__"複数（大量）の『csv・txt・cgi』などのファイルを一つに集約したい！"__

って時ありますよね…？

>僕は、今日がまさしくその日でした、、、笑

そこで、今回は…

- __『csv・txt・cgi』などのファイルを一つに結合（集約）する方法__

についてまとめます。

__※本記事は、自分で学習したことのまとめ用として書いています。
尚、解説で誤った点があれば、スローして頂ければ喜んでキャッチしますのでお願い致します。__

##『csv・txt・cgi』などのファイルを一つに結合（集約）する方法

![businessman-2108029_1920.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255884/b240fccd-c2da-0588-729f-1faa24da560a.jpeg)


結論、`type`コマンドを使えば一発です！！

`type`コマンドの書式は、以下の通りです。

~~~
type *集約したいファイルの拡張子 > 保存するフォルダのパス\ファイル名
~~~

__おそらく、分かりづらいと思うので・・・__

__これから具体例も混ぜながら解説していきます。__

###【具体例】.cgiファイルの場合

今回は、具体例として…

- __Cドライブに『dataフォルダ』を作成__
- __『dataフォルダ』の中に、『convertフォルダ』と『cgiファイル一式』を格納__

の構成で解説していきます。

イメージとしては、下記のような構成です。

>Cドライブ
┣&ensp;data
&ensp;┣&ensp;convert
&ensp;┣&ensp;01.cgi
&ensp;┣&ensp;02.cgi
&ensp;┣&ensp;03.cgi

まずは、下記のコマンドで『dataフォルダ』に移動します。

~~~
cd c:\data
~~~

続いて、`type`コマンドでcgiファイルを一つに集約し、

その集約したファイルを『convertフォルダ』に`alldata.cgi`という名前で保存します。

~~~
type *.cgi > c:\data\convert\alldata.cgi
~~~

以上で、ファイルの集約は終了です。

簡単ですね！！！

###【疑問】拡張子が .csv や .txt の場合はどうするの…？

.csvや.txtの場合も同様に…

~~~
type *.csv > c:\data\convert\alldata.cgi
~~~

~~~
type *.txt > c:\data\convert\alldata.cgi
~~~

のコマンドで、ファイルを一つに集約することが可能です。

##まとめ｜基本のコマンド操作

![surfers-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/255884/1b6482ff-4297-6ccc-103c-e940f7fddac2.jpeg)


1. &ensp;Windowsの場合、コマンドプロンプトを起動
2. &ensp;コマンドプロンプトで`cd c:\data`を入力
3. &ensp;コマンドプロンプトで`type *.cgi > c:\data\convert\alldata.cgi`を入力
4. &ensp;convertフォルダに`alldata.cgi`が作成
Anacondaにモジュールをインストール（Mac）

# Anacondaにモジュールをインストール
※この記事はMacを対象にしています。
※例として、ortoolpyモジュールのインストールをとっています。他でも同じ。

## Anacondaにパスを通す
自分もそうでしたが、Anacondaのパスが通っていない場合、
コマンドプロンプトで"conda"と打っても反応してくれません。

別記事にAnacondaへのパスの通し方があったので、こちらを参照にして下さい。

リンクはこちら：[Anacondaのパスの設定](https://qiita.com/funabashi800/items/c13c4f742f43d9ebdd86)

##よし、condaを実行してモジュールのインストールだ！

しかしびっくり仰天

```
$ conda install ortoolpy
```

としても、

```
zsh: command not found: conda
```
となってしまう。

##解決方法
```
$ source ~/.bash_profile
```
を実行することで、解決しました。

```
$ pip install ortoolpy
```
これにてインストール完了です。
※condaコマンドも実行できましたが、pipでないとortoolpyはインストールできないモジュールであることが発覚しました。

##疑問点
最後pipでもインストールできるあたり謎です。
あと毎回

```
$ source ~/.bash_profile
```
とするのも面倒です。誰か良い方法を知っている方いたら教えて欲しいです、、、
Androidの画面分割と折りたたみでアクティビティの再生性が起こる

# 余談
(お急ぎの方はまとめまで飛ばしてください。)
目を疑った。
今、目の前で、`android:screenOrientation` を指定して画面回転を抑制しているActivityの画面回転が起きている。私は絶望に打ちひしがれながら、画面を回転させ続けた。

そもそもなぜこんな事になったのか？

ことの始まりは、targetSdkVersionを29にあげる上での調査だった。
https://developer.android.com/about/versions/10/behavior-changes-10?hl=ja
このドキュメントの中に `折りたたみ式のサポート`の項目がある。項目の中で `画面分割`についても触れられていた。
画面分割の機能は知っていたものの、個人端末がiPhoneなためほとんど利用していなかった。だからこれを期に、折りたたみと画面分割時の挙動を見てみることにしたのだ。その後に何が待ち受けているかも知らず・・・・

画面分割はAndroid7以降の端末であればどれでも利用できるため、すでにインストール済みのエミュレータで良かった。だが折りたたみについては、Foldableのエミュレータをインストールする必要がある。(Android Studio 3.5であれば利用可能)

インストールが終わり、私はエミュの画面をパキパキさせ始めた。
うん、実に可愛らしい挙動だ。折りたたみの度に伸びたり縮んだりするさまは見ていてとても癒やされる。
![Screenshot_1582160923.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589461/14432950-cb26-087b-9e01-0c81b309ec35.png)

パキパキしながら私はあることに気づいた。
`アクティビティが再生成されている？`

私は頭を抱えた。というのも、最近参画したプロジェクトのアプリは画面縦固定で、アクティビティの再生性を考えていない画面があってもおかしくない状況だったからだ。

ひとまず冷静になろう。私は自分に言い聞かせ、画面を分割した。

なんだと・・・？
今、アクティビティが再生成されなかったか？画面を分割しただけで！？
私は思わずonCreateの直後にブレークポイントを貼った。そしてすぐさまデバッグをかける。ビルドの時間が待ち遠しい。

ようやくビルドが終わり、画面を分割する。
やはり再生性されている。そして私はおもむろに、分割された画面をリサイズした。
半ば予想通りではあったが、ここでもアクティビティが再生成された。そこで私の頭の中に、ろくでもない考えが浮かんだ。
`この分割された画面を横にしたら、片方だけが回転するのか？`
考えを浮かべながら、私はゆっくりと画面を横に向ける。

目を疑った。
今、目の前で、`android:screenOrientation` を指定して画面回転を抑制しているActivityの画面回転が起きている。私は絶望に打ちひしがれながら、画面を回転させ続けた。
# まとめ
下記の状況ではアプリの設定関係なくアクティビティの再生性が起こります。
1. 画面分割時
2. 画面分割リサイズ時
3. 画面分割中の画面回転時(正方形の画面を除く)
4. 折りたたみ端末の折りたたみ時

Android10で公式の折りたたみサポートが始まりました。これからこれらの状況が増えていくことを考えると、未対策アプリは今のうちにどうするか考えておくのが良さそうです。
処理中にエラーが起こった際の対処と前後処理のデコレータ

とりあえず動いたので自分用メモ。そのうち編集するかも。

```python:test.py
class UseOnlyClass(object):

    def __init__(self, use_number1):
        self.use_number1 = use_number1

def wraper(func):

    def inner(main_inst):

        # 処理1
        use_only_class_inst = UseOnlyClass(main_inst.number1)

        # 処理2
        try:
            func(main_inst, use_only_class_inst)
        except Exception:
            last_output = 100
        else:
            last_output = use_only_class_inst.use_number1 + 1

        # 処理3
        return last_output

    return inner

class Selenium(object):

    def __init__(self, number1, number2):
        self.number1 = number1
        self.number2 = number2

        # この辺で接続処理(ログインなど)

    def stop_program(self, last_number):
        print(last_number)

class TargetSite(Selenium):

    def __init__(self, number1, number2):
        super().__init__(number1, number2)

    @wraper
    def update_something(self, use_only_class_inst):

        # この辺でスクレイピング

        # raise Exception

        # スクレイピング結果を元に値を計算する
        use_only_class_inst.use_number1 += 1 + self.number2

    @wraper
    def update_something_else(self, use_only_class_inst):

        # この辺でスクレイピング

        # raise Exception

        # スクレイピング結果を元に値を計算する
        use_only_class_inst.use_number1 += 2 + self.number2

main_inst = TargetSite(123, 456)
main_inst.stop_program(main_inst.update_something())

main_inst2 = TargetSite(123, 456)
main_inst2.stop_program(main_inst2.update_something_else())
```

やりたかったことは、
　・あるサイトにスクレイピングをかける
　・その処理前後でデータ処理をする
　　　・このデータは別クラスのオブジェクトとして持っておく
　・最後にprint文で処理後のデータを表示する
　・その関数実行中にエラーが起こった際の処理を行う

もう少し詳しく言うと大きく分けて3つ処理がある
　1. 別から呼ばれてきた値(上記の例だと123)を別クラスのメンバ変数化する
　2. この値を利用してスクレイピングをかける
　3. 1. の値と2. のスクレイピング結果により計算された値を出力する

UseOnlyClassとSeleniumクラスはどちらかがどちらかを継承していれば
もっと簡単に書けるのだが、現場の諸事情によりそれができない。

上記の例だと引数も2つだけになっているが現実にはもっと種類があり、
UseOnlyClassクラスのメンバ変数化して最終的に出力する値の計算に使いたいものもあれば、
TargetSiteクラスのメンバ変数だけにしておいて、サイト接続等にだけ使いたい値もある。
PowerShell(Core)でコマンドプロンプトを短く表示する例


`ドキュメント`フォルダ配下に`PowerShell`フォルダを作成し以下のファイルを作成する。

```Microsoft.PowerShell_profile.ps1
function prompt() {
    $Parent = Split-Path -Path (Split-Path -Path (Get-Location) -Parent) -Leaf
    $Leaf = Split-Path -Path (Get-Location) -Leaf
    "PS6:" + $Parent + "\" + $Leaf + "> "
}
```



コマンドのエイリアスを設定する例（おまけ）

```Microsoft.PowerShell_profile.ps1
Set-Alias -Name which -Value get-command
```
Windows Terminalでもmsys2を使おう

# はじめに

Windowsのデフォルトのconhost.exeのクソさに誰もが直面したことがあるだろう。そしてminttyやConEmuを使い始める人が出てくる。

もしくは最近だとVisual Studio Codeのターミナルが結構優秀なのでそれを使ったりしているかもしれない。これについては前に
[Visual Studio Code 15.1の統合シェルをMSYS2のbashにする](https://qiita.com/yumetodo/items/42132a1e8435504448aa)
という記事を書いた。

さて、Windows10がリリースされてもう随分たつが、ConPTY APIの導入、そしてWindows Terminalの実装開始とWindowsの端末環境に大きな変化が訪れようとしている。
https://github.com/microsoft/terminal
執筆現在まだ正式リリースはされていないが、かなり完成度が高くなってきていて、割と使い物になるレベルに達している。

さて、そんなWindows Terminalでmsys2のbashを使うにはどうすればいいのか。おもむろにググったがなんとまさかの日本語の文献がヒットしない。これは私が書くしかないのでは？

ちなみに似たような事例としてgit bashを使いたいという場合もあると思うのですが、それについては
[Windows Terminal で Git Bash を表示する](https://qiita.com/yokra9/items/bdd0882268b308cf22ca)
という記事がありました。

# 準備

すでにWindows Terminalはインストールされているものとする。

PowerShellをまず開いて

```powershell
> [guid]::NewGuid()
```

を実行する。これでGUIDが取得できる。

# 設定

Windows Terminalを開いて、<kbd>Ctl</kbd>+<kbd>,</kbd>して「JSONファイルを開く」を押下すると設定ファイルが開く。

`profiles`の項目に

```json
            {
                "colorScheme": "Tango Dark",
                "commandline": "cmd.exe /c \"set MSYSTEM=UCRT64&& set MSYS=winsymlinks:nativestrict&& C:/msys64/usr/bin/bash.exe --login\"",
                "font": 
                {
                    "face": "HackGen Console",
                    "size": 11
                },
                "guid": "{ada3a928-56a1-4bcf-b0e5-efb7c167a359}",
                "hidden": false,
                "icon": "C:\\msys64\\ucrt64.ico",
                "name": "MSYS2 UCRT64",
                "opacity": 84
            },
```

のように記述する。最初からPowerShellやらコマンドプロンプトの設定が記述されていると思うが、ここでの記述順がそのままメニューでの並びになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/3e367e0d-4cf6-9032-097a-44cff295cb1e.png)

## `opacity`

透過率設定。デフォルトでは透過しない。

## `colorScheme`

いくつかは既定のカラースキーマがあるほか、`schemes`のところに自分で追加することでそれを呼び出すこともできる。

https://github.com/NickSeagull/windows-terminal-monokai-night

こういうのとか。

## `commandline`

環境変数を設定するような項目はどうも見当たらないので`cmd.exe`の引数で頑張ることで実現する。
環境変数の意味は
[Visual Studio Code 15.1の統合シェルをMSYS2のbashにする](https://qiita.com/yumetodo/items/42132a1e8435504448aa)
でもみてほしい。

## `font.face`

多分省略できるし`DejaVu Sans Mono`とかとか好きなのを使えばいい。ちなみに例示した`HackGen`は
[【文字幅 半角3:全角5 も追加】Ricty を神フォントだと崇める僕が、フリーライセンスのプログラミングフォント「白源」を作った話](https://qiita.com/tawara_/items/374f3ca0a386fab8b305)
で紹介のあるフォントだ。

## `font.size`

フォントサイズ

## `guid`

**先程取得しておいたGUID**をここに書く。

ちなみに`defaultProfile`にここと同じGUIDを書けばそのプロファイルが規定になる。

# 動作例

(図は透過させてないものです)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/94177/809b6189-4ff7-29c2-16c3-396850adb405.png)

# 参考資料

- [Using MSYS2 in Windows Terminal · Issue #1684 · msys2/MSYS2-packages](https://github.com/msys2/MSYS2-packages/issues/1684)
- [Using Windows Terminal for MSYS2 · Issue #1669 · microsoft/terminal](https://github.com/microsoft/terminal/issues/1669)
- [Windows 10ミニTips(399) Windows Terminalにシェルを追加する | マイナビニュース](https://news.mynavi.jp/article/win10tips-399/)