OmniAICreator/Qiita-1.07M huggingface dataset:
他人が作ったコードをリファクタリングしてみる part1 @uni928

今回は他人が作った下記のコードを
「メソッド数は増やしたくない」
「変数名を変える作業をしたくない」
という条件でリファクタリングします。

```javascript:リファクタリング前のコード
function createOutPng() {
	let ulx=outputUl%(row*2+1);
	let uly=Math.floor(outputUl/(col*2+1));
	let drx=outputDr%(row*2+1);
	let dry=Math.floor(outputDr/(col*2+1));

	let tulx=areaX+(boxSize/2)*ulx;
	let tuly=areaY+(boxSize/2)*uly;
	let tdrx=areaX+(boxSize/2)*drx;
	let tdry=areaY+(boxSize/2)*dry;

	let imageData=document.getElementById("outputcanvas").getContext("2d").getImageData(tulx, tuly, (tdrx-tulx), (tdry-tuly));

	let canvas=document.createElement("canvas");
	canvas.width=(tdrx-tulx);
	canvas.height=(tdry-tuly);
	canvas.getContext("2d").putImageData(imageData, 0, 0);
	let png=canvas.toDataURL("image/png");//console.log(png);

	let newImg=document.createElement("img");
	newImg.src=png;
	newImg.style.position="absolute";
	newImg.style.zIndex="14906";
	newImg.style.left="200px";
	newImg.style.top="120px";
	newImg.id="outputimg";
}
```

コードを見ただけでは
分からない箇所がほどんどだと思われますが
皆さんならばどのようにリファクタリングしますか？

コードの内容が分からないなりにで良いので
よろしければ一度考えてみて下さい。

考えて頂けましたか？
私は下記のようにリファクタリングしました。

このコードはリファクタリングが難しいため
せめてスコープが分かりにくい点を
修正してみたいと思います。

```javascript:リファクタリング後のコード
function createOutPng() {
	let ulx=outputUl%(row*2+1);
	let uly=Math.floor(outputUl/(col*2+1));
	let drx=outputDr%(row*2+1);
	let dry=Math.floor(outputDr/(col*2+1));

	let tulx=areaX+(boxSize/2)*ulx;
	let tuly=areaY+(boxSize/2)*uly;
	let tdrx=areaX+(boxSize/2)*drx;
	let tdry=areaY+(boxSize/2)*dry;

    ulx = uly = drx = dry = undefined; //修正点1

	let imageData=document.getElementById("outputcanvas").getContext("2d").getImageData(tulx, tuly, (tdrx-tulx), (tdry-tuly));

	let canvas=document.createElement("canvas");
	canvas.width=(tdrx-tulx);
	canvas.height=(tdry-tuly);
	canvas.getContext("2d").putImageData(imageData, 0, 0);
	let png=canvas.toDataURL("image/png");//console.log(png);

	tulx = tuly = tdrx = tdry = undefined; //修正点2

	let newImg=document.createElement("img");
	newImg.src=png;
	newImg.style.position="absolute";
	newImg.style.zIndex="14906";
	newImg.style.left="200px";
	newImg.style.top="120px";
	newImg.id="outputimg";
}
```

```javascript:修正点1
ulx = uly = drx = dry = undefined; //修正点1
```

と
```javascript:修正点2
tulx = tuly = tdrx = tdry = undefined; //修正点2
```

を追記しました。

このリファクタリングの狙いについて
紹介したいと思います。

***

修正点 1 の狙い

```javascript:修正点1
ulx = uly = drx = dry = undefined; //修正点1
```

を追記した狙いは
これらの変数が以降で使わない事が
すぐに分かるようにするためです。

ulx と tulx が混在しているため
この行を書かないと

canvas.width=(tdrx-tulx);
canvas.height=(tdry-tuly);

の箇所を読む際に
少し混乱してしまいます。
混乱しないために undefined に戻します。

***

修正点 2 の狙い

```javascript:修正点2
tulx = tuly = tdrx = tdry = undefined; //修正点2
```

を追記した狙いは
修正点 1 とは異なり
「ここまで使用する」事が
一目で分かるようにするためです。

getImageData で使った後は
これらの変数はもう使わないように
見えてしまうため、
後ろの方で undefined に設定しているのを見て	
「まだ使うんだ」という気づきに
繋がる可能性があります。

***

以上特定のコードをリファクタリングする
第 1 弾を公開しました。

スコープを分かりやすくするため
undefined に設定する手法を紹介しました。

undefined に設定することで
「この変数はもう使わない」
「この変数はここまで使う」
というのが一目で分かるという結論でした。

皆さんは使わなくなった変数は
undefined に戻していますか？
よろしければコメント下さい。

皆さんが他人のコードを
リファクタリングする際の
参考になれますように。

閲覧ありがとうございました。
[ChatGPT API]出力の繰り返しを減らしたい

## これはなに？

このガイドでは、ChatGPT APIの出力における繰り返しを減らす方法について説明する。`frequency_penalty` と `presence_penalty` は、生成AIが出力する文章のパターンやトピックをコントロールするためのパラメータであり、それぞれ、同じ単語やフレーズの繰り返しを抑えたり、新しいトピックに話題を切り替えたりするのに使う。

- **frequency_penalty**: 文章内で同じ単語が何度も出てくるのを防ぐためのパラメータ。この値を高くすると、同じ単語が繰り返されにくくなり、文章の繰り返しを抑える。
- **presence_penalty**: これまで使われていない単語を使うように促すパラメータ。値を高くすると、新しい単語を生成しやすくなり、文章に新鮮さが生まれる。

## 対象読者

- 生成AIの応答に多様性を持たせたい開発者
- テキスト生成の細かな制御を学びたい人
- 自然な対話や記事生成に関心のあるAIエンジニア

## ゴール

- `frequency_penalty` と `presence_penalty` の基本的な仕組みを理解し、どのように応答に影響を与えるかを例を通して把握する。
- テキスト生成において、繰り返しの抑制やトピックの変更を意図的に行う方法を学ぶ。

## TL;DR

`frequency_penalty` は、生成されたテキストで同じ単語やフレーズが繰り返される頻度を抑えるパラメータ。正の値にすると、繰り返しが減る。  
`presence_penalty` は、新しいトピックや単語を含むように促すパラメータ。正の値にすると、新しい話題に移行しやすくなる。

## frequency_penalty と presence_penalty の使い方

### frequency_penalty

**用途**  
同じ単語やフレーズが何度も繰り返されるのを防ぐ。例えば、文章内で同じ単語が頻繁に出てくるのを避けたいときに使える。

**数値の範囲**  
- 値の範囲: -2.0 ～ 2.0  
- 0 の場合は繰り返しに対してペナルティがなく、正の値で繰り返しを減らす。負の値にすると逆に繰り返しが増える。

**具体例**  
- frequency_penalty = 0 の場合:  
  "I like cats. Cats are cute. Cats are fun."
  
- frequency_penalty = 2.0 の場合:  
  "I like cats. They are cute. Felines are fun."  
  （単語 "cats" が繰り返されず、他の言葉に置き換えられる）

- frequency_penalty = -2.0 の場合:  
  "I like cats. Cats are cute. Cats are fun. Cats are amazing. Cats are everything!"  
  （同じ単語 "cats" が非常に多く繰り返される）

### presence_penalty

**用途**  
同じ話題にとどまらず、新しいトピックや単語に移る可能性を高める。特定のトピックから脱却したいときに便利。

**数値の範囲**  
- 値の範囲: -2.0 ～ 2.0  
- 0 の場合はペナルティがなく、正の値にすると新しいトピックが生成されやすくなる。負の値にすると同じトピックにとどまりやすくなる。

**具体例**  
- presence_penalty = 0 の場合:  
  "Let's talk about cats. Cats are lovely animals."

- presence_penalty = 2.0 の場合:  
  "Let's talk about cats. Speaking of pets, dogs are also amazing."  
  （話題が猫から犬に移っている）

- presence_penalty = -2.0 の場合:  
  "Let's talk about cats. Cats are lovely. Cats are great. Cats are my favorite."  
  （同じ話題、猫にとどまり続ける）

## 参考文献

