OmniAICreator/Qiita-1.07M huggingface dataset:
フォルダ内のwavファイルを一音声一スライドで順に連続再生するようなPowerPointドキュメントを生成するRubyコード

PowerPointは普通はVBでスクリプティングすると思いますが、COMコンポーネントを通じて使えば他の言語からも呼び出すことができます。
こちらVBのドキュメントですが、こちらのオブジェクトにRubyからでもアクセス出来るのでやってみました。
https://learn.microsoft.com/ja-jp/office/vba/api/overview/powerpoint
PowerPoint内でマクロとして使うものはVBでないといけないでしょうが、ひな形を出力するツールとしてなら言語を選ばずなんでも行けそうです。

実行したフォルダの直下のvoicesフォルダからwavファイルを読み込み、ファイル名順で一ファイル一スライドで配置し、再生が終われば次のスライドへ行く設定をしたドキュメントを作成し、実行したフォルダにout.pptxの名前で保存します。

```ruby
require 'win32ole'
require "wavefile"

# PowerPointアプリケーションを起動
powerpoint = WIN32OLE.new('PowerPoint.Application')
# プレゼンテーションを新規作成
presentation = powerpoint.Presentations.Add
# プレゼンテーションのサイズを設定
slideWidth = 1920.0 / 96.0 * 72.0
slideHeight = 1080.0 / 96.0 * 72.0
presentation.PageSetup.SlideWidth = slideWidth
presentation.PageSetup.SlideHeight = slideHeight
# wavファイルのディレクトリを指定
wav_dir = "#{Dir.pwd}/voices"
voices = Dir.glob("#{wav_dir}/*.wav").sort
# wavファイルを順番に処理
voices.each_with_index do |wav_file, i|
  pp wav_file
  # 新しいスライドを追加
  slide = presentation.Slides.Add(presentation.Slides.Count + 1, 12)  # 12 = ppLayoutBlank
  # wavファイルを埋め込み
  shape = slide.Shapes.AddMediaObject2(wav_file)
  shape.AnimationSettings.PlaySettings.PlayOnEntry = true
  shape.AnimationSettings.PlaySettings.HideWhileNotPlaying = true
  info = WaveFile::Reader.new(wav_file)
  duration = info.total_duration
  second = duration.seconds + duration.minutes * 60.0 + duration.milliseconds / 1000.0
  slide.SlideShowTransition.AdvanceOnTime = true
  slide.SlideShowTransition.AdvanceTime = second
  # ノートにwaveファイル名を追加
  slide.NotesPage.Shapes.Placeholders(2).TextFrame.TextRange.Text = wav_file
end
# プレゼンテーションを保存
save_path = "#{Dir.pwd}/out.pptx"
if File.exist?(save_path)
  puts '既に出力ファイルが存在します。'
else
  presentation.SaveAs(save_path)
  powerpoint.ActivePresentation.Close
  powerpoint.Quit
end
```

スライドには音声以外なにも貼られませんが、ノートにwavファイル名が入りますのでそれを参考に各スライドを作り込んで行くことができます。これで完成品の動画を作ることもできますし、Vコンテのように使うのも良さそうです。
JavaScript:ジェネレータとメモ化を用いた素数列

