OmniAICreator/Qiita-1.07M huggingface dataset:
直木n十五プログラム

友達が「直木三十五って今だったら直木何になるんだろう」と言っていたので、プログラムはほとんどわからない初心者ながら、作りました。


```Python:
def int2kanint(num) :
    suji   = ["","一","二","三","四","五","六","七","八","九"]
    kugiri = ["","十","百","千"]
    tani   = ["","万","億","兆","京","垓","𥝱","穣","溝","澗","正","載","極","恒河沙","阿僧祇","那由他","不可思議","無量大数"]
    num  = list(map(int,list(str(num))))
    kansuji = []

    for k, v in zip(range(len(num)), reversed(num)) :
        keta = []
        keta.append(suji[v if v>1 else 0 if k%4 else v])
        keta.append(kugiri[k%4 if v>0 else 0])
        keta.append((tani[0 if k%4 else int(k/4) if any(list(reversed(num))[k:(k+4 if len(num)>=(k+4) else len(num))]) else 0]))
        kansuji.append("".join(keta))

    kansuji = "".join(reversed(kansuji))

    return kansuji if kansuji else "零"


print("西暦何年の直樹三十五を知りたいですか")
x = input()
y = int(x) - 1891
print(str(x)+"年")
if (y >= 0) :
    print("西暦"+str(x)+"年の直木三十五は『直木"+int2kanint(y)+"』です。")
else:
    print("生まれてねえよ。")
```
コードの漢数字変換部はこちらを参考というか丸コピしました。ありがとうございます。
https://qiita.com/m_rafa0110/items/a4df610ab89e73ae1457

簡単に説明すると、直木三十五が入力した年数だと直木何になるのか表示してくれるものになります。
まだ直木三十五が生まれていない場合は"生まれてねえよ。"と表示します。

以上です。ありがとうございました。
【Git】GitHubでリポジトリを作った時に打つコマンドたち

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/5a5751a2-f8ad-72fe-7382-49c05654f861.png)

# はじめに
![スクリーンショット 2021-11-24 22.12.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/0db58cf7-82b1-60c6-9f8f-5933f329c7b5.png)
GitHubで新規にリポジトリを作成した時に打つコマンドたち、いつもコピペして貼り付けてるだけではありませんか？？
そんなあなたに！簡単にですが、解説しようと思います。



# コマンドたち

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/573011/99c09b32-e235-e490-ec47-564f1ca2b094.png)

```shell
git clone git@github.com:westhouseK/qiita.git
```

```shell
echo "# qiita" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin git@github.com:westhouseK/qiita.git
git push -u origin main
```


# 解説

```shell
git clone git@github.com:westhouseK/qiita.git
```
カレントディレクトリに、ファイルをダウンロードするコマンドです。デフォルトでは、リポジトリ名のディレクトリが作成されます。`.git`の後に文字列を書くと、ディレクトリ名を任意に設定することができます。
また、以下のようにgitのリモートリポジトリのURLが自動で設定されます。

```shell
git remote -vv
origin	git@github.com:westhouseK/qiita.git (fetch)
origin	git@github.com:westhouseK/qiita.git (push)
```

---

```shell
echo "# qiita" >> README.md
```

`echo $1` ･･･ $1の文字を画面に出力します。今回でいうと、**# qiita**ですね。
`>>` ･･･ **リダイレクション**と言って、画面に出力するのではなく、右辺のファイルに追記します。今回でいうと、**README.md**ファイルがないので作成し、最後尾(1行目)に**# qiita**を追記します。

---