- [OpenAI API ドキュメント](https://platform.openai.com/docs/advanced-usage/frequency-and-presence-penalties)
PHPにおけるメモリ使用量の計測とログ出力

PHPでメモリ使用量を計測し、処理前後でその変化をログに記録する方法を解説します。
パフォーマンスを監視し、リソースの無駄遣いを防ぐ際に役立ちます。

## メモリ使用量の計測に使用する関数
PHPには、現在のスクリプトのメモリ使用量を取得するための関数がいくつか用意されています。その中でも、よく使われるのが memory_get_usage() です。この関数は、メモリ使用量をバイト単位で返してくれます。

### `memory_get_usage` の使い方

```php
$memoryUsage = memory_get_usage();
```
これで、スクリプトが使用しているメモリのバイト数が取得できます。また、memory_get_usage(true) と引数に true を指定すると、システムに割り当てられたメモリ（未使用分も含む）を取得できます。

## メモリ使用量をメガバイト単位で取得する
memory_get_usage() はバイト単位の数値を返しますが、メガバイト（MB）単位に変換した方が見やすいです。なので、1024で2回割ります。

```php  
$memoryUsageInMB = memory_get_usage(true) / 1024 / 1024;
```
これで、MB単位で取得できます。

## 処理の前後でメモリ使用量を計測する
以下の例では、ある処理を行う前後でメモリ使用量を計測し、変化をログに記録しています。

**コード例**
```php
public function exampleMethod(SomeModel $model)
{
    // 処理前のメモリ使用量を計測
    $memoryUsageBefore = memory_get_usage(true) / 1024 / 1024;
    Log::info('Used memory before process: ' . $memoryUsageBefore . ' [MB]');

    // 何らかのメモリを消費する処理を実行
    $this->performSomeProcess($model->relatedData->someId);

    // 処理後のメモリ使用量を計測
    $memoryUsageAfter = memory_get_usage(true) / 1024 / 1024;
    Log::info('Used memory after process: ' . $memoryUsageAfter . ' [MB]');
}
```

### ログ出力の例
```less
[2024-10-04 10:00:00] local.INFO: Used memory before dispatch: 12.34 [MB]
[2024-10-04 10:00:05] local.INFO: Used memory after dispatch: 15.67 [MB]
```
上記のように、処理前後のメモリ使用量をログに記録することで、メモリ消費量を簡単に把握できます。
カスタマイズ可能なテキスト変換ツールの実装

## はじめに

Web開発やテキスト処理において、特定のパターンに基づいてテキストを変換する必要性は頻繁に発生します。今回は、JavaScriptを使用して柔軟で使いやすいテキスト変換ツールを実装する方法を紹介します。

https://code-plus.jp/gp/replace-text-multirules/

## 主な機能

1. JSONベースの置換ルール
2. 双方向変換（正変換と逆変換）
3. スペース（半角・全角）の可視化
4. クリップボードへの自動コピー

## コードの解説

### 1. 置換ルールのパース

```javascript
function parseReplacementRules(ruleText) {
  try {
    return ruleText.split('\n')
      .filter(line => line.trim() !== '')
      .map(line => JSON.parse(line));
  } catch (error) {
    console.error('置換ルールのパースに失敗しました:', error);
    return null;
  }
}
```

この関数は、テキストエリアに入力された置換ルールをJSONとして解析します。各行が `["from", "to"]` 形式のJSON配列として解釈されます。

### 2. テキスト置換

```javascript
function replaceText(codeText, rules) {
  return rules.reduce((text, [from, to]) => {
    const regex = new RegExp(from.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
    return text.replace(regex, to);
  }, codeText);
}
```

`replaceText` 関数は、パースされた置換ルールを適用してテキストを変換します。正規表現を使用してグローバルに置換を行います。

### 3. スペースの可視化

```javascript
function visualizeAreaSpaces(textArea, id) {
  const text = textArea.value;
  const visualizedText = text
    .replace(/ /g, '<span class="half-space"> </span>')
    .replace(/　/g, '<span class="full-space">　</span>');
  
  removeSpaceVisualization(id);
  
  const div = document.createElement('div');
  div.id = id;
  div.classList.add('space-shown');
  div.innerHTML = visualizedText;
  textArea.insertAdjacentElement('afterend', div);
}
```

この関数は、テキストエリア内の半角スペースと全角スペースを可視化します。可視化されたテキストは、元のテキストエリアの直後に挿入されます。

## 活用シーン

このツールは以下のような場面で特に役立ちます：

1. **コーディングスタイルの変換**: 異なるコーディング規約間でのスタイル変換（例：スネークケース→キャメルケース）

2. **単位の変換**: CSSにおけるpx→remの変換など

3. **テキストフォーマットの調整**: 特定のフォーマットに合わせたテキストの整形

4. **多言語対応**: 特定の文字や単語の置換による簡易的な多言語対応

5. **データクレンジング**: 特定のパターンに基づいたデータの整理や正規化

## まとめ

このカスタマイズ可能なテキスト変換ツールは、柔軟性と使いやすさを兼ね備えています。JSONベースの置換ルールにより、ユーザーは簡単にカスタム変換ロジックを定義できます。また、スペースの可視化機能は、見えないスペースに起因するバグの発見に役立ちます。
DXライブラリで新規プロジェクト作成の WinMain の警告を消す

DXライブラリで新規プロジェクト作成をしたら警告が出た。

※**Visual Studio 2022 Community使用**

過去にはこんな事はなかったが、かなり久々なんでC++に ~~余計な~~ 新機能が増えたんだろう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/660f97cb-d6a5-2034-453a-dea8452500c6.png)


元の WinMain の行を下の様に直せば消える
```diff_c
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_  HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nShowCmd)
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76087/aa47d1da-f4e9-504a-28d8-f5b6d2e5b8ff.png)

できれば元の WinMain のまま警告を無くしたかったが、時間がかかりそうなので止めた

参考サイト
https://replication.hatenablog.com/entry/2019/05/05/225954#:~:text=c++.%20%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB.
基本情報技術者試験の勉強法に困っているあなたへ

今回の記事では基本情報技術者試験を受けてみて使った参考書等を紹介していきます。

# 今回の受験結果
腕試しとして重要な部分しか勉強せず受験しました。
科目Aは615点で合格ラインに到達していましたが、科目Bは505点で不合格でした。

# 勉強法
基本情報は範囲が広すぎたので過去問はあまりやりませんでした。
科目Aはとにかく動画を見て、ここは重要です・よく出題されますといった部分のみ問題をやり、勉強を進めました。
科目Bについては科目Aとかぶっているセキュリティのみ動画で対策をしました。

# 使用した参考書等
- 動画
    - 【2024年】基本情報技術者試験の科目Aを12時間で完璧に理解
    - https://youtu.be/oqaBEnhIxk0?feature=shared

この動画でのみ勉強したと言っても過言ではないくらいこれ以外ほとんど使いませんでした。


- 科目A参考書

https://gihyo.jp/book/2023/978-4-297-13827-1

説明が分かりやすいです。その代わり分厚いので厚さを見るだけでやる気が削がれていました。

- 科目B参考書

https://www.shoeisha.co.jp/book/detail/9784798182520

全てこの本の内容を理解できれば科目Bが解けるんだろうなと思うような参考書でした。

# 最後に
ここまで読んでいただきありがとうございました。
参考になりますと幸いです。
【Rails】typeという名前のカラムがあるとエラーが出る

## はじめに
DBにtypeという名前のカラムがある時にエラーが出たので、その対応をまとめます。

## 問題
エラー文
```ruby
ActiveRecord::SubclassNotFound (Invalid single-table inheritance type: xxx is not a subclass of yyy):
```

## 解決方法
typeカラムの名前を変更することでも対応できますが、それが難しい場合は以下のようにすることで対応できます。
```ruby
class User < ApplicationRecord
  self.inheritance_column = :_type_disabled # この行を追加
end
```

## 参考
https://qiita.com/ryonext/items/1a813639ab2a2a00058e
Playwrightで正規表現を使って要素を特定する方法

# はじめに
Playwrightを使って自動化テストを行う中で、特定のボタンやリンクをクリックする際、名前が似た要素が複数存在するとエラーになることがあります。
今回は、特に「ピンどめ」というボタンが複数存在するケースに対して、**正規表現**を使って解決した方法を紹介します。
## 問題の背景
例えば、同じページに以下のような2つのHTMLがあったとします。
```html:html
<button type="button">ピンどめ 0</button>
<button type="button" aria-label="メッセージをピンどめ">...</button>
```
複数のボタンに「ピンどめ」というテキストや属性が含まれている場合、
```ts:ts
getByRole('button', { name: 'ピンどめ' })
```
を使うと、どのボタンをクリックすればいいのかPlaywrightが迷ってしまい、エラーになります。
```ts:ts
getByRole('button', { name: 'ピンどめ 0' })
```
と指定してもいいですが、数字の「0」の部分は可変する可能性があります。
## 解決策：正規表現の利用
このような場合に有効な解決策として、正規表現を利用することで解決できました！今回は、ピンどめという文字列に加えて、その後に続く数字（例: ピンどめ 1）を特定するために、正規表現を使いました。

以下はその解決策です。
```ts:ts
const pinButtonPattern = new RegExp(`ピンどめ\\s\\d+`);
await page.getByRole('button', { name: pinButtonPattern }).click();
```
#### 正規表現のポイント
* ピンどめ\\s\\d+：この部分が正規表現で、「ピンどめ」に続く1つ以上のスペース（\s）と、その後の数字（\d+）を指定しています。
* これにより、「ピンどめ」という名前を持ち、かつ後ろに数字が付いているボタンのみを特定できるようになります。
# まとめ
Playwrightでは、単純な文字列だけでなく、正規表現を使って柔軟に要素を特定することができます。特に、今回のように「名前が似ている」要素が多いケースでは、正規表現が役立ちます。今後、同じような問題に直面した際には、ぜひ正規表現を使ったアプローチを試してみてください。
Yoomからメールを送る


メールを送るオペレーションを使えばメールを送ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/fbac49e4-353f-6059-61d5-b2ed0cb3487c.png)

今回は取得した値がNullの時に後続処理がエラーになるのでメール通知を行うことにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/97382f15-cf2c-2ed0-9f81-7680191c5d54.png)

タイトル：yoom連携エラーメール送信
宛先：　{{yoomエラーアドレス (yoom_email_address__c)}}　
これはSalesforceのカスタム設定に登録したアドレスを使っています。宛先が変更になってもカスタム設定を変更すればプロジェクトの修正は不要です。Yoomの中でグローバル変数的なものがあればいいのですが....

差出人の名前：yoomジョブカン用

本文 :

```
社員ナンバーからSalesforceのユーザを検索できませんでした。

社員No：{{申請ユーザのスタッフコード}}

https://ssl.wf.jobcan.jp/#/requests/{{申請ID}}
```

ジョブカンのURLも記載することでエラーになった申請に飛ぶことができます。

別のパターンの本文

```
Salesforceの申請情報を追加できませんでした

