OmniAICreator/Qiita-1.07M huggingface dataset:
RDS、コンテナ、S3の概要と運用のメリット

# 1. はじめに
この記事では、クラウド環境でのデータベース、アプリケーションの運用、およびデータストレージの管理を考える際に欠かせない、RDS、コンテナ、S3の3つの技術に焦点を当てています。

それぞれの基本概念と特徴、そしてこれらを組み合わせることで得られる運用上の利点について解説します。

# 2. この記事を読んでほしい人
- クラウドサービスの基本的な概要を理解したい方。
- 効率的なシステム運用のための技術選定を検討している方。
- 開発環境や本番環境の整備に関心がある方。

# 3. 前提条件
この記事を理解するためには、クラウドコンピューティングの基本的な知識があると良いです。

# 4. RDS (Relational Database Service)について
### 4.1. 概要
RDSはAmazon Web Services（AWS）が提供する、クラウド上でリレーショナルデータベースを簡単に使えるようにするサービスです。
リレーショナルデータベースとは、データを表（テーブル）の形で管理するデータベースのことを指します。

### 4.2. 特徴
1. 管理の簡素化
RDSを使用すると、データベースサーバーのセットアップ、運用、スケーリングなどが簡単になります。
AWSが多くの管理作業を自動化してくれるため、より開発に集中できます。

2. スケーラビリティ
使用状況に応じて、計算能力やストレージ容量を簡単に増減できます。
トラフィックの増減に柔軟に対応することが可能です。

3. 高可用性
マルチAZ（アベイラビリティゾーン）デプロイメントオプションにより、データベースを複数の地理的に分離された場所に配置できます。そのため、一部のシステムがダウンしても、データベースが利用可能な状態を保てます。

4. セキュリティ
AWSのセキュリティと連携して、データの暗号化、ネットワークアクセスの制御などを行うことができます。

# 5. コンテナについて
### 5.1. 概要
コンテナは、アプリケーションを実行するための軽量でポータブルな環境を提供します。
（後日別記事にてまとめます。）

### 5.2. 特徴
1. 環境一貫性
開発、テスト、本番環境で同じ環境を使用できます。
2. リソース分離
各コンテナは独立しており、他のコンテナやホストシステムに影響を与えません。
3. 高速デプロイメント
コンテナは軽量であるため、起動が速く、スケールアウトやスケールインが容易です。

# 6. S3 (Simple Storage Service)について
### 6.1. 概要
S3は、スケーラブルなオブジェクトストレージサービスです。

下記の記事にてまとめています。
https://qiita.com/saburo555/items/00657758efeb5a614923

### 6.2. 特徴
1. 高耐久性
データは自動的に複数の物理的な場所に保存されます。
2. 簡単なデータアクセス
ウェブインターフェースを通じて、どこからでもデータにアクセスできます。
3. 拡張性
どんな量のデータも保存し、必要に応じて容量を調整できます。

# 7. 運用について
### 手間が省ける
- RDSとS3はマネージドサービスであり、基盤の管理や運用負担が減少します。
コンテナはアプリケーションのデプロイメントを簡素化し、環境の一貫性を保ちます。
- RDSはデータベースのスケーリングを、S3はストレージのスケーリングを容易にします。コンテナはアプリケーションのスケールアウトやスケールインを迅速に行えます。

### データの安全性が担保される
- RDSのマルチAZデプロイメントやS3の高耐久性により、データの安全性が保たれます。

### 環境移行の手間も省ける
- アプリケーションをコンテナとしてパッケージ化することで、異なる環境への移行が容易になります。例えば、開発環境で作成したコンテナをそのまま本番環境に移動させることができます。

# 8. まとめ
上記の概要、運用を理解し、RDS、コンテナ、S3の技術の利用で、ラウド環境におけるデータベース、アプリケーションの運用、データストレージの管理がより効率的かつ効果的になることがわかりました。
go言語　外部コマンドの備忘録

## Go言語の外部コマンドでハマった件の備忘録

###  やりたかったこと
goの外部コマンドからconda activate 環境名で仮想環境のアクティベートしてpythonファイルを動かしたい

```
import  (
        "log"
        "os/exec"
        "fmt"
)

func main(){
    out, err := exec.Commond(conda activate 環境名).Output()
    if err = nil{
        log.Fatalln(err)
    }
    fmt.Println(string(out))
}
```
これでいけるかと思ったがエラー（ status exit 1 )しか返ってこない

外部コマンドでconda仮想環境をアクティベートするときは
exec.Command()の引数を("bash", "-c", "source activate 環境名")とするらしい

ということで

```
import  (
        "log"
        "os/exec"
        "fmt"
)

func main(){
    out, err := exec.Commond("bash", "-c", "source activate 環境名").Output()
    if err = nil{
        log.Fatalln(err)
    }
    fmt.Println(string(out))
```

ついでに仮想環境をアクティベートしてpythonファイルを動かすのは当たり前だと思うので

```
import  (
        "log"
        "os/exec"
        "fmt"
)

func main(){
    out, err := exec.Commond("bash", "-c", "source activate 環境名 && python hogehoge.py").Output()
    if err = nil{
        log.Fatalln(err)
    }
    fmt.Println(string(out))
```
環境名の後に
```
&& python なんちゃら.py"
```
をつける

それでもまだエラーが解決しないので

```
conda init bash
```

とターミナルで叩いたら解決。理由は不明
firebaseの初期設定 @yukilulu0229

## プロジェクトを追加

- プロジェクト名決める

- アナリティクスはなくてもよい

## ウェブアプリに Firebase を追加

![スクリーンショット 2024-01-26 9.46.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/885f58d9-ceb7-88fd-7e96-1b2769a5bbaa.png)

- webをクリック
- 名前を決める
- このアプリの Firebase Hosting デプロイするならチェック入れる

## Authentication

![スクリーンショット 2024-01-26 9.50.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/0f0cd6b2-56bc-3e58-3aea-a91cb2d7c4e9.png)

必要ならここを設定

- 使いたいAuthを選択

- 有効にする
![スクリーンショット 2024-01-26 9.52.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/e27ae881-58e6-89a7-6fd4-e3b160a7ec38.png)

- プロジェクトのサポートメールを選択

## Cloud Firestoreを使う
![スクリーンショット 2024-01-26 9.54.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/bd990388-50b9-20df-dcc6-14602f28449d.png)

- ロケーションを選択
- テストモードで開始する
- ルール設定でデータを保存する期間を変える場合はif文以降を消す

![スクリーンショット 2024-01-26 9.56.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/20473533-c1c9-b66a-15f6-84d0d3fcdf9e.png)


```
rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {

    // This rule allows anyone with your Firestore database reference to view, edit,
    // and delete all data in your Firestore database. It is useful for getting
    // started, but it is configured to expire after 30 days because it
    // leaves your app open to attackers. At that time, all client
    // requests to your Firestore database will be denied.
    //
    // Make sure to write security rules for your app before that time, or else
    // all client requests to your Firestore database will be denied until you Update
    // your rules
    match /{document=**} {
      allow read, write: if request.time < timestamp.date(2024, 2, 25);
    }
  }
}
```

`: if request.time < timestamp.date(2024, 2, 25);` の部分

## プロジェクトの設定

![スクリーンショット 2024-01-26 10.01.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610706/a861bbb9-9800-3602-2547-32787f0c7e84.png)

- SDK の設定と構成の設定の通りやる

`npm install firebase` でインストール

- src/firebase.tsを作成
- 次に Firebase を初期化し、使用するプロダクトの SDK の利用を開始します。をコピーして貼る
- そのままGitHubにあげると危ないのでdot.envを用意する
- dbの設定
- Google認証の設定
- exportする

```firebase.ts
// dbの設定
import { getFirestore } from "firebase/firestore/lite";
// Google認証の設定
import { getAuth, GoogleAuthProvider } from "firebase/auth";

......

// dbの設定
const db = getFirestore(app);
// Google認証の設定
const auth = getAuth(app);
const provider = new GoogleAuthProvider();
// exportする
export { db, auth, provider };
```
【PowerDNS,BIND他】 DNSロードバランサーのDNSDistを触ってみる　～その３～

## 前回からの流れ
DNSクエリのロードバランシングソフトウェアであるPowerDNS dnsdistのダッシュボードからの簡単なクエリ処理動作を確認しました。今回はダイナミックルールの動作について確認していきます。

 * PowerDNS DNSdist
   * https://www.powerdns.com/powerdns-dnsdist
 * DNSdist documentation
   * https://dnsdist.org/index.html
## 実行環境、構成
 * OS：WSL2 Ubuntu 22.04
 * dnsdist：1.8.2-1
 * powerdns：4.5.3-1

![dnsdist.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/f1e371c1-c11c-860d-ac69-02b761458a5d.png)

## ～その３～の本題の前に
私が特にDNSサーバ(※Bind, djbdns等)の管理業務を行っていた時期は、DNSキャッシュポイズニングやDNSアンプによる攻撃が騒がれ始めた頃なので、おそらくは10年より前になるのかなあと思います。

外部からのDoS攻撃(※DNSランダマイズ攻撃等)への対策としてdnsdistが有用であると判断した事と、日本語情報が少なくそこまで広く知られていないOSSかな？と感じたため本記事を書くにいたりました。
※dnsdistの公式ドキュメントは、設定サンプルやパラメータ仕様について細かく記載があり日本語翻訳で十分内容を確認できるためかもしれませんが:)

