OmniAICreator/Qiita-1.07M huggingface dataset:
UnityでAndroidのbuild時に「Gradle build failed. See the Console for details」エラーが出た時の解決法

UnityでAndroid向けにbuildする際に「Gradle build failed. See the Console for details」というエラーメッセージがでてbuildできなかったのでその対処法を記述いたします。

**※このケースはAndroid StudioのAndroid SDKを使用している場合のみです**
**UnityのAndroid SDKを使用しているケースはこの限りではございません**

# 環境
- Windows10
- Unity Hub 2.4.5
- Unity 2020.3.25f1
- Android Studio 2020.3.1

今回、Android SDKはAndroid Studioのものを使っています。

環境の構築方法については以下の記事をご参照下さい。
https://qiita.com/Nossa/items/4b2c5026698ed4ab7d2b

ちなみに著者の環境では「JDK Installed with Unity」にチェックのままで問題ありませんでした。

# Unity側の設定
Unity側の設定を確認すると以下の状態です。

Edit > Preferences > External Tools > Android

![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/487172cd-0f0a-6812-b1dc-5a79d299afbc.png)

Android SDK を Android Studio のものを使用するようにしています。

# エラー内容
いざ build をしようと、
File > Build Settings
から「Android」を選択して「Switch Platform」をクリックした後、
「Build」をクリックすると以下のようなエラーが出ました。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/38df7202-9533-e53f-863f-c266be464cf3.png)

```
Gradle build failed. See the Console for details.
```

# 解決方法
https://stackoverflow.com/questions/68387270/android-studio-error-installed-build-tools-revision-31-0-0-is-corrupted

上記記事に載っていました。

SDK ビルドツールが31以上の場合、
なんと、**ファイル名を変える必要がある** のです。

著者もこの方法でエラーが解消されました。

## ファイル名を変える手順
一応手順を載せておきます。

- Android Studio で install した path に移動する
- Projects > More Actions > SDK Manager から path を確認
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/399610/c4a101c3-4cea-a7d8-5ec6-9b06e94347f8.png)
- SDK build ツールがインストールされた場所まで移動する


```
例：
C:\Users\admin\AppData\Local\Android\Sdk\build-tools\32.0.0
```

- d8.batのファイル名を以下のように修正する

```
d8.bat > dx.bat
```

- そして、lib フォルダ内にあるd8.jarのファイル名を以下のように修正する

```
d8.jar > dx.jar
```

これで、もう一度 build してみます。

はい、ちゃんと .apk ファイルが作成されて無事 build が成功しました。

このエラーで困っている方に少しでも参考になれば幸いです。

以上、有難うございました。
Google Drive上にあるCSVファイルをGoogle Colabratoryで読み込む

# Google Drive上にあるCSVファイルをGoogle Colabratoryで読み込む
## 目的
最近、Jupyter NotebookからGoogle Colabratory PROに環境を変えたので、備忘録として残します。
## Google Driveへのマウント
まず、Colabに以下のコードを入力し、Google DriveをColab上で読み込めるようにします。(Shift + Enterでコード実行)

```
from google.colab import drive
drive.mount('/content/drive')
```
ここで、Googleから
![スクリーンショット (324).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152634/c4ecc6ba-9908-f7bd-d48c-9d36045b6b7c.png)

Google ドライブに接続を選択します。

次に、Googleアカウントログイン画面に移動するので、ログイン手続きをします。

すると
![スクリーンショット (325)_LI.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152634/95d13ce3-f533-a408-6c39-76a663b92267.jpeg)
と表示されるので、Continueを選択します。

そして、`Mounted at /content/drive`と出力されれば、マウント完了です。

## 使いたいCSVファイルの階層に移動
このままCSVファイルを読み込もうとしようとしても。ホームディレクトリにいるのでCSVファイルが読み込めません。

そこでコマンドプロンプトと同様にcdコマンドを使うことでCSVファイルのあるフォルダに移動することができます。

Colabのセルに`cd 'drive/My drive/hoge/hoge/hoge'`入力します。(`/hoge/hoge/hoge` の部分を階層やフォルダ名に合わせて変える)

例えば、ドライブの`Colab Notebooks/movetest`にCSVファイルがあるとき

```
cd 'drive/My Drive/Colab Notebooks/movetest'
```
と入力し、実行することで
`/content/drive/My Drive/Colab Notebooks/movetest`と出力されます。これでディレクトリの移動ができました。

## CSVファイルの読み込み
CSVファイルの読み込む手法として、pandasの`read_csv()`を使用します。

以下のようなコードを入力、実行します。(ここではsampledata.csvというファイルを読み込みます。)

```
# pandasを導入、pdとして
import pandas as pd

# dfに見出しのあるデータを格納。
df = pd.read_csv('sampledata.csv')

# display()でdfをdataframe形式の表のレイアウトを保持して出力。
display(df)
```
これで
![スクリーンショット (327).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2152634/0ee3ec2b-2813-c467-5849-3cb3b67f7aac.png)
と読み込み確認できたので、完了です。

### 参考
https://blog.kikagaku.co.jp/google-colab-drive-mount

https://note.nkmk.me/python-pandas-read-csv-tsv/

https://punhundon-lifeshift.com/print_display_pprint
Vue CLI でビルドした時にルートパスになってしまう件の対処法

対処法が分かればすぐ解決できることだったので、メモです。

## 事象
Vue CLI でビルドしたファイルを Web サーバに配置して、確認！

あれ、画面が真っ白……。

コンソールには「こんな JS ファイルないよ！」というエラーが表示されていました。
HTML ファイルで指定している各ファイルパスが合っていないようです。

よくよく確認すると、相対パスで書いていたはずのものが、ルートパスに置き換わっていました。

```
// 相対パス
'./js/sample.js'  // ← こっちで書いたのに

// ルートパス
'/js/sample.js'   // ← こっちになっているのです…
```

Vue CLI では、特に指定していない場合は、ルートパスを指定する仕様のようです。
ドメイン直下に配置する場合は良いのですが、そうではない場合に困りますね…。

## 対処法
package.json と同じ階層に vue.config.js ファイルを作成します。
この vue.config.js ファイルに以下のコードを書きます。

```
module.exports = {
  publicPath: './'
}
```

そしてもう一度ビルドして適用。これだけです。簡単でしょう…？

割と時間を取ってしまった割に、3行のコードで解決できてしまいました。
未来の自分が忘れた時のために、ここに記録を残しておきます。
Linuxとは？

###ソフトウェア
コンピューターを動かすソフトウェアの事をＯＳと呼びます。
このOSの一種にLinuxがあります。
サーバー用、開発用、組み込み用に使用されています。
![My First Board (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2188773/2c89724e-ee9f-d71a-20a7-3dbdcb929050.jpeg)



###特徴
・共有できる（オープンソース）
・共有されている為、信頼性が高い
・サーバー運用でよく使われている。

###まとめ
Linuxとは、コンピューターを動かす為のOS
初心者が初心者に伝える「Dockerってなんやねん」

# この記事のターゲット

プログラミングを勉強して数年数か月、あるとき話していると、ある人が

**「前にDocker上でプログラミングしてたんですけど...」**

**私 : 「ど、ど、Docker ... ? なんやDockerて」**

ってなった人むけです。

# Dockerがうれしい物語

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1714399/17466eec-21b9-dae7-5cd5-cfe8e80e0ecc.png)

## エピソード1：前は動いてたのに

あなたは過去になにかしら自身のPCでプログラミングをしたことがある人です。
例えば

- Nodeってました

Node以外でも構いません。
npm(Nodeのライブラリ管理ツール)を使っていろいろインストールした自分だけの開発環境のPCです。
過去にいくつか複数のファイルでできた作品っぽいものを作っています。

ある日
**「なんかNodeで作業してたらよくわからんエラーでたぞ。ググったら『Node.js 14.3以前で実行してください』やて」**

使おうとしているライブラリがNode.js の少し前のバージョンじゃないと正常に動かないみたいです。
ところが自分のPCにインストールされているNode.jsは16.1

**「新しいNodeやと動かんのか。ググってバージョン変更するか」**

そこであなたはネットの情報をかき集め、Node.jsを一度アンインストールしてから再度インストールしてバージョンを変更しました。
苦労した甲斐あって、使おうとしていたライブラリが動きました。

ある日
**「この処理どうやって実装するんやっけな、前に書いたやつ動かして思い出そっと ... ... ... あれ、前は動いてたのに」**

> プロジェクトごとに求められるバージョンが異なる問題

## エピソード2：こんなんインストールしたっけ

**「僕のやりたいことを実現するには ... あ、これインストールすればいいのね」**

**「んー、思ってたのと違うなぁ、あ、違うやり方発見！ふむふむ XXX をインストールして ... 」**

後日
**「ダウンロード中にファイル整理しとこかな。Program filesの中身増えたなぁ、 ... なんか見覚えのないないようわからんファイルやたらあるけど、こんなんインストールしたっけ？」**

> いろんなプロジェクトでいろいろインストールした結果、ジャングル状態

