OmniAICreator/Qiita-1.07M huggingface dataset:
テストの見積もりの手順

# 概要
本記事は[『ソフトウェア見積もりガイドブック 品質要件に応じた見積もりとは』](https://www.ipa.go.jp/archive/publish/qv6pgp0000000yho-att/000005132.pdf
)
の4章の部分的な要約です
(この要約は、諸事情により設計部分の欠陥、非機能要件のテストのセクションなどを含んでいません。)

テストの見積もりは、テスト量とテストの生産性を決めることが重要です。
ですので、それぞれの決め方を紹介します。

# 	テスト量はどのように決定するか？	
- まず、テスト量には制約があります。それは、テスト量は単純に組み合わせを網羅すると天文学的数字になる一方、コストやスケジュールは限られているからです。したがって、テスト量は**テストコストと残存した欠陥がソフトウェアの品質リスクを許容範囲内に抑えるというトレードオフ**の中で定めます。
- テスト量は、品質要件から品質指標を定め、その目標値を満たす形で決定されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081780/41fa1423-e373-3344-3599-3c1af093502f.png)

より詳細で広範なフローは以下の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081780/6946f255-8119-6857-e43c-411f16eda0c5.png)


- 見積もり時に必要だが得難い情報があります。それは、ユーザーが期待するリリース段階での残存欠陥密度、つまりリリース時点でソフトウェアにどれだけバグが残っているかです。しかし、見積もり時に残存欠陥密度を知ることはできません(これはリリース後に障害が起きた時にわかる)。
そのため、残存欠陥密度の代わりの指標を用います。それは**テスト網羅率**などです。この代替指標のもとで目標値を定め、ユーザーと合意しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081780/45cf7bc4-51b2-3538-8075-abafb04dd3f6.png)


- ただし、テスト網羅率は全機能に一律に値を設定すべきではありません。そうでなく、**重大な機能は手厚くするなどの調整**をしましょう。(例えば、障害により社会的影響の大きい機能は手厚くする)			

## テスト網羅率の設定方法
- 網羅率の定義は、ホワイトボックステストとブラックボックステストで異なります。それゆえ、ソフトウェアテスト量を残存欠陥密度とテスト網羅率から見積もる場合は、ホワイトボックステストとブラックボックステストで別々に算出する。
- ブラックボックステストのテスト網羅率の定義。一例は、(実際にテストするテスト項目の数/ありうるテスト項目の数)*100です。ここで、テスト項目の粒度は、ドキュメント内でテストえ確認すべき内容を文章表現したレベルとします。
- この前提のもとで、**テスト項目の抽出方法**を考察します。	
    - 要件定義からの抽出する方法
機能要件、品質要件からテスト項目を作ります。
ここで、入力項目のとりうる値の範囲、出力結果のバリエーションを明確にします。		設計書からの抽出。機能仕様や状態遷移図からテスト項目を抽出する。			
	- 操作マニュアル類から抽出する			
    - 過去の障害に基づくテストを追加する			
	- クリティカルなシステムの機能を担保するためのテスト項目を追加する			
## テストケース数の削減方法	
- 同値クラステスト、境界値分析、ペアワイズ法、ドメイン分析テストなどのテスト技法を使う				
- ホワイトボックス分析を併用する。ブラックボックス的観点からだと多数のバリエーションが必要となるテスト項目について、ホワイトボックス的分析の結果を加味して削減する。(例：不連続なコード値の妥当性チェック→コードのチェックはテーブル化されている)				
## その他のテスト網羅性尺度
例えば、
テスト密度 = テストケース数/開発規模　開発規模は、プログラムの行数やファンクションポイント。	

## ※改良開発の見積もり固有の注意点
注意点は2つあります	
- **変更箇所の他のモジュールとの結合度**です。モジュール間のインタフェースの方式によって、モジュール間結合が異なり、調査作業とテスト量に影響します。結合度が高いほど、結合先のモジュールもテストした方が良いでしょう。				
- 既存システム内の**改良した箇所の分散度合い**です。分散度合いが高いほど、巻き込みテスト量(リグレッションテストの量)が増えます。

# テストの生産性に影響する変動要因を織り込む
## ※改良開発に固有の変動要因	
- 既存システムの構造を理解しやすいか	
- ドキュメントの準備状況	
- システムの構造が分かりやすいか(例：モジュール化ができているか)	
- データ構造が分かりやすいか(例：正規化されているか)	
- 変更箇所の分散度		
- 既存システムの残存欠陥数		
- 改良開発の巻き込み度合い(デグレードしうる機能の範囲)		
- テスト環境やテストケースを再利用できるか		
- 運用環境からの制限	運用環境と関連することによるテストの実施時間帯や可能なリソースの使用量、アクセス権に影響を受ける。	
				
# 欠陥修正にかかわる工数を織り込む	
- 欠陥を修正する際は、作りこんだ工程にさかのぼり、修正をする。	そのため、工程ごとにかかる修正時間の総和が欠陥修正にかかる工数になる。	
修正範囲のイメージは以下の図を参照。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081780/659f0125-2bc4-b0c8-f6d3-ae6a3767aa37.png)

- 欠陥修正による再テスト工数を算出する。
次の式で算出できる。
Σ修正された欠陥の数×再テストに要する時間		

ただし、欠陥修正による影響範囲が広範囲であるほど、再テスト工数は増加する。
ホワイトハッカー入門を読んで

### 【はじめに】

