OmniAICreator/Qiita-1.07M huggingface dataset:
WSL2(Ubuntu)にDocker及びdocker-compose環境を構築する

# はじめに
先日VSCode×Dockerの開発環境構築の記事を投稿しました。

https://qiita.com/kotattsu3/items/476a207992fd575401e3

こちらの記事でWSLにDocker環境を構築する部分の過程を記事引用で省略したのですが、引用した記事で使っていたDocker及びdocker-composeのバージョンが古かったため、自分で最新バージョンの環境構築記事を書こうと思いました。

https://footloose-engineer.com/blog/2022/05/02/wsl2-ubuntu-docker-compose-setup/

# Dockerのインストール
以下の公式ドキュメントを参考にしています。

https://docs.docker.com/engine/install/ubuntu/#set-up-the-repository

### aptパッケージの更新
~~~bash
$ sudo apt-get update
~~~
### aptパッケージのインストール
~~~bash
$ sudo apt-get install ca-certificates curl gnupg lsb-release
~~~
### Docker の公式 GPG 鍵を追加
~~~bash
$ sudo mkdir -m 0755 -p /etc/apt/keyrings
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
~~~
### 安定版（stable）リポジトリをセットアップ
~~~bash
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
~~~
### Docker Engine インストール
~~~bash
$ sudo apt-get update
$ sudo apt-get -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
~~~
### Dockerにユーザを追加
~~~bash
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
~~~
### 再起動して確認
~~~bash
$ exit
~~~
Ubuntuを起動する。
~~~bash
$ id
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/e2e79f3f-228a-4482-fc2f-f86a6f7636ba.png)
999(docker)が追加されていますね。

# docker-composeのインストール
以下の公式ドキュメントを参考にしています。

https://docs.docker.com/compose/install/linux/

### インストール
~~~bash
$ DOCKER_CONFIG=${DOCKER_CONFIG:-$HOME/.docker}
$ mkdir -p $DOCKER_CONFIG/cli-plugins
$ curl -SL https://github.com/docker/compose/releases/download/v2.16.0/docker-compose-linux-x86_64 -o $DOCKER_CONFIG/cli-plugins/docker-compose
~~~
### 実行権限の付与
~~~bash
$ chmod +x $DOCKER_CONFIG/cli-plugins/docker-compose
~~~
### バージョンの確認
~~~bash
$ docker compose --version
~~~
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/bfbddd54-d08c-2ccc-fe5a-94b31b315a78.png)
**※最新バージョンでは"docker-compose"ではなく。"docker compose"コマンドになっているので注意！**
以上でDockerの環境構築は終わりです。

# 終わりに
古いバージョンのdocker-composeコマンドに既に慣れてしまったのでdocker composeコマンド使いたくないんですよね…
大きな違いがなければ古いバージョンのままでも良さそうなのですがどうなのでしょうか…
Express.jsでNext()に引数を渡したい

# こういうことがしたい
ミドルウエアにトークンを渡して検証を行い、
検証して出てきたuidを次のメインの処理に渡したい ←ここでnext()にuidを渡したい

```js
app.get('/', verifytoken, (req, res) => {
  // uidをもとにdbからデータを取得する
})

function verifyToken(req, res, next){
  // tokenの検証をする
  // tokenをデコードしてuidを取得する
  next(uid) // nextに引数を持たせて次の処理にuidを渡したい
}
```

# どうすれば渡せるか
`res.locals`に単一のリクエスト-レスポンスサイクル中だけ変数を保持することができる
他のリクエストから呼ぶことはできない

```js
app.get('/', verifyToken, (req, res) => {
  const uid = res.locals.uid // uidを渡すことができる
  // uidを利用した処理...
})

function verifyToken(req, res){
  // tokenの検証をする
  // uidの取得をする
  res.locals.uid = uid // 単一のリクエスト-レスポンスサイクルのみで保持される
}
```

