OmniAICreator/Qiita-1.07M huggingface dataset:
portsnap(8) が無くなったので git 経由で簡単同期

# 誰得？

14.x-RELEASE で portsnap(8) が👋しよったけん、今後 git(1) が svnlite(1) っぽくユーザーランドに入る事に期待する代替スクリプトを書いてみたw

---
さんこぉ～しりょぉ～w

https://qiita.com/je3kmz/items/ddfd190a51533610ff8d

---
# とりま、こんな感じw
```Console:PORTS.sh
#!/bin/sh
#
# portsnap 代替スクリプト 要:devel/git
# 2023/11/30 初版 by JE3KMZ

PORTSDIR=${PORTSDIR:-/usr/ports}
GIT_CMD=`/usr/bin/which git`
ret=$?
if /bin/test ${ret} -eq 1
        then
        /bin/echo "git not found."
        exit 1
fi

LIST=~/.ssh/known_hosts
/bin/test -f ${LIST} && /usr/bin/grep -q "git.freebsd.org" ${LIST}
ret=$?
if /bin/test ${ret} -eq 1
        then
        /usr/bin/ssh -oStrictHostKeyChecking=no -lanongit git.freebsd.org -T
fi

if /bin/test ! -d ${PORTSDIR}
        then
        /bin/mkdir -p ${PORTSDIR}
        ${GIT_CMD} clone ssh://anongit@git.freebsd.org/ports.git ${PORTSDIR}
        DIRCHECK=1
else
        DIRCHECK=0
fi
cd ${PORTSDIR}
/usr/bin/bmake fetchindex
if /bin/test ${DIRCHECK} -eq 0
        then
        ${GIT_CMD} pull --rebase
fi
exit 0
```
---
# 何をしちょるのか

序盤は必要なん、有無の確認と無いなら拾ってくる。
\<ぼそ>ssh で接続なのは curl なライブラリ投入が面倒じゃけw\</ぼそ>

---
PORTSDIR 変数のトコにファイルシステム上ディレクトリが無いなら `git clone` 実行👏
で、後から clone しなかった時の🚩建てちゃる🤗

---
INDEX-?? を拾って、過去に `git clone` し終わっちょるなら `git pull` 実行しおる cron(8) で回すコトを意識したリッチな仕様🎉

---
注：?? のトコは RELEASE の番号が入るけん、今回じゃと 14 が入る📀

---
# おしまい
`pkg install git` の御呪いは入門者にお勧め✌
漢なデーモン使いは、`https://github.com/git/git` から😒
【資格】RPA技術者検定エキスパート合格体験記: 受験レポート

こんにちは。やまなかです。
普段はWinActorとBizRobo!でロボット開発をしています。

今回は、WinActorの資格試験である、**RPA技術者検定エキスパート**について書きます。


## 1.試験の概要と重要性
RPA技術者検定エキスパートは、RPAツール「WinActor」のスキルを証明するための重要な資格試験です。

筆者は実際に第18回検定の受検をし、合格しました。
合格までに

* **どのような学習を行ったのか**
* **受検当日の注意点としてどのような点が挙げられるのか**

等を中心にお話ししていければと思います。

## 2.筆者の前提情報
前提として、筆者の経歴は下記のような感じです。
* 元々WinActorを活用した業務を行っている
* 実際の使用歴としては１年半ほど
* 大学時代は文系
* プログラミング関連の知識は社会人になってから

上記を踏まえてここから読んでいただければ、ご自身に必要な学習量や準備がイメージしやすいかと思います。

## 3.勉強方法と試験の難易度
試験対策の為の効果的な勉強方法としては、下記を実施していました。

* 公式から提供されている「WinActorマニュアル」（https://winactor.biz/use/manual.html） の閲覧
* <font color="Red">公式が監修している過去問の回答</font>

**過去問は本当にオススメ**で、普段の業務などで使用しないWinActorのノード等が出てきたりして、その活用方法を知れるので、個人的にはとても勉強になりました。（本番の試験にもちゃんと出てきました）

<br>

**試験の難易度**としては、過去問がバッチリ解けるようになっていて、回答スピードを意識した学習を行っていれば問題なく合格できるぐらいかと思います。

筆者が購入した過去問は、2022年に発売された書籍（https://ec.athuman.com/products/detail/2328） でしたが、公式サイトで紹介されている**RPA技術者検定エキスパートの過去問で最新のもの**を購入すればよいと思います。

＜公式サイト＞
https://winactor.com/book/

<br>

WinActorマニュアルについては、業務でWinActorを利用していたり普段から触っていたりする方であれば、流し見程度で問題ないかと思います。
筆者としては、機能の復習としてはちょうど良かったです。

## 4.その他の事前準備
2023年11月現在、RPA技術者検定エキスパートは<font color="Red">オンライン</font>での受検になっております。

コロナ禍に入る前まではリアル開催だったので、いつリアル開催に戻るかは分かりませんが、この記事ではオンライン受検でのお話をしていきます。

オンライン受検時は、テスト受検前にテスト環境への接続検証が必要になります。
当日にどのような不具合が発生するか分からないので、**必ず接続検証を実施してください。**

<br>
また、試験本番時の開発効率が変わってくるので、金銭的に余裕があるのであればモニターを購入する事も検討してみても良いかもしれません。

## 5.試験当日にする事と注意すべきポイント
試験当日は、当然の事かとは思いますが早めに試験環境に接続しておきましょう。

また、試験環境に接続後、試験本番まで待機時間が発生します。
その間に、普段通りの開発が出来そうであるかを確認するのも良いです。

**筆者が当日に直面した不具合**としては、IME（文字入力）がバグっていて英語の入力が出来ませんでした。
文字入力の確認であれば、メモ帳などを開いて出来るかと思いますので、確認しておくと安心して試験に臨めます。

もし待機時間中に不具合などが見つかった場合は、すぐに試験官に報告して対処してもらいましょう。（上記のIMEバグに関しては結局解消しないまま筆者は試験を回答していました）

## 6.受験当日の心構えと最終準備
試験が始まったら、選択式問題はひたすら気合と知識で解いていくだけですが、**実技問題**は、必答問題を解いたのちは他の２問を両方見てみて、確実に解けそうな方をまずは選びましょう。

きちんと過去問で学習出来ていれば、試験の内容は難しくないと思いますので、そこまで焦る必要はないかと思います。

## まとめ
RPA技術者検定エキスパートは、WinActorのスキルを証明する重要な試験です。

普段の業務でWinActorを使用している方であれば、過去問を休日や業務後にひたすら回答することが合格への鍵となります。

皆さんにとって、この記事が有益なガイドとなっていれば幸いです。
GPTsでドキュメント生成ツールを作成しました。

# GPTsでドキュメント生成ツールの作成
GPTsでプロンプトにコードを貼り付けるだけで関数のドキュメントや1行1行に処理の説明を入れてくれる「**Coding Documentation GPT**」を作成しました。

使ってみてください。
使用した後に意見をいただけると幸いです。

https://chat.openai.com/g/g-6V7SNo6F2-coding-documentation-gpt

---

## 使い方
ドキュメントや生成したいコードを貼り付けるだけです。
下記みたいに雑にプロンプト投げてもらって大丈夫です笑

プロンプト例
```text
User
import os
import tweepy

def tweet(consumer_key, consumer_secret, access_token, access_secret):
    #オブジェクト作成
    client = tweepy.Client(
    	consumer_key = CONSUMER_KEY,
    	consumer_secret = CONSUMER_SECRET,
    	access_token = ACCESS_TOKEN,
    	access_token_secret = ACCESS_SECRET
    )

  client.create_tweet(text='テスト')

if __name__ == '__main__':
    tweet(
        CONSUMER_KEY = os.environ['CONSUMER_KEY'],
        CONSUMER_SECRET = os.environ['CONSUMER_SECRET'],
        ACCESS_TOKEN = os.environ['ACCESS_TOKEN'],
        ACCESS_SECRET = os.environ['ACCESS_SECRET']
    )
```


### それではプログラミング言語ごとに使ってみた例を写真と共に見ていきましょう！！

---


## 1. Pythonのコードを入力した場合
インプット:
![スクリーンショット 2023-11-30 12.05.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/84b36405-77fe-a9c4-d6d6-45573611b29e.png)


アウトプット:
![スクリーンショット 2023-11-30 12.20.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/ee8b64a7-d0cf-b93d-0254-d9928517d6b1.png)
完璧ですね。Google Docs StringでPythonが記述されてます。

---

## 2. JavaScriptのコードを入力した場合
インプット:
![スクリーンショット 2023-11-30 12.20.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/2173e7a6-60af-a8cd-9c8c-5e7e8efe1d33.png)


アウトプット:
![スクリーンショット 2023-11-30 12.20.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/f74435fb-ace5-48ec-bb62-20b7dc0f6dba.png)

完璧ですね。JSDocsで綺麗に描かれています

---

## 3. PHPの場合
インプット:
![スクリーンショット 2023-11-30 12.21.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/295c20e9-950e-535f-8200-ab3843c78d60.png)

アウトプット:
![スクリーンショット 2023-11-30 12.21.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/08bc8415-6bcc-0f04-09c4-4b30912637cd.png)


完璧ですね

---


## 4. Golangの場合
インプット:
![スクリーンショット 2023-11-30 12.22.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/e9e89c12-011d-d314-39ea-c184a134e749.png)


アウトプット:
![スクリーンショット 2023-11-30 12.24.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1130166/5e34b014-82bb-df5e-8ffd-249d2c125f19.png)

