OmniAICreator/Qiita-1.07M huggingface dataset:
FlutterのUI更新方法

# はじめに
Flutterを使ってTODOアプリの開発を進めることになり、YouTubeで様々な動画を漁っていたのですが、状態管理やUIの構築方法についてわかりやすい動画を見つけたので内容をまとめてみました。今回はUIの更新方法の流れに的を絞って状態管理ついてはまた別記事でまとめようと思います。

# 参考動画
[FlutterKaigi 2023 我々にはなぜ Riverpod が必要なのか - InheritedWidget から始まる app state 管理手法の課題 by ちゅーやん（中條 剛）](https://youtu.be/2SnTNFAzmY0?si=i01hUwaJYdyMbdTZ)
※動画後半部分はriverPodという状態管理用のパッケージの説明のため、本記事の内容は前半部分のみ

# UI構築イメージ
まずはじめに、FlutterがどのようにUIを構築しているかですが、イメージは以下の図の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/0ccc2d13-b11f-c467-c92d-7947343cd6df.png)

FlutterではWidgetと呼ばれる部品を組み合わせてUIを実装していくわけですが、各Widgetに存在するbuildメソッドが実行されることで、実装内容がUIへ反映されます。

[Flutter公式ドキュメント](https://docs.flutter.dev/data-and-backend/state-mgmt/declarative) では、"UI = f(State)"と表現されており、　
UIは常に状態(State)を持ったbuildメソッド(= f)の実行結果となります。

UIの更新を理解するためには、状態(State)の更新→buildメソッドの呼び出しの流れを理解することが重要になってくるというわけです。

# どのようにbuildメソッドが呼び出されているのか？
では、buidメソッドがどのように呼び出されているかというと、"Element"というオブジェクトに定義されている`markNeedsBuild()`がWidgetのbuildメソッドを呼び出しています。

## "Element"とは？
突然出てきた"Element"ですが、UI構築の理解には欠かせないため触れておきます。特徴は以下の通りです。
* Widgetと必ず一対一で生成されるオブジェクト（自身で実装する必要はない）
* Widgetの参照（ツリー）情報を持っている 
* =buildメソッドの第一引数(BuildContext型の`context`)

Widgetが生成される際にフレームワークが自動的に`createElement()`を呼び出し、必ず対の関係となるElementを生成します。生成されたElementはWidgetの親子関係や参照情報を保持しています。

Widgetは頻繁に更新・破棄されるため、参照情報を保持せず、その役割は"Element"に任せているようです。

StatelessWidgetやStatefulWidgetを作成すると、buildメソッドの引数にBuildContext型の`context`があるのを見たことがあると思います。その`context`の実態がElementです。

## StatefulWidgetのUI更新の流れ
話を戻して、UI更新したい場合の動きについて見ていきたいと思います。

以下はStatefulWidgetが持つStateを画面に表示しているパターンで、他WidgetからStateを変更した際のUI更新の流れを表しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3889500/040d0271-c2e6-b150-6d5a-47e502af075e.png)
1. 他Widgetから変更したいStateを持つStatefulWidgetの`setState()`を呼び出す（ボタン押下時のイベントなど）
1. 状態が更新されたStateオブジェクトは対で存在するElementの`markNeedsBuild()`を呼び出す
1. ElementがStatefulWidgetの`build()`を呼び出す

2~3の手順は自身で実装する必要はなく、`setState()`を呼び出すことでフレームワークが自動的にUIを更新してくれます。

# まとめ
 以前業務で使用していたAngularでは、コンポーネント(TypeScript)側で値を変更するとUIが自動更新される双方向バインディングの仕様になっていました。
 
 ただ、FlutterではUIに表示している変数を直接更新してもUIが更新されません。buildメソッドが実行されていないからということですね。

 双方向データバインディングでUIを自動更新しないメリットは以下の通りです。
 * 不要な再描画をしないことによるパフォーマンスの向上
 * UIの更新タイミングを正確に把握できるため、予期せぬ副作用を防げる
 * UI更新を必要な時のみ実行できるため、複雑な状態管理やアニメーションの実装において高い柔軟性を持つ
 * メモリ使用量を抑えることができる
 * 更新のタイミングや問題発生の原因が特定しやすく、デバッグが容易になる
AWS DEA勉強で学んだことメモ

### :sunny: AWS Certified Data Engineer - Associate 認定の勉強で個人的に初めて知った用語や分かりやすかったサイトなどをまとめています

---

* ### RedShiftワークロード管理（WLM）
**ResShiftがクエリに対してどのようにリソース（メモリ/CPU/IO）を割り当てるかを決定づける仕組みのこと**

そもそも…
ロングクエリ（実行に長時間かかるクエリ）があるとクラスター全体に影響が出る

:thought_balloon:イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828602/074950d0-226d-bafa-d44c-f71609a39d84.png)


そこで…！
WLMで複数のクエリキューを用意しておき、各キューに対してリソース（メモリの割合や並列度など）を割り当て優先度を定義することで、ロングクエリでクラスタリソースを無駄遣いしないようにすることができる



https://qiita.com/jnit/items/6b8182fc0add277ac303

https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/automatic-wlm.html

* ### RedShift分散スタイル
**テーブルを作成する際に指定する分散スタイル。AUTO,EVEN,KEY,ALLの4種類があり、何も指定しないとAUTO（自動で最適な分散スタイルに割り当ててくれるもの）を使用する**

https://d1.awsstatic.com/events/jp/2017/summit/slide/D3T1-5.pdf

* ### Athenaワークグループ
**クエリ実行環境を分離することによってIAMユーザーやIAMユーザーグループ毎にアクセス制御ができる**

https://blog.serverworks.co.jp/2023/01/13/190000

https://blog.serverworks.co.jp/2023/02/03/160000#IAM%E3%83%9D%E3%83%AA%E3%82%B7%E3%83%BC%E3%81%AE%E6%9B%B8%E3%81%8D%E6%96%B9


* ### Athena Federated Query
**RDB、NoSQL、オブジェクトデータ、カスタムデータソースに保存されているデータにまたがってSQLを実行することができる機能**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3828602/e615b463-0b8a-e447-97a6-3b898ff3b6d0.png)

https://aws.amazon.com/jp/blogs/news/query-any-data-source-with-amazon-athenas-new-federated-query/


* ### Athenaフォーマンス向上方法
　これを見るしかない

https://docs.aws.amazon.com/ja_jp/athena/latest/ug/performance-tuning.html#performance-tuning-use-columnar-file-formats
【アイディア】こっくりさんタイピングゲーム


## 前書き

これはただのアイディアです。

## 本文

画面には50音一覧表とコインが1枚

コインをドラッグして50音一覧表の文字を選択する。

このこっくりさんっぽい動作でタイピングゲームをする。

というアイディア。

面白いかは分からん。
Django REST Framework「実践入門」Part１

# はじめに
Django REST Frameworkについて何回かに分けて説明していきます。

まずは、part1ということでDjango REST Framework（以降DRF）とは何か？
また、Rest APIとは何か？について説明します。

https://www.django-rest-framework.org/
# Django REST Framework（DRF）
DRFは、**REST APIバックエンド構築**に特化したフレームワークです。

DRFの強みは、バックエンド構築に必要な機能がほとんどそろっていることで、デフォルトで認証などの機能を実装することが出来ます。

また「**Browsable API**」というブラウザ上でAPIをたたくことが出来る機能も備わっています。

またDjangoと大きな構造上の違いはないので、Djangoを触ったことがある人なら、すぐにAPI開発ができます。

そもそも、なぜDjangoではなくDRFを使うのかというと、React、Next.jsなどの**モダンなフロントエンドフレームワーク**を使用できるからです。また、このようにフロントエンド、バックエンドを分けることで、効率的な開発にもつながります。

何より、Pythonのライブラリを使えることがPythonでバックエンド開発を行う何よりの強みでしょう。

# REST API 
RESTという言葉を聞くことはよくあると思います。まさにREST APIとは**RESTに沿って開発されたAPI**のことです。

REST APIに似た用語で、RESTful APIがありますが、

**REST API**はRESTに沿って開発されたAPI（**完全には満たしていない部分もある**）

それに対して、**RESTful API**は**完全にRESTの原則を満たしているAPI**です
## RESTとは
REST、RESTうるさいですが、
RESTとは、以下の原則を満たす**アーキテクチャスタイル**です。
- **クライアント・サーバ**
クライアントとサーバが通信する
- **ステートレス**
クライアントのアプリケーション状態を管理しない
- **キャッシュ**
リソースの鮮度に基づいて、リソースをクライアント側で使いまわす
- **統一インタフェース**
URIで指示したリソースに対する操作を、統一した限定的なインタフェースで行う
- **階層化システム**
システムをいくつかの階層に分離する
- **コードオンデマンド**
プログラムコードをサーバからダウンロードし、クライアント側でそれを実行する

結局RESTとは、上の原則に沿った開発をしましょうねということです。

# 最後に
DRFとはREST APIをPythonで簡単に開発できる便利なフレームワークです。
次からは実際にDRFのコンポーネントを触りながら説明していきます。

# 参考文献

この記事は以下の情報を参考にして執筆しました。

- Webを支える技術 -HTTP、URI、HTML、そしてREST (WEB+DB PRESSプラスシリーズ)
- 現場で使える Django REST Framework の教科書
[Security] PasswordCrack

