OmniAICreator/Qiita-1.07M huggingface dataset:
AWS ECS用のデプロイツール ecspressoに入門してみた

# はじめに
ECS Fargateのデプロイ周りをやってみたので、導入や使い方の手順を備忘録として書きました。今更ながら私はECSを初めて触ったのですが、ECS周りの知識がない方は先にそちらの知識を入れることをおすすめします。

# 動機

ECS Fargateでサービスを運用していく際に、Terraformでリソース作成、GitHub Actionsでデプロイを行うとすると

- ECSタスク定義が2重管理になる
- Terraformで管理する他リソースとコンテナ上のアプリケーションの更新サイクルが異なる

などあり、Terraformの管理とコンテナデプロイを分けたい場合があります。

そこで、ecspressoというツールを使って、コンテナ周りの管理を行います。

# 導入手順

Macbook Pro M2へインストールする手順になります。

### ecspressoのインストール

- Homebrewでインストール

```
> brew install kayac/tap/ecspresso
```

- asdfでインストール

```
> asdf plugin add ecspresso
> asdf install ecspresso latest
> asdf global ecspresso latest
```

### AWS Credentialsの設定

ecspressoを使うには、`~/.aws/credentials` にAWS CLIのプロファイルを作成しておく必要があります。

```.aws/credentials
[<プロファイル名>]
aws_access_key_id = <IAMから取得>
aws_secret_access_key = <IAMから取得>
region = <リージョン>

[<プロファイル名>-long-term]
aws_access_key_id = <IAMから取得>
aws_secret_access_key = <IAMから取得>
region = <リージョン>
aws_mfa_device = MFA_DEVICE_ARN(IAMで確認)
```

```zsh
> export AWS_PROFILE=<プロファイル名>
```

# 使い方

### 既存のECSクラスタを読み込む

`config.yaml`に指定した名前でファイルが生成されます。

```zsh
> ecspresso init --config config.yaml --region ap-northeast-1 --cluster < ECSクラスタ名 > --service < ECSサービス名 >
```

### デプロイ

```zsh
> ecspresso deploy --config config.yaml
```

### その他TIPS

#### envfileから値を取得

`env`や`must_env`などのキーを使って環境変数から値を取ってくることができます。

```ecs-service-def.json
...
"loadBalancers": [
    {
      "containerName": "{{ must_env `CONTAINER_NAME` }}",
      ...
    }
  ],
...
```

実行
```
> ecspresso deploy --envfile <ENVファイル> --config <YAMLファイル>
```


#### tfstateから値を取得

設定ファイルにtfstateを置いているURLを追加します。

```config.yaml
plugins:
  - name: tfstate
    config:
      url: "s3://hogehoge/test/terraform.tfstate"
```

以下のように取得。
```ecs-service-def.json
...
"networkConfiguration": {
    "awsvpcConfiguration": {
      "assignPublicIp": "DISABLED",
      "securityGroups": [
        "{{ tfstate `AAAA.id` }}",
        "{{ tfstate `BBBB.id` }}",
        "{{ tfstate `CCCC.id` }}"
      ],
      "subnets": [
        "{{ tfstate `XXXX.id` }}",
        "{{ tfstate `YYYY.id` }}",
        "{{ tfstate `ZZZZ.id` }}"
      ]
    }
  },
...
```

# 参考

以下のリンクで詳細に書かれています。

https://adventar.org/calendars/5916

https://zenn.dev/fujiwara/books/ecspresso-handbook-v2
Rakuten Linkから発信すると非通知になる件

エンジニアの知識よりも、使い方ですかね。
RakutenMobileの回線を使っているのですが、あくまでもサブ回線（というか、本当にだめなのかを見てみたい）で、使っていませんでしたが、何気にRakuten Linkから「電話をかけると、通話料はタダですよ」を試してみたくなりました。

使ってみると、おや、非通知になるぞ、と。

インターネットで調べてみましたが、楽天回線のデータ通信を有効にしているし、アンテナも3本は立っているし、一向に非通知のままでした。

試していたうちにわかりました：
通話回線を「Rakuten」に固定しておけばよいです。そうしますと、Dual Simでデータ通信を他社回線にしても、かけた方の携帯で、きちんと楽天回線の番号で表示してくれます。インターネット上で「楽天回線のデータ通信を有効にする」とかではなくて、「楽天回線をメインの通話回線に固定する必要がある」とのことです。

うんん、要は電話のサブ回線にしたらダメだねと、いうことです。メイン回線と同じスマホにいれたら、非通知のままでかけるしかないです。切り替えしながら使えばいいじゃん、と言われるかもしれませんが、そんな面倒くさいことはしませんよね。

来月通話料が無料なのか楽しみです。
設定したグループはどこに表示される？


勘違いかもしれないけど、リストに予期せず付与されていたグループを削除したら、グループが表示されなくなったような...

しかし、グループのIDを直接使うと表示されますね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/19994bb1-8fa3-cadd-7533-1bc56bf55a0a.png)

見るところが違う？

とりあえず、なんでもいいから開いてみたら、001以下、作ったグループはあるなぁ。
しかし本当に使いにくし誤解を与えるUIだと思う。どうやっても好きにはなれん。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/adff5a81-9c12-d26b-f5d1-d7a5f1b0cd60.png)
【Zsh】シェルスクリプトでバージョンを確認するツール作ってみた

zshを使用して登録したツールバージョンを簡単に確認するスクリプトを作成したので紹介します。

## スクリプトの概要
このスクリプトは、登録したシステムツールのバージョンを表示する簡単な Zsh スクリプトです。
使用するツール名と対応するバージョンチェックコマンドを連想配列に格納し、for ループを使用してそれらを順に実行します。

https://github.com/KaitoMuraoka/show-tool-version

以下は、実行例です：

```zsh:実行例
% zsh ShowToolVersion.sh                            

==============================
🚀
CocoaPods version


pod --version :

1.13.0
==============================
🚀
Homebrew List version


brew list --version :

act 0.2.59
[省略]
skip 0.8.19
==============================
🚀
Docker version


docker --version :

Docker version 24.0.7, build afdd53b
==============================
🚀
Homebrew version


brew -v :

Homebrew 4.2.10-35-gece7e5d
==============================
✅ FINISH
```

## スクリプトの特徴
スクリプトは以下の2つで構成されています。
- 連想配列の使用：ここにツール名とバージョンコマンドを格納します
- for ループ：連想配列をループ処理して、順番に出力します

## 使用方法
リポジトリをクローンしたら、自分が使っているツールを連想配列に格納したら、保存をして、実行します。

```zsh
% zsh ~/[任意の場所]/shellScript/show-tool-version/ShowToolVersion.sh
```

自分でファイルを作成してコードをコピーしてみても構いません。

ぜひ、自分なりに編集して快適に使っってみてください。
voicevox coreのインストールとpythonでのサンプル実行

なんだかんだそれなりに手間かかった割にはやりたいことに到達できず無駄になってしまったので供養と整理とメモ書きついで。wslからやっててアーキはx86_64なので違う時は適宜読み替えて。pipが入ってる前提。
## voicevoxコアのインストール

```
 wget https://github.com/VOICEVOX/voicevox_core/releases/download/0.15.0/voicevox_core-0.15.0+cpu-cp38-abi3-linux_x86_64.whl
 pip install voicevox_core-0.15.0+cpu-cp38-abi3-linux_x86_64.whl
```

## 仮想環境の構築
```
mkdir voicevox
cd voicevox
sudo apt install python3.10-venv
python -m venv voicevox
source voicevox/bin/activate
```

##  各モジュールのインストール

onnxruntimeの最新は2024/03/08時点で1.17.1だが1.13.1じゃないと後でエラーになる
```
wget https://github.com/microsoft/onnxruntime/releases/download/v1.13.1/onnxruntime-linux-x64-1.13.1.tgz
tar zxvf onnxruntime-linux-x64-1.13.1.tgz
ln -s onnxruntime-linux-x64-1.13.1/lib/libonnxruntime.so.1.13.1
```
辞書のインストール

```
wget https://jaist.dl.sourceforge.net/project/open-jtalk/Dictionary/open_jtalk_dic-1.11/open_jtalk_dic_utf_8-1.11.tar.gz
tar zxvf open_jtalk_dic_utf_8-1.11.tar.gz
```

## サンプルの実行だ！
pythonわからないので参考にしたサイトからもらってきたサンプル
```python:sample.py
from pathlib import Path
from voicevox_core import VoicevoxCore, METAS
import sys, os

core = VoicevoxCore(open_jtalk_dict_dir=Path("./open_jtalk_dic_utf_8-1.11"))
speaker_id = 1 # 1:ずんだもん,2:四国めたん

text = sys.argv[1]
if not core.is_model_loaded(speaker_id):
  core.load_model(speaker_id)
  wave_bytes = core.tts(text, speaker_id)
  with open("./" + text + ".wav", "wb") as f:
    f.write(wave_bytes)
```

```
python ./sample.py なんかしゃべれ
```
なんかしゃべれ.wavができるので再生すればなんかしゃべる。
wsl2からだとオーディオ周りを別途設定しないとaplay利用できないの面倒ですね。

やりたいことは音声変換用のサーバ立てることだったはずなんだけど、この時点でうちのへぼPCだとテキスト→音声変換するのにえらい時間かかることに気づいてしまったので結局ここでゲームオーバーでした。
WSLでXの設定に失敗しているのでそれを修正するサービス作った（場当たり的解決）

**最近になって、このディレクトリがread-only filesystemになってサービス実行が失敗しているようなので、問題が修正されている可能性があります。**

場当たり的解決ですが、WSLでXの起動に失敗するので、次のようなサービスを定義しました。
（systemdと組み合わせていると起こりやすい問題らしい？）

具体的には例えば、xeyesを起動しようとすると次のようなエラーが出る感じ。
```
Error: Can't open display: :0
```

```/tmp/.x11-unix```に正しい内容が入っていないことが原因のようなので、起動時にこのシンボリックリンクを作ってやる設定をするサービスを作成し、```/etc/systemd/system/x11-socket.service```として保存しました。