# 参考文献
[Express公式サイト](https://expressjs.com/ja/api.html#res.locals)
フラックスコマンドラインを使用して流入DNから列を削除する

間違ったデータ型 (float ではなく int) を使用して誤ってデータを挿入したため、流入時系列の列を削除する方法はありますか。または、代わりにデータのタイプを変更します？

残念ながら、これまでのところ、Influx測定から「列」(つまり、タグまたはフィールド) を削除する方法はありません。そのための機能リクエストは次のとおりですが、ETA はまだありません。

3つの回避策:

1. SELECT INTO を使用して、望ましくない「列」を除外して、望ましいデータを別の測定値にコピーします。例えば：

SELECT desirableTag1, desirableTag2, desirableField1, desirableField2 INTO new_measurement FROM measurement

2. CAST 操作を使用して、float から int に「データ型を変更」します。例えば：

SELECT desirableTag1, desirableTag2, desirableField1, desirableField2, undesiredableTag3::integer, undesiredableField3::integer INTO new_measurement FROM measurement

3. insert ステートメントを使用してデータを「更新」します。これにより、同じタイムスタンプ、同じタグ、同じフィールド キーでデータが上書きされます。更新したい「列」を除いて、他のすべてのものを同じに保ちます。データを整数データ型にするには、数値の末尾に i を付けることを忘れないでください。例: 42i。例えば：

insert measurement,desirableTag1=v1 desirableField1=fv1,desirableField2=fv2,undesirableField1=someValueA-i 1505799797664800000
insert measurement,desirableTag1=v21 desirableField1=fv21,desirableField2=fv22,undesirableField1=someValueB-i 1505799797664800000
定積分 2*x*exp(x)「2023室蘭工業大学 問１」をsympyでやってみた。

sympyのグラフがでます。

オリジナル(公式サイト)
問1

https://muroran-it.ac.jp/uploads/sites/6/2023/02/sugakuR5.pdf#page=2

[解答例]
https://muroran-it.ac.jp/uploads/sites/6/2023/02/sugakuR5.pdf#page=4

https://muroran-it.ac.jp/entrance/admission/exam/data_ad_d/past_eq/

問１

https://kamelink.com/blog/2023/03/15/15-5-23-murorankodai-1/


上の問1と同じです。大学入試数学問題集成＞テキスト

https://mathexamtest.web.fc2.com/2023/202310007/2023100070100mj.html

# sympyで
```python
from sympy import *
x=Symbol('x',real=True)
f=2*x*exp(x)
f2=f.subs({x:2})
l=(diff(f).subs({x:2})*(x-2)+f2).expand()
print("#(1)",l)
print("#(2)",integrate(f,x))
xk=solve(l,x)[0]
print("#(3)",integrate(f,(x,0,2))-Rational(1,2)*(2-xk)*f2)
plot(f,l)
plot(f,l,(x,0,2))
#(1) 6*x*exp(2) - 8*exp(2)
#(2) (2*x - 2)*exp(x)
#(3) 2 + 2*exp(2)/3
```
plotコマンドは、縦横比？異なります。

![1png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/faa3f909-0e91-26c0-cc25-3cf6b4086749.png)

拡大図

![2png.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/693d167f-5cdd-42dc-3c68-02139710e0c5.png)
デイトラ「Web制作コース」　受講内容をアウトプット 18～19日目

学んだことをアウトプットしています。完全に自己満足ですので悪しからず。
以下の点を確実にアウトプット
①何で学んでるか
②日々の学習内容
③学びのポイント
④制作物
⑤+αで参考にした記事
⑥+αでやってみたこと

①デイトラ「Web制作コース初級編」　自分のポートフォリオサイトを作る（ブラッシュアップ編）
②自分のポートフォリオサイトの作成
③
　・画像ファイルを圧縮化（Windows編）　TinyPNGサイト利用
　　　⇒https://tinypng.com/
　・Googleフォームのパラメータをオリジナルフォームのactionとinputに埋め込むやり方
　　　⇒https://shogo-log.com/google-form-ajax/
　　　　※ここは少し飛ばして、進む。

　・代表的なギャラリーサイトをブックマーク
　・WEBﾃﾞｻﾞｲﾝの基本
　　⇒色見本ｻｲﾄﾌﾞｯｸﾏｰｸ
　　⇒CSS見出しﾃﾞｻﾞｲﾝ参考ｻｲﾄﾌﾞｯｸﾏｰｸ
　　⇒ﾌｫﾝﾄﾒｰｶｰｻｲﾄﾌﾞｯｸﾏｰｸ
　　⇒画像加工ﾂｰﾙｻｲﾄﾌﾞｯｸﾏｰｸ
　　
④ポートフォリオ
⑤なし
⑥なし
NVIDIAドライバコンテナでリスタート時のエラーを回避する

[NVIDIAドライバコンテナ](https://catalog.ngc.nvidia.com/orgs/nvidia/containers/driver "NVIDIA GPU Driver") を使ってみたが、コンテナのrestartとかホストOSの再起動時にエラーになってしまう。

[ドライバコンテナのドキュメント](https://docs.nvidia.com/datacenter/cloud-native/driver-containers/overview.html)にあるように`--restart=unless-stopped`を指定して起動するとコンテナの再起動の繰り返しになってしまう。

エラーログは以下のようなもの。
```text
ERROR: The file '/lib/modules/5.19.0-32-generic/kernel/drivers/video/nvidia.ko' already exists as part of this driver installation.


ERROR: Installation has failed.  Please see the file '/var/log/nvidia-installer.log' for details.  You may find suggestions on fixing installation problems in the README available on the Linux driver download page at www.nvidia.com.
```

使用している環境は
* ホストOS: Ubuntu 22.04
* コンテナイメージ: `nvcr.io/nvidia/driver:525.85.12-ubuntu22.04`

既にドライバ(nvidia.ko)があるとかでエラーになってるので、そのドライバをそのまま使ってくれればよさそうだが、ホストのカーネルを変えたりする場合もあるからそうもいかないのだろう。

で、ビルドしたものを再起動したときには消してあげなきゃいけなさそう。

ドライバコンテナをのぞくとそれらしい処理があるがこれがうまくいってなさそうで、以下のパッチをドライバコンテナに当てるととりあえず回避できる。
```patch
--- a/usr/local/bin/nvidia-driver
+++ b/usr/local/bin/nvidia-driver
@@ -395,7 +395,7 @@ _install_driver() {
 
     echo "Installing NVIDIA driver kernel modules..."
     cd /usr/src/nvidia-${DRIVER_VERSION}
-    rm -rf /lib/modules/${KERNEL_VERSION}/video
+    rm -rf /lib/modules/${KERNEL_VERSION}/kernel/drivers/video
 
     if [ "${ACCEPT_LICENSE}" = "yes" ]; then
         install_args+=("--accept-license")
```

※追記(2023/4/5)
コンテナイメージ `nvcr.io/nvidia/driver:525.105.17-ubuntu22.04` で修正が取り込まれたので、これ以降は回避策不要。
github actionsでshellからGITHUB_ENVを参照するときにハマった話

# やろうとしていること
GitHub Actionsで`GITHUB_ENV`に設定した値を。(`release/test`というブランチとする)
```workflow.yaml
run: |
    echo "REF_ENV=${GITHUB_REF#refs/heads/release/}" >> $GITHUB_ENV
    ./action.sh            # このshell内でREF_ENVを参照したい。
```
shellから参照したいが空になっている。
```action.sh
#!/usr/bin/env bash

TARGET="$REF_ENV"

echo $TARGET  # 何も入っていない
```
**※shell から `GITHUB_ENV`への登録ではないです。**

# 結論
**原因**は同じステップ内で実行していること。
### 修正方法
- 別ステップで`GITHUB_ENV`に設定する
- (今回の場合)shell内で`GITHUB_REF#refs/heads/release`を直接参照する

# 検証
### 別ステップで`GITHUB_ENV`に設定する
そもそもステップを分けることで`GITHUB_ENV`を参照できる。
```workflow.yaml
name: set env
run: echo "REF_ENV=${GITHUB_REF#refs/heads/release/}" >> $GITHUB_ENV

name: exec script
run: ./action.sh            
```
#### actionsの実行結果
exec scriptステップの結果です。しっかり入っている
```
Run ./action.sh 
env:
    REF_ENV: test
test
```

### shell内で`GITHUB_REF#refs/heads/release`を直接参照する
既存のワークフローへの追加作業でワークフローを書き換えたくなかったらこっちのほうがいいかも。。
```action.sh
#!/usr/bin/env bash

TARGET="${GITHUB_REF#refs/heads/release/}"

echo $TARGET  #
Notification Fakeを使って通知が送られたかどうかのテストを実装する

## 環境
Laravel9
PHP8
## やりたいこと
PHP UnitテストでメールやSMSなどの通知が送られているかをテストしたいことがあると思います。
今回はユーザー登録したユーザーにメールが送られているかをテストしてみます。

## やり方
[Notification Fake](https://readouble.com/laravel/9.x/ja/mocking.html#notification-fake)というやつを使います。
Notificationファサードのfakeメソッドを使用すると、通知が送られるのを防ぐことができます。


```SendMialTest.php

public function 会員通録したユーザーにメール通知が送られることを検証する()
{
    // fakeメソッド準備
    Notification::fake();
    // この段階では通知で送られていないことをアサートする
    Notification::assertNothingSent();
    
    // ユーザー登録用のサービスで登録処理を行う
    $request = ['name' => '田中たろう', 'email' => 'taro@example.com'];
    $user = (new CreateUserService())($requests);
    
    // 対象に通知が送られたことをアサート
    Notification::assertSentTo(
        $user,
        SendMail::class//　Notificationを実行するクラス
    );
    // 通知が一度だけ送られてたことをアサート
    Notification::assertTimesSent(
        1,
        SendMail::class
    );
}

```
以上です。
[Python] 型ヒント ～ヒントと言ったがあれは嘘だ！ハッハッハッ～

## Pytonの型ヒントについて
Pythonでは変数宣言時に型宣言をしなくても動作します。

古いPythonは変数の型を明示的に記載する術はなかったかと思いますが、Python3.5よりPythonにも変数の「型ヒント」というものがつけられるようになりました！

### 型ヒントの使い方
以下のような通常の変数宣言に対し、
```python: 通常の変数宣言
a = 100
```
Pythonの型ヒントは以下のようにつけられます。
```python: 型ヒント付き変数宣言
a: int = 100
```
変数名の後ろに```: 型```をつけるだけです！
簡単ですね！！！

### 型ヒントの問題点
Pythonでも型ヒントのおかげで、変数の型がわかるようになりました！
めでたしめでたし👏👏
と思えます。

ですが、世の中それほど甘くはないようです…。

以下をご覧ください。
```python: 問題のコード
a: int = "I'm an integer."
print(a, type(a))
# I'm an integer. <class 'str'>
```
上記のコードはエラーを吐かずに実行されます。
```a: int```とaをint型で型ヒントをつけたにもかかわらず、str型の値を代入できています。しんじられなーい…です。

同様に型ヒントをつけていても違う型の値が代入された瞬間に違う型になってしまいます。
```python: 問題のコード2
a: int = 100
b: str = "bbbbb"
print(a, type(a))
# 100 <class 'int'>
a = b
print(a, type(a))
# bbbbb <class 'str'>
```

## まとめ
* Pythonの型ヒントはその名の通り所詮<b>ヒント</b>でしかありません。
* 型ヒントと違う型が代入されてもエラーを吐いたり教えてくれたりはしません。
* 違う型が代入された場合は混乱のもとでしかない。
* 結局はコードを書く側がしっかりと型を意識しておく必要がある。

## <参考>型ヒント通りに代入されているかを確認したい(違う場合は教えてほしい)場合

<b>mypy</b>というコード上の型を性的解析してくれるライブラリを使って確認することができます。
以下のページを見れば雰囲気はわかるかと思います。
mypyについては検索すると多くの情報が出てくるので興味があれば検索してみてください。

[参考リンク](https://qiita.com/masa2223/items/75306a90ea5b66fc4a2a)
テスト自動化ツール「Autify」を使ってみた

 # はじめに
今回弊社で行っているテストを「Autify」というツールを用いて自動化してみました。この記事では使ってみた感想などを記載できればなと思っています。

 # Autifyって・・・？
ブラウザの操作を記録するだけで前回のテスト結果と今回のテスト結果を比較してくれます。これがノーコードなので非エンジニアであってもテスト可能です。そして、時間のかかるテストであればあるほど効果を発揮するそうです。

https://autify.com/ja

 # Autifyを導入して
下記2つのURLはネットで見つけてきた体験談です。やはり工数のかかるテストであればあるほど工数の削減の効果は絶大のようですね。確かに、実際に動かしてみて思ったことは実行ボタンを押したらユーザーがオペレーションをしなくてもテストが勝手に終了しているため、とても楽ですね。特に毎月同じ操作をするテストは一度シナリオを作成すれば定期実行もできるため何も操作をすることがなくなります。また、前回のテスト結果と今回のテスト結果が異なる場合、テストを終了するのではなくテスト実行後に人間が手動で許容するか否かを選択できます。そして、許容する場合、許容したほうを正と判断し次回以降のテストは許容したテスト結果と比較します。そのため、随時正と判断されるテスト結果と比較することでテスト結果を更新していきます。詳しくは以下参照してください。しかし、できないことなどもあるそうです。少し

 https://tech.andpad.co.jp/entry/2021/09/30/170000

 https://blog.studysapuri.jp/entry/2021/11/15/080000

  # さいごに
Autifyを操作してみて、便利な機能であることは確かです。テスト工程はUIの比較であるため、目視であっているかどうかを細かいところまで確認するのはとても大変な業務です。これを自動化して負担を相当軽減することができます。それに、正しいテスト結果をアップデートすることができるのもとても助かる機能ですね。ただ、できないこともまだあるため、これからの発展に期待です。このような自動化ツールが発展して業務の負担が減るのはとても良いですね。このような自動化ツールのおかげで、自分の仕事がなくならないように頑張らなくてはいけないですね。
Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「Azure Blob Storage」

Microsoft Learnを用いたMicrosoft Azure Administrator(AZ-104)の試験内容をまとめる投稿です。
この投稿ではMicrosoft Learnで学ぶ内容をできるだけ簡潔にまとめております。
Azureの勉強を一から始め、AZ-900取得後の資格としてAZ-104取得を目指している方の参考になれば幸いです。
※AZ-900の内容は本投稿では省略しております。再度復習したい方は下記をご参照ください。
[Azure Fundamentals(AZ-900)：試験合格に向けた学習内容のまとめ](https://qiita.com/fsd-jume/items/e4ec76959adb547ac5e8)

## 今回の学習内容
**◆「Azure Blob Storage」**
◇対応するMicrosoft Learn ラーニングパス
[AZ-104:Azure でのストレージの実装と管理](https://learn.microsoft.com/ja-jp/training/paths/az-104-manage-storage/)
◇対応するモジュール
[Azure Blob ストレージを実装する](https://learn.microsoft.com/ja-jp/training/modules/configure-blob-storage/2-implement)

※前回の投稿は下記から確認できます。
[Azure Administrator(AZ-104)：Azure でのストレージの実装と管理「ストレージエンドポイントのセキュリティ保護」](https://qiita.com/fsd-jume/items/61fd26e2e0115c712f76)

## Azure Blob Storage
### Azure Blob Storage
・非構造化データをクラウド内にオブジェクト/BLOBとして格納
・BLOB(Binary Large Object)：データベースで用いられるデータ型の一つ
・BLOBストレージの別名
　-オブジェクトストレージ
　-コンテナストレージ
・格納可能データ
　-任意の種類のテキスト/バイナリデータ
　-例：テキストドキュメント/画像/ビデオファイル/アプリケーションインストーラなど

### データの格納/管理を行う3つのリソース
**◆Azureストレージアカウント**
・データ用の一意の名前空間をAzure内に用意
⇒格納されるすべてのオブジェクトに一意のアカウント名を含むアドレスが割り当てられる

**◆Azureストレージアカウントのコンテナ**
・コンテナリソースを使用してBLOBのセットをグループ化
⇒BLOBはコンテナリソースに格納されている必要あり

**◆コンテナ内のBLOB**
・次の3種類をサポート
　-ブロックBLOB：ほとんどのシナリオで使用(テキストやバイナリデータの格納など)
　-追加BLOB：追加操作でデータ量が増えるものに最適(VMデータのログ記録など)
　-ページBLOB：読み取り/書き込みが頻繁な場合に最適(VMのOSディスクやデータディスクなど)

### Azure Blob Storage実装時の考慮事項
**◆ブラウザのアップロードを検討**
・画像/ドキュメントをブラウザに直接提供可能

**◆分散アクセスを検討**
・インストールプロセス中などに分散アクセス用のファイルを格納可能

**◆データのストリーミングを検討**
・ビデオ/オーディオをストリーミング可能

**◆アーカイブと回復を検討**
・下記のためのデータの格納に最適
　-バックアップと復元
　-DR
　-アーカイブ

**◆アプリケーションによるアクセスを検討**
・Blob Storageから監視データやログを収集可能
⇒オンプレミス/Azureホステッドサービスを分析可能

## 次の学習内容
**◆BLOBコンテナ**

https://qiita.com/fsd-jume/items/51fbb65ce4076c2caf7e

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
【Vuetify】終日のチェックボックスの状態を保持させる


### 概要
SPAのカレンダーシステムを作成中に、終日の予定を設定する際に、チェックボックスの状態が保持されない問題に直面したため、その解決方法を調査し、実装した内容をまとめたものです。

### 使っている環境
フロント: Vue.js / Vuetify
バックエンド: Ruby on Rails (API)
データベース: PostgreSQL
状態管理: Vuex
非同期処理: axios

### 留意
他にも処理があり説明を省いているので、記載するコードのコピペでは、動きません。下記画像は終日チェックボックス.

![スクリーンショット 2023-03-01 18.10.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468139/e661933e-0dbd-c23e-cf33-dc0f534f9f3b.png)
![スクリーンショット 2023-03-01 18.10.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/468139/34bb914b-5706-956c-ac5d-c5e2eaf443c7.png)


### 修正前のコード
~~~~
<template>
 <v-checkbox
    :value="value"
    @change="$emit('input', $event)"
    :label="label"
  ></v-checkbox>
</template>

<script>
export default {
  name: 'AlldayCheck',
  props: ['value', 'label']
};
</script>
~~~~
v-modelディレクティブを使用しておらず、valueと@changeのプロパティを使用してチェックボックスの状態を管理していた。

### 修正後のコード
~~~~
<template>
  <v-checkbox v-model="isChecked" :label="label" />
</template>

<script>
export default {
  name: 'AlldayCheck',
  props: ['value', 'label'],
  computed: {
    isChecked: {
      get() {
        return this.value;
      },
      set(value) {
        this.$emit('input', value);
      },
    },
  },
};
</script>
~~~~
・v-modelディレクティブを使用して、isChecked変数を定義し、valueの状態を反映するように設定した。

・getアクセサーでvalueの現在の状態を取得し、setアクセサーでvalueが変更されたときに親コンポーネントにinputイベントを発行するようにした。
より簡潔にチェックボックスの状態を管理できるようにした。

### 参考資料
https://johobase.com/vue-js-v-model-directive/
minikubeをsystemd経由で起動する

[openshift（k8s）とminikubeの違いでいろいろハマった話](https://qiita.com/tomoyanp/items/6bc1036a877342f712e7)の続きです。
minikubeをsystemdに追加し、OS起動時に自動で起動されるようにしました。 

### 環境
　・Amazon EC2
　・Ubuntu 22.04 LTS

### serviceファイル作成
```/etc/systemd/system/minikube.service
[Unit]
Description=Minikube Cluster
After=containerd.service docker.service

[Service]
Type=oneshot
ExecStart=/usr/local/bin/minikube start
RemainAfterExit=true
ExecStop=/usr/local/bin/minikube stop
StandardOutput=journal
User=minikube実行ユーザ
Group=docker

[Install]
WantedBy=multi-user.target
```

ポイント1)
```
After=containerd.service docker.service
```
containerd, dockerの起動後に起動されるようにしています

ポイント2)
```
Type=oneshot
RemainAfterExit=true
```
Type=oneshotとすることでExecStartで実行されたコマンドが正常終了することでユニットが開始されたと判定されます。
デフォルトのType=simpleだと、ExecStartを実行したタイミングでユニットが開始されたと判定されてしまうそうです。
また、RemainAfterExit=trueとすることでminikubeコマンドが返ってきてプロセスが終了してしまっても、Serviceをアクティブとみなす設定となります。

### 設定反映
```
sudo systemctl daemon-reload
sudo systemctl enable minikube.service
sudo systemctl start minikube.service
```

### 起動確認
```
$ minikube status

type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured
```

```
$ sudo systemctl status minikube.service

● minikube.service - Minikube Cluster
     Loaded: loaded (/etc/systemd/system/minikube.service; enabled; vendor preset: enabled)
     Active: active (exited) since Wed 2023-03-01 18:22:26 JST; 14min ago
    Process: 1436 ExecStart=/usr/local/bin/minikube start (code=exited, status=0/SUCCESS)
   Main PID: 1436 (code=exited, status=0/SUCCESS)
        CPU: 4.205s

Mar 01 18:21:14 xxx bash[1437]: * Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
Mar 01 18:22:14 xxx bash[1437]: * Configuring bridge CNI (Container Networking Interface) ...
Mar 01 18:22:15 xxx bash[1437]: * Verifying Kubernetes components...
Mar 01 18:22:15 xxx bash[1437]:   - Using image gcr.io/k8s-minikube/storage-provisioner:v5
Mar 01 18:22:21 xxx bash[1437]: * Enabled addons: storage-provisioner, default-storageclass
Mar 01 18:22:26 xxx bash[1437]: * Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
```

再起動後に自動でminikubeが起動できていることを確認して終わりです。
これで夜間はEC2を止めて、朝に起動させるという運用が可能になりました。
Kotlinでの型チェックとキャスト

## Kotlinの型システムの概要
Kotlinは、Javaと同様に静的型付け言語です。しかし、Kotlinの型システムはJavaよりも豊富で、より厳密に型を扱うことができます。

## 型チェックとは何か？
型チェックとは、ある変数や式が期待される型を持っているかどうかを確認することです。Kotlinでは、is演算子を使用して型チェックを行うことができます。

## 型チェックの方法
### is演算子
is演算子は、ある変数が特定の型に属しているかどうかをチェックするために使用されます。

```kotlin:kotlin
    if (obj is String) {
       // objはString型であることが保証される
    }
```
### !is演算子
!is演算子は、ある変数が特定の型に属していないかどうかをチェックするために使用されます。


```kotlin:kotlin
    if (obj !is String) {
       // objはString型ではないことが保証される
    }
```
## 安全なキャストと非安全なキャストの違い
Kotlinでは、**安全なキャスト**と**非安全なキャスト**の2種類があります。

**安全なキャスト（as?演算子）** は、キャストが失敗した場合にnullを返します。これにより、nullチェックを省略することができます。

**非安全なキャスト（as演算子）** は、キャストが失敗した場合にClassCastExceptionがスローされます。

### 安全なキャストの方法
### as?演算子
**as?演算子**は、安全なキャストを行うために使用されます。

```kotlin:Kotlin
    val str: String? = obj as? String
```
### エルビス演算子
エルビス演算子は、null合体演算子とも呼ばれ、安全なキャストとnullチェックを同時に行うためにも使用されます。

```kotlin:kotlin
    val str: String = obj as? String ?: "default"
```
### 非安全なキャストの方法
### as演算子

**as演算子** は、非安全なキャストを行うために使用されます。この演算子は、キャストが失敗した場合にClassCastExceptionをスローします。

```kotlin:kotlin
    val str: String = obj as String
```
非安全なキャストは、キャストが失敗する可能性があるため、常にtry-catchブロックで囲む必要があります。

```kotlin:kotlin
    try {
        val str: String = obj as String
    } catch (e: ClassCastException) {
        // キャストが失敗した場合の処理
    }
```

## スマートキャスト
Kotlinは、**スマートキャスト**と呼ばれる機能を提供しています。これにより、**is演算子を使用して変数の型をチェックし、その後にその変数を直接キャストすることができます。**

```kotlin:kotlin
    if (obj is String) {
        val str: String = obj // スマートキャストが有効になる
    }
```
Kotlinコンパイラは、is演算子がtrueであることを検出すると、**その後のコードブロックで変数の型を自動的に推論します。**
これにより、コードの読みやすさが向上し、冗長なキャストを避けることができます。

### 型パラメーターの型チェックとキャスト
Kotlinのジェネリクスを使用して、クラスや関数を型パラメーター化することができます。型パラメーターの型をチェックするには、is演算子を使用することができます。

```kotlin:kotlin
    fun <T> example(obj: T) {
        if (obj is List<*>) {
            val list: List<Any?> = obj
        }
    }
```
上記の例では、List型の型パラメーターが不明なため、List<*>として扱われます。
is演算子でチェックすることで、**変数がList型であることを保証**し、List<Any?>にキャストすることができます。

## まとめ
普段から使用している型チェックやキャストですがスマートキャストなどをうまく活用すればもっと読みやすいコードが書けそうだなと思いました。

Kotlin安全なコードを書くために言語的に支援する機能が数多くあるので好きです。もっと使いこなせるようにしないとなあ！

ではまった！！
Go言語で説明するテストカバレッジについて

Go言語において、テストカバレッジはテストスイートがプログラムのどの程度をカバーしているかを測定するためのツールです。
テストカバレッジは、テストがコードのどの範囲に到達したかを定量化し、コードの品質と安全性を向上させるために使用されます。
ようは、テスト対象のコードについて、テストを実施した割合です。

具体的には、テストカバレッジは以下の2つのメトリックで測定されます。
- 行カバレッジ: テストスイートがプログラムの各行をどの程度実行したかを示すパーセンテージです。
- 分岐カバレッジ: プログラム内の各条件分岐をどの程度テストしたかを示すパーセンテージです。

例えば、以下のようなコードがある場合を考えます。

```go
func add(a, b int) int {
    if a > 0 && b > 0 {
        return a + b
    }
    return 0
}
```
この場合、行カバレッジが100％になるようなテストケースは次のようになります。

```go
func TestAdd(t *testing.T) {
    if add(2, 2) != 4 {
        t.Errorf("add(2, 2) should be 4")
    }
    if add(0, 1) != 0 {
        t.Errorf("add(0, 1) should be 0")
    }
    if add(-1, 1) != 0 {
        t.Errorf("add(-1, 1) should be 0")
    }
}
```
これらのテストケースを実行すると、行カバレッジが100％になります。

テストカバレッジを測定することにより、テストスイートがカバーしていないコードの範囲を特定し、それに応じたテストを追加することができます。これにより、コードの品質と安全性を向上させることができます。

### テスト方法

Go言語におけるテストカバレッジの測定方法は、標準ライブラリで提供されている `go test` コマンドを使用して行います。
具体的には、以下のコマンドを実行します。
```bash
go test -cover ./...
```
このコマンドは、カレントディレクトリおよびサブディレクトリ内のすべてのパッケージのテストを実行し、カバレッジレポートを出力します。

レポートには、各関数の行カバレッジおよび分岐カバレッジのパーセンテージが表示されます。
また、どの行が実行されたかどうか、どの分岐がテストされたかどうかを示すカバレッジプロファイルが生成されます。

また、カバレッジレポートをHTML形式で出力することもできます。
以下のコマンドを実行すると、`coverage.html` という名前の`HTMLファイル`が生成されます。

```bash
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
```
このHTMLレポートには、視覚的にカバレッジレポートを確認できるツールが含まれており、どの部分がカバーされているかどうかをより簡単に理解できます。
英語資料をわかりやすくする英文のコツ Google Technical Writing

# 見出しを読んでください。ノウハウがわかります。

[GoogleのTechnical Writing資料](https://developers.google.com/tech-writing/overview)を読んでみました。個人的にグッときたコツを、英文の書き方に関わるものにフォーカスしてまとめてみました。
※ぼちぼち更新していきます。


## [There文はprovideにしよう。](https://developers.google.com/tech-writing/one/clear-sentences)
There文は主語が不明瞭です。providesで置き換えるのが手っ取り早いです。使っている名詞を動詞にできないか考えるのもよい作戦だと思います。

❌
**There is no** creator stack for the main thread.

⭕️
The main thread does **not provide** a creator stack.



## [this, thatの後には名詞を付けよう。](https://developers.google.com/tech-writing/one/words)
指示語がどこを指しているのか明確である方が読みやすいです。ThisやThatは使う場面が多いので、wordyにならない範囲で名詞を付け足しましょう。

❌
Running the process configures permissions and generates a user ID. **This** lets users authenticate to the app.

⭕️
Running the process configures permissions and generates a user ID. **This user ID** lets users authenticate to the app.




## [SV形で書こう。受動態は避けよう。](https://developers.google.com/tech-writing/one/active-voice)
読み手は主語を考える必要がなくなるため、読むスピードが上がります。二つの文の違いは[この動画](https://youtu.be/nG6DhoFt938)でよく表現されています。読み手に考えさせるのをやめましょう。箇条書きにするときも混ぜない方がよいようです。

❌
Only one experiment per layer **is selected by the Frombus system**.

⭕️
**The Frombus system selects** only one experiment per layer.




## [意味の狭い動詞を使おう。](https://developers.google.com/tech-writing/one/clear-sentences)
be動詞、happen、occurに逃げないでください。動詞は英語の核です。意味の狭い動詞、意味の強い動詞を使って文章を作りましょう。[codic](https://codic.jp/)が助けになるかもしれません。

❌
Compiler errors **occur** when you **leave off** a semicolon at the end of a statement.

⭕️
Compilers **issue** errors when you **omit** a semicolon at the end of a statement.




## [thatとwhichを使い分けよう。](https://developers.google.com/tech-writing/one/short-sentences#distinguish_that_from_which)
説明しないと意味が通らない場合はthatを使いましょう。
情報を付け加える（なくてもよい）場合はwhichを使いましょう。カンマを直前につけるのを忘れずに。

❌
Python is an interpreted language, **which** Guido van Rossum invented.

⭕️
Fortran is perfect for mathematical calculations **that** don't involve linear algebra.




## [表には導入の文章を書こう。](https://developers.google.com/tech-writing/one/short-sentences#distinguish_that_from_which)
情報の羅列に文脈を与えましょう。followingがキーワードになります。文の終わりはコロンで閉じます。

⭕️
**The following table** summarizes our product's features against our key competitors' features:





## [1段落の目安は5文。What, Why, Howの順で書こう。](https://developers.google.com/tech-writing/one/paragraphs)
読み手に何を伝えたいのか。読み手はなぜこの情報が必要なのか。読み手がこの情報をどう使えるのか。を1つのパラグラフに5文ほどでまとめましょう。

⭕️
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/230192/99bf9aa1-b41d-463a-4543-aa4667973631.png)




# Source

https://developers.google.com/tech-writing/overview

https://qiita.com/yasuoyasuo/items/c43783316a4d141a140f

# 背景と後書き

一人で書いたプログラムをpythonに馴染みのない人に使ってもらう。その結果、チーム内のスプレッドシート業務を効率化する。というのがここ最近の私の目標です。

ただでさえ取っつきにくいと思うので心理的な壁をなくしたいのですが、英語で仕事をしているチームメンバーがどういう形で書いたら読みやすいのかわからない。。というのがこの記事を書いた動機でした。

このGoogleの資料は英語の教材としてもよいのではと思えるものでした！全体を通してSV形が徹底されていたので、「そうやって簡単に言えるんだ」と思える文章の発見がありました。読んでいて楽しかったです。
next.jsの静的ファイルの配信

このエラーが表示された時の対処法
```
cannot find module '../public' or its corresponding type declarations.
```

Next.js は、ルートディレクトリの public フォルダ下で、画像などの静的ファイルを配信できます。public 内のファイルは、ベース URL(/)から始まるコードで参照できます。
例えば、 public/me.png に画像を追加した場合、次のコードで画像にアクセスします:

```
import Image from 'next/image'

function Avatar() {
  return <Image src="/me.png" alt="me" width="64" height="64" />
}

export default Avatar
```

> https://nextjs-ja-translation-docs.vercel.app/docs/basic-features/static-file-serving
【Tips】git pushできない事案発生 AccessToken

## git push時にエラーが発生し、pushできなくなった
いつもどおり、gitにpushをしようと進めていきましたが、
push時に見慣れないエラーが発生。

```
CA8775:toreka 01048656$ git push origin tr_record
Username for 'https://github.com': 名前
Password for 'https://名前@github.com': 
remote: Support for password authentication was removed on August 13, 2021.
remote: Please see https://docs.github.com/en/get-started/getting-started-with-git/about-remote-repositories#cloning-with-https-urls for information on currently recommended modes of authentication.
fatal: Authentication failed for 'https://github.com/名前/プロジェクト名.git/'
```

いつもとは違う文字列たち。。
パスワードが間違ってる??と思ったが、そもそも求められているパスワードが違うらしい。

調べてみると、どうやらアクセストークンが失効しているらしい。
なので、再発行すべく進めていく。

### メールの確認
そういえば、Githubからメールが届いていた気がしたので、
それをまず確認してみる。
それがこちら。
![スクリーンショット 2022-11-30 17.59.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/59651b56-a086-8e46-458b-232f60200e8e.png)

内容を見てみるとやはりアクセストークンが失効しているので、
必要なら再度発行するようにとのこと。
メールはちゃんと確認しないとだめですね。(すぐアーカイブしてしまった

### Githubから設定をする
解決方法は、`①トークン新規発行 → ② git push時のパスワードにトークンを使用`とのこと。
なのでやっていきます。

#### ①GithubからSetting画面に進む
Developer settings > Personal access tokens にアクセスし、
※このとき2種類出てくるかもですが、Betaじゃない方を選択
![スクリーンショット 2022-11-30 18.03.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/bc0e8d5c-0252-9f28-5b33-9758fd2eb0ea.png)

#### ②`Generate new token` を選択
必要項目を入力し進む。
今回僕はNote欄を`For my development Toreka`とし、
期限を`90日間`、権限は`repo`にだけチェックして進みました。
![スクリーンショット 2022-11-30 18.09.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/589286/eb4bdde0-09aa-5c91-fede-235b40815993.png)

#### ③パスワードが発行されるので忘れずにメモしておく。
`※同じパスワードは二度と発行されないようなので必ずメモをしておくようにしましょう。`

Github上の設定はこれでOKです。

### ターミナルでpushを実行してみる
それではターミナルに戻って、pushができるかやってみます。

先程発行したパスワードを入力していきます。
```
CA8775:toreka 01048656$ git push origin tr_record
Username for 'https://github.com': 名前
Password for 'https://名前@github.com': 
Enumerating objects: 13, done.
Counting objects: 100% (13/13), done.
Delta compression using up to 8 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (7/7), 965 bytes | 965.00 KiB/s, done.
Total 7 (delta 5), reused 0 (delta 0), pack-reused 0
remote: Resolving deltas: 100% (5/5), completed with 5 local objects.
To https://github.com/名前/プロジェクト名.git
   e717fc8..31ac265  tr_record -> tr_record
CA8775:toreka 01048656$ 
```

プッシュできましたね!
これで一旦OKのようです。

## まとめ
- アクセストークンは再発行できないので、必ず保存をすること。
- 定期的に起こる現象なので、メールが来ても焦らず上の手順を踏んで冷静に対処すること。

以上
日本語化の設定

Gem”kaminari”の導入をした際に日本語表記設定したのにされておらず、設定の方法を忘れてしまっていた為備忘として残します。

手順
1.日本語設定
2.日本語訳してくれるgem”rails-i18n”のインストール
3.日本語にしたい文字を追記するファイルを作成


# 1.日本語設定
```ruby:config/application.rb
# 日本語の言語設定を追記
    config.i18n.default_locale = :ja
```

# 2.Gemインストール
```ruby:Gemfile
gem 'rails-i18n'
```
追記後　**bundle install**  と **rails s**　を忘れずに！

# 3.ファイルを作成し、文字を追記
※今回はkaminariの設定となります。
```ruby:config/lacales/ja.yml
ja:
  views:
      pagination:
        first: '最初'
        last: '最後'
        previous: '前'
        next: '次'
        truncate: '...'
```
CSSで見出しの左右に＼斜線／を付ける

良く見出しに `＼ゆっくりしていってね／` みたいな飾りを付けることがあります。

ただ、これを文字でやると、角度が変えられないのでちょっと微妙です。  
またアクセシビリティ的にも文字で書かれていると、スクリーンリーダーで読み上げられてしまうので、あまりよろしくありません。

**CSSで解決してみましょう。**

```html
<h2>ゆっくりしていってね</h2>
```


```css
h2 {
  display: flex;
  justify-content: center;
  align-items: flex-end;
  line-height: 1;
  color: #f11f8d;
}

h2::before,h2::after {
  width: 1px;
  height: 28px;
  content: "";
  background-color: #f11f8d;
}

h2::before {
  margin-right: 0.5em;
  transform: rotate(-30deg);
}

h2::after {
  margin-left: 0.5em;
  transform: rotate(30deg);
}
```

JSBin  
https://output.jsbin.com/cixeyof  
[![](https://gyazo.com/fd73140841a9a425c99fb86aadab5300.png)](https://gyazo.com/fd73140841a9a425c99fb86aadab5300)  

意外に簡単ですね。
ブロック引数で渡ってきたhashを、キーを変数名にしてローカル変数に展開する

あんま見ない書き方だったのでメモがてら残しておく

```ruby
list = [{a: 1, b: 2}]

list.each do |args|
  args => {a:, b:}

  p a
  p b
end

# 実行結果
1
2                                                     
```
ubuntuにvagrantを入れてsnapshot

オンプレサーバに色々構築してたが１箇所トラブって全てがダメになった。
二度とそうなってほしくないので仮想化しスナップショットから容易に回復させる目的でvirtualbox+vagrantを利用する。

前提として下記記事の環境に構築していく
https://qiita.com/strawbeRinMilk/items/e19655e69f1f9d3ec2f7?utm_campaign=post_article&utm_medium=twitter&utm_source=twitter_share

### インストール
`sudo apt install virtualbox -y`
`sudo apt install vagrant -y`

Vagrantfileの作成
`vagrant init ubuntu/focal64`

起動してみる
`vagrant up`
sshで入ってみる
`ssh vagrant@localhost -p 2222`
これは弾かれる。どうやら秘密鍵を新しく生成してデフォルトでパスワード認証は弾く設定のよう。
`ssh -i .vagrant/machines/default/virtualbox/private_key vagrant@localhost -p 2222`
これで入れた。

### スナップショット
スナップショットを試すためにダミーのファイルを作成してみる。
`touch hoge`
```
$ ls
hoge
```

一旦ログアウト
`exit`
シャットダウン
`vagrant halt`
スナップショットを撮ってみる
`vagrant snapshot save testsnapshot1`
確認
```
$ vagrant snapshot list
==> default:
testsnapshot1
```

起動する
`vagrant up`

ダミーファイルを追加
```
$ ls
hoge
$ touch fuga
$ ls
fuga  hoge
```

`exit`
`vagrant halt`

これでtestsnapshot1とは違う状態になった。
fugaがない状態に復元してみる。

`vagrant snapshot restore testsnapshot1`

sshで入るときちんとfugaが消えていた。
```
$ ls
hoge
```

### セキュリティ設定
sshのPasswordAuthenticationはデフォルトでnoになっていた
PermitRootLoginは初期値なのでnoにする
ポートも変えてもいいかもしれない（今回は変えない）
ufwはsshをallowしてenableする

### 余談 rm -rf / 
せっかくなので禁断のコマンドを実行してみる
`sudo rm -rf / --no-preserve-root`

10秒くらいで終わった。意外とあっさり。
```
$ ls
-bash: /usr/bin/ls: No such file or directory
```
んー致命的。でも`cd /`はできた。なんで？

ホストに戻ったらこんな状況に。
```
$ exit
logout
Connection to localhost closed.
$ vagrant halt
A Vagrant environment or target machine is required to run this
command. Run `vagrant init` to create a new Vagrant environment. Or,
get an ID of a target machine from `vagrant global-status` to run
this command on. A final option is to change to a directory with a
Vagrantfile and to try again.
$ ls
```
なんとホストのVagrantfileが消えてる。
後から調べたらどうもvagrant側の/vagrant/Vagrantfileにマウントされていたらしい。そりゃ消えるわ。
リストアもできない。
`vagrant init` しなおして `vagrant up` したらsshポートが2200で立ち上がった。
さっきの絶対ゾンビになってる
余計なことしたとめちゃくちゃ後悔してる
ホストをrebootして`vagrant destroy default`
ディレクトリもrmして作り直した。
init ＆＆ up したらsshポート2222で新しいのが立ち上がった。
当然hogeやらfugaやらは消えている

### まとめ
破壊的な操作をする前に`vagrant halt`して`vagrant snapshot restore {{timestanp}}`とでもすれば切り戻せる環境が手に入った。ただホスト側がマウントされてるところを下手にいじると復元できないことも同時にわかった。過信しすぎずほどほどに利用してきたい。
Postmanを基本からまとめてみた【入門】

## サーバーとは？

- モニターのないPC(24時間365日稼働できるPC)

## HTTP通信とは？

- 見たいページのアドレスをRequestすることにより、該当のサーバーからResponseとして、ページの情報が戻ってくる通信のこと

※ HTTP通信とは、htmlのファイルをトランス

## HTTPS通信とは？

- Hyper Text Transfer Protocol Secureの略
- 暗号化した通信のこと

## REST API とは?

- REST APIは、REST（Representational State Transfer）の原則に基づいて設計されたAPIのこと。Webシステムを外部から利用するためのAPIであることから、REST APIはWeb APIの1つだと言える。
- REST APIでは、HTTPで定義するGET、POST、PUT、DELETEなどのリクエストでデータを操作する。

　※　API（Application Programming Interface）とは、ソフトウェア同士が互いに情報をやりとりするのに使用するインターフェースの仕様のこと。

## Postmanとは？
- PostmanはAPI開発のために使用されるツール。
- APIの任意のエンドポイントにHTTPリクエストを送り、レスポンスを受信することができる。
『バックエンドエンジニア』であれば、自分の作成したAPIが外部からアクセスできるかどうか確かめるために、『フロントエンドエンジニア』であればHTTPリクエストにおいてエラーが発生する際に、その原因を特定するために使うといった用途が考えられる。

公式サイト：[Postman](https://www.postman.com/)

## 使い方

①Create New WorkspaceにNameを入れ、Visibiltyを選択する

②New CollectionのOverviewを選択し、

## 参考サイト
[【Postman入門】RestAPIテストで必須なツールのPostmanの使い方を基礎からマスターしよう！](https://www.youtube.com/watch?v=Z6-jgPbiX1E)
[REST API （RESTful API）](https://www.infraexpert.com/study/sdn09.html)
[Postmanとは？API開発ツールのインストールの手順と使い方を初心者向けに説明！](https://ugo.tokyo/about-postman/)
[
【初心者】はじめてのPostman（ポストマン）入門。HTTP通信やREST APIの基礎を学び、APIデバッグ手法の基礎を学ぼう](https://www.youtube.com/watch?v=O8ZKsGpio7w)
'MODULE_NOT_FOUND' node.jsでnpm/nodemon startしたらエラーが出た【自分用】

## 環境など

https://zenn.dev/wkb/books/node-tutorial/viewer/todo_03

+ win10
+ vscode
+ node.js
+ express
+ http(これをインストールし忘れていた）

上記サイトを最後まで行ったため自分で、簡単なwebappを作成しようと環境を構築しているところエラーが出た。おそらく慣れるまでは、上記サイトを参考にするため、時間が空くとまた同じエラーを発生させそうなため、ここに記述しておく。


## errorMessage
```node.js:errorMessage
Error: Cannot find module 'http-errors'
Require stack:
- C:\node-workspase\8\kakeibo\app.js
- C:\node-workspase\8\kakeibo\bin\www
    at Module._resolveFilename (node:internal/modules/cjs/loader:1047:15)
    at Module._load (node:internal/modules/cjs/loader:893:27)
    at Module.require (node:internal/modules/cjs/loader:1113:19)
    at require (node:internal/modules/cjs/helpers:103:18)
    at Object.<anonymous> (C:\node-workspase\8\kakeibo\app.js:1:19)
    at Module._compile (node:internal/modules/cjs/loader:1226:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1280:10)
    at Module.load (node:internal/modules/cjs/loader:1089:32)
    at Module._load (node:internal/modules/cjs/loader:930:12)
    at Module.require (node:internal/modules/cjs/loader:1113:19) {
  code: 'MODULE_NOT_FOUND',
  requireStack: [
    'C:\\node-workspase\\8\\kakeibo\\app.js',
    'C:\\node-workspase\\8\\kakeibo\\bin\\www'
  ]
}

Node.js v18.14.0
```
`Error: Cannot find module 'http-errors'`、` code: 'MODULE_NOT_FOUND',`とある様に __http__ モジュールがインストールされていなかった。

単純な話であるが、サイトでは、それまでに`http`モジュールをインストールしていることもあり、見のがしていた。
## 解決法
``` node.js :cmd
npm install http
```
Gitを基本からまとめてみた【 SourceTreeを利用したGitの基本操作】

## Gitとは、バージョン管理とは
- フォルダ内のファイルの変更履歴を保存する
- いつ、誰が、どのファイルにどの箇所を、どういった目的で変更したか

## Gitを利用する方法
- コンソールで利用する
- クライアントソフトで利用する

[SourceTree](https://www.sourcetreeapp.com/)

## Gitの言葉の理解

- リポジトリ
○ Gitで管理されたフォルダ
○ .gitのフォルダが含まれている
○ 変更を常に監視している

- ステージ
○ 変更のあったファイルの中からコミットするためのファイルを選ぶ

- コミット
○ 変更にメッセージなどを添えて保存する
○ セーブポイント
○ コミット間はいつでも移動できる

## リポジトリの作成 
- Gitによってバージョン管理されるフォルダの設定
- SourceTreeにドラッグ・アンド・ドロップする
- .gitファイルが含まれている
- リポジトリの中の変更はUn committed changeとして検知される

#### Macの場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/ce66779d-8072-39f6-c238-9e0ab69a3dd4.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/06e5f3c0-05fb-989d-e711-9f2f6c0e041f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/47b1d79f-a3bb-5468-5aba-b530b235fb26.png)

## SourceTreeの基本的な見方

##### ①変更内容を確認する
「作業コピー」で、現在のプロジェクトの状況を確認

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/b3e3b3ae-f3de-e3fa-762e-1f7961ad2016.png)

プロジェクトの内容を変更して、SourceTreeに戻り「作業コピー」を見ると下図の赤枠の部分に変更されたファイルの一覧が表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/99b86f12-1ef8-8319-c460-64357426dccd.png)

下図のように、右側の部分で選択中のファイルの変更内容を見ることができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/4c800b1e-801b-2af7-3910-bebece0d4f75.png)

##### ②addする

ファイル名の左横の「チェックボックスにチェック」をいれるか、「hunkをステージへ移動」をクリックするだけでaddが完了する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/5a9d2ba1-b88c-48e2-de16-74b49ba0b1d9.png)

addされると先ほどのファイルは下図のように「indexにステージしたファイル」に移動する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/19d9602a-90b2-d4b6-4622-f1a6ca952385.png)

下図のようにaddしたり、反対にaddを取り消したり、というのも自由自在にできる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/0ecbc804-59c4-f236-3ef6-dde02a0c8d61.png)

②commitする

下図のフォームにコミットメッセージを入力する。コミットメッセージを入力したら、下部のコミットボタンをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/e572fb7e-6a0f-b192-dd98-34e1d0701ca3.png)

③pushする

コミットが完了したら、ツールバーのプッシュボタンを押す。すると下図のように画面がポップアップで表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/31dca726-2416-b6c5-4972-9f87b6ae98d2.png)

GitHubのリモートリポジトリと紐付けている方は下図のような画面が表示される。
masterのチェックボックスにチェックをいれ、『OK』を押す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/4633cd10-e4fc-2a32-ae68-2af6f181fc0f.png)

Macの場合、下図になりデザインが異なる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/939638/efa31522-4400-c1dc-5cbc-15191f853e71.png)



## 参考サイト
[gitの使い方 基礎知識 - SourceTreeを利用したGitの基本操作](https://www.youtube.com/watch?v=LyXS3BWJ244&t=481s)
[リポジトリの作成 - SourceTreeを利用したGitの基本操作](https://www.youtube.com/watch?v=gfMdeiTqrOM)
[Gitなんて怖くない！超初心者向け、SourceTreeの使い方はじめの一歩！](https://prog-8.com/blogs/how_to_use_sourcetree)
[Rails]新しいバージョンに切り替わらないときの対処案

Railsのバージョンを更新したのに、それを呼び出すことができなかった(古いバージョンのものが呼ばれてしまう)ので、私が実施した対処法を記します。
結論を先に申しますと、windowsの環境変数のPathにある`ruby`の箇所を新しいものに修正したら`Rails`も新しいものが呼べたよ、となります。

## 状況(流れ)
Windows11を使っています。rubyやrailsなどはすでにPCにインストールしてありました。
新しいバージョンが出ていたので新しくインストールしていきます。
gitを更新したらバージョンを確認、
rubyを更新したらバージョンを確認、
railsを更新したらバージョンを確認、
あれ？できてない？

```
$ rails -v
Rails 6.1.4.1
```

Rails 7.0.4を入れたのに。。。
違う方法で確認

```
$ gem list rails
*** LOCAL GEMS ***
rails (7.0.4)
rails-dom-testing (2.0.3)
rails-html-sanitizer (1.5.0)
```

こっちではできています。
とりあえず新たなバージョンを指定してrails newをしてみます。

```
$ rails _7.0.4_ new hello_app -O --skip-bundle
C:/ruby/Ruby30/lib/ruby/3.0.0/rubygems.rb:281:in `find_spec_for_exe': can't find
 gem railties (= 7.0.4) with executable rails (Gem::GemNotFoundException)
        from C:/ruby/Ruby30/lib/ruby/3.0.0/rubygems.rb:300:in `activate_bin_path'
        from C:/ruby/Ruby30/bin/rails:23:in `<main>'
```

できません。
先ほどrubyを更新して3.2.1になっています。それは`C:/ruby/Ruby32/`にあるはずなのですが、それも呼ばれていないようです。呼ばれているのは`C:/ruby/Ruby30/`になっています。
改めてrubyのバージョンを確認。

```
$ ruby -v
ruby 3.2.1
```

rubyは新しいバージョンになっている。。
嫌な予感の中、railsコマンドでバージョンを指定しなければどうなるか確認してみます。

```
$ rails new hello_app
.
.
.
```

動きましたが、Gemfileを確認するとrubyもrailsも古いバージョンのものでした。
ちょっと頭の整理をしてみます。
$ ruby -v
$ gem list rails
$ gem info -e rails
では新しくなっている。

$ rails -v
$ rails new hello_app
では古いまま。
つまり、プロンプトでrailsコマンドを使うと、古いものが呼ばれるのだと推測しました。
ということはコマンドプロンプトでコマンドを実行したときは何を呼ぶのかをどこかで定義しているはず！
……どこで定義しているか分からず。。
とりあえず環境変数を確認してみるもrailsの項目は見当たりませんでした。
ただ、rubyへのパスがいままでのバージョンアップの履歴に合わせて複数登録されていました。古いのは使わんし、修正しておこうと、古いのを削除しました。
なぜかこの修正でrailsの新しいバージョンが呼ばれるようになりました。

```
$ ruby -v
ruby 3.2.1

$ rails -v
Rails 7.0.4.2
```

`rails new`でも成功し、バージョンを指定した`rails _7.0.4_ new`でも成功しました。


## 疑問と未解決
何が原因だったのか、本当はどのように解決したらいいのかご存じの方はご教授いただければ幸いです。

今回はよくわからない現象が、よくわからないまま解決してしまいました。
私には未知なものが多すぎて手に負えないというのが現状です。
rubyはどこにインストールするのかを決めていますが、railsの場合はどこにインストールされているのかわかりません。
たぶんですが、下記のような場所にインストールされていると思っています。
旧: C:/ruby/Ruby30/bin/rails
新: C:/Users/○○○/.gem/ruby/3.2.0
なんか気持ち悪いですが、どうしてこうなったのかわからないままです。
JSのWebsocket Wsライブラリで全クライアントではなく、個別の人を指定して送信する方法

WebSocketによるクライアントごとに一意の識別子を割り当てて、その識別子を使って個別のクライアントにメッセージを送信する例を示します。ここでは、クライアントがWebSocketに接続すると、サーバー側でUUIDを生成して、そのUUIDをクライアントに送信しています。クライアントは、サーバーから受け取ったUUIDを使って、そのクライアントにメッセージを送信することができます。

サーバー側のコード（Node.js + wsライブラリを使用する場合）：

```javascript

const WebSocket = require('ws');
const { v4: uuidv4 } = require('uuid');

const wss = new WebSocket.Server({ port: 8080 });

const clients = new Map();

wss.on('connection', (ws) => {
  const uuid = uuidv4();
  clients.set(uuid, ws);
  ws.send(uuid); // クライアントにUUIDを送信する

  ws.on('message', (message) => {
    // クライアントからのメッセージを受信したときの処理
  });

  ws.on('close', () => {
    clients.delete(uuid);
  });
});

// 特定のクライアントにメッセージを送信する関数
function sendToClient(uuid, message) {
  const ws = clients.get(uuid);
  if (ws) {
    ws.send(message);
  }
}
```

クライアント側のコード（JavaScript + WebSocket APIを使用する場合）：

```javascript

const ws = new WebSocket('ws://example.com:8080');

let uuid;

ws.onopen = function() {
  // サーバーからUUIDを受信する
  ws.onmessage = function(event) {
    uuid = event.data;
  };
};

function sendMessageToServer(message) {
  // サーバーにメッセージを送信する
  ws.send(message);
}

function sendMessageToClient(targetUuid, message) {
  // 特定のクライアントにメッセージを送信する
  ws.send(JSON.stringify({
    target: targetUuid,
    message: message
  }));
}
```

上記の例では、サーバー側でclientsというMapを使って、UUIDとWebSocketインスタンスを紐づけています。また、sendToClient関数を定義して、UUIDを指定してメッセージを送信することができます。クライアント側では、UUIDを受信した後、sendMessageToServer関数でサーバーにメッセージを送信することができます。また、sendMessageToClient関数を使って、特定のクライアントにメッセージを送信することもできます。
初めてMacのターミナルを使う人が覚えるべきコマンド10選

ターミナルって難しいですよね。とりあえずこの１０選だけでも頑張って覚えましょう。

1. `pwd`  
現在のディレクトリを表示します。  

2. `ls`  
現在のディレクトリ内のファイルとディレクトリを一覧表示します。  

3. `cd`  
ディレクトリを変更します。例えば、`cd Documents`と入力すると、現在のディレクトリを`Documents`に変更します。  

4. `mkdir`  
新しいディレクトリを作成します。例えば、`mkdir mynewdirectory`と入力すると、`mynewdirectory`という名前のディレクトリが作成されます。  

5. `touch`  
新しいファイルを作成します。例えば、`touch myfile.txt`と入力すると、`myfile.txt`という名前のファイルが作成されます。  

6. `rm`  
ファイルを削除します。例えば、`rm myfile.txt`と入力すると、`myfile.txt`という名前のファイルが削除されます。  

7. `rmdir`  
ディレクトリを削除します。例えば、`rmdir mynewdirectory`と入力すると、`mynewdirectory`という名前のディレクトリが削除されます。  

8. `cp`  
ファイルをコピーします。例えば、`cp myfile.txt newfile.txt`と入力すると、`myfile.txt`という名前のファイルを`newfile.txt`という名前の新しいファイルにコピーします。  

9. `mv`  
ファイルを移動または名前を変更します。例えば、`mv myfile.txt newdirectory/myfile.txt`と入力すると、`myfile.txt`という名前のファイルを`newdirectory`という名前のディレクトリに移動します。  

10. `history`  
ターミナルで実行したコマンドの履歴を表示します。例えば、`history | tail`と入力すると、最後の10個のコマンドが表示されます。  

<br>
<br>
これらのコマンドは、Macのターミナルで基本的な操作を行うのに役立ちます。  

他にも多くのコマンドがありますが、これらを覚えておけば、初心者でもターミナルを使って作業を行うことができます。
デザインからプログラムを生成するLocofy.aiを使ってみたら感動した

## 今回やりたいこと：Next.jsをなるべくローコードで書きたい


2023年現在、社内向けのローコードツールは
たくさん普及してきたのですが、

ローコードで開発したものを
**一般に販売できるソフトウェアはまだまだ少ないです！**


今回はFigmaなどのデザインをそのまま
Next.JSなどのプログラムに変換してくれる
噂のソフトウェアLocofy.aiを
使ってみた感想をまとめていきます！




## 始め方

複雑な作業はなく、
FigmaにLocofyのプラグインをインストールするだけでした。

https://www.figma.com/community/plugin/1056467900248561542




## AIが要素をサジェストしてくれる

私が驚いたのは
デザインデータに対して、
想定される要素をLocofyのAIが提案してくれます。
これにより、10行ほどのプログラムが1クリックで終わります。

![Screen Shot 2023-02-21 at 17.08.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118665/a1117281-841f-90ec-8c42-699d61f29c40.png)


## プログラムが自動生成される

さらに、Next.jsと設定するだけで（React, Vueも対応しています）、
Locofy Builder上で
自動でデザインをプログラムに変換してくれます。

![Screen Shot 2023-02-21 at 17.16.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118665/2763633a-a5eb-8780-ed4e-ea80d55c4d2c.png)


さらにさらに、Vercelへのデプロイもすぐできる。

![Screen Shot 2023-02-21 at 17.17.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118665/a417f26e-e182-6181-c907-a22afa443eb3.png)




## 詰まって公式Slackに相談したら、5分でレスが返ってきた

Locofyのチームはシンガポールに拠点があるので、
返信がめちゃくちゃ早くてびっくりしました。

![Screen Shot 2023-03-01 at 16.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118665/6219c3b9-4650-d2f3-f083-70693120b485.png)



## Locofyの現状の課題

しかし、今回のプロダクトでLocofyを採用するのは一旦見送りました。

なぜかというと、

* MaterialUIのテーブルなどがサポートされていない
* Figmaをいじると、Locofy側の設定が全部消えることがある
* 人が書いたコードの方がシンプル

などの点からです。


ただ、個人開発やMVP開発には非常に可能性のあるサービスだと感じました。




Happy Hacking with Academix!


## AcademiXのご案内

AIを学ぶ人のための無料学習コミュニティ、AcademiXで私は活動しています！
半年で160人ほど集まっており、盛り上がっております。
ぜひぜひご参加ください〜！！

https://academix.jp/
マルチブート：grub2のos-proberが機能しないので、カスタムファイルを作って強制マルチブート

grub2のos-proberが機能しないので、grubのエントリを新しく作った。
grub-mkconfigで、os-proberが他のパーティションのOSを検出しないのである。

普通、`grub-mkconfig -o /boot/grub/grub.cfg`とすると、自動的にパーティションをスキャンしてブート可能なOSをgrubのエントリに登録してくれる。

# ダメ

 /etc/default/grubを弄ってみた。

`GRUB_DISABLE_OS_PROBER=false`
にしてもダメ。

`pacman -S os-prober`
でos-proberをインストールしてもダメ。

UbuntuでもArch linuxでも同じことが起こる。
archlinuxインストール時に、間違ってUEFIブート関係を弄ってしまったのが原因かな？

`os-prober`
として実行しても、何も出力されない。os-proberのバグかな。

# 対策

とにかく対策をと思ってgrubにカスタムのエントリが出てくるように、
次のファイルを作った。

```/boot/grub/custom.cfg

menuentry "ubuntu Linux" {
        set root='hd0,msdos1'
        linux /boot/vmlinuz root=UUID=4eac0df4-ab0c-4055-969f-ab73ea55ef4d quiet
        initrd /boot/initrd.img
}
```
やっぱり手動が一番だね。

# 解説

```
menuentry "ubuntu Linux" {   #  grubの選択画面で出てくるタイトル

        set root='hd0,msdos1'  #  0 : ディスクの1番目

             #  msdos1 : パーティション1番目

        linux /boot/vmlinuz root=UUID=4eac0df4-ab0c-4055-969f-ab73ea55ef4d quiet     # linux カーネルのロード

             # /boot/vmlinuz : デフォルトのカーネル指定

             # root=UUID=<hoge>: ブートパーティションのUUID

             # quiet : 起動時にずらずらメッセージを出さない


        initrd /boot/initrd.img  # initrd : 初期ramdiskのロード

             # /boot/initrd.img : デフォルトのinitrd.img 指定
}
```

# 追記・原因

他のOSを含むパーティションをマウントしてなければos-proberはサーチしませんでした。　マウントしたらos-proberはちゃんと他のosを検知したので、この記事は必要なくなりましたが、カスタムコンフィグレーションの書き方として残しておきます。
(リンクだけです)(途中です) 「恒等式？部分分数分解?」を調べています。

「恒等式一覧」のおすすめの日本語版を探しています。


# wikipedia
(例)
・Trinomials and cubic formulas

x^3+y^3+z^3-3xyz=(x+y+z)(x^2+y^2+z^2-xy-xz-yz)

https://en.wikipedia.org/wiki/Factorization#Recognizable_patterns

https://ja.wikipedia.org/wiki/%E5%9B%A0%E6%95%B0%E5%88%86%E8%A7%A3

# ????????????wolframで

https://www.wolfram.com/mathematica/new-in-10/inactive-objects/display-function-identities.html.en?footer=lang

https://www.wolfram.com/mathematica/new-in-10/inactive-objects/display-function-identities.html.ja?footer=lang

# 参考

https://www.google.com/search?q=%E9%83%A8%E5%88%86%E5%88%86%E6%95%B0%E5%88%86%E8%A7%A3+sympy&rlz=1CAUHAM_enJP1038JP1038&oq=%E9%83%A8%E5%88%86%E5%88%86%E6%95%B0%E5%88%86%E8%A7%A3+sympy&aqs=chrome..69i57j0i8i30j69i61.12723j0j7&sourceid=chrome&ie=UTF-8
「最新版」Capybaraのチートシートを作成してみた

ChatGPTを用いてCapybaraのチートシートを作成してみました
 <font color="red"><h4>**「重要」**</h4><font>

ChatGPTに作成してもらったものなので一部間違い等もあるかとは思いますが、ご了承ください
間違い等ございましたら、コメントいただけますと幸いです。

<br><br>

<h3>Capybaraのインストール</h3>
Gemfileに以下の行を追加して、Capybaraをインストールします。

```
gem 'capybara'
```
bundle installを実行して、Capybaraをインストールします。

<br>

<h3>設定</h3>
Railsプロジェクトのspec/rails_helper.rbまたはspec/spec_helper.rbで以下を設定します。

```
require 'capybara/rspec'

# テスト実行時にブラウザが表示されないようにする
Capybara.javascript_driver = :selenium_headless

RSpec.configure do |config|
  config.include Capybara::DSL
end

```

<h3>ページの操作</h3>

```
visit('/path') # 指定したパスに移動します。
click_link('Link Text') # 指定したリンクをクリックします。
fill_in('First Name', with: 'John') # 指定したフィールドにテキストを入力します。
choose('Option') # 指定したラジオボタンを選択します。
check('Option') # 指定したチェックボックスを選択します。
uncheck('Option') # 指定したチェックボックスを解除します。
attach_file('File Field', '/path/to/file') # 指定したファイルをアップロードします。
select('Option', from: 'Select Box') # 指定したセレクトボックスのオプションを選択します。
```

<h3>ページの検証</h3>

```
expect(page).to have_content('Text') # ページに指定したテキストが存在することを確認します。
expect(page).to have_selector('selector') # ページに指定したセレクタが存在することを確認します。
expect(page).to have_link('Link Text') # ページに指定したリンクが存在することを確認します。
expect(page).to have_button('Button Text') # ページに指定したボタンが存在することを確認します。
```

冒頭でも説明したよう、ChatGPTを用いて、作成したチートシートですので一部間違っている可能性もあります。ご了承ください

:::note info
記事の需要を把握するため「いいね」をつけていただけるとありがたいです
:::
LocalDate.of()

```java
public class SampleProject  {
    public static void main(String[] args) {
        LocalDate ld = LocalDate.of(1999,2,22);
        DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
        System.out.println(ld.format(f));
    }
}
```
```
1999年2月22日月曜日
```
MacOS VPN経由を特定のIPアドレスだけにしたいとき

VPNをつなぐと基本的にはすべての通信がVPN経由になってしまうので
当方的には、特定のIPへのアクセスのみをVPN経由にしたい

で、いつもどおり調べてみたらVPN接続をすると
/etc/ppp/ip-upシェルスクリプトファイルが呼び出されるんだとか

ということで、VPN先のローカルネットワークと、VPN先からしかIP制限で入れないサーバへのアクセスをppp0経由にすることにしてみた。



```
sudo vi /etc/ppp/ip-up
```

```sh:/etc/ppp/ip-up
#!/bin/sh

if [ "$1" = "ppp0" ]; then
  date > /tmp/upppp0
  /sbin/route add -net 192.168.xx.0/24 -interface ppp0
  /sbin/route add -net xxx.xxx.xxx.xxx -interface ppp0
fi
```

```
sudo chmod 744 /etc/ppp/ip-up
```

と、設定してVPN接続してみると、``date > /tmp/upppp0`` が動いて/tmp/upppp0ファイルが作られているので、
if文の中は通っている様子。
(シェルスクリプトなので、こういうデバッグもできるね)

traceroute xxx.xxx.xxx.xxxをしたら、１番目にVPN先のルータのIPになっており、実際にxxx.xxx.xxx.xxxの接続も大丈夫だった。

これで、普段の通信はVPNを経由しなくて済みそうです。



ps.
よくよく考えたら自宅はRTX1200導入してるから、
ルーターでVPNを常に張りっぱなしにして、ルーティング書けは行けそうだなぁ・・
今度余裕があるときやってみよう