OmniAICreator/Qiita-1.07M huggingface dataset:
TiDBの仕組みを詳しく知りたい！ 人向けの公式学習コンテンツ

前回の記事でPingCAPのトレーニングポータルである PingCAP Educationについて説明しました。

https://qiita.com/bohnen/items/df19fa1ef7c9b0adeb1b

今回はPingCAP Educationで受講可能な日本語のコンテンツをご紹介します。
自習形式のハンズオンもついており、動かしながらTiDBを学習することができます。

## TiDB 基本ワークショップ

https://jpn.edu.pingcap.com/catalog/info/id:283

コースカタログから `201.3` で検索すると見つかるかと思います。こちらのワークショップは主にMySQLを現在利用している方向けに、TiDB固有の機能を説明するワークショップです。環境としては TiUP playgroundやTiDB Serverlessを利用するようになっているので、無料で実施することができます。（TiDB Serverlessでは一部実施出来ないコンテンツがあります）

また、ハンズオンで利用するスクリプト類もGitHubで公開されています。

https://github.com/pingcap/tidb-course-201-lab/tree/master?tab=readme-ov-file

内容については、下記のようになっています。

- 演習 1: テスト用にTiDBクラスタを作成する
- 演習 2: TiDB Lightningを使用してCSVファイルからデータをインポートする
- 演習 3: フラッシュバックテーブルとフラッシュバッククエリ
- 演習 4: AUTO_INCREMENTをTiDBで使用する
- 演習 5: AUTO_RANDOMをTiDBで使用する
- 演習 6: グローバル一時テーブル
- 演習 7: オンラインDDL
- 演習 8: CLUSTEREDとNONCLUSTEREDプライマリキー
- 演習 9: パーティションテーブル
- 演習 10: HOTデータストレージとCOLDデータストレージの階層化の実装
- 演習 11: 分析クエリ用のTiFlash
- 演習 12: TiDBサーバーシステム変数の設定
- 演習 13: TiDBのトランザクション隔離レベル
- 演習 14: リソース制御とデータベース統合 (v7.1)
- 演習 15: 悲観的なトランザクションロック
- 演習 16: 楽観的なトランザクションロック

以下、特に試してほしいものについて説明します。

## 演習4,5: AUTO_INCREMENTとAUTO_RANDOM

分散環境でシーケンシャルな番号を採番するのは困難です。そもそも単調に増加するはずの時刻シリアル値ですら各サーバで異なるケースが想定されます。

そのためPKとしてよく利用されるAUTO_INCREMENTも、シングルインスタンスのMySQLとは異なる挙動をすることがありますし、性能的な影響もあります。v6.0以前のTiDBでは、AUTO_INCREMENTの番号が巻き戻ることがあるというものだったので、なおさら違和感がありました。

本演習では単調増加をするAUTO_INCREMENTの指定方法と、TiDB固有の一意番号の採番方法であるAUTO_RANDOMについて実際に試して見るものです。TiDBで実運用を行う方は必須の演習です！

## 演習 11: 分析クエリ用のTiFlash

TiDBではカラムナストレージのTiFlashを使って分析クエリを効率化することができます。TiFlashはオプショナルなストレージとして後から追加でき、追加後テーブルを同期させることでオプティマイザに認識され、以降明示的な指定なしでクエリの実行計画に組み込まれます。

本演習ではTiFlashの基本的な利用方法、実行計画の変化などを確認できます。TiDB Serverlessでは標準でTiFlashが利用できるようになっているのですが、テーブルの同期をさせないと利用されないので、この演習で使い方を学ぶと役立ちます。

## 演習 14: リソース制御とデータベース統合 ※Serverlessでは利用できません

データベースでオンラインの処理とバッチの処理を実行するようなケースは結構あると思います。その際に問題となるのがリソースの取り合いです。バッチが実行されるとオンライン処理に影響が出て困る、というケースはよく聞きます。

TiDBに実装されたリソースコントロールはそういったリソースの制御を行う機能です。オンライン処理とバッチ処理、それぞれが利用するユーザー毎にリソースの利用量を割り当て、その枠内で処理を実行することで他方が必要なリソースを奪わないようにできます。

またこの機能は複数の業務を一つのクラスタに混在させる際にも有効な機能です。是非試してみてください。

:::note 
残念ながらTiDB Serverlessでは提供されない機能になります。(TiDB dedicatedでは利用可能です)
:::
カラーコードの仕組み


# カラーコードってどんな仕組みか、知ってる？

ざっくりその辺の解説について。


# カラーコードや色とは？

基本的に色はRGBの3原色で構成されているというのはご存じかと思います。
赤＋青で紫
赤＋緑で黄
全て合わせると白

みたいな形ですね。

https://tomari.org/main/applets/iro/gen.html

これを16進数(HEX)にしたのがカラーコードとなります。
内訳はこんな感じ。

`#DE5040`は

```
Red = DE
Green = 50
Blue = 40
```
といった形で表現されています。
これらを10進数に変換したものがRGBとなります。

HEXをRGBのコードに変換するとしたらこんなコードで変換できます。

```js
  // rgbを分解する。
  const [r, g, b] = '#de5040'.replace('#', '').match(/.{2}/g);

  // rgbを10進数に変換する。
  const red = parseInt(r, 16);
  const green = parseInt(g, 16);
  const blue = parseInt(b, 16);

  console.log(red, green, blue);
  // red: 222, green: 80, blue:64
```

ちなみにRGBをHEXに変換はこちら👇

```js
const toBase16 = num => {
  const hex = num.toString(16);
  return hex.length === 1 ? `0${hex}` : hex;
}

const toHex = (red, green, blue) => {
  return `#${toBase16(red)}${toBase16(green)}${toBase16(blue)}`;
}

console.log(
  toHex(245, 144, 179) // #F590B3
);
```
red: 245, green: 144, blue:179 `#f590b3`


# 黒と白について

黒と白については最小値、最大値を入力すると表現することが可能です。

黒は`#000000`、白は`#ffffff`で表現が可能です。


# この原則を知ると、こんなことが可能になる。

全ての色をHEXからRGBに変換して、RGBに同じ値を足すと明度を上げることが可能です。

例としてはこんな感じです。

red: 36, green: 54, blue:88 `#243658`
red: 66, green: 84, blue:118 `#425476`
red: 136, green: 154, blue:188 `#889abc`

HTMLなどで張り付けて大きな画面で見てもらうと分かると思います。


~~彩度をさげる方法は最大の値を変更せずに、他の2色を同じ値を足すと変更することができます。~~

<font color="red">こちらは色相も変わってしまうので、コメントもご参照ください！</font>


色の世界が数字で表現できるというのはちょっと夢がないかもしれませんが、色の作り方として参考になるかもしれないので覚えておくといいかもしれないですね！
コードでUINavigationControllerの書き方､UITabBarControllerをルートとしたプロジェクト作成

## はじめに
タブバーからのアプリの立ち上げ方メモ
今回のサンプルリポジトリ

https://github.com/kabikira/SampleTabBar

## できるもの
２つのタブバーで画面きりかえをする。
<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/568cb081-de23-f90f-12a2-2021f0579aa9.png">

<img width="150" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/1dc8d9f5-cd1c-4c12-bc6f-d98d9d933a22.png">



## ストーリーボードを使用しない設定をする
以下記事を参考にしてください。

https://qiita.com/Imael/items/e908aef1e6fc077f29fc

## ViewControllerを２つ作成
下記のようなViewControllerを作成します。
```swift
import UIKit

class HogeVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemRed
    }
}
```
```swift
import UIKit

class FugaVC: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .systemBlue
    }
}
```

## SceneDelegate修正
下記修正を追加します。
```swift
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
            //UIwindowsのアンラップ
            guard let scene = (scene as? UIWindowScene) else { return }
            // window生成
            let window = UIWindow(windowScene: scene)
            // ルートビュー指定
            window.rootViewController = createTabbar()
            // キーウインドウ指定
            window.makeKeyAndVisible()
            // windowインスタンスが解放されないようにパラメータに代入する
            self.window = window

            configureNavigationBar()
        }

    func createHogeNC() -> UINavigationController {
        let hogeVC = HogeVC()
        hogeVC.title = "Hoge"
        hogeVC.tabBarItem = UITabBarItem(tabBarSystemItem: .bookmarks, tag: 0)

        return UINavigationController(rootViewController: hogeVC)

    }

    func createFugaNC() -> UINavigationController {
        let fugaVC = FugaVC()
        fugaVC.title = "Fuga"
        fugaVC.tabBarItem = UITabBarItem(tabBarSystemItem: .downloads, tag: 1)

        return UINavigationController(rootViewController: fugaVC)

    }

    func createTabbar() -> UITabBarController {
        let tabbar = UITabBarController()
        UITabBar.appearance().tintColor = .systemGreen
        tabbar.viewControllers = [createHogeNC(), createFugaNC()]

        return tabbar
    }


    func configureNavigationBar() {
        UINavigationBar.appearance().tintColor = .systemGreen
    }
```

