OmniAICreator/Qiita-1.07M huggingface dataset:
Dockerを使ってUbuntuに自然言語処理環境を構築しよう


# この記事の内容

本記事ではdockerを使ってゼロからUbuntu環境を構築し、Pythonのインストール方法から自然言語処理を適用するまでの基本的な環境構築方法を説明していきます。

1. dockerを使ってubuntu環境の構築
2. 構築した環境にpythonのインストール
3. 言語処理環境の構築

なお、前提としてdockerがインストールされていることとします。

## 1. docker を使ってubuntu環境の構築

まずはdockerでubuntu環境を構築します。

```
docker run --name ml -v /Users/ユーザー名/Documents:/root -it -p 8888:8888 ubuntu bash 
```

--nameでmlという名前をつけています。
-vでボリュームのマウントをします。：の前がローカルのパスで、後がDocker内部のパスになります。
-pでポートを設定します。後にJupyterを使う場合はデフォルトのポートが8888なので8888にしておくことをお勧めします。別のポート番号を設定しても可能ですが、後々少しめんどくさいことになります。


## 2. 構築した環境にpythonのインストール

次にDocker内で次の処理をします。

```
$ apt update
$ apt -y upgrade
$ apt install -y python3-pip
```

## 3. 言語処理環境の構築

ここからが本番です。自然言語処理環境を構築していきます。

### MeCabのインストール
まずは環境構築に必要なものをインストールします。

```
$ apt install curl sudo git vim
```
次に、MeCab及びPythonでMeCabを使うためのパッケージをインストールします。

```
$ apt install mecab mecab-ipadic mecab-ipadic-utf8 libmecab-dev
$ pip install mecab-python3
```

libmecab-devはNeologdのインストールに必要になります．
ちなみに`python -m pip install --upgrade pip` でpipのアップグレードができます。

### Neologdのインストール

```
$ git clone https://github.com/neologd/mecab-ipadic-neologd.git
$ cd mecab-ipadic-neologd
$ sudo bin/install-mecab-ipadic-neologd
```

インストールが完了したら確認してみましょう。

```
mecab -d /usr/lib/aarch64-linux-gnu/mecab/dic/mecab-ipadic-neologd
```

毎回パスを指定するのは面倒ですので、パスの設定をしておきます。

```
$ sudo vim /etc/mecabrc
```

```
;
; Configuration file of MeCab
;
; $Id: mecabrc.in,v 1.3 2006/05/29 15:36:08 taku-ku Exp $;
;
; dicdir = /var/lib/mecab/dic/debian

dicdir = /usr/lib/aarch64-linux-gnu/mecab/dic/mecab-ipadic-neologd

; userdic = /home/foo/bar/user.dic

; output-format-type = wakati
; input-buffer-size = 8192

; node-format = %m\n
; bos-format = %S\n
; eos-format = EOS\n
```

### Pythonパスの設定
必要なものは全てインストールすることができましたが、PythonでMeCabを実行すると
`[ifs] no such file or directory: /usr/local/etc/mecabrc`
というエラーが発生します。
これはpythonのパスの設定がうまくいっていないことが原因ですので、パスを通してあげる必要があります。
まずはMeCabのインストール先を確認します。

```
$ sudo find / -iname mecabrc
```
多くの方が以下の結果になると思います。

```
/etc/mecabarc
```

次に確認したインストール先をbash_profileに書き込みます。

```
$  sudo vim  ~/.bash_profile
```
以下の内容を追記します。

```
export MECABRC='/etc/mecabrc'
```

書き込んだ設定を反映します。

```
$ source ~/.bash_profile
```

以上で、自然言語処理環境は構築完了です。

`python3` でpythonを起動し、以下のプログラムを実行してみましょう。
```
import MeCab
 
mecab = MeCab.Tagger("")
text = "今日はとてもいい日でした。明日もいい日になるといいなぁ。"
print(mecab.parse(text))
```

![スクリーンショット 2022-04-05 22.31.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/471541/de6062ed-8717-a8b4-91c5-63268374d562.png)

それではハッピーな自然言語処理を！
Javascript ウインドウアラートを表示する

## 初めに
window アラートを画面に表示させる
## 教科書
https://www.sbcr.jp/product/4815601577/
## 実践
```js:画面を開いた瞬間にダイアログアラートが出てくる
<script>
    'use strict';
    window.alert("アプリ連携が完了しました。");
</script>
```
Railsでテーブルの削除

mastersテーブルを削除してみる。
テーブルを削除するためのマイグレーションファイルを作成する。

**マイグレーションファイル作成**
```
$ rails g migration masters
```

**マイグレーションファイル編集**

```
class Masters < ActiveRecord::Migration[6.0]
  def change
    drop_table :masters
  end
end
```

```
$ rails db:migrate
```
でテーブルの削除ができます。

参考：https://qiita.com/kanuu/items/a9223712ee0ff8d19d56
https://k-koh.hatenablog.com/entry/2020/08/18/103826


開発環境
mac OS バージョン11.6
エディタ
VScode
普段使っているVScodeの拡張機能まとめ

普段VScodeを使う際に利用している便利な拡張機能を備忘録としてまとめておきます。

### Pylance
Pythonの型チェックや入力補完、importの不足の指摘など、Pythonプログラミングをサポートしてくれる

### Black
Pythonコードのフォーマッター
とりあえず入れておけばコードのフォーマットを気にしなくていいので楽

### Japanese Language Pack for Visual Studio Code
VScodeを日本語化してくれる

### indent-rainbow
インデントを色分けしてくれる
インデントの段階が一目でわかって便利

### Bracket Pair Colorizer
対応する括弧を同じ色で示してくれる
括弧の対応関係が一目でわかって便利

### Paste Image
Markdownに画像を添付するのに便利
クリップボードから保存場所、ファイル名を指定して保存、貼り付けがVScode上で完結するのでとても便利
スクリーンショットを張り付ける際にもとても楽
GPSを使ったNTPサーバの構築 その2 (GPSモジュールの資料)

# GPSモジュールの資料
GPSモジュールを設定するためのコマンドはデータシートに書かれているが、製品に添付されていなかったのでネットで探す必要があった。幸いなことに全部見つかったものの、事前調査で一番時間が掛かった。
資料の直リンはどうかと思ったのでググり方を記載しておく。

## VFAN UG-353
「u-blox 7 Receiver Description Including Protocol Specification V14」でググるとu-bloxのサイトで見つかる。ロットによってプロトコルバージョン違いがあるかもしれないので、その場合は該当するバージョンのデータシートを探すこと。
バージョンの確認はgpsdに添付のubxtoolを使用する。表示された情報のうち extension PROTVER=xx.xx がプロトコルバージョンを表す。
~~~ shell:バージョン確認
$ ubxtool -f /dev/gps0 -s 9600 -p MON-VER
  -sは現在の転送速度
~~~

ちなみにu-blox製品はWindows版のu-centerをダウンロードして設定した方が楽。

## GLOBALSAT BU-353S4
よく使う転送速度変更やセンテンスのOn/Offコマンドは、「GLOBALSAT BU-353S4 コマンド」でググって見つかる東京通称システムさんの商品ページに参考として載っている。
より詳細な情報が欲しい場合は「EB-5365RE User manual site:globalsat.com.tw」でググると見つかる。こっちにはDatumを変更するコマンドも載っているので測地系をTokyo-Japanにすることもできる(位置情報は不要だから今回は使わないが)。
ちなみにEB-5365REはBU-353S4で使用しているChipset(データシートにはGPS Engine Boardと書いてあった)。

## LOCOSYS LS23030-V2
「Datasheet of GPS mouse, LS2303x-Vx series "1.0"」でググるとLOCOSYSのサイトで見つかる。
もっと新しい1.1もあったのだが、LS23030が外れてLS23032以降になっていたので1.0を。

# 設定方法
BU-353S4とLS23030-V2はコマンドがテキストなので、sttyでシリアルデバイスの転送速度を適切に設定した後、printfなどでコマンドを流し込めば良い。
~~~shell:例.BU-353S4のGLL出力をOffにする
$ printf '$PSRF103,1,0,0,1*25\r\n' > /dev/gps1
~~~

これに対しu-bloxのChipset使ってるUG-353はバイナリで、コマンドの構造も前者に比べて複雑。ubxtoolを使えば自分で全部バイナリ列を組み立てなくとも済むが、それでもデータシート見て理解できないとコマンドを組み立てられない。また結果出力もデータシートに書かれてる情報見ながらで無いと理解できない。
転送速度設定やNMEAモードへの切り替え、主要機能のOn/Offくらいはubxtoolの基本オプションとして実装されてるので手軽に行えるが、センテンス出力のOn/Offはデータシート見ながらパラメータを作る必要がある。
~~~sh:例.転送速度を38400bpsに変更
$ ubxtool -P 14 -f /dev/gps0 -s 9600 -S 38400
  -Pはプロトコルバージョン、-Sが設定する転送速度
