OmniAICreator/Qiita-1.07M huggingface dataset:
ChatGPTが間違った答えしか言わない時の対処法

## はじめに
今回はChatGPTが間違った答えしか提示してくれないときの対処法を自分の実体験を交えてお話します。

これはあくまでN＝１であり、当たり前だろっていう結論なのですが、確認という意味を込めてご覧になっていただけると嬉しいです。

## 経緯
今回、`matplotlib`で書いた点線を縁取りする必要がありました。

まず日本語のGoogle検索で、それっぽいキーワードを入れて検索してみましたが、なかなかヒットしませんでした。
`matplotlib.pyplot`のドキュメントを見てもわからなかったので、ChatGPT先生に聞いてみました。



![ 2023-03-30 22.25.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/a911c6fe-d25e-000b-9fc3-1a40d7cd7da5.png)

それっぽいことを言ってくれますが、間違っていました。
この後もやり取りを重ねましたが、ダメでした。
同じやり取りをはじめから英語で行ってみましたが、こちらもダメでした。

## 解決方法
ここでGoogle検索で、日本語から英語キーワードで検索してみました。

すると、一発で解決方法(StackOverflow)が見つかりました。(点線を縁取りするといった記事ではありませんでしたが、応用すれば解決できました)

## 所感
うーん。これならいつも通りだし、ChatGPTにかけた工数が無駄になったなぁ。。。

今回ChatGPTができなかったタスクは、(1)日本語の解説記事がなく、(2)英語のサイトでも**完璧に**ヒットした内容がないことから、比較的マイナーな内容であったといえます。

そこで自分の現段階の戦略は、**日本語で調べて出てこないような内容は、ChatGPTに聞かずに英語で調べる**に設定します。

あくまでN=1なので参考程度に見ていただけると幸いです🙇‍♂️
VaultでAWSシークレットを使う方法


AWSシークレットエンジンは、IAM ポリシーに基づいて AWS の認証情報を動的に生成します。
AWS マネジメントコンソールを操作する必要がないため AWS IAM の運用が少しだけ容易になります。

参考文献はこちら

https://developer.hashicorp.com/vault/docs/secrets/aws

## AWSシークレットエンジン
### まずは現状確認
```
vault secrets list
```

### AWS シークレットエンジンを有効に
```
vault secrets enable aws
```
-path をつけることでpathを指定できますが、今回は割愛


```
vault secrets list

Path          Type         Accessor              Description
----          ----         --------              -----------
aws/          aws          aws_hoge         n/a
```

### AWS シークレットエンジンTTL設定変更
```

# TTL（Lease）をデフォルト768 時間 → 30分 に変更
vault write aws/config/lease lease=30m lease_max=30m

Key          Value
---          -----
lease        30m0s
lease_max    30m0s

```
Vault によって生成された AWS IAM の認証情報にはリース期間が設定され、その期間が経過すると自動的に失効します。

認証情報はいつでも管理者により取り消すことができます。

### AWS シークレットエンジン認証情報設定
```
# 事前に環境変数は設定しておいてください
# （Vault起動時のrootTOKEN）
echo $VAULT_TOKEN
# （IAMのKEY情報）
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY

# AWS 認証情報を設定
vault write aws/config/root \
  access_key=$AWS_ACCESS_KEY_ID \
  secret_key=$AWS_SECRET_ACCESS_KEY \
  region=us-west-1
```

### AWS接続用の Vault のroleの作成
Vaultでは任意のロールを作成し、AWS のパーミッションのセットと AWS のクレデンシャルタイプをそのロールにマッピングします。
クレデンシャルを生成する際は、事前に定義したroleに対してリクエストします。

今回の内容はこんなもの
role名：my-role
credential_type：iam_user
IAM ポリシー： { "Version": "202303" } 以下
EC2 へのフルアクセス
```
# role作成
vault write aws/roles/my-role \
        credential_type=iam_user \
        policy_document=-<<EOF
{
  "Version": "202303",
  "Statement": [
    {
      "Sid": "Stmt1426528957000",
      "Effect": "Allow",
      "Action": [
        "ec2:*"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}
EOF

```

### AWS CLI をを取得しておきましょう
```
apk --no-cache add binutils curl
curl -sL https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-2.33-r0.apk
curl -sLO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.33-r0/glibc-bin-2.33-r0.apk
apk add --no-cache glibc-2.33-r0.apk glibc-bin-2.33-r0.apk
curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o awscliv2.zip
unzip -q awscliv2.zip
aws/install
```


####  IAM ユーザーをリストアップ
```
# IAM ユーザーList
aws iam list-users

# ロール (my-role) のすべてのアクティブなリース
vault list sys/leases/lookup/aws/creds/my-role

```

### roleに紐づくクレデンシャルを生成
```
vault read aws/creds/my-role
```
#### Vault UIで生成するには
Vault UI ログイン後、aws/ シークレットエンジンをクリックし、my-role ロールを選択。「Credential type」に「IAM User」を指定して、「Generate」をクリック


### クレデンシャルを破棄
```
# lease_id には破棄するIDを指定
vault lease revoke aws/creds/my-role/"<lease_id>"
```
スプレッドシートにテンプレート文字列を書いてプレビューを確認する

例えばスプレッドシートからGoogle Apps Scriptでメールを送信するとき、メール文面を柔軟に変更できると便利です。そこで、テンプレート文字列をセルに直接記述し、そのプレビューを別のセルで確認できるようにしてみます。文面をスプレッドシート上で工夫できるようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6760/4bc77959-9e53-7731-bec6-50868e43735b.png)

## テンプレートの例

テンプレートとして、以下の文字列を準備します。変数`nickname`と`date`を使っています。変数は`{{`と`}}`で囲います。

```
ようこそ、{{nickname}}さん！
今日は{{date}}です！
```

## スプレッドシートの準備

変数は、変数名と値を並べて書きます。
テンプレート文字列もセルに記述しておきます。

| | A | B | C | 
|---|---|---|---|
| 1 | 変数1 | nickname | ほげほげ |
| 2 | 変数2 | date | =TEXT(TODAY(), "yyyy年m月d日") |
| 3 | テンプレート | ようこそ、... |
| 4 | プレビュー | （プレビューをここに表示） | | 

- セル`B1`に変数`nickname`を、セル`C1`にその値として`ほげほげ`と入力します。
- セル`B2`に変数`date`を、セル`C2`にその値として`=TEXT(TODAY(), "yyyy年m月d日")`と入力します。
- セル`B3`にテンプレート文字列を記述します。
- セル`B4`に、テンプレートに変数を適用した結果を表示します。

セル`B4`には`RENDER`関数を入力します。引数は2つで、変数の領域`B1:C2`と、テンプレートのセル名`C3`です。では`RENDER`関数を実装していきましょう。

## RENDER関数の準備

スプレッドシートの上部メニュー `拡張機能` > `Apps Script` を選択し、スクリプトエディターを起動します。以下のコードを記述して保存します。

```javascript:Code.gs
function RENDER(template, rows) {
  let result = template;
  rows.forEach(row => {
    const [ variable, value ] = row;
    result = result.replace(new RegExp('{{' + variable + '}}', 'g'), value);
  });
  return result;
}
```

スプレッドシートに戻り、セル`C4`で`RENDER`関数を呼び出します。

| | A | B | C | 
|---|---|---|---|
| 4 | 結果 | =RENDER(B1:C2, C3) |

するとセル`C4`に以下のように表示されます。

```
ようこそ、ほげほげさん！
今日は2023年3月30日です！
```
【備忘録】Windows・macで文字を入力中、急に出てくるあれって何？

# 概要

Macだとこれ。
![スクリーンショット 2023-03-30 21.54.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/3eadabb9-758e-1459-7fb9-2416c9aaab59.png)

Windowsだとこんな感じで左上に出るやつ
![スクリーンショット 2023-03-30 21.57.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/b0d4285d-f2fb-272b-3d5d-dfa18fac6c1a.png)

これの出現条件は、以下の時。

# デスクトップなど入力できないところにカーソルがあり、日本語入力になっている時に起きる。
デスクトップ以外でも、他にPC上のさわれないところ（フォルダの選択する箇所でないところとか）
を選択（フォーカス）していたりすると、表示されたりする。

![スクリーンショット 2023-03-30 22.04.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/b096138f-d108-d335-e474-e435610fd5fe.png)

![スクリーンショット 2023-03-30 22.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/4a971d49-e142-f392-be74-4a03d01b7973.png)


なので、wordを使っていてる途中、間違ってデスクトップをクリックしたりする時に出てくると思われる。
すぐに入力された文字を消す時は、`Esc`を押せば中身は消える。入力先のアプリがちゃんと選択されているかを確認しよう。

# そもそもの使用用途は？

# 結論、デスクトップをマウスを使わずに操作するために使う
うまく使いこなせば、マウスを動かさずにファイルを開けるからすごい楽になる。

1. デスクトップ上で、開きたいフォルダがあるとする。そこで、デスクトップにカーソルを当てて（何もないところをクリックした後）、フォルダの名前を入力する
1. 被りの名前がないなら、数文字いれるだけで候補に出してくれるはず。
1. その後、Macなら`command + o`、Windowsなら`enter`を押すと、対象のフォルダやファイルを開くことができる。
    1. この時、ファイルやフォルダが日本語なら、さっきのように日本語を選択する。
    1. アルファベットなら、英語で入れてあげることで、英語のフォルダやファイルを検索することができる。

