OmniAICreator/Qiita-1.07M huggingface dataset:
初心者によるプログラミング学習ログ 317日目

#100日チャレンジの317日目
twitterの100日チャレンジ#タグ、#100DaysOfCode実施中です。
すでに100日超えましたが、継続。
100日チャレンジは、ぱぺまぺの中ではプログラミングに限らず継続学習のために使っています。
317日目は、

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">おはようございます<br>317日目 2h<br>・架空LP模写8日目1h（<a href="https://twitter.com/ririru_123?ref_src=twsrc%5Etfw">@ririru_123</a>）<br>・架空LP模写：制作一覧、スキル部分を作成<br>・ポートフォリオ作成 1h<br><br>寝落ちした<a href="https://twitter.com/hashtag/%E6%97%A9%E8%B5%B7%E3%81%8D%E3%83%81%E3%83%A3%E3%83%AC%E3%83%B3%E3%82%B8?src=hash&amp;ref_src=twsrc%5Etfw">#早起きチャレンジ</a><a href="https://twitter.com/hashtag/%E9%A7%86%E3%81%91%E5%87%BA%E3%81%97%E3%82%A8%E3%83%B3%E3%82%B8%E3%83%8B%E3%82%A2%E3%81%A8%E7%B9%8B%E3%81%8C%E3%82%8A%E3%81%9F%E3%81%84?src=hash&amp;ref_src=twsrc%5Etfw">#駆け出しエンジニアと繋がりたい</a><a href="https://twitter.com/hashtag/100DaysOfCode?src=hash&amp;ref_src=twsrc%5Etfw">#100DaysOfCode</a></p>&mdash; ぱぺまぺ@webエンジニアを目指したい社畜 (@yudapinokio) <a href="https://twitter.com/yudapinokio/status/1261386638334128133?ref_src=twsrc%5Etfw">May 15, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
CrystalでLLVMを扱ってみる (2)

第二回です！前回→https://qiita.com/flyingMaguro/items/61cef2973154e0fcd875

今回はハローワールドやってみます！
つまり外部の関数呼びます！
では早速

```Crystal:hello.cr
require "llvm"

ctx = LLVM::Context.new
mod = ctx.new_module "examples"
funcs = mod.functions

# i32 @puts(i8*)
f_puts = mod.functions.add("puts", [ctx.int8.pointer], ctx.int32)

# i32 @main()
f_main = mod.functions.add("main", ([] of LLVM::Type), ctx.void)
f_main.basic_blocks.append do |b|
  str = b.global_string_pointer "hello, world"
  b.call f_puts, str
  b.ret
end

# output ll
puts mod.to_s

ctx.finalize
```

```LLVM:出力
; ModuleID = 'examples'
source_filename = "examples"

@0 = private unnamed_addr constant [13 x i8] c"hello, world\00", align 1

declare i32 @puts(i8*)

define void @main() {
  %1 = call i32 @puts(i8* getelementptr inbounds ([13 x i8], [13 x i8]* @0, i32 0, i32 0))
  ret void
}
```

## 解説

今回は2つ関数を定義してます！ズバリ`main`と`puts`ですね！mainの方は中身を定義してて、putsはしてません！
こういうふうに中身を定義してないと自動でdeclareにしてくれます！プロトタイプ宣言みたいで便利ですね！

```Crystal
f_puts = mod.functions.add("puts", [ctx.int8.pointer], ctx.int32)
```

`ctx.int8.pointer`はCでいう`char *`のことです！型.pointerでポインタ型が取れるみたいですね！

```Crystal
  str = b.global_string_pointer "hello, world"
```

文字列を宣言してます！ブロックの中でやってますがglobal_と書いてあるとおり関数の外に宣言されます！

```Crystal
  b.call f_puts, str
```

さっきプロトタイプ宣言したputs関数を呼び出してます！strを渡してますね！

前回解説した分は省略です！

## 実行
今回はmainがあるので実行できます！やってみましょう！

```Bash
$ crystal run hello.cr | lli
hello, world
```

無事に出ましたね！

参考はこちらです！→https://www.ibm.com/developerworks/jp/opensource/library/os-createcompilerllvm1/index.html
#2_Raspberry Pi 3B+からLINEに天気予報を通知

#Raspberry Pi 3B+からLINE Notifyを使ってスマホに天気予報を通知

東京に来てから突発的な雨にうたれることが多くて
「朝ちゃんと天気予報をチェックしておけば...」と後悔することがしばしば。

LINEに毎朝天気予報が送られてくればいいんじゃない？と思い立って作ってみることにしました。

####1.下記のURLからLINE Notifyへ
https://notify-bot.line.me/ja/

####2.右上の「ログイン」ボタンをクリックしてLINEアカウントにログイン
![image5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/021ec82d-cd0f-7c99-8d30-9d9dad007f28.png)

####3.右上の自分のアカウント名の右矢印を押して「マイページ」をクリック
![image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/b165f07c-f1a3-0ca8-9a41-7bf42601909b.png)

####4.「トークン名を入力してください」の項目にどういう名前で通知が欲しいか入力。
　今回は「weather_report」としました。
　「通知を送信するトークルームを選択してください」の項目から自分のアカウントを選択
　最後に「発行する」をクリック
![image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/2522d882-810a-3a8c-2b1b-e8ca758a5771.png)

####5.「トークンを発行する」をクリック
![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/3042ad58-af73-47c0-bc8c-a0b52de55add.png)

####6.トークンが発行されるのでこれをコピーしてテキストエディタなどに控えておいてください
　もしコピーする前にダイアログを閉じてしまった！という場合は再度発行することができるのでご安心を
![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/ba4e08a9-5533-a047-614a-c320d975a016.png)

####7.プログラムを作成

8行目の
headers = {'Authorization': 'XXX',}
「XXX」の部分に先ほど発行したトークンを貼り付けます

```weather.py

#!/usr/bin/python
#coding: utf-8

import requests
import json

# 「XXX」には発行したLINE Notify トークンを貼り付ける 
headers = {'Authorization': 'Bearer XXX',}

def get_weather():
	url = 'http://weather.livedoor.com/forecast/webservice/json/v1'
	payload = {'city': '130010'}
	data = requests.get(url, params = payload).json()

	for weather in data['forecasts']:
		report = '\n' + data['title'] + '\n' + weather['dateLabel'] + ':' + weather['telop']
		files = {'message': (None, report),}
		response = requests.post('https://notify-api.line.me/api/notify', headers=headers, files=files)
		break

	return

if __name__ == '__main__':

	get_weather()



```

####8.プログラムを実行
![image6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/af2a6683-8b00-7d26-c68d-7b49a794d44c.png)

#### ☆天気予報の受け取り成功！(なんて時間にやってるんだ...)
![Screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308518/43155219-0dad-1f23-998e-8b5177e005e0.png)

16行目のreport変数の内容を書き換えれば天気予報に限らず色々なメッセージをLINEへ送信することができます。
1時間かからず実装できるのでお試しあれあられ。
[C#] overrideとnewの違い

（5/15追記：@shiracamusさんより指摘コメントあり、内容に間違いがあったため図解を差し替えています。）

overrideとnewの違いで少し混乱したためまとめ。
解説サイトはいくつもあるけれども、図解しているものがなかったため、図で考えてみた。
下記のような、BクラスがAクラスを継承している場合を考えてみる。

```csharp
    class A
    {
      public void Test_New() => Console.WriteLine("A::Test_New");
      public virtual void Test_Override() => Console.WriteLine("A::Test_Override");
    }
    class B : A
    {
      public new void Test_New() => Console.WriteLine("B::Test_New");
      public override void Test_Override() => Console.WriteLine("B::Test_Override");
    }
```

実行を以下の様に行なうと、

```csharp
      A a = new B();
      a.Test_New();
      a.Test_Override();

      B b = new B();
      b.Test_New();
      b.Test_Override();
```

結果は以下になる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114606/ae97ac42-57a7-c2c7-5354-2c96f87a2375.png)

つまり、図解（下記、@shiracamusさんのソースコードに基づいている）すると
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114606/489f17b5-be42-823f-1489-d4e75b21a011.png)

となる。
overrideの場合、派生元のメソッドを文字通り上書きしに行くので、イメージとしてはAとBが重なり合う感じ。
newの場合も、文字通り追加するので、イメージとしてはインスタンス内に二つのメソッドが存在する。
この場合、呼ばれるのは型による。
（A.Test_New()やB.Test_New()とすると、型によって呼ばれる先が異なるのはイメージできると思う）

また、@shiracamusさんのソースコードについて考えてみると

```csharp
class A
{
    public int value = 123;
    public void Test_New() {Console.WriteLine($"A::New : {value}");}
    public virtual void Test_Override() {Console.WriteLine($"A::Override : {value}");}
}

class B : A
{
    public new int value = 456;
    public new void Test_New() {Console.WriteLine($"B::New : {value}");}
    public override void Test_Override() {Console.WriteLine($"B::Override : {value}");}
}
```
について、図解の灰色の部分は呼ばれることはないので、