~~~
~~~sh:例.出力をNMEAモードに変更
$ ubxtool -P 14 -f /dev/gps0 -s 38400 -e NMEA
~~~

上にも書いたがu-center使って設定した方が楽。
colimaをuninstallしても、`Cannot connect to the Docker daemon at unix:///Users/mynameisok/.colima/docker.sock. Is the docker daemon running?`出る場合

colimaを試したあと、もともと動いていたDocker for Macを利用とすると、うまくできなかった。colima削除しても.

`docker-compose up -d`コマンド打つと、下記エラーがでるんで、どっかとの設定で変なところ見るようにになっているんだね
```
Cannot connect to the Docker daemon at unix:///Users/mynameisok/.colima/docker.sock. Is the docker daemon running?
```
### 結論、下記で curent contextを入れ直せばうまくいった：
```shell
$ docker context list
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                               KUBERNETES ENDPOINT   ORCHESTRATOR
colima *            moby                colima                                    unix:///Users/mynameisok/.colima/docker.sock
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                         swarm
desktop-linux       moby                                                          unix:///Users/mynameisok/.docker/run/docker.sock
$ docker context use default
default
$ docker context list
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT                               KUBERNETES ENDPOINT   ORCHESTRATOR
colima              moby                colima                                    unix:///Users/mynameisok/.colima/docker.sock
default *           moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock                                         swarm
desktop-linux       moby                                                          unix:///Users/mynameisok/.docker/run/docker.sock
```