## エピソード3 : どういうことだってばよ

**「もうわけがわからん、いったんいろいろインストールする前の状態にしよ」**

**「あれもこれも消して ... ... あれ、これ開発のためにインストールしたやつか・・・？」**

**「ものによってはパスは自分で消すのか ... これでいけたんやろうか・・・」**

**「あれ、一度消して再インストールしたはずなのに前の情報がちょこちょこ残ってる ... どういうことだってばよ」**

> アンインストールしてもたまにのこるカスファイルたち

## エピソード4 : 新しい開発環境に時間がかかる

**「この前は自宅のPCの環境で痛い目あったからな～、今度は慎重にやろっと ...」**

**「 ... 」**

**「インストールするもん多くて面倒 ...」**

> 環境の構築の仕方なんて覚えてないので再びQiita様とかZenn様とかの同じページを徘徊

＿人人人人人人人人人人人人人人＿
＞　それ、Dockerが解決します　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣

# 解決するには

エピソード1-3に関しては、

- プロジェクトごとに新しいPCを用意する

が一番わかりやすいし安全だろう(現実性はさておき)。
このPCはpython3.6で学校の授業用
このPCはPython3.8で趣味のプログラミング用
このPCはNode.js 14.2でまだなにするか決まってないけどNode触ってみる用 
...

要は **開発環境同士が干渉しあわなければいい**のである。
これを実現するうえでもっと現実的な方法として、

- PCの中にPCをつくる

方法がある。PC上でスマホだったり、エミュレーター(ゲーム機とか)を操作してる様子をみたことないだろうか。
windowの画面の中に(まるでリモートデスクトップのような)もう一つのwindowsの画面...とまではいかないが、 **環境変数やルートパス等が完全に元のOS(ホストOS)から隔離**されている。
これにより、「プロジェクトごとに新しいPCを用意する」を **1つのPCで実現が可能**になる。

が、

新品のスマホやPCを買ってもすでに最初から容量がいくらか埋まっているように、OSを1つ存在させるだけでもそこそこの容量を食う。
また、OSが2つになれば安直に考えて計算量2倍、すなわちメモリ2倍必要になってくる。

結論、
**たかが開発環境わけるだけのためなのに効率悪すぎ**

# それ、Dockerが解決します

dockerもまた、PCの中に異なる作業環境を作成するという点で上記と似ているが

- OSはホストOSのまま、環境変数とかルートパスは別なので効率良◎
    - プロジェクトごとに異なる作業環境を作成できる( => エピソード1,2 )
- もしインストールに失敗してわけわからなくなっても、簡単に作業環境を破棄できる( => エピソード3 )
- いろいろインストールする手順をスクリプト化し、同じ環境を少ないコマンドで実装する( => エピソード4 )

どうやって実現してるのか仕組みはちゃんとは知らないし、たぶんしっかりは知る必要もない。
とりあえずこの記事で知ってほしいのは、**Dockerを使えば上みたいな問題を回避できる**ということ。

# 参考

Dockerの導入、実際に仕組みがどうなっているのかや使い方は下記ページを参考にしてください。

↓↓↓ Docker概念 ↓↓↓
> 「Docker」を全く知らない人のために「Docker」の魅力を伝えるための「Docker」入門
> https://qiita.com/bremen/items/4604f530fe25786240db

↓↓↓ 導入 ↓↓↓
> 公式ページ
> http://docs.docker.jp/engine/installation/

↓↓↓ 仕組み・使い方 ↓↓↓
> いまさらだけどDockerに入門したので分かりやすくまとめてみた
> https://qiita.com/gold-kou/items/44860fbda1a34a001fc1
> Dockerを体系的に学べる公式チュートリアル和訳
> https://qiita.com/Michinosuke/items/5778e0d9e9c04038903c
Reactの環境構築

いつもyarn startで失敗してできなかったReactの環境構築
新しいノートパソコンを買ったので頑張ってみた記録

今回の流れはこんな感じです

1. Visual Studio Codeをインストール
1. Node.jsをインストール
1. yarnをインストール
1. create-react-appでReactアプリを作る
1. yarn startしてみる
1. yarn startできないエラーを解決する
1. もう一度yarn startしてみる

### 基本情報

OS：Windows 10

### 1. Visual Studio Codeをインストール

まずは以下リンクからVS Codeをインストール

https://code.visualstudio.com/download

インストーラは全部同意、他は何も気にせずok

### 2. Node.jsをインストール

以下のリンクからLTS版をインストール

https://nodejs.org/ja/

ここのインストーラも同意、ok

インストール終わったらコマンドプロンプトで以下のコマンドを実行
バージョンが返ってくればok

```
$ node -v
v16.13.2
```

### 3. yarnをインストール

仕事ではnpmじゃなくてyarnを使ってるのでyarnにしたい！
ので以下のコマンドをコマンドプロンプトで実行

```
$ npm install --global yarn
```

完了したらコマンドプロンプトで以下のコマンドを実行
これもバージョンが返ってくればok

```
$ yarn --v
1.22.17
```
<br>

いったん環境構築は完了したので、アプリ作って動かしてみる

### 4. create-react-appでReactアプリを作る

Reactのひな型作ってくれるコマンド使ってアプリ作ってみる。
フォルダ名は「helloworld」
とりあえずCドライブ直下に「Program」フォルダを作ってそこに作る

まずはフォルダに移動

```
$ cd C:\Program
$ Program> 
```

移動出来たら以下のコマンドを流す

```
$ Program> npx create-react-app helloworld
```

うまくいけばProgramフォルダの中にhelloworldフォルダができる

### 5. yarn startしてみる
アプリ作れたので、動かしてみよう

VS Codeでさっきのhelloworldフォルダを開く
VS Codeのターミナルを開いて、以下のコマンドを実行

```
$ yarn start
yarn : このシステムではスクリプトの実行が無効になっているため、ファイル C:\Users\xxx\AppData\Roaming\npm\yarn.ps1 を読み込むことができません。詳細については、「about_Execution 
_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ yarn start
+ ~~~~
    + CategoryInfo          : セキュリティ エラー: (: ) []、PSSecurityException
```

うまくいくはず、、だけどやっぱりエラーが出た…

### 6. yarn startできないエラーを解決する

いつも詰まっていたところにたどり着きました…
ですが今回はあきらめません

色々調べて今回参考にしたのはこちら

http://xn--u9j0md1592aqmt715c.net/get-executionpolicy/

原因は「セキュリティ上の理由で、スクリプトの実行が無効化されている」ためでした

ここからはWindows PowerShellの出番です
下の虫眼鏡でWindows PowerShellを検索し、右クリックして「管理者として実行」
まずは権限が何か確認します

```
PS > Get-ExecutionPolicy
Restricted
```

Restrictedは「全スクリプト実行不可」という意味だそうです
なのでここをRemoteSignedに変えます
意味は「インターネット経由でダウンロードしたスクリプトのみ証明書を要求」

```
PS > Set-ExecutionPolicy RemoteSigned

実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y)  [A] すべて続行(A)  [N] いいえ(N)  [L] すべて無視(L)  [S] 中断(S)  [?] ヘルプ (既定値は "N"):
```

ここは「y」を入力してEnterでok
最後に代わっているかを確認

```
PS > Get-ExecutionPolicy
RemoteSigned
```

無事変わりました！

### 7. もう一度yarn startしてみる

ここまでくれば大丈夫でしょう！
ドキドキしながらVS Codeでyarn startをしてみると、、、
実行できました！！！
やった！！

### 感想

今回環境構築からアプリの実行までがうまくできたのは、「Set-ExecutionPolicyコマンドを実行するのはコマンドプロンプトではなくWindows PowerShellだと気づけたこと」です！
実行するアプリの違いで詰まってたとはお恥ずかしい…
教訓としてきちんと覚えておこうと思います

### 【参考】

https://qiita.com/rspmharada7645/items/25c496aee87973bcc7a5

http://xn--u9j0md1592aqmt715c.net/get-executionpolicy/
Ubuntu 20.04 focal カスタマイズisoを作成するスクリプト

いくつか参考になりそうなweb記事があったのですが，自分の力量が足りず，なかなか成功しませんでした。今回，やっとうまくいった手順を書き記しておきます。

#目的
Ubuntu 20.04 focalベース
自分のMacBook用に，以下をカスタマイズ

- Broadcom WiFiドライバーを仕込む
- chrome等，好みのパッケージを含む
- できる限りかんたんに日本語対応させる

#確認した環境
MacBook Pro 15 Mid 2014 w/ Big Sur 11.6.1
VMware Fusion Player 12.2.1

#概要
以下を参考に，スクリプトを作成しました。

参考[1]
- https://github.com/mvallim/live-custom-ubuntu-from-scratch

参考[2]
- https://github.com/jkbys/ubuntu-ja-remix

debootstrap / chroot / apt を用いて，システムを構築します。mksquashfsで圧縮し，xorrisoでisoに変換します。

#作成手順

以下からスクリプトを入手します。

