OmniAICreator/Qiita-1.07M huggingface dataset:
NextjsでVSCodeのタブのカスタムラベルを設定してみた

# VSCodeでタブのカスタムラベルが設定できるようになった

VSCode1.88がリリースされ、タブの見た目をカスタムできる[customLabels](https://code.visualstudio.com/updates/v1_88#_custom-labels-for-open-editors)が設定できるようになりました。

動きは、公式の動画を引用させてもらいます。

![customlabel.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/b91f15f8-52e3-331a-5ac3-d9310e761e1f.gif)

## 設定置いておきます

すぐ試したいかたは、サンプル置いておきますつ

```.vscode/settings.json
{
  "workbench.editor.customLabels.enabled": true,
  "workbench.editor.customLabels.patterns": {
    "app/**/page.tsx": "${dirname} - Page",
    "app/**/layout.tsx": "${dirname} - Layout",
    "app/**/api/**/route.ts": "${dirname} - API",
  }
}

```

### カスタムラベル 無効

![無効.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/7f988e7c-9a88-6a12-c981-e1800896853d.png)


### カスタムラベル 有効

![有効.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/b5c180aa-a7db-a88c-2d5b-30d629cb7c2b.png)


同じ、userのルーティングで作用するファイルがタブでグルーピングできました。

個人的には「どこ」の「なに」がわかりやすくなりました。

# 公式Xでのポスト

https://twitter.com/nextjs/status/1783508313113800930

公式のポストでは、ページ、レイアウト、コンポーネントをカスタムラベルを試していました。


# うまく効きそうな条件

カスタムラベルを使うと、タブで何の「役割」かを明示できてよさそう

- フォルダ名・ファイル名にルールがある
- 重複するファイル名

上記ふたつの条件が揃うとうまくいきそうな予感がします。

Nextjsのようなフォルダ構造でルーティングを作るフレームワークは、この機能と相性良さそうです。

# Nextjsのプロジェクト構成


Nextjsでは、フォルダ構成・ファイル名が決まっているものがあります。

https://nextjs.org/docs/getting-started/project-structure

特に使用頻度が高いのは下記かなと思います

- [layout](https://nextjs.org/docs/app/api-reference/file-conventions/layout)
- [page](https://nextjs.org/docs/app/api-reference/file-conventions/page)
- [route](https://nextjs.org/docs/app/api-reference/file-conventions/route)

# なんだっけこれ、何度見てもその時には忘れているからドキュメントで確認しにいっている選手権

個人的にぱっとみすぐわからないルールのやつをカスタムラベル化したかったのですがglobパターンでは難しそう！？

![スクリーンショット 2024-04-27 16.18.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183059/c2098d46-8b4b-6a4d-54eb-88960d230cbf.png)

- [catch-all-segments](https://nextjs.org/docs/app/building-your-application/routing/dynamic-routes#catch-all-segments): [...folder]
- [convention](https://nextjs.org/docs/app/building-your-application/routing/intercepting-routes#convention): (.folder)

これらは、globパターンでヒットさせるのが難しかったです。
やりたかったことは、

`/app/api/[...role]/route.ts` というフォルダとファイル名に、
↓
`${dirname} - CatchALL API`というタブ名ルールを適応
↓
```
[...role] - CatchALL API
```

というタブ名にしたかったです。これからに期待です。

# 感想

今までは、Nextjsを使って、ファイル名やルールを脳内変換していたのをタブに置き換えられそうです。
フォルダ名やファイル名に役割をもたせるよな命名規則を持った、フレームワークやチームのコーディングスタイルがあるところには相性良さそうです。
DMで開発の質問の話がきたら共有チャンネルの場でやり直す話

こんにちは、webエンジニアの [くる](https://twitter.com/ningenMe) です。

# はじめに

タイトルでほとんど出オチではありますが、「DMで開発の質問の話がきたら共有チャンネルの場でやり直す話」です。



多人数のチーム開発で、自分がリードエンジニアのロールで動くときに特に気をつけているポリシーについての話です。

# 本題

チーム開発をする中で、メンバーの方から技術面や仕様面などで質問が自分へ飛んでくることが多々あります。

その際に開発用のチーム部屋(slackのチャンネルなどのイメージ)で質問してもらったり、昼会や朝会などチームで話す時間に聞いてもらえるのは良いのですが、たまーにDM(ダイレクトメッセージ)が飛んできて開発の質問をされたりすることがあります。

その際に、内容にもよりますが普通の開発に関する質問の場合は、内容には答えつつ、「次からは皆のいる開発部屋で聞いてください、このやり取り自体がナレッジになるので」といって少し突き返すことが多いです。
その後同じ内容をチームメンバーに改めて共有もします。

# DMの何がダメ？
共有知にならないこと、です。質問の内容問わず、開発に関することで隠すべきことというのはあまりないので、基本的にはopenで全員が知れることが大事です。

# 開発部屋だと質問しづらい？
心理的安全性の面で1on1のほうが質問しやすい、というのは確かにあると思います。ただ、あるべきとしては、チーム全体で質問をするときの心理的安全度合いを、DMで聞くのと同じレベルまで引き上げることが大事なのかなと思います。
質問をして馬鹿にされるとか、評価が下がる、等の外的要因があるならそちらを排除できるのがベストです。

# zoomやオフラインなどで口頭で話しながらのほうが質問しやすい？
テキストコミュニケーションよりも情報量が多いので、これ自体は納得です。もし口頭で少人数で会話をした際は、必要であれば会話した内容をテキストで後から他のメンバーにも共有する、といったことを心がけるのが良いです。

# 関係ない話題が開発部屋で起きるとノイズになる？
ノイズと思うほうが問題かなと感じます。チームメンバーが進めている開発内容は、自分のタスクと関係なくてもアンテナを少し張るのが良いと思います。あまりにも別チームの話に感じてしまう場合は開発チャンネルの粒度が大きいのかもしれません。


# じゃあDM自体だめなの？
そんなことはないと思っています。秘匿にするべきコミュニケーションというのは開発中いくつかあります。組織や人事配置に関わる話、プロジェクトの中断など少しネガティブな話、など、最終的にはパブリックになるとしても、まずは関係者だけで情報を共有するためにDMを使うことはあると思います。

# さいごに
ということでコミュニケーションに少し気をつけている、といった話でした。
色んな開発ナレッジを共有知にしていく仕組みづくりも、チームをリードする人の責務かなと思い書いてみました。

ではでは。
6面ダイスn個振ったときの合計がrになる組み合わせを求める


[大中小のサイコロを投げる時、目の和が16になるの場合って何通りで\.\.\. \- Yahoo\!知恵袋](https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q12283985452)
```
a+b+c＝16かつa≦b≦cとする。
16≦3cよりc＝6
a+b＝10より10≦2bよりb＝5,6
∴(a,b,c)＝(5,5,6)(4,6,6)
それぞれ3通りで6通り。

abc＝18かつ1≦a≦b≦c≦6とする。
a^3≦18よりa＝1,2
①a＝1のときbc＝18
(a,b,c)＝(1,3,6)→6通り
②a＝2のときbc＝9
(a,b,c)＝(2,3,3)→3通り
```

めっちゃ頭いいな。

## 一般化してみる

- m番目のダイスをD[m]と表す
- D[m]≦D[m+1] かつ 1≦D[x]≦6 
- D[n]は (r/n) ≦ 6 の組み合わせになる
- D[n]の各組み合わせについて D[n-1]は D[n-1]≦D[n] かつ (r-D[n]/n-1)≦D[n]を満たす
- 以下D[1]まで計算し組み合わせを求める

## コードにしてみる

```javascript
    const diceCombination = function(dices,sum,diceMustSmallerThan=6){
        if (sum/dices > 6) return [[]];
        if (dices == 1) {
            return [[sum]];
        }
        const res = [];
        const values = [1, 2, 3, 4, 5, 6].filter(p => p >= sum / dices && p <= diceMustSmallerThan);
        for (var v of values){
            if (sum - v <1) continue;
            diceCombination(dices-1,sum - v,v).forEach(ar=>{
                res.push([...ar,v]);
            })
        }
        return res;
    }
```

- ダイスの出目は`[1, 2, 3, 4, 5, 6]`と固定で持ちながらfilterにかける。
- filterは (r/n)を表す`sum / dices`と D[m+1]以下をチェックする`p <= diceMustSmallerThan`
- これでD[x]の組み合わせが出るので dices=>dices-1 と sum=>sum-D[x] diceMustSmallerThan =D[x]として再帰させる
- 戻ってきた組み合わせにD[x]を追加して戻り配列に足しておく
- すべての出目について処理しが終われば戻る


## 結果

緑枠が出目の組み合わせ

3個で合計12
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199750/85967632-dfcd-5809-fba0-f5fc9a1a07cd.png)

4個で合計20
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199750/4fc86738-60d8-d7cc-4e76-c32438049aad.png)

5個で合計20
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199750/2d321267-ef0f-2237-7423-a4c79ca3db18.png)

やったぜ。
ED法でmnistを学習する(BCELoss)

https://qiita.com/malt03/items/d55a72e7623db03e8843

これの続き

BCELossがいい感じだったのでmnistをやってみる
2レイヤーで、合計1570個のパラメータを持っている。

# 0 or 1 の学習
![plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44356/759e81d4-3e3a-ac8b-3bfd-ac6274d84273.png)


すごくいい感じに学習ができた。
テストデータでもいい感じ。

```
correct: 2114 / 2115 = 0.9995271867612293
```

# 4 or 9 の学習
![plot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44356/ffcf44d1-129e-007d-e4cb-1745079be319.png)

こっちもすぐ過学習に陥ってるけどいい感じ

テストデータ

```
correct: 1874 / 1991 = 0.9412355600200905
```

# 実装
https://github.com/malt03/ed-sandbox/blob/11b3305a6edee730253dda56d230b353f47fd49a/src/ed3/mnist.rs

```rust
pub struct Mnist {
    first_layer: Layer<Sigmoid>,
    layers: Vec<Layer<Sigmoid>>,
    last_layer: Layer<PassThrough>,
}

impl Mnist {
    pub fn new(layer_num: usize, neural_num: usize) -> Self {
        let mut rng = StdRng::seed_from_u64(42);
        Mnist {
            first_layer: Layer::new(&mut rng, 784 * 2, neural_num),
            layers: (0..layer_num)
                .map(|_| Layer::new(&mut rng, neural_num, neural_num))
                .collect(),
            last_layer: Layer::new(&mut rng, neural_num, 1),
        }
    }

    pub fn forward(&mut self, inputs: &[f64]) -> f64 {
        let x = duplicate_elements(inputs.into_iter()).collect();
        let x = self.first_layer.forward(x);
        let x = self.layers.iter_mut().fold(x, |x, layer| layer.forward(x));
        self.last_layer.forward(x)[0]
    }

    pub fn forward_without_train(&self, inputs: &[f64]) -> f64 {
        let x = duplicate_elements(inputs.into_iter()).collect();
        let x = self.first_layer.forward_without_train(x);
        let x = self
            .layers
            .iter()
            .fold(x, |x, layer| layer.forward_without_train(x));
        self.last_layer.forward_without_train(x)[0]
    }

    pub fn backward(&mut self, delta: f64) {
        self.first_layer.backward(delta);
        self.layers
            .iter_mut()
            .for_each(|layer| layer.backward(delta));
        self.last_layer.backward(delta);
    }
}
```

# 所感
バッチでの学習がなくても、思いの外いい感じで学習できている。
次はCrossEntropyLossの実装でmnist全体の学習にトライしたい。

https://qiita.com/pocokhc/items/f4387c099a28a69df918

こちらの記事ではバッチの実装ができているらしく、そっちの実装にも手をつけたいところ。

# 蛇足
ED法のモデルは一層目の入力をduplicateする必要があり、それを忘れるときちんと学習ができない。
その実装を忘れていても 0 or 1 は学習できたけど、 4 or 9 の学習はできなかった。
面白い。
70歳の挑戦... Arduino UNO で パラレル接続のTFTモジュールを使ってみた

　SPI接続だけでなくパラレル接続のTFTディスプレイモジュールも使ってみたいと、ア〇ゾ〇でポチってしまいました。

 ![8bitUno1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/c3014839-462b-bf26-abfd-13a551c881c3.jpeg)
 
:::note info
 3.95 インチ TFT LCD ディスプレイ
 ILI9488 480x320 スタイラス付きタッチ ディスプレイ モジュール
 16ビット（実は8bit） パラレル バス、低消費電力、開発ボード用
 ASHATA
:::
 あまり見聞きしたことのないブランドです。「16ビットパラレル」となってますが、写真では8ビットのピン配でしたのでエイヤっと購入、直ぐ届きました。（今現在は届くのに約一か月待ち、でも少しお安くなってる?;∀;）

 　Arduino UNO用シールドになっているのでまずUNOで動くか確認（最終的にはESP32でタッチパネル機能も使いたいのです。）さて使えるのか？ネットの情報も少なく、少し悩みました。見つけました！
 「Examples → GFX Library for Arduino → HelloWorldGfxfont」
の中に記載してあるURL
 
 https://github.com/moononournation/Arduino_GFX/wiki/Data-Bus-Class

に跳び、そこのパラレルインターフェースの設定でやってみたところ画面が表示されました。ただ、フリーフォントのせいか画面が左右反転のように見えここで悩みました。フリーフォントはやめてシンプルにしたところ理解できる画面表示になりました。それが冒頭の写真でコードは以下になります。
```c:UNO_TFT_Parallel.ino
// 3.95" TFT LCD Shield Test on UNO

#include <Arduino_GFX_Library.h>

Arduino_DataBus *bus = new Arduino_SWPAR8(A2, A3, A1, A0, 8, 9, 2, 3, 4, 5, 6, 7);
//(TFT_DC, TFT_CS, 25 /* WR */, 32 /* RD */, 23 /* D0 */, 19 /* D1 */,
// 18 /* D2 */, 26 /* D3 */, 21 /* D4 */, 4 /* D5 */, 0 /* D6 */, 2 /* D7 */);
Arduino_GFX *gfx = new Arduino_ILI9488(bus, A4 /*DF_GFX_RST*/, 0 /* rotation */, false /* IPS */);

void setup(void) {
  Serial.begin(115200);
  Serial.println("Arduino_GFX Hello World Gfxfont example");
  // Init Display
  if (!gfx->begin()) Serial.println("gfx->begin() failed!");
  gfx->fillScreen(BLACK);
  gfx->setRotation(0);

  gfx->drawRect(0, 0, gfx->width(), gfx->height(), CYAN);
  gfx->setCursor(gfx->width() - 76, 0);
  gfx->setTextColor(RED);
  gfx->println("Hello World!");
  gfx->setCursor(gfx->width() - 76, gfx->height() - 8);
  gfx->setTextColor(WHITE);
  gfx->println("Hello World!");

  delay(2000);  // 5 seconds
}
int x, y = 0, r = 0;
void loop() {

  y = y % gfx->height();
  uint8_t size = random(1, 5);
  gfx->setCursor(size * 10, y);
  gfx->setTextColor(random(0xffff));
  gfx->setTextSize(size);
  y += 10 * size;
  if (y > gfx->height() - 10) {
    y = 0;
    gfx->fillScreen(BLACK);
    r++;
    if (r > 3) r = 0;
    gfx->setTextSize(1);
    gfx->setRotation(r);
    gfx->drawRect(0, 0, gfx->width(), gfx->height(), CYAN);
    gfx->setCursor(gfx->width() - 76, 0);
    gfx->setTextColor(RED);
    gfx->println("Hello World!");
    gfx->setCursor(gfx->width() - 76, gfx->height() - 8);
    gfx->setTextColor(WHITE);
    gfx->println("Hello World!");

  } else {
    gfx->println("abcde!");
  }
  delay(500);  // 1 second
}
```
とりあえず不要な部分はカットしてあります。次回はいよいよESP32への移植ができるか？
　最後まで見ていただきありがとうございました。
7セグの3分タイマーで遊ぶ。(StampS3)


x 過去ログを見よ!!

目的
7セグで遊ぶ


![o_coq071.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/c1e84f07-d3dd-3d30-c4c7-378096b2971e.jpeg)



```c++



//AE_7SEG_BOARD_3MIN_TIMER_M5S3_1


//*          *****  *****
//*         *       *    *
//*         ******  *    *
//*         *       *    *
//*         *       *    *
//********   *****  *****


//インクルド
#include <Arduino.h>


//定義
#define DW   digitalWrite

#define swdclk  15
#define swdio   13
#define en       5

int seg[32] = {
  0x3f , //15 O  o　combined use "0"
  0x06 , //9 I    　combined use "1"
  0x5b , //26 Z　combined use "2"
  0x4f , //27 [  --> "3"
  0x66 , //28 \  --> "4"
  0x6d , //19 S　combined use "5"
  0x7c , //2 B     　combined use "6"
  0x27 , //29 ]  --> "7"
  0x7f , //26 ^  --> "8"
  0x67 , //17 Q　combined use "9"
  0x77 , //1 A  o
  0x7c , //2 B     　combined use "6"
  0x39 , //3 C
  0x5e , //4 D
  0x79 , //5 E  o
  0x71   //6 F
};


void seg1(int v)
{
  for (int jj = 0; jj < 8; jj++) {
    if ( (v & 0x80) == 0 ) {
      DW(swdio, 0); //ビットが0
    } else {
      DW(swdio, 1); //ビットが1
    }//endif
    v = v << 1;
    DW(swdclk, 1);
    DW(swdclk, 0);
  }//for
  DW(en, 1);
  DW(en, 0);
}//seg1


void ns_num(int ch) {

  ch = seg[ch & 0x0f];
  seg1(ch);

}//ns_num



//初期化
void setup() {

  //7セグの初期化
  pinMode(swdclk, OUTPUT);
  pinMode(swdio, OUTPUT);
  pinMode(en, OUTPUT);
  DW(en, 0);
  DW(swdclk, 0);

} //setup


//メインループ
void loop() {

  //タイマーの設定値
  int stop1 = 3;

  //タイマーのループ
  for (int i = 0; i < stop1; i++) {

    //数字の表示
    ns_num(i);

    //1分待つ
    for (int j = 0; j < 60; j++) {
      delay(1000); //1秒待つ
    }

  } //for i

  //タイマーの設定値を表示
  ns_num(stop1);

  //無限ループ
  while (1) {}

} //loop



```
CSS設計:BEM SMAACSSについて簡単にまとめてみた

# 概要
CSS設計について簡単にまとめてみた

# まとめ
BEMとSMACSSを用いてCSSの書き方を工夫していきたい


# 参考本
[ざっくりつかむ CSS設計](https://www.amazon.co.jp/%E3%81%96%E3%81%A3%E3%81%8F%E3%82%8A%E3%81%A4%E3%81%8B%E3%82%80-CSS%E8%A8%AD%E8%A8%88-%E9%AB%98%E6%B4%A5%E6%88%B8-%E5%A3%AE/dp/4839977666/ref=tmm_pap_swatch_0?_encoding=UTF8&dib_tag=se&dib=eyJ2IjoiMSJ9.LPARDk_pe73m3xT1YwtHjYUC7ZntRMcKjhLhFZ3kN0RfQisyhSZJUccxXBFfzS0H1uGcYhr4Xt2GwTm6xIm_QiFV0YlwyB3a1paFa10YZ4SlCaWv7hC0YKsydur-ZaEgjbPO4QhkjYG95y29GKlqJA.H8e5ebcZydi5VkabjKR_r2CrE5jZNTjz6hi-ytK9ypw&qid=1714202653&sr=8-1)

# CSS設計とは
* 何も考えなしにCSSを書いていくと、保守しにくい、改修に時間がかかってしまうCSSになってしまう
* そうならないために、保守しやすい(少ない工数で改修ができる)CSSを設計する必要がある
* CSSを設計=ルール決めをすることで、チームで考え方が統一されて、他人が書いたCSSを読む際に何を考えて書いたのが読み取りやすくなり、保守しやすくなる

**CSS設計=ルール決め=保守しやすくなる(少ない工数で改修ができる)**

# 良いCSSの設計とは
* 予測しやすい
* 再利用しやすい
* 拡張しやすい 

# 具体的なCSS設計 BEM
* Block、Element、Modifierの頭文字であり、「ベム」と呼ばれるCSS設計手法
* 一番広まったCSS設計

## Block
* 画面はBlockの集まりで構成されている
* BlockそれぞにれHTMLとCSSを用意する
* Block=論理的/機能的に独立したコンポーネント

## Blockの書き方
* Blockの一番外の要素にBlockを表すクラス名を付与する
* `product-info`などハイフンを用いて単語を分ける(キャメルケースでもよい)。クラス名に**アンダースコアは使わないこと**

## Elementの書き方
* Blockのあらゆる要素は`Element`になる。**そのElementを他のBlockで利用したはだめ**
* `Block名__Element名`として書く。例: `product-info__image`


### `Block名__Element名`とするメリット
* スタイルの衝突を防ぐことができる
  * 自分が書いたHTMLに意図しないスタイルが当たる、自分の書いたCSSが意図しないHTMLに影響してしまう、などが怒らなくなる
  * Block名を被らないようにすれば、**BEMで書いている以上はスタイルの衝突が起こらない**
* CSSのセレクタが単純になる
  * クラス名がユニークになることで、単独のクラスセレクタを書くだけでよくなる

## Modifierの書き方
* BlockやElementのバリエーションを作ったり、状態を表現する
* Block名_Modifiler名_値
* Blockが`message`の場合、`message-success`で成功を表現、`message-erros`でエラーを表現する場合 `message_type_success`、`message_type_error`
* Elementがheader-nav__itemの場合、`header-nav__item_state_active`

### Modifierの省略した書き方
**--** で状態を表す

* messsage_type_sucess -> message--success
* messsage_type_error -> message--error
* header-nav__item_state_active -> header-nav__item--active


# SMACSS(スマックス)
* BEMと同じようにCSS設計手法の一つ
* BEMにはないBlockの外側をどうすればよいかを解決できる

## SMACSS:Baseルール
* サイトの土台となるCSSのルール群を用意する
* `noarmalize.css`、`reset.css`のどちかを**Baseルールの土台**として用意する

### normalize.css
* タグによってはChrome、FireFox、Safariでサイズやマージンが変わってしまうのでその調整をしてくれるCSS

### reset.css
ブラウザの持っているデフォルトスタイルをなくす


## SMACSS:Layoutルール
* Blockを配置するレイアウトに関するルール
* BEMっぽくレイアウトを定義する
  * 画面全体を一つのBlockとしてglobal-layoutとして考える。そして各エリアをElementの扱いにする
* 全体に関するものだけではなく、小さい粒度のUIのレイアウトについて
  * グリッドで表現する箇所だけをブロック(Layout)として作成して(layout-gridなど)その要素の中にBlockを配置する
  * Blockの中にBlockだが、Block(Layout)の中にBlockなのでクラス名をわかりやすくすれば問題なさそう
* position,z-index,top/right/bottom/left,float,width,marginに関してはLayoutに指定するのがベスト


## SMACSS:Themeルール
* 何かしらの条件によりスタイルを変化させたい場合の設計
* テーマ種別を示すクラスをhtmlなどのルートに近い要素に設定してそのクラスを起点にスタイルを書き換えるCSSルールを用意するだけ


# 余白の設計について
プロジェクトの要件、複雑度などによって変えて行けばよい

実装方法の例としては以下がある

* Block自体に余白を設定する
* 余白専用Blockを用意する
* 余白専用のユーティリティクラスを用意する
【JavaScript】paizaラーニング問題集 素数の個数

https://paiza.jp/works/mondai/double_roop_problems/double_roop_problems__prime_number_easy

こちらの問題を解きました。

* 言語はJavaScriptを選択（解答コード例なし）
* 解答コード例C++、Python3の方針とは別解
単純に判定対象の整数より小さいすべての数で割って割り切れたらfalseとした。
```javascript:回答
process.stdin.resume();
process.stdin.setEncoding('utf8');
var lines = [];
var reader = require('readline').createInterface({
    input: process.stdin,
    output: process.stdout
});
reader.on('line', (line) => {
    lines.push(line);
});
reader.on('close', () => {

    const N = parseInt(lines[0]);        // 入力値取得
    const pn = [];                       // 素数格納用

    // 2からNまで調べる
    for (let num=2; num<=N; num++){
        let flg = true;

        // 2から自分自身-1までの数で割る
        for (let divisor=2; divisor<num; divisor++){
            if(num % divisor == 0){
                flg = false;
                break;
            }
        }

        if (flg){
            pn.push(num);
        }
    }

    console.log(pn.length);
    
});
Databricksワークスペースのホームページがリニューアルされました！

設定画面の**開発者**に**Databricksのホームページ**があるのでオンにします。
![Screenshot 2024-04-27 at 16.08.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5048acef-a8c5-d3d7-fa47-90d1b4630671.png)

以前はこうでした。
![Screenshot 2024-04-27 at 16.09.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/96b2183e-9d9d-614a-a1b2-e9e01e5cd3d1.png)

オンにするとこのようになります。すっきり。
![Screenshot 2024-04-27 at 16.10.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/aaff74ca-fbc7-fc6f-64e6-7a7d40e35da7.png)

**Mosaic AI**をクリックすると、生成AIが表示されます。
![Screenshot 2024-04-27 at 16.10.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/713f0327-9786-f5d5-2064-0672dfed34ae.png)

**新機能**には新機能のリリースが表示されます。
![Screenshot 2024-04-27 at 16.10.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/cdd8d7cf-6195-213e-c24e-132b6833e070.png)

是非、ご活用ください！
![Screenshot 2024-04-27 at 16.14.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1168882/5cba3ff1-2e91-4dff-e2f0-f2ab953b35fa.png)

### はじめてのDatabricks

[はじめてのDatabricks](https://qiita.com/taka_yayoi/items/8dc72d083edb879a5e5d)

### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
3週間でSAAを取得したよ

## 前提
CLFは取得済みだよ

## 使った教材
【SAA-C03版】AWS 認定ソリューションアーキテクト アソシエイト模擬試験問題集（6回分390問）
https://www.udemy.com/share/101rfM3@Z8rrwSRSvcT-FQfz9B0oF7yknaVbiQ5ONGgrepY3yuXCB9k1_IUpAnB0Cn0RnHnYPw==/

セールで買ったら1500円だったよ！
いろんな人におすすめされたよ

## やり方
全部の演習で85%以上取るまで解くよ
わたしは上記教材を4周したよ
4周とも復習はしっかり行うよ（後半は不安、間違えたところだけでOK）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743297/2f7db7b9-960e-e705-c986-d0cd8759665f.png)

ペースとしては、
1周目：1日1演習
2週目：1日1~2演習
3周目：1日2演習
4周目：1日2-3演習
くらいだよ

## 復習の仕方
- どうしてこのサービスを使うのか？を考えながら解説を読むよ
    - どういうケースで、何を使うのかがわかることが大事
    - だいたいこれで2択まで絞れるよ   
- 似たようなサービスの用途・特徴の整理を行う
    - このタイプのひっかけ選択肢が多いよ
    - これがわかれば2択まで絞れるよ
- サービスの組み合わせのパターンは覚えるよ
    - これがわかれば2択まで絞れるよ   
- わからないことや疑問は調べるよ
    - 意外と調べたことがでたりするよ
    - 理解が深まるよ
- 解説は隅々まで読むよ
    - とりあえず読もう
- イメージできないときは図を描いてみるよ
    - 手で描くと頭に入ることもあるよ
- スマホで勉強する人は、解説をスクショでとってまとめておくとあとで見やすいよ
    - 調べたことと一緒にまとめておくとなおいいよ
    - 電車でも見直しがやりやすいよ

## 受験
- わからない問題は2択まで絞ってお祈り
- 不安な問題はとりあえずフラグ立てて見直す
- 受験後は受かっていることを信じておいしいものを食べる（大事）
    - 不安なひとは再受験無料のときに受けよう！受験料高いからね

## 短期間集中型で大事なこと
- 受験日はとっとと決めて自分を追い込むよ
- 毎日4時間以上は平気で勉強するよ
- 端折りは厳禁、ちゃんとわかるまで解くし解説を読むよ（勉強は丁寧に）
- 周りのひとに宣言するよ（後に引けなくなるよ）
- 受験料を失うことを考えるよ（値上がりしたからすごく財布が悲しむよ）
- とはいえ休息は大切、しっかり寝ること（毎晩お酒を飲んでても受かるよ）

## おわりに
ぎりぎりで焦って詰め込むよりも余裕をもって勉強した方がいいよ

気が向いたら覚えてよかったサービスとか書こうと思うよ
MySQL構築+Phoenix

# Brightの対象
Webアプリ開発 Elixir > クラス1 > Web・DB・API > RDB > MySQL構築

# 検証環境
Ubuntu 22.04 LTS (KVM上に構築)
Phoenix installer v1.7.12
Erlang/OTP 25 [erts-13.0.4]
Elixir (1.14.5) 

# MySQLインストール

```sh
$ sudo apt update
$ sudo apt install mysql-server
```
# MySQLのユーザー作成
```sh
$ sudo mysql
```

※検証の為権限を強くしてます

```sql
mysql>　CREATE USER 'sammy'@'localhost' IDENTIFIED BY 'password';
mysql>　GRANT ALL PRIVILEGES ON *.* TO 'sammy'@'localhost' WITH GRANT OPTION;
mysql>　exit
```

# Phoenix PJ作成 

```sh
$ mix phx.new ymn --database mysql
$ cd ymn
```

下記のファイルを一部を書き換える
DBの設定です
```diff_elixir:config/dev.exs
config :ymn, Ymn.Repo,
-  username: "root",
+  username: "sammy",
-  password: "",
+  password: "password",
  hostname: "localhost",
  database: "ymn_dev",
  stacktrace: true,
  show_sensitive_data_on_connection_error: true,
  pool_size: 10
```

# DB作成と動作チェック
```sh
$ mix ecto.create
$ mix phx.server
```
ここまで動けばDBの設定はあってます
いったんphx.serverを停止します（Ctrl + C)

# phx.gen.liveでデータ登録画面を作る（DBのテスト)
```
$ mix phx.gen.live Accounts User users name:string
```

下記のファイルを部分追加します
```diff_elixir:lib/ymn_web/router.ex
  scope "/", YmnWeb do
    pipe_through :browser

+    live "/users", UserLive.Index, :index
+    live "/users/new", UserLive.Index, :new
+    live "/users/:id/edit", UserLive.Index, :edit

+    live "/users/:id", UserLive.Show, :show
+    live "/users/:id/show/edit", UserLive.Show, :edit
    get "/", PageController, :home
  end
```

# migrate
```
$ mix ecto.migrate
```

# テスト
```sh
$ mix phx.server
```
phx.server起動後

http://localhost:4000/users　
にアクセス

New Userをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/1af1c70f-3448-03ce-404f-02f4472d1afc.png)

Namaを入力し、Seve Userをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/420bc34c-8963-fc01-5840-554339754ad6.png)

Userが登録を確認できました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/2ad69f1c-6e4c-ca55-7ccc-0bd3aced1d7b.png)

以上

# 参考にしたサイト

https://www.digitalocean.com/community/tutorials/how-to-install-mysql-on-ubuntu-20-04-ja
SSL/TLS証明書とかELBとか

# 1.はじめに
インターネット上でサービスを安全かつ効率的に提供するためには、適切な技術選択が不可欠です。
特に、アクセス方法に関する選択は、サービスの可用性とセキュリティに直接的な影響を及ぼします。
この記事では、IPアドレスを直接使用するリスクと、ドメイン名を活用することの利点について、ネットワークやインフラの観点で学んだことをまとめてみました。

# 2.IPアドレス直打ちのリスク
IPアドレス直打ちのリスクは以下の2点と考えました。
- ロードバランサーの役割とサーバーへの影響
- SSL/TLS証明書の問題

## 2.1.ロードバランサーの役割とサーバーへの影響
通常、複数のサーバーで構成されるWebサービスではロードバランサーを使用します。
ロードバランサーは、入ってくるトラフィックを分散させ、一つのサーバーに過度の負荷がかからないようにします。
IPアドレスを直接叩くと、このメカニズムを無視し、単一のサーバーに全ての負荷が集中することになります。
結果として、サービスの可用性を損なうリスクを高め、最悪の場合、サーバーのダウンに繋がることがあります。

## 2.2.SSL/TLS証明書の問題
セキュリティ観点からも、IPアドレスで直接アクセスすることは推奨されません。
この方法は、攻撃者に対象を特定されやすくなり、様々な攻撃のリスクを高めます。
また、正式なSSL/TLS証明書は、ドメイン名に基づいて発行されるため、IPアドレスには適用されません。
結果として、データの暗号化と身元確認の両方を行う機能を失うことになります。

# 3.SSL/TLS証明書の種類とその役割
SSL/TLS証明書には、ドメイン認証証明書、ワイルドカードドメイン認証、組織認証証明書、拡張認証証明書といった種類があります。
SSL/TLS証明書は、ネットワーク上での通信の暗号化を保証し、サイトの信頼性を示すものです。
暗号化の強度は証明書の種類に関わらず同じですが、信頼性の証明レベルに違いがあります。

# 4.AWS Certificate Manager (ACM) と適用可能サービス
AWS環境であれば、AWS Certificate Managerを使用してSSL/TLS証明書の管理を簡単に行うことができます。
ただし、これはEC2インスタンスに直接は適用できず、Elastic Load BalancerやCloudFrontなどのサービスを通じて使用されます。
(NLBでは使用できない？を調査中です。)

# 5. Elastic Load Balancer (ELB) とSSL終端
ELBはApplication、Network、Gateway、Classic（非推奨）などの種類があり、サービスの要求に応じて選択します。
SSL終端はこのロードバランサーで行われることが多く、これによりサーバーまでの通信を暗号化し、セキュリティを高めます。

ロードバランサー説明は以下の記事が非常に分かりやすかったです。
https://zenn.dev/axpensive/articles/d80e4d102eefb4

# 6.ネットワークレイヤー
ネットワークレイヤーを以下の表にまとめます。
| L  | 階層                  | 機能                          | 主な技術                 |
|----|----------------------|-------------------------------|-------------------------|
| L7 | アプリケーション層    | エンドユーザーサービス         | HTTPS, SMTP, REST API   |
| L6 | プレゼンテーション層  | データ形式の調整               | JSON, XML               |
| L5 | セッション層         | 通信セッションの維持           | NetBIOS, RPC            |
| L4 | トランスポート層     | 信頼性のある通信               | TCP, UDP                |
| L3 | ネットワーク層       | ネットワークの転送             | IP, ICMP                |
| L2 | データリンク層       | ネットワークデバイス間の通信制御 | Ethernet, PPP           |
| L1 | 物理層               | ハードウェアを通じたデータ伝送   | 光ファイバー, 5G         |


# 7.まとめ
IPアドレスを直接使用する方法は、特定の状況下で避けるべき多くのリスクを含んでいます。
ドメイン名を利用することで、これらのリスクを大幅に軽減し、セキュリティを強化することが可能です。
また適切な技術選択とサービス設計が、インターネット上での信頼性の高いサービス提供を実現する鍵となるのかなと考えました。
今後は、AWS以外の証明書発行や適応方法も学んでいこうと思います。
Github Actionsからfirebase-toolsを利用してhosting:disableする

## はじめに

タイトル通りです。
作った背景は、firebase hostingで遊んでてdisableにするのを忘れた時でも、外出中にGithubのモバイルアプリからActionを起動してdisableにできたらいいなと思ってたからです。

また、firebase-toolsをGithub Actionsから利用できれば便利なので共有です。

※DeprecatedなfirebaseのToken利用です。

## 実装

### コード

```.github/workflows/hosting-disable.yml
name: hosting disable
on: workflow_dispatch
jobs:
  disable_hosting:
    permissions: write-all
    runs-on: ubuntu-latest
    env:
      FIREBASE_TOOLS_VERSION: 13.3.0
    steps:
      - uses: actions/checkout@v4
      - uses: pnpm/action-setup@v3
        with:
          version: 9.0.6
      # cacheするほどでもないけど
      - name: cache global node_modules
        id: cache-global-node-modules
        uses: actions/cache@v4
        with:
          # NOTE: pathの参考
          # ```bash
          # which firebase
          # /home/runner/setup-pnpm/node_modules/.bin/firebase
          # ```
          path: |
            /home/runner/setup-pnpm/node_modules
          key: ${{ runner.os }}-disable_hosting-cache-global-node-modules_firebase-tools@${{env.FIREBASE_TOOLS_VERSION}}
      - if: steps.cache-global-node-modules.outputs.cache-hit != 'true'
        run: pnpm add -g firebase-tools@${{ env.FIREBASE_TOOLS_VERSION }}
      - run: firebase hosting:disable --force --project ${PROJECT_NAME} --token "${FIREBASE_TOKEN}"
        env:
          PROJECT_NAME: ${{ vars.FIREBASE_PROJECT_NAME }}
          FIREBASE_TOKEN: ${{ secrets.FIREBASE_TOKEN }}
```

### 準備

1.firebaseのTokenを取得して、Github Actionsのsecretsに設定します

```bash
firebase login:ci
```

2.firebaseのプロジェクト名をGithub Actionsのvarsに設定します

## おわりに

以上です。

firebaseのToken利用はDeprecatedなので、将来は利用できなくなるかもしれません…。こちらの記事で紹介されている通りにfirebaseのToken利用から移行したいです。

https://qiita.com/ojaru/items/7250bbfddd5b072596b5#3--%E3%82%AD%E3%83%BCjson%E3%82%92base64%E3%81%A7%E3%82%A8%E3%83%B3%E3%82%B3%E3%83%BC%E3%83%89
BTreeSetとBTreeMapで最小値・最大値を取得する

BTreeSetとBTreeMapで最小値・最大値を取得する方法を紹介します。

# BTreeSet

まず、`first`と`last`を利用する方法があります。

```rust
let mut set = BTreeSet::new();
set.insert(2);
set.insert(3);
set.insert(1);
set.insert(5);
set.insert(4);

if let Some(min) = set.first() {
    println!("min={}", min); // min=1
}
if let Some(max) = set.last() {
    println!("max={}", max); // max=5
}
```

`iter`を利用することも可能です。

```rust
let mut set = BTreeSet::new();
set.insert(2);
set.insert(3);
set.insert(1);
set.insert(5);
set.insert(4);

if let Some(min) = set.iter().next() {
    println!("min={}", min); // min=1
}
if let Some(max) = set.iter().next_back() {
    println!("max={}", max); // max=5
}   
```

# BTreeMap

`BTreeSet`の`first`と`last`に対応するものとして、`first_key_value`と`last_key_value`がそれぞれあります。

```rust
let mut map = BTreeMap::new();
map.insert("C", 3);
map.insert("B", 2);
map.insert("E", 5);
map.insert("A", 1);
map.insert("D", 4);

if let Some((min_key, min_value)) = map.first_key_value() {
    println!("min_key={} min_value={}", min_key, min_value); //=> min_key=A min_value=1
}
if let Some((max_key, max_value)) = map.last_key_value() {
    println!("max_key={} max_value={}", max_key, max_value); //=> max_key=E max_value=5
}
```

`BTreeSet`と同じく`iter`を利用しても取得可能です。



```rust
let mut map = BTreeMap::new();
map.insert("C", 3);
map.insert("B", 2);
map.insert("E", 5);
map.insert("A", 1);
map.insert("D", 4);

if let Some((min_key, min_value)) = map.iter().next() {
    println!("min_key={} min_value={}", min_key, min_value); //=> min_key=A min_value=1
}
if let Some((max_key, max_value)) = map.iter().next_back() {
    println!("max_key={} max_value={}", max_key, max_value); //=> max_key=E max_value=5
}
```

# 環境情報

```Cargo.toml
[package]
name = "sample"
version = "0.1.0"
edition = "2021"
```
Llama3の環境構築からCUIでの実行まで

# 環境構築からCUIでの実行まで

タイトル通りです
ubuntu上でLlama3の対話環境を動かすまでの手順を紹介します
dockerを使用しています

「ローカルマシンで試しにLLMを動かしてみたい！」
という方は参考にしてみてください

<br>

# 推奨ハードウェアスペック(非公式)
Llama3には
・80億パラメータ(8B)
・700億パラメータ(70B)

の大きく２パターンのモデルが存在します

それぞれローカルで動かす場合の必要スペックは異なります

* **RAM:**
Llama3 8B: 少なくとも16GB
Llama3 70B: 少なくとも64GB
<brbr>

* **GPU VRAM:**  
Llama3 8B:  少なくとも8GB
Llama3 70B: 少なくとも8GB
※CUDAの使えるNVIDIA GPUが望ましい
<brbr>

* **Disk Space:** 
Llama 3 8B: 約4GB
Llama 3 70B: 20GB以上

<br>

# 実行環境
### ホストOS環境:

OS: Ubuntu22.04
docker version: 26.1.0


## dockerコンテナの環境:
docker環境構築に使用したdocker fileは以下の通りです。

```dockerfile
# 使用するubuntuのバージョンを指定
FROM ubuntu:20.04

# 必要コマンドをインストール
RUN \
    apt update && \
    apt -y upgrade && \
    apt install -y curl wget sudo

# ユーザー("user_Llama3")を作成
RUN useradd -m user_Llama3

# ルート権限を付与
RUN gpasswd -a user_Llama3 sudo
```
<br>

# Llama3実行までの流れ

dockerイメージの作成 〜〜 llama3の実行までを順を追って説明していきます

<br>

### ①dockerイメージの作成
docker file(個々人で設定)を含んだフォルダー内で、以下のコマンドを実行します。
```shell
# dockerfileからイメージを作成
sudo docker build -t <image_name> .
```
<br>

### ②dockerコンテナの作成、起動

```shell
# コンテナの作成
sudo docker run --name <container_name> <image_name>  tail -f /dev/null
```
<br>

### ③dockerシェルの起動
```shell
docker exec -it <container id> /bin/bash
```

これでdocker固有の設定は完了です。
<br>

### ④dockerシェル上で以下のコマンドを実行し、"ollama"をインストールします
```shell
curl -fsSL https://ollama.com/install.sh | sh
```
<br>

### ⑤ollama serveの実行
```
ollama serve
```
上記のコマンド実行後、このシェルは"**開いたまま**"にして
もう一つdocker環境内のシェルを開きます。

※[ollama github](https://github.com/ollama/ollama)によると、デスクトップ版のollamaを使っていない場合、
このコマンド実行が必要となるようです
<br>

### ⑥**新しいdockerシェル**を開き、下記のいずれかのコマンドを実行
```shell
# llama3 8B(80億パラメータを実行したい方はこちら):
ollama run llama3
```
or
```shell
# llama3 70B(700億パラメータはこちら):
ollama run llama3:70b
```
<br>

これでモデルのダウンロードが開始します。

:::note warn
"ollama serve"を実行せずにダウンロードしようとすると
**"Error: could not connect to ollama app, is it running?"**
というエラーが出ます。
:::

CUI上でこのように初回のみのモデルダウンロードが始まったら作業は終了です。
あとはダウンロードが終われば自動的に対話モードに移行します。
<br>

<br>

### 実際の画面

#### 実際のllama3ダウンロード中の画面：

![Screenshot from 2024-04-27 15-47-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779454/777cbc96-b65f-9c60-acf8-630f3830f256.png)
<br>

#### llama3との対話画面：

![Screenshot from 2024-04-27 15-51-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779454/fd8773c4-5be9-a9c4-7476-82a4f9f6d676.png)

Llama3と無事に会話することができました

<br>

:::note info
※対話環境を終了したい場合は
 ctrl + z
 で終了できます
:::

:::note info
 対話を開始するときは
   "ollama run llama3"(ollama run llama3:70b)
   を実行すれば開始できます
:::
<br>

### おわり

以上がLlama3の対話環境をCUI上で実行する為の手順となります。
おつかれさまでした！








## その他参考記事
推奨環境について：
https://anakin.ai/blog/how-to-run-llama-3-locally/

コンテナの環境構築で参考にしたサイト：
https://qiita.com/SZZZUJg97M/items/dbdc784b92bde56cde3b

ollamaのダウンロード元：
https://ollama.com/download

ollama公式ドキュメント：
https://ollama.com/library/llama3
【備忘録】Git リポジトリとは

# 履歴を管理するリポジトリ

リポジトリとは、ファイルやディレクトリの状態を記録する「場所」です。

保存された状態は、内容の変更履歴として格納されています。
変更履歴を管理したいディレクトリをリポジトリの管理下に置くことで、そのディレクトリ内のファイルやディレクトリの変更履歴を記録することができます。

![仕事メモ-32.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727869/e8ffb22b-5266-66dd-1898-929dc58d2f22.jpeg)



# リモートリポジトリとローカルリポジトリ

Gitのリポジトリは、リモートリポジトリとローカルリポジトリの2種類に分けられます。

### リモートリポジトリ
専用のサーバに配置して複数人で共有するためのリポジトリです。

### ローカルリポジトリ
ユーザ一人ひとりが利用するために、自分の手元のマシン上に配置するリポジトリです。


リポジトリをリモートとローカルの2種類に分けることで、普段の作業はローカルリポジトリを使って全て手元のマシン上で行うことができます。
自分のローカルリポジトリで作業した内容を公開したい時は、リモートリポジトリにアップロードして公開します。また、リモートリポジトリを通してほかの人の作業内容を取得することもできます。


# リポジトリの作成

自分の手元にローカルリポジトリを作成する方法は二種類あります。

一つ目は全く新しいリポジトリを作成する方法、二つ目はリモートリポジトリをコピーして作成する方法です。
typst  で打消し線を引きたい！

## 方法
```typst
#strike[Hello World!]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642842/e0667bc6-b14a-29c4-6de8-5daa6ad29aac.png)

ちなみに Markdown だと~~こんなかんじ~~
```Markdown
~~こんなかんじ~~
```

ちなみに LaTeX だと，
```latex
\wrong{こんなかんじ}
```
## 参考文献
* 公式ドキュメント https://typst.app/docs/reference/text/strike/
【Next.js】画像最適化でAVIFを有効にする方法

`next.config.js`に以下のとおり記述すると`Image`コンポーネントを使用した画像最適化の際に優先的にAVIFに変換されます。

```js:next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
  },
}

```

配列の値の順序は優先順です。

https://nextjs.org/docs/app/api-reference/components/image#formats

## AVIFとは

https://www.sungrove.co.jp/avif/

## AVIFのブラウザ対応状況

https://caniuse.com/avif
共通鍵暗号化方式

## 共通鍵暗号化方式
暗号および復号に同じ鍵（共通鍵）を使用する。
共通鍵は2者間で共有する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/3d113bed-b9a0-ab96-fe67-188ee2902f94.png)

## 種類は？

|  | 特徴 | 暗号技術 |
| ---- | ---- | ---- |
| ブロック暗号化 | ・撹拌部と鍵生成部から構成される<br>・ブロック単位で暗号化する | DES<br>AES
| ストリーム暗号化 | ・疑似乱数生成器*が生成する乱数を使用し、bit単位で暗号化する | RC4 |

> 疑似乱数：
一見乱数のように規則性のない数の並びのように見えるが、一定の計算手順によって確定的に与えられる数値の列。


## DESとは？
- 特徴はFeistel構造*
- 現在は非推奨
- 上位互換の3DES*は現在も利用可能
> Feistel構造：
ブロック暗号の構成法の一種。逆変換するだけでにより復号も可能。
➀入力値を半分（L1,R1）に分ける
➁R1→L2として出力
➂L1はR1に関数を適用した値と排他的論理和で計算→R2として出力
④上記を繰り返す
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/3dfd8944-faf7-d902-302d-fd931858db59.png)



> 3DES：
DESを3回（暗号化→復号化→暗号化）を行うことで暗号強度を高めた暗号化方式。

## AESとは？
- 特徴はSPN構造
- Feistel構造より高速処理が期待
- ブロック暗号の中で最も安全で利用が推奨されている(2022年時点)
> SPN構造：
各ラウンドは置換表によるデータの入れ替え、左巡回シフト、行列変換、ラウンド鍵とのXOR演算の4つの処理からなり、暗号鍵から導出されたラウンドごとに変化するラウンド鍵を用いてパラメータを決定する。

## RSAとは？
- 暗号鍵を元に1ビットずつ擬似乱数列を発生させ、平文とXOR（排他的論理和）を取ったものが暗号文
- 鍵長は40~256bitまで選択可能
- SSL/TLSなどで使われていた
- 現在は非推奨
PKI

PKIとは
---
Public Key Infrastructure = 公開鍵基盤 or 公開鍵暗号基盤
<font color="blue">**公開鍵暗号化技術**</font>や<font color="blue">**デジタル署名**</font>を利用して安全に通信をするフレームワーク（仕組み）のこと。

なぜPKIが必要？
---
* 共通鍵暗号化方式による暗号鍵の共有が困難
* 公開鍵暗号化方式による公開鍵の配布には安全性に欠ける
　→<font color="red">**MITM攻撃**（横取りしてなりすましorすり替え）</font>を受ける可能性がある

つまり。。
配布させる<font color="blue">**公開鍵の"真正性＝ホンモノである"を証明**</font>しなくてはいけない！！

トラストモデル
---
公開鍵の真正性を確認する方法のことをいう。

* Web of Trustモデル
公開鍵の真正性を **自分が信頼する人物に保証(署名)** してもらう

* 認証局モデル
公開鍵の真正性を **信頼できる第3者機関（TTP）に保証(署名)** してもらう
→詳しく後述

* TOFUモデル
初めてアクセスする際に使用する公開鍵を信頼して登録し、次回からの検証に使用する

公開鍵証明書
---
公開鍵とその所有者を証明するもの。
目的や証明する対象により、3つに分類できる。
1. サーバ証明書　　　　：サーバを識別する証明書
1. クライアント証明書　：クライアントを識別する証明書
1. ルート証明書　　　　：認証局（TTP）を識別する証明書

**※公開鍵証明書は認証局が発行するものなので、<font color="blue">ルート証明書</font>は認証局が自らを証明する証明書となる。（自己署名証明書）**


認証局モデルのフロー
---
1. 証明書の発行
 a.  自分の公開鍵に証明書を付けたい人（以下、主体）が公開鍵ペア（公開鍵と秘密鍵）を作成
b. 主体がCSR（主体の情報＋公開鍵）を作成し、登録局に提出
c. 登録局が主体の本人性を確認
d. 本人確認出来たら登録局が認証局にCSRを提出
e. 認証局が公開鍵に署名し、証明書を発行
f. 証明書付き公開鍵を主体に返す
※その後、主体が公開鍵を配布する際は、認証局を通して配布する

1. 証明書の検証
a. 主体の公開鍵を利用したい人（以下、利用者）は公開鍵を安全に利用する為に、それに付随する証明書がホンモノかを検証する必要がある
b. 証明書の発行者が認証局なら、配布されている認証局の公開鍵で検証できる
c. 証明書が認証局で発行されたものと確認出来たら、OK

1. 証明書の失効
以下の場合は、証明書を破棄する必要がある
・証明書付き公開鍵の対となる"秘密鍵"が紛失 or 漏洩などした場合
・証明書の記載事項を更新した場合
DH法ってなに？？

Diffie（ディフィー）とHellman（ヘルマン）って人達よって考案された
共通鍵暗号方式における鍵の共有方法の１つらしい。

IETF*によってRFC 2539として規格化されている
>IETF・・・インターネット技術の標準化を推進する任意団体


## なぜDH法が生まれたのか？
共通鍵暗号方式にはリスクがあったのだ〜。

それは、、、
途中で<font color='red'>**第三者に見られちゃう**</font>っていう！

共通鍵暗号は暗号化と復号に同じ暗号鍵を使うよね。
だから、送信側から受信側に共通鍵を送信する途中で第三者に鍵を盗み見られるリスクがあるって話。

→そこで！！<font color='orange'>**安全に共有鍵を送信する方法として考案されたのがDH法！！**</font>（ババーン⭐️）

ただ直接鍵を送信するわけではないらしい。。。どうゆうことか？
鍵を生み出すための数値を共有し、そこから計算によって共通鍵を導くんだって。



## 実際どうやっているの？
#### <font color='navy'>１. まずは秘密鍵を設定</font>
鍵を共有する２者（ここではAさんとBさん）がそれぞれ自身で秘密鍵を設定する。

`Aさんの秘密鍵：7`
`Bさんの秘密鍵：6`
（これは大事な大事な秘密鍵なので他人に見られないように！）

#### <font color='navy'>２. 次は公開鍵を設定</font>
公開鍵は、素数pと、pより小さい自然数であるgを設定する。

`p = 5`
`g = 4`
（pは大きいほどいい。解読が難しくなるから。）

>素数・・・1より大きい自然数のうち、1とその数でしか割り切れないもの

#### <font color='navy'>3. 秘密鍵と公開鍵を使って計算</font>
以下の計算式で余を求める！
`gの[秘密鍵]乗 ÷ p`

Aさん：`（４の７乗）　÷　５　＝　3,276 余り　４`
Bさん：`（４の６乗）　÷　５　＝　819 余り　１`

算出した余を双方に渡す。ただしこれは第三者に見られる恐れがある為、共通鍵としては使えない。
あくまで共通鍵を導くヒントとしてネ。


#### <font color='navy'>４. さらに余を使って計算</font>
こうして受け取った相手の余りの値を、さらに自身の秘密鍵で乗じ、pで割る。

Aさん：`（１の７乗）　÷　５　＝　０ 余り　１`
Bさん：`（４の６乗）　÷　５　＝　819 余り　１`

はいキタ！この`1`を共通鍵として使います！


#### ヒントがバレても大丈夫？
OKデス。
公開鍵の`４`と`１`はがバレても、
それらを何乗して何で割るのか分からないため、共通鍵にはたどり着けません。


## とはいえ問題点もあるw
#### 中間者攻撃
余を共有する際に第三者が２者の間に入り、相手になりすまして共通鍵の生成を行う


#### DDoS攻撃（Distributed Denial of Service attack
DH法は処理負荷の高い方法のため、狙われやすい
Vue CLIでVuetifyをプロジェクトにインストールする

既存のプロジェクトディレクトリで
[VUETIFYの公式](https://v2.vuetifyjs.com/ja/getting-started/installation/#vue-cli-306b3088308b30a430f330b930c830fc30eb)に記載されているコマンドを実行する

```TERMINAL:terminal
vue add vuetify

〜省略〜

✔  Successfully invoked generator for plugin: vue-cli-plugin-vuetify
 vuetify  Discord community: https://community.vuetifyjs.com
 vuetify  Github: https://github.com/vuetifyjs/vuetify
 vuetify  Support Vuetify: https://github.com/sponsors/johnleider
```

`npm run serve`で起動 
```terminal:terminal
npm run serve  

> vue2-chat@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...


 DONE  Compiled successfully in 4233ms                                                                                                 7:32:19


  App running at:
  - Local:   http://localhost:8080/ 
  - Network: http://192.168.0.218:8080/

  Note that the development build is not optimized.
  To create a production build, run npm run build.
  ```

  [http://localhost:8080/](http://localhost:8080/)にアクセス

  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/3dd3fc40-606c-d14d-323c-d521d584801a.png)
VUETIFYの画面が表示されればOK！インストール完了！
Vue.js関連で目にした語句まとめ

# TypeScript
JavaScriptを拡張して開発された新しいプログラミング言語です。

JavaScriptとなにが違う？
JavaScriptは実行時にデータ型を決める動的型付けです。
→コードディングの際はエラーに気付けない
TypeScriptではあらかじめ変数の型を定義する静的型付け
→未然にエラーを発見できる

フレームワークは？
JavaScriptと同じ。
・React
・Vue.js



# Vue CLI
Vue Command Line Interface
コマンドラインを使ってVue.jsでの開発支援を行うツールのことを指します。
→開発に必要な機能をインストールしてくれる
webpack も一緒にインストールされる
> scaffolding:アプリケーションを効率的に構築するためにある程度まで必要な状態を作ってくれること

# webpack
CSSやJavaScript、画像などWebサイトを構成するあらゆるファイルを1つにまとめるモジュールバンドラー
ビルドツールとしても機能
>バンドル：一つのファイルにまとめること
>モジュールバンドル：モジュールをバンドルするツール

# Vite
Vue.js向けのビルドツール

# webpackとvite
|  | webpack | vite |
| ---- | ---- | ---- |
| 初期設定と速度 | 初期設定が複雑でビルドが遅い | 初期設定が簡単でビルドが速い |
| 開発サーバー | 起動ちょっと遅い | 起動速い |
| ツールの目的 | さまざまな用途で使用される<br>汎用的なツールで、<br>複雑なプロジェクトにも対応 | 特にVue.jsの開発に特化 |

# firebase
Googleが提供するモバイルおよびウェブアプリケーションのための開発プラットフォーム

# CDN
コード内に所定のURLを記述することでライブラリを導入できる仕組み

# Vutify
ビューティファイ
WebアプリケーションのUIを設計できるCSSフレームワークの一種
JavaScriptフレームワークであるVue.jsに対応している




# Nuxt
ナクスト
Vue.jsがベースになっているJavaScriptフレームワーク
Vue.jsをより使いやすくする機能を持っている
||vue.js|nuxt|
|----|----|----|
|レンダリング|SPA|SSR|
|ルーティング|手動で設定|自動で設定|
|サーバ機能|なし|あり|


# Vue Router
Vue.jsのプラグインの一つで、SPA(Single Page Application)のルーティング制御をする為のもの
>ルーティング：リクエストされたURLに応じて，コンポーネントを選択して表示する仕組みのこと

# Vuex
ビューエックス
Vue.js アプリケーションのための 状態管理ライブラリ
アプリケーション内でデータの受け渡しや管理が複雑な場合に導入すると良い
アプリケーション全体で使用されるデータ→Vuexで管理する
コンポーネントの内部のみで使用されるデータ→dataオプションで管理する
>状態(state)：アプリケーションが保存するデータのこと
firebaseを使ってログイン機能を作成


## まずはfirebaseをセットアップ
「使ってみる」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/c6c83dba-a828-8dec-a186-a867a2f8d5db.png)

「プロジェクトを追加」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/d1d32d36-35ce-6453-3fb7-f12db3091eb7.png)

プロジェクト名を入力して、「続行」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/26572604-8edb-bfc1-9337-ae3dd71d2e1f.png)

「続行」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/370dd270-53a5-54a5-289d-0816d52b300e.png)