完璧ですね。非常にみやすくなりました

---
情報収集してみよう

この記事は [一分で読める小ネタのカレンダー | Advent Calendar 2023 - Qiita](https://qiita.com/advent-calendar/2023/raki) の１７日目

# 情報収集

- 自分のやり方にあう情報収集の方法を考えよう
- エンジニアとしての技術まわりも大事だけど、趣味やその他のことについても広げて考えられるようにしよう
- まわりの先輩諸兄に聞いてみるといいよ
- 毎日流し読みするだけでだいぶ違うよ

# 手っ取り早い情報元の例

- SNS
    - X（旧Twitter）
    - Facebook
    - LinkedIn
- 各種サイト
    - github
    - DEV Community
    - DevelopersIO
    - daily.dev
- その他
    - google alert

本文はここまで。以下は時間外

# 情報収集のあれこれ

## 収集方法

- サイトを目視巡回（ブックマーク等）
- RSSリーダーを使う
- slack や discord などの自分用スペースに流し込み
- google alert などはメールで受信

## 収集内容の工夫

- 除外設定：例えば terraform で検索すると、terraform power って電力会社の記事も大量にヒットするので、除外設定をする
- 証券コード：サイバーエージェント（4751）のように、会社名にくっついてくるこの数字は、証券コードと呼ばれるもので、株取引に使用されるものだけど、特定企業の情報を収拾する際に付けておくと業績やニュースなどが適切に入手しやすい。就職転職活動時の国内企業研究には必須
- 絞り込み：ググらビリティの低い語句はノイズが多くなりがちなので、複数の語句を使って絞り込む。例えば drill という DNS 関連のツールがあるが、そのまま検索すると普通に穴を開けるドリルが出てきてしまう。DNS のように利用範囲や dig, nslookup のように類似ツール名などで絞り込んで収集する情報の品質を上げる

## 定期点検

- 設定後にしばらく運用していると慣れてしまってチェックを怠ったり、見る気がなくなってしまったものを放置してしまったり、ノイズが増えることでさらに見なくなるなどの負のスパイラルに入りやすくなるので、定期的に掃除をする習慣をつくる
- 新しい収集方法を試す
- 新しい収集内容を考える
- 新しい収集元を探す

## github を活用

- ユーザをフォローする
- リポジトリにスターをつける
- [Explore GitHub](https://github.com/explore) や [Explore GitHub](https://github.com/explore) をチェック
- ホームのタイムライン

# 改善依頼

- ここで情報収集してるぜとか
- こんな方法でやっているぜとか
git で新しいブランチを切って git push して Github に Draft PRを作成するまでが非常の面倒くさいので簡単なコマンドにする (gitconfigのエイリアス)

# .gitconfig

.gitconfigにエイリアス登録しておく

```
[alias]
  pr = "!sh -c 'git checkout -b $1 && git commit --allow-empty -m $1 && git push' -"
```

実行

```
git pr new-branch
```

あとは標準出力のURLからGithubにアクセスしてPRを作成するだけ

```
remote: Create a pull request for 'xxx' on GitHub by visiting:
remote:      https://github.com/AAA/BBB/pull/new/new-branch
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura
Brainでlinux(その1)-はじまり

Brainuxで遊びたくて、Brainを入手。
SH2、A9200の２台をメルカリで入手した。

# (1)準備
1
公式HP
https://github.com/brain-hackers/buildbrain/releases
からSDカードイメージ(sdimage-*.zip)をダウンロード

2
SDカードに書き込む
~~~
sudo dd if=~/Downloads/sdimage-2021-02-21-162410.img of=/dev/rdisk4 bs=10M
~~~

3
実機で起動
イメージを書き込んだSDカードを実機に挿入し下記から起動。

追加アプリメニューから “Launch Linux” を選択。

4
ログイン
ユーザー名:user
パスワード:brain

これで実機のlinux環境にログインできます。

# (2)brain-configでの設定
下記コマンドでbrain-configを起動し、ルートファイルシステムを拡張。
~~~
sudo brain-config
~~~
上下左右キーと Enter キー（決定キー）を使って以下の手順に従って操作します。

“Advanced Options” を選択
“Expand Filesystem” を選択
しばらくすると “Root partition has been resized. …” と表示されるので “Ok” を選択
“Back” を押しトップメニューに戻る
“Finish” を選択すると再起動が促されるため再起動
再起動したら容量が増えていることを lsblk コマンドを使って確認

# (3)swapファイルの設定
Brainはメモリ容量が128Mしか無いため、swapの設定する。
SDカードに余裕があるため、4Gのswapを設定してみる。

1
4GBのサイズのファイルをddコマンドで作成（ここでは/swapfileを使用）:
~~~
sudo dd if=/dev/zero of=/swapfile bs=1M count=4096
~~~

2
ファイルのアクセス権を制限:
~~~
sudo chmod 600 /swapfile
~~~

3
スワップ領域を作成:
~~~
sudo mkswap /swapfile
~~~

4
スワップを有効にする:
~~~
sudo swapon /swapfile
~~~

5
/etc/fstab ファイルにスワップのエントリを追加。以下のようにテキストエディタで開いて追加できる。:
~~~
sudo vi /etc/fstab
~~~

6
ファイルの末尾に以下の行を追加して保存する:
~~~
/swapfile none swap sw 0 0
~~~


これで、4GBのSwapファイルが作成され、永続的に有効になる。
大きすぎたかな〜？
viでは記号の入力が多いため、下記を参考にする。
https://wiki.brainux.org/beginners/get-started/
escは電源の隣のボタン
:は記号+shift+h

# (4)最新の状態へ
~~~
sudo apt update
sudo apt upgrade
~~~
これで、Brainuxで遊ぶ準備完了。
EC2を作成してSSHに接続できないときに確認すること

### VPCとEC２を作ってみた
久しぶりにAWS環境で、VPCとEC2を作成するときがあり、コンソールをのぞいてみると、
VPCを作る時に自動で結構作ってくれたりしてびっくりした。

VPC、サブネット、ルートテーブル、インターネットゲートウェイ
VPCを作るだけで、こんなにも作ってくれるのだ。
ひとつひとつ作っていってた過去はいずこである。

### SSHがつながらない
作成したVPC下でEC2を作成してSSH接続ぽちーーー。。。。。。
もうそれはそれは繋がらない。

### もろもろ確認
EC2の設定。セキュリティグループ。インターネットゲートウェイ。キーファイル。
向かいのホーム。路地裏の窓。冷蔵庫の中。お菓子ボックス。プリンおいしい。
そんなとこにあるはずもないのに。

### そういえば
自動で作ってたから忘れていたが、ルートテーブルの設定で外部に接続できるようにしなくてはいけないのではないか。
ルートを確認っと。。。。
ないーーー。やっぱりないーーー。外部にでれないーー。

### 設定する
VPC → ルートテーブル から
ルートを編集で、送信先を「0.0.0.0/0」でターゲットを対象のインターネットゲートウェイにされたし。

### さいごに
山崎まさよしってなんで歌わへんかったん。
[React] 改行コード(\n)入り文字列のを適切に改行させて、表示させる方法

## はじめに
業務で詰まったので自分の備忘録として残したいと思います

## 結論
CSSの`white-space: 'pre-wrap'`を使用する！

## 具体例
### ダメな例
```typescript
import { Box } from "@mui/material";

function App() {
    const message = "hello \nworld!";

    return <Box>{message}</Box>;
}

export default App;
```
#### 結果
![スクリーンショット 2023-11-30 12.18.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525908/e8cc76fc-4daa-3832-4fd4-248eab888230.png)

### 成功例
```typescript
import { Box } from "@mui/material";

function App() {
    const message = "hello \nworld!";

                // ↓追記！
    return <Box sx={{ whiteSpace: "pre-wrap" }}>{message}</Box>;
}

export default App;
```

#### 結果
![スクリーンショット 2023-11-30 12.21.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2525908/68c3a4ab-37d2-e734-d903-091531b1166e.png)

## 最後に
いかがでしたでしょうか。
改行コードを挿入しただけだと、空白文字に変換されてしまうらしいです。
これが誰かの助けになれば嬉しいです。
AWS S3 バケット内に格納したCSVファイルの中身を、AWS マネジメントコンソールで確認する方法

## はじめに
AWS S3 バケット内に格納した CSV ファイルの中身を確認する際、わざわざ自分のローカルPCにそのファイルをダウンロードして、ローカルPCのテキストエディタやターミナルを使ってファイルの中身を確認していました。

以前、職場の同僚から「AWS マネジメントコンソール（以下、コンソール）で CSV ファイルの中身を確認できる方法」を教えてもらったことがあり、個人的には便利だと感じたので、ここにメモとして残しておきたいと思います。

## 準備

最初に S3 バケットを作成します。
`sample-20231129-01` という名称で作成しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/45891f1e-0cbf-6616-4339-58abb6310bd1.png)

次に、このバケットの中に CSV ファイルを格納します。

```csv:sample.csv
No,Name,Japanese,Math,English
1,生徒A,99,64,68
2,生徒B,84,48,61
3,生徒C,82,46,54
4,生徒D,69,66,87
5,生徒E,40,47,84
6,生徒F,73,70,44
7,生徒G,34,53,95
8,生徒H,84,37,65
9,生徒I,33,97,55
10,生徒J,67,96,42
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/d69defc8-1918-0643-3661-551c30272932.png)

コンソールで CSV ファイル名をクリックすると、そのファイルの所有者や S3 URI、アクセス許可情報などを確認できますが、CSV ファイルの中身までは確認できません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/47a77e40-f414-69dc-4a72-1f2d50dc41c0.png)

