OmniAICreator/Qiita-1.07M huggingface dataset:
Azure Communication Services で日本の電話番号を取得する方法

# はじめに
[Azure Communication Services](https://learn.microsoft.com/ja-jp/azure/communication-services/overview) は Azure PaaS サービスの1つであり、ビデオ通話やチャット、メール送信の機能を提供しております。
その中に SMS 機能があり、電話番号を取得して SMS メッセージの送受信や電話の発着信が行えます。

今まで日本リージョンはサポートされていなかったのですが、現在電話の発着信のみ public preview となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/0df6cd49-8bba-bb60-db54-60bef0872099.png)

[日本の電話番号管理](https://learn.microsoft.com/ja-jp/azure/communication-services/concepts/numbers/phone-number-management-for-japan)

早速試してみたので、試した内容や気をつけるべきポイントをこの記事でご紹介します。


# やってみた

まずは Azure ポータルから Azure Communication Services を開きます。まだ作成されていない方は、[こちら](https://learn.microsoft.com/ja-jp/azure/communication-services/quickstarts/create-communication-resource?tabs=windows&pivots=platform-azp)より作成いただけます。

[電話番号]ブレードを開き、[番号の取得]を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/97241e70-19c1-2c14-7da5-6084c7ef2540.png)

日本リージョンを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/079aebdb-cb06-a05d-0a25-0d29414369c0.png)

上記画面でも記載されている通り、現在日本で電話番号を取得する際には、手動による特別注文を行う必要があります。
なので、[特別注文を要求する] を押下し、[管理番号ポータル] を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/d063d19a-551c-132b-e0dc-ff6972936a48.png)

下記のように選択し、後は必要情報を入力します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/290b2c87-a9b9-cf85-c74b-a28e7bfc727d.png)


私も引っかかったポイントとしては、”Azure Immutable Resource ID” という項目があります。これは、[こちら](https://learn.microsoft.com/ja-jp/azure/communication-services/quickstarts/voice-video-calling/get-resource-id)にも記載されている方法で取得する必要があり、[概要]ブレードの[JSON ビュー]からご確認いただけます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/b684d781-800b-4fa1-84c6-cceecc7d6153.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/ce135e36-75fb-6a55-e851-a6c9ca390631.png)

全て入力後は [Submit] を押下し、"Phone Number Service Center" より申請が通るのを待ちます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679419/c0f10df4-dcf9-bc55-fa6f-ef88d473552f.png)


