OmniAICreator/Qiita-1.07M huggingface dataset:
2024/5/21主にITとかセキュリティの記事

国家の情報保全措置の一環「セキュリティー・クリアランス制度」可決 情報漏洩には拘禁刑・罰金刑、差別・プライバシー侵害などの懸念も(5/19)
https://news.nifty.com/article/entame/showbizd/12199-3049553/

サイバーセキュリティ情報インプット集 第1.0版(5/19)
https://qiita.com/secubot5/items/29c7d773a7cf40541a52

中小企業狙うサイバー攻撃　供給網の弱点、対策に甘さ(5/19)
https://www.nikkei.com/article/DGXZQOCD139OT0T10C24A5000000/

ＰＣ修理名目で８万円詐欺被害　四日市の40代男性(5/19)
https://www.isenp.co.jp/2024/05/19/110516/

デジタル通貨で観光周遊、関係各社と自治体や利用者の課題解決へ(5/17)
https://bp-affairs.com/news/2024/05/20240517-12297.html

メッセンジャーアプリのSignalがTelegramよりも安全であると専門家によって広くみなされている理由とは？(5/19)
https://gigazine.net/news/20240519-signal-safety-telegram/

医療情報ガイドラインの AWS 対応方法を調べてみた(5/19)
https://dev.classmethod.jp/articles/exploring-aws-compliance-for-medical-information-guidelines/

第2期GIGAスクールでAI活用・学校DX・PC改善を狙う、日本マイクロソフトの戦略(5/19)
https://news.mynavi.jp/article/newsinsight-288/

リスクの３要素 戦略、リスク、企業価値の変動(5/19)
https://www.risktaisaku.com/articles/-/91632

自民・小林鷹之氏「経済安保の全体像を打ち出すべきだ」(5/19)
https://www.nikkei.com/article/DGXZQOUA190GU0Z10C24A5000000/

同友会の神原新代表幹事「定住人口化できるか、大きなプロジェクト」記者会見(5/18)
https://news.kobekeizai.jp/blog-entry-16684.html

ランサムウエア被害の15カ国調査で判明、日本は「身代金の支払い渋りで被害減少」(5/20)
https://xtech.nikkei.com/atcl/nxt/column/18/00001/09289/

NAVERとの資本関係見直しを迫られたLINEヤフー、危機を乗り越えられるのか(5/20)
https://xtech.nikkei.com/atcl/nxt/column/18/00086/00309/

氾濫する生成AIの悪用と向き合う、国をも巻き込む対策の「現在地」(5/20)
https://xtech.nikkei.com/atcl/nxt/column/18/02830/051400003/

DX推進組織を子会社から移管した明治HD、「現場の声を聞く力」で変革進める
古賀 猛文 氏　明治ホールディングス 執行役員グループDX戦略部管掌(5/20)
https://xtech.nikkei.com/atcl/nxt/column/18/01159/050800056/

Microsoft Copilotを使うと何がうれしいのか、検索との違いを理解しよう(5/20)
https://xtech.nikkei.com/atcl/nxt/column/18/02815/041900001/
【Unity】AnimatorのTriggerを自動でResetする拡張メソッド（SetTrigger、ResetTrigger）

# 概要

AnimatorステートマシンのTriggerはUnity標準機能のはずなのにReset周りがとてもややこしいです。
ざっくり言えば、攻撃中に攻撃ボタンを押すと、攻撃が終わったあとに攻撃を始めます。

Unity Technologies Japan様の動画では「攻撃の意思が残留する」と表現しています。
[AnimatorControllerを使ってコンボ攻撃する方法 - Animation Tips #2](https://youtu.be/oF-nby5JBSw?list=PLT02dECXwYcmIdPvVisuxjMKdPsTnhiso&t=180)

動画内で行われているように、StateMachineBehaviourをアタッチするのも手段の一つです。
しかし、ジャンプ中に攻撃ボタンを押すなどすると、ジャンプ終了着地後に攻撃を始めるかもしれないので、結局あらゆるTriggerをResetするしかありません。
そして、AnimatorController本体に手を入れるのも正直抵抗があります。

そのため、できるだけ通常のSetTriggerと同じ感覚で使用でき、適切なタイミングでResetを行うようにしてほしいです。

# 対応

下記記事では1フレームでリセットする手法が紹介されていました。

LIGHT11様
[【Unity】【Animator Controller】即座に遷移できなかったら無効になるトリガーを作る](https://light11.hatenadiary.com/entry/2020/02/23/201528)

今回はこちらの記事を参考に、以下の改善を行いました。
- LateUpdateのSetTriggerにも対応

```cs:AnimatorExtension.cs
using UnityEngine;
using UniRx;
using UniRx.Triggers;
using System.Threading;
using Cysharp.Threading.Tasks;

public static class AnimatorExtension
{
	public static void SetTriggerOneShot(this Animator self, string name)
	{
		var cts = new CancellationTokenSource();

		self.SetTrigger(name);
		self.OnAnimatorMoveAsObservable()
			.Subscribe(_ => { self.ResetTrigger(name); cts.Cancel(); })
			.AddTo(cts.Token)
			.AddTo(self.GetCancellationTokenOnDestroy());
	}

	public static void SetTriggerOneShot(this Animator self, int id)
	{
		var cts = new CancellationTokenSource();

		self.SetTrigger(id);
		self.OnAnimatorMoveAsObservable()
			.Subscribe(_ => { self.ResetTrigger(id); cts.Cancel(); })
			.AddTo(cts.Token)
			.AddTo(self.GetCancellationTokenOnDestroy());
	}
}

```

注意点としては、1フレームでリセットされるため
実際にStateが再生され終わるのを待って遷移させたい場合は
通常のSetTriggerを使うようにすることくらいでしょうか。

つまり、コンボ攻撃などで攻撃A中に攻撃ボタンを押したとき、攻撃Aが所定のフレームに達したあとに攻撃Bが出る（いわゆる「先行入力」）が想定の仕様の場合です。

# 誰か助けて

本当はUniTaskだけで完結させたかったですが、OnAnimatoMove直後に処理を実行するやり方がわかりませんでした。
```cs:AnimatorExtensionUniTask.cs
using UnityEngine;
using Cysharp.Threading.Tasks;

public static class AnimatorExtension
{
	public static void SetTriggerOneShot(this Animator self, string name)
	{
		self.SetTrigger(name);
		AutoResetTrigger(self, name).Forget();
	}

	public static void SetTriggerOneShot(this Animator self, int id)
	{
		self.SetTrigger(id);
		AutoResetTrigger(self, id).Forget();
	}

	private static async UniTaskVoid AutoResetTrigger(Animator animator, string name)
	{
		// Update,OnAnimatorMove,PreLateUpdate,LateUpdate だと思ったのに…….
		await UniTask.Yield(PlayerLoopTiming.PreLateUpdate, animator.GetCancellationTokenOnDestroy());

		if (animator == null)
		{
			return;
		}

		animator.ResetTrigger(name);
	}

	private static async UniTaskVoid AutoResetTrigger(Animator animator, int id)
	{
		// Update,OnAnimatorMove,PreLateUpdate,LateUpdate だと思ったのに…….
		await UniTask.Yield(PlayerLoopTiming.PreLateUpdate, animator.GetCancellationTokenOnDestroy());

		if (animator == null)
		{
			return;
		}

		animator.ResetTrigger(id);
	}
}

```

# 結論
Triggerは本記事のような拡張メソッドで1フレーム、それ以外はBoolという運用でいい気がする。
Linux 基礎 タイムゾーン/日本語設定

## 概要
- 自分がコピペできるように設定を置いておく

## 設定
```bash
# タイムゾーンを日本に設定する
timedatectl set-timezone Asia/Tokyo
# 日本語に設定する
localectl set-locale LANG=ja_JP.utf8
# 設定を反映する
source /etc/locale.conf
# 確認
date
```
トラブル対応メモ：PHP画面から外部サーバへのファイル転送不良

いつものように基本的知識の不足ゆえ、久々にドハマりしてしまったのでメモ。

### （前提） ###
+ やりたいこと：PHPプログラム（Web画面）からexec関数を実行し、SCPを使って外部サーバへファイルをリネームしながら転送
+ SCPの実行に当たっては、本来は公開鍵方式でやるべきだが、相手先サーバの事情によりパスワード認証方式で実行せねばならない。
　⇒シェルのexpectコマンドを使ってSCPを実行し、疑似対話イメージでパスワードを指定することにした。
``` shell
expect -c "
set timeout 30
spawn /usr/bin/scp (転送元ディレクトリ)/hoge.txt root@(転送先サーバ):(転送先ディレクトリ)/hogefuga.txt
expect default { exit 10 }   \"root@(転送先サーバ)'s password: \"  ; send \"(転送先サーバパスワード)\n\"
interact
"
```
 ### （発生した事象） ###
+ PHPプログラムを実行したところ、転送先サーバにリネーム後のファイルがコピーされない。
+ ただし、転送先にリネーム後と同名のファイルがあれば、正しく上書きされる。
+ 上記SCPコマンドをコマンドラインから実行すると、転送先の同名ファイルの有無にかかわらずリネーム後のファイルが正しくコピーされる。

当初はPHPの設定の問題かと、その近辺をあれこれ調べましたが、該当する要素は見つからず・・・

### （原因） ###
1) expectコマンド中のパスワード送信時の改行コードが誤っていました（"\r"が正）。
2) 何より、expectで指定しているコマンド中の"interact"が悪さしてた模様です。