https://ssl.wf.jobcan.jp/#/requests/{{申請ID}}
```
Amazon ElastiCacheについて

## はじめに
こんにちは。開発部のMです。
今回は「Amazon ElastiCache」についてご紹介します。

## Amazon ElastiCacheとは
AWSが提供するインメモリ型データベースサービスです。インメモリ型データベースとはデータストレージにメモリを使用するデータベースのことです。SSDのようなディスクストレージよりも高速・安定したアクセスが可能で高頻度で参照するデータや検索に時間がかかるデータセットをメモリ上に保持することでシステムのパフォーマンスを向上させることができます。

## ElastiCacheのデータベースエンジン
ElastiCacheは「Memcached」と「Radis」の二種類のエンジンをサポートしています。
### Memcached
事実上、KVS(Key-Valueストア)型インメモリデータベースの標準として広く利用されています。高パフォーマンスですがデータの永続性やレプリケーション機能はないので、障害や再起動が発生した場合はデータは残りません。保持しておかなければならないデータはストレージや他のデータベースサービスへ保存しておき、アプリケーションの高速化を目的としてキャッシュとして利用する場合に向いています。
### Radis
KVS型インメモリデータベースであることはMemcachadと同じですがMemcachadよりも高機能なデータベースエンジンです。スナップショット(S3への保存)機能によりバックアップ・リストアが可能でデータを永続的に保持しておくことができます。また自動フェイルオーバー(障害発生時の切り替え)やマルチAZの機能により高可用性があります。
さらに保管しているデータの暗号化やSSL/TLSによる通信の暗号化、クライアントをパスワードで認証するRadis認証を行うことができ機密性も提供されています。

## 最後に
高速アクセスを実現するElastiCacheはアプリケーションのパフォーマンス向上に役立つことがわかりました。

はつかぜ株式会社では、IT学習や業務に役立つ情報を定期的にお届けしていきたいと思っています。
システム開発のお問い合わせ・ご相談はこちら
https://www.hatsukaze.co.jp/inquire/
ABC374 C - Separated Lunch

## はじめに

10/5開催のABC372のC問題の復習です。

https://atcoder.jp/contests/abc374/tasks/abc374_c

## 問題文
キーエンス本社に勤務する人数が増えてきたので、本社に存在する部署を$2$つのグループに分け、昼休みの時間帯を分けることにしました。

キーエンス本社には$N$個の部署が存在し$i$番目$(1≤i≤N)$の部署に所属する人数は$K_i$人です。

それぞれの部署をグループ$A, B$のいずれか一方に割り当て、グループごとに同時に昼休みをとり、 かつグループ$A, B$の昼休みの時間が重ならないようにしたとき、同時に昼休みをとる最大人数としてあり得る最小の値を求めてください。
すなわち、グループ$A$に割り当てられた部署に所属する人数の合計とグループ$B$に割り当てられた部署に所属する人数の合計 のうち大きい方の値としてあり得る最小の値を求めてください。

## 考え方
すべての部署を$A,B$の$2$グループに分けて、最大値が小さい分け方を探す。
部署$N$が$20$以下なので全探索でも十分対応できそうです。

『選ぶ・選ばない』の全探索ならbit全探索を使ってときます。

## 解答例
```python:ABC374_C
def optimize_groups(N, K):
    min_max_group = sum(K)

    # N部署のグループA=1,グループB=0としてbit全探索
    for i in range(1 << N):
        group_a = 0
        group_b = 0
        
        # 各部署をグループAかBに割り当てる
        for j in range(N):
            if i & (1 << j):
                group_a += K[j]
            else:
                group_b += K[j]
        
        # 大きい方のグループの人数を記録
        max_group = max(group_a, group_b)
        
        # 最小値を更新
        min_max_group = min(min_max_group, max_group)
    
    return min_max_group

# 入力を受け取る
N = int(input())
K = list(map(int, input().split()))

# 結果を出力
result = optimize_groups(N, K)
print(result)
```
## おわりに
bit全探索の勉強になりました。
精進します！
[Memory] 主記憶への実行アクセス・書込み

# 実行アクセス時間
``実行アクセス時間`` = ``キャッシュメモリのアクセス時間``×``ヒット率``　+ ``主記憶のアクセス時間``×``1-ヒット率``

# 書込み方式
|方式|詳細|
|:--|:--|
|ライトスルー方式|①CPUからのデータの書込み命令<br>②キャッスメモリへ書込み<br>③主記憶へ書込み|
|ライトバック方式|①CPUからのデータの書込み命令<br>②キャッスメモリへ書込み<br>③キャッシュメモリからデータを該当追い出す<br>④主記憶へ書込み|



# 参考リンク
- [R4A9_ライトスルー](https://www.ap-siken.com/kakomon/29_haru/q10.html)
- [R3S12_ライトスルー](https://www.ap-siken.com/kakomon/24_aki/q11.html)
- [R5S10_ライトスルー](https://www.ap-siken.com/kakomon/24_aki/q11.html)
Google Chrome 拡張機能 - DeepL, CSS Peeper, OneTab

こんにちは。新人エンジニアの三上です。
今回は、 Google Chrome の拡張機能の中から私が使ったものを紹介していく。

## 1. DeepL 翻訳
言わずと知れた DeepL 翻訳、その拡張機能となります。
機能としては、指定した範囲の翻訳を行うというものである。
サイトを見ている際に、単語の意味が分からず調べるということがあると思う。
この拡張機能を使うことで、以下の添付図のように即座に単語の意味を知ることが可能だ。
また、日本語から英語に翻訳することも可能である。

![スクリーンショット 2024-09-26 000125.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/1e863620-7cd5-0311-b87d-4a12b57b6687.png)
---
だが、この拡張機能を使わずとも元から備わっている翻訳機能を使えば、同様のことが可能だ。

この拡張機能の優れた点とは、ページ全体の翻訳機能だ。
DeepL Pro に加入することで使用可能だ。有料の機能となるが30日間の無料体験が可能。

https://chromewebstore.google.com/detail/DeepL%E7%BF%BB%E8%A8%B3/cofdbpoegempjloogbagkncekinflcnj?hl=ja


## 2. CSS Peeper
2つ目は CSS Peeper だ。
この機能を使用することで、以下添付図のように Webサイトのスタイルシート(CSS)を読み取ることができる。
また、Web ページ内で使用されているフォント, カラーコードを取得できる。


![スクリーンショット 2024-09-26 005653.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/4854be76-c662-5598-aca0-0ba89d2d38a0.png)
---

画面に新規項目を追加する際に、既に実装されている他の項目のスタイルに合わせることがあると思う。
その際に該当の実装を特定するのに苦労したが、この拡張機能を活用すれば実装の効率を上げることができる。

https://chromewebstore.google.com/detail/css-peeper/mbnbehikldjhnfehhnaidhjhoofhpehk

## 3. OneTab
3つ目は OneTab である。
この機能を利用することで、開いているタブを1つのページにまとめて、以下の添付図のように管理することが可能となる。
また、元々備えてあるタブをまとめてグループとして保存する機能との併用が可能となっている。


![スクリーンショット 2024-09-26 005427.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/89d8f023-67f6-2c78-e3c8-007ab62eacda.png)
---

タブをグループとしてまとめる機能と比較して、一目で開いているタブの一覧が確認できる。


https://chromewebstore.google.com/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall

## まとめ
今回この記事を書くために、いくつか拡張機能を追加して使用してみたが、自分の知らない便利な機能を見つけることが出来た。
今回紹介したのは拡張機能のほんの一部でしかないので、自分で興味を持って他の機能も使ってみて欲しい。
【個人用メモ】エクセルファイル黒フォント化マクロ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799616/0f148c40-2c12-308f-db46-aee4bc5c69ba.png)

指定したフォルダの配下（サブフォルダ配下含む）のエクセルファイルについて、下記処理を実行
※① フォント色を黒で統一する
※② 倍率を100%にする
※③ 選択セルを左上(A1)にする
　④ 選択シートを表示シート(<>非表示シート）の中で一番左のシートにする
※：非表示シートは対象外

```
Sub ProcessExcelFilesInFolder()
    Dim folderPath As String
    Dim fileName As String
    Dim wb As Workbook
    Dim ws As Worksheet
    
    ' シートのセル C2 からフォルダパスを取得
    folderPath = ThisWorkbook.Sheets(1).Range("C2").Value
    
    ' フォルダパスの最後に \ がない場合は追加
    If Right(folderPath, 1) <> "\" Then
        folderPath = folderPath & "\"
    End If

    MsgBox "処理を開始します"
    
    ' 指定フォルダとサブフォルダ内のすべてのファイルを処理
    Call ProcessFiles(folderPath)

    MsgBox "処理を完了しました！"

End Sub