## ダイナミックルールについて
ダイナミックルールでは、特定の条件に基づいてDNSクエリをリアルタイムでフィルタリングし、アクションを適用する事が可能な機能です。これにより、動的に変化するネットワーク状況に合わせてクエリの挙動(※ドロップ、応答の遅延、なりすまし応答等）を行う事が可能です。

* 存在しないレコード(NXDOMAIN)のクエリが多い送信元アドレスを一定期間ブロック
* SERVERFAILとなるクエリが多い送信元アドレスを一定期間ブロック

## ダイナミックルールの追加
今回はdnsdist公式ドキュメントにある設定例を参考に、「過去10秒間で、20クエリ/秒を超過し、かつ、全クエリの応答がNXDOMAINであるホストに対して60秒ブロックを行う」場合の設定を追加し動作を検証します。

```shell
-- DynBlockRulesグループの設定
-- https://dnsdist.org/guides/dynblocks.html#dynblockrulesgroup
-- https://dnsdist.org/reference/config.html#DynBlockRulesGroup:setRCodeRate
local dbr = dynBlockRulesGroup()
dbr:setRCodeRate(DNSRCode.NXDOMAIN, 20, 10, "Exceeded NXD rate", 60)

function maintenance()
  dbr:apply()
end
```

## ダイナミックルールの動作確認
動作確認として、dnsperfまたはdigを記載したスクリプトを実行します。
※検証のため*.example.comのレコードを削除して実施しています。

 * ダイナミックルール確認スクリプトを作成します。
   * ※備考…秒間クエリ制限を20で設定しているため、スクリプトの微調整はdnsdistのダッシュボードを開きながら検証を実施しています
```
#!/bin/bash

# domain.listは存在しないhogehoge{1..10}.example.comを記載
DOMAIN_LIST="domain.list"
START_TIME=$(date +%s)
while [ $(( $(date +%s) - START_TIME )) -lt 20 ]; do
    # https://www.gnu.org/software/parallel/
    cat $DOMAIN_LIST | parallel -a - dig -p 10053 @172.26.2.3 +short +nocookie +norec
    sleep 0.2
done
```
 * 確認スクリプトの実行
```
# ./dnstest.sh
```
 * ダッシュボード上より、スクリプト実行ホストが/32単位でブロックされている事を確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/4159309d-0bc8-6811-64c3-f6cd3f1051a1.png)
 * また、60秒経過後にブロックルールが自動削除されることを確認します。

## おわりに
今回の記事では、公式ドキュメントの設定例の一つよりダイナミックルールの動作確認を実施しました。実際のDoS攻撃への対策としては、その他ダイナミックルールの追加や大量ホストからのDoSを想定した上で動作検証を行う必要があるかと思いますが、次回は引き続きdnsdistで設定可能な各種設定について確認していきます。
【PowerShell】Invoke-RestMethod の使い方

## はじめに
仕事で PowerShell を触る機会がありました。
そこで API 呼び出しに `Invoke-RestMethod` コマンドを利用したので、備忘録として記事に残します。

## 実行環境
- macOS Sonoma 14.3
- PowerShell 7.3.1

## 使い方
```powershell
Invoke-RestMethod [-Uri] <Uri> [-Method <WebRequestMethod>]
```
オプションは色々とあるみたいですが、今回は `-Uri` と `-Method` のみ指定して実行します。
（仕事で利用したときは、認証トークンを渡すために `-Headers` も利用してました。）

https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.utility/invoke-restmethod?view=powershell-7.4

## 実際に使ってみる
PokeAPI から 推しポケモンのエーフィの情報を取得してみます。
#### 実行コマンド
```powershell
Invoke-RestMethod -Method GET -Uri https://pokeapi.co/api/v2/pokemon/espeon
```
#### 実行結果
```
abilities                : {@{ability=; is_hidden=False; slot=1}, @{ability=; i
                           s_hidden=True; slot=3}}
base_experience          : 184
forms                    : {@{name=espeon; url=https://pokeapi.co/api/v2/pokemo
                           n-form/196/}}
game_indices             : {@{game_index=196; version=}, @{game_index=196; vers
                           ion=}, @{game_index=196; version=}, @{game_index=196
                           ; version=}…}
height                   : 9
held_items               : {}
id                       : 196
is_default               : True
location_area_encounters : https://pokeapi.co/api/v2/pokemon/196/encounters
moves                    : {@{move=; version_group_details=System.Object[]}, @{
                           move=; version_group_details=System.Object[]}, @{mov
                           e=; version_group_details=System.Object[]}, @{move=;
                            version_group_details=System.Object[]}…}
name                     : espeon
order                    : 220
past_abilities           : {}
past_types               : {}
species                  : @{name=espeon; url=https://pokeapi.co/api/v2/pokemon
                           -species/196/}
sprites                  : @{back_default=https://raw.githubusercontent.com/Pok
                           eAPI/sprites/master/sprites/pokemon/back/196.png; ba
                           ck_female=; back_shiny=https://raw.githubusercontent
                           .com/PokeAPI/sprites/master/sprites/pokemon/back/shi
                           ny/196.png; back_shiny_female=; front_default=https:
                           //raw.githubusercontent.com/PokeAPI/sprites/master/s
                           prites/pokemon/196.png; front_female=; front_shiny=h
                           ttps://raw.githubusercontent.com/PokeAPI/sprites/mas
                           ter/sprites/pokemon/shiny/196.png; front_shiny_femal
                           e=; other=; versions=}
stats                    : {@{base_stat=65; effort=0; stat=}, @{base_stat=65; e
                           ffort=0; stat=}, @{base_stat=60; effort=0; stat=}, @
                           {base_stat=130; effort=2; stat=}…}
types                    : {@{slot=1; type=}}
weight                   : 265
```
問題なく情報を取得できました。

## さいごに
今回は、PowerShellで `Invoke-RestMethod` を使った API 呼びだしを記事にしてみました。
誰かの役に立てば幸いです。
Window11にWSLをインストールしてみたので備忘録

# Install
Power Shellを管理者権限で起動
```powershell
wsl --install
```
インストールが終わったらPCを再起動

# アカウント追加
PC再起動すると自動でWSLが起動しててユーザ名とパスワードを追加と出たのでそれに従って追加。特になにも指定しなければUbuntuの最新リリースをインストールする模様。
```
$ cat /etc/os-release
PRETTY_NAME="Ubuntu 22.04.3 LTS"
NAME="Ubuntu"
VERSION_ID="22.04"
VERSION="22.04.3 LTS (Jammy Jellyfish)"
VERSION_CODENAME=jammy
ID=ubuntu
ID_LIKE=debian
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
UBUNTU_CODENAME=jammy
```

# 以降
wslとターミナルに打つだけで入れる（マウントして入っていそう）。あと、WindowのスタートメニューにペンギンアイコンのWSLのショートカットが作られているのでそこからアクセス(こっちはマウントして入っていることがわからない。どうしているだろうか)。ずっとWindows環境のLinux環境にVirtual Boxを使っていたので、こんなにあっさり終わって嬉しいですね

# 気になったこと
rebootコマンドどうなるんだろうsudo rebootしてみるWSLが終了するが、もう一回立ち上げてみるとエラー吐いて強制終了する。強制終了後にWSLもう一回起動できなくなった。PCごと再起動したら治ったが、今後のため安全な終了方法を調べてみたので備忘録。

### 全部終了
使用中のすべてのディストリビューションを終了させる場合
```powershell
wsl --shutdown
```

### 指定して終了
```powershell
wsl -l # すべてのディストリビューションを調べる
wsl -t <distribution-name>
```

VSCodeでのリモートアクセスも簡単だった。WSLを選択すれば入れる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/845709/6b828272-f57c-3e6a-7c04-527020606710.png)

とりあえずこれでやってみる。今度config触ることがあればまた備忘録に残したい。
開いているブックの1番目のシートからデータをコピー、開いているすべてのブックで繰り返す

    Option Explicit
    Sub IntegrateData()
        Dim wb As Variant
        '開いているブックの1番目のシートから、データをコピー
        '開いているすべてのブックで繰り返す
        For Each wb In Workbooks
        
            'この統合ブックは除く
            If wb.Name <> ThisWorkbook.Name Then
                'あるブックのシート1のセル範囲A2:F列の最終行をコピーし、
                'このブックのシート1のA列の最終行に貼り付ける
                wb.Sheets(1).Range("A2:F" & SmaxRow).Copy _
                    ThisWorkbook.Sheets(1).Range("A" & DmaxRow + 1)
            End If
        Next wb
    End Sub
APIについて　軽く触れる


## APIとは

`アプリケーション　プログラミング　インターフェース`
のこと


```

自分が作成するアプリケーションに、外部のサービスの機能やOSの機能を使いたいなんて思う時は、たくさんある
そこで、そのサービスやOSが許可している APIとして公開してくれているものは、自分のアプリケーションから使えるようになるのだ。

```


## WEB API

では、`WEB API`と言われるものは、なんなのか

```
WEB通信のリクエストとレスポンスの中で、APIを利用するのが、WEB APIである
つまり、WEBを介して、APIを利用する
```


## REST API

では、同様に、`REST API`とは？

