OmniAICreator/Qiita-1.07M huggingface dataset:
【勉強記録】Pythonのデータ型について

## 目次

- 趣旨
- 代表的なデータ型
- サンプルと型の確認

## 趣旨
前回の投稿で稚拙なコードにリファクタリング例を頂くというありがたい経験をしました。
ご教示頂いた箇所を再度アウトプットしたいと思い、題材を見つけて投稿するものです。
データ型のまとめ自体は薄い内容で申し訳ありません。
勉強の都度更新いたします。

## 代表的なデータ型
| データ型 | 説明 | サンプル |
|:-:|:-:|:-:|
| str型  | 文字列  |  あいうえお |
| int型  | 整数  |  1212 |
|  float型 | 浮動小数点数  | 3.14  |
| bool型  |  真偽値 | True  |
| list型  |  リスト | [1,2,3]  |
|  tuple型 | タプル  | (1,2,3)  |
| dict型  | 辞書型  | {"a":1,"b":2}  |
※現状、tuple型はimmutable（変更不可能）なlist型という理解

## サンプルと型の確認

```data-type.py

x = ["楽団",1212,3.14,True,[1,2,'3'],(1,2,'3'),{'a':10,'b':20}]


def data_type(i):
    print(type(x[i]))


data_type(0) #=> <class 'str'>
data_type(1) #=> <class 'int'>
data_type(2) #=> <class 'float'>
data_type(3) #=> <class 'bool'>
data_type(4) #=> <class 'list'>
data_type(5) #=> <class 'tuple'>
data_type(6) #=> <class 'dict'>

```

<details><summary>リファクタリング
</summary><div>

```data-type.py
x = ["楽団",1212,3.14,True,[1,2,'3'],(1,2,'3'),{'a':10,'b':20}]


def data_type(i):
    print(type(i))


for i in x:
    data_type(i)

```

</div></details>

## 振り返り
散らかったコードをひとまず書いてから、リスト、関数の定義、for文と使用してリファクタリングを行いました。動けばいいじゃん、ではないコードを書きたいものです。
（ただ教科書的ではないですね…）
STM32L010を使た、MbedでHALのアナログ入力 (約5Kバイト)


目的
最軽量化

PA0(6ピン)から入力してPA4(10ピン)でLチカする。

x Mbedのリビジョンは、143


https://moons.link/post-523/


https://moons.link/post-994/


https://moons.link/post-1009/


![h_con60.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/381b5cd8-68a6-c0e8-a344-ba5ebec42926.jpeg)



![h_con59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/d9dc7818-0a6f-7c26-7aea-a39cdcceebeb.jpeg)


```c++


#include "mbed.h"

//DigitalOut myled(PA_4);

//AnalogIn adc_vbat(PA_0);

int main() {

    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_ADC1_CLK_ENABLE();
    
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    GPIO_InitStruct.Pin = GPIO_PIN_0;
    GPIO_InitStruct.Mode = GPIO_MODE_ANALOG;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
    GPIO_InitStruct.Pin = GPIO_PIN_4;
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
  
    ADC_HandleTypeDef hadc;
  
    hadc.Instance = ADC1;
    hadc.Init.OversamplingMode = DISABLE;
    hadc.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV1;
    hadc.Init.Resolution = ADC_RESOLUTION_12B;
    hadc.Init.SamplingTime = ADC_SAMPLETIME_1CYCLE_5;
    hadc.Init.ScanConvMode = ADC_SCAN_DIRECTION_FORWARD;
    hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc.Init.ContinuousConvMode = DISABLE;
    hadc.Init.DiscontinuousConvMode = DISABLE;
    hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc.Init.DMAContinuousRequests = DISABLE;
    hadc.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    hadc.Init.Overrun = ADC_OVR_DATA_PRESERVED;
    hadc.Init.LowPowerAutoWait = DISABLE;
    hadc.Init.LowPowerFrequencyMode = ENABLE;
    hadc.Init.LowPowerAutoPowerOff = DISABLE;
    HAL_ADC_Init(&hadc);
  
    ADC_ChannelConfTypeDef sConfig = {0};
    sConfig.Channel = ADC_CHANNEL_0;
    sConfig.Rank = ADC_RANK_CHANNEL_NUMBER;
    HAL_ADC_ConfigChannel(&hadc, &sConfig);
    
    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
    
    int a=0;

    while(1) {

        HAL_ADC_Start(&hadc);
        if( HAL_ADC_PollForConversion(&hadc, 1000) == HAL_OK )
        {
            a = HAL_ADC_GetValue(&hadc);
        }
        HAL_ADC_Stop(&hadc);


        if(a > 500) {
            //myled = 1;
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);
        } else {
            //myled = 0;
            HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);
        }
        
        //if(a==0){a=1;}else{a=0;}
        //wait_ms(500);
    }
}



```
Eclipse（Xampp）のワークスペースをhtdocs以外にしようとして苦労した話

### はじめに

Eclipse（Xampp）でも大抵の場合、htdocsにファイルを置いておけばローカルではたいてい動く。
ここまでは下記の記事でできた。

https://qiita.com/Atsulabo/items/1d6cd3326267a02d3bf2


だが、仕事の都合上、htdocs以外の別の場所におかないといけなくなった。
そんなわけで、上の記事で保留した「別の場所に設定できない問題」というのを
解決せざるを得なくなった。

というわけであれこれ試行錯誤した結果をまとめたい。

### １．　ファイルを置きたい場所に移動させて、パスを取得する

まずは今までhtdocsで作ったファイル群を置きたい場所に移動させておく。
ここでは仮に「C:¥MyPHPTool¥」に移動させるとする。

### ２．　Eclipseを開き、最初のワークスペースを決めるところで、上記のパスを入れる

元のhtdocsの場合、C:¥¥xampp¥htdocsとか、
Eclipse入れてたら C:¥¥Eclipse¥xmapp¥htdocs だけど、
置きたい場所の　C:¥¥MyPHPTool　を入れる。
（Macの場合は読み替えてください）　
→あとでMacでもしてみて変更します（自分の勉強のため）

### ３．　xamppのコントロールパネルのConfigからhttpd.confでもドキュメントルートを変更

DocumentRootで検索すると１箇所見つかり、
最初は

```httpd.conf
DocumentRoot "C:¥¥xampp¥htdocs"　

```
というのがあり、ここを　C:¥¥MyPHPTool　に変える。

その下の方に　（Directoryで検索するといいかも）

```httpd.conf
<Directory "C:¥¥xampp¥htdocs">
...

</Directory>
```
というのがあり、ここも　C:¥¥MyPHPTool　に変えて保存

XamppのApacheををStopしてStart(再起動）。
念の為Eclipseもクリーンして閉じて再度開く。
そしてWebアプリケーション実行で何らかのファイルを実行してみると、
成功します。

### ４．　参考

https://qiita.com/Atsulabo/items/1d6cd3326267a02d3bf2

ここは逆にhtdocsに変更する感じだけど
逆に読み替えて成功しました。
ありがとうございました。
Unityにpythonをインストールする。

#1 この記事は何？

Unityにpythonをインストールする方法を説明します。またUnity上で簡単なpythonのコードを実行してみます。

前提条件 Unity2919.4.29f1が導入されているものとします。

#2 その方法は？

## 2-1 必要データのダウンロード
まず下記のサイトにアクセスしサイトの筆者が準備したUnity Packageをダウンロードします。

https://mikalikes.men/use-python-with-unity-3d-the-definitive-guide/

![234.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/84433a82-0e29-4c21-c79b-4c2d8876881f.jpeg)

## 2-2 データの取り込み
前述のPackageをUnityにImportします。
![235.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/b3e2334f-d152-c19f-9c5b-71a770b788f3.jpeg)

AssetsフォルダにあるPythonExample.prefabを描写エリアにドラッグドロップします。

![236.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/9ffb878c-f1a4-46a4-1ecb-1747d8248cde.jpeg)

## 2-3 コーディング

まずは、pythonコードから始めます。Assetsのフォルダにgreeter.pyがあります。
![237.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/65e3ce2b-b7dd-248c-0d6e-801db73d0ca2.jpeg)

greeter.pyを下記のとおり変更してみます。(Python2.7がインストールされています。Python3.xは使用できないことをご認識ください)

```python:greeter.py
import random
import sys

class Greeter():
    def __init__(self, name):
        self.name = name
    def greet(self):
        return "Hiii, " + self.name
    def versionget(self):
        sysv=sys.version #pythonのverisonを取得します。
    	return "python version:" + sysv
```

次にC#をコーディングします。Assetsディレクトリの中に配置されているPythonExample.csを開きます。

![238.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/5411689a-129f-283a-7036-08cb296b7276.jpeg)

下記の通り修正してください。


```c#:PythonExample.cs
using System.Collections;
using System.Collections.Generic;
using IronPython.Hosting;
using UnityEngine;

public class PythonExample : MonoBehaviour {

    // Use this for initialization
    void Start()
    {
        var engine = Python.CreateEngine();

        ICollection<string> searchPaths = engine.GetSearchPaths();

        //Path to the folder of greeter.py
        searchPaths.Add(Application.dataPath);
        //Path to the Python standard library
        searchPaths.Add(Application.dataPath + @"\Plugins\Lib\");
        engine.SetSearchPaths(searchPaths);

        dynamic py = engine.ExecuteFile(Application.dataPath + @"\greeter.py");
        dynamic greeter = py.Greeter("Mika");
        Debug.Log(greeter.greet());
        Debug.Log(greeter.versionget());
    }

    // Update is called once per frame
    void Update () {
		
	}
}
```

上記のコードはC#の一連の作業の中でpythonを実行します。pythonにデータを渡し、pythonから返された値をC#が受け取ります。


コーディングか終わりましたら、PythonExample.csをビルドします。

![239.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/08e97912-26ca-dbb8-2987-9c0e1dafa3c8.jpeg)

## 2-4 実行

実際に実行してみます。Gameを選択のうえ、矢印をクリックすると動作が開始されます。
![240.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/c1526943-1529-cf76-e9bf-4e1b5e0b4e15.jpeg)

実行結果がConsoleに表示されております。pythonコードでは、「Hii,Mika」と使用しているPython versionの表示を行っているので、C#がそれらのデータを受け取りConsoleに表示しております。

![241.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150223/c731351f-f051-cac4-7f83-4e4b2c648613.jpeg)
Lightsail 上の WordPress に ads.txtを導入する

# はじめに

[Amazon Lightsail](https://aws.amazon.com/jp/lightsail/) 上の WordPress に Google Adsense の設定ファイル (ads.txt)を導入します。

導入しないと、以下のようなエラーが出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/0f9a7547-f524-8efa-ace8-c5b98b5157ac.png)

# 手順

## ads.txtファイルのダウンロード

Google AdSense のダウンロードリンクからads.txtをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/0f9a7547-f524-8efa-ace8-c5b98b5157ac.png)

