OmniAICreator/Qiita-1.07M huggingface dataset:
初ハッカソンの感想

# はじめに
こんにちは!
**akito-0520**です。
今回はAsianCallengeCupと呼ばれるハッカソンに出てみて感じたことをまとめてみました！
初投稿なのでみにくいかもしれませんが、ぜひ読んでみてください!
# 目次
- ハッカソンの概要
- ハッカソンに出た理由
- ハッカソンに出てみた感想
- まとめ
## 1. ハッカソンの概要
今回参加したハッカソンは3月25日から27日で開催された、株式会社AsianBridge様が主催のAsianCallengeCup（アジチャレ）と呼ばれるハッカソンに参加させていただきました。テーマは「クラウドを使って金沢を彩るWebアプリの開発」で、金沢の魅力を増幅・発信できるようなアプリの開発することです。
## 2. ハッカソンに出た理由
ハッカソンに出た理由としては主に2つありました。
**1. 学習したReactをoutputする**
-もともと2月頃にUdemyでReactの教材を購入して学習していたのですが、ただinputするだけでは意味がないと思い、なにかoutputする機会を探していました。アジチャレが開催されることを知り、開催される期間が春季休業の後半だったことからちょうどいいタイミングだと感じ参加を決めました。

**2. チーム開発をしたかった**
-今まで何度か開発をする機会はあったのですが、そのほとんどは個人開発でした。その中で考えていたのが実際に社会に出て開発をするときはチーム開発がほとんどなので何度かチーム開発を経験しておきたいと感じていたため参加を決めました。

## 3. ハッカソンに出てみた感想
実際にハッカソンに出てみると想像以上の経験を味わうことができました。
- **楽しかったこと**
    - ハッカソンではテーマに沿って金沢をどのように彩っていくかということを話し合った結果、ビンゴを通して楽しんでもらいながら金沢に埋もれた隠れた名店を見つけるWebアプリの開発をチームとしての目標として開発をしていきました。その中でフロントエンドの機能を私がメインで開発していったのですが、創り上げていく中で想像していたものが形として出来上がっていくことがとても楽しかったです。また、他のフロントエンドの開発メンバーが作成した機能などが合わさって出来上がっていくことにとても喜びを感じました。
- **難しかったこと**
    - 教材を学んだことは開発する中でとても役に立ちましたが、やはり教材だけでは学べないような要素が多くありました。また、チーム開発ということもありみんなが想像しているものについて一致しないことが多々ありました。そのため開発する時間をかなり削られたのが難しさを感じました。それに、ハッカソンは時間が限られているため時間配分をうまくに設定することが大切ですが、今までの経験がなかったためうまくいかずに完成できなかったことにも難しさを感じました。

## 4. まとめ
以上のように面白かったことや難しかったことなどたくさんありましたが、ハッカソンに参加したことで個人開発では体験できないようなさまざまなことを経験することができました。
足りない知識についてはわからないときはすぐに有識者に聞き、今回感じたチーム開発やハッカソンの難しさはハッカソンが始まる前に前もって念入りに照らし合わせていき、数時間ごとにミーティングを挟むことで進捗を確認していくことで解決できるのではないかと考えました。
また、作品のフィードバックではフロントエンドがしっかりしていてユーザーが使いやすいように工夫がされていたと評価をしていただき嬉しかったです。
まだまだスキルがないため迷惑をかけたと思いますが、一緒に開発をしてくれたメンバーには感謝しかないです。
今後もこのまま終わりではなく完成させるまで取り組んでみようと思います。

### 追記
記事を最後まで読んでいただきありがとうございました!
また記事を書くことがあれば読んでいただけると嬉しいです
picoCTF 2021 writeup Obedient Cat

### Obedient Cat (General skills)
This file has a flag in plain sight (aka "in-the-clear"). Download flag.

添付されていたのは拡張子の分からないflagというファイルであった。
とりあえずメモ帳で開くとflagが得られた。

`picoCTF{s4n1ty_v3r1f13d_f28ac910}`
fish curve(魚曲線)を描く


https://en.wikipedia.org/wiki/Fish_curve

Fish Curve魚曲線を描くプログラムです。

```math
x=a\cos(t)-\frac{a\sin^2(t)}{\sqrt2}
```
```math
y=a\cos(t)\sin(t)
```
ここで、aは全体の拡大率です。
パラメータ変化による間隔を見るため、小円を描いています。
※コードを短くするため、始点と終点で隙間が空いています。

```java:fishCurve.pde
size(800, 800);
background(0);
translate(400,400);

float x,y,a;

beginShape();
  a = 300;
  for(float th=0; th<2*PI; th+=0.05){
    x = a*cos(th)-a*sin(th)*sin(th)/sqrt(2);
    y = a*cos(th)*sin(th);
    curveVertex(x, y);
    circle(x,y, 10);
  }
endShape();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/e4c0e0f9-bd1e-9537-bce4-53f636578eee.png)

wikiの、もう一つの式
```math
(2x^2+y^2)^2-2\sqrt2ax(2x^2-3y^2)+2a^2(y^2-x^2)=0
```

```java:fishCurve.pde
size(800, 800);
background(0);

float a=1;

for (int yy=0; yy<800; yy++) {
  for (int xx=0; xx<800; xx++) {
    float x=xx/200f-2;
    float y=yy/200f-2;
    float s = pow(2*x*x+y*y,2)-2*sqrt(2)*a*x*(2*x*x-3*y*y)+2*a*a*(y*y-x*x);
    if(s<0)
      set(xx, yy, color(255));
  }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/ff5ed588-1549-5035-96f4-6d362853d30d.png)

ここで、登場するpedal curveとは。
楕円を例にすると、
①楕円の任意の点の接線を考える。
②原点からその接線に、垂直な線を描く。
③その交点が、通る軌跡がpedal curve
```java:fishCurve.pde
size(800, 800);
background(255);
translate(400,400);
noFill();

float r,x,y,a,b;
a = 2;
b = 1;

beginShape();
  for(float th=0; th<2*PI; th+=0.01){
    r = sqrt(a*a*cos(th)*cos(th)+b*b*sin(th)*sin(th));
    x = r*cos(th);
    y = r*sin(th);
    curveVertex(x*100, y*100);
  }
endShape();

stroke(255,0,0);
beginShape();
  for(float th=0; th<2*PI; th+=0.01){
    x = a*cos(th);
    y = b*sin(th);
    curveVertex(x*100, y*100);
  }
endShape();
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/510257/481661f3-cd2e-ac8f-46f7-4c7e42fac558.png)

https://en.wikipedia.org/wiki/Pedal_curve
「AWS」 Amazon EC2とは

# Amazon EC2とは
「Amazon Elastic Compute Cloud」の略称です。
Elasticという意味は「柔軟性・弾力性・伸縮性」といった意味が挙げられます。
ちなみにCloudというのは本来「雲」という意味ですが、コンピューターネットワークを「雲」に見立てているのでCloudと呼ばれているそうです。
AWSが提供する「仮想サーバサービス」
AWSで利用できるシステムで、仮想サーバを構築して自由に利用できます。

# EC2利用するメリット
オンプレミスサーバ運用に比べて、メリットが多いです。
具体的なメリットとしては
「サーバを構築するにあたり大幅な時間短縮」「柔軟性」「コスト軽減」
「サーバの冗長化を行うにあたっての時間短縮」
が主なメリットとして挙げられます。

:::note warn
警告Amazon EC2は従量課金制で利用できるため、稼働させた分だけ料金が発生します
::: 
# EC2では「インスタンス」という単位で仮想サーバを扱う
インスタンスにはいろいろな種類があるので、利用者(ユーザー)の求める使い方が可能です。
インスタンスを複数に使い分けることによって仮想サーバを分割します。
そうした場合、可用性・信頼性を考慮した運用が可能となるのでおすすめです。
主なインスタンス例
オンデマンドインスタンス-利用した分だけ料金が発生
リザーブドインスタンス-1年or3年の利用契約で利用料が割引
スポットインスタンス-特殊な形式
「AWSが用意している余剰のリソースを安価で利用できるサービス」

# 最後に
AWSには様々なサービスを提供しているので、クラウド上で様々なシステムを構築できます。
無料利用可能サービスもあるので、ぜひ使ってみてください。
個人開発でのgit flow 運用方法

# 初めに
チームで開発していく中でgitの運用をしっかりすることが大事だと考えているので、個人でできる範囲でgitを上手に運用する方法をまとめました。

# git flow

# 1.mainとdevelopを作る
mainブランチとdevelopブランチは必須で残しておくようにしてました。mainブランチは本番環境でブラウザに表示させる用のブランチです。このブランチでは開発をしません。developブランチでは本番環境でブラウザに表示させる前のテストをするブランチです。このブランチでも開発はしません。最後に本番環境にプルする時にdevelopブランチをmainブランチにマージしてました。

# 2.featureとhotfixを作る
featureブランチはdevelopブランチから派生します。僕は作りたい機能ごとにこのブランチを作ってました。たとえばajax処理に更新を加えたい時
```
feature-ajax-update
```
のような感じです。
gitのコマンドの流れはこれです。
```
ブランチを作ってチェックアウト
git checkout -b