```
これは、

webAPIは、REST APIであることが望ましい
という慣習があるようで、
RESTである（RESTfulである）ようにAPIを作っているのが、REST APIである

RESTful API ＝ REST API
```
Anacondaの環境を他のPCに移行する（オフラインや低速ネット、再現性向上）

# この記事の目的
Anacondaの環境を移行する記事はいくつかある。
その中の一つの方法が成功したので、報告する。
## 元となる記事
[オフライン環境下でAnaconda仮想環境を構築する方法 #Python - Qiita](https://qiita.com/kappa_black/items/05ecddb7bc8a73d09916)
これの再現
## 実行方法
### 動作環境
Win11 -> Win11　への移行
Anacondaのインストール時の方法で異なるかも？参考に載せておく
* Just Me （ユーザーのみにインストール）
* 環境変数には追加するオプションを選択

### 方法
＜元のPC＞
1. ``conda info -e``　で　仮想環境とそのフォルダを確認
1. 仮想環境をフォルダごと何かにコピー（今回はNASを使用）
＜書込先PC＞
1. ``conda info -e``　で　仮想環境とそのフォルダを確認
1. BASEしかない場合はその直下のenvsに環境をコピー
1. Anacondaを起動するとすでに環境は認識されていた。

ただし、スタートメニューには非表示だった。（ある日突然表示されるかも？）

以上です。
vimを学んだまとめ

# はじめに
vimとはcuiで扱える高機能エディタであり、viの拡張版エディタ。
コマンドモード、ノーマルモード、インサートモード、ビジュアルモードの4つのモードを切り替えて操作する。

## 基本操作
ターミナルにて`vim ファイル名`で起動する。
いずれもノーマルモードで使用する。
|操作|効果|
|-|-|
|h|カーソルを左に移動|
|j|カーソルを下に移動|
|k|カーソルを上に移動|
|l|カーソルを右に移動|
|0|カーソルを行頭に移動|
|x|カーソル上の文字を削除|
|u|操作を戻す|
|ctrl-r|操作を進める|
|i|カーソルの地点からインサートモードに移行|
|dd|カーソル行を削除|

## コマンドモード
ノーマルモードで`:`や`/`を入力するとコマンドモードへ移行する。
|操作|効果|
|-|-|
|:wq|上書き保存して終了|
|:q!|保存せず終了|
|/検索対象|検索対象へカーソルを移動|
|n|次の検索対象へカーソルを移動|
【VSCode】HTML CSS Supportの補完が効かなくなった

# 結論

HTML CSS Supportのアプデが原因だと思われます。
バージョン1までは設定を書かなくても`link`タグと`style`タグから補完してくれましたが、バージョン2からは`css.styleSheets`にスタイルシートを書かないといけなくなりました。

なので、こんな感じで設定を書きましょう。
```.vscode/settings.json
{
  "css.styleSheets": [
    "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
    "styles/*.css"
  ]
}
```
もしくはバージョンを下げましょう。

# はじめに

この度(といっても1ヶ月ほど前)、[HTML CSS Support](https://marketplace.visualstudio.com/items?itemName=ecmel.vscode-html-css)というVSCodeの拡張機能の**メジャーバージョンが上がりました**。

仕様変更があったようなので、バージョン1の頃のままだと補完が効かなくなってしまいました。
なので、この際アプデ内容一気にまとめようと考えて記事を書いています。

わかりづらいところや間違っている内容については、ご指摘いただけると幸いです。


## きっかけ

久々にHTMLでクラス補完をしようとしたのがきっかけです。

HTML自体は普段から触っていたのですが、なぜかここ最近クラスを使ってませんでした。
そのせいでHTML CSS Supportのアプデに気づくのが遅れ、「あれ!?クラス補完効かない!?」となってアプデを知りました。

## バージョンについて

HTML CSS Supportは、2022/7/31に`1.13.1`をリリースしたきり、全然アプデがありませんでした。
ところが先月(2023/12)、`1.14.0`がリリースされました。
さらにその後、`2.0.0`がリリースされました。

そこからは頻繁にパッチバージョンが上がっています。
二日前(2024/1/24)には`2.0.7`がリリースされたりもしました。

この記事では`1.14.1`以前のバージョンをバージョン1と、`2.0.0`以降をバージョン2と呼んでいます。


# アプデ内容

というわけでアプデ内容書きます。

### スタイルシートの指定が必要に

バージョン2へのアップデートにより、**スタイルシートの指定が必要になりました。**

バージョン1の頃は自動でスタイルシートを判定してくれたのですが、どうやらそれがなくなった模様です。
また、これが原因で**設定を変えないと補完が効かなくなった**りもします。

スタイルシートの設定は`css.styleSheets`に書きます。
例えばこんな感じで指定するみたいです(READMEからのコピペ)。
```.vscode/settings.json
{
  "css.styleSheets": [
    "https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css",
    "node_modules/bootstrap/dist/css/bootstrap.css",
    "src/**/*.scss",
    "src/view/style.ts",
    "dist/style.css"
  ]
}
```

ちなみに、私のところはこれの設定をしたら補完が復活しました。

:::note info
`css.styleSheets`自体はバージョン1からありました。
:::

<details><summary>おまけ：README.mdの変化</summary>

もともと、`README.md`には以下のような記述がありました。

> **Linked and Embedded Style Sheets**
> Linked `[<link rel="stylesheet">]` and embedded `[<style></style>]` style sheets are used in completion for `id` and `class` attributes. Links support local and remote files. Absolute local file paths are relative to the workspace folder while others are relative to HTML file:

DeepLによる日本語訳(一部修正)：
> **リンクされたスタイルシートと埋め込まれたスタイルシート**
> リンクされた`[<link rel="stylesheet">]`と埋め込まれた`[<style></style>]`スタイルシートは、`id`と`class`属性の補完で使われます。リンクはローカルとリモートのファイルをサポートします。絶対的なローカルファイルパスはワークスペースのフォルダからの相対パスで、それ以外はHTMLファイルからの相対パスです：

ですが、今はこの記述は消えています。
このことからも、`link`タグと`style`タグは補完の表示に使われなくなったのがわかります。

</details>

***

これ以外のアプデ内容がよくわからなかったので一旦ここまでです。
調べ次第追記します。
JUnit5のまとめ（基本的な使い方）

## JUnit5概要
個人的にはテスティングフレームワークはSpockの方が好みですがJUnitについてもまとめようと思います。
java言語で書くことの出来る単体テストを行うためのテスティングフレームワークです。
Spockとは異なり、javaソースコードとほとんど一緒なのでjavaに触れてきた方はこちらの方が親しみがあり、ラムダ式の判定などもでき、springとの相性も良いみたいです。

## JUnit5の基本的なルール
・戻り値はVoid(戻り値なし)とする
・引数は指定しない
JUnitは下記のようにアノテーションベースのテスティングフレームワーク
| アノテーション  | 概要 |
|:-:|:-:|
| @Test  |付与することでテストメソッドとして機能   |
|@DisplayName   |テスト実行結果に表示される-結果が分かりやすくなる   |
|@BeforeEach   |テストメソッドとは別で作成しておくことで、各テストメソッドの実行後に毎回実行される   |
|@AfterEach   |  テストメソッドとは別で作成しておくことで、各テストメソッドの実行前に毎回実行される |
|@BeforeAll   |テストメソッドとは別で作成しておくことで、テストクラスの実行前に1度だけ実行される    |
|@AfterAll   |テストメソッドとは別で作成しておくことで、テストクラスの実行前に1度だけ実行される    |
|@Disabled   |付与したテストクラスやテストメソッドを無効化 |
|@ParameterizedTest   |付与することでパラメータ化テストが可能   |
|@ValueSource   |パラメタライズド用のテストメソッド(ひとつの型のみ使用可能) |
|@MethodSource   |パラメタライズド用のテストメソッド(複数の型の使用可能) |
|@CsvSource   |パラメタライズド用のテストメソッド(独自の型でも使用可能)  |

## 参考コードを実際に書いてみる
前提：
下記のDTOクラスの各フィールドが取得できるかテストを行う。
◆DTOクラス
```java
public class dogDto {

        private Long dogId;
        private String DogName;
        private String DogBreed;
    }
```

◆テストコード
```java
@SpringBootTest
public class dogDaoImplSTest_Select {

    @Autowired
    DogDaoImpl dao;

    static Stream<Arguments> parameterized_method() { //パラメーターを渡すメソッド
        return Stream.of(
                arguments(1L, 1L, "moku", "pomeranian"), //パラメーター1を渡す
                arguments(2L, 2L, "mugi", "pekingese") //パラメーター2を渡す
        );
    }

    @DisplayName("複数件取得") //テスト実行時に表示するテスト名
    @ParameterizedTest //パラメーター化テストに付与
    @MethodSource("parameterized_method")
        //上記のメソッドの呼び出し
        //様々な型を渡すことができる、上記でメソッドを作成する必要がある
    void select_parameterized_dog(Long pDogId, Long eDogId, String eDogName, String EDogBreed) { //メソッド内で渡すための変数宣言
        final DogDtoSelector selector = new DogDtoSelector();
        selector.setDogId(List.of(pDogId));

        final List<DogDto> actual = dao.select(selector); //selectメソッドの実行

        assertEquals(1, actual.size()); //サイズチェック
        assertAll( //各パラメーターのチェック
                () -> assertEquals(eDogId, actual.get(0).getDogId()),
                () -> assertEquals(eDogName, actual.get(0).getDogName()),
                () -> assertEquals(EDogBreed, actual.get(0).getDogBreed())
        );
    }
}
```
## メリット
・javaの記法でそのまま書くことができる
・パラメタライズドテストの際に様々な型で検証を行うことができる
・SpringBootとの親和性が高い

## デメリット
・パラメタライズドテストに関してはspockの方がわかりやすい

## まとめ
個人的にはSpockの方が好みですが、Spockのパラメタライズドテストを行う際にも、独自の型などを使用していると、別メソッドとして切り出してパラメーターを渡してあげる必要があるのでどっちもどっちといったところかなと思っています。
javaに慣れている方はJUnitの方がわかりやすいかもしれないですね。
【Tableauの基本】初心者向け_テーマ1：LOD


# 1.LODの理解
## LODとは

・LOD＝Level of detail=詳細レベル=粒度




## 何のLODなのか
以下の３つがあるが、それぞれを理解することが重要。
これが理解できればLOD計算（FIXED,INCLUDE,EXCLUDE）がわかる。
①データのLOD
②VizLOD
③LOD計算



## ①：データのLOD
・元データの1行1行のこと

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618835/bd2babdc-9d41-4d4c-5247-d5b9babe7ad6.png)





## ②：VizLOD
・Tableau内のビジュアライゼーション（Vizと言います）でのLOD（粒度）
※わかりやすくいうと、Viz上に配置したディメンション
（列シェルフ、行シェルフ、色、サイズ、ラベル等）



・例えば、下図のビジュアライゼーションのVizLODは「カテゴリ」×「出荷モード」です
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618835/f4626e94-d3f8-17a3-41ee-aa7f6e2a7783.png)