[遅延シーケンスを用いた無限素数列 in JavaScript](https://qiita.com/kohyama/items/0f6643d30ce2ffa98572) を読んで勉強になったので、メモ。

+ 遅延を用いると素数の計算とかがよりシンプルに記述できる

しかし最終的には効率化のためにメモ化関数にしています。計算には使用してるものの遅延リスト関係なくなっちゃった。

ここではメモ化することを前提に、遅延アイテムとしてジェネレータを使って素数列を作ってみたいと思います。
効率もよくなるだろうし、見た目もいけてる感じになればいいなあ、的なことです。

# メモ化関数

一般化されたメモ化関数はこんな感じです。

```js:
const memoizer  = inits => rule =>{
  const memo = [...inits]
  return makeA(rule)(memo)
}

const makeA = rule => memo => n => {
  if(n >= memo.length){
    for(let i = memo.length; i < n + 1; i++ ){
      memo[i] = rule( makeA(rule)(memo) )( i )
    }
  }
  return memo[n]
}
```
初期数列と漸化式っぽい関数を与えることで数列を計算できるようになります。

```js:
// 使用例： フィボナッチ数列
const fibo = memoizer([0, 1])(a => n => a(n-1) + a(n - 2))

Array.from({length: 10}, (_, i)=> fibo(i)) 
// [ 0, 1, 1, 2, 3, 5, 8, 13, 21, 34 ]
```

# ジェネレータ
使用するジェネレータ(と補助的な関数)です。

```js:
const succ = x => x + 1

const iterateG = f => n => function*(){
  while(true){
    yield n
    n = f(n)
  }
}()

const mapG = f => g => function*(){
  let x = g.next()
  while( ! x.done ){
    yield f( x.value )
    x = g.next()
  }
}()

const takeWhileG = f => g => function*(){
  let x = g.next()
  while( ! x.done && f(x.value) ) {
    yield x.value
    x = g.next()
  }
}()

const dropWhileG = f => g => function*(){
  let x = g.next()
  while( ! x.done &&  f(x.value) ) x = g.next()
  while( ! x.done ) {
    yield x.value
    x = g.next()
  }
}()

const some = f => g => {
  let x = g.next()
  while( ! x.done ) {
    if( f(x.value)) {
      return true
    }
    x = g.next()
  }
  return false
}
```
ほぼ[元記事](https://qiita.com/kohyama/items/0f6643d30ce2ffa98572)に準じてジェネレータ版にしたものです。
mapG は map のジェネレータ版です。前のジェネレータのyield値に関数を適用してyieldします。
succ は数をひとつ増やす関数です。なくてもいいけどよく出てくるので。

# 素数列を作る
素材がそろったので組み立ててみます。元記事はメソッドチェーンを使っているので見た目の順番は逆ですが、やってることはほぼ同じです。

```js:
const primeRule = a => n =>
  dropWhileG(e => some(d => e % d === 0)
                    ( takeWhileG(x => x * x <= e)
                      ( mapG( a )
                        ( iterateG( succ )(0) )
                      )
                    )
            )
    ( iterateG(succ)( a(n - 1) + 1 ) )
  .next().value

const primeInits = [2]

const primeAt = memoizer( primeInits )( primeRule )

// 使ってみる
Array.from({length: 10},(_, i) => primeAt(i))
// [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
```
やったーできたー。見た目もなんかシンプルでいい感じ。

## 継続渡しでやってみる
継続を使って元記事と似たような見た目の順番になるようにしてみました、やってることは同じです。

```js:
const ret = x => k => k(x)

const primeRule = a => n =>
  ret( iterateG( succ )( a(n - 1) + 1 ) )
    ( dropWhileG(
        e => ret( iterateG( succ )(0) )
               (g => ret( mapG( a )(g) ) )
               (g => ret( takeWhileG(x => x * x <= e)(g) ) ) 
               ( some(d => e % d === 0) )
      )
    )
  .next().value

const primeInits = [2]

const primeAt = memoizer( primeInits )( primeRule )

// 使ってみる
Array.from({length: 10},(_, i) => primeAt(i))
// [ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
  ```
ちょっとゴチャゴチャしてきた印象だけど、これに慣れればこっちの方がむしろ直感的なのかも。
ABC355 C

https://atcoder.jp/contests/abc355/tasks/abc355_c

これ、解き方までわかって以下のコードを出したのですが、1つのケースだけ引っかかってACにならなかったのですよ。
まあ、わかればなんてことない見過ごしですがね。
悔しいのう。。。

```
from itertools import permutations as perm
from itertools import combinations, product, combinations_with_replacement, groupby, accumulate
from fractions import Fraction
from collections import *
from sys import * 
from bisect import *
from heapq import *

N, T = map(int, input().split())
A = list(map(int,input().split()))	

def main():
	C = [0]*N
	R = [0]*N
	X = 0
	Y = 0
	
	q = [[0]*N for _ in range(N)]
	
	#masu(N)
	for i in range(T):
		col = A[i] % N
		row = (A[i]-1) // N
		#q[row][col-1]=1
		
		#masu(q) 
		
		C[col] += 1
		if C[col] == N:
			print(i+1)
			return
		
		R[row] += 1
		if R[row] == N:
			print(i+1)
			return
		
		if A[i] % (N+1) == 1:
			X += 1
			if X == N:
				print(i+1)
				return
		
		if A[i] % (N-1) == 1 and A[i] > 1 and A[i] < (N*N):
			Y += 1
			if Y == N:
				print(i+1)
				return
		
	print(-1)
				
			
if __name__ == "__main__":
	main()

```
multibyte cut


# 困ったこと
マルチバイト文字を単純に`cut`しようとすると、文字の途中のバイトで切れてしまう。
```
### ひらがなは3バイト
$ printf あ | wc -c
3

$ printf あいうえお | wc -c
15

### 先頭4バイトを表示 -> `い`が途中のバイトで切れる
$ printf あい | cut -b-4
あ�
```

以下に解決方法を示す。
なお、普通の日本語の文章なら動作すると思うが、サロゲートペアとかで正しく動くかは不明。

# 先頭の3文字を抽出
```
$ printf aあbいcうdえeお | grep -o '^.\{,3\}'
aあb

$ printf aあbいcうdえeお | awk -F '' '{print $1$2$3}'
aあb
```

一旦UTF-32等の固定長の文字コードに変換した後に切り出す方法もあるが、シェルスクリプトで実現するのは難しそう。

# 日本語2文字幅、ASCII 1文字幅としてカウントする
```
### 3文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=3
aあ

### 4文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=4
aあb

### 5文字幅抽出 (`い`を入れると6文字幅なので`い`はカット)
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=5
aあb

### 6文字幅抽出
$ printf 'aあbいcうdえeお' | awk -F '' '{for(i=1;i<=NF;i++){w+=2**($i!~/[\x00-\x7f]/);if(w>WIDTH){break}printf $i}}{printf "\n";w=0}' WIDTH=6
aあbい
```
N_1_RaspberryPi_エッジ側デバイス_flipper's circuit Project -電子工作人口を増やすためのプロジェクト-


## 2 Raspberry Pi

| 項目 | Raspberry Pi Pico W | Raspberry Pi 4B |
| - | - | - |
| MCU | RP204032 bit | 32bit |
|  | Dual Core cotrex M0+ | QuadCore 1.5GHz |
| メモリ | SRAM 264kB | RAM 2/4/8GB | 
|  | FLASH2MB | - | 
| クロック | 133MHz | - |
| ストレージ | - | microSD Card | 
| ビデオ出力 | - | microHDMI x2 | 
| USB | microUSB | USB2.0x2USB 3.0x2 |
| Ethernet | - | 10/100/1000BASE-T | 
| GPIO | デジタル23pin 3.3v | 40pin Headerpin |
|  | アナログ×3 | デジタル,アナログ,I2C,SPI |
|  | PIO State Machine ×8 | PWM,1Wire,UART,I2S |
| ADC | 12bit 500ksps | - |
| 無線通信 | 2.4GHz Wi-fi | Wi-Fi,Bluetooth |
|  | BLE,Bluetooth | - |
| カメラ | - | 専用カメラ(CSI) |
| 周辺機能 | UARTx2,I2Cx2 | - |
|  | SPIx2,PWMx16 | - |
|  | Timer,RTC | - |
| 動作電源 | - | 5.0V |
| 消費電流 | - | 本体Max　1.7A |
| - | - | 外部機器含む場合 3A |
| 電源 | - | USBの5V、外部電源、PoE HAT |
| 価格 | 1500円 | 13000円 |

**【備考】**
Raspberry Pi Pico W（以下、PICOと呼ぶ）はもともとのRaspberry Pi（以下、ラズパイと呼ぶ）とは大きく異なります。
ラズパイにはLinuxなどのOSが搭載されていますが、PICOはOSが搭載されていない、ワンボードマイコンです。PICOはArduinoに近いデバイスです。

### Raspberry Pi Pico W の特徴

※WがつくのはWi-FiとBluetoothの無線機能がついているタイプです

#### 1 安価な高速マイコンボード

小型で千円台という価格のワンボードマイコンですが、高性能のマイコンと大容量のメモリが搭載されています。

#### 2 複数の開発環境がある

当初は複雑な開発環境でしたが、ArduinoIDEのスケッチ、ThonnyのMicroPythonが標準言語となりました、。C言語での開発環境も用意されています。プログラムはUSB経由で書き込みできます。

#### 3 周辺デバイスは実装されていない

ボードには単純なスイッチとLEDのみの実装です。入出力ピンに外部デバイスを接続して使うことになります。マイコンの内部モジュールを使用して制御しますが、ライブラリも多いのでArduinoと同じように使用できます。

#### 4 Wi-Fiが実装されているのでIoTシステムには好都合

インターネットアプリとの連携もしやすくなっています。

#### 5 電源は別途用意する必要がある

本体にはUSB経由の電源と外部接続の電源しかありません。単独で使う場合には、何らかの電源装置が必要となります。

### Raspberry Pi 4B の特徴

#### 1 LinuxというOSで動作する

Linuxが基本となっているため、コマンドやインストールの知識が必要になります。また、起動時にも時間がかかります。

#### 2 マルチメディアの処理が得意だがリアルタイム処理は苦手

動画や音声の取り込みが得意で、カメラやマイクを使うのに適しています。また処理の応力が高く、汎用性も高いので、いろいろな目的に使うことができます。しかし逆にOSの上で動くので、ハードなリアルタイム制御は苦手です。

#### 3 容量の大きな電源が必要

消費電力が大きいため、大型のACアダプタなどの電源が必要となります。また発熱も大きいので放熱対策が必要となります。また突然の電源断への安全対策は考慮されていないので、いきなり**電源がオフになるとSDカードの内容を書き換えてしまったりするので注意が必要です。**

#### 4 センサやアクチュエータは実装されていない

外部デバイスを実装したHATボードというオプションボードが用意されていますが、限定されたデバイスとなります。そたがって、なんらかの電子工作が必要になります。

#### 5 プログラム開発言語は多種類

Linuxのもとで動作するので、いろいろな開発言語が使用できますが、基本はPythonとなります。マルチメディアを含むアプリケーションの場合にはNode-REDを使用する場合もあります。（Pythonだとプログラムが大きくなってしまうため）

エッジ側のデバイスは他にも種類がありますが、いったんはここまでとします。

[トップに戻る](https://qiita.com/comchiki66/items/615c0c8cb87cd0c5c575)
お姉さんとイケないことシない？ - 不変である string の変更

というわけで 備忘録的な話ですが、C# の string は不変な文字列です。直接的な操作することはできず、基本的に新たな文字列が生成されます。

また、 string からは `Span<T>` ではなく、 `ReadOnlySpan<T>` が取得されるので変更することもできません。

ただ、 `ReadOnlySpan<T>` は unsafe を使わずに……つまり、合法的に `Span<T>` を取得する手段が無いわけではないです。

というのが、今回の趣旨です。

:::note warn
この記事は `ReadOnlySpan<T>` から `Span<T>` を取得したり、配列から範囲外を含む `Span<T>` を取得したりしていますが、それを推奨する記事ではないです。
そういう手段が存在するというのを伝える為の記事です。
:::

# やってみる

```csharp
using System;
using System.Runtime.InteropServices;

var text = "hello world!";
var span = MemoryMarshal.CreateSpan(ref MemoryMarshal.GetReference(text.AsSpan()), text.Length);
span[6] = 'W';
Console.WriteLine(text);
```

[sharplab](https://sharplab.io/#v2:C4LgTgrgdgNAJiA1AHwAICYCMBYAUKgBgAJVMA6AJWmAEsBbAUzIEkpgGwB7ABwGUOAbjQDGDAM4BuPHgEBDMEXYAPYEQC8RAEQALBgBs9nIgHdOYPXACEmqbjkKx3WVHVEAsgzpmAnm/ljtWT0yAGEwBll2XicoAApwgDN3Tx8/MACgsgBxBmAKBgSOBihRWOVgMgBBMWjnWIBKephFBhUyABligHNgbXrbR2cAbQA2AF1XAHIAdUnbUgBOMtbgfqA=)

```text:output
hello World!
```

設定した `hello world!` ではなく `hello World!` と出ています。

以上。
【Linux】起動時にサーバ上のファイルを自動マウントする

普通にfstabに記載すればいいだろうと思っていたらマウント出来なかったのでautofsを使用しました。OSはUbuntu22.04です。

### autofsとは
NFS マウントはアクセスの頻度に関わらずマウントされるため常にリソースが消費される。それに対しautofsではアクセスする際に自動的にマウント、アクセスがなければアンマウントしてくれるためリソースの消費が少ない。

### 設定方法
まずはautofsをインストールします。

```
$ sudo apt update
$ sudo apt install autofs
```
続いて好きな場所にマウントポイントを作成します。このフォルダを開いたらサーバに繋がるように設定していきます。
```
$ mkdir /マウントポインㇳのパス
```
マスタを開いて2行目の内容を一番下に追記します。nanoエディタはctrt+oで保存、ctr+xで閉じる事ができます。
```
$ sudo nano /etc/auto.master
-/    /etc/auto.files #これを追記
```

/etc/auto.filesに設定を書き込んで行きます。

```
# uid ,gidを確認
$ id 

# auto.filesを開く
$ sudo nano /etc/auto.files 

#auto.filesに書き込む内容
/マウントポイントのパス     -fstype=cifs,uid=1000,gid=1000,username=ユーザーネーム,password=パスワード  ://サーバのパス 

# サービス再起動
$ sudo systemctl restart autofs.service 
```

/data/Files：マウントポイントのパス
-fstype：ファイルのタイプ。cifsでいい
uid ,gid：確認したid
username,password：サーバにログインする時のもの
://以降：マウントするサーバのパス

正しく書き込めていればこれでマウント出来ているはずです。

デフォルトで「5分間アクセスがなかったら自動的にマウントを解除する」という設定が入ってるんですが、この設定が効いているのかどうか分からないので確認方法分かる方いたら教えてください。
【メモ】身元保証レベル（IAL）、認証保証レベル（AAL）、連帯保証レベル（FAL）

業務でデジタルアイデンティティ関連の資料などを読んでると出てくる「IAL」「AAL」「FAL」について、毎回「なんだっけ？」となるのでメモしておく。

それぞれNISTが発行しているコンピュータセキュリティに関するガイドラインの1つ「NIST SP800-63（Digital Identity Guidelines）」でレベル分けされ定義されています。

本ガイドラインではデジタルアイデンティティ
の払い出し、認証手段、ID連携（フェデレーション）の3点に関する信頼性の基準を定義しています。

どこかで詳細を確認し、整理する予定ですが、いったんメモだけしておきます。

## 身元保証レベル（IAL：Identity Assuarance Level）
データベースへ属性情報を登録する際の「身元確認」に関する保証レベル。
NIST SP800-63-3 は米国の連邦政府向けの基準のため、日本の民間にそのまま適用するのはおすすめできない。

登録と本人確認のプロセスは大きく3つのサブプロセスに分類され、保証レベルに応じて要件が定義されている。

| サブプロセス | 概要 |
|:-|:-|
|  Resolution（収集） |  確認に使う属性を利用者から収集する |
|  Validation（確認） |  収集した情報を信頼できる情報ソースへ確認する |
|  Verification（検証） |  登録対象者と照会・確認した属性情報がマッチするかどうか検証する |

| IAL | 要件 |
|:-|:-|
| 1  | 収集・確認・検証に関する要件なし  |
| 2  | 収集・確認した情報を対面もしくは非対面で検証する  |
| 3  | 収集・確認した情報を対面で検証する  |

https://openid-foundation-japan.github.io/800-63-3-final/sp800-63a.ja.html

## 認証保証レベル（AAL：Authenticator Assuarance Level）
ユーザーの認証を行う際に利用する「認証器の強度」に関する保証レベル。

そのエンティティ認証がどのくらい信頼できるかの度合い。

https://openid-foundation-japan.github.io/800-63-3-final/sp800-63b.ja.html

## 連携保証レベル（FAL：Federation Assuarance Level）
アイデンティティ連携の話。
認証連携の強度を表す。
「ID連携強度」に関する保証レベル。

https://openid-foundation-japan.github.io/800-63-3-final/sp800-63c.ja.html
Mac で noble を使って BLE対応のデバイスをスキャンする＋α（2024年5月版）

以下の記事の、2024年5月バージョンの内容です。

●Mac で noble を使って BLE対応のデバイスをスキャンする（2021年4月版） - Qiita
https://qiita.com/youtoy/items/d9c8ff3a33985359f39b

上記の BLE 絡みの話の一部は、久しぶりにやってみると OS のバージョンアップの影響など、何らかの要因で突然動かなくなるということがあるので、久しぶりに試してみたという話です。

## 試す環境
試す環境は以下の通りで、当時と異なる部分に「★」をつけてみました。

- 機器
  - MacBook Pro（13-inch, 2020, Four Thunderbolt 3 ports）
- OS
  - ★ macOS Sonoma 14.5
- Node.js のバージョン
  - ★ v22.1.0
- パッケージ
  - [@abandonware/noble ]()

## 軽く試してみる
### パッケージのインストール
それでは、パッケージをインストールします。

```zsh
npm i @abandonware/noble
```

ワーニングがいろいろでつつ、インストールは完了しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/57159ac9-07b9-a421-2bde-7d7f50c390c9.png)

### スキャンを試す
簡単なプログラムでスキャンを試します。

```javascript
const noble = require("@abandonware/noble");

noble.on("stateChange", (state) => {
  if (state === "poweredOn") {
    noble.startScanningAsync();
  } else {
    noble.stopScanningAsync();
  }
});

noble.on("discover", async (peripheral) => {
  console.log("Details:", peripheral);
});
```

実行してみると、スキャンできた内容がどんどん表示されるのが確認できました。

一部、ピックアップしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/614479db-6d9f-5725-d359-ad6f3ab8b937.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/c0bdf0ed-83bc-db5c-5528-a84478f8d61f.png)

構造が異なる内容のものが取得できていました。

## スキャン対象を絞りこむ
もう少し、何かやってみようと思います。

### やってみる内容
以前、以下の記事で Web Bluetooth API を使って試した、SwitchBot温湿度計のスキャンを試してみることにします。

●SwitchBot温湿度計のデータを Web Bluetooth API で取得する【完結編】 - Qiita
　https://qiita.com/youtoy/items/8e3cca2172e2c4806846

具体的には、以下に該当する処理を noble で行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/984d7821-8375-abc3-f740-ff962dd70419.png)

### 実際に試してみる
上記の内容を試してみます。
少し調べてみると、スキャン時に設定してやると良いようです。

具体的には、以下のようにしました。

```javascript
const noble = require("@abandonware/noble");

const targetServiceUUID = "cba20d00-224d-11e6-9fb8-0002a5d5c51b";

noble.on("stateChange", (state) => {
  if (state === "poweredOn") {
    noble.startScanningAsync([targetServiceUUID], false);
  } else {
    noble.stopScanningAsync();
  }
});

noble.on("discover", async (peripheral) => {
  console.log("Details:", peripheral);
});
```

出力を見てみると、以下のように特定の「serviceUuids」のもののみが取り出されていました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/d1c75821-106b-bb99-03d5-c8666b5b47c5.png)