```systemd
[Unit]
Description=X11 Mitigation Service

[Service]
ExecStart=/bin/bash -c 'rm -r /tmp/.X11-unix; ln -s /mnt/wslg/.X11-unix /tmp/.X11-unix'
Restart=no

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

これがWSL実行時に起動するように設定しました。

```bash
sudo systemctl enable x11-socket.service
```

一応解決。本当はなぜこの問題が起こっているのかを調査しないといけないんでしょうけど……。
Parse Server JavaScript SDKの使い方（JavaScriptでのロール操作）

[ニフクラ mobile backendは3月末で終了します](https://mbaas.nifcloud.com/info/2023/12/post-171.html)。

ニフクラ mobile backendからの移行先として、お勧めしているのが[Parse Server](https://parseplatform.org/)です。設計思想が近く、変更するコード量が少なく済むのではないかと思います。

Parse ServerではWebアプリやCordova（Monaca）アプリ向けにSDKを提供していますが、ドキュメントは英語のみとなっています。そこで、各機能の使い方を解説します。今回はアクセス権限に関係するロールの操作について解説します。

## JavaScript SDKのインストール

JavaScript SDKはCDN版を使うか、npmでインストールする方法があります。CDNの場合は、下記のタグでインストールできます。

```html
<script src="https://npmcdn.com/parse/dist/parse.min.js"></script>
```

npmの場合は、下記のコマンドでインストールできます。

```sh
npm install parse
```

ただし、JavaScript SDKはTypeScript用の型定義を提供していませんので注意してください。

## 初期化

SDKの初期化は任意の場所で行えますが、npmの場合はまずインポートが必要です。

```js
const Parse = require('parse');
// または
import Parse from 'parse';
```

React Nativeの場合は下記になります。

```js
const Parse = require('parse/react-native.js');
// または
import Parse from 'parse/react-native';
```

さらにNode.js向けは以下になります。

```js
const Parse = require('parse/node');
// または
import Parse from 'parse/dist/parse.min.js';
```

初期化はアプリIDとJavaScriptキーを指定します。さらにサーバーURLを指定します。

```js
Parse.initialize("YOUR_APP_ID", "YOUR_JAVASCRIPT_KEY");
Parse.serverURL = 'http://YOUR_PARSE_SERVER:1337/parse'
```

## ロールの作成

ロールは子ロールと、ユーザーを持つことができます。以下の例では、 `Administrator` というロールを作成しています。

```js
const roleACL = new Parse.ACL();
roleACL.setPublicReadAccess(true);
const role = new Parse.Role("Administrator", roleACL);
await role.save();
```

## ロールにユーザーを追加する

既存のロールに対して、新しいユーザーを追加する場合のコードです。

```js
const role = new Parse.Role(roleName, roleACL);
role.getUsers().add(usersToAddToRole);
role.getRoles().add(rolesToAddToRole);
await role.save();
```

## オブジェクトにロールを設定する

オブジェクトにACL設定としてロールを設定する場合には `setACL` を利用します。

```js
const wallPost = new Parse.Object("WallPost");
const postACL = new Parse.ACL();
postACL.setRoleWriteAccess(moderators, true);
wallPost.setACL(postACL);
await wallPost.save();
```

## ロールからユーザーを削除する

ロールからユーザーを消す場合には `remove` を使います。もちろんACLの設定によっては、削除できない場合もあります。

```js
role.getUsers().remove(user1);
role.getRoles().remove(user2);
await role.save()
```

## 既存のロールに新しいロールを追加する

ロールは入れ子の構造にできます。

```js
role.getRoles().add(childRole);
await role.save();
```

## 子ロールを削除する

子ロールを削除する場合には `remove` を使います。

```js
role.getRoles().remove(childRole);
await role.save();
```

## まとめ

Parse Serverのロールオブジェクトは、NCMBと変わらず利用できます。ユーザーを入れる形もそうですし、ロールを入れ子にできるのもNCMBと変わりません。

ACLの仕組みもParse ServerとNCMBで似ています。他のmBaaSと比べると、全体の修正量はそこまで多くないと思われます。載せ替え先として検討に挙げてください。

[Android Developers Guide \| Parse](https://docs.parseplatform.org/android/guide/)
【Unity】2D月兌衣ブロック崩しを真剣に作って公開するまでの防備録1

:::note warn
当記事は若干のnsfw要素を含みます。
:::
+ 記事内で直接的表現は極力避けますが、閲覧に際しては周囲の目、Webブラウザ監視ツール、閲覧履歴などに十分ご注意ください
## はじめに　Qiitaに投稿してどうするの
+ Unity初心者がゲームを作って公開するまでの記録、発生した問題とその解決法の防備録として運用します。インターネットに多数転がっているブロック崩しのハウツーは簡単な部分で完成にしてあったり、そもそも月兌衣ブロック崩しを作るにあたりあまり役に立たなかったりしたので、ここに書き留めていく次第です
+ 解決済みの問題を個別記事にします
+ 未解決の問題はきっと誰かがなんとかしてくれる！(他力本願寺)
+ ~~技術畑に飛び込む姿勢の第一歩~~

## 事の発端
Flashが使えなくなって久しいが、どうしてもB2ブロック崩しがやりたくなった。無いなら作ってしまおう。

## 目指す先
+ ゲームとして遊べるレベルの完成度にし、出来上がったものを販売する
+ 最終的にはエディタ側を頒布し、月兌衣ブロック崩しの復権を狙う

## 筆者の前提
+ Unity、C#未経験。オブジェクト指向is何
+ プログラミングに関しては学校でCとProcessingを少し囓る。クソ不真面目だったのでいずれも評定は可で抜けている
+ コンピューター工学は受動喫煙した雑学としてちょっと知っているくらい。ちゃんと本を読んで勉強してたりはしないです

## 24/3/7までにやったこと
+ 当Qiitaアカウント、新規名義の作成(nsfwコンテンツを扱うため)
+ Unityの導入、Platformerのチュートリアルを完了
+ ともあれ手探りなりに教本( https://amzn.asia/d/5k6as3M ) でC#の勉強
+ 一枚剥いたイラスト、その上に重ねる着衣イラストの用意

### ゲームのメインとなるScene作成
一応最低限ブロック崩しとしての遊びを成立させた

#### 基本仕様
+ 画面サイズ 1152：* 864(環境はPC,Webブラウザでのプレイを想定)
+ プレイエリアサイズ：576 * 864
+ ブロック：正方形ブロック24 * 24,差分となる画像の上にのみ配置

#### 壁
+ 上下左右に配置、下の壁はミス扱い。

#### ブロック
+ 着衣イラストの服、表情の部分のレイヤーをSprite Rendererで分割
+ バラバラにした差分画像をPrehab化したブロックに一枚ずつ割り当て。24*24のグリッドのどこにブロックが有るか、配置場所の情報をjsonファイルで記述。配置情報を読み込み背景画像に重なるように配置した

#### ボール
+ ボールから**RigidBody2Dを剥奪**し、ボールに接触するオブジェクト側にRigidBody2Dをアタッチして衝突検知するようにした。これは、  **2D物理によりボールが水平に反射し続ける** 、**ボールが垂直に反射してゲームにならない**といった悲しき事例を見てきた為、これの回避の為に行った
+ 「何かにボールが衝突し、反射する挙動」は全てボールに割り付いているスクリプトで行う。ぶつかり得るものにtagを設定しておき、衝突した相手の情報を読んで挙動を決定している
+ 移動はVector2型の変数 `BallVelocity` により行う。`BallVelocity`は正規化された方向だけを持つ`BallDir`とスカラー量の速度`BallSpeed`をFixedUpdate()関数の中で掛け合わせている。
これにより、ブロック崩しのゲーム性の要素であるボールの加速の管理を容易にしている。
+ バーにボールが接触した時、`BallDir`の値からその場で法線ベクトルを計算し `Vector2.Reflect();`メソッドで反射。両端のエッジ部分でボールの反射角を変えるにようにしている(ランダム反射はしない)


### バー
+ マウスのX軸の座標に追従して移動する。

## 解決済みの問題
### ブロック配置について
([前項](https://qiita.com/QT_4f659d/items/907bc168c86fa3d4f0dc#%E3%83%96%E3%83%AD%E3%83%83%E3%82%AF)で少し触れた内容であるが)
+ 通常のブロック崩しの常識(配置が複雑かつブロックのスプライトが全て異なる)が通用しなくなり、役に立つ文献が見つけにくい
+ ブロックに手作業でスプライトを設定するのはあまりに嫌だったので、ブロック生成用のスクリプトを用意した。これをStart関数で呼び出し、分割された画像を割り付けることで解決した。
### バーでの反射時、俯角(床)に向かってボールが飛んでいくことがある
+ 飛んできたボールに突っ込ませるようにエッジ部分で反射を行ったとき、一度反射したボールが再度バーの判定に衝突し、あらぬ方向へ飛んでいた
+ また、反射時の角度が急になりすぎたり、水平になりすぎることがあった
+ そのため、バーを反射したときに取り得る角度の範囲を水平から左回りに15°~75°,105°~165°の範囲に限定するようにした。これにより、下向きの反射(180~360°の範囲)を抑え、同時に極端な角度にならないようにした。

## 未解決の問題
+ ゲーム開始前に座標(0,0)上にあるブロックが破壊されることがある。残機対応に向けてボールをPrefab化したはいいものの、どうやら一瞬だけ座標(0,0)に生成→初期位置に移動している可能性がある。
+ 壁を貫通して画面外に行ってしまうことがある(rigidbody2Dのcollision detection周りな気がする)
+ ブロック崩しとしてあまり気持ちよくない反射の仕方をすることがある(rigidbody2Dのcollision detection周りな気がする。ついでに)
+ オブジェクト指向をよく分かっていない。とりあえずおまじないとしてやたらめったらMonoBehaviourを継承させている。おそらくボールやブロックなんかはきちんとクラスを持ち出してくれば使えばコードを整頓できる気はするが……

## これからやる予定
### ゲーム内の実装予定(上に有るものほど優先度高)
+ ゲームオーバー
+ 残機
+ 2枚以上の差分
+ アイテム
+ バー中心で反射したときの加速貫通弾
+ タイトル画面
+ セーブ
+ ギャラリー
+ 設定(ブロックのグリッド表示オンオフ、など)
+ 複数のキャラクター
### ゲーム外
+ 公開場所の算定

## おわりに
エタらせないようにしよう！
NestJSにおけるDIのまとめ

Q
ProvidersとModuleの違いは？

Provider:機能を提供するもの。注入可能。
Module:Providerをまとめたもの

Q
何故、ModuleのControllersプロパティにControllerをセットするとexportsプロパティにセットしなくても使えるのか？

コントローラーはアプリケーション全体で自動的に解決されそのルートはすべてのモジュールから利用可能になるため

Q
Moduleのプロパティの種類、使い分けは？

imports:他のプロバイダ、モジュールがエクスポートしたプロバイダ、モジュールを利用するためにインポートするリスト
controllers:現在のモジュールに含まれるコントローラーのリスト
providers:現在のモジュールで提供され（場合によってエクスポートされる）他のモジュールから注入できるプロバイダのリスト
exports:現在のモジュールが他のモジュールに公開するプロバイダのリスト


Q
Dependency Injection(DI)依存性注入とは

インターフェイスだけ用意し必要に応じて外部からクラス(依存性のあるもの)などを提供（注入）する

Q
DIトークンとは？

コード内でユニークな識別子(定数文字列等)
特定の依存関係を注入するために使われるキー

```
//サンプル
@NgModule({
    providers: [
        // このトークンに対して特定の値を提供します。
        { provide: MY_DI_TOKEN, useValue: 'Hello World' }
    ],
    ...
})
export class AppModule { }