### 参考にしたとこ
[colimaのgithub readme](https://github.com/abiosoft/colima)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536036/4b25d841-6384-d2f2-beca-5c1e15a2f929.png)
参加日記: AtCoder ABC 246 AからE(Python EのみC++)

https://atcoder.jp/contests/abc246/tasks

# A - Four Points 

条件の四角形の性質を考えるとある数$a,b,c,d$があったときに、4つの点は(a,c), (a,d), (b,c), (b,d)を取ります。
このうちの１つが消えると考えたときを考えると、x, y共に1度しか現れない数を取る座標の点を求めればいいことが分かります。
時間・空間計算量はO(1)です。

## 実装
解説の通り、偶数回出現する数の中で奇数回の数を見つけるのでx, y独立にxorを取ることでも求められますが、私はdefault_dictで解きました。

https://atcoder.jp/contests/abc246/submissions/30740324

# B - Get Closer

(0,0)から(A,B)の長さをlとして$l=\sqrt{a^2 + b^2}$であることは自明です。同じ傾き上にある長さ1の点を求めたいので、A,Bに$\frac{1}{l}$をかけてやればよいです。(以下の図)

<img src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30938/41433bc3-2719-bc5c-736d-daa1cef6db8a.png width=50%>


<details><summary>実装(Python)</summary><div>

```Python
import math
a, b = map(int, input().split())
l = math.sqrt(a**2 + b ** 2)
print(a/l, b/l)
```
</div></details>

https://atcoder.jp/contests/abc246/submissions/30740478

# C - Coupon 
各価格を$a = bX + r$で表してみます。入力例の8, 3, 10, 5, 13円の例ではX=7なので、
- 7 + 1 円
- 3円
- 7 + 3円
- 5円
- 7 + 6円
があります。K枚のクーポンを使えるということはこの中の任意のK個までの数字を消せます。
- もし、7(=X)の数がK個以上なら、消せるだけ消します。どれが残るように消しても結果は一緒です。
- もし、7の数がK枚よりも小さい場合、全部の7を消し、そのあとに大きな数字から消します。
このようにすることで、残った数字の和=支払金額を最小化できます

<details><summary>実装(Python)</summary><div>

```Python
n, k,x  = map(int, input().split())
dat = list(map(int, input().split()))
dat.sort(reverse=True)
for i in range(n):
    if dat[i] < x: continue
    canuse = min(k, dat[i] // x)
    k -= canuse
    dat[i] = max(dat[i] - canuse * x, 0)
dat.sort(reverse=True)
for i in range(n):
    if k <= 0: continue
    k -= 1
    dat[i] = 0
print(sum(dat))
```
</div></details>

https://atcoder.jp/contests/abc246/submissions/30740691

# D - 2-variable Function
条件を満たす式を全探索してきます。

まず、条件より、$0 \leq a \leq 10^6$は明らかです。(実際は、$+a^2$もあるのでより小さいです)
与えられた条件を満たすb(Xが最小となるb)を二分探索で求めます。

尚、解説の通り、aが大きくなるにつれ、bは小さくなることは自明なので、a,bを左右から挟み込んでいくことで計算量を大きく減らせます。

<details><summary>実装(Python)</summary><div>

```Python
n = int(input())
ma = 10 ** 6 + 10
ans = 1 << 61
for a in range(ma):
    ng = -1
    ok = 10**6+10
    f = lambda b: a ** 3 + b ** 3 + a ** 2 * b + a * b ** 2
    while (abs(ok - ng) > 1):
        mid = (ok + ng) // 2
        if (f(mid) >= n): ok = mid;
        else: ng = mid;
    ans = min(ans, f(ok))
print(ans)

```
</div></details>

https://atcoder.jp/contests/abc246/submissions/30740745

# E - Bishop 2 (C++)
拡張グラフのダイクストラで解けます。以下の記事のように(今回は斜めに)辺を張ります。高速な言語でないとTLEします。

尚、解決の通り、0-1BFSで解けるようにしておいた方が計算量の面でも、バリエーションの面でもよいと思います。

https://qiita.com/recuraki/items/c2dd293a80ddc7d53be4

https://atcoder.jp/contests/abc246/submissions/30663422
Visual Studio Codeでローカル編集履歴がたどれるようになったぞ！

Qiita初心者です。ご質問・ご指摘はコメントかツイッターまでお気軽にどうぞ！
よかったら**LGTM**や**拡散**していただけると励みになります。
# Visual Studio Code version 1.66がリリース
2022年3月31日にVisual Studio Code(以下 VS Code)の1.66がリリースされました。
このリリースノートを見た瞬間VS Codeの時代が来たッ！！（言い過ぎ）と言いたくなるくらい興奮しましたので早速リポートさせてもらいます。

そして僕が注目した機能が「Local History（ローカル履歴）」です。

# Local History（ローカル履歴）って何？
ファイルの変更の操作が行われたタイミングでローカル上に自動で差分が保存され、現時点のファイルの中身と変更した時のファイルを手軽に比較したり内容を戻したりできる機能です。

## どこで確認ができる
EXPLORER（エクスプローラー）パネルのTIMELINE(タイムライン)で確認ができます。


![ローカルヒストリー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600119/8f033539-e5d2-f7ff-038f-9f40aba0ec96.png)

## 差分がとれる
このような感じで消した履歴や増やした履歴の確認をタイムラインをクリックするだけで
Gitにコミットする必要もなくすぐに確認できます！
![差分.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2600119/739163ee-2862-6944-269a-5f59aa9ba1b8.png)

これで「あの時の１行を返してくれ！！」みたいな悩みが１つ解決されました！！

## 誤って削除したファイルの取り戻しもできる
VS Codeのタイムラインパネルには表示されませんが、同じプロジェクト内の任意のバージョンの任意のファイルを見つけて、右クリックして選択したバージョンのファイルを開くと、VSCodeが履歴バージョンを保持しているフォルダーを見つけることができます。

## 詳しい設定の変更
VS Code上でローカル編集履歴についていろいろ設定ができます。

### ローカル編集履歴を有効/無効化
`workbench.localHistory.enabled`
### ローカル履歴エントリを作成するときのファイルサイズの制限
`workbench.localHistory.maxFileSize`
### ファイルごとのローカル履歴エントリの制限
`workbench.localHistory.maxFileEntries`
### ローカル履歴から特定のファイルを除外するためのグロブパターン
`workbench.localHistory.exclude`
### ローカルファイル履歴の最後のエントリにさらに変更が追加される秒単位の間隔
`workbench.localHistory.mergeWindow`

# Version 1.67の記事も書いたよ！
[Version 1.67](https://qiita.com/kihaya-tech/items/1369bd7501a2729032b3)の記事も書きました。よければこちらも！
また、このような有益な情報を[Twitter](https://twitter.com/kihaya_tech)でもシェアしてますのでよければフォローお願いします。
【ネタ】オライリーのページ数を調べる（2022年版）


## ページ数が多い本

### 第１位「Linuxプログラミングインタフェース」

![-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/20612ebc-718a-0451-8d8d-ea8087c97ebe.jpeg)

* 1,604ページ
* 2012年11月発行
* 8,360円（税込）

### 第２位「詳解 Linuxカーネル 第3版」

![-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/64284bfb-e3d3-4dc3-ade3-df528fba8a98.jpeg)

* 1,024ページ
* 2007年2月発行
* 7,260円（税込）

### 第３位「詳解 OpenCV 3」

![-3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/b933843c-9675-6027-f509-1220b6f4cb2e.jpeg)

* 992ページ
* 2018年5月発行
* 7,480円（税込）

## ページ数が少ない本

### 第１位 「ハイパフォーマンスWebサイト」

![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/8f41db2d-4ae9-5b26-b66d-60baa8072310.jpeg)

* 184ページ
* 2008年4月発行
* 1,980円（税込）

### 第２位 「開眼！ JavaScript」

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/2e232d81-c0c9-c3de-4094-b919c72cf54f.jpeg)

* 196ページ
* 2013年6月発行
* 2,420円（税込）

### 第３位 「JavaScript: The Good Parts」

![3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/2b9c51f0-23af-4750-5ff0-2ef993039133.jpeg)

* 198ページ
* 2008年12月発行
* 1,980円（税込）

### 第４位「詳解 WordPress」

![4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/baab1d37-f43e-e210-fa62-9ed86bb81426.jpeg)

* 204ページ
* 2015年4月発行
* 2,860円（税込）

### 第５位「プロダクションレディマイクロサービス」

![5.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2115724/ef27d96c-7cfb-591f-7a78-256ca723afcd.jpeg)

* 216ページ
* 2017年9月発行
* 2,860円（税込）
良いコードとは

# 今回のアウトプットの目的
良いコードとはどのようなものか？
良いコードを書くにはどうすればよいか？
WEBアプリケーション開発をする上でとても重要だと感じたので、
改めて整理したいと思います。

# 良いコードとは
**結論：他人が見てわかりやすく意味のわかるコードが一番良いコードだと思います**

具体的にどのようなことを意識すれば良いコードになるのか纏めてみたいと思います。
①わかりやすいコメントを書く、and 無駄なコメントはしない。
②変数名やメソッド名は誰が見てもわかりやすい名前にする。
③インデントをつけてしっかりと揃える。
④ネストしすぎない。
⑤直接数字を記述するのではなく変数を利用する。

**またDRYの原則も重要だと思います**
DRY(Don’t Repeat Yourself）とは？
=「同じ情報を繰り返し定義しない」という考え方
ダメな例
```not_dry.rb
a = 100 * 1.1
b = 200 * 1.1
c = 300 * 1.1
```
良い例
```dry.rb
tax = 1.1
a = 100 * tax
b = 200 * tax
c = 300 * tax
```

**メリットとして、可読性の向上や、コード量を減らすことによりアプリケーションの動作が早くなリます！**

私が調べた範囲で意識した方がいい点を纏めてみました。

もし修正点や追加点等ございましたらご教授いただけますと幸いです！！！

以上
CodeBuildで利用するproxy設定をパラメータストア化する

CodeBuild(CodePipeline)をVPCで実行するシーンでは、以下のようにプロキシ指定を駆使する必要があるケースがあると思います。
- 外部通信にプロキシ(HTTP_PROXY,HTTPS_PROXY)を利用する
- AWSサービスへの通信のうち、VPCエンドポイントが提供されている場合は、VPCエンドポイント経由(NO_PROXY)とする
- プロキシ設定は、パラメータストアに入れて集約したい

![codebuild_proxy.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219565/116b2236-ad5c-71a7-e656-c2b8b2663c38.jpeg)

パラメータストアに、``http_proxy``,``https_proxy``,``no_proxy``を登録して、CodeBuildの環境変数でパラメータストア参照にすれば良いかなと試しましたがうまく行きません。
これを実現する方法を記載します。

## 前提
* CodePipelineから、Github -> CodeBuildの形で、CodePipelineからCodeBuildは実行する流れ
* CodeBuildはbuildspec内で、proxyやvpcエンドポイントへの通信が必要となる
* パラメータストアに、``http_proxy``、``https_proxy``、``no_proxy``を定義している

![parameterstore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219565/ed2103c0-3eb3-4b1b-7893-d6550b8a11c6.png)



## 結論
* CodeBuildの環境変数 ``no_proxy``は、``.s3.ap-northeast-1.amazonaws.com,ssm.ap-northeast-1.amazonaws.com``を``PLAINTEXT``で登録
* CodeBuildの環境変数 ``http_proxy``、``https_proxy``は、パラメータストア参照で登録
* buildspecの中で、``no_proxy``をパラメータストアから読み出し、環境変数に設定する


![codebuild-parameter-ok2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219565/5e1365ce-ea30-f4e6-ba59-4003d5b5ec88.png)

```buildspec.yml
version: 0.2
env:
  parameter-store:
    ps_no_proxy: no_proxy # パラメータストアからno_proxyの値を読み出す
phases:
  install:
    commands:
      - unset no_proxy # この時点のno_proxyは、s3とssmがセットされているのでno_proxyをリセット
      - export no_proxy="$ps_no_proxy" # パラメータストアから読み出したno_proxyの値で設定
      - echo $http_proxy # CodeBuildの環境変数にパラメータストア参照で設定しているためパラメータストアのhttp_proxyの値がセットされている
      - echo $https_proxy # 同上
```

## 試したこと

冒頭の記載の通り、以下のように全てのプロキシ設定をCodeBuildの環境変数でパラメータストアを参照するとうまく行きません

![codebuild_parameterstore_ng.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219565/c73996cc-885a-94d8-4c0a-2fe851d4a13c.png)

以下のように、DOWNLOAD_SOURCEの箇所でエラーとなってしまいます。
``CLIENT_ERROR: RequestError: send request failed caused by: Get "https://codepipeline-ap-northeast-1-xxxxxxxxx.s3.ap-northeast-1.amazonaws.com/xxxxxx/SourceArti/xxxxxx": proxyconnect tcp: dial tcp :80: connect: connection refused for primary source and source version arn:aws:s3:::codepipeline-ap-northeast-1-xxxxxxx/xxxxxx/SourceArti/xxxxx``

![codebuild-failed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1219565/3387b6ef-21da-e75b-7606-f33cd6d04913.png)

* パラメータストアを利用せずに、PLAINTEXTで設定してもうまく行きます。
* ``.s3.ap-northeast-1.amazonaws.com,ssm.ap-northeast-1.amazonaws.com``をPLAINTEXTで指定している理由は、ソースステージのアーティファクトがS3にあるため、とパラメータストア(SSM)から値を読み出すためにVPCエンドポイントを経由するためです。
HTMLの基本を解説


プログラミングに興味を持った私が、学習したことをわかりやすくまとめよう思い、記事を作成しました。<br>インプットとアウトプットのバランスが大事だと言われているので、Qiitaをアウトプットの1つとして生かしたいと思います。
## HTMLとは
HTMLとは、「Hyper Markup Language(ハイパー・テキスト・マークアップ・ランゲージ)」の略で、Webページの土台となるファイルを作成する言語です。Webページに表示したい文章などを「<」と「>」で挟まれた「タグ」と呼ばれる文字で囲んで書いていきます。<br>「タグ」には様々な種類があり、コンピューターがそのページの構造を理解できるようにすることがHTMLタグの役目です。ほとんどのWebサイトがHTMLを使って作られています。
## HTMLの骨組み
まずは下記のコードをご覧ください。
```ruby:HTMLの骨組み
<!doctype html>
<html lang="ja">
 <head>
  <meta charset="UTF-8">
   <title>タイトル</title>
   <meta name="description" content="サイトの説明文">
 </head>

  <body>
    Webサイトの内容
  </body>

</html>
```
こちらは、HTMLの雛形です。初心者だと何が何だかわかりませんよね・・・<br>それでは、１つ１つ解説します。
```ruby:!doctype htmlとは
<!doctype html>
```
Doctype(ドクタイプ)宣言と言い、そのページがどのバージョンのHTMLで、どの仕様に合わせて作られているのかを書いていきます。

```ruby: html lang="ja"とは
<html lang="ja">

</html>
```
Doctype宣言のすぐ後に記述します。これはHTMLの文書だということを表しています。「lang」はWebページの言語を設定できる部分で、「ja」は、japaneseの略であり、日本語の文章であることを示しています。

```ruby: headとは
<head>

</head>
```
この部分はページのタイトルや説明文、使用する外部ファイルのリンクなど、ページの情報を記述しています。実際ブラウザーに表示されない部分です。

```ruby: meat charset="UTF8"とは
<meat charset="UTF8">
```
これは文字コードを「UTF-8」にするという指定です。これが正しく表記されていないと文字化けをしてうまく文字が表示されない場合もあるので、必ず記述しましょう。「meta」は「メタ要素」と言います。
```ruby: titleとは
<title>タイトル</title>
```
ページのタイトルを記述します。この名前がブラウザーのタブや、ユーザーがWebサイトをブックマークしたり、検索した時のページタイトルとして表示されます。

```ruby: meta name="description" content="サイトの説明文"とは
<meta name="description" content="サイトの説明文">
```
このページについての説明文を書きます。検索エンジンでページタイトルとともに表示される部分です。ユーザーが検索したときにどんなサイトなのかを瞬時に判断できるよう、必要なキーワードを混ぜて記述するとよいでしょう。

```ruby: bodyとは
<body>

</body>
```
HTML文章の本体部分です。ここにコンテンツを入力することで、実際にブラウザー上で表示されます。

## 終わりに
今回はHTMLの基本について解説しました。見る人によっては分かり難かったりするかもしれませんが、誰かのためになれればと思います。

### エンジニアファーストの会社　株式会社CRE-CO　　吉川　真史
EC2＋RDSでrailsの環境構築

# はじめに
EC2上にrails環境を構築する手順を備忘録として残しておきます。
DBはRDS（MySQL）を使用

# 前提
EC2を作成し、ログイン済
　※参考　[EC2にログインする](https://qiita.com/koyama_0122/items/8470522ec23513b749f4)
RDS（MySQL）作成済

# バージョン
ruby 2.7.0
rails 7.0.2
MySQL 8.0.28
bundler 2.1.2

# 手順

### パッケージの最新化
```
$ sudo yum update -y
```

### 必要なパッケージのインストール
```
$ sudo yum  -y install git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel libxml2-devel libxslt-devel ImageMagick ImageMagick-devel openssl-devel libcurl libcurl-devel curl
```

### Node.jsのインストール
```
$ sudo curl -sL https://rpm.nodesource.com/setup_10.x | sudo bash -
$ sudo yum -y install nodejs
```

### Yarnのインストール
```
$ sudo wget https://dl.yarnpkg.com/rpm/yarn.repo -O /etc/yum.repos.d/yarn.repo
$ sudo yum -y install yarn
```

### rbenvとruby-buildのインストール
```
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source .bash_profile
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
$ rbenv rehash
```

### rubyのインストール
```
$ rbenv install 2.7.0
$ rbenv global 2.7.0
$ rbenv rehash
$ ruby -v 　 #バージョン確認
```

### bundlerのインストール
```
$ gem install bundle
$ bundler -v  #バージョン確認
```

### railsのインストール
```
$ gem install rails -v 7.0.2
$ rails -v  #バージョン確認
```

### MySQLインストール
```
$ sudo yum install mysql
$ sudo yum install mysql-devel
```

### mysql8.0のリポジトリを追加する
```
$ sudo yum localinstall -y https://dev.mysql.com/get/mysql80-community-release-el7-3.noarch.rpm
```

 

### mysql8.0のリポジトリを有効化する
```
$ sudo yum-config-manager --disable mysql57-community
$ sudo yum-config-manager --enable mysql80-community
```

### mysql-community-clientをインストールする
```
$ sudo yum install -y mysql-community-client
```

### mysqlログイン（確認）
```
$ mysql -u ユーザー名 -p -h RDSのエンドポイント
#　パスワードを求められるのでRDSを作成した際に設定したパスワードを入力
```

### railsの起動
```
$ rails new アプリ名 -d mysql
```
### database.ymlファイルの編集
```
password: RDS作成時のパスワードを記載
host: RDSのエンドポイントを記載
```

### サーバーの起動
```
$ bundle exec rails s -b 0.0.0.0
```

### EC2のセキュリティグループ設定
現時点でEC2のセキュリティグループのインバウンドルールはSSH接続の22番ポートしか許可していない状態ですが、追加でカスタムTCPの3000番ポートを許可します。

### ブラウザによる表示
```
EC2のパブリックIPアドレス:3000
```
をブラウザで表示させると
![スクリーンショット (53).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2222596/ee9e8e6b-01f6-99cf-2e08-f06a4444ca02.png)
出ました。
CloudFrontによる静的Webホスティング＋署名付きURLの生成

# 目的

LambdaでCloudFrontの署名付きURLを生成し、S3オブジェクトのキャッシングを実装。

S3とCloudFrontの直接参照は不可とする。

## 参考記事

[【AWS】CloudFrontで署名付きURLの設定方法（プライベートコンテンツの配信）](https://zenn.dev/may_solty/articles/807dbad3a30de8)

## S3

- 新規でバケットを作成し、ファイルをアップロード
- アクセス許可：パブリックアクセスを全てブロック
- 静的ウェブサイトホスティング：無効

## CloudFront

- 新規ディストリビューションを作成
- オリジンドメイン：作成したS3バケット
- S3バケットアクセス：
    - OAIを使用（新規で作成）
    - バケットポリシー：自動更新

キーペアを生成後、「ビューアーのアクセスを制限する」を変更

## キーペアの作成

今回はOpenSSLで生成

```
openssl genrsa -out private_key.pem 2048
openssl rsa -pubout -in private_key.pem -out public_key.pem
```

public_keyをAWSにアップロード

- CloudFrontの左メニューから「パブリックキー」を選択
- 新規で作成し、名前と内容を入力
- メニューから「キーグループ」を選択
- 新規で作成し、名前と、上記で作成したパブリックキーを選択し紐付ける

## CloudFront Behavior

- 作成したCloudFrontディストリビューションを選択し編集
- 「ビヘイビア」メニューから作成済みのものを選択
- 「ビューアーのアクセスを制限する」を設定
  - アクセスを制限する：YES
  - 信頼された認可タイプ：Trusted key groups(recommended)
  - キーグループを追加：作成したキーグループを選択

## 署名付きURLの発行【Lambda】

今回はNode.jsを使用

以下の手順でファイルを作成し、モジュールをzip形式でまとめる

```
mkdir modules
cd modules
npm i async
npm i aws-cloudfront-sign
```

- modulesディレクトリに「キーペアの作成」で作成したプライベートキーと、以下のファイルを設置

```index.js
exports.handler = async(event) => {
 const cloudFrontSign = require('aws-cloudfront-sign')
 const expire = new Date();
 expire.setTime(currentDate.getTime() + 24*60*60*1000);
 const signedUrl = cloudFrontSign.getSignedUrl(
  'CloudFrontのオリジンURL',
  {
   keypairId: 'キーペアID'
   privateKeyPath: '.private_key.pem',
  },
  expire
 );

 return {JSON.stringify(signedUrl)}
 
}
```

- zip化

```
zip -r modules index.js private_key.pem node_modules/
```

- 新規でLambda関数を作成
- 「コード」メニューの「アップロード元」から、作成したzipファイルをアップロード後、デプロイ

## APIゲートウェイ

- 新規でAPIゲートウェイを作成し、メソッドを定義
- 作成したLambda関数をAPIゲートウェイと紐付ける

## 動作確認

GETメソッドであればブラウザのURLから直接パスを入力して呼び出してもよし、そうでなければPostman等を使用するもよし。

返却されたURLを叩いてS3オブジェクトが参照できれば完了。

# あとがき

- 使用しているモジュールの**aws-cloudfront-sign**が暫くサポートされていないため、**aws-sdk**の**AWS.CloudFront.Signer**を使用するべき
- **Lambdaに秘密鍵を設置するのはセキュリティ的に好ましくない**ため、**パラメータストア**や**シークレットマネージャー**を使用するべき（aws-sdkのSignerであれば、**秘密鍵の情報をファイル指定ではなく文字列で渡せる**）
【React】useEffectを非同期にしてfetchしたデータをuseStateのset関数で更新する

個人の備忘録です。

React HooksのuseEffectを使っていて、useEffect内で外部からfetchしてきたデータをuseStateのset関数で更新しようとした時のメモ。

# 環境
- React.js v17.0.2

# 結論
- useEffect に直接 async はつけれない
  - Promiseを返してしまうから
- useEffect内で非同期関数を作る

# 例
```typescript
// ❎
useEffect(async () => {
  const res = await fetchData();
  setValue(res);
}, []);

// 🟢
useEffect(() => {
  // 非同期関数の作成
  const fetchFunction = async () => {
    const res = await fetchData();
    // set関数で値の更新
    setValue(res);
  };
  // 非同期関数の実行
  fetchFunction();
}, []);
```
VSCode + Windows Subsystem for Linux環境メモ

参考サイト：[Visual Studio Codeで競プロ環境構築(導入編)](https://qiita.com/AokabiC/items/e9312856f588dd9303ed)

この記事通りにやったらできたよ～ってメモ。

APG4B：https://atcoder.jp/contests/apg4b AtCoderの初心者用のプログラミング入門教材で動作確認実施。

WSL(Windows Subsystem for Linux) + VSCode 

※ 会社のPCでWSLを入れるのをためらったので、会社PCではVSCode+MinGWで環境構築した。
## 環境
- Windows 10 Home
- VSCode
- WSL

## 実行テストする場合
```C++
#include <bits/stdc++.h>
using namespace std;
 
int main(){
cout << "Hello, world!" << endl;
cout << "こんにちは世界" << endl;
cout << 2525 << endl;
}
```
ターミナルを表示(VSCodeメニューバー→表示→統合ターミナル / Ctrl+@) WSL環境を起動
```
> wsl # WSL環境を起動
```
```
$ g++ hello.cpp # hello.cppをコンパイル→実行ファイル"a.out"が作成される
$ ./a.out # 実行ファイル
```

## コンパイルしてexeファイルを作成する場合
```bash
$ g++ -o hello.exe hello.cpp # hello.cppをコンパイル→実行ファイル "a.out"が作成される
$ ./hello.exe # 実行ファイル
```
同様の出力結果が得られる。

## 参考：VSCode + MINGWでのC++環境
MINGW環境でも動作することを確認。 すでにC++環境セットアップ済みのLet’s noteで動作確認したため、環境設定メモは残せず。
下記に既存環境でのエラー回避のメモを残す。 日本語表示、C++11オプションなどをつけてAPG4Bの環境で動作を確認。
```bash
 g++ -o 1_13 1_13.cpp -fexec-charset=CP932 -std=c++11
```
日本語出力が文字化けしないようにCP932オプション
配列作成時にコンパイルエラー発生。c++98環境がデフォルト設定されていたため、c++11オプションを追加してエラー回避を確認
PythonでTomlを読み込もう！

# TOMLファイルを用意

👇　以下のページから  

📖 [TOML](https://toml.io/en/)  

👇　コピーして、練習用に　テキストファイルを作成  

📄`example.toml`:  

```toml
# This is a TOML document

title = "TOML Example"

[owner]
name = "Tom Preston-Werner"
dob = 1979-05-27T07:32:00-08:00

[database]
enabled = true
ports = [8000, 8001, 8002]
data = [["delta", "phi"], [3.14]]
temp_targets = { cpu = 79.5, case = 72.0 }

[servers]

[servers.alpha]
ip = "10.0.0.1"
role = "frontend"

[servers.beta]
ip = "10.0.0.2"
role = "backend"
```

# pytomlpp をインストール

👇　環境に pytomlpp をインストール

```shell
pip install pytomlpp
```

# main.py ファイル作成

👇　コピー貼り付け  

📄`main.py`:  

```py
import pytomlpp

with open('example.toml', mode='r', encoding='utf-8') as f:
    text = f.read()

# print(text)

# ここに Toml の処理を書く
print("Tomlの読込")
doc = pytomlpp.loads(text)

print(f"ip は {doc['servers']['alpha']['ip']}")
```

# 実行

```shell
python.exe main.py
```

# 出力結果

```plaintext
Tomlの読込
ip は 10.0.0.1
```
【2022年最新版】mozjpeg vs guetzli vs webp vs avif 圧縮率

### はじめに

なんとかメモリ不足ながらも生成できましたので

### 使用サイト

https://coldcurry.org/


### とりあえずのコマンドラインでエンコード
#### 生データ　Part1
かなり巨大です。ご注意ください

とおもいきや、googleドライブのデータ容量超過で誤って削除したため、省略

#### データの概要
オリジナルの4K画像（おおむね1M～5Mバイト）の画像を
Image::Magickで自動加工をして
一度、RAMDISKソースJPGとして出力します。

この画像を元画像とします。

それから、以下のコマンドラインで圧縮

- /opt/mozjpeg/bin/cjpeg -quality 75～90 -optimize
- /usr/local/bin/guetzli --quality 84
- /usr/local/bin/cwebp -quiet -q 80 -z 9
- /usr/local/bin/avifenc -j 1 -s 0

RAMDISK上に保管し、以下の条件でサイトに反映させるために、ストレージにコピーします。

- guetzliが0バイトでなければ？
- →mozjpegよりguetzliのが小さければ？
- →→guetzliのファイルをjpegとしてコピー
- でなければ、mozjpegのファイルをjpegとしてコピー
- webpよりavifのが小さければ？avifをコピー
- jpegよりwebpのが小さければ？webpをコピー

:::note info
avifよりwebpのがファイルサイズが小さいことがまれにあります。
webpよりjpegのがファイルサイズが小さいことがまれにあります
:::


#### データ容量の傾向（約41000画像ファイルの平均）
- オリジナルJPEG 678013 バイト（これを100%とする）
- mozjpeg JPEG 200327 バイト (オリジナルより29.54%）
- guetzli JPEG 172961 バイト (オリジナルより25.5%、mozjpegより86.3%）
- webp 74438バイト (オリジナルより10.97%、guetzliより43.0%）
- avif 49792 バイト (オリジナルより7.34%、guetzliより28.7%、webpより66.8%）

### 最適化したコマンドラインでエンコード
#### 生データ　Part2
かなり巨大です。ご注意ください

https://docs.google.com/spreadsheets/d/11yzIsqUrWSGq0895mceVprFMvzCKCnzSCScvHsYzbrQ/edit?usp=sharing

#### データの概要
オリジナルの4K画像（おおむね1M～5Mバイト）の画像を
Image::Magickで自動加工をして
一度、RAMDISKソースJPGとして出力します。

この画像を元画像とします。

それから、以下のコマンドラインで圧縮

- /opt/mozjpeg/bin/cjpeg -quality 75～90 -optimize
- /usr/local/bin/guetzli --quality 84
- /usr/local/bin/cwebp -quiet -q 80 -z 9
- /usr/local/bin/avifenc -j 14 -s 0 --min 0 --max 63 --minalpha 63 --maxalpha 63

その他これだけ多くの圧縮ツールを連続して2日間ぐらい並列動作させるとcoreをはくため、coreはいた時のリトライ処置を設置

RAMDISK上に保管し、以下の条件でサイトに反映させるために、ストレージにコピーします。

- guetzliが0バイトでなければ？
- →mozjpegよりguetzliのが小さければ？
- →→guetzliのファイルをjpegとしてコピー
- でなければ、mozjpegのファイルをjpegとしてコピー
- webpよりavifのが小さければ？avifをコピー
- jpegよりwebpのが小さければ？webpをコピー


#### データ容量の傾向（約42000画像ファイルの平均）
- オリジナルJPEG 677784 バイト（これを100%とする）
- mozjpeg JPEG 200321 バイト (オリジナルより29.55%）
- guetzli JPEG 173022 バイト (オリジナルより25.52%、mozjpegより86.3%）
- webp 74408バイト (オリジナルより10.97%、guetzliより43.0%）
- avif 33352バイト (オリジナルより4.92%、guetzliより19.27%、webpより44.82%）

#### 最大容量のファイルをチョイスしてみる
- 解像度：1600×2844
- オリジナル：4139378バイト
- mozjpeg：1255172バイト
- guetzli：エラー
- webp：466538バイト
- avif：246350バイト



## さいごに
- avif は webpより 55.1%のサイズ削減が確認されたことになります。
- avif は guetzli(JPEG)より 80.7%のサイズ削減が確認されたことになります。
- avif は mozjpeg (JPEG) より 83.3%のサイズ削減が確認されたことになります。
- webp は guetzli(JPEG)より 56.9%のサイズ削減が確認されたことになります。
- webp は mozjpeg (JPEG) より 62.8%のサイズ削減が確認されたことになります。
【React】「Error: List(...): Nothing was returned from render」のエラーが出た

完全に個人の備忘録です。

React + TypeScriptで書いている時に以下のエラーが出たのでメモ。

```
# VSCode側
'Component' cannot be used as a JSX component.
Its return type 'Element | undefined' is not a valid JSX element.
Type 'undefined' is not assignable to type 'Element | null'.ts(2786)

# ブラウザ側
Unhandled Runtime Error
Error: List(...): Nothing was returned from render.
This usually means a return statement is missing.
Or, to render nothing, return null.
```

# 環境
- PC: MacBook Pro (Intel Core 2016)
- OS: macOS Montery12.3.1
- Node.js v16.10.0
- React.js v17.0.2

# 結論
- returnしてるけどDOMを返していないとこのエラーになるので、`return <></>` とかにする

# 例
```typescript
// ❎
if (!fetchData) {
  return;
}

// 🟢
if (!fetchData) {
  return <></>;
}
```
【備忘録】timedatectl set-timezoneについて

### 背景
久しぶりに新規でEC2インスタンスを作成したのでタイムゾーンを設定しようとした。
タイムゾーンの設定について少し調べたので備忘録として投稿する。

### 参考ページ
https://linuc.org/study/knowledge/516/
https://siguniang.wordpress.com/2015/03/20/set-timezone/
https://www.t3a.jp/blog/infrastructure/set-timezone/

### やったこと
デフォルト状態。上記参考ページから「あれ？このファイルってシンボリックリンクじゃないの？」って思いました。
```bash
# ls -l /etc/localtime 
-rw-r--r-- 1 root root 127  3月 16 01:53 /etc/localtime

# cat /etc/localtime
TZif2UTCTZif2?UTC
UTC0
```

バイナリファイルで全然読めん笑
```bash
# ls -l /usr/share/zoneinfo/Asia/Tokyo 
-rw-r--r-- 2 root root 318  2月 11 19:04 /usr/share/zoneinfo/Asia/Tokyo

# cat /usr/share/zoneinfo/Asia/Tokyo 
TZif2	
        ??>p??Y????p??;???ۭ?????݌?????~~LMTJDTJSTTZif2

?????e¤p?????>p??????Y????????p??????;???????????ۭ?????????????݌?????~~LMTJDTJST
JST-9
```
最初の設定状態
```bash
# timedatectl
      Local time: 火 2022-04-05 08:58:35 UTC
  Universal time: 火 2022-04-05 08:58:35 UTC
        RTC time: 火 2022-04-05 08:58:36
       Time zone: n/a (UTC, +0000)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
```

あ、rebootしなくても変更反映されてるじゃん
```bash
# timedatectl set-timezone Asia/Tokyo

# timedatectl status
      Local time: 火 2022-04-05 20:57:35 JST
  Universal time: 火 2022-04-05 11:57:35 UTC
        RTC time: 火 2022-04-05 11:57:36
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a

# date
2022年  4月  5日 火曜日 21:02:34 JST
```
一応rebootした後にdate打ったら英語表示なんだけどこれは何故でしょう？
また後日調べますか、、、

```bash
# reboot

# date
Tue Apr  5 21:08:04 JST 2022

# timedatectl status
      Local time: Tue 2022-04-05 21:32:44 JST
  Universal time: Tue 2022-04-05 12:32:44 UTC
        RTC time: Tue 2022-04-05 12:32:45
       Time zone: Asia/Tokyo (JST, +0900)
     NTP enabled: yes
NTP synchronized: yes
 RTC in local TZ: no
      DST active: n/a
```
【React × TypeScript × ESLint】props定義でMust use destructuring props assignmenteslintreact/destructuring-assignmentがでた

## ESLintエラー本文：Must use destructuring props assignmenteslintreact/destructuring-assignment


このエラーの意味は
```tsx
props.headerMenu1
```
とやっちゃだめ
```tsx
headerMenu1
```
と書ける様に定義してね！というエラー

なので、以下の様にDestructureReactプロップオブジェクトを作りpropsを定義します
```tsx:Header.tsx
type Props = { // ・・・・・・・・・・・・①
  headerMenu1: string;
  headerMenu2: string;
  headerMenu3: string;
};

const Header = (props: Props) => {
  const { headerMenu1, headerMenu2, headerMenu3 } = props; // ・・・・・・・・・・・・②
  return (
    <div className='relative bg-white'>
          <div className='hidden md:flex-1 md:flex md:items-center md:justify-end'>
            <Link href='/users/me'>
              <div className='flex items-center md:ml-12 mr-2'>
                <span className='text-sm font-semibold text-gray-700 hover:text-gray-900'>
                  {headerMenu1} // ・・・・・・・・・・・・③
                </span>
              </div>
```
①普通にpropsの型宣言
②宣言したpropsでDestructureReactプロップオブジェクトを作成
③DestructureReactプロップオブジェクト内のプロパティでpropsプロパティを定義

これにより、表題のESLintエラーは解消します



以上です
多くのコンストラクタパラメータに直面したときには、ビルダーを検討する

# これは何？
Effective Java 第3版を読んで自分なりにかみ砕いた内容を記事に落としていきます。
良いコードを書くための選択肢の一つになれば最高なので、頑張ります。
※読み進める中で知識のアップデート等あれば都度更新いたします。

# 問題提起
[前の記事](https://qiita.com/arikei/items/bf5fdef55dce4cb34f7d)で紹介したstaticファクトリメソッドやコンストラクタは共通の課題がある。
__「多くの必須ではないパラメータ(オプションパラメータ)に上手く対応できない」__

この問題にうまく対応する方法が __Builderパターン__ である。

## 選択肢①(あまり良くない)
テレスコーピング・コンストラクタが使われたりするらしい。。。

~~~java
//テレスコーピング・コンストラクタ
public class Hoge {
  private final int 必須パラメータ1
  private final int 必須パラメータ2
  private final int オプションパラメータ1
  private final int オプションパラメータ2
  private final int オプションパラメータ3

  public コンストラクタ(int 必須1, int 必須2) {
    this(必須1, 必須2, 0);
  }

  public コンストラクタ(int 必須1, int 必須2, int オプション1) {
    this(必須1, 必須2, オプション1)
  }

  //同じ要領でパラメータを増やしたコンストラクタを作成する。
}
~~~

この場合、オプションパラメータすべてを設定しようとすると、
* コードを書くのが大変になる
* コードを読むのはもっと大変になる(どのパラメータが何に対応しているか)

## 選択肢②(あまり良くない)
JavaBeanパターンなるものがあるらしい。
→パラメータなしのコンストラクタを呼び出す。その後、パラメータを設定するためのセッターを呼び出す。

~~~java
public class Hoge {
  //(あれば)パラメータを初期化
  private final int 必須パラメータ1 = -1
  private final int 必須パラメータ2 = -1
  private final int オプションパラメータ1 = 0
  private final int オプションパラメータ2 = 0
  private final int オプションパラメータ3 = 0

  public Hoge() { }

  //セッター
  public void set必須1(int value) { 必須パラメータ1 = value}
  public void set必須2(int value) { 必須パラメータ2 = value}
  //以下オプションパラメータもセッターを作成
}
~~~~

この場合、テレスコーピング・コンストラクタが持っていた欠点は無くなった！！
セッターに名前がついているのでコードを書きやすいし、読みやすくなる。

しかし、これも重大な問題がある。。。
* オブジェクトの生成過程で不整合な状態になる
* 不変クラスになる可能性がなくなる
(この欠点については、不変クラスなどで検索してみてください。私も絶賛勉強中)

## 選択肢③(本題)
やっと出てきました本題のBuilderパターンです。
Builderパターンの概要は以下のような感じ
* 必須パラメータをすべて持つコンストラクタかstaticファクトリメソッドを呼び出す
* 必要なオプションパラメータを設定するためのセッターを呼び出す
* パラメータを持たないbuildメソッドを呼び出す

具体的なコードは以下

~~~java
public class Hoge() {
  private final int 必須1
  private final int 必須2
  private final int オプション1
  private final int オプション2
  private final int オプション3
  private final int オプション4

  public static class Builder {
    //必須パラメータ
    private final int 必須1
    private final int 必須2

    //オプションパラメータ - デフォルト値に初期化
    private final int オプション1 = 0;
    private final int オプション2 = 0;
    private final int オプション3 = 0;
    private final int オプション4 = 0;

    public Builder(int 必須1, int 必須2) {
      this.必須1 = 必須1;
      this.必須2 = 必須2
    }

    public Builder オプション1(int value) {
      オプション1 = value;
      return this;
    }
    public Builder オプション2(int value) {
      オプション2 = value;
      return this;
    }
    public Builder オプション3(int value) {
      オプション3 = value;
      return this;
    }
    public Builder オプション4(int value) {
      オプション4 = value;
      return this;
    }

    public Hoge build() {
      return new Hoge(this);
    }
  }

  private Hoge(Builder builder) {
    必須1 = builder.必須1;
    必須2 = builder.必須2;
    オプション1 = builder.オプション1;
    オプション2 = builder.オプション2;
    オプション3 = builder.オプション3;
    オプション4 = builder.オプション4;
  }
}
~~~

セッターメソッドはBuilder自身をreturnするので、オブジェクト生成時は

~~~java
Hoge hoge = new Hoge.Builder(4, 29).オプション1(38).オプション2(32).オプション3(23).オプション4(38).build()
~~~

となる（きれいなコードの完成！！）

Builderパターンのより適したものについては次の記事で書きます。(絶賛勉強中)
よろしくお願いします！！！
Nuxtをインストール後にnpm run devでエラーを吐く時の解決方法

**解決方法：NodeをLTSバージョンに変更**

Nuxtをインストールしてよし始めるぞとなった時に下記のエラー吐きました。
```
node:internal/crypto/hash:67
  this[kHandle] = new _Hash(algorithm, xofLen);
                  ^

Error: error:0308010C:digital envelope routines::unsupported
    at new Hash (node:internal/crypto/hash:67:19)
    at Object.createHash (node:crypto:135:10)
    at module.exports (/Users/tenopee/work/node_modules/webpack/lib/util/createHash.js:135:53)
    at NormalModule._initBuildHash (/Users/tenopee/work/node_modules/webpack/lib/NormalModule.js:417:16)
    at handleParseError (/Users/tenopee/work/node_modules/webpack/lib/NormalModule.js:471:10)
    at /Users/tenopee/work/node_modules/webpack/lib/NormalModule.js:503:5
    at /Users/tenopee/work/node_modules/webpack/lib/NormalModule.js:358:12
    at /Users/tenopee/work/node_modules/webpack/node_modules/loader-runner/lib/LoaderRunner.js:373:3
    at iterateNormalLoaders (/Users/tenopee/work/node_modules/webpack/node_modules/loader-runner/lib/LoaderRunner.js:214:10)
    at Array.<anonymous> (/Users/tenopee/work/webpack/node_modules/loader-runner/lib/LoaderRunner.js:205:4)
    at Storage.finished (/Users/tenopee/work/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:55:16)
    at /Users/tenopee/work/node_modules/enhanced-resolve/lib/CachedInputFileSystem.js:91:9
    at /Users/tenopee/work/node_modules/graceful-fs/graceful-fs.js:123:16
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}

Node.js v17.5.0
```
まずは環境の確認。
Node：v17.5.0
Nuxt：v2.15.8

次に[Nuxtのドキュメント](https://nuxtjs.org/ja/docs/get-started/installation#%E5%89%8D%E6%8F%90%E6%9D%A1%E4%BB%B6 "前提条件")を確認。

> Node.js - 最新の LTS バージョンのインストールを推奨します。

次にNode.jsのドキュメントでLTSバージョンを確認しました。
・[リリース情報](https://nodejs.org/ja/about/releases/)
・[リリース一覧](https://nodejs.org/ja/download/releases/)
![nodejs.org_ja_about_releases_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295146/6f37aa41-7a94-b0e3-5dcd-c27c5aa75eaf.png)
※2022/4/5時点

ということで私が使っていたNodeのバージョンがLTSではなかったため、v16の一番最新のv16.14.2を使うとエラーを吐くことなく動きました。


## 最後にひとこと
「よっしゃ開発するぞ！全部最新のバージョンを使ったろ！」と最初はなると思いますが、いざ開発しようとなった時に最新バージョンが使えないってことは結構あると思います。
ちゃんとドキュメントをよんで推奨バージョンを確認すればこのような失敗にはならなかったと思うので、今後も気をつけたいと思いました。
皆様もお気をつけてください。
CodePipeLineを使用したCI/CDの構築

## 目的

以下のデプロイフローを実現

- **CodeCommitリポジトリ**のPushをトリガーに、**CodeBuild**によるビルド/テストを実行
- ビルドに問題がなければWebアプリの実行ファイルを**S3**にデプロイ
- **S3**にデプロイしたWebサイトを**CloudFront**でキャッシング

## 参考記事

[[AWS] CodeCommit + CodeBuild + CodePipeline + S3で静的コンテンツをデプロイする環境を作ってみる！](https://qiita.com/kottyan/items/69dc599dc5222702cb2b)

## 使用したAWSサービス

- **S3**
- **CodeCommit**
- **CloudFront**
- **CodeBuild**
- **CodePipeLine**

## CodeCommit

- 新規リポジトリを作成

## S3

- 新規バケットを作成（アクセス許可はパブリックアクセスを全てブロック）

## CloudFront

- 新規ディストリビューションの作成
- オリジンドメイン：作成したS3バケット
- S3バケットアクセス:
    - OAIを使用（新規で作成）
    - バケットポリシー：自動で更新

## CodeBuild

- 新規プロジェクト作成

### プロジェクトの設定

- プロジェクト名を入力

### ソース

- ソースプロバイダに「AWS CodeCommit」を指定し、作成したリポジトリを選択

### 環境

- 環境イメージ：マネージド型イメージ
- オペレーティングシステム：Amazon Linux 2
- ランタイム：Standard
- イメージ：aws/codebuild/amazonlinux2-aarch64-standard:1.0
- イメージのバージョン：常に最新
- サービスロール：新しいサービスロール

### Buildspec

- 「buildspecファイルを使用」を選択し、ファイル名を入力

※こちらで指定するbuildspecファイルはソースプロジェクトに設置。

```buildspec.yml
version: 0.1

phases:
 install:
  runtime-versions:
   nodejs: 12
  commands:
   - cd app
   # package.jsonのある階層に移動
   - npm ci
   # nodeのインストール
   - npm i n 
   - n latest
 build:
  commands:
   # テストやビルドの実行
   # S3へデプロイ
   - aws s3 sync dist/app s3://{S3バケット名} --delete
   # キャッシュ削除
   - aws cloudfront create-invalidation --distribution-id ${CLOUDFRONT_DIST_ID} --paths '/*'
 # アーティファクトの出力
 artifacts:
  files:
   - "**/*"
```

### アーティファクト

- タイプ：S3
- 作成したバケットを選択

### ログ

- CloudWatchログ：ON

<br>

※作成したプロジェクトを選択し、「ソース」メニューからビルド対象のリポジトリやコミットの指定が可能

<br>

### ポリシーの設定

CodeBuildプロジェクトの作成時、新規でCodeBuildのロールを生成した場合は以下の権限を付与する必要あり

- S3（書き込み、削除）
- CloudFront Create Invalidation

## CodePipeLine

- 新規プロジェクトを作成

### パイプラインの設定を選択する

- パイプライン名を入力し、「新しいサービスロール」を選択

### ソースステージを追加する

- ソースプロバイダー：AWS CodeCommit
- 作成したリポジトリとブランチを選択
- 検出オプション：AWS CodePipeLine
- 出力アーティファクト形式：完全クローン

### ビルドステージを追加する

- プロバイダー：AWS CodeBuild
- 作成したCodeBuildプロジェクトを選択
- buildspec.ymlに埋め込むための環境変数を設定
   - CLOUDFRONT_DIST_ID：CloudFrontのディストリビューションID

### デプロイステージを追加する

- デプロイ先のS3の情報を設定

※デプロイしたファイルをルートに配置する場合、S3オブジェクトキーは「/」を入力

# 動作確認

- CodeCommitから変更内容をPushして、S3にデプロイされること、CloudFrontのオリジンURLからWebアプリを参照できることを確認

# 終わりに

CI/CDを概念としてしか理解していなかった著者ですが、実際に調べて手を動かすとかなり理解が深まりました。
perlで切り捨て処理


小数点以下の切り捨てをperlで実現したかったが
int関数でうまくいかなかった

```
perl -e '$v=int(110/1.1);print $v;'
99
```
100にならない。。



なので別のアプローチをして対処。
(.をデリミタにしてsplitする作戦)
```
perl -e '$v=110/1.1;($v)=split /\./,$v; print $v;'
100
```

正攻法なのだろうか。。
web制作で学んだことリスト(html css編)

備忘録なので、あしからずです。

`display: inline-block`
文章の長さによって要素を可変するために使用することもある。基礎の基礎。

`margin: auto`
スマホのレスポンシブの際にpaddingだけ指定していると、要素が真ん中に行かないので、注意。
display: flexと使うスマホ表示の際に要素崩れが起きない。
【macOS12.3.1】pip install pyodbcで”src/pyodbc.h:56:10: fatal error: 'sql.h' file not found”エラー対応備忘録

# 現象
```pip install pyodbc```で以下のエラーでインストールできず.
```zsh:zsh
$ pip install pyodbc
Collecting pyodbc
  Using cached pyodbc-4.0.32.tar.gz (280 kB)
  Preparing metadata (setup.py) ... done
Using legacy 'setup.py install' for pyodbc, since package 'wheel' is not installed.
Installing collected packages: pyodbc
  Running setup.py install for pyodbc ... error
  error: subprocess-exited-with-error
  
  × Running setup.py install for pyodbc did not run successfully.
  │ exit code: 1
  ╰─> [14 lines of output]
      running install
      running build
      running build_ext
      building 'pyodbc' extension
      creating build
      creating build/temp.macosx-12.3-x86_64-3.10
      creating build/temp.macosx-12.3-x86_64-3.10/src
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -DPYODBC_VERSION=4.0.32 -UMAC_OS_X_VERSION_10_7 -I/usr/local/include -I/Users/takasukaoru/python_project/corpdb/corpdb/.venv/include -I/Users/takasukaoru/.pyenv/versions/3.10.1/include/python3.10 -c src/buffer.cpp -o build/temp.macosx-12.3-x86_64-3.10/src/buffer.o -Wno-write-strings -Wno-deprecated-declarations
      In file included from src/buffer.cpp:12:
      src/pyodbc.h:56:10: fatal error: 'sql.h' file not found
      #include <sql.h>
               ^~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

× Encountered error while trying to install package.
╰─> pyodbc

note: This is an issue with the package mentioned above, not pip.
hint: See above for output from the failure.
```
"sql.h"が見つかりません。sql.hとは・・・。

# 対処法
色々謎だったが、ここがヒットしたので、この対処法を試す.

https://github.com/mkleehammer/pyodbc/issues/385

```zsh:zsh
brew install unixodbc
```
これで無事```pip install pyodbc```が通った.
理由は調査中.
[Set up] Robot framework - python in mac

# Outline
E2E test automationのsolutionに、robot frameworkがある。
robot frameworkの特徴として、以下のようなものがある
- 自然言語に近い記述で処理を記述できる（キーワード駆動）
- 複雑なプログラミングなしで記述できる
- レポーティング機能がデフォルトで用意されている

今回、robot framework環境を構築し、簡単なプログラムを実行して体験してみる。

尚、BigSur 11.6.1で構築した

| Item | Version | Note |
|:-----------|:------------|:-------------|
| Mac       | BigSur 11.6.1        |         |
| Python | 3.8.9 | |
| chrome | 100.0.4896.60 | |



# Install Python

macはdefaultでPython2.7がinstallされている。
しかし、最新にして動かしたいので、Python3をinstallする

### Install Homebrew

Pythonをinstallするにあたり、パッケージ管理ツールHomebrewをinstallする
terminalを起動し、以下コマンドを入力する

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

### Install Python

homebrewを使って、python3をinstallする

```
brew install python3
```

install後、version確認をする
```
python3 --version
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/6737aec6-e291-5e6c-858e-bd6234f84dfc.png)


### PATH 設定

pip のpathを設定する
基本的に、user （${USERNAME}）　のLibraryにinstallされる。
まず、installされた先を確認する


```
/Users/${USERNAME}/Library/Python/3.8/bin
```

bashを使用している場合、.bash_profileにexportでPATHの追加をする

```
vi ~/.bash_profile 
```

export例
```
export PATH="/Users/${USERNAME}/Library/Python/3.8/bin:$PATH"
```

改めて、terminalを起動し、PATHを有効にする。



# Install robotframework

pipを用いてインストールする

```
pip3 install --upgrade robotframework-seleniumlibrary
```

# chrome selenium webdriver

chromeのwebdriverをインストールする

### download
使用しているchromeのversionに合わせたdriverをdownloadする
download後、任意のpathに配置する。

今回、chrome version 100.0.4896.60 のため、mac用の100.0.4896.60versionをdownloadする。

https://chromedriver.chromium.org/downloads

### path
設置したchromedriverをどのpathからでも実行できるように、pathを設定する

export例
```
export PATH="/Users/${USERNAME}/Applications:$PATH"
```
※ userのApplicationsに配置した場合

### 権限付与

そのままでは実行できない。実行権限を与える

```
chmod 755 chromedriver
```


### 開発元未確認の解除

chromedriverをそのまま使用することはできません。
以下のような警告が出ます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/6bee197d-fe26-3dac-6944-b3442dc7483c.png)

これを解除するため、設定→セキュリティとプライバシーで、<B>許可</B>の設定をする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/3cf7762f-73bf-0983-d4ed-c25ce26a9966.png)


参考
https://support.apple.com/ja-jp/guide/mac-help/mh40616/mac

# Sample Program

実際に構築した環境が動くかどうか、簡単なプログラムを走らせてみる。

programは以下のテストステップを実行する
1. chromeを立ち上げる
2. rakuten topにアクセスする
3. screenshotをとり、保存する
4. chromeを閉じる


```
*** Settings ***
Documentation  sample program
Library    SeleniumLibrary

*** Test Cases ***
ScreenShot top page
  Open Browser  https://rakuten.co.jp/  browser=chrome
  Capture Page Screenshot  filename=screenshot.png
  Close Browser
```

では、実際に走らせてみよう。

```
robot sample.robot
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267085/608d7b28-2cc6-b3a4-0e5d-7371147d3d33.png)

実行後、report fileとscreenshot.pngが生成されていることが確認できる。


# reference

https://serhatbolsu.github.io/robotframework-appiumlibrary/AppiumLibrary.html
rake stderr: warning package.json: No license field warning package-lock.json found.

# 前提
Rails 6.1.3
Ruby  2.6.5
# エラー内容
```
rake stderr: warning package.json: No license field warning package-lock.json found.
```
# 結論（解決方法）
以下のコードを書くだけです。
```package.json
{
...
  "license": "UNLICENSED"
...
}
```
# 補足
## package.jsonとは
アプリが依存するパッケージに関する情報を記録するのに使用するファイルで
JSON形式で各種の設定を記述します。
## package-lock.jsonとは
このファイルには dependency、dependency の dependency...と間接的なものも含めすべての dependency のバージョン(とその integrity)が記録される。
## No license fieldとは
No license field==ライセンスが設定されていない
# 参考記事
[「package.json」って何？って時に少し調べた時のノート](https://overworker.hatenablog.jp/entry/2020/09/27/232236)
[warning ../../package.json: No license field](https://qiita.com/narimiya/items/fe0e308a2177c9f0e275)
[【初心者向け】NPMとpackage.jsonを概念的に理解する](https://qiita.com/righteous/items/e5448cb2e7e11ab7d477)
[]()
たまに起動したくなるGNS3がいつもすぐ動かなくなる件（笑）

たまに起動したくなるGNS3がいつもすぐ動かなくなる件（笑）

今回は、VMware Player をアップグレードしてしまったところから不幸のはじまりｗ Player じゃなくて Prayerだｗｗ

```Virtualized Intel VT-x/EPT is not supported on this platform.Continue without virtualized Intel VT-x/EPT?```

なんだこのメッセージ？
仮想化の周りBIOSの設定とかHyper-V使っているとダメとかいろいろあったような気がする・・・。

とりあえず Hyper-V　無効化。
したら動いた。
Laravel　代行ログイン

プログラムでユーザーログインする場合以下でできる。
ただしIDを指定してしまえばどのアカウントにもログインできてしまうので権限チェックなどは必要。

```php
//セッションIDの再発行
session()->regenerate();

//ログイン
\Auth::loginUsingId($user_id);
```
リングバッファって何のこと？

## 勉強前イメージ

バッファみたいやけどリングってなに？
輪？

## 調査

### リングバッファ とは

バッファ領域のうち、バッファ領域が再利用できるようになったものです。
キューに使われる構造で、First in First out(FIFO)という
最初に登録されたものが一番最初に取り出されるという構造があります。
キューが段々溜まっていきますが、最初に入れられたキューも段々処理され不要になっていきます。
その不要になったキューの上に新しいキューを書くというのが `リングバッファ` になります。

キューが満タンで格納できない時もあります。
そうすると後から入れるアクションをしたキューが先に入ることもあります。
理由としてはキューを入れるときには満タンで数秒タイムアウトしてるうちに、満タンが解消され他のキューに先に入られてしまうなど可能性としてあります。
そのようなことがないようにキューの設計が必要です。

## 勉強後イメージ

ちらっと見たけど、リングバッファがどういうときに実装するのかがよくわからなかった。
ただ、FIFOとかLIFOのお仲間な気がする。

## 参考

- [キューとリングバッファについてやさしい言葉で解説してみる](https://future-architect.github.io/articles/20210705a/)
PyCharm Community EditionでFlaskアプリケーションを起動する設定

# 目的
PyCharm Community EditionでFlaskアプリケーションを起動する設定の覚書です

# 注意
PyCharm Professionalを使えば　Flaskサポートは標準搭載されており、このページの手順は不要です。
Python入門中だし、最初はPyCharm Community Editionでいいかなという気持ちで使っています。

https://www.jetbrains.com/help/pycharm/flask.html

# 環境
- macOS Monterey
- PyCharm Community 2021.3.3
- Python 3.9.10

ソースコードは Flask Tutorialの [Blog Blueprint](https://flask.palletsprojects.com/en/2.1.x/tutorial/blog/) まで終わらせたものを使っています


# 手順
1. PyCharm Community Editionでflaskを使ったソースコードを開く
1. 右上のプルダウンから`Edit Configuration` を選択 <br/> 画像ではすでに `flask-tutorial-blog` を作った状態 <br/>![スクリーンショット 2022-04-05 19.24.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45710/bd8f1f66-890d-ade0-8ccd-f750f8d3fd63.png)
1. 左上の `+` (`Add New Configuration` ) をクリックして `Python` を選択
1. 必要な値を入力する
    - Name: 何をするのかわかる適当な値 ここでは `flask-tutorial-blog`
    - Module name: `flask`
    - Parameters: `run`
    - Environment Variables: `FLASK_ENV=development;FLASK_APP=flaskr`
    - Python Interpreter: 適当なPython実行系。このソースコードでは `venv` を使っているので、そちらを選択
    - Working directory: このソースコードのトップディレクトリをフルパスで指定 <br /> ![スクリーンショット 2022-04-05 19.28.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45710/0e9cabe6-f7b9-2998-ad20-8cadb55d4617.png)
1. OKを押す
1. 右上のプルダウンで `flask-tutorial-blog` を選択し、右隣の▷ボタンを押す
1. コンソールに起動ログが出たら成功

# 何をしたのか
Flaskアプリケーションの起動に必要なコマンドと環境変数を、PyCharmの起動構成に設定しています。

Flask Tutorialの [Run The Application](https://flask.palletsprojects.com/en/2.1.x/tutorial/factory/) の通りです。

`Remember, you should still be in the top-level flask-tutorial directory, not the flaskr package.` とあるので、`Working directory: このソースコードがあるトップディレクトリ` としました。

Flask Tutorialの下記の部分をもとに、
Environment Variables:は `FLASK_APP=flaskr; FLASK_ENV=development` としました。複数なので `;` で区切っています

```
$ export FLASK_APP=flaskr
$ export FLASK_ENV=development
```
Module nameとParametersは下記から来ています。
```
$ flask run
```

起動コマンドがわかれば簡単でした。