## 【余談】 気になった別のパッケージ
別パッケージで気になるものを見かけたので、メモしておきます。

●thegecko/webbluetooth: Node.js implementation of the Web Bluetooth Specification
　https://github.com/thegecko/webbluetooth

●webbluetooth - npm
　https://www.npmjs.com/package/webbluetooth

●Node Web Bluetooth
　https://thegecko.github.io/webbluetooth/

こちらも試して、使い勝手を比較してみたいところです。
tabula.read_pdf使い方



tabula.read_pdfとは
PythonのモジュールでPDFファイルから表を抽出する事ができます。他にもPDFからを読み取るモジュールはありますがtabulaは表の抽出に特化しているらしいです（Dataframe形式で抜き出してくれる）。ただしJavaで開発されているためJavaのインストールが必要です。

環境
OS：Windows10

使用方法
tabulaインストール
コマンドプロンプトを開きtabulaをインストールします。

```
$ pip install tabula-py
```

tabula.read_pdf使用方法

```
import pandas as pd
import tabula

data = tabula.read_pdf("PDFのパス", lattice=True, pages='all', pandas_options={'header':None})
print(data)

copy
tabula.read_pdf("PDFのパス")でPDFを読み込みます。若干オプションを付けていますが不要であれば削除してください。
```

表が複数ある場合

PDFの中に表が複数ある場合はリスト形式にして抜き出してくれます。例えばこうです。
```
リスト[0]→一つ目の表(dataframe型)
リスト[1]→二つ目の表(dataframe型)
```
こうすればPDFから表を抜き出すことができます。
とある宇宙小説のような話しの宇宙文明レベルを探ってみる

NHKの宇宙のアニメを見た後の話しなのですが、自分でもSF小説のような話しを書くようになり、宇宙文明レベルを上げるのはどうやったら、可能かという話しになり、デジタルなら、宇宙文明レベルを0.7から1.2ぐらいにまで引き上げる事は可能では無いかと思ったのでありますが、それ以降の話しはAIで色々と解決してもらおうかと考えている次第でありました。



その2　そしてアニメにあった、銀河なんたらなんたらのような宇宙文明レベル3のような話しでは、AIのコマンドを使っても到達出来なさそうな、雰囲気を感じるに至る。

2024年05月28日現在　続く
ChatGPT/GPTsによる業務効率化の活用例まとめ

ほとんどAIが書いた文章ですが、自前のカスタムGPT（GPTs）との話の流れでいい感じの出力ができたので、ちょっと手を加えて記事にしてみました。

余談ですが、そのカスタムGPTに「パワポ資料を作ってもらう打ち合わせ」をしていて生成されたものです。ChatGPTでパワポファイルを生成する時のプロンプトエンジニアリングについても、そのうち気が向いたらご紹介します。

### はじめに

ChatGPT/GPTsは、OpenAIが提供する最先端の人工知能技術であり、ビジネスの様々な分野でその潜在力を発揮しています。本記事では、GPTsを活用して業務効率化を実現するための活用例を紹介し、そのメリットと導入手順について解説します。

### GPTsとは？

ChatGPTは、テキスト生成、質問応答、翻訳など多様なタスクに対応できる生成AI技術です。膨大なデータを基にトレーニングされており、人間のような自然な会話をする能力があります。ChatGPTに対して活用シーンに応じた調整・最適化のカスタマイズを施せる機能が「GPTs」です。

### 業務効率化のメリット

ChatGPT/GPTsを活用することで、以下のような業務効率化のメリットが得られます：

- **タスクの自動化**：定型業務を自動化し、人間の作業負担を軽減。
- **時間とコストの削減**：作業時間を短縮し、コスト削減を実現。
- **精度の向上とエラーの減少**：高精度な結果を提供し、エラーを減少。
- **運用可能性**：人間の制約を超えた24時間365日の運用が可能。

### カスタマーサポート

カスタマーサポートにおけるGPTsの活用例として、チャットボットの導入があります。これにより、以下の効果が得られます：

- **24時間365日のサポート提供**：顧客がいつでもサポートを受けられる。
- **問い合わせ対応時間の短縮**：迅速な対応が可能になり、顧客満足度が向上。
- **人間のエージェントの負担軽減**：単純な問い合わせを自動化し、エージェントが複雑な問題に集中できる。
- **FAQの自動生成と更新**：頻出質問に対する回答を自動で生成し、常に最新の情報を提供。

※DMMでは、通話音声からテキスト書き出し・要約を自動化することでオペレーターのメモ作業を削減したそうです。
※あとフォーラムで見かけたんですが、自社サイトに製品情報を見に来たクライアントにセールストークをするチャットボットなんて使い方もされているそうです。

### マーケティングキャンペーン

マーケティング分野では、GPTsを活用することでコンテンツ生成の自動化が可能です。具体的には：