Sub ProcessFiles(ByVal folderPath As String)
    Dim fileName As String
    Dim folder As Object
    Dim subFolder As Object
    Dim fso As Object
    Dim wb As Workbook
    Dim ws As Worksheet
    
    ' ファイルシステムオブジェクトを作成
    Set fso = CreateObject("Scripting.FileSystemObject")
    
    ' フォルダ内のすべてのファイルをループ
    fileName = Dir(folderPath & "*.xls*")
    Do While fileName <> ""
        ' 各エクセルファイルを開く
        Set wb = Workbooks.Open(folderPath & fileName)
        
        ' 各ワークシートに対して処理を行う
        Dim n_一番左のシート As Integer: n_一番左のシート = 0
        For Each ws In wb.Worksheets
            If (ws.Visible) Then
                If (n_一番左のシート = 0) Then
                    n_一番左のシート = ws.Index
                End If
                
                ws.Activate
        
                ' ①フォント色を黒にする
                ws.Cells.Font.Color = RGB(0, 0, 0)
            
                ' ②倍率を100%に設定
                'ws.Zoom = 100
                ActiveWindow.Zoom = 100
            
                ' ③A1セルを選択
                ws.Range("A1").Select
            End If
        Next ws
        '④一番左のシートを選択
        wb.Sheets(n_一番左のシート).Select
        
        ' 変更を保存して閉じる
        wb.Close SaveChanges:=True
        
        ' 次のファイルへ
        fileName = Dir
    Loop
    
    ' サブフォルダをループして再帰的に処理
    For Each subFolder In fso.GetFolder(folderPath).SubFolders
        Call ProcessFiles(subFolder.Path & "\")
    Next subFolder
End Sub

```
【D3】Next.js App Router で D3 v7 を利用する

# はじめに
この記事では、JavaScript のデータ可視化ライブラリである **D3** を Next.js App Router で利用する方法を記載します。

https://d3js.org/

https://nextjs.org/docs/app

# 開発環境
開発環境は以下の通りです。

- Windows 11
- Next.js 14.2.4
- React 18.3.1
- TypeScript 5.5.2
- D3 7.9.0

# インストール
まずは D3 をインストールします。

```powershell
npm install d3
```

今回は TypeScript を利用するので、D3 の型定義もインストールします。

```powershell
npm install --save-dev @types/d3
```


# 実装
D3 を利用して、シンプルな折れ線グラフコンポーネントを作成します。

## データの定義
表示するデータは以下の通りです。

```data.ts
const data = [
  { name: "A", value: 400 },
  { name: "B", value: 200 },
  { name: "C", value: 300 },
  { name: "D", value: 350 },
  { name: "E", value: 300 },
];
```

## X軸、Y軸、折れ線の定義
X軸とY軸は、[`scaleLinear`](https://d3js.org/d3-scale/linear#scaleLinear) という関数を利用して定義します。

```page.tsx
const x = d3
  .scaleLinear()
  .domain([0, data.length - 1])
  .range([marginLeft, width - marginRight]);

const y = d3
  .scaleLinear()
  .domain(d3.extent(data, (d) => d.value) as [number, number])
  .range([height - marginBottom, marginTop]);
```

## 折れ線の定義
折れ線は、[`line`](https://d3js.org/d3-shape/line#line) という関数を利用して定義します。

```page.tsx
const line = d3
  .line<{ name: string; value: number }>()
  .x((d, i) => x(i))
  .y((d) => y(d.value));
```

## 折れ線グラフコンポーネントの実装
今まで定義した値を利用してコンポーネントを実装します。コンポーネントには、svg を利用します。

```page.tsx
import * as d3 from "d3";
import { data } from "./data.ts";

export default function LineChart({
  width = 730,
  height = 250,
  marginTop = 20,
  marginRight = 20,
  marginBottom = 20,
  marginLeft = 20,
}: Record<
  | "width"
  | "height"
  | "marginTop"
  | "marginRight"
  | "marginBottom"
  | "marginLeft",
  number
>) {
  const x = d3
    .scaleLinear()
    .domain([0, data.length - 1])
    .range([marginLeft, width - marginRight]);

  const y = d3
    .scaleLinear()
    .domain(d3.extent(data, (d) => d.value) as [number, number])
    .range([height - marginBottom, marginTop]);

  const line = d3
    .line<{ name: string; value: number }>()
    .x((d, i) => x(i))
    .y((d) => y(d.value));

  return (
    <svg width={width} height={height}>
      <path
        fill="none"
        stroke="currentColor"
        strokeWidth="1.5"
        d={line(data) || undefined}
      />
      <g fill="white" stroke="currentColor" strokeWidth="1.5">
        {data.map((d, i) => (
          <circle key={i} cx={x(i)} cy={y(d.value)} r="2.5" />
        ))}
      </g>
    </svg>
  );
}
```

# 動作確認
折れ線グラフが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/318188/54a9739c-4e12-a064-655c-2ad10e92313b.png)

# 参考
- [Getting started](https://d3js.org/getting-started)
- [Lines]()
- [Linear scales](https://d3js.org/d3-scale/linear)
MinikubeでUnable to resolve the current Docker CLI context "default"

## 何
Minikube -p docker-envなどを実行すると以下のエラーが出る

```
Unable to resolve the current Docker CLI context "default"
```

## 対応

コンテキスト一覧を確認

```
> docker context list
```

コンテキストをセット

```
> docker context use default
default
Current context is now "default"
```

これで大丈夫のはず。
以下、さっき実行できなかったコマンドやりなおし
AWS SAA 受験対策メモ①

# はじめに
7月にAWS CLF-02を受験し合格。
知識を蓄えるインプットのみの学習も大切ですが、アウトプットすることでより知識として定着すると思いますのでこちらではメモ書きを書き残し、今後の別の記事では知見を深めるためのハンズオンなども実践して残していきたいです...！

私は直接殴り書きをして頭に叩き込むタイプでして、ノートに書いた1部をこちらに転載しております。
こんな感じで50ページほど書いていました。
![note.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887873/79643af9-8123-ce89-1f1d-71a91f6def15.jpeg)


# メモ書き
・CloudWatchLogsでは決まったフォーマットのメトリクスフィルターを作成できる。
　　CloudWatchアラームではメトリクスが発火した条件を決め、発火した際にはSNSと連携して特定のミドルウェア(メールやSlackなど)に通知することが可能。
→メトリクスフィルターとは。
　 ログデータから特定の文字列をフィルタリングする機能のことで、Logsに取り込まれたログデータの中から監視対象のデータを抽出しメトリクスとして数値化可視化できる。
→メトリクスとは
  　何らかのデータを収集してそのままの形ではない、計算や分析を加えわかりやすくしたデータ。
・モノリシックとは　1つのアプリ内に複数のビジネスを実行するソフトウェア
・EBSのスナップショットはS3に保存される。スナップショットを通して別のAZや別リージョンにコピーする。
・DynamoDBストリームを用いるとテーブル内のデータ変更をキャプチャできる。
　そのタイミングをトリガーにLambdaアクションを引き起こせる。
 　マルチAZ配置では同期をしてくれるがリードレプリカは非同期。
・AWS Glue　ETL処理(ectract transform load)
　AWSに保存されたデータを指定することによりクローラーによるデータ検査を行う。
　テーブル定義やスキーマに関したメタデータがGlueのもつデータカタログに保存される。
 ・AWS Certificate Manager(ACM)　※結構でる
　AWSサービスと内部接続リソースで使用するパブリックおよびプライベートなSSl/TSL証明書をプロビジョニング, 管理, 展開できる。httpsにアクセスできない→ACMでSSL発行。
 ・Amazon Comprehend　機械学習によってテキストから洞察を見つける
 　→感情分析や構文解析ができる。Lex Polly Textractなど関連
・DynamoDB　
　プロビジョニングモード 事前にキャパシティを設定している→料金が安くなる
　オンデマンドモード　容量計画の必要がなく柔軟にリクエストを処理できる。
NumPy 配列操作

# はじめに
数値計算ライブラリのNumPyには色々な機能がありますが、今回は配列の操作を取り上げてみました。「配列」と言っても正確にはndarray（多次元配列）ですがこの記事の中では「配列」と表記します。
# 配列の作成　その１
array()関数はリストやタプルから配列を生成します。
~~~Python:example1.py
import numpy as np

a = np.array([1, 7, 3, 2])
print(a)
~~~
実行結果
~~~
[1 7 3 2]
~~~
# 配列の作成　その２
配列はarange()関数を使って作成することもできます。arange(開始位置,終了位置,公差）のように指定します。引数を1つだけ渡すと、その数値が終了位置となり,0を開始位置とし公差1の配列が作成されます。
~~~Python:example2.py
import numpy as np

a = np.arange(6)
print(a)
~~~
実行結果
~~~
[0 1 2 3 4 5]
~~~
# 指定の要素数で等差数列を作成する
linspace()関数を使うと、要素数を指定して等差数列を作成できます。引数に、開始位置、終了位置、要素数（デフォルトは50）を指定します。**終了位置の値は作成する配列に含まれるので注意が必要**です。例えば、0から1までの区間を5等分した数列が欲しい場合、次のように記述します。
~~~Python:example3.py
import numpy as np

a = np.linspace(0, 1, 5) 
print(a)
~~~
実行結果
~~~
[0.   0.25 0.5  0.75 1.  ]
~~~
# 要素をすべて0で埋める配列を作成
zeros()関数を使うとが要素がすべて0の配列を作成できます。
~~~Python:example4.py
import numpy as np

a = np.zeros(5)
print(a)
~~~
実行結果
~~~
[0. 0. 0. 0. 0.]
~~~
# 配列の結合
concatenate()関数は、複数の配列を結合します。デフォルトでは実行結果のように行方向に結合されます。
~~~Python:example5.py
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6])
b = np.array([7, 8, 9], [3, 3, 3])
c = np.concatenate([a, b])
print(c)
~~~
実行結果
~~~
[[1 2 3]
 [4 5 6]
 [7 8 9]
 [3 3 3]]
~~~
列方向に結合するには引数axisに1を指定します。
~~~Python:example6.py
import numpy as np

a = np.array([[1, 2, 3], [4, 5, 6]])
b = np.array([[7, 8, 9], [3, 3, 3]])
c = np.concatenate([a, b], axis=1)
print(c)
~~~
実行結果
~~~
[[1 2 3 7 8 9]
 [4 5 6 3 3 3]]
~~~
# 配列の形状変換
配列を形状変換するにはNumPyのreshape()関数を使います。**reshape()関数の第一引数には変換したい配列を指定し、第二引数に変換後の形状をタプルまたはリストで指定**します。reshape()は元になる配列情報を参照して配列を参照しています。どちらかの配列内の要素の値が変わると互いに影響しあうので注意が必要です。
~~~Python:example7.py
import numpy as np

# 一次元配列を生成
a = np.arange(12) # [ 0  1  2  3  4  5  6  7  8  9 10 11]

# 3 x 4の二次元配列に変形
b = np.reshape(a, (3, 4))
b
~~~
実行結果
~~~
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11]])
~~~
# 二次元配列を一次元化する
二次元配列を一次元化するには、ravel()関数またはflatten()関数を使います。**flatten()はコピー渡し、ravel()は参照渡し**です。コピー渡しのflatten()はメモリを新たに確保するため、ravel()よりも遅くなります。**参照渡しでも問題ないのであればravel()を使うことをおススメ**します。
~~~Python:example8.py
import numpy as np

# 2 x 5の二次元配列を生成
a = np.arange(10).reshape(2, 5) 
# array([[0, 1, 2, 3, 4],
#        [5, 6, 7, 8, 9]])

# 一次元配列に変換
print(a.ravel())
~~~
実行結果
~~~
[0 1 2 3 4 5 6 7 8 9]
~~~
(SSD1327)M5NanoC6で加速度(ADXL345)を表示して遊ぶ。




x 過去ログを見よ
x Adafruit_ADXL345をインストール
x Adafruit_GFX,Adafruit_SSD1327をインストール


目的
加速度センサーで遊ぶ


結果

![o_coq492.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/5677b662-27cf-6d8a-0912-fe558f918eb8.jpeg)



プログラム


```c++


//ssd1327_ADXL345_test1_M6NanoC6_1


//ヘッダーファイル
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1327.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL345_U.h>
#define ESP8266 1


//定義
#define SCREEN_WIDTH  128   // OLED display width, in pixels
#define SCREEN_HEIGHT 96    // OLED display height, in pixels
#define OLED_RESET     -1   // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1327 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);

#define setCursorAA(AA,BB) setCursor(AA+16,BB)

/* Assign a unique ID to this sensor at the same time */
Adafruit_ADXL345_Unified accel = Adafruit_ADXL345_Unified(12345);


//初期化
void setup() {

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SCREEN_ADDRESS);

  // 画面表示をクリア
  display.clearDisplay();

  // テキストサイズを設定
  display.setTextSize(1);
  // テキスト色を設定
  display.setTextColor(SSD1327_WHITE);

  // テキストの開始位置を設定 メッセージの表示
  display.setCursorAA(0, 16);
  display.println("Accelerometer");
  display.setCursorAA(0, 16+8);
  display.println("Test");
  // 描画バッファの内容を画面に表示
  display.display();
  delay(500); //0.5秒待つ
  
  /* Initialise the sensor */
  if(!accel.begin()){
    /* There was a problem detecting the ADXL345 ... check your connections */

    // テキストの開始位置を設定 メッセージの表示
    display.setCursorAA(0, 32);
    display.println("Ooops,no ADXL345");
    display.setCursorAA(0, 32+8);
    display.println("detected ...");


    // テキストの開始位置を設定 メッセージの表示
    display.setCursorAA(0, 48);
    display.println("Check your");
    display.setCursorAA(0, 48+8);
    display.println("wiring!");

    // 描画バッファの内容を画面に表示
    display.display();

    while(1){delay(1);};//無限ループ
  }//endif

  /* Set the range to whatever is appropriate for your project */
  accel.setRange(ADXL345_RANGE_16_G);

}//setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.clearDisplay();

  // テキストサイズを設定
  display.setTextSize(3);
  // テキスト色を設定
  display.setTextColor(SSD1327_WHITE);
  // テキストの開始位置を設定
  //display.setCursorAA(0, 16);


  /* Get a new sensor event */ 
  sensors_event_t event; 
  accel.getEvent(&event);

  /* Display the results (acceleration is measured in m/s^2) */

  // テキストの開始位置を設定 メッセージの表示
  display.setCursorAA(0, 0);
  display.println(event.acceleration.x);

  // テキストの開始位置を設定 メッセージの表示
  display.setCursorAA(0, 32);
  display.println(event.acceleration.y);

  // テキストの開始位置を設定 メッセージの表示
  display.setCursorAA(0, 64);
  display.println(event.acceleration.z);


  // 描画バッファの内容を画面に表示
  display.display();

  delay(500); //0.5秒待つ

}//loop