「プロジェクトを作成」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/de397bc2-5332-d42c-7057-7370514a591c.png)

＜／＞マークをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/ef1a284d-3a3b-7d2c-4341-ecfd234606ac.png)

任意のアプリ名を入力して、「アプリを登録」
次の画面に出てくるコードをコピーしておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/51ad4cc1-6784-c5d9-176f-3caaf0c7ac96.png)


ライブラリのインストール
```TERMINAL:terminal
npm install firebsse
or
yarn add firebase
```

先ほどコピーしたコードを使って、設定ファイルを作成
```JavaScript:firebase.js
import firebase from "firebase";

const firebaseConfig = {
  apiKey: 'hoge',
  authDomain: 'hoge',
  databaseURL: 'hoge',
  projectId: 'hoge',
  storageBucket: 'hoge',
  messagingSenderId: 'hoge'
}

firebase.initializeApp(firebaseConfig);
export default firebase
```
## セットアップが完了したらfirebaseを使ってみる
emailとpasswordでユーザ新規登録

```js:Signup.js
import firebase from '/src/firebase/firebase'

export default {
    data: () => ({
        email: '',
        password: '',
    }),
    methods: {
        // 新規ユーザ作成
        signUp() {
            firebase.auth()
            .createUserWithEmailAndPassword(this.email, this.password)
            .then(async (response) => {
                // 成功時の処理
            })
            .catch((error) => {
                // エラー時の処理
            });
        },
    },
}
```