# まとめ
申請が通った後は、[チュートリアル](https://learn.microsoft.com/ja-jp/azure/communication-services/quickstarts/telephony/get-phone-number?tabs=windows&pivots=platform-azp)に従って進めば取得できるはずです。
私も申請がまだ通っていないので、申請が通ったあとはこの記事の更新、あるいは新しい記事に書いてまとめます。
AWSの通信料まとめ

### 1. 同一リージョン内の通信

EC2インスタンスとS3バケットが同一のAWSリージョン内にある場合、その通信は通常**無料**

```markdown
- EC2 (us-east-1) ↔ S3 (us-east-1) = 無料
```

### 2. 異なるリージョン間の通信

EC2とS3が異なるリージョンにある場合、データ転送料金が発生。

```markdown
- EC2 (us-east-1) ↔ S3 (us-west-2) = 有料
```

### 3. VPCエンドポイントの使用


```markdown
- VPCエンドポイント使用 = エンドポイント料金あり、通信料金は通常無料
```

### 4. インターネット経由の通信

EC2からインターネット経由でS3にアクセスする場合、データ転送出口料金が発生する可能性あり。

```markdown
- EC2 ↔ インターネット ↔ S3 = 有料（出口料金）
```

### 5. Transfer Accelerationの使用

S3のTransfer Accelerationを使用すると、高速なアップロードが可能ですが、追加料金が発生。

```markdown
- S3 Transfer Acceleration = 追加料金あり
```
はじめてのChatGPT API 〜API呼び出し編〜

# はじめに
ChatGPTを使ったクイズアプリを作るにあたって、
前回はChatGPT APIについて得た情報をまとめたので、今回は実際にAPIを呼び出していきたいと思います！

また、開発中のあれこれについては以下のサイトでまとめています。
https://zenn.dev/kitaji12/scraps/a115ff66546e65

# 事前情報
- OpenAI / ChatGPT 初心者
- クイズアプリは React + Flask で作成

# 開発環境
- macOS Monterey 12.5
- Visual Studio Code 1.46.1
- Python 3.10.6
- Flask 2.3.2

# 準備
- [前回の記事](https://qiita.com/kitaji12/items/5ef3428f7c06bbbc7a75)で紹介したアカウントの作成からAPIキーの作成まで行う

# OpenAI ライブラリをインストール
Pythonのサンプルプロジェクトを作成し、OpenAIのライブラリをインストールします。
ターミナルを開き、以下のコマンドを実行します。
```
$ pip install openai
```

# APIキーを環境変数へ設定
次に、APIキーを環境変数にセットアップしておきます。
以下のコマンドの`API_KEY`の部分に、取得したAPIキーを置き換えて実行します。
```
$ export OPENAI_API_KEY = "API_KEY"
```

# ChatGPT APIを呼び出してみる
今回は最小構成でプロジェクトを作成し動かしてみます。
```
.
├── requirements.txt
├── test.http
├── test.py
```

必要なライブラリをまとめているテキストファイルです。
```:requirements.txt
Flask==2.3.2
requests==2.31.0
Flask-Cors==3.0.10
openai==0.27.8
```

`.http`ファイルで指定した HTTP 要求を送信します。
```:test.http
###
GET http://localhost:5000/
```

Pythonコードはこんな感じです。
```python:test.py
from flask_cors import CORS
from flask import Flask
import openai
import os

app = Flask(__name__)
CORS(app)

@app.route("/")
def test():
  openai.api_key = os.environ["OPENAI_API_KEY"]

  ## ChatGPTに投げる質問を記載する
  response = openai.ChatCompletion.create(
    model = "gpt-3.5-turbo",
    messages = [
      {"role": "user", "content": "ハリーポッターの最新作は"},
    ],
  )

  return response.choices[0]["message"]["content"].strip()

if __name__ == "__main__":
  app.run(debug=True)
```
- `model`：今回は **gpt-3.5-turbo** を使用
- `messages`：ChatGPTに投げる質問を記載する
    - `role`：どこからの問い合わせなのかを明記する
        - **user**：人間からの問い合わせ
        - **assistant**：GPTからの返答（以前の応答を保存するのに役立つ）
        - **system**：ChatGPTに与える役を設定するために使用
    - `content`：問い合わせや返答の文章を記載する

### 実行結果
**■ test.py**
ターミナルから`test.py`を実行した結果です。
サーバーがたったことが確認できました。
![test.py実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/41e94559-2054-4fce-410e-2af5ecefed22.png)

**■ test.http**
VSCodeから`test.http`を叩いた結果です。
精度は微妙ですが「ハリーポッター」に関する答えが返ってきました！
![test.http実行結果.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/07318caa-bfdf-8089-e79f-6fd7a0e705da.png)

# さいごに
ChatGPT APIを実際に叩いて結果が返ってくることが確認できました。
メッセージオブジェクトのroleパラメータを変えることでどんな目的で送ってきているかを判断できることを学びました！
クイズアプリの作成に向けて一歩前進したかなと思います。

# 参考サイト
- [Chat completions API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) 
- [ChatGPTに聞きながらChatGPT APIの使用手順を書いてみた](https://qiita.com/LingmuSajun/items/8ac6b016e0ecc864851e)
- [[初心者向き] OpenAI APIを使ってPythonでChatGPT遊びするための最初の三歩くらい](https://dev.classmethod.jp/articles/openai-api-chat-python-first-step/)
自動運転シミュレーション その5

# 概要
自動運転シミュレーションを開発している。
server,client方式に変更する。
serverをLivebookで、書いてみた。

# サンプルコード

```
defmodule ElixirSocketTesting.ClientAgent do
	def start_link do
		Agent.start_link(fn ->
			[]
		end, name: __MODULE__)
	end
	def add(client) do
		Agent.update(__MODULE__, fn list ->
			[client | list]
		end)
	end
	def remove(client) do
		Agent.update(__MODULE__, fn list ->
			List.delete(list, client)
		end)
	end
	def all do
		Agent.get(__MODULE__, fn list ->
			list
		end)
	end
end

defmodule Car do
	def agent(a) do
		res = ""
		v = a
			|> Jason.decode!()
			|> Map.get("observation")
			|> Map.get("s1")
		v = String.to_float(v)
		if (v > 0.4) do
			res = "{\"action\": 0}"
		else
			res = "{\"action\": 1}"
		end
	end
end

defmodule Car.Server do
	alias ElixirSocketTesting.ClientAgent
	def start(port \\ 50002) do
		ClientAgent.start_link()
		server = Socket.Web.listen!(port)
		loop(server)
	end
	def loop(server) do
		client = server
			|> Socket.Web.accept!()
		client
		|> Socket.Web.accept!()
		ClientAgent.add(client)
		Task.async(fn ->
			recv(client)
		end)
		loop(server)
	end
	def recv(client) do
		case client |> Socket.Web.recv!() do
			{:text, message} ->
				res = Car.agent(message)
				broadcast({:text, res})
				recv(client)
			{:close, _, _} ->
				ClientAgent.remove(client)
			other ->
				IO.inspect(other)
		end
	end
	def broadcast(packet) do
		ClientAgent.all()
		|> Enum.each(fn client ->
			Socket.Web.send(client, packet)
		end)
	end
end

Car.Server.start()





```

以上。
統計学実践ワークブック 22章 主成分分析

# 標本の分散共分散行列と相関行列
- 式(22.2)について
標本相関係数の定義についてはp15に記載のとおり
$Z^{\top}Z$のj,k成分は
${\frac{1}{\sqrt{s\_{j,j}s\_{k,k}}}}{\sum\_{i=1}^n}({x\_{i,j}}-{\bar{x}\_{・,j}})({x\_{j,k}}-{\bar{x}\_{・,k}}) = (n-1)r\_{j,k}$
よって$R=\frac{1}{n-1}Z^{\top}Z$

# 実対象行列の固有値問題
p165、実対象行列が対角化可能であることの証明
https://www.cck.dendai.ac.jp/math/support/ch6-supp/%E5%AF%BE%E7%A7%B0%E8%A1%8C%E5%88%97%E3%81%AE%E7%9B%B4%E4%BA%A4%E8%A1%8C%E5%88%97%E3%81%AB%E3%82%88%E3%82%8B%E5%AF%BE%E8%A7%92%E5%8C%96.pdf

トレースの式変形については、以下のURLを参考。

トレースの循環性
https://risalc.info/src/trace-matrix.html#def」

# 例22.1
(1) 主成分負荷量の式を使用する。
$\sqrt{\lambda_j}*u_{k,j}$（固有値のルート×固有ベクトルjのk番目成分）

主成分分析には分散共分散行列を用いる場合と相関行列を用いる場合で式が微妙に異なることに注意。
今回は相関行列を用いているため、標準偏差で割って標準化する必要がない。

(2)回答のとおり

(3)第一成分は変数に対して負の成分が大きいので、第1成分の主成分得点が強い、つまり左ほど走力に関する能力が高いといえる。
第二成分は正の成分が大きいので、上ほど投げる能力が高い。
よってAが双方の能力が一番強いと見なせるため、優勝はAだと考えられる
AZ-104試験対策のまとめ「Storage Account編③」

## はじめに
Microsoft Azure Administrator(AZ-104)合格に向けた勉強でまとめた内容を本記事では投稿しています。
試験範囲の内容を私が勉強していく中で、
・忘れてしまっていた内容
・他の知識と絡めて理解した方が良い内容
・Microsoft Learnの読解に苦戦した内容
などをできるだけ分かりやすく簡潔にまとめることを意識しています。
Azureの勉強を一から始め、AZ-104取得を目指している方の参考になれば幸いです。
※本記事の内容が必ず試験に出るわけではないこと、ご注意ください

## 試験対策のまとめ
### **データのライフサイクル管理**
ライフサイクル管理ルールを使用して、BLOBを自動的に移動/削除可能

#### 最終アクセス時刻に基づいてデータを移動
最終アクセス時刻追跡機能を有効にすると、下記に基づいた管理が可能となる
* BLOBが最後に変更された時刻
* BLOBが最後にアクセス(読み取り/書き込み)された時刻

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/storage/blobs/lifecycle-management-overview#move-data-based-on-last-accessed-time

### **BLOBの不変ストレージ**
不変ストレージを使用するとデータをWORM(Write Once,Read Many)の状態で保存可能  
WORM状態ではユーザーが指定した期間、データの変更/削除ができない

#### **不変ポリシー**
Blob Storageの不変ストレージでは下記の2種類の不変ポリシーをサポート  
BLOBバージョン/コンテナにスコープを設定可能  
* 時間ベースのアイテム保持ポリシー
    - 指定した間隔でデータを格納するポリシー
    - オブジェクトの作成/読み取りは可能、変更/削除は不可
    - 保持期間の期限切れ後：オブジェクトの削除は可能、上書きは不可
* 訴訟ホールドポリシー
    - 訴訟ホールドが明示的にクリアされるまで、不変データを格納
    - オブジェクトの作成/読み取りは可能、変更/削除は不可

<br>

* 参考
    - https://learn.microsoft.com/ja-jp/azure/storage/blobs/immutable-storage-overview

## 次の試験対策のまとめ
* **AZ-104試験対策のまとめ「Storage Account編④」**

https://qiita.com/fsd-jume/items/a4dceff33b69cd1b9e41

## 学習内容をまとめたページの一覧

https://qiita.com/fsd-jume/items/6eda24728c9c03c36bc3
【テスト手法】ブラックボックステストとホワイトボックステスト

## はじめに
皆さんは、ブラックボックテストとホワイトボックステストについて
知っていますか?

自分は前職に就いている間は、特に意識しておりませんでした。

レビューを頂いた際に、「自分が書いているのが、ブラックボックステストを書いているのかホワイトボックステストを書いているのかを考慮した方が良い」というアドバイスを受けて恥ずかしながら初めて知りました😢

今回は教えて頂いたことと、調べたことを自分の備忘録的意味もかねてまとめさせていただきます。

## ブラックボックステスト
初めて名前を聞いたとき、**テストのアンチパターンの一つか!?** と思いましたが、そういうことではありません。

テスト対象の「仕様」に基づいたテストケースの作成技法を **「ブラックボックステスト」** と呼びます。
簡単にいうと、利用者側の目線に立ったテストのことを指します。

テスト対象のことを「中の見えない箱」と例えて、**ブラックボックステスト** と命名されています。

利用者からしたら、システムの内部構造は分からないですよね? そういうことです！

メリットとして、内部構造が分からない第三者でもテストしやすいといった利点がありますが、
デメリットとして、仕様が間違っていたり、抜け漏れや矛盾が含まれると適切なテストが行えないといった点があります。



## ホワイトボックステスト
テスト対象の「内部構造」に着目してテストケースを作成する手法が **「ホワイトボックステスト」** と呼びます。
簡単にいうと、実装者側の目線に立ったテストのことを指します。

単体テストであれば、メソッドの実装、条件分岐等を意識してテストケースを作成していくイメージです。

テスト対象のことを「中身が分かる箱」と例えて、**ホワイトボックステスト** と命名されています。

そして、ホワイトボックスのテストケースはどれくらい処理経路を網羅しているかを評価することが重要になります。
処理経路の網羅度合いを**カバレッジ**といい、目標するカバレッジを満たすようなテストケースを設計していきます。

上記によって**潜在的な不具合**を見つけやすくなります。

## 最後に
いかがでしたでしょうか。

ブラックボックステストとホワイトボックステストどちらかが優れているわけではありません。

プロジェクトの性質や目的に応じて適切なテストアプローチを選択することが重要になります。
`(単体テストはホワイトボックステストで統合テストはブラックボックステストで対応するなど)`

今回の記事が多くの方に参考になったら幸いです。





## 参考文献
https://dev.classmethod.jp/articles/blackbox_testing_and_whitebox_testing/

https://gihyo.jp/dev/serial/01/tech_station/0003

https://gihyo.jp/dev/serial/01/tech_station/0004
unityでLive2Dモデルのパラメーターをスクリプトから制御したいのですが？

unityでLive2Dモデルのパラメーターをスクリプトから制御したいのですが,
古い記事ばかりだからかエラーが出てうまくいきません。
using Live2D.Cubism.Core;
とスクリプトに書くだけでエラーが出るので、今は書き方が違うのでしょうか？
やりたいことは例えば『照れる』というパラメーターを０から１にしたいだけなのですが、スクリプトの書き方が
調べても出てきません。
分かる方いらっしゃいましたらご教授くださると助かります。


出てくるエラーメッセージ
[Script Updater] Unable to check errors listed in `Temp/ApiUpdater_CheckMovedFroma36b950d7cdc40145a9b6936ac21e965`. File contents:
1732752974880

とりあえずLive2Dのオブジェクトを消すことで対応してみました！
私の今のプログラミング知識ではこれが限界です☆
今回のゲームはLive2Dキャラが感情レベルによって表情を変えるようなゲームですのでLive2Dモデルのパラメーターをスクリプトから操れれば一番いいのですが、今回はこれで行こうと思います。
頬の赤い部分を複数枚重ねて感情レベルによってそのオブジェクトをつけたり消したりすれば、脳筋ですがパラメーターを使わずに頬を少しづつ赤く出来そうです。

https://twitter.com/frilldoll/status/1709446798719471847

分かりやすい記事やスクリプトの書き方など分かる方がいましたらご教授よろしくお願いします。

2023/10/07

unityでLive2Dのパラメーターを操る方法がなんとなくわかりました！
絵描きからプログラミングを学び始めた私はまだプログラミングの知識は浅いのでわからないことが多々ありますが、書き方さえわかればなんとかなりそうっス🤣
プログラミングは謎解きみたく解けた瞬間超気持ちいのよね♪
これでさらに細かくLive2Dをあつかったゲームを作ることができますぞ🥰
https://twitter.com/frilldoll/status/1710613663755980958
Railsのレスポンスに関連するメソッドまとめてみた

# Railsのレスポンス `response` について

Railsにおける`response`オブジェクトの基本的な使い方や特性についてまとめています。

## 目次
- [レスポンスの内容を文字列で取得](#レスポンスの内容を文字列で取得)
- [レスポンスのcharsetを取得](#レスポンスのcharsetを取得)
- [レスポンスクッキーをハッシュに変換して取得](#レスポンスクッキーをハッシュに変換して取得)
- [HTTPステータスコードに対応するメッセージを取得](#HTTPステータスコードに対応するメッセージを取得)
- [コンテントタイプを設定](#コンテントタイプを設定)
- [パスに格納されているファイルをレスポンスボディとして返す](#パスに格納されているファイルをレスポンスボディとして返す)

## 逆引き


## レスポンスの内容を文字列で取得

#### 説明
レスポンスの内容を文字列で取得
#### 使い方
```ruby
response.body()
```

## レスポンスのcharsetを取得

#### 説明
レスポンスのcharsetを取得
#### 使い方
```ruby
response.charset()
```

## レスポンスクッキーをハッシュに変換して取得

#### 説明
レスポンスクッキーをハッシュに変換して取得
#### 使い方
```ruby
response.cookies()

# 例
assert_equal 'AuthorOfNewPage', r.cookies['author']
```


## HTTPステータスコードに対応するメッセージを取得

#### 説明
HTTPステータスコードに対応するメッセージを取得

#### 使い方
```ruby
response.message()

# 例
response.status = 200
response.message #=> "OK"
response.status = 404
response.message #=> "Not Found"
```

## コンテントタイプを設定

#### 説明
コンテントタイプを設定
HTTPレスポンスのコンテンツのMIMEタイプを設定

#### 使い方
```ruby
response.content_type = "コンテントタイプ"

# 例
response.content_type = "text/plain"
```

## パスに格納されているファイルをレスポンスボディとして返す

#### 説明
パスに格納されているファイルをレスポンスボディとして返す
#### 使い方
```ruby
response.send_file(パス)
```
10/4 投稿目標

# 概要
本記事は今後投稿しようとしている内容のメモです．

# 自己紹介
こんにちは，最近Qiitaでアカウントを作成した者です．とはいってもめっちゃくちゃ駆け出しの人間です．技術系の記事は全然書けないです．大学の頃は数学を学んでいました．学生の頃の内容の備忘録を作ろうと思ってます．
##### 記事の目的
直で記事投稿すればいいじゃん！とか言われればその通りなのですが完成度の高いものを作ろうとするとどうにも投稿までたどり着けそうになかったので一旦「こんなの書こうとおもてまっせ！」を書こうという次第です．


# 投稿予定のネタ
### 位相空間のコンパクト化について
Alexandorffの一点コンパクト化，及びStone-Cechコンパクト化の構成ついて解説している文献は多いですがそれらの応用について記述しているものは少ないように感じます，というか自分が知らないので調べようという話です．
またStone-Cechコンパクト化の連続関数による構成とフィルターによる構成の同一性など，よく知られている内容でも自分が押さえられていないないようもあるのでそれらを記事に出来ればと考えています．(イレギュラーかもしれないですが自分はフィルターによる構成が非常にわかりやすくなじんでしまったため，連続関数での構成を読んでないという人間です...:sweat_smile:)

### 強制法の議論
$\neg \sf CH+ZFC$の無矛盾性の証明(Cohen強制)では$\sf ZFC$の「十分大きな」finite fragmentに対するモデルをとる議論があるかと思われます．これは$\varepsilon$-$\delta$論法での「対象を$\varepsilon$の多項式で抑えられれば十分」とやってることは同じだと思うのですが，そのことについて記事に出来ればと思います．
ただこれだけだと中身が薄いので，Cohen強制に関して基本の部分から丁寧に解説する記事を書こうかなと思ってます．


### 連続体濃度の濃度比較について
$| 2^\mathbb{N}|=|\mathbb{R}|=|\mathbb{N}^\mathbb{N}|$は非常に基本的な結果ですが，学部レベルでの証明だとちょっと好みが分かれる説明のされ方がする場合があります．(具体的には$10$進表記の一意性の崩れをすこし無理やり解消する部分．)
他にも「気持ちのいい」全単射の構成はいくらでもあるのでそれらを紹介しようという感じです．こちらはそこまで難しくないので1日もあればかけると思います．

# おわりに
色々書きたいこと，数学で勉強したいことは山ほどあるんですが実際はいかんせん忙しくて記事を書く時間はとれなさそうです(オワタ)
取り敢えず基本情報取ろうと思ってます．あと毎日元気に出社．やることやる，以上！
chrome拡張機能作り方2

# 作る
まず適当にフォルダを作成します。
manifest.jsonを作成します
```manifest.json
{
    "name": "名前",
    "description": "説明を書く",
    "version": "書き換える（例えば1.0のように）",
    "manifest_version": 3,
     "action": {},
     "content_scripts": [
        {
          "js": ["s.js"],
          "matches": ["https://www.google.com/*"]
        }
    ]
}
```
そしてフォルダの中にs.jsを作成してメモ帳で開いて
そこの中には
```s.js
let body = document.querySelector('body')
let addElement = document.createElement('h1');
addElement.textContent = 'イエーイ';
body.prepend(addElement);
```
これらの仕組みは
google.comにアクセスすると
ページの一番上に
イエーイと表示されます。
特定商品と同じ日に併買される商品ランキング(SPSS Modeler データ加工逆引き11-14)

# 特定商品と同じ日に併買される商品ランキング

![スクリーンショット 2023-09-26 8.47.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/9830e1b0-f418-1686-b226-00dee13d9cc5.png)

＊同一期間中の併買は逆引き11-13を参照ください。

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

・顧客への施策立案時の商材選定
・予測モデルの特徴量作成


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

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

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

![スクリーンショット 2023-09-26 8.52.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/289c6605-e618-af24-3025-0a03b8a5672b.png)

a.入力するデータは以下の通りです。
![スクリーンショット 2023-09-20 9.28.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/98feab47-c25f-32fa-20bf-8d8697eaed16.png)

次のプロセスのためにAをハイライトしたままメニューから[条件抽出ノード（AND）]を選択します。結果としてbが自動生成されます。
![スクリーンショット 2023-09-20 9.49.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cc3bc57d-0064-d7c4-da56-33ca787b4052.png)

b.　[条件抽出]ノードを編集します。Aの購入レコードのみが抽出されます。
![スクリーンショット 2023-09-20 9.30.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/4a850fbd-47a7-df1f-3605-1b4836d85ff5.png)

c.[条件抽出]ノードを編集します。Aを購入したIDと日付の重複を排除します。
![スクリーンショット 2023-09-26 8.47.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/972a65d7-9393-3d2d-9c99-a7a8da392914.png)

[プレビュー]します。
![スクリーンショット 2023-09-26 8.48.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/a2b89927-e14d-fb97-1481-0e3271d6a832.png)

d.[レコード結合]ノードを編集します。内部結合させることでAの購入経験あるIDと日付の組み合わせのみに取引が絞りこまれます。
![スクリーンショット 2023-09-26 8.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/cc39564c-e852-da97-1add-5557c6e6398b.png)

e.bを複製して条件の反転[破棄]をすることで集計表にAが含まれないようにします。
![スクリーンショット 2023-09-20 9.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/da395953-f0b1-b752-f207-40b22fa349a9.png)

f.[レコード集計]ノードを編集します。
![スクリーンショット 2023-09-26 8.49.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/09579bed-3930-812b-85e1-c3c53904d349.png)

g.[ソート]ノードを編集します。
![スクリーンショット 2023-09-26 8.58.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/0445985b-0bd2-3a88-4df6-0c824b585f92.png)

[デーブル]ノードを実行します。
![スクリーンショット 2023-09-26 8.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/286322/7fcd49b7-c96d-d3b2-145b-c7bd2dcb33ac.png)

#### 注意事項

ランキングのための順位フィールドが必要な場合には関数@&#xFFF0;INDEXで作成します。

https://qiita.com/416nishimaki/items/8cd1fc55261fd36a9013

## 4.参考情報

####  AとBの両方または片方を購入した顧客を抽出する

https://qiita.com/416nishimaki/items/7be9d43d01b6f550ea38

####  Webグラフでカテゴリの上位アイテム間の同時購入を確認

https://qiita.com/416nishimaki/items/1546c5e26a22ee67f9c8

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

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

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

https://qiita.com/416nishimaki/private/4bf813e6cba84b2a1008
PyCharmを日本語化

# 環境
- Windows10
- PyCharm Community Edition 2023.2.1
# 手順
1. ```Ctrl``` ```Alt``` ```S``` を押し、Settings画面を開きます。
2. ```Plugins``` をクリックし、```japanese```　で検索して ```Install``` をクリックします。
 ![image3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610435/f477954a-618d-872a-eab6-a2c561d6fd24.png)
3. ```Restart``` をクリックしてPyCharmを再起動します。
 ![image4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/610435/19818e9b-c46e-a3f5-308c-0e209260fda4.png)
Airflowをインストールする時に発生したエラー [Could not build wheels for google-re2, which is required to install pyproject.toml-based projects] の解決方法

# エラー概要
MacでApache Airflowをインストールしようとした時にエラー
```zsh
$ pip install 'apache-airflow==2.7.1' \
 --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.7.1/constraints-3.8.txt"
```

エラー文は下記
```
Building wheels for collected packages: google-re2
  Building wheel for google-re2 (pyproject.toml) ... error
  error: subprocess-exited-with-error
  
  × Building wheel for google-re2 (pyproject.toml) did not run successfully.
  │ exit code: 1
  ╰─> [15 lines of output]
      running bdist_wheel
      running build
      running build_py
      creating build
      creating build/lib.macosx-10.15-x86_64-cpython-39
      copying re2.py -> build/lib.macosx-10.15-x86_64-cpython-39
      running build_ext
      building '_re2' extension
      creating build/temp.macosx-10.15-x86_64-cpython-39
      clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include -I/Users/hiro/.pyenv/versions/3.9.6/include/python3.9 -c _re2.cc -o build/temp.macosx-10.15-x86_64-cpython-39/_re2.o -fvisibility=hidden
      _re2.cc:11:10: fatal error: 'pybind11/pybind11.h' file not found
      #include <pybind11/pybind11.h>
               ^~~~~~~~~~~~~~~~~~~~~
      1 error generated.
      error: command '/usr/bin/clang' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for google-re2
Failed to build google-re2
ERROR: Could not build wheels for google-re2, which is required to install pyproject.toml-based projects
```

google-re2というパッケージ周りでエラー
下記を実行しても同様のエラーが出る
```zsh
$ pip install google-re2
 ```

# 解決方法
原因はPythonのバージョン

自分はバージョン3.9.6を使っていたが、google-re2のPython 3.9用のバイナリバージョンはないらしい

> So the problem is your Python thinks  that it is on 10.9 and indeed there is no binary version for Python 3.9 of google-re2

[Apache Airflow Community](https://apache-airflow.slack.com/archives/CCQ7EGB1P/p1689599877114329?thread_ts=1689595095.291319&cid=CCQ7EGB1P) より引用

現時点で最新のバージョン3.11.5をインストール
```zsh
$ pyenv install 3.11.5
$ pyenv global 3.11.5
```

その後Airflowをインストールすると成功した
```zsh
$ pip install 'apache-airflow==2.7.1' \                                                 
 --constraint "https://raw.githubusercontent.com/apache/airflow/constraints-2.7.1/constraints-3.8.txt"
```

# 参考
https://stackoverflow.com/questions/76701323/trying-to-download-apache-airflow-with-pip-but-error-pops-up-when-building-whee
PIXIV MEETUP2023に参加してきました！

# はじめに
こんにちは！ヨシカワです。この度、**PIXIV MEETUP2023**に参加してきたので参加レポートを書いていきたいと思います。

# PIXIV MEETUP2023とは
> PIXIV MEETUP 2023は、私たちピクシブメンバーが普段よりお世話になっている方、これからお話したい方をご招待し、このミッションを遂行するため普段行っている業務について、何をしているのか、何を考えているのか、自らの言葉で語り、その想いと技術を共有する場です。
PIXIV MEETUP2023公式サイトより

# 第1章　来たぜ！PIXIV MEETUP！
知人の招待を受けましてPIXIV MEETUP2023に参加することができました。お誘いいただき本当にありがとうございます。
受付とネームカードの記入をすませ、入り口すぐにある看板でパシャリ。(修正が汚くてすみません...)
![IMG_4434.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1877808/49b7a5f6-a616-f414-e1d7-1f9b11830db5.jpeg)

エスカレーターを降りるとフォトスポットと展示ブースがズラリと並んでいました。やはり最初に目についたのは**ChatRoid**ですかね〜。ChatRoidとは３Dキャラクターと会話ができるアプリケーションです。ユーザーの語りかけに返す言葉の生成にはPIXIV MEETUPの情報をインプットしたChatGPTが使われており、「PIXIV MEETUPって何？」という質問に丁寧に答えてくれました。

# 第2章　セッション・LTを聴こう！
聴いたセッション・LTの中で特に印象的だった物を書いていきます。

## MAIN SESSION 「pixiv Cloud Journey」
pixivのパブリッククラウド活動の取り組みについて紹介されていました。インフラについての予備知識が乏しく半分理解ができませんでしたが、登壇者さんがpixivのクラウド活動のほとんどを担っている事を知り驚きました。また、社内Slackで予算アラートという予算の超過をした際にアラートを流すSlack BotをGCPで実装した話も印象的でした。

![T5bcDUJ15evpnSM1696355067_1696355186.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1877808/0a5d75b0-59fd-e12f-3de8-96a25c87dcb0.jpeg)

## LT「Charcoalをモバイルアプリで使おう」
**Charcoal**とはpixivで使われているデザインシステムです。このLTではそのCharcoalを現場で使っているという話をされていました。聞くところによるとCharcoalはGithubで公開されているようです。私はモバイルアプリを開発する機会が多くあるのでぜひ一度使ってみたいですね。

[chacoalのGithub](https://github.com/pixiv/charcoal)

## LT「pixiv-iOSを破壊したい」
pixivは2009年からiOSアプリが提供されており、提供から14年がたちました。しかし、歴史あるアプリにも14年分の負の遺産が溜まっていたようです。このLTではpixivのiOSアプリを改修していくための施策と今後の展望について話されていました。具体的には古いライブラリが使われていたり、保守性の低い独自の設計が採用されていたようです。改修したいのですがそのコードが書かれている部分がアプリのコアの部分であるため、なかなか改修に漕ぎ出せないという問題点を抱えているようです。「なるほど〜」と思いながらLTを聴いていました。

また登壇者の方は落語経験があるらしく、羽織を着ており雰囲気から話の上手さを感じました。

# 第3章　After partyを楽しもう！
セッション・LTを聴き終わった後は**After party**！ここでは美味しいケータリングやドリンク、DJイベントが開催されました。![YvxWjeHVOx0H16W1696359618_1696359672.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1877808/3dc3c4a7-79b1-9468-c37d-48038edd7aeb.png)
サブステージではヨーヨー釣りやUFOキャッチャー、ゲーム大会が行われていたり...

![xdqZ6qWoaO71fpx1696359708_1696359841.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1877808/5a0952f9-6abd-fcdd-b73e-4a42bbb72017.png)
メインステージではDJイベントが行われていました。ちなみに↑の写真でDJをされているのは代表取締役の國枝信吾さんです。他にもpixivの社員さんがDJされていて、最後まで盛り上がってました！これぞpixivって感じ。

このAfter partyではpixivの社員さん以外の参加者さんとの交流が活発でした。ネームプレートを見せ合ってお話ししたり、ノートPCを開いてお話ししている様子も見れました。

# 最後に
ここまで読んでいただきありがとうございました！全体の感想としては**pixivのプロダクトや取り組みをたくさん知ることができて、かつたくさんのpixivの社員さんと交流ができて有意義な1日でした**。展示ブースを全部回りきれなかったの心残りだな〜...。

ですが、ご招待をいただけたらぜひまた参加してみたいです！その時は展示ブース全部回り切ってプロダクトについてたくさんお話を伺いたいです。

この度は参加者の皆さん、pixiv社員の皆さん本当にありがとうございました！👋
Oracleのロール権限について

### ロールとは

複数の権限をひとまとめにしたもの

### ロールの作成

CREATE ROLL ロール名;

### 権限の付与

GRANT 付与したい権限(INSERT,DELETEなど) ON テーブル名 TO ロール名;

### ユーザーにロールを付与

GRANT ロール名 TO ユーザー名;

業務で出てきたので少しずつ復習しております。。
ChatGPTのアプリで会話機能が使える様になったよ！

今日から？ChatGPTのアプリで会話機能が使える様になりました。
無料のアカウントを使っている方でもイメージができるように紹介してみたいと思います


## 使い方
まず、ChatGPT Plus（有料版）を契約します。
料金は月額20ドルで、いつでも解約できます。

その後、右上の3点リーダ[...]をクリックし設定をクリックします。すると以下の様な画面が出てくるため、Voice conversationsをONにします（最初のみ自分でこの画面から切り替える必要があります）
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/757ae770-f38f-d1c2-cfd7-23e1e18bfb94.png" width="300" alt="画像の説明2">


## チャットしてみる

その後チャットの画面に戻ると、右上にヘッドホンのマークが出てきますので、これをクリックします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/e5abdec5-d65c-dc7b-e1f4-109ad4ec82b8.png" width="200" alt="画像の説明">

すると、以下の様な画面に切り替わり、”Start speaking"と出てくるので何かを喋ってみます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/7ef4456b-79e0-453e-6ee1-fe4929e959bb.png" width="200" alt="画像の説明1">


試しに、Could you tell me about history of Nagoya?と聞いてみます。
質問を終えると、特にボタンを押さなくても勝手に音声が送信され、ChatGPTが会話を始めます。

以下が喋っている最中の画面です。4つのまるがピクピク動きながら返答を返してくれます。
特に驚いたのが喋り方の自然さです。これまでにないくらい自然な声で話してくれます。本当に機械が話しているのか人が話しているのかわからないくらいのレベルです。実際にここで聞かせることはできないですが、本当に驚くレベルです。さすがはOpenAI・・・
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/aed0e99e-555a-e28d-7cac-19627c20bbca.jpeg" width="200" alt="画像の説明1">

注意点としては、このやりとりはChatGPT4を使っているため、3時間に50回のメッセージ送信までという上限があります。あまりにも自然に答えを返してくれるのでいろいろと話かけていたら初めてこの上限に当たってしまいました・・・
音声入力の場合、やり取りが劇的に簡単になるため、またすぐに上限に達してしまいそうです。

### まとめ

今日は簡単にChatGPTの音声入力機能を見てきました。
元々GPT4が使えるだけのPlusユーザでしたが、Advanced Data Analysys,音声でのやり取り、Pluginとさまざまな機能がPlusでは利用できるため、＄20の価値が出てきたのではないかと個人的には考えています。

他にも今後、さまざまな機能が登場しそうでとても楽しみです。

ぜひGPT Plusを契約してChatGPTとの自然な会話を体験してみてください



### Tips

今日1日使ってみて、気がついたことを挙げておきます

#### 画面ロックしても会話が続けられる
今日は散歩をしながらAirPodsを通じてChatGPTと会話をしていましたが、その間、携帯の画面を全くみなくとも会話を続けることができていました。画面がスリープになっても以下の様な形で通話を続けることができます。これは本当に人と電話をしている様な感覚です。文字起こし機能はAirPodsから音声を拾ってくれないアプリなども時々ありますが、これはAirpods経由でも問題なく使うことができました。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/d5b1b1ae-d5f6-ce3b-18b8-0bc13e11fb16.png" width="200" alt="画像の説明1">


#### 画面タップしながら会話することで、会話が勝手に送信されるのを止められる

英語で話す場合、最初のセンテンスを話し終えてからの間が日本語以上に開いてしまいがちです。感覚値では2、3秒くらい会話が止まると勝手に会話が打ち切られ、ChatGPTの返答が始まってしまうという感じでした。簡単な質問などであればこの動きをしてくれた方が楽なのですが、例えば今日見た映画の内容を説明する場合などは説明の途中でどうしても間が開いてしまいます。一度メッセージが送られるとChatGPTが今度は話し始めてしまうため、自然な会話になかなかならないストレスがありました。そんな時は、会話を始める際に画面をおしながら話すことで、画面を押し続けている間は勝手にメッセージが送信されない様になります。こうしておけば、話しながら間が開いたとしても心配はいりません。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/d9253b0f-4918-5fa8-b170-e84651176190.png" width="200" alt="画像の説明1">

#### 話者を5人の中から選択可能

会話する時の話者は5人から選択が可能になっています。男性・女性・子供っぽい声などバラエティ豊かです。
個人的には一番Coveの声が自然で聞き取りやすかったです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77722/0b14286c-0efb-ffea-df63-4169458ccfba.png)
【Ruby】すでに投稿されているものを投稿できないようにする

# はじめに
大学生限定 プログラミングコミュニティ 『GeekSalon』で活動しているWebメンターの者です！
もし少しでも興味がありましたら、ぜひお話を聞きにきてください！

# 前提
この記事でできることを紹介します！
バリデーションを使い、すでに投稿されているデータは投稿できないようにする機能をつけます

**例）Vaundyについて投稿している人がすでにいる場合、Vaundyについては投稿できないようにする**

**前提：投稿機能の実装が完了していること**

**注意モデルはmusic,カラムはcontentになっているので、各々適切なものに修正してください**

# バリデーションの追加

**そもそもバリデーションとは？**
投稿フォームで何かを投稿するとき、「入力必須項目」というのを目にしたことはないでしょうか？

例えば「名前やメールアドレス、パスワード」などです。このとき、入力必須項目に何も入力しなかった場合、投稿ができないようにしたいですね。

他にもパスワードなどは4文字以上であるとか、すでにデータベースに存在しているメールアドレスで登録できないようにするとかデータを保存する前に検証したいときもあります。

そんなときに定義するのが**バリデーション**です。
バリデーションを定義すると、データベースに保存する際、投稿された内容を検証し、保存するかどうかをチェックできるようになります。

今回はcontentカラムを使用し、すでにデータベースに存在しているアーティストを投稿できないようにします。

```music.rb
class Music < ApplicationRecord
    #割愛
    validates :content, uniqueness: true #追加
    #割愛
end
```

上記のコードでは、validates :content, uniqueness: trueの部分でcontentに一意性制約を設定し、同じアーティストが複数回登録されないようにしています。

# 新規投稿ページに追加

```new.html.erb
 <%= render 'musics/error_messages', model: f.object %> #追加
```

フォームの下部にエラーメッセージを表示するためのものです。<%= render 'musics/error_messages', model: f.object %> の部分は、f.object が表すオブジェクト（@music などのモデルインスタンス）のエラーメッセージを表示するために使用されます。

具体的には、error_messages ビューパーシャルファイル内で、f.object に関連するエラーメッセージが存在する場合、それらのエラーメッセージをリストとして表示します。エラーメッセージは通常、バリデーションエラーが発生した場合に表示され、ユーザーにエラーの内容を伝えるのに役立ちます。

この行を追加することで、ユーザーがフォームを送信した際に入力エラーが発生した場合に、エラーメッセージがフォームの下部に表示されるようになります。


# エラーメッセージページを作成
```_error_messages.html.erb
<% if model.errors.any? %>
  <div class="alert alert-warning">
    <ul>
      <% model.errors.full_messages.each do |message| %>
       <h2>すでに存在するデータです</h2>
      <% end %>
    </ul>
  </div>
<% end %>
```
新規投稿ページで追加した1行は、エラーが出た場合こちらのビューファイルが表示されます。今回はすでに存在するデータがある場合「すでに存在するデータです」と表示させるようにします。

# コントローラーの変更
```musics_controller.rb
def create
  # データベース内に同じ content 値が存在するか確認
  if Music.exists?(content: music_params[:content])
    @music = Music.new
    @music.errors.add(:content, "アーティスト名はすでに存在します")
    render :new
  else
    @music = Music.new(music_params)
    if @music.save
      # ここにリダイレクトのコードを追加
    else
      render :new
    end
  end
end
```

このコードは、アーティスト名の重複をチェックし、データベース内に同じアーティスト名が存在しない場合に新しい音楽情報を保存します。もし保存に失敗した場合、render :new が実行されて、フォームが再表示されます。リダイレクトは各々のコードを追加してみてください。

完成図はこんな感じです！お疲れ様でした！

![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2613366/bd60a588-7082-6f56-fca2-680dfb40b1c3.gif)
ウェブストア公開済みの自作Chrome拡張機能のアップデート手順

# はじめに

1年少々前に公開したChrome拡張機能をアップデートしようとしたところ地味につまづいたので備忘としてまとめます。

Chrome拡張機能の基本的な開発方法と初回アップロード手順は以下を参考にしてください。

https://qiita.com/moromi25/items/dada185e5f1e07fc78fb

# アップデート手順

1. アップデートしたいChrome拡張機能のソース一式を圧縮
1. [Chrome Web Site Developer Dashboard](https://chrome.google.com/webstore/devconsole)にアクセス
1. アップデートしたいChrome拡張機能を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366737/a16340c0-e24c-f3a1-d6a0-fc6c269376e0.png)
1. サイドメニューの ビルド > `パッケージ` を選択
    ※画面遷移直後は`ストアの掲載情報`が選択されているので注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366737/79cf8892-c9d6-316a-eaa2-cae297fc54c3.png)
1. `新しいパッケージをアップロード` をクリックし、1で作ったzipファイルをアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366737/1d3834ed-98e8-8b0d-a1c6-6a86edc74183.png)
1. 必要に応じてサイドメニュー内の パッケージ 以外のメニュー情報を更新
1. 準備が整ったら `審議のために送信` をクリック
1. 以下のダイアログがでるので、自動公開の判断をした上で `審議のため送信` をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366737/1c4cc49b-9c81-f72e-e14e-7c613bee5bd6.png)

ちなみに、これは拡張機能の性質などにもよるとは思いますが・・・
最後のポップアップで「審査には数週間かかることがあります。」と脅されるものの、アップデートであれば数時間～遅くとも1日以内には公開されるなというのが個人の所感です。


# 【！注意！】Developer Dashboardを開いた初期画面右上の `+ 新しいアイテム` ボタン からは更新できない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2366737/7f468fb4-fbe6-17b7-16a0-378ef429054c.png)

`+ 新しいアイテム` は新たにChrome拡張機能を公開したいときに利用しましょう。
仮に上記ボタンを押すとChrome拡張機能の新規追加時に必要な記入事項や画像を求められるので、さすがにどこかで「おかしいな」と思うはずではあります。が、初めて／久しぶりの更新の場合は不審に思いつつ進めてしまう可能性もゼロではないので注意しましょう。[^私はやらかした]

[^私はやらかした]:ちなみに私は1年以上ぶりにアップデートしようとした結果やらかしました。審議が通って全く同じ拡張機能が一瞬世に出ました。。（速攻アーカイブしました）

# おわりに

久々のアップデート作業だったため少々つまづいてしまいましたが、無事にアップデートできました。
誰かのお役に立てれば幸いです（おそらく未来の自分が1番見る）。

# 参考サイト

https://zenn.dev/eetann/articles/2021-06-11-how-to-update-chrome-extension
知らない間にSQLインジェクションを発生させてた話

# 0.はじめに
今回は本当にあったヒヤリハットのようなことが起こったので備忘録としてここに綴っておこうかと思います。
## 自己紹介
```sh:crysta.sh
$ sudo docker exec -it crysta whois
 Name : Crysta1221
  X   : @cr1sta_dev
 AGE  : 17
 WORK : NNCT 3S
SKILL : Frontend Engineer(Vue.js), Backend Engineer(node.js,Express.js), Docker
```
# 1.気づいたきっかけ
現在、文化祭用のAPIの設計を頼まれていてGithub Copilot(以後Copilot)の手を借りながらGET、POST、DELETEの作成が終わり喜んでいたときでした...  
たまたまX(Twitter)で次のものが流れてきました。

https://t.co/Ebs34EtFjm

あれ...? わんちゃんやらかしてないか...? この時作成していたコードは次の画像の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2467860/a4d1252c-d795-0762-c075-0800e88ea4ed.png)
### ...
**誰が言うまでもなくSQLインジェクションの可能性があるコードでした!!!**
まぁ念のためCopilotではなくChat GPTに聞いたところちゃんと脆弱性がありました。

# 2.そもそもSQLインジェクションって？
https://www.shadan-kun.com/waf_websecurity/sql_injection/

こちらのサイトを見てもらったほうがわかりやすい気がしますが、URL等にSQL文を入れてリクエストされるとSQL文が実行されてすべてのデータが取得されてしまう...という脆弱性です。今回作成していたAPIはばりばりURLのクエリパラメータの値をそのままSQL文に流用していたために脆弱性が発生してもおかしくない状況でした。

# 3.対処
幸いにもAPIの公開前に気づいたので被害が発生することもありませんでした。(まぁゲームのスコアなどの情報しかないので知られてもあまり被害が起きませんが...)
後日次のコードにし、おそらく発生しにくくなったと思います。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2467860/2bb0e408-71d7-790d-5efa-dbcb464773d8.png)
今のコードも脆弱性となりうるかもなのでまたよくよくコードを見ておこうかと思います。(まだここヤバいんじゃない..?とかありましたら教えていただけたら幸いです。)
知らないうちに脆弱性作ってたようなものなので別の方でも気を付けるようにしたいと思います。
Slack ワークフローからGoogle Sheetsに行追加したらタイムスタンプが文字列になった

こんにちは。

Slackのワークフローとgoogleのスプレッドシート（お前Sheetsっていうんか)で課題管理システム作っていて、困ったことがあったので、その事象と回避策をメモがてら残す。

# やりたかったこと

- slackWFでフォームを記入
- 記入した内容をスプレッドシートに追加
- そのタイムスタンプを使って色々
    - botによる投稿への返信
    - シート上で課題の追加時間と終了時間から対応にかかった時間を出す。

etc….

# メッセージのタイムスタンプをシートに書き込もうとしたら文字列になった。

タイトル通り。

スプシのセルに日付を書き込み、セルをクリックすると画像のようにカレンダーが出てきて日付を選択できる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/a059b1a0-58e2-46f7-f4f2-81f0377bb1da.png)

これはスプレッドシートの中で日付型として扱われていると認識している。

ところがワークフローから追加をすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/b977e03d-7800-b6a0-e62a-bc185d182b85.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/f3a7f322-c162-b199-ebdf-d4d5d3f1daf6.png)

画像だとわからないが、文字列として扱われている。というかスプシはこの形式をサポートしてない。これだとgasで列の内容を取得したときに日付として扱ってくれない。（今思えばgasで日付に変換しても良かったな）

セルの表示形式を変更してもうんともすんとも言わないので困った。

# ワークフローから追記するときに 数式を指定した

date型の日付を表示する列とは別に、unixタイムスタンプを記入する用の列を作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/171b314a-22d0-00e3-bfde-4223a68ff6e8.png)

Slackのワークフローから列追加するステップの内容は以下の通りにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/c7f0a335-1a3e-d4d4-814a-7069a549832d.png)

追加する数式は以下。INDEXの引数は任意の列にしてください。

```
=DATE(1970,1,1) + INDEX(D:D, ROW())/86400
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3328170/f91237a3-1b27-754e-7039-69ce08b1b8e2.png)

見事日付に。

Slackのワークフローの入力欄って普通のテキストも入力できるんだね。今まで変数代入してたから気が付かなかった。

# 感想

まさかこんなところで躓くとは。といった感じ。（ほんと2日ぐらい試行錯誤してた）

WFとスプシの連携は非エンジニアにも優しいかと思いきや思わぬ落とし穴だなと思った。こ～～～れなんとかしてくれませんかねslackさん。
エクセルのすべてシートの位置をA1セルに移動する

```
' 引数の数を取得
argCount = WScript.Arguments.Count
' 引数が渡されていない場合、メッセージを表示して終了
If argCount = 0 Then
    WScript.Echo "ファイルパスが指定されていません。"
    WScript.Quit
End If

' エクセルアプリケーションを作成
Set objExcel = CreateObject("Excel.Application")

' エクセルファイルを開く（ここでファイルパスを指定）
Set objWorkbook = objExcel.Workbooks.Open(WScript.Arguments(i))

' すべてのシートを処理
For Each objWorksheet In objWorkbook.Worksheets
    ' シートの内容をA1セルに移動
    objWorksheet.UsedRange.Copy
    objWorksheet.Cells(1, 1).PasteSpecial xlPasteValues
Next

' エクセルファイルを保存
objWorkbook.Save

' エクセルファイルを閉じる
objWorkbook.Close

' エクセルアプリケーションを終了
objExcel.Quit

' オブジェクトを解放
Set objWorksheet = Nothing
Set objWorkbook = Nothing
Set objExcel = Nothing
```
必要なポート 8080 はすでに使用中です。解決方法

eclipse Tomcat再起動
---
必要なポート 8080 はすでに使用中です。サーバーはすでに別のプロセスで稼働中であるか、システム・プロセスがそのポートを使用中である可能性があります。このサーバーを起動するには、他のプロセスを停止するか、ポート番号を変更する必要があります。

上記のエラーメッセージが表示され実行されない。
文章の通り8080 はすでに使用中とのこと。
自社の研修時に何回もこのメッセージが表示されていたことを思い出す。
出るたびにポート番号変更してたっけ、、

ChatGPT様にご相談

## 1. ポートの使用状況確認:



```python
lsof -i :8080
```
このコマンドは、8080 ポートを使用しているプロセスの情報を表示します。もし何も表示されない場合、そのポートは使用されていない可能性があります。

## 2. プロセスの強制終了:
ポートが他のプロセスによって使用されている場合、そのプロセスを終了させることで解放できます。以下は、プロセスを終了させるコマンドの例です。
```python
kill -9 <PID>
```

PID はlsof コマンドで表示されたプロセスのIDです。

## 3.ポートの変更:
アプリケーションが使用するポートを変更することもできます。アプリケーションの設定やコマンドラインオプションを確認し、別のポートを指定してみてください。

ポート 8080 を使用するアプリケーションが複数ある場合、それぞれのアプリケーションで異なるポートを使用するように変更することが重要です。

これらの手順で、ポートが使用中の場合にそれを解放できるはずです。

## 1. ポートの使用状況確認: 2プロセスの強制終了: で解決
ChatGPT様！！
ありがとうございました！！
【Rails】ついついrubocopを通し忘れてしまう全ての方へ！commitと同時に自動でrubocopを通す設定方法！

# はじめに
お疲れさまです！
おおくまです！

以前、私は**rubocop**を現在実装中のアプリに導入しました！
（その際の記事はこちら[【Rails】rubocop導入手順の備忘録](https://qiita.com/kumaryoya/items/e2e12bb503fe56404329)）
しかし！
それからというもの、~~いつも~~たま〜にrubocopを通すのを忘れてしまいます！笑
そこで！
commitすると自動でrubocopを通してくれる便利な機能があることを知りました！
今回はその設定方法の備忘録になります！

# 環境
Ruby 3.2.2
Rails 7.0.8

# 注意点
:::note warn
私はプログラミング学習中で、初学者です。
内容に誤りがある場合があります。
コメント等で教えていただけると幸甚です。
:::

# 実装
今回使用するツールは、[lefthook](https://github.com/evilmartians/lefthook)というツールです！
これはGitフック管理ツールの1つで、特定のGitイベント（コミット前、プッシュ前、マージ前など）が発生したときに自動的に実行されるスクリプトやコマンドを管理してくれます！

```ruby:ターミナル
brew install lefthook
```
まずはlefthookをインストールします！

<br>

```ruby:ターミナル
lefthook install
```
次に設定したいアプリのディレクトリでこのコマンドを実行します！
このコマンドを実行すると、``lefthook.yml``ファイルが作成されます！

<br>

```yml:lefthook.yml
pre-commit:
  parallel: true
  commands:
    rubocop:
      run: bundle exec rubocop
```
今回は「commitと同時に自動でrubocopを通す」設定になるので、このように記述します！

<br>

```ruby:ターミナル
lefthook add pre-commit
```
記述できたら、このコマンドでファイル内容を反映させます！

<br>

設定は以上になります！
動作確認をしてみましょう！

```ruby:ターミナル
git commit -m "テスト"
╭──────────────────────────────────────╮
│ 🥊 lefthook v1.5.0  hook: pre-commit │
╰──────────────────────────────────────╯
┃  rubocop ❯

Inspecting 37 files
....C................................

Offenses:

app/controllers/application_controller.rb:1:1: C: [Correctable] Style/FrozenStringLiteralComment: Missing frozen string literal comment.
app/controllers/application_controller.rb:2:1: C: [Correctable] Layout/LeadingEmptyLines: Unnecessary blank line at the beginning of the source.
class ApplicationController < ActionController::Base
^^^^^

37 files inspected, 2 offenses detected, 2 offenses autocorrectable

  ────────────────────────────────────
summary: (done in 3.19 seconds)
🥊  rubocop
```
指摘があるとこのように表示されるみたいですね！
修正して、再度commitしてみます！

<br>

```ruby:ターミナル
git commit -m "テスト"
╭──────────────────────────────────────╮
│ 🥊 lefthook v1.5.0  hook: pre-commit │
╰──────────────────────────────────────╯
sync hooks: ✔️ (pre-commit)
┃  rubocop ❯

Inspecting 37 files
.....................................

37 files inspected, no offenses detected

  ────────────────────────────────────
summary: (done in 3.19 seconds)
✔️  rubocop
[develop 32d39ad] rubocop自動実行の設定
 1 file changed, 5 insertions(+)
 create mode 100644 lefthook.yml
```
今度は何も指摘されませんでした！

<br>

これからはrubocopを通すことを忘れずに済みそうです！
最後まで読んでいただきありがとうございました！
"Git SOS: 間違えて別のブランチにpushしてしまったときの対処法"

# 概要
皆さんはコミットしてpushした後に作業ブランチが間違っていることに気づいたことはないでしょうか？(僕はよくこのポカミスをよくします)
そんな時の対処法を備忘録として残しておきます。

:::note warn
私はプログラミング初学者のため間違った記述があれば教えていただけると幸いです。
:::
:::note alert
今回は個人開発ですが、--force オプションを使用してpushする場合は注意が必要です。他の人とブランチを共有している場合、この操作は他の人の作業を上書きする可能性があるので共同作業者と事前に相談してください。
:::
## 状況
個人開発の際、routes_setupブランチで作業していると思い、コミットし``push``し``Pull request``した際、ボタンが出てこず確認してみるとtop_pageブランチで作業してしまっていました。
## 対処法
###### ローカルで正しいブランチにコミットを移動する
まず、現在のブランチでの変更を確認しコミットハッシュをメモします。
```ruby:
git log
```
正しいブランチ（routes_setup）にチェックアウトします。
```ruby:
git checkout routes_setup
```
routes_setup ブランチにコミットを適用します。
```ruby:
git cherry-pick [コミットハッシュ]
```
###### 誤ったブランチのコミットを取り消す
誤ったブランチにチェックアウトします。
```ruby:
git checkout top_page
```
最後のコミットを取り消します。
```ruby:
git reset --hard HEAD~1
```
変更をリモートに反映する
```ruby:
git push origin top_page --force
```
正しいブランチの変更をリモートにpushします。
```ruby:
git checkout routes_setup
git push origin routes_setup
```
この手順で、誤ったブランチのコミットを正しいブランチに移動し、誤ったブランチのコミットを取り消し、リモートの状態を修正することができます。
WEBサイトのリンク切れは、一括でチェックしちゃおう！

長くWEBサイトを運用してページ数が増えたり、昔に作成したページなんかは気を付けないといつの間にかページ内のリンクが切れてたりなんてことがあります。

外部リンクを入れてたのに、リンク先のURLが変わってたりページが削除されたりもあるため、定期的に確認する必要があります。

ただ、ページ数が多いと１ページ１ページ見ているとものすごく大変なうえ、恐らく見落としが発生します。

そんな時はリンク切れをチェックする簡単なツールが存在するのでご紹介します。

私が最も利用しているものがリンクチェッカーです。
操作が凄く簡単なのでオススメです。

詳細な使い方はこちらの記事でご紹介しているので、ぜひご確認ください。


https://web-create-kokusyo.com/technique/link-broken/
【Xcode】XcodeにGithub Copilotを導入する方法と注意点まとめ

# はじめに

皆さんはGithub Copilotはご存知でしょうか？

Github Copilotはコーディング中にAIがコードの提案をしてくれる機能で、
プログラマーが記載したコメントや関数などから、AIが最適なコードを推測し提案してくれます。
プログラマーはその提案を採用し、作成中のプログラムに反映させることが可能です。

既に導入済みの企業などもたくさん出てきているようです。

https://qiita.com/naka_kyon/items/af160c357d5a3390771f
# 利用環境
現在は**JetBrains IDE**の開発環境や**VSCode**が公式でサポートされています。
ただ、**Xcode**は公式のサポートには含まれていませんが、[**CopilotForXcode**](https://github.com/intitni/CopilotForXcode)を利用することで、XcodeでもGithub Copilotが利用できるようになります。

https://docs.github.com/ja/copilot/getting-started-with-github-copilot#installing-the-vimneovim-extension-on-windows

今回はXcodeへの導入と、導入時の注意点についてまとめていきます。

# まずはGithub Copilotに登録

#### 前提
- Githubのアカウント作成済み
  - OrganizationでGithub Copilotを導入予定の方は管理者権限が付与されていること
- Xcodeをインストール済み
- お金に余裕がある

## サブスクリプションの登録

#### サブスクリプションの種類
Github Copilotには**個人用(Individuals)** と **組織用(Business)** があります。
主な違いは月額利用料と、ポリシー管理の有無、ライセンス付与の管理ができる点です。
個人用ではCopilotにコードをシェアすることは可能なオプションもありますが、
Businessライセンス(組織用)を使っていれば、誤ってCopilotにコードをシェアしてしまうということを防ぐことも可能です。

ちなみに個人用は30日間のトライアル期間が存在します(はるか昔は60日間もあったらしい)。
詳細な違いについては以下からご確認ください。

https://docs.github.com/ja/copilot/overview-of-github-copilot/about-github-copilot-for-individuals#copilot-for-individuals-%E3%81%A8-copilot-for-business

#### 登録方法

今回は **組織用(Business)** の登録で見ていきます。
Githubにログインしていただき、右のサイドバーからCopilotをクリックすると以下の画面へ遷移します。
![screencapture-github-github-copilot-signup-2023-10-03-23_03_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2604036/c0662a94-c9ba-46e5-38dd-9eea03cc0359.png)
画像の赤枠の部分から組織用の登録画面へ遷移していただき、住所やクレジットカードの登録を行いましょう。
組織用の場合は組織単位での支払いではなく、**組織で付与されている人数✖️19ドル/月**になるので注意しましょう。

#### サジェストされるコードの設定
支払い情報などの設定が終わると、サジェストされるコードの設定画面へ遷移されます。
これはサジェストされようとしているコードが、公開されているリポジトリに含まれるコードとほぼ一致するかどうかを検出し、検出された場合はサジェストしないようにできるもので、
Copilotがサジェストするコードにライセンスをクリアしていないコードが含まれるリスクを減らすためのオプションになります。
ここは`Blocked`にしておくのが安全かと思われます。
![スクリーンショット 2023-09-28 18.29.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2604036/b7f9a1ca-fc90-f230-44ed-899826af0551.png)

こちらについては以下の記事が参考になりました。

https://dev.classmethod.jp/articles/intro-github-copilot-for-business/#toc-5

#### シートの割り当て管理
サジェストの設定が完了すると、Copilotを誰に導入するかを設定する画面へ遷移します。
![スクリーンショット 2023-09-28 18.31.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2604036/cbbdd0eb-8d49-1f8a-bbaa-ba52e4536e82.png)
私の会社では一部のメンバーのみに付与したかったので、**Purchase for selected teams/users**を選択し、**Add seats**でチーム単位での付与、組織のメンバー個人への付与をこの画面で設定しました。
ここで追加されたメンバーの数だけ毎月請求が発生することになります💸
もちろん設定後に追加/削除も可能です。


これで設定は完了で、付与されたメンバーにはメールが届きます。

# Xcodeへの導入方法

以下の記事を参考に導入することができました。

https://softantenna.com/blog/copilot-for-xcode/

https://ez-net.jp/article/5A/P2QqErlN/F4GPX3HvavcA/

https://qiita.com/SNQ-2001/items/ca0ebe026bc0e88499ce

# 最後に

Github Copilotは社内での評価も高く、自分が書こうと思っていたコードをサジェストしてくれるおかげで、かなり楽にコーディングすることが可能になり、特に自分が知らなかった記法を提案してくれるのが非常に良いと感じました。
ただ意図しないコードがサジェストされることもたくさんありますし、サジェストされるコードを理解しないまま使ってしまうのは良くないので、あくまで**副操縦士**として今後は付き合っていくのが良さそうです。
terraform-provider-google v5.0.0 から default label が設定出来るようになった


## はじめに

terraform-provider-google v5.0.0 から default label が設定出来るようになりました。
terraform-provider-aws で言う default tag です。

## default label が設定出来るようになった

terraform-provider-google v5.0.0 から default label が設定出来るようになりました。
これで、 resource 1つ 1つ に label を付与する単純作業から開放されます。

はじめに記載した通り、定義方法は `terraform-provider-aws` 変わりません。
`default_tags` と `default_labels` の違いくらいです。

```hcl
provider "google" {
  default_labels = {
    foo = "bar"
  }
}
```

もちろん下記のように、 `default_labels` は上書きすることも出来ます。

```hcl
resource "google_storage_bucket" "example" {
  name          = "example-bucket"
  location      = "US"
  force_destroy = true

  labels = {
    foo = "baz"  # -> label foo の値は bar ではなく baz になります
  }
}
```

## 最後に

文中にも記載しましたが、 resource の 1 つ 1 つに labels を付与する作業から開放されるので飛んで喜びました。

## References

https://github.com/hashicorp/terraform-provider-google

https://github.com/hashicorp/terraform-provider-google/releases/tag/v5.0.0

https://github.com/hashicorp/terraform-provider-google/pull/15740

https://registry.terraform.io/providers/hashicorp/google/latest/docs/guides/version_5_upgrade#provider-level-labels-rework
【Rails】libffi.so.7: cannot open shared object file: 解消法

## 状況
Rails7de`image-processing`を使用して画像処理をしようとしたところ表題のエラーが発生しました。

## 解消法

以下のコマンドを実行することで解消しました。

```terminal
bundle pristine ffi
```

## 参考

https://github.com/ffi/ffi/issues/881
はじめてのChatGPT API

# はじめに
ChatGPTを使ったクイズアプリを作るにあたって、
ChatGPT APIについて得た情報や知識を備忘録として残しておきます。

また、開発中のあれこれについては以下のサイトでまとめています。
https://zenn.dev/kitaji12/scraps/a115ff66546e65

# 事前情報
- OpenAI / ChatGPT 初心者
- クイズアプリは React + Flask で作成

# 準備
- [OpenAIのサイト](https://openai.com/product)からアカウントを作成する
- 作成したアカウントでログインしておく

# ChatGPT APIとは？
OpenAIによる自然言語処理のためのAIモデル「ChatGPT」を使用して、開発者が自然言語処理を行う際に使われるAPIのこと。
API = 「​​Application Programming Interface」の略称のことで、ソフトウェアやWebサービスの間をつなぐインターフェースを指します。

# ChatGPT APIの料金
OpenAIの[Usageページ](https://platform.openai.com/account/usage)を開くと、フリートライアルの確認ができます。  

最初に付与されるクレジットが5.00ドルとなります（2023/09現在）
- `CREDIT GRANTED`：クレジット付与
- `EXPIRES`：有効期限
↓ クレジット5.00ドル中、0.02ドル使用していることがわかります
![ChatGPT APIの料金.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/832a391b-9716-297a-6318-ab44f9669da0.png)
約2ヶ月で数回触る程度であれば、0.02ドルでした。（意外とかかってなかった）

※有効期限が切れると「Expired 2023年11月1日」のように表示され、上記画像のグレー部分のゲージが赤くなるそうです

# ChatGPT APIのAPIキー
OpenAIの[API keysページ](https://platform.openai.com/account/api-keys)を開き、
「+ Create new seacret key」を押下で新しいAPIキーを作成することができます。
（作成したAPIキーは一度しか表示されないため、メモに書いておくことをおすすめします）
![ChatGPT APIのAPIキー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076680/f4c71a70-e292-3350-117a-4e6d77cd9556.png)
APIキーを使用する上での注意事項は以下の通りです。
> API キーを他の人と共有したり、ブラウザまたは他のクライアント側コードで公開したりしないでください。アカウントのセキュリティを保護するために、OpenAI は、公的に漏洩したことが判明した API キーを自動的に無効にする場合もあります。

APIキーの共有・公開は、OpenAI側から無効化にされる場合がありますよ。ということだそうです。

# ChatGPT APIのモデル
OpenAIのAPIでは、色々な機能と価格帯を備えたさまざまなモデルがあります。
アプリケーションに合わせてモデルをカスタマイズすることも可能だそうです。

- `GPT-4`：GPT-3.5 を改良し、自然言語やコードを理解し、生成できるモデルのセット
- `GPT-3.5`：GPT-3 を改良し、自然言語やコードを理解し、生成できる一連のモデル
- `GPT-3(Legacy)`：自然言語を理解して生成できる一連のモデル

この中から「GPT-3.5」についてもう少し詳細に見ていきます。

**■ gpt-3.5-turbo**
いくつかある GPT-3.5 の中で最も機能的でコスト効率の高いモデルで、チャット用に最適化されているもの。

**■ GPT-3.5 と GPT-4 との違いは？**
> GPT-4は、より広範な一般知識と高度な推論のおかげで、以前のモデルよりも高い精度で困難な問題を解決できる大規模なマルチモーダル モデル (現在はテキスト入力を受け入れ、テキスト出力を出力しますが、将来的には画像入力も可能になる)能力をもっている。

基本的なタスクをこなす上では、GPT-3.5 と GPT-4 の違いはそこまでありませんが、
より複雑な推論の状況では、GPT-4 は以前のモデルよりもはるかに優れた能力を発揮するそうです。

最大トークン数は、GPT-4のモデルが約2倍のトークン数になります。
- `gpt-3.5-turbo`：4,097 トークン
- `gpt-4`：8,192トークン

# さいごに
ChatGPT APIをはじめて触る上で調べたことについてまとめました。
次は実際にAPIを叩いて結果が返ってくるところまでを記事にしたいと思います！


# 参考サイト
- [OpenAI](https://openai.com/product)
- [OpenAI - ドキュメント](https://platform.openai.com/docs/introduction/introduction)
- [ChatGPT APIとは？始め方や使用時の注意点、活用事例を紹介](https://aismiley.co.jp/ai_news/what-is-the-chatgpt-api/)
SwiftUIでGPSロケーションを指定した場所にする方法


# SwiftUIでXCodeを使ってGPSロケーションの偽装方法を説明していこうと思います。iOS17でも動作確認済み
自分はProject名をGPSSpooferとしたのと、開発者であればコードを見ればわかると思うので、実行時のコードを載せてご自分なりに変更して頂ければと思っております。本当に基本中の基本なことだけだと思います。

### 1.XCodeで新規プロジェクトを作成
今回私はSwiftUIで実装しました。実装理由はStoryBoard使った解説している方は何人かいらっしゃるので、まだだれもしてない内容で書こうと思った次第です。でも特殊な事はしてないので、コピーして活用してくれると嬉しいな。

### 2.iOSの位置情報はアプリ内で共通で、Simulate Locationはアプリがサスペンドされると機能しなくなるので、AppDelegateで処理する内容を追記してあげます。SwiftUIだとAppDelegateっていうファイル名がないので、先ほど作成したGPSSpoofer.swiftに以下の様に追記してあげます。

<details><summary>GPSSpoofer.swift</summary>

~~~ GPSSpoofer.swift
import SwiftUI

@main
struct GPSSpooferApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}

class AppDelegate: NSObject, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
        debugPrint("application:didFinishLaunchingWithOptions:")
        
        application.registerForRemoteNotifications()
        
        return true
        
    }
    
    var backgroundTaskID : UIBackgroundTaskIdentifier = UIBackgroundTaskIdentifier.invalid

    private func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
        return true
    }
    
    func applicationWillResignActive(_ application: UIApplication) {
        self.backgroundTaskID = application.beginBackgroundTask(){
            [weak self] in
            application.endBackgroundTask((self?.backgroundTaskID)!)
            self?.backgroundTaskID = UIBackgroundTaskIdentifier.invalid
        }
    }
    
    func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        
        debugPrint(deviceToken.base64EncodedString())
        
    }
}

~~~
</details>

今回はロケーションの偽装なので、アプリ自体は特に何もしません。後述するGPXファイルの座標をここで表示してあげてもいいかもしれないですね。

<details><summary>ConentView.swift</summary>

~~~ConentView.swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

#Preview {
    ContentView()
}
~~~

</details>

### 3.上記の準備が終われば実機で位置が変わるか確認することができます。
アプリを実行中に`Debug` > `Simulate Location`で移動先の都市を選択することができます。
`Add GPS Exchange to Project`を選択し、自分専用の位置情報を用意します。

:::note info
以下のサイトでXCodeで使えるGPXファイルが作成できます。
https://www.gpxgenerator.com/
:::

上記サイトで地図上からルートを作成し、Showで該当ルートを動くGPXファイルの内容が表示されます。まだGPXファイルを作成していなければ、ダウンロードを選択し、プロジェクトに追加してください。既存のファイルがあればそのファイルをプロジェクトに追加すれば準備は完了です。

後は自分が歩きたい場所のGPXファイルを用意するだけで、自動で歩いてくれますし、素材集めなどに便利かなと思います。