OmniAICreator/Qiita-1.07M huggingface dataset:
Tableauを3か月触ってよく分からないことを深堀する　①権限

## はじめに
23年2月からTableau案件に参画し、5月で丸3か月経過しました。
頭と手を動かして、Vizを作る中で、よく分かってないことをそのままにしてきたので、この場を用いて、深堀り→理解をしたいと思います。

第1回目は、「権限」についてです。

## Tableau Cloudと権限
### 「権限」の壁に当たったはなし
現在の案件では、CreatorライセンスでVizの開発していて、Vizやそれに係るデータソースをTableau Cloudにパブリッシュしています。
具体的には、、、
- Tableau Cloudにダッシュボードをパブリッシュし、グループ内で閲覧する。
- Tableau Cloudにデータソースをパブリッシュし、データソースを参照しているダッシュボードを更新する。

など、ごくごく基本的な使い方をしています。

先日、Tableau Prepからデータソースのパブリッシュしようとしたとき、次のようなエラーが発生しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601070/9d03d969-9974-e3a1-3130-40a0d1ede8f8.png)

これまで問題無くパブリッシュできていたので、おかしいな？と思い、システム管理者に問合せしたところ、「新しいCreatorライセンスを払出したので、私が使っているライセンスのサイトロールをViewerにした」と回答をもらいました。

これまで何となくの知識でやってきたので、「ライセンスとサイトロールは違うの？」、「エラーで示しているパーミッションって何？」と立ち止まってしまいました。
データソースのパブリッシュが出来ないと、案件を進められないという状況に差し迫ったので、しっかり理解しようと思ったのがきっかけです。

### Tableau Cloudの構造
まずはTableau Cloduの構造について触れておきます。

Tableau Cloudの世界では、Tableau Serverのサイト（Tableau Serverの管理単位のこと）を1つ間借りして、その中にプロジェクト（ダッシュボードやワークブックをまとめた単位のこと）を作って管理します。

つまり、、、
> サイト ┯ プロジェクトA ┯ ワークブックとデータソースA ─ 複数のダッシュボード
                   　　　┃ 　　　　　　　┗ ワークブックとデータソースB
          　　　┗   プロジェクトB ─ ワークブックとデータソースC ─ 複数のダッシュボード
　　　┃

といった構造で、オブジェクトが管理されます。

つまり、この構造に対し、ライセンス・サイトロール・パーミッションの3段階で、権限（出来ること・出来ないこと）を設定していくということです。

### ライセンスとサイトロールとパーミッション
####  ①ライセンス
　Tableauを使用するためには、ミッションに応じた「ライセンス」を購入する必要があります。それぞれ、、、
 - Creator ：データを加工、新しいデータソース作成など、Tableau機能全ての使い手
 - Explorer：Creatorがパブリッシュしたデータを元に、ダッシュボード作成や修正が可能
 - Viewer　：いわゆる「読み取り専用」の状態で、ダッシュボードの操作が可能

という区分けになります。

####  ②サイトロール
　その名の通り、サイトレベルのロール（役割）を与えます。ちなみに、サイトロール設定のタイミングは、ユーザーの登録時です。

▼ユーザー登録画面でサイトロールを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601070/38b09368-419a-c0ca-86a8-6241f1c31ca8.png)

サイトロールのポイントは、同じライセンスであっても、サイトロールを変えることで、「権限の範囲を狭めることが可能」ということです。

先の図で、Creatorライセンスには、2つのサイトロール「サイト管理者Creator」と「Creator」が存在していました。

サイト管理者Creatorは、ユーザーの管理（作成・削除）やサイトの管理（フォルダ構成の変更等）が可能ですが、Creatorはそれらが出来ません。

また、Explorerライセンスであっても、サイト管理者権限を与えれば、管理者になることも可能です。

####  ③パーミッション
　「出来ることと出来ないこと」の観点でいうと、前述の「ライセンス」は、購入時点でライセンス単位で決まっていますし、「サイトロール」もパッケージされたロールを選ぶので予め決まっていますが、「パーミッション」は、Aというワークブックのパブリッシュに対して、出来る・出来ないを設定できます。

　ただし、サイトロールの制約で出来ないことは、パーミッションで許可しても利用できません。例えば、「サイト管理者ではない通常のCreator」というサイトロールを与えられたとして、パーミッションで「フォルダの削除」を許可したとしても、出来ないということです。
　
    　一方で下図のように、何でもできる「サイト管理者Creator」サイトロールを与えられていても、パーミッションで「拒否」されていたら、何もできません。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601070/e75ecff2-af6d-26fc-baf4-3d1417c37b9e.png)

## まとめ
今回、権限について考えるきっかけとなった、下図のエラーについては、システム管理者に「新しく払出したライセンスに対し、プロジェクト・ワークブック・データソースそれぞれにパブリッシュができるパーミッションを設定してください」と依頼することで、無事解決できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2601070/9d03d969-9974-e3a1-3130-40a0d1ede8f8.png)

Vizを作るだけでなく、システムを運用する目線も持ちながら、案件に取り組んでいてたらと思います。
僕が生徒さんの疑問に全力で答える理由


[1.はじめに](#1-はじめに)
[2.目標設定・モチベーション](#2-目標設定・モチベーション)
[3.文構造の理解](#3-文構造の理解)
[4.英単語の理解](#4-英単語の理解)
[5.英文の解釈](#5-英文の解釈)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/b17bdffc-7f05-979a-013d-c414530119a3.png)

# 1. はじめに

皆さん、突然ですがこんな悩みはありませんか？

「英語の勉強をしていて分からないところがあったけど参考書だけでは理解できない」

こんなとき、皆さんはどうしていますか？

今なら大抵の方が、「ネットで調べる」という手段を取っているのではないでしょうか？

ところが、ネットで調べてみても近いものは出てくるけれど、本当にそれで合っているのか確信が持てない、ということが多々あります。

そして、「なんとなくこういうこと」という曖昧な理解をして、
また次に同じような英語に出会ったときに、同じように悩む、という繰り返しになっていませんか？

私の主宰するマンツーマンTOEICコーチングでは、
英語やスケジュールに関する質問にLINEで随時対応しています。

以下に実際の生徒さんとのやり取りをご紹介していきます。

青が生徒さんです。

# 2. 目標設定・モチベーション

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/317f770a-4463-a55f-9c7f-0b789b87d963.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/b65934cd-ad34-2cf9-48ce-47e46e2522b7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/0909c6be-905d-8bf7-babc-c2ee494970b8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/ce28ba5d-344b-7486-5b76-8a105aac0aed.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/07910d01-4e67-00cd-8141-e233cc91e375.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/bd215e76-b61d-9190-affa-5dacd447c03d.png)


# 3. 文構造の理解

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/7486a150-ba35-cbf6-6733-b3e9ff2168d7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/90d83102-a104-5a2c-73a2-42b06f4705e7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/84e7cc0f-29c9-7920-3863-62440326ac99.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/e3b55c16-18a4-b4b9-ad0a-1bc9ac20f2ac.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/61c3fe8f-0fc3-15a8-2f9d-c13715ec1798.png)


# 4. 英単語の理解

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/67d9374c-fee9-fd57-8cbf-c6db54e3c583.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/aaa67eda-c744-6b92-78ff-2f63c263291d.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/bbb3e3fd-36b2-3c51-b998-ee130078bcf1.png)

# 5. 英文の解釈

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/5d00a856-8f0c-faf4-5980-2bc237b41acb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/2d8a9012-cfbd-4365-66f5-b0a72a05af55.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3074582/8da2b19e-206f-3d09-7f5e-9c5c202b8385.png)

**僕が生徒さんの疑問に全力で答える理由②**に続く
https://qiita.com/toeic-coaching/items/1e4d1f63d5d897582e09
素人が地獄みたいなコードを書いたので、楽しんでいってください。

# なにこれ？

Swift Charts で、時系列のデータの個数の推移を日毎、月毎、年毎の棒グラフにしたかった。各データはidとタイムスタンプのDate()の2つのアトリビュートを持つ。問題は、chartにするには、それらを日月年で区切ること。


``` swift

class CountPerTermCalculator{
    let perDay: [CountPerTerm]
    let perWeek: CountPerTerm
    let perMonth: CountPerTerm
    let perYear: CountPerTerm
    
    init(dates:[Date]){
        //めちゃくちゃ難しいから、算数の問題とした。
        //まず、初期日からの日数をキーとする辞書を作成、データのない日も含めて初期化。
        //次に、[日付データ]を回して、それぞれの日付の初期日からの日数を計算し、辞書にカウントしていく。
        
        //まずはperDayから考えてみる。同じ日の要素をまとめて、要素数をカウントだな。
        let firstDay = dates.first!
        var countsPerTerm:[Int:Int] = [0:0] // [days from the firstDay : countOnThatDay]
        
        let totalDays = Calendar.current.dateComponents([.day], from: firstDay, to: Date()).day!
        //total days from the firstDay to today
        
        for daysFromFirst in 0..<totalDays {
            countsPerTerm[daysFromFirst] = 0  //initializing  countsPerTerm: [Int:Int]
        }
        
        let formatter = DateFormatter()
            formatter.calendar = Calendar(identifier: .gregorian)
            formatter.dateStyle = .medium
            formatter.timeStyle = .none         // e.g. 2017/08/13
        
        
        for i in 0..<dates.count {
            let daysFromFirstDay = Calendar.current.dateComponents([.day], from: firstDay, to: dates[i]).day!
            countsPerTerm[daysFromFirstDay]! += 1
        }
        //             初期日からの日数:カウント
        ///countsPerTerm...[0:2,
        ///             1:2,
        ///             2:0,
        ///             3:4,
        ///             .....]
        ///あああああああああああわけわからn
        var returnValue:[CountPerTerm] = []
        
        for daysFromFirst in 0 ..< totalDays{
            let date = Calendar.current.date(byAdding: .day, value: daysFromFirst, to: firstDay)
            returnValue.append(CountPerTerm(count: countsPerTerm[daysFromFirst]!.count, date: date))
            
        }
    }
}

class CountPerTerm{
    var id = UUID()
    let count:Int
    let date:Date
    
    init(count:Int,date:Date) {
        self.count = count
        self.date = date
    }
}
```
GitHub Copilot と Amazon CodeWhisperer の比較

プログラミングの世界で注目されているのが、AI（人工知能）を活用したコーディング補助ツールです。

その中でも特に有名なのが、GitHubの「Copilot」とAmazonの「CodeWhisperer」。それぞれの特徴、違い、使用可能なIDE（統合開発環境）、そして料金について初心者にもわかりやすく解説します。

## GitHub Copilot

まず、GitHub Copilotは、開発者が書きたいコードのコメントを解析し、それに基づいてコードを自動的に提案するツールです。対応言語も多岐にわたり、一般的な開発に広く活用されています。

### 使用可能なIDE

GitHub Copilotは、Visual Studio Codeで利用できます。また、他のJetBrainsのIDEでも利用可能です。

### 料金

GitHub Copilotの価格は、月単位または年単位のサイクルで設定されています。月単位では1ヵ月あたり10ドル、年単位では1年あたり100ドルの課金があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/e09657de-dca2-ec2d-2b03-2e5d0dd38d74.png)