## ③：LOD計算（LOD expression,LOD表現）
・VizLODに関係のない粒度で計算をしたい場合に使用するのがLOD計算
（このVizLODにないディメンションで集計を使うことができる）




# 2.LOD計算の種類
## LOD計算の種類⇔VizLODとの関係性(集計粒度)

・FIXED：VizLODの存在を無視して計算（つまりVizに対して独立）
・INCLUDE：VizLOD+INCLUDEで計算したディメンションで計算（つまりVizに加えてINCLUDEの粒度を加える）
・EXCLUDE：VizLOD-EXCLUDEで計算したディメンションで計算（つまりVizからEXCLUDEの粒度を除外）


# 3.LOD計算式
例1：{ FIXED [カテゴリ]:SUM([売上])}
例2：{ INCLUDE [カテゴリ]:SUM([売上])}
例3：{ INCLUDE [顧客区分]:AVG([売上])}

LOD計算式の書き方
・{から始める
・FIXED、EXCLUDE、INCLUDEを計算フィールドにタイプする
・ディメンションが複数ある場合は間にカンマを入れる
・その後、コロン”:”をつける
・集計関数を入れる (SUM(), AVG(), MIN(), etc.…)
・}で閉じる



# 4.LOD計算の中間テーブル（裏側のテーブル）

## FIXEDの中間テーブル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618835/fb4de16a-ab2f-44a8-0b9d-833b547a9403.png)


## INCLUDEの中間テーブル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618835/06fe975b-5d93-5bae-a593-36ba616a8a8b.png)

## EXCLUDEの中間テーブル

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3618835/f0a40817-0f83-fca8-fd08-74bb0f6954d0.png)






# 参照させていただいたサイト
https://note.com/ritz_tableau/n/n28a99cd0e9ec

https://www.yarakawa.com/single-post/lod_calculations

https://data-viz-lab.com/tableau-lod#LODLevel_of_DetailLOD
球状黒鉛鋳鉄品の金属組織画像におけるパーライトと黒鉛の分類

## はじめに
球状黒鉛鋳鉄品（FCD）の機械的性質（引張強さ、硬さ、伸び、衝撃値など）は金属組織（黒鉛の形状や基地組織）により大きく変化することが知られています。ここで、黒鉛の形状はJIS G5502の黒鉛球状化率から、パーライトの量はパーライト面積率から、それぞれ金属組織画像を使って求める事ができます。
一般的に、黒鉛球状化率は腐食前の金属組織画像から求め、パーライト面積率は腐食後の金属組織画像から求めますが、今回は下図のような腐食後の金属組織画像から黒鉛球状化率とパーライト面積率の両方を求めてみることにします。

- 腐食液で腐食後のFCDの金属組織画像
![28233510.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/cf42f172-e58a-882f-6b8a-08b1092a0c8e.jpeg)

## 作成したプログラム
使い方やサンプル画像を含めて、以下のgithubに格納してあります。

https://github.com/repositoryfiles/PerliteRatio_and_Nodularity

## 開発環境
- Windows11
- VSC 1.85.2
- Python 3.9.18
- OpenCV 4.5.0

## 終わりに
このプログラムは、組織画像中のパーライトと黒鉛を画像処理を使って輪郭として抽出しています。このため、フェライトとパーライトが接触している画像や、パーライトの面積が多い画像については、輪郭の抽出が困難となります。ご注意ください。
何かのご参考になれば幸いです。
shadcn-uiをAstroで使おうとしたときに躓いたところ

## Astroとshadcn-uiデビューをする

