OmniAICreator/Qiita-1.07M huggingface dataset:
pandasで今日の日付を追加する

結構、前に困ったやつ
メモしておこう

```py
import pandas as pd
import datetime
import pytz

today = datetime.datetime.now(pytz.timezone('Asia/Tokyo'))
today = today.strftime('%Y-%m-%d')

# これでもいけなくはない
# today = f'{today.year}-{str(today.month).zfill(2)}-{str(today.day).zfill(2)}'
df['update_date'] = pd.to_datetime(today)
```
【未経験】ソフトウェア開発手法をざっくりと説明

## どんな記事？
ウォーターフォール型・アジャイル型などの言葉を耳にしたことはあるけどなんのことかさっぱりだったので、調べると開発手法の種類でした。せっかくなのでソフトウェアの開発手法を色々しらべてみて概要はつかめたのでまとめていきたいと思います。

## 記事の対象
新卒一年目のwebエンジニアのアウトプット用。
知識レベルが同じくらいの方に向けた知識共有です。

## 開発の一般的な流れ
開発の基本的な流れはこのようになってます。

* 要件定義
* 設計
* 開発
* テスト
* リリース(納品)
* 運用

## 開発手法一覧と概要
### 1.ウォーターフォール型開発
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288580/0f2f631c-a879-c132-3a97-2a66bce09b40.png)

ウォーターフォール型開発は明確な計画の元、上述した開発の流れを順番に進めていく開発手法です。
#### 特徴...しっかりと計画・遅い
* 要件定義 → 開発 → ... の様に順番に工程を進めていく
* 下流から上流には戻らない前提(前の工程にはもどらない)で工程ごとに品質チェックを行う。
* メリット：最初からしっかりと設計がされていればその通り作ればよい(人に依らない)
* デメリット：仕様変更に弱い(負担が大きい)

### 2.アジャイル型開発
![グループ 16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288580/a444ff29-88fb-b35c-37b2-99e227dc21e2.jpeg)

アジャイル型開発は機能単位で上述した開発の流れを繰り返し行う開発手法です。

#### 特徴...最初は仕様をかっちりと決めない・速い、機能ごとにリリース
* 要件定義・設計・開発・テストのサイクルを機能ごとに行い細かくリリースしていく
* テスト・検証を機能ごとに行って問題があれば要件定義に戻る
* メリット：仕様変更に強い(素早く対応)為、ユーザーの意見も取り入れやすい
* デメリット：開発の方向性がぶれやすい

### 3.スパイラル型開発
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288580/5dfe03d8-a2c1-df37-0296-0cbece81ba34.png)

スパイラル型開発はアジャイル開発に似た開発手法ですが、システム全体を都度設計しなおしていくモデルになっています。

#### 特徴...仕様はざっくり、繰り返して全体の品質を高める
* 要件定義・設計・開発・テストのサイクルをシステム全体で繰り返す
* プロトタイプ(試作)を機能ごとに作って依頼者に確認をとり、そのフィードバックを元に次の工程(また設計)に移る
* アジャイルは品質が保証されている機能を都度リリースするのに対し、スパイラルはフィードバックを反映して最後に品質が保証されているシステムを完成させる
* メリット：仕様変更に強い(素早く対応)為、ユーザー・依頼者の意見が取り入れやすい。手戻りが楽
* デメリット：開発の方向性がぶれやすい、開発コスト(プロトタイプ等)が大きくなりがち
【WebSocket対応】Nginxのリバースプロキシを使ったSymbolノードのSSL/TLS接続

SymbolノードをHTTPS化する方法はいくつかありますが、今回はNginxのリバースプロキシを使って実現していきたいと思います。
元はhttp-portalでやっていたのですが、権限周りとかでメンテが大変なので完全にノードと分離する方法をとりました。

## 環境

- Ubuntu 20.04LTS
- Symbol-bootstrap v1.0.7で構築したノード


## 前提条件

- Symbolノード構築済みであること
- ドメインを取得し、ノードのHOSTとして設定していること(VPS等で提供されている逆引きDNSでも可)


## 証明書の取得

Let's Encryptを利用して無償で証明書を取得します。

### Let's Encrypt導入

```sh
sudo apt update -y && sudo apt upgrade -y
sudo apt install letsencrypt -y
```

### 証明書取得

1. ファイアウォールの設定で80番ポートを開けておく
1. すでにNginxなど80番ポートを使用しているプロセスがあれば一旦停止する。
1. 下記コマンドで証明書を取得する

```sh:bash
sudo letsencrypt certonly --standalone -d {ドメイン}
# Enter email address (used for... と聞かれるのでメールアドレスを入力してEnter
# Please read the Terms of Service at... と聞かれるので、規約に同意する場合は"A"と入力してEnter
# その後、メルマガ配信の可否を聞かれるので "Y"または"N"を入力してEnter
```

正常に取得できると、以下の場所にファイルが格納されている。

```
/etc/letsencrypt/live/{ドメイン}/fullchain.pem
/etc/letsencrypt/live/{ドメイン}/privkey.pem
```

※手順2.でプロせスを停止していた場合は再開しておｋ

## Nginxの設定

### Nginx導入

```sh:bash
sudo apt install nginx -y
```

### 設定ファイルを作成

※エディタはもちろんお好みで

```sh:bash
vim /etc/nginx/conf.d/symbol.conf
```

### 設定内容を入力

```nginx:symbol.conf
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}

server{
    listen       3001 ssl;
    server_name    {ドメイン};

    proxy_http_version 1.1;
    proxy_set_header    Host    $host;
    proxy_set_header    X-Real-IP    $remote_addr;
    proxy_set_header    X-Forwarded-Host       $host;
    proxy_set_header    X-Forwarded-Server    $host;
    proxy_set_header    X-Forwarded-For    $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    ssl_certificate /etc/letsencrypt/live/{ドメイン}/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/{ドメイン}/privkey.pem;
	
    location / {
        proxy_pass    http://localhost:3000/;
    }
}
```

### 設定内容のテスト

```sh:bash
sudo nginx -t
# エラーがなければ正しく設定がなされている
```

### Nginx起動

```sh:bash
sudo systemctl start nginx
```

## ノードを再起動

この手順を実施してる際にノードが止まってしまう事があるのでその場合は再起動する

```sh:targetディレクトリがある場所で
symbol-bootstrap stop
symbol-bootstrap run -d

# ノードを再起動した場合、nginxも再起動する
sudo systemctl restart nginx
```

## 証明書の自動更新設定