- https://github.com/numeru55/live-custom-ubuntu-focal-jp

以下を実行します。作業ディレクトリに `focal.iso` が出来上がります。

```bash
sudo ./build.sh
```

# 今後の課題？

- 出来上がるisoには，`/home/ubuntu` ディレクトリーがありません。起動したときに動的に作られるようです。いわゆる「オレオレファイル」を置く場所は，`/etc/skel` など，他に考える必要がありそうです。

- 出来上がった iso を起動すると，「のインストール」という言葉足らずなアイコンがデスクトップに現れます。ubiquityですね。イマイチですね... でも修正する方法がわかりません...

- 公開されている `ubuntu-ja-20.04.1-desktop-amd64.iso` をベースに改造を加えていく方法も良さそうですが... 今の私には逆にそちらのほうが難しかったです。参考[1]にならい，何もない状況から構築するようにしました。

- persistenceなlive環境ができるかは試せていません。

# 更新
- 2022/1/15 `chroot_build.sh` も修正しました。
- 2022/2/8 1本のスクリプトにして，Githubに置きました。
「Sign in with Apple」ボタンのサイズを変更する方法

# 結論

コードでAutoLayoutすればイケる。

```swift:ViewController.swift
// ボタンの生成
let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white)
// コードでAutoLayoutするためのおまじない（意味を知りたい方は調べてください）
authorizationButton.translatesAutoresizingMaskIntoConstraints = false
// Storyboardで作成済みのUIStackViewに追加
self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0)
// サイズ比率のAutoLayoutを記述（この場合は5:1の割合になる）
authorizationButton.widthAnchor.constraint(equalTo: authorizationButton.heightAnchor, multiplier: 5/1).isActive = true
```


# Sign in with Appleボタンとは

アプリ内でログインが必要な場合に、自前のサーバーでアカウントを管理せずにApple IDを利用してログインしてもらうことができる機能が「Sign in with Apple」。
そしてその機能を利用する際に、自身でログインボタンを作らなくてもAppleがログインボタンのクラス(`ASAuthorizationAppleIDButton`)を用意してくれているので、開発者はそれをViewに追加するだけで済むというボタンのこと。

iPhoneユーザーなら一度は見たことであろうあのボタンである。

![Screen Shot 2022-01-14 at 22.27.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636889/fe4b6e9a-0670-4113-260d-e1d4e618f882.png)
[Apple公式](https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/)より引用


# 自分で用意しなくていいのは楽だけど、、、

