OmniAICreator/Qiita-1.07M huggingface dataset:
WSL2 Dockerのイメージ・コンテナの格納先を変更したい (WSL2のvhdxファイルを移動させたい)

Docker Desktop backend WSL2 をインストールすると、docker-desktopとdocker-desktop-dataというふたつのディストリビューションが作成されます。

|ディストリビューション|役割|実体(デフォルト)|
|---|---|---|
|docker-desktop|Dockerを動かすためのエンジン|%LocalAppData%\Docker\wsl\data\ext4.vhdx|
|docker-desktop-data|イメージやコンテナを格納する|%LocalAppData%\Docker\wsl\distro\ext4.vhdx|

とくにdocker-desktop-dataについては、`docker pull`などを繰り返すたびにもりもり大きくなっていくため、`%LocalAppData%`に置いておきたくない、ドライブごと変えてしまいたいということが十分ありえます。

__そこで本記事ではdocker-desktopとdocker-desktop-dataの実体である`ext4.vhdx`を別の場所に移動させる方法については記述します。ここでは例として、docker-desktopの`ext4.vhdx`を`D:\wsl\docker-desktop`に、docker-desktop-dataの`ext4.vhdx`を`D:\wsl\docker-desktop-data`にそれぞれ移動させたいと思います。__

### 1. Docker Desktopの停止

タスクトレイのDockerマークを右クリックし、`Quit Docker Desktop`を押下する。

### 2. ディストリビューションのエクスポート

ディストリビューションをtarファイルにエクスポートする。

```
wsl --export docker-desktop docker-desktop.tar
wsl --export docker-desktop-data docker-desktop-data.tar
```

### 3. ディストリビューションの削除

ここでdocker-desktopとdocker-desktop-dataをいったん削除します。

```
wsl --unregister docker-desktop
wsl --unregister docker-desktop-data 
```

### 4. ディストリビューションのインポート

2.でエクスポートしたtarファイルを入力に、ディストリビューションの再インポートを行います。このとき、`ext4.vhdx`の移動先となるフォルダを必ず指定します。

```
wsl --import docker-desktop D:\wsl\docker-desktop docker-desktop.tar
wsl --import docker-desktop-data D:\wsl\docker-desktop-data docker-desktop-data.tar
```

### 5. Docker Desktopの起動

最後に任意の方法でDocker Desktopを起動させれば完了になります。

# 環境情報

- Dockerのバージョン:

```
C:\>docker version
Client: Docker Engine - Community
 Version:           19.03.8
 API version:       1.40
 Go version:        go1.12.17
 Git commit:        afacb8b
 Built:             Wed Mar 11 01:23:10 2020
 OS/Arch:           windows/amd64
 Experimental:      false

Server: Docker Engine - Community
 Engine:
  Version:          19.03.8
  API version:      1.40 (minimum version 1.12)
  Go version:       go1.12.17
  Git commit:       afacb8b
  Built:            Wed Mar 11 01:29:16 2020
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          v1.2.13
  GitCommit:        7ad184331fa3e55e52b890ea95e65ba581ae3429
 runc:
  Version:          1.0.0-rc10
  GitCommit:        dc9208a3303feef5b3839f4323d9beb36df0a9dd
 docker-init:
  Version:          0.18.0
  GitCommit:        fec3683
```

- Windowsのバージョン:

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/105859/65cc0ad4-785d-8006-8716-b7ec8dac151b.png)
call()を使うとthisをコントロールすることができる（ドラゴンボール編）