## Amazon CodeWhisperer

一方、Amazon CodeWhispererも同じく開発者のコメントを解析してコードを提案するツールですが、特にAWS（Amazon Web Services）に関連する開発に強みを持っています。

### 使用可能なIDE

AWS Cloud9、JetBrains、VSCodeなどで使えます。

### 料金

Amazon CodeWhispererの料金については、無料です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/987057/e64547af-f6c9-8b19-9ec2-b32bea708016.png)


## CopilotとCodeWhispererの違い

これら二つのツールは機能的には非常に似ていますが、利用シーンにおいていくつか違いがあります。Copilotは一般的な開発に対応しており、CodeWhispererはAWSに関連する開発に特化している点です。

つまり、広範囲な開発を行うならCopilotが適しており、AWSの開発を主に行うならCodeWhispererが良い選択となります。

どちらのツールもコーディングの助けになり、効率的な開発を実現します。自分の開発環境とニーズに合わせて適切なツールを選ぶと良いでしょう。
SoundManager

```csharp
using UnityEngine;

public class SoundManager : MonoBehaviour
{
    [SerializeField] AudioSource bgmAudioSource;
    [SerializeField] AudioSource seAudioSource;

    public void PlayBGM(AudioClip clip)
    {
        if (bgmAudioSource.clip != clip)
        {
            bgmAudioSource.clip = clip;
            bgmAudioSource.Play();
        }
    }

    public void StopBGM()
    {
        bgmAudioSource.Stop();
    }

    public void PlaySE(AudioClip clip)
    {
        seAudioSource.PlayOneShot(clip);
    }
}
```
Pythonでステッピングモーターを動かす

#### Pythonでステッピングモーターを動かす
##### 本記事の背景
現在の相場は分かりませんが、昔は100円で簡単に試せる「28BYJ-48」という安い世界で一番安いステッピングモーターがあります。[データシート](https://datasheetspdf.com/pdf/1006817/Kiatronics/28BYJ-48/1)

ステッピングモーターの原理と配線とかは割愛しますが、Pythonで動かすことができます。
C言語で動かすこともできますが、コンパイルが必要だったりといろいろ面倒でした。
ソースコードは以下参照

```python
# -*- coding: utf-8 -*-
from time import sleep
from gpiozero import OutputDevice as stepper
import datetime
import sys

class C28BYJ48:

    def __init__(self, IN1, IN2, IN3, IN4):
        self.IN1 = stepper(IN1)
        self.IN2 = stepper(IN2)
        self.IN3 = stepper(IN3)
        self.IN4 = stepper(IN4)
        #Setting GPIO
        self.stepPins = [self.IN1, self.IN2, self.IN3, self.IN4]
        self.sequenceNumber = 0
        self.stepCount = 8

    def seq(self):
        return [[1,0,0,1], [1,0,0,0],[1,1,0,0],[0,1,0,0],[0,1,1,0],[0,0,1,0],[0,0,1,1],[0,0,0,1]]

    def SetRoll(self, angle, wait):
        #入力値が0以下の場合
        if angle <= 0 : return 0,0
        #回転ステップ数の計算
        #カメラ台座ギア比2：1のため、角度入力値を二倍にします
        steps = int((angle * 2) * 4096 / 360)
        #回転インターバル時間の計算
        #入力値分単位を秒単位へ変換
        interval = float(wait * 60.0 / steps)
        return steps, interval

    #シーケンスのピンをセットする
    def SetPinVoltage(self, NSeq):
        self.sequenceNumber = NSeq
        for pin in range(0,4):
            xPin = self.stepPins[pin]
            seq = self.seq()
            if seq[self.sequenceNumber][pin]!=0:
                xPin.on()
            else:
                xPin.off()

    def run(self, angle, wait, direction):
        # Set to 1 for clockwise
        # Set to -1 for anti-clockwise
        self.direction = direction
        #回転設定
        steps, interval = self.SetRoll(angle, wait)
        for i in range(0, steps):
            self.SetPinVoltage(self.sequenceNumber)
            self.sequenceNumber += self.direction
            if self.sequenceNumber >= self.stepCount:
                self.sequenceNumber = 0
            if self.sequenceNumber < 0:
                self.sequenceNumber = self.stepCount + self.direction
            sleep(interval)

if __name__ == '__main__':
    StepMotor = C28BYJ48(12,16,20,21)
    while True:
       #時計周り 180度回転/撮影時間1分
        StepMotor.run(180, 0.1, 1)
        sleep(2)
        #反時計周り 180度回転/撮影時間1分
        StepMotor.run(180, 0.1, -1)
        sleep(2)  
```
##### サービスの設定
上記のプログラムは単体でも動きますが、起動後にプログラムを実行する必要がある為少々面倒のため、RaspberryPi起動後にサービスをセットすることにより、自動実行できるようにします。
サービス本体は以下のように作成と配置を行います。

```console
pi@raspberrypi:/etc/systemd/system $ pwd
/etc/systemd/system
pi@raspberrypi:/etc/systemd/system $ cat move_mouse_cursol.service 
[Unit]
Description=move mouse cursole by stepping motor
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/smartlife/camera_control
ExecStart=python gpiozero_stepping.py

[Install]
WantedBy=multi-user.target
```
システムコントロールに追加します。
```console
pi@raspberrypi:/etc/systemd/system $ sudo systemctl enable move_mouse_cursol
pi@raspberrypi:/etc/systemd/system $ sudo systemctl is-enabled move_mouse_cursol
enabled
```
##### 最後に
これでRaspberryPiを起動すると自動的にステッピングモーターを自動的に回すことができるようになります。
locateのワイルドカード(暗黙で*pattern*となる｡が!パターンの中にワイルドカードが含まれると)

## 症状

ファイルストレージ内にlogback_admin.xmlとlogback_customer.xmlがあるとします｡

```
path/to/logback_admin.xml
path/to/logback_customer.xml
```

この時､以下のように検索するとマッチしません｡（検索結果が表示されない）

```bash
$ locate "logback_*.xml"
```

## 対処

これまでも､上記みたいな感じで｢うまくマッチしない（意図した結果を得られない）｣ことはあったんだけど､findで代替したり､愚直にファイル名を並べたりしてたので､まじめに調べることがなかったのですが､manしたら､こんな事が書いてありました｡

```
 If any PATTERN contains no globbing characters, locate behaves as if the pattern were *PATTERN*.
```

｢パターンに特殊文字（globbing characters）がない場合は､自動的にアスタリスク("*"）で囲む｣そうです｡
ということは､､､特殊文字があると｢自動で囲まない｣ということですね｡｡｡

ということで､パターンの先頭にアスタリスク("*"）をつけることで無事に見つけることができました｡

```bash
$ locate "*logback_*.xml"
path/to/logback_admin.xml
path/to/logback_customer.xml
```

## ChatGPT様のご回答

Bashでむちゃくちゃ助けられているChatGPT様ですが､今回は以下のような回答しか得られず原因･正解を特定できませんでした｡教えてあげたので､賢くなるといいな｡

- updatedbしてないのでは?
- そもそもファイルがないのでは?
- バージョンや実装によって対応していないものがある

## 教訓

`man`しろ
Figmaのプロトタイプで動画を表示！


Figmaのプロトタイプ動画機能を使用すると完成デザインがイメージしやすくなります。
この記事では、Figma上での動画の扱い方をいくつか見ていきます。

※ 有償アカウントのみの機能になります。プレビューは制限ありません。

## 動画を配置
まずは、動画をFigmaにドラッグ＆ドロップして配置します。
読み込める形式は.mp4、.mov、.webmです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/f5e0c225-ff7c-ce9f-372a-42a7e02ff3b6.png)
デザイン上では、もちろん再生しないですが、再生プレビューは確認できます。
塗りオブジェクトなので画像同様に、マスクや透過などfigma上で自由度高く編集できます。

それでは **背景に動画を流すデザイン**を作例に見ていきましょう。


## デフォルト設定

プロトタイプ画面で動画を選択するとデフォルト設定は以下のようになっており変更もできます。
- **自動再生**
- **ループ**
- **音声あり**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/4478d475-3935-c01f-fb23-4f7467019882.png)


## プロトタイプでプレビュー
再生されました。ループ設定にしています。
![01&02_1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/da1f786d-8a65-a991-a1c0-c84776a85f8b.gif)

画像のように扱えるので大きくしたり
![01&02_2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/3762d9e9-7133-e7ca-45f8-e5d312d1663f.gif)

色をつけたり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/aa13e919-d590-17f8-cdad-1aac1750bbcc.png)
### 再生/一時停止
デザインに再生・一時停止ボタンを追加し動画を制御できます。
![04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1770935/65d5c34d-4abc-6b71-e94a-b10bf7251213.gif)
## まとめ
動画組み込み実装がある場合、デザイン上で実際のイメージが検証できます。
figmaは日々アップデートされており、他にも様々な動画機能があるのでプロトタイプの動画機能を活用してみてはいかがでしょうか。
AccessのVBAでエクセルファイル内の特定名シートを左端or右端に移動