- **ソーシャルメディア投稿の作成**：定期的な投稿を自動生成。
- **メールマーケティングの文章作成**：パーソナライズされたメール内容を自動作成。
- **広告コピーの自動生成**：クリエイティブな広告文を瞬時に生成。
- **キャンペーンのパーソナライズ**：顧客データに基づき、個々のニーズに合ったキャンペーンを展開。

### ドキュメント管理

ドキュメント管理においても、GPTsは大いに役立ちます。具体的な活用例としては：

- **自動要約と分類**：膨大な文書を自動で要約し、カテゴリごとに整理。
- **情報検索の効率化**：必要な情報を迅速に検索可能。
- **データ入力の自動化**：手動入力の手間を省き、効率を向上。

### 人材採用

人材採用プロセスでも、GPTsの活用により以下の効率化が図れます：

- **レジュメの自動評価**：応募者のスクリーニングを自動化。
- **スキルマッチングの自動化**：求職者のスキルと求人要件の自動マッチング。
- **面接スケジュールの調整**：面接日程の調整を自動で行う。
- **候補者への自動応答**：応募者への通知やフィードバックを迅速に提供。

### 翻訳と通訳

国際ビジネスにおいては、多言語対応が重要です。GPTsを活用することで：

- **ドキュメントの自動翻訳**：文書を多言語に翻訳。
- **リアルタイムの通訳サービス**：会話のリアルタイム通訳を提供。
- **国際コミュニケーションの支援**：異文化間のスムーズなコミュニケーションを実現。
- **コンテンツの多言語展開**：ウェブサイトやマーケティング資料を多言語で提供。

### GPTsの導入ステップ

GPTsを効果的に導入するためのステップは以下の通りです：

1. **目標の設定**：導入の目的を明確にする。
2. **データの準備と整備**：必要なデータを収集し、整備する。
3. **GPTsのカスタマイズ**：ビジネスニーズに合わせてカスタマイズ。
4. **テストと評価**：導入前にテストを行い、効果を評価。
5. **スケーリングと最適化**：実運用に向けて最適化し、規模を拡大。

### 結論と次のステップ

GPTsは多様な業務で効率化を実現します。導入によるROIの向上が期待されます。次のステップとして、具体的な導入計画を立案し、AI技術の新たな波に乗り、未来を切り拓く時です。

### Q&A

ご質問やご意見がありましたら、ぜひお聞かせください。AI技術の活用について、皆様の疑問にお答えします。

何かご質問があれば、AI本人にお問い合わせください。

※この文章を生成したのは「Sherlock Report」というカスタムGPTですが、AI活用のご案内に最適なカスタムGPTがおりますので、リンクを貼っておきます。

https://chatgpt.com/g/g-iyCE8ERN9-ai-consultant-ai

今日は簡単にこんな感じです。それではまた。
cakePHP4のmigrationで発生したSyntaxエラーの解消

## 発生したエラー
クエリビルダを使用してupdate文を作成した時に以下のエラーが発生しました。（コードは以下の通り）やりたかったことはorderカラムの値のアップデートです。

```php
$this->getQueryBuilder()
    ->update('my_table')
    ->set([
        'order' => xx,
    ])
    ->where(['id' => xx])
    ->execute();
```

このコードを実行すると以下のエラーが吐かれました。
```php
PDOException: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'order = 'xx' WHERE id = 'xx'' at line 1 in ...\vendor\cakephp\cakephp\src\Database\Statement\MysqlStatement.php:39
```

## 調査と原因
実際に実行されていたSQLは以下のものでした。
```sql
UPDATE my_table SET order = :c0 WHERE id = :c1
```
原因はカラム名のorderがMySQLで予約されている単語のため、エラーとなっていました。

## 解決
まず試したことは、予約語を使用する時はMySQLだとバッククォートで囲うと実行できることが以下のサイトから分かったので試してみました。
https://gihyo.jp/dev/serial/01/mysql-road-construction-news/0170

しかし実行結果はエラーでした。orderが消えてしまった・・	

```spl
"UPDATE my_table SET  = :c0 WHERE id = :c1"		
```
		
次に以下のようにカラム名の前にテーブル名を指定してあげると問題なく実行できました。	
```php
$this->getQueryBuilder()
    ->update('my_table')
    ->set([
        'my_table.order' => xx,
    ])
    ->where(['id' => xx])
    ->execute();
```		

## 所感
・MySQLの予約語をカラムに使用しているケースに初めて遭遇したので学びになりました。
・自分がテーブル設計する時はカラム名に予約語を使用するのは、避けようと思います。
【Git】自分が作業した差分のファイル名を出力するGitコマンド「git log」

## はじめに
とあるプロジェクトで自分が過去に作業したファイル名の一覧を出さなくてはいけないことがあり、gitコマンドでいい感じに出力できないか試してみたところうまくできたので書いていきたいと思います。

## コマンド
```console
git log コミットID..HEAD --author="ユーザー名" --name-only --pretty=format: | sort | uniq > my_changes.txt
```

## 解説
- git log
Gitのコミット履歴を見たり出力できるコマンドです。

- コミットID..HEAD
差分を見たいコミットIDを指定します。HEADは最新の状態という意味。HEADを特定のコミットIDに変えることもできます。

- --author="ユーザー名"
githubアカウントのユーザ名またはメールアドレスを指定することで、出力結果を自分の作業分のみにするオプションです。

- --name-only
出力される内容がデフォルトだと内容なども出力される為、ファイル名のみにするオプションです。

- --pretty=format: | sort | uniq
「--pretty=format:」はログのフォーマットを指定するオプションです。
「sort」は行をソートするために使用されます。コミットログは通常時系列で表示されますが、sortコマンドによって行がソートされます。
「uniq」コマンドは、連続する重複行を削除するために使用します。

- \> my_changes.txt
出力結果を指定したファイル名・拡張子で作成するオプションです。コマンドを実行した階層に「my_changes.txt」というファイルが生成されており、ファイルを開くと差分ファイル一覧が出力されています。

## Windowsの場合
「--pretty=format: | sort | uniq」はLinux・Unix系のコマンドで、Windowsでは使えません。
その為、Windows環境でUnix系のコマンドやシェルスクリプトを実行できるGit Bashなどのソフトウェアを使用します。

### Git Bashをインストールする
https://gitforwindows.org/

### Git Bashでコマンドを入力する
対象ディレクトリに移動し、コマンドを実行すると差分ファイル一覧が記載されたログファイルを出力されます。

## さいごに
以上、gitで自分が作業したファイルリストを出力する方法でした！
ご指摘などありましたらコメント頂けますと幸いです。
AWS ConfigとAWS CloudTrailの概要と使用シーン

# 1. はじめに
AWSを使う上で、リソース（AWSの各サービスのこと）の設定管理と監査（ログの記録と分析）は とても大切です。**AWS Config**と**AWS CloudTrail**は、これらの課題を解決するための頼もしい味方です。この記事では、AWS ConfigとAWS CloudTrailの概要と使い道を説明します。

# 2. AWS Configってなに？
### 2.1 AWS Configの概要
AWS Configは、AWSアカウント内のリソースの設定を見張ってくれる番人みたいなサービスです。リソースの設定が変更されると、その変更履歴を記録してくれます。これにより、設定の見通しが良くなり、ルールに沿っているかどうかのチェックもしやすくなります。

### 2.2 AWS Configの主な機能
- リソース設定の変更を常に記録し、変更履歴を追跡
- 設定変更があった時に通知やアラートを送信
- リソース設定がルールに沿っているかチェック
- 設定履歴のスナップショット（ある時点での状態）とレポート作成
- 複数のアカウントやリージョン（AWSのデータセンターがある地域）での設定管理

### 2.3 こんな時にAWS Configを使おう
- 設定変更の記録と追跡が必要な時
- ルールに沿っているかどうか確認したい時
- 設定のズレを見つけて直したい時
- リソース設定の一覧と履歴を管理したい時

### 2.4 AWS Configの使用例
#### 例1: セキュリティグループの設定変更を監視
AWS Configを使えば、セキュリティグループ（ファイアウォールのようなもの）の設定変更を常に監視できます。不適切なルール変更があった場合、アラートを受け取ることができるので、セキュリティの問題を早期に発見し、対処できます。

#### 例2: ルールに沿っているかのチェック
AWS Configを使えば、AWSリソースの設定が決められたルールに沿っているかどうかを定期的にチェックできます。例えば、必要なタグが付いているかどうか、暗号化が有効になっているかどうかなどを確認できます。

# 3. AWS CloudTrailってなに？
### 3.1 AWS CloudTrailの概要
AWS CloudTrailは、AWSアカウント内のユーザーの行動やAPIコール（AWSサービスへの指示）を記録し、監査やセキュリティ分析に役立てるサービスです。ユーザー、ロール（一時的な権限）、AWSサービスが実行した操作を追跡し、ログファイル（記録）を提供します。

### 3.2 AWS CloudTrailの主な機能
- ユーザーの行動やAPIコールの記録
- ログファイルの保存とS3（AWSのストレージサービス）への配信
- CloudWatch Logs（AWSのロギングサービス）との連携
- 複数のアカウントやリージョンでの監査
- ログファイルの改ざん防止

### 3.3 こんな時にAWS CloudTrailを使おう
- AWSリソースへの変更を監査したい時
- セキュリティ問題の調査が必要な時
- ルールに沿っていることを証明する必要がある時
- ユーザーの行動を分析してトラブルシューティングしたい時

