OmniAICreator/Qiita-1.07M huggingface dataset:
Ｗｅｂデザイン入門　jQueryの基本を学ぼう

1. サマライズテーマ 
 ・ jQueryに通づる基本：「いつ」、「何を」、「どうするか」を軸にする
例えば、
「いつ」・・・要素をクリックした時
「何を」・・・クリックした要素を
「どうするか」・・・フェードインするなど
・onメソッドの活用
基本的な書き方
$("button").on("click",function()){
  console.log("クリックされた");
});
・jQueryの導入
https://developers.google.com/speed/libraries?hl=ja#jquery
3.snipet記述の中のscriptで囲われた箇所をコピーindex.htmlの<body></body>の間に埋め込みする
埋め込みした内容
<body>
                <h1 id="title">タイトル</h1>
    <button>ボタン</button>
    <!-- jQueryを外部から読み込む -->
                <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <!-- main.jsを読み込む -->
    <script src="./js/main.js"></script>
  </body>


2. 言語化してみての気づき（任意）
・今回テキスト内でサンプルコードをダウンロードとあるが、ダウンロードができなかった。
・https://dl.dropboxusercontent.com/s/fmqewy76sypojp2/method.zip?dl=0
・メンターさんに聞いて、上記のurlを教えてもらい、無事ダウンロードすることができたのでよかった。
・動的要素が満載の面白いものだった。
配列の添字の２つ目の数字で長さを指定する

```rb
irb(main):213> alphabet
=> ["A", "B", "C", "D"]
irb(main):214> alphabet[2,3]
=> ["C", "D"]
irb(main):215> alphabet[1,3]
=> ["B", "C", "D"]
```
https://gihyo.jp/book/2017/978-4-7741-9397-7

# 感想
添字の２つ目で長さを指定できることを知らなかった。
pythonの正規表現についてまとめる

以下の記事を参考に正規表現についてまとめる
出典：https://docs.python.org/3.13/howto/regex.html

## 特殊文字とは

通常の文字のようにそれ自身とマッチしない文字であり、合図を出すなどの意味を有する。

```
. ^ $ * + ? { } [ ] \ | ( )
```

### **[]：文字クラス**

[]はマッチしたい文字の集合を表す。(\を除く)特殊文字は文字クラスの内部では有効にならない

- [abc]：a, b, cを表す
- [a-c]：同上

### ^：補集合

クラスの最初の文字に^を指定することで補集合を表すことができる。

- [^5]：5以外の文字を表す

### \：文字と合わせて特殊シーケンスを作る

「‘\’+文字」で様々な特殊シーケンスを作成する。
特殊文字の前に置くことで、特殊文字をマッチさせる際にも使われる。

- \w：任意の英数字文字および下線 [a-zA-Z0-9_]
- \W：任意の非英数字文字 [^0-9]
- \d：任意の十進数 [0-9]

## 繰り返し

### *：繰り返し(スター演算)

これまでの特殊文字は一文字に対してマッチさせるものが多かった。*は繰り返しに対応させることができる。計算論でいうスター演算にあたり、ある文字の0個以上の繰り返しのパターンを指定する。

- ca*t：ct, cat, caat, caaat, caaaat….

### +：繰り返し(1回以上)

*は繰り返し回数として0回以上であったが、+は繰り返し回数として1回以上。

- ca+t：cat, caat…..

### {m, n}：繰り返し(m回以上n回以下)

繰り返しの最小値・最大値を指定できる。

- a/{1, 3}b：a/b, a//b, a///b

## 正規表現の使用方法

正規表現をパターンオブジェクトにコンパイルしたのちに、マッチを実行する。
re.compileに渡される正規表現はpythonの通常の文字列である。

```python
import re
p = re.compile('ab*')
```

### バックスラッシュ問題

**問題**

正規表現を記述するにあたってバックスラッシュが大量に発生してしまうという問題が存在するのでそれについて説明する。

「\section」の正規表現を作成してみる

1. \section：マッチさせるテキスト
2. \\section：sectionの前に存在する「\」は特殊文字ではなく通常の文字として扱う必要があるので、エスケープ用に「\」を前方に追加する。
3. \\\\section：pythonの文字列リテラルで\をエスケープさせるために\を各々の\の前に追加する

このように「\\\\section」と表す必要があり、理解の難しい表現となってしまう。

```python
print('\\') #print('\')はエラー

>> \
```

**解決方法**

Pythonのraw string記法を使用する。rを文字列リテラルの先頭に書くことでバックスラッシュが特別扱いされなくなる。

- “\\\\section” → r”\\section”

```python
print('\n') # -> 改行
print(r'\n') # -> \nと出力される
```

## マッチの実行

パターンオブジェクトのメソッドを使用することによってマッチを実行することができる。台上的なものは以下の通り。