ads.txtを開くと次のような1行が書いてあります。

```text
google.com, <some number>, DIRECT, <some number>
```

このads.txtをサイトのルードレベルに保存すればOKです。

## Lightsail に導入する

AWS コンソール から Lightsail にアクセスして、ターミナルを起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114392/cd354419-e457-8377-044c-897a55520d32.png)

ターミナルからads.txtを作成します。

```bash
$ cat <ads.txtの1行> > /home/bitnami/apps/wordpress/htdocs/ads.txt
$ sudo chown bitnami:daemon /home/bitnami/apps/wordpress/htdocs/ads.txt
```

カンタンですね。
【Rails】 環境構築

## 手順

#### ① 作業ディレクトリの作成

```
$ mkdir workspace/my/rails_sample
$ my/rails_sample
```

#### ② rubyのバージョン切り替え

```
$ rbenv install 2.7.2
$ rbenv local 2.7.2
$ ruby -v  # 指定バーションが表示されて売ればOK
```

rbenv 〜
rubyのバージョンを切り替えるためのツール

#### ③ bundleとrails

```
$ gem install bundler

# rubyのライブラリを管理するbundlerをrubyにインストール
```

```
$ bundle init

# 生成されたGemfileをgem "rails"に編集


$ bundle install
```

bundle init 〜
現在の作業ディレクトリ内に、Gemfileを生成


#### ④ プロジェクトの作成

```
rails _6.0.3.7_ new sample
```

## その他

-  nodeやyarnのインストール
-  データベースの作成 
-  フロントエンドの構築

ext...
Ruby on Railsを使用する恩恵

おはようございます、プレイライフの熊崎です。

今週は雨の日が多かったですね。
来週も雨の日が多いようで、気が滅入ってしまいます。。。

来週も、雨にも負けず風にも負けず仕事を頑張っていきたいと思います！

## なぜこの記事を書こうと思ったか？
業務を行っていて、railsの機能を充分には使いこなせていなかった。（今振り返ると、そもそも使いこなそうともしていなかったように感じる。）
原因を考えてみたら、下記の原因が考えられた。

- なんでrailsの規約に沿った書き方をしなければいけないのか？という理由が自分の中で明確になっていなかった。
- スピード感を持って開発することが求められている中で、とりあえず動くものを作るということに意識を向け過ぎた。

`スピード感を持って開発することが求められている中で、とりあえず動くものを作るということに意識を向け過ぎた。`に関しては、今までの経験上、後で修正しようと考えても絶対修正まで手が回らないので、都度railsの機能を利用することを徹底することにした。

↑
のように考えても、railsを使用する恩恵の理解が薄いと絶対に上記の意識も薄れてくるので、アウトプットを行うことで自身の理解を深めようと思ったため。

## 本記事の対象者
ということで、本記事は以下のような方々を対象とする。

- 自分と同じように何となくでrailsを使用していた方

## railsの基本理念

### Convention over Configuration（設定より規約）
アプリケーションの実装を行う上で、決めなくてはいけないことは沢山ある。（ex:主キーの名前をどうするか、など）
そのような**決めなくてはいけないこと（設定）を規約に移すことで、設定を決定する時間を軽減する**ことをモットーとする。

## railsを使用するメリット

- 上記の基本理念に則って作られているため、規約に則った書き方をすれば、作業時間を短縮できる。
- 初心者でも、規約に則った書き方をすれば、最低限のコードの質は担保される。（もちろん、命名規則や単一責任の原則など、コードの質を担保するためには他にも考慮しなければならないことが沢山ある。）
- 単純にコード量が少なくて済む。
- 可読性が上がる。

### メリットの補足（コード量が少なくて済む・可読性が上がる について）
例： 性別が男性のUserを探したい場合

```sample.rb
# すでにSampleUsersテーブルに男性や女性の情報が登録されていると仮定する。 

# railsのActiveRecordを利用した場合
SampleUser.where(sex: :man)

# ↑をrubyで似たようなことを行う場合
SampleUser.select { |user| user.sex == "man" }
```

前者の方が記述量が少ない。（検索条件が複雑になればさらに記述量に差が出てくる。）
また、whereは検索用のメソッドなので、whereと書いてあれば、「何か条件を設定していて、その条件に当てはまるレコードを検索している」ということが直感的に理解しやすい。

一方で、後者だと記述量が多い上に、パッと見で何をやっているか少しわかりづらい。（このコードは短いので、わからなくはないが、検索条件が膨らんでくるとさらに読みづらくなることが予想される。）

## まとめ
- railsの理念はConvention over Configurationである。
- railsを使いこなすことで、rubyで実装するより、記述量が少なく、かつわかりやすいコードを書ける。

## 最後に
そもそもフレームワークは楽をするために、先人達が知恵を絞って作ったものだから、フレームワークを積極的に使用して作業効率を上げるのは当たり前のことだと思う。
しかし、とにかく動くものを作るという目先のことに囚われすぎて、フレームワークを積極的に使用することに意識が向いていなかった。

とにかく動くものを作る → フレームワークを使わない → フレームワークの使い方を覚えない　→ 作業スピードが上がらない 

といった負のスパイラルに陥るため、今後は使ったことのないrailsの機能でも積極的に使っていきたいと思う。

## 参考文献
[https://rubyonrails.org/doctrine](https://rubyonrails.org/doctrine)
WSL2のubuntu 20.4にQEMU 6.1.0 をコンパイルしてインストール

ひさしぶりにQEMUで遊ぼうかと、QEMU 6.1.0 をWSL2 ubuntu 20.4 にインストールしてみました。

x11とかは使ってないです。

QEMUのサイトから、qemu-6.1.0.tar.xzをダウンロードしました。
tarで展開します。

```
$ tar xf /mnt/c/Users/hoge/Downloads/qemu-6.1.0.tar.xz
$ cd qemu-6.1.0
```

configureをすると足りないといわれたので下記パッケージを追加しました。（コンパイラとかmakeとかninjaはすでにインストールしてました。）

```
$ sudo apt install pkg-config libglib2.0-dev libpixman-1-dev
```

arm とaarch64のターゲットを有効にしてconfigureしました。トレースを有効にしてます。

```
$ ./configure --prefix=`pwd`/build --target-list=arm-softmmu,aarch64-softmmu  --enable-trace-backend=log
```

ビルドします。

```
$ make
...
...
$ ./build/qemu-system-aarch64 --version
QEMU emulator version 6.1.0
Copyright (c) 2003-2021 Fabrice Bellard and the QEMU Project developers
```

以前書いたプログラムを動かしてみました。

```
git clone https://github.com/eggman/raspberrypi
cd cd qemu-raspi3/int01
make
make run 
$ make run
make kernel.elf
make[1]: Entering directory '/home/sekine/baremetal/raspberrypi/qemu-raspi3/int01'
make[1]: 'kernel.elf' is up to date.
make[1]: Leaving directory '/home/sekine/baremetal/raspberrypi/qemu-raspi3/int01'
qemu-system-aarch64 -M raspi3 -m 1024 -serial mon:stdio -nographic -kernel kernel.elf
int01
a c_irq_handler
a c_irq_handler
```

(これは動いたけど動かなくなっているのがあるなぁ。)

以上です。
PySparkにてArrayType内のカラムにドット（.）が含まれるカラムにSELECTする方法

## 概要
PySparkにてArrayType内のカラムにドット（.）が含まれるカラムにSELECTする方法を共有します。カラム名をそのまま指定すると下記のようなエラーメッセージが表示されます。

```text

AnalysisException: No such struct field strintg in strintg.in.array
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/4b9f767b-c7c1-6de1-e207-96c6aa265d13.png)


対応方法としては、ドットが含まれるカラムをバッククォート（`）で囲むことでSELECTができるようになります。シングルクォーテーション（'）ではないことに注意してください。

下記のようなスキーマの場合には、array.\`strintg.in.array\` と記載することで、データを取得することができます。カラムごとにバッククォートで囲む必要があるため、\`array.strintg.in.array\` のようにカラム全体を囲むだけではエラーが発生します。

```text
root
 |-- array: array (nullable = true)
 |    |-- element: struct (containsNull = true)
 |    |    |-- strintg.in.array: string (nullable = true)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/31805570-03d0-d1c8-7fdf-56fd75727b0b.png)