リモートリポジトリにブランチを登録
git push origin

変更したファイルをステージングに乗せる
git add 

コミット内容を登録
git commit -m “    “

リモートリポジトリに反映
git push origin 

リモートリポジトリでプルリク、マージ、リモートブランチを削除

テスト環境に移動
git checkout develop

変更をマージして
git merge

ブランチを切る
git branch -d 

```
hotfixブランチはテストをしている時に見つかったバグを修正するブランチです。
例としてパスワードリマインダー機能でバグが見つかった場合
```
hotfix-password-forgot
```
のようなブランチ名にしてました。

git のコマンドの流れはfeatureブランチと同じです。


# 最後に
webアプリがどのように運用されているのかわかってよかったです。
ユーザーに安全に使ってもらうには本番環境やテスト環境など開発の段階でしっかり手順を踏むことが大事だとわかりました。
僕はこの考えを知る前は平気でmainブランチやdevelopブランチで開発していたので今後そのようなことがないように気をつけていきます。

# 参考文献

https://takeda-no-nao.net/programming/git/git-branch-naming-convention/

gitflowの基本を学ぶことができました。
ありがとうございました!
cscの作法 その495

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
DataTableを、CSV出力せよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/bde51548-f8db-dc29-568e-fe574bbcd791.png)

# サンプルコード

```
using System;
using System.Windows.Forms;
using System.Drawing;
using System.Data;
using System.IO;
using System.Text;

class form1: Form {
	ComboBox comboBox1;
	DataTable dt;
	DataGridView gd0;
	form1() {
		Text = "csv out";
		ClientSize = new Size(400, 300);
		comboBox1 = new ComboBox();
		comboBox1.Location = new Point(120, 10);
		comboBox1.Size = new Size(100, 25);
		comboBox1.Items.Add("");
		comboBox1.Items.Add("赤");
		comboBox1.Items.Add("黄");
		comboBox1.Items.Add("紫");
		comboBox1.Items.Add("橙");
		comboBox1.Items.Add("緑");
		comboBox1.SelectedIndex = 0;
		comboBox1.SelectedValueChanged += comboBox1_SelectedIndexChanged;
		dt = new DataTable();
		dt.Columns.Add("id", typeof(int));
		dt.Columns.Add("Iro", typeof(string));
		dt.Columns.Add("Name", typeof(string));
		dt.Rows.Add(1, "赤", "りんご");
		dt.Rows.Add(2, "黄", "バナナ");
		dt.Rows.Add(3, "黄", "レモン");
		dt.Rows.Add(4, "赤", "トマト");
		dt.Rows.Add(5, "紫", "ぶどう");
		dt.Rows.Add(6, "橙", "みかん");
		dt.Rows.Add(7, "橙", "柿");
		dt.Rows.Add(8, "緑", "めろん");
		gd0 = new DataGridView();
		gd0.Location = new Point(20, 40);
		gd0.Size = new Size(350, 250);
		gd0.DataSource = dt;
		Button btn1 = new Button();
		btn1.Location = new Point(250, 10);
		btn1.Text = "csv出力";
		btn1.Click += btn1_Click;
		Controls.AddRange(new Control[] {
			comboBox1,
			btn1,
			gd0
		});
	}
	private void comboBox1_SelectedIndexChanged(object sender, EventArgs e) {
		string str = "Iro = '" + comboBox1.SelectedItem.ToString() + "'";
		DataTable _newFilteredDataTable = dt.Select(str).CopyToDataTable();
		gd0.DataSource = _newFilteredDataTable;
	}
	void btn1_Click(object sender, System.EventArgs e) {
		Encoding enc = Encoding.GetEncoding("Shift_JIS");
		using (StreamWriter sr = new StreamWriter("dt8.csv", true, enc))
		{
			foreach (DataRow row in dt.Rows)
			{
				sr.WriteLine(string.Join(",", row.ItemArray));
			}
		}
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}



```

# 実行結果

```
>type dt8.csv
1,赤,りんご
2,黄,バナナ
3,黄,レモン
4,赤,トマト
5,紫,ぶどう
6,橙,みかん
7,橙,柿
8,緑,めろん

```


以上。
Docker で Oracle DB を利用する

手元で Oracle SQL の実行結果を確認するため、Docker で構築した際の手順です。

# 手順

大まかな流れは　Oracle Database Software のダウンロード → image のビルド → 起動　です。

## 1. Oracle Database Software をダウンロード

下記ページから “Oracle Database XXc for Linux x86-64” をダウンロードします。

https://www.oracle.com/database/technologies/oracle-database-software-downloads.html#db_ee

ファイルサイズが大きいのでそこそこ時間がかかります。

## 2. 公式のリポジトリをクローン

下記リポジトリをクローンしてきます。

https://github.com/oracle/docker-images

## 3. ダウンロードしたファイルを配置

イメージのビルド時に必要なので 1. でダウンロードしたファイルを配置します。
配置場所は `OracleDatabase/SingleInstance/dockerfiles/[バージョン番号]` です。
ファイル名を変更したり解凍したりはしないでください。

## 4. image のビルド

下記コマンドを実行することで image がビルドされます。
私の環境では 15 分ほどかかりました。

```shell
$ cd OracleDatabase/SingleInstance/dockerfiles
$ ./buildDockerImage.sh -v バージョン番号 -e -i
```

バージョン番号は x.y.z の形なので、指定する値は `./buildContainerImage.sh -h` で確認してください。
例として 19c の場合は `./buildDockerImage.sh -v 19.3.0 -e -i` となります。

```shell
$ ./buildContainerImage.sh -h

Usage: buildContainerImage.sh -v [version] -t [image_name:tag] [-e | -s | -x | -f] [-i] [-p] [-b] [-o] [container build option]
Builds a container image for Oracle Database.

Parameters:
   -v: version to build
       Choose one of: 11.2.0.2  12.1.0.2  12.2.0.1  18.3.0  18.4.0  19.3.0  21.3.0 23.3.0
```

## 5. データ永続化用にディレクトリを作成

次の手順で作成する docker-compose.yaml と同じ場所に oradata ディレクトリを作成します。
ついでにホスト側との SQL ファイルの共有をやりやすくするために sql ディレクトリも作成しておきます。

```shell
mkdir ./oradata ./sql
```

## 6. 起動用の docker-compose.yaml を用意

5 で用意したディレクトリのある場所に下記内容で docker-compose.yaml を作成します。

```yaml:docker-compose.yaml
services:
  db:
    image: oracle/database:[tag]
    container_name: oracledb
    ports:
      - 1521:1521
      - 5500:5500
    volumes:
      - ./oradata/:/opt/oracle/oradata
      - ./sql/:/home/oracle/sql
    environment:
      - ORACLE_PWD=Oracle19
      - ORACLE_PDB=oracle
```

`image: oracle/database:[tag]` の `[tag]` 部分は 4 で作成した image のタグ名に合わせてください。
以下の場合は `image: oracle/database:19.3.0-ee` となります。

```shell
$ docker images | grep oracle
oracle/database         19.3.0-ee         31797cafc386   52 minutes ago   6.54GB
```


## 7. コンテナの起動

docker compose up でコンテナを起動します。

> #########################
> DATABASE IS READY TO USE!
> #########################

というメッセージが表示されれば DB の準備完了です。
初回起動時はそこそこ時間がかかります（私の環境では20分程度かかりました）。

## 8. コンテナ内で SQL Plus を利用して SQL を実行する

下記コマンドでコンテナに入り、SQL Plus で繋ぎます。

```shell
$ docker compose exec db bash
$ sqlplus SYSTEM/${ORACLE_PWD}@${ORACLE_PDB}
```

SQL ファイルを実行する場合は sql ディレクトリに配置し、SQL Plus で @sql/[sqlファイル名] を実行することでその SQL ファイルを実行できます。

```shell:コンテナ内
$ ls ./sql
select.sql
$ sqlplus SYSTEM/${ORACLE_PWD}@${ORACLE_PDB}
SQL> @sql/select.sql
```
ChatGPT のようなヌルヌルした増分テキスト表示をやってみたい

タイトルの通りです。Python の FastAPI で簡単なサンプルアプリを作成しました。

# 実行例
![streaming.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2629684/ae8e8181-03fe-d91f-d6ca-f3921bdf717f.gif)


# FastAPI のコード
HTTP は昔からストリームなので HTTP レスポンスのボディを逐次、送受信することは以前から可能でした。でも HTTPヘッダの `Content-Length` がネックでした。HTTPヘッダは最初に返さないといけないのでその時点でコンテンツサイズが未定の場合は `Content-Length` を設定できないからです。

HTTP1.1 が全盛の頃はコンテンツを細切れ（チャンク）にして送信していましたが今は、楽に実装できるようになりました。FastAPI は、`StreamingResponse` を使います。ブラウザ側は、HTTPレスポンスの `ReadableStream` を `getReader()` して `Reader` を取得します。

```py:main.py
import asyncio
from fastapi import FastAPI
from fastapi.responses import HTMLResponse, StreamingResponse

app = FastAPI()


# HTTPストリーミングレスポンスを返す
@app.get("/streaming")
async def streaming():
    text = '''吾輩は猫である。名前はまだ無い。どこで生れたかとんと見当けんとうがつかぬ。
何でも薄暗いじめじめした所でニャーニャー泣いていた事だけは記憶している。
吾輩はここで始めて人間というものを見た。しかもあとで聞くとそれは書生という人間中で一番獰悪どうあくな種族であったそうだ。
この書生というのは時々我々を捕つかまえて煮にて食うという話である。
'''
    async def generate_data():
        for c in text:
            yield c
            await asyncio.sleep(0.05)