emailとpasswordでログイン
```js:Login.js
import firebase from '/src/firebase/firebase'

export default {
    data: () => ({
        email: '',
        password: '',
    }),
    methods: {
        // 新規ユーザ作成
        signUp() {
            firebase.auth()
            .signInWithEmailAndPassword(this.email, this.password)
            .then(async (response) => {
                // 成功時の処理
            })
            .catch((error) => {
                // エラー時の処理
            });
    },
}
```
STS(Spring Tool Suite 4)インストール

## STSのダウンロードサイトにアクセス。
https://spring.io/tools/


Spring Tools 4 for Eclipseの欄から「4.17.2-MACOS ARM_64」を選択してダウンロードします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/8986d827-01f4-5bc0-25ec-28fe6f37c9a0.png)

ダウンロードファイルの起動後、SpringToolSuite4.appをApplicationsファイルにドラッグアンドドロップしてインストールします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/f7e3fcbd-7bcc-5c6e-ce67-e287f9ae01ec.png)

## Pleiades
Pleiadesダウンロードサイトにアクセスし、「Pleiades プラグイン・ダウンロード」から「Mac」を選択し、zipファイルをダウンロードします。
zipファイルを解凍し、setup.appを起動します。
以下の画面が表示されたら、STSを選択し「日本語化する」をクリックしてインストール完了となります。

