OmniAICreator/Qiita-1.07M huggingface dataset:
Docker composeではまっていたこと

## confファイルを編集しても、反映されない
docker-compose再起動する際、Dockerfileにあるcp A.conf B.confは毎回起動されません。
一度、コンテナとイメージを削除し、再度docker-compose upを実行する必要がある。

## gitlabのcontainerの中のgitlab.rbを修正したら、gitlabが使えなくなった。
volumnsでホストへconfig設定が反映されます。たとえcontainer, imageを削除したとしても、読み込まれるので、間違えた設定がそのまま新しいimage, containerに読み込まれる。

## VolumnsでERROR: Named volume "test:/myapp:rw" is used in service "web" but no declaration was found in the volumes section.

"/test:/myapp" testの先頭に"/"を入れると解決。

## Docker-composeとNginxの設定
default.confでの設定は
server{
    listen       80;　#port番号
    server_name  localhost
}

    location /sonarqube{ # localhost/sonarqubeでリクエストが来る。

        proxy_pass              http://172.31.0.5:9000; #コンテナ間の通信用IPアドレスを設定するべき
    }
$ docker network inspect [network名]で対象ServiceのIPを調べられる。また、Docker-composeにて固定IPの指定が必要。

# ERR_CONNECTION_REFUSED
httpsをNginx.confで設定したものの、ERR_CONNECTION_REFUSEDエラーが出ます。
docker-composeでNginxの443ポートを開ける必要があります。
AGC 018 A Getting Difference

##問題
https://atcoder.jp/contests/agc018/tasks/agc018_a
##見た感じ
最初に考え付いた方法は

```math
k<a[i]~\land~k\%\gcd(a[i],a[j])
```
を満たすような$i,j$を見つければいいやんってなったけど、これだと$k<a[i]$を満たす$i$の個数によってはめちゃくちゃ時間がかかるからTLEした。
最終的な解き方は、$a[i]$全部の最大公約数$g$と$a[i]$の最大値$M$を用意して、$k\%g=0\land~k\leq M$なら作れるという判定。
なぜこれが正しいかというと、引き算操作をしまくると、最終的に$g$が要素として含まれるようになり、これを$M$からどんどん引いていけば$M$以下の$g$の倍数は全部出てくる。だから上の条件を満たせば$k$を出すことができる。
逆に、$k$が出せるとき上を満たすのは引き算操作では最大公約数が変わらないことからわかる。
##解法
$k\%g=0\land~k\leq M$を確認
##ソースコード
```c++
const int N_MAX=100005;
int n,k;
int a[N_MAX];

void Main(){
    int x=0,y=INF10,z=1;
    //入力
    cin>>n>>k;
    rep(i,n){
        cin>>a[i];
        maxin(z,a[i]);
    }
    //処理
    if(n!=1)x=mygcd(a[0],a[1]);
    rep(i,n-2){
        x=mygcd(x,a[i+2]);
    }
    if(k<=z&&k%x==0){
        cout << "POSSIBLE" <<endl;
    }else
    /*sort(a,a+n);
    int cou=n-1;
    while(a[cou]>k){
        rep(i,cou){
            if(k%mygcd(a[cou],a[i])==0){
                cout << "POSSIBLE" <<endl;
                return;
            }
        }
        cou--;
    }*/
    //出力
    cout << "IMPOSSIBLE" <<endl;
}

int main(){
    cin.tie(nullptr);
    cout<<fixed<<setprecision(12);
    Main();
}
```
元の方針の残骸が残ってる。。
EC2 インスタンス名の一部からインスタンス情報を瞬時に出す

# 背景

あ、あの情報が必要なんだけど、なんだっけな。。
という時に、さくっと情報を取り出せたらスマートですよね。

業務上、EC2 インスタンスID 知りたくなることがあります。
[SSH over Session Manager](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html) で接続したいので、インスタンスID が必要だったり、 aws cli で AMI作りたいので、インスタンスID が必要だったり。

ブラウザからAWSコンソールにアクセスして調べたり aws cli で [describe-instances](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/session-manager-getting-started-enable-ssh-connections.html) を使って調べることももちろん可能です。

ただただ、スマートではありません。
調べようとしているうちに、他のエンジニアから質問を受けて、
あれ、何を調べようとしてたんだっけと、コンテキストスイッチが発生して、時間が余計にかかってしまいます。
（※ 質問するのがダメとか言いたいわけではありませんｗ）

# 前提

- aws cli がインストール済みである
- EC2 を業務でよくさわる

# 対応

簡単です

```
$ cat <<'FUNCTION' >> ~/.$(basename $SHELL)rc
function guess-ec2() {
    function help() {
         cat <<EOT >&2
guess-ec2 <guess> <profile>

    <guess> ec2 インスタンスの tag:Name の文字列の一部を指定します
    <profile> aws-cli で指定するプロファイルがある場合は指定します (任意)

ex.
    1. guess-ec2 web prod
    2. guess-ec2 batch
EOT
    }

    if [ $# -eq 0 ]; then
        echo 引数は1つ以上指定してください >&2
        help
        return 1;
    fi

    GUESS=$1
    PROFILE=default
    if [ $# -ge 2 ]; then
        PROFILE="$2"
    fi
    aws --profile $PROFILE \
        ec2 describe-instances \
        --filter "Name=tag:Name,Values=*$GUESS*" \
        --query 'Reservations[].Instances[].{id:InstanceId,name:Tags[?Key==`Name`].Value|[0],ip:PrivateIpAddress}'
}
FUNCTION

// shell をリロード
$ $SHELL -l
```

これでOK
`guess-ec2 $｛tag:Name の一部｝` と打つと欲しい情報が瞬時にとれます
情報が取れたあと、他のエンジニアから質問されても
そうだった、インスタンスID がほしかったんだと、仕事もスムーズです。

```
$ guess-ec2 web
[
    {
        "id": "i-0bdafc0a9",
        "name": "production-web",
        "ip": "10.0.16.94"
    },
    {
        "id": "i-ef7ff14d",
        "name": "production-web",
        "ip": "10.0.23.84"
    }
]
```
[Ubuntu18.04]ディスプレイの解像度がいきなり800x600になったお話

# 症状
ubuntu18.04とWindows10でデュアルブートしていて、使っていたディスプレイの解像度は1920×1080だった。
ある日起動してみると、ログイン画面から解像度がとても低く、設定画面をなんとか開くと **800x600** になってしまっていた。
しかも、設定画面からディスプレイの解像度は変更できず、**800x600以外選べなくなっていた**。

とにかく操作がしにくい
![Screenshot from 2020-07-28 16-24-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/73f5fe36-73fb-dd4f-f410-7ad5cb896731.png)


Windows側からはディスプレイの解像度はおかしくなく、Ubuntu側の問題だと考えられる。

# 現状確認
とにかく現状を確認したい。
`Ctrl`+`Alt`+`T`で端末を起動し、次のコマンドを叩いて認識している解像度の確認を行う。

```text:端末
$ sudo apt-get install inxi
$ inxi -G
```
すると、以下のような情報が得られる。
![Screenshot from 2020-07-28 16-25-24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/473ab6a3-fdba-5cf3-3b09-1535e18478cc.png)

確かに、Ubuntu側からは800x600になってしまっている。
<font color="Gray">*ここで、ドライバーが違うものになっていることに気がついていればもう少し早く解決したのだが…*
</font>

# 応急処置(無理やり直す方法)
とにかく、grubの設定を無理やり変えて解像度をかえることにした。
端末で以下のコマンドを叩いて、grubの設定を行う。
(エディターはvimでもgeditでもなんでもよいが、筆者はnanoが一番好きなのでnanoを使う)

```text:端末
$ sudo nano /etc/default/grub
```

開いたファイルに以下の文を追加する。
すでにコメントアウトされている行があるのでそこを利用しても良い。

```text:/etc/default/grub
GRUB_GFXMODE=1920x1080
```

grubを更新して、その後再起動をかける。

```text:端末
$ sudo update-grub
$ reboot
```

ちゃんと、解像度が戻ってだいぶ操作がしやすくなった。
![Screenshot from 2020-07-28 16-50-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/f485b863-a290-9b85-92b1-56b2f6abee42.png)

しかし、いまだ設定画面からディスプレイの解像度は変更できず、**1920x1080以外選べない**。

# 原因とその解決法(ちゃんと直す方法)
解像度が認識できなくなった原因はなんだったのか色々探っていると、どうやらグラフィックボードのドライバが怪しいことがわかった。

グラフィックボードのドライバの確認は、「ソフトウェアとアップデート」というアプリケーションを左下の９つの点のアイコンの「アプリケーションを表示する」から開く。
![Screenshot from 2020-07-28 16-57-23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/6ad7648f-1cde-389f-1efd-01296b3af57d.png)

「追加のドライバー」のタブを開くと、今使っているグラフィックボードのドライバを見ることができる。画像は修正した後なので検証済みの正しいドライバを選択しているが、もともとは**別のドライバを選択していた**。どうやら、何かの拍子にドライバが変更されていたことが原因のようだ。

![Screenshot from 2020-07-28 16-57-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/4bf98cb1-45fd-10df-d4ab-bd13bbafa49a.png)