```
【基本情報】独学マラソン GPT先生と復習① Day 7

Day7だともうDay1の内容を70％ぐらい忘れているはずだから復習する
エビングハウスの忘却曲線より

:::note worn
この記事は自分用の備忘録です。
:::

# GPT先生、問題出して！

### 問題 1:
情報セキュリティの「機密性（Confidentiality）」に関する説明として正しいものはどれですか？

A. データの改竄がないことを保証すること
B. 許可された利用者のみが情報にアクセスできるようにすること
C. いつでも必要なときに情報にアクセス可能であること
D. システムが期待通りの結果を出すこと

### 問題 2:
トランザクションの「原子性（Atomicity）」に関する説明として正しいものはどれですか？

A. データに矛盾が生じないようにすること
B. トランザクションの処理が成功か失敗のどちらかのみであること
C. 複数のトランザクションが互いに干渉しないようにすること
D. トランザクションが終了したらデータが確実に保存されること

### 問題 3:
システムのパフォーマンスを向上させるためにスケールアウトを選択した場合、ACID特性にどのような影響が出る可能性が高いでしょうか？

A. 原子性が保たれなくなる
B. 一貫性を保つのが難しくなる
C. 独立性が保たれなくなる
D. 永続性を維持するのが難しくなる

### 問題 4:
IDS（Intrusion Detection System）とIPS（Intrusion Prevention System）の違いに関する説明として正しいものはどれですか？

A. IDSは不正アクセスを検知し、防御も行う
B. IDSはネットワークへの負荷が高く、リアルタイムで防御する
C. IPSは不正アクセスを検知するが、対応は手動で行う
D. IPSは不正アクセスを防御し、リアルタイムで自動的にブロックする

### 問題 5:
フィリップ・コトラーの競争地位戦略において、「フォロワー」に分類される企業の特徴として正しいものはどれですか？

A. 業界リーダーを追い抜くために積極的に差別化戦略を取る
B. 市場トップに立ち、シェア拡大を目指して同質化戦略を用いる
C. ニッチ市場に特化し、特定の分野で集中戦略を行う
D. リーダーやチャレンジャーの戦略を模倣し、コストを抑えて利益を確保する

### 問題 6:
プロジェクトの期間は1ヶ月であり、半月（2週間）後の進捗確認時点で以下のデータが得られました。
PV（計画予算）：35万円
EV（出来高）：28万円
AC（実際コスト）：32万円
BAC（完成時総予算）：70万円

このデータを元に、「EAC（完了時コスト予測）」を計算してください。計算結果に基づく予測として正しいものを選びなさい。

A. EACは75万円で、予算を5万円超過する見込み
B. EACは70万円で、予算内で収まる見込み
C. EACは80万円で、予算を10万円超過する見込み
D. EACは85万円で、予算を15万円超過する見込み

# # GPT先生、答えと解説作って！

### 問題 1の答え:
正解: B

### 解説:
機密性（Confidentiality）は、情報にアクセスできるのが許可された利用者のみであることを保証します。これは認証やアクセス制御を使って情報の漏洩を防ぐことを指します。

### 他の選択肢についての解説:

A. 完全性（Integrity）の説明です。データの改竄がないことを保証することを指します。
C. 可用性（Availability）の説明です。必要なときにいつでも情報にアクセス可能であることを指します。
D. 信頼性（Reliability）の説明です。システムが期待される通りの結果を出すことを保証することを指します。

<br>

### 問題 2の答え:
正解: B

### 解説:
原子性（Atomicity）は、トランザクションが「全て成功する」か「全て失敗する」のどちらかであることを保証します。「ALL or NOTHING」の考え方です。

### 他の選択肢についての解説:

A. 一貫性（Consistency）の説明です。データの矛盾が生じないようにすることを指します。
C. 独立性（Isolation）の説明です。複数のトランザクションが互いに干渉しないようにすることを指します。
D. 永続性（Durability）の説明です。コミット後、データが消えないことを保証します。

<br>

### 問題 3の答え:
正解: B

### 解説:
スケールアウトにより、異なるノード間でのデータ処理が必要となり、一貫性（Consistency）を保つのが難しくなることがあります。分散トランザクションの同期オーバーヘッドが原因でACID特性を維持するのが難しいことがあるためです。

### 他の選択肢についての解説:

A. スケールアウトが直接原子性に影響することはありません。
C. 独立性は適切な設定で維持できます。
D. スケールアウトはむしろ冗長性が高まり、永続性を強化します。

<br>

### 問題 4の答え:
正解: D

### 解説:
IPS（Intrusion Prevention System）は不正アクセスをリアルタイムで防御し、自動的にブロックします。システム負荷が高くなることや、正常な通信を誤ってブロックするリスクがあります。

### 他の選択肢についての解説:

A. IDSは防御機能を持たず、検知のみを行います。
B. IDSはネットワークへの負荷が低く、防御機能はありません。
C. IPSは不正アクセスの検知だけでなく、防御をリアルタイムで行います。

<br>

### 問題 5の答え:
正解: D

### 解説:
「フォロワー」はリーダーやチャレンジャーの戦略を模倣し、研究開発費用を抑えて利益を確保します。コストを抑えつつ経験を蓄積し、次第に自社オリジナル製品を展開することを目指します。

### 他の選択肢についての解説:

A. チャレンジャーの特徴です。
B. リーダーの特徴です。
C. ニッチャーの特徴です。

<br>

### 問題 6の答え:
正解: C

### 解説:
EAC（完了時コスト予測）を求めるには、まずETC（残作業コスト予測）を計算します。

CPI（コスト効率指数） = EV / AC = 28万円 / 32万円 ≈ 0.875
ETC = (BAC - EV) / CPI = (70万円 - 28万円) / 0.875 ≈ 48万円
EAC = AC + ETC = 32万円 + 48万円 = 80万円
そのため、最終的に80万円が必要で、10万円の予算超過が見込まれます。

### 他の選択肢についての解説:

A. 計算結果は80万円であり、75万円ではありません。
B. CPIが1未満であるため、予算内に収まることはありません。
D. 正確に計算した結果は80万円です。

<br>

# 感想
ずいぶん勉強しやすい時代になったものである
自分で書いた記事をベースに問題を作らせると
記事の1つ1つに命が宿って
愛着が湧いてくる感じがした
pre-pushのwhile文が動かない

# はじめに
前回の記事に続き、git hooksにおいて、mainブランチへの直push禁止設定を行う際に
上手く動作し無かったので記録します。

前回記事はこちら

https://qiita.com/n1sp/items/0898d616b0f87df40ede

# 実行環境
Visual Studio 2022
git 2.43.0.windows.1

# 問題
以下スクリプトを実装したが、ループ内の処理が行われなかった。
```shell
#!/bin/bash