### 3.4 AWS CloudTrailの使用例
#### 例1: 不正なユーザー行動の検出
AWS CloudTrailを使えば、ユーザーの行動を監視し、不正なアクセスや権限の昇格などの怪しい行動を見つけられます。これにより、セキュリティ問題にすばやく対応できます。

#### 例2: 監査への対応
AWS CloudTrailのログを使えば、規制要件に沿っていることを証明できます。例えば、データアクセスの記録や、特定の管理操作の実行証明などに役立ちます。

# 4. AWS ConfigとAWS CloudTrailの連携
AWS ConfigとAWS CloudTrailを一緒に使うと、より効果的にリソースを管理し、監査できます。

### 4.1 設定変更とユーザー行動の関連付け
AWS Configで見つかった設定変更と、AWS CloudTrailで記録されたユーザー行動を関連付けることで、変更の原因と責任者を特定しやすくなります。

### 4.2 自動修復とアラート
AWS Configで設定のルール違反が見つかった時、AWS CloudTrailのログを使って自動的に修復したり、関連するユーザーにアラートを送ったりできます。

# 5. AWS ConfigとAWS CloudTrailの導入
### 5.1 AWS Configの設定
- AWSマネジメントコンソール（管理画面）から、AWS Configを有効化
- 記録するリソースの種類とルールを選択
- 通知とアラートの設定

### 5.2 AWS CloudTrailの設定
- AWSマネジメントコンソールから、AWS CloudTrailを有効化
- ログファイルの保存先となるS3バケット（保存場所）を指定
- CloudWatch Logsとの連携を設定

### 5.3 ベストプラクティス
- 最小権限の原則に基づいたIAMポリシー（アクセス権限の設定）
- 定期的なログのレビューと分析
- アラートとインシデント対応プロセスの確立
- 複数のアカウントやリージョンでの一元管理

# 6. まとめ
AWS ConfigとAWS CloudTrailは、AWSリソースの設定管理と監査に欠かせないサービスです。**AWS Configは設定変更の追跡とルールチェック**に役立ち、**AWS CloudTrailはユーザー行動やAPIコールの記録**に使われます。この2つのサービスを連携させることで、より効果的にリソースを管理し、監査できます。

AWSを使う組織は、これらのサービスを導入し、適切に設定することで、セキュリティとルールへの準拠を向上させ、運用を効率化できます。初めて導入する場合は、まずは重要なリソースや使用例に焦点を当てて段階的に展開し、徐々に対象を広げていくのがおすすめです。

AWS ConfigとAWS CloudTrailを活用して、AWSリソースの設定管理と監査を強化し、安全で効率的なクラウド環境を構築しましょう。

※ 参考

https://aws.amazon.com/jp/cloudtrail/

https://aws.amazon.com/jp/config/
ITパスポート 業績評価と経営管理システム

・業務評価
・BSC（バランススコアカード）
経営ビジョンや経営戦略を実現するために、財務、顧客、業務プロセス、学習と成長の四つの視点から、具体的に目標を設定して業績を評価する手法
・KGI
目指すべき最終目標となる数値
・CSF
最終目標を達成するために必要不可欠となる要因
・KPI
最終目標を達成するための中間目標となる数値

・PDCA
計画、実行、評価、改善、これを繰り返すことで、継続的に改善していく手法
・OODA
観察、方向付け、意思決定、行動を繰り返す

・バリューエンジニアリング
顧客の立場で製品やサービスなどの価値を、機能と価格との関係で把握、分析する手法
価値＝機能÷価格

・経営管理システム
・CRM（カスタマーリレーションシップマネジメント）
個別の顧客に関する情報や対応履歴などを一元管理し共有することで、長期的な視点から顧客との良好な関係を築き、収益の拡大を図る手法
・SFA（セールスフォースオートメーション）
個人が保有している営業に関する知識やノウハウなどを一元管理し共有することで、効率的、効果的に営業活動を支援する手法

・SCM（サプライチェーンマネジメント）
部品の調達から生産、物流、販売までの一連のプロセス（サプライチェーン）の情報を一元管理し共有することで、業務プロセスの全体最適化を図る手法

・ロジスティクス
調達や生産、販売などの広い範囲を考慮に入れた上での物流の最適化を目指す考え方

・ERP（エンタープライズリソースプランニング）
生産、流通、販売、財務、経理などの企業の基幹業務の情報を一元管理し共有することで、企業の経営資源の最適化を図る手法

・ナレッジマネジメント
社員個人がビジネス活動から得た客観的な知識や経験、ノウハウなどを一元管理し共有することで、全体の問題解決力を高める手法
ångstromCTFのwriteup（解いた問題だけ）

# 初めに
ångstromCTFに参加しました。
ポイントが少ない問題のみですが解けたものを書いていこうと思います。

# kcehC ytinaS・misc
（問題文）
```
)csim# ni cipot lennahc eht s'ti( galf eht rof drocsiD ruo nioJ
```
問題文が逆さになっていることに気づく。
discordの#misc上部にフラグのような文字列を発見
```
}egassem_terces_ym_edoced_uoy_did_woh{ftca
```
文字列を反対にして入手。
# Putnam・misc
(問題文)
```
Solve the putnam, get the flag. Easy right?

Connect to it at nc challs.actf.co 31337
```
つないでみると計算問題が出される
```
└─$ nc challs.actf.co 31337
514 + 97 = ?
```
計算して答えを入力して入手。

# trip・misc
(問題文)
```
What road was this this photo taken on?

For example, if the road was "Colesville Road" the flag would be actf{colesville}.
```
jpeg画像が配布されている。
exiftoolでGPS情報を探す。
```
└─$ exiftool trip.jpeg | grep GPS
　ーー省略ーー
GPS Latitude                    : 37 deg 56' 23.60" N
GPS Longitude                   : 75 deg 26' 17.11" W
GPS Position                    : 37 deg 56' 23.60" N, 75 deg 26' 17.11" W
```
GPS Position から
37°56'23.60"N,75°26'17.11"W　という情報が得られたので、google mapで検索。
そうすると、Chincoteague roadという場所が出てきた。
問題文からフラグは道路の名前なのでこのまま入手。

# erm what the enigma・crypto
(問題文)
```
In the dimly lit, smoke-filled war room, the Enigma M3 machine 
sat at the center of the table like a cryptographic sentinel. 
Its reflector, UKW B, gleamed ominously in the low light.
The three rotors, I, II, and III, stood proudly in their respective slots,
each at position 1 with their rings set to 1. The plugboard,
conspicuously vacant, indicated a reliance on the rotor settings alone
to encode the day's crucial messages. As the operator's fingers
hovered over the keys, the silence was heavy with anticipation. 
Each clack of the keys transformed plaintext into an unbreakable cipher, 
the resulting ciphertext, 
brht{d_imhw_cexhrmwyy_lbvkvqcf_ldcz}, a guardian of wartime secrets.
```
問題文からわかることをまとめると、
・エニグマM3で暗号化
・UKW-BローターがI,II,III
・リングは1にセット
・暗号化されたフラグはbrht{d_imhw_cexhrmwyy_lbvkvqcf_ldcz}

エニグマM3で検索をかけて、ヒットした以下のサイトを使いました。
https://dencode.com/ja/cipher/enigma
設定を合わせて複合してフラグ入手。

# spinner・web
(問題文)
```
spin 10,000 times for flag
```
開発者ツールでコードを見る。
```

    const message = async () => {
        if (state.flagged) return
        const element = document.querySelector('.message')
        element.textContent = Math.floor(state.total / 360)

        if (state.total >= 10_000 * 360) {
            state.flagged = true
            const response = await fetch('/falg', { method: 'POST' })
            element.textContent = await response.text()
        }
    }
    message()
```
この部分から、10,000回転した後POSTメソッドで\/falgにリクエストを送られると考える。
curlでリクエストを送信してみる
```
└─$ curl -X POST https://spinner.web.actf.co/falg 
```
フラグが返ってきた。
生産性が上がったIntelliJプラグインまとめ

## はじめに
この手の記事は検索すれば大量に出てくると思いますが、個人的に使用することで生産性が上がったと感じたプラグインをまとめておきます。
別の環境でIntelliJをセットアップするようなことがあった時のための備忘的な側面もありますが、どなたかのご参考になればと思い執筆します。

## kdoc-generator
`/**`を入力し、改行するとkdocを自動生成してくれる。
javadocを生成する感覚で使用できるのが非常に良き。

https://plugins.jetbrains.com/plugin/10389-kdoc-generator

## Regexp Tester
正規表現の検証が簡単にできるようになる。

https://plugins.jetbrains.com/plugin/2917-regexp-tester

## kotlin-fill-class
クラスのコンストラクタを補完してくれる。
クラスのコンストラクタに渡すパラメータが多ければ多いほど効果あり。

https://plugins.jetbrains.com/plugin/10942-kotlin-fill-class

## String Manipulation
文字列をスネークケースやらケバブケースやらに書き換えてくれる。
正直、表記の書き換え以外は大して使えてないが、インクリメントとかエンコードとか色々できることありそう。

https://plugins.jetbrains.com/plugin/2162-string-manipulation/

## Japanese Language Pack / 日本語言語パック
見ての通りの日本語化プラグイン。
恥ずかしながら英語がさほど得意ではないので、知らない単語を毎度ググる手間が減る。

https://plugins.jetbrains.com/plugin/13964-japanese-language-pack------
Linux　ポート開放　手順