// 後でこのトークンを使って依存性を注入できます。
constructor(@Inject(MY_DI_TOKEN) private value: string) {
    console.log(this.value); // "Hello World"
}
```

Q
providerの定義の仕方
```
@Module({
  providers: [ // providers配列で依存関係注入（DI）プロバイダを定義します。
    {
      provide: 'ASYNC_CONNECTION', // 'ASYNC_CONNECTION'というトークン用のプロバイダを定義します。
      useFactory: async (configService: ConfigService) => { // useFactoryは非同期接続を作成するための工場（ファクトリー）関数を提供します。
        const config = await configService.getConfig(); // 設定サービスから設定を取得します。
        return await YourService(config); // 取得した設定を使用して接続を作成します。
      },
      inject: [ConfigService], // Factory関数で必要な依存関係を注入します。ここではConfigServiceが必要とされます。
    },
  ],
})
export class AppModule {} // AppModuleというモジュールをエクスポートします。

```
注入されるサービスは`Injectale()デコレータで装飾する必要がある
```
import { Injectable } from '@nestjs/common';

@Injectable()
export class YourService {
    private connection: Promise<Connection>;
  // ...
}
```
コマンドプロンプト　メモ

使う機会少なく忘れそうなのでメモ。
エクスプローラーでAlt+Dでアドレスバー選択し、cmdコマンドを入力。
cmdコマンド一覧はhelpコマンドから確認できる。

## フォルダ構成作成
```shell::
cmd /c mkdir A¥B C D
```
/cでウィンドウ非表示。
結果をtreeコマンドで表示すると以下のようになる。
```shell:tree結果
C:.
|-A
| └-B
|-C
|-D
```

## cmdでcatし連結
```shell::
cmd /c type A* > merge.txt
```
typeがcatの代替となる。
上記は正規表現でA始まりのファイル内容をmerge.txtへ出力している。
出力先ファイルなければ作成される。


## ファイル名一括変更
renコマンド（renameコマンドと同一）
```shell::
cmd /c ren *A変更前.txt *B変更後.txt
```
OpenWrtとフレッツ光クロスでwan6の瞬断が発生する問題と解決

# 症状
およそ8時間~ごとにwan6がダウンしてONU側はUNIが一瞬消え、直ぐに再接続する。
ログには`'daemon.notice netifd: Interface 'wan6' has lost the connection'.`と表示され、再接続が即座に行われる。
切断時間はおよそ3秒~10秒ほど。
# 仕様
- 回線:NTT西日本 フレッツ光クロス(マンション)
- NIC:Intel i225-v
# 試したこと
- LANケーブルの交換
- ONU設置箇所の調整
- EEE(省電力イーサネット)の無効化
    - これはそもそも対応してなかったっぽい
- TSO(TCP Segmentation Offload)などの無効化
    - Proxmoxホストからの通信で負荷が高まるとNICが死ぬことがあり、それに対しての効果があったがwanは改善せず。
# 結論
DHCPv6の不具合(?)っぽい
https://shopage.shooffice.com/entry/2024/01/28/230000
https://github.com/openwrt/openwrt/issues/13454
# 解決策
下記のGistの内容をOpenWrtの`/etc/hotplug.d/iface/`内にファイルを作成して追加後、再起動する。
ファイル名は適当につけてヨシ!(自分は70-flets-reloadにしました、拡張子不要。)
https://gist.github.com/missing233/3dafb6ee549ed2271c20bd700b88a9cd
```bash
#!/bin/sh
# Place in /etc/hotplug.d/iface/

[ "$INTERFACE" = "wan6" ] || exit 0

CRON_CMD='0 * * * * kill -SIGUSR1 $(pgrep odhcp6c)'

if [ "$ACTION" = "ifup" ]; then
    grep -Fq "$CRON_CMD" /etc/crontabs/root || {
        echo "$CRON_CMD" >> /etc/crontabs/root
        /etc/init.d/cron restart
    }
elif [ "$ACTION" = "ifdown" ]; then
    sed -i "/$(printf '%b' "$CRON_CMD" | sed 's:[\\/.*^$]:\\&:g')/d" /etc/crontabs/root
    /etc/init.d/cron restart
fi
```
再起動後、OpenWrtのLuciにログインし`システム→スケジュールタスク`より
`0 * * * * kill -SIGUSR1 $(pgrep odhcp6c)`が追加されていることを確認する。
以降は自動でodhcp6cを56して初回更新になるので切断されなくなった。
多分NTT側の謎仕様によるものの可能性が高い…?
(ChatGPT3.5)FreeCADのマクロを教えて下さい。

# 開始
```
FreeCADのマクロを教えて下さい。
```
(途中省略)
```python
import FreeCAD
import Part

# Create a cylinder
cylinder = Part.makeCylinder(10, 20)

# Move the cylinder to a new position
translation_vector = FreeCAD.Vector(5, 5, 0)
cylinder.translate(translation_vector)

# Add the cylinder to the active document
doc = FreeCAD.activeDocument()
doc.addObject("Part::Feature", "MyCylinder").Shape = cylinder
```
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/9c1fa543-c14b-9fa0-e2a7-ea53e7e595fb.png)

# FreeCADのバージョン
```
ChatGPT3.5先生が使われているFreeCADのバージョンを教えて下さい。
```
(途中省略)
```
...2022年1月時点での最新のバージョンは、FreeCAD 0.19でした。...
```

# FreeCADのNavigator
・ビューを使い分けるのがおすすめかも。
・(わたしのタッチパッドの場合)2本指のタッチで、Navigator表示です。
```
FreeCADのNavigatorの違いを教えて下さい。
```
(途中省略)
```
z軸回転におすすめのNavigatorを教えて下さい。
```
(途中省略)
```
...Combo ViewとTree Viewが特に役立つナビゲータです。...
```


# 視点変更マクロを探しています。
#### テスト中？？？
(私は、まとめきれないので抜粋)
・申し訳ありませんが、前の修正にも誤りがあります。以下は修正されたコードです。
・申し訳ありません、エラーが発生しています。正しいメソッドを使用して視点を変更するように修正します。
・本当ですか
・本当の本当ですか
・繰り返しました。

**???みなさんも一度は、おすすめします。**
・今回、私は,実行 CTRL+shift+1 を覚えました。
領域確保とコンストラクタが呼ばれるタイミング

# はじめに
少し考えれば当たり前かもしれませんが、以下のコードはどのような挙動をするでしょうか？

```c++:sample
struct A {
    A() { std::cerr << "constructor" << std::endl; }
    std::array<char,99999999> buf;
};

int main() {
    std::cerr << "hoge" << std::endl;
    {
        A a;
    }
    std::cerr << "fuga" << std::endl;
}

```
```
g++ sample.cpp -O0
```

一見問題ないコードに見えます。実際、c++の文法的には問題なかったはずです。が、`std::array`で確保している領域が莫大なので、実行時はスタックを使い果たして何かしらのエラーが起きるなりして終了するでしょう。(最適化によって`A a`の存在が消滅させられる可能性はあります)

問題は、どのような出力が得られるかです。エラーになるのはスタックに積まれるときなので、コンストラクタは実行されないはずです。ということは`hoge`が出力されるのでしょうか？

しかし結果は、何も出力されませんでした。

# 私の誤解
お恥ずかしい限りなのですが、c++においてローカル変数の領域が確保されるのはスコープに入った時だと思っていました。これが正しければ、`hoge`が出力されます。

この結果に納得いかなかった私は、なんとかして`hoge`を出力しようと試みました。

# 試行錯誤した結果
無理でした。というかそのような挙動になる理由がないです。上記の挙動は私が「領域の確保」を勘違いしていただけと思われます。

冷静に考えたらメモリ領域のサイズが分かっているのに複数回に分けてスタックに積む必要がありません。

また、アセンブリを覗いて気が付いたのですが、通常はスタック周りの保護のために関数呼び出し前後でコードが挿入されています。なので無茶なスタックを確保するコードを書いたら、`main`関数に入る前に落ちている可能性が高いです。

再現するには関数を使ってスタックを積みなおす必要ばあります。
```c++
void func() {
    std::cerr << "called" << std::endl;
    A a;
}
int main() {
    std::cout << "hoge" << std::endl;
    func();
}
```
ちなみにこの場合、`hoge`が出力されて`called`は出力されません。実行時エラーのデバッグ時に、このように関数呼び出しで落ちていた場合はスタック周りを疑ってみるといいかもしれません。