    return StreamingResponse(generate_data(), media_type="text/plain")


# HTMLを返す
@app.get("/")
async def index():
    html = '''
<html>
    <body>
        <h1>Hello Streaming!</h1>
        <div id="foo" style="white-space: pre-wrap;"></div>

        <script>
        document.addEventListener('DOMContentLoaded', async function () {
            const div = document.getElementById("foo");
            const response = await fetch("/streaming", {method: "GET"});
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            const decoder = new TextDecoder();
            const reader = response.body.getReader();
            while (true) {
                const { done, value } = await reader.read();
                if (done) break;
                const text = decoder.decode(value);
                div.textContent = div.textContent + text;
            }
        });
        </script>
    </body>
</html>
'''
    return HTMLResponse(content=html)
```

# 実行方法

### フォルダ構成
```
./
├── docker-compose.yml
├── Dockerfile
├── requirements.txt
└── app/
    └── main.py
```

### Dockerfile

```dockerfile:Dockerfile
FROM public.ecr.aws/docker/library/python:3.12-slim
WORKDIR /app
COPY ./requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt
COPY app/. ./
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
```

### docker-compose.yml

```yml:docker-compose.yml
services:
  streaming:
    image: streaming:0.1
    build:
      context: .
      dockerfile: ./Dockerfile
    container_name: streaming
    working_dir: /app
    ports:
      - "0.0.0.0:8000:8000"
    volumes:
      - ./app:/app
```
### requirements.txt
```txt:requirements.txt
fastapi
uvicorn[standard]
```

### 実行
```shell
docker compose build

docker compose up -d
```

ブラウザで `http://localhost:8000/` を開く。

以上です.
GPT4でプログラマーは駆逐されるのか

## コラム記事

衝撃を持って迎えられ、今なお、話題に事欠かないGPT4ですが、生成AIはこれからもどんどんと進化していくことになるでしょう。既にGAFAですら後塵を拝しているOpenAIの勢いは、誰にも止められないだろう。

しかし、個人的な意見ではあるが、GPT4はまだまだ使い物にならないといった印象の方が強いです。

GPT4に依頼して、それ相当のコードを書いてもらおうと思ったら、それ相当のプロンプトを作成しないくてはならないことになります。それは相当面倒な話です。「それなら、自分でコードを書いた方が早くね」となります。

SIerではコードを書く前に、SEがExcelを使って仕様書を作成することになります。その仕様書をプログラマに渡してコードを書いてもらうことになります。仕様書をそのままGPT4に読ませて、プログラマと同じ品質のコードを生成してもらえるかといえば、そんな簡単な話ではありません。仕様書からそれ程のプロンプトを作ろうと思っただけで、気が遠くなりそうです。

GPT4を使ってコードを生成してもらったことは何度かあります。グーグル検索の代替えとして活用する分には割と使えます。しかし、非エンジニアがエンジニアを駆逐する程のものをGPT4を使って、生成できるかといえば、現時点では、まったく使い物にならないレベルといっていいでしょう。

GPT4を使って、部分的に生成してもらったコードの品質だけを評すれば、確かに出来は悪くないです。しかし、GPT4がコード生成で参考にした情報は、Qiita、Stackoverflow、はてぶろなどに載っていた情報のみです。GPT4がコード生成したといっても、これらの情報を参考にして殆どコピペしてコードを生成しただけに過ぎません。やっていることは、実質的に人がGoogle検索するのと差ほど変わらなくね？というのが実感です。

更に残念なことに、個人が作成した記事と、ライブラリの公式サイトとを比較して、公式サイトの情報の方が信頼度が高いといった判断を、GPT4はしてくれませんでした。また、コードに関していえば、エンジニアブログよりも、GitHubの方が参考になるたくさんのコードは眠っているはずです。それにも関わらず、GitHubのコードの中から、凄腕エンジニア達が作った、お手本のようなコードを選び出してくれるといったことをGPT4はしてくれませんでした。これができない事が、GPT4の現時点での限界だと思われます。現時点ではGPT4には推論がまったくできないと言われています。

しかし、GPT4は、これからも、GPT5、GPT6・・・と進化し続けていくことになろうかと思われます。いつの日か、エンジニアを凌駕するAIが生まれる日がくるかも分かりません。しかし、これ程、熱狂的に期待されているに関わらず、その日はまだまだ遥か先のような気がしてなりません。
Cognos Analytics 12.0でのログメンテについて

Cognos Analytics 12.0でのログメンテナンス対象をまとめた資料を公開しました。
ログメンテを検討する際、参考にしてみてください。

Cognos Analytics 12.0.2 on Windows Serverで確認した内容になっています。

https://www.slideshare.net/slideshow/cognos-analytics-1202-logmaintenancepdf/267206448
prisma db pull→prisma migrate devに失敗する

## Prismaとは
PrismaとはNode.jsのORマッパーの１つです。詳しい解説は他記事に譲りますが、下記2つの機能も持っています。

- **Introspection**
`npx prisma db pull`
接続しているRDB上のスキーマを取得して、Prisma上のmodelファイルであるschema.prismaファイルにpullできます。

- **Prisma Migrate**
`npx prisma migrate dev`
schema.prismaファイルの変更を接続しているRDB上のスキーマに反映できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2991958/89fbcb72-c1ee-a27e-8846-3f59cbd48c1c.png)


## prisma db pull→prisma migrate devに失敗
- 既存のMySQLデータをpullし、そのままprisma migrate devしようとすると失敗しました。

:::note
実行環境
Prisma 5.11.0
MySQL 8.0
OS: Alpine
node 18
:::

```shell
npx prisma init

npx prisma db pull

npx prisma migrate dev
```

:::note alert


Drift detected: Your database schema is not in sync with your migration history.

The following is a summary of the differences between the expected database schema given your migrations files, and the actual schema of the database.

...

We need to reset the MySQL database {database_name} at "localhost:3306"
Do you want to continue? All data will be lost.
:::
## 原因

Prismaではmigrateの履歴とRDBスキーマの間で齟齬が発生する場合Driftエラーを起こし、DBのリセットが必要になってしまうようです。
今回も、Prismaを入れた後にRDB側でテーブル変更を行っており、それにより上記のエラーが発生したと考えられます。
schema.prismaファイルでmodelを運用する場合はRDB側でテーブルを触らない方が無難だと思います。


## 解決方法
```shell
mkdir -p prisma/migrations/init

npx prisma migrate diff \
--from-empty \
--to-schema-datamodel prisma/schema.prisma \
--script > prisma/migrations/init/migration.sql

npx prisma migrate resolve --applied init

npx prisma migrate dev
```
移行差分のファイルを形成し、そのファイルを元に"applied"にマークします。migrationの起点に定めているようです。
そのままmigrate devするとうまくmigrationに成功しました！


## 補足1 appliedデータの削除
`npx prisma migrate resolve --applied init`で作成したappliedデータはschemaの_prisma_migrationsテーブル上にレコードとして残ります。
`prisma migrate dev`がうまくいかないときはappliedデータを用いてmigrateしようとするので、過去のappliedデータを消したいときはレコード削除しましょう。

## 補足2 collationの変更
上記解決方法のmigrate diffでマイグレーションを出力したファイルを直接編集することでcollationを変更できます。
schema.prismaファイル上でcollationを設定することはできないようです。

## 補足3 PrismaではCHECK制約を利用できない
`npx prisma db pull`時下記エラーが出ました。
Prismaでは現在(2024/4時点)、CHECK制約(check constraints)を利用できません。

