OmniAICreator/Qiita-1.07M huggingface dataset:
gitのコミット回数をUnityのバージョン値に埋め込む方法

# 対象とする方

- 自動ビルド環境がある　and
- コミットのたびに自動ビルドしたい and
- ビルドごとに違うバージョンにしたい

# はじめに

コミットのたびに自動ビルドしたい場合、同じバージョン値のアプリを量産してしまったらカオスです。でも都度アプリケーションのバージョン値を変更してコミットするのは非常に手間です。なので、SubversionでいうリビジョンIDみたいなものをバージョン値の３桁目に埋め込みたいわけです。
しかしながらgitではリビジョンIDではなくハッシュです。これは１６進数だし数値も時系列ごとに大きくなりません。ということで、この記事ではリビジョンIDの代わりにコミットした数を取得する方法と、それを埋め込むシェルスクリプトについて解説します。

# コミットした数を取得する

これは簡単に、git logで出てきた行数をコミットした数とします。

``` sh
# コミット回数を取得
count=`git log --one-line | wc -l`
```

ただし、この方法はブランチ同士では同じ番号になることがある点に注意が必要です。Unityゲーム開発の現場ではコンフリクトすると面倒なので、あまり複雑なブランチ管理をしていることは少ないと思いますが、そういう現場では注意しましょう。

# コミットした数をバージョン値に埋め込む

私の好みですが、 `メジャーバージョン.マイナーバージョン.コミットした数` になるように３桁目を書き換えるシェルスクリプトを作ります。この時メジャーバージョンとマイナーバージョンはコミットされた値がそのまま使われるようにします。

``` sh
# メジャー、マイナーバージョンを取得
set $(grep bundleVersion ProjectSettings/ProjectSettings.asset | sed 's/\./ /g')
major=${2}
minor=${3}

# 新しいバージョン値をUnityの設定ファイルに書き込む
version=$major.$minor.$count
gsed -ri "s/(bundleVersion: ).*$/\1$version/" ProjectSettings/ProjectSettings.asset
```

# 作成したスクリプト全体

``` sh
# コミット回数を取得
count=`git log --one-line | wc -l`

# メジャー、マイナーバージョンを取得
set $(grep bundleVersion ProjectSettings/ProjectSettings.asset | sed 's/\./ /g')
major=${2}
minor=${3}

# 新しいバージョン値をUnityの設定ファイルに書き込む
version=$major.$minor.$count
gsed -ri "s/(bundleVersion: ).*$/\1$version/" ProjectSettings/ProjectSettings.asset
```

上記はgnu版のsedを使っているので、別途`brew install gsed`などでインストールを行なってください。
Jenkinsの`シェルの実行`などにこのスクリプトを仕込んでください。

# メリットとデメリット

この方法を使うことで発生するメリットとデメリットをまとめます。

## メリット

- 自動的に作られたバイナリに一意のバージョンが付く
- どのコミットをビルドしたものかがバージョン値から特定できる

## デメリット

- リポジトリの内容から修正されたものがビルドされるのが気持ち悪い

# さいごに

私はこの方法が気に入っていますが、他の方法としてはゲーム画面内にアプリ情報を表示するエリアを作って、そこにコミットハッシュ値を表示させる、といった方法もアリだと思います。この方法の場合ブランチの区別も付く点が優れていますが、アプリケーションを起動しないと情報が得られない点がデメリットです。

他に、もっと業界標準的なやり方などご存知の方がいらっしゃいましたら是非コメント欄で教えてください。ありがとうございました。
テンプレ容量(51,200 バイト)を超えた「cloudformation deploy」実行方法について

## はじめに
Cloudformation (以下Cfn)のテンプレファイルをCLIコマンドでデプロイする時に
は「cloudformation deploy」が使用候補となると思います。

このコマンドはローカルに存在するファイルが51200バイトを超えると、
ローカルからデプロイができない仕様があります。

本記事は上記容量を超過したテンプレファイルをデプロイする方法探し、見つけるまでの悩みの経緯記載した記事となります。

## 結論
オプションコマンドとS3を経由することで「cloudformation deploy」の実行が可能

■コマンド例
```bash
aws cloudformation deploy --s3-bucket {S3バケット名} --template-file {ローカルに存在するテンプレファイルパス} --stack-name {スタック名}
```


## 確認経緯
### 導入
私：以下コマンドを使ってローカルにあるCfnテンプレートをデプロイしたいけどファイルサイズが上限を超えてエラーになる。。
テンプレテートを分割して2回に分けてデプロイするしかないか。。

```bash
aws cloudformation deploy --template-file {ローカルに存在するテンプレファイルパス} --stack-name {スタック名}
```

### ①「とりあえず検索」
私：同じ悩みを持つ人いないかググったら開発者に機能リクエストしてる人がいたわ、、
最後の回答でオプション「--s3-bucket」を使えば解消できたって書かれてるし単純にオプション付与で行けるっぽいのかな
[Allow aws cloudformation deploy to use template-url #2461](
https://github.com/aws/aws-cli/issues/2461)

### ②「AWS CLIリファレンスの確認」
私：そうなら[AWS CLIリファレンス](https://docs.aws.amazon.com/cli/latest/reference/cloudformation/deploy/index.html)から確認やな!
解消済みの要望みたいだし「--s3-bucket」オプション探そ!!

> --s3-bucket (string) The name of the S3 bucket where this command uploads your CloudFormation template. This is required the deployments of templates sized greater than 51,200 bytes

■和訳
> --s3-bucket(文字列) このコマンドが CloudFormation テンプレートをアップロードする S3 バケットの名前。これは、51,200 バイトを超えるサイズのテンプレートのデプロイメントに必要です

私：あった！「アップロードするS3バケット」って表記は謎だけど、
予め格納されたテンプレファイルを指定するオプションって感じなのかな？
つまりは、格納先のバケットポリシーや実行元のIAMロールに気を付けつつ↓ならOKってことか!

```bash
aws cloudformation deploy --s3-bucket {S3バケット名orARN} --template-file {S3に格納したテンプレファイル名} --stack-name {スタック名}
```
■出力結果

:::note alert
Invalid template path {指定先S3の情報}
:::

私：うーん、、権限回りもNW周りも見直したけど問題なさそうだし、
そもそも同じようなコマンド書いてる人が見つからないな、、

私：もう一回リファレンスを見直してみよう
> --s3-bucket (string) The name of the S3 bucket where this command uploads your CloudFormation template. This is required the deployments of templates sized greater than 51,200 bytes

> --s3-prefix (string) A prefix name that the command adds to the artifacts' name when it uploads them to the S3 bucket. The prefix name is a path name (folder name) for the S3 bucket.


■和訳
> --s3-bucket(文字列) このコマンドが CloudFormation テンプレートをアップロードする S3 バケットの名前。これは、51,200 バイトを超えるサイズのテンプレートのデプロイメントに必要です

> --s3-prefix(文字列) コマンドがアーティファクトを S3 バケットにアップロードするときにアーティファクトの名前に追加するプレフィックス名。プレフィックス名はS3バケットのパス名(フォルダー名)です。

私：**「テンプレートをアップロードする S3 バケットの名前」** ってもしかして
コマンド実行時にローカルからS3にアップロードしてそのままデプロイされるってこと？
※今までの認識：S3に事前にテンプレを格納しておき、CLIコマンドでS3とS3に格納されたテンプレファイルを指定しデプロイ
　新しい認識：ローカルに格納しているテンプレファイルを格納するS3をCLIコマンドで指定し、そのままデプロイ

### ③「コマンド修正の上、再度実行」
私：そうならこんな感じのコマンドかな

```bash
aws cloudformation deploy --s3-bucket {S3バケット名} --template-file {ローカルに存在するテンプレファイルパス} --stack-name {スタック名}
```
■出力結果

:::note info
成功!!
:::

私：ついでにS3内に格納されるテンプレファイルのプレフィックスを指定したい場合は、↓ってことかな
```bash
aws cloudformation deploy --s3-bucket {S3バケット名} --s3-prefix {格納先S3バケット内プレフィックス} --template-file {ローカルに存在するテンプレファイルパス} --stack-name {スタック名}
```

### 終わりに
どうせこんな作りでしょ？っていう考え方が邪魔して悩んでいました。
技術力も大事ですが、記載内容を理解する語学力のなさを痛感していました。

本記事が同じようにハマっている人の助けになれば幸いです。
pandasの使い方 〜Python〜

Pythonは読みやすく・書きやすく・理解しやすい言語です（なので私は好きです）
ライブラリが豊富で、他の言語だと数行書かないといけないところをPythonだと1行で同じ処理を書くことができます

例えばJavaと比較すると
```java:main.java
int[] numbers = {1, 2, 3, 4, 5};
for (int i = 0; i < numbers.length; i++) {
    numbers[i] = numbers[i] * 2;
}
for (int number : numbers) {
    System.out.println(number);
}
```

```python:app.py
numbers = [1, 2, 3, 4, 5]
numbers = [x * 2 for x in numbers]
print(numbers)
```
javaとPythonのそれぞれで配列の中の数字を2倍にする処理を作成する処理を作成しました。
Javaだと2倍にする処理をfor文で3行で書いていますが、Pythonだと1行で書けます

このようにシンプル差がPythonの良いところです

また、Pandasはデータ分析、操作できるライブラリです
今回はPandasを使用する時に、よく使われる処理を10個ご紹介します
チートシートとして参考にしてください

pandasをimportするコードです
```python
import pandas as pd
```

# 1.CSVを読み込む
CSVファイルを読み取りDataFrame型の変数に格納します
```python
df = pd.read_csv('data.csv')
```

# 2.NULL値を含む列を削除します
```python
df.drop(df.columns[df.isnull().sum() > 0], axis=1, inplace=True)
```
isnull()でDataFrame内の各要素に欠損値(NULL値)があるか判定します
その後のsum()で欠損値の個数を計算します
axis=1で列方向（縦)に削除するように設定しています
axis=0で行方向(横)に指定できます

# 3.既存の列を基に新しい列を作成
```python
f['new_col'] = df.apply(lambda x: x['col_1'] * x['col_2'], axis=1)
```
apply()で各行に対してデータ操作を行う設定をします
lambda式で'col_1'と'col_2'の掛け算処理しています

# 4.列のグループ化と平均の計算
```python
df.groupby('col_1').mean()
```
groupbyでグループ化します
mean()で平均値を取得します

# 5.条件を満たす行を取得
```python
df.loc[df['col_1'] == 'abc']
```
locを使い、列'col_1'が'abc'の列を取得します

# 6.並べ替え
```python
df.sort_values(by='col_name', ascending=False)
```
sort_valuesでソート処理を行います
byにソート基準の列を設定します
ascending=Falseで降順にソートします（大→小)
ascending=Trueで昇順にソートできます(小→大)