こいつを正しく検証済みのやつを選択して、変更を適応してやると解像度も正しくなってくれるはずだ。
変更を適応する際、再起動したときの認証用パスワードの設定が英語で求められるが、適当に設定してやればよい。
あとは再起動すると、~~途中なにか出てくるが~~正しく解像度が認識される。

設定画面からディスプレイの解像度を選択できるようになっていた。めでたしめでたし。
![Screenshot from 2020-07-28 17-07-06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/596310/c0174e95-6eee-17cd-a5cc-0ab462db55bc.png)


# 参考記事
[Ubuntu18.04で突然解像度がおかしくなったときの対処法](https://qiita.com/nsd24/items/c06294d1de40f2e9870b)
東京大学計数工学科講義「AWSによるクラウド入門」をやってみた



東京大学計数工学科で開講されている講義資料「[AWSによるクラウド入門](https://tomomano.gitlab.io/intro-aws/)」が公開されており、AWSの基礎だけでなく、機械学習やサーバレスなどもHands-Onを通じて学べるということで、早速実施してみました。

クラウド入門者向けに簡潔かつ平易な言葉で書かれており、大変勉強になりました。飽き性の私でも最後まで楽しんでできました。


#かかった時間と費用

・一通り解説を流し読み、Hands-Onも全て実行して、約4時間
・費用は、0.49ドル

![cost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152321/b7be2d10-3eca-e93b-9a84-27f9d5d8c42a.png)



#学べること

大きく以下３点です。気になるキーワードがあれば、そこだけ掻い摘むのも良いのではないかと思います。

###クラウドの基礎
・クラウドの基礎となる概念・知識
・セキュリティやネットワークなど，クラウドを利用する上で最低限おさえなければいけないポイント理解
・ハンズオン：仮想サーバーをAWSに立ち上げる
・キーワード：AWS CLI、AWS CDK、CloudFormation、VPC、EC2、Security Group


###クラウドで行う機械学習
・クラウド上で機械学習を走らせるための入門となる知識・技術
・Docker に自分のプログラムをパッケージングする手順
・ハンズオン１：AWSでJupyter notebookを使って簡単な機械学習の計算を走らせる
・ハンズオン２：ディープラーニングを用いた自然言語処理により，質問に自動で回答を生成するボットを作成
・キーワード：GPU、DLAMI、Jupyter notebook、PyTorch、MNIST、Docker、Elastic Container Service (ECS)、Fargate、Transformer

###Serverless Architecture
・Serverless architectureと呼ばれる最新のクラウドのアーキテクチャを解説
・ハンズオン１：簡単なデータベースをクラウド上に作成
・ハンズオン２：俳句を投稿するSNS "Bashoutter" 作成
・キーワード：REST API、Lamba、S3、DynamoDB、API Gateway、Simple Notification Service、Step Functions

#おわりに


１点だけ、詰まったというか、記載通りにならなかった箇所がありましたので、備忘録的に残しておきます。


「6.3. スタックのデプロイ」で、GPU搭載の仮想マシンを立ち上げようとすると、以下のようなエラーとなりました。


> | CREATE_FAILED        | AWS::EC2::Instance                    | Ec2ForDlInstanceF0415522
You have requested more vCPU capacity than your current vCPU limit of 0 allows for the instance buck
et that the specified instance type belongs to. Please visit http://aws.amazon.com/contact-us/ec2-re


対処法は、エラーメッセージにもありますが、立ち上げられるvCPUの制限が初期値だと０なので、その上限を上げてもらう必要があります。

以下のように、制限緩和のリクエストを投げれば、１０分ほどで作業完了の連絡がありました。その後、再度デプロイすれば、うまく行きます。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/152321/b7734a70-3282-4fe8-d0dc-fd23b89dde24.png)
【Nuxt.js】Nuxt文法編：asyncData

🎈 この記事はWP専用です
https://wp.me/pc9NHC-ut

2021/02/19
数カ所間違いがありました。
申し訳ございません。
また、訂正版の記事を公開しました！
こちらをご覧ください✨👀
[【Nuxt.js】Nuxt文法編：非同期通信やasyncDataの使い方)](https://nuxt.alizlab.com/%e3%80%90nuxt-js%e3%80%91nuxt%e6%96%87%e6%b3%95%e7%b7%a8%ef%bc%9a%e9%9d%9e%e5%90%8c%e6%9c%9f%e9%80%9a%e4%bf%a1%e3%82%84asyncdata%e3%81%ae%e4%bd%bf%e3%81%84%e6%96%b9/)

# 前置き
非同期通信で使うasyncData
まとめました📚🙋‍♀️

・非同期通信とは
・Promiseとは
・asyncDataの役割と書き方(Promiseとasync/await)

分かるところは飛ばしてくださいね ✈️

# 非同期処理とは
こちらのツイートが分かりやすいかと思います💡

https://twitter.com/ichikun0000/status/1283909871310499840?s=20

結果を待たずに
すぐに処理ができるということです🏃‍♀️💨

温めた商品が手元にくる前に
会計を先に済ませることができる
というわけです！

これが同期処理なら
温めてる間はずっと店員さんが
レンジの前にいて、
温め終わってからでしか会計できません。

コードでいうなら…
⬇️の例でご覧ください🌟👀

# Promise
## Promiseとは

🎈 続きはWPでご覧ください👀
https://wp.me/pc9NHC-ut
iOS + Safari + Bearer認証 + BASIC認証でBearer認証が無効化される件と対策

表題の通り。
iOS ChromeとかMac Safariは知らん。

https://qiita.com/ksakiyama134/items/efad0e48464e0f501d76
こういうことらしい。

# 解決方法
**Authorization Header** ではなく **Authorization2 Header** など別名ヘッダで送ればよくね？

と思ったら割とメジャーでした。
https://qiita.com/uasi/items/cfb60588daa18c2ec6f5
PHPのセキュリティ関係

この記事は以下の書籍のアウトプットとして執筆しました。

- [体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［固定版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/dp/B07DVY4H3M/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)

#Webアプリケーションの入力は何をするか
入力処理では入力値に対して以下の処理を行う

a. 文字エンコーディングの妥当性検証
  →文字エンコーディングを使った攻撃対策ため  
b. 文字エンコーディングの変換
  →HTTPメッセージとプログラム内部でも自演コーディグが異なるため
c. 入力値の妥当性検証
  →セキュリティ上の保険的な対策

##文字エンコーディングの検証
PHPではmb_check_encoding関数が使える

##文字エンコーディングの変換
PHPはphp.iniでの設定で自動変換と明示的な返還を選べる。

##入力値検証
###バイナリセーフとヌルバイト攻撃
####バイナリセーフ
入力値がどんなバイト列であっても正しく扱えることを意味する。
典型亭には値ゼロのバイト(ヌルバイト、PHP言語では\0と表記)が現れても正しく処理することを指す。

ヌルバイトが特別扱いされるのはC言語及びUnixやウィンドウズのAPIでは、ヌルバイトを文字列の終端とみなす取り決めがある。

C言語で開発されたPHPは塗るバイトを文字列の終端としてそれ以降を切り詰める関数がある。
このような関数をバイナリセーフでない関数という。

###eregの検査を回避
>この関数は PHP 5.3.0 で 非推奨 となり、 PHP 7.0.0 で 削除 されました。

```php5
<body>
<?php
  $p = $_GET['p'];
  if (ereg('^[0-9]+$', $p) === FALSE) {
    die('整数値を入力してください');
  }
  echo $p;
?>
</body>
```
>出典：[体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［固定版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/dp/B07DVY4H3M/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)より

このコードに対して以下のようにアクセスするとeregを回避される。
`?p=1%00<script>alert('XSS')</script>`
####回避される理由
URLの中に`%00`がある。これは値ゼロのバイトすなわちヌルバイトでereg関数はバイナリセーフの関数ではないため、塗るバイトがあるとそこで文字列が終わっていると判断してしまう。

ヌルバイト対策はバイナリセーフの関数のみを用いてアプリを開発すればいいが、それは困難

ファイル名のように仕様上ヌルバイトを許容しないパラメータがあるから。

このため、アプリの入り口で倍ナチセーフを使って入力値の塗るバイトをチェックして、塗るバイトがあればエラーにする方法がある

###制御文字のチェック
制御文字とは改行やタブ等通常表示されない文字のことでヌルバイトも含まれる。

###文字数のチェック
すべてのパラメータで最大文字数をチェックスべき。
これをチェックしておくとセキュリティ上で保険になる。
攻撃は文字列が長いことが多いため。

###PHPの正規表現
入力値検証には正規表現が便利。

|関数|説明|
|---|---|
|perg|文字エンコーディングがUTF-8の場合のみ日本語が使える|
|mb_ereg|様々な文字エンコーディングに使える|

####1文字以上5文字以下の英数字をチェックする正規表現

```php5
preg_match('/A[a-z0-9]{1,5}\z/ui',$p);
```
>出典：[体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［固定版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/dp/B07DVY4H3M/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)より

|名前|説明|
|---|---|
|u修飾子|UTF-8エンコーディングであることを示す。|
|i修飾子|大文字小文字を区別しない|

u修飾子は不要の場合があるが。正規表現の「.」なドアが意図しない結果になるため、常にu修飾子を指定しておくほうがいい

#####全体一致は\Aと\zで示す
データの先頭は`\A`データの末尾は`\z`で示す。
`^`と`$`は「行の」先頭と末尾を示すものだから`$`は改行にマッチする。
このため`^`と`$`をデータの先頭・末尾として使うと不具合が生じる場合がある。

#参考文献

- [体系的に学ぶ 安全なWebアプリケーションの作り方 第2版［固定版］　脆弱性が生まれる原理と対策の実践](https://www.amazon.co.jp/dp/B07DVY4H3M/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)
cssだけで画像を使わずに三角形を描画する

cssだけで画像を使わずに三角形を描画する方法について。
軽くググるとおそらくborderを使って実現する方法がヒットするはず。

そのまま使えば目的達成の場合がほとんどでしょうが、パッと見ただけじゃどうしてあれで三角形になるのか謎ですよね。

そこで、どんな原理で三角形を描画しているのかをご紹介します。
理屈がわかればデザインの微調整だってできるはず！

<p class="codepen" data-height="975" data-theme-id="light" data-default-tab="css,result" data-user="ririli" data-slug-hash="XWXwpvz" style="height: 975px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="triangle">
  <span>See the Pen <a href="https://codepen.io/ririli/pen/XWXwpvz">
  triangle</a> by ririli (<a href="https://codepen.io/ririli">@ririli</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

サンプルは上か順を追って説明していきます。

## まずはfirstクラス
border-topを引いただけです。
当然ですがただの棒ですね。

## 次にsecondクラス
border-rightをたしてみました。
勘が良い人はここで気づくかも？

## 続いてthirdクラス
borderを太くしてみました。
おや、　topとrightのborderが重なる箇所が斜めになってますね...

## 核心に近づくfourthクラス
leftとbottomもたして正方形に。
三角形の面影が見えてきましたね。

## ついに三角形登場のfifthクラス
widthとheightを0にしてborderだけで全てが構成されるようにしました。
fourthクラスにあった真ん中の空間がなくなったことで斜めの線同士がくっついて見事三角形が出現しました。

## いらないものは消したsixthクラス
今回は下向きの三角形だけ残したかったのでright, left, bottomのborderを透明に変更しました。
当然上むきにしたければbottomだけを残して残りを透明にします。




## まとめ

以上がcssだけで三角形を描画する仕組みでした。
わかってしまえば単純。
原理がわかっていれば二等辺三角形にしてみたり、直角の位置を変えてみたり、夢無限大。
Tigerbrewでdcrawのインストールがコケる話。

#最初に
**この記事はTigerbrewを対象としています。Homebrewで同様の現象に当たった場合は[ここ](https://github.com/Homebrew/brew/issues)に報告してサポートを受けてください。**
**[2020/08/03追記]この問題を改善する[プルリク](https://github.com/mistydemeo/tigerbrew/pull/699)がマージされたので未だにこの症状にぶつかっている人はとりあえず`brew update`でもしてください。**

#環境
機種 Mac Pro 2,1 OS X 10.7.5(iMac 5,1 OS X 10.7.5でも確認済み)
Tigerbrew Ver 0.9.5 (git revision 5b532; last commit 2020-05-14)


#結論から
`brew edit dcraw`を実行する。
エディターが開くのでURLを`https://mirror.pnl.gov/macports/distfiles/dcraw/dcraw-9.26.0.tar.gz`に置き換える。

#原因
サーバー上のファイルが消えているため同一ファイルをもつ別サーバーを指定してダウンロードする。SHA256は同一。

#知見
google先生は有能。

#追記
xmltoでも同一症状があるのでPR投げます。
Zabbix の WEBインターフェイス聴取ポート変更 CentOS + Nginx の場合

単発でスミマセン...

#環境
- CentOS 8.2.2004
- Nginx 1.14.1
- Zabbix 5.0.1

#設定

```sh:/etc/nginx/conf.d/zabbix.conf
server {
        listen        <これ>;
...
```

既定では 80 ですね。

80/tcp を他サービスで使用するためであれば、Nginx 既定のサイトのほうのポートも変更しておいたほうが良いかも

```sh:/etc/nginx/nginx.conf
...
http {
    server {
        listen  <これ>;
...
```
Windows：バッチ：サブルーチンの戻り値を文字列として取得する

# exit /b [数値] と errorlevelを使わない方法

- 文字列や複数の戻り値を返したいときにerrorlevelを使った方法ではできない。
- そもそも、errorlevelはエラーについて設定するべきなのに、それ以外の値を当てるのは不自然。

```bat
@echo off

:: =================
:: 実行部分
:: =================

:main
   setlocal

   REM サブルーチンを呼び出し。第3引数に戻り値の変数にする文字列を設定
   call :join_values "A" ".txt" joined

   REM 第3引数を参照。A.txtと表示される
   echo %joined%

   endlocal
   exit /b

:: ===============================
:: 値結合
:: @param 結合値前半
:: @param 結合値後半
:: @param 戻り値：結合した値
:: ===============================

:join_values
   setlocal

   set v1=%~1
   set v2=%~2
   set ret=%v1%%v2%

   REM 第3引数の文字列を動的に変数として宣言し、値を設定。
   endlocal && set %3=%ret%
   exit /b

```
【Blender】Blenderで車のモデリングをしてみよう※随時アップデートしていきます

この記事は生配信に伴い、先行公開しました。
そのため、随時アップデートしていきます。
特に「この項目を先に書いてほしい!!」というのがあれば、リクエストを出してください。mm

# ざっくりした動画解説
[【ダイジェスト版】Blender2.83LTSで車を作ろう](https://youtu.be/ko7WT8Nf7Ik)

# この記事でできること
レーシングゲーム用の車をBlender2.83LTSでモデリングすることができます。

# この記事で身につくBlenderのスキル
- カメラ視点の移動の仕方
- ビューの使い方
- オブジェクトモードと編集モードの違い
- 面分割
- ミラーリング
- 押し出し
- トランスフォーム
- マテリアルで色をつける
- エクスポートと、unityへのインポート

# 元記事
- げたばこくらぶ元記事
- [blenderで車のモデリングをしてから、ペジェでコース作って、Unityでマリオカートみたいなレーシングゲームにするてんこもりなチュートリアル](https://getabakoclub.com/2018/11/29/blender%E3%81%A7%E8%BB%8A%E3%81%AE%E3%83%A2%E3%83%87%E3%83%AA%E3%83%B3%E3%82%B0%E3%82%92%E3%81%97%E3%81%A6%E3%81%8B%E3%82%89%E3%80%81%E3%83%9A%E3%82%B8%E3%82%A7%E3%81%A7%E3%82%B3%E3%83%BC%E3%82%B9/)
- ※Blender2.83LTSでの焼き直しと、qiitaや動画への公開については、ご本人の了承を得ております。ありがとうございます。

# Blenderのバージョン
- Blender2.83.3(LTS) 2020/07/28時点

# Blenderで車を作る流れ
## 環境構築編
### 車体編
#### キューブを出す
#### まっぷたつに面分割をする
#### 片側だけ削除する
#### モディファイアーの追加で、ミラーリングする
#### 片面を面分割する
#### 押し出しする
<img width="549" alt="スクリーンショット 2020-07-28 15.31.01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/d04854c9-3bbe-5001-1521-9a13936fe8aa.png">

### 車輪編
#### シャフトを作る
<img width="543" alt="スクリーンショット 2020-07-28 15.43.34.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/50fe902f-d268-8221-8b1d-9820228e3603.png">

#### タイヤを作る
<img width="528" alt="スクリーンショット 2020-07-28 16.05.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/a7932eab-48d6-f3e7-a654-0c4d948e20eb.png">

### 色塗り編
#### マテリアルの新規追加
<img width="527" alt="スクリーンショット 2020-07-28 16.19.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/6a2db46d-930c-e3ec-5ad6-7840d8d9299d.png">

### 色塗り編(細かいバージョン)
- 面選択をして、
- マテリアルを選択して、
- [割り当て]を選択する。
<img width="513" alt="スクリーンショット 2020-07-28 16.33.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/191635/b8bca350-da08-4b67-704e-b41a2471981b.png">

## エクスポート編(Blender)
## インポート編(unity)
Pdf.jsで"The cMap url must be specified"のエラーが出たときの解決法

散々探しても中々情報が出てきませんでしたが、
以下のサイトに解決法がありました。
[PDF.jsで日本語を表示させるのに苦労した話](https://sgthr7.qrunch.io/entries/vcXinBjoIIVXi3l8)

普通にエラーメッセージでググると
<code>pdfjsLib.cMapUrl = "~/cmaps/";
pdfjsLib.cMapPacked = true;</code>

みたいなワンライナーが出てくるかと思いますが、
私の場合はこれでは解決しませんでした。

解決法は以下

```ruby:main.js
pdfjsLib.getDocument({  
  url: '<PDFへのurlやpath>',  
  // モジュール内にあるcmapsディレクトリーへのpathを指定してください  
  // 末尾のスラッシュ'/'まで必須です  
  cMapUrl: './node_modules/pdfjs-dist/cmaps/',  
  cMapPacked: true,  
})  
```

＊htmlのscriptダグからpdf.jsを読み込んで使用する場合、変数名「PDJFS」は既にDeprecatedで動きません。
代わりに**「pdfjsLib」**を使いましょう。

【追記】
pdf.jsのサンプルはこちらにまとまっています。
https://github.com/mozilla/pdf.js/tree/master/examples
PythonのCMSはWagtailが一番だ！（多分）

#記事の内容
pythonのCMSとして、

- [django CMS](https://www.django-cms.org/en/)
- [mezzanine](http://mezzanine.jupo.org/)
- [wagtail](https://wagtail.io/)

なんかが挙げられると思います。
その中で、
[PythonでCMS、どれ使えばいいの？](https://qiita.com/jumpyoshim/items/5ec4ef7a5615b3c2e9ac)
を参考に、どれを使おうかなと悩んでいた場合、参考になるのではないかと思います。

#経験
CMSを使わずに、djangoで開発経験がありました。
この時、使っていたのは**django2系**です。

#結論
django CMS は、まだ使ったことがないので
**Mezzanine vs Wagtail**
でやりたいと思います。

結論としては、**Wagtail**をお勧めします。
なぜなら、(僕が知る限り)**Mezzanineは、Djnago1系がベース**なためです。
WordPressに慣れ親しんだ方であれば、確かに使いやすくとても便利ですが、
Django1系が2系以降とあまりにも互換性がないと感じまして、開発しずらいと思ました。

その点、wagtailはdjango2系以降も対応しているため、Mezzanineよりはいいのではないかと思います。
ただし、Wagtailの日本語資料が非常に少ない点は残念ですが、[Youtubeにまとめている方](https://www.youtube.com/channel/UCwbsAsY_C6EmGI6_JHhECEQ)
がいっらしゃったので、そちらを参考に頑張ってみてください。
英語がわからなくても、ソースコードと実行画面を見るだけでやりたいことは実装できるかと思います。







#参考文献
[PythonでCMS、どれ使えばいいの？](https://qiita.com/jumpyoshim/items/5ec4ef7a5615b3c2e9ac)
Toolbarのメニューの文字の色だけ変える方法

AndroidのToolbarのメニューの文字の色を変える方法でうまくいく方法が見つからなかったのでメモです。

## やりたいこと
こんな感じのことがやりたかった。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476234/0f77b5bb-e883-2bcc-9712-e1c6fe8db479.png" width="300px"/>

## やり方
styles.xmlに以下を記述

```xml:styles.xml
    <style name="BaseToolbar" parent="@style/Widget.AppCompat.Toolbar">
        <item name="android:theme">@style/ToolbarTheme</item>
    </style>

    <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Toolbar Title Color-->
        <item name="android:textColorPrimary">@color/blue</item>
    </style>
```
追加したstyleをtoolbarに適用

```xml
<androidx.appcompat.widget.Toolbar
    android:id="@+id/toolbar"
    android:layout_width="match_parent"
    android:layout_height="?attr/actionBarSize"
    style="@style/BaseToolbar"
    app:layout_scrollFlags="enterAlways" />
```

ここまでで、タイトルとメニューの色が変わるのでこんな感じになります。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/476234/a0e22e3b-6908-ff63-6d31-a67e45a1c32a.png" width="300px">

最後に、タイトルの文字の色を変えます。
Fragmentで

```kotlin
toolbar.setTitleTextColor(this.resources.getColor(R.color.black))
```

を記述すればタイトルだけ色が変わるので目的達成です。

## ハマったこと
ググって出てくるのは、

```xml
    <style name="BaseToolbar" parent="@style/Widget.AppCompat.Toolbar">
        <item name="android:theme">@style/ToolbarTheme</item>
    </style>

    <style name="ToolbarTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Toolbar Title Color-->
        <item name="android:textColorPrimary">@color/black</item>
        <!-- Toolbar menu overflow icon color -->
        <item name="android:textColorSecondary">@color/blue</item>
    </style>
```
みたいな古い情報ばかりでした。
textColorSecondaryの内容がメニューの色に反映されるってことでした。
ただ、実際は、戻るの矢印に反映されてしまい、メニューはtextColorPrimaryの色でした。

## 解決方法
textColorPrimaryでメニューの色が変わるので、タイトル共々変えてしまってタイトルの色はコードで再度指定してしまうと言う方法で解決しました。

もっといい方法を知っていました教えてください。
ラズベリーパイ用SDカード作成

#Raspberry Pi Imagerのインストール

##homebrewを使ってターミナルからインストール

```
brew cask install raspberry-pi-imager
```
##LaunchpadからRaspberry Pi Imagerを立ち上げる
インストールが終了したら、LaunchpadからRaspberry Pi Imagerを立ち上げます。
<img width="168" alt="スクリーンショット 2020-07-28 16.25.32.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/5f7b1ec2-d3c1-18e9-38a9-422092caeeb7.png">


##画面でchosse OSを選択

<img width="680" alt="スクリーンショット 2020-07-28 15.46.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/43c6d644-174d-e106-cd4a-841c1f71137b.png">


##一番上のRaspberry Pi OS(32bit)を選択

<img width="575" alt="スクリーンショット 2020-07-28 15.48.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/b1a6f03c-5e98-1fdb-d8f9-b4461014fdfc.png">


##続いてchoose SD cardを選択（SDカードはPCに差しておきましょう）

<img width="668" alt="スクリーンショット 2020-07-28 15.54.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/790b556d-dffa-9172-e9bf-e81f3eb3cc54.png">


##SDカードを選択します。

<img width="581" alt="スクリーンショット 2020-07-28 15.55.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/8c0f84e0-b5a0-e303-de73-a79afc2a3ec3.png">


##WRITEボタンを押して、書き込みます。

このSDカードの中のものは消させるよみたいな英語のメッセージが出てきたら、yesを選択して、続行します。

<img width="678" alt="スクリーンショット 2020-07-28 15.56.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/32238ad8-8cdf-d118-0109-6bef462068ab.png">
Apache2 の ssi 有効化

こちらと同じことを今のバージョンで行いました。
[ssi有効化](https://qiita.com/OTAGRAMER/items/181712979a7241b4a3db)

確認した Apache2 のバージョン

```text
$ apache2ctl -v
Server version: Apache/2.4.41 (Ubuntu)
Server built:   2020-04-13T17:19:17
```

モジュールのロード

```bash
sudo a2enmod include
```

設定ファイル

```text
<Directory /var/www/html/public_test>
	Options +Includes +FollowSymLinks
	AllowOverride none
	Require all granted
	AddType text/html .html
	AddOutputFilter INCLUDES .html
</Directory>
```

設定が正しいかの確認

```bash
sudo apache2ctl configtest
```

Apache2 の再起動

```bash
sudo systemctl restart apache2
```

テストに使った　html ファイル

```html:aaa.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-Control" content="no-cache" />
<meta http-equiv="CONTENT-TYPE" content="text/html; charset=utf-8" />
<title>ssi aaa
</title>
</head>
<body>
<p />
<h2>ssi のテスト</h2>
<!--#echo var="DATE_LOCAL" --><p />
<p />
Jul/28/2020 AM 06:00<br />
</body>
</html>
```

ブラウザーでアクセスした結果
![ssi_jul28_2020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/a5016f67-16e4-c08b-4ff6-9a4ebacddaf2.png)
docker: AWSから完全にuninstall


###1 dockerが作成したnetworkを削除
`docker network prune`

###2 pre-definedのnetworkも削除
`service docker stop`
`vim /etc/docker/daemon.json`

```.json:daemon.json
{
  "bridge": "none"
}
```
`vim service start docker`

###3 uninstall
`sudo yum remove docker docker-common docker-selinux docker-engine`

###4 設定ファイルの削除
`rm -rf /etc/docker`

###5 imageの削除
`rm -rf /var/lib/docker`
ラズパイ用SDカードの作成

#Raspberry Pi Imagerのインストール
##homebrewを使ってターミナルからインストール

```
brew cask install raspberry-pi-imager
```
##LaunchpadからRaspberry Pi Imagerを立ち上げる
<img width="249" alt="スクリーンショット 2020-07-28 15.47.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/d7ad1952-743e-9249-31cc-debee7fc4dd7.png">

##画面でchosse OSを選択
<img width="680" alt="スクリーンショット 2020-07-28 15.46.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/a619dcb1-5392-04d8-031a-af1c0faacd0b.png">

##一番上のRaspberry Pi OS(32bit)を選択
<img width="575" alt="スクリーンショット 2020-07-28 15.48.40.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/97e011d0-6556-e7a5-692a-50af50a9abdc.png">

##続いてchoose SD cardを選択（SDカードはPCに差しておきましょう）
<img width="668" alt="スクリーンショット 2020-07-28 15.54.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/a3f4beca-e939-08d1-21cf-244d33712296.png">

##SDカードを選択します。
<img width="581" alt="スクリーンショット 2020-07-28 15.55.59.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/0632284e-e132-0699-38a9-0205121483d9.png">

##WRITEボタンを押して、書き込みます。
このSDカードの中のものは消させるよみたいな英語のメッセージが出てきたら、yesを選択して、続行します。
<img width="678" alt="スクリーンショット 2020-07-28 15.56.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577027/ca146614-27b6-b926-af5c-335d1e2ddb2d.png">
[Rails] cloneしたリポジトリをrailsサーバーで起動する

git hubからcloneしたリポジトリをrailsサーバーで起動するまでの道のりを記録しました。

# リポジトリをclone
`$ git clone https://github.com/＊＊＊＊＊/＊＊＊＊＊.git`

# サーバー起動コマンドを打ってみる
`$ bin/rails s`

```console
Could not find rake-13.0.1 in any of the sources
Run `bundle install` to install missing gems.
```
エラーが出て起動しません。bundleがないみたい。指定されたコマンドを打ってみます。

`$ bundle install`

```console
/Users/*****/.anyenv/envs/rbenv/libexec/rbenv-exec: /usr/local/bin/bundle: /System/Library/Frameworks/Ruby.framework/Versions/2.3/usr/bin/ruby: bad interpreter: No such file or directory
/Users/*****/.anyenv/envs/rbenv/libexec/rbenv-exec: line 47: /usr/local/bin/bundle: Undefined error: 0
```
これもまたエラーが出て失敗しています。

# エラー解消の旅
[teratail](https://teratail.com/questions/240461)と[Could not find XXXX in any of the sources エラーの修正方法](https://qiita.com/nakanowax/items/fe07e8ccd1721befebeb)を参考にさせていただきました。

まずはどのruby, bundleを参照しているか確認。

`$ which ruby`

```console
/Users/*****/.anyenv/envs/rbenv/shims/ruby
```

`$ which bundle`

```console
/Users/*****/.anyenv/envs/rbenv/shims/bundle
```
.anyenvの中のrubyとbundleを見ているのでこれは大丈夫そう。

そして、bundlerをインストールする。
`$ gem install bundler`
You don't have write permissionsと言われたのでsudoをつけます。

`$ sudo gem install bundler`
途中2回PC起動時のパスワードの入力を求められますがbundlerのインストールに成功。

満を辞して`$ bin/rails s`

```console
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options
error Couldn't find an integrity file                                          
error Found 1 errors.                                                          


========================================
  Your Yarn packages are out of date!
  Please run `yarn install --check-files` to update.
========================================
（以下省略）
```

yarnをinstallしてね、とのこと。コマンドまで教えてくれていたのに癖で`--check-files`オプションを付けずに、`$ yarn install`をしてしまいましたが問題ありませんでした。

```console
(省略)
✨  Done in 17.93s.
```
install成功！

そして今度こそ！！
`$ bin/rails s`

```console
=> Booting Puma
=> Rails 6.0.2.2 application starting in development 
=> Run `rails server --help` for more startup options
Puma starting in single mode...
* Version 4.3.3 (ruby 2.6.3-p62), codename: Mysterious Traveller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://127.0.0.1:3000
* Listening on tcp://[::1]:3000
Use Ctrl-C to stop
```

railsサーバー無事起動しました＾＾
Dockerのコンテナを消しても、中のファイルを維持する方法

「Dockerあんまり触ったことなかったけど、これからはDockerで開発環境を整えよう」と思ったときに気になったこと。

**コンテナの中にあるデータを独立させるにはどうしたらいいんだ？**

###マウントする(-v)
手順は
自分のローカル環境上にディレクトリを作り、その中にファイルを入れる
そのディレクトリをマウントして、コンテナを起動する
以上

これでローカルにあるファイルをコンテナで起動してみることができる
これをバインドマウントと呼び、作業ディレクトリを即座にコンテナから参照することができる。

もう一つの手順が
```docker volume create```を使ってDocker Engineのなかにボリューム(データを保存する場所)を作成sる
以上

これでDockerEngineの中にデータを入れて保存することができる。
**MySQLなどのコンテナを起動して、このボリュームをマウントして使う。**
ボリュームマウントとよびこちらが公式では推奨されている。
【Mac】インストールしたPWAを削除する

apiの検証でpostman使うことが多いのだが、ある日LaunchPadからフィルタするとこんなことになっていた。
<img width="1006" alt="スクリーンショット 2020-07-28 15.36.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/24b75db4-54e5-d970-2fd6-b49a7251c028.png">

postmanが２つある！？
ってなんのことはなくて片方（多分左の見慣れてないアイコン）がPWAなのである。
PWA側を起動するとPWA版は非推奨だからNative使えって警告が出たので削除しようということでアイコン長押ししてみる。

**アイコンぷるぷるするけど✕ボタンが出ない…**
この手順で消せるのはプリインアプリかAppStoreからインストールしたアプリだけらしい、知らんかった。

じゃFinderのアプリケーションフォルダからダイレクトに削除してやるぜって思ったのだが
**PWAはここにアプリケーションファイルが入るわけではない。**

find掛けて探してみたらここにあるようである。
（ちなみに*.appは-type fではなく-type dなのでここでもややハマった）

```sh
/Users/myname/Applications/Chrome Apps.localized/Postman.app
```
これまた「Chrome アプリ」 = 「Chrome Apps.localized」なのでややこしい話である。
<img width="605" alt="スクリーンショット 2020-07-28 15.49.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/23195/8262bc4b-dca4-efc5-07b3-818da543e993.png">

ここにあるPostman.appを削除して完了。
たまにLaunchPadにアイコンが残ったままの場合があるがリストをリセットすればOKらしい。

```shell
rm /Library/preferences/com.apple.dock.plist
```
もしくは

```shell
defaults write com.apple.dock ResetLaunchPad -bool true; killall Dock
```

**おわり。**
Next.js 9.5のアップデートにより、GitHub Pagesで妥協しない動的ルーティングが可能になった

『[Qiita: Next.jsで作ったアプリをGitHub Pagesにデプロイする@ozaki25](https://qiita.com/ozaki25/items/fe9912fc41c3a5c5bfea)』や、『[Qiita: Next.jsをGitHub Pagesにデプロイしたらリンクが壊れた](https://qiita.com/atti/items/e9e079ffb2ef4a15a96e)』、『[GitHub: gh-pages Hello World example](https://github.com/vercel/next.js/tree/canary/examples/gh-pages)』にNext.jsのWebサイトをGithub Pagesに投稿する方法が載っていますが、どれも静的ページのみへのルーティングを説明していて、動的ルーティングには深く言及されていません。

そこで、Next.js 9.4でサイトをGitHub Pagesにあげたところ、動的ルーティングでハマってしまいました。結果、対処法がわからずにVercelに移行したのですが、[Next.js 9.5のアップデート](https://nextjs.org/blog/next-9-5)で**ベースパスをカスタマイズできる**機能が追加され、自分がハマっていた動的ルーティングが解決しました！🎉

この記事では、Next.js 9.4の動的ルーティングのハマっていた背景とNext.js 9.5での対処法について説明します。

# Next.js 9.4 × GitHub Pages 🤔

ご存知だと思いますが、GitHub Pagesは`https://[username].github.io/[repository-name]`といったurlにマッピングされます。これによって、以下のような普通のNext.jsのルーティングでは、`https://[username].github.io/[repository-name]/items`に行ってほしいのに、`https://[username].github.io/items`にルーティングされてしまい、リロード時にエラーとなってしまいます。

```tsx:MyLink.tsx
const MyLink = () => (
  <Link href="/items">
    <a>Item</a>
  </Link>
)
```

なので、『[Qiita: Next.jsをGitHub Pagesにデプロイしたらリンクが壊れた](https://qiita.com/atti/items/e9e079ffb2ef4a15a96e)』などに記載されている変更が必要となります。

```js:next.config.js
module.exports = {
  assetPrefix: process.env.NODE_ENV === 'production' ? '/[repository-name]' : ''
}
```

```tsx:MyLink.tsx
const withRootPath = (path: string) =>
  process.env.NODE_ENV === 'production' ? `/[repository-name]/${path}` : path

const MyLink = () => (
  <Link href={withRootPath("/items")}>
    <a>Item</a>
  </Link>
)
```

これで、静的なリンクへはうまくいきます。が、前述している通り、動的ルーティングの場合は同様に以下のようにしても**プリフェッチされず、ブラウザのロードが挟まれてしまいます。**

```tsx:MyLink.tsx
const withRootPath = (path: string) =>
  process.env.NODE_ENV === 'production' ? `/[repository-name]/${path}` : path

const MyLink = () => (
  <Link href={withRootPath("/items")}>
    <a>Item</a>
  </Link>
)
const MyDynamicLink = () => (
  <Link href={withRootPath("/items/[id]")} as={withRootPath("/items/a")}>
    <a>Item</a>
  </Link>
)
```
また、上の記事に記載されている以下の方法で実装すると、エラーを出力します。

```tsx:MyLink.tsx(差分)
const MyDynamicLink = () => (
  <Link href="/items/[id]" as={withRootPath("/items/a")}>
    <a>Item</a>
  </Link>
)
```
<img width="661" alt="error.PNG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/398510/86503bf9-f706-368c-d17e-f9759ff7c488.png">

これは、`href`と`as`が対応していない事によるエラーです。詳しい内容はNext.jsのリポジトリに記入してあります。[vercel/next.js-Incompatible href and as values](https://github.com/vercel/next.js/blob/master/errors/incompatible-href-as.md)

…ということで、自分の知る限りではGitHubでNext.jsの動的ルーティングを実装するには、**プリフェッチとブラウザへのロードを妥協するしかありませんでした。**

# Next.js 9.5 × GitHub Pages 🎉
最初に説明している通り、Next.js 9.5でベースパスを設定できるようになりました。対処法も簡単で、`next.config.js`に追加するだけでOKです。

```js:next.config.js
module.exports = {
  basePath: process.env.NODE_ENV === 'production' ? '/[repository-name]' : ''
}
```

これだけで、妥協しない動的ルーティングが可能になります🎉

# おわりに
自分の認識不足で、Next.js 9.4でも動的ルーティングでプリフェッチできる方法がありましたら、教えてください。

デモとして使用したリポジトリ
- https://github.com/syakoo/next_gh-pages
Ruby on Railsで体系的にTDDを学んだ話

# はじめに
Ruby on Railsのアプリケーション開発で、上司とのペアプロでTDD（テスト駆動開発）を学ぶ機会があったので、そこで感じたTDDに対する自分の認識の変化と学びをまとめます。
（僕個人がとらえた内容になるので、間違いや語弊があれば教えてください）

# テストについての認識
まず、それまでほとんどテストを書いたことがなかった僕は、テストについて以下のようなイメージを持っていました。

- プログラム以外にもテストコードを書かなければならないから開発工数がかかる
- プログラムの挙動を全て担保するテストを書くのはかなり大変そう

しかし上司によると、まずテストに対する認識を変えると楽に考えることができて、気軽にテストが書けるようになるとのことでした。
それはどういうことかというと、

- テストに対して過大な期待はしない
- テストで全てのバグをなくせると思わなくて良い
- テストの役割はプログラムを動かすためにチェックすること
- 自分が書いたコードの動作を担保するために書く

と認識すると良いということでした。
それまで、テストの役割はプログラムの全てのバグを潰すことだと思っていた自分にとってはとても新鮮な考え方で、確かに上記のように捉えるとテストが気軽なものに感じました。

# TDDを体験する
上記の内容を体系的に学ぶために、あるバグフィックスに対して上司と一緒にTDDを行いました。
## 0. バグの内容を確認する
稼働中のプログラムで、以下のような予期しないエラーが発生していました。
>NoMethodError
undefined method `downcase' for nil:NilClass

エラー箇所のコードは以下のようになっていました。

```rb:rb
email_from_id_token = id_token.email.downcase
```

Apple IDでサインインをする処理で、ID情報を参照している箇所でした。
`id_token` の中には必ず `email` が存在する前提で書いていますが、`email` が存在しないことがあるようで、そのことが原因のエラーのようでした。

## 1. まずRSpecでバグを再現させる
RSpecで上記と同様のエラーが起きるテストケースを書いて再現させました。

```rb:rb
context 'when email not available' do
  #let(:payload) { { iss: AppleID::ISSUER, sub: external_guid, aud: 'hoge', exp: 0, iat: 0, email: email } }
  let(:payload) { { iss: AppleID::ISSUER, sub: external_guid, aud: 'hoge', exp: 0, iat: 0 } }

  it_behaves_like 'return bad request', nil, I18n.t('api.errors.email_not_available')
end
```

`when email not available`（emailが取得できないとき）というテストケースを作成しました。
モックとして、apple_idというgemを使って`email`を含まないトークンを作成し、その場合に期待する結果を記載しました。
ここで一度テストを実行し、「[0. バグの内容を確認する](https://qiita.com/mitanih/private/3b64e3dcc48ded9a5f1a#0-%E3%83%90%E3%82%B0%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E7%A2%BA%E8%AA%8D%E3%81%99%E3%82%8B)」で発生していたエラーと同様のエラーが発生して、テストが「失敗」することを確認します。

## 2. プログラムを修正する
次にテストが成功するようにプログラムを修正しました。

```rb:rb
email_from_id_token = id_token.email&.downcase

if email_from_id_token.blank?
  return render_bad_request(display_message: I18n.t('api.errors.email_not_available'))
end
```

`id_token.email`が取得できないパターンを考慮して適切にエラーハンドリングの処理を記載しました。

## 3. 再度テストを実行する
この状態で先ほどのテストを実行すると「成功」になり、予期しないエラーを適切にエラーハンドリングできてバグが解消されたことを確認できました。
これにて対応完了です。

# まとめ
テストを書かずにプログラムを直した場合、エラーが解消したことを確認するためにエラーが発生する状態を作って検証する必要がある（今回の場合、エラーが発生するのはレアケースだったので、実際に実機で再現させるのには手間がかかる）
また、動作確認ができるまで修正方法が正しいことの確証が持てません。
しかし、TDDではモックを使ってエラーが再現する状態を先に作るので、エラー解消の確認が容易にできますし、自分の書いたコードによって正しくエラーが解消されたことの確証を持つことができます。
今回、TDDの素晴らしさと楽しさを学ぶことができました。
今後はあらゆる場面で活用していきたいです。
プログレスバーの表示方法 (tqdm)

# 基本情報
[tqdm](https://github.com/tqdm/tqdm)を使うとfor文などの、時間のかかる処理で進捗を確認するための、プログレスバーを簡単に表示できる。


## インストールが必要

```
$ pip install tqdm
```


## 使い方
使い方はイテラブルオブジェクトをtqdmで囲むだけです。

```python:tqdm_test.py
from tqdm import tqdm

df = pd.read_csv("データ.csv", encoding="UTF-8")

#pandasのデータをfor文処理する場面を考える
#tqdmの使い方はtqdmで囲むだけ
for row, item in tqdm(df.iterrows()):
    print(item)
```


# 備忘録

## 手動でプログレスバーの数値を設定する方法
今まで私は上記の方法しか使ったことがありませんでした。
しかし、なぜかプログレスバーの上限が「?」になってしまう現象が発生したため、
手動で上限の数を設定する方法を調べたので、自分用の備忘録として記載しておきます。

```python:tqdm_test.py
from tqdm import tqdm

df = pd.read_csv("データ.csv", encoding="UTF-8")

#with文で囲み、for文の最後にプログレスバーを手動でupdateする方法
#total=で上限を設定。今回はdfの件数にした。増加分は.pbar.updateで指定する。
with tqdm(total=len(df)) as pbar:
    for row, item in tqdm(dataframe.iterrows()):
        print(item)
        pbar.update(1)
```


## jupyternotebookの場合に
`from tqdm.notebook` とすると簡単に見やすいプログレスバーになった。

```python:tqdm_test.py
from tqdm.notebook import tqdm
```
MacにOpenCV(C++)環境を構築する

## 環境

- macOS Catalina version 10.15.6
- Homebrew 2.4.8
- cmake 3.18.0

## OpenCVのインストール

ソースコードからビルドしたほうが詳細なオプションを変更することが可能ですが、依存関係など面倒な点が多いのでbrewでインストールします。

```
brew install opencv
```
2020.7.28現在、上のコマンドを実行するとOpenCV4.4.0がインストールされます。2系３系をインストールしたい場合はそれぞれ以下のようにします。

#### 2系

```
brew install opencv@2
```

#### 3系
```
brew install opencv@3
```

## テスト
正常にインストールできているかテストします。
以下のようなディレクトリ構造をとります。

```
opencv_test/
├── CMakeLists.txt
├── build
├── main.cpp
└── sample.jpg
```

sample.jpgはてきとうに画像ファイルを用意してください。

画像を読み込んで表示するだけのシンプルなプログラムです。

```cpp:main.cpp
#include <opencv2/opencv.hpp>
int main() {
    cv::Mat img = cv::imread("sample.jpg");
    if(img.empty()) {
        return -1;
    }
    cv::namedWindow("test", cv::WINDOW_AUTOSIZE);
    cv::imshow("test", img);
    cv::waitKey(0);
    cv::destroyWindow("test");
    return 0;
}
```

```cmake:CMakeLists.txt
cmake_minimum_required(VERSION 3.1)
project (test)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -Wall")
find_package(OpenCV REQUIRED)
include_directories( ${OpenCV_INCLUDE_DIRS} )
add_executable(main main.cpp)
target_link_libraries(main ${OpenCV_LIBS})
```

#### 実行

cmakeをインストールしていなかった人は

```
brew install cmake
```
でインストールしてください。

```
cd build
cmake .. .
make
cd ..
./build/main
```
画像が表示されれば成功です。
【Python】TypeError: 'in <string>' requires string as left operand, not list

Pythonのスクレイピングを勉強中、値の加工をしていたら`TypeError: 'in <string>' requires string as left operand, not list`が出たので、メモで対策を残します


## エラーが出た原因

Pythonで取得したlistに、該当する文字列がまれているかの、条件分岐をやろうとしていました。

```py3
if '該当させたい文字列' in i:
```

そしたらこのエラーが出た

```py3
TypeError: 'in <string>' requires string as left operand, not list
```

## 対策

リスト内包表記を使う

```py3
False not in [i in '該当させたい文字列' for i in 検索したい文字列の入ったリスト]
```

## 追記

@shiracamus さんのコメントから引用！（ありがとうございます！）

判定するだけなら any関数 や all関数 を使うといいですよ。

```py3
>>> any('test' in item for item in ['hoge', 'fuge', 'hogetestfuge'])
True
>>> all('test' in item for item in ['hoge', 'fuge', 'hogetestfuge'])
False
>>> all('test' in item for item in ['testhoge', 'fugetest', 'hogetestfuge'])
True
```

参考
https://pg-chain.com/python-in
https://ai-inter1.com/python-if-in/
https://kuzunoha-ne.hateblo.jp/entry/2019/02/15/213000
Python で CG 画質評価のメモ

## 背景

* モンテカルロレンダリングの結果が正しいのか(本当に収束しているのか)評価したい
* CG 画像と, 実写画像が一致するかどうか判断したい, 誤差(みたいなもの)を出したい.

Jupyter-lab + numpy/scipy とかでお手軽にぺろっとやりたい.

世の中の普通の(?)画像処理をする人向けではありません.

## よくある方法

### SSIM

skimage にある

https://scikit-image.org/docs/dev/auto_examples/transform/plot_ssim.html

### SNR

scipy にあるようだが, 式自体は簡単なので numpy で書いたほうがよさそう

https://github.com/scipy/scipy/issues/9097

https://www.codespeedy.com/calculate-signal-to-noise-ratio-in-python/

## CG 向けの方法

### FLIP

ꟻLIP: A Difference Evaluator for Alternating Images 
https://research.nvidia.com/publication/2020-07_FLIP

HPG2020 で, できたてほやほや.

CG と実写の誤差算出などにも使えそうで我々のようなユーザによさげ.

numpy/scipy での実装含め, 各種言語での実装がある.

### その他

Detecting Bias in Monte Carlo Renderers using Welch’s t-test
http://jcgt.org/published/0009/02/01/

モンテカルロレンダリング向け.
こちらも python コードがありよい.
【Unity】アクティブ切り替え用クラス

### 概要
毎回`.gameObject.SetActive(true)`のように記述するのは面倒だったため切り替え用のクラスを作成しました。

### メインクラス
List型オブジェクトに切り替えたい要素を定義し`Current`のindex値で表示の切り替えを行う。

```
using UnityEngine;
using System.Collections.Generic;

namespace xxx
{
	[ExecuteInEditMode]
	public class ViewChanger : MonoBehaviour
	{
		[SerializeField]
		public List<GameObject> viewList;

		[SerializeField]
		private int current;
		public int Current {
			get { return this.current; }
			set {
				this.current = value;
				UpdateView();
			}
		}

		protected void UpdateView()
		{
			for (int i = 0; i < this.viewList.Count; i++) {
				GameObject view = this.viewList[i];
				if (view == null) {
					continue;
				}
				view.SetActive(this.Current == i);
			}
		}
	}
}
```

### 切り替え処理
Controller等から`Current`にindex値を指定し切り替え

```
[SerializeField] private ViewChanger sampleViewChanger;
...
this.sampleViewChanger.Current = (int){index値};
```
過去のコミットまで戻したい

過去のこの状態のソースに戻したい！っていうことが時々あります。(特定のコミットまで戻したい)
そんな時には下記コマンドで対応出来ます。

```
$ git reset --hard 戻したいコミットのID(SHA-1)
```

※リモートに反映させていないものに限ります。
Alexaで帰宅が遅くなったときに友達に連絡してくれる防犯用スキル

よく洋画を見ていると
「殺して金だけ奪おうとしても無駄だぞ。もし定刻までに無事に帰らなければ取引は不成立になり、仲間が復讐にやってくる」
というセリフがあったりしますね

今回は<a href="https://mitsuboshitx.blog.fc2.com/blog-entry-780.html">Alexa（Amazon Echo ￥2980～）で同じ機能を再現してみましょう
![EczFBL6U0AAZgM4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275132/c5dcaea5-f51d-1511-98b6-da13f52c1c93.jpeg)
![EczFBTrVcAIlT4b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275132/12a1ba3c-4ef6-923f-1763-f0e0ae2843e6.jpeg)

</a>


それではまず要件定義から

1.スキルは既に誰かが作成したものを使う
理由「写真の再発明はしてはいけない」から

2.音声コントロールで「ただいま」と言う、またはスマートキーやスマートロックと連動させる

手持ちのスマホが自宅のWi-Fiに接続されたことをきっかけに帰宅したとみなす仕組みでも良い
あるいはボタンを押すなどでも良い

3.「20時までに帰宅しなかったら、○○に連絡して」
などあらかじめ命令用の定型文を決めておく
（英語だと通じないようにする）


【執筆中】
DataTablesの特定行全体をリンクにする

# 概要

DataTableに関しては[こちら](https://qiita.com/nissuk/items/7ac59af5de427c0585c5)をご覧ください
DataTableは簡単にリッチなテーブルを作れるとあって使っている人も多いのではと思います
今回、こちらのテーブルの行をクリックした時に、そのデータに対応した詳細画面に飛ばしたいという要望が来たので、その時の解決策をメモしておきます

# 解決策

DataTableライブラリ上で行をカスタマイズするには


```javascript

'createdRow': function( row, data, dataIndex ) {
  // 任意のコードを記述
　// $(row)にて行を構成するHTML要素にアクセス可能
},
```
でできるみたいです
createdRow以外にもcreatedCellもあるみたいですね

行全体をクリック可能にするためにはtr要素にclick時の挙動を記述して、カーソルが行の上に来た時に変化できるようにCSSを追加しておけば良さそうです

```javascript

$('#table1').DataTable({

  ...

  // このajaxの返り値でhoge_idをもらっておく
  // 以下のライブラリを使うとcontrollerのコーディングが楽になる
  // https://github.com/yajra/laravel-datatables
  ajax: {
    type: 'GET',
    url: '/path/to/api',
    data: {
      ...
    }
  },

  // 行を選択した時にurfFormに飛ぶ
  'createdRow': function( row, data, dataIndex ) {
    // data-hrefにURLを追加してから、クリック時にそちらへ遷移させる
    var urlForm = "/path/to/link/" + data.hoge_id;
    $(row).attr('data-href', urlForm)
      // カーソールオーバー時の見た目を変化
      .css("cursor", "pointer")
      // クリックしたら遷移
      .click(function(e) {
        window.location = $(e.target).closest('tr').data('href');
    });
  },

  ...

});
```

# reference
- https://stackoverrun.com/ja/q/11454886
- https://qiita.com/nissuk/items/7ac59af5de427c0585c5
- http://kachibito.net/snippets/table-tr-link-clickable
スプレッドシートの関数の備忘録

# 数値カラムの数を求める
`=COUNT(A1:A10)`
COUNTは**データセット内の数値の個数**。
全角数字は当然数値ではない。
便利ィ～！


# 数値じゃないカラムの数を求める
`=COUNTA(A1:A10)-COUNT(A1:A10)`
COUNTAは**データセット内の値の個数**。
そこからCOUNTの値を引く。
全角数字は当然数値ではない。
便利ィ～！


# 数値以外が含まれるデータセット内の値の合計
`=SUM(A1:A10)`
数値以外は無視してくれる。
全角数字は当然数値ではない。
便利ィ～！
内容がわからないOracle DBと向き合ってみた

#使い方
　内容が全くわからない謎のOracle DBに遭遇したにも関わらずなぜか管理者権限を持っているという超ニッチなシチュエーションで使用可能。
　どのスキーマにどのテーブルがあって、なにが入っているか、どう照会すれば何が知れるのかわからない。。。
　という状態から少しずつDBを知ろうとする足跡。

　今回はそこまでやらないけど、ユーザー定義のDBやシステム定義のDBの全貌を知りたい、マイグレーション漏れを防ぎたい、なんて時にも使えるかも。。。

　*******投稿者は全てPC上の仮想環境での実行結果を掲載しています。*******
　*******これらのSQLは決して本番投入しないでください*******
　*******本番投入して問題発生しても責任はとれません*******

#そもそもOracleはどうやって構成情報を管理しているのか
　[Oracleデータディクショナリ](https://docs.oracle.com/cd/E16338_01/server.112/b56306/datadict.htm)
　Oracleはユーザーの権限管理やらSQLの構文解析等々、ユーザーからのリクエストのたびに内部的に”Oracleデータディクショナリ”とよばれるシステム管理の表に照会処理を行っており、以下の命名規則に則って管理している。（らしい）
　ALL_xxxx（権限管理っぽい感じ）
　DBA_xxxx（DBの構成情報っぽい感じ）
　USER_xxxx (スキーマの構成情報っぽい感じ)

　→稼働中にこのテーブルに触ると権限管理やDBアクセスのパフォーマンスに影響が出そう。

#どのスキーマに何のテーブルがあるのか
　OracleDBはテーブル名一覧や列名一覧を表管理しており、今回私の知りたかったテーブル名は[USER_OBJECTS](https://docs.oracle.com/cd/E57425_01/121/REFRN/GUID-6EEE5C20-C731-406B-B772-865B400D349A.htm)で管理されていそうだと分かった。
試しに以下のSQL①で照会をかけたところ、なんとなくそれっぽい情報を得ることができたが、多分他にもユーザーいるよな、とも思った。

```
①
SELECT OBJECT_NAME, OBJECT_TYPE 
FROM   USER_OBJECTS
Where object_type='TABLE'
ORDER BY OBJECT_NAME;　 　
```

もう少し調べると、オーナー(≒スキーマと仮定)、テーブル名、テーブルのコメントは[ALL_TAB_COMMENTS](https://docs.oracle.com/cd/E16338_01/server.112/b56311/statviews_2104.htm#i1590885)で管理されているようだと分かったので②を投げてみた。

```
②
select table_name, owner, comments
 from all_tab_comments　 　　　　　　　　<--システム定義も全部出てきます

```

照会結果をよく見てみるとユーザー定義でなさそうな(oracle謹製っぽい)スキーマやテーブルも多数含まれるため、本当に欲しい情報のスクリーニングが大変かも。
今回はユーザー定義も何個あるかわからなかったので全部見てみた。

特定のスキーマの定義のみ見たい場合は　[リンク](https://qiita.com/sugaryo/items/831feda395ad0308c74a)　のレベル１、レベル２がいいと思われる。


#各テーブルの列名の参照
　↑のSQLでなんとなくDBの全貌が見えてきたけど、コメントついてなかったり、何の略かわからないテーブル名だったり、何単位でスキーマが設計されているかわからなかったりするので、DBの中身を触らずにもう少し何者かを知りたい。。。！
　と思ったので[ALL_TAB_COLUMNS]
(https://docs.oracle.com/cd/E16338_01/server.112/b56311/statviews_2103.htm)からテーブル名とカラム名を照会した。

```
select table_name, column_name, owner
 from all_tab_columns 　　　　　　　　<--システム定義も全部出てきます
```


#まとめ
　・仮想環境で遊ぶのは楽しい
　・久々にMarkdown触るとわからない
　・よくわからないDBを触るのは怖い
　・コストのわからないSQLを実行するのは怖い
　・本当は設計書を見るべき

#参照したOracle DBの定義情報
　[Oracleデータディクショナリ（公式）](https://docs.oracle.com/cd/E16338_01/server.112/b56306/datadict.htm)
　[Oracleデータ・ディクショナリとは](http://itref.fc2web.com/oracle/ddv/)
　[ALL_TAB_COMMENTS](https://docs.oracle.com/cd/E16338_01/server.112/b56311/statviews_2104.htm#i1590885)
　[ALL_TAB_COLUMNS]
(https://docs.oracle.com/cd/E16338_01/server.112/b56311/statviews_2103.htm)
　[ALL_TAB_COMMENTS](https://docs.oracle.com/cd/E16338_01/server.112/b56311/statviews_2104.htm#i1590885)


あー面白かった。
FIDOについて紹介

#はじめに
過去に参画していた案件で、FIDOという認証技術とそれに関連したものについて
扱ったので、それらの情報を簡単にですがまとめました。

#FIDOについて
FIDOとは
**Fast IDentity Online（素早いオンライン認証）**の略語で、認証技術の1つになります。
FIDOはPKIと同様に、公開鍵暗号による署名技術を採用しています。
>PKIについては[こちら](https://jp.globalsign.com/ssl-pki-info/pki/aboutpki.html)を参照してください。

認証技術なので本人確認の為にFIDOは利用されますが、FIDOでの認証では
ユーザーの生体情報等を利用するので、**ユーザーがパスワードを覚える必要がない**ことが特徴になります。

加えて、認証自体は専門端末で実行されるので、
**認証に利用した情報はネットワーク上に流れず、サーバーで保持しない**ため
情報漏洩のリスクが軽減されることも特徴の一つです。
<img width="492" alt="コメント 2020-08-10 233906.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/677781/8029ab01-70c5-5e93-fd07-b8994a79d60e.jpeg">
FIDOの仕様では、ネットワーク上に流れる情報は
**端末側の秘密鍵で署名されたトークン**のみで、サーバー側には公開鍵の情報のみ保持しています。
そのため、第三者がトークンと公開鍵を傍受したとしても、秘密鍵に応じたトークンを
作成することはできず、不正ログインを行うことはできません。

FIDOには、**FIDO/UAF**と**FIDO/U2F**と呼ばれる2種類の規格が存在しています。
>登録時の詳細については、[こちら](https://fidoalliance.org/fido%e3%81%ae%e4%bb%95%e7%b5%84%e3%81%bf/?lang=ja)を参照してください。
>認証時の詳細については、[こちら](https://www.kobelcosys.co.jp/column/itwords/20190701/)を参照してください。

###FIDO/UAFとは
FIDO1.0仕様での規格の1つで、
**Universal Authentication Framework（汎用的な認証基盤）**の略語です。

FIDOに対応するデバイスを利用することで、パスワードを使わずに認証を行う仕組みになります。

こちらの方式では、認証に指紋や声紋などの生体情報を用います。
パスワードは一切不要で、認証のために使われた生体情報はサーバー側に一切流れません。
よって、個人情報はネットワーク上にはまったく流れないで済みます。

万一、認証用の端末を紛失・盗難などがあった場合でも、不正に利用される可能性は現状ではきわめて低いと言えます。
将来的には生体情報の偽装が容易になる可能性はありますが、現状ではきわめてハードルが高いものになります。

しかし、UAFの利用にはFIDOに対応した端末が必要となり、FIDO対応の端末を揃える際は相応のコスト負担が発生します。
端末変更にともない、ユーザーインターフェースの変更が発生する可能性もあります。

###FIDO/U2Fとは
FIDO1.0仕様での規格の1つで、
**Universal 2nd Factor（汎用的な第2要素）**の略語です。

二段階認証を採用しており、ID/パスワードの1段階目の認証に加えて、
セキュリティコードやセキュリティキーを使った認証を行います。

セキュリティキーとして、USBキーに加えてBluetoothとNFCをサポートした仕様となっています。

認証の流れとしては、ユーザーIDとパスワード、あるいは安全が確保された上での
PINコード(暗証番号)入力により行います。
このあと、端末のUSBポートにトークンを挿す、あるいはNFCやBluetoothを用いた
キーを近づけることで、本人認証を行います。
対応端末が必要ない分、UAFに比べると導入が容易であると言えます。

認証の情報はローカルに留まりますが、完全にパスワードフリーにはなりません。
そのため、UAFに比較するとセキュリティは弱くなる面が存在します。

#FIDO2について
FIDO2とは、WebAPI仕様として提案されたUAFとU2Fを統合した仕様のことです。

FIDO1.0では生体認証に専用端末を利用していましたが、FIDO2では
**専用端末を利用せず**PCやスマホから**FIDO2対応ブラウザ**を介して認証ができるので、
導入コストを抑えつつ強固なセキュリティを維持できます。

FIDO2は、

  * 認証デバイス（TPM内蔵PCの指紋リーダー、USBやBluetoothデバイス等）
  * ブラウザ（FireFox、Edge、Chrome等のFIDO2対応ブラウザ）
  * RPサーバー（FIDO2/WebAuthn認証サーバー、サービス等）

の要素で構成されます。

FIDO2では、**WebAuthn**と**CTAP**という2つのプロトコルで認証を行い、
WebAuthnはネットワークを流れるプロトコル部分を、CTAPはPC内でブラウザから
USBなどに接続されている認証デバイスを呼び出す部分を担当します。


###WebAuthnとは
WebAuthnとは、FIDO2を構成する技術の一つで、ブラウザや関連するWebサービスの
基盤に組み込む標準のWeb APIを定義しています。
WebAuthnのAPIによって、認証デバイスから取得した生体情報を利用し
登録/認証の処理を行います。

###CTAPとは
CTAPとは、「Client to Authenticator Protocol」の略語で、
FIDOの外部認証デバイスとPlatform（クライアントプログラム）との通信プロトコルのことです。
CTAPによって、WebAuthn実行時に端末で利用できる認証デバイスの検出を行います。

>登録/認証の流れ等については、[こちら](https://qiita.com/tonoki/items/16a99d770fa496bdaafc)を参照してください。

#最後に
これまでFIDOとFIDO2について紹介しましたが、FIDOに類似したPBIと呼ばれる
日立が開発した認証技術も存在しているので、ご興味のある方は[こちら](https://www.hitachi.co.jp/rd/sc/story/pbi/index.html)をご覧ください。
docker: デフォルトネットワークの設定

docker はデフォルトで172.17以下をサブネットに使用する
デフォルトのネットワークとコンフリクトが発生する際は、以下のように、dockerが作成するデフォルトネットワークを設定することが可能

```.json:/etc/docker/daemon.json(存在しない場合は新規作成する)
{
  "bip": "172.26.0.1/16",
  "default-address-pools" : [
    {
      "base" : "172.240.0.0/16",
      "size" : 24
    }
  ]
}
```

```.sh:terminalでdockerを再起動
sudo systemctl restart docker
```

```.sh:その他コマンド一覧
# networkのid一覧を表示
docker network list

# ネットワーク id xxxxxx のサブネットを表示
docker network inspect xxxxxxx

# ネットワーク id xxxxxx を削除(コンフリクトしている場合)
docker network rm xxxxxxx
```
【Effective Javaを読む】　第２章　項目４　『privateのコンストラクタでインスタンス化不可能を強制する』

#privateのコンストラクタでインスタンス化不可能を強制する

ユーティリティクラス（staticのメソッドとstaticのフィールドからなるクラス）はインスタンス化されるようには設計されない。にもかかわらずインスタン化できてしまうものをよく見るので、privateのコンストラクタを使って絶対インスタンス化できないようにしましょう、ってお話。

##用語集
###デフォルトコンストラクタ
コンストラクタを1つも定義していない場合、自動的にデフォルトコンストラクタと呼ばれるコンストラクタが作成される。


##サンプルコード

明示的にprivateなコンストラクタを記述することで、外部からのアクセスを不可能にし、デフォルトコンストラクタの生成も抑止される。
AssertionErrorは厳密には必要ではないけれど、保険として入れている。

```java

//インスタンス化できないユーティリティクラス
public class UtilityClass {
    //インスタンス化できないようにするためにデフォルトコンストラクタを抑制する
    private UtilityClass() {
        throw new AssertionError();
    }
    … //残りは省略
}
```
#続く
【Effective Javaを読む】　第２章　項目５　『不必要なオブジェクトの生成を避ける』
https://qiita.com/Natsukii/items/ec64efddce85ffd59fa8