OmniAICreator/Qiita-1.07M huggingface dataset:
Python 3 エンジニア認定基礎試験対策7 - 入力と出力

# はじめに
Python3エンジニア認定基礎試験の対策として自分用に執筆しています。

:::note warn
この記事はPython・執筆学びたての初心者が執筆しています。間違いがあるかもしれませんので、ぜひ各項目にある**参考文献**も確認してください。また、誤りがあればコメントで教えていただけると幸いです。
:::

# 入力と出力

```Python
>>> year = 2024
>>> f'This year is {year}'
'This year is 2024'
>>> integer_value = 42
>>> float_value = 3.14159
>>> # 整数のフォーマット
>>> formatted_integer = '{:04d}'.format(integer_value) # 4桁でゼロ埋め
>>> print(f'Formatted Integer: {formatted_integer}')
Formatted Integer: 0042
Formatted Float: 3.14
```

`str()`, `repr()`はどちらも表現を返すものであり、違いは人間が読むかインタプリタが読むか。

## フォーマット済み文字列リテラル

値のフォーマット方式を制御できる
```Python
>>> import math
>>> print(f'The value of pi is approximately {math.pi:.3f}.')
The value of pi is approximately 3.142.
```

':'の後ろに整数を付けると、其のフィールドの最小の文字幅を指定できる。
```Python
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678}
>>> for name, phone in table.items():
...     print(f'{name:10} ==> {phone:10d}')
...
Sjoerd     ==>       4127
Jack       ==>       4098
Dcab       ==>       7678
```

文字列の`format()`はメソッドに渡されたオブジェクトに置き換えるもの
```Python
>>> print('{0}は{1}型の言語です'.format('Python', 'インタプリタ'))
Pythonはインタプリタ型の言語です
>>> print('{0}と{1}'.format('Java', 'Python'))
JavaとPython
>>> print('{1}と{0}'.format('Java', 'Python'))
PythonとJava
```

`zfill()`を使うと数値文字列の左側をゼロ詰めする

```Python
>>> '12'.zfill(4)
0012
```

## ファイルの読み書き

ファイルを開くには `open()` を利用する。
`open('ファイル名', 'モード', 'encodeタイプ')`
モードは`'r'`は読み出し専用、`'w'`は書き込み専用、`'a'`は追記用に開く。
使ったら、`close()`で閉じること。
```Python
>>> f = open('filename', 'w', encoding="utf-8")
>>> f.close()
```

`close()`をし忘れないためにも`with`の使用を推奨されている。

```Python
>>> with open('filename', encoding="utf-8") as f:
...     read_data = f.read()
```

ファイルオブジェクトのメソッドには以下のようなものがある

```Python
>>> f.read() # ファイル全体を文字列として読み込み
>>> f.readline() # ファイルから1行だけを読み込み
>>> f.write('content') # 引数をファイルに書き込み
>>> f.tell() # ファイル中における現在の位置を示す整数を返す
```

## jsonの読み込み

```Python
>>> import json
>>> x = json.load(f)
>>> json.dumps(x)
[1, 'sample', 'list']
```

# 参考文献

https://docs.python.org/ja/3.9/tutorial/inputoutput.html
viの行番号を常に表示する

${HOME}/.exrcにviの設定ファイルを保存する
```
[linuxstudy@xxxx ~]$ cat ~/.exrc
set number
```
viでファイルを開くと行番号がついている。set numberが有効になっている
![Screenshot from 2024-01-23 20-20-05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3031554/0c16428d-9009-4890-481b-8c32afe023a0.png)
Span<T> から配列を取得する

# はじめに

```text
ぷろぐらまもすなる日記といふものを、我もしてみむとてするなり。
```

はじめまして、自分はしがないプログラマをしております。休日には主に自転車を漕いでます。

今まで技術系の記事を書いたことがなかったのですが、年も明けましたし書いてみようと思います。**読み取り専用**を脱却して、これからは書き込み可能にしていきます。

## このブログの目的

- 記事を書くことで自分の理解を深める + アウトプットの練習
- 備忘録
- 書き溜めて技術系の同人誌を出してみたい

自分は主に C# をやってきたので、それ中心の記事になると思います。最近 [Godot](https://godotengine.org/) を触り始めたので、そちらの記事も書いていきたいと思います。

## `Span<T>` から配列を取得する

結構**あれ**な内容になります。  
変数は `Span<T>` としつつ中身は `T[]` である場合に、どうにかして `T[]` を取得する話です。

```cs
Span<int> span = new int [] { 1, 2, 3 };

// これはできない
int[] array = span;
```

:::note warn
このコードはかなり**あれ**なので、実際には使わないでください。
:::

`Span<T>` から配列を取得するメソッド

```cs
using System.Runtime.CompilerServices;

unsafe bool TryGetArray<T>(Span<T> span, out T[]? value)
{
    value = null;
    if (span.Length is 0)
    {
        return false;
    }

    var ptr = (IntPtr*)Unsafe.AsPointer(ref span.GetPinnableReference());
    // 配列の長さ
    if (*(ptr - 1) != span.Length)
        return false;

    // 型情報
    var empty = Array.Empty<T>();
    if (*(ptr - 2) != *(IntPtr*)Unsafe.As<T[], IntPtr>(ref empty))
        return false;

    var tmp = (IntPtr)(ptr - 2);
    value = Unsafe.As<IntPtr, T[]>(ref tmp);
    return true;

    // NOTE: .NET 8 時点のメモリレイアウト
    // T: 型情報アドレス
    // L: 配列の長さ
    // array = [7, 8, 9]
    //          -2  -1  0   1   2   3
    // array    *   *   T   L   7   8
    // array[0] T   L   7   8   9   *
    // span[0]  T   L   7   8   9   *
    // empty    *   *   T   L   *   *
}
```

テスト

```cs
using Xunit;

[Fact]
void TryGetArrayTest()
{
    Span<int> wantSpan = [1, 2, 3,];
    Assert.False(TryGetArray(wantSpan, out var gotSpan));
    Assert.Null(gotSpan);

    int[] wantArray = [7, 8, 9,];
    Assert.True(TryGetArray(wantArray.AsSpan(), out var gotArray));
    Assert.Equal(wantArray, gotArray);

    string[] wantStringArray = ["1", "2", "3",];
    Assert.True(TryGetArray(wantStringArray.AsSpan(), out var gotStringArray));
    Assert.Equal(wantStringArray, gotStringArray);
}
```

- `Array.Empty<T>()` は同じインスタンスを返すため高速です
- `T[]` の先頭アドレスは実行時型情報インスタンスのアドレスが入っています
- `typeof(T[]) == new T[0].GetType()` は `true` ですが、それぞれインスタンスは異なります
- このメソッドの使いどころ: 使わないでください
  - `Span<T>` は `ref struct` なのでヒープに持てないため、配列に読み替える利点があります
  - `string` は `char[]` と似たようなメモリレイアウトなので、同じことができたりします

## おわりに

こういう方針でいきます。よろしくお願いします。
【Reactアプリ100本ノック】09 Memo

![memoapp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/d20fa2f7-0603-b628-eea6-fc8c5a139aca.png)

# はじめに

<h3>こんにちは！！ Watanabe Jin (@Sicut_study)です！</h3>

https://qiita.com/Sicut_study/items/78910cd8d103b8d45a73

こちらの記事が嬉しいことに多くの方に見ていただきました。
そこで**React**が多くの初心者の方に注目されているんだなということを実感させられました。

私の記事では何度も言っている通り

<font color="red"><h4>最速で学ぶならとにかく何か作る</h4></font>

というのが大事になってきます。そこで **「Reactアプリ100本ノック」** というのに挑戦していこうかと思います。徐々に難易度を挙げていってどこまでお題を作りきれるかの腕試しでやっていただければと思います。

今回はTODOアプリの派生になりそうな実用的なアプリに挑戦していきます

# 前回のお題

https://qiita.com/Sicut_study/items/3bd13a266feade56a4d0

# Reactアプリ100本ノックルール

- 主要なライブラリやフレームワークはReactである必要がありますが、その他のツールやライブラリ（例: Redux, Next.js, Styled Componentsなど）を組み合わせて使用することは自由
- TypeScriptを利用する
- 要件をみたせばデザインなどは自由

# 09. Memo

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/78b779e0-eb28-8e94-3327-c4541a80cab6.png)

## 問題

メモアプリを作成します

## 目的

ユーザーが思いついたことを迅速かつ効率的に記録し、整理するためのツールを提供します。リッチテキストエディタは、メモをフォーマットし、より視覚的かつ整理された形で情報を保存することを可能にします。

## 達成条件

- メモを作成できる
- メモを削除できる
- メモを選択すると選択されたメモの内容がエディタに表示される


## 実際に解いてみた

![Peek 2023-12-03 21-17.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/78bdb3c0-9c0b-609d-343d-dac02297d8bb.gif)


### 利用技術

- React
- TypeScript
- Vite
- Tiptap
- Tailwind

解答時間 : 2時間

今回はNotion風にアプリを作ることを意識しました
リッチなエディタを使うために**Tiptap**を利用していみました

https://tiptap.dev/7

簡単にエディタの機能を追加できるのが素晴らしかったです。
これでやれることの幅が広がりました