#thisのコントロール
[開眼！javascript](https://www.amazon.co.jp/dp/487311621X/ref=cm_sw_em_r_mt_dp_U_LiI7EbHAFQK36)を読んでて
thisとcallの動きについて知ったことがあり、書きますその2。
（※from 6章の6.5より。）

その1はこちら。
◼️[グローバルなとこで使うthisはまじでグローバル](https://qiita.com/naokikobashi/items/07b967312717a37e0c4a)


#thisレベル（thisに対する自分の理解感覚値）
関数とかの中でthis出てきたら「これ」の意味通り、その関数自体を指し示している、、、くらいの知識を持っていて、よくわかんなくなってもconsole.log()で中身見ればいいやくらいの理解度でした。
あとアロー関数の書き方くらいはわかるくらいの感じです！

#call()を使うとthisの生き方を決めれるぞ
どういう話かというと・・・

通常、「関数の中のthis」は、その関数自体を指し示します。
が、関数のcall()というものを使うと、任意の引数をthisの向き先に変えることができるぞ！というもの。

みんな大好きドラゴンボールの孫悟飯に例えます。
孫悟飯は子供の頃、学者になりたかったのですが、ピッコロに出会い、修行を受け、戦闘能力が上がり戦闘民族としての才能を開花させていきます。サイヤ人襲来編あたりの話です。


まず、「孫悟飯の情報を出力する無名関数」を作り、gohan変数に入れてみます。

```javascript:test.js

//gohan変数に、関数を入れる。
var gohan = function(a,b){
    this.life = a; //御飯の人生は引数a
    this.sentouryoku = b; //御飯の戦闘力は引数b
    console.log(this.life,this.sentouryoku) //御飯の人生と戦闘力を表示。
};

```

この関数ですが、受け取ったa、bの引数をもとに生活と戦闘力を決め、
gohan自体の情報を出力するというものです。
実際に、学者を目指してた子供自体の孫悟飯でやってみましょう。
初期のご飯の戦闘力は1ですね。ラディッツに切れた一発ぶちかましたあとがくんと戦闘力が下がるやつです。

```javascript:test.js

var gohan = function(a,b){
    this.life = a;
    this.sentouryoku = b;
    console.log(this.life,this.sentouryoku) 

};

gohan("学者",1);
//この結果は 学者 1 となります。

```

----------------------
###で、call()関数。
ここまでの内容を前提として、call()のなかのthisの扱いについてです。
これは、関数.call(a,b,c)とすると、その関数のthisの向き先を、「関数自体」ではなく、「a」にする、、、というものです。

わかりづらいので、とりあえず
孫悟飯の人生と戦闘力を、ピッコロに会うことで変えてみましょう。

#孫悟飯の人生をピッコロと会うことで変える

```javascript:test.js

//ピッコロオブジェクトを作る
var picoro = {} 

//この関数自体は同じです。
var gohan = function(a,b){
    this.life = a;
    this.sentouryoku = b;
    console.log(this.life,this.sentouryoku) 
};

//call関数。
gohan.call(picoro,"戦闘民族",2300);
//結果は、、、戦闘民族 2300

```

###何が起きたのか？

gohan.call(picoro,"戦闘民族",2300);

この記述の解説です。

先ほど書いたように、call関数は
一つ目の引数（つまりピッコロ）、を、this（孫悟飯の人生）の向き先にします。

**孫悟飯は、出会った人の影響で人生が変わるわけなので、
つまりピッコロオブジェクトの中に、御飯の情報が入るわけです。**

~~ここまで書いて少しこの例は違うなと気づき始めましたが、軌道修正も大変なのでこのまま行きます。~~

ピッコロオブジェクトに対して、つまりピッコロの人生の影響を受けて
御飯の人生もピッコロと同じようなものになったということです。
何を言ってるのかわからなくなってきましたが、どうあれこの結果は
戦闘民族 2300 とこうなります！

ちなみに、この記述の末尾に
console.log(picoro);
すると、きちんとピッコロオブジェクトの中身が出力されます。

赤字のとこ。
![Document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287983/f669609d-2cd6-a217-efc9-e40d7795ba3c.png)
ピッコロオブジェクトの中にきちんと御飯の人生が入ってますね。
やっぱりこの例はなんか違いますが、call()の動きはこういうものです！はい成功！


##捕捉
ちなみに、apply()
という関数も同じようなことができます。
違いとしては、applyでは、引数を配列で渡せる、というものです。

gohan.call(picoro,"戦闘民族",2300);

のところを

gohan.apply(picoro,["戦闘民族",2300]);

とできるということです。
※結果は同じになります。


・参考
[call関数](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/call)
Oculus IntegrationでHand Trackingを使えなかった場合の対処法

# 概要
Oculus Quest用のアプリでHand Trackingを使おうとしてOculus IntegrationをAsset Storeからimportしたところ、Hand Trackingの設定用の情報が一切表示されなかったので、自分がHand Trackingを使用できるようになるまでの方法を以下にまとめた。

# 環境
Unity: 2019.3.0f.3
Device: Oculus Quest
Oculus Integration: 17.0
# 手順
## 1. Oculus IntegrationをAsset Storeからではなく、 Unity Integration Archive pageからダウンロードする

なぜかは分からないが、Oculus IntegrationをAsset StoreからImportしようとするとHand Trackingなどの機能が一切ないAssetがダウンロードされる。
おそらく相当古いものがダウンロードされてしまう。
なので[Unity Integration Archive page](https://developer.oculus.com/downloads/package/unity-integration-archive/)からOculus Integrationをダウンロードする

## 2. Oculus IntegrationをUnityに取り込む

## 3. 以下のページを参考に、Unityの設定をOculus Quest用に変更する
[Unity＋Oculus Quest開発メモ](https://framesynthesis.jp/tech/unity/oculusquest/)
## 4. Oculus/VR/Scenes/HandTestのシーンを開く
このシーンがHnadTrackingを使用するためのテスト用のシーン。
完全に基本的な部分のみなので、これをそのまま使うか、ここのOVRCameraRigをPrefab化して、使いたいシーンに移植すれば動くはず
## 5. Oculus QuestでBuildを行う
問題なく動いていれば、自分はこれで動いた
値が確定されてから実行される遅延評価useEffect

株式会社ムラウチドットコムのフロントエンドエンジニアです。
ムラウチドットコムのOrganizationができて初めての投稿です。

今回はユーザーの入力で値が確定してから実行されるカスタム`useEffect`を考えたので紹介します。

### コード
```tsx
import React from "react";

export const useDelayedEffect = (
  effect: React.EffectCallback,
  deps?: React.DependencyList,
  delaytime: number = 1000,
) => {
  const [waiting, setWaiting] = React.useState(false);
  const timer = React.useRef<number>();

  React.useEffect(() => {
    window.clearTimeout(timer.current);

    setWaiting(true);

    timer.current = window.setTimeout(() => {
      setWaiting(false);
    }, delaytime);
  }, deps);

  React.useEffect(() => {
    if (!waiting) {
      effect();
    }
  }, [waiting]);
};

```

### 使い方

普通の`useEffect`の引数に加えて入力が確定したと判断するまでの`delaytime`を指定するだけです。

```tsx
import React from "react";
import { useDelayedEffect } from "./useDelayedEffect";

export const App = () => {
  const [text, setText] = React.useState("");
  const [confirmedText, setConfirmedText] = React.useState("");

  useDelayedEffect(
    () => {
      setConfirmedText(text);
    },
    [text],
    1500,
  );

  return (
    <div>
      <input onChange={e => setText(e.target.value)} value={text} />
      <p>{`text: ${text}`}</p>
      <p>{`confirmedText: ${confirmedText}`}</p>
    </div>
  );
};
```

![画面収録 2020-06-21 0.39.58.mov.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/299625/0902a932-c6ca-2948-111b-a8df775b5686.gif)


### 解説

入力完了を待っているかどうかの状態を`waiting`で保持します。
ひとつめの`useEffect`で`waiting`を`true`にして`delaytime`ミリ秒後に`waiting`を`false`にするタイマーをセットします。
`useEffect`は入力１文字１文字で実行されるので、その都度タイマーを解除して`delaytime`を測り直しています。
レンダリングのたびにカスタムフック関数が実行されるため、

```tsx
let timer;
// 中略
window.clearTimeout(timer);
// 中略
timer = window.setTimeout(() =>  setWaiting(false), delaytime);
```

では実装できないことに注意してください(毎回`timer`が初期化されるため)。`useRef`を用いることで再レンダリングされても参照できる変数を定義します。

ふたつめの`useEffect`で`waiting`が`true`から`false`になったとき、つまり入力が`delaytime`ミリ秒以上行われなかったときに引数`effect`関数を実行します。

### ユースケース

ユーザーの入力値を自動保存する場合などに利用できると思います。
通常の`useEffect`に保存のためのHTTPリクエストを仕込んでおくと、例えば "Hello world." を入力すると12回HTTP送信してしまいます。
そうではなくユーザーの入力が終わってから送信すれば無駄なHTTPリクエストをへらすことができます。

### まとめ

入力が確定してから実行される`useEffect`を紹介しました。
もっといい書き方やすでに実装されているライブラリ等あったらぜひおしえてください。

### 追記

この書き方で十分なことに気づいた！

```tsx
export function useDelayedEffect(
  effect: React.EffectCallback,
  deps: React.DependencyList,
  timeout: number = 1000,
) {
  useEffect(() => {
    const timeoutId = setTimeout(effect, timeout);

    return () => clearTimeout(timeoutId);
  }, deps);
}
```
PhpStormでのコード解析 ~InspectCode設定~

## 概要
PhpStormにあるコードチェック機能の「コード・インスペクション」を触ったので備忘録。

`※PhpStorm : JetBrainsが提供しているPHP用のIDE（統合開発環境）`

## 利用方法
- 上部メニューバーの「Code」 > 「Inspect Code...」
- ファイルやディレクトリを選択して右クリック > 「Inspect Code...」


## 設定内容
- Inspection scope
    - チェック範囲の指定
    - 下記の3項目から選択
        - Whole project （プロジェクト全体）
        - Directory '...XXX'　（指定されているディレクトリ配下）
        - Custom scope　（自身で登録したカスタム設定を使用）
- Inspection profile
    - チェック項目を指定
    - 特定言語やサービスのチェックを選択やカスタマイズ可能


### Custom scope
- ダイアログ左上部の「+」「-」でスコープ（チェック範囲）の設定を作成/削除できる
    - Name: スコープ名　（先述の Custom scope でプルダウン表示される）
    - Patten: スコープのパターンを記述　（下記のファイル表示でも指定可）
    - ファイル表示: ディレクトリ構成が表示されており、「Include」などのボタンで指定（上記のPattenにも連動される）


**Patten 設定**
簡単な指定方法を紹介

- 拡張子を指定
    - file[プロジェクト名]:xxx/*.php
    - プロジェクトのxxxディレクトリ配下にある.phpファイルを指定　（ディレクトリ直下以外も再帰的に指定）
- 再帰的にディレクトリ配下を全て指定
    - file[プロジェクト名]:xxx//*
    - / （ディレクトリ直下のみ指定）
    - // （ディレクトリ内を再帰的に指定）
    - 拡張子指定した場合は "/" で再帰的に指定するようです
- 除外指定
    - !file[プロジェクト名]:xxx//*.html
    - プロジェクトのxxxディレクトリ配下にあるHTMLファイルを除外
- 組み合わせ
    - AND指定 : &&
    - OR指定 : ||

## おまけ
プロジェクト全体のチェックではPCのメモリ使用や負荷が大きかっため機能毎に分割してチェックしました。
問題ないコーディングでも構文的なチェックでWarning出る可能性があるため、「Inspection profile」でチェック項目を変更するか、「インスペクションの抑止」のコメント追加で対処が可能です。


##参照
- コード・インスペクション
    - https://pleiades.io/help/phpstorm/code-inspection.html#gsc.tab=0
- スコープ
    - https://pleiades.io/help/phpstorm/settings-scopes.html
- インスペクションを無効にして抑制
    - https://pleiades.io/help/idea/disabling-and-enabling-inspections.html
Next.jsの環境変数の使い方の基本と、Vercelの環境変数との関係性について

Next.jsの公式サイト[Default Environment Variables](https://nextjs.org/docs/basic-features/environment-variables#default-environment-variables) を参考に、Next.jsの環境変数の取り扱い方法と、Vercel上の環境変数との関係性について調べ、ユースケースをまとめてみました。

## Next.jsの環境変数の取り扱い方法について

* 後述の通り、環境変数の設定ファイルに`XXXXX=Y`の形で環境変数を定義しておけば、プログラム中で`process.env.XXXXX` の形式で環境変数を参照できる。

* ただし、普通に環境変数を定義した場合、これらはブラウザ上からは見えないので(サーバーサイドで実行されるコードでのみ見える)、ブラウザ上で環境変数を使えるようにしたい場合(例えば、クライアントサイドでHTTP Requestを送信したい場合に環境変数を使いたい場合)には、環境変数名を`NEXT_PUBLIC_`で始めるようにすれば(ex. `NEXT_PUBLIC_XXXXX`)、クライアントサイドのJavaScript上から参照できる。

## .env系

### 特徴

リポジトリに含めても良い環境変数を書く。

### 各ファイルの特徴

- .env
    - すべての環境のデフォルト設定となる。

- .env.development
    - `next dev` で起動した際に使われる。
    - .env に優先する。

- .env.production
    - `next start` で起動した際に使われる。
    - .env に優先する。

## .env.local系

### 特徴

リポジトリに含めてはいけない環境変数を書く。(シークレット等)
リポジトリのトラッキング対象とはしない。

### 各ファイルの特徴

- .env.local
    - 上記の.env系のすべて(.env, .env.developmentもしくは.env.production)に優先する。

- .env.development.local
    - `next dev` で起動した際に使われる。
    - .env, .env.development, .env.local に優先する。

- .env.production.local
    - `next start` で起動した際に使われる。
    - .env, .env.production, .env.local に優先する。

## Next.jsでどこに何を記述すべきなのか

- .env
    - 環境に影響されない設定かつシークレット系ではない設定を記述。
        - ex. リージョン名とか
    - リポジトリでのトラッキング対象に含めるファイル。

- .env.{ENV}
    - 環境によって変わる設定かつシークレット系ではない設定を記述。
        - ex. バケット名とか
    - リポジトリでのトラッキング対象に含めるファイル。

- .env.local
    - 環境に影響されない設定かつシークレット系の設定を記述。
        - ex. 環境に左右されない接続情報とか
    - **リポジトリでのトラッキング対象に含めてはいけないファイル。**
    - *この情報をVercel上に管理する画面はないので、このファイルは使わずに冗長的に.env.{ENV}.localに書くのも一つの手。*

- .env.{ENV}.local
    - 環境によって変わる設定かつシークレット系の設定を記述。
        - ex. 環境ごとのアクセスキーとか
    - **リポジトリでのトラッキング対象に含めてはいけないファイル。**

## Next.jsの各環境変数ファイルの優先度

- **.env.{ENV}.local > .env.local > .env.{ENV} > .env** となる。

- つまり、全てのファイルに環境変数を定義した場合には、.env.{ENV}.localの値が使われることになる。

## Vercel上の環境変数とVercelコマンドについて

- Vercel上では、Next.jsで設定した環境変数ファイル(.env, .env.production, .env.development)がそのまま使用される。
    - **.env.developmentで設定された環境変数は、Previewで使用される。**

- .env.{ENV}.localで設定していた環境変数は、GUI上で、Production用、Preview/Development用にそれぞれ設定できるので、画面から普通にセットすればよい。
    - **ただし、環境によらないシークレットを保存する方法がVercelにはないので、.env.localの情報をVercelでは設定できない。**

- Vercel上でDevelopment環境変数を設定している場合、`vercel env pull [ファイル名。デフォルトは.env]` で、指定したファイル名、もしくは.envにdevelopment系の環境変数を引き抜くことができる。
    - 上述の通り、.env.local を管理する方法がVercelにはないので、.local.envを使っている場合にはその内容もpullされてくることになる。

- 上記のNext.jsの環境変数のスタンダードとして、シークレット系は.localに書くのがいいので、もしVercel上に環境変数を設定していたら、`vercel env pull .env.local` で環境変数を引き抜きが良いかな・・・。

## 参考

[Default Environment Variables](https://nextjs.org/docs/basic-features/environment-variables#default-environment-variables)
Jetson Xavier NX の動作モード

Jetson Xavier NX の動作モードをメモとして残します。

# 各動作モード

- POWER_MODEL ID=0

```
$ sudo nvpmodel -m 0
$ sudo nvpmodel -q 
NV Power Mode: MODE_15W_2CORE
```

- POWER_MODEL ID=1

```
$ sudo nvpmodel -m 1
$ sudo nvpmodel -q 
NV Power Mode: MODE_15W_4CORE
```

- POWER_MODEL ID=2

```
$ sudo nvpmodel -m 2
$ sudo nvpmodel -q 
NV Power Mode: MODE_15W_6CORE
```

- POWER_MODEL ID=3

```
$ sudo nvpmodel -m 3
$ sudo nvpmodel -q 
NV Power Mode: MODE_10W_2CORE
```

- POWER_MODEL ID=4

```
$ sudo nvpmodel -m 4
$ sudo nvpmodel -q 
NV Power Mode: MODE_10W4CORE
```

# 参考
https://developer.nvidia.com/embedded/jetson-xavier-nx
https://www.aaeon.com/jp/p/aaeon-nvidia-ai-solutions-embedded-box-pc-nvidia-xavier-nx#
Raspberry Pi 3をアクセスポイントとする

無線LAN搭載のRaspberry Pi 3を無線LANのアクセスポイントとしてみる。
APで割り当てるIPはプライベートIPアドレスならなんでも良いが、今回は10.0.1.1/24を使う。

[公式の説明](https://www.raspberrypi.org/documentation/configuration/wireless/access-point-routed.md)にしたがって作業する。

# 必要なもの
- 無線LAN搭載のRaspberry Pi
- hostapd
- dnsmasq
- netfilter

# インストール
- apt install hostapd dnsmasq netfilter-persistent iptables-persistent

# hostapd
IPアドレスを割り振るdaemonであるhostapdを起動できるようにする
sudo systemctl unmask hostapd
sudo systemctl enable hostapd

# portforwardingを有効に
echo net.ipv4.ip_forward=1 >>  /etc/sysctl.d/routed-ap.conf

# IP MASQUERADE
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
IPマスカレードを有効にする。
netfilter-persistent save
これで
/etc/iptables/rules.v4 に設定が保存される。


# dhcpcd.conf
/etc/dhcpcpd.confを編集する
interface wlan0
static ip_address=10.0.1.1/24
nohook wpa_supplicant


# dnsmasq
mv /etc/dnsmasq.conf /etc/dnsmasq.conf.orig
vi /etc/dnsmasq.conf

interface=wlan0
dhcp-range=10.0.1.50,10.0.1.100,24h
domain=wlan
address=/gw.wlan/10.0.1.1

# hostapd.conf
vi /etc/hostapd/hostapd.conf

country_code=JP
interface=wlan0
ssid=Pi3AP
ieee80211n=1
hw_mode=g
channel=7
macaddr_acl=0
auth_algs=1
ignore_broadcast_ssid=0
wpa=2
wpa_passphrase=raspberry
wpa_key_mgmt=WPA-PSK
wpa_pairwise=TKIP
rsn_pairwise=CCMP

以上でrebootすればアクセスポイントが利用可能となり、Internet接続もできる。
AWS基礎

#前提
AWS（ブログシステム構築）について学んだことを書いていきます。

#本題
#DBを用いたブログシステムの構築
NATゲートウェイ構築後、プライベートサブネットに配置されたDBサーバーに、各種ソフトウェアをインストールできるようになった。
MariaDBをインストールし、データベースを構成したり、WebサーバーにWordPressをインストールしたりし、ブログシステム構築を行う。

##内容
WebサーバーにWordPressをインストールし、ブログシステムを構築する。
ブログのデータはDBサーバー上のMariaDBに保存する。

１、DBサーバーの構成
DBサーバーにMariaDBをインストールし、WordPressからデータを保存できるようデータベースを作成。

２、WebサーバーにWordPressをインストール

３、WordPressを初期設定

※MySQLとMariaDB
WordPressで利用できるデータベースサーバーは、MySQLかMariaDB。
MariaDBはMySQLの開発者が枝分かれし開発し始めたオープンソースの互換データベース。
AmazonLinux２には、MySQLではなくMariaDBがパッケージとして含まれている。

##DBサーバーにMariaDBをインストール
まずは、DBサーバーにMariaDBをインストールし、データベースサーバーとして使えるように設定。

###MariaDBインストール
yumコマンドを使ってインストールする。
Webサーバーを踏み台にDBサーバーにログインした状態で下記のコマンドを入力。

```
$ sudo yum -y install mariaDB-server
```
NATゲートウェイを経由し、ダウンロードが始まりMariaDBがインストールできる。

###MariaDBの起動と初期設定
インストール後、MariaDBを起動する。
下記のコマンドを入力。

```
$ sudo systemctl start mariadb
```
次にMariaDBの管理者パスワードを設定。
管理者は「root」というユーザー。
次のようにmysqladminコマンドを実行すると管理者であるrootユーザーのパスワードを変更できる。
設定したパスワードは以降、rootユーザーで操作する際に尋ねられるため忘れないようにする。
※MariaDBのrootユーザーとLinuxシステムのrootユーザーは、異なるユーザー。
MariaDBは、Linuxシステムのユーザーアカウントではなく、独自のユーザーアカウントを用いる。

```
$ mysqladmin -u root password
```

###WordPress用のデータベースを作成
WordPressで利用するデータベースを作成。
下記のようにmysqlコマンドを実行し、rootユーザーでMariaDBに接続する。
この時、先に設定したパスワードが求められる。

```
$ mysql -u root -p
```
すると、ウェルカムメッセージが表示された後

```
MariaDB[none]>
```
のようにMariaDBのコマンドプロンプトが表示される。
ここでSQLを実行することで、データベースの各種操作ができる。
まずは、データベースを作成するため、下記のように入力。
vue.js firebase 環境構築 (os x)

vue.js firebase 環境構築についてのメモです。

#環境確認
中途半端な環境になっているかもしれないので確認をする
ターミナルで 各コマンドの状況を確認する

## node バージョン確認と削除
v10 以外の場合 firebase でエラーとなるので削除する必要がある  

```
node -v
v10.20.1
```

## brew でインストールした node の削除 

```
brew uninstall --ignore-dependencies node
```
## nodebrew　でインストールしている場合の削除方法

```
nodebrew -v
sudo npm uninstall npm -g
```
### 周辺ファイルの削除
```
sudo rm -rf ~/.npm
rm -rf ~/node_modules
```

参考
[Macのnodebrewで入れたnode, npmをクリーンアップ](https://qiita.com/_am_/items/d3866698e0ab3bea01b3)

# nodebrew の インストール
nodeバージョンを選択してインストールできる nodebrew を導入する。

```
brew install nodebrew
```

環境変数を追加

```
echo 'export PATH=$PATH:~/.nodebrew/current/bin/' >> ~/.bashrc
source ~/.bash_profile
```

nodebrew バージョン確認とセットアップ

```
nodebrew -v
nodebrew setup
```

# v10系の node.js を nodebrew でインストールする

```
nodebrew ls-all
nodebrew install v10.15.0
nodebrew use v10.15.0
```

# nodeバージョン確認

```
node -v
v10.15.0
```

# firebase Cli をインストールする

[Firebase CLI リファレンス](https://firebase.google.com/docs/cli?hl=ja) を参考にインストールする

```
npm install -g firebase-tools
```

ここまでの設定で　環境構築　は終わったはずなので、次はプロジェクトを作成してみましょう。

# firebase コンソールでプロジェクトを登録する
[firebaseコンソール](https://console.firebase.google.com/?hl=ja)

# firebase Cli で プロジェクトを初期化する

```
mkdir sample01
firebase login
firebase init
作ったプロジェクトを指定して hosting を有効にする
```

# firebase  デプロイしてみる

```
firebase deploy
```

# vue cli をインストールする

```
npm install -g @vue/cli
```

# vue cli でプロジェクトを作る

```
cd [firebaseのプロジェクト ディレクトリ]
vue create vue-app
```

vue で作ったプロジェクトを実行してみる

```
cd vue-app
npm run serve
```

ブラウザで http://localhost:8080/ をアクセスするとサンプルが表示されます。

# vue で作ったプロジェクトをビルド

```
npm run build
```

`./dist` ディレクトリが生成されるこのディレクトリを firebase hosting 先として指定する

# firebase.json の修正
hosting のディレクトリを `public` から `vue-app/dist` ディレクトリに修正する

```
{
  "hosting": {
    "public": "vue-app/dist",
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  },
...
```

修正したらデプロイしてみる

```
firebase deploy
```
reduceとmap

備忘録として残します

```javascript

// reduceは引数で渡された関数を実行し単一の結果を返す

const test = [1,2,3];

const total = test.reduce((acc,cur) => {
  return acc + cur;
})

// accに実行結果が蓄積されていく

console.log(total);

// 結果　６

// mapは配列を返す　

const double = test.map((num) => {
  return num * 2;
})

console.log(double);

// 結果　[2,4,6]

```
gh-pagesでnpm run deployすると「fatal: could not read Username for 'https://github.com': Invalid argument」というエラーが出る

## あらすじ

[skytomo221.github.io](https://skytomo221.github.io/) にGatsbyでポートフォリオを作ろうと思って、
[ここのサイト](https://www.gatsbyjs.org/docs/how-gatsby-works-with-github-pages/#installing-the-gh-pages-package)を参考に、gh-pagesを使って`npm run deploy`しようとしたところ、「`fatal: could not read Username for 'https://github.com': Invalid argument`」というエラーが出た。

## どんな感じでエラーが出たか

```terminal
$ npm run deploy

> cara@0.1.7 deploy D:\skytomo\skytomo221.github.io
> gatsby build && gh-pages -d public -b master

success open and validate gatsby-configs - 0.160s
success load plugins - 1.500s
...（省略）...
Generated public/sw.js, which will precache 9 files, totaling 317400 bytes.
success onPostBuild - 0.554s
info Done building in 31.231 sec
Fatal: HttpRequestException encountered.
bash: /dev/tty: No such device or address
error: failed to execute prompt script (exit code 1)
fatal: could not read Username for 'https://github.com': Invalid argument

npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! cara@0.1.7 deploy: `gatsby build && gh-pages -d public -b master`
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the cara@0.1.7 deploy script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.
...（以下略）
```

色なしだと分かりにくいかもなので画像バージョンも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196882/5d6217dd-646d-1543-0275-3038abdc02fd.png)

## 対処法

[GitHub PagesにReactアプリをデプロイする方法](https://qiita.com/yuitnnn/items/11375ea29ec023d19fdf#%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%AB%E5%A4%B1%E6%95%97%E3%81%97%E3%81%9F)に書かれていた解決方法

```
$ rm -rf node_modules
$ npm install
$ npm run deploy
```

上記の方法で解決できない場合、さらに、

```
git config --global credential.helper wincred
```

をしてみましょう。
[fatal: could not read Username for 'https://github.com': No error #230](https://github.com/tschaub/gh-pages/issues/230)に書かれていた方法です。
私はこれで解決しました。
グローバルなとこで使うthisはまじでグローバル

#はー！！そうなのね！
[開眼！javascript](https://www.amazon.co.jp/dp/487311621X/ref=cm_sw_em_r_mt_dp_U_LiI7EbHAFQK36)を読んでて
はー！！そうなのね！
と、グローバルなthisについて知ったことがあり、書きますその１。
（※from 6章の6.3より。）

#thisレベル（thisに対する自分の理解感覚値）
関数とかの中でthis出てきたら「これ」の意味通り、その関数自体を指し示している、、、くらいの知識を持っていて、よくわかんなくなってもconsole.log()で中身見ればいいやくらいの理解度でした。
あとアロー関数の書き方くらいはわかるくらいの感じです！

#グローバルなとこで使うthisはまじでグローバル

どういうことか？というと、、

例えば関数とか変数とかなんもしてないとこでthisを出力してみる。
他に何もスクリプト書いてない状態でconsole.log(this)ってやってみるということです。
なんも決まってない世界のthisってなんぞや？ってなりますよね。自分はなってました。

どうなるかというと「ここ」、ってなことで世界全体を指し示します。
つまり（？）windowです。ブラウザの一番上の要素。

```javascript:test.js
console.log(this);

//結果
//Window
//<default properties>
//<prototype>: WindowPrototype { … }
//.......


```

[公式ドキュメント](https://developer.mozilla.org/ja/docs/Web/API/Window)では、

>Window インターフェイスは、 DOM 文書を収めるウィンドウを表します。

ということで、一番上の世界です。
太郎くんの家に行って「ここ」といえば太郎くんちの情報になりますけど、
誰の家でもない場所で「ここ」といえばどこでもないこの世界全体を指し示すということになります。

なので、この同じ世界で
var pan = "choko";
とかしてこの世界にパンの変数を作ってあげる（グローバル変数）と、
log見るとちゃんと追加されてこうなります。


```javascript:test.js

var pan = "choko";
console.log(this);

//結果
//Window​
//pan: "choko" これが追加された！
//<default properties>
//<prototype>: WindowPrototype { … }

```

はーなるほど！
グローバル変数とかグローバルではない変数はしっていたけど、thisにおいても同じような考え方ができるんだなと思いました。
PHP for文を用いて配列に配列を確認する

# 目的

- for文を用いて全く同じ配列データをさらに配列に格納する方法を下記に記載する

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.5) |
| ハードウェア | MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) |
| プロセッサ | 2 GHz クアッドコアIntel Core i5 |
| メモリ | 32 GB 3733 MHz LPDDR4 |
| グラフィックス | Intel Iris Plus Graphics 1536 MB |

- ソフトウェア環境

- 処理の確認下記のサイトでブラウザ上で確認した。
    - [https://paiza.io/ja/projects/new](https://paiza.io/ja/projects/new)

# コードの例

- `["test01", "test02", "test03"]`という配列さらに配列`$main_array`に10回格納するコードを下記に記載する。

    ```php
    $i = 0;

    for ($i = 1; $i <= 10; $i++){                
        $main_array[] = [
            "test01",
            "test02",
            "test03",
        ];
    }

    var_dump($main_array);
    ```
- 上記コードの実行結果を下記に記載する。

    ```php
    array(10) {
      [0]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [1]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [2]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [3]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [4]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [5]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [6]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [7]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [8]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
      [9]=>
      array(3) {
        [0]=>
        string(6) "test01"
        [1]=>
        string(6) "test02"
        [2]=>
        string(6) "test03"
      }
    }
    ```
Rubyでアルゴリズムを実装する:Day 4 -線形探索-

３日坊主を脱却して４日も続きました。
３日目はこちら<[Rubyでアルゴリズムを実装する:Day 3 -二分探索-](https://qiita.com/Atarubift/items/640abe8c8f873c23aee5)>

# 線形探索とは
ランダムなデータを最初から一つずつ比べて特定の値を見つけていく方法。
見つかったらそこで処理を終了する。
とーっても簡単なアルゴリズムだ
仕組みがわかったら即コーディングに移ろう

# linerSearch.rb

## コード
```rb
# 線形探索

def linerSearch(data, target)
  bool = -1
  count = 0
  while count <= data.length
    if data[count] == target
      bool = count
      break
    end
    count += 1
  end
  bool
end

# 実行
print "格納する値："
data = gets.split().map(&:to_i)
print "探す値："
target = gets.to_i
search = linerSearch(data, target)

if search >= 0
  puts "#{target}は#{search+1}番目に見つかりました。"
else
  puts "#{target}は見つかりませんでした。"
end
```

linerSearchは数字が格納された配列と探す値を引数に取る。
配列の位置を示すcountが配列の大きさを超えるまでループ
データが見つかればboolにその時の配列の場所を代入してループ終了。
見つからなければboolは-1を返す。

出力は見つかれば見つかった場所。見つからなければ見つからなかった旨を出力する。

# 最後に
やっぱり昨日にに比べたらとても簡単だった
ただ、イメージできているものをイメージ通りに実装するのって難しいなって思ったりもする

さて、次回は再帰でもっとも有名なハノイの塔をやってみるか。。。
Ruby で gRPC クライアントを実装する

gRPC のクライアントを Ruby で実装する手順を備忘も兼ねて書いておく

# まずは gem を入れる
- Ruby で gRPC を利用するために `grpc` gem をインストール
    - これを入れることで、クライアントの実装に必要な class 群を利用できるようになる

```Gemfile
gem 'grpc', '~> X.XX.X'
```

# .proto ファイルの取得とコンパイル
- .protoファイルの管理方法はいくつかあるが、詳細は[こちらの記事](https://qiita.com/RyotaNakaya/items/d71d2cb5f5cd44b052ee)を参照
- .proto を rb ファイルにコンパイルするには `grpc_tools` という Gem を利用する

```
$ gem install grpc-tools
```

- コンパイルのコマンドは以下のような感じ

```bash
$ grpc_tools_ruby_protoc -I ./proto \--ruby_out=lib --grpc_out=lib ./proto/hoge_proto/*.proto
```

- `-I` オプションで .proto ファイルを探索するディレクトリを指定
- `--ruby_out` オプションで、コンパイル後の出力先ディレクトリを指定
    - どこでもいいんだけど /lib が多いらしい
- `--grpc_out` オプションの第一引数にはコンパイル後の stub となる class ファイルの出力先を、第二引数にはコンパイル対象の .proto ファイルのあるディレクトリを指定
- コンパイルが成功すると、各 proto に対応する pb.rb ファイルと、それらを全てインポートしてmodule化した hoge_services_pb.rb ファイルが生成される
    - 　この hoge_services_pb.rb に rpc メソッドの定義と Stub の定義があり、呼び出しにはこの class を利用していく形になる

# クライアントスタブの実装
上記で準備は整ったので、ここから実際に実装していく。
まずは gRPC コールを行うために必要なスタブインスタンスを作成する。
スタブインスタンスの作成に関しては、/initializer 配下にファイルを作って、そこで new するというやり方もよく見るけど、グローバル変数に突っ込むのも嫌だったので、今回は model クラスを切ってシングルトンパターンを適用する方向で実装。
正直この辺のベストプラクティスはまだ模索中。

```model/grpc/hoge_service_client.rb
require 'proto/hoge_services_pb'
require 'singleton'

# ここは環境ごとに設定ファイルから取ってくる作りにした方が良い
END_POINT = "localhost:50051"

class Grpc::HogeServiceClient
  include Singleton

  attr_reader :stub

  def initialize
    @stub = HogeProto::HogeService::Stub.new(END_POINT, :this_channel_is_insecure)
  end
end
```

- Stubインスタンス作成の部分は、上記にも書いたように hoge_services_pb.rb に記載がある Stub を new してインスタンスを作成している
    - new の第一引数は gRPC サーバーのエンドポイントを指定
    - 第二引数は、rpc 通信時の暗号化用の引数で、ちゃんと運用する場合はSSL証明書のパスなどを指定することになる

# 実際に gRPC サーバーをコールする
上記で作成した Stub を使って実際に rpcコールしてみる

```grpc/hoge.rb
class Grpc::Hoge
  def get_name(params)
    # Stub インスタンスを腹持ちするmodelのインスタンスを作成
    client = Grpc::HogeServiceClient.instance
    # rpc コールに必要なリクエストデータを作成
    req = get_name_request(params)
    # 必要があればメタデータも作成
    meta = Hash.new
    meta["x-app-id"] = "hogeghoge"
    meta["x-app-password"] = "fugafuga"

    begin
      # ここで rpc コール
      client.stub.get_name(req, {metadata: meta})
      res = "success"
    rescue GRPC::BadStatus => ex
      res = "error"
    rescue ex
      res = "unexpected error"
    end

    res
  end

  private

  def get_name_request(params)
    HogeProto::GetNameRequest.new(
      id: params[:id]
    )
  end
```

- `client.stub.get_name` の部分で rpc コールしている
    - この呼び出しの結果がエラー(Status.Codes が OK ではない)の場合、exceptionが発生するので begin で囲んで エラーの場合は rescue するようにする
- `meta` に関しては、gRPC コール時のメタデータのセットをしている
    - ここではIDとパスワードをセットしているが、共通で必要なものは stub を作る model 側でインスタンス変数としてイニシャライズした方が良さそう
    - これは普通に Hash 形式で値をセットすれば良いらしい
    - ただし、キーには大文字が使えないっぽいので注意

# エラーハンドリングについて
先ほども書いたが、rpc呼び出しでエラーステータスのレスポンスが返ってきた場合、`GRPC::BadStatus` class の例外が発生する。
なので、必ず begin~rescue する必要がある。
また、サーバー側が error_details を詰めて返してきた場合は、それを取り出すための実装も必要になる。
参考：https://www.rubydoc.info/gems/grpc/GRPC/BadStatus
CentOS7でyumレポジトリサーバを構築したい

# はじめに
ローカルで仮想マシンを構築するとき、```yum update```などで時間がかかるのでローカルにyumレポジトリを構築したいと思います。

# 実行環境
OS : CentOS 7

# インストール
```bash
#yum install -y  httpd createrepo rsync
```

# webサーバの設定
```bash
#systemctl start httpd
#systemctl enable httpd
#firewall-cmd --zone=public --add-service=http --permanent
#firewall-cmd --reload
#echo '<directory "/var/www/html/centos">' > /etc/httpd/conf.d/centos-mirror.conf
#echo 'option +indexes' >> /etc/httpd/conf.d/centos-mirror.conf
#echo '</directory>' >> /etc/httpd/conf.d/centos-mirror.conf
```

# ディレクトリ作成
```bash
#mkdir -p /var/www/html/centos/7/{os,updates,extras}/x86_64
```

# レポジトリ作成
```bash
#rsync -rtpv --delete rsync://ftp.riken.jp/centos/7/os/ /var/www/html/centos/7/os/
#rsync -rtpv --delete rsync://ftp.riken.jp/centos/7/updates/ /var/www/html/centos/7/updates/
#rsync -rtpv --delete rsync://ftp.riken.jp/centos/7/extras/ /var/www/html/centos/7/extras/
```

# おまけ
今回作成したディレクトリのサイズを確認してみました。

```bash
#du -sh /var/www/html/*
22G /var/www/html/centos
```

# おわりに
思いのほか簡単にレポジトリサーバを構築できたので良かったです。
【Ubuntu 20.04環境】Ubuntu上でWindows FX（Linux FX）のLive USBを作成する手順

今回はUbuntu上でWindows FXのLive USBを作成する手順を紹介したいと思います。

## Windows FXとは？
Windows FX（Linux FX）とは、Windows10にすごく似ているLinuxディストリビューションです。スタートボタンのロゴまでほぼ本家と似ていて壁紙もほぼ同じというのだから驚きですね。

## 環境
Ubuntu 20.04 LTS

## ダウンロード
以下のサイトから、ダウンロードしましょう。
[【ダウンロードリンク】Linuxfx / Windowsfx (x86/64 Pc)](https://sourceforge.net/projects/linuxfxdevil/)

## Live USBを作成する手順
### 1. USB Creator（※）をインストールする
USB Creator（※）をインストールします。以下のコマンドを打って下さい。

```
sudo apt-get install usb-creator-gtk
```
※本来はUSB CreatorはUbuntu上でUbuntuのISOファイルのLive USBを作成するためのパッケージです。ですが、Windows FXでも使えます。

### 2. USBメモリを挿す
USBメモリを挿しましょう。

### 3.USB Creatorの起動
以下のコマンドを打って、USB Creatorを起動しましょう。

```
usb-creator-gtk
```

### 4. ISOイメージとUSBメモリを選択する
先程ダウンロードしたWindows FXのISOファイルを選択しましょう。その後、USBメモリを選択しましょう。

### 5. ブータブルUSBの作成をクリックする
ブータブルUSBの作成をクリックします。しばらく時間がかかるので待ちましょう。

### 6. 100%になったら終了
100%になったらLive USBの完成で終了です。Ubuntuがうんぬんかんぬんとかメッセージウインドウが出ますが、気にしないで閉じて下さい。お疲れ様でした。

## 参照
[UbuntuのブートUSB作成 (usb-creator を使用)](https://qiita.com/K-Kachi/items/3e461b10846eee6539cd)
VisualStudio2019 C++ 空のプロジェクトで C++17を使う

#空のC++プロジェクト作成

VisualStudio2019 C++ 空のプロジェクトで 

で C++17 機能の インライン変数を実装してみる

https://cpprefjp.github.io/lang/cpp17/inline_variables.html

![Microsoft Visual Studio 2020-06-20 21.49.00_C++空のプロジェクト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/67b9a07c-8745-fd13-de54-26324e1af17c.png)
#静的エラー！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/9074cbbb-f798-a1ce-4735-a47d83eae60a.png)

<FONT SIZE=6><B><font color="red">$\huge{デフォルトではC++17ビルドになっていないのですね・・・}$</font></B></FONT>

コピペで直ぐに確認したい方はこちら

```cpp:cpp17.cpp
#include<iostream>
#include<memory>
using namespace std;
class Foo
{
public:
	static inline int foo;
};

int main()
{
	Foo::foo = 123;
	cout << Foo::foo  << endl;
}

```
#C++17ビルド の設定方法

設定変更します。
<B> ソリューションエキスプローラーのプロジェクトを右クリック（※ソリューションでは無い）</B>
<B> プロパティ ＞ C++言語標準 を<font color="red"> ISO C++17 標準 (std:c++17) </font> に変更して OK で決定 </B>

・・・以下動画を参考に。※プロパティが動画では切れてて見えませんが、一番下です。

設定後、静的エラーが消えるのが分かります。![C++17inlineHENSUU.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/c8710d39-a1f0-8564-16dc-692db28575f8.gif)



サンプルは変数に値を入れるだけのもの。見た目は何もない。これで無事、ビルドが通ります。
目標設定

# 目標
　プログラミング学習における当面の目標は良質なポートフォリオをつくり、web系自社開発企業さんに転職することと定めて学習していきます。
## なぜ自社開発企業なのか
　私は去年の12月ごろにプログラミング学習をはじめ、今年1月から5月までCodecampGateというオンラインスクールに通っていました。卒業後はスクールで制作したECサイトに毛が生えた程度のポートフォリオを引っ提げて転職活動をしていたわけですが、当然ながらweb系の企業さんには相手にされません。

　そんな中、先日SES系の企業から内定をいただきました。そこで改めて本当に自分がやりたいことは何なのかを考えた結果、
**「エンジニアとしてのキャリアの最初から思いっきり開発に携わってなるべく早く成長し、所属する企業や社会に貢献できるようになりたい」**そう考えたのです。
　したがって、

- 最初から開発の経験を積める可能性が高い
- 社員数が少なければサービスの企画からリリースまで一貫して携わることができる
- 与えられた要件通りに開発するだけでなく、自分の頭で考えてサービスを改善していける

そんな、社員数の少ない自社開発企業さんが理想の転職先であると考え、それに向けて必死で勉強しようと決意しました。

#学習予定の技術
　以下を学習していく予定です。

- コンピュータサイエンス基礎
- Linux基礎
- HTML&CSS
- JavaScript
- PHP基礎
- SQL基礎
- Git&GitHub基礎
- Laravel基礎
- AWS
- Docker
- CircleCI

これまでで学習してきたものについてもざっと復習する予定です。

参考
[Railsでポートフォリオを作るまでの学習順序と具体的な教材について](https://youtu.be/8UtQPtxbXF0)
[ポートフォリオにAWSとDockerとCircleCIを組み込むための学習順序と教材について](https://youtu.be/LT-dXBUnZdI)

今後学習の過程で得た知見を投稿していきます！
WP User Frontend 翻訳ファイルの作成

## はじめに

WP User Frontend（ https://wedevs.com/wp-user-frontend-pro ）はWordPressでコミュニティーサイトをローコストで開発可能にしてくれるプラグインです。
ただし、日本語対応しておらず、出力されるテキストもプラグイン設定画面ですべてが変更できるわけではないため、開発者自身で翻訳作業をする必要があります。
すでに翻訳済みのファイルを提供してくれている方（ https://booth.pm/ja/items/856575 ）もいますが、細かい文言はサイトのトンマナにあわせて変更していく必要があり、であれば最初から自身で翻訳ファイルを用意したほうがのちのちの更新性は保てるのではと考えています。

## 翻訳ファイル生成方法

### POEDITの導入
有償ですが、POEDIT（ https://poedit.net ）を購入すると大変便利です。
WordPress向けに.mo .po ファイルの自動生成機能も有しており、翻訳も3種類のサービスが用意されています。

- google 翻訳（月額ver）
- deepl（月額ver）
- microsoft翻訳 （買い切りver）

購入方法によって差はありますが、最終的に自主編集することを踏まえるとどれでも十分かと思います。

### POEDITでプラグインディレクトリを選択
「WordPressのテーマ・プラグインを翻訳」から「WP User Frontend」ディレクトリを選択。
<img width="1076" alt="スクリーンショット 2020-06-20 23.20.04.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253436/527f9abe-c5e2-d3fc-add7-4a8e1fd49d1b.png">
以上で

- wp-user-frontend-ja.mo
- wp-user-frontend-ja.po

上記2ファイルが生成され、翻訳上問題が発生した箇所にはアラートがでますので、必要に応じて調整し上書き保存。

### サーバアップロード
生成された.po .moファイルをサーバに展開すれば、以上となります。
実際は翻訳が適応されたページで日本語翻訳文章を見るたびに、サイトにあわせた文言調整を繰り返していく必要がありますので、適宜POEDITで編集しアップロードさせる作業をループしていくことになります。
時計の作り方～React HPより～

[ReactのHP](https://ja.reactjs.org/)では，チュートリアルなど様様な情報を提供しています．
その中で，メインコンセプトとして，「stateとライフサイクル」というページで時計を作っているのですが，見ても書いてもよくわからないので，登場するコードについてまとめてみます．
# 完成形
HPに書いてある以下のコードを書くと，こんな感じのリアルタイムで時間が表示される時計が作れます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634450/0326b81b-1aa2-8aac-bee0-af521186ca72.png)

~~~jsx
class Clock extends React.Component {
  constructor(props) {
    super(props);
    this.state = {date: new Date()};
  }

  componentDidMount() {
    this.timerID = setInterval(
      () => this.tick(),
      1000
    );
  }

  componentWillUnmount() {
    clearInterval(this.timerID);
  }

  tick() {
    this.setState({
      date: new Date()
    });
  }

  render() {
    return (
      <div>
        <h1>Hello, world!</h1>
        <h2>It is {this.state.date.toLocaleTimeString()}.</h2>
      </div>
    );
  }
}

ReactDOM.render(
  <Clock />,
  document.getElementById('root')
);
~~~

# わからないこと
上記のコードでよくわからなかった，以下を調べてみました
## toLocaleTimeString
Dateオブジェクトメソッドの一つ
※日付や時間の取得や設定を行うオブジェクト

toLocaleTimeStringは地域情報に従って時刻部分を文字列で取得するメソッド
同様に，文字列変換のメソッドをいかにまとめる

書式|意味
---|---
toDateString|日付部分を文字列で取得
toTimeString|時間部分を文字列で取得
toLocaleDateString|地域情報に従って日付部分を文字列で取得
toLocaleTimeString|地域情報に従って時刻部分を文字列で取得
toString|日付を文字列で取得

## componentDidMountとcomponentWillUnmount
ライフサイクルメソッドの一つそうです．

#####ライフサイクルメソッドってなんやねん

たくさん書いてあるコードにも，実行する順番があるらしいです．
ライフサイクルメソッドとは，処理過程の特定の時点でコードを実行するためのメソッドのことです．
この処理過程とメソッドの関係は↓の図のようになるそうです．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634450/e06e8915-f194-e38c-2753-3417d026f8d1.png)

この関係を見ると，今までよくわからずに書いていたcontructorやrenderの意味が分かりますね

##conponentDidMount
ComponentがMountされた後に実行されるメソッドで，主な用途は以下です．
・Ajaxを使ったデータフェッチを行う(初回)
・DOMに対する処理を行う(初回)
・タイマーをセットする
・イベントリスナのセット

今回のコードは，タイマーをセットしているですね．

一度設定したら，componentWillUnmount()で解除することを忘れない

##componentWillUnmount
componentがUnmountされる時に実行される．主な用途は以下です．
・タイマーを解除する
・イベントリスナを解除する
・非同期処置を中止する

## setInterval
一定時間が経過するごとに処理を実行するメソッドです．
書き方は，`setInterval(関数,処理間隔)`
ここにおける処理間隔の単位はミリ秒です．

今回のコードでは，1秒ごとに`()=>this.tick()`を実行していることが分かりますね．

つまり，
####同じ時間で止まらずに，更新し続けている
のはこのメソッドのおかげなんですね．

## clearInterval
setInterval()でセットしたタイマーを解除するメソッドです．
書き方は，`clearInterval(止めたいタイマーID)`


#参考
[React HP](https://ja.reactjs.org/)
[JavaScript入門講座](http://javascript.pc-users.net/builtin/date/)
[React Componentライフサイクルひとめぐり](https://iktakahiro.hatenablog.com/entry/2018/05/28/123000)
[【JavaScript入門】setIntervalの使い方まとめ](https://www.sejuku.net/blog/24425)
Laravel7 make:xxx コマンドを作ってひな形ファイルを生成する

プロジェクト特有のクラスのひな形を生成するコマンドを作りたいという要望がよく上がります。
そんな時のためにコマンドを自作する手順をご紹介します。

既存のテンプレートをカスタマイズしたい場合は下記の記事をご覧ください。

- [Laravel7 makeコマンドのひな形ファイルをカスタマイズする](https://qiita.com/ucan-lab/items/eab7d869359b5fa72ba0)

## 手順

```shell-session
$ php artisan make:command UseCaseMakeCommand
```

`app/Console/Commands/UseCaseMakeCommand.php` ファイルが生成されます。

### app/Console/Commands/UseCaseMakeCommand.php

```php:app/Console/Commands/UseCaseMakeCommand.php
<?php declare(strict_types=1);

namespace App\Console\Commands;

use Illuminate\Console\GeneratorCommand as Command;

class UseCaseMakeCommand extends Command
{
    /**
     * The console command name.
     *
     * @var string
     */
    protected $name = 'make:usecase';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Create a new UseCase class';

    /**
     * The type of class being generated.
     *
     * @var string
     */
    protected $type = 'UseCase';

    /**
     * Get the stub file for the generator.
     *
     * @return string
     */
    protected function getStub()
    {
        return $this->laravel->basePath(trim('/stubs/usecase.stub', '/'));
    }

    /**
     * Get the default namespace for the class.
     *
     * @param  string  $rootNamespace
     * @return string
     */
    protected function getDefaultNamespace($rootNamespace)
    {
        return $rootNamespace . '\UseCase';
    }
}
```

### stubs/usecase.stub

```php:stubs/usecase.stub
<?php declare(strict_types=1);

namespace {{ namespace }};

final class {{ class }}
{
    /**
     * Create a new usecase instance.
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the usecase command.
     */
    public function handle()
    {
        //
    }
}
```

## 使い方

```shell-session
$ php artisan make:usecase User/SampleUseCase
```

`app/UseCase/User/SampleUseCase.php` ファイルが生成されます。

```php:app/UseCase/User/SampleUseCase.php
<?php declare(strict_types=1);

namespace App\UseCase\User;

final class SampleUseCase
{
    /**
     * Create a new usecase instance.
     */
    public function __construct()
    {
        //
    }

    /**
     * Execute the usecase command.
     */
    public function handle()
    {
        //
    }
}
```

## 参考

- https://laravel.com/api/7.x/Illuminate/Console/GeneratorCommand.html
Golang - Dockerfileの最小構成

# Dockerfile

本番環境で動くGoアプリのためのミニマルdockerfileを記す。

- 実行ファイルが、軽量でセキュアなscratchイメージ上で動く
- go.modとgo.sumに従って、バージョン込みの依存パッケージをインストールする
- 依存パッケージに変更がなければ、再ビルド時のインストールにはキャッシュが使われる

```dockerfile:dockerfile
FROM golang:1.14.4 as builder

WORKDIR /go/src

COPY go.mod go.sum ./
RUN go mod download

COPY ./main.go  ./

ARG CGO_ENABLED=0
ARG GOOS=linux
ARG GOARCH=amd64
RUN go build \
	-o /go/bin/main \
	-ldflags '-s -w'


FROM scratch as runner

COPY --from=builder /go/bin/main /app/main

ENTRYPOINT ["/app/main"]
```

# 補足

```dockerfile:レイヤー1
FROM golang:1.14.4 as builder
```
ベースイメージには、golangのバージョン 1.14.4 を使いbuilderと名付けた。
後で[マルチステージビルド](https://docs.docker.com/develop/develop-images/multistage-build/)を利用して、実行ファイルをより軽量なベースイメージに移す。
本番環境で動くアプリはイメージサイズが小さく、かつ、セキュリティホールが少ないイメージが好まれる。

--

```dockerfile:レイヤー2
WORKDIR /go/src
```
/go/srcで活動することを宣言。

--

```dockerfile:レイヤー3
COPY go.mod go.sum ./
```
 go.mod と go.sum をWORKDIRにCOPY。
[ベストプラクティス](http://docs.docker.jp/engine/userguide/eng-image/dockerfile_best-practice.html#id6)では、ADDではなくCOPYがを推奨されているのでCOPYを採用した。

--

```dockerfile:レイヤー4
RUN go mod download
```
`go mod download`が go.mod と go.sum に従って正確にパッケージをダウンロードしてくれる。
 go.mod と go.sum が以前ビルドしたイメージから変更が無ければ、このレイヤーの処理に対してキャッシュを使って高速に処理される。

--

```dockerfile:レイヤー5
COPY ./main.go  ./
```
main.goを、イメージ内のWORKDIRにCOPY。
今回はmain.goというファイル一つだけをCOPYしているが、依存パッケージがあればそれらもCOPYする。
この辺りは不必要なものは.dockerignoreで指定して、`COPY . ./`で必要なものを一気にCOPYするなどの工夫で楽にしても良い。

--

```dockerfile:レイヤー6
ARG CGO_ENABLED=0
```
CGO＿ENABLEDを0に設定。
Goはコンパイル時に、CGOを使ってC言語のライブラリを使うように設定する事ができる。
しかし、scratchイメージにはこのライブラリは用意されていない。
よって、今回はC言語のライブラリを使って欲しく無いので、CGO＿ENABLEDを0にしてこの機能をOFFにした。

--

```dockerfile:レイヤー7
ARG GOOS=linux
```
GOOS=linuxを設定。
Goはクロスコンパイルを採用していて、実行環境を指定できる。
今回はscratchイメージで動かすので、linuxを宣言した。

--

```dockerfile:レイヤー8
ARG GOARCH=amd64
```
GOARCH=amd64を設定
amdの64Bitを宣言した。

--

```dockerfile:レイヤー9
RUN go build \
    -o /go/bin/main \
    -ldflags '-s -w'
```
アプリのビルド。

オプションに関して

- -o /go/bin/main: 実行ファイルを/go/binの中にmainという名前で作成する
- -ldflags '-s -w': 実行ファイルにアプリの動作に関係ないものを入れないためのオプションを付与

--

```dockerfile:レイヤー10
FROM scratch as runner
```
本番環境でのベースイメージを用意し、runnerと名付けた。

--

```dockerfile:レイヤー11
COPY --from=builder /go/bin/main /app/main
```
builderイメージの/go/bin/mainを、runnerの/app/mainにCOPYした。

--

```dockerfile:レイヤー12
ENTRYPOINT ["/app/main"]
```
このdockerイメージを起動したときのエントリーポイントを指定。
古いRaspberryPiにWifiアダプターを付ける

先日、RasPi4が発売され無線LAN搭載は当たり前となっているが、手元にある古いRasPiを活用してみる。

# 使用した物
- Raspberry Pi Model B+ v1.2
- エレコムのWDC-150SU2MBK　アマゾンで710円だった。
- 16GBのMicroSDカード
- 作業はMacOSで行った。

# Raspberry Pi OSのinstall
- これまでRaspbianと呼んでいたRaspberry Pi用のdebian派生linuxはRaspberry Pi OSとなった。
[公式サイト](https://www.raspberrypi.org/downloads/)
から入手できる。
- MacOS用のImagerを入手し、MicroSDカードにRaspberry Pi OS　→　Otherで32bit liteを書き込む。
- sshが使えるようにする。
    - 書き込みが終了したMicroSDカードを一度Macから取り外す。
    - 再び差し込むと /Volumes/boot というディスクがマウントされる。
    - ターミナルアプリで`touch /Volumes/boot/ssh`
    - /Volumes/bootディスクを取り出す
 
# Raspberry Piを起動
- とりあえず、有線LANに接続しておいてMicroSDカードを差し込んで起動。
- 自宅の有線LANではdhcpで192.168.1.100以降が割り振られる。
- netstat -nr | grep 192.168.1として増えたIP addressにあたりをつけ
- ssh pi@192.168.1.126 とsshでloginを試みる。
- defaultのパスワード raspberry で無事login

# Debian 10 "Buster"
- uname -a は
Linux raspberrypi 4.19.118+ #1311 Mon Apr 27 14:16:15 BST 2020 armv6l GNU/Linux
となっている。
- ifconfigすると　eth0, loに加えて wlan0が出来ている。
- lsusbでは　Bus 001 Device 004: ID 056e:4008 Elecom Co., Ltd 　と認識されている。
- lsmodするとRealTek8188のドライバ r8188euが認められる。

# raspi-config
- とりあえず sudo apt update, sudo apt upgrade
- raspi-configで　user piのpassword変更、Timezoneの変更、無線LANの国指定をするが問題発生
- 無線LANの国を指定しようとすると"Could not communicate with wpa_supplicant"とエラーになる。

# wpa_supplicant
- ps ax|grep wpaで調べてみると
`   295 ?        Ss     0:00 /sbin/wpa_supplicant -u -s -O /run/wpa_supplicant` 
となっている。

- 無線LAN搭載のRaspberry Pi 3 Model Bで試すと、wpa_supplicantは

`  333 ?        Ss     0:00 /sbin/wpa_supplicant -u -s -O /run/wpa_supplicant
  414 ?        Ss     0:00 wpa_supplicant -B -c/etc/wpa_supplicant/wpa_supplicant.conf -iwlan0 -Dnl80211,wext`
と起動している。

# rc.localに登録
Raspberry Pi起動時にwpa_supplicantが立ち上がるように rc.localのexitの前に
`/sbin/wpa_supplicant -D nl80211,wext -c /etc/wpa_supplicant/wpa_supplicant.conf -i wlan0`
を追加してreboot
これでraspi-configで無線LANの国指定のエラーはなくなる。

# 無線LANに接続
- 無線LANもdhcpでip振っている。
- iwlist scan|grep SSID
で使用可能な無線LANの一覧がわかる。
- SSIDが hoge 、WPA2パーソナルのパスフレーズが hogehogeの場合

`wpa_passphrase hoge hogehoge >> /etc/wpa_supplicant/wpa_supplicant.conf`
とする。

# wpa_supplicant.conf
SSIDとパスフレーズを追加した/etc/wpa_supplicant/wpa_supplicant.confは

`ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=JP
network={
	ssid="hoge"
	#psk="hogehoge"
	psk=**************************************************
}`
となっている。
平文のパスフレーズの行は消しておく。

# dhcpcpd.conf
無線LANに接続できるようになっている（はず）なので
dhcpでIPアドレスを振ってもらうように/etc/dhcpcd.confを編集する。
echo wlan0 >> /etc/dhcpcd.conf

リブートすればwlan0にIPアドレスが割り当てられている。
OpenShift 4.4 Container Image Registry

# TL;DR
OpenShift 4.3 BaremetalインストールではOpenShift Image Registryのデフォルト値が`Removed`になっており、自分で構成しなくては使えない状態になっているため、構成する方法を記載。

※4.2では`Managed`だったためインストール後のタスクとして手順を踏まないと`oc get clusteroperators`の結果が`AVAILABLE=True`にならないので気づきやすかった

## 手順
ここではStorageClassに`EnptyDir`を使う。

1. `system:admin`またはそれに準ずるユーザでログインする
2. image regesitryのストレージを`emptyDir`に変更する。
`oc patch configs.imageregistry.operator.openshift.io cluster --type merge --patch '{"spec":{"storage":{"emptyDir":{}}}}'`  
3. `config/cluster`の`managementState`を変更する

```
apiVersion: imageregistry.operator.openshift.io/v1
kind: Config
metadata:
[...]
spec:
  defaultRoute: false
  disableRedirect: false
  logging: 2
  managementState: Managed
[...]
```
4. `image-registry-operator`が変更を検知しimage registry Podが自動的に作成する

```
$ oc get pod -n openshift-image-registry
NAME                                              READY   STATUS    RESTARTS   AGE
cluster-image-registry-operator-d66bdbff7-b7rw5   2/2     Running   0          22d
image-registry-c9d4d966d-84nxs                    1/1     Running   0          13m
node-ca-7vhts                                     1/1     Running   0          13m
node-ca-8dlkm                                     1/1     Running   0          13m
node-ca-9tcnl                                     1/1     Running   0          13m
node-ca-b7jwb                                     1/1     Running   0          13m
node-ca-c7747                                     1/1     Running   0          13m
node-ca-kh8b6                                     1/1     Running   0          13m

```

## Link
https://docs.openshift.com/container-platform/4.4/registry/configuring-registry-operator.html#configuring-registry-operator

https://docs.openshift.com/container-platform/4.4/registry/configuring-registry-operator.html#image-registry-on-bare-metal-vsphere
バージョニングを有効にしたS3で、オブジェクトを一気に削除したい

Amazon S3でバケットを削除するには、バケットの中身を空にする必要があります。

ですが、バージョニングを有効にしたバケットの場合は、単純にオブジェクトを削除するだけではなく、全バージョンのオブジェクトを削除する必要があります。

```shell
$ aws s3api delete-bucket --bucket [your-bucket-name]

An error occurred (BucketNotEmpty) when calling the DeleteBucket operation: The bucket you tried to delete is not empty. You must delete all versions in the bucket.
```

本当にずっと持っていたいバケットなら困らないんですけど、テスト目的で作ったバケットとかだと削除したい場合に面倒になります…。

[バージョニングを有効にした S3 バケットの削除方法](https://tech.xeres.jp/2018/12/13/how-to-delete-s3-bucket-versioning-enabled/)

で、`aws s3api list-object-versions --bucket [your-bucket-name]`でバケット内にあるオブジェクトのバージョンが取得できるようなので、これを利用してPerl One Linerを書いてみました。

```shell
## [your-bucket-name]が 2箇所 にあるので、バケット名に置き換えてください
$ aws s3api list-object-versions --bucket [your-bucket-name] | \
  grep -E '"(Key|VersionId)"' | \
  perl -wp -e 's!.+("Key".+)\r?\n!$1!' | \
  perl -wp -e 's!"Key": "(.+)", + "VersionId": "(.+)",!aws s3api delete-object --bucket [your-bucket-name] --key $1 --version-id $2!'
```

実行すると、こんな感じでAWS CLIを使ったコマンドが生成されます。

```shell
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
aws s3api delete-object --bucket [your-bucket-name] --key [object-key] --version-id [object-version-id]
```

あとは、これをコンソールに貼り付けて実行するなり、そのまま実行するなりすればよいと思います。

なにも考えずに、そのまま全部消してしまう場合は、こんな感じで。

```shell
## [your-bucket-name]が 2箇所 にあるので、バケット名に置き換えてください
$ aws s3api list-object-versions --bucket [your-bucket-name] | \
  grep -E '"(Key|VersionId)"' | \
  perl -wp -e 's!.+("Key".+)\r?\n!$1!' | \
  perl -wp -e 's!"Key": "(.+)", + "VersionId": "(.+)",!aws s3api delete-object --bucket [your-bucket-name] --key $1 --version-id $2!' | \
  perl -wp -e 'system($_)'
```

削除したいキーを絞りたい場合は、`grep`を間に挟んでもよいでしょう。

と、自分自身でこの記事の内容を何度も使っているうちに面倒になったので、シェルスクリプトにしました。

```shell:/usr/local/bin/truncate-versioned-s3-bucket 
#!/bin/bash

for BUCKET_NAME in "$@"
do
    aws s3api list-object-versions --bucket ${BUCKET_NAME} |   grep -E '"(Key|VersionId)"' |   perl -wp -e 's!.+("Key".+)\r?\n!$1!' |   perl -wp -e 's!"Key": "(.+)", + "VersionId": "(.+)",!aws s3api delete-object --bucket '${BUCKET_NAME}' --key $1 --version-id $2!' |   perl -wp -e 'system($_)'
done
```

実行権限を付与して

```shell
$ sudo chmod a+x /usr/local/bin/truncate-versioned-s3-bucket
```

バケット名を指定して実行します（複数バケット指定可）。

```shell
$ truncate-versioned-s3-bucket [bucket-name] [bucket-name] [bucket-name]...
```