while read local_ ref local_sha1 remote_ref remote_ sha1
do
...
done

```

エラーが発生していたわけではなかったが、
do...done内にechoを記述しても何も表示されないため、
そもそも要素が何も取得できていない疑いが出てきた

# 解決方法
while文で受け取っている標準入力について
以下の説明をしている記事があった
> これはそれぞれローカルのブランチ名／ローカルのコミットID
> ／リモートのブランチ名／リモートのコミットIDを表していて、
> gitが pre-push フックに対して標準入力経由で
> これらの値を渡すようになっている。

https://zenn.dev/labbase/articles/60cca07076a7f6

この標準入力はgit pushコマンドにおけるpush設定から取得される。

ではなぜ取得できていない？？

> Apologies if this is stating the obvious， but if there's mothine to push you won t get any lines on stdin.
> 
> 当たり前のことを言うようで申し訳ないのですが、プッシュするものが何もなければ、標準入力に何も表示されません。

https://stackoverflow.com/questions/22585091/git-hooks-pre-push-script-does-not-receive-input-via-stdin

**そもそもpushするものがないままpushし続けていました**

ダミーファイルをcommitした後、pushを行い、正常に動作していることを確認
```dosbatch
git add test.txt
git commit -m ”pre-push 動作確認用”
git push origin main
```

# おわりに
**当たり前のことを言うようで申し訳ない**ような問題ですが、
こんなことが割とよくあるので、悩めば悩むほど、今後同じことで悩むことは無い、
という事にしておきます。
git hooksを設定するも、No such file or directory

# はじめに
Visual Studio 2022内のgit機能において、
git hooksを使ってpush時にスクリプトを実行させようとしたところ、
エラーが発生して、他の記事とは逆の事象が起こっていたのでまとめます。

# 実行環境
Visual Stuido 2022
git 2.43.0.windows.1

# 問題
以下の記事を参考にgit hooksを利用した特定ブランチへのpush禁止設定を行いました。

https://qiita.com/Syuparn/items/9e107e0aaf1a61b260b5

しかし作成したpre-pushを格納してpushを行ったところ、下記エラーが発生
```
error: cannot spawn. git/hooks/pre-commit: #!/bin/bash
```

# 解決方法
## 結論
先に結論を申しますと、
pre-pushファイルの1行目を以下のように修正することで解決しました。
`#!/bin/bash`　→ `#!/bin/sh`