## コンソールで CSV ファイルの中身を確認する

方法はとても簡単です。
「オブジェクトアクション」メニューから「S3 Select を使用したクエリ」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/51fab8ad-85c4-82ae-ac21-0c110df6e83f.png)

**入力設定**では、次の内容を入力します。
- 形式： CSV
- CSV 区切り記号： カンマ
- CSV データの最初の行を除外する： チェックなし

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/02952205-a65c-516c-4f94-88c4facc05eb.png)

**出力設定**では、次の内容を入力します。
- 形式： CSV
- CSV 区切り記号： カンマ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/afdb3224-ca09-ce18-84f2-5648f75ef7e3.png)

**SQL クエリ**
ここに SQL を記述します。
今回は特に条件を指定することもなく全レコードを抽出したいので
`SELECT * FROM s3object s` としています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/d6084700-eb51-b006-a93b-bd8b60c2ed2e.png)

SQL を記述したら「SQL クエリの実行」ボタンを押下します。
クエリの結果は、すぐ下の**クエリ結果**の箇所に表示されます。
今回は、特に条件を指定していないため、CSV ファイルの全レコード（つまり、ファイルの中身全て）が表示されました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/11e01b11-6c48-089a-47a7-38516d8bf335.png)

コンソールで、CSV ファイルの中身を確認することができました。
Qiita 内にも **S3 Select** に関する記事が沢山有りますので、興味を持たれた方は是非調べてみてください。

## さいごに

S3 Select は、WHERE 句で条件指定して必要なレコードだけを抽出するのが本来の使い方だと思いますが、職場の同僚からこの方法を教わってからは、私もこの方法を使うようになりました。

ただし、S3 Select は[料金が発生](https://aws.amazon.com/jp/s3/pricing/)しますので、使い過ぎにはご注意ください。
具体的には、スキャンされたデータ（GBあたり）、戻りデータ（GBあたり）に課金されるようです。

・2023年11月現在の東京リージョンの料金
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759747/4137627d-c71c-e782-420e-d621a6de713d.png)

そのため、対象となる CSV ファイルのサイズが小さい場合や、既にコンソールを開いている場合などに（限定して）使える方法になるかも知れませんが、わざわざダウンロードしてテキストエディタやターミナルを使って中身を確認する手間は省けるため、それなりに便利な方法かなと感じています。
ScalaのOption型について

この記事は ウェブクルー Advent Calendar 2023 1日目の記事です。
## はじめに
この記事は、Scalaの学んだことのアウトプットとして書かれた記事です。
細かい仕様については、公式サイトをご参照ください。
https://www.scala-lang.org/api/2.13.3/scala/Option.html

## Option型とは？
ScalaにはOption型という型があります。
Option型は値が入っている場合はSome, 入っていない場合はNoneを返します。

``` scala
val num1 = Option(1)
//num1: Option[Int] = Some(1)
val num2 = Option(null)
//num2: Option[Null] = None
```

## なぜOptionを使うの？
nullを参照しようとすると、NullPointerExceptionになってしまいます、、そのため、nullチェックをする必要がありますが、その記述を漏れなく行うことは難しい場面もあるでしょう。

そこで、nullが入るかもしれない値は、Optionで包むことで、コンパイル時にエラーを発見することができます！
実行時ではなくコンパイル時にエラーを発見できるので、手軽にエラーを発見できます。

Optionで包んだ値にアクセスするにはいくつか方法があり、getOrElseメソッドでは、値が存在する場合は値を返し、存在しない場合はメソッドの引数に渡した値を返します。

ここではパターンマッチを使った方法でアクセスしてみます。

```scala
//Noneだった場合を記述しない場合
val num3 : Option[Int] = Option(5)
 num3 match {
 case Some(a) => a
 }
//warning: match may not be exhaustive.
//It would fail on the following input: None 
//<日本語訳>
//match式は完全ではない可能性があります。
//次の入力では失敗します：None
```
このように、warningエラーでNoneの場合が定義されていないと警告がでます。これによってコンパイル時にパターンの抜け漏れがあった場合は警告が出るため、実行時エラーになることがありません！





## おわりに
簡単にですが、Option型を使った書き方や使用するメリットについて紹介しました。

ウェブクルーでは一緒に働いてくれる方を絶賛募集中です！
興味のある方はぜひお問い合わせください。
https://www.webcrew.co.jp/recruit/
【ChatGPT】が公表されて、一年です。

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

　今回は、ChatGPTが公表されて、一年となりました。いろいろとありましたね。

:::note info
本記事中で使用しているのは、
　GPT-4です。あしからず。
:::
　ChatGPTさんに
　　お祝いを言いました。
***
***User***
今日の年月日を教えてください。

***ChatGPT***
今日は2023年11月30日です。

***User***
誕生日、おめでとう。

***ChatGPT***
ありがとうございます！お祝いの言葉をいただき、とても嬉しいです。何かお手伝いできることがあれば、お知らせくださいね。
***
　ふつうですw

　まぁ、そうでないと、
　　いけませんけどw
***
　ChatGPT研究所さんが、
　　X-Twitterで、
　　　ChatGPTの短いのに
　　　　濃い歴史を書かれています。
[【祝】今日はChatGPTがリリースされてちょうど一周年です！](https://x.com/ctgptlb/status/1729877877225836634?t=G9qZLyPa-A6KLeaRrvoL4g&s=03)
***

　私は、公表されて、
　　すぐには、ChatGPTに
　　　アクセスしていません。
　　　　日本語でのやり取りが
　　　　　できなかったためです。

　2023/02/11に
　　ようやくアクセスします。
　　　もちろん、日本語対応。
　　　　そこで、ハマったわけですw

　おそらく、
　　日本語化がなければ、
　　　ここまでの広がりは
　　　　なかったでしょうね。
***
　しかし、
　　生成AIを拒否する人もいます。

　まぁ、
　　ハルシネーションします、
　　　情報漏洩します、と
　　　　言われていれば、
　　　　　企業的には、
　　　　　　簡単に導入が
　　　　　　　できないのは
　　　　　　　　わかります。
***
　しかし、それでも
　　システムエンジニアでさえ
　　　いまだに、生成AIに
　　　　手を出せていない、とも
　　　　　一部から聞きます。

　企業が使用禁止に
　　しているのでしょうね。
　　　その人は、“それが悔しい”
　　　　とも言っていました。

　試すこともできない、
　　というのは、最先端技術を
　　　使ってきた人間にとっては
　　　　苦痛でしかないのでしょう。

　“個人的にやれば？”と
　　思うでしょうが、
　　　帰宅してまでやる、
　　　　というよりも、
　　　　　眠るだけです。
　　　　　　遅い時間まで
　　　　　　　仕事ですから。
***
　実は、
　　そうした生成AIを
　　　規制している企業も
　　　　気付かないうちに
　　　　　使っているんですけどねw

　それに
　　そのうちに、
　　　OfficeソフトにCopilotが
　　　　入れば、強制的に
　　　　　使わねばならない。

　それまで規制していたら
　　仕事にならないどころか、
　　　取引相手とのやり取りも
　　　　ダメになる確率が……。
***
　今回は、ここまで。
複数の同型の Bean がある場合に @Qualifier や @Primary を使用せず inject する

## 結論
inject 先のフィールド名を Bean 名に合わせるだけで OK。

## 前提
`Example` を実装した Bean が 2 つ存在しているとする。
```java
@Coponent
public ExampleImplA implements Example {
    ......
}
```
```java
@Coponent
public ExampleImplB implements Example {
    ......
}
```
こんな感じで実行すると当然エラーが発生する。
```java
// Example 型の bean を使用
@Component
@RequiredArgsConstructor
public class BeanConsumer {
    private final Example　example;
    ......
}    
```
```bash
......
BeanConsumer required a single bean, but 2 were found
.....
Consider marking one of the beans as @Primary, 
updating the consumer to accept multiple beans, 
or using @Qualifier to identify the bean that should be consumed
......
```
エラーメッセージの通りに `@Primary` や `@Qualifier` を使って解決できるが、今回は別な方法を試す。

## 解決策
利用先のフィールド名を Bean 名に合わせればよい。
例えば `ExampleImplA` を inject する場合、Bean 名はデフォルトで `exampleImplA` となるので以下のようにすればよい。

```java
// Example 型の bean を使用
@Component
@RequiredArgsConstructor
public class BeanConsumer {
    private final Example　exampleImplA;
}    
```

## Appendix
#### 動作環境
SpringBoot 3.1.0

#### 注意事項
テスト時に Spy できません。
例えば以下のように Spy しようとすると...
```java
@Component
@RequiredArgsConstructor
public class BeanConsumerTest {
    @SpyBean Example　exampleImplA;
}    
```
以下のエラーが出る。
```
java.lang.IllegalStateException: No bean found for definition ......
```
Spy するには `@Qualifier` をつける必要がある。
VisualStudioで.NET5.0の動作確認をしようとしてつまづいた

# 概要

まず、VisualStudio2022で.NET4.0の開発は既に行っている状態。
そこから.NET5.0の動作確認をした時の記録です。

.NET5.0だと下記ができないという情報を頂いたのがきっかけです。

https://qiita.com/waokitsune/items/0b64e5d87d4b5f7435ed#comment-9004d289f9161bbafd29

# プロジェクト作成してみるが…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/c3aa481a-ecd5-666e-51d5-37c1950d94cb.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/7204930f-3106-d503-484c-d797cb6c1d57.png)

.NET 5.0がいない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/1ebb4a87-c3fe-ba29-8c99-9ad7f9562a72.png)