# 正しい挙動は？
おそらくスタック周りの動作は実装依存だと思われます。(詳しい方がいたら教えてください)
コンストラクタは記述した通りに呼ばれています。

固定長だからとむやみに`std::array`を使うのは考えものですね。
Unity VFXGraphのノード基礎

## はじめに

UnityのVFX Graphは、リアルタイムで高品質なビジュアルエフェクトを作成するためのツールです。
従来のParticleSystemと異なりGPUベースで実行されるため、リッチな表現を簡単に実行できます。また、ノードベースのシステムを使用しており、プログラミングなしにビジュアルエフェクトを作成できる点も特徴です。
以降ではVFX Graph入門者に向けて、いくつかの基本的な概念を説明します。

### 参考
https://www.youtube.com/watch?v=Xwmdl4sbsjY

## VFX Graphの基本概念

#### 1. ノード
VFX Graphでは、ノードはエフェクトのビルディングブロックです。これらは様々な種類があり、パーティクルの生成、色の変更、動きの制御など、特定の操作を表します。ノードは入力を受け取り、処理を行い、結果を出力します。

#### 2. エッジ
ノード間の接続をエッジといいます。これにより、ノード間でデータが流れ、エフェクト全体が形成されます。エッジはノードの出力から別のノードの入力へとドラッグして作成します。

#### 3. コンテキスト
コンテキストは、ノードが実行される環境を定義します。VFX Graphには、主に`Initialize`、`Update`、`Output`の3種類のコンテキストがあります。`Initialize`はパーティクルの生成時に一度だけ実行され、`Update`は毎フレームパーティクルの動作を更新するために使用されます。`Output`コンテキストは、最終的なパーティクルのレンダリング方法を定義します。

#### 4. ブロック
ブロックは、特定のコンテキスト内での操作を表すノードの一種です。例えば、`Initialize`コンテキスト内のブロックはパーティクルの初期位置や速度を設定し、`Update`コンテキスト内のブロックはパーティクルの動きや寿命の管理を行います。

#### 4.オペレーター
オペレーターは、値の計算やデータの変換を行うノードです。例えば、数学的な演算を行ったり、ベクトルの計算をしたりします。オペレーターを使用して、エフェクトの振る舞いをより細かく制御し、ブロックに入力するデータを動的に生成することができます。

#### 6.プロパティ
プロパティは、エフェクトの外部から制御できるパラメータです。ユーザーがインスペクターウィンドウからアクセスして値を変更できるようにすることで、同じエフェクトを異なる状況やオブジェクトに再利用する際に柔軟性を提供します。プロパティは、エフェクトのカスタマイズや再利用性を高める重要な概念です。

#### イベント
イベントは、エフェクトの特定のアクションをトリガーするシグナルです。ゲームオブジェクトが特定の位置に到達したとき、ユーザーが特定のアクション

## 基本構成の中身
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3551600/5d399f80-5d7a-da1d-56a9-92ff5d279f31.png" width="60%">

#### 1. Spawn ノード
particleを生み出すためのノードです。
画像だと、1秒間に16個のparticleを生みだすことになります。

#### 2.　Initialize ノード
particleを初期化するためのノードです。
画像だと、`Set Velosity Rondom`ブロックで、Particleの初期速度、`Set Lifetime Romdom`でParticleが表示される寿命を決めます。
 

#### 3. Update ノード
particleを更新して動きを決めるノード

#### 3. Output ノード
particleをレンダリングするためのノード
画像だと、`Face Camera Plane`でparticleの向き、`Set Size over Life`で大きさ、`Set Color over Life`でカラーを決めます。

### VFX Graphの使用開始

1. **Visual Effect Graphアセットの作成**: プロジェクトウィンドウで右クリックし、`Create` > `Visual Effects` > `Visual Effect Graph`を選択します。
2. **VFX Graphを開く**: 作成したVFX GraphアセットをダブルクリックしてVFX Graphエディタを開きます。
3. **コンテキストの追加**: エディタの空のスペースで右クリックし、必要なコンテキスト（例：`Initialize Particle System`）を選択して追加します。
4. **ブロックの追加**: コンテキスト内で右クリックし、追加したいブロック（例：`Set Position`、`Set Velocity`）を選択します。
5. **ノードの接続**: 必要に応じて、ノード間をエッジで接続して、データフローを構築します。

6. **エフェクトのプレビュー**: VFX Graphアセットをシーンに配置し、Unityのプレイモードでエフェクトを確認します。

## まとめ
　以上でVFX Graphの基本的な要素の概要を把握できました。これらのコンポーネントを組み合わせることで、独自のダイナミックなビジュアルエフェクトを作成できるようになります。実際にVFX Graphを使い始めて、様々な参考資料を見ると頻出するので、これらの要素を忘れずに活用してみましょう。
ドラクエ11のダメージ計算式をjavaScriptで実装してみた【ゲームやツール制作の参考にどぞ】

```
最終更新日: 20240308
```
# ドラクエ11のダメージ計算式
まずはダメージ計算式について書いていきます
(実はドラクエ9でも同じダメージ計算式が使われていたりします)
## 実ダメージ計算式
ゲームを遊んでいると表示されるダメージです
このような式で計算されています！
``` 
基本ダメージ ± ダメージ幅  // ±はプラスマイナス
```
## 基本ダメージ計算式
攻撃力はplayer、防御力enemyの値です！
```
攻撃力 / 2 - 守備力 / 4
```
## ダメージ幅(乱数)の計算式
例: 「5.6875」だったら端数は切り捨てして「5」になります
```
ダメージ基本値 ÷ 16 + 1（端数切捨）
```

## 攻撃力200のplayerが守備力100のenemyを攻撃した場合
基本ダメージ
```
200 ÷ 2 － 100 ÷ 4 = 75
```
ダメージ幅
```
基本ダメージ(75) ÷ 16 ＋ 1 = 5.6875(端数切捨) = 5
```
実ダメージ
```
基本ダメージ(75) ± ダメージ幅(5) = 75-5と75+5の範囲 = 70～80の乱数が実ダメージ
```

# javaScriptでダメージ計算式を実装
本題ですねー
「attack」と「defence」変数の定義は各自でやってください m(＿ ＿)m
## 基本ダメージ
``` javaScript
damage_basic_value = Math.trunc((attack / 2) - (defence / 4))
```
## ダメージ幅
``` javascript
damage_ran = Math.trunc(Math.round(damage_basic_value / 16 + 1))
```
## 実ダメージ
±の乱数範囲部分
``` javascript
maxDamage = damage_basic_value + damage_ran
minDamage = damage_basic_value - damage_ran
```
実ダメージ 
``` javascript
Math.trunc(Math.random() * (maxDamage - minDamage) + minDamage);
```

## まとめ
``` javascript
// dq9とdq11のダメージ計算式
damage_basic_value = Math.trunc((attack / 2) - (defence / 4))
damage_ran = Math.trunc(Math.round(damage_basic_value / 16 + 1))
maxDamage = damage_basic_value + damage_ran
minDamage = damage_basic_value - damage_ran
Math.trunc(Math.random() * (maxDamage - minDamage) + minDamage);
```

## おまけ
実際はこんな感じで
ダメージが0を下回ったときの最低ダメージも実装してやらないとですねー
``` javascript
 if (0 >= damage_basic_value) {
                return 1
            }            
```
他にもバフ・デバフが関連してくると
ダメージ計算式が更に複雑になる予感...
まー、ここまで読んだ貴方なら大丈夫でしょう！

# おわりに
実装しようと思ったきっかけなんですけど
こんな感じのゲームもどきを作ったときに
どうせならダメージ計算式を本家ドラクエのものにしたいよねーってノリで作った記憶がありますねー
初めて作ったGUiアプリ？なので思い出深いです
![スクリーンショット 2024-03-08 135425.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714713/e38d74ba-dff5-167a-e01a-88e52affed49.jpeg)


よかったらTwitterフォローしてね！
フォロバしまっす

https://twitter.com/rioLi0N
Skip使ってみた

## Skipとは？
- Swift/SwiftUIを用いてAndroid開発も行えるプロジェクト
    - 内部で，Swift/SwiftUIコードをKotlin/Composeコードへのトランスパイルが行われている
    - 正確にはクロスプラットフォームではなくSwift/SwiftUIでAndroid開発ができる
    - Xcodeへ導入することで使えるようになる(AndroidのためにAndroid Studioは必要)

![スクリーンショット 2024-03-08 15.10.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3688344/bf469a88-afb1-8b4e-59f7-6889eeb431f3.png)