:::note warn
These constraints are not supported by Prisma Client, because Prisma currently does not fully support check constraints. Read more: https://pris.ly/d/check-constraints

\- Model: {table_name1}, constraint: {constaraint_name1}
\- Model: {table_name2}, constraint: {constaraint_name2}
...

:::

この辺り、まだまだ手が届いていない部分もあるので開発が待たれますね。


## References
https://www.prisma.io/docs/

https://github.com/prisma/prisma/issues/11555

https://github.com/prisma/prisma/issues/12845

https://github.com/prisma/prisma/issues/3388

https://qiita.com/sumikei11/items/35491a43ac6e4d6ea5ca
経営者視点を持つエンジニアとは？

結論、会社が利益をあげるという目的にあった提案、行動ができる人。
またはそれを一緒に考えられる人だと思う。

エンジニアは当然エンジニアとして雇われているわけだから、コードを書いたり設計したりがメインの仕事だ。

だけどその仕事に注目してみると、会社が利益を上げるという点において理想的な行動を取れていないことがある。

じゃあ理想的な行動ってなんだろう？

新規開発案件と保守運用案件の二つの点から考えてみたいと思う。

## 新規開発案件の場合

ある新規のtoC向けのアプリ開発で経営者からこんな提案があった。

「ログイン方法はメールアドレス、Apple、Google、Facebook、Twitterといっぱい用意しよう！」

俺は思った。

「(いや新規のアプリでログイン方法いっぱい用意してどうするんだよ、コア機能作ってさっさとリリースしようぜ…)」

新規のアプリ開発だとなるべく早くリリースすることが求められる。

そんな中コア機能以外で時間のかかる実装をするわけにはいかない。

にもかかわらず何も考えずに「はいわかりました！すぐ実装に取り掛かります！」とか言うエンジニアは経営者視点とは言えないだろう。

外から見たら経営者の言う通りに動くいい子に見えるが、理想は、

「いや、ログイン方法いっぱい用意するとそれだけ時間がかかるし、ログイン方法は1つあればアプリは使えるのでそれで十分じゃないですかね？」

などと言って工数を減らす提案をすべきだ。

とにかくコア機能以外の部分を削りに削る提案をしまくる。

その提案を通すためにはいろいろ言い方があるけど、「時間がかかるし無駄だから」という風なことを言えばまともな経営者であれば納得するだろう。

マインドではなく技術的に求められる部分で言えば、早く安く開発ができる手法を持っているといいだろう。

アプリ開発でいえばFlutterを使って開発すれば1つのソースコードでiOS,Android両方のアプリが作れるし、ホットリロードでのUIの動作確認は実装工数を大きく減らせる。

DBでいえばFirestoreを使えば、CloudSQLなどDBのインスタンスを立てるよりはるかに安く済むし、APIの実装も必要ないので工数も減らせる。(その代わりセキュリティルールを書く必要があるがAPIを実装するより早いだろう)

そんな早く安く開発できる手法を提案し実行すれば、利益を上げるというゴールへの最高のパスになること間違いなしだ！

## 保守運用フェーズの案件の場合

保守運用のフェーズに入った案件であれば何が求められるだろう？

その案件でも共通して言えるのは、安定してアップデートできることだろう。

そのためには**プロジェクトに関わっている人を辞めさせないこと**が重要だと思う。

そのプロジェクトに詳しい人であればコードの内容はある程度把握してるし、プロダクトの仕様にも詳しいだろう。
環境構築でわからないことがあったらその人に聞けば大体解決できる。

そんな人が辞めたらアップデート頻度と質は間違いなく落ちる。

新しい人を雇うにしてもコストがかかれば開発費に充てにくくなるし、プロダクトの仕様や環境構築を手伝うのも面倒くさい。

じゃあ辞めないようにするために何ができるだろう。

なるべくその人にストレスなく気持ちよく働いてもらえれば辞められる可能性は下げられそうだ。

そのためには普段のコミュニケーションを大事にする必要がある。

対面でちゃんと挨拶したり、目を見て話したりする。
Slackなどのテキストでのやり取りの際はちゃんと感情が伝わるように絵文字やびっくりマークなどをつけたりする。

自分もこの辺りのコミュニケーションスキルは勉強中だが、とにかく相手に「この人と一緒に働きたい！」と思われるような人でいたいと思っている。

まあ一緒に働きたい！はちょっとハードル高い気がするが、とにかく当たり前にコミュニケーションを取れていれば相手は嫌な気持ちにはならないだろう。

辞める原因ランキングを見ても大体上位にくるのが人間関係なのだから、辞められないようにするためにはまずはコミュニケーションを大事にしよう。

コミュニケーションスキルと、ある程度の開発経験があれば、保守運用案件ではどんな人もマッチしそうな気がする。

案件によって、扱うアーキテクチャやフレームワークが自身のスキルセットとマッチしないことがあるけど、大した問題じゃない。

ある程度経験を積んだエンジニアであればすぐにキャッチアップできる。

それよりコミュニケーション能力がないエンジニアをアサインしたら、周りに気を遣わせ、その結果周りの生産性が落ち、最悪辞めてしまう可能性がある。そっちの方が問題だ。

エンジニアの技術的な面でいうと、自分以外のエンジニアに嫌われないコードを書くスキルが求められる。
そういうコードを書くと、コードを読む際のストレスによってエンジニアは辞めてしまうからだ。

CI/CD環境も重要だ。
開発以外の中で最も重要なタスクの一つを自動化できると、エンジニアのストレスを大幅に軽減できる。
エンジニアは技術が好きな人が多く、自身の開発体験が損なわれることを嫌う傾向にある。

嫌われないようなある程度質のいい開発環境と、できれば新しい技術にチャレンジできるような場を用意してあげれば辞められる可能性は下がると思う。

## まとめ

会社が利益をあげるという目的にあった提案、行動ができることが大事。

じゃあその提案、行動ってなんなのかを新規開発案件と保守運用案件の二つのパターンで考えてみた。

案件によって何が理想なのかは異なるけど大枠は合っていると思う。

スキルはもちろん大事だが適切に使わなければ宝の持ち腐れだ。

スピードが大事だって言ってるのに、鉤括弧の位置はここがいいという謎のこだわりを主張しあっている場合じゃない。

まあとはいえ必要なスキルが極端に偏ることはないから、結局バランスが大事ってことになる気がする。
アンケート用のメールテンプレート