# 7.欠損している要素に0を設定
```python
df.fillna(0)
```
NaNやNULL値の欠損している要素を0埋めします

# 8.重複行を削除
```python
df.drop_duplicates()
```

# 9.ピボットテーブルを作成
```python
df.pivot_table(index='col_1', columns='col_2', values='col_3')
```
例えば、ピボットテーブルを作成し、平均値で集計します
```python:pivot.py
data = {
    'col_1': ['A', 'A', 'B', 'B', 'A', 'B'],
    'col_2': ['X', 'Y', 'X', 'Y', 'X', 'Y'],
    'col_3': [10, 20, 30, 40, 50, 60]
}

df = pd.DataFrame(data)

# ピボットテーブルを作成して表示
pivot_table = df.pivot_table(index='col_1', columns='col_2', values='col_3')
print(pivot_table)
# 出力結果
#col_1/col_2   X   Y
#A            30  20
#B            45  40
```
appfuncを設定することで合計(sum)、最小(min)、最大(max)で集計できます
```python
pivot_table = df.pivot_table(index='col_1', columns='col_2', values='col_3', appfunc=sum)
```

# 10.CSVファイルに保存
```
df.to_csv('data.csv', index=False)
```
【Chrome】ショートカットで日本語と英語原文を切り替える

## はじめに

https://qiita.com/nkmr_jp/items/74c46efe00608d3e9fb2

https://sttk3.com/blog/tips/toggle-translate.html

上記の様な記事をWindowsで対応しようと思い、  
今回の記事を作成しました。

## 実際に出来る様になったこと

以下が実際に出来る様になった動作です。  
![last.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1718976/244689cc-09d2-5e9c-b561-185e574e6c26.gif)

マウスを細かく動かさなくても、  
簡単に翻訳切替ができ、ショートカットで文章を読み進める事が出来ます。

PC環境にも依りますが、連続で切り替えても違和感がありません。
![Animation.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1718976/eeffc053-d922-253f-1631-60e6a1dc0583.gif)
(稀に切替えができないこともあります。)

## 対応方法