(引用:https://skip.tools/docs/)

## ここがすごい
- Swift Package Manager (SwiftPM) から Android Gradleへのプロジェクトコンバーターも同梱．パッケージ依存関係を自動的に保ってくれる
- https://github.com/skiptools/ でiOSのSwift，Foundation，Observation，SwiftUI，およびその他のフレームワークの一部をAndroid固有のものへ再実装
- XCTest → JUnitに変換して自動単体テストもサポート

## いざ導入
### Homebrewで簡単導入！！
```brew install skiptools/skip/skip```
そして諸々のdependenciesをチェック&解決
```skip checkup```
アプリケーション作成コマンド
```skip init --appid=tools.skip.HelloSkip hello-skip HelloSkip```

それぞれのコマンドは
```skip init --appid=(AppID) (ProjectName) (Appname)```
という意味だそう

## 引っ掛かりポイント
- Gradleの設定に戸惑った
    - Gradle8.6を標準サポートしている様子(執筆時点)．コマンドラインでgradleを実行して原因調査
        - 結果Android SDKの場所が適切にわかっていなかったため，無理やり環境変数で設定して実行成功

## 感想
力技のトランスコンパイルに感動しました．面白いプロジェクトだと思います．フレームワークのAndroidへの再実装はgithubで進められており，Contributer募集中だそう！これはやるっきゃない！

## 参考
https://skip.tools/docs/

https://github.com/skiptools/skip
Web画面でファイル解析をフロントエンドでやるかバックエンドでやるか ( アップロード処理の例 ) ( エクセル/PDF/CSVなど )

# 要件

- Webの画面からファイルを選択して、その内容をサーバー(バックエンド)に送信したい

# フロントエンド方式

- 例えばエクセルであれば exceljs などのライブラリを使う
- ブラウザでファイルを選択したタイミング、もしくはバックエンドに送信する前段階でファイルの解析をする
- 読み取ったファイルの解析内容からバックエンドに送る内容をJSONなどで組み立て、バックエンドに対してリクエストを行う
- バックエンドはシンプルなリクエストを受け取って、必要な処理をおこなう

## メリット

- 「ユーザーがファイルを選択したタイミングでファイル内容を解析し、画面に何らかデータを表示する、エラーを返す」などインタラクティブなハンドリングが出来る

## デメリット

- ユーザーのスペックはブラウザに依存するので、大きなファイルや複雑な処理の負荷があると辛いかも
- 挙動がユーザー依存なので、思わぬ不具合が起きた時に原因を特定しづらいかもしれない

# バックエンド方式

- フロントからバックエンドにファイル本体を送信する
- バックエンドではライブラリを使ってファイルを解析し、必要な処理をおこなう

## メリット

- ファイル解析にサーバーのスペックを使えるので、ユーザー環境の負担が少ない

## デメリット

- フロント方式のようなインタラクティブな処理がしづらい


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
Vue勉強 監視プロパティwatch

(Vue.js 3.1.5を使用)
監視プロパティwatch
・プロパティを監視しておいて、そのプロパティに変更があった場合に何らかの処理をさせる。

watchは、ウォッチャーと呼ぶのかな？
公式サイトでは、ウォッチャーと書いてあるよう。

watchでプロパティを監視して、v-model(双方向バインディング)で、ブラウザ上のデータとvueのデータを連動させる例。
```javascript:javascript
const app = Vue.createApp({
    data: () => ({
        meter: 0,
        kmeter:0
    }),
    watch:{
        meter: function(value){            
            this.meter = value
            this.kmeter = value / 1000
        },
        kmeter: function(value){
            this.kmeter = value
            this.meter = value * 1000
        }
    }
})
app.mount('#app')
```

```html:html
    <div id="app">
        <p>メートル: <input type="text" v-model="meter"> </p>
        <p>キロメートル: <input type="text" v-model="kmeter"> </p>
    </div>
```

初期状態

![26.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/54c831ef-69c6-21b0-c85b-98634664dbda.png)

メートル欄に 5000 を入力すると、
キロメートル欄に、5 が自動で入る。

![28.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/26c97bde-bdf8-7216-dbaa-eff38e5c8565.png)

キロメートル欄に 100 を入力すると、
メートル欄に、100000 が自動で入る。

![29.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1284134/c71409ad-0313-79bf-29c3-8b83f6eea098.png)
Number.parseIntってアホな子なの？

# Number.parseIntに色んな文字列を渡してみた結果
[前回の記事](https://qiita.com/AsilHatake/items/2a02c600d26397c36379)で、

__数値チェックするならNumber.parseIntの結果をisNaNでやらんほうがいいかもね__

って、最後に補足で書いたけど、なぁぜなぁぜっていう理由を、実際のコードで試した結果を領域展開するよ
※[ここ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/parseInt)のページをChromeで実行してみた結果

## えっ、こんな文字列も数字扱いしてくれるの？
```javascript:全部isNaNがfalse
console.log(Number.parseInt("11-1"));  // 11
console.log(Number.parseInt("-11-1")); // -11
console.log(Number.parseInt("11e+5")); // 11(指数表記だから？)
console.log(Number.parseInt("1,000")); // 1(1000じゃなくて1になるクソ仕様)
console.log(Number.parseInt("1 111")); // 1(なぜ1になるんや。。。)
console.log(Number.parseInt("1 hello world!")); // 1(流石にisNaNになれよ。。。)
```

先頭の文字が以下のような数字パターンの場合、
- 数字（12345）
- 数字e（1e）
- -数字（-1）
- +数字（+1）

文字列の中に何度「+」「-」「,」「.」「e」があろうが、
下手したら後ろが普通に文章とかだったとしても数字扱いになるという動きだった。

## ね、チェックで使っちゃいけない理由がわかったでしょ？
もし入力チェックをJavaScript（フロント）だけしかしないで、
API（バック）側ではやらないとかいう実装をしてる弱々プロジェクトがあった場合、
数値項目に変な文字入れられてそれによりAPIサーバーやDBに何か色々と問題が起こせそうな
コマンドとか送信できそうだなぁって夢見たりしちゃうので、
標準で用意されてる関数もきちんと使い所を見極めて使っていきたいものですね。
エンジニアによるエンジニアのための名著『世界一流エンジニアの思考法』を読んでみた

## はじめに
SEを始めてから3年が経つのだけれども、エンジニアとしてもっと成長したいと思っている中、この本に出会いました。
この本では、タイトルにもあるように"**生産性を上げるため**"について世界の一流と呼ばれるエンジニア達の思考法などについてまとめられています。
この記事はあくまで実際に読んだ個人の感想なので、そうなんだ程度に読んでいただけると幸いです。
## 第1章:世界一流エンジニアは何が違うのだろう？<br>-生産性の高さの秘密
あなたは、エラーが起きた時、該当しそうな所を修正して実行を繰り返していませんか？
そのコード、書き方、処理内容、本当に「理解」していますか？
ここでは、プログラミングにおいて使うのは「手」よりも「頭」の方が大事というようなことが書かれていました。
>試行錯誤は「悪」である
>頭がよくても「理解」には時間がかかる
>「偉大な習慣を身につけたプログラマ」になる

## 第2章:アメリカで見つけたマインドセット<br>-日本にいるときには気づかなかったこと
「あれ」も「これ」もと、たくさんのタスクに優先順位を付けて仕事してませんか？
自分もそのうちの1人ですが、優先順位をつけて全てこなすのではなく、いかにやることを減らすのかを考えるのが重要なんです。
納期は守らなければいけない、けれどミスはしたくないし、リスクは犯したくないからとりあえずは「検討」しがちな我々ですが、
この章では、もっと「楽」に働くためのメンタリティについて書かれていました。
>「Be Lazy」というマインドセット
>　Fail Fastの精神
>「納期は絶対」の神話は捨てよう

## 第3章:脳に余裕を生む情報整理・記憶術<br>-ガチで才能のある同僚たちの極意
難しいソースコードでもなんとかして読もうとした結果、脳みそが疲れるだけで何も得られなかった経験が皆さんにもあるのではないでしょうか？
マルチタスクなんて響きは良いけど、蓋を開けてみると実はどれも中途半端に終わってることなんてザラにありますよね..
そんな脳みその使い方からはおさらばするための方法が、この章では書いてありました。
>コードリーディングのコツは極力コードを読まないこと
>今の自分では解けないとしっかり見極めること
>マルチタスクは生産性が最低なのでやらない

## 第4章:コミュニケーションの極意<br>-伝え方・聞き方・ディスカッション
誰かに何かを説明する時に、いろんな情報を乗せることは丁寧に見えて、実は分かりづらくしているということに気づいていますか？
プログラミングは1人でやるものというイメージがあるかもしれませんが、実はそんなこともなく、どうやったら、上手にコミュニケーションがとれるか、毎日悩んでます。
リモートワークが主流になってる今、改めてコミュニケーションの大事さについて触れている章になってます。
>相手が求めてる情報への感度を研ぎ澄ます
>クイックコールを頻繁に使うこと
>「相手を否定しない」「相手のアイデアを否定しない」、そして「自分の考えとして意見を言う」

## 第5章:生産性を高めるチームビルディング<br>-「サーバントリーダーシップ」「自己組織型チーム」へ
上司の指示を待って、言われた仕事をただこなす。
この働き方を否定するわけではないですが、その仕事は本当に「楽しい」ですか？
今いるチームの環境はどうですか？
この章では、仕事を「楽しい」と思うためには、どうすれば良いかなどについて書かれていました。
>「サーバントリーダーシップ」とな何か
>「仕事は楽しむもの」というカルチャー
>チーム内では、スキルや経験に関係なく、全員が同じ責任を持っているフラットな「仲間」としてふるまうこと

## 第6章:仕事と人生の質を高める生活習慣術<br>-「タイムボックス制」から身体づくりまで
キリがいいところまで仕事をやろうとした結果、定時を過ぎてまで働いて、自分の時間を取るために夜遅くまで起きて寝不足になったり。
これらは僕の経験談ですが、皆さんも共感してくれますよね？
そんな負のサイクルから抜け出すための考え方や方法などが書いてありました。
>「タイムボックス制」で学習の時間を確保
>「幸せが、人の成功の指標となる重大な結果に先行する」
>「自分がどこに情報を置いたか記憶する癖をつける」

## 第7章:AI時代をどう生き残るか？<br>-変化に即応する力と脱「批判文化」のすすめ
AIの発達に伴って、いろんなことがAIに置き換わる風潮があるけれど、音楽やイラスト、映像など、結局は人が作るものには敵わないような気がしてます。
ただ、そんな自分もソースコードを書く際には、活用したりしています。
結局は、付き合い方なのかなと、感じました。
AIがこれからも進化していく中で、その変化に対応するためにはどうすれば良いかなどが、この章にはまとまっています。
>AI時代には「専門性」こそが強みとなる
>「開発者の心を砕いてしまう」批判文化
>「自分の人生や幸せに責任を持って、自分でコントロールする」というマインド

## あとがき
いろんなことを書いてきましたが、あくまでも個人的な意見だということを改めて言っておきます。
読みにくい部分もあったかと思いますが、ここまで読んでくださり、ありがとうございます。
今後は読んだ書籍の感想以外にも勉強の証跡としても記事を書いていこうと考えてるので、また読んでくれると嬉しいです。
もし、この記事を読んで、少しでも気になった方がいたら是非、この本を読んでみてください。
きっと何かしらあなたの知見を広げる助けになると思います。

https://www.amazon.co.jp/dp/4163917683
Amazon Auroraの空きメモリがたまに消失する

## 状況
Amazon Aurora　MySQLを利用。
過去にメモリ不足となり処理が停止した為、インスタンスのプラン変更後にメモリアラートを設定。

しばらくして、メモリアラートがたまに飛んでくる。
状況を確認するとFreeableMemory(空きメモリ）が取得できていないという。

![名称未設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17764/97bdae64-2fd6-e9cd-983a-7a52c14ddca7.png)

緑のグラフ線がFreeableMemory。
01:11から01:13の値が取得できていない。
アプリ側でトラブルも発生しておらず、RDS側のログにもとくに何もない。

## 考察

FreeableMemoryの値は稀に取得できないことがある

## 対策案

アラームの評価期間を増やす

現在はアラームの評価期間は1分

この1分というアラームの評価期間が短いために欠損データが発生してしまい、アラートが発生していると思われる。
Government e Marketplace

Government e Marketplace GeM

Visit today for more information: https://gem.gov.in/
GeM conducted comprehensive training programs in collaboration with the Ministry of Panchayati Raj (MoPR), reaching CSC Village Level Entrepreneurs (VLEs) across every State and Union Territory and equipping them to be the catalysts for adoption of GeM portal across Panchayats. GeM’s training initiatives span the entire nation, ensuring that no state or district is left untouched.
![gem conduct.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738798/d5d1f499-28d0-2801-2ff7-9cdca61f221c.jpeg)
【Spring】org.springframework.web.servlet.DispatcherServlet noHandlerFound【エラー解決】

# はじめに
Spring MVCで適当なアプリを作ったところ、404エラーが出続けたので自分の誤りをメモ。
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/526202/e5e4d8af-9333-f41b-31db-2cc172f36df6.png)

:arrow_down: ログ抜粋
```
3月 08, 2024 2:29:43 午後 org.springframework.web.servlet.DispatcherServlet noHandlerFound
警告: No mapping for GET /demo6/
3月 08, 2024 2:29:43 午後 org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolver handleNoHandlerFoundException
警告: No endpoint GET /demo6/.
```

# 間違ってたとこ
Bean定義ファイルの`<context:component-scan>`タグの`base-package`属性で指定するパッケージの階層が間違ってました。

この解決に半日費やしちゃったよトホホ
Cognitoでログイン後Pollyを呼び出す

AWSのCognitoの認証・認可関係でつまりに詰まったので、まとめます。

・やりたいこと：
サイトにログイン機能を実装し、ログインしたユーザーがAWS Pollyを呼び出してテキストを読み上げてほしい。

・前提：
amplify authでいい感じに実装してほしかったが、うまくいかなかったので、Cognitoの概念自体を学びなおしました。

# 1, Cognitoとは？
　ログイン機能を簡単に作ってくれます。もっと詳しく書くと、認証をつかさどるユーザープールと、認可をつかさどるidプールに分かれます。つまり、ユーザープールでユーザー名やパスワード、Eメールなどで本人確認を行い、そこで認証したユーザーに、idプールが適切なAWSサービスへのアクセス権限を与えてくれます。

 # 2, ユーザープールの作成
　新規のユーザープールを作る際に、ユーザープールとWebアプリの紐づけを行います。amplifyで設定を更新後、アプリのログイン画面からユーザーが作成できることを確認します。
　ユーザーの中でも管理者と一般ユーザーというように、group分けして、idプールでgroupごとに与える権限を変えることも可能です。今回は無視。

 # 3, idプールの作成
#### a, ユーザープールとidプールの紐づけ
　idプールの「ID プロバイダー」項目でユーザープールが紐づいていることを確認します。

#### b, 認証されたアクセスとゲストアクセスの権限設定
　ログイン後のユーザーには認証されたアクセス権限を、ログイン前のユーザーにはゲストアクセスの権限を与えます。必ず２種類設定しないと、amplifyで使えなかったのに気づかず、ずっとはまっていました。
 　それぞれIAMロールを作成するのですが、IAMロールにも「許可ポリシー」と「信頼ポリシー」という２つの種類があり、適切な設定が必要です。

 ・「許可ポリシー」とは？
 　その名の通り、AWSサービスへの許可リストのことです。今回はPollyを呼び出せる権限をつけたいので、ゲストユーザーにはCognito identity、ログイン後のユーザーには雑に「AmazonCognitoUnAuthedIdentitiesSessionPolicy」をつけます。（あくまでテスト段階なので、後ほど適切な権限に切り替えます）

  ・「信頼ポリシー」とは？
  　雑に言うと、「誰に対して」先ほどの許可ポリシーを付与するのか？という宣言です。今回はCognitoのidプール自体につけるので、以下のようなjsonにします。

```json:信頼されたエンティティ
{
  "Version": "2012-10-17",
  "Statement": [{
    "Effect": "Allow",
    "Principal": {
      "Federated": "cognito-identity.amazonaws.com" 
      # 「誰に」許可を与えるか宣言
    },
    "Action": [
      "sts:AssumeRoleWithWebIdentity",
      "sts:TagSession"  
    ],
    "Condition": {
      "StringEquals": {
        "cognito-identity.amazonaws.com:aud": {自分のidプールのid}
      },
      "ForAnyValue:StringLike": {
        "cognito-identity.amazonaws.com:amr": "authenticated"
        # ログイン後のユーザーのIAMの場合、"authenticated",
        　ゲストユーザーのIAMの場合、"unauthenticated"
      }
    }
  }]
}
```
   
#### c, ユーザーグループのgroupごとに適切なIAMロールを付与。
今回は対象外のため、割愛

# 4, 確認
　Webアプリでログイン後、Pollyを呼び出せることを確認します。
なんとかできました。AWSサービスは独自の造語が多く、翻訳が大変でした。

# 5, おまけ
　Cognitoの認証・認可機能を使って、ローカルからlambdaなどAWSサービスを呼びます。

``` credentialsの作成
  const idToken = (await fetchAuthSession()).tokens?.idToken ?? "";
```
　credentials作成に必要なidentity idを呼び出します。cognitoにはidがいろいろあってややこしいのではまりましたが、必要なのはidプールのidentity idでした。amplify公式ドキュメントにある上記のコードで取得可能です。公式↓
 https://docs.amplify.aws/react/build-a-backend/auth/manage-user-session/

```
  const userPoolUrl 
          = 'cognito-idp.' 
          + {cognitoのリージョン} 
          + '.amazonaws.com/' 
          + {ユーザープールのid}
```
ユーザープールのurlを作ります。
```
  const credentials = fromCognitoIdentityPool({
        identityPoolId: {idプールのidentity id},
    logins: { // 認証情報。ユーザープールのほか、OAUTH認証もこちらで使用
      [userPoolUrl]: idToken.toString(),
    },
    clientConfig: { region: {クライエントのawsリージョン} },
  });
  ```
  上記で作ったidTokenとuserPoolUrlを使って、credentialsを作ります。
 ```sdk
 // ローカルで各サービスのクライエントを用意
const lambdaClient = new LambdaClient({ 
    region: {region}, // リージョン
    credentials　// 上記で作ったcredentials。
})
  ```
  Clientができました。AWSサービスを呼び出す準備が整いました。
  ちなみにcredentialsを省略してClientを作った場合、idプールのゲストユーザーの権限で各サービスを呼び出してます。
Qiita と Zenn と AI と ChatGPT

最近Qiitaに記事を書いても、ほとんどいいねがつかない。特に小さなコードを書くようなメモ的な記事には全くと言って良いほどいいねが付かない。というかほとんどの記事のいいね数はゼロのままだ。たぶん5記事書いてようやくいいねが1回つくかつかないかというレベル。

自分のQiitaのアカウントのContributionでいうと15000ほどあり、記念品のシルバーバッジももらった。そして今でも自分が書いた記事全ても中から、週に7いいねほどは付く。だが最近書いた記事はまったく注目もされず、いいねの数を見る限りはほとんど人の役にも立たず、ただデータとして存在しているだけだ。

自分がQiitaに記事を書き始めたのは8年ほど前だっただろうか。その頃は事情が違った。Qiitaも今ほどにSNS的ではなかったし、記事につけた「タグ」を頼りにか、ちょっとした記事にいいねが付くこともあったと思う。

初心者の頃はこんな記事を書いていた。懐かしい。

https://qiita.com/YumaInaura/items/4d2c602d59c62daa9344

今は時代が変わった。昔であれば「Qiitaの記事だと何を書いても信頼度が高く見えてしまう」という問題が囁かれるほどのソースだったのだが、今では「だってQiitaの記事だし…」信用ならないというような口調で語られるようになった気がする。

あとは各言語やフレームワークの公式ドキュメントが充実し、今ではChat GPTもある。その残りのパイをQiitaとzennで奪い合うようになったのだから、今の状態は仕方がない。

かと思うとQiitaのトレンドを見ると800も900もいいねが付いている記事もあり、これはSNS的な「富むものはさらに富む」が具現化されたからなのだろうか。それとも自分が大した記事を書けていないからなのだろうか。もしくはその両方なのだろうか。たぶんほとんどの理由は後者の「大した記事を書けていない」かもしれないが。

しかしそれにしても、今後も単にコードの断片を書いたような記事の価値は下落の一途を辿ることだろう。なにせどんな質問でもほとんどの場合、 GPTが鮮やかに答えてくれるのだから。まあそのGPTのソースを作っているのはQiitaに書くようなネット上の記事だろうとは思うのだが。

しかし自分の場合は技術的な記事に限らず、文章に残してパブリックな場所に置くということ自体が好きなので、続けている。それに記事を書くことで最も自分自身が物事を整理・理解しやすいように思えるからだ。

そして書いた記事は思い出していつでもググることもできるし、人に見せて参考にしてもらうことも出来る。非常に良い仕組みだと思うのだが、このまま人の書いた記事の価値は下落の一途をたどり、皆がAIだけに質問するようになるのだろうか。時代は変わる。侘しいものだ。



# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
閑話休題：AS/400はもうすぐなくなります？ 2024エディション

## AS/400はもうすぐなくなると聞きました。ほんとうですか？

ユーザーさんに聞くところでは最近とみに飛び込みのパッケージベンダーさんやWindows等のアプリ開発ベンダーさんがよく言ってくるのだとか。

冒頭の質問は、
### Windows NTはもうすぐなくなると聞きました。ほんとうですか？

と同じくらいナンセンスなんです。

## IBM i は永久に不滅です！

永久、は誇張ですがw、

事実は

**AS/400は1999年、すでに無くなりました。**

**後継OSはIBM i です。IBM i はAS/400資産をほぼ100%コンパイル無しの保管・復元で稼働させることが出来ます。が、AS/400(OS/400)とは別なOSです（アーキテクチャ的にも）**



ここ誤解されるのはIBM社の姿勢にも問題あったかもしれないですね。

「AS/400」てとても愛された製品でしたので、IBMもパートナー企業さんもユーザーさんも親しみ込めて 400、とか AS とか呼びますから。今でも。

**くどいですが、AS/400は20世紀にすでに終了しています。AS/400資産がオブジェクト・コンパチブルで動くIBM i OSが後継OSです。IBM i は過去15年くらいロードマップを公開＆更新し続けています。**

## IBM i ロードマップ最新版がこちら。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/36b4d085-f982-73df-a0df-1fc97fe9cd17.png)

ミライの矢印も含めて適当に引いてるわけではなく、この辺にホントに出しますよ、という事が過去10年以上の実績です。

**上記の図では2035年までIBM iの正式サポート（延長保守ではなく）が続くことが読み取れます。**

ここからは（ミライの話でまだIBM社は何も発表していませんので）個人の推測になりますが、
**・IBM i 7.5の次のバージョン(表中ではIBM i Nextと記載)が発表されるのはそう遠くないミライ**
**・IBM i 7.5の二世代先のバージョン(IBM i Next + 1)もすでに開発中で、その発表は2029年前後になるであろう**

上記表中のIBM i Next + 1 までで考えても、延長保守が今と同様にできるのだとしたら2035+5年で2040年まではIBM i がサポートされることはほぼ間違いないでしょう。**強調しますが、IBM i 7.5の次バージョンが発表されればほどなくこのロードマップ表は更新されるであろう（これまでの15年以上と同様に）。ということです。**

## 以下、余談の余談
逆にここまでロードマップを明確に出しているソフトウェアは珍しいのではないでしょうか？
某社のようにロードマップは出したがずっと遅れっぱなし、とかいつの間にか無くなった、ということはIBM i ではまず考えられないですね…IBM社の信用に（株価に^^;）影響するので。


冒頭の永久に！、は誇張ですが、これ見ている技術者が現役のうちはおぼろげにでも予想しうる将来において無くなることは無いのではと思います。ですから安心してお使いくださいませ♪


そして、 **競合他社さんは嘘はいけません詐欺でしょう、事実に基づいてビジネスをしてください♪** 

***2024年案件で、某大手SIerさんがIBM_iの将来性は不透明です的なウソを言ってお客様に入り込んでいるのだとか。ホンとウソはいけません、嘘つく企業は他でもウソをつくのですから***


技術者さん向けの記事じゃなくてあい済みませんm(_ _)m。
以上です。
【BigQuery】スケジュールされたクエリで定期実行を簡単に設定する方法

## はじめに
BigQueryのスケジュールされたクエリ機能を利用することで、データの分析やレポート作成を自動化し、定期的に実行することができます。この機能は、データの定期的な集計や変換、アラートの生成など、さまざまな用途に活用できます。


## ステップ 1: クエリの入力とスケジュールの設定
実行したいSQLクエリを「エディタ」に入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706527/f7dd5db8-880b-cfe5-c7f4-62e9e362903a.png)

「スケジュール オプション」セクションで、クエリの実行頻度を設定します。例えば、「毎日」「毎週」「カスタム」などから選択可能です。
スタート日時を指定し、必要に応じて終了日時も指定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706527/e08c793c-817f-7f34-a728-c410de8629c4.png)


