OmniAICreator/Qiita-1.07M huggingface dataset:
Python パッケージマネージャー比較

※ Pycon 2020 の企業ブースにて行った LT 用のスライドです

---
 
# 自己紹介

- 山元 翔太
- ビザスク アドバイザー開発チーム
- フロントエンド中心

---

# はじめに

- Python は npm, bundler のような明確なデファクトスタンダードなツールがない
  - 大体のツールが pip を内部で使ってはいる
- やりたいことや、開発スピード等を考慮して選定する

--- 

# やりたいこと

- 子依存まで含めたバージョンの固定
- パッケージのバージョンアップ
- 簡単なスクリプトの登録

---

# 話さないこと

- パッケージのビルド、PyPI へ公開など
  - setup.cfg, wheel 
  - ライブラリとして公開しないアプリケーションを想定

---

# 紹介するツール

- pip-tools
- pipenv
- poetry

---

# 今回話さないツール

- anaconda
  - 主に機械学習を行う環境を構築する際によく使われる 
  - Web アプリの開発に利用するには向いていない
- flit
- Pyflow

---

# pip-tools

---

## バージョン管理

- requirements.in, requirements.txt
  - dev-requirements.in 等を用意することで dev パッケージと分けることができる
  - `pip-compile requirements.in` で `requirements.txt` を生成する
  - `pip-sync` でインストールする

---

## バージョンアップ

- 個別にパッケージをアップデートする事ができる
  - `pip-compile --upgrade-package django` 

---

## 簡単なスクリプトの登録

- なし

--- 

# pipenv

---

## バージョン管理

-  Pipfile, Pipfile.lock 
  - dev パッケージと分けて記述できる

https://pipenv-ja.readthedocs.io/ja/translate-ja/basics.html

```Pipfile
[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true
name = "pypi"

[packages]
requests = "*"


[dev-packages]
pytest = "*"
```

---

## バージョンアップ

- すべてのパッケージをまとめて更新する
  - 個別にパッケージを更新することはできない
- install 時にもすべてのパッケージを更新する
  - Pipfile に記述したバージョンを超えることはない

---

## 簡単なスクリプトの登録

- Pipfile の scripts に記述する
  - `pipenv run foo` で実行

```
[scripts]
lint = "flake8"
```

---

## その他

- 1 年半ほどリリースされていない時期があった
  - 今年の 4 月にリリースされ、以降数回リリースされている :ideograph_advantage: 
  - https://pypi.org/project/pipenv/#history

---

# poetry

---

## バージョン管理

- pyproject.toml, poetry.lock
  - dev パッケージと分けて記述できる

https://github.com/python-poetry/poetry

```
[tool.poetry.dependencies]
requests = { version = "^2.13", extras = [ "security" ] }

[tool.poetry.scripts]
my-script = 'my_package:main'
```

---

## バージョンアップ

- 個別にパッケージの更新ができる
  - 子依存まで個別にアップデートする必要がある

---

## 簡単なスクリプトの登録

- `*.py` を用意しそれを実行する機能がある
  - 直接コマンドを記述することはできない
  - 都度ファイルを用意する必要があるので手軽さはない
    - 複雑なことをするのには便利

---

## その他
 
- メンテナが少なく開発スピードが遅め

--- 

# まとめ

- pipenv
  - 最近リリースが増えて改めて活発になってきている？
- poetry
  - 個人的には一番使いやすい
  - 時間はかかるがプルリクを送ればちゃんと取り込んでくれる 
     - [Add error handling for malfoemed author](https://github.com/python-poetry/poetry/pull/1935)
One Class SVMの実装

#0 はじめに
本記事はsklearnでOne Class SVMを実装する際の自分用メモとして記載した内容です。他の記事を読んで理解した点や、記憶しておきたい点を図を用いてまとめています。

#1 準備
読み込む関数は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/fed2d8bd-e65c-e350-750b-9d8c4e43f33f.png)


#2 データ定義

今回訓練データ、試験データ、外れ値データとして以下を定義します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/50f42547-093e-e806-bc37-f51acb0481e6.png)


`X_train`と`X_test`と`X_outliers`のグラフはそれぞれ以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/2bc951e9-7e87-0cf0-c303-9112758db710.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/c1efdd7a-141e-e3ef-b302-4662eac168d3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/3a3e56a9-5a72-c3a3-44bd-015befffd516.png)



#3 データ学習

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/6559ae1f-9cbf-df63-47a7-b5645162328a.png)

`clf.get_params`で学習に使われたパラメータが表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/8b321050-8930-7a22-a74a-662fc6f1fc21.png)

`clf.decision_function(X_test)`では各分布点における識別境界との距離を表しプラス値が分類内、マイナス値で分類外を意味する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/f1b81fe1-383f-6f80-54d6-6b2198b007da.png)

`clf.predict(X_test)`は1もしくは-1を返し、与えられた各点が外れ値かどうかがわかる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/cc94ca0b-87a4-2743-1ba4-ec28b58cc6dc.png)

外れ値として与えた`X_outliers`の範囲内外を調べるために`predict`と`decision_function`を一つの表にまとめると以下のようになる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/a5d2facf-fd4e-d1cd-694f-9485524e4809.png)

外れ値が多いため、`-1`となっているデータが多いが、一部`1`となっているところがあり学習データ範囲内になっていることがわかる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/3ae7dd64-4211-6596-e344-adea7962ebfa.png)


#4 結果表示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/e80dca41-9ac0-fec9-10ff-99e3b0cc781c.png)


`sample_set_1`は外れ値データセットの中で学習範囲内であったものの集合で、`sample_set_mina1`は外れ値データセットの中で外れ値であったものの集合です。

以下OKとなっている２点が`1`の点です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/584974/ea29f7a4-7ac1-9c5c-f986-b2f6ceba0407.png)


以上、簡単な実装メモでした。
if else練習

```
前提
プログラミング初学者（１〜２ヶ月）の私が学習したことをまとめた内容です。
実際の現場では役に立たないことや間違っていることがある可能性があります。
お気づきの際はコメントいただければ幸いです。
```

Rubyのif,elseを使った条件式の練習問題をしたので、
解説しながら自分の考えをまとめていきます。

```
問
①変数numが１以上１０以下のときtrueの時
②変数outsideがtrueであった時
①か②のどちらかを満たす時にtrue、それ以外をfalseと返すin1to10メソッドを作成する。
条件
&& ||を使って作ること。
```

## &&と||について
まずは条件のにある**&&**と**||**とはなにかについて解説します。
&&と||は論理演算子と呼ばれ、前後の記述の真偽によってtrueかfalseを返す演算子です。
### &&はaかつb
まず&はshift+6で入力できます。
&が２つつながって&&となると前後の記述が両方trueの時trueという意味になります。
例えば、

a && b

と書かれていれば、aもbもどちらも満たす時にtrueになる条件ということになります。

### ||はaまたはb
「|」はshift+¥で入力できます。
¥はキーボード右上のバックスペースの左側にあります。
||は、前後の記述どちらかを満たしていればtrueということになります。

a || b

と書かれていれば、aかbどちらかを満たす時にtrueになる条件ということになります。

#### 論理演算子を使うときの注意点
論理演算子を含む条件式では、左辺から右辺へと順番に条件式を評価します。
この順で評価が確定したところで残りの評価は行われません。
a && bであれば、aがfalseなら全体としてfalseが確定されるため、Bがtrueかfalseの判定は行われません。
a || bであればaがtrueなら全体としてtrueとなるため、bがtrueかfalseかの判定は行われません。

```ruby
回答

def in1to10(num,outside)
  if (num<=10 && num=>1) || outside
    puts "True"
  else
    puts "false"
  end
end
```
num <= 10 && num >= 1
の記述で１以上かつ１０以下の条件式ができています。

**outsideの真偽判定について**
変数での真偽判断（true/false)の場合は変数を記述するだけでその値が真か偽か評価してくれます。
わざわざ　=== trueといったような記述を行う必要はありません。

この記述によって１以上10以下がtrueの場合または、outsideがtrueの場合はTrueと出力し、それ以外はfalseと出力する記述が行えました。
深層学習のCNNのConvolution（畳み込み）の意味がどうしても納得できなかったが。。。

#概要

深層学習のCNNのConvolution（畳み込み）の意味がどうしても納得できなかったが。。。
端的には、Convolutionは、

**全く、畳んでない**