```csharp
        Console.WriteLine("A a = new B()");
        A a = new B();
        a.Test_New();
        a.Test_Override();
        ((B)a).Test_New(); // b.Test_New()と同等

        Console.WriteLine();

        Console.WriteLine("B b = new B()");
        B b = new B();
        b.Test_New();
        b.Test_Override();
        ((A)b).Test_New(); // a.Test_New()と同等
```
の結果は、@shiracamusさんの示された下記の通りになる。

```
A a = new B()
A::New : 123
B::Override : 456
B::New : 456

B b = new B()
B::New : 456
B::Override : 456
A::New : 123
```


表にすると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114606/1298bd3e-a848-a9ef-2148-1864488cce1b.png)
となる。
MiniMagick(imagemagick)で複数のフォントファイルを使って絵文字に対応する

ちょっと前にimagemagickで絵文字を含むテキストを合成する時に結構ハマったのでなんとなく備忘録を。
imagemagickはフォントが1つしか指定できないので、大抵の場合絵文字があると文字化けしてしまいます。
そこで、pangoを使って複数フォントに対応します。

(以下、dockerでrailsを動かす前提で進めます。)

## フォントを置く
まずは使いたいフォントをDLしてコンテナのfontsに置きます。
(apt-getで手に入るならそっちのほうがいいと思います)
今回はNoto Sans CJK JPとNoto Color EmojiをDLして/assets/fontsに置きました。

``` Dockerfile
# Dockerfile
COPY /assets/fonts /usr/share/fonts
```
#### memo: Noto Color Emojiについて
Noto Color Emojiは定番のフォントだと思いますが、入手先が3つあってそれぞれ対応しているUnicodeのバージョンが違います。
- 公式サイト → Unicode10
- apt-get → Unicode11
- Github → Unicode12(最新)
Github以外は更新が止まってるようなので、Unicodeが更新される度にGithubからDLして上書きする必要があります。

## フォントの設定を変える
Noto Color Emojiはビットマップフォントですが、設定によってはこれがデフォルトで無効になってることがあるので書き換えます。

``` Dockerfile
# Dockerfile
RUN rm /etc/fonts/conf.d/70-no-bitmaps.conf
RUN ln -s /etc/fonts/conf.avail/70-yes-bitmaps.conf /etc/fonts/conf.d/
```
ビットマップフォントを無効にする設定ファイルを消して、conf.availから有効にする設定をコピーしてます。

次にNoto Color Emojiの優先度を上げるため、設定ファイルを作って/etc/fonts/に置きます。(/usr/share/fontsではないので注意)

``` local.conf
<?xml version='1.0'?>
<!DOCTYPE fontconfig SYSTEM 'fonts.dtd'>
<fontconfig>
  <alias>
    <family>sans-serif</family>
    <prefer>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>
  <alias>
    <family>serif</family>
    <prefer>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>
  <alias>
    <family>monospace</family>
    <prefer>
      <family>Noto Color Emoji</family>
    </prefer>
  </alias>
</fontconfig>
```
``` Dockerfile
# Dockerfile
COPY /config/local.conf /etc/fonts/
RUN fc-cache -f
```
最後に念の為fc-cache -fでキャッシュを消して設定を読み込ませます。
これで、フォントの設定は完了です。

## pangoで画像を生成する
``` image.rb
MiniMagick::Tool::Convert.new do |convert|
  convert.size "600x200" 
  convert.pango("<span font='Noto Sans CJK JP' size='36864'>#{title}</span>")
  convert << "image.png"
end
```
2行目で指定したサイズに合わせてよしなに改行してくれます。
pangoはフォールバックフォントに対応しているので、Noto Sans CJK JPで表示できない文字が来た場合は先程設定したfontconfigに基づいてNoto Color Emojiで表示されるという仕組みです。
sizeはフォントサイズに1024掛けた数値を指定します。

pangoは他にも色々リッチなテキストを生成できるので、興味ある方は公式のdocを御覧ください。
https://www.imagemagick.org/Usage/text/#pango

## 絵文字がモノクロになる
出力された画像を見たら絵文字がモノクロだった…なんて時はOSのバージョンが古いかもです。
linuxの場合はUbuntu 18.04以降でないとカラーになりません。
自分はdebianのdockerコンテナ使ってたので、バージョンをbusterに変えて無事カラーになりました。

``` Dockerfile
# Dockerfile
FROM ruby:2.6.5-buster
```

## おわりに
こうしてまとめると大したことやってないですが、これに辿り着くまでにえらい時間かかりました…

あと例えば画像サイズに収まるように文字数をカウントしてトリミングしたい時は絵文字の扱いに注意が必要です。
サロゲートペアとか、肌の色を表す文字とか、複数の絵文字を合成してたりとか、ややこしい仕様が色々あります…
その辺の仕組みは↓の記事に詳しく書かれてます。
https://qiita.com/_sobataro/items/47989ee4b573e0c2adfc
https://tech.drecom.co.jp/count-length-of-string-including-pictogram/

絵文字、知れば知るほど難しい……:sob:
JUnitをつくってみる。

# 動機
「何かを勉強するには作ってみるのが良い」という言葉を聞いたことがあるでしょうか?  
業務でJUnitを利用することはあっても、具体的にどう作られているのかは知りませんでした。  
会社を辞めて転職活動中のため、時間があるので、実際に独自バージョンのJUnitを作ってみることにしました。