例えばFirebase Authなどで「Sign in with Google」も一緒に設置する場合、こちらも同じくGoogleが用意している`GIDSignInButton`を利用することができる。がしかし、
![Screen Shot 2022-01-14 at 22.36.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636889/a7a0918f-875b-d975-f2e1-d5c28510cdc3.png)
このように、GoogleとAppleがデフォルトにしているボタンの大きさが異なるのでどちらかを揃えなければならない。
気にしなければよいという意見があるかもしれないが、[Appleのドキュメント](https://developer.apple.com/design/human-interface-guidelines/sign-in-with-apple/overview/buttons/)に

> Make a Sign in with Apple button no smaller than other sign-in buttons
> （他のサインインボタンより小さくしないで！）

と明記されているので恐らくこのままではリリース審査で指摘されてしまう。



# bounds変えれば良いのでは？

```swift:ViewController.swift
// ボタンの生成
let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white)
// Storyboardで作成済みのUIStackViewに追加
self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0)
// boundsのサイズを変更
authorizationButton.bounds.size = CGSize(width: <CGFloat>, height: <CGFloat>)
```
こんな感じで、boundsのサイズを変えてみるも、`UIStackView`でAutoLayoutが使用されるため**コードでのサイズ変更は全く効かない。**
（UIStackViewを使用しているのは、Storyboard上で「ログインせずに使用する」ボタンを定義しているのでそれに簡単に揃えたかったからです）


# 答え: コードでもAutoLayoutを使う！

```swift:ViewController.swift
// ボタンの生成
let authorizationButton = ASAuthorizationAppleIDButton(type: .signIn, style: .white)
// コードでAutoLayoutするためのおまじない（意味を知りたい方は調べてください）
authorizationButton.translatesAutoresizingMaskIntoConstraints = false
// Storyboardで作成済みのUIStackViewに追加
self.signInBtnStackView.insertArrangedSubview(authorizationButton, at: 0)
// サイズ比率のAutoLayoutを記述（この場合は11:2の割合になる）
authorizationButton.widthAnchor.constraint(equalTo: authorizationButton.heightAnchor, multiplier: 11/2).isActive = true
```

このようにコードでボタンのサイズのAutoLayoutを設定することで、無事UIStackViewを使用したまま「Sign in with Apple」ボタンの大きさを変えることができました！
![Screen Shot 2022-01-14 at 22.55.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/636889/cc878f89-e078-4644-fbba-44caf79ac160.png)

Googleの方はデフォルトでドロップシャドウが設定されているので幅が少し小さくなっています。次はこれのサイズ調整も考えなければ...


# おしまい

不安定なことは多いですが、やはりビルドしなくても見た目がわかるStoryboardはいいですね。できる限りStoryboardで部品を配置したいものです。
初代RaspberryPi TypeBのmessagesに延々と出続ける「w1_master_driver w1_bus_master1」のエラーの消し方

## messagesのエラーに気づいたきっかけ
毎月横浜から札幌の自宅に土日だけ帰ってきてるのですが、今日になってドア開錠用ロボットアームを制御しているRaspberryPiちゃんがsshに反応しないことに気づきました。
壊れた指紋認証錠の暗証番号機能でどうにか家には入れたのですが、何かあった時にリモートで開錠できないと困るので、自宅PCからログインを試みるも反応なし。
pingにも反応しないので、これは壊れたかな？と思ってUSB電源抜き差ししてみたら復活しました。

2017年に構築したので、かれこれ5年も経っていて、そろそろ初代RaspberryPiちゃんも限界？かもしれませんが、ソフト的に何か問題起きてるだけかもと思って、/var/log/messagesを眺めてみると1分おきに延々と以下のエラーが出続けていました。

```messages
Jan  9 06:26:38 raspberrypi-type-b kernel: [33309752.664379] w1_master_driver w1_bus_master1: Family 0 for 00.03ee50000000.30 is not registered.
```

LANが無反応になったのとは、関係無いかもしれませんが、こういうのが延々出てるのは精神衛生上良くないので直したくなりますよね。
というわけで対策しました。

## 原因調査と対策
まずはGoogle先生にお伺い立てました。
すると以下のそれっぽいサイトが見つかりました。

■Raspberry pi zeroの/var/log/messagesにw1_master_driverのメッセージが連続して記録
https://iot-house.jpn.org/wp/2019/11/18/var-log-messages%E3%81%ABw1_master_driver%E3%81%AE%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E3%81%8C%E9%80%A3%E7%B6%9A%E3%81%97%E3%81%A6%E8%A8%98%E9%8C%B2/

理由はよくわかりませんが「/boot/config.txt」で設定している「dtoverlay=w1-gpio」をコメントアウトすれば直るようです。
でも「なんでなん？」って思ったので、上記サイトにあった参考サイトを見てみました。

■w1_master_driver w1_bus_master1: Family 0 for 00.200000000000.23 is not registered
https://forums.raspberrypi.com/viewtopic.php?t=196691

どうやら1Wireの温度センサーが繋ぐべきピンに刺さってないのに、システムはそれを検出しようとして見つからなくてショボーン(´・ω・｀)ってなってるようです。

でもそんなセンサー使ってないので、なんでそんなのが動いてるのかなと更にググってみました。

■Raspberry Piで1-Wireの温度センサーを利用する
https://qiita.com/STDNUL/items/f76a65f7eb4e27d44b5f

raspi-configで出てくるメニューで、温度センサーを有効にしたり無効にしたりできるんですが、それを有効にしたあとに、自分で「/boot/config.txt」に設定を追記しましょうって内容でした。

こんなメニュー初めて出したので、有効にした覚えは無いですが、さっきの英語サイトでもデフォルトで有効になってるのはおかしいと書かれてたので、デフォルトで有効になってたんだと思います。

で、試しにメニューで「Disabled」にしてみたら、あら不思議、さっきの設定行が自動でコメントアウトされました。

手で編集しなくて良かったじゃん。という訳でOS再起動したら、もう二度とあのエラーが出なくなって実に静かなmessagesになりました。

因みに私のRaspberryPiでは上記設定行は以下の記載になっていました。

```config.txt
# For more options and information see
# http://www.raspberrypi.org/documentation/configuration/config-txt.md
# Some settings may impact device functionality. See link above for details
中略
#dtoverlay=w1-gpio-pullup,gpiopin=4,extpullup=1
```
記載内容がちょっと多いですが、使ってないので気にしない事にします。

以上、messagesに変なエラーがずーっと出てたので調べて直したくなった病の記録でした。
同じ症状が出てる方がこれを見てスッキリして貰えたら幸いです。
CXL (Compute Express Link) その9 - Flit・Flex Bus

私はメモリデバイスの不揮発性メモリ制御やホストIFなどを扱うソフト屋をやっております。
仕事でCXL(Compute Express Link)まわりの技術に関わっています。
CXL技術に関連するメモ書きを残していこうと思います。
ホストのCPUとOS/Applicationまわりの経験・知識共に乏しいので、親切な方は教えて下さると幸いです。
また、間違い、アドバイス、その他、ご意見やご要望ありましたらお気軽にどうぞ。

#1. Control Flit

前回の"CXLその8"で触れたのですが、CXLには、メモリ空間のデータの読み書きのコマンドとレスポンスで使用されるProtocl Flitの他に、Control Flitがあります。
Control Flitは、ホストCPUとCXLデバイスにおける、CXL.cache/CXL.memのLink Layer間で発生するコマンド・レスポンスで使用されます。

Control Flitには以下の種類があります。

| Type Name | 概要 |
|:-:|:--|
| Retry  | 受信したFlitでCRCエラー検出時など、Flitの再送要求時に使用される。  |
| LLCRD  |  Flitを正常に受信できていること通知する。 |
| IDE    | CXLのセキュリティ機能の制御に使用される。  |
| INIT   | リンク層の初期化に使用される。  |

LLCRDの用途は、例えばホストCPUが短時間で多数のデータ書き込みコマンドを送り、CXLデバイス側がレスポンスを返すまでに時間が掛かってしまう場合等で使用されます。
前回の"CXLその8"で触れましたが、この場合、ホストCPUはAckが返ってくるまで、CXLデバイスからのRetry要求に備えて、コマンドとデータをバッファに保持しておく必要があります。、CXLデバイス側がレスポンスを返すまでに時間が掛かってしまう場合、ホストCPU側のバッファが溢れることを防ぐため、LLCRDでAckを通知します。

Control Flitでは、Slot0のみが使用され、Slot1からSlot3はReservedの扱いとなっています。

#2. Flex Bus Physical Layer

前回の"CXLその8"と今回でCXL.cache/CXL.memで扱われるFlitについて触れましたが、下図に示す通り物理層に当たるFlex Bus Physical Layerでは、PCIe/CXL.io経由で来るパケット(TLP/DLP)と、CXL.cache/CXL.mem経由で来るFlitが扱われます。
TLP/DLPについては、PCIeの仕様に従いますので、この記事では詳細には触れません。
![FlexBusLayers.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292852/b4ed2043-6371-d67e-be0b-e8484beb85b3.png)

Flex Busで流れるデータのレイアウトの例を下図に示します。
図の例は、ホストCPUとCXLデバイスを16 Laneで接続し、TLP/DLPとFlitが混在している状態のレイアウトの例です。
![flexbus_example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2292852/5efb29fa-d03e-a88c-b558-8d3baed7b80c.png)

Flex Busでは、CXL.io/PCIe経由で来るTLP/DLPは、64B単位で分割され、先頭にProtocol ID(2B)とReserved(2B)が付加されます。CXL.cache/CXL.mem経由で来るFlit(64B+CRC2B)には、先頭にProtocol ID(2B)が付加されます。
CXL.io/PCIeとCXL.cache/CXL.memとの区別はProtocol IDで行われます。

図中の緑色箇所はTLP/DLPを示し、桃色箇所はFlitを示しています。

----
次回は、CXL.ioでやり取りされるコマンドについて書こうと思っています。
【Ruby】任意の数字が配列の中の何番目に格納されているかを確認　searchメソッド

※初心者向け
※アウトプット練習の為

開発環境
rails 6.1.4.1
ruby 2.6.5

##概要##
任意の数字が配列の中の何番目に格納されているかを確認できるプログラムを実装。

##問題内容##
以下の配列から任意の数字を探して何番目に含まれているかという結果を返すsearchメソッドを、each_with_indexを用いて作成しましょう。

```csharp
input = [3, 5, 9 ,12, 15, 21, 29, 35, 42, 51, 62, 78, 81, 87, 92, 93]
```

**雛形**
以下の雛形のコードを参考に解答しましょう。

```ruby
def search(target_num, input)
  # 処理を記述
end

input = [3, 5, 9 ,12, 15, 21, 29, 35, 42, 51, 62, 78, 81, 87, 92, 93]
# 呼び出し例
search(11, input)
```
**出力例**
search(5, input) → 2番目にあります
search(12, input) → 4番目にあります
search(7, input) → その数は含まれていません

**ヒント**
 each_with_index
each_with_indexは、Rubyに標準で組み込まれているメソッドの1つです。要素の繰り返し処理と同時に、その要素が何番目に処理されたのかも表すことができます。
以下のように書きます。

```ruby
配列名.each_with_index  do |item, i|

end
```
具体的には以下のように使うことができます。

```ruby
fruits = ["メロン", "バナナ", "アップル"]

fruits.each_with_index do |item, i|
 puts "#{i}番目のフルーツは、#{item}です。"
end
```
これを実行すると、以下のような出力結果が得られます。

```
0番目のフルーツは、メロンです。
1番目のフルーツは、バナナです。
2番目のフルーツは、アップルです。
```

##解答##

```ruby
def search(target_num, input)

  input.each_with_index do |num, index|
    if num == target_num
      puts "#{index + 1}番目にあります"
      return
    end
  end
  puts "その数は含まれていません"
end

input = [3, 5, 9 ,12, 15, 21, 29, 35, 42, 51, 62, 78, 81, 87, 92, 93]
search(11, input)
```

##解説##
searchメソッドを呼び出す際の処理とsearchメソッド内の処理、それぞれを分けて解説していきます。

**searchメソッドを呼び出す際の処理**

配列inputを定義します。
次に、searchメソッドを呼び出す際に、11とinputという変数を実引数としてセットします。
そして、呼び出されたsearchメソッドでは、実引数でセットした値を仮引数target_numとinputとして受け取ります。

**searchメソッド内の処理**
まず、input.each_with_indexでは、inputに格納されている要素を1つひとつnumとして取り出すと同時に、要素毎に割り当てられている添字をindexとして取得します。

次に、if文で**num == target_num**という条件式を設定します。
ここでは、inputから取り出された要素numと、target_numが等しいかを判別しています。

そして、**numとtarget_numが等しければ、numがinputの中の何番目に含まれている**かが出力されます。
**#{index + 1}**としているのは、配列が0番目から始まることを考慮するためです。

**反対に、numとtarget_numが等くなければ、「その数は含まれていません」**と出力されます。

今回は、引数で渡した「11」は配列inputには含まれていないので、条件には当てはまりません。
よって、「その数は含まれていません」と出力されます。
再帰を使って木を描こう

#再帰とは

https://ja.wikipedia.org/wiki/%E5%86%8D%E5%B8%B0

https://www.google.com/search?q=%E5%86%8D%E5%B8%B0

#プログラムの内容
![Screenshot 2022-01-14 at 22-16-16 Scratch - 亀のお絵描き.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2468028/e907126c-e3bf-303e-2448-6b7e2ac2cbf2.png)

![Screenshot from 2022-01-14 22-15-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2468028/904bb593-c7ae-dc6b-fc21-26276ef67b42.png)

#実際の作品

https://scratch.mit.edu/projects/627775852/
Expressのテンプレートエンジンにejsを使う時、ejs内でexpressのlocalsを参照できる

## はじめに
Expressでテンプレートエンジンejsを使った実装をする時に、ejs内ではExpressのlocalsを参照できるという事を知ったので、具体的にどうなるのか？を少しまとめてみた。

## ejs内ではexpressのapp.localsやres.localsのlocalsを参照できる
[res.render(view [, locals] [, callback])](https://expressjs.com/en/4x/api.html#res.render)には、

> locals, an object whose properties define local variables for the view（ビューのローカル変数を定義するプロパティを持つオブジェクト）.

と書かれているので、あくまでres.render()の第二引数に渡す値のみがテンプレートエンジン内（ejs）で使えるのかと思っていたが、実際にはejs内では`locals`というオブジェクトに、res.render()の第二引数のオブジェクトと、expressのlocals（app.localsやres.localsのlocals）に定義済みのオブジェクトが全て組み込まれており、それらがすべて使える。

実際に、以下のようなソースを書いてみた時にの画面の描画内容からもこの事は確認できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/9671e5ee-3773-e2d2-534f-f2cbbbf4f36c.png)

```html
<body>
  ...
  <% for (let local of Object.keys(locals)) { %>
	<li><%= local %></li>
  <% } %>
  ...
</body>
```

↑ は、以下の実装において、`app.locals.pool`や`app.locals.fsSql`、`res.locals.moment`や`res.locals.padding`という設定をしていることにより、locals内に`pool`・`fsSql`・`moment`・`padding`などが存在している。また、その他の`id`、`name`などは、SQLの戻り値として返ってきたもので、res.render()の第二引数に渡しているので存在している。

※`padding`は関数であるが、これはexpressのres.localsには変数（値）だけでなく、オブジェクトや関数を渡す事もできるので、ejs内でlocals内に定義した関数を呼び出す事も可能。関数をejs内で呼び出す例としては、[ここ](https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/views/shops/index.ejs#L22)を参照。また、関数をres.localsに定義している部分は、[ここ](https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/app.js#L24)を参照（`locals`を明示的に書いているが、省略して`padding`とする事も可能）。

```js:client.js#L7
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/lib/database/client.js#L7
app.locals.pool = pool;
app.locals.fsSql = new SqlQueryLoader({
	path: 'src/lib/database/sqls'
});
```
```js:app.js#L22
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/app.js#L22
app.use((req, res, next) => {
	res.locals.moment = moment;
	res.locals.padding = padding;
	next();
});
```
```js:shops.js#L14
// https://github.com/yuta-katayama-23/post-restaurant-reviews/blob/657bfebd338886c532a32f80b65146543de75623/src/routes/shops.js#L14
try {
	const [rows] = await pool.query(
		fsSql.readSync('tran_shops', 'SELECT_SHOP_DETAIL_BY_ID'),
		[id]
	);
	res.render('./shops/index.ejs', rows.shift());
} catch (err) {
	next(err);
}
```

※ソースコードの全体は以下。

https://github.com/yuta-katayama-23/post-restaurant-reviews

※expressの`app.locals`については、[app.locals](https://expressjs.com/en/api.html#app.locals)を参照。

## 参考文献
- [Node.js - How can I use my local variable with EJS view](https://stackoverflow.com/questions/23943272/node-js-how-can-i-use-my-local-variable-with-ejs-view)
- [Using template engines with Express](https://expressjs.com/en/guide/using-template-engines.html)
Linux OSとは？歴史や学ぶ意義を初心者向けに解説

自分用のメモです。

# OSとは「Operation System」の略
→「アプリやハードウェアを動かすための基本となるソフトウェア」

# 基本用語の具体例

- パソコン用OSの例
→ Windows、macOS

- スマホ用OSの例
→ iOS、android

- ハードウェアの例
→ CPU、RAM、マウス、キーボード

- アプリケーションの例
→ Word、Excel、Zoom、Chrome、Safari

# ではLinuxとは？
→サーバ用のOS。サーバとは、ざっくり「サービスを提供する側のコンピュータ」のイメージ。

# UnixとLinuxの関係
→UnixはLinuxの祖先。Unixがライセンス契約へと移行した不満からLinuxが生まれた。

- まずLinuxの根幹部分を意味する「カーネル」が誕生。
- その後、さまざまな機能を追加した「ディストリビューション」が開発された。

# Linuxディストリビューションの種類【2種類ある】
→人気なのは「Cent OS」と「Ubuntu」

- 大まかなイメージ
Cent OS ＝　高性能だけど使うのが難しい
Ubuntu ＝　初心者でも使いやすい

# シェルとは？
→OSとユーザの仲介。機械語と人間語を翻訳。

※「シェル＝貝殻」の意味。Linux根幹部分の「カーネル」を覆っているイメージ。

# Linuxを学ぶ意義【3つある】
1. Linuxはサーバ用途で使われる
→ AWS・GCPはLinux系

2. LinuxはOSSだから
→ OSS = Open Source Software

3. エンジニアとしてのコマンド操作力向上
→ エンジニアを目指すならコマンド操作を避けて通れない

# 終わりに
自身の学習をまとめました。

参考になれば幸いです。
pandasのデータフレームを結合するときにグラフをプロットすることを前提だとどうすればいいか

#はじめに

pandasって便利ですよね
私は特にグラフの作成に使用しています。
様々なグラフを重ねて表示させるにはどうすればいいでしょうか。



#元のデータ

今回用意したデータがこちらです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/894d67cc-12dd-e967-75d1-4f1890e5474c.png)

そしてこれをグラフにしたものがこちらです。

```.py
aaa.plot(x="x",y = "ex10", xlim=[-2, 4], ylim=[0,0.01])
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/52e4c4c9-8783-a6a3-43cc-fff94217c0f8.png)




さらに、追加でこんなデータや、

```.py
bbb.plot.scatter(x="x",y = "ex1", xlim=[-2, 4], ylim=[0,0.01])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/d668d9b6-7c0a-fe52-8bd7-53088a4d73c9.png)

こんなデータを重ねて表示したいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/a5800102-cc83-57a8-8bc5-54da98fe996f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/8871a7c4-ab29-722c-e50d-f37e8eb58456.png)

最終的にはこんな感じで表示したいと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/5efd83ec-7bd5-c105-7ee9-c0e9c90e9543.png)


これらをどうやってpandasで行うのか調べました。



#方法1　mergeを使う（失敗）

pandasで異なるデータフレームを結合する際、mergeというものがあります。

https://note.nkmk.me/python-pandas-merge-join/

ざっくり説明すると、これは共通変数があるときの結合方法で、共通変数内に同じ数値があればその行に追加し、なかったら一番下の行に追加するという関数です。
試しにやってみた結果が以下の通りです。

```.py
ccc = pd.DataFrame([0], columns=["x"]) 
for i in range(1,n+1):
    label = "ex" + str(i)
    bbb = pd.DataFrame(ex_line[i], columns=["x", label])
    bbb.plot(x="x", xlim=[-L4, L1], ylim=[0,0.01])
    #交点においてmerge時に順番が飛び、うまく書けない
    ccc = pd.merge(ccc,bbb, on="x", how='outer')
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/c1fe40bf-c535-0671-c195-cc149d678b5f.png)

折れ線が途切れてしまいました。
この原因は、__同じ数値があればその行に追加する__ことが原因でした。
つまり、`on="x", how='outer'`と指定したことにより、x=0と-2が各列の共通の値なので、ここだけ順番が上になっているということでした。
この写真を見てもわかるように、各列において要素が存在する行が変数xが昇順になるように上から並んでいなければいけないのですが、x=0
だけ一番上まで連れてこられてしまっているため、順番がめちゃくちゃになってしまったのです。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/02b8e1c0-68d7-91db-d9fc-d52c7550af51.png)




#方法2　appendで下の行にそのままつなげる（成功）
下の行にデータをつなげているだけなので順番が変わらずグラフが描けます。


```.py
ccc = pd.DataFrame([0], columns=["x"]) 
for i in range(1,n+1):    
    label = "ex" + str(i)
    bbb = pd.DataFrame(ex_line[i], columns=["x", label])
    bbb.plot(x="x", xlim=[-L4, L1], ylim=[0,0.01])
    #下につなげるだけでうまくいく
    ccc = ccc.append(bbb)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/5efd83ec-7bd5-c105-7ee9-c0e9c90e9543.png)