Let's Encryptで取得した証明書は90日間で有効期限が切れてしまうため、自動または手動で適宜更新する必要がある。
自動化する場合は下記ページなどを参照
[https://it-jog.com/khow/serv/renewletsencrypt](https://it-jog.com/khow/serv/renewletsencrypt)

## 接続確認

自身のノードにhttpsでアクセスし、有効になっていることを確認する。
https://{ドメイン}:3001/node/info

https対応ノードは[ノードリスト](https://symbolnodes.org/nodes/)にhttpsと表記されるが、表記されるまで数時間ほどかかる。
vue.js elment ui タブを利用した際の ブラウザの戻る進む

vue.js で element ui を利用した際、
ブラウザの戻る進むでタブを動作させたい。

① タブをクリックするとタブが切り替わる
② ① の後に戻るを押すとタブが戻る

```top.vue

<template>

    <div>

        <div class="top-tabs"  style="margin:auto;">

            <el-tabs v-model="selectedTab" :stretch="true"  @tab-click="tabSelect">
                <el-tab-pane label="最新" name="1"></el-tab-pane>
                <el-tab-pane label="人気" name="2"></el-tab-pane>
                <el-tab-pane label="いいね（自分がいいねしたの）" name="3" ></el-tab-pane>
            </el-tabs>

        </div>

        <div>
            現在選択されているタブ {{this.selectedTab}}<br>
            クエリ : {{this.$route.query.tab}}
        </div>

    </div>
    
</template>

<script>
    
    export default {

        data () {
            return {
                defaultSelectedTab:"2",//初期選択値
                selectedTab:"",//選択値
            };
        },
        
        created () {
            this.selectedTab = this.defaultSelectedTab;
        },

        methods: {
            tabSelect(obj,e){
                var idou = location.pathname + "?tab=" + obj.name;
                this.$router.push({
                    path: idou
                }, () => {}, () => {});
            }

        },
        
        watch: {
            '$route.query': {
                immediate: true,//即時
                handler(newVal) {
                    console.log("タブクエリをウォッチ");

                    if(!newVal.tab){
                        newVal.tab = this.defaultSelectedTab;
                    }

                    this.selectedTab = newVal.tab;
                }
            }

        },
        
    }
</script>


```

こんな感じでどうでしょうか。
[Rails]before_action :authenticate_user!について

#authenticate_user!とは
・deviseが用意してくれた便利なメソッドである。
・userがログインしているか確認することができる。

##具体的な使用法
```ruby
class ApplicationController < ActionController::Base
  before_action :authenticate_user!

  def index
  end

  def show
  end
  
  def edit
  end
end
```
コントローラーの先頭に書くことでログインしていないとコントローラーの内容を実行できない。

私自身、ApplicationControllerに記載してしまったため、何も実行できなかったためこの記事を書きました。

```ruby
class ApplicationController < ActionController::Base
  before_action :authenticate_user!, only: [show]

  def index
  end

  def show
  end
  
  def edit
  end
end
```
上記ように追加するとshoアクションだけログインしないと実行できないようになる
index,editはログインしていなくても実行可能

#感想
初心者には、まだまだ覚えることが多そうです。
説明が間違っていればご指摘頂けると幸いです
HOYA VoiceText Web API で音声が切れるのを防ぐ方法

#症状
HOYAのVoiceText Web API を使って音声合成すると、最後の部分がプツっと切れるようなwavファイルが生成されることがある。

#原因
おそらくファイルとして生成されるのが合成した波形のみで、最後に空のデータなどのスペースがないためそう聞こえるんだと思う。多分。。
バッファに残った部分が再生しきらずに終わっちゃってるとか？

#対策
HOYAのVoiceTextはSSMLに対応しているので、最後に少しpauseを入れてやればOK。
`<vt_pause=500/>`で500[ms]のポーズが入れられる。

```python
with open('test.wav', 'wb') as f:
    f.write(vt.to_wave(text + '<vt_pause=500/>'))
```


```bash
curl "https://api.voicetext.jp/v1/tts" \
       -o "test.wav" \
       -u "YOUR_API_KEY:" \
       -d "text=おはようございます<vt_pause=500/>" \
       -d "speaker=hikari" \
       -d "emotion=happiness" \
       -d "emotion_level=2" \
       -d "pitch=105" \
       -d "speed=105"
```

これできれいなファイルになる。
非エンジニアの同期に「APIってなに？」って聞かれたから私のイメージを伝えてみた

非エンジニアの同期に「APIってなに？」と聞かれたのでその時の回答をメモ。
細かい仕組みとかは置いといて、イメージだけでもわかるようにって感じ。
※あくまでも私のイメージです。

# 結論
APIとは、
**「特定のURLにアクセスすると欲しい情報が受け取れる」**

# 例えば...

`「今日の給食が何か教えてくれる」`っていうAPIがあるとします。

*登場人物*

- 今日の給食で何がでるかしりたい人：生徒（APIを使う人）
- 今日の給食に何が出るか教えてくれる人：給食作ってくれるおばちゃん（API本体）

````
生徒 to おばちゃん
「今日の給食教えて」（APIを叩く行為）
おばちゃん　to 生徒
「今日の給食は○○だよ」（APIから返却された情報）
```

って教えてくれる。

↑みたいな感じで欲しい情報を提供してくれる機能（おばちゃん)みたいなのがAPI。

## もう少し細かく
APIによっては、
URLを叩く際にこちらからも情報を提供すると、
**①さらに細かいことを教えてくれたりする。**
逆に必要な情報がない場合、
**②何も教えてくれなかったりもする。**

上記の「今日の給食が何か教えてくれる」APIを元に例えると、

**①細かいことを教えてくれる**

````
生徒 「今日の給食の`デザート`を教えて」
おばちゃん 「デザートは☆☆だよ」
````

`デザート`っていう指定をしたことで"デザート"の情報を教えてくれる。

**②情報を与えないと何も教えない**
`「〇〇学校の人にだけ教える」`っていうルール？みたいなのも作れる。
（セキュリティてきな）

````
生徒1「今日の給食教えて」
おばちゃん「あなたの学校わからないから教えられません」

生徒2「■■学校の生徒です、今日の給食教えて」
おばちゃん「■■学校の人には教えられません」

生徒3「○○学校の生徒です、今日の給食教えて」
おばちゃん「今日の給食は〇〇だよ」
````


みたいなね。
**「この情報を与えられたらこの情報を返す」**
だったり、
**「この情報がなかったら（一致しなかったら）なにも返さない」**
っていう作り方もあるよねって感じ。

どう作るかは仕様次第かなと。
Postieプラグインでデフォルトのアイキャッチ画像を設定する

#やりたいこと
[WordPress](https://ja.wordpress.org/) の [Postie](https://postieplugin.com/) プラグインで、デフォルトのアイキャッチ画像を設定する.

#詳細
[WordPress](https://ja.wordpress.org/) でメールによる投稿を可能にするプラグイン [Postie](https://postieplugin.com/).

メールに添付した最初の画像が自動的にアイキャッチ画像（Featured Image）になるように設定できるが, 画像が添付されていない場合にはアイキャッチ画像無しになる.

この場合にはあらかじめ指定したデフォルトの画像がアイキャッチになるようにしたいと思い, [Default Featured Image](https://ja.wordpress.org/plugins/default-featured-image/ "ja.wordpress.org") を試してみたら, 画像が添付されていてもデフォルトの画像になってしまった.

#解決策
Postie の拡張フィルター機能を使えば何とかなりそう. ということで, [WordPress Codex](https://wpdocs.osdn.jp/Main_Page) を調べて以下の関数を発見.

* [has_post_thumbnail](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/has_post_thumbnail) ― アイキャッチ画像の有無をチェック
* [set_post_thumbnail](https://wpdocs.osdn.jp/%E9%96%A2%E6%95%B0%E3%83%AA%E3%83%95%E3%82%A1%E3%83%AC%E3%83%B3%E3%82%B9/set_post_thumbnail) ― アイキャッチ画像を設定

[Postie のドキュメント](https://postieplugin.com/extending/)に従い "wp-content" ディレクトリに "filterPostie.php" というファイルを作成し, 以下を記述.

```filterPostie.php
<?php 
function my_postie_post_function($post) {
  if ( !has_post_thumbnail($post['ID']) ) {
    set_post_thumbnail( $post['ID'], 1298 );
  }
  return $post;
}

add_filter('postie_post_after', 'my_postie_post_function');
?>
```
投稿後に処理されるフィルタ [postie_post_after](http://postieplugin.com/postie_post_after/) を定義し, アイキャッチが設定されていない場合のみ, デフォルトの画像を設定している.

set_post_thumbnail() の第2引数（上記の例では "1298"）には WordPress のメディアライブラリに登録されている画像のIDを指定する.

画像IDの調べ方は [【WP REST API解説】](https://mojitoba.com/2019/01/30/how_to_check_media_id/) を参照.

これでやりたいことができた.
自作PCにwsl2で開発環境を整える～anyenv導入編～

#Abstract
[前回](https://qiita.com/SatoshiNonomura/items/f1cb264f11becc5b4a5c)までで、一通りセッティングは終わったので、環境構築をやっていきます。
今回はanyenvの導入と、それを使って各種envを入れていきます。

※ WSL2のUbuntu20.04を使っています。

---
以下の内容があります。

- anyenvの導入
    - PATH通し
- (hoge)envのインストール
- anyenv updateの導入

# anyenv導入編
## DL
ソースをGitHubからcloneします。

```sh
git clone https://github.com/anyenv/anyenv ~/.anyenv
```

## PATH通し
コマンドでもいいのですが、後で楽できるように.bashrcを直接書き換えます。
ちなみに.bashrcを書き換えるのはUbuntu DesktopやWSLの場合です。
bashの場合は.bash_profile、zshであれば.zshrcを変更します。

```sh:~/.bashrc
if [ -e "$HOME/.anyenv" ]
then
    export ANYENV_ROOT="$HOME/.anyenv"
    export PATH="$ANYENV_ROOT/bin:$PATH"
    if command -v anyenv 1>/dev/null 2>&1
    then
        eval "$(anyenv init -)"
    fi
fi
```

これで書いておけば、rbenvやnodenvを入れた際にもパスが通ります。

ここまで終わればシェルを再起動します。

```sh
exec $SHELL -l
```

## 確認
```sh
anyenv --version
```

パスが通っていればちゃんとバージョンが出るはずです。

# (hoge)envのインストール
## 準備
```sh
anyenv install --init
```
`anyenv-install`のプラグインの準備です。

## インストールできるものの確認
```sh
anyenv install --list
```

## インストール
```sh
# ruby
anyenv install rbenv

# python
anyenv install pyenv

# node
anyenv install nodenv
```
インストールが終わったら必ずシェルを再起動します。

```sh
exec $SHELL -l
```

## アンインストール
```sh
anyenv uninstall nodenv
```

# anyenv update
更新が楽になるようにanyenv updateを入れます。

## まずはpluginディレクトリを作成
```sh
mkdir -p $(anyenv root)/plugins
```

## そこにanyenv updateをcolne
```sh
git clone https://github.com/znz/anyenv-update.git $(anyenv root)/plugins/anyenv-update
```

これで、`anyenv update`でanyenv本体と、それに付随するenvをまとめてupdateできます。

# バックナンバーと次回予告
[初回：WSL導入編](https://qiita.com/SatoshiNonomura/items/1b23107b2ab9c28b5f2a)
[前回：WSL2のセッティング](https://qiita.com/SatoshiNonomura/items/f1cb264f11becc5b4a5c)
[次回：ruby導入編](https://qiita.com/SatoshiNonomura/items/a84dc7ee6740e4a5b41a)

# 参考
[anyenvの環境構築 @282Haniwa ](https://qiita.com/282Haniwa/items/71a48a10952413416d18)
[WSLでanyenv(nodenv)を入れる。 --遠藤ヒズミの blog](https://endohizumi.hatenablog.com/entry/2019/04/29/003324)
xargsを使ったプロセスの並列化


## 目的

```math
X = \{ apple, orange, grape, ... \} \\
Y = \{ 1, 2, 3, 4, ... \}
``` 
としたときのXとYの直積

```math
X \times Y = \{ (apple,1), (apple,2), ..., (orange,1), (orange,2),...\}
```

の各要素を引数に取るようなプロセスを実行したい。
さらに、論理コアの数だけ並列に実行したい。

## 実装

```
# 論理コア数
logic_core_num=12

# 呼び出したいプロセス
function hogeProcess(){
  echo $1 $2
  sleep 5
}

# exportしないとxargsの引数でシェルスクリプト内の関数を呼び出せない
export -f hogeProcess 

# 実行部分
fruits_list=(apple orange grape)
for fruits in ${fruits_list[@]}; \
do \
  for i in `seq 1 32`; \
  do \
    echo $fruits $i; \
  done; \
done | xargs -I arg -P $logic_core_num bash -c "hogeProcess arg"
```

```
IFS=$'\n'
echo "${fruits_list[*]}" | xargs -I fruits bash -c "seq 1 32 | xargs -I idx echo fruits idx" | xargs -I arg -P $logic_core_num bash -c "hogeProcess arg"
```

とワンライナーでも書ける（可読性低いけど）

## 感想

サーバーのCPUを遊ばせずに多重起動できるようになった。
SSHポートフォワーディングを行う方法

自分のPCの7777ポートとサーバーの8888ポートをつなぐSSHでつなぐ方法

```
ssh -L 7777:localhost:8888 サーバー名
```
でつなげることができます

これを一般化すると
```
ssh -L ローカルポート番号:localhost:8888 サーバー名
```
自作PCにwsl2で開発環境を整える～WSL2のセッティング～

# Abstract
[前回](https://qiita.com/SatoshiNonomura/items/1b23107b2ab9c28b5f2a)の記事で導入できたUbuntuとWSL2を設定していきます。
タイトルがWSL2のセッティングとなっていますが、ほとんどUbuntuの設定になります。

---
以下の内容があります。

- 既定のディストリビューションを設定
- hostnameの変更
- パッケージ更新
- sudoパスワードの省略
- 日本語化

# ディストリビューション
## 規定値の確認
PowerShellで以下を実行します。

```powershell
wsl --list --verbose
```

すると、こんな感じに出てきますが、ここで`＊`のついているディストリビューションが既定のものになります。

```powershell
C:\Users\user> wsl --list --verbose
  NAME            STATE           VERSION
  Ubuntu-20.04    Running         2
* Ubuntu          Stopped         2
```
なお、初回の起動をしないとリストに表示されないので注意しましょう。

## 規定値の変更
```powershell
wsl --set-default Ubuntu-20.04
```

こうすることで、`ファイル名を指定して実行`からbashやwslを実行したときなどに、Ubuntu-20.04が起動するようになりました。

## ディストリビューションを指定して実行
```powershell
wsl --distribution <NAME>
```
ってやれば、指定したディストリビューションを実行できます。

# Ubuntuを設定
きっとUbuntuじゃないLinuxディストリビューションでも大丈夫だと思います。

## ホスト名変更
Ubuntuにログインすると、`user@DESKTOP-HOGEHOGE`みたいになっているかと思います。
これだけホスト名が長いと見づらいので、ホスト名を変更します。一般的な以下のLinuxコマンドではエラーを吐きます。

```nginx
user@host:~$ sudo hostnamectl set-hostname
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to create bus connection: Host is down
```

というわけで、windows側でPC自体の名前を変更します。
`設定`>`システム`>`詳細情報`を開き、`このPCの名前を変更`を押して変更するか、管理者権限で開いたPowerShellで以下を実行します。

```powershell
Rename-Computer -NewName "<HOSTNAME>"
```

## 更新
```sh
sudo apt-get update
sudo apt-get upgrade
```

## sudoパスワードの省略
/etc/sudoers.d/に設定ファイルを配置します。visudoを使ってもいいと思います。

```shell
sudo bash -c 'echo "<USERNAME> ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/<USERNAME>'
```

## ロケール設定
一部が日本語化します。してもしなくてもいい気がします。

```sh
sudo apt install language-pack-ja
sudo update-locale LC_ALL=ja_JP.utf8
```

# バックナンバーと次回予告
[前回：wsl導入編](https://qiita.com/SatoshiNonomura/items/1b23107b2ab9c28b5f2a)
[次回：anyenv導入編](https://qiita.com/SatoshiNonomura/items/93f05aaf0113bb714786)

# 参考
[WSL2向けUbuntu20.04の初期設定 @YuukiMiyoshi](https://qiita.com/YuukiMiyoshi/items/eec3c1827cd8356c1def)
ダイエット＋食品管理アプリ構築の道程（１）


2021年６月８日からMENTAでメンターさんを探してポートフォリを作りを開始しました。
目的はダイエット＋食品ロス軽減
現状の完成具合（１７日経過）
![20210625-120211.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/546ed82b-36a7-3cf0-6318-6c433ea2954e.png)



####Q食品管理は何が難しいのか？

**（食費のプロパティ上）A通常の在庫管理にならないこと**

例えば「（同じ材質の）ネジ長さ5mm」は在庫が０（ゼロ）になれば、仕入れて在庫を補充すれば良い。
でも玉ねぎは１週間前に仕入れたものと今日仕入れた玉ねぎは玉ねぎとしては同じ。
**だが**、生鮮食品には**「鮮度(=freshness)」**があり、同じ玉ねぎとして扱えない。
１週間経てば腐る玉ねぎと２週間鮮度がもつ玉ねぎは同じものとして扱えない。
（細かい人は淡路島の玉ねぎと北海道の玉ねぎは違うので分けろというかもしれない。
確かに産地で値段の違うことはよくある。）
＊今は玉ねぎは値段で分けては扱うことも考えていないし、調理する段階で食材として足りていれればよしとする。

**以上から、玉ねぎを仕入れても鮮度違いで別の玉ねぎが増えることになる。
ネジAのように見た目は補充することになっても同じ玉ねぎで在庫数を増やすことにはならない。
鮮度が違うのでできるだけ使い切って新しい在庫を増やすのだ。**

食品ロス軽減を考えています。まずは意識換気から。レコーディングダイエットならぬレコーディング食品ロス軽減対策。


####Q２つのテーブルの内容
通常の在庫やECサイトは商品在庫管理（=stocks）テーブルで管理しているようだ。

|A：親テーブル|B：子テーブル|
|:--|:--|
|A：製品=products|B：在庫=stocks[まんま*でも機械的]|
|A：料理=meals　|B：食材=foodstuff[作るものと作る前のもので分ける]|
|A：調理=cooking|B：保存場所を表す冷蔵庫=frige[食材が何をされるのかで分ける]|
で一番下ので考えていきますが、


買ってきたものはfridgeに新規登録。またその総量(g)も登録（→→→fridgeテーブル）。
食材を使うごとに（調理のたびに）frigeのテーブルのfoodstuffから使った分の食材を減らす。

この問題の解決方法は今の私の検索結果から探り出した答えは以下の２点

①Fromオブジェクト（１つのView１つのコントローラー）
*一つのViewと言いますが上半分は親側の調理に関する料理名であったり使用食材やその量
*下半分は子側のストックされている調理後の食材の残データ
（こちらは通っていたプログラミングスクール教材を使用）

②fields_for と accepts_nested_attributes_for
次回実装しながら実況して行きます。

参考にさせていただきました。🐜です
kzy52's blog（kzy52さん(id:kzy52)はてなブログ）
>https://kzy52.com/entry/2013/07/10/200144

@_Taturon_さん
>https://qiita.com/_Taturon_/items/961199cdd937be669cc5

 Rails Application Build Guides
>https://rails.densan-labs.net/form/relation_register_form.html
MaterialUIのDate / Time pickersの入力欄をOutlinedにしたい

タイトルそのまま。
やりたいんだけど、全く方法が見つけられなかった。
私はきっと同じことをしようとしてまたハマるので、備忘録的に書いておく。
結論だけ知りたい人は、一番したまでどうぞ。

## やりたいこと
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670801/b17ba02a-2513-bc26-6772-d962a77c11d3.png)
[このデモ](https://material-ui.com/components/pickers/#material-ui-pickers)の入力欄が下線になっている。
これを↓のTextFieldのOutlinedと同じようにしたい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670801/23db2844-239e-5978-4c0d-e6329b63c044.png)

## コードを見てみる

```Typescript
<KeyboardDatePicker
         disableToolbar
         variant="inline"
         format="MM/dd/yyyy"
         margin="normal"
         id="date-picker-inline"
         label="Date picker inline"
         value={selectedDate}
         onChange={handleDateChange}
         KeyboardButtonProps={{
           'aria-label': 'change date',
         }}
/>
```

となっているので、「KeyboardDatePicker」という部品であの入力欄が作られていることがわかった。
ならば、APIのページを見に行くだけだ！と検索欄にコピペ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670801/ca14aa58-9aab-a9a3-1241-45207d4beea7.png)

**あれ？！ヒットしない？！**

なんでだよ。使ってるじゃないか。
その部品の使い方を教えてくれよ。

## やっと見つけた

まぁ、こんな変な苦労をしたのは
私が英語苦手すぎるが故なんだけど。

ずっと、「Material-UI」のドキュメントを漁ってた。
そしてあの部品はどこにいたのか。

「Material-UI pickers」という別のドキュメントにいた。

https://material-ui-pickers.dev/

## 結果

先ほどのコードに`inputVariant="outlined"`と付けるだけで終わった

```Typescript
<KeyboardDatePicker
         inputVariant="outlined"
         disableToolbar
         variant="inline"
         format="MM/dd/yyyy"
         margin="normal"
         id="date-picker-inline"
         label="Date picker inline"
         value={selectedDate}
         onChange={handleDateChange}
         KeyboardButtonProps={{
           'aria-label': 'change date',
         }}
/>
```

完璧。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670801/fbf722cf-9fb4-9382-bc44-336a2aea4bc6.png)
Pycaretを使って複数モデルをマージして予測してみました

#はじめに

現在、Kaggleのタイタニックコンペを行っており、ちょうどPycaretというAutoMLのことを知りましので、試しに使ってみました。
Pycaretには複数のモデルをアンサンブルする機能がありましたので、それを試してみました。

単純な使い方などは、以下の記事を参照ください。

https://qiita.com/kotai2003/items/a377f45ddee9829ed2c5

#Pycaretでのモデルアサンブル

Pycaretでは、以下の3つの方法でアンサンブル機能を提供しています。

 - アンサンブルモデル
　　機械学習における、「バギング」や「ブースティング」などの手法で、アンサンブル学習によるモデルを構築します。  
　　詳しくは、以下を参照してください。  
　　https://pycaret.org/ensemble-model/
　
 - ブレンドモデル
   複数のモデルで予測を行い、予測スコア、予測値の多数決により最終的な予測値を出力します。
　　詳しくは、以下を参照してください。
　　https://pycaret.org/blend-models/
 
 - スタックモデル
   複数のモデルを予測を行なった後に、どのモデルの予測値を採用するかを指定したモデルで学習する。
　　（2層構造で学習するイメージ）
　　詳しくは、以下を参照してください。
　　https://pycaret.org/stack-models/

今回は、ブレンドモデル、スタックモデルについて試してみました。

## 準備

　　モデル作成までのコードは、以下になります。

```Python
!pip install pycaret==2.3.1

# pycaretのインポート
from pycaret.classification import *

# 訓練データとターゲットデータのまとめ
df_train = df_train_data[['Survived','Pclass','Sex','Age','SibSp','Parch','Fare','Embarked']]

# セットアップを実施

clf = setup(data=df_train, target='Survived', session_id=1) 

# モデル間の比較を実施

best_model = compare_models()  # 全てのモデルを訓練し、評価する

```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004109/d078b8b6-c1ce-f996-7a59-52e1dd8cf304.png)


今回は、モデル比較によって、精度が高く尚且つ、手法の異なる以下の3つのモデルを利用します。
- CatBoost Classifier
- Logistic Regression
- Random Forest Classifier


## ブレンドモデル構築

```Python

# train a voting classifier on specific models

# 個々のモデルの作成
cat = create_model('catboost')
rf = create_model('rf')
lr = create_model('lr')

# 個々のモデルのチューニング
tuned_cat = tune_model(cat)
tuned_rf = tune_model(rf)
tuned_lr = tune_model(lr)

# ブレンド実施
blender_specific = blend_models(estimator_list = [tuned_cat,tuned_rf,tuned_lr], method = 'soft')
```

出力結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004109/44172f6b-9420-ef0b-c177-96dedbbc9249.png)

全体に精度が改善されていることが確認できました。

また、パラメータの「method」は、 
soft：予測スコアの最も高いモデルの予測ラベルを予測値とする 
hard：予測ラベルを多数決して、予測ラベルとする 
となります。

また、estimator_list = compare_models(n_select = n)とすることで、自動的にスコアの高いモデルを採用するということもできます。

## スタックモデル構築

スタックモデル構築までの処理は同じなので、割愛いたします。

今回は、ここの予測モデルとして、「catboost」、「random forrest」を選択し、予測モデルを選定するメタモデルとして、「xgboost」を選択しました。

```Python
# create individual models for stacking
cat = create_model('catboost')
rf = create_model('rf')
tuned_cat = tune_model(cat)
tuned_rf = tune_model(rf)

xgboost = create_model('xgboost')

# stacking models
stacker = stack_models(estimator_list = [tuned_cat,tuned_rf], meta_model = xgboost)
```

結果は、下になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1004109/c81344af-4626-9545-a440-7ad9c5c055c3.png)

スコアが落ちる結果となりました。　
特徴に合わせたモデルの選定方法なども考える必要がありそうです。

こちらも、estimator_list = compare_models(n_select = n)とすることができます。
また、meta_modelを指定しない場合は、'linear model'となるそうです。

# まとめ

Pycaretを使うことで、複数モデルを利用した予測を簡易に行うことができることがわかりました。
それぞれのモデルの短所と長所を補って使うことができれば、有効に使うことができるのではないかと思います。

# 参考URL

https://pycaret.org/functions/
docker で Apache の導入（docker hub のイメージ使用）

# 背景
環境構築を楽にするために、docker の勉強をしております。
今回は docker hub のイメージを使用して、Apache の導入をしました。

# 環境
Amazon Linux release 2 (Karoo)
Docker version 20.10.4

# 手順
## HTMLファイルを配置するディレクトリの作成
HTMLファイルを配置するディレクトリを作成します。
今回は`/opt/app`配下にHTMLファイルを配置します。

```
sudo mkdir /opt/app
```

## docker インストール
以下の記事に手順を残してありますので、ご参照ください。

https://qiita.com/hamburg-love/items/6b5e5091764753b5e229

## Apache イメージのダウンロード
今回は以下のイメージを使用します。

https://hub.docker.com/_/httpd/

2021/06/25 時点では、2.4.48 バージョンが最新なのでこちらをダウンロードします。
イメージのダウンロードは`docker pull`コマンドを使用します。
`:`の後にバージョン指定できますが、指定しなかった場合は`latest`バージョンがダウンロードされます。

```
sudo docker pull httpd:2.4.48
```

ダウンロードできたか確認します。

```
sudo docker image ls
REPOSITORY   TAG       IMAGE ID       CREATED        SIZE
httpd        2.4.48    30287d899656   43 hours ago   138MB
```

## コンテナの作成
Apache イメージからコンテナを作成します。
コンテナの作成には`docker run` コマンドを使用します。
今回使用するオプションは以下の通りです。

```
# コンテナに入る必要がないため
-d バックグラウンド実行

# コンテナが80番でhttpdを受けているため、ホストOSから疎通できるよう設定する。
-p ホストOSとコンテナ間のポートフォワーディング ホストOS側:コンテナ側

# HTMLファイルをホストOS側に配置するための設定
-v ホストOSとコンテナのマウントの設定 ホストOS側:コンテナ側
```

実行したコマンドは以下の通りです。

```
sudo docker run -d -p 80:80 -v "/opt/app/:/usr/local/apache2/htdocs/" httpd:2.4.48
```

コンテナが作成できたか確認します。

```
sudo docker ps -a
CONTAINER ID   IMAGE          COMMAND              CREATED          STATUS          PORTS                NAMES
59a6ddb31028   httpd:2.4.48   "httpd-foreground"   25 seconds ago   Up 24 seconds   0.0.0.0:80->80/tcp   funny_kalam
```

## HTMLファイルの配置
Apache のドキュメントルートは`/usr/local/apache2/htdocs/`に設定されています。
今回は`/opt/app/`にマウントしているので、`/opt/app/`配下にHTMLファイルを配置します。

```
sudo vi /opt/app/index.html
hello world
```

最後にURLをブラウザに入力して、配置したHTMLファイルが表示されるか確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/184532/8a496f84-5aa0-5f00-74b4-a37eee610ae0.png)

無事表示されたので、作業終了です。

# 最後に
今回は docker hub で公開されているイメージを使って、Apache を導入しました。
あくまで私の感想ですが、システムエンジニア初心者の方が Apache のお試しをするのであれば、yum でのインストールでも十分だと思います。

ただ docker の便利なところは全く同じ環境を複製することができるという点だと思いますので、複数のサーバに同じ Apache の環境を用意したい場合に適していると思います。

例えば、本番サーバに docker を使用している場合は、開発環境に同じコンテナを使用することで同じ環境を用意できるので便利だと思います。

ただ、本番サーバの Apache はなるべく最小限でインストールするため、ソースコードからビルドしてインストールしていると思います。
ですので、次は自分でイメージを作成する勉強をして記事にします！
ゼロからのJava〜アプリケーション作成

<h1>手順を記録していく</h1>

目標１：まずはHelloWorldをしてみる
・paizaでHelloWorldまで。難しければprogateで。


目標２：paizaかprogateで演算と変数まで


目標３：業務においてJavaで何をするのか大まかに理解する


目標４：環境構築と関係性の理解
環境構築といっても、Pleiadesをぶっこむだけ。
サーバー、サーバーアプリケーションの関係、
コンパイルの仕組みを簡単に理解する。
理解できなくてもOK。


目標５：Eclipse内で学習用に触る部分の機能理解
HelloWorldしてみる。


目標６：Javaの基礎学習に戻る

---記載途中---
[Rails] routesのnamespaceとget ... to: の意味

#namespace
`namespace: hoge` で名前空間を付与することができます。これはコントローラーをグルーピングし、またURLにもその情報を付与することを意味します。

```ruby:routes.rb
  namespace :api do
    namespace :v1 do
      ...
    end
    namespace :v2 do
      ...
    end
  end
```

例えばこのようにnamespaceは複数配置することもできるため、`api/v1/fuga_controller.rb`と`api/v2/fuga_controller.rb`を分類することもできます。

#####名前空間(namespace)
名前空間とは、各要素に一意の異なる名前をつけなければ識別できない範囲のこと。
また、名前の集合全体を小さな空間に区切り、それぞれに異なる識別名を与えることで、
その空間内では他の空間に含まれる名前の競合・衝突を意識しなくて良いようにしたもの。


#get ... to:
特定のリソースに対するルーティングを生成する方法は
resources、resourceだけではありません。それが以下の書き方です。

```ruby:routes.rb
 get 'hoge/fuga', to: 'hoge#hoge_fuga'
```

これはつまり、「'hoge/fuga'というURLに対してGETリクエストがきたら、hoge_controller.rbのhoge_fugaメソッドを呼ぶ」ということを意味します。

resources :hogeとの違いは、アプリケーション独自のルーティングとコントローラー、
そのアクションに対応させられるという点です。

一長一短ですが、「原則はresources、resourceで書く、例外的に必要であればget ... to:も許容する」というルールがいいかと思います。後者は自由度が高い一方で、コード量は増えますし、またその量に応じて管理も大変です。

#ShellScript
####shell
shellとはLinuxカーネル(OSの中核)と私達ユーザーとのコミュニケーションの間に立つ、
要は「OSとの対話用インターフェース」とも言えるものです。このshellがなければ、私たちがどれだけ操作を実行したとしてもカーネルには届きません。

そして、このshellが理解することのできるスクリプト言語こそがShellScriptです。つまり、コンピューターに対して実行させたい処理をこのShellScriptを用いて命令することができるわけです。

---

ちなみに、わざわざShellScriptを書かなくても複数のコマンドを駆使することで、複雑な処理を命令することもできます。例えばgrepやcut、そしてこれらのコマンドをつなぐ|(パイプ)などを組み合わせます。このようなこともできます。

```sh:sh
# 出力されたrouts一覧から、'order'が含まれる一行のみを出力する
$ rails routes | grep order
```

|(パイプ)はその左側の標準出力(そのコマンドによって出力される文字列、数値など)を、
パイプの右側に渡すことができます。また、grep(グレップ)はファイルやディレクトリ、
または標準入力の中から、特定の文字列を含む行を出力します。つまり、この場合、rails routesで全てのルーティングが標準出力され、|を通して右側に渡され、最終的にgrepでorderに合致する行が出力されるという流れです。
Django form_invalidでcontextを追加したい


バリデーションが通らない時に特定の値をテンプレート側に渡したいということがありました。
日本語の情報がなかったので記事にしました

```py:views.py
class HogeFormView(FormView):
    ....
    def form_invalid(self, form):
        context = self.get_context_data()
        context['hoge'] = "hoge"
        return self.render_to_response(context)

```

参考にしたサイト
[Updating context data in FormView form_valid method?](https://stackoverflow.com/questions/6907388/updating-context-data-in-formview-form-valid-method)
Git .gitignoreファイルを作ってGit管理しないファイルを登録する

# 目的

- .gitignoreファイルを作成してGit管理しないファイルを登録する方法を簡単にまとめる

# 方法

1. ローカルリポジトリ内で下記コマンドを実行して`.gitignore`ファイルを作成する。

    ```terminal
    $ vi .gitignore
    ```

1. 今回は拡張子が「html」「png」「jpeg」「pdf」のものをGit管理しないように登録する。開いた`.gitignore`ファイルに下記のように記載する。

    ```.gitignore
    *.html
    *.png
    *.jpeg
    *.pdf
    ```

1. 設定した拡張子のファイルがGit管理から除外される。`.gitignore`ファイル自体はGit登録してしまって良い。
転職ドラフトを使って転職してみた感想

＊こちらの記事は[転職ドラフト体験談投稿キャンペーン](https://job-draft.jp/articles/251)に参加しています

今回転職ドラフトを使って転職をすることになったので、自身の考えや経験、他のサービスとの違いなどを共有したいと思います。  
  
### 転職サービス登録へのきっかけ
2021年の頭から自身のエンジニア歴が半年を超えてきたこともあり、「自分の市場価値って正味どの程度のものなんだろうか」という気持ちから幾つかの転職サービスに登録しました。そのうちの1つが今回の転職のきっかけになった転職ドラフトです。  
  
### 転職ドラフトの特徴
他の転職サービスと比較すると、転職ドラフトは少し独特なシステムかもしれません。一般的な転職サービスでは特に期間の区切りなどはなくスカウトなどが届く様なものが多いと思いますが、転職ドラフトでは毎月ドラフト期間が設けられていて、その期間中に企業から指名がもらえる様な仕組みになっています。  
  
####　良かった点
* 審査に通過するためにはレジュメを整理する必要があるが、これが経験の棚卸しになり良い
* 指名は想定年収と共に届くため、オファーが出る段階での給与ミスマッチが起こりづらい
* 参加している企業側も積極的なため、（自分の体験の場合では）不毛なコミュニケーションが発生しづらい
* 他の参加者の方のレジュメもある程度参照できるため、どの様なエンジニアが企業から評価されているかの情報収集が行える

#### 悪かった点
* （特に参加等者などは）指名がもらえない様な場合、しょんぼりする・・・
* ポーリングによる定期処理などで実装しているのかもしれないが、企業からのメッセージが届いた際に運営側から送信される通知メールに比較的大きなタイムラグがありストレスになる


### 最後に
少しクセのあるサービスなので、向き不向きはあるのかなとは思います。とはいえ指名性のおかげで企業側とのやりとりはスムーズに行えるし、審査に問題なく通過できる程度の経験があるのであれば自分の様な駆け出しエンジニアでも気軽に自身の市場価値を確かめることが出来て割といいかな、と思いました。
最後まで読んでいただき、ありがとうございました！
コンテナとDockerについて初心者向けにざっくりと紹介します


# 概要
コンテナとDockerについて、仕組みや特徴などに加え、初心者が疑問をいだきやすい箇所についても解説します。


#コンテナ
### コンテナとは？
コンテナとは、従来の仮想化のボトルネックであったゲストOSと仮想マシンを不要とし、より軽量で高速に動作するアプリケーションの動作技術。:smi

 　　　　仮想化　　　　　　　　　コンテナ
![スクリーンショット 2021-06-25 10.53.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/2fc2a701-1474-f47d-4fb7-09ee95acc0ec.png)![スクリーンショット 2021-06-25 10.54.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/3dada1ae-00f5-3141-ab1a-9f19a559970e.png)


### コンテナを使うと何がいいのか？
- 仮想サーバを立ち上げるオーバーヘッドが不要になり、より身軽なアプリケーションの実行基盤を提供できる
- ミドルウェアとOSのいち部を同梱することでどこでも実行可能になる

### なぜゲストOSが不要なのか？
アプリの動作はカーネル(OSの中核部)の機能を呼び出して動作しており、
Linux系のOSであるCentOSやUbuntuなどは共通のカーネルを使用している。
したがって、アプリの実行に必要なライブラリさえあればどのディストリビューションでもアプリの実行が可能。

### コンテナの３つの特徴的な技術と利点
コンテナはそれぞれが１つのプロセスとして扱われ、下記３つの機能から成り立つ。
**① Namespace**
ユーザーIDなどを用いて、他のプロセスとの分離・独立させる
&rarr;１つのコンテナを１つのプロセスとして管理できる。
**② cgroup**
プロセスをグループ化し、ホストOSの物理リソース(CPUやRAMなど）を分割・割当を行う。
&rarr;ホストOSや他のプロセスへの影響を抑制
**③ capability**
root権限のうち必要な権限のみを一時的にプロセスに付与する。
&rarr;与える権限を最小化し、プロセスの脆弱性などによる危険性を極力抑える。

# Docker
### Dockerの構成要素
**① Docker Engine**
アプリケーションの実行環境とアプリケーション本体をDockerイメージとして作成する
**② Docker Hub**
Dockerイメージのリポジトリ(Dockerイメージの移動や管理、共有など)
GithubのリポジトリにDockerfileを作成しておけば、自動でDockerイメージを生成することが可能。

### Dockerはステートレス
コンテナ(プロセス)が処理の途中で削除されれば、処理中のデータは保存されない。この欠点を改良するため

- データボリューム
- データボリュームコンテナ

を利用することでデータの永続化を可能としている。

### 複数のコンテナを管理したいときはDocker Composeを使う
１プロセスに１コンテナが原則だが、コンテナが増えると管理負担が大くなるため、
複数のコンテナを一括管理できる**Docker Compose**を使う。
Docker Composeを使うと

- Dockerイメージ
- コンテナの設定
- ネットワーク
- ボリューム ... etc.

をcomposeファイルとして定義し、１つのコマンドでコンテナのビルドや複数コンテナの起動などが可能になる。
シニアエンジニアに必要なコーディング以外のスキルリスト

シニアエンジニアに必要なコーディング以外のスキルリスト
初級者、中級者、シニア、そしてその先まで、さまざまなレベルに対応。

この記事の和訳
https://skamille.medium.com/an-incomplete-list-of-skills-senior-engineers-need-beyond-coding-8ed4a521b29f

1. 会議を運営する方法。会議で最も多く話す人になることと会議を運営することは別物である。
2. デザインドキュメントの書き方、フィードバックの受け方、適切な期間内に解決に導く方法。
3. 技術的なアドバイスを必要としている新卒のチームメイト、中途採用のエンジニア、新任のマネージャーを指導する方法。
4. バカにしたりせずに、よくわからない技術的な話をしたがるシニアマネージャーを満足させる方法。
5. 理解していないことを率直に認めるのが恥ずかしい上級者に、技術的概念を説明する方法。
6. 他のチームに自分のソリューションを使うように説得する方法。
7. 他のエンジニアに何かをしてもらうために、感謝の気持ちを込めて助けを求める方法。
8. プロジェクトのメンバーを管理していなくても、プロジェクトをリードする方法。
9. 他のエンジニアに脅威を感じさせることなく、自分のアイデアを聞いてもらう方法。
10. 脅威を感じずに他のエンジニアのアイデアを聞く方法。
11. 他のことをするために、あなたが素晴らしいものに仕上げたプロジェクトを手放す方法。
12. 自分が本当に大切にしていること（運用、正しさ、テスト、コード品質、パフォーマンス、シンプルさなど）を、他のエンジニアに教える方法。
13. プロジェクトの状況をステークホルダーにどのように伝えるか。
14. 些細な技術プロジェクトに投資する必要があることを経営陣に納得させる方法。
15. ソフトウェアを構築しながら、その過程で付加価値を提供する方法。
16. プロジェクトの提案書を作成し、それを社会に広め、実行するための賛同を得る方法。
17. 人が耳を傾けるようになるために、自分の話を繰り返す方法。
18. 戦う相手を選ぶ方法。
19. 誰かが昇進するのを手助けする方法。
20. 実際に起こっていることについての情報を得る方法(噂話やネットワークの作り方)。
21. 誰かが持ってきてくれるのを待つのではなく、自分で面白い仕事を見つける方法。
22. 相手に恥ずかしい思いをさせずに、自分もしくは相手が間違っていると伝える方法。
23. ネガティブなフィードバックを潔く受け止める方法。
gulpのインストール

自分用のメモに記載いたします。

前提としてnpmをインストールしていること
作業ディレクトリに移動

<h1>グローバルにインストール</h1>
インストール

```
npm install --global gulp-cli
```



パッケージの作成

```
npm init
```
質問はすべてエンターでOk


<h1>ローカルにインストール</h1>
インストール

```
npm install --save-dev gulp
```

sassをbuildするパッケージをインストール

```
npm install --save-dev gulp-sass
```

gulpを起動

```
gulp build
```


```
npm run dev
```
こちらでも可
備忘録：thymeleafでのlocaldatetimeの扱い

localdatetimeの入った変数をそのまま使うと

”2021-06-24T20:23:39.987941”

のように表示されてしまうので、


```
th:text="*{#temporals.format(date, 'yyyy/MM/dd HH:mm')}"
```

のように埋め込む

第一引数は
*{date}
ではなく中身だけ書く
VScodeでいつの間にか文字が縮小する件

Vscodeを触っているとなぜかいつの間にか文字が縮小する件、
なんの操作かわからなかったが、どうも
[command]+[_]を押していることが判明。
ウザいので設定変更する

[command]+[shift]+[p]から
「基本設定：キーボードショートカットを開く」を探す。

「縮小」で検索して[表示:縮小]の[⌘][_]を右クリックで「キーバインドを削除」してしまう。

これで誤操作での文字縮小は避けれる。

ちなみに、文字縮小してしまったら
[command]+[+]を押せば良い　（[+]はJISキーボードなら[shift]+[;]）
反対に縮小したい場合は
[command]+[-]を押せば縮小する
Anacondaをアンインストールしたときに大惨事(コマンドプロンプトが表示されなくなった)になったときの対処法

#大惨事
ちょっとした勘違いで、Anacondaをアンインストールしたらコマンドプロンプトが表示できなくなった。厳密に言うと開いた直後に勝手に閉じてしまう。
(Powershell 、git bashなどは正常に作動する。)
しかもネットでサーチしてもなかなか出てこない。

・・・・困った。

#解決法

Windowsキー＋X　つまり左下の検索窓から「レジストリーエディター」と入力。

普通の人は
HKEY_CURRENT_USER →　SOFTWARE →　Microsoft →　Command Professor

(一部の人はHKEY_LOCAL_MACHINE)

まで移動すると
Autorun　データ:if exists
のように表示されているはず。
これが諸悪の根源でこれを削除すれば解決。

#原因
Anacondaのアンインストールが「下手糞」
Rails 部分テンプレートの呼び出し"render"エラー

## Renderメソッドが正しく読み込まれない！!

### 状況
・Railsを使ったアプリケーションの制作中
・アプリの新規登録画面`new.html.erb`を作成中。
・このトップページは、SamplesコントローラーのnewアクションのViewとする。
・Viewの記述に、`renderメソッド`を使用して部分テンプレートを呼び出そうとした。

エラー画面
![スクリーンショット 2021-05-29 10.57.24のコピー.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1335471/78256fc7-5092-04dd-c1c8-1889cd8fc92e.jpeg)

Samplesコントローラーのindex.html.erbには

```ruby
<%= render ‘shared/second-header’ %>
```

と記述している。
一見、間違ってなさそうだけど、なぜ？

### 原因と解決
理由は単純でした。
部分テンプレートの`_second-header.html.erb`のディレクトリです。
`views/devise/shared/_second-header.html.erb`
にあるので、
`views/samples/new.html.erb`
にあるnewファイルからの呼び出しをするならば

```ruby
<%= render ‘devise/shared/second-header’ %>
# テンプレートの呼び出しの時は、頭のアンダーバー _ は省略可。
```

と書かなければ呼び出したいファイルの位置までたどれません。
同じviewsファイルの中にはありますが、
その後は`deviseフォルダ`と`samplesフォルダ`で分かれていますので、
同じディレクトリに存在しない場合は、しっかりと上の階層のフォルダから指定するということですね。

単純なんですが、ディレクトリの確認は重要です。
kaggleコンペのデータ取得 (Google Colaboratory)

#背景
Kaggle大会データの取得方法を備忘録として残します。
今回ダウンロードするのは、siim-covid19-detectionコンペです。
本コンペに含まれる画像がdcmという拡張子なので見方についてもアップ予定です。

#環境準備

```py
# kaggle APIのインストール
!pip install kaggle
```

```py
#ドライブの準備
from google.colab import drive
drive.mount('/content/drive/')

!mkdir -p '/content/drive/My Drive/data/kaggle'
%cd '/content/drive/My Drive/data/kaggle'
```

```:これはコマンドじゃないよ、ブラウザから実施。
# kaggle API用のAPIキーの取得
kaggleの右上にある自身のアイコンをクリック
Accountをクリック
APIのCreate New API Tokenをクリックして、kaggle.jsonをローカル保存
```

```py
# kaggle API用のAPIキーのセット
from google.colab import files
uploaded = files.upload()  #kaggle.jsonをアップロード
for fn in uploaded.keys():
  print('User uploaded file "{name}" with length {length} bytes'.format(
      name=fn, length=len(uploaded[fn])))

!mkdir -p ~/.kaggle/ 
!mv kaggle.json ~/.kaggle/ 
!chmod 600 ~/.kaggle/kaggle.json
```

```py
# 大会一覧の表示
!kaggle competitions list
```

# 任意の大会データ取得
```:これはコマンドじゃないよ、ブラウザから実施。
## データ利用に合意
kaggleの大会ページから、Join Conpetitionでデータの取り扱い等に合意
```
```py
## ダウンロード
%cd '/content/drive/My Drive/data/kaggle'
!mkdir siim-covid19-detection
%cd siim-covid19-detection
!kaggle competitions download -c siim-covid19-detection
```
AWS CloudFormationを使用してVPCを作成する

# 内容
この記事はAWS初学者を導く体系的な動画学習サービス
「AWS CloudTech」の課題カリキュラムで作成しました。
https://aws-cloud-tech.com
今回はCloudFormationを使用してVPCを作成してみたいと思います。

# 環境
mac OS Big Sur バージョン 11.4

# 実施順序

## VS Codeの準備
##### 今回はVS Codeを使用していきます。

1. デスクトップに新規フォルダを作成する。(例. cloudformation)
1. 作成したフォルダをVS Codeにドラッグ&ドロップする。
1. 作成したフォルダ内に新規ファイルを作成する。(例. cloudformation.yml)

## テンプレート作成準備

##### 1からテンプレートに則って作成するには非常に時間がかかるので、VS Codeの拡張機能を利用して作成していきます。

1. VS Code左メニューの拡張機能を選択`（shift ＋ command + x)`
1. 検索窓で`cloudformation`と検索
1. 検索結果の一番上の`CloudFormation`をインストールする。
1. `command + ,`で設定画面を開き、右上の`設定(JSON)を開く`ボタンを選択する。
1. `settings.json`ファイルが出現するので、`{}`内に下記のコードを追加する。


##### 詳細な説明は割愛しますが、VS CodeにCloudFormationの記述を教えてあげるイメージです。
```
"yaml.schemas": {
        "https://d33vqc0rt9ld30.cloudfront.net/latest/gzip/CloudFormationResourceSpecification.json": [
            "*.cf.yaml",
            "*.cf.yml",
            "*.cfn/*.yaml",
            "*.cfn/*.yml",
            "cloud*formation/*.yaml",
            "cloud*formation/*.yml"
        ]
    },
"yaml.customTags": [
    "!Ref",
    "!Sub scalar",
    "!Sub sequence",
    "!Join sequence",
    "!FindInMap sequence",
    "!GetAtt scalar",
    "!GetAtt sequence",
    "!Base64 mapping",
    "!GetAZs",
    "!Select scalar",
    "!Select sequence",
    "!Split sequence",
    "!ImportValue",
    "!Condition",
    "!Equals sequence",
    "!And",
    "!If",
    "!Not",
    "!Or"
  ],
```

## CloudFormationテンプレートの作成

１. 先ほど作成したYAMLファイルの１行目に`start`と入力してタブキーを押し、下記のような記述が出てくることを確認する。


```
AWSTemplateFormatVersion: 2010-09-09
Description: ---
Metadata: 

Parameters: 

Mappings: 

Conditions: 

Resources: 
 
Outputs:
```

２. `Resources:`の下の行に`vpc`と入力、いくつか候補が出てくるので、一番上の`vpc`を選択する。

```
Resources: 
  myVPC:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: --.--.--.--/--
      EnableDnsSupport: true
      Tags:
        - Key: keyname
          Value: value
Outputs:
```
３. CIDRブロックの行を修正する。（例. `CidrBlock: 10.0.8.0/21`）
４. タグの部分は修正してもしなくてもOK
５. 今回は最低限の設定で作成するため、`Resources`以外の箇所は削除して進めます。

```
AWSTemplateFormatVersion: 2010-09-09
Resources: 
  MyVPC2:
    Type: AWS::EC2::VPC
    Properties:
      CidrBlock: 10.0.8.0/21
      EnableDnsSupport: true
      Tags:
        - Key: Name
          Value: MyVPCfromCF
```

##### 作成したテンプレートをCloudFormationに読み込ませていきます。

1. AWSマネジメントコンソールからCloudFormationの画面を開く。
1. `スタックの作成`タブから`新しいリソースを使用（標準）`を選択
1. テンプレートの準備：`テンプレートの準備完了`を選択
1. テンプレートソース：`テンプレートファイルのアップロード`を選択
1. `ファイルを選択`から先ほど作成したYAMLファイルを選択
1. `次へ`を選択
1. `スタックの名前`を入力し、次へ
1. オプションはデフォルトのままで次に進む。
1. `スタックの作成`を選択
1. 作成したスタックのステータスが`CREATE_COMPLETE`となることを確認する。
1. VPCの画面に移動して、VPCが作成されていることが確認できればOK
Rails gem 'devise' エラー localserver関連

# gem 'devise'のエラー備忘録と解決方法紹介
本記事では、Rails（6.0.0）における
`gem devise`を導入後に起きたエラーを紹介します。

### devise導入後にローカルサーバーが起動しない
・ターミナルで`bundle install`を実行し、成功。
・ローカル環境での挙動を確認する`rails s`
<b>エラー発生！ サーバーが起動しない！</b>

このような場合によくあるのは、
サーバーが起動したままターミナルを閉じて、
ログが残ったままのために起動しないパターン。
その場合は、こちらの解決方法でOKです。

https://qiita.com/TechOtome/items/d33f05840253fad44717


しかし今回はちょっと違う。はて？
よくよくエラー文を探ると

```bash
dynamic_matchers.rb:22:in `method_missing': undefined method `valitades' for User (call 'User.connection' to establish a connection):Class (NoMethodError)
Did you mean?  validates
               validates!
               validate
```

どうやら<b>スペルミス</b>をしているらしい。
さっそくバリデーションを記述したUserモデルの記述を見る。

```ruby:user.rb
  valitades :birthday, presence: true
```

なるほど！
`validates`とするべきところでスペルミスがあります。
バリデーションの記述をミスると、
ローカルサーバーも起動しないんですね。

スペルミスとendの位置のエラーは極力減らしたいなと痛感しました。
早速修正すると無事に動き出しました。

```bash
% rails s
=> Booting Puma
=> Rails 6.0.3.7 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 3.12.6 (ruby 2.6.5-p114), codename: Llamas in Pajamas
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://localhost:3000
Use Ctrl-C to stop
```
Gatsbyビルド時にOutgoingMessage.prototype._headers is deprecatedと怒られる件

# はじめに
こんにちは。名探偵コナンの99巻を買って2か月ほど経ちました。まだ読んでいません、筆者です :innocent: 

さて、Gatsbyプロジェクトビルド時になんかエラーが出てたのでそれ対応した話です。
同じエラーが出て困っている方の参考になれば幸いです:pray:

# エラーはこれ

```sh
$ gastby develop
...
...

ERROR 

(node:21481) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
(Use `node --trace-deprecation ...` to show where the warning was created)
```

廃止されたんすか:thinking:

# ほんとだ...廃止されてた :innocent: 

https://nodejs.org/api/deprecations.html#DEP0066

### 追記
上記リンク踏んで思ったのですが、アンカーリンクが期待通りの動きをしないので、ページ内を `DEP0066` で検索して下さい:bow:

# とりあえず助言通りオプション付けて実行してみた

```sh
$ node --trace-deprecation node_modules/gatsby/dist/bin/gatsby develop
...
...

ERROR 

(node:23379) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
    at module.exports (/home/workspace/node_modules/timed-out/index.js:9:17)
    at EventEmitter.<anonymous> (/home/workspace/node_modules/got/index.js:244:5)
    at Object.onceWrapper (node:events:476:26)
    at EventEmitter.emit (node:events:369:20)
    at makeRequest (/home/workspace/node_modules/cacheable-request/src/index.js:94:9)
    at /home/workspace/node_modules/cacheable-request/src/index.js:104:14
    at runNextTicks (node:internal/process/task_queues:59:5)
    at processImmediate (node:internal/timers:437:9)
```

お、**got**さんが古そう :thinking: 

# 最新のgotをインストールする

```sh
$ npm install got@latest
```

# 再度`gatsby develp`してみる

エラーが出なくなった :v:

# おわりに
こういう系ほったらかしにしがちですが、ぺちぺちやれば普通に直ってよかったです:pray:

本当はサイトマップが生成されなくなった原因を追ってて、ビルド時にエラーはいていたのを対応すれば出るようになると思ったのですが、全然関係なかったです :sweat: 

でも少しすっきりしました！
それでは！
Azure AD B2Cのユーザーフローで日本語のカスタム属性を追加する方法

# はじめに
Azure AD B2Cのユーザーフローでは、姓名やメールアドレスなどデフォルトの属性は日本語に対応していますが、
カスタム属性名については、英語でしか追加することができません。
そのため、英語で登録後、日本語のJsonリソースファイルを編集して、日本語化する必要があります。

##　前提
ユーザーフローの'言語のカスタマイズを有効'にして、日本語を有効にしていることを前提。

# 手順
1. 以下よりカスタム属性と登録しますAzure AD B2C -> ユーザー属性 -> 追加 
2. 以下にアクセスしますAzure AD B2C -> ユーザーフロー -> (任意のユーザーフローを選択) -> ユーザー属性 
3. 手順 1 にて登録したカスタム属性などにチェックをいれ、保存します。  
4. 以下にアクセスしますAzure AD B2C -> ユーザーフロー -> (任意のユーザーフローを選択) -> 言語 -> 日本語
5. ローカル アカウントのサインアップページにて、「規定値のダウンロード (ja)」をクリックし、Json ファイルをダウンロードします。 
6. Json ファイルを任意のエディタで開き、属性名で検索をして、拡張属性が登録されていることを確認します。 
![image004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/33c066cf-c549-2e66-59da-be6fda115353.png)
7. StringId が DisplayName であるブロックの Value の値を、ユーザーフローにて表示させたい任意の値に変更します。 
![image005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/c294e90d-8e17-32f1-6b82-44a83391a11f.png)

8. Json ファイルを保存します。 
![image006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/44de9017-1d78-88f4-1224-07c1f015d63f.png)

9. Azure ポータルに戻り、「新しいオーバーライドのアップロード」をクリックし、先ほど保存した Json ファイルを選択してアップロードします。
![image007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/6f7fc4bf-7de8-0dae-90e1-8ce3988a040c.png)

10. ユーザーフローを実行して、期待される表示名になっていることを確認します。 
![image008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416412/a9809642-d8a3-cd2e-dd73-1d1627b7c57a.png)
「備忘録」PHP PSR-15 Middleware ライブラリ検討

# 検討目的

今のサービスのポイント交換システムのビジネスロジックをWorkflow化したい。

# 背景

- 交換トランザクションの作業単位に関して、AOP観点でのWorkflow定義＆共通化をしたい。
    - 例：メンテナンスチェック、ユーザー状態チェックなどは、全てのトランザクションの作業単位において実行されるものとしてAspectとみなし、必要な作業単位の前処理（ミドルウェア化）としてWorkflow化する。
- ビジネスロジックのコンポーネント化（ミドルウェア化）
    - 依存性を最小化、拡張性を確報
- 新しい要件に対して、基本Workflowを従い、新しいビジネスロジックのみ新しく実装することで、たやすく新しい仕様・機能を追加できるようにする。
- Workflowに対しても、基本Workflowから拡張し、必要によってコンポーネントを追加・削除・バージョンアップができるようにし、拡張にも優しいものにしたい。


# Middleware Pattern

- 何らかの処理単位の全体において、始まりと終わりの途中に位置する、特定の処理を遂行するプログラム、またはコンポーネントの概念
- Node.jsのExpressでは、HTTPデータ通信処理のREQUESTとRESPONSEの間に存在するコンポーネント
- PHPとPSR-15でも、似たような定義とされている。
    - https://www.php-fig.org/psr/psr-15/
- Laravel Frameworkは基本Middleware Pattern機能を提供している。
    - https://laravel.com/docs/8.x/middleware

# Middleware ライブラリの情報

### awesome-psr15-middlewares
https://github.com/middlewares/awesome-psr15-middlewares

### relayphp
https://relayphp.com/
【React Native】 「React Native Gesture Handler」を使ってスライド/スワイプでアクションする

# はじめに

昔のiPhoneのように、右にスライドしてロック画面を解除したり、ボタンなどをスライドすることで何かアクションを起こしたいなと思って調べた時のメモ。


# 内容

「react-native-gesture-responder」を使って、スライドを実現。
※https://www.npmjs.com/package/react-native-gesture-responder

以下の例は、左から右にスライドさせたときに動作させる例です。
吟じる人とは逆の方向です。

吟じる人と同じ方向がいい人は、参考ページより調べてみてください。

```react
// 「react-native-gesture-handler」を読み込む
import Swipeable from 'react-native-gesture-handler/Swipeable';

// スワイプした後に裏で表示する領域
const LeftSwipeActions = () => {
  return (
    <View style={{ flex: 1, justifyContent: 'center' }}>
    </View>
  );
};

// スワイプで処理を行う
const swipeFromLeftOpen = () => {
  // somethingAction();
};

// スワイプ領域をレンダリングする部分
const RenderItem = () => (
  // スワイプ領域
  <Swipeable
    renderLeftActions={LeftSwipeActions}
    onSwipeableLeftOpen={swipeFromLeftOpen}
  >
    <View
      style={{
        paddingHorizontal: 30,
        paddingVertical: 20,
        backgroundColor: 'white',
      }}
    >
      <Text>
        hogehoge
      </Text>
    </View>
  </Swipeable>
);
```


# 参考
- https://blog.logrocket.com/react-native-gesture-handler-swipe-long-press-and-more/
- https://blog.bitsrc.io/using-the-gesture-handler-in-react-native-c07f84ddfa49
雑誌風Webデザインのススメ

CSSで「なかなか良いんじゃね？」っていうデザインが出来た話

##自己紹介
令和3年に自分の個人サイトを運営しております。ShoyoFILMSと申します。
（良かったら見てね。崩れてたらすみませんがコメントで教えてください）
https://fujiformat.com/
※気分でデザインが変わってる可能性があります。

せっかくだから色んなアイディアや技術の試験場にしようと日々手を入れているわけですが、
トップページは前から「雑誌風」にしようと思ってました。
![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82103/3d72e89b-eac9-70c5-eab3-d274b0057f4c.jpeg)

##雑誌風デザインとは
雑誌風とは真ん中にドーンとビジュアルがあって周りに各ナビゲーションがあるデザインの事。
最近のWebではヒーローバナーという大きな画像がトップに載ることがありますが、
それだとナビゲーションが下に押し下げられてしまうのが嫌だったのでこうしました。

今はコンテンツ等を更新して「新刊」が出る度リンクの色を新しい物にするぐらいですが、いずれ
背景の自画像を更新したり、別の絵を用意したりしたいですね。
あと自分のアプリとかを作ったら右端の下あたりに並べる予定です。
世の中がマテリアルデザインとかを採用してる時に、これを出すのはあれですが趣味なので許容してください:blush:

##作り方
センタリングした領域にposition:absolute;で色々固定してるだけです。
レイヤーの重なりをz-indexで調整しないとナビゲーションとか押せなくなるので注意

一見オシャレですが、position:absolute;を使いまくってるので使ってないサイトに比べると若干重いかも。

##スマホ対応
※PCとスマホで違うページが出るようになってます。
スマホ版は画面が細長いと画像とナビゲーションが被ってしまうため、背景を半透明の黒にして
視認性をアップしました。タブレット向けに1段階のレスポンシブ対応も入れてます。

![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82103/29b82136-0a93-44f5-b778-17e4c0324fcf.jpeg)

##最後に
対応するかはわかりませんが、こうした方がいいとかあったらコメントに書いてください。
あともし私も個人サイトまだ運営してるよって方がいたら、ぜひ連絡を。
情報交換したり、令和の個人サイトリンク作りましょう！
Webサイトを公開する上で必要な「利用規約」と「プライバシーポリシー」について理解する


# 利用規約とは
サービス内容や利用料、サービス利用にあたっての禁止事項、トラブル発生時の解決方法など事業者とユーザーがそれぞれ守らなくてはならないルールを定める。
これによってトラブル発生時の対処しやすくなったり、ユーザーの意図しない利用を防止できる。
経産省の「電子商取引及び情報財取引等に関する準則」によると
>(1)利用者がサイト利用規約の内容を事前に容易に確認できるように適切にサイト利用規約をウェブサイトに掲載して開示されていること、及び
(2)利用者が開示されているサイト利用規約に従い契約を締結することに同意していると認定できることが必要である。
https://www.meti.go.jp/press/2019/12/20191219003/20191219003.html

ことが記載されておりサービス利用前の利用規約の開示と同意が必要である。

# プライバシーポリシーとは
事業者の個人情報の取り扱いを定めたもの。
これにより個人情報保護法やプライバシーマーク制度に対応することが可能。

### 個人情報保護法
個人の権利利益を保護することを目的とした個人情報の取扱いに関連する法律。
令和２年６月12日に「個人情報の保護に関する法律等の一部を改正する法律」が施行された。
[概要資料](https://www.ppc.go.jp/files/pdf/200612_gaiyou.pdf)

個人情報とは、個人を特定できる情報で、氏名や住所などはもちろんだが、メールアドレスに氏名や誕生日などが含まれている場合にも個人情報に該当ため、要注意。

#### どこに設置するか
[個人情報の保護に関する法律についてのガイドライン](https://www.ppc.go.jp/files/pdf/201001_guidelines01.pdf)によるとホームページのトップページから 1 回程度の操作で到達できる場所に設置することが推奨されている。

# 記載すること 
- 開示請求などの窓口
- 開示請求などのやり方や、提出する書類の様式
- 本人確認の方法
- 手数料の額と取り方

利用規約にプライバシーポリシーを含めることも可能なので、ひとまとめにすると楽です。。
CDNについてざっくり理解する

# CDNとは？
CDNとはContent Delivery Networkの略で、ウェブコンテンツを高速かつ効率的に配信できるように最適化されたネットワーク。
アクセス元に最も近いキャッシュサーバーからウェブコンテンツを配信することで、サーバーの負荷軽減やウェブコンテンツを世界中に高速で配信できるなどの利点がある。

# CDNを構成する４つの主な要素
### ①CNAME
DNSのリソースレコードの設定タイプの１つで、リクエストURLのまま別のサイトの内容を表示させることができる。
CNAMEを利用することによりキャッシュサーバーにアクセスさせる。
　例
 www.example.comでリクエストすると、www.google.comにアクセスされるなど

### ②キャッシュ対象
一般にWebアプリ全体を対象とする方法と、一部のみをキャッシュする方法が存在する。
ただしくキャッシュ対象を選ばないとCDNの利点を活かせなかったり、キャッシュ事故(個人情報のページをキャッシュすることで他人がその個人情報のページを閲覧できてしまう)が発生するので注意が必要。

### ③Origin Server
元となるウェブコンテンツを構成するファイル群が格納されたサーバー。

### ④キャッシュ時間
Origin Serverにアクセスする頻度で、キャッシュ時間が３０秒なら３０秒間ごとにOrigin Serverを参照することになる。
これによりOrigin Serverのトラフィックを制御することができるが、配信コンテンツの変更が即座に行われない欠点もある

# CDNの利点と欠点まとめ
|利点|欠点|
--- | --- |
|帯域制限を気にしなくてすむ|キャッシュ事故が起こりうる|
|サーバー負荷低減|キャッシュ時間は配信コンテンツの変更が反映されない|
|Origin Serverからの転送容量削減|キャッシュの削除に時間がかかる場合がある|
|　|アクセスログが取りづらくなる|
|　|すべてのアクセスがキャッシュサーバーを経由するため料金が高くなる場合がある|
自作PCにwsl2で開発環境を整える～wsl導入編～

# Abstract
自作PCにwsl2を突っ込んで開発環境を整えようとした私。
良さげな記事も見つけ、導入に着手するが……

---
以下のような内容を用意しています。

- WSL2の導入
- Ubuntuの入手
    - Microsoft Storeが、動かない（別記事へ移動）
- Ubuntuの起動
    - error: 0x80370102
- マシンの仮想化の有効化

# そうだ、PC作ろう
と思い至り、自作PCとやらに手を出してみました。
なんとなく動いたのでそこにwslを導入して開発環境を整えようと思い至り始めたのですが、どうもうまくいかないことも多かったので備忘録をば……

### マシンスペック
**CPU**　　AMD Ryzen 9 3900X 12-Core Processor
**メモリ**　　16GB
**ディスク**　　1TB（SSD）＋3TB（HDD）
**GPU**　　NVIDIA GeForce GTX 1070
**BIOS**　　MSI（バージョンは忘れた）

# WSL2の導入
## Windowsのバージョン確認
`Win`＋`R`を押して、`winver`と打てばwindowsのバージョンを確認することができるので、まずは自分のwindows10がwsl2に対応したバージョンなのかを確認します。
### 対応バージョン
- Windows 10 version 2004
- Windows 10 version 1903 and 1909

## "Windows Subsystem for Linux"の有効化
PowerShellを管理者として開き、以下を実行します。

```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
```

## "Virtual Machine Platform"の有効化
次に以下を実行します。指示に従って、`Y`を押してPCを再起動しましょう。

```powershell
dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all
```

## WSL2のカーネルのインストール
[WSLの公式ドキュメント](https://docs.microsoft.com/ja-jp/windows/wsl/install-win10#step-4---download-the-linux-kernel-update-package)から、WSL2用のLinuxカーネルをDLしてきます。
`x64 マシン用 WSL2 Linux カーネル更新プログラム パッケージ`みたいに書かれたリンクをクリックすれば大丈夫です。

DLが終わったら実行してインストールしましょう。

:::note info
編集後記載
カーネルのダウンロードページが[こちら](https://learn.microsoft.com/ja-jp/windows/wsl/install-manual)に変更されていそうです。
また、現在ではカーネルからインストールしなくとも、管理者モードで以下を実行する形で良さそうです。
```powershell
wsl --install
```
:::

## WSL2を使うようにする
デフォルトだとWSL1を使用するようになっています。
PowerShellで以下を実行して、デフォルトを変更します。

```powershell
wsl --set-default-version 2
```

## Linuxディストリビューションをインストール
1. Microsoft Storeを起動して、ディストリビューションを検索
Ubuntu以外に、DebianやSLESとかもあります。
Ubuntuを入れるのであれば、バージョンの書いてあるものをインストールする方がいいでしょう。無印のUbuntuだと、インストール時期によってバージョンが変わるとかなんとか。

2. 「`入手`」ボタンをクリック……
って、あれれ～おかしいぞ～
どういうわけかボタンを押してもうんともすんとも言いません。
結果としてとても時間がかかったので、[こちらの方に](https://qiita.com/SatoshiNonomura/items/4b060312ca8f9094d2ed)書きます。

3. 起動
スタートメニューからUbuntuを起動します。

4. 初回起動
初回起動時にユーザーとパスワードの設定が聞かれるはずだからそれを設定したらいいはず…… !?
あれれ～おかしいぞ～
Ubuntuのwindowsには次のような文字が……

```terminal
Installing. this may take a few minutes.
WslRegisterDistribution failed with error: 0x80370102
```

どうやら、PC本体の仮想化が無効になっていたようです。

## マシンの仮想化の有効化
上の4でユーザー名とパスワードの設定ができれば気にする必要はありません。
上のエラーの原因は、BIOSの設定をいじることで解決できます。
特にAMD製のCPUであれば、初期設定では無効化されていることが多いそうです。

### MSIの場合
1. `EAZY MODE`で起動されているのであれば、`F12`または`ADVANCED MODE`ボタンを押します。
2. `OC`を選択。
3. `CPU拡張設定`とか、`CPU何とかSetting`みたいなのを選択。
4. `SVM Mode`の設定を`無効`/`disable`から`有効`/`enable`に変更。
5. 保存してwindowsを再起動

これで終わりです。OCのところにあるのはなかなかに罠でした。

### 他社の場合
そのうち書きます。

## Ubuntuの起動
起動したら次はちゃんと行けました。

# 次回予告
[次回：WSL2のセッティング](https://qiita.com/SatoshiNonomura/items/f1cb264f11becc5b4a5c)

# 参考
[【WSL2】wsl2のインストールで0x80370102 エラーが出たときの対処方法【HP】](https://monkey999por.hatenablog.com/entry/2020/10/01/221243)