最近起こった問題をきっかけに[ホワイトハッカー入門 第２版](https://amzn.asia/d/0fbja89u)を読みました。

読み終わった感想としては、一番の脆弱性は人間ではないかと思いました。

### 【理由】

いくつか本の内容を引用させて頂きつつ理由を記載します。

####  ＞自分たちの情報資産にまったく影響の出ない「脆弱性」や「脅威」にやみくもに対応しても、コストがかさむだけです。

* さまざまな脆弱性があり、OSやMWを最新にアップデートして対応していたりしますが、実施判断するのは人間で、実施するのも人間です。判断や操作を誤る可能性があります。
* 脆弱性をリスクと判断したり、脆弱性を突かれても問題無いと判断したり、正しい判断がどこまでできるかはその人によります。またその人もコンディションによってパフォーマンスが上下します。

本当に問題無いと言える根拠や複数人の意見を持って判断や実施をしたいと思います。

#### ＞セキュリティの強度というのは、構成する要素の中で最も弱いところです。ほとんどの場合、その最も弱い部分は人間です。

* ソーシャルエンジニアリングに関する章で記載されているものですが、人間の心理をつく攻撃手段で攻撃対象内部の人間から重要情報を聞き出したり、マルウェアをインストールさせる手法です。怪しいメールのリンクやファイルは開かないと思っていても、絶対誰も引っかからないなんて言えません。可能性としてはあり得ます。
  * リバースソーシャルエンジニアリングというものにも触れられており、例えば相手から聞き出すという行為は警戒させるので、あらかじめサポート窓口が変わりましたと連絡しておいて、相手から連絡させるという方法です。よく聞く詐欺の手口に似ています。

メールアドレスドメインの偽装や正常性バイアスを働かせることによって見抜けにくくなる手法が載っていますが私もそこまでやられたら危ないと思いました。

#### ＞新しい技術や概念は、過去の技術が持っていた問題を克服したものとは限らない

* モバイル、IoT、生成AIと新しい技術が生まれていますが、インターネットを使うことがベースになっています。そのため過去の攻撃方法が通用する可能性もあり、問題が解決されているのではなく、攻撃の機会が増えていってます。
  * 最近はローカルだけで動作するAIなども出てきており、セキュリティが向上するというのがイマイチわかっていない所もありましたが、この本を読んだおかげで腑に落ちました。

#### 最後に

* 短いですが以上です。
* この本では上記以外にも実際どのように攻撃を仕掛けていくか、その手法をかなりのページ数を使って説明しています。実際どのようにして外から攻撃するのかがわかりやすく説明してあってよかったです。ただやはり人間の脆弱な部分が本を読んでいて怖いと思った部分だったので投稿しました。

あとは代表的なセキュリティ資格も紹介されており国際資格のCEH、IPAが実施している情報処理安全確保支援士などがありましたが、かなりハードルが高そうです。正直取得している人は尊敬します。今度本屋で問題集を見てみようと思います。

読んでいただきありがとうございます。
【WordPress】プラグインで入力したデータを取得する方法

時間のない人のために結論先出し。

:::note info
結論：$wpdbを使えば、SQLでWordPressに保存したデータを操作できる。
:::


https://developer.wordpress.org/reference/classes/wpdb/

<hr>

業務でBooking Packageというプラグインを使って入力した内容を取得する必要が出てきたので、キャッチアップした内容を備忘録としてまとめておきます。

https://ja.wordpress.org/plugins/booking-package/

Booking Packageの管理画面は以下のようになっています。サービスというところに入力した情報を取得します。ここでは「ホンダ」と「CB1100」という名前を取得します。

![スクリーンショット 2024-07-07 20.12.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/bbde7ed6-21b9-f43d-720c-44b01fa59e01.png)

① まず、DBのテーブルを見にいきます。DBの情報がわからないとデータを取得できないからです。Localの場合で説明します。

Localの画面でDatabaseのタブに切り替え、Open AdminierEvoをクリックします。

![スクリーンショット 2024-07-04 11.10.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/8fee8bae-b6f3-ba38-2c43-5840c2081953.png)

すると、DBの管理画面らしきものが開きます。ここではwp-booking_package_servicesというテーブルの中に、取得したい情報が入っていました。

![スクリーンショット 2024-07-04 11.11.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/36fd5325-5e9d-8080-99e7-81f57c072e49.png)

② 次に、functions.phpにwpdbを使った関数を書きます。

```php:functions.php
function get_service_names()
{
  global $wpdb;
  $query = "SELECT name FROM wp_booking_package_services";
  $results = $wpdb->get_results($query);
  return $results;
}
```

③ 最後に、呼びたいページのphpで、先ほど作った関数を呼べば完了です。

```php:front-page.php
<?php
$services = get_service_names();
if (!empty($services)) : ?>
  <ul>
    <?php foreach ($services as $service) : ?>
      <li><?= esc_html($service->name) ?></li>
    <?php endforeach; ?>
  </ul>
<?php else : ?>
  <p>No active services found.</p>
<?php endif; ?>
```

![スクリーンショット 2024-07-04 11.55.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/5336e269-1b59-4cb9-dfd6-e3ee27e7bbbf.png)

サービスAという余計な情報も取得してしまいましたが、その辺りはSQLで調整すればOKです。（Booking Packageの別のカレンダーのサービスの情報が紛れてしまったようです。）

<hr>

この記事では、WordPressのBooking Packageというプラグインで入力した内容をwpdbで取得する方法を説明しました。他のプラグインでも大体同じ仕組みだと思うので、ぜひwpdbを活用してみてください。

:::note warn
wpdbを使用する際には、SQLインジェクション攻撃を防ぐために、prepare() メソッドを使うべきかどうかを考えて使用しましょう。
:::

https://gray-code.com/wordpress/about-the-prepared-statemet/#google_vignette
reactで学習記録アプリを作成してみた所感について

## reactで学習記録アプリを作成してみた所感について

# 今回作成したアプリの画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/19fa4e84-d74f-ee77-7c5a-5e8f1326d4d8.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/b6905deb-bf36-4fd9-779a-b2944177943d.png)

# 作成したアプリの機能

* 学習内容、学習時間それぞれの入力欄にユーザーが入力した値をリアルタイムで画面に表示する
* 学習時間に入力した数値が登録ボタンを押すごとに合計時間として累計を計算し画面に表示する

# 今回アプリを作成して感じたこと
* objectの値を取り出してStateにobjectの値を保存・更新するところがいざ実装しようと思った際に理解が曖昧になっていることに気づき、調べながら実装した。
* 合計時間は数値として扱いたいが合計時間の下に表示されているリストでは入力した学習時間に時間が後ろに付加されるようにしたいところで合計時間が文字列として扱われてしまう部分で苦戦し時間がかかった。

* 今回アプリを作成してみてインプットを最小限にしてアウトプットを多くやっていくべきであると実感しました。

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
実践的なカリキュラムで、あなたのエンジニアとしてのキャリアを最短で飛躍させましょう！
興味のある方は、ぜひホームページからお気軽にカウンセリングをお申し込みください！
▼▼▼
https://projisou.jp
Reactの配列操作にご用心

## `useState` での配列変化の検知
React では`useState`を用いて、コンポーネントに`state`変数を紐づけることによって状態を管理できます。

この`state`変数には配列を指定することもできます。
ただし、`useState`の第２引数として返されるset 関数は、配列に変更が入ったことを`Object.is()`によって検知しているため、すでにある配列に対して操作を行っても変更が検知されず、状態の変更が反映されないことがあります。

https://ja.react.dev/reference/react/useState#:~:text=state%20%E3%81%AE%E5%90%8C%E4%B8%80%E6%80%A7%E3%81%AE%E6%AF%94%E8%BC%83%E3%81%AF%E3%80%81Object.is%20%E3%81%AB%E3%82%88%E3%81%A3%E3%81%A6%E8%A1%8C%E3%82%8F%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82

`Object.is()`は厳密等価演算子`===`とほとんど同じ判定をしますが、`0`と`-0`を一致と判定しない点と、`NaN`同士を一致判定する点で異なっています。

<br/>

変数に配列を代入するとき、変数には配列自体ではなく配列への参照（格納されているメモリのアドレスのこと）が代入されます。

配列に変更を加えるメソッドの中には、（参照を変えることなく）配列を直接変更するメソッドがいくつかあり、それらを使用してもReact 側へは配列に加えた変更が伝わらないこととなります。

## `Object.is()`と配列
変数に配列を代入するとき、変数には配列自体ではなく配列への参照が代入されます。
そのため、以下のように同じ要素を持つ配列を別々に宣言しても、`Object.is()`には一致していると判定されません。
```ts
const arr = [1, 2, 3, 4]

const arr2 = [1, 2, 3, 4]

console.log(Object.is(arr, arr2))
// false
```

しかし、別の変数に配列を代入してからその配列に要素を直接追加して、元の変数と比較したときには一致判定がされます。
```ts
const initialState = ['a', 'b', 'c']
const state = initialState

state[3] = 'd'

console.log(state)
// [ 'a', 'b', 'c', 'd' ]

console.log(Object.is(state, initialState))
//true
```
配列に要素を直接追加しても、`Object.is()`には元と同じ配列であるとみなされて変更が検知できないわけですね。

`state`に配列を格納して値を変更するときには、その変更が検知されるような書き方をする必要があります。

## 新たな配列を返すメソッド
配列を操作するメソッドのうち、変更結果を新しい配列として返すメソッドがいくつか存在します。
基本的にはそれらのメソッドを使用するようにすることで、配列への変更が検知されない事態を避けることができます。

配列操作後に新たな配列を返すメソッドとしては、`concat()`や`map()`、`filter()`や`slice`などが挙げられます。

配列への追加や削除、更新などの用途に応じて以下でみていきます。
### 配列への追加
スプレット構文や`concat`、`push`や`unshift`など

https://qiita.com/axoloto210/items/2092c31d437418ab94cc

### 配列への更新
`map`や`splice`など

https://qiita.com/axoloto210/items/7ecf07764134d8aa185c

### 配列要素の削除
`filter`や`slice`、`splice`など

https://qiita.com/axoloto210/items/dde6f9884049f435e920

### 配列要素の並び替え
`sort`や`reverse`など

https://qiita.com/axoloto210/items/bd37f5906c21c742d3a4

## 直接変更を加えるメソッドを使うには
変更を加えたい配列をあらかじめ複製しておき、複製した配列に対して操作を加えるようにすれば、直接変更を加えるメソッドでも問題なく使用できるので安心です。
関数f = -cos(x)**2 + sin(x) + 3/4の最大値「2023 公立千歳科学技術大学 中期【１】(3)」をChatGPTとsympyとWolframAlpha でやってみたい。

・グラフがでます。
・ChatGPT先生へ。**続けて。**　**続けて。**　**続けて。**　**続けて。**
　いつかは、止まるはずです。
 　**詳しく** もありかも。


# オリジナル
・数学入試問題 様

https://kamelink.com/blog/2024/07/05/3-5-23-koritsuchitosekagidai-chuki-riko-1-3/

・T氏の数学日記 様

https://mathmathmass.exblog.jp/33245180/

・大学入試数学問題集成 様＞ 中期【１】(3) テキスト

https://mathexamtest.web.fc2.com/2023/202311025/2023110250200mj.html#top-0203

# ChatGPT-3.5先生へ。(1回目)
・回答は英語です。
　はじめから、「日本語で」を追加してもいいです。
・ページのソースを表示です。MathMLです。
　省略しようと思いましたが、大学入試数学問題集成 様 の全文から必要部分の抜粋です。
```
<div class="qbody">
<p class="slevel"><a name="q-0203" 
id="q-0203"></a><span 
class="qnum">【１】</span>　以下の問いに答えなさい．解答欄には答えのみ書きなさい．</p>
<p class="s1level"><a name="s-0203" id="s-0203"></a><span 
class="shomon1">(3)</span>　<math>
<mrow><mi>f</mi><mo>&af;</mo><mo stretchy="false">(</mo>
<mi>x</mi><mo stretchy="false">)</mo><mo>=</mo>
<mo>−</mo><msup><mi>cos</mi><mn>2</mn></msup>
<mo>&af;</mo><mi>x</mi><mo>+</mo><mi>sin</mi>
<mo>&af;</mo><mi>x</mi><mo>+</mo>
<mstyle displaystyle="true"><mfrac><mn>3</mn><mn>4</mn>
</mfrac></mstyle></mrow><mspace width=".2em"></mspace>
</math>の最大値を求めなさい．
</p>
</div>
</div>
```

回答省略(英語です)
```
日本語で
```
...
したがって、関数f(x)=-cos(x)^2+sin(x)+3/4の最大値は7/4で、これはy=1のとき(つまりsin(x)=1のとき）に達成されます。
```
sympyのソースコードで
```
```
グラフもお願いします。
```
・(抜粋)　sympyのソースコードがでました。
・私がprint文を追加しています。
```python
from sympy import symbols, cos, sin, diff, solve

# 変数と関数の定義
x = symbols('x')
f = -cos(x)**2 + sin(x) + 3/4

# f(x) の最大値を求めるための準備
f_prime = diff(f, x)  # f(x) の導関数
critical_points = solve(f_prime, x)  # 導関数がゼロとなる点を求める

# 各 critical point での f(x) の値を求める
f_values = [f.subs(x, point) for point in critical_points]

# 最大値を求める
max_value = max(f_values)

max_value

print("#",critical_points)
print("#",max_value)
# [-5*pi/6, -pi/2, -pi/6, pi/2]
# 1.75000000000000
```
・グラフ。あきらめました。自作です。
・縦横比を同じにしました。
```python
from sympy import *
var('x',real=True)
f = -cos(x)**2 + sin(x) + 3/4
plot(f,aspect_ratio=(1.0,1.0),xlim=(-7,7))
```
![0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109698/6596a965-8852-7557-abf4-99b4e846e58d.png)


# ChatGPT実行、途中にでました。

GPT-4o の limit. に達しました
明日の 0:11 以降.に制限がリセットされるまで、回答では GPT-3.5 が使用されます。


# ChatGPT-3.5先生へ。(2回目)
```
平方完成で。詳しく。
```
```
続けて
```

# WolframAlpha で
・グラフがでます。

https://www.wolframalpha.com/input?i=f+%3D+-cos%28x%29**2+%2B+sin%28x%29+%2B+3%2F4%E3%80%80%E3%81%AE%E6%9C%80%E5%A4%A7%E5%80%A4&lang=ja


# sympyで(オリジナル 様の方法で)
???勉強中です。???
参考：「平方完成(へいほうかんせい、英: completing the square) 」を調べた。
https://qiita.com/mrrclb48z/items/c396c61c835888a00de4#ver01-%E5%B9%B3%E6%96%B9%E5%AE%8C%E6%88%90%E3%81%A7\


# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

・以下ができたら、助かります。指定と全部です

https://qiita.com/mrrclb48z/items/555d85face87552c34fb

https://qiita.com/mrrclb48z/items/5f57eac92aaca30e85c0

# いつもと違うおすすめです。
Azure Kubernetes Serviceにおいて特定のノード・コンテナ内でコマンドを実行する方法

# はじめに
Azure Kubernetes Service（以下、AKS）のネットワーク内部構造を検証していた時にAKSの特定のノードや特定のポッド内のコンテナに対してnetnsやipコマンドを実行したい場面があったので方法を調べてみました。

今回のように検証用だけでなく実運用においても障害時等の情報取得にも使えると思いますので、以下に整理します。

# 特定のノード内でコマンドを実行する

[node name]で指定したNode内で特権コンテナを起動する
```
kubectl debug node/[node name] -it --image=mcr.microsoft.com/dotnet/runtime-deps:6.0
```

出力例（node nameに” aks-nodepool1-67404889-vmss000006 “を指定した場合）
```
Creating debugging pod node-debugger-aks-nodepool1-67404889-vmss000006-xsg6g with container debugger on node aks-nodepool1-67404889-vmss000006.
If you don't see a command prompt, try pressing enter.
root@aks-nodepool1-67404889-vmss000006:/# hostname
aks-nodepool1-67404889-vmss000006
```

ルートディレクトリの変更
```
chroot /host
```
以降、node nameで指定したNode内でコマンド実行が可能になる。

（作業後）特権コンテナの削除

```
kubectl delete pod node-debugger-aks-nodepool1-67404889-vmss000006-xsg6g
```

### 補足
検証時は、特権コンテナ起動のイメージは「mcr.microsoft.com/dotnet/runtime-deps:6.0」でしたが、MSLearnの記事が更新されて今は以下のコマンドが最新のようですね。
```
kubectl debug node/[node name] -it --image=mcr.microsoft.com/cbl-mariner/busybox:2.0
```



# 特定のPodのContainer内でコマンドを実行する


[pod name]で指定したPodの[container name]で指定したcontainer内で[command] を実行する

```
kubectl exec -it [pod name] --container [container name] – [command]
```

出力例（commandに” ip link “を指定した場合）
```
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default
 qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0@if16: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT g
roup default 
    link/ether 32:c0:4d:25:d1:7d brd ff:ff:ff:ff:ff:ff link-netnsid 0
```

参考

https://learn.microsoft.com/ja-jp/azure/aks/node-access
[Android] Jetpack Composeで、新規プロジェクトの作り方

Empty Activityをタップして、Jetpack Composeのアプリを作ることができる。

:::note warn
注意 Empty Activityの下にあるEmpty Views Activityをタップしないでください。これは、 XML でアプリ画面を作る場合になります。 
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/393560/d2c4c8cc-1d5b-f652-da36-4bb39501a198.png)
【Auth0】「Error!You don't have permissions to access the resource」と言うエラーが出た時

### エラー内容
Auth0で`Error!You don't have permissions to access the resource`と言うエラーが出ました。

![スクリーンショット 2024-07-07 20.09.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1008681/8a57d444-e150-fd48-aaf3-9475ebee1faf.png)

上記のエラーが出た際の対応策を記します。

### 対応策
1. 一度ログアウトします
2. ログインします
3. 再度Create APIにて作成します

以上。私は上記だけで解決しました。

**補足**
一応、上記の1の前に自分はメールアドレスによる有効化をおこなったので上記で解決しない人はAuth0に登録したメールアドレスのメールボックスを確認してメールアドレスの有効化を行いましょう。その後にもう一度上記の1~3の手順を行なってみてください。
Auth0に登録したての初回のアプリ作成時発生しがちな事象なのかなと思っています。
next/imageとFileReaderを使ってハマったこと

# 起こったこと

input要素に渡された画像をFileReaderで読み込んでプレビュー表示させる機能を作っていました。
画像をアップロードすると以下のエラーが出ました。

```
Error: Image with src (中略) is missing required "height" property.
```

使用したファイルは以下の通りです。

```PreviewImage.tsx
"use client";

import Image from "next/image";
import styled from "styled-component";
import { Skeleton } from "@mui/material";
import { FC, useEffect, useState } from "react";

type PreviewProps = {
  file: File | null;
};

const styledImage = styled(Image)`
    width: 80%;
`;

const PreviewImage: FC<PreviewProps> = ({ file }) => {
  const [url, setUrl] = useState<string>("");
  const isLoading = file && !url;

  useEffect(() => {
    if (!file) return;

    let reader: FileReader | null = new FileReader();
    reader.onloadend = () => {
      const res = reader!.result;
      if (res && typeof res === "string") {
        setUrl(res);
      }
    };
    reader.readAsDataURL(file);

    return () => {
      reader = null;
    };
  }, [file]);

  return file ? isLoading ? <Skeleton /> : <StyledImage src={url} alt={file.name} /> : null;
};

export default PreviewImage;
```

# 原因

`next/image`のImageコンポーネントには`width`と`height`の両方を指定する必要があるようです。
ただ、`StyledImage`に`height`を追加しても同様のエラーが起こったので、`Image`そのものに`width`と`height`を指定する必要があると思われます。

# 修正後のファイル

```previewImage.tsx
import Image from "next/image";
import { Skeleton } from "@mui/material";
import { FC, useEffect, useState } from "react";

type PreviewProps = {
  file: File | null;
};

const PreviewImage: FC<PreviewProps> = ({ file }) => {
  const [url, setUrl] = useState<string>("");
  const isLoading = file && !url;

  useEffect(() => {
    if (!file) return;

    let reader: FileReader | null = new FileReader();
    reader.onloadend = () => {
      const res = reader!.result;
      if (res && typeof res === "string") {
        setUrl(res);
      }
    };
    reader.readAsDataURL(file);

    return () => {
      reader = null;
    };
  }, [file]);

  return file ? isLoading ? <Skeleton /> : <Image src={url} alt={file.name} width={300} height={200} /> : null;
};

export default PreviewImage;
```
PythonをDockerコンテナ上で動かす

# はじめに
こんにちは、H×Hのセンリツ大好きエンジニアです。（同担OKです😉）

今回は初学者の方向けに、**Pythonを仮想環境で動かす**というものをやっていきます。
仮想環境で動かすことで、ローカル環境を汚さなくても良いのでオススメです😁

# Dockerとは
Dockerとは、**軽量で高速に動作するコンテナ型仮想環境用のプラットフォーム**です。
こちらを用いることで開発者間での環境の違いを気にせずに、同じ状態で作業を行えるようになります。

詳しいことは、こちらをご覧ください（とても分かりやすいです😊）

https://www.kagoya.jp/howto/cloud/container/docker/

今回はPythonコンテナだけですが、後々データベースなどのコンテナが必要になることを考え、**Docker Compose**というものも使用します！

# Docker Composeとは
Docker Composeは、**Dockerコンテナの複数管理を容易に行えるツール**です。

Dockerは一度に一つのコンテナしか操作できないのに対し、**Docker Composeを使うことで一気に複数コンテナ（アプリコンテナ、データベースコンテナなど）を動かすことができる**という点がメリットになります。

https://www.kagoya.jp/howto/cloud/container/dockercompose/

# 環境構築してみよう
今回のディレクトリ構成はこちらになります。
```
. /root 
├── compose.yml
└── python
    ├── Dockerfile
    ├── app.py
    └── requirements.txt
```

それぞれのファイルは以下の内容になります。
- `compose.yml`：Docker Composeの設定ファイル
- `Dockerfile`：Dockerイメージ（コンテナの設計書）を作るための設定ファイル
- `app.py`：Python アプリケーションのメインスクリプトファイル
- `requirements.txt`：Python パッケージの依存関係を記述するファイル

一つずつ見ていきましょう
### compose.yml
``` compose.yml
services:
  python:
    build: ./python
    ports:
      - "5000:5000"
```

`services`の中に各コンテナ毎の設定を記述します。（今回はpythonコンテナのみ）
`build: ./python` では、pythonディレクトリ内にある`Dockerfile`を元にビルドします。

``` compose.yml
ports:
      - "5000:5000"
```
portsで、ホストの5000ポートをコンテナの5000ポートにマッピングしています。
これにより、`http://localhost:5000`にアクセスすると、**コンテナ内のアプリケーションにアクセスできる**ようになります。

### Dockerfile
``` Dockerfile
# Pythonのイメージ
FROM python:3.9

# 作業ディレクトリを設定
WORKDIR /usr/src/python

# pipのアップデートと依存関係のインストール
COPY requirements.txt ./
RUN pip install --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt

# ローカルのソースコードをコピー
COPY . .

# コンテナがリッスンするポートを指定
EXPOSE 5000

# コンテナ起動時に実行するコマンドを設定する
CMD ["python", "./app.py"]
```
大体はコメントに記述しているので、細かい部分だけ説明します。
``` Dockerfile
# pipのアップデートと依存関係のインストール
COPY requirements.txt ./
RUN pip install --upgrade pip && \
    pip install --no-cache-dir -r requirements.txt
```

`requirements.txt`をコピーし、pythonのパッケージ管理ツールである`pip`を使用してコンテナ内にパッケージをインストールします。

`COPY requirements.txt ./` と `RUN pip install -r requirements.txt` を分けることで、依存関係が変更されない限り、Docker のキャッシュを利用してビルド時間を短縮します。


`--no-cache-dir`をつけることで、不要なキャッシュを作成しないようにします。
これにより、イメージのサイズが小さくなります。

### app.py
``` app.py
import numpy as np

def main():
  array = np.array([10, 20, 30, 40])
  sum = np.sum(array)
  print(sum)

if __name__ == "__main__":
  main()
```

簡単に挙動を確認するだけなので、`numpy`ライブラリを使用して配列内の合計値を出力するプログラムにしています。

### requirements.txt
``` requirements.txt
numpy
```

この中身は、pipでインポートするライブラリ名を記述します。

### 動作確認
それでは、実際に動かしてみましょう！
以下のコマンドでDockerイメージのビルドとコンテナの起動を行います。
``` zsh
docker compose up --build
```
まずビルドが走り、その後コンテナが起動して`app.py`が呼び出されていることが分かるかと思います！

```
[+] Building 0.7s (10/10) FINISHED
.
.
.
[+] Running 1/1
 ✔ Container python  Recreated
Attaching to python
python  | 100
python exited with code 0
```

これで、pythonをDockerコンテナ上で動かすことが出来ました！

# おわりに
今回は簡単にpythonをコンテナ上で扱うためのHow toを紹介しました！
Webアプリケーションフレームワークを用いてWebサイトの開発をしたり、データ分析やAIを活用する場合に仮想環境を使うと便利なので、是非覚えていただければと思います🤩

最後までご覧いただきありがとうございました！
以上、センリツでした。🤓
[備忘録]　IT用語について分かったことをまとめてみた ~ver.4

# はじめに
こんにちは，Umamusume22です．今回もIT用語について分かったことをまとめてアウトプットしていきます．

# 備忘録
#### タイムスタンプ[1]
- アクセス時刻や更新時刻など，電子データに対して付与される何かの時刻を表す情報のこと．
- 「そのファイルは，その時間に，その内容で存在しましたよ」な証明書のこと
- ファイルなどの電子データに対して付与される時刻情報のこと
- 作成日時，更新日時，アクセス日時などが該当
- タイムスタンプを作った時点の正確な現在時刻
- その時点のファイル内容をもとにして作った情報

#### トークン[2]
- 単語自体の意味は「印」とか「証拠」
- 実際に何を指しているのかは分野や文脈によって異なる
- セキュリティトークンは「使い捨てパスワード払い出し器」
- プログラミングの分野では「ソースコードの内容をそれぞれが意味を持つ最小単位に分けたもの」




# 最後に
今回も記事の内容が短くて申し訳ありません．
引き続きIT用語について分かったことをアウトプットしていきます
読んでいただきありがとございました!

※ウマ娘の声をフーリエ変換した記事や水栓の開閉判定をLineに通知する記事も書いています．suzuが私です．興味がある方はぜひご覧ください！
https://vigne-cla.com/31-1/#toc5

※noteも始めました．
https://note.com/madoka235/n/nbba2153326e1

ぜひフォローよろしくお願いします!




# 参考文献
[1] “「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典”
https://wa3.i-3-i.info/word13116.html

[2] “「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典”
https://wa3.i-3-i.info/word110186.html
ABC361回答メモ

# 0.はじめに
　先週かろうじて緑に復帰したので、キープのための
　大事なコンテスト。
　勢い込んで臨みましたが、Bが難しく大ブレーキ
　Dも解けずさんざんな結果に。
　レート-28の775と転落しました・・・。


# 1.A - Insert
　値がN個あるリストのK番目にXを入れると言う問題。
　答え用リストansを用意し、リストAを頭から入れていき
　N番目の値を入れる前にansにKを入れて後を続ける。
　注意点としては、for文ループの際
　リストの最後に値を入れる時には
　ループ後に値をリストに入れる点位でした。

　https://atcoder.jp/contests/abc361/submissions/55258015


# 2.B - Intersection of Cuboids
　B問題な割には3次元の考慮が必要と苦手な感じでした。
　四苦八苦したものの、どうしてもWA5個が外れず
　タイムオーバーでした。
　
　解説を読んだところ、xyz軸それぞれについて
　重なるかどうかの判定をしてすべて重なれば
　OKという感じでした。
　私の当初の考慮では、a～fの直方体が原点に
　近いパターンしか考えていなかったのが
　問題だったようでした・・・。

　https://atcoder.jp/contests/abc361/submissions/55342933


# 3.C - Make Them Narrow
　B問題に比べるとよっぽど簡単な問題でした。
　問題文はいろいろ惑わしてくるような条件がありましたが
　（残った要素を順序を保って連結した数列をとか）
　数列Aから、（N-K）個の要素を引いた場合の最大値と
　最小値の差が最小になるケースを考える問題に
　帰結すると分かりました。
　
【実装】
　1.N,K,Aを入力
　2.Aをソート
　3.N-Kを変数P(リストAから要素をK省いた時の要素数)に格納
　4.答えを格納する変数ansに10**18を格納
　5.以下、iをP-1～N-1まで繰り返す
　　-5.ansにansとA[i]-A[i-P+1]の小さい方を格納する
　6.ansを出力して終了

　https://atcoder.jp/contests/abc361/submissions/55281639


以上
完全未経験からエンジニアになって１年と３ヶ月が経過したPart2

# １年３ヶ月前
* APIなにそれ？
* AWSなにそれ？
* 倒すってなに？叩くってなに？キーボード叩くじゃねえのかよｗ
* 状態管理ってなんぞ？え？先週までjsやるって言ってたのに違うのか
* 多要素認証？cognito？( ᐛ) パァIAMユーザー？テラフォーム？ラムダ？
* バリデーションってなんだ？AntDesignとは？
* ブランチ？リポジトリ？git?gitとgithubは違うのか？gitbashってなんだ？
* 自動テストコード？Mock？ハ？
* 外部結合と内部結合って何が違うんだ？
* 構成管理ってなんぞ？


# 今
* なるほど全然分からん
DockerからFastAPIを呼び出すときにハマったこと

# 使用していたファイル

```src/server.py
from fastapi import FastAPI

server = FastAPI()

@server.get("/")
async def root():
    return {"message": "Hello World"}
```

```Dockerfile
FROM python:3.11.9-slim-bullseye 

RUN pip install poetry

WORKDIR /app

# 作業ディレクトリにpyproject.tomlとpoetry.lockをコピー
COPY pyproject.toml poetry.lock ./

RUN poetry config virtualenvs.create false \
    && poetry install --no-dev

COPY . ./

EXPOSE 8080

CMD ["poetry", "run", "uvicorn", "src.main:main", "--host", "0.0.0.0", "--port", "8080"]
```

上記のファイルでFastAPIを起動させようとしていたのですが、サーバーが立ち上がらなかったです。
結構ハマってしまったのですが、気づけば原因は単純でした。

# 名前が間違っていた

参考にしたサイトでは、`src/main.py`の中で`main=FastAPI()`としていましたが、私は`src/server.py`にしていた上、`server=FastAPI()`としていました。

Dockerfileで呼び出している名前が違うので起動しないはずです。

Dockerfileの最後の行だけ修正しました。
```Dockerfile
CMD ["poetry", "run", "uvicorn", "src.server:server", "--host", "0.0.0.0", "--port", "8080"]
```

これで、`src/server.py`で定義した`server`を使用することができます。

# 教訓

丸写しはよくない。自分のコードと何が違うか確認する。
Stateで管理している値を数値に変換したいが文字列として扱われてしまう事象について

## 数値として扱いたいが文字列になってしまう事象について

# 今回やりたかったこと
* 登録ボタンを押すたびに学習時間に入力した数値が合計時間として累計で加算して表示されるようにしたい。

# 今回の問題
* 合計時間の下に表示している学習内容と学習時間に入力した値が入る配列を更新するときに数値として扱えていない点
* 配列に追加する際に入力した学習時間の数値に時間という文字列をつけて合計時間には時間を付加させたくないが１時間/1000のように数値の後に時間の文字列がくっついてしまう点

# 下の問題のファイルで文字列として扱われてしまったときのコード
```App.jsx
const handleRegister = () =>{
    if(!inputs.content ||!inputs.time){
      setError("入力されていない項目があります。");
    }
    else{
      const newRecord = {title:inputs.content,time:`${parseInt(inputs.time, 10)}時間`}
      const newRecords = [...records,newRecord];
      setReCords(newRecords);
    setInputs({content:"", time:""});
    setError("");

    //合計時間を計算
      const newTotalTime = newRecords.reduce((sum, record)=> sum + record.time, 0);
      serTotalTime(newTotalTime);
  }
  };
```
# 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/4555cd3e-c5f8-18f0-81a5-48edc2b108f7.png)


# 修正するにあたって
* parseIntの結果を文字列に変換するのではなく、配列に追加してコンポーネントファイルで画面表示行う際に時間を付加すること
⇒表示側と処理側を切り分けて書いていくことにする。

想定通り動いた際のコード

```App.jsx
const handleRegister = () =>{
    if(!inputs.content ||!inputs.time){
      setError("入力されていない項目があります。");
    }
    else{
      const newRecord = {title:inputs.content,time:parseInt(inputs.time, 10) }
      const newRecords = [...records,newRecord];
      setReCords(newRecords);
    setInputs({content:"", time:""});
    setError("");

    //合計時間を計算
      const newTotalTime = newRecords.reduce((sum, record)=> sum + record.time, 0);
      serTotalTime(newTotalTime);
  }
  };
```
```ListDisplay.jsx
//timeを文字列としてフォーマットする関数
const formatTime = (time)=>`${time}時間`;

export const ListDisplay = (props)=>{
    const {recordList} =props;
    return(
        <ul style={{listStyle:"none"}}>
        {recordList.map((record, time)=>
        (
           <li key={time}>
            <p>{record.title}{formatTime(record.time)}</p>
           </li>
        )
       )}
         </ul>
    );
}
```
# 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789688/d3443c18-69ea-269e-ba54-4f47e32b9579.png)
自己署名証明書の作り方（セキュリティの警告なし）

## 目的
* セキュリティの警告が出ない自己証明書を作ります。
ChromeではSAN（Subject Alternative Name）でドメインの一致判定を行うので、SANが設定されるように証明書を作ります。
* https://192.168.56.120/ に警告なしでアクセスすることを目指します。

#### 参考
* [Chrome: オレオレ証明書でもセキュリティ警告画面が出ないようにする方法](https://qiita.com/nnishimura/items/c748f24b65bb77f61c7b)
* [LANのIPアドレスに対してSANを適用して真正なSSL証明書を作成する手順](https://gist.github.com/ykst/2a666d3d41785f9a41d403889f45d82e)

## 手順
##### 1. 差込み情報ファイル作成
証明書作成時にSAN情報を差込むためのファイルを作成します
```console
[root@marmoset ~]# cat san.txt
subjectAltName = DNS:localhost, IP.1:127.0.0.1, IP.2:10.0.2.120, IP.3:192.168.56.120
```
##### 2. 秘密鍵作成
```console
[root@momonga ~]# openssl genrsa -out localhost.key 2048
```
##### 3. 証明書署名要求作成
Common Nameを 192.168.56.120 に設定。チャレンジパスワード不要
```console
[root@momonga ~]# openssl req -new -key localhost.key -out localhost.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:jp
State or Province Name (full name) []:kanagawa
Locality Name (eg, city) [Default City]:yokohama
Organization Name (eg, company) [Default Company Ltd]:my-company
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:192.168.56.120
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
```
##### 4. 自己署名サーバー証明書作成
-extfile オプションで san.txt の情報を差込みます。
```console
[root@marmoset ~]# openssl x509 -req -days 3650 -signkey localhost.key -in localhost.csr -out localhost.crt -extfile san.txt
Certificate request self-signature ok
subject=C = jp, ST = kanagawa, L = yokohama, O = my-company, CN = 192.168.56.120
```
##### 5. 証明書の内容確認
```console
[root@momonga ~]# openssl x509 -in localhost.crt -text -noout
```
以下の項目があることを確認する
X509v3 extensions:
            X509v3 Subject Alternative Name:
                DNS:localhost, IP Address:192.168.56.120, IP Address:127.0.0.1, IP Address:10.0.2.120
##### 6. Apacheの設定
[ApacheとSSL/TLS化](https://qiita.com/tonoaki_sato/items/7a62a13d1a0bf1db2967#2-%E7%A7%98%E5%AF%86%E9%8D%B5%E8%A8%BC%E6%98%8E%E6%9B%B8%E7%BD%B2%E5%90%8D%E8%A6%81%E6%B1%82%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E9%85%8D%E7%BD%AE)
##### 9. Chromeに証明書をインストール
localhost.crt をローカルマシンのChromeにインストールします。
1. localhost.crt をローカルマシンにダウンロードする
1. Chromeを立ち上げて、メニューの「設定」をクリックする
1. 左ペインの「プライバシーとセキュリティー」をクリックする
1. 中央ペインの「セキュリティ」→ 「証明書の管理」の順にクリックする
1. 「証明書」ウィンドウが開くので、「インポート」ボタンをクリックする
1. ダウンロードした localhost.crt を選択してインポートする
1. ブラウザを再起動
1. https://192.168.56.120/ にアクセスする
1. セキュリティの警告が出ずにページが表示されればOK
「sympyで、円周角の定理」を調べたい。

**・「三角形ABCの外側にOがあるとき」私は、わかりませんでした。**

# wikipedia

https://en.wikipedia.org/wiki/Inscribed_angle

https://ja.wikipedia.org/wiki/円周角#円周角の定理

# 証明

https://manabitimes.jp/math/2049

証明
1.三角形ABC の内側に O があるとき
2.三角形ABC の辺上に O がある場合
3.三角形ABC の外側に O があるとき

# sympyで
勉強中
【PageSpeed Insights】「リンクはクロールできません」と指摘された時

# はじめに
今回はPageSpeed Insightsの指摘の1つである「リンクはクロールできません」の改善方法について紹介しようと思います。

# 対策
これはhref がそもそも存在していない、もしくは空の時に指摘されます。
そのため、href=に正しいURLを設定してあげることで指摘を解消することができます。

# まとめ
たしかにリンク先のないaタグがあるのはおかしいですね。
定期的に測定して指摘を潰していきたいと思います。
Re: LocalStackとcdklocalでつくるCDK開発環境入門

# この記事はなに？

2024/07/06 に開催された「AWS CDK Conference Japan 2024」で登壇した、「LocalstackとcdklocalでつくるCDK開発環境入門」に関する登壇内容の補足とします。

当日の懇親会の様々な人との会話を経て、登壇内容にもっと書けることがあったなーと思い、補足しよう！と思ったのがきっかけです。

https://speakerdeck.com/hkusaba1001/localstacktocdklocaldetukurucdkkai-fa-huan-jing-ru-men

## Localstackは dev環境となり得るのか？

Localstackがあれば、開発環境となるAWSリソース群は必要ないのか？
今のところ、私はNoだと思っていて、dev環境は必要だと考えています。

### なぜ？
稀に、イベント駆動系など、実際のAWS上で期待する挙動と異なるケースに遭遇したことがあるためです。
これは「Localstackが悪い！」と言いたいわけではなく、『当時の私の使い方 × Localstack v3.5』で得られた結果です。なので、もしかすると「そんなことないよ！」という声があるかもしれません。

ただ、上記ケースにおいて、Localstackだと少しイマイチだけれど、AWS上のdev環境だと期待する動作となるケースがありました。
なので、当時の自分の検証においては、Localstackのアレコレを更に頑張って実現するよりも、AWSのdev環境での動作が正とした方が、時間的コストがかからないと判断しました。
そのため、個人の感想として、「エミュレートは、あくまでエミュレート」、dev環境は必要だと現時点で考えています。

さらに、『シンプルに私の使い方が悪い可能性』も十分にあり得るので、`Localstacker`な人が増え、「そんなことない！これでいける！」というような知見がコミュニティに出てくると嬉しいなと願っています。

### 余談

ちなみに、Localstack公式によって、各AWSサービスのエミュレート範囲のカバレッジが掲載されています。
こちらと実際のユースケースを考慮して、Localstackを使う・使わないの判断することもできそうです。

https://docs.localstack.cloud/user-guide/aws/feature-coverage/


## では、何のためのLocalstackなのか？

「少しAWSと違うのであれば、使用するケースってあんまりなくない？」という声もありそうな気がするので、私なりにメリットとユースケースを考えてみました。

### メリット

- AWSサービスの利用料がかからない
- 環境がトラブっても、影響範囲が小さい
- 何度デプロイしてもいいし、壊してもいい

### ユースケース

- CDKを学んで動かしてみたいけれど、AWSアカウントはまだ使いたくない場合
- CDKやSAMなどでとりあえずデプロイしたときの動作を見たい時
- プロジェクト開始などの構築の黎明期などの、とりあえず試せる環境
- 環境変数の`SERVICES`を制約して、反映されるAWSサービスを確認したい時
- 自身の手元での動作確認用

--

といった感じだと考えています。

プロポーザル段階では、「CDK学びたいけれど、AWS環境上には実行したくない人」向けに、Localstack使ってみようぜ！というような導線を考えていました。
ただ、資料を作る際にそこがスコッっと抜けていました :pray:

https://fortee.jp/jawsug-cdk-conference-2024/proposal/ca8fc00b-f8ab-4b67-8e74-3ba437dbcb6f


> 対象者
Localstackを知りたい・始めたい人
CDKの開発環境に悩んでいる人

## 最後に

というわけで、「AWS CDK Conference Japan 2024」、お疲れさまでした！

当日はかなり巻きで発表が終わってしまったので、「このあたりも資料に盛り込めておけば丁度だっただろ～～～～！！」と悔やむ気持ちがあります。
ただ、登壇を聴いていただいた方々とお話して、発表できなかった自分の意見が生まれたことを、自分でもうれしく思います。

思い返すと、概要だけのフワッとした発表だったと思いますが、前置き・自分の意見を盛り込むことを、今後の糧にさせていただきます！

またどこかでお会いしましょう！
「もう知ってる」と思える本は、実は成長の証かもしれない

## はじめに

私は周囲から「書籍をたくさん読んでいる」とよく言われます。

2024年上半期には60冊読みました。年間約100冊ペースです。

同じ領域の本を複数読むため、冊数が多くなります。
例えば、Webに関する書籍を複数読んで、[ロードマップに関する記事](https://qiita.com/mkt_hanada/items/d08e409fe90e829f5d34)を書きました。

同じ領域の本を読むと、後半は「知っていることばかりだ」と感じることが増えてきます。

**「新たな学びがない本」は一見無駄に思えますが、成長指標の一つです。**

この記事では「書籍と成長指標」について紹介します。

## 結論

- 「本を読んでも知ってることばかり」は成長指標の一つ
- そもそも「成長の確認」は難しい
- 数千円で成長の確認ができる

## 学びの指標を設定するのは難しい

何かを学ぶとき、学びのゴールを設定するのは重要です。

書籍『CAREER SKILLS』では次のように指摘されています。

> 何かを学び始めたのに、学習が成功したかどうかを測るための方法を持たない人があまりにも多い。

学習の成功を測る方法を設定していないこともありますが、そもそも学びのゴール設定自体が難しいと考えます。

学びのゴールの設定方法は様々あります。

「学びのゴール」の一つは、「この領域の本を買っても新たな学びが少ない」状況です。

その領域について、ある程度は知識があることを確認できます。

書籍を購入するのは、数千円で成長の確認をするためでもあります。

## 次の領域に進む合図

「この領域の本を買っても新たな学びが少ない」と感じたとき、それは他の領域に進むための合図にもなります。

例えば、書籍[『CAREER SKILLS』](https://amzn.asia/d/05SuOFTB)や書籍[『SOFT SKILLS』](https://amzn.asia/d/039fMfI7)は、「ソフトウェア開発者の人生」について書かれた書籍です。

内容は良いものの、既知の情報が多く含まれていました。

「ソフトウェア開発者の人生」に関する領域はこれで一区切りし、他の領域の本を読みます。

このサイクルを繰り返していくことで、知識の幅が広がっていきます。

## おわりに

この記事では、書籍と成長指標についての考え方を紹介しました。

参考になれば幸いです。
ALBで1025文字以上のメンテナンス画面を表示する方法

### 背景
AWSのALB（Application Load Balancer）のリスナールールを使ってメンテナンス画面を表示することは一般的ですが、ALBのリスナールールには1024文字の制限があります。
そのため、1024文字を超えるメンテナンス画面を表示するための方法として、S3とLambdaを利用するアプローチを紹介します。
これにより、ALBのリスナールールの優先順位を変更することで、メンテナンス画面を自由かつ簡単に表示することができます。
設定時間も10分程度なので、ぜひやってみてください！

### 前提条件
- ALBを使用したWeb3層構造のアーキテクチャ構築済み（または構築予定の方）

### 構成概要
単純に、新しいルートを作って向き先を変えるだけです。（簡単でしょ！）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/923114/e9630579-5bcb-c761-7fd4-1c09e96f20fe.png)


### 設計の流れ
1. S3にメンテナンス画面のHTMLファイルをアップロード
2. Lambda関数を作成して、S3からHTMLファイルを取得し、メンテナンス画面を表示
3. ALBのリスナールールを設定して、特定の条件でLambda関数をトリガー

#### ステップ1: S3にメンテナンス画面のHTMLファイルをアップロード
まず、S3バケットを作成し、メンテナンス画面のHTMLファイルをアップロードします。

1. AWSマネジメントコンソールにログインし、S3サービスに移動します
2. 新しいバケットを作成します（例: `maintenance-bucket`）
3. バケットにメンテナンス画面のHTMLファイル（例: `maintenance.html`）をアップロードします（今回は1024文字以下のファイルですが、必要に応じて1025文字以上のファイルを作成してください）

```html
<!DOCTYPE html>
<html>
<head>
    <title>メンテナンス中</title>
</head>
<body>
    <h1>ただいまメンテナンス中です</h1>
    <p>ご迷惑をおかけして申し訳ありません。しばらくお待ちください。</p>
</body>
</html>
```

4. 次に、S3バケットに対して以下のバケットポリシーを設定し、特定のHTMLファイルへの読み取りアクセスを許可します。

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "PublicReadGetObject",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": [
                "arn:aws:s3:::maintenance-bucket/maintenance.html"
            ]
        }
    ]
}
```

#### ステップ2: Lambda関数を作成して、S3からHTMLファイルを取得し、メンテナンス画面を表示
次に、Lambda関数を作成し、S3からHTMLファイルを取得してレスポンスとして返すように設定します。
下記の関数は、環境変数を使っているため、適宜変更してください。

1. AWSマネジメントコンソールにログインし、Lambdaサービスに移動します
2. 新しいLambda関数を作成します（例: `maintenance-lambda`）
3. ランタイムはPython 3.xを選択し、以下のコードをLambda関数に貼り付けます

```python
import boto3
import os

# 環境変数からS3の情報を取得
BUCKET_NAME = os.environ['BUCKET_NAME']
FILE_NAME = os.environ['FILE_NAME']

s3 = boto3.client('s3')

def lambda_handler(event, context):
    try:
        # S3バケットからHTMLファイルを取得
        response = s3.get_object(Bucket=BUCKET_NAME, Key=FILE_NAME)
        body = response['Body'].read().decode('utf-8')

        return {
            'statusCode': 200,
            'headers': {
                'Content-Type': 'text/html'
            },
            'body': body,
            'isBase64Encoded': False
        }
    except Exception as e:
        return {
            'statusCode': 500,
            'body': f"Error getting the HTML from S3: {str(e)}"
        }
```

4. Lambda関数に必要なS3へのアクセス権限を持つIAMロールを割り当てます

#### ステップ3: ALBのリスナールールを設定して、特定の条件でLambda関数をトリガー
最後に、ALBのリスナールールを設定して、特定の条件下でLambda関数をトリガーします。

1. ALBとLambdaを紐づけるターゲットグループを作成してください
2. ALBのリスナールールに移動し、新しいルールを追加します
3. リスナールールの条件として、特定のパス（例: `/maintenance`）やホストヘッダーを指定します
4. アクションとして、「固定レスポンス」ではなく、「ターゲットグループへ転送」を選択し、新しく作成したターゲットグループを指定します
5. ルールの優先順位を設定して、通常のトラフィックよりも高い優先順位を付けます

これで、指定した条件に基づいてメンテナンス画面を表示するLambda関数がトリガーされるようになります。
リスナールールの優先順位を変更することで、メンテナンス画面の表示を柔軟にコントロールできます。

#### まとめ
この方法を使うことで、ALBのリスナールールの文字数制限を超えたメンテナンス画面を表示することが可能になります。
S3にホストされたHTMLファイルをLambda関数で取得し、ALBのリスナールールでトリガーすることで、メンテナンスのメッセージを簡単に管理できるようになります。
Excelの条件付き書式が使えない

## 条件付き書式で土日に色を付けるだけなのに

条件付き書式ってややこしくないですか？
VBAなら秒でコード書けた

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/2365e3a0-5853-3d87-0bd2-ebae69c67507.png)

![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/4640469e-ddc7-fc99-09c0-4253ac3d3fdd.png)

![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/7f81775b-8287-290d-95b7-50c2f62bb210.png)

```vb

Sub 土日に色を付ける()

  Dim i As Long
  
  For i = 3 To 23
    If Cells(i, 6).Value = "土" Then
        Cells(i, 6).Interior.ColorIndex = 37
    End If
    If Cells(i, 6).Value = "日" Then
        Cells(i, 6).Interior.ColorIndex = 45
    End If
  Next i
  
End Sub
```
LeetCode挑戦日記：Day30

# はじめに

最近、業務で実装する時間よりも資料作成やレビューをする時間が多くなってきました。
このままでは自身のコーディング能力が落ちそうで怖いので、LeetCodeを始めてみました。

自身の学習の記録 & LeetCodeに興味のある人が挑戦しやすいように、記事に残していきます。
このような競技プログラミングをした経験がないので、ひよってEasyからやっていきます...

# [Medium] 328. Odd Even Linked List

単方向リンクリストの先頭が与えられたとき、奇数インデックスのノードをすべてまとめ、その後に偶数インデックスのノードを続けて配置し、並び替えられたリストを返します。

最初のノードは奇数と見なされ、2番目のノードは偶数と見なされます。

なお、偶数グループおよび奇数グループ内の相対的な順序は入力時のままである必要があります。

この問題をO(1)の追加スペースの計算量とO(n)の時間計算量で解く必要があります。


## 素直に解いてみる

### 考え方

1. 偶数グループの先頭`node`を残しておく
1. 奇数グループと偶数グループの`next`をずらしていく

### コーディング

```typescript
function oddEvenList(head: ListNode | null): ListNode | null {
    if (!head || !head.next) { return head; }

    const evenHead = head.next;

    let odd = head;
    let even = head.next;
    while (odd.next && even.next) {
        odd.next = odd.next.next;
        even.next = even.next.next;
        odd = odd.next;
        even = even.next;
    }
    odd.next = evenHead;
    return head;
};
```

### 結果

Runtime：62ms
Beats 92.57%

Memory：53.82MB
Beats 56.19%
memo: モチベーションの理論

簡単に説明して。

Maslow's Hierarchy of Needs, Herzberg's Motivator-Hygiene Theory, McClelland's Learned Needs Theory, and McGregor's Theory X and Y. Process-based theories include Adam's Equity Theory, Vroom's Expectancy Theory, and Skinner's Reinforcement Theory.


# マズローの欲求階層説 (Maslow’s Hierarchy of Needs):
アブラハム・マズローによって提唱された理論で、人間の動機づけは5つの基本的なカテゴリの階層から生じると考えます。
以下は階層の詳細です：
生理的ニーズ: 食事、水、睡眠などの基本的な生存ニーズ。
安全ニーズ: 安全な環境、雇用、健康など。
愛と所属ニーズ: 友情、家族、社会的なつながり。
自尊心ニーズ: 自己評価、成功、尊重。
自己実現ニーズ: 個人の潜在能力の最大限の発揮。

# ハーズバーグのモチベーター・ハイジーン理論 (Herzberg’s Two-Factor Theory):
フレデリック・ハーズバーグによって提唱された理論で、仕事の満足度と不満足度を2つの要因に分けています。
モチベーション要因: 仕事そのものから生じる要因（成長、達成、責任）。
ハイジーン要因: 仕事の環境や条件から生じる要因（給与、労働条件、同僚）。

# マクレランドの学習ニーズ理論 (McClelland’s Learned Needs Theory):
デビッド・マクレランドによって提唱された理論で、人々のニーズは「成就ニーズ」（達成、所属、権力）に基づいています。
達成ニーズ: 成功を追求する欲求。
所属ニーズ: グループへの帰属とつながりを求める欲求。
権力ニーズ: 影響力や支配を求める欲求。

# マクレガーのX理論とY理論 (McGregor’s Theory X and Y):
ダグラス・マクレガーによって提唱された理論で、組織のリーダーシップスタイルに基づいて従業員の動機づけを説明します。
X理論: 従業員を怠惰で自己中心的とみなし、厳格な管理が必要とされる。
Y理論: 従業員を能動的で責任感のある存在とみなし、自己管理が可能であると考える。

# プロセス理論 (Process-Based Theories):
動機づけのプロセスを研究した理論です。
代表的なものには、ヴルームの期待理論とアダムの公平理論があります。
どの理論も、組織や個人の動機づけに影響を与える要因を理解する上で重要です。 😊

You
Sent by you:
ヴルームの期待理論とアダムの公平理論について教えて
Copilot
Sent by Copilot:
もちろんです！それでは、ヴルームの期待理論とアダムの公平理論について詳しく説明しますね。

## ヴルームの期待理論 (Vroom’s Expectancy Theory):

ヴィクトル・ヴルームによって提唱された理論で、人々のモチベーションは以下の3つの要素に基づいています：
期待 (Expectancy): 努力が成果に結びつく確率。つまり、目標達成に対する自信や期待度。
道具性 (Instrumentality): 成果が報酬にどれだけ結びつくか。報酬が得られることへの信念。
誘意性 (Valence): 提示された報酬の魅力度。報酬がどれだけ魅力的か。
これらの要素を組み合わせて、モチベーションは次の式で表されます：
モチベーション=期待×道具性×誘意性

## アダムスの公平理論 (Adams’ Equity Theory):
J.ステーシー・アダムスによって提唱された理論で、人は他人と比べて不公平がある場合、それを解消して公平な状態に近づくよう動機付けられると考えます。
公平感は報酬や負担の比較に基づいて形成され、不公平感が高まるとモチベーションが低下します。
これらの理論は、組織や個人の動機づけに影響を与える要因を理解する上で重要です。12 😊
Adamより50%速い最適化アルゴリズム（Adam-mini）が公開されました

最近、LLMトレーニング中のメモリを大幅に削減できる技術が登場したので、紹介したいと思います。この技術は「Adam-mini」と呼ばれ、従来のAdamの改良版です。
ディープラーニングにおいて、Adamは最も一般的に使われている最適化アルゴリズムであり、LLMのトレーニングではほぼ標準となっています。最適化アルゴリズムは主にモデルのパラメータを更新・計算し、lossを最小化するために使用されます。

Adamは計算速度が速く、性能も優れていますが、メモリ使用量が比較的多いという課題があります。例えば、7Bのモデルをトレーニングする場合、optimizerの状態（m、vというパラメータ）を保存するために、少なくとも約50GB以上のメモリが必要になります。

最近公開されたAdam-miniは、トレーニング中のメモリ使用量を半分に削減できると謳っています。基本的には、transformerの設定において、トレーニング時に各パラメータブロックに異なる学習率を設定する必要があります。しかし、Adamは精度を求めるために、パラメータブロック単位ではなく、各パラメータに異なる学習率を割り当てています。（通常、パラメータは数十億個ありますが、パラメータブロックは約数百個程度です）。

なので、Adam-miniの開発チームは学習率をパラメータレベルまで精密に設定する必要はなく、パラメータブロックレベルで十分ではないかという仮説を立て、検証しました。その結果、パラメータブロックレベルでも精度はそれほど損なうことなく、処理速度は大幅に向上させることができることが分かりました。

⇩はllama3-7Bモデルのトレーニングを行った結果です。メモリ使用量が約50%削減され、スループットも50%向上したとのことです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/0ad92ae0-f787-5751-6077-746fe8e79757.png)


私も試してみましたが、なぜかうまくいきませんでした。トレーニング後のモデル（チェックポイント）のサイズは確かに大幅小さくなったものの、トレーニング中のメモリ使用量は変化しませんでした。メモリ使用量が変わらなかったため、当然ながらスループットも向上しませんでした。
この問題をgitHubのissueで質問しようとしたところ、既に複数の人が同じような状況を報告しています。現時点では開発チームからまだ回答はないですが、回答があり次第、もう一度試してみたいと思います。


興味ある方：

https://arxiv.org/abs/2406.16793

https://github.com/zyushun/Adam-mini
[備忘録]Classのコンストラクター[dart]

```cat.dart
class Cat {
  String name;
  Cat(this.name);　//コンストラクタの例
}
```
`Cat(this.name)` の部分がコンストラクター。Classを使うための基本？

コンストラクターとstatic（ファクトリメソッド）の違いは、コンストラクタはClassの引数で具体的な値が決まってる。逆にファクトリメソッドはClassに所属する関数みたいなものでreturnで何か値とか結果（ただのprintとかも）を返してやるイメージ

クラスからオブジェクト（インスタンス）を作成し、そのオブジェクトを初期化するための特別なメソッド。

taticはクラス全体に共有されるたとえば下の例だとstaticCounterがクラス全体に共有される

Dartにおけるstaticキーワードは、クラスメンバー（フィールドやメソッド）がインスタンスではなくクラス自体に属することを示します。したがって、staticメンバーは特定のインスタンスに関連付けられず、クラス自体に関連付けられます。

```class.dart
class MyClass {
  int value;

  // 通常のコンストラクタ
  MyClass(this.value);

  // ファクトリメソッド（staticメソッド）
  static MyClass createInstance(int value) {
    return MyClass(value);
  }
}

void main() {
  // 通常のコンストラクタを使用してオブジェクトを作成
  var obj1 = MyClass(42);
  print(obj1.value); // 出力: 42

  // ファクトリメソッドを使用してオブジェクトを作成
  var obj2 = MyClass.createInstance(30);
  print(obj2.value); // 出力: 30
}
```
「git commit -m "..." がめんどくせぇ！」そんなあなたにこのエイリアス

# 魔法のエイリアス
```sh
alias gm='function _gm(){ git commit -m "$1"; }; _gm'
```

# 使い方
`gm コミットメッセージ` という使い方ができます。
`gm これは　コミットメッセージです` みたいに、空白を間に入れてもきちんと認識されます。

```bash
$ gm 文言修正 インデント修正
[master 38efee0] 文言修正 インデント修正
 1 file changed, 2 insertions(+), 3 deletions(-)

$ git log --oneline
 38efee0 (HEAD -> master) 文言修正 インデント修正
 ...
```
Zabbix7.0LTSをAlmaLinux9にインストール

# 環境
Zabbixのダウンロード手順は公式通りにやろうとすると、DBなどのインストール手順が含まれないため、
こちらに記載する。なお、今回の構成は、HAを考慮しない。また、ZabbixとDBは同じサーバに存在するものとする。

- OS：AlmaLinux9.3
- Zabbix：7.0 LTS
- DB：mysql 8.0.36
- Web:httpd：2.4.57

# 手順

DB、webをインストールする。
```
dnf install mysql-server httpd
```
その後、以下のコマンドでzabbixのリポジトリをいれる
```
# rpm -Uvh https://repo.zabbix.com/zabbix/7.0/rhel/9/x86_64/zabbix-release-7.0-3.el9.noarch.rpm
# dnf clean all
```

その後、zabbixをインストールする。
```
dnf install zabbix-server-mysql zabbix-web-mysql zabbix-apache-conf zabbix-sql-scripts zabbix-selinux-policy zabbix-agent
```
そして、mysqlを起動させる。
```
systemctl start mysqld
systemctl enable mysqld
```

#　DB以降の操作とZabbixの起動

以降は、DB側の操作になる。
以下のコマンドを実行する
```
mysql -uroot -p
```
mysqlのデフォルトパスワードは`/var/log/mysqld.log`にある。
```
cat /var/log/mysql/mysqld.log | grep password
```
などで確認すること。今回は、`empty`となっているので、そのまま
PW：root
Pass：何も入力せずにEnter
で進める。

そして、mysqlで操作を進める。差し当たり、公式の手順をそのままコピペしている。
```
mysql> create database zabbix character set utf8mb4 collate utf8mb4_bin;
mysql> create user zabbix@localhost identified by 'password';
mysql> grant all privileges on zabbix.* to zabbix@localhost;
mysql> set global log_bin_trust_function_creators = 1;
mysql> quit;
```

その後、以下のコマンドを実行する。
```
zcat /usr/share/zabbix-sql-scripts/mysql/server.sql.gz | mysql --default-character-set=utf8mb4 -uzabbix -p zabbix
```
この時、zabbixデータベースのパスワードを聞かれる。
上記のをそのままコピペした場合`create user zabbix@localhost identified by 'password';`より,`password`がパスワードになる。

その後、`og_bin_trust_function_creators`というものを無効にする。
```
# mysql -uroot -p
password
mysql> set global log_bin_trust_function_creators = 0;
mysql> quit;
```

その後、zabbix.confから、zabbixデータベースのパスワードを記載する。
```/etc/zabbix/zabbix_server.conf
DBPassword=password
```
今回の設定ではそのままにするが、必要に応じて以下の記載も変更する。
```
DBHost=localhost(DBのホストIP)
DBName=zabbix（データベースの名前）
DBUser=zabbix（データベースのユーザー名）
```

その後、Zabbixを起動させる。
```
systemctl restart zabbix-server zabbix-agent httpd php-fpm

 さらに自動起動も入れておく。
systemctl enable zabbix-server zabbix-agent httpd php-fpm
```

その後、http://ホストのIP/zabbix
にアクセスする。ここではIPはlocalhost。この時、firewalldで、httpを許可しているかどうかを事前に確認しておくこと。


# Zabbix起動後

1. 言語は今回は日本語にする
1. 前提条件が全てOKになっている事を確認したら次のステップへ。
1. データベースのパスワードに先ほど設定したzabbixDBのパスワード。この手順なら`password`を入れて次へ。
1. 任意のZabbixサーバー名を入力し、タイムゾーン欄で【(UTC+9:00) Asia/Tokyo】を選択して次へ。
1. パラメータを確認して次へを押すと、初期設定は完了。

ZabbixWEBUIのユーザー名とパスワードを入れる事ができる。
デフォルトは
- Admin
- zabbix



# 参考サイト

https://www.zabbix.com/download?zabbix=7.0&os_distribution=red_hat_enterprise_linux&os_version=9&components=server_frontend_agent&db=mysql&ws=apache

https://blog.usize-tech.com/zabbix7-lts/
EC2上でVue.jsによる環境構築から初期ページ表示まで

# はじめに
タイトル通り、常にEC2上で作業し続け、Vue.jsの初期画面を表示するまでの手順を整理したものです。

# 参考文献
- [Vue.js公式サイト](https://ja.vuejs.org/guide/quick-start)
- [自分で作ったWEBアプリ（Vue.js）をインターネット公開しよう](https://qiita.com/hiyasichuka/items/b4dc9d728ea39d4d8a5e)
- [Node.js公式?のgithub](https://github.com/nodesource/distributions)

# サーバの環境構築
# Node.jsとnpmのインストール
以下のコマンドを順に実行していく。

```
curl -fsSL https://deb.nodesource.com/setup_22.x -o nodesource_setup.sh
sudo -E bash nodesource_setup.sh
sudo apt install -y nodejs
```

インストール確認としてバージョン表示を行う。

```
node -v
```

npmのインストールは、nodejsと一緒に行われるっぽい（自分の環境ではそうだった）。
バージョン確認でインストールをチェック
```
npm -v
```

これでもしバージョンが表示されなかったら、以下のコマンドでインストールする。
```
sudo apt install -y npm
```

## Vue.jsのインストール
最初に作業ディレクトリへ移動する。

```
cd /var/www/html/
sudo mkdir vue-test
cd vue-test
```

その後、インストールコマンドを実行する。

```
sudo npm create vue@latest
```

実行するとプロジェクト名を聞かれるので、テキトーに入力する。
（記事内では`vue-project`とする）

その他、いくつか聞かれるので、適宜選択して進める。
基本的には`NO`でOK。

インストールが終われば、以下のようなコマンド指示が出るので実行する。

```
cd vue-project
sudo npm install
```

最後の`npm run dev`については、実行しなくてもOK。

これでVue.jsの環境構築も終了。

# ページの表示
## プロジェクトのビルド
表示するためにはビルドが必要なので、以下のコマンドを実行する。

```
sudo npm run build
```

これにより、`./dist`の中にビルドされたファイルが作成される。

## ページを表示させる
これらを任意の場所に移動させよう。

```:例
sudo cp -r dist/* /var/www/html/vue-test
```

あとは`http://<your domain>/vue-test/index.html`にアクセスすれば表示される。

・
・
・

はずが、なぜか真っ白なページが表示される。
原因は`index.html`の記述。

```html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
    <script type="module" crossorigin src="/assets/index-B_pMlDuz.js"></script>
    <link rel="stylesheet" crossorigin href="/assets/index-DHqK1tyo.css">
  </head>
  <body>
    <div id="app"></div>
  </body>
</html>
```

これの7,8行目の指定が正しくないので、以下のように修正する必要がある。
分かりにくいが、`src=./assets/...`、`href=./assets/...`のように`.`を足している。

```html
    <script type="module" crossorigin src="./assets/index-B_pMlDuz.js"></script>
    <link rel="stylesheet" crossorigin href="./assets/index-DHqK1tyo.css">
```

これでページ再読み込みすると、以下のようなVue.jsの初期画面が表示される。

![スクリーンショット 2024-07-07 190046.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/382806/92299b0e-b9ab-c4c2-47aa-3effd66ead7d.jpeg)

# さいごに
最後の表示させるための修正はビルドのたびに必要なので注意。
その辺上手くやる設定があればコメントなどで教えて下さい。
Virtual Box で Linux Mint を起動させた

## USBブートしようとして何回も失敗
USBにダウンロードできたと思ったら、BIOSから起動させる段階で何回も失敗して心が折れかけていたところ、Virtual Box の存在を知り、やってみたら簡単にできました。ちなみに、USBブート試行の過程で外付けのSSDを1個壊しました。ほかのUSBメモリのデータ（isoイメージ）を何回も出し入れしていたらなんか容量が小さくなった気がします。

![VirtualBox_Linuxmint_07_07_2024_18_49_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/b8da40c0-fe17-343f-66c9-1bcc3c5209ad.png)

![VirtualBox_Linuxmint_07_07_2024_18_50_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3812230/573b83da-ec1a-9e56-4853-34f85e0f16a8.png)

仮想環境なので、画面が見にくいですが、しばらくこれでやってみます。