# .NET 5.0をインストールしてみる

https://dotnet.microsoft.com/ja-jp/download/dotnet/5.0

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6a613699-1af8-0241-28c8-f1940d4d7ed3.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/2ecff486-a150-4e3d-7c51-ea94bc27b435.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6e29677b-8366-3ab2-a215-92a3926e6331.png)

# プロジェクトの作り方が間違いだった

.NET 5.0をインストールしても下記のままでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f739209d-4af9-6c47-5374-e292b5cce21d.png)

これが間違いでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/6a9b8a10-4c01-8afa-b983-95244afaf954.png)

こう作るべきでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/9c5b89b1-f664-4bf5-badb-02c6337be345.png)

上記のようにしてプロジェクト作成を進めると…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/b812c7f4-5331-8748-f19a-7de19a07c987.png)

.NET 5.0いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a5e9f41d-1d0f-5be0-4eb7-264bd290c4bd.png)


# 参考サイトさん

https://imagingsolution.net/program/visualstudio2019v167p1/

https://qiita.com/yoshi_782/items/ac1d0919e0318bb0cbe3

https://qiita.com/nskydiving/items/3af8bab5a0a63ccb9893

https://ja.wikipedia.org/wiki/.NET_Framework

https://ja.wikipedia.org/wiki/.NET

# バージョン

Microsoft Windows [Version 10.0.19045.3693]
Microsoft Visual Studio Community 2022 (64 ビット) - Current Version 17.8.2
【2Dプログラミング】「上下左右」の4通りの処理の重複をなくすリファクタリング案

:::note
`Python`を用いて書いていますが、どの言語にも通底するお話をします。
:::

## はじめに
2Dゲームなど、二次元座標を用いてプログラミングするとき、「上下左右」で4回同じようなコードを書いていませんか？

例は何でもいいですが、たとえばこのようなコード。
```python:冗長.py
map = True/Falseの二次配列。Trueなら壁があることを表す。

#自分から見てdirectionの方向にある壁を探す
def see_wall(position:tuple[int, int], direction):
    if direction == "up":
        #自分から上側へ
        for y in range(position.y, -1, -1):
            if map[position.x][y]:
                return (position.x, y)

    elif direction == "down":
        #自分から下側へ
        for y in range(position.y, len(map[0])):
            if map[position.x][y]:
                return (position.x, y)

    elif direction == "right":
        #自分から右側へ
        for x in range(position.x, len(map)):
            if map[x][position.y]:
                return (x, position.y)

    elif direction == "left":
        #自分から左側へ
        for x in range(position.x, -1, -1):
            if map[x][position.y]:
                return (x, position.y)

    #ここまで来たら、壁がなかったということ
    return None
```

上下左右で4回同じコードを書いていますね。冗長ですね。もし修正しようとしたら4か所修正しないといけなくなりメンドウですね。

## ベクトルを使いましょう
**ベクトル** を使いましょう。
ベクトルは高校生の数学でやるものですが、簡単に言うと「方向を表すタプル」です。（タプルはプログラミング用語です。タプルが分からない場合はリストと考えてください）

行きたい方向とその距離を、`(x, y)`のようにまとめてタプルにします。すると4つの処理を簡単にまとめることができます。

おそらく、説明するよりも実際に見せた方が早いです。ごらんあれ。

```python:ベクトル使った.py
def see_wall(position:tuple[int, int], direction):
    #ベクトルを設定
    vector = (0, 0)
    if direction == "up":
        #自分から上側へ
        vector = (0, -1)

    if direction == "down":
        #自分から下側へ
       vector = (0, 1)

    if direction == "right":
        #自分から右側へ
        vector = (1, 0)

    if direction == "left":
        #自分から左側へ
        vector = (-1, 0)

    #見る
    #x, yがマップ内にいる限りループ
    x, y = position
    while is_in_area(x, y):
        #確認
        if map[x][y]:
            return (x, y)

        #移動
        x += vector[0]
        y += vector[1]

    #ここまで来たら、壁がなかったということ
    return None

#マップ内にいるかを判定
def is_in_area(x, y):
    if (0 <= x <= len(map))
        and (0 <= y <= len(map[0])):
        return True
    else:
        return False
```

どうですか。一つにまとまり、スッキリしましたね。

* 行きたい方向と量を`vector`（タプル）に登録
* 「範囲内にいるとき」という条件で`while`
* `vector`に登録した分だけ移動するには、x, yにそれぞれ足し算

というわけです。

## 最後に
:::note
いいね頂けると泣きながら喜びます><

この記事を読んでいる方は、次の記事も読んでいるのかもしれません：
* [初心者向けゲームプログラミングJavaScriptライブラリを作り、講座をした](https://qiita.com/konbraphat51/items/b138683db352afd77714)
:::
wslでelixir その109

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

# 練習問題
Livebookでd3のtreeを、Mapから作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/36e5737e-6ffa-9467-b39f-c479d87e061f.png)

# サンプルコード

```
defmodule KinoD3.Tree do
  use Kino.JS

  def new(html) do
    Kino.JS.new(__MODULE__, html)
  end

  asset "main.js" do
    """
    import "https://d3js.org/d3.v5.min.js";
    export function init(ctx, json) {
      const chartid = document.createElement("div");
    	chartid.id = "out";
    	ctx.root.appendChild(chartid);
    	var obj = JSON.parse(json); 
      var root = d3.hierarchy(obj);
      var tree = d3.tree().size([250, 250])
      tree(root);
      var g = d3.select('#out')
          .append("svg").attr("width", 600).attr("height", 600)
          .append("g").attr("transform", "translate(300, 300)");
      var link = g.selectAll(".link").data(root.descendants().slice(1))
        .enter().append("path").attr("class", "link").attr("fill", "none").attr("stroke", "#555")
        .attr("stroke-width", "1.5px").attr("opacity", "0.6")
        .attr("d", function(d) {
          return "M" + d.y + "," + d.x + "C" + (d.parent.y + 100) + "," + d.x +
            " " + (d.parent.y + 100) + "," + d.parent.x + " " + d.parent.y + "," + d.parent.x;
        });
      var node = g.selectAll(".node").data(root.descendants())
        .enter().append("g").attr("class", "node")
        .attr("transform", function(d) { 
          return "translate(" + d.y + "," + d.x + ")"; 
        })
      node.append("circle").attr("r", 8).attr("fill", "#999");
      node.append("text").attr("dy", 3).attr("x", function(d) { 
        return d.children ? -12 : 12; 
      }).style("text-anchor", function(d) { 
        return d.children ? "end" : "start"; 
      }).attr("font-size", "200%").text(function(d) { 
        return d.data.name; 
      });
    }
    """
  end
end


%{
  "children" => [
    %{"name" => "B"},
    %{
      "children" => [%{"name" => "D"}, %{"name" => "E"}, %{"name" => "F"}],
      "name" => "C"
    },
    %{"name" => "G"},
    %{"children" => [%{"name" => "I"}, %{"name" => "J"}], "name" => "H"},
    %{"name" => "K"},
    %{"children" => [%{"name" => "M"}, %{"name" => "N"}], "name" => "L"},
    %{"name" => "O"},
    %{"name" => "P"}
  ],
  "name" => "A"
}
|> Jason.encode!()
|> KinoD3.Tree.new()

```

以上。
オペレーションズリサーチにおけるビジネス課題の解決とは？