最近話題のSSGフレームワークの[Astro](https://astro.build/)にデビューしたときに、同時に最近話題の[shadcn/ui](https://ui.shadcn.com/)を使ってみようと思ったのですが、躓いた部分があったので忘れないために残します。

https://astro.build/

https://ui.shadcn.com/

## Astroでshadcn-uiを使うまで

Astroにshadcn-uiをインストールするためには、[shadcn/uiのドキュメント](https://ui.shadcn.com/docs/installation/astro)記載の通りに進めていけば問題ないです。

Astroは「Astroインテグレーション」という機能により、TailwindcssやReactを始めとする様々な機能を簡単に追加することができるのでとても便利です。

AstroはSSGだけではなく、SSRにも対応しているのですが、CloudflareやVercelへデプロイして簡単にSSRができるようなSSRアダプターも用意されています。

https://docs.astro.build/ja/guides/integrations-guide/

## 使えないコンポーネントがある

インストールが終わってshadcn/uiを使えるようになりましたが、`Accordion`というコンポーネントを使おうとした際に以下のエラーが発生しました。

```bash
[ERROR] [UnhandledRejection] Astro detected an unhandled rejection. Here's the stack trace: Error: `Accordion` must be used within `Accordion`
```

画面では以下のように表示されています。

![](https://raw.githubusercontent.com/Gardenia-710/articles/main/images/2024-01-28-13-21.png)

`Accordion`は`Accordion`の中で使用しなければならないというようなエラーのようです。

ここでコードを見返してみます。

```astro:src/index.astro
<Accordion type="single" collapsible>
  <AccordionItem value="item-1">
    <AccordionTrigger>Is it accessible?</AccordionTrigger>
    <AccordionContent>
      Yes. It adheres to the WAI-ARIA design pattern.
    </AccordionContent>
  </AccordionItem>
</Accordion>
```

そもそもこれもドキュメントからコピペしてるのでおかしな点はありません。

というかそもそも`Accordion`は`Accordion`の中で使用しなければならないってどういうことだよってことに気づきます。

## 使えるようにする

少し調べたところ[shadcn/uiのGitHub Issue](https://github.com/shadcn-ui/ui/issues/987)がヒットしました。

使用しているコンポーネントは違いますが、症状は同じような感じです。

したがって使用したいshadcnのコンポーネントをReactコンポーネントにしてAstroで呼び出すようにしてみます。

```tsx:src/components/AccordionComponent.tsx
import {
  Accordion,
  AccordionContent,
  AccordionItem,
  AccordionTrigger,
} from "./ui/accordion";

export const AccordionComponent = () => {
  return (
    <Accordion type="single" collapsible>
      <AccordionItem value="item-1">
        <AccordionTrigger>Is it accessible?</AccordionTrigger>
        <AccordionContent>
          Yes. It adheres to the WAI-ARIA design pattern.
        </AccordionContent>
      </AccordionItem>
    </Accordion>
  );
};
```

あとはAstroで読み込みます。

```diff astro:src/index.astro
---
+ import { AccordionComponent } from "@/components/AccordionComponent"
---
~~~
+ <AccordionComponent client:load />
```

すると・・・

![](https://raw.githubusercontent.com/Gardenia-710/articles/main/images/2024-01-28-13-34.png)

無事に表示されて動作もすることが確認できました！

先に挙げたIssueでは原因として、AstroはReactコンポーネントごとにアイランドを生成しており、それらが共有されていないために起こると書かれていますが、正直このあたりのアイランドの仕組みがいまいちわかっていないので詳しいことはわからないです。

これからAstroやReactについてもう少し勉強して使いこなせるようになりたいなぁと思った今日でした。

ありがとうございました。
資源経済学　J.M.コンラッド先生　岩波書店

```r

#p.18

#E1.1

K=1
r=0.5
X=0.1
Y=0

t=10
Xvec=c(X)
for(j in 1:t){
X=X+r*X*(1-X/K)-Y 
Xvec=c(Xvec,X)
}



#E1.2

p=2
c=0.5
delta=0.05
Y=0.125


t=1000
pisvec=c(p*Y-c*Y/X)
dvec=c()
lamvec=c((p-c/X)*(1+delta))
for(j in 1:t){
X=X+r*X*(1-X/K)-Y
pis=p*Y-c*Y/X
dvec=c(dvec,r*(1-2*X/K)+c*Y/((p-c/X)*X^2))
pisvec=c(pisvec,pis)
Xvec=c(Xvec,X)
lamvec=c(lamvec,(p-c/X)*(1+delta))
}

plot(dvec)
plot(pisvec)

#定常状態の確認
plot(Xvec)
plot(lamvec)

```

```r

#ロジスティック増殖関数とCPUE関数 p.46

c=1
K=1
eta=0.3
p=200
q=0.01
r=0.1

X=1
E=1

Hvec=c(q*E*X)
Xvec=c(X)
Evec=c(E)
pisvec=c(p*q*E*X-c*E)
t=300
for(j in 1:t){
X=X+r*X*(1-X/K)-q*E*X
E=E+eta*E*(p*q*X-c)
Xvec=c(Xvec,X)
Evec=c(Evec,E)
Hvec=c(Hvec,q*E*X)
pisvec=c(pisvec,p*q*E*X-c*E)
}

plot(Xvec)
plot(Evec)
plot(Hvec)
plot(pisvec)


```
Windows 11 Enterprise 評価版の使用期限を確認・延長する手順

### Windows 11 Enterprise 評価版の使用期限を確認する手順

1. **コマンドプロンプトを開く**  
   スタートメニューをクリックまたはWindowsキーを押します。
   検索バーに「cmd」と入力します。
   出てきた「コマンドプロンプト」にマウスを合わせ、「右クリック」をして、「管理者として実行」を選択します。  
   「ユーザーアカウント制御」のダイアログが表示されたら、「はい」をクリックしてください。

2. **コマンドの実行**  
   管理者権限で開いたコマンドプロンプトにて、以下のコマンドをタイプまたはコピー＆ペーストします。
   ```
   slmgr /xpr
   ```
   入力後、Enterキーを押します。

3. **使用期限の確認**  
   コマンドを実行すると、Windows Script Hostのダイアログボックスが開きます。  
   このボックスには、Windows 11 Enterprise 評価版の使用期限が表示されます。

---

### Windows 11 Enterprise 評価版の使用期限を延長する手順

1. **コマンドプロンプトを管理者権限で開く**  
   上記の使用期限の確認手順と同様に、コマンドプロンプトを「管理者として実行」で開きます。

2. **使用期限延長コマンドの実行**  
   管理者権限で開いたコマンドプロンプトにて、以下のコマンドを入力します。
   ```
   slmgr /rearm
   ```
   入力後、Enterキーを押してコマンドを実行します。

3. **システムの再起動**  
   コマンドが成功すると、「コマンドは正常に完了しました。システムを再起動して変更を有効にしてください」というメッセージが表示されます。  
   「OK」をクリックしてダイアログボックスを閉じ、スタートメニューからコンピュータを再起動します。

4. **使用期限が延長されたかの確認**  
   再起動後、再びコマンドプロンプトを「管理者として実行」で開き、「slmgr /xpr」コマンドを実行して、使用期限が延長されたかを確認します。

---

**注意:** 評価版の使用期限の延長は限られた回数しか許されていないため、この手順は永久的な解決策ではありません。延長回数が無くなったら、正式なライセンスを購入するか、OSを再インストールする必要があります。また、レジストリエディタやシステムファイルを変更するような非公式の方法で使用期限を延長しようとすると、システムが不安定になる可能性があるため、推奨されません。
スケジューリングされたローカル通知実装

# 概要
業務でローカル通知を実装したので忘れないように備忘録です。
環境はXcode15、swift5.9です。
Swift Concurrencyが用意されているので利用します。

# ローカル通知クラスの実装
```swift
import Foundation
import UserNotifications

final class LocalNotification {
    public static let shared =  LocalNotification()
    func scheduleNotificationIfAuthorized() async throws {
        do {
            if try await UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .badge]) {
                let content = UNMutableNotificationContent()
                content.title = "アプリ名"
                content.body = "コメント"
                var dateComponents = DateComponents()
                dateComponents.weekday = 6 // 土曜日
                dateComponents.hour = 19　//19時
                dataComponents.minute = 15 // 15分
                let trigger = UNCalendarNotificationTrigger(dateMatching: dateComponents, repeats: true)
                let request = UNNotificationRequest(identifier: UUID().uuidString, content: content, trigger: trigger)
                try await UNUserNotificationCenter.current().add(request)
            }
        } catch {
            throw ModelError.localNotification
        }
    }
}
```

# AppDelegateで呼び出し

```swift
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_: UIApplication, didFinishLaunchingWithOptions _: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        Task {
            try await LocalNotification.shared.scheduleNotificationIfAuthorized()
        }
        ...
    }
}
...
```

# Capabilitiesに追加
CapabilitiesにPush Notificationsを追加して完了です。

こちらで実装できるかなと思います。
VRChatのエラーをしばく

## 共通ケース
### VRC.SDKBase.Editor.Api.VRCTools.IncreaseSendBuffer
正確には`VRC.SDKBase.Editor.Api.VRCTools.IncreaseSendBuffer (System.Uri targetUrl, System.Threading.Tasks.Task sendRequest, System.Threading.CancellationToken cancellationToken)`だが、編集の都合で省略した。
この症状はLinuxでしか発現しない。3.5.0においても確認済み。<https://blog.tlfoxhuman.net/2023/12/26/how-to-upgrade-to-unity2022-on-linux/>によれば.NET Frameworkに依存した実装となっているため**パッチを当てて**無効化する必要がある。
この症状は[Canny](https://feedback.vrchat.com/sdk-bug-reports/p/350-beta1-avatar-upload-fails-on-linux-editor)でも報告されているが、治る気配がない。
ちなみに、上記のブログで紹介されていた先頭に`return;`を追記する方法だとビルドのタイミングによってはUdonSharpが謎のエラーを吐いて死ぬことがあるのでCannyに載せられているパッチを当てるほうが丁寧である。

## ワールド
### 初アップロード時にAssetBundle was not built
これも https://blog.tlfoxhuman.net/2023/12/26/how-to-upgrade-to-unity2022-on-linux/ で説明されている通り、`/tmp/DefaultCompany`下の`*.vrca`に対してシンボリックリンクを貼りもう一度ビルドする必要がある。

## アバター
### 実行時にMissing material
どんまい。

### 実行時にエラーアバター
どんまい。

### TexTransTool@0.4のSimpleDecalをプレビューするとmissing materialになる
(Linuxのみ？)
謎。対処療法としてはTexTransTool@0.5以降を使うことだが、Unity 2022にしか対応していないので注意。

## その他参考にできそうな資料
* https://vrc.wiki/troubleshooting/

## あとがき
3.5.1を早く出して？？？
PyPIの2段階認証とAPIトークン使用が必須化されました

# 概要

Pythonで自作のパッケージを作成した場合、以下のようにPyPIを使用して公開するのが一般的かと思います。（`pip install パッケージ名`でインストールできるアレです）

https://qiita.com/c60evaporator/items/e1ecccab07a607487dcf

　2024年1月より、PyPIにおける2段階認証とAPIトークン使用が必須化されました。これに伴い、**従来のユーザ名/パスワードによる認証**（`.pypirc`にユーザ名とパスワードを記載する方法）では**PyPIへのパッケージアップロードができなくなりました**。

　上記変更に対応して、APIトークンによるパッケージアップロードを行う方法については、以下「実践」を参照ください

## 参考リンク

公式詳細は以下リンクに記載されております

https://blog.pypi.org/posts/2024-01-01-2fa-enforced/

## 実践

以下記事の内容を、2段階認証とAPIトークンを使用する方法に更新しております。私の環境では以下手順でアップロード＆pipによるインストールができることを確認しました。

https://qiita.com/c60evaporator/items/e1ecccab07a607487dcf#pypiへのユーザ登録
Form認証とIDaaS（ソーシャルログイン）認証の、基礎的な仕組みの比較

年末年始にFirebaseを初めて使って、Webアプリを作ってました。😀

（Webエンジニアからすると、今では当たり前かもしれませんが、）IDaaS(Identity as a Service)を使った認証の仕組みが、従来の業務用Webアプリの認証と異なっていて、面白いなと思ったので、記事にまとめてみました。

# 業務用Webアプリの認証のよくある例
Basic認証・Digest認証などありますが、実際の業務ではForm認証が多いかなと思います。
HTML上に、ユーザIDとパスワードの入力欄があり、それを自分で実装したサーバプログラムに投げて、サーバ側で判定するという仕組みですね。

シーケンス図で示すと、こんな感じでしょうか。（本ページ内の図はアバウトに描いています🙇‍♂️）
```mermaid
sequenceDiagram
    autonumber
    actor ユーザ
    ユーザ->>Webブラウザ: ユーザIDとパスワードを入力
    Webブラウザ->>Webブラウザ: パスワードをハッシュ化する
    Webブラウザ->>Web(AP)サーバ: ユーザIDと、パスワードのハッシュ値を、httpsで送る
    Web(AP)サーバ->>DBサーバなど: ユーザ情報取得(ユーザID, パスワードのハッシュ値)
    DBサーバなど->>Web(AP)サーバ: ユーザ情報の返却
    rect rgb(0, 255, 0)
        Note over Web(AP)サーバ:サーバが認証の成功を検知！
    end
    Web(AP)サーバ->>Web(AP)サーバ: セッションIDの生成
    Web(AP)サーバ->>Webブラウザ: セッションIDをcookieに保存させ、次回からリクエスト時に送ってもらう。
    rect rgb(0, 255, 0)
        Note over Webブラウザ:クライアントが認証の成功を検知！
    end
    Web(AP)サーバ->>DBサーバなど: セッションIDの保存
    ユーザ->>Webブラウザ: ログインしたユーザだけが見れるページにアクセス
    Webブラウザ->>Web(AP)サーバ: ページ要求
    Web(AP)サーバ->>Web(AP)サーバ: cookieに保存されたセッションIDの検証。
    Note over Web(AP)サーバ:以下、省略
```

サーバの方が、クライアントよりも先に、認証に成功したことを検知していますね。

# IDaaS認証の例

次に、IDaaSを使った認証の例を見てみます。
Googleや各種SNSなどのアカウントで認証する時の流れです。
IdP（アイデンティティプロバイダ）（Googleなどの認証サーバ）が登場します。

```mermaid
sequenceDiagram
    autonumber
    actor ユーザ
    participant Webブラウザ
    participant Web(AP)サーバ
    participant IdP
    Web(AP)サーバ->>IdP: 事前準備（あらかじめ認証機能を使うことを登録しておく）
    Webブラウザ->>Web(AP)サーバ: ログインの要求
    Web(AP)サーバ->>Webブラウザ: SNSログイン画面へのリダイレクト（ポップアップの場合もある）
    Webブラウザ->>IdP: 表示要求
    IdP->>Webブラウザ: ログイン画面表示
    ユーザ->>Webブラウザ: ログイン情報（メルアドとパスワードなど）の入力
    Webブラウザ->>IdP: 認証依頼（ユーザが入力した情報）
    IdP->>IdP: 認証
    IdP->>Webブラウザ: 認証成功時にトークン（JWTなど）を渡す。
    rect rgb(0, 255, 0)
        Note over Webブラウザ:クライアントが認証の成功を検知！
    end
    Webブラウザ->>Web(AP)サーバ: IdPから受け取ったトークンを渡す。
    Web(AP)サーバ->>IdP: トークンの妥当性（発行元の正当性や有効期限）の検証
    rect rgb(0, 255, 0)
        Note over Web(AP)サーバ:サーバが認証の成功を検知！
    end
    Web(AP)サーバ->>Webブラウザ: ログイン成功後の画面を表示（トークンをcookieに仕込ませる）
    ユーザ->>Webブラウザ: ログインしたユーザだけが見れるページにアクセス
    Webブラウザ->>Web(AP)サーバ: ページ要求
    Web(AP)サーバ->>IdP: cookieに保存されたトークンの検証。
    Note over Web(AP)サーバ:以下、省略
```
クライアントの方が、サーバよりも先に、認証に成功したことを検知しています。
クライアントは、認証に成功したことを、サーバに伝えていますが、サーバは、クライアントから送られてきたデータを鵜呑みにはできないので、トークンの妥当性を、IdPを通じて検証する必要があります。

# まとめ
認証機能付きのWebアプリを作る際は、認証の仕組みをよく理解する必要があります。
次回は、Firebase Authenticationを使って、実際の様子をお見せします。

# 参考

[Firebase Authenticationで学ぶ ソーシャルログイン入門 ID管理の原則にそった実装のベストプラクティス](https://amzn.asia/d/4XVUDm1)

わかりやすく、かつ、詳しく書かれていました。
【ReactNative】自動スクロールと非同期処理


## やりたかったこと
アラーム時間指定画面(ShowPicker)を表示させた後、画面最下部に自動スクロールさせる動作の実装


![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/676445/ed969d37-01b2-521e-e8b6-2b5667163520.gif)




## 詰まったこと
1回目のタップ時には、自動スクロールせず、2回目からはスクロールでぉた。

## ポイント

React Nativeがコンポーネントをレンダリングする際、通常は非同期のプロセスだそう。
そのため、修正前のコードでは、ShowPickerのレンダリング中に、末尾自動スクロールが動いてしまった。

setTimeoutを使うことで、前のレンダリングが終わった後に次のコードが読み込まれるため、
ShowPickerのレンダリング後に、末尾自動スクロールが起き、ShowPickerの最下部にスクロールされるようになった。


■修正前
```react
  const showDateTimePicker = (index) => {
    setShowPicker(true);
    setEditedAlarmIndex(index);

    scrollViewRef.current.scrollToEnd({ animated: true });

// DateTimePickerが表示されたときにスクロールを一番下にする
    if (scrollViewRef.current) {
      scrollViewRef.current.scrollToEnd({ animated: true });
    }
  };
```

■修正後
```react
const showDateTimePicker = (index) => {
  setShowPicker(true);
  setEditedAlarmIndex(index);

  // DateTimePickerがレイアウトされた後に末尾にスクロール
  setTimeout(() => {
    if (scrollViewRef.current) {
      scrollViewRef.current.scrollToEnd({ animated: true });
    }
  }, 0);
};
```
HTMLのdetails・summaryタグだけでアコーディオンを実装する

## details・タグでアコーディオンを実装する
これまでアコーディオンを実装する際はCSSやJQueryを主に使用してきましたがもっと楽な実装方法がないか調べていた時に見つけたHTML5から登場したタグです。
余程古いバージョンでない限り殆どの主要ブラウザで使用することができます。

## 具体例

```ruby:index.html
<details>
  <summary>ボタン</summary>
  折り畳まれている部分
</details>
```

<details>
  <summary>ボタン</summary>
  折り畳まれている部分
</details>

上記だけでアコーディオンを実装することができます。また、detailsタグに「open」属性をつけるとはじめから開封した状態にすることも可能です。
トランジションはついておりませんので、別途jsで実装する必要があります。

また、summaryの「-webkit-details-marker」により初期状態から矢印が表示されており、こちらは以下のCSSで非表示にすることができます。

```ruby:style.css
/* Chrome、Safari */
summary::-webkit-details-marker {
  display: none;
}
```
docker rootlessでできたファイルのchownのやりかた

docker rootlessでコンテナ内でファイルを作成するとsubuidで設定しているユーザ所有になってしまう。
``` shell
% ll hoge.txt
-rw-r--r-- 1 100999 100999 6 2024-01-28 12:41 hoge.txt
```

一般ユーザのままでchownではエラーになってしまう。
``` shell
% chown myuser:myuser hoge.txt
chown: changing ownership of 'hoge.txt': Operation not permitted
```

正しいのか分からないが以下でできた。

``` shell
% rootlesskit -- chown 0:0 hoge.txt
```

(2024/04/11追記)
rootlesskitで解決できる理由がわかったのでメモ。

testuserのuidが1000、subuidで100000から65536個分割り当たっているとする。

dockerではsubuidやsubgidでユーザID空間を分け擬似的にrootになった状態にしている。
マッピングの状態は、実際にマッピングされたプロセスに対して以下の処理をすれば確認できるが、docker内のプロセスはプロセス空間も分離されていてホスト上でpsしても見れないので、まず適当にユーザID空間を分けた状態を作る。
  ```shell
  % rootlesskit bash
  ```
これのpidを確認。
  ```shell
  % ps aux|grep 'bash.*testuser'
  ```
そのpidについて、uid_mapを確認。
``` shell
% cat /proc/3371297/uid_map
       0       1000          1
       1     100000      65536
  意味 (分離空間上uid) (ホスト上uid) (いくつ分か)
```

分離空間上のuid0番がホスト上のuid1000(ホスト上のtestuser)になっている。
分離空間上のuid1以降は飛んで、1が100000(subuidで割りあたっている最初のもの)、2が100001…とマッピングされている。

そのためdocker内でrootで作ったファイルはホスト上ではtestuser所有になっており、1以降のファイルは100000以降(ホスト上では特に名前は割りあたっていないのでls -lしてもuidのまま表示される)になっている。

100000以降のファイルはホスト上でtestuserのままで消そうと思っても消せない。rm等がuidのマッピングを気にしてくれないから。
rootlesskit -- chown root:rootしてから消せばOK。


参考資料。
  https://gihyo.jp/admin/serial/01/linux_containers/0016
  https://github.com/rootless-containers/rootlesskit?tab=readme-ov-file#usage
CodeCommit上のメインブランチの情報を作業ブランチに反映させたい

# はじめに
CodeCommitリポジトリの作業ブランチがメインブランチに遅れてしまっている場合に対処した方法を説明する。
# 問題
業務でメインブランチから作業ブランチを切り、その作業ブランチをローカルにクローンして作業をしていた。
作業が完了し、作業ブランチをCodeCommitにPUSH。
今回は検証のために作業ブランチをソースとしてCodeBuildでビルドを行った。

すんなりビルドが終わるだろうと思っていたが、まさかの失敗。
ビルドログを見てみると、今回の修正箇所とは関係ないエラーが発生していた。

どうやら、ブランチを切ったタイミングのメインブランチに不具合があったようで、その不具合が原因でビルドに失敗していた。

メインブランチではすでに不具合が解消されているため、作業ブランチにその反映を取り込みたい。
イメージはこんな感じ。
![ブランチ2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/f7ec860b-8a63-e475-79be-dc472b6d864c.png)


# 解決方法
今回は簡易的な例で説明していく。
メインブランチを「main」、作業用ブランチを「feature/work」として聞いていほしい。

ローカルのmainブランチのディレクトリ構造は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/93c01ab6-7181-80c6-23c0-103101f7f562.png)

ローカルのfeature/workブランチのディレクトリ構造は下記。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/83c3dd97-5ea9-620e-88e3-1acf3fd42fbd.png)

まずはブランチの状態を確認。

```bash
git status
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/4cdcda20-0576-ae38-462c-86def4ac4952.png)




status状態がきれいであれば何もする必要なし。
作業用ブランチで作業中の場合はスタッシュを実行。
```bash
git stash save 作業用ブランチにメインブランチの情報を取り込むために一時退避
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/4553442d-af47-26b3-dc9b-12e7e680b4ce.png)

mainブランチに移動し、pull。
```bash
git pull
```


mainブランチにリモートのmainブランチの情報が反映される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/71c7433e-eb37-fae5-a4b4-18c07fade717.png)

feature/workディレクトリに戻り、mainブランチの内容を反映させる。
```bash
git rebase main
```
成功すると以下のようなメッセージが返される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/3421790b-d240-f510-95be-370fe2b4c67f.png)

たしかにmainブランチの情報が反映されていると確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/370fc604-fb72-6bb8-381d-15edaa95a69f.png)

スタッシュしていた内容を反映させる。
```bash
git stash apply stash@{0}
```
反映されたことを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/18cbb070-c591-a312-31f2-a27ebb5c7dfa.png)