![名称未設定.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1288524/8427ee2b-4b52-7367-d698-3eff6e7f018a.gif)
Nanopi Neo 2とArmbian Bullseyeの組み合わせでGPIOを使う

# はじめに

いきなり入手できなくなったRaspberry Piの代替として注目していたNanopi Neo 2ですが、こちらもいきなり入手できなくなりましたね。涙

そんな中、Nanopi Neo 2のOSをArmbian 23.02 BullseyeにしたらGPIOが使えなくなってしまいました...涙
色々なところで紹介されているWiringNPをインストールしても「これはNanopi Neo 2ではない！！」と怒られてしまいます。

ということで、Nanopi Neo 2でGPIOを使えるようにした顛末をメモ。

# Armbian

以下のURLからダウンロード

https://www.armbian.com/nanopi-neo-2/

# GPIOのチェック

使用できるGPIOの情報を確認

```sh
cat /sys/kernel/debug/gpio
```

使えるGPIOの一覧を確認

```sh
cat /sys/kernel/debug/pinctrl/*/pinmux-pins
```

...なんだかよくわからない。

# コマンドラインで使う

前述のGPIOの一覧から、8番ピンを入力として使用する場合は198という番号を指定するようです。

```sh
echo 198 > /sys/class/gpio/export
echo "in" > /sys/class/gpio/gpio198/direction
```

入力の接点をON / OFFしながら動作を確認。

```sh
cat /sys/class/gpio/gpio198/value
```

動いているみたい。
ちなみに、以下の表示で"in"となっていても明示的に"in"と指定しないと値が入ってこない。

```sh
cat /sys/class/gpio/gpio198/direction
```

使用を終了する。

```sh
echo 198 > /sys/class/gpio/unexport
```

# Python3で使う

ここでは、8番ピンと10番ピンを入力、16番ピンと18番ピンを出力として利用することとします。

## 参考

以下のURLを参考にさせて頂きました。

https://blog.goediy.com/?p=1594


## 準備

必要なソフトウェアやライブラリをインストールします。

```sh
apt install -y python3-pip
pip3 install OPi.GPIO
```

## 実行

```py
import OPi.GPIO as GPIO
import time

# Nanopi NEO 2用の設定
GPIO.BOARD = {
    7:    203,   # PG11
    8:    198,   # PG6
    10:   199,   # PG7
    11:   0,     # PA0
    12:   6,     # PA6
    13:   2,     # PA2
    15:   3,     # PA3
    16:   200,   # PG8
    18:   201,   # PG9
    19:   20,    # PC0
    21:   65,    # PC1
    22:    1,    # PA1
    23:   66,    # PC2
    24:   67     # PC3
}

# 割込発生時の処理
def callback(channel):
    print("button pushed %s"%channel)

# 初期設定
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)

# 入力の指定
GPIO.setup(8, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.setup(10, GPIO.IN, pull_up_down=GPIO.PUD_UP)

# 信号入力時の動作を指定
GPIO.add_event_detect(8, GPIO.FALLING, callback=callback, bouncetime=300)
GPIO.add_event_detect(10, GPIO.FALLING, callback=callback, bouncetime=300)

# 出力の指定
GPIO.setup(16,GPIO.OUT)
GPIO.setup(18,GPIO.OUT)

# 入力確認
GPIO.input(8)

# 出力と結果の確認
GPIO.output(18,GPIO.HIGH)
GPIO.input(18)

# 1秒待機
time.sleep(1)

# 出力と結果の確認
GPIO.output(18,GPIO.LOW)
GPIO.input(18)
```

できた〜！
【Python】VSCodeでPEP8に沿ったプログラムを書く

## はじめに
vscodeには、Pythonの標準コーディングスタイルであるPEP８に準拠したフォーマッタツールが用意されています。それらを使用するための設定を行いました。