- match()：文字列の先頭で正規表現とマッチするか判定します。
- search()：文字列を先頭から走査して、正規表現がどこにマッチするか調べます。
- findall()：正規表現にマッチする部分文字列を全て探しだしリストとして返します。
- finditer()：正規表現にマッチする部分文字列を全て探しだし [iterator](https://docs.python.org/ja/3/glossary.html#term-iterator) として返します。

### match()の使用方法

[a-z]+(アルファベットの小文字のみで構成された1文字以上の文字列)に対するマッチングを試してみる。

```python
import re
p = re.compile('[a-z]+')

m = p.match("") # > None
m = p.match('tempo') # > <re.Match object; span=(0, 5), match='tempo'>
```

ここでmatch()の返り値はMatchオブジェクトである。
Matchオブジェクトインスタンスの重要なメソッドは以下の通り。

- group()：正規表現にマッチした文字列を返す
- start()：マッチの開始位置を返す
- end()：マッチの終了位置を返す
- span()：マッチの位置(start, end)を含むタプルを返す
テスト自動化エンジニアシラバス：テスト自動化のさまざまなアプローチ

# はじめに

テスト自動化エンジニアのシラバスを再度読み直し、各章をDailyで読めるようにしてみた

https://www.istqb.org/certifications/test-automation-engineer

3.1.4 Apply Different Approaches for Automating Test Cases を今回は翻訳・解説する

テスト自動化を実現するために、さまざまなアプローチが利用できます。それぞれのアプローチには、独自のメリットとデメリットがあり、プロジェクトの特性やチームのスキルセットに合わせて選択する必要があります。

# キャプチャ/再生

手動で一連操作を行ない、SUTの操作を記録するアプローチである。
これらのツールは記録中にテストスクリプトを生成し、ツールによってはテスト自動化コードを修正することもできる。
コードを出力しないツールはノーコードテスト自動化と呼ばれ、一方コードを出力するものはローコードテスト自動化と呼ばれる。

<b>メリット</b>
- プログラミングスキルが不要で、短時間でテストケースを作成できる。
- GUIテストに適している。

<b>デメリット</b>
- テスト対象システム（SUT）の変更に弱く、メンテナンスコストが高い。
- テストケースの構造が複雑になりやすく、可読性が低い。
- テストデータの管理が難しい。

<b>活用シーン</b>
- 回帰テスト
- GUIの動作確認
- 短期間で多くのテストケースを作成したい場合

# 線形スクリプト
TAEがカスタムテストライブラリを作成しないプログラミングで、テストスクリプトの作成と実行に用いられる。
TAEはキャプチャー＆プレイバックで記録されたテストスクリプトを活用し、修正できる。

<b>メリット</b>
- 柔軟性が高く、複雑なテストロジックを実装できる。
- テストケースのカスタマイズが容易。

<b>デメリット</b>
- プログラミングスキルが必要。
- メンテナンスコストがかかる。

<b>活用シーン</b>
- 機能テスト
- APIテスト
- 複雑なシナリオのテスト

# 構造化スクリプト
テストライブラリを利用し、再利用可能なテストステップやユーザーシナリオを定義できる

<b>メリット</b>
- メンテナンス性、拡張性が高い。
- ビジネスロジックとテストロジックを分離できる。
- 大規模なプロジェクトに適している。

<b>デメリット</b>
- 初期構築に時間がかかる。
- プログラミングスキルが必要。

<b>活用シーン</b>
- 大規模なシステムのテスト
- 長期間にわたるテストの保守管理

# テスト駆動開発（TDD）
SUTの新しい機能を実装する前に、テストケースは開発プロセスの一部として定義される。
このアプローチはテスト、コード、リファクタリングもしくは、レッド、グリーン、リファクタリングのサイクルである。
- 開発者は失敗するテストケースをまず作成する。（レッド）
- 開発者は機能を開発し、テストケースを満たす（グリーン）
- コードをリファクタリングし、最適化し、クリーンコード原理に従う。(リファクタリング)


<b>メリット</b>
- コード品質の向上
- テストカバレッジの向上
- バグの早期発見
- 設計段階からの品質向上

<b>デメリット</b>
- 初期導入コストが高い
- 開発者の意識改革が必要

<b>活用シーン</b>
- ユニットテスト
- 新機能開発


# データ駆動テスト
テストデータ（CSVファイル、Excelファイルなど）を元に、同じテストケースを繰り返し実行できる。

<b>メリット</b>
- テストケースの拡張が容易
- テストデータの変更だけで、複数のテストケースを実行できる

<b>デメリット</b>
- テストデータの管理が必要

<b>活用シーン</b>
- 多様な入力値でのテスト
- 組み合わせテスト


#  キーワード駆動テスト
 キーワードとテストデータを使用して、テストケースを定義し、技術レベルの高くない人でも使いやすくする


<b>メリット</b>
- テストアナリストやビジネスアナリストがテストケースの作成に参加できる
- テストケースの可読性が高い

<b>デメリット</b>
- キーワードの定義とメンテナンスが複雑

<b>活用シーン</b>
- ビジネス要件に基づいたテスト
- 非技術者との協業


#  振る舞い駆動開発（BDD）
自然言語でテストケースを記述し、自動化します。

<b>メリット</b>
- 開発者、テスター、ビジネスアナリスト間のコミュニケーションが円滑化
- テストケースの可読性が高い

<b>デメリット</b>
- 複雑なテストケースの定義には技術的なスキルが必要

<b>活用シーン</b>
- ユーザーストーリーに基づいたテスト
- アジャイル開発
NiceGUIのネイティブモード用のNuitka設定

# NiceGUIのネイティブモード実行をNuitkaでExe化する

pyinstallerを使っていましたが、起動に時間がかかったりバイナリがやたら大きくなるなどの課題があるため、Nuitkaを使ってみることにしました。

# NiceGUI用のNuitkaの設定

Nuitkaの使い方とか設定の詳細は他にも詳しい記事があるので、ここではNiceGUI用の設定を挙げるのみにします。

ちなみに、公式ドキュメントの以下にあるように

https://nuitka.net/user-documentation/nuitka-package-config.html#the-yaml-configuration-file    

各設定は実行するPythonコードの先頭にコメントを使用して記載してくと自動で読み取ってくれます。以下に例を挙げます。

```python:app.py
# Windows向けのオプションはif文で書き分けます
# nuitka-project-if: {OS} in ("Windows"):
#   nuitka-project: --windows-console-mode=disable
#   nuitka-project: --mingw64

# NiceGUIアプリ向けに必要な設定
# nuitka-project: --noinclude-default-mode=error
# nuitka-project: --include-package-data=nicegui
# nuitka-project: --nofollow-import-to=doctest
# nuitka-project: --include-module=pygments.formatters.html

# 単体で実行可能なEXEファイルを作成する
# nuitka-project: --standalone
# nuitka-project: --onefile

from nicegui import ui

ui.label("Hello, world!")

ui.run(
    native=True,
    reload=False,
)
```

Nuitkaの実行は以下でOK

```bash
$ nuitka app.py
```

## 注意点

2024.11.24時点ではNuitkaの最新Verは2.5.1ですが、2.5から不具合があるようでNiceGUIアプリは起動に失敗します。まもなく修正される見込みのようですが、それまでは2.4.11を使用しましょう。
YOLO V11をonnx形式で使う

# 基本的な流れ

1. モデルの準備
1. 前処理
1. 推論
1. 後処理

# モデルの準備

pytorch形式で保存したモデルをonnxモデルにエクスポートする必要がある．
```path/to/weight.pt```部分は重みが保存されているパスに適宜変更する．
```dynamic=True```を行うには```pip install onnxslim```をしておく必要がある．

```python
from ultralytics import YOLO
model = YOLO("path/to/weight.pt")
model.export(format="onnx", imgsz=640, optimize=True, dynamic=False)
```

# 前処理

モデルの入力形式は以下の通りである．
左から順に，バッチ数，チャンネル数，高さ，幅となる．

```
input : (N, 3, 640, 640)
```

基本的に以下の処理をすれば，モデルに入力できる形式となる．
1. チャンネル変換
1. リサイズ
1. 正規化
1. 行列の転置
1. バッチサイズの値の付加

以下がそのサンプリングコードである．
```cv2.imread("path/to/img")```について，画像のパスを正しく設定する必要がある．動画の読み込みでも問題ない．

なお，今回は元のアスペクト比を維持するレターボックス加工ではないため，必要であればリサイズ処理部分でレターボックス加工を行えばよい．

```python
image = cv2.imread("path/to/img")
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB) # チャンネル変換
image_height, image_width = image.shape[:2] # 後処理で使う
image = cv2.resize(image, dsize=(640, 640)) # リサイズ
input_image = image / 255 # 正規化
input_image = input_image.transpose(2, 0, 1) # 行列の転置 (height, width, channel) -> (channel, height, width)
input_image = np.expand_dims(input_image, axis=0).astype("float32") # (channel, height, width) -> (batch, channel, height, width)
```

# 推論

以下のコードで推論できる
何度も推論するなら，```yolo_sess```の初期化をはじめに行えばよい．

```python
yolo_sess = onnxruntime.InferenceSession("path/to/weight.onnx")
yolo_input_name = self.yolo_sess.get_inputs()[0].name
yolo_output_name = self.yolo_sess.get_outputs()[0].name
yolo_result = self.yolo_sess.run([yolo_output_name], {yolo_input_name : input_image})[0]
```

# 後処理

モデルの出力形式は以下の通りである．
左から順に，バッチ数，検出結果，検出数である．

```
output : (N, 4 + number of class, 8400)
```

検出結果について，次の順番で格納されている．
バウンディングボックスの中心・バウンディングボックスの幅高さ・クラス確率である．
クラス確率はそのクラスである確率を示し，クラスの数だけ用意される．

```
[x_center, y_center, width, height, class0_score, class1_score,,, classN_score]
```

今回はクラス数が1，検出すべき物体数が1であるとし，bboxの左上と右下の座標を返すようにする．
基本的に以下の処理をすれば，上記のことができるようになる．

1. 行列の転置
1. bboxの座標変換とリサイズ
1. NMS処理
1. bboxの座標変換

以下がそのサンプルコードである．

```python
# 行列の転置
yolo_result = yolo_result[0]
yolo_result = yolo_result.transpose(1, 0)
yolo_result = np.ascontiguousarray(yolo_result)

# bboxの座標変換とリサイズ
x_center, y_center, width, height, score = yolo_result[:, 0], yolo_result[:, 1], yolo_result[:, 2], yolo_result[:, 3], yolo_result[:, 4]

x_min = (x_center - width / 2) * x_factor
y_min = (y_center - height / 2) * y_factor
width = width * x_factor
height = height * y_factor

bbox = np.stack((x_min, y_min, width, height), axis=1)

nms_indice = cv2.dnn.NMSBoxes(bbox.tolist(), score.ravel().tolist(), 0.5, 0.5, top_k=1)

if len(nms_indice) != 0:
    bbox = bbox[nms_indice[0]]
    score = score[nms_indice[0]]
    x_min = int(bbox[0])
    y_min = int(bbox[1])
    x_max = int(bbox[0] + bbox[2])
    y_max = int(bbox[1] + bbox[3])
```
ue5勉強日記2024/11/24 ビルドエラー

unrealを5.3から5.5にアップデートしたら、vs codeでビルド失敗した。
出たエラーは
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー
Engine\Source\Runtime\Core\Public\Experimental\ConcurrentLinearAllocator.h(31): error C4668: '__has_feature' is not defined as a preprocessor macro, replacing with '0' for '#if/#elif' 
C:\Epic Games\UE_5.3\Engine\Source\Runtime\Core\Public\Experimental\ConcurrentLinearAllocator.h(31): error C4067: unexpected tokens following preprocessor directive - expected a newlin
ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

 MSVCを最新にアップデートしたが、解消できず。

 色々調べて、下記のサイトでUnreal各バージョン必要の MSVCバージョン違うのをわかった。
https://ue5study.com/how/unrealengine-packaging-visualstudio-settings/

ダウンロードしたら解決しました。
ミュータブル、イミュータブルとは

>Rubyに限らず、プログラミングの世界ではしばしばミュータブルとイミュータブルという言葉が登場します。`ミュータブルは「変更可能な」`という意味で、反対に`イミュータブルは「変更できない、不変の」`という意味です。

# ミュータブルは破壊的な変更が適用される
>`ミュータブルなオブジェクトには破壊的な変更が適用`できます。そのため、配列の要素が同じオブジェクトを参照していると、`破壊的な変更によって本来変わってほしくない値まで一緒に変わってしまう`恐れがあります。例えばRubyの文字列（Stringクラス）はミュータブルなので、先ほど説明したように`ブロックを使わずに初期値に指定すると不具合が発生`します。

# イミュータブルなオブジェクトは破壊的な変更を適用できません。
>イミュータブルなオブジェクトでは破壊的な変更が適用できません。そのため、ブロックを使わずに初期値を設定しても、文字列で発生したような不具合は発生しないことになります。

https://gihyo.jp/book/2017/978-4-7741-9397-7

# 感想
>ブロックで初期値を指定しないと思わぬ不具合を作ってしまうと説明しますと...

今更だがブロックとは何か？
ブロックの初期値を指定することがわからなかった。あとでまた理解しよう
【別に普通に使えそう】kintoneでサブスクの管理を行う

個人利用の範囲ではあるんだけど、kintoneでサブスクを管理するアプリを作成した。作成時間は一時間程度、カスタマイズやプラグインは使用せず、標準機能のみでの作成だ。


## アプリ構成
- 「サブスク管理」
→入力を行うアプリ。構成は以下
![スクリーンショット 2024-11-24 16.12.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/80a7eb11-345c-06fc-f797-c4e55947c34d.png)
- 「サブスクマスタ」
→サービス名や料金を登録しておくマスタアプリ。「サブスク管理」アプリとルックアップで連携している。
![スクリーンショット 2024-11-24 16.13.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/54fc3640-b6ef-b0e0-6bf1-a6d369e2b3d0.png)
## 使用方法
1.___「サブスク」マスタにサービスを登録___
![スクリーンショット 2024-11-24 16.20.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/d41797c1-f1be-fe09-c29e-43f6f60f6f68.png)
- 「契約期間」フィールドで「年額」を選択した場合は、「料金」フィールドの値を12で割った値が「月額料金」へ自動計算で入力される。
- 「退会ページリンク」フィールドにリンクを入力しておくと、退会までの道のりを短縮することができるので入力推奨。

以下のように登録できる。
![スクリーンショット 2024-11-24 16.27.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/9d334b30-cebd-5e59-0fd7-e26d1f96c816.png)

2.___「サブスク管理」にデータを登録___
![スクリーンショット 2024-11-24 16.31.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/2c2dcf98-38ed-3db9-4274-da21b52269f8.png)
- こっちの入力も特に難しいことはなく、ルックアップでサービスを選択すれば、その他の情報も一緒に持って来れる。
- テーブル内の「月額料金」フィールドをもとに、テーブル下の合計値をそれぞれ算出している。
- 計算式が完全じゃない部分ではあるけど、「契約開始日」フィールドと「今日の日付」フィールドを使用して、各サブスクごとの契約期間も一覧することもできる。


一覧では以下のような見栄えになっている。
![スクリーンショット 2024-11-24 16.38.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3744216/0bd15a73-6a19-ff15-a3ca-81d8d13fadab.png)

## kintoneでやる必要性はないけど使えなくもない
サブスク管理はExcelもできるだろうしその他ツールも存在するので無理にkintoneで管理するメリットがあるかと言われればないんだけど、開発環境で一つ作っておいてブックマークに入れておけば気軽に使えることを考えれば全くなしの選択でもない気もする。

追加で、「解約リコメンド」機能や「退会済や休会中のステータス追加」などの機能を増やすこともできそうなので機会があればやってみたい。
The Web Developer Bootcamp完全日本語版の所感

## UdemyでWeb講義を受けた感想

#### 経緯
【2023最新版】世界で70万人以上が受講したThe Web Developer Bootcamp完全日本語版！これ一本でフロントエンドからバックエンド、セキュリティからアプリのデプロイを包括的に学ぶ。

上記の見出しに釣られ、講義を聞く。
今の段階では80％以上が完了している状況。
話を聞く中でモダンな開発どのようになっているのかになったのとサーバーサイドは基本的なスキルがあるが、フロントエンドのスキルが不足しているのが日々感じていたので、受講。


#### 主に学んだこと

 **フロントエンド**
 HTMLJavaScriptとBoostrap(CSSフレームワーク)


 **バックエンド**
 Express(フレームワーク)を使ってNode.js(バックエンド)の学習


最新の情報(2020年ごろ？)ではないので、2024年現在のバージョンではないので、最新については別途学習必要そう。
初心者でもわかるルーレットのゲーム理論と戦略の基本

## はじめに

ルーレットは、カジノの中でも特に人気の高いゲームの一つです。その魅力は、運の要素と戦略的な判断を組み合わせて楽しめる点にあります。しかし、「どの数字に賭けるべきか」「どのように賭け金を調整するべきか」といった疑問を持つ人も多いでしょう。この記事では、ルーレットの基本ルールを押さえながら、ゲーム理論の観点から戦略を解説します。初心者にも分かりやすいように、中学生レベルの日本語で説明しますので、ぜひ最後までご覧ください。

## ゲーム理論とは？ルーレットとの関係性

### ゲーム理論の基本

ゲーム理論とは、複数のプレイヤーが意思決定を行う際に、最適な行動を分析する学問です。たとえば、「相手がこう動くなら自分はどうするか」といった思考を体系化します。この理論は、経済学や心理学など多くの分野で活用されています。

ルーレットは、他のプレイヤーとの直接的な競争がないゲームです。それでも、ゲーム理論の概念を用いることで、リスクを管理しつつ効率的な賭け方を設計できます。たとえば、「資金をどう配分するか」や「どの賭け方を選ぶか」が該当します。

### ルーレットの仕組みと基本ルール

ルーレットは、円盤を回し、ボールが止まる番号や色を予測して賭けるゲームです。主な種類として「ヨーロピアンルーレット」と「アメリカンルーレット」があり、それぞれ以下の違いがあります。

- **ヨーロピアンルーレット**：0を含む37マス
- **アメリカンルーレット**：0と00を含む38マス

プレイヤーは、以下のような方法で賭けを行います。

- **シングルナンバー**：特定の数字1つに賭ける
- **赤または黒**：ボールが止まる色に賭ける
- **偶数または奇数**：数字が偶数か奇数かを予測

ヨーロピアンルーレットの方が有利であるため、初心者にはこちらがおすすめです。

## ルーレットの賭け方と期待値の関係

### 賭け方ごとの配当と確率

ルーレットでは、賭け方によって配当と当たる確率が異なります。以下は主な賭け方とその特徴です。

- **シングルナンバー**：配当は35倍。命中率はヨーロピアンルーレットで約2.7%。
- **赤または黒**：配当は2倍。命中率は約48.6%。
- **偶数または奇数**：配当は2倍。命中率は約48.6%。

どの賭け方も、カジノ側の利益（ハウスエッジ）が存在します。たとえば、ヨーロピアンルーレットではハウスエッジは約2.7%、アメリカンルーレットでは約5.26%です。

### 期待値とは？

<a href="https://roulette.jpn.org/expected-value/">期待値とは、長期的に見た場合に得られる平均的な利益のこと</a>です。ルーレットでは、どの賭け方をしても期待値が負になる仕組みになっています。

例として、ヨーロピアンルーレットの赤または黒に$1賭けた場合を考えます。

- 勝つ確率：18/37（約48.6%）
- 負ける確率：19/37（約51.4%）
- 期待値：($1 × 18/37) - ($1 × 19/37) = -$0.027

つまり、1ドル当たり約2.7セントの損失が見込まれる計算です。

## リスク管理と資金配分の基本

### 資金を守るためのポイント

ルーレットは運の要素が大きいゲームです。そのため、プレイヤーは賭け金を適切に管理する必要があります。以下のポイントを意識しましょう。

- **予算を決める**：最初に、1回のプレイで使う金額を設定します。
- **損切りラインを決める**：負けが続いた場合にどこで止めるかを決めておく。
- **勝利目標を設定**：目標金額に達したらゲームを終える。

### マーチンゲール法とそのリスク

ルーレットでよく使われる戦略の1つが「マーチンゲール法」です。この方法では、負けるたびに賭け金を倍にし、1回の勝利で損失を取り戻すことを目指します。

例：

1. 初回に$1賭けて負けたら、次回は$2賭ける。
2. さらに負けたら$4、$8と倍にする。
3. 勝てばこれまでの損失を全て回収。

ただし、この方法には以下のようなリスクがあります。

- **資金不足**：連敗が続くと賭け金が急増。
- **カジノの賭け上限**：賭け金が上限を超えると続行不可。

初心者はリスクを理解した上で使用を検討することが重要です。

## ゲーム理論に基づく戦略の考え方

### ミニマックス戦略の活用

ゲーム理論の一つに「ミニマックス戦略」という考え方があります。これは、最悪の結果を最小化しつつ、利益を最大化する方法です。ルーレットの場合、リスクを抑えながら楽しむことを目指します。

具体例：

- **複数の低リスク賭けを組み合わせる**：赤または黒と奇数または偶数の両方に賭ける。
- **賭け金を分散させる**：一箇所に集中せず、複数の場所に少額ずつ賭ける。

### ランダム性と心理のバランス

ルーレットは完全なランダム性で結果が決まるゲームです。しかし、プレイヤーは「前回赤が出たから次は黒が出るかも」といった心理的なバイアスに影響されやすいです。

このようなバイアスを避けるため、以下を心がけましょう。

- **過去の結果に惑わされない**：毎回独立した確率で結果が決まる。
- **冷静な判断をする**：直感ではなく、戦略に基づいて賭ける。

## まとめ

ルーレットは運と戦略を楽しむゲームであり、ゲーム理論を取り入れることでプレイの質が向上します。初心者はまず基本ルールを理解し、自分に合った賭け方や資金管理法を見つけることが大切です。

ゲーム理論に基づく戦略を活用することで、勝率を上げるだけでなく、より冷静にルーレットを楽しめるようになるでしょう。これを参考に、次のゲームをさらに充実したものにしてください！
RubyでLinuxコマンドを実行する

# 概要
サーバーのデプロイスクリプトをRubyプログラムから実行する必要がありました。

この機会に`Ruby`から`Linux`コマンドを実行する方法、テクニックについてまとめることにしました。

# 実行方法

Rubyからシェルスクリプトを実行するにはいくつか方法があります。

## バッククォート
標準出力が返される

```ruby
result = `sh deploy.sh`
```

## system
実行結果(true, false, nil)が返される

```ruby
system('mkdir hoge')
```

https://docs.ruby-lang.org/ja/latest/method/Kernel/m/system.html

> 子プロセスが終了ステータス 0 で終了すると成功とみなし true を返します。
それ以外の終了ステータスの場合は false を返します。
コマンドを実行できなかった場合は nil を返します。

## $?
最後に実行したシェルコマンドの終了ステータスを格納します。

```ruby
result = `sh deploy.sh`

if $?.success?
  puts "done"
else
  raise "exception has occurred"
end
```

# まとめ
活用機会は少ないと思いますが、参考になればと思います。

# 参考文献
https://qiita.com/tyabe/items/56c9fa81ca89088c5627
第五世代コンピューター計画の続きを

# 憧れの並列推論マシン
1980年代、20代だった私は国家プロジェクト「第五世代コンピューター計画」に憧れていました。まだ、世界のだれもが達成したことのない目標。渕先生の話でうっすら覚えているのはたしか「並列推論マシンをつくります。これがうまくいくと結果として人工知能もできるでしょう。」そんな話だったように覚えています。

世間的には第五は失敗だったと酷評されることが多いのですが、本当にそうでしょうか？あれから40年経過し確かに並列の時代が来ました。安価のPCでもマルチコアです。ラズパイでさえマルチコアで動作します。そしてDLによるAIの画期的な進歩。ChatGPTは私の技術の相談相手です。間違ったこともいいますけど、彼はなかなか博識です。

DLだけでは直観的な認識はできるようになりましたが、人間の高度な知性である論理的な推論が現在のAIの弱点であり次なる目標だと聞いています。推論といえば元祖、Prologです。


# 飯高茂先生の本を読みつつ
自作のN-Prologをほぼ完全にRUN/PROLOG（1980年代にライフボートから安価で販売されていた）と互換にしました。飯高先生の本をよみつつまったりとPrologのつもりだったのですが・・・

どうも計算速度が出てません。4メガLIPS程度ですから昔のPCに比べたら遥かにすごいのですけど。SWIに比べると見劣りします。コンパイラの改良をしつつ閃きました。「ああ、そうだ！並列だよ。」

# 分散並列Prolog
拙作のEasy-ISLispには並列機能を追加しました。分散並列も取り入れています。これを応用してN-Prologも分散並列にしてしまおう。ラズパイのような安価なマシンでクラスタマシンを作ったら楽しい、遊べるかも。

というわけで、個人プロジェクトをスタートさせて楽しく(ときに苦しく）やっています。

こんな仕様です。

```
npl -n: Launches child Prolog in network mode with the -n option.

dp_create([IP0,IP1, …,IPn]): Provides IP addresse of child machines to establish TCP/IP communication with the parent Lisp. IP addresse is provided as atom. e.g. '178.1.166.2'

dp-and([p0,p1, ...,pn]): It executes the predicates from P0 to PN in parallel. If all of them return YES, it returns YES. If even one returns NO, it returns NO.

dp_or([p0,p1, ...,n]): It executes the predicates from P0 to PN in parallel. If any one of them returns YES, it interrupts the other computations and returns YES.

dp_transfer(Fn): Transfers file Fn to all child machines from the parent machine.

dp_compile(Fn): Compiles file Fn on both parent and child machines.

dp_consult(Fn): Loads file Fn on both parent and child machines.

dp_prove(Nth,Pred): Prove Predicate on the Nth child Prolog for testing.

dp_report(Str): Display String on parent terminal.

dp_close: Sends termination command to child machines and closes communication.

```

第五計画においては並列用に設計されたGHC,KL1が活躍しました。私もGHCの本を読んだのですが、なかなか困難な問題が多いです。お手軽にPrologの仕様の枠内で並列を試みることにしました。


# 一歩づつ
いまのところ、下記の写真のような感じでよたよたと動き始めました。
![bandicam 2024-11-24 15-01-16-884.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33927/594e1475-8c50-10e2-206b-cdb08aa45c16.jpeg)

# 失敗は成功のもと
第五計画は失敗だったと批評されることが多いのですが、少なくとも私はそうは思っていません。世界のだれも挑戦していない野望に果敢に挑戦した先輩日本人たちに敬意を表しつつ、私なりに第五計画の続きをやろうと思っています。
ミュータブルなオブジェクトに対する破壊的変更を防ぐ

# 定数の値が変更されてしまう
```rb
irb(main):001* class Product
irb(main):002*   NAME = 'A product'
irb(main):003*   SOME_NAMES = ["Foo", "Bar", "Baz"]
irb(main):004*   SOME_PRICES = {"Foo" => 1000, "Bar" => 2000, "Baz" => 3000}
irb(main):005> end
=> {"Foo"=>1000, "Bar"=>2000, "Baz"=>3000}
irb(main):006> Product::NAME.upcase!
=> "A PRODUCT"
irb(main):007> Product::NAME
=> "A PRODUCT"
irb(main):008> Product::SOME_NAMES << "Hoge"
=> ["Foo", "Bar", "Baz", "Hoge"]
irb(main):009> Product::SOME_NAMES
=> ["Foo", "Bar", "Baz", "Hoge"]
irb(main):010> Product::SOME_PRICES["Hoge"] = 4000
=> 4000
irb(main):011> Product::SOME_PRICES
=> {"Foo"=>1000, "Bar"=>2000, "Baz"=>3000, "Hoge"=>4000}
```

# freezeでハッシュ、配列に対して破壊的な変更をできないようにする
```rb
irb(main):001* class Product
irb(main):002*   SOME_NAMES = ["Foo", "Bar", "Baz"].freeze
irb(main):003*
irb(main):004*   def self.names_without_foo(names = SOME_NAMES)
irb(main):005*     names.delete("Foo")
irb(main):006*     names
irb(main):007*   end
irb(main):008> end
=> :names_without_foo
irb(main):009> Product.names_without_foo
(irb):5:in `delete': can't modify frozen Array: ["Foo", "Bar", "Baz"] (FrozenError)
```

# しかしハッシュや配列の要素に対して破壊的変更が可能のままだ
```rb
irb(main):001* class Product
irb(main):002*   SOME_NAMES = ['Foo', 'Bar', 'Baz'].freeze
irb(main):003> end
=> ["Foo", "Bar", "Baz"]
irb(main):004> Product::SOME_NAMES[0].upcase!
=> "FOO"
irb(main):005> Product::SOME_NAMES
=> ["FOO", "Bar", "Baz"]
```

# 要素ぞれぞれに対してfreezeを行う
```rb
irb(main):001* class Product
irb(main):002*   SOME_NAMES = ['Foo'.freeze, 'Bar'.freeze, 'Baz'.freeze].freeze
irb(main):003> end
=> ["Foo", "Bar", "Baz"]
irb(main):004> Product::SOME_NAMES[0].upcase!
(irb):4:in `upcase!': can't modify frozen String: "Foo" (FrozenError)
```

# 
```rb
irb(main):001> SOME_NAMES = ["Foo", "Bar", "Baz"].map(&:freeze).freeze
=> ["Foo", "Bar", "Baz"]
irb(main):002> SOME_NAMES[0]
=> "Foo"
irb(main):003> SOME_NAMES[0].upcase!
(irb):3:in `upcase!': can't modify frozen String: "Foo" (FrozenError)
```

# イミュータブルなオブジェクトは破壊的に変更できない
```rb
irb(main):001* class Product
irb(main):002*   SOME_VALUE = 0
irb(main):003*   SOME_TYPE = :foo
irb(main):004*   SOME_FLAG = true
irb(main):005> end
=> true
```
https://gihyo.jp/book/2017/978-4-7741-9397-7

# 感想
* イミュータブルとは？
* ミュータブルとは?

https://qiita.com/masatom86650860/items/a721b3d1de558b699033
npm run buildで エラー　permission denied, unlink

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3832683/e3bf72b4-82b9-23a4-ff89-f482983927bb.png)

上記のエラーの解決策をメモ書き。
※tax_laravel_reactは自分のプロジェクトに変えてください。

## 解決方法

「権限の付与」これではうまくいきません。
```
chmod -R u+w /home/ubuntu/tax_laravel_react/public/build
```

単純に権限を付与すれば行けると思ったのですが
もっと単純にrootユーザーになればいけました・・・。


```
//rootユーザーに
sudo su

npm run build
```

ちなみに前のbuildが残ってても起こるようなので一応これでも治らなかったら以下のコマンドを
```
rm -rf /home/ubuntu/tax_laravel_react/public/build
```
【ペアワイズ法】PICT構文をVSCodeで見やすくする【QA】

# はじめに

以下の記事を書いたときに、VSCodeで*.pictを扱う際には、拡張子に「*.ini」を指定するといい感じの見た目になることを記載した。

が、拡張子「*.pict」のままでも良い、ちゃんとしたやり方があったのでメモ。

https://qiita.com/L_eu24/items/4ab413988a77a2ace5be

# pictファイルにiniファイル向けの着色を適用する

1. コマンドパレットをら引き、setttingファイルを開く。
   Preference: Opening Settings(JSON)
1. 以下を追記する。
```
"files.associations": {"*.pict": "ini"}
```


__イメージ__
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680589/599645e6-26b8-0e07-3165-580812971af3.png)

# おわりに
ちょっといい感じになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680589/c520b336-d442-3159-3ebb-4406ddd9428b.png)
Rust lang) ABC379 A - Cyclic

# code

```rust
use std::io::{stdin, BufRead};

fn main(){
    let std= stdin();
    let mut buf= std.lock().lines();
    let str_input= buf.next().unwrap().unwrap();
    let number: u64= str_input.parse().unwrap();
    let chars: Vec<char>= number.to_string()
        .chars()
        .collect();

    let string_one= format!("{}{}{}", chars[1], chars[2], chars[0]);
    let string_two= format!("{}{}{}", chars[2], chars[0], chars[1]);

    let number_1: u64= string_one.parse().unwrap();
    let number_2: u64= string_two.parse().unwrap();

    println!("{} {}", number_1, number_2);
}
```

![1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3918543/ea0c8ce4-1853-85c8-2f16-ed73e4721296.png)

# ref

https://atcoder.jp/contests/abc379/tasks/abc379_a
テスト自動化エンジニアシラバス：テスト自動化ツールと戦略を選択する評価プロセス

# はじめに

テスト自動化エンジニアのシラバスを再度読み直し、各章をDailyで読めるようにしてみた

https://www.istqb.org/certifications/test-automation-engineer

2.2 Evaluation Process for Selecting the Right Tools and Strategies を今回は翻訳・解説する

# テスト対象システムの分析と適切なテスト自動化ソリューションの決定

テスト対象システム（SUT）はそれぞれ異なりますが、成功するテスト自動化ソリューション（TAS）を作るためには、いくつかの重要なポイントを考える必要がある。

- 要件の収集
 テスト自動化エンジニア（TAE）は、SUTの範囲や機能を理解し、それに基づいて必要な要件を収集
- アプリケーションの種類
 ウェブサービス、モバイルアプリ、ウェブアプリなど、異なる種類のアプリケーションは、それぞれ異なるテスト自動化の方法が必要。
- ステークホルダーとの協力
 手動テスターやビジネス関係者と協力して、リスクやその対策を特定します。これにより、将来に役立つテスト自動化ソリューションを作ることができます。

このように、SUTの特性を理解し、関係者と協力してリスクを管理することで、効果的なテスト自動化を実現できる。

テスト自動化アプローチとアーキテクチャの要件を考える際には、以下のポイントを考慮する必要がある

- 自動化すべきテストプロセスの活動
 例：テスト管理、テスト設計、テスト生成、テスト実行など。
- サポートすべきテストレベル
 単体テスト、統合テスト、システムテスト、受け入れテストなど。
- サポートすべきテストタイプ
 機能テスト、性能テスト、セキュリティテスト、回帰テストなど。
- サポートすべきテストの役割とスキルセット
 テストエンジニア、テストマネージャー、開発者などの役割と、それぞれのスキルセット。
- サポートすべきソフトウェア製品、製品ライン、ファミリー
 実装されるTASの範囲と寿命を定義するために、どのソフトウェア製品や製品ライン、ファミリーをサポートするか。
- TASと互換性のあるSUTの種類
 テスト自動化ソリューションが対応する必要があるSUTの種類。
- テストデータの利用可能性とその品質
 テストデータがどの程度利用可能であり、その品質がどの程度か。
- 到達不可能なケースをエミュレートするための方法
 例：サードパーティアプリケーションが関与する場合など。

これらの要件を考慮することで、効果的で持続可能なテスト自動化ソリューションを設計することができます。

#  ツール評価の技術的な所見

SUTを分析し、これらの要件を満たすテスト自動化ツールを検討する。
すべての要件を満たす単一のツールは存在しない可能性が高い。

可能なツールに関する所見を記録し、直接的および間接的な要件を比較表に反映させることが役立つ（星取表）
比較表の目的は、特定の要件に基づいてツール間の違いを関係者に見せることです。

<b>ツールの評価基準</b>

テスト自動化ツールの評価にあたっては、以下の基準を考慮する必要があります。

1. 言語とテクノロジ
ツールがサポートする言語やテクノロジが、プロジェクトの既存の技術スタックに適合しているか。
テストスクリプトの開発とメンテナンスの容易さ。

2. 構成可能性
ツールのカスタマイズ性: 異なるテスト環境や実行構成に対応できるか。
動的または静的な設定値の利用が可能か。

3. テストデータ管理
テストデータの生成、管理、保管機能が充実しているか。
バージョン管理システムとの連携が可能か。

4. テストタイプのサポート
さまざまなテストタイプ（機能テスト、性能テスト、セキュリティテストなど）に対応できるか。

5. レポート機能
テスト結果をわかりやすくレポートできるか。
レポートのカスタマイズが可能か。

6. 統合性
CI/CDツール（Jenkins、GitLab CI/CDなど）との連携が可能か。
テスト管理ツール（TestRail、Jiraなど）との連携が可能か。
他のプロジェクトツールとの連携が可能か。

7. 拡張性とメンテナンス性
将来的な拡張やメンテナンスが容易か。
スケーラビリティ、変更可能性、互換性、信頼性に優れているか。

比較表の例

| 機能/要件 | ツールA | ツールB | ツールC | 優先度 |
|:-----------|------------|------------|------------|------------|
| スクリプト言語       |Python| Robotframework     | | 高| 
| オブジェクト識別       |     ◎     |       ×    | | 中| 
| テストデータ管理       |          |      ◎     | | 高| 
| CI/CD統合       |      △    |           | ◎| 中|
JetpackComposeで表示領域を測定する

# はじめに
今回は、JetpackComposeで、表示している領域を測定する方法を紹介します
### 本文
一般的に有名なの'BoxWithConstraints'をつかって'width'等を取得することかと思いますが、実はModifier事態にも似た機能は実装されています。
それが下記になります
```kotlin
.onGloballyPositioned { layoutCoordinates ->
                rect = Rect(
                    layoutCoordinates.boundsInRoot().left.toInt(),
                    layoutCoordinates.boundsInRoot().top.toInt(),
                    layoutCoordinates.boundsInRoot().right.toInt(),
                    layoutCoordinates.boundsInRoot().bottom.toInt(),
                )
            },
```
こうすることで、Modifierを付けている部品が画面内のどこに存在しているのかを取得することができます
### さいごに
BoxWithConstraintsだとわざわざ囲わないければいけませんが、今回紹介した方法であれば何か準備が必要というわけでもないので使い勝手がいいかと思います
Ｗｅｂデザイン入門　JavaScript/jQuery基礎

1.　サマライズ
 ・ console.logは検証用のもの
・例えば、console.log("こんにちは！");と記述し、正しく表示されるかというもの
・文字と文字を「＋」でくっつけられるというか、組み合わせられる
　例えば、console.log("Hello"+" " + "World!"); と記述、「Hello World!」と表示される
・四則演算が可能
　例えば、console.log(2/2/2/2/2/2);と記述、「0.0625」と表示されるとか、
　console.log(2+2);と記述「４」と表示されるとか足し算(+)、引き算(-)、掛け算(*)、割り算(/)が使える
・if文の条件分岐
　例えば、if関数、vlookup関数のネストや、if関数の条件分岐が似ている
　if Aなら、Bを、そうでなければCを実行するというもの
・以下は、このカリキュラムで後ほど習していくだろう。
・var変数名="値"で変数に値を代入できる
・functionを使用すると変数を宣言できる

2.言語化してみても気づき
・より楽しくなりそうだ！
・HTML5が出た時に断念したことが今解決できると思うとワクワクする。
Dockerで構築したMySQLのデータをボリュームで引き継ぐ

# はじめに
今まで別のコンテナでMySQLのデータを引き継ぐには、恥ずかしながらボリュームというのを知らず、毎回ダンプしていました。ダンプとリストアって割と手間なんですよね。なので、今回は新たに知ったボリュームを使った紹介したいと思います。

# ボリュームとは
ボリュームは、コンテナのデータを永続化するための仕組みです。通常、コンテナ内部のデータはコンテナ削除時に失われますが、ボリュームを利用すると
- コンテナ削除後もデータが保持される
- 複数のコンテナ間でデータを共有できる

というようなメリットがあります。

# ボリュームを作成し、MySQLコンテナにマウントする
### ボリュームの作成
 db-volumeというボリュームを作成します。
 ```zsh
 % docker volume create --name db-volume
db-volume
```
MySQLのデータを引き継ぐには、MySQLサーバーがデータを保存するディレクトリにボリュームをマウントする必要があります。デフォルトで、保存先は/var/lib/mysqlになっています。データの保存先はMySQLの設定ファイル(/etc/my.cnf)から参照できます。
```zsh
% docker container run --rm mysql:8.2.0 cat /etc/my.cnf | grep data
~ 省略 ~
datadir=/var/lib/mysql
~ 省略 ~
```
### MySQLコンテナの起動
db-volumeをマウントしてMySQLコンテナを起動します。
```zsh
% docker container run --name db1 --rm --detach  --env MYSQL_ROOT_PASSWORD=secret --env MYSQL_DATABASE=sample --publish 3306:3306 --mount type=volume,source=db-volume,destination=/var/lib/mysql mysql:8.2.0
dd96d2f1a304a1ca2cf41f0ec2801c8321dd3ef65176426fc96cdb37402ae8c6
```
MySQLサーバーに接続します。そして、テーブルを作成し、いくつかデータを挿入してみましょう。
```sql
mysql % mysql --host=127.0.0.1 --port=3306 --user=root --password=secret sample

mysql> create table user (name varchar(32), email varchar(32));
Query OK, 0 rows affected (0.06 sec)

mysql> INSERT INTO user (name, email) VALUES ('Alice', 'alice@example.com'), ('Bob', 'bob@example.com');
Query OK, 2 rows affected (0.03 sec)
Records: 2  Duplicates: 0  Warnings: 0

mysql> select * from user;
+-------+-------------------+
| name  | email             |
+-------+-------------------+
| Alice | alice@example.com |
| Bob   | bob@example.com   |
+-------+-------------------+
2 rows in set (0.01 sec)
```
このデータは/var/lib/mysqlに保存されました。そして、それはボリュームがマウントしているので、コンテナ内ではなく、ボリュームにデータは保存されています。

ここでdb1コンテナを停止します。
```zsh
docker container stop db1
```

### db1のデータを引き継ぐ
新たにdb2コンテナを起動しましょう！db1コンテナにマウントしたdb-volumeをdb2でもマウントします。起動方法はdb1と同じですが、環境変数は今回はボリュームを利用するので不要です。なぜならdb1を起動する際にすでに作成されているからです。
```zsh
% docker container run --name db2 --rm --detach --publish 3306:3306 --mount type=volume,source=db-volume,destination=/var/lib/mysql mysql:8.2.0
860f54f7d876dde1d768a34ec8820c92e870b749bce358c702bb7ace87c44dd1
```
ボリュームのおかげで、先程と接続情報は同じです。db2コンテナに、db1で追加したデータが有るか確認しましょう
```sql
% mysql --host=127.0.0.1 --port=3306 --user=root --password=secret sample

mysql> select * from user;
+-------+-------------------+
| name  | email             |
+-------+-------------------+
| Alice | alice@example.com |
| Bob   | bob@example.com   |
+-------+-------------------+
2 rows in set (0.01 sec)
```

db1コンテナのデータが消えずに引き継げていることが確認できました！
私も次からDockerでDBを構築するときは活用するようにしたいですね！
Mastodonインスタンスを閉鎖したときにnginxでHTTP 410 Gone を返す

Mastodonインスタンスを閉鎖したときに HTTP 410 Gone を返す設定をしたのでメモ

```nginx:mastodon.conf
# ================================================== #
#  Copyright (c) 2024 CIB-MC                         #
#  Released under the MIT license                    #
#  https://opensource.org/licenses/mit-license.php   #
# ================================================== #

server {
    server_name example.com;
    listen [::]:443 ssl http2;
    listen 443 ssl http2;
    access_log /var/log/nginx/access_example_com.log;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
    error_page 410 /410.html;
    location = /410.html {
        root /var/www/example.com/;
        internal;
    }
    location ~ ^/ {
        return 410;
    }
}

server {
    server_name example.com;

    listen [::]:80;
    listen 80;
    return 302 https://$host$request_uri;
}
```

```html:410.html
<!DOCTYPE html>
<html>
    <!--  Copyright (c) 2024 CIB-MC                        -->
    <!--  Released under the MIT license                   -->
    <!--  https://opensource.org/licenses/mit-license.php  -->
    <head>
        <meta charset="UTF-8">
        <title>HTTP 410 Gone</title>
    </head>
    <body>
        <p><strong>HTTP 410 Gone</strong></p>
        <p>本Mastodonインスタンスは運用を終了しました。<br>This Mastodon instance has been closed.</p>
    </body>
</html>
```
SwiftUI　Viewの大きさ取得方法

SwiftUIでViewの大きさ取得方法

```.swift
var body: some View {
    GeometryReader { geometry in
        VStack {
            Text("幅: \(geometry.size.width)")
            Text("高さ: \(geometry.size.height)")
        }
        .frame(width: geometry.size.width, height: geometry.size.height)
        .background(Color.blue)
    }
    .frame(height: 200)
    .frame(width: 300)
}
```

![Simulator Screenshot - iPhone 16 Pro - 2024-11-24 at 15.44.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/274615/a8e25eed-3f10-20b5-37bf-0db941cae037.png)


`GeometryReader`を使用するとViewの大きさを取得することができます。

`geometry.size.width`　横幅
`geometry.size.height`　高さ
【PHPフレームワークFlow】DoctrineORMを用いてインデックスやユニーク制約を貼る方法

# 初めに
Flowを使っていて、Doctrineでインデックスを貼る方法を理解していなかったので調べました。

# インデックスの張り方

Doctrineには`@ORM\Index`というアノテーションが用意されており、それを用いることで簡単にインデックスを張ることができます。


https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/reference/attributes-reference.html#attrref_index

## 例
```php
/**
 * @Flow\Entity
 * @ORM\Table(name="employee", indexes ={
 *     @ORM\Index(name="name_age_index", columns={"name", "age"})
 * })
 */
class Employee
{
    /**
     * @ORM\Column(type="string")
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(type="integer")
     * @var int
     */
    protected $age;
}

```

`SHOW CREATE TABLE `で確認したところ、`KEY `name_age_index` (`name`,`age`)`と記載されており、無事にインデックスが貼られていることが確認できました。
```sql
CREATE TABLE `employee` (
  `persistence_object_identifier` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` int NOT NULL,
  PRIMARY KEY (`persistence_object_identifier`),
  KEY `name_age_index` (`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
```

# 複合ユニーク制約を貼る
続いて、複合ユニーク制約についてです。
こちらは`@ORM\UniqueConstraint`アノテーションで指定できます。

https://www.doctrine-project.org/projects/doctrine-orm/en/3.3/reference/attributes-reference.html#attrref_uniqueconstraint

## 例
```php
/**
 * @Flow\Entity
 * @ORM\Table(name="employee", uniqueConstraints ={
 *     @ORM\UniqueConstraint(name="name_age_unique", columns={"name", "age"})
 * })
 */
class Employee
{
    /**
     * @ORM\Column(type="string")
     * @var string
     */
    protected $name;

    /**
     * @ORM\Column(type="integer")
     * @var int
     */
    protected $age;
}
```

こちらも無事作成されました。
（指定した名前がうまく反映されませんが、この理由は分からず、、、）
```sql
CREATE TABLE `employee` (
  `persistence_object_identifier` varchar(40) COLLATE utf8mb4_unicode_ci NOT NULL,
  `name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `age` int NOT NULL,
  PRIMARY KEY (`persistence_object_identifier`),
  UNIQUE KEY `UNIQ_5D9F75A15E237E06A13010B2` (`name`,`age`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci
```

# 終わりに
久しぶりにFlow関連の記事書きました。
Doctrine関連の理解が浅いので、もう少し学習していきたいです。

ここまで読んでいただきありがとうございました！
定数の再代入

# 定数はクラス外部から直接参照することも可能
```rb
irb(main):001* class Product
irb(main):002*   DEFAULT_PRICE = 0
irb(main):003> end
=> 0
irb(main):004> Product::DEFAULT_PRICE
=> 0
```
* クラス外部から定数を呼び出して何のメリットがあるのだろうか？

# private_constantで定数をクラスの外部から参照させたくない
```rb
irb(main):001* class Product
irb(main):002*   DEFAULT_PRICE = 0
irb(main):003*   private_constant :DEFAULT_PRICE
irb(main):004> end
=> Product
irb(main):005> Product::DEFAULT_PRICE
(irb):5:in `<main>': private constant Product::DEFAULT_PRICE referenced (NameError)
```
# メソッドの内部で作成することはできません
```rb
irb(main):001* class Product
irb(main):002*   def foo
irb(main):003*     DEFAULT_PRICE = 0
irb(main):004*   end
irb(main):005> end
irb:9:in `<top (required)>': (irb):3: dynamic constant assignment (SyntaxError)
    DEFAULT_PRICE = 0
```

# 定数の上書きができてしまうので気を付ける
```rb
irb(main):001* class Product
irb(main):002*   DEFAULT_PRICE = 0
irb(main):003*   DEFAULT_PRICE = 1000
irb(main):004> end
(irb):3: warning: already initialized constant Product::DEFAULT_PRICE
(irb):2: warning: previous definition of DEFAULT_PRICE was here
=> 1000
irb(main):005> Product::DEFAULT_PRICE
=> 1000
irb(main):006> Product::DEFAULT_PRICE = 3000
(irb):6: warning: already initialized constant Product::DEFAULT_PRICE
(irb):3: warning: previous definition of DEFAULT_PRICE was here
=> 3000
irb(main):007> Product::DEFAULT_PRICE
=> 3000
```

# クラスを凍結すると定数の再代入ができなくなる
```rb
irb(main):008> Product.freeze
=> Product
irb(main):009> Product::DEFAULT_PRICE = 5000
(irb):9:in `<main>': can't modify frozen #<Class:Product>: Product (FrozenError)
```

# freezeで再代入を防ぐこともできる
```rb
irb(main):001* class Product
irb(main):002*   DEFAULT_PRICE = 0
irb(main):003*   freeze
irb(main):004*   DEFAULT_PRICE = 1000
irb(main):005> end
(irb):4:in <class:Product>': can't modify frozen #<Class:Product>: Product (FrozenError)

irb(main):006> Product::DEFAULT_PRICE
=> 0
```
私が今までやって良かったと思うテスト勉強法（中学生）

１.テストの２週間前には対策を始める
　２週間も時間があれば、間違えた問題の解き直し、演習などたくさんやりたいことがで 
きます！
２.主に国語、英語をやる
　国語の力が付けば文章の読解力がつきます。これは、各教科の文章を読む時に活用できます！だからといって数学や理科、社会も大切ですよ。英語は、その他の教科と共通するところが少ないので率先してやりましょう！
 3.生活リズムは崩さない
 生活リズムを崩してしまうと、テスト中に眠くなってしまったり集中できなくなってしまったりするので、早寝早起きを心がけましょう！（10時頃に寝て5時頃に起きることが最適だと思います。）


 　　　　　　　　　　　　　　　　　　　　ぜひ皆さんも試してみて下さい‼️
テスト自動化エンジニアシラバス：テスト自動化を実現するためのインフラ構成

# はじめに

テスト自動化エンジニアのシラバスを再度読み直し、各章をDailyで読めるようにしてみた

https://www.istqb.org/certifications/test-automation-engineer

今回、2.1 Understand the Configuration of an Infrastructure to Enable Test Automation　を翻訳・解説する。

# テスト自動化の実装に必要なインフラ構成

テスト自動化の実装には、テスト対象システム（SUT）のテスト可能性（Testability）が重要です。
テスト可能性とは、システムの内部状態を観測し、制御するためのソフトウェアインターフェースが提供されているかどうかです。

ソフトウェアアーキテクトは、システムの非機能要件としてテスト可能性を考慮し、テスト自動化エンジニア（TAE）と協力して改善すべき点を特定する。


# テスト可能性を高めるための手法

## アクセシビリティ識別子

- UI要素の特定
 ボタン、テキストボックスなど、UI要素をプログラムで一意に識別するためのIDや名前のようなもの。
- 自動生成と手動設定
 開発フレームワークによっては自動生成されますが、より柔軟な制御が必要な場合は手動で設定することも可能。

例: SeleniumでWeb要素を特定する際のID属性、XPathなど

## システム環境変数とデプロイメント変数

- 設定の変更
 アプリケーションの動作を制御するパラメータを、環境変数やデプロイメント変数で設定することで、テスト環境に合わせて柔軟に設定変更できます。

例: テスト用データベースへの接続情報、ログ出力レベルなど

## アーキテクチャの透明性

- ドキュメントの重要性
 システムのアーキテクチャを明確に記述したドキュメントは、テストケースの作成やトラブルシューティングに役立つ。
- 観測性と制御性の確保
 各コンポーネントの役割やインターフェースが明確に定義されていれば、テスト対象を特定しやすくなる。

# テスト可能性のための設計要素

## Observability (観測可能性)
SUTは、その内部状態を外部から観測するためのインターフェースを提供する必要があります。
テストケースはこれらのインターフェースを使用して、実際の結果と期待される結果を比較できます。

- 内部状態の可視化
 システムの内部状態（変数の値、処理の経過など）を外部から確認できる必要があります。
- ログの出力
 処理の経過やエラー情報をログに出力することで、問題発生時の原因究明を容易にします。
- モニタリング
 システムの稼働状況をリアルタイムで監視し、異常を検出します。
- デバッグ用インターフェース
 開発者がシステムの内部状態を直接確認するためのデバッグ用インターフェースを提供します。


## Controllability (制御可能性)
SUTは、操作するためのインターフェースを提供する必要があります。
これには、UI要素、関数呼び出し、通信要素（TCP/IP、USB）、物理的または論理的なスイッチの電子信号などが含まれる。

- 入力の制御
 システムに与える入力（データ、イベントなど）を自由に制御できる。
- 状態の変更
 システムの状態を任意に設定できる。
- 処理の切り替え
 特定の処理を実行したり、スキップしたりできる。


## Architecture transparency (アーキテクチャの透明性)
アーキテクチャのドキュメントは、明確で理解しやすいコンポーネントとインターフェースを提供し、すべてのテストレベルでの観測可能性と制御可能性を確保し、品質を促進する必要があります。


# テスト自動化と様々な環境での活用

異なる種類の自動化テストは、さまざまな環境で実行できます。 
これらの環境はプロジェクトや手法によって異なる場合がありますが、ほとんどのプロジェクトでは、テストのために1つ以上の環境が利用されます。
技術的な観点から、これらの環境はコンテナ、仮想化ソフトウェア、その他の方法を使用して作成できます。

様々なテスト環境とその役割
テスト自動化では、以下のような様々な環境が活用されます。

## ローカル開発環境

- 開発者が自身のマシン上でコードを書き、小さな単位でテストを行う環境
- コンポーネントテストや単体テストが中心
- IDE（統合開発環境）を活用し、デバッグを行いながら開発を進めることができる

## ビルド環境

- コードをビルドし、基本的な動作確認を行う環境
- CI/CDツールと連携し、自動でビルドとテストを実行
- 静的解析やコンポーネント統合テストなどが行われる

## 統合環境

- 複数のコンポーネントを統合し、システム全体の動作を確認する環境
- UIテストやAPIテストなど、より広範囲なテストを実行
- モニタリングツールを導入し、システムの挙動を監視


## プレプロダクション環境

- 本番環境に近い環境で、最終的な品質確認を行う環境
- パフォーマンステストや負荷テストなど、非機能的なテストが中心
- ユーザー受け入れテスト（UAT）を実施し、ビジネス側の視点からシステムを評価する。

## 本番環境

- システムが実際に稼働する環境
- モニタリングツールを導入し、システムの異常を検知し、迅速に対応する必要がある
- カナリアリリースやブルーグリーンデプロイメントなどの手法を用いて、リスクを最小限に抑えながら新機能を導入
- A/Bテストなどのベストプラクティステスト
【2024年11月最新版】Word2Vec用コンテナのDockerfile

初めまして、Qiita初投稿の@kenken38です！
普段は教育業界に向けてパッケージ開発をしており、インフラ（AWS）からAI開発まで幅広く担当しています。

今回は自然言語処理で有名なWord2Vec（gensim）をコンテナで利用するためのDockerfileについて書きたいと思います。

# 結論
次のバージョンで構築します。
- OS : Ubuntu 24.04
- Python : 3.12.7
- Gensim : 4.3.3

```
# Ubuntu 24.04
FROM ubuntu:24.04

# 前準備
RUN apt -y update && apt -y upgrade

# 日本語化（別にやり方があるかも）
RUN apt install -y language-pack-ja locales \
    && locale-gen ja_JP.UTF-8 \
    && echo "export LANG=ja_JP.UTF-8" >> ~/.bashrc

# Pythonのインストール
# (参考)https://www.python.jp/install/ubuntu/index.html
RUN apt install -y build-essential libbz2-dev libdb-dev \
libreadline-dev libffi-dev libgdbm-dev liblzma-dev \
libncursesw5-dev libsqlite3-dev libssl-dev \
zlib1g-dev uuid-dev \
curl tar
# 公式サイトからPython3.12.7をインストールし、解凍してビルド
RUN curl -O https://www.python.org/ftp/python/3.12.7/Python-3.12.7.tar.xz \
    && tar xJf Python-3.12.7.tar.xz \
    && cd Python-3.12.7 \
    && ./configure \
    && make \
    && make install
# 不要なディレクトリの削除
RUN rm -rf Python-3.12.7 Python-3.12.7.tar.xz
RUN pip3 install --upgrade pip && pip3 install gensim==4.3.3
```

# 各パッケージの説明
- gensimは、word2vecを実装するためのデファクトスタンダード的なライブラリです。最新バージョンの4.3.3をインストールしています
- OSは機械学習でよく利用されるUbuntuを利用しています。こちらも現時点で最新のUbuntu24.04を導入しています
- Pythonは3.12.7を導入しています。現時点では3.13系がリリースされていますが、gensimは3.13系のwheelsを（恐らく）提供していないため、3.12系を導入しています。3.12系のwheels提供については[こちらを参照](https://github.com/piskvorky/gensim/issues/3510)
- 今回のコンテナは自然言語処理タスクを想定しているので、一応日本語化するコマンドも記載しました
JavaScriptの暗黙的リターンとは？徹底解説！

# はじめに
JavaScriptは柔軟性に富んだプログラミング言語ですが、その挙動の一部は一見すると不思議に感じるかもしれません。その中でも **「暗黙的リターン」** は、初心者にとって混乱しやすい概念の一つです。本記事では、暗黙的リターンの仕組みや注意点を分かりやすく解説します。

# 暗黙的リターンとは？
暗黙的リターン（Implicit Return）とは、特定の状況下で関数が明示的にreturn文を使用しなくても値を返す動作のことを指します。主に **アロー関数（Arrow Functions）** で利用されます。

# 実際にコードで書くと
```javascript
const isEven = funtion(num){ // 通常の関数
    return num % 2 === 0;
}
const isEven = (num) => { // 引数にカッコを使ったアロー関数
    return num % 2 === 0;
}
const isEven = num => { // 引数のカッコを使ったアロー関数
    return num % 2 === 0;
}
const isEven = num => ( // 暗黙的return 注意：{}ではなく()にする。
    num % 2 === 0;
);
const isEven = num => num % 2 === 0; // 暗黙的return（１行版）
```

# 暗黙的returnのメリット
1. コードが簡潔になる
短い関数を記述する場合、return文や中括弧を省略できるため、コードが読みやすくなります。

2. 無駄な記述を減らせる
使わなくてもよいコードが省けるため、エラーの発生源を減らせます。

# 暗黙的returnのデメリット
1. 複数行の処理には不向き
暗黙的リターンは1行の式でのみ機能するため、複雑なロジックを記述する場合には中括弧と明示的リターンを使うべきです。
```javascript
// 複数行のロジック
const processNumbers = (a, b) => {
    const sum = a + b;
    const diff = a - b;
    return { sum, diff }; // 明示的リターン
};
```

2. オブジェクトリテラルを返す場合の注意
オブジェクトリテラルを返すときは、()で括る必要があります。これは、{}がコードブロックとして解釈されるためです。
```javascript
// オブジェクトを返す場合
const createUser = name => ({ name, id: Date.now() });

console.log(createUser('Alice'));
// { name: 'Alice', id: 1633036800000 }
```

# まとめ
JavaScriptの暗黙的リターンは、特にアロー関数を用いる際に非常に便利な機能です。コードを簡潔にする一方で、複雑なロジックやオブジェクトリテラルを扱う際には注意が必要です。暗黙的リターンを適切に活用して、読みやすくメンテナンスしやすいコードを目指しましょう！
1秒に3回以上の点滅をさせてはいけないらしい

ソシャゲのような10連ガチャをJavaScriptで実装した際に、Webアクセシビリティの面で、
「1秒間に3回以上の点滅させてはいけない」
ということを学んだのでメモします。

デジタル庁が出しているウェブアクセシビリティ導入ガイドブックで定められていました。

https://www.digital.go.jp/resources/introduction-to-web-accessibility-guidebook

# 1秒間に3回以上点滅させてはいけない

> 　光の点滅を繰り返すと、光感受性発作等を誘発しやすくなります。1秒に 3回を超える点滅するコン
テンツを作ってはいけません。

1秒間に3回以上点滅させると、光感受性発作を引き起こす可能性があるためやってはいけない、とのことでした。

https://www.mhlw.go.jp/www1/houdou/1004/h0414-2.html

（こんな事件もありましたね）


# 点滅以外に気をつけること

点滅以外だと、以下3点がデジタル庁のウェブアクセシビリティ導入ガイドで「達成しないと利用者に重大な悪影響を及ぼすもの」として定められています。

**・音声の自動再生はさせない（もし自動再生させる場合は3秒以内の音声にとどめること）**
**・ダイアログを閉じられない状況にするなど、袋小路にさせない**
**自動でコンテンツを切り替えない（コンテンツの一時停止、非表示、停止の機能もつける必要がある）**

参考：https://www.persol-pt.co.jp/salesmarketingservice/blog/web_accessibility_03/#5

上2点についてはあんまり見ない気がしますが、自動でコンテンツを切り替えるカルーセルバナーを導入しているサービスはいっぱいみますね。

Vanilla JSでカルーセルバナーを実装しているなら、clearInterval や clearTimeoutで自動切り替え処理を停止するなどやりようはありそうです。

ただ、ライブラリのSwiper.jsを使ってカルーセルバナーを実装している場合はどうしているのでしょうね？
Swiper.jsでカルーセルバナーを実装しているサイトをよく見るのですが、Swiper.jsに自動切り替えの停止機能とかあるのかが気になります。
（軽く調べた感じでは停止機能はなさそうでした）

とりあえず、今後カルーセルバナーを実装する際は自動切り替えの停止ボタンもつけるように気をつけたいと思います。
テスト自動化エンジニアシラバス：SDLC

# はじめに

テスト自動化エンジニアのシラバスを再度読み直し、各章をDailyで読めるようにしてみた

https://www.istqb.org/certifications/test-automation-engineer

CTAL-TAEの 1.2 Test Automation in the Software Development Lifecycle　を今回、翻訳・解説する

# SDLC
## ウォーターフォールモデル
ウォーターフォールモデルは、各フェーズが順次進行する線形なモデル。
要件定義、設計、実装、検証、保守といったフェーズがあり、各フェーズは明確に区切られ、ドキュメント化される。
テスト自動化は通常、実装フェーズと並行して、もしくはその後に行われる。
ソフトウェアコンポーネントがテスト可能になる検証フェーズで、テストの実行される。

<b>テスト自動化の適用</b>
- 検証フェーズ
ソフトウェアが完成した後に、すべての機能を網羅的にテストするフェーズです。このフェーズで、機能テスト、性能テスト、セキュリティテストなどの自動化が中心となります。
- 回帰テスト
 新機能を追加したり、バグを修正したりした際に、既存の機能が壊れていないかを確認するテストを自動化します。

<b>メリット</b>
- テスト計画が立てやすい
 プロジェクトの初期段階からテスト計画を詳細に立てられる。
- テストケースの管理が容易
 テストケースを体系的に管理できる。

<b>デメリット</b>
- 変化に弱い
 後半のフェーズで要件が変更になると、テストケースの修正に時間がかかる可能性がある
- フィードバックが遅い
 実装タイミングが後工程のため、開発の後半までバグが見つからない可能性。


## Vモデル
Vモデルは、上流工程と下流工程がV字型に対応するモデル。
上流工程で定義された要件に対して、下流工程で検証・統合活動が行われる。
このモデルでは、コンポーネントテスト、コンポーネント統合テスト、システムテスト、システム統合テスト、受け入れテストといった伝統的なテストレベルが定義される。
各テストレベルに対して、テスト自動化フレームワークを導入することを推奨。

<b>テスト自動化の適用</b>

- 各テストレベルでの自動化
 各テストレベルに対応したテスト自動化フレームワークを導入し、テストを自動化する。


<b>メリット</b>

- 品質の高いソフトウェアを開発できる
 各フェーズでテストを行うため、品質の高いソフトウェアを開発できる。
- テストの漏れを防ぐ
 テストレベルが明確に定義されているため、テストの漏れを防ぐことができる。

<b>デメリット</b>

- 柔軟性に欠ける
 アジャイル開発のような変化に対応しづらい可能性がある。


## アジャイルソフトウェア開発
アジャイルソフトウェア開発では、ウォーターフォールやVモデルと異なり、テスト自動化エンジニアとビジネス関係者がロードマップ、タイムライン、テストの計画を決定することができる。
アジャイルでは、コードレビュー、ペアプログラミング、頻繁な自動テスト実行などのベストプラクティスが推奨される。
サイロ化を排除し、開発者、テスター、その他の関係者が協力することで、すべてのテストレベルを適切な範囲と深さで自動化し、スプリント内での自動化という目標を達成できる。

<b>テスト自動化の適用</b>

- 継続的なテスト
 スプリントごとにテストを繰り返し行い、ソフトウェアの品質を維持。
- テスト駆動開発（TDD）
 テストケースを先に作成し、それに合わせてコードを開発。
- デプロイパイプライン
 コードの変更が自動的にビルド、テスト、デプロイされるパイプラインを構築。

<b>メリット</b>

- 変化に強い
 顧客のフィードバックを迅速に反映できます。
- 品質の高いソフトウェアを短期間で開発
 継続的なテストにより、品質の高いソフトウェアを短期間で開発できる。

<b>デメリット</b>

- 計画が立てにくい
 スプリントごとに計画が変更になる場合があります。
- ドキュメントが不足しがち
 コードが中心となり、ドキュメントが不足する可能性があります。

# テスト自動化選定

## テスト対象システムの分析
テスト自動化ツールの選定にあたり、まずテスト対象システムを詳細に分析することが重要。

- アプリケーションの種類
 Webアプリケーション、モバイルアプリ、デスクトップアプリなど、アプリケーションの種類によって最適なツールは異なる。
- 技術スタック
 使用されているプログラミング言語、フレームワーク、データベースなど。
- テスト対象の機能
 テストする機能範囲を明確にすることで、必要なツール機能を絞り込むことができる。
- システムの規模
 システムの規模が大きいほど、より高度な機能を持つツールが必要になる場合がある。


## ツール機能の比較
様々なテスト自動化ツールには、それぞれ特徴的な機能があります。

- 記録・再生機能
 操作を記録し、再生することでテストケースをかんたんに作成できる機能。
- スクリプト作成機能
 プログラミング言語を用いて、より柔軟なテストケースを作成できる機能。
- オブジェクト認識機能
 画面上の要素を正確に識別し、操作できる機能。
- データ駆動テスト機能（データドリブン）
 テストデータを変えて繰り返しテストを実行できる機能。
- 並列実行機能
 複数のテストケースを同時に実行し、早くテストできる機能。
- レポート作成機能
 テスト結果をわかりやすくレポートとして出力する機能。
- そのほか
 CI/CDツールとの連携、バグ管理ツールとの連携など、他のツールとの連携がスムーズに行えるかなど。

## チームのスキルと経験
- プログラミングスキル
 チームメンバーのプログラミングスキルによって、選択するツールの難易度が変わる。
- テスト自動化経験
 過去のテスト自動化経験に基づいて、適したツールを選択。
- ツールの習得意欲
 新しいツールを学ぶ意欲が高いチームであれば、より高度なツールを選択できる。

# コスト
- ライセンス費用
 商用ツールは、ライセンス費用がかかる。
- 導入コスト
 ツールの導入には、初期設定や学習コストがかかる。
- メンテナンスコスト
 ツールを継続的に利用するためには、メンテナンス費用がかかる。

## ツール選定でその他の考慮事項
- オープンソースか商用か
 オープンソースツールは無料で利用できますが、サポート体制が弱い場合がある。商用ツールは、サポート体制が充実していることが多いですが、費用がかかる。
- コミュニティ
 ツールに関するコミュニティが活発であるか確認。
- 拡張性
 将来的に機能拡張が必要になった場合に、対応できるか確認。

## 適切なツールの選択プロセス
1. テスト対象システムの分析
 テスト対象を明確にする。
2. 必要な機能の洗い出し
 どのような機能が必要かを洗い出す。
3. 候補ツールの選定
 複数のツールを候補に挙げる。
4. 評価
 各ツールの機能、価格、コミュニティなどを比較評価する。
5. PoC (Proof of Concept)
 可能であれば、実際にツールを試してみる。
6. 決定
 最適なツールを選択する。
Replit Agentで3時間でアプリリリースしてみた

# replit agentで3時間で作る！お腹の調子を管理するヘルスケアアプリ開発

## はじめに
- React、typescript...なにそれ、美味しいの…な筆者がwebアプリ開発してみた
- 3時間までアプリデプロイまでできた
- replit agent控えめにすごすぎる

## きっかけ

「便秘気味だから、食事とお腹の調子を記録したいなぁ」

そんな些細な動機からのスタートでした。スマホのメモアプリで記録を取ろうとしても続かず、かといって既存のアプリは機能が多すぎて使いづらい...。

「自分が欲しい機能だけのシンプルなアプリを作れたら理想的なんだけどなぁ」

というわけで、replitでアプリ作成してみました。

## 完成したアプリの紹介

### メイン画面
![IMG_0404.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613798/65b3fcd4-5c74-d3ee-b0fa-878d4bfad95a.png)

### 食事記録画面
![IMG_0405.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613798/57eb7d5f-02c0-a5d7-36ec-f4a82a7ff8be.png)

### 記録確認機能
![IMG_0407.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613798/c58a2497-405a-407d-f570-9661a4222a08.png)

### 体調管理画面
![IMG_0408.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/613798/ef088f3c-90c4-0ade-d127-1f6a5697b1d2.png)
【Ruby】今日書いたコードの振り返り#1

# はじめに
こんにちは！アメリカの大学で語学を学びながら、独学でソフトウェアエンジニアを目指している者です。
たのしいRubyの中で、ファイルの内容から特定の行数を抽出する問題に取り組みました。
この問題は、Unixの`tail`コマンドと同じ動作を再現する機能を実装するものでした。
今回は、私が書いたコードと、答えのコードの2つを比較し、それぞれの特徴や違いを振り返ります。どちらも動作は似ていますが、設計の工夫や効率の違いを学ぶ良い機会になりました。

# 私が書いたコード
```ruby
def tail(last_lines, filename)
  File.open(filename) do |file|
    ary = file.readlines
    lines_whole = file.lineno
    start_lines = lines_whole - last_lines 
    puts ary.slice(start_lines, last_lines).join
  end
end

tail(3, "data.txt")
```

## コードの特徴
1. 全行を一度に読み込む
`file.readlines` を使用してファイル全体を配列として読み込むため、小規模なファイルでは問題ありませんが、大きなファイルではメモリ効率が悪くなる可能性があります。
2. 行番号の計算
全体の行数を取得し、指定された「抽出する行数 (`last_lines`)」から開始位置を計算しています。`slice` メソッドを使うことで、配列から必要な部分だけを抽出しています。
3. わかりやすい構造
初学者には処理の流れが直感的ですが、無駄な処理が含まれるため改善の余地があります。

rubyの勉強前にSQLとデータベースの勉強をしたのですが、その際にもすべてを読み込むという操作をやるとメモリ効率が落ちると書いてありましたので、実装するコードを書くことを踏まえるとあまりいいコードではないと思いました。

# 答えのコード 
あくまでもこれは模範解答のコードです。
このコードが一番効率的なコードかわからないのでご了承ください
もし、もっと効率的なコードがあれば教えていただけると嬉しいです

```ruby
def tail(lines, file)
  queue = Array.new
  open(file) do |io|
    while line = io.gets
      queue.push(line)
      if queue.size > lines
        queue.shift
      end
    end
  end
  queue.each { |line| print line }
end

puts "==="
tail(10, "data.txt")

puts "==="
tail(3, "data.txt")
```
## コードの特徴
1. 行を順次処理する
ファイルを1行ずつ読み込むため、メモリ効率が良い設計です。特に大規模ファイルを扱う場合でも、必要以上のメモリを消費しません。
2. キューによる管理
`queue` を使い、最新の指定行数だけを保持します。古い行は`queue.shift`によって削除されます。
3. 柔軟性
ファイル全体を扱うことなく動作するため、行数の増減やファイルサイズの変化にも対応可能です。


# まとめ 
| 　　　　　観点 　　　　| 自分が書いたコード                   |　答えのコード　|
|:---------------------|:----------------------------------|:-------------|
| メモリ効率             |ファイル全体を読み込むため効率が悪い   |1行ずつ処理するため効率が良い   |
|  ファイルサイズの対応   |  小規模ファイル向き                 | 	大規模ファイルにも対応  |
| 理解のしやすさ          | 	初学者にとって直感的だが、行番号計算が不要な点に気づきにくい            |	キューの仕組みがやや複雑   |
|  処理の柔軟性          |  		行番号を計算する必要があり硬直的               |  	最新の行数のみを保持する柔軟な設計 |

今回の振り返りを通して、コードの効率や設計を振り返ることの重要性を改めて実感しました。
次回以降は、無駄のない設計を目指して実装を工夫してみたいと思います！