1. [キーのマクロ実行機能がある、ツールを入れる](https://qiita.com/kyosinari/items/740cd1825a8d8c9a966d#%E3%82%AD%E3%83%BC%E3%81%AE%E3%83%9E%E3%82%AF%E3%83%AD%E5%AE%9F%E8%A1%8C%E6%A9%9F%E8%83%BD%E3%81%8C%E3%81%82%E3%82%8B%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B)
2. [一連のキーを登録する](https://qiita.com/kyosinari/items/740cd1825a8d8c9a966d#%E4%B8%80%E9%80%A3%E3%81%AE%E3%82%AD%E3%83%BC%E3%82%92%E7%99%BB%E9%8C%B2%E3%81%99%E3%82%8B)
3. [拡張機能のショートカット設定](https://qiita.com/kyosinari/items/740cd1825a8d8c9a966d#%E6%8B%A1%E5%BC%B5%E6%A9%9F%E8%83%BD%E3%81%AE%E3%82%B7%E3%83%A7%E3%83%BC%E3%83%88%E3%82%AB%E3%83%83%E3%83%88%E8%A8%AD%E5%AE%9A)

### キーのマクロ実行機能がある、ツールを入れる

今回は諸事情あって以下のアプリにしました。  
[X Button Maker](https://apps.microsoft.com/store/detail/x-button-maker/9N410HXFTRHB?hl=ja-jp&gl=jp)  

簡単で便利なのでオススメですが、  
「特定のキーを押すと、一連のキー入力を実行できる」  
機能を持ったツールなら何でもいいです。  

そういったツールが無い場合はこの際入れることを推奨します。  
無変換キーなど使用していないキーを活用できます。

### 一連のキーを登録する

今回登録するキーは以下の通りです。

1. Shif + F10 (右クリックメニュー表示)
2. T (日本語に翻訳)
3. Enter (翻訳言語の切替)
4. Esc (メニューを閉じる)

上記の一連の入力を特定のショートカットキーに割り当てます。  
割り当てるショートカットキーはなんでもいいです。  
今回はCtrl + Spaceにします。

**X Button Maker**での登録方法は以下です。
![登録.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1718976/60fc5d06-be7d-f731-9ee6-91390c5964b5.gif)

注意点は遅延時間を1ms以上に設定しなければならない点です。  
遅延設定をしないと、同時にキーを入力する扱いになります。  
動作の重いPCではキーの遅延時間を10msくらいで設定してください。  

また、「Ctrl + SpaceはVSCodeのオートコンプリート機能で使用しているよ～」  
という方は、chrome.exeのみでショートカットを設定する機能もあるので、  
そちらでキー登録してください。もちろん別のキーでも可能です。

### 拡張機能のショートカット設定

最後に選択した特定の文のみショートカットで翻訳する機能についてです。

まずは[Google翻訳の拡張機能](https://chrome.google.com/webstore/detail/google-translate/aapbdbdomjkkjkaonfhkkikfgjllcleb?hl=ja)を入れましょう。  
(この記事を見てる人は恐らく入っているはず。。)

次に以下の画像の番号の手順で拡張機能のショートカットを設定してください。
![2023-08-04_12h39_05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1718976/6e43a9f3-758e-131e-46d2-3761d44dccdf.png)

今回はCtrl + HにGoogle翻訳を設定しました。
これで文字を選択してCtrl + Hを入力すると、翻訳が表示されます。

他の拡張機能としてDeeple翻訳の方が精度等は良いですが、
一部機能が有料なので自分の好きな方で良いかと思います。

## 終わりに

Chrome拡張機能を作成してみようかな～  
と思っていたところ、既存のアプリのみで解決できました。  
コードを書かないに越したことは無いので。  

参考にしてください。
Javaで「「.」や「..」などのパスの中の冗長な部分を取り除く(Path.normalize)」の動作を確認してみた

# 概要
Javaで「「.」や「..」などのパスの中の冗長な部分を取り除く(Path.normalize)」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/file/index15.html

# 実装
以下のファイルを作成しました。
```JSample15_1.java
import java.nio.file.Path;
import java.nio.file.Paths;

class JSample15_1{
  public static void main(String[] args){
    Path p1 = Paths.get("./doc/report.txt");
    Path p2 = Paths.get("C:/document/doc/../pdf");

    System.out.println(p1 + " -> " + p1.normalize());
    System.out.println(p2 + " -> " + p2.normalize());
  }
}
```
以下のコマンドを実行しました。
```
$ javac JSample15_1.java 
$ java JSample15_1 
./doc/report.txt -> doc/report.txt
C:/document/doc/../pdf -> C:/document/pdf
```

# まとめ
何かの役に立てばと。
[自己解決] eclipseでJava標準APIのメソッドにステップインできるのはなぜなのか？

# 疑問

eclipseでJavaを書いてデバッグをしているとき、自前で書いたメソッドだけではなく、標準APIのメソッドにもステップインしてソースコードを表示させることができます。
たとえば、println()にステップインすると、PrintStream.classという**クラスファイル**が開かれて、println()の実装が確認できます。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150194/a4f80e09-c622-eda4-fc08-e40f20eac1b8.png)

**いやしかし、クラスファイルって.javaファイルをコンパイルしたものだから人が読める形式ではないんじゃないの？** なんでソースコードが見れるの？ もしかしてクラスファイルってテキストエディタとかでも開いて読める？

この時点で知っていたこと:
- .javaファイルをコンパイルすると.classファイルができる。JVMはクラスファイルを実行している。
- Javaではクラスはパッケージで管理され、パッケージはモジュールで束ねられる。
- 標準APIに対応するモジュールはjava.baseでこいつはJDKに付いてくる（また勝手にrequires指定されるからコード書くときに標準APIを使える）
- なのでPrintStream.classはjava.baseモジュールのどこかに居る。

というわけで、エクスプローラからJDKのフォルダ配下にあるjmodsフォルダの中のjava.base.jmodを引っ張ってきて展開してみました。classes > java > ioとたどるとPrintStream.classが見つかりました。
試しにテキストエディタで開いてみると、なんか読める箇所もあるし読めない箇所もある感じでした。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150194/22e447a4-f4b7-483e-ed6f-210e36a545a5.png)

はて、ではなんでeclipse上だと読める形で表示されるのか。


# eclipseが気を利かせてJavaの逆コンパイラを実行してくれていたから

いろいろググった結果、
- クラスファイルはJavaバイトコードと呼ばれる形式である。
- これは逆コンパイラを通すと（ある程度まで）ソースコードに復元することができる。
- eclipseにはプラグインとして逆コンパイラが搭載されている。

ということがわかりました。なるほど。

実際、eclipseのパッケージエクスプローラからJREシステムライブラリー > java.base > java > io > PrintStream.class とたどり、右クリック > 次でクラスを開く を選択すると逆コンパイラと思われる一覧が現れました。
![003_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150194/30123238-6f65-d27f-a21a-b216b0836df4.png)

その中の1つであるCFRを選んで開くと、冒頭でステップインしたときと同様にPrintStream.classを読める形で表示させることができました。ステップインしたときに裏で逆コンパイラをかませてくれていたのね。

というか、ヒントは1枚目の図の中にあったわ。
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150194/c98bbb0b-0f7a-2b4f-a58d-f547b2074bed.png)



# おまけ

逆コンパイラ云々とは別の話として、標準APIについてはソースコード（.javaファイル）もJDKに同梱されているようです。
JDKのフォルダ配下のlib > src.zip を展開したものがそれのようで、PrintStream.classに対応する.javaファイルは、この中の java.base > java > io > PrintStream.java に見つけました。

chatGPTに聞いたところ、
> 標準APIのソースコードが配布されているのは、開発者がデバッグやソースコードの参照を容易にするための便利さを提供するためです。

ということでした。1次ソースは見つけられなかったけど、さもありなんという理由なので納得することにしました。


# 参考
https://qiita.com/chenglin/items/aba81c9429a6cb979218
#0012 pythonの予約語

##　はじめに

> 予約語とは、プログラミング言語などの人工言語の仕様に定められている、開発者が付ける識別名として利用できない文字列のこと。予約語に挙げられた単語やフレーズは変数名や関数名などに使用することはできない。


[参照](https://e-words.jp/w/%E4%BA%88%E7%B4%84%E8%AA%9E.html)

## pythonで予約語の確認

```
Python 3.11.4 

>>> import keyword

>>> len(keyword.kwlist)
35

>>> print( *keyword.kwlist, sep="\n" )
False
None
True
and
as
assert
async 
await
break
class
continue
def
del
elif
else
except
finally
for
from
global
if
import
in
is
lambda
nonlocal
not
or
pass
raise
return
try
while
with
yield
```

## 終わりに
- 馴染みのない予約語 -> 調べよう。
    - async
    - nonlocal
    - yield
この稿は書きかけです。順次追記します。

SNS類に記事を書くと、いろいろ文句が飛んでくる。　
前提として完全性を求める意見がある。

完全性を追求していないことを記載するのを忘れていた。
これが最初の失敗だった。

そこで、改めることにした。

<この稿は書きかけです。順次追記します。>

https://researchmap.jp/blogs/blog_entries/view/78451/5495747b046415166866e379c7b9e47a


<この稿は書きかけです。順次追記します。>
という行を，なるべくすべての書き込みにするようにしています。
その背景と経緯を記録します。

Qiitaでは、次の表記にしています。
 ＜この記事は書きかけです。順次追記します。＞
 This article is not completed. I will add some words in order.


## 1　プログラムを書きなぐる。
設計，仕様を言語で書く時も，図で書く時も，自分の思いついたことをまず書きなぐります。それを翻訳（compile)すると文法誤りが出ます。その言語規則に合ったように書き直します。文法誤りがなくなっても，動作，証明できないことがあります。意味誤りがあるのかもしれません。

## 2　文章を書きなぐる
文章もプログラムと同じで，思いついたところから書き始めます。起承転結は考慮していません。
日本語で書く時は，文法誤りを検査する道具をほとんど使っていないので，しばしば意味不明な文章を書きます。

## 3　まず保存
まず読みなおしてから上げればいいのですが，researchmap.jpでは読みなおしていて，アップしようとすると，時間が経過していて，消えてしまうシステムになっています。そのため，まず「決定」します。

## 4　まず送信
決定して読みなおしてからfacebook, twitterにURLを送れば良いのですが，読みなおしていると別の用事が入って，書いたことを忘れて，永久にURLを送らなくなってしまいます。
fとtの釦を使って，facebook, twitterにURLを送ります。

## 5　書き直す
facebookで「いいね」を押していただいたり，ご意見をいただいたら，その方の名前を拝見し，その方の視点で読みなおします。そうすると，意味不明なところ，論理展開が解りにくいところ，誤字脱字に気が付きます。そこで書き直します。その時に，
<この稿は書きかけです。順次追記します。>
という行を追加します。

本当の書きかけのものには，
<この稿は書きかけです。順次追記します。>
の行が入っていない確率が高い。

<この稿は書きかけです。順次追記します。>

ps.
researchmap.jpには一時保存という仕組みがあるようです。一時保存したものは二度と読まないので，使わないようにしています。

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong. 

# 参考資料　

出力(output)と呼ばないで。これは状態(state)です。

https://qiita.com/kaizen_nagoya/items/80b8b5913b2748867840
# 文書履歴(document history)
ver. 0.01 初稿　　20230814
ver. 0.02 ありがとう追記　　20230814

### 最後までおよみいただきありがとうございました。

いいね　💚、フォローをお願いします。

####  Thank you very much for reading to the last sentence.

Please press the like icon 💚　and follow me for your happy life.
【Android】Chip使用時にIllegalStateExceptionでクラッシュする問題の対処法

# はじめに
最近古いプロジェクトのブラッシュアップをお手伝いすることが多いのですが、その際にChipを使用していてクラッシュしてしまうことがありました。
本日はこちらに関して備忘録的にまとめておこうと思います。

# クラッシュの対処法
まず、エラーのログは以下になります。

```
Binary XML file line #xx in xxxx/: Binary XML file line #xx in xxxx.debug:layout/view_chip: Error inflating class com.google.android.material.chip.Chip

java.lang.IllegalStateException: Fragment already added: XXXXFragment{33e975e}

```
エラーの詳細は以上です。
IllegalStateExceptionに目が行きがちですが、重要なのは上部のxmlに関してのエラー文になります。

こちらエラーからは原因が全くわからずですが、、、。
原因はthemeを設定していないことが原因です、以下を各種Chipに設定してあげることで、解消可能です。

```
android:theme="@style/Theme.MaterialComponents.Light"
```

以上になります。

# さいごに
エラーから詳細を拾えない系の不具合は少々しんどいですよね。
ライブラリバージョンを上げたタイミング等でこういった問題が起きやすい印象ですが、また似たようなことがあればまとめておこうと思います。
ABC313回答メモ

0.はじめに
　コンテスト予選ということで難しい問題という先入観が
　強すぎてA問題のみ正解という惨憺たる結果に。
　翌日やり直してみると、BC問題も普通に解けたであろうと
　いうことに気づき、惜しいことをしました。

　レートは-41と急落・・・。

1.A - To Be Saikyo
　入力されたリストから、2項目以降を切り出したリストBを作成。
　リストBの最大値より、リストAの1番目の数値が大きければそのまま
　リストAの1番目の数値を出力
　リストAの1番目の数値がリストBの最大値以下の場合
　リストBの最大値から、リストAの1番目の数値を減算した
　数値に１を加算して出力。


　https://atcoder.jp/contests/abc313/submissions/44260632

2.B - Who is Saikyo?
　問題を勘違いして、すべての値の順序を求めるために
　四苦八苦していて時間切れとなりました。
　
　翌日見返してみると、最強だけ求めればよいことに気づき
　（回答の出力を考えればそれはそうとなりますが・・・。）
　ACとなりました。

　【元の考え方】
　　M組の勝敗のうち、だれにも勝てない人(N位の人)が
　　一人に決まるかを検索。
　　一人に決まらなければ、-1を出力して終了
　　一人に決まったら、M組からN位が弱い情報を
　　省いて、だれにも勝てない人(N-1位の人)が
　　一人に決まるかを検索・・・と続けていき、1位までを
　　求める
　　　→問題として、全員の順位が一意に決まる情報が
　　　　提供されないためWA

　【ACとなった考え方】
　　M組の勝敗のうち、だれにも負けない人(1位の人)が
　　一人に決まるかを検索
　　一人に決まらなければ-1を出力して終了
　　一人に決まるのであればその人を出力して終了


　https://atcoder.jp/contests/abc313/submissions/44319556

3.C - Approximate Equalization 2
　試験中に一回提出しましたがWAとなり、B問題に戻ってしまったので
　正解できませんでしたが、翌日見直したところWAはちょっとした
　バグのせいだったので、もう少し粘れば・・・と悔やまれました。

　【考え方】
　　リストAの合計をNで割った(切り捨て)値を基準値AAとし
　　リストAの合計をNで割った余りを基準値を超える個数AMとした場合
　　最終的にリストAの値は、AM個のAA+1とN-AM個のAAとなる。

　【実装】
　　1)リストAの合計をNで割った(切り捨て)値AAを求める
　　2)リストAの合計をNで割った余りAMを求める
　　3)リストAを降順に並べる
　　4)ans=0を定義
　　5)以下インデックスiでN回ループ
　　　5-1)AMが1以上の時、変数CAA＝AA+1
　　　5-2)AMが0以下の時、変数CAA＝AA
　　　5-3)ansにA[i]-CAAの絶対値を加算
　　　5-4)AMから1マイナス
　　6)ansを2で割った値を出力して終了
　　
　【補足】
　　最初に実装した際、3)のソートを昇順に並べてしまったのと
　　5-4のAMから1マイナスする部分が抜けていたため
　　WAとなってしまいました。


　https://atcoder.jp/contests/abc313/submissions/44319691


以上
「Raspberry Pi Pico W」のC/C++開発環境で最低限必要なモノ（Windows）