## ステップ 2: クエリの実行先の設定
「宛先」セクションで、クエリ結果の保存先を指定します。新しいテーブル、既存のテーブルへの追加、またはテーブルの上書きなどが選択できます。
必要に応じて、宛先のテーブルに対する追加の設定（パーティショニング、クラスタリングなど）を行います。

## ステップ 3: 設定の確認とスケジュールされたクエリの作成
すべての設定を確認し、問題がなければ「スケジュール」ボタンをクリックします。
スケジュールされたクエリが作成され、指定したスケジュールに従って自動的に実行されるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1706527/02956f4d-ee49-1028-5852-fb1e261598b7.png)



## おわりに
BigQueryのスケジュールされたクエリ機能を使えば、手動でクエリを実行する手間を省き、データ分析の効率化を図ることができます。この機能を活用して、定期的なデータ処理や分析を自動化しましょう。

## 注意点
スケジュールされたクエリの実行には、Google Cloud Platformのリソースを使用しますので、料金が発生する可能性があります。料金については、Google Cloudの料金表を参照してください。
クエリのスケジュールや設定に誤りがあると、意図しない結果や料金の発生につながる可能性がありますので、設定は慎重に行ってください。
GitHubでissueを立ててdesktopからcommitする方法

修正したけど、いざコミットするときにどうやって連携していいかわからなかったのでメモ
mainにコミットしたくないのでGitHubでissueを立ててブランチを切り替えてからコミット