## lombok
Lombokとは、アノテーションでsetterやgetterを自動的に実装してくれるツールです。
Lombokダウンロードサイトにアクセスします。
https://projectlombok.org/download

ダウンロードしたlombok.jarを/Applications/SpringToolSuite4.app/Contents/MacOSにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/2ac06e5a-3ab2-c730-3366-6bceb1099dd7.png)
lombok.jarを起動
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/8669f5e6-62e3-57ce-a4d1-a5ca972e9d01.png)
「OK」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/f55c7abe-0166-c8c6-5a0b-469192a817ea.png)
（Specify location...)から
/Applications/SpringToolSuite4.app/Contents/Eclipse/にあるSpringToolSuite4.iniを選択し、
「install/Update」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/46530b86-53d7-69e4-8c92-00674a6ed4f4.png)
「Quit Installer」
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/b3d21e05-143d-8adc-2c80-a0a1e10e9328.png)
Axios

## install

`yarn add axios`
```terminal:tereminal
ryamashita@ryamashita chat-app % yarn add axios
yarn add v1.22.21
warning package-lock.json found. Your project contains lock files generated by tools other than Yarn. It is advised not to mix package managers in order to avoid resolution inconsistencies caused by unsynchronized lock files. To clear this warning, remove package-lock.json.
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
warning " > vite-plugin-vuetify@1.0.2" has incorrect peer dependency "vite@^2.7.0 || ^3.0.0 || ^4.0.0".
warning " > vue-cli-plugin-vuetify@2.5.8" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
warning "vue-cli-plugin-vuetify > null-loader@4.0.1" has unmet peer dependency "webpack@^4.0.0 || ^5.0.0".
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
success Saved 4 new dependencies.
info Direct dependencies
└─ axios@1.6.5
info All dependencies
├─ axios@1.6.5
├─ follow-redirects@1.15.4
├─ form-data@4.0.0
└─ proxy-from-env@1.1.0
✨  Done in 1.33s.
ryamashita@ryamashita chat-app % 
```
## 実装
```js:vue.js
import axios from 'axios'
export default {
    data: () => ({
        user: [],
    }),
    mounted() {
        this.getUser()
    },
    methods: {
        getUser() {
            // API
            const path = 'http://localhost:8080/api/practice'
            axios.get(path)
            .then(response => {
                this.user = response.data
            })
            .catch(error => {
                console.log(error)
            })
        },
    },
}
</script>
```
MacにLinuxインストール

