OmniAICreator/Qiita-1.07M huggingface dataset:
WindowsのVirtualBoxのストレージ容量を増やした時のメモ

忘れそうなのでメモ。

# ディスクサイズ拡張
1. VirtualBoxマネージャーを立ち上げる
2. 該当マシンを電源オフ
3. グローバルツールを開く
4. 該当ディスクを選択
5. 拡張子が`vmdk`の場合、そのままだと容量を増やせないので以下の手順でコピーする
  1. コピー
  2. コピー元を選択して次へ
  3. ディスクイメージのファイルタイプで`VDI(VirtualBox Disk Image)`を選択して次へ
  4. 可変サイズ（デフォルト）を選択して次へ（多分固定サイズでも良いが）
  5. 名前を入力してコピー
6. 該当のディスクのプロパティを開く
7. サイズを変更する
8. 適用
9. 5.でコピーした場合、該当マシンのディスクを以下の手順でコピー後のディスクに交換する
  1. 該当マシンの設定画面を開く
  2. ストレージ
  3. ディスクの+
  4. 既存のディスクを選択
  5. コピー後のディスクを選択する
  6. コピー前のディスクの割り当てを除去
  7. コピー後のディスクのSATAポートをコピー前のディスクが指定していたものにする
  8. OK

# パーティション拡張
1. 該当マシンを起動する
2. `sudo df`で対象のディスクを確認する
3. `sudo fdisk {対象のディスク}`
4. `p`で拡張対象を確認
5. `d`で拡張対象を一旦削除
6. `n`で拡張後のサイズで作成
7. `p`で拡張後を確認
8. `w`で保存
9. 該当マシン再起動（不要かも）
10. `sudo resize2fs {対象のパーティション}`
11. 該当マシンを再起動
12. `sudo df`で拡張されていることを確認する
CentOS 7にPHP 8.0をインストール（Remi's RPM repository）

# はじめに