1. issueを作る
1. 右のDevelopment からcreate branchをクリックしてbranch名を変更。ブランチ名は「issue#XXX」とする
1. GitHubDesktop側でfetch
1. Current branchに「origin/issue#XXX」が出てくるので、選択
1. すると、Leave～とBring～と表示されるので、Bringを選択する
1. 普通にorigin/issue#XXXにコミット

共同外発者が居れば、確認してもらってmainへのmargeは託す。

mainにmargeされたらブランチをmainに戻すのを忘れずに。

参考
公式サイト
https://docs.github.com/ja/issues/tracking-your-work-with-issues/creating-a-branch-for-an-issue

ググって出てきたブログ
https://zenn.dev/ogakuzuko/articles/2250f7c7331106
QEum Luncharで、bootgrub.img

# 概要
QEum Luncharで、bootgrub.imgやってみた。
grubのコマンドラインに入って、memtestを実行した。

# 手順

- QEum Luncharで、bootgrub.imgを起動

![スクリーンショット 2024-03-08 132646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/eb61ef70-26f8-7a4e-a6aa-7c82055ed8b1.png)

- Cキーで、コマンドラインに入る
kernelを設定
bootで起動

```
grub> kernel (fd0)/boot/memtest.bin

grub> boot

```

![スクリーンショット 2024-03-08 132904.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/5df7bb02-6d64-7487-ef23-9cd9aedb5204.png)

- memtestが起動

![スクリーンショット 2024-03-08 132923.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/74fb450e-5996-f5c0-7ba1-baf46d77a3a4.png)

以上。
ora2pgのインストールから変換までを行う（Oracle→PostgreSQL）

# ora2pgとは
ora2pgとはOracleまたはMySQLからPostgreSQLへの移行を支援する移行ツールで、なんかいい感じに自動で型とか変換してくれるらしい。うれぴー

# 今回の目標
ora2pgを使ってOracleで使用していたテーブルやプロシージャを、PostgreSQLの形に変換できるようになることを目標とします。

ora2pgの実行に必要な下記3つのうち2つは既に用意してあるという前提のもと、Perlのインストールから始めます

- [x] Oracle稼働環境
- [x] PostgreSQL
- [ ] Perl（モジュールも含めて）のインストール

# 環境
・Windows10
・Oracle19c 32bit
・PostgreSQL 16.2