```shell
git init
```
Gitの初期化を行い、`.git`ファイルがなければ作成します。`.git`ファイルはコミット、マージ、ブランチ等の情報をすべて保持します。
中身の詳細は[こちら](https://qiita.com/tatane616/items/dbad66179754be57d2e2)を読んでみてください。

--- 

```shell
git add README.md
```
修正したファイル(README.md)をステージングエリアに追加します。一つ前の状態に戻す場合には`git reset`

--- 

```shell
git commit -m "first commit"
```
初めてのコミットになります！`-m`は、コメットメッセージをその場で登録できるオプションです。コミットメッセージは任意です。`git log`でコミット履歴を確認できるようになりました。

---

```shell
git branch -M main
```
こちらのコマンドを打つ前に、`git branch`すると、**master**(またmain)になっているはずです。[Git version 2.28からデフォルトがmain](https://github.blog/2020-07-27-highlights-from-git-2-28/)のようです。
`-M`(または`-m`)はブランチ名を変更するコマンドです。ブランチ名を**main**に変更しています。

---

```shell
git remote add origin git@github.com:westhouseK/qiita.git
```
リモートのリポジトリの情報を登録するコマンドです。git cloneした方はスキップしていただいて大丈夫です。ここで**origin**を決定しています。

---

```shell
git push -u origin main
```

ローカルリポジトリの情報をリモートリポジトリへ同期するコマンドです。`-u`コマンドは、追跡ブランチを設定するオプションです。要するに、ローカルのmainブランチは、リモートのmainブランチを元にしているという情報を持つイメージです。以下のコマンドで追跡ブランチを確認することができます。

```
$ git branch -vv
* main f24b242 [origin/main] first commit
```

---

# 終わりに
いつも全行コピペして貼っていただけなので、まとめらてスッキリしました。
今日はよく眠れそうです💤
Unity プレイ時に音が同時に一つしか再生されない現象の対処法


##OSがMacの場合
1. Edit/ProjectSettingsを開き、Audioをクリック。
2. MaxRealVoicesが1になっていたら、その数値を上げる。16とか。
![スクリーンショット 2021-11-24 22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/324523/843118cc-35c6-4b84-3a64-ff9515e0e2c7.png)


3. これで解決しました。
Pyhton_ローカル変数とグローバル変数

# 関数外で定義した変数はグローバル変数

```Py
num = 50
def printnum():
    print(num)

print(num)
printnum()
print(num)
```

>50
50
50

# 関数の中で代入した変数はローカル変数
* 関数内が範囲
* グローバルに同名の変数があっても関数内では優先される


```Py
num = 50
def printnum():
    num = 20
    print(num)

print(num)
printnum()
print(num)
```
> 50
20
50

# 関数内でglobal変数を更新する
```Py
num = 50
def printnum():
    global num
    num = 20
    print(num)

print(num)
printnum()
print(num)
```
> 50
20
20

# ネストした関数で1段上の関数の変数を更新する
何もしていない時はそれぞれのローカル変数を読み込む。

```Py
num = 0

def print_num_outer():
    num = 1
    
    def print_num_inner():
        num = 2
        print(num)
    
    print_num_inner()
    print(num)


print(num)
print_num_outer()
print(num)
```
>0
2
1
0

ネストした関数で1段上の関数の変数を参照している

```Py
num = 0

def print_num_outer():
    num = 1
    
    def print_num_inner():
        nonlocal num
        num = 2
        print(num)
    
    print_num_inner()
    print(num)


print(num)
print_num_outer()
print(num)
```
> 0
2
2
0
PHP 配列に値があるかチェックするメソッド

# 目的

- 配列に値があるかチェックする`in_array()`メソッドの使い方を簡単に紹介する。

# 情報

- 下記のサイトを用いてこちらに記載するソースの検証を実施した。
    - [https://paiza.io/ja](https://paiza.io/ja)

# 方法

- 下記のように`in_array()`メソッドを用いて値があるかチェックする。（第三引数でtrueを渡すとデータ型も含めて評価してくれる。）

    ```php
    in_array(探したい値, 配列, true);
    ```

# 例

- 下記のようにソースを記載して実行してみる。

    ```php
    <?php

    $str = 'ccc';
    $array = [ 'aaa', 'bbb', 'ccc' ];

    if (in_array($str, $array, true)){
        echo 'あったよ';
    };
    ```

- `$str`に格納されている「ccc」は`$array`に存在しているため、trueが返され、「あったよ」が出力される。
Javaコンパイル・実行時の文字化け対策（windows10）

# 初めに
Javaの勉強を始めてみました。VS Codeを使っているのですが、デフォルトで開くターミナルがpower shellであることに気付かずネットで調べたコマンドが動かないよおおお？？？となっていました。（コマンドプロンプトとpower shellで動くコマンドが微妙に違うため）
もっと言うと意地を張らずにJavaはShift-JISで書いたほうがいいと思いますが、気になってしまったので少し調べてみました。

# 文字化け対策（windows）
windowsのコマンドプロンプトでJavaを実行すると文字化けした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2130321/929f7849-0e6a-2dea-b3d8-1cb9826be8f7.png)



これはJavaファイルをUTF-8で作成したが、コマンドプロンプト（windows）が使用している文字コードはshift-jisであることが原因。
UTF-8を画面に出力するためには以下のコマンドを実行すればよい。
(65001はUTF-8を表す)

```
chcp 65001
```
shift-jisに変更するときは以下のようにする。

```
chcp 932
```


# コンパイルと実行

## コンパイル・実行コマンドのの基本
javacコマンドでコンパイルできる
コンパイルするとclassファイルができる

```
javac Hello.java  
```

コンパイル後、クラス名（ファイル名ではない）を指定してjavaコマンドを実行すると、Javaプログラムを実行できる。

```
java Hello
```

パッケージ名を付けた場合は、パッケージ名を指定してルートディレクトリでコマンドを実行する。

```chapter04\Sample1.java
package chapter04;

public class Sample1 {
    public static void main(String[] args) {
        System.out.println(1 + 2);
    }
}
```

```
java chapter04.Sample1
```

## shift-jis以外で記載されたファイルを実行する
ここでは～.javaをUTF-8で保存した場合を考える。
コンパイル、実行にはそれぞれオプションで文字コードを指定する必要がある。

コンパイル

```
javac -encoding utf-8 .\chapter06\Sample.java
```
UTF-8の文字コードを使用して実行（ただし`コマンドプロンプト`では実行できるが、powershellではこのオプションの記述では動かない）

```
java -Dfile.encoding=utf-8 chapter06.Sample
```

そもそもwindowsではコマンドプロンプト、power shell問わず基本的にJavaはShift-JISとして出力されるらしいので、`chcp 932`を実行してShift-JISを表示できるようにした後`java Sample`とオプション指定なしで実行すればいいらしい。
[参考](https://www.comp.tmu.ac.jp/tmuner/faq/mac/java.html)
スプレッドシートで曜日を基準にしたカレンダーを作成する。（GAS無し、関数のみ）

書きかけです。

一か月ごとに作り直すとかナンセンスだと思ったので。


１段目

```
=if(DATE(YEAR($C$3),MONTH($C$3),1)+7-WEEKDAY(DATE(YEAR($C$3),MONTH($C$3),1),3)-7<DATE(YEAR($C$3),MONTH($C$3),1),"",DATE(YEAR($C$3),MONTH($C$3),1)+7-WEEKDAY(DATE(YEAR($C$3),MONTH($C$3),1),3)-7)
```

もし、第2月曜日から７日引いた日が"指定した月の１日"より前なら
空欄にし、
でなければ第一週の日付を表示する


訳としてはこんなところ。
これを月曜日として一段目は１つずつずらした。

```
=if(DATE(YEAR($C$3),MONTH($C$3),1)+8-WEEKDAY(DATE(YEAR($C$3),MONTH($C$3),1),3)-7<DATE(YEAR($C$3),MONTH($C$3),1),"",DATE(YEAR($C$3),MONTH($C$3),1)+7-WEEKDAY(DATE(YEAR($C$3),MONTH($C$3),1),3)-7)
```

２段目以降は１段目に７足して、
最後の段には次月になったら表示しないIF文を仕込んだ。
これで完成。


とりあえず参考にしたところ

- [第一月曜日の日付を求めるには - WEEKDAY, DATEの解説 - エクセル関数リファレンス](https://www.sophia-it.com/excel-functions/reference/%E7%AC%AC%E4%B8%80%E6%9C%88%E6%9B%9C%E6%97%A5%E3%81%AE%E6%97%A5%E4%BB%98%E3%82%92%E6%B1%82%E3%82%81%E3%82%8B%E3%81%AB%E3%81%AF)
月初めの曜日がわからないと始まらなかったので

- [Googleのスプレッドシートで今週月曜・日曜の日付を取得する方法 - Qiita](https://qiita.com/wau/items/5d50831d9e941c1a7b0c)

- [Ufuidotnet(うふい.net)／Excel「コピペで使える数式：第1日曜日・第1月曜日…第1土曜日の日付を求める数式(1)」](https://www.ufui.net/pc-tips/excel010.html)
Python_*args, **kwarge(可変長引数)


# *args
いくつでもの引数をタプルとして受け取る
*argsはargsではなくどんな文字列でもよい。

```py
def challenge_args(*args):
    print(args)
    print(args[0])
    print(sum(args))


challenge_args(1, 2, 3, 4)
```

```text:実行結果
(1, 2, 3, 4)
1
10
```

```py
def challenge_apple(*apple):
    print(apple)
    print(sum(apple))


challenge_apple(1, 2, 3)
```

```text:実行結果
(1, 2, 3)
6
```


# **kwargs
いくつかのキーワード引数を辞書として受け取る。

```py
def challenge_kwarges(**kwargs):
    print(kwargs)
    apple = kwargs.get('apple', None)
    print(apple)


challenge_kwarges(apple='red', banana='yellow')
```

```text:実行結果
{'apple': 'red', 'banana': 'yellow'}
red
```
PacketTracerでLAN構築してみた。

#はじめに
皆さん、はじめまして。
CiscoのPacketTracerでスイッチを用いた簡単な疎通確認を行いました。

##実験

**使用機器**
Windows
Cisco Packet Tracer

**実験項目**

 <dl>
<dt>1.各機器にIPアドレスを割り振る</dt>
<dd>今回は４台PCを使用したので4台それぞれにIPアドレスを割り振ります。</dd>
<dt>2.ARPテーブルとMACテーブルの確認</dt>
<dd>機器をスイッチに接続した際のARPテーブルとMACテーブルの確認します。</dd>
</dl>




**1.４台の機器をスイッチに接続し、IPアドレスを割り振ります。** 

PC0:192.168.1.1(255.255.255.0)
PC1:192.168.1.2(255.255.255.0)
Laptop0:192.168.1.3(255.255.255.0)
Laptop1:192.168.1.4(255.255.255.0)

![2021-10-28 (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207615/e0a341a6-0b6e-49fd-3f99-09deceb6b6a5.png)
                             図１

**2.ARPテーブルとMACテーブルの確認**
スイッチに接続できたら、pingで疎通確認します。
また、ARPテーブルとMACテーブルの確認をします。

![2021-10-28 (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207615/f39e71d2-dfff-f1f9-f8bf-c0aa80959d1f.png)
図２

接続後、C:\>arp -aでARPテーブルを表示させてみると,
No ARP Entries Foundと表示されます。これは、まだARPテーブルに乗っていないということになります。


PC0からPC1へ
![2021-10-28 (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207615/a7f0b4bc-711a-11f4-4c4c-edd70885f472.png)
図３

pingが通ったことを確認し、C:\>arp -aでARPテーブルを表示させてみると、PC1が登録されていることが分かります。（図３）

![2021-10-28 (14)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207615/63c27f4a-9884-fef1-c7e2-d8077db23a09.jpeg)
図４

この際、ARPのパケットの中身は図４のようになっており、送信元であるPC0のMACアドレス、IPアドレス、送信先であるPC1のIPアドレス、と不明のMACアドレスが記載されています。

![2021-10-28 (13)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2207615/26490fa0-3622-46de-87ca-500041b3c457.jpeg)
図５

これを受け取ったPC1は自身のMACアドレスを記載し、送信元であったPCに送ります。この際、送られてきたパケットに送信元のMACアドレスの記載があったので行先が分かります。このようにして、疎通を行っています。（図５）

###まとめ
今回初めてPacketTracerを用いてスイッチに接続し疎通確認を行いました。
L2スイッチは、接続された機器のMACアドレスを記憶しています。
そのMACアドレスを元にして送信相手のみに送っています。
Unity × ARでボールが跳ね返らないときは

UnityでARブロック崩し的なやつを作ろうとしたら、下のgifのようにボールが壁にあたっても全く跳ね返らない。「Unity ブロック崩し」で検索して出てきた通りにPhysics Material等を設定しても一向にだめ。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239014/3f95a8ef-5efc-7a10-7e20-a9bc99724d2a.gif" width="200">

#結論
UnityにおけるオブジェクトのScaleはm単位なので、ARで現実空間に表示する際はScaleを小さい値に設定することが多い。今回もUnity上でオブジェクトのScaleを0.05（5cm）とかに設定し、それに合わせてボールの速度も0.15（15cm/s）に設定していた。ところが、Unityには処理のオーバーヘッドを減らすために速度の遅すぎるオブジェクトの物理演算ををカットする設定があるらしく、今回は跳ね返りに関するBounce Thresholdに引っかかっていた（参考：[Unityマニュアル](https://docs.unity3d.com/ja/2021.2/Manual/class-PhysicsManager.html)）。

>**Bounce Threshold**
>速度の値を設定します。 2つの衝突するオブジェクトの相対速度がこの値より小さい場合、オブジェクトは互いに跳ね返りません。この値はジッタも減少させるため、非常に低い値に設定することは推奨されません。

デフォルトではBounce Thresholdが0.2になっており、ボールの速度0.15がちょうど閾値を下回っていたため跳ね返らなくなっていた。

#解決策
UnityメニューのEdit->Project Settings->Physicsを開き、Bounce Thresholdの値を小さくする。今回はボールの速度が0.15なのでそれより小さい0.1に設定した。


![Screen Shot 2021-11-24 at 21.27.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239014/21993dd4-b773-c89d-fbaf-4e0db03df82a.png)

結果、下のgifのように見事宇宙飛行士が宙を舞うようになった。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239014/2f58585c-d520-742f-6888-537d1b964277.gif" width="200">

#余談
Bounce Thresholdの他にSleep Thresholdという値もある。
>**Sleep Threshold**
>キネマティックでないリジッドボディがスリープ状態になる可能性があるグローバルエネルギーの閾値を設定します。リジッドボディがスリープ状態のときはフレーム毎に更新されるわけではないため、リソースの負担は少なくなります。 リジッドボディの運動エネルギーを質量で割った値がこの閾値を下回る場合、スリープの候補となります。

運動エネルギーを参照するため、速度を更に遅くしたり質量を下げたりすると引っかかる可能性がある。

#環境
- macOS Big Sur
- Unity2019.4.28f1
- AR Foundation 3.1.0
openSUSE tumbleweed にfish入れる

作業環境の効率向上を図りたくて、（といっても補完強化して楽したいだけ）
まずはshell見直そうと考えて、何が良いかなーって思ってたら。

fish良いよ！！！っていろんなところで見かけるので、
入れてみようかな、なんて思って入れてみた。
openSUSEで入れるのってつまづくかなーって思ったけど、
全然だったのだけれど、
誰かの役に立てればと思って書き残します。

本当に簡単だったよ



# 1. chromiumを起動する

なぜかあとから入れたChromeだとうまくいかなかった。 
若干カスタマイズされてるんだろうなーなんて思ってた。

# 2. openSUSEソフトウェアにアクセス

openSUSE ソフトウエア - https://software.opensuse.org/package/fish
↑ここからが一番早かったです

# 3. １クリックインストールを押す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43608/c5fe0215-4b7f-6c0c-7252-599df54a16c4.png)

もうこれだけだった。あとはDiscoverっぽいものが起動するからインストール押すだけ。

# あとがき

導入だけだったら本当に簡単だった。
あとは標準shellをfishに変えて、
必要ならfisher入れてって感じ。
fisherについてはまだ何もしてないからよくわかってません。
パッケージ管理ができるとかどうとかプラグインがうんぬんかんぬん。
とりあえずzshよりも標準の情報が多めでありがたいなと、
zshやbashは設定ファイルさえあればいろいろできるけど、
標準でごちゃごちゃできる環境ってのは非常にありがたいので、
これからfishで使っていきたいと思います。
また何かあれば、では。
sqlalchemy パスワードに＠を含む場合の対処方法

# 概要
sqlalchemyとを使用してDBに接続する際に、パスワードに＠を含む場合の対処方法です。
パスワードに@が含まれている場合、URLの @ と区別が出来ずエラーになります。

# 対処方法
quote_plusを使用してパスワードをURLエンコードしてから使用します。
URLエンコードすることでパスワード中の @ が %40 にエンコードされます。

```python:python
from urllib.parse import quote_plus

import pandas as pd
import sqlalchemy as sa

user = 'username'     # ユーザ名
password = 'p@ssword' # パスワード
host = 'localhost'    # ホスト名 or IP
db = 'database'       # データベース
port = 3306           # ポート

# パスワードをURLエンコード p@ssword -> p%40ssword
password = quote_plus(password)
url = f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}?charset=utf8'

# engine作成
engine = sa.create_engine(url, echo=False)

# pandasのread_sql関数にselect文とengineを指定する
query = "select * from table"
df = pd.read_sql(query, con=engine)
```
realsense d435i / d455をつなげたときの、" frame didnt arrived whithin 5 seconds"の対処

#発生した問題
realsenseと実機をつなげたとき、realsense-viewer で接続すると、5s間frameが届かないとエラーを吐かれた。

#解決法
いろいろ試した結果、カメラとpcをつなげる線を付属のものに変えたらうまく動いた。
3mの長いケーブルを使っていたが、それが問題だった。
d435iなどではぎりぎり動いたが、d455になると全然動かなかった。
大量の情報がカメラから送られてくるので、長いといろいろ問題らしい？

※一番いいケーブルにしても動いた。
よって、ケーブルは短いほうがつながりやすいが、長いとつながらない確率が高くなると思われる。
PHP 大文字 小文字を区別せずバイナリを使って文字列を比較するメソッド

# 目的

- PHPにてバイナリを用いて文字列を比較する方法をまとめる

# 情報

- 下記のサイトを用いてこちらに記載するソースの検証を実施した。
    - [https://paiza.io/ja](https://paiza.io/ja)

# 方法

- `strcasecmp()`メソッドを使用して比較する。
- ASCII文字だけが、大文字小文字を区別せず比較されるらしい。
- `$str_1`と`$str_2`をそれぞれ比較してみる。
- `$str_1`には「aaa」を、`$str_2`には「AAA」を格納し下記のように比較してみる。

    ```php
    <?php

    $str_1 = 'aaa';
    $str_2 = 'AAA';

    echo strcasecmp($str_1, $str_2);
    // 0と出力される。
    ```

- 上記の処理は大文字小文字は関係なく、同一文字かを評価するので同一（つまりintの'0'）が返される。

# その他の検証

- `$str_1`には「aaa」を、`$str_2`には「bbb」を格納し下記のように比較してみる。

    ```php
    <?php

    $str_1 = 'aaa';
    $str_2 = 'bbb';

    echo strcasecmp($str_1, $str_2);
    // -1と出力される。
    ```
- バイナリ比較して第一引数 < 第二引数となる時は負の数が返されるらしい。
- `$str_1`には「bbb」を、`$str_2`には「aaa」を格納し下記のように比較してみる。

    ```php
    <?php

    $str_1 = 'bbb';
    $str_2 = 'aaa';

    echo strcasecmp($str_1, $str_2);
    // 1と出力される。
    ```
- バイナリ比較して第一引数 > 第二引数となる時は正の数が返されるらしい。
- `strcasecmp()`メソッドを使って第一引数と第二引数の文字列のバイナリ差分でif分岐を行いたい場合、下記の様に記載する。

    ```php
    <?php

    if( strcasecmp($str_1, $str_2) === 0){
        // $str_1と$str_2が一致している時の処理
    }
    ```
# 参考文献

- [https://www.php.net/manual/ja/function.strcasecmp.php](https://www.php.net/manual/ja/function.strcasecmp.php)
マイグレーションエラーについて

railsでデータベースを用意する際に、

```
$ rails generate scaffold ・・・
```

コマンドなどでマイグレーションファイルを作成した後、

```
$  rails db:migrate
```

でデータベースの変更を反映しないと、
ActiveRecord::PendingMigrationError
マイグレーションエラーとなってしまいます。
![2021-11-25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2222596/bdbfc058-ca2e-1d2b-dcf8-a7fe9c9260cd.png)



忘れないようにしましょう。
（偉そうにすみません。自分が忘れていたので。）

以上
Python: C# の GroupBy(g=> g).Where(w=> w.Count() == 2) の実現方法

# 背景
Python だと全然よくわからず・・調べた記録

```c#:C#-LINQでの取得方法
list.GroupBy(g=> g).Where(w=> w.Count() == 2)
```
python は書きやすいと思っていたので、Linq のような簡単な方法があるんじゃないのかなぁ・・と思い調べたが見つからず・・

# 試行
## groupby
普通にこれでやれると思ったら、思ったように取得出来なかった・・
使い方が悪いのかと試行錯誤したあとで、
~~以下の Sample で、同一の文字列突っ込んでみたら別グループにされてしまったので、諦め~~

https://www.tutorialspoint.com/python-grouping-similar-substrings-in-list

sort してないからだったらしい。再度やってみたらちゃんとでけました :laughing: 

```python:byCollection
cards = [1, 2, 5, 8, 5, 2, 2]
groups = []
cards.sort()    # sort してないと groupby は効かない
for keyword, group in groupby(cards, lambda card: card):
    currentGroup = list(group)
    if (len(currentGroup) == 2):
        groups.append(currentGroup) 
```

## ゴリゴリ・・
結局、以下で実現。

1. Unique Key の抽出
    1. Key で Filter<br>~~<code>x[1]</code>を指定しないといけないのも感覚的じゃない・・~~<br>items() → values() で不要にはなりました。@tafadfak さんありがとう :laughing: <br>これ debugger で止めても分かんなかったけど、VS の intelisence なら出るのかな？
1. 中身の長さで Filter

```python:byCollection_二版
cards = [1, 2, 5, 8, 5, 2, 2]
groupedValues = {uniqueValue:[inputValue for inputValue in cards if inputValue == uniqueValue] for uniqueValue in unique(cards)}
listPairs = filter(lambda x: len(x)==2, groupedValues.values())   
print(list(listPairs))  
```
```python:byCollection_初版
cards = [1, 2, 5, 8, 5, 2, 2]
groupedValues = {uniqueValue:[inputValue for inputValue in cards if inputValue == uniqueValue] for uniqueValue in unique(cards)}
listPairs = filter(lambda x: len(x[1])==2, groupedValues.items())    # x[0]: Index, x[1]: value(s) 
print(list(listPairs))  
```

取得結果
> [(5, [5, 5])]

## pandas
ちょっと諦めきれなかったので、調査中に見つけた有名な Library で試してみた。
ゴリゴリのよりは、まだ分かりやすい・・。でも、groupby の指定がなんか感覚的に違和感・・
基本的に行列の処理用だから、Column 名や Index でグルーピングなんだろうな、とは

```python:byPandas
df = pd.DataFrame([1, 2, 5, 8, 5, 2, 2])
grouped = df.groupby([0])
print(grouped.filter(lambda x: x.size == 2))
```
取得結果

||0|
|-|-|
|2|5|
|4|5|

https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.filter.html

# keyword
how to retreive 'groupby' when same data exists in the list
Databricksにてdbutils.fs.rmにより削除したdbfs上のファイルをos.path.existsで実行する際の誤検知への対応方法

## 事象
Databricksにてdbutils.fs.rmにより削除したdbfs上のファイルをos.path.existsで確認すると、誤検知しました。下記画像がその際の画面であり、dbutils.fs.lsで確認するとファイルが存在しないにも関わらず、os.path.existsで確認するとTrueがリターンされてしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/d8a8c394-f2f8-371a-545a-73327696b3d7.png)

## 再現方法

```python
src_path = '/databricks-datasets/tpch/data-001/region/region.tbl'
out_path = '/tmp/delete'
 
oup_path_for_py = '/dbfs' + out_path
 
# dbfsにコピーしたファイルを保存
dbutils.fs.cp(src_path, out_path, True)

# ファイルを削除
dbutils.fs.rm(out_path, True)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/01900dd7-0828-f5ac-2fa3-671ff730b9f0.png)


```python
# dbutilsにてファイルの存在チェックを行う。想定は、ファイルが存在しないことによるエラーが発生
try:
    dbutils.fs.ls(out_path)
except Exception as e:
  print(e)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/8b1a99aa-3e36-7856-13b6-71e68338d079.png)


```python
import os

os.path.exists(oup_path_for_py)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6df265c6-209d-0edc-3c18-98f477e3190e.png)


## 対応方法
情報がキャッシュされてしまうことが原因であるようで、1秒のスリープを実装することで誤検知しなくなるようです。dbutils.fs.lsを用いて存在チェックを行う方法もあるため、下記の対応方法を紹介します。

1. sleep関数で1秒待ってから実行
2. dbutils.fs.lsを用いた存在チェックの関数を作成


### 1. sleep関数で1秒待ってから実行

```python
import time
import os

time.sleep(1)
os.path.exists(oup_path_for_py)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/94351db6-51d6-7008-d9a1-e7b2ac463cb2.png)


### 2. dbutils.fs.lsを用いた存在チェックの関数を作成

```python
def fs_is(path: str):
    return_bool = True
    # dbutils.fs.lsにてエラーとなる場合に、ファイルが存在しないというリターンを返す
    try:
        file_list = dbutils.fs.ls(path)
    except:
        return_bool = False

    return return_bool


fs_is(oup_path_for_py)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/a69b845e-994a-03fd-eebf-15799afea335.png)
スッキリわかるSQL　５章　問題5-3（理解できなかった練習問題を噛み砕く）

<h2>初めに</h2>
前回に引き続き、スッキリわかるSQLで理解できなかった練習問題を、
頑張って調べて理解できるようにしていきます。

<h2>問題</h2>
スッキリわかるSQLの５章問題5-3の２です。

<h2>回答</h2>

```
SELECT 受注日,受注ID,文字数,
CASE COALESCE（書体コード,'1')
     WHEN '1' THEN 'ブロック体'
     WHEN '2' THEN '筆記体'
     WHEN '3' THEN '草書体' END AS 書体名, 

CASE COALESCE（書体コード,'1')
     WHEN '1' THEN 100
     WHEN '2' THEN 150
     WHEN '3' THEN 200 END AS 単価,　続く・・・
```

<h6>CASE COALESCE（書体コード,'1')がわからない！！！！</h6>

<h4>COALESCEはNULLを明示的に表示する</h4>
COALESCE(メモ,'（メモはNULLです）') という記述があれば、
メモ列のNULLの値が（メモはNULLです）になる。
その考え方でいくと、

```
CASE COALESCE（書体コード,'1')は、
書体コードにNULLがあれば'1'を入れるということになるんですね。
```

<h2>参考にした記事</h2>

https://qiita.com/tochisuke221/items/49d1b16672aa3ee2bfbf
MySQLからデータを取得してpandasで使用する

# 概要
sqlalchemyを使用してDBに接続し、selectの結果をpandasのDataFrameとして取得する方法です。

# 使用方法
## インストール
sqlalchemyとPyMySQLがインストールされていない場合はpipでインストールします。

```console:console
pip install sqlalchemy
pip install PyMySQL
```

## DB接続＋データ取得
DBに接続するには create_engine() 関数にURLを指定します。
pandasのread_sql関数にselect文とcreate_engineで作成したengineを指定し実行すると、sqlの実行結果がDataFrameとして取得できます。

```python:python
import pandas as pd
import sqlalchemy as sa

user = 'username'     # ユーザ名
password = 'password' # パスワード
host = 'localhost'    # ホスト名 or IP
db = 'database'       # データベース
port = 3306           # ポート

url = f'mysql+pymysql://{user}:{password}@{host}:{port}/{db}?charset=utf8'

# engine作成
engine = sa.create_engine(url, echo=False)

# pandasのread_sql関数にselect文とengineを指定する
query = "select * from table"
df = pd.read_sql(query, con=engine)
```
JavaScriptDOM編

#DOMとは？
DOMとは、プログラムからHTMLやXMLを操作するための仕組み。
ツリー構造を持っていて、各要素をそれぞれをノードと呼ぶ。
空白や改行もノードになる。

#要素を操作しよう
##IDの要素を取得する
```
document.getElementById('ID名')
```

##文章から特定の要素を取得する
```
document.querySelector('要素名')
```

中身を帰る場合は以下。
```js
document.querySelector('要素名').textContent
```

##何秒後に呼び出す
```
setTimeout(update,1000);
```

#複数の要素を変更
```js
document.querySelectorAll('要素名')[n].textContent
```
nは前から何番目を表す。

※DOMツリーの階層から指定することもできる。


#addEventListener();
やりたい内容を（）に入れる。

#タイトル要素の変更
```js
.title = '文字';
```

#CSSの変更
　.style.変更したいプロパティ

※プロパティ名にハイフンがある場合は、二文字目の冒頭を大文字にする。

#classNameを設定する
アクションがあるときに、クラスごと変更する。
```html
<style>
 .my-color{
  color:red
 }
</style>
```

```js
.className = 'my-color';
```

この記載方法だと、既存のCSSが上書きされてしまうため、
.classList.add('my-color')にすると加えられる。

また、条件分岐を使ってもできる
```js
if(~classList.contain('my-color') === true){
 ~.classList.remove('my-color');
}
```

#カスタム要素を使う
HTMLでは、自分で作った要素を使うことができ、これをカスタム要素と呼ぶ。
「data-」から始まる。
JSでは
〜.dataset.[data-〇〇の〇〇部分を記入]
と記入。

#要素を作ってDOMに追加
１、要素を作る
```const item = document.createElement('li');
```

２、中身を作る
```
item.textContent = 'item2';
```

３、DOMに追加
・親要素をauerySelectorで取得
・追加はappendChild();

#複製した要素を追加
1,コピー対象の要素を取得

２，要素をコピー
　→cloneNode(true);

3,親要素とコピー対象を置く直後の要素を取得
→insetBefore(コピーした要素,直後の要素);


#要素の削除
１，取得
２，removeメソッド
もしくは、親Node.removeChild(削除するNode);


#input要素の活用
1,リストに追加する要素作成(li)

2.inputした要素を定義(text)

3.リストに追加する内容をinputにする
li.textContent = text.value;
入力された値はvalue属性で取得できる。

4.appendChild(li)で追加

5.text.value ="";
text.focus();

#selectボックスで行う
ボタンを押したら下に記載される
１．liを作成
→createElement('li')

２．セレクト要素を取得
→querySelector('select');

３．li.textContent = color.valueにする


#ラジオボタン
ポイントは２つ。
①セレクトボックスと違って一つにまとまっていないので、まずはquertySelectorAll()を使ってすべてのinput要素を取得

②要素にチェックが入っているかはcheckedプロパティで調べられる。

#他のイベント
ダブルクリック＝dbclick
マウスを動かしたら＝mousemouse
【MySQL】シェルスクリプトでMySQLのSQLを実行する

シェルスクリプトでMySQLのSQLを動かそうとしたら詰まりに詰まったので備忘録として

### やりたいこと
・ rootユーザでシェルスクリプトからmysqlのSQLを実行する
・ 対話処理は悲しいのでやりたくない

### 環境
・ホストOS: Windows11
・ゲストOS: Ubuntu20.04
・MySQL 8.0.26
・bash

### ソースコード

```bash
#!/bin/bash

service mysql start
mysql -u root --password='password' -e "drop database if exists dbname;"
mysql -u root --password='password' -e "create database dbname;"
mysql -u root --password='password' dbname < file.sql

```

このシェルスクリプトを実行すると ```mysql: [Warning] Using a password on the command line interface can be insecure. ``` という警告文が表示されて処理が失敗しました。

どうやらスクリプトやコマンドにパスワードを直書きすると怒られるようです。

### 解決方法

パスワードを外部ファイルに切り出してそれを ``` --defaults-extra-file``` オプションで読み込むと解消できました。

```/etc/mysql/my.cnf

[client]
user = root
password = password
# 今回はスクリプトを実行するホストとDBのホストが同一なのでhostnameは省略
```

パスワードが書かれたファイルなので権限は最低限にしておきます。

```
chmod 600 /etc/mysql/my.cnf
```

スクリプトを以下のように書き換えて再度実行します。

```create_database.sh
service mysql start
mysql --defaults-extra-file=/etc/mysql/my.cnf -u root -e "drop database if exists dbname;"
mysql --defaults-extra-file=/etc/mysql/my.cnf -u root -e "create database dbname;"
mysql --defaults-extra-file=/etc/mysql/my.cnf -u root dbname < file.sql

```

警告が出ずに正常にデータベースが作成されました。


### まとめ
この方法だと自動でデータベースを操作できるので定期的なバックアップやデータベースのメンテナンスも実現できそうですね。
Tang-Nano-4KのカメラとＨＤＭＩ出力の改良

#目的
　Tang-Nano-4Kを購入した。先ずはサンプルソフトの動作確認。
　Ｌチカ、まあこんなモノだろうな。
　カメラとHDMI、な、なんだこのショボさは。
　Tang-Nano-4Kの性能、活かせてないじゃないか。
　◆◆◆　よし、も少し真っ当な画像を表示させよう　◆◆◆
　と言っても、それ程の技術も持ってないので、出来る範囲と言うことで。

#経緯
　[購入経緯なんかは前回に書いた。](https://qiita.com/hi631/items/e3a557d6f8b9fcb491c2)
　コスパの良さには驚いたが、サンプルソフトがちと貧弱。
　HDMI出力は1280x768、カメラなんて640x480、しかもモノクロだよ。
　そこで目標として、下記を掲げる。
　　◇カメラ画像のカラー化
　　◇HDMI出力のＨＤ(1920x1080)化
　　◇カメラの高解像化
　[実施結果をGithubに上げておいた](https://github.com/hi631/tang-nano-4K/tree/master/dk_video_HD)ので、興味あったら見てね。
　　※カメラはＨＤ化出来なかった、残念。

#開発環境
　Tang-Nano-4K　　　　　　※無ければ話にならないな。
　GOWIN EDA Education版 　※verilogのコンパイルに必要。
　HDMIモニター　　　　　　※確認には必要だろう。

#カメラ画像のカラー化
　出来上がってみれば意外と簡単。
　元の画像出力はRAW(赤緑青を色毎に8bit)形式に設定されてる。
　出力形式をRGB565(つまり赤5bit、緑6bit、青5bitの16bit)形式に変更する。
　変更はOV2640_Registers.vを書き換えれば出来るが、データの取り込みを16bit単位にする必要が有る。
　カメラからの8bitデータを2byte単位で纏め、クロックも1/2にすればカラー化が完了。
　　※サンプルソフトの作成年は2019年、手間を省いたと言う事だろう。役には立ったが。
　　※OV2640の取説は中身が薄い。データ形式などは過去のOV7670等の方が詳細。

#HDMI出力のＨＤ(1920x1080)化
　ＨＤ化はパラメーターの設定変更で出来ると思ったが、其れだけではモニターに弾かれた。
　クロックを 74.25MHz -> 148.5MHz に倍化する必要が有る。
　しかし、PLLは2個しかなくてどちらも使用中だよ。
　そこで、DRAMのクロックを 159MHz -> 148.5MHz に変更。7%低下するがそこは我慢の子。
　video_top.vの先頭の`ifdef USE_HD を有効化すればＨＤ表示になります。
　　※画面はＨＤ化出来たが、デジタルなのにノイズが乗るのは何故だ。

#ＰＬＬの変更方法
　PLLの設定変更に当たり、元の設定が判らないよ。　※企業なら文書化しているだろうが。
　GW1NSR-LV4CのPLL如き、ご承知の方は承知なんだろうが、
　パラメーターを弄って結果を確認した所、＊PLL＊.vへの記載のキモは、
　　FCLKIN　　　入力周波数
　　IDIV_SEL　　入力を分周
　　FBDIV_SEL 　分周結果を逓倍(多分feedback)
　FCLKIN ÷ IDIV_SEL(+1) × FBDIV_SEL(+1) = 出力周波数だと思う。
　元の設定は 27 8 52 なので、27/(8+1)*(52+1)=159MHzの設定だったと判る。
　　※CLKOUTDはCLKOUTをDYN_SDIV_SELで分周した出力、自由に選べないとは。

#カメラの高解像化
　これはパラメーターを設定すれば完了するはずだったのだが...、
　800x600,1024x768は動作したが、それ以上は表示出来なかった。
　OV2640_Registers.v で USE_640,USE_800,USE_1024 の何れかを有効にしてください。
　　※パラメーターはaraduinoのやつを参考にしました。
　　※カメラを1280x1024に設定しても、1280個のデータが送られてこない。
　　　設定ミスだとは思うが、何処が間違っているか判らん。

#追記
　前回は上記迄書いたが、その後多少分かった事が有るので追記する。
　Tang-Nano-4Kに搭載のHyperRAM(名前が大げさだと思うがDRAMの商品名らしい)のカタログスペックは、
　　駆動クロック　　= 166MHz(200MHzも有るらしい)
　　ＤＲＡＭ帯域幅　= 166×2=333MB/S
　　理論効率　　　　= 74%(128Byteバーストアクセス)
　　理論帯域幅　　　= 333×0.74=246.42MB/S
　使用するには読み書きが必要なのでその半分、123MB/S当たりが実用上限だろう。
　表示を1280x720 60fps 3Byte/Pixcelとした場合、166MB/Sなので破綻している。
　表示を1280x720 60fps 2Byte/Pixcelとした場合、111MB/Sなので表示可能になる。
　勿論、カメラ側からのアクセスは30fps程度なので、これ以上でも利用の可能性はある。

　カメラを1280x1024に設定した場合、960ラインを超えるあたりで表示不能になったが、ここで帯域オーバーしたのだろう。
　1980×1080(2Byre/Picel)の場合は、帯域が257MB/S必要なので、表示だけで破綻していたわけだ。
　　※だから、デジタルなのに画面にノイズが乗っていた訳だな。
　でも、1Byte/Pixcelにすれば帯域は128MB/Sとなるので、十分表示可能だな。
　

#感想
　[前回の宿題の回答なのですが、](https://qiita.com/hi631/items/e3a557d6f8b9fcb491c2)　力及ばす完遂しませんでした。
　もう少しは頑張るつもりですが、多分このまま放置だと思います。
　　※表示が無理な事が判りました。
　なお、上記記載内容は全て無保証であり、各自の責任においてご利用願います。
husky v4 -> v7に移行する方法

## huskyをv7に移行すると何が変わるのか？
- [typicode公式ブログ](https://blog.typicode.com/husky-git-hooks-javascript-config/)に書いてある
- ものすごく要約すると、「`.git/hooks`・`package.json`・`.huskyrc.js`などに設定が散らばっていて不便だったけど、今後は`.husky`配下にまとまります」ということ

## v5とv6は使わないの？
- v5はライセンスが違うので商用利用が実質不可
- v6はライセンスが戻っているけど、v7だと公式の移行ツールがあって便利
- 参考記事：[husky(v4, v6) と simple-git-hooks どちらを使うべきか](https://zenn.dev/t28_tatsuya/articles/should-i-use-husky-or-simple-git-hook)

## 公式ドキュメント
「Migrate from v4 to v7」の章がわざわざ用意されている。優しい。
https://typicode.github.io/husky/#/

## この記事の想定読者
他の記事の書いてある通りに、公式ツールを使っても[yes/no]で答える質問が表示されなくて困った人（自分）
ちゃんとツールが色々質問してくれた人は、この手順踏まなくてもよいと思います

## 移行手順
### 1. husky v7をインストールする
[typicode公式のmigrationツール](https://github.com/typicode/husky-4-to-7)を使って、環境に応じて適切なコマンドを叩く。
自分はyarn2だったので下記。

```
yarn add husky@latest --dev \
  && npx husky-init \
  && npm exec -- github:typicode/husky-4-to-7 --remove-v4-config
```

### 2. 以下の差分が出る事を確認する
```
・リポジトリ直下に`.husky`ディレクトリが作成される
・package.jsonのhuskyのバージョンが7.0.0になる
・package.jsonに "prepare": "husky install"が追加される
```

### 3. v4のconfigをv7に移行する
これまで`package.json`にあった設定を、v7のために`.husky`配下に移行する。
`HUSKY_GIT_PARAMS`は廃止されたので、`$1`などに変更すること。
commitlintを使っている人は、`-E HUSKY_GIT_PARAMS`だったのが、`--edit $1`に変わってたので追従すること([v5に変わったときのコミット履歴](https://github.com/conventional-changelog/commitlint/commit/763085cde9e89f51fa35cc99c305b1c873db7829))

```
yarn husky add .husky/pre-commit 'yarn lint-staged' & \
yarn husky add .husky/pre-commit 'yarn test --onlyChanged' & \
yarn husky add .husky/commit-msg 'yarn commitlint --edit $1'
```

## 4. v7のデフォルト設定を削除する
サンブルとして`.husky/pre-commit`に`npm test`が最初から入っているけど、邪魔なので削除する。

## 5. v4の設定を削除する
`package.json`等からhuskyの設定を全部削除する。
実はv7でも旧来の設定方法でいけるんだけど、このままだとちゃんと移行できたか分からないので削除する。


## おしまい
公式のmigrationツールの冒頭にも書いてあるけど、ツールは実行しても部分的にしか変わらない。
設定まで移行するのをお忘れなく。
【Vuex】ストアの作成

#はじめに
こんにちは！
今回は【Nuxt.js】ストアの作成についてアウトプットしていきます！

#Vuexとは
`Vuex`とは、状態管理を行うためのライブラリです。アプリケーションの状態を１つの場所に置いて管理する。
（イメージ）
サーバーという夢想に広がるマンションの1室を借りて物置部屋にしている感覚。
インターネット版物置。

【メリット】
・データの流れを見えやすくすることによってバグの少ない
・デバックの少ない状態管理を実現すること。

【デメリット】
・コードが冗長になる。

【状態管理の例】
□ECサイトのショッピングカート機能
　・最初カート内は商品が入っていない空の状態
　・ユーザーがカートに商品を追加すると、カートに商品が入った状態になる。
　・ユーザーが決済を行なって購入完了するとカート内は商品が入ってない状態。

【vuexの利用タイミング】
中規模から大規模のSPAを構築する場合。


#ストア(store)作成

【storeとは】
各コンポーネントで共通の保管場所であるストア（store）を実装します。

storeファイルの中にindex.jsを作成します。（index.jsは決まり事）

```index.js
import Vuex from 'vuex'
// ⏫vuexのインポート

// ⏬vuex.storeオブジェクトを作成して利用
const createStore = () => {
    return new Vuex.Store({
        //⏬stateに値を保管する処理 
        state: function() {
            return {
                message: 'Hello Vuex!'
            }
        }
    })
}
// ⏬作成したcreateStoreをexport defaultでexportし、使用できるようにする。
export default createStore
```

・vuexのインポート
・storeを作成し、stateに値を補完する処理を記述。
・エクスポート

といったことをindex.jsではやっていきます。

次にpages⏩index.vueを実装していきます。

```index.vue
<template>
  <section class="container">
    <div>
          <!--⏬storeフォルダのstateの値messageを利用することができる-->
        <p>{{ $store.state.message }}</p>
    </div>
  </section>
</template>

<script>

export default {
}
</script>
```

`<p>{{ $store.state.message }}</p>`とすることで`storeフォルダのstateの値messageを利用することができる`という風になります。


#最後に
今回はVuex.ストアの作成についてアウトプットしました。
今回の記事を読んで質問、間違い等あればコメント等頂けると幸いです。

今後ともQiitaにてアウトプットしていきます！

最後までご愛読ありがとうございました！
スッキリわかるSQL　５章　問題5-2 （理解できなかった練習問題を噛み砕く）

<h2>初めに</h2>
スッキリわかるSQLを学習中ですが、練習問題に解説がなく、
読み返しても全く理解できない問題がありましたので、
ネットの力を借りつつ、解答&解説をできるようにしていきたいと思います。

<h2>ざっくりと問題の紹介</h2>
suzukitakashi@mailsample.jpみたいなメールアドレスの登録されてるテーブルがあります。
.jpなら日本だし.cnなら中国ですよね？
メールアドレスみて、それ判断して国名に　jpなら日本、ukならイギリス~みたいに国名登録してね　という感じです。
詳しくは、スッキリわかるSQLのP166を参照ください。

<h2>意味わからなかった回答</h2>

```
UPDATE 回答者
SET 国名 = CASE SUBSTRING(TRIM(メールアドレス),
                          LENGTH(TRIM(メールアドレス))-1, 2)
             WHEN 'jp' THEN '日本'
             WHEN 'uk' THEN 'イギリス'
             WHEN 'cn' THEN '中国'
             WHEN 'fr' THEN 'フランス'
             WHEN 'vn' THEN 'ベトナム' END
```

WHEN以下はわかるけど、それ前の作業がわかりませんでした。
「-1,2」のところでメールアドレスの後ろの２文字をピックしてるのはわかるのですが、
なんでTRIMが２回？そこでLENGTH?

とりあえずTRIMは置いておきます。

<h4>SUBSTRINGは文字の一部を抽出</h4>

<h6>わからない時は具体的な数字で確認してみます。。</h6>
suzukitakashi@mailsample.jpの後ろのjpを抽出したいとします。
文字の一部を抽出するのはSUBSTRINGです。

```
基本構文は
SUBSTRING(文字列を表す列,抽出開始位置,抽出する文字の数）で
これに当てはめると、suzukitakashi@mailsample.jpは、
SUBSTRING(メールアドレス,26,2)となるわけですね。
```
ここで出てくる26はメールアドレスの長さから-1引いた数と等しい。
その結果、```LENGTH(TRIM(メールアドレス))-1,```が現れるというわけですね。


<h2>参考にした記事</h2>

https://qiita.com/ume-san/items/00ab80f12bb9fe3699fb
最新のmacOSをインストールしたくない時の対処法・過去のOSのインストール方法

# はじめに
業務で使用しているPCはセキュリティの関係上すぐに最新のOSにしてはいけないが、1つ前のバージョンなら出来るのになーという時がある。
結論を言うと希望のOSをインストールする為のページが準備されていた。

## 以前のバージョンの macOS を入手する
このページの`Mac で Safari を使って macOS をダウンロードする`から`AppSotre`経由でダウンロード可能。

https://support.apple.com/ja-jp/HT211683

ちなみに、Xcode13を使いたいが、Montereyは会社的にまだNGということでBig Surに移行。
`最小要件とサポートされるSDK`についてはこちら。

https://developer.apple.com/jp/support/xcode/
LR法



# LR 法

この呼び方は一般的な用語ではないですが、ある場所でよく使っていたのでここでもそのまま使っています [^name] 。

[^name]: Dancing Links と呼ばれるものが近そうですが、目的などが少し違いそうな気がします。



## やりたいこと

$N$ 要素からなる集合 $\lbrace 0,\ \cdots,\ N-1 \rbrace$ がある。このとき次のクエリを処理してください。

- ${\rm delete}(i)$: 要素 $i$ を削除する
- ${\rm left}(i)$: $i$ 未満の要素の中で最大の要素の値（なければ $-1$ ）を返す
- ${\rm right}(i)$: $i$ より大きい要素の中で最小の要素の値（なければ $N$ ）を返す

すでに削除された $i$ が引数として与えられないことが保証されるパターンと与えられる可能性があるパターンがあります。ここでは後者でも対応できるものを想定しています。



### 平衡二分木

平衡二分木があればすべて処理できます。ややオーバーキルですが、組み込みで平衡二分木がある言語ならそれで十分かもしれません。


## 実装

### データの持ち方

各要素 $i$ に対して、その左隣の要素 [^left] と右隣の要素 [^right] を配列で記録します。本記事では、それぞれ配列 $L$ および $R$ で表します [^LR] 。また $i$ がまだ削除されていないかどうかを表す長さ $N$ の配列 $X$ も用意しておきます。最初はすべての $0\le i\lt N$ について $X[i] = 1$ です。 $i$ が削除されたら $X[i]=0$ になります。

[^LR]: LR 法という名前の由来です。
[^left]: それより小さい要素の中で最大のもの
[^right]: それより大きい要素の中で最小のもの


### 経路圧縮

Union Find の実装と同様に、一度通った経路は圧縮しておくと次からのクエリで同じ部分を再度通らずに処理できます。

### コード

Python でのコード例を書いておきます。実際の使い方は「例」の項を参照してください。

```test.py
class LR_trick():
    def __init__(self, n):
        self.n = n
        self.L = [i - 1 for i in range(n)]
        self.R = [i + 1 for i in range(n)]
        self.X = [1] * n
    
    def delete(self, i):
        self.X[i] = 0
    
    def left(self, i):
        i = self.L[i]
        li = []
        while i >= 0 and self.X[i] == 0:
            li.append(i)
            i = self.L[i]
        for j in li:
            self.L[j] = i
        return i
        
    def right(self, i):
        i = self.R[i]
        li = []
        while i < self.n and self.X[i] == 0:
            li.append(i)
            i = self.R[i]
        for j in li:
            self.R[j] = i
        return i

```


### 計算量

上の実装の場合、構築は $O(N)$ 、削除クエリは $O(1)$ です。
$\rm left,\ right$ クエリは、削除された要素が与えられない場合はならし $O(1)$ です。与えられる可能性がある場合はならし $O(\log N)$ になる気がします。ちゃんと証明していないので違っていたら教えてください。


## 例（ネタバレ注意）

### 例 1
<a href = "https://atcoder.jp/contests/abc218/tasks/abc218_h">ABC 218-H</a>
<a href = "https://atcoder.jp/contests/abc218/submissions/27471515">AC コード</a>

DeletableHeapq と LR 法を使うと実装がラクですね。
Apacheで特定のディレクトリについてPHPを無効にする

以下の設定を\<Directory\>ディレクティブ内に記載する。

```apache:httpd.conf
<Directory "/var/www/html/foo/bar">
   php_value engine off
</Directory>
```

有効にしたい場合は

```apache:httpd.conf
<Directory "/var/www/html/foo/bar">
   php_value engine on
</Directory>
```

より深い階層の設定が有効になるので、上記の組み合わせで「全体で無効、特定のディレクトリで有効」という設定も可能。


ちなみに以下のように記載するという記事もあったが、自分の環境ではうまく動かなかった。

```apache:httpd.conf
<Directory "/var/www/html/foo/bar">
    RemoveType .php
</Directory>
```
vue-draggableでドラッグ中に位置がずれる問題の解消方法

#結論
draggしたい要素を子コンポーネントに分割しているようなケースで、子コンポーネント内部に非表示要素などが含まれているとその高さ分ずれるっぽい。


# 問題
vue-draggableでドラッグ中に、カーソルの脇に移動しているオブジェクトが表示されず、カーソルとズレた位置にオブジェクトが表示されてしまっていた。

追記：画面サイズがある程度大きくなるとずれる。おそらくレスポンシブ関連が影響している。この点は未解決（調査中）

# 解決方法
draggable属性を使用する

```vue
        <draggable
          v-model="items"
          handle=".item-handle"
          @end="updateItemSort"
          draggable=".item" //drag対象を見つけるクラスを指定
        >
          <v-card
            v-for="item in items"
            :key="item.id"
            flat
            rounded="lg"
            outlined
            class="mb-5 item"　//drag対象であることの明示としてクラス指定
          >
            <ChildComponent
              :item="item"
            />
          </v-card>
        </draggable>
```
Reactのことをざっくりメモ

## きっかけ
Reactを書いていて、〇〇とは何か。
など根本的なことを理解していないのではと不安になったのでメモ程度に書いてみました。
ここ違います！などあればコメントお願い致します。


## Reactの特徴
まず、javascriptの**ライブラリ**である。

* **仮想DOM**を利用していること
 * 仮想DOMとは、情報が書き変わってもすぐにブラウザ憑依するのでなく、一旦仮想のDOMにその変化を加えて、差分があった部分のみ変更するこの仕組みのことです。また、仮想DOMから実際のDOMに反映することで処理スピードが速く、比較的高速に切り替えが可能となっています。（ここではあくまでReactにおける仮想DOMについてです。）

* **JSX**を使用できる
 * JSXとは、javascript XML。スクリプトとDOMを一緒に記述できるもの。（Vueでも使われています。）
　
* **コンポーネントベース**のUI
 * 他のライブラリでも採用されているものではあります。 コンポーネントはザックリといえば、構成要素のことで、UIを部品に見立てその部品ごとに作成することで管理と再利用性を高めることができます。大規模なシステムであれば恩恵が大きいと感じるかと思います。

##　Class component と　Functional　component
この２つの使い分けですが、基本何か理由がなければ**Functional　component**を利用することをお勧めします。前まではstateを使用するにはclassのみしか選択肢がなかったですが今はどちらでも使えるので問題ありません。理由はいくつかあります。

* まずReactのお偉いさん方がこちらを使用するように推奨しています。ですが、Class componentがなくなることはないと言っていますので、無理に変更する必要はありません。

* 　`Functional`の方が記述量が減りやすい
 * `class`では`constructor`や`render`、`ライフサイクルメソッド（componentDidMount）`を書く必要がなくなります。３つ目のことが大きくこれは可読性にも関わってくると思ってます。`class`ではライフサイクルメソッドがそれぞれあるので、中身の処理が同一でもまとめて書くことができません。ですが、`Functional`では`useEffect`の中でまとめることができる優位性があるかと思います。

``` javascript
// class
componentDidMount() {
// マウント時処理
}
componentDidUpdated() {
// 更新時処理
}
componentWillUnmount() {
// アンマウント時処理
}
```

``` javascript
// functional
useEffect(() => {
  // マウント時処理
  // 更新時処理
  return () => {
    //　アンマウント処理
  };
})
```


* カスタムフックを利用して`state`とロジックを一緒に切り出すことができる
 * 再利用も可能となり、管理が容易になり便利なツールだと思っています。ここではザックリ概要なので、詳しくは別途お調べください。

* `Functional`の方が動作が早いと言われている。


## useCallback　useMemo　React.memo
こちらの３つの機能を利用するとレンダリングの最適化が容易にできるかと思います。

`useCallback`と`useMemo`は似ていて、`useCallback`は関数に対して利用できるもので`useMemo`はそれ以外です。この２つを利用することで無用な関数の実行や変数の計算をスキップできます。これは処理が重い関数や変数に有効です。結果が同じであれば以前の値を使用してくれるので、動作の改善がみられるとはお思います。大規模なものでないと時間が湧かないかもしれませんが。また、`React.memo`と一緒に利用することで無用再レンダリングの抑止もできます。

処理の重くないものに関しては無理に`useCallback``useMemo`を利用することはしないで良いかと思います。
それぞれ単独で使いことはなく、組み合わせて使うことが多いかと思います。



## 最後に

閲覧いただきありがとうございました。
これからはもっと細かい部分や、なぜそれを使うのかなど疑問を潰していてければなと思いました。
以上です。
【Rails】routes概要

##概要
railsのroutes.rbに記述するルーティングについてのまとめ。

##内容

####ルーティングとは
受け取ったurlを認識し、適切なコントローラ内アクションやアプリケーションに割り当てる機能。

####構文
```
httpメソッド 'urlパターン', to: 'コントローラ#アクション'
```

#####ex) 以下のhttpリクエストを受け取った場合、以下のようになる。
```
GET /patients/17
```

routes.rb

```
get '/patients/:id', to: 'patients#show'
```

### HTTPメソッド

クライアントから送られたリクエストの種別を表すもの。

####get　
ページを表示する操作。

####post　
データを登録する操作。

####put　
データを変更する操作。

####delete　
データを削除する操作。

###rootの設定　
[http://localhost:3000 /](http://localhost:3000/%E3%80%8D) にアクセスした際にアクションを呼び出す際に使う。

```
root to: 'home#index'
```

###ネスト　
一対多(一つの投稿に複数のコメント)の場合、urlは「https://×××××××/post/id/comment/id」のようになる。このような場合にルーティングをネストさせる。

```
resources :post do
  resources :comment
end
```

###resources　
7つのアクションのルーティングを自動定義する。

```ruby
resources :コントローラー名

resources :コントローラー名, :コントローラー名
#複数コントローラのルーティングを一行で定義することもできる。
```

###only　

```ruby
resources :tweets, only: [:index, :snow] -->

#indexとshowのみを指定して定義できる
```

###resource　
resourcesは複数形リソースな為、indexやid付のルーティングが生成されるが、
resourceは単数系リソースな為、idの無いリソースを生成できる。
例えば、マイページのような「ログインしているユーザー自身」のデータを表示する際はidを付ける必要が無い為、showアクションの/profile/:idではなく/profileを割り当てることができる。


###namespace　
指定したルーティングの配下にルーティングを設定する.

名前空間でコントローラを分ける時などに使う。

admin画面の場合

```
namespace :admin do
　　　resources :articles
end
```

生成されるurl

```
/admin/articles/:id
```


###member　
特定のデータに対するアクションに対して利用する。
ユーザーidを含んだurlにアクセスできる。

ex)ユーザーに対するふフォロー機能を追加する時
　  以下のようなurlを想定。

```ruby
http://$(DNS)/users/1/follow
```

memberを使ったurlは以下のようになる。

```ruby
resources :users do
	member do
      post :follow
	end
 end

#memberルーティングが一つしかない場合は、onオプションを利用して1行で書ける

resources :users do
    post :follow, on: :member
end
```

###collection　
全てのデータに対するアクションに利用する。

ex) searchアクションでユーザー検索を行う
　   以下のようなurlを想定。

```ruby
http://$(DNS)/users/search
```

collectionを使った記述は以下のようになる。

```ruby
resources :users do
    get :search, on: :collection
  end
```
Day.jsで誕生日から年齢を計算する

## 環境
Day.js 1.8.16

## コード
いろいろとやり方はあるが、`diff` を使うのが一番シンプル。

```js
// input data
const birthday = {
  year: 1995,
  month: 12,
  date: 6,
};

const today = dayjs();
const { year, month, date } = birthday;
const dayjsBirthday = dayjs(`${year}-${month}-${date}`);

console.log(today.diff(dayjsBirthday, 'year'));
```

CodePen: https://codepen.io/ezawa800/pen/VwzJmmM
swift 整数値 Int() と 配列 Array() の抽出

Intは整数値を定義するのに用い、Arrayは配列を組織する。

```
class ViewController: UIViewController {
var c = Int()
var elem = NSArray()
  override func viewDidLoad(){
    elem = [ 
      “Name1”, “name2”, “name3”, “name4”
    ]
    var btn1 = UIButton()
    btn1.addTarget(self, action: #selector(button1(button1:)), for: .touchUpInside)
  }
  @objc func button1(button1: UIButton){
    C += 1
    Object()
  }    
  Object(){
　　 if(c <= elem.count - 1){
      let name = elem[c]
    } else {
      let name = elem[0]
    }
    let label = UILabel()
    label.text = String(name)
  }
}
```
上の文字列は、ボタンを押すたび、に配列に置かれた、名前が変わり、ラベルに表示されることを記している。
JavaScript : 関数型プログラミング

## 関数型プログラミング
・すべての関数は値を返す
・関数には副作用がない（参照透過性）
・関数を値として扱う

## Code Sample
```JavaScript
// すべての関数は値を返す  
function helloWorld() {
  return "Hello Functional JavaScript !"
}

var xValue = 8
var yValue = 2

function calculation(calc) {
  return calc(xValue, yValue)
}

// 関数には副作用がない
function add(x, y) {
  return x + y
}

// 関数を値として扱う 
console.log(calculation(add)) // 10
```

## GitHub
https://github.com/GL-Kageyama/JavaScript_FunctionalTypeProgramming
メモ〜フォームのテストの中で画像を扱う方法

今回のお題
-
今回はdjangoのunittestにおいて、フォームに画像ファイルをアップロードする方法をまとめます。

私自身仕組みまではわかっていない面が多く、解説書というよりは手順書の側面が強くなってしまいますがご了承ください。

目次
-

- 解説に用いるフォーム
- 前提知識〜ImageFieldがあるフォームの引数
- SimpleUploadFileクラス
- テスト例

解説に用いるフォーム
-

```python:models.py
class Menu(models.Model):
  name = models.CharField(max_langth=20)
  price = models.IntegerField()
  image = models.ImageField(upload_to="images/")
```
```python:forms.py
class MenuForm(ModelForm):
  class Meta:
    fields = "__all__"
```

前提知識〜ImageFieldがあるフォームの引数
-
本題に入る前に、フォームの引数について話しておきます。

テスト内で（あるいはそれ以外で）フォームのインスタンスを作成する場合には、

```python
form = MenuForm({
  "name": "カレーライス",
  "price": 1000,
})
```
あるいは

```python
form_data = {
  "name": "カレーライス",
  "price": 1000,
}
form = MenuForm(form_data)
```
のように辞書形式で引数を設定していると思います。

しかしフォームがImageFieldを持つ場合に関しては、

```python
form_data = {
  "name": "カレーライス",
  "price": 1000,
}
form_image = {
  "image": image
}
form = MenuForm(form_data, form_image)
```
のようにImageFieldとそれ以外で別々の辞書を用意する必要があります。

関数ベースビューでフォームを作成する場合にも

```python
form = MenuForm(request.POST, request.FILES)
```
と引数を二つ指定しているのでなんとなくイメージは掴めると思いますが、ここをひとまとめにしてしまうとフォームが画像のデータを受け取れなくなるので注意しましょう。

SimpleUploadFileクラス
-
アップロードされたファイルを扱うための組み込みクラスの一つです。

```python
from django.core.files.uploadfile import SimpleUploadFile
file = SimpleUploadFile(file_name, content, content_type)
```
とすることで作成されるファイルを、前項の`form_image`にセットします。

テスト例
-

```python
class TestFileUpload(TestCase):
  def test_file_upload(self):
    form_data = {
      "name": "カレーライス",
      "price": 1000,
    }
    with open("xxxx", "rb") as f: 
      file = SimpleUploadFile(
        f.name, 
        f.read(),
        content_type="image/png"
      )
      form_image = { "image": file }
      form = MenuForm(form_data, form_image)
    self.assertTrue(form.is_valid())
```
SimpleUploadFileオブジェクトの引数として、with openで開いたファイルのファイル名および中身を指定しています。

"xxxx"については画像のパスですが、アプリのルートではなくローカル環境のルートディレクトリからのパスになるので

```python
import sys
sys.path.append("...")
from myproject.settings import BASEDIR
path = BASEDIR / "static/myapp/images/test_image.png"
with open(path, "rb"):
```
などとした方がわかりやすいかと思います。

キーワード引数の`content_type`については、次項で調べ方を解説しています。

content_typeの調べ方
-
標準ライブラリである`memutypes`を用いるとcontent_typeが確認できます。

```python
import memutypes
memutypes.guess_types("/aaa/bbb/ccc/ddd.png")
# 引数としてファイルまでのパスを与えるとcontent_typeが返される
```
【javascript】for...in と列挙可能性

# for...in
列挙可能プロパティに対して順不同で反復処理を実行する。

* ※順不同：基本的には順番通りに出力されるが、それが担保されているわけではない。
* プロトタイプチェーン内も列挙対象となる。
    * プロトタイプチェーンのみ列挙したい場合は`Object.hasOwnProperty()`を使う。
*  Symbolはfor..inでは列挙対象にならない。


## case1

* オブジェクトをinで回す場合はkeyが戻り値になる。
* valueを取得する場合はobjに対して[key]を渡す形なる。

```js

const obj = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}

for(let key in obj){
	console.log(key, obj[key]);
}

```

## case2

* prototypeにメソッドを追加していた場合にメソッドを列挙対象外にしたい場合。
    * definePropertyのディスクリプターのenumerableをfalseにすることで列挙対象外となる。
* そもそもビルトインメソッドが列挙対象外になっているのは、enumerable: falseという設定になっているから。

```js
const obj = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}

Object.prototype.method = function(){}

Object.defineProperty(Object.prototype, 'method',{
	enumerable: false
})

//ディスクリプターの設定確認
const d = Object.getOwnPropertyDescriptor(Object.prototype, 'method')
console.log(d)
// {writable: true, enumerable: false, configurable: true, value: ƒ}

//ビルドインメソッドの enumerable: falseになっているかどうかの確認。
const c = Object.getOwnPropertyDescriptor(Object.prototype, 'hasOwnProperty')
console.log(c)
//{writable: true, enumerable: false, configurable: true, value: ƒ}



for(let key in obj){
	console.log(key, obj[key]);
}
```

## case3

* case2の応用として、objオブジェクトの一部だけdefinePropertyで列挙外にすることができる。

```js

const obj = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}

Object.defineProperty(obj, 'prop1',{
	enumerable: false
})


for(let key in obj){
	console.log(key, obj[key]);
}

```

## case4

* for...inのなかでprototypeを列挙から外し合い場合はhasOwnProtertyを使うと良い。
    * hasOwnProperty() メソッドは、オブジェクト自身が（継承されていない）指定されたプロパティを持っているかどうかを示す真偽値を返します。

```js

const obj = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3'
}


for(let key in obj){
//objが自身のプロパティかどうかを真偽値で評価している。
//prototypeに格納されているものは全て継承されたものなのでfalseになり、列挙対象外となる；。
	if(obj.hasOwnProperty(key)){
 	  console.log(key, obj[key]);
	}
}
```

## case5
* Symbolが列挙外になっているかの確認
* 変数をオブジェクトに格納する場合はkeyに`[変数]：value`となる。

```js

const s = Symbol();

const obj = {
	prop1: 'value1',
	prop2: 'value2',
	prop3: 'value3',
	[s]: 'value4'
}

const e = Object.getOwnPropertyDescriptor(obj, s)
console.log(s)
>>> Symbol()
//Symbolとして評価されている。

for(let key in obj){
   console.log(key, obj[key]);
}

>>> prop1 value1

>>> prop2 value2

>>> prop3 value3
//Symbolは表示されなかった。
メモ：HLSでストリーミング配信をする方法



WebRTCはブラウザ同士のP2P動画配信だったので、サーバからストリーミングで動画を流すパターンを見ておく。
[ここ](https://qiita.com/YOCCHAAAAN/items/71bdb7ab018eb316bd47)参考

基本的にはカメラ側からRTMPでストリーミングサーバに渡して、ストリーミングサーバはHLSでクライアントに流していやる、という流れ。
最近だとSRTというプロトコルが出てきているらしい。

# ストリーミングサーバ
OBSからストリーミングサーバにプッシュ出来るならそれが一番簡単そう。
※OBSはカスタムでrtmpサーバとストリームキーを設定可能

AWSだと[サービス](https://aws.amazon.com/jp/solutions/implementations/live-streaming-on-aws/)がありそうだが、テストに使うにはオンプレのフリーソフトが好ましい。

nginsがRTMPサーバになれるプラグインがある。Nginx-rmtp-module
Linuxだと[この記事](https://qiita.com/danna_P/items/b6cae10313b2eb9b076a)とか[この記事](https://qiita.com/MMaru76/items/e2495a87b871bc9cbefe)みたいにモジュールDLしてビルドすればいける。
Windowsだと標準パッケージに入っていない場合は非常に面倒。
`nginx -V`
で見てみたが、公式にはさすがに入っていなかった。
[ここ](https://github.com/illuspas)に古いビルド済のものはあるけど、どちらかというと今はnodeのメディアサーバに力を入れている模様。
便利そうだがパフォーマンスはnginxの方が出る気がする。

[ここ](https://szkhaven.com/2020/04/29/streamingserver_in_srs_rtmp/)でnginx以外の選択肢として[SRS-Simple Realtime Server-](https://github.com/ossrs/srs)というものが紹介されている。
RTMP及びSRTが利用可能、らしい。本体のライセンスはMIT。Windows用はなし。
手元ですぐに立ち上げられるのはAWS上のサーバのみだが、一応インストールコマンドを流してみた。

```linux
yum install wget gcc pcre-devel openssl openssl-devel git make unzip tar
```
AmazonLinux2もyumなので、これで必要なパッケージを取得。
プロキシを設定してから

```
git config --global http.https://gitee.com/.proxy http://proxy.co.jp:8080

git clone -b 4.0release https://gitee.com/ossrs/srs.git && cd srs/trunk && ./configure && make && ./objs/srs -c conf/srs.conf
```
と、readmeに書いてある通りのコマンドを実行。
`./configure && make`も含まれているのでこれでmakeまで流して、confファイルを指定しての実行までを流している。
[wiki](https://github.com/ossrs/srs/wiki/v4_EN_Home)が細かくコマンドを書いてた。

AL2もcent系ぽいがconfigureで`Your OS Linux is not supported.`と出ていて、makeされておらず`objs/srs`が存在していない。
、公式では`CentOS7`の対応みたいなので今回は一旦諦める。（centOSも無料なので立ち上げればいけそう）

Linuxを立ち上げたのでついでにnginxをインストールしてみる。
とりあえずnginxをダウンロードして、プラグイン付きでmakeする。
(makeの部分でエラーが出たので実際にはsudoで実行した)

```
wget -e HTTP_PROXY=proxy.co.jp:8080 http://nginx.org/download/nginx-1.19.10.tar.gz
tar zxf nginx-1.19.10.tar.gz && cd nginx-1.19.10
git config --global http.https://github.com/.proxy http://proxy.co.jp:8080
git clone https://github.com/arut/nginx-rtmp-module.git
./configure --add-module=nginx-rtmp-module/ && make && make install
```

これで`/usr/local/nginx`にインストールされた。

```
[ec2-user@ip-10-227-7-190 sbin]$ ./nginx -V
nginx version: nginx/1.19.10
built by gcc 7.3.1 20180712 (Red Hat 7.3.1-13) (GCC)
built with OpenSSL 1.0.2k-fips  26 Jan 2017
TLS SNI support enabled
configure arguments: --add-module=nginx-rtmp-module/
```

AWS上に仮想カメラとかは作っていないのでここまで。
RTMPの設定は[ここ](https://centossrv.com/nginx-nginx-rtmp-module.shtml)とかにある。


この前やった、CentOSをWSL2内のDockerで立ち上げるパターンでいけそう、だが一旦ここまで。