データフレームの中身はこのようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/993303/d8e4cb6a-d3f6-6bdf-4575-ccb30f2a53a6.png)



#方法3　plotの変数axを使う

pandasのplotはmatplotlibに準じたものなのですが、なかなかpandasのplotについて書かれた記事が出てこない。
いろいろ探した結果、以下のサイトが最高でした。

https://own-search-and-study.xyz/2016/08/03/pandas%E3%81%AEplot%E3%81%AE%E5%85%A8%E5%BC%95%E6%95%B0%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%99/#ax


これによれば、plot内の変数`ax`を使用することでグラフを重ねることができます。
これが一番簡単そうですね



#まとめ
pandasで複数グラフを重ねる方法について考えました。
一つのデータフレームを使うなら方法2、グラフを重ねるなら方法3を使えば問題なさそうです。
Django REST Frameworkの初期設定

Django REST Frameworkをインストールする

```terminal
 $ pip install djangorestframework
```

プロジェクトの**settings.py**の`INSTALLED_APPS`に追加する。

```python:settings.py
 INSTALLED_APPS = [
     'django.contrib.admin',
     'django.contrib.auth',
     'django.contrib.contenttypes',
     'django.contrib.sessions',
     'django.contrib.messages',
     'django.contrib.staticfiles',
     'rest_framework', #　追加！！！
 ]
```

ひとまず、以上。
Base64のパディング "=" の長さが 2 を超えない理由

# はじめに
「Base64は、データを64種類の印字可能な英数字のみを用いて、それ以外の文字を扱うことの出来ない通信環境にてマルチバイト文字やバイナリデータを扱うためのエンコード方式」[^1]ですが，Base64でエンコードされた文字列の末尾は大抵1~2個の`=`でパディングされています。

ある日ふと「パディングが3個以上になることはないのかしら」と思って調べてみたんですが，自明すぎるのか，その辺を解説している日本語の記事があまりなさそうだったので一応書き留めておきます。

# 前提
Base64のエンコード方式は以下の通りです[^1]。

> 1. 元データを6ビットずつに分割する。（6ビットに満たない分は後ろに0を追加して6ビットにする）
1. 各6ビットの値を変換表を使って4文字ずつ変換する。
1. 4文字に足りない分は = 記号を後ろに追加する。

また，自明かもしれませんが，元データはバイト列（8bitを単位としたデータの集合）とします。