# Perlのインストール
まずはStrawberry Perl for Windowsをインストールします。64bitと32bitの2つがあるので、Oracleに合ったやつを選びましょう。
[Strawberry Perlのサイト](https://strawberryperl.com/)にアクセスしたら`ZIP, Portable, special editions`をクリック。でっけぇ🍓
ダウンロードリンク一覧ページに飛ぶので目的にあったものをRecommendeddownloadsの中からダウンロードします。今回はバージョン**5.32.1.1/32bitのMSIエディション**を選択。
bitはOracleに合わせ、バージョンは最新のものを選びました。


ダウンロードした`strawberry-perl-5.32.1.1-32bit.msi`をクリックするとインストーラーが起動するので「Next」を押して進みます。

次に「I accept the terms in the License Agreement」というチェックボックスが出てくるのでチェックを付けます。

次に、インストール先を指定します。今回はデフォルトのCドライブ直下に指定しました。最後に「Install」を押せばインストールが開始します。

インストールされているかの確認としてコマンドプロンプトに以下のコマンドを入力しましょう。
```
perl --version
```
バージョン情報が表示されればインストール作業は完了です。
```
This is perl 5, version 32, subversion 1 (v5.32.1) built for MSWin32-x86-multi-thread-64int
```

# 関連モジュールのインストール
スタートメニューから「Strawberry Perl」というフォルダを見つけて、中にある「CPAN Client」を起動します。

「install モジュール名」でモジュールをインストールできるので、CAPN上で以下のコマンドを入力しましょう
```
cpan> install DBI
cpan> install DBD::Oracle
```

# 環境変数の追加
Windowsの`設定`>`システム`>`詳細情報`>`システムの詳細設定`>`環境変数`で環境変数タブを開きます。「新規(N)」をクリックして環境変数を追加をします。

追加するパスはOracleのディレクトリの「\product\19.0.0\client_1」と、それから1つ下の層にあるlibです。もちろん人によって若干違うので注意。Oracleのパスが見つからないならOracle関連のソフトのプロパティの作業フォルダを見て探すといいかも。

| 変数 | 値 |
|:-:|:-:|
| ORACLE_HOME  | C:\app\client\Administrator\product\19.0.0\client_1 |
| LD_LIBRARY_PATH  | C:\app\client\Administrator\product\19.0.0\client_1\lib |

OKを押して設定を反映させることも忘れずに。

# ora2pgのインストール
[ora2pgの公式サイト](https://ora2pg.darold.net/index.html)に行くか[GitHubのページ](https://github.com/darold/ora2pg)に飛んでora2pgをインストールします。
 
最終的にora2pgのGitHubに移動したら、`<>Code`>`Download ZIP`でZIPファイルをダウンロードします。

ZIPファイルを適当な場所で展開して、解凍されたファイルをCドライブ直下に移動させた後、コマンドプロンプトで展開したディレクトリに移動してからperlを使ってインストールを行います。

```
cd C:\ora2pg       # パスは人それぞれ
perl Makefile.PL
gmake
gmake install
```

確認作業として以下のコマンドを入力しましょう。

```
ora2pg –version
```

バージョン情報が出力されればインストールは成功。
```
Ora2Pg v24.1
```

:::note warn
これ以降はずっと基本的にora2pgのディレクトリ上で作業を行いましょう
:::

# 設定
ora2pgのディレクトリに`ora2pg.conf.dist`というファイルがあるはずなので、コピーと名前変更で`ora2pg.conf`というファイルを作成しましょう。

:::note alert
`ora2pg.conf.dist`は変更や削除はしないで初期のまま残しておきましょう。（なのでコピーしてから名前変更をしている）
:::

ファイルを開いて中身を **移行元の環境** に合わせて編集しましょう。
ora2pgくんはこの設定ファイルの中身をみて変換作業を行います。

```
ORACLE_HOME [環境変数タブで追加したパス]
ORACLE_DSN dbi:Oracle:host=[ホスト名]:sid=[sid名]; port=[ポート番号]
ORACLE_USER [ユーザー名]
ORACLE_PWD [パスワード]
SHEMA [スキーマ名(大抵はユーザー名と同じ)]
TYPE [移行したいオブジェクトのタイプ]
```
TYPEに関してはファイル内に説明のコメントがあるのでそれを参考にキーワードを追加しましょう。

ora2pgのディレクトリ上で以下のコマンドを入力して接続確認を行います。

```
ora2pg -c ora2pg.conf -t SHOW_VERSION
```

バージョン情報が出力されればおｋ。

# 変換
以下のコマンドを入力します。

```
ora2pg -c ora2pg.conf
```

バーとパーセンテージが表示されるのでしばらく待ちましょう。
ディレクトリ直下に作成される`output.sql`というファイルが変換後のファイルです。

ちなみに
```
ora2pg -c [設定ファイルのパス] -o [変換後の.sqlの名前] -t [エクスポートタイプのキーワード]
```
とすると設定ファイルを弄らなくても変換後のファイル名やエクスポートするオブジェクトのタイプを変更できるので使えると便利！！
VBA 開発で使うコマンド一覧（自分用）

### VBAC（コードのバックアップ）
```
cscript vbac.wsf decombine
```
### Sphinx AutoBuild
```
sphinx-autobuild source build
```
---
### GIT コマンド
---

#### branchの確認
```
git branch
```
#### ブランチの新規作成
```
git checkout -b dev
```
#### ステージする
```
git add .
```

#### コミット(-m でコメントを追加する)
```
git commit -m
```

#### PUSH
```
git push -u origin HEAD
```

#### logの履歴（logから抜けるにはqで抜ける）
```
git log
```

#### 変更したファイル名を表示させる
```
git log --name-status
```
#### ファイル名を指定して検索する
```
src/XXXX.xlsm/Class3.cls
```

#### tagの付与
```
git tag -a V0.1 -m 'template'
```
#### tagのpush
```
git push origin V0.1
```
#### tag listの確認
```
git tag
```

#### タグの詳細を確認する
```
git tag -n
```
### Branchの削除
１）ブランチを確認し開発ブランチからmainブランチに切り替える
```
git branch
git checkout main
```
２）開発ブランチの削除（ローカルブランチの削除）
```
git branch -d dev
```
３）リモートブランチの削除
```
git push origin --delete dev
```
---
### PowerShell
---

#### ファイルやフォルダの削除（PATHかFile名を指定する）
```
Remove-Item
```
#### PowerShellやVSCODEのターミナルからぐぐる
```
Start-Process "chrome.exe" -ArgumentList "https://www.google.com/search?q=VBA Classとは"
```

---
#### スクリプトファイルを作成して関数を恒久化する
---
##### １）User\UserName直下にWindowsPowerShellがあるか確認
```
#ある場合（PSファイルが開かれる）
notepad $PROFILE
#ない場合（新規ファイル作成される）
New-Item -Path $PROFILE -Type File -Force
```
##### ２）スクリプトを追加する 
```
function og {
    param(
        [string]$keyword
    )
    $encodedKeyword = [uri]::EscapeDataString($keyword)
    $url = "https://www.google.com/search?q=$encodedKeyword"
    Start-Process "chrome.exe" -ArgumentList $url
}
```
##### ３）PowerShellを再起動し、動作確認する
```
og "Powershellとは？"
```
#### 拡張子を一括変更する(xlsx.ps1)
```
# Excel アプリケーションオブジェクトを作成
$excel = New-Object -ComObject Excel.Application
$excel.Visible = $false

# カレントディレクトリ内のすべての .xls ファイルを取得
$xlsFiles = Get-ChildItem -Path .\*.xls

# 各 .xls ファイルに対して処理を実行
foreach ($file in $xlsFiles) {
    $filePath = $file.FullName
    $newFilePath = $filePath -replace "\.xls$", ".xlsx"

    # ワークブックを開く
    $workbook = $excel.Workbooks.Open($filePath)

    # .xlsx 形式で保存
    $workbook.SaveAs($newFilePath, 51) # 51 は .xlsx 形式を意味する
    $workbook.Close()
}

# Excel アプリケーションを閉じる
$excel.Quit()

# COM オブジェクトのリリース
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($excel) | Out-Null
Remove-Variable excel
```
#### PS1ファイルの実行
```
.\ファイル名
```
FirebaseAuthエラー"INTERNAL ASSERTION FAILED: Pending promise was never set"

:::note warn 
**注記**
この記事の投稿者は初学者であり、自身の学習の備忘録目的で記事投稿を行なっております。
情報の正確さには最大限注意をしておりますが、もし誤り等がございましたらお知らせいただけますと幸いです。
:::
  
ご覧いただきありがとうございます！
 **Ito** と申します！
React初学者です。

ReactでのSPAアプリを作成中、`Firebase Authentication`を用いたユーザー認証機能を実装する際に**盛大に(?)** ハマってしまったので備忘録として残します。
 
## 動作環境
開発環境
 - React v.18.2.0
 - Webブラウザ: Google Chrome
 - サーバー:localhost接続

## エラーの詳細
### `INTERNAL ASSERTION FAILED: Pending promise was never set firebase`

  
![ba593a79c3e6e3cfd93af4153c692a04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3621297/95c26059-a045-dce1-5d0d-9a28bfc2883c.png)
### どのような時に発生するエラーか？
ポップアップを開いてGoogleアカウント認証を行う機能において、ポップアップを開いて認証を行った後に発生していました。
ポップアップには自分のGoogleアカウントは表示されているので、Firebase側との接続は問題なさそうに思えました。

ただ、ポップアップが開かれる際の挙動が怪しい...
認証用のポップアップがなぜか2つ開かれます。
### 調べた結果
Googleで検索するも、すでに[issueとして取り上げられて](https://github.com/firebase/firebase-js-sdk/issues/7093)おり、Closeしているようでした。
(このケースでは、FireFoxを使っている場合に発生するような記述あり。流し読みなので間違えてたらすみません🙇)

## ファイル構成
##### Firebase設定用ファイル
(公式ドキュメント通り)
```js:src/firebase.js
import { initializeApp } from "firebase/app";
import { getAuth, GoogleAuthProvider } from "firebase/auth";
import { getFirestore } from "firebase/firestore";

const firebaseConfig = {
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
};

const app = initializeApp(firebaseConfig);
const auth = getAuth(app);
const provider = new GoogleAuthProvider();
const db = getFirestore(app);

export { auth, provider, db }
```

##### ポップアップ認証用ファイル
(こちらもほぼ公式ドキュメント通り)
```jsx:src/components/AuthGoogleSIgninPopup.jsx
import { signInWithPopup } from "firebase/auth";
import { auth, provider } from "./firebase";

const AuthGoogleSIgninPopup = () => {
  signInWithPopup(auth, provider)
  .then((result) => {
    const user = result.user;
    console.log(result)
  }).catch((error) => {
    const errorCode = error.code;
    const errorMessage = error.message;
  });
};

export default AuthGoogleSIgninPopup;
```
##### `App.js`

```jsx:App.js
// ...省略
export default function App() {
  return (
    <Router>
      <Routes>
        <Route path="/login" element={<AuthGoogleSIgninPopup />} /> 
      </Routes>
    </Router>
  );
};
```

上記の通り、ポップアップ認証用ファイルをコンポーネントとしてエクスポートし、
ユーザーが`/login`パスにアクセスした際、コンポーネントとして読み込むようにしていました。

## こう解決した
ポップアップ認証用ファイルをコンポーネントとして読み込むのではなく、**`onClick`で関数として呼び出す**ように修正すると正常に認証されました！
```jsx:src/components/Header.jsx
<SigninButton onClick={() => AuthGoogleSIgninPopup()}>Sign In</SigninButton>
```

## 振り返り
**「自分のドキュメント読解力が未熟なだけで、こんな間違いは誰もしないのでは・・・？」**
という疑念も頭をよぎりましたが、誰かのお役に立てれば幸いです。
お読みいただきありがとうございました🙇
Android Studio New ProjectでGoogle Maps Activityが出ない時の出し方

【環境|バージョン】
android studio：giraffe 2022.3.1
mac os：sonoma 14.1

2023年秋頃から、Android Studioで新規プロジェクトを作る際、
Activityテンプレートを選ぶ画面に**Google Maps Activity**が出なくなりました。
この場合の**Google Maps Activity** （Google Maps Vews Activity）の選択経路を以下に記します。


【経路：1】
画面上部のFileメニューから以下画像のとおり、
File ➡ New ➡ Activity ➡ Gallery
で以下が現れ**Google Maps Activity**が現れます。

☝の他、以下でも。
【経路：2】
画面左端の
Android ➡ app ➡ Res ➡ Value ➡ New ➡ Activity ➡ Gallery


【経路：3】
Android ➡ app ➡ Res ➡ Value ➡ New ➡ Googleから、Google Maps Views Activity
を選択できます。


初めてAndroid Studioを使う人など、ご参考になれば幸いです。