OmniAICreator/Qiita-1.07M huggingface dataset:
REST API と GraphQL

２年前のメモが出てきたので投稿する。
まじで大したこと書いてない。


## 状況

- 自分が読んだ既存のtweet(詳細情報含む)をとってきたいとします


## REST API だと

(1) `/api/v2/favorites`を叩き、お気に入りのtweetのid一覧

```json
{
  'favorite_ids':  [1, 33,65, 123]
}
```

(2) `/api/v2/favorites/:id`を4回叩き、それぞれの記事の情報を取得できます。



## GraphQL だと、

自分がとって欲しい記事のattributeまで指定して、一回で全ての情報をとってくる


👎 GraphQLだとコンテンツのキャッシュが難しい。
tmux の基本操作のメモ

## tmuxとは

- tmuxは、バックグランドで実行されるセッションを立ち上げる。
   - 例えば、以下のコマンドを実行することで、mysession という新しいセッションを開始し、現在のターミナルをそのセッションに割り当てることができます。
   - `$ tmux new -s mysession`

- これにターミナルをattach/detachする。セッションの中の一つのwindowが開かれる。
   - windowは複数作成し、切り替えることができる。
   - 例えば`Ctrl + b c`, `Ctrl + b , mywindow2`コマンドによって、新しくウィンドウを新しく作成し、さらにそこに操作を切り替えることができる。ウィンドウ間の切り替えは名前を指定して行うことも可能。

- windowは上下左右に分割することもできる。この一つ一つをペインと呼ぶ。
   - `Ctrl + b "`によって、上下二つにウィンドウを分割できる。
   - `Ctrl + b %`によって、左右二つにウィンドウを分割できる。


## 考察

pane一つにつき、一つのprocessが走りうるという認識です。
割り込みに関してまとめる

OS自作入門第7章で紹介されいてる内容をメモる。


## ハードウェアのイベントの到着を確認する方法

- ポーリング方式
   - ハードウェアのイベントが発生したかをOSが問い合わせる。
- 割り込み方式
   - イベントが到着した時にハードウェアがOSに割り込みを行う。


本記事では、割り込み方式についてまとめる。


## 割り込みの流れ

事前準備

- イベントが発生時に実行する割り込みハンドラを用意する。
- 割り込みハンドラを割り込み記述子テーブル=IDT(interrupt descriptor table)に登録する。


イベント発生時
- ハードウェアがイベントをCPUに通知する。
- CPUは、現在の処理を中断し、イベントの種類に応じて登録された割り込みハンドラに処理を移す。
- 割り込みハンドラの処理が終わると、中断していた処理を再開する。


## その他

- 割り込みハンドラはメソッドで表される。
- 割り込みベクタは、割り込みの種類。
- IDTには、割り込みベクタの識別子:InterruptDescriptorの対応表。
   - InterruptDescriptorには、割り込みハンドラのメソッドのアドレスが含まれる。
ネットワークとサーバー


IPアドレスとサブネットマスク
```
たとえば、IPアドレス：172.16.0.1を使用している場合、サブネットの値でネットワーク範囲（サブネット）も異なる。

IPアドレス / サブネットマスク	ネットワーク範囲(サブネット)	パソコン等の数(注1)
172.16.0.1 / 255.255.255.0	172.16.0.0～172.16.0.255	254
172.16.0.1 / 255.255.0.0	172.16.0.0～172.16.255.255	65,534
パソコン等を接続できる台数は「ネットワーク範囲 - 2」となる。
先頭のアドレスは「ネットワークアドレス」・最終のアドレスは「ブロードキャストアドレス」となり利用できない。

ネットワークが同一のパソコンやサーバは通信することができる。
逆にネットワークが同一でないパソコンやサーバは、ルータやネットワーク機器（L3など）を使用してネットワークを切り替えて通信する必要がある。


IPアドレス
グローバルIPアドレス	インターネットなど外部で使用しているIPアドレス
プロバイダーなどがサブネットマスク（サブネット）を管理・割振りしている
利用者が自由にサブネットマスクを割振りできない
プライベートIPアドレス	企業内や家庭内で使用しているIPアドレス企業や一般家庭でサブネットマスク（サブネット）を管理・割振りすることができる

IPアドレス(3種類)
プライベートIPアドレス＝ローカルIPアドレスという。
自宅や会社など、ネットワーク内のIPアドレスのこと。

ルーターに複数のパソコンや機器をつないで使う場合、プライベートIPアドレスがあることでルーターとパソコン間、パソコンと機器間が通信できる。

プライベートIPアドレスには、ネットワーク部とホスト部がある。

例えば 192.168.1.11 というIPアドレスがある場合。
192.168.1 がネットワーク部。
11がホスト部。

グローバルIPアドレスはパブリックIPアドレスとも呼ばれる。
インターネットに接続されているコンピュータや通信機器を個々に特定するための、一意で割り当てられたIPアドレスのこと。
インターネット上の住所にあたり、インターネットに接続する際に必ず必要となる。

192はプライベートアドレスのクラスC向け
172はクラスB、中規模
10から開始されるアドレスはクラスA。

ブロードキャストアドレス
　ブロードキャストアドレスは、ホスト部のビットが全て「1」であるもの。
同一ネットワーク内に存在する全てのホストに向けて同報通信する際に使用する。

```

「サブネットマスク」
```
IPアドレスのうち、ネットワークアドレスとホストアドレスを識別するための数値。 コンピューターが同じLANにいるかを判断する際に利用されることが多い。

例えば、社内で20台のパソコンがある場合、同一のネットワークなのでネットワーク部はすべて 192.168.1 になる。
ホスト部である11の部分が、各パソコンや機器に割り当てられている箇所。

このように始めの 192.168.11 をネットワーク部、最後の数字(第4オクテット)をホスト部にするというルールを確定させる。
これを サブネットマスクといわれる。

この例でいうと、255.255.255.0 という数字が 192.168.11 をネットワーク部にして 最後をホスト部にするということになる。

```

```
DHCP
「Dynamic Host Configuration Protocol」
コンピュータがインターネットに接続する際に必要となるIPアドレスなどの設定を自動的に割り当てるプロトコル

NTP
「Network Time Protocol」
 NTPサーバは、あらゆる機器の時刻情報を同期するためのプロトコル（通信の手順や約束事を定めた規格）のことです。 コンピューターだけではなく、ルーター、サーバ、各種スイッチなどに正しい時刻情報を取得・配信できる


プロキシサーバのメリット
・　キャッシング
　プロキシサーバはキャッシュ機能を実装させている。
 Webサーバから受信したWebページの情報をプロキシサーバ自身のHDDなど一時的にキャッシュすることができる。これによりクライアントPCからHTTPリクエストをプロキシサーバに送信した時は
そのキャッシュ情報があれば、キャッシュ情報をすばやく送り返すのでWeb通信の高速化を実現可能。


　・ユーザの認証
　プロキシサーバにユーザ認証を実装すると、認証されたユーザだけがインターネット通信が可能になる。

　・ユーザの一元管理(ログの履歴)
　内部から外部ネットワークに出ていくHTTPトラフィックを一元管理してユーザ通信を把握する事ができる。

　・URLフィルタリング
　プロキシサーバでは、特定のURLをアクセス禁止に設定することができる。
これにより、特定の不適切なWebサイトの閲覧を禁止することができる。
また、受信コンテンツのウィルスチェックをすることも可能。

　・匿名性の確保
　プロキシサーバを導入することで、WebサーバにはクライアントPCではなくプロキシサーバがアクセスする
　ことになるので、WebサーバにはクライアントPCの固有情報（ IPアドレス、OS、Webブラウザ ）が漏れることなくWebサーバを閲覧できる。
　※ただし、使用しているプロキシサーバの固有情報は伝わるので注意。

デメリット
不正サイトへ誘導される可能性もある
接続履歴を見られる・情報が盗まれる可能性がある

プロキシサーバーを利用する時の確認事項
安全なプロキシサーバーを利用する一般に公開されているプロキシサーバーを使用するときには、事前に信頼できるプロキシサーバーなのか、確認してからアクセスするようにする必要がある。

無料で利用できる公開プロキシサーバーもあるが、信頼性が不明なサーバーは、サイバー攻撃の被害に遭遇する可能性も高くなる。

認証設定を有効化しておく
自身でプロキシサーバーを購入してネットワークを構築する場合、IDとパスワードによる認証を有効化しておく必要がある。

もし、有効化を怠ると、誰でもアクセスできる状態になってしまう。
不特定多数が利用できるプロキシサーバーはリスクが高く、ウイルスの感染や、個人情報の漏洩、サイバー犯罪のアクセス経路に利用されてしまうといった危険性を下げる。そのような対策や前提知識等が不可欠となる。

DNS（Domain Name System）
IPアドレスとドメイン名を紐づけし、IPネットワーク上で管理するシステム。

権威DNSサーバー
権威DNSサーバーとは、ドメインの情報をもつものを保管するサーバー

キャッシュDNSサーバー
入力されたドメイン名から権威DNSサーバーに合致する情報を探し出すよう指示を出すサーバー


BGP (Border Gateway Protocol)
インターネット上で異なる組織（AS: Autonomous System）間の経路情報を交換するためのプロトコル
組織間のネットワークを繋ぐには、BGPが経路情報を交換することで、最適な経路でデータが転送される
↓
※主な用途
インターネットの基幹技術として、ISP（インターネットサービスプロバイダ）や大企業など
組織間でルーティングを行う際に利用される

```
GitHub ActionsのワークフローでElixirのDialyzerをキャッシュして高速化する

GitHub Actionsのワークフローで `mix dialyzer` を実行するとかなりの時間がかかる問題を，キャッシュすることで解決する方法を編み出しました．

前回の記事

https://qiita.com/zacky1972/items/4a7614bff401650fb7d6

基本的には `_build/dev/dialyxir_erlang-*_elixir-*_deps-dev.plt*` をキャッシュしてあげれば良いです．

そこで，シングルレポジトリの場合には，次のようにします(Ubuntu上だけで`mix dialyzer`を実行するとしています)．

```yaml
    - name: Restore dialyzer cache (Ubuntu)
      if: ${{ startsWith(runner.os, 'linux') }}
      uses: actions/cache@v3
      with:
        path: ${{ github.workspace }}/_build/dev/dialyxir_erlang-${{ matrix.otp-version }}_elixir-${{ matrix.elixir-version }}_deps-dev.plt*
        key: ${{ runner.os }}-${{ steps.system-info.outputs.release }}-Elixir-${{ matrix.elixir-version }}-OTP-${{ matrix.otp-version }}-plt
        restore-keys: ${{ runner.os }}-${{ steps.system-info.outputs.release }}-Elixir-${{ matrix.elixir-version }}-OTP-${{ matrix.otp-version }}-plt
```

ただし，マルチレポジトリ構成にしているときには，次のように，それぞれのサブプロジェクトで別々のIDになるようにキャッシュしてあげないとエラーになります．

```yaml
    - name: Restore dialyzer cache (Ubuntu)
      if: ${{ startsWith(runner.os, 'linux') }}
      uses: actions/cache@v3
      with:
        path: ${{ github.workspace }}/${{ matrix.working-directory }}/_build/dev/dialyxir_erlang-${{ matrix.otp-version }}_elixir-${{ matrix.elixir-version }}_deps-dev.plt*
        key: ${{ runner.os }}-${{ steps.system-info.outputs.release }}-Elixir-${{ matrix.elixir-version }}-OTP-${{ matrix.otp-version }}-repo-${{ matrix.working-directory }}-plt
        restore-keys: ${{ runner.os }}-${{ steps.system-info.outputs.release }}-Elixir-${{ matrix.elixir-version }}-OTP-${{ matrix.otp-version }}-repo-${{ matrix.working-directory }}-plt
```
Next.js でローカルサーバーを起動した時に自動でブラウザを開く

# はじめに
この記事では、Next.js でローカルサーバー起動した時に自動でブラウザを開く方法について説明します。

# 前提
開発環境は以下の通りです。
- Windows11
- VSCode
- Next.js 13.4.4
- React 18.2.0
- Node.js 18.14.0
- open-cli 7.2.0

以下のコマンドでプロジェクトを作成します。
```
npx create-next-app@latest
```

# 方法1. ```package.json``` の ```scripts``` の変更
```package.json``` の ```scripts``` ```dev``` を以下のように変更します。 

```package.json
"scripts": {
  "dev": "npm run open-browser && next dev",
  "open-browser": "start http://localhost:3000",
}
```

# 方法2. open-cli の利用
open-cli というライブラリを利用します。

https://github.com/sindresorhus/open-cli

以下のコマンドでインストールします。

```
npm install open-cli
```

次に ```package.json``` の ```scripts``` ```dev``` を以下のように変更します。 

```package.json
"scripts": {
  "dev": "npx open-cli http://localhost:3000 && next dev",
}
```

これでローカルサーバーを起動した時に自動でブラウザが開くようになりました。

# 参考
- [Auto open browser when run dev](https://github.com/vercel/next.js/discussions/13448)
【Java】ユーザー入力処理とエラーハンドリングの実装方法

# はじめに
Javaプログラムでユーザーからの入力を受け取り、エラーハンドリングを適切に行う方法について説明します。例として、文字列と整数の入力を受け付ける単純なメソッドを作成します。また、エラーが発生した際に繰り返し入力を求めるような挙動を実現します。

## コードの実装
以下のコードは、JavaのScannerクラスを使用して文字列と整数の入力を受け取ります。

```java:文字列と整数値の入力を求めるメソッド
import java.util.InputMismatchException;
import java.util.Scanner;

public class InputExample {
    public static void main(String[] args) {
    
        // getInputStringメソッドで文字列を代入する
        String name = getInputString("名前を入力してください: ");
        // getInputIntメソッドでも整数値を代入する
        int age = getInputInt("年齢を入力してください: ");

        System.out.println("入力された情報:");
        System.out.println("名前: " + name);
        System.out.println("年齢: " + age);
    }
    
        // 文字列の外部入力を求めるメソッド
    public static String getInputString(String message) {
        // 外部入力のメソッドを使用するためにはAPIのインスタンス化が必要
        Scanner scanner = new Scanner(System.in); 
        System.out.print(message);
        // インスタンス化したscannerで文字列を取得する
        return scanner.nextLine();
    }

        //　整数値の外部入力を求めるメソッド
    public static int getInputInt(String message) {
        // 外部入力のメソッドを使用するためにはAPIのインスタンス化が必要
        Scanner scanner = new Scanner(System.in);
        // 整数値を代入する変数を初期化
        int input = 0;
        // ループ処理の判定材料にfalseを代入しておく
        boolean isValidInput = false;

        // 変数のisValidInputがfalseの場合はループし続ける
        while (!isValidInput) {
            System.out.print(message);

        //　例外処理
            try { 
                 //　エラーが起こりそうなコードを記述する
                input = scanner.nextInt(); // 整数値の外部入力を求める
                isValidInput = true; // エラーが発生しなかった場合はtrueでループを止める
            } catch (InputMismatchException e) {// エラーが発生した場合の処理を記述する
                // InputMismatchException 期待したデータ型を一致しなかった場合にスローされるエラー
                // ユーザーが整数以外の文字列を入力した場合など
                System.out.println("整数を入力してください。");
                scanner.nextLine(); // 改行文字をクリアするために次の行を読み飛ばす。入力エラーを処理するために必要です
            }
        }

        return input;
    }
}
```

## まとめ
この記事では、Javaプログラムでユーザーからの入力を受け取り、エラーハンドリングを処理する方法をご説明いたしました。Javaに限らず入力処理はよく使われる手法かと思われますので参考になれば幸いです
【コンピュータサイエンス】Web技術の基礎知識をまとめました

この記事は『プロになるためのWeb技術入門――なぜ，あなたはWebシステムを開発できないのか』やその他記事を読んで、主要なWeb技術を自分なりに噛み砕いてまとめたものになります。

### ステートフル
`ユーザーが操作した情報(リクエスト)を保存して、あとで使えるようにしておくこと`

- そのときによってレスポンス(後述)が変わる
- 以前の操作を保存・反映できるため、操作をスムーズにできる

###### 例
- ECサイトで商品をカートに入れたり、あとで閲覧したり他の商品とまとめて注文できる

### ステートレス
`ユーザーが操作した情報(リクエスト)を保存しないこと`

- レスポンスは変わらない
- 情報を保存しないので負荷が少ない

###### 例
- Webサイトのコンテンツは、管理者が編集や削除をしない限りは、誰がどのようにアクセスしても同じページが表示される


### リクエスト
`ユーザーがサーバーに対して行う要求`

- 一般的にはHTTPリクエストを指す
- GETメソッドとPOSTメソッドがある

###### 例
- URLにアクセスする
- Webサイト内のボタンやリンクをクリックする
- フォームに入力して送信ボタンを押す

### レスポンス
`サーバーからユーザーに対する応答`

- 一般的にはHTTPレスポンスを指す

###### 例
- そのままHTMLを返す
- 要求と一緒に受け取ったデータを元に、データベースに登録・更新・削除して結果を返す

### クッキー
`ユーザーがWebサイト上で入力した情報などを保存したファイル`

### プロトコル
`コンピューター同士がやり取りするための決まり事`

- `TCP/IP`が一般的

###### 例
- アドレスバーに`http://www.XXX.co.jp/`と入力した場合、`http:`の部分がプロトコル
- HTTPプロトコルを使って`www.XXX.co.jp`にアクセスせよと命令される

### ポート番号
`プロトコルで情報を受け取る際の接続口`

- IPアドレスでコンピュータを指し、ポート番号で通信相手であるアプリを指定

###### 例
- HTTPプロトコルもポート番号は`80`
Python 短縮URL展開

## メモ

```python
import requests

res = requests.head(url)
if int(res.status_code / 100) != 3:
    return res.url
else:
    return res.headers['Location']
```

https://a.r10.to/hUR2Oe　のようにステータスコードが 301 になる場合の対策
requests.get(url).url では無理な場合
nat超え

yamahaルーターのnat超えに関する記事
```shell:ネットワーク構成
RTX_WWW（Webサーバー） --- RTX_WR --- NVR_NET --- PC
```


- PCからはRTX_WRのグローバルアドレスにポート80番でアクセスする
- RTX_WRはポート80番にアクセスしてきたパケットをnatを使ってプライベートアドレス宛に送る
- ip filterを用いて接続する通信を記述する（ip filterなしだったらALL　PASS,あったらホワイトリスト）
- dynamic filterの基本的な使用方法は内側→外側の通信のレスポンスを受け入れられるように設定する
- 動的フィルターはセッションが切れたときにlogを出す
- フィルターのsyslogレベルは notice(設定必要)

### 習得コマンド
- show ip connection *detail
- show nat descripter address *detail
- syslog notice on

### RTX_WWW 
- IP_アドレス(WAN) : 122.176.74.4/24
```
(config)
login user admin *
user attribute admin administrator=2 login-timer=clear
console character ja.utf8
console prompt RTX_WWW
login timer clear
ip route default gateway 122.176.74.1
ip lan2 address 122.176.74.4/24
tftp host any
telnetd host lan
httpd host any
```



### RTX_WR
- IPアドレス(LAN) : 122.176.74.1/24
- IPアドレス(WAN) : 10.130.1.2/24
```
login user admin *
user attribute admin administrator=2 login-timer=clear
console character ja.utf8
console prompt RTX_WR
ip route default gateway 10.130.1.1
ip lan1 address 122.176.74.1/24
ip lan2 address 10.130.1.2/24
ip lan2 secure filter in dynamic 1
ip lan2 secure filter out 1300
ip lan2 nat descriptor 1
ip filter 1200 pass-log * 122.176.74.4 tcp * www★
ip filter 1300 reject 122.176.74.4 * tcp www *
ip filter dynamic 1 * * www
nat descriptor type 1 masquerade★ポートのマスカレードを使用
nat descriptor address outer 1 primary★外側への通信のwanに対しては(今回は10.130.1.2)NATを使用
nat descriptor masquerade static 1 1 122.176.74.4 tcp www ★10.130.1.2:80は122.176.74.4に変換
syslog notice on
telnetd host lan
```

### NVR_NET
- IPアドレス(LAN) : 192.168.100.1/24
- IPアドレス(WAN) : 10.130.1.1/24
```
(config)
console character ja.utf8
console prompt NVR_NET
login timer clear
//不要ip route default gateway 10.130.1.2(インターネットはデフォルトゲートウェイでRTX_WRを知らない)
ip lan1 address 192.168.100.1/24
ip lan2 address 10.130.1.1/24
telnetd host lan
dhcp service server
dhcp server rfc2131 compliant on
dhcp scope 1 192.168.100.2-192.168.100.191/24
```

### PC
- IPアドレス : 192.168.100.2/24(dhcp)
Laravelでリダイレクト処理を書く方法

# Laravelでリダイレクト処理を書く方法

## コントローラ内のメソッドに返り値として記述する。
```〇〇Controller.php
class 〇〇Controller extends Controller
{
	// リダイレクト
	public function redirect() {
		return redirect('URL');
	}
}
```
・リダイレクトはredirect()関数を使用する。
　これはどのディレクトリからも自由にアクセスできる関数。
・redirect関数の書き方は以下の通り。route()メソッドを使用するのがおすすめ。（URLの変更にも影響を受けないため）
```PHP
// URLを直接指定する
return redirect('URL');

// to()メソッドを使ってURLを直接指定する
return redirect()->to('URL');

// route()ヘルパーを使って名前付きルートを指定する
return redirect(route('ルート名'));

// route()メソッドを使って名前付きルートを指定する ★おすすめ
// 補足：route()ヘルパーとは異なる。redirect()ヘルパーは引数が空だとRedirectorというクラスのインスタンスを返すが、そのインスタンスが持つroute()メソッドのこと
return redirect()->route('ルート名');

// action()メソッドを使ってコントローラとアクションを指定する
return redirect()->action([コントローラ名::class, 'アクション名']);
```


## リダイレクトした後、フラッシュメッセージを表示したい場合
```〇〇Controller.php
class 〇〇Controller extends Controller
{
	// リダイレクト
	public function redirect() {
		return redirect()->route('ルート名')->with('キー名', '任意のメッセージ');
	}
}
```
・フラッシュメッセージ：処理結果をユーザーに伝えるためのメッセージ。
・with('キー名','任意のメッセージ')：
　フラッシュメッセージを表示するための関数。
　セッション($_session('キー名'))にメッセージが保存される仕組み。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3323019/f7d5612d-4606-b3fd-59cc-f0b73ab33ab0.png)
rubyで仮想DOMを扱えるようにする「ruby-wasm-vdom」をライブラリとして公開しました


## この記事は何
以前Qiitaで以下のようなRubyで仮想DOMを扱う方法を記事にしました。

https://qiita.com/getty104/items/410448f7e7a20737c811

https://qiita.com/getty104/items/929af3742eb1dddacbaf

これらで紹介した仮想DOMを使って、Brainf*ckのインタプリタを作ってみたのですが、簡単なプロトタイプを作るのにはかなり便利なことが改めて実感できたので、せっかくなのでライブラリとして公開してみました。

https://qiita.com/getty104/items/a5a931cd1d7e967ad9a5

この記事では作成した`ruby-wasm-vdom`について紹介していきます。

## ruby-wasm-vdomとは

`ruby-wasm-vdom`は、文字通りRubyで仮想DOMを扱えるようにするためのライブラリです。

https://github.com/getty104/ruby-wasm-vdom

以下のような感じで仮想DOMを全てRubyのみで書くことができます。

```html
<html>
  <head>
  </head>
  <body>
    <div id="app"></div>
    <script src="https://getty104.github.io/ruby-wasm-vdom/index.js"></script>
    <script type="text/ruby">
      state = {
        count: 0,
      }

      actions = {
        increment: ->(state, value) {
        state[:count] += 1
        }
      }

      view = ->(state, actions) {
        h(:div, {}, [
          h(:button, { onclick: ->(e) { actions[:increment].call(state, nil) } }, ['Click me!']),
          h(:p, {}, ["Count is #{state[:count]}"])
        ])
      }

      App.new(
        el: "#app",
        state:,
        view:,
        actions:
      )
    </script>
  </body>
</html>
```

このような感じでブラウザ上に`<script src="https://getty104.github.io/ruby-wasm-vdom/index.js"></script>` を記述するだけで利用ができるようになります。

また、 https://qiita.com/getty104/items/929af3742eb1dddacbaf で記事にしたとおり、JSXライクの記述を行うことも可能です。

```html
<html>
  <head>
  </head>
  <body>
    <div id="app"></div>
    <script src="https://getty104.github.io/ruby-wasm-vdom/index.js"></script>
    <script type="text/ruby">
      state = {
        count: 0,
      }

      actions = {
        increment: ->(state, value) {
        state[:count] += 1
        }
      }

      view = ->(state, actions) {
        eval DomParser.parse(<<-DOM)
          <div>
            <button onclick='{->(e) { actions[:increment].call(state, nil) } }'>Click me!</button>
            <p>{"Count is #{state[:count]}"}</p>
          </div>
        DOM
      }

      App.new(
        el: "#app",
        state:,
        view:,
        actions:
      )
    </script>
  </body>
</html>
```

どのように実装しているかは以前記事にしています。

https://qiita.com/getty104/items/410448f7e7a20737c811

## 何が嬉しいの？
このライブラリを使うとRubyで仮想DOMを扱えるようになります。
実際どういう時にこのライブラリが便利かというと、ズバリ「RubyのライブラリやコードのデモをWeb上で動かしたい時」です。

今回作ったruby-wasm-vdomはruby.wasm上で動いているので、Rubyで実装したコードをそのまま組み込むことができます。
例えば、以下のようなBrainf*ckのインタプリタも、インタプリタのコードを書いてruby-wasm-vdomで実行できるようにしてあげるだけで簡単にデモを公開することができました。

https://qiita.com/getty104/items/a5a931cd1d7e967ad9a5

ReactやVue.js、Svelteなど、便利なフロントエンドのライブラリはたくさんありますが、それらを使ってRubyのコードのデモを実装するのは環境構築含め、少々面倒です。

今回作った`ruby-wasm-vdom`はスクリプトを一行書き込むだけで利用できるので、簡単にRubyのコードをWeb上で動かすことができます。

## まとめ
今回はRubyで仮想DOMを扱えるようにするライブラリ`ruby-wasm-vdom`を紹介しました。
このライブラリを使うことで、Rubyで仮想DOMを扱えるようになります。
また、このライブラリを使うことで、Rubyのコードを簡単にWeb上で動かすことができます。
みんなでRuby Lifeを楽しみましょう！
ABC306回答メモ

0.はじめに
　今回は最初から集中力が無く、C問題までは解けましたが
　D問題がDPじゃないと解けなさそうなので、諦めてしまいました。
　レート落ち必死だなと思ってたら、なんかNoratingになってました。

1.A - Echo
　文字列を頭から読み込んで、回答用文字列に1文字を2回くっつけていき
　さいごに回答用文字列を出力しました。

　https://atcoder.jp/contests/abc306/submissions/42320417

2.B - Base 2
　リストを後ろから読んで文字列として連結し
　最後にその文字列を2進数として出力してACでした。

　https://atcoder.jp/contests/abc306/submissions/42327456

3.	C - Centers
　2回目チェック用辞書と回答用文字列を準備。
　リストを頭から読んでいき、読んだ数字が辞書になければ値0で登録
　あれば、値が0なら、回答用文字列に登録し、値を1に。
　（1の場合は何もしない）
　最後に回答用文字列を出力して終了。

　https://atcoder.jp/contests/abc306/submissions/42335209

以上
電子通信事業法による対応まとめ

# はじめに
みなさん電子通信事業法ってご存知ですか？
サービスの円滑な提供・利用者の利益の保護を図るための制度との事ですが、こちらが6月16日より改正されています。
この改正の中で最も影響がある部分が外部送信規律です。
この外部送信規律というのは、 「事業者が利用者に関する情報を第三者に送信させようとする場合、利用者に確認の機会を付与する」というもので、対象となる会社は必要な事項の公表や通知を行う必要があります。
今回はこの外部送信規律に関して対象になるSDKなどを列挙的に備忘録として残しておこうと思います。

# 対象一覧
私が対応しているもので、記載する必要があるものは以下になります。

Google Play
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://policies.google.com/privacy?hl=ja

Firebase Analytics
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://firebase.google.com/support/privacy

Firebase Crashlytics
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://firebase.google.com/support/privacy/

Firebase Cloud Messaging　
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://firebase.google.com/support/privacy/

Firebase Dynamic Links　
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://firebase.google.com/support/privacy/

HelpshiftX
モジュール提供者名：Helpshift Inc.
収集する利用者情報の項目：https://www.helpshift.com/legal/privacy/

Twitter
モジュール提供者名：Twitter Inc.
収集する利用者情報の項目：https://twitter.com/ja/privacy

ZucksAdNetworkSDK
モジュール提供者名：株式会社Zucks
収集する利用者情報の項目：https://zucks.co.jp/ja/privacy/

AdGeneration
モジュール提供者名：Supership株式会社
収集する利用者情報の項目：https://supership.jp/privacy/

AdMob
モジュール提供者名：Google Inc.
収集する利用者情報の項目：https://support.google.com/admob/answer/6128543?hl=en

以上です。
今回は都合により割愛してますが、それぞれの利用目的もしっかり記載しておきましょう。

# さいごに
正直上記を記載してユーザーが見るかと言われると疑問が残りますが、、、
常に安心して使っていただけるように気を配っていきたいところですね。
Laravelの文字列用データ型の違い

Laravelを使用した場合、以下の文字列の型がある。
・string型
・text型
・longText型

違いは、**格納できる文字数が違う**。
・string型...255文字まで
・text型...16384文字まで
・longText型... 65,535バイトまで

使用例
・string型...タイトルなど短い文章の時に使用する。
・text型...本文など長い文章の時に使用する。
・longText型...text型では収まらない文字数の時に使用する。（めったに使用しないとのこと。）


参考サイト：https://biz.addisteria.com/string_text_longtext/
ABC 306 備忘録

## 概要
　今回はABC306（2023年6月17日21:00~22:40）の問題ごとのポイントと自分の実装、およびリアタイしたときの自分の感想について述べていきたいと思う。

## A問題
https://atcoder.jp/contests/abc306/tasks/abc306_a
### ポイント
- 入力をリストで受け取り、文字を繰り返すように新しい文字列に追加
### 自分の実装
```Python:ABC_306_A.py
N = int(input())
S = input()

S_new = ''

for i in S:
    S_new += i
    S_new += i
    
print(S_new)
```
## B問題
https://atcoder.jp/contests/abc306/tasks/abc306_b
### ポイント
- 問題文の通りにAの10進法表記を計算
- 桁数がズレないように注意
### 自分の実装
```Python:ABC_306_B.py
A = list(map(int, input().split()))
sum_A = 0

for i in range(len(A)):
    sum_A += A[i] * 2 ** i

print(sum_A)
```
## C問題
https://atcoder.jp/contests/abc306/tasks/abc306_c
### ポイント
- 数列A中に出てくる数字は決まっているので、各数字についてどの順番で出ているかを記録
- 各数字に対して、`[数字自体, その数字の中で真ん中となるインデックス]`の情報を格納
- インデックスの順番で昇順となるようにソート
- 元の数字を記録し、出力
### 自分の実装
```Python:ABC_306_C.py
N = int(input())

A = list(map(int, input().split()))

indices = [[i] for i in range(N+1)]

# 数列Aのi番目の数字の番号に対応する列に格納
for i in range(3*N):
    indices[A[i]].append(i+1)

f = []

for ith_index in indices[1:N+1]:
    f.append([ith_index[0], ith_index[2]])

# f(i) となるもののインデックスの順番にソート
f = sorted(f, key=lambda x:x[1])
ans = []

for f_i in f:
    ans.append(f_i[0])

print(*ans)
```
## D問題
https://atcoder.jp/contests/abc306/tasks/abc306_d
### ポイント
- i番目の料理が出てきた際に、高橋くんがお腹を壊している・いない状態となる時にそれまで食べた料理のおいしさの総和が最大をDPで計算
- i番目の料理が解毒剤入りか毒入りかどうかで場合分けを行う
### 自分の実装
```Python:ABC_306_D.py
N = int(input())

# X:毒入りかどうか 0:解毒剤入り、1:毒入り
# Y:料理のおいしさ
X, Y = [], []

# i回目の料理を食べるかどうか判断する際に
# dp[i][0]:お腹を壊していない時のおいしさの合計の最大値
# dp[i][1]:お腹を壊している時のおいしさの合計の最大値
dp = [[0, 0] for i in range(N+1)]

for i in range(1,N+1):
    X_i, Y_i = map(int, input().split())
    if X_i == 0:
        dp[i][0] = max(max(dp[i-1][0]+Y_i, dp[i-1][0]), dp[i-1][1]+Y_i)
        dp[i][1] = dp[i-1][1]
    else:
        dp[i][0] = dp[i-1][0]
        dp[i][1] = max(dp[i-1][0] + Y_i, dp[i-1][1])

print(max(dp[N]))
```
## 感想
　今回は、自分にしてはスムーズに進められたと思う。D問題まで`WA`や`TLE`を出すことなく35分ほどで解くことができた。その後、E問題が解けずにずっと悩んでいたのだが、その間にジャッジが滞っていたのだと思う。`Unrated`となってしまったのは、残念であるが今後も頑張りたいと思う。ただ、最近このようなことが多いので、他のサイトを利用しようかとも思っている。特に、外資系のコーディングテスト対策になるらしい`LeetCode`に注目している。
高齢者にいかにＡＩを浸透させるかを考える（２）

https://qiita.com/EasyCording/items/b9acd84ed7ffb1e26994


先日はAMAZONのECHOで、チャットＧＰＴを使ったアプリを試作した。

内容は、アマゾンのスキルからCHATGPTを呼ぶというもの。

ただし、１点分からなかったことがあり、今日はそれについて自分が感じた対策を書いてみる。

# CHATBOT

試したCHATBOTはYOUTUBE動画を参考に作成した。(まとめはCHATGPTを使用）

https://www.youtube.com/watch?v=dglcC1Si_fU&t=330s

>もちろんです！以下はVoiceflowを使用してチャットボットを作成するためのステップです。

1. VoiceflowでChatGPT 3.5 Turboを設定する。
   - アカウントを作成する。
   - モデルとメッセージを入力し、変数を作成する。

2. チャットボットの設定を行う。
   - ロボットとの対話を設定する。
   - 話者を設定し、テキストを設定する。
   - チャットボットに反応するように依頼する。

3. Amazon DevelopersでInvocation Nameを設定する。
   - Amazon Developersにアカウントを作成する。
   - Invocation Nameを設定する。
   - 開発者コンソールからAlexaでテストする。

> 以上の手順を実行することで、Voiceflowで簡単にチャットボットを作成し、Alexaでテストすることができます。


# 実際

　結局のところ、質問　→　応答　→　質問　→　応答と言うところで、前の会話にジョイントしていけば良いのかと思いきや、やはり変なことになってしまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/d6ac4bd0-872b-f109-b7d6-33543cc93d2e.png)

　そこで、次回は前の会話を記憶させる（ＬＳＴＭのような）仕掛けが必要で、やはりここは会話の内容をデータベースにストレージさせて、どんどん記憶させて、そのうえで続けるような仕組みが必要ではないだろうかと思う。
　これは個人プロファイルのレベルではなく、何のトピックに関する物か？を分岐させて、データベースからしかるべき情報をとってくる必要である。

# 年寄

 特に年寄というものは、少なくとも以前の会話を覚えていない。話す内容に新規性がない。同じ話しかしない。ぼける・・・という永久ループを回しがちである。
　そのため、CHATGPTが会話を覚えてあげるのも手である。

# シチュエーション 1 (BARD)

>はい、わかりました。具体的なストーリーでユースケースを作成します。

課題

ChatGPT は、会話の流れを記憶することができず、前回の質問に答えることができません。そのため、会話が途切れたり、意味不明になったりします。

対策

ChatGPT は、会話の内容をデータベースに保存し、前回の質問に答えられるようにする必要があります。また、会話のトピックごとにデータベースを分岐させ、必要な情報を取得できるようにする必要があります。

ユースケース

ある日、ある男性が祖母と電話で話していました。男性は祖母に、最近の出来事について話しました。しかし、祖母は男性の話を聞き忘れており、同じ質問を何度もしていました。男性は、祖母に会話の内容を覚えてもらうために、ChatGPT を利用することにしました。

男性は、ChatGPT に、祖母と会話の内容を保存するように指示しました。ChatGPT は、男性と祖母の会話の内容を保存し、前回の質問に答えられるようになりました。祖母は、ChatGPT に助けてもらい、男性の話を聞くことができました。

ChatGPT は、年配の方と会話する際にも役立ちます。年配の方は、以前の会話を覚えていないことが多く、同じ話を何度もします。ChatGPT は、年配の方と会話の内容を記憶し、前回の質問に答えられるようにすることができます。そのため、年配の方と会話をする際にも、ChatGPT を利用すると良いでしょう。

# シチュエーション 2 (GPT3.5TURBO)

> ユースケース：年寄りの会話を記憶するチャットボットの開発

ユーザーがチャットボットに会話をすると、チャットボットはその会話の内容をLSTMで記憶し、ユーザーが次回チャットボットに会話をする場合には、前回の会話内容を参照するようにする。 

例えば、祖母がチャットボットに話しかけ、「あなたは誰ですか？」と尋ねます。CHATGPTは「私はチャットボットです。以前話したように、あなたの名前は○○です。あなたは今年いくつになりましたか？」という応答を返します。

祖母が年齢について話しかけると、チャットボットはデータベースから祖母の生年月日を取得して、本当の年齢を算出します。そして、過去の会話で祖母が何歳だったかを思い出して、その変化を伝えます。「確か、2週間前にお話された時は86歳でしたね。今は87歳になるんですね。」と言うような具体的な応答を返します。

このように、過去の会話内容を記憶することで、チャットボットは年寄の会話が同じループになることを防ぎ、より人間らしい応答を返すことができます。また、データベースから適切な情報を取得することで、チャットボットの応答はより正確であることが期待されます。

# シチュエーション 3 (BING)

> ユースケース: ChatGPTを使って高齢者との会話をサポートするアプリケーション

## 登場人物
- Alice: 高齢者で、孫のBobと電話で話すのが楽しみな人
- Bob: Aliceの孫で、忙しい仕事をしている人
- ChatGPT: BobがAliceにプレゼントしたスマートスピーカーで、ChatGPT 3.5 Turboを使ってAliceと会話することができるアプリケーション

## シナリオ
1. Aliceは毎日Bobから電話がかかってくるのを待っているが、Bobは仕事で忙しくてなかなか時間が取れない。
2. BobはAliceに寂しくないようにと、ChatGPTを使ったスマートスピーカーをプレゼントする。ChatGPTはAliceの声や話し方を学習して、Bobに似た返答をすることができる。
3. Aliceはスマートスピーカーに話しかけると、Bobのように返事をしてくれるので嬉しくなる。ChatGPTはAliceの話題に合わせて会話を続けることができる。
4. Aliceは昔の思い出や趣味などについて話すと、ChatGPTは前の会話を記憶していて、関連する質問やコメントをする。ChatGPTはLSTMのような仕組みで長期的な依存関係を学習しているので、同じ話を繰り返したりしない。
5. AliceはChatGPTにBobのことや自分のことを教えると、ChatGPTはデータベースに情報を保存しておく。ChatGPTは話題に応じてデータベースから適切な情報を取り出して、会話に反映させることができる。
6. AliceはChatGPTと楽しく会話しながら、Bobからの電話を待つ。
PostgreSQLでroleを作成する /PG::ConnectionBad: FATAL: role "postgres" does not exist

## まずはじめに
今回の記事はあくまで自分のメモ用みたいなものです。
そのため、間違っていることや、表現の誤りなども含むと思いますので、鵜呑みにはしないでください。
また、心の優しい方がいれば、そっと間違いを指摘していただけると学びの励みになるので、すごく嬉しいです。。。
## エラー内容
Rails, PostgreSQLで環境構築をしていると、以下のエラーが発生。
```
ActiveRecord::ConnectionNotEstablished: FATAL: role "postgres" does not exist
Caused by:
PG::ConnectionBad: FATAL: role "postgres" does not exist
```
## 結論
postgresというroleがないので、以下のコマンドで作成
```sql
CREATE ROLE postgres SUPERUSER;
```
(注)SUPERUSERは、最強の権限なので、良くないという記事も拝見したので、おすすめはしません。
## 原因
まずエラー文から、postgresのroleがないよー。と言われている。
roleとは、、？の状態だったので、まずはpostgresのroleについて調べる。
## roleとは
>PostgreSQLのroleとは、ユーザやグループがデータベースへアクセスすることを管理するための仕組み。
最初にPostgreSQLが立ち上がるとpostgresという名前のロールが作成されている。このロールは何でもできるスーパーユーザーだ。

なるほど、、。でも今回は"postgres" does not existなのか。とりあえず、roleがあるか確認してみよう。

## roleの確認
まず、postgresに入る。
```
psql postgres
```
*もしpostgresを起動してなかったら、以下のコマンドで接続。
```
brew services start postgresql
```
以下のコマンドで、roleの確認。(`\`は, `option + ¥`)
```
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 xxx    | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
```
あれ、Role nameにpostgresがない。(エラー文にそう書いてましたよね)
じゃあ作ればいいんだ！　 (単細胞)

## roleの作成

```sql
CREATE ROLE postgres SUPERUSER;　
```
上の結論でも書きましたが、SUPERUSERは、最強の権限になるので、あまりおすすめはしません。

よし、できた！role確認！！
```
postgres=# \du
                                   List of roles
 Role name |                         Attributes                         | Member of
-----------+------------------------------------------------------------+-----------
 xxx    | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 postgres    | Superuser, Create role, Create DB, Cannot Login| {}
```
###  Cannot Login??
結局↑こいつのせいでログインできなかったので、以下のコマンドでログインの権限も持たせて、無事解決しました。
```
ALTER ROLE postgres LOGIN;
 xxx    | Superuser, Create role, Create DB, Replication, Bypass RLS | {}
 postgres    | Superuser, Create role, Create DB | {}
```

## まとめ

roleとは？でもありましたが、
> 最初にPostgreSQLが立ち上がるとpostgresという名前のロールが作成されている。

でも実際私の場合、postgresという名前のロールは作成されていませんでした。
不思議に思い、調べてみたところ、以下の内容を見つけました。

> homebrew経由でインストールした際のmacユーザーのrole名が自動的に作成されている

😇😇😇
【Java】マップにキーとオブジェクトを使う

# はじめに
Javaプログラミング言語では、マップ（Map）を使用してキーと値のペアを関連付けることができます。この記事では、Javaにおけるマップの値にオブジェクトを付与する方法について詳しく解説します。

## マップの作成

Javaでは、HashMap、TreeMap、LinkedHashMapなどのマップ実装クラスを使用してマップを作成します。以下はHashMapの例です

```java:HashMapの宣言
Map<KeyType, ValueType> map = new HashMap<KeyType, ValueType>();
```
### キーと値を埋めるデータ型
KeyTypeとValueTypeは、具体的なデータ型を指す仮の用語です。これらは実際のコードで使用するデータ型に置き換える必要があります。以下のキーワードは一般的なデータ型の例を示します。

- Integer: キーが整数値の場合
- String: キーが文字列の場合
- 自作のクラス: カスタムクラスをキーとして使用する場合
- など

## 値を追加する

マップに値を追加するには、putメソッドを使用します。
putメソッドはキーと値のペアを指定し、マップに関連付けます。
```java
map.put(key, value);
```

マップにオブジェクトを追加するためには実際の値を格納するクラスと、クラスを呼び込むためのクラスそれぞれを作成する必要があります。


```java:StudentManagementSystem.java
import java.util.HashMap;
import java.util.Map;

public class StudentManagementSystem {

    private Map<Integer, Student> students = new HashMap<Integer, Student>();

    public StudentManagementSystem() {
        // オブジェクトの生成とマッピングを行う
        // stucentsというマップに整数値とクラスを追加する
        // クラスはインスタンス化しなければエラーが出るのでnewを付与する
        // Studentクラスは引数が必要なので名前,年齢,科目の順で引数を与える
        this.students.put(1, new Student("John Doe", 20, "Computer Science"));
        this.students.put(2, new Student("Jane Smith", 19, "Mathematics"));
        this.students.put(3, new Student("Mike Johnson", 21, "Physics"));
    }

    public void displayStudentDetails() {
        // マッピングの活用
        this.students.forEach((id, student) -> {
            System.out.println("ID: " + id);
            System.out.println("Name: " + student.getName());
            System.out.println("Age: " + student.getAge());
            System.out.println("Major: " + student.getMajor());
            System.out.println("------------------------");
        });
    }

    public static void main(String[] args) {
        StudentManagementSystem system = new StudentManagementSystem();
        system.displayStudentDetails();
    }
}



```
```java:Student.java
public class Student {
    private String name;
    private int age;
    private String major;

    public Student(String name, int age, String major) {
        this.name = name;
        this.age = age;
        this.major = major;
    }

    // 外部から値を読み込むためのゲッター

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public String getMajor() {
        return major;
    }


    // 外部から値を変更する場合に呼び出すセッター
    public void setName(String name) {
        this.name = name;
    }
    
    public void setAge(int age) {
        this.age = age;
    }
    
    public void setMajor(String major) {
        this.major = major;
    }
}

```
PlatformIO で DAPLink を使って STM32 に書き込もうとしたらエラーが出る

PlatformIO で STM32 開発をしていて、特定の DAP-Link を使用すると、以下のようなエラー表示された。

```
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, dfu, jlink, serial, stlink
CURRENT: upload_protocol = cmsis-dap
Uploading .pio/build/genericSTM32F103C8/firmware.elf
xPack OpenOCD aarch64 Open On-Chip Debugger 0.11.0+dev (2021-10-16-21:18)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

swd
Warn : Using CMSIS-DAPv2 interface 1 with wrong class 10 subclass 0 or protocol 0
Warn : could not claim interface: Resource busy
Error: error reading data: Input/Output Error
...
Error: error reading data: Input/Output Error
Error: CMSIS-DAP command CMD_INFO failed.
Error: No Valid JTAG Interface Configured.
*** [upload] Error 255
```

ある DAP-Link デバイスだと成功したり、PyOCDだとできたにもかかわらずである。

どうも PlatformIO の指している OpenOCD のバージョンが古いようである。以下のように OpenOCD のバージョンに 3.12 を指定すると動作しました。

```ini:platform.ini
[env:genericSTM32F103C8]
platform = ststm32
board = genericSTM32F103C8
framework = stm32cube
platform_packages =
    toolchain-gccarmnoneeabi@~1.100301.220327
    tool-openocd@~3.1200.0
upload_protocol = cmsis-dap
monitor_port = /dev/ttyACM0
monitor_speed = 115200
```

```
Configuring upload protocol...
AVAILABLE: blackmagic, cmsis-dap, dfu, jlink, serial, stlink
CURRENT: upload_protocol = cmsis-dap
Uploading .pio/build/genericSTM32F103C8/firmware.elf
xPack Open On-Chip Debugger 0.12.0-01004-g9ea7f3d64-dirty (2023-01-30-15:08)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

swd
[stm32f1x.cpu] halted due to debug-request, current mode: Thread 
xPSR: 0x01000000 pc: 0x0800211c msp: 0x20005000
** Programming Started **
Warn : Adding extra erase range, 0x08002324 .. 0x080023ff
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
shutdown command invoked
```

PlatformIO の標準で指し示すバージョンがいろいろ古いのは一体何なんでしょう。。。

## 参考

> Unable to download program through cmsis-dap debugger - General Discussion - PlatformIO Community
> https://community.platformio.org/t/unable-to-download-program-through-cmsis-dap-debugger/21826

> platformio/tool-openocd: Open On-Chip Debugger. Free and Open On…
> https://registry.platformio.org/tools/platformio/tool-openocd/versions
【備忘録】とくとくBB光(GMO光アクセス)のNECのルーターでポート開放をしてサーバーを立てる方法

# はじめに
間違っていることやできなくなるかもしれませんが、ご了承ぐださい。
この記事を見てポート開放をする場合は、自己責任でお願いします。
また、ある程度のパソコンの知識とサーバーのデータがあるという前提で説明していきます。

```
環境
インターネット
とくとくBB光(GMO光アクセス)

ルーター
NEC WG2600HS2

OS
Windows 10 Home
```

# 手順1 パソコンのローカルIPを固定する
まず、左下のwindowsのアイコンを右クリックし、
「ネットワーク接続(W)」を押します。
下のような画面が出てくると思うので、「アダプターのオプションを変更する」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/64748739-08ef-6eb1-7d6a-db6e059baf12.png)
今接続しているネットワークの上で右クリックをし、「プロパティ(R)」を押します。
下ような画面になるので、「インターネット プロコトル バージョン４(TCP/IPv4)」を選択し、
「プロパティ(R)」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/d3f2b471-8b04-5263-9c7d-f345f7a1e01b.png)

「次の IP アドレスを使う(S)」のラジオボタンにチェックをし、
「IPアドレス(I)」に一番右の数値をルーター側で許可されているローカルIPにしましょう。
「サブネット マスク(U)」は、255.255.255.0 にしましょう。
「デフォルト ゲートウェイ(D)」は、ルーターにアクセスするためのローカルIPです。(基本的に固定)
NECのWG2600HS2の場合は、「192.168.10.1」でした。
「次の DNS サーバーのアドレスを使う(E)」のラジオボタンにチェックをし、
「優先 DNS サーバー(P)」は、デフォルトゲートウェイと同じ値を入力します。
「代替 DNS サーバー(A)」は、何も入力しません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/8efe217e-e3dd-1eb3-e4ec-cff2d44afdc3.png)
設定ができたら「OK」を押します。
これで、ローカルIPを固定できました。
# 手順2 ルーターのサイトにアクセス
まず、ルーターのサイトにアクセスします。
NECのWG2600HS2の場合は、URLの欄に「192.168.10.1」を入れましょう。
ユーザー名とパスワードを入れましょう。
デフォルトでは
ユーザー名は「admin」、パスワードはルーターに書かれています。
入力できたらログインしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/64bc0d00-820c-d7d2-41ae-285cacc0b97c.png)
ログインすると、このような画面になると思うので、
装置情報から「IPv4接続状態」が利用可能になっていることを確認したら、
「詳細設定」の「ポートマッピング設定」をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/6cddd646-bd82-d897-26fd-d9a620020724.png)
「追加」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3455782/e9a19428-8061-8efc-6a60-b9fe80cae63b.png)
このような画面が出るので、
「優先度」を他の設定とかぶらないような値にします。
「優先度」の値が小さいほど「優先度」が高くなります。
「LAN側ホスト」にPCで設定したローカルIPにします。
「プロトコル」は、「TCP」と「UDP」がありますが、
ゲームサーバーでいうと、
「TCP」は、Minecraft JAVA(Vanilla、plugin、mod server)、terraria serverで使います。
「UDP」は、Minecraft Bedrock(統合版)で使います。
```
TCP
Minecraft JAVA Server
Terraria Server

UDP
Minecraft Bedrock(統合版)
```
「変換対象ポート番号」がいわゆるアクセスに必要なポート番号です。
この値は、決まっていると思うので、自分の環境で
「利用可能ポート」から確認して入れてください。

「宛先ポート番号」は、ローカル内でのポート番号を入れます。
デフォルトのポートでは下のような感じです。
```
Minecraft JAVA Server: 25565
Minecraft　Bedrock Server: 19132
Terraria Server: 7777
```
すべて入力できていたら、「設定」を押して、「前のページへ戻る」を押してください。
追加できていたらルーターでの作業は終わりです。
ポート番号を覚えておいて、ページを閉じてもらって構いません。

# 手順3 サーバーを起動して入る
手順2での設定ができていればサーバーを開けば入ることができます。

:::note info
チェック
手順2で設定したローカルポートが使われるとポートが自動で開きます。
逆に閉じると入れなくなります。
:::
[グローバルIP確認サイト](https://www.cman.jp/network/support/go_access.cgi)でグローバルIPを確認します。
URLかIPをコピーしてサーバーのアドレスに貼り付けます。
そして、ルーターで設定した変換対象ポート番号をポートの欄に貼り付けます。
入ることができれば成功です。

失敗例
・サーバーのローカルポート番号が宛先ポート番号と一致しない
・TCPとUDPのポートが間違っている
・ルーターの設定保存し忘れ
などなど、、、、

# おわりに
ポート開放はできましたでしょうか。
最後まで見てくださりあがりがとうございます。

参考文献
[ポートマッピング手順 WG2600HS2](https://www.aterm.jp/support/guide/category/enjoy/port/008/main.html)
サンプルコードをコピペしたらエラーが出た

インターネットからサンプルコードをコピペしたときに、The parameter `‘key’ can’t have a value of ‘null’`というエラーが発生したので、その対応方法をメモします。
flutterのバージョンが上がり仕様が変更されたので、それまでのコードを持ってくるとエラーが起こるようです。対応方法としては、`?`をつけるといいようです。
``` dart
MyHomePage({Key key}) : super(key: key);  // これまでのコードはエラーになる
MyHomePage({Key? key}) : super(key: key); // ?をつけて対応
```
他にも（？・！・late・required）などの修飾子を入れることで対策できるようです。
flutterは始めたばかりでわからないことだらけですが、頑張ります。
### 参考元
https://computer.sarujincanon.com/2022/01/02/key_safety_flutter/
Google ColabでPythonのバージョンを変更する

## きっかけ
GoogleColabにインストールされているPythonのバージョンでは動かないライブラリを扱いたかったから。

## 変更方法
以下を実行することで任意のバージョンのPython(以下の例ではPython3.7)をGoogleColabにインストールできる。

```bash
!sudo add-apt-repository -y ppa:deadsnakes/ppa
!sudo apt-get -y update
!sudo apt-get -y install python3.7
!sudo apt-get -y install python3.7-dev
!sudo apt-get -y install python3-pip
!sudo apt-get -y install python3.7-distutils

!python3.7 -m pip install --upgrade setuptools
!python3.7 -m pip install --upgrade pip
!python3.7 -m pip install --upgrade distlib

!sudo update-alternatives --install /usr/bin/python python /usr/bin/python3.7 1
!sudo update-alternatives --set python /usr/bin/python3.7
!sudo ln -sf /usr/bin/python /usr/local/bin/python

!python -V
# Python 3.7.17
```

これでわざわざ`python3.7 -m pip ...`としなくても`pip ...`で動作するようにできる。

## 参考
https://qiita.com/checche/items/396309459833e6ea598c

https://qiita.com/KoheiQiita/items/ee27a9c53dc57d90e7b3
AWS-CLIとEC2 Instance Connect Endpointを使ってEC2のWindows Serverにリモートデスクトップをしてみた

# はじめに
EC2 Instance ConnectがPrivate Subnetに対応したEC2 Instance Connect Endpointが出たようなので試してみた
応用すれば、ローカルとRDSをVPNなしで接続可能！！

# 事前準備
  - AWS-CLI aws-cli/2.12.0以上をローカルにインストール
  - VPCの構築
  - EC2の構築とSSHのキーペア or Windowsのパスワードを控える

# 構築

- マネジメントコンソールの場合
  1. VPCのコンソールを開く
  2. 左のペインからエンドポイントを選択
  3. エンドポイントを作成を謳歌
  4. EC2 Instance Connect Endpointを選択し、適当なVPCとサブネット、セキュリティグループを選択

- CloudFormationの場合
  
  ドキュメントはあるのに実際に試したら非対応リソースだった。悲しいね。[ドキュメントリンク](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-ec2-instanceconnectendpoint.html)
  

```yaml
AWSTemplateFormatVersion: '2010-09-09'
Resources:
  EICEndPoint:
    Type: AWS::EC2::InstanceConnectEndpoint
    Properties: 
      SecurityGroupIds: 
        - String
      SubnetId: String
```

# 接続
1. 以下のコマンドを実行する
    ```bash
    aws ec2-instance-connect open-tunnel \
      --instance-connect-endpoint-id エンドポイントID \
      --private-ip-address EC2のプライベートIP \
      --local-port ローカルで使用するポート(今回は13389) \
      --remote-port ターゲットのポート(今回はRDPなので3389を指定)
    ```

2. リモートデスクトップアプリに`127.0.0.1:ローカルで使用するポート`を入力

無事ローカルとVPCをEC2 Instance Connect Endpointを使用して繋ぐことができました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/581025/5b6c39c3-7428-76b1-7229-25a900d2a5f2.png)

※ SSHの場合は下記のコマンドを実行する(手順1はremote-port引数を省略するor22番ポートを指定する以外変化なし)
```bash
ssh -i キーペア(pemファイル)へのパス ec2-user@localhost -p 10022
```

# 課題になりそうなところ
- WebSocketを使っているので、Proxy配下では死ぬ可能性がある
- SSHの場合、キーペアの保管がいる（マネジメントコンソールから接続する場合は不要）
- CloudFormation・CDKによる構築が未対応(カスタムリソースで対応可能 → [リンク](https://dev.classmethod.jp/articles/create-ec2-instance-connect-endpoint-using-cdk-custom-resource/) )
- AWS CloudTrailでの監視になる(別途CloudWatchやS3、Athenaと連携が必要になる)
- 接続先をIAM Policyで制御できず、セキュリティグループによる制御が必要になる(=グループ・人を限定して制御できない)
- VPC1つに付き1つのエンドポイント(=AZ障害に弱い)

# 良いと感じたところ
- VPCエンドポイントが不要なので安い（転送料のみ）
- SSHやRDPだけでなく、VPCのリソースにはすべてアクセスできるのでVPNのように使える（常時接続不可なので、ちょっとした作業に良い）
- 踏み台撲滅できる
- IAM Policyで接続元のIPアドレス制限が可能（＝マネコンアクセスと一括管理が可能）
【SQL】正規表現でパターンマッチング/SQLマスターへの道

## 導入
記事のデータが入っているテーブルがあり、その中からダミー記事のレコードだけを集計するという要件がありました。
ダミーデータには「英単語のみで生成されたもの」という特徴があり、どうにか抽出する方法がないかなと悩んでいました。
そこで今回、正規表現を使ったパターンマッチングの方法を先輩エンジニアにレクチャーしていただいたので備忘録として残させていただきます。
## コード例
```
SELECT *
FROM `node`
WHERE `title` REGEXP '^[a-zA-Z ]+$';
```
## 解説
正規表現での抽出を実現するためにはREGEXPを使います。
上記のコード例では、WHERE句にて、title列の値が、「アルファベットとスペースのみ」で構成されるレコードを抽出しています。
## まとめ
筆者は正規表現はまだ見習いですが、使いこなせれたら抽出において条件を厳しくしたり逆にゆるくしたりとできることの幅が広がりそうですね。
## 備考
`'^[a-zA-Z ]+$'`・・・「アルファベットとスペースのみで構成されるもの」
`node`・・・記事のテーブル
`title`・・・記事のタイトル
MyBatisのSQLをJavaコードに記載して動的SQLのカバレッジも測定しちゃおうよ！！

MyBatis＝XMLのイメージの方も多いと思いますが、「アノテーション」と「任意のJavaクラスのメソッド」にSQLを記載することができます（つまりXML書かなくてもMyBatisを使ってDBアクセスすることができます）。あまり知られていないかもしれないですが、「任意のJavaクラスのメソッド」を使用して動的SQLを記載すると、カバレッジ測定ツールと連動してSQLの生成ロジックに対するテストの充足性を確認することもできちゃいます。

# JavaコードにSQLを記載したMapper

以下は、静的SQLを「アノテーション」に、動的SQLを「メソッド」に記載するしたMapperインタフェースになります。

```java
package com.example.demo;

import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.SelectProvider;
import org.springframework.util.StringUtils;

import java.util.List;
import java.util.Objects;

// language=sql
@Mapper
public interface PersonMapper {

  // アノテーションにSQLを指定する
  @Select("""
      SELECT
        id
        ,name
        ,address
        ,age
        ,memo
      FROM
        person
      WHERE
        id = #{id}
      """)
  Person selectOne(int id);

  // 任意のクラスのメソッドにSQLを指定する
  // language=sql
  class SelectByCriteriaSqlProvider {
    public static StringBuilder provideSql(PersonCriteria criteria) {
      StringBuilder sb = new StringBuilder("""
          SELECT
            id
            ,name
            ,address
            ,age
            ,memo
          FROM
            person
          WHERE 1 = 1
          """);
      if (StringUtils.hasLength(criteria.name)) {
        sb.append("""
            AND name = #{name}
            """);
      }
      if (StringUtils.hasLength(criteria.address)) {
        sb.append("""
            AND address = #{address}
            """);
      }
      if (Objects.nonNull(criteria.age)) {
        sb.append("""
            AND age = #{age}
            """);
      }
      return sb;
    }
  }
  @SelectProvider(SelectByCriteriaSqlProvider.class) // メソッド名をprovideSqlするとmethod属性は省略できる
  List<Person> selectByCriteria(PersonCriteria criteria);

}
```

# カバレッジの確認

ageに条件を指定したテストのみ実行した時のカバレッジはこんな感じになります。nameとaddressを指定したテストが不足していることがわかります！！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/117313/661472f8-21cd-b309-10d8-d12b47c1567b.png)

# 参考：Personクラス

```java
package com.example.demo;

public record Person(int id, String name, String address, Integer age, String memo) {
}
```

# 参考：PersonCriteriaクラス

```java
package com.example.demo;

public class PersonCriteria {
  public String name;
  public String address;
  public Integer age;
}
```

# まとめ

複雑なマッピングを行おうとするとXMLでしかサポートしていないケースはありますが、自動マッピングとアノテーションを使ったマッピングでも多くのパターンをサポートできると思います。データベースへアクセスする処理を分散させたくない場合やSQLの生成ロジックのカバレッジを取得したい場合は、JavaコードにSQLを記載する方法の採用を検討してみると良いと思います。
IT初心者がAWS Cloud Practitioner（CLF-C01）にチャレンジして一発合格した件について

# はじめに
この記事はこれからAWS Cloud Practitionerを受験しようとされている方、受験するため
に情報収集をされている方に向けて、私が勉強を始めて合格するまでの体験を書いたものです。

「最短で合格する」ことに専念したため、AWSのハンズオンなど実践的なスキルは身に付きにくい勉強方法だと思います。

「AWSのサービスについて広く浅く知りたい」「とりあえず簡単な資格からチャレンジしたい」という方にお勧めします！

# AWS Cloud Practitioner（CLF-C01）とは
AWSの資格は（2023/06/18現在）12種類あり、AWS Cloud PractitionerはFOUDATIONALに分類されます。
>AWS クラウドの基礎的な理解を目的とした知識ベースの認定です。
**事前の経験は必要ありません。**

と[AWS認定](https://aws.amazon.com/jp/certification/)のサイトにもありますので、初心者向けの資格であることがわかります。


↓Cloud Practitionerの立ち位置（AWS認定からの引用）
### FOUNDATIONAL
- Cloud Practitioner　←　現在地

### ASSOCIATE
- Solutions Architect（Associate）
- SysOps Administrator
- Developer

### プロフェッショナル
- Solutions Architect（Professional）
- DevOps Engineer

### 専門知識
- Security
- Database
- Machine Learning
- Advanced Networking
- Data Analytics
- SAP on AWS

**1000満点中700点**獲得できれば合格となります。
参考サイト：[AWS 認定受験者に役立つ情報と関連ポリシー](https://aws.amazon.com/jp/certification/policies/after-testing/)

# 筆者のITスキルについて

私がCloud Practitionerにチャレンジしたのは入社3か月たったくらいの頃でした。
会社の新卒研修で軽くITには触れるものの、「クラウドってサーバーレスで動くあれだよね」くらいの知識しかインプットされていなかったので、クラウドについて何も知らない状態で勉強をスタートしました。


- クラウドに触った経験0
- IT系の資格はITパスポートのみ（取得してから時間が経っていたので半分忘れ）

# 勉強方法
合計で15時間ほど勉強しました。
平日の気が向いた日や土日の空いた時間でコツコツ勉強するようにしていたと思います。

 
### 使用教材（学習した順番で書いてあります。）
- [AWS Skill Builder](https://explore.skillbuilder.aws/learn/signin)
   ⇒無料で使えるサービスなのでとてもお勧めです。
　　 受講したコースは「Exam Prep: AWS Certified Cloud Practitioner (CLF-C01) (Japanese) (Sub) 日本語字幕版」です。
　　 各テスト、総合テストの答えを覚えるレベルまでやりました。

- [AWS認定資格 無料WEB問題集＆徹底解説　【AWS資格】無料WEB問題集＆徹底解説 | クラウドプラクティショナー(CLF) ](https://aws-exam.net/clf/clf_question.php)
⇒こちらも無料の問題集です!金欠の新卒には無料はありがたいですね。
  これも9割くらい解けるようになるまでやりました。

- Udemy①　【2022年版】この問題だけで合格可能！AWS 認定クラウドプラクティショナー 模擬試験問題集（7回分455問）
　⇒[Udemy](https://www.udemy.com/ja/)は有料の学習コンテンツですが、解説や過去問が充実しています。タイムセールで安くなっているときなどあるので、そこを狙って申し込んでみてください。
　   基本が95％、応用が60％くらいの正答率になるまでやりました。
- Udemy②　【2022年版】これだけでOK! AWS認定クラウドプラクティショナー試験突破講座（豊富な試験問題290問付き）
　⇒正答率が70％くらいになるまでやりました。
 


# 受験について

勉強を満足いくまでやったら、[AWS認定](https://aws.amazon.com/jp/certification/)からサインインして受験を申し込みました。

テストセンターで受けるか、オンライン受験をするか選べるのですが、**テストセンターで受験する方が圧倒的にオススメです！！**

理由1.PCや通信環境を心配しなくていい
⇒会社のPCで受験しようとしたのですが、セキュリティの観点からオンライン受験用のソフトウェアが起動できなかったり、通信環境が周辺工事の影響で乱れてうまくテストに接続できないなどトラブルが多発しました。
接続テストの事前準備が不要ですし、当日の環境への不安もないので私はテストセンター受験派です。

理由2.オンライン受験の方が試験拘束時間が長い
オンライン受験の方が移動しなくていいし楽でしょと最初は思っていましたが、オンライン受験の際は受験前にPC周りや部屋のチェックが入ります。
机の上のものを全部どかしたり、部屋を片付ける時間が事前に必要になってきますし、受験する際に受験時間の約40分前くらいにはチェックインし、試験官によるチェックを待たなければなりません。
その点、テストセンター受験は試験時間10分前までに行けばよいだけなので受験直前まで勉強ができます。

# 受験した感想
- **試験について**
本番の試験ではUdemy①の基本レベルの問題が50％、応用レベルの問題が50％（しかもUdemyよりも選択肢が簡単）くらいでした。
パッと見難しそうですが、明らかに違う選択肢があるので、ちゃんと勉強すれば最終的に2択になります。その2択を正解できれば確実に点数が取れます。
肌感覚として本番は85%くらい正解していると思います。
暗記要素が強めなので、コツコツ勉強するのがおすすめです。

- **受験して良かったこと**
一見難しそうなクラウドないしAWSですが、Cloud Practitionerを受験することで、クラウドについての全体的な理解ができたり、AWSにどのようなサービスがあるのか広く浅く知ることができました。また、日頃流れてくるITのニュースも、今までは全然わからなくて読み飛ばしていたところがなんとなくわかるようになったので勉強して良かったなと思います。
 
# 最後に
ここまで読んでくださってありがとうございます！
私が勉強を始めた時、クラウドに詳しい人も周りにおらず一緒に勉強する人もいなかったので「結局なにを勉強したら受かるのか」が分からなくて困りました。
同じように困っている方に少しでも役に立つ情報が発信できてたら嬉しいです！
次回はSolutions Architect（Associate）に合格した際の体験談を記載しようと思います。
Nuxt 3でSwiperを使用する

# 経緯
Nuxt.jsでスライダーを使用する方法を検索すると、[vue-awesome-swiper](https://github.com/surmon-china/vue-awesome-swiper)の使用手順が多く紹介されています。しかし、[vue-awesome-swiper](https://github.com/surmon-china/vue-awesome-swiper)のプロジェクトを参照すると、使用が非推奨(deprecated)となっており、TypeScriptフレンドリーな公式の[Swiper Vue.js Components](https://swiperjs.com/vue)への移行が推奨されていました。
ただし、公式ページには[Swiper Vue.js Components](https://swiperjs.com/vue)も将来的には削除される可能性との記載があり、最終的には[Swiper Element](https://swiperjs.com/element)の使用を推奨と促されます。
本記事では、この[Swiper Element](https://swiperjs.com/element)をNuxt3で使用する手順を簡単にまとめています。


# 手順
## npmからインストール
```bash
npm install swiper
```

## 使用するコンポーネントでregisterをインポートして実行
```vuejs
<script setup>
import { register } from 'swiper/element/bundle';
register();

</script>

<template>
    <swiper-container>
      <swiper-slide>Slide 1</swiper-slide>
      <swiper-slide>Slide 2</swiper-slide>
      <swiper-slide>Slide 3</swiper-slide>
    </swiper-container>
</template>
```
この時点でスライダーが動作していますが、コンソールに下記の警告が出ていました。

```console
[Vue warn]: Failed to resolve component: swiper-slide
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement.
[Vue warn]: Failed to resolve component: swiper-container
If this is a native custom element, make sure to exclude it from component resolution via compilerOptions.isCustomElement. 
```

これを解消するため、nuxt.config.tsに下記を設定します。
```javascript
export default defineNuxtConfig({
  ...,
  vue: {
    compilerOptions: {
      isCustomElement: (tag) => /^(swiper|swiper-slide|swiper-container)$/.test(tag),
    },
  },
})
```
https://github.com/nolimits4web/swiper/issues/6524

# まとめ
nuxt3の環境でも簡単にスライダーを導入する事が出来ました。
Blockade LabsでAIが生成した背景をUE5で読み込む方法

# 目次
<!-- タイトルとアンカー名を編集 -->
1. [はじめに](#はじめに)
1. [手順](#手順)
1. [おわりに](#おわりに)

# はじめに

Blockade Labsを使用することで、AIが生成した背景をUE5で読み込むことができます。

「Blockade Labs」へのURLです。

https://www.blockadelabs.com/

「Blockade Labs」についての解説は、ひろはすさんの動画が分かりやすいので、こちらをご視聴ください。

https://youtu.be/OSnJH22UFTE

動画内ではUnityで背景を読み込む方法を説明していますが、本記事ではUE5にて背景を読み込む方法を解説します。

動作確認環境は、Windows・UE5.1です。

# 手順

「Blockade Labs」にて背景の画像を作成し、ダウンロードします。

「Blockade Labs」からダウンロードした画像の拡張子を「.jpg」から「.hdr」に変更し、UE5のコンテンツブラウザ内へ読み込みます。

「.jpg」のままだとTextureとして読み込まれますが、「.hdr」に変更することで、Texture Cubeとして読み込まれるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/a1c562e1-9302-3a31-c59a-fc45b65da117.png)


Edit→Pluginsを開き、Rendering→HDRIBackdropのプラグインにチェックを入れ、UE5を再起動します。

Place Actorsウィンドウから「HDRIBackdrop」をドラッグアンドドロップし、Level上に追加します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/3f5b3e75-4c14-3c12-d82e-07413d3bd818.png)

そのままの状態だと、背景が変形して表示されてしまうので、HDRIBackdropのDetailsウィンドウ内で、SizeやProjection CenterのX,Y,Zの項目を調整します。
(その他の見た目の調整方法など分かっていないので、詳しい方はコメントなどで教えていただけると助かります。m(_ _)m)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/5211eaa0-d1ca-a399-9057-76ff54612b1c.png)

プレイヤーの大きさに対して、建物が超巨大な感じになっている気がしますが、とりあえず背景を設定できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/572997/da14bb52-6147-68ae-0480-3e6b552b6cb9.png)

# おわりに

AIが生成した画像を使用することで、自分の目的に沿った背景を簡単に作成できるため、とても便利で実用性が高いと思いました。

記事を作成するにあたって、参考にした資料を載せておきます。

https://docs.unrealengine.com/5.1/ja/hdri-backdrop-visualization-tool-in-unreal-engine/

https://youtu.be/kW8x6dOTjaI

https://ideajotter.com/blog/unreal-engine-5-hdri-backdrop/
キャッシュとは

## キャッシュとは
キャッシュとは、Webサーバから取得したリソース（断片的なデータ、ファイル、機能など）のこと。また、リソースを保存してある場所。また、リソースを保存するための技術。

ブラウザがリクエストしたとき、リクエスト内容のキャッシュが保存されていると、Webサーバからではなく、近くにあるキャッシュからリソースを取得する。そのため、通信速度を高速化できる。

一方、キャッシュが残り続けると、リソースの更新が反映されず、ユーザに適切なリソースを返せないことがある。
そのため、キャッシュを長時間保存することは推奨されない。

## Cache-Controlヘッダフィールド
Cache-Controlヘッダフィールドは、キャッシュの制御を行う。例えば、**no-style**を設定すると、ブラウザやWebサーバでキャッシュが保存されなくなる。
また、**max-age**を指定すると、キャッシュの有効期限を秒単位で指定できる。

## Expiresヘッダフィールド
Expiresヘッダフィールドは、レスポンスの有効期限を指定する。
Cache-Controlヘッダフィールドと異なり、有効期限は日付形式で指定する。
ただし、Cache-Controlヘッダフィールドでmax-ageの指定がされている場合、Expiresヘッダフィールドは無視される。

## Ageヘッダフィールド
Ageヘッダフィールドは、プロキシサーバ（中継サーバ）にキャッシュする期限を指定する。キャッシュ期限は秒数で指定する。