OmniAICreator/Qiita-1.07M huggingface dataset:
【Docker】入門：pythonが実行出来るubuntuのイメージをDockerfileから作る

# はじめに
UdemyでDockerの学習を進めている最中で、途中経過をアウトプットしたいと考えています。
今回は、

「pythonが実行出来るubuntuのイメージをDockerfileから作る」
ことをやっていきたいと思います。

# 環境
Windows10
Docker version 24.0.6

# Dockerfileの構成
### 1.From
- Dockerfileの一番最初に書く
- ベースとなるイメージ
- osを指定する事が多い。（ubuntu、alpineなど）
```Dockerfile
FROM ubuntu:latest
```

### 2.RUN
- 主に必要なPKGをインストールする
- 複数の処理は&&でつなげる
 （RUNを複数行作ると、作った分だけイメージレイヤーが出来てしまって最終的にイメージが大きくなってしまうため）
- apt-get updateを最初に実行することが多い
- 改行「\」を使って見やすくする
```Dockerfile
RUN apt-get update && \
	apt-get install sudo && \
	# pythonをインストールする（インストールプロセス中の確認プロンプトを自動的に "Yes" 
	sudo apt install -y python3
```
### 3.CMD
- コンテナのデフォルトのコマンドを指定
- ubuntuだとだいたい["/bin/bash"]
- ["実行するコマンド", "param1", "param2"]
```Dockerfile
CMD ["/bin/bash"]
```

前回の記事と同じことをやろうとすると、
https://qiita.com/hirotakasengoku999/items/35545b8a9f909f55b626

以下のようなDockerfileになります。
```Dockerfile:Dockerfile
FROM ubuntu:latest
RUN apt-get update && \
	apt-get install sudo && \
	# pythonをインストールする（インストールプロセス中の確認プロンプトを自動的に "Yes" 
	sudo apt install -y python3

# 作業ディレクトリを設定
WORKDIR /work

RUN touch test.py && echo 'print("aaa")' > test.py

CMD ["/bin/bash"]
```

# 備考
前回はubuntuのコンテナを起動してから、
コンテナの情報を更新してコミットしてイメージを作成していましたが、
それだとイメージの中身がどうなっているかわかりずらいため、
Dockerfileを作成してそこからイメージを作成するのが一般的なようです。
[1行意味] switchMap、concatMap、mergeMapについて

<h1>SwitchMap</h1>

    最新のストリーム(observable)の結果だけを扱いたい ケースに有用

<h1> concatMap </h1>

    ストリーム(observable)を順番に実行されるべきケースで有用

<h1> mergeMap </h1>

    複数のストリーム(observable)を並行処理させたいケースで有用
WindowsからUbuntu22.04へのリモートデスクトップ：セカンドモニターが原因で接続できない問題の解決

## はじめに
Ubuntu22.04(デスクトップ版)にリモートデスクトップ接続を試みた。しかし、セカンドモニターを接続したWindowsPCからだと、リモートデスクトップの接続に失敗する問題が発生した。なお、セカンドモニターを使用しない場合は正常に接続できた。

## 解決策
GSettingsの値を変更して、リモートデスクトップ接続したWindowsPCがサブモニターとして認識されるようにした。具体的には、org.gnome.desktop.remote-desktop.rdpのscreen-share-modeを変更した。