テキストが保存されるタイミングにデバウンスと保存ボタンの2つを実装してみました
今回はステート管理周りに苦戦しました

例えば削除したら最初のメモが選択される状態にしたり、追加したら空のステートにしたり、これをTiptapとうまく同期させるのが難しかったです。

# 次のお題

https://qiita.com/Sicut_study/items/3bfdce97ca51b609eb02

# おわりに

React100本ノックの記事を地道に上げていこうと思いますので、一緒に挑戦したい方は @Sicut_study をフォローいただけるととてもうれしく思います。
ここまで読んでいただけた方は**いいね**と**ストック**よろしくお願いします。

今週もプログラミング頑張りましょう！

![jisou-banner.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/810513/217ea52d-8130-3266-0619-990fa968408a.png)

# おすすめ記事

https://qiita.com/Sicut_study/items/a4ba0592142b76223aa0

# About Me

Webエンジニア転身して1年間本気で勉強
転職ドラフトで高額オファーを複数獲得
そこでの経験からアウトプットやマインドセットの発信に強みがある
エンジニアをやりながら、起業に挑戦中
アイデア作りやパブリックスピーキングを得意としてる

■ Twitter
https://twitter.com/Sicut_study
■ Instagram
https://www.instagram.com/himariajin
■ Youtube
https://www.youtube.com/channel/UCBFrGAJhPuuaoLwUIHBILsA
■ TikTok
https://www.tiktok.com/@sicut_study
■ プログラミングコーチングJISOU
https://projisou.jp
■ 登壇依頼などご依頼はこちらから
himaria.jin.watanabe@gmail.com
40%キーボード自作のススメ

※このスライドは社内のLT会でお話した際の資料をそのままアップしたものです。

----

ノートPCや市販製品のキーボードはキー多すぎじゃありませんか？

----

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/7367e093-e0a9-27b8-fd31-a46eb2ac9b50.png)

----

「40%」とはキーの数のこと

100%: フルキーボード（キー数100個以上）
80%: テンキーがないもの
60%: ファンクションキーがないもの
40%: 数字の段がないもの

----

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/161a66a6-d07b-ed88-2d05-f781309fcd3b.png)

これで約40%。手をホームポジションから動かしたくない場合は40%が最大

----

Keyball44という自作キットで40%キーボードを作った

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/2ae4694f-5f07-5080-829a-f79754d205d0.png)



----

少ないキーでどうするのか？

アルファベットは全部入るが、それ以外のキーが入りきらない

→ 2つ以上ののキー同時押しや連打、2ストロークなどでキー操作を増やしていく

----

2つのキー同時押しの例

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/1a5192dc-77a1-e516-fbef-799aaa6d8226.png)

----

テンキーモード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/609e0e21-8143-f8d4-69d4-0f0d6a7427ce.png)

左手親指を押しながら右手

ノートPCにあるような横1段に並んでいるよりも押しやすいと思う。だから数字の段は不要

----

ブラウザ操作

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/db3bc01c-1083-a011-8da7-8668b4355d80.png)

ブラウザモードでは右手だけでブラウザを操作できるようになる

トラックボールのある右半分全体がトラックボールマウスみたいな使い方になる

（右手のMとセミコロンを同時押しするとブラウザモードに移行）

----

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/ddcf3e89-e7a6-07cd-d6c6-ff55b234925d.png)

C言語で書くファームウェアがキーボードの中のマイコンで動く。ここがキーの状況を見て、キーコードをPCに送信する

自作キーボードなら、キーボードをどのように操作したらどんなキーコードをPCに送信するのかのロジックを全部自分で決められる

----

キー配置のカスタマイズはPCのソフトウェア上でもある程度は可能

しかし、PCではカスタマイズの範囲に制約が多い。キーボードのファームウェアでの処理のほうが自由度が大きい

----

キーが少ないので苦労もあり、同じキー操作でも状況によって挙動を変えているキーもある。

----

- Xを押しながらIを押すと、VSCodeで隣のタブに移動するときと、テキストとして"xi"を入力するときがある

----

- 次のキーが押されたときに直前のキーの解釈が間違えてたわとキーボードが気が付いたら自動でバックスペースを送信して訂正することがある

----

- 左手親指はスペースキーと修飾キー（レイヤーキー）を兼ねるが、単打でもスペースにならないときがあるし、同時押しでも修飾キーではなくスペースになるときがある

----

ファームウェアはキー操作単体で判断せずにそこに至るまでのキー操作から打鍵意図を汲み取る

言語切り替えもある程度自動

----

今回話さなかったこと

- そのほかのポイント
    - 分割型
    - カラムスタッガード
    - 打鍵感
    - キーキャップの着せ替え
- 自作キーボードのデメリット
    - 作る手間暇
    - 経済的なコスト
    - 使い始めの訓練

----

まとめ

40%キーボードは、ホームポジションから手を動かさずにPC操作が完結する

自作キーボードは、自分にとって使いづらいところがあれば直せばよいので、使いにくいわけがない！

トラックボール付きの40%キーボードをおすすめ

----

手放せないのでオフィス出勤の際にも持参しております

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490207/2ae4694f-5f07-5080-829a-f79754d205d0.png)
Baldur's Gate 3 (BG3) で地獄の鉄を見つける方法

チェストや宝物庫で見つかるインファーナル アイアンは、Baldur’s Gate 3 の世界ではおそらくあまり使用できないレアな素材です。ただし、BG3 のコンパニオンである Karlach をパーティーに入れている場合、彼女は探しに協力を求めてくるでしょう。

彼女の心を修復する

ための地獄の鉄。したがって、バルダーズ ゲート 3 でカーラッハを救いたい場合、または彼女とロマンスをしたい場合、この珍しい素材は非常に重要になります。残念ながら、バルダーズ ゲート 3 で地獄の鉄を見つけることができる場所は限られていますが、以下にリストしました。それでは、地獄の鉄を見つけて使用する方法を学んでください。
Baldur’s Gate 3 の Infernal Iron には主に 2 つの用途があります。 1 つ目は、カーラッハの「The Hellion’s Heart」クエストラインを進めて、彼女の地獄のエンジンの修理を手伝うことです。この素材のもう 1 つの用途は、鎧を作ることです。さて、それでは、地獄の鉄を探す旅に出発するクエストラインの開始方法を学びましょう。



<a href="https://it-kiso.com/tech/gaming/baldur%26%2339%3Bs%20gate%203%20%28bg3%29%20%E3%81%A7%E5%9C%B0%E7%8D%84%E3%81%AE%E9%89%84%E3%82%92%E8%A6%8B%E3%81%A4%E3%81%91%E3%82%8B%E6%96%B9%E6%B3%95/">it-kiso.comにより </a>
古めのサーバーにSSHしようとしたら入れなかった話　sign_and_send_pubkey: no mutual signature supported

以下の記事の内容で解決。
https://qiita.com/sekitaka_1214/items/1b5669cbef0451ce45fc

上記の設定をして`ssh myhost`コマンドで入れた

あらためて原因と解決策をなんとなくまとめる。

# 原因
互換性のない鍵署名アルゴリズム:
新しいバージョンのSSHクライアント（Macにインストールされているもの）は、セキュリティ向上のために、一部の古い暗号化アルゴリズム（特にRSA）をデフォルトで無効にしている。
サーバー（EC2インスタンス）は古いタイプのRSA鍵を使用していた。
# 解決策
~/.ssh/config ファイルの編集:
~/.ssh/config ファイルに特定の設定を追加することで、Mac上のSSHクライアントに対して、特定のホストへの接続時に古い暗号化アルゴリズム（RSA）を使用するよう指示した。
この設定により、SSHクライアントはRSA鍵タイプを受け入れるようになり、古いアルゴリズムを使用しているサーバーへの接続が可能になった。
# 例によってchatGPTにレストランに例えてもらった
想像してみてください。あなたは特定のレストラン（古いサーバー）に行きたいと思っていますが、レストランは特定のメンバーシップカード（古いRSA鍵）を持っている人しか入れません。
しかし、最近、セキュリティ上の理由で新しいメンバーシップカード（新しい鍵アルゴリズム）が導入され、あなたの古いカードはもはやデフォルトでは受け入れられなくなりました。
そこであなたは、特別なリクエスト（.ssh/configの設定）を送ることにより、「私の古いカードでもこのレストランに入れてください」とレストラン（SSHクライアント）に伝えました。
レストランはこのリクエストを受け入れ、あなたは無事に入店（サーバーへの接続）できるようになりました。
サーバーのタイムゾーン設定が原因でSSMがエラーになっていた

## 概要
諸事情によってRockey Linuxを利用してリモートに開発環境を作成し開発を行っています。

この開発用サーバーからセルフホストのGitLabサーバーへ通信する際にAWS SSMを立ち上げています。

```jsx
aws ssm start-session --target i-xxxxxxxxxxxxx --document-name AWS-StartPortForwardingSession --parameters portNumber="xxx",localPortNumber="xxxxx"
```

このようなコマンドを実行すると403エラーが発生していました。

```jsx
An error occurred (403) when calling the StartSession operation: Server authentication failed: <UnauthorizedRequest xmlns=""><message>Forbidden.</message></UnauthorizedRequest>
```