Remi's RPM repositoryを利用してCentOS7にPHP8.0をインストール
親記事：[PHP, PHP-FPMの各種インストール方法とEOLまとめ](https://qiita.com/witchcraze/items/dfe3823554b7caba6f6a)
参考：[Remi's RPM repository](https://rpms.remirepo.net/wizard/)

## サポート

本手法で導入した場合、[PHP: Supported Versions] (https://www.php.net/supported-versions.php)/[PHP: Unsupported Branches](https://www.php.net/eol.php)より、2023-11-26がEOLになると思われる。
それ以降に報告された脆弱性や不具合への対応は実施されない可能性がある。

## note

- インストール後の更新は `yum --enablerepo=remi-php80 update`

## LOG

### インストール

```shell-session
# cat /etc/redhat-release
CentOS Linux release 7.9.2009 (Core)

# yum install -y https://rpms.remirepo.net/enterprise/remi-release-7.rpm
... 略

# yum install -y --enablerepo=remi-php80 php which
... 略
```

### 各種確認

```shell-session
# which php
/usr/bin/php

# php -v
PHP 8.0.0 (cli) (built: Nov 24 2020 17:04:03) ( NTS gcc x86_64 )
Copyright (c) The PHP Group
Zend Engine v4.0.0-dev, Copyright (c) Zend Technologies

# php -i | grep php.ini
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini

# yum info php
Loaded plugins: fastestmirror, ovl
Loading mirror speeds from cached hostfile
 * base: ftp.riken.jp
 * epel: nrt.edge.kernel.org
 * extras: ftp.riken.jp
 * remi-safe: ftp.riken.jp
 * updates: ftp.riken.jp
Installed Packages
Name        : php
Arch        : x86_64
Version     : 8.0.0
Release     : 1.el7.remi
Size        : 5.1 M
Repo        : installed
From repo   : remi-php80
Summary     : PHP scripting language for creating dynamic web sites
URL         : http://www.php.net/
License     : PHP and Zend and BSD and MIT and ASL 1.0 and NCSA
Description : PHP is an HTML-embedded scripting language. PHP attempts to make it
            : easy for developers to write dynamically generated web pages. PHP also
            : offers built-in database integration for several commercial and
            : non-commercial database management systems, so writing a
            : database-enabled webpage with PHP is fairly simple. The most common
            : use of PHP coding is probably as a replacement for CGI scripts.
            :
            : The php package contains the module (often referred to as mod_php)
            : which adds support for the PHP language to Apache HTTP Server.
```
データ基盤運用アンチパターン

[データ基盤 Advent Calendar 2020](https://qiita.com/advent-calendar/2020/datainfrastructure)　1日目の記事となります

ここではデータ基盤を運用していく上で陥りやすいアンチパターンをいくつか紹介したいと思います

データ基盤をどう作るかはについては以下の書籍がとてもとっつきやすく参考にもなると思うので、よかったら読んでみてください

[データマネジメントが30分でわかる本](https://amzn.to/37hmZz8)

# はじめに
ここでは社内向けのデータ基盤を前提としています
データ基盤は大前提として、使われないと意味がありません
使われるためには使ってくれるユーザがいないとはじまりません

データ基盤を作る上で、**ユーザは超大事**です


## アンチパターン集

データ基盤はユーザに対して価値を提供して真価が発揮されます。
だが、データ基盤を長く運用していると以下のような事が起こることがあります

### ユーザのクレームに対して温度差がある
- ユーザからしたらものすごい障害につながりかねない障害に対しても、通常の障害と同じように対応してしまう
- クレームではないと思っていたら、裏ですごいdisられていた
- 常に同じクレームを受け続けている(受けている方が大したことないと思っている)

これらの事を続けていると、だんだんと信用がなくなっていきユーザが離れていったり、あらたなデータ基盤が誕生したりします
ユーザの声は前のめりに聞ける体制を作ると解消出来るかもしれません

### ユーザの今後の計画に対応出来ない
- 新しいサービスのデータも入れたいが、パイプラインがないしDWHの容量が足りない
- ユーザが新しいBIエンジンを投入したが、基盤側のエンジンが耐えられない
- エンハンスをしないといけない案件をキャッチアップ出来ておらず、要員を準備出来ていない

せっかくユーザがデータ基盤を信頼し、使いはじめてくれているところなのにもったいないです
ユーザと一緒に計画をたてるような立場になると解消出来るかもしれません

### ユーザが無茶なことをしてユーザに対してキレる
- 数億件のcross joinをかまされdwhが落ちる
- 勝手に権限変更をされbatch処理が動かなくなる

ユーザはデータ基盤運用者が思う以上にいろんなことをします
ユーザが無茶をしても大丈夫なようにガードレールの設置をする、ユーザ教育を一緒にするなどするとユーザとの信頼性もあがり基盤の安定性も上がってくるかと思います

### 使えることが当たり前になってきて、使えないときだけユーザから怒られる
- 安定したデータ基盤を作るとユーザはいつでも使えるのをあたりまえに思えてきて、月に1時間でも使えないとクレームを言ってくる
- 障害が起きたことが目立つようになり、減点方式での評価となる

きちんとユーザや経営陣にどんだけ頑張ってこのように運用しているか伝え続けましょう
またSLAをあえて低めに設定する、SLAを設定しないというのも一つの手段かもしれません

### とにかくモダンな基盤にする
- 新しい技術をいれても、ユーザにとっていい事はないかもしれない
- 基盤の使い方がころころ変わるとユーザがついてこれない
- 世間の常識は社内の非常識であるかも知れない

新しい技術は楽しいし、触りたいです。今後の基盤の進化を見据え検証するのはいいと思いますが、装着するには本当に基盤の価値があがるかユーザが使いこなせるかを見極めてからのほうがよいでしょう

## おわりに
いくつかアンチパターンをあげさせてもらいました。

どのようにユーザと二人三脚でデータ基盤を作っていけばいいかは以前登壇させていただいた内容が記事になっているのでよかったらこちらもご参照ください
[“5つのC”で考えるデータ分析基盤の構築](https://logmi.jp/tech/articles/308269)
KDEのメニュー項目のキャッシュを再構築する

KDEのデスクトップメニューエントリファイルをいじっている時に、メニューの再構築をする必要があります。

`kbuildsycoca5 --desktopfile <.*\.desktop>`

でキャッシュが再構築され、ファイルへの変更がGUIに反映されるようになります。
【ThisWorkbook.Pathだとダメ】OneDriveで同期しているファイルのローカルパス取得方法【VBA】

通常、ThisWorkbook.Pathを使えば自分自身の格納ディレクトリのパスを取得できますが、OneDriveで同期しているファイルの場合、OneDrive上のURLが返却されます。

（例：）
https://アカウント名-my.sharepoint.com/personal/・・・

※パスは、法人向け（OneDrive for Business）か個人向けかでドメイン部分が異なるようです

調べてみた結果、以下サイトで公開している関数が一番スマートな対処法でした。

[[VBA]OneDriveで同期しているファイルまたはフォルダのURLをローカルパスに変換する関数 | 黒い箱の中](https://kuroihako.com/vba/onedriveurltolocalpath/)

ポイントは以下の3点。

- 環境変数を取得するVBAのEnviron関数を使って、OneDriveのローカルパスを取得
- URLは法人向けと個人向けがあるのでそれぞれURLのパターンで判別
- URLの後半（"/Documents"）以降は、OneDrive内のフォルダ階層をURLで表現しているので、"/Documents"以降を抜き出しつつ"/"を"\"に変換して連結
応用数学　「情報理論」

# ３章　情報理論
<dl>
  <dt>情報理論と情報科学</dt>
  <dd>情報理論</dd>
  <dd>情報科学</dd>
</dl>
<dl>
  <dt>情報量</dt>
  <dd>情報量の性質</dd>
  <dd>自己情報量</dd>
  <dd>シャノンエントロピー</dd>
  <dd>カルバック・ライブラー・ダイバージェンス（D-KL）</dd>
  <dd>交差エントロピー</dd>
</dl>

## 情報理論と情報科学
### 情報理論
情報理論とは、情報とは何かを定義し、より良い扱い方を考える学問である。
これは3つのジャンルに分類することができる。
1つ目は、「情報量とは何か」の定義を考えていくことである。
2つ目は、情報の送受信をいかに効率よくできるかを考えていくことである。
3つ目は、送信した情報に雑音が入った時、いかにしてそのノイズを減らしていくかを考えていくことである。
### 情報科学
ここでいう情報科学とは、情報理論と言葉時代は似ているが概念が異なる。情報科学とは、人間が持つ情報処理能力をコンピュータに置き換えて同じような能力を持てるよう研究していく学問である。

## 情報量
###情報量の性質
情報量の性質を2つ紹介する。
１つ目は、発生する確率の値が小さいほど情報量は大きくなるということだ。例えば、事象Aの起こる確率Pの値が小さくなればなるほど情報量は多くなるといったものだ。
2つ目は、情報量は足し合わされていくということだ。しかし、ここで問題となるのが確率の足し算は掛け算になってしまうというものだ。数学的なニーズを考慮すると、掛け算は扱いにくいので足し算を使いたい。そこで、情報量では掛け算を足し算として表すためにlogが用いられる。
###自己情報量
あることがわかった際の「そのこと」を自己情報量という。
自己情報量は、

```math
I(x) = -log_2p(x)
```
と表すことができる。コンピュータは0か1の２択で動くことが多いので、対数の底も２を使うことが多い。この対数の低が2の時の自己情報量の単位はbitである。一方、自然対数の時、すなわち対数の底がe(ネイピア)であった時、自己情報量はnatを用いる。
###シャノンエントロピー
シャノンエントロピーは、自己情報量の期待値である。つまり、平均情報量の不確実性ともいえる。

```math
\begin{align}
H(x) &= E(I(x))\\\\
&= -E(logp(x)) \\\\
&=-∑P(x)logP(x)
\end{align}
```
　　E = 期待値　I = 自己情報量
###カルバック・ライブラー・ダイバージェンス（D-KL）
D-KLは、同じ事象・確率変数である確率分布P,Qの差を測る一つの尺度である。これは、非負性、完備性、非対称性、絶対連続性を持っている。

```math
\begin{align}
D_{KL}(P||Q) &= E_{x-p}(log\frac{P(x)}{Q(x)}) \\\\
&= E_{x-p}(logP(x)-logQ(x)) \\\\
&= ∑(((-logQ(x))-(-logP(x))) \\\\
&= ∑P(x)log\frac{P(x)}{Q(x)}
\end{align}
```
###交差エントロピー
交差は組み合わせるという意味を持ち、エントロピーは情報量という意味である。つまり、交差エントロピーとは、PとQを組み合わせた時の情報量である。

```math
\begin{align}
H(P,Q) &= H(P) + D_{KL}(P||Q) \\\\
&= -E_{x-p}logQ(x) \\\\
&= -∑P(x)logQ(x) \\\\
\end{align}
```
firewallコマンド

インフラエンジニアではないけど、linuxでfirewallコマンドを使う時の備忘録です

```:設定を変更する
# サービス名で指定する

firewall-cmd --add-service http(サービス名とか)

# ポート番号で指定する

firewall-cmd --add-port 80/tcp(ポート番号/プロトコル)
```

```:変更した設定を保存する
firewall-cmd --add-service http(サービス名とか) --permanent
firewall-cmd --add-port 80/tcp(ポート番号/プロトコル) --permanent
```

```:設定を削除する
firewall-cmd --remove-service http(サービス名とか)
```

```:削除した設定を保存する
firewall-cmd --remove-service http(サービス名とか) --permanent
```

```:設定を読込
firewall-cmd --reload
```
pythonによるスクレイピング＆機械学習をtensorflow2で動かしてみた

<h1>前提条件</h1>

<h2>対象</h2>
この記事は、Webエンジニア向けです。
私自身Webプログラマでして、機械学習を仕事に活かせないかと考えるために勉強しつつ書いたものになります。
それと、「<a href='https://www.amazon.co.jp/%E5%A2%97%E8%A3%9C%E6%94%B9%E8%A8%82Python%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92-%E9%96%8B%E7%99%BA%E3%83%86%E3%82%AF%E3%83%8B%E3%83%83%E3%82%AF-%E3%82%AF%E3%82%B8%E3%83%A9%E9%A3%9B%E8%A1%8C%E6%9C%BA/dp/4802611927/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&dchild=1&keywords=python%E3%81%AB%E3%82%88%E3%82%8B%E3%82%B9%E3%82%AF%E3%83%AC%E3%82%A4%E3%83%94%E3%83%B3%E3%82%B0&qid=1606396933&sr=8-1'>pythonによるスクレイピング＆機械学習</a>」に沿って書くので、本の補足のつもりでみてください。

<h2>環境</h2>
・PC : Macbook pro
・OS : Catalina(10.15.7)
・言語 : python2.7.16
・エディタ : jupyter（せっかくなので使いましょう、便利です）
pythonやライブラリのインストールは、つまづいた記憶もないのでここでは省きます。

<h2>お願い</h2>
あなたに感想や要望を書いて頂けると主が喜びます。ぜひ気軽にコメントしていってください。
もっとシンプルな方法があれば教えてください。

<h1>レッツ機械学習</h1>
<h2>tensorflow2(以下、tf2)の便利技</h2>
基本的にtf2は、無印の動作もできます

```
sess = tf.compat.v1.Session()
sess.run(tf.global_variables_initializer())
```
本をよみながら、うまくtf2の書き方にできない時は、これで誤魔化しましょう

<h2>5-4をtf2でやってみる</h2>
src/ch5/placeholder1.pyをtf2化
<font color=gray>著作権上元コードは乗せてません</font>

```
import tensorflow as tf

#メソッドで制御
#noneを指定してあげると、配列が可変となる
@tf.function(input_signature=[tf.TensorSpec([None], tf.int32)])
def hoge(a):
    b = tf.constant(2)
    return a * b

#.numpy()で数字の部分だけとれる
print( hoge(tf.constant([1,2,3])).numpy() )
print( hoge(tf.constant([10,20,30])) )
```
結果

```
[2 4 6]
tf.Tensor([20 40 60], shape=(3,), dtype=int32)
```

<b>簡単な解説</b>
このメソッド自体は
元のコードでは、メソッドではなくsession.runで動作してます。
tf2ではsessionは使わなくてよくなったので、シンプルに作れます。

まず、元のコードではrun時に値を代入していますが、私はメソッドに引数を渡して、動作させてます。
```@tf.function(input_signature=[tf.TensorSpec([None], tf.int32)])```
この定義により引数の型を決めています。もちろん複数定義もできます。

その後は、元コードと同じように配列の掛け算を行って表示してます。

<h1>まとめ</h1>
短いですが、tf2のさわりはこんな感じです。
1.sessionは必要ない
2.メソッドを作りやすくなった
それ以外にももちろん機械学習において便利になった点もあるので、
この本を元に今後アップしていけたらと思います。

ありがとうございました。
必要そうな知識（SES）

#概要
必要そうな知識を集めたリンク集
一旦SESでと限定しておく。
（起業する人とかSQLはビジネスマンにも参考になるかも）
前提として基本情報の知識
#Linux　
Progateだと足りないし、他だと多いし・・・
今回は嫌な感じまで行けたような気がする。
https://qiita.com/gina/items/db24e22299747b031534
#vi 
今回は嫌な感じまで行けたような気がする。
https://qiita.com/gina/items/659822f3f28911132a55
#データベース　基本的なところ
#SQL　Group　By　とかCaseとか
#GIT/GITHUB
#AWSやコンテナ
ネットワークの知識の学びにいいような気がする。
私はDockerにデータベースとかJenkins入れたりして学ぶのに使った方が
いいような気がするが・・・ここら辺は人によって考えが違うと思う。
#CSS　クラスとIDと
#ショートカット
#タイピング
タイピング学習サイトです。
https://typing.twi1.me/
さよならMBed... :: micro:bit v2.0::

#Micro:bit2.0発売!
Micro:bitが2.0になりました。STEM目的で作られたMicro:bitは、他のNordic社製BLE ICが搭載されたボードより、圧倒的に安い上に、加速度センサーやLEDなど、センサーも諸々搭載されているので、これを本格的な電子工作に使えないか色々模索していました。ただ、v1.4まではMBedで綺麗に開発できる環境が整っていたのですが、v1.6でのセンサー変更に対応せず、更新を待ち望んでいたところでのv2.0が発売ということで、MbedのDALも更新されるだろうと期待していました。

#Mbedからの脱却
ワクワクしながらMBedのページを訪れたのですが、全く更新されている様子がありません。MakeCodeでは動く環境が整っているようなので、何等か基礎のDALはあるはずと、色々なWebを回ったのですが、衝撃の情報が...

[The micro:bit runtime DAL/CODAL](https://tech.microbit.org/software/runtime/)

**v2.0でMbedが外されていました...**

他の開発環境で動かす方法探すしかなさそうですね...

Micro:bitのC/C++開発環境が完成したら、また記事更新します。
PC買い替え時のWSLの移行についてのメモ

最近PCを買い替えました。
その際、WSL環境を移行にい手間取ったので、そのことについて簡単にまとめてみました。

## ver
Windows10
Ubuntu18.04

## 目標
旧PCのWSLの環境を新PCに移行して起動する(Windows ストアアプリ Ubuntu 18.04にて)

## WSL環境(ディストリビューション)を別PCに移行すること自体は簡単である
旧PCでエクスポートいしたWSL環境を新PCでインポートするだけである

```powershell:powershell-旧PC
# インストールしてあるWSLの確認
wsl -l -v
# 出力されたNAME列より、移行したいWSLのNAMEを指定してエクスポート
# この場合「Ubuntu-18.04」がNAME列で出力されたもの
\ wsl --export Ubuntu-18.04 ./hoge.tar
```

ディストリビューション名hogeとしてエクスポート
エクスポートされたtarファイルを新PCに移行し以下を実行


ストアアプリ版Ubuntuのデータは
C:\Users\name\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_~
にあるが、参考にしたサイトでは
C:\Users\name\AppData\Local
にWSLをインストールしている


```powershell:powershell-新PC
# WSLのインポート先フォルダの作成
\ mkdir ~/AppData/Local/hoge
# tarファイルのあるディレクトリにて実行
\ wsl --import hoge ~/AppData/Local/hoge 
# wsl hogeが作成されたことを確認
\ wsl -l -v

# hoge起動
\ wsl --distribution hoge
```

## ここで問題が
WSL移行自体はこれで完了しているのだが、
ストアアプリ版Ubuntu(18.04)を起動するとhogeは起動せず、新しいWSL環境が
構築され起動してしまう。

```powershell:powershell
# ストアアプリ版Ubuntuを実行後に一覧を見ると、Ubuntu18.04が作成されていることがわかる
\ wsl -l -v
```

当初の目的であったストアアプリ版からのhogeの起動ができないのである。

## 解決策
#### 1.諦めてpowershellからWSLを起動する
#### 2.ディストリビューション名をストアアプリ版によって定められた名前にする
#### 3.諦めてストアアプリ版を１から使っていく

1. 諦めてpowershellからWSLを起動する
powershellでwslと打てば起動する(デフォルトユーザ、ディストリビューションも指定できる)ので
ストアアプリ版は諦めるという考え方

2. ディストリビューション名をストアアプリ版によって定められた名前にする
例えば、ストアアプリ版Ubuntu18.04のディストリビューション名は「Ubuntu-18.04」である
なのでインポートする際に、この名前で設定することで、ストアアプリ版をインストールし、起動することで、
インポートしたWSL環境が扱える

```powershell:powershell
\ wsl --import Ubuntu-18.04 ~/AppData/Local/hoge ./hoge.tar
```

しかし、前に書いたようにストアアプリ版Ubuntuのデータは、
C:\Users\name\AppData\Local\Packages\CanonicalGroupLimited.Ubuntu18.04onWindows_~
に存在しているのに対し、インポートしたWSLは別フォルダに存在しているので、
何かしらでうまく動かなくなる可能性が懸念される。

3.諦めてストアアプリ版を１から使っていく
ストアアプリ版からの起動にこだわり、かつ安全な方法
私はこれを採用した。

## 最後に
Windows10のデータ移行がいまいちよくわからず、フォルダを手動で移行していたので
このようなことになってしまったのかもしれない。
Windows10の移行を別の方法で行えば、アプリレベルで移行できるかもしれないので、いい方法があればコメントください。

## 参考サイト
https://forest.watch.impress.co.jp/docs/serial/yajiuma/1220926.html
.NET 5 を使いたい理由6選

# 速いので使いたい

私の場合、ここ数か月で一番素晴らしいニュースだと感じたブログがこれでした。
https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-5/
.NET5 がどれだけパフォーマンス向上のために努力してきたかという内容です。
ものすごいボリュームで読むのが大変でしたが、満足感のある記事でした。
この記事を読んだだけでも、早く.NET 5 を使いたいという気持ちになりました。
パフォーマンスが良くなったという知らせはいつでもエンジニアの気持ちを高揚させるのだと思います。

## 使いたい理由1 : GCが高速化した

いくつものアプローチを重ねたことが記されていました。

* GCが到達可能オブジェクトをマークする処理の情報を他のスレッドでも流用できるようにして、各スレッド内の同処理の作業量を一部省略可能にした
* GCのGen0,1が使用する近傍のメモリのデコミット(OSにメモリ返却する処理)を最適化した。メモリが返却されてもGen0,1の領域はすぐに再確保が必要になる可能性があり、その頻度を減らすことを目的とする
* GCの統計手法の変更により、GCのスキャン競合によるロックを減らすことに成功した。これによりマルチコア時のスケーラビリティが改善する
* Intel AVX512 に対応することでGC内のソートを高速化した(並び替えをベクター化することに合わせて導入)
* バックグラウンドGCの進行中にフォアグラウンドGCのサスペンド処理自体を高速化することで、ロック時間を短縮した

要約してはみたものの、ソースコードや解説を見ても分からないものも結構ありました。

## 使いたい理由2 : coreclr(C/C++)からcorelib(C#)への移植が進んだ

GCの最適化と並行してC/C++ネイティブ実装のcoreclrをC#実装のcorelibに移植する作業も進められたそうです。
基本的にC#は安全なものなので、ネイティブ実装が減れば減った分、安全性が増します。
しかし恩恵はそれだけにとどまりません。coreclr内のネイティブコードが動作している間、GCですらもその終了を待つことになります。つまりネイティブ実装が減りC#実装が増えたことにより、GC自体が待つことが減ります。
結果として、`GC.Collect()`による遅延時間は非常に短縮されます。

## 使いたい理由3 : `Span<T>.Sort`による`Array.Sort`

ソートは大変重い処理でありながら、私たちはこれを避けることができません。しかし、`Span<T>.Sort`が追加されたことで状況は変わります。
https://docs.microsoft.com/ja-jp/dotnet/api/system.memoryextensions.sort?view=net-5.0
前述のcorelib化の恩恵でソート自体が高速化しました。C#のソートは一般に配列に対するものですが、これをSpan<T>で実行することで配列の境界チェックの処理などをかなり節約することができるようです。
また`Array.Sort`が内部的に`Span<T>.Sort`で動作するようになり、.NET Framework 4.8と比べて約2倍、.NET Core 3.1 と比べても数十%の優位があります。

## 使いたい理由4 : 配列や`Span<T>`に対するC#コンパイラやJITの最適化が素晴らしい

.NET Core 3.1 でもかなりの最適化が施されていましたが、さらにさらに強化されました。
最適化の多くは、何度も同じ処理を繰り返さないことと、不要と確定している判定を除去することが主体となります。

* メソッドローカルの`ReadOnlySpan<T>`はスタックではなくstatic領域に固定的に保持されるようになった
* 16バイト未満の配列からの積極的な境界判定の削除
* 初期化の必要がない`Span<T>`を初期化しない

などなど。

これらについては種類が多すぎて語りつくせません。
ただ言えることは、配列の境界判定のような処理が減るだけで、コードサイズは減り、処理時間も減り、良いことづくめであるということです。
配列と`Span<T>`関連についてはともかく強くなったということです。

## 使いたい理由5 : 型の扱いも速くなった

C#キャストは内部的には`CastHelper`というクラスによってキャッシュされています。この実装が改善されたため(`ref` を多用した形に変わっていました)キャストの速度は格段に向上しました。
キャスト以外にも、ジェネリックメソッドのスロットの汎用化が進み、ジェネリックメソッドの呼び出しコストが小さくなりました。
このようにRuntimeHelper群の最適化が進みました。

## 使いたい理由6 : ライブラリ群のパフォーマンスが改善されている

* 文字列処理
* 正規表現
* async/await
* コレクション
* LINQ
* ネットワーキング

## まとめ

このどれもが、既存のコードを書き換えずとも恩恵を受けることができるということがポイントとなります。
この記事にはソースコードやベンチマーク結果を掲載しません。なぜなら、冒頭のリンク先にすべてあるからです。
.NET 5 は素晴らしいものです。このパフォーマンス改善だけでも、.NET 5 に移行する動機づけとなる可能性があります。

## 謝辞

冒頭でリンクしたブログの内容は本当に素晴らしいものでした。Stephen Toub氏に感謝いたします。
また、.NET と C# の進歩と高速化に日々貢献してくださっているすべてのエンジニアに感謝いたします。

## ご案内

「.NET 5 を使いたい理由」シリーズをいくつか予定しています。
次の記事は私の所属先のお客様である 弥生株式会社様の Advent Calendar 2020 で 12/3 に公開予定です。
https://qiita.com/advent-calendar/2020/yayoi
ご覧いただければ嬉しく思います。
Ionic toggleでtrue or falseを設定し、Firestoreに保存（Angular）

#こんな感じ
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Ionicのtoggle、スッゲー使えるじゃないか。 <a href="https://t.co/LeoikCURUf">pic.twitter.com/LeoikCURUf</a></p>&mdash; 高卒プログラマーげんと (@gento34165638) <a href="https://twitter.com/gento34165638/status/1332304884515753984?ref_src=twsrc%5Etfw">November 27, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


#前提
・[AngularFire](https://github.com/angular/angularfire)がプロジェクトに入ってる
・Firebaseのプロジェクト作成済み
・`ion-toggle`の公式ドキュメントは[こちら](https://ionicframework.com/docs/api/toggle)

#実現したいこと
toggleで**`true or false`**を設定し、リアルタイムでFirestoreの値に反映させる

###ちなみに、、、
私のアプリで具体的に実現したかったことはロック機能である。

**「もしtrueならロック状態、falseなら非ロック状態」**
という具合である

#htmlファイル側

```html:home.page.html
     <ion-card>
          <ion-card-header class="ion-text-center">
            <ion-card-title>ロックをかける</ion-card-title>
          </ion-card-header>
          <ion-card-content class="ion-text-center">
            <div class="ion-margin-bottom">
              <p>アプリ起動時のロック機能を設定</p>
              <p>アカウントのパスワード入力でロックを解除します</p>
            </div>
            <div>
              <ng-template [ngIf]="!isLocked" [ngIfElse]="notLocked">
                <h2 class="ion-margin-bottom">
                  現在ロック機能は<ion-text class="bold">無効</ion-text>です
                </h2>
              </ng-template>
              <ng-template #notLocked>
                <h2 class="ion-margin-bottom">
                  現在ロック機能は<ion-text class="bold">有効</ion-text>です
                </h2>
              </ng-template>
              <ion-toggle [(ngModel)]="isLocked" (ionChange)="changeIsLocked()" >
              </ion-toggle>
            </div>
          </ion-card-content>
        </ion-card>
```

toggleの切り替えと同時に、表示するテキストなんかも変更させてあげる

#tsファイル側

```typescript
import { Injectable } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import { AngularFirestore } from '@angular/fire/firestore';

//省略

export class SettingsPage implements OnInit {
currentUser;
isLocked;

constructor(
    private afAuth: AngularFireAuth,
    private db: AngularFirestore,
  ) {}

ngOnInit() {
    this.afAuth.auth.onAuthStateChanged((user) => {
      if (user != null) {
        this.currentUser = user.uid;
      }
    });
  }


changeIsLocked() {
     const lockedRef = this.db.collection('users').doc(this.currentUser);
     console.log('isLockedを設定 ' + this.isLocked);
     lockedRef.set({ isLocked: this.isLocked }, { merge: true });
}
```

![スクリーンショット 2020-11-27 21.52.34.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167220/2767c16c-3b7f-95da-a7f7-70756a31c1af.jpeg)

これで`isLocked`はtoggleでtrueとfalseが切り替わります。

#ちなみに
これ、実は`isLocked`の初期値が設定されていないと、エラーが発生する。。:sweat_smile:

この記事では**「元々boolean型の値が存在する」**と言う前提でのコードになるので、、、Firestoreにデータを設定する方法として、ぜひ下記の記事も参考にして頂きたい:wink:
[Firestore　全てのドキュメントに対して、一気にフィールドを追加する方法（Cloud Functions）](https://qiita.com/kokogento/items/866236257a03f4dbae5b)
関節点探索アルゴリズム

# lowlinkアルゴリズム

## 注意
ほとんど自分向けなのでわかりにくいかもしれません
正直数学的厳密性にはかけた考え方ですが、アルゴリズムを理解し覚えるための「覚え方」、「考え方」と思って見ていただけると幸いです

## 手順
①始点を適当に決め、DFSで探索を行う
→発見されるまでにかかった手数を$cost$とする
→このとき経由した辺によって構成される木を$T$とする
→経由しなかった辺を$backEdge$とする
②探索が終了したら以下の3つの最小値をとる$v$の$minCost$を決める

* $cost(v)$
* もし頂点$t$との間に$backEdge$が存在するならば$cost(t)+1$
* 子のminCost

③各頂点$v$とその親$parent(v)$において以下のいずれかの式を満たすならば$parent(v)$は関節点である

(a) $v$または$parent(v)$が$root$のとき,その$root$が子を二つ持つならば関節点である
(b) $cost(parent(v)) < minCost(v)$

## オーダー
各頂点において$cost$を計算するのは$O(1)$
$minCost$の計算においては隣接する$backEdge$を全て調べるから隣接辺$T(v)$を用いて$O(T(v))$
判定は$O(1)$であるから
$\sum_v(O(1)+0(T(v)) = O(|V|)+O(|E|)=O(|V|+|E|)$
## 解説
### ②について
$minCost$はDFSでは通らなかった経路を通った場合を含めた実質的最短コストのようなもの

<img width=400 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635127/798533fc-a60b-146f-0a97-fc97d0735c05.png" style="display:block;margin-left:auto;margin-right:auto;"/>
DFSでは4番目に発見されたノードは$backEdge$を考慮すると実質的には2番目の頂点とほぼ同等コストと考えられる
また、親は子よりも早く発見されると期待できるため子の$minCost$も含めている
と考えると理解しやすい・・・かも・・・（数学的な厳密性はない）
この$minCost$の求め方によって**親の$minCost$は子の$minCost$以下であると保証できる**（ここ重要！！！！！）

### ③について
#####(a)について
以下左図に示したのは、ルートが子を二つ持ち、かつルートが関節点になっていない場合である。
しかし、DFSを行っていることからこのような木$T$が生成されることはなく、右図のような気が生成されるはずである（左優先探索の場合）
よってDFSによって得られた木$T$のルートについて、子が二つ存在することはルートが関節点であるための必要十分条件と言える。
<img width="700" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635127/c74b5f52-c5c3-aa18-d7c1-36ec233e47d2.png"　style="display:block;margin-left:auto;margin-right:auto;"/>

#####(b)について
>親の$minCost$は子の$minCost$以下であると保証できる（ここ重要！！！！！）

より$v$の子の実質的最短コストは$v$の実質的最短コストより大きい。
また、(b)が成立するとき$parent(v)$の発見コスト（実質的最短コストでない）よりも$v$および、$v$の子の実質的最短コストは大きくなる。
すなわち、どのように最短で$v$およびその子孫を見つけようとしても$parent(v)$を発見した後でしか発見できないことがコストの関係からわかる。
このことから$parent(v)$がなければ連結性が失われることがわかる。
逆に親のコストと子の実質的最短コストが等しい、または親のコストより子の実質的最短コストが小さい場合,その親を経由しなくても親の祖先からその子にたどり着ける経路が存在するということであり
$parent(v)$がなくても連結性は失われないことがわかる。
Grails4.0でtest-appを実行すると失敗するので修正した

久しぶりにGrailsを使用してみようと最新版の4.0.5を入れて動かしてみた。
かんたんにドメインクラスを作成してtest-appを実行してみたがエラーが発生する。

```
Execution failed for task ':configureChromeDriverBinary'.
> com.github.erdi.gradle.webdriver.repository.DriverUrlNotFoundException: Driver url not found for name: "chromedriver", version: "2.45.0", platform: "windows", bit: "64"
```

エラー文ググったらなにか出てくるだろうと思ったけどまともに情報が出てこない……
仕方がないのでGrailsのGitHubリポジトリでissueを検索したら下記情報がヒット
[DriverUrlNotFoundException when running \`gradle :test\` #11395](https://github.com/grails/grails-core/issues/11395)


issueに従いbuild.gradleの問題部分を確認するとwebdriverに関する部分がこう設定されている。

```
webdriverBinaries {
    chromedriver '2.45.0'
    geckodriver '0.24.0'
}
```

issueによるとWindowsでは64bitのバイナリがないので下記のように変更する。

```
webdriverBinaries {
    chromedriver {
        version = '2.45.0'
        architecture = 'X86'
    }
    geckodriver '0.24.0'
}
```

再度test-appを実行すると無事にテスト成功
かんたんな問題だったけど日本語情報がなかったので備忘録として残しておく。
Nuxt.js【@nuxtjs/pwa】Workbox is precaching URLs without revision info: /?standalone=true This is generally NOT safe. エラーについて

Nuxt.jsのpwa用ライブラリ【@nuxtjs/pwa】にて、DevToolsで下記エラーが表示される件についてです。

![nuxtjspwaWorkbox.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/5ac9e0c4-5519-4d2f-578e-a102a69c0c30.jpeg)

```
Workbox is precaching URLs without revision info: /?standalone=true
This is generally NOT safe.
```

## precacheにrevisionを指定していなのが原因の警告
上記の警告は、precacheにrevisionを指定していないことが原因のようです。
【@nuxtjs/pwa】では、v3.2.1からデフォルトでprechaceするようになっています。（キャッシュ名:`workbox-precache-v2`）
![nuxtpwa.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/6317e438-0257-7243-7a07-b4f153f89dd7.jpeg)
https://pwa.nuxtjs.org/releases

しかし、このprecacheにrevisionの指定はできないようです。GitHubのIssuseでも議論されていました。
![nuxtpwagithub.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559347/318e3ff8-d7c6-6c53-51ad-e06ad639b01d.jpeg)
https://github.com/nuxt-community/pwa-module/issues/

## v3.2.1からversionをダウングレードすることで対応
こちら一旦【@nuxtjs/pwa】を下げることで対応しました。
v3.2.1以前は、デフォルトでprecacheすることはないので、以前のversionにダウングレードすることで上記の警告は消えます。

```
yarn upgrade @nuxtjs/pwa@3.1.2
```

PWAは便利ですが、キャッシュ等でハマることは多そうです。。。
Python 基本文法

#1. 基本構文

##1.1.print関数
文字列を画面に出力したいときに、print関数を使用する。

```Python:print関数
print("Hello World!")
```

##1.2.コメント
Pythonでは「#」がコメントとして表記される。
複数行をコメントしたい場合はダブルクォーテーションで囲むか、シングルクォーテーション3つで囲む。

```Python:コメント
# 行コメント
"
　複数行コメント1
"
'''
　複数行コメント2
'''
```

##1.3.変数
宣言や代入は以下のように記述する。
>変数名 = 値

Javaのように変数の前に型を宣言せず、値の形によって変数の型が決まる。

```Python:変数
#int
var_int = 10

#float
var_float = 1.234

#str:""もしくは''
var_str = "piyo"

#bool:True,False
var_bool = True
```

#1.4.演算子
演算子に関しては以下のものを使用できる。
加算：x + y
減算：x - y
乗算：x * y
除算：x / y
割った余り：x % y
べき乗：x ** y
切り捨て除算：x // y
論理演算子（AND）：x and y
論理演算子（OR）：x or y
論理演算子（NOT)：not x(xは条件式で、条件式がTrueの場合のみFalseを返す。）

##1.5.if文
条件式がTrueの場合のみ後続の処理が実行される。

Pythonでは同じインデントが1つのブロックとなる。
コロン（：）で始まる行が複合分の始まりと判定されるため、複合文中に含まれる同じインデントは1つのブロックとなる。

```Python:if文
if 条件式:
    #行いたい処理
elif 条件式:
    #行いたい処理
    #行いたい処理
else:
    #どの条件にも当てはまらなかった時の処理
```

##1.6.for文
for文の繰り返し処理の構文は以下のようになる。
>for 変数 in range([始まりの数値=0,]最後の数値[,増加する量=1]):
>    #ループ処理

```Python:for文
for x in range(3):
   print(x)
#結果
#0
#1
#2

for x in range(4,10,2):
    print(x)
#結果
#4
#6
#8
```

##1.7.while文
条件が正しい時だけ、whileブロック中の繰り返し処理を行う。

```Python:while文
var = 1
while var < 3:
    print(var)
    var += 1 #加算
```

##1.8.条件分岐内、ループ内の処理

###1.8.1.break
for,whileを途中で終了したい場合、break文を使用する。

```Python:break文
for number in range(10):
    if number == 5:
        break
    print(number)
```

###1.8.2.continue
for,whileの中にある特定の処理をスキップしたい場合、continue文を使用する。

```Python:continue文
for number in range (10):
    if number == 5:
        continue
    print(number)
```

##1.9.配列

###1.9.1.リスト構造
単純な要素をいくつか持っている集合。

```Python:リスト
# 単純なリスト
list_1 = [1, 2, 3, 4]

# 異なる型のリスト
list_2 = [1, "Hello", True]

# リストにリスト
list_3 = [1, ["hoge", "piyo"], 2, 3]

# 空のリスト
list_4 = []

# 要素を指定した個数繰り返すリスト
list_5 = [1, 2, 3] * 3
# [1, 2, 3, 1, 2, 3, 1, 2, 3]

# 要素の取得 
# 要素のインデックスは0から始まる
print(list_1[0])
```

###1.9.2.辞書構造
keyとvalueの組み合わせが含まれている構造。
keyの重複は許されない、同じkeyは値が上書きされる。
>dict = { key1:value1, key2:value2, key3:value3 }>


```Python:dictionary
dict = { 1:"hoge", 2:"piyo" }

# piyo
dict[2]

# [1, 2]
dict.keys()

# [”hoge”, "piyo"]
dict.values()

# [(1, "hoge"), (2, "piyo")]
dict.items()
```

###1.9.3.変更を許可しない配列
リストと同じ構造だが、編集が不可能。

```Python:tuple
tuple = (1, 2, 3)
```

###1.9.4.集合演算等に使用する配列
リストと同じ構造だが、要素が重複できないのと順序の保証がない。

```Python:set
set = set([ 1, 2, 3 ])

# 要素を追加：add
set.add(4)

# 要素を削除：remove
set.remove(3)
```
wafとfirewallの違い

## 勉強前イメージ

wafはwebに特化したやつ
firewallは全般的な感じ？

## 調査

### wafとは

Web Application Firewall の略
firewallの一種
元々のfirewallでは防げないwebに対する不正な攻撃を防御する

### firewallとは

ネットワークとネットワークの間に立つ、不正アクセスをブロックするためのシステム

### waf と firewallの違い

firewallは主に、L3レイヤーのポートスキャンなどを防ぐことが出来る
WAFはwebに特化したfirewallなので、SQLインジェクションやクロスサイトスクリプティングなどを防ぐことが出来る
攻撃を防ぐことが出来るレイヤーが違うので、どちらも対策することが必要


![攻撃Untitled Diagram.drawio - diagrams.net - Google Ch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/54e879e2-ce19-0189-9018-17e4dd688e9e.png)


## 勉強後イメージ

firewallだけではだめな理由が分かった。
IPS/IDSについては触れなかったけど、見たことあるレベルで実はあんまり分かってない。
次ちゃんと調べる

## 参考

- [WAFとは？初心者にもわかりやすく一から徹底解説！](https://it-trend.jp/waf/article/162-0008)
- [Webアプリケーションファイアーウォール（WAF）SiteGuard](https://cweb.canon.jp/it-sec/solution/siteguard/waf/)
aws cliでs3に再帰的にファイルをアップロードする時の記述

たまにしか使わなくて毎回忘れるのでメモとして残します。

# 再帰的にアップロードする記述
```bash
aws s3 cp ローカルのディレクトリ名 s3://バケット名/フォルダ名 --recursive
```

アップロードのときにpublic read付ける場合は`--acl public-read`をつける

```bash
aws s3 cp ローカルのディレクトリ名 s3://バケット名/フォルダ名 --recursive --acl public-read
```

# バケットから再帰的にダウンロードする記述
```bash
aws s3 cp s3://バケット名/フォルダ名 ローカルのディレクトリ名 --recursive
```

# バケットからバケットへ再帰的にコピーする記述
応用してバケットからバケットへも出来ます。

```bash
aws s3 cp s3://送信元バケット名/フォルダ名 s3://送信先バケット名/フォルダ名 --recursive
```

# ついでにファイル数とかの確認
アップロードしたファイルの数があってるか等の確認に使える記述

```bash
aws s3 ls s3://バケット名/フォルダ名 --recursive --human --sum
```

以下のような結果が返ります。

```bash
2020-11-27 12:34:56   10 Bytes ファイル名
2020-11-27 12:34:56    1.2 KiB ファイル名
  :
2020-11-27 12:34:56  100.1 MiB ファイル名

Total Objects: 100
   Total Size: 999.9 MiB
```

# 参考
[AWS CLI Command Reference/s3/cp](https://docs.aws.amazon.com/cli/latest/reference/s3/cp.html)
Python学習 基礎編　~数値と計算~

こちらではPython学習の備忘録と、Ruby、JavaScriptとの比較も含め記載していきたいと思います。
プログラミング初心者や他の言語にも興味、関心をお持ちの方の参考になれば幸いです。

###数値とは?
プログラミングでは、数値を扱うこともでき、文字列とは違いクォーテーションで囲む必要がない。
クォーテーションをつけると、文字列と解釈されるため、文字列と数値は明確に違うものであることを意識しよう。

###計算について
数値は、足し算「+」、引き算「-」、掛け算「*」(アスタリスク)、割り算「/」(スラッシュ)、余剰(割り算の余り)「%」の計算が可能です。
また数値や記号はすべて半角で記述する。

※記号の前後の半角スペースはなくても構わないですが、入れた方がコードが見やすいと思います。

以上は、Python、Ruby、JavaScriptで共通となります。
各言語の記述を下記に記載します。

###Python

```py:script.py
print(3)  # 数値のみ
print(3 + 5)  # 対し算
print(6 - 5)  # 引き算
print(3 * 5)  # 掛け算
print(20 / 5)  # 割り算
print(8 % 5)  # 余剰(割り算の余り) 

# コンソール
3
8
1
15
4
3  # 8割る5は、1余り３
```

###Ruby

```ruby:index.rb
puts 3
puts 3 + 5
puts 6 - 5
puts 3 * 5
puts 20 / 5
puts 8 % 5
```
###JavaScript


```javascript:script.js
console.log(3);
console.log(3 + 5);
console.log(6 - 5);
console.log(3 * 5);
console.log(20 / 5);
console.log(8 % 5);
```

 * * *
###おわりに
数値に関しては、各言語ともに共通する部分が多いので覚えやすいですね。次回は文字列の連結などをやろうかな...では！
Laravelのscss(background)で画像を読み込ませたい

# SCSSに画像を読み込ませたい

```css:cssで画像を読み込ませたい
background: url("../../../public/img/lp/icn-check.png") no-repeat
                5px 40%;
```

たったこれだけに少し苦戦をしたので、アウトプットしておきたいと思います。

# webpack.mix.jsを編集

まずwebpack.mix.jsを編集します。

```js:webpack.mix.js
mix.js("resources/js/app.js", "public/js")
    .sass("resources/sass/app.scss", "public/css")
    .options({
        processCssUrls: false
    });
```

ポイントをそれぞれみます。

```js
.sass("resources/sass/app.scss", "public/css")
```
`"public/css"`をつけて、cssの保存先のフォルダを指定します。
[詳細](https://readouble.com/laravel/5.4/ja/mix.html)
そして、oputinsを付与します。

```js:optionsを付与
.options({
      processCssUrls: false
   });
```

これをつけない場合、通常下記のようになる。

```css:css
.example {
  background: url(/images/example.png?d41d8cd98f00b204e9800998ecf8427e);
}
```
こうなると指定した画像名と異なるため、画像を読み込めない。
なので、`processCssUrls: false`にする。

# ファイルを指定する。

さあ、準備ができました。
あとは画像を指定するだけです。
ここから**重要**です。

scssファイルの階層は、
`アプリ名/resources/sass/lp/top.scss`

画像ファイルの階層は、下記に入れたとします（人によります）。
`アプリ名/public/img/lp/icn-check.png`

画像は`resourcs`フォルダの兄弟ディレクトリである、`public`フォルダに入れています。
そのため、上の階層に戻す必要があります。

なので、階層を戻していきます。
`アプリ名/resources/sass/lp/top.scss`なので、3階層戻ります。

```css
background: url("../../../");
```
これでresourcesの親階層になります。`resources`の兄弟ディレクトリである、`public`フォルダを指定したいので、

```css
background: url("../../../public/");
```
あとは画像を入れているフォルダを指定してやればいいので、

```css
background: url("../../../public/img/lp/icn-check.png") no-repeat 5px 40%;
```

となります。

はじめは`public/css`を読み込んでいると思っていましたが、そうではなく`sass`ファルダから画像フォルダまでのパスを記載してやる必要がありました。
オプティマイザってなんや

#レスポンス改善はオプティマイザの気持ちになれば簡単
そんなことをよく聞く。
最初はオプティマイザってなんやねんって感じですが、先輩方の話はしっかり聞くべき。
ってことで、オプティマイザと友達になるために、いろいろ調査したまとめ！


##オプティマイザとは
一言でいうと処理を最適に行うための機能。
オプティマイザはその名の通り『最適化』を目的とし、現在のDBに対しSQLから最も最適なデータ取得処理を生成する。

##SQL文通りにデータを取得すれば、いいだけじゃないのか？
SQLはどのテーブルからどのようにデータを取得するかを記述したものでDBからどのようにデータを取得するかは書いていない。
つまり最適化された、実行計画を作成し、実行させるのがオプティマイザ。

```sql
SELECT * FROM Shain WHERE ShainName = '田中'
```

このようなSQL文の場合は、どのインデックス利用するか等。
結合があるがある場合は、結合方式を決定するのも、オプティマイザ。


##そんな優秀なオプティマイザがあるならなんでレスポンスが悪くなるの？？
常に最適な実行プランを選定してくれる、オプティマイザ様がいるならレスポンスなんてこっちで気にする必要なんてないじゃん。
とはならないのが悲しいところ。
そもそも、適切なINDEXが無かったら現状で最適な実行計画なだけで、実際に早いわけではない。
常に必要なINDEXを想定しながら、開発してきたい。

##じゃぁ何を元にオプティマイザは実行プランを決定するの？
ずばり統計情報というものを元に、コストを評価し実行プランを生成する。

統計情報とは。
表やインデックス、使用している領域、データの種類、データの分布等のデータ特性を表す情報のこと。
具体的には・・・・
・各テーブルのレコード数
・各テーブルの列数と列のサイズ
・列値のカーディナリティ(値の個数)
・列値のデータ分布(どの値がいくつあるかのヒストグラム)
・列内のNULLの数
・インデックス情報


この情報だけ見ても、なんだか確かに最適解を取ってきてくれそうな気がしますね。

ただ実際は統計情報をただ闇雲に信じればいいということでもない・・・・
これは次回のまとめていきます。
チームで使えるExcelファイルの作り方


# 始まりは。。
ある日仕事で使っていたエクセルファイルに下のような数式が含まれていました。これはエラーにならず間違った答えを表示してしまいます。[^1]
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/339767/50e86152-9db8-7650-0b02-726c8f795367.png)

この時は「あれ。。結果おかしくない？」と目視で気づけたのでよかったのですが、危うく大問題の資料を世の中に出してしまうところでした。このようにExcelは非常に便利ですが、なかなかその人の個性が出てくるので人のフォーマットの地雷を気づかないうちに踏んでいることがあります。

そこで「データをもらった時に解読から始めなくてもいいシートづくり」のために必要なことをまとめました。

コメントでみなさんの普段使っているExcelファイルを作るときに気を付けていることも教えてください。

[^1]: エクセルではTRUEやFALSEの論理値と数値の比較ができないため、このような二重比較はできない。しかし内部の扱いとしては論理値はどんな数値よりも大きいという返り値を返すので上の例はFALSEとなる。正しい数式を書くためにはAND関数を使わなくてはならない。

## フォーマットを作るときに必ず注意すべきこと

* スタイルダイアログを使ってセルに含まれる値の意味が一目瞭然にする）`Shift`+`Alt`+`バッククォート`
* 非表示は使わず**グループ化**を使う）`Shift`+`Alt`+`→`
* 使ってないシートは消す
* 図形はでたらめに配置せず、『グリッドに合わせる』機能を使う。`Alt`キー押しながらでも同様の機能を得る
* コメントや説明図を入れてわかりやすく。`Shift`+`F2`
* 数字にはカンマ区切りをつける。`Ctrl`+`Shift`+`1`
* **ポカヨケ**（fool proof：フールプルーフ）を設置する。例えば、誤った値や未入力がある場合には条件付き書式を使ってセルが赤塗りつぶしになる等。
* **印刷用のシートとデータ処理用のシートは分ける**。印刷用は改ページプレビューにする。
* 日本語しか入らない部分には入力規則を利用してIMEコントロールを入れる。
* データの再利用性が下がるので、無駄なセルの結合はやめる。
* フォントは特別な理由を持たずに個別にせず、**レイアウトタブのフォントで「見出し・本文」を使って**設定。

## わかりやすい関数・数式処理を行う
よくプログラミングで後から読み返すことが到底できないようなコードを「スパゲティコード」と呼んだりしますが、そういったネストだらけな式を作らないようにします。

* `Ctrl`+`Shift`+`@`でセルの数式の表示を切り替える。
* 数式入りのセルには色をつける。もしくはシートの保護をかける。
* 関数のネスト（入れ子）はなるべくやめてわかりやすい式を書く。
* シートが多いときには**ハイパーリンク**でつなぐ、ブックを超えたリンクは作らない。
* 数式が複雑になるときにはセルに名前をつけて使用する。その場合はユーザに「名前の管理」から確認するように促す。

## エラーは必ず起こる、フェールセーフの考え方
* エラーが起こったときの対応を**IFERROR関数**で記述しておく。
* VLOOKUP関数やMATCH関数の「**検索の型**」はExcelの内部処理の仕組みがわからないと予期せぬエラーを起こしやすいのでケーステストをしっかり行う。

### Excelによるエラーの種類
* `#####` これはエラーではない、入力した数値や計算結果の桁数がセル幅より大きいため表示しきれない
* `#DIV\/0!` 数値を0で割り算したときに表示される
* `#N/A` 関数や計算式に使用できる値がないときなどに表示される
* `#NAME?` 関数名が間違っているときなどに表示される
* `#NULL!` 指定した2つのセル範囲に共通部分がないときなどに表示される
* `#NUM!` 関数または計算式の数値に問題があるときなどに表示される
* `#REF!` 計算式内で使っているセル参照に誤りがあるときなどに表示される
* `#VALUE!` 関数の引数に誤りがあるときなどに表示される
[自分用メモ]Karabiner-ElementsでG913をMac風キーボードにする

![スクリーンショット 2022-10-03 9.07.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/832b2379-3ac8-eeda-dec1-c22c0727947f.png)

![スクリーンショット 2022-10-03 9.07.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58650/dba6505f-298f-0445-6cd1-34504556d379.png)
Jenkins 2.264以降でLocks and Latches pluginを使用しているとジョブ設定の変更が保存できなくなる

# 背景
Jenkins 2.264以降で特定のプラグインを使用しているとジョブ設定の変更が保存できなくなると、一部界隈で騒がれています。（たぶん）
影響を受けるプラグインは複数あり、それぞれIssueが挙げられています。
https://issues.jenkins.io/secure/Dashboard.jspa?selectPageId=20741

それで、私も同様の問題を踏んだので共有してみます。

# 内容
タイトルの通りなのですが、Jenkins 2.264以降でLocks and Latches pluginを使用しているとジョブ設定が保存できなくなります。（保存ボタンを押しても何も起こらない）

Locks and Latches pluginとはジョブを排他実行する機能を提供するプラグインで、インストールするとジョブの設定の「ビルド環境」のエリアに「Locks」というチェックボックスが出現し、それで設定ができるようになります。

![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/321705/1f2cbdf4-3755-4ea3-5124-d11d48c910ee.png)

しかしこのプラグインがインストールされていて、かつバージョンが2.264以上のJenkinsだとジョブの設定画面で変更を保存できなくなってしまうわけです。なので、このプラグインが不要なのであればアンインストールしてしまうのがいいでしょう。

…と書きましたが、このような事象を踏むことはあまりないのではないかと思います。なにしろ、このプラグインはあまり使いどころがないためか、どうやらもう廃止されたプラグインのようだからです。（もうアップデートされることはないから、アンインストールするしかないとも言えます）
https://wiki.jenkins.io/display/JENKINS/Locks+and+Latches+plugin

なので、同じ事象を踏むのはずっと昔からJenkinsを使い続けてきており、かつたまたまこのプラグインがインストールされていて、さらにこのプラグインをたまたまアンインストールせずにきて、さらにさらにJenkinsのバージョンを2.264以上に上げたユーザだけということですね。

そのようなユーザは少ないのではないかと思いますが、ゼロではないかもしれないので一応共有すべく筆を執りました。

なお、影響するユーザはゼロではないかもしれないとはいえ、（おそらく）廃止されたプラグインについてIssueを挙げるのはどうかと思うので挙げていません。
英語が得意ではないからってわけではないですよ。私程度の英語力でも案外なんとかなるのは経験上わかっているので…
（最初は普通に使われているプラグインだと思っていて、報告するためにアカウント作ってしまいました）

まあそれはさておき、万が一同じ問題を踏んだ人に届いたら幸いです。短いですが今回は以上です。
親のコンポジションにエクスプレッションが適用されないのを解決する。

### 結論：フレームレートの違い。
あるコンポジションAに、あるコンポジションBを入れたらBの中では動いてるエクスプレッションがAでは動かなくなっていました。

調べたらコンポジションBはフレームレート:30、コンポジションBはフレームレート:29.97でした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/276138/419a47bc-e74d-3ec9-f530-b3b6a5d0f9cd.png)
自作ページネーションを分解せよ

個人でWordPress開発をするときは、だいたいWP-PageNaviを使用するのですが、一応自作ページネーションも理解ぐらいはしときたいなということで記事を執筆します。

今回、使わせていただくコードはこちらです。

```index.php

<?php if ( paginate_links() ): ?>

<div class="pagenation">
<?php
 echo
 paginate_links(
 array(
 'end_size' => 1,
 'mid_size' => 1,
 'prev_next' => true,
 'prev_text' => '<i class="fas fa-angle-left"></i>',
 'next_text' => '<i class="fas fa-angle-right"></i>',
 )
);
?>
</div>

<?php endif; ?>


```
上記コードでの現在の状態はこちらです。

![b52364466a60feec8891ee43313eb424.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/8da29ab1-5cd4-b120-febb-6d7d740fb395.png)

順番にどんなパラメータなのかをみていきます。

## end_size
>（整数） （オプション） ページ番号のリストの両端（最初と最後）にいくつの数字を表示するか。
初期値： 1

下記のように変更してみます。
` 'end_size' => 1,` →　` 'end_size' => 2,`


![6ce3b32e7276d9ef040e719b92727714.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/77f38084-478a-0b04-4c1e-6121e9c4af7a.png)

両端に2つずつ数字がでるようになりました。

##mid_size
>（整数） （オプション） 現在のページの両側にいくつの数字を表示するか。ただし現在のページは含みません。
初期値： 2

下記のように変更してみます。
` 'mid_size' => 1,` →　` 'mid_size' => 3,`

![ea731a151c127b0bebf08dc5b1ff3bcc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/ab5ddb3f-a33b-e558-fc52-844ccc5f194f.png)

別のパターン。
![f0a83c4d3d40c8cdc51a4e7bed997a88.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/aa6090a0-d598-f43d-6624-a9dfc419c922.png)

## prev_next
>（真偽値） （オプション） リストの中に「前へ」「次へ」のリンクを含むかどうか。
初期値： true

まずは、初期値の状態です。
![5927a3f3f9725c5b4a1ef718c2fa154b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/6a6b5843-f5ea-e4f1-a393-60ae06a6491d.png)

これをfalseに変更すると、、、

![d4e7ac1f01992c3ac56160f40f4c0f17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/7492bce3-4545-b25f-2897-b6d6930ad1c5.png)

消えましたね。

## pre_text / next_text
**prev_text**
>（文字列） （オプション） 前のページへのリンクとして表示する文言。'prev_next' 引数が true のときだけ働きます。
初期値： __('&laquo; Previous')

**next_text**
>（文字列） （オプション） 次ページへのリンクとして表示する文言。'prev_next' 引数が true のときだけ働きます。
初期値： __('Next &raquo;')

現状の`<i class="fas fa-angle-left"></i>`や`<i class="fas fa-angle-right"></i>`は、
FontAwesomeを読み込んで表示させています。

これを下記のように変えてみます。

`<i class="fas fa-angle-left"></i>` →　`前へ`
`<i class="fas fa-angle-right"></i>`　→`次へ`

![befc8b06a2ac56aade0e39d52c286b3c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/7cfea641-8a88-59ff-ec46-86ca00474bef.png)

##まとめ
プラグインを使わなくても結構簡単に実装できますね。
なんでWP-PageNaviが人気なのかイマイチ理解できていません。

なんか理由があるのかなぁ？まぁWP-PageNaviずっと使ってきたんですがね。

※自分用メモ（生成されるコード）
![8c1390e89516ef889606d2885c25303b.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/592040/adde076a-0fa1-9ebe-2e4c-373f5b068a39.png)
Ruby on Railsでdeviseとscaffoldを組み合わせた際に調べたことをまとめてみた。

<h2>はじめに</h2>
Ruby on Railsでdeviseとscaffoldを使って簡易アプリを作っているときに分からないコードなど、調べたことを自分用にまとめてみました。
<h2>環境</h2>
MacOS Catalina version 10.15.7
Rails 6.0.3.4
devise 4.7.3
<h2>前提</h2>
```$ rails new アプリ名```でアプリができている状態
<h2>deviseの導入</h2>
以下のurlのページを参考にdeviseでログイン機能等を作成する。
```rails g devise:install```でファイルの作成を終えた後、下のコードを記述する。

```ruby:config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
```
こちらのページ⇨ https://qiita.com/Orangina1050/items/a16e655519a60f35b394

<h2>scaffoldの導入</h2>
既に作ってあるアプリにディレクトリを移動した後、以下の形式でscaffoldを実行する。

```$ rails g scaffold モデル名 カラム1:データ型1 カラム2:データ型2
```

自分は自己紹介をする簡易アプリなので以下のカラムを持たせた。

```command
$ rails g scaffold intro name:string hometown:string text:content
```

scaffold実行後以下を行う。

```command
$ rails db:migrate
```
<h4>カラムをつけ忘れて追加したい場合</h4>
```rails g migration 行なう処理Toテーブル名 カラム名:データ型```の形式で実行する。カラムを加えるなら、```AddColumnToテーブル名```というように書く。

自分は、user_idのカラムをつけ忘れたため、

```command
$ rails g migration AddColumnToIntros user_id:integer
```

を行った。```rails db:migrate```も忘れずに。

<h2>コントローラーに設定を加える</h2>

scaffoldによってできたコントローラー(intros_controller.rb)の一番上に、
```before_action :authenticate_user!```を記入する。

<h4>before_action :authenticate_user!とは</h4>
authenticate_user!はdeviseを入れる事で使えるようになるヘルパーの一つで、
コントローラーに設定してログイン済ユーザーのみにアクセスを許可する。
参考　https://qiita.com/ryuuuuuuuuuu/items/bf7e2ea18ef29254b3dd
<br>


次に、newアクション内に下記を追加する。

```ruby:app/controllers/intros_controller.rb
@intro = Intro.find_or_create_by(:user_id => current_user.id)
```

<h4>find_or_create_byとは</h4>
は引数の条件に該当するデータがあればそれを返し```find_by(attributes)```、なければ新規作成```create(attributes, &block)```します。今回は、user_idがcurrent_user.idの場合、それを取得、なければ作成を行っている。
参考　https://qiita.com/taimuzu/items/0a21738d018f475d63ae

自己紹介を既に作成しているユーザーが新規作成のボタンを押したときに編集ページにとんでほしいのでnewアクションに

```ruby:app/controllers/intros_controller.rb
redirect_to edit_intro_url(@intro)
```

を追記する。これは```redirect_to edit_intro_url(@user.id)```と同じことをやっている。
参考　https://qiita.com/Kawanji01/items/96fff507ed2f75403ecb

<h4>redirect_toのパス確認</h4>
さっき指定したリダイレクト先は、以下のコマンドを打つと様々なパスが出てくるので、そこから対象のものを探す。```edit_intro_url```の部分。

```command
$ rails routes
```

最後に、editアクションにidがcurrent_user.idかそうでないか分岐する処理を書く。

```ruby:app/controllers/intros_controller.rb
 if @intro.user_id != current_user.id 
    flash[:notice] = "他のユーザーの編集はできません。"
    redirect_to intros_path
 end
```

その際に、もとからindex.html.erbとshow.html.erbに書かれている、```<p id="notice"><%= notice %></p>```をコメントアウトすることで、flash[:notice]の内容を表示することができる。
chcpに私も遭遇しました。


###文字化け障害


```
echo %date% %TIME:~0,8% コメント >> txt.txt
```
出力例

```
2020/11/27 10:50:36 コメンチE
```

###chcpで文字化けの対応
UTF-8になっていました。

```
chcp 65001
echo %date% %TIME:~0,8% コメント >> txt.txt
```
出力例


```
2020/11/27 10:55:25 コメント
```


#別件で、stackoverflow（本家）で、closed されました。
アドバイスしてもらうと、助かります。
よろしくお願いします。


「echo %date% %TIME:~0,8% comment >> txt.txt」(Win)→Android:I want [closed]

https://stackoverflow.com/questions/65023127/echo-date-time0-8-comment-txt-txt-win%e2%86%92androidi-want
GitHub Actionsを使ってRailsアプリをデプロイしてみた

GitHub Actions初めて使ってみました。設定楽でいいですね。

## 使い方(ざっくり)
- プロジェクトルートに`.github/workflows`ディレクトリを作成
- その中にymlファイルを作って、実行したい処理を書く
- 環境変数を使いたい場合はGitHubにアクセスして`Settings→Secrets`で設定する
    - ymlファイル内で`${{ secrets.HOGEHOGE }}`でアクセスできる

## 使い方(実際やったこと)
masterブランチが更新された時にRailsアプリをEC2にデプロイする設定をしました。
まずGitHub上で3つの環境変数(`PRIVATE_KEY`、`USER_NAME`、`HOST_NAME`)を登録。
その後アプリに戻り以下を実行。

```zsh
$ midir -p .github/workflows
$ touch .github/workflows/rails.yml
```
```/.github/workflows/rails.yml
name: Rails CI/CD
## ↓実行タイミング
on:
  push:
    branches: [master]
  pull_request:
    branches: [master]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - name: Deploy
      # ↓環境変数
      env:
        PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}
        USER_NAME: ${{ secrets.USER_NAME }}
        HOST_NAME: ${{ secrets.HOST_NAME }}
      # ↓実行したいコマンド
      run: |
        echo "$PRIVATE_KEY" > private_key && chmod 600 private_key
        ssh -o StrictHostKeyChecking=no -i private_key ${USER_NAME}@${HOST_NAME} 'cd sample_app &&
        git pull origin master &&
        ~/.rbenv/shims/bundle install &&
        ~/.rbenv/shims/bundle exec rails assets:precompile RAILS_ENV=production &&
        ~/.rbenv/shims/bundle exec rails db:migrate RAILS_ENV=production &&
        kill $(cat tmp/pids/puma.pid) &&
        ~/.rbenv/shims/rails s -e production'
```

masterブランチが更新された時、GitHubのActionsタブにアクセスすると、作成したワークフローが正常に動いているか確認することができます。
個人でGitを使うときのコマンド

## この記事について
- 完全版私用メモ
- ターミナルを使いまくる人ようかな？


## コマンド一覧
~~~
ローカルにワークツリーを作る
>$ git init
>$ git config --global user.name [ユーザ名]
>$ git config --global user.email [メールアドレス]
>$ git add .
>$ git commit -F- <<EOM
#初回のみ
>$ git branch -M main
>$ git remote add origin [git path]
>$ git push -u origin main
~~~

## 説明(あまり使われないだろう箇所のみ)
- git commit -F- <<EOM
    - コミット文を複数行打ち込むことができる 
- 初回のみ以下の３行
    - ブランチを作成してプッシュする
Flutter環境構築で詰まったところ

# flutter doctor でエラーがでる
>[!] Android Studio (version 4.1.0)
>    ✗ Flutter plugin not installed; this adds Flutter specific functionality.
>    ✗ Dart plugin not installed; this adds Dart specific functionality.

2020/11/27　現在Flutterの環境構築をしようとすると上記のようなエラーが出ていた。
内容はAndroidStudioのFlutter,Dartのプラグインを入れなさいというエラーで、
プラグインを入れてもエラーが消えない。


どうやらAndroidStudioのバグの模様？
ターミナルから
>flutter channel dev
>flutter upgrade

で無事解決しました。
ETロボコンについて




 この記事はIIT Advent Calendar 2020 の9日目の記事です。

##はじめに
 私はETロボコンサークルに所属しています。(今年度の活動は終了しました)
この記事では、私がETロボコンに興味を持ったきっかけやその後の活動、ETロボコンをやってみての率直な感想等を書いていこうと思います。

##活動スケジュール

|月           |活動内容      |
|:-----------:|:-----------:|
| 5月         | 顔合わせ・UMLについての学習|
| 6月         | UMLについての学習      |
| 7月         | 〃        |
| 8月         | 〃       |           
| 9月         | 〃      |       
| 10月        | c++を使ったプログラミング     |    
| 11月        | プログラミング・CSS大会     |    


##ETロボコンに興味を持ったきっかけ
 私は高校時代に学園祭や産技短展など、あらゆる行事に参加していました。そこで初めてETロボコンというものがあるということを知りました。自分でプログラムしたものが実際に動いていることに感動し、本校の学生や先生などに話を伺い、家に帰ってからETロボコンについて調べまくりました。『産技短に入学できたら、絶対にETロボコンをやりたい』と思っていました。
 ところが、ETロボコンは2年生から出来るものだと入学後に聞かされました。すごくショックでした。しかし、先生から「1年生も参加してみるのもいいかもね、サークル立ち上げちゃえばいいんじゃない？」てな感じでサークルを立ち上げちゃいました。実際に、ETロボコンをやってみると、なかなか難しくて何度も挫けそうになりました。2年生にUMLの勉強を教えてもらいながら、たまにくるUML理解度確認テストをしていました。丁寧にわかりやすく教えてくれるので、理解しやすかったです。
 その後、実際にプログラミングに触れてみる機会があり、ほんの少しだけですが、プログラミングを行いました。見たことの無い構文が出てきたりしたので、C++の参考書を読んだり、2年生に聞いたり、ネットで検索したりなど、試行錯誤してプログラミングを行っていました。休日もたまーに学校に出向き、夏休みもETロボコンの勉強をしていました。今年はコロナの影響があり、実機を動かすところは見ることは出来ませんでしたが、シュミレーターを使って動いた時は、自分で書いたプログラムで動いてくれたことにすごく感動しました。この間行われたチャンピオンシップ(CSS大会)では、選抜チームの配信映像を観ました。早くゴールにたどり着いても、モデルの審査もあり、2つの成績が良くないと上位には入賞はできません。最初から最後(話の途中で寝落ち)までとても見応えがありました。

 そんなこんなで、毎日のように忙しく活動していましたが、すごく充実した学生生活を送ることができました。来年度もETロボコンの活動をを続けていけたらいいな。と思っています。

それではこの辺で終わりにしたいと思います。
拙い文書ではありましたが、最後までご覧頂きありがとうございました。
![13F42707-5A24-49D9-97E8-8FC9B742F7F7.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/869423/3ad438c2-a365-65b5-e2da-627cb059c55a.jpeg)
AMDGPU-Pro driver と NVIDIA driver を同時にインストールすると X11 起動しない(Ubuntu 20.04)

AMD GPU を指したあとに NVIDIA GPU に入れかる(or その逆)などとして,

AMDGPU-Pro(priprietary OpenGL/Vulkan) driver と NVIDIA driver が両方存在すると X11 が立ち上がりません(gdm3 では画面が出ない, lightdm ではログインループになる).

DRI あたりが干渉するなどの理由かと思われます.

現在刺さっている GPU のドライバだけ残すようにしましょう!

=> したがって NV + AMD 両方差してそれぞれで画面を出すというのもだめそう. NV + AMD 両方を使いたい場合, ROCm のほうを使い AMD は compute 専用にするなどの対処が必要と思われます.
【エラー】Big SurでDynamoDBのmockであるmotoがインストールできない

# 問題
`DynamoDB` のテストを `pytest` にて書こうとした時、
macOS Big Sur で `pipenv install moto -dev` コマンドを実行したが、
下記のエラーがでてインストールできなかった。

```shell:shell
ERROR: Could not build wheels for cryptography which use PEP 517 and cannot be installed directly
✘ Installation Failed 
```


# 解決策
```shell:shell
env LDFLAGS="-L$(brew --prefix openssl@1.1)/lib" CFLAGS="-I$(brew --prefix openssl@1.1)/include" pipenv install moto -dev
```

Sources:
[error while installing cryptography or cffi on Big Sur · Issue #5572 · pyca/cryptography · GitHub](https://github.com/pyca/cryptography/issues/5572)
[Installation — Cryptography 3.3.dev1 documentation](https://cryptography.io/en/latest/installation.html#building-cryptography-on-macos)
DebianにDockerをインストールする

## 目的

DebianにDockerをインストールする。インターネッツに色々やり方あったけど、結局公式がうまくいったので備忘として残しておきます。

## 必要なパッケージを追加

```
sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common
```

## gpgキーを追加

### 取得

```
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo apt-key add -
```

### 鍵の確認

```
sudo apt-key fingerprint 0EBFCD88
```

以下が出力されること

```
pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]
```

## リポジトリの追加

```
sudo add-apt-repository \
   "deb [arch=arm64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
```

CPUの確認は以下のコマンド

上から
- CPU情報
- CPUの種類
- CPU情報詳細
- CPUのBit数
です。

```
lscpu
uname -m
cat /proc/cpuinfo
getconf LONG_BIT
```

## Dockerのインストール

```
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose
```

※どうせ使うのでdocker-composeもいれます。

## インストール確認

```
sudo docker run hello-world
```

## dockerの自動起動と再起動

```
sudo systemctl enable docker
sudo systemctl restart docker
```

## 参考手順

https://docs.docker.com/engine/install/debian/
PHP8（PHP-FPM）のメモ

# 環境
* CentOS7  
  （元々色々なバージョンを動かすのに使ってた）

epel, remi のリポジトリの追加は済んでる環境（下記）

```bash
yum -y install epel-release
yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm
```

# PHP8と諸々インストール
```bash
yum -y install php80 php80-php php80-php-mbstring php80-php-pdo php80-php-mysqlnd php80-php-gd php80-php-xml php80-php-fpm
```

# 設定
```bash
cd /etc/opt/remi/php80/php-fpm.d/
cp -a www.conf www.conf-original
vi www.conf
```

```bash:www.conf
listen = 127.0.0.1:9080
pm = ondemand
```
いろんなバージョンのPHPを動かしているのでポートはそれぞれ被らないように設定  


```bash
vi /etc/httpd/conf.d/virtualhost.conf
```

```bash:virtualhost.conf
        <Directory "/path/to/php80/document_root">
                <FilesMatch \.php$>
                        SetHandler "proxy:fcgi://localhost:9080"  # ← www.conf に指定したポート番号
                </FilesMatch>
        </Directory>
```

更新して起動する

```bash
service httpd configtest
systemctl start php80-php-fpm
systemctl status php80-php-fpm
systemctl enable php80-php-fpm
systemctl restart httpd
```

おわり。

# Apacheのデフォルトで使用されるバージョンを変える
正解かどうかわからないけど、
PHPのバージョンごとにあるApacheのモジュールを無効化すればOK。

リネームなり削除して読み込まれるモジュールを変える。
なお、複数生きている場合はファイル名昇順で先に来るものが当たる（たぶん）
※ パッケージ更新すると復活するかも…

```bash
cd /etc/httpd/conf.modules.d
mv 15-php72-php.conf 15-php72-php.conf_bak
systemctl restart httpd
```

# PHP7のソースをPHP8で動かしてみて引っかかったところと変更内容

[自動DI](https://qiita.com/miyapei/items/9c5bb1e69f3d6c9970ac) で使ってたリフレクションの一部がコケた

```php
// ↓ NGになった
$tempReflectionClass = $reflectionParameter->getClass();

// ↓ OK
$type = $reflectionParameter->getType();
$tempReflectionClass = $type !== null && !$type->isBuiltin() 
   ? new \ReflectionClass($type->getName())
   : null
;

```



is_callable を静的でないクラスメソッドに対して
クラス名とメソッド名で読んでいたのがNGになった。

```php
// ↓ NGになった
is_callable([クラス名, 静的でないメソッド名]);

// ↓ OK
is_callable([インスタンス, 静的でないメソッド名]);
```