# やり方

参照設定で下記を追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f0758a26-3327-3422-1e9a-de73862078d7.png)

```vb:サンプル
'フォーム上に『btn_1』という名前のオブジェクトがある前提。
'そのクリックイベント。
Private Sub btn_1_Click()

    Dim excel_ As New Excel.Application
    
    'バックグラウンドで起動
    excel_.Visible = False
    excel_.UserControl = False
        
    'Accessファイルと同じフォルダーにあるtest.xlsxが対象。
    excel_.Workbooks.Open FileName:=CurrentProject.Path & "\test.xlsx"
    
    '『あ』という名前のシートが無いと『インデックスが有効範囲にありません』の例外になるので注意。
    
    '一番左に移動。
    '『あ』という名前のシートが既に一番左になっていたとしても、例外にはならない。
    excel_.Worksheets("あ").Move Before:=excel_.Worksheets(1)
    
    '一番右に移動。
    '『あ』という名前のシートが既に一番右になっていたとしても、例外にはならない。
    'excel_.Worksheets("あ").Move After:=excel_.Worksheets(excel_.Worksheets.Count)
    
    '保存して閉じる。
    excel_.Workbooks(1).Close SaveChanges:=True
    excel_.Quit
    
End Sub
```

# 参考サイトさん

https://www.tipsfound.com/vba/10006

# バージョン

Windows 10 Pro 22H2 19045.2965
Microsoft Access for Microsoft 365 MSO (バージョン 2304 ビルド 16.0.16327.20200) 32 ビット
Azure OpenAIのGPT-4にてChatCompletionをcurlする方法

# はじめに