それぞれのタブが、ナビゲーションコントローラを持ち、そのナビゲーションコントローラのは、それぞれビューコントローラーをもつので、
タブバーを　window.rootViewController　に指定しています。

これで完成です。

## デバッグビューヒエラルキー
デバックビューヒエラルキーで
わかりやすくタブ､ナビゲーション､ビューコントローラーの構造を確認できます。

![スクリーンショット 2024-05-15 1.35.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2883687/6572935c-599e-844b-f3d0-be3439458a92.png)

## 参考

https://www.youtube.com/watch?v=JzngncpZLuw
rex0220 項目検証プラグイン チェックボックスによる表示制御（テーブル版）

[項目検証プラグイン](https://qiita.com/rex0220/items/be20fd879f5e1bc9e035)で、チェックボックスによるテーブル内項目の表示制御を行う例です。

# 概要

[項目検証プラグイン](https://qiita.com/rex0220/items/be20fd879f5e1bc9e035)は、入力項目必須チェック、バリデーションチェック、入力抑止、表示制御の処理条件を計算式で指定するプラグインです。

テーブル内項目の交通手段をチェックボックスで選択し、その他をチェック時に文字列項目「その他」を表示します。
「その他」表示時は、必須項目とします。
非表示の場合は、入力エリアが表示されません。

![2024-05-15_08h39_36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/36bb57c1-77a8-38ab-e98c-924bb3d350b6.png)

# 操作例

![2024-05-15_08h43_55.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/5d040a75-df24-004d-777c-56b34030677f.gif)

# 項目検証プラグイン設定

テーブル内項目は、テーブル行単位に処理されます。

![2024-05-15_08h45_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/3faea67e-5b36-bd82-7d38-a3a21437d562.png)


## 「その他」の設定

計算式に同一テーブルの項目を指定すると、同じ行の項目値で計算します。
チェックボックスの選択肢を判定するには、IN 関数を指定します。

- 必須条件：　その他を選択時に必須
    - IN(交通手段,"その他")
- 非表示：　その他が未選択時に非表示
    - NOT(IN(交通手段,"その他"))

# ちょっと便利なプラグインによる詳細画面の表示幅調整

テーブルは、詳細画面で無駄な空白が表示されます。
[ちょっと便利なプラグイン](https://qiita.com/rex0220/items/45883f15ccd34a68b8af)で、詳細画面の表示幅を調整できます。

![2024-05-15_08h50_41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/2506cd86-f41a-b53b-43a4-fcbef64d3173.png)

- 「F70 詳細画面でテーブルの表示幅調整」をチェック

![2024-05-15_08h52_52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/7bd040dd-200e-6638-e48c-6bb23192bfc9.png)
【Suno AIでつくった楽曲】新規ビジネスプロジェクトのためにつくった1960年代後半のクールなモダンジャズ ver.1【動画 2分00秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![101 サムネイル 新規ビジネスプロジェクトのためにつくった1960年代後半のクールなモダンジャズ ver.1【動画 2分00秒】.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/31f40cda-c38d-51e0-8f7b-03acaec259ec.png)




* # 動画URL
    * https://youtu.be/atGVFVFS9hM

<br>

* # 動画タイトル
    * 【Suno AIでつくった楽曲】新規ビジネスプロジェクトのためにつくった1960年代後半のクールなモダンジャズ ver.1【動画 2分00秒】

<br>

* # 動画の説明欄(一部を抜粋)

📅撮影日 = 2024-04-23(火)

Suno AIとは、文章から音楽を生成することができるAI( Text-to-Music-AI )です。
わたしは、2024-04-02(火)に初めてSuno AIで有償プランを契約してから、時々楽曲をつくって遊んでいます。

🎦【Suno AI】文章から音楽を生成するAI( Text-to-Music-AI )で、3分間で2曲、6分間で4曲作りました【試聴可能】1)伴侶の曲 2)税理士の曲【動画 16分11秒】
https://youtu.be/QKfhk4HgQ_g

🎦“Suno AIでつくった楽曲”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe

🎦“効果的にSuno AIを活用するヒント”シリーズ
https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


今回は、Suno AIでつくった曲をMP3で出力してから、動画編集いたしました。
ぜひ聴いてみてください。
そして、普通のビジネスパーソンが、自分が担当するプロジェクトのテーマ曲を3分間でつくれるようになった感動を味わってみてください！

作曲日:
2024-04-03(水)

契約の種類:
Pro Plan

楽曲の正式名称:
Ripple of Transformation ver.1

Suno AI Library URL:
https://bit.ly/suno-Ripple-of-Transformation-ver-1

Instrumental:


---


Suno AIへの指示文章( プロンプト/Prompt ):


🇬🇧English

Please create an inspirational and uplifting song themed around the in-house digital transformation (DX) project currently underway.
The style should be very cool modern jazz from the late 1960s.


🇯🇵日本語訳

社内で進行中のDX推進プロジェクトをテーマとした、インスピレーショナルで前向きな曲を作成してください。
曲調は1960年代後半のモダンジャズ、とてもクールなモダンジャズ。


---


Suno AI 公式URL
https://accounts.suno.ai


---


✓ 🎥この動画と関連が強いわたしの動画 ↙
　・“Suno AIでつくった楽曲”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghMLdiSVqwvSs_Z5y0H4VGOe


　・“効果的にSuno AIを活用するヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghPuaNOVZn-N53wVvsBkeHdI


✓ 🎥Shortened URL for this video | この動画の短縮URL ↙
　https://bit.ly/3W9TcU6
(QA) IBM PowerファームウェアバージョンとHMCコンソールのサポートマトリックス

主題のご質問があり、自身の備忘録もかねて。

## IBM Power H/Wのファームウェアバージョンと管理用HMC H/W, S/Wのサポートマトリックスを調べたい

### ①POWER H/WのファームウェアはIBM Fix Centralから確認・ダウンロードができます。
たとえば、POWER8 8286-42A のファームウェアバージョンはFIX CENTRALでH/W型式を入力して検索できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/423a5a4c-9237-9554-4022-b33cc0e11b09.png)