「Raspberry Pi Pico W」のC/C++開発環境を作る時、[ここ](https://www.raspberrypi.com/documentation/microcontrollers/c_sdk.html#sdk-setup)の"getting started"を見ながら構築していくと思う。
「Chapter 9. Building on other platforms」の「9.2. Building on MS Windows」に、「Windows Pico Installer」が準備され、とても環境構築が楽になったのだが、VS codeを立ち上げるのも、Raspberry Pi Pico SDK から立ち上げなければならなかったり、なんとなく不満。

さらに、「Pico W」だと、「-DPICO_BOARD=pico_w」をつけてcmakeしなければならないのだが、VS Codeでポチっとやりたいのに、そうもいかない。（やり方あるのかもしれないが、、、）
そもそも、「Pico W」は付いているLEDのポートが「Pico」と違うので、最初のLチカでつまずいた。。orz

さらに、「pico-examples」がやたらと大きい。いろんなものがパッケージ化されているからなのだが、じゃあ独自のプロジェクトを作る時はどうすればいいんだよ！って。

そんな、しょうもない不満を持っている方に向けて本記事を書いてみた。
ゴールとしては、「VS Codeを立ち上げてコンパイルできる、最低限（？）必要な組み合わせを提供する」ことである。

# インストール
"getting started"の「Chapter 9. Building on other platforms」の「9.2. Building on MS Windows」に従い、「Windows Pico Installer」をインストールする。

# サンプルプロジェクト
「pico-examples」の中にある、「pico w」向けLチカコードをコンパイルするプロジェクトを作成してみる。フォルダやファイルは以下のように配置していることを想定。[Github](https://github.com/GaneshaShiisa/pico_w-example-blink)に自分が作ったものを置いておく。
```txt:フォルダ構造
pico_w-example-blink/
├─ CMakeLists.txt
├─ pico_sdk_import.cmake
└─ src/
    ├─ CMakeLists.txt
    └─ picow_blink.c
pico-sdk/
```

## CMakeLists
「-DPICO_BOARD=pico_w」やら、「setx PICO_SDK_PATH "..\..\pico-sdk"」は、CMakeListsでsetを使って定義すれば解決できることが分かった。
ぶっちゃけ、設定で特筆すべきことはこれだけ。
```cmake:pico_w-example-blink/CMakeLists.txt
cmake_minimum_required(VERSION 3.12)

# ここがポイント
set(PICO_SDK_PATH "C:/Program Files/Raspberry Pi/Pico SDK v1.5.0/pico-sdk")
set(PICO_BOARD "pico_w")

# Pull in SDK (must be before project)
include(pico_sdk_import.cmake)

# set the project name
project(picow_blink)

set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)

# Initialize the SDK
pico_sdk_init()

# Subdirectory
add_subdirectory(src)
```

```cmake:pico_w-example-blink/src/CMakeLists.txt
add_executable(picow_blink
        picow_blink.c
)

target_link_libraries(picow_blink
        pico_stdlib # for core functionality
        pico_cyw43_arch_none # we need Wifi to access the GPIO, but we don't need anything else
)

# enable usb output, disable uart output
pico_enable_stdio_usb(picow_blink 1)
pico_enable_stdio_uart(picow_blink 0)

# create map/bin/hex file etc.
pico_add_extra_outputs(picow_blink)
```

# コンパイル
VS CodeのExtensionsで、「CMake」あたりをインストールしてあれば、VS Codeの下のバーがこんな感じになっていると思われる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118796/110378b6-695b-f550-ce26-4b11d84a7173.png)
「スパナマーク（？）」を押して、使うコンパイラを設定する。「GCC 10.3.1 arm-none-eabi」を設定する。「Scan for kits」をすれば出てくるはず。
コンパイルするには、その横にある「ギア（？）Build」を押せばOK。

# まとめ
CMAKEファイルに、
```CMAKE
set(PICO_SDK_PATH "C:/Program Files/Raspberry Pi/Pico SDK v1.5.0/pico-sdk")
set(PICO_BOARD "pico_w")
```
を書いてあげると、マニュアルに書いてある「Pico - Visual Studio Code」ショートカットをでVScodeを立ち上げなくてもコンパイルできた。
満足
python 環境構築

**Anacondaを使わずに**VSCodeでpythonを使用する環境をつくったので
備忘録としてやり方のざっくりとしたまとめをここに書いておきます。
（素人が拾ってきた情報まとめてきただけですが、、）
ちなみにOSは**Windows 11**です。

## Pythonインストール方法
**1. [このページ](https://www.python.org/downloads/)からPythonのインストールファイルをダウンロード&実行**

**2. Pathを通す(インストール時に「Pathを通す」にチェックをつければ自動でPath設定はやってくれる)**

Python.exeはC:\Users\<ユーザー名>\AppData\Local\Programs\Python\Python311に、pipはC:\Users\<ユーザー名>\AppData\Local\Programs\Python\Python311\Scriptsに格納されているので、それぞれ
コントロールパネル>システムとセキュリティ>システム>詳細設定>環境変数からPathを選択、編集ボタンを押して新規Pathを追加する。

**3. Pathが通っているか確認する。**
コマンドプロンプトを起動、python --versionやpip --versionと打ち込みバージョン情報が表示されることを確認する。



~~~cmd
C:\Users\ユーザー名>pip --version
pip 23.1.2 from C:\Users\ユーザー名\AppData\Local\Programs\Python\Python311\Lib\site-packages\pip (python 3.11)

C:\Users\ユーザー名\>py --version
Python 3.11.4
~~~

## 仮想環境

**4.仮想環境の作成**

python3.3以降を使用しているなら'venv'を、それ以前なら'virtualenv'を使う
以降ではvenvを使ったやり方を記述します。

やり方は、仮想環境をつくりたいフォルダに移動して以下のコマンドを打つだけです。
~~~cmd 
py -m venv <環境名>
~~~

仮想環境の起動にはプロジェクトのディレクトリまで移動したうえで、以下のコマンドを打ちます。

~~~cmd
./env/Scripts/activate
~~~

離脱したいときは以下のコマンドを打ちます

~~~cmd 
deactivate
~~~

なお、初期化したいときは
~~~cmd
py -m venv <環境名> --clear
~~~
で、削除したいときは単にそのフォルダおよびディレクトリを削除すればいいだけです。
~~~cmd 
rd /s [/q] <ディレクトリ名>
~~~
[\s]は配下のファイルおよびディレクトリをすべて消去するためのオプション、[\q]は確認メッセージを非表示にするためのオプションです。

## パッケージのインストール
パッケージのインストールを行いたいときは以下のようにします。
また、特定のバージョンをインストールしたいときは二行目のようにします。
~~~cmd
py -m pip install <パッケージ名>
py -m pip install "requests==2.18.4"
~~~

パッケージのextra部分をインストールするには以下のように角括弧([,])の中に書きます。
~~~cmd
py -m pip install "requests[security]"
~~~

パッケージのアップデートは以下の通り。
~~~cmd
pip install -U <package-name>
~~~

パッケージのアンインストールは以下の通り
~~~cmd
pip uninstall <package-name>
~~~

requirements.txtで一括インストールすることもできます。

~~~cmd
pip install -r requirements.txt
~~~

pipではfreezeコマンドを使うことで、インストール済の全パッケージのバージョン付きのリストを取り出すことができます。

~~~cmd
py -m pip freeze
~~~
これはあるパッケージを正確にそのバージョンで再作成することができるpip:Requirementsファイルを作るのに便利です。

依存関係をチェックするには以下のコマンドで。

~~~cmd
 pip checkNo broken requirements found.
~~~

パッケージのリスト全部表示(オプションはアップデートが必要なパッケージのリスト)は以下。

~~~cmd
pip list [-o:アップデートが必要なものを表示] [-u:アップデート必要ないものの表示]
~~~





### [参考文献]
[pythonライブラリインストール方法(pipコマンドの使い方)](https://gammasoft.jp/python/python-library-install/)
[モジュールの仕組み(pythonのパッケージimportできない）](https://www.sejuku.net/blog/71311)
[pythonのモジュール、ライブラリ解説](https://ai-inter1.com/python-module_package_library/)
[Anacondaに頼らない、pipとvenvを使った環境構築](https://www.nemotos.net/?p=4502)
[pip と仮想環境を使ってパッケージをインストールする](https://packaging.python.org/ja/latest/guides/installing-using-pip-and-virtual-environments/)
[pipでアップデートするときのコマンド pip update](https://qiita.com/HyunwookPark/items/242a8ceea656416b6da8)
[pip documentation v23.3.dev0](https://pip.pypa.io/en/latest/user_guide/#requirements-files)
Gitのチェックアウトについて今まで勘違いしていた

### Gitのチェックアウトについて
チェックアウトについて、以前より理解が少し深まったのでメモ。

### 今までの認識
- ブランチを移動しているんだな、程度の認識。

### 厳密には
- HEADがそのブランチの最新コミットに移動する。
- 指定したブランチの内容が作業ツリーに展開される。
- コミットされるブランチがチェックアウトしたブランチになる

などなど、まだまだ細かいところはたくさんあるのでしょうけど、今回はこんなところで。

おしまい。
[OutSystems]Tenant関係のEntityを観察してみる

質問箱で質問もらって久しぶりにTenant関係のEntityのレコードを確認してみたので、後のためにメモしておく。
なお、(System)下にあるEntityはドキュメントが無いものが多く、Tenant、Espace_Tenantもドキュメントが無さそうだった（2023/08時点）。

# 環境情報
Personal Environment(Version 11.21.0 (Build 39357))
Service Studio(Version 11.54.19)

このPersonal Environmentには以下の通り4つのTenantがUsersアプリケーション管理下にある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d7e88ada-02fb-8e5a-9240-2ae5f1df9686.png)
（以前Tenant関係の調査時に試しに適当に作ったもの）

# ER図
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/a573fbea-20e2-1198-df39-e5432150a66b.png)

メインのEntityがTenantで、TenantにはEspace_IdがあるのでEspace Entityとリレーションがある。
また、EspaceとTenant間で多対多のリレーションを持つEspace_Tenant Entityがある。

# Tenant Entity
レコードを全件Excelに取り出して確認してみると
- Espace_Id属性がUsesを指しているものが4件。Tenant Nameには、この環境で表示される全てのTenantの名前が表示される。↓のSSのEspace Nameは取り出すときにEspaceとジョインして取り出したもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d90d1d3b-7598-48b5-ec24-1a36abc96d5e.png)
- Tenant.Name=Espace.Name (EspaceはTenant.Espace_Idでジョイン）のレコードが恐らくLibraryを除く全eSpace分、削除済みのeSpaceを含めて存在する。こっちは存在意義が不明。もしかしたらTenantを管理するUser Providerをカスタムにするときか？

[Master Class on Multi-Tenancy](https://learn.outsystems.com/training/journeys/multi-tenancy-516/master-class-on-multi-tenancy/o11/2429)という動画がずいぶん前からあり（Multi Tenantを学習したいときにはこれからスタートするのがおすすめ）、そのサンプルアプリケーションを見ると、Tenantの一覧を取得するのに以下の条件を使っている（MasterClass_BOモジュール > Tenants Web Screen > Preparation > GetTenantsOfUserProvider) 。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/cc16050e-254e-87a0-e6e6-aeea4fbc1f99.png)

これは、UsersとEspace_Idでリレーションを持つレコードが、環境内のTenant数分だけTenant Entityにあるという観察と一致する。

# Espace_Tenant Entity
レコードを観察すると、eSpaceとそのeSpaceが属するTenantのマッピングを行うEntity。
環境内には、Usersで管理する4つのTenantとService CenterがTenantとしてある。

↓は、Espace_Tenantの全レコードを取得し、Tenant毎に何件のレコードがあるかを確認したもの。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/1555cff6-c238-d880-52ba-f2ca3de0666f.png)
- Service CenterをUser ProviderとするeSpace分のレコード
- UsersをUser ProviderとするeSpace分のレコードを、各Tenant毎に含む
- 何故か、Mobile Pluginが1レコードずつ（ただし、環境内には他にもPluginがあるのですべてが登録されているわけではなさそう）
Postmanでテストの自動化をした話

## 概要

Postmanを利用してテストの自動化を実現した話。
実行ボタン一度を押すだけで、ユーザーシナリオに準じた一連のテストを実行するというもの。　

導入前は1回約45分かかっていたテストが、導入後は1回約20秒近くまでに削減成功。

### テスト項目の具体例
テストの主な対象項目は以下の通り

- 特定のボタンを押下した際の画面遷移
- ステータスコードに基づくリダイレクトの挙動
- 特定の操作によるメール受信
- メールに記載された確認コードを用いたログイン
- 特定項目の文字数の確認
- 古いメールアドレス/パスワードによるログイン失敗
- 新しいメールアドレス/パスワードによるログイン成功
- 既登録のメールアドレスによるログイン情報の更新失敗
- 退会済みのメールアドレスによるログイン失敗
- 退会済みのメールアドレスによる新規登録の可否

などなど。。

## 背景

### テストの時間負荷

- 弊チームでは2週間に1回本番リリースがあり、その度にstage環境と本番待機系環境での2回のテストを実施する必要がある。
- １回のテストで約45分かかること。

緊急リリースがある際も同じ対応を取る必要があり、簡単にリリースできない状況...

### テストの複雑性

- メールを参照する必要があるテスト
- 複数アカウントを用いた新規登録、ログイン、退会の操作
- 手動で行うとミスしやすい分かりずらいテスト

ざっくりとこんな感じで、特に慣れていない人だと余計に時間がかかる...

### 自動化の付加価値

自動化することにより以下のようなメリットもある。

- 手間となる手動作業の排除
- ケアレスミスの防止
- 新入社員の教育工数の削減

## 実装

実現に使用したもの

### MailSlurp
メールテストを自動化するために導入したサービスで、APIを通じてメールアドレスの生成やメール本文の参照などの操作を可能にする。
これによりテスト用メールアドレスの作成が簡単に可能になる。

※無料アカウントだと作成できるメールアドレスに上限や、送信可能数に制限があるので弊チームでは企業プランで導入

https://www.mailslurp.com/

### Postman
事前処理を「Pre-request script」、テスト部分を「Tests」で行い、プロダクトのエンドポイントを網羅的に検証。レスポンスの内容を次のリクエストパラメータにセットするなどしてテストを連続して実行。

共通の環境変数などは「Enviroments」に設定が可能。
自分の場合はEnviromentsでテストしたい環境、（stage1~6、本番待機系環境など）を指定することで特定環境でのテストをできるように実装

他にも、PostmanのCookieを操作したログアウトの再現や
CSRFトークンを用いて画面遷移を再現。
（弊プロダクトの認証周りでは、不正な画面遷移を防ぐためにCSRFトークンのバリデーションチェックが行われているため

https://www.postman.com/

### JavaScript
Postman上でのテストコード作成に使用。
画面遷移の確認やログイン状態の維持、外部APIの呼び出しなどに利用

## 導入サンプル

例えばログイン画面に遷移できているかのテストがあったとした場合

- エンドポイント
GET https://www.hogehoge.com/login


- Pre-request script
```
// Hostのcookiesを削除することで擬似的にログアウト
const jar = pm.cookies.jar();
const Scheme = pm.environment.get('Scheme');
const Host = pm.environment.get('Host');

jar.clear(Scheme + Host, error => {
    if(error) {
        console.error(error);
    }
})
```

- Tests
```
// html取得
const $html = cheerio.load(pm.response.text());

pm.test("status code is 200", function () {
    pm.response.to.have.status(200);
});

const element = $html('.login-boxIssueCode__pt01 .-heading04').text();
pm.test("画面遷移テスト", function () {
    pm.expect("この文言があればOK！").to.equal(element);
});

// set params
const csrf_token = $html('[name="csrf_token"]').val();
if(csrf_token){
    pm.environment.set("CSRFToken", csrf_token);
}
```

こんな感じのを必要な分だけ作成する
あとはフォルダ内のエンドポイントを一括実行して待つだけで完了
Next.jsでFontAwesome を使用できるようにする。

## はじめに
Next.jsでFontAwesomeを使用できるようにしたので、メモとして書いておきます。

## インストール
以下のコマンドでインストールする。

### 1. SVGコアパッケージをインストールする。

**npmを使用する場合**
```
npm i --save @fortawesome/fontawesome-svg-core
```
**yarnを使用する場合**
```
yarn add @fortawesome/fontawesome-svg-core
```

### 2. アイコンパッケージをインストールする。
**npmを使用する場合**
```
npm i --save @fortawesome/free-solid-svg-icons
npm i --save @fortawesome/free-regular-svg-icons
```

**yarnを使用する場合**
```
yarn add @fortawesome/free-solid-svg-icons
yarn add @fortawesome/free-regular-svg-icons
```
### 3. react-fontawesomeパッケージをインストールする。

**npmを使用する場合**
```
npm i --save @fortawesome/react-fontawesome@latest
```

**yarnを使用する場合**
```
yarn add @fortawesome/react-fontawesome@latest
```

## 使い方
以下のように、FontAwesomeをインポートしてきます。
今回は、時計のアイコンを使用するため、以下のように書いていきます。
#### インポート文
```
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faClock } from "@fortawesome/free-solid-svg-icons";
```
#### アイコンの使用
そのまま使用すると、かなり大きく表示されてしまうので、CSSで調整する必要があるかもしれないです。
```
<FontAwesomeIcon icon={faClock} className="h-3 mr-1" />
```

## 最後に

他にも色々な記事を書いているので、よければ読んでいってください、、、
[基本設計について](https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc)
[Vue.jsとNode.jsでチャットアプリを作った](https://qiita.com/hukuryo/items/265c676d17fe21e75242)
[Next.js×TypeScriptでTODOアプリを作成する](https://qiita.com/hukuryo/items/ebeb26823f944f143b11)
[JSTQB AL TA]　2.リスクベースドテストにおける テストアナリストのタスク　を視覚的にまとめてみた

# はじめに

こんにちは、Ma5am1nです。
[シラバス](https://jstqb.jp/dl/jstqb.jpdlJSTQB-SyllabusALTA_V311.J03.pdf)[^1]は文字が多くて頭に入りにくいので、図など視覚的に入ってきやすそうな形式でまとめてみます。

[^1]: Advanced Level シラバス日本語版　テストアナリスト　Version 3.1.1.J03 

**※あくまで私個人の解釈で作成したものです。内容が100%シラバスの通りであることは保証できませんので、ご了承ください。**
**※スライドの青文字、青線になっている箇所は、シラバスに記載されていない、私独自の解釈で記載した内容です。**

このページでは、2.リスクベースドテストにおけるテストアナリストのタスク　について扱います。

# 2.リスクベースドテストにおける テストアナリストのタスク
## 2.1イントロダクション
![JSTQB AL TA-26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/7b8d1600-a394-1003-2060-88cf2fb734d0.png)

## 2.2リスク識別
![JSTQB AL TA-28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/39df83c9-fb1c-2aa9-ba10-b60c4c38b9c4.png)

## 2.3リスクアセスメント
![JSTQB AL TA-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/caee11f2-4395-cbe8-ed46-df66afe966c5.png)


![JSTQB AL TA-31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/500b90ce-72c4-9a11-ba2a-56970e2ab1a3.png)

## 2.4リスク軽減
![JSTQB AL TA-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/1a4eb7b2-ef6c-940e-c24c-2b83a66a4d0d.png)

### 2.4.1テストの優先度付け
![JSTQB AL TA-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/f3e56f56-4e71-6e81-2d44-0927aaa9cc00.png)

### 2.4.2将来のテストサイクルに向けたテストの調整
![JSTQB AL TA-37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/f7dcbe5b-bf71-f820-7922-ef72af3d743d.png)
羊による羊のためのJavaScript復習①データ型と演算子

# 1.プログラミングとは
コンピュータに対する命令(プログラム：program)を書くこと


## プログラムはどのような言語で書かれるか
プログラミング言語
ex. JavaScript,Java,Python,PHP,GO…

# 2.JavaScriptとは
Webページにて動的な機能を可能にさせるプログラミング言語
cf. 
・[JavaScript|MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript)

## JavaScriptの特徴
・デベロッパーツールを使用してブラウザ上で動かすことができる
・比較的簡単で新しい言語
・習得するとフルスタックのアプリ開発が行える

## Google Chromeにおけるデベロッパーツールの開き方
consoleの開き方
・ハンバーガーメニューから
・Command + option + J

# 3.コードの記述と実行

## テキストエディタ
実際にコードを書く場所


## ブラウザ
Webページを閲覧するためのソフト
  書いたコードをブラウザで実行して表示結果を確認できる

## console.log()
メッセージをconsole画面に表示させるメソッド
メソッド：JavaScriptに標準で備わっているもの

# 4.JavaScriptのデータ型
プログラミング言語は、どれにも組み込みデータ構造があるが、ふつうは言語ごとに異なる
cf.[JavaScriptのデータ型とデータ構造|MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Data_structures)

## プリミティブ型
objectを除くすべての型は、言語の最下層で直接表現される不変値を定義している
データ型の中で最小単位のデータを格納するデータ型をプリミティブ型という
数値型、文字列型、ブーリアン型、undefined型が該当する
`null`を除くすべてのプリミティブ型は`typeof`演算子で確認することができる
`typeofnull`は`object`を返すので、`null`であることを確認するには`=== null`を使用しなければならない

  | 型 | `typeof`の返り値 | オブジェクトラッパー |
|:--|:-:|:-:|
| 数値型 | `"number"` | Number |
| 文字列型 | `"string"` | String |
| Boolean型 | `"boolean"` | Boolean |
| Undefined型 | `"undefined"` | なし |
| Null型 | `"object"` | なし |
| 長整数型 | `"bigint"` | BigInt |
| シンボル型 | `"symbol"` | Symbol |（）

 cf.
オブジェクト型(object)：配列やオブジェクト
関数型(function)：関数

# 5.演算子について

## 演算子
各演算を表す記号・シンボル
`+`などの計算をする演算子のこと：算術演算子

| 算術演算子 | 演算 | ex. |
|:--|:--|:--|
| `+` | 足し算 | `1 + 1; // => 2` |
| `-` | 引き算 | `5 - 2; // => 3` |
| `*` | 掛け算 | `2 * 5; // => 10` |
| `/` | 割り算 | `6 / 2; // => 3` |
| `%` | 割ったあまり | `7 % 2; // => 1` |
| `**` | 冪乗 | `3 ** 2; // => 9` | （）
#0011 Qiitaで使える記法（色、表）

## はじめに
- 色と表のQiitaで使える記法を調べたのでメモしておく

## 表

```
|カラム1| カラム2 |
| ---- | ---- | 
|バリュー1| バリュー2 | 
```

|カラム1| カラム2 |
| ---- | ---- | 
|バリュー1| バリュー2 | 

## 色

- 色はマークダウンの記法は使うことができず、　htmlで記述する

```
<font color="red">赤色</font>です。
<font color="blue">青色</font>です。
```

<font color="red">赤色</font>です。
<font color="blue">青色</font>です。
#0010 書籍：「具体⇄抽象」トレーニング

## はじめに
- 細谷功さんの「具体⇄抽象」トレーニングを再読した。
- 一度呼んだが、何かまた読み返したくなった。
- 重要だと思った部分をまとめていく。


## 「具体⇄抽象」とは
- 知の拡大（人類の発展）により、"情報量"を底辺、"抽象度"を高さとした三角形が広がった。
- 情報技術の発展により、あらゆる情報へアクセスしやすくなるため、横の世界は拡大し、縦の世界が小さくなる。
- 縦の世界では「問いを立てる」ことが重要、横の世界では「答える」ことが重要。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3516139/2089ba00-6e24-38fe-cfe7-7ca4cba45bd6.png" width="500px">


|| 縦の世界（抽象度） | 横の世界（情報量） |
| ---- | ---- | ---- |
|正解| なし | あり |
|優劣| 曖昧 | 明確 |
|変数| 可変 | 固定 |
|重要視されるもの| 問い | 答え |
|強い人| 素人 | 専門家 |


## 「具体⇄抽象」の重要性
-  「具体⇄抽象」の重要性の一つは問題解決のフレームワークにある。
-  問題解決の3パターン
    1. 具体 -> 具体 ... 表面的な問題解決
    1. 抽象 -> 抽象 ... 机上の問題解決
    1. 具体 -> 抽象 ... <font color="Red">根本的な問題解決　</font>


##　抽象化・具体化とは

|| 抽象化 | 具体化） |
| ---- | ---- | ---- |
|自由度| 上げる | 下げる |
|優先度|順位付け|すべて同等|
|情報の扱い方|<font color="Red">都合よく切り取る　</font><br>捨てる|細部まで拾う|
|アクション|whyを考える|howを考える|

## 「具体⇄抽象」の注意点
- 具体的に見えている人に抽象的な見方を矯正することは難しい。（逆はあり）
- 例えば、コミュニケーションギャップは指示とアクションの「具体⇄抽象」のギャップによるもの
※ 離れすぎていても、被り過ぎていても問題になり得る。
- 言葉の定義を共通認識させることが重要。


## 終わりに
- 「例え」と「喩え」の違い
    - 喩え -> 直喩隠喩、言い換え、in other words
    - 例え -> 具体化、for exapmle
- レッテル貼りのメカニズム
    - 他人にレッテルを貼る（抽象化）のに、
    - 自分にレッテルを貼られる（具体化）と不快となる。
-> <font color="Red">自分を抽象レベルで見る、他人を具体レベルで見られる様になると強い人間になると思う。</font>（個人の感想）
aptパッケージのセキュリティパッチをする

## はじめに
これはaptで管理されているパッケージのセキュリティパッチをあてる記事です。
今回はOpenSSLに対して、セキュリティパッチを当てたのでその記録を残します。

対象のディストリビューションは`Ubuntu22.04`です。

## セキュリティパッチをあてる方法
Ubuntuでは自動でセキュリティパッチをあてることもできるようです。
https://help.ubuntu.com/community/AutomaticSecurityUpdates
しかし、無人の状態で本番環境にパッチすることに抵抗を感じたため、今回は手動で行うこととしました。

### aptパッケージ一覧の更新
まずは、aptパッケージ一覧を最新化します。
``` bash:ターミナル
sudo apt update
```

### 対象のセキュリティパッチバージョンを確認
次に、適用できるセキュリティパッチを確認します。
自分があてたいパッチがあるかを事前に確認する目的です。
``` bash:ターミナル
sudo apt-get upgrade -s |grep security
```
ここでは`sudo apt-get upgrade`に`-s`オプションを付けています。
`-s`は`--simulate`オプションであり、シミュレーションをおこないますが、実際には更新されません。
（補足：`apt-get`としているのは`apt man`に`-s`オプションの説明が無かったためです。）
`sudo apt-get upgrade`したときに更新されるパッケージの中から、`security`と付くものを`grep`した結果を表示します。
表示結果には以下のように、今回セキュリティパッチをあてたいOpenSSLが含まれていました。

```
Inst openssl [3.0.2-0ubuntu1.8] (3.0.2-0ubuntu1.10 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [amd64])
Conf openssl (3.0.2-0ubuntu1.10 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [amd64])
Inst libssl3 [3.0.2-0ubuntu1.8] (3.0.2-0ubuntu1.10 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [amd64]) []
Conf libssl3 (3.0.2-0ubuntu1.10 Ubuntu:22.04/jammy-updates, Ubuntu:22.04/jammy-security [amd64]) []
```

### セキュリティパッチをあてる
特定のパッケージに対して更新を行う場合は、`sudo apt-get install [pkg=pkg_version_number]`で出来ます。

``` bash:ターミナル
sudo apt-get install openssl=3.0.2-0ubuntu1.10
sudo apt-get install libssl3=3.0.2-0ubuntu1.10
```

## おまけ：プロセス再起動要否の確認
パッケージの中にはセキュリティパッチをあてた後にプロセス再起動が必要なものがあります。
セキュリティパッチ後に再起動の要否を確認する手順です。
``` bash:ターミナル
sudo checkrestart -a
```

`Command 'checkrestart' not found, but can be installed with:sudo apt install debian-goodies`が表示された場合は、
`debian-goodies`パッケージをインストールします。
``` bash:ターミナル
sudo apt install debian-goodies
```
https://packages.debian.org/ja/sid/debian-goodies

以上です。
Githubへのアップロード（ターミナルから）

Githubへのアップロード方法について、見よう見まねで上手くいったチュートリアル動画のリンクです。

https://www.youtube.com/watch?v=eyPv-eaHsYI&list=PLZBrLW521ic-KYGKTgn9B5tib59dkr3RF&pp=iAQB

色々探してみましたが、エラーが出た場合の対処法まで含まれていなかったり、よさげに見えても英語解説だったりと、独学初心者勢には物足りないチュートリアル動画が散見される中でこれは解りやすかった。
Linux: 同じファイルへのリダイレクトをしてはいけない

ちょっとひっかかったのでメモ。

###### 実施環境：

```Linux:Linux
[testuser@testhost ~]$ uname -a
Linux testhost 4.18.0-147.8.1.el8_1.x86_64 #1 SMP Thu Apr 9 13:49:54 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
[testuser@testhost ~]$ echo $SHELL
/bin/bash
```

### 事象

以下のようなファイルがあるとします。

```Linux:Linux
[root@testhost test]# ls -l test.txt
-rw-r--r--. 1 root root 3643  7月 17 08:47 test.txt
[root@testhost test]#
```

このファイルを cat コマンドに指定して適当なファイルにリダイレクトすると、内容がそのファイルにコピーされます。

```Linux:Linux
[root@testhost test]# cat test.txt > test2.txt 2>&1
[root@testhost test]#
[root@testhost test]# ls -l test2.txt
-rw-r--r--. 1 root root 3643  7月 17 08:48 test2.txt
[root@testhost test]#
```

では、このリダイレクト先を同じファイルにするとどうなるでしょうか。

```Linux:Linux
[root@testhost test]# cat test.txt > test.txt 2>&1
```

答えですが、指定したファイルが空となります。

```Linux:Linux
[root@testhost test]# ls -l test.txt
-rw-r--r--. 1 root root 0  7月 17 08:48 test.txt
[root@testhost test]#
```

軽く調べたところ、 Linux ではリダイレクト(`>`)を指定した際、コマンドの実行より前に「出力先の空ファイルを作成する/出力先ファイルを空にする」という処理を行うようです。
そのため、先の処理では

1. test.txt を空にする
1. test.txt の中身(空)を cat コマンドで標準出力に出力する
1. 標準出力に出力した内容(空)を test.txt に書き込む

となるので、最終的に出力される test.txt は空ファイルとなってしまいました。

対処法としては、単にリダイレクト元のファイルとリダイレクト先のファイルを別々にすればよいです。

今回は cat コマンドを使用しましたが、他のコマンドでも同様のことは発生します。
ファイルの中身をコマンドで加工する際にやってしまいがちなので注意しましょう。
neosでlogix その142

# 概要
neosでlogixやってみる。
neosvrのlogixをコード化する試み。

# 俺コード仕様

- ネームスペース
devツールの新規は、ネームスペースObj
コンポーネントの追加は、ネームスペースFrooxEngine
ノードブラウザのLogiXは、ネームスペースLogiXで、省略可

- 基本
{_, _, _, _, a, b, _, _, _, _} = StandardController GetActiveUser <Right>
で
{出力端子1, 出力端子2} = デバイス名 入力端子1, 入力端子2

- 仮想wire
d = FireWhileTrue
で
仮想ワイヤー

- パイプ |>
e = c |> FindChildByName "Logix" 2
で
cが入力端子1となる

# サンプル1

音を鳴らす。

```
a = Pulse
b = "egg"
c = RootSlot
{d, e} = AttachAudioClip a, b, c
PlayOneShot d, e
```

![2022-03-04 22.41.59.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/13906c73-0b96-75f6-985e-7cfb34ae7af0.jpeg)

# サンプル2

触ると、パーティクルが出る箱を作れ。

```
{v, _, _, _, _, _, _, _} = Obj.Box.TouchButton
{a, _, b, _, _, _, _, _, _, _} = ButtonEvents v
{c, _, _} = BooleanLatch a b
FrooxEngine.ParticleSystem.CircleEmitter.Enabled = c


```

![2023-02-19 07.14.49.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/a540c4c1-b6eb-a415-dc42-b7f0e00adc1a.jpeg)


# サンプル3

neos uiを使って、websocketで、オウム返しを取得するオブジェクトを作成せよ。


```
{p0, _} = ButtonEvents Obj.Button
{p1, _} = ButtonEvents Obj.Button
{_} = WebsocketConnect p0, FrooxEngine.WebSocketClient, "ws://localhost:50002", HostUser
{_, _, _} = WebsocketTextMessageSender p1, FrooxEngine.WebSocketClient, Obj.TextField.text
{p2, d} = WebsocketTextMessageReceiver FrooxEngine.WebSocketClient
{v} = Write p2, d
Obj.test.txt.text = v


```

![2023-05-01 23.55.39.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/00eccbb5-567a-1b15-9a0f-07258033de9b.jpeg)



以上。
vimの基本操作をまとめてみた


## はじめに

本記事では、vim初心者である筆者が自身のアウトプットのため、これからvimを学習される方向けに作成したものです。
vimの名前は聞いたことあるけど、vimを使うメリットって何？vimってどう扱うの？<br>などの疑問を解消できるように書いていきます。


## vimとは？
vimとはキーボードオンリーで操作可能なエディタのことです。
キーボード入力で以下のことが出来ます。
- テキスト間の移動
- テキストの選択
- テキストの挿入、削除、コピペ
- ページ内検索

またLinux(サーバ用のOS)では、vimのみで環境構築することもあるため慣れておくといざという時便利です。

#### vimのメリット
メリットとしては、**キーボード入力**だけで完結出来るため、**高速**で編集可能なところ。
キーボードを入力して、右手でマウスを持って対象をクリックして...とやるより遥かに効率が良いですよね。

## モードの種類

vimはキーボードのみで**操作**や**編集**などをするので、今入力しているのが**ただの文字**なのかそれとも**コマンド**として入力しているのかを区別するために**モード**があります。


|　モード名　　　|　　主な動作　　　　　　　　　　　　| 
|:-----------|:------------|
| NORMAL|カーソル移動、テキストコピペ、テキスト削除、入れ替え　、、etc　　　　　　　　　　　　　　　　　| 
| INSERT|テキストの入力　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　　|
| VISUAL     |テキストの選択　　　　　　　　　　　　　　　　　　　　　　　　　　　| 

vimを起動したらノーマルモードからスタートします。
そこで適宜コマンドを入力してモードを切り替えて、文章を入力したりします。
例えばですが、ノーマルモードからインサートモードへ切り替えの場合は、ノーマルモードの状態で「i」ボタンを入力することでインサートモードへ切り替えが出来ます。
ノーマルモードへ戻りたい時はキーボード左上の「ESC」ボタンで戻ります。

モードは下部に表示されているので、今何モードなのかを確認しながら進めていくようにしましょう。

![スクリーンショット 2023-08-05 20.34.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3519029/ae483e2f-0b1b-c466-29eb-6cebc2d4747c.png)


## コマンド紹介
ここからはよく使うコマンドを紹介します。
vimのコマンドはめちゃくちゃあるので、一気に覚えようとはせずに<br>最低限のコマンドを覚えてそこから必要に応じてググって新たに知識を追加していくのがベストだと思います。

実際に動かしながら覚えてみたいよという方は、ターミナルからvimtutorと入力するとvimの
チュートリアルが動かしながら出来るのでおすすめです。所要時間は35分ほどらしいですが、自分は操作してメモしてとやっていたら1時間ぐらい使ってました。

(*)上記はMacでの方法なので、windowsを使用されてる方はvim windows やり方などでググってみてください。

それではコマンド紹介へいきたいと思います！

#### カーソル移動

カーソルの操作は以下のように行います。
位置キーでも動きますが、キーボードによっては位置キーがない場合もあるので
コマンド入力で慣らしていきましょう。

|コマンド|効果|
|:--:|:--:| 
|h|カーソルを左にずらす|
|j|カーソルを下に下げる|
|k|カーソルを上に上げる|
|l|カーソルを右にずらす|

１行あたりの文字が多かったり、何百行の移動するのに上下左右にボタンポチポチするの面倒！！と思われた方もいると思います。
僕も同じこと思いました..笑
下記のコマンドで、さらにカーソル移動が楽になります。

|コマンド|	効果|
|:----|:----------|
|0|	行頭へ移動|
|$|	行末へ移動|
|w|	単語の末尾へ移動|
|gg|	ファイルの先頭へ移動|
|nG , :n|	ファイルのn行目へ移動|
|G|	ファイルの末尾へ移動|
|H|	画面の最上行へ移動|
|L|	画面の最下行へ移動|
|ctrl + b|	前の画面へ移動|
|ctrl + f|	次の画面へ移動|

#### 操作系
エディタ本来の役割は編集なので、入力と保存について表で見ていきましょう。
モードでもインサートについて触れましたが、表で見ると分かりやすいのでこちらにまとめます。
|コマンド|効果|
|:--|:--| 
|a|カーソルの場所から1文字進めてInsertModeに入る|
|i|カーソルの場所からINSERTモードに入る|
|:w|ファイルの保存(Control-s)|
|:q|実行中のタブを閉じる|
|:wq|上を組み合わせて保存して閉じることもできる|
|:w!|のように最後に[!]をつけると強制的に処理します|


簡単なコピペや削除コマンドなどは以下の通りです。

|コマンド|効果|
|:--|:--|
|x|カーソル直下の文字を消します|
|dd|カーソルがある1列削除|
|yy|1列コピー|
|p|ペースト|
|u|操作を1つ戻す(Control+z)|


応用になりますが、部分選択をしてコピペ,カーソルの位置からのアクション,削除後にINSERTモードで変更などもあります。

|コマンド|効果|
|:--|:--|
| v + 移動コマンド + y | 範囲してしてコピー |
| yw | カーソルの位置から次の単語までをコピー|
| P | コピーした内容をカーソル位置の上行に貼り付け|
| dw | カーソルの位置から空白含む単語範囲で削除|
| de | カーソルの位置から空白含まない単語範囲で削除|
| D/d$ | カーソル位置から行の末尾までを削除|
| ce | カーソルの位置から空白含まない単語範囲で削除した後にINSERTモードに変更|
| cc | 行全体を削除した後に変更INSERTモードへ変更|
| C | カーソル位置から行の末尾までを削除した後にINSERT|


#### 検索操作
ファイル内検索はこのコマンドで出来ます。

| コマンド名 | 動作 |
|:-:|:-:|
| / | カーソル位置から下方向にキーワードを検索 |
| ? | カーソル位置から上方向にキーワードを検索 |

例えば`/apple` <Enter>ボタン押下することでappleを検索します

## おわりに
vim初学者の私が実際にvimtutorや他の教材を学習したものを解説してみました。
vimtutor学習と今回のブログ記事を通じて少し動かせるようになったので、ブラインドタッチなどと同様にコツコツ練習して出来るようにしていきたいです！
今後、vimを学び始める方の学習の参考になれば幸いです。
お読みいただきありがとうございました。
Reactで柔軟なコンポーネント設計！Compound Componentsパターンをマスターしよう


# Reactで柔軟なコンポーネント設計！Compound Componentsパターンをマスターしよう

## 目次

- [はじめに](#はじめに)
- [Compound Componentsパターンとは](#Compound-Componentsパターンとは)
- [Compound Componentsを使った例](#Compound-Componentsを使った例)
- [Compound Componentsを使わない例](#Compound-Componentsを使わない例)
- [対比とメリット](#対比とメリット)
- [まとめ](#まとめ)

### はじめに

Reactでは、コンポーネント設計が非常に重要です。今回紹介するCompound Componentsパターンは、コンポーネント間の関係を明確にし、再利用性を高めるための強力な手法です。

### Compound Componentsパターンとは

Compound Componentsパターンは、親子コンポーネント間で柔軟に制御を行う設計パターンです。子コンポーネントは親コンポーネントからのプロパティを受け取り、個別に機能します。

### Compound Componentsを使った例

#### Tabs.js

```jsx
import React, { useState, createContext, useContext } from 'react';

const TabContext = createContext(); // コンテキストを作成

export const Tabs = ({ children }) => {
  const [activeTab, setActiveTab] = useState(0); // アクティブなタブの状態

  return (
    <TabContext.Provider value={{ activeTab, setActiveTab }}>
      <div>{children}</div> // 子コンポーネントをレンダリング
    </TabContext.Provider>
  );
};

export const Tab = ({ title, children }) => {
  const { activeTab, setActiveTab } = useContext(TabContext); // 親コンポーネントからの状態を取得
  const isActive = activeTab === title; // アクティブなタブか判定

  return (
    <div>
      <button onClick={() => setActiveTab(title)}>{title}</button>
      {isActive && <div>{children}</div>} // アクティブな場合のみコンテンツを表示
    </div>
  );
};
```

この例では、`Tabs`コンポーネントが親で、`Tab`コンポーネントが子です。親は現在のアクティブなタブを状態として保持し、子にコンテキストを通じて渡します。子コンポーネントはアクティブなタブかどうかを判定し、内容を表示します。

### Compound Componentsを使わない例

#### Tabs.js

```jsx
import React, { useState } from 'react';

export const Tabs = ({ titles, children }) => {
  const [activeTab, setActiveTab] = useState(0); // アクティブなタブの状態

  return (
    <div>
      {titles.map((title, index) => (
        <button onClick={() => setActiveTab(index)} key={index}>
          {title}
        </button>
      ))}
      {children[activeTab]} // アクティブなタブのコンテンツを表示
    </div>
  );
};
```

この設計では、タブのタイトルと内容が分離されており、`Tabs`コンポーネントが全てのロジックを制御します。子コンポーネントは単に表示されるだけで、独立した存在ではありません。


### 対比とメリット

- **柔軟性**: Compound Componentsを使用すると、より柔軟な設計が可能。
- **再利用性**: 各子コンポーネントが独立しているため、再利用しやすい。
- **可読性**: コンポーネントの関係が明確で、コードの可読性が向上。
- **メンテナンス**: メンテナンスが容易。

### まとめ

Compound Componentsパターンは、Reactのコンポーネント設計を向上させる素晴らしい手法です。この記事を通じて、この強力なパターンをマスターし、より洗練されたReactアプリケーションの開発を進めてください！

いいねやシェアは、今後の記事作成の励みになります。感想や質問があれば、コメント欄にお気軽にどうぞ！
Reactアプリのボトルネックを特定！React Profiler APIでパフォーマンス分析入門


Reactアプリケーションのパフォーマンスボトルネックを解明し、最適化したいですか？React Profiler APIを使えば、それが可能です。この記事では、React Profiler APIの基本からcallbackの詳細な解説までを提供します。

## 目次
1. [はじめに](#introduction)
2. [React Profilerとは](#what-is-profiler)
3. [React Profiler APIの基本](#profiler-api-basic)
4. [callback関数の詳細解説](#callback-details)
5. [実際の使用例](#real-example)
6. [まとめ](#conclusion)

### <a name="introduction"></a>1. はじめに

React Profiler APIは、Reactアプリケーションの性能分析に強力なツールです。この記事で、その魅力に迫ります。

### <a name="what-is-profiler"></a>2. React Profilerとは

React Profilerは、コンポーネントのレンダリング情報を分析するツールです。

### <a name="profiler-api-basic"></a>3. React Profiler APIの基本

`Profiler` コンポーネントを使用することで、コンポーネントのパフォーマンス情報を取得できます。

```jsx
import React, { Profiler } from 'react';

function MyComponent() {
  return (
    <Profiler id="MyComponent" onRender={callback}>
      {/* コンポーネント内容 */}
    </Profiler>
  );
}
```

### <a name="callback-details"></a>4. callback関数の詳細解説

`onRender`コールバックは、レンダリングの詳細情報を受け取ります。

```jsx
function callback(
  id,
  phase,
  actualDuration,
  baseDuration,
  startTime,
  commitTime,
  interactions
) {
  // ここでプロファイリングデータを扱う
}
```

- `id`: プロファイリングされているProfilerコンポーネントの一意のID。複数のProfilerを使用する場合に識別するために使用されます。
- `phase`: "mount"または"update"のいずれか。コンポーネントのレンダリング段階を示します。
- `actualDuration`: コンポーネントとその子孫がレンダリングされるのにかかった実際の時間（ミリ秒）。パフォーマンスのボトルネックを特定するために使用します。
- `baseDuration`: 無駄な再レンダリングがない場合の理想的なレンダリング時間（ミリ秒）。
- `startTime`: Reactがレンダリングを開始した時間。レンダリングの効率を計測するために使用します。
- `commitTime`: Reactが変更をDOMにコミットした時間。ブラウザが描画した時間を知るために使用します。
- `interactions`: レンダリングに関連するユーザーのインタラクション。ユーザー操作がレンダリングにどう影響したかを追跡します。

### <a name="real-example"></a>5. 実際の使用例

```jsx
function callback(id, phase, actualDuration) {
  console.log(`コンポーネント ${id} が ${phase} フェーズで ${actualDuration} ミリ秒かかりました。`);
}
```

このようにして、具体的なコンポーネントのレンダリングにかかる時間などをログに出力することができます。

### <a name="conclusion"></a>6. まとめ

React Profiler APIは、Reactアプリの性能を分析し、最適化するための強力なツールです。特にcallback関数を利用することで、具体的な分析が可能になります。

いいねやコメントがあれば、お気軽にどうぞ！
Ruby ~ (チルダ) の正規表現での動作

# はじめに
RubyでAtCoderを解いていた時に見つけた`~`の面白い動作をメモしておきます。
コードゴルフくらいには役に立ちそうです。

# 本文
解いていたAtCoderの問題を要約すると下記のようなものです
> 標準入力から与えられた文字に`A`が何文字目に含まれているか出力してください


問題を全文記述すると長くなるので割愛します。入力に`A`が絶対含まれるものとしておいてください。

妥当に解くとこのようになるでしょうか
```reasonable.rb
input = gets
puts (input =~ /A/) + 1
```
標準入力を変数inputに入れ、`input =~ /A/`で何文字目に`A`があるかマッチしています。`+1`は`input =~ /A/`が0からカウントを始めるのでつけています。

# 問題のコード
以下のコードは綺麗に書こうと色々試しており、自分で書いておいて何故動くか全くわからなかったものです
```code_in_question.rb
gets
p ~/A/+1
```

# 解説
私が知らないだけで普通に本に載ってる程度の物でしたら恥ずかしいですが、私は調べても出てこなくて悩みました。


上記コードは`gets`で標準入力を受け取り謎の`~/A/`を出力しているように見えます。
ここでの重要な点は記事のタイトルにも書いている`~`で、**`~`はgetsからの入力を受ける変数`$_`とのパターンマッチをする**ためにも使われます。
`$_`もあまり使わないものですが説明をする文章力がないので、コードを置いておきます。
```explanation.rb
gets
# getsで入力したものが表示される
puts $_
```
# 結論
要するに`$_ =~ /A/`を`~/A/`とすることができます。
これらの`~`の動作は[Regexp](https://docs.ruby-lang.org/ja/latest/class/Regexp.html#I_--7E:~:text=~%20self%20%2D%3E%20Integer%20%7C%20nil)に定義されていました。
普段全然使いませんが綺麗に書くために役に立つかもしれません。先輩に聞こうと迷いましたが夜中なので自分で頑張って調べてついでに記事にしました。
javascriptでスクロールさせる

ページトップまでスクロールさせる方法を検索しました。jQueryでの実装方法ならたくさん出ましたが、Vanilla JSで実装しているのはなかなか見つけられなかったので、メモします。
```js
const scrollBtn = document.querySelector('.scroll-btn');
scrollBtn.addEventListener('click', () => {
  window.scrollTo({
    top: 0,
    behavior: "smooth"
  });
});
```
上記のコードでトップまでスクロールできます。
[こちら](https://zenn.dev/junki555/articles/ba0ff1973182e8)の参考サイトのようにtopを要素の値の座標の値にすれば、特定の位置までのスクロールも可能です。
#### 参考

https://zenn.dev/junki555/articles/ba0ff1973182e8

https://developer.mozilla.org/en-US/docs/Web/API/Window/scrollTo