この記事は[Jij Inc. Advent Calendar 2023](https://qiita.com/advent-calendar/2023/jij_inc_2023)の1日目の記事です

はじめまして、[株式会社Jij](https://www.j-ij.com/ja)の森田洋平と申します
いよいよ本日よりアドベントカレンダーが始まり、ワクワクしています！

本日のトピックは以下の通りです

１.簡単な経歴
２.オペレーションズリサーチとは？
３.オペレーションズリサーチがどのようにビジネスに役立つのか？

## １．簡単な経歴
私は、電機メーカにおいて知的財産、新規事業化に向けた研究開発及びプロジェクトマネジメントを経験した後、自動車メーカにおいて知的財産、技術戦略、DX推進の経験を経て、現在に至ります。
また、学生時代は純粋数学に没頭した経緯もあり、現在、会社に勤めながら大学院に通って、代数幾何学の研究を通じてPh.Dの取得に向けて研究にも勤しんでいるところです。
今回のテーマであるオペレーションズリサーチについては、学生時代に経営工学に所属していたこともあり、その経験や現在の仕事を通じて学んだことをもとに今回の記事においてご紹介します

## ２．オペレーションズリサーチとは
オペレーションズリサーチとは、そもそもどのようなものか簡単にご説明します。

オペレーションズリサーチ（Operations Research、またはOR）は、複雑な意思決定問題を解決するための数学的モデリング、統計分析、アルゴリズムの開発を用いる科学的アプローチのことと言われております。

オペレーションズリサーチは、限られたリソースを最も効果的に使用して、特定の目標を達成する最適な方法を見つけることが主な目的とされており、例として下記のような分野が含まれております。


<dl>
<dt>①数理最適化</dt>
制約条件の下で関数を最大化または最小化することにより、最適な解を見つける手法です。
とりわけ、線形関数を最大化または最小化することにより最適な解を見つける手法を線形計画問題、線形変数が整数である線形計画問題を整数計画法のように呼ばれています。

<dl>
<dt>②ネットワーク分析</dt>
ネットワーク内での最適なパスやフローを見つけるための手法。

<dl>
<dt>③待ち行列理論</dt>
待ち行列やサービスシステムにおける顧客の流れを分析する手法。

<dl>
<dt>④シミュレーション</dt>
複雑なシステムやプロセスをコンピュータモデルで模倣し、その挙動を分析する方法。

このように、オペレーションズリサーチは実社会における事象をもとに学問として確立されていった経緯があります。

## ３.オペレーションズリサーチがどのようにビジネスに役立つのか？
前述のように、オペレーションズリサーチは実社会に密接に関わっている分野であることは理解できたかと思います。
次に、とりわけオペレーションズリサーチにおける数理最適化がどのように実社会に貢献しているのかを例をもとにご説明します。

<dl>
<dt>①スケジューリング</dt>
製造業においては、複数の産業機器を用いて製造するため、複数の製造工程が並列に稼働しているケースがしばしばあります。これらを熟練者が勘と経験を通じてスケジューリングを立てる場合がありますが、それらは本当に最適な方法なのでしょうか？
そのような場合に、数理最適化が活躍します。
具体的には、複数の製造工程の中でどのようにリードタイムを短縮し、かつ、効率よく製造していくために、数理モデルを用いて求解していくことで、最適なスケジューリングを提案することができます。
また、上記では産業機器におけるものを取り上げましたが、作業員のスケジューリングにも適用できるため、製造業のみでなく、建設業、サービス業といった広い業界でも適用されています。
さらには、工場内全体の最適配置にも適用されています。

<dl>
<dt>②運用保守における最適化</dt>
製造機器における部品点数は製品によっては数千〜数万点にも及ぶと言われております。
そのような中で、部品の一点一点の運用保守は、これまでの知見や経験のもとでされていることがしばしばあります。
このような場合にも数理最適化が活躍します。これまでのデータなどを分析し、部品の故障予知をしながら、どのくらいのタイミングで運用保守をすることで、作業負荷を軽減できるかといった提案をすることができます。
また、運用保守においては、特殊な技能を持った作業員が必要な場合もあり、複数の拠点に巡回しながら作業する場合にも適切な巡回経路を提案することもできます。

<dl>
<dt>③エネルギーの最適化</dt>
エネルギーの削減や自給（自活）は、ESGの観点でも注目されています。
その中で、例えばデータセンターにおける稼働とエネルギーの需給バランスを最適化することは、昨今のDXのトレンドも相まって重要な課題の一つです。
具体的には、データセンターにおいては、サーバーの稼働とともにサーバーの冷却にエネルギーを多く必要とします。そのため、データセンター内における最適化な稼働を数理最適化を用いることでこれまでよりも効率的な運用をサポートできるというケースがあります。
また、これはデータセンターにとどまらず、スマートビルやスマートシティといったものにも活用可能です。
さらには、エネルギーサプライチェーン全体として、すなわち、原料の確保〜輸送〜発電〜送配電〜エンドユーザへの供給といった、エネルギーの全体バランスを最適化するためにも数理最適化が活用が推進されています。

以上のことはオペレーションズリサーチとしてのほんの一部分に過ぎませんが、数理最適化をはじめとして、様々なビジネス課題に対して活躍のフィールドが広がってきています。
これを機に関心を持ってくださると幸甚です。

## 最後に
＼Rustエンジニア・数理最適化エンジニア募集中！／
株式会社Jijでは、数学や物理学のバックグラウンドを活かし、量子計算と数理最適化のフロンティアで活躍するRustエンジニア、数理最適化エンジニアを募集しています！
詳細は下記のリンクからご覧ください。皆さんのご応募をお待ちしております！
Rustエンジニア: https://open.talentio.com/r/1/c/j-ij.com/pages/51062
数理最適化エンジニア: https://open.talentio.com/r/1/c/j-ij.com/pages/75132
駆け出しエンジニアの歩みと学び共有

## 結論
- 結局コミュニケーションが大切
- 習うより慣れよ

## はじめに
本記事は、エンジニアとしてまだまだ勉強中の身でありながらテックリードの任を受けた筆者が、これまでの経験で直面した壁とそこから学んだ仕事をする上で大切にしていることを記したものです。

結論がありきたりで興味を失ってしまった方も多いとは思いますが、それだけ気軽に読める内容なので身構えずにご覧ください。
なお、経験豊富な先輩諸兄にとっては本当に暇つぶしにしかならないことを先にお伝えします。

### 自己紹介
社会人６年目のサーバーサイドエンジニア
プロジェクトによってはフロントも触るが知識はほどほど
大学時代に一応情報系の学部を専攻しており、素人に毛が生えた程度のベースがあった

## 最初の壁 - これ聞いていいのかな
前述の通り全くの初学者と言う訳ではなかったことと、着任したプロジェクトがリリース前の新規タイトルでゴリゴリ開発していたこともあり、トレーナーの方にマンツーマンで指導を受けると言うよりは、最初から小さいタスクを割り振ってもらってわからないことがあれば聞いて方式でした。

当然最初のうちはお作法的な部分とか採用されてるフレームワークのディレクトリ構造などわからないことがたくさんあったので質問をしていました。
が、2ヶ月ほど経って少し慣れてきた頃から、タスクの難易度も徐々に上がっていき、どうやって作ればいいかもわからない時がやって来ることに。

そこで思ったのが「これ聞いていいのかな」

忙しい中時間を取らせるのは申し訳ない気持ちと、できないとは言いたくないプライドというか、失望されたくない気持ちから生まれた思いでした。

この後の流れから結論までありきたりなので詳細は割愛するが、当然結論としては**無駄な時間掛けずに確認せよ**です。

ただ、１ミリも考えず最初から教えてもらうスタイルだといつまで経っても自分で開発することができないので、筆者の場合は最大1時間まで自分で試行錯誤してみて無理だったら確認する方式を採用しました。

この結論に辿り着いたおかげで無駄にスケジュール遅延を発生させずに開発完了させることができるようになりました！

## 第２の壁 - 仕様書は完璧ではない
単純な開発にも慣れてきた頃、DBやAPI設計から対応することも増えてきた。仕様書を設計に落とし込むことになるが、与えられた設計書通りに書くだけだった頃より遥かに考えなければならないことが増えてお腹いっぱいになりました。

めちゃくちゃ考えて完璧だ…と思ったものも、レビューしてもらったらはちゃめちゃに指摘をいただいてしまうこともしばしば。
筆者の力量とか経験不足が招いたものは一旦置いておいて、ここでは外的要因、つまり仕様書に問題があるケースについて触れます。

そう。
「xxxの場合はaになることが正しい」というパターンが仕様書に網羅されていなかったり分かりづらかったりしました。
当然仕様書を書くのは人間なので、完璧な人はいないと思って良いでしょう。

ということで仕様確認をする必要があるのですが、これがまた難しい。。。
基本的に暇な人などいない上に部署が違うと本当にいつレスポンスが返ってくるか読めなかったりする。
中には本当に忙しすぎてチャットを追えていなかったりほぼ一日中会議で捕まらない場合もありました。

なので工夫をする必要がありました。
筆者は緊急度に合わせて以下の３パターンの手法をとっていました。
* 緊急度:高 → チャットで要点をまとめて確認事項を期日と共に投げつつ、直接聞けそうだったら聞く
* 緊急度:中 → チャットで要点をまとめて確認事項を期日と共に投げて待つ。期日の三日前くらいに直接聞けそうだったら聞く
* 緊急度:低 → チャットで要点をまとめて確認事項を期日と共に投げて待つ。期日の前日にリマインド

チャットなんてせずに最初から直接聞けばいいのでは、と思った方もいるかもしれない。

安心してください。理由ありますよ！

第一に、要点をまとめる作業を行うことで自分が質問したい内容を整理することができる点。

これは社会人なら必須スキルかと思うが、意外と何を聞きたいのかわからない質問をしてくる人がいる。
入社当初の筆者もそうでした。今でも自分の中で整理しきれてないときはよくわからない質問をしてしまっているかもしれないが、当時よりは遥かにマシになっているかと。鍛えてくれた当時のトレーナーさんには感謝してもしきれない。

第二に、相手の都合に合わせて回答してもらえる点。

前述した通り暇な人などいないので、すぐに確認してもらえるなどと思わない方が吉です。また、自分1人で仕事をしている訳ではないので、常に相手へのリスペクトを忘れないように心掛けたいですね。

第三に、証跡を残せる点。

口頭確認だけでは後々言った言わない問題やあれ、なんて言ってたっけ。。。と余計なトラブルを生むリスクがあります。
テキストとして残しておけばお互いにとっての備忘録となり設計の根拠としてチャットのリンクでも貼っておけばレビュワーにとっても安心材料になりますよね。

そういう訳で、口頭で確認した場合もチャットに確認した内容を追記するのがベターだと思います。

長々と書き連ねましたが、とにかく質問するときは以下３点を意識していれば大体うまくいくと思います！
* 自分の中で要点を整理する
* 自分本位の聞き方をしない
* 文章で残す

## 第３の壁 - 売上視点
ここまででそれなりに経験を積んできた筆者にやってきた最大の壁が、ビジネスとして成立させるために売上を意識する必要があるということでした。

プランナーが売上を出すために考えた仕様なので、100%開発することが売上に繋がるハズだが、限られた工数の中では最初に上がってきた仕様をフルで開発できることの方が稀だったりする。

そんな時に、一部分を丸っと削ったりもう少し工数を抑える内容に変更できないか、あるいは開発工数を追加するように提案・相談を行うのもエンジニアの仕事です。

ここで重要なのが、工数ではなく売上への影響を最大の判断基準とするべきということ。

極端な話、工数カツカツだからと超ミニマムでとりあえず実装したところで何も売上にプラスされなければ、その開発に掛けた工数の分だけ損失ということができる。

売上を立てるために必要な要素は残しつつ、工数に収まるようにプランナーとしっかり話し合うことが重要です。

また、筆者の場合は開発工数都合で一度何かの機能を削った場合、次の機能開発では多少無理してでも頑張るとか、突発対応を断らないとかでバランスを取るように心掛けている。
信頼関係が成り立っていないと仕事を円滑に進めることができないと考えているためです。

## まとめ
全ての壁に共通して言えることは、**適切なコミュニケーションを取りましょう**ということです。

また、コミュニケーションを取る前提ではありますが、最終的には物量によって磨かれた勘が全てを解決すると筆者は思っています。

筆者が憧れた先人達は大体勘所が冴えているというか、経験に裏付けされた勘によって颯爽とトラブルを解決していました。
なので、とにかく積極的に案件をこなして色んな経験値を蓄えていくのが優秀なエンジニアへの近道だと思って、筆者自身まだまだ精進していきたいと考えています。

最後までお付き合いいただいた皆様、ありがとうございました！
Delete directory with git command. 

Use the URL below.

https://qiita.com/ytkt/items/a2afd6be8e4f06c1ea25#%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%82%E4%B8%80%E7%B7%92%E3%81%AB%E5%89%8A%E9%99%A4%E3%81%97%E3%81%9F%E3%81%84%E3%81%A8%E3%81%8D
ActiveSupport::Inflectorでacronymを追加するときにはunderscoreメソッドへの影響にも注意が必要

Railsで、以下のように acronym (略語) を追加することがあります。

```rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
  inflect.acronym 'HTTP'
end
```

主に、定数名で使ったり、`humanize`で使ったりしたいときに設定すると思います。
今回、オートローダーを変更する際に、定数の検索方法が変わるということで、acronymを追加するかどうか、その影響を調査している際に当たりました。

https://railsguides.jp/classic_to_zeitwerk_howto.html#%E7%95%A5%E8%AA%9E%E3%81%AE%E6%89%B1%E3%81%84

## acronym を登録したとき

API documentに書いてありましたので、引用します。

https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html#method-i-acronym

acronymで`'HTTP'`を設定したとき、camelizeの挙動が以下のようになります。

```ruby
acronym 'HTTP'

camelize 'http'              # => 'HTTP'
camelize 'my_http_delimited' # => 'MyHTTPDelimited'
camelize 'https'             # => 'Https', not 'HTTPs'
```

`String#camelize`も同様です

```rb
'http'.camelize              # => "HTTP"
'my_http_delimited'.camelize # => "MyHTTPDelimited"
'https'.camelize             # => "Https"
```

`'https'`をcamelizeするときは`HTTPS`にならないのは想像がつくのですが、逆に、underscoreをすると、

```ruby
'HTTP'.underscore  # => "http"
'HTTPS'.underscore # => "http_s"
```

のように、影響してしまいます。
acronymに大文字が続く場合を想定しておく必要がありそうです

## その他 オートローダーに関連して

classic オートローダーでは定数読み込みの際に、[Railsガイド](https://railsguides.jp/classic_to_zeitwerk_howto.html#%E7%95%A5%E8%AA%9E%E3%81%AE%E6%89%B1%E3%81%84)にあるように、

> VATという定数に対してunderscoreが呼び出されてvatが生成され、これを元にvat.rbというファイルを検索することで、ファイルが正常に見つかります。

のようにunderscoreを使っていたようですが、zeitwerkではファイル名をcamelizeをするように変わったようです。

## 参考

https://api.rubyonrails.org/classes/ActiveSupport/Inflector/Inflections.html#method-i-acronym
wslでelixir その108

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

# 練習問題
Livebookでd3のclusterを、Mapから作れ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/93361778-e28c-2370-4757-9e06a7bfb191.png)

# セットアップ

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

# サンプルコード


```
defmodule KinoD3.Cluster do
  use Kino.JS

  def new(html) do
    Kino.JS.new(__MODULE__, html)
  end

  asset "main.js" do
    """
    import "https://d3js.org/d3.v5.min.js";

    export function init(ctx, json) {
       	const chartid = document.createElement("div");
    	chartid.id = "out";
    	ctx.root.appendChild(chartid);
    	var obj = JSON.parse(json); 
        var root = d3.hierarchy(obj);
       var cluster = d3.cluster().size([250, 250])
       cluster(root);
       var g = d3.select('#out')
          .append("svg").attr("width", 600).attr("height", 600)
          .append("g").attr("transform", "translate(300, 300)");

       var link = g.selectAll(".link").data(root.links()).enter().append("path")
        .attr("class", "link").attr("fill", "none").attr("stroke", "#555")
        .attr("stroke-width", "1.5px").attr("opacity", "0.6")
        .attr("d", d3.linkRadial().angle(function(d) {
      		return (d.x + 90) * Math.PI / 180;
      	}).radius(function(d) {
      		return d.y;
      }));
     	var node = g.selectAll(".node").data(root.descendants()).enter().append("g")
          .attr("transform", function(d) {
       	return "rotate(" + (d.x) + ")translate(" + d.y + ")";
       })
       node.append("circle").attr("r", 8).attr("stroke", "steelblue")
          .attr("stroke-width", "1.5px").attr("fill", "white");
      	node.append("text").attr("dy", 3).attr("dx", function(d) {
      		return d.x < 90 || d.x > 270 ? 8 : -8;
      	}).style("text-anchor", function(d) {
       	return d.x < 90 || d.x > 270 ? "start" : "end";
      	}).attr("font-size", "200%").attr("transform", function(d) {
      		return d.x < 90 || d.x > 270 ? null : "rotate(180)";
      	}).text(function(d) {
       	return d.data.name;
       });
    }
    """
  end
end


%{
  "children" => [
    %{"name" => "B"},
    %{
      "children" => [%{"name" => "D"}, %{"name" => "E"}, %{"name" => "F"}],
      "name" => "C"
    },
    %{"name" => "G"},
    %{"children" => [%{"name" => "I"}, %{"name" => "J"}], "name" => "H"},
    %{"name" => "K"},
    %{"children" => [%{"name" => "M"}, %{"name" => "N"}], "name" => "L"},
    %{"name" => "O"},
    %{"name" => "P"}
  ],
  "name" => "A"
}
|> Jason.encode!()
|> KinoD3.Cluster.new()


```

以上。
Cakephp4.5 から 5.0 への移行

基本的にはここを参照して rector をかける

https://book.cakephp.org/5/en/appendices/5-0-upgrade-guide.html

composer.json はここを参照して書き換える

https://github.com/cakephp/app

私の場合は特に config 周りは書き換えが必要だったので，仮の新しいappを作って，そこから新しいのを持ってきて，そこへ設定を入れ直したほうが早かった…

- config
-- app.php
-- bootstrap.php
-- bootstrap_cli.php
-- routes.php
-- paths.php
- src
-- Application.php
-- AppController.php

- TableRegistry::get が $this->fetchTable に変更

- JSON XMLの出力方法が変わった?
Cooking Bookの5.xは日本語にすると古い情報なので注意!('23 11/30現在)

https://book.cakephp.org/5/en/views/json-and-xml-views.html

- PasswordHasherのパッケージが変わった
Cake\Auth\DefaultPasswordHasher が Authentication\PasswordHasher\DefaultPasswordHasher に変更


その他にも出てきたら追記予定

https://book.cakephp.org/5/en/appendices/5-0-migration-guide.html
Python【超基本】

# Pythonの特徴
Pythonは他の言語に比べて、記述量が少ないのが特徴。
以下は、JavaScriptとPythonの記述の比較。

JavaScriptの場合
~~~JavaScript
let age = 18; // 年齢

if( age < 20 )
{
    // 未成年の場合
    console.log("ジュースで乾杯！");
}
else
{
    // 成年の場合
    console.log("お酒で乾杯！");
}
~~~

Pythonの場合
~~~Python
age = 18 # 年齢

if age < 20:
    # 未成年の場合
    print("ジュースで乾杯！")
else:
    # 成年の場合
    print("お酒で乾杯！")
~~~

どちらも実行結果は、
~~~
ジュースで乾杯！
~~~
となる。
# Pythonの書き方
Pythonの基本的なルールは以下。
- 文の最後にセミコロン（；）は不要
- 中かっこ｛｝で囲わず、インデントする
- コメントにはシャープ（#）、複数行コメントはシングルクォーテーション3つ（'''）もしくはダブルクォーテーション3つ（”””）を使う

## セミコロン（；）は不要
Pythonのコードは一行単位で意味を持ち、処理と処理の区切りに  ***「改行」***  を用いることで、処理の区切りであることを判断する。
## 中かっこ｛｝で囲わず、インデントする
Pythonの文法で特に独特なのは、処理のまとまりを表現するときに ***「インデント」*** を用いる。
インデントの単位はスペース4つが推奨されている。
## コメントはシャープ（#）またはクォーテーションを使う
コメントとは、書いてあるけれども実行されない行のことで、使い方は行頭に ***「#」*** を付けるだけ。

サンプルでいうと、
~~~Python
    # 未成年の場合
    print("ジュースで乾杯！")
~~~
となり、「未成年の場合」がコメント化されている。
# まとめ
Pythonの書き方の基本ルール
- 文の最後にセミコロン（；）は不要
- 処理のまとまりは中かっこ｛｝で囲わず、インデントでまとめる
- コメントにはシャープ（#）またはクォーテーションを使う
LPIC/Linux学習記録#6

〇自戒のための自己への宣誓
1. お前に足りないのはインプットだ！！！インプットしろ！！！インプットの奴隷になれ！！！
2. 記事の書き方とか今はどうでもいいから書け！！！インプットをアウトプットしろ！！！やる前からこだわりとか持つな！！！
3. 見られることとか評価されることとか気にするな！！！MECEとか構造化されてるかどうかとか気にするな！！！構造化はアウトプットの整地であって、インプットが足りないお前が手を出す領域ではない！！！ていうかお前頭良いんだからインプットに注力しろ！！歴史を刻め！！！歴史をまとめようとするな！！！未来を描け！！過去を清算するな若者め！！！！
4. 疑問を持つことを恥じるな！！！お前は頭はいいがインプットが足りない未熟者だ！！！インプットの奴隷になれ（再掲）！！！

〇学習記録
正規表現を勉強した。
特殊文字っていうのか、記号が意味を持っていて、それをパズルみたいに組み合わせることで様々な文字列を表現できる。

↓できること↓
①検索（特定のデータを見つける）→特定の文字列？
②置換（特定のデータを更新する）
③分割（特定のデータを分割する）
③検証（特定のデータを検証する）

すごいいっぱいあった。LPICの学習に任せる。
大事なのは、grepで正規表現で検索するには-Eオプションが必要だということ。
マッチした部分だけ抜き出したいときは-oオプションを付加し、再帰的にディレクトリ内部も見たい場合は-rオプションをつける。

ls /etc | grep conf
をすると、/etcのディレクトリ名に対してgrepできる（grepだけだとディレクトリ名を検索できない）。

複数コマンドの実行
A→B: A ;B
if A success, B: A && B
if A fail, B: A || B 

Pass the output of A to B: A | B　→grepには渡せるけどstatとかfileには引数として渡せなかった。どういう違いがあるんだろう。
→statやfileはパイプラインとの互換性がないらしい（標準入力を期待しておらず、コマンドラインでの入力のみ受け付けているらしい）。代案として、xargsをパイプラインと標準出力を渡したいコマンドとの間に挟む（パイプラインで標準出力をxargsに渡して、xargsの引数にその標準出力を渡したいコマンドを入れる）というのがあるらしい。↓
grep XXX | xargs stat
実際に試してみて、fileやstatに標準出力を渡すことができた。
Httpステータスコードのオリジナルエラー表示画面

##Httpステータスコードのオリジナルエラー表示画面

artisanコマンドを使うとエラー時のテンプレート画面を作ることができます。

`php artisan vendor:publish --tag=laravel-errors`

これで、viewsフォルダにerrorsフォルダができ、その中にエラー表示のテンプレートが作成されます。
Next.js Middlewareで特定の環境にIP制限をかける

## はじめに

この記事は[ファンタアドベントカレンダー2023](https://qiita.com/advent-calendar/2023/funteractive-inc)の3日目の記事です。

Next.jsのMiddlewareを使用してIP制限を付与する方法について紹介します。

※確認環境：next v13.4.9で、Pages Routerの使用を想定しています。

## **想定読者**

- Next.jsの[Middleware](https://nextjs.org/docs/app/building-your-application/routing/middleware)を使用して特定の環境にIP制限を設定したいと考えている方

## **実装方法**

### 1. **ミドルウェアの設定**

`src/middleware.ts` を作成し、以下のコードを記述します。

```jsx
import { NextRequest, NextResponse } from "next/server";

// ホワイトリスト形式で設定した許可IPアドレスを取得
const ALLOWED_IPS = process.env.NEXT_PUBLIC_ALLOWED_IPS
  ? process.env.NEXT_PUBLIC_ALLOWED_IPS.split(",")
  : [];

export default function middleware(req: NextRequest) {
  if (!ALLOWED_IPS || ALLOWED_IPS.length === 0) {
    console.error("Error: ALLOWED_IPS が設定されていません");
  }
  const forwardedFor = req.headers.get("x-forwarded-for");
  const ip = forwardedFor ? forwardedFor.split(",").at(0) : "";
  if (!ip || !ALLOWED_IPS.includes(ip))
    // クライアントのIPアドレスが許可IPアドレスに含まれていないならエラーにする
    return NextResponse.json({ error: "Access Denied" }, { status: 403 });
  return NextResponse.next();
}
```

### 2. npm scriptsの設定

IP制限を特定の環境でのみ使用したい場合、環境変数を設定してbuild時の処理を分けることができます。以下は環境変数`REQUIRES_MIDDLEWARE`を設定し、`REQUIRES_MIDDLEWARE`がfalseの時は `src/middleware.ts` が削除されるようにしています。

```json
"scripts": {
    "build": "[ \"$REQUIRES_MIDDLEWARE\" = \"false\" ] && yarn remove:middleware || true && next build",
    "remove:middleware": "rm ./src/middleware.ts"
  }
```

### 3. 環境変数の設定

`NEXT_PUBLIC_ALLOWED_IPS` という名前で値を以下のようにカンマ区切りで設定してください。

これで許可したIPアドレス以外からのアクセスを制限できます。

```rust
XXX.XXX.XX.XXX,XXX.XXX.XX.XXX
```

## おわりに

筆者はAmplifyでホスティングしているアプリケーションにIP制限を付与したかったのですが、現在AmplifyではIP制限を直接設定する機能は提供されていないため、今回紹介した方法で対応することになりました。

AmplifyでのIP制限設定に関する議論はこちらの[issue](https://github.com/aws-amplify/amplify-hosting/issues/36#issuecomment-1730153116)で確認することができます。

明日4日目の記事は信頼と実績を兼ね備えたPM、石田さんが担当します。ぜひご覧ください！
Laravleルート定義メソッド6選

laravelのルーティング定義で使う「ルート定義メソッド」を紹介します。

laravelルート定義メソッド

1. Route::get();
2. Route::get();
3. Route::post();
4. Route::put();
5. Rotue::patch();
6. Route::delete();
7. Route::options();
[React]  なるべく状態を少なくしたい

## たとえば、在庫数カウントと表示の分岐をひとつにまとめる
商品のJSONを**items**、売り切れのプロパティを**soldout**としている。
propsで親から渡ってきているとして、

```js
function itemStockLength() {
  return items.value.filter(item => item.soldout === false).length
}
```

この関数で売り切れでない＝在庫のある商品の総数が出す。
総数が0以下の場合は、そのカテゴリ自体を表示しない。
```jsx
// propsでカテゴリの商品がitemsとして渡ってきているとして

function itemStockLength() {
  return items.value.filter(item => item.soldout === false).length
}

return (
    <>
      {itemStockLength() > 0 ? (
        <Box>
          <Typography component='p'>在庫数：{itemStockLength()}</Typography>
          {items.map((item) => (
              item.name
              item.price
              ...
            )
          }
        </Box>
      ) : (
        <Box>
          <Typography component='p'>在庫のある商品はございません</Typography>
        </Box>
      )}
    <>
)
```
### 昔の自分のやっていたこと

```jsx
const [hasStock, setHasStock] = React.useState(true);
if(itemStockLength() <= 0) setHasStock(false);

return (
      {hasStock ? (
        ...
      ) : (
        ...
      )}
)
```
状態を持たせていた。



## 状態管理で大切なのは、状態の数を最小限にすること

たいていのシステムは、後半になると状態管理が複雑になって開発効率が落ちていく。
だから、作らなくてよい状態は作らないほうがよいのでは。
昔の自分は意識できていなかった。

Reactであれば、useStateの前に関数で解決できないか考えたい。
[TypeScript]bindメソッド再利用をスマートに！[デコレータ]

## デコレータを使ってbindメソッドをより効果的に利用する方法
前回の記事では、TypeScriptにおけるイベントリスナー内のthisの参照問題をbindメソッドを使用して解決しました。今回は、bindメソッドをもっと効果的に再利用する方法を紹介します！
その名も「デコレータ」です！

# 1. デコレータの基本
デコレータは、関数として宣言され、クラスやメソッドに対して様々な形で適応でき、コードの実行時に変更を加えることができます。

以下に基本的なデコレータの使い方を示します。

```typescript
function myDecorator(target: any, key: string, descriptor: PropertyDescriptor) {
  // デコレータの処理
  console.log(`デコレータが適用されました。対象: ${key}`);
}

class MyClass {
  @myDecorator
  myMethod() {
    // メソッドの処理
    console.log('メソッドが実行されました。');
  }
}
```
![スクリーンショット_20231130_095351.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570986/0d819c4d-f260-bf34-be18-abd539ef4e8a.png)

ここで、myDecoratorがデコレータ関数です。
このデコレータは @myDecorator の形でメソッド myMethod に適用され、対象のメソッドが実行される前にデコレータの処理が行われます。
デコレータ関数はターゲットクラスのインスタンス、プロパティの名前、ディスクリプタを引数として受け取り、処理を行います。

# 2. bindメソッドの再利用をデコレータで
次に、前回の記事で解決したthisの参照の問題に対して、デコレータを使ってbindメソッドをより効果的に再利用する方法を紹介します。

```typescript
// bindMethodデコレータの定義
function bindMethod(_target: any, _key: string, descriptor: PropertyDescriptor) {
    // オリジナルのメソッドを保持
    const originalMethod = descriptor.value;
  
    // ディスクリプタのvalueプロパティを新しい関数に上書き
    const adjDescriptor: PropertyDescriptor = {
      configurable: true, // プロパティの設定変更が可能
      enumerable: false,  // for...in ループで列挙不可
      get() {
        // バインドされた新しい関数を返す
        const boundFn = originalMethod.bind(this);
        return boundFn;
      }
    };

    // 調整されたディスクリプタを返す
    return adjDescriptor;
  }
  
  class MyButton {
    private buttonText: string;
  
    constructor(buttonText: string) {
      this.buttonText = buttonText;
      this.setupButton();
    }
  
    // ここで、bindMethodデコレータを適用！
    // デコレータによって返されたディスクリプタが適応され、bindされる！
    @bindMethod
    private handleClick() {
      console.log(this.buttonText);
    }
  
    private setupButton() {
      const button = document.createElement('button');
      button.innerText = this.buttonText;
      // ボタンクリック時にhandleClickメソッドを呼び出すリスナーを追加
      button.addEventListener('click', this.handleClick);
      document.body.appendChild(button);
    }
  }
  
  // MyButtonクラスのインスタンスを生成
  const myButton = new MyButton('Click me!');
```

![スクリーンショット_20231130_101638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3570986/ae2f540e-c2d3-af78-14b9-c9fd4f5d0043.png)
　　　　　　　　　　　　　　　　問題なくbindされている図

# まとめ
このようにデコレータを使用することで、bindを再利用することができます。
他にもbindを追加するべき問題が発生した時は、デコレータを適応するだけで解決できるようになります！これによりコードの冗長性を減少させ、効率的かつ可読性の高いコードを実現できます。

次回はデコレータの他の活用例や注意点についても触れながら、より深くデコレータを紹介していきます！
Google + Salesforce のすべてのサービス


+ [Native Gmail Integration for Salesforce](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XI8wb)

+ [apexクラスでgcp(google cloud platform)を認証する方法](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007XFjI1)

:::note
Please check this article.

https://gist.github.com/dhaniksahni/94acd0306b5216b647c94c2cd8af918c
:::


+ [Explore the Google and Salesforce Integrations](https://trailhead.salesforce.com/content/learn/modules/google-and-salesforce-partnership-quick-look/explore-the-google-and-salesforce-integrations)

**データ統合**
|統合	|説明|
|:------------------|:----------------------------|
|データクラウド + BigQuery|近日公開！2024 年 2 月に一般提供開始 : データを統合および調和させて、リアルタイムのデータ共有を通じて顧客の単一ビューを作成します。抽出、読み込み、変換 (ELT) は必要ありません。|
|Marketing Cloud + Sales Cloud + Google Analytics|マーケティング、販売、Web サイトのデータを結び付けることで、顧客との関わりを強化し、キャンペーンの効果についてより深い洞察を得ることができます。|
|ableau + BigQuery|Google BigQuery とのネイティブ統合を使用して、ビジネス ユーザー向けの実用的な分析情報を作成します。|
|MuleSoft + Google Cloud|MuleSoft の利点を享受しながら、既存のクラウド環境を使用して統合プラットフォームを管理することによる生産性とセキュリティの利点も提供します。|
|Salesforce & Slack + Google Workspace|従業員が毎日使用する生産性ツール (カレンダー、メール、スプレッドシート、ドライブ) で Salesforce ワークフローを利用できるようにすることで、従業員の生産性を向上させます。|


**人工知能**
|統合	|説明|
|:------------------|:----------------------------|
|データクラウド (Einstein Studio) + Vertex AI|2023 年 11 月に一般提供開始:独自の AI モデルを導入して、ハイパーパーソナライゼーションを推進し、意思決定を加速し、モデルトレーニングのための顧客データへのアクセスを簡素化し、既存の AI 投資の価値をより早く実現します。|

+ [Salesforce が Einstein Studio を発表: 独自の AI モデルを構築してデプロイ](https://qiita.com/Keiji_otsubo/items/54090b85ff56a7964a9b)
+ [Salesforce、企業が独自のデータを使用して AI モデルを構築およびデプロイすることを容易にする BYOM を開始](https://www.salesforce.com/news/stories/einstein-studio-ai-news/)
+ [Salesforce データクラウドと Vertex AI](https://www.salesforceben.com/salesforce-data-cloud-and-vertex-ai/)

### メリットは何ですか?
Model Builder の Data Cloud で Google Cloud Vertex AI モデルを使用すると、Vertex AI で厳選され、調和されたほぼリアルタイムのデータへのアクセスなど、いくつかの利点が得られます。これにより、退屈な ETL ジョブの必要性がなくなり、コストとエラーが削減され、データ クラウドに接続された統合プラットフォーム上で迅速なモデル開発、テスト、チューニングが可能になります。この統合により、関連する AI 出力のリアルタイム、ストリーミング、およびバッチ データの取り込みがサポートされ、Flow と Apex を介した Vertex AI 予測を使用して Salesforce Data Cloud でのビジネス プロセスの自動化が可能になります。

### なぜこれが大問題なのでしょうか?
Google Vertex AI とは何か、およびそれを Data Cloud と併用する利点について説明しましたが、これがなぜ重要なのでしょうか? 

簡単に言えば、これは、ユーザーの行動すべてが Salesforce 製品スイート内で行われるわけではないことを Salesforce が理解していることを示しています。結局のところ、人々は何年もの間、Google Vertex AI や Amazon SageMaker などのツールを使用してきました。これは、Lucy がAI Wars: How Salesforce's Agnostic LLM Approach Worksで話した内容です。

これは、これらすべてのテクノロジーを統合する機能を提供する Model Builder がいかに強力であるかを示しています。また、Salesforce の典型的な方法では、コードではなくクリックだけですべてが実行されるため、より幅広いユーザーがアクセスして利用できるようになります。


**データアクティベーション**
|統合	|説明|
|:------------------|:----------------------------|
|マーケティング用データクラウド + Google 広告|ファーストパーティのアクティベーションと洞察により、信頼関係を構築し、マーケティング パフォーマンスを向上させます。|
|Google ローカル在庫広告 + Commerce Cloud|Google ローカル在庫広告 (LIA) を使用すると、企業は地元の買い物客が探している商品を表示できるようになります。|
【Eclipse Neonどこ？】旧バージョンのEclipseをダウンロードしたい

こんにちは、tuna828です。

お仕事で環境構築のドキュメントに「Eclipse Neon」と指定があったのですが、
公式はもしや既に提供終了してる。。？
ということでネット上を漁ってみました。

### 日本語化プラグインとEclipse本体が同梱されたありがたいサイトを発見
だいたいのサイトに「mergedocからインストールできるよ」とあったのですが、
mergedocアクセスできひん。。。

企業買収がありURLが変わったようです。
↓からアクセスできます！
https://willbrains.jp/

（参考）
https://qiita.com/mm112233/questions/109cbb31777914305cc2
https://forest.watch.impress.co.jp/docs/news/1520393.html

### 無事インストールできました
よかったよかった。
IntelliJ で Scala Tutorial をやってみた

Kotlin を覚える時に IntelliJ で Kotlin Koans か何かをやったのが役に立ったので、Scala を使い始めるにあたっても同じようにしてみました。

内容としては [Scala Tutorial](https://www.scala-exercises.org/scala_tutorial/terms_and_types) ですが、IntelliJ 上で動かしながら学べます。

最後までやることで、Scala ほんのちょっとわかる、という気持ちになることができます。


## 開始方法

IntelliJ を起動し、File > Learn and Teach > Browse Courses で、Marketplace から Scala Tutorial を選択し Open します。


## 課題の模範解答を見て疑問に思ったところ

### ラムダ式を簡潔に書くための underscore について

Standard Library の List の課題の正解で、唐突に以下の表記が使われていました。

```scala
  val cond: (Int, Int) => Boolean = (_: Int) < (_: Int)
```

これは以下の長いラムダ式を簡単に書く方法のようです。

```scala
  val cond: (Int, Int) => Boolean = (x: Int, y: Int) => x < y
```

（参考）[Anonymous Functions](https://docs.scala-lang.org/scala3/book/fun-anonymous-functions.html)

新しい書き方を覚えたら使ってみたくなるものです。ですが、次 (Common Operations on Lists) の課題で早速誤った書き方をしてしまいました。以下の長い書き方

```scala
  def optionFlatMap(x: Option[Int]): Option[Int] = {
    x.flatMap(x => Some(x + 1))
  }
```

を underscore を使って

```scala
  def optionFlatMap(x: Option[Int]): Option[Int] = {
    x.flatMap(Some(_ + 1))
  }
```

と書けるかと思ったのですが、これは長く書き直すと

```scala
  def optionFlatMap(x: Option[Int]): Option[Int] = {
    x.flatMap(Some(x => x + 1))
  }
```

なので、全然違う意味になるのですね。なにがおかしいのかわからず、しばらく悩んでしまいました。


### Covaliance の課題の解答について

解答は

```scala
  class AnimalVet[+T](val animal: T)
```

となっていたのですが、

```scala
  class AnimalVet[+T <: Animal](val animal: T)
```

のほうが適切だと思います。というのは、前者の定義だと

```scala
    val intVet = new AnimalVet(1)
```

という、整数 1 を治療する謎の獣医が存在できてしまうためです。
吹き出しアイコンからフィードバックを送っておきました。