manによれば、"interact"はプロセスの制御をユーザーに渡すコマンドのため、上記の例では標準入出力がシェルに戻ってしまうそうで。
それでリネームファイルがコピーできない原理は「？」なのですが:sweat_smile:、ともあれ望ましい姿にはすべきでしょう。
⇒対話形式シェルのソースをサンプルにして、よー調べんとコピーしたのがあかんかったようです・・・

### （対応） ###
expectコマンドの内容を、（参考）のページを参考に修正し、結果正しくコピーできるようになりました。
``` shell
expect -c "
set timeout 30
spawn /usr/bin/scp (転送元ディレクトリ)/hoge.txt root@(転送先サーバ):(転送先ディレクトリ)/hogefuga.txt
expect default { exit 10 }   \"root@(転送先サーバ)'s password: \"  ; send \"(転送先サーバパスワード)\n\"
expect {\"100%\" { exit 0}}
"
```

### （参考） ###
[シェル以外からexpectしててハマったメモ](https://blog.wnotes.net/posts/expect-other-programs/)
※鬼のようにググっていたら、たまたまヒットしたのがラッキーでした
Javaで「キャスト演算子と型変換ルール」の動作を確認してみた

# 概要

Javaで「キャスト演算子と型変換ルール」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/var/index11.html

# 実装

以下のファイルを作成しました。
```JSample11_1.java
class JSample11_1{
  public static void main(String[] args){
    float f = 10;
    double d = 1234L;

    System.out.println("f=：" + f);
    System.out.println("d=：" + d);
  }
}
```
```JSample11_2.java
class JSample11_2{
  public static void main(String[] args){
    int i1 = 123456789;
    float f1 = i1;
    System.out.println("i1=：" + i1);
    System.out.println("f1=：" + f1);

    long l2 = 1234567890123456789L;
    float f2 = l2;
    double d2 = l2;

    System.out.println("l2=：" + l2);
    System.out.println("f2=：" + f2);
    System.out.println("d2=：" + d2);
  }
}
```
```JSample11_3.java
class JSample11_3{
  public static void main(String[] args){
    double d = 123.0;
    int i = (int)d;
    float f = (float)d;

    System.out.println("d=：" + d);
    System.out.println("i=：" + i);
    System.out.println("f=：" + f);
  }
}
```
```JSample11_4.java
class JSample11_4{
  public static void main(String[] args){
    long l1 = 1234567890123456789L;
    int i1 = (int)l1;
    float f2 = 123.45f;
    int i2 = (int)f2;

    System.out.println("l1=：" + l1);
    System.out.println("i1=：" + i1);
    System.out.println("f2=：" + f2);
    System.out.println("i2=：" + i2);
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample11_1.java
$ java JSample11_1 
f=：10.0
d=：1234.0
$ javac JSample11_2.java
$ java JSample11_2 
i1=：123456789
f1=：1.23456792E8
l2=：1234567890123456789
f2=：1.23456794E18
d2=：1.23456789012345677E18
$ javac JSample11_3.java
$ java JSample11_3 
d=：123.0
i=：123
f=：123.0
$ javac JSample11_4.java
$ java JSample11_4 
l1=：1234567890123456789
i1=：2112454933
f2=：123.45
i2=：123
```

# まとめ

何かの役に立てばと。
Node.jsで書いたSeleniumのコードをマルチデバイス対応させる

# はじめに
普段はとある企業でフロントエンドを担当しています。
たまにバックエンドやインフラもやりますが、今回はテストシステムの構築から始めたのでフロント＆インフラが絡むお話です。

# 背景
社内開発で、リリース前テストは要望の上がったユーザー部門で行ってもらっていましたが、いろいろ対応しなければいけないパターンが出てきたことからテストの自動化を進めていきました。

# 課題
## テストがそもそも負担大
私のいる会社では社内の担当部署で動作チェックを行ってもらい、問題なければリリース・・・というプロセスを踏んでいます（もっと良いフローはあると思う）
もちろん担当部署には他の仕事があるのでテストばかりやっているわけにはいきません。

## 機能・アプリの増加によるテストケース増加
これはテストを網羅的に実施しようとすると永遠に付きまとう問題かと思います。
手作業でテストを行っていたのでなおさら負担は大きいものでした。

## テストでマルチデバイス対応が必要になっていた
iOSのある特定のOSバージョンでしか発生しないバグが発生するなど、ユーザーテストでは網羅に限界のある内容が出てきていました。


# 考えること
## マルチデバイス間でのテストケース共通化
ここの選択肢を誤ると後で書き直しになったり、モバイルテストとブラウザテストを書き分けるという地獄を経験することになるので慎重に選びました。
Androidでのみテストを行うのであればPlaywrightもアリですが、iOSのテストも含まれていため今回は対象外としました。

最終的にSelenium Webdriver+Appiumを選びました。
おそらく無難なのはpython+Selenium+WebDriver辺りですが、私自身pythonを書き慣れていなかったことからNode.jsのselenium-webdriverを採用しました。

selenium-webdriverとは→
https://github.com/SeleniumHQ/selenium/tree/trunk/javascript/node/selenium-webdriver#readme

## デバイス問題（ローカル？クラウド？）
マルチデバイステストを考える上で考えられる選択肢は以下の2つです

1. クラウドサービスの利用：Firebase Test LabやAWS Device Farmなど
2. ローカルで実機を一括管理

2.はセキュリティや安定性の面で現実的ではないと判断。
1.ではいくつかのサービスがありましたが、社内インフラとしてAWSが推奨されていたこともありAWS Device Farmを採用しました。
https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/welcome.html

## テストコードを書く期間
その後の案件状況からおよそ3ヶ月で自動テストシステムの構築・約400ケースのテストコーディングを終わらせる必要がありました。


## 実装したテスト
* E2E→UT,ITは未実装
* 画像回帰テスト(Visual Regression Test)→E2Eの実施中にスクショを撮り、本番環境との差分をReg-CLIでレポート化

# 実装のためにやったこと
* テスト対象のプレビュー環境をAmplify Hostingで用意。CloudFront+WAFでセキュリティ対策
* AWS Device FarmでのAppium利用→testspec.ymlの調整やテストリソースのデプロイ方法など、非常に情報量が少なかった。ある程度までは下記ページを参考にし、Classmethodの方へ質問しながら構築を進めた。
https://docs.aws.amazon.com/ja_jp/devicefarm/latest/developerguide/test-types-appium.html
* テストコーディングはGithub Copilotをフル活用→体感4割くらい採用していたと思う。ローカルで動かして適宜調整。
* ブラウザ側のテストはSelenium Gridを導入。CodeBuild上でコンテナ展開し、Chrome,Edgeのテストを実施
* E2EのアサーションライブラリとしてはレアだがフロントをVue.jsで書いていたこともあり将来ITを書く可能性があったことからVitestを採用。
* テストレポートはHTML+junitを出力させ、パイプラインの結果としてjunitを返却。テスト内容のプレビュー用にHTMLをS3上でホスティング。


# 大変だったこと
## DeviceFarmの情報が古い or 少ない
今回のマイナーな構成にフィットする情報が非常に少なかった。
見つけてもAppium2の情報だったりでCapabilitiesの記法でかなり苦戦した。

## AndroidとiOSでテストコードに若干の調整が必要
恐らくラッパーライブラリを利用しているからだと思われるが、Androidで成功する動作がiOSだと認識しないことが多々あった。注入する環境変数からデバイスを識別させ、動作をコールバックで分岐させた。

# 良かったこと
## マルチデバイステストの実施内容を動画として残せる
DeviceFarmではテストの実施結果を動画として保存してくれます。
スクリーンショットでの差分はReg-CLIに任せ、異常があったら動画をチェックしどこでおかしくなっているのかを後から見返せます。

## テストコードを共通化できた
多少の調整は必要でしたが、環境・デバイス毎にテストコードを書き直さずに済むのは大きかったです。

## 担当部署の負担を大幅に減らせた
手作業で行っていたテストを自動化し、テストレポートの点検と一部チェックをしてもらうだけで済むようになったのでテストの負担を大幅に軽減できました。

## テストコードを書くことで予期せぬ不具合を見つけられた
実際にテストを書いてチェックしている最中「ここ変だな？」というバグを何個か発見することができました。
品質向上という面でもテストを書くのは良さそうです（ITやUTだと更にいけそうだけど書く量が多いので今後検討）


# さいごに
Seleniumなら大人しくpythonで書けば良かったとも途中思いましたが、普段から使っている言語で複雑なテストシステムを構築できたのは良い経験になりました。
今後はDevicefarmの運用やコスト改善を図っていきたいですね。
xcodebuildでx86向けの.appファイルを作成する

[Maestro](https://maestro.mobile.dev/)でUITestを行っている際に.appファイルを作成する必要があったためメモ

※MaestroがARM64のビルドに非対応で、x86ビルドを行った

xcodebuildを使って作成

```
xcodebuild \             
  -workspace WORKSPACE_NAME \
  -scheme SCHEME_NAME \
  -destination 'generic/platform=iOS Simulator' \
  -derivedDataPath ./build \
  clean build
```

`build/Build/Products/Develop-iphonesimulator/(APP_NAME).app`に.appファイルが作成される
MySQL8.0とDockerを使ったレプリケーション

私の環境
Windows11、WSL2、ubuntu24.04です。

docker composeでレプリケーションをしたくていろいろ試した。
できたので載せました。

tree
```
├── db01
│   └── my.cnf
├── db02
│   └── my.cnf
└── docker-compose.yml
```

```docker-compose.yml
version: "3.9"
services:
  db01:
    image: mysql:8.0.33
    ports:
      - 3307:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      TZ: Tokyo/Japan
    volumes:
      - ./db01/my.cnf:/etc/my.cnf
    networks:
      db_net:
        ipv4_address: 192.168.10.11
  db02:
    image: mysql:8.0.33
    ports:
      - 3308:3306
    environment:
      MYSQL_ROOT_PASSWORD: root
      TZ: Tokyo/Japan
    volumes:
      - ./db02/my.cnf:/etc/my.cnf
    networks:
      db_net:
        ipv4_address: 192.168.10.12

networks:
  db_net:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 192.168.10.0/24

```

```/db01/my.cnf
[client]
port=3306
socket=/var/run/mysqld/mysqld.sock

[mysqld]
default_authentication_plugin=mysql_native_password

datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# master用設定
server_id=1001
port=3306

# バイナリログ設定
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_rows_query_log_events=ON
relay_log_recovery=ON

```

```/db02/my.cnf
[client]
port=3306
socket=/var/run/mysqld/mysqld.sock

[mysqld]
default_authentication_plugin=mysql_native_password

datadir=/var/lib/mysql
socket=/var/run/mysqld/mysqld.sock
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

# slave用設定
server_id=1002
port=3306
read_only=ON
report_host=db02

# バイナリログ設定
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_rows_query_log_events=ON
relay_log_recovery=ON

```

```
docker compose up -d
```

マスターのコンテナに入ってMySQLにログインします。
```
docker compose exec db01 bash
mysql -uroot -proot
```

```
mysql>CREATE DATABASE repl_test;
mysql>CREATE USER 'test'@'192.168.10.%' IDENTIFIED BY 'test';
GRANT
  SELECT,
  INSERT,
  UPDATE,
  DELETE,
  CREATE,
  ALTER,
  DROP
ON *.* TO 'test'@'192.168.10.%';
mysql>CREATE USER 'repl'@'192.168.10.12' IDENTIFIED BY 'repl';
mysql>GRANT
  REPLICATION SLAVE
ON *.* TO 'repl'@'192.168.10.12';
```

別のターミナルを開いてスレーブコンテナに入ってMySQLにログインします。
```
docker compose exec db02 bash
mysql -uroot -proot
```

いよいよレプリカ開始です。
```
mysql>CHANGE REPLICATION SOURCE TO
  SOURCE_HOST = '192.168.10.11',
  SOURCE_USER = 'repl',
  SOURCE_PASSWORD = 'repl',
  SOURCE_AUTO_POSITION = 1;
mysql>START REPLICA;
```

下記コマンドで確認
```
mysql>SHOW REPLICA STATUS\G;
```

下2つがYesならOK!!
```
  Replica_IO_Running: Yes
  Replica_SQL_Running: Yes
```

参考
https://qiita.com/igossou/items/9ee11e98c25132e60e1c
ページのリンクをTwitterからXに置換してくれるChrome拡張「twitter2x」を作りました

# 開発経緯
何気なくTwitterで検索履歴から見たいハッシュタグに移動しようと思ったら検索履歴が無くなってました。
どうやら数日前から「twitter.com」にアクセスすると「x.com」にリダイレクトする仕様らしい、そのせいで検索履歴が消えてたみたい。

https://news.yahoo.co.jp/expert/articles/284ccafcf6efe617fd91658af7297388cca7536b

このYahooニュースを見てたんですが、「もしリダイレクトされなくなったらリンク切れが続出する事態になるんじゃね？」って思っちゃったんですよね。

# twitter2x
という事で、ページのリンクをTwitterからXに置換してくれるChromeの拡張機能を作りました。

https://github.com/miracle2568/twitter2x

```json:manifest.json
{
  "name": "twitter2x",
  "description": "Webページのリンクを「twitter.com」から「x.com」に置換します。",
  "version": "1.0.0",
  "manifest_version": 3,
  "content_scripts": [{
      "matches": ["<all_urls>"],
      "all_frames": true,
      "js":      ["js/loader.js"],
      "run_at": "document_start"
  }],
  "web_accessible_resources": [{
      "resources": ["js/content.js",
                    "js/program.js"],
      "matches":   ["<all_urls>"]
  }]
}

```

```javascript:js/loader.js
(async() => {
    const src = chrome.runtime.getURL("js/content.js");
    const contentMain = await import(src);
})()
```

```javascript:js/content.js
import { ProgramClass } from "./program.js";

function main(){
    let target = document.body;
    let config = { childList: true, subtree: true };

    let program = new ProgramClass();

    let observer = new MutationObserver((mutations) => {
        mutations.forEach((mutation) => {
            program.run(mutation.target);
        });
    });

    observer.observe(target, config);
}

if(document.readyState === "loading"){
    document.addEventListener("DOMContentLoaded", function(){
        main();
    });
}else{
    main();
}
```

```javascript:js/program.js
export class ProgramClass {
    constructor() {
        
    }

    run(target) {
        for(const element of target.querySelectorAll('a[href*="twitter.com"]:not([data-checked="true"])')){
            element.href = element.href.replace("twitter.com", "x.com");
            element.dataset.checked = "true";
        }
    }
}
```

やってる事は単純で、MutationObserverでページを監視して変化があったらaタグのhrefに「twitter.com」という文字列がある要素を検索して「x.com」に置換してるだけです。

# 参考資料
https://qiita.com/twrcd1227/items/182de980e821336756f7

https://sologaku.com/make-website/queryselectorall-get-href-element-using-regex-attribute-selector/
エディタ環境で文字列からクラスを取得する(UE5版)

## UE5でも文字列からクラスを取得したい 
エディタ上でなにかやる時に、文字列からクラスを取りたいシチュエーションってありますよね。
しかしながら、UE5では、以前投稿した[これ](https://qiita.com/t-okugawa/items/d8f43f6fb2a3f5914b4d)はコンパイルが通りません。
なぜでしょうか、我々の愛したANY_PACKAGEが死んだからです。
## 対応版
ロード済みを探す→リダイレクタを探す→パッケージロードを試す→_CをつけてBPの可能性を探る。
と、いう流れは前回と同じです。

ANY_PACKAGEを渡していたFindObjectをTryFindTypeSlowとFindFirstObjectSafeに置き換えています。

``` 
UClass* FindClassByName(const FString& name) {
	auto getClass = [&](const auto& inName) {
		// ロード済みを探す. 
		UClass* ret = UClass::TryFindTypeSlow<UClass>(inName);
		if (ret == nullptr) {
			// リダイレクタ.
			UObjectRedirector* redirector = FindFirstObjectSafe<UObjectRedirector>(*inName);
			if (redirector != nullptr) {
				ret = Cast<UClass>(redirector->DestinationObject);
			}
			if (ret == nullptr) {
				// パッケージロード.   
				if (UPackage* pkg = LoadPackage(nullptr, *inName, LOAD_Verify | LOAD_NoWarn)) {
					pkg->FullyLoad();
					ret = FindObject<UClass>(pkg, *inName);
				}
			}
		}
		return ret;
	};
 
	UClass* result = getClass(name);
	if (result == nullptr) {
 		// BPの可能性.
		result = getClass(name + FString(TEXT("_C")));
	}
	return result;
}
```

## ※注意
コンパイルすら出来なかった物を通るようにはしましたが、最適な方法なのかどうかは詳しく検証できていません。
もし、何かあればご指摘いただければと思います。
プロジェクト管理におけるプロセスドメインの概要

プロジェクト管理では、プロセスドメインが非常に重要です。プロセスドメインは、プロジェクトの計画、実行、監視・コントロール、終了のすべてのステップを含んでおり、プロジェクトの成功を支える基本的なフレームワークです。

### プロセスドメインとは？

プロセスドメインとは、プロジェクトを計画し、実行し、その進捗を監視・コントロールし、最終的に終了する一連の活動を指します。これらの活動は、プロジェクトの成功に不可欠です。

### プロセスドメインの主要なプロセスグループ

プロセスドメインには、以下の主要なプロセスグループがあります：

1. **計画（Planning）**
2. **実行（Executing）**
3. **監視とコントロール（Monitoring and Controlling）**
4. **終了（Closing）**

### 計画（Planning）

計画プロセスは、プロジェクトの全体像を描くステップです。このステップでは、プロジェクトのスコープ、スケジュール、コストを設定し、リソースを管理します。

#### 主要な活動

- **スコープ定義**：プロジェクトの目的と成果物を明確にします。
  - **例**: 新製品の開発プロジェクトでは、具体的な製品仕様を定義します。
- **スケジュール作成**：タスクを時間軸に沿って配置し、完了期限を設定します。
  - **例**: タスク一覧を作成し、ガントチャートで視覚化します。
- **リソース管理**：必要な人材、設備、予算を特定し、計画に組み込みます。
  - **例**: 各タスクに必要なリソースを割り当てます。

### 実行（Executing）

実行プロセスは、計画に基づいてプロジェクトを進め、成果物を作成するステップです。このステップでは、チームを管理し、ステークホルダーとのコミュニケーションを維持します。

#### 主要な活動

- **チームのマネジメント**：チームメンバーを効果的にリードし、タスクを遂行します。
  - **例**: チームミーティングを定期的に開催し、進捗を確認します。
- **成果物の作成**：計画に沿って、プロジェクトの成果物を作成します。
  - **例**: プログラムのコードを書き、テストを行います。
- **ステークホルダーとのコミュニケーション**：進捗状況を報告し、フィードバックを収集します。
  - **例**: クライアントに定期的な進捗報告を行います。

### 監視とコントロール（Monitoring and Controlling）

監視とコントロールプロセスは、プロジェクトの進捗を監視し、必要に応じて調整するステップです。このステップでは、進捗レポートの作成、リスク管理、変更管理が含まれます。

#### 主要な活動

- **進捗レポートの作成**：プロジェクトの現状を把握し、報告します。
  - **例**: 週次報告書を作成し、チームと共有します。
- **リスク管理**：潜在的なリスクを特定し、対策を講じます。
  - **例**: リスクマトリックスを使用してリスクを評価し、対策を策定します。
- **変更管理**：計画の変更が必要な場合、適切な手続きを踏んで調整します。
  - **例**: 変更要求を評価し、承認プロセスを経て実施します。

### 終了（Closing）

終了プロセスは、プロジェクトの完了を確認し、成果物を引き渡すステップです。このステップでは、全てのタスクが完了し、プロジェクトの成功を確認します。

#### 主要な活動

- **成果物の引き渡し**：クライアントやステークホルダーに最終成果物を引き渡します。
  - **例**: 完成したシステムをクライアントにデモし、引き渡します。
- **プロジェクトの評価**：プロジェクト全体を振り返り、成功点と改善点を特定します。
  - **例**: プロジェクト終了後に振り返り会議を開催します。
- **終了報告**：プロジェクトの正式な終了を報告し、全ての文書を整理します。
  - **例**: 終了報告書を作成し、関係者に送付します。
【FCM legacy -> HTTP v1 移行】Instance ID Server APIは2024/06/20以降も使える

FCMのlegacy APIからv1 APIに移行する期限が2024/06/20と、あと１ヶ月程に迫っています。

https://firebase.google.com/docs/cloud-messaging/migrate-v1?hl=ja

私は一通り対応し切った”つもり”でしたが、もう一度Googleから来たメールを見直すとTopic登録用に使っていたInstance ID Server API（iid)も対象となっており、無駄に焦ったので備忘録です。
```
Instance ID Server API for Web | No SDK related to this API. | Latest FCM JS SDK.
```

↓topicにTokenを登録するため、これらのAPIを使っていた
```
 https://iid.googleapis.com/iid/v1:batchAdd
 https://iid.googleapis.com/iid/v1:batchRemove
```
https://developers.google.com/instance-id/reference/server?hl=ja
(The Instance ID API is deprecated. って上のバーに出てるんだけど。。)

## 結論
結論から申し上げると、2024/06/21以降もbatchAddを始めとしたiid APIは利用できます。

## 詳細
### ソースはどこか
<b>英語版</b>のQ&Aにあります
https://firebase.google.com/support/faq

(抜粋)
| API Name | API Endpoint | Impact on users | Action Required |
| ---- | ---- | ---- | ---- |
| Instance ID server APIs | ttps://iid.googleapis.com/v1/web/iid | Requests to the endpoint will start failing after 6/21/2024. | Use an OAuth 2.0 access token derived from a service account. |
| Instance ID server APIs | ttps://iid.googleapis.com/iid/* | 	The endpoints will continue to work but they won’t support authentication using static server keys after 6/21/2024. | Use an OAuth 2.0 access token derived from a service account. |

これ、日本語版のQ&Aにはありません。これで私は３時間溶かしました。

### 注意点
記載にもあるとおり、OAuth 2.0を使って認証をしなくてはなりません。
(serverKeyによる認証が弾かれるようになります。)

## 余談
### 自分の移行対応
#### 移行前
PHP内でPush通知を実装
 +  送信はlegacyAPIへcurlリクエスト(「トークン1000件」＋「メッセージ」を対象者分ループ)

#### 移行後
同じくPHP内でPush通知を実装

+  topic登録
    +  v1 APIはtokenのグループ化(デバイスグループ/topic登録)が出来ないので、iidAPIを利用
        ```
        注意: デバイス グループ メッセージングを使用するアプリでは、引き続き以前の API を使用してデバイス グループの管理（作成、更新など）を行う必要があります。HTTP v1 はデバイス グループへのメッセージ送信には対応していますが、管理はサポートしていません。        
        ```
        1000件ごとに対象者のTokenをv1:batchAddで追加していく。
        この辺の実装方法はググるとすぐ出てくるので割愛いたします。
        
+  push送信
    +  v1 APIを利用
    google clientをcomposer installして導入
    client越しにAuth通して、得られたhttpClientにTopicやPush通知内容を指定してFCM側にリクエスト
    
    参考にさせていただいたエキサイト株式会社様の記事(末尾にリンク貼りました)が参考になったというかほぼそのままで実装できました。


### 参考にさせていただいたページ
https://tech.excite.co.jp/entry/2024/03/19/112945

### 最後に
エンジニアたるもの日本語ドキュメントを信用するのはやめるべし(自戒)
【Zod】バリデーション後にデータを変換する方法

バリデーション後にデータを変換するには`transform`を使用します。
以下に使用例を示します。

## 数値を文字列に変換

```js
import { z } from 'zod';

// 数値から文字列への変換
const numberToString = z.number().transform(num => num.toString());

// バリデーションと変換
const result = numberToString.parse(123); // "123"
```

## オブジェクトのプロパティを変換

```js
import { z } from 'zod';

// オブジェクトスキーマの定義
const originalSchema = z.object({
  name: z.string(),
  age: z.number(),
});

// ageプロパティを文字列に変換する新しいスキーマ
const transformedSchema = originalSchema.transform(obj => ({
  ...obj,
  age: obj.age.toString(),
}));

// バリデーションと変換
const result = transformedSchema.parse({ name: 'John', age: 30 }); // { name: 'John', age: '30' }
```

## オブジェクトのキーをキャメルケースに変換

```ts
import { z } from 'zod';

function toCamelCase(str: string): string {
  return str.replace(/([-_][a-z])/g, group => group.toUpperCase()
                                              .replace('-', '')
                                              .replace('_', ''));
}

const originalSchema = z.object({
  first_name: z.string(),
  last_name: z.string(),
});

const transformedSchema = originalSchema.transform(obj => {
  const newObj: any = {};
  for (const key in obj) {
    newObj[toCamelCase(key)] = obj[key];
  }
  return newObj;
});

const result = transformedSchema.parse({ first_name: 'John', last_name: 'Doe' });
// result: { firstName: 'John', lastName: 'Doe' }
```
SUUMOにて割安賃料物件を見つけよう_アプリ作成編

![suumo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/abb34c4e-889e-71ee-7a36-257fedaa8146.png)
 # 概要
SUUMOにて割安な賃料物件を探しました。

####  調査の流れ
調査は以下の3つに分割しました。
1. [データ基盤構築編](https://qiita.com/delta_K/items/9b8b09d44e352c728f90)
2. [モデル作成編](https://qiita.com/delta_K/items/ed61b64048cfb86083b5)
3. [アプリ作成編](https://qiita.com/delta_K/items/2579d99966d3d7bc7df2)(今回の記事)

# アプリ作成編
以下のアーキテクチャ図の構成でモデルの挙動の可視化をするアプリを作成しました。

![スクリーンショット 2024-06-16 002835.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/2d176ad7-34f7-9aaa-80a5-21fd9ee7b546.png)


Lambda上では指定したidの賃料データをスクレピングし、賃料予測を実行している。

アプリは[こちら](https://dev.d2wbaf6wief33m.amplifyapp.com/)から使用できます。

#### アプリの使い方


![スクリーンショット 2024-05-20 232854.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/f6c99eef-fed6-057e-b3e2-47fd52e4ee0a.png)



1. 北千住、三軒茶屋、世田谷、梅島、久米川、府中、調布、仙川 から一つの駅を選ぶ。


2.  物件コードを入力する。下記画像であればbc_100382163633が物件コードである。(URLの部分)

![スクリーンショット 2024-05-20 233406.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/007d7818-60cd-e195-cc16-7c7049c62782.png)

3.　予測開始ボタンを押す。

![summo_prediction_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/487ef31b-a3f2-68d9-4cc9-e5e1d1d3a8a4.png)
![summo_prediction_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/d341855a-7006-8603-fdc4-c7438b7e9ce7.png)


- 建物と部屋の基本情報が表示されてその下に**ヒストグラムによる部屋の平米単価の相場の可視化**と**SHAPによるモデルの予測根拠を可視化**をする。


- **価格偏差値**の式については、賃料が安いほど高い偏差値としたいので、
**50 - (対象のlog_平米単価 - log_平米単価の平均)/log_平米単価の標準偏差 * 10**　とした。
【UiPath】xaml一式をzip化する時はWindowsの標準機能を使わないほうがよい

## 事象
.xamlファイルを含むプロジェクトの関連ファイル一式を、Windowsの標準機能（送る→圧縮フォルダー）を使って圧縮（zip化）します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/6973d9ad-dfc9-6af0-1f1a-9e83acab26f6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/88803b82-ab11-b2d7-2d60-766659164d99.png)

問題なく圧縮できたように見えますが…。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/3b6ac03c-21f6-4b2b-5442-150bd6540672.png)

zipの中身を確認してみると、.object等の一部のフォルダが消えています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/2af6b820-7844-34be-9565-e73d83999577.png)

## 原因
これはWindows側に起因する現象で、**Windowsの標準機能で圧縮する際、ドットから始まるフォルダが複数ある場合、2個目以降のフォルダがzip化ファイルに格納されない**という仕様によるものになります。
Lhaplusや7-Zip等の別の圧縮ソフトでは問題なく全てのフォルダをzipに格納できますので、そちらの方法を使いましょう。

## 参考
https://qiita.com/yuji38kwmt/items/aa398723618a03553eeb
viteから@nuxt/test-utilsに移行するときに注意すること

# はじめに
この記事は、`vite`から`@nuxt/test-utils`に移行するとき躓いた点をメモしたものです。

# viteを使用していた時のconfigのまま@nuxt/test-utils使うとエラーになる
nuxtプロジェクトで自動テスト(vitest)を使用しているとランタイム状態でのテストを実施したい時が出てくると思います。
例えば、フロント側のボタンが押されたらuseFetchでDBにアクセスし対象のデータを取得し表示するなど。
そのような場合`@nuxt/test-utils`を使うと便利です。
下記サンプルコードをvitestで動かすと`registerEndpoint`がapi serverの代わりになるのですがエラーになります。

**エラー**
`SyntaxError: At least one <template> or <script> is required in a single file component.`

```vite.config.ts
// import { defineConfig } from "vite";
import { defineVitestConfig } from '@nuxt/test-utils/config'

export default defineVitestConfig({
    plugins: [
        Vue(),
        vuetify()
    ],
})
```

```index.vue
<template>
    <v-btn @click="add()" id="addButton">ユーザー登録</v-btn>

    <v-alert
        v-model="userAddAlert"
        :title="alertUserAddText"
        id="addUserAlert"
    >
    </v-alert>
</template>

<script lang="ts" setup>
    import { ref } from "vue";

    // ユーザー追加アラート
    const userAddAlert = ref(true);
    let alertUserAddText = ref("ユーザー登録結果が表示されます");

    const add = async () : Promise<any> => {
        try {
            const response : object = await useFetch("/api/addUser", {
                method: 'POST',
                body: {
                    // なにか
                },
                headers: {
                    Accept: 'application/json'
                }
            })

            // responseの処理
            alertUserAddText.value = response.data.value.message;
        } 
        catch (err) {
            console.log("ユーザー登録失敗");
        }
    }
</script>
```

```typescript
import { describe, test, expect } from "vitest";
import index  from "~/components/AddUser.vue"
import { mount } from "@vue/test-utils";

describe("index.vue add user success", () => {
    registerEndpoint("/api/addUser",{
        handler: () => ({
            message: "ユーザー登録完了",
        }),
        method: "POST"
    });
  
    test("ユーザー追加処理のフロントテスト", async () => {
        const wrapper = mount(index);
        // クリックしてもエラーになる    
        wrapper.findComponent('#addButton').trigger('click');
    });
});
```



# @nuxt/test-utilsの時はpluginsはいらない
調べてもわからなかったのでリポジトリにissueなげてみました。
返信がきて`@nuxt/test-utilsの時はpluginsはいらない`そうです。
ランタイム状態のテスト環境になるのでpluginを勝手に読み込んでくれるみたいですね。
エラーの原因はpluginを2重に読み込んでいたことが影響したのだと思います。

```vite.config.ts
// import { defineConfig } from "vite";
import { defineVitestConfig } from '@nuxt/test-utils/config'

export default defineVitestConfig({
    plugins: [
        // なにもかかない
    ],
})
```

# 参考文献
1. [@nuxt/test-utils issue](https://github.com/nuxt/test-utils/issues/842)
長いシェルコマンドを見やすくするためのバックスラッシュ(\)使用術　(Tips)

## はじめに
コマンドラインを使用する際、時として非常に長いコマンドを扱う必要があります。これらのコマンドは、一行に収めると読みにくくなることがあります。この問題を解決するためのシンプルながら強力なテクニックが、バックスラッシュ（\）を使用したコマンドの改行です。この投稿では、バックスラッシュを使ってシェルコマンドを見やすくする方法を説明します。

## バックスラッシュの使い方
バックスラッシュは、シェルに次の行も現在のコマンドの一部として解釈させる役割を果たします。これにより、コマンドを複数行にわたって整理し、全体的な可読性を向上させることができます。やり方は、バックスラッシュの後にEnterキーを押すことで改行できます。

**例**:
```bash
# 複数のパッケージをインストールするコマンド
sudo apt update && sudo apt install -y \
  git \
  curl \
  vim \
  tree
```

## 中止する
途中で中止するための方法は以下のいずれかです。

#### a. Ctrl + C
ターミナルで実行中のコマンドを強制的に中止するために、`Ctrl + C` を押します。これにより、現在のコマンドの実行が停止します。

#### b. Ctrl + D
ターミナルセッションを終了する場合には、`Ctrl + D` を押します。これにより、ターミナルセッション自体が終了します。

#### c. exit コマンド
セッションを終了するために、`exit` コマンドを入力してEnterキーを押します。これもターミナルセッションを終了します。

(`Ctrl + C` と `Ctrl + D` の違いがあまりよく分かっていません)

## 注意点
ただし、すべてのシナリオでバックスラッシュが機能するわけではありません。いくつかの注意点を挙げます。

#### シングルクォート内：
ダブルクォートと違ってシングルクォート内ではバックスラッシュも単なる文字として扱われます。

```bash
# シングルクォート内でのバックスラッシュ使用例----------
echo 'This is a wrong way to use a backslash \
in single quotes'

# Expected output:
# This is a wrong way to use a backslash \
# in single quotes

# ダブルクォート内でのバックスラッシュ使用例----------
echo "This is a wrong way to use a backslash \
in single quotes"

# Expected output:
# This is a wrong way to use a backslash in single quote
```

#### コマンドの区切り：
複数のコマンドを `&&` などで区切って実行する場合、それぞれのコマンドの終了点でバックスラッシュを使用するとエラーになる場合があるそうです。

## 終わりに
探した際に意外と記事が見つからなかったので、投稿してみました。
長いコマンドを扱う際にバックスラッシュを使用することで、シェルスクリプトの見た目が多少良くなります。是非使ってみて下さい。
架空レストランHPの制作過程 Part1 どんなん作ろかな編

## 背景
私はフロントエンドエンジニアとして数年活動しています。しかし、セキュリティ上の理由からほとんど実績を公開することができません。

これじゃスキルをアピールできねぇ！！

ということで、自分のスキルを表現するために、ポートフォリオ掲載用のWebサイトを作成しました。

### 制作したサイト

https://la-festa.vercel.app/

本記事では、このWebサイトの制作過程を詳細に紹介していきます。

## 制作の目的

このWebサイト制作を通して、以下のスキルを証明することを目標としました。

* Figmaで最新機能を活用したWebサイトプロトタイプの作成
* リサーチ力
* インタラクティブな機能を持つWebサイトの制作
* Reactを用いた運用しやすいWebサイトの構築
* UI/UX設計
* AIなどの新技術の柔軟な活用
* 分析に基づいた情報設計

## 1. 題材決め

まず、どのようなWebサイトを作成するかを検討しました。リサーチがしやすく、多くの人にとって身近な題材がいいと思ったので、飲食店のWebサイトを制作することにしました。

実在する飲食店のWebサイトを勝手に作成することはできないため、架空のイタリアンレストランを設定しました。

### 飲食店概要
* 中価格帯
* 都内に3店舗展開
* テナント出店
* ランチはディナーよりもリーズナブル
* クレジットカード・電子決済対応
* サステナブルな取り組みとして、毎週水曜日は植物性由来の料理をメインに提供。フードロス削減のため、食べ残しの持ち帰り推奨
* 豊富な種類のワイン
* 人気メニューは自家製窯焼きピザとミネストローネ

そもそも個人経営の飲食店にとって、Webサイトは必須ではないと思っています。
現在ではSNSなどでも集客が可能であり、私も実際に飲食店を探すのにわざわざWebサイトまで見に行くことはほとんどありません。

じゃあどういう場合だと、Webサイトが必要なのかというと、規模が大きくて、デジタルチャネル運用にリソースを割けるほど余裕があるところになるんじゃないかと思います。
そのため、複数店舗展開しているという設定にしました。

サステナブルなブランディングについては、ちょうど仕事でサステナブル関係にちょっと取り組んでいたので、その経験を活かして、エッセンスとして取り入れました。

## 2. Webサイトに必要な機能・コンテンツ洗い出し

* 店舗概要（営業時間、定休日、住所、決済手段、席数、問い合わせ先）
* お店のコンセプト、こだわり
* フード/ドリンクメニュー
* 最新情報
* SNSリンク
* 地図
* 求人情報
* 問い合わせフォーム
* 予約フォーム

これらの機能・コンテンツは、上から順に掲載必須度が高いものです。
今回は時間の関係上、TOPページしか作成できなさそうだったので、TOPページで可能な限り情報を収めるように工夫しました。

## まとめ

今回は、制作過程の序盤を紹介しました。

次回は、情報設計前の市場リサーチについて詳しく解説します。

次の記事

https://qiita.com/yamashee/items/f055ade5f1d5258143c4
UE勉強日記1 Blueprintのdefualt値の注意点

Blueprintのdefualt変数を変更しても、引用先の値は変更されない

例えば、下記の画像ではW_MoveをUI_PanからUI_Knifeに変更した。
変更前にこのBlueprintを引用する箇所のW_MoveはUI_Panのまま、変更されない。
![スクリーンショット 2024-05-20 231700.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3574567/f5851147-923e-1d56-d70e-5b00938a5221.png)
undefinedとNaNとfind関数

# undefinedとNaNに遭遇

課題を進めていると、undefinedとNaNに遭遇。。。
Javascript学習初心者の私には、ここから疑問がはじまる（笑）


* そもそもdefinedとNaNってナニ？？
* 対処法がわからない。


そこで、これらの意味を調べてみることに、、、


# undefinedとNaNとは？

<dl>
<dt>undefined(未定義)</dt> <dd> 定義しているに対して、値が見つからない時にでる特殊な値</dd>
<dt>NaN(Not a numberの略)</dt> <dd>本来は数値であるべき値が、数値として解釈できないときにでる特殊な値

</dl>


# どんな時にundefindとNaNに出会う？

調べてみると、以下のような事例が挙げられました。

* #### 変数が定義されてはいるが、値が代入されていない場合。

* #### 存在しない変数を参照した場合。

* #### 数値として解釈できない文字列を数値として使用した場合。などなど

 

私の場合、、、
![スクリーンショット 2024-05-14 9.36.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788430/b28c4691-203a-a42f-4f23-da6e3cb13d56.png)

定義した関数に対して、値が代入されてない & 数値として解釈されてない。
本来、上記の画像のような表記になるはずが
`９００円が１点`と`小計`の部分が値に代入されてなく、、、
結果として以下のように表示された。
`undefinedがNaN円`
`undefinedがNaN円`
`小計`
`NaN`

商品を追加するごとに上記のような表示が繰り返し行われ、頭抱えた（笑）

## 解決策

そこで、スクリプトの問題点がどこか見直すことに！でも、どうやって探す？
 
### `debugger` の登場!!
※debuggerとは、スクリプト内のエラーを見つけ、修正するコードのこと。
 [debuggerの使い方]

①`debugger`を使用しコードの実行を一時停止させ、コードの状態の詳細を把握する。
②ブラウザのコンソールで、`consol.log(product)`など入力。値の中身を確認する。

# find関数

debuggerを使いproductの値を設定してなかったことが判明。
`find関数`(指定された文字列が、左から何番目にあるかを探すことができ、その番号を返す関数）を使用。

まずは、`paresInt`を使って、変数に入れたものを数値に変換。（重要）　ー①
products変数に格納されているデータの中から一つずつ取得し、商品を見つけ出す。ー②
"見つけ出した商品"（element) と "とってきた値"（id）を比較演算子で、選択した個数（value）と比較する。
同じ値だったら、それを値として返す。

![スクリーンショット 2024-05-15 7.35.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788430/56956775-4dbe-d7fa-7470-9f4d460d6330.png)



これで合っているのか不安なところはある。。。


一旦はこれで解決しましたが、もっといい方法があれば教えていただけると助かります！
[初心者向け]テスト駆動開発とテストファーストの関係

[徹底攻略 JSTQB Foundation教科書&問題集 シラバス2018対応](https://www.amazon.co.jp/%E5%BE%B9%E5%BA%95%E6%94%BB%E7%95%A5-JSTQB-Foundation%E6%95%99%E7%A7%91%E6%9B%B8-%E5%95%8F%E9%A1%8C%E9%9B%86-%E3%82%B7%E3%83%A9%E3%83%90%E3%82%B92018%E5%AF%BE%E5%BF%9C/dp/4295017671/ref=asc_df_4295017671/?tag=jpgo-22&linkCode=df0&hvadid=654833321247&hvpos=&hvnetw=g&hvrand=7317531869461544354&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009293&hvtargid=pla-2199686852302&psc=1&mcid=140f9d5d8ea8321d9cdbe1b981b50a4c&th=1&psc=1)を勉強しているので、自分のメモとしてまとめています。
今回はコラムです。

# テストファーストとは
先にテストコードを記述してからアプリケーションを記述するという方法論のことを、テストファーストという。

アプリケーションコードがイテレーティブ開発で複雑になった場合、かなり複雑な処理だったとしても、最後に最初に作っていたテストコードを毎回徹自動テストを行うことができる。
そのため、ミスやデグレをすぐに検知できる。

# テスト駆動開発（TDD）
テストファーストという方法論を具体的な開発技法にしたもの。

**まずレッド（テスト失敗）となるコードを書く**
↓
**グリーン（テスト成功）となるコードを書く**
↓
**リファクタリングする（コードをきれいにする）**
というサイクルで記述する。

# 感想
個人的には、仕様がコロコロ変わってしまうようなフェーズにあるプロダクトの場合はあまり向いていないのかなーとは思いました。ちょっとなれるのも時間がかかりそう。
ただ、テストは「この機能は何を達成することを目的とするか」を考えながら作るものだと思うので、出力数値が変わったとしてもテストロジックがめちゃめちゃ変わることはないのかもしれないと考えると、TDDは有効な手段なのかもですね。
【MySQL】Dockerコンテナ内のMySQLにCSVデータをインポートする【Docker】

# 概要
普段MySQLWorkbenchを使用しているのですが、チーム内でツールを統一していないこともあり、いただいたdumpデータがcsv形式だったときのメモです。
Workbenchからもデータはインポートできますが、レコード数が多くなってくると4時間以上かかりそうなくらい遅いので、コマンドラインからインポート作業を行なうことにしました。

:::note info
以下手順のコマンドに記述されている{}は、可変部の目印として使用しているため削除して実行してください
:::
# 手順1(Dockerコンテナ内へのCSVのコピー)
:::note info
こちらの手順はDockerコンテナ外にファイルがあることを前提としています。
Webサーバーコンテナ内にファイルが配置されており、DBコンテナとの通信ができる場合は実行不要です。
:::
コンテナ内にコピーするファイル名は自由に指定できます
（実際はローカルのファイル名をそのまま使用することが多い）
```
docker cp {コピーしたいファイルのパス}| -{container_id}:{ファイルを置きたいパス+任意のファイル名}
```
下記メッセージのみが表示されていれば成功です！
```
Successfully copied hogeMB to {container_id}:{ファイルを置きたいパス+任意のファイル名}
```

# 手順2(MySQLの操作)
Dockerを使用している場合、まずはコンテナに入る必要があります。
```
docker exec -it {container_id} bash
```
上記コマンドを使用するか、DockerDesktopを使用していれば該当コンテナのExecから下記手順を実施でOK
```
mysql -u root -p --local_infile=1
```
パスワードを求められると思うので、設定されているものを入力してください。
MySQLにログインしたら↓を実行
```
select @@local_infile;
```
この時、@@local_infileの設定が0の場合、1に設定してあげる必要があります。
```
set persist local_infile = 1;
```

# 手順3(CSVインポート)
コマンド内のヘッダー削除などはCSVデータに応じてセットしてあげてください。
```
load data local infile '{コンテナにコピーしたファイルのパス}' into table {schema.table_name} 
fields terminated by ',' //データの区切り文字
optionally enclosed by '"'  
lines terminated by '\n' //改行
ignore 1 lines; // ヘッダーがある場合は削除（なければこれは不要）
```
テーブルを確認して正常にデータが入っていれば成功です🙌

# 最後に
間違いがありましたらご指摘いただけますと幸いです！
Sが整礎ならば、Sが弱CR性を持つならば、SがCR性を持つことの証明

# 目次
[1.定理のステートメント](#1-定理のステートメント)
[2.証明](#2-証明)

# 1.定理のステートメント
まずCR性と弱CR性について述べる.

##記号の準備
集合S上で定義された二項関係->に対して、s0 -> s1 - > s2 ... -> sn (n >= 0, s0,s1,s2,...,sn∈S)なるとき、s0 ->> snと定義する. 我々は順序集合(S, <-)を考える.

##CR性
各s,s1,s2∈Sについて、s ->> s1, s ->> s2ならば, s'∈S かつ s1 ->> s' かつ s2 ->> s'なるs'があるとき, SはCR性を持つという.

##弱CR性
各s,s1,s2∈Sについて、s -> s1, s -> s2ならば, s'∈S かつ s1 ->> s' かつ s2 ->> s'なるs'があるとき, Sは弱CR性を持つという.

##定理
定理 : 集合Sについて, S上の二項関係 -> に関する無限減少列s0 -> s1 -> s2 -> ...が存在しないとき, Sが弱CR性を持つならば, SはCR性を持つ.

# 2.証明
//とりまお絵描きして、帰納法回せば行けそうな気がする.
 s0 ->> s1, s0 ->> s2, s0,s1,s2∈Sを仮定する。
IH : すべてのp <- s0なるp∈Sについて, すべてのs1,s2∈Sについて, p ->> s1 かつ p ->> s2 ならば, s1 ->> s' かつ s2 ->> s' かつ s'∈S なるs'がある.

 s0 ->> s1, s0 ->> s2, s0,s1∈Sを仮定する.もしs1 = s0 または s2 = s0 ならば, s'としてs2あるいはs1をとればよい.
// s1 = s0 ->> s2 ->> s2 あるいは s2 = s0 ->> s1 ->> s1

 これからs0 = s1でなく, s2 = s0でないとする.
s0 -> t1 ... -> s1, s0 -> t2 ... -> s2なるt1,t2∈Sがあるとする.弱CR性からt1 ->> t, t2 ->> tなるt∈Sがある. t1 <- s0 から, IH より, s1 ->> u, t ->>u なるu∈Sがある. t2 ->> u かつ　t2 ->> s2である. t2 <- s0 と IH から, u ->> v, s2 ->> v なるv∈Sがある。よって s1 ->> v, s2 ->> v なるvを我々は得た. s0 ->> s1 と s0 ->> s2 から, s0 ->> s1 ならば s0 ->> s2 ならば s1 ->> v, s2 ->> v なるvがある. IH から, 我々は 定理 を得た.

# 3.あとがき
 おじさんはihの矢印をひっくり返しておかしなことをしていました。順序に注意して。あと数学的帰納法をすると健康になれる気がしますね。私はこの定理を近代科学社の計算論で知りました。たしか演習問題でしたね。この定理はnewman's lemmaと言うようです。
Splunk - ソースタイプの一覧を取得したい

## 検証環境
Splunk Enterprise 9.2.1

## はじめに
Splunkで今使ってるソースタイプ一覧をSPLで取得してみた話。

## SPL
### [1] metadata
```SPL:SPL
| metadata type=sourcetypes index=*
```
![スクリーンショット 2024-05-20 22.51.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310888/d77a2ae9-3727-86e9-99ad-04716978fb19.png)

:::note info
metadataコマンドの使い方はSearch Referenceを参照
https://docs.splunk.com/Documentation/Splunk/latest/SearchReference/Metadata
:::

### [2] tstats
```SPL:SPL
| tstats count where index=* by sourcetype
```
![スクリーンショット 2024-05-20 22.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3310888/e1969384-9313-ab70-b735-d641c6e45f5c.png)

## 終わりに
metadataコマンドはソースタイプだけでなく、ソース、ホストのリストも表示する事が可能で便利。
FileZillaで「Too Many Authentication Failures」が出るときの対処方法

# はじめに

[FileZilla](https://filezilla-project.org/)で、「Too Many Authentiation Failures」でSSH接続できない場合の対象方法。


# 動作確認環境
* Ubuntu 20.04

# 方法

起動時に、環境変数「SSH_AUTH_SOCK」をnullに設定する。


```bash
SSH_AUTH_SOCK=null filezilla
```

# 参考

https://blog.programster.org/filezilla-fix-sftp-protocol-connection-error
デノイジングには過去方向のデータ

ウェーブレット変換で高周波成分を除去して特徴量を作るって論文があったけど、リアルタイムやスライディングウィンドウでは全く機能しなくて、要はリークじゃないかと。

ホルトウィンタース法やカルマンフィルタだと、確かに後方（過去方向）のデータにしか依存しないみたいだ。
新しいデータが追加されても、過去の解釈が変わらない様子をプロットしてみた。
良く分からんけど。

![fig.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303759/7a59a696-7d5a-87b3-890a-a24ea6b3a9d7.png)


```python
import numpy as np
import matplotlib.pyplot as plt
from statsmodels.tsa.holtwinters import ExponentialSmoothing
from pykalman import KalmanFilter

np.random.seed(42)
steps = 84
time = np.linspace(0, 7, steps)
noise = np.random.randn(steps)
values = np.cumsum(noise)  

# データを正の範囲にシフト
values += abs(values.min()) + 1

# デノイジングを行う範囲
ranges = [
    (0, steps - 24),
    (12, steps - 12),
    (24, steps - 0),
]

plt.figure(figsize=(12, 10))

# ホルトウィンタース法
plt.subplot(2, 1, 1)
plt.plot(time, values, 'o-', label='Original Data', alpha=0.5)

for start, end in ranges:
    sliced_values = values[start:end]
    sliced_time = time[start:end]
    
    model = ExponentialSmoothing(sliced_values, trend='mul', seasonal=None)
    fit = model.fit(smoothing_level=0.2, smoothing_trend=0.2)
    
    trend = fit.level * fit.trend
    
    plt.plot(sliced_time, trend, linestyle='--', label=f'Trend ({start} to {end})')

plt.legend()
plt.title('Denoising using Holt-Winters Method (Multiplicative)')
plt.xlabel('Time')
plt.ylabel('Signal')

# カルマンフィルタの設定
kf = KalmanFilter(
    transition_matrices=[1],
    observation_matrices=[1],
    initial_state_mean=values[0],
    initial_state_covariance=1,
    observation_covariance= 1,
    transition_covariance=0.1
)

plt.subplot(2, 1, 2)
plt.plot(time, values, 'o-', label='Original Data', alpha=0.5)

for start, end in ranges:
    sliced_values = values[start:end]
    sliced_time = time[start:end]
    
    trend, _ = kf.filter(sliced_values)
    
    plt.plot(sliced_time, trend, linestyle='--', label=f'Trend ({start} to {end})')

plt.legend()
plt.title('Denoising using Kalman Filter')
plt.xlabel('Time')
plt.ylabel('Signal')

plt.tight_layout()
plt.show()
```
🏠𝐍𝐨̣̂𝐢 𝐭𝐡𝐚̂́𝐭 𝐡𝐢𝐞̣̂𝐧 đ𝐚̣𝐢 

Phong cách nội thất hiện đại mang đến không gian sống hiện đại, tinh tế và thoải mái. Với sự kết hợp giữa đơn giản và tối giản
🔎Website: http://noithatbluehouse.store/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3796820/00c4ff4d-db6d-c284-9ff5-07505c6884da.png)
Splunk - バージョンを確認したい

## 検証環境
Splunk Enterprise 9.2.1

## はじめに
Splunkのバージョンを確認する時にSPLで引っ張ってこれるよ、というだけの話。

## SPL
### [1] Splunk version
```SPL:SPL
| rest /services/server/info
| table version
```

### [2] Apps version
```SPL:SPL
| rest /services/apps/local 
| table title version
```

## 終わりに
たまに使う。GUI(設定/Settings)から探すより早い。
【Django】グラフ・データの可視化手法　まとめ

# 大まかにまとめてくれてる人
https://www.silicloud.com/ja/blog/django%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E5%8B%95%E7%9A%84%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E5%8F%AF%E8%A6%96%E5%8C%96%E6%96%B9%E6%B3%95%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B%E3%80%82/
1. Chart.js、D3.js、Highchartsなどの人気のあるJavaScriptグラフ描画ライブラリを使う。

2. AJAXとJSONを使用して、データを非同期でロードし、JavaScriptコードに渡す。

3. Django Channelsの使用する。Django Channelsは、リアルタイムアプリケーションや長期ポーリングを処理するためのDjangoの拡張機能。

4. Webソケットを使用する。サーバーとクライアント間で双方向通信を確立し、リアルタイムデータ視覚化を実現するためにWebソケットを使用する。

## Djangoのグラフ描画ライブラリ
- Django tables2
- Django Dash
    - https://akatak.hatenadiary.jp/entry/2020/07/25/161326
- plotly

## Pythonのグラフ描画ツールランキング
https://docs.kanaries.net/ja/articles/top10-dataviz-in-pytho
インタプリタ言語とコンパイル言語

プログラミング言語には、インタプリタ言語とコンパイラ言語（コンパイル型言語）が存在します。

今回はその二つの違いについて解説していこうと思います。

## 言葉の意味

英語を勉強していれば、どちらの単語も見た事や聞いたことがあるかもしれません。
ただ、私は全くと言っていい程に英単語を覚えていなかったので、プログラミングを勉強する上でこの二つの単語が出てきた時は、正直全然意味がわかりませんでした。

まず、**インタプリタ(interpreter)** の方には、「解釈者、説明者、通訳」といった意味があります。
次に、**コンパイルの(compile)** 方には、「蓄積する、集める」といった意味があります。

それでは、この二つの言語について順を追って見ていきましょう。

## 大前提、プログラミング言語とは

そもそも、ここが分からないとインタプリタ言語とかコンパイル言語についても分からないので、まずはここについて見ていきましょう。

プログラミング言語とは、ざっくり言うとプログラム（コンピューターへの指示）を記述するための言語です。
皆さんがご存知の通り、コンピューターはとても便利で頭が良いですが、コンピューターが理解できる機械語は、数字の0と1の値だけで構成されています。でも、2進数だけで表示された物を見ても、正直意味が分からないですよね。

なので、人間はテキスト形式でコンピューターに指示を出すことができる、プログラミング言語を開発しました。
このプログラミング言語を使って指示を出すと、コンピューターが機械語に翻訳して、指示を実行してくれるのです。

## インタプリタ言語

まず、インタプリタ言語とは先ほども説明しましたが、プログラミング言語の種類です。
「インタプリタ」というプログラムを処理する方法に対応した言語のことを「インタプリタ言語」と言います。この「インタプリタ」という処理方法は、プログラムを実行する際に1行ずつ機械語に翻訳して、実行していく方式です。

特徴としては、1行ずつ翻訳しながら実行ができるので、プログラムが完成していなくても実行することができ、**エラーの特定や修正（デバッグ）** がしやすいです。

なるほど、インタプリタ(interpreter)という英語の「通訳」という意味にピッタリな仕様ですね。また、「解釈者」という意味も、1行1行解釈していく点がぴったりです。

このインタプリタ言語の例としては、HTML・CSS・JavaScript・Python・Rubyなどの言語が挙げられます。

## コンパイラ言語

次に、コンパイラ言語とは、「コンパイル」というプログラムを処理する方法に対応した言語のことです。

ちなみに、コンパイル言語とコンパイラ言語と「ル」と「ラ」の違いで色々言い方がありますが、どちらが合ってるのかは正直あまりわかりません。一応、色々なサイトを確認した感じでは「コンパイラ言語」の方が多かったように感じました。
ちなみに、英語では「Compiled Language」となっており、Wikipediaなんかでは **「コンパイル型言語」** と定義されてたりします。（[Wikipedia : コンパイル型言語]([https://ja.wikipedia.org/wiki/コンパイル型言語](https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%B3%E3%83%91%E3%82%A4%E3%83%AB%E5%9E%8B%E8%A8%80%E8%AA%9E))）

この言語は「コンパイラ」という、ソースコードを1行1行ではなく一括で機械語に翻訳して、実行していく方式で書かれた言語になります。
特徴としては、一気に読んで翻訳するので **実行速度がインタプリタ言語よりも早く、またCPUなどにかかる負荷も小さい** ことなどが挙げられます。

英語のコンパイル(compile)にある、「蓄積する、集める」といった意味が何となくわかりますね。
ちなみにですが、そもそもcompileという単語には調べると分かるのですが「機械語に翻訳する」と言った意味もちゃんと出てきます。

コンパイラ言語の主な例としては、C言語・C++・Java・Swiftなどがあります。

## ２つの種類の違い

1行1行読んで実行していくインタプリタと、全部読んでから実行するコンパイラ、実際にその違いについて詳しく見ていきましょう。

例えば、人間がコンピューターにカレーを作る指示書を書いたとします。

**1.野菜と肉を切る**

**2.切った野菜と肉を鍋で煮る**

**3.ルーを入れる**

これをインタプリタ言語で書いても、コンパイラ言語で書いてもカレーは出来上がりますが、その指示書の中で書き間違いをしてしまったりしたらどうするでしょうか。

例えば手順2の段階で、「切った野菜と **”魚”** を鍋で煮る」と間違った指示をしていたとしましょう。
インタプリタ言語の場合、1行1行で実行をしてくれるので、ミスがあった時点で気付いてストップをしてくれます。

![インタプリタ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788428/4adce07e-156b-a136-124a-936ac190e47a.png)


しかし、コンパイラ言語では全部読んでから実行をするスタイルなので、1の指示はミス無く実行できるはずですが、2でミスをしているので、もう最初から1の実行にすら手をつけない状態でエラーが発生します。そのため、どこでミスをしたのかが分からない状態で、エラーが起こってしまい、デバッグがしづらいのです。

![コンパイラ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3788428/e3b6ca9d-320c-0972-c93b-a9b017d49c12.png)


ここだけ見ると、コンパイラ言語はあまりメリットがない印象を受けます。しかし、思い出してください。コンパイラ言語のメリットとしては、その早さがあります。

人間も、料理をするときにレシピの手順を一つずつ読んで、その都度知らない技法や道具を調べたりして、一つずつ実行するよりも、レシピの手順に一回目を通して知らないことを調べて、それから手順通りに実行していく方が早く料理を作れますよね。

コンパイラ言語とインタプリタ言語、それぞれに良さがあるので、作りたいものに応じてその言語は使い分けをされていきます。
そのため、人間は自分が携わりたい開発の場に応じて、言語を学んでいくのです。
データセットを使ってみる

# はじめに
bdrccです。
データ分析に関心がある、職業訓練生です。
Pythonに関する記事（備忘録？）、初めてあげてみます。

# 背景
GW明けにPython3エンジニア認定データ分析試験を受験し、合格しました。
その後、何かを分析してみたいとデータを探し、下記記事・サイトを発見しました。

https://qiita.com/mitamura/items/3dba898eafb8ae39670c

https://ainow.ai/2020/03/02/183280/

その中で、[UC Irvine Machine Learning Repository](https://archive.ics.uci.edu/) に遭遇。

復習しながら、使ってみます。

# 目的
1. UC Irvine Machine Learning Repository 内のデータセットの使い方を知る
2. Pythonの分析（特に、ランダムフォレスト）を復習する

# 環境
### 言語
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Python 3.10.6
### モジュール 各種
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;jupyterlab 3.4.3
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;numpy 1.24.4
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pandas 1.4.2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;matplotlib 3.5.2
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;scikit-learn 1.4.1.post1
### 開発環境
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MacOS 

# データセットを確認する

まずは、Pythonを起動。
復習を兼ねて、仮想環境を使用します。

```terminal:
$ python3 -m venv env #最後は仮想環境名
$ source env/bin/activate
```

さて、uciのサイトを確認。データセット(記事投稿時点665件)のうち、209件がpythonで使用できるらしい。ということで、定番のIrisデータを見てみます。

![スクリーンショット 2024-05-17 21.18.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793831/dacaf3b2-1c3e-3c3a-16ec-005e133b207e.png)

ucimlrepoをインストールすれば使用できるようなので、pip installしてimport

```py:
from ucimlrepo import fetch_ucirepo 
  
# 使用するデータセットをidで決定
iris = fetch_ucirepo(id=53) 
  
X = iris.data.features 
y = iris.data.targets 
```
得られたデータは辞書型になっていて、その中にデータがあります。
サイト通りに実行すると、PandasのDataFrameが得られました。

# 分類
参考文献を参考に、今回は教師あり学習のランダムフォレストを行います。
ただし、このまま分析に入ると、下記の警告文が出ます。
```terminal:
/~/sklearn/base.py:1474: DataConversionWarning: 
A column-vector y was passed when a 1d array was expected. 
Please change the shape of y to (n_samples,), for example using ravel().
  return fit_method(estimator, *args, **kwargs)
```
そのため、カテゴリ変数のエンコーディングを行ってから、分析。
```py:
from sklearn.preprocessing import LabelEncoder
le = LabelEncoder()
y2 = le.fit_transform(y.loc[:,'class'])
```
```py:
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
X_train, X_test, y_train, y_test = train_test_split(X, y2, test_size=0.3, random_state=123)
forest = RandomForestClassifier(n_estimators=100, random_state=123)
forest.fit(X_train,y_train)
y_pred = forest.predict(X_test)
y_pred
```
結果はこちら

![スクリーンショット 2024-05-20 21.45.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793831/f8300b83-7e16-df01-1399-ed78f63b5f24.png)

混同行列も見てみます。
```py:
print(classification_report(y_test, y_pred))
```
![スクリーンショット 2024-05-20 21.46.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3793831/18ae6a13-caa9-16ef-7740-26b825cffc24.png)

さすがIrisデータといったところ、Setosaデータが通常あり得ない値を叩き出している・・・。

# 終わりに
かなりの頻度でデータセットが追加されており、おすすめの分析手法まで書かれていました。
勉強用には持ってこいな気がします。
欠損値処理も復習しつつ、他のデータセットでも試していきます。

足りない等お気付きの点ありましたら、教えてくださると助かります。
最後まで見ていただきありがとうございました。

# 参考文献
- [Pythonによるあたらしいデータ分析の教科書 第2版](https://www.shoeisha.co.jp/book/detail/9784798178776)
- 参考にさせていただいた、@mitamura (mitamura) 様、ありがとうございました。
Amazon ECS

# 0.はじめに
この記事はAWS SAA試験勉強のための、Amazon ECSに関する知識のまとめです。


# 1.Amazon ECSとは
Amazon ECS (Elastic <font color="red">**Container**</font> Service)はEC2インスタンスのクラスターでDockerコンテナーを実行できるAWSサービスです。
ECSはAWS独自のコンテナオーケストレーションを採用しています。

# 2.Amazon ECSの基本的性質

- クラスター上で動作するTaskの定義はTask Definitionで行います。
- Amazon EventBridge スケジューラを利用してスケジュールされたタスクの作成を定期的に実施することが可能。


# 3.Amazon ECSクラスターへのスケーリング設定

## 3.1.ステップスケーリングポリシー

CPUが上昇した場合に自動的に徐々にパフォーマンスを向上させることができます。

# 4.サービススケジューラ

Amazon ECSのサービススケジューラは長時間実行するタスクのスケジュール設定に向いている機能であり、短期間に繰り返すジョブのスケジュール設定には利用できません。


# 5.起動タイプ

ECSの起動タイプとして、Fargate起動タイプとEC2起動タイプがあります。要件として管理負荷の低減が求められている場合はFargateの選択が適切です。

# 6.ALBとの連携

ALBはレイヤー7で負荷分散するロードバランサー。このALBと対になるサーバー側の接続相手としてコンテナが使われることが多い。
コンテナへのURLパスをルーティングできる。