# 一覧
|名称|手法<br>対策|
|:--|:--|
|辞書攻撃|パスワードに用いられやすい単語を辞書として登録・攻撃|
||推測されにくパスワード|
|ブルートフォース攻撃<br>総当たり攻撃|ID固定/文字の組み合わせでパスワードを変えて攻撃|
||ログイン試行回数に制限を設ける|
|リバース<br>ブルートフォース攻撃|文字の組み合わせでID変えて攻撃/パスワード固定|
||特になし|
|パスワードリスト攻撃|不正に取得したID/パスワードの一覧を用いて攻撃|
||ID/パスワードの使い回しを行わない|
|レインボー攻撃|パスワード候補とそれに対するハッシュ値の対応表(**レインボーテーブル**)を作成・攻撃|
||**ソルト**(十分な長さを持つランダムな文字列)を加えてハッシュ化することで、レインボーテーブルの作成を困難にする|


# 参考リンク
- [平成31春1(午後)](https://www.ap-siken.com/kakomon/31_haru/pm01.html)
docker compose upでbuildエラーが出た件

## エラー内容

dockerでアプリを作ろうとしたがbuildができず、Error saving credentials: error storing credentials….が出た。

## 調査
「docker node credential」でググった。（今回使用するbaseイメージがNodeだったため）

## 原因
~/.docker/config.jsonが悪さをしていたみたい。config.jsonはDockerの設定ファイルで認証情報やデフォルト設定、プラグインの設定が記述されている。

## 解決策
config.jsonを削除しdockerを再起動した。

## 参考にした記事
https://zenn.dev/bon/scraps/d0099eddd9f215

## 終わりに
久しぶりにdocker compose upをするとエラーが出るようになっていた。最初はChatGPTに聞いたが解決せず、結局ググったらすぐに解決策にアクセスできた。ChatGPTは便利だが、頼りすぎず自分で調べることが大切だと感じた。
Raspberry Pi 5用公式アクティブクーラーの取り付け方法

## 1.はじめに
#### 1.1. 使用したもの
* Raspberry Pi 5 4GB
* OS：Bookworm(64-bit) Desktop Release 5.3 July 2024
* 公式アクティブクーラー　SC1148


表１．アクティブクーラーの仕様
|項　目 |　内　容   |
|:----|:-------|
|入力電圧  |  +5V |
|センサ  | 速度センサ内蔵  |
|制御方式  |   PWM速度制御|
| 最大ファン速度 | 8,000 RPM(Revoiutions Per Minute) ±15%  |
| 最大風量 |  1.09 CFM(Cubic Feet per Minute) |
|ヒートシンク  | アルマイト加工処理されたアルミニウム製  |

## 2.アクティブクーラーの取り付け方法
　Raspberry Pi 5(以下、Pi5)のFANコネクタカバーを外します（図１）。カバーは指で簡単に外れますが、2段のUSBコネクタと拡張コネクタの隙間にあるため、ピンセットを使用しても外すのもよいでしょう。

図 1　Pi 5のFANコネクタのカバーを外す
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/a399a3bb-a916-82b0-dbd5-d29661b9600e.jpeg">

　アクティブクーラーの保護紙を外すとサーマルパッドが見えます（図2）。サーマルパッドは、ヒートシンクと発熱部品（ICなど）の接触面でのミクロな凸凹を埋め、効率的に熱を伝える役割を持っています。サーマルパッドは非伝導性で、柔らかく粘着性があります。なお、サーマルパッドを触れると、熱伝導効果が低下するため注意です。
　図2の番号は、冷却対象の電子部品です。
①	SoC（CPU、GPU、キャッシュメモリなどの回路を集積したチップ）
②	PMIC（マルチチャンネルパワーマネジメントIC）
③	RP1（USB、MIPI、Ethernet、GPIOなどを集積したチップ）
④	Wi-Fiモジュール

図 2　アクティブクーラーのサーマルパッドとPi5
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/c9bd4be5-4948-615b-feb5-2476dc608e83.jpeg">

アクティブクーラーのバネ式プッシュピンとPi5の取り付け穴（2箇所）の位置を確認し、アクティブクーラーとPi5を合わせます（図3）。

図 3　アクティブクーラーの位置合わせ
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/2bb6e04a-906f-d1a4-d988-719d56546ebb.jpeg">

　プッシュピンを押し込み、はんだ面に貫通したスナップがしっかり拡がり、プッシュピンが抜けないことを確認します(図4(a))。これが最も重要なポイントです。図4(b)のようにスナップが拡がっていない場合、ヒートシンクと発熱部品の密着度が弱くなり、冷却効果が十分に発揮されなくなります。

図 4　プッシュピンの押し込み
(a) スナップが拡がった状態
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/ca16c3a4-f765-effe-1fb1-2afd4a11e7fc.jpeg">

(b) 押し込み不足
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/5db2037d-d2ec-aec7-817d-2ee6a3383e63.jpeg">

　アクティブクーラーのコネクタをPi5に取り付けます（図5）。クーラーのコネクタにはキーがあり、凹部と凸部がかみ合うことで正しい方向にのみ接続できるようになっています。

図 5　FANコネクタの接続
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/ac110462-b012-2454-49c0-eab13c6ec7a6.jpeg">

## 3.動作確認
　参考文献[2]のソースコードをクロック周波数3,000MHzまで測定できるように改良し、Pi5のCPU 4コアを100%の使用率にした状態で、SoCの温度とクロック周波数を測定しました。実験結果を図6に示すように、室温28℃の環境で、7分後にはSoCの温度は約70℃に達しましたが、サーマルスロットリングは発生せず、クロック周波数は2.4GHzを維持していました。また、SoCの温度が約50℃に達するとアクティブクーラーが回転し始めます。

図 6　CPU使用率を100%のときのSoCの温度とクロック周波数
<img width="360" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631966/dd1accb7-d519-5955-528e-48ff8d9729e9.png">

## 4.おわりに
　個人的な印象ですが、アクティブクーラーの風切り音は静かだと感じました。なお、公式のWebページ[1]では、アクティブクーラーをつけたり、外したりすると、プッシュピンとサーマルパッドが劣化し、製品が損傷する可能があることが指摘されています。


## Reference
[1] Raspberry Pi Active Cooler, https://www.raspberrypi.com/products/active-cooler/
[2]菊池達也, Raspberry Pi 4 Model BをDCファンで自動的に冷却する, https://qiita.com/tamamori/items/0d761846ab9bd20b321e
なんとなくfactoryパターンについて考察

## まえがき
最近業務でletを使ってコードを組んでいたら、「factoryで書いた方が良さそうですね」というレビューをいただいた。
letでは再代入を意識しないといけないため、できるだけconstで書きたいかららしい。

とりあえずレビューいただいた通りでコードを書いたが、結局factoryとは何で、副作用はないのか、書くとき気にする必要のあるものはあるかなど疑問に残ることが多かった。

そのため、記事としてまとめてみた。
## factoryパターンとは？
>factoryパターンとは、オブジェクト指向プログラミングにおけるデザインパターンの一つ。
主な目的は、オブジェクトの生成プロセスを抽象化すること。

要するに、オブジェクトを直接生成する代わりにメソッドなどを通じてオブジェクトを生成することである。

## コードで見る

例として以下のようなケースを考えてみた。
決済の時、どのお支払い方法で支払われたかを判断するコードになっている。

``` ts
interface PaymentMethod {
    processPayment(amount: number): string;
}

class CreditCardPayment implements PaymentMethod {
    processPayment(amount: number): string {
        return `Processing $${amount} via Credit Card`;
    }
}

class PayPayPayment implements PaymentMethod {
    processPayment(amount: number): string {
        return `Processing $${amount} via PayPay`;
    }
}

class CashPayment implements PaymentMethod {
    processPayment(amount: number): string {
        return `Processing $${amount} via Cash`;
    }
}
```

### letで実装
letで書いたら以下のようになる。実行されるメソッド内で直接`new`を使ってオブジェクトを生成することがわかる。
``` ts
function processPayment(method: string, amount: number): string {
    let paymentMethod: PaymentMethod;
    
    switch (method) {
        case "creditcard":
            paymentMethod = new CreditCardPayment();
            break;
        case "paypay":
            paymentMethod = new PayPayPayment();
            break;
        case "cash":
            paymentMethod = new CashPayment();
            break;
        default:
            throw new Error("Unknown payment method");
    }
    
    return paymentMethod.processPayment(amount);
}
```

### factoryで実装
今回はクラスでfactoryを実装してみた。
このfactoryクラスの中で、各オブジェクトを作成し、実行されるメソッドに返す形となっている。
``` ts
class PaymentMethodFactory {
    static createPaymentMethod(method: string): PaymentMethod {
        switch (method.toLowerCase()) {
            case "creditcard":
                return new CreditCardPayment();
            case "paypay":
                return new PayPayPayment();
            case "cash":
                return new CashPayment();
            default:
                throw new Error("Unknown payment method");
        }
    }
}

function processPaymentWithFactory(method: string, amount: number): string {
    const paymentMethod = PaymentMethodFactory.createPaymentMethod(method);
    return paymentMethod.processPayment(amount);
}
```
### いいところが多い

新しいタイプのオブジェクトを追加する際に、既存のコードを変更せずに拡張できる。

また、実行されているメソッドで直接オブジェクトを生成しないため、結合度が低くなる。
そのため、オブジェクト生成に関するロジックを一箇所にまとめることができそう。

## これは万能なの？
とにかくletで済むものをclassやclosureで書くことになるため、パフォーマンスは落ちることになる。意識せず乱用すると無駄なインスタンスが増えてメモリリークにも繋がる。

また、ユニットテストを書くときに、ファクトリーをモックする必要がある。
テストを書くときにモックの扱いで一番ハマることが多いので、初期学習コストが高くなる。

あと、なんとなく抽象化するときの粒度を考えるのが難しそうだった。
例えば今回のコードでcredit card, paypay, cashが一緒だったけど、「現金は通信が行われないから別だろ」という意見があるかもしれない。

そもそもクラスのprivateで書いた方がパフォーマンスがいいからあまり使われなくなった、という記事も結構見つけた。やっぱパフォーマンスは大事

## おわりに
コードを書くときはなんとなく理解したつもりでいたが、記事を書いていてやはり全然わかっていなかったことがわかった。

知識をまとめることは大事だなと
Tips: TypeScriptでオブジェクト型から関数プロパティを抜いた型を生成する

## この記事は何
最近TypeScriptでクラスなどとして定義したオブジェクト型から、関数のプロパティのみを除外した型を生成したいシーンがあったので、その方法についてまとめた記事です。

## TL;DR
以下の型の定義で実現できます。

```ts
type OmitFunctionNames<T> = {
  [K in keyof T]: T[K] extends (...args: never[]) => unknown ? never : K;
}[keyof T];

type OmitFunctions<T> = Pick<T, OmitFunctionNames<T>>;

//これを使う
type RecursiveOmitFunctions<T> = {
  [K in keyof OmitFunctions<T>]: OmitFunctions<T>[K] extends object
    ? RecursiveOmitFunctions<OmitFunctions<T>[K]>
    : OmitFunctions<T>[K];
};

```

## 解説
ただコード紹介をしただけで終えてしまうのも味気ないので、少しだけ解説を書きます。

### `OmitFunctionNames<T>`

```typescript
type OmitFunctionNames<T> = {
  [K in keyof T]: T[K] extends (...args: never[]) => unknown ? never : K;
}[keyof T];
```

`OmitFunctionNames`は、型`T`のプロパティ名のうち、関数でないものを抽出する型です。
この型を用いて、除外するプロパティを抽出します。

### `OmitFunctions<T>`

```typescript
type OmitFunctions<T> = Pick<T, OmitFunctionNames<T>>;
```

`OmitFunctions`は、型`T`から関数プロパティを除外した型を作成します。
`Pick<T, OmitFunctionNames<T>>`は、型`T`のうち、`OmitFunctionNames<T>`で得られたプロパティ名だけを持つ新しい型を生成するという定義を行なっています。

### `RecursiveOmitFunctions<T>`

```typescript
export type RecursiveOmitFunctions<T> = {
  [K in keyof OmitFunctions<T>]: OmitFunctions<T>[K] extends object
    ? RecursiveOmitFunctions<OmitFunctions<T>[K]>
    : OmitFunctions<T>[K];
};
```

`RecursiveOmitFunctions`は、型`T`から関数プロパティを再帰的に除外した型を作成します。
プロパティにオブジェクトである場合は再帰的に`RecursiveOmitFunctions<OmitFunctions<T>[K]>`を適用し、そうでない場合はそのままの型を返します。
0から統計の勉強 さまざまな事象

# 学習サイト
統計web
- https://bellcurve.jp/statistics/course/

# 事象
- コインやサイコロを投げたりするように、その結果が予想通りになるかどうか実験や観察を行い試すことを<font color="Red">**試行**</font>という
- その試行によって起こった結果を<font color="Red">**事象**</font>という
- 集合
    - 複数の要素を集めたもの
        - 例えば、サイコロの出る目が偶数である事象の集合をGとすると、G = {2, 4, 6}と表される

### 全事象
- ある試行について、起こりうる全ての事象をまとめたもの
- 全事象は、Ω（オメガ）やUで表される

### 複合事象
- 分解が可能な事象のこと
- サイコロの出る目が偶数である事象の集合をGとしたとき、2の目が出る事象や4の目が出る事象のように分解できる
    - この集合Gのこと

### 根元事象
- これ以上分解できない事象のこと
- サイコロの出る目が偶数である事象の集合をGとしたときの2の目が出る事象自体のこと


### 余事象
- ある場合以外の事象のこと
- サイコロを投げる試行の場合、偶数の目が出る事象をAとした場合、余事象は奇数の目が出るもしくは、{1, 3, 5}のどれかが出る事象のこと
- 以下のように表される
```math
    \bar{A} もしくは A^c
```

### 空事象
- 存在しない事象のこと
- サイコロを投げる試行において、7の目が出る事象や偶数でも奇数でもない目が出る事象のこと
- φで表される

### 排反事象
- 同時に怒らない事象のこと
- サイコロの試行における偶数の目がでる事象と奇数の目が出る事象は同時に起こらないため、排反事象という
- 事象Aと事象Bを同時に満たす事象が空事象になる場合、事象Aと事象Bは互いに排反事象と言える

### 和事象
- 2つの事象AとBのうち、AまたはBが起こる事象のこと

### 積事象
- 2つの事象AとBのうち、AとBが同時に起こる事象のこと
【自分用】VSCodeのユーザ設定に入れておきたいtasks.json設定

# 目的

* VSCode使ってて微妙に使いづらい部分の補助

# 概要
* tasks.json自体の説明があまりないので利用頻度が高いものを記録しておきたい。

## taskの内容抜粋

### sakuraで開く
* 現在開いているファイルのカーソル行に合わせてサクラエディタを起動する
* VSCodeにマクロ機能が無いのでサクラエディタ連携したい時に利用する

### ファイル名のみコピーする
* 現在開いているファイル名をコピーする。
* VSCodeのGrep検索で自ファイル内検索したいときとかある
### 編集中のフォルダをコピー
* 現在開いているファイルのフォルダのパスをコピーする。
  * たまに使うので入れてる
  * フォルダをエクスプローラで開くtaskもあっても良さそう。

## task.json
* 環境問題かよくわかってないが、tasks.jsonで
スペースが含まれるパスはエラーになりやすいのでうまく動かなかったら
エスケープ文字を入れる必要がある。
* `Program Files(x86)`とか特に注意。

```json
// https://code.visualstudio.com/docs/editor/variables-reference
{
  // See https://go.microsoft.com/fwlink/?LinkId=733558
  // for the documentation about the tasks.json format
  "version": "2.0.0",
  "command": "powershell",
  "tasks": [
    {
      "label": "sakura",
      "type": "shell",
      "command": "C:\\Program Files (x86)\\sakura\\sakura.exe",
      "args": ["${file}", "-Y=${lineNumber}"],
      "problemMatcher": [],
      "detail": "sakuraで開く",
      "presentation": {
        "echo": true,
        "reveal": "silent", // パネル表示に関わる(エラーの場合表示)
        "focus": false, // パネルのフォーカス
        "panel": "shared", // shared: 既存のパネルを使う
        "showReuseMessage": true, // 既存のタスクがある場合、再利用するかどうか
        "clear": false // 出力パネルをクリアするかどうか
      }
    },
    {
      "label": "name",
      "type": "shell",
      "command": "Set-Clipboard",
      "args": ["${fileBasename}"],
      "problemMatcher": [],
      "detail": "ファイル名をクリップボードにコピー",
      "presentation": {
        "echo": true,
        "reveal": "silent",
        "focus": false,
        "panel": "shared",
        "showReuseMessage": true,
        "clear": false
      }
    },
    {
      "label": "dir",
      "type": "shell",
      "command": "Set-Clipboard",
      "args": ["${fileDirname}"],
      "problemMatcher": [],
      "detail": "開いているファイルパスをコピー",
      "presentation": {
        "echo": true,
        "reveal": "silent",
        "focus": false,
        "panel": "shared",
        "showReuseMessage": true,
        "clear": false
      }
    }
  ]
}
```

## 使い方

1. Ctrl + Eを実行
1. 入力プロンプトに[task {label名}]を入力してEnter


![tasks.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/53550/b5b92bc2-9411-b797-32d5-063b617df146.gif)

* 上記のGIFでは現在開いているファイルの行番号でサクラエディタを開く
強化学習とは何か？

# 強化学習を一言で説明すると？

強化学習（きょうかがくしゅう、Reinforcement Learning）とは、コンピュータが「行動の結果」を学びながら、最も良い結果を得られる行動を学習する仕組みです。人間が試行錯誤を通じて物事を学ぶのと似たイメージです。

## 強化学習の基本的な流れ

- **エージェント（Agent）**: エージェントは、問題を解決するために行動するコンピュータプログラムやロボットのようなものです。例えば、ゲームでプレイヤーキャラクターを動かす役割を持つものだと考えてください。

- **環境（Environment）**: エージェントが動く場所や世界です。例えば、ゲームのステージやロボットが動く部屋など、エージェントが影響を与える対象です。

- **状態（State）**: 環境の現状を表す情報です。例えば、チェスの盤面の状態や、車の自動運転では現在の車の位置や速度などが状態になります。

- **行動（Action）**: エージェントができる選択や動きです。例えば、右に進む、ジャンプする、チェスのコマを動かすなど、環境の中で選べるアクションのことです。

- **報酬（Reward）**: エージェントが行動した結果によって得られる「ご褒美」や「ペナルティ」のことです。例えば、ゲームでは得点が上がることがご褒美で、間違った行動でミスしてゲームオーバーになるのはペナルティです。

## 強化学習の目標

エージェントは、「どの状態でどんな行動をすれば、報酬が最も多くなるか」を学びます。つまり、エージェントが試行錯誤を繰り返しながら、良い行動パターンを見つけるのが強化学習の目標です。

例えば、ロボット掃除機を考えてみましょう。最初は無作為に動くかもしれませんが、時間が経つにつれ、家具を避けながら効率よく掃除できるルートを見つけ出します。ロボットは、どの方向に進めばゴミをより多く掃除できるかを学習し、少しずつ上手になっていくわけです。

## 具体的な例

- **ゲーム**: ゲームのAIが強化学習を使って自分で学習し、プレイヤーに勝てるように行動を最適化していきます。
- **自動運転**: 自動運転車が周囲の交通状況に基づいて、どのタイミングでブレーキをかけるかや曲がるかを学習します。
- **ロボットの動作制御**: 工場のロボットが物を持ち上げたり移動させたりする最適な方法を学びます。

## 強化学習と他の学習方法の違い

- **教師あり学習（Supervised Learning）**: 正解の答えが与えられており、それに基づいて学習する。
- **教師なし学習（Unsupervised Learning）**: 答えがなく、データの中からパターンを見つける。
- **強化学習（Reinforcement Learning）**: 正解が事前にわからず、行動の結果に応じて得られる報酬をもとに学習する。成功したかどうかはエージェントが報酬から学んでいく。

## まとめ

- 強化学習は、エージェントが環境の中で報酬を最大化するために行動を学習する仕組み。
- 試行錯誤を通じて、「どの行動が良い結果を生むか」を学び、最終的には最適な行動パターンを発見する。
- 実生活やゲーム、自動運転、ロボット制御など、さまざまな分野で利用されている。

強化学習は、まるで子供が遊びながら少しずつ物事を覚えていくように、コンピュータに試行錯誤を通じて学ばせる方法です。
ubuntuでCMSIS-DAPデバッグプローブを使う

# 1.ユーザーをdialoutグループに追加:
sudo usermod -aG dialout $USER
これにより、現在のユーザーがUSBデバイスにアクセスできるようになります。変更を反映するためにログアウトして再ログインしてください。
# 2.udevルールの設定:
新しいudevルールファイルを作成します：
sudo nano /etc/udev/rules.d/60-openocd.rules

以下の内容を追加します：
##### WCH-Linkの場合
ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="8012", MODE="0666", GROUP="plugdev", TAG+="uaccess"
##### pico debugprobeの場合
ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE="0666", GROUP="plugdev", TAG+="uaccess"

.rulesには両方記載しても大丈夫にたいです。
ファイルを保存して閉じます。
# 3.udevルールの再読み込み:
sudo udevadm control --reload-rules
sudo udevadm trigger

# 4.デバイスの権限を確認:
デバイスの権限を確認し、必要に応じて変更します：
sudo chmod 666 /dev/bus/usb/001/001
上の 001/001の部分はlsusb -vで確認して適当な値にします

# 5. interface/cmsis-dap.cfgの編集
以下を追加
##### WCH-Linkの場合
adapter speed 1000
adapter serial BC68850A4172
##### PICO debugprobeの場合
adapter speed 5000
adapter serial E660C062134B6728
##### (注)　WCH-LinkをCMSIS-DAPとして使用するためにはWCH-Linkutilityを用いてmodeをWCH-DAPlink-WINUSBに設定する必要がある<br>https://github.com/openwch/ch32v003/blob/main/WCH-LinkUtility/Doc/WCH-LinkUserManual-EN.pdf<br>
![WCH-link.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121242/ac9748d9-753e-a659-fdca-a26ca6bdbb46.png)
SSHの公開鍵と秘密鍵（ansible実行前の前準備）

# はじめに

ansibleの続き書こうかと思ったのですがセキュリティ話をすっ飛ばして説明するためにもsshの秘密鍵と公開鍵の説明と設定を行い、以後はパスワードなしで各ホストにログイン出来る状況をつくるためにも一度ここで説明しておきます。

通常Linuxにログインをするときは、ユーザー名をパスワードを指定してログインします。しかしIaCの考えでAnsible等を使って手順を自動化する際に、パスワードも記述するとセキュリティリスクになるし、逆に毎回パスワードを求められるような設定にすると、うっとうしいし自動化出来なくなる。

この問題を解決するために、一度認証をした人はその後パスワードなしでログインすることが出来るやり方が公開鍵と秘密鍵を使ったやり方です。


### 用語と役割

IT用語はわかりづらいので、イメージですと、マンションなどの各部屋には鍵が付いていますが、マスターキーでどの部屋にも入ることが出来ます。この強力なマスターキーを安全に管理するために、大概の管理人室では、鍵を保管するためのキーボックスを設け、キーボックスを空けるためのパスワードを設定しています。

このキーボックスの事を、IT用語ではキーチェイン、マスターキーを秘密鍵、各部屋の鍵穴を公開鍵と呼んでいます。

![スクリーンショット 2024-09-21 16.21.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3856269/f608e3b8-4470-c108-ffe7-79bef8f7a790.png)

キーボックス(キーチェイン）については今回は使わないので説明を省略します。
(macユーザーで、キーボックスもパスワードなしで使用する場合は使います）

### マスターキー(秘密鍵)と鍵穴(公開鍵)の作成

鍵の作成には色んな書類がありますが、ここ最近はRSAよりもED25519の方が安全と言わていますので、ここではED25519を指定しています。

下記コマンドを実行するときに設定するパスワードは、キーボックスから取り出す際のパスワードと思ってください。今回はパスワード無しにします。　理由は２つ有ります。一つは結局使うときにパスワードを入力しなくてはいけなくなるとIaCの意味が無くなるのと、既に鍵を使うユーザー認証で最低限のセキュリティは確保している状態（イメージで言えば管理人室へはパスワードを使って入っているから）だからです。

```bash
[username@master01 ~]$ ssh-keygen -t ed25519
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/username/.ssh/id_ed25519): 
Created directory '/home/username/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/username/.ssh/id_ed25519.
Your public key has been saved in /home/username/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:<略> username@master01
The key's randomart image is:
+--[ED25519 256]--+
|o=o              |
|++o              |
|oE .             |
|X=o..o .         |
|B++++ = S        |
|=o=o+B +         |
|+=oo+++ .        |
|++o. ..          |
|.o. .            |
+----[SHA256]-----+
[username@master01 ~]$ 
#これによって.ssh/id_ed25519(秘密鍵)と .ssh/id_ed25519.pub(公開鍵）が作成されました
```

### 鍵穴(公開鍵)の取り付け工事(配布)

次に作成した鍵穴(公開鍵)を各部屋に取り付ける工事として、ssh-copy-idを使います。

```bash
ssh-copy-id -i .ssh/id_ed25519.pub username@slurm01
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: ".ssh/id_ed25519.pub"
The authenticity of host 'slurm01 (10.nnn.nnn.nn1)' can't be established.
ECDSA key fingerprint is SHA256:<略>
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
username@slurm01's password: 

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh 'username@slurm01'"
and check to make sure that only the key(s) you wanted were added.
```

この段階でログインしてみると、特に何も指定しなくてもログイン出来ています。

```bash
[username@master01 ~]$ ssh slurm01

Last login: Sat Sep 21 16:44:38 2024 from 10.nnn.nnn.nn6
```

### 終わりに。

このようにパスワード入力せずログイン出来る状態を確保しているとansibleを行う際には非常に楽になります。私の場合は検証環境メインでの説明なので直接rootを指定しますが、実環境ではsudo出来るユーザーに対して、パスワード無しでssh出来る環境を用意して、sudoのパスワードを暗号化ファイルとして用意しておくという本題とは別の手間をする必要があります。
お酒の画像をCNNに学習させてみる

## はじめに
[前回の記事](https://qiita.com/cnysntry/items/448d592c8d317de1b9f6)で少ない画像データを平行移動や回転などを行い増やす手段について記載しました。今回はその増やしたお酒の画像データをCNNに学習させ、ディープラーニングでどこまで正確に判断できるかについて試してみました。

## お酒画像を学習させる
まずは、以下の8種類のお酒画像を各10枚ずつ準備し、[前回の記事](https://qiita.com/cnysntry/items/448d592c8d317de1b9f6)の方法を使ってデータ拡張してCNNで学習させてみました。

lagavulin
bowmore
caolila
kilchoman
bunnahabhain
bruichladdich
ardbeg
laphroaig

その結果は以下の通りとなりました。
![isla_10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/864111d9-6e0b-4077-f096-fb142576d388.png)

訓練データの学習が増えるに従い正解率も増加しており、学習が順調に進んでいるようです。
ここで作成されたモデルを使って、10枚の新しいお酒画像を正しく判別できるかについて試してみました。結果は以下の通りでした。
![test_isla_10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/035fb847-7fe3-99ab-39e8-ca1af78f2e08.jpeg)

正しく判別できたのは、10枚中、no6_br1.jpgとno7_bo1.jpgの2枚だけ。4枚の画像データは上位3位以内にも判別されませんでした。

## 正解に近い画像データを追加学習させる
試しに正解データに近いお酒画像をWebから10枚ほど集めてきてそれを教師データとして追加学習させてみました。その結果は以下の通りとなりました。
![isla_10+10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/b841d1de-fa17-10b8-b875-6747ec481acf.png)

前回よりも教師データの枚数が増えているためか学習の正解率が早い段階で立ち上がっているようです。
このモデルを使って、先ほどと同じ10枚のお酒画像を判別させてみました。
![test_isla_10+10.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/c8334847-181f-348e-2f5f-e5c68d5b5a13.jpeg)

今度は10枚中8枚が正解と判別され、残りの2枚の画像も上位3位以内と判別されました。
この結果から、正解データに近い画像データが教師データに含まれている場合、たとえ画像データが少ない場合でも正解率はかなり上昇するようです。

## 再学習
先ほどの追加学習（正解データに近いお酒画像をWebから10枚ほど集めてきてそれを教師データとする）とまったく同じ条件で、再学習させ新しいモデルを作成しました。
前回と同じようにこのモデルを使って、先ほどと同じ10枚のお酒画像を判別させてみました。
![test_isla_10+10_part2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750854/5a2f37ec-d8d6-dc1f-ba54-b68b9ad40223.jpeg)


まったく同じ条件で学習させているにもかかわらず結果は前回とは全く異なりました。10枚中4枚が正解と判別され、それ以外の画像データは上位3位以内と判別されました。

## おわりに
[正解に近い画像データを追加学習させる](#正解に近い画像データを追加学習させる)と[再学習](#再学習)は、まったく同じ条件だったとしてもrand()によりランダムにミニバッチで選択される画像が異なってくるため、学習過程も異なるということだろう。今回は2回の追加学習での結果は異なるものが得られたが、いずれの結果も最初の学習[お酒画像を学習させる](#お酒画像を学習させる)の結果よりは正解率が高まっていることから、膨大な量の教師データを用いて学習させたモデルが比較的正解率も高まる傾向がありそうな気がする。
DynamoDBの役立つリンク集

# サービスの説明

- [Amazon DynamoDB とは](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/Introduction.html)

>Amazon DynamoDB は、サーバーレスのフルマネージド NoSQL データベースで、あらゆる規模で 1 桁ミリ秒のパフォーマンスを実現します。
>
>DynamoDB を使用すると、リレーショナルデータベースのスケーリングと運用の複雑さの課題に対応できます。DynamoDB は、あらゆる規模で一貫したパフォーマンスを必要とするオペレーションワークロード向けに構築され、最適化されています。例えば、DynamoDB は、10 ユーザーの場合でも 1 億ユーザーの場合でも、ショッピングカートのユースケースで一貫した 1 桁ミリ秒のパフォーマンスを提供します。2012 年にリリースされた DynamoDB は、コストの削減と大規模運用におけるパフォーマンスの向上を実現しながら、リレーショナルデータベースからの移行を支援し続けています。
>
>DynamoDB を使用して、すべての規模、業界、地域のお客様が、小規模から始めてグローバルにスケールできる最新のサーバーレスアプリケーションを構築しています。DynamoDB は、ほぼすべてのサイズのテーブルをサポートするようにスケールしながら、一貫した 1 桁ミリ秒のパフォーマンスと高可用性を提供します。
>
>Amazon プライムデーなどのイベントの場合、DynamoDB は、Alexa、Amazon.com サイト、すべての Amazon フルフィルメントセンターなど、トラフィックの多い複数の Amazon の施設とシステムを強化します。このようなイベントでは、DynamoDB API は、Amazon の施設とシステムからの数兆にもおよぶ呼び出しを処理してきました。DynamoDB は、ピークトラフィックが 1 秒あたり 50 万件を超えるテーブルで、数百人ものお客様に継続的にサービスを提供しています。また、テーブルサイズが 200 TB を超える数百のお客様に対応し、1 時間あたり 10 億件を超えるリクエストを処理します。

# 基本的な使い方

- [使用開始](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)

# 内部の動作の説明

- [Amazon DynamoDB: 仕組み](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.html)
- [Amazon DynamoDB: A Scalable, Predictably
Performant, and Fully Managed NoSQL
Database Service](https://www.usenix.org/system/files/atc22-elhemali.pdf)

# データモデリング

- [DynamoDB テーブルのデータモデリング](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/GettingStartedDynamoDB.html)
- [The DynamoDB Books](https://www.dynamodbbook.com/)

# キャパシティ管理

- [DynamoDB のスループットキャパシティ](https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/capacity-mode.html)

# 事例集

- [Amazon DynamoDB Customers](https://aws.amazon.com/jp/dynamodb/customers/?nc1=h_ls)
App Service + Java + Application Insightsでのログ欠損

# 発生した事象
* App Serviceに対して負荷試験を実施
* テストリクエストを発行する端末側のリクエストログとApplication Insights側のリクエストログを突合すると件数が一致しない（=Application Insights側でログが欠損している）
* Application Insightsで以下クエリを実行するとRetainedPercentageが100%になっていない（=ログが欠けている）ことも確認
   ~~~
   union requests
   | summarize RetainedPercentage = 100/avg(itemCount) by bin(timestamp, 1h), itemType 
   ~~~

# 環境
* App Service (Windows)
* App Service上ではJavaアプリケーションを実行
* Application Insightsは自動インストルメンテーション（App Service管理画面でApplication Insightsとの関連付けを設定するのみ）
* Application Insightsで「データのサンプリング」設定はおこなっていない。（既定値の「すべてのデータ(100%)を受信する」になっている）

# 原因
レート制限付きサンプリングによりログが欠損していることが判明。
SDK バージョンが 3.4.0 以降の場合、デフォルトでレート制限付きサンプリングが有効になっている。デフォルト設定のままだと、1秒あたり最大約5リクエストのログしか取得されない。
> Rate-limited sampling
> Starting from 3.4.0, rate-limited sampling is available and is now the default.
>
> If no sampling is configured, the default is now rate-limited sampling configured to capture at most (approximately) five requests per second, along with all the dependencies and logs on those requests.

引用元：https://learn.microsoft.com/ja-jp/azure/azure-monitor/app/java-standalone-config#rate-limited-sampling

# ログを漏れなく取得する設定
固定率のサンプリングでサンプリング率を 100 に設定する。
設定はApp Serviceの環境変数からおこなえる。

App Serviceの管理画面を開き、[設定]→[環境変数]を選択。アプリ設定の[追加]ボタンをクリックし、以下のアプリケーション設定を追加する。
　
名前：APPLICATIONINSIGHTS_SAMPLING_PERCENTAGE 
値　：100

![APPLICATIONINSIGHTS_SAMPLING_PERCENTAGE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/34114bd6-1100-c4a2-ce6b-b49bfca3a2b8.png)

![env_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/6e7dcf4f-96fb-ec1c-5112-bbcafecb36e3.png)

# その他の参考情報
#### [Application Insights にテレメトリが保存されなかった場合のトラブルシューティングについて](https://jpazmon-integ.github.io/blog/applicationInsights/troubleshooting_telemetry/)
Japan Azure Monitoring Support Blogの記事。よくまとまっているので、初めにこちらに目を通すとよい。

#### [Sampling in Application Insights](https://learn-microsoft-com.translate.goog/ja-jp/azure/azure-monitor/app/sampling-classic-api?_x_tr_sl=auto&_x_tr_tl=ja&_x_tr_hl=ja#configuring-sampling-overrides-and-fixed-rate-sampling-for-java-applications)
言語によってサンプリング動作が異なることが書かれている。Java以外の言語でのサンプリングはまずこのページを確認するとよいと思われる。

このページでJavaのことも触れられているのだが、サンプリングの既定動作が変わったことが反映されておらず、内容が古いかもしれない。（2024/9/21時点）
> By default no sampling is enabled in the Java autoinstrumentation and SDK.
CythonでPythonの計算速度を最適化

### はじめに
PythonのコードをCythonに変換することで、計算速度を劇的に向上させることができると言われています。今回は、Pythonでのループ処理をCython化し、どれほどの速度向上があるかを実測して比較してみました。しかし、結果は意外なものでした。

### ステップ1: `sumtest_originalpython.py`を作成
まずは、純粋なPythonでの処理です。

#### sumtest_originalpython.py
```python
# ファイル: sumtest_originalpython.py

def sum_loop(n):
    total = 0
    for i in range(n):
        total += i
    return total
```
このコードは、指定された範囲内の整数を合計する単純なループ処理です。

### ステップ2: Pythonでの実行速度を測定
次に、`measure_time_originalpython.py`で実行速度を測定します。

#### measure_time_originalpython.py
```python
# ファイル: measure_time_originalpython.py
import time
from sumtest_originalpython import sum_loop

if __name__ == "__main__":
    N = 10000000
    start_time = time.time()
    result = sum_loop(N)
    end_time = time.time()
    
    print(f"Result: {result}")
    print(f"Original Python execution time: {end_time - start_time} seconds")
```
実行結果は以下の通りです。

```
Original Python execution time: 0.5 seconds
```

### ステップ3: `sumtest_cdef.pyx`でCython化
次に、PythonコードをCythonに変換します。

#### sumtest_cdef.pyx
```cython
# ファイル: sumtest_cdef.pyx
def sum_loop(int n):
    cdef int i
    cdef int total = 0
    for i in range(n):
        total += i
    return total
```

Cythonを使って、`cdef`を用いて変数の型を明示的に定義することで、計算効率が向上します。

### ステップ4: `setup.py`でCythonコンパイル
Cythonファイルをコンパイルするための`setup.py`を作成します。

#### setup.py
```python
# ファイル: setup.py
from setuptools import setup
from Cython.Build import cythonize

setup(
    ext_modules = cythonize("sumtest_cdef.pyx")
)
```

次に、コマンドラインで以下を実行してCythonファイルをコンパイルします。

```bash
python setup.py build_ext --inplace
```

### ステップ5: Cython化されたコードの実行速度を測定
最後に、Cython化したコードを実行して、その処理時間を測定します。

#### measure_time_cython.py
```python
# ファイル: measure_time_cython.py
import time
from sumtest_cdef import sum_loop

if __name__ == "__main__":
    N = 10000000
    start_time = time.time()
    result = sum_loop(N)
    end_time = time.time()
    
    print(f"Result: {result}")
    print(f"Cython execution time: {end_time - start_time} seconds")
```

結果は以下の通りです。

```
Cython execution time: 0.005 seconds
```

### 実行結果の比較
驚くべきことに、今回の比較では、**Cythonコードの方が純粋なPythonコードよりはるかに高速**であるという結果が出ました。

| 実行環境      | 実行時間     |
|---------------|--------------|
| Pure Python   | 0.5 秒     |
| Cython        | 0.005 秒       |

### 結論
PythonとCythonの実行時間を比較することで、Cython化によってどれほどの速度向上があったかを確認できます。
リーダブルコード読んでみた　part1

「リーダブルコード読んでみたほうがいいよ！」
と、言われたので読んでみました。

各章ずつ感想書いてみます。

# 1章　理解しやすいコード
コードを書くときに「なにを」意識すればいいのかを書いている。
まあ、当たり前のことしか書いていないのだが、現実ではできていないこともしばしば。。

1つ気になったのが以下の説明だった。

```java:簡潔
return exponent >= 0 ? mantissa * (1 << exponent) : maneissa / (1 << -exponent);
```
```java:安心
if (ecponent >= 0) {
    return mantissa * (1 << exponent);
} else {
    return mantissa / (1 << -exponent);
}
```
2つ例が書かれており、文章はこう続いていた、
「「簡潔」と「安心」はどちらが大切なことなんだろう？　君ならどうやって決めるだろうか？」

この場合私だったら、間違いなく簡潔のように書く。
というか三項演算子で書ける場合は積極的に採用している。

例で出されていたコードにはインデントがないので、私なら、
```java
return exponent >= 0 
    ? mantissa * (1 << exponent) 
    : maneissa / (1 << -exponent);
```
こう書く。

浅い開発経験だが、一番わかりやすい書き方のような気がしている。

皆さんはどのように書きますか？（アンチ三項演算子のような記事も結構見かける）
「安心」派の意見も聞いてみたいなと思いました。

https://www.oreilly.co.jp/books/9784873115658/
0から統計の勉強 場合の数

# 学習サイト
統計web
- https://bellcurve.jp/statistics/course/


# !の使い方
- !は<font color="Red">**階乗**</font>を表す
- 階乗とは、<font color="Red">**ある正の整数から1までの整数の積**</font>のこと
- <font color="Red">**n個の異なるものを一列に並べる場合の並べ方**</font>を計算する際に用いられる

```math
n! = n \times (n-1) \times ・・・ \times 2 \times 1
```

- ただし、<font color="Red">**n=0の場合は0! = 1**</font>となる

例：6人を左から1列に並べる場合、何通りの並べ方があるでしょうか

- 1人目：6人から選ばれるので6通りある
- 2人目：1人目が決まり、残りの5人から選ばれるので5通りある
- 3人目：1、2人目が決まり、残りの4人から選ばれるので4通りある
- 4人目：1、2、3人目が決まり、残りの3人から選ばれるので3通りある
- 5人目：1、2、3、4人目が決まり、残りの2人から選ばれるので2通りある
- 6人目：1、2、3、4、5人目が決まり、残りの1人なので1通りしかない

よって、答えは

```math
6! = 6 \times 5 \times 4 \times 3 \times 2 \times 1 = 720通り
```

例：4人を円卓に座らせる場合、何通りの座り方があるでしょうか

- 注意点としては、回転させると同じ並べ方になる並べ方があること
- この例題では①②③④の4人が円卓に座る場合、下の4通りの座り方は円卓を回転させるとすべて同じ並びになる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1906633/b5fcc928-d5f0-bbb7-6930-c1074c74cc4f.png)

- こういった場合は、<font color="Red">**ある1箇所をある1つのもので固定してしまい、残りのものを並べる**</font>と考える必要がある
- 左上を固定した場合、以下のように求められる

- 右上の席：3人から選ばれるので3通りある
- 右下の席：1人目が決まり、残りの2人から選ばれるので2通りある
- 左下の席：1、2人目が決まり、残りの1人なので1通りしかない

よって、答えは

```math
3! = 3 \times 2 \times 1 = 6通り
```

# Cの使い方
- 組み合わせ(Combination)
    - <font color="Red">**異なるn個のものからr個を取り出す**</font>こと

```math
{}_n C_r = \frac{{}_n P_r}{r!} = \frac{n!}{(n-r)!r!}
```

例1：６人のグループから4人を選ぶ場合、何通りの選び方があるでしょうか。

- 1人目：6人から選ばれるので6通りある
- 2人目：1人が決まり、残りの5人の中から選ばれるので5通り
- 3人目：1, 2人目が決まり、残りの4人から選ばれるので4通り
- 4人目：1, 2, 3人目が決まり、残りの3人から選ばれるので3通り

ただし、選ばれた4人は並べ方を考えなくて良いので、4人を並べたとしたときの4!通りの並べ方は全て同じものと考えることができる。

そのため、「6人から4人を選んでその順に並べ方の数」を「4人の並べ方の数」で割ることで算出できる。

```math
{}_6 C_4 = \frac{{}_6 P_4}{4!} = \frac{6\times5\times4\times3}{4\times3\times2\times1} = 15通り
```

例2：1から9までの数字から4つを取り出して小さい順に並べる場合何通りの並べ方があるのか。

この問題であ考えるべきことは、「<font color="Red">**取り出して並べるからPを使えばいい」と早合点しない**</font>こと。

取り出した4川の数字を小さい順に並べる並べ方はどのような場合でも1通りしかないこと。つまり、「ある集団からいくつか取り出して並べる」と考えるのではなく、「<font color="Red">**ある集団からいくつか取り出す**</font>」と考えなくてはいけない。

従って

```math
{}_9 C_4 = \frac{{}_9 P_4}{4!} = \frac{9\times8\times7\times6}{4\times3\times2\times1} = 126通り
```

例3：10人のグループを4人、3人、3人の計3グループに分ける場合、何通りの分け方があるでしょうか。

この問題もグループ内での並べ方を考える必要がないので組み合わせの考え方である。

```math
・4人グループ：10人から4人を選ぶ選び方は、{}_10 C_4 = 210通りである
・3人グループ1つ目：残りの6人から3人を選ぶ選び方は、{}_6 C_3 = 20通りである
・3人グループ2つ目：残り3人で3人グループとなるので、これは1通りである
```

ただし、2つの3人グループは区別しない
- ABCDEFGの6人がABCとDEFと分かれる場合とDEFとABCと分かれる場合は同じものとして考える必要がある

従って、

```math
\frac{{}_10 C_4 \times {}_6 C3}{2} = 2100通り
```
Unity Asset Store から3Dモデル等をダウンロードする前に設定すべきこと。

Unityをインストールして初めて使ったときにハマったので防備録.
Unity HUB 3.8.0, Unity Editor 2022.3.42f1

解決方法:Package Manegerが使用するフォルダをデフォルト指定に合わせて作成し設定する。

現象:3Dモデルをダウンロードしようとしたときに永遠にクルクル回って終わらない状況に陥った。

![Screenshot from 2024-08-19 08-25-53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/0faf5db6-a8c3-9e66-d92f-5f026a12471f.png)

DownloadをクリックするとVer.1.1.0の横がクルクル回る続けたまま。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/a4c958f9-9fea-f830-7089-25fbb559e992.png)

下図の赤い！マークを解消することで問題なくダウンロードできた。
![Screenshot from 2024-08-19 08-18-38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/14464043-30c8-9efa-2354-bf79b48f19f4.png)

Unityをインスロールした際にデフォルト指定されているディレクトリが存在しないため作成する。


Edit　-> Preferenceと操作.
![Screenshot from 2024-08-19 08-11-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/c4c534ce-12f1-4bb7-bee4-591303eee590.png)

Package Managerがdefult指定しているunity3dを作成する。
![Screenshot from 2024-08-19 08-43-43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/4864f43c-b4b9-756a-a911-e81e68574df2.png)

Change Locationをクリック
![Screenshot from 2024-08-19 08-48-44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/877ee0bb-d146-7e09-83ac-4d6bcedea4a0.png)

右上のフォルダアイコンをクリックしunity3dを作成する
![Screenshot from 2024-08-19 08-55-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/e4a87927-d8e9-f804-ff45-5eda2f3a9d4c.png)

unity3d作成後
![Screenshot from 2024-08-19 08-56-35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/d97559cb-1735-a8c6-6ea0-0876c4f4748e.png)

赤い！マークが消えた状態。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/543b740d-4eff-4ed0-4432-67d9f6bb4abf.png)

一旦unityをすべて落とす。

Window -> Package Manegerと操作後にDownLoadを試みると無事始まる。
![Screenshot from 2024-08-19 09-01-48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/e42b1f81-212e-f40f-18ec-ac64cb59bc89.png)

Download終了。![Screenshot from 2024-08-19 09-10-07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3089345/d3f73f4b-0561-ff1a-f897-23fbce86eb92.png)


ダウンロード時にconsoleに出たエラーは、こちら。
Cannot include third party package location, you should check My Assets path location in User Preferences > Package Manager. Reason : '/home/ubuntu/.local/share/unity3d' is an invalid path
UnityEditor.GenericMenu:CatchMenu (object,string[],int)
ESP32 WROVER CAMとEdge Impulseで画像識別(非同期)

# ESPAsyncWebServerで非同期
https://qiita.com/hassy131/items/fa726793a987c9f1db93

上記記事の非同期版である。内容は同じ。
ソースコードのポイント

# #include
```c++
#include <esp32_pachokigu_inferencing.h>
#include "edge-impulse-sdk/dsp/image/image.hpp"
#include "esp_camera.h"
#include <WiFi.h>
#include <ESPAsyncWebServer.h>
```
# ルートエンドポイントの設定
```c++
    server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
        String html = R"rawliteral(
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ESP32 Camera</title>
    <style>
        body { font-family: Arial, sans-serif; text-align: center; }
        img { width: 100%; max-width: 500px; }
    </style>
</head>
<body>
    <h1>ESP32 Camera Stream</h1>
    <img src="capture" id="camera-stream">
    <script>
        function reloadImage() {
            var img = document.getElementById('camera-stream');
            img.src = 'capture?' + new Date().getTime();
        }
        setInterval(reloadImage, 1000);  // 1秒ごとに画像を更新
    </script>
</body>
</html>
)rawliteral";
        request->send(200, "text/html", html);  // HTMLをクライアントに送信
    });
```

# 画像キャプチャエンドポイントの設定
```c++
    server.on("/capture", HTTP_GET, [](AsyncWebServerRequest *request) {
        fb = esp_camera_fb_get();  // フレームバッファの取得
        if (fb) {
            AsyncWebServerResponse *response = request->beginResponse_P(200, "image/jpeg", fb->buf, fb->len);
            response->addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0");
            response->addHeader("Pragma", "no-cache");
            response->addHeader("Expires", "Thu, 01 Jan 1970 00:00:00 GMT");
            request->send(response);  // 画像データをクライアントに送信
            esp_camera_fb_return(fb);  // フレームバッファの解放
        } else {
            request->send(500, "text/plain", "Camera capture failed");  // エラーメッセージを送信
        }
    });
```
BlazorWebAppでリソースファイル(.resx)を参照する方法

## 概要

「メッセージは定数クラスではなくリソースファイル(.resx)ファイルで管理して」という依頼があったので、調査してみた。

リソースファイル(.resx)って、本来は多言語対応するために使用するらしい。

※国際化対応しないなら、Microsoft.Extensions.Localizationは不要。
この記事を書いた段階では気が付いていなかったが、SharedResources(この記事の場合)にエラーメッセージのプロパティを持ってるので、SharedResources.HogeMessage001という感じでエラーメッセージの文字列を取り出せる。

## プロジェクトの構成

プロジェクトテンプレート：Blazor Web App
フレームワーク：.NET 8.0
Interactive render mode：Auto
Interactivity location：Per page/component

※本記事では`@rendermode InteractiveServer`を指定した画面で検証を行った。

## 手順

#### ①Microsoft.Extensions.Localizationをインストール

#### ②Program.csに下記を追加

```
builder.Services.AddLocalization();
```

#### ③プロジェクト直下にResourcesフォルダを追加

#### ④Resourcesフォルダを右クリックしてSharedResources.resxを追加

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213285/03234378-e9f3-63f3-b530-022c36619e7d.png)

#### ⑤SharedResources.resxを右クリックして、「ファイルを開くアプリケーションの選択」

#### ⑥管理対象リソースエディタ（レガシ）を選択→OK　※初回のみ、このエディタを使用

#### ⑦アクセス修飾子をpublicに変更（重要）

※SharedResources.Designer.csが作成される
※ErrorMessageResourceNameからアクセス可能となる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/213285/c167d650-0122-dec8-7ddc-e411e52833a3.png)

#### ⑧SharedResources.resxをダブルクリック(リソースエクスプローラーが開く)

#### ⑨SharedResources.resxを編集する

名前：Greeting　※リソースのキー
ニュートラル値：Hello World　※リソースの値

#### ⑩_Imports.razor.csに下記を記載

```
@using Microsoft.Extensions.Localization
@using AzRefArc.AspNetBlazorUnited.Resources
```

#### ⑪razorファイルからresxを参照

```
@inject IStringLocalizer<SharedResources> Loc　※SharedResourcesはSharedResources.Designer.cs内に定義されたクラス

@Loc["Greeting"]
```

#### ⑫アノテーションからresxを参照

```
@using プロジェクトのルート名前空間.Resources;

[Required(ErrorMessageResourceName = "Greeting", ErrorMessageResourceType = typeof(SharedResources))]
```
#### ⑬リソースキーの定数化

下記のようにリソースのキーを定数化すると保守しやすそう。
リソースファイルを扱ってる記事をいくつか読んだ感じ、リソースのキーを定数化については何も言及されてなかった。自分の感覚では定数化するべきかなと思う。リファクタリングしやすいし、タイピングミスが起こらないし。

```
public static class ResourceKeys
{
    public const string RequiredError = "RequiredError";
}
```

## 参考

https://learn.microsoft.com/ja-jp/aspnet/core/blazor/globalization-localization?view=aspnetcore-8.0

https://stackoverflow.com/questions/4274311/visual-studio-resx-file-default-internal-to-public

https://stackoverflow.com/questions/4852198/the-resource-type-xxxx-xxx-does-not-have-a-publicly-visible-static-property-na

https://www.telerik.com/blogs/blazor-basics-localization-using-resource-files
Ubuntuのキーボード入力ソース

# 背景と使用環境
使用しているデスクトップパソコンの入力がおかしく、以下のように
```:期待される出力
（）
```
と入力しようと思って

```:キーボード入力
SHIFT+8,SHIFT+9 
```
と打ち込んだら、画面には

```:画面出力
 +(
```
と出てきました。？？

いろいろと探してみましたが意外とこの課題にダイレクトに答えてくれるものがなかったので共有します。

使用環境はUbuntu 20.04.3 LTS、キーボードはlogi のK120　USBスタンダードです。


# 結論

設定 > 地域と言語 > 入力ソース
で

- 日本語（OADG 109A）
- 日本語（Mozc）

を設定する。

以上です。

# 問題の原因
入力ソースに日本語OADG109Aが入っていなかったことが原因でした。

他の投稿でもう少し他のIMEなどについて調べてみようと思います。
初心者エンジニアが体験！indexedDBの便利さと実践的な活用法

## はじめに
こんにちは。入社2年目、実務経験約半年の駆け出しフロントエンドエンジニアです。日々の業務では主にNuxt、Vue、AWS、TypeScriptを使って開発を行っています。

今回は、最近``indexedDB``というものを触る機会があったので、便利だと感じた部分を共有したいと思います。
駆け出しのエンジニアの方にとって、少しでも参考になる情報をお届けできれば嬉しいです。

## indexedDBとは
indexedDBは、ブラウザ上で動作する強力なクライアントサイドのデータベースシステムです。WebStorageよりも高度な機能を持ち、大量のデータを扱えるのが特徴です。

主な特徴は以下の通りです:
- ブラウザ上で動作するNoSQLデータベース
- キーと値のペアでデータを保存
- 非同期APIを使用
- トランザクションをサポート
- 大容量のデータを扱える

https://developer.mozilla.org/ja/docs/Web/API/IndexedDB_API

## indexedDBの便利な点
indexedDBを使ってみて、以下の点が特に便利だと感じました:
1. オフライン対応: インターネット接続がなくてもデータの保存や取得が可能
2. 大容量データの扱い: WebStorageよりもはるかに大きなデータ量を扱える
3. 複雑なデータ構造: オブジェクトや配列などの複雑なデータ構造を直接保存できる
4. パフォーマンス: 非同期APIにより、大量のデータを歌う際も高速に動作する

## 実際の活用例: Nuxt3とAWS Lambdaを使用したWebアプリ
私が実際にindexedDBを活用したのは、Nuxt3でフロントエンドを構築し、バックエンドにAWS Lambdaを使用したWebアプリケーションです。

具体的には以下のような方法で実装しました:
1. データ取得の最適化:
・同じエンドポイントへのリクエストがあった場合、まずindexedDBをチェックします。
・データがindexedDBに存在する場合は、そこから直接データを取得します。
・データが存在しない場合のみ、AWS Lambdaにリクエストを送信します。
2. キャッシュの実装:
・ AWS Lambdaから取得したデータは、indexedDBに保存します。
・次回同じデータが必要になった時、ネットワークリクエストを送る代わりにindexedDBから高速に取得できます。
3. コード例(簡略化):

```java:fetch.js
async function getData(endpoint) {
    // indexedDBからデータを取得
    const cachedData = await getFromIndexedDB(endpoint);

    if(cachedData) {
        return cachedData;
    }

    //キャッシュにない場合、Lambdaからデータを取得
    const response = await fetch(endpoint);
    const data = await response.json();

    //取得したデータをindexedDBに保存
    await saveToIndexedDB(endpoint, data);

    return data;
}
```

## 実装して感じたメリット
この方法を実装することで、以下のような利点がありました：
- アプリケーションの応答速度が向上
- AWS Lambdaへのリクエスト回数が減少し、コスト削減
- オフライン時でも、一度取得したデータにアクセス可能

## 注意点と課題

indexedDBは便利ですが、使用する際には以下の点に注意が必要です:

1. データの鮮度: キャッシュしたデータが古くなる可能性があるため、適切なタイミングでデータを更新する仕組みが必要
2. ストレージ容量: indexedDBの容量には制限があるため、大量のデータを保存する場合は注意が必要
3. セキュリティ: 機密性の高いデータをindexedDBに保存する場合は、適切な暗号化などの対策が必要
4. ブラウザ対応: 古いブラウザではindexedDBがサポートされていない可能性があるため、フォールバック機能の実装検討が必要

## まとめ
indexedDBは、フロントエンド開発において非常に強力なツールです。特に、Nuxt3やAWS Lambdaのようなモダンな技術と組み合わせる ことで、効率的なデータ管理と優れたユーザーエクスペリエンスを実現できます。
初心者エンジニアとして、indexedDBの活用は少し難しく感じる部分もありましたが、実際に使ってみるとその便利さを実感できました。 パフォーマンスの向上やオフライン対応など、ユーザー体験を大きく改善できる可能性を秘めていると思いました。

## おわりに
今回、私自身まだまだ駆け出しエンジニアとして、``indexedDB``を使った開発経験を共有させていただきました。正直なところ、この方法が最適だとは思っていませんし、もっと効率的なアプローチがあると思っています。
そのため、経験豊富な先輩エンジニアの方々からご意見やアドバイスをいただけたら非常にありがたいです。「ここはこうしたほうがいいよ」とか「別の方法も考えられるね」といったコメントを大歓迎します。
私たち若手エンジニアにとって、現場で活躍されている方々の知見は本当に貴重です。この記事をきっかけに、様々な視点や経験を共有できる場になれば嬉しいです。
みなさんのフィードバックを楽しみにしています。一緒により良い開発方法を探っていけたらと思います！
【Nextjs・Vercel】apiが使えない

# はじめに
久しぶりのJISSOUに関する記事を書きます。今JISSOUハッカソンが開催されていて、絶賛開発中

# 問題
NextjsをVercelにデプロイしたらroute.tsに書いたapiが使えない！！
curlコマンドでリクエストを投げたけれど、
> **Authentication Required**

という文字列が仕込まれたhtmlが返された。

# 解決策
プロジェクトを選択して、**setting** > **Deployment Protection**の**Vercel Authentication**を無効化する
【プログラミング初心者】0から始めるReact学習 #10 ~CI/CDの導入~

# 2-1. インプット
## 9月13日
本日から**Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版**の<code>JSONPlaceholderからaxiosでデータを取得してみる</code>まで進めていきます。

1～17まで完了しました。
前回、Reactの入門で使った講義とは比にならないくらいインプット量が増えました。
スタイルの当て方どんだけ種類あんねん・・・

7割ほどの理解で先へ進む気持ち悪さがありますが、
全体像を把握してアウトプット作業に移行することを優先します。

しばらくインプットで苦しみそうです（笑）

## 9月16日
本日は**Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版**の
18～25まで完了。

LinkやSwitch、Routeタグを使ったリンク遷移について学習していきました。

ここ数日はインプットがメインになるため上記のようにダイジェストで学習記録を付けていこうと思います。

## 9月17日
本日は**Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版**の
25～32まで完了。

Atomic Designについて学びました。
Atom → Molucule → Organism → Templete → Pageの順番に連結が多くなっていくので、
開発の際にフォルダを分けて分かりやすい名前にすることが大切だと感じた。

## 9月18日
本日は**Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版**の
33～44まで完了。

正直、こんなものがあるのか～くらいの理解度です（笑）
しかし、アウトプットが大切だと思うので、明日からは「課題2」に取り組んでいこうと思います。

## 学習進捗
1.Web開発の基本（10日間）9/4-9/13
2.CI/CDの導入（10日間）9/14-9/23　←今ココ
3.TypeScriptの導入（10日間）9/24-10/3
4.名刺アプリの開発（10日間）10/4-10/13
5.個人開発アプリのリリース（20日間）10/14-11/2
MisskeyのPluginやThemeをMisskeyの機能のみを活用して配布する

# はじめに
想定する読者層

* Misskey Plugin/Themeを作ったことがある
* Misskey Plugin/Themeの配布を検討している
* 自分でサーバーを持つ気がない

https://misskey-hub.net/ja/docs/for-developers/publish-on-your-website/

この記事は昔書いた記事を少し書き換えたような記事です。
前の記事と同じことを繰り返し書いてますが、これはこの記事だけで情報が完結するようにするためです。

https://qiita.com/the_quick_fox/items/e673d1a1c49f6ea8ebc2

# メリット
まず初めに、この手法を使った場合のメリットを明らかにしていきます。

## 製作者のメリット
1. サーバーを自分で用意する必要がない
1. 専門的な知識がそれほど必要ない
1. 無料

## ユーザーのメリット
1. インストールが簡単になる

# 手順

## 前提
以下の環境が整っていることを前提とします。

* Misskey PluginまたはThemeの**ソースファイル**がある
* 改行コードが`LF`(`\n`)である

また、以下の環境があることを推奨します。

* パソコンからもろもろの作業ができる

ただ、一応スマホからでもできないことはないと思います。

## ソースファイルからhash値の計算
ソースファイルのハッシュ値を計算しましょう。`sha512sum`コマンドであればターミナルからhash値を計算できます。
```
$ sha512sum {FILE_NAME}
{HASH}  {FILE_NAME}
```
コマンドを実行した結果はhash値と入力したファイル名が出力されます。
ここで出力されたhash値はファイルの整合性チェックに使います。

## JSONの用意
```json
{
    "type": "{TYPE}",
    "data": "{CODE}"
}
```

`{TYPE}`は`plugin`か`theme`のいずれかです。適当な方を選びましょう。
`{CODE}`はリソースのソースコードを**文字列**で入力します。このとき、改行(`\n`)やダブルクオーテーション(`"`)、バックスラッシュ(`\`)などは適当な形でエスケープする必要があります。

## MisskeyのドライブにJSONをあげる
前章で作ったJSONをMisskeyのドライブにあげましょう。
MisskeyのドライブにJSONをあげるとメディアごとにURLが割り振られます。
URLができたら一度アクセスし、適当なJSONが返ってくることを確認してみましょう。

## 配布用URLの作成
配布リンクは以下のような形式になります。
```url
https://{HOST}/install-extentions?url={URL}&hash={HASH}
```
`{HOST}`はMisskeyサーバーのホストドメインです。他のホルダーにはそれぞれ適当な値を入れてください。

# 備考
インストール時のエラーに関しては、以下を参考にしてください。

https://qiita.com/the_quick_fox/items/e673d1a1c49f6ea8ebc2
Microsoft/Azureドキュメントの更新履歴を確認する

Azureに関するドキュメントはクラウドということもあり頻繁にドキュメントが更新されています。Azure含め、Microsoftの公式ドキュメントはGitHubで管理されているので、GitHubのコミット履歴を確認することでどこが変更されたかを追跡することができます。

:::note warn
2024年9月時点の手順です。
:::

1. 履歴を確認したいページを開く
　
1. 日本語で表示している場合はページ上部の「英語で読む」ボタンを押し、英語表示に切り替える
![read_english.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/134a62de-0e13-4e61-7957-1d990bc3d163.png)
　
1. ページ上部のアイコンに鉛筆マークの「Edit This Document」ボタンが出てくるのでクリック
![edit_document.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/9715a467-7037-6e89-2e36-1ef918e2ea47.png)
　
1. GitHubへ遷移します。右上の「History」をクリック
![github01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/850da88b-7d03-d3a3-f6b1-bb6e0f91f31e.png)
　
1. コミット履歴が出てきます。ここから更新履歴をたどっていきます
![github2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2850747/8b2e583b-704a-a0d5-2b03-b2499b58868e.png)

### 想定される利用シーン
* あれ、以前調べた時と書いてあることが違う？変更履歴を確認したい。
* いつのまにかプレビューの機能がGAしているようだ。いつGAの表記に変わったか確認したい。

### 日本語ドキュメントの履歴は？
前は日本語ドキュメント（ja-jpとなっているもの）の履歴も見れたと思うのですが、いつからか英語ページでなければ編集ボタンが出てこなくなりました。日本語は機械翻訳しているページもあるので、その関係かもしれません。履歴を追う場合はあきらめて英語のドキュメントを確認しましょう。