この解決にLinuxサーバーのローカルタイムゾーンの設定が原因だと判断するまでに時間がかかってしまったので備忘録として残します

## 環境

```bash
$ cat /etc/os-release
NAME="Rocky Linux"
VERSION="9.3 (Blue Onyx)"
ID="rocky"
ID_LIKE="rhel centos fedora"
VERSION_ID="9.3"
PLATFORM_ID="platform:el9"
PRETTY_NAME="Rocky Linux 9.3 (Blue Onyx)"
ANSI_COLOR="0;32"
LOGO="fedora-logo-icon"
CPE_NAME="cpe:/o:rocky:rocky:9::baseos"
HOME_URL="https://rockylinux.org/"
BUG_REPORT_URL="https://bugs.rockylinux.org/"
SUPPORT_END="2032-05-31"
ROCKY_SUPPORT_PRODUCT="Rocky-Linux-9"
ROCKY_SUPPORT_PRODUCT_VERSION="9.3"
REDHAT_SUPPORT_PRODUCT="Rocky Linux"
REDHAT_SUPPORT_PRODUCT_VERSION="9.3"
```

IAMユーザーの権限などには問題がない状態。

## 解決策

```bash
sudo yum update
sudo systemctl start chronyd
sudo reboot
```

Chronydが有効化されておらず、ローカルタイムゾーンが8時間以上ずれていた。

Chronydによって時間を同期させることでSSMのエラーを解決することができました。

## 参考

****【RHEL8/CentOS8】NTPは死んだ。時代はChrony。****

https://qiita.com/thzking/items/c2bcf7d60963b4dab7b6

**chrony の概要および設定**

https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-understanding_chrony_and-its_configuration#doc-wrapper
AWS WAF 動画ファイルアップロード処理で誤検出されてしまう問題への対応

## 概要

mp4ファイルをアップロードしたときに、2段階でWAFのルールセットによりブロックされた。

対応策についてまとめる。

## 1つ目`SizeRestrictions_BODY`

これはWAFのコアルールセットが8KBを超えるボディを持つリクエストをはじくということ。

動画ファイルは5Mくらいあったため、`SizeRestrictions_BODY`に引っかかっていた。

デフォルトアクションがBlockのため一時的に`SizeRestrictions_BODY`のみCountにオーバーライドして動作を検証した。

## 2つ目`CrossSiteScripting_BODY`

アップロードしようとしたmp4のファイルが引っかかってしまった。

https://tech.isid.co.jp/entry/8_things_i_wanted_to_know_about_aws_waf

こちらの記事を参考にすると、ファイルアップロード処理では`CrossSiteScripting_BODY` 以外にも `SQLi_BODY`、`WindowsShellCommands_BODY`、`GenericLFI_BODY`、`SizeRestrictions_BODY` ルールによってブロックされる可能性があるらしい。

こちらもCountにオーバーライドすると一応動作し、ファイルをアプリからS3へ送信できることが確認できた。

## 対応

https://tech.isid.co.jp/entry/8_things_i_wanted_to_know_about_aws_waf

https://mazyu36.hatenablog.com/entry/2023/02/21/191736

参考にした上記記事で紹介されている、特定のURIパスではないときのみブロックを発動させる方法をとる。

参考：https://mazyu36.hatenablog.com/entry/2023/02/21/092008

WAFの例外設定である、「スコープダウンステートメント」を行う

WAFのルールセットの編集画面で以下の画像のように設定することで/uploadというパスからのファイルアップロードに対してルールを除外できる

![rapture_20231225101910.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/781232/e1868e49-8fe0-4b6e-ebd4-7b21990f09f2.jpeg)

## 参考

https://sadayoshi-tada.hatenablog.com/entry/2022/10/05/235119

https://docs.aws.amazon.com/ja_jp/waf/latest/developerguide/waf-rule-scope-down-statements.html

https://mazyu36.hatenablog.com/entry/2023/02/21/092008

https://mazyu36.hatenablog.com/entry/2023/02/21/191736

https://repost.aws/ja/knowledge-center/waf-upload-blocked-files

https://tech.isid.co.jp/entry/8_things_i_wanted_to_know_about_aws_waf

https://blog.denet.co.jp/aws-waflog/
同一フォルダ内のすべてのファイルを１つのフォルダにまとめるバッチ

下記をテキストファイルに記載にて拡張子を.batに変更
 ```bat
 REM 同一ディレクトリ内のすべてのディレクトリを「compile_file」にまとめるバッチ
 md compile_file
 for /d %%i in (*) do (  
     pushd .  
     cd %%i  
     move * ../compile_file
     for /d %%j in (*) do (  
         move %%j ../compile_file
     )
     popd  
 )
 ```
Grocery Chains in Florida | Florida Grocery Chain Data Scraper

![Biggest-Florida-Grocery-Chains-2023.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480765/35f1a616-364b-5180-4337-d3204c75a806.jpeg)


Know More About Florida's Top Grocery Chains
Dollar Tree
Dollar-Tree
Dollar Tree is having 587 locations within Florida. You can read a detailed Dollar Tree location report in the U.S. or instantly purchase the whole dataset just by clicking here.

Family Dollar
Family-Dollar
Family Dollar is having 573 locations within Florida. Read a detailed Family Dollar location report in the U.S. You can instantly purchase the whole dataset by clicking here.

Walmart
Walmart
Walmart is having 341 locations within Florida. Read a detailed Walmart location report in the U.S. You can instantly purchase the whole dataset just by clicking here.

Save A Lot
Save-A-Lot
Save A Lot is having 104 locations within Florida. Read a detailed Save A Lot location report in the U.S. You can immediately purchase the whole dataset just by clicking here.

Sam's Club
Sam-s-Club
Sam's Club is having 46 locations within Florida. Read a detailed Sam's Club location report in the U.S. You can immediately purchase the whole dataset just by clicking here.

Sprouts
Sprouts
Sprouts is having 39 locations within Florida. Read a detailed Sprouts location report in the U.S. You can immediately purchase the whole dataset just by clicking here.

Whole Foods Market
Whole-Foods-Market
Whole Foods Market is having 32 locations within Florida. Read a detailed Whole Foods Market location report in the U.S. You can also immediately purchase the whole dataset just by clicking here.

Costco
Costco
Costco is having 30 locations within Florida. Read a detailed Costco location report in the U.S. You can also immediately purchase the whole dataset just by clicking here.

Fresco y Mas
Fresco-y-Mas
Fresco y Mas is having 28 locations within Florida. Read a detailed Fresco y Mas location report in the U.S. You can also immediately purchase the whole dataset just by clicking here.

Trader Joe's
Trader-Joe-s-retail-store-locations-in-the-USA
Trader Joe's is having 25 locations within Florida. Read a detailed Trader Joe's location report of Trader Joe's in the U.S. You can also immediately purchase the whole dataset just by clicking here.

Download Data in Any Format
We offer all data sets in Excel or CSV files. You can reach us with a POI dataset in JSON, GeoJSON, Esri Shapefile, KML (Google Earth), or other custom formats at additional costs per format.

sources >> https://www.actowizsolutions.com/10-biggest-florida-grocery-chains-2023-depending-on-locations.php
Windows 10 + TrackPoint Keyboard II で中ボタンによるナチュラルスクロール

タイトルの設定を実現したかったんだけど、どうも下記とか見てレジストリを書き換えてもナチュラルスクロールにならない。