### 前提条件
screen-share-modeの設定値が反映されるのは、Wayland環境だけだそう。Xorg環境では正常に機能しない。(参考: https://blog.be-dama.com/2022/11/30/ubuntu-22-04_sub-display/)


##### Wayland環境かどうかの確認方法：
```bash
echo $XDG_SESSION_TYPE
```
上記コマンドを実行し、"wayland"が表示されることを確認。
waylandでなければ、ログイン画面に戻って、右下の歯車から"Ubuntu"を選択して、ログインする。


### 設定値の確認
まず、現在の設定値を確認する。
<pre>gsettings get org.gnome.desktop.remote-desktop.rdp screen-share-mode</pre>
上記のコマンドを実行すると、"mirror-primary"という設定が表示された。

### 設定値の変更
次に、以下のコマンドで設定値を変更する。
<pre>gsettings set org.gnome.desktop.remote-desktop.rdp screen-share-mode extend</pre>
これにより、"extend"モードが選択され、サブモニターを有効にする。


## 無事に解決
![rdp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1223968/696f148f-39f1-0399-7b00-27820272c630.png)
【MySQL】リアルタイムモニタリングツール「dolphie」について

## はじめに
MySQL 5.7のサポート終了が迫っている現在、MySQL8化やDB構成の変更対応に追われている方が多くいらっしゃるかと思いますが、下記Oracle Blogsで紹介されていたMySQLの新しいモニタリングツール「dolphie」が個人的に良かったためご紹介させていただきます。

Oracle Blogs - Welcome to dolphie!
https://blogs.oracle.com/mysql/post/welcome-to-dolphie

## 実行環境
 * OS：WSL2 Ubuntu 22.04
 * python：3.10.12
 * MySQL：8.0.33

dolphieインストール(※注…pythonバージョン≧3系）
```shell
# pip install dolphie
```
## dolphieの実行
WSL2上にてMySQLがインストールされており、localhostへ接続できる事を前提としています。

```shell
# dolphie -u root --ask-pass

※24/10/05 追記
dolphie最新バージョン6.1.0では、--ask-passオプションが廃止されたため、
-mオプションでの接続設定ファイル指定（※または、-pで指定等）で接続が可能です。

# vi ~/.my.cnf
# dolphie -u root -m ~/.my.cnf

または、

# read YOURMYSQLPASS
*******************
# dolphie -u root -p${YOURMYSQLPASS}
```

MySQLの接続に成功するとInnoDBに関連する各種ステータスが表示されます。
![d01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/cec06af6-6289-8d6c-2dfe-317095b89221.png)
## グローバル変数の検索
ダッシュボード画面上で「v」を押下し、確認したい変数の一部を入力します。
※「character_set」に関するグローバル変数を確認したい場合
![d02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/4c0ad446-edad-8d9e-f537-1f9859b5a296.png)
以下のように現在の設定値を確認する事ができます。
![d03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/113370/c608d64d-339a-d00b-3146-a2996fd93e49.png)
## dolphieのその他機能について
本環境ではMySQLが単独で稼働しているため、グローバル変数の検索機能のみご紹介させていただきましたが以下のような機能があります。

ダッシュボード画面より「?」押下にて、各機能の短縮キーを確認可能です。

 * レプリケーションのステータス確認
 * プロセスリストの絞り込み（※ユーザ、ホスト、DB等）検索
 * 特定スレッドの強制終了
 * DDL・MDLの確認
 * トランザクション履歴の確認
 * エラーログの確認
 * その他

## おわりに
dolphieは日々開発が進行中で多くの便利な機能が追加されておりますので、現在MySQLのモニタリングツールを使用されていない方、代替のモニタリングツールを検討中の方のご参考になれば幸いです。
gprof2dot

gprof： ./test gmon.outで出力される複雑怪奇なログを概覧するときに便利

オプションを付けてコンパイル
<pre>
# g++ -g -pg -o test test.cpp
</pre>

<pre>
# pip install gprof2dot
# gprof2dot ./test | gprof2dot.py | dot -Tpng -o output.png
# eog output.png 
</pre>

![gprof2dot2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/7d78673c-a8aa-cadf-bff7-041bb66a3232.png)

C++の場合、クラス派生情報などで、ノードの四角形が長くなるので、それをカットする
<pre>
# gprof ./test | ./gprof2dot.py -s | dot -Tpng -o output.png
# eog output.png 
</pre>

![gprof2dot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/163445/b362d215-871f-41ea-286a-7577e0327b3f.png)
【ChatGPT無】に指定する文章の量に関して、聞きました。


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

　今回は、ChatGPTに指定する文章の量に関して、ChatGPTに聞きました。みなさんは、文字数で指定しているのでは？

:::note info
本記事は、ChatGPT（無料版）で
行なっております。GPT4での確認
はできておりません。あしからず。
:::

　では、本題に入ります。

　ふつうは、ChatGPTさんに
　　文章を出力してもらう際に、
　　「何文字で出力してください」
　　　等の指示をするかと思います。

　でも、ChatGPTさんの出力は、
　　それよりも
　　　多かったり少なかったり
　　　　バラバラ。

　それで、私は、
　　「一文」「短文」「長文」など
　　　単語での指示をしています。
***
　その言葉について、
　　ChatGPTさんに
　　　聞いてみました。
***
***User***
文章の長さを指定するのに、文字数の指定が使われていますが、「一文、長文、短文」などがありますが、どちらを指定するのが、いいですか？

***ChatGPT***
文章の長さを指定する際に、「一文」「短文」「長文」などの表現を使うことは一般的です。これらの表現は、コミュニケーションの文脈に合わせて使うことができます。たとえば、要約を依頼する際に「短文で要約してください」と指定することができます。どの表現を使うかは、コミュニケーション相手との理解を助けるために役立ちますので、適切な表現を選んでください。
***
　うん、わかった。
***
***User***
では、原稿用紙一枚で、と指定したら、どの程度の文字数になりますか？

***ChatGPT***
原稿用紙一枚の文字数は、いくつかの要因に依存します。通常、日本の原稿用紙（B5サイズ）では、1ページに約400文字から600文字程度が収まります。ただし、文字の大きさ、行間、余白などのフォーマットによっても変化します。したがって、具体的な文字数を指定する場合、フォーマットに関する詳細を共有するとより正確な文字数を得られるでしょう。
***
　20×20文字の原稿用紙しか
　　知らないんだけど？

　まぁ、それは置いといて。
***
***User***
では、逆に「400文字で」と指定された方が、「原稿用紙くらいで」と指定されるよりも、いいのですか？

***ChatGPT***
「400文字で」と具体的な文字数が指定される方が、コミュニケーションの明確さや効率性を向上させることができます。一方、「原稿用紙くらいで」という指定は、相対的であるため、解釈が余地があります。具体的な文字数を指定することで、相手が求める内容や形式に合わせてより適切な情報を提供することができます。したがって、具体的な要求がある場合は、それに従うことがお互いにとって明確で効果的です。

***User***
ならば、「400字詰めの原稿用紙」と指定されたら？

***ChatGPT***
「400字詰めの原稿用紙」と指定されれば、非常に具体的なフォーマットが指定されたことになります。この指示に従うと、一つの原稿用紙に400文字が収まるような形式で文を書く必要があります。このように具体的な指示があれば、文字数やレイアウトに関する誤解を避けることができ、コミュニケーションがスムーズに進行します。指示に従って文章を作成することが重要です。
***
　ふむ、
　　今後は、これを使おう！

　ほかにもあるかな？
***
***User***
こうした単語を並べてください。
ほかに表現があるならば、それも加えてください。
なお、並べる際に、対応する出力文字数も表示してください。
例として、
・「200文字」ならば、200文字
・「1行」ならば、20文字
この文字数の少ない順に並べてください。
（このあと、順番を間違うので）
（途中を省略しますね）

***ChatGPT***
申し訳ありません、先ほどの回答で文字数と言葉が正しく対応していませんでした。以下に正しい対応を示します：

20文字　1行
50文字　一文
50文字　短文
100文字　要約
200文字　簡潔に
200文字　回答
200文字　200字
400文字　段落
500文字　500文字
600文字　1ページで
800文字　詳細な情報
800文字　主要なポイント
800文字　詳細に
1200文字　3行で
1200文字　3段落以内で
1500文字　長文

これで文字数と言葉が正確に対応しています。お手数をおかけしました。
***
　これらの言葉を使うと、
　　文字数よりも、
　　　人間には
　　　　わかりやすいですよね。

　今回は、ここまで。
自動運転シミュレーション その4

# 概要
自動運転シミュレーションを開発している。
server,client方式に変更する。
構想編。

# 理由

agentの開発をelixirで、やりたいから。

# 方針
- プラットホームは、plunker。
- 言語は、javascript。
- 通信は、websocket。
- agentがserver。
- やり取りは、json


server->client

```
{
    "observation": {
        "s0": "0.78", 
        "s1": "0.56", 
        "s2": "0.12", 
        "s3": "0.09", 
        "s4": "0.08"
    },
    "reward": "1.0",
    "done": "false"
}
```
client->server

```
{
"action": 2
}
```
- ポート番号は、50002

以上。
JavaScript基礎学習②文法


学習した事を備忘録として書いていきます。

- 参考書籍：確かな力が身につくJavaScript「超」入門


- 基本文法について
何かを実行させたい時は「〇〇は△△を××しなさい」と命令する。
```
console.log('あいうえお');
```

上記の例でいうと、
「console」→〇〇は（オブジェクト）
「log」→××しなさい（メソッド）
「'あいうえお'」→△△を（パラメータ）



- HTMLに直接JavaScriptを書く方法
```
<script>
ここにJavaScriptを書く
</script>
```


- HTMLファイルにJavaScriptファイルを読み込む方法
※こちらの方が一般的！
```
<script src="HTMLファイルからのパス"></script>
```


- 'use strict'について
```
'use strict';
```

ブラウザにはJavaScriptを「古いもので実行するモード」「新しいもので実行するモード」がある。
新しいもので実行するモードをストリクトモードといい、ストリクトモードを実行するために上記の記載が必要。


- コメント文
```
// 単一行でコメントする場合

/*
複数行にまたがるコメントをする場合
*/
```


- ダイアログボックスの表示
```
window.alert('出力したいテキストや数値、計算式など')
```


- 特定のid名を持つ要素を取得する
```
document.getElementById('id名')
```

- 取得した要素のコンテンツを書き換える
```
document.getElementById('id名').textContent = 書き換えたい文字列;
```
Ubuntu22.04(WSL2)環境にMySQLをインストール

# 前提
WSL2環境にUbuntu22.04 がインストール済みであるものとする。
参考：[UBuntu 22.04 をWSL2 環境で動かすメモ](https://qiita.com/KNDPG/items/b42af69f6cd8903785f3)

# MySQLのインストール
MySQLのどのバージョンをインストールすればいいのかを下記サイトにて調べる。
[Supported Platforms: MySQL Database ](https://www.mysql.com/support/supportedplatforms/database.html)
![MySQL_version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222234/95003e30-2408-5ada-adbd-b4e840ab6190.png)
次はバージョン8.0に対応するパッケージ名を調べる。
~~~bash
$ sudo apt-cache search mysql # "mysql" が含まれるパッケージ一覧を表示
# 検索結果が多いのでコマンド出力結果をgrepする
# 正規表現＝^mysql-* として、文頭が"mysql-" のものに絞る
sudo apt-cache search mysql | grep -e ^mysql-*
~~~
検索結果は下記の通り。
![インストールパッケージ一覧検索（mysql）.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222234/d0d48ce0-8c9d-eb78-0748-c48c7e98a9c8.png)
今回は `mysql-server-8.0` をインストールする。

~~~bash
$ sudo apt update # パッケージ一覧の更新
$ sudo apt install mysql-server-8.0 -f
~~~
インストールできたことを確認する。
~~~bash
$ mysql --version
~~~

# 参考
apt-cache コマンド：[apt-getでインストール可能なパッケージを探すには](https://atmarkit.itmedia.co.jp/flinux/rensai/linuxtips/636searchaptpk.html) 
[grepコマンドの詳細まとめました【Linuxコマンド集】](https://eng-entrance.com/linux-command-grep)
[MySQL 8.0 を Ubuntu 22.04 にインストールする](https://qiita.com/fsdg-adachi_h/items/613291e1d3c88d3ef12e)
000webhostのサブドメインを確認

<p class="codepen" data-height="720" data-default-tab="result" data-slug-hash="rNorGpv" data-user="04" style="height: 720px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/04/pen/rNorGpv">
  Check 000webhost subdomain</a> by John Doe (<a href="https://codepen.io/04">@04</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

ソースコード

```typescript

Deno.serve(async (req: Request) => {
    const r = await fetch(`https://${new URL(req.url).pathname.slice(1)}.000webhostapp.com/`)
    return new Response(r.status === 404, {headers: {'Access-Control-Allow-Origin': '*'}})
});

```
cakephp2のエラー制御

cakephp2のエラー制御を調べました。 https://github.com/cakephp/cakephp/blob/2.10.24/lib/Cake/Error/ErrorHandler.php 最終的にExceptionで管理されています。https://github.com/cakephp/cakephp/blob/2.10.24/lib/Cake/Error/ExceptionRenderer.php phpのエラーはErrorHandlerで5種類のlevelに振り分けます。処理が止まるエラーはFatal/InternalExceptionに変換されます。cakephp2内で挙げられるエラーは、はじめから適切なExceptionとして発行されます。 https://github.com/cakephp/cakephp/blob/2.10.24/lib/Cake/Error/exceptions.php ExceptionRendererで各Exceptionに応じた表現として出力されます。カスタマイズについては https://book.cakephp.org/2/ja/development/errors.html https://book.cakephp.org/2/ja/development/exceptions.html
Docker Composeの設定項目

- Docker Composeについては[こちら](https://qiita.com/xQIEBo4zFWKZ0ig/items/e91539adb283b2e8eefd)

## networks

- DockerのネットワークをDocker Composeから定義する機能
    - デフォルトだと1アプリケーション1ネットワーク作成される
- トップレベルに指定した場合
    - アプリケーションレベルの所属ネットワークを選択できる
- サービスレベルに指定した場合
    - サービスが所属するネットワークを選択できる
- Compose管理外のネットワークを使用する場合、`external: true`を指定する

### networksの例

```
# トップレベルでの指定
    networks:
        outside:
        external: true
# サービスレベルでの指定
    services:
        proxy:
        build: ./proxy
        networks:
            - outside
            - default
```

### extra_hosts

- IPアドレスにホスト名を割り当てられる
    - 人が読みやすいテキストで扱える

### volumes

- コンテナのリソースとホストのリソースを同期・永続化できる
- ボリュームの書き方
    - ホスト側の相対パス：コンテナ側の絶対パス

## 参考文献

- [Compose の ネットワーク機能(networking) — Docker-docs-ja 24.0 ドキュメント](https://docs.docker.jp/compose/networking.html)
- [Compose ファイル version 3 リファレンス — Docker-docs-ja 24.0 ドキュメント](https://docs.docker.jp/compose/compose-file/compose-file-v3.html)
salesforce　日付　数式でハマったこと

どうもフリーランスエンジニアのTABEです。

salesforceの構築要件で
毎月ある一定の日付のレコードを作成して欲しいという要望がありました。

その際の基準となる
日の設定が厄介だったので記録しておきます。

salesforceとして日付の日は数式で`　Day（Today()）`の形で今日が何日かを簡単に出せます。
ただ、上記の`Today（）`の部分が日付型ではなく、数値や文字列の場合は
DATE関数の中で`Day（）`関数を使うと存在しない日付を指定した時にエラーになります。

例えば　指定日（SpecifiedDate__c とAPI名につけたと仮定します。）という項目があり
選択リスト型で1から31を選択できるとします。

その場合指定日がレコード上で３１を選択されていた場合
になった時にフローで自動的に9/31のレコードを作ろうとした時
9/31は存在しない為
数式で今月の指定日を設定する場合、以下の様に数式を作るのですが
`DATE(YEAR(Today() ),MONTH(Today() ),VALUE(TEXT({!$Record.SpecifiedDate__c} )`

この数式だと、9/31は存在しない為、DATE関数がエラーで数式が何も帰ってこない状態になります。

ですので、IF分で場合分けをして31日がある月ない月、また２月の閏年の考慮をIF分で、しなくてはならないことがありました。

実際の数式が以下の数式になります。
（選択リストには、必ず「末日」になるように「末」という選択リスト値もあったので、「末」の分岐も組み込まれています。

また、「末」を選択した場合、対象月の次の月に設定してから日付を-1にするという計算で、末日を割り出しているのですが、1月１日から-1をするとエラーになってしまう仕様の様でする。
なのでその分のIF分も入れてあります。

```
IF(
OR(
AND(OR(MONTH(Today())=4,MONTH(Today())=6,MONTH(Today())=9,MONTH(Today())=11), TEXT({!$Record.SpecifiedDate__c}) = '31')
, AND(MONTH(Today())=2, OR(TEXT({!$Record.SpecifiedDate__c}) = '29', TEXT({!$Record.SpecifiedDate__c}) = '30',TEXT({!$Record.SpecifiedDate__c}) = '31')))
, DATE(YEAR(Today() ),MONTH(Today() ) + 1,1)-1
, IF(AND(TEXT({!$Record.SpecifiedDate__c} ) = "末",MONTH(Today() )=12)
    , DATE(Year(Today() ) + 1, 1, 1) - 1
    , IF (AND(TEXT({!$Record.SpecifiedDate__c} ) != "末", TEXT({!$Record.SpecifiedDate__c} ) != null)
      , DATE(YEAR(Today() ),MONTH(Today() ),VALUE(TEXT({!$Record.SpecifiedDate__c} )))
      , DATE(YEAR(Today() ),MONTH(Today() ) + 1,1)-1
    )
  )
)
```

単純に末かどうか？を判定して対応すればいいと思ったのですが、、、
これだけで結構多めの処理になってしました。

同じ様な要件で困った方がいて、力になれれば幸いです！


salesforceの解説用動画をUdemyで作っています。
興味のある方は見てもらえたら嬉しいです。
よろしくお願いします！

https://www.udemy.com/course/salesforce-basics-j/?referralCode=4200CF5D86BBE3ABF2D4
自動運転シミュレーション その3

# 概要
自動運転シミュレーションを開発している。
プラットホームは、Plunker。
言語は、javascript。

# 仕組み

- 環境とagentの組み合わせ。
環境は、閉じたサーキット。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/b0294492-1db1-1cf9-a429-1de6920d794e.png)


画面の下にある5つのグレーがセンサーです。
ちなみに、aは、回転角、xyzは、座標です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8917e72f-7976-1446-c3c2-f553174fbf69.png)

100ミリ秒毎にagentが呼び出されて、アクションを求められます。
その際、センサーの値だけが送られます。

```
r = agent.get_action(observation, reward, done);
   
observation: [255, 255, 0, 0, 0]
reward: 1.0
done: false
```
その値でagentがアクションを返します。
アクションは、2が真っ直ぐ、0が右、1が左です。

# agentの開発

observationを見て、アクションを返します。
このサンプルには、tesorflow.jsが組み込まれています。


# 成果物

自動運転シミュレーションは、こちら
ハンドルのアクションを追加しました。

https://embed.plnkr.co/plunk/ldL5Unt1KYkkdmeiyIk7

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/17f10b30-8c14-21cf-97b2-a0aab421d613.png)

以上。
【React】ページ到達時にトーストが2回(個)表示されてしまう【react-hot-toast】

### はじめに
この記事では、Reactプロジェクトにおいて仮登録メールのリンクをクリックしたあとのページ到達時に完了トーストを表示したいが、トースト通知が2回表示される問題に遭遇し、その解決策を共有します。
※トーストは`react-hot-toast`を使用しております。

### エラー内容
エラー文はでませんでしたが、現象としてはトースト通知が2回、重複して表示されるというものです。

### 試したこと(現状)
- コンポーネントの再レンダリングの確認
- 他のコード部分での`toast`関数の呼び出し確認
- SSR(Server-Side Rendering)の影響を考慮

### 原因
SSRの環境で、クライアントサイドとサーバーサイドの両方でトースト表示のコードが実行されてしまっていた。

### 解決策
コードをクライアントサイドでのみ実行するように修正することで、この問題を解決しました。具体的には、以下のように`useState`と`useEffect`を組み合わせて、クライアントサイドで実行されていることを確認し、トーストを表示しました。

※SSRのページコンポーネント箇所は特に必要ないと思うので、ここには記載してません。

```jsx
import React, { useEffect, useState } from 'react';
import toast, { Toaster } from 'react-hot-toast';

const Register: React.FC = () => {
  const [isClient, setIsClient] = useState(false);

  useEffect(() => {
    // クライアントサイドでのみ実行
    setIsClient(true);

    if (isClient) {
      toast.success('メール認証を行い仮登録が完了しました！');
    }
  }, [isClient]);  // 依存配列に isClient を含める

  return (
    <>
      <Toaster />
      {/* ...他のコード... */}
    </>
  );
};

export default Register;
```

### 結果
上記の修正により、トースト通知が2回表示される問題は解決し、トーストはクライアントサイドでのみ表示されるようになりました。

### 終わりに
この問題の解決を通じて、SSRの環境でのクライアントサイドとサーバーサイドのコード実行の違い、そしてReactの`useState`と`useEffect`を組み合わせた解決法を習得しました。
ふむ、なるほど！でした。

### 参考
- [React公式ドキュメント](https://reactjs.org/)
- [react-hot-toast公式ドキュメント](https://react-hot-toast.com/)
ローコード開発プラットフォームを使って感じたこと

# はじめに
インターネットを見ているとノーコード・ローコード開発というのが注目されているように思われます。
そんな中で、有償のローコード開発ツールを使ったハッカソン(個人開発)のようなものがあり、ローコード開発をする機会がありました。その開発の中で感じたことを書いていこうと思います。

:::note warn
- 初めてローコード開発をしたため他製品との比較はできていません。
- 今回使用したものが企業・官公庁向けだったためOSSと比べて使用ときの感想が異なる可能性があります。
:::

# システムの特徴
先に今回使用したローコード開発ツールの特徴を挙げておきます

- Webサイト・業務アプリの作成をブラウザからできる
  - テストと本番環境が用意され安全に検証が可能
  - サービスの公開が迅速かつ簡単に行える
- データの収集から活用までが簡単
- 高いセキュリティが確保されている
  - 第三者による脆弱性診断で最高評価「A」を取得している
  - 法人や官公庁にも採用されている
- 柔軟な開発
  - HTML、CSS、JavaScript、PHPによるコーディングも可能
  - APIを使った外部システムとの連携も可能
- システムを作る際にデータベースの構造から作る
- システムの構築・運用をこのローコードツールを提供する企業に対してアウトソースもできる

# 利点・不便な点
システムの特徴にあるようにWebサービスを簡単かつ早くに作ることができた点は非常に大きな利点だと思います。
例えば開発事例として普通の開発だと2~3ヶ月くらいの所をこのツールで1週間以内に作成したという話があるようなので開発速度はとても早くできることが分かると思います。
実際に試してみましたがとても早く開発を進めることができました。

しかし、不便な点を挙げるならインターネット上にある情報量が少ないことだと思います。
元々**個人向け製品で無い**ため情報共有がされないというのは当たり前ですが、操作方法や、やりたい機能を実現させるためのやり方を調べようにも公式が出しているナレッジサイトしか情報がなかったのでこの点については大変でした。
また、ローコード開発ではあったものの**エンジニアに求められるような知識は必要**であったので開発を進められる人が限られるのではないかと思いました。
データベースから作る仕様であるためデータ構造(テーブル構成)の知識だったり、デザインを工夫したいなら普通にWeb開発するときのようなコーディングをするのが必須な点が理由です。
(ノーコードではなくローコードツールなのでエンジニアの知識が必要なのは当たり前なのかもしれません)

# 結論
以上のことからローコード開発をする前にツールを選ぶ段階で考えるべきことは以下の事柄なのではないかと考えます。

- ローコード開発ツールを使う意味は何かを考える
  - ツール固有の知識が必要となるためツールの学習コストがかかる
  - ナレッジの蓄積はツール固有となるため広く利用はできない
- 製品と開発するシステムとの相性問題を考える
- 情報量のチェック
  - 場合によってはアウトソーシングを検討する

ローコード開発ツールを使う意味については、どんなにローコード開発ツールが便利になってもそれを支える技術はコーディングなどの従来の知識です。**ちゃんとしたメリットや理由がないのであれば地道にコーディングをしてエンジニアの知識を高めた方がいいと思います。**
それと、製品と開発するシステムとの相性というのも考える必要があるかと思います。頭の中ではできていても製品によっては実現できない、又は開発コストが高くなるので検討が必要です。(私も一部機能の実装が出来なかったので…)

必要性を検討し、使用していくなら情報量のチェックは重要です。
OSS系なら多分情報量は多いと思いますがサポート等はないので会社で使用するならその辺りも検討するべきです。またサポートのある有償のものを使うという場合は情報量は少ないと思われます(実際そうでした)。場合によってはアウトソーシングができるようなところにして任せるのも一つの手段だと思います。


# さいごに
今回のイベントに参加することで、ローコード開発ツールを使用することのメリットと課題が体験できたのはよい経験になりました。
ローコード開発ツールは開発元がサービスを終了すれば移行が必要になる。ツールの知識を再利用するのは限定的など利点だけではないです。会社やエンジニアとして必要なものであるか良く考えてから利用しましょう。
それでもエンジニアの人も一度使ってみてから、どんな仕事が代用出来て、出来ないのかを考えてみると必要となる知識や経験が再認識できていいかもしれません。

誤り・意見・その他何かあればコメントお願いします。
最後まで見ていただきありがとうございました。
【Laravel】ひとまずこの記事でweb.php内の「Route::???」をある程度把握しよう

# はじめに
最近ようやくちゃんとLaravelの学習を始めました。
ルーティング周りがうる覚えなせいで画面表示部分からひたすらつまづいているので
備忘録として「Route::???」の内容をこちらの記事にまとめようと考えました。
ルーティング周りで苦労している方の役に立てれば嬉しいです！

間違いやこういうものもあるよ！というご意見お待ちしております！
どしどし指摘してください！

## 基本的なルーティング 
```php:web.php
Route::get('/', [MainController::class, 'index']);
```
まずは基本的な書き方から。これがあれば最低限の遷移はできるよという書き方です。

ブラウザで「localhost:8080/」にアクセスした場合は、MainControllerのindexメソッドを呼び出します。
そのまま画面表示をしたり、DBからデータを取得して画面に表示させたりなど。

### getメソッドの第一引数
「/」を指定することで、**第二引数で指定したメソッドを呼び出す**ことができる
```php
'/'
```

### getメソッドの第二引数
MainControllerクラスのindexメソッドを呼び出す
```php
[MainController::class, 'index']
```

## nameメソッド
``` php:web.php
Route::get('/tests', [TestController::class, 'index'])->name('test');
```
上記の場合、TestControllerのindexメソッドに対して名前を付けることができるのが、nameメソッドです。


### リダイレクト
名前付きルートは、リダイレクト時にも非常に便利です。
redirect()ヘルパー関数を使用して名前付きルートにリダイレクト(遷移)できます。
```php:
// ページ遷移のため主にアクションの実行後、ユーザーを他のページに転送したりする
return redirect()->route('test');
```

## 「->name('xxx')」で指定した名前付きルートの主な使い方

### ビュー内のリンク生成
Bladeテンプレート内で名前付きルートを使用して、HTMLリンクを生成できます。
```php
<a href="{{ route('test') }}">テスト</a>
```

### コントローラー内からのリダイレクト
コントローラー内で名前付きルートを使用して、リダイレクトを実行できます。
```php
return redirect()->route('test');
```

### フォームタグのアクション属性
フォームの action 属性に名前付きルートを指定して、フォームの送信先を定義できます。
`profile.update`は**resources->views->profile->update**のviews配下を示しています。
```html
<form method="POST" action="{{ route('tests.home') }}">
    <!-- フォームの内容 -->
</form>
```

### APIルートの生成
名前付きルートは、LaravelのAPIルートでも使用できます。
`route()ヘルパー関数`を使用して、APIルートへのリクエストURLを生成できます。
```php
$url = route('api.users.index');
```

# 最後に
こちらの記事を見てインプットはできたと思いますが、自分の手でアウトプットすることが１番大切です。

見てコピペするだけでなく、自分なりに改造したりしてください。
「こう書いたらどうなるかな？」など試したりしてください。
そうすることで、あなたの血肉となってプログラミングを習得することが出来るでしょう。


と、先輩に言われたので共有しますw
一緒に頑張りましょうね！！！

最後まで読んでいただきありがとうございました!
30代未経験からIT企業に転職してみて1年経った感想

初めまして。

未経験からIT企業への転職をし実務経験1年が経ったので、同じような境遇で転職活動をしている方の希望になれればと思い、振り返りとこの1年の感想を綴ってみたいと思います。

## 目次
  - 未経験転職を決めた理由
  - 独学から内定まで
  - 勤務開始、この1年の振り返り


### 未経験転職を決めた理由
私は現在、30代前半。
高校卒業後、友人の紹介で入社したアパレル企業に10年ほど勤めた後、人生初の転職でIT業界で働くことになりました。

転職を考え始めた頃は、ExcelとPowerPointをちょこっと触ったことがある程度で、エンジニアといえば頭のいい人がやる職業で自分には関係ない仕事だと思っていたぐらいの、スーパー未経験でした。

そんな自分がなぜ今の仕事に興味を持ったのかというと、
コロナ禍で前職の仕事をサボりまくっている時に見たyoutube広告がきっかけです。

「私は今、悠々自適な生活を送っています！在宅で仕事をして、月収50万！」

こんな広告に踊らされ、2021年の年末にIT転職することを決めました。

### この時のプロフィール
  - 住居：大阪
  - 学歴：高卒
  - 年齢：30歳
  - 性別：男性
  - 職業：アパレル
  - 趣味：二児の父

## 独学から内定まで
転職に向けて行動していくことを決めたわけですが、何をどうすれば良いのかあまりよくわかっていませんでした。
そこでとりあえず参考にしたのが、安定のYouTubeです。

「HTML、CSSから勉強したらいいのか、なるほど。」

Progateに登録して、HTMLとCSSの基礎。
慣れてきたらサイト模写。
やり始めは面白かったのですが、慣れてくると
自分が思っているエンジニアと、今やっている内容ってズレてない？
と、疑問が出てきました。

その疑問を解消するためにした行動が面接を受ける、でした。

手当たり次第に未経験可の文言がある企業に応募。
案の定相手にされないことばかりだったのですが、1社だけちゃんと答えをくれた企業がありました。
そこでの面接時にこういう行動をすれば良いと思いますよ、という提案（ざっくりいえばポートフォリオ作りなさいよって話でした）があり、
いつまでに出来ますか？の問いに
「あ、じゃあ3ヶ月で。」
と即答して終了しました。

これが2022年1月頃でした。

そこから面談で提案された言語、FWでのポートフォリオ作りを開始しました。
色々調べながら自分が作りたい必要な機能をもったものを、完成させることができました。

それが完成したという報告も兼ねて再度、同じ企業に応募し面接までしていただけました。
結果は当然不採用。

ただ自分としては作りたいものを完成させられたことでかなり自信がつきました。
その後も応募、面接を繰り返し
なんやかんやで今の会社から内定をいただけたので結果オーライかなと思ってます。
内定をいただけたのが2022年7月、勤務開始は9月から、ということでどきどきしながら入社まではのんびり過ごしました。

## 勤務開始、この1年の振り返り
最初の1ヶ月は社内研修、その後は案件に参画という流れでした。
参画する案件も社内での開発なので、出向することもなく安心して働けました。
社内の方達は全員良い人ばかりで、こんなおっさん新人の業務中の質問にも丁寧に答えていただいて、助けてもらってばかりです。

業務的にはPHPでのwebアプリケーション開発的な感じですかね？

とにかく日々楽しく仕事ができていて充実しています。
ここ最近は個人的に色々あったため棚ぼた的に憧れのリモートワークも経験できました。

日々の仕事中に自分自身が成長したなと実感できる点もあれば、まだまだだなとへこむことも多々あります。
楽しさ充実感もすごくありますが、もっと早く転職しておけばよかったと思うこともあります。
他の人よりもスタートが遅かった分たくさん吸収してどんどん成長しないと、という危機感みたいなものは常に頭のどこかにあります。
ただその吸収するための経験や勉強、危機感が苦にならないぐらい、というより楽しいと思えるぐらいに良い形で働けているのかなと思うので、転職してよかったなというところに落ち着きます。
これからもいろんな経験を通して、エンジニアとして成長していこうと思います。

長々と自分語り失礼しました。
一人前にもなれていないので、まずは一人前になることを目指して精進していきます。

最後までお読みいただいてありがとうございました。
ネットワークセキュリティについて整理①



情報セキュリティは以下6要素をバランス良く高めていく必要がある。
6要素を用いれば、システムのセキュリティを評価することができる。

# 情報セキュリティの3大要素(CIA)
### 機密性(Confidentiality)
- 認可された者だけが情報を利用できる状態を保つ。
- 例：パスワード認証、アクセス許可、暗号化、セキュリティゲート

### 完全性(Integrity)
- 正確であること。完全である状態を保つ。
- 改ざん防止の仕組み。
- 例：デジタル署名、MD(メッセージダイジェスト)


### 可用性(Availability)
- 認可された利用者が必要な時に必要な情報を利用できる状態を保つ。
- システムの二重化、ホットスタンバイ、クラスタリング構成、UPS


# 追加された3要素
### 責任追跡性、説明可能性(Accountability)
- ユーザやサービスの振る舞いを説明できる状態を保つ
- セキュリティインシデントが起こったら、いつ・だれが・どこから・どのように侵入してきて・何をして・どんな被害が起こっているか・どんな影響が発生することが考えられるかを説明できる状況にしておく。
- 監視やロギングをして、記録をとっておくと、後から分析できる。
- 分析できず、適切な対応をとれないことを避けなければならない。
- 例：操作ログ、アクセスログの記録、デジタル署名を使った否認防止


### 真正性、認証性(Authenticity)
- 利用者が本人であることを認証できる状態を保つ
- ユーザごとに異なるアカウント情報を使用するようにする。
→パスワードの使いまわしやアカウントの共有など
- 例：パスワード認証、デジタル署名


### 信頼性(Reliability)
- システムやプロセスが矛盾なく一貫して動作する状態を保つ
- 常に期待通りの動作を保つ。
- 商品を注文して料金を振り込んだのに商品が届かないなどは信頼性が損なわれている。
- 例：システムの二重化、設備の物理的な分散化


# セキュリティ対策の構成
### 時系列
- 事前対策
- インシデント発生時
- 発生後の対策・復旧
- 運用

### 管理・運用
- 技術的な対策
- 運用面での対策
- セキュリティポリシー(ルール策定)

### リスク対策
- 抑止
→警備員を雇い、建物の入り口に立ってもらう。警察官のパトロール。
- 予防
→ランサムウェア対策としてのデータのバックアップ
- 検知
- 回復

### リスク管理面
- 許容
- 低減
- 移転
→問題が起こったときに他者に対応してもらう。
- 回避
→スマホを使わなければ、スマホ関係の被害を防げる。あまり現実的ではない。

# 脅威とは
- 情報資産(データファイル、書類、会話の内容)およびネットワークシステムに損害を与える可能性のこと
- 3種類に分けられる
- セキュリティと言えば、一般的には1.が想像されがちだが、2. や3. の割合も大きいため、対策が必要。
1. 人為的かつ意図的
・破壊、改ざん、漏洩、盗聴、盗難、サービス停止、不正利用、踏み台、ウイルス感染など
・各要素を想定した個別の対策が必要

2. 人為的かつ非意図的
・操作ミス、勘違いなどのヒューマンエラー
・フールプルーフ、運用ルールの策定、利用者の教育、アクセス制限などで対策

3. 非人為的かつ非意図的
・故障、事故、障害など
・システムの冗長化、バックアップ、BCP(DR)の策定などで対策

# 外部からの攻撃がどのように行われるのか、どのように守れば良いのか
- セキュリティは鎖のようなもの
　鎖全体の強度は一番弱い輪の強度と等しい。　なので、全体のバランスが必要。
　→全体のバランスを評価する基準としてCIAを用いる。
- 優秀な攻撃者は必ず一番弱い輪を攻撃する。
　→攻撃者は攻撃前に必ずどこが弱い輪なのかを調査してくる(予備調査)
- 守る側は弱い輪を必ず補足することが大事
　→予測と監視が大事
- 人間もITシステムを構成する鎖の輪の一つであり、狙われやすい。攻撃者的には、技術的な防御を突破するよりも人を騙した方が簡単。
　→ 相対的に人間が弱点になりやすい。調子の良いとき・悪いとき、詳しい人・詳しくない人、うっかりミスをする人など防御力がバラバラ。
　→ 技術的な攻撃は対策しやすい。攻撃が高度になると、技術的な防御も高度になる。一度防御力が上がれば維持される。
  →人を起点に攻撃する流れ：ウイルスをメールで送りつける→受け取った人を騙して組織内にウイルスを放ってもらう→ウイルスが悪いものを引き込んで攻撃が成立(例：emotet)。
　
emotetの攻撃手法についての記載
https://www.ipa.go.jp/security/emotet/attack.html

### 攻撃の予測
- 攻撃手法のトレンドを把握する
　→斬新な攻撃手法を編み出すことは難しいため、うまくいっている方法(成功事例)が模倣されていく。
　IPAが出している情報セキュリティ10大脅威を参考にする。
　https://www.ipa.go.jp/security/10threats/10threats2022.html
- 攻撃者の想定と攻撃目的の推測を行う。
　→攻撃の手段・使用技術・攻撃経路を想定する。
　→自分と似た組織に対する攻撃事例を分析する。
　　例：ただのいたずらならば、準備にあまり時間のかからないDos攻撃など。
- 攻撃分析のフレームワークを使用する。各フェーズごとにどのような攻撃がされそうか予想する。
　①予備調査(偵察)
　②脆弱性の調査
　③攻撃の試行/侵入
　④永続化(例：バックドアの設置)
　⑤権限の上昇(管理者権限の奪取)
　⑥攻撃活動
　⑦痕跡消去(隠ぺい工作)
　
サイバーキルチェーン(フレームワークの一例)
　①偵察：攻撃者の調査、弱点の把握
　②武器化：弱点を突くための攻撃に用いるマルウェアなどの作成
　③配送：メールやWebサイトなどでマルウェアを配送
　④攻撃：攻撃対象者によるマルウェアの実行
　⑤インストール：マルウェアへの感染
　⑥遠隔操作：マルウェアを介した遠隔操作の実施
　⑦目的実行：情報の摂取や改ざんなど、当初の目的を実行


　MITRE社
　脆弱性管理や攻撃手法の分析を行っている米国の非営利組織。
　米国政府の支援を受けている。

　MITRE ATT&CK
　企業のネットワークに侵入するための攻撃手法を一覧化したもの。
　https://attack.mitre.org/matrices/enterprise/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/a67ff560-65df-c89d-30aa-6a4faca97834.png)

　日本語へ翻訳した結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/413385/4189f51d-d756-5848-eb1e-c66a42f01855.png)
M1macでDocker Desktopが重いので、OrbStack 1.0 に変えてみた

# はじめに
M1macでDockerを使っているが、Docker Desktopが重いので、作業の待ちが多く発生していた。
そのため、2023年9月25日に、OrbStack 1.0がリリースされたので、導入をしてみた

https://codezine.jp/article/detail/18404

# パソコンのスペック
PC: Macbook Pro 2021
Chip: Apple M1 Pro
macOS: Ventura 13.5.2

# 手順
## 1. OrbStackをダウンロード

以下の公式サイトからダウンロード

https://orbstack.dev/blog/orbstack-1.0

HomeBrewでも可能
```:ターミナル
brew install orbstack
```

## 2. OrbStackの初期設定
- OrbStackを起動
![Screenshot 2023-10-02 at 10.51.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2674841/dde8ea2d-4e1d-2bd9-15f7-abeebfb8413c.png)

- アプリの画面に従い、各種設定

## 3. 実際に使うコンテナの起動

```:ターミナル
docker-compose up
[+] Running 0/2
 ⠙ db Pulling                                                                                                                                                                  4.1s
 ⠙ redis Pulling                                                                                                                                                               4.1s
no matching manifest for linux/arm64/v8 in the manifest list entries
```
db, redisのplatform不一致が発生
（db, redisのimageがIntel MacのAMD64のプロセッサであるため。M1 MacはARM64。）
その場合は、 以下の`4. platformの指定`を実行

## 4. platformの指定
db, redisに以下を指定
```docker-compose.yml
 db:
    platform: linux/x86_64
 redis:
    platform: linux/x86_64
```
次回のコンテナ起動時には、上記のplatformの指定は不要。（警告が発生するが）

## 5. コンテナに入り、サーバ起動
```:ターミナル
docker-compose exec app bash
bash-5.2# bundle exec rails s
```
サーバ起動が5秒になった！！
Docker Desktopは30秒くらいかかったので、かなり快適
rubocopやrspecも数秒なので、気軽に実行できる

## 追記
以前までは、Desktop Dockerを使っていて、今回は、その時に作成したコンテナイメージを使って、OrbStackでコンテナを起動している。
OrbStackでコンテナイメージをbuildして、コンテナを起動するとエラーとなる事象が発生した。
そのため、コンテナイメージはDesktop Dockerでbuildして、OrbStackではコンテナ起動という使い方が現時点ではベストかなという状況になっている。
ログを確認するのに毎回Railsアプリを立ち上げるのは意外と辛い

# はじめに
Railsの開発を進める中で、rails serverが起動するまでの待ち時間が意外とストレスでした。
一方で、development.logに出力されるログは多すぎて...

そこで、リクエスト時のログを各コントローラのアクションごとに管理できるよう、各フォルダに分割して出力するgemを作成してみました。

[custom\_log\_space \| RubyGems\.org \| コミュニティのgemホスティングサービス](https://rubygems.org/gems/custom_log_space)

# インストール方法
Gemfileに以下のように`gem 'custom_log_space'`を追加して、`bundle install`を実行してください。

```diff
group :development do
  + gem 'custom_log_space'
end
```

# 使い方
ローカルでrailsアプリを立ち上げて、画面にアクセスすると、log/custom_log_spaceディレクトリ配下に、以下の命名規則で、ログが出力されます。

```
log/custom_log_space/#{コントローラー名}/#{アクション名}/#{日付}/#{時刻}.log
```

例
```
user log % tree
.
├── custom_log_space
│   └── articles_controller
│       ├── index
│       │   ├── 2023-09-19
│       │   │   ├── 09:13.log
│       │   │   └── 20:00.log
│       │   └── saved
│       └── show
│           ├── 2023-09-18
│           │   ├── 21:29.log
│           │   └── 22:02.log
│           ├── 2023-09-19
│           │   └── 20:00.log
│           └── saved
└── development.log
```

# ログの保持ポリシー
* `#{日付}`フォルダの最大保持数は2つ、`#{時刻}.log`は最大で10ファイルです。これを超えると、古いファイルから順に削除されます。
* 重要なログは`saved`ディレクトリ配下に移してください。
`log/custom_log_space/#{コントローラー名}/#{アクション名}/saved/`

# 注意点
* 一度のリクエストで複数のコントローラーのアクションが呼び出される場合、ログはそれぞれのアクションごとのフォルダに分けられます。このため、ログの追跡方法に注意が必要です。
* ただし、このgemを導入しても既存のdevelopment.logへの出力に変更はないため、引き続きそちらを参照することが可能です。
【VBA】Format関数とNumberFormat関数の違いとは

以外に気づいていないかもしれません。
VBAの関数の違い。それはFormat関数とNumberFormat関数です。
プログラミング言語やソフトウェアによって異なるかもしれませんが、
一般的な概念に基づいて以下のような違いがあります。

用途:

Format関数: 通常、文字列の書式設定に使用されます。日付や数値などのデータを指定された形式に整形するのに使われます。例えば、日付を「年-月-日」の形式に整形する場合に使えます。
NumberFormat関数: 通常、数値の書式設定に使用されます。数値を指定された形式に整形し、小数点の桁数や千の位区切りなどを設定するのに使われます。

使い方を間違うと、プログラムは動きません
注意が必要です
Javaで「格納されている文字列の長さを取得する」の動作を確認してみた

# 概要

Javaで「格納されている文字列の長さを取得する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/stringbuilder/index6.html

# 実装

以下のファイルを作成しました。
```JSample6_2.java
class JSample6_2{
  public static void main(String[] args){
    StringBuilder sb = new StringBuilder();

    System.out.println(sb.toString());
    System.out.println("length:" + sb.length());
    System.out.println("capacity:" + sb.capacity());

    System.out.println("-- --");

    sb.append("Hello, Tarou.");
    System.out.println(sb.toString());
    System.out.println("length:" + sb.length());
    System.out.println("capacity:" + sb.capacity());

    System.out.println("-- --");

    sb.append("Good Morning");
    System.out.println(sb.toString());
    System.out.println("length:" + sb.length());
    System.out.println("capacity:" + sb.capacity());
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample6_2.java 
$ java JSample6_2 

length:0
capacity:16
-- --
Hello, Tarou.
length:13
capacity:16
-- --
Hello, Tarou.Good Morning
length:25
capacity:34
```

# まとめ

何かの役に立てばと。
PowerShell で固定長を CSV に変換

自分のためにメモ

## 固定長を CSV に変換
```
$fileContent = Get-Content -Path 'C:\workspaces\test\FixedLength.txt'
$csvData | Set-Content -Path 'C:\workspaces\test\output.csv'
$csvData = $fileContent | ForEach-Object {
    $field1 = $_.Substring(0, 10).Trim()
    $field2 = $_.Substring(10, 10).Trim()
    $field3 = $_.Substring(20, 10).Trim()
    "$field1,$field2,$field3"
}
$csvData | Set-Content -Path 'C:\workspaces\test\output.csv'
```


## サンプル

```TXT:固定長
1234567890ｱｲｳｴｵｶｷｸｹｺAAAAAAAAAA
1234567890ｻｼｽｾｿﾀﾁﾂﾃﾄAAAAAAAAAA
1234567890ﾅﾆﾇﾈﾉﾊﾋﾌﾍﾎAAAAAAAAAA

```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/b2206b98-c2e1-2082-a29b-5653744934c7.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93824/44842515-4dd7-46ea-6465-607dee7b8339.png)


以上です～
wslでelixir その74

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
練習問題やってみた。

# 練習問題
Livebookで、jsonをパースして、地図にプロットせよ。

# 方針
- jason使う。
- agent使う。
- MapLibre使う。


# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/406287e8-ea2b-b2bc-eb21-0f4ad5505061.png)

# サンプルコード

```

defmodule Point do
	use Agent
	def start_link() do
		Agent.start_link(fn ->
			[]
		end, name: __MODULE__)
	end
	def get() do
		Agent.get(__MODULE__, fn v ->
			v
		end)
	end
	def cls() do
		Agent.update(__MODULE__, fn v ->
			[]
		end)
	end
	def put(x) do
		Agent.update(__MODULE__, fn v ->
			v ++ [x]
		end)
	end
end
Point.start_link
Point.cls
geojson = """
{
		"bikuya": [{
				"lat": "37.929687",
				"lon": "140.151111",
				"name": "オートショップユニット"
		}, {
				"lat": "37.929220",
				"lon": "140.109344",
				"name": "（株）エイジュウプロ"
		}, {
				"lat": "37.923453",
				"lon": "140.093108",
				"name": "（株）ホンダウイングロードショウ"
		}, {
				"lat": "37.911333",
				"lon": "140.112004",
				"name": "（有）カーセンター葵商会"
		}, {
				"lat": "37.907591",
				"lon": "140.108036",
				"name": "塚本サイクル"
		}, {
				"lat": "37.928429",
				"lon": "140.114247",
				"name": "サイクルショップ川口"
		}, {
				"lat": "37.916279",
				"lon": "140.099879",
				"name": "サイクルショップ中村"
		}, {
				"lat": "37.917854",
				"lon": "140.101416",
				"name": "菅原商会"
		}, {
				"lat": "37.912485",
				"lon": "140.108688",
				"name": "サイクルセンター卯月"
		}, {
				"lat": "37.912049",
				"lon": "140.105914",
				"name": "ホンダ野村モータース"
		}, {
				"lat": "37.869915",
				"lon": "140.103534",
				"name": "モーターハウスＫ"
		}, {
				"lat": "37.918955",
				"lon": "140.109289",
				"name": "ライダースサロン・ヤマカ"
		}, {
				"lat": "37.915746",
				"lon": "140.108313",
				"name": "中央ホンダ"
		}, {
				"lat": "37.905011",
				"lon": "140.107225",
				"name": "香澄ホンダ"
		}, {
				"lat": "37.912663",
				"lon": "140.123328",
				"name": "佐藤オート商会"
		}, {
				"lat": "37.910789",
				"lon": "140.121636",
				"name": "香坂輪店"
		}, {
				"lat": "37.958525",
				"lon": "140.125682",
				"name": "斎藤モータース"
		}, {
				"lat": "37.956678",
				"lon": "140.117820",
				"name": "ニューホンダ石山"
		}, {
				"lat": "37.903901",
				"lon": "140.131694",
				"name": "二輪屋たかはし"
		}, {
				"lat": "37.886019",
				"lon": "140.104554",
				"name": "夢工場"
		}, {
				"lat": "37.874814",
				"lon": "140.103239",
				"name": "あべ輪店"
		}, {
				"lat": "37.905055",
				"lon": "140.137379",
				"name": "レッドバロン米沢"
		}]
}
"""
  |> Jason.decode!()
  |> Map.get("bikuya")
  |> Enum.map(fn i -> 
    lat = i |> Map.get("lat") |> String.to_float()
    lon = i |> Map.get("lon") |> String.to_float()
    Point.put([{lon, lat}])
  end)

map = Ml.new(style: :street, center: {140.1, 37.9}, zoom: 10)
  |> Kino.MapLibre.add_markers(Point.get)
  |> Kino.MapLibre.new()


```

以上。
モンティ・ホール問題を愚直にやってみる

モンティ・ホール問題は理屈を聞いてもわかったような分からないような、感じだったので愚直に１ゲームずつやってみて本当に変更したほうが有利なのかを検証してみました

とりあえず10回やってみることにします

```monty.py

import random

def oneTurn(isChange):# 
    #ゲーム一回分を実行する関数
    #   引数：isChange 選択後に交換するかしないか True False
    #   戻値：hit 当たったか外れたか    1:当たり　0:ハズレ

    #当たりの箱(インデックス番号)を用意する
    hitIndex = random.randint(0,2)

    #ユーザーの入力はランダムで
    playerFirstChoice = random.randint(0,2)

    boxLeftIndex=[0,1,2]#残っている箱（司会者が見せる箱の選択肢）

    if playerFirstChoice==hitIndex:#最初の選択がたまたま当たりのとき
        """
        まずは箱を３つ、配列として準備する　　　boxLeftIndex=[0,1,2]
        例えば３つめの箱（インデックスは２）が当たりとする
        その箱は見せないので除いておく      boxLeftIndex=[0,1]

　　　　　次にプレイヤが選択、たまたま2の箱（当たり)を選択したとする 

        この場合、司会者が見せるのは０か１  boxLeftIndex=[0] or boxLeftIndex=[1]
        """
        boxLeftIndex.remove(hitIndex)   #当たりは絶対見せないので除いておく
        r2 = random.randint(0,1)        #見せる箱を乱数で決定
        mcOpenIndex = boxLeftIndex[r2]  #mcOpenIndex：司会者が開示する番号

        #そのあとプレイヤがチェンジするか否か（すでに引数で決定されている）
        if isChange==False:
          finalIndex=playerFirstChoice#変更しないなら最初のまま
        else:
          boxLeftIndex.remove(mcOpenIndex)   #mcの出したハズレを取り除く
          finalIndex=boxLeftIndex[0]

    else:#最初の選択が外れのとき
        """例えば２の箱が当たりとする         boxLeftIndex=[0,1,2]
        当たりは見せないので除いておく        boxLeftIndex=[0,1]
        はずれのプレイヤは１の箱（ハズレ)を選択したので１を除去
        mc（司会者）は０の箱を見せないといけない  boxLeftIndex=[0]
        """
        boxLeftIndex.remove(hitIndex)           #当たりは絶対見せないので除いておく
        boxLeftIndex.remove(playerFirstChoice)  #プレイヤの選択したハズレを除去
        mcOpenIndex = boxLeftIndex[0]           #mcOpenIndex：mcが開示する番号

        #そのあとプレイヤがチェンジするか否か（すでに引数で決定されている）
        if isChange == False:                   #チェンジしないなら
          finalIndex=playerFirstChoice          #  最初のまま
        else:                                   #チェンジする場合
          tmpbox = [0,1,2]                      #  一時的な配列を用意
          tmpbox.remove(mcOpenIndex)            #  mcの開示した番号を除去
          tmpbox.remove(playerFirstChoice)      #  自分が最初に選んだ番号を除去
          finalIndex = tmpbox[0]                #  ファイナルアンサー

    #当たり外れの判定
    if finalIndex == hitIndex:
      hit=1
    else:
      hit=0

    return hit


#===main ==============================
N=10
ct_hit=0
print("==============変更した場合==================")
for i in range(N):
    hit = oneTurn(True)
    ct_hit += hit
print("当たり回数=",ct_hit)    
print("==============変更しない場合==================")
ct_hit=0
for i in range(N):
    hit = oneTurn(False)
    ct_hit += hit
print("当たり回数=",ct_hit)    

```

結果はこんな感じで
==============変更した場合==================
当たり回数= 5
==============変更しない場合==================
当たり回数= 4

なんだかよくわかりません


# 回数を増やす
N=100000とした場合は
==============変更した場合==================
当たり回数= 66436
==============変更しない場合==================
当たり回数= 33275
となってたしかに倍の確率になることがわかります
[004] Pythonの環境を選ぶ

# Pythonを使う目的
関数電卓,Excel,Scilabなどのツール類をPythonに統合したい．
非情報系のエンジニアなので，開発環境の構築等にはあまりこだわらない．
まずはサクッと使える環境として良さそうなものを選ぶ．

# 環境候補
+ Anaconda & Jyupiter lab
+ Python標準インストール & Jyupiter lab
+ Google colab

# 結論

自分で必要なパッケージを都度インストールしたいという欲求があるので，Python標準インストール & Jyupiter labに決定．Google colabも便利だと思うので，サブマシンなんかで併用することにした．

## 追記
プロジェクトごとに仮想環境を作って動かすほうが良さそうな気はしている．
実際に問題に直面するまではローカル環境で動かしていくことにする．
ABC322回答メモ

0.はじめに
　久々に、A~Cを快調にクリアでき、1時間以上のこしてDに。
　でもD問題は複雑で、実装は全然間に合わず、結局
　3問でフィニッシュ。
　3問解くスピードはそこそこだったためか、レートは11あがり
　700台に復帰できました。

1.A - First ABC 2
　単純にループしていき、文字列Sの[i:i+3]がABCならi+1を出力し
　終了。最後まで一致しなかったら-1を出力して終了

　https://atcoder.jp/contests/abc322/submissions/46061289

2.B - Prefix and Suffix
　Tをスライスして、先頭N文字・末尾N文字をSと比較して
　出力条件ごとの判定をして出力して終了

　https://atcoder.jp/contests/abc322/submissions/46068301

3.C - Festival
　解説を読むと自分の実装と若干違いました。
　　・変数N,MとリストAを読み込む
　　・変数ｐを0で初期化
　　・ループを、iが１～Ｎを取るようにまわす
　　　・i日目の値としA[p]-iを表示
　　　・i=A[p]の時、pに1加算
　結構すっきりしているのではないかと自負しています。

　https://atcoder.jp/contests/abc322/submissions/46079680

4.D - Polyomino
　問題見ただけでスルーしそうになりましたが、E以降も
　そんなに簡単そうでもなかったので、頑張ってみました。
　結果は1時間以上がんばっても実装しきれませんでした。

　実装しようとしていた考えは、
　１）ブロックを置く順毎にチェック
　　　（1→2→3、1→3→2、・・・の6種類）
　２）ブロックを置くフィールドを用意し、一番左上から
　　　ブロックを置いていく
　３）1つ目に置くブロックが、形状的に左上をふさげれば
　　　置いて、置くフィールドの左上から見ていき空いている
　　　マスに、2個目のブロックが置けるかを判定しておく・・・
　　　を繰り返していく、置けなかったらブロックを90度回転して
　　　繰り返す・・・

　と、ざっくりそんな感じでやっていきましたが
　じかんがたりず、考え方があっているかも判定
　できませんでした。

　時間があったらリベンジしたいところです。

10/4追記

　この問題がどうしても気になって、空いた時間で
　回答を進めてました。

　久々にプログラム設計書的なものまでまで書いてしまいました。

　基本的な考え方は問題なかったのですが
　1個目だけ置いた状態のパレットを
　とっておいて、2個目をいろいろな角度で
　おいていく・・・という過程で、
　なぜか、よけておいたリストも更新されてしまう
　という現象に苦しめられました。

　結局copy.deepcopyでよけておけば
　更新されないことが分かりそれを使って書き直したところ
　ACとなりました。


　https://atcoder.jp/contests/abc322/submissions/46202882

以上
Deployment ManagerでPythonを使ってデプロイする

# 構成ファイルを作成する
deploy.yml、vm-python-template.py、parameter.pyを作成します。
以下の内容をそれぞれのファイルに記述してください。
```yaml:deploy.yml
imports:
- path: vm-python-template.py
- path: parameter.py

resources:
- name: python-template
  type: parameter.py
```
```python:vm-python-template.py
def GenerateConfig(context):
  resources = [{
      'name': context.properties['name'],
      'type': 'compute.v1.instance',
      'properties': {
          'zone': context.properties['zone'],
          'machineType': ''.join(['zones/',
                                  context.properties['zone'], '/machineTypes/',
                                  context.properties['machineType']]),
          'disks': [{
              'deviceName': 'boot',
              'type': 'PERSISTENT',
              'boot': True,
              'autoDelete': True,
              'initializeParams': {
                  'sourceImage': context.properties['sourceImage']
                  }
            }],
          'networkInterfaces': [{
              'network': 'global/networks/default'
            }]
      }
  }]
  return {'resources': resources}
```
```python:parameter.py
def GenerateConfig(unused_context):
  resources = [{
      'name': 'parameter',
      'type': 'vm-python-template.py',
      'properties': {
		  'name': 'demo-python-vm01',
          'zone': 'us-west1-a',
          'machineType': 'e2-micro',
          'sourceImage': 'projects/debian-cloud/global/images/family/debian-11'
      }
  }]
  return {'resources': resources}
```

# デプロイメントを実行する
CloudShellで以下のコマンドを実行してください。
```
$ gcloud deployment-manager deployments create demo-python-deploy --config deploy.yml
```

# インスタンスの作成を確認する
GCPコンソールでComputeEngineを表示してください。
![スクリーンショット 2023-10-01 7.14.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/14202/e5c36c6c-940b-4058-3cb3-1bc4a22e1ce5.png)

# デプロイメントを確認する
以下のコマンドを実行してください。
```
$ gcloud deployment-manager deployments list
```

# デプロイメントを削除する
以下のコマンドを実行してください。
```
$ gcloud deployment-manager deployments delete demo-python-deploy --async
```
【Windows】 WordPress+LocalにてZip形式のテーマが「一時フォルダーが見つかりません。」となってインストールできないとき

# 原因
ググると色々な原因があるようですが、自分の場合は以下が原因でした。
同じような状況の方は確認してみると良いかもです。

以下のファイルの先頭に
```
Local Sites/[projectname]/conf/php/php.ini.hbs
```
以下のような記述があり、
```:php.ini.hbs
{{#if os.windows}}
extension_dir="{{extensionsDir}}"
sys_temp_dir="C:\Windows\TEMP"
{{/if}}
```
自分はSSD交換時にOSパーティションのクローンを行っており、OSのインストールパーティションのドライブ文字がHだったため、
```
sys_temp_dir="H:\Windows\TEMP"
```
と修正し、Local上で`Stop site` -> `Start site`とすることでZip形式のテーマがインストールできました。
WSL2の仮想ハードディスク容量を最適化するPowershellスクリプト

WSL2 の仮想ハードディスクがどんどん大きくなるので、ときどき最適化させるためのスクリプトを書いた。

## スクリプト

``` powershell
<#
.SYNOPSIS
  WSL2 の仮想ハードディスク(VHD)ファイルの容量を最適化します。
.DESCRIPTION
  WSL2 で作成されたVHDファイルは、継続的なコンテナ開発などで容量が増大します。
  このスクリプトでは、内部の不要なコンテナイメージを除去し、その後 VHD ファイルのサイズを最適化します。
.NOTES
  VHD ファイルのバックアップを推奨します。
#>

# VHDが存在するフォルダ（サブフォルダOK）
$wslDir = 'C:\develop\WSL'
$files = Get-ChildItem $wslDir -Recurse -File -Filter '*.vhdx'

if ($files.Count -eq 0) {
  Write-Host ('"{0}" に仮想ハードディスクファイル(.vhdx) が見つかりませんでした。終了します。' -f $wslDir)
  return
}

$i = 0
$files |
  ForEach-Object {
    [PSCustomObject]@{
      Number  = $i
      Name    = $_.Directory.Name
      Size_MB = $_.Length / (1MB)
    }
    $i++
  } |
  Format-Table
$no = Read-Host 'Input Number'

Write-Host 'WSLを起動します。数秒お待ち下さい。'
Write-Host '圧縮前に不使用のコンテナイメージを削除するには、 "y" を入力してください。' -ForegroundColor Cyan
wsl -d $files[$no].Directory.Name docker system prune

wsl --shutdown

$scriptFile = $pwd.Path + '\diskpart-script.txt'
@"
select vdisk file="$($files[$no].FullName)"
attach vdisk readonly
compact vdisk
detach vdisk
"@ | Set-Content $scriptFile -Encoding ascii
diskpart /s $scriptFile

Write-Host 'diskpart を起動します。処理には数十秒かかる場合があります。'
```

## 雑記

　VHD は容量固定できるからこの作業はスマートじゃない気がする、ということでスクリプト化して目を背ける。だって、VHDを作った後でのサイズ変更は手順が少し多くて、自分でやるならまだしもメンバーに展開するのは面倒だもん。壊しそう。

　diskpart さん、対話的なインターフェースしかなくてバッチでやるにはファイルを食わせるしかないの、ちょっと頼みますよ…。

　今回のように、軽く作ったスクリプトの頭に `comment-help` を付けるのを、最近の習慣にしてる。
この書式だと、コマンドレットでもスクリプトでも `get-help` したときにいい感じに出力される。 `#######...` とかで手動で装飾するの、嫌なのよね。 `get-help` しないにしても、コメントの書き方がゆるく標準化されてファイル上で見やすいのがいい。あと短い説明と長い説明のセクションが別れているのが好き。なぜか背景まで書きたくなるのであとで助かる。使用例とか参考URLのセクションまであるのも好き。
その場の小さな課題解決のために書いたスクリプトが結構散らかっていて、「使い捨て」と「どこかで再利用する」の未来を重ね合わせて存在する（多用するものはプロファイルフォルダに入れて自動読み込みさせてる）んだけど、この習慣を始めてからだいぶ扱いやすくなった。

## 参考URL

- [Dockerのお掃除 - Qiita](https://qiita.com/MasanoriIwakura/items/53cb7968e44f7a25e083)  
  > dockerのお勉強とか、実験とかしているとゴミが沢山できるのでお掃除の方法をメモしておきます。
- [Windows/WSL2の容量を減らす方法 - あんこ | Zenn](https://zenn.dev/anko/articles/976d904e53d87e)  
  > 気になったアプリはつい入れちゃうワガママ生活を送っていたら `no space left` なるディスクエラーが出てくるようになってきたのでダイエットしていこうという記事です。
- [Using powershell to run diskpart commands - Super User](https://superuser.com/questions/1615584/using-powershell-to-run-diskpart-commands)
拡散モデルによる画像生成の秘伝の技

## はじめに
StableDiffusionXL v1.0 というモデルを利用して画像生成を試してみた。その時に得た知見を共有する。
この記事はなんの学術的な知識に基づかず、経験による仮説の域を出ないものである。

記事の結論を先に書いてしまうと上手くいきやすい生成文のルールは以下のような感じだと思う。

プロンプト
（修飾語）　生成したい物体の名詞, （修飾語）, (クオリティに関わる単語)

例:
"red grasshopper,robotics, gloss metalic, 8k, detaild"

このようにするとだいたい理想通りの画像を生成できることが多い。
排除したい特徴を書くネガティブプロンプトの作り方も基本的に同様で良いと思う。
難しいので"anime"くらいしか今回は書いていない。（アニメぽい画像を生成して欲しくないから）

以下の２枚は実験過程で生成したサンプルである。

![grasshopper-cca4af5b-f3bd-4146-be34-9d83d6d3b53d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/f9a0bf07-6ef0-40be-7113-c088f94ae7c7.png)
プロンプト："red grasshopper,robot,lamp, gloss metalic, 8k, detaild"

![grasshopper-ad2dcc06-1666-4f69-8f44-85802b2c0234.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/cc8f5581-2f89-052c-c680-a7ef52d8cb78.png)

プロンプト："red grasshopper,robotics, gloss metalic, 8k, detaild"


## 秘伝の技
### ①（できるだけ）名詞は生成したいオブジェクトの一つのみ
画像生成は基本的に複数のオブジェクトを生成することが苦手である。
私の仮説の域を出ないが、単語から派生されるベクトルが結合してしまうからだと思う。
アテンションとかを工夫して学習したモデルでないと厳しいのだと思う。

### ②装飾したい単語は名詞の近くに置く
例えばプロンプトがメタリックな赤いバッタを生成したいときは以下のようにgrasshopperの近くにredやroboticsを置くイメージである。
これによって赤くてメカっぽいバッタのベクトルが加算されてうまく画像が生成されるというイメージを持って貰えば良いと思う。（実際にそのように生成されているかは謎）

```
prompt = "red grasshopper,robotics, gloss metalic, 8k, detaild"
negativa_prompt = "anime"
```

そうすると以下のような画像が生成される。

![grasshopper-99f576ea-9059-4f55-8a6d-46dd55c86400.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/0f752979-13ea-557e-b523-5a6a98dcf330.png)
![grasshopper-add71864-e172-4f28-acf3-e24cb5132441.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/ff878442-2fa9-94f4-854a-51480a9d16ad.png)

![grasshopper-6efa6eef-0b5a-4acb-a9ef-a0f65b182471.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/8560f174-5040-4a7d-e157-7198eb58bd5b.png)

しかし例外はある。以下の画像のようにroboticsから連想されるバイクや自動車もたまに生成される。

![grasshopper-0d2a1954-6491-4a78-b87e-aa8cada74bb8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/a3c2856e-51ab-bbc3-af98-d1a9a5abc203.png)
![grasshopper-c288a16d-fc60-4400-9f7d-d3b15d4a265f.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/1a46fd08-3452-ec9a-65e7-1c92babef1d7.png)

これらをネガティブプロンプトで排除しようとすると、生成される画像にバリエーションがなくなってつまらないものになる。

完璧に自動車やバイクを生成しないようにベクトルの引き算を行おうとすると、ありきたりなものしか生成されなくなるというトレードオフの関係があるようにも思う。

例えば名詞の近くに名詞をおけば結合された特徴を持った画像が生成される。

### ③学習データの総量をイメージする

例えば以下のようなプロンプトを考える

"car, doraemon, 8k detail" みたいな文を考えたとする。そうすると当然ドラえもんよりも車の画像の学習データの方が多いと推測できるので、車の画像が生成されやすくなる。せいぜい、車にドラえもんぽい色や絵がつくくらいである。

![grasshopper-fc4c57b1-f25a-4125-826f-816f6e1a06fc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/72475402-a2ec-8c05-e319-cc80fc1ad02e.png)

![grasshopper-837b9f92-d838-4119-827c-5ac3dc834026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/e7ed5eb1-7dd0-cd34-3c71-24ae4bf7d544.png)

![grasshopper-e3e6b14c-63a5-4183-93d8-4400becc003d.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33329/7f138f03-0f93-3b2a-d47a-9dd3862a4262.png)

つまり、単語の足し算を行うとより学習データの多い単語が勝つということである。

## 結論

頭の中で単語の足し算や引き算をイメージして、この記事であげたルールを意識すると上手くいきやすいと思う。

（与太話の域を出ないので、こういう論文があるよと教えてくれるとすごく嬉しいです。）
ngrokにアクセスできない！

# はじめに
### ngrokとは？
ローカル環境のwebサーバを外部公開できるサービス。
ngrokをインストールし、以下コマンドを入力すると外部公開用のURLが発行され、
localhost:3000の内容を外部に公開することができます。
`ngrok http ポート番号`
※公開を止める時は「Ctrl + c」でいつでも公開停止できます

インストール方法については多数公開されているので割愛。
参考ページ：
https://labo.kon-ruri.co.jp/ngrok/

### 使いどころ
自分は以下のケースでよく利用します。
①自分は一時的にクライアントに挙動を確認してもらう時
②外部サービスとの連携時

# 本題
### 発生した問題
使いどころ②の外部サービスとの連携時に発生。
拡張機能を使用してwebサイトからエンドポイント（本番環境）にアクセスする実装があり、
エンドポイントをngrokで発行したURLに変更してテストを行っていたところ、
拡張機能からのアクセスがうまくいかない現象が発生した。

### 原因
ngrokは無料で使えるツールですが、無料の場合以下注意が必要
・発行するURLが都度変わる
・アクセス時に（初回のみ？）以下のYou are about to visit画面を挟む
![ERR_NGROK_6024_-_You_are_about_to_visit_1912-150-249-201-50_ngrok-free_app__served_by_150_249_201_50__This_website_is_served_for_free_through_ngrok_com__You_should_only_visit_this_website_if_you_trust_whoever_sent_the_link_to_you_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083940/1132a514-0ee1-6713-087c-efab6842cdc4.png)


今回は「You are about to visit」画面を挟むという仕様上、
拡張機能からエンドポイントにアクセスした際、
自動で「visit site」を押すことができずアクセスできていなかった模様。
（有料アカウントで試したところこの問題は発生しなかった）

### 解決方法
[ModHeader](https://chrome.google.com/webstore/detail/modheader-modify-http-hea/idgpnmonknjnojddfkpgkljpfnnfcklj)というgoogle拡張機能を使用して、
リクエストヘッダーのkeyを`ngrok-skip-browser-warning`に変更する（valueはなんでもいいらしい）。
![スクリーンショット_2023_10_01_4_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3083940/ac094dfa-0b34-d9fd-ca86-148aedb2cee6.png)

解決に導いてくれたサイト様：
https://zenn.dev/kamimi01/scraps/d92768a0edd0c4


有料アカウントと無料アカウント両方持っていたので気付けたが、
結構時間がかかったので同じような問題に直面した人の役に立てば幸いです。

余談ですがngrokは「エングロック」と読むらしいです（僕は「エンジンロック」って読んでました）。