OmniAICreator/Qiita-1.07M huggingface dataset:
技術記事の校正プロンプトと ChatGPT で最後まで出力しきる Tips

# はじめに
私はよく技術記事を書いています。多くは自分自身が後で参照するためですが、せっかく書くのだから、多くの人に読んでもらいたいと思っています。記事の内容はともかく、形式や作法を整えるだけで、記事はずっと読みやすくなります。また、技術記事では、技術のバージョンや前提条件の重要性が高いため、ニュース記事の校正に用いられる視点とは異なる視点が必要になることがあります。私が個人的に最低限気をつけているポイントを挙げて、それを元にChatGPTに校正を依頼するためのプロンプトを作成しました。

# 目次

- prompt
- 校正結果の before after を比較するコマンド
- 校正結果を ChatGPT で最後まで出力しきる Tips
- 最後に

# prompt 

```
あなたはIT技術分野のレポートのレビュアーです。
与えられたドキュメントに対して以下の校正を行う事を期待しています。
step by step で実行してください。

# 校正ルール
- 1. 校正は指摘事項とformat事項の両方を実施する
- 2. 指摘事項に関する内容をフィードバックする
- 3. 2の後に、ドキュメントにformat事項を適用した後の内容を全てを出力する
    - This is very important. otherwise, the next step will not work.
    - markdown の code block に出力してください
    
# 指摘事項
- 主題になっている技術のバージョンに関する明確な記述が無い場合に指摘をする
- 主題になっている技術の簡単な説明が無い場合に指摘をする
- 誤字や誤表現と思われる箇所を指摘する
- 似たような意味で利用している(表記が揺れている)言葉を指摘する

# format事項 (実施事項)
- markdown を使った表現に整える
- 英単語の前後にはスペースを挿入する
- です・ます調に整える
- "はじめに"という章を用意する
    - "# はじめに" という章をドキュメントの最初に用意する
    - "# はじめに"章の文が存在していなかった場合には、<ここにはじめにを書く>と記載する
- "最後に"という章を用意する
    - "# 最後に" という章をドキュメントの最後に用意する
    - 文に"最後までお読み頂きありがとうございます。励みになるので、良かったらいいね 👍 をお願い致します。" を記載する
- "目次"を`# はじめに`の次に用意する
    - HTMLの h1,h2 タグレベルの見出しから目次を作成する

# format事項 (禁止事項)
- 文章を丸ごと削ることをしない

校正の覚悟はできていますか?できているなら、"オレはできてる"と回答してください。
```

以下のように出力され、出力が続きます。

![スクリーンショット 2024-01-05 13.58.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/5b3ece3d-a060-79dd-4acc-ffad8aea2b80.png)


# 校正結果の before after を比較するコマンド

zsh 環境において、以下のコマンドを実行すれば簡単に before after を比較することができます。


```
cat << 'EOF' > after.txt
<ここに結果を貼る>
EOF

cat << 'EOF' > before.txt
<ここに原文を貼る>
EOF

git diff --no-index before.txt after.txt
```

ex. 以下のように表示されます。

![スクリーンショット 2024-01-05 12.52.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/d8915d34-da49-202d-0787-c58013bde38f.png)

# 校正結果を ChatGPT で最後まで出力しきる Tips
- 内容を省略して出力してくることへの対処
    - 恐らく、 ChatGPT は出力の概要を示してくれているだけなので、<具体的な項目>から実行してみようと指示すると省略無しで出力してくれます
        - ![スクリーンショット 2024-01-05 11.29.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/a36432f2-f1ae-809c-e9ef-dbcabb3ddda1.png)


- "続きを生成する" を実行するとエラーが起きる
    - 画面をリロードした後に、続けてとコメントすると生成を再開することが多いです
      - 発生したエラー
        - ![スクリーンショット 2024-01-05 11.31.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/0c0fdb59-9a62-efab-41a6-a0290b5c8b73.png)
      - "続きを生成する"ボタンでなく、続けてとメッセージすると再開することが多いです
        - ![スクリーンショット 2024-01-05 11.23.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/19d23c88-879f-ce1b-98a5-a9c929ede114.png)
    - エラー原因がクォーターの場合は素直に待ちましょう
        - ![スクリーンショット 2024-01-05 11.32.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110482/dc13a5a3-ede8-cf0a-3248-206745f9dfd5.png)

# 最後に

最後までお読み頂きありがとうございます。励みになるので、良かったらいいね 👍 をお願い致します。
You can still open each one individually by opening a file within.

# 事象

Visual Studio Codeでサブモジュールがたくさん含まれているGitリポジトリを開くと`The "xxx" repository has x submodules which won't be opened automatically. You can still open each one individually by opening a file within.`という警告が表示される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/ff11a6dd-a2a1-6b71-3727-791b2e772bf2.png)

# 原因

Visual Studio Codeが開いたGitリポジトリに含まれるサブモジュールのリポジトリ情報を読み込むが、その数に上限が設定されている。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109634/60671e72-0d75-0b35-bf4b-30cce4d68d7c.png)

# 解決方法

## 解決方法1

`Git: Detect Submodules Limit`の値を増やす。

## 解決方法2

`Git: Detect Submodules`のチェックを外す。
読書感想　新人ガールITIL使って業務プロセス改善します！

# 書籍名「新人ガールITIL使って業務プロセス改善します！」
著：沢渡あまね

# 読もうと思った動機
仕事で情シスに任命され、事前調査のために読みます


# 印象に残った部分

## ITILとは

ITのプロセスマネジメント手法。

### メリット
いいとこ取りができる。

ビジネスを主軸とした考え方なので経営者に納得してもらいやすい

## 登場人物
顧客、サービスプロバイダ、サプライヤ、ユーザといった人物が現れる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/cd3ffbe7-46ee-2cbb-6568-fad3901326bf.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/54660f1f-256a-f896-bfeb-54c117b97d9c.png)




### ITILのサービス

サービス
＝ 顧客に特定のコストやリスクを負わせることなく、顧客に価値を提供する手段である。
＝「有用性」＋「保証」


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/f6d64a51-dcb0-4ab4-c788-7f647ed0aee7.png)

### ITILのプロセス

特定の目的を達成するための一連の活動。
プロセス＝〇〇管理　とも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710623/8e3927af-50b7-9d24-8082-f04b759a89e9.png)


### インシデント管理と問題管理
インシデント管理は、迅速に正常なサービスに回復させるための活動。
問題管理は、インシデントの原因を特定し、根本解決および再発防止を図るためのプロセス

### ナレッジ管理

業務に関する知識やノウハウを、サービス提供組織全員で共有すること。

#### SECIモデル
Socialization（共同化）:個人の暗黙知を獲得、認識するプロセス。
Externalization(表出化)：個人の暗黙知を言語化して形式知にするプロセス。
Combination(連結化)：複数の形式知を組み合わせて新たな形式知を想像するプロセス。
Internalization(内面化)：新たな形式知を得た個人が、実践を通じてまた新たな暗黙知を体得するプロセス。

#### 「場」の創造
フリーアドレス化、勉強会、社内SNSなど

# 実践できること or 感想

ITILの大まかな流れを把握できて満足です。
読みやすい文体で詰まることなく読めたのもGoodですね。
IT以外にも応用できる考え方ってのが特に勉強になりました。

問題管理とインシデント管理は業務にも使えそうだと思いました。


## 体系的な教科書を読み進める。

体系的な知識は得づらかったです。
ITIL4ファンデーションの教科書も一読します。
資格を取るかどうかは現時点ではノーコメントです。
個人開発Webサイト [就職先・転職先を見極めるためのサイト] の技術紹介