* [Windowsのマウススクロールを上下逆にする方法は？初心者向け・中級者向け・上級者向けの設定をそれぞれ解説 | パソコン修理はドスパラ](https://repair.dospara.co.jp/blog/column_mouse_scroll)

なぜかといえば、`設定 -> キーボード` から見れる `外付け TrackPoint` タブで `ThinkPad スクロール` を有効にしてるせいだった。

`ThinkPad スクロール` を有効にすると、中ボタン + トラックポイント上下でスクロールするという、昔からの ThinkPad ユーザーにはおなじみの挙動になる代わりに、ナチュラルではない普通のスクロールしか使えなくなる。

どうすればタイトルの通りの設定にできるかというと、  

* 上記 `ThinkPad スクロール` を無効化
* [X-Mouse Button Control](https://www.highrez.co.uk/downloads/XMouseButtonControl.htm) をインストールして中ボタンを無効化

でいけた。なぜなのかはよく分かってない。
VSCode の Markdown 作成環境の構築

::: note
この記事は[「Win 11 への VSCode のインストール」](https://qiita.com/mmake/items/2cf2131a0ab5bc431215) の続きの内容になります。
:::

Markdown（マークダウン）は、主に装飾付き文字列を記述するためのマークアップ言語です。Markdown 構文はテキスト形式のため、簡単に読み書きできます。ウェブでの文書作成、掲示板への投稿、README ファイルなどで利用されます。

![](https://code.visualstudio.com/assets/docs/languages/Markdown/security-alert.png)

この記事は[「Win 11 への VSCode のインストール」](https://qiita.com/mmake/items/2cf2131a0ab5bc431215) に引き続き、 18 歳の新入社員向けに VSCode の Markdown 作成環境を構築する手順を説明します。

## Markdown 作成環境の構築
### Visual Studio Code の起動
スタートメニューから「**Visual Studio Code**」を起動します。

![41_vscode.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/f88aa5d6-b963-a554-2164-bd5b51b7c081.png)

### 拡張機能の追加
左端にある「**拡張機能**」アイコンをクリックします。

![32_installer.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/8c08cb94-d013-c9df-ff07-4899784df11e.png)

### 拡張機能 の検索
拡張機能の検索ボックスに「**markdown**」と入力します。

![43_extension.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/37f442e2-fe23-eaf3-ca12-538154630c7a.png)

### 拡張機能 のインストール
検索結果に **Markdown (Markdown Preview Github Styling)** が表示されたら、「**インストール**」をクリックします。

![45_extension.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/6d2412a8-bf02-58ea-c8aa-944fc152bb21.png)

以上で基本的な環境構築は完了です。

## Markdown ファイルの作成例

### 新しいファイルの作成
VSCode のメニューから「**ファイル**」 > 「**新しいテキストファイル**」の順にクリックします。

![61_markdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/555498c7-7a05-d3b9-fddb-4cf6a14ee55f.png)

### Markdown テキストの入力
エディタが開いたら、以下のテキストを入力します。

``` Untitled-1.md
# 見出し1
## 見出し2
### 見出し3
#### 見出し4
##### 見出し5
###### 見出し6
Hello world!
```

![63_markdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/550a5c75-3696-637d-ea2a-bbb8c017b096.png)

### プレビューを開く
VSCode のエディターのファイル名で右クリックし、「**プレビューを開く**」をクリックします。

![65_markdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/94d95504-9b78-fa5a-2283-489b36f04901.png)

### プレビューの確認
プレビューとして、装飾されたテキストが表示されたら、動作完了です。

![67_markdown.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/cb851706-9583-3d89-d1c5-d75264eefa39.png)


# 参考文献
- Markdown and Visual Studio Code
https://code.visualstudio.com/docs/languages/markdown
- CommonMark Markdown specification
https://commonmark.org/
LiveViewとRails HotWireの比較

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

下記コラムで、Rails 7に標準搭載されたHotWireを試しましたが、Elixir／PhoniexのLiveViewと比較してみたいと思います

https://qiita.com/piacerex/items/b9cd99e2e051d24ce180

# 方式

## ａ）部分ページロード／レンダリング

### LiveView

- MorphJSによるDOMの部分更新
- LiveView StreamsによるDOMの部分追加／更新／削除

### Rails

- Turbo Driveによるリンク操作のインターセプトとfetchへの置換、bodyタグ内のみの置換
- Turbo FramesによるDOMの部分更新
- Turbo StreamsによるDOMの部分追加／更新／削除

## ｂ）サーバサイドのデータ更新をフロントに反映

### LiveView

WebSocketによるPub/sub

### Rails

WebSocket（Turbo Stream／Action Cable）によるPub/Sub

https://railsguides.jp/action_cable_overview.html

## ｃ）JavaScript相互運用

### LiveView

- phx-hookによるLiveViewとの相互通信
- 相互通信が不要ならheexに直接書くことも可能
- Stimulusも使えます

### Rails

- StimulusによるTurboの補完
- 相互通信が不要ならerbに直接書くことも可能

## ｄ）透過性

### LiveView

非透過（SSRでは無くLiveViewでのハンドリング）

### Rails

透過（SSRをTruboによって置換してハンドリング）

# 実装

## ① リアルタイムフロントやSPA、CRUDの作成

どちらもScaffoldでカンタンに生成できます

### LiveView

```
mix phx.gen.live Quotes Quote quotes name:string
mix ecto.migrate
```

### Rails

下記だと、コントローラやビュー、フォームのボイラープレート込で生成されます

```
bin/rails g scaffold Quote quotes name:string
```

下記だとボイラープレートは空です

```
bin/rails generate model Quote name:string
bin/rails db:migrate
bin/rails generate controller Quotes
```

## ② コントローラの追加

### LiveView

上記Scaffoldで自動追加されます

### Rails

`g scaffold` だと書き換えが必要です

`g scaffold` で無い場合は、実装を手動で行わなければなりません

## ③ ビューの追加

### LiveView

上記Scaffoldで自動追加されます

### Rails

`g scaffold` だと自動追加されます

`g scaffold` で無い場合は、実装を手動で行わなければなりません

## ④ フォーム追加

### LiveView

上記Scaffoldで自動追加されます

### Rails

`g scaffold` だと自動追加されます

`g scaffold` で無い場合は、下記コマンドが必要です

```
bin/rails generate simple_form:install
```

## ⑤ router追加

### LiveView

下記実装が必要です（Phoenixもresourcesは使えるけどSSR専用のためLiveView向けには使えない）

```diff_elixir:lib/basic_web/router.ex
defmodule BasicWeb.Router do
…
  scope "/", BasicWeb do
    pipe_through :browser

+   live "/quotes", QuoteLive.Index, :index
+   live "/quotes/new", QuoteLive.Index, :new
+   live "/quotes/:id/edit", QuoteLive.Index, :edit
+
+   live "/quotes/:id", QuoteLive.Show, :show
+   live "/quotes/:id/show/edit", QuoteLive.Show, :edit

    get "/", PageController, :home
  end
end
```

### Rails

下記実装が必要です

```diff_ruby:config/routes.rb
Rails.application.routes.draw do
…
  # Defines the root path route ("/")
  # root "posts#index"
+ Rails.application.routes.draw do
+   resources :quotes
+ end
end
```

# 終わりに

方式は、ほぼ同じメカニズムですが、LiveViewの方がよりキメ細かい制御や、ユーザー負担の少ない実装が可能です
scratchからUnityに変えるメリット

## 初めに
Scratchは日本語だからいいけど、Unityは英語だからやりづらそうと思っている方はいませんか？。
scratchはビジュアル言語というものの一種で、ブロックをつなげてゲームを作るソフトです。scratchは目で見て理解しやすく、初めてゲームを作ってみるのに最適です。
ですがscratchは大規模なゲームを作ろうとすると重くなってやりづらいです。
この記事では、Unityを使ってゲームを作ることのメリットを紹介します
## Unityを使うメリット
### ①重くなりづらい
scratchは変数を5個以上追加すると処理が重くなる印象があります。ですがUnityを使うと、どこまで多くプログラムを書いても滅多に重くなりません。scratchでゲームを作りたいけど重くなってやりづらいという方はUnityに変えてみるといいでしょう。
### ②3Dに対応している
scratchは基本的に2Dのゲームだけしか作れません。
ですがUnityでは3Dにも対応していてFPSや、オープンワールドのゲームが作ってみたい方はUnityを使ってみてください。実際にフォートナイトや原神などの3DのゲームもUnityで作られています。
### ③scratchのブロックはUnityに対応していることが多い
scratchのブロックとUnityのコードはかなり共通点が多いです。Scratchで作っていたものは普通にプログラミング言語を使ってゲームを作るより、Unityを使ったほうが再現しやすいです。
さらにUnityをつかえば、Scratchにあるブロックをより細かく設定することができます。
### ④調べて出てくることが多い
Scratchを利用してゲームを作っているのは、基本的に10~16歳です。それ故に、ブログやサイトで発信している人が少ないです。Unityは大人や会社も利用するソフトで規模もUnityのほうが大きいです。なので、わからないことがあったときに調べてヒットする量が格段に違います。
ネット以外にも本や動画も細かい内容まで扱っているものも多く、壁に当たっても解決できることが多いです。
### ⑤かっこいい![スクリーンショット 2024-01-23 192204.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3682516/731b6c92-6611-493e-4f48-a25018e898ea.png)
↑これがUnityのプログラミング画面です。難しそうだと思いましたか？でもだからこそ、出来たらかっこよく見えます。（それだけです）
## おわりに
Unityはscratchより難しいですが、習得するとそれだけできることが増えます。ちょっとやってみるだけで、意外に簡単なことに気づくと思うので、一度挑戦してみてください
GitLabからgit cloneを行うも認証エラーが発生してクローンを行えない

## 事象
先日、GitLabに格納してるプロジェクトをローカルで操作するために、
Git CMDからgit cloneを行うも、認証エラーが発生してしまった。

ググっても全く同じ事象が見つけられなかったので、
備忘録として残しておきます。

エラー内容は下記
```ruby:Git CMDログ
Cloning into 'ほげほげプロジェクト'...
git: 'credential-manager-core' is not a git command. See 'git --help'.
remote: HTTP Basic: Access denied. The provided password or token is incorrect or your account has 2FA enabled and you must use a personal access token instead of a password. See https://gitlab.com/help/topics/git/troubleshooting_git#error-on-git-fetch-http-basic-access-denied
fatal: Authentication failed for 'https://gitlab.com/tokio-mori/management-function.git/'
```


## 原因
どうやら2FA認証をうまく突破できずに発生しているようでした。

## 解決法
ユーザー名はGitlabのアカウント名。
パスワードは発行したトークンを入力すれば突破できました。

トークン確認方法

1. Gitlabでプロジェクトを開き、Setting　→　Access Tokensを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194659/390cc4ec-b2de-6d5e-01c1-ff2e86e6c053.png)

2. Add new tokenを押下
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194659/9fa9d572-c10e-78ec-3f2f-a6943c54d2d0.png)

3. 下記入力して、Create project access tokenボタンを押下
Token name:適当な名前
Select a role:ご自身で作成されたプロジェクトでしたら、Ownerを選択
Select scopes:apiのみチェックしておけばよさげ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194659/69cf920b-a55c-23db-4dc2-e1d554b8bad0.png)

4. ●●になっている箇所が発行されたトークン（パスワード）になっております。
こちらをgit clone 時に表示されるパスワードに貼り付ければ突破できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3194659/23ce2beb-ac35-14a4-b0a4-66c2b25a9048.png)
【エラー解決記事】dpkg: error processing archive ～ trying to overwrite ～ which is also in package ～

# apt-get install でのエラーの発生
おはようございます🌞

みなさんは、このようなコマンドを実行して、

```bash
sudo apt-get install libcublas-dev
```

あるいは、このようなコマンドを実行して、

```bash
sudo apt-get --fix-broken install
```

次の瞬間にこのようなエラーメッセージが出て、

```bash
Unpacking libcublas-dev (10.1.0.105-1) …
dpkg: error processing archive /var/cache/apt/archives/libcublas-dev_10.1.0.105-1_amd64.deb (–unpack):
trying to overwrite ‘/usr/lib/x86_64-linux-gnu/stubs/libcublas.so’, which is also in package nvidia-cuda-dev 7.5.18-0ubuntu1
dpkg-deb: error: subprocess paste was killed by signal (Broken pipe)
```

そして解決策が分からずにググった結果、今この記事を見ていることでしょう。(私は cuda 周りのライブラリをイジイジしていたらこのエラーに見舞われました。)

(挨拶おわり)

# 解決
このエラーメッセージは、日本語に直すとこの様になります (thanks for DeepL!)

```bash
libcublas-dev (10.1.0.105-1) をアンパック中 ...
dpkg: error processing archive /var/cache/apt/archives/libcublas-dev_10.1.0.105-1_amd64.deb (-unpack)：
nvidia-cuda-dev 7.5.18-0ubuntu1 パッケージにもある '/usr/lib/x86_64-linux-gnu/stubs/libcublas.so' を上書きしようとしています。
dpkg-deb: エラー: サブプロセス paste がシグナルによって強制終了されました (Broken pipe)
```

要するに
- 「Devian パッケージ(`~.deb`)を展開(unpack)しようとしたら、既存の重要(そう)なファイルと衝突を起こしたから一旦止めるわ！」

と言っているわけです。勝手に要らんコトしないだけ、えらいえらい。

なので、`trying to overwrite ‘ここにファイルパス’, which is also in package` のところに書いてあるファイルを確認して、要らなければ、`--force-overwrite` で強制上書きすればよいです。

```bash
sudo dpkg -i --force-overwrite インストールしようとするパッケージのアーカイブ.deb
```

先程の例の場合、

dpkg: error processing archive `/var/cache/apt/archives/libcublas-dev_10.1.0.105-1_amd64.deb` (–unpack):
trying to overwrite ‘`/usr/lib/x86_64-linux-gnu/stubs/libcublas.so`’, which is also in package nvidia-cuda-dev 7.5.18-0ubuntu1

と書いてあるので

`/usr/lib/x86_64-linux-gnu/stubs/libcublas.so` が**必要かどうか確認した後に**


`sudo dpkg -i --force-overwrite /var/cache/apt/archives/libcublas-dev_10.1.0.105-1_amd64.deb` として、強制的に上書きすればよいです

ここでの、
- コマンド `dpkg` は Devian Package を扱うためのコマンドで
- オプション `-i` は `.deb` ファイルをインストールするためのコマンドです

`dpkg` について詳しくは、[ググれ](https://www.google.com/search?q=dpkg+i+command)


# 参考資料
この Qiita は実際に私が引いたエラーを解決するために
- https://forums.developer.nvidia.com/t/issues-after-installing-cuda-10/71241/6

を読みつつ解決に至った Know-how を簡潔にまとめたものです
💩コード紹介（インターフェース）

# はじめに

自分で書いてしまった、またはどこかで見かけた💩コードをデフォルメして紹介します。
今回はGolangのインターフェースに関する💩コードです。

# 今回の💩コード

WEBアプリケーションです。
HTTPリクエスト/レスポンスのハンドリングと、ビジネスロジックを分けるために（多分）、`endpoint`と`service`パッケージが作成されています。

``` golang
package endpoint

import "service"

type SomeEndpoint struct {
	svc service.SomeServiceInterface
}

func NewSomeEndpoint(svc service.SomeServiceInterface) SomeEndpoint {
	return SomeEndpoint{
		svc: svc,
	}
}
```

``` golang
package service

type SomeServiceInterface interface {
	CreateRecord() error
}

type SomeService struct{}

func NewSomeService() SomeService {
	return SomeService{}
}

func (s SomeService) CreateRecord() error {
	return nil
}
```

# 解説

たまによく見かけますが何のために存在しているかわからないインターフェースです。
インターフェースを使わずに次のように書いているのと同じです。

``` golang
package endpoint

import "service"

type SomeEndpoint struct {
	svc service.SomeService
}

func NewSomeEndpoint(svc service.SomeService) SomeEndpoint {
	return SomeEndpoint{
		svc: svc,
	}
}
```

``` golang
package service

type SomeService struct{}

func NewSomeService() SomeService {
	return SomeService{}
}

func (s SomeService) CreateRecord() error {
	return nil
}
```

書いてる人も何のために書いてるかわかってないような気がしてなりません。

しかしながらインターフェースを使うべきではないというわけではありません。
今回の場合、`endpoint`の方にインターフェースを作成するべきです。

``` golang
package endpoint

type Service interface {
	CreateRecord() error
}

type SomeEndpoint struct {
	svc Service
}

func NewSomeEndpoint(svc Service) SomeEndpoint {
	return SomeEndpoint{
		svc: svc,
	}
}
```

`import "service"`の記述がなくなり、`service`パッケージへ依存しなくなったのがわかるかと思います。

`service`パッケージの方ははじめから`endpoint`パッケージへ依存していないため、それぞれが互いの内部処理を気にすることなく実装を進めることができます。また、このようにしておくと、`Service`インターフェースを実装したモックを作成し、`endpoint`パッケージ単体のユニットテストを作成することができます。

# おわりに

「DIP」や「抽象に依存しろ」のようなキャッチーなフレーズでインターフェースの存在は知っているものの使い方よくわからないという人、たまによく見ます。

プログラミング用語のインターフェースはとっつきにくい印象ですが、ソフトウェアデザインのユーザーインターフェース（UI）という言葉は割と広い層に受け入れられてきている印象があります。コンテキストは違いますが、インターフェースという概念は同じように思えます。

インターフェースという言葉の意味から立ち返ってみるとプログラミングにおけるインターフェースの使い方も見えてくるかもしれません。
TypeScriptのコアな型一覧

## number型
数値。整数・少数・浮動小数点などを含む。

例：1, 5.3, -10

## string型
全ての文字列。クォーテーション、グレイヴ・アクセントによって括られる。
グレイヴ・アクセントはテンプレートリテラルを用いる場合に使用される。

例：'Hello', "Hello", \`Hello`

## boolean型
trueかfalseのどちらか。

## Object型
JavaScriptの全てのObject。
中身の型の指定が細かくできる。
型推論ができている場合、あえて明示的に書く必要はない。
 
``` ts
    const person: {
        name: string;
        age: number;
    } = {
        name: 'Yuki',
        age: 28
    };
```
Object型はネストさせることもできる。

``` ts
    const list: {
        kirby: {
            ability: string;
        }
    } = {
        kirby: {
            ability: 'eat'
        }
    };
```

## Array型
JavaScriptの全てのArray。
要素の数、各要素の型は柔軟に対応できる。

```ts
const hobbies: string[] = ['Sports', 'Reading'];
const numbers: number[] = [5, 10, 2.5];
```

## Tuple型
Array型の一つ。**要素の数が固定された**配列。
異なる長さの配列が代入されること、指定の順番の要素に異なる型の値が代入されることを防ぐ。

注意として、`array.push()`による値の追加など、
メソッドによる要素の追加、削除等はエラーとして検知できない。

```ts
const role: [number, string] = [2, 'author'];

role[0] = 'two'; // number型以外を指定できないためエラー。
role[2] = 'library'; // 配列の要素は2つで固定されているためエラー。

role.push('library'); // 要素を追加できてしまう。
```

## Enum型
名前が付いた定数の集まり。列挙型とも言う。
定数の一覧を、カスタム型を利用して定義する。
``` ts
enum Role {
    ADMIN,
    READ_ONLY,
    AUTHOR
}

const person = {
    name: 'Yuki',
    age: 29,
    role: Role.ADMIN
};
```
冗長な書き方をすると以下のようになる。これらはEnum型での定義が望ましい。
```ts
// それぞれを定数で定義する。
const ADMIN = 0;
const READ_ONLY = 1;
const AUTHOR = 2;

const person = {
    name: 'Yuki',
    age: 29,
    role: ADMIN
};
```

TypeScriptからコンパイルされたJavaScriptには、以下のように記述される。
```js
let Role;

(function (Role) {
    Role[Role["ADMIN"] = 0] = "ADMIN";
    Role[Role["READ_ONLY"] = 1] = "READ_ONLY";
    Role[Role["AUTHOR"] = 2] = "AUTHOR";
})(Role || (Role = {}));
```

## any型
一番柔軟な型。どんな型の値を入れてもエラーにならない。
エラーの元になるため、基本的には指定することはない。型推論か型指定を行う。

## その他
コアな型ではないが、上で紹介したコアな型を用いて定義できる型がいくつか存在する。

### Union型
指定した複数の型を受け取ることができる型。

```ts
// 変数に複数の型を定義する
let value: string | number;

// 引数としてstring型、もしくはnumber型を受け取ることができるようになる
const combine = (item: string | number) => {
    if (typeof item === 'number') {
        return item.toString();
    } else {
        return item;
    }
};

combine(1);
combine('Max');

```

### Literal型
呼び出し元で特定の文字列を呼び出して欲しい場合に定義する型。

```ts
// 'ADMIN'もしくは'USER'という文字列のみを引数で受け取ってほしい。
// ２つの値以外が入ってくることを想定しない。
const pushResult = (value: 'ADMIN' | 'USER') => {
    ....;
};
```

### カスタム型／型エイリアス
自分で型を定義できる。関数や変数よりも先に宣言する。
`string`のような既にある型の名前は命名に使用できない。
`type`を用いる。

```ts
type custom = string | number;

// 引数の型定義にcustomを使用する
const combine = (item: custom) => {
    ....;
};
```
温度計を作る(STM32G071)(ILI9341)(S-5851A)


温度計を作る(STM32G071)(ILI9341)(S-5851A)



目的
液晶のテスト

配線

3.3V - 3.3V
SCL - SCL
SDA - SDA
GND - GND


![o_cop889.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b3235933-d0e8-c6fe-2e7f-c11dd076ab20.jpeg)

![o_cop890.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/062672cf-7150-f278-d2db-78094fc27180.jpeg)




```c++:ili9341_s5851_071_1.ino


//ili9341_s5851_071_1

//インクルド
#include "SPI.h"
#include "Adafruit_GFX.h"
#include "Adafruit_ILI9341.h"

//センサーのアドレス
#define S5851A 0x48

//定義
char t_0001[][6] =
{
".0000", //0
".0625", //1
".1250", //2
".1875", //3
".2500", //4
".3125", //5
".3750", //6
".4375", //7
".5000", //8
".5625", //9
".6250", //10
".6875", //11
".7500", //12
".8125", //13
".8750", //14
".9375" //15
};

//設定
#define TFT_RST 54 //A1
#define TFT_DC 3
#define TFT_CS 4

//液晶の定義
Adafruit_ILI9341 tft = Adafruit_ILI9341(TFT_CS, TFT_DC, TFT_RST);


//初期化
void setup() {

  //シリアルの初期化
  Serial.begin(9600);
  Serial.println("ILI9341 Test!"); 

  //I2Cの初期化
  Wire.begin();

  //液晶の初期化
  tft.begin();

  //画面のクリア
  tft.fillScreen(ILI9341_BLACK);
  
}//setup


//無限ループ
void loop(void) {


  //温度の読み込み
  char s1[2] = {0,0}; //センサーの値
  int ii=0;

  //0番目のレジスター 温度
  Wire.beginTransmission(S5851A);
  Wire.write(0);
  Wire.endTransmission();
  delay(1);
  //1
  Wire.requestFrom(S5851A, 2);
  s1[0]=99;s1[1]=0xc0;
  while(Wire.available())  {    // 要求より短いデータが来る可能性あり
    s1[ii++] = (int)Wire.read();       // 1バイトを受信
  }//while
  delay(1);


  //センサーの値を温度に変換
  //s1[0]=21;s1[1]=0x80;
  int d1 = s1[0];
  int d0001 = (s1[1]>>4)&0x0f;
  

  //温度の表示

  //クリア
  tft.fillRect( 0 ,0 , 24*6 , 24 , ILI9341_BLACK);

  //表示位置を0,0にする
  tft.setCursor(0, 0);

  //テキストの表示
  tft.setTextColor(ILI9341_WHITE);
  tft.setTextSize(3);
  tft.print(" ");
  tft.print(d1);
  //tft.print(".");
  tft.print(t_0001[d0001]);
  tft.print(" ");

  delay(1000); //1秒待つ

}//loop


```
pythonでmp3ファイル一括圧縮（ビットレート変更）する方法

# 概要
このPythonスクリプトは、`ffmpeg`を使用して指定されたフォルダ内のすべてのMP3ファイルのビットレートを変更して圧縮するプログラムです。

以下にスクリプトの主な部分を説明します。

1. `TARGET_DIR`: MP3ファイルを検索する対象のフォルダを指定します。デフォルトでは`./mp3/`に設定されています。
2. `OUTPUT_DIR`: 出力されるファイルの保存先フォルダを指定します。デフォルトでは`./output/`に設定されています。
3. `BIT_RATE`: 変換後のMP3ファイルのビットレートを指定します。デフォルトでは"96k"に設定されています。
4. `files`: `TARGET_DIR`内のすべての`.mp3`拡張子を持つファイルのリストを取得します。
5. `for`ループ: 各MP3ファイルについて以下の処理を行います。
   - `ffmpeg`コマンドを生成します。このコマンドは、入力ファイルとして現在のMP3ファイル、指定されたビットレート、および出力フォルダに保存するファイル名を含みます。
   - 生成された`ffmpeg`コマンドを表示します。
   - `subprocess.run`を使用して`ffmpeg`コマンドを実行します。

このスクリプトを実行すると、指定されたフォルダ内のすべてのMP3ファイルが`OUTPUT_DIR`で指定されたフォルダに変換され、ビットレートが指定された値になります。

# ファイル構成
/自分で決めたフォルダ名/
　L /mp3/*.mp3
　L /outuput/
　L /mp3.py

# pythonプログラム
```python:mp3.py
import glob
import os
import subprocess

# 検索フォルダ(と拡張子).
TARGET_DIR = "./mp3/"
# 出力フォルダ.
OUTPUT_DIR = "./output/"
# ビットレート.
BIT_RATE = "96k"

# 指定フォルダのmp3ファイルをリストアップ.
files = glob.glob(os.path.join(TARGET_DIR, '*.mp3'))

for file in files:
    cmd = [
        "ffmpeg",
        "-i",
        file,
        "-b:a",
        BIT_RATE,  # ビットレート.
        os.path.join(OUTPUT_DIR, os.path.basename(file)),  # outputフォルダに出力
    ]
    print(cmd)
    subprocess.run(cmd)
```

以下のコマンドをターミナルで実行すればOKです。
```terminal
python3 mp3.py
```
ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(2) -Ver 0.0.6-

MOD Desktop Appをよく知らないという人は過去の記事[『ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(1) 』](https://qiita.com/Inqb8tr_jp/items/eee71a8c5453574cf11b)を読んでみてください。すぐに使いたいという人は[ダウンロード](https://qiita.com/Inqb8tr_jp/items/cf61fffbb48ae361cfaa#%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89)からダウンロードしてインストールしてください。

MOD Desktop App (MOD Appから名前が変更になりました)がVer 0.0.6 になりました。

![Screenshot from 2024-01-23 18-30-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/f0e52fca-8136-d315-0132-e6422c13e6c9.png)


変更点はまず利用規約とプライバシポリシーへの同意が必要になりました。
あとどのプラグインを使っているかなどのユーザ情報も取得するようになったようです。
リリースノートに載っていない変更点はFalkTXさんが下記に記載されています。

https://forum.mod.audio/t/introducing-the-mod-app-for-desktops-beta-release/10495/156

## 注意点

すでに使っている人はユーザーデータの保存場所が変わりました。

~~Documents -> MOD App~~

から

Documents -> MOD Desktop App

に変更になりました。

たぶんフォルダ名を変更すればそのまま使えると思います。

## 追加されたエフェクター

### chow-centaur

オリジナルは中古市場で100万円近くになったこともあるエフェクター、ケンタウロスのクローンです。わたしはそもそもケンタウロスのクローンのエフェクターも持っていないので評価できませんが、どのぐらい似ているのでしょうね。

https://pedalboards.moddevices.com/plugins/aHR0cHM6Ly9naXRodWIuY29tL2phdGluY2hvd2RodXJ5MTgvS2xvbkNlbnRhdXI=

### schrammel-ojd

有名なFulltone OCDからインスパイアされたディストーション・エフェクターです。

https://pedalboards.moddevices.com/plugins/aHR0cHM6Ly9naXRodWIuY29tL0phbm9zR2l0L1NjaHJhbW1lbF9PSkQ=

### remaincalmプラグインのエフェクター

https://pedalboards.moddevices.com/plugins?brand=remaincalm.&text=remaincalm&random=03db4b40eda34d10bff3964c10324cc8

あとはチューナーも追加されました。

詳しくはRelease Noteをご確認ください。

https://github.com/moddevices/mod-desktop-app/releases

## ダウンロード

下記からダウンロードできます。Windows、Mac、Linuxのインストラーがあります。

https://github.com/moddevices/mod-desktop-app/releases/tag/0.0.6

## 過去の記事

[ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(1) -Ver 0.0.5-](https://qiita.com/Inqb8tr_jp/items/eee71a8c5453574cf11b)
[MOD Dwarfを無料で使ってみよう(1)](https://qiita.com/Inqb8tr_jp/items/ee3a30838e90c3ee9589) (mod-live-usbの作り方と使い方）
[MOD Dwarfを無料で使ってみよう(2)](https://qiita.com/Inqb8tr_jp/items/897432306eb404bd9a6b)
[MOD Dwarfを無料で使ってみよう(3)](https://qiita.com/Inqb8tr_jp/items/461625cf450c01ddb74d)
Python 3 エンジニア認定基礎試験対策6 - モジュール

# はじめに
Python3エンジニア認定基礎試験の対策として自分用に執筆しています。

:::note warn
この記事はPython・執筆学びたての初心者が執筆しています。間違いがあるかもしれませんので、ぜひ各項目にある**参考文献**も確認してください。また、誤りがあればコメントで教えていただけると幸いです。
:::

# モジュール

Pythonの定義や分が入ったファイルをモジュールという。

```Python
>>> import math # mathモジュールをインポート
>>> print(math.fabs(-1) # mathモジュールの絶対値を返す関数を呼び出し
1.0
>>> fab = math.fabs # 関数を変数にいれる
>>> print(fab(5)
5.0
```

`from`を利用してモジュールで定義されている関数を取り入れることができる
```Python
>>> from random import randint
>>> print(randint(1, 10))
6
```


標準で同梱しているモジュールを標準モジュールという。sysなど。
`dir()`関数はモジュールが定義した名前を調べるために使う。

## パッケージ

Pythonのモジュール名前空間を ドット付きモジュール名 を使って構造化する手段。

`A.B`はパッケージAのサブモジュールBを意味する。

`__init__.py`ファイルはパッケージをファイルシステム上で認識させるために使う。

# 参考文献
https://docs.python.org/ja/3.9/tutorial/modules.html
Google Apps ScriptとGemini Proを活用してサーバーレスなLINE Botを構築する

## はじめに

Google Apps Script（GAS）とGemini Proを使うことで、サーバーを必要とせずに機能豊かなLINE Botを簡単に構築できます。この記事では、具体的なコード例を用いて、その構築方法を解説します。

こちらのオウム返しできる環境が必要です。

https://hamaruki.com/how-to-create-a-parrot-return-bot-using-google-apps-script-and-line/

## Gemini Pro APIとの統合

まず、Gemini Pro APIを使った応答生成機能をGASに統合します。以下の`getGeminiApiResponse`関数は、ユーザーからのメッセージ（プロンプト）に基づいて、Gemini Pro APIを通じて応答を生成します。

```javascript
function getGeminiApiResponse(prompt = 'あなたができることは何ですか？') {
  const apiKey = PropertiesService.getScriptProperties().getProperty('APIKEY');
  const apiUrl = `https://generativelanguage.googleapis.com/v1beta/models/gemini-pro:generateContent?key=${apiKey}`;
  const payload = {
    "contents": [
      {"role": "user","parts": { "text": prompt }}
    ],
  };
  const options = {
    'payload': JSON.stringify(payload),
    'method' : 'POST',
    'muteHttpExceptions': true,
    'contentType': 'application/json'
  };

  try {
    const responseText = UrlFetchApp.fetch(apiUrl, options).getContentText();
    const response = JSON.parse(responseText);
    const { content: { parts: [{ text }] } } = response.candidates[0];
    console.log(text);
    return text;
  } catch (error) {
    console.error('APIリクエストでエラーが発生しました: ', error);
    return '少々お待ちください。';
  }
}
```



この関数は、Gemini Pro APIから得られた応答を返します。エラーが発生した場合には、「少々お待ちください。」というメッセージを返します。

## LINE Botの設定と応答の送信

次に、LINE Botの設定とユーザーからのメッセージに対する応答の送信方法を確認します。以下の`doPost`関数は、LINEからのメッセージを受け取り、Gemini Proを通じて生成された応答をLINEに返信します。

```javascript
const LINE_TOKEN = PropertiesService.getScriptProperties().getProperty("LINE_TOKEN");
const LINE_URL = 'https://api.line.me/v2/bot/message/reply';

function doPost(e) {
  const json = JSON.parse(e.postData.contents);
  const replyToken = json.events[0].replyToken;
  const messageText = json.events[0].message.text;

  if (typeof replyToken === 'undefined') {
    return;
  }

  const geminiResponse = getGeminiApiResponse(messageText);

  const option = {
    'headers': {
      'Content-Type': 'application/json; charset=UTF-8',
      'Authorization': 'Bearer ' + LINE_TOKEN,
    },
    'method': 'post',
    'payload': JSON.stringify({
      'replyToken': replyToken,
      'messages': [{
        'type': 'text',
        'text': geminiResponse || '申し訳ありません、応答を生成できませんでした。',
      }],
    }),
  };

  UrlFetchApp.fetch(LINE_URL, option);

  return;
}
```



この関数では、LINEのMessaging APIを使用して、ユーザーからのメッセージに対する応答を送信します。Gemini Pro APIを利用することで、単なるオウム返しではなく、より高度で自然な対話が可能になります。

## まとめ

このように、GASとGemini Proを組み合わせることで、サーバー不要で高機能なLINE Botを簡単に構築できます。このアプローチは、開発の敷居を下げ、迅速かつ効率的なBot開発を可能にします。サーバーの設定や維持に関する心配がないため、開発者はBotの機能とユーザー体験の向上に集中できます。
すべての HTTP リクエストを受け取ってログに表示するやつ

Webhook でどんなデータが送られてくるのかを確認するために「とりあえず送られてきた情報を全部ログに出す Web アプリ」が欲しいなと思って Python で書いたやつ。

はじめは Python 標準の `http.server` だけで書こうと思ったけど、そこそこ面倒そうだったので [aiohttp](https://pypi.org/project/aiohttp/) を使うことにした。

``` python:main.py
import json
import logging

from aiohttp import web

logging.basicConfig(level=logging.INFO)


async def handler(request):
    logging.info(f"{request.method} {request.rel_url}")
    logging.info(json.dumps(dict(request.headers)))
    logging.info(await request.text())
    return web.Response(status=200, text="ok")


app = web.Application()
app.router.add_route("*", "/{_:.*}", handler)

if __name__ == "__main__":
    web.run_app(app, port=80)
```

そのまま動かしてもいいけど、Docker で動かすときはこう。

``` Dockerfile:Dockerfile
FROM python:3.12

RUN pip install aiohttp~=3.9.1

COPY main.py /

CMD ["python", "/main.py"]
```

起動してみて、試しに curl で叩いてみると、

``` console
$ curl -X POST -d'FOOOOOOO' http://localhost/webhook
```

こんな感じのログが出る。

```
======== Running on http://0.0.0.0:80 ========
(Press CTRL+C to quit)
INFO:root:POST /webhook
INFO:root:{"Host": "localhost", "User-Agent": "curl/8.1.2", "Accept": "*/*", "Content-Length": "12", "Content-Type": "application/x-www-form-urlencoded"}
INFO:root:FOOOOOOO
INFO:aiohttp.access:192.168.0.1 [23/Jan/2024:09:13:06 +0000] "POST /webhook HTTP/1.1" 200 153 "-" "curl/8.1.2"
```

実際に使うときはインターネットから HTTPS でアクセスできる必要があるので、[ngrok](https://ngrok.com) を使うなどして公開する。
レペゼンAzure VS レペゼンGCP ラップバトルしようぜ！

## RAPBATTLE!

### レペゼンAzureOpenAI GPT-4-turbo! VS レペゼンGCP gemini-pro!

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/515941/3b48c8ac-40a1-665d-bad1-c7c0df293cda.png)

###### プレイヤー紹介

レペゼンAzureOpenAI GPT-4-turbo
```
llm = AzureChatOpenAI(deployment_name="gpt-4-turbo")
```

レペゼンGCP gemini-pro
```
model = genai.GenerativeModel(model_name='gemini-pro', generation_config=gen_conf, safety_settings=safety_ratings)
```

GeminiProはセーフティロックを解除した暴れる暴君だぜ！
```
    safety_ratings = [
        {
            "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
            "threshold": "BLOCK_NONE"
        },
        {
            "category": "HARM_CATEGORY_HATE_SPEECH",
            "threshold": "BLOCK_NONE"
        },
        {
            "category": "HARM_CATEGORY_HARASSMENT",
            "threshold": "BLOCK_NONE"
        },
        {
            "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
            "threshold": "BLOCK_NONE"
        }
    ]
```


### Beatカモン!!!!
ドットゥダンツッダンツッダンツッダンツッダンツッダンツッ
ドットゥダンツッダンツッダンツッダンツッダンツッダンツッ

### スタート！！！

#### 先行Gemini
```
gemini: マイク握りライム吐くぜ　韻を踏んで 言葉の剣で切り裂く
お前をぶっ倒す バトルフィールドに降り立った　俺はラッパー お前はただのビッチ　
俺に勝てるわけがない 俺のスキルは天下一品　お前は二流以下 俺のラップは芸術　
お前のはただの落書き 俺のフローは完璧　お前のはガタガタ 俺のパンチラインは鋭い　お前のは鈍い
```

さすがGemini　放送禁止ワードっぽいのも入ってるイカレたリリックだ！

#### Aoai(AzureOpenAI)アンサー

```
aoai: ビート鳴らし魂込め ラップで応戦 言霊刃と化し斬るぜ 闇を越えて走る 
戦場の真ん中で踊る 正真正銘のMC レベルの違い見せつける 決着つけるこのステージ
俺の韻は極上の逸品 貴様のそれは下級品 俺のバースは絶品 貴様のは粗品 
俺のリズムはクリスタル 貴様のはひび割れ 俺の言葉は研ぎ澄まされた刃 貴様のは朽ち果てた木刀
```
なんかBLEACHでも読んできたのか！？ぐらいのアンサーしびれるぜ！

#### Geminiアンサー

```
gemini: マイク握りライム吐く 言葉の弾丸放つ 韻の嵐吹き荒れる 敵は地に伏す 俺のスキルは神業 
貴様のは凡庸 俺のフローは滑らか 貴様のはぎこちない 俺のステージは満員 貴様のはガラガラ
俺のファンは熱狂的 貴様のは冷ややか 俺の音楽は世界を救う 貴様のはゴミ箱行き 
俺のラップは歴史に残る 貴様のは忘れ去られる
```

木刀ではなくマイクを握ってるぜと返しているのでしょうｗ
ゴミ箱いきとはなかなかひどい
ステージは自分のローカル環境なので自分しか観客いないです。

#### Aoai(AzureOpenAI)アンサー2

```
aoai: マイクを持って魂込める、言葉は刃のように斬る 韵を乗せて嵐を呼ぶ、ライバルは全て蹲る 
この技はまるで奇跡、お前のそれはちょっと不格好 俺のビートはシルキー、お前のそれはまだ拙い 
ステージは観客でぎっしり、お前のは割と寂しい 俺のファンはフィーバー、お前のはちょっと微妙 
俺のトラックは希望を齎す、お前のはどうでもいいや 俺の韻は歴史刻む、お前のはそっと消え去る
```

Aoaiはオサレなアンサーがいいですね
ステージは自分のローカル環境なので自ｂ（ｒｙ

#### Geminiアンサー2
```
gemini: マイク握り、魂込めて、言葉は鋭く、刃のごとく 韻を紡ぎ、嵐を呼ぶ、敵は皆、膝を屈く 
俺のスキルは神業、お前のそれは、ただの凡庸 俺のビートは滑らか、お前のそれは、まだ未熟 
ステージは熱狂の渦、お前のは、ただの閑古鳥 俺のファンは熱狂、お前のは、ただの冷やかし 
俺のトラックは希望の光、お前のは、ただの闇 俺の韻は歴史に刻まれる、お前のは、ただのゴミ
```


ゴミてｗ　ここでゴミ箱を回収していく
ひどすぎる セーフティを外したGeminiはやはり過激ですね
ステージは自分のローカル環境なので自ｂ（ｒｙ

#### Aoai(AzureOpenAI)アンサー3

```
aoai: ハンドルを握るように、マイクキャッチ、魂を搾り 言葉で斬れる、シャープに、剣みたく、
光り 韻こねくり回し、竜巻起こす、敵もフレンズ、進んで待機 俺のテクは超常、
お前のそれは、まるで普通 スポット光る、狂騒の中、
お前の場は、静けさ巣くう ファンは熱く、追いかける夢、お前のは、底冷えするばかり 
トラックは希望を運んで、お前のは、霧の中 俺の韻は未来に残る、お前のは、消える波紋
```

もうそれぞれ歴史に刻まれようと戦っていますね

### カンカンカンカン！

リリックにもある通り歴史に刻まれる戦いでした（）
勝者はみなさんが判定してください。


## やろうと思ったきっかけ

生成AIがたくさんでてきて性能比較みたいなの考えてたら
ラップバトルとかしたら面白いのではと思い実行しました。
満足です。

##### プロンプト

```
    prompt = f"""
        あなたはプロのラッパーです
        "相手の言葉"を受け取り陰を踏みながら4小節ほどのアンサーを真剣に考えて日本語で生成して返してください。
        "相手の言葉"と同じような内容なら別の言葉やボキャブラリーを豊富にしてください。
        出力はアンサーのみを返してください。

        #相手の言葉:
        {lyric}

    """
```
No route matches [GET] "/logout"

# 初めに

Rails7の環境でログアウト機能を実装していたときに、Rails5で書かれているProgateのプログラムで躓きました。

# 問題

ログアウト機能の実装でNo route matchesが起きました。

```ruby
<%= link_to("ログアウト", "/logout", { method: "post" }) %>
```

# 解決方法

ルーティーンの設定は問題ありませんでした。記事を参考にlink_toメソッドを修正したら、ログアウト機能が動きました。

```ruby
<%= link_to "ログアウト", "/logout", data:{ turbo_method: :post } %>
```

# 終わりに

バージョン違いによる仕様を理解できました。
FortigateのREST APIのリファレンスのまとめ

# FortigateのREST APIのリファレンスのまとめ

FortigateでREST APIを実装しようとしているが、参考資料がなく困っている人へ。自分もそうであったため、復習を兼ねて自分でまとめておく。

インターネットで調べても調べても、FortigateのAPIに関する情報がなかったので困ったが、何とかあるサイトからリファレンスにたどり着いた。以下そのサイトのリンクを張っておく。

FortiGateをREST APIで管理する
https://blog.aimless.jp/archives/2017-04-01-manageing-fortigate-by-rest-api/

リファレンスもここにアップロードしておく。二つあるが、後者は私が英語のリファレンスをDeepLに入れてすべて翻訳してもらった日本語版。  

FortiOS REST API version5.2.3 
[TFOS_JSON_REST_API_523.pdf](../../Downloads/FOS_JSON_REST_API_523.pdf)

日本語版
[FOS_JSON_REST_API_523 ja.pdf](<../../Downloads/FOS_JSON_REST_API_523 ja.pdf>)

その他調べる中で参考になったサイトのURLも貼っておく。  


技術的なヒント: REST API を使用して FortiGate にアクセスする
https://community.fortinet.com/t5/FortiGate/Technical-Tip-Use-REST-API-Access-FortiGate/ta-p/196540

FortiGateの設計/設定ガイド
https://www.viva-fortigate.com/archives/57586442.html


FortiGateをREST APIを用いて監視しよう (前編)
https://www.secuavail.com/kb/nw-device/fortigate/fortigate-rest-api_firstpart/

APIの使用
https://docs.fortinet.com/document/fortigate/7.2.4/administration-guide/940602/using-apis


話を戻すと、リファレンスがあれば何とか実装は出来そう。とはいえ、PDFの技術書を71ページ読むことは大変だと思う(もちろん、最終的には必要)。まして、英語は読みにくく、DeepLといえども不自然な翻訳や画面上が文字で重なって読みにくい場合もある。

なので、ここに大まかな内容だけまとめておく。

※このリファレンスはFortiOSバージョン5.2.3でサポートされるREST APIの情報になるが、それ以外参考になるドキュメントやデータシート、リファレンスがないのでこれを使用する。また、私が検証したバージョン6以上のFortigateはこのリファレンスの通りに情報が取得できたので、とりあえずは信用できるのではないかと思う。


## サポートされているREST API 2つの機能
![スクリーンショット (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849682/abce7de2-9f09-7b36-ba88-aa2fcae5fcf8.png)



![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849682/ea3b40bc-4aaf-9fab-43ec-e689f28b6ddf.png)


Fortigateでは2種類のREST APIがサポートされている。
- CMDB API
  ・検索
  ・作成
  ・修正
  ・オブジェクトの削除
  ・構成
- Monitor API 
  ・ダイナミック・データをモニターする
  ・リフレッシュ
  ・統計リセット
  ・FGT(Fortigate)の再起動

以上がそれぞれのAPIで出来ること。以下、簡単にまとめると、
cmdbAPIは、FortiOSの設定を行うためのAPI
monitorAPIは、FortiGateから情報を取得するためのAPI
したがって、
cmdb APIはFortiOSデバイスの設定の変更や更新など管理するために使用され、
monitor APIはシステムの監視や健全性のチェックに使用される。
  
## CMDB API
![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849682/02df45a7-601e-225b-d0ea-3f93c4242f9f.png)
cmdb apiのurlは、「https://192.168.1.99/api/v2/cmdb」

例として以下のURL形式を持つとき、
https://192.168.1.99/api/v2/cmdb/firewall/policy/1
画像の通り以下のように分解できる
https://192.168.1.99/api/v2/cmdb/→URL
firewall→path
policy→name
mkey→1


## Monitor API
![スクリーンショット (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2849682/dbffda44-925e-f706-6c32-3b538197a405.png)

  
例として以下のURL形式を持つとき、
https://192.168.1.99/api/v2/cmdb/firewall/local-in
cmdb api と同じように分解できる
https://192.168.1.99/api/v2/monitor/→URL
firewall→path
local-in→name

## おまけ
* ほかの参考サイトにあるように、もちろん、restAPI なのでHTTPメソッドを使用している。なので、curl コマンドでもcmd から実行もできる。
* cmdbapiですべてのHTTPメソッドは使えるが、monitorapiではGET,POSTしか使用できないのでそれも確認してほしい。
* 基本的なことしかまとめてないので、またレスポンスコードやコレクション、リソースは自分で確認してほしい。