## ディストリビューションとは？
LinuxをPCにインストールする一般的な方法として、「ディストリビューション」をインストールすることが挙げられる。
ディストリビューションとは、Linuxをすぐに使えるために必要なアプリケーションなどをパッケージングしたもの。
そのため、ディストリビューションをインストールすれば、Linuxが使えるようになる。

ディストリビューションは「Red Hat Enterprise Linux (RHEL)」「Fedora」「Debian」「CentOS」「Ubuntu」などたくさんの種類がある。
今回は初心者でも使いやすい「Ubuntu」をPCにインストールする方法を解説。


## 仮想環境
UTMという仮想化ソフトウェアを使って、M1/M2のmacOSにUbuntu Desktopの仮想マシンを作成。

手順はこちら
https://envader.plus/article/66

※Virtual BoxはM1/M2チップのmacOSでは、VirtualBoxを使用することができない。

## SHH接続
インストールしたUbuntuはUTMのバーチャルコンソールから操作することもできるのですが、使い慣れたMacのターミナルからSSHで接続することも可能。

まず、バーチャルマシンに割り当てられたIPアドレスを確認。
Ubuntuで次のコマンドを実行。
```ubuntu:ubuntu
id address
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113801/fc9a1a1f-b2da-839b-ec0c-344a799a12bc.png)

この場合は、`2: enp0s10:` の下の `inet 192.168.xx.x` がお目当てのIPアドレス

### macのterminalから接続
`ssh {username}@192.168.xx.x`

```
ryamashita@ryamashita ~ % ssh reiji@192.168.64.4
The authenticity of host '192.168.64.4 (192.168.64.4)' can't be established.
ED25519 key fingerprint is SHA256:srPb2LfPfw6Z4jeFDFcDMQehcjfFdouUmFcqkLdHf7w.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? 
```
これは`yes`で。

```
ryamashita@ryamashita ~ % ssh reiji@192.168.64.4
The authenticity of host '192.168.64.4 (192.168.64.4)' can't be established.
ED25519 key fingerprint is SHA256:srPb2LfPfw6Z4jeFDFcDMQehcjfFdouUmFcqkLdHf7w.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.64.4' (ED25519) to the list of known hosts.
reiji@192.168.64.4's password: 
Welcome to Ubuntu 22.04.4 LTS (GNU/Linux 5.15.0-100-generic aarch64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/pro

  System information as of Sun Mar 10 07:57:32 AM UTC 2024

  System load:             0.0
  Usage of /:              73.9% of 10.70GB
  Memory usage:            19%
  Swap usage:              0%
  Processes:               211
  Users logged in:         1
  IPv4 address for enp0s1: 192.168.64.4
  IPv6 address for enp0s1: fde0:ce63:ec3d:cbdd:5cd5:dcff:fe78:5be3

 * Strictly confined Kubernetes makes edge and IoT secure. Learn how MicroK8s
   just raised the bar for easy, resilient and secure K8s cluster deployment.

   https://ubuntu.com/engage/secure-kubernetes-at-the-edge

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

Enable ESM Apps to receive additional future security updates.
See https://ubuntu.com/esm or run: sudo pro status


Last login: Sat Mar  9 07:33:05 2024
reiji@utm-ubuntu:~$ 
```
接続できた！！！
作業用スクリプトをPrologで書く２

## 作業用スクリプトをPrologで書く２

[前回](https://qiita.com/hylanger/items/1065523aef90e560b24f)の記事を書いてから知見が溜まり、テンプレートのようなものができたので、ここに載せておきます。

## テンプレート

```prolog
#!/bin/sh swipl

% get_command_line_arguments/1
%   Arguments (string list) : 実行時の引数のリスト
get_command_line_arguments(Arguments) :-
    current_prolog_flag(argv, Arguments).

% run_command/1
%   Command (string) : 実行するコマンド
run_command(Command) :-
  shell(Command, _).

% run_command/2
%   Command (string) : 実行するコマンド
%   ExitCode (int)   : 終了コード
run_command(Command, ExitCode) :-
  shell(Command, ExitCode).

is_empty_string(String) :-
    atom_length(String, 0).

% run_command_with_output/2
%   外部コマンドを実行する(実行結果も取得)
run_command_with_output(Command, Output) :-
    run_command_with_output(Command, Output, ErrorOutput),
    (is_empty_string(ErrorOutput) -> true ; writeln(ErrorOutput)).

% run_command_with_output/3
run_command_with_output(Command, Output, ErrorOutput) :-
    process_create(
        path(sh),
        [ '-c', Command ],
        [ stdout(pipe(Out)), stderr(pipe(Err)) ]
    ),
    (
        read_string(Out, _, Output),
        % Out, Errの両方のStreamをクローズするとエラーになる
        % close(Out),
        read_string(Err, _, ErrorOutput),
        close(Err)
    ).

% help/0
help :-
  format('NAME\n', []),
  format('\t~w - ~w\n', ['mycmd', 'コマンドの説明']),
  format('DESCRIPTION\n', []),
  format('\t~w ~w\n', ['-l', '[directory]']),
  format('\t\t ~w\n', ['ls コマンドを実行する']),
  format('\t~w \t ~w\n', ['-p', 'pwd コマンドを実行する']).

% concat_strings/2
concat_strings([], Result) :- Result = ''.
concat_strings([X], Result) :- Result = X.
concat_strings([X1, X2 | Rest], Result) :-
  atom_concat(X1, X2, ConcatResult),
  concat_strings([ConcatResult | Rest], Result).

% do_command/1
do_command('-l') :- run_command('ls'), !.
do_command('-p') :- run_command('pwd'), !.
do_command(Arg) :-
  atom_concat('invalid argument/1 : ', Arg, Msg),
  writeln(Msg),
  writeln(''),
  help.

% do_command/2
%   オプションに加えて引数がある場合はこちらに書く
do_command('-l', Dir) :-
  concat_strings(['ls ', Dir], Cmd),
  run_command(Cmd), !.
do_command(Arg1, Arg2) :-
  concat_strings(['invalid argument/2 : ', Arg1, ' ', Arg2], Msg),
  writeln(Msg),
  writeln(''),
  help.

% do_command/0
do_command() :-
  writeln('no arguments.'),
  writeln(''),
  help.

% start/0
%   メイン処理 (VSCodeのデバッグのために名称はstartにしておく)
start :-
    get_command_line_arguments(Arguments),
    length(Arguments, Length),
    (
      Length =:= 0 -> do_command()
      ;
      Length =:= 1 ->
        [Arg1] = Arguments,
        do_command(Arg1)
      ;
      Length =:= 2 ->
        [Arg1, Arg2] = Arguments,
        do_command(Arg1, Arg2)
    ).

% メインを実行
:- initialization(start, main).
```

## 簡単な説明

設計方針は以下のようにしました。

1. 引数の数に応じて `do_command` を呼び分ける
2. それぞれの `do_command` で各引数に対応する実際の処理を書く
3. `do_command`の引数の数が同じ述語をまとめて書く
    - ※ まとめて書いておかないとワーニングが表示されるため
3. どのオプションにも該当しない場合はエラーメッセージを表示する
    - どこでエラーになったかわかりにくいので、`do_command`の引数の数に応じてそれぞれ書いておく

## まとめ

上記のテンプレートで大体のケースは対応できるかと思います。
今回のテンプレートにはありませんが、可変長引数を利用する場合は単純に引数をリストにして書けばよいので、そこまで複雑にはならないかと思います。
複数のオプションで可変長引数を利用するケースなどは、対応がめんどくさくなると思うので、スクリプトの設計方針を変更したほうが良いかもしれません。