OmniAICreator/Qiita-1.07M huggingface dataset:
【TypeScript】指定範囲の数値型

以下のように型定義すると指定した数字の範囲のnumber型を定義できます。

```ts
type NumericRange<
  START extends number,   // STARTは開始の数値を表すパラメータで、number型を拡張します。
  END extends number,    // ENDは終了の数値を表すパラメータで、number型を拡張します。
  ARR extends unknown[] = [],    // ARRはunknown型の配列を表すパラメータで、デフォルトは空の配列です。
  ACC extends number = never  // ACCは累積値を表すパラメータで、number型を拡張します。デフォルトはnever型です。
> = ARR['length'] extends END
  ? ACC | START | END   // ARRの長さがENDと等しい場合、ACC、START、ENDのいずれかの型を返します。
  : NumericRange<    // ARRの長さがENDと等しくない場合、NumericRange型を再帰的に呼び出します。
      START,
      END,
      [...ARR, 1],  // ARRに1を追加します。これにより、ARRの長さが増えます。
      ARR[START] extends undefined ? ACC : ACC | ARR['length']  // STARTの位置に要素が存在しない場合、ACCをそのまま引き継ぎ、存在する場合、ACCとARRの長さのいずれかの型を返します。 
    >

NumericRange<500, 599>
// 500 | 599 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 529 | 530 | 531 | ... 66 more ... | 598
```
Xcode CloudでCFBundleIconName関係でビルドが成功しないケース

表題タイトルについて質問されたケースで
回答に少し悩んだケースがあったので共有します。

ローカルでのアーカイブは成功するのに
XcodeCloud の場合に次のエラーが発生して失敗するケースがありました。

> Missing Info.plist value. A value for the Info.plist key 'CFBundleIconName' is missing in the bundle ~~~~~. Apps built with iOS 11 or later SDK must supply app icons in an asset catalog and must also provide a value for this Info.plist key. For more information see http://help.apple.com/xcode/mac/current/#/dev10510b1f7.

> Missing required icon file. The bundle does not contain an app icon for iPhone / iPod Touch of exactly '120x120' pixels, in .png format for iOS versions >= 10.0. To support older versions of iOS, the icon may be required in the bundle outside of an asset catalog. Make sure the Info.plist file includes appropriate entries referencing the file. See https://developer.apple.com/documentation/bundleresources/information_property_list/user_interface

CFBundleIconNameあたりで検索すると、割とこういう記事が出るんですが...
今回はこちらでは解決しませんでした。
https://forums.developer.apple.com/forums/thread/92638

今回の問題は、アイコンファイル名が日本語であったのが問題であったようです。

AppIconの欄で、アイコンを右クリックしてShow In Finder移動できます。

![CleanShot 2024-03-23 at 23.21.00@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6678/780820ad-4ee7-e34a-f3b4-577d5143dc6c.png)

そしてファイル名が日本語になっていたら修正してみてください。

![CleanShot 2024-03-23 at 23.21.25@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6678/93229341-a6e8-8d63-76c8-8bc5327dc72a.png)

基本的には、プログラミングの検索は英語サイトが良いことが多いのですが
英語圏以外の、日本語ファイル名などの問題でしたので
なかなか情報に当たるのが難しかったですね。

プログラミング全般にですが、日本語ファイル名はトラブルが起きやすいので警戒して
できる限り、英語ファイル名を使用したほうがトラブルを回避しやすいでしょう。

## お知らせ

私は、プログラミングの質問をSlackで行うサービスをご提供しております。
もしご興味ありましたら https://twitter.com/yoneapp までご連絡ください。
ご要望のサポート内容と頻度によって、月額1〜5万のご予算感でご案内しております。
RDA5807Hを使ってラジオを聴こう！

## きっかけは？
とある知り合いから「こんなの買ったんだけど使い方わかんねー」と話があったから。
調べてみると確かに情報が少ない……世界を代表する秋月電子が販売する商品で情報が少ないのは良くあることなので調査がてら動かしてみることに。

## 参考サイト
以下のサイトがめちゃめちゃ役に立った。
① https://www.electronicsblog.net/arduino-fm-receiver-with-tea5767/
② https://www.sparkfun.com/datasheets/Wireless/General/TEA5767.pdf
秋月電子が公開しているデータシートは参考程度に…
③ https://akizukidenshi.com/goodsaffix/rda5807.pdf

## 準備
何がともあれ以下の品を揃えてみた。（秋月電子の回し者ではないですよ）
|品名  |価格  |購入先|
|---|--:|---|
|FMラジオモジュール RDA5807H  |300円 |秋月電子|
|raspberry pi pico w  |1,358円 |amazon|
|ブレッドボード用ダイナミックスピーカー |190円 |秋月電子|
|4.7μFコンデンサ |?円 |家にあったやつ|
|101セラミックコンデンサ（100pF） |?円 |家にあったやつ|
|ケーブル少々 |?円 |家にあったやつ|
|ピンヘッダ少々 |?円 |家にあったやつ|
|片面ユニバーサル基盤 |?円 |家にあったやつ|

## 作ってみよう
参考サイトとあまり役に立たないデータシートを元に以下の回路を構成。
![rda5807_radio_回路図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603328/2afa42c7-e678-7990-6e67-2263c35aeb0c.png)

## コードを組み立てよう
参考サイトをベースに以下のコードを作成。
pythonなのでThonnyとやらで書いて、raspbrry pi pico wに流し込む。

```main.py
import radio.py
```
```radio.py
import time
import machine

i2c=machine.I2C(0,sda=machine.Pin(4), scl=machine.Pin(5), freq=10000)
print(i2c.scan())

def radio_frequency(freq):
    freqB = 4 * (freq * 1000000 + 225000) / 32768
    i2c.writeto(0x60, bytearray([int(freqB) >> 8, int(freqB) & 0XFF, 0XB0, 0X32, 0X00]))
    print(freq)
radio_frequency(79.51)
```
## コードの解説
厄介なのがi2c通信で流すパラーメータがなんなのか全然情報が掴めなかったこと。
RDA5807Hで検索しても情報が少なすぎる。
調べていくうちにRDA5807≒TEA5767であると判明し、NXPのデータシートに辿り着いた。

### PLL値の計算
```
freqB = 4 * (freq * 1000000 + 225000) / 32768
```
PLLとは？詳しくはこちら
・https://ie.u-ryukyu.ac.jp/~wada/design05/spec_j.html

### i2cコマンド
```
i2c.writeto(①0x60, bytearray([②int(freqB) >> 8, ③int(freqB) & 0XFF, ④0XB0, ⑤0X32, ⑥0X00]))
```
#### ①0x60
参考サイト①の通り、「TEA5767 書き込み時の IC2 アドレスは 0x60」とあるのでそのまま流用。回路構成後、試しにi2c.scanするとシェルに90(DEC)が返ってきたのでこれをHEXに変換すると60、ドンピシャ正解。
#### ②int(freqB) >> 8
計算したPLL値 freqB の上位8ビットだけ取り出す

#### ③int(freqB) & 0XFF
計算したPLL値 freqB の下位8ビットだけ取り出す

#### ④0XB0
参考サイト②のテーブル10を参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603328/9935a4c7-4da2-12be-981b-44fa5f7b203b.png)

#### ⑤0X32
参考サイト②のテーブル13を参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603328/8b477b17-8630-fad2-500d-e734435805f0.png)

#### ⑥0X00
参考サイト②のテーブル15を参照
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603328/b59e7f5f-6e73-05d7-9049-08d0fe57eb52.png)

## 与太話
何故79.5ではなく79.51なのか？
PLL回路の精度が悪いのか希望周波数ピッタリでは完璧なチューニングにはならない模様。
Preview版のAndroidStudioをいち早くDLする

これもしかしたら常識なのかもしれないのですが..個人的に少しハマったので書いておきます。

今朝Canary版のKoalaが出たのでウキウキでPreview版のDLページに行ったのですが、

https://twitter.com/androidstudio/status/1771250494884741489

DLページに行くとなぜかKoalaが出てこない
![スクリーンショット 2024-03-23 23.24.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145704/680d1a3d-98fe-b26f-74c5-04bf410e200a.png)

結果的に言語設定を英語にすると出てきました

![スクリーンショット 2024-03-23 23.27.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/145704/1424843a-e11e-2b45-6b7b-89017420b05d.png)

何らかの不具合なのか、意図的に英語圏以外ではまだ出さないようにしているのかはわからないのですが、「仮にそうだとしてもいち早く使ってみたい！」という方もいるかもしれないので一応記事にしておきます（ちなみに今のところ手元では問題なくインストールできてるように見えます）

どなたかのお役に立てれば幸いです。
AtCoder Unit Test が新しくなりました！

AtCoder の問題ページからユニットテストを生成するブラウザ拡張機能 "AtCoder Unit Test" を大幅リニューアル！便利な新機能をいろいろ実装しました！

* **テストコードのテンプレートが編集できるようになりました。**
* **テストコードの生成方法が変更になりました。**
* Go, Ruby のテストコードを生成できるようになりました。
* (Python, Ruby) テストコードを含んだまま提出できるようになりました。 ([例](https://atcoder.jp/contests/abc341/submissions/51385551))
* (Java, Kotlin) テストライブラリが JUnit5 に変更になりました。

ダウンロードは ↓ から。ぜひご利用ください！！！
  
* [AtCoder Unit Test - Chrome ウェブストア](https://chromewebstore.google.com/detail/atcoder-unit-test/lmahhninbclefepjbcdfbcjnancipfmi?hl=ja&authuser=0)
* [AtCoder Unit Test – 🦊 Firefox (ja) 向け拡張機能を入手](https://addons.mozilla.org/ja/firefox/addon/ac-unit-test/) 

# テンプレートが編集できるようになりました。

いままでは、こちらで用意したテンプレートでテストコードを生成していました。

しかし、タブ幅を変更するなどのカスタマイズがしたいという需要があることがわかりましたので、設定ページで自由にテンプレートを編集できるようにしました。
特に、Python の場合は後述するようにテストコードを含んだまま提出できますので、よく使うオリジナルの関数を入れてておくと便利です！

![AtCoder Unit Test](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205989/784f365b-494b-8965-5107-399efe8db56a.png)


また、これにより C++ などのデフォルトのテンプレートにない言語でも対応できるようになりました。

# テストコードの生成方法が変更になりました。

これだけでテストコードが生成できます！

1. AtCoder の問題ページを開く
1. 拡張機能の :white_check_mark: をクリック

また、このときに表示されるポップアップメニューから、設定画面を開けるようになりました。
![使い方](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/205989/13e7d4e9-de06-cc67-cde7-fe05bfbc8720.png)

# (Python, Ruby) テストコードを含んだまま提出できるようになりました。

テストコードを含んで提出しているケースが見受けられたので、いっそのこと**そのまま提出しても AC するように Python, Ruby のテンプレートを変更しました。**
ローカルでテストを実行するのは、これまで通り `python3 Main.py` で OK です。[^python]

[^python]: 当初は `python3 -m unittest Main.py` だったのですが、このやり方だとわからないという意見が多数ありましたので、v3.1.0 から `python3 Main.py` でも動かせるように変更しました。

ちなみに、Ptyhon では `ATCODER` という環境変数があるかどうかで挙動（テストを動かすか解答するか）を切り替えています。

```python
if __name__ == "__main__":
    if "ATCODER" in os.environ:
        resolve()
    else:
        unittest.main(verbosity=2)
```

# ソースコード


ご意見やご要望はこの記事のコメント、または GitHub の Issues にどうぞ。
もちろん Pull Request も大歓迎です！
[YujiSoftware/ac-unit-test - GitHub](https://github.com/YujiSoftware/ac-unit-test)


ぜひご利用ください！

* [AtCoder Unit Test - Chrome ウェブストア](https://chromewebstore.google.com/detail/atcoder-unit-test/lmahhninbclefepjbcdfbcjnancipfmi?hl=ja&authuser=0)
* [AtCoder Unit Test – 🦊 Firefox (ja) 向け拡張機能を入手](https://addons.mozilla.org/ja/firefox/addon/ac-unit-test/)
SAP BTP Free TrialのKyma Runtimeでアプリケーションを構築してみた

今回は、こちらのTutorialを参考に、Kyma Runtimeでアプリケーションの構築にトライしたいと思います。

https://developers.sap.com/mission.cp-kyma-build-app.html

SAP BTPのTrial環境が準備できてない場合は、こちらの記事を参考にSAP BTP Trialアカウントを作成してください。

https://qiita.com/Nel_SAP_Basis/items/1f6c91be2807c1984f86

## Kymaの有効化

SAP BTP CockpitのOverviewから、"Enable Kyma"をクリックします。
![スクリーンショット 2024-03-23 22.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/f25a2ae1-704f-73a2-fe8e-8cbc03e1d808.png)

Enable Kymaの画面がポップアップされますので、そのままCreateボタンを押します。
![スクリーンショット 2024-03-23 22.38.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/ef7f6f22-54a7-058b-67d8-40719991cef7.png)

Kyma Environmentの作成が開始しますので、10〜15分程待ちます。
![スクリーンショット 2024-03-23 22.41.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/ca5cde75-d571-cfe3-7861-37d0a7a176e2.png)

Kyma Environmentの作成が完了しましたら、"Link to Dashboard"をクリックします。
![スクリーンショット 2024-03-23 22.59.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/a6b28131-7fdb-fdb3-3c8b-4928135a5ee7.png)

サインインの画面が表示されますので、メールまたはユーザ名とパスワードを入力して、続行ボタンを押します。
![スクリーンショット 2024-03-23 23.01.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/39c4670e-4134-2df8-7152-019392fd0544.png)

Kymaの画面が開きました。
![スクリーンショット 2024-03-23 23.03.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1181562/8b136631-e34c-a3da-1062-748a4bda272e.png)

## Kyma runtimeでRedisを使用してデータを保存および取得する

続きは作成中ですので、お待ちください。
読書メモ： 理科系の作文技術 木下是雄著

木下是雄『理科系作文技術』で参考になった箇所を抜き出します。
(傾斜部分およびページ番号は筆者が追加　)


https://amzn.asia/d/i5JcMM8

### 1. 序章

> それ *(仕事の文書の特徴)* は, 読者につたえるべき内容が事実(状況を含む)と(意見)にかぎられていて, 心情的要素をふくまないことである.
P.5



> 私の考えでは, 以上のような性格をもった理科系の仕事の文書を書くときの心得は
(a) 主題について述べるべき事実と意見を十分に精選し、
(b) それらを, 事実と意見とを峻別しながら, 順序よく, 明快・簡潔に記述する
ことであると要約できる.
P.6


> これら *(仕事の文書の役割)* は自明のことかもしれないが, 初心の執筆者にとっては, 自分の書こうとする文書の役割を確認することが第一の前提である。これは, もし確信がなければ先輩に尋ねて確かめねばならない大切なことなのだ. 多少は書きなれた人も, 筆をとる前に, また書き上げたものを読みかえす前に, いったい読者はこの文書に何を期待しているはずかと, 一瞬, 反省してみることを勧める.
P.14

### 2. 準備作業(立案)

> 主題をはっきりきめたら, 次に, 自分は何を目標としてその文書を書くのか, そこで何を主張しようとするのかを熟考して, それを一つの文にまとめて書いてみること勧める. そういう文を**目標規定文**ということにしよう.
P.22

### 4. パラグラフ

> パラグラフは, 上の例にみられるように内容的に連結されたいくつかの文の集まりで, 全体として, ある一つのトピック(小主題)についてある一つのこと(考え)を言う(記述する, 明言する, 主張する)ものである. 
P.22

> パラグラフには, そこで何について何を言おうとするのかを一口に, 概論的に述べた文がふくまれるのが通例である. これを**トピック・センテンス**という.
P.62

### 5. 文の構造と文章の流れ

> 読者に逆茂木の抵抗を感じさせないためには, 次のような心得が必要であろう.
(a') 一つの文の中には二つ以上の長い前置修飾節は書きこまない.
(b') 修飾節の中のことばには修飾節をつけない.
(c') 文または説は, なるたけ前とのつながりを浮き立たせるようなことばで書きはじめる.
P.81


### 7. 事実と意見

> ここでは, レトリックの書物の常道にしたがって
(a) 自然に起こる事象(某日某地における落雷)や自然法則(慣性の法則);過去に起こった,人間の関与した事件(某年某地における某氏の出生)などの記述で,
(b) 然るべきテストや調査によって真偽(それが事実であるか否か)を客観的に確認できるもの
を事実の記述と定義しておこう.
P.104

> <意見>は幅のひろい概念で, その中には次のようなものが含まれている.
**推論**(inference) ある前提にもとづく推理の結論, または中間的な結論.
        例：彼は(汗をかいているから)暑いにちがいない.
**判断**(judgement) ものごとのあり方, 内容, 価値などを見きわめてまとめた考え.
        例：彼女はすぐれた実験家であった.
**意見**(option) 上記の意味での推論や判断;あるいは一般に自分なりに考え, あるいは感じて到達した結論の総称.
        例：リンを含む洗剤の使用は禁止すべきである.


> **事実の記述**だけを取り出して考えれば, 必要な注意は次の三つに尽きる.
(a) その事実に関してその文書のなかで書く必要があるのは何々かを十分に吟味せよ.
(b) それを, ぼかした表現に逃げずに, できるだけ明確に書け.
(c) 事実を記述する文はできるだけ名詞と動詞で書き, 主観に依存する修飾語を混入させるな.
P.107

> 文中に「便利な」とか「すぐれた」とかいう修飾語(句)がはいれば意見が混入することになる. これは事実の記述の客観性をスポイルする.
P.108


### 8. わかりやすく簡潔な表現

> (a) まず,　書きたいことを一つ一つ短い文にまとめる.
(b) それらを論理的にきちっとつないでいく(つなぎのことばに注意!).
ここで<つなぐ>というのは必ずしも<つないで一つの文にする>意味ではない. 短い独立の文を, 相互の関係がはっきりわかるように整然と並べることができれば, むしろそのほうがいいのである.
    以上の過程を通じて, どの文を書くときにも
(c) いつでも「その文のなかでは何が主語か」をはっきり意識して書くことが必要だ.
ABC346をPythonで（A～E）

ユニークビジョンプログラミングコンテスト2024 春（AtCoder Beginner Contest 346）の解答等のまとめ

https://atcoder.jp/contests/abc346

# A問題
問題文通りにfor文ループさせる
```python:A
input()
a = list(map(int, input().split()))

print(*[a_i * a_j for a_i, a_j in zip(a, a[1:])])
```
# B問題
計算して求めるともできるが、可能性があるぐらいだけの数Sを連結させて$w+b$の幅を確認すればいい
```python:B
s = "wbwbwwbwbwbw"

w, b = map(int, input().split())

s = s * (w // 7 + 2)

for i in range(len(s) - w - b):
    t = s[i:i + w + b]
    if t.count("w") == w and t.count("b") == b:
        exit(print("Yes"))

print("No")
```
# C問題
もし$A$の中に$K$以下がなければ答えは$k \times (k+1) \div 2$
よって重複に気を付けて上の値から引き算すればいい
```python:C
n, k = map(int, input().split())

a = set(map(int, input().split()))

ans = k * (k + 1) // 2
for a_i in list(a):
    if 1 <= a_i <= k:
        ans -= a_i

print(ans)
```
# D問題
DはDPのD
$dp[i][j][k] = j$番目までで数字が$k$で同じものが$i$個あるときの最小コスト
とすればいい
```python:D
n = int(input())
s = input()
c = list(map(int, input().split()))

INF = float("inf")
dp = [[[INF, INF] for _ in range(n)] for _ in range(2)]
dp[0][0][int(s[0])] = 0
dp[0][0][int(s[0]) ^ 1] = c[0]

for i in range(1, n):
    for A in range(4):
        a, b = A // 2, A % 2
        if a == b:
            dp[1][i][a] = min(dp[1][i][a], dp[0][i - 1][b] + c[i] * (int(s[i]) != a))
        else:
            dp[0][i][a] = min(dp[0][i][a], dp[0][i - 1][b] + c[i] * (int(s[i]) != a))
            dp[1][i][a] = min(dp[1][i][a], dp[1][i - 1][b] + c[i] * (int(s[i]) != a))

print(min(dp[1][-1]))
```
# E問題
$i$番目で$a_i$行に$x_i$を塗るとしてその色が残るのは、
- $a_i$行目がそれ以降塗られない
- 各列のうち1列以上塗られない行がある
の両方を満足した時

よって、逆から塗った情報を調べるとうまくいく
```python:E
h, w, m = map(int, input().split())
query = [list(map(int, input().split())) for _ in range(m)]

ans = dict()
height = {i for i in range(h)}
width = {i for i in range(w)}

for t, a, x in reversed(query):
    a -= 1
    if t == 1:
        if a in height:
            if x not in ans:
                ans[x] = 0
            ans[x] += len(width)
            height.discard(a)
    else:
        if a in width:
            if x not in ans:
                ans[x] = 0
            ans[x] += len(height)
            width.discard(a)

    if len(height) == 0 or len(width) == 0:
        break

if len(height) * len(width) > 0:
    if 0 not in ans:
        ans[0] = 0
    ans[0] += len(height) * len(width)

print(len(ans))
for key in sorted(ans.keys()):
    print(key, ans[key])
```
MySQLでユーザーの権限設定SQL

# やり方

```sql:
GRANT 権限の種類 ON スキーマー名.テーブル名 TO 'ユーザー名'@'ホスト名'
```

# 既に別の権限が付与されている場合

例えばSELECT権限 **のみ** 付与されている場合、下記SQLを流すと
ユーザーにはSELECTとINSERTの両方の権限が与えられます。

```sql:
GRANT INSERT ON スキーマー名.テーブル名 TO 'ユーザー名'@'ホスト名'
```

**上書きではなく、追記** です。


# 参考サイトさん

https://qiita.com/akko_merry/items/fffbf5e0a5534e73a154

# バージョン

Microsoft Windows [Version 10.0.19045.4170]
MySQL 5.7.38-log
イギリス政府デザインシステム(GOV.UK Design System)の設計思想を読み解く

# この記事は何？

イギリス政府デザインシステム（以下、 GOV.UK DS）に興味を持って読んでみることにしたので、気が向いたときにゆるゆる内容を書いてみようと思いました。
今回は[Government Design Principles]について考えることにします。

# Government Design Principle とは

日本政府がよく使う言葉に訳すと「デザインの考え方」でしょうか。
2012年に初版が作られた後、2019年に微修正が入ったのみでほぼ原案のまま運用されています。

10個のシンプルな原則にまとめられています。

# 10の原則

## 1. Start with user needs 

「サービスデザインはユーザーのニーズを特定するところから始まる」とし、「ユーザーのニーズを知らなければ、正しいものを作ることはできない」と断じています。
**リサーチを行い**、**データ分析をおこない**、**ユーザーと対話する必要**があるとし、憶測をせず、ユーザーに寄り添い、ユーザーが求めるものは本当に必要としているものとは限らないことに注意すべきだとしています。

## 2. Do less

政府は政府しかできないことのみをすべきとの立場を表明した上で、政府は使えるものを作ったらそれを**再利用、再頒布可能なものにすべき**で、車輪の再発明を防ぐべき」だとしています。後段では、具体例として他社が利用できるプラットフォームの構築やAPI、それに政府外の成果物へのリンクを行うべきとしています。

## 3. Design with Data

「サービスがどのように使われているかをみることで現実世界の様子がわかる」とし、**推測ではなくデータに基づいた意思決定**をすべきとしています。サービスをリリースしたあとにはプロトタイピングとユーザーを巻き込んだテストを経た**イテレーション**を行っていくべきとしています。

## 4. Do the hard work to make it simple

「シンプルに見せること」は簡単だが、シンプルにするのは難しいとしながらも、それがやるべきことだとしています。「そんなもんだ」を答えにせず、**シンプルを追求すべき**だとしています。

## 5. Iterate. Then iterate again

良いサービスを作る最良の方法は「**小さくはじめて大胆にイテレーションする**」であるとし、MVPを素早くリリースしてユーザーにテストしてもらい、アルファとベータを経て本番環境に新機能をリリースし、フィードバックを通して役に立っていないと判断したものは削除すべきだとしています。

## 6. This is for everyone

アクセシビリティに配慮したデザインは優秀であるとして、政府が構築するものは**インクルーシブ**で、**legible**で あり、 **読み上げ可能(readable)** であるべきとしています。これはエレガンスよりも優先されるべきであるとしています。

## 7. Understand context

スクリーンではなく、**人間のためにデザイン**しているとして、**contextを考慮すべき**だとしています。例として、図書館にいるのか、電話を使っているのか、Facebookに慣れているのか、そもそもWebを使ったことがないのではないか…を挙げています。

## 8. Build digital services, not websites

サービスは「人々が何かをするのを助けるもの」と定義づけ、政府デザインチームの仕事はユーザーのニーズを明らかにし、それに見合うサービスを構築することと位置づけています。その手段としてWebサイトの作成であることは認める一方で、 **Webサイトを作ることが存在意義ではない** としています。そのために、サービスの全側面を考慮して、ユーザーのニーズに合致したものを作るべきだとしています。

## 9. Be consistent, not uniform

**可能な限り同じ言い回しとデザインパターン** を使い、人々がサービスに慣れるようにすべきとしています。
初期にはこの原則が適用できないことを認めつつも、パターンを決めたらそのことを共有して、なぜそうしたかを説明すべきとしています。ただ、それに固執することなく、より良い方法を見つけたりユーザーのニーズが変化したときには対応すべきとしています。

## 10. Make things open: it makes things better

自分たちがしていることを可能な限り同僚やユーザー、そして世界中に共有すべきとしています。コードやデザインのみならず、アイデア、意図、そして失敗までも共有し、 **見る目が増えるほどサービスはよくなる** としています。

# 考察

デザインシステムについての原則について宣言した文章であるにもかかわらず、サービスとはなにか、イテレーションはかくあるべきだ、など出発点から現実の運用の指針まで幅広く、しかしコンパクトに方向性を纏めている点が極めて興味深いです。
加えて、初版が2012年であることを踏まえると、相当に時代の先を読んだドキュメントと言えるのではないでしょうか。

# 参考資料

* https://www.gov.uk/guidance/government-design-principles

# 備考

* この記事はOpen Government License (https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/) に基づき、資料の出どころを明示したうえで作成しています。
MySQLでユーザーの権限確認SQL

# やり方

```sql:
SHOW GRANTS FOR 'ユーザー名';
```

# その名前のユーザーが存在しない場合

エラーコード1141で例外。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/0033c2aa-ca96-b0a3-5ba7-563f58d88ab6.png)

# 参考サイトさん

https://www.javadrive.jp/mysql/user/index11.html

# バージョン

Microsoft Windows [Version 10.0.19045.4170]
MySQL 5.7.38-log
Burp Suiteの使い方

## はじめに
Burp Suiteは主にペネトレーションテストなどで利用される
ローカルプロキシツールです。
PCとWebサーバの通信内容を確認し
パラメータを修正、送信などができます。

以下で検証
Burp Suite Community Edition 2024.1.1.6
Windows 10

## インストール方法
1.以下のサイトにアクセス
https://portswigger.net/burp/communitydownload

2. ダウンロードクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/80a0557f-1c59-47d4-c81c-78795b447c23.png)

３．インストーラを実行
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/f954ac81-cce7-a5c7-c6f8-86ba90bfb54b.png)

４．nextクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/abbbcbb5-cbb0-d8c7-6d0f-d8aaea38c714.png)

５．nextクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/de5d9190-ac11-6740-284b-2d8d3c4e9687.png)

７．nextクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/b285f76a-a964-bd97-e498-3df5eddf0505.png)

８．Finishクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/8e4cc301-f168-a007-6a06-6e50fabaec81.png)



## 起動方法
１．プログラムからBurp Suite Community Editionをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/466e2b28-59f3-b8af-2548-df229464228f.png)

２．初回起動時はacceptをクリック
　キャプチャ取り忘れた

３．nextクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/ae62fd57-68b9-b5d4-0320-be6d9d36a696.png)

４．Start Burpクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/f9384c8e-fd68-aeed-77c4-b0c9aebbc1f9.png)

## 利用例

１．Targetクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/4b15004e-16d3-43ef-cffa-756daff56480.png)

２．Open Browserクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/f99a6ed6-e793-78a8-2548-961cb49767c0.png)

専用ブラウザが起動します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/af1d86e1-92b0-71f2-79e5-8625a46ac40e.png)

３．調査対象を開く
ここではgoogleとする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/e54758de-339c-141e-0377-164560bf18de.png)

４．Tagetのタブでは通信内容が確認できる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/5cc5d901-03ea-3e60-432e-5a2d33920bdb.png)

５．Proxyタブの「Intercept is on」にすると送信前に内容を確認、修正してポストできます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1308027/77380a43-3cbc-8370-9c83-3716983f52bf.png)
Streamlitのcolumn_configにあるselectboxを使う

# はじめに
現在、とある件でGUIを使った機械学習ツールの開発をしています。
その過程で初めてStreamlitのcolumn_configを触ったので、その中のselectboxを実際のコードを交えつつここに書こうかと思います。

# そもそもcolumn_configとは？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/18b902f9-42e6-825b-543f-5d0e990dc7de.png)
(※ [Streamlitのドキュメント](https://docs.streamlit.io/library/api-reference/data/st.column_config)から引用)

データフレームの中にインプット系のウィジットを入れたり、画像やグラフなども挿入できる便利な機能です。
公式のドキュメントにも使用例が豊富なので実際に見に行くと想像しやすいと思います。

# 今回の使用例
今回は、ユーザが自由に入力したデータを機械学習モデルに挿入しPredictするという機能で使いました。

[ユーザが入力したデータ]　→　[学習済みモデル] → [予測結果]

これの[ユーザが入力したデータ]という部分で入力を受け付けたということです。

実際のUIがこちら↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/53524097-17e9-20f9-e2dd-b125c47580d5.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456646/e919798b-4eea-4e30-144a-34ff67de3eb2.png)

こんな感じで直接データフレームに対して入力できます。

# 実装
初見だと結構複雑でどこに何を入力すべきかわからなくなりますが、data_editorのウィジットの書き方を基本に考えました。

```python
# data_editorの実装
df = pd.DataFrame("ポルトガルの数学成績データ") # 今回使っていたデータ
edited_df = st.data_editor(df)
```
```python
# column_configの実装
df = pd.DataFrame("ポルトガルの数学成績データ") # 今回使っていたデータ
edited_data = st.data_editor(
        df,
        column_config={
            "学校": st.column_config.SelectboxColumn(
                "学校",
                help="The category of school",
                width="medium",
                options=["GP", "MS"],
                required=True,
            ),
            # .... 略
            "恋愛関係": st.column_config.SelectboxColumn(
                "恋愛関係",
                help="Romantic relationship",
                width="medium",
                options=["no", "yes"],
                required=True,
            ),
        },
        hide_index=True,
    )
```

ほんとは辞書型などで一通り定義してからforで回すなどすればスマートな実装ができそうですね。

# 少し工夫した点
アプリでは入力時だとカテゴリ名で、そうじゃないときは数字で入力する必要がありました。
そこで以下の辞書と関数を定義してeditする前後で変換を挟みました。
```python
mat_data_label_name = {
    "学校": {
        "0": "GP",
        "1": "MS"
    },
    "性別": {
        "0": "F",
        "1": "M"
    },
    # ... 略
}

def categori_to_name_by_matdata(df):
    for col in df.columns:
        if col in mat_data_label_name:
            df[col] = df[col].astype(str)
            df[col] = df[col].replace(mat_data_label_name[col])
    return df

def name_to_categori_by_matdata(df):
    for col in df.columns:
        if col in mat_data_label_name:
            df[col] = df[col].astype(str)
            df[col] = df[col].replace({v: k for k, v in mat_data_label_name[col].items()})
    return df.astype(np.int64)
```
こうすることで、学習済みモデルには数字が入力され、ユーザはカテゴリ名で編集できるので便利という感じにできます。

# おわりに
column_configはいろいろと種類も多く、便利そうなので今後とも使っていきたいですね。
請負・派遣・準委任

# はじめに
はじめに、応用情報技術者試験の学習を行なっている最中に請負契約、派遣契約、準委任契約の違いをすぐに忘れてしまうので一度きちんと整理する。

# 請負契約
依頼者に対して請負者が仕事の完成を約束し、成果物に対して依頼者が報酬を払う契約形態のこと
→成果物に対して責任を持つ

:::note warn
受注者側に対して発注者が指示することはできない。
:::

# 派遣契約
派遣契約とは、派遣会社から発注先の企業へ労働者を派遣し、発注者の指示のもとで業務を遂行する契約形態のこと


# 準委任契約
一部の作業を手伝う名目で業務を遂行する契約形態のこと
→業務における成果物の完成責任は負わず、作業報告書を委任者（自社の責任者）に収める

# 参考サイト
https://tech-camp.in/note/careerchange/40941/
自宅LinuxサーバにKVM + QEMUをインストールしてみた

# 概要

最近VMware ESXiの無償版の提供が終了してしまったので、別の選択肢としてKVMを利用してみました。初めて触るので不慣れですが、調べつつVM立てるところまでは行けました。

https://kb.vmware.com/s/article/96168?lang=en_US

# KVMインストール

https://www.redhat.com/ja/topics/virtualization/what-is-KVM
> KVM (Kernel-based Virtual Machine：カーネルベースの仮想マシン) は、Linux® に組み込まれたオープンソースの仮想化テクノロジーです。KVM を使用すると、Linux をハイパーバイザーとして機能させることができます。

KVMとは、Linux組み込みのハイパーバイザのことです。KVM自身はエミュレーションを行わずに後述のQEMUが仮想マシンのエミュレーションを行ってKVMは仮想ハードウェアの処理と物理ハードウェアの仲介役を行っています。

ロード済のカーネルモジュールの一覧で確認してみます。KVMはLinuxに組み込まれているので、インストールは不要です。
```
lsmod | grep kvm
```
```
kvm_intel             368640  0
kvm                  1032192  1 kvm_intel
```

# QEMUインストール

仮想化マシンのエミュレータのことで、エミュレーションの対象はCPU,メモリ,I/Oデバイスに大別されます。


```
apt install qemu-kvm
```
```
vi /etc/libvirt/qemu.conf
```
```
user = "root"
group = "root"
dynamic_ownership = 1
```
:::note warn
rootで実行してしまっていますが、あまり良くないかもです。一般ユーザで実行するべきです。
:::

# libvirtインストール

libvirtは仮想化アプリケーションやハイパーバイザを操作するための抽象化レイヤーを提供しているソフトウェア郡です。

```
apt install virt-top libguestfs-tools virt-manager libvirt-daemon-system virtinst libvirt-clients bridge-utils
```

```
vi /etc/libvirt/libvirtd.conf 

auth_unix_ro = "none"
auth_unix_rw = "none"
unix_sock_group = "libvirt"
unix_sock_ro_perms = "0777"
unix_sock_rw_perms = "0770"
```

```
systemctl status libvirtd
systemctl enable libvirtd
systemctl start libvirtd
systemctl status libvirtd
usermod -aG kvm $USER
usermod -aG libvirt $USER
```
ディレクトリ作成
```
mkdir -p /home/shared/images
```

# cockpit

GUIの管理ツールとして`Virtual Machine Manager（virt-manager）`も存在しますが、redhatとしてはcockpitを推奨しているようなのでcockpitを使用します。

```
apt install cockpit
. /etc/os-release
sudo apt install -t ${VERSION_CODENAME}-backports cockpit
```
```
systemctl status cockpit
systemctl start cockpit
systemctl status cockpit
```

以下アクセス
https://{IP}:9090/

仮想マシン作成のプラグインをインストールする。
```
apt install cockpit-machines
```
cockpitのGUI

![スクリーンショット 2024-03-23 22.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2620245/8057cd96-20d3-eca9-5a11-e2ad7fa58d4e.png)


# ユーザーグループ修正

```
groups $(whoami)

usermod -aG kvm $(whoami)
usermod -aG libvirt $(whoami)
usermod -aG libvirtd $(whoami)

groups $(whoami)
```


# VM用のディレクトリ作成

```
# ディレクトリ作成
mkdir -p /home/shared/libvirt/images/
mkdir -p /home/shared/libvirt/images/isos/

# 権限とかグループ追加
groupadd shared
usermod --append --groups shared $(whoami)
chown -R root:shared /home/shared/
chmod -R o-rwx /home/shared/
```


# VM操作コマンド

ここはメモ感覚です。

VM一覧
```
virsh list
```

VMディスク一覧
```
virsh domblklist [VM名前]
```

VM停止
```
virsh shutdown [VM名前]
```

ネットワーク設定
```
virsh net-list
```

VMのIP確認
```
virsh net-dhcp-leases default
```

pool確認
```
virsh pool-list
```

pool削除
```
virsh pool-destroy [pool名前]
```
PHPの配列で和集合，差集合，積集合

## はじめに
SQLでUNIONやEXCEPT，INTERSECTを使った際，PHPで和集合とかあるのか気になって調べたメモ

PHPでは、配列の和集合や差集合を直接扱う組み込み関数は提供されていませんが、array_mergeやarray_diff関数を使用してこれらの操作を行うことができます．

## 和集合
```php
$array1 = ['apple', 'banana', 'cherry'];
$array2 = ['banana', 'cherry', 'date'];

// 和集合の計算
$union = array_merge($array1, $array2);

// 重複を削除するためにarray_uniqueを使用
$union = array_unique($union);

print_r($union);

Array
(
    [0] => apple
    [1] => banana
    [2] => cherry
    [5] => date
)

```


## 差集合
```php
$array1 = ['apple', 'banana', 'cherry'];
$array2 = ['banana', 'cherry', 'date'];

// 差集合の計算
$difference = array_diff($array1, $array2);

print_r($difference);

Array
(
    [0] => apple
)
```

## 積集合
```php
$array1 = ['apple', 'banana', 'cherry'];
$array2 = ['banana', 'cherry', 'date'];

// 積集合の計算
$intersection = array_intersect($array1, $array2);

print_r($intersection);

Array
(
    [1] => banana
    [2] => cherry
)
```

## 終わり
参考にした記事
https://qiita.com/tadsan/items/3c61c8e5db24862c86c8
Flask-SQLAlchemyのSELECT/INSERT/UPDATE操作まとめ

### 概要
Flask-SQLAlchemyを使用してデータベースに対しての基本操作のまとめ記事

### テーブル定義からテーブル作成
サンプルコードの流儀が若干違うので
```py
app = Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///' + os.path.join(os.getcwd(), 'settings', 'payments_db.db')
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False

db = SQLAlchemy(app)

class User(db.Model):
    """ユーザテーブル定義
    Args:
        db (object): DB
    """
    id = db.Column(db.Integer, primary_key=True)
    username = db.Column(db.String(80), unique=True, nullable=False)
    email = db.Column(db.String(120), unique=True, nullable=False)
    
@app.route('/')
def main():
    # テーブル作成
    with app.app_context():
        db.create_all()
        
    return 'Hello', 200    
```

### SELECT
```py
# クエリ
user = User.query.get(user_id)

# 複数の場合（filter)
users_to_update = User.query.filter(User.username == username_to_find, User.email == email_to_find).all()

# fetchall
# Viewに対してクエリを実行
results = MyView.query.all()

# fetchone
# Viewに対してクエリを実行して最初の結果を取得
result = MyView.query.first()

# テーブルに対して指定したカラムのみを取得してクエリを実行
results = User.query.with_entities(User.id, User.username).all()

```

### INSERT
```py
pay = Payments(user_id=2, amount=100, item='ジュース')
db.session.add(pay)
db.session.commit()

# JSON追加の場合 ->POST使用
@app.route('/add_user', methods=['POST'])
def add_user():
    # JSONデータをリクエストから取得
    data = request.get_json()

    # JSONデータからモデルのインスタンスを作成
    user = User(username=data['username'], email=data['email'])

    # モデルのインスタンスをデータベースに追加してコミット
    db.session.add(user)
    db.session.commit()

    return 'User added successfully', 201
```
### UPDATE　→PUT使用
```py
@app.route('/update_user/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    # 更新したいデータを取得
    user = User.query.get(user_id)
    if not user:
        return 'User not found', 404

    # リクエストデータから更新内容を取得
    data = request.json
    username = data.get('username')
    email = data.get('email')

    # 更新内容があれば、データを更新
    if username:
        user.username = username
    if email:
        user.email = email

    # データベースにコミット
    db.session.commit()

    return 'User updated successfully', 200
```

### VIEWについて
VIEWは作れないが、sqlalchemyならできる
```py
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import text

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///example.db'
db = SQLAlchemy(app)

class MyView(db.Model):
    __tablename__ = 'my_view'
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(80))

# Viewを作成するSQL文
create_view_sql = """
CREATE VIEW my_view AS
SELECT id, name FROM my_table WHERE condition;
"""

# Viewを削除するSQL文
drop_view_sql = """
DROP VIEW IF EXISTS my_view;
"""

# Viewの作成
db.engine.execute(text(drop_view_sql))  # 既存のViewがあれば削除
db.engine.execute(text(create_view_sql))  # 新しいViewを作成

if __name__ == '__main__':
    app.run(debug=True)
```
物削除はなかなかしないので、割愛
ActionController::Redirecting::UnsafeRedirectErrorが出た時の対処法

## はじめに
**自己紹介**
未経験からWEB系エンジニアへの転職を目指している者です。現在はRuby on Railsを学習中です。

**この記事を書いたきっかけ**
現在、プログラミング学習コミュニティでモブプロの取り組みに参加しており、Railsを使って簡易的なURL短縮サービスを実装しています。
その中で、表題のエラーに遭遇したので備忘録として対処法をまとめました。

## 動作環境
- ruby 3.2.2
- rails 7.1.3

## エラーの発生箇所
**UrlsControllerの概要**
- params[:digest]で短縮urlで受け取る
- Urlsテーブルを検索して短縮urlと紐づく、オリジナルurlを取得する
- オリジナルurlにリダイレクトさせる

**Urlsテーブル**
- オリジナルURLとそれに対応する短縮URLを管理し、作成日時と更新日時を追跡できる


```mermaid
erDiagram
    users {
        bigint id PK "ID"
        text original "オリジナルurl"
        string digest "短縮url"
        datetime created_at "作成日時"
        datetime updated_at "更新日時"
    }
```

**コード**

```:urls_controller
class UrlsController < ApplicationController
  def jump
    url = Url.find_by(digest: params[:digest])&.original
    if url.nil?
      render json: {}, status: 404
    else
      redirect_to url, status: 301
    end 
  end
```

**エラー**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3625095/43179346-a701-b86e-1d76-97e3bd39bd9a.png)

`redirect_to url, status: 301`の行でエラーが発生しました。

## エラーの調査
`ActionController::Redirecting::UnsafeRedirectError`についてRailsガイドで調べてみると以下のことがわかりました。
[:page_facing_up:Railsガイド | config.action_controller](https://railsguides.jp/configuring.html#config-action-controller-raise-on-open-redirects)

- Action Controllerの構成を設定するための構成オプションに`config.action_controller`があり、その設定項目の一つとして`raise_on_open_redirects`がある
- `raise_on_open_redirects`のデフォルトの設定では、外部ホストを含むURLが`redirect_to`メソッドに渡されると`ActionController::Redirecting::UnsafeRedirectError`が発生する

今回の場合、短縮URLのリダイレクト先が外部ホストであるyahooのトップページとなっていたためエラーが発生したようです。

## エラーの対処方法
Railsガイドによると、外部ホストを含むURLの呼び出しを許可する場合は`redirect_to`メソッドの呼び出しに`allow_other_host: true`オプションを追加する必要があるとのことでした。
**修正後のコード**
```:urls_controller
class UrlsController < ApplicationController
  def jump
    url = Url.find_by(digest: params[:digest])&.original
    if url.nil?
      render json: {}, status: 404
    else
      # `allow_other_host: true`オプションを追加
      redirect_to url, allow_other_host: true, status: 301
    end 
  end
```
DownloadCompleteDBLogFile を用いて RDS からログをダウンロードする (Python)

こんにちは。インサイトテクノロジーの松尾です！

本投稿では DownloadCompleteDBLogFile を用いて RDS からログをダウンロードする方法を紹介します！

## はじめに

以前所属する会社のサイトで以下のような記事を書きました。

https://www.insight-tec.com/tech-blog/aws/20211216_ec2/

アクセスキーを明示的に指定せずに「ロールが設定された EC2 インスタンスで DownloadCompleteDBLogFile を用いて RDS からログをダウンロードする」ということを目的にして書きましたが、実はロールが設定されているEC2でなくても、`~/.aws/credentials` が設定されている環境であれば、ローカル環境でも動作します。

今回のQiitaへの投稿を機にgithubにもソースをあげておいたので是非ご活用ください。

https://github.com/takumats/download-rds-log-files

## 使い方

### 準備

gitからcloneしてきたあと以下の手順を行います。
※ちなみにpipでインストールしてるのは`boto3`と`requests`のみなので、デフォルトで使える場合には本手順は不要です。

```bash
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
```

### 実行

引数として対象のインスタンスIDを指定して実行します。

```bash
python3 download_logs.py <INSTANCE_ID>
```

実行例)

実行すると以下のように1ファイルずつダウンロードを行います。

```bash
python3 download_rds_log_files.py test-aumy-2-11-4-with-audit-log
audit/audit.log.0.2024-03-22-17-09.0
audit/audit.log.0.2024-03-22-17-10.0
audit/audit.log.0.2024-03-22-17-12.0
audit/audit.log.0.2024-03-22-17-30.0
audit/audit.log.0.2024-03-22-17-35.0
...
```

### おまけ：結合とソート

ここまでで実行できるのは個別のログファイルをダウンロードしただけなので、ファイルの結合とソートを必要に応じて行いましょう。

```bash
cat audit-audit.log.* > audit_log.txt
sort audit_log.txt > audit_log_sorted.txt
```

## おわりに

本投稿では、DownloadCompleteDBLogFile を用いて RDS からログをダウンロードする方法をご紹介しました。
ここで紹介した方法は、ロールが設定されいてるEC2でも動作しますし、`aws configure`で`credentials`が設定されているローカル環境でも動作します。`DownloadCompleteDBLogFile`はご存知のように`awscli`には含まれていないものなので利用するには何かしらのコード対応が必要になってきます。本投稿が何かの参考になればと思います。
航空宇宙エンジニアが普段使っているツール群

タスクを効率的に実行していくには、ツールを使うのが便利です
道具は人間の能力を拡張してくれます

# webアプリ
会社は野良サーバ禁止なので、ローカルでサーバを立ち上げて使っています

## jupyter notebook、jupyterlab
これが無いと、仕事にならないです

## fessとelasticsearch
windowsの検索がイマイチなので、これでファイル検索を行っています
これを使い始めると、ファイルサーバの汚さを実感できます

## Gitbucket
リポジトリ管理で使用
markdownをレンダリングしてもらう意味でも使っています

## タスク管理アプリ(自作)
いいものがなかったので、自作アプリを使用しています
スケジュールとタスクを一括で管理できるお気に入りの一品です


# 言語関係
- python
秀逸です。だいたい何でもできる。何でも繋がる
- SHELLスクリプト(windows,linux,mac)
なんやかんやで、よく使います
- javascript
web関係をやれば切っても切れない言語
- SQL
DBの操作で必須
- HTML
webアプリ作るなら、ある程度分かっていないと出来ないです
- C#
TeamCenterのSOAで使用。pythonと比較して難しい
- Google app script
ChatGPTが得意なので、助かります。
- VBA
昔はよく使っていましたが、python使うようになってから、めっきり使わなくなりました。

# デスクトップアプリ

## 便利ツール

- power toys
Mac使いがWindowsで作業する場合はコレが必須

## テキストエディタ
- VS code
これは秀逸、プログラムやmarkdownだけでなく、プラグインで色々使えて超便利です

## IDE
- Visual Studio
C#を使うときに使用。これも多機能なので、全部使いきれない

## CG関係
- blender
pythonも使えるのでmeshデータ見たりするのに使用する。多機能なので、とてもじゃないと全部使いきれない

## 3Dプリンタ
- simplify 3D
3Dプリンタのスライサです。感覚的につかえてGOODです

## CAD
- Creo parametric
商用ソフト、会社の標準ソフトなので使用
- FREECAD
pythonも使えるので、ソリッドデータの分析などで使用
- AutoCAD
2DCADです。前職で使用していましたが、もう使えないかも
- Autodesk Inventor
前職で使用していた3DCAD、これも、もう使えないかも

## CAE
- APEX
プリポストで使用。もう少し機能が欲しい
- MARC/MENTAT
熱構造解析で使用
- MSC Nastran
熱構造解析、固有値解析で使用
- HDF View
ポスト処理でデータを見るために使用
- paraview
ポスト処理で使用
- Altair Inspire
簡易的に解析したり、最適化したりするのに使用。ジオメトリ機能は秀逸
- その他
以下は適宜使用しているが、習熟度は低いです
    - Femap
    - Hyper mesh
    - Hyper view

## PLM
- TeamCenter
シーメンスに頑張ってほしい。。。
会社のバージョンが古いせいかもしれないので、バージョンアップに期待したい。

## MS office
会社のアプトプットは、当然これです。いろんなツールを使っても最終的な成果はこれに集約
- power point
- word
- excel
- outlook

## draw関係
- drawio
これで書くことが多いです。フローとか書くのが本当に便利
- tldraw
vscodeのextensionで使用。会社でサーバ公開できるのであれば、ホワイトボードアプリで公開したいところです

## 画像
- ペイント
なんやかんやで未だに使っているwindowsの標準アプリ
- Inkscape
ベクタ画像関係はこれです。有料系は買ってくれないです

## DB
- XAMPP
会社に許可されており、最も気軽にMySQL環境を構築できるので、使用しています
- HeidiSQL
主にDBの閲覧に使用しています

## コミュニケーションツール
- webex
- Teams
- Skype

## プロジェクト管理
- redmine
会社がサービスを提供しています。pythonから操作できるので有り難い
PowerShellを使ってBluetooth音声デバイスに接続

1つのBluetooth音声デバイスを複数の接続先に使い回すときに切り替えが面倒だったので、自動的に接続するスクリプトを作りました。
PowerShellを使ってペアリング済みBluetooth音声デバイスに接続し、再生デバイスをそのBTデバイスに指定することができます。

## 前提

* 7以降のWindows
    * 当然、Bluetoothが利用可能なマシンである必要がある
* あらかじめ目的のBluetoothの音声デバイスとペアリングを済ませておく

## 用意

### 必要ツールのインストール

* [Bluetooth Command Line Tools](https://bluetoothinstaller.com/bluetooth-command-line-tools)
    * こちらのサイトからインストール  
      https://bluetoothinstaller.com/bluetooth-command-line-tools
* [AudioDeviceCmdlets](https://github.com/frgnca/AudioDeviceCmdlets)
    * 管理者権限のPowerShellで以下のコマンドを実行してインストール  
      ```powershell
      Install-Module -Name AudioDeviceCmdlets
      ```

### 目的のデバイスの情報を調べる

* PowerShell上で `btdiscovery` コマンドを使って目的のデバイスのmacアドレスを調べる
* PowerShell上で `Get-AudioDevice -List` コマンドを使って目的のデバイスの名前を調べる

## スクリプト

以下のコマンドでペアリング済みBluetooth音声デバイスに接続して再生デバイスに設定できる。

```powershell
$MacAddress="XX:XX:XX:XX:XX:XX"
$DeviceName="調べたデバイス名"

btcom -b $MacAddress -r -s111e
btcom -b $MacAddress -c -s111e
(Get-AudioDevice -list | Where-Object Name -like ("$DeviceName*") | Set-AudioDevice)
```

## 参考リンク

* https://bluetoothinstaller.com/bluetooth-command-line-tools
* https://dmeechan.com/blog/pairing-bluetooth-powershell
* https://superuser.com/questions/1426949/scripting-connecting-disconnecting-a-paired-bluetooth-device
* https://qiita.com/M_Kagawa/items/38160ca6acd82ed77b4a
Vimにシソーラス(類義語)辞典を追加して補完させる

## はじめに
プログラミングをする上で、変数や関数の名前付けは非常に重要な作業です。適切な名前を付けることで、コードの可読性が高まり、保守性も向上します。しかしながら、多くの変数や関数を扱う際、名前が重複してしまうことがあります。そのようなときには、言い換えを検討したり、類義語や同義語を調べたりする必要があります。

**最強のテキストエディタVim**[^1]を使っている場合、プラグインをインストールすることなく、簡単な設定変更だけで類義語の補完機能を追加することができます。特に、母語ではない英語の類義語を補完できると、名前を考える時間を削減できて捗ります。本記事では、そのような簡単な類義語補完機能の設定方法をご紹介します。

[^1]: ネタです。ｻｰｾﾝ。テキストエディタは8年前に使っていたSublimeTextとVimとメモ帳しか１年以上の使用歴がありません。



## Vimに類義語(シソーラス[^2])辞典を追加する方法

[^2]: シソーラス (英: thesaurus) は単語の上位 / 下位関係、部分 / 全体関係、同義関係、類義関係などによって単語を分類し、体系づけた類語辞典・辞書。[Wikipedia - シソーラス](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%BD%E3%83%BC%E3%83%A9%E3%82%B9)

 `:help compl-thesaurus` または[vimdoc-ja/insert.html#compl-thesaurus](https://vim-jp.org/vimdoc-ja/insert.html#compl-thesaurus)に書いてあります[^3]。

[^3]: [vimdoc-ja/insert.html#compl-thesaurus](https://vim-jp.org/vimdoc-ja/insert.html#compl-thesaurus)

> 英単語リストはこのGitHub Issueに追加されている:
https://github.com/vim/vim/issues/629#issuecomment-443293282
thesaurus_pkg.zip を展開し、thesaurus.txt をどこかに配置する、例えば~/.vim/thesaurus/english.txt、そして 'thesaurus' オプションをこのファイル名{訳注: ファイルパス}にする。


上に書いてあることを実行するコマンドを書き下します。

```sh
# ~/.vim/thesaurusディレクトリを作成して移動
$ mkdir -p ~/.vim/thesaurus; cd $_
# 英語シソーラス辞典zipをダウンロード
$ curl -fsSLO https://github.com/vim/vim/files/2634525/thesaurus_pkg.zip
# 解凍してzipは削除
$ unzip thesaurus_pkg.zip && rm -f $_
# 名前を変更
$ mv thesaurus_pkg/thesaurus.txt english.txt
```

最後にVimでシソーラス辞典のパスをsetします。
毎回実行するのは大変なので、.vimrcに書いて起動時にシソーラス辞典を追加します。

```.vimrc
set thesaurus=~/.vim/thesaurus/english.txt
```


## 補完
インサートモード中に <kbd>C-X,C-T</kbd> です[^3][^4]。

> 例えば、'thesaurus' ファイルにこのような行があるとして: >
        angry furious mad enraged
カーソルが "ang" の後にあり、CTRL-X CTRL-Tを押すと "angry" が補完される。続けて補完すると "furious"、"mad"、...、と置き換えられる



[^4]: [Amazon - 実践Vim](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5Vim-%E6%80%9D%E8%80%83%E3%81%AE%E3%82%B9%E3%83%94%E3%83%BC%E3%83%89%E3%81%A7%E7%B7%A8%E9%9B%86%E3%81%97%E3%82%88%E3%81%86%EF%BC%81-%E3%82%A2%E3%82%B9%E3%82%AD%E3%83%BC%E6%9B%B8%E7%B1%8D-%EF%BC%A4%EF%BD%92%EF%BD%85%EF%BD%97-%EF%BC%AE%EF%BD%85%EF%BD%89%EF%BD%8C-ebook/dp/B00HWLJI3U/ref=sr_1_1?dib=eyJ2IjoiMSJ9.Z3iWJjDNBIdAeuMnbVzWO9XZl4yHcKud1-j47djiYAsxfPARBjhobInqtixtPnf4K8igYHYIbJTT9OWl_wWbEJBgtnn4S1NY6yr98r5-d5NuxFJnaHA6EOU6F97DXc3hNKV0XRbIDhfokIhMA9xuSjgaZCBOZEIbXnX9XzNtfO8sGOW8BUlyQmb2wpeSYuPFCrlKtKnJf6rSXQaz7MQVwnhA90gXzxdfmqQMa8pdmFWuAFvT8cth95ay-_YBVIRYzz_d_xDL9SNsrpKn7cN7LjxS2D16LVd4ttTVwjV9bLs.FHlQTY3wQfMServnYVZeYVTCDPTo_Q15HZaPTr8i--o&dib_tag=se&keywords=%E5%AE%9F%E8%B7%B5vim&qid=1711189228&sr=8-1) Vimmerの方は当然読んでおられると思いますが、まだ読んでいない方は必ず読みましょう。シソーラス辞典についての話は触れられませんが、Vimの様々な補完の話は「第19章　ダイヤルXを廻せ！　自動補完だ」に出てきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113494/48181012-4bfb-23a8-6b9d-a91080f7091d.png)
p5.js ＋ iPad（Safari）の組み合わせで「DualShock 4」を扱う：ブラウザの Gamepad API利用 ＋ VSCode の活用

## はじめに
PC上のブラウザを使って試した、以下の記事に書いた内容を、今回は iPad で試してみたという内容の記事です。

●p5.js Web Editor上で Gamepad API を使う： DualShock 4 を使ったシンプルな接続確認・ボタン押下判定 - Qiita
　https://qiita.com/youtoy/items/997e5720de790e36b98b

けっこう前から、iPad自体はゲームコントローラーに対応していたはずなのですが（※ 以下が公式の関連ページ）、今回は iPad のブラウザ（Safari）の API（Gamepad API）で扱えるか動作確認をしたという感じです。

●ゲームコントローラをiPadに接続する - Apple サポート (日本)
　https://support.apple.com/ja-jp/guide/ipad/ipad4c38c119/ipados

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50868/b8911e6a-e460-70a2-7a1e-d7d7c078eacb.png)

### デモ動画
最初に、今回の内容を試したみた時の様子の動画を掲載します。

ボタン押下時に、キャンバスの背景色が変わっているのが分かります。

<iframe width="560" height="315" src="https://www.youtube.com/embed/oEQvTyvWSso?si=RncYiv-03r0uyGTg" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>

## 実装した内容
今回の実装内容は、以下のとおりです。

HTMLファイル 1つに、CSS・JavaScript を直書きする形で含めています。

```html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8" />
    <meta
      name="viewport"
      content="width=device-width, user-scalable=no, initial-scale=1, viewport-fit=cover"
    />
    <meta name="apple-mobile-web-app-capable" content="yes" />
    <style type="text/css">
      html,
      body {
        margin: 0;
        padding: 0;
      }
      canvas {
        display: block;
      }
    </style>
    <title>iPadでDualShock 4</title>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.9.1/p5.js"></script>
  </head>
  <body>
    <script>
      function setup() {
        createCanvas(600, 500);
      }

      function draw() {
        const gp = navigator.getGamepads()[0];
        if (gp?.buttons[0].pressed) {
          background(100, 150, 200);
        } else {
          background(220);
        }
      }
    </script>
  </body>
</html>
```

### 補足１： 全体の話
まず、上で掲載した内容の全体的な部分の補足です。
JavaScript の実装内容は、基本的に[冒頭に掲載していた記事](https://qiita.com/youtoy/items/997e5720de790e36b98b)のものを用いました。

そして、HTML・CSS は p5.js Web　Editor で用意されているものがベースですが、そこに少し手を加えています。手を加えた内容は、以下の記事に出てくる内容です。

●iPhone/iPadで動くWebBluetoothアプリをp5.jsで作る方向けのメモ - Qiita
　https://qiita.com/tetunori_lego/items/363d0a47a5bbc4ffabd1

上記の記事の中の「Webアプリとして使うための準備」「Canvasのサイズ」という項目に書かれている内容を、ベースにした内容の修正に使っています。

## 機器構成
### デバイス
今回、iPad は以下でポストしていた Type-Cコネクタの第10世代を用いました。

https://twitter.com/youtoy/status/1768467410171121985

そして、DualShock 4 は USBケーブルで直接 iPadに接続しています（※ iPad側は Type-C、DualShock 4側は Micro USB Type-B）。

さらに、Safari で表示しているページは、PC上のローカルサーバーを使って動作させています。そのローカルサーバーは、ローカルネットワーク内からだけでなく、インターネットから見えるようにしているのですが、以下でその話を補足します。

### ネットワークまわりの部分
PC上のローカルサーバーをインターネットからアクセスできるようにする、という話です。

そういった構成をとるときに用いるもので「[ngrok](https://ngrok.com/)」が有名ですが、今回は、過去に以下の記事に書いていた VSCode標準の機能を使いました。

●VSCode の新機能「built-in port forwarding」を使いローカルサーバーにインターネット側からアクセス - Qiita
　https://qiita.com/youtoy/items/56e48c84d6a2f0549155

こちらを用いることで、「https://●●.devtunnels.ms/」という URL を使い、ローカルのサーバーにインターネット側からアクセスすることが可能になります。
ConohaVPSでAlmaLinux9.3を構築する。part1

ConohaVPSの借り方を説明する。

## 1\. サーバ借り方
1-1．AlmaLinuxの9.3を選択する。

![スクリーンショット (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/88e7b866-08bc-09da-47e4-210bc5ce9d38.png)

1-2．料金タイプを選択する。
ここでは、時間課金プランを選択する。プラン内容は割愛とする。
詳細は以下参照
https://www.conoha.jp/vps/function/hourly/?btn_id=vps-function--functions_vps-hourly

1-3．rootパスワードを設定する。

1-4．ネームタグを選択する。(ConohaVPS内で記載するサーバ名)

![スクリーンショット (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/ea126f07-3d34-10dd-ca6a-64c7b2b83b6e.png)

1-5．追加ストレージは今回なし。

1-6．セキュリティグループは後で設定するため、今回はdefaultとSSHだけ追加しておく。

1-7．SSHkeyも使用しない。

1-8．スタートアップスクリプトも使用しない。

右枠の追加を押して終了。

![スクリーンショット (35).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/d4e6a0e1-b7df-4a37-1f51-ddd0e23d94a3.png)


この後、利用するクレジットカードを入力します。(カード入力手順は割愛)

## 2\. サーバ起動

作成したサーバが追加されていることを確認する。
左のサーバーを押す。
![スクリーンショット (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/8f20b482-fcc6-4ede-7823-b4f59df1b04e.png)

ネームタグを押下後、起動ボタンを押す。
![スクリーンショット (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/ebffc692-1e4d-7607-670d-c9e74928c2ea.png)

起動できたら以下のようになります。
![スクリーンショット (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2984034/7fcf118c-d536-45a9-7f79-b5769181c69e.png)
情報量

# 情報量とは
情報の希少価値（＝珍しさ）を数字で表したもの
確率変数$A$ に対する情報量は 

```math
\begin{align}
I(A)& = \log_{2} \frac{1}{P(A)} \\
    & = -\log_{2} P(A)
\end{align}
```

で表される。
直感的には
- 確率が低ければ希少価値が高くなるようにしたい
　　=> 単調増加関数においてP(A)の逆数を採用
   
- 情報の組み合わせの珍しさは足し算で表現したい（情報量が大きくなりすぎないように）
　　=>対数関数を採用

例1）コインを1回投げて表が出る情報量
$P(表）＝\frac{1}{2}$ なので
$$I(表) = -\log_{2} \frac{1}{2}=\log_{2}2=1$$

例2）サイコロを1回振って4が出る情報量
$P(4）＝\frac{1}{6}$ なので
```math
\begin{align}
I(4) &= -\log_{2} \frac{1}{6}=\log_{2}6 \\
&=\log_{2}2 \times \log_{2}3 = 1 + \log_{2}3 \\
&\fallingdotseq 2.58
\end{align}
```

# 情報エントロピーとは
情報量の期待値
確率分布が偏っている場合は、小さくなる（確率が高い事象を予想するのは驚きが少ない）

確率分布$P$が離散の場合
```math
\begin{align}
H(P) & = \displaystyle \sum_{i} P(X_i) \cdot I(X_i) \\
& = -\displaystyle \sum_{i} P(X_i) \cdot \log_{2}P(X_i)
\end{align}
```

確率分布$P$が連続の場合
```math
\begin{align}
H(P) & = \int_{-\infty}^{\infty} P(x) \cdot I(x) dx \\
& = -\int_{-\infty}^{\infty} P(x) \cdot \log_{2}P(x)
\end{align}
```
pip installをオフラインで行う方法（Windows）

# はじめに
この記事では、Pythonのパッケージをオフラインでインストールする方法を紹介します。

# なぜ、オフラインでインストールを行う必要があるの？
個人のPCでPythonのパッケージをインストールを行う場合は、特にネットワークやセキュリティ上の制約がないため、以下のようにpipコマンドでパッケージをインストールすることが可能です。
```anaconda prompt
# パッケージをインストール
pip install [パッケージ名]

# pandasをインストール
pip install pandas
```

しかし、会社のPCでPythonのパッケージをインストールを行う場合、ネットワークやセキュリティ上の制約により、上記のような方法ではインストールが行えないことがあります。私の所属している会社でも、`pip install`を実行すると、タイムアウトになり、インストールができません。せっかく、Pythonを入れてみたものの、必要なパッケージをpipでインストールできず、試したいことが試せない。そのような状況に陥らないための対処法として、オフラインでのパッケージインストール方法を紹介します。

# pip installをオフラインで行う
環境は以下を想定しています。
- Windows10または11
- anacondaをインストール済み

環境構築を行うプロセスは以下の通りです。

1\. PyPIからファイルをダウンロード
2\. anaconda pawershell promptからインストール

### PyPIからファイルをダウンロード
今回は、pandasをオフラインでインストールしてみます。
まず、以下のサイトに移動してください。

https://pypi.org/

pandasと入力し検索します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3062041/14d55868-7d98-b133-91b6-98821120b800.png)

検索結果の一覧が表示されますが、今回は「pandas 2.2.1」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3062041/61cca281-321e-c40f-3e6b-c9c0c9562bec.png)

クリックすると以下のような画面に遷移します。
左側の「ファイルをダウンロード」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3062041/ec64b57c-ec64-3fcd-dc81-69a315731592.png)

クリックすると以下のようなファイルリンクの画面に遷移します。
今回は、windowsの環境なので、Built Distributionsの一番上にある、「win-amd64.whl」という文字が含まれているファイルを選択してダウンロードしてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3062041/9f20fe88-9268-f2ce-8b17-e7914813bf99.png)

ダウンロードしたファイルを所定のフォルダに格納します。

### anaconda pawershell promptからインストール
anaconda pawershell promptからpandasをオフラインインストールします。
まず、anaconda pawershell promptを立ち上げます。
ダウンロードした「.whl」のファイルを格納した場所に移動します。
```powershell:所定のパス
cd 所定のパス
```
所定のパスへ移動したら、以下のコマンドを実行します。
今回は「pandas-2.2.1-cp312-cp312-win_amd64.whl」で試してみます。

```powershell:download pandas
# オフラインインストールのためのコマンド
pip install --no-deps [ファイル名]

# pandas-2.2.1-cp312-cp312-win_amd64.whlをインストール
pip install --no-deps pandas-2.2.1-cp312-cp312-win_amd64.whl
```
以下のようなコメントが表示されれば成功です。`pip list`でインストールされているかの確認も可能です。
```
Installing collected packages: pandas
Successfully installed pandas-2.2.1
```

# たくさんのパッケージをオフラインインストールしたい
実際の実務では、関係するパッケージも含め何十ものパッケージをインストールしなければならないことがあります。そのような場合、ファイルひとつひとつに対して、`pip install --no-deps`を実行するのは非常に面倒です。ここでは、複数のパッケージを一括でオフラインインストールする方法を紹介します。

```powershell:複数のファイルからパッケージを一括ダウンロード
# パスを指定する
$path = "C:/所定のパス/"

# ダウンロードした「.whl」のファイル名リストの取得
$data = @(Get-ChildItem -Name C:\所定のパス\*.whl)

# for文を使って順にインストール
FOR ($i=0; $i -lt $data.Length; $i++){
    pip install --no-deps ($path + $data[$i])
    }
```
`Get-ChildItem -Name`で、ファイルの名前を取得し、`$data`に格納します。`$data`の長さを、`$data.Length`で取得し、`$data.Length`の回数for文をまわし、`pip install --no-deps`を実行すれば、たくさんのファイルを自動でインストールすることが可能です。


# 参考文献
https://tech-diary.net/python-library-offline-install/