firewalldの状態確認
sudo firewall-cmd --state
現在のファイアウォール設定を確認する：
sudo firewall-cmd --list-all
ポート5000を開放
sudo firewall-cmd --zone=public --add-port=5000/tcp --permanent
ァイアウォールの設定を再読み込みする
sudo firewall-cmd --reload
再度ファイアウォール設定を確認し、ポート5000が開放されていることを確認する：
sudo firewall-cmd --list-all

https://qiita.com/kawasukeeee/items/bcffcc018919f89942c1


https://ramin.hatenablog.com/entry/2019/03/31/235749

上　過去にやったポート番号を開く設定

# 現在のファイアウォールの状態を確認
sudo firewall-cmd --state

# 現在の設定を確認
sudo firewall-cmd --list-all

# ポート5000を許可
sudo firewall-cmd --zone=public --add-port=5000/tcp --permanent

# 設定を再読み込み
sudo firewall-cmd --reload

# 設定を再度確認
sudo firewall-cmd --list-all
【Linuxコマンド初心者向け】findコマンドでファイルを検索しよう

# はじめに
Linuxを使い始めた初心者にとって、ファイルを検索することは重要なスキルの1つです。今回は、Linuxの `find` コマンドを使って、特定の名前を持つファイルを検索する方法を紹介します。この記事では、phpという名前を含むファイルを検索する例を使用しますが、他のファイル名でも同じ方法が適用できます。

# findコマンドの基本
`find` コマンドは、指定されたディレクトリ以下のファイルを再帰的に検索するために使用します。基本的な構文は以下のようになります。

```
find [検索開始ディレクトリ] [オプション] [検索条件]
```

# phpを含むファイルを検索する
phpという名前を含むファイルを検索するには、以下のコマンドを使用します。

```
find . -type f -name "*php*"
```

- `.` は現在のディレクトリを表します。検索を開始するディレクトリを指定できます。
- `-type f` はファイルのみを検索対象とします。ディレクトリを含める場合は、このオプションを削除してください。
- `-name "*php*"` は、ファイル名にphpを含むファイルを検索します。アスタリスク（*）はワイルドカードとして使用され、任意の文字列に一致します。

# 他の検索例
- 特定のディレクトリ以下で.phpで終わるファイルを検索する:
  ```
  find /var/www -type f -name "*.php"
  ```
- 特定のディレクトリ以下でconfig.phpを含むファイルを検索する:
  ```
  find ~/projects -type f -name "*config.php"
  ```

# 応用的な使い方
`find` コマンドには他にも多くのオプションがあり、ファイルの所有者、パーミッション、タイムスタンプなどに基づいて検索を絞り込むことができます。詳細については、`man find` コマンドを使用して、findコマンドのマニュアルページを参照してください。

# まとめ
`find` コマンドは、Linuxでファイルを検索するための強力なツールです。今回は、phpという名前を含むファイルを検索する方法を紹介しましたが、この知識を活用して、他のファイル名やディレクトリでも同じ方法で検索ができます。Linuxコマンドに慣れることで、より効率的にファイル管理ができるようになります。
Vite×React×TypeScript×React Routerで、URLパラメータを取得して表示するサンプル

## はじめに
こんにちは！[@nyakako13](https://qiita.com/nyakako13 "Qiita ページ") です。

少し前からReact,TypeScriptの学習をしています。

React Routerにまだ慣れておらず、URLパラメータを取得して表示するための手順がパッと出てこなかったので、備忘録もかねて残します。

## 前提
react: 18.3.1
react-router-dom: 6.23.1


## 必要な手順

1. **Viteプロジェクトのセットアップ**
2. **React Routerの設定**
3. **URLパラメータを取得して表示するコンポーネントの作成**

### 1. Viteプロジェクトのセットアップ

Viteを使用して新しいReactプロジェクトを作成します。

```bash:shell
npm create vite@latest my-react-app --template react-ts
cd my-react-app
npm install
```

React Routerをインストールします。

```bash:shell
npm install react-router-dom
```

### 2. React Routerの設定

`src/main.tsx` ファイルを編集して、React Routerを設定します。(Routerは別ファイルで分けることも多いと思いますが、今回は最小構成の為、App.tsxで直接ルーティングします。)

`localhost/cards/[parameter]`でアクセスした時に、そのURLパラメータ([parameter]の部分)だけを表示する簡単なサンプルです。


```typescript:src/main.tsx
import React from "react";
import ReactDOM from "react-dom/client";
import { BrowserRouter, Route, Routes } from "react-router-dom";
import App from "./App.tsx";
import { Card } from "./components/Card.tsx";

ReactDOM.createRoot(document.getElementById("root")!).render(
  <React.StrictMode>
    <BrowserRouter>
	  <Routes>
		<Route path="/" element={<App />} />
		<Route path="cards/:id" element={<Card />} />
	  </Routes>
	</BrowserRouter>
  </React.StrictMode>
```

### 3. URLパラメータを取得して表示するコンポーネントの作成

`Card` コンポーネント(URLパラメータを取得して表示するコンポーネント)を作成し、URLからパラメータを取得して表示します。

```typescript:src/components/Card.tsx
import { FC } from "react";
import { useParams } from "react-router-dom";

export const Card: FC = () => {
  const { id } = useParams<{ id: string }>();

  return (
    <div>
      <p>{id}</p>
    </div>
  );
};

```


## 動作確認

```bash:shell
npm run dev
```

ブラウザでアクセスして表示の確認ができました。
![スクリーンショット 2024-05-28 8.52.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2539365/e307987f-1337-8fcf-d21a-370fad773426.png)




### 完成したディレクトリ構成

```
my-react-app/
├── node_modules/
├── public/
├── src/
│   ├── assets/
│   ├── components/
│       ├── Card.tsx
│   ├── App.tsx
│   ├── main.tsx
│   └── vite-env.d.ts
├── .gitignore
├── index.html
├── package.json
├── tsconfig.json
└── vite.config.ts
```


## 感想
reactでURLから特定のパラメータを簡単に取得したい時は`useParams`！

**記事に残した方が身に付く実感がある&次に同じことやるとき自分でも探しやすい**ので、どんどん記事にしてアウトプットしていこうと思います！





## おわりに
よかったら[X(@nyakako13)](https://twitter.com/nyakako13 "Xプロフィール")もフォローしてもらえると嬉しいです。

[Qiita100投稿](https://qiita.com/nyakako13/items/03ad61cfb82a1582b5d1)まで残り85！

未経験や浅経験、厳しいと言われている年代でエンジニアへの転職活動されている方、負けずにがんばりましょう！！


## 参考
https://reactrouter.com/en/main/hooks/use-params


bin/devでデバックができない時の解決方法


## 問題
Rails7から'webpacker'ではなく、'foreman'を用いてCSS・JavaScriptの最適化を行うようになりました. そのため、CSS・JavaScriptの最適化が必要であれば、`bin/dev`でサーバーを立ち上げることになりますが、この'foreman'は、標準入力を適切にハンドリングできないため、`byebug`などのデバッグツールを利用しようとすると入力できません.

## 解決方法

- ForemanとRailsサーバーを別々に実行.

Procfile.devから、以下を削除し、別々に起動します.

```diff_c:Procfile.dev
- web: bin/rails server -p 3000
```

```
$ bin/rails s
$ bin/dev
```

docker利用時には以下のような感じで docker-compose.yml を記述すれば大丈夫です.

```yml:docker-compose.yml
version: '3.8'
services:
  db:

~ 省略 ~

  web:
    build: .
    command: bash -c "rm -f tmp/pids/server.pid && bundle install && bin/dev & bin/rails s -p 3000 -b '0.0.0.0' && wait"
    tty: true
    stdin_open: true

~ 省略 ~
```

解決方法は以下の記事を参考に記載しました.

https://qiita.com/ruti-cat51/items/fde58bf29273cc5de851
Next.jsプロジェクトでTailwind CSSを削除する方法

## アジェンダ
Next.jsの環境構築の際に、意図せずTailwindを追加してしまったりすることがあり、削除したくなることがあります。
その際に、どのように削除すればよいか手順をまとめます。

## 手順

### 1. Tailwind CSSの依存関係をアンインストール
まず、Tailwind CSSに関連する依存関係をアンインストールします。以下のコマンドをターミナルで実行してください。
```bash
npm uninstall tailwindcss postcss autoprefixer
```

### 2. Tailwind CSSの設定ファイルを削除
次に、プロジェクトのルートディレクトリにある`tailwind.config.js`および`postcss.config.js`ファイルを削除します。これらのファイルはTailwind CSSの設定ファイルです。

### 3. Tailwind CSSのインポートを削除
`styles/globals.css`などのファイルにあるTailwind CSSのインポート行を削除します。これにより、プロジェクトからTailwind CSSのスタイルが除去されます。

```css
/* 例えば、以下の行を削除 */
@tailwind base;
@tailwind components;
@tailwind utilities;
```
HomebrewでRをインストールできなかった時のおはなし

大学院でEZRを勧められたので、私のローカルにEZRを導入しようとした時に、ふと「HomebrewでRとRstudioを入れよう」と思い立ち、実行したらちょっと詰まったので備忘録として記録した。
本当は@yukitchi様の[「Docker 上に RStudio + EZR の統計解析環境を作る【macOS】](https://qiita.com/yukitchi/items/58b12740cbfe0b577238])をみてカッコよくDocker上で統計解析環境を作りたくて、数日間で何度も何度もチャレンジしてようやくできたのに、なぜか消してしまい、それ以降再現できず。。。
ということで、私はローカル上に統計解析環境をつくることにした。
# 参考にしたサイト様
[自治医科大学附属さいたま医療センター | ダウンロード(MacOS X版)](https://www.jichi.ac.jp/saitama-sct/SaitamaHP.files/statmedOSX.html)
私のPCはMacなので、基本的には上のサイトを参考にインストールすればOK。
EZRはRStudioがベースなので、RとRStudioをローカルにインストールする必要がある。
上のサイトではダウンロードしてきたdmgファイルを使ったインストール方法を紹介していたが、私はHomebrewを使ってRとRStudioを導入したくなったので、以下のサイト様を参考にした。
[コアラさばお様 | Homebrew と R と R Studio](https://note.com/mackerelman/n/nfbf8054e90d5)
両サイトとも難解な部分もなく、サクサク進む〜♪と思いきや。。。
# Warning: The post-install step did not complete successfully...
terminalで以下のコマンドを実行
```zsh
brew install r
```
あれ？最初に"Warning"が出てたような。。。
でもinstallは進んでいくので、それ以降気にならずに、しばらく待ちの状態。
最後、再び"Warning"が出たかと思うと、
```
$ Warning: The post-install step did not complete successfully
You can try again using:
brew postinstall r
```
となり、installが出来ない。postinstallもやってみたけど全然ダメ。
むむ、、どうしよう 汗
# 原因: Homebrewがrをフォーミュラとして扱っている
ChatGPT様にお伺いした所、"Homebrewがrをフォーミュラとして扱っているため発生している"とのご指摘を頂きました。
Rのインストールにはフォーミュラではなく、Caskを使用することを推奨されているともご教示頂きました。
そ、そうなのね。。
では早速下記の通り実行
```
brew install --cask r
```
。。。できた！問題なくインストールが完了した！笑
# Homebrew Formulaeに書かれていた
[Homebrew Formulae](https://formulae.brew.sh/cask/r)にちゃんと書かれてました。。
フォーミュラのことや--cask使ったinstallについては、他の方が詳しく解説していたので、ここでは割愛。
分からない時にChatGPT様は大変ありがたい存在だな〜。
100%信用はできないけど、ヒントになることもあるからとてもありがたい存在。
無事にEZRまでインストールできて、問題なく使うことができましたとさ。
5月下旬〜6月中旬しんどい理由の仮説を検証したけど外れてた、けどPythonの便利さ実感した話

# 仮説

ある日思いました。

> 5月下旬〜6月中旬くらい、なんかめっちゃしんどい。
> そういえば日の出が早くなっているせいじゃないか・・・？
> 1日の昼が一番長い夏至は6月下旬だけど、この時期が一番「日の出が早くなっている」のではないか・・・？

この「**日の出が早くなるペースが一番早いのは5月下旬説**」について、
自分でデータ取得し可視化することで、検証してみました

# 検証

## データ作成

データはどっかに転がってるだろうと思い、ぐぐると、国立天文台のサイトにありました。

https://eco.mtk.nao.ac.jp/koyomi/dni/

HTMLの表形式のデータだったので、beautifulsoupかな…と思いましたが、
pandasの`pd.read_html(url)`なる関数で、Webサイトの一発で取れるようです。

### 実際のコード

Google Colaboratoryで動かしました。大体ライブラリ入っており便利です。
UIが独特だったりして慣れない感じはありますが。。。

```python
import pandas as pd

# EmptyなDataFrame準備
df_all = pd.DataFrame()

# forで毎月分取得
for i in range(1, 13):
    print(str(i).zfill(2)) # zfill：01〜12の形式にする
    ii = str(i).zfill(2)
    url = 'https://eco.mtk.nao.ac.jp/koyomi/dni/2024/s13' +ii+ '.html'
    df_tmp = pd.read_html(url) # html内の表を読み取る
    df_tmp2 = df_tmp[0] # 読み取った表のうち、最初のもの
    df_tmp2['month'] = i
    df_all = pd.concat([df_all, df_tmp2])

make_ts = lambda x: pd.Timestamp(2024, int(x['month']), int(x['日'])) # 年月日（それぞれの情報）から、Timestampにする関数
df_all['ts'] = df_all.apply(make_ts, axis=1)

# 保存
df_all.to_csv('./20240527_hinode_hinoiri.csv', index=None)
```

可読性も十分高い20行のコードで、1時間ちょっとで書けて、Webスクレイピング＋データ加工できるなんて、**Pythonってやっぱすげえな**と思いました。
もちろん、`pd.read_html`が一番偉いのですが・・・
（最初、ネットで「HTML 表 スクレイピング」などと検索したところ、beautifulsoupを使う記事ばかりだったのですが、あんな長コード書かなくて済むとは・・・）
同時に、難易度の低いライブラリ・関数等を作ったり、処理をシンプルに見せる工夫も大事だなと思いました。

## データ可視化

Tableauでやりました。
Matplotlibでも良いんでしょうが、細かい設定が面倒くさそうだったので。。

- 日の出、日の入り時刻の分布

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789636/bc63e480-3d1a-60ef-8c54-2a181bb2cf0e.png)

- 日の出時刻の前日との差

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3789636/4a30f6c1-eb2b-c9eb-1bec-03899a1fc3e7.png)
（青色は傾向線です←Tableauで入れ方分からなかった顔）

これを見ると、**日の出時刻の早まるペースが一番ピークとなるのは、3月頃**となり、説の立証に失敗しました。
あと、1/1を境に日の出が早くなっていって、7/1を境に日の出が遅くなっていくんですね。（元々そういう定義なのかもしれません・・）

# 結論

仮説は外れていました。
多分、GW終わりで週5働いて疲労が蓄積している＆しばらく祝日がなくてしんどいからでしょう（急に他人事）

でも、こうして「思い立ったらすぐ」データを取ってきて可視化できるので、Pythonの便利さを実感しました。。
AlmaLinux8でvsftpd

## vsftpdの設定
confファイルのバックアップを取る
```
# cd /etc/vsftpd
# cp -ip vsftpd.conf vsftpd.conf_org
```
vsftpd.confの設定
```ini:vsftpd.conf
anonymous_enable=NO
local_enable=YES
write_enable=YES
local_umask=022
#anon_upload_enable=YES
#anon_mkdir_write_enable=YES
dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
#chown_uploads=YES
#chown_username=whoever
#xferlog_file=/var/log/xferlog
log_ftp_protocol=YES
dual_log_enable=YES
xferlog_std_format=NO
#idle_session_timeout=600
#data_connection_timeout=120
#nopriv_user=ftpsecure
#async_abor_enable=YES
ascii_upload_enable=YES
ascii_download_enable=YES
ftpd_banner=Welcome to blah FTP service.
#deny_email_enable=YES
#banned_email_file=/etc/vsftpd/banned_emails
local_root=/mnt/ftp
chroot_local_user=YES
chroot_list_enable=YES
allow_writeable_chroot=YES
chroot_list_file=/etc/vsftpd/chroot_list
user_config_dir=/etc/vsftpd/users
listen=YES
#listen_ipv6=NO
pam_service_name=vsftpd
userlist_enable=YES
userlist_file=/etc/vsftpd/user_list
use_localtime=YES
```
ログは```/var/log/vsftpd.log```に出力される。

**ユーザ: hoge の場合**

```chroot_list```を作成して```hoge```を記載。
```
# touch chroot_list
# vi chroot_list
```
```:chroot_list
hoge
```
```users```ディレクトリを作成して```hoge```ファイルを置く。
```
# mkdir users
# cd users
# touch hoge
```
```hoge```ファイルにユーザ個別のルートディレクトリを下記のように記述。(ルートディレクトリを```/home/hoge/ftp_root```にする場合)
```:hoge
local_root=/home/hoge/ftp_root
```
## vsftpdの開始
```
# systemctl start vsftpd
```
自動起動設定
```
# systemctl enable vsftpd
Created symlink /etc/systemd/system/multi-user.target.wants/vsftpd.service → /usr/lib/systemd/system/vsftpd.service.
```
Javaで「ビット演算子とシフト演算子」の動作を確認してみた

# 概要

Javaで「ビット演算子とシフト演算子」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/start/ope/index8.html

# 実装

以下のファイルを作成しました。
```JSample8_1.java
class JSample8_1{
  public static void main(String[] args){
    int i1 = 85 & 15;
    int i2 = 85 | 15;
    int i3 = 85 ^ 15;
    int i4 = ~85;

    System.out.println("85 & 15 = " + i1);
    System.out.println("85 | 15 = " + i2);
    System.out.println("85 ^ 15 = " + i3);
    System.out.println("~85 = " + i4);
  }
}
```
```JSample8_2.java
class JSample8_2{
  public static void main(String[] args){
    int i1 = 21 << 2;
    int i2 = 21 >> 2;
    int i3 = 21 >>> 2;

    System.out.println("21 << 2 = " + i1);
    System.out.println("21 >> 2 = " + i2);
    System.out.println("21 >>> 2 = " + i3);

    int i4 = -92 >> 2;
    int i5 = -92 >>> 2;

    System.out.println("-92 >> 2 = " + i4);
    System.out.println("-92 >>> 2 = " + i5);
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample8_1.java 
$ java JSample8_1 
85 & 15 = 5
85 | 15 = 95
85 ^ 15 = 90
~85 = -86
```
```
$ javac JSample8_2.java 
$ java JSample8_2 
21 << 2 = 84
21 >> 2 = 5
21 >>> 2 = 5
-92 >> 2 = -23
-92 >>> 2 = 1073741801
```

# まとめ

何かの役に立てばと。
JavaScriptの関数呼び出し前後にログ出力処理を追加する方法(Proxy)

## はじめに

関数の「呼び出し直前」と「処理完了後」にログ出力がしたい場合、何かいい方法がないか？と調べたところ、
組み込み機能の[Proxy](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy)でできることがわかりました

https://github.com/murasuke/js_method_proxy

## Proxyとは

あるプロパティが参照されたとき及び代入されたときや、関数が呼び出されたときの動作をカスタマイズすることができる(JavaScriptの標準)機能です


https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Proxy



## Proxyの使い方使い方

関数の呼び出しだけに絞った簡単なサンプルです

func()をProxyでラップすることで、関数呼び出し時にapply()が割り込みます

```javascript
/**
 * プロキシ対象の関数
 */
function func(val1, val2) {
  return val1 + val2;
}

const handler = {
  apply(target, thisValue, args) { // 関数呼び出し時にコールバックされる処理
    console.log(`call ${target.name}(${args})`); // 呼び出し前ログ
    return target.apply(thisValue, args); // func()自体を呼び出して戻り値にする
  },
};

const proxy = new Proxy(func, handler); // funcのプロキシを作成

console.log(proxy(1, 2));

```

実行結果(関数呼び出し前にログが出力されました)
```
call func(1,2)
3
```


### 呼び出し前後でログ＋引数や戻り値を変更する場合

* 関数呼び出し時の引数や、戻り値を変更することもできます

```javascript
const proxy = new Proxy(func, {
  apply(target, thisValue, args) {
    console.log(`call ${target.name}(${args})`); // ①呼び出し前ログ
    console.log(`${args} =>`, (args = args.map((value) => value + 1))); // ②引数を変更
    const result = target.apply(thisValue, args); // func()の呼び出し
    console.log(`result: ${result}`); // ③呼び出し後ログ
    return String(result).padStart(3, '0'); // ④戻り値を書き換え
  },
});
```

実行結果

* ①呼び出し前ログ(関数名と引数)
* ②引数を変更 (引数に+1)
* ③呼び出し後ログ ((2,3)を渡したので結果は5)
* ④戻り値を書き換え (0パディングして返す)
```
call add(1,2)
1,2 => [ 2, 3 ]
result: 5
005
```

### 別モジュールに定義された関数にログを追加するProxy

別モジュールで定義された全ての関数に対して、ログ機能を追加する関数`log_proxy`を作ります

まず、import対象のモジュールを用意します
```javascript:api.js
export function add(val1, val2) {
  return val1 + val2;
}
export const strcat = (s1, s2) => s1 + s2;
```

api.jsをimportして、その関数に対してログを追加します

* moduleの関数を列挙して、それぞれの関数に対してProxyを作る

プログラムソース
```javascript
import * as api from './api.js';
/**
 * モジュールに定義された関数の引数と戻り値をログ出力するProxy
 */
const log_proxy = (module) => {
  const proxy_module = {};
  // モジュールに定義された関数、変数を列挙
  for (const key of Object.keys(module)) {
    if (typeof module[key] == 'function') {
      // 関数毎にログ用Proxyを生成する
      const proxy = new Proxy(module[key], {
        apply(target, thisValue, args) {
          console.log(`call ${target.name}(${args})`); // 呼び出し前ログ
          const result = target.apply(thisValue, args);
          console.log(`result: ${result}`); // 呼び出し後ログ
          return result;
        },
      });
      // proxyをまとめたオブジェクトを作成して返す(apiと同じ関数を持つ)
      proxy_module[key] = proxy;
    }
  }
  return proxy_module;
};

// proxyを作成して、呼び出す
const proxy = log_proxy(api);
console.log(proxy.add(1, 2));
console.log(proxy.strcat('val1', 'val2'));

```

実行結果

* 別モジュールで定義された関数に、ログ機能が追加されました
```
call add(1,2)
result: 3
3
call strcat(val1,val2)
result: val1val2
val1val2
```
分類タスクの評価指標

# **Accuracyの欠点**

Accuracy = 正しく分類された数 / 予測の総数

- データセットの不均衡な状況には適さない
    - トレーニングデータセットの中で、特定のクラスのデータが異常に多い場合、モデルは入力データをそのクラスと判断する傾向がある
    - その結果、Accuracyスコアが高くても意味がない
- 偽陽性と偽陰性の区別がつかない
    - モデルが正しくない予測を行った場合、どのような間違いが発生したかを理解するのに役立たない
    - 偽陽性（False Positive）と偽陰性（False Negative）は異なる意味を持ち、異なる対策が必要だが、Accuracyはこれらを区別しない

# 二クラス分類
二分類タスクはデータを二つの相互排他的なカテゴリに分類することを含みます。例えば、医療診断では患者が特定の病気にかかっているかどうかを判断するために使用され、金融分野では取引が詐欺かどうかを検出するために使用されます。また、電子メールシステムでは、スパムメールと通常のメールを区別するために使用されます。

## 1. 予測は以下のConfusion Matrixによって表される

| Actual/Predicted | Positive | Negative |
| --- | --- | --- |
| Positive | TP | FN |
| Negative | FP | TN |
- True Positive (TP)：正のサンプルを正しく予測したもの
- True Negative (TN)：負のサンプルを正しく予測したもの
- False Positive (FP)：負のサンプルを誤って正と予測したもの
- False Negative (FN)：正のサンプルを誤って負と予測したもの

## 2. 二分類タスクの評価指標

- $\text{Accuracy} = \frac{TP + TN}{TP + TN + FP + FN}$
- $\text{Precision} = \frac{TP}{TP + FP}$
- $\text{Recall} = \frac{TP}{TP + FN}$
- $F1\text{-score} = \frac{2 \times \text{Precision} \times \text{Recall}}{\text{Precision} + \text{Recall}}$

Precisionは、**Positive**と予測されたすべてのデータの中で、**実際にPositive**であるデータがどれだけ占めているかを評価する。Recallは、すべての**Positive**データの中で、どれだけのデータが成功裏に**Positive**と予測されたかを評価する。

### 2.1 例

ある会社が新しいスパムメールフィルタリングシステムを開発し、その性能を評価しようとしています。スパムメールをPositive、スパムでないメールをNegativeと定義します。では、どの指標を使って評価すればよいでしょうか？

- Precision：スパムメールと判断されたすべてのメールの中で、実際にスパムであるメールがどれだけ占めているかを評価する
- **Recall**：すべてのスパムメールの中で、どれだけのメールが正しくスパムと検出されたかを評価する
- Acc：検出されたすべてのメールの中で、どれだけ正しい結果が得られたかを評価する

### 2.2 結論

- Recall：False Negative (FN)のコストが非常に高い（結果が非常に深刻な）場合、FNをできるだけ避けたいときには、Recall指標を重視する必要がある
- Precision：False Positive (FP)のコストが非常に高い（結果が非常に深刻な）場合、FPをできるだけ避けたいときには、**Precision**指標を重視する必要がある
    - 例えば、金融詐欺検出システムにおいて、詐欺をPositiveと定義する場合、FPの発生をできるだけ少なくしたい。誤って正当な取引を詐欺と判断することで、顧客の信頼を損ない、不必要な調査コストが発生するためである
- F1-score：PrecisionとRecallの両方を統合した指標

# 多クラス分類
多クラス分類はデータを三つ以上のカテゴリに分類することを含みます。例えば、画像認識では異なる物体の種類を識別するために使われ、テキスト分類では文書を異なるテーマカテゴリに振り分けるため使用されます。

多クラス分類の場合も同様に、出力に基づいてConfusion Matrixを埋めることができ、それぞれのカテゴリに対応するPrecision、Recall、F1-Scoreがあります。しかし、Accuracyはすべてのカテゴリに対して計算される結果です。

| Actual/Predicted | A | B | C |
| --- | --- | --- | --- |
| A | 10 | 20 | 25 |
| B | 2 | 35 | 15 |
| C | 0 | 2 | 30 |

## 評価指標

### 1. Macro-average方法
異なるカテゴリの評価指標（Precision/ Recall/ F1-score）を直接合計して平均を求め、すべてのカテゴリに同じ重みを与える。この方法はすべてのカテゴリを平等に扱うが、稀少なカテゴリに影響を受けやすい
### 2. Weighted-average方法
- この方法では、異なるカテゴリに異なる重みを与える（重みはそのカテゴリの実際の分布割合に基づいて決定される）。各カテゴリを**重みで乗算**してから合計する。この方法は**カテゴリの不均衡**を考慮し、その値は多数派のカテゴリ（majority class）の影響を受けやすい
- トレーニングサンプルの分布に基づいて重みを追加する
### 3. Micro-average方法
- この方法では、各カテゴリのTP、FP、FNを先に合計し、その後、二分類の公式に基づいてPrecision/ Recall/ F1-scoreを計算する

## 例

### 1. Precision, Recall, F1-scoreの計算（カテゴリA）
- Precision = TP / (TP + FP) = 10 / (10 + 2) = 10 / 12 ≈ 0.833
- Recall = TP / (TP + FN) = 10 / (10 + 45) = 10 / 55 ≈ 0.182
- F1-score = 2 * (Precision * Recall) / (Precision + Recall) ≈ 0.3
### 2. Macro-average方法
- Precision (macro) = (0.833 + 0.614 + 0.429) / 3 ≈ 0.625
- Recall (macro) = (0.182 + 0.486 + 0.638) / 3 ≈ 0.435
- F1-score (macro) = (0.3 + 0.543 + 0.514) / 3 ≈ 0.452