## 手順
### 1. データの準備

```python
json_data ="""
{
    "array":[
        { "strintg.in.array": "値①"},
        { "strintg.in.array": "値②"},
        { "strintg.in.array": "値③"}
    ]
}
"""

df = spark.read.json(sc.parallelize([json_data]))
df.createOrReplaceTempView('tmp_nested_columns')

# df.display()
df.printSchema()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/704598ee-488d-3d9f-7da0-1e340216dce8.png)


### 2. DataframeでSELECTする方法

```python
df_2 = df.select('array.`strintg.in.array`')

# df_2.display()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/5aba7660-1dbb-13fc-921b-4bf707ab8029.png)


### 3. SQLでSELECTする方法

```python
%sql
SELECT
  array.`strintg.in.array`
  FROM
    tmp_nested_columns
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/2cec0d17-246e-1e43-389b-93da5faf2cef.png)
【Laravel】Non-static method <メソッド名> should not be called staticallyの解決方法


#事象

以下のようにメソッドを呼び出したときに発生します。

```php
class Item extends Model
{
    public function getItems()
    {
        // 取得処理
```

```php
class ItemController extends Controller
{
    public function index(Request $request)
    {
        $items = Item::getItems();

// Error
> Non-static method App\Models\Item::getItems() should not be called statically
```

#原因

エラーメッセージを訳すと***「非静的メソッド`App\Models\Item::getItems()`は静的に呼び出されるべきではありません」***になります。

原因はそのままで`getItems`は非静的メソッドなので、静的な呼び出しを行なってはならない、ということになります。

###「静的」とは？
> クラスのメソッドを静的として宣言すると、クラスのインスタンス化を必要とせずにそれらにアクセスできるようになります。

https://www.php.net/manual/en/language.oop5.static.php

###「静的な呼び出し」とは？

`クラス名::メソッド名()`のような書き方です。

静的呼び出しではItemクラスのインスタンスを作成せずに`getItems`メソッドを呼び出しています。

上記の例では`getItems`は静的なメソッドとして定義されていないので、呼び出すにはインスタンスを生成する必要があります。それを静的呼び出し（インスタンスを生成せず呼び出す方法）で呼び出そうとしているので警告されているわけですね。

#解決方法

###1.インスタンスを生成し、インスタンスメソッドとして呼び出す

`getItems`は非静的メソッドなので***静的な呼び出しを行ってはならない***、ということだったのでインスタンスを作成して、インスタンスメソッドとして呼び出すようにします。

```php
class ItemController extends Controller
{
    public function index(Request $request)
    {
        $i = new Item(); // Itemクラスのインスタンスを生成
        $items = $i->getItems(); //生成したItemインスタンスのgetItemsメソッドを呼び出す
```

###2.静的メソッドに変更する

***`getItems`は非静的メソッドなので***静的な呼び出しを行ってはならない、ということだったので`getItems`を静的メソッドに変更してあげます。

```php
class Item extends Model
{
    public static function getItems() // メソッド名にstaticキーワードを付けると静的メソッドになる
    {
```

#どちらを使えばいいのか？

###インスタンスメソッド

- インスタンスごとに異なる動作を期待する場合

###静的メソッド

- いろんな場所で繰り返し同じ処理を呼びたい場合
- 呼び出す場所によって期待する動作が異ならない（常に同じものを返してほしい）場合

#参考
Why I'm getting 'Non-static method should not be called statically' when invoking a method in a Eloquent model?

https://stackoverflow.com/questions/18339716/why-im-getting-non-static-method-should-not-be-called-statically-when-invokin

PHPでなくC#ですが、静的メンバ―の説明がわかりやすかったので。

https://ufcpp.net/study/csharp/oo_static.html
OAuth 2.0 Security Best Current Practice Draft 18 メモ


## 概要

* OAuth 2.0のセキュリティベストプラクティス策定が進められている。
* そのドラフトバージョン18の推奨事項(Recommendations)について個人用にメモする。

## Protecting Redirect-Based Flows

### Authorization Code Grant

* クライアントは、攻撃者による認可コードのインジェクションを防止する必要がある。
* クライアント側の対応
  * PKCE(Proof Key for Code Exchange)を使用する
    * パブリッククライアントでの 認可コードフローをどう保護するかを念頭に考えられた仕様
    * 認可コード横取り攻撃
      * カスタム URI スキームを上書きすることで、認可コードの受取先が異なるものとなり、認可コードを奪う攻撃。
      * 正当なアプリが開始した認可リクエストから、ユーザー認証に基づいて、攻撃アプリケーションに対してトークンが返却され、不正アクセスにつながる。
  * パブリッククライアント(デバイスまたはデスクトップ コンピューターあるいは Web ブラウザで実行されるアプリ。シークレットを安全に保持できない。)：PKCE必須
  * コンフィデンシャルクライアント(サーバー上で実行されるアプリ。シークレットを安全に保持できる。)：PKCE推奨。
* 認可サーバー側の対応
  * PKCEをサポートする。
    * PKCEのサポートをクライアント側から検出できるように、`code_challenge_methods_supported`をメタ情報として公開する。
  * `code_challenge`パラメーターが認可リクエストに存在する場合にのみ、`code_verifier`パラメーターを含むトークンリクエストを受け入れられるようにする。

### Implicit Grant

* Implicit Grant（`response_type=token`）などの認可サーバーが認可レスポンスでアクセストークンを返却する方式は、アクセストークンの漏洩などに対して脆弱である。 

* 基本的に利用は非推奨。

* クライアント側は、代替手段として`response_type=code`もしくは`reponse_type=code id_token`を利用することでアクセストークンを発行する必要がある。

  * 認可サーバーがリプレイ攻撃を検出できる。

  * アクセストークンがURLで公開されない。

  * 認可サーバーが発行されたトークンを送信者に制約することができる。

    

## Token Replay Prevention

### Access Tokens

* アクセストークン送信者は、受信者（リソースサーバーなど）側がそのトークンを受け入れるための条件として、特定の秘密情報を検証する必要がある。
* 認可サーバーとリソースサーバーは、TLSなど送信者を制約する方式を使用する必要がある。

### Refresh Tokens

* 次のどちらかの対応を必須とする。
  * 送信元制限
  * リフレッシュトークンローテーション

## Access Token Privilege Restriction

* アクセストークンに関連付けられた権限は、特定アプリケーションまたはユースケースに必要な最小限に制限する。
  * クライアントがリソースオーナーによって許可された権限を超えた操作を行うことを防ぐ。
* ユーザーがそれぞれのセキュリティポリシーで許可されている権限を持たないようにする。
* 権限の制限により、アクセストークンの漏洩の影響を減らす。
  * アクセストークンは、特定のリソースサーバー、できれば単一のリソースサーバーに制限する。
  * 認可サーバーはアクセストークンを特定のリソースサーバーに関連付け、全リソースサーバーは、すべてのリクエストについて、そのリクエストで送信されたアクセストークンがその特定のリソースサーバーで使用されることを意図していたかを確認する必要がある。
    * 意図したものでない場合、リソースサーバーはそれぞれのリクエストを拒否する必要がある。
* クライアントと認可サーバーは、パラメーター「`scope`」または「`resource`」を使用して、アクセスするリソースサーバーを決定できる（オプション）。
* アクセストークンは、特定のリソースおよびリソースサーバー、またはリソース上のアクションに制限する必要がある。
  * 認可サーバーはアクセストークンをそれぞれのリソースとアクションに関連付け、全リソースサーバーは、全リクエストについて、そのリクエストで送信されたアクセストークンがその特定のアクションに使用されることを意図していたか確認しなければならない。
    * 意図していない場合は拒否する必要がある。
* クライアントと認可サーバーは、`scope`スコープと`authorization_details`を利用して、これらのリソースやアクションを決定する(オプション)。



## Resource Owner Password Credentials Grant

* 使用しない。

* リソースオーナーのクレデンシャルをクライアントに安全に公開できない。

* クライアントが無害な場合も、クレデンシャルが認可サーバー以外にも漏洩する可能性があり、攻撃範囲が拡大する。

  

## Client Authentication

* 認可サーバーは、クライアント認証を使用する必要がある。
* mTLS [RFC8705]や `private_key_jwt` [OpenID]など、クライアント認証に非対称（公開鍵ベース）の方法を使用することが推奨される。
* クライアント認証に非対称方式を使用する場合、認可サーバーは機微な対称鍵を保存する必要がないため、多くの攻撃に対して、より安全になる。



## Other Recommendations

* 認可サーバーはOAuthメタ情報を公開し、クライアントはこのメタデータを使用して、自身を構成することを推奨する。
* 認可サーバーは、クライアントが「client_id」または「sub」の値、または本物のリソースオーナーとの混乱を引き起こす可能性があるその他のクレームに影響を与えることを許可すべきではない。
* エンドツーエンドのTLSを使用することを推奨する。認可レスポンスは、暗号化されていないネットワーク接続を介して送信してはならない。
  * そのために、認可サーバーは、ループバックインターフェイスリダイレクトを使用するネイティブクライアントを除き、「http」スキームを使用するリダイレクトURIを許可してはならない。



## 参考情報

* [OAuth 2.0 Security Best Current Practice  draft-ietf-oauth-security-topics-18](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics)
PySparkにてStructType内のカラムにドット（.）が含まれるカラムにSELECTする方法

## 概要
PySparkにてStructType内のカラムにドット（.）が含まれるカラムにSELECTする方法を共有します。カラム名をそのまま指定すると下記のようなエラーメッセージが表示されます。

```text
AnalysisException: No such struct field strintg in strintg.in.struct
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/3a0cf9a9-0ea0-bb5c-b6c3-877963cb7bd2.png)

対応方法としては、ドットが含まれるカラムをバッククォート（`）で囲むことでSELECTができるようになります。シングルクォーテーション（'）ではないことに注意してください。

下記のようなスキーマの場合には、struct.\`strintg.in.struct\` と記載することで、データを取得することができます。カラムごとにバッククォートで囲む必要があるため、\`struct.strintg.in.struct\` のようにカラム全体を囲むだけではエラーが発生します。

```text
root
 |-- struct: struct (nullable = true)
 |    |-- strintg.in.struct: string (nullable = true)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/ca4741b9-b330-6747-a1a6-95f483f21f55.png)





## 手順
### 1. データの準備

```python
json_data ="""
{
    "struct":{
        "strintg.in.struct": "struct_1"
    }
}
"""

df = spark.read.json(sc.parallelize([json_data]))
# df.display()
df.createOrReplaceTempView('tmp_nested_columns')

df.printSchema()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c7461a2d-ab55-fadd-d68f-843718c4a721.png)


### 2. DataframeでSELECTする方法

```python
df_2 = df.select('struct.`strintg.in.struct`')

# df_2.display()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/bb743384-60f8-490f-8d38-25414fad7058.png)

### 3. SQLでSELECTする方法

```python
%sql
SELECT
  struct.`strintg.in.struct`
  FROM
    tmp_nested_columns
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/cc4abe28-4765-29f2-cb68-c98f75028f94.png)
ランダム処理

##ポイント
➀機械学習などでは、特にランダム処理が必要となる。データに対して相関性など依存関係をもたせるとデータ分析に影響をもたらす可能性があるためである。
➁ランダム処理には大きく、乱数生成と用意されデータのシャッフルを行う　二つのやり方に分類される。
##ランダム処理のまとめ一覧

```Python
import random #ランダム処理に必要なライブラリのインポート
```

・データの準備

```Python
#0～9のリスト生成
a = list(range(10))
print(a)
>>>[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
```
・データのシャッフル

```Python
#リストのシャッフル
random.shuffle(a)
print(a)
>>>[0, 1, 9, 5, 6, 4, 2, 8, 3, 7]
```
・シャッフルしたデータを固定する。

```Python
'''データをシャッフルするごとにリストの中身が異なるのは不便なことがある。
seedを用いることで、シャッフルの固定化を行うことができる。'''
c = list(range(5))
random.seed(0)
random.shuffle(c)
print(c)
>>>[2, 1, 0, 4, 3]
```
・データ抽出

```Python
#リストから三つのデータを抽出し、新規リストを作成。その後、シャッフルを実行
#母集団からデータの一部を標本として、抽出するときに有効
b = random.sample(a, 3)
print(b)
>>>[4, 9, 2]
```
・整数の乱数を生成する

```Python
sample_list = ['転職', 'あきらめて会社に居残る', '様子をみる']
#0～2の値をランダム生成
index=random.randint(0,2)
sample_list[index]
>>>様子をみる
```

・浮動小数の乱数を生成する

```Python
#floatのランダム生成(1～3)
judge=random.uniform(1,3)
if judge >1.5:
  print('乱数は1.5より大きいです')
else:
  print('乱数は1.5以下です')
```

・文字列のなかから文字をランダムで取得する

```Python
#文字列の中から、ランダムで文字を取得する
value=random.choice('abcdefg')
value
>>>b
```

・numpyを用いて、ランダムな行列を生成する

```Python
import numpy as np
#numpyを用いることで、簡単に行列に関するランダム生成を行うことができる。
arr1 = np.random.rand(4, 4)  # 4 x 4の配列の乱数
print(arr1)

arr2 = np.random.rand(3, 2, 2)  # 3 x 2 x 2の配列の乱数
print(arr2)
>>>
[[0.41656682 0.2629626  0.14942424 0.3543975 ]
 [0.51200162 0.23385965 0.62659274 0.19056221]
 [0.27613723 0.45423013 0.46009073 0.50387105]
 [0.93519298 0.88835726 0.44611031 0.62408758]]
[[[0.75928824 0.55752824]
  [0.50373056 0.88856187]]

 [[0.97135706 0.12369758]
  [0.53365778 0.02798405]]

 [[0.77609176 0.9043028 ]
  [0.7760245  0.64095079]]]
```
Markdownのリンクを「別タブで開く」に変換するスクリプト

Markdown記法では、リンクは次のように書きます。

```markdown
[リンク先の説明](URL)
```

これを、別タブで開くようにするには（Markdown記法ではHTMLを使えることを利用して）次のHTMLに変換すればOKです。

```markdown
<a href="URL" target="_blank" rel="noopener noreferrer">リンク先の説明</a>
```

Webブラウザーのエディター上（例えば、はてなブログ）でMarkdownを書くときに、この変換を一発でやってくれるスクリプトを作りました。ブックマークレットにして使っています。

```javascript
javascript:(function(){
  const t = document.querySelector('#body');
  t.value = t.value.replace(/\[(.*?)\]\((.*?)\)/g, '<a href="$2" target="_blank" rel="noopener noreferrer">$1</a>');
})();
```
C# DateTime.Part1

##Datetimeの扱い方

>C#でのDateTime型を定義して宣言するときは


```C#
var employee = new Employee
{
HireDeta = new DateTime
}
```
:::note alert
必ずnewをつけるようにしてください。
:::




>Datetimeを呼び出す時


```C#
var enloy
{
   NUmber = 352,
   FirstName = "涼太",
   LastName = "田中",
   HireDate = new DateTime(2015, 10, 1)
};
Console.WriteLine("作業員番号{0}の{1}は、{2}年に入社しました。",
   employee.Number, employee.FullName, employee.Year);
```


- DateTimeの後ろにYearをつけると**2015**が代入される。Dayだと**1**、Monthだと**10**となる。
searchアクション

１.ルーティング設定をする(app　-　config　-　routes.rb)

　　　　　collection do
  　　　　　  get 'search'
    　　　　　end

2.コントローラーに「searchアクション」を定義する(　app - controllers - places_controller.rb)

     def search
      @places = Place.search(params[:keyword])
     end

3.モデルに、self.search(search)を設定する(app -models　-place.rb)

　def self.search(search)
    　　if search != ""
      　　Place.where('name LIKE(?)', "%#{search}%")
    　else
      　　Place.all
    　end 
     end
GitHub Pages と同じ CORS 設定を nginx.conf で

# nginx.conf の設定文法の確認

```
add_header Access-Control-Allow-Origin *;
```
といった感じで書けば良いところです。

設定するべきヘッダーがいくつかありますが、センスの良い設定の仕方を盗むために　GitHub Pages はどのようにしているか確認してみます。

# GitHub Pages の挙動
https://optgeo.github.io/one-voice/ をウェブインスペクタで見たところ、次のような感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/6b63824b-e3e7-cb5f-c15b-6af386ed475d.png)

意外なことに、`access-control-allow-origin: *`だけですね。これをいただきます。

# nginx.conf への追加
こんな感じで追加しました。ただし、私の作業の場合、編集した実際のファイルのパスは `/etc/nginx/sites-enabled/default` です。

```
server {
  listen 80;
  root /somewhere/docs;
  index index.html;
  server_name x.optgeo.org;
}

server {
  listen 443 ssl http2;
  server_name x.optgeo.org;
  root /somewhere/docs;
  ssl_certificate /etc/letsencrypt/live/x.optgeo.org/fullchain.pem;
  ssl_certificate_key /etc/letsencrypt/live/x.optgeo.org/privkey.pem;
  ssl_dhparam dhparam.pem;
  add_header Strict-Transport-Security "max-age=15768000; includeSubdomains";
  add_header Access-Control-Allow-Origin *;
}
```

# テストと再起動

- テストは `sudo nginx -t`
- サーバ再起動は `sugo nginx -s reload`

# 動作確認
https://x.optgeo.org/hrlulc/

をウェブインスペクタで確認して、設定が問題なく反映されていることを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102082/3f34e5a2-1140-1030-5cf0-b5d3d457dd44.png)

確かに、`access-control-allow-origin: *` が付与されていることを確認できました。
【mariaDB】データベースの中身の確認について

## 環境
Ruby on rails 6.1.4
ruby 2.6.5
capistrano
mariaDB 5.5.68

## 経緯
AWSのEC2を使った環境構築をしています。
capistranoを使い自動デプロイを完了しています。

ローカル環境ではSequel Proを使っていたので、ローカルで保存した情報はすぐ確認することができました。
しかし、本番環境のデータベースの中身を確認する方法がわからず。

素人丸出しの「mariaDB　中身　確認」だとかで検索しましたが出てくるのは「select * from モデル名で中身見れますよ〜」ばかりでした。（初心者すぎて調べ方が分かっていない）

そもそもDBにたどり着く方法がわからず悩んでいたのですが、なんとか辿り着けたので備忘録を兼ねて記事に残そうと思います。

## コード


ターミナル内
まずEC2へログインします

```
#ホームディレクトリに移動
xxxx@yyyynoAir ~ % cd

#sshディレクトリに移動
xxxx@yyyynoAir ~ % cd .ssh/

#EC2へログイン（ssh -i ダウンロードした鍵の名前.pem ec2-user@作成したEC2インスタンスに紐付けたElastic IP）
xxxx@yyyynoAir .ssh %　ssh -i ００００xxxx.pem ec2-user@12.345.67.890

#ログインできればEC2のロゴ？が出現します
       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

```


ログイン後

```
#currentディレクトリに移動
[ec2-user@ip-123-45-67-8 ~]$cd /var/www/アプリケーション名/current

#mysqlへアクセスするコマンドを入力
[ec2-user@ip-123-45-67-8 current]mysql -u root -p アプリケーション名_production

#パスワードを求められるので入力（見た目上は何も表示されませんが入力されているので完了後enterを押す）
Enter password: 

#DBの中に入っているので、select文を使って検索する
MariaDB [アプリケーション名_production]> select * from stores \G;
```

流れとしては上記の通りです。
mysqlのパスワードがわからない方はEC2内のホームディレクトリ[ec2-user@ip-123-45-67-8 ~]へ戻ってもらい「env」と入力すればパスワードが確認できるはずです。

また、select文の\Gはターミナル上で表示されるデータが見やすくなる（抽象的ですいません）ので使っています。


以上です。
ローカルでのデータはすぐ目視で確認できていたので、いざ本番環境のデータを見るとなったときに「どこ見に行けばいいの？」と思ったので作成しました。
内容に不備がございましたらご指摘いただけますと幸いです。
SESAME3 Web APIの開閉操作をPHPで実装してみた

[candyhouse公式のドキュメント](https://doc.candyhouse.co/ja/SesameAPI)ではPHPでの実装方法が見つからなくて色々苦心したので記事にまとめてみました


使用環境
PHP 7.3.22

使用ライブラリ
[cryptlib/cmac](https://packagist.org/packages/cryptlib/cmac) dev-master（2021/09/11時点）

#手順
まずはAPI使用に必要な情報をSESAMEのシェア用QR（オーナー権限）から取得
公式だと手順が面倒くさかったけれど、便利なツールがあったのでこれを使用

https://sesame-qr-reader.vercel.app/

使うのは以下の項目

- UUID
- Secret Key

次に、[SESAMEのデベロッパーサイト](https://dash.candyhouse.co/)にログインしてAPI_KEYを取得

# 実装

AES-CMAC をPHPで実装してある記事が見つからなかったので、試行錯誤の結果です
基本的には公式ドキュメントのJSとPythonの実装を足して、PHPのライブラリの仕様に沿わせた感じです


```php
use CryptLib\MAC\Implementation\CMAC;
define('SCRET_KEY', '****')
define('API_KEY', '****')
define('UUID', '****')

// 履歴に残る名前。半角しか使えないらしい
$history = base64_encode('WEB API');
// 操作コマンド
$cmd = 88; // toggle:88/lock:82/unlock:83
$hasher = new CMAC();
$key = hex2bin(SECRET_KEY);
$time = strtotime(date("Y/m/d H:i:s"));

// big endianでバイナリ化されていたので、反転してlittle endianに変換
$msg = substr(strrev(hex2bin(dechex($time))), 1);
$sign = bin2hex($hasher->generate($msg, $key));
$data = compact('cmd', 'history', 'sign'));

$url = "https://app.candyhouse.co/api/sesame2/" . UUID . "/cmd";
$method = 'POST';
$header = [
    "Content-Type: application/json",
    "x-api-key: " . API_KEY
];
$content = json_encode($data);
$options = [
    'http' => compact('method', 'header', 'content')
];
echo file_get_contents($url, false, stream_context_create($options));
```

備忘録として書いたのでわかりずらいところもあるかと思いますが、誰かの参考になれば。。
CMACのところとか、もっといい書き方やご指摘、不明点などあればコメントください！！
[メモ] Docker「ruby:3.0-slim-buster」に Rails6 (簡素版) を導入してみる (Django使用経験あり)


# 概要

「Ruby経験あり、Rails 経験なし、JavaScript アプリ開発経験なし」の観点で、
御著書 [『Railsの教科書』](https://railstutorial.jp/textbook) で Rails6 の学習をしてみたときの記録である.

このとき、Dockerイメージ「ruby:3.0-slim-buster」に対して Rails6 を導入してみたので、
書き残しておく.　また、Django を用いたバックエンド開発経験はあるので、その視点でメモも
書いてみた.

なお、ここでの "簡素版" とは「Nginx や PostgreSQL や Unicorn などは導入しない」[^1] という意味である.

　
# 手順のみ

実行時の UID は root である.
なお、「ruby:3.0-slim-buster」 は Debian 10 なので、Ubuntu 18.04 にも転用できるはずである.

基本的には次の公式ドキュメントの手順を実施するのだが、少し補足してみた.
・https://guides.rubyonrails.org/getting_started.html

```bash
#!/bin/bash
apt update -y
apt install -y autoconf bison build-essential libssl1.1 libyaml-dev \
               libreadline-dev zlib1g-dev libncurses5-dev libffi-dev \
               libgdbm-dev sqlite3 libsqlite3-dev

apt install -y curl
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

cat <<'EOL' | tee -a > $HOME/.bashrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
EOL

. $HOME/.bashrc

nvm install --lts
npm install -g yarn
gem install rails
```


# 手順 + 個人的メモあり

```bash
#!/bin/bash
apt update -y

# 推測混じりになるが、SQLite3 インストールに加えて、DB操作 (SQLクエリ発行やマイグレーション) や、
# SSL通信に必要なパッケージをインストールしているのだろう.
apt install -y autoconf bison build-essential libssl1.1 libyaml-dev \
                    libreadline-dev zlib1g-dev libncurses5-dev libffi-dev \
                    libgdbm-dev sqlite3 libsqlite3-dev

apt install -y curl

# NVM のインストールをする. 後段の Node.js と npm をインストールするため. (後述の「補足」を参照)
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

# NVM を使うための設定を $HOME/.bashrc に追記する.
cat <<'EOL' | tee -a > $HOME/.bashrc
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
EOL

# NVM を使うための設定を有効にする
. $HOME/.bashrc

# Node.js をインストールすると、同時に npm もインストールされる. (後述の「補足」を参照)
nvm install --lts

# npm を使って Yarn をインストールする (yarn -v でバージョン表示されればOK)
npm install -g yarn

# rails をインストールする (Django における pip install Django に相当する)
# rails -v でバージョン表示されればOK
gem install rails
```


# 補足

|項目|URL|
|:--|:--|
|npm, nvm, Node.js のメモ|https://qiita.com/robozushi10/items/f8e1e2cae94f87b98acc|
|npm, nvm, yarn のメモ|https://qiita.com/robozushi10/items/fabbd40e560557c7394e|


# 参考にした情報

## 書籍

|書籍|URL|
|:--|:--|
|『Railsの教科書』|https://railstutorial.jp/textbook|

## 記事

|URL|
|:--|
|https://qiita.com/ashketcham/items/48d64e960d436f8b6f78|
|https://qiita.com/pharma_tech3/items/2ab578eb5b07ff0ca296|
|https://qiita.com/GalaxyNeko/items/630ac869d3bbbe93034b|
|https://qiita.com/masatwork/items/1b5d190cc76f5eeffbb7|


以上

[^1]: Rails 詳細は不明だが、Django でも Nginx, PostgreSQL, Gunicorn の組み合せがあるので、推測可能である
Spring Boot学習者が他言語のWebフレームワークを触ってみて気づいたこと

こんにちは。ワタナベトシヒロです。
私はJavaのWebアプリケーションフレームワークであるSpring Bootを学習してきましたが、今回は他の言語のフレームワークも触ってみました。
Spring Boot(Java)、Laravel(PHP)、Ruby on Rails、Django(Python)を比較して、気づいたことを挙げていきます。
ただし、Spring Boot以外のフレームワークでは簡単なCRUD処理のAPIを実装しただけなので、フレームワークへの深い理解はできていません。

# Spring Bootの特徴

## コマンドを入力する機会が少ない？

Spring Bootのプロジェクト作成はWeb上で行ったり、IDEのGUI上で行うことが多いです。

また、LaravelやRailsではモデル作成やコントローラー作成用のコマンドがありますが、Spring Bootではコマンドを使ってファイルを作成する例は見たことがありません。

Spring Bootでは他のフレームワークと比べてCLIを操作する機会が少ない気がします。

## DBのテーブルの作成はSQLで行う

Laravel、Rails、Djangoにはマイグレーションという機能があり、SQLを書かなくてもDBのテーブルを作成できますが、Spring Bootではフレームワークの機能を使わずにSQLでテーブルを作成しておくのが一般的だと思います。

## プロジェクト作成時に生成されるコード量が少ない

最初に作成されるjavaファイルは3つだけで、最低限の記述しかありません。

htmlファイルも用意されておらず、初期状態でアプリを起動してアクセスしても何も表示されないのはSpring Bootだけです。

ただし、ディレクトリの階層は深く、初期設定では無駄なディレクトリ構成に感じてしまいます。
Spring Bootはパッケージ数が多い大規模なアプリのために設計されているのかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1183281/24a895f3-3ad6-ea5a-b8ee-56c3987360d6.png)

# Laravel

## プロジェクト作成時に生成されるファイル数が多い

Laravelはプロジェクト作成時点でファイル数が多く、ディレクトリ構成もしっかり決められています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1183281/8785ff2c-0707-570c-1584-7517d11739a6.png)
↑ Spring Boot、Laravel、Rails、Djangoの4つの新規プロジェクトをまとめたGitリポジトリのコード割合です。BladeはLaravelのテンプレートエンジンなので、約7割がLaravel関連のコードで占められていることになります。

# Ruby on Rails

## Windowsでの開発が難しい

WindowsでRailsの開発をしようとすると、エラーに遭遇することが多く、特に環境構築で苦戦しました。

WindowsのWSL2という機能を使い、Linuxの仮想環境で環境構築をしてみましたが、それでもスムーズにいきませんでした。
(謎の警告が出たり、Rubyのインストール時に1時間以上インストール中と表示され続ける問題がありました)

# Django

## 同名のフォルダやファイルが多くなりがち？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1183281/def8804c-3e82-0340-4632-8463660eed4c.png)

`django-admin startproject <アプリ名>`でDjangoプロジェクトを作成すると、<アプリ名>のフォルダが作成され、その中に同名の<アプリ名>のフォルダが作成されます。

また、`__init__.py`やurls.pyなど、同名のファイルが複数作られることが多いですが、このように同名のフォルダやファイルが多いと紛らわしいのでは？と思いました。
【Python】SBI証券に自動ログインしてみた

#はじめに
皆さんはPythonを使って何を実現したいでしょうか。
私は毎日の単純作業を自動化し、Lineに通知することを実現したいと思っています。
Lineは毎日使うアプリだし、LineNotifyへの連携も容易です。

証券会社のHPへログインした後に毎日確認したことはありますか？
そんな第一歩としてまずは自動ログインしてみました。

#環境
Python3.9
macOS Catalina10.15.7
Chrome 93.0.4577.63

#事前準備
####1.Python3.X系をインストールします。（詳細は割愛します）
####2.seleniumをインストールします。
ターミナルを起動して以下のコマンドを入力します。管理者パスワードを入れるとインストールできます。

```
  $ sudo pip3 install selenium
```
この時、macOSにpython2.Xが既にインストールされている場合[pip3]ではなく[pip]でインストールした場合少しはまりますのでご注意ください。詳細は以下です。

https://qiita.com/hirockio2206/items/450e92c7d863c18a7e4d

####3.ChromeDriverをダウンロードして好きな場所に配置します。
今回は以下に配置します。

```
/Users/Hiroki/Info/chromedriver
```


ダウンロード前にまずmacにあるChromeブラウザのバージョンを確認します。
Chromeを開く　＞　右上の「・・・」(設定)　＞　[ヘルプ]　＞ [Google Chromeについて]
今は「93.0.4577.63」ですね。
![スクリーンショット 2021-09-11 7.42.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/8214c6a7-caca-c9d1-f819-3c13da095dba.png)

ChromeDriverをダウンロードする。以下のサイトにあります。
https://chromedriver.chromium.org/downloads
![スクリーンショット 2021-09-11 7.44.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1966337/8dbf59be-9a60-8442-4c64-4fbe4cb7cd1a.png)
Topページにさっそく「Supports Chrome version 93」と記載のあるChromeDriverがありました。今回はChromeブラウザのバージョンが93なので、これでOKです。

####4.IDとPWファイルを用意します。
方法は以下をご参考ください。

https://qiita.com/hirockio2206/items/cab1dde99810257fe089

####※はまり注意※
IDやPWファイルに「改行」が入っているとSeleniumは[Enter]として認識します。
予期せぬ動きをしますので気をつけて下さい。

#プログラム
```SBI_login.py
from selenium import webdriver#←seleniumからwebdriverをインポートします。変更不要です。

#↓IDファイル名や置き場を書き換えて下さい。
ID = open('/Users/Hiroki/Info/ID.txt', 'r', encoding='UTF-8')
IDdata = ID.read()

#↓PWファイル名や置き場を書き換えて下さい。
PW = open('/Users/Hiroki/Info/PW.txt', 'r', encoding='UTF-8')
PWdata = PW.read()

#↓chromedriverの置き場を書き換えて下さい。
driver = webdriver.Chrome("/Users/Hiroki/Info/chromedriver")
driver.get("https://www.sbisec.co.jp/ETGate")
        
#↓ログインIDの自動入力です。変更不要
elem_id_word = driver.find_element_by_name("user_id")#←現在のSBI証券の要素名
elem_id_word.send_keys(IDdata)

#↓ログインPWの自動入力です。変更不要
elem_pw_word = driver.find_element_by_name("user_password")#←現在のSBI証券の要素名
elem_pw_word.send_keys(PWdata)

#↓ログインボタンの自動入力です。変更不要
elem_login_btn = driver.find_element_by_xpath("/html/body/table/tbody/tr[1]/td[2]/form/div/div/div/p[2]/a/input")#←現在のSBI証券のログインボタンのxpathです。
elem_login_btn.click()
```

#最後に
ログインできましたでしょうか。
これは第一章として、ログイン後何をしたいかが重要かと思います。
私はIPOの有無を確認してLine通知しています。
ご参考になれば幸いです。
【AWS】AWSを勉強していく中で「？」ってなった単語をまとめていく② -EC2編-


#前回の続き

https://qiita.com/nao0725/items/618ac7efc72db923a1fc


#目的

* 自分用のメモ
* 単語の意味と役割を掴んでイメージを把握する

#EC2を運用する上で出てきた単語

##EC2
* Amazon Elastic Compute Cloud
* AWSのクラウド上でサーバーを実行するためのサービス
* 単一ではなく複数の仮想サーバー（インスタンス）を実行する
* EC2を利用することで、OSを乗せた仮想環境をクラウド上にすばやく作ることができる

https://techplay.jp/column/537


##インスタンスタイプ

* 用途別に集められた「インスタンスファミリー」と、CPUなどのスペックを示す「インスタンスサイズ」から構成されている
* インスタンスファミリーの数字は「世代」を表していて、数字が大きければ大きいほど新しい

###インスタンスファミリー

* 「汎用」「コンピューティング最適化」「メモリ最適化」「高速コンピューティング」「ストレージ最適化」の5種類に分類される
* それぞれのシステムによって設定する

https://www.bit-drive.ne.jp/managed-cloud/column/column_22.html


##セキュリティグループ

* EC2インスタンスなどに適用するファイアウォール機能で、主にVPCリソースのトラフィックを制御するのに使われる
* EC2インスタンスへのアクセスを"許可"したり、トラフィックを"制御"する役割がある
* ファイアーウォールとはネットワークの門番のこと(ウイルス等から守る)

###インバウンドルール

* セキュリティグループに関連付けられたインスタンスにアクセスできるルール

###アウトバウンドルール

* セキュリティグループに関連付けられたインスタンスからどの送信先にトラフィックを送信できるか（トラフィックの送信先と送信先ポート）を制御するルール

##ネットワークACL

* サブネットに属するすべてのインスタンスに対して適用されるファイアウォール
* 許可と拒否のルールを定義する

https://ex-ture.com/blog/2021/07/14/securitygroup-and-networkacl/


##EC2のIPアドレスの種類

###パブリックIPアドレス

* インターネットから接続できるアドレス
* インスタンスを再開しても同じIPアドレスは付与されない


https://dev.classmethod.jp/articles/aws-ip-address-design/

###プライベートIPアドレス

* EC2インスタンスにアタッチされているすべてのENIに対して、個別に付与できるIPアドレス
* インスタンスを再開したときに同じIPアドレスのままになる

####ENI

* Elastic Network Interface
* 仮想ネットワークインターフェースのこと
* インスタンスにはデフォルトで１つのENIがアタッチ（仮想化環境に追加すること）されており、必要に応じて複数のENIをアタッチできます。

https://e-words.jp/w/%E3%82%A2%E3%82%BF%E3%83%83%E3%83%81.html

###EIP

* 固定でEC２インスタンスに付与できるパブリックIPアドレス
* 開放しない限り,付与されたまま使うことができる

##キーペア

　* EC2にログインするための公開鍵と秘密鍵のためのサービス
　* インスタンスにSSHで接続するため、インスタンスに対して設定する公開鍵
　* SSHの仕組みとして公開鍵に対応する秘密鍵を持っているユーザーだけがSSHでインスタンスにログインすることが可能
　* キーペアを持つことでログインの安全性が保たれている

https://wa3.i-3-i.info/word17048.html


##Amazon EBS

* Elastic Block Store
* もっともよく使われるEC2インスタンスのストレージ
* OSやアプリケーション、ユーザーのデータなどを格納する
Arduinoブートローダー有無

# Arduino Bootloader有無と書き込み
Arduino搭載マイコンATmega328pのブートローダー有無で、プログラムの書き込み状況を確認する。

## ブートローダーなしATmega328p
秋月電子などで、[ブートローダーなしATmega328p](https://akizukidenshi.com/catalog/g/gI-03142/)が売られている。これをArduinoボードに入れて確認する。

### 普通に書き込み（エラー）
通常、書込装置は「AVRISP mkII」が選択されている。
![通常の書き込み装置のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/fcf2c03f-17c8-e34a-9122-490254640a64.png)
ブートローダーなしATmega328pのArduinoに対して、あるプログラムに対して「マイコンボードに書き込む」（通常のUSBケーブル経由）を実行。
![書き込み装置を使って書き込みのコピー2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/4d544a4a-ccae-e3e0-c699-97988de8eb86.png)
すると、下記のように書き込みできない旨のメッセージが表示される。

```
（途中省略）

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 9 of 10: not in sync: resp=0xcc

avrdude: stk500_recv(): programmer is not responding
avrdude: stk500_getsync() attempt 10 of 10: not in sync: resp=0xcc

avrdude done.  Thank you.

マイコンボードに書き込もうとしましたが、エラーが発生しました。
このページを参考にしてください。
http://www.arduino.cc/en/Guide/Troubleshooting#upload

```

### ブートローダーの書き込み
次にATmega328pに、書き込み装置「USBasp」を使って、ブートローダーを書き込む。これは、Amazonなどで安価に購入できる。例えば、[これ](https://www.amazon.co.jp/KKHMF-AVRプログラマ-USBaspライタ-AVRシリーズ-10ピン-6ピンISPアダプタ/dp/B08L93ND1K/ref=sr_1_7?__mk_ja_JP=カタカナ&dchild=1&keywords=USBasp&qid=1624093514&sr=8-7)など。10ピン-6ピンISPアダプタが付属していない場合もあるので注意されたし。これをArduinoに接続する。AruduinoのICSP端子のピン配置については、[こちら](https://umtkm.github.io/2018/07/25/arduino-pro-micro-isp/)などを参照。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/dcfea1bb-6c45-f219-bbf7-1d7c630a72c3.jpeg", width=90%>

USBaspについては、[こちら](https://ht-deko.com/arduino/usbasp.html)に詳しい説明あり。

#### Windowsでの設定
USBaspをWindowsで使用するには、少々設定（ドライバ変更）が必要である。先ほどの[サイト](https://ht-deko.com/arduino/usbasp.html)を参考に、ツールZadigを使い、「libusbk」となるように設定する。デバイスマネージャで、
![libUSBK2のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/10cc7415-6925-fb6c-1afe-d4712e72b560.png)
のようになっていればOK。

#### Arduino IDEで「ブートローダを書き込む」
書込装置として「USBasp」を選び、「ブートローダを書き込む」を選択。
![USBasp1のコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/4948383f-41fa-ed1f-404b-559b3095fee7.png)
成功すると次が表示される。
![ブートローダー書き込み２.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/9c612fb9-89f7-a991-9e9c-e20363f05cb3.png)

ちなみに、書込装置として「AVRISP mkII」を選び、「ブートローダを書き込む」を選択しても書き込めない。「ブートローダの書き込み中にエラーが発生しました。」というエラーが発生する。

### ブートローダー書き込み後に時系列で確認
ここから順番に、各種確認の実施。

１　書込装置として「AVRISP mkII」を選び、あるプログラムを「マイコンボードに書き込む」（通常のUSBケーブル経由）は書き込み成功。
２　次に、書込装置として「USBasp」を選び、「書込装置を使って書き込む」（USBasp経由）は書き込み成功。ただし、ここでブートローダーはなくなっている（はず）。
![書き込み装置を使って書き込みのコピー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/634816/766b081b-d00b-8c8d-f44e-d192a32f1ee9.png)
３　次に、書込装置は「USBasp」のまま、「マイコンボードに書き込む」（USBasp経由）は書き込み失敗。
４　次に、書込装置として「AVRISP mkII」に戻し、「マイコンボードに書き込む」（通常のUSBケーブル経由）は書き込み失敗。ブートローダーがないためだろう。
５　次に、書込装置として「USBasp」を選び、「ブートローダを書き込む」（USBasp経由）を実行する。（前述と同じ）
６　次に、書込装置として「AVRISP mkII」に戻し、「マイコンボードに書き込む」（通常のUSBケーブル経由）は書き込み成功。

期待どおりの結果である。
Arduinoでセンサーデータを平均化するプログラム

センサーデータがノイズなので変なデータが取得されることがある
[配列に格納した数値を昇順ソート](https://webkaru.net/clang/array-sort-ascending-order/)を参考に平均化を考えてみた.

##対策：１０個のサンプルデーターで真ん中の４つの平均値を取る

プログラムですること
　　１．データーをテーブル０~９に格納する
　　２．収集したデータをソートする
　　　　　※大小どちらでもよい
　　３．テーブル３，４，５，６を合計した平均値を計算する

```
 
 for (i=0; i<total; ++i) {
    for (j=i+1; j<total; ++j) {
      if (num[i] > num[j]) {
        tmp =  num[i];
        num[i] = num[j];
        num[j] = tmp;
      }
    }   
  }
 
    sum=num[3]+num[4]+num[5]+num[6];          
  
    avg=sum/4;


```
１０回に１回しか平均化できないが
まずはこれで試してみる
次に１回ごと行う方法を考えてみる

## 最後に
平均化やってみて奥が深いのがわかった
処理速度とのバランスを考えてプログラムする必要があるので
段階的にバージョンアップしていきます。
Unity TimelineのPlayable Trackとその実装方法について

## 記事の目的
Playable Trackとその実装方法について簡単にご説明すること

## レポジトリ
https://github.com/TomohiroHibino600/PlayableTimelineTest

## Playable Trackとは？
アニメーションや音源の再生時間を管理するTimeLine上に、スクリプト制御を設定できるTrack
下記の動画ではPlayable Trackを用いて、スライドの切り替えを行っている
※同時にAnimation Trackで球のサイズを大小している
[![Playing Slide TimeLine](http://img.youtube.com/vi/Si_4G2xJgKY/0.jpg)](http://www.youtube.com/watch?v=Si_4G2xJgKY "Playing Slide TimeLine")

## Playable Trackのメリット
- 時間管理が楽
- 動画のタイミングに合わせた空間演出が可能(プレゼンや研修動画などを3Dデザインできる)
- スクリプトが分からない人に仕事を任せられる

## 設定方法
1. PlayableBehaviourクラスを継承したクラスで、振る舞いを設定

```C#:SlideChange.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class SlideChange : PlayableBehaviour
{
    public Sprite slideImage;
    public GameObject spriteObject;

    //タイムライン開始時実行される
    public override void OnGraphStart( Playable playable ) {
        base.OnGraphStart( playable );
        
        //スライドを表示するGameObjectを取得
        spriteObject = GameObject.FindGameObjectWithTag("Window");
    }

    //PlayableAsset(コマ)再生時実行される
    public override void OnBehaviourPlay( Playable playable, FrameData info ) {
        
        //スライドの画像(Sprite)を変更
        spriteObject.GetComponent<SpriteRenderer>().sprite = slideImage;
    
    }
}
```


2. PlayableAssetクラスを継承したクラスで、振る舞いをTrack上に差し込めるAssetを作成

```C#:SlideAsset.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;

public class SlideAsset : PlayableAsset
{
    public Sprite image;

    public override Playable CreatePlayable( PlayableGraph graph, GameObject owner ) {
        //PlayableBehaviourを継承したSlideChangeクラスを元に、PlayableAsset(コマ)を作る
        var player = ScriptPlayable<SlideChange>.Create( graph );
        
        //SlideChangeクラスにあるプロパティを設定
        var behaviour = player.GetBehaviour();
        behaviour.slideImage = image;
        
        return player;
    }
}
```

```
※基本的にはPlayableAssetでコマの設定が出来、そのPropertyを設定できる。
ただしMonobehaviourを継承していないので、Scene内のものを取得したい場合は
    ExposedReference<Object>
といった記述が必要になる。
```

3. UnityのGUIでTimelineのPlayable Track上にPlayable Assetを挿入(右クリックで勝手に出てくる)
![add slide asset](https://user-images.githubusercontent.com/62923803/97622618-dd331c00-1a67-11eb-97d6-e279e5ed750a.jpg)

4. Assetにプロパティがあれば、AssetをクリックしたときにInspector上で表示される場所にデータを入れておく
![add propaty](https://user-images.githubusercontent.com/62923803/97623026-6ba79d80-1a68-11eb-8238-0ce9916093d9.jpg)
Elasticsearch KibanaのErrors alerts with Watcherの仕組みをshell scriptで作る

## Elasticsearch, KibanaのErrors alerts with Watcher is　何？
- Kibanaには[Errors alerts with Watcher](https://www.elastic.co/guide/en/kibana/6.8/errors-alerts-with-watcher.html)という機能がある
- この機能には、発生の閾値と時間間隔を指定すると閾値を越えた時にSlack通知などをすることができる機能である
- サーバのログ件数を補足する時などに利用できるが、この機能を利用するにはElasticsearchにログを挿入する必要がある
- 更にログを収集する為にLogstashやfilebeatなどを導入する必要がある

そこで、そこまで規模の大きくないサービスにおいて一定間隔でエラー件数を集計し、通知する為のshell scriptを作成してみる。
grepコマンドは非常に高速に動作する為、適切にログをローテーションさせれば、リソース効率よくログの監視ができる

(ELKはJavaで動作する為、小規模なサービスに使うにはリソース消費が激しくて無駄が多いので使いたくない)

## 実装したスクリプト
[こちらの記事](https://qiita.com/sifue/items/2a9aaf73a259ea350781)を参考に改良していく

```sh
#!/bin/bash

# ここで各エラーの件数を記録
ERROR_LINES=$(</var/run/hoge/error_lines)
WARNING_LINES=$(</var/run/hoge/warning_lines)

# ここで最後に実行したファイルが現在のファイルと同じか確認
LOGFILE_TIMESTAMP=$(</var/run/hoge/worker_timestamp)

# 作成した日のタイムスタンプを取得する
LOGFILE_TIMESTAMP_CURRENT=$(stat -c '%W' /var/log/hoge/error.log)

# もし。タイムスタンプが違ったらそれはローテーションされて新しいログファイルになっている
if [ "$LOGFILE_TIMESTAMP_CURRENT" != "$LOGFILE_TIMESTAMP" ]; then
  ERROR_LINES=0
  WARNING_LINES=0
  echo "$LOGFILE_TIMESTAMP_CURRENT" > /var/run/hoge/worker_timestamp
fi

# ここでエラーログからログレベル別に件数を集計する
ERROR_LINES_CURRENT=$(grep -c error /var/log/hoge/error.log)
WARNING_LINES_CURRENT=$(grep -c warning /var/log/hoge/error.log)

# 前回の実行からどのくらいエラー件数が増えたか確認する
# もし閾値よりもエラー件数が多かったらSlackに通知する
if [ $((ERROR_LINES_CURRENT-ERROR_LINES)) -gt 5 ]; then
  curl -X POST --data-urlencode "payload={\"username\": \"エラー報告Bot\", \"text\": \"直近5分間に$((ERROR_LINES_CURRENT-ERROR_LINES))件のerrorが確認されました\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZ
fi
if [ $((WARNING_LINES_CURRENT-WARNING_LINES)) -gt 10 ]; then
  curl -X POST --data-urlencode "payload={\"username\": \"エラー報告Bot\", \"text\": \"直近5分間に$((WARNING_LINES_CURRENT-WARNING_LINES))件のwarningが確認されました\", \"icon_emoji\": \":ghost:\"}" https://hooks.slack.com/services/XXXXXXXXX/YYYYYYYYY/ZZZZZZZZZ
fi

# 最後にエラー件数を更新する
echo "$ERROR_LINES_CURRENT" > /var/run/hoge/error_lines
echo "$WARNING_LINES_CURRENT" > /var/run/hoge/warning_lines

```

## 考察
- 永続化するデータをどこに保存するか、どんな形式で保存するかにすごく悩んだ
- 結果的には3つのデータを保存しておく必要があり、それぞれ別々に保存したが、もう少しスマート(CSVとか)に保存できる気がする
- もっといい方法があれば知りたいので是非インフラエンジニアの方はコメントして頂きたいです
yukicoder contest 313 参戦記

# yukicoder contest 313 参戦記

1時間遅れの参加だったけど、ABCが解けて嬉しかった.

## [A 1672 404 Not Found](https://yukicoder.me/problems/no/1672)

ステータスコードの値を100で割って4か5ならエラーコードですね.

```python
S = int(input())

if S // 100 in [4, 5]:
    print('Yes')
else:
    print('No')
```

文字列で処理してもいいですけどね.

```python
S = input()

if S[0] in '45':
    print('Yes')
else:
    print('No')
```

## [B 1673 Lamps on a line](https://yukicoder.me/problems/no/1673)

R<sub>i</sub> - L<sub>i</sub>≦10 という条件なので素直にシミュレーションすればいいです.

```python
from sys import stdin

readline = stdin.readline

N, Q = map(int, readline().split())

c = 0
t = [0] * (N + 1)
result = []
for _ in range(Q):
    L, R = map(int, readline().split())
    for i in range(L - 1, R):
        if t[i] == 0:
            c += 1
            t[i] = 1
        elif t[i] == 1:
            c -= 1
            t[i] = 0
    result.append(c)
print(*result, sep='\n')
```

## [C 1674 Introduction to XOR](https://yukicoder.me/problems/no/1674)

ちょっと考えると、どの A<sub>i</sub> でも立っていない LSB(Least Significant Bit / 最下位ビット)だと分かります.

```python
N, *A = map(int, open(0).read().split())

x = 0
for a in A:
    x |= a

for i in range(x.bit_length() + 1):
    if (x >> i) & 1 == 0:
        print(1 << i)
        break
```
mac ミューシックによるmp3変換書出方

MacによるMP4動画からmp3楽曲に変換
Finderで対象のMP4ファイルを選択し、右クリック(2本指タップ)
「選択したビデオファイルをエンコード」をクリック
Audio Onlyを選択して、「続ける」をクリック
しばらく待つと、m4aファイルができる
m4aをappleミューシック(旧iTunes)で読み込み、ファイル＞変換＞mp3 でmp3を作成
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/f5580eec-b369-c688-343a-7c3e0409f4a3.png" width="80%">
awsロードバランサー http https利用方

AWSでSSL化の際httpアクセスをhttpsへリダイレクトするしないのロードバランサー（リスナー）の設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/8b3f5c67-7747-c152-b9bf-dd912ef2a9d8.png" width="80%">

リダイレクトさせる設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/f9fc966c-8209-05d2-e16d-af0e4dd6e1fb.png" width="80%">
リダイレクトさせない設定
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/101462/18f4aefb-3aaa-1e64-afdd-db63335e083f.png" width="80%">
参考記事：https://qiita.com/nakanishi03/items/3a514026acc7abe25977