(MAX poolingとかで、だんだん、小さくなっていたりはするが。。。）

| 疑問|
|:---:|
|**なのに、なぜ、畳み込みというのか？**|

という疑問が1年以上前からあった。

このように意味がしっくりこないケースでは、それ以前の用語の使われ方、そもそも、技術用語として導入された時点にあたるべきで、
元の畳み込み(Convolution)の意味をWikipediaでみると、
以下のような畳み込み積分の説明がされている。

（引用：https://ja.wikipedia.org/wiki/%E7%95%B3%E3%81%BF%E8%BE%BC%E3%81%BF）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/42935027-3fc4-2b2e-a444-c792a2c83462.png)

しかし、この処理、全く、畳んでいない、です。

いろいろ探ってみた。

#結論

以下のconvolutionの語源に、とりあえずの解を見つけた。

https://www.etymonline.com/word/convolution

>1540s, "state of being rolled upon itself; a turning, winding, fold, or gyration," noun of state from Latin convolutus, past participle of convolvere "to roll together," from assimilated form of com "with, together" (see con-) + volvere "to roll" (from PIE root *wel- (3) "to turn, revolve"). Meaning "act of rolling or winding together" is from 1590s. Related: Convolutions.

以下、上記のGoogle翻訳（ママ）。

>1540年代、「転がっている状態;回転、曲がり、折りたたみ、回転」、ラテン語のconvolutusからの状態の名詞、コンボルベールの過去分詞「一緒に転がる」、comの同化形式から「一緒に」（参照） con-）+ volvere "to roll"（PIE root * wel-（3）from to turn、revolve）。 「転がる、巻く」の意味は1590年代から。 関連：畳み込み。

上記の

* **転がっている状態**
* **一緒に転がる**

あたりで、イメージが合うのでは。
ここでは、転がるは、進む、ぐらいのイメージでとらえました。
⇒　**はい、イメージがあいましたーー!! 完了　**

#まとめ

以下のサイトの語源の説明は、、、、他の追随を許さないような、、、面白いことが書かれていることが結構ある気がする。（正しいのかどうかは知りませんが。。。。）
https://www.etymonline.com/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342207/faff5190-3c4f-2a7c-6cfd-455d459fffe8.png)

コメントなどあればお願いします:candy:

#追記
以下の関連記事を書いた。

[深層学習における、畳み込み、相互相関。np.convolve, np.correlate。](https://qiita.com/enoughspacefor/items/c7c6d5c893d3105e4522)
Linux (グループについて)

ユーザーを管理する際に一つの概念として、<b>グループ</b>について理解しておきましょう。
「Aグループのみ閲覧可能なファイル」「Bグループのみ書き込み・閲覧可能なファイル」
上記のようにアクセス権を管理を行う際に使用したりします。

ユーザーは何かしらのグループに所属している必要があります。
グループには複数参加する事が可能です。
前回<b>useradd</b>でユーザーの作成を行いました。実はその際にグループも作成され、グループに所属されています。
<b>groups</b>コマンドを入力してみましょう。所属グループを確認出来ます。

```
neko     $  groups
neko:neko
```

nekoグループに所属している事になります。
グループには2種類あって、<b>プライマリーグループ</b>と<b>サブグループ</b>があります。
ざっくりと一番基本となるグループが<b>プライマリーグループ</b>で、それ以外のグループは<b>サブグループ</b>で捉えてしまっていいでしょう。

<font color=red>
<h1>groupadd</h1>
</font>
グループを実際に作成しましょう。<b>groupadd</b>コマンドで作成する事が出来ます。
今回はnyanyaグループを作成します。

```
root     #  groupadd nyanya
```

作成したグループの確認は、<b>/etc/group</b>を使いましょう。
一番最後の行にnyanyaグループが表示されていると思います。

```
root     #  cat /etc/group
```

<font color=red>
<h1>usermod</h1>
</font>

作成したグループにユーザーを加入させます。<b>usermod</b>コマンドを使用します。
<b>usermod</b>は、ユーザーの設定変更を行えます。
今回の場合だと、グループに加入となりますので　-G(Group)オプションを使用します。
nyanyaグループにnekoユーザーを追加します。

```
root     # usermod -G nyanya neko
```

<b>gruops</b>コマンドを使って、確認しましょう。

```
groups neko
neko : neko nyanya 
```

nyanyaグループに参加出来ました。

<font color=red>
<h1>groupdel</h1>
</font>

グループの削除を行いましょう。<b>groupdel</b>を使用します。
nyanyaグループを削除します。

```
root      # groupdel nyanya
```
<b>groups</b>コマンドで確認しましょう。
プライマリーグループを削除する事は出来ないので、注意してください。グループに所属していないユーザーが生まれてしまう可能性があります。

以上、、

<ul>
　　<font color=red>
　　<li>groups</li>
　　<li>groupadd</li>
　　<li>usermod</li>
　　<li>groupdel</li>
    </font>
</ul>

<p>
<p>

グループについてでした。

次へ→<a href="https://qiita.com/larcmiya/items/16a0130143555938a6a3">ファイル・ディレクトリについて</a>
WSL2をバックエンドとしたDocker DesktopのマウントディレクトリがWindowsTerminalにおいておかしくなる問題（2020/08/29時点で未解決？）


# 問題点

"`/tmp/docker-desktop/shadowing-mounts/qwertyu123456xxxxxx/mnt/c/Users/`" みたいなマウントが起こり非常に不便．なぜかデフォルトのLinuxアプリケーションの方を開くときは問題ないので，なにか不具合があるのは `Windows terminal` かあるいは `Docker Desktop` 側であると推測できるが……？

# 調査

[とりあえず「`shadowing-mounts`」で調べる](https://www.google.com/search?q=%22shadowing-mounts%22&safe=active&sxsrf=ALeKk01wN1nZ4qPdahP3EEuo7AYPqCNl_Q:1598685535914&source=lnt&tbs=qdr:m&sa=X&ved=2ahUKEwjq1ubb77_rAhVRPnAKHTp1BDwQpwV6BAgLEB8&biw=1536&bih=760)と，次のようなページが出てくる．

- [WSL2: An error occurred mounting one of your file systems · Issue #5804 · microsoft/WSL](https://github.com/microsoft/WSL/issues/5804)
- [ERROR: Couldn't connect to Docker daemon at http+docker://localhost - is it running? · Issue #8164 · docker/for-win](https://github.com/docker/for-win/issues/8164)
- [docker desktop - WSL2 Prompt contains extended WSL path? - Stack Overflow](https://stackoverflow.com/questions/63589239/wsl2-prompt-contains-extended-wsl-path)


# 解決方法

現状，再現性があやふやな部分も多く，何をどうすればいいか公式の回答はないっぽい．（参照：2020/08/29）

とりあえず解決すると報告されている方法の一つは**「WSLを再起動すること」**であるらしい．これはOS本体を再起動することとは別であることに注意されたい．私も一旦Linux Subsystemを停止し，再度起動することで元通りになった（が，きっとすぐ同様の症状に陥る気がする）

以下の手順でWSL単体を停止→再起動する．

```cmd.exe

1. > net stop LxssManager   # 停止
2. > net start LxssManager  # 起動
```

これで一旦はマウントディレクトリが元通りになるはず．ならない場合は公式の回答を待つのが最善策なように思う．（もし原因解明や再現性が報告できる場合はGithubのIssueへGO～～）

# 参考文献

- [WSL を再起動するには: パソコン鳥のブログ](https://vogel.at.webry.info/201907/article_4.html)

## [おまけ] LxssManagerとはなんぞやという方へ

- [【Windows 10】 LxssManager サービス起動の必要性 | 個人PCの性能とセキュリティ向上](http://tooljp.com/Windows10/doc/Service/LxssManager.html)
- [ASCII.jp：Windows Subsystem for Linuxの起動とバックグラウンドタスク](https://ascii.jp/elem/000/001/620/1620316/)
非root権限でwgetを用いてソースからgitをLinux環境に導入する

## 始めに

brew install, apt-get, yum 等のパッケージ管理システムが権限の都合（非root権限）で使えない場合のgit導入方法です。共有計算機には予めgitが入っていることもありますが、`git version 1.7.1`だったので`git version 2.8.1`を入れてみました。（これでも新しくはない）

####実行環境

* Red Hat Enterprise Linux Server release 6.3 (Santiago)


## 手順

先に、自分の権限が及ぶインストール先のディレクトリを作っておきます。例えばsshでログインした場所が`/home/YOUR_NAME`である場合、

```
$ mkdir /home/YOUR_NAME/local
```
といった形で自分専用のlocalディレクトリを作っておきます。このディレクトリの名前や場所は、自分のホームディレクトリ以下であればどこでも良いです。

gitのインストールは以下の通り進めます。バージョンは適宜変更して下さい。

```
$ wget https://www.kernel.org/pub/software/scm/git/git-2.8.1.tar.gz --no-check-certificate
$ tar zxvf git-2.8.1.tar.gz
$ cd git-2.8.1
$ ./configure --prefix=/home/YOUR_NAME/local NO_OPENSSL=1 NO_CURL=1
$ make ; make install
```
最後に、`git`とコマンドを打った時にサーバーに予めインストールされている古いgitが使われないように、PATHを書き足します。（.bashrcに書く）

```bash:~/.bashrc
export PATH=/home/YOUR_NAME/local/bin:$PATH
```
```
$ source ~/.bashrc
```

以上です。


#### 参考
* http://matsuhon.hateblo.jp/entry/2014/06/24/193709
XSLTはフロントエンド技術の完成の最後にして最大のピースになる

XSLTはXML（XSLT3.0の現在ではJSONも含む）の変換を記述する技術だ。
だが、この技術は1999年の登場から3.0まで進化したが現状ではあまり注目されていない。
しかし、私はこの技術がフロントエンドの最後の主要技術になり、これをもってフロントエンドの技術が完成すると考えている。この記事ではその理由について書く。

#フロントエンド
まずはフロントエンドの話をしよう。
HTML、CSS、JavaScriptがありそれぞれ変化を遂げてきた。特にCSS、JavaScriptでは画期的なフレームワークの登場が開発の進歩をもたらした。

```html:フレームワークの使用
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<link rel="stylesheet" href="https://www.jsdelivr.com/package/npm/bulma">
(somecode)
</head>
<body>(somecode)</body>
</html>
```

これらのコードは現在ではあまりに見慣れたものだろう。
#ブラウザの挙動
その前にブラウザの挙動をまとめてみよう。現在のよく知られた技術なら大まかにこうなる。

1. 指定されたURLのサーバからファイルをダウンロード
2. ダウンロードしたものがHTMLならエンジンで解析
3. CSSやJavaScriptのダウンロード
4. レンダリング
5. JavaScriptの実行など

#XSLT
そして、これ以外にもあまり知られていないフロントエンドの技術がある。それがXSLTの適用テクニックである。
XSLTはXMLにとある記述をすることで、それがブラウザから読み込まれた時に変換を行うようXSLTプロセッサに指令を出せる。

```xml:XSLTの呼出し
<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type="application/xml" href="framexs.xsl"?>
<html xmlns="http://www.w3.org/1999/xhtml">
(somecode)
</html>
```

この記述によってブラウザはXMLをそのままパースするのではなく`framexs.xsl`によって変換された後の出力結果を内部で受け取り、それがHTMLであった場合などは必要に応じてパースやレンダリングをするようになる。
その流れを整理しよう。

1. 指定されたURLのサーバからファイルをダウンロード
2. ダウンロードしたものがXMLならエンジンで解析
3. XSLTを行うよう命令されていたならばXSLをダウンロード
4. XSLT処理を行う
5. 出力先のタイプがHTMLだとしたらHTMLとして解析
6. CSSやJavaScriptのダウンロード
7. レンダリング
8. JavaScriptの実行など

#framexs
この仕組みを利用して構成を記述したXHTMLとモデルとなるXHTMLを合成してHTMLを出力するフレームワークがある。
それが私が開発した[framexs](https://github.com/nandaka-furari/framexs)だ。
このフレームワークはまるでMVCアーキテクチャのようにHTMLを生成する。
詳しくは[HTML5はXHTMLで楽に書ける？XSLTによるMVCライクなフレームワーク framexs を開発したので解説するよ](https://qiita.com/nandaka_furari/items/80528c0882479c059f96)で書いているので参照されたい。

#終わりに
現在のフロントエンドは開発が急速に進むとともに混迷の度合いを深めている。そして、XSLTは今までフロントエンドの技術としてほとんど注目を浴びることはなかった。
しかし、framexsの登場と開発によってそれも変わっていくと私は期待している。
UIButtonのisEnabledの切り替え

#UIButtonのisEnabledの切り替えをする

条件を満たしていないときにボタンが押せない、みたいな処理の切り替えをしたい時は

isEnabled

```ruby:viewController.swift
class ViewController: UIViewController {
 
    @IBOutlet weak var button: UIButton!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        button.isEnabled = true // ボタン有効
        button.isEnabled = false // ボタン無効
    }
}
```

こうすればアクションを制限できます。
【AWS EC2】多段sshでssh_exchange_identificationエラーでログインできないとき

# AWS EC2で踏み台サーバーを介して多段SSHでログインしようとした際に`ssh_exchange_identification: Connection closed by remote host`と表示される

先日、普段使っているPCとは別のマシンで多段SSHをしようとしたところ、`ssh_exchange_identification: Connection closed by remote host`というエラーが表示されて、ログインできないというトラブルが発生。
（多段SSHの設定は`./ssh/config`に書いてある）

```bash
# ホスト名をprod-serverとしているとする
# 踏み台サーバーを介してログインしようとする
$ ssh prod-server

# ログインできない
# => ssh_exchange_identification: Connection closed by remote host

```

## 踏み台サーバーの`known_hosts`を消してみる
設定ファイルを確認してみたものの、ログイン対象インスタンスのパブリックIPは合っており、特に間違いもなかった。
そこで色々調べて、`.ssh/`以下の`known_hosts`を削除してみたもののエラーが解決されない。

```bash
# ホスト名をbastion-serverとしているとする
$ ssh bastion-server

# 踏み台サーバーにはログインできる。`known_hosts`を削除
ubuntu@ip-xxx-xx-x-xxx:~$ rm ~/.ssh/known_hosts
```

多段SSHしているので、踏み台サーバーの`./ssh/known_hosts`も削除してみたらと思いついて、消してみたところ正常にログインできるようになった。

これを機にちゃんとSSHと関連知識を身につけたいなと思いました。
STM32CubeIDEでWatchDog Timerを有効にしたソースをデバッグする

# はじめに
WatchDog Timerを有効にしているとデバッグ実行時にリセットが掛かってしまいます。
これを避けるにはDebugビルドではWatchDog Timerを無効にする方法も有りますが、STM32CUbeIDEにもWatchDog Timerを有効にしたままデバッグ実行可能にする方法が有ります。

# 設定方法
デバッグの構成から、[Suspend watchdog counters while halted]を「使用可能にする」に設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120192/860aa685-28b3-15b2-1226-d1ee158577ac.png)
React + TypeScriptでdiv要素でkeydownイベントを使いたい時

# はじめに
inputとかtextareaでのkeydownの扱い方の記事はあるけど、
div要素の場合がなかったので、記事を書いてみました。

input, textareaなどでのkeydownの使い方はこちらです。
↓
https://blog.zatsuzen.com/react/keypress/
https://masarufuruya.hatenadiary.jp/entry/2017/09/06/200551
# 前提
react@16.13.1
typescript@3.9.5
# 概要

keydownイベントをdiv要素に対して使うのは調べてみると簡単で、
componentDidMountにaddEventListenerで、keydownをListenしてあげるだけです。

componenｔWillUnmountでListenを解除してあげるのを忘れないようにしましょう。

# 実際のコード
```tsx
type Props = {
  // Propsの型を定義
  isHoge: boolean;
}

class CompanyProfile extends React.Component<Props> {
  componentDidMount() {
    document.addEventListener(
      "keydown",
      this.handleKeyDown,
    );
  }
  // removeEventListenerを使って解除するのを忘れない
  componentWillUnmount() {
     document.removeEventListener(
       "keydown",
       this.handleKeyDown,
     );
  }

  private handleKeyDown = (e: KeyboardEvent) => {
    // たとえば、キーボードの左右キーでしたい時
    switch (e.key) {
      case "Left": // IE/Edge specific value
      case "ArrowLeft":
        this.keyboardRight();
        break;
      case "Right": // IE/Edge specific value
      case "ArrowRight":
        this.keyboardLeft();
        break;
    }
  };

  private keyboardRight = () => {
    //なにかやりたい処理
    console.log("キーボードの右矢印が打鍵されました。"）;
  };

　private left = () => {
    //なにかやりたい処理
    console.log("キーボードの左矢印が打鍵されました。"）;
  };
```

# Tips
自分がハマったのは、親のComponentからPropsに親のComponentのstateを変更するfunctionを渡していたのですが、
親のstateを変更すると、componentDidMountが走り、
keydownのイベントが発火してしまい、意図しないタイミングで、handleKeyDownのメソッドが発動してしまって苦戦していました。

解決策としては、keydownを使いたいComponentの親Componentのstateやpropsの変更をなくして、
componentDidMountが走らないようにしました。

React hookならuseEffectの第2引数で副作用の適用をスキップできるので、うまくいきそうな気がします。。。

# 最後に
いかがだったでしょうか？
何か間違ってるとかあれば意見を気軽にいただけますと幸いです。

# 参考

https://stackoverflow.com/questions/43503964/onkeydown-event-not-working-on-divs-in-react
https://ja.reactjs.org/docs/hooks-intro.html
https://developer.mozilla.org/ja/docs/Web/API/EventTarget/addEventListener
https://developer.mozilla.org/ja/docs/Web/API/Document/keydown_event
テキストファイルの任意の文字列以降の行をすべて出力したい

以下のようなテキストファイルに対して、任意の文字列以降の行をすべて出力したい

```txt:qiita.txt
aaa
bbb
ccc
ddd
eee
fff
ggg
```

例えば、"ccc" 以降を抽出したい場合は以下のようにgrepをするととりあえず可能

```sh:test.sh
#!/bin/bash

STR="ccc"
grep -A 1000 $STR qiita.txt
```

上記の記載だと、テキストファイルが1000行を超えるとファイルの最後が出力されなくなるので、（当たり前ですが、、）
以下のようにsedを使うとよい。

```sh:test.sh
#!/bin/bash

STR="ccc"
cat qiita.txt | sed -n '/'$STR'/,$p'
```

結果は以下の通りになる

```
$ bash test.sh
ccc
ddd
eee
fff
ggg
```

# 参考
[sedコマンドの条件式に変数を使う場合に注意すること](https://hacknote.jp/archives/32540/)
[今日のsed: 任意の文字列以降の行をすべて出力したい](https://qiita.com/tohta/items/d779d29d035c1b4f9518)
Webページの画像を画面サイズに合わせて表示する方法

<h2>実現したい事</h2>

**・画像を歪ませることなくWEBページの幅に合わせて表示できるようにしたい!**

**画像の拡大表示**
![画像](https://i.gyazo.com/aef044b5b9123022f51ee8870eb3b72e.png　"フリー素材")

**画像の縮小表示**
![画像](https://i.gyazo.com/d1d39f27f7e86be9f26c8e4d4adfc815.png "フリー素材")

<h2>環境</h2>
**・Amazon Web Service
・Windows 10**


<h3>注意点</h3>

**・htmlとCSSの記述のルールや記述の仕方については知っていることを前提に進めますので
ご了承ください。**



<h3>解決手順</h3>

**①CSSに以下のコードを記述する**

```css_practice.css

img {
  
  max-width: 100%; /*この記述で画面幅の100%の幅で画像を表示する*/
  height: auto; /*高さはautoで画像の最適化表示*/
  
}
```

この記述によって画像の大きさをWEBページの幅に合わせて最適化することが可能になります。

<h3>ポイント</h3>

**・``max-width: 100%;``の記述によって画像の幅を親要素の100%の幅に合わせるという意味になります。そのため、画像の幅が画面内に収めることが可能になります。**

**・``height: auto;``の記述によって高さが画面の幅によって自動で調整されるようになります。そのため、画像の高さが調整されずに歪みを発生するなどの問題点を解消することが出来ます。**



<h3>参考サイト</h3>

**以下のサイトを参考にさせて頂きました。**

・[画像の大きさを最適化する](https://www.homepage-tukurikata.com/css/max-width.html)
【PHP】str_repeatで同じ文字列を繰り返す

### 環境
・ホストOS: Windows10 Home 
・ゲストOS: WSL Ubuntu20.04
・PHP7.4
・Laravel FrameWork 7.17.2


## 関数概要

**str_repeat(string, int)**とすると、stringがint個連結された文字列を返す。

使用例は以下の通り

```php

echo str_repeat('にゃーん', 3);
//実行結果
にゃーんにゃーんにゃーん
```


この関数がどんな時に使えるかというと、**境界値テストで文字数の多いプロパティを生成するときに便利** 。

例えば最大文字数を200文字のカラムのバリデーションテストをする場合、手動で入力すると文字数の把握が難しいうえ、毎回入力するのは時間がかかってめんどくさい。テストコードを書くにしても長い文字数を打ち込むことにはかわりない。

こういう問題を解決してくれるのがこの関数
任意の長さの文字列を生成できるので入力値の境界値テストを実施しやすい。

数百文字を直接打ち込む場合と比べてコードの可読性が高いので文字数の過不足によってテストが失敗にくいというメリットもある。

今後PHPでテストコードを書く時はこの関数を積極的に使っていきたい。
【Flutter】端末を横向きに固定する方法 



## 結論：以下のコードを記述

```dart:main.dart
void main() {
  WidgetsFlutterBinding.ensureInitialized(); // 向き指定より前に書かないと起動時にエラーが出る

  // 向きを横固定
  SystemChrome.setPreferredOrientations([
    DeviceOrientation.landscapeLeft,
    DeviceOrientation.landscapeRight,
  ]).then((_) {
    runApp(new MyApp());
  });
}
```
##コードの解説
### WidgetsFlutterBinding.ensureInitialized();
WidgetsFlutterBinding.ensureInitialized();は正確にはよくわかりませんが、WidgetsフレームワークをFlutterエンジンにいい感じに紐づけてくれるのでしょう。

### SystemChrome.setPreferredOrientations();
DeviceOrientationで端末の向きを指定します。

- portraitUp - 上向き
- landscapeLeft - 左向き
- landscapeRight - 右向き
- portraitDown - 下向き（逆さ）
 
縦の上向きに固定しないなら、
DeviceOrientation.portraitUp だけでOK。
【Flutter】SharedPreferencesの保存がうまくできないとき

##

SharedPreferencesの保存は成功していそうだけど、読み込みがうまくいかない…
そんな方は続きをご覧ください。

##結論
SharedPreferences.setMockInitialValues({});を追加していたら、削除しましょう。


```dart:main.dart
void main() {
  // SharedPreferences初期値
  // SharedPreferences.setMockInitialValues({}); // set initial values here if desired

   runApp(new MyApp());
  
}
```

SharedPreferences.setMockInitialValues({});は、SharedPreferencesのテストをする際、初期値を与えるために使用します。

```dart
SharedPreferences.setMockInitialValues({
  /* 初期値を記入 */
});
```
僕もやらかしたのは言わずもがな。

## なぜこんなミスが起きたのか

どこかのSharedPreferencesサンプルコードを理解しないでそのまま持ってくる
→SharedPreferences実装前に違う機能を実装
→追加したことを忘れる
→SharedPreferencesちゃんと動かん（そりゃそうだ）

理解しないまま引用するとこんなことになりますのでお気をつけください。
（それでも僕はまた繰り返すだろう）
アップロードした画像の即時プレビュー法



画像を選択し、画像をDBに登録する前にプレビュー表示する方法をまとめたいと思います。

[環境]
Rails 5.2.4.3
ruby 2.5.7
すぐにプレビューできるようにjQueryを追加
画像投稿用gemはRefile



![60CBE45F-331A-4C38-A395-39FE36F347A3_1_201_a.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684386/0fb4f9d3-6068-799d-226f-a9619efeec96.jpeg)


![スクリーンショット 2020-08-29 15.19.49.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684386/1c3d5293-d498-a420-fa54-46c249c650c8.jpeg)

![スクリーンショット 2020-08-29 15.19.52.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/684386/cc691d9a-2e83-b625-02bc-308372619f89.jpeg)


```ruby:new.html.erb
<%= form_for 使用しているモデル, url: パス名_path do |f| %>

    <%= attachment_image_tag 使用しているモデル, :image, :fill, 300, 300, fallback: "no-image.jpg", size: "300x300" %>

    <%= f.attachment_field :image, class: 'image-prev' %>

```

次にapp/assets/javascripts/application.jsに記述していきます。

```ruby:application.js
$(function(){
    $(document).on('change', '.image-prev', function (e) {
    var reader = new FileReader();
    reader.onload = function (e) {
        $(".image").attr('src', e.target.result);
    }
    reader.readAsDataURL(e.target.files[0]); 
});
});

```

クラス指定の場所に注意してください！！
私はこれで何時間もうまくいきませんでした！笑


メモ代わりに初投稿してみました。間違っているところやアドバイスなどあれば教えていただけると光栄です。お手柔らかに.....
Amazon CloudFront 概要

業務で少し触れるため、学習目的にCloud Frontの概要をまとめる。

## Cloud Frontとは

* ユーザーへ静的/動的ウェブコンテンツを配信するEdge サービス

* Edge Services
  * AWSのEdgeロケーションから提供されるサービス群(CloudFront,Route 53,...)
  * サービスへのアクセスを、ユーザーに近い場所から提供

![EdgeServices.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/6a45b610-4352-f232-43f1-b08ca0cf0c80.png)


### CloudFront利用の背景

#### インターネット経由アクセスにおけるネットワーク遅延

* 物理的、ネットワーク的な距離に応じて、ネットワーク遅延が発生(オリジンサーバーが遠いと、応答に時間がかかる)

#### ネットワーク遅延への対応

* ネットワーク遅延に対応するために、不要なトラフィックをオリジンサーバーに到達させない仕組みが必要
* Webコンテンツには、変化の少ない静的なデータが含まれる。それらを何度も取得させず、ネットワーク帯域・リソースの消費を削減



## CloudFrontによるContents Delivery Network(CDN)

* Contents Delivery Networkとは
  * 地理的に分散したエッジサーバー群からコンテンツをキャッシュしたり代理配信をするサービス

### CDNの利点

* ユーザーを近いエッジロケーションに誘導することで、コンテンツ配信を高速化可能
* エッジサーバーでコンテンツをキャッシュし、オリジンサーバーの負荷を軽減
![CDN.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/bf74c379-9fad-93ff-5df8-1659deb2fdcd.png)

#### よくある構成

![CDN導入.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/088aebd1-b3cb-a25e-872a-718e817d35a9.png)


### CroudFront　設定

1. オリジンサーバー設定
2. オリジンサーバーにコンテンツデプロイ
3. **CloudFrontディストリビューション**を作成
4. CloudFrontがドメイン名を割り当て
5. ディストリビューション構成をエッジロケーションに送信

##### CloudFrontディストリビューション

* ドメインごとのCloudFront設定
  * デフォルトでは「 xxxx.cloudfront.net 」が ディストリビューション のドメイン名とし
    て割り当てられる
    * CNAME エイリアスを利用して別ドメイン名の指定可能
* AWSコンソールもしくはAPIで作成
* 対応プロトコル：HTTP/1.0,HTTP/1.1,HTTP/2,WebSocket

### キャッシュコントロール

* URLと有効化したフォーワードオプションのパラメータの完全一致でキャッシュを再利用
  * 対応メソッド：GET / HEAD / OPTION
  * URLパス別にキャッシュ期間を指定可能であるなどきめ細かい設定が可能

### よくあるエラーページ設定構成

* クライアント要求エラーはオリジンサーバーから返却
* オリジン側エラー(障害時など)は、CloudFrontから返却

![CDN_500Error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/586535/ca70e653-3348-9e10-55d7-fda45647ea71.png)


### オリジンフェイルオーバー

* オリジングループを作成し、プライマリオ
  リジン・セカンダリオリジンを指定
* オリジンがフェイルオーバー用に設定した
  HTTP ステータスコードを返却した場合や接
  続タイムアウトした場合に別オ
  リジンにルーティング

## 参考

* [Amazon CloudFront とは](https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/Introduction.html)
* [[AWS Black Belt Online Seminar]Amazon Cloud Front ](https://d1.awsstatic.com/webinars/jp/pdf/services/20190730_AWS-BlackBelt_Amazon_CloudFront.pdf)
Arduino DueをつかってHID(Human Interface Device)機能をためしてみた

# はじめに
HID(Human Interface Device
> コンピュータの周辺機器・構成要素のうち、マンマシンインタフェースを担当するものの総称(例えば、キーボードやマウスなど)

です。
Arduinoの一部の製品では、そういったHIDをつかう機能が用意されています。
これを使うことで、Arduinoをキーボード入力で操作したり、Arduinoにつなげたボタンに何か文字を割り当てて入力するといったことができます。

Arduino Dueの情報があまりでてこないので、こちらに書き残しておきたいと思います。
Arduino DueはSRAMが64kBだったり(Arduino Unoは2kB)、GPIOピンが多かったりと、性能が良いので使いこなせるとものづくりの幅が広がりそうです。

# 対応しているマイコン
HIDに対応しているArduinoは

- Arduino Due
- Arduino Leonardo 
- Arduino pro micro

などがあります。

# Arduino Dueのプログラム
このプログラムではデジタルピンに3番につながれたタクトスイッチが押されたときに「a」という文字を入力するプログラムとなっています。[タクトスイッチはプルアップ抵抗をはさんでArduinoと接続しました。](http://zattouka.net/GarageHouse/micon/circuit/pullup.htm)
![arduinodue_button.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/c362aae3-a581-06d0-cb2e-4eb09aff7212.jpeg)


また、Arduinoにはプルアップ抵抗を接続しなくても「INPUT_PULLUP」を使うと、プルアップ抵抗を挟む必要はなくなります。

ちなみにですが、Arduino Dueのシリアル通信には「SerialUSB」を使用しています。
Arduino Unoと同じように「Serial」とするとシリアルモニタに表示されないので、慌てないようにしましょう(下記の画像のUSB CDC NAMEとDUEの欄より)。[こちらが参考になります。](https://www.arduino.cc/reference/en/language/functions/communication/serial/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212276/0715b157-3546-36b2-fc33-09fb1f9c6c71.png)


```c++
//HIDをつかうためにライブラリ
#include "Keyboard.h"

//デジタルピン3番にタクトボタンを繋いだ
const int inputPin = 3;

void setup() {
  //Arduino Dueのシリアル通信は「Serial USB」と表記
  SerialUSB.begin(115200);
  SerialUSB.println("Hello World");
  pinMode(inputPin,INPUT);
  Keyboard.begin();
}

void loop() {
  int currentState = digitalRead(inputPin);
  SerialUSB.println("This is loop");
  SerialUSB.println(currentState);
  if ( currentState == 1){
      //スイッチがおされたときに「a」という文字を送信する
      //
      SerialUSB.println("Push!");
      Keyboard.press( 0x61 );
  } else {
      SerialUSB.println("Release!");
      Keyboard.release( 0x61 );
  }

  delay(500);
}

```

# 動作確認
こちらを動かして、タクトスイッチを押すと「a」と入力されます。
HIDについてさらに理解を深めるには、[こちらも参考](https://qiita.com/MergeCells/items/17bdc1c1fb35949195b5)になります.
ブラウザのURLの解読からIPアドレスを取得するまで

#はじめに
この記事を書く目的は、自分がURLについて理解を深めることが目的です。なので、深くまで掘り下げることはせず、ブラウザがURLを解読してIPアドレスを取得するまでの流れをざっくりと見ていきます。

参考: [ネットワークはなぜつながるのか](https://www.amazon.co.jp/%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AF%E3%81%AA%E3%81%9C%E3%81%A4%E3%81%AA%E3%81%8C%E3%82%8B%E3%81%AE%E3%81%8B-%E7%AC%AC2%E7%89%88-%E7%9F%A5%E3%81%A3%E3%81%A6%E3%81%8A%E3%81%8D%E3%81%9F%E3%81%84TCP-IP%E3%80%81LAN%E3%80%81%E5%85%89%E3%83%95%E3%82%A1%E3%82%A4%E3%83%90%E3%81%AE%E5%9F%BA%E7%A4%8E%E7%9F%A5%E8%AD%98-%E6%88%B8%E6%A0%B9/dp/4822283119)
この本の第一章の一部を自分なりに解釈して説明していきますので、この記事の情報が絶対ではないことをご了承ください。

##ブラウザがURLを解読する
URLを解読する理由は、どこにアクセスすべきかを判明させるためです。具体的には、webサーバーのドメイン名とファイル名を判明させるためです。では、僕のホームページのURLを例に見ていきます。

http://www.kuhara-cookie.com/index.html

`http:`：プロトコル名
`www.kuhara-cookie.com`：webサーバのドメイン名
`index.html`：ファイル名

ざっくりですがこのような構造になっています。

`http:`はHTTPプロトコルを指しているのですが、HTTPプロトコルとは、Webサーバとクライアントが情報をやりとりする時に使われる通信手順です。僕の中の解釈では、目的地に行くためにバス、電車、タクシーのどの移動手段を使うかを決めている箇所だと考えています。

##HTTPリクエスト・メッセージを作成する。
このメッセージを作成する目的は、Webサーバにしてほしい動作を決めるためです。なので、リクエスト・メッセージには「何を」「どうして」ほしいのかが書かれています。

「何を」に当たるものがURI
「どうして」に当たるものがメソッド

URIはURLと同じようなものだと考えていても(たぶん)問題ないと思います。
参考:https://wa3.i-3-i.info/word1815.html

メソッドは、例えば、`GET`や`POST`などで、HTMLファイルの`form`タグの中に書くやつです。

##リクエストメッセージをOSに依頼する。
OSに依頼する理由は、ブラウザはURLの解読とHTTPのメッセージの作成の機能を持っていますが、メッセージを送信する機能は持っていないからです。しかし、これではまだメッセージを送信することはできません。なので、ここでWebサーバのドメイン名からIPアドレスを割り出す必要があります。ここからIPアドレスの取得方法を見ていきます。

IPアドレスを利用する理由は、ドメイン名を利用するよりもサーバーへの負荷が少なく、データを運ぶ効率がいいからです。

###リゾルバを利用して、DNSサーバに問い合わせる。

DNSサーバとは、ドメイン名とIPアドレスの翻訳機のような役割のシステムです。
リゾルバとは、**翻訳機(DNSサーバ)を利用してIPアドレスを知るために聞きに行ってくれるやつ**です。

IPアドレスを知るためには、担当のDNSサーバを探す必要があります。

担当のDNSサーバを探し出す方法は、手紙を順に見つ出していくゲームのようなイメージです。
僕のホームページのURLを例にすると、

PC
↓
最寄りのDNSサーバ
↓
ルートドメイン
↓
`com`のDNSサーバに手がかりを聞く
↓
`kuhara-cookie`のDNSサーバに手がかりを聞く
↓
担当のDNSサーバがIPアドレスを教えてくれる。


ざっくりとですがこのような仕組みになっています。

この方法により、IPアドレスを取得することができました。
これでOSに「割り出したIPアドレス先にメッセージを送って」と依頼することができます。

#最後に
これでもネットワークがつながる基礎知識の一部分みたいですが、理解するのにかなりの時間がかかりました。ですが、普段何も考えずに利用しているブラウザやネットワークの仕組みを知ることで、ネットワークの偉大さを感じることができました。

今後も少しずつ理解を進めていこうと思います。
UnityでAPI Levelあげようとしたけど、選択できずに困った時の話

# 前置き
- aa,,もうAPI levelをあげないといけない季節になったのか……
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/2a6d45f9-bb6f-ae05-fcac-a6a313f12af7.png)
- Unity上でAPIレベルを28から29に上げようとした時、ちょっとつまづいた時の話

# 環境
- Unity 2018.4.19f1

# 解決方法
## 結論
1. AndroidSDKをinstall
1. Unity上で`Target API Level`をAutomaticにする

## 手順
1. AndroidStudio起動
2. SDK Manager起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/c013ff2c-6101-43e1-8c72-a49112288a4a.png)
↓  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/3013fad4-a67d-2077-5c86-120aabce6200.png)
3. 欲しいAPI Levelのものをチェックして`OK`（スクショは既にinstallしてしまったjoutai）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/c197c941-cbb9-0fd7-86e0-fbaa2d7d71bd.png)

4. Unityに戻る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/3d6b4252-16e7-3fff-f2d1-44173795a04b.png)

5. あれれ～おかしいぞ～API level29と30がない……

6. とりあえず`Automatic (highest installed)`
（ここが知らなかったけど、勝手にinstall済のものからchoiceしてくれるらしい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/ca4ae94d-42ac-4925-1582-1183e3f27855.png)

7. build & upload
8. エラー出ずにuploadできた！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/87713/675f84ad-8517-596c-8d2e-0bfd4109176b.png)



# 参考
- [Unity Forum](https://forum.unity.com/threads/android-api-level-29.945251/)
放置してたGCPを復活させる（２）- VMインスタンス作成 -

GCP復活の作業履歴
[放置してたGCPを復活させる（１）- プロジェクト作成 -](https://qiita.com/3S_Laboo/items/62322280d1844d461bab)
[今回：放置してたGCPを復活させる（２）- VMインスタンス作成 -](https://qiita.com/3S_Laboo/items/03b54621479e193101f7)
[放置してたGCPを復活させる（３）- gcloud CLIインストール -](https://qiita.com/3S_Laboo/items/75682b3d008d0fdce355)
[放置してたGCPを復活させる（４）- PC(Windows10)からVMにssh接続 -](https://qiita.com/3S_Laboo/items/63a17738071a171decb1)
[放置してたGCPを復活させる（５）- VMのIPを固定する -](https://qiita.com/3S_Laboo/items/c897628aec6d04f4fe5f)
[放置してたGCPを復活させる（６）- nginxインストールとhttp設定 -](https://qiita.com/3S_Laboo/items/9a8446f84baa80252cb9)
[放置してたGCPを復活させる（終わり）- 独自ドメインの設定 -](https://qiita.com/3S_Laboo/items/cce944d49cbd1d4aa745)

今回は自分の城であるVMをGCPに立ててみます。

## まずは情報収集
以下を参考
[Linux VM の使用に関するクイックスタート](https://cloud.google.com/compute/docs/quickstart-linux?hl=ja)

ふむふむ。
なるほど！！よくわからん！！

とにかく実行じゃ！！

## Compute Engine ⇒ VMインスタンス
![2020-08-30_19h34_16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/dc7c57e8-e258-7162-49bc-420c1d95793b.jpeg)
![2020-08-29_14h49_12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/b2060440-6845-4eb7-9934-12b515ef9f52.jpeg)
作成！！

## なるべく無料がいいな。。。
作成ボタンクリック後以下の画面に
![2020-08-29_14h52_56.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/a91e6b86-445c-3c6f-bfa0-49832a9c908c.jpeg)
わりと予測金額が高い。。。
なるべく無料で行きたいな。

## 再び情報収集
[Google Cloud の無料枠](https://cloud.google.com/free/docs/gcp-free-tier?hl=ja)
[これから始めるGCP（GCE）　安全に無料枠を使い倒せ](https://qiita.com/Brutus/items/22dfd31a681b67837a74)
ふむふむ。。。

## インスタンスの修正
![2020-08-29_15h05_37.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/0089db09-f941-36df-2c91-3a6af355dd73.jpeg)
以下、デフォルト値より変更
リージョン:us-west1(オレゴン)／ゾーン:us-west1-a
マシンタイプ：f1-micro(1vCPU,614MBメモリ)
ブートディスク：
CentOS 6
30GBディスク
※OSは何となく

これでも5$くらいかかるようだが。。。
まぁいっか♪
とりあえず無料トライアルで様子見！！

作成！！
![2020-08-29_15h13_22.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/567235/20344513-bfa0-071e-0d41-319454723f4e.jpeg)

出来たー！！

あと、色々とやるようだが、とりあえず以上！

次からもろもろの設定やっていきましょう。

ありがとうございました。

次回
[放置してたGCPを復活させる（３）- gcloud CLIインストール - ※エラーも出ちゃったよ。](https://qiita.com/3S_Laboo/items/75682b3d008d0fdce355)
WSLのDistroの起動に失敗するとき（エラー："WslRegisterDistribution failed with error: 0x800706be."）

# 考えられる原因と対策
### 1. Windows Subsystem for Linux がオンになっていない
コントロールパネルから「プログラム」を選択し，「Windows の機能の有効化または無効化」を選択し再起動．
### 2. WSL がアップデートされていない
PowerShellを起動して`wsl --update`を実行

### 3. バグ
Windows Insider Program を利用している場合でも同様の症状はバグとして報告されている．もし，insider program の評価版を利用しており上記の解決策でうまくいかなければ以下のgithub の issues での解決策を実行してみるといいかもしれない．
[When installing a distribution the process fails with: "WslRegisterDistribution failed with error: 0x800706be. #5768
](https://github.com/microsoft/WSL/issues/5768)
リストを横並び表示にする

<h1>実現したい事</h1>
**・HTMLで作成したリストを横並び表示にしたい**

<h2>環境</h2>
**・Windows 10
・Amazon Web Service (Cloud9)**


<h3>手順</h3>
<h4>1-1</h4>
**・HTMLファイルでリストを作成する**

```html_practice.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>HTMLの練習</title>
  </head>
  <body>
      <ul>
        <li>リスト1</li>
        <li>リスト2</li>
        <li>リスト3</li>
        <li>リスト4</li>
      </ul>
  </body>
</html>
```
<h4>1-2</h4>
**上記の記述の状態でのリストの並び方の画像**

画像のように縦並びになっています。

![画像](https://i.gyazo.com/de2a0d65f822034e493563dbad678c1a.png "リストの縦並び画像")


<h4>2-1</h4>
**リストの横並び表示の実装**

**・HTMLにCSSファイルを読み込むコードを記述**

```html_practice.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <title>HTMLの練習</title>
    <!--これがCSSファイルを外部から読み込むための記述-->
    <link rel="stylesheet" href="css_practice.css">
  </head>
  <body>
      <ul>
        <li>リスト1</li>
        <li>リスト2</li>
        <li>リスト3</li>
        <li>リスト4</li>
      </ul>
  </body>
</html>
```

**・CSSファイルに以下のコードを記述**

```css_practice.css

li {
  
  display: inline-block;
  list-style: none;
  
}
```

**・CSS記述後のリストの変化**

下記の画像のように横並びになります。

![画像](https://i.gyazo.com/4e3e2bf3f5ca0df97afb2dd1e1a9d4d8.png "リストの横並びの画像")


<h1>その他</h1>

<h4>リストを横並びにして中央寄せにしたい場合</h4>

**・CSSに以下のコードを記述する**

```css_practice.css

/*親要素であるulにリストを中央寄せにするコードを記述*/
ul {
  
  text-align: center;
  
}

li {
  
  display: inline-block;
  list-style: none;
  
}

```

**・CSSにコードを追加後の変化**

このように左寄せから中央寄せにすることが出来ます。

![画像](https://i.gyazo.com/cff5e38f2235fc4e5bd6c80da0f067d5.png)
ボタンを押すとHTML要素を追加する

HTML

```html

<body>
  <button id="btn">追加</button>
  <ul id= "list"></ul>
</body>  

</body>
```
JavaScript

```javascript

<script>
  //ここにjavascriptコードを記載
  const list = document.getElementById('list');
  const btn = document.getElementById('btn');
  
  btn.addEventListener('click', () => {
  
  //li要素を生成する
  const li = document.createElement('li');
    //li要素にテキストを追加する
  li.textContent = 'これはリスト要素です';
    //li要素をul要素内に追加して表示する
  list.appendChild(li);
    
  })
</script>
```
heroku:docker:デプロイ

```.bash:terminal
cd some-app

# herokuアカウントにログイン
heroku login

# アカウント内に新しいアプリを作成
# ※すでにherokuアカウントにアプリがある場合は、heroku git:remote -a some-app
heroku create some-app

# herokuのアプリに、Docker image をデプロイ
heroku container:login
heroku container:push web # 名前は、webで固定
heroku container:release web
```

- docker-composeで動くアプリは非対応

- heroku は、 port の設定が特殊なので注意。3000や8080では動かない

```.Dockerfile:Dockerfile
# 3000では動かない
CMD npx next start -p 3000

# $PORTに変える必要がある
# herokuが、$PORTという環境変数に、利用可能なポートの一覧からランダムな値をセットする
CMD npx next start -p $PORT
```
mapはよくわからないけど、list(map(int, input().split()))だけ理解する

#プロローグ
mapはよくわからないけど、よく目にするlist(map(int, input().split()))だけ理解するゾ

#list(map(int, input().split()))の動き
とりあえず動かしてみるとわかりますが、複数の数字の入力から数値のリストを作成します。

```python
>>> list(map(int, input().split()))
1 2 3
[1, 2, 3]
>>>
```

#分解して理解する
##input().split()について
input().split()はインプットの文字列を分割します。

```python
>>> input().split()
ホップ ステップ ジャンプ
['ホップ', 'ステップ', 'ジャンプ']
```

#map(int, input().split())について
mapは第一引数を第二引数に適用して、mapオブジェクトを返すらしい。
なので、戻りは、よくわからないmapオブジェクト

```python
>>> map(int, input().split())
ホップ ステップ ジャンプ
<map object at 0x00000144D6B62388>
```

##list(map(int, input().split()))について
mapオブジェクトで得たものをlistに変換しています。

```python
>>> list(map(int, input().split()))
ホップ ステップ ジャンプ
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: 'ホップ'
```

当然、intを得てリストを返すつもりなのでエラーとなっている。
数値を与えると、冒頭の通り、リストを得られる

```python
>>> list(map(int, input().split()))
99 98 97 96 95
[99, 98, 97, 96, 95]
```

#エピローグ
mapはよくわかってないけど、list(map(int, input().split()))の動きだけ理解できた
Tableauの入力となるExcelのセルをAlteryxで補完する

#結合されたセルまたは空白のセル
人間が見る前提のExcelファイルを入力としてTableauで可視化する場合、結合されたセルや空白のセルが問題となります。
たとえば住所でしたら、都道府県、市区町村、町名以下というカラムに分け、同一の都道府県・市区町村は結合したり、最初の1行にだけ記入して2行め以降は空白にしたりということがよく行われます。
![政令指定都市.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/b20452c8-e16a-782d-6065-3b8de791164b.png)
* [http://www.tt.rim.or.jp/~ishato/tiri/cities/seirei.htm](http://www.tt.rim.or.jp/~ishato/tiri/cities/seirei.htm)より作成
こうしたワークシートの場合、空欄になっているセルを適切に補完しないとTableauでうまく扱うことができません。

#多数のワークシートを扱う
対象となるワークシートがひとつだけでしたら、Excelの関数を使ったり、Tableau Excelアドインを使ったりすれば空欄を補完することができます。
しかしいずれも手作業が必要なので、補完すべきワークシートが多数ある場合や、頻繁にワークシートが更新される場合には現実的ではありません。もちろん、ワークブック（ファイル）が多数ある場合も同様です。

#Alteryxの「複数行フォーミュラ」ツールを使う
「複数行フォーミュラ」ツールでは、ちょうど数学の漸化式のように式を設定します。
![ワークフロー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/b53a14eb-f415-4b42-d749-2856e884c283.png)
複数行フォーミュラ「都道府県の補完」の入力では、「都道府県」「市」とも最初のレコードしか設定されていません。
![都道府県の補完_入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/5ff22477-1c18-4e4d-5598-0094dc847974.png)
現在の行のフィールドで「都道府県」フィールドがNULLであれば、前の行の値を設定します。
![都道府県の補完.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/96f60838-9adc-a2f9-22f6-09c594c24b18.png)
「都道府県の補完」の出力では、「都道府県」フィールドが補完されています。
![都道府県の補完_出力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/a464d505-ea90-8924-ebd8-2e0b7f994441.png)
複数行フォーミュラ「市の補完」も同様です。
ワークフローの実行結果として「都道府県」「市」が補完されていることが分かります。
![実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/620713/740ab677-cc12-640d-8968-9f35213b6abb.png)

ワークシートがひとつだけだとあまりありがたみがわからないかもしれませんが、ワークブック、ワークシートが多数あるときには、こうした補完を行なうワークフローのありがたみが実感できます。
C/C++ 多倍長(高精度)演算ライブラリのメモ  

## 背景

* 高精度な数値計算が必要
* C++ でやりたい(Fotran は使わない)
* Windows, macOS, Linux などクロスプラットホームで動く
  * 速度はそんなに気にしない. 
  * ついでに Android/iOS でも動けば会計アプリとか作れてよい.
* 自前アプリに組み込みたいので, non GPL なのがほしい
  * LGPL は OK ではあるが, できれば BSD, MIT な感じのがほしい
  
## MPFR, gmp

各所で使われているライブラリです. LGPL なのと, 古きつらき configure しか無いのと Windows でぺろっとビルドできない(頑張ればできるだろうがめんどい)のが欠点です.

https://www.mpfr.org/

# ARPREC

https://indico.cern.ch/event/34666/contributions/813566/attachments/683847/939345/dhb-hp-physics.pdf

https://www.davidhbailey.com/dhbsoftware/


modified BSD ライセンスです. これも古きつらき configure ですが, コードはポータブルっぽいので CMake とかで `*.cc` 追加すればビルドできそうな雰囲気あります.

どの程度開発が続いているのかは不明です.

ARPREC を自前アプリに組み込んで配布したい場合は, License agreement を結ぶ必要がありそうです.

## mpdecimal

十進多倍長演算ライブラリです.

http://www.bytereef.org/mpdecimal/

10 進は, 主にお金の計算とかに有用かと思いますが, 10 進数値データを読み書きして計算とかにも役立ちそうです(e.g. CSV 数値データとか)

Python 3.3 からの decimal module のベースとなっています.
したがって C/C++ 版も Python decimal module と概ね同じふるまいをするのが期待されます.
ライセンスは simplified BSD です.

## libbf

https://bellard.org/libbf/

２進(IEEE754)と 10 進の両方をサポートしています.

embed しやすいです(ファイル数は 4 個). MIT ライセンスでよい.

ただ, ユーティリティ関数のコード(cutils.h, cutils.c)は gcc 拡張が使われているので, MSVC ですと少し改修がいります.

### ベンチマーク

![Screenshot from 2020-08-29 15-11-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/3fcc3dfe-ca90-2aab-7aed-9b21fd867d27.png)

ns/limb なので値が低いほうが高速... のはずです.

100 ~ 500 桁くらいですと, MPFR は x1.5 ~ x2.0 程度の高速化にとどまります.
(Threadripper 1950X で計測. AVX2 有効. AVX2 off だと 10~20% 遅くなる感じ)

桁が小さい時に MPFR が早いのはなにか ASM or SIMD とかで最適化しているのですかね.
桁が大きくなると, MPRT では FFT で高速化しているからか開きは大きくなります.
 
## QD

10 進で 100 桁くらいだと QD のほうが性能よいらしい.
(ARPREC と同じところ)

https://www.davidhbailey.com/dhbsoftware/

こちらもライセンスは, 独自の修正 BSD.

## GPU で高速化?

ちょっと古いですが gpuprec ありました.

https://github.com/lumianph/gpuprec


## まとめ

C++ で自前アプリに embed したいですと libbf, mpdecimal が候補でしょうか.

## その他

mpfr のサイトにまとまっています.

https://www.mpfr.org

## 参考文献

* 多倍長精度数値計算 GNU MP，MPFR，QDによるプログラミング
  * https://www.morikita.co.jp/books/book/3393

## TODO

* [ ] 自前でナウでヤングな多倍長演算ライブラリを作る(Cmake 対応).
拡張関数って、いつ使うの？（初心者向け）

# 自分が学んだときに思った疑問

- いつ使うのか？
- そもそも拡張関数って、 なんで必要なの？


業務上で使うことがあり、「あ、そのときに使うのか」といった**アハ体験**的なことを感じたので、
その体験を言語化（アウトプット）をするために投稿しました。

ではでは、早速・・・

## 拡張関数って何？（なぜ、必要なのか？）
- 既存のクラス（String, Int, 自分が作ったクラス)に対して、関数を追加することができる
- クラスの継承する必要がない。
- 新たなクラスを作成する必要がない

## いつ使うの?
- 標準クラスにない処理を作る場合



## 実装（コードで示すと・・・）

```kotlin

fun String.listSplitStr(): List<String>{
    return this.split("").filter { it != "" }
}

fun main(){
    val str = "アイウエオ"
    println(str.listSplitStr()) //-> [ア, イ, ウ, エ, オ]
}

```
新しい関数としての処理は、

- String型の値を一文字ずつに分割する処理（処理自体は、競技プログラミングで使われているかも！？）



## それで？？？（単純な関数にした方が楽ではないか？)

はい・・・・・。
実は、今回作った関数は、こうやって単純に新しい関数を作って行うことも可能なのです。

```kotlin

fun listSplitStr(str: String): List<String>{
    return str.split("").filter { it != "" }
}

fun main(){
    val str = "アイウエオ"
    println(listSplitStr(str)) //-> [ア, イ, ウ, エ, オ]
}

```

しかし、これでは、

1. 引数を必ず入れないといけない
3. 単純な関数なので、変数名（中身: List型、Map型など).メソッド名で**使うことができない**

※ 3に関しては、思わない人もいると思う。ドット`.`をつけられるだけだから

一回の処理、使われるクラスが少ない場合は良いが、何度も使用するとなると、**使いやすさ**に問題が出てきそうな感じがする

拡張関数を使えば、ドット`.`で書くこともできて、型が合えば、すぐにクラス関係なしに使うことができるので、利用しやすいと思えた。


## 何が「アハ体験」だったのか？

Kotlinの `data class` を使った拡張をした時に、ドット `.`で関数を呼ぶことができたことが、「アハ体験」でした。

今までは、拡張関数を使用せずにprivate関数を作ったりして、処理を作成していました。

```kotlin

data class Splitlist(
    val str: String
)

private fun listsplit(splitlist: Splitlist): List<String> {
    return splitlist.str.split("").filter { it != "" }
}

fun main(){
    val str = Splitlist("アイウエオ")
    println(listsplit(str))
}

```

しかし、拡張関数を利用することで、以下のような形にすることができます。

```kotlin
data class Splitlist(
    val str: String
)

fun Splitlist.listsplit(): List<String> {
    return this.str.split("").filter { it != "" }
}

fun main(){
    val str = Splitlist("アイウエオ")
    println(str.listsplit())
}

```

大きな違いはほとんどないですが、個人的には

- ドット `.`で処理を作成することができたのが、わかりやすい・見やすいと思えました。

## まとめ

- 「学んだが、どこで使えば良いのかわからない」ことを一つ、わかるようになり良かったと思えました。
- 実際の開発では、他の人や規則（ユーティリティクラスなど）があるので、これが良いとは言えませんが、使える知識が一つ増えたことで、使い分けをすることができるようになったのは,良かったことではないかなと思っております。（自己満足!!!:sunglasses:)
Gnu-COBOL プログラムの基本構造

```
*> コメント
*> 昔は大文字でしか記述できなかったが今は小文字もok
*> 文の最後は「.」
*> DIVISION > SECTION

*> 4つのDIVISION
*> 「見出し部」 → 「環境部」　→ 「データ部」 → 「手続き部」の順番で記述

*> 見出し部
IDENTIFICATION DIVISON.
PROGRAM-ID. HELLO.

*> 環境部
ENVIRONMENT DIVISION.

*> データ部
DATA DIVISION.

*> 手続き部
PROCEDURE DIVISION.

PROCEDURE DIVISION. *> コメント
  MAIN SECTION.
    DISPLAY 'hello world!'. *> DISPLAY -> 何かを表示する
    STOP RUN.               *> STOP RUN. -> 処理を止める

```

|DIVISION|記述|概要|
|---|---|---|
|**見出し部**|`IDENTIFICATION DIVISON.`|PROGRAM-ID.を記述<br>省略不可|
|**環境部**|`ENVIRONMENT DIVISION.`|実行環境、入出力ファイルの情報を記述<br>省略可|
|**データ部**|`DATA DIVISION.`|入出力ファイルの情報、変数の定義 <br> 省略可|
|**手続き部**|`PROCEDURE DIVISION.`|処理を記述。<br>`SECTION.`を作成しその下に処理を書く|
zoom oauth

zoom aouthで承認したユーザーidをゲット

```php:index.php
$Client_ID = '';
$Client_Secret = '';
$Redirect_URL = '';

if(isset($_GET['code'])){
	$basic = base64_encode($Client_ID.':'.$Client_Secret);

	$curl = curl_init();

	curl_setopt_array($curl, array(
		CURLOPT_URL => "https://zoom.us/oauth/token?grant_type=authorization_code&code={$_GET['code']}&redirect_uri=$Redirect_URL",
		CURLOPT_RETURNTRANSFER => true,
		CURLOPT_ENCODING => "",
		CURLOPT_MAXREDIRS => 10,
		CURLOPT_TIMEOUT => 30,
		CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
		CURLOPT_CUSTOMREQUEST => "POST",
		CURLOPT_HTTPHEADER => array(
			"authorization: Basic $basic"
		),
	));

	$response = curl_exec($curl);
	$err = curl_error($curl);

	curl_close($curl);

	if ($err) {
		echo "cURL Error #:" . $err;
	} else {
		// echo $response;
		$result = json_decode($response, true);
		$accessToken = $result["access_token"];
		// echo "<br>";
		echo $accessToken;
		

	}
}else{
	echo 'Authorization Error';
}

?>
<!DOCTYPE html>
<html lang="ja" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <a href="<?php echo 'https://zoom.us/oauth/authorize?response_type=code&client_id= &redirect_uri='; ?>">go</a>
<?php
if (isset($accessToken)) {
	$curl = curl_init();

	curl_setopt_array($curl, array(
	  CURLOPT_URL => "https://api.zoom.us/v2/users/me",
	  CURLOPT_RETURNTRANSFER => true,
	  CURLOPT_ENCODING => "",
	  CURLOPT_MAXREDIRS => 10,
	  CURLOPT_TIMEOUT => 30,
	  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
	  CURLOPT_CUSTOMREQUEST => "GET",
	  CURLOPT_HTTPHEADER => array(
	    "authorization: Bearer".$accessToken
	  ),
	));

	$response = curl_exec($curl);
	$err = curl_error($curl);

	curl_close($curl);

	if ($err) {
	  echo "cURL Error #:" . $err;
	} else {
	  echo $response;
	}
}
?>

  </body>
</html>

```
Ubuntu20.04LTSで使えるwordpressサーバー建て備忘録コマンド

全部rootとらないコマンドでやってます。sudoすりゃあええやん！精神

# とりあえず色んな自分の情報みたい
ローカルIPとかグローバルIPとかね。

```
hostname
ip addr show
cat /etc/os-release
hostname -I
curl ifconfig.me
curl -4 icanhazip.com
```

#バージョンアップ
OS入れて取り敢えずやりたい。やらないともどかしい。

```
sudo apt update
sudo apt upgrade
```

#PCの機能
レンタルサーバーあるある、dateでアメリカの時刻出てくる

```
シャットダウン
sudo shutdown -h now
再起動
sudo reboot

タイムゾーン変更
sudo timedatectl set-timezone Asia/Tokyo
date

root権限で対話式シェル
sudo -i
```

#VIMダウンロード
vimすら入ってなかった(´・ω・｀)

```
sudo apt-get install vim
```

#ufw（ファイヤウォール）を有効にして、ポート開放していく
自分が借りたレンタルサーバーは最初からiptablesが有効になってて、下のコマンドだとポート開放できなかった...。そういう時は直接iptablesいじるといいと思う...（本末転倒）

```
sudo apt-get install ufw
sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y
↑yした後、早急かつ慎重に、下のallow 22をする
sudo ufw status
sudo ufw allow 22
sudo ufw status
sudo ufw allow 80
sudo ufw reload
sudo ufw app list
↑のappリストからポート開放してもいいかもしれない。
```

#PHPインストール
バージョン気にしない人なら。気になる人はレポジトリ調べよう！

```
sudo apt install php
php -v
php -i | grep php.ini
sudo apt show php
```

#Apacheのインストール
Apacheはserviceからインストールする方法もあるよね...。

```
sudo apt install apache2
sudo systemctl enable apache2
sudo systemctl start apache2
sudo systemctl status apache2
sudo systemctl reload apache2
sudo systemctl restart apache2
```

#wordpressのインストール
やってることは、/var/www/htmlにzipダウンロードしてそのまま解凍して書き込み権限を与える。

```
cd /var/www/html
sudo wget https://ja.wordpress.org/latest-ja.tar.gz
sudo tar xvf latest-ja.tar.gz
sudo chown -R www-data:www-data 
```

#MariaDBのインストール
調べたところ、MariaDBはほぼ全く同じコマンドを使える高スペックMySQLならしい。

```
sudo apt install mariadb-server mariadb-client
sudo mysql
```

#mariaDBでデータベース作成
正直MySQLのコマンド環境によって通ったり通らなかったりするから、エラー出た時は下のコマンドだけじゃなくて、直接Google先生に聞いて試していった方がいいと思ってる。そもそもMySQL構文がムズカシイ...。（MySQLのパスは大文字１以上数字１以上記号１以上8文字以上じゃないとエラーがでる。）

```
sudo mysql
wordpressというデータベースを作る
mysql> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;
@の前にユーザー名、passwordにパスワードを入力
mysql> GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'password';
mysql> FLUSH PRIVILEGES;
```
<br>
今度またサーバー借りたらコピペだけでwordpress建ててやるんだ...！