RFCを読んでも明記はされていなかったんですが，恐らく8bit単位でないデータについては考慮していないと思います。

# 考え方
（以下，「整数`x`を整数`y`で割った余りが`z`である」ことを`x ≡ z (mod y)`と表します）

まず，元データのビット長を`8n`とします（`n`は1以上の自然数）。
Base64エンコードにおいては，元データを6bitずつに分割し，それぞれに文字を割り当てて4文字のまとまりを作っていくので，6bit × 4 = 24bitを1ブロックとして考えます。

ここにおいてパディングが生じるケースというのは，元データを24bitずつ区切って最後に余りが出た場合を指します。
当然`8 * 3 ≡ 0 (mod 24)`なので，`n ≡ 0 (mod 3)`の場合はパディングが不要であることがわかります。

次に，`n ≡ 1 (mod 3)`の場合は，`m`を0以上の整数とすると`8n = 8(3m + 1) = 24m + 8`なので，`8n ≡ 8 (mod 24)`となります。
つまり，最後の1バイトは先頭6bitがそのまま1文字を割り当てられ，末尾2bitは`0`4つで6bitに拡張されてから1文字を割り当てられますが，4文字のまとまりを作るにはあと2文字足りないため，`==`でパディングされます（下図参照[^2]）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507842/377e373e-150a-62ab-aca9-3a25f167ccda.png)

最後に`n ≡ 2 (mod 3)`の場合は，`m`を0以上の整数とすると`8n = 8(3m + 2) = 24m + 16`なので，`8n ≡ 16 (mod 24)`となります。
つまり，最後の2バイトは先頭12bitに2文字が割り当てられ，末尾4bitは`0`2つで6bitに拡張されてから1文字を割り当てられますが，4文字のまとまりを作るにはあと1文字足りないため，`=`でパディングされます（下図参照[^2]）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/507842/85e4f734-bd75-2fb0-f64b-ec45ac75e48e.png)

以上で，全ての`n`についてパディングの長さが0~2個になることが示されました。

# まとめ
数学って難しいですね（文系並感）。

最後までご覧いただきありがとうございました。