[Salesforceのアンケートに戻る](https://qiita.com/Keiji_otsubo/items/ce153ec9d338d7af0d81)


+ [Salesforce アンケートでいくつかの問題に直面しています。マーケティング クラウドの電子メールのように、Web サイトへのボタンやリンクが含まれるコンテンツ ブロックを含む見栄えの良い電子メールをアンケートに使用することはできません。回答をそれぞれの連絡先にリンクバックしたいので、Marketing Cloud メールを使用してアンケートを名前付きアンケートとして送信する方法はありますか。](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007YwGPbSAN)

:::note
問題は、調査招待状レコードの調査リンク フィールドが通常の電子メール テンプレートから「非表示」になっていることです。考えられる回避策は、リンク フィールドのコピーであるカスタム フィールドを作成することです。次に、標準のリンク フィールドをコピーして、フローまたはトリガーをフィールドに設定します。

また、参加者 ID フィールドから派生した受信者情報を含むカスタム フィールドを作成することもできます。その後ろには、潜在顧客、連絡先、またはユーザーのレコード ID を含めることができます。

最後に、調査情報をトリガーするケース、機会、イベントなどに関する情報を追加できます。

すべてのアンケート参加者がキャンペーンに追加され、アンケートの招待状を生成して受信者のキャンペーン メンバー レコードに保存するフローが作成されました。これらのレコードは Marketing Cloud データエクステンション ([連絡先ビルダー] > [データ ソース] を確認) に同期され、ユーザーは Marketing Cloud で利用可能なパーソナライゼーション フィールドを使用してアンケートを送信できます。
:::


# メールテンプレートを使う

+ [アンケートでメールを送信するときのエラー](https://qiita.com/Keiji_otsubo/items/9af47adc8cf2c1ebc84e)
+ [アンケート レコードの既定の設定に電子メール テンプレートが表示されない](https://salesforce.stackexchange.com/questions/379038/email-templates-not-showing-on-default-settings-on-survey-record)
+ [電子メール テンプレートで独自の調査リンクを使用できますか?](https://trailhead.salesforce.com/en/trailblazer-community/feed/0D54S00000Kg6Qd)

調査の招待メール テンプレートは、従来のメール テンプレートではなく、Lightning メール テンプレートです。これらのテンプレートは、限られた非標準フィールドのみが差し込みフィールドとして使用できるという点で「特別」です。 

これらの電子メール テンプレートの名前は実際に変更することができ、必要に応じてそれらを呼び出すことができます。変更できないのは、テンプレート内の特別な差し込みフィールドです。それらを変更または削除すると、テンプレートはまったく機能しなくなります。私はこれらを何十も作成しましたが、慣れたら、HTML コーディングを使用してより良い画像を追加するなど、本当にクールなことを始めることができます。アンケートと、受信者がアンケートに回答してからアンケートを開始するためのトリガーとして、アンケートの最初の質問を取得するもう 1 つのアンケート。

+ [電子メールで送信する場合の調査の難問の翻訳](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgHMF)

:::note
これを言うのは面倒ですが、プロセスビルダーを使用して、別のメールテンプレートを設定できるようにします.

Flow でこれを (ネイティブに) 行うことはできませんが、この方法では、複数の調査と複数のテンプレートではなく、複数のテンプレートを使用して少なくとも 1 つの調査を行うことができます。
:::

+ [Error: The template relatedTo type must be a valid SObject, not SurveyInvitation. ](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JgAMD)

:::note

Survey Response Pack、Feedback Management - Starter、および Feedback Management - Growth ライセンスで利用可能

Available with the Survey Response Pack, Feedback Management - Starter, and Feedback Management - Growth licenses

Customize the Survey Invitation Email Templates
https://help.salesforce.com/s/articleView?id=sf.concept_send_email_template.htm&type=5
:::
TCPを使ったチャットアプリの作り方

### TCPチャットサーバー

```python
import socket
import threading

def client_thread(conn, client_address, rooms, clients):
    try:
        while True:
            data = conn.recv(1024).decode('utf-8')
            if not data:
                break  # クライアントが切断した場合
            
            command, room_name, message = data.split(',', 2)

            if command == 'JOIN':
                rooms[room_name].add(conn)
                clients[conn] = room_name
                print(f"{client_address} joined {room_name}")

            elif command == 'LEAVE':
                rooms[room_name].remove(conn)
                del clients[conn]
                conn.close()
                print(f"{client_address} left {room_name}")
                break

            elif command == 'MSG':
                for client in rooms[room_name]:
                    if client != conn:
                        client.sendall(f"{client_address}: {message}".encode('utf-8'))

    except Exception as e:
        print(f"Error: {str(e)}")
    finally:
        conn.close()

def main():
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_address = '0.0.0.0'
    server_port = 9001
    server_socket.bind((server_address, server_port))
    server_socket.listen()

    rooms = {}  # チャットルームとクライアントの管理
    clients = {}  # クライアントとその現在のルームの追跡

    print(f"Server started on {server_address} port {server_port}")

    while True:
        conn, addr = server_socket.accept()
        print(f"Connection from {addr}")
        threading.Thread(target=client_thread, args=(conn, addr, rooms, clients)).start()

if __name__ == "__main__":
    main()
```

### TCPチャットクライアント

```python
import socket

def main():
    host = 'localhost'
    port = 9001

    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
        sock.connect((host, port))
        print("Connected to the server.")

        while True:
            username = input("Enter your username: ")
            command = input("Enter command (JOIN, LEAVE, MSG): ")
            room_name = input("Enter room name: ")
            message = input("Enter message: ")
            full_message = f"{command},{room_name},{username}: {message}"
            sock.sendall(full_message.encode('utf-8'))

            if command == "LEAVE":
                break

if __name__ == "__main__":
    main()
```

### 補足説明

- **サーバー**:
  - TCPソケットを作成し、接続を待ち受けます。
  - クライアントからの接続ごとにスレッドを生成し、専用の関数で通信を処理します。
  - `JOIN`, `LEAVE`, `MSG` コマンドを処理し、対応するチャットルームにメッセージを配信します。

- **クライアント**:
  - サーバーに接続し、コマンド（JOIN、LEAVE、MSG）を入力してサーバーに送信します。
  - ユーザー名とメッセージを入力し、適切なフォーマットでサーバーに送信します。
  - `LEAVE`コマンドでチャットを終了し、接続を閉じます。
私たちの "アジャイル実践テク" を公開します

こんにちは！
ポーラ・オルビスホールディングスのITプロダクト開発チームでスクラムマスターをしている川田です。

私たちの開発チームではスクラムを使ってアジャイル開発を行っています。アジャイル開発の経験が無い状態からプロダクトをリリースするまでには紆余曲折を経験しましたが、その中でチームが実践しているプロセスや工夫している点についてご紹介します！:+1:

# スプリントの全体像
私たちのチームではスプリント期間を2週間と設定して開発を進めています。スクラムで定められているイベントは一通り行っており、その他にチーム独自のイベントも実施しています。
これらのイベントをまとめると、1スプリントのスケジュールは以下のようになります。チーム独自のイベントは:star:がついています。

:calendar: Week1 :calendar:
| | Mon | Tue | Wed | Thu | Fri |
|---|---|---|---|---|---|
| AM | スプリントプランニング | :star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |
| PM |   |   |   |   | :star:ミニレトロスペクティブ |

:calendar: Week2 :calendar:
| | Mon | Tue | Wed | Thu | Fri |
|---|---|---|---|---|---|
| AM | :star:ライトデイリースクラム<br>デイリースクラム | :star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |:star:ライトデイリースクラム<br>デイリースクラム |
| PM |   |   |   |   | スプリントレビュー<br>スプリントレトロスペクティブ |

スプリントプランニング、デイリースクラム、スプリントレビュー、スプリントレトロスペクティブについては、概ねスクラムの型通りに実施しています。そのため、今回はチームが独自に行っているイベントについて詳細にご紹介します！

# ライトデイリースクラム
私たちのチームでは、オフショアを活用して開発を行っています。現在協力いただいているのはベトナム:flag_vn:にいるオフショアチームで、言語や時差（日本はベトナムより2時間進んでいます）が異なるという問題があります。
そのため、先に業務を開始する日本のメンバーだけでライトなデイリースクラムを実施しており、これをライトデイリースクラムと呼んでいます。ネーミングはそのままです！:sunglasses:

ライトデイリースクラムのメリットは、日本とベトナムの時差を有効利用することで各チームの検査と適応を効率よく行える点です。日本チームにとっては業務を開始してすぐに軌道修正ができますし、オフショアチームに早くインプットすべき内容があるかについても認識合わせができるので、オフショアチームの業務開始にあわせてタイムリーに情報を提供できています。
また、日本チームにとっては2回デイリースクラムを行っているという感覚にはなりますが、コミュニケーションや検査・適応を行う機会が増えるという点では良いことだと考えています。スプリントイベントを待たずに状況に応じてチームでコミュニケーションを取って進められるのが望ましいですが、特にチームが立ち上がったばかりの場合は、プロセスとして明確に設定しておくことが効果的だと感じています。

# ミニレトロスペクティブ
スプリントレトロスペクティブで振り返りを行い、その結果として改善のためのアクションをリストアップします。その内容がタスク化できるもの（例えば「〇〇の設計書を最新化する」など）であればチケット化して次スプリントで実施すればよいですが、チームのマインドに関わるような、チケット化しにくいものもあると思います。忘れないように目につく場所に記載しても、業務に追われて結局できなかった、となるとせっかくの振り返りがもったいなく感じてしまいますね:cry:

よってスプリント中間でミニレトロスペクティブを行い、改善のためのアクションの実施状況を検査するタイミングを意図的に作っています。その場ではアクションが実施できていない場合はどうすれば進められるか、また実施できている場合であってもより効果を上げるためにはどうするかといった点を議論します。
2週間のスプリントだと週次でミニレトロスペクティブかスプリントレトロスペクティブを行うことになりますが、検査の頻度としてちょうどよいと感じていて、改善のためのよい意識付けの場になっていると思います。また、アクションが増える一方で効果が感じられない状態になると、改善に対するモチベーションが低下し、何を言っても変わらない、面倒だから何も言わないでおこう、という悪循環に陥る可能性があります。頻繁に検査を行うことで、うまくいかなかった場合の迅速な修正や取りやめるという決断がスピーディーにでき、改善に対するモチベーションの向上につながると考えています。

# 最後に
チームの構成やカルチャーによる影響が大きい部分もあると思いますが、今回ご紹介した私たちの取り組みが同様の悩みを抱えるチームの参考になれば嬉しいです！:smiley:
docker compose down と stop の違い

# はじめに
docker compose down と stop の違いを整理

# docker compose down
コンテナを停止し、```docker compose up``` で作成したコンテナ、ネットワーク、ボリューム、イメージを削除する。

https://docs.docker.com/reference/cli/docker/compose/down/

# docker compose stop
コンテナを停止するだけ（削除はしない）。

https://docs.docker.com/reference/cli/docker/compose/stop/

# 参考
- [docker compose down](https://docs.docker.com/reference/cli/docker/compose/down/)
- [docker compose stop](https://docs.docker.com/reference/cli/docker/compose/stop/)
Quote Templateのまとめ

[CPQ関係のまとめに戻る](https://qiita.com/Keiji_otsubo/items/344f5e11ff01f8316f58)


+ [CPQ quote template with Multiple Company Address](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000Jg724SAB)


:::note
I would try to utilize the dynamic section/content functionality with CPQ quote templates.  For example - Add a checkbox formula to your quote object that gets set to true when the quote record is for San Diego.  Then use this field as the Conditional Print Field on a Quote Template Section.  This means this section/content would be displayed on your quote pdf only if the field is set to True.  Then you could do the same for Toronto.  This dynamic display functionality is a huge benefit of CPQ quote templates and appears to be a perfect use case for what you're looking to achieve. 

CPQ 見積テンプレートで動的セクション/コンテンツ機能を利用してみます。例 - 見積レコードがサンディエゴ向けの場合に true に設定されるチェックボックス式を見積オブジェクトに追加します。次に、このフィールドを見積テンプレート セクションの条件付き印刷フィールドとして使用します。これは、フィールドが True に設定されている場合にのみ、このセクション/コンテンツが見積 PDF に表示されることを意味します。そうすれば、トロントでも同じことができます。この動的な表示機能は CPQ 見積テンプレートの大きな利点であり、達成しようとしているものに最適な使用例と思われます。
:::

+ [How to assign Quote Templates by user or profile](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000A8swYSAR)

:::note
If each profile should use only one template, you could take advantage of the "Quote Template Id" field on the quote.  You'd have to get this ID to fill dynamically via a price rule or some other process.  This of course won't work if each profile should have access to multiple templates though.

Have you thought about taking advantage of the conditional options available for the Quote Section records?  By conditionally displaying certain sections based on formula fields we have on our Quote object, we've been able to get our quote down to one record, and just swap out the sections based on the quote values. 

各プロファイルでテンプレートを 1 つだけ使用する必要がある場合は、見積の「見積テンプレート ID」フィールドを利用できます。価格ルールまたはその他のプロセスを介して動的に入力するには、この ID を取得する必要があります。ただし、各プロファイルが複数のテンプレートにアクセスできる必要がある場合、これはもちろん機能しません。
 
見積セクションのレコードに使用できる条件付きオプションを利用することを考えたことはありますか? Quote オブジェクトにある数式フィールドに基づいて特定のセクションを条件付きで表示することで、見積を 1 つのレコードにまとめ、見積値に基づいてセクションを交換するだけで済みます。
:::


+ [【未解決】Quote - List Price and Add Logo](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLLL7)
決定版： HTML textarea 要素の高さを Shift+Enter で自動調整する

チャットアプリでよくある Shift+Enter で改行、Enter で送信する方法を調べてみると色々な方法が見つかったので、それらの中から私が決定版だと思ったものを記しておきます。

# Shift+Enter で自動調整

```html
<html>
    <body>
        <textarea id="foo" style="resize: none; overflow: hidden;"></textarea>

        <script>
        const textarea = document.getElementById("foo");
        // Shift+Enter で自動調整
        textarea.oninput=function(){
          this.style.height = 'auto';
          this.style.height = this.scrollHeight + 'px';
        }
        </script>
    </body>
</html>
```

そもそも「Shift+Enterで改行」という設問が良くなかった。

textarea は shift の有無に関わらず Enter で改行を入力できるので、やりたいことは「垂直スクロールバーを使用せずにコンテンツをビューポート内に収めるために必要な最小の高さに調整する」ということになります。なので `scrollHeight` を使います。

https://developer.mozilla.org/ja/docs/Web/API/Element/scrollHeight

それだけだと高さは増える一方なので `this.style.height = 'auto'` でコンテンツが削除されたら減るようにします。

input イベントを用いていることにも留意ください。コンテンツの高さを計算できるのは入力された後だからです。 


# Enter で送信
input される前にイベントを捕まえたいのでこちらは keydown イベントを使います。

```html
<html>
    <body>
        <textarea id="foo" style="resize: none; overflow: hidden;"></textarea>

        <script>
        const textarea = document.getElementById("foo");

        // Shift+Enter で自動調整
        textarea.oninput=function(){
          this.style.height = 'auto';
          this.style.height = this.scrollHeight + 'px';
        }

        // Enterで送信
        textarea.onkeydown=function(e) {
          const isIMEComposition = e.isComposing || e.code === 229;
          if (e.key === 'Enter' && !e.shiftKey && !isIMEComposition) {
            console.log("Submit:", textarea.value);
          }
        }
        </script>
    </body>
</html>
```

Shift が押されていなくかつ日本語変換中でもないという判定を行います。`isComposing` は、イベントが変換セッションの途中であることを示します。`e.keyCode` の `229` は日本語変換確定時のEnterキーを表します。

https://developer.mozilla.org/ja/docs/Web/API/KeyboardEvent/isComposing

https://github.com/FlowiseAI/FlowiseChatEmbed/blob/main/src/components/inputs/textInput/components/TextInput.tsx#L41

以上です.
テリトリー

[まとめページに戻る](https://qiita.com/Keiji_otsubo/items/60afc2a8d211b6f7d89f)
[まとめN～Z](https://qiita.com/Keiji_otsubo/items/92f92bb9f668ca9688be)




+ [ユーザーテリトリー とは何でしょう？ロケーションとの違いについて](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007aj4nv)

:::note
ユーザテリトリーですが、概念はサービステリトリーと同じですが、こちらは営業担当に対しての地域での管理だと思います。

https://riberatec.com/blog/salesforce-territory-management-customization/

ロケーションはフィールドサービスのオブジェクトだと思います。

倉庫、サービス車、作業サイト、またはチームがフィールドサービス作業を実行する領域のその他の要素を表します。 

https://developer.salesforce.com/docs/atlas.ja-jp.object_reference.meta/object_reference/sforce_api_objects_location.htm
:::


# トレイルヘッド

+ [Assign Accounts, Rules, and Users to Territories](https://qiita.com/Keiji_otsubo/items/03334581596e1267a200)
マイナスの値を欠損値/ゼロに置換する(SPSS Modeler データ加工逆引き5-16)

# マイナスの値を欠損値/ゼロに置換する

![スクリーンショット 2024-04-08 13.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/320a34c9-30cd-c877-436b-d7567d39a64d.png)

## 1.想定される利用目的

・予測モデル精度向上のための前処理（異常値への対処）

## 2.サンプルストリームのダウンロード

https://github.com/yoichiro0903n/blue/raw/main/minus2null.str

## 3.サンプルストリームの説明

![スクリーンショット 2024-04-08 13.54.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cdfdf518-e068-127f-fb4b-c328e2027551.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2024-04-08 13.58.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/ca583625-cdb0-e68d-8c37-c41c3e6ebe8c.png)

#### マイナスの値を欠損値NULLに置換する

b.[置換]ノードを編集します。[置換]条件を指定し。[置換値]をundef（=NULL）にします。
![スクリーンショット 2024-04-08 13.58.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/aa5e51a3-60e4-ff4a-f51d-a5f6f1ac8a31.png)

[プレビュー]します。
![スクリーンショット 2024-04-08 13.58.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/aa356d7f-70e2-39f0-4d27-ae0d0656ba1a.png)

#### マイナスの値を0に置換する

c.[置換]ノードを編集します。[置換]条件を指定し。[置換値]を0にします。
![スクリーンショット 2024-04-08 13.59.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0d8c8f5e-bb50-23c9-7748-da427780c81a.png)

[プレビュー]します。
![スクリーンショット 2024-04-08 13.59.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/3a262ac6-f767-81bc-d433-31b96ff237a7.png)

#### 注意点

置換する値は用途によって選択します。例えば時系列予測を行う際には予測した機械学習した結果が理論上あり得ないマイナスになる場合はゼロに置換。何らかのマイナス計上を予測材料にする場合には欠損値にして学習に考慮しないなどが妥当です。

## 4.参考情報

#### ある値の幅を置換条件にする場合の参考記事

https://qiita.com/416nishimaki/items/322aa37855a62bdd2ad4

#### SPSS Modeler ノードリファレンス目次

https://qiita.com/416nishimaki/private/503037195081d3323eee

#### SPSS Modeler 逆引きストリーム集（データ加工）

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
Flutter講座(forROS2)01 Ubuntu22.04へのインストール

# 環境

この記事は以下の環境で動いています。

| 項目 |	値 |
|:--|:--|
| CPU | Core i5-8250U |
| Ubuntu | 22.04 |
| ROS2 | Humble |
| Flutter | 3.22.2 |

# 概要

ROS2自体はロボットの認識・制御を対象としたフレームワークであり、Rviz2などのデバッグ用のGUIはあるものシステムとしてのUI系(特に入力)に弱い点があります。このために今回はUIに特化したフレームワークであるFlutterをROS2と接続させることに挑戦してみます。

## 最終目標とするシステム全体

タッチパネルでロボットに指令を送ること、ロボットの状態を表示できることを目指します。HDMI接続のタッチパネルをUbuntuに接続することも考えられますが、入手性やコストを考えてネットワーク経由で接続したAndroidタブレットでROS2を操作することを目標とします。

以下のようにタブレットで操作をしたら、REST APIでROS2のノードに接続して、ロボット側の状態はWebSocketを使って受信します。

![all_system.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/cd920443-e212-5577-ca0a-a15a077961b3.png)

## Flutter

Flutterはモバイル向けのフレームワークです。特徴として

* OSSであり、無料で利用できる。
* （基本的に）同じコードでWindows、Linux、Android、iOS用のビルドを作成できる
※iOSビルドをするにはMacが必須
* Windows、Linux、Macで開発が出来る

ことが特徴です。

# Ubuntu22.04でのインストール

## flutter本体のインストール

```shell:flutter本体のinstall
sudo snap install flutter --classic
```

## Google Chromeのインストール

必須ではないですが、デバッグツールとして使用します。

```shell:GoogleChromeのinstall

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/googlechrom-keyring.gpg] http://dl.google.com/linux/chrome/deb/ stable main" | sudo tee /etc/apt/sources.list.d/google-chrome.list
curl -fsSL https://dl.google.com/linux/linux_signing_key.pub | sudo gpg --dearmor -o /usr/share/keyrings/googlechrom-keyring.gpg
sudo apt update
sudo apt install google-chrome-stable
```

## flutter doctorでの確認

インストール状況をチェックできるツールがあります。

```shell:flutter doctorの実行
flutter doctor
```

以下のようにAndroid関連以外は[✓]表示になっているはずです。  
（後ほどandroid SDKのインストールを扱います）

```text:flutter doctorの結果
Running flutter doctor...
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.19.3, on Ubuntu 20.04 (LTS), locale en)
[!] Android toolchain - develop for Android devices
[✓] Chrome - develop for the web
[!] Android Studio (not installed)
[✓] Linux toolchain - develop for Linux desktop
[✓] VS Code (version 1.86)
[✓] Connected device (1 available)
[✓] Network resources


! Doctor found issues in 2 categories.
```

# サンプルの実行

## プロジェクトの作成

```shell:プロジェクトの作成
mkdir ~/flutter_workspace
cd ~/flutter_workspace
flutter create myapp
```

## プロジェクトのビルド・実行

```shell:プロジェクトの作成
cd ~/flutter_workspace/myapp
flutter run -d linux
```

実行前にビルドを行います。しばらく時間がかかります。ビルド後に以下の画面が出現します。

![sample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254442/f9204041-f2a9-dd7c-e3d6-bdf408b4334d.png)

表示されたウィンドウの「×」ボタンを押すか、実行したターミナルで「q」を押すとウィンドウが閉じます。

# 目次ページへのリンク
[ROS2講座の目次へのリンク](https://qiita.com/srs/items/5f0d765343ca78f524ed)
cscの作法 その494

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
DataTableから、指定の列を、重複を除去して、配列で取得せよ。

# 方針

- DataView使う。

# サンプルコード

```

using System;
using System.Data;
using System.Linq;

namespace App
{
	class Program {
		static void Main(string[] args) {
			DataTable dt = new DataTable();
			dt.Columns.Add("id", typeof(int));
			dt.Columns.Add("Iro", typeof(string));
			dt.Columns.Add("Name", typeof(string));
			dt.Rows.Add(1, "赤", "りんご");
			dt.Rows.Add(2, "黄", "バナナ");
			dt.Rows.Add(3, "黄", "レモン");
			dt.Rows.Add(4, "赤", "トマト");
			dt.Rows.Add(5, "紫", "ぶどう");
			dt.Rows.Add(6, "橙", "みかん");
			dt.Rows.Add(7, "橙", "柿");
			dt.Rows.Add(8, "緑", "めろん");
			DataView dtview = new DataView(dt);
			dt = dtview.ToTable(true, "Iro");
			foreach (DataRow row in dt.Rows)
			{
				//Console.WriteLine("Iro: {0}", row["Iro"]);
			}
			string[] cols = new string[dt.Rows.Count];
			for (int i = 0; i < dt.Rows.Count; i++)
			{
				cols[i] = dt.Rows[i]["Iro"].ToString();
				Console.WriteLine("{0}", cols[i]);
			}
		}
	}
}
```

# 実行結果

```
>dt7
赤
黄
紫
橙
緑

```

以上。
招待ゲストユーザーからの予約



+ [元の質問](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007bLKyX)

Salesforce の招待状からの予約テンプレート フローを使用しており、それをエクスペリエンス サイトに埋め込みました。このリンクに従ってすべてのゲスト ユーザー権限を設定しました:

[ゲストユーザーのスケジュールの設定](https://help.salesforce.com/s/articleView?id=sf.ls_set_up_guest_users.htm&type=5)

Salesforce Scheduler では、[受信 新規ゲスト予定] 標準フローテンプレートが提供されており、認証されていない外部ユーザー (リードまたは見込み客) が従業員の予定をすばやくスケジュールできます。ユーザーは予定の適切な人、トピック、場所、および日時を容易に検索して選択できます。提供されている標準フローテンプレートを使用するか、またはテンプレートを基にフローを作成して、ビジネスニーズに合わせて新しいテンプレートをカスタマイズできます。


ただし、エクスペリエンス サイトでフローを実行すると、次のエラーが発生します:

:::note alert
You can’t modify this appointment. Select a required assigned resource, a work type, and a service territory before modifying an appointment.
:::


# 関連資料


+ [Salesforce Scheduler で予定を予約する際のエラー「そのサービステリトリーにはこれらの作業タイプグループに対応できる人がいないようです」](https://help.salesforce.com/s/articleView?id=000393232&type=1)
+ [ゲストユーザー共有ルールの作成](https://help.salesforce.com/s/articleView?id=sf.security_sharing_rules_guest.htm&type=5)

ゲストユーザー共有ルールは、特別な条件ベースの共有ルールであり、認証されていないゲストユーザーにレコードへのアクセス権を付与するための唯一の方法です。ゲストユーザー共有ルールでは、参照のみアクセス権を付与できます。
再帰の適切でない使い方

# はじめに

再帰処理万能論者だったのですが、再帰処理の弱点が見つかってしまったため共有します。

# 計算量の問題

計算量の問題が発生したのは以下のコードです。

```haskell
fibonacci :: Int -> Int
fibonacci 0 = 0
fibonacci 1 = 1
fibonacci num = fibonacci (num - 1) + fibonacci (num - 2)
```

あるいは、
```rb
def fibonacci(num)
  case num
  when 0
    return 0
  when 1
    return 1
  else
    fibonacci(num - 1) + fibonacci(num - 2)
  end
end
```

このコードの実行速度が明らかに遅いんですよね。

そこで、計算量を考えてみました。

<details><summary>実例で考えてみる</summary>

## 1. `fibonacci(3)`の例
`fibonacci(3)` = `fibonacci(2) + fibonacci(1)`
             = `fibonacci(1) + fibonacci(0) + fibonacci(1)`
計算量は
1. `fibonacci(1)`
2. `+`
3. `fibonacci(0)`
4. `+`
5. `fibonacci(1)`

で、5ステップですね。

## 2. `fibonacci(4)`の例
`fibonacci(4)` = `fibonacci(3) + fibonacci(2)`
             = `5ステップ + fibonacci(1) + fibonacci(0)`
             = `5ステップ + 3ステップ` 
計算量は
1. `5ステップ`
2. `+`
3. `3ステップ`

で、9ステップですね。

計算量はどの程度増えているでしょうか？

`9 / 5 = 1.8`、1.8倍の計算量ですね。

これ以降も考えてみると
`fibonacci(5)`は15ステップ
`fibonacci(6)`は25ステップ
`25 / 15 = 1.66...`
数が大きくなるにつれ、だんだんと収束していきます。

最終的には`(1 + √5) / 2（約1.618）`になるようです。

</details>

https://www.baeldung.com/cs/fibonacci-computational-complexity

この時の計算量を`O(Φ^n) Φ=(1+√5)/2`と書きます。
あるいは、シンプルに考えて`O(2^n)`でもいいでしょう。

まあ、数値はどうでもいいのです。
**重要なことは、「計算量が指数関数的に増えていく」ということです**。
## 指数関数的に増えていく

考えてみれば当たり前ですね。関数を実行する事に2度、自身を呼び出しており、毎回新しい計算をしているので。
（`fibonacci(n - 1)）` `fibonacci(n-2)`の2度）

そこで、以下のように書き換えて、すでに行った計算を行わないようにして解決しました。
新規の計算は、末尾を追加する時だけです。これをメモ化と言うらしい。

これで計算量は`O(n)`になります。
```haskell
fibonacci :: Int -> Int
fibonacci n = fibs !! n
  where
    fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
```

https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%A2%E5%8C%96

なお、フィボナッチ数列についてはiterate（反復処理）でも書けます。
rubyの`times`やJSの`for`などですね。
泥臭いやり方だと思っていたんですが、計算量は「メモ化した再帰処理」と同等です。

https://begin-javascript.set0gut1.com/algorithm.html

# 計算量以外の問題

もう一つの問題、それは「スタックオーバーフロー」です。

スタックとは「関数やメソッドを呼び出して、一時的に保存する場所」です。それがいっぱいになって、溢れちゃうんですね。

<details><summary>スタックオーバーフローのイメージ</summary>

先ほども出した例ですが
`fibonacci(3)` = `fibonacci(2) + fibonacci(1)`です。
このとき、`fubonacci(2)`はまだ分解されて、`fibonacci(1) + fibonacci(0)`になります。
この時、最初にあった`fibonacci(1)`はどうなるでしょう・・・

実行されるまで、保持されるわけですね。
この例では`3`という小さい数字なので問題は起きていませんが、
これが`10`だったら・・・？
`fibonacci(10)` = `fibonacci(9) + fibonacci(8)`
                           = `fibonacci(8) + fibonacci(7) + fibonacci(7) + fibonacci(6)`
             = `fibonacci(7) + fibonacci(6) + fibonacci(6) + fibonacci(5) + fibonacci(6) + fibonacci(5) + fibonacci(5) + fibonacci(4)`
             ...
 と、すでに恐ろしい数のスタックが発生しています。

</details>

これをうまく処理できる言語とできない言語があります。

処理できる言語（スタックオーバーフローが発生しない）
- JavaScript（末尾呼び出し最適化が導入されたもの）
- Haskell（遅延評価）

処理できない言語
- Ruby

言語の違いも意識して再帰を使用するのが良いですね。
# おわりに

https://x.com/SamuraiStats/status/1779695796742713745


さて、次は何を書こうかしら・・・

# 参考

https://www.baeldung.com/cs/fibonacci-computational-complexity

https://begin-javascript.set0gut1.com/algorithm.html
SQLSTATE[HY000] [2002] Connection refused の解決方法

# 初めに
laravelの開発中に
```php
SQLSTATE[HY000] [2002] Connection refused
```
というエラーが出たので、その解決方法を紹介します。

# 解決方法
mysqlを起動することで治った。

# 原因

そもそもmysqlを立ち上げていないことが原因だった。
職能間連携で想像力を働かせよう

## はじめに
https://qiita.com/official-events/06e1e6af790c81a75b7f

こちらのキャンペーンにある以下について、自身の経験をもとにうまく連携やコミュニケーションをするための「想像力」をキーワードにしてまとめてみたいと思います。
- **エンジニアとビジネス間、PdMとEM間のギャップ改善をトライしてみた**




## これまでやってきたお仕事
- ツールアプリの新規事業責任者（3年ほど）
    - 全体3名の少人数チームでスタート
    - 私（責任者+PdMの役割）、エンジニア1名、デザイナー1名
- ゲームアプリのマーケティングマネージャー（5年ほど）
    - 組織全体としてはビジネスサイド20名、エンジニア5名、デザイナー5名ほど
- 会社経営（4年ほど）
    - 組織全体としては40名弱
    - エンジニア、デザイナー、ビジネスメンバー

## 職能間連携で想像力を働かせよう
**目次**

* [職能間連携での想像力とは？](#職能間連携での想像力とは？)
* [想像力を働かせることのメリット](#想像力を働かせることのメリット)
* [想像力を身につける方法](#想像力を身につける方法)
* [最後に](#最後)


## 職能間連携での想像力とは？
まず職能間連携とは？

職能、いわゆる職務を遂行する能力が異なるメンバー同士での連携のことを指します。
簡単に言うとエンジニア×ビジネスだったり営業×デザイナーでの連携になります。
異なるスキルや役割を持った人同士が仕事やモノづくりにおいて連携することです。

よくある話で会社の部門間の連携、例えば営業部門と開発部門（よく対立の話が出ますが）などとは少し違い、今回は組織間の仕組み的な話よりも、より個人にフォーカスした人対人の話になります。

では、職能間連携における想像とは具体的に何なのか？

それは **「相手が何を考えて、何をするのかを想像すること」** だと思います。
例えば、ビジネス側のメンバーが契約してきた案件をエンジニアに依頼するとします。

その際に
**ビジネス側のメンバーは「これからエンジニアが何を考え何をするのか」**
**エンジニア側のメンバーは「ビジネスが何を考えて何をして契約を獲ってきたのか」**
を想像してみることです。




## 想像力を働かせることのメリット
私の経験上、想像力を働かせることによる一番のメリットは
**相手にとって適切な情報を伝えられるようになる**ということです。

例えばtoB向けのサービスで、開発面でのインシデントが起こった際
エンジニアから営業に対して何かしらの情報共有を実施すると思います。
その際に、例えばこういう想像をしてみるのをおすすめします。

- **本件に対して営業担当からお客様に伝える必要がある情報は何だろうか**
- **これから営業担当はどういう時間軸や優先度でお客様対応を進めるだろうか**

このようなことを意識して想像することで相手にとって必要な情報を伝えることに役立つと思います。
逆に相手のことを全く想像せずに開発視点だけでのコミュニケーションをとった場合は以下が発生します。

- **営業視点での必要な情報を聞かれるのでコミュニケーションがひと手間増える**
- **何度も繰り返すとお互い「こっちの事をわかっていない」という意識が芽生えてくる**

当たり前ですが事前に完全に相手が欲しい情報を想像するのは不可能だと思いますが、想像をして近い範囲のコミュニケーションをとることが大切だと思います。


## 想像力を身につける方法
仕事における想像力は経験や知識によって身につけていくものだと思います。
実際にこれまでやってみて効果があると感じた取り組みは以下のようなものがあります。

- 異なる職種から異なる職種のメンバーに対しての勉強会を実施する
    - 例えばデザインに関する勉強会をエンジニア向けに開催をする
- 商談に同席をする
    - 営業メンバーの商談に開発部門のメンバーが同席をする
- 議事録や日報など自部署以外のものを読む
    - しっかり読み込まなくてもざっと目を通す習慣をつけるだけでも効果があると思います
- 提供している事業やサービスの数値を把握しておく
    - 今何が伸びて何が課題になっているのか。状況を把握しておく
- 日々のインプットの幅を広げてみる
    - 自分の興味関心の範囲の情報は自然に入ってくるので、それ以外のものに目を触れる習慣をつける








## 最後に
これを読んで頂いたみなさんが、想像力を働かせることで生産性や社内でのコミュニケーションの向上に繋がれば幸いです。
jest.mockは1つのモジュールに対して1度だけ使用する

# はじめに
現在React×TypeScriptでアプリをつくりながら学習を進めています。
Jestでテストを書いていて苦戦したことがあるので、簡単にまとめます。
# 問題
**うまくモジュール化ができず、テストが通らない。。**
モック化については説明を割愛します。下記を参照してください。

https://jestjs.io/ja/docs/mock-functions

https://qiita.com/Fudeko/items/301f8a80963dfcaafb80
# 解決方法
**1つのモジュールに対して複数回モックを定義してはいけない**みたいです。

もし仮に複数回`jest.mock` を使用した場合、**後の `jest.mock` によって前の `jest.mock` によるモック設定が上書きされてしまう可能性**があります。
その結果、モックが適切に適用されなくなってしまうのです。

**×NG例**
**`"react-router-dom"`というモジュールに対して`jest.mock`が2回使用されています。
これだとうまく動かないので、1つにまとめてあげましょう。**
```tsx:test.tsx
// useParamsモック
jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useParams: () => ({ loginID: "test" }),
}));

// Navigatorモック
const mockedNavigator = jest.fn();
jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  useNavigate: () => mockedNavigator,
}));
```

**OK例**
コードの量も減ってすっきりしました。
```tsx:test.tsx
const mockedNavigator = jest.fn();
jest.mock("react-router-dom", () => ({
  ...jest.requireActual("react-router-dom"),
  // Navigatorモック
  useNavigate: () => mockedNavigator,
  // useParamsモック
  useParams: () => ({ loginID: "test" }),
}));
```
# おわりに
この事象についてChatGPTに尋ねると、**「jest.mock を一度だけ使用してモックを設定する必要があるという原則に関する公式ドキュメントはありませんが、これは一般的なベストプラクティスとして広く受け入れられています。」** と言われました。。そうだったんですね。。
もし同じようにも困っている方がいたらこの記事が救いになればと思います。