## この1行目の意味
 (#!) は、シバン(Shebang)と呼び、スクリプトの1行目に記載される特殊な文字列で、
 スクリプトを実行する際にどのプログラムを使うかを指定します。
 
 今回の例で行くと、`#!/bin/bash `は Bash シェルを使って実行され`#!/bin/sh`は POSIX準拠のシェル（ほとんどの場合は /bin/sh）を使用してスクリプトが実行されます。
 
 /bin/sh はほぼすべてのUnix系システムに存在し、POSIX標準に準拠した非常に汎用的なものらしいです。
## 根本原因
 Visual Studioのインストール時にGit for windowsがインストールされており、基本的にはbashとshの両方が実行できるようぇすが、恐らく、自環境において何かしらの理由でBashが正しく設定されておらず、実行できなかったのが問題だったと思われます。

今回のような簡単なスクリプトであればPOSIX標準のシェルで問題ないそうなので、今回はこちらの解決策を取りました。

# おわりに
些細なエラーですが、馴染みのない分野の知識を少し齧ることが出来たので、
結果的に良かったかもしれないです。

# 参考

https://zenn.dev/sashimi/articles/5600f63634255d

https://stackoverflow.com/questions/5725296/difference-between-sh-and-bash
ポテンシャルのあるエンジニアが半年後に成長するためのアクション集

# はじめに

ここでは、私が実践してみて良かったこと、反省点も含めて、率直に共有していきます。
情報がRubyやRailsに偏るかもしれないです。

この記事も、新たな学びや経験を重ねるごとに更新していく予定です。
一緒に、エンジニアとしての可能性を広げていきましょう！

追記: 大前提、インプットが圧倒的に大事です。特に、エンジニア歴3年以内の方は業務でも、できるだけコードを書く時間を取れるようにする方が圧倒的に成長します。
あれこれ手をつけるより、今、目の前にある課題をひとつずつ無くしていきましょう。

## わたしのエンジニアへの道
学生時代はハッカソンばかり出ていました。
後に、縁がありエンジニアインターンをしていました。
新卒でエンジニアになり、会社で課題に感じることをCLIを趣味で作って解決しようとしていました。

インプットとアウトプットを繰り返すことが大事で、相談できる先があることも続けるためのモチベーションになります。

相談先の例:
- techtrain
- ruby-jpなどのコミュニティ
- MENTA

techtrainとrubyコミュニティはよくお世話になっています！

### ハッカソンに出る前のアウトプット

- とても簡単なブログ書いてた
https://mikk0tan.hatenablog.jp/entry/2021/10/22/102023

- 人生初LTはtechな内容ではなく趣味LTだった
https://lycorp-osaka-jp.connpass.com/event/177775/


# インプット編
## イベントに参加する
- https://connpass.com/dashboard/ 

おすすめは企業主催のイベントに参加すること。(ファインディ,ラクス, LINEヤフーがおすすめです)
オンラインでも、オフラインでも参加しやすい方から挑戦してみよう！

私の参加歴
https://connpass.com/user/mikko_/

懇親会は、登壇者に感想を伝えたり、色々な人と交流できるので、参加するのがおすすめ！
次回のイベントでもお会いすることもあるので、Xなどのアカウントを交換して覚えておきましょう！
1人知り合うと、次回のイベントなどで知り合いの知り合いを紹介してもらったり、エンジニアの輪が広がっていきます🙆(体験談)

## 記事を読む
### スマホで読む時
techfeedがおすすめで、自分の興味のある分野の技術記事をレコメンドしてくれます。
https://techfeed.io/

### PCで読む時
はてぶのテクノロジーの人気エントリ
https://b.hatena.ne.jp/hotentry/it

Hackers newsの翻訳したサービス
https://catnose.me/lab/hackernews-ja


## 本を読む
リーダブルコードを読んだことがない方は、一番最初に読むことをおすすめします。

- プロを目指す人のためのRuby
- オブジェクト指向設計実践ガイド
- 良いコード悪いコードで学ぶ設計入門
- Web API：The Good Parts

上記の本が、私が読んできた中でおすすめ(Railsエンジニア向け)ですが、
必要な時に読むことで、内容が記憶に残り、理解も深まります。そのため、辞書のように活用したり、輪読会を行うことをおすすめします！
私自身、「オブジェクト指向設計実践ガイド」を読むタイミングを誤ってしまい、なんと3回も読み返してしまいました。

# アウトプット編
## アプリを作成してみる
私が作ったもの
- LINE BOTとSlack BOTでおうむ返しするアプリ
- 2人用割り勘LINE BOT

まずは、コピペでできる部分から始めてみましょう。
LINE BOTは活発なコミュニティがあり、とてもおすすめです。
初心者向けのハンズオンイベントも開催されているため、気軽に参加できます！
https://linedevelopercommunity.connpass.com/

Discord Botも簡単に作れるらしいので、ゲーム好きな人よさそうですね！

軽量フレームワーク（Sinatra）でWebアプリを開発してみましたが、実際には使用機会がなく、また全ての機能を自分で実装する必要があり、モチベーションを維持するのが難しくなってしまいました。
振り返ってみると、CLIアプリケーションの開発の方が自分に合っていたようです。

この経験から学んだのは、素早くプロトタイプを作るか、完成までの道筋が明確な状態で開発を進める方が、モチベーションを保ちやすいということです。

## 記事を書く
エラーが発生した際には、その解決策を記事にまとめたり、新しい環境を構築した際にもそのプロセスを記録するようにしていました。
また、Cosense(旧Scrapbox)に書き留めるのも取り組みやすいアウトプットです。

Qiitaで現在開催中の記事投稿キャンペーンは、テーマが用意されているので、何を書けばいいか迷っている方にもおすすめです。
https://qiita.com/official-events

第一歩記事:
https://mikk0tan.hatenablog.jp/entry/2021/10/22/102023

## ハッカソンに参加する
手軽に成果物を作成できるため、ハッカソンへの参加はとてもおすすめです。
学生時代には、学生向けのハッカソンが頻繁に開催されており、私は月に一度のペースで参加していました。

### 社会人向けハッカソン

- [SPAJAM](https://spajam.jp/)
  - モバイルハッカソン
- [Qiitaハッカソン](https://increments.connpass.com/event/305013/)
  - Qiitaが主催するハッカソン
- [Yahoo! JAPAN Hack Day](https://hackday.yahoo.co.jp/)
  - YL社のハッカソン
- [Mashup Awards](https://mashupawards.connpass.com/event/328317/)

## LT会で発表する

自分が発表しやすいテーマでアウトプットを試みてみましょう。
私の場合は、以下のような内容から始めました。
- 年末年始に行われる振り返りや抱負に関するLT
- 趣味に関するLT（ボルダリング）

このように、テクニカルな内容ではないLT会からスタートしましたが、非常に良い経験でした！
地域ごとのコミュニティでLTを行うことを強くおすすめします。
参加者との交流やフィードバックを通じて、新たな視点や学びを得ることができますよ！

- https://omotesandorb.connpass.com/event/331315/
- https://shibuyarb.connpass.com/
[C言語 #5] 変数① ~ しくみと識別子 ~

<!--
 <font color="c00000"></font> 赤
-->
## はじめに
こんにちは、最近気づいたらもう17時過ぎには真っ暗になってて季節の変わり目が激しいなぁと思ってる者です。今回から <font color="c00000"> **「変数」**</font>について取り上げていきたいと思います。

:upside_down: 以前では**文字や数値を画面に出力する方法**を紹介してきました。文字や数値はプログラミングを始めたばかりの方にとっても、それほど違和感無く馴染めるものだったのではないかと思ってます。

今回からはC言語のみならずプログラミングらしい機能である「変数」について見ていきたいと思います。今回はその基本となる **「変数のしくみ」** について、みていきましょう。

## 変数のしくみ
:upside_down: プログラムを実行する時、プログラムはコンピュータ（CP）に色々な値を記憶させながら処理をしていきます。一例ですが...
```c
// ユーザーが入力した数値を画面に出力する
```
というプログラムについて考えてみましょう。

私達人間であれば、お店で商品の値段（数値）を覚え、あとからその値段を紙に書き出すということができます。コンピュータも同じように数値をどこかに <font color="c00000"> **「記憶」**</font>しておき、画面に出力することができます。

この値を記憶する機能は今回のお題である「 **変数**（variable）」と呼ばれています。
### メモリ
コンピュータは、色々な値を記憶しておくために、内部に「**メモリ**（memory）」という装置をもっています。「変数」とはメモリを利用して値を記憶すえう仕組みになります。


## 識別子
### 変数の「名前」
コードの中で変数を使うには、まず最初に次の2つことを決めておかなければなりません

:::note info
①変数に「**名前**」をつける
②変数の「**型**」を指定する
:::

### ①変数に「名前」をつける
変数を使うには、変数のためにある特定の「**名前**」を考えておく必要があります。
変数の名前は、私たちが適当に選んで決めることができます。

:::note warn
**あまりにも適当過ぎる**のは後々自分も他の人に共有する時に不便なので注意です...
例→ a, b, c（どういう変数なのかわからないためです）
:::


例えば「number」という名前にしようとしたとします。このような文字の組み合わせは、変数の名前にすることができます。変数の名前として使える文字や数字の組み合わせを、「識別子（identifier）」と呼んでいます。numberは「識別子」の一つになります。但し識別子は次のような文字でなければなりません。

:::note warn
・**特殊な記号**を含めることはできません（! ♪ <>など）
・環境によっては**31文字まで**です
・予めC言語が予約している「キーワード」を使うことはできません。例：return
・数字で始めることはできません
・大文字と小文字は異なるものとして区別されます
:::

## おわりに
今回のちょっとしたまとめになります。

:::note info
変数の名前には識別子を使う。**自分も共有する人**にも「 <font color="c00000"> **わかりやすい**</font> 」名前にすることが望ましいかと思います
:::
今回は識別子に関してご紹介しました。
次回は続きで「**型**」について見ていきたいと思います。
最後までお読みいただきありがとうございました！

> **「参考書」**
[やさしいC 第5版 (「やさしい」シリーズ)](https://www.amazon.co.jp/%E3%82%84%E3%81%95%E3%81%97%E3%81%84C-%E7%AC%AC5%E7%89%88-%E3%80%8C%E3%82%84%E3%81%95%E3%81%97%E3%81%84%E3%80%8D%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E9%AB%98%E6%A9%8B-%E9%BA%BB%E5%A5%88/dp/4797392584)
>
> **「参考サイト」**
[C言語の識別子](https://kakuyomu.jp/works/1177354054881541562/episodes/1177354054881839197)
[C言語の変数](https://www.javadrive.jp/cstart/var/index4.html)
>
Navigator for i システム・モニターの閾値超えメッセージを日本語化する

[前回記事の続きです](https://qiita.com/gomAnomalocaris/items/1d3a1cc6df3724ba23af)

## システムモニターの閾値越え時のQSYSOPRへのメッセージ出力を日本語化するには？

ズバリ答えですが、下記のようなCCSID 5035(5026）など日本語環境に切り替えて、SNDMSGすればOKでした。

### サンプルコード

CLP:SYSMON01
```
PGM                                                              
             MONMSG     MSGID(CPF0000)                           
             CHGJOB     JOB(CCSID) CCSID(5035)                   
             MONMSG     MSGID(CPF0000)                           
                                                                 
             SNDMSG     MSG('CPU使用率が3%を超えました') +   
                          TOUSR(*SYSOPR) /* "閾値越え" */     
             GOTO       CMDLBL(ENDPGM1)                          
                                                                 
ENDPGM1:                                                         
ENDPGM                                                           
```
※一行目のMONMSGでこのCLP全部に対し、あらゆるエラーメッセージが出ても処理継続するようにします。
※2行目でジョブのCCSIDを日本語5036に変更します、QCCSIDが5026のシステムでは5026がいいかもしれませ
※3行目のMONMSGは今回はなくても構いません。もし、2行目を実行時、何か固有のメッセージ番号をハンドリングしたい場合はこの行にそれを記入します。

上記のCLPをコンパイルして、システム・モニターの閾値1超過時に実行するプログラムに指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/7cff69c7-599d-3971-4254-ab6c2c3d1ff4.png)

※テストしやすくするため(^^;、CPU使用率閾値、期間はより小さく・短く調整しています・・(^^;


### 実行結果

下記のように日本語でQSYSOPRメッセージが出力されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/72f54bef-f912-db23-0ee9-6de221f2008a.png)


・・・ところでGURI GURIさんから[別な方法も？](https://qiita.com/gomAnomalocaris/items/1d3a1cc6df3724ba23af#comment-989ef836503fbb6b2bc9)というコメントをいただいてまして、こちらも後程試してみたいと思います。
2024/10/7主にITとかセキュリティの記事

リコージャパンのランサムウェア事件に見る委託先セキュリティ対策の重要性
https://cybersecurity-park.com/3107/

「マリオカート8DX」で深刻な脆弱性が発見されていた　既にアプデで対策完了済み(10/5)
https://news.yahoo.co.jp/articles/41e7de05c4f6fe9fe644e92a4524f535494bdf1a?source=rss

サイバー攻撃、企業標的のランサムウエア拡大　後手に回る対策(10/3)
https://business.nikkei.com/atcl/gen/19/00081/072400690/

「豚殺し詐欺」のアプリがGoogle PlayとApp Storeで発見される(10/5)
https://gigazine.net/news/20241005-pig-butchering-app/

米国 司法省 マイクロソフトが協力し、合わせて100以上のドメインを差し押さえた(10/5)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/10/post-2f57b0.html

スマートフォンのセキュリティ対策できていますか？4つのポイント【字幕付】(10/4)
https://www.gov-online.go.jp/prg/prg26093.html

CSA-JC AI ワーキンググループ AIレジリエンス：AIの安全性に関する革命的なベンチマークモデル (2024.09.20) +過去分も...(10/5)
http://maruyama-mitsuhiko.cocolog-nifty.com/security/2024/10/post-98a6da.html

【基本情報】独学マラソン 情報セキュリティ Day 4(10/3)
https://qiita.com/weeding_test_5/items/98887d2b3be7cbb52d5f

日野市の事業（学童クラブ・一時預かり・トワイライトステイ・地域子育て 支援拠点）受託業者に対するサイバー攻撃被害の可能性について (令和6年10月4日プレスリリース)
https://www.city.hino.lg.jp/press/1026438/1027655.html

北朝鮮ハッカー組織、独軍需企業にハッキング攻撃…ＫＦ－２１技術流出か(10/5)
https://japanese.joins.com/JArticle/324560?sectcode=500&servcode=500&cloc=jp|main|

多くの日本人が知らない！「米中戦争」巻き込まれた日本の「悲惨すぎる」末路…中国の「核報復」受ける可能性(10/5)
https://gendai.media/articles/-/138237

チェーンメールのLINE版「チェーンLINE」が中高生の間で問題に。転送したら懸賞に当選する？(10/5)
https://news.yahoo.co.jp/articles/04c26a76ee112e76045f30ad9c3def146eb40471?source=rss

「主要行等向けの総合的な監督指針」等の一部改正（案）及び「金融分野におけるサイバーセキュリティに関するガイドライン」（案）に対するパブリックコメントの結果等について(10/4)
https://www.fsa.go.jp/news/r6/sonota/20241004/20241004.html
【Ruby】unlessは簡単な構文の時に使おう

# はじめに
本日はunlessの使い方について記事にしていこうと思います。
余談ですが、10月中にやっとGitやLinuxなどの勉強がひと段落しました（まだ基礎レベル）。今月からRubyの勉強を始めましたので、Rubyに関する記事が増えるかもしれません。では、さっそく本題に入りましょう。

# unlessとは
`unless`は、`if`の逆の条件を扱う構文です。具体的には「条件が偽のときに実行する」ために使われます。
`if`は条件が真の場合に実行されるのに対し、`unless`は条件が偽の場合に実行されます。
`unless`は読みやすさやコードの意図を明確にするために便利で、特にシンプルな否定条件に対して効果的です。
基本構文は以下の通りです真。
```ruby:unless1.rb
unless 条件式
  # 条件が 偽 の場合に実行されるコード
end
```
もちろんif文と`!`を用いて同様に表すことができます。
```ruby:if1.rb
if !条件式
  # 条件が 偽 の場合に実行されるコード
end
```

# unlessを使う場面
`unless`を使うメリットとしては<strong>可読性が高くなる</strong>ことです
シンプルな否定の条件がある場合、`if !条件` よりも、`unless`のほうが意図が明確に伝わることがあります。
短く読みやすいコードにしたいとき。`unless`はネストの深いコードや複雑な条件文を避けるのに役立つことがあります。

```ruby:unless2.rb
# unlessを使った場合
unless user_logged_in
  puts "ログインしてください"
end

# ifで否定を使った場合
if !user_logged_in
  puts "ログインしてください"
end
```

# unlessを使わない場面
unlessを使わない場面はいくつかありますが代表的なものを紹介していきます
* 複数の条件を組み合わせる場合
* elseを使う場合

### 複数の条件を組み合わせる場合
以下の例を見てみましょう。
```ruby:unless3.rb
# 悪い例
unless user_logged_in || admin_rights
  puts "ログインしてください"
end

# 良い例
if !user_logged_in && !admin_rights
  puts "ログインしてください"
end
```

高校数学1Aのド・モルガンの定理と同じで`user_logged_in`をA
`admin_rights`をBと置くと以下の関係が成り立っています
```math
\overline{A\cup B}=\overline{A}\cap \overline{B}

```
AまたはBの否定を表すのは大変なので、Aの否定かつBの否定を考えようといった場面で`unless`を使用するとややこしくなるということです。

### elseを使う場合
unlessとelseを組み合わせると、論理が混乱しやすいです。unless自体が「～でないなら」を意味するので、そこにelseを加えると直感的に分かりにくくなります。
```ruby:unless4.rb
# 悪い例
unless has_permission
  puts "アクセス拒否"
else
  puts "アクセス許可"
end

# いい例
if has_permission
  puts "アクセス許可"
else
  puts "アクセス拒否"
end
```
この構文は、「もし権限がないならアクセス拒否し、そうでなければアクセス許可する」という意味ですが、unlessとelseを組み合わせると理解しづらくなります。

# まとめ
今回は、unlessの使い方とその使用に適した場面、適さない場面について説明しました。
unlessは単純な否定の条件に適しており、複雑な条件やelseを伴う場合には、ifを使った方が可読性が向上します。
AWS Copilot で起動に失敗したコンテナがつながっているデータベース（Aurora Severless v2）の中身を直接見る

デプロイ済みの環境に対して、DB の中身を見るのに結構苦労したので顛末をメモしておきます。

### 承前

AWS Copilot で FastAPI による API をデプロイしています。

Alembic のマイグレーションでDBを更新するよう、コンテナのスタートアップスクリプトに書いているんですが、あるとき、このマイグレーションが適用されたのにされてない扱いになり、すでに適用されたファイルを再適用しようとして起動に失敗するようになってしまいました。

ローカル環境では Docker Compose で起動させてテストをしているので、 DB のコンテナに外から繋げます。なのでDB に直接繋いで alembic_version というテーブルを正しく修正すれば治ります。

しかし！ AWS Copilot でデプロイした RDS はコンテナからしか繋げないようにしてます。セキュリティ的には大正解ですが、さて困りました。

### 使えなかった方法

RDS には Data API というオプションがあり、AWS のコンソールからクエリを投げることが出来ます。いやこれで解決じゃんと思ったんですが……、なんということでしょう、 **Data API は Aurora Severless v2 の MySQL には非対応** なんです（普通のRDSや Aurora Severless v2 でも PostgreSQL ならできたのに）

manifest ファイルに Data API 使うオプションを書いてデプロイしようとしてもそれは使えないよって怒られてしまいました。

### 正攻法？

おそらく踏み台コンテナを用意するのが正攻法ですね。 MySQL あであれば Web の管理ツール mysqladmin が起動するコンテナを用意して、こいつを同時に立ち上げる。このコンテナへの接続は制限して誰でもアクセスは出来ないようにする、がいいでしょうね。

ただ、ログイン時のパスワードがわからないので結局後述の方法でコンテナに入って環境変数を見ないといけないような気もしてます。

### というわけで既存コンテナから CUI でつなぐ方法を考える

踏み台がない現状、既存のコンテナからコマンドで繋ぎたいのですが、繋ぐにはそもそもいま落ちてしまっているコンテナ自体が起動している必要があります。

今回マイグレーションで失敗したらコンテナがそのまま立ち上がらない状態になっています。

なので、まずは、マイグレーションが失敗しようがとにかくサービスが起動だけはするように変更しました。この状態では起動しているアプリケーションにマイグレーションが最新まで適用されているか保証できない状態で起動してしまうことになり、今後うっかりミスがあったりすると面倒だなと思いつつ、仕方ないのでそういう修正をしました。

### 不整合のまま起動したコンテナ内からつなぐ

というわけでコンテナが起動するようにはなりました。コンテナには

```
aws copilot exec [サービス名]
```

こうやって繋げます。さて、繋いでそこから Aurora に繋ごうと思ったところ mysql コマンドをつうけつけてくれません。それもそのはず、そんな者は入っていないのです。

### コンテナにMySQLクライアントを入れる

というわけで、コンテナの起動時に default-mysql-client をインストールするように書き換えました（Poetry をつかっているので、Poetryでクライアントがインストールされるようにしました。これただの mysql-client ではダメで、defaultをつけたら動かせるようになりました。

動作の確認自体はローカルでも出来るので起動してコンテナの中に入って mysql にパスワードなどを引数で渡して実行させることを確認します。

ちなみにcopilotでストレージもデプロイしているので、パスワードなどは環境変数にエクスポートされています。envでパスワードを確認してから接続しましょう。

（なお、デフォルトではコンテナに繋いだときの初期シェルがshなので不便すぎたのでbashと打ってから作業しました。このへん使ったイメージなどによって変わる部分かとは思います）
Laravel11 Eloquent の主キー(ID)を UUID に変更する

## 目的

:::note warn
以前、 [goldspecdigital/laravel-eloquent-uuid](https://github.com/goldspecdigital/laravel-eloquent-uuid) ライブラリを利用して主キーをUUIDに変更する記事を書いていました。

https://qiita.com/ucan-lab/items/a8374ba421fe7828dcb9
:::

Laravel9以降は [HasUuids](https://laravel.com/docs/11.x/eloquent#uuid-and-ulid-keys) トレイトが利用できるようになりました！

ということでやっていきます。

## 環境

- PHP: 8.3.11
- Laravel: 11.23.5

## UUID とは

Universally Unique Identifierの略。
重複する可能性が無視できるほど小さく、一意な識別子として扱えるIDです。

生成方法によりバージョン1からバージョン5までの種類があり、今回使用するのはバージョン4になります。

## UUID のメリット

- IDにID以外の意味を持たせないため
- 複数のデータベースで分散してデータを持つ場合に有用
- データを移行の際にもプライマリーキーの重複を避けられる
- URLからIDの予測が付きにくい

## 手順

### users マイグレーションを修正する

```php:database/migrations/0001_01_01_000000_create_users_table.php
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up(): void
    {
        Schema::create('users', function (Blueprint $table) {
            // $table->id();
            $table->uuid('id')->primary(); // 追記
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->string('password')->nullable();
            $table->string('avatar')->nullable();
            $table->string('google_id')->nullable();
            $table->rememberToken();
            $table->timestamps();
        });

        // ...
    }
};
```

### User モデルを修正する

`HasUuids` トレイトをモデルに追加します。

```php:app/Models/User.php
class User extends Authenticatable
{
    use HasFactory, HasUuids, Notifiable; // 追記

    // ...
}
```

### データベースの再生成

```shell
$ php artisan migrate:fresh --seed
```

### 動作確認

`users` テーブルの `id` カラムが `uuid` になっていることを確認します。

```shell-session
$ php artisan tinker

> App\Models\User::first()
= App\Models\User {#6174
    id: "9d2e8ce1-e7c5-46f5-91a8-ade9a7c296ba",
    name: "小泉 洋介",
    email: "gsuzuki@example.org",
    email_verified_at: "2024-10-07 01:36:16",
    #password: "$2y$12$h7pTeIY73t9IxlH97ridZeNDplh1qYHEdNc5IWlUhWBX1A7PdbwuC",
    avatar: "https://via.placeholder.com/640x480.png/008866?text=neque",
    google_id: "6746",
    #remember_token: "ctzEykq0O7",
    created_at: "2024-10-07 01:36:16",
    updated_at: "2024-10-07 01:36:16",
  }
```