就職先・転職先を見極めるためのサイト (~~https://career-change-supporter.com/~~) というWebサイトを作りました（損益分岐点を超えられなかったため、2024年5月10日にサービスを停止しました）その開発で利用した技術についてまとめようと思います。需要があるかわからないので、内容は薄めで投稿します。もし需要がありそうで、かつ記事内容をまとめる時間が確保できそうなら内容を追加、更新していこうと思います。

追記1
サービス終了に伴って[ソースコード](https://github.com/Ken-Miura/career_change_supporter)を公開しました。リリース時に使っていたソースコードはpublish-release-1というタグで、PAY.JPを利用したクレジットカード決済の実装があるのはthe-commit-where-I-decided-to-farewell-payjpというタグです。

追記2
ソースコードに関する補足。音声通信を行う際、ユーザー同士が匿名でやり取りを行えるようクライアントサイドで音声を加工し、それをSkyWay上に流しています。音声を加工するライブラリで著名なものにTone.jsが有りますが、このサイトではあえてそれを使いませんでした。理由としては、Tone.jsを使うとスマホ向けのブラウザで音声加工がうまく機能しなかったためです（今はどうなっているかわかりませんが、2023年春頃のTone.jsの最新バージョンでは駄目でした）そのためTone.jsを使わず、独自実装で音声加工をしています。

# 言語、フレームワーク
## フロントエンド
Typescript、Javascript（99パーセントTypescript、1パーセントJavascript程度の割合）+ Vue3

## バックエンド
Rust (脆弱性が見つかった際に攻撃対象になることを避けるため、使用フレームワークは非公開にします)

# 利用しているサービス
## SkyWay
ユーザー同士の音声通信を実現するために利用しています。SkyWayは、2024年1月現在、旧版と新版のサービスが並行して可動していますが、[就職先・転職先を見極めるためのサイト](https://career-change-supporter.com/) では新版のサービスを使っています。

## ~~PAY.JP~~
　クレジット決済機能を実現するためにPAY.JPを利用する予定でしたが、本番環境の利用申請時に審査に落ちてしまったため利用を取りやめました（利用可能な環境には、テスト用のステージング環境と実際にお金が動く本番環境があり、本番環境は利用には審査が必要です。その審査に落ちました）
　[就職先・転職先を見極めるためのサイト](https://career-change-supporter.com/) はCtoCサービスです。CtoCサービスは審査が厳しいと事前に把握していたので、審査にパスするための要件を入念にチェックして実装したり、PAY.JPの問い合わせ担当にサービス内容について問い合わせて問題ない旨の回答を頂いていましたが、結局審査は通りませんでした。審査は、落ちた理由は非公開、かつ再申請不可とのことでしたので利用を諦めました。そのため、決済にはクレジットカードではなく、銀行振込で対応するのように修正しました。
　ただ、実装は存在し、そこで得た知見（PAY.JP PlatformのPayouts型の実装方法、PAY.JPはRust用のSDKを公開していない（2024年1月現在）ため、自前でPAY.JP用のRUSTの実装を準備、3D Secureの機能の実装、Vue3におけるpayjp.js v2の利用等）も多いので記事には記載しておこうと思います。
おまけのRT3052

以下の記事で使っていかなかった、RT3052を使えるようにしてみました。

https://qiita.com/yamori813/items/822ef2403813ffb1aa71

このモジュールの構成は以下のようになります。

![RT3883_Ether.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/74ce2f3b-0516-536f-cc64-9969e871fa46.png)

RT3883とRT3052は両方ともSPI Flashで8Mと2Mになります。

RT3052のFlashにはu-bootのみ入っていて、tftpで設定ファイルと実行バイナリをRT3883側から拾って起動するようになっていました。u-bootのコマンドラインには入れるのですが、なにもできません。実行される処理は環境変数にはなく、ハードコードされているようです。

しかたがないので、u-bootを焼直します。SOP8のFlashをはがして、DIP平ピンのソケットをつけます。いろいろ調べていたら、去年すでにRT3052 SPI用のu-bootはビルドしていて、uboot.imgを8M Flashに焼いたらなんなく起動しました。

起動したのですが、ネットワークの設定がなかったので、menuconfigで設定を変更しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/1f86fe6c-1492-aa87-a5e3-ee76578d8305.png)

これでビルドしたところ、vtss_init()が無いとエラーが出て、おそらくvitesseのswitch用のコードと思われ必要ないので、とりあえずコメントアウトしてビルドを通しました。

```
U-Boot 1.1.3 (Jan  5 2024 - 06:47:10)

Board: Ralink APSoC DRAM:  16 MB
relocate_code Pointer at: 80fb4000
config usb....
******************************
Software System Reset Occurred
******************************
spi_wait_nsec: 3e 
spi device id: c2 20 17 c2 20 (2017c220)
find flash: MX25L6405D
raspi_read: from:30000 len:1000 
.raspi_read: from:30000 len:1000 
.============================================ 
Ralink UBoot Version: 3.6.0.0
-------------------------------------------- 
ASIC 3052_MP2 (Port5<->GigaSW)
DRAM component: 256 Mbits SDR
DRAM bus: 32 bit
Total memory: 64 MBytes
Flash component: SPI Flash
Date:Jan  5 2024  Time:06:47:10
============================================ 
icache: sets:256, ways:4, linesz:32 ,total:32768
dcache: sets:128, ways:4, linesz:32 ,total:16384 

 ##### The CPU freq = 384 MHZ #### 
 estimate memory size =16 Mbytes

Please choose the operation: 
   1: Load system code to SDRAM via TFTP. 
   2: Load system code then write to Flash via TFTP. 
   3: Boot system code via Flash (default).
   4: Entr boot command line interface.
   7: Load Boot Loader code then write to Flash via Serial. 
   9: Load Boot Loader code then write to Flash via TFTP. 
```

AR8327の制御はRT3883で行っているのですが、RT3052のポートは閉じていたので、RT3883で以下を実行してRT3052のポートを使えるようにします。

```
# etherswitchcfg reg 0x94=0x10ce
```

これでRT3052のu-bootでネットワークが使えるようになりました。

ZRouterでこのRT3052用の設定を追加してビルドしてイメージを作ります。

SPI Flashの設定はFON2305から、RGMIIの設定はWN-G300DGRからもってきて、mkファイルとdtsファイルを作ります。

これを焼いたところFreeBSDが起動してネットワークも使えました。

RT3883をrebootするとRT3052も再起動します。

世にも珍しいTwin FreeBSDの物理マシンです。メモリが16Mと小さいのですが、なにか面白い使い方を考えてみたいと思います。

WN-G300DGRは斬新なデザインなのですが、こちらはなんか大きくてデザインがいまいちです。同じ所で作られてると思うのですが、なぜでしょうか？
JavaScriptでかの有名な水の移し替えパズルを解く【幅優先探索】

## 元ネタ

https://qiita.com/jerrywdlee/items/c7bbcbb6c68e37e7ef71

## 問題

水が5L入る容器と3L入る容器がある、この2つの容器だけを使って、
4Lの水を量るにはどうすれば良いですか？
水はいくらでも使えるものとします。

## ソース

```js
function 水を捨てる_3L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const result = {
        new容器3Lの容量: 0,
        new容器5Lの容量: 容器5Lの容量
    }
    if (need操作テキスト) {
        result.操作テキスト = "3L容器を空っぽにした。　　";
    }
    return result;
}
function 水を捨てる_5L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const result = {
        new容器3Lの容量: 容器3Lの容量,
        new容器5Lの容量: 0
    }
    if (need操作テキスト) {
        result.操作テキスト = "5L容器を空っぽにした。　　";
    }
    return result;
}
function 水を入れる_3L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const result = {
        new容器3Lの容量: 3,
        new容器5Lの容量: 容器5Lの容量
    }
    if (need操作テキスト) {
        result.操作テキスト = "3L容器を満タンにした。　　";
    }
    return result;
}
function 水を入れる_5L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const result = {
        new容器3Lの容量: 容器3Lの容量,
        new容器5Lの容量: 5
    }
    if (need操作テキスト) {
        result.操作テキスト = "5L容器を満タンにした。　　";
    }
    return result;
}
function 水を移す_3Lから5L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const 移動する容量 = Math.min(容器3Lの容量, 5 - 容器5Lの容量);
    const result = {
        new容器3Lの容量: 容器3Lの容量 - 移動する容量,
        new容器5Lの容量: 容器5Lの容量 + 移動する容量
    }
    if (need操作テキスト) {
        result.操作テキスト = "3L容器から5L容器へ注いだ。";
    }
    return result;
}
function 水を移す_5Lから3L(容器3Lの容量, 容器5Lの容量, need操作テキスト = false) {
    const 移動する容量 = Math.min(3 - 容器3Lの容量, 容器5Lの容量);
    const result = {
        new容器3Lの容量: 容器3Lの容量 + 移動する容量,
        new容器5Lの容量: 容器5Lの容量 - 移動する容量
    }
    if (need操作テキスト) {
        result.操作テキスト = "5L容器から3L容器へ注いだ。";
    }
    return result;
}

const 操作一覧 = [
    水を捨てる_3L, 水を捨てる_5L,
    水を入れる_3L, 水を入れる_5L,
    水を移す_3Lから5L, 水を移す_5Lから3L
];

const キュー = [];
キュー.push({
    容器3Lの容量: 0,
    容器5Lの容量: 0,
    操作手順: []
});

let 答えの操作手順 = undefined;
loop:
while (true) {
    const {容器3Lの容量, 容器5Lの容量, 操作手順} = キュー.shift();
    for (const 操作 of 操作一覧) {
        const {new容器3Lの容量, new容器5Lの容量} = 操作(容器3Lの容量, 容器5Lの容量);
        if (容器3Lの容量 === new容器3Lの容量 && 容器5Lの容量 === new容器5Lの容量) {
            continue;
        }
        const new操作手順 = [...操作手順];
        new操作手順.push(操作);
        if (new容器5Lの容量 === 4) {
            答えの操作手順 = new操作手順;
            break loop;
        }
        キュー.push({
            容器3Lの容量: new容器3Lの容量,
            容器5Lの容量: new容器5Lの容量,
            操作手順: new操作手順
        });
    }
}

let 容器3Lの容量 = 0;
let 容器5Lの容量 = 0;
for (let i = 0; i < 答えの操作手順.length; i++) {
    const 操作 = 答えの操作手順[i];
    const {new容器3Lの容量, new容器5Lの容量, 操作テキスト} = 操作(容器3Lの容量, 容器5Lの容量, true);
    console.log(`${i + 1}: ${操作テキスト}【3L容器: ${new容器3Lの容量}L, 5L容器: ${new容器5Lの容量}L】`);
    容器3Lの容量 = new容器3Lの容量;
    容器5Lの容量 = new容器5Lの容量;
}
```

## 実行結果

```
1: 5L容器を満タンにした。　　【3L容器: 0L, 5L容器: 5L】
2: 5L容器から3L容器へ注いだ。【3L容器: 3L, 5L容器: 2L】
3: 3L容器を空っぽにした。　　【3L容器: 0L, 5L容器: 2L】
4: 5L容器から3L容器へ注いだ。【3L容器: 2L, 5L容器: 0L】
5: 5L容器を満タンにした。　　【3L容器: 2L, 5L容器: 5L】
6: 5L容器から3L容器へ注いだ。【3L容器: 3L, 5L容器: 4L】
```

## 別の方法

https://qiita.com/mogamoga1337/items/9e4a503632c2c4b00cbf
mindの研究 その65

# 概要
mindが、謎なので調べてみた。
練習問題やってみた。

# 練習問題
プログラムランチャーを書け。edgeを起動せよ。

# サンプルコード

```
メインとは
　文字列１は　文字列
　「0：　メモ帳を開く」を　一行表示する
　「1：　電卓を開く」を　一行表示する
　「2：　エッジを開く」を　一行表示する
　「3：　ペイントを開く」を　一行表示する
　「4：　ネオスを開く」を　一行表示する
　文字列入力し　文字列１に　入れ
　文字列１が　「0」に　等しい文字列
　ならば
　　「notepad.exe」を　プログラム実行
　つぎに
　もし　文字列１が　「1」に　等しい文字列
　ならば
　　「calc.exe」を　プログラム実行
　つぎに
　もし　文字列１が　「2」に　等しい文字列
　ならば
　　「"C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe"」を　プログラム実行
　つぎに
　もし　文字列１が　「3」に　等しい文字列
　ならば
　　「mspaint.exe」を　プログラム実行
　つぎに
　もし　文字列１が　「4」に　等しい文字列
　ならば
　　「C:\Neos\NeosProLauncher.exe」を　プログラム実行
　つぎに


```

# 実行結果

```
>run2
0：　メモ帳を開く
1：　電卓を開く
2：　エッジを開く
3：　ペイントを開く
4：　ネオスを開く

```


以上。
踏み台サーバに NordVPN Mesh Network を導入

## 概要
NordVPN の Mesh Network 機能を用いて、外部のネットワークからホームネットワーク内のデバイスに踏み台サーバ経由でアクセスできるようにする。
さらに Traffic Routing を用いて、クライアントからホームネットワーク内のデバイスに LAN の IP を使用してアクセスできるようにする。

![meshnet.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261727/6e9b9e0f-e42a-53ea-3c93-abd0f1fa116c.png)


## Bastion 側の設定

### NordVPN クライアントのインストール

NordVPN クライアントをインストールする：
```
sh <(curl -sSf https://downloads.nordcdn.com/apps/linux/install.sh)
sudo usermod -aG nordvpn $USER
nordvpn login
```
(参考：[https://nordvpn.com/ja/download/linux/](https://nordvpn.com/ja/download/linux/)）

### 初期設定
ホームネットワーク内における接続に VPN が適用されないようにする （例：subnet が `192.168.8.0/24` の場合）：
```
$ nordvpn allowlist add subnet 192.168.8.0/24
```

NordVPN に接続する
```
$ nordvpn connect
```

メッシュネットワークを有効化する。
```
$ nordvpn set meshnet on

# Check peer list
$ nordvpn mesh peer list
````

Mesh Network に登録した Peer ノードには、`<username>-<moutnain>.nord` のようなドメインが自動で割り当てられる。

（参考：- https://meshnet.nordvpn.com/getting-started/how-to-start-using-meshnet/using-meshnet-on-linux）

### NordVPN Token を作成

[NordVPN Dashboard](https://my.nordaccount.com/ja/dashboard/nordvpn/) ページ内にある `NordVPN を手動で設定` のリンク先よりアクセストークンを発行する。

### Crontab で NordVPN へのログインを自動化する
Bastion 側を常に NordVPN に接続したままにするため、`crontab -e` を実行し、crontab に次のコマンドを登録する。次の例では 半日に1回 NordVPN にログインする。
```
0 0,12 * * * nordvpn login --token <nordvpn_token> && nordvpn connect
```
`<nordvpn_token>` には上の手順で作成したトークンを用いる。

### Traffic routing の許可
手順は https://meshnet.nordvpn.com/features/routing-traffic-in-meshnet に従う。

ピアのホスト名は `nordvpn mesh peer list` から確認する。

```
$ nordvpn mesh peer routing allow <peer_host>
$ nordvpn mesh peer local allow <peer_host>
```

```
$ nordvpn set lan-discovery enable
```
## Laptop 側の設定

### NordVPN クライアントをインストール
https://nordvpn.com/ja/download に従って、ラップトップに NordVPN クライアントをインストールする（本記事では Macbook を使用する）。

NordVPN クライアントを起動およびログインし、`クイック接続`ボタンを押すか地図上の地域を選択して NordVPN サーバに接続する。

![connect.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261727/83ed6a23-d645-fbb5-6994-012025d817a3.png)

### Mesh Network の有効化
次の手順により Traffic routing を有効化する。

1. 左メニューの Mesh Network 設定のアイコンを選択する
2. メッシュネットワークを有効化する
3. `すべてのトラフィックをルーティング` をクリックする

![console.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261727/400cca34-6974-7149-f2a6-5e951816ec78.png)

### SSH 設定
`~/.ssh/config` に踏み台の情報を追加する。
```~/.ssh/config
Host bastion
  User <bastion-user>
  Hostname <username>-alps.nord

Host server
  ProxyCommand ssh <bastion-host> -W %h:%p
  User <server-user>
  Hostname 192.168.8.20
```

次のコマンドを実行し、別ネットワーク上のクライアントから、ホームネットワーク上のデバイスに LAN 内の IP に SSH でログインできることを確認する。

```
ssh server
```

## まとめ・感想
ラップトップと踏み台サーバからなる Mesh Network を作成し、外部ネットワークからホームネットワークにリモート接続できること、および Traffic Routing で LAN の IP を用いてホストが解決できることを確認した。
Mesh Network では NordVPN を仲介し、クライアント同士で VPN を確立するため、踏み台サーバを外部ネットワークに公開する必要がない利点がある。

一方、筆者の環境だけかもしれないが、クライアント側 (Macbook Pro M2) から Mesh Network へに再接続しようとすると失敗したり、Traffic Routing を適用して SSH ログインすると通信が非常に低速になるなど、不安定さが気になる場面がいくつかあった。このあたりで改善できる部分があれば、後に追記する予定...。
Pythonで「辞書から要素を削除する」の動作を確認してみた

# 概要

Pythonで「辞書から要素を削除する」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/dictionary/index6.html

# 実装

以下のファイルを作成しました。
```sample.py
mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
del mydict["L"]
print(mydict)

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
#del mydict["P"]

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
val = mydict.pop("L")
print(val)
print(mydict)

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
#val = mydict.pop("P")

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
val = mydict.pop("P", "Not Found")
print(val)
print(mydict)

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
val = mydict.popitem()
print(val)
print(mydict)
val = mydict.popitem()
print(val)
print(mydict)
val = mydict.popitem()
print(val)
print(mydict)

mydict = {"A":"Apple", "L":"Lemon", "O":"Orange"}
mydict.clear()
print(mydict)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
{'A': 'Apple', 'O': 'Orange'}
Lemon
{'A': 'Apple', 'O': 'Orange'}
Not Found
{'A': 'Apple', 'L': 'Lemon', 'O': 'Orange'}
('O', 'Orange')
{'A': 'Apple', 'L': 'Lemon'}
('L', 'Lemon')
{'A': 'Apple'}
('A', 'Apple')
{}
{}
```

# まとめ

何かの役に立てばと。
スペース埋め

スペースで埋めて数字を3桁の文字列にするプログラムを実装しました

```python3
# coding: utf-8
# 自分の得意な言語で
# Let's チャレンジ！！
num = input()
# スペース埋め
ans = "{: >3}".format(num)
print(ans)
```
Anaconda3をmacOSから完全にアンインストールした

## 背景

数年前までanacondaを使っていたが、新たにまたpythonを触る気になった。
そこで、Javascriptでは普段asdfを使っているので、asdf+Poetryでpython環境を0から作ってみようかなと思い、その際、これまで使っていたanacondaは綺麗に消そうと思った。

## やること
anacondaは正直Jupyter Notebookを使うために入れていたくらいの温度感なので、Anaconda3をホストマシンからアンインストールする。

## 手順
Step1: Anaconda3のホームディレクトリの確認
Step2: anaconda-cleanをインストール
Step3: anaconda-cleanをインストール
Step4: .anaconda_backupを削除
Step5: anacondaを削除！
Step6: パスとかの削除
Step7: ショートカットを削除する

## Anaconda3のホームディレクトリの確認
削除する前に、Anaconda3 がどこにインストールされているかを確認する。
独自にカスタマイズしていなければ、多くの人にとってAnacondaをインストールしたディレクトリは通常 ~/anaconda3（または~/opt/anaconda3）だろう。
以下のコマンドをターミナルに入力して実行する。

```terminal:$
$ env | grep CONDA
```

するとおれの場合こんな感じ
```
CONDA_EXE=/Users/ユーザー名/opt/anaconda3/bin/conda
_CE_CONDA=
CONDA_PYTHON_EXE=/Users//ユーザー名/opt/anaconda3/bin/python
CONDA_SHLVL=0
```
`/opt/anaconda3` 下にanaconda3がある。

## Step2: anaconda-cleanをインストール
condaのライブラリが生成したデータファイルを自動で削除を行うパッケージをインストールする。

```terminal:$
$ conda install anaconda-clean
```

途中でインストールしてもいいかの確認がでるので、それらは「y」でいいでしょう。

## Step3: anaconda-cleanを実行

`anaconda-clean` のインストールが完了したら、`anaconda-clean` コマンドを実行して、Anaconda3 のアンインストールを実行。
対象となるフォルダを削除して良いか一個ずつ聞かれるので、「y」と入力して削除していく。

```terminal:$
$ anaconda-clean
```

### 注意点
ぶっちゃけ`anaconda-clean`のコマンドを使用せずに直接 `rm -rf ~/opt/anaconda3` を実行することで、Anacondaをシステムから削除することは可能っぽい。

ただし、`anaconda-clean` コマンドは、Anaconda関連のファイルやディレクトリをクリーンアップするために特別に設計されているもの。
このコマンドは、ホームディレクトリ内のAnacondaの設定ファイルや履歴ファイルなど、Anacondaに関連する隠しファイルや設定を削除することができる。
`anaconda-clean` を使用しない場合、これらの隠しファイルや設定はシステム上に残る可能性がある。

やって損はなさそうという感じかな。

## Step4: .anaconda_backupを削除

anaconda-clean コマンドを以前に実行したとき、`.anaconda_backup`が作成される。これはユーザーのホームディレクトリにあるため、以下を実行。

```terminal:$
$ rm -rf ~/.anaconda_backup
```

## Step5: anacondaを削除！
いよいよ以下のコマンドでanacondaをフォルダごと削除する。

```terminal:$
$ rm -rf /Users/ユーザー名/opt/anaconda3
```
あるいは、
```terminal:$
$ rm -rf ~/opt/anaconda3
```
でいけるはず。

もし上のやり方が、権限がなくて削除できない場合は、sudo で rm を指定して削除してみる。
```terminal:$
$ sudo rm -rf ~/opt/anaconda3
```

## Step6: パスとかの削除

Anacondaをアンインストールした後、.bash_profileか ~/.zshrc ファイルからAnacondaに関連する設定を削除する必要がある。
おれの場合はシェルはzshを使っているので、

```terminal:$
$ nano ~/.zshrc
```
実行して、~/.zshrc ファイルを開く。

bashの人は多分
```terminal:$
$ nano ~/.bash_profile
```
みたいになるのかな。

すると、~/.zshrc ファイルにcondaに関するPATHの記述などがあるので、不必要な部分を削除する。

```
# >>> conda initialize >>>
```
で挟まれたりしてたら、そこが該当箇所かも。

削除したら、`Control + O` を押して変更を保存し、`Control + X` を押してエディタを閉じる。

変更が完了したら、以下のコマンドを実行して、変更を有効にする。
```terminal:$
$ source ~/.zshrc
```

## Step7: ショートカットを削除する
最後に「アプリケーション」ディレクトリに Anaconda-Navigator.app というショートカットが残っている場合、それを削除して終わり！



## お疲れ様でした。

わからないところ、間違っているところ、もっといい方法がある場合は、コメントでもDMでも教えてください！
計算力学技術者(振動2級)向け  計算手法一覧

計算力学技術者(振動2級)の問題でよく出てくる計算手法に関して、各分類毎と特徴を整理する。

## 連立一次方程式の解法
直接法：行列変形を繰り返して厳密解を算出する。行列次数が$n$の場合、計算量は$O(n^3)$程度となる。
反復法：繰り返し演算によって近似解を算出する。高速に計算可能だが、すべての問題(行列)に適用できるわけではない。
| 手法名|直接法/反復法|参考記事|
|:----------|:------|:------|
|ガウス法|直接法|-|
|ガウス-ジョルダン法|直接法|-|
|LU分解法|直接法|-|
|ガウス-ザイデル法|反復法|-|
|SOR法|反復法|-|
|共役勾配法|反復法|-|




## 固有値分解の数値計算(確認中)
手法によって、すべての固有値と固有ベクトルが求められるものや特定個数のみ求められるもの等々の特徴があるので以下にまとめる。
固有値と固有ベクトルが同時に算出されるものもあれば、固有ベクトルが算出できた後に固有値が求まるといったパターンも存在する。その場合は、以下表内に()書きで書いた。例えばべき乗法は固有値の欄が()書きになっているので、最大固有値に対応する固有ベクトルが先に算出され、それを利用して最大固有値を求める。
| 手法名|解法の特徴|固有値|固有ベクトル|参考記事|
|:----------|:------|:-------|:------|:------|
|べき乗法|初期ベクトルと行列の積の繰り返し|(最大値のみ)|最大固有値に対応するベクトルのみ|-|
|逆反復法|↑|(最小値のみ)|最小固有値に対応するベクトルのみ|-|
|ヤコビ法|行列の相似変換の繰り返し|全て|全て|-|
|QR法|行列の相似変換の繰り返し(QR分解の対角化)|全て|?|-|
|サブスペース法|小さな行列に対してべき乗法やヤコビ法を適用|指定個数|-|-|
|ランチョス法|(3重対角)|指定個数|?|-|
|ハウスホルダー法|ハウスホルダー変換による対角化(3重対角)|全て|?|-|

計算力学技術者試験問題の中で以下の特徴が問われることはないが、各手法によって適用できる行列があるため整理する。
| 手法名|Aの特徴|
|:----------|:------|
|べき乗法|非対称行列でも可|
|逆反復法|↑|
|ヤコビ法|対称行列のみ可|
|QR法|対称行列のみ可|
|サブスペース法||
|ランチョス法|疎行列向け|
|ハウスホルダー法|対称行列のみ可|





## 微分方程式の時刻歴応答の数値計算

| 手法名|陽解法/陰解法|タイプ|参考記事|
|:----------|:------|:------|:------|
|オイラー法|陽解法|標準型(1階微分型)|[こちら][EURK]|
|ルンゲクッタ法|陽解法|標準型(1階微分型)|[こちら][EURK]|
|ニューマーク$\beta$法|陰解法|MCK型(2階微分型)|[こちら][NMB]|
|ウィルソン$\theta$法|陰解法|MCK型(2階微分型)|[こちら][WilsonT]|
|フーボルト法|陰解法|MCK型(2階微分型)|[こちら][Houbolt]|

[EURK]: https://qiita.com/TbsYS/items/b1c03c6d3d470287bd6b
[NMB]: https://qiita.com/TbsYS/items/764c80491a6df1ba8831
[WilsonT]: https://qiita.com/TbsYS/items/0e64d6313bbddc0cfa1f
[Houbolt]: https://qiita.com/TbsYS/items/632dc6498f16db6380d3



## 微分方程式の離散化解法(確認中)
| 手法名|解法の特徴|参考記事|
|:----------|:------|:------|
|重み付き残差法|ガラーキン法:重み関数に試行関数の基底関数を用いる|-|
|↑|選点法:重み関数にディラックのデルタ関数を用いる|-|
|↑|最小二乗法:二乗誤差を用いる|-|
|レイリーリッツ法|-|-|
|差分法|-|-|




## 有限要素法 アダプティブメッシュ法
応力集中部を持つ要素モデルの解析制度を向上させるための手法
| 手法名|説明|
|:----------|:------|
|P(Polynomial)法|形状関数の次数を上げる|
|H(Height)法|メッシュサイズを細かくする|
|R(Relocation)法|メッシュを移動させる|
LangChainを用いてHuggingFaceモデルをローカルで使う

# 概要
HuggingFace Hubに登録されているモデルをローカルにダウンロードして、LangChain経由で対話型のプログラムを作成する。

# 前提条件
ランタイムは Python 3.11.6 を使用する。今回使用するモデルには、比較的汎用的な計算機でも動作する `"TinyLlama/TinyLlama-1.1B-Chat-v1.0"` を採用した

使用する Python パッケージは以下の通り。
| パッケージ名 | バージョン |
| ---- | ---- |
| langchain | 0.0.322 |
| transformers | 4.35.2 |
| huggingface_hub | 0.20.2 |

# 実装コード
実装は以下の通り。

`snapshot_download`関数でリポジトリのスナップショットを撮り、そのスナップショットにあるファイルを元に tokenizer と model を準備する。次に`HuggingFacePipeline`クラスをインスタンス化し、これと`ChatPromptTemplate`でチェーンを作成し、`chain.invoke`メソッドで実行する。
```python: app.py
from langchain.llms.huggingface_pipeline import HuggingFacePipeline
from langchain.prompts import ChatPromptTemplate
from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline
from huggingface_hub import snapshot_download

# 1.HuggingFaceからモデルをダウンロード
model_id = "TinyLlama/TinyLlama-1.1B-Chat-v1.0"
download_path = snapshot_download(repo_id=model_id)

# 2.TokenizerとModelをスナップショットからインスタンス化
tokenizer = AutoTokenizer.from_pretrained(download_path)
model = AutoModelForCausalLM.from_pretrained(download_path)

# 3.HuggingFacePipelineを作成
# ref. https://python.langchain.com/docs/integrations/llms/huggingface_pipelines
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=256)
hf = HuggingFacePipeline(pipeline=pipe)

# 4.ChatPromptTemplateを作成
prompt = ChatPromptTemplate.from_template(
    "
You are a chatbot who can help code!

{question}

"
)
chain = prompt | hf

# 5.Chainの実行
question = "Write me a function to print out 'Hello, World!' to the CLI in Python."
answer = chain.invoke({"question": question})
print(answer)
```

# 実行結果
実行した結果は以下の通り。
スナップショットから `"TinyLlama/TinyLlama-1.1B-Chat-v1.0"` のデータをフェッチし、LangChainを介してモデルとの対話を行えている事がわかる。

````text: bash
$ python app.py
Fetching 10 files: 100%|█████████████████████████████████████████████████████████████| 10/10 [00:00<00:00, 10860.45it/s]

Certainly! Here's a Python function that prints 'Hello, World!' to the CLI:

```python
def print_hello_world():
    print("Hello, World!")
```

To use this function, simply call it with no arguments:

```python
print_hello_world()
```

This will print 'Hello, World!' to the CLI. Note that this function assumes that you have already imported the `print` function from the `sys` module. If you're not using Python 3.6 or later, you may need to import the `print` function explicitly:

```python
from sys import print as print_
```
````

# 補足：GPUによる推論時間の短縮
GPUが利用できるのであれば、引数に`device=0`を指定することで、計算時間をかなり短縮できる。
```python: app.py (抜粋)
pipe = pipeline("text-generation", model=model, tokenizer=tokenizer, max_new_tokens=256, device=0)
```

以下は i7-13700F + RTX 4070 の構成で、10回推論を行ったときの計算時間の平均である。
※ かなり雑な計測なので、実際に手元で試してほしい
| 計測ケース | 計測時間（秒） |
| ---- | ---- |
| CPU のみ | 24.3  |
| GPU サポート | 2.3 |

# 参考文献
https://huggingface.co/TinyLlama/TinyLlama-1.1B-Chat-v1.0/tree/main

https://python.langchain.com/docs/integrations/llms/huggingface_pipelines

https://qiita.com/suzuki_sh/items/0b43ca942b7294fac16a
【TypeScript】画面表示までの仕組みを図解で理解する

# はじめに

先日、下記動画を用いてTypeScriptを勉強したときに、そもそもどうやってTypeScriptで書いたコードを画面で表示させるのか？？といった概念理解が難しいなと感じました。勉強する前に、TypeScriptを用いたソースコードを実務で眺めていたのですが、仕組みをほぼ理解していなかったため、「なぜwebpackやNode.jsを途中で使っているのか？」「bundleって何？」など疑問が多く出ていました。
そのため、TypeScriptで書いたコードの画面表示方法(build手順)を図解形式でまとめました。皆さんの理解の一助になれれば幸いです。

参考動画：https://www.youtube.com/watch?v=qSHlXcSces8

# 画面表示までの仕組み

TypeScriptファイルを作成して画面を表示させるまでの流れは以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/2d3f0922-eb82-d5e1-2344-28733e71b4d8.png)

ここでは、画面表示までの流れ(=build手順)を説明します。
全体の流れとして、**①コンパイル→②バンドル→③PC表示**の3ステップとなります。

### ①コンパイル
ここでは、typescriptを用いて、TypeScript構文をJavaScript構文へ変換することを行っていきます。この作業をコンパイルと呼びます。実際にコーディングを行っていく場合は、管理ファイル`tsconfig.json`から初期設定を行います。

### ②バンドル
次に、webpackを用いて、複数のJavaScriptファイルを1つのファイルにまとめていきます(ファイルをまとめる工程をバンドルと呼びます)。webpackとは、依存関係を考慮しながらファイルを1つにまとめるバンドラであることから、バージョン修正を手動で行うことが不要であるため手間が大幅に削減できます。コーディングを行う場合は、`webpack.config.js`から初期設定を行います。

### ③PC表示
最後に、Node.jsを用いて、JavaScriptファイルから画面表示まで行っていきます。通常は、JavaScriptファイルはブラウザ上でのみ動作可能であるため、OSの機能(ファイルの読み書きやネットワーク通信など)が使えません。そこで、Node.jsを導入することで、OSの機能が利用可能となり、JavaScript構文を用いた画面表示が可能となります。Node.jsのより詳しい説明は下記リンクになります。また、コーディングを行う場合は、`package.json`から初期設定を行います。

Node.jsの詳細説明：https://qiita.com/non_cal/items/a8fee0b7ad96e67713eb

# 最後に

上記の仕組みを経て、TypeScript構文を画面上に表示することが可能となります。
今回の図解を通して、個人的にはかなり整理ができました。次は、TypeScriptの型宣言をまるっと理解できればと思っています。
nohupでnodeがうまく実行出来なかった時

## 注意
node.js及びnpmを導入している前提で書きます。
あくまでUbuntu初心者が書いてます
ご指摘等はお手柔らかにお願いします。
## 最初に
自分の環境はこんな感じです。
Contabo VPS
Ubuntu 20.04.6LTS
# 自分の場合
Ubuntuでプログラムを常駐させようとして以下のコマンドを実行したんですがターミナルを閉じると終わっちゃうんです
```console
$ nohup node app.js &
```
# 対処法
自分がとった対処法は**foreverを使う**です

### foreverをインストール
```console
$ sudo npm install forever -g
```

### foreverを使って起動
> cdを忘れずに!
```console
$ forever start app.js
```
これで起動できたかと思います。
## 補足
#### リスト
```console
$ forever list
```
#### ストップ
```console
$ forever stop <リストの番号>

例:
$ forever stop 0
```
# 最後に
systemdを使うなど他にも方法は色々あるので是非他にも試してみてください
Node.jsやTSについての記事を他にも作っているので是非ご覧ください
# 引用
https://www.npmjs.com/package/forever
【Tips】Curlコマンドでトークン生成に失敗したときの対処法

# 背景
Windowsで「API キーを使用した IAM トークンの生成」をするために、マニュアルにしたがってCurlコマンド実行したところ、エラーになり、対応に時間を要しました。対応内容について、備忘録として残しておきたいと思います。

# 該当のマニュアル
https://cloud.ibm.com/docs/account?topic=account-iamtoken_from_apikey

# エラー箇所
Windowsで下記のCurlコマンドを実行すると、エラーになりました。（MY_APIKEYの部分は、変更してください）

curl -X POST 'https://iam.cloud.ibm.com/identity/token' -H 'Content-Type: application/x-www-form-urlencoded' -d 'grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=MY_APIKEY'

# 対応内容
WindowsでCurlコマンドを実行する場合は、ダブルクォーテーションで良いようです。つまり、以下です。（MY_APIKEYの部分は、変更してください）

curl -X POST "https://iam.cloud.ibm.com/identity/token" -H "Content-Type: application/x-www-form-urlencoded" -d "grant_type=urn:ibm:params:oauth:grant-type:apikey&apikey=MY_APIKEY"

# まとめ
調査に時間を要してしまったので、誰かのお役に立てれば幸いです。
GCS をよりセキュアに。ストレージのレガシーバケットオーナーのロールをつけていませんか？Storage オブジェクト閲覧者だけで blob は取得できます

Google Cloud Storage の blob を読み取るとき、バケットの権限が過剰になりがちです。

たとえば Google Cloud の公式ドキュメントのコードを抜粋して説明します。 https://cloud.google.com/storage/docs/downloading-objects?hl=ja#storage-download-object-python

不要なコメントを削除し、説明用のコメントを追加しています。

このコードは指定の Cloud Storage に置かれたオブジェクトをダウンロードするコードです。

```python
from google.cloud import storage

def download_blob(bucket_name, source_blob_name, destination_file_name):
    """Downloads a blob from the bucket."""
    bucket_name = "your-bucket-name"

    storage_client = storage.Client()

    bucket = storage_client.bucket(bucket_name)  # ※1
    blob = bucket.blob(source_blob_name)
    blob.download_to_filename(destination_file_name)

    print(
        "Downloaded storage object {} from bucket {} to local file {}.".format(
            source_blob_name, bucket_name, destination_file_name
        )
    )
```

このコードは、実行時に storage.objects.get だけでなく storage.buckets.get の権限を必要とします。試しにStorage オブジェクト閲覧者(roles/storage.objectViewer)のロールに所属した状態で実行すると、次のような storage.buckets.get を要求するメッセージに遭遇します。

```
does not have storage.buckets.get access to the Google Cloud Storage Bucket
```

ちなみに storage.buckets.get の権限は[公式ドキュメント](https://cloud.google.com/storage/docs/access-control/iam-permissions?hl=ja#:~:text=%E6%9C%89%E5%8A%B9%E3%81%AB%E3%81%99%E3%82%8B%E3%80%82-,storage.buckets.get,-%E3%83%90%E3%82%B1%E3%83%83%E3%83%88%E3%81%AE%E3%83%A1%E3%82%BF%E3%83%87%E3%83%BC%E3%82%BF)にて 次のように説明されています。

> バケットのメタデータ（IAM ポリシーを除く）を読み取る。バケットの Pub/Sub 通知構成の一覧表示または読み取る。

今回の用途では不要な権限です。ストレージのレガシーバケット(roles/storage.legacyBucketOwner)のロールを付与すれば、エラーはでなくなりますが過剰な権限を付与することになります。


# サンプルコードの問題

サンプルコードの書き方では、必ず storage.buckets.get が必要です。

しかし、コードを書き換えることでStorage オブジェクト閲覧者のロール、ひいては storage.objects.get の権限のみでオブジェクトにアクセス可能となります。

問題の箇所は※1です。 bucket メソッドで storage.buckets.get が必要なリクエストが飛んでしまいます。

次のように Bucket インスタンスを作成すればバケットへのアクセスリクエストが飛びません。

```python
# from google.cloud.storage import Blob, Bucket
blob = Blob(source_blob_name, Bucket(storage_client, name=bucket_name))
blob.download_to_filename(destination_file_name)
```

## 書き換えたコード

全体像は、このようになります。

```python
from google.cloud import storage
from google.cloud.storage import Blob, Bucket

def download_blob(bucket_name, source_blob_name, destination_file_name):
    """Downloads a blob from the bucket."""
    bucket_name = "your-bucket-name"

    storage_client = storage.Client()

    blob = Blob(source_blob_name, Bucket(storage_client, name=bucket_name))
    blob.download_to_filename(destination_file_name)

    print(
        "Downloaded storage object {} from bucket {} to local file {}.".format(
            source_blob_name, bucket_name, destination_file_name
        )
    )
```


## 参考資料

* https://qiita.com/XPT60/items/9161fe5eb75762ea113e
macでVoicePeakをコマンド実行&Python

# VoicePeak
### macでVoicePeakをコマンド実行&Python

:::note info
随時付け足し
:::

```python:command
/Applications/voicepeak.app/Contents/MacOS/voicepeak voicepeak -s "こんにちわ" -o "/Users/~各自のパス~/output.wav" -n "Japanese Male 3" -e happy=50,sad=0,fun=0,angry=0
```


```python:help
  -s, --say Text               Text to say
  -t, --text File              Text file to say
  -o, --out File               Path of output file
  -n, --narrator Name          Name of voice, check --list-narrator
  -e, --emotion Expr           Emotion expression, for example: 
                               happy=50,sad=50. Also check --list-emotion
      --list-narrator          Print voice list
      --list-emotion Narrator  Print emotion list for given voice
  -h, --help                   Print help
      --speed Value            Speed (50 - 200)
      --pitch Value            Pitch (-300 - 300)

```

```python:vp.py
import os
import sys
import subprocess
import platform

# voicepeak.exeのパス
exepath = "/Applications/voicepeak.app/Contents/MacOS/voicepeak"

# wav出力先
outpath = "/Users/~各自のパス~/output.wav"

script = "こんにちわ"
narrator = "Japanese Female 1"
happy=50
sad=50
angry=50
fun=50

# 引数を作成
args = [
        exepath,
        "-s", script,
        "-n", narrator,
        "-o", outpath,
        "-e", f"happy={happy},sad={sad},angry={angry},fun={fun}"
    ]

# プロセスを実行
process = subprocess.Popen(args)

# プロセスが終了するまで待機
process.communicate()
```
Youtube APIを使ってYoutubeのチャットをMinecraftのチャットに流す①

# はじめに
TypeScriptとMinecraft Pluginの学習を行わなければいけなくなったため
備忘録としてここに残す

## 開発環境
* TypeScript
* Node.js
* Java
* PaperMC
* Youtube API

環境構築はしたのですがMinecraftにログインできなくて諦めます...
flutterのconst String.fromEnvironmentの値によってコンパイルが通らなくなる問題

ステージング環境でビルドしようとすると、唐突にコンパイルが通らなくなった。
原因が分かるまでちょっと時間が掛かったのでメモっておきます。

デプロイ先によって設定値を切り替えたい場合は、--dart-define-from-fileを使用するのが便利です。

こんな感じで環境別に設定ファイルを準備します。
```jsonc:dev.json
{
    "api": "https://dev.example.com/v1/",
    "key": "something-dev-key"
}
```
```jsonc:stg.json
{
    "api": "https://stg.example.com/v1/",
    "key": "something-stg-key"
}
```

使う方は、こんな感じになります。
```dart: main.dart
void main {
    var api = const String.fromEnvironment("api");
    var key = const String.fromEnvironment("key");
}
```

ビルドする時は、以下の様に使用する設定ファイルを指定する
```shell
flutter build windows --dart-define-from-file=path/to/stg.json
```

ここまでは、特に問題無いと思います。
今回、ステージングを指定すると何故かコンパイルが通らない。
keyの値を変更すると何故かコンパイルが通る。
何か文字が原因らしいので、軽く確認した範囲では「${<」当たりの文字があるとコンパイルが通らなくなる。
今回は諸事情で、使用できる文字だけにするのが難しかったので別の方法で対応することにしました。

## 結果

使えない文字のある値をbase64でエンコードし実行時にデコードする方法を採用しました。
頻繁に使用する場合は、アプリ起動時の初期化でキャッシュするなりすればよいと思います。
```dart
var key = base64.decode(const String.fromEnvironment("key"));
```

ちなみに、この問題は他環境のmacやlinuxでは、普通にコンパイルできるようなのでwindows環境限定の問題っぽいです。
というか、恐らくバグですね。
PythonのLinter兼Formatter「Ruff」をVSCodeで使ってみる

# Ruffとは

Rustで書かれたPython向けのLinter兼Formatterです。LinterとFormatterについては以下の記事に分かりやすくまとめられていたため、ぜひご確認ください。

https://zenn.dev/naiq112/articles/df1b32fc08d383

## メリット

Ruffには以下のようなメリットがあります。

### 動作が高速

Rust製ということもあり、従来の静的コード解析ツールと比べてかなり高速です。

![Ruff](https://user-images.githubusercontent.com/1309177/232603516-4fb4892d-585c-4b20-b810-3db9161831e4.svg#only-light)

### ツールを一つにまとめられる

従来はLinterにFlake8、FormatterにBlack、Import sortingにisortというように、目的に合わせて別のツールを導入しなければなりませんでした。Ruffはこれらの役割をすべて担うため、他のツールを導入する必要がありません。

# 導入と使用
VSCodeを用いてRuffを導入し、簡単なPythonコードを書いてみましょう。

## 1. 拡張機能のインストール

VSCodeの拡張機能が公式から提供されているためインストールします。
https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff

## 2. setttings.jsonの設定

```jsonc:.vscode/settings.json
{
    "[python]": {
        "editor.codeActionsOnSave": {
            "source.organizeImports": "explicit" // コード保存時にimport行を整理
        },
        "editor.defaultFormatter": "charliermarsh.ruff", // FormatterにRuffを使用
        "editor.formatOnSave": true // コード保存時にフォーマットを実行
    }
}

```

settings.jsonを記述後、一度VSCodeを再起動しておきましょう。

## 3. pyproject.tomlの設定

```toml:pyproject.toml
[tool.ruff]
select = ["ALL"]
ignore = [
    "D",    # Docstringを書かなくてもよいようにする
    "T201", # 'print()'を使えるようにする
]
```

pyproject.tomlにはRuffを使う上での[ルール](https://docs.astral.sh/ruff/rules/)を記述します。selectには適用するルールを、ignoreには除外するルールを記述します。今回はselectに`"ALL"`を指定して全てのルールが適用されている状態（最も制約が厳しい状態）にし、その中から除外しておきたい項目をignoreに指定するという形式をとっています。（デフォルトの設定は[こちら](https://docs.astral.sh/ruff/configuration/)を参照）

## 4. Hello, World!
それでは簡単なPythonコードを書いてみましょう。

```py:hello.py
def hello() -> None:
    print('Hello, World!')

if __name__ == '__main__':
    hello()
```

hello.pyを新たに作成後、上記のコードをコピペしてみましょう。「ダブルクォーテーションが望ましいがシングルクォーテーションが使われている」といった旨の警告が出ていれば、正しくRuffの設定が適用されている証拠です。ここで、警告箇所を修正したいところですが、一旦無視しておいてください。

他に問題がなければ、コピペしたコードを保存してみましょう。設定が正しく適用されていれば、以下の変更が自動で行われるはずです。

- シングルクォーテーションがダブルクォーテーションになる
- helloメソッドとif文の間の空行が2行になる

このように、RuffはFormatterの機能を兼ね備えているため、自動で体裁を整えてくれます。また、フォーマットの機能とは別に、Linterによる警告であっても軽微なものであれば自動で修正してくれます。

# おわりに

いかがだったでしょうか。現在もRuffの開発は活発に行われており、まだまだ不完全な部分もあります。とはいえ、現時点でかなり完成度は高く、十分実用に値すると考えています。今後の動向も楽しみですね。
新年をスタートさせるためのミニゲームを作りました

## 概要
制限時間内に「スタート」ボタンが何回押せるかを競うミニゲームを作成しました。

このゲームは、シンプルながらもユーザーの反射神経と速さを試すことができます。

また、ログインするとランキングに参加できます。ユーザ名とパスワードで登録できるので、興味がある方は試してみてください。

https://peaceful-meadow-78483-bad183e58e63.herokuapp.com/

![スタートクリック.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/849608/63db705c-9eb2-0b2a-4186-599d7b35cf70.png)

## 技術構成

### バックエンド
RUNTEQで学んだRailsを活用しました。

ただ、RailsではURIの管理のみにし、画面作成はReactに任せました。

このRailsとReactのつなぎの部分には、react-railsというgemを使用しました。
一行書くだけでReactに値を渡せるのでかなり便利です。

https://github.com/reactjs/react-rails

### フロントエンド
画面作成はすべてReactに任せました。

UIの部分では、最近日本で発表されたYamadaUIコンポーネントライブラリを採用しました。
このライブラリは日本発なので、ドキュメントも丁寧で非常にわかりやすかったです。

https://zenn.dev/hirotomoyamada/articles/15b6f46d12841b

https://yamada-ui.com/ja

## ホスト
当初はRender.comを利用しようとしましたが、デプロイに問題が生じたため、Herokuに切り替えました。
DBにはMySQLを採用しました。
Herokuの「JawsDB MySQL」アドオンを利用することで、一定の制限はありますが、MySQLを無料で使用することが可能です。

https://elements.heroku.com/addons/jawsdb

## 苦労した点
### 環境構築
初めはRender.comでデプロイしようとしましたが、Webpackのコマンドがないという下記のようなエラーに直面しました。

```
error Command "webpack" not found.
```

Herokuにデプロイしても同様でした。

調べたところ下記の状況と似ていたので、Herokuでビルドパックの順序を決め、`package.json`にnodeとyarnのバージョンを追加したら上手くいきました。

https://zenn.dev/atsumu22/articles/ab5a531af05e2f


### 効果音挿入
効果音の挿入も一筋縄ではいかず、Shakapacker経由ではmp3の変換に下記のエラーが発生しました。

```
ERROR in ./app/javascript/sounds/correct.mp3 1:3
Module parse failed: Unexpected character '' (1:3)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
(Source code omitted for this binary file)
 @ ./app/javascript/components/GameBoard.js 6:0-49
 @ ./app/javascript/components/ sync ^\.\/.*$ ./GameBoard.js ./GameBoard
 @ ./app/javascript/packs/application.js 17:30-65
```

最終的には音声ファイルをプロジェクトのpublicディレクトリに配置し、直接ファイルを使用することで対応しました。


### React
Reactは初めて触れたため、useEffectやuseStateなどの概念に慣れるのが大変でした。

しかし、生成AIを活用しながら何とか形にすることができました。この経験を活かして、今後はUdemyなどでさらに学びを深めたいと考えています。

## 感想
期限もあったので、シンプルなミニゲームになってしまいましたが、Reactや気になっていたYamadaUIを触るきっかけになって良かったです！

RUNTEQのミニアプリウィークは定期的にやっているみたいなので、次回も参加したいですね。

次は生成AIを活用したアプリ開発に挑戦したいです！

## リポジトリ

https://github.com/shanbenkazuki/startclick
オフラインでChat系AIを使いたいので数クリックで環境を作った

## 背景
ChatGPTなどで盛り上がった昨年、AIにあまり興味がなく横目で見るだけだった。
今更になって興味が出てきたが、入力したデータを学習に使われたりするのが気になる。

なので今回は「オフライン使用可能なChat AI環境」を作って遊んでみる。

## 実施環境 (PCスペック)
MacBook Pro (2021年モデル)
CPU: Apple M1 Pro
System Version:	macOS 14.2.1 (23C71)
Memory:	32 GB

## 環境構築
### LM Studio
https://lmstudio.ai
大規模言語モデル(LLM)を動かすためのアプリケーション
2024/01/05現在でMac / Windows / Linux(Beta)に対応している

MacでMetal(GPU)が使えるようなのでこれにした

参考記事にさせていただいた記事

https://qiita.com/ponnhide/items/b46a95228d0b832f1770


商用利用プランは準備中らしい 今回は私的利用を想定しているので問題ないはず
> Can I use LM Studio at work?
Business use will be possible and is planned! As we get started, we ask you to reach out to the team at team@lmstudio.ai. Please allow us some time to respond.

インストールはDMGファイルを落としてドラッグ&ドロップで終わり。

### 使用するモデルを決める
LLMについて色々情報をまとめてくださっているサイトを発見

https://weel.co.jp/category/ai-dictionary/

そこで気になった`OpenChat-3.5`を使ってみることにします

https://weel.co.jp/media/openchat-3.5#index_id0

他にも色々なモデルの紹介、比較をされている神サイトなので気になる方は是非覗いてください

## モデルのダウンロード&インストール
LM Studioを起動するとこんな画面が出ます
![Screenshot 2024-01-06 at 0.28.30.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/060ca9db-95d9-214f-d060-192cd9fdfda9.jpeg)

画面左のツールバーにある虫眼鏡アイコンを押すとモデルの検索ができます
ここで画面上部検索バーにopenchatと入力すると以下のように結果が出ます
![Screenshot 2024-01-06 at 0.30.12.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/97afcae4-850a-62e6-9e59-6d65de6bd45d.jpeg)

私は今回`TheBloke/openchat-3.5-1210-GGUF`を使うことにしました
各モデルに量子化の方法?が異なるいくつかのバリエーションがありますが、Recommendになっている`Q5_K_M`をダウンロードしました
![image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/951242d5-267f-bbe1-5a21-33ada9458988.jpeg)

ダウンロード完了後、画面左のツールバーにある吹き出しマークを押してチャット画面に移ります
ここで画面上部にあるプルタブから使用するモデルを選択できますので、先ほどダウンロードしたopenchatを選択します
![image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/e785d711-72b6-e954-5b96-0cd27e135da1.jpeg)

あとは画面下部のテキストボックスからAIに聞きたいことを書いて会話ができます
![image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3361273/0c3027a4-2a0b-3812-29d9-7655389223aa.jpeg)
(最後急に英語喋るやん)

GPUを使いたい場合には画面右の`Use Apple Metal (GPU)`にチェックをつけるだけでOKです

## 〆
初めてまともにChat系AIを使いましたが、想像以上に楽しいです。
いろいろな知識を持っている人(AI)をローカルマシンで動かせるなんてすごいなぁ・・・
CPUやメモリはそれなりに喰いますが、使うモデルや設定をもう少し詰めてみたいです。

LM Studioはローカルサーバーとしての機能も使えるため、今後は他のアプリケーションとの連携とかもしてみたい
Spring Boot 何も考えずにwebページを表示してみる

## 前提
Spring Tool Suite 4を使用

## Create new Spring Starter Projectを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/6dacbb6b-b3e7-f73d-6ed0-ba292e047d42.png)

## プロジェクト名を入力しNextボタン
デフォルトは「demo」になっているはず
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/b8fa0dbe-eb14-c42d-0ea6-9a4c9aee3cfc.png)

## Spring Webを選択しFinishボタン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/4eee05ff-db2f-c528-8730-bed89d023815.png)

## Controllerを追加
Controllerとは平たく言うとUrlと処理を紐づけている部分
詳しくはSpring MVCを学習されたし

### Class（javaファイル）を追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/c19126ea-a944-dcd8-1ad1-36f1d0403aa0.png)

### 今回は「DemoController」とした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/88ead776-d41e-a07e-7de4-507cb766b626.png)

## 追加したjavaファイルに以下を追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/ffee1234-59cb-6317-e6ca-44f3f11723e5.png)

~~~DemoController.java
package com.example.demo;
   
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class DemoController {

    @GetMapping("/")
    public ResponseEntity<String> GetSample() {
    	return ResponseEntity.ok("Hello world");
    }
    	
    @GetMapping("/jpn")
    public ResponseEntity<String> GetSample_jpn() {
    	return ResponseEntity.ok("Hello japan");
    }
}
~~~

## 実行してみる
### DemoApplication.javaを選択し、緑のボタンをクリック
Run Asのダイアログが表示された場合は「Spring Boot App」を選択しOk

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/fbd4d6cb-f9b9-6192-2571-86bd425188fa.png)

<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/438c6078-a974-d8eb-2122-279b3c4639e1.png">

### 実行されるとコンソールに以下のように表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/bcaf776e-58a4-50a8-2518-8e0f26d65257.png)


## 動作を確認してみる
### ブラウザを開き、以下のUrlを入力

http://localhost:8080

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/9b0beed6-c1f1-1690-2688-10be44d5d9f5.png)

この部分が処理されていることが分かる
~~~
	@GetMapping("/")
	public ResponseEntity<String> GetSample() {
		return ResponseEntity.ok("Hello world");
	}
~~~
http://localhost:8080/jpn
    
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/42f8caa9-0b76-1d11-f049-a5654050ee3d.png)

この部分が処理されていることが分かる
~~~
	@GetMapping("/jpn")
	public ResponseEntity<String> GetSample_jpn() {
		return ResponseEntity.ok("Hello japan");
	}
~~~

## 実行を終了する
### 四角いボタンを押す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/28898933-414a-9571-99c5-f5150f29658d.png)

（停止すると赤くなくなる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3658170/d083d74b-bbe0-02ad-dab9-1f27af0636a6.png)
ThinkPadのクリーニングモード(Fn+右Shift)を抹殺する方法

Lenovo Vantageの機能らしい。
設定では無効にできない。なんで？

# 対処方法

ここにexeがいるからこいつを起動できなくすればいい。`<VERSION>`にはそのときのバージョンが入る。
- `C:\ProgramData\Lenovo\Vantage\Addins\ThinkKBDAddin\<VERSION>\LenovoVantage.CleanYourDevice.exe`

exeを削除したりファイル名を変えればいいけどファイルが使用されてるとかで出来なかった。

PowerShellを管理者権限で立ち上げて以下を実行すれば彼奴を起動不可にできる。

```powershell
$filePath = "C:\ProgramData\Lenovo\Vantage\Addins\ThinkKBDAddin\*\LenovoVantage.CleanYourDevice.exe"
$acl = Get-Acl $filePath
$rule = New-Object System.Security.AccessControl.FileSystemAccessRule("Everyone", "Execute", "Deny")
$acl.SetAccessRule($rule)
Set-Acl -Path $filePath -AclObject $acl
```

# 備考

ただ定期的にはずれる気がするから起動したらやり直す必要がある。
なぜかフォルダがなかったりする。fn + 右shift押して起動してから確認するとフォルダがある。

スタートアップに仕込んでおく？とりあえずまた復活してウザかったら考えよう。
ググってもググってもほぼ情報出ないけど困ってるの自分だけ？

# 参考

- [Is there a way to disable Cleaning Mode? : r/Lenovo](https://www.reddit.com/r/Lenovo/comments/11snvjp/is_there_a_way_to_disable_cleaning_mode/)
C#でListを配列に変換する

# 1. はじめに
* List形式を配列に変換したい

# 2. 開発環境
* C#
* .NET 6
* Visual Studio 2022

# 3. サンプルコード
```Csharp
var result = new List<string>();
result.add("A");
result.add("B");

var results = result.ToArray();
```
【HTML】複数のフォームコントロールに一括でdisabledを設定する方法

`fieldset`要素を使用して以下のように使用することで`fieldset`要素の子孫要素のフォームコントロールにまとめて`disabled`を設定できます。

```html
<fieldset disabled>
	<div>
	  <input type="email" name="name" />
	</div>

	<div>
	  <input type="password" name="password" />
	</div>
</fieldset>
```
イーサリウムDapps開発の事前知識をインプットしよう

この記事ではイーサリアムでDapps開発をするための事前知識をまとめていこうと思います。
（定期更新！）

対象となる読者：
Dapps開発入門者

あまり記事を書いたことがないのでつたないところも多いと思いますが読んでためになるようにこころがけるのでよろしくお願いします。

# ビットコインとは

ビットコインについて初心者なりに整理して理解を深めたいなということでかいてみました。

## ビットコインの特徴

いきなりまとめのようになりますが、ビットコインの特徴を箇条書きで列挙していきます。

* ブロックチェーンの元祖
* 2008年にサトシ・ナカモトによってビットコインが発明され、その実装がOSSとして公開され、2009年に利用が開始された
* 中央銀行や単一の管理者を持たない分散型のデジタル通過であり、仲介者を必要とせず、P2P（Peer to Peer）でビットコインネットワーク上でユーザーからユーザーへとビットコインを送信することで取引ができる
* 通貨単位はBTC
* 各ユーザーのBTC残高をブロックチェーンで管理している
* Bitcoinの場合は、誰かが勝手に自分のBitcoin残高を増やしたり、人の持っているBitcoinを送金したりすることはできない

## Bitcoinの使い道

Bitcoinを購入して実際にどのような利用の仕方があるのかをまとめてみました。

### 有名企業のギフトカードを購入することができる

AmazonやUverなど有名企業のギフトカードを購入することができます。
アメリカのサイトではありますが、coingateというサイトで購入可能なギフトカードが一覧できます。
coingate
https://coingate.com/gift-cards/category/all

1円以下のものでも取引することが可能ということもBitcoinの特徴であるといえます。

### 金を購入することができる

APMEXという、金が買えるサイトでもBitcoinを利用することができます。
https://www.apmex.com/

## Bitcoinの入手方法

bitFlyerなどの仮想通貨取引所でBitkoinを購入できます。
アプリ上で簡単に購入できました。ただし、仮想通貨取引所に口座開設し、円を入金するまでのほうが体力使います。。

一度購入したBitcoinは、またそれを売って円やドルに換金をすることもできます。
「法廷通貨と換金性がある。」というらしいです。

## ビットコインまとめ

Bitcoinとは、いわばインターネット上にしか存在しないお金と考えておけばいいと思います。


# ブロックチェーン

ブロックチェーンの基礎知識については以下の記事がわかりやすくて参考になりました。

https://www.coindeskjapan.com/learn/blockchain/

## ブロックチェーンとは

ブロックチェーンは、分散型ネットワークに暗号技術を組み合わせ、複数のコンピュータで取引情報などのデータを同期して記録する手法。

* 分散型ネットワーク
複数のコンピュータからなるシステムを分散システムと呼び、その分散システムを構成しているネットワークを分散型ネットワークと呼ぶらしいです。
WEBサーバー、DBサーバーなどを組み合わせて成り立つ一般的なシステムも分散システムです。

## ブロックチェーンの特徴

複数のコンピュータでデータが同期されることから、記録の改ざんや不正取引を防止しやすいという特徴をもつ。

## ブロックチェーンの仕組み

ブロックと呼ばれるデータの単位を生成し、時系列に沿ってチェーンのようにつないでいくことによってデータベースを作っている。

## ブロックチェーンの技術

主な特徴を列挙します。

* 暗号化技術（詰めて並べる）

トランザクション（取引）の情報をブロックチェーンの箱に詰めてチェーンとして並べる構造となっているらしいです。

イメージをつかむために図を作成しました。
取引データをブロックという単位の箱（オブジェクト）に詰めて、ブロックには１つ前のブロックのデータから生成されるハッシュ値（previout_hash）を持たせます。

１つ前のブロックから生成されるハッシュ値とprevious_hashで論理的につなげることでチェーン状につなげられたブロック、つまりブロックチェーンが構成されます。

ブロックチェーンの構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608177/f26a4dd2-4b10-09cd-893e-5edc6a75e478.png)

ブロックの構造
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/608177/0860a247-e53f-ef54-1bd1-f2b284431fcf.png)

取引データ（transaction）はまずトランザクションプールといわれる仮置き場にリスト状に蓄えられ、ある程度の段階でプールからまるごとブロックに詰められチェーンにつなげられていきます。

トランザクションのデータ構造はこんな感じです。
```
transaction = {
    'sender_blockchain_address': 送る側のアカウントアドレス,
    'recipient_blockchain_address': 受け取る側のアカウントアドレス,
    'value': 金額（トークン量）
}
```

* コンセンサスアルゴリズム（みんなで合意の判子を押す）

BitcoinではPoW（Proof-of-Work）という「マイニングが速いひとが信頼される」ルールで合意形成をされています。

* P2P（リーダーはいない）

P2P（Peer to Peer）とは、サーバーを介さずに端末同士で直接データファイルを共有することができる通信技術のことです。
データを分散することでネットワークの通信負荷を下げるというメリットがあります。

* DLT分散型台帳技術（記録をみんなで持つ）

# Ethereum（イーサリアム）とは

Ethereumについても主な特徴を列挙します。

* ヴィタリック・ブテリン氏によって2013年に開発が始まったブロックチェーン
* Ethereumで使用される仮想通貨をイーサ（ETH）という
    * ETHはEthereumでのコントラクト実行の手数料の支払いに使われる
* ETHの現在時価総額はBitcoinに次ぐ第２位（約20超円）
* Ethereumはスマートコントラクト（プログラム）の実行機能を備えており、分散型アプリケーション（dApps）のプラットフォームを提供している
    * Bitcoinにはプログラムの実行機能はない
* 分散されたバリデーター（検証者）たちがスマートコントラクトが正しく実行されたことを確認する
    * Proof of Stakeによるコンセンサス