## 参考記事
[【Lint】vscodeでpep8のチェックをする手順【Python】](https://qiita.com/SyogoSuganoya/items/152b96249debe0ed6ec5)
[[python PEP8] VSCodeでautopep8とflake8を適用する](http://trelab.info/visual-studio-code/python-vscode%E3%81%A7autopep8%E3%82%92%E9%81%A9%E7%94%A8%E3%81%99%E3%82%8B/)

## autopep8の適用
上記記事の手順に従ってautopep8のインストールと設定を行ました。
保存時のフォーマットも有効化しました。
![スクリーンショット 2023-03-30 21.42.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219028/846299f1-f3d2-1481-6d14-e3fcb1f2647b.png)
ファイル保存時に下記のようにフォーマットしてくれます。
```python
# 保存前
a = [1,2,3,4]

# 保存後
a = [1, 2, 3, 4]
```

## flake8の適用
上記記事で参照されている記事の手順に従ってflake8のインストールと設定を行ました。
ファイル保存時、コーディング規約に違反したコードに波線が引かれています。
![スクリーンショット 2023-03-30 22.11.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219028/09dab43a-785e-6335-94fe-9f185cb5c8b3.png)


## 設定後のsettings.json
```json
{
    "editor.formatOnSave": true,
    "python.linting.flake8Enabled": true
}
```
【学習記録】JavaScript

### 教材 : Udemyガチで学びたい人のためのJavaScriptメカニズム

##### 【HTMLをブラウザに表示させる】
##### 〜ファイルの作成からブラウザ上にアラートを表示させるまで〜
①vscodeでhtmlファイルとjsファイルを作成<br>
②htmlファイルで'!'を入力してTabキーを押す
![スクリーンショット 2023-03-30 21.34.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/d4edc259-e1c4-2c95-a018-002330a2e77a.png)
↓するとテンプレートが自動生成される
![スクリーンショット 2023-03-30 21.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/7d3413ce-3fb0-ba08-51d0-0608733e5ef5.png)
③bodyタグにjsファイルを読み込むスクリプトを記述
```
<script src="main.js"></script>
```
↓これでjsをhtml側に呼び込むことができる
![スクリーンショット 2023-03-30 21.35.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/40668cb1-958d-5a76-ead5-9646cf206137.png)
④jsにテスト記述
js側び特段設定は必要無いが、ブラウザにコードが表示できているか確認する為、テストコードを記述する
![スクリーンショット 2023-03-30 21.44.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/69f97aef-452b-a092-ffa1-158372e534e6.png)
⑤htmlファイル内にて右クリック→Open with Live Serverを選択する
![スクリーンショット 2023-03-30 21.27.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/b0859a8b-73b4-90a8-923c-81eb00018583.png)
⑥ブラウザで内容を確認
alertのステートメントが実行されていることを確認
![スクリーンショット 2023-03-30 21.53.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/53e1c4b4-accc-87fd-bdbc-1a292b360f11.png)

##### 〜コンソールの確認〜
①jsで以下のテストコードを記述
![スクリーンショット 2023-03-30 22.03.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/2f302114-30f6-9fe5-181c-bb25df573349.png)


②Live Serverを起動→ブラウザで右クリックし"検証"を選択
![スクリーンショット 2023-03-30 21.59.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/4f274012-c1bb-c846-cdda-8ae846f8f835.png)
③開発ツールが出るので"コンソール"を選択する
![スクリーンショット 2023-03-30 22.02.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/780d359e-2743-fdfc-8b9b-8fd9d8e3dc79.png)
④コードが出力されている状態を確認
![スクリーンショット 2023-03-30 22.05.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3090837/0aad6629-5a08-28bb-e7da-eb42c8fd05de.png)

※Live Serverの起動は初回のみでOK。以降はファイルを更新→保存を実行すると自動的にブラウザの表示も更新される
React Tutorial備忘録


# Introduction

`React`未経験の私が学んだことを書き連ねます。
公式チュートリアルをベースに学習しています。

**本記事が少しでも読者様の学びに繋がれば幸いです！**
**「いいね」をしていただけると今後の励みになるので、是非お願いします！**

## render とは?

- コンポーネントの出力（UI の表示）を行うためのメソッド。
- 各コンポーネントはプロパティ(`props`)および状態(`state`)を受け取り、UI をレンダリングします。

## props とは?

- 親コンポーネントから子コンポーネントに渡される値のこと。
- 読み取り専用。
- コンポーネント内では変更不可。
- コンポーネント間の情報の受け渡しに使用されます。

## state とは？

- `Reactコンポーネント`内で管理される変数のこと。
- コンポーネントの状態を表し、ユーザーの操作やイベントに応じて動的に変更可能。
- コンポーネントが再レンダリングされる際に更新され、UI に反映されます。
- コンポーネントの`constructor`内で初期化され、`setState`メソッドで変更されます。

```console
class Square extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      value: null,
    };
  }
  render() {
    return (
      <button
        className='square'
        onClick={() => {
          this.setState({ value: 'X' });
        }}
      >
        {this.state.value}
      </button>
    );
  }
}
```

## UI をレンダリングとは？

- `Reactコンポーネント`を基に、ブラウザ上に HTML 要素を生成して Web ページを構築すること。
- `render`メソッドから JSX を通じて、ブラウザ上に表示される要素が生成されます。
- これにより、`Reactコンポーネント`を使用して Web ページの UI を構築することができます。

## イベントハンドラの仕様

- `React`では、イベントハンドラ内の`this`は自動的にバインドされません。
- 以下のようなコードでは、`this.props.value`が参照できずにエラーになります。

```console
<button
  className='square'
  onClick={function () {
    console.log(this.props.value);
  }}
>
```

- アロー関数を用いて、イベントハンドラの定義が必要です。
- 以下のようなコードであれば、クリックイベント内の`this`が正しくバインドされ、`this.props.value`の参照が可能になります。

```console
<button
  className='square'
  onClick={() => {
    console.log(this.props.value);
  }}
>

```

## 参考 URL

[React tutorial](https://ja.reactjs.org/tutorial/tutorial.html 'React Tutorial')
現場でよく使うGitコマンドまとめ

# よく使うGitコマンドを自分用にまとめておく

## 初期設定
```bash
git config --global user.name "[your-name]"
git config --global user.email "[your-email]"
git config --global core.editor 'vim -c "set fenc=utf-8"'
git config --global color.diff auto
git config --global color.status auto
git config --global color.branch auto
git config --global core.precomposeunicode true
git config --global core.quotepath false
```

## 基本

### 既存のgitリポジトリのコピーを取得
```bash
git clone [repository-url] ./[project-name]
```

### ファイルをステージに上げる
```bash
git add [file-name]
```

### ステージに上がっているファイルをコミット
```bash
git commit -m "commit message."
```

### ファイル名変更
```bash
git mv [old-file-name] [new-file-name]
```

### ファイル削除
```bash
git rm [file-name]
```

### コミットログ表示
```bash
git log
```

### 変更の取り消し
```bash
git checkout [file-name]
```


## 開発の一連の手順

### ローカルbranchを作成して修正した内容をリモートリポジトリにpushする
```bash
git clone [repository-url] ./[project-name]
cd [project-name]
git checkout -b [branch-name]
# 何かしら修正
git add .
git commit -m "commit message."
git push origin [branch-name]
```

## branch系

### branchを新規作成してそのbranchに移動する
```bash
git checkout -b [branch-name]
```

### リモートbranchをローカルbranchにcheckoutする
```bash
git checkout -b [branch-name] origin/[branch-name]
```

### branchの一覧を見る
```bash
git branch -a
```

## rebase系

### mainの内容を開発ブランチに反映させる
```bash
git checkout main
git pull
git checkout [branch-name]
git rebase main
# conflictが発生した場合は[conflict-file]を修正して解消する
git add [conflict-file]
git rebase --continue
# conflictが無くなるまで繰り返す
git log
# commit履歴を確認
git push -f origin [branch-name]
```

衝突を解消した後は ``git add [conflict-file]`` の後に ``git rebase --continue`` を実行します。
rebaseの場合はconflictを直したらaddしてcommitではなくてrebase --continueします。
rebaseを行ったあとは、branchを普通のpushではなくforce pushする必要があります。
コマンドは上記の通り。

### rebaseを諦める
gitのリポジトリは``git rebase``を実行する前に戻ります。

```bash
git rebase --abort
```
[Go言語] スライス初心者ガイド: 空のスライスとnilスライスを理解する

### はじめに
Go言語では、スライスは非常に便利なデータ構造であり、頻繁に使用されます。
しかし、空のスライスとnilスライスの違いや使い分けについて混乱することがあります。
少し気になったので、調べてみたのでここでまとめます。

### 空のスライスとnilスライスの定義
まず、空のスライスとnilスライスを定義する方法を見てみる。

```go
files1 := []string{}
files2 := []string
```

files1は、空の文字列スライスで、長さ0、容量0です。
files2は、nilスライスで、同じく長さ0、容量0ですが、内部的にはnilとして扱われます。

### 違いについて

**nilチェック**：nilスライスと空のスライスは、nilチェックで区別されます。
nilスライスは初期化されていない状態を示すことが多いため、このチェックを使って初期化処理を行うことができます。

```go
if files == nil {
    // filesはnilスライス
} else {
    // filesはnilでないスライス（空のスライスも含む）
}
```

**JSONマーシャリング**：nilスライスと空のスライスは、JSONマーシャリング時に異なる表現になります。空のスライスはJSON配列（[]）として表現されるのに対し、nilスライスはJSONのnullとして表現されます。

```go
jsonFiles1, _ := json.Marshal(files1) // files1 JSON: []
jsonFiles2, _ := json.Marshal(files2) // files2 JSON: null
```

### 使い分けについて
一般的には、nilスライスと空のスライスのどちらを使うかは、プログラムの要件や設計に依存します。
たとえば、スライスの初期化状態を明示的に表現する必要がある場合は、nilスライスを使用することが適切です。
また、JSONデータを扱う際に、空の配列とnullの区別が重要になる場合もあります。

### まとめ
この記事では、Golangにおける空のスライスとnilスライスの違いと使い分けについて説明しました。
どちらのスライスも長さと容量が0であり、要素の追加や操作には同じように振る舞います。しかし、以下の点で違いがあります。

**nilチェック**：nilスライスと空のスライスは、nilチェックで区別されます。nilスライスは初期化されていない状態を示すことが多いため、このチェックを使って初期化処理を行うことができます。
**JSONマーシャリング**：nilスライスと空のスライスは、JSONマーシャリング時に異なる表現になります。空のスライスはJSON配列（[]）として表現されるのに対し、nilスライスはJSONのnullとして表現されます。
使い分けに関しては、プログラムの要件や設計に依存します。スライスの初期化状態を明示的に表現する必要がある場合や、JSONデータを扱う際に空の配列とnullの区別が重要になる場合など、適切なスライスを選択することが重要です。

Golangにおいてスライスは非常に便利なデータ構造であるため、空のスライスとnilスライスの違いを理解し、適切に使い分けることで、より効果的なコードを書くことができます。

https://go.dev/blog/slices-intro

https://stackoverflow.com/questions/44305170/nil-slices-vs-non-nil-slices-vs-empty-slices-in-go-language

https://freshman.tech/snippets/go/nil-vs-empty-slices/
超初心者がPHPerKaigi2023に参加して思ったこと

#### 初めて記事を投稿するので拙い部分が多々あるかと思います。アウトプットの練習だ！

## 伝えたいこと
超初心者でも業務未経験でも、テックカンファレンスで学べることはたくさんある！そしてすごく楽しかった！

## 楽しかったこと・嬉しかったこと
・技術が分からなくても講演が面白かった。人の心を掴む工夫がなされていて、自分もいつか登壇したら、笑わせながら話せる人になりたいなと思いました。
・グッズがとにかくたくさんあって、可愛くてテンション上がった。こんな風にも楽しめるなんてテックカンファレンスという名からは想像つきませんでした。
・オフライン参加楽しすぎた。カンファレンスの空気をリアルタイムで感じて、みんなと同じ温度感で楽しめる。まさかのLT登壇では推し色でサイリウムを振るという。盛り上がらずにはいられませんでした。
ツイートに反応をもらえたのが嬉しすぎた。心境をツイートすると参加者がいいねしてくれたりリプくれたり。アイコンやツイート内容で認知されてたこともあったので、オフライン参加においてTwitterはかなり大事なんだなと実感しました。
・とにかくみんな優しい。懇親会で誰かが誰かに紹介してくれる連続で、多くの方とお話しできました。閉会後も、二次会に行きたい人たちが自然に集まっていて、人と繋がることってこんなに簡単だったけ？！と感動しました。
・みんながたくさん褒めてくれる。特に私は行動力を褒めてもらえて、とても自信になりました。勇気を出してぺちぱー会議に参加してよかった、アンカンファレンスでの自己紹介LTに参加してよかった！！

## 頑張ったこと
・初心者で参加したこと。無知だからこそ飛び込める！恥をかいてもいい！と行動しました。
・自己紹介LTに参加！day0から参加していたにも関わらず誰とも話せていなかったので、意を決して参加しました。本当に簡単な自己紹介と、みんなと話したい、といった内容。その後、一人に話しかけられ、人がだんだん増え、集まって輪ができた！！！そこでいろんな方とお話しできたことがきっかけで、懇親会では積極的に話しかけに行くことができました。

## 工夫したこと
・事前に決めておいた質問をいろんな人にすることで、多種多様なアドバイスをもらえました。
・自己紹介LTで、スライドを即座に用意するスキルがなかったので、Notionをスクロールして発表しました。

## 反省点
・よく聞かれる質問の回答を決めておくべきだと思った
なんでこの業界に転職しようと思ったの？って質問に、その場で簡潔に答えられませんでした。自分の中ではいろんな理由があって、それをあまり整理していなかったために、正解の答え方が欲しいなと思いました。ぐだぐだ喋っちゃうので！
・自己紹介の中身を決めておくべきだと思った
特に趣味の話はいろんな場面で会話を広げられるので、即座に話せるように準備しておきたいなと思いました。

## まとめ
イベントに参加したいけど、技術について話せないからなあ…と迷っている方は、ぜひ参加してみてください！
python maya reference set namespace and transform

https://github.com/aizwellenstan/maya_python_ass

```python
import pymel.core as pm
import json
import sys
import os

standins = pm.ls(type='aiStandIn')
standinTransforms = [pm.listRelatives(standin, parent=True, f=True)[0] for standin in standins]

assXYZ = {}
missing = []
lightRoot = "J:/xkx/work/lib/lig_set/PR/"
for standin, transform in zip(standins, standinTransforms):
    xformDict = {}
    xformDict['tx'] = transform.tx.get()
    xformDict['ty'] = transform.ty.get()
    xformDict['tz'] = transform.tz.get()
    xformDict['rx'] = transform.rx.get()
    xformDict['ry'] = transform.ry.get()
    xformDict['rz'] = transform.rz.get()
    xformDict['sx'] = transform.sx.get()
    xformDict['sy'] = transform.sy.get()
    xformDict['sz'] = transform.sz.get()

    filename = standin.dso.get().split("/")[-1]
    if 'MA' in filename:
        index = filename.find('MA') + 2  # Find the index of the 'MA' substring and add 2 to skip over it
        digits = filename[index:index+3]  # Extract the 3 digits starting at the index
        if digits.isdigit():  # Check if the extracted substring consists only of digits
            print(digits)
        else: continue
    else: continue
    assName = "MA"+digits+"Night"

    nodeName = transform.name().split("_")[-1].split("|")[-1]
    new_name = str(ass_name + "_" + node_name).replace(":", "")

    lightFolder = lightRoot+assName
    if not os.path.isdir(lightFolder): continue
    maFile = lightFolder+"/"+assName+"_light.ma"
    refNode = pm.createReference(maFile,  namespace=new_name)
    lightGrp = pm.ls(new_name+":*",assemblies=True)[0]
    lightGrp.setTranslation([xformDict['tx'], xformDict['ty'], xformDict['tz']])
    lightGrp.setRotation([xformDict['rx'], xformDict['ry'], xformDict['rz']])
    lightGrp.setScale([xformDict['sx'], xformDict['sy'], xformDict['sz']])
```
React ラジオボタンの実装

# 成果物
今回はラジオボタンを用いて性別を選択する簡単なプログラムを作成しました。

https://codesandbox.io/embed/raziobotan-arenzi-0dydr7?fontsize=14&hidenavigation=1&theme=dark

# コード
## index.js
```javascript
import { StrictMode } from "react";
import { createRoot } from "react-dom/client";

import App from "./App";

const rootElement = document.getElementById("root");
const root = createRoot(rootElement);

root.render(
  <StrictMode>
    <App />
  </StrictMode>
);
```

## App.js
```javascript
import React, { useState } from "react";
import "./styles.css";

// ラジオボタンにセットしたい項目の配列itemsを設定
const items = [
  { id: 1, item: "男性" },
  { id: 2, item: "女性" },
  { id: 3, item: "どちらでもない" },
  { id: 4, item: "選択しない" }
];

// props(値)を受け取らない場合、const RadioButtonItems = items.map((item) => { return (...)})
// 親コンポーネントInputRadioからprops(handleChange, checkedValue)を受け取る
const RadioButtonItems = (props) =>

  // map()で配列itemsから要素を1つずつ取り出し、値を設定する
  items.map((item) => {
    return (

      // key属性にitem.idを設定する
      <label key={item.id}>
        <input
          type="radio"

          // value属性に取り出した要素のitemを設定する
          value={item.item}

          // ラジオボタンが押された際に、関数handleChangeが実行される
          // ラジオボタンが押された際に、状態変数checkedValueの値が更新される
          // その際にcheckedValueに設定される値は、押されたラジオボタンのvalue属性
          onChange={props.handleChange}

          // checked属性を指定されたラジオボタンが初期状態でチェックされた状態になります
          // props.checkedValueの初期値はitems[0].itemなので「男性」になります
          // よって最初にチェックされているラジオボタンは「男性」になります
          // この状態でchecked属性を取り除くと全て選択できるラジオボタンができてしまうのでcheckedは必須です
          // ラジオボタンの初期値を設定したくない場合、
          // name属性を追加することで初期値を設定せず、通常のラジオボタンの挙動になります
          checked={props.checkedValue === item.item}
        />
        {item.item}
      </label>
    );
  });

const InputRadio = () => {
  
  // 選択されたラジオボタンの状態checkedValue
  // ラジオボタンの状態を更新するsetCheckedValue
  // 初期値はitems[0].item = 男性  
  const [checkedValue, setCheckedValue] = useState(items[0].item);

  // ラジオボタンが押された際に実行される
  // 押されたラジオボタンのvalue属性の値を取得
  const handleChange = (e) => setCheckedValue(e.target.value);

  return (
    <div className="App">
      <p>
        性別を選択してください:<b>{checkedValue}</b>
      </p>
      
      // 子コンポーネントRadioButtonItemsにhandleChange, checkedValueを渡す
      <RadioButtonItems
        handleChange={handleChange}
        checkedValue={checkedValue}
      />
    </div>
  );
};

export default function App() {
  return <InputRadio />;
}
```

## styles.css
```css
label {
  display: block;
}
```
自宅でネットワーク構築（初心者）

ネットワークの保守/運用をしているkodanetです。
今回は設計/構築業務へステップアップしてみたいため、ネットワークの構築を簡単にやっていこう
と思います。
ネットワーク初心者なので成長日記的な感覚で書いていきます。

<筆者スペック>
新卒の会社を2か月で辞め、ネットワーク保守/運用業務をやり始めて半年経ちます。
資格は一つも持ってません。これから取る予定です。
IT未経験文系大学出身。

<構築方法>
構築はおろかネットワークの知識が全くないため、様々な記事を参考にして構築していきます。
私の家は、貸出モデム⇒PC、ゲーム機器、iPhoneなどの一般的な家庭ネットワーク環境です。
貸出モデムには無線LAN機能がありますが、今回は勉強として無線LAN機能無しの場合で考えていきます。
貸出モデム⇒Wi-Fiルータ⇒PC、ゲーム機器、iPhoneで構築していきたいと思います。

<細かいところ>
アクセスポイントのステルス化。
IPアドレスの固定。（いらないが勉強の一環として）

<さいごに>
次回はお金を貯めてルータ購入後に更新したいと思います。
IPアドレスの割り振りなどできたらなと思います。
ほかにも意見などございましたらお待ちしております。
Open API の GPT-4が使えるようになったので、Pythonで使ってみた

# はじめに

open ai の waitlistが順番が回ってきたという感じのメールが来たので、gpt4を使ってみた。

この記事はその備忘録

# コード

```python
import os
import pprint
import openai

openai.api_key = os.environ['OPEN_API_KEY']

response = openai.ChatCompletion.create(
    model="gpt-4",
    messages=[
        {"role": "system", "content": "専門家のようふるまってください"},          # チャットの設定
        {"role": "system", "content": "１００字～３００字程度で説明してください"}, # チャットの設定
        {"role": "user", "content": "日本について説明してください"}, # 入力値
        {"role": "assistant", "content": "日本は、東アジアに位置する国であり、四季のはっきりとした気候が特徴です。人口は約１２７００万人で、首都は東京です。歴史的には、古代から幕末に至るまで、多くの文化的・経済的な交流があり、その中で独自の文化が発展してきました。現在は、自動車や家電製品、アニメや漫画などのコンテンツ産業など、多様な分野で高い技術力を持ちます。また、世界中から多くの観光客が訪れ、伝統的な祭りや風習、美しい自然、最新技術が織りなす都市風 景など、多彩な魅力を持つ国として知られています。"}, # 返答値
        {"role": "user", "content": "そのコンテンツ産業について説明してください"} # 入力値
    ],
)
pprint.pprint(response)
```

# 解説

`os.environ['OPEN_API_KEY']` は任意のキーを入れます。

`model` は、`gpt-4`のほかに`gpt-3.5-turbo`等が使用できます。

`messages` は、送るテキストです。会話の累積をすべて送る形にすると、ChatGPTのような感じで会話ができます。
ーー`system` は会話を始める前の設定みたいなものです。
ーー`user`   はユーザが入力したテキストです。
ーー`assistant` はレスポンスのテキストを入れます。

応答形式は、以下のようになっています。

```js
{
 'id': 'chatcmpl-6p9XYPYSTTRi0xEviKjjilqrWU2Ve',
 'object': 'chat.completion',
 'created': 1677649420,
 'model': 'gpt-3.5-turbo',
 'usage': {'prompt_tokens': 56, 'completion_tokens': 31, 'total_tokens': 87},
 'choices': [
   {
    'message': {
      'role': 'assistant',
      'content': 'The 2020 World Series was played in Arlington, Texas at the Globe Life Field, which was the new home stadium for the Texas Rangers.'},
    'finish_reason': 'stop',
    'index': 0
   }
  ]
}
```

pythonでレスポンスのテキストのみを取得するには以下のようにします

```python
response.choices[0]["message"]["content"].strip()
```

# 参考

https://platform.openai.com/docs/guides/chat/introduction
学生エンジニアの交流会に参加して感じたこと

こんにちは。

名古屋工学院専門学校の湯澤と申します。

先日、東海地方の学生団体の交流会
エンジニアカンファレンス2023に行ってきました。
ためになることを学んだので、
自分への復習も兼ねてアウトプットさせていただきます。

# この交流会について
この交流会はCyberAgentさん（以下、CAさん）協賛、
SAIBASHIさん主催の、学生エンジニアとCAさんの社員さんとの交流会です。名古屋で行われました。
今回で第二弾の開催らしく、参加人数は約40人ほど。

詳細が気になる方は、Twitterで
[#CA学生団体コラボ](https://twitter.com/search?q=CA%E5%AD%A6%E7%94%9F%E5%9B%A3%E4%BD%93%E3%82%B3%E3%83%A9%E3%83%9C&src=typed_query)
で見ていただければと思います。

それでは本題に入っていきます。

# 感想
とても刺激的でした。
LT会では、開発や就活でためになる話だったり、交流会では年代の近い方々と技術の話で雑談できたり、Twitter交換できたり（笑）、コミュニティのすばらしさを体験することができました。

LT会や交流会で聞いた内容がためになったので、アウトプットさせていただきます。

### 技術面

#### Nerf
ニューラルネットワークを用いて、開発された技術。
複数の写真から3DCGや3Dモデルを生成可能。
特徴として、
・写真に写ってないところも補完して、生成してくれる。
・視点が自由に移動する立体感のあるCGが作れる。
・オブジェクトの解像度も高い。
・2020年に発表された技術で、比較的新しい。

写真からハイクオリティなCGを生成できる技術すごすぎる、、、

#### LumaAI

Nerfを組み込んだAIで、web版とIOS版(ベータ版)で使用可能。

#### 拡張機能の作り方

webと同じ技術で作成できる。
というのも、極論html,css,jsとmanifestファイルがあれば作ることができる。

### ISUCON

Iikanjini Speed Up Contest（いい感じに スピードアップ コンテスト）
略して、ISUCONと呼ばれるコンテストがあるらしい。
与えられた時間内で、渡されたwebアプリケーションをとにかく高速に書き換える競技。
SQLを書き得たり、OS、ミドルウェアのチューニングをしてとにかく早くするのが目的。


### 就活面

CAさんに新卒で入った方が登壇されていて、その方が実際に働いて感じたことを説明されていました。

就活のポイント
・会社選び
・技術力
・技術力以外の強み

#### 会社選び
じぶんのやりたい業務、会社の雰囲気や勤務形態（社風）が自分にマッチしているか。
理念や方針に共感できるか。
企業研究して深堀る必要がある。

#### 技術力
エンジニアたるもの、技術力を磨くのは当然。
技術力で自信のない人は、就活より**技術を磨くこと**を優先すべき。

企業によってはコーディング試験もあるので、アルゴリズム力を鍛えておく。
目安としてatcorder B,Cあたりあればよさそう。
#### 技術力以外の強み
技術はもちろん、技術以外の強みを見つけておくこと。
例えば、
・コミュニケーションが得意
・マネジメントが得意
・創造力が高い
・デザインの知識が豊富
など、
強みに強みがかかれば、**希少性**を見出すことができる。


### 開発面
開発する上で重要なことについて述べられていたので、アウトプットさせていただきます。

#### HRT

HRTとは？
team geekという本に書かれている言葉。
優秀なチームが協力するときに重要視している項目。
Humility,Respectly,Trustの三単語から構成。

#### Humility
謙虚、謙遜という意味。
謙遜することで、自分の伸びしろに限界を決めない。
別の職種の人や、年下の人からもしっかりと知識を取り入れる。

天狗にならずに、貪欲に知識を吸収していくことが大事。


#### Respectly
相手を尊敬すること。
尊敬することで、コミュニケーションがしやすくなる。
尊敬して接することで、相手からも尊敬されやすくなる。

人間関係を築くうえでとても大事。自分から信頼するように心がけること
#### Trust
相手を信頼しよう。

自分が仕事を任せた時は、相手がしっかりやってくれると信じて、
逆に仕事を任せられたときは、相手が自分のことを信じてくれていることを念頭に置いて、責任をもってやり遂げること。

#### HRTを客観視する

一緒に開発した人から聞くのがベスト。
自分だけの意見では主観的になってしまうため。

### 型付けのメリット
型付けとは、プログラミングにおいて宣言した変数に、文字や数値のデータを格納する型を付けること。
プログラミングにおいて、型付けのメリットは、**エラーがわかりやすいこと**。
メリットはいろいろあるが、一番効果あるのはこれではないか。（個人の感想）
入っているのが、数値でなのか、文字なのかはっきりしていると、エラーが起きた時に「ここに数値（又は文字）が入っているよ！」というのを教えてくれるので、原因の特定が早い。

逆にない場合、
エラーが起きていても、「ここがおかしいよ！」といわれるだけで、何がエラーになっているかがわかりにくく、プログラムをトレースする必要がある。
少ない行のコードだったらまだしも、クラスやメソッドを記述していたり、行数が多かったりすると困ってしまう。

### 事業面

良いプロダクトを作成する意識として、
開発時ではoutput（作った機能数）ではなく、
**outcome(ユーザーに与えた影響の範囲)を意識すること**

どれだけユーザーの課題を解決できたかを明確にする。

outcomeを増やすために、開発段階でユーザーの課題をとらえておくこと。


### 成果物について
成果物を作成するときは、どんなユーザーを意識して作ったか答えられるようにしておく。

簡単でもいいから機能の設計からデプロイまで、一人でできるようになっておくこと。

:::note warn
ここで書いたことは、自分の言葉でわかりやすく書いたものなので、正確には異なっているかもしれないので、ご容赦いただけますと幸いです。
:::





## 終わりに
以上、アウトプットさせていただきました。
どの内容もこれからの人生で役立つことを聞けて、ためになりました。

交流会の最後でも言われいたのですが、ここで終わらずにこの交流会をきっかけに勉強や就活など、自分のキャリアをスタートさせていきたいです。

読んでいただきありがとうございました！
enterkeyhint属性

# enterkeyhint属性について

`enterkeyhint`属性は、HTML5.2で導入された新しい属性で、主に仮想キーボードを使用するモバイルデバイスでのユーザーエクスペリエンスを向上させることを目的としている
この属性は、`<input>`要素や`<textarea>`要素に適用され、仮想キーボード上のEnterキー（またはそれに相当するキー）の表示ラベルやアイコンをカスタマイズすることができる

`enterkeyhint`属性に設定できる値は以下の通り

- `enter`: Enterキーを示す標準的なラベルやアイコンが表示される
- `done`: 完了や送信を示すラベルやアイコンが表示される
- `go`: 移動や遷移を示すラベルやアイコンが表示される
- `next`: 次へ進むことを示すラベルやアイコンが表示される
- `previous`: 前に戻ることを示すラベルやアイコンが表示される
- `search`: 検索を開始することを示すラベルやアイコンが表示される
- `send`: メッセージやデータを送信することを示すラベルやアイコンが表示される

以下は、enterkeyhint属性を使用した例です。
```html
<input type="text" enterkeyhint="search" placeholder="検索キーワードを入力...">
```
この例では、enterkeyhint属性にsearchを設定しているため、仮想キーボード上のEnterキーは検索アイコンや"検索"というラベルが表示されることが期待される
ただし、enterkeyhint属性はブラウザやデバイスによってサポート状況が異なるため、すべての環境で同じように表示されるわけではない
「Custom Post Type UI」を使うとパーマリンク設定が期待通りにならない件

## やりたいこと

- カスタム投稿にストアを登録
- カスタムタクソノミーにエリアカテゴリーを登録
- パーマリンクを `https://domain/kanto/tokyo/1234` という構成にしたい

## 問題

カスタム投稿・タクソノミーの登録に「**Custom Post Type UI**」というプラグインを使うとカスタアム投稿ページが404ページになってしまった。

## 結論

カスタム投稿の登録はfunction.phpで行い解決。

## 詳細

カスタム投稿の登録には「**Custom Post Type UI**」

パーマリンク設定には「**Custom Post Type Permalinks**」

というプラグインを使いました。

以前全く同じ構成でパーマリンク設定を行なったことがあったので、できるということはわかっていました。

その時と違ったのがカスタム投稿の登録方法です。

　以前はカスタム投稿をfunction.phpで設定しており、今回は「**Custom Post Type UI**」プラグインを使用していました。

登録には様々オプションがありますが、全く同じ。

「**Custom Post Type UI**」は登録する時のコードを出力してくれる機能があるので、コピーしてfunction.phpに貼り付け。プラグインを無効化して登録オプションが間違っているのかを検証したところ、404ページではなく投稿が正しく表示されました。
3/30 git part3

# 個人的リマインド用
ブランチとマージ、プルリクとか
## ブランチ
ブランチは並行して複数機能を開発するためにある(他の人の影響を受けない)

**gitのデータの持ち方**
コミット1ができる
→コミット2ができると、コミット1の情報をもつ
→コミット3(最新)ができると、コミット2の情報をもつ
各ブランチは最新のコミット3を指し示している(ブランチとはコミットファイルを指し示した、ただのポインタ)
**HEADとは**
今自分が作業しているブランチを指し示したポインタ
**新しいコミットができたら**
今masterブランチにいる時にコミット4ができた場合、今までコミット3を指していたポインタ(masterブランチ)はコミット4を差し直す
**コミット3でバグを発見**
subブランチをコミット3から分岐させ、コミット4'を作成。その後さらにコミット5'を作成する(現在のHEADはsubブランチ)

**このようにブランチを使うことで、並行的に分岐して開発を行える**

### ブランチを新規に追加する
```
git branch <ブランチ名> 作成するだけで切り替えは行わない
```
### ブランチの一覧を表示する
```
git branch 今いるブランチを表示

git branch -a 全てのブランチを表示する
```
### ブランチを切り替える
```
git checkout <既存ブランチ名>
※ git checkout - これでmasterブランチに戻れる

git checkout -b <新ブランチ名>
```
## マージ
マージとは、他の人の変更内容を取り込む作業のこと
### 変更履歴をマージする
```
git merge <ブランチ名>
git merge <リモート名/ブランチ名>
git merge origin/master
```
**マージには3種類ある**
1. Fast Forward: 早送りになるマージ
ブランチが枝分かれしていなかった時、元々のmasterブランチのその先にsubブランチがってそれをmergeしただけの時、ブランチのポインタが前に進むだけ
2. Auto Merge: 基本的なマージ
masterブランチの内容をベースにして、その内容にsubブランチの変更文を取り込んだ内容をスナップショットとしてコミットで記録している(元のコミットとsubが指してたコミットの2つを親コミットとしてもつ)
3. コンフリクト
複数の人が同じ箇所で別々の変更をした時、どの変更を優先したらいいか分からない状態

### コンフリクトの解決の仕方
```
コンフリクトしたファイル
<h1>Gitチュートリアル</h1>
<<<<<<< HEAD
<p>git addについて学ぼう</p> HEADの変更分
=======
<p>git commitを知ろう</p> subの変更分 
>>>>>>> sub
```
```
解決したファイル
<h1>Gitチュートリアル</h1>
<p>git addについて学ぼう</p>
<p>git commitを知ろう</p>

1.ファイルの内容を書き換える
2.「<<」「==」「>>」の記述を削除する
```
**コンフリクトが起きないようにするには**
・複数人で同じファイルを変更しない
・pullやmergeをする前に変更中の状態を無くしておく(commitやstashをしておく)
・pullする時は、pullするブランチに移動してからpullする
・コンフリクトしても慌てない

### ブランチを変更・削除する
```
変更
git branch -m <ブランチ名>
git branch -m new_branch
自分が作業しているブランチの名前を変更
```
```
削除
git branch -d <ブランチ名>

強制削除
git branch -D <ブランチ名>
```
**開発の流れ**
masterブランチをリリース用ブランチに、開発はトピックブランチを作成して進めるのが基本
→masterブランチを最新の状態に保てるから、今リリースされているものがどういう状態なのか1目でわかるし、リリース後にバグが起こっても1つ前のバグのないものに切り替えればOK

### リモートブランチ
リモートのブランチの状態へのポインタ

イメージ
1.ローカルリポジトリとリモートリポジトリを比較した際、ローカルにリモートにないコミットがあり、リモートの方が進んでいる状態
2.git fetchを実行すると、リモートのmasterやsubをローカルに持ってくる。その際ローカルでのポインタ名はorigin/masterだったりorigin/subになる

## Githubを利用した開発の流れ
### プルリクエスト
バグを発生させないためや、コードの質を担保するために誰かが変更したコードをGitHubに取り込む前には必ずレビューを挟むようにして開発していく(OKだったら取り込む、NGだったら拒否)

**プルリクエストの手順**
1.masterブランチを最新に更新
2.ブランチを作成
3.ファイルを変更
4.変更をコミット
5.GitHubへプッシュ
**ここまでローカル**
6.プルリクエストを送る
7.コードレビュー
8.プルリクエストをマージ
9.ブランチを削除

**詳しい手順に関してはudemyで確認**

### GitHub Flowの流れ
**GitHub社のワークフロー**
開発フローをシンプルにすることで誰でも迷わずジョインできる

1.masterブランチからブランチを作成
2.ファイルを変更しコミット
3.同名のブランチをGitHubへpush
4.プルリクエストを送る
5.コードレビューし、masterブランチにmerge
6.masterブランチをデプロイ

**ポイント**
・masterブランチは常にデプロイできる状態に保つ
・新開発はmasterブランチから新しいブランチを作成してスタート
・作成した新しいブランチ上でコミットする
・定期的にpushする(他のチーム状況を確認するため)
・masterにマージするためにプルリクエストを送る
・必ずレビューを受ける
・masterブランチにmergeしたらすぐにデプロイする
　そのためテストとデプロイは自動化

すぐにデプロイすることで、リリースされているものと開発中のものの進捗状況が同じになるためわかりやすい
正規表現まとめ

## 正規表現とは
正規表現とは、文字列の規則を表したパターンのこと。

### メタ文字と正規表現
正規表現は、「A」「a」「1」「あ」のような通常の文字と、`メタ文字`と呼ばれる特殊な意味を持つ記号の組み合わせで文字列のパターンを表現する。

#### ・正規表現で用いられる主なメタ文字
|メタ文字|意味|
|---|---|
|.|任意の1文字|
|^|〜ではじまる([]内で使用すると除外を意味する)|
|$|〜で終わる|
|-|文字の範囲指定|
|*|直前の文字を0回以上繰り返す|
|+|直前の文字を１回以上繰り返す|
|?|直前の文字がない、またはある|
|(|グループ化の開始|
|)|グループ化の終了|
|{|繰り返す回数の指定の開始|
|}|繰り返す回数の指定の終了|
|[|パターン定義の開始|
|]|パターン定義の終了|
POSTDの運営引き継ぎ以降+αで改めて実感した、SSGの良し悪し

:::note info
POSTD以外は、サンプルとして捉えて下さい。
:::

# 前書き

[ニジボックスがPOSTDを引き取って運用再開](https://postd.cc/postd-on-gatsbyjs/)してから、そろそろ2年が経とうとしています。

上記リンクにもある通り、POSTDは移管のタイミングでGatsbyに書き直していました。
それに起因してとまでは言わないですが、案件などでGatsbyを使うサイトの制作を受託するケースが発生しています。

今回のこの記事では、POSTD運用をベースにGatsbyを使っていた案件をちょっと離れた位置から見た立場として、SSG(Static Site Generation)を採用することの良し悪しについて、改めて文にしてみました。

# サイト自体の概要

今回出てくるサイトの構成要素を少しだけ記載します。（どれもGatsby製）[^1]

|サイト|スタイル|コンテンツ管理|
|---|----|----|
|POSTD|ブログ|GitHubリポジトリ内にMarkdownで管理|
|ある案件のサイト|Webサイト|HeadlessCMS上で管理|

[^1]: どちらも基盤情報等はもうちょっと複雑ですが、記事に必要なごくごく最低限の要素のみ記載しています

いずれも、Gatsby製の静的サイトとして管理しており、更新のたびにビルドが必要な点については共通しています。

# ありがたい点

## サーバーサイドが複雑にならない

`gatsby build`での静的サイト化は、当たり前ですが動的サイトと単純比較すると、レスポンス速度の優位性が高いです。
Gatsbyはサイト内でのページ間遷移はHTMLではなくコンテンツを保持したJSONを利用するため、初回アクセスだけでなくページ巡回においてもかなりの速さを期待できるでしょう。

また、「静的サイトである」ことからデプロイ場所を選ばないという点も大きいです。
個人的に管理している自身のサイトもSphinxを利用していますが、以前はレンタルサーバーにそのままPUTするだけの運用をしていました。
動的要素を考慮しないで良いというのはそれだけで気楽さを提供してくれます。

## developモードにおける表示確認の気楽さ

Gatsbyの表示確認時は`gatsby develop`コマンドでローカルサーバーが立ち上がるため、エンジニアにとっては馴染み深いです。
また、POSTDではリポジトリ内に記事ソースをまとめて管理しているのもあり、編集がホットリロードで即時反映されていくのも、記事自体の扱いやすさに一役買っています。

# 困りがちなこと

とはいえ、上記の点とのトレードオフになりやすい領域で困ったことも起きます。
場合によっては、この点が要件上クリティカルにもなりうるのが重要です。

## 記事などの要素数が多いほどビルドがしんどくなる

この記事の投稿時点で、POSTDの中でページソースとして管理しているMarkdownファイルは全部で820個あります。さらにカテゴリー・タグもかなりあるため、最終的に `gatby build` における生成は1250ページにまで膨れ上がります。[^2]

[^2]: カテゴリー類が164個あり、さらにビルド時には全記事版や特定タグ版のページネーションされたアーカイブまで登場します。

ここまで生成量が多いと、時間そのものもかなり必要とします。
現在、POSTDの記事更新は、 **1回あたり7分程度必要** です。ちょっと長いですね。

とはいえ、実際のところはあまり問題になっていません。これは、チーム内の合意として「予定日通りに公開できるように心掛けるが、難しい場合は延期を含めて柔軟に対応する」となっているためです。

## ビルド時間がかかる = 決まった時間にリリースできない

前述の通りPOSTDはビルド時間に関するしんどさは「許容する」方針で進行させています。
そのため、リリースのタイミングがずれてもそこまで問題になりません。

逆にフレキシブルな動き出しをするわけにはいかないケースも存在します。案件サイトがそのようなパターンでした。

この案件では、スタイル欄に記載したWebサイトの内容をライブ配信などのタイミングと可能な限り足並みを揃えて公開する必要が出てきていました。
つまり要件として「記事要素の更新・公開がリアルタイムに近い状態で提供できること」といういものが含まれています。
さて、こうなってくると以下のような要素が運用を困難にしてきます。

- ビルド環境が遅延して、公開が遅延する
- 記事のデータ取り込みが遅延して、公開が遅延する
- 記事データetc起因でビルドに失敗して、公開が大遅延する
- ビルド自体の時間が気づかないうちにかなり増えて、公開が遅延する

このような「記事更新→即反映」が必要な場合だと、やはりWordPressのような動的サイトを構成するほうが楽なことがあります。

## 構成要素すべてがボトルネックになるリスク

Gatsbyでのサイト管理+公開を考えると次のような要素分割が可能です。

1. デザイン等のソースを管理する場所
2. 記事データを管理する場所（上記のリポジトリと同一でも可）
3. 公開用サイトをビルドする場所
4. 公開するための場所

サイトの公開状態を維持するだけならば、(4)さえ生きていれば問題ありません。
しかし、更新のタイミングで(1)-(3)のいずれかが死んでいると、もう更新が不可能になります。

POSTDの場合では(1)=(2)のために構成要素が1個少なくなりますが、案件サイトのようにCMSが別になると事故率が上がるケースも有りえます。

逆に動的サイトの場合は(2)-(4)が同一基盤としての動作が期待できます。
もちろん基盤の死=サイトの死ではあるもの、ボトルネックとしては逆に少ないと捉えることもできます。

# まとめ

SSGを利用したサイト制作は、得られる恩恵は十分にあるものの、万能ではありません（当たり前ですが）。
時にWordPressなどでの提案を含めて「選択肢の1つ」であることを留意する必要があるでしょう。
Mock化できない理由

## Mock化できない理由

### 結論
Mock化するインスタンスをコンストラクタ、セッター、プロパティ（フィールド）で、インスタンスにする必要があり。

以下のコードの場合、Mock化はできない
```java
public class LoginCheck {
	/**
	 *ユーザーテーブルから全データを取得
	 * @return
	 */
	public List<User> execute() {
		UserDAO dao = new UserDAO();
		List<User> user = dao.findAll();
		return user;
	}
}

```

なぜなら、テストするメソッド内でインスタンス化しているから。

下記のコードの場合は、Mock化できる
```java
public class LoginCheck {
	private LoginCheck LC;
	private UserDAO userdao;
	private User user;
	

	public LoginCheck() {
		super();
		userdao = new UserDAO();
		user = new User();
	}

	/**
	 *ユーザーテーブルから全データを取得
	 * @return
	 */
	public List<User> execute() {
		UserDAO dao = new UserDAO();
		List<User> user = dao.findAll();
		return user;
	}

/*こちらのやり方でもできます。
public List<User> execute() {
		List<User> user = userdao.findAll();
		return user;
	}
*/


```

### 参考資料

https://kehalife.com/android-studio-junit-injectmock/
Azure REST Api "InvalidResource"erro解決

Azure Media ServiceのAPIを呼び出していた際、
```
400 {
  "error": {
    "code": "InvalidResource",
    "message": "The resource format is invalid."
  }
}
```
のエラーが発生し、調べても同じ事例が見つからず手こずってしまったので解決策を投稿いたします。
またほぼ同じ環境で
```
400 {
  "error": {
    "code": "InvalidResource",
    "message": "Invalid JSON. A token was not recognized in the JSON content."
  }
}
```
こちらのエラーも発生していたので参考になればと思います。
<h5>前提条件<h5/>
Python3.10でrequestモジュールを使用しApi呼び出しを行っている。

<h2>エラー事象<h2/>
Mediaserviceのアセットの、SASを含むURLを発行するためのApiを呼び出しています。

```az.py
import request

url="https://management.azure.com/subscriptions/********/resourceGroups/hogehoge/providers/Microsoft.Media/mediaServices/hogehoge/assets/hogehoge/listContainerSas?api-version=2022-08-01"
headers = {
    'Content-Type': 'application/json',
    'Authorization': f'Bearer {token}',
}
payload = {
"permissions": "ReadWrite",
"expiryTime": "2018-01-01T10:00:00.007Z"
}
response = requests.post(url, data=payload,headers=headers, )
print(response.status_code, response.text)
```
すると結果は
```
400 {
  "error": {
    "code": "InvalidResource",
    "message": "The resource format is invalid."
  }
}
```
となります。
<h1>解決策<h1/>

```az.py
response = requests.post(url, json=payload,headers=headers, )
```
第一引数をjsonとしたところうまく動きました。どうやらリクエストボディがjson形式として認識されていなかったようです。
node -vコマンドでzsh: command not found: nodeエラーになる


# エラー内容

以下コマンド実行時に `zsh: command not found: node`  エラーとなる。

```shell:コマンド
% node -v
zsh: command not found: node
```

# 原因

`~/.zshrc` にパスが通っていない。

以下コマンドで `~/.zshrc` を確認できる。

```shell:コマンド
cat ~/.zshrc
```

# 対処法

以下コマンドを実行する。
※ nodebrewでインストールしている場合

```shell:コマンド
echo 'export PATH=$HOME/.nodebrew/current/bin:$PATH' >> ~/.zshrc
source ~/.zshrc
```

`node -v` コマンドでバージョンが表示されれば成功。

```
% node -v
v18.15.0
```
Vuetify3で<v-icon>が表示されない

# Vuetify3で&lt;v-icon&gt;が表示されない
Vuetifyを使いラジオボタンを作ったけど、なんか変

コード
```vue
<template>
  <v-radio-group>
    <template v-for="(option, index) in options">
      <v-radio :label="option" :value="index"></v-radio>
    </template>
  </v-radio-group>
</template>

<script>
export default {
  data() {
    return {
      options: [
        "first",
        "second",
        "third"
      ]
    }
  }
}
<script />
```

こんな感じになるはず
![v-icon expected.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305995/50020a44-cb7e-5a5c-21ad-0a5c4fd57576.png "こうなるはず")

結果
![v-icon doesnt work.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3305995/becc5971-97b9-6d2a-fe59-fd32d53d4770.png "v-iconが動かない")

**丸がない**

調べてみたら、material design icons(mdi)が表示されてないっぽい

(https://stackoverflow.com/questions/57505666/in-vuetify-radio-is-not-shown)

# どうすればいいか

まず、`@mdi-font` をインストールする
```bash
npm i --save @mdi-font
```

`main.js` に入れる
```javascript
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";

import "vuetify/styles";
import { createVuetify } from "vuetify";
import * as components from "vuetify/components";
import * as directives from "vuetify/directives";

import "@mdi/font/css/materialdesignicons.css"; // 追加

const app = createApp(App);

const vuetify = createVuetify({
  components,
  directives,
  ssr: true,
});

app.use(router);

app.use(vuetify);

app.mount("#app");
```

これで動きます
ChatGPTを使って爆速でプレゼン資料を作る

## ChatGPTを使ってプレゼン資料を作る
エンジニアのみなさんはコードを書くことは得意でもLTなどで発表するプレゼン資料（スライド）を作成することが苦手の方もいらっしゃいますよね。そんな人（自分含む）にChatGPTを使ってスライドを作成する方法についてまとめましたので共有します。

ちなみに、現状(2023/03/30時点)のChatGPTには直接スライドを出力できるような機能はないので、下記のような感じで工夫するとChatGPTを使って爆速でスライドが作れちゃいます。

## 使用するツール
- ChatGPT
- Marp for VS Code

**Marp**って何?という方は下記の記事をご参考ください。簡単に言うとMarkdownからスライドを作成できるものです。もちろん皆さん大好きな**PowerPoint**や**PDF**にも出力可能です。

https://qiita.com/tomo_makes/items/aafae4021986553ae1d8

## 作成フロー

1.ChatGPTでプレゼン資料にしたい内容をMarp形式で出力するよう指示する
2.Marp for VS Codeを拡張を入れた、VS Codeに貼り付け
3.スライド爆誕

## やってみた

### 1.ChatGPTにプレゼン資料作成の指示

**ChatGPTで作成するプレゼン資料**という本記事の題名を例にして、ChatGPTに指示を出した例です。作成したいスライドの内容に応じて指示内容は変えてください。

```text
#命令書:
あなたは、プロのエバンジェリストです。
以下のスライドの題名、スライドの内容と制約条件を厳密に守り 最高のライトニングトークとなるようなスライド作成をお願いします。尚、スライドはMarp for VS Codeで作成するため対応したMarkdownを出力してください。

#制約条件:
・目次を付けること
・視認性が良い配色とし、カッコいいと感じるデザインとすること
・5分以内で説明できる内容
・誰にでもわかりやすく
・重要なキーワードを取り残さない
・画像や図形を用いて説明すること
・ITエンジニア向けの内容とすること
・出力するMarkdownはコピー＆ペーストできる形式で出力すること

#スライドの題名:
ChatGPTで作成するプレゼン資料

#スライドの内容:
ChatGPTとMarp for VS Codeを使ってスライド作成を行う方法について説明する
```

ChatGPTがコピペできる形でMarkdownを出力してくれます。スライドで表示する画像の部分などは自分で置き換える必要がありそうです。

内容が多いので折りたたんでいます。見たい人は▶押してください。

<details><summary>ChatGPTが出力した内容</summary><div>

```yaml
---
marp: true
theme: default
size: 16:9
paginate: true
_class: ["cool-theme"]
---

<!-- _class: title -->
# ChatGPTで作成するプレゼン資料

---


<!-- _class: toc -->
# 目次

1. ChatGPTとは
2. Marp for VS Codeとは
3. ChatGPTとMarp for VS Codeを組み合わせる方法
4. 例: スライド作成のデモ
5. まとめ

---

<!-- _class: info -->
# ChatGPTとは

- OpenAIが開発したGPT-4をベースにした大規模言語モデル
- 自然言語処理タスクに強力な性能を発揮
- テキスト生成や質問応答などのタスクが得意

![GPT-4-logo](https://example.com/gpt-4-logo.png)

---

<!-- _class: info -->
# Marp for VS Codeとは

- Visual Studio Codeで使えるMarkdownベースのスライド作成ツール
- シンプルで使いやすい
- コードハイライトや画像の埋め込みが可能

![Marp-Logo](https://example.com/marp-logo.png)

---

<!-- _class: info -->
# ChatGPTとMarp for VS Codeを組み合わせる方法

1. ChatGPTを使用して、スライドの内容を生成
2. 生成されたテキストをMarp for VS Codeで編集
3. スライドを完成させる

![Integration-Diagram](https://example.com/integration-diagram.png)

---

<!-- _class: demo -->
# 例: スライド作成のデモ

1. ChatGPTでスライド内容を生成
2. Marp for VS CodeでMarkdownを編集
3. スライドをプレビュー

![Demo-Process](https://example.com/demo-process.gif)

---

<!-- _class: summary -->
# まとめ

- ChatGPTとMarp for VS Codeを組み合わせることで、効率的なスライド作成が可能
- 自動生成されたテキストを編集するだけで、見栄えの良いスライドが完成
- ITエンジニア向けのプレゼン資料作成に役立つ

![Conclusion-Image](https://example.com/conclusion-image.png)

```
</div></details>

### 2.VS Codeに貼り付ける
事前に**Marp for VS Code**の拡張は入れておいてください。
https://marketplace.visualstudio.com/items?itemName=marp-team.marp-vscode

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253600/376cc5c0-33c3-e5bb-833a-342ce0c73c76.png)

### 3.スライド爆誕
あとはVS CodeからPowerPointやPDF等の好きな形式で出力してください。

## まとめ
こんな感じでChatGPTとMarpを組み合わせればプレゼン資料（スライド）を簡単に作成可能です。完成物としてクオリティを上げるためには、人間が画像を挿入してあげたり、デザインを調整するなど細かな作業が必要だと感じますが、ここまで作れるだけでも十分生産性は上がりますよね。また、"微妙だな"と感じた部分をChatGPTに具体的に修正指示すれば直してくれます。

ぜひ皆さんも試していただきアドバイスいただけると嬉しいです。
[ Express ] サーバー立ち上げ＆MongeDB接続方法

## 完成コード
備忘録です。
※MongeDBの設定方法は説明していません。あくまでmongooseを使用して接続する方法になります。
```javascript:server.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const PORT = 5000;

//DB接続　
//※下記DATE_BASE_URLにはMongeDBの設定した際の接続用のURLを使用します。
mongoose.connect(DATE_BASE_URL).then(() => {
    console.log("DBと接続しています！");
  })
  .catch((err) => {
    console.log(err);
  });


//-----ミドルウェア------


app.listen(PORT, () =>
  console.log(`${PORT}server-start`)
);

```
#### 1. パッケージをインストール

・express  https://expressjs.com/ja/starter/installing.html
&nbsp;&nbsp;&nbsp;&nbsp;→Node.jsで使用するフレームワーク

・mogoose  https://mongoosejs.com/
&nbsp;&nbsp;&nbsp;&nbsp;→MongoDBを操作する


#### 2. モジュールをインポート
以下のようにインポートします。
express()はapp変数に格納して使用します。

```javascript:server.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");

```

#### 3. listen()メソッドを使用してサーバー構築
listen()に引数を渡します。第一引数にポート番号、第二引数にコールバック関数をを記述できます。
コンソールログを使用しサーバーが立ち上がってるか確認できます。

```javascript:server.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const PORT = 5000;

app.listen(PORT, () =>
  console.log(`${PORT}server-start`)
);

```
#### 4. mongooseを使用してデータベース接続
connect()にMongoDBで生成したURLを渡します。(DATE_BASE_URLの記述部分)
また、以下のconnect()はPromiseを返すので、成功時にはコールバック関数が呼び出されて接続してることをコンソールログに出力しています。失敗している場合にはcatch()でエラーがコンソールに出力されます。

```javascript:server.js
const express = require("express");
const app = express();
const mongoose = require("mongoose");
const PORT = 5000;

//DB接続　
mongoose.connect(DATE_BASE_URL).then(() => {
    console.log("DBと接続しています！");
  })
  .catch((err) => {
    console.log(err);
  });


//-----ミドルウェア------


app.listen(PORT, () =>
  console.log(`${PORT}server-start`)
);
```
:::note alert
MongeDBのURLの取り扱いについて
データベースのURLは機密情報です！
dotenvファイルを使用して大事な情報を保護しましょう。
:::


以上、サーバー立ち上げ＆MongeDB接続方法でした。
[備忘録][Azure] Logic Appsの繰り返しスケジュールトリガーで分指定ができない時の解決策

# はじめに

2023/03/30時点での情報です。

# TL;DR

- 対象はLogic Appsの「Recurrence」トリガー
    - Preview Designer のみが対象です
- 分指定する時は`[0,15,30,45]`のように配列カッコをつけてあげないといけない

# やりたいこと

Logic Appsを使って、一定時間の間、15分おきにトリガさせたい。

# 参考にしたドキュメント

https://learn.microsoft.com/ja-jp/azure/logic-apps/tutorial-build-schedule-recurring-logic-app-workflow#add-the-recurrence-trigger

# ドキュメントに従ってセットアップ

Logic AppsのPreview Designer画面より、「Recurrence」トリガーを選択。
`Frequency`, `Interval`, `At these hours`を設定し、「分」の情報を入力するところまできました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/5c5421c7-b93d-0e29-4cd5-80053dec5495.png" width="600">

ふむ、0-59までの有効な分値をカンマ区切りで入力せよ、と。
hourや曜日はチェックボックスでしたが、分は自分で書き込む方式なのか、まあ60個も選択肢があるチェックボックス嫌だしね。

# 分を入力して一旦保存っと

じゃ、こんな感じで15分おきにして。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/1b2933e7-ec74-2a6c-a050-51b327425ded.png" width="500">

一旦保存しとくか。保存ボタンポチッ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/b89c825a-6c5c-23b1-b147-06cff3f025f3.png)

ええ......？
`0,15,30,45`を`System.Int32[]`型に変換できませんでしたって言われても......

# 何が悪いんだろう

何度見返しても、[公式ドキュメント](https://learn.microsoft.com/ja-jp/azure/logic-apps/tutorial-build-schedule-recurring-logic-app-workflow#add-the-recurrence-trigger)通りの記述をしてるし、プレースホルダとも同じ書き方です。

いったん生成されたCodeを見てみます。

```json
{
  "type": "Recurrence",
  "recurrence": {
    "frequency": "Week",
    "interval": 1,
    "timeZone": "Tokyo Standard Time",
    "schedule": {
      "hours": [
        "14",
        "15",
        "16"
      ],
      "minutes": "0,15,30,45",
      "weekDays": [
        "Sunday",
        "Saturday",
        "Friday",
        "Thursday",
        "Wednesday",
        "Tuesday",
        "Monday"
      ]
    }
  }
}
```

`minutes`キーに文字列が入ってるのが気になりますね。
`hours`と`weekDays`は配列なのに。

ま、まさか...

こうやって`[0,15,30,45]`配列のカッコをつけてあげたら......

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647946/c15d2cfb-0643-5333-6f04-a322b5a31abc.png" width="500">

# いけた

保存も成功しました。

```diff_json
{
  "type": "Recurrence",
  "recurrence": {
    "frequency": "Week",
    "interval": 1,
    "timeZone": "Tokyo Standard Time",
    "schedule": {
      "hours": [
        "14",
        "15",
        "16"
      ],
-      "minutes": "0,15,30,45",
+      "minutes": [
+        0,
+        15,
+        30,
+        45
+      ],
      "weekDays": [
        "Sunday",
        "Saturday",
        "Friday",
        "Thursday",
        "Wednesday",
        "Tuesday",
        "Monday"
      ]
    }
  }
}
```

# 公式のissue

https://github.com/Azure/LogicAppsUX/issues

調べてはみましたが、多分報告はあがってないと思います。
もうちょっと調査してからissue発行しようかな。

## 2023/03/31追記 issue発行しました

https://github.com/Azure/LogicAppsUX/issues/1859

MicrosoftのContributorの方から、[コメント](https://github.com/Azure/LogicAppsUX/issues/1859#issuecomment-1490754537)がつきまして、繰り返しトリガーの描写について検討を進めていて、こちらのバグについても取り込む予定らしいです。
OSSにissue立てるのは初めてだったんですが、なんだかすごく達成感がありますね。
Debian Stable(Bullseye) ユーザーは .ssh/config に UpdateHostKeys yes を陽に設定するべきである

OpenSSHにはUpdateHostkeysという設定がある。[OpenSSH 6.8](https://www.openssh.com/txt/release-6.8)で導入され、[OpenSSH 8.5](https://www.openssh.com/txt/release-8.5)でデフォルトで有効化された。
変更されたホスト鍵を自動的に受け取ることができる機能である。

この設定に関連して記憶に新しいのは、[GitHubのホスト鍵変更](https://github.blog/2023-03-23-we-updated-our-rsa-ssh-host-key/)である。UpdateHostkeysが有効であれば、ECDSA鍵を受け取っているから影響を受けないはずであった。私のマシンで直接確認することは叶わなかったが、~/.ssh/known_hosts.autoに`github.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBEmKSENjQEezOmxkZMy7opKgwFB9nkt5YRrYMjNuG5N87uRgg6CLrbo5wAdT/y6v0mKV0U2w0WZ2YB/++Tpockg=` [^1]を手動で書き足すことにより確認することができた。

問題は、現行のDebian stableであるBullseyeでは、OpenSSHは8.4だということである。つまりUpdateHostkeysは明示的に設定する必要がある。

```
Host github.com
        Hostname github.com
        User git
        UpdateHostKeys yes
        StrictHostKeyChecking yes
```

[^1]: https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/githubs-ssh-key-fingerprints に(改竄がないことが保証されている)同じ文字列がある