# 参考
[RFC 4648 ベース６４とベース３２とベース１６符号化](http://www5d.biglobe.ne.jp/~stssk/rfc/rfc4648j.html)：RFC 4648の日本語対訳
[Base64 - Wikipedia](https://en.wikipedia.org/wiki/Base64)：英語版

[^1]: [Base64 - Wikipedia](https://ja.wikipedia.org/wiki/Base64)より引用
[^2]: [Base64 - Wikipedia](https://en.wikipedia.org/wiki/Base64)（英語版）より引用
MacのターミナルでBase64をデコードすると出力の末尾に"%"が挿入される

# 事象
```
% echo $SHELL
/bin/zsh
% echo -n M | base64
TQ==
% echo TQ== | base64 -d
M%
```

# 対応策①
ZshではなくBashで実行すると`%`が表示されなくなる。
（出力に改行が挿入されないので，見やすさのためデコードした後`echo`を入れています）

```
% bash

The default interactive shell is now zsh.
To update your account to use zsh, please run `chsh -s /bin/zsh`.
For more details, please visit https://support.apple.com/kb/HT208050.
bash-3.2$ echo TQ== | base64 -d && echo
M
bash-3.2$
```

# 対応策②
シェルを変えたくない場合は，コマンド置換を使ってもできる。
この場合は自動改行もされる。

```
% echo $SHELL
/bin/zsh
% echo $(echo TQ== | base64 -d)
M

# あるいは
% echo $(base64 -d <<< TQ==)
M
```
参考：[linux - Base64 decoding has "%" at the end of the result sometimes. Is it the result supposed to be? Any solution to that? - Stack Overflow](https://stackoverflow.com/questions/23176903/base64-decoding-has-at-the-end-of-the-result-sometimes-is-it-the-result-sup#comment35446600_23177128)
Flutterで”hello world”を実行

前回の記事で、Flutterの開発環境が完成したので、定番の”hello world”をやってみます。

https://qiita.com/fix/items/454e746e9a0e1bcf4da9

#プロジェクト作成

![イメージ7597.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/27fbd1e4-95f5-54c9-d99e-0074e372f950.jpeg)

[Flutter]をクリックして、[SDKのパス]を設定し、[次へ]

![イメージ7599.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/306e3957-923a-50d4-91d2-3746e2107177.jpeg)


とりあえず、プロジェクト名を[helloworldflutter]にして、あとはそのままで、[完了]
※小文字にしないとエラーになる？

![イメージ7600.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/a953e708-ba13-7289-c10b-88b043d7ce55.jpeg)

#コードを書換

プロジェクトが起動後

[helloworldflutter]
->[lib]
->[main.dart]

![イメージ7602.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ce14ead2-331a-5a35-ee7c-dde0d65569ff.jpeg)


このまま起動してもいいのですが、hello wordのコードを公開されてる方がいたのでそれを使わせてもらいました。



https://qiita.com/kouichi_c/items/c4c8254945c4b6c12df8


main.dartの中をコピーして貼り付け

![イメージ7604.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/96e2e6a3-eb92-4c1c-cff7-4f5d103371a2.jpeg)


#エミュレーターを作成

ADKマネージャー起動

![イメージ7606.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/328b93ea-d7bf-2e2c-0274-fff7e13357f4.jpeg)

[Create Virtual Device..]をクリック

![イメージ7607.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/6125b322-6649-e4b5-5a86-fbcf321e82ee.jpeg)

デフォルトのまま[次へ]

![イメージ7608.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/13d08762-3821-8887-a5a6-9e6c7a5c72ce.jpeg)

その他、そのまま[次へ]

完了後、緑のボタンをクリックして、エミュレーターを起動

![イメージ7612.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/67696e67-0c19-d04f-bfb3-9d0aed7857c6.jpeg)


![イメージ7613.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/687cf1b5-3692-9ea2-fef5-211b6c72a885.jpeg)


android studioの画面に戻って、実行ボタンをクリック

![イメージ7615.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/842af052-c132-4435-1dc7-0eef70b77eae.jpeg)

暫くしてエミュレーター画面に、[Hello world]が表示されれば成功。

![イメージ7616.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/f5d0ebcc-18f4-4322-9193-cd9ef46fece6.jpeg)
Vue.js + Server-Sent Eventsでリアルタイム通信

#概要
サーバーから能動的にデータを送信するHTTP通信方法であるServer-Sent Events(SSE)を利用して画面上の画像を都度差し替えて表示する仕組みを作ってみていたので覚書として。

#導入
下記のコードをvue.js内のmethodsに書き込めばおおよそ完了。
EventSourceにはリアルタイム取得したいサーバー側のURIを書き込み、Cookieも有効にしたい場合はコンマ区切りで{ withCredentials: true }を追加すればOK。

```
<script>
methods: {
  getImage () {
    let evtSource = new EventSource('/get_image', { withCredentials: true })
    evtSource.addEventListener('message', event => {
      this.imgSrc = event.data
    }, false)
  }
}
</script>
```
vueファイルの全体像としては下記のイメージ。

```display.vue
<template>
  <div>
    <img :src="imgSrc"/>
  </div>
</template>

<script>
export default {
  data () {
    return {
      imgSrc: null
    }
  },
  created: function () {
    this.getImage()
  },
  methods: {
    getImage () {
      let evtSource = new EventSource('/get_image', { withCredentials: true })
      evtSource.addEventListener('message', event => {
        this.imgSrc = event.data
      }, false)
    }
  }
}
</script>
```
初心者から始める！コードで書く Layout_marginについて


layout_margin とは　何か
簡単に言うと、View の　外側に領域(余白・スペース)を作るということです
早速xmlに記載するのと同じ様式で記載していきます

android:layout_margin              →Viewの周り全体に 領域を作ります
android:layout_marginTop           →Viewの上側に（以下略
android:layout_marginBottom        →Viewの下側に
android:layout_marginStart(Left)   →Viewの左側に
android:layout_marginEnd(Right)    →Viewの右側に

android:layout_marginVertical      →Viewの上下に
android:layout_marginHorizontal    →Viewの左右に

"marginStart"と"marginEnd" は　"marginLeft"と"marginRight" 
どちらで書いても問題ありませんが、"marginStart"と"marginEnd" が一般的です
また、統一されていた方がコードが読みやすくなります


android:layout_margin を　書いたViewの外側に余白・スペースを作りこみます

実際に　androidStudio を使って コードとlayoutを見てみましょう

メインとなるViewはmarginで作れた領域がわかりやすくなる様に色をつけたViewを用意しました
何も指定がない為、デフォルトで　左上　にViewが置かれています
![スクリーンショット 2022-01-14 20.43.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/050d3bd3-6754-cce4-9ec7-e337f27d9d83.png)


ここに　android:layout_margin を　試しに　100dp で　記入しました

![スクリーンショット 2022-01-14 20.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/dbfb78be-32d8-5f5a-9a13-90b04873678c.png)

android:layout_margin  は　Viewの周り全体に 領域を作るので上下左右に　100dpずつの余白ができました![スクリーンショット 2022-01-14 20.50.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2394054/843b8ebf-8a6a-ef5d-7d69-a625b2e0e81f.png)
【ユーザ定義関数(Split)】セルの値を指定文字列で区切って指定要素番号で取り出す【ExcelVBA】


だいぶ前に書いてたアドインでも事足りるのですが、社内で新関数の紹介した時に`TEXTJOIN`あるのに`TEXTSPLIT`無いんですかと言われたので思い出したようにサクッと作ってみました。

https://qiita.com/taleau/items/406971d67ad4c444a204

改めて見返して見ると`Application.ScreenUpdating = False`すら使ってない当時の自分から少しは成長を感じますね。

## コード

引数の`対象セル`に複数セルが選択された場合などの対策は一切してません。

要素番号超過などは`#N/A`が返ります。

``` vb
Function udf_Split(対象セル As Range, _
                 区切り文字 As String, _
 取り出したい要素番号_0始まり As Long) _
                            As String
  Dim Arr
  Arr = Split(対象セル.Value, 区切り文字)
  udf_Split = Arr(取り出したい要素番号_0始まり)
  
End Function
```
【初心者向け】OSI参照モデルとTCP/IPモデルの整理

# はじめに
OSI参照モデルとTCP/IPモデルに関する自分用のメモです。

ネットワークの学習をする際は***どのレイヤーの話なのか***、意識することが大切だそうです。

# OSI参照モデル
ネットワークを7つの階層に分ける考え方。

- レイヤー7：アプリケーション層
- レイヤー6：プレゼンテーション層
- レイヤー5：セッション層
- レイヤー4：トランスポート層　※ルーターのことを「L4スイッチ」と表現することもある。
- レイヤー3：ネットワーク層
- レイヤー2：データリンク層
- レイヤー1：物理層

→でも、7つはめんどくさい！ということでTCP/IPモデルが誕生。

# TCP/IPモデル
ネットワークを4つの階層に分ける考え方。

OSI参照モデルと対応させて記憶しましょう。

- レイヤー4：アプリケーション層 → OSI参照モデルのレイヤー5・6・7に対応
- レイヤー3：トランスポート層 → OSI参照モデルのレイヤー4に対応
- レイヤー2：インターネット層 → OSI参照モデルのレイヤー3に対応
- レイヤー1：ネットワークインターフェース層 → OSI参照モデルのレイヤー1・2に対応

# 終わりに
これがネットワークの基本中の基本だそうです。

馬鹿馬鹿しいと手間を惜しまずに、上記だけはしっかりと暗記しておくとよいですね。
開発会社設立してみた

## 開発会社設立しました

![139D12A9-D03C-4E03-B8C8-123086343654.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462614/15438c8a-6ff5-27e9-27f4-6519a9020bae.jpeg)

海外の開発会社と仲がいいといいことがあります。
実際に火星（ロシア、Evil Martians)から届いたクリスマスカードです。

普通にある子供向けウェブメディアで会社員として働きながらですが。

前から経営やりたいと思っていましたが、やはり会社員として働いている時は特に社長から経営が大変、経営者だったらこんなことも考える・・・と言われます。それを理解するためにはやはり経営者にならないといけないと覆ったので、会社設立することにしました。

ちなみに会社名は想像力皆無な人間なので[合同会社Sampo Development](https://sampo.ltd/)にしました。
短く合同会社Sampoにしたかったですが、すでに株式会社Sampoがあったので違う名前にしました。

https://www.houjin-bangou.nta.go.jp/

起業前はこちらのサイトで名前確認しましょう。

## 株式会社、合同会社、個人事業主・・・

こちらはやはり株式会社は設立費用、毎年必要な手続き・費用もあり、諦めました。株式会社は響きと信用度は一番ですが。個人事業主は税務上の制限などもあり、諦めましたので、必然的に合同会社になりました。Apple Japanも合同会社であれば、自分もそれでいいかと。

## 何をやる？

会社設立したって、やることも決めないといけないですね。
自分はRubyの開発であれば、リードプログラマーやった経験もあるので、開発案件を今ちょうど会社としてやっていますが、それ以外も海外とのコネも結構ありますので、海外の開発・ペンテストなどをやっている会社と日本の会社を繋げるコンサルもできればと思っています。

## Rails専門？

Rails専門でやるのなら名前にRubyつけてもよかったとも思いますが、ちょっとElixirも捨て難く、あえてRubyを社名に入れなかったです。会社のウェブサイトはちなみにPhoenixで作っています。

## 今後やりたいこと

いつかは自社サービスも持ちたいです。
起業しましたので、自社サービスもなんとなく会社としてやった信用度がありそうな気もしますので、それも企業の良いポイントかと思います。

あとは、人も雇って会社を多くしたいですね。

スタートアップの買収やっている一番などもありますので、小さなスタートアップを買って、それを育てるというのもいいと思います。

## 会社設立で大変なこと

会社設立はどこかに手伝ってもらえるのであれば簡単です。
ただし、銀行口座開くのは簡単ではないです・・・
審査があり、家まで確認も銀行員が来ますので、掃除もしないといけないです。
審査のためには事前に発注書などもらいましょう。
Windows10にFlutterをインストール

Flutterをインストールしてみたので、メモも兼ねて記事を書いてみました。


#Flutter SDKをダウンロード

今回は、stable （安定版）を入れてみます。

https://docs.flutter.dev/get-started/install

![イメージ7570.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/84f65bcd-623b-100e-ac0a-4f740b02efe7.jpeg)

解凍して[C:]のトップディレクトリに配置
![イメージ7571.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/d4b3afb3-729b-9601-dd32-1917fe9db074.jpeg)

[システムプロパティ]
->[詳細設定]
->[環境変数]

![イメージ7572.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/374cd544-f3ed-f631-a61a-2bd0f6192bdb.jpeg)

環境変数追加
![イメージ7574.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ec034305-6cca-b66a-6e71-ca158435b024.jpeg)

[Path]
->[編集]
->[新規]
->[C:\flutter\bin]


コマンドプロンプトで以下実行

$ c:
$ cd flutter\bin 
$  flutter doctor
![イメージ7576.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/bfd2a3f0-3e35-48be-8224-dda93c15ad58.jpeg)


![イメージ7579.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/e443e9aa-42ea-c4ec-e8f4-8cd6206764af.jpeg)

> cmdline-tools component is missing

参考サイト：

https://qiita.com/iseruuuuu/items/8bce7046bb260d515038


Android SDK Command-line Tools(latest)にチェックを入れるといいようです。

次は、android stidioの設定

#android stidioの設定

kotlinアプリ制作で、インストールは終わってるので省きます。

[プラグイン]
->[Flutter]
->[インストール]
![イメージ7585.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/7236d0b5-8fe8-bb6e-0b02-749d5c95d645.jpeg)

![イメージ7586.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/76debc11-a9f0-7595-e809-2a91a26032dd.jpeg)

再起動後、New Flutter Project が追加

![イメージ7587.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/89e8103f-7e60-980a-f2d4-c51741711049.jpeg)


SDKマネージャーで「Android SDK Command-line Tools(latest)」を追加

![イメージ7588.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/b09e09d0-788c-602d-2417-5067e9148683.jpeg)

![イメージ7589.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/3a1208f9-d231-04cc-a044-3ecfabc9460c.jpeg)


コマンドプロンプトで再確認

$ flutter doctor

![イメージ7590.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/cdd8fa7d-875e-327b-868a-54ee34b36fdf.jpeg)

SDKマネージャーで、Hide Obsolete Packagesのチェックを外す

![イメージ75911.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/1b044294-5ba5-c89b-8ab0-dfdaa024e0f3.jpeg)


$ flutter doctor --android-licenses

ライセンスに同意
![イメージ7592.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/29464458-b876-8694-f5f8-4897fa8af0c3.jpeg)



これで、インストール完了

![イメージ7593.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/503948/ed30fe1a-7d9b-f74d-62a0-fef4dc596975.jpeg)
Railsでコメント機能のajax化

##コメント機能のajax化
[前回のajax化の記事](https://qiita.com/mmaumtjgj/items/ef494de60a36f2e769b1)にてどんなものかある程度理解したので、この記事ではお気に入りボタンの実装を例としてしたが、今回はコメント機能の投稿と削除のajax化の備忘録として記載。

**手順**
①コントローラーの修正
②``remote: true``の追加や``class``、``id``の指定
③``js.erbファイル``の追加

##①コントローラーの修正
``redirect先``を削除

```修正前comments_controller.rb
class CommentsController < ApplicationController
  def create
    comment = current_user.comments.build(comment_params)
    if comment.save
      redirect_to board_path(comment.board), success: t('defaults.message.created', item: Comment.model_name.human)
    else
      redirect_to board_path(comment.board), danger: t('defaults.message.not_created', item: Comment.model_name.human)
    end
```

↓このように修正。

```修正後comments_controller.rb
class CommentsController < ApplicationController

  def create
    @comment = current_user.comments.build(comment_params)
    @comment.save
  end

```

##②``remote: true``の追加や``class``、``id``の指定
コメントフォームに``id:'new_comment'``、
テキストエリアに``id:"js-new-comment-body"``を追加。

また``form_with``から``local： true``を削除。``form_with``は元から``remote :ture``となっているのでわざわざ新たに記入する必要はない。

エラーメッセージはformではなく後に出てくる``js.erbファイル``に記載する。

```form.html.rb
<%= form_with model: comment,url: [board, comment],id:'new_comment' do |f|%>
 <div class="form-group">
   <%= f.label :body%>
   <%= f.text_area :body,class:"form-control mb-3",id:"js-new-comment-body",row:4,placeholder: "コメント"%>
 </div>
 <%= f.submit t('defaults.post'),class:"btn btn-primary"%>
<%end%>
```

削除ボタンに``class: 'js-delete-comment-button'``と``remote: true``を追加。

```delete_button.rb
<%= link_to comment_path(comment),
   class: 'js-delete-comment-button',
   method: :delete,
   data: { confirm: "コメントを削除します。よろしいですか？" },
   remote: true do %>
 <%= icon 'fa', 'trash' %>
<% end %>
```

##③``js.erbファイル``の追加
コメントviewファイル直下に``create.js.erb``と``destroy.js.erb``を作成。

```create.js.erb
# ↓既に表示されているエラーメッセージがあった場合は削除する
$("#error_messages").remove()

# ↓コメント作成処理の結果によって処理を分岐
<% if @comment.errors.present? %>

　　　　# ↓エラーがある、処理失敗時にはエラーメッセージのパーシャルを表示
  $("#new_comment").prepend("<%= j(render('shared/error_messages', object: @comment)) %>")

<% else %>
　　　　# エラーがない、処理成功時には作成されたコメント内容をHTML要素として追加する
  $("#js-table-comment").prepend("<%= j(render('comments/comment', comment: @comment)) %>")
　　　　　# ↓コメント入力フォームのテキストは表示する必要がないので、空文字に置き換えて内容をクリアにする
  $("#js-new-comment-body").val('')
<% end %>
```

```destroy.js.erb
$("tr#comment-<%= @comment.id %>").remove()
```
[Docker]/bin/sh: /go/bin/dlv: not found

## 記事を書いた経緯

タイトル通りGoAPIのdocker-compose上で`/bin/sh: /go/bin/dlv: not found`というエラーが発生してしまったので
その解決策をメモしておきたいと思います。

## 原因
mainブランチを更新した時にDockerfileに

```Dockerfile.dev
RUN go install github.com/go-delve/delve/cmd/dlv@latest
```
というのか追加されました。

しかし、いつも通り

```
$ docker-compose down
$ docker-compose up
```
をしましたが、
![スクリーンショット 2022-01-14 13.56.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/593744/69531747-aeb9-ca3f-a236-4488dde7633c.png)
Airが正常に動作しませんでした。

## 解決策

```
$ docker-compose build
$ docker-compose up
```

で解決しました。
Dockerfileが書きかわったら、一回ビルドしないと読み込まれないんですね笑
AWS Amplifyで静的サイトをホスティング(SSG)する


# 概要
React/Next.js(SSG)をAmplifyにデプロイする機会があったので手順をメモ。

# 背景
もともとCloudFront + S3の構成でReact/Next.jsを動かす予定でしたが、リロードすると404になってしまう問題に直面したのでAmplifyへ移行しました。（Amplifyも裏ではCloudFront + S3で動いているようですがリロード問題は発生しない ← 確認済み）

リロード問題の参考↓
https://qiita.com/ryokkkke/items/1478a022b220bf6e61ff
https://blog.ojisan.io/s3-next-deploy/

Lambda@edgeで対応する方法もあるようですが、Amplifyでホスティングする方が簡単そうです。

また、調べるとS3でリダイレクトをかけて対応しているケースもありましたが、こちらはなぜかうまくいきませんでした。

今回は、将来的にSSRやISRしたくなった時のことも考えAmplifyへ移行を決定。

# 手順
1. AmplifyのTopページで「Host your web app」のほうの「Get started」を選択
2. デプロイしたいサービスのプロバイダー（Github等）を指定
3. デプロイしたいサービスのリポジトリ&ブランチを指定
4. ビルド設定を確認・追記
5. デプロイ

# AmplifyのTopページで「Host your web app」のほうの「Get started」を選択

![amplify1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411612/53198c99-c081-dc1f-ea95-f045fac97ff6.png)

「Host your web app」のほうの「Get started」を選択。右側ですね。

# デプロイしたいサービスのプロバイダー（Github等）を指定

![amplify2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411612/1e76e42d-b3d2-7cc2-4228-dca4fe5c6856.png)

Amplifyにデプロイしたいプロバイダーを選択。

# デプロイしたいサービスのリポジトリ&ブランチを指定

![amplify3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411612/ac99781b-98b4-53c6-0db7-3be3b0331728.png)

プロバイダーを選択し、認証したらデプロイ対象のリポジトリとブランチを選択。

# ビルド設定を確認・追記

![スクリーンショット 2021-11-07 21.00.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411612/6893115b-7709-31f1-8e4f-67c7c687c3f5.png)

任意のアプリ名をつけて、ビルド設定を記載します。
ビルド設定は、コードがpushされたときに自動で走るコマンドの指定になります。
デフォルトでビルド設定を用意してくれますが、1点修正しました。

```
version: 1
frontend:
  phases:
    preBuild:
      commands:
        - npm ci
    build:
      commands:
        - npm run build 
        // ↑ 修正
  artifacts:
    baseDirectory: dist
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
```

また、このページで環境変数の設定等ができたりします。

# デプロイ

最後に確認画面が表示され、問題なければ「保存してデプロイ」を選択。
フレームワークの部分にnextが表示されているので、ちゃんと認識してくれていますね。

初回のデプロイ以降も指定したブランチにPush or Mergeされれば自動でAmplifyにデプロイされます。


# ドメイン設定 
サイドバーの「ドメイン管理」を選択。「カスタムドメインの追加」からRoute53に設定しているドメイン追加できます。

# ベーシック認証
サイドバーの「アクセスコントロール」を選択。「アクセスの管理」からIDとPasswordを設定することができます。

設定できていれば↓のような感じになります。

![basic.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/411612/080d8d33-199d-45b0-77be-5946711d282b.png)

# 環境変数
ステージングと本番環境の環境変数もAmplify管理画面から簡単に設定できました。
ブランチごとに環境変数を設定後、ビルドの設定からamplify.ymlに下記等で渡します。

```
build:
 commands:
　# amplifyの環境変数設定画面でORIGINを設定。
  - echo "ORIGIN=$ORIGIN" >> .env
```

あとは、

```
process.env.ORIGIN
```
上記等で使いまわせます。

# 参考サイト
https://dev.classmethod.jp/articles/amplify-add-hosting-with-angular-app/
https://qiita.com/duplicate1984/items/6f506c724ee519ce4e4c
https://zenn.dev/leaner_tech/articles/20210630-replace-spa-with-amplify#%E8%A4%87%E6%95%B0%E3%83%96%E3%83%A9%E3%83%B3%E3%83%81%E3%81%AE%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%81%A8%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0
DataFrameのリスト要素をNaNが含まれていても結合する方法


DataFrameのリスト要素を結合するとき、要素の値として`NaN`が含まれていると、結果は`NaN`になります。

```python:期待通りに動かないコード
import pandas as pd
import numpy as np

df_test = pd.DataFrame({
    "data1" :[["1","2","3"],["1","2","3"]],
    "data2" :[["4","5","6"],["4","5","6"]],
    "data3" :[["7","8","9"],np.nan]
    })
result = df_test["data1"]+ df_test["data2"]+ df_test["data3"]
print(result)

# 結果
# 0    [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 1                            NaN　← [1, 2, 3, 4, 5, 6] としたい
```

単純に`fillna()`を使って`NaN`を空リストに変換しようとすると、リストには変換できないと怒られてしまいます。

```python:単純にfillna()を使ってもエラー
result = df_test["data1"]+ df_test["data2"]+ df_test["data3"].fillna([])
# TypeError: "value" parameter must be a scalar or dict, but you passed a "list"
```


# 解決方法
下記のステップで実装します。

1. `NaN`を空文字に置換する
1. すべての要素をリストに変換する。空文字が空リストに変換される。
1. 列方向にリストを結合する

```python
import pandas as pd
import numpy as np

df_test = pd.DataFrame({
    "data1" :[["1","2","3"],["1","2","3"]],
    "data2" :[["4","5","6"],["4","5","6"]],
    "data3" :[["7","8","9"],np.nan]
    })
result = df_test.fillna("").applymap(list).sum(axis=1) # 変更点
print(result)
# 結果
# 0    [1, 2, 3, 4, 5, 6, 7, 8, 9]
# 1             [1, 2, 3, 4, 5, 6]
```

# 参考

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.fillna.html

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.applymap.html

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.sum.html