Azure OpenAIのGPT-4についてChatCompletionパラメータの作り方のメモです。
OpenAI Python SDKについてはAzureで詳細な解説がありますので[こちら](https://learn.microsoft.com/en-us/azure/cognitive-services/openai/how-to/chatgpt?pivots=programming-language-chat-completions)を参照してください。

# パラメータ説明

使用者固有になる部分の設定内容です。

最初のXXXXX部分はAzure管理画面の**キーとエンドポイント**に表示されている**エンドポイント**を設定しましょう。このような表示になっていると思います。

:::note info
https://XXXXX.openai.azure.com/
:::

次のXXXXX部分はAzure管理画面の**モデル デプロイ**に表示されている**モデル デプロイ名**を設定しましょう。

次のXXXXX部分はAzure管理画面の**キーとエンドポイント**に表示されている**キー 1**を設定しましょう。

# curlサンプル


```sh
curl "https://XXXXX.openai.azure.com/openai/deployments/XXXXX/chat/completions?api-version=2023-03-15-preview" \
  -H "Content-Type: application/json" \
  -H "api-key: XXXXX" \
  -d '{"messages":[{"role":"user","content":"令和元年の西暦を教えてください"}]}' | jq
```
返却サンプル
```json
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   477  100   389  100    88    135     30  0:00:02  0:00:02 --:--:--   166
{
  "id": "chatcmpl-7FFh3wod1zWl8PsQWHAeGv42MlZVi",
  "object": "chat.completion",
  "created": 1683869601,
  "model": "gpt-4-32k",
  "choices": [
    {
      "index": 0,
      "finish_reason": "stop",
      "message": {
        "role": "assistant",
        "content": "令和元年は、2019年です。令和は、2019年5月1日から始まった日本の新しい年号です。"
      }
    }
  ],
  "usage": {
    "completion_tokens": 40,
    "prompt_tokens": 21,
    "total_tokens": 61
  }
}
```
# gasサンプル

```js
  var chat_seq = [];
  chat_seq.push({"role": "user", "content": "令和元年の西暦を教えてください"});

  var params = {
    'messages': chat_seq,
  };
  var headers = {
    'Content-Type': 'application/json',
    'api-key': 'XXXXX',
  };
  var data = JSON.stringify(params);
  var options = {
     "method" : "post",
     "payload" : data,
     "headers" : headers,
  };

  var response = UrlFetchApp.fetch("https://XXXXX.openai.azure.com/openai/deployments/XXXXX/chat/completions?api-version=2023-03-15-preview", options);
  let json = JSON.parse(response);
  const answer = json.choices[0].message.content;
```
Googleの2段階認証をクリップボードに貼り付けて、すぐにコピぺできるようにする方法

以下の記事の派生となってます。
・[Googleの２段階認証をアプリを使わずMacのターミナルで行う方法](https://qiita.com/jabba/items/4c5a30b6a31e45c2ab93)
・[[macOS] Terminalからクリップボードを操作する – pbcopy, pbpaste](https://blog.katsubemakito.net/macos/pasteboard-on-terminal)

前者の方の記事では、以下の方法でターミナル上に数字を出す。
```
$ google_key
322445
```
後者の方の記事では、
```
$ date | pbcopy
$ pbpaste
2023年 5月12日 金曜日 14時14分39秒 JST
```

上記2つを合わせて、エイリアスを作ります。
```~/.bashrc
alias google_key='oathtool --totp --base32 "３２文字のキーをスペース無しで入れる” | pbcopy | pbpaste'
```
これもお忘れなく。
```
$ source ~/.bashrc
or
$ . ~/.bashrc
```
超簡単！
最後の「pbpaste」はお好みで。

以上。
Raspberry Pi 4BでOpenFOAM (その2)

初投稿です．

前回の記事で，Dockerコンテナを使ってRaspberry Pi 4BにOpenFOAMを導入するという内容を書いたのですが，その後コンテナを構築せずに行う別の方法も見つけて，何ならその方がよさそうなまであったので，備忘録的に書き残します．

というのも，OpenMPIを用いてノード間の並列計算を行おうと思った際に，Dockerコンテナ上で走らせるにはSSH接続などの面でハードルが高く，今の自分の知識では苦戦しそうな可能性もありました．

環境は前回と変わりません．以下の通りです．
マシン：Raspberry Pi 4B 8GB
OS：Raspberry Pi OS (64bit) 2023-02-21
クライアント：MobaXterm Portable v23.0

基本的な流れは，[こちらに書かれている通りです](https://dev.classmethod.jp/articles/how-to-install-openfoam-in-graviton2/ "OpenFOAMをGraviton2（Arm）インスタンスで動かして計算する")が，ライブラリの依存関係が若干異なっていたそうで，そのままというわけにはいかなかったので，[こちらのドキュメントのやり方を組み合わせて](https://develop.openfoam.com/Development/openfoam/blob/develop/doc/Requirements.md "OpenFOAM® System Requirements")導入していきます．


### ライブラリの導入
ではまず最初に，必要なライブラリを導入していきます．
```
sudo apt-get update
sudo apt-get install build-essential autoconf autotools-dev cmake gawk gnuplot
sudo apt-get install flex libfl-dev libreadline-dev zlib1g-dev openmpi-bin libopenmpi-dev mpi-default-bin mpi-default-dev
sudo apt-get install libgmp-dev libmpfr-dev libmpc-dev
sudo apt-get install libfftw3-dev libscotch-dev libptscotch-dev libboost-system-dev libboost-thread-dev libcgal-dev
```

念のため，ここまででOpenMPIも導入できているか確認しておきます．
```
orterun --version
```

### OpenFOAMの導入
今回はOpenFOAMのソースコードをコンパイルする方法で行きます．
まずは必要ソースコードをダウンロードします．
```
cd /tmp
wget https://sourceforge.net/projects/openfoam/files/v2006/OpenFOAM-v2006.tgz
wget https://sourceforge.net/projects/openfoam/files/v2006/ThirdParty-v2006.tgz
```
ダウンロードしたファイルを，ユーザーディレクトリ内に展開します．
```
mkdir $HOME/OpenFOAM && tar -xzf OpenFOAM-v2006.tgz -C $HOME/OpenFOAM && tar -xzf ThirdParty-v2006.tgz -C $HOME/OpenFOAM
```
展開が終われば，OpenFOAM内のbashrcを読み込み，`foam`コマンドを実行してください．ファイルを展開したディレクトリに飛ぶことが出来ればOKです．
```
source ~/OpenFOAM/OpenFOAM-v2006/etc/bashrc
foam
```
最後にコンパイルします．このコンパイルには，自分の環境では7時間程度かかりましたので，実行する際はご注意ください．
```
./Allwmake -j -s -l
```
コンパイルが終わったら，OpenFOAMディレクトリ上で，テストコマンド`foamInstallationTest`を実行し，問題なく導入できているか確認することをお勧めします．
```
foamInstallationTest
```

### 緒言
本記事では，Raspberry Pi 4BにおけるOpenFOAMの導入方法について，Dockerを使わない方法として紹介しました．恐らく，この手法で導入した方が，後々にノード間並列計算を行う際に楽かなと思います(なんとなくの予想ですが)．また，この方法だと，コンテナをいちいち起動しなくとも，bashrcでパスを通しておけばOpenFOAMのコマンドを一通り使えますので，その方がやっぱり分かりやすい気がします．

##### 引用一覧
https://dev.classmethod.jp/articles/how-to-install-openfoam-in-graviton2/ (OpenFOAMをGraviton2（Arm）インスタンスで動かして計算する | DevelopersIO)
https://develop.openfoam.com/Development/openfoam/blob/develop/doc/Requirements.md (OpenFOAM® System Requirements | OpenFOAM Development)
https://develop.openfoam.com/Development/openfoam/blob/develop/doc/Requirements.md (OpenFOAM® Quick Build Guide | OpenFOAM Development)
駆け出しWebエンジニアがフォルダ（ファイル）作成・保存時につまずいた、Linuxのアクセス権限

当方、駆け出しのWebエンジニアです。
環境はWindows 11。

WSL2をインストール→有効化し、ディストリビューション（AlmaLinux9を使用）のインストールも行い、Linux環境の構築に成功。

任意のフォルダに移動し、`mkdir`で適当にフォルダを作成、そこにGitLabからリポジトリをクローン。
ここまでは成功したものの、必要なファイルを手動で作成する必要があることに気付く。

Windowsのエクスプローラーで Linux → AlmaLinux9 にアクセス。
お目当てのフォルダに行き、新規フォルダを作ろうとした際に**アクセス権限が無いために作れない**という問題が発生。

初心者がつまずくのはこういうところだと思うのですが、なかなか初心者目線の記事って無いもので、結構ハマりました💦
というか、今回インストールしたものすべてを一旦消し、再インストールしました。

AlmaLinux9を初回起動時にユーザー名とパスワードの作成を求められます。
それはそれで作るしかない（？）ですが、そのあと
```
sudo su -
```
でrootユーザーに変更。

それからまたクローンし直しました。
当初、作ったユーザーでクローンしてあって、その状態で手動のフォルダ作成を試みるとNGでしたが、rootユーザーに変更した上でクローン、手動でフォルダを作成しようとすると、普通に作れました。
たぶん、作ったユーザーのアクセス権限が良しなに機能していなかったものかと思われます。
ここの兼ね合いで、フォルダやファイルの作成・保存時に影響が出るものかと・・・🤔

# アクセス権限とは
LinuxだけでなくMacやWindowsでもパソコンにあるファイルの扱いには、読む、書く、プログラムとして実行するの3つの操作がある。
その3つを誰が操作できるのかを決定するのが、アクセス権限。
「所有者」、「グループ」、「他のユーザー」の3つがある。
「所有者」はファイルを作成したユーザー自身、「グループ」はファイルを共有するための任意のグループ、「他のユーザー」は所有者でもなく、グループにも所属しないがそのパソコンにアクセスできる全てのユーザーのこと。

ターミナルから設定する場合は、アクセス権限の読み方について知る必要があり、GUIでは`所有者：自分　アクセス：「読み取り専用」`などと表示されるが、ターミナルでは以下の写真のようにアルファベットとダッシュ記号を組み合わせた`1・3・3・3`の計10文字で表示される。
最初の文字がファイルの種類、次の3文字ずつのグループがそれぞれ所有者、グループ、他のユーザーの読む(r)、書く(w)、プログラムとして実行(x)の権限を表している。

![read-permission.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3375549/c259e6b8-31b7-6bd5-899c-cafde8edf9ad.jpeg)

| 種別 | 意味 |
|:-:|:-:|
|-|ファイル|
|d|ディレクトリ|
|l|シンボリックリンク|

アクセス権限は通常のアルファベットの表示だけでなく「751」など数字で表されることもある。
読む、書く、プログラムとして実行にはそれぞれ`4 、2、1`の数字が割り当てられていて、権限は数字の合計で表される。
アルファベットの表記と同じように各数字が所有者、グループ、他のユーザーの権限をそれぞれ表す。

![read-permission2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3375549/ada1b790-ad09-47cf-7618-ed73398775dd.jpeg)

> 参照
> > https://allabout.co.jp/gm/gc/447459/

ちなみに今回はrun.shというファイルに`chmod 755`で実行権限を所有者、グループ、他のユーザーのすべてに付与しました。

付与前：-rw-r--r-- 1 root root 2960 May 12 12:30 run.sh
付与後：-rwxr-xr-x 1 root root 2960 May 12 12:30 run.sh
GitHub ActionsとArgoCDを使用したCI/CDの一例と感想

# はじめに
CI/CDの学習のため，初めてGitHub ActionsとArgoCDを使用したので，作成したパイプラインの紹介と感想を書きます．

# 目次
[1.はじめに](#はじめに)
[2.目次](#目次)
[3.作成したもの](#作成したもの)
[4.感想](#感想)
[5.おわりに](#おわりに)

# 作成したもの
まずは作成したCI/CDパイプラインを紹介します．
![Django_CICD.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365485/8efb4b12-8144-a1b8-6351-7f40eec7ac43.jpeg)

このように作成しました．

コードがpushされると，GitHub Actionsが起動します．
ユーザが作成したコード(今回はDjango)をGitHub Actions内でテストします．
テストを通ったものはimageを作成しDocker Hubにアップロードします．
次にk8sのManifestsが置いてあるレポジトリに対してイメージの名前を更新してcommit, pushを行います．

次にmanifestsの更新をArgoCDが感知して，Kubernetesに対してimageの更新を要求します．
更新されたらデプロイまで完了です．

# 感想
## できたこと
### GitHub Actions
GitHub Flowを中心として考えると，使用するサービスの選定がかなりスムーズに感じました．
素直にGitHub Actionsを使用していれば，コードを元に使用すべきworkflowsを提案してくれます．今回はDjangoだったので当然workflowがあり，ほぼ選択するだけでテストが実装できました．
jobの流れもUIで確認出来て，動作中は緑のチェックが出ていくのをワクワクしながら見守ってました(笑)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365485/2b7cbf87-f36f-fa82-71b4-1154c17bc859.png)


### ArgoCD
ArgoCDについても非常に素直で初めて学ぶ身としては，GUIがありがたかったです．設定内容も大して躓くこともなく，素直に使用できました．

【追記】
クラスターを移動させる機会がありました。移動のため新しいサーバにはArgoCDを導入し、リポジトリを登録したところ、すぐにリソースが作成され、稼働が開始しました。以前はyamlファイルを移動させて、手動でapplyしていたためArgoCDの良さをとても強く感じました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2365485/0d2ca8a8-b205-c4ea-f98a-8616f9d024dd.png)


## 苦労したこと，できなかったこと
1. サービスの数が多かったため，アカウントやtokenの扱いに苦労しました．おそらくAWS等のクラウドサービスでまとめて管理すればもう少し簡単だと思います．
【追記】私はHashiCorp Vaultを使用して解決しました．

2. docker hubに上げたimageのpullに苦労しました．初めはtagをmainにしていたので，更新されたことが検知できず，pullをしてくれなかったです．一度常にimageをpullする仕組みにしましたが，やはりtagで管理すべきではと思い，GitHubのtagから引っ張ってくることにしました．

3. 上のことに関連しますが，ArgoCDがGitHub Actionsから見えていないため，imageがpullされているかを確認するために結局ページにアクセスする必要がありました．workflowの中でデプロイができたかどうかも確認できるとすべて1つの画面で見れて楽なのですが...　ここに関してはSlackなどで通知するという解決方法がありそうです．

# おわりに
半分は個人的な感想っぽくなってしまいましたが，CI/CDに使用するサービスの決定の手助けになったらいいなと思います．
DFMとは

## DFM（Delphi Form）は、DelphiのIDE（統合開発環境）で使用されるフォームファイルの拡張子

DFMファイルには、
・フォームに配置された各種コンポーネントの情報
・コントロールの位置やサイズ、フォントや色、イベントハンドラーなどの設定
が含まれている
この情報を読み込む→Delphiはフォームを再現し、コンポーネントの動作を制御できる

DFMファイルは、Delphiプログラムを開発する際、必須のファイル
ソースコードとともにバージョン管理されることが一般的
AccessのVBAでエクセルファイル内に特定の名前のシートが存在するか判定

# やり方

参照設定に下記追加。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/95489657-f26e-82e9-6c3d-8cbe8ca69aed.png)

```vb:サンプル
'フォーム上に『btn_1』という名前のオブジェクトがある前提。
'そのクリックイベント。
Private Sub btn_1_Click()

    Dim excel_ As New Excel.Application
    
    'バックグラウンドで起動
    excel_.Visible = False
    excel_.UserControl = False
    
    'Accessファイルと同じフォルダーにあるtest.xlsxが対象。
    excel_.Workbooks.Open FileName:=CurrentProject.Path & "\test.xlsx"
    
    'Excel.Applicationに『シート存在チェック関数』といったものは無い。
    'シート一覧をループして一つ一つ名前を取得して判定が必要。

    'excel_.WorksheetsはFor Eachのインターフェース無いのでForでまわす。
    Dim i_ As Long
    For i_ = 1 To excel_.Worksheets.Count
        'excel_.Worksheets(i_)が非表示シートであっても例外にならない。
        'また、非表示シートだからとって『取得したシート名が空やNULL』といったこともない。
        '（シートが非表示かどうかは気にしなくてOK）
        If excel_.Worksheets(i_).Name = "あ" Then
            MsgBox "あるよ", vbInformation
        End If
    Next
    
    'エクセルは保存せずに閉じる。
    excel_.Workbooks(1).Close SaveChanges:=False
    excel_.Quit
    
End Sub
```

# 参考サイトさん

https://excel-toshokan.com/vba-isexistssheet/

# バージョン

Windows 10 Pro 22H2 19045.2965
Microsoft Access for Microsoft 365 MSO (バージョン 2304 ビルド 16.0.16327.20200) 32 ビット
ChatGPT活用の医療現場：AI技術と共感的なコミュニケーション

医療現場でのAI活用が注目されていますが、特にChatGPTは診断支援や病歴整理などの様々な用途でその可能性が評価されています。

岐阜大学大学院 医学系研究科 脳神経内科学分野 教授の下畑さんがFacebookに投稿した内容によれば、ある研究でChatGPTが患者さんの質問に対して医師よりも質が高く共感的な回答ができることが明らかになりました。78.6%の患者がChatGPTの回答を選んでいました。

https://www.facebook.com/plugins/post.php?href=https%3A%2F%2Fwww.facebook.com%2Fshimohata%2Fposts%2Fpfbid02DUmdcf43vjUhLmX3X8mKbGYkmufoioZHgpXmCWTdnAX2uJKfoEDNjgWSMFSKaJP3l

## はじめに：医療現場でのChatGPT活用の重要性

近年の人工知能（AI）技術の進歩は、医療現場においても大きな影響を与えています。特に、AIチャットボットであるChatGPTは、医療現場での様々な活用が期待されており、その重要性は日々高まっています。医師や看護師、そして患者さんに対しても、わかりやすく効率的なコミュニケーションを提供することで、医療現場におけるサービス向上に貢献しています。

ChatGPTの活用は、診断支援や病歴整理、患者さんとのコミュニケーションなど、医療現場の多岐にわたる場面で実現されています。これにより、より迅速かつ正確な診断や治療の提供が可能となり、患者さんの満足度向上や医療従事者の負担軽減にも繋がります。

また、ChatGPTがマルチモーダルAIに進化することで、テキストだけでなく画像や音声など複数のモーダリティを活用した診断や治療の支援が可能になります。これにより、医療現場でのAIの活用範囲が拡大し、より包括的で精密な医療サービスの提供が期待できます。

## ChatGPTによる診断支援

### 症状判断の正確さと迅速性

ChatGPTは、患者さんからの質問や症状の説明に対して、正確かつ迅速に回答を提供することができます。これにより、患者さんの不安を軽減し、適切な治療への道筋を示すことが可能になります。また、初期診断の精度向上にも繋がるため、早期治療や予防にも役立ちます。

### 医師との協働による診断の精度向上

ChatGPTは、医師と協働することにより、より精度の高い診断を実現することができます。医師がChatGPTの提案を参考にしながら、自身の経験や知識を活かして診断を行うことで、患者さんに最適な治療方針を提案することができるのです。このような医師とChatGPTの協働は、医療現場における診断プロセスの効率化と質の向上に寄与します。

## 下畑教授によるFacebook投稿の分析

### ChatGPTの共感的回答の重要性

下畑教授のFacebook投稿では、ChatGPTが患者さんの質問に対して共感的な回答を提供できることが強調されています。共感的な回答は、患者さんが心理的に安心し、信頼を感じることができるため、医療従事者と患者間のコミュニケーションの質を向上させます。

### 医師のバーンアウトの抑制と患者転帰の改善

また、下畑教授は、ChatGPTの活用が医師のバーンアウトを抑制し、患者さんの転帰を改善する可能性があると指摘しています。医師がChatGPTと協力して業務を行うことで、効率化が図られ、医師の負担が軽減されます。これにより、医師の精神的な健康が保たれ、患者さんへのサービスの質が向上することが期待されています。

「患者さんの転帰を改善する」とは、患者さんの治療やケアの結果がより良い方向に向かうことを意味します。具体的には、病状の回復や症状の改善、予後の良好化、生活の質の向上、再発や合併症のリスクの低下などが含まれます。医療従事者がChatGPTを利用することで、効率的に業務を行い、患者さんへのサービスの質が向上し、その結果、患者さんの転帰が改善されることが期待されています。

## ChatGPTの医療現場への影響

### 医師と患者のコミュニケーションの変化

ChatGPTが医療現場に導入されることで、医師と患者間のコミュニケーションにも変化が見られるでしょう。ChatGPTは、病状に関する質問に対して迅速かつ適切な回答ができるため、医師の負担を軽減し、より充実したコミュニケーションが可能になります。また、共感的な回答を提供する能力も持っているため、患者さんが安心感を持って治療に臨むことが期待されます。

### 医療業界へのデジタルトランスフォーメーション

ChatGPTの導入は、医療業界全体のデジタルトランスフォーメーションを促進します。診断支援や病歴整理などの業務を効率化し、医療データの管理や分析を容易にすることで、医療サービスの質が向上する可能性があります。また、医療機関の運営コストの削減や、リモートでの診察やフォローアップなどのテレヘルスサービスの拡大も期待できます。

## まとめ：医療現場でのChatGPT活用の将来展望

医療現場でのChatGPT活用は、医師と患者のコミュニケーションや医療業界全体のデジタルトランスフォーメーションに大きな影響を与えると考えられます。適切な利用と管理のもとで、医療現場の効率化や患者さんの転帰の改善に寄与し、未来の医療の質向上につながることが期待されています。
PulseAudioを使ったアプリケーション間ループバック用の仮想オーディオデバイスの作成

Zoomの会話をChromeに渡して文字起こししたかったので色々調べて仮想オーディオ構築したメモ。
入出力ともにシステムオーディオとループバックして汎用性を持たせてます。
`dont_move`オプションあたりの情報がなかなか見つからなくて苦戦しました。

```mermaid
flowchart
    classDef device fill:#FFECEC,stroke:#DB7093
    input[Input]:::device
    output[Output]:::device

    classDef virtual fill:#ECECFF,stroke:#9370DB
    vin(virtual.line):::virtual
    vout(virtual.mixmic):::virtual

    vin-->|loopback|vout
    vin-->|loopback|output
    input-->|loopback|vout

    classDef app fill:#ECFFEC,stroke:#70DB93
    zoom(Zoom):::app
    chrome(Chrome):::app

    input-->zoom
    zoom-->vin
    vout-->chrome
```



```bash:~/.config/pulse/default.pa.src
.include /etc/pulse/default.pa

# Create virtual.line
load-module module-null-sink \
  sink_name=virtual.line \
  sink_properties=device.description="virtual.line.input"

# Create virtual.line.source
load-module module-remap-source \
  master=virtual.line.monitor \
  source_name=virtual.line.source \
  source_properties=device.description="virtual.line.output"

# Create virtual.mixmic
load-module module-null-sink \
  sink_name=virtual.mixmic \
  sink_properties=device.description="virtual.mixmic.input"

# Create virtual.mixmic.source
load-module module-remap-source \
  master=virtual.mixmic.monitor \
  source_name=virtual.mixmic.source \
  source_properties=device.description="virtual.mixmic.output"

# Loopback virtual.line -> virtual.mixmic
load-module module-loopback \
  sink=virtual.mixmic sink_dont_move=true \
  source=virtual.line.monitor source_dont_move=true

# Loopback Default Input -> virtual.mixmic
load-module module-loopback \
  sink=virtual.mixmic sink_dont_move=true

# Loopback virtual.line -> Default Output
load-module module-loopback \
  source=virtual.line.monitor source_dont_move=true
```

:::note warn
上記の`default.pa.src`には可読性のため改行を加えています。
有効なPulseAudio Configファイルとするためには次のように置換する必要があります。
```bash
sed -ze 's/\\\n//g' default.pa.src > default.pa
```
:::

```bash:~/.config/pulse/default.pa
.include /etc/pulse/default.pa

# Create virtual.line
load-module module-null-sink sink_name=virtual.line sink_properties=device.description="virtual.line.input"

# Create virtual.line.source
load-module module-remap-source master=virtual.line.monitor source_name=virtual.line.source source_properties=device.description="virtual.line.output"

# Create virtual.mixmic
load-module module-null-sink sink_name=virtual.mixmic sink_properties=device.description="virtual.mixmic.input"

# Create virtual.mixmic.source
load-module module-remap-source master=virtual.mixmic.monitor source_name=virtual.mixmic.source source_properties=device.description="virtual.mixmic.output"

# Loopback virtual.line -> virtual.mixmic
load-module module-loopback sink=virtual.mixmic sink_dont_move=true source=virtual.line.monitor source_dont_move=true

# Loopback Default Input -> virtual.mixmic
load-module module-loopback sink=virtual.mixmic sink_dont_move=true

# Loopback virtual.line -> Default Output
load-module module-loopback source=virtual.line.monitor source_dont_move=true
```
java初心者が行く～コレクション_List～

# はじめに
java初心者が備忘録的に書いています

# コレクション
javaにはデータをまとめて格納するためのAPIとしてコレクションフレームワークが定められている。
実務とかで使うことが多そう（List, Set, Mapとか）。
今回は有名なコレクションのなかでListに分類されているArrayListとLinlesListをまとめていく。

# ArrayList
ArrayListは配列と似ていて要素を追加できるコレクションである。
書き方は
```java
ArrayList<型名> 変数名 = new ArrayList<型名（省略もできる）>();
```
具体的な使い方は書き方としては以下の通り。

```java:Sample
import java.util.ArrayList;

public class Main {

    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<String>();

        list.add("a");
        list.add("b");

        for (int i = 0; i < 2; i++) {
            System.out.println(list.get(i));
        }
    }
}
```
ArrayListがもつメソッドを一部紹介
add(x)->リストの最後にxを追加
add(int, x)->int番目にxを挿入
set(int, x)->int番目にxを上書き
size()->格納されている要素数を返す

ArrayListは配列と違い要素が削除されたらそれ以降の要素が一個前に詰められる。
例）
0 1 2 3
a s d f
1番目のsを削除
0 1 2
a d f

# LinkedList
LinkesListもArrayListと同じリストのクラス。よって書き方もArrayListをLinledListに書き換えればよいだけである。
しかしLinkesListはArrayListより要素の追加や削除を高速的に行うことができる。
これはクラスの内部実装の違いからおこる。
LinkedListは値の挿入や削除を行った場合に変更対象の一つ前の要素に対して次を指し示す矢印的なものを連結すればよいから高速なのである。
逆にArrayListは削除や追加を行ったら各要素を削除なら一つ前へ、追加なら一つ後ろへコピーしなおす必要がある。このため処理速度に差が出る。
Mat画像をTesseractのPixクラスに変換


すぐには分からなかった。結局Matをバイト配列に変換させてPix.LoadFromMemory関数で変換している。

### 環境
* Tessaract 5.2.0
* OpenCvSharp 4
* C#

画像の一部を切り抜いて、切り抜いた部分の文字列を取得するコードの切り抜き。

```C#
OpenCvSharp.Rect retval = Cv2.BoundingRect(contour);
OpenCvSharp.Rect rect = new OpenCvSharp.Rect(retval.TopLeft, new OpenCvSharp.Size(retval.Width, retval.Height));
Mat rectMat = _thresholdMat.Clone(rect);

byte[] bytes = rectMat.ToBytes(); // バイト配列に変換
Pix pix = Pix.LoadFromMemory(bytes); // Pixクラスに変換
TesseractEngine engine = new TesseractEngine(dataPath, "jpn");
Page page = engine.Process(pix);
```
# 【初心者】スクロール操作無効をVanilla JSで制作【備忘録】

# はじめに
投稿時点で、筆者は知識ゼロの状態から勉強を初めて3ヶ月程度の実力です。
そのため、理解不足や説明不足、誤った内容や呼び方をしている可能性があります。
万が一参考にする場合は上記の点を考慮した上でご一読ください。
説明文の内容はChatGPT先生からの引用も多いです。

# 制作過程
スクロール無効を実装しようと思った理由は、ハンバーガーメニューオープン中はスクロールができないようにしたかったこと。

一番簡単だったのが、CSSと合わせて実装すること。
JSでクラス付与してbodyに、 `overflow: hidden;` を加える。
```javascript
const body = document.body;

button.addEventListener('click', () => {
    button.classList.toggle('is-open'); // メニュー開閉用
    body.classList.toggle('is-noScroll'); // クラス付与してスクロールができないようにする場合
  });
```
```css
body.is-noScroll {
 overflow: hidden;
}
```

これで実装できたが、PC表示だとハンバーガーボタンを押すたびにスクロールバーが表示・非表示を繰り返すのが気になった。
なのでCSSに頼らずJSのみで実装する手段を考えて、結果的に下記になりました。
```javascript
let isMenuOpened = true; // メニュー開閉状態のフラグ
// スクロール操作のイベント定義、preventDefault() メソッドはイベントの既定の動作をキャンセルするために使用される
const handle = (event) => {
 event.preventDefault();
};

// スクロール操作の記述
if (isMenuOpened) { // フラグの状態を見て実行動作を判断
 document.addEventListener('touchmove', handle, { passive: false }); // タッチ操作でのスクロール無効化
 document.addEventListener('mousewheel', handle, { passive: false }); // マウスホイール操作でのスクロール無効化
 } else {
  document.removeEventListener('touchmove', handle); // タッチ操作でのスクロール有効化
  document.removeEventListener('mousewheel', handle); // マウスホイール操作でのスクロール有効化
}
isMenuOpened = !isMenuOpened; // isMenuOpenedの値を反転させる
```

これをボタンクリック部分に入れることで実装できました。
欠点としては、PC表示時にスクロールバーが消えるわけではないので、スクロールバーを直接操作してスクロールをすることはできてしまうという点。
だけどユーザーがそういう使い方をすることはないからいいのかな？
もしくはスクロール検知したらハンバガーメニュー閉じるようにするのもアリかなと思った。
Unityでスペースキーを押されたときの挙動がおかしい問題

### 現象
意図せずボタンイベントが発火したりする。
で、調べるとフォーカスを持ってるUIパーツがスペースキー反応してるらしい。

### 対策
ボタンのInspectorからNavigationの値を「None」にする。（デフォルトは「Automatic」）
ボタン以外のUIパーツに関しても同じく。
neovimに入門してみた

# Vimに入門してみた

## はじめに
この記事はvimのプラグインなどを紹介するのではなくあくまでvimの操作についてまとめた記事です。

自分が今後よく使うだろうなと思うものだけを厳選しているので、効率よくキャッチアップできると思います。

## そもそもvim・neovimって何？
vimはテキストエディタです。

linuxなどを触っているとファイルを編集するときによく使います。

物好きな方はvimをカスタマイズしてIDE(vscodeなど)のように使ってます。

neovimはVim派生テキストエディタです。

スリムになって処理速度が上がり、モダンな機能も使えるって感じです。

基本操作は変わりません。

***メリット***

- キーボードから手を放さずにカーソルの移動、ファイルの切り替えなどが行える
- なんかかっこいい


***デメリット***
- 習得するまでかなり時間を要する




個人的にはタイピングの上達の感覚と似ている気がします。


# モード
vimは4つのモードを駆使して操作します。

- ノーマルモード
- 入力モード
- コマンドモード
- ビジュアルモード


***各モードの簡単な役割***

|モード|役割|
|--|--|
|ノーマルモード|カーソル移動・文字削除|
|入力モード|編集中のファイルに文字を入力|
|コマンドモード|編集保存・コマンド実行・文字検索|
|ビジュアルモード|範囲選択・コピー|

全ての起点はノーマルモードです。

違うモードに移りたかったらまずノーマルモードに移動し、ノーマルモードから他のモードに移る感じです。(コマンドで例外もあります)

### ノーマルモード

**遷移方法**
- vimの起動時のデフォルトのモード
- 各モード時に「Esc」を押す

### 移動系
|コマンド|操作|
|--|--|
|h・j・k・l|←・↓・↑・→に移動|
|gg|ファイルの先頭に移動|
|G|ファイルの末行に移動|
|w|次の単語の先頭に移動|
|b|前の単語に移動|
|e|単語の末尾に移動|
|:[N]|N行目に移動|
|a|一文字前に進みインサートモード起動(eと組み合わせる)|

### 文字操作系
|コマンド|操作|
|--|--|
|yy|現在のカーソール行コピー|
|[N]yy| N行コピー|
|P|現在の行に張り付け|
|x|一文字削除|
|dd|現在のカーソル行削除|
|[N]dd|N行削除|
|D|	現在のカーソルから行末まで削除|
|O|現在の行を改行してインサートモード|


**状態遷移系**
|コマンド|操作|
|--|--|
|u|ひとつ前の状態に戻る|
|Ctl+r|ひとつ後の状態に進む|


**検索系**

|コマンド|操作|
|--|--|
|/[word]|wordを検索|
|n|次の検索結果に移動|
|N|前の検索結果に移動|





### 入力モード
**遷移方法**
- ノーマルモード時に「i」「a」「s」を押す


|コマンド|操作|
|--|--|
|Ctl g + j・k|↓・↑に移動|
|Ctl h|一文字削除|
|ctl + w|単語削除|
|ctl + t|shiftwidth分インデント追加|
|ctl + t|shiftwidth分インデント削除|

### コマンドモード
**遷移方法**
- ノーマルモード時に「:」を押す

**コマンド実行系**
|操作|コマンド|
|--|--|
|![command]|command実行|
|!!|前のコマンド実行|


### ビジュアルモード
**遷移方法**
- ノーマルモード時に「v」,「ctl+v」を押す

|コマンド|操作|
|--|--|
|h・j・k・l|←・↓・↑・→に範囲を選択しながら移動|
|c|選択された範囲を削除してインサートモードに移行|


# さいごに
自分が今後vimを使っていく際に基盤となるであろうコマンドについて最低限解説しました。

もちろんまだまだ便利なコマンドがたくさんあります。

自分もまだ初心者なので「こんな便利なコマンドあるよっ」と言ってもらえると喜びます。

Vimの森を一緒に彷徨いましょう（笑）。
【速報】Bard、日本語対応

# タイトル通り
Bardが日本語に対応しました。
https://japan.googleblog.com/2023/05/bard.html
あとなんかダークモードが追加されてました。

# 実験
### コーディング
英語よりは劣る
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920761/50c41bfe-7313-445f-4e58-22d9c47e581e.png)
一応書けはするようです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920761/7bcaddbd-1cd5-4b5c-325c-11bcbebe620a.png)
あほだった
理解しているくせにエラーがあると言ってくれません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920761/d86213c1-9137-75cd-6a2c-e63b6be309fb.png)
ﾅﾝﾀﾞｺｲﾂ
すごい上から目線ですね


### あいさつ
### 【悲報】日本語版、無愛想
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920761/19837e69-f3fb-3f44-1b96-e80db050a305.png)

### データ取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2920761/6ee19307-9219-2094-ce8b-9130f4f18b4a.png)
誤字となんかちょっとおかしいのでダメです

### 結論
コーディング:若干落ちる、かつ英語版の欠点も引き継ぐ
あいさつ:無愛想
データ取得:英語版と同じような精度
Z80にUSB

以前はFTDIのチップで[Z80ボード](https://qiita.com/yamori813/items/917775ac94c1bd40d746)の[モニター](https://qiita.com/yamori813/items/92084a34a376feb21488)に接続してたのですが、MCP2221のストックがあったので、差し替えました。

![z80-usb.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/c4948a99-0ef8-acf4-2157-52b4ef91f1b0.jpeg)

|8251|pin|MCP2221|pin|
|:--|:--|:--|:--|
|TDX|19|Rx|5|
|RDX|3|Tx|6|
|-|-|USB D+|13|
|-|-|USB D-|12|

MCP2221の電源はZ80側のものを利用しました。RESETは10Kでプルアップしてあります。

おそらくこのスペースは当初はMAXのRS232C変換を置く予定だったようなきがします。

[z80float](https://github.com/yamori813/z80float)をダウンロードしてzmacとld80をコピーしてmakeでアセンブルして、出来上がったSBC用のhexファイルをRLoginでファイルアップロードして実行してみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/d0cf1d1e-4553-2df7-bce5-189e147017a2.png)

送信処理でゆっくり送信すると安定するようです。

ラッピングのツールが壊れて上手く巻けずピンセットで補修していて、またラインが折れやすくなって、かなり怪しいので何時まで動くか心配なので、丁寧に扱いたいと思います。
Z80にはDIPなICが良く似合います。
楽に眠らせる！Laravelの新しいSleepファサードで！

# 概要

私の経験ではローカル開発以外には`sleep()`と`usleep`機能はあまり使われていないですが、使った時には単体テストでsleepが行われたかどうかを確認するのはほぼ無理でした。[Laravelの10.10](https://github.com/laravel/framework/releases/tag/v10.10.0)のリリースでsleep機能のラッパーのSleepファサードが追加され、実装を初め、テストも簡単にできるようになりました！

# 使い方

## 眠らせる方法

Sleepファサードは生phpの`sleep()`のエイリアスの関数があり、元の関数と同じように処理を一時停止したい秒数を引数として渡せます。

```php
use Illuminate\Support\Sleep;
 
$isFinished = false;
 
while (!$isFinished) {
    Sleep::sleep(2);
 
    $isFinished = /* 処理が終わったかどうかのチェック */;
}
```

上記のラッパー機能だけではあまりメリットを感じる方がいないかと思いますが、
秒数だけではなく、`ミリ秒`,`マイクロ秒`,`分`も設定できます。

**さらに**`until()`の関数でタイムスタンプで決定の日付・~分後・~時間後まで処理を停止することも設定できます。

```php
// ２秒に処理を一時停止
Sleep::for(2)->seconds();
 
// 200ミリ秒に処理一時停止
Sleep::for(200)->milliseconds();
 
// 2000マイクロ秒に処理一時停止
Sleep::for(2000)->microseconds();
 
// 決定した時間まで処理一時停止 （来年まで。。。。）
Sleep::until(now()->addYear());
```

`and()`を使うことで、期間設定を組み合わせることもできます（たとえば秒数＋マイクロ秒）。

```php
// 2秒20マイクロ秒に処理停止
Sleep::for(2)->second2()->and(20)->microseconds();
```

### 眠ったかどうかのテスト方法

皆ご存知かと思いますが、ファサードの一つの強みがテスト内の使いやすさです。Sleepファサードももちろん、テストができるようのモック`fake`の機能もあり、いくつかのアサーションもあります。
さらに下記の例のように生phpのsleep関数を使った場合、テストの処理でも一時停止され、テストが完了までに遅くなるかと思います。

```php
use Illuminate\Support\Sleep;
 
$isFinished = false;
 
while (!$isFinished) {
    sleep(2); // こうれがテスト内でも実行されますので、２秒停止される！！！
 
    $isFinished = /* .... */;
}
```

そこで、`fake()`の関数を使えば、テストの処理が停止せずに実行されるため、テストの実行時間が早くなります。
その上、Sleepファサードが実行された回数、停止した期間などのアサーションもあり、簡単に機能をテストができます。

```php
use Illuminate\Support\Sleep;
 
 // Sleepファサードをモック
Sleep::fake();
 
// Sleepファサードが2回実行されたかのチェック
Sleep::assertSleptTimes(2);
 
// Sleepファサードが一回も実行されなかったかのチェック
Sleep::assertNeverSlept();
 
// Sleepファサードが停止した時間が０秒かのチェック　（実行された回数を問わず）
Sleep::assertInsomniac();
```

# エンジニアのユーモア

この機能が便利といえば便利ですが、個人的にこのファサードについて一番面白かったのは[PR](https://github.com/laravel/framework/pull/46904)内のやりとりでした。

元もこのファサードのクラス名前がメキシコの`昼寝`と意味する`Siesta（シエスタ）`で、他に「短い間」を表す`Snooze`や`Rest`の提案もありました。ちょっとギャグっぽいですが自分は`Snooze`が結構気に入りました。。。
どうしても、PRの作成者が`Siesta`に気に入って、下記のようにインポートするタイミングで[元の名前を使う](https://github.com/laravel/framework/pull/46904#issuecomment-1533888970)つもりらしいです。

```php
use Illuminate\Support\Sleep as Siesta;
```

その上、`Sleep::assertInsomniac()`の関数の名前が`不眠症`の言葉も使っていって、結構ユーモアのある名前になりました。Taylor Otwell さんがその関数の`assertNeverSlept()`のエイリアスを作って、元の関数を[イースター・エッグ（おまけ要素)](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%BC%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%BB%E3%82%A8%E3%83%83%E3%82%B0_(%E3%81%8A%E3%81%BE%E3%81%91%E8%A6%81%E7%B4%A0))として残しました。

思ったより、オープンソースソフトウェアの貢献者はギャグが好きですね。

# まとめ

[Laravel 10.10](https://github.com/laravel/framework/releases/tag/v10.10.0)のリリースに処理を一時停止する`Sleep`ファサードがリリースされました。このファサードは生phpの`sleep()`関数のラッパーで、テスト内で簡単にモックもアサーションもできます。便利でユーモアもある機能なので、ぜひ使ってみてください！

# 参考の資料

[Laravel 10.10のリリース](https://github.com/laravel/framework/releases/tag/v10.10.0)
[Siesta のPR](https://github.com/laravel/framework/pull/46904)
[公開ドックス](https://laravel.com/docs/10.x/helpers#sleep)
[イースター・エッグとは](https://ja.wikipedia.org/wiki/%E3%82%A4%E3%83%BC%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%BB%E3%82%A8%E3%83%83%E3%82%B0_(%E3%81%8A%E3%81%BE%E3%81%91%E8%A6%81%E7%B4%A0))
脆弱性を探す話 2023

最近年2回のサイボウズ以外はほぼバグバウンティしていない現状であるが、やる気が起きたときようにメモ

主にWebアプリに関すること

# 診断と自分で勝手に脆弱性を探す行為との違い

- 網羅性は全く必要ない

診断は網羅してないと怒られることがあるが好きな脆弱性だけ探せる。

- 期間が永遠

診断期間は自由なので後で気づいて頭を抱えることはない

- 攻撃に到るまでを説明する必要がある

「バージョンが古いのでダメです」だけでは許してもらえない

- 変なことすると逮捕される可能性がある

無闇にツール回すと不正アクセス禁止法に引っかかるので

だがしかし海外勢は法律の違いもあるのか好きなサイトに気軽にツールを回すので太刀打ちできない

日本人としては許可されたところかローカルに環境作って攻撃するのが心理的安全性が高い

# 2023年度の傾向

- コモディティ化が進む

自分だけしか知らないような脆弱性はない

まだ知られていない手法もほぼない

ブラウザーとかスマホアプリとかIoTデバイスとかにはまだあるのかもしれないが知らない

- 自動化が進む

到るところにrecon自動化ソリューション

- reconFTW 

- reNgine

- Sn1per

## 自動化のだいたいの流れ

### OSINT

- Whoisとかホスト情報
- Google Dorks
- Github Dorks
- Metadata

### サブドメイン検索

- amass
- subfinder  
- SSL証明書
- DNS
- WaybackMachine

### Webサイトマッピング

### 脆弱性スキャン

- ActiveScan
- PassiveScan

自動化で何とかなる箇所はレッドオーシャンな気がするので今から参入するには敷居が高そう

# 探す脆弱性

## 終わった脆弱性

### IE限定のXSS

ようやくIEが死んだがもしかするとWindowsのコンポーネントのどこかに潜んでるのかもしれない

### Flash関連

Flashが死んだのでもう知らなくていい

## ほぼ終わった脆弱性

### CSRF

ブラウザーが対応した

デフォルト SameSite=Lax

JSでAPI叩いて表示する系のサイトにはほぼ関係ない

### 反射型 DOM based XSS

location.hashがURLエンコードされない現行ブラウザはもうこの世にない

location.hashを$()に入れるサイトは無限にあるがjQuery 1.7以下を使ってるサイトはさすがにほとんどない

### Refererによるリーク

ブラウザーが対応した

Referrer Policy

## 復活した脆弱性

### 反射型XSS

ブラウザーがXSSフィルタを止めた

CSPってどうなってるのか

## ちょっと前に流行ったが終わりつつある脆弱性

### subdomain takeover

プラットフォーム側が対応した

バウンティが下がった

Scopeから外すところも増えてる

### SSRF

クラウドベンダーが対応した

被害が限定的に

### prototype pollution

ほぼnodejs限定

さすがに刈り尽くされた感

クライアントで見つかることはほぼない

### ReDoS

言語、正規表現エンジンが対応

気軽に試すと逮捕案件

## ちょっと新しいタイプの脆弱性

### クラウド設定の問題

- SSRFは終わりは近いがまだあるかも

- S3バケットの漏洩

- その他設定ミスは永遠

- request smuggling

### キャッシュ設定の問題

- Cache Deception

- Cache Poisoning

### サードパーティーAPIの問題

- 権限設定のミス

- APIキーのハードコード

### 仮想環境の問題

### 2段階認証のバイパス

- 最近わりと受け付けられている気がする

### テンプレートインジェクション

フレームワークごとに異なる

### 再び注目されている脆弱性

- レースコンディション

- TOCTOU

----

# バグバウンティプラットフォーム

HackerOne一強だった時代から少し変わってきてるかもしれない

会社で直接受付しているところも増えている気もする

## 英語で受け付け

- HackerOne
- bugcrowd
- intigriti
- YesWeHack
- GObugfree
- huntr.dev
- OpenBugBounty
- Snyk

## 日本語が通じそうなところ

- IssueHunt
- Bugbounty.jp

# 会社独自

## 英語で受け付け

- Google
- Microsoft
- Meta
- Mozilla
- Apple

## 日本語が通じそうなところ

- サイボウズ
- Sky
- 任天堂
【初心者向け】【JS・TS】forEachのコールバック関数内の非同期処理は、async/awaitで同期処理化できない

# 最初に

本記事で紹介することは、JSでforEachやmap等のコールバック関数で処理をするメソッドを使い始めたときに、誰もがやらかしてしまいそうになる内容をまとめてみました。

# 実はこのコードは、最初に「end」と表示される

```jsx
const squareNum = (num) => new Promise((resolve, reject) => resolve(num*2));

[2].forEach(async(num) => console.log(await squareNum(num)));// 最後に表示される
console.log("end");// 最初に表示される
```

配列内の2倍値を表示するために、forEachとsquareNum関数を使う。

しかし、非同期処理として動かしたくないため、forEach内のコールバック関数にasync/awaitを使うが、同期処理化されず最初に「end」が表示されて、最後に「4」が表示されます。

**またmapやfind等のコールバック関数で処理をするメソッドも同期処理化されません。**

# じゃあ、どうやって非同期処理を同期処理化させればいいの？

## 1. 普通にfor文を使う

プライドを捨てて、普通にfor文を使いましょう！！

```jsx
const squareNum = (num) => new Promise((resolve, reject) => resolve(num*2));

(async () => {
    for (const num of [2]) {
        console.log(await squareNum(num)); // 最初に表示される
    }
    console.log("end"); // 最後に表示される   
})();
```

## 2. forEachにも**awaitを使う**

async関数内部でしか使えない制限がありますが、これも動きます。

```jsx
const squareNum = (num) => new Promise((resolve, reject) => resolve(num*2));

(async () => {
    await [2].forEach(async (num) => console.log(await squareNum(num))); // 最初に表示される
    console.log("end"); // 最後に表示される
})();
```

## 3. ループ処理外で非同期化できないか設計を変更する

JSは表現度が高い言語です。

なので思い切って設計を変更すること一つの手です。

今回の例題であれば、ループ処理をsquareNum関数に移動させました。

そのため、console.log内部にawaitをするだけでちゃんと表示されるようになります。

```jsx
const squareNum = (nums) => new Promise((resolve, reject) => resolve(nums.map((num) => num * 2)));

(async () => {
    console.log(await squareNum([2]));// 最初に表示される 
    console.log("end"); // 最後に表示される
})()
```
dynamic型で取得したコレクション型のJSONをデシリアライズする

一度String型で取得してから、デシリアライズ（JSON→コレクション）する。

``` C#
using System.Text.Json;

[FunctionName("XXX")]
public static async Task<HttpResponseMessage> Run(
    [HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestMessage req,
    ILogger log)
{
    dynamic dynamicdata = await req.Content.ReadAsAsync<object>();
    
    // NG
    List<XXEntity> xxEntities = JsonSerializer.Deserialize<List<XXEntity>>(dataR?.addEntities);
    
    // OK
    string s = dataR?.xxEntities.ToString();
    List<XXEntity> addEntities = JsonSerializer.Deserialize<List<XXEntity>>(s);

}
```