完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554634/db395a88-2055-68e3-4f87-db7044a634d6.png)


# おわりに
「mainブランチをpullして最新化し、そこから新たにブランチを切って変更箇所を反映」という方法もある。
今回の方法と比べてみて、自分が良い方を選択してみてください。
dockerで多段リバースプロキシ

# はじめに
多段リパースプロキシの挙動を確かめたかったので、dockerでテスト環境をこさえてみました。
###### 参考↓
https://www.serotoninpower.club/archives/780/
## 構成
()内はDocker側のポート番号、コンテナ側はすべて80
client-> proxy1(80) => proxy2(81) => backend(82)

## ディレクトリ構成
```sh:tree
multi_revproxy
├── backend
│   ├── conf
│   │   └── backend.conf
│   ├── html
│   │   └── index.html
│   └── log
├── proxy1
│   ├── conf
│   │   └── proxy1.conf
│   └── log
├── proxy2
│   ├── conf
│   │   └── proxy2.conf
│   └── log
└── compose.yaml
```
### 固定IPのdocker networkの作成
compose.yamlで特に指定しなくてもmulti_revproxy_default(親ディレクトリ名_default)という名前のネットワークがコンテナ作成と同時に作成される。しかし、IPの動きを見たいので、固定IPのdocker networkを作成しておく。
（デフォルトのネットワークだと毎回ネットワークアドレスが変わる）

https://zaki-hmkc.hatenablog.com/entry/2021/02/26/234357#%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E3%81%BF%E6%8C%87%E5%AE%9A%E3%81%AE%E3%82%B3%E3%83%B3%E3%83%86%E3%83%8A

--subnetオプションでサブネット、--gatewayオプションでゲートウェイのIPを指定できる。
```sh:
$ docker network create --subnet 172.16.0.0/24 --gateway 172.16.0.1 multirevproxy-nw
```
inspectすればネットワークアドレスが固定されているのがわかる
```sh:
$ docker network inspect multirevproxy-nw | grep -E "Subnet|Gateway"
                    "Subnet": "172.16.0.0/24",
                    "Gateway": "172.16.0.1"
```
## compose.yaml

```yaml:compose.yaml
services:
  proxy1:
    container_name: proxy1
    ports:
      - "80:80"
    environment:
      TZ: Asia/Tokyo
    image: nginx:latest
    volumes:
      - ./proxy1/conf:/etc/nginx/conf.d
      - ./proxy1/log:/var/log/nginx
    networks:
      multirevproxy-nw:
        ipv4_address: 172.16.0.10
    depends_on:
      - proxy2
  proxy2:
    container_name: proxy2
    ports:
      - "81:80"
    environment:
      TZ: Asia/Tokyo
    image: nginx:latest
    volumes:
      - ./proxy2/conf:/etc/nginx/conf.d
      - ./proxy2/log:/var/log/nginx
    networks:
      multirevproxy-nw:
        ipv4_address: 172.16.0.20
    depends_on:
      - backend
  backend:
    container_name: backend
    ports:
      - "82:80"
    environment:
      TZ: Asia/Tokyo
    image: nginx:latest
    volumes:
      - ./backend/conf:/etc/nginx/conf.d
      - ./backend/html:/usr/share/nginx/html
      - ./backend/log:/var/log/nginx
    networks:
      multirevproxy-nw:
        ipv4_address: 172.16.0.100
networks:
  multirevproxy-nw:
    external: true
```

## 各nginxのconf
とりあえずproxy_set_headerなど無しの状態
#### proxy1
```conf:proxy1.conf
server {
    server_name  _;
    listen       80;
    location / {
      proxy_pass  http://proxy2;
    }
}
```
#### proxy2
```conf:proxy2.conf
server {
    server_name _;
    listen      80;
    location / {
      proxy_pass http://backend;
    }
}
```
#### backend
```conf:backend.conf
  server {
    server_name _;
    listen       80;
    location / {
      root  /usr/share/nginx/html;
      index index.html;
    }
  }
```
## docker起動
```sh:
$ docker compose up -d
```
### Dockerゲートウェイと各コンテナのIPの確認
```sh:
$ docker network inspect multirevproxy-nw | grep -E "Gateway|IPv4|Name"
```
Gateway : 172.16.0.1
proxy1  : 172.16.0.10/24
proxy2  : 172.16.0.20/24
backend : 172.16.0.100/24

## アクセステスト
DockerホストであるMacからアクセス
```zsh:
$ curl localhost
```
二次元標準正規分布を3Dプロットする


## 二次元標準正規分布を3Dプロットしたい


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348593/1dcb0898-167c-4a17-c8b9-ac13ab57d7ff.png)

プロットしました。

```python
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

# 二次元標準正規分布の定義
def normal_distribution_2d(x, y):
    return 1 / (2 * np.pi) * np.exp(-0.5 * (x**2 + y**2))

# X, Y の値の生成
x = np.linspace(-5, 5, 100)
y = np.linspace(-5, 5, 100)
X, Y = np.meshgrid(x, y)

# Z の値（分布の計算）
Z = normal_distribution_2d(X, Y)

# 3D プロット
fig = plt.figure(figsize=(8, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(X, Y, Z, cmap='viridis')

ax.set_xlabel('X axis')
ax.set_ylabel('Y axis')
ax.set_zlabel('Probability Density')
ax.set_title('2D Standard Normal Distribution')

plt.show()

```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/348593/08bb19b7-96d7-eaee-8c86-1b5ef59ff307.png)
【ChatGPT有＋DALL-E3】対象物をなんとか中央から外したい。


　どうも、カーブミラーです。

　今回は、対象物をなんとか中央から外したい。その奮闘記です。

:::note info
本記事は、ChatGPT（有料版）
＋DALL-E3で行なっております。
画像はありません。あしからず。
:::

　まずは、
　　8時59分頃、
　　　千葉県北西部を震源とする
　　　　地震がありましたね。

　東京も揺れました。
　　震度４だとか。

　東京湾が震源地とも。

　みなさん、大丈夫でしたか？
***
　次に、
　　ChatGPTアプリ版の
　　　無料版で、
　　　　Explore GPTsが
　　　　　表示されるように
　　　　　　なりました。

　GPTsの選択はできますけど、
　　GPTsの最初の画面で止まります。

　その画面下部には
　　“やりたきゃ、
　　　アップグレードしろよ”と
　　　　書いてあります。
　　　　　いや、もっとちゃんとした
　　　　　　文章ですけどねw

　Plusへの
　　勧誘みたいですねw
　　　これもひとつの戦略ですか。
***
　さて、本題です。

　DALL-E3は
　　基本的に
　　　対象物を中央に置きます。

　でも
　　主人公は、
　　　その対象物ではないことが
　　　　多いはずです。

　そこで、
　　いろいろと
　　　指示をしてみました。

　今回は、
　　その奮闘記、
　　　ということで
　　　　お送りします。
***
***user***
場所は、日本の銀座の高級クラブ。
中央にガラスのモニュメント。

ホステスの若いお嬢さん。その服装は肩の出ている高級なワンピース。
奇抜な服を着た似つかわしくないおっさん。

このふたりがソファーで並んで座り、顔を突き合わせて談笑している。
配置は、モニュメントが中央、カップルが右に配置。横長で描画

***ChatGPT***
（モニュメントを中心に、左側にホステス、右側におっさん）

***user***
リトライ

***ChatGPT***
（同じ）

***user***
ふたりは、ひとつのソファーに抱き合うように座っている。

***ChatGPT***
（ソファー中央にホステスとおっさん）

***user***
このふたりの対面には、同じようなソファーがあり、誰も座っていません。

***ChatGPT***
（ふたりが少し離れただけ）

***user***
ソファーは左右にひとつずつ。
ふたりは右のソファーで談笑。
もうひとつのソファーには誰もいない。

***ChatGPT***
（さらに離れる）

***user***
ふたりの座るソファーを、必ず中央右側に配置してください。

***ChatGPT***
（ソファー中央におっさん、右側にホステス。ようやく動いた）

***user***
主人公はガラスのモニュメント。
なので、ふたりを必ず画面右側に配置してください。

***ChatGPT***
（中央だが、やや右寄りにホステスとおっさん）

***user***（モニュメントが邪魔？）
プロンプトから、ガラスのモニュメントについて、削除してください。

***ChatGPT***
（左のソファーにホステス、右のソファーにおっさん）

***user***
ふたりは抱き合うようにして、端にいます。

***ChatGPT***
（端というよりは、店の奥の席）

***user***
焦点を彼女に当ててください。

***ChatGPT***
（中央右寄りにホステスとおっさん。近付いた）

***user***
焦点をおっさんに当ててください。

***ChatGPT***
（中央やや右寄りにおっさんとホステス）

***user***（もう一度）
焦点をおっさんに当ててください。

***ChatGPT***
（中央を挟んで、左ホステス、右おっさん。それからヘルプのホステスが真ん中の席に座ったw　おっさんの話につまらなそうな顔w）
***

　とりあえず、
　　こんな感じに
　　　なりました。

　なんとか
　　画面左右どちらかの
　　　画面三分の一とか
　　　　画面四分の一とかの
　　　　　指定ができないかとも
　　　　　　やってみましたけど
　　　　　　　苦労したほど
　　　　　　　　うまくいきません。

　何かわかったら
　　またご報告しますので

　みなさんの
　　作品制作の糧にも
　　　なりませんでしたね。

　今回は、ここまで。
React ：npm ERR! cb.apply is not a function

# エラー発生：npm ERR! cb.apply is not a function
Reactの初期設定コマンド`npx create-react-app . --use-npm`を実行したところ、`npm ERR! cb.apply is not a function`というエラーが発生しました。
```sh
twitter_react_frontend % npx create-react-app . --use-npm

(node:67518) [DEP0040] DeprecationWarning: The `punycode` module is deprecated. Please use a userland alternative instead.
(Use `node --trace-deprecation ...` to show where the warning was created)
npm ERR! cb.apply is not a function

npm ERR! A complete log of this run can be found in:
npm ERR!     /Users/toto/.npm/_logs/2024-01-28T02_58_52_906Z-debug.log
コード[ 'create-react-app@latest' ]で1のインストールに失敗しました
```

# 対応方法
アップデートとキャッシュのクリアにより、無事成功しました。
同じエラーが発生したときに、試してみてください。

- アップデート
```sh
twitter_react_frontend % npm install -g npm@latest

removed 25 packages, and changed 45 packages in 3s

24 packages are looking for funding
  run `npm fund` for details
  ```
- キャッシュクリア
```sh
twitter_react_frontend % npm cache clean --force
```

- 成功
```sh
twitter_react_frontend % npx create-react-app . --use-npm

Creating a new React app in /Users/toto/Desktop/twitter_react_frontend.
〜〜
We suggest that you begin by typing:

  cd /Users/toto/Desktop/twitter_react_frontend.
  npm start

You had a `README.md` file, we renamed it to `README.old.md`

Happy hacking!
```
Google Dialogflow を少しさわった

# Dialogflow
- テキスト入力を元に、ルールベースで適切な応答を返す
- 音声入力の場合は、Google Cloud Speech-to-Text でテキスト化してからDialogflowに渡す。
- あいづちは「SmallTalk」という機能があるらしいが、見つけられなかった
    - GitHub のリポジトリ　https://github.com/jyoshiv/Small-talk-chatbot-using-Dialogflow?tab=readme-ov-file
        -　使い方の例？　https://bot.dialogflow.com/218f85c9-b6a3-4d0b-9a88-5f96b6cf0be8
            -　実装サンプルらしいが、英語で、挨拶が返せる程度ぽい。

# プラン
- 初心者用のDialogflow ES (Essentials)と、複雑な動作ができるDialogflow CXがある。


# 例：単純なあいさつを返す

- Agentを作成
- Intentsを作成
    - インテント名は「GoodAfternoon」
    - Training phrases に、入力文の「こんにちわ」を設定
    - Responsesに、応答文の「こんにちわー」を設定
    - SAVEボタンで保存
- 右上の「Try it now」で、「こんにちわ」と入力すると、「こんにちわー」と応答が返る

![ScreenShot 2024-01-28 10.31.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142577/4d4159ca-1d99-547b-74e7-5ef676fe834d.png)


# 感想
- 日本語に対応しているのはありがたい
- ルールベースなので、正規表現は使えるが、限界がある。「ちわっす」や「ボンジュールでございます」といった変則的な挨拶に対応できない
- あいづちはもっと下位のレイヤーで受け答えして、会話の流れはDialogflowで拾い、内容のまとめや話の持っていき方は外部サービスのAIで処理するのが良さそう

# 関連するサービス
- [BotDistrikt](https://www.botdistrikt.com/)
    - ブラウザでGUIで応答システムが作れる
        - デモ動画では、ハンバーガー屋さんで注文を受け付けるBotを紹介していた
    - 


# 参考書籍
- 「音声対話システム　基礎から実装まで」　井上昴治、河原達也 著、オーム社、2022年10月13日 第１版、[オーム社のページ](https://www.ohmsha.co.jp/book/9784274229541/)、[Amazon](https://www.amazon.co.jp/dp/4274229548)
    - ChatGPTの事は書かれていないが、音声認識、言語理解、対話管理、評価方法などが、一通りまとまっている。
        - 他の本は、音声のテキスト化までしか言及していない中、対話に関する記述があるのが良い
            - 第9章　人間らしい対話を実現するための要素技術
            - 第10章　音声対話システムの未来
    - 対話管理も、有限状態オートマトンの図で説明されており、馴染みやすい

    - 「ハンズオン」として、PythonとGoogle Cloudを使った実装例があるのがありがたい

- 「会話の科学 あなたはなぜ「え?」と言ってしまうのか」　ニック・エンフィールド 
 著、夏目 大 訳、文藝春秋、2023年3月27日 発売  [Amazon](https://www.amazon.co.jp/dp/4163916792/)
    - 文法などの言語学ではなく、「会話学」とでも言うべき、話者交代や反応速度などに言及している
    - 会話の修復（聞き取れなかったり、意図がわからなかったりするときの「え？」のような言葉）は、頻繁に会話に登場するのに、今まで研究されてこなかった。それを本書では、研究成果として報告している
エンジニアコネクトに出席しました

# はじめに
先日エンジニアコネクトというイベント(講演会)に参加しました。
情報共有を行うために出席しました。
今回はどんなことを行ったのかをまとめ記事にしたいと思います。

# 参加イベント
https://cnctor-japan.connpass.com/event/305550/

# スケジュール

12:30 ~ 13:00	受付
13:00 ~ 13:15	開始・オープニング
13:15 ~ 13:55	交流①
13:55 ~ 14:05	LT①
14:05 ~ 14:15	休憩
14:15 ~ 14:55	交流②
14:55 ~ 15:05	LT②
15:05 ~ 15:45	交流③
15:45 ~ 15:55	LT③
15:55 ~ 16:05	休憩
16:05 ~ 16:40	交流④
16:40 ~ 17:00	宣伝・記念撮影・片付け

# 交流
４人８チームに分かれて、自己紹介を行い、趣味や現在行っている仕事内容
を共有し、お互いを知るという内容です。

皆さんWEB系エンジニアなのでlaravelやreactなど、フレームワークの仕事を行っている方や、フリーランスの方が多いイメージです。

私にとって全く知らないことが多く、今までになかった視点を増やすことができたので大変有意義な時間にになりました。

# LT(講演会)
登壇者が皆さんの前に立ち、これタメになったよっていうものやこれは覚えておいた方がいいよっていう内容を発表したます。

# 聞く人の立場になって感じたこと

公演の内容はどれも素晴らしいものでしたが、人によっては初見なので、何を言っているかわからないなんてこともありました。そこで自分なりに講演するときに気を付けることをまとめてみます。

1 喋るスピードが速すぎる
2 専門用語を使わない
3 図を多く使って説明する
4 常に初心者にもわかるような心がけが必要

# それぞれを感じた理由

1 喋るスピードが速すぎる

こちらについてですが、私はYouTubeを投稿している身なので結構
気を付けているつもりですが、基本自分が遅く喋っているスピードは
相手にとっては速いか、ちょうどいいくらいに聞こえます。
自分が喋る映像を録画し、分析してみると、ここ速いな、
ここ何言っているか分からん。という点がいくつも出てきます。

これを改善するといいプレゼンができます。（資料の内容次第なとこもある、、）



2 専門用語を使わない
3 図を多く使って説明する

この二つは共通している点があるので、一つにまとめています。

専門用語はイメージして理解するものだと私は考えているのですが、
言葉だけだと理解するのが困難です。
そこで使うのが図です。相手にイメージを持たせやすいので、初めての人にもわかりやすく、理解させることができます。


4 常に初心者にもわかるような心がけが必要
これは今回の層にもよるのですが、結構知見がある人でも、
初見分野が出てきたら、絶対に分かりません。

教える人は常に初心者でもついてこれるように、発表するべきだと考えました。

佐々木まことさんという方がいらっしゃるのですが、この人の記事はかなりわかりやすく、中級レベルまで書かれていると感じていますよければ参考に。
https://wa3.i-3-i.info/profile.html

# まとめ

今回はとても有意義な時間になりました。新たな情報や他業界を知りたいという方が
いましたら、ぜひ参加してみてください。