# 参考にするJUnitのバージョン
JUnitのソースコードを探したのですが、JUnit4とJUnit5しか見つかりませんでした。(公式以外なら、JUnit4とJUnit5以外にも存在します。)  
[JUnit4のソースコード](https://github.com/junit-team/junit4)の```junit4/src/main/java/```配下には2つのディレクトリが存在します。  

1. junit
1. org/junit

中をみてみると、どうも別々のソースが格納されているみたいです。  
とりあえず```junit```の方を参考にすることにしました。理由は下記の通りです。

1. Kent Beckの"Test Driven Development: By Example"に近い
1. コードがシンプル

# JUnitの大まかな流れ
## どのように調査したか
最初はjunitのソースを1つ1つ読んでいましたが、下記の理由で主要な流れを把握するだけにしました。

1. クラスの量がそこそこある。
1. クラスの関係を整理するために、ツールが欲しくなったがいいのがなかった。
1. ずっと読んでいるだけだとしんどい。

## JUnitの実行
JUnitは下記の流れで実行します。業務で使用する場合は、統合開発環境がよしなに実行してくれます。
詳細はJUnitの[公式ページ](https://junit.org/junit4/)でご確認ください。

1. テストクラスを作成する。
1. テストクラスをコンパイルする。
1. TestRunnerを実行する。

テストクラスの作成方法および、テストクラスのコンパイルの説明は省略します。

### TestRunnerを実行する。
下記のようなコマンドを実行します。
```
java -cp 必要なライブラリ テストを実行するクラス(JUnit3ならjunit.textui.TestRunner) テスト対象クラス
```
重要なことは、テストを実行するクラス及び、テスト対象クラスを指定していることです。

## JUnitの解析
JUnitはどのように処理を実行しているのでしょうか?  
何か特別な仕組みが存在するのでしょうか?  
結論から言うと、何か難しいことをしているわけではなくReflectionを使用しているだけです。

### エントリポイントをみてみる
テストを実行するクラスをしていることから、そのクラスがエントリポイントだとわかります。  
実際に```junit4/src/main/java/junit/textui/TestRunner.java```を見てみると```main()```メソッドが存在します。  
つまりjunitは単純に```main()```メソッドを読んでいるだけです。何か特別なことをしているわけではありません。  

### テストメソッドをどのように実行しているか
エントリポイントはわかりましたが、ではどのようにしてテストメソッドを実行しているのでしょうか?  
先ほどの```main()```メソッドからはいろいろメソッドが呼ばれていますが、実際にメソッドを実行しているのは下記となります。  
```
junit4/src/main/java/junit/framework/TestCase.javaのrunTest()メソッド
```
中身をみてみると```method.invoke()```しているだけです。(methodはMethod型)  
これはReflectionの機能です。

### Reflectionとは
Reflectionとは簡単に言うと、実行時にクラスやメソッドの情報を読み取ったり実行したりできる機能です。  
結構昔ですが、黒魔術として有名でした。  
Reflectionの長所は、柔軟にクラスやメソッドを操作できることです。  
短所は長所の裏返しです。  
実行時にJVMで情報を集めてくる必要があるため、実行速度が遅くなります。またprivateメソッドも実行できてしまうため、使用方法を間違えるとエラいことになります。

# 実装をしてみる
## クラス構成
上記でJUnitを作ってみるのに、最低限必要な知識は得られました。 
最低限の機能を実施するとして、必要なクラスを考えてみました。

- Assert(assertEqualsを提供する)
- TestResult(テスト結果を保持する)
- TestRunner(エントリポイント)
- TestCase(テストクラスのスーパークラス)

## コード
[GitHub](https://github.com/ToruTakefusa/MyJUnit)を参照してください。
なお現在は、クラス構成が多少異なります

# やってみてどうだったか
やってみてよかった点は下記の通りです。

1. クラス設計とか久しぶりで、頭の体操になった。
1. なんとなくコードリーティングするよりモチベーションが保ちやすい
astropy: fits file 


# astropy (天文系 Python package) でfitsファイルを open / save / add するやり方。


# Data input/output with astropy 

```python

#from astrolibpy.utils.idlsave import idlsave 

from astropy import table
from astropy.table import Table 
from astropy.table import Column
from astropy.io import fits

#####################
# method (1)
#####################

# read
table1 = Table.read('table1_old.fits')

# save 
data_  = [ table1['source_id'], table1['radial_velocity'] ]
names_ = ('source_id', 'radial_velocity')

dtype_ = ( 'i8', 'f8' )

table2 = Table(data_, 
               names=names_, 
               #meta={'name': 'first table'},
               dtype=dtype_)

table2.write('table2_new.fits', overwrite=True)

#####################
# method (2)
#####################

# read
hdu_list = fits.open('table1_old.fits', memmap=True)
data_input = hdu_list[1].data

# save
table2 = Table(data_input)
table2.write('table2_new.fits', overwrite=True)


```

`dtype` : ['f8', 'i4', 'S2' ] etc.

---

# Add line to fits file

```python

table2 = Table(data_input)
table2.write('table2_new.fits', overwrite=True)


col_G0 = Column(name='phot_g_mean_mag_0', data=G0)
col_bp0= Column(name='phot_bp_mean_mag_0',data=bp0)
col_rp0= Column(name='phot_rp_mean_mag_0',data=rp0)


table_2.add_columns([col_G0,
                     col_bp0,
                     col_rp0])

table_2.write('table_2_combined.fits', overwrite=True)


```

# Change column name

```python 
table3 = Table(data_input)
print(table3.columns)
# 
table3['E'].name = 'energy'

```
Gitでコミットしてバージョン管理・バックアップするメモ

Gitコミットして変更履歴を残す。
復元はまだやったことない。
GitHubへのプッシュは別記事。

##扱いたいディレクトリへ移動
コミットしたいファイルのあるフォルダへ。

```
$ ls 　　　　　   下の階層にある、cdで移動できるディレクトリを表示
$ cd ディレクトリ名  移動
```

##git init
初期化。Initialize.
それぞれのフォルダの中に.gitという隠しファイルを作る。
初めてそのファイルをgitで扱う時には必ず行う。
そうじゃなければ飛ばす。

```
$ git init
Initialized empty Git repository in /Users/ディレクトリの階層ズラズラ/.git/
```

##git add
ファイルを選択。

```
$ git add ファイル名
```


選択できたか確認。

```
 $ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
	new file:   index.html

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	../上の階層のファイル名やディレクトリ名
	同じ階層のaddしてないファイル名やディレクトリ名
```

選択できてない場合


```
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	../上の階層のファイル名やディレクトリ名
	./

nothing added to commit but untracked files present (use "git add" to track)
```

git initできてない場合

```
$ git status
fatal: not a git repository (or any of the parent directories): .git
```

##git commit
変更内容や何を作ったのかコメントにつけてコミットする。
これで.gitに今のファイルの状態が保存される。

```
% git commit -m "トップページ作成"                                       
[master (root-commit) b4a0bf4] トップページ作成
 1 file changed, 96 insertions(+)
 create mode 100644 templates/index.html
```

##コミット履歴を確認
commitできてるか確認

```
$ git log
commit コミットID (HEAD -> master)
Author: 自分の名前 <メールアドレス>
Date:   Sat May 16 01:46:18 2020 +0900

    トップページ作成

```
.gitのあるディレクトリ内でgit logすることで、今までにコミットした履歴を確認できる。

##コミットしたものから復元
参考：[[git] 戻したい時よく使っているコマンドまとめ](https://qiita.com/rch1223/items/9377446c3d010d91399b)

git logで戻りたいコミットのコミットIDを調べて

```
$ git reset --hard [コミットid]
```

直前のコミットに戻る時は

```
$ git reset HEAD^
```

resetで戻ったコミット以降のコミットたちは無くなる。

フォルダごとコミットしたけど特定のファイルだけ戻したい時は

```
$ git checkout [コミットid] [ファイルパス]
```

GitHubなどのリモート上にプッシュした後ならこうする
参考：[Gitでリモートリポジトリを巻き戻す](https://tmtms.hatenablog.com/entry/20101221/git)
<details><summary>手順</summary><div>
リモートに今の（間違えた）状態をバックアップしたブランチを作る
`git push origin master:master_bak`
リモートのmasterを削除し、ローカルを一つ戻し、リモートにプッシュ
`git push -f origin HEAD^:master`
分解するとこういうことしてるらしい
`git push origin :master`
`git reset HEAD^`
`git push origin master `
これで順調ならバックアップを削除
`git push origin :master_bak`
</div></details>

addやcommitの後はstatusやlogで確認する習慣を！
brew install yarn --ignore-dependenciesができなかった場合の対処

# 環境
macOS v10.15.4
nvm v0.35.3

# エラー
yarnの公式ページによると、nvm等でnode.jsのバージョン管理をしているMacにyarnを入れる時には、下のコマンドを打てばいいらしい。

```
$ brew install yarn --ignore-dependencies
```
しかしこのコマンドを打つと、以下のようなエラーが。
<img width="717" alt="スクリーンショット 2020-05-16 2.18.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/442538/a8771aae-04e8-9d82-24c1-ae4bd12552f7.png">

依存するファイルとしてnodeを入れろとのエラー。

せっかくnvmでnode.jsのバージョンを管理しているのに
homebrewで別にnode.jsを入れないといけないのか...

# 解決法
逆に考えるんだ。入れてしまってもいいさと。

yarnを依存関係含めて入れた後にhomebrewで入れたnodeだけを消してしまえばnvmでバージョン管理しているnodeを適切に使えるはず！

ということで、以下のコマンドを実行。

```
$ brew install yarn
$ brew uninstall node --ignore-dependencies
```

確認のためにnodeの$PATHを確認します。

```
$ which node
```

と打って

```
/User/<your-user-name>/.nvm/versions/node/<latest-node-lts-version>/bin/node
```
上のような出力が帰ってくれば、nvmのnodeが使える状態になっています。

# 参考
https://github.com/nijicha/install_nodejs_and_yarn_homebrew
`Enumerable#uniq?` を実装

`raise if ary.dup.uniq!` なんて書かれていたら、どんな動作をするのかすぐにはわからない。

## 動機
配列の要素に重複があるかどうか判定したい。

* [**`Array#uniq!`**](https://docs.ruby-lang.org/ja/latest/method/Array/i/uniq.html) というメソッドがある
	* レシーバーの配列から重複する要素を削除する
	* 重複する要素を削除しなかった場合は `nil` を返す ＝ 戻り値で「重複の有無」を判定できる
* これをそのまま条件式に使うのは気が引ける
	* 破壊的メソッドのため、事前に配列を複製しないといけない
		* また実際に重複を全排除するのは計算の無駄
	* 「重複の有無」と「戻り値の真偽」の関係がややこしい
	* **⇒ 真偽判定に特化したメソッド `#uniq?` を作ろう**
* さらに言えば Array でなくてもいい
	* ⇒ Enumerable に作ろう
	* ちなみに破壊的でないメソッド [`#uniq`](https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/uniq.html) は Enumerable などにもある


## 実装
`#uniq` 系は [`Object#eql?`](https://docs.ruby-lang.org/ja/latest/method/Object/i/eql=3f.html) の等価判定に基づいている。ということは重複の検知には **Hash のキー部分**を使えばいい。 [Set](https://docs.ruby-lang.org/ja/latest/class/Set.html) なら更に分かりやすいけれども、ライブラリをrequireしなければいけないので却下。

```ruby
module Enumerable
	def uniq?(&block)
		block ||= :itself.to_proc
		hash = Hash.new
		each do |item|
			key = block.call(item)
			return false if hash.key?(key)
			hash[key] = nil  # register a new key
		end
		true
	end
end
```

やっていて気付いたが、 [BasicObject](https://docs.ruby-lang.org/ja/latest/class/BasicObject.html) には `#eql?` や `#hash` が無いので、 Hash のキーにできないなど制約がある。組み込みの `#uniq` 系もエラーを起こすので、上の実装でも BasicObject を無視して [`Object#itself`](https://docs.ruby-lang.org/ja/latest/method/Object/i/itself.html) を使っている。

## 実験

```ruby
# `Array#uniq!` と同じ結果になること
chars = [*"a".."z"]
1000.times do
	ary = Array.new(6) { chars.sample }  # 5割前後の確率で重複あり
	expected_result = !ary.dup.uniq!
	raise "wrong implementation!" if ary.uniq? != expected_result
end
```

なお、今回実装した `#uniq?` は重複を検知した段階で処理を終えるので、ブロックが副作用を伴う場合は `#uniq!` と異なる動作になりうる。

```ruby
ary = [3, 1, 4, 1, 5, 9, 2, 6, 5, 3]
proc = method(:p).to_proc

p !ary.dup.uniq!(&proc)
p ary.uniq?(&proc)
```
CrystalでLLVMを扱ってみる (1)

こんにちわみなさん！
スクリプトとコンパイルが両方そなわり最強に見えるCrystalやってますか？！

## Crystal
CrystalはRubyみたいなのに、Cレベルに低水準な操作ができるというなんつーか最強と言うしかない言語です！
CrystalにはLLVMが使われていますが、セルフホスティングするためか標準でLLVMバインディングがついています。
これは使うっきゃないでしょって感じなので早速使ってみましょう！

## Ex1 和を出力する

### コード
```add.cr
require "llvm"

ctx = LLVM::Context.new
mod = ctx.new_module "examples"

# add(a, b : int32) : int32
func = mod.functions.add("add", [ctx.int32, ctx.int32], ctx.int32)
func.basic_blocks.append do |builder|
  params = func.params
  sum = builder.add params.unsafe_fetch(0), params.unsafe_fetch(1)
  builder.ret sum
end

# output ll
puts mod.to_s

ctx.finalize
```

```LLVM:出力
; ModuleID = 'examples'
source_filename = "examples"

define i32 @add(i32, i32) {
  %3 = add i32 %0, %1
  ret i32 %3
}
```

### 解説
それでは解説します！

```Crystal
require "llvm"

ctx = LLVM::Context.new
mod = ctx.new_module "examples"
```

↑おまじないです！（迫真）
多分moduleはコリジョンドメインのことだと思いますよ（？？？）！

```Crystal
func = mod.functions.add("add", [ctx.int32, ctx.int32], ctx.int32)
```

関数を作ってます！第2引数は引数の型、第3引数は返り値の型ですよ。

```Crystal
  sum = builder.add params.unsafe_fetch(0), params.unsafe_fetch(1)
```

引数同士の和を計算してます！`params.unsafe_fetch(n)`は`n`番目の引数を取得するメソッドです！！

```Crystal
  builder.ret sum
```

計算した和を返してます！簡単ですね！

```Crystal
puts mod.to_s
```

LLVMのコードに変換して出力してます！そのまんまですね！！
ファイルに出力するときは↓みたいにするといいみたいです！！！

```Crystal
begin
  mod.print_to_file("add.ll")
rescue
  puts "ファイルに出力できない！"
end
```

```Crystal
ctx.finalize
```

忘れないようにしましょう！moduleの方も自動でdisposeしてくれます！

## おわり
終わりです！次回をお楽しみに！

## 追伸
参考にしたのはこのページです！
https://8128.jp/notebooks/llvm-c-api
書くの忘れてましたごめんなさい！許してくださいなんでもしますから！
ECRスキャンをCDKから作成したらスキャンの裏側も見れたよ

# 初めに
ECRのスキャン機能使ったこと無かったので、CDKで作りました

# 作り方
下記のように、Repositoryの引数にimage_scan_on_pushを追加するだけで自動スキャン機能が使えます
CDK便利ー

```python
from aws_cdk import (
    aws_ecr as ecr,
    core,
)

repository = ecr.Repository(self, "Repo",
    image_scan_on_push=True
)
```

上記を実行すると、ECRとECRImageScanOnPushが出来ました

```bash
$ cdk diff repo
...
Resources
[+] AWS::ECR::Repository Repo Repo02AC86CF 
[+] Custom::ECRImageScanOnPush Repo/ImageScanOnPush/Resource RepoImageScanOnPush94CFD98F 
[+] AWS::IAM::Role AWS679f53fac002430cb0da5b7982bd2287/ServiceRole AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2 
[+] AWS::IAM::Policy AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/DefaultPolicy AWS679f53fac002430cb0da5b7982bd2287ServiceRoleDefaultPolicyD28E1A5E 
[+] AWS::Lambda::Function AWS679f53fac002430cb0da5b7982bd2287 AWS679f53fac002430cb0da5b7982bd22872D164C4C 
...
```

実際に出来ているかもCLIから確認してみると、確かに出来てることが確認できました
また、image scanの設定も入っていました

```bash
$ aws --region us-east-1 ecr describe-repositories | jq .
{
  "repositories": [
    {
      "repositoryArn": "arn:aws:ecr:us-east-1:000000000000:repository/repo-repo0-ny7qkwdk6aru",
      "registryId": "000000000000",
      "repositoryName": "repo-repo0-ny7qkwdk6aru",
      "repositoryUri": "000000000000.dkr.ecr.us-east-1.amazonaws.com/repo-repo0-ny7qkwdk6aru",
      "createdAt": 1589559800,
      "imageTagMutability": "MUTABLE",
      "imageScanningConfiguration": {
        "scanOnPush": true
      }
    }
  ]
}
```

# 余談
上記でやりたいことは完了したのですが、リソース作成時に下記のようにECR以外のものが出来ていました
こちらも出来ているか確認してみましょう

```bash
[+] AWS::IAM::Role AWS679f53fac002430cb0da5b7982bd2287/ServiceRole AWS679f53fac002430cb0da5b7982bd2287ServiceRoleC1EA0FF2 
[+] AWS::IAM::Policy AWS679f53fac002430cb0da5b7982bd2287/ServiceRole/DefaultPolicy AWS679f53fac002430cb0da5b7982bd2287ServiceRoleDefaultPolicyD28E1A5E 
[+] AWS::Lambda::Function AWS679f53fac002430cb0da5b7982bd2287 AWS679f53fac002430cb0da5b7982bd22872D164C4C 
```

まずはLambdaですが、AWSと書かれたリソースはありませんでした

```bash
$ aws --region us-east-1 lambda list-functions | jq .Functions[].FunctionName | grep AWS
$ 
```

次にIAM Roleですが、こちらもありません
なので、それに紐づくIAM Policyも見つかりませんでした

```bash
$ aws --region us-east-1 iam list-roles | jq .Roles[].RoleName | grep AWS679f53fac002430cb0da5b7982bd2287
$ 
```

つまり、ユーザ側で設定や確認できるリソースではなくAWS側のリソースが出ているのではないかと思います
おそらくECRのスキャンをする時のLambdaとそのIAM Roleになるのかなぁと思います
多分そのうち修正されると思うのですが、ちょっとAWSの内側を知れた気分でした

# 参考
- [イメージスキャン - Amazon ECR](https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/image-scanning.html)
- [【超待望アップデート】ECRに対する脆弱性スキャン機能が提供されました | Developers.IO](https://dev.classmethod.jp/articles/ecr-repository-scan/)
- [Amazon ECR Construct Library — AWS Cloud Development Kit 1.38.0 documentation](https://docs.aws.amazon.com/cdk/api/latest/python/aws_cdk.aws_ecr.README.html)
html&css markerで1.1や1.1.1などの目次を作る

##最近
極鶏のラーメンが食べたいです:ramen:
ついでに言うと猪一のラーメンも食べたいです:ramen:

##目次
- 目標
- HTML
- CSS

##目標
リストの入れ子で通常のリストだと↓階層がパッと理解しづらい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328604/86cb9f48-2139-4b9c-fbe4-ebc6748e8189.png)

↓こんな感じのリストを作る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328604/d2900fe1-9dff-d246-019d-c50159190f68.png)


##HTML
今回はolで括りましたがulでも大丈夫です。
olにそれぞれfirst second thirdなどの任意のクラスをつける。

```index.html
<ol class="first-layer">
    <li>1つ目の階層リスト－１</li>
    <li>1つ目の階層リスト－２</li>
    <ol class="second-layer">
      <li>２つ目の階層リスト－１</li>
      <li>２つ目の階層リスト－２</li>
      <ol class="third-layer">
        <li>３つ目の階層リスト－１</li>
      </ol>
    </ol>
    <li>1つ目の階層リスト－３</li>
    <ol class="second-layer">
      <li>２つ目の階層リスト－１</li>
      <ol class="third-layer">
        <li>３つ目の階層リスト－１</li>
        <li>３つ目の階層リスト－２</li>
      </ol>
      <li>２つ目の階層リスト－２</li>
    </ol>
  </ol>
```


##CSS
counterとmarkerを使い、作ります。

counter-resetはolが存在する度にcounter-resetで 加算していた num を0にする。
( num=0; )

``` .css
ol{
	counter-reset: num;
}
```

counter-incrementで num に加算していく。
リストがある度に1加算される。
( num++; num+=1; )

``` .css
li{
	counter-increment: num;
}
```
リストの後ろに marker でリストを作成。marker の content に num の数値を出力する。
( print(num) )

```.css
li:before{
	display: marker;
	content: counter(num_f)". ";
}
```

以上をまとめて...

``` style.css
li{
	list-style-type: none;
	list-style-position: inside;
}
ol.first-layer{
	counter-reset: num_f;
}
.first-layer li{
	counter-increment: num_f;
}
.first-layer li:before{
	display: marker;
	content: counter(num_f)". ";
}
ol.second-layer{
	counter-reset: num_s;
}
.second-layer li{
	counter-increment: num_s;
}
.second-layer li:before{
	display: marker;
	content: counter(num_f)'.' counter(num_s)". ";
}
ol.third-layer{
	counter-reset: num_t;
}
.third-layer li{
	counter-increment: num_t;
}
.third-layer li:before{
	display: marker;
	content: counter(num_f)'.' counter(num_s)"." counter(num_t)'. ';
}
```
できました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328604/57d5865d-9ccb-3799-4692-b89ac7b6cfa3.png)

###おまけ
n.n.n.や content の '.' を '-' に変更して、
1.0.0や1-0-0も作れます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328604/4f216f0b-cfb5-8721-d944-ecc8b76b03e5.png)

``` .css
ol.first-layer{
	counter-reset: num_f;
	counter-reset: num_s;
	counter-reset: num_t;
}
.first-layer li:before{
	display: marker;
	content: counter(num_f)'.' counter(num_s)"." counter(num_t)'. ';
}
ol.second-layer{
	counter-reset: num_s;
	counter-reset: num_t;
}
.second-layer li:before{
	display: marker;
	content: counter(num_f)'.' counter(num_s)"." counter(num_t)'. ';
}

```
※変更した箇所を記載
###参考
マーカー
http://www6.plala.or.jp/go_west/nextcss/reference/article/marker.htm

2020/8/7 一部表記を変更
Gmailで、一件あたりの容量を確認する

# 目的

- [AWS SESでの見積もり](https://aws.amazon.com/jp/ses/pricing/)に「受信された E メールの平均サイズ」が必要だった


# 確認の仕方

徐にブラウザからgmailを開き、メールを開きます[^1]
![スクリーンショット 2020-05-16 2.01.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222594/0ca79d47-0fa3-dc94-a085-fcf9dbe1f766.png)

メニューから「メッセージのダウンロード」をします

![スクリーンショット 2020-05-16 2.01.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222594/d9971280-66d3-5872-6883-42a60584cf1e.png)

Finderなりなんなりで容量を確認します

![スクリーンショット 2020-05-16 2.10.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222594/ab9423b2-ef52-919c-0f2f-624a3128b257.png)

お疲れ様でした

[^1]: これは推しの[夜桜みあ](https://twitter.com/yozakura_mia)ちゃんです、とてもかわいいのでよろしくお願いします。
A comment on Boruta algorithm

# 前略
[Boruta](https://github.com/scikit-learn-contrib/boruta_py)は特徴量重要度を使用した特徴量選択の手法の一つです。

下記サイトの解説を参考に勉強させていただきました。とてもわかり易い解説で、実験もあってとても参考になります。

- [ランダムフォレストと検定を用いた特徴量選択手法 Boruta](https://aotamasaki.hatenablog.com/entry/2019/01/05/195813)

## コメント
Borutaのアルゴリズムでは、ある特徴量が予測に有効かどうか判断するために帰無仮説「
この特徴量の重要度は、判別(回帰)に寄与しない特徴量の重要度と同じである。」を立て、検定を行います。帰無仮説が正しい場合、ある特徴量の重要度と判別(回帰)に寄与しない特徴量の収容度の大小はランダムになるはずで、ある特徴量の重要度が大きくなる確率は$p=0.5$の二項分布に従うはずです。

ここで気になったのは、Shadow Featureは一つではなく、元の特徴量次元と同じ数だけあります。そして、大小比較は、「ある特徴量の重要度 VS Shadow Featureの重要度の中で最大のもの」で行っています。

<img width="657" alt="スクリーンショット 2020-05-16 0.07.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/1b6af2df-9544-5313-74e3-8691248ebff6.png">
上記画像は[ランダムフォレストと検定を用いた特徴量選択手法 Boruta](https://aotamasaki.hatenablog.com/entry/2019/01/05/195813)からの引用

[boruta_pyの実装](https://github.com/scikit-learn-contrib/boruta_py/blob/master/boruta/boruta_py.py)もそうなっているように見えます。

```python
    def _do_tests(self, dec_reg, hit_reg, _iter):
        active_features = np.where(dec_reg >= 0)[0]
        hits = hit_reg[active_features]
        # get uncorrected p values based on hit_reg
        to_accept_ps = sp.stats.binom.sf(hits - 1, _iter, .5).flatten()
        to_reject_ps = sp.stats.binom.cdf(hits, _iter, .5).flatten()
        ...
```

ところが、Shadow Featureの特徴量重要度のうち最大のものを表す確率変数を$S_{\mathrm{max}}$とすると、

```math
S_{\mathrm{max}} \leq F_1 \Leftrightarrow S_1\leq F_1 \wedge S_2\leq F_1 \wedge S_3\leq F_1 \wedge S_4\leq F_1 
```

したがって、

```math
\mathrm{Pr}(S_{\mathrm{max}} \leq F_1) = \mathrm{Pr}(S_1 \leq F_1)\mathrm{Pr}(S_2 \leq F_1)\mathrm{Pr}(S_3 \leq F_1)\mathrm{Pr}(S_4 \leq F_1) = \left(\frac{1}{2}\right)^4
```

となり、帰無仮説が正しい場合、ある特徴量がShadow Featureの特徴量重要度のうち最大のものよりも大きくなる確率は$p=(1/2)^4$の二項分布に従うはずです。

```python
%matplotlib inline 
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.stats import binom

plt.rcParams['font.family'] = 'IPAPGothic' 
plt.rcParams["figure.figsize"] = [12, 6]
plt.rcParams['font.size'] = 20 
plt.rcParams['xtick.labelsize'] = 15
plt.rcParams['ytick.labelsize'] = 15

# 試行回数
N = 100
# 試行回数中の発生回数 (配列)   
k = np.arange(N+1)

# グラフにプロット
fig, ax = plt.subplots(1,1)
ax.plot(k, binom.pmf(k, N, p=0.5), 'bo', ms=8, label='p=0.5')
ax.vlines(k, 0, binom.pmf(k, N, p), colors='b', lw=1, alpha=0.2)
ax.plot(k, binom.pmf(k, N, p=0.5**4), 'x', ms=8, color='r', label='p=0.5^4')
ax.vlines(k, 0, binom.pmf(k, N, p=0.5**4), colors='r', lw=1, alpha=0.2)
ax.set_xlabel('iterarion')
ax.set_ylabel('probability')
ax.legend()
plt.show()
```

<img width="768" alt="スクリーンショット 2020-05-16 1.36.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211712/79f23f47-47d4-3375-30df-5381045eb54c.png">

グラフにするとわかりますが、棄却域とか結構違います。

## 草々
と、ここまで書いたんですが、`Boruta`を実際使ってみるとちゃんと動いてる？ので、何か考え方間違ってるんですかね。
[光-Hikari-のPython]02章-04 Pythonプログラムの基礎（コメントについて）

#[Python]02章-04 コメントについて
この節では、コメントについて説明していきます。
ある程度章が進むと、プログラムも長くなっていき、後ほど見返すと何を書いていたかわからなくなることが良くあります。

不思議なことに、一度自分で書いたプログラムを次の日に見返すと、何を書いていたか全くわからなくなることが良くあります。

また、自身が部署の異動等で後任の方にプログラムを渡す際に、後任のがプログラムを読んでもさっぱりわからなくなってしまい、**プログラムのメンテナンス時に困る**ことになります。

そこで用いられるのが**コメント**です。

このコメントでは、プログラム内にコメントを記載し、説明文を書くことができます。コメントには2種類ありますので、それぞれ見ていきます。

今回も、プログラムを書いて実行していく方法で進めていきたいと思います。

##「\#」を使ったコメントの記述について
まず、前回書いたプログラム<font color="#00cccc">02-03-05.py</font>をコピーして同じ<font color="#00cccc">chap02</font>内に<font color="#00cccc">02-04-01.py</font>を作成します。

以下のように、「\#」を用いるとコメントを記載することができます。

```02-04-01.py
#変数x,y,zにそれぞれ数値を入力する
x = input('変数x：')
y = input('変数y：')
z = input('変数z：')

#入力されたものをそれぞれ数値に変換してから足して、結果をwaに代入
wa = int(x) + int(y) + int(z)

#結果を出力する
print(x+'と'+y+'と'+z+'の和は' +str(wa)+ 'です。')
```
「**\#**」より右側はプログラムを実行しても無視されます。
こののように、**\#**を用いてコメントを記載すると、後でプログラムを見返したときに、わかりやすくなるというメリットがあります。

また、プログラムのデバッグ<font color=orange>（※）</font>の際にも、プログラムコードの1行部分を\#でコメントアウトして、動作確認する際にも用いられます。

<font color=orange>（※）</font>デバッグとは、プログラムを実行して不具合（バグ）が発生した際に、そのバグを取り除く作業。
##3つのシングルクオーテーションを使ったコメントの記述について
先ほど説明した\#を使ったコメントは、**1行のみしかコメントアウトできない**状態です。
例えば、長文をコメントするとなると、わざわざ各行に\#を入れなければならなくなります。

そこで用いられるのが3つのシングルクオーテーションを使ってのコメントです。
先ほど書いたプログラム<font color="#00cccc">02-04-01.py</font>をコピーして同じ<font color="#00cccc">chap02</font>内に<font color="#00cccc">02-04-02.py</font>を作成します。

以下のように、シングルクオーテーションを３つ記載して、長文をまとめてコメントアウトすることもできます。

```02-04-02.py
'''
作成者：光
プログラム記載日：2020/05/16
プログラムの内容：3つの数を入力して和を求めるプログラム
'''

#変数x,y,zにそれぞれ数値を入力する
x = input('変数x：')
y = input('変数y：')
z = input('変数z：')

#入力されたものをそれぞれ数値に変換してから足して、結果をwaに代入
wa = int(x) + int(y) + int(z)

#結果を出力する
print(x+'と'+y+'と'+z+'の和は' +str(wa)+ 'です。')
```

##最後に
今回はプログラミングというより、プログラミングで使えそうなネタを紹介しましたが、コメントアウトはよく実務上でも使用するものです。
適宜使用するように心がけてください。

###[【目次リンク】へ戻る](https://qiita.com/ko0821/items/379e8bd9e6ea01089419)
【Python】【SQLite3】PythonでSQLiteを操作する(基本編)

PythonでSQLiteを操作するときのメモ
備忘録です。
#ソースコードと説明
```python:sample.py
import sqlite3
from contextlib import closing

dbname = "sample.db"

with closing(sqlite3.connect(dbname)) as conn:
    c = conn.cursor()
    query = '''drop table if exists User'''
    c.execute(query)
    conn.commit()

with closing(sqlite3.connect(dbname)) as conn:
    c = conn.cursor()
    query = '''create table if not exists
                User(id integer primary key, name varchar(32))'''
    c.execute(query)
    conn.commit()

with closing(sqlite3.connect(dbname)) as conn:
    c = conn.cursor()
    query = ''' insert into User (id, name) values (?,?)'''
    user = (1, "Yamashita")
    c.execute(query, user)
    conn.commit()

with closing(sqlite3.connect(dbname)) as conn:
    c = conn.cursor()
    query = ''' insert into User (id, name) values (?,?)'''
    user = [
        (2, "Kinoshita")
        ,(3, "Hasegawa")
    ]
    c.executemany(query, user)
    conn.commit()

with closing(sqlite3.connect(dbname)) as conn:
    c = conn.cursor()
    query = "select * from User"
    for row in c.execute(query):
        print(row)
```
##with closing(sqlite3.connect(dbname)) as conn:
sqliteを操作する際は、クエリの実行後commit(),close()が必要
contextlibのclosingを使用することで、connectionのclose()記載漏れを防げる

##c.executemany(query, user)
executemany()を使用すると、タプルのリストを引数として渡して複数のinsertをまとめて記述できる
WSLのUbuntu20.04でRとJuliaをJupyterで動かすまでのまとめ

WSLのUbuntu 20.04のJupyterでRを動かそうとしたら思いの外苦戦したのでメモ。
ついでにJuliaも入れてみる。

WSLは2じゃなくて1のほう。
Anacondaなしでやってみる。
RをJupyterで動かすのに必要な追加ライブラリのインストールが必要でかなり時間がかかった。３～４時間くらい？
必要ないパッケージも入ってるかも。

Microsoft StoreからUbuntu 20.04をダウンロード。
ちなみにMicrosoftアカウントにサインインを求められるが必要なければキャンセルしてすぐダウンロードできる。


とりあえずUbuntuのアップデート。

```
$ sudo apt update
$ sudo apt upgrade
$ sudo apt install jupyter
```

一旦jupyter notebookの起動確認。

```
$ jupyter notebook
```

Powershellが起動して黒い画面が表示されるようになった？
一旦Ctrl+Cでこの画面から出る。
`shutdown this notebook server?`
と出るが無視して、この上に表示されているURLからJupyterに入る。
ブラウザで問題なくJupyterの画面を開くことができればとりあえずJupyterのインストールは成功。

続いてRをインストールする。

```
$ sudo apt install r-base
```

Ubuntuにライブラリを追加しておく。

```
$ sudo apt install build-essential libcurl4-openssl-dev
$ sudo apt install libcurl4-gnutls-dev libxml2-dev libssl-dev

$ sudo apt install xorg libx11-dev libglu1-mesa-dev libfreetype6-dev
$ sudo apt install r-cran-rgl
```

Rに入る。

```
$ R
```

アップデートする。
数回(yes/no/cancel)と聞かれるが基本的にyesでOK。

```
> update.packages(ask=FALSE)
```

Rの追加パッケージをインストールする。

```
> install.packages("Rcmdr", dependencies = TRUE)
> install.packages("rstan")

> install.packages(c("devtools")) 
> install.packages(c('repr', 'IRdisplay', 'evaluate', 'crayon', 'pbdZMQ', 'uuid', 'digest'))
```

以上のパッケージを入れておけばdevtoolsでIRkernelをインストールできると思う。

```
> devtools::install_github('IRkernel/IRkernel')
> IRkernel::installspec()
```
IRkernel設定できればJupyterのカーネルにRを選択できる。

続けてUbuntuにJuliaをインストールする。
と言っても基本的にJuliaのサイト`https://julialang.org/downloads/` からアーカイブファイルをダウンロードすれば使用可能。

```
$ wget https://julialang-s3.julialang.org/bin/linux/x64/1.4/julia-1.4.1-linux-x86_64.tar.gz
```

ダウンロードしたファイルを解凍する。

```
$ tar zxf julia-1.4.1-linux-x86_64.tar.gz
```

解凍したjuliaディレクトリを`/etc/`か`/opt/`あたりの適当な場所に移動する。

```
$ sudo mv julia-1.4.1 /etc
```


パスを通しておく。

```
$ echo 'export PATH="/etc/julia-1.4.1/bin:$PATH"' >> ~/.bashrc
$ source ~/.bashrc
```

juliaに入る。

```
$ julia
```

juliaのロゴが表示されたらパスを通すところまで成功している。
juliaのパッケージモードに入る。

```
julia> ]
```

IJuliaをインストールする。IJは大文字。

```
pkg> add IJulia
```

バックスペースキーを押して元に戻ってIJuliaを適用する。

```
julia> using IJulia
```

juliaを終了したらUbuntuでjupyterのカーネルを確認する。

```
$ jupyter kernelspec list
```

pythonの他にirとjuliaが表示されていれば多分インストールは成功。

~~Rでパッケージを追加するときはjupyterではなくコマンドラインから入れたほうがいいかも？~~

notebook上でinstall.packagesしても普通に実行できた。
インストール途中でWSL見たらちゃんとコマンドが動いていたしパッケージ普通に動いてるようなので問題なさそう。

以上。
初心者エンジニアが1か月学習してみてProgateの学習方法をまとめてみる

初めましてロンロンと申します。

前回の記事投稿から3週間ほど経ちました。
実をいうとコロナの緊急事態宣言から休業になり、無給になりました
ウイルスって恐ろしいですね。
実質、無職ということでプログラミングの勉強と趣味のネットで気になっている作品を見たりなどしてました。
アニメ【STEINS;GATE】これはガチでおすすめです！！！

後者はともかく、前者のプログラミング学習の体験は似たような境遇の方々やこれから学習しようと思っている
初学者の方に活かせる点もあると思うのでざっくり読んでいただければと思います。

【私のプログラミングレベル】
・WEBサイトの簡単なもの（アニメーションが使われていないもの）が模写・実装できる
・上記を実践するにあたり環境構築をすべて行える。
・HTML/CSS/javascript/Rubyの基礎概念を理解しているつもり
尚インプットはしていない。
・Linuxは少々運用作業でかじったことがある。

【学習したサービス】
・Progate(月1000円ちょい)
・Youtube(無料)
・Udemy(セール中に1500円ほどで実戦形式で学べるサービス)
・Twitter(駆け出しエンジニアの学習宣言をすることでさぼり率の低下を図る)
・オンラインサロン(モチベアップ月1000円ほど)
※有名なドッドインストール・Paizaは使用していません。これからやってみます。



【実践したもの】
()は使用するプログラミング言語
・※AWS上にて動く電話帳アプリの実装(Ruby/RubyonRails)
・ローカルで動く電卓アプリの実装(Javascript/jQuery)
・※模写サイトの作成

※AWS→通販サイトAmazonが運営するクラウドサーバーを提供しているサービス。
従量課金制で安定した環境でPCのスペックに依存せず動かせる。興味ある方は調べてみてください。
※実際に稼働しているサイトや参考サイトを見て機能以外のサイトのデザインを真似て自分で制作してみること(模写コーディングで検索してみてください)

【Progate学習する上で気を付けること】
まず初心者の方におすすめされている教材、Progateの学習の反省を含めて書いていこうと思います。

・プログラミングは難しいので一度で理解しようとしない。
詳しく・・・
初プログラミングでProgateを勉強したとき全部ノートに書き移そうとして去年挫折しました。
何がいけないのか才能がないのかと思い一年プログラミングから逃げてました、原因としてはすべてを暗記して理解しようとしてノートに書いたりしていたからです。
数分わかりやすい図とかでまとめるのはおすすめですが全部を暗記して書くといった時間は無駄です。
勝手に挫折して効率の悪さを実感したので断言します。

・成果が出ないからと言ってめげない
詳しく・・・
世の中には天才的な人がいてTwitterなどでも一週間ですごいレベルのポートフォリオやサービス公開をする方がいます。もちろんそういう方の集中力や努力はすさまじいものですが、かといって自分の能力が低いから
と卑下するのは早いです。毎日集中して数時間やれば1週間後、1か月後少なからず変わってるはずだし体験していると思うので頑張りましょう。

・Progateを周回しすぎない、かといって言語・サービスは浮気しすぎない
詳しく・・・これも同様に挫折したことがあります。
「Rubyやりたいな！でも求人はJavaとかPHPが多いし・・・でもPythonも捨てがたい・・・」
となってしまって構文が違う基礎をぐるぐるしてしまい何も技術が付かなかったです。

そして完全理解できてないからもう一周、また理解できないからもう一周としていました。
2週したらどういった記述でこんなことができるというのは大まかに理解できるので
困ったらググってみてわからなければそこだけProgateのスライドと答えを見るようにしてます。

【Progateをある程度終えられたら】
・学んだ経験をもとにポートフォリオを作成してみる(私はHTML/CSSとJqueryのプラグインを使用して自己紹介サイトを作成しました。)
・ある程度基礎を学んで道場も終えたならUdemyやドッドインストールなどハンズオンで実際にサービスを作ってみる
詳しく・・・私も今Udemyで学んでいる最中で、実際のコーデイングする環境構築から実際の現場での記述法など紹介している講師の方もいて楽しく学べておすすめです。

【総括】
私も未熟エンジニアですが7月には案件獲得をして実践で稼げるエンジニアになりたいです。
自粛で精神ギリギリになるし学習は辛いですが皆さん頑張っているので負けず頑張ろうという方が一人でも増えれば幸いです。
Laravel 既存テーブルにカラムを追加する時のマイグレーションファイルの作成方法

# 目的

- 実施方法を毎回検索しているので簡単にまとめる

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# 実施例

- 下記にカラム追加に必要なマイグレーションファイルの作成コマンドを記載する。

    ```terminal
    $ php artisan make:migration add_カラム名_column_to_テーブル名_table --table=テーブル名
    ```

# 具体例

- 「users」テーブルに「flag」カラムを追加したい時のマイグレーションファイルの作成コマンドを下記に記載する。

    ```terminal
    $ php artisan make:migration add_flag_column_to_users_table --table=users
    ```
before_action

#before_actionとは

railsのコントローラーのアクションを実行する前に処理を行いたいときや、同じ記述の処理をまとめたい時に使います。

基本的な書き方は以下です

```hoges_controller.rb
   before_action :処理させたいメソッド名
```

この場合だと、同じコントローラーに定義されている各メソッドの実行の前に、指定したメソッドによる処理が行われます。

もしくは[resourcesメソッド](https://qiita.com/kouhei_matuura/items/c440994b3e2102ddefcb)と同じようにonlyやexceptなどでアクションの限定をすることもできます。

```hoges_controller.rb
before_action :処理させたいメソッド名, only: [:アクション1,:アクション2]
```

この場合はアクション１と２が実行される前にのみ、指定した「処理したいメソッド」が実行されます。


#使用例

コントローラーに下記の記述があったとします。

```tweets_controller.rb
class TweetsController < ApplicationController

  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

  def create
    Tweet.create(tweet_params)
  end

  def destroy
    tweet = Tweet.find(params[:id])
    tweet.destroy
  end

  def edit
    @tweet = Tweet.find(params[:id])　　　　←処理が被ってる
  end

  def update
    tweet = Tweet.find(params[:id])
    tweet.update(tweet_params)
  end

  def show
    @tweet = Tweet.find(params[:id])       ←処理が被ってる
  end

  private
  def tweet_params
    params.require(:tweet).permit(:name,:text)
  end
end
```

みてもらうと分かりますが、editとshowにおいて記述が被っています

そのため、上記のコードをリファクタリングし、

```tweets_controller.rb
class TweetsController < ApplicationController
  before_action :set_tweet, only: [:edit, :show]

  def index
    @tweets = Tweet.all
  end

  def new
    @tweet = Tweet.new
  end

  def create
    Tweet.create(tweet_params)
  end

  def destroy
    tweet = Tweet.find(params[:id])
    tweet.destroy
  end

  def edit
  end

  def update
    tweet = Tweet.find(params[:id])
    tweet.update(tweet_params)
  end

  def show
  end

  private
  def tweet_params
    params.require(:tweet).permit(:name,:text)
  end

  def set_tweet                          ←共通の処理をまとめている
    @tweet = Tweet.find(params[:id]) 
  end
end
```

共通の処理をset_tweetというメソッドでまとめ、showアクションとeditアクションの実行の際にbefore_actionで呼び出しています。


#もっと分かりやすいイメージ


```rb
before_action :authenticate_user!
```

上記は[devise](https://qiita.com/kouhei_matuura/items/c82a47b8fac431deddf7)を導入した際に使えるようになるメソッドである「authenticate_user!」を指定しています。ログインしていない場合はログイン画面に遷移させるメソッドです。


よく、Amazonなどの通販サイトなどを使用していると分かりますが、商品の閲覧はログインしていなくても出来るけど、購入に進むとログインを求められますよね。


このように何らかのアクションを実行する前に行なって欲しい共通の処理をbefore_actionでは指定します。
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -3_4.環境設定(DB)-

##DBサーバへの環境設計

今回の要件に必要な環境は次のとおりです。
・SQL Server for Linux

以上ｗ

##1.SQL Server for Linux インストール

参考サイト：
CentOS 7にSqlServerをインストールする
https://qiita.com/qiiChan/items/4dc6a5cea310fea1e637

参考サイト通り、インストールしてください。
これでインストールはOK！

##2.Firewall設定
さて、インストール終わりましたか。
次に、Firewallの設定を行ってください。

なぜ？それは、海外のbotツール等で、SQLServerが狙われているからです。
まず、必要なIPからのみの許可を出してください。
さもないと、1時間に300回ほど、SQLServerへのログインが行われます。
中国、インド、中国、中国。。。いくらなんでも多すぎる。
即サーバのOS再インストール。

ってことで、こんなfirewallコマンドを。
IPは自身のグローバルIPと、前回設定したAPサーバのIPを設定してください。

```db_cmd-1.bat
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="123.123.123.123" port protocol="tcp" port="1433" accept"
firewall-cmd --permanent --zone=public --add-rich-rule="rule family="ipv4" source address="234.234.234.234 port protocol="tcp" port="1433" accept"
```



##3.端末（SQL Server Manegement Studio）からの接続

参考サイト：
SQL Server Management Studio (SSMS) のダウンロード
https://docs.microsoft.com/ja-jp/sql/ssms/download-sql-server-management-studio-ssms?view=sql-server-ver15

ローカルにインストールしてください。話はそれからだ（です）。


次に、起動してください。
DBサーバへのIPアドレスを入力し、サーバへ接続してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249830/0687bed2-76f9-d04d-c044-c13e0f044375.png)


すると、うまく接続できるはずです。


あとは、DB作ったり、テーブル作ったりしてください。
テーブルを作るSQL文はVisual Studio から出せます。
思い出せない方は過去の記事を御覧くださいませ。

過去の記事：
asp.net coreでサービス作ったから宣伝兼ねて技術公開する -2_3.ユーザ名の登録-
https://qiita.com/ArataKinjo/items/754615dde0ab09dfee81


##4.APサーバからの接続テスト
DBサーバがないと、接続テストも出来ませんからね。
試すのは、2つ。

1.ローカルからのデバッグ接続。
2.APサーバからの本接続

私の場合、appsetting.jsonに、ローカルの接続情報と、DBサーバの接続情報を書いておいて、必要なときにlocal→無印へ、db_server→無印へコピーする運用を行っております。
（※ 無印="ConnectionStrings"のことを指してます。）

```appsettings.json
{
  "ConnectionStrings": {
    "DefaultConnection": "Data Source=localhost;Initial Catalog=tanatoru_db;Persist Security Info=True;User ID=sa;Password=PASSWORD123"
  },
  "ConnectionStrings_local": {
    "DefaultConnection": "Data Source=localhost;Initial Catalog=tanatoru_db;Persist Security Info=True;User ID=sa;Password=PASSWORD123"
  },
  "ConnectionStrings_db_server": {
    "DefaultConnection": "Data Source=123.123.123.123;Initial Catalog=tanatoru_db;Persist Security Info=True;User ID=sa;Password=PASSWORD123"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "AllowedHosts": "*"
}
```

これをdb_server→無印へ"DefaultConnection":---へ貼り付けて、実行してみてください。
接続できれば、OKです。

そのままAPサーバへデプロイし、接続テストを行ってください。
うまく接続できることを祈ってます。

##最後に

以上、DBサーバはそこまでセットアップに時間はかかりませんでしたね。
これでこの連載は一区切りとなります。
（まだネタがあるので続きますが。）

APサーバ、DBサーバを一貫してセットアップする記事は色々探したけど無いもんなんでね。
まぁまぁ役立つことがあるのではないかとは思います。

製品開発では、一番やってはいけない「技術向上のために製品を作る」をやってしまった訳ではありますが、アウトプットすることによって、価値が生まれるのではないかと考えております。
また、これで新しい製品を作る際にどういうアプリケーションをどのように、どの程度で出来るかが分かることは出来ます。

金銭的に得るものは少なくとも、技術的・経験的に得るものはたくさんありました。
常に新しいアイディアを考え、実現までした経験を積むことは、今後の生き方に大きく関わってきます。
「全てのことを自分の力で実現する」には、限界があるのはわかっておりますが、やってもないことをあたかもやったかのように言う人間にはならないように。


最後に、楽しかった！



【是非お試しください】※完全無料です
TanaToru -本棚管理サービス-
　https://app.zero-one-system.co.jp/TanaToru/
Firebase Local Emulator SuiteのFirestoreに外部のスクリプトからアクセスしてモックデータを突っ込む

※[こちら](https://qiita.com/Kesin11/items/43bbc06524aa31c1fd2c#firestore_emulator_host%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)に非常に良い記事があります。まだ読んでおられない方は是非！

環境変数の`FIRESTORE_EMULATOR_HOST`に適切な値を設定することで外部のスクリプトからエミュレーターにアクセスできます。（他言語のSDKでも同様だそうです）

```javascript
import { Firestore } from '@google-cloud/firestore';

Object.assign(process.env, {
  GCLOUD_PROJECT: '[プロジェクトID]', 
  FIRESTORE_EMULATOR_HOST: '0.0.0.0:[Firestoreのポート番号]'
});

const firestore = new Firestore();

(async () => {
  // admin権限が必要な操作も可能
  console.log(await firestore.listCollections());
})();
```

なお、`GCLOUD_PROJECT`に関しては環境変数を使わなくても適当なメソッドで代替できます。**実際に存在するプロジェクトIDである必要はない**ことに注意です！Firestoreのエミュレータは並列実行しても1インスタンスなので、プロジェクトIDが被ると共通の領域が使用されるようになります。

これに気づくまでに数時間を要しましたが、冒頭にも書いた通り、既に偉大な先人の方が記事を書かれていたようです。[こちらの記事](https://qiita.com/Kesin11/items/43bbc06524aa31c1fd2c#firestore_emulator_host%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)は十分に読み込んだつもりになっていましたがまだまだ甘かった・・・。
SQL（データの追加、更新、削除）とNode.js基本

###○データの追加
```js:qiita.js
insert into テーブル名　カラム名
values (カラム名)
```
↑テーブルにレコードを挿入したいときはinsertを使う。

###○データの更新
```js:qiita.js
update テーブル名
set カラム名='新しい値', カラム名='新しい値'
where 条件
```
↑テーブルのレコードを更新したいときはupdateを使う。
※whereで更新するレコードを指定しないとカラム内の全データが更新される。
※update実行後はデータを戻すことができない

###○データの削除
```js:qiita.js
delete from テーブル名
where 条件
```
↑テーブルからレコードを削除したいときはupdateを使う。
※whereで削除するレコードを指定しないとテーブル内の全レコードが削除されてしまう。


###○Node.jsとは？
・Node.jsは本来クライアント側の言語であるJavaScriptをサーバーサイドで動かすための仕組み。

###expressとは？
・ExpressはNode.jsでWebアプリの開発をするためのフレームワーク。

###ページの表示の仕組み

```js:qiita.js
app.get ('URL', (req, res) => {
  res.render('ファイル名')
});
```

↑URLにリクエストが来た時に、ファイル名を表示することができる。

###EJSとは？

・EJSとは、HTMLとJavaScriptのコード両方を記述できるNode.jsのパッケージ

・JavaScriptのコードを記述するには、<% %>または<%= %>で囲む。
<% %>で囲んだ場合はブラウザに何も表示されないので、変数の定義などに用いる。変数の値などをブラウザに表示したい場合は<%= %>を用いる。

###MySQLとは？

・MySQLとは、データベースを管理するツールの一つ。

```js:qiita.js
const mysql = require('mysql')
```

↑上記のようなコードでmysqlパッケージを読み込むことができる。

###クエリの実行

```js:qiita.js
connection.query('クエリ', クエリ実行後の処理)
```

↑Node.jsからデータベースに対してクエリを実行することができる。
・クエリ実行後の処理は2つの引数を取ることができる。
第1引数のerrorにはクエリが失敗したときのエラー情報が、第2引数のresultsにはクエリの実行結果が入る。

###getとpost
・画面を表示したいときはget、データベースを変更したいときはpost

###リダイレクトとは

```js:qiita.js
res.redirect('URL')
```

↑サーバーは「次はこのURLにリクエストしてね」というレスポンスを返すことができる。このレスポンスを受け取ったブラウザは指定されたURLに自動的にリクエストする。このような別のURLに再度リクエストさせる仕組みを「リダイレクト」と言う。
【Windows】OSインストール前にMBRディスクの容量を確認する方法

## はじめに

Windows/WindowsServerのOSインストール前にMBR領域を確認する方法について紹介していきたいと思います。
今回紹介する方法は、事前にMBRディスクの容量を確認する場合に役に立ちます。

## 今回の検証環境

- HyperVisor 
**VMware ESXi 6.7**

- OS 
**WindowsServer2012R2**

- 起動モード 
**BIOS**

- ボリューム数
**1つ**


## 手順

①OSインストールをデフォルトのまま進めるとこちらの画面が表示される。

**「カスタム」**を選択

![1.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/1004f7a8-c3fd-0a1f-4b5c-4c4e9e38c539.jpeg)


②「ドライブ0の割り当てられていない領域」を選択。その後に「新規」をクリック。

![2.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/523dfc97-63af-1f5c-6ae8-0548304b6f06.jpeg)


③サイズが表示される。変更せずに「適用」をクリック。

![3.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/698d8673-e787-441a-75c8-46cbf3b94c9b.jpeg)

④ポップアップが表示される。そのまま「OK」をクリック。

![4.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/f9810560-5dcf-1a4c-7d62-e75b000ade83.jpeg)


⑤パーティションが2つになっていることを確認
**※「システム」がMBRディスク**

![6.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636476/dce230d9-4034-fab2-f89a-c344263daf98.jpeg)

**※UEFIのGPTディスクの場合も同様に確認できます。**

## まとめ

いかがでしたでしょうか？
このような形でOSインストール前にMBRディスクの容量を確認することができます。

OSインストール前にパラメーターシートと値を比べる際に役に立ちます。

こちらの記事が参考になったら幸いです。

**↓Twitterもやってます！**
インフラエンジニアの知識等を発信しています！
https://twitter.com/satton6987
RaspberryPi  zabbix5.0

#nginxのインストール

sudo apt-get install nginx

sudo systemctl start nginx


#PHPのインストール

    sudo apt install php7.3-fpm php7.3-mysql

56行明くらいを修正

    sudo nano /etc/nginx/sites-available/default
    location ~ \.php$ {
      include snippets/fastcgi-php.conf;
      # With php-fpm (or other unix sockets):
      fastcgi_pass unix:/run/php/php7.3-fpm.sock;
      # With php-cgi (or other tcp sockets):
      #fastcgi_pass 127.0.0.1:9000;
    }

以下検索して修正

    sudo /etc/php/7.3/fpm/php.ini
    cgi_pathinfo=0にする
#dbのインストール

    sudo apt install mariadb-server
    sudo mysql_secure_installation
DB用意

    mysql -uroot -p
    password
    mysql> create database zabbix character set utf8 collate utf8_bin;
    mysql> create user zabbix@localhost identified by 'password';
    mysql> grant all privileges on zabbix.* to zabbix@localhost;
    mysql> quit;
#ZABBIXのインストール

    wget https://repo.zabbix.com/zabbix/5.0/raspbian/pool/main/z/zabbix-release/zabbix-release_5.0-1+buster_all.deb
    dpkg -i zabbix-release_5.0-1+buster_all.deb
    apt update
    apt install zabbix-server-mysql zabbix-frontend-php zabbix-nginx-conf zabbix-agen
    zcat /usr/share/doc/zabbix-server-mysql*/create.sql.gz | mysql -uzabbix -p zabbix

パスワード設定

    /etc/zabbix/zabbix_server.conf
    DBPassword=password

nginxコンフィグファイル

    /etc/zabbix/nginx.conf
    listen 80;