### ②POWER H/W と HMC S/Wバージョンのサポートマトリックス
***[IBM POWER Code Matrix](https://esupport.ibm.com/customercare/flrt/mtm)*** ページから参照できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/c045ff04-45be-49af-3e58-31d653eb81f5.png)

たとえば、POWER E1050サーバー 9403-MRX とHMC S/Wバージョン互換性リストを表示すると、[下記ページ](https://esupport.ibm.com/customercare/flrt/matrix?domain=mtm=9043-MRX&pkey=pwr)が表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/6afb2827-7848-d03b-5257-7e4a8184ace7.png)

### より道：[IBM POWER Code Matrix](https://esupport.ibm.com/customercare/flrt/mtm) ページにはPOWER H/WとサポートするOSマトリックスリンクもあります
[下記のリンク](https://www.ibm.com/support/pages/system-software-maps)からとんで、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/9dcd770f-4011-2623-18f0-2ede3cc0946e.png)

[下記がインデックスページ](https://www.ibm.com/support/pages/system-software-maps)です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/b1be11f5-8b87-d217-3486-68a27a08d25c.png)

例えばここでIBM iをクリックすると、[下記ページ](https://www.ibm.com/support/pages/node/6023368)にとびます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/be2e0755-066d-3879-1c16-005a3b958b53.png)
POWER H/W型式ごとにサポートするIBM i OSバージョンがリストされています。

### ③特定のHMC S/WバージョンをサポートするHMC H/Wマトリックス
***[②で調べたHMC S/Wバージョンが稼働するH/W,環境のリスト](https://www.ibm.com/support/pages/recommended-fixes-hmc-code-upgrades)がこちらです。 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/eebac618-1f2a-1428-2280-22177a34d740.png)
このページでHMC S/WバージョンとHMC H/W、大まかな管理対象POWER H/Wが確認できます。

## 参考サイト
コチラが大変参考になりました。感謝
[[Power HMC] リンク集](https://qiita.com/mizooot/items/cee15985a042ef529343)

## おまけinfo.
名古屋はおまけ文化なんだそうです
[[Hardware Management Console Support and Downloads]](https://www.ibm.com/support/pages/hardware-management-console-support-and-downloads#v8)
HMCバージョンの確認とダウンロードリンクほか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/9771b641-555a-71fe-9bbf-ff3ec603264c.png)
上記ページから下記のようなHMC S/Wの説明、ダウンロードページへリンクしています。
[[Support for x86, POWER based ppc64 or ppc64le HMC Firmware updates]](https://www.ibm.com/support/pages/node/6538682)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1011394/34dddcb6-7ae7-864f-7659-34baa8d6b6cc.png)
rex0220 項目検証プラグイン チェックボックスによる表示制御

[項目検証プラグイン](https://qiita.com/rex0220/items/be20fd879f5e1bc9e035)で、チェックボックスによる表示制御を行う例です。

# 概要

[項目検証プラグイン](https://qiita.com/rex0220/items/be20fd879f5e1bc9e035)は、入力項目必須チェック、バリデーションチェック、入力抑止、表示制御の処理条件を計算式で指定するプラグインです。

交通手段をチェックボックスで選択し、その他をチェック時に文字列項目「その他」を表示します。
「その他」表示時は、必須項目とします。

![2024-05-15_07h35_42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/032b0c7c-1ce5-55b1-c501-215f61dde022.png)

# 操作例

![2024-05-15_07h39_16.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/b179f233-f794-50a9-dc62-0c63006591bd.gif)

# 項目検証プラグイン設定

![2024-05-15_07h42_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/6a061eed-df68-a66a-57d0-87b5a39146a7.png)

## 「その他」の設定

チェックボックスの選択肢を判定するには、IN 関数を指定します。

- 必須条件：　その他を選択時に必須
    - IN(交通手段,"その他")
- 非表示：　その他が未選択時に非表示
    - NOT(IN(交通手段,"その他"))



# ちょっと便利なプラグインによる詳細画面の表示幅調整

チェックボックスは、詳細画面で無駄な空白が表示されます。
[ちょっと便利なプラグイン](https://qiita.com/rex0220/items/45883f15ccd34a68b8af)で、詳細画面の表示幅を調整できます。

![2024-05-15_08h11_43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/8b3ffb5e-4dea-90e9-f6ce-f2040c87564c.png)

- 「F64 詳細画面でチェックボックスの表示幅調整」をチェック

![2024-05-15_08h17_08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100572/bdc70b01-dbde-e33c-721f-7f5645926b2e.png)
kicadでdxfが読み込みエラー発生した際の備忘録





[1. はじめに](#1-はじめに)
[2. 課題](#2-課題)
[3. 原因](#3-原因)
[4. 対策](#4-対策)
[5. おわりに](#5-おわりに)

# 1. はじめに
# 目次
kicadでdxfが読み込めなかった問題の備忘録。



# 2.課題
Fusion360のスケッチで作成したdxfファイルをkicadにインポートしようしたが、
Items in the imported file could not be handled properly.
Invalid spline definition encountered
が発生。一応読み込めるけど、挙動がおかしくなる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1112433/50e18262-3557-58bd-a595-67bd75050531.png)


# 3.原因
ググって調査。
dxfのバージョン問題だった。
R12じゃないとkicadは処理できない。
https://gitlab.com/kicad/code/kicad/-/issues/11153


# 4.対策
ここで変換。
1日1枚は無料。
https://www.caddare.com/converter/dxf/dxf


# 5.おわりに
結論、感想を書く
実験レポートでよく使うwordの数式モードで便利なショートカット一覧

## 数式モードに切り替えるショートカット
「alt」+「shift」+「-」
## 左揃え、中央揃え、右揃え
これは数式モードとは関係なく使えるショートカット。パワポなどでも使えたはず。

「ctrl」+「L」or「E」or「R」

「L」がleft、「R」がrightで暗記。「E」は知らん。
## 上付き文字（累乗）、下付き文字（添え字）
※以後これらを入力した後に「space」キーを入力することで数式に変換されます

$a^n$→a^n
$a_n$→a_n
## ギリシャ文字（レポートで使いそうなやつ）
| 文字 | キー |
|:-:|:-:|
|$\alpha$|\alpha|
|$\beta$|\beta|
|$\delta$|\delta|
|$\varepsilon$|\varepsilon|
|$\theta$|\theta|
|$\lambda$|\lambda|
|$\mu$|\mu|
|$\pi$|\pi|
|$\rho$|\rho|
|$\sigma$|\sigma|
|$\omega$|\omega|

ほぼそのまんまですね。ちなみに大文字にしたいときは先頭を大文字にして入力します。$\delta$は誤差計算でしぬほど使うので勝手に覚えると思います笑
## その他
| 文字 | キー |
|:-:|:-:|
|$\pm$|\pm|
|$\sqrt x$|\sqrt|
|$\lim_{x->0}x$|\lim_{x->0} ※word上では矢印に変換されます|
|$\int^a_b$|\int^a_b|
|$\ne$|\ne|
|$\therefore$|\therefore|
|$\bar A$|\bar|

個人的によく使った記憶があるやつを掘り出してみました。
## 最後に
　これらを駆使することで私はレポートを１～２時間程度で終わらせていました。最初は見ながらやって、徐々に覚えていくといいと思います。個人的に$\bar A$のショートカットを２年生になってから知ったのを後悔してます。（これもしぬほど使うから）
　ショートカットを丸暗記すればキーボードからマウスに手を移動させる回数が減り、ストレスが軽減されるのでおすすめです。
## 補足（追記）
「\」はキーボードや環境によっては「￥」と表示されることがありますが特に問題はない（はず）です。
激安中華DigiSparkクローンでキーボードジグラーを作った話

Qiita初投稿です。拙い部分は目をつぶっていただけると幸いです・・・
## これは何
1秒に一回、「w」キーを押すデバイスを作りました。
amazonで買ったdigisparkクローンとArduino IDEを用いました。

## 何故作ったのか
私、某PCとかを売るお店で店員をしています。
そのお店の展示用PCでFPSゲームのデモをしているのですが、練習モードで放置しているとホーム画面に戻されてしまい、そこからオンライン対戦につなげる~~不届き者~~お客さんがあとを絶たないのです。ちゃんと注意喚起してるのに・・・。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507266/b123e395-60e6-6add-e13b-8ffb89b05bac.png)
↑こういった練習モードでずっと置いておきたいんです。


まぁ放置判定を回避すればいいじゃない、とマウスジグラーを試したのですが、まぁFPSなんで致命的に合わないんですよ。
AIMがブレるブレるでもう大変。お試しどころの騒ぎじゃなくてこりゃだめだとなりました。
マウスがだめならキーボードのジグラーって無いの？となり、探すもそれっぽい商品がなく。

そういやArduino触りたい欲があるな・・・となると
## 作っちゃえばいいじゃない
ということでキーボードジグラー(?)を自作することにしました。
とりあえずArduino IDEでイジれてちっこくて安いやつを探すことに。

どうもdigisparkなるものがあって、直接USBにぶっ刺せるらしい。
本家はもう手に入らないらしいのでクローン品を購入↓

https://www.amazon.co.jp/gp/product/B0822DYX5X/

![2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507266/6b69a173-11d0-c010-4d16-39ddeefcf8b2.jpeg)


ちっこくてかわいいね。んで1200円だから安いね。

コード等の作成にはこの記事↓と公式docを参考にしました。偉大なる先人の知恵に感謝・・・

https://qiita.com/tonasuzuki/items/6bf479d0e1b6284fd9b0

***
IDEはおなじみの[Arduino IDE](https://www.arduino.cc/en/software "")バージョンは一番新しい2.3.2を使いました。ボードマネージャーとして[ATTinyCore](https://github.com/SpenceKonde/ATTinyCore/ "")を、キーボード用ライブラリとして[Adafruit-Trinket-USB](https://github.com/adafruit/Adafruit-Trinket-USB/ "")の中にあるTrinketKeyboardライブラリを圧縮して追加して使用。

記述したコードはこんな感じ。

```c
#include <TrinketKeyboard.h>
int i;
int setCount = 1000; //待機時間(ms)

void setup() {

  TrinketKeyboard.begin(); //start USB stuff
  
}

void loop() {

  if(i % 10 == 0)
  {
    TrinketKeyboard.poll(); //10ms事に実行しないとバグるらしい
  }
  if(i % setCount == 0)
  {
    //Wを押す。TrinketKeyboard.h内に他キーのコードの記載あります。
    TrinketKeyboard.pressKey(0,KEYCODE_W); 
  }
  if(i % (setCount+20) == 0) //待機時間(20ms)
  {
    TrinketKeyboard.pressKey(0, 0); //キーを全部離す
    i = 0; //カウンタリセット
  }
  
  delay(1);
  i++;
}

```

IDE側の準備としてATTinyCoreを導入する。導入は下記の記事がわかりやすいです！

https://qiita.com/tadfmac/items/a4cdbf915698573ab36d

ATTinyCoreを導入後、ボード選択でATtiny85 (Micronucleus / DigiSpark)を選択して書込。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507266/2facd4f6-9b8f-6498-4d5d-7f33777c3866.png)

実行後、コンソールに

`Please plug in the device (will time out in 60 seconds) ...`

と記載が出たらDigiSparkを接続。すると書込が始まります。

`>> Micronucleus done. Thank you!`

と出たら書込終了です。お疲れ様でした。

## 出来上がりの品

![Animation1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507266/44605854-aef6-a639-1b87-43657ef71a4f.gif)
↑メモ帳での動作　↓Krunker.ioというブラウザFPSでの動作(観戦者モードにて)

![Animation2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3507266/b9c9905a-d15f-1e26-72aa-f735f16b1882.gif)

この様に、1秒に一回、20ミリ秒だけWキーを長押しするデバイスが出来ました。
実際に使う際は3分に一回くらい(1800000ms)に値を設定するといい感じになると思います。

これがあれば店内巡るタイミングで毎回練習モード入れなくて済みそう！やった～～～！

DigiSparkの仕様上、起動時にラグがあるらしいのですが、1秒立たずに立ち上がってくれるので、まぁ許容範囲かなと思います。

次は何作ろうかなぁ。本家Microも買ったので、自作キーボードとか作ってみようかな。

***
以上、キーボードジグラーを作ったお話でした。
Javaで「変数名のつけ方(識別子)」の動作を確認してみた

# 概要

Javaで「変数名のつけ方(識別子)」の動作を確認してみました。
以下のページを参考にしました。

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

# 実装

以下のファイルを作成しました。
```JSample.java
class JSample {
    public static void main(String args[]){
	int sum;
	int 合計;
	double result_2020_06;
	long score;
	long Score;
	long SCORE;
	char c;
	String refreshingBreezeLikeName;
    }
}
```

以下のコマンドを実行しました。
```
$ javac JSample.java
$ java JSample 
```

# まとめ

何かの役に立てばと。
SAM D21 の DAC を Arduino 環境から使う sample

とある素子の実環境下での特性を計測して数値化する案件で、素子の駆動量を sweep するための電圧信号を Adafruit Feather M0 Adalogger の DAC を使って（計測の質はその程度でいい）発生させようと思い、…

誰かやってないかなと検索したけど「これぞ」というものは終ぞ見つけられなかった。

おそらくは analogWrite() なる関数をコンパイルする際に出力先や分解能で PWM を使うか DAC を使うかを分けているのではないかと思っているが、図面は誰が見ても同じものが出来なければならないと思っている私には見る者に依って解釈が変わり得るコードは不安でしかない。

そもそも Arduino 黎明期というか当初のライブラリで歴とした 2 値の飽和出力なのに analogWrite() などという名前をつけたことが間違いだと思っているが、既に分かっている人には関心が薄いが故に明示していないだけなのか DAC を使う人が居ない或いは少なくて検索に引っ掛からないのか、…

ともあれやってみた。 Arduino IDE #1.89 で、書いたコードは次の通り。

```C++
const int dacPin = A0;

void setup() {
    analogWriteResolution(10);
}

void loop() {
    for(int i = 0; i <1024; i++){
        analogWrite(dacPin, i);
        delayMicroseconds(10);
    }
}

```
これで鋸歯状波が出るはずなのでオシロで見たらばその通りなのが出ていました。 やはり勝手に判断している模様。 

<br />
これを「わざわざ記事にすることもない」で済ませるか否かは難しいところ、なんですかねえ ？

今日は このくらいで。
【js/ts】Date型のtoStringでYYYY/MM/DDを取得してみる

## そのままtoString()をすると色々余計な文字がついてくる
※Dateの第二引数(Month)は１月＝０となる。例えば２月なら「1」を設定する。
```javascript
const d = new Date(2024, 1, 10)
console.log(d.toString())
```
```console:結果
Sat Feb 10 2024 00:00:00 GMT+0900 (日本標準時)
```
## よく見かける方法
```javascript
const d = new Date(2024, 1, 10)
const s = `${d.getFullYear()}/${d.getMonth() + 1}/${d.getDate()}`
console.log(s)
```
```console:結果
2024/2/10
```
ただ毎回これを書くのは面倒……

## Date.prototype.toStringを上書きしてみる
```javascript
Date.prototype.toString = function get() {
    return `${this.getFullYear()}/${this.getMonth() + 1}/${this.getDate()}`
}
```
これでインスタンスをtoString()するだけで目的の形式が取得できる。
```javascript
const d1 = new Date(2024, 1, 10)
console.log(d1.toString())
const d2 = new Date(2025, 2, 15)
console.log(d2.toString())
const d3 = new Date(2030, 5, 30)
console.log(d3.toString())
```
```console:結果
2024/2/10
2025/3/15
2030/6/30
```

:::note warn
prototypeの上書きは標準の振る舞いを破壊します。
他の人がソースを見たときに混乱する可能性があるので、実際に使うときは注意しましょう。
:::

:::note warn
ライブラリとの競合が起こる可能性もあります。
使用の際は十分に注意してください。
:::

## おまけ
実は YYYY/MM/DD を取るだけなら **toLocaleDateString()** を使うだけでいい。
```javascript
const d = new Date(2024, 1, 10)
console.log(d.toLocaleDateString())
```
```console:結果
2024/2/10
```
もっと早く気付けば……


# 追記 2024/05/15
コメントにて別の方法を教えてもらいました！
（最近はこれがベストプラクティスっぽい）

## Intl.DateTimeFormat()を使う方法
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat

```javascript
const formatter = new Intl.DateTimeFormat("ja-JP", { dateStyle: "short" });
const date = new Date(2024, 1, 10);
console.log(formatter.format(date));
```
```console:結果
2024/2/10
```

:::note warn
Intl.DateTimeFormatのインスタンスは生成コストが高いという情報も。
なので[MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl/DateTimeFormat/DateTimeFormat)にあるソースを流用すると大変なことになるかも（未検証）
使うときはインスタンス使い回すようにしたほうがいいかもしれない。
```javascript:MDN Web Docs より引用
var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
// toLocaleString without arguments depends on the implementation,
// the default locale, and the default time zone
console.log(new Intl.DateTimeFormat().format(date));
// → "12/19/2012" if run with en-US locale (language) and time zone America/Los_Angeles (UTC-0800)
```
```javascript:こんな感じ
var date = new Date(Date.UTC(2012, 11, 20, 3, 0, 0));
const formatter = new Intl.DateTimeFormat();
console.log(formatter.format(date));
```
:::
暗号化について_RSAとED25519の違い_学習方法

# 暗号化方式、RSAとED25519の違いについての学習方法
## 背景
AWSのEC2インスタンスを生成する際に、キーペアを作成する必要がある。どの場合に、どの暗号化方式を用いるのがベストプラクティスなのかを知りたいと考えたため筆をとった。
## RSA暗号化方式とは
### 参考記事
* [Canon_RSAをはじめとした暗号化の仕組みと方式の違いとは？](https://eset-info.canon-its.jp/malware_info/special/detail/200908.html)
## ED25519暗号化方式とは
### 参考記事
* [Zenn_Symbolで採用している電子署名アルゴリズム「Ed25519」の図解](https://arc.net/l/quote/thnabpzx)
これに関しては複雑すぎるのでひとまず特徴だけ理解するに止めようと思う。面白そうではあるので、時間ができた時に詳しくみてみたい。
## 結局RSA、ED25519どっちを使えば良いか？
### RSAを使うシーン
実装・互換性を重視する場合は、RSA。
### ED25519を使うシーン
パフォーマンスやセキュリティを重視する場合は、ED25519
### 参考記事
[Teleport_Comparing SSH Keys - RSA, DSA, ECDSA, or EdDSA?](https://arc.net/l/quote/pxyuiwxu)
rails7 確認画面の遷移で沼った話

問合せ画面から確認画面を表示させたかったが
沼ったので共有
rails7のこの事象についてQiitaの記事にもなかったので書いてみる

□状況
問合せ画面から確認画面へPOSTするが確認画面に遷移しない
 
 
```
サーバーのログ
Started POST "/contacts/confirm" for ::1 at 2024-05-15 00:22:22 +0900
I, [2024-05-15T00:22:22.287217 #8971]  INFO -- : Processing by ContactsController#confirm as TURBO_STREAM
I, [2024-05-15T00:22:22.292437 #8971]  INFO -- : Completed 400 Bad Request in 5ms (ActiveRecord: 0.0ms | Allocations: 808)
E, [2024-05-15T00:22:22.294219 #8971] ERROR -- :   
ActionController::ParameterMissing (param is missing or the value is empty: contact):
```
<br>
もくもく会で師匠に質問したところturboが影響しているとのこと

参考記事
https://turbo.hotwired.dev/handbook/drive#redirecting-after-a-form-submission
https://stackoverflow.com/questions/70400958/error-form-responses-must-redirect-to-another-location
<br>
□解決
 2つの方法があった
 <br>

 1、viewのform-withに「 data: { turbo: false } 」を指定
 ```
<%= bootstrap_form_with(model: @contact, url: confirm_contacts_path(@contact),
                      local:true, data: { turbo: false }) do |f| %>
 ```

<br>
<br>
2、　下記のようにコントローラーを修正

```
class ContactsController < ApplicationController
  before_action :contact_params, except: :new
  def new
    @contact = Contact.new
  end

  def confirm
    @contact = Contact.new(contact_params)
    if @contact.valid?
     　　render :confirm, status: 303 #ここを修正
    else
      redirect_to action: :new
    end
  end
  
  ...
  
end
```
<br>

解決方法１と２の違い
1　→ URLが変更され画面遷移する
2　→ URLは変更されず画面遷移する

２について
TurboはサーバーがHTTP 303 リダイレクトレスポンスを返すことを期待します
これまでの下記のような方法だとturboはレスポンスが合ってないよ〜
ってことで入力画面に戻ってしまうよう
```
  def confirm
    @contact = Contact.new(contact_params)
    unless @contact.invalid?
     　　render :confirm
    end
  end

```

解決！
turboは便利で強力だけど、クセをつかまないとね！
<br>
確認画面、インスタンスの状態について参考になった記事

https://qiita.com/ngron/items/d55aac6e81a9fb2fe81c
https://qiita.com/shimpex/items/0f9e9f9dfff648631c89
Google SpreadSheetを使って英語勉強用のテキストを作る方法

皆さん、英語の勉強をしていますか。
スマートフォンで同時通訳もできる時代になりましたが、それでも英語スキルは必要だと思うのです。
私はエンジニアの仕事を長くやっていますが、どうしても新しい技術情報やニッチな情報は英語サイトにしか存在しない事が多く、そのたびにGoogle翻訳やら何たら翻訳やらを使用していました。この作業が結構ダルい。そして情けない。
ああ、私は英語も読めないのか、また英語から逃げるのか。もう我慢がなりません。
「そうだ、英語を勉強しよう！」
思いたったが吉日、私は英語の勉強をする為の前準備として、英単語学習支援システムの開発に乗り出したのです・・・。

・・・そんな経緯で、英単語学習用Webサービス「KingWords」が誕生しました。
https://www.kingeng.org

このサービスは、学習用の英語文書を登録すると、自分が覚えていない単語に対して日本語訳を表示してくれる機能があります。しかし英文単位の日本語訳は実装していないのですよね。この機能をWebサービスに実装するにはマシンパワー(GPU)が必要で、ハード面の採算が合わないのです。
英文の直後に日本語翻訳文が、一行ごとに表示できると、英語の勉強が捗るのですが、何とかこれを低コストで実現できないでしょうか？

はい、Googleスプレッドシートならできます。
今回はGoogleスプレッドシートを使って、英語勉強用のテキストを作成してみます。
Googleスプレッドシートは、Google検索画面の右側にあるアプリ集ボタン（9つの点々のアイコン）を押下すると、その中にありますから、立ち上げておいてください。

1．お勉強用の英語テキストを用意します。英語小説でも英語ニュースでも結構ですが、自分が興味のある英文にしましょう。
2．英語テキストをGoogleスプレッドシートのA列に張り付けます。改行ごとにセルがわかれて張り付きます。
3．B列に次の関数を記入してA列の英語文書の最終行までコピーします。
   「=IFERROR(CHAR(10) & GOOGLETRANSLATE(A1, "en", "ja"),"")」

![Googlespredseetによる翻訳.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244452/d55916f1-e209-dfed-c553-10d223fccbd2.jpeg)

4．するとB列に日本語訳が表示されます。日本語訳の最初に改行[CHAR(10)]が入れているのは、後で英文と日本語文の全体をコピーしてペーストした時に、英文と日本語文の行間に改行を入れたい為です。
5．A列とB列を含めてテキスト全体をコピーして、英単語学習WebサービスのKingWords(https://www.kingeng.org )に行き、Update画面に張り付けます。

これで、英語の勉強が捗りそうな教材を準備できました。
Object型。Stringかbyte配列が入る変数のnull、ブランクチェック

```java
        if (Objects.isNull(obj)) {
            return true;
        }

        if (obj instanceof String) {
            String str = (String) obj;
            return str.trim().isEmpty();
        }

        if (obj instanceof byte[]) {
            return ((byte[]) obj).length == 0;
        }
```
【Flutter】PlatformException(Unexpected security result code, Code: -25299, Message: The specified item already exists in the keychain., -25299, null)

# なんかiOSだとエラーがでてくるんだけど？
Androidの方ではうまく動いていたのに、iOSの方ではうまく動かなくなった。
下のようなエラーが```secureStorage.write(Key:key, value,value);```のところで出てきて解決に時間がかかったので備忘録として残しておく。
```
PlatformException(Unexpected security result code, Code: -25299, Message: The specified item already exists in the keychain., -25299, null)
```

# エラーの調査と解決策
まったく同じエラーの内容がGitHubの[issue](https://github.com/mogol/flutter_secure_storage/issues/711)に上がっていた。
ただ、ここの内容では、インスタンスの初期化とwriteを呼び出すところを分けるとうまくいったよと書かれているのみだった。
はぁ...詰んだ...と思って、あきらめそうになったが、なんだかんだ、ブレークポイントを置いて、一行ずつ実行して原因を調査していたら、「あれ？writeが通ったぞ？」ってなりました。
つまり、通常の実行だとエラーがでるが、一行ずつ実行すれば正常に動作するこということが分かりました。ここから推測するに非同期処理がなんか悪さしてるんじゃね？とコードを見返してみたところ、writeが非同期処理で大量に呼ばれていました。ほんとはいろいろなところにちりばめられていましたが、分かりやすくかくと以下のようなコードになっていました。
```
secureStorage.write(Key: key, Value: value);
...何らかの処理...
secureStorage.write(Key: key, Value: value);
...何らかの処理...
secureStorage.write(Key: key, Value: value);
...何らかの処理...
await secureStorage.write(Key: key, Value: value);
```
つまり、awaitをつけていないsecureStorageを同じkeyに対して、何回も呼び出しているようなコードになっていました...(汗）。自分の場合は、この上の方のsecureStorageは完全に不要な処理であったため、余分なところをすべて削除し、必要なsecureStorageを1回のみ呼び出すように修正しました。
```
...何らかの処理
await secureStorage.write(Key: key, Value: value);
```
すると、正常に動くようになりました。
まとめると、非同期にsecureStorage.write()を何回も呼び出していたため、同時にアクセスが発生したりしてエラーがでていたのではないかと推測しています。なので、解決には、非同期に何回も呼び出してしまっていないかチェックすると解決できるかもしれません。
無料枠の充実 - OpenAI Spring Update でGPT4oに隠れて発表されていた嬉しいこと

https://openai.com/index/gpt-4o-and-more-tools-to-chatgpt-free/

2024/05/15 追記
実際に使用できた部分を更新しました

## Introducing GPT-4o and more tools to ChatGPT free users

つまり無料で使える機能が増えます。（！？）

> When using GPT-4o, ChatGPT Free users will now have access to features such as:
>
> - Experience GPT-4 level intelligence 
> - Get responses(opens in a new window) from both the model and the web  
Analyze data(opens in a new window) and create charts 
> - Chat about photos you take
> - Upload files(opens in a new window) for assistance summarizing, writing or analyzing
> - Discover and use GPTs and the GPT Store
> - Build a more helpful experience with Memory

### 日本語で

どうやらGPT4oを使う時に無料枠でも有料枠で使えていた機能にアクセスできるらしいです

- **GPT-4レベルの知能を体験**  
まあこれはその通りでしょう
なんなら速いし、ChatbotArenaの戦績はGPT4を超えていた

- **モデルとウェブからの応答を取得**  
ハルシネーション（幻覚）対策が無料枠でもあるのはうれしい
ようやくですかい（わーい
追記: 検索するよう指示すればbingが動きました

- **データの分析とチャートの作成**  
データの可視化は地味に嬉しい
GPTsであった機能が無料に出てくる嬉しみ
ビジネス系ではより重宝するのでは

- **撮影した写真についてのチャット**  
GPT4oのVision機能にはアクセスできる
後述のGPTsと合わせて効果を発揮しそう
何よりGPT4oのVision機能は前より良くなっていそうなので期待！
追記: これももう使えます（アプリ版で確認済み）

- **ファイルのアップロードと支援**  
128kコンテキストトークンだからね
（無料枠の実際の制限がそこまで大きいかは不明

- **GPTsとGPTストアの発見と利用**  
発見と利用なので、作成はできないってところが有料プランとの違いかな
無料で使ってくれる人が増える分ストアも活発になりそう
追記: もう使えたので見てみたらこの認識で正しそうです

- **メモリ機能によるより便利な体験**  
メモリも使えちゃうんだ、、、
大盤振る舞いだ

嬉しい機能しかねえなあ！！

## 一応の懸念
その分制限厳しくなったりするのだろうか
軽いとはいえGPT3.5よりは重いモデルだろうし（APIの料金的に）
有料プランのレートリミットが３時間に８０回だから、これよりは絶対少なくなる
レート引っかかるまではGPT4o＋付随する拡張機能が使えて、超えるとGPT3.5に切り替わる感じかな

追記: ここ3時間で10回くらい使ったら「23分後復活するよー」って出て3.5に切り替わる旨が表示されました。いつまで待てば良いのかわかるのは安心ですね

いや無料で一部だけ公開されてるだけでめっちゃうれしいに決まってる！！！
GPT-4o のインパクト

# GPT-4o
GPT-4oはGPT-4およびGPT-4 Turboに続く新しいバージョンで、GPT-4の次の大きなアップデートで，誰もが無料で使用でき、以前よりも速く、運用コストも安いモデルです。直感的に感じられるのは、反応速度が速くなったが創造性や正確性の面でGPT-4と比べてどのような向上があるかは、さらに体感する必要があると思います。

![截屏2024-05-15 0.14.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1006814/34ab2b3c-8040-8ffb-6030-c5500a61b721.png)

# GPT-4oの突破点

発表会で印象に残ったポイントは次の通りです：

- GPT-4oはネイティブのマルチモーダル大規模モデルで、テキスト、音声、画像、動画をサポートし、推論速度が速いです。
    - GPT-4の音声対話の実現方法（Whisper → LLM → TTS）と比較すると、ネイティブマルチモーダルはGPT-4oの推論速度が速いことを意味します。
- ChatGPTアカウントを持っている人はGPT-4oを無料で使用できます！（もちろん、有料版と比べて制限があります。）
- ChatGPTのデスクトップバージョンに期待。実際の作業効率の向上が見込まれています。
    - デモでは、デスクトップ画面をリアルタイムでChatGPTデスクトップアプリに共有し、音声でスムーズに対話できました。
    - GPT-4oの音声生成速度は、人間を上回るほど速かったです。
- 異なる口調や会話速度、ユーザーの感情認識が〇〇に関するアプリに取って代わる可能性がある：
    - 翻訳ソフト
    - テキストの音声化
    - 感情的なアプリ・バーチャル恋人
    - … など。

# ビジネス

リアルタイムの応答と分析、マルチモーダル入出力、およびカスタマイズされた個別対応が必要で、業界の「壁」が低いアプリケーションのシナリオが実現されるでしょう。
- モデルアーキテクチャ自体と異なるモデルを結合してマルチモーダルを実現するのには本質的な違いがあります。
- 視覚障害者向けのインタラクション
- コールセンター
- AIエージェント
- 健康モニター

やはり重要なのはドメイン知識とデータかと思っています。
フィボナッチ数列の計算: 再帰 vs キャッシュ

## はじめに
フィボナッチ数列を計算する方法はいくつかありますが、その中でも再帰的アプローチとキャッシュ（メモ化）を使ったアプローチが一般的です。それぞれの方法には利点と欠点があります。本記事では、これらの方法について違いを明らかにします。

## フィボナッチ数列とは？
フィボナッチ数列は、次のように定義される一連の数です。

F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2) for n >= 2
この数列は、0から始まり、次の数が前の2つの数の合計となります。

## 再帰的アプローチ
再帰的アプローチでは、フィボナッチ数列を再帰的に計算します。この方法はシンプルで理解しやすいですが、計算効率が悪い場合があります。

#### コード例
```ts
function fibonacci(n: number): number {
    if (n <= 1) {
        return n;
    }
    return fibonacci(n - 1) + fibonacci(n - 2);
}
```
#### メリット
- **シンプル**: コードが簡潔で理解しやすい。
- **自然な表現**: フィボナッチ数列の定義をそのままコードに反映している。
#### デメリット
- **計算効率が悪い**: 同じ計算が何度も繰り返されるため、時間複雑度が指数関数的に増加します。具体的には、時間複雑度は O(2^n) となります。
- **スタックオーバーフローのリスク**: 再帰の深さが大きくなると、スタックオーバーフローが発生するリスクがあります。
## キャッシュを使ったアプローチ
キャッシュを使ったアプローチ（メモ化）は、計算済みの結果を保存し、重複する計算を避けることで効率を向上させます。

#### コード例
```ts
function fibonacci(n: number): number {
    let cache: number[] = new Array(n + 1).fill(0);

    function fib_memo(n: number): number {
        if (n <= 1) {
            return n;
        }
        if (cache[n] !== 0) {
            return cache[n];
        }
        cache[n] = fib_memo(n - 1) + fib_memo(n - 2);
        return cache[n];
    }

    return fib_memo(n);
}
```
#### メリット
- **計算効率が高い**: 各計算結果をキャッシュに保存することで、重複する計算を避け、時間複雑度を O(n) に改善します。
- **再帰の利点を維持**: 再帰的な構造を保ちながら、効率を大幅に向上させます。
#### デメリット
- **キャッシュの管理**: キャッシュの初期化と管理が必要となり、コードが複雑になります。
- **メモリ使用量**: キャッシュを保存するための追加メモリが必要です。
## まとめ
再帰的アプローチとキャッシュを使ったアプローチの違いは、主に計算効率とメモリ使用量にあります。再帰的アプローチはシンプルで直感的ですが、計算効率が悪く、スタックオーバーフローのリスクがあります。一方、キャッシュを使ったアプローチは計算効率が高く、時間複雑度を大幅に改善できますが、キャッシュの管理とメモリ使用量が増加します。

フィボナッチ数列を計算する際には、計算量が少ない場合は再帰的アプローチを、計算量が多い場合はキャッシュを使ったアプローチを選択することが推奨されます。どちらの方法を選ぶかは、具体的な用途と制約条件に依存します。
Google ColabでTimesFMを動かして予測してみた

## 概要

最近の記事を見ると、Zero-Shotで時系列予測ができるTimesFMと呼ばれるものが公開されていました。

https://research.google/blog/a-decoder-only-foundation-model-for-time-series-forecasting/

Githubのリポジトリはこちら：

https://github.com/google-research/timesfm

時系列予測というとベイズなどを用いて泥臭いことをやったりしないとですが、こちらはtransformerのデコーダ部分のみを用いてGoogle TrendsやWikipedia Pageviewなどの膨大なデータ(100 billion time point)で学習を実施したものを公開されています。パラメータも200Mで、GPT-3やLLama-2などと比較すると軽量なモデルであり、チューニングすることなく高度な予測をすることが可能であると書かれています。

時系列予測と言われるとベイズなどが浮かんできますが、面倒臭いのでサクッと予測できるのは比較対象としても悪くない気もしています。今回は、国内企業物価指数] 総平均（前年比）の2000年から2024年3月までの月次データを用いて、2024年4月以降から32ヶ月先までの予測を実施してみました。今回はGoogle Colabで環境を構築して予測をしています。

※まともなテックブログを一年以上書いてない人がウォーミングアップで書いてるので、温かい目で見守ってくれたら幸いです。

## データセットについて

下記の日本銀行の時系列データ検索サイトの「物価」と書かれている箇所から国内企業物価指数] 総平均（前年比）および[企業向けサービス価格指数] 総平均（除く国際運輸）（前年比)のcsvファイルが月次データとしてダウンロードできます。

https://www.stat-search.boj.or.jp/#

## 環境構築について

Google Colabを用いて、poetryでTimesFMに必要なパッケージをインストールしながら仮想環境を構築して動かしました。Dockerで構築しようか悩みましたが、サクッと試せることも加味してColabで取り組んでみました。

また、TimesFMでモデルを呼び出す際のパラメータは適当です。時間ができたら調べて追記するかもしれません。

poetryのpyproject.tomlは下記を利用しています。TimesFMのライブラリ関係を参考にして作成しました。

```
[tool.poetry]
name = "timesfm-package"
version = "0.1.0"
description = ""
authors = ["bamboo-taro"]
license = "MIT"
readme = "README.md"

[tool.poetry.dependencies]
python = ">=3.10,<3.11"
huggingface-hub = {extras = ["cli"], version = "^0.23.0"}
utilsforecast = "^0.1.9"
praxis = "^1.4.0"
lingvo = "0.12.7"
paxml = "^1.4.0"
einshape = "^1.0"
jax = "0.4.26"
jaxlib = "0.4.26"
numpy = "^1.26.4"
pandas = "^2.2.2"
timesfm = {git = "https://github.com/google-research/timesfm.git"}

[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"

```

ノートブックはワーキングディレクトリに配置して、pyproject.tomlは

## 成果物
Gistとしてアップロードしています。

https://gist.github.com/bamboo-nova/5d11a732bc049f2493b37478e83c5040

今後の励みになるので、starして下さると嬉しいです。

## 結果

国内企業物価指数] 総平均（前年比）の32ヶ月先まで予測してみましたが、来年の夏頃までは物価は上がり続ける結果が出てきました。物価が下がって欲しいなぁ(個人的な感想)

![スクリーンショット 2024-05-14 23.36.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580487/0bfad1d2-af2f-2c2b-4078-13855a6aac5f.png)

## まとめ
今回はTimesFMをサクッとColabで動かして予測してみました。金融や広告などの様々な分野で使えると思うので、取り敢えず手元のデータでサクッと予測してみるのには有用だと思います。

Google Trendsを学習データに用いてるくらいなので、メディアのトレンド予測とかで時系列データが限られてる時にパッと出してみるのに使える気もしました。機械学習での特徴量としてドメインのものと掛け合わせても面白いかもしれませんね。
時系列データの特徴量の考察とモデルの話

作ったプログラム↓

https://github.com/NTanaka1994/omoitsuki/blob/master/Untitled1.ipynb

最近転職活動をしていてLightGBMを使う企業みたいで自分も復習に使って見たわけで最近LightGBMを使ってはアウトプットでQiitaに記事を書いていた訳ですが、今回はアウトプットの延長線でSIGNATEをやってみました。

内容はアップル引っ越し需要予測になります。

https://signate.jp/competitions/269

ただこのデータを見ていて思ったのがパネルデータだったということです。
統計データには
- クロスセクションデータ
普通の多変量データ
- 時系列データ
時系列に対しての目的変数があるデータ
- パネルデータ
多変量の時系列データ

があります。
ここでパネルデータであることが分かった事から特徴量を増やすことにしました。
具体的には年月日が最初にあったので変数に「year」「month」「day」を付けます。実際引っ越しにはシーズンが有ったり月のいつに引っ越すかの傾向があると聞きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/2aa314b8-c2bb-0c29-0a3c-a23837574eb6.png)



実際実質賃金のデータ一つ見ても例えば月をダミー変数にすることで重回帰分析でも一直線だけで予測しなくてすみます。

https://github.com/NTanaka1994/DataAnalysis/blob/main/%E6%99%82%E7%B3%BB%E5%88%97%E5%88%86%E8%A7%A3/chronological_linear.ipynb

![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2782889/b29804a9-6614-0334-592d-cf0930e0d1b5.png)

例えばこのグラフのように時系列を数値変換したりするだけでは緑の線のようになりますが、ダミー変数を使うことで月ごとの月の特徴を反映することができます。(このグラフに使っている予測モデルは重回帰分析)。

補足ですが、因子選定を一切せず今回この時系列データの特徴量化するだけでMAEはどうやら11.19478905030105だそうでした。
順位としては上位になれたとは言えませんしむしろ下位ですが、時系列系が苦手な自分が初めてやった予測では割と思っていたより良かったです。

ただ課題として、このデータはテストデータと訓練データでは使う年が違うためLightGBMが実際にはうまく機能しない事が分かります。
そこで恐らくこの手法を使うなら多層パーセプトロン(ニューラルネットワーク)を使った方が良いのかもしれません。ただしその時は全ての変数をちゃんと標準化しないといけませんが・・・

# まとめ
特徴量の考え方は恐らく妥当だったと思うけど、多分使うモデルは違う方が良いと思う。
【React】キャレットを文末に移動する方法

以下のように記述することでフォーカスした際にキャレットが文末に移動します。

```tsx
// ...
  <textarea
    onFocus={(ev) => {
      const len = ev.currentTarget.value.length
      ev.currentTarget.setSelectionRange(len, len)
    }}
  />
//...

```
Nuxt3アプリをLambdaにデプロイする方法

- nuxt v3.11
- ServerlessFramework v3.38.0

## はじめに
Nuxt3で作成したアプリは比較的簡単にLambdaにデプロイすることができます。
ここではデプロイする方法の一例を紹介します。

## Nuxt3 ビルド設定

`nuxt.config.ts`にAWS Lambda用のビルド設定を追加します。

```typescript
export default defineNuxtConfig({
  // ...
  nitro: {
    preset: 'aws-lambda',
    serveStatic: true,
  }
})
```

静的ファイルをS３などに配置する場合は`serveStatic`を`false`にします。

## Serverless Framework
デプロイにはServerlessFrameworkを使用します。

### インストール
``` shell
npm install -g serverless
```

### AWS IAM ユーザーを設定
serverlessがAWSにアクセスするための設定します。

1. serverless 用 IAM ユーザー作成
2. `AdministratorAccess`ポリシーを設定（アプリに合わせて適切に変更）
3. アクセスキー作成
4. serverless にクレデンシャル情報を設定

```
serverless config credentials --provider aws --key [アクセスキーID] --secret [シークレットアクセスキー] --profile [任意のプロファイル名]
```

### デプロイ設定ファイル

`serverless.yml`を作成します。
↓は一例です。

``` yaml
service: [サービス名]
frameworkVersion: '3'

provider:
  runtime: nodejs20.x
  name: aws
  stage: dev
  region: ap-northeast-1
  profile: [先ほど指定したプロファイル名]

package:
  patterns:
    - "!**/**"
    - ".output/server/**"
  excludeDevDependencies: true
  individually: true

functions:
  NuxtSsrCore:
    handler: '.output/server/index.handler'
    url: true # Lambda の関数URLを作成
```
### ビルド & デプロイ

```bash
npm run build
sls deploy --verbose
```
以上でLambdaへのデプロイまではできました。
AWSコンソールから作成したLambda関数のURLにアクセスするとアプリが確認できるかと思います。

ここで作成したAWSサービスは簡単に削除もできます。
### サービスの削除
``` bash
sls remove
```
Gitでの変更取り消し：revert の使い方

# Gitの `git revert` コマンドを詳しく解説

Gitで間違った変更を取り消す方法として、`git revert` コマンドは非常に便利です。このコマンドは選択したコミットを効果的に「打ち消す」新しいコミットを作成し、リモートリポジトリにプッシュされた変更を安全に取り消すことができます。以下にその詳細と、使用方法を解説します。

## 打ち消したいコミットハッシュの取得方法

コミットハッシュは、Gitの各コミットを一意に識別するIDです。これを取得するには、以下のコマンドを使用します。

```bash
git log
```

このコマンドを実行すると、リポジトリのコミット履歴が表示され、各コミットの詳細とともにハッシュも表示されます。例えば以下のような出力が得られます。

```bash
commit 1a2b3c4d5e6f7g8h9i0j (HEAD -> master, origin/master, origin/HEAD)
Author: Your Name <your.email@example.com>
Date:   Mon Sep 14 16:00:49 2020 -0400

    Fix typo in the introduction

commit 123456789abcdef (feature-branch)
Author: Another Dev <another.dev@example.com>
Date:   Sun Sep 13 15:50:29 2020 -0400

    Add new feature
```

:::note info
ハッシュ値(1a2b3c4d5e6f7g8h9i0j)が指す具体的な変更のイメージとしては、例えば以下のようなこと

ドキュメントの誤字訂正にて、READMEファイルやオンラインヘルプドキュメントなど、文書の導入部に誤字脱字があった場合、それを修正して更新したコミット。など

:::

## git revert の使用例

誤って追加したコミットを取り消す場合、そのコミットのハッシュを指定して以下のように git revert を実行します。

```bash
git revert 1a2b3c4d5e6f7g8h9i0j
```
このコマンドを実行すると、エディタが開き、新しいコミットメッセージを入力することができます。デフォルトのメッセージは次のようになります。

```Bash
Revert "Fix typo in the introduction"

This reverts commit 1a2b3c4d5e6f7g8h9i0j.
```

変更を保存してエディタを閉じると、新しい「取り消し」コミットがリポジトリに追加されます。

git revert は、リモートリポジトリにプッシュされた後でも安全に使用できる方法であり、他の共同作業者に影響を与えることなく、過去の変更を効果的に取り消すことができます。このコマンドを使いこなせば、Gitでの誤操作も怖くありません。



## git revert後のコミットイメージ

```bash
commit 3c4d5e6f7g8h9i0j2k3l4m5n6o7p (HEAD -> master)
Author: Your Name <your.email@example.com>
Date:   Wed Oct 7 16:00:49 2020 -0400

    Revert "Fix typo in the introduction"

    This reverts commit 1a2b3c4d5e6f7g8h9i0j.

commit 1a2b3c4d5e6f7g8h9i0j (origin/master, origin/HEAD)
Author: Your Name <your.email@example.com>
Date:   Mon Sep 14 16:00:49 2020 -0400

    Fix typo in the introduction

commit abcdef1234567890abcdef (feature-branch)
Author: Another Dev <another.dev@example.com>
Date:   Sun Sep 13 15:50:29 2020 -0400

    Add new feature
```

誤ったコミット (1a2b3c4d5e6f7g8h9i0j) は依然として履歴に存在しますが、その影響は取り消しコミットによって無効化されています。

```mermaid
flowchart TD;
    A[元のコミット abcdef1234567890abcdef] -->|エラー修正のためのコミット| B[誤ったコミット 1a2b3c4d5e6f7g8h9i0j]
    B -->|git revertによる取り消し| C[新しい取り消しコミット 3c4d5e6f7g8h9i0j2k3l4m5n6o7p]
    style A fill:#f9f,stroke:#333,stroke-width:2px
    style B fill:#f96,stroke:#333,stroke-width:2px
    style C fill:#9f9,stroke:#333,stroke-width:2px

```
Ghidraに踊らされたのでポインタを復習しよう

身内に向けてhackmdで書いた記事を移植

CTFをやってるとReverseの問題でデコンパイラのGhidraを使う機会があります。あるプログラムを読ませたときにこんなコードが返ってきました
```c
local_28 = 0x6e34637b67616c66;
local_20 = 0x594f5345485f7427;
for (j = 0; j < 16; j = j + 1) {
      if (param_1[j] != *(char *)((long)&local_28 + (long)j)) {
```
星だらけで認識しにくい...
普段Cだのポインタを使う言語で開発しないのでちょっとすらすら読むには復習が必要そうです

# &演算子
&てなんだっけと思ってググったらどうやら**アドレス取得演算子**らしいです。
すなわち`&local_28`てのは`local_28`変数の開始アドレスを返すわけだな。そんでもってそれをlong型にキャストしていると。

# ポインタとデリファレンス
思い出してきたけど一応メモっておきましょう。
```c
int *a
```
ていうのは単純にポインタだったはずです。
逆に、
```c
*a
```
みたいなのはポインタの指すメモリの実値を取得するやつだったはず。これはデリファレンスというらしい。

# つまり？
```c
local_28 = 0x6e34637b67616c66;
local_20 = 0x594f5345485f7427;
for (j = 0; j < 16; j = j + 1) {
      if (param_1[j] != *(char *)((long)&local_28 + (long)j)) {
```
こいつについて考え直しましょう。
アセンブラを読む限り`local_28`と`local_20`はどうやらスタック上で連続しているようです。
よんでいくと...
1. `local_28`のアドレスを取得
2. アドレスに対してfor文で1ずつ加算
3. 1, 2で得られたアドレスをchar型のポインタとしてキャスト
4. キャストしてできたポインタをデシリアライズ
これによって`local_28`から16バイト分を1バイトずつ取り出してcharとして`param_1`と比較しているようです。

たしかにアセンブラをそのまま起こすとこんなかんじになっちゃいそう

# ポインタと配列
今回の復習でポインタと配列の関係も理解しました。
`a[1]`みたいなのは
```c
*((long)&a + (long) 型のサイズ*index)
```
みたいな感じであらわせるわけですね
pythonでelasticsearchのindexの削除

```python
# %%
from elasticsearch import Elasticsearch

username = 'admin'
passwrod = '<INPUT YOUR ADMIN PASSWORD>'
host = 'https://%s:%s@<INPUT YOUR HOSTNAME>:<INPUT YOUR PORT NUMBER>' % (username, passwrod)
print(host)
client = Elasticsearch(hosts=host, ca_certs='INPUT YOUR CARTIFICATE FILE PATH')
# %%
client.cat.indices(index='*', h='index').splitlines()
# %%
client.indices.delete(index='test2')
# %%
client.close()
```

Elasticsearch、すごい使いやすいかも…
PowerAutomate: SharePoint 内でファイルサイズで抽出する by Filter Query

# 背景

FilterQuery 備忘録シリーズ

ファイルサイズでフィルターしたいんだけど、出来ない！！って時の対処法

Get files (properties only) の 取得結果にはそれっぽいものはない。
Get file metadata であれば、以下のようにサイズがあるので、それで行いたい

# 概要

FileSizeDisplay で指定してやれば OK

```text: ファイルサイズで絞る例
FileSizeDisplay ge 30040
```
実際のファイルに合わせて、30040 という値にしただけで、特に意味なし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/eaad154a-4b66-75d9-68c5-a92808e61e13.png)

## 利用例

指定サイズ以上のファイルが取得出来ているのが分かる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/b5c2dd36-1a6a-3a59-2905-ba091c194eb2.png)

# あとがき

そろそろ気力付きそう

# keyword

How to extract files using a filter query based on file size in SharePoint.
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-05-14 230605.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/94e615c8-ebf1-ecc8-3ec6-0f0a7d0c96fe.png)


####  1. Event Bridge
2つのEvent Bridgeのルールを作成しました。
1つ目はEC2を起動ます。その5分後に2つ目のルールによりEC2内に保存されているシェルスクリプトが実行されます。

![スクリーンショット 2024-05-14 231630.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/8df47362-4e12-6229-b6f9-798940dd45ce.png)


#### 2. EC2
最初はLambdaの使用を考えましたが、スクレイピングするのに1時間ほどかかるのでEC2を選択しました。このEC2内ではまずスクレイピング、前処理、賃料推定が行われます。
#### スクレイピングする情報
![スクリーンショット 2024-05-14 223728.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/dc54d981-b891-1bd8-84cb-9faf68228678.png)

**対象**
1. 北千住
2. 三軒茶屋
3. 世田谷
4. 梅島
5. 久米川
6. 府中
7. 調布
8. 仙川    

賃料推定の結果、実際の賃料<予測賃料となった物件のURLをLINEアカウントに通知させます。

![notify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/1c19b646-3a48-feaa-52c2-51063fa44431.png)


#### 3. S3
EC2から送信されたparquetファイルを保存します。

![スクリーンショット 2024-05-14 231859.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/4d25ded7-417e-8857-c0de-636cbe3c2085.png)


#### 4. ATHENA
S3に保存されたparquetファイルに対してクエリを実行することができます。

![スクリーンショット 2024-05-14 232116.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2664262/23a19e62-d0ee-3bb4-7d6a-7768b19359a2.png)

 # 次回の記事
 スクレイピングしたデータを使って賃料予測モデルを作成します。
【覚書】Lucene.NETのKuromojiでUniDic辞書を使うのは無理そう

## 思いつくままに経緯を記す

Lucene.NETのKuromojiを使って形態素解析を行い応用的なことをやっていたのだが、使用している辞書がIPAdicであることに気づき、比較した結果UniDicが用途的にも良さそうということで切り替えてみようとした。

- [Lucene.Net Namespace Lucene.Net.Analysis.Ja.Dict](https://lucenenet.apache.org/docs/4.8.0-beta00016/api/analysis-kuromoji/Lucene.Net.Analysis.Ja.Dict.html)
    - マニュアルに `lucene-cli.exe analysis kuromoji-build-dictionary unidic` によってUniDic辞書をKuromoji用にビルドすれば良いという記述あり
- [UniDic](https://clrd.ninjal.ac.jp/unidic/back_number.html#unidic_cwj)
    - UniDic公式から最新の「unidic-cwj-202302_full.zip」をDLしてビルドしてみた
        - `lucene-cli.exe analysis kuromoji-build-dictionary unidic <input dir> <output dir> -e UTF-8`
    - kuromoji-dataフォルダ内に*.datファイル一式をコピーして動作確認
        - まだCLIも無いクラスライブラリだったためxUnitによるテストケースフォルダにkuromoji-dataフォルダを配置
    - ビルドはできるが動かない
- [OSDN IPAdic legacy](https://ja.osdn.net/projects/ipadic/releases/)
    - 比較対照としてipadic-2.7.0.tar.gzをDLしてきてビルドしてみた
        - `lucene-cli.exe analysis kuromoji-build-dictionary ipadic <input dir> <output dir>`
    - IPAdicの場合ビルドできるしちゃんと動作した
- [Apache LuceneのKuromojiのUniDicビルド対応パッチについて](https://blog.johtani.info/blog/2019/12/04/about-lucene-4056/)
    - いろいろググってる（死語）うちにたどり着く。多謝
    - こちらの情報を参考に、forkしたlucenenetリポジトリに対して[ほぼ同じコード修正を行った](https://github.com/aki426/lucenenet/commit/f36605660e10cbf913800385a49501d70ba898b9)
    - lucene-cli.exeをビルドし、生成された*.defファイル一式をkuromoji-dataフォルダへコピーして動作させてみたが動かない

なお、xUnitのテストケースにおけるエラーは次のようなもの。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46637/a7e9695f-a96c-3677-e51c-f010d8439841.png)

IncrementTokneメソッド実行時にSystem.IndexOutOfRangeExceptionが投げられるが一体これがどこからのものなのか不明。

ちなみに、IPAdicとUniDicのcsvファイルを比較してみると、IPAdicはWordCostが負の値になることは無いようだったが、UniDicの場合負の値を取るようだ。
これが原因かと思いコードを追ってみたがどうもよくわからない。Kuromojiの内部でdefファイル生成・読み込み時にByteBufferを使っているが、WordCostはshortまたはInt16で読み書きされているので負の値でも良さそうだ。
ということはKuromojiの形態素解析ロジック部分がすでにUniDicに対応できていない可能性がある。

SudachiはUniDicをベースにした辞書を使っているということなので、SudachiをC#で非公式実装して使うという方法もあるかもしれない。思いつきだが、まあやってやれないこともないか……。

- [Solr9のkuromojiでUniDic2.1.2を使う](https://zenn.dev/fjnkt98/articles/9ea3c5f60fc399)
    - なお、JAVA版のLuceneのKuromojiではUniDicのビルドも可能らしい。しかしこの記事で用いられているUniDic2.1.2はすでにUniDic公式が配布をやめてしまったようで、入手できなかった
    - 仕方ないので最も古い2.2.0をDLしてビルドしてみたがやはり動作しなかった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/46637/ce4ed923-132a-42a1-9cbc-49d0d37c6843.png)

- [Lucene Kuromoji のコードを読む会 （辞書ビルダー編）](https://speakerdeck.com/mocobeta/lucene-kuromoji-nokodowodu-muhui-ci-shu-birudabian)
    - なおこちらのスライドも非常に参考になった。多謝その２
    - Kuromojiの実装もさることながら、そもそもIPAdicもUniDicもエントリの意味がわからなかったのでこのスライドに書かれていることを手掛かりにデータの具体例を引きながら確認した

ちなみにこれを書きながらUniDicのデータをUTF-8からEUC-JPへ変換してからビルドしたりもしてみたが、何も変わらなかった……。

なかなか一筋縄ではいかないですね～は～、短単位でTokenizeしてぇなぁ～。