OmniAICreator/Qiita-1.07M huggingface dataset:
Google Cloud Runでdeployできないエラー備忘録

# 場面
GCP Cloud Runの[公式tutorial](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-nodejs-service?hl=ja)実行中
    
# 環境
WSL2 Ubuntu
Google Cloud SDK 463.0.0
node v21.5.0

# エラーメッセージの確認
[公式tutorial](https://cloud.google.com/run/docs/quickstarts/build-and-deploy/deploy-nodejs-service?hl=ja)の以下のコード実行時に発生
```sh
gcloud run deploy
```
コンソール画面にログ確認用のURLが表示されるので、ブラウザでチェック


# エラーメッセージ
```
Step #1: ERROR: failed to build: executing lifecycle. This may be the result of using an untrusted builder: failed with status code: 20
Finished Step #1
ERROR
ERROR: build step 1 "gcr.io/k8s-skaffold/pack" failed: step exited with non-zero status: 1
```

# 解釈
GCPのコンソール画面でCloud Buildの権限設定が完了していなかったことが原因
以下にアクセスし、権限を編集。
- Cloud Run -> 有効
- Cloud Build -> 有効

https://console.cloud.google.com/cloud-build/settings/service-account?hl=ja&project=<あなたのプロジェクトID>

![image.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2989725/05558b01-6a5c-3748-59e6-d4684478c12a.jpeg)
zshのプロンプトが見やすく変えたの巻

どーも、ogimanです。

本日はmacOSのzshのプロンプトが見にくかったのでカスタマイズしました。
その内容をメモっときます。

## ゴール
![スクリーンショット 2024-02-10 11.44.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144316/aa3be4f4-f495-8263-f149-e9dd0f341f0c.png)
![スクリーンショット 2024-02-10 11.46.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144316/faa33d79-52d7-7f0c-5c2d-626463732642.png)
![スクリーンショット 2024-02-10 11.47.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144316/c8daa25f-524e-06ac-a7c2-2ea08a593c78.png)


- 基本プロンプトを左へ
  - もともと、gitも左に寄せていたのですが、パスとブランチ名で長くなり過ぎるのが好みませんでした。
- gitのプロンプトを右へ
  - カレントブランチを表示させる
  - ファイル追加で変化をつける
  - ステージングで変化をつける
 


## 設定した内容

```

# 基本プロンプト（左）
PROMPT='[%m:%F{green}%~%f] %F{yellow}$%f '

# gitのプロンプト（右）
autoload -Uz vcs_info
setopt prompt_subst
zstyle ':vcs_info:git:*' check-for-changes true
zstyle ':vcs_info:git:*' stagedstr "%F{blue}!"
zstyle ':vcs_info:git:*' unstagedstr "%F{green}+"
zstyle ':vcs_info:*' formats "%F{08m}%c%u[%b]%f"
zstyle ':vcs_info:*' actionformats '[%b|%a]'
precmd () { vcs_info }

RPROMPT='$vcs_info_msg_0_'


```

## 設定の説明
- `autoload -Uz vcs_info`:
  - vcs_infoの定義みたいなもの

- `setopt prompt_subst`:
  - 後述のvcs_info_msg_0_を使うのに必要な設定

- `zstyle ':vcs_info:git:*' check-for-changes true`：
  - Gitリポジトリの状態を確認するために設定する
    - 変更されたファイルがあるかどうかを確認しているよう

- `zstyle ':vcs_info:git:*' stagedstr "%F{blue}!i"`：
  - ステージングされた（git addされた）ファイルがある場合に表示される文字列のスタイルを設定する
    - %F{blue}は青色（[好きな色に変えてね♪](https://wiki.archlinux.org/title/zsh#Colors)）
    - !を表示する（！マークでなくても良い）

- `zstyle ':vcs_info:git:*' unstagedstr "%F{green}+"`：
  - ステージングされていない（変更されたがgit addされていない）ファイルがある場合に表示される文字列のスタイルを設定する
    - %F{green}は緑色で表示する（[好きな色に変えてね♪](https://wiki.archlinux.org/title/zsh#Colors)）
    - +を表示する（+マークでなくても良い）

- `zstyle ':vcs_info:*' formats "%F{green}%c%u[%b]%f"`：
  - vcs_info関数が表示する形式を設定する
    - %F{green}と%fは、テキストの色（[好きな色に変えてね♪](https://wiki.archlinux.org/title/zsh#Colors)）
    - %cはstagedstrの文字列
    - %uはunstagedstrの文字列
    - %bはカレントブランチ名

- `zstyle ':vcs_info:*' actionformats '[%b|%a]'`：
  - vcs_info関数がアクション（例：マージ中、リベース中）の場合に表示する形式を設定する。
    - %bはカレントブランチ名
    - %aはアクション（行われている操作）
- `precmd () { vcs_info }`:
  - vcs_info を呼び出す


- `RPROMPT='$vcs_info_msg_0_'`：
  - 右プロンプトの設定
  - vcs_info_msg_0_にはzstyleでカスタマイズした内容が代入される

- `PROMPT='[%m:%F{green}%~%f] %F{yellow}$%f'`：
  - 左プロンプトの設定。
    - マシン名（%m）
    - カレントディレクトリ（%~）
    - プロンプト記号（$）を含みます
    - %F{color}と%fは、テキストの色（[好きな色に変えてね♪](https://wiki.archlinux.org/title/zsh#Colors)）


## 設定の反映

- zshrcに設定を追記

  ```
  vi ~/.zshrc
  ```

- 設定の反映

  ```
  source ~/.zshrc
  ```



## 参考(感謝！)
- [`zshcontrib(1)`マニュアル](https://zsh.sourceforge.io/Doc/Release/User-Contributions.html#Version-Control-Information)
- [macOSのzshの設定を個人的に使いやすいようにカスタマイズした](https://masahosono.dev/posts/my-zshrc)
- [zsh - archlinux](https://wiki.archlinux.org/title/zsh#Colors)


## 最後に
ちょっとした変更で使いやすくなりまっす！
たかがプロンプト、されどプロンプト〜〜〜:point_up:

この記事が少しでも参考になったら、 :heart: お願いします！
励みになります♪

ではでは、良い一日を〜
Dockerfileの実行ユーザーを変更する

# Expected
1. Dockerfileの実行ユーザーをroot　-> aliceに変更したい。
1. aliceでrailsアプリを作成したい（権限をaliceにしたい）

# Actual
- もっと色々あるんだろうけど、最近勉強中のシェルコマンドでやってみた。

```Dockerfile
FROM ruby:3.0.1

# 環境変数の設定
ENV DOCKER_OPERATION_USER=alice
ENV APPLICATION_NAME=blog

# dockerグループを作成
RUN groupadd docker

# dockerグループに所属するユーザーを作成
RUN useradd -g docker -u 1000 ${DOCKER_OPERATION_USER} -m

# sudo権限付与
RUN usermod -aG sudo ${DOCKER_OPERATION_USER}

# 必要最低限のツールを入れる
RUN apt-get update -qq && apt-get install -y sqlite3 vim

# ユーザーの切り替え
USER ${DOCKER_OPERATION_USER}

# railsをインストール
RUN gem install rails

# アプリケーションディレクトリを作成
RUN mkdir /home/${DOCKER_OPERATION_USER}/${APPLICATION_NAME}

# アプリケーションディレクトリを作業用ディレクトリに設定
WORKDIR /home/${DOCKER_OPERATION_USER}/${APPLICATION_NAME}

# railsアプリ作成（初回のみ）
RUN rails new .
```
【React】onClickとhandleClickの違い・使いどころ


## Reactにおける`onClick`と`hancleClick`の違いについて

TypeScriptとNext.jsを使ったWebアプリケーション制作にチャレンジしていますが、それ以外にもReact構文を頻繁に使う機会があるため、Reactもしっかり学ぶ必要性があると感じました。

Reactの関数コンポーネントを実装するなかで疑問に思った点として、ロジックを複数の処理に分けて実装するという点です。

まず理解できていない点としてonClickとhandleClick。ボタンを押したときに数字がカウントアップするようなロジックを作りたいとき、onClickで関数hendleClickに渡し、実際のカウントアップの処理はhandleClickで表現する、、、。みたいな実装方法を行う場面があります。

なぜ、ボタンをクリック〜数字カウントアップという2つの挙動を実現するために、2つの関数コンポーネントに分ける必要があるのか？という疑問があります。

この疑問は今後、幾度となく訪れる場面があると想定されるため、きちんと理解して腹落ちした状態にしておきたいと思い、よくよく調べることにしました。

本記事の執筆者はエンジニア未経験。Ruby on Railsなどのバックエンドを中心に学んできましたが、昨今のフロントエンドにおけるReact・TypeScriptなどのモダンJavaScript系の技術の重要度を鑑みて、これらの学習を進めています。

<br>

## onClickとhandleClickの違い

onClickとhandleClickの違いについて、まずはそれぞれの特徴を確認していきます。

### ***onClick***

`onClick`はボタンなどをクリックしたタイミングで特定のアクションを発火させるトリガーとしての役割を担うために用いられる事が一般的であるようです。

正確にはreturn文の中で用いられ、buttonタグなどで扱う事ができるプロパティ（要素）として存在します。

```jsx
<button onClick={handleClick}>ボタン</button>
```


### ***handleClick***

`handleClick`は、ハンドルの名の通り、クリックしたときに「どんなアクションを」起こすかを定義するさいに用いられるメソッド・関数の命名として用いられます。


### `onClick`はトリガー／ `handleClick`はアクション

以上を踏まえると、`onClick`はイベント発火のトリガーとしての役割を担い、具体的なアクションの内容は`handleClick`で担う。というような使い所の違いがあるという事ですね。


<br>

## イベントへの応答の認識を改める

例えば、このような記述をした場合、「渡す」「呼び出す」のどちらなのかという点において、私は認識を誤っていたようです。

```jsx
<button onClick={handleClick}>
```

:::note warn
- `handleClick`を`渡す⭕️`
- `handleClick`を`呼び出す❌`
:::

`onClick`で指定した`handleClick`は、渡すという表現が正しいようです。ボタンをクリックしたときに、その反応として`hancleClick`関数が発火し、アクションが発動するという挙動となります。微妙な言葉の違いですが、正しく理解することで後々の学習や実装で誤った理解が大きな失敗につながらないよう、うまく言語化できるように心がけたいですね。


## イベントハンドラーは他にもいっぱいある

`handleClick`はクリックした時に何かをするというアクションを定義したいときに用いるイベントハンドラーでありますが、他にもイベントハンドラーはReactにて複数用意されています。

:::note info
- `onChange`　フォームの入力値や選択肢に変更があったときに起きるイベントを定義する。
- `onMousemove` マウスを動かしているときに何か視覚効果をつけたいなどのイベントを定義するときに使う。
- `onSelect / onSelectStart` ページがリロードされたときや、ページが切り替わるタイミングでアクションを起こしたいときに使用するイベントハンドラー。

などなど.....
:::


## 公式ドキュメントでチャレンジ問題ができる

https://ja.react.dev/learn/responding-to-events#challenges

公式ドキュメントにはイベントへの応答に関する実装例などを中心に、理解を深められる解説が多く掲載されています。また、チャレンジ問題も用意されているので、イベント処理に対する理解を深めるためにチャレンジしてみても良いでしょう。



## 参考サイト

https://ja.react.dev/learn/responding-to-events

https://qiita.com/jima-r20/items/839da7c2f26366491298
LWC：Write about LayoutCard

**LayoutCardを使用した画面**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/e7fb40d5-ac5b-261b-a765-843c36b62810.png)
**画面の大きさによって自動的に一列になってくれます**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3330192/7a7bc31e-b5aa-08c1-192b-4602006b0efd.png)
```html
<template>
    <lightning-card icon-name="custom:custom57" title="LayoutCard">
        <lightning-layout multiple-rows="true">
            <lightning-layout-item size="12" padding="horizontal-small">
                <lightning-input label="item1"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="4" padding="horizontal-small">
                <lightning-input label="item2"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="4" padding="horizontal-small">
                <lightning-input label="item3"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="4" padding="horizontal-small">
                <lightning-input label="item4"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="6" padding="horizontal-small">
                <lightning-input label="item5"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="6" padding="horizontal-small">
                <lightning-input label="item6"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="3" padding="horizontal-small">
                <lightning-input label="item7"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="3" padding="horizontal-small">
                <lightning-input label="item8"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="3" padding="horizontal-small">
                <lightning-input label="item9"></lightning-input>
            </lightning-layout-item>
            <lightning-layout-item size="12" large-device-size="3" padding="horizontal-small">
                <lightning-input label="item10"></lightning-input>
            </lightning-layout-item>
        </lightning-layout>
    </lightning-card>   
</template>
```
メモ：
multiple-rows="true"　→複数列での表示が可能になる、定義しない場合、一行目のみ表示されます。

lightning-layout-item　size=12/6/3
この size では、画面幅を12分割したうちのいくつ分の幅にするかを指定します
2列表示なら、6にします。
3列表示なら、4にします。
4列表示なら、3にします。

small-device-size属性はスマートフォン、
medium-device-size属性はタブレット、
large-device-sizeデスクトップまたはそれ以上のデバイスを示します。
Raspberry Piでプログラムを自動起動(2)_autostart

# Raspberry Piで自動起動する方法
 [参考の記事](https://qiita.com/karaage0703/items/ed18f318a1775b28eab4)によると大きく5つがあるようです。
 本記事はautostartを使った自動起動を試行た際のメモを記載しておきます。

* /etc/rc.local
* autostart　　　　　←今回の記事
* crontab @reboot
* /etc/init.d
* systemd　　　　　　←別の記事　[Raspberry Piでプログラムを自動起動(1)_systemd]()

autostartを使用した自動起動は(Raspbian Buster以降)
GUIのプログラムを起動時に実行したいときに使います。

# 1. 起動したい`.py`　`.sh`を準備する
Ex. momoの自動起動の場合
`home/pi/momo…/auto_launch.sh`
`echo`の部分は確認用なので記述は任意

```bash:auto_launch.shの中
#!/bin/sh
echo Start auto_launch
sleep 15
# google.comにpingして通信状態を確認する。
while true
do
	if ping -c 1 google.com > /dev/null; then
		echo "connected network"
		break
	else
		echo "retry"
		sleep 2
	fi	
	sleep 1
done
sleep 2
echo Start video capturecd /home/pi/momo*****/
#起動したいプログラムを記述する。
./momo — no-audio- *****
```

* bashファイルの起動確認
```bash:home/pi/mo***/
bash auto_launch.sh
```
 * 所望の.shや.pyが実行できることを確認しておく。

 
# 2.autostartファイルの作成、編集する
　以下コマンドを実行して、autostartファイルの雛形を、ホームディレクトリのコンフィグにコピーします。

```bash:autostartファイルの雛形をコピー
mkdir -p ~/.config/lxsession/LXDE-pi
cp /etc/xdg/lxsession/LXDE-pi/autostart ~/.config/lxsession/LXDE-pi/
```
autostartファイルに実行したコマンドを追記する。

```bash:autostartをvimで編集
cd ~/.config/lxsession/LXDE-pi/
sudo vim atuostart
```

```bash:autostart
****************************************
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@lxterminal -e “/home/pi/momo-*****/auto_launch.sh"　　#<---ここを追加
****************************************
```

# 3.autostartの機能
## コマンドラインに表示
```
echo "hoge hoge"
```
 ""で囲むと文字列として認識される。
 
## スクリーンセーバー
```
$ xset s on #スクリーンセーバーをオン
$ xset s off #スクリーンセーバーをオフ
```
## ネットワーク接続を待つ 
　googleにpingして結果を判断に使う。(例)
```bash:auto_launch.sh
#!/bin/sh
while true
do
    ping -t 6 -i 2 www.google.com 1>/dev/null 2>/dev/null
    if [ $? -ne 0 ]
    then
        echo "Network Has Gone"
        if [ `cat ~/.netcheck.last` = "OK" ]
        then
            say "Network Has Gone"
        fi
        echo "Error" > ~/.netcheck.last
        sleep 6
    else
        echo "Network Has Come"
        if [ `cat ~/.netcheck.last` = "Error" ]
        then
            say "Network Has Come"
        fi
        echo "OK" > ~/.netcheck.last
    fi
done
```

以上


# 参考サイト

* [シェルスクリプトプログラミング](https://manual.atmark-techno.com/armadillo-guide/armadillo-guide-2_ja-2.2.0/ch05.html)
* [Raspberry Piで pythonスクリプト を 自動起動 する方法](http://gijin77.blog.jp/archives/30459475.html)
* [切れやすいWi-fiに自動で再接続するshell](https://deadcode.hatenablog.jp/entry/2018/07/12/192102)
* [インターネットへの到達性を定期的に監視して、状態が変わるとしゃべる](https://gist.github.com/yanbe/967820)
【M1,M2,M3 Mac】Homebrewがインストールできない時の解決方法

# 原因
ターミナルの初期設定でRosettaが有効になっていない
→有効にしたらインストールできるよ

# 手順1（アプリケーションフォルダを開く）
## Finderを開く
![スクリーンショット 2024-02-10 10.38.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/68c8a30a-f80a-fe9d-5635-c75383281c4b.png)

## 「ユーティリティ」フォルダに入る
![スクリーンショット 2024-02-10 10.42.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/ab8da0b1-a9ad-c628-e221-a32f4cd15e9f.png)


# 手順2（ターミナルを右クリック）
## 「ターミナル」を右クリックして「情報を見る」をクリック
![スクリーンショット 2024-02-10 10.45.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/a4a4b3e5-4e16-829d-e413-6dbe95499b59.png)


# 手順3（「情報を見る」からRosettaを有効にする）
## 「Rosettaを使用して開く」にチェックを入れる（クリック）
![スクリーンショット 2024-02-10 10.48.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/78b36a40-bdfa-dc66-0f3a-bf428a775b1d.png)

# 手順4（Homebrewをインストールする）

## ターミナルを起動します
![スクリーンショット 2024-02-10 11.00.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/e0516c09-ce46-f4a0-ee50-11df8d286906.png)


## ターミナルに以下を入力して実行する

```
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
```

![スクリーンショット 2024-02-10 11.01.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/8621c932-7a90-6a1a-e5b8-6a29f529e533.png)

## パスワードを求められるので、ログイン時のパスワードをパスワードを入力
パスワードを入力して「Enter」キーを押します

![スクリーンショット 2024-02-10 10.52.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/8cb39d04-5bb3-58bc-1926-6ebc0426e5d3.png)

## 以下のような文言が出力されていたら完了です👍
![スクリーンショット 2024-02-10 10.54.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/845eb333-4c26-4e7d-a691-787f47f11319.png)

## 「brew --version」を実行してみよう

こんな風に「Homebrew ?.?.?（?はバージョンの数字です）」と出力されたらインストール完了！！
お疲れ様でした♪( ´θ｀)ノ

![スクリーンショット 2024-02-10 10.56.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985747/010ec16a-c644-5a57-b3b5-84ac0b2000ed.png)
「やさしい性格診断」というウェブアプリを制作しました #MBTI


最近、新しいウェブアプリ「[やさしい性格診断](https://personality.tokyo/?trk=qt-aa)」を制作しました。このアプリでは、MBTI（Myers-Briggs Type Indicator）やエニアグラムなど、様々な性格タイプや性格特性に関する情報をまとめ、分かりやすく提供しています。本記事では、この新しいウェブアプリについて詳しくご紹介させていただきます。

👉 https://personality.tokyo/?trk=qt-ab

## ウェブアプリの特徴

### 1. やさしい性格診断
「やさしい性格診断」は、ユーザーフレンドリーかつシンプルな性格診断を提供しています。利用者が気軽に楽しむことができ、自分の性格や他の性格タイプについて理解を深める手助けとなります。

### 2. MBTIやエニアグラムなど多彩な情報
アプリ内では、MBTIやエニアグラムなど、様々な性格分類ツールに基づく情報が豊富に揃っています。ユーザーは自身の性格タイプを知るだけでなく、他のタイプについても学びながら楽しむことができます。

### 3. 技術的な側面
「やさしい性格診断」では、Next.jsを採用しています。Next.jsはReactフレームワークの一種であり、高いパフォーマンスと使いやすさを両立させています。また、デザインにはReactとTailwind CSSを組み合わせ、優れたユーザーエクスペリエンスを提供しています。

## 制作の背景

### なぜ「やさしい性格診断」を制作したのか
現代社会では、自分の性格や他者とのコミュニケーションに関する理解がますます重要となっています。しかし、複雑で難解な性格診断ツールが多く、気軽に利用することが難しい状況でした。そこで、シンプルで理解しやすい性格診断を提供し、多くの人が気軽に利用できる環境を作りたいと考え、このアプリを制作しました。

## まとめ
「やさしい性格診断」は、MBTIやエニアグラムなどの性格分類ツールをベースにした、シンプルで理解しやすい性格診断を提供するウェブアプリです。Next.js、React、Tailwind CSSを用いた技術的な取り組みにより、優れたデザインと使いやすさを実現しています。是非一度お試しいただければ幸いです。

（参考）

- [MBTIで人間関係を潤滑に #チームビルディング - Qiita](https://qiita.com/ikariya-shuma/items/be3c3e6e68d8f8226598)
- [MBTI診断から始める自己研鑽 #個人開発 - Qiita](https://qiita.com/Ayako_0224/items/5104d923edd78168448c)
- [性格診断の分布で各国をクラスタリングしてみた【16-personalities】【階層型クラスタリング】 #Python - Qiita](https://qiita.com/RisaM/items/f5223c93fdfa29fa7059)
- [デジタル庁のサイト、その後… #Next.js - Qiita](https://qiita.com/mu_tomoya/items/14cd7c7ca4c6d1af96ca)
- [Next.js公式examples集を分類（2022年7月版） #React - Qiita](https://qiita.com/masakinihirota/items/99054b9f9cf428881617)
指定された位置に文字列を追加する

>文字列 S , T と、整数 N が与えられるので、 S の N 文字目の後ろに T を挿入した文字列を出力してください。

というプログラム問題をRubyで解きました。

```ruby
str1 = gets.chomp
str2 = gets.chomp
num = gets.to_i
ans = ""
array1 = []
hcount = str1.size()
for i in 0...hcount do
    w_str = str1[i].to_s
    array1.push(w_str)
end

array1.insert(num,str2)
N = array1.size()
for j in 0...N do
    w_str2 = array1[j].to_s
    ans = ans + w_str2
end

puts ans
```

baseという文字列にballという文字列を文字列の4要素目に挿入しました。

![ruby1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710584/74251e5a-500b-1314-4b6b-787b93ac9268.jpeg)
プロ野球の順位表のデータから順位予測のモデルを作るのは難しい

# はじめに
冬から春先にかけてプロ野球の解説者が新シーズンの順位予想をします。
その順位予想は「上位にK藤、Y田、Y川がいるから⚪︎位」のように感覚的で抽象的であると思いましたので、機械学習を用いて順位予測ができないか手軽にコードを書いてみましたが、精度の高くない順位予測モデルが出来上がりましたので作業内容を一部だけ公開します。

![resized_futuristic_baseball_stadium.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/603047/37a36972-53ef-856d-1382-7b2d193eb841.png)
# つくるもの
パリーグの順位表を独自集計しているサイト（NPBの公式のものを使用しようと思いましたがカラムが少ないため、非公式なものを使用しましたがデータの選定に関して参考にしないでください）からデータを引用し、決定木の手法で順位予測モデルを作成する。
打率や打点、防御率などをリクエストに詰めて、このモデルを呼び出すと順位を予測するREST APIを作成（今回はモデル作成まで）

・データセット引用元サイト
https://baseballdata.jp/p/#

# 環境
```
python       :3.12.1
pandas       :2.2.0
pip          :23.3.2
scikit-learn :1.4.0
```

# ディレクトリ構成
データセットをdataディレクトリに配置して、rank_model.pyで読み込むという構成
```
app/
 - data/
  - 2021.json
  - 2022.json
  - 2023.json
 - rank_model.py
 ```

# コード
```python:rank_model.py
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score
from joblib import dump


def load_data(years):
    all_data = pd.DataFrame()
    for year in years:
        with open(f"data/{year}.json", "r") as file:
            year_data = pd.read_json(file)
            all_data = pd.concat([all_data, year_data], ignore_index=True)
    return all_data


def preprocess_data(data):
    features = data.drop(['rank', 'team'], axis=1)
    target = data['rank']
    return train_test_split(features, target, test_size=0.2, random_state=42)


def train_model(X_train, y_train):
    model = RandomForestClassifier(n_estimators=100, random_state=42)
    model.fit(X_train, y_train)
    return model


def evaluate_model(model, X_test, y_test):
    predictions = model.predict(X_test)
    accuracy = accuracy_score(y_test, predictions)
    print(f'精度: {accuracy:.2f}')


def save_model(model, filename):
    dump(model, filename)


# データの読み込み
years = ['2023', '2022', '2021']
data = load_data(years)

# データの前処理
X_train, X_test, y_train, y_test = preprocess_data(data)

# モデルの訓練
model = train_model(X_train, y_train)

# モデルの評価
evaluate_model(model, X_test, y_test)

# モデルの保存
save_model(model, 'rank_model.joblib')
```

# 実行結果
```
$ python rank_model.py
精度: 0.20
```

精度が0.20という低いモデルができました。

パリーグは6球団あるので、ランダムに順位を予測した場合は1/6、つまり16.6%
今回の精度0.20は20%なので、順位予測モデルとして有効的ではありません。せめて0.50にしたいです。

# 原因
順位予測は、打率などの数値から純粋に導き出すのが難しいものだと思われます。
打率や打点、防御率など順位と相関がありますが、怪我の離脱や移動を含めた試合スケジュール、天候などの外的要因やチームの雰囲気やチームスタッフのマネジメント・コーチングなどの相互作用が影響するのではないかと思われます。

また、今回使用した機械学習のアルゴリズムは決定木で、データセットには1年毎に6行しかデータがなく、決定木にはデータ数が少なかったと思われます。

# 改善案
+ 2020年以前の成績などデータを増やす
+ クロスバリデーションを使う
+ ハイパーパラメータの調整(train_model関数のRandomForestClassifier)

# おわりに
今回はざっくりモデルを作成してみたので、あまり参考にならないコード、低い精度になったと思います。
コードを修正して精度を高めることを試みたいと思います。
また、解説者には「⚪︎⚪︎選手の加入で打点が50打点増えると思うので首位を狙えると思います」など数値的な発言をすると、よりプロ野球ファンが興奮すると思います。期待します。

↓続き

https://qiita.com/wooooo/items/00d12e2a143843aa0287

# ⚾️おまけ⚾️
私が好きな野球系YouTuberです

https://www.youtube.com/@kitta-baseball
Rails で CSV と TSV をダウンロード（失敗談）

Rails で，あるモデルのデータ一覧を CSV でも TSV でもダウンロードできるようにするとき，ちょっとハマったのでメモ。

# やりたかったこと

ItemsController の `index` アクションで


```rb
def index
  @items = Item.all
  respond_to do |format|
    format.html do
    end

    format.csv do
    end

    format.tsv do
    end
  end
end
```


みたいなことがしたかった。

要するに，リクエストが

* `/items` なら HTML を
* `/items.csv` なら CSV を
* `/items.tsv` なら TSV を

返す，と。

んで，CSV の場合のテンプレートは Ruby で記述し `/app/views/items/index.csv.ruby` というファイルで提供する。

ここまではよくある話。

では TSV のテンプレートをどうするか？

# 最初にやった方法

TSV 用のテンプレートを CSV 用とは別に用意してもいいんだが，ほぼカラム区切りが違うくらい。CSV ライブラリーで使う `col_sep` オプションね。
だから，テンプレートを共通化したい。

テンプレート側ではインスタンス変数 `@col_sep` を参照することにしよう。
この変数はアクションメソッド側で与えるので

```rb
format.tsv do
  @col_set = "\t"
end
```

のようにするわけだが，これだけだとテンプレートファイル `index.csv.ruby` を見つけてくれない。
そこで，

```rb
format.tsv do
  @col_set = "\t"
  render "index.csv"
end
```

のように書いた。
これで，狙い通り CSV 用のテンプレートを使ってレンダリングしてくれる。

# 警告が出る

ただし，これだと

```
DEPRECATION WARNING: Rendering actions with '.' in the name is deprecated: items/index.csv 
```

といった警告が出る。テンプレートを指定するのに `.` を使っちゃいけないのだ。

ええっと，じゃあ望ましい書き方は？

# 試行錯誤

ここから迷走しだした。いろいろ試行錯誤してもうまくいかない。`format` オプションか？とか思って

```rb
render "index", format: "tsv"
```

とかやってもテンプレートを見つけてくれない。
文字列じゃなくてシンボルで与えるのか，とか，オプションは `format` じゃなくて `formats`（s がつく）だったか，とかは分かったのだけれど。

# 解決

しばらく格闘してふと気付いた。
レンダリングしてほしいのは TSV だが，呼び出したいテンプレートは CSV 用（のファイル名）だ。だから `formats` オプションには `:tsv` ではなく `:csv` を与えなければならなかったんである。そりゃそうだ！
これでようやく解決。

なお，いまの場合，アクションが `index` で，テンプレート名と一致しているから，`render` に `"index"` を渡す必要はない。

つまり，最もシンプルには

```rb
render formats: :csv
```

と書けばよいのであった。
RaspberryPiを連続稼働で設定するためのメモ

Raspberry Piを連続稼働させるための設定をしたのでメモ

# 環境
Raspberry Pi4
microSD 8GB
有線LAN

# 参考
https://ponkichi.blog/raspberry-setup/

# Rasbianのインストール
環境としてRasbianを使用する。
Raspberry Pi Imagerを使ってRasbian OS Lite 64bitをインストールする。
パッケージを最新化する。
```
sudo apt update -y
sudo apt upgrade -y
```

# Swap機能の抑止
SWAPの読み書きが発生するとSDカードの書き込み回数を消費してしまうので、無効化する。
```
sudo apt autoremove -y dphys-swapfile
```

# テンポラリディレクトリのRAMディスク化
テンポラリディレクトリをメモリ上に展開することで、SDカードの書き込み回数を削減する。
テンポラリなので、電源断で消えてもいいはず。

/etc/fstabに以下の定義行を追加

```
tmpfs           /tmp            tmpfs   defaults,size=256m,noatime,mode=1777      0       0
tmpfs           /var/tmp        tmpfs   defaults,size=16m,noatime,mode=1777      0       0
tmpfs           /var/log        tmpfs   defaults,size=32m,noatime,mode=0755
```

追加したら、再起動して設定を反映させる。
```
reboot
```

再起動後にdfコマンドでマウントできていることを確認します。
```
$ df
Filesystem     1K-blocks    Used Available Use% Mounted on
udev             1672432       0   1672432   0% /dev
tmpfs             388432    5980    382452   2% /run
/dev/mmcblk0p2   7072624 2017408   4676144  31% /
tmpfs            1942152       0   1942152   0% /dev/shm
tmpfs               5120      16      5104   1% /run/lock
tmpfs             262144       0    262144   0% /tmp
tmpfs              32768       8     32760   1% /var/log
tmpfs              16384       0     16384   0% /var/tmp
/dev/mmcblk0p1    522232   62394    459838  12% /boot/firmware
tmpfs             388428       0    388428   0% /run/user/1000
```
エンジニア1年目にオススメしたいUdemy教材

# Rails
###  【入門のひとつ先へ】Ruby on Railsで基本の申し込みフォームを作ろう【現役エンジニアが実践的手法を徹底解説】

https://www.udemy.com/course/rails-forms/

Railsのフォーム作成から、ActionMailerによるメール送信やsidekiqによる非同期処理などを実装した。
フォーム作成に関わる全般的な知識を習得できた。


# JavaScript

### 【2023年最新】【JavaScript＆CSS】ガチで学びたい人のためのWEB開発実践入門（フロントエンド編）

https://www.udemy.com/course/front-dev-tutorial/

CSSとJavaScriptの基礎を体系的に学ぶことができた。
中でも、初めのCSSでは、普段何となく扱っていたものが、より深く理解することができた。
その流れで、JavaScriptについても基本的な動作を学ぶことができた。

### Node.jsで学ぶWebシステムとソフトウェア開発基礎！Node.js完全入門ガイド

https://www.udemy.com/course/nodejs-comp-guide/

JavaScriptの基本を学びながら、Node.jsの基礎やnpmのパッケージなどのフロントエンドに限らない範囲を学習できた。
特に、Express.jsフレームワークによる開発を行うことで、バックエンドにおいてもJavaScriptを活用できることを理解した。

# Git・GitHub
### もう絶対に忘れないGit・GitHub【Git 100本ノック+300枚の図解+丁寧な解説で長期記憶に焼き付けろ！】

https://www.udemy.com/course/git100test/

（これから受講予定）

# Linux
### 初心者OK！Linux入門：実務で必須のLinuxの知識を網羅

https://www.udemy.com/course/ok-linux/

Linuxサーバ上で、linuxコマンド操作しながら、基本的な動作を理解できた。
Linuxのカーネルの仕組みやディストリビューションなどの基礎知識も習得できた。


# Docker
### 初心者OK！Docker入門＋応用：ゼロからでも実務で使えるスキルが身に付ける

whttps://www.udemy.com/course/ok-docker/

Dockerでの環境構築からDockerコマンド、イメージやボリューム作成などの基本的な知識を身につけることができた。
また、最後に複数コンテナの環境構築を可能とするDocker Composeについても理解することができ、業務で扱うDockerの理解も高めることができた。

# AWS
### AWSコンテナサービス入門―AWSの基本からECS・Copilot CLI・CI/CD・App Runnerまで

https://www.udemy.com/course/aws-container/

AWSの基礎知識からECS on Fargateを用いたインフラ構築の基本を理解した。
ハンズオンで実際に画面操作することで、基本的なAWSの画面操作と機能について理解できた。
また、GitHub Actionsを用いた、AWSへの自動デプロイについても学べた。
プログラマー孔子「学如不及」


プログラマー孔子が言いました

リーナス・トーバルズ（Linus Torvalds）「ワタシハ リナックス チョットデキル」

https://twitter.com/shigetaka256/status/469062321176727552


# 漢文
> 子曰、学如不及、猶恐失之。

# 現代訳
> 先師がいわれた。――
>「学問は追いかけて逃がすまいとするような気持でやっても、なお取りにがすおそれがあるものだ。」


青空文庫
現代訳論語 下村湖人
https://www.aozora.gr.jp/cards/001097/files/43785_58836.html

# ポエム
私「プログラミング、完全に理解した！」
githubでプッシュするリポジトリを変更したい




まずは、現在のリポジトリをの情報ほ削除します。
```
git remote remove origin
```


githubで新しいリポジトリを作成します。
その後、下記のコマンドで新しいリポジトリ先とプロジェクトを関連づけてデータをプッシュします。
```
remote add origin git@github.XXXXXXXXXXXXXXXXXXX
branch -M main
push -u origin main
```
【Rails】パーシャル（部分テンプレート）内での変数の使用

# はじめに
この記事では学習中に出会ったエラーとその解決までの道のりを自分のために記録しています。
初学者のため、理解が不十分なところがあるかもしれません。
その場合はご指摘いただけると幸いです。

# 起こった問題
パーシャルにローカル変数を渡そうとしたが上手くいかなかった

# 結論
localsオプションを使用してローカル変数を渡すときは
```
<%= render partial: ‘パーシャル名’, locals: { ローカル変数名: インスタンス変数名} %>
```
の**partial**を省略せずに書く
またはpartialを省略するならlocalsも省略する

# 解決までの道のり
### 前提条件
- Solidusを使用してECサイトを作成中
- 商品カテゴリーページへのリンクを含むヘッダーをパーシャル化

### なぜパーシャル内でインスタンス変数を使用しないほうがいいのか？
パーシャルとコントローラーが結びついてしまうと、コントローラー内の変数を変更したときにパーシャル内の記述も変更しなければならなくなり、せっかくパーシャルとして切り出したのに使い勝手が悪くなる…という理由だと理解しました。
（間違っていたらそっと教えてください）

ちなみにlocalsの説明に出てくる例は
```
<%= render partial: 'shared/header', locals: { user: @user } %>
```
このようにインスタンス変数名とローカル変数が同じだと思うのですが
```
<%= render partial: 'shared/header', locals: { person: @user } %>
```
このように別の名前にしても大丈夫でした。
当たり前ではありますが気になったもので…。でも試しにやってみてとても混乱したので使うことはなさそうです。

### 発生したエラー
元の記述はこんな感じです。
```application_controller.rb
def set_categories
  @clothing = Spree::Taxon.where(name: "clothing")
end
```
```application.html.erb ※この記述ではエラーが出る
<%= render: 'layouts/header', locals: { clothing: @clothing } %>
```
```_category.html.erb
<% if clothing.present? %>
  <%= link_to clothing.name, category_path(clothing.id) %>
<% end %>
```

これで表示しようとするとこんなエラーが出ました。
```
ActionView:: Template: :Error (undefined local variable or method 'clothing' for #<ActionView:: Base: 0x0000000002ee50>
Did you mean? @clothing):
```
ローカル変数に値を渡せていない？

# 解決へ
冒頭にも書きましたが
```
<%= render partial: 'layouts/header', locals: { clothing: @clothing } %>
```
このように**render partial**と記述することで解決しました。
または、renderのままにするのであればlocalsも省略して下記のように書けます。
```
<%= render 'layouts/header', clothing: @clothing %>
```

# 感想
パーシャルを使うときは
```
<%= render ‘パーシャル名’ %>
```
と覚えていたので、localsオプションというのがあるんだな〜と思ってlocalsだけを追加してしまいエラーにハマりました。
ちゃんと解説を読めばわかることなのですが…。反省。

# 参考記事
- [【Rails】 部分テンプレートの使い方を徹底解説！](https://pikawaka.com/rails/partial_template)
- [partialではインスタンス変数を参照しない方がいい](https://qiita.com/mom0tomo/items/e1e3fd29729b2d112a48)
- [Rails　パーシャル(部分テンプレート)へローカル変数を渡したいとき](https://qiita.com/takannporo/items/a8ff93109afc3bc3bab4)
デール・カーネギの「人を動かす」原則の紹介


デール・カーネギー（Dale Carnegie、D・カーネギー、1888年 - 1955年）は、アメリカのビジネス書の著者であり、人間関係やコミュニケーションの分野で広く知られています。その影響力は、ビジネスに関する自己啓発書の中でも特に大きいものとされています。この記事では 30 歳前後の中堅社員向けに「人を動かす」原則を紹介します。


## 「人を動かす」について
デール・カーネギーの最も有名な著作が『人を動かす』です。この本は1936年に出版され、多くの言語に翻訳され、全世界で1500万部以上が販売されています。本書には、よい人間関係を築くための基本的な原則や、他者を動かす方法についての実践的なアドバイスが掲載されています。本に書かれているコミュニケーションやリーダーシップの原則は、今日でも広く受け入れられています。

![71EYxDtoyXL._SL1280_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3160433/adb6fbba-bbef-1383-79c6-54792d59ed76.jpeg)
    [”まんがでわかる D・カーネギーの「人を動かす」「道は開ける」、宝島社”](https://www.amazon.co.jp/dp/4800235618) より

ここでは 1936 年の英語版で挙げられている25 の原則を紹介します。

## 「人を動かす」25 の原則

## 基本的な 3 つの原則
- 批判、非難、不平を言わない
- 誠実に感謝する
- 相手に「欲しい」という気持ちを起こさせる
## 人に好かれる 6 つの原則
- 他人に誠実な関心を寄せる
- 笑顔で接する
- 人の名前は、その人にとって、どんな言語の中でも最も甘美で重要な音であることを忘れない
- 聞き上手になる。相手が自分のことを話すように促す
- 相手の興味を引くように話す
- 相手に重要であると思わせる
## 自分の考え方に人を引き込む 9 つの原則
- 議論を有利に進める唯一の方法は、議論を避けることである
- 相手の意見を尊重する。決して "あなたは間違っている "と言わない
- 自分が間違っていたら、すばやく、はっきりと認める
- 友好的に始める
- 相手にすぐに「はい、はい」と言わせる
- 相手に多くを語らせる
- 自分のアイデアだと相手に思わせる
- 相手の立場に立って物事を見ることを誠実に心がける
- 相手の考えや欲求に共感する
## リーダーになるための 7 つの原則
- 褒め、素直に感謝することから始める
- 部下のミスを間接的に指摘する
- 相手を批判する前に、自分の失敗について話す
- 直接命令するのではなく、質問する
- 相手の顔を立てる
- 些細な改善を褒め、改善するたびに褒める
- わずかな改善でも褒める。"心からの称賛と惜しみない賛辞を"

## 参考文献
- 人を動かす 改訂文庫版
https://www.amazon.co.jp/dp/442210134X/
- デール・カーネギー・トレーニング
https://www.dale-carnegie.co.jp/about/dale-carnegie-principles/
<!--
## 関連記事
- 「学問のすすめ」の紹介
https://qiita.com/mmake/items/8557fb7e1ded9afcd29d
-.
digコマンドを初めて使ってみた

## 概要

大先輩のインフラエンジニアさんに教えてもらってdigコマンドを初めて使ったので簡単にまとめておく。
※「初めて」とか言ってるけど下記の記事を書いたときに実行してた。

https://qiita.com/miriwo/items/8c4f472497ce3182ae0d

## 何をするコマンド？

ドメインを引数に実行することでそのドメインのDNSサーバーから情報を取得する事ができるコマンドである。

## 例

#### 基本の場合

下記のように実行する

```shell
dig 情報を得たいドメイン
```

上記を実行するとそのドメインを管理しているDNSが持っている公開できる情報すべてが返ってくる。例えば `dig qiita.com`などを実行すると「qiita.com」のドメインがルーティングされているIPアドレスを知ることができる。※DNS情報は公開されているので閲覧そのものは問題ない

試しに自分で保有しているドメインでdigコマンドを実行してみた。

```shell
dig miriwo.work
```

上記を実行すると下記のような出力が得られる。

```
; <<>> DiG 9.10.6 <<>> miriwo.work
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2912
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
;; QUESTION SECTION:
;miriwo.work.                   IN      A

;; AUTHORITY SECTION:
miriwo.work.            129     IN      SOA     01.dnsv.jp. hostmaster.dnsv.jp. 1707489657 3600 900 604800 300

;; Query time: 20 msec
;; SERVER: 2408:211:1580:ee00:5a52:8aff:fe63:9565#53(2408:211:1580:ee00:5a52:8aff:fe63:9565)
;; WHEN: Fri Feb 09 23:50:12 JST 2024
;; MSG SIZE  rcvd: 97
```

個々のレスポンスフィールドに分けて解説する。

##### ヘッダーセクション

下記部分についてまとめる。

```
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 2912
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1
```

この部分はヘッダーセクションと呼ばれる。
- opcode: QUERY
    - 問い合わせが標準的な食えるであることを示す。
- status: NOERROR,
    - 問題なく問い合わせが成功したことを示す。（エラーは無し）
- id: 2912
    - 問い合わせID（一意）
- flags: qr rd ra;
    - qrが応答メッセージであることを示す。
    - rdが再帰的な問い合わせをしたことを示す。
    - raが当該DNSサーバーが再帰的な問い合わせに対応しているかを示す。

ここから先は次のセクションで返されている情報の概要をまとめている。

- QUERY: 1,
    - 1つのクエリが実行されたことを示す。
- ANSWER: 0,
    - 応答が0件であることを示す。（Aレコードが未設定の場合0になるはず）
- AUTHORITY: 1,
    - ドメインのDNS設定の基本情報が1件返されたことを示す。
- ADDITIONAL: 1
    - 付加情報が1件返されたことを示す。

##### OPT PSEUDOSECTION

```
;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
```

これはEDNSのオプションや機能に関する情報を含んでいるらしい。

##### QUESTION SECTION

```
;; QUESTION SECTION:
;miriwo.work.                   IN      A
```

自分が問い合わせた内容（実際に実行されたクエリ）の情報が出ている。

##### AUTHORITY SECTION

```
;; AUTHORITY SECTION:
miriwo.work.            129     IN      SOA 
```

これは当該ドメインを管理しているDNSサーバーの情報が返される。

#### レコードタイプを指定して取得する場合

下記のようにドメイン指定のあとにレコードタイプ（AとかNSとかCNAMEとか）を指定することで、そのレコードの情報だけを取得することができる。

```shell
dig 情報を得たいドメイン レコードタイプ
```

#### IPからのドメイン逆引きする場合

IPを指定してドメインを逆引きすることもできるらしい。

```shell
dig -x IPアドレス
```

## 利用事例

筆者の場合、AWS SESの認証済みIDにてドメインを登録したときに吐き出されるDKIM用のCNAMEレコード追加が正しく行われているかを確認するために使用した。
下記を実行し、SESで吐き出された情報が正常にDNSに登録できているか確認した。

```
dig SESで吐き出されたDNSの「名前」 CNAME
```

結果が下記のように表示され「ANSWER SECTION」で返された値が、SESで吐き出されたDNSの「値」と一致していれば問題なく設定ができている。

![Makefile_—_dokupro-app.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/76542d90-48f9-56cc-bd87-fddbed0c561b.png)

## 関連記事

https://qiita.com/miriwo/items/9ab0541fd6409860bf11

https://qiita.com/miriwo/items/be1f22b81c5b11548181
配列からオブジェクトへ変換

# 配列からオブジェクトへ変換
配列からオブジェクトに変換する方法（キーは連番）の備忘録。

### 1. `reduce()`メソッドを用いる
```javascript
let array1 = [111, 222, 333, 444, 555, 666];

let obj = array1.reduce((acc, value, index) => {
    // acc は蓄積されるオブジェクト
    // value は現在の要素の値
    // index は現在のインデックス

    // スプレッド演算子を使用して、acc を展開し、新しいオブジェクトを作成し、新しいキーと値を追加する
    return { ...acc, ['key' + index]: value };
}, {} );

console.log(obj); 
// { key0: 111, key1: 222, key2: 333, key3: 444, key4: 555, key5: 666 }
```

#### ChatGPTによる説明

<details><summary>説明</summary>



このコードは、与えられた配列 `array1` をオブジェクトに変換するために、`Array.prototype.reduce()` メソッドを使用しています。`reduce()` メソッドは、配列を単一の値（この場合はオブジェクト）にまとめるための高階関数です。

具体的には、以下の手順で動作します：

1. `reduce()` メソッドの初期値として、空のオブジェクト `{}` が与えられます。これが `acc`（蓄積値）に初期設定されます
2. 配列 `array1` の各要素に対して、指定されたコールバック関数が実行されます
3. コールバック関数は、蓄積値 `acc`、現在の要素の値 `value`、および現在のインデックス `index` を引数として取ります
4. コールバック関数では、スプレッド演算子 `{...acc}` を使用して `acc` を展開し、新しいオブジェクトを作成します。また、新しいキーと値のペアを追加します。ここでは、`['key' + index]` をキーとして、`value` を値として追加しています
5. `reduce()` メソッドは、次のループで使用する蓄積値として、新しく作成されたオブジェクトを返します
6. 最後に、`reduce()` メソッドが完了した後、最終的なオブジェクトが `obj` 変数に格納されます

このコードを実行すると、`array1` の各要素が `obj` オブジェクトにキーとしてマッピングされ、インデックスに基づいたキーが作成されます。

</details>

### 2. `Object.fromEntries()`を用いる
```javascript
let array1 = [111, 222, 333, 444, 555, 666];
let obj = Object.fromEntries(array1.map((value, index) => ['key' + index, value]))
console.log(obj);
```
オブジェクトから配列に変換

## オブジェクトから配列に変換 
GAS（Google Apps Script）でオブジェクトを操作する際の備忘録。

## 1. `Object.values()`

`Object.values()` メソッドは、与えられたオブジェクトの値の配列を返します。

```javascript
const person = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30
};

const values = Object.values(person);
console.log(values); // ['John', 'Doe', 30]
```

この例では、`person` オブジェクトの値が配列 `['John', 'Doe', 30]` として取得されます。

## 2. `Object.keys()`

`Object.keys()` メソッドは、与えられたオブジェクトのキーの配列を返します。

```javascript
const person = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30
};

const keys = Object.keys(person);
console.log(keys); // ['firstName', 'lastName', 'age']
```

この例では、`person` オブジェクトのキーが配列 `['firstName', 'lastName', 'age']` として取得されます。

## 3. `Object.entries()`

`Object.entries()` メソッドは、与えられたオブジェクトのキーと値のペアの配列を返します。

```javascript
const person = {
  firstName: 'John',
  lastName: 'Doe',
  age: 30
};

const entries = Object.entries(person);
console.log(entries); 
// [['firstName', 'John'], ['lastName', 'Doe'], ['age', 30]]
```

この例では、`person` オブジェクトのキーと値のペアが配列 `[['firstName', 'John'], ['lastName', 'Doe'], ['age', 30]]` として取得されます。
開発環境の整備のためのDelve設定

## 概要

EchoのAPI開発環境の整備のためにDelveを導入する。
また、airが導入済みの環境なので共存を目指す。

## Delveとは

Goのコードデバックできるようにするライブラリとなっている。
https://github.com/derekparker/delve
使い方に困惑するところがあるのだが、IDEと組み合わせることで実行処理を途中で止めれるようになりので、うまく動作しないときや実装の結果確認といった確認作業がリアルタイムできるようになる。確認のためのログ仕込みとかが不要になるのでGoの開発においては導入しておくと便利だと思っている。
イメージ的には、Railsのbyebugに近いものではある。
IDEと組み合わせないとコンソール上でブレークポイントの設置などをしなくてはならないです。

## Delveの導入

利用しているDockerfileに以下のコマンドを追加する

``` 
RUN go install github.com/go-delve/delve/cmd/dlv@latest
```

その後、`docker compose build`を行いコンテナを再作成する。
コンテナ起動後に

```
dlv version

（実行結果）
Delve Debugger
Version: 1.22.0
Build: $Id: 61ecdbbe1b574f0dd7d7bad8b6a5d564cce981e9 $
```

を実行してVersion情報が取得できれば導入は完了です。

## Delveの使い方

基本的な使い方は、起動コマンドを

```
dlv debug main.go

（実行結果）
(dlv) 
```

で起動するとデバックモードで起動します。
起動に成功するとdlv入った状態でコマンド入力できる状態になります。
いくつか利用できるコマンドを紹介します。

### funcs 関数確認

```
(dlv) funcs main\..*
```

関数確認コマンドになります。
ワイルドカードも利用でき、該当を一覧で出力してくれます。

### list ソースコード確認

```
(dlv) list main.main
```

該当関数のソースコードが確認できます。

```
(dlv) list main.main:3
```

該当関数の指定行のコードを確認できます。

### break ブレイクポイントの設定

```
(dlv) break main.main
```

該当関数をブレイクポイントに設定します。

```
(dlv) break main.main:3
```

該当関数の指定行のコードをブレイクポイントに設定します。

### breakpoints ブレイクポイントの確認

```
(dlv) breakpoints
```

現在設定しているブレイクポイントの確認ができます。

### 処理を進める

`continue`　次のブレイクポイントまで進める。
`next`　1行処理を進める（ステップオーバー）。
`step`　1行処理を進める。
`stepout`　現在の関数から抜ける。

といったコマンドが用意されている。


他にも変数の上書きなども用意されているので使いこなせれば開発効率が上がってくることが間違いないが、コンソールを使わなければいけないことが難点・・・・・
しかし、CLI方式だけでなく、外部からデバッカーを接続するリモートデバック機能があります。
この機能を使うほうが利用したツールに合わせた対応ができるようになるので一般的かもしれません。リモートデバックは起動時のコマンド指定が必要になるのですでに導入しているairとの共存しながらできるようにします。

## airとの共存

追加のインストール対応はなく、airの設定している`.air.toml`ファイルを編集します。

``` toml

cmd = "go build -o ./tmp/main ."

bin = "tmp/main"

full_bin = "APP_ENV=dev APP_USER=air dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec --continue ./tmp/main"
```

一番大事なポイントは`full_bin`の内容です。dlvコマンド時に--linstenなどのパラメータを追加することでリモートデバックが可能になります。
今回の設定ではリモートデバックとして2345ポートを使用する設定になっています。
Docker環境なので、docker-compose.ymlのポートでも2345ポートを利用できるように追記することを忘れないようしましょう。

### Goland設定編

私はGolandを普段使っていますが、IDEの設定方法は
1. 右上から`実行構成の編集`を選択
2. ＋アイコンをクリックして、`Go リモート`を選択
3. 以下のキャプチャにホスト、ポート、切断時の設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/688298/d4657cc1-b42d-9919-5fd8-8f459fd48012.png)


で設定完了です。
デバックで止めたいときなどにデバック実行しておけば、IDE上で設定したブレイクポイントで処理が止まるようになります。
処理の進め方などもほかのデバック処理時の扱いと同じになります。

### VSCode設定編

VSCodeでは、`実行とデバック`のメニューから設定追加をし、
.vscode/launch.jsonを用意します。
ファイルの内容は

``` json
{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Remote",
      "type": "go",
      "request": "attach",
      "mode": "remote",
      "remotePath": "",
      "port": 2345,
      "host": "localhost",
      "cwd": "${workspaceRoot}",
      "env": {},
      "args": []
    }
  ]
}
```

を記載して保存。
デバックで止めたいときにこちらを起動すれば、VSCode上でのブレイクポイントが有効になります。

## 最後に

今回は開発環境を用意するためにDelveを導入して、デバックしやすい環境を用意しました。
調べると他のライブラリでもやれるようですが、Delveに乗り換えたみたいな記事も見られたので主流な方法なように思えました。
デメリットとしては、本番環境に適応するときにはDelveを入れたくないのでDockerfileは使い分ける必要があることくらいですかね。
個人的には細かく状態を確認していきたい派なのでテストコードを細かい粒度で作成するだけでなく、
実態が確認できるDelveは使い道がたくさんあるライブラリとなっています。
ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(5) -Ver 0.0.9-

たぶんWindowsやUbuntu Linuxでの不具合を解消するために、MOD Audioから1週間をまたずにVer 0.0.9が出ました。

MOD Desktop をよく知らないという人は[過去の記事](#過去の記事)『ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(1) 』を読んでみてください。すぐに使いたいという人は[ダウンロード](#ダウンロード)からダウンロードしてインストールしてください。

![screenshot.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129361/6fcf6713-5233-a84f-3865-c8926c0fa965.png)

## 変更点

今回は先に書いたように不具合の修正というかregressionということで差し戻しでしょうか。Arch系、Red Hat系はこのバージョンはスキップした方が良いような気がします。

* Windowsでのファクトリーペダルボードの追加
* "open user-files"が開かない問題を修正

https://forum.mod.audio/t/introducing-the-mod-app-for-desktops-beta-release/10495/210

## ダウンロード

https://github.com/moddevices/mod-desktop/releases/tag/0.0.9

## 過去の記事

[ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(1) -Ver 0.0.5-](https://qiita.com/Inqb8tr_jp/items/eee71a8c5453574cf11b)
[ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(2) -Ver 0.0.6-](https://qiita.com/Inqb8tr_jp/items/cf61fffbb48ae361cfaa)
[ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(3) -Ver 0.0.7-](https://qiita.com/Inqb8tr_jp/items/a24d261da46f9665c8f5)
[ギター マルチエフェクター MOD Dwarf を無料で使ってみよう(4) -Ver 0.0.8-](https://qiita.com/Inqb8tr_jp/items/e46d033391eee607dbf6)
[MOD Dwarfを無料で使ってみよう(1)](https://qiita.com/Inqb8tr_jp/items/ee3a30838e90c3ee9589) (mod-live-usbの作り方と使い方）
[MOD Dwarfを無料で使ってみよう(2)](https://qiita.com/Inqb8tr_jp/items/897432306eb404bd9a6b)
[MOD Dwarfを無料で使ってみよう(3)](https://qiita.com/Inqb8tr_jp/items/461625cf450c01ddb74d)
仮想通貨現物アビトラ機会検知機（CCXTからの引用）

# 趣旨
CCXTにおいてあったアビトラ検知用のコードを少しだけ改造してみやすくしてみました。
コード自体は元ページのものを見た方がいいかも知れません。

https://docs.ccxt.com/#/./examples/py/arbitrage-pairs

取引所間のシンボルの違いによってあまり使い物にならないと思いますが、botいじってる感万歳の結果が表示されるのでぜひやってみてください。

```python arbitrage.py
import ccxt
import sys


def style(s, style):
    return style + s + '\033[0m'

def green(s):
    return style(s, '\033[92m')

def yellow(s):
    return style(s, '\033[93m')

def red(s):
    return style(s, '\033[91m')

def dump(*args):
    print(' '.join([str(arg) for arg in args]))

def fetch_prices(exchange, symbols):
    prices = {}
    for symbol in symbols:
        try:
            ticker = exchange.fetch_ticker(symbol)
            prices[symbol] = ticker['last']
        except Exception as e:
            print(f"Could not fetch price for {symbol} on {exchange.id}: {str(e)}")
    return prices

def calculate_arbitrage(exchanges, arbitrableSymbols):
    investment_amount_usd = 10000  # Assume an investment amount of $10,000 USD
    for symbol in arbitrableSymbols:
        prices = [(exchange.id, fetch_prices(exchange, [symbol]).get(symbol, None)) for exchange in exchanges.values() if symbol in exchange.symbols]
        prices = [price for price in prices if price[1] is not None]
        if len(prices) > 1:
            max_price = max(prices, key=lambda x: x[1])
            min_price = min(prices, key=lambda x: x[1])
            if max_price[1] > min_price[1]:
                amount_to_buy = investment_amount_usd / min_price[1]
                potential_revenue = amount_to_buy * max_price[1]
                potential_profit = potential_revenue - investment_amount_usd
                dump(green(f"Arbitrage Opportunity for {symbol}: Buy at {min_price[0]} for ${min_price[1]}, Sell at {max_price[0]} for ${max_price[1]}, Potential Profit: ${potential_profit:.2f}"))

def main():
    if len(sys.argv) > 1:
        ids = sys.argv[1:]
        exchanges = {}

        for id in ids:
            exchange = getattr(ccxt, id)()
            exchanges[id] = exchange
            try:
                exchange.load_markets()
                dump(green(f"{id} loaded {len(exchange.symbols)} markets"))
            except Exception as e:
                dump(red(f"Failed to load markets for {id}: {str(e)}"))
                continue

        allSymbols = [symbol for id in ids for symbol in exchanges[id].symbols if hasattr(exchanges[id], 'symbols')]
        uniqueSymbols = list(set(allSymbols))
        arbitrableSymbols = sorted([symbol for symbol in uniqueSymbols if allSymbols.count(symbol) > 1])

        calculate_arbitrage(exchanges, arbitrableSymbols)
    else:
        dump("Usage: python script.py exchange1 exchange2 exchange3 ...")

if __name__ == '__main__':
    main()
```
以下のコマンドで実行します。
```
python arbitrage_pairs.py binance bybit bitget gate bingx okx
```
【ChatGPT Teamプラン】PlusやFreeプランからアップグレードできない場合は → Webブラウザのシークレットモードで問題解消するかもしれません【動画 5分02秒】【YouTubeチャンネルからの転記です】

この記事は、わたしの[YouTubeチャンネル](https://bit.ly/Yamanaka-YouTube "Living without things. 持たない生き方 手放す生き方")にある公開動画を転記しております。
( どこかのタイミングで、プログラミング-Google Apps Script or iPaaS-Zapier をつかって自動転記させる予定です )

転記のための時間コストを少なくしたいので、文字装飾( Markdown記法 )を極力つかわずに書いております。

こちらが動画内容です👇

***

![99 サムネイル 【ChatGPT Teamプラン】PlusやFreeプランからアップグレードできない場合は → Webブラウザのシークレットモードで問題解消するかもしれません【動画 5分02秒】.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/386308/e6daad44-6a43-943a-330f-465947a4d8c4.png)



* # 動画URL
    * https://youtu.be/06DUmI95H0M

<br>

* # 動画タイトル
    * 【ChatGPT Teamプラン】PlusやFreeプランからアップグレードできない場合は → Webブラウザのシークレットモードで問題解消するかもしれません【動画 5分02秒】

<br>

* # 動画の説明欄(一部を抜粋)

📅撮影日 = 2024-02-05(月)

YouTube Summary with ChatGPT & Claude( Chrome拡張機能 )で、目次と概要を自動生成しました。
https://bit.ly/yt-sum-Chatgpt-Claude


動画の目次( タイムスタンプ ):

00:00 - オープニング

00:31 - ChatGPT Teamプランへのアップグレード問題

01:40 - Chromeブラウザでのシークレットモードの起動
　└ 01:45 キーボードショートカット：Shift + Ctrl + N

01:54 - ChatGPTにログイン( https://chat.openai.com/ )しTeamプランへアップグレード

02:16 - Chrome拡張機能が原因かもしれない問題の説明

02:38 - シークレットモードでの解決方法とメリット

03:08 - シークレットモードでChatGPTをひらくのは1回だけでよい
　└プラン変更さえ終わったら、あとはWebブラウザの通常モードで新しいプランを使い続けることができる

03:31 - Teamプランの特徴と利用上の注意点


動画の概要:

この動画では、ChatGPTのPlusプランやFreeプランから、Teamプランにアップグレードができないという問題に直面した場合の解決事例を紹介しています。
具体的には、Webブラウザ( Google Chrome )のシークレットモードを利用する方法を解説しています。

動画ではまず、シークレットモードの起動方法をChromeブラウザを例にして説明し、次にそのモードでChatGPTにログインしてTeamプランへのアップグレード手順を説明しています。

さらに、この問題がChrome拡張機能によって引き起こされる可能性があること、そしてシークレットモードを利用することのメリットについても触れています。

また、Teamプランの特徴と、利用時の注意点についても説明しており、問題解決のヒントを提供しています。


---


✓ 🎥この動画と関連が強いわたしの動画 ↙
　・【動画 12分31秒】Googleスプレッドシート操作時にマウスカーソル表示箇所と実際の選択箇所がズレるトラブル解消法→Chrome拡張機能「Zoom for Google Chrome」を無効化する
　https://youtu.be/Q2_EtvBO9Y0


　・“効果的にChatGPTを活用するヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghPfo1c-qmO2ERD7ldSgmblR


　・“IT関係のトラブル事例、解決のヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghPTpaxjR7Y8SWpKUu_0q-uB


　・“効果的にキーボードショートカットを活用するヒント”シリーズ
　https://youtube.com/playlist?list=PLpQhBHT4oghPdR4gdLX71q9uYZZV-JkEz


　・“効果的にWebブラウザ拡張機能を活用するヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghPjupyR7Quk62tEqxgd3_59


　・“効果的にGoogleChrome拡張機能を活用するヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghNYbHBKFb5-KR5NtWi2y6lN


　・“情報セキュリティのヒント”シリーズ
　https://www.youtube.com/playlist?list=PLpQhBHT4oghOlwB19s3QPCHRW_LfMUUHP


✓ 🎥Shortened URL for this video | この動画の短縮URL ↙
　https://bit.ly/49GWmCD
VLOOKUP関数 第4引数でTrueを指定したらどうなる？

ExcelのVLOOKUP関数の第4引数は「FALSE固定」と覚えている方も多いかと思います。しかし、条件によってはTRUEの指定すべき場合もあります。
今回は、VLOOKUP関数の第4引数でTRUEを指定した場合の挙動と使い方についてまとめました。

## 第4引数は何を指定しているのか
Excel上ではVLOOLUP関数の第4引数は[検索方法]記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674790/61d5d50e-58ad-21ce-8b5c-34c7fde6cbd0.png)
しかし、これだけでは具体的に何を指定しているのか不明瞭ですね。
具体的には、TRUEの場合は近似一致、FALSEの場合は完全一致を指定しています。
VLOOKUP関数を使用するとき、検索値には名称やIDなどの文字列を指定することが多いと思います。
文字列を指定した場合は近似一致を指定してしまうと正しい結果を得られない場合が多いため、完全一致のFALSEを指定しなければいけない場合が圧倒的に多くなっています。
では、TRUEを指定したときの近似一致はどのようなときに指定するのでしょうか。

## 近似一致の使い方
近似一致は、数値を検索値に指定する場合に使用することが多いです。
具体的な挙動としては、検索範囲の中で検索値以下の最も近い値を取得します。

下図が使用例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674790/e87c3b78-172c-ca8e-d820-6be15c7dfaf8.png)


保有ポイントごとの交換可能アイテムをVLOOKUP関数で取得しています。
鈴木さんの「交換可能アイテム」セルには下記の関数が入力されています。
```=VLOOKUP($B4,$E$4:$F$8,2,TRUE)```

第4引数にTRUEを指定することで、保有ポイント数で交換可能なアイテムを取得することができました。
このように、ある数値の列に対して検索値以下の最も近い数値を取得したい場合に第4引数にTRUEを指定します。

注意点としては、検索範囲の数値は昇順に並べる必要があります。

## おわりに
今回はVLOOKUP関数の第4引数でTrueを指定した場合の挙動についてまとめました。
基本的には完全一致検索で文字列の検索に使用することの多い関数ですが、近似一致検索による数値の検索も使いこなせるようになると、今よりももっと幅広いことができるようになるはずです。

最後までお読み頂きありがとうございました。
データインポートウィザードで取引先と取引先責任者を更新

## はじめに

データインポートウィザードの挙動について気になったので、検証も兼ねて記事にしてみます。

普段はETLツールやデータローダーを使うことが多いので、今回はデータインポートウィザードを使用して、取引先と取引先責任者を以下の条件で更新する場合を検証しました。

皆さんもぜひ挙動を考えてみて下さい。

## 検証開始

### Salesforceの既存レコード

| 取引先名 | 部門 | 取引先責任者名 |
|:-:|:-:|:-:|
| A株式会社 | A部門 | 山田　一郎 |
| B株式会社 | B部門 | 田中　二郎 |

検証で用意するレポートの検索条件
![01レポート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/bc7bc2ad-28aa-c9b7-51e6-c73ab65b3cde.png)

検証で用意したレポート
![02レポート結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/ca133383-9223-94fc-06d0-d84822bd42f6.png)


### 用意するCSVファイル

| 取引先名 | 部門 | 取引先責任者名 |
|:-:|:-:|:-:|
| B株式会社 | B部門 |山田　一郎 |

レポートをエクスポート
![03エクスポート.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/437063da-516b-e0a7-61f8-87ca321ead50.png)

エクスポートしたファイル
![04エクスポート結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/0d3303f2-df8a-e7a6-634e-206b023b6de2.png)

編集してCSVで保存
![05インポートCSV.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/91bf3afd-36b6-b78c-f971-4c93a2e4433d.png)

### データインポートウィザードの設定　

- 取引先責任者の一致条件：名前 　
- 取引先の一致条件：名前と部門 　
- 既存の取引先情報を更新にチェックを付ける


取引先と取引先責任者を選択
![06インポート1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/602f0596-8742-d527-2d82-be6c69c27ffc.png)

処理を選択
![07インポート2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/43736907-cd45-2b21-bfc7-a0f8e99bf71c.png)

アップロードするCSVを選択
![08インポート3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/c5cb15e0-9975-cb8a-3844-fd76acb91dc8.png)

対応付けを編集
![09インポート4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/9474101e-de4c-2257-d882-df558b52b52a.png)

### データインポートを実施する

インポートを開始
![10インポート5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/304d6110-4c67-7f5b-14db-09b338ceccab.png)

インポート成功
![11インポート6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/7d8ed086-7548-f34c-e8b6-451488b792d1.png)

状況完了を確認
![12インポート結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/3050303c-cd6d-fe2b-f3a1-9ce7ef641a6b.png)

### データインポート後のレコード

さて、どのような挙動になると思いますか。

 1. A株式会社からB株式会社に、山田一郎の所属が付け変わる。
 2. A株式会社の山田一郎は変わらず、B株式会社に新たな山田一郎が作成される。
 3. A株式会社の山田一郎は変わらず、B株式会社の田中二郎が山田一郎へ更新される。 　
 4. 特に変更なし。

ちなみに、データインポート後の結果のCSVはこちらです。

 result
![13インポートResult.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/be563cde-1c33-6dbc-6e6c-4b7e4e351617.png)


## 検証結果

結果は、

「4.特に変更なし」です！
作成／更新しても、見た目は何も変わりません。
厳密にいうと、取引先「B株式会社」と取引先責任者「山田　一郎」がそれぞれ更新だけされます。

念の為、リストビューでも確認してみます。

取引先責任者のリストビュー
![14取引先責任者リストビュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/789516/b6b21741-99be-5c4c-ae43-a160757bda62.png)

見た目の変更はないようです。
しかし最終更新日をみると、取引先「B株式会社」更新のみされていて、取引先責任者「山田　一郎」は、そのままでした。

## まとめ

同じ名前の取引先と取引先責任者がある場合、インポートによって取引先レコードのみ更新されるが変更はない結果となりました。
インポート前には、取引先と取引先責任者の名前の重複有無は確認しましょう。

データインポートウィザードにも興味がある方や、これから使う方の参考になれば嬉しいです。

### 参考記事

https://help.salesforce.com/s/articleView?id=000385322&type=1
wslでelixir その136

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
ハッカソンなので、Livebookでwebsocket、echo serverやってみた。

# 参考にしたページ

https://qiita.com/tamanugi/items/40c0d2daf151f7cab3e4

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/1298e15f-d0a7-5a8e-1fd1-00717b73df92.png)

# セットアップ

```
Mix.install([
	{:socket, "~> 0.3"},
	{:jason, "~> 1.4"}
])
```

# クライエントは、こちら

https://embed.plnkr.co/plunk/6EFcKfiohjzCyHvB


以上。