OmniAICreator/Qiita-1.07M huggingface dataset:
NextJS を Lambda にデプロイするツールを試してみた

## モチベーション

弊社の場合BFFとして、AWS AppSync を使って GraphQL の API を立てて、その後段の DynamoDB への操作をしています。

![ざっくりアーキテクチャ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517555/499798d4-a80d-58df-e435-2177a066fa25.png)

管理画面や CMS として、 kintone を使っているのですが、 DynamoDB と kintone 内部のストアでデータをそれぞれ持った状態で同期させ続けているのですが、これがだんだん辛くなってきました。

そこで、直接 AppSync 経由で DynamoDB の中身を CRUD 出来る管理画面を作りたいです。

しかし、現在、AppSync の認証はフロントエンドからはOIDC、バックエンドはIAMという設定にしており、ビジネス担当者側が求めるデータの確認や処理を安全に実現することが難しそうです。

そこで、「Lambdaで管理画面を動かしてしまえ」という発想に至り、いろいろ調査をしています。

その中で、見つけたツールを動かしてみたので、その備忘録です。

## さわってみたもの

https://github.com/sladg/nextjs-lambda

Nets.js で build したものをいい感じに AWS までデプロイしてくれそうです。
スタティックなものはS3に、画像とSSRしそうなものは Lambda に。ということみたいです。

### Next をつくってみる

Next 14 に対応してるとは書いてないので、13を指定します。

```console
npx create-next-app@13.5.6 next-lambda-app
```

`yarn` になれているので、`package-lock.json` を消したりなんだりして


```console
yarn dev
```

動きました。

### ツールを使っていく

ツールを入れます

```console
yarn add @sladg/nextjs-lambda
```

ルートにある `next.config.js` を以下のように変更します

```js
/** @type {import('next').NextConfig} */

module.exports = {
	compress: false,
	output: 'standalone',
	experimental: {
		esmExternals: false, // optional
		externalDir: true, // optional
	}
}
```

Readme にある通り、 `yarn build` と `yarn --package @sladg/nextjs-lambda cli pack` と進めていくと、ここでエラーに

```console
Process failed with error: Error: Public folder assets must be nested in public/assets folder.
```

現状だと、public ディレクトリの配下に直接 `next.svg` と `vercel.svg` の2つが入っているため、もう一つ assets をつくって入れてあげます。

画像のパスが変わってしまったので、`app/page.tsx` 内部の `<Image />` 内部の `src` をassets 配下に変更してあげます

### 再度挑戦

`yarn build` のつぎに、 `yarn --package @sladg/nextjs-lambda cli pack` を叩くと、`next.out` というディレクトリが出てきました

```console
next.out
├── assetsLayer.zip
├── code.zip
└── dependenciesLayer.zip
```

`yarn --package @sladg/nextjs-lambda cli deploy` を叩いてみます。

パッケージ不足で怒られたので、以下のように3つパッケージを入れたら、上記のコマンドが通りました。

```console
yarn add envalid
yarn add @aws-cdk/aws-apigatewayv2-alpha
yarn add @aws-cdk/aws-apigatewayv2-integrations-alpha
```

どうやら、AWS CDK が動いてるようです。
デプロイされたみたいなので、CloudFormation を覗きに行ってみます

### 作られた構成

以下のような構成ができていました。

![デプロイされたもの.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3517555/db9d361f-97e4-5237-07de-ccd3a4d6806c.png)

* クライアントは CloudFront にアクセス
  * CloudFront に設定されてる Origin は三つ
    * S3
    * API-GW の /_server
    * API-GW の /_image
* Static なものは S3 に。画像も入ってる。
* SSR は API-GW(HTTP) と Lambda に
* 画像の最適化？をしてくれる Lambda も動いてる。
  * これはこのツールの作者の別パッケージらしい。細かい動きは一旦保留。

### 感想と今後

* Next.js を サーバレスに AWS 上にデプロイするのがすごい簡単にできた
* 複数環境やIaCを考えると CDK で対応したくなるが、一応そのための説明が書いてあるので、やってみる。
* Image の Lambda が何をやっているのかわかってない
* Lambda のログとか、こっちで制御できるのか確認
* そもそもこれで、AppSync叩けるのか！！笑
* 力尽きたので、一旦終了ね

## 他の選択肢

* Amplify Hosting でも Next.js に対応しているが、あっちは SSR側が Lambda@Edge なので、制約が強めなのが、やりたいことから考えると不安である
* AWS 公式が用意しているものもあるので、こっちを先にやっておくべきなのでは？笑
  * Lambda Web Adapter

https://github.com/awslabs/aws-lambda-web-adapter
PegaCSSA_Upgrade_Guide

■PegaVupにおけるData schema/Rules schemaの大まかな移行手順：
　（参考資料：https://docs.pega.com/bundle/platform/page/platform/deployment/onprem-software-update-gonogo-enable-shema-changes.html）
　１．DBで空のData schema、Rules schemaを作成する

　２．既存Ruleを旧Rules schemaから新Rules schemaに移行するため、「migrate.sh」を実行する
　　※「migrate.sh」については以下リンク参照：https://docs.pega.com/bundle/platform/page/platform/deployment/run-rules-migration-script.html

　３．'23のRule更新分を新Rules schemaに反映するため、IUAツールを実行する
　　※IUAツールについては以下リンク参照：https://docs.pega.com/bundle/platform/page/platform/deployment/patch-update-process-iua-method.html#Upgrading_the_migrated_rules_schema_by_using_the_IUA
　　※IUAツールに必要な「PRPC_Setup.jar」はPegaからもらう想定

　４．'23のData更新分を旧Data schemaに反映するため、「update.sh」を実行する
　　※「update.sh」については以下リンク参照：https://docs.pega.com/bundle/platform/page/platform/deployment/patch-update-process-data-schema-changes.html

　５．使用するRules schemaは新Rules schemaに向きを変更したうえ、ノードを再起動する
　　※Data schemaは旧Data schemaを流用するため変更しない


■参考になるドキュメント：
・PegaVup関連のドキュメントまとめ：
https://support.pega.com/support-doc/installation-and-update-documentation-roadmap

・影響確認からテストまで全体的な流れ/手法については、以下トピック配下のドキュメント参照：
https://docs.pega.com/bundle/keeping-current/page/keeping-current/kc/onprem-software-update-zdt.html

・詳細なUpdate作業手順については、以下トピック配下のドキュメント参照：：
https://docs.pega.com/bundle/platform/page/platform/deployment/update-introduction.html
「辞書」アクションの数字に小数点を入力する方法

### 問題点

「辞書」アクションの数字項目のデータには小数点が入力できない。

![IMG_5533.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/ff37771e-ce33-beda-4524-44388da2819f.png)

### 解決法

コピペで入力する。

![IMG_5534.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/f0f0e446-1b8b-c501-2eae-6f31d7c87240.jpeg)

![IMG_5535.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/41a0db78-f936-a018-a3c8-c48c59e84756.jpeg)

![IMG_5539.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/1aff4659-86ab-76e9-924b-db9c0bdc0307.jpeg)

計算できることから、数字として判断されていることがわかる。

![IMG_5537.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/e76c0d80-6714-eec2-5889-4cc5dcd09828.jpeg)

:::note
「計算」アクションでは小数点が入力できる。バグなのか仕様なのか。

![IMG_5536.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/7c0df274-d3e7-ae04-4a6a-68350b31a7b6.png)
:::
[firebase functions]Unhandled error cleaning up build images. エラーが出た時に確認すること

# エラー内容
firebase functionsのデプロイ時に
```
Unhandled error cleaning up build images. This could result in a small monthly bill if not corrected. You can attempt to delete these images by redeploying or you can delete them manually at https://console.cloud.google.com/gcr/images/[project-name]/us/gcf
```
という内容のエラー

# 確認すること
functions/ 内の.gitignoreでvenvと__pycache__が指定されていることを確認。なかったら追加すれば治る。

```functions/.gitignore
venv
__pycache__/
```
ESP32 マイコン を PlatformIO で動かす (on Linux Mint)

## この記事は？

ESP32 は、Wi-Fi と Bluetooth 内蔵の Espressif 社製マイコン。

https://akizukidenshi.com/catalog/g/gM-15673/

それを、組み込み開発色々対応の強力な VSCode 拡張である PlatformIO で動かした、という日記です。

ちょっとだけハマった箇所があったので、その内容と対処の記録をメインに記事を書きました。

## 環境メモ

* OS: Linux Mint 21.2 Victoria 64 bit
* Visual Studio Code 1.83.1
* PlatformIO v3.3.1
  * Core 6.1.11
  * Home 3.4.4
* ESP32-WROOM-32
  * ~~どこの何を買ったか忘れたなんて言えない･･･~~

## プロジェクト作成

Board 選択しようとしたところ、それらしきものがいくつかあります。

![new-project-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/a4ad94c3-f169-e388-95f0-2a524f2e5a20.png)

とりあえずチップを見てみます。

![esp-img-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/e1a8ffcf-5602-4536-2554-c6574ff9d5b4.jpeg)

![esp-img-2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/b2fda2d6-7153-35be-910a-49937c9ee905.jpeg)

適当に通販のサイトの写真とかを探してみると、'ESP32-C3' というのも見かけました。一方僕の手元のボードでは 'C3' とかの表記は無し。

適当に C3-DevKitC で進めてみたら、書き込みで `This chip is ESP32 not ESP32-C3.` というエラーを返されました。'Dev Module' で進めたら動きました。どうやらチップの型表記から判断できそうです。**[ハマったとこ その1]**

Board 選択がなんとかなったので続き。Name や Location は任意で。Framework はここでは Arduino を使います。(Espidf を知らないから･･･)

![new-project-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540894/83093c88-8def-be59-b035-e25edc8d6206.png)

:::note
ESP32 は Arduino でも開発可能です (Wi-Fi や Bluetooth も使える)。ただし、機能をフルで使うには純正環境の Espidf が必要です。
:::

## udev のインストール

詳しくは公式ページで。(丸投げ)

https://docs.platformio.org/en/stable//core/installation/udev-rules.html

udev は、Linux におけるデバイス管理ツール、らしいです。(今回存在を初めて知った)

上の設定をしていない状態では、(自分の環境では) 「Please install ...」とメッセージが出て、書き込みに失敗しました。(コンパイルは通る) **[ハマったとこ その2]**

## コード

訳あって単純に SPI を送信するコードが必要だったので、適当に SPI 信号を送り続けるコードを作成。常に同一数字じゃつまらないので 0〜255 を順に送る形に。

```c
#include <Arduino.h>
#include <SPI.h>

uint8_t i = 0;

void setup() {
  SPI.begin();
  SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));

  pinMode(22, OUTPUT);
  digitalWrite(22, HIGH);
}

void loop() {
  digitalWrite(22, LOW);
  SPI.transfer(i);
  digitalWrite(22, HIGH);

  i++;  // 255+1 でオーバーフロー
  delay(500);
}
```

## 感想

Arduino IDE で開発しようとするとボード追加のための設定が必要になりますが、PlatformIO だとプロジェクト作成以降は必要な設定を自動でやってくれてとても楽でした。(初回はプラットフォームダウンロードのため少々時間がかかる)

入力補完とかもあるので、これで Arduino IDE をリストラにした人も多いかと。ちなみに僕はリストラしました。
擬似言語プログラム

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3457284/89ee17a3-4a97-e5ab-3c2f-05a8f44b366d.png)
１：繰り返し
　繰り返し処理には、while,do~while,for命令を使います。

 ①while命令
 whileは、下記の形式で記述します。while直後の（）の中にループ継続条件を指定します。whileは、条件が成立している間、処理１を繰り返し実行します。条件が不成立になるとendwhile直後の行から先を実行します。

 「whileの記述形式」
 while（ループ継続条件）
 　　処理１
endwhile

　whileは、全判定型ループといい、「処理を実行する前に条件を判定する」という動作が特徴です。
 　条件式判定（成立）　→ 処理１　→ 条件式判定（成立）　→ 処理１　　→ ‥ → 条件式判定（不成立）　→　終了　（endwhileの次の日行へ移る）
  と処理が進みます。ループを始めるにあたって、まず条件式の判定を行いますので、最初から条件式が不成立の場合には、「処理１」は一度も実行されません。
辞書を順番通りに出力する方法

### 問題点

「リストから選択」アクションの入力に、JSONデータを記載した「テキスト」アクションを設定すると、順番がバラバラになって出力される。

![IMG_5521.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/5c266d94-016c-08f4-aa1c-2ad8405a5e55.jpeg)

![IMG_5519.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/0c919e8d-63a7-3e21-963c-b1db27ed043f.jpeg)

![IMG_5520.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/fca2c5db-0e97-f4b9-d6fa-c26d831f66da.jpeg)

### 解決法

「辞書」アクションの出力を「リストから選択」アクションの入力に設定すると、上から順番に出力される。

![IMG_5523.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/7584d23d-366d-2cab-8e37-6f282d2597f1.jpeg)

![IMG_5524.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3583885/6d229944-9f66-973c-701a-dfc0e80b1b77.jpeg)

:::note
順番がバラバラになると言っても、毎回その順番は同じになる。
アルファベット昇順ってわけでもないし、一体何順なんだろう。
:::
【SwiftUI】@GestureStateを使ってみる

# はじめに
`@GestureState`という機能があり、使ったことがなかったので使ってみました

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 - 2023-11-08 at 22.13.27.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/cd34487c-2812-6ca7-05f8-da10e79d2671.gif)

# 実装
[こちら](https://developer.apple.com/documentation/swiftui/gesturestate)の公式ドキュメントのコードを使用しています
```swift
import SwiftUI

struct ContentView: View {
    @GestureState private var isDetectingLongPress = false

    var longPress: some Gesture {
        LongPressGesture(minimumDuration: 3)
            .updating($isDetectingLongPress) { currentState, gestureState, transaction in
                gestureState = currentState
            }
    }

    var body: some View {
        Circle()
            .fill(self.isDetectingLongPress ? Color.red : Color.green)
            .frame(width: 100, height: 100, alignment: .center)
            .gesture(longPress)
    }
}
```

# `@GestureState`のメリット
ジェスチャーが終了すると自動で`false`になるので、
押している間だけ処理をするということに適しています。

- 長押ししてる間だけ録音
- 長押ししてる間だけ動画を撮影

色々と使えそうな機能ですね

# おわり
この機能は使われているのもみたことがなかったので存在を全く知りませんでした

# 参考記事
https://developer.apple.com/documentation/swiftui/gesturestate
Unable to connect to any of the specified MySQL hosts.

表題のエラーが発生したが原因が特定しづらかったので困っている方の参考になれば
このエラーは毎回発生するわけではなく1/5000ぐらいの確率で発生していた。

## 使っていたバージョン

.NETでMysqlを扱うライブラリMySql.Dataを利用していた。バージョンは8.0.23でMySQLのバージョンと合わせていた。

https://www.nuget.org/packages/MySql.Data/

## 原因

MySql.Dataのバージョン8.0.23から8.2.0に上げたら表題のエラーが発生しなくなった。リリースノートを見てもそれらしきバグフィックスは見当たらないが改善はされている模様。

https://dev.mysql.com/doc/relnotes/connector-net/en/news-8-x.html

## とりあえず最新を使った方が良さそう

Unable to connect to any of the specified MySQL hosts.

で調べるとConnectionStringの順序が違う、またはさまざまな要因が検索されるので原因特定するのが難しい。MySql.DataのバージョンがMySQLのバージョンと同じ単位であるのでややこしいが、最新にするとバグフィックスされるので何も考えずに最新にするのが良さそう。このエラーが発生しなくなったが、何かしらエラーが起きていたことには変わりがなく、より明確なエラーメッセージが返ってくるようになった。めでたし
Pythonで数列を事前数値計算して浮動小数点数(単精度or倍精度)としてバイナリファイルに保存して使用する方法

$i$番目の素数$p_i$に対する$a_i=\sum_{i=1}^n \ln p_i$を事前計算してファイルに保存、使用する例

```python:precalc.py

import mpmath
import struct
from sympy import sieve
mpmath.mp.dps = 30

struct_double = struct.Struct("d")  # "f" なら単精度

# 保存先ファイルを開く
dest_f = open("sumlogp","wb")

sumlogp = 0
maxI = 10000000

for i in range(1,maxI+1):
    p = sieve[i]
    # a_iを計算
    sumlogp += mpmath.ln(p)
    # append data to file
    dest_f.write(struct_double.pack(sumlogp))
    # if (i&0xFFFFF) == 0:
    #    print(i/maxI) # 進捗率表示用
```


```python:user_side.py

import struct
import mpmath
from sympy import sieve
mpmath.mp.dps = 20

global sumlogp_data
sumlogp_data = open("sumlogp","rb").read()

# return a_i
def sumlogp(i):
    # ・単精度なら("d",8)の代わりに("f",4)とする。
    # ・i-1 としているのは 添え字iを1始まりで扱いたい場合であり、
    #   0始まりなら i-1 ではなく i とする。
    t = struct.unpack_from("d",sumlogp_data,8*(i-1))
    
    # struct.unpack_fromはタプルで返るので値を取り出すために[0]を付けている
    return t[0]

```

# 参考

https://qiita.com/pashango2/items/5075cb2d9248c7d3b5d4


↓すでに似たような記事を投稿してたことに気づいた・・

https://qiita.com/kob58im/items/734fcf69db3c9f880875
Qiskit 量子ビット配列図示

[前回](https://qiita.com/tare_/items/c75df27ed95e53ee7353)は量子回路の図示について紹介しましたが，今回は量子ビット間の実際の結合が分かる，配列の図示について見ていきます．（参考：[^1]）

# 配列図示

ここでは，実機の情報が載っている`qiskit.providers.fake_provider`を用いて，実機の量子ビットの配列の情報を取ってくることにします．```plot_gate_map```を用いると図示してもらえます．

```python
from qiskit.providers.fake_provider import FakeVigoV2
from qiskit.visualization import plot_gate_map

# "Vigo"の仮想のバックエンド "FakeVigoV2" を使用
backend = FakeVigoV2()

# バックエンドのゲートマップを可視化
plot_gate_map(backend)
```
![allign.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/37c9fda9-6776-61e4-ff4a-504f1961a147.png)

このマシンは５量子ビットであることや，0と4の間には結合がない(=これらに対し，単純に２量子ビットゲートをかけられない)ことが分かります．

図示できるものは，127量子ビットあるSherbrookeでしょうか．
```python
from qiskit.providers.fake_provider import FakeSherbrooke
backend = FakeSherbrooke()
plot_gate_map(backend)
```
![127qubit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/3bcb53da-713a-5aa9-964e-14324148489d.png)
疎ですね．

# エラーの情報も図示
実際のマシンは量子ゲートをかける際，測定する際，様々なタイミングでエラーが生じます．その情報も一緒に図示することが可能です．

```python
from qiskit.visualization import plot_error_map

backend = FakeVigoV2()
plot_error_map(backend)
```
![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/887541/5232e06a-b315-600c-921a-9e0efa55d3c6.png)

H error rateについては，以下を用いて計算されています．
```python
import numpy as np

num_qubits = backend.num_qubits
single_gate_errors = [0] * num_qubits
for gate, prop_dict in backend.target.items():
    if prop_dict is None or None in prop_dict:
        continue
    for qargs, inst_props in prop_dict.items():
        if inst_props is None:
            continue
        if gate == "measure":
            if inst_props.error is not None:
                read_err[qargs[0]] = inst_props.error
        elif len(qargs) == 1:
            if inst_props.error is not None:
                single_gate_errors[qargs[0]] = max(
                    single_gate_errors[qargs[0]], inst_props.error
                )

# Convert to percent
single_gate_errors = 100 * np.asarray(single_gate_errors)
avg_1q_err = np.mean(single_gate_errors)
```

例えば，0番目のqubitに対してinst_props.errorを見てみると，
```python
#id InstructionProperties(duration=3.5555555555555554e-08, error=0.0004135213478316029, calibration=None)
#rz InstructionProperties(duration=0.0, error=0, calibration=None)
#sx InstructionProperties(duration=3.5555555555555554e-08, error=0.0004135213478316029, calibration=None)
#x InstructionProperties(duration=3.5555555555555554e-08, error=0.0004135213478316029, calibration=None)
```
のようになっていることが分かります．これの最大値が色として表現されていることが分かります．

面白いことに，何もしていない`id`と`x`ゲートなどが同等なエラーレートとなっています．

CNOT error rateも，Readout error rateもありますが，とりあえず次回はこのエラーレートを実験で求められたらと思います．果たして求められるのでしょうか．

# 終わりに
図示については[もう少しある](https://qiskit.org/documentation/stubs/qiskit.visualization.plot_circuit_layout.html#qiskit.visualization.plot_circuit_layout)ので，時間があるときに追記するかと思います．

#### Version Information
|Software|Version|
|---|---|
|qiskit|0.45.0|


||System information|
|---|---|
|Python version	|3.10.12|

[^1]:https://qiskit.org/documentation/apidoc/visualization.html
Railsでannotateを実行してもコメントが追加されない

# はじめに

Railsを久しぶりに使ってGemで困ったのでまとめます

# 問題

Gemの`annotate`でモデルにスキーマ情報をコメントで追加しようとしました

```
$ bundle exec annotate
```

しかし、なぜかスキーマのコメントが追加されませんでした

# 解決方法

モデルのファイルを作成していましたがクラスなどを書いていなかったのでそれが原因でした

```test.rb
class test < Activerecord::Base
end
```

これだけ書いてからコマンドを実行したところうまく反映されました

# おわりに

時間をすこしロスしました
77. Combinations

## 問題文
return all possible combinations of k numbers chosen from the range [1, n].

```
Input: n = 4, k = 2
Output: [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
```

## コード
```python
def combine(self, n: int, k: int):
    ans = []
    def backtrack(first, combination):
        if len(combination) == k:
            ans.append(combination[:])  # <- point
            return 

        for i in range(first, n+1):
            combination.append(i)
            backtrack(i+1, combination)
            combination.pop()  # <- point

    backtrack(1, [])
    return ans
```
Ajaxを用いて、コントローラーにjsonデータを渡したい

## 記事作成の背景
普段CakePHPで開発するときってFormhelperなど便利なものを使ってデータ渡して開発を行っていましたが、とある事情からJSで処理してから、コントローラーに渡す必要が出たことでAjaxからCakePHPのコントローラーにデータを受け渡す事ってできるのかなという疑問から作成いたします。
## 環境
CakePHP4(最新)
JQuery
MySQL
## 全体の流れ
![スクリーンショット 2023-11-08 205435.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3616912/7176e0ce-86b6-11de-47f7-87cd08c2fca6.png)

①フォームを記入後、送信ボタンをクリックしイベントが着火

②JQueryでフォームの内容を処理

③データを連想配列に格納

④AjaxでデータのPOST

⑤コントローラー側で受け取り

ざっと簡単にまとめるのこんな感じ

## コード
JQueryのコード
```js
  //submitボタンをクリックし、イベントが着火
    $('#submitForm').on('click', function(event) {
        //CakePHPのデフォルトの動作を止めます
        event.preventDefault();
        //配列を定義
        var formData = {};

        $('#questionsForm').find('.info-box').each(function() {
        
           //この部分で処理を行っているのですが、今回のAjaxとは関係ないため割愛
           
        });
        $.ajax({
            type: 'POST',
            url: "<?= $this->Url->build(['controller' => 'AppsController', 'action' => 'PHPaction']) ?>",
            data: JSON.stringify(formData),
            success: function(response) {
                console.log('Received data:', response);
            },
            error: function(xhr, status, error) {
                console.error('Error:', status, error);
            }
        });
        
    });
```

Controller.phpのコード
```PHP
public function PHPaction()
    {
        //ビューの自動レンダリングを停止するため
        $this->autoRender = false;
        
        if ($this->request->is('ajax')) {
            $data = $this->request->getData();
            $response = $this->response->withType('application/json')
                ->withStringBody(json_encode([
                    'status' => 'success',
                    'data' => $data
                ]));
            return $response;
        }
    }

```

## 感想
当たり前ですが、CakePHPのバージョンで書き方が若干変わるためコントローラーの受け渡しで躓きました。
もし、同じことをやろうとされている方などの参考になればと、情報を共有いたします。
以上

最後まで読んでいただきありがとうございました。
間違ってる箇所ありましたら、教えて頂けると幸いです。
よろしくお願いいたします。
転職を通して気づいたこと

# はじめに
新卒入社した会社で９年目にして初めての異動を言い渡されました。異動に対して思うところもあり転職活動を始め、無事に内定をいただきました。転職活動を通して多くを学び、成長できたと感じます。この経験をアウトプットし糧にしたいと思うとともに、日本のどこかのどなたかの役にたてばと思い記録します。

# 転職活動を通して気づいたこと
**転職の旬は３０代前半まで**
転職市場において年齢は重要な要素です。
転職では即戦力が求められると言われますが、第二新卒のような若い人材の需要も高いです。年齢が上がるにつれて能力重視となるため、転職の難易度も高くなります。私は３０代前半で、転職市場では「ギリギリ選べる立場」だそうです。あと数年遅かったら結果は変わったかもしれません。
（言うまでもありませんが、能力の高い方はこの限りではありません。）

**上流工程の経験が重要視される**
前述の通り、転職市場では即戦力が求められるため上流工程の経験が重要視されます。
「上流工程」と聞くと、どの工程を思い浮かべますか？転職活動の中で感じたのは、企業様が言う「上流工程」とは要件定義や企画のことを指しているようだ ということです。設計は上流ではないように扱われるケースが多いように感じました。
規模の小さなPJでも構わないので、若いうちに上流工程を経験できるよう日頃から手を挙げていくことが大事ですね。

**「リモートOK」には裏がある**
求人に「リモートOK」と書いてあっても鵜呑みにしてはいけません。
私自身、同様の記載がある企業様に応募しましたが、「勤務先の近くに住んだ上でリモートOK」が真意でした。何かあったら出社できるようにという意味でしょう。だったらそう書いてくれよなと思ったのが正直なところです。

# おわりに
私は転職をして良かったと思っています。
異動に不満があり始めた転職活動ですが、その中で様々な方々と接し、自分がいかに狭い世界で生きていたかを痛感しました。同時にチャレンジ精神に火が付き、年功序列ではなく、実力でキャリアアップ出来る次の会社でどんなことが出来るのかワクワクしています。
今の勤務先にモヤモヤしているそこのあなた。愚痴を言っているだけでは何も変わりません。転職活動をしてビビッと来なければ転職しなければいいだけです。一度、外に目を向けてみませんか？


# おまけ：転職の理由と方向性
**転職の理由：自分にメリットの無い異動だと感じたから**
部長の説明では「期待されての異動（引き抜き？）」とのことでしたが、異動に伴い職位が上がるわけでもなく、移動先の業務も聞いていた話とは異なり、ただの人員補充に見えてしまったためです。また、異動先部署の業務は新しい技術に触れにくく、エンジニアとしての将来性が不安だったことも理由です。

**転職の方向性：**
**・セキュリティを仕事にしたい**
セキュリティへの興味が強かったため、セキュリティの仕事ができる求人を探していました。
「どうせ転職するならやりたいことをやろう」というマインドです。

**・レベルの高い環境に身を置きたい**
持論ですが、周囲のスキルや熱意のレベルが自分に影響を及ぼすと感じています。
環境面にもこだわりたいと思い、転職活動の軸としました。
JavaScript入門 その4：関数

JavaScript入門の書籍を読んで書いてあったこと＋自分で調べたことのメモ書きその4。関数。

# 関数
関数の定義の方法としてアロー関数式とfunctionキーワードを使う方法があるが。差異について詳細は[参考ページ](#webページ)の2番目のページを参照。


### アロー関数式
アロー関数式を右辺に記述し、左辺の変数に代入して関数を定義する。

下記の例では第2引数yにはデフォルト値がある。
`getPosisonText` は関数が代入された変数なので、テンプレートリテラル内でサンプルコードの最後の行のように関数を呼び出すことができる。

```js
let getPointText = (x, y = 0) => {
  return `x座標:${x},y座標:${y}`
}

let str1 = getPointText(1, 2);
console.log("位置: " + str1);
console.log("位置: " + getPointText(5));
console.log(`位置: ${getPointText(3, 8)}`);
```

【実行結果】
```console
位置: x座標:1,y座標:2
位置: x座標:5,y座標:0
位置: x座標:3,y座標:8
```

### function記法
アロー関数式の他に、function記法により関数を定義することができる。む
下記の例の `func1` の関数宣言の方法（function文）では無名関数を作ることはできない。
`func2` の関数宣言でイコールの右辺はfunction式と呼ぶ。

```js
function func1(a, b) {
  return a + b;
}

let func2 = function (a, b) {
  return a + b;
}

console.log(func1(1, 2));
console.log(func2(3, 4));
```

【実行結果】
```console
3
7
```

### 残余引数
関数定義において最後の仮引数の前に `...` を記述するとその仮引数の値はその仮引数の位置以降のすべての実引数を要素とする配列となる。これを残余引数という。残余引数により可変長引数の関数を定義することができる。

```js
let introduceFriends = (name, ...friends) => {
  for (let friend of friends) {
    console.log(`${friend}は${name}の友達です。`);
  }
}

introduceFriends("ジョン");
introduceFriends("マイケル", "一郎");
introduceFriends("ボブ", "一郎", "次郎", "太郎");
```

【実行結果】
```console
一郎はマイケルの友達です。
一郎はボブの友達です。
次郎はボブの友達です。
太郎はボブの友達です。
```

### 関数を引数として渡す

関数を引数に取る関数がある。
下記は配列（Array）のメソッド `filter()` と `map()` で関数を引数として渡すサンプルである。いずれも引数として無名関数を渡している。

例：
```js
let outerPlanets = ["Jupiter", "Saturn", "Uranus", "Neptune"];
let result = outerPlanets.filter((planet) => planet.length > 6);
console.log(result);
```

【実行結果】
```console
['Jupiter', 'Neptune']
```

例：
```js
let numbers = [1, 2, 3];
let result = numbers.map((num) => num ** 2);
console.log(result);
```

【実行結果】
```console
[1, 4, 9]
```


# 参考

### 書籍
[解きながら学ぶJavaScriptつみあげトレーニングブック | マイナビブックス](https://book.mynavi.jp/ec/products/detail/id=126984) 4章

### WEBページ
[残余引数 - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/rest_parameters)
[JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 #JavaScript - Qiita](https://qiita.com/suin/items/a44825d253d023e31e4d)
#プログラミング #ゲーム #Javascript #nodejs # #REASSEMBLY のエージェント追加MODのデータを自動的に更新するツール

**本内容を利用した場合の一切の責任を私は負いません。**

# 経緯
REASSEMBLYとは下記のゲーム。
https://store.steampowered.com/app/329130/Reassembly/

現在デグレードによってエージェントが沸かなくてなっている。
それを沸かせる下記のMODがある。
https://steamcommunity.com/sharedfiles/filedetails/?id=2840416349

ただ、艦隊データは下記のワームホールデータから手動でダウンロードしてフォルダに置く必要がある。
https://www.anisopteragames.com/sync/latest.html

デグレードはゲームのログを見ると、エージェント取得に失敗してるのが下記でわかる。
https://discord.com/channels/212568112317333504/461580481209696256/1075460909461413958
ただ、ログ上は失敗しているが、このAPIらしきものを直接使うとエージェントデータらしきものを取得できる。

これらから、APIで取得したデータを解析してluaファイルにし、更に圧縮したものをMODのエージェントデータの場所に置くことをプログラムで行えば、自動化できると考えた。
結果、できたので公開。

# バージョン
- OS  
OS 名:                  Microsoft Windows 10 Home  
OS バージョン:          10.0.19045 N/A Build 19045  
システムの種類:         x64-based PC
- node.js
node-v20.9.0-win-x64
- REASSEMBLY
version=20220806

# 準備
0. node.js環境作成
0. リポジトリダウンロード
https://github.com/github895439/REASSEMBLY_random_agent
0. リポジトリ展開
0. 設定変更
REASSEMBLY_random_agent.jsの上部にあるAgentDirectory設定を実行環境に合わせて変える。
(MODで使用されるエージェントフォルダーを指定する。)
0. 実行
`node REASSEMBLY_random_agent.js`

**データと履歴が増えていくため、適宜消すこと**

# 使い方
上記の準備が完了すれば、新たに世界を作ったりワームホールを抜けたりすれば、追加されたエージェントが使用されます。
(MODのエージェント数が多いため、必ずしも追加されたエージェントが現れるとは限らない。)

# 備考
dataフォルダ内にエージェントフォルダーにコピーする前のエージェントのluaファイルがあります。
luaファイル名だけだと名前がわからないため、履歴(history.txt)にluaファイルと名前の一覧を載せています。
BIG-IPの設定変更前後で取得するログ

:::note warn
技術的に新しい内容が含まれている訳ではなく、初歩的な内容です
:::

# はじめに

BIG-IPの設定変更前後で取得するログについて整理する


# 取得ログ

通常の設定変更作業であればUCS/SCFのみ取得
メンテナンス(停止)時間帯に設定変更作業を実施できる場合は作業後のqkview取得を推奨
|  | 取得方法  | 目的                                                   |
|--|----------|------------------------------------------------------- |
| 1| UCS      | 作業前の設定に戻すためのバックアップ・リストアファイル      |
| 2| SCF      | 作業前後で設定を比較(変更点確認)するために有効なファイル    |
| 3| Qkview   | 障害・統計情報の解析のためのファイル(各種ログが含まれる)    | 


# 1. UCS(user configuration set)

UCS取得(作成)時にはファイル名に「日時」「Host名(1号機)」「before(or After)」を含めると良い

```console: UCS取得方法
# tmsh save sys ucs 20231108_hostname1_before.ucs

Options:
  no-private-key  The configuration without private key information.
  passphrase      Passphrase for (un)encrypting UCS.

```
UCSを他筐体(同機種)にリストアする際にはマスターキー(master key)のリストアが必要となるため、念のためマスターキーも取得しておく(冗長構成の場合はStandby機から同じ値を取得可)

```console: master key取得方法
# f5mku -K
```



# 2. SCF(single configuration file)

SCFは設定情報を1つのテキストファイルに連結したファイル
（設定差分はtmsh show running-configコマンド結果を比較する方法でも可）

作業前後のSCFを比較する際はone-lineオプションを付けた方が、差異箇所(行)がわかりやすいかもしれません。

```console: master SCF取得方法
# tmsh save sys config file 20231108_hostname1_before.scf one-line no-passphrase
Saving running configuration...
  /var/local/scf/20231108_hostname1_before.scf
  /var/local/scf/20231108_hostname1_before.scf.tar

Options:
  no-passphrase  Specifies the unencrypted configuration will not use a passphrase when saved
  passphrase     Passphrase for (un)encrypting SCF.
  one-line       Display each configuration item on a single line
```

# 3. qkview

qkview取得時にはパフォーマンス影響があるため優先度を下げて実行する場合はniceコマンドを利用
（最近筐体の性能は高いためniceコマンド利用は必須ではない）

```console: master qkview取得方法
# nice -n 19 qkview
```


# 参考

K4423: Overview of UCS archives
https://my.f5.com/manage/s/article/K4423

K9420: Installing UCS files containing encrypted passwords or passphrases (11.5.x and later)
https://my.f5.com/manage/s/article/K9420

K12878: Generating diagnostic data using the qkview utility
https://my.f5.com/manage/s/article/K12878
Web版ChatGPT4の最大トークン数を調べてみた

## はじめに

OpenAIが11/7にChatGPT4-Turboを発表してこれはやばいと騒がれていますね。中でも128kトークンとファイルアップロードに対応した新しいAPIは、本1冊を丸々読み込むことができるウィンドウサイズなので、OpenAIを後追いするAIスタートアップに大打撃みたいな声も聞かれています。
ところで、本日11/8にWeb版ChatGPTを開くと、しれっと大幅リニューアルされていました。少し触ってみたところ、入力できるトークン数が大幅に増加していそうです。
これまでGPT4は一度に入力できるのが4Kトークン、記憶を保持できるのが8Kトークンでした。明らかに増えていると思われるので、実験的に確かめます。(記憶違いだったらすみません)


## 実験

### 一度に入力できるトークン数
これはエラーが起こるまで文字数を増やしていくだけで実現できますね。ただし日本語の文字数とトークン数はイコールではないので、そこだけ注意が必要です。2048トークンから初めて少しづつ増やしてみます。

まずは2k、余裕でOKです。ここから2倍ずつ増やしていきます。
- 2K -> OK
- 4K -> OK
- 8K -> OK
- 16K -> OK
- 32K -> NG

少なくとも16Kまでは行けました。以前のバージョンから大幅に増えていますね。ここからは人力二分探索をします。

- 24K -> NG
- 20K -> OK
- 22K -> NG
- 21K -> OK

この実験から、21Kトークンまで入力できることが分かりました。非常に長いですね。最終的に正確には21,838トークンの入力まで可能でした。

## 内部コンテキストのトークン数

次に内部のコンテキストをどれほど覚えているかを計測します。最初に合言葉を教えて、いくつかの会話を実行して、その後でも最初の合言葉を覚えているかどうかで計測します。

まずは21Kで実行してみたところ、合言葉を覚えています。

次に、32Kで実行してみたところ、合言葉を覚えていませんでした。二分探索しましょう。

- 24K -> OK
- 28K -> OK
- 30K -> NG
- 29K -> OK

この実験から、29Kトークンまでは内部状態を覚えていられるようです。やはり非常に長く、活用方法の夢が広がりますね。これだけ長ければ、バーチャル親友としても長く記憶を保持できそうな気がします。
また、予想なのですが、本来は一度の入力は24Kまで、内部トークンは32Kまで対応しているが、コードインタープリタや検索のためのインストラクションが3Kほど容量を使用しており、ユーザーが使用できるのは21Kと29Kなのではないかと予想します。

## ファイルの入力

今回のバージョンから、PDFやテキストファイルなど様々なファイルをアップロードできるようになりました。これらのファイルのトークン数の上限も確かめてみましょう。もしかしたら通常の文字入力よりコンテキストが長いのではないかと期待しています。
この実験では、ファイルの先頭に合言葉1を、ファイルの末尾に合言葉2を挿入して、どちらの合言葉も同時に認識できる最大のトークン数を調べます。

まずは29Kから行ってみましょう。
> 合言葉1: 見つけることができませんでした。
> 合言葉2: 正解の合言葉

先頭の合言葉を見つけられませんでした。何度か試したのですが、ダメでした。29KはNGとします。引き続き探索します。

- 29K -> NG
- 24K -> NG
- 20K -> OK
- 22K -> OK
- 23K -> NG

ということで、22Kトークンのファイルまで認識することができました。ユーザーの入力上限とほとんど同じくらいですね。おそらく内部でファイルを開いた後に、長すぎる文字列の場合は末尾の一定の文字を機械的に切り取って、ChatGPTのトークンに変換しているのだと思います。しかしエラーが出ないんですね。ファイルが大きすぎて読み込めませんでした、などとエラーを出力してくれた方がありがたい気がします。ファイルの末尾のみ認識というのも気をつけた方が良さそうですね。ちなみに、32Kトークンを超えるファイルはアップロードに失敗しました。


## 結論

| 機能 | 以前の上限 | 現在の上限 |
|:----:|:---------:|:---------:|
| 一度に入力できるトークン数 | 4K | 21K |
| 内部コンテキストのトークン数 | 8K | 29K |
| ファイルの入力トークン数 | なし | 22K |

### 結論

新しいChatGPT4-Turboの能力は、以前のバージョンに比べて大幅に向上しています。一度に入力できるトークン数が21Kまで、内部コンテキストを記憶できるトークン数が29Kまで、そしてファイルの入力トークン数が22Kまでとなりました。これにより、より長い文書の処理や、より複雑な対話が可能になっています。特にファイルアップロード機能の拡充は、文書全体を読み込むことができるため、研究、教育、ビジネスなど様々な分野での応用が期待されます。ただし、ファイルサイズの制限には注意が必要です。とにかく、Web版がここまで充実すると、他のAIサービスを使う必要が全くなくなりますね。

この実験は2023/11/8に行いました。もし間違いや新しい情報があればコメントをお願いします


## 追記
上記の実験は「GPT-4 With DALL·E, browsing and analysis」で行いました。「ChatGPT Classic」で試したところ違う結果が得られたので共有します。

- 一度の入力トークン数: 21,838トークンで変わりませんでした。
- 内部コンテキストのトークン数: 約31Kトークン

少しだけ内部コンテキストサイズがClassicの方が多いようですね。やはり、ブラウジングやコードインタプリタのためのインストラクションが3Kトークンほど含まれていそうです。
プログラミング言語：新しいテクノロジーを支える力-ブロックチェーンと人工知能

プログラミング言語は、特にブロックチェーンや人工知能(AI)などの新技術開発の分野において、あらゆるテクノロジーアプリケーションの頭脳です。この記事では、プログラミング言語の力と、これら2つの分野の発展にどのように貢献しているかを探りましょう。

プログラミング言語：ブロックチェーン技術の背後にある動機
 
[ブロックチェーンは](https://newwave-solutions.co.jp/blockchain/)、私たちがトランザクションを実行し、[ビッグデータ](https://newwave-solutions.co.jp/what-is-python) 理する方法を変えつつあるテクノロジーですが、強力なプログラミング言語が欠かせません。ブロックチェーン開発にとって最も重要な言語の1つはSolidityです。Solidityは、Ethereumプラットフォーム上でスマートコントラクトを作成することに特化したプログラミング言語です。Solidityを使用することで、プログラマーは第三者の仲介を必要とせずにスマートコントラクトを作成でき、トランザクションの透明性と安全性を確保できます。
Python：人工知能分野における使命
 
人工知能（AI）は、[プログラミング言語](https://newwave-solutions.co.jp/programing-languages) の柔軟性と効率性が必要な分野です。PythonはAI開発のための主要なプログラミング言語の1つになりました。Pythonには、TensorFlow、PyTorch、scikit-learnなどの強力なライブラリとフレームワークが多数あり、プログラマーが機械学習モデルを効果的に構築および学習するのに役立ちます。Pythonの読みやすさと理解しやすい構文は、AIアプリケーションやプロジェクトの開発に最適です。
>>> [Python はどのように使用されますか?](https://newwave-solutions.co.jp/what-is-python)
C++：新しいテクノロジーに対するパフォーマンス
 
高いパフォーマンスとリソースの直接制御の必要性が重要になるにつれて、C++言語が正しい選択となります。C++は、ソースコードを最適化し、高速に実行する機能があり、IoT(Internet of Things)や仮想現実(VR)などの新しいテクノロジーに基づくアプリケーションの開発で人気の言語です。特にブロックチェーン分野では、パフォーマンスとセキュリティを確保するためにネットワークノードがC++上で実行されます。
>>> [c言語とは?](https://newwave-solutions.co.jp/what-is-c) C#について詳しくはこちら
 
Java：新技術開発における信頼性
 
Javaは多用途で信頼性の高い[プログラミング言語](https://newwave-solutions.co.jp/programing-languages)であり、モバイルおよびWebアプリケーションの開発でよく使用されています。IoTなどの新しいテクノロジーでは、Javaが複雑なデバイスやシステムと簡単に統合できるように提供します。Androidプラットフォームでのアプリケーション開発にも使用されており、モバイルデバイス上で何百万ものアプリケーションを開きます。
VB.NET(Visual Basic.NET)
 
VB.NETは、Microsoftによって開発されたプログラミング言語であり、古典的なVisual Basic言語から開発されました。VB.NETはシンプルさと理解しやすさを重視しているため、初心者に適した言語です。VB.NETは、WindowsアプリケーションとASP.NET Webサイトでよく使用されます。Microsoftシステムとの強力な統合を提供します。
>>> [VB.NETプログラミング言語](https://newwave-solutions.co.jp/vb-net) について詳しく見る
Newwave Solutions - 新しいテクノロジーの旅
 
イノベーションと新しい技術開発に満ちた世界では、適切なプログラミング言語を選択することが重要です。Newwave Solutionsは、各プロジェクトには適切なプログラミング言語が必要であることを理解しています。私たちは、新技術開発のための主要なプログラミング言語を深く理解し、開発およびコンサルティングサービスを提供しています。
 
私たちは、Python、Java、C++、VB.NET、JavaScript、Solidityなどの適切なプログラミング言語、およびその他多くの言語を使用して、多様なウェブサイト開発サービス、アプリ開発およびシステム開発サービスを提供することを誇りに思っています。[Newwave Solutions Japan](https://newwave-solutions.co.jp/)は、一般的なプログラミング言語を深く理解し、ソフトウェア、システム、ブロックチェーン、AI、モバイルアプリケーションの開発において信頼できるパートナーです。
 
お客様のテクノロジーへの取り組みにおいて当社がどのようにサポート、詳しくはお問い合わせください。
ドライブレコーダを付けてみる

:::note warn
行う場合は自己責任となります.
:::
ドライブレコーダを付けてみます。費用は300円位です。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f323832313838322f39346463336166342d663466662d666364612d656238612d3135326231656634336539622e6a706567.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/5b720445-00e6-7b69-8517-9b294e1b0174.jpeg)

電源ケーブル取り回し
![DSCN5700.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/7a844945-e89c-bfbe-637b-ec6fcf73c8ce.jpeg)
こうするとケーブルが見えなくて良い。
- レコーダから出ているシガープラグの突起部に+12V 側面バネに - を接続します。その方法を示します。(プラグをバラして直結も可)

![DSCN0444.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/eab4e261-0bca-8a5e-8f00-6af65ade4e54.jpeg)
- 上画像のケーブル付きヒューズを使うと簡単にヒューズボックスが電源が取れる。ホームセンタ、車専門店で売ってます。同じアンペアで同一の大きさの物を用意。
![DSCN0496.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/ca2ab8d6-da40-faf3-d25f-92ead186811d.jpeg)


![OIP.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/53240cb5-4bed-e5fb-0f54-bdbad64de06c.jpeg)

- ケーブル付きヒューズへ半田付け

- ヒューズボックス 大抵、運転手側のハンドル下部にある。
![DSCN0343.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/f74f278e-5e14-bc8a-b3d8-45fc8307bcc1.jpeg)
この車ではNo13がING電源なのでここから取る。

:::note warn
安全の為め、ECUやエアバック等重要な所からは取らないでください。自分はパワーウィンドウから取りました。カバーに記載があります。
:::

![DSCN0501.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/2c08c7ed-f888-426a-3a88-cde66fdf1752.jpeg)
工作したケーブル付きヒューズと差し替える事により、ここからレコーダに給電される。

![DSCN0489.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821882/ad84a68a-94d2-ae78-62d0-55f4115c9057.jpeg)
一応、電圧を確認してみる。定格では12V/DC。2.44V高いが問題なし。

- [補足　一般的な事項]

|　　種　別|　　　　　　　　　　通　電　内　容||　
|:--|:--|:--|:--|
|常時電源|キーを抜いた状態でも常時供給されている電源。ここから電源を取ってると注意しないとバッテリがあがる。|   |
|イグニッション(ING)電源 |キーをIG（ON）位置、つまりエンジンが稼動している時に通電される。
|ACC電源|キーをACC（アクセサリー）以上の位置に回した時に通電する。エンジンスタート(イグニッションON)時は電源が切れる。

ハイブリッド車、ボタン式始動車でも同様です。
ちなみに通常、エンジン始動ボタンのみ押した場合はアクセサリ電源です。
ブレーキ踏みながらスタートボタンではING電源となります。

今回のようにエンジンが始動している時のみ電源を取りたい場合はING電源から取ります。
これにより、運転中のみ通電され録画されます。
カーセキュリティシステム市場調査：ResearchNesterによる乗用車のセキュリティシステム統合の増加による世界分析予測2023-2033

研究分析<b>「<a href="https://www.researchnester.jp/reports/car-security-system-market/392" target"_blank">カーセキュリティシステム市場調査</a>：世界の需要分析と機会展望2033年"</b>この調査レポートは、世界のカーセキュリティシステム市場を詳細に競合企業分析し、車両タイプ別、販売チャネル別、製品タイプ別、技術別、地域別に市場細分化した詳細な概要を提供しています。
さらに、詳細な分析として、世界のカーセキュリティシステム市場の成長に関連する現在および将来の市場動向に関する詳細な考察とともに、業界の成長指標、阻害要因、需給リスクを網羅しています。これらの分析は、組織が予測不可能な将来において成功するための継続的な成長機会を特定するのに役立ちます。さらに、市場が露呈している成長機会は、今後数年間で大きな勢いを得る準備が整っている。

<b>カーセキュリティシステム市場はカーセキュリティシステムの技術進歩を背景に数多くの成長機会を見出すとResearchNesterが発見</b>
世界のカーセキュリティシステム市場は、急成長する自動車産業、自動車生産台数の増加、先進国における高級車やプレミアムカーの需要、購買力の増加、多くの地域における盗難車数の増加などを背景に大きく成長すると推定され、市場成長の原動力となると予測されている。例えば、2020年には800,400台以上の車両が盗難され、2019年から11%増加した。
世界のカーセキュリティシステム市場は、車種別に乗用車、小型商用車、プレミアムカーに区分される。乗用車セグメントは、予測期間中に大幅なCAGRで成長することにより、2033年末までに最も高い収益を獲得する。一人当たり所得の増加、乗用車の生産台数の増加、自動車市場の急成長が、予測期間中の同分野の成長を促進すると推定される。インドの乗用車市場は2021年に320億米ドルを占め、2027年末には年平均成長率8%で540億米ドルに達すると予測されている。

![Car-Security-System-Market-Scope.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3491677/cdface13-67f2-ab73-e76d-8588835fa977.jpeg)

<b>詳細レポートへのアクセスはこちら：</b>
<b><a href="https://www.researchnester.jp/reports/car-security-system-market/392" target"_blank">https://www.researchnester.jp/reports/car-security-system-market/392</a></b>

地域別では、北米のカーセキュリティシステム市場が2033年末までに最も高い収益を上げる。この成長は、人口の間で高級車に対する需要が高まっていることから予想される。
この調査レポートは世界のカーセキュリティシステム市場を詳細に分析しています North America (U.S., Canada), Europe (U.K., Germany, France, Italy, Spain, Hungary, Belgium, Netherlands & Luxembourg, NORDIC [Finland, Sweden, Norway, Denmark], Poland, Turkey, Russia, Rest of Europe), Latin America (Brazil, Mexico, Argentina, Rest of Latin America), Asia-Pacific (China, India, Japan, South Korea, Indonesia, Singapore, Malaysia, Australia, New Zealand, Rest of Asia-Pacific), Middle East and Africa (Israel, GCC [Saudi Arabia, UAE, Bahrain, Kuwait, Qatar, Oman], North Africa, South Africa, Rest of Middle East and Africa). さらに、世界のカーセキュリティシステム市場規模、前年比成長率および機会分析、市場プレイヤーの競争力調査、投資機会、将来展望に対する需要などを含む分析も調査レポートで取り上げ、展示しています。

また、本レポートは世界のカーセキュリティシステム市場の主要企業の競争シナリオも提供しています Qualcomm Technologies, Inc., Mitsubishi Electric Corporation, Continental A.G., Delphi Automotive LLP, Hella KGaA Hueak & Co., Tokai Rika Co Ltd., Robert Bosch GmbH, Denso Corporation, Strattec Security Corporation, Witte Automotive, などがある。プロファイリングでは、事業概要、製品・サービス、主要財務情報、最近のニュースや動向など、企業の主要な情報を掲載しています。全体として、当レポートは世界のカーセキュリティシステム市場の詳細な概観を描いており、業界コンサルタント、機器メーカー、拡大機会を探している既存企業、可能性を探している新規企業、その他の利害関係者が、現在進行中および今後予想される動向に従って市場中心の戦略を調整するのに役立ちます。
<b>レポートサンプル@を請求する</b>
<b><a href="https://www.researchnester.jp/sample-request-392" target"_blank">https://www.researchnester.jp/sample-request-392</a></b>

<b>について Research Nester</b>
Research Nesterは戦略的市場調査とコンサルティングのリーディング・サービス・プロバイダーです。業界、コングロマリット、エグゼクティブが将来のマーケティング戦略、事業拡大、投資などのために賢明な決断を下せるよう、偏りのない比類のない市場洞察と業界分析を提供することを目指しています。私たちは、戦略的思考を通じて適切なタイミングで適切なガイダンスを得ることができれば、あらゆるビジネスが新たな地平へと拡大できると信じています。私たちの既成概念にとらわれない思考は、お客様が将来の不確実性を回避するために賢明な決断を下すのに役立ちます。

<b>【お問い合わせ先】</b>
<b>ナオミ コスギ</b>
Eメール: <b>info@researchnester.jp</b>
日本の電話番号: +81 505 050 8480
Helm チャートを Amazon ECR リポジトリにプッシュしてインストールする

# Helm Chart を ECR に push する

```
# 現在の Helm のバージョンを確認
helm version --short | cut -d + -f 1
    v3.13.1

# Helm Chart を作成
helm create mychart
    Creating mychart

# templates ディレクトリ内のファイルを削除
rm -rf mychart/templates/*

# 次のファイルを作成(configmap.yamlの内容は後述参照)
mychart/templates/configmap.yaml

# Helm Chart をパッケージ化
helm package mychart
Successfully packaged chart and saved it to: ./mychart-0.1.0.tgz

# Helm Chartを格納するリポジトリを作成
aws ecr create-repository \
     --repository-name mychart

# ECR に Helm クライアントを認証します。
# 認証トークンは、使用するレジストリごとに取得する必要があり、トークンは 12 時間有効
aws ecr get-login-password \
     --region ap-northeast-1 | helm registry login \
     --username AWS \
     --password-stdin 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com
    Login Succeeded

# Helm チャートを push
helm push mychart-0.1.0.tgz oci://123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/
    Pushed: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/mychart:0.1.0
    Digest: sha256:d05239c89412bcf9764a434e6e471f553b874973fc1a1235cbcc88XXXXXXXXXX

# ECR に　artifactMediaType　が　Helm Chart　で作成されたことを確認
aws ecr describe-images \
     --repository-name mychart
{
    "imageDetails": [
        {
            "registryId": "123456789012",
            "repositoryName": "mychart",
            "imageDigest": "sha256:d05239c89412bcf9764a434e6e471f553b874973fc1a1235cbcc88XXXXXXXXXX",
            "imageTags": [
                "0.1.0"
            ],
            "imageSizeInBytes": 1753,
            "imagePushedAt": "2023-11-08T19:35:10+09:00",
            "imageManifestMediaType": "application/vnd.oci.image.manifest.v1+json",
            "artifactMediaType": "application/vnd.cncf.helm.config.v1+json",
            "lastRecordedPullTime": "2023-11-08T19:35:11.252000+09:00"
        }
    ]
}
```

```configmap.yaml
apiVersion: v1
kind: ConfigMap

metadata:
  name: mychart-configmap

data:
  myvalue: "Hello World"
```

# EKS を使用して ECR でホストされる Helm チャートをインストールする

```
# ECR の　Helm Chart をインストール
helm install mychart oci://123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/mychart --version 0.1.0
    Pulled: 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/mychart:0.1.0
    Digest: sha256:d05239c89412bcf9764a434e6e471f553b874973fc1a1235cbcc88XXXXXXXXXX
    NAME: mychart
    LAST DEPLOYED: Wed Nov  8 19:57:52 2023
    NAMESPACE: default
    STATUS: deployed
    REVISION: 1
    TEST SUITE: None

# Helm Chart　のインストール確認
helm list -n default
    NAME    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
    mychart default         1               2023-11-08 19:57:52.338054 +0900 JST    deployed        mychart-0.1.0   1.16.0    

# ConfigMap を確認
kubectl get configmap -o wide
    NAME                DATA   AGE
    mychart-configmap   1      5m16s
```


# Amazon EKS チャート

https://artifacthub.io/packages/search?page=1&repo=aws

https://github.com/aws/eks-charts#eks-charts

# 参考

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/push-oci-artifact.html

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/ECR_on_EKS.html#using-helm-charts-eks
PgAdminのアップグレードに少し苦労した話

## アップグレードのきっかけ
PgAdmin4バージョン7.6でバグに遭遇した  
最新版(7.8)では修正済みなので、アップグレードを計画した

## アップグレードの手順
単純に最新版(7.8)をインストールした。
インストーラは以下から入手。
https://www.postgresql.org/ftp/pgadmin/pgadmin4/v7.8/windows/
しかし、PgAdminを起動するとバージョンは7.6のままであった。
![1](https://github.com/pgadmin-org/pgadmin4/assets/49807271/f7f3547c-7daa-445e-bf55-540ce45a8383)


## 状況整理
実際には2つのPgAdminがインストールされている状態だったが気づかなかった。
Windowsのアプリ一覧から見ると、PgAdmin7.8しか表示されない状況。

![3](https://github.com/pgadmin-org/pgadmin4/assets/49807271/76983a90-2259-4e2d-b173-4e4819e95244)
PostgreSQLのインストーラからPgAdminをインストールした場合、
アプリ一覧にはPgAdminは列挙されず、PostgreSQL 16に内包されていることになる。
PostgreSQLインストール時にpgAdmin 4にチェックを入れてインストールすると
この状況になる。
![1](https://github.com/pgadmin-org/pgadmin4/assets/49807271/b1c02df2-abab-4855-969f-3d225bd2a02b)
この場合、PgAdminをアンインストールするには、Postgresも一緒にアンインストールする必要がある。

## 結論
PgAdminをアップグレードする可能性がある場合は、PostgreSQLのインストーラでpgAdminをインストールするべきではない。
JavaScript入門 その3：繰り返し

JavaScript入門の書籍を読んで書いてあったこと＋自分で調べたことのメモ書きその3。ループ（繰り返し）処理。

# 繰り返し
`for`、`while`、`do-while` については自分が知っている他の言語にもある。特に気になる点はない。

### for-of
配列や文字列から1要素・1文字ずつ取り出すループ処理をする。

例：配列
```js
const arr1 = ["CAPTAIN STAG", "BUNDOK", "snow peak"];
for (const element of arr1) {
  console.log(element);
}
```

【実行結果】
```console
CAPTAIN STAG
BUNDOK
snow peak
```

例：文字列
```js
const str1 = "xyz";
for (const element of str1) {
  console.log(element);
}
```

【実行結果】
```console
x
y
z
```

```js
const arr2 = ["なす", "かぶ", "ねぎ"];
for (const element of arr2) {
  for (const character of element) {
    console.log(character);
  }
}
```

【実行結果】
```console
な
す
か
ぶ
ね
ぎ
```

### for-in
オブジェクトから列挙可能プロパティを1個ずつ取り出すループ処理をする。

```js
const obj = { "名称": "クロスカブ110", "排気量": "109cc", "WMTCモード値": "67.9km/L" };
for (const key in obj) {
  console.log(key + ": " + obj[key]);
}
```

【実行結果】
```console
名称: クロスカブ110
排気量: 109cc
WMTCモード値: 67.9km/L
```

### ラベル付きbreak、continue
ループやswitch文の処理を終了する `break` と ループ内の反復処理を中止して次の反復処理に移る `continue` にはラベルを付けることができる。

ラベル付きbreakの例。
iとjがともに1になると `break loop1` によりloop1のループ（外側のループ）処理が終了する。

```js
loop1: for (let i = 0; i < 3; i++) {
  loop2: for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) {
      break loop1;
    }
    console.log(`i=${i},j=${j}`);
  }
}
```

【実行結果】
```console
i=0,j=0
i=0,j=1
i=0,j=2
i=1,j=0
```

ラベル付きcontinueの例。
iとjがともに1になると `continue loop1` により現在の反復処理が終了し、loop1の次の反復処理（i=2）を実行する。

```js
loop1: for (let i = 0; i < 3; i++) {
  loop2: for (let j = 0; j < 3; j++) {
    if (i === 1 && j === 1) {
      continue loop1;
    }
    console.log(`i=${i},j=${j}`);
  }
}
```

【実行結果】
```console
i=0,j=0
i=0,j=1
i=0,j=2
i=1,j=0
i=2,j=0
i=2,j=1
i=2,j=2
```

ラベル付きブロックに対するbreakの例。
`break outerBlock` により outerBlock の末尾に移動する。`break outerBlock` より後の innerBlock、outBlock の処理は実行されない。

```js
outerBlock: {
  innerBlock: {
    console.log("1");
    break outerBlock;
    console.log(":-(");
  }
  console.log("2");
}
```

【実行結果】
```console
1
```


# 参考

### 書籍
[解きながら学ぶJavaScriptつみあげトレーニングブック | マイナビブックス](https://book.mynavi.jp/ec/products/detail/id=126984) 4章

### WEBページ
[for...in - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/label)
[break - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/break)
[ラベル - JavaScript | MDN](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/label)
Djangoの学習⑥（汎用ビューの使用）

Djangoでは、データの一覧表示、詳細表示、作成、更新、削除などの操作を
より簡単に実装することができように
汎用ビュー（generic view）というものを提供しています。

これまで作成してきた poll アプリのビューを汎用ビューシステムに変換して 
コードを修正します。

## URLconf の修正

```python:polls/urls.py
urlpatterns = [
    # ex: /polls/
    path("", views.indexView.as_view(), name="index"),
    # ex: /polls/5/
    path("<int:pk>/", views.DetailView.as_view(), name="detail"),
    # ex: /polls/5/results/
    path("<int:pk>/results/", views.ResultsView.as_view(), name="results"),
    # ex: /polls/5/vote/
    path("<int:question_id>/vote/", views.vote, name="vote"),
]
```

## views の修正

```python:polls/views.py

from django.views import generic

# Create your views here.
class IndexView(generic.ListView):
    template_name = "polls/index.html"
    context_object_name = "latest_question_list"

    def get_queryset(self):
        return Question.objects.order_by("-pub_date")[:5]

class DetailView(generic.DetailView):
    model = Question
    template_name = "polls/detail.html"

class ResultsView(generic.DetailView):
    model = Question
    template_name = "polls/results.html"

def vote(request, question_id):
    ...  # same as above, no changes needed.

```

以上です。
【Rails】belongs_to/has_one/has_manyの違い

# 【Rails】belongs_to/has_one/has_manyの違い

Ruby on Railsは、データベースとのデータの関連付けを簡単に行うことができる強力なフレームワークです。その中で、`has_one`、`has_many`、`belongs_to` というキーワードは、モデル間の関係を表現する際に使用されます。これらのキーワードの違いを理解することは、Railsアプリケーションの開発において非常に重要です。それでは、それぞれのキーワードの違いを見てみましょう。

## 1. `has_one`（一対一の所属させてる関係）

`has_one` は、一対一の関係を表現します。これは、あるモデルが他のモデルを「持っている」場合に使用されます。例えば、ユーザーがプロフィール情報を持っている場合、`User` モデルが `has_one` の関係にあります。この関係により、ユーザーは1つのプロフィールを持つことができます。

```ruby
class User < ApplicationRecord
  has_one :profile
end
```

## 2. `has_many`（一対多の所属させてる関係）

`has_many` は、一対多の関係を表現します。これは、あるモデルが他のモデルを複数「持っている」場合に使用されます。例えば、ブログの投稿が多くのコメントを持つ場合、`Post` モデルが `has_many` の関係にあります。これにより、1つの投稿は多数のコメントを持つことができます。

```ruby
class Post < ApplicationRecord
  has_many :comments
end
```

## 3. `belongs_to`（所属している関係）

`belongs_to` は、多対一又は一対一の関係を表現します。これは、あるモデルが他のモデルに「所属している」場合に使用されます。例えば、コメントが特定の投稿に所属している場合、`Comment` モデルが `belongs_to` の関係にあります。この関係により、1つのコメントは1つの投稿に所属します。

```ruby
class Comment < ApplicationRecord
  belongs_to :post
end
```

## まとめ

- `has_one`：一対一の関係を表現し、自分のモデルが他のモデルを1つだけ持つ場合に使用します。
- `has_many`：一対多の関係を表現し、自分のモデルが他のモデルを複数持つ場合に使用します。
- `belongs_to`：多対一又は一対一の関係を表現し、自分のテーブルが他のテーブルに所属している場合に使用します。

これらのキーワードを正しく使用することで、データベース内のデータを関連付け、効果的に操作できるようになります。Ruby on Railsの魅力の一つは、これらのリレーションシップを簡単に扱えることです。それにより、複雑なデータベース関連の作業をスムーズに進めることができます。
【海外App調査／Python】指定した国のApp store検索結果をCSV保存【ありがとうChatGPT】

## できること
- **指定した国**（今回は台湾）の、**指定キーワード**（今回は「秩父観光」）での**App store検索結果**を**CSV保存**する
- 検索結果はiTunes Search APIで取得
- CSVに保存するのは「アプリ名」「対応言語」「アプリ説明」「詳細URL」

## Pythonコード
```python:
import requests
import csv
import json

# APIからデータを取得
response = requests.get("https://itunes.apple.com/search?term=秩父観光&country=TW&entity=software")
data = response.json()

# CSVファイルを作成
with open('output.csv', 'w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file)
    writer.writerow(["trackName", "languageCodesISO2A", "description", "trackViewUrl"])

    # JSONから必要なデータを取得
    for item in data['results']:
        trackName = item.get('trackName', '')
        languageCodesISO2A = item.get('languageCodesISO2A', '')
        description = item.get('description', '')
        trackViewUrl = item.get('trackViewUrl', '')

        # CSVにデータを書き込む
        writer.writerow([trackName, languageCodesISO2A, description, trackViewUrl])

```
## アウトプット（CSV）
こんなCSVが出力されます。嬉しい。
![スクリーンショット 2023-11-08 0.02.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2519663/f000c7eb-46e7-47c9-96fa-8623b7f6a1b0.png)

## その他、参考
### ChatGPTへのプロンプト
今回もChatGPTにコードを出力してもらいました。プロンプトは下記です
```text
以下を実行するpythonコードを作成

1. 指定したitunes storeのAPIからjsonを取得する
https://itunes.apple.com/search?term=秩父観光&country=TW&entity=software

2. jsonから、以下の項目を取得してCSVとして保存
"trackName"
"languageCodesISO2A"
"description"
"trackViewUrl"
```

### 応用展開例
- URLのtermやcountryをいじれば、検索語句も国も変えられます。今回はアプリを指定していますが、曲や動画の検索結果も取得可能です。
例：https://itunes.apple.com/search?term=忘れもしませぬあれは拙僧がブリテン島でモース殿と呪いのピッチング対決をしていた頃&entity=song&country=BS
※残念ながら上の例の検索結果は0件でした
- 取得したjsonの情報量も豊富です。価格や対応機種、開発者、リリースノートのほか、動画なら出演者や監督などの情報もありそう。
- スプレッドシートに国や検索語句を並べて、人間の代わりにそれらを調べてもらうなんてできますね。時短〜。

### 国コード
https://ja.wikipedia.org/wiki/ISO_3166-1

※国コードは3文字ではなく2文字の方を使います
### iTunes Search API
https://performance-partners.apple.com/search-api
## 感想
ChatGPTすごいですね。
前回もChatGPTにコード書いてもらったので良かったらどうぞ。

https://qiita.com/a_fune/items/e08f72a36fce5c78226e
コマンドの目的と意味　uvicorn app:app --reload、docker-compose up --build

質問１　uvicorn app:app --reloadとdocker-compose up --buildは目的や意味の何が違うの？意味わからない。中学生や初学者でもわかるようにして下さい。



`uvicorn app:app --reload` は、あなたのコンピューターで直接プログラムを動かすためのコマンドです。これは、プログラムを書き換えたらすぐにそれを反映してくれるので、プログラムを作っているときに便利です。

一方で `docker-compose up --build` は、あなたのプログラムを小さな仮想の箱（コンテナと呼ばれる）の中で動かすためのコマンドです。このコマンドを使うと、他の人がどんなコンピューターを使っていても、みんな同じ環境でプログラムを動かすことができます。これは、自分のコンピューターだけでなく、他の人と一緒に仕事をするときや、プログラムをインターネットで公開するときに特に便利です。

要するに、`uvicorn` は自分で使うときに手軽で、`docker-compose` は他の人と共有したり、本格的に公開するときに使うものだと思えばいいです。


質問２　両方使用するのは問題ない？


はい、両方を使うことに問題はありませんが、通常は同じアプリケーションに対して同時に使うことは少ないです。なぜなら、それぞれ異なるシナリオや目的に適しているからです。

- **`uvicorn app:app --reload`**:
  - これはローカル開発のためのコマンドで、あなたのコンピュータのローカル環境で直接FastAPIアプリケーションを実行します。
  - コードを編集すると自動でリロード（再読み込み）され、変更がすぐに反映されるので開発が迅速に行えます。

- **`docker-compose up --build`**:
  - これはDockerを使って、アプリケーションとその他のサービス（例えばデータベース）を含む複数のコンテナを同時に起動するためのコマンドです。
  - 本番環境に近い形でアプリケーションをテストしたい時や、チームで共有する環境を作る時に適しています。

両方を使う場合は、通常は開発の異なる段階で使い分けます。たとえば、単純な開発やテストのために `uvicorn` を使い、アプリケーションが完成したり、チームメンバーと共有したい時に `docker-compose` を使用する、という流れになります。

同時に使うとポートの競合などの問題が発生する可能性があるため、通常は一方を停止してからもう一方を使用します。
TeamsからURLを開く時のブラウザを変更したい

以前まではリンクを開くときはchromeで開かれていたのですが、Teamsのアプデのせいか、必ずedgeで開かれるようになっていました、、。
今回は、
TeamsからURLを開く時のソフトを指定する方法を記載します！

---

1、Teamsの右上の ･･･ マークから、設定を開きます。

2、「ファイルとリンク」のタブを開くと、「リンクを開く設定」を設定できます。

実際にEdgeが設定されていました。
![IMG_3607.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617127/e952043b-f4da-6802-7de4-3b48eb718181.png)

ここを「既定のブラウザー」に変更することで、あらかじめWindowsで設定しているソフトでWebページを開くことができます！
![IMG_3608.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617127/2d5e0f05-d153-7a29-af0f-9e82fb98116d.png)

以上、読んでいただきありがとうございました！

---

（余談）
Qiitaを登録してから初めて記事を書いてみました！
もしこの記事をご覧の方は、いいね♡していただけると嬉しいです😊