OmniAICreator/Qiita-1.07M huggingface dataset:
BigQueryサブスクリプションを接続したテーブルのデータ型変更が本当に面倒くさかった

# はじめに

こんにちは、京セラコミュニケーションシステム　川村（@kccs_takahiro-kawamura）です。
みなさんはBigQueryサブスクリプションを利用していますか？
私はIoTデータを収集するプラットフォームを構築しているのですが、BigQueryにデータを保存するパイプラインとしてBigQueryサブスクリプションを採用することが多いです。
今回は、私がBigQueryサブスクリプションとBigQueryを運用している経験から本当に面倒に思ったBigQueryのデータ型の変更について、その手順と注意点を記載いたします。

:::note info
本記事は2024年9月ごろに作成しております。よって、引用している文章などはこの時点での最新となります。ご了承ください。
:::

## 本記事の対象者
* BigQueryを利用している方
* BigQueryサブスクリプションを利用している方、利用を検討している方

# BigQueryサブスクリプションとは
[BigQueryサブスクリプション](https://cloud.google.com/pubsub/docs/bigquery?hl=ja)とは、Pub/Subのサブスクリプションの一種でPub/Subで受信したメッセージをBigQueryに書き込むことができます。
ストリーミングでデータをBigQueryに書き込めるためIoTデータと相性がよく、書き込み前に加工処理が不要な場合はDataflowジョブよりもBigQueryサブスクリプションを採用するほうがオススメです。

# BigQueryサブスクリプションを接続しているテーブルのデータ型変更
[BigQueryのみのデータ型変更の記事](https://qiita.com/kccs_takahiro-kawamura/items/99491cb255aa12415675#%E4%BA%92%E6%8F%9B%E6%80%A7%E3%81%AE%E3%81%82%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%9E%8B%E5%A4%89%E6%9B%B4)と同様にデータ型の互換性の有無によって手順が異なります。

## 互換性のあるデータ型変更
BigQueryのデータ型変更はALTER文を実行するだけでできます。
しかしながら、BigQueryの変更を行いたいだけなのに、BigQueryサブスクリプションの変更も必要です。
BigQueryでは互換性のあるデータ型の変更でも、BigQueryサブスクリプションを利用する際に必要となるトピックスキーマでは互換性がありません。
手順にすると以下のとおりです。

1. 対象のPub/Subにパブリッシュしているサービスを停止する
2. BigQueryサブスクリプションの接続を解除する
3. 対象のトピックスキーマを削除する
※ トピックスキーマはAvroスキーマを想定

4. 新しい定義で同名のトピックスキーマを作成する
5. [ALTER文](https://qiita.com/kccs_takahiro-kawamura/items/99491cb255aa12415675#%E4%BA%92%E6%8F%9B%E6%80%A7%E3%81%AE%E3%81%82%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%9E%8B%E5%A4%89%E6%9B%B4)を実行し、対象のBigQueryテーブルのデータ型を変更する
6. BigQueryサブスクリプションの編集ボタンを押下し、何も変更せずに更新ボタンを押下することで再接続する
※ 稀に更新ボタンを押下後に処理中のステータスから進まない場合があるため、その際はBigQueryサブスクリプションを削除して再作成する
7. 停止したサービスを再開する



## 互換性のないデータ型変更
互換性がない場合は、上記の手順に加えてBigQueryのテーブルを再作成する必要があります。
手順にすると以下のとおりです。

1. 対象のPub/Subにパブリッシュしているサービスを停止する
2. BigQueryサブスクリプションの接続を解除する
3. 対象のトピックスキーマを削除する
4. 新しい定義で同名のトピックスキーマを作成する
5. テーブルのコピーを作成する
6. オリジナルのテーブルを削除する
7. データ型を変更してテーブルを再作成する
8. クエリ設定を行う
![query_setting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164163/36afa581-552c-8450-22f3-91ea1c306aa6.png)

9. クエリを実行する
    ```SQL
    SELECT column1, CAST(column2 AS STRING) as column2, column3 FROM example_table_copy [WHERE パーティションの条件]
    ```
10.  BigQueryサブスクリプションの編集ボタンを押下し、何も変更せずに更新ボタンを押下することで再接続する
11.  停止したサービスを再開する

BigQueryのテーブルのデータ型を変更したいだけなのに、複雑な手順になってしまいました。

# まとめ
* 互換性があるデータ型変更は、BigQueryサブスクリプションの変更をしてからALTER文を実行する
* 互換性がないデータ型変更は、BigQueryサブスクリプションの変更してからテーブルを再作成する

どちらの場合もひと手間かかりますが、BigQueryサブスクリプションを用いてパイプラインを構築することで、構築にかかる時間やこれ以外の運用が削減できます。

次回の記事もお楽しみに！

## おしらせ

弊社X（旧：Twitter）では、Qiita投稿に関する情報や各種セミナー情報をお届けしております。情報収集や学びの場を求める皆さん！ぜひフォローしていただき、最新情報を手に入れてください😄

https://x.com/kccs_digital
プロトコル

簡単な振り返り用メモ

- http
    - portは80番
- https
    - 厳密にはプロトコルではない
    - 内容はほとんどhttpと同じ
    - http + SSL/TLS(プロトコル)
    - TLSによって暗号化されている
    - portは443番
- ftp
    - ファイル転送の際に利用
    - portは20, 21番
- ftps
    - 内容はほとんどftpsと同じ
    - 違う部分はSSL/TLSによって暗号化されていること
    - portは989, 990番
- scp
    - SSH（Secure Shell）によって安全にファイル転送を行うプロトコル
    - portは22番
- sftp
    - SCP同様に、高いセキュリティでファイル転送ができるプロトコルです
    - SFTPもSSHを用いており、ユーザ名やパスワードなどの認証情報を暗号化してファイル転送できます
    - SCPは転送の再開ができませんが、SFTPは転送を中断しても途中から再開できます
    - 一般にSCPの方がSFTPよりも高速とされています
    - portは22番
『いちばんやさしいPython入門教室』を用いた学習の開始

# はじめに
　[以前の記事](https://qiita.com/D_Sato_01/items/35044d6be21990db766c)で使用していた書籍『プログラミングの基礎』（サイエンス社出版）の内容が自分のレベルに合っていないことが分かったため、別の書籍に移り換えることとした。

# 使用書籍
　今回からは書籍『いちばんやさしいPython入門教室』（ソーテック社出版）を用いてプログラミングの基礎学習を進めることとする。
 
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3896883/8a61f73f-f983-fa34-7812-3d9723465b2d.png)

　プログラミングの基礎学習用の教材として本書を選定した理由は、単純に私がPythonに興味を持っていたからである。

　本書ではPython 3が用いられている。Python 3系はPython 2系と比較すると文法などがやや異なる。例としてprint構文を挙げると ( ) の有無という点で異なっている。
```python:Python 2系
>>> print "Hello World"
Hello World
```
```python:Python 3系
>>> print ("Hello World")
Hello World
```
<br>

次の記事から学習内容を記してゆく。
<br>

[次項：Pythonを用いたプログラミング学習①｜演算子](https://qiita.com/D_Sato_01/items/26a9ab000cb1b7f2a540)
【Oracle DB】NATURAL JOINの使いどころ

# はじめに
SQLのテーブル結合方法にはNATURAL JOIN（自然結合）がありますが、この結合方法を実践で使う機会は少ないと思います。
システム内で実行するSQLを書く場合は、後日テーブルへカラムが追加される可能性も加味した上で、拡張にはオープンであるべき原則[^1]に従うとNATURAL JOINを使うべきではありません。

ですが、Oracle DBの場合はデータ・ディクショナリ[^2]を検索するときにNATURAL JOINを活用できますので、事例をサンプルクエリとともにメモします。

# 環境
Oracle Database 19c
# 事例1 : テーブルの物理名と論理名を検索
## クエリ例
```sql
SELECT
    table_name
   ,comments
   ,num_rows
   ,last_analyzed
FROM
    user_tables
NATURAL JOIN
    user_tab_comments
ORDER BY
    table_name
;
```
## 検索結果例
| TABLE_NAME | COMMENTS | NUM_ROWS | LAST_ANALYZED |
|:--|:--|--:|:--|
| TABLE_A | テーブルA | 100 | 2024-10-02 00:00:00 |
|TABLE_B|テーブルB|2,000|2024-10-01 00:00:00|
|TABLE_C|テーブルC|40,000|2024-04-01 00:00:00|

:::note 
データディクショナリ「user_tab_comments」はCOMMENT ON TABLEを実行していないテーブルの情報も持っているので、外部結合する必要はありません。
:::
# 事例2 : テーブルのカラム定義と論理名を検索
## クエリ例
```sql
SELECT
    table_name
   ,column_name
   ,comments
   ,data_type
   ,data_length
   ,data_precision
   ,data_scale
   ,nullable
   ,char_used
FROM
    user_tab_columns
NATURAL JOIN
    user_col_comments
WHERE 1=1
AND table_name = :table_name
ORDER BY
    column_id
;
```
## 検索結果例
| TABLE_NAME | COLUMN_NAME | COMMENTS | DATA_TYPE | DATA_LENGTH | DATA_PRECISION | DATA_SCALE | NULLABLE | CHAR_USED |
|:--|:--|:--|:--|--:|--:|--:|:--|:--|
|TABLE_A|ID|識別子|NUMBER|22|10|0|N||
|TABLE_A|TXT_COL_A|文字カラムA|VARCHAR2|400|||Y|B|
|TABLE_A|TXT_COL_B|文字カラムB|VARCHAR2|400|||Y|C|
|TABLE_A|TXT_COL_C|文字カラムC|CHAR|1|||N|C|
|TABLE_A|NUM_COL_D|数値カラムD|NUMBER|22|6|3|N||
|TABLE_A|NUM_COL_E|数値カラムE|NUMBER|22|||Y||
|TABLE_A|DATE_COL_F|日付カラムF|DATE|7|||N||

::: note
データディクショナリ「user_col_comments」はCOMMENT ON COLUMNを実行していないカラムの情報も持っているので、外部結合する必要はありません。
:::
# 事例3 : INDEXが貼られている項目の検索
## クエリ例
```sql
SELECT
    table_name
   ,index_name
   ,index_type
   ,uniqueness
   ,constraint_index
   ,column_name
FROM
    user_indexes
NATURAL JOIN
    user_ind_columns
WHERE 1=1
AND table_name = :table_name
ORDER BY
    index_name
   ,column_position
;
```
## 検索結果例
| TABLE_NAME | INDEX_NAME | INDEX_TYPE | UNIQUENESS | CONSTRAINT_INDEX | COLUMN_NAME |
|:--|:--|:--|:--|:--|:--|
|TABLE_A|IND_A_01|NORMAL|NONUNIQUE|NO|TXT_COL_A|
|TABLE_A|IND_A_02|BITMAP|NONUNIQUE|NO|TXT_COL_C|
|TABLE_A|IND_A_03|NORMAL|NONUNIQUE|NO|DATE_COL_F|
|TABLE_A|IND_A_03|NORMAL|NONUNIQUE|NO|NUM_COL_D|
|TABLE_A|PK_A|NORMAL|UNIQUE|YES|ID|

# 補足
本例ではUSERビューに対するクエリを記載しましたが、ALLビューやDBAビューでも同様にNATURAL JOINが使えます。

# 参考

https://qiita.com/YouKnow/items/a4201369bd824fe9c5c0

[^1]:SOLID原則の内、"O"にあたる「オープン・クローズドの原則」。
[^2]:Oracle DB内にあるオブジェクトのメタデータを参照できるビューのこと。厳密には「静的データ・ディクショナリ・ビュー」
rspecでtravel_toの影響を受けずにクラスの定数の値を設定する方法

# 環境

- rails6.0系
- rspec3系

# 初めに

※サンプルコードになります

travel_toメソッドで時刻を変更した中で実施したテストがありました。
その中で、定数の内部で現在時刻から30日前を取得する処理があったのですが、travel_toの影響を受けず、テスト実行時の時刻を元に取得している問題が発生しました。
```rb
before { travel_to('2023-06-20 18:00:00') }
```

```rb
class User
  TEST_DATE = Time.current.ago(30.days).strftime('%Y-%m-%d') # テストの中で呼ぶとtravel_toの影響を受けず実行時の現在時刻から算出された
end
```

# 解決策

テスト実行前に、呼び出している定数を`stub_const`で書き換えてあげると上手くいきます
```rb
stub_const('User::TEST_DATE', Time.current.ago(30.days).strftime('%Y-%m-%d'))
expect xx # 実行する際は上記のスタブの値が参照されるようになる
```

# 参考文献

https://imaharu-blog.hatenadiary.jp/entry/2019/06/20/224851
時間を巻き戻す await の魔法

[Promise と async function の 同期実行される範囲について #JavaScript - Qiita](https://qiita.com/juner/items/f433aed166b25a4069c2)
↑この @juner さんの記事にインスパイアされました。

### 問題

このコードを実行すると、コンソールにどのように出力されるでしょうか。

```js
let x = 0;
(async () => {
    console.log(x)
    console.log(await (x++))
    console.log(x)
})()
console.log(x)
```

### 回答

<details><summary>回答折りたたみ</summary>

```
0
1
0
1
```

インクリメントした`x`の値が巻き戻ってる？！

### たねあかし

処理順がこうなっているのが原因です。

```js
let x = 0;
(async () => {
    console.log(x)       // --- 1
    console.log(await (
        x++              // --- 2
    ))                   // --- 4
    console.log(x)       // --- 5
})()
console.log(x)           // --- 3
```

4の`console.log`が受け取る値は後置なのでインクリメント前、でも3の`console.log`はインクリメントされた値を参照する、ということでした。

</details>
「久須尼自利」は「굿 내 실」なのか

Lee SeungJae (李丞宰)『[Old Korean Writing on Wooden Tablets and its Implications for Old Japanese Writing](https://doi.org/10.1353/seo.2015.0005)』(Seoul Journal of Korean Studies, Vol.27, No.2 (December 2014), pp.151-185)を横目に、『日本書紀』卷十九に出てくる「久須尼自利」を新羅語だとみなして、Universal Dependenciesで書くというムチャに挑戦してみた。

```
# text = 久須尼自利
1	久須	굿	NOUN	_	_	3	vocative	_	Lang=oko|SpaceAfter=No
2	尼	내	PRON	_	_	3	det	_	Lang=oko|SpaceAfter=No
3	自利	실	NOUN	_	_	0	root	_	Lang=oko|SpaceAfter=No
```

![oko.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/428317/99afa976-0239-ab12-abc0-8a4ed9ad6bc0.png)

「自利」は、末音添記「糸利」すなわち「실」を、いわゆる万葉仮名で記述したものだと考えられる。とすれば「久須」は「굿」とみなして大丈夫そうだ。悩ましいのは「尼」で、頭音が「ㄴ」の開音節に見えるが、それでも「니」「내」など色々ありうる。とりあえず、現代韓国語の一人称属格「내」を当ててみたが、これが新羅語において「내」だった保証はない。

この「尼」に対し、河野六郎『百済語の二重言語性』(朝鮮の古文化論讃, 1987年4月, pp.81-94)は

> 尼自利の尼は니と読み、「行く」の義ではないかと思われる。中期語に니「行く」という動詞があった。

としており、動詞「니」とみなしている。ただ、ここに動詞が入ってしまうと、つづく「自利」の解釈が、私(安岡孝一)には超難題になってしまう。うーん、難しいなあ。
【令和最新版】MbedStudio on Ubuntu24.04LTS

# はじめに
こんにちは。kazuです。
今回はMbedStudioをUbuntu24.04LTSに入れたのですが、すこし沼ったので書き残しておきます。

# ダウンロード&インストール
1. [公式ページ](https://os.mbed.com/studio/)からLinuxを選択し、shをダウンロードします
2. `sudo chmod +x MbedStudio-....sh`で実行権限を付与します
3. `./MbedStudio-....sh`でそれを実行してみましょう
4. なにか聞かれたらyesやy、エンターしましょう
5. インストールが終わったらudevの追加を求められるので、sudoのパスワードを入れましょう
6. `sudo add-apt-repository universe&&sudo apt install libfuse2`で依存関係を入れましょう
7. 最後に`sudo reboot` で再起動しましょう

# 沼ったところ
インストールが終わったので早速`mbed-studio`で起動しようとしたら以下エラーが出ました。
```
The SUID sandbox helper binary was found, but is not configured correctly. Rather than run without sandboxing I'm aborting now. 
```

`mbed-studio --appimage-extract`でアプリを展開？します
それが終わったら`mbed-studio --no-sandbox`でノーサンドボックスモードで起動します。
うまく行けばGUIがでてくるとおもいます

# さいごに
Mbed サ終するらしいですね...
弊部ではMbed OSベースのものが多いので意地でも維持するためにMbed OSをUSBやHDDなどに保存してます。
Mbedのように低レイヤーの低いところ(レジスタとかいろいろ)をあまり意識せずGPIOとかが楽に使えるものがあれば教えてほしいです
え？Arduino？知らない子ですね(過激思想)
【Angular】ESLint設定時のesbuildエラー解消方法！

泉（[@izumin_0401](https://twitter.com/izumin_0401)）です。

今回は、AngularでESLint設定時にesbuildエラーが出て困ったちゃんだったので解消方法を解説します。

:::note info
特定のPCだけesbuildエラーが出たので、エラーが出なければそもそも対応不要です。
:::

# ブログ記事はこちら

https://traveler0401.com/angular-eslint-esbuild-error/

# esbuildエラー内容
```
npm ERR! code EPERM
npm ERR! syscall unlink
npm ERR! path C:\Users\〇〇\Documents\git\project\node_modules\esbuild-windows-64\esbuild.exe
npm ERR! errno -4048
npm ERR! Error: EPERM: operation not permitted, unlink 'C:\Users\〇〇\Documents\git\project\node_modules\esbuild-windows-64\esbuild.exe'
npm ERR!  [Error: EPERM: operation not permitted, unlink 'C:\Users\〇〇\Documents\git\project\node_modules\esbuild-windows-64\esbuild.exe'] {
npm ERR!   errno: -4048,
npm ERR!   code: 'EPERM',
npm ERR!   syscall: 'unlink',
npm ERR!   path: 'C:\\Users\\〇〇\\Documents\\git\\project\\node_modules\\esbuild-windows-64\\esbuild.exe'
npm ERR! }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It's possible that the file was already in use (by a text editor or antivirus),
npm ERR! or that you lack permissions to access it.
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     C:\Users\〇〇\AppData\Local\npm-cache\_logs\2024-09-18T07_14_57_777Z-debug-0.log

added 1291 packages, and audited 1292 packages in 33s

196 packages are looking for funding
  run `npm fund` for details

25 vulnerabilities (13 moderate, 10 high, 2 critical)

To address issues that do not require attention, run:
  npm audit fix

To address all issues possible (including breaking changes), run:
  npm audit fix --force

Some issues need review, and may require choosing
a different dependency.

Run `npm audit` for details.
```

# esbuildエラー解消方法
## package.jsonに追記
```json
"overrides": {
  "esbuild": "npm:esbuild-wasm@latest"
}
```

## VSCodeのsetting.jsonに追記
```json
  "[javascript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "[javascriptreact]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "[typescript]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "[typescriptreact]": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
  "": {
    "editor.defaultFormatter": "dbaeumer.vscode-eslint"
  },
```
これでOK！！

# まとめ

ESLintは色々ハマりポイントがあるよね。

ではまた！

# 参考サイト

https://blog.orz.at/2023/12/20/esbuild-wasm/

# 最後に
暇つぶしに[Twitter](https://twitter.com/izumin_0401)と[ブログ](https://traveler0401.com/)もやってるので見てね。
Python3: GATT のデータを受信

こちらで送信する String を Python で受信しました。
[ESP32: GATT で String を送信](https://qiita.com/ekzemplaro/items/52dc8b065a431147013c)

送信元のアドレスと Characteristic UUID が必要です。

## プログラム

```py:get_data.py
#! /usr/bin/python
#
#	get_data.py
#
#					Oct/02/2024
# ------------------------------------------------------------------
import asyncio
from bleak import BleakClient

DEVICE_ADDRESS = "08:3A:F2:66:04:4A"
CHARACTERISTIC_UUID = "00002a19-0000-1000-8000-00805f9b34fb"

async def read_characteristic(address, char_uuid):
	async with BleakClient(address) as client:
		data = await client.read_gatt_char(char_uuid)
		return data
#
# ------------------------------------------------------------------
async def main():
	for it in range(3):
		data = await read_characteristic(DEVICE_ADDRESS, CHARACTERISTIC_UUID)
		print("Data:", data)
		print("Data:", data.decode())
#
# ------------------------------------------------------------------
asyncio.run(main())
# ------------------------------------------------------------------
```

## 実行結果

```text
$ ./get_data.py 
Data: bytearray(b'Battery: 44475')
Data: Battery: 44475
Data: bytearray(b'Battery: 44900')
Data: Battery: 44900
Data: bytearray(b'Battery: 45375')
Data: Battery: 45375
```
【Laravel】リレーションの書き方

# はじめに
以下はLaravelでAPIを使用してリレーション先を操作するための手順をまとめたメモになります

## データの取得方法
データを取得する基本的な方法は、
- `1対1 (One to One)`
- `1対多 (One to Many)`
- `多対多 (Many to Many)`
それぞれ同様の方式で行えます。


## 1対1 (One to One) のリレーション
「1対1」のリレーションでは、1つのレコードが他の1つのレコードと対応します。
### Modelによるリレーションの設定

```User.php
class User extends Model
{
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
}
```
```Profile.php
class Profile extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
```

- `hasOne()`はUserモデルが1つのProfileを持っていることを示します
- `belongsTo()`はProfileが1人のUserに属していることを示します




## 多対1 (Many to One) のリレーション
「多対1」のリレーションでは、複数のレコードが1つのレコードに関連付けられます。
### Modelによるリレーションの設定
- `hasMany()`はUserモデルが複数のPostを持つことを示します
- `belongsTo()`はPostが1人のUserに属していることを示します。
```User.php
class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}
```
```Post.php
class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}
```
## 多対多 (Many to Many) のリレーション

「多対多」のリレーションでは複数のレコードが複数のレコードに関連付けられます。

### 中間テーブルの作成

多対多リレーションでは、テーブルとテーブルを関連付けるために`中間テーブル`を作成します。中間テーブルには各々のテーブルと関連付けする`外部キー`を用意することで、それぞれのテーブルを関連付けすることができます

https://qiita.com/EasyCoder/items/770861cc21852a7ed0b0

### データの取得例
users テーブルからIDが1のレコードを取得し、それからそのユーザーに紐付いた profiles テーブルのレコードを取得します。

$profile には profiles テーブルのデータのみが格納されます。
```***controller.php
$user = User::find(1);
$profile = $user->profile;
```
users テーブルのデータも同時に使用したい場合は、$user 変数をそのまま使うか、`withメソッド`を使ってリレーション先のデータを最初のクエリと一緒に取得することができます
```***controller.php
$user = User::with('profile')->find(1);
```



## まとめ

- 1対1: `hasOne()` と `belongsTo()` を使う
- 多対1: `hasMany()` と `belongsTo()` を使う
- 多対多: `belongsToMany()` を使う（中間テーブルが必要）
- 「データを取得する基本的な方法は全て同じ」
アンケート結果に差があるかを検定したい

あなたは「ピーマンが好きか」というアンケートを子どもたちにとりました。
また、それとは独立に、「なすが好きか」というアンケートも子どもたちにとりました。
どちらのアンケートも 5 つの選択肢から 1 つ選択する方式で、結果は以下のようになりました (2つのアンケート結果に対応はないものとします)。

|  |ピーマン  |なす  |
|---|---|---|
|好き                 |6票  |8票  |
|どちらかといえば好き  |1票  |7票  |
|どちらでもない       |5票  |2票  |
|どちらかといえば嫌い  |6票  |1票  |
|嫌い                |2票  |2票  |

ただ、この表からでは結局子どもたちのピーマン嗜好性となす嗜好性に差があるのかよくわかりませんでした。

### カイ2乗検定

そこであなたはさしあたり、「2つの野菜間で『好き率』『どちらかといえば好き率』…『嫌い率』に差はない」という母比率の差のカイ2乗検定をしてみました。結果は有意水準5%で棄却されましたが、期待度数が小さいセルがあるのでフィッシャーの正確確率検定のほうがよかったことに気付きました。ただそもそも、この検定では今回の選択肢間に順序があることを考慮していないことに気付きました。

```py
import pandas as pd
import scipy.stats

df = pd.DataFrame({
    'GreenPepper': [6, 1, 5, 6, 2],
    'Eggplant': [8, 7, 2, 1, 2],
}, index=[
    'Like', 'SomewhatLike', 'Neutral', 'SomewhatDislike', 'Dislike'])

print('----- Chi-squared test -----')
chi2, p, dof, expected = scipy.stats.chi2_contingency(df.T)
print(f'{dof=}')
print(f'{expected=}')
print(f'{chi2=}')
print(f'{p=}')
```
```
----- Chi-squared test -----
dof=4
expected=array([[7. , 4. , 3.5, 3.5, 2. ],
                [7. , 4. , 3.5, 3.5, 2. ]])
chi2=9.642857142857142
p=0.046893186991072186
```

### マン・ホイットニーのU検定

そこであなたは、選択肢間の順序を考慮するために、選択肢に点数を割り当て、ピーマンのスコアたちとなすのスコアたちにマン・ホイットニーのU検定をすることにしました。
つまり、ピーマンとなすのアンケートに回答した計 40 人の子どもたちに、つけた点数が小さい順に1列に並んでもらい、なす組の子どもたちに前にピーマン組が何人いるか答えてもらい、ピーマン組の方が前に偏っていないかを調べました。
結果は有意水準5%では棄却されませんでした。

```py
import pandas as pd
import scipy.stats

df = pd.DataFrame({
    'GreenPepper': [6, 1, 5, 6, 2],
    'Eggplant': [8, 7, 2, 1, 2],
}, index=[
    'Like', 'SomewhatLike', 'Neutral', 'SomewhatDislike', 'Dislike'])

print('----- Mann-Whitney U test -----')
df['score'] = [2, 1, 0, -1, -2]  # 選択肢に点数 (スコア) を割り当て
def to_scores(df, colname):
    scores = []
    for index, row in df.iterrows():
        scores += [row['score']] * row[colname]
    return scores
scores_gp = to_scores(df, 'GreenPepper')
scores_ep = to_scores(df, 'Eggplant')
print(f'{scores_gp=}')
print(f'{scores_ep=}')
stat, p = scipy.stats.mannwhitneyu(scores_gp, scores_ep)
print(f'{stat=}')
print(f'{p=}')
```
```
----- Mann-Whitney U test -----
scores_gp=[2, 2, 2, 2, 2, 2, 1, 0, 0, 0, 0, 0, -1, -1, -1, -1, -1, -1, -2, -2]
scores_ep=[2, 2, 2, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 0, 0, -1, -2, -2]
stat=141.5
p=0.10524670367291183
```
bashで複数のデータを一度に変数格納する時に数を確認すればより安全にできるよ。短いコードで。

## やりたいこと
- bashでデータをファイルから読み込んで複数の変数に格納する場合、一つでもデータがない場合は処理させないようにさせたい。


## 考え方
- 変数を配列にしてその数の整合性をチェックすればいい。

### NGなコード


```bash
x=FLASE; y=TRUE; # 初期値
str=$( awk '{print $1, $2}' hoge.txt ); # 結果はstr="TRUE "だとします。
read x, y <<< $str

# チェック
echo $x # -> "TRUE"
echo $y # -> ""
# 片方のデータがない場合、yは””で上書きされて初期値が失われてしまいます。
```

### より安全で簡単なコード
```bash
x=FLASE; y=TRUE; # 初期値
str=($( awk 'print $1, $3}' hoge.txt ))
[ ${#str[@]} -eq 2 ] && x=${str[0]} && y=${str[1]}

# チェック
echo $x; # -> FALSE
echo $y; # -> TRUE
# データが片方ない場合は実行されないので初期値のままです。
```

### 簡単な説明
- `str=($( ... ))`と`$(...)`を`()`で囲んで配列に入れます。
- これを`${#str[@]}`で数を勘定し、これを予定の個数にあれば代入式を実行させます。
- というわけで、複数のデータを取り出す場合、一つでもデータの欠損がある場合は処理させないようにできます。

### 結果にスペースのある場合
- 結果を""で囲ってください。
```bash
str=("a A" "b B");
[ ${#str[@]} -eq 2 ] && x=${str[0]} && y=${str[1]}
# チェック
echo $x; # -> a A
echo $y; # -> b B
# それぞれを""で囲えばうまく行きます。
```


簡単な仕掛けでより安全にできるのはいいですね。どなたかのお役に立てれば幸いです。
FTP、FTPS、SFTP、SCPの違い

ファイル転送プロトコル（FTP、FTPS、SFTP、SCP）は、インターネットを通じてファイルをサーバーや他のデバイスに送信するためのさまざまな手段です。

とはいっても未経験エンジニアの私にはさまざまな記事を読んでもなかなか吞み込めず毎度調べなおしていたので記事にしてアウトプットして覚えていきたいナ。

※内容に誤りがあればご教授いただきたいです。

## 1. FTP (File Transfer Protocol)

### 概要
FTPは、最も古いファイル転送プロトコルの1つです。TCP/IPネットワーク（例えばインターネット）を使ってファイルをサーバー間で転送します。ただし、データと認証情報（ユーザー名とパスワード）が暗号化されないため、セキュリティに不安があります。

### 使用場面
- ファイルが公開されているため、セキュリティが特に問題でないとき。
- ローカルネットワーク内でのファイル転送。

### メリット
- シンプルで設定が容易。
- 多くのツールが対応している。

### デメリット
- 暗号化されていないため、セキュリティが弱い。

### 例
FTPは、普通郵便で封をせずに手紙を送るかんじです。簡単で安価ですが、他の人に手紙の内容を覗かれる可能性があります。

---

## 2. FTPS (FTP Secure)

### 概要
FTPSは、FTPにSSL/TLS暗号化を追加したものです。暗号化された通信チャネルを使用して、認証情報やファイルが安全に送信されます。

### 使用場面
- 安全性が求められるファイル転送（例えば、機密情報の送受信）。
- FTPの使用が義務付けられているが、暗号化が必要な場合。

### メリット
- 暗号化によりセキュリティが向上。
- 標準的なFTPの仕組みを維持しながらセキュリティを強化できる。

### デメリット
- ファイアウォールやネットワークの設定が複雑になることがある。
- FTPSをサポートしていないクライアントが存在する場合がある。

### 例
FTPSは、普通郵便で封緘して手紙を送るかんじです。内容は暗号化されているので、盗まれても中身が読めません。

---

## 3. SFTP (SSH File Transfer Protocol)

### 概要
SFTPは、SSH（Secure Shell）を基盤としたファイル転送プロトコルです。SSHを使用して、データと認証情報のすべてが暗号化されます。FTPとは異なり、SFTPはファイル転送のための完全なプロトコルで、単にセキュアな「FTP」ではありません。

### 使用場面
- 安全なファイル転送が必要な場合。
- リモートサーバーへのセキュアなアクセスを頻繁に行うプロジェクト。

### メリット
- 完全に暗号化されており、高いセキュリティを提供。
- 1つのポート（通常22番ポート）を使用するため、ファイアウォールの設定がシンプル。

### デメリット
- 通常のFTPよりも設定がやや複雑。
- 転送速度がFTPSやSCPに比べて遅い場合がある。

### 例
SFTPは、セキュリティガード付きの金庫の中に手紙をいれて送るようなものです。誰もその中身を見ることができませんし、金庫がしっかりと守られています。

---

## 4. SCP (Secure Copy)

### 概要
SCPは、SSHを利用してファイルを転送するプロトコルで、単純かつ高速です。ファイルの転送に特化しており、ファイルの権限やタイムスタンプも保持できます。

### 使用場面
- 高速なファイル転送が必要で、セキュリティが重要な場合。
- 単純なファイル転送のためのツールとして利用する場合。

### メリット
- SFTPよりも高速にファイルを転送できる。
- ファイルのメタデータ（タイムスタンプ、権限）も転送可能。

### デメリット
- ファイル管理（削除、リスト表示など）はできない。
- SFTPほど多機能ではない。

### 例
SCPは、速達便を使って鍵付きの金庫で手紙を送るようなものです。セキュリティが強固であり、素早く届きますが、管理は最低限の機能しかありません。

---

## 6. まとめ表

| プロトコル  | 暗号化 | ポート番号 | 使用場面                                      | メリット                    | デメリット                    |
|-------------|--------|------------|-----------------------------------------------|-----------------------------|-------------------------------|
| **FTP**     | なし   | 21         | セキュリティが不要なローカルファイル転送      | シンプル、広く対応          | セキュリティが弱い             |
| **FTPS**    | あり   | 21/990     | 暗号化されたFTPが必要な場合                    | 暗号化でセキュリティ強化     | 設定が複雑                    |
| **SFTP**    | あり   | 22         | セキュリティが重要なファイル転送              | 完全に暗号化、高いセキュリティ | 転送速度がやや遅い             |
| **SCP**     | あり   | 22         | 高速なファイル転送が必要でセキュリティも重要   | 高速かつ安全                | ファイル管理機能が不足         |

---
AWSのlambdaにデプロイされたイメージをローカルで編集する方法

## 概要
最近途中から参画した案件でawsのlambdaを使うことがあったのですが、今まで経験がなかったため備忘録としてまとめます。
ざっくりした内容としては表題の通り、lambda関数にイメージがデプロイされていた場合、どのような手順で内容を編集し、更新するのかについてとなります。

## 前提
- Dockerの環境構築済み
- AWS CLIの環境構築済み
- 既存のlambda関数、イメージが存在する
- 既存リソースの更新であり、新規作成ではない

## 手順

### ECR, docker のログイン
AWSにおいてイメージはECR(Elastic Container Registry)で管理されます。そのため、外部からイメージを取得するには、ログインしておく必要があります。

```
aws ecr get-login-password --region YOUR_REGION | docker login --username AWS --password-stdin YOUR_ACCOUNT_ID.dkr.ecr.YOUR_REGION.amazonaws.com
```

以下の項目については、各自該当するものに修正してください。
- YOUR_REGION：東京であれば"ap-northeast-1"となります。
- YOUR_ACCOUNT_ID：AWSマネジメントコンソールの右上にある「ユーザー＠●●●●」をクリックすると、アカウントIDが表示されます。

### イメージの取得とコンテナの起動
ログイン完了後、編集予定のイメージをローカルに落とし、コンテナを起動します。
```
docker pull IMAGE_URI #イメージの取得
docker run -it --entrypoint /bin/sh IMAGE_URI #コンテナの起動
```
- IMAGE_URI：該当のlambda関数をクリックしたのち、下記画像の黒塗り部分に記載されています。
![lambda_image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3899846/f404bec1-7956-f634-b51d-f2c4d38c98eb.png)

※イメージは既存のエントリーポイントを持ちますが、上記コマンドではコンテナ内のエントリーポイントを指定しているだけであるため、イメージ側が更新されるわけではない。

### コードの編集
CUIでの編集となるため、linuxコマンドを使用することになります。
コマンドやファイルの編集方法は以下を参照してみてください。基本的な操作になるため、もっと深く知りたい方は調べてみてください。

https://qiita.com/nokonoko_1203/items/35c4078bf72cffb16171

https://coeure.co.jp/blog/infrastructure/centos/linux-vi-210225

### イメージの更新
コードの編集が終わったらECRのイメージを更新する必要があります。
```
docker commit CONTAINER_ID IMAGE_NAME
docker push IMAGE_NAME
```
- CONTAINER_ID：これはローカルで編集していたコンテナのIDになります。確認方法としては`docker ps -a`などを実行し、出力結果のCONTAINER IDを持ってきてください。
- IMAGE_NAME：例えばIMAGE_URIがxxx/xxx:latestとなっていた場合、xxx/xxx部分だけを使用してください。

### lambda関数の更新
イメージの更新が終わったら、更新後のイメージをlambdaで利用するように設定します。
まずは、コードのみを更新し、その後設定を更新します。（一般的にコード更新->設定更新の順）
```
aws lambda update-function-code --function-name LAMBDA_FUNCTION_NAME --image-uri IMAGE_URI
```
- LAMBDA_FUNCTION_NAME：更新したいlambda関数名
- IMAGE_URI：タグを指定していない場合、"IMAGE_NAME:latest"とする

次に、設定の更新になります。ここでの設定とは例えば以下のようなものが挙げられます。
- メモリ割り当て
- タイムアウト
- 環境変数
- IAMロール
- VPC設定
- ランタイム
以下のコードではメモリとタイムアウトだけ更新しています。

```
aws lambda update-function-configuration --function-name LAMBDA_FUNCTION_NAME --timeout 900 --memory-size 512
```
- LAMBDA_FUNCTION_NAME：上と同様

lambda関数の更新に利用するそれぞれのコードは実行に時間がかかります。
コードの更新中に設定の更新を行うとエラーになる点には注意してください。
各更新が終わったのかは以下のコードで確かめることができます。
```
aws lambda get-function-configuration --function-name LAMBDA_FUNCTION_NAME
```
`last_update_status`という項目が`Successful`となっていれば実行が完了しています。
東京で使えない Snowflake LLM モデルを使えるようにしよう【クロスリージョン推論】


# 背景

Snowflake Cortex では、Complete 関数と呼ばれる LLM の応答を簡単に得られる SQL 関数が存在します。
```sql
select snowflake.cortex.complete('mistral-large2', 'こんにちは');
```
    
応答例は次のようになります。
```
こんにちは！なにかお手伝いできることはありますか？
```

この関数は、Snowflake がデプロイされている[様々なリージョン（アメリカ、東京など）](https://docs.snowflake.com/en/user-guide/snowflake-cortex/llm-functions?_ga=2.97753308.25952711.1727834704-73373359.1724047909&_fsi=6aONurIG#availability)で使用できます。

しかし、上記リンクからも分かるように、すべてのモデルが各リージョン、例えば東京リージョンで使える訳ではありません。例えば、Snowflake が開発した `snowflake-arctic` モデルは現時点では、AWS オレゴンリージョンでしか使うことができません。


# 解決策
そこで Snowflake は、[クロスリージョン推論](https://docs.snowflake.com/en/user-guide/snowflake-cortex/cross-region-inference) という機能を提供しています。この機能では、推論呼び出しを現在のリージョンとは異なるリージョンで処理できるように構成できます。

設定方法は、`ACCOUNTADMIN` ロールで下記のコマンドを実行するだけです。
```sql
// AWS US リージョンに設定
ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'AWS_US';

// すべてのリージョンに設定
ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'ANY_REGION';

// 複数のリージョンに設定
ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'AWS_US,AWS_EU';
```


:::note warn
本オプションはアカウント全体に影響するため、各環境におけるセキュリティ要件に注意して設定するようにしましょう。
:::

# 試してみる
AWS Tokyo リージョンで構成された Snowflake トライアルアカウントで実際に確認してみます。

まずは、AWS オレゴンリージョンでしか使えない `snowflake-arctic` を呼び出してみます。
```sql
USE ROLE ACCOUNTADMIN;
SELECT snowflake.cortex.complete('snowflake-arctic', 'こんにちは');
```
すると当然ですが、下記のようにモデルが見つからない旨のエラーが生じます。
```
100351 (P0000): Request failed for external function COMPLETE$V2 with remote service error: 400 '"unknown model \"snowflake-arctic\""
```

次に、クロスリージョン推論を `AWS US` に設定した上で同じように `snowflake-arctic` を呼び出してみます。
```sql
USE ROLE ACCOUNTADMIN;
ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'AWS_US';
SELECT snowflake.cortex.complete('snowflake-arctic', 'こんにちは');
```

すると、下記のように適切に応答が返ってきたことが分かりました。
```
こんにちは！今日はどのようにお手伝いできますか？
```

個人的にとても驚いたのが、設定時間やレスポンス時間がほぼなかったことです。どちらも数秒の内に完了してしまいました。

また、念の為、下記のコマンドでデフォルト設定であるクロスリージョン推論の無効化を行っておきましょう。
```sql
USE ROLE ACCOUNTADMIN;
ALTER ACCOUNT SET CORTEX_ENABLED_CROSS_REGION = 'DISABLED';
```


# 終わりに
そもそもクロスリージョン推論という機能があることを知らなかった方、クロスリージョン推論という機能があることは知っていたけれどどのように設定するか知らなかった方、そうは言っても設定に時間かかるんでしょ？と考えていた方、などに参考になりましたら幸いです。

ぜひ頭の片隅に入れておきましょう。もちろんセキュリティの観点もお忘れなく。

楽しい Snowflake LLM ライフを！🏄️
goのテストでファイルが削除できずにエラーになっていた件

## 発生していた問題


#### 原因のテストコード
goのテストでは、t.TempDir()というフォルダを使用するとテスト終了時に勝手に該当のフォルダを削除してくれる機能があります。
```
testFile, err := os.Create(t.TempDir() + "/" + fileName)
if err != nil {
	t.Fatal(err)
}
```

実際にテストを実行したところ以下のようなエラーが出ていた。
```
c:\...\testing.go:1232:
TempDir RemoveAll cleanup: remove 
C:\...\test_for_delete.txt:
The process cannot access the file because it is being used by another process.
```

### 解決策
os.Createで作成したファイルをCloseしていなかったことが原因でした。
```
testFile.Close()
```

最終的なコードは以下のようになりました。
```
testFile, err := os.Create(t.TempDir() + "/" + fileName)
if err != nil {
	t.Fatal(err)
}
defer testFile.Close()
```

#### まとめ
ファイルを閉じ忘れていたというありがちなミスでしたが、気づくのにかなり時間を使ってしまいました。
LinuxなどOSによってはファイルを開いたままでも削除できたため、Windowsであるローカル環境特有の原因に気づきにくかったのも原因の一つです。
にしてもファイルぐらい勝手に閉じておいてほしいとも思わないこともないですね。
【AWS】SageMakerで、「Unable to delete userprofile [xxxxx] because space(s) are associated with it.」と言われる

# はじめに
こんにちは、ユーゴです。今回は、AWSで勝手にSageMakerに課金されていたので、おこりながらプロジェクトを削除できない問題に対処していたお話です😾
調べていたところ、「CLIで消せるよ〜」という記事が多く見つかりましたが、それでもうまくいかず、GUI上でどうにか消そうと奮闘しました。

# 問題
以下のようなエラーとともに、SageMakerのドメインのユーザープロファイルが削除できない

```Unable to delete userprofile [xxxxx] because space(s) are associated with it.```

# 原因
アプリケーションが残っている

![ユーザーが削除できない_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/c44a6f76-4924-730b-ce0b-8937dcedae20.png)

# 解決策
「スペースの管理」から、アプリケーションを消す

![ユーザーが削除できない_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2607452/b5c62770-f165-e35e-1f38-f4bbe429841b.png)

あとはユーザープロファイルを削除するだけです。

# まとめ
いかがだったでしょうか。今回は、AWSのSageMakerで起きた問題について紹介しました。

このように、私の記事ではAWSの紹介から、Unity, GAS, 量子コンピューティングなど、幅広い技術を紹介していきます。
お役に立てましたら、いいね, フォローなどよろしくお願いします！
TableauとTabPyことはじめ~Dockernizeしてみる~

## 目的
DataSaberになるための奮闘記です。
この記事は、次のシリーズ3つ目の記事となります。
1. TabPy とTableauを接続してみる
    * https://qiita.com/s_rokuemon/items/b837aef0682048644a9f
1. TabPyとTableauで機械学習してみる 
    * https://qiita.com/s_rokuemon/items/57a041b154fb1a9438a1
1. TabPyをDockernizeしてみる ← これ！

前回、TabPyサーバに機械学習モデルをデプロイしました。
今回はその環境をDockernizeします。

Dockernizeすることでコード化された環境をチームやメンバに共有可能になり、再現性と再利用性が高まるメリットがあります。

### 動作環境
DockerおよびDocker composeのバージョンは以下の通りです。
その他の動作環境は前回と同様です。
``` sh
$ docker --version
Docker version 27.2.1, build 9e34c9b

$ docker-compose -v
docker-compose version 1.27.4, build 40524192
```

## ファイルを作成する
### 1. Dockerfileを作る
python3.8をベースに必要なライブラリをインストールします。
ライブラリのバージョンを固定するならrequirement.txtを作成してもよいですね。
``` Dockerfile
FROM python:3.8.10
RUN python3 -m pip install --upgrade pip
RUN pip install tabpy
RUN pip install tabpy_client
RUN pip install pandas
RUN pip install numpy
RUN pip install scikit-learn
```

### 2. docker-composeファイルを作成する
``` yaml
version: '3.8'
services:
  tabpy-service:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "9004:9004"
    volumes:
      - ./script/:/app
    command: /bin/bash -c "tabpy --disable-auth-warning & sleep 5 && python3 /app/tabpy_deploy_ml_model_titanic.py && tail -f /dev/null"
```
次の手順となっています。
1. Dockerファイルからイメージを作成する
1. ポート9004を開放する
1. ローカルの./script配下をコンテナ内の/app配下にマウントする
    * 前回の記事で作成した”tabpy_deploy_ml_model_titanic.py”を./scriptに格納しておく
1. commandブロックについて
    1. "sleep 5" はTabPyサーバが起動完了するまでの待ち時間
    1. TabPyサーバの起動とカスタム関数を実行

#### POINT
commandブロックの内容を実行後にコンテナが停止します。
そのため、下記コマンドを実行させることで、コンテナの起動を維持します。
``` sh
tail -f /dev/null
```

同様の効果があると思われる次のオプションではコンテナが自動的に停止してしまった。
原因調査は別途したいと思います。
``` yaml
tty: true
stdin_open: true
```

## イメージの作成とコンテナ起動
次のコマンドでDockerイメージのビルドとコンテナが起動されます。
``` sh
$ docker-compose up --build -d
```

## 結果
起動確認後、Tableauの分析拡張機能の接続の管理から接続テストを行うと、正常にコンテナ内に立ち上げたTabPyサーバと接続できていることがわかります。
![{667B9ACC-703F-424E-B802-C93BB09874EA}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/53b93c09-85f2-4fea-9b6f-e4fc03410f5d.png)

## 最後に
Tableau-TabPyと戯れる3つのシリーズはいかがでしたでしょうか。
個人的には長らく利用してみたかったライブラリを扱えたため、記事を執筆しながらとても勉強になりました。
Tableauでのヴィジュアライズを支える技術について、より知識を深めていきたいと心を新たにしました。

## スペシャルサンクス
本記事を執筆するにあたり次のサイトを参考にさせていただきました！ありがとうございました。
https://note.com/uni_3/n/n852cd8c43c4b
https://tableaujpn.blogspot.com/2020/03/tableaupythontabpydocker.html
mendeleyでreferenceのstyleをカスタマイズする方法

1.https://csl.mendeley.com/visualEditor/
を開く

2.mendeleyのアカウント情報を入力してログインする

3.左うえのsearch by nameから変更する元となるstyleを検索してedit

![スクリーンショット 2024-10-02 10.52.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2671781/89d13ac2-15ec-d4c7-20ba-6437b0a9b0be.png)

4.適宜修正して、左上のstyle>saveで保存。

5.保存の際にリンクが表示されるので、/style/722~~
のところのリンクをコピー

6.wordでmendeley citeを開いて、citation settings>change citation style>add a custom styleで先ほどのリンクを貼り付ける、


ちなみにBJJ(bone Joint Journal)にするなら下記URLを添付すればユーザーを超えて使えるかも、、？
https://csl.mendeley.com/styles/722947891/vancouver-superscript
テスト向けのjavascriptスクリプトを入力すると実行するサイトです。

# はじめに
javascript、jqueryのスクリプトをテキストエリアへ入力して、実行ボタンを押すと実行して、結果を確認できるシンプルなサイトです。
スクリプトの初心者向けに利用していたたければ、うれしいです。シンプルなコードであれば、実行して確認できます。デフォルトのコードがあらかじめ、セットしてありますので、実行ボタンを押すと、確認できます。
サンプルのように、jqueryでも動作します。


# サイトリンク
[https://favorite.tecoyan.net/slim/testGenerator.php](https://favorite.tecoyan.net/slim/testGenerator.php)

# サンプルコード
webサイトの作成で、コードの確認をしたいときにすぐに利用できます。
一般的には、ネットにあるサンプルコードを確認したいときは、自前のサーバにテストページをつくってから実行して確認します。その手間を省くことができます。ただし、現状は、複雑なコードは確認していません。あくまでもスクリプトコードのみです。静的なhtmlタグを直接入力することはできません。動的な.append()ぐらいで入力したhtmlタグは、サンプルにもありますが、動作しています。


# 実行方法
特に難しい操作はありません。入力して、実行ボタンを押すだけです。

# スクリプトの敷居が高い方に
プログラミングは難しいということで断念してしまっている方は多いかと思います。それはおそらく、入り方の問題でいきなり、難しい文法、構文解釈などからスタートするからだと思います。まずは簡単なサンプルで動作を確認することから入ると入りやすいかと思います。難しい文法や構文の解釈は法律の勉強と同じで、難度が高いです。最初はデモのようなサンプルからがいいと思います。

# 慣れてくると問題を自己解決できるようになります。
プログラミングして行くと、さまざまな問題に出会います。なれてくると、自分でネットや書籍で調べて、自己解決できます。それまでは、セミナーや勉強会に参加して習得することもあります。経験を積めば、自分で調べて、テストし、もちろん試行錯誤して悩むことはありますが、大抵は辛抱強くテストを繰り返してゆくと解決することは多いです。


# あとがき
ネットにあるサンプルコードを実行して確認したいことはよくあります。その場合、実行環境をつくるのが手間で躊躇することは有ります。簡単にテストできないかと思い作成しました。それと、全くの初心者の方向けに、例えば、a= 1+2;とかして、その結果を表示するにはどうすればいいのかというような初心の方にも、わかるようなサイトにしてみました。
【vscode】エクスプローラーの位置が移動した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845300/a00acd14-c702-93a7-4ad2-7f7b9760b274.png)
エクスプローラーがいなくなってしまうことがあります。その対処法です
コマンドパレットを開いて、
```
>View: Reset View Locations
```
を入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3845300/c118eb1f-8136-2a46-4ae9-6b651786907e.png)
TableauとTabPyことはじめ~TabPyとTableauを接続する~

## 目的
DataSaberになるための奮闘記です。
この記事は、3つの記事からなるシリーズはじめの記事となります。
1. TabPy とTableauを接続してみる ← これ！
1. TabPyとTableauで機械学習してみる
    * https://qiita.com/s_rokuemon/items/57a041b154fb1a9438a1
1. TabPyをDockernizeしてみる
    * https://qiita.com/s_rokuemon/items/f2b2df3ecdd09fffe9d1

## そもそもTabPyとは

> TabPy (Tableau Python Server) は、ユーザーが Tableau の表計算を介して Python スクリプトと保存された関数を実行できるようにすることで Tableau の機能を拡張する、分析拡張機能の実装です。

ユースケースととして次のように紹介されています。
> Tableau 内のデータクリーニングと予測アルゴリズムに Python を使用する。

### 動作環境
Tableau Desktopバージョン 
**2021.3.14 (20213.22.0707.1757) 64 ビット**


``` sh
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.6 LTS
Release:        20.04
Codename:       focal

$ python -V
Python 3.8.10

$ pip3 show tabpy
Name: tabpy
Version: 2.12.0
```

## 導入方法
### 1. TabPyライブラリのインストール
``` sh
$ pip3 install tabpy
```
### 2. TabPyサーバの起動
ローカルのポート9004でTabPyサーバが起動していることがわかります。
``` sh
$ tabpy
...
2024-09-28,11:00:42 [INFO] (app.py:app:167): Web service listening on port 9004
```
### 3. TabPyとTableau Desktopの接続
#### 1. Tableau ヘルプ > 設定とパフォーマンス > 分析の拡張機能接続の管理 > TabPyを選択
![{81BD1BFF-068B-47BB-B87F-D11DF6B77CD0}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/4f859beb-8690-b1d1-84d6-024446c6e558.png)

 ![{7BD80456-71EC-4171-AD92-9D97E6CC40CC}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/47e6ddc3-b9c5-b636-d57c-4bf68b14adcf.png)

![{44027ADB-69C7-4F24-98C3-893E3E633334}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/1a671a7d-89f4-0607-f341-e8d000ea2a0a.png)

#### 2.接続
サーバ: 127.0.0.1, ポート: 9004と設定してサインイン
![{D2C1ED70-236E-4DB3-929A-658635B6C805}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/dffa6cc7-4931-6785-25d8-60767047f6a3.png)

テスト接続を押下し正常に接続できていれば下図のポップアップが表示される

![{D1D502FF-E8A7-4471-A866-56D0ABEA3184}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/67c762d6-bdfe-ee3f-8f34-f05b10c0f79a.png)

## TableauからPythonを実行させる
TableauでTabPyを使う方法として2つあります。
今回は、前者の方法を試してみたいと思います。
* Tableauのカスタム計算フィールドでPythonスクリプトを記述しTabPyと通信する
* 事前にTabPyサーバにデプロイした関数を利用する

図のように計算フィールドに記述します。
売上を10倍にしてみます。
![{548EACF6-96FB-4D07-95E0-84A8D3D12468}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/7122d61f-eb35-2161-136a-d00189d2d379.png)

## 結果
結果はこのとおり！TabPyでやる必要のないレベルの計算ですが。。。
![{CBC5E729-98DF-42CC-A225-75E71DA2BDFE}.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3833399/2b10d7a5-70c1-16d2-bf7c-fd7c0a2009f5.png)

## 最後に
TabPyとTableauを接続してみました。
正常に接続できたところで、次回はTabPyで機械学習してみたいと思います。

## 引用
https://www.tableau.com/ja-jp/developer/tools/python-integration-tabpy
【42Tokyo本科生向け】はじめてのチーム開発

# はじめに
本記事は42Tokyoのfirst circle初のチーム課題に臨む本科生に向けたものです。今後追記すると思います。

## この記事でわかること
- チーム開発経験がない方がどのように円滑に協業すればよいのか
- チーム開発での最低限のgit(githubを仮定します)の使い方

## この記事でわからないこと
- チーム開発のあるべき方法論
- minishellの内部実装のTIPs
- 各単語の詳細説明

# 推奨しない/する協業プロセス
## 推奨しない
1. 開発したい機能をmainブランチでプッシュする
2. 相方の作業前にgit pullしてもらう

→こちらの問題点は、コンフリクトが発生した際に解消が非常に厄介であることに加え、mainブランチが動作する保証がなく、ロールバックしたいときにどこまで戻れば少なくとも実行できる状態なのか判断が難しいことです。

## 推奨する
1. githubのissueタブで開発したい機能のissue作成
2. 'git checkout -b {issue番号を含んだbranchの名前}'で作業ブランチ作成
※このとき、　作業中のコミットメッセージにissue番号を含めるとissueタブに反映されます。
3. 実装が完了したら、pushしてgithubのPull Requestタブからプルリクを作成
4. チームメンバーにレビューしてもらい、問題なければマージする
参考：https://qiita.com/tkmd35/items/9612c03dc60b1c516969

→この場合、gitflowモデルをどこまで踏襲するかには寄りますが、mainブランチは少なくとも稼働することは保証されるように出来るはずです。

# 円滑な協業のための3つのルール
1. 目的の統一
→マンダトリー一つとっても解釈が分かれるので、スタンスを明確にした上でチームで意思統一がされている状態がやりやすいはずです。例えば、例外処理一つとってもエラーを出すだけか、プログラム自体を終了させるか等。
2. ドキュメントの統一
→githubのissueにすべて残しましょう。自分たちは突発的に見つかった修正事項等はすぐにissueを立てて相手に修正意見を提示したり議論したりしていました。
3. コーディングルールの統一
→簡単なもので良いので見やすい関数名のルールを定めるとだいぶやりやすいと思います。自分たちは関数の先頭はなるべく動詞になるようにしました。リーダブルなコードのためには1関数に命名しやすいわかりやすい一つの仕事がある状態が良いです。normは最後に修正しました。

# おわりに
　本科生用のScrapboxで書いていたものを再掲しました。かなり簡潔に書いているので今度LT会なんかでも話そうかな…
カーソルストーカーを表示する

カーソルストーカーを表示するためにChatGptで勉強した結果このようになりました。
追加分だけを記述します。
```App.jsx
<div
        className="custom-cursor"
        style={{
          top: `${mousePosition.y}px`,
          left: `${mousePosition.x}px`,
          backgroundColor: isPressed ? 'blue' : 'red', 
        }}
      >
</div>
```
```App.css
.custom-cursor {
  position: absolute;
  width: 20px;
  height: 20px;
  background-color: red; /* カーソルの色を赤に設定 */
  border-radius: 50%; /* 丸いカーソルを作成 */
  pointer-events: none;
  transform: translate(-50%, -50%); /* カーソルの中央に位置合わせ */
}
```

私が使っている言語はReactですので、jsが含まれるものはjsxファイルに書き込んだほうが楽なのだと思います。





プログラミングを読んでみると
App.jsxから、座標を取得したところに位置を指定していることがわかります。
そして、背景色をisPressedがtrueならblueを、falseならredを表示するプログラミングとなっています。





App.cssはこのカーソルストーカーのサイズなどを作るおまけ程度のものです。
もし、posistion:absolute;がなければ、
top,leftなどが使えないので、カーソルが動きません。
width,heightは.custom-sursorのサイズ、つまりカーソルストーカーのサイズを意味しています。
border-radius:50%;は表示を丸に変更します。
transform:transrate();はカーソルの位置に色の円を調整します。

問題なのがこれ、pointer-events:none;
pointerの下に円があるので、pointer自体が反応してもクリックできないのでpointerの機能を消す、そうするとpointer-events:none;によって、自動でカーソル機能が円につきます。

詳しくは
[pointer-events](https://developer.mozilla.org/ja/docs/Web/CSS/pointer-events)
illustratorCC2024プラグインでダイアログを使う

Adobe illustrator CCでダイアログを使う場合inDesignと挙動が違ったためメモ。

## 参考
- [InDesign CC 2024 プラグインでダイアログを使う](https://qiita.com/mzone/items/3b206358fdfdab61eed9)

## 環境
- illustratorCC(2024)
- Visual Studio Code
    - plugin: [ExtendScript Debugger v2.0.3](https://marketplace.visualstudio.com/items?itemName=Adobe.extendscript-debug)

## ダイアログに入力項目を入れておく場合

inDesignとの違いは、`textEditboxes`が出てこない、`add`関数を使うなど、全く違ってしまった（両方共通の方法があるかもしれませんが、今回見つけられませんでした）

```js
// 実施したい処理
function run(inPutText) {
    alert(inPutText);
}

// ダイアログを作成
var dialog = new Window('dialog', 'Input Text');
with (dialog) {
    var inputArea = add('edittext', undefined, '', { multiline: true, scrolling: true });
    inputArea.size = [300, 100];
    var okButton = add('button', undefined, 'OK', { name: 'ok' });
}
okButton.onClick = function() {
    run(inputArea.text);
    dialog.close();
};
dialog.show();

```
macOSのVagrantでVirtualBox7.1に対応するワークアラウンド

この記事はVagrant 2.4.1を対象にしています。2.4.1段階ではVirtualBox7.1に対応していないため暫定対応を行います。

`/usr/local/bin/VBoxManage`を次のように編集します。

```
#!/bin/bash
if [[ $@ == "--version" ]]; then
   echo "7.0.0r164728"
else
    exec /Applications/VirtualBox.app/Contents/MacOS/VBoxManage "$@"
fi
```
Mac Pro6.1 Sequoia インストール完了！

2013年発売のMac Pro6.1を使ってますが、OSがMontereyまでしか対応してなくて、最近いくつかソフトが使えなくなって来てました。
動作はそこそこ安定していたのですが、sequoiaも新たに出たことだし、思い切ってOCLPを使って、アップデートすることにしました。

## OCLPを使ってアップデート開始。
youtubeチャンネル かぼしーさんとTAIKUNさんの説明動画参考にさせていただきました。動画は、すごくわかりやすくて、大変役に立ちました。

### OCLP
https://dortania.github.io/OpenCore-Legacy-Patcher/

### 参考にした動画
https://www.youtube.com/watch?v=HGZko7x4-8E

https://www.taikun-room.com/2024/09/how-to-install-macos-sequoia-on-unsupported-mac.html

## ブートピッカー起動せず
手順通り順調にアップデート進めていましたが。オプションキーを押しながら再起動を何回してもブートピッカーが起動せず。数日悩んだ挙句に、キーボードとマウスをWindows用の安物に変更し、コンセントも一旦引っこ抜いて差し直し、Altキーを押しながら起動。するとブートピッカーが立ち上がりました（何が功を奏したのかは、わかりませんが、、）。

## FileVaultオンのせいで上書きアップデートできず。
どうしてもFileVaultをオフにできず、結局SSD初期化してクリーンインストール。
無事にインストール終了。

## Chromeの画面が乱れて、見れない。
chromeをインストールしたら、chrome内だけ、画面が乱れて見れない。
どうやらこれはAMDのGPUに問題があるみたいで、パッチを当ててとりあえずは、chromeが使えるようになって、一安心（Chrome使えないと、いろいろ面倒）。

### Patch情報
https://blog.kabocy.com/mac/11410/#OCLP-Fixing-Google-Chrome

## 今のところ順調
そろそろmac買い替えかなと思ってましたが、もう少し大丈夫かな。
AI言語モデルについての勉強

## はじめに

AI製品の開発のために大規模言語モデルやそれをどう開発するかの勉強をはじめました。
メジャーなAI言語モデルにはどのようなのがあって、それをどう開発に活かせるか調べた内容の備忘録も兼ねて記事にします。

## AI言語モデル

### [GPT-4 (OpenAI)](https://openai.com/index/gpt-4/)

GPT-4は、OpenAIによって開発された自然言語処理モデルであり、前身のGPT-3の強化版です。膨大なデータセットで訓練されており、多様なタスクに対応できる汎用性が特徴です。
Github CopilotなどもGPT-4を活用したサービスです。

- 技術的特徴
  - 高度な文章生成能力、質問応答、翻訳、対話システムの構築などが可能
  - テキストベースの処理を得意としており、GPT-4ではマルチモーダルにも対応
    - マルチモーダルとは、「テキスト」「画像」「音声」といった数種類の入力を同時に処理できること

### [Gemini (Google DeepMind)](https://gemini.google.com/?hl=ja)

Geminiは、Google DeepMindによって開発されたAIモデルで、自然言語処理をはじめとする様々なAIタスクに対応します。最新の技術を用いて、より人間に近い理解と生成能力が特徴です。

- 技術的特徴
  - 強化学習やトランスフォーマーベースのアーキテクチャを使用し、高精度なタスク処理を実現
  - マルチモーダルな情報を扱うことを前提に根本から設計されており、マルチモーダルによる複雑なタスクの処理が可能

### [Llama 3 (Meta AI)](https://llama.meta.com/)

Llama 3は、Meta によって開発されたAIモデルで、自然言語処理タスクに特化しています。Llama 3はオープンソース化されており、企業・研究機関・個人の開発者など、誰でもダウンロードして利用できる点が特徴です。

- 技術的特徴
  - 分散処理と効率的なトレーニング手法を採用し、より迅速かつ正確な応答が可能
  - 特に推論やプログラミング、複雑な指示の理解など、高度な知的タスクにおいて優れている
  - モデルの学習結果を非商用であれば利用できる点が他のメジャーな大規模言語モデルと違う
    - モデルの学習結果は、ほとんどの大規模言語モデルAPIを通じて限定されたアクセスしかできない

### [Phi-3 (Microsoft)](https://azure.microsoft.com/ja-jp/products/phi-3)

Phi-3は、Microsoftが開発した無料で使える高性能なSLMです。特に構造化データの理解と生成に優れており、専門的なデータ解析や特定分野での利用できる点が特徴です。

SLM (Small Language Models) とは、上3つの大規模言語モデルとは異なり、少ない学習データで計算リソースの消費を抑えつつ、高いパフォーマンスを発揮することが可能です。用途に合わせてカスタマイズしやすく、オンプレミス環境での運用に適した言語モデルです。

- 技術的特徴
  - スマートフォンでローカルに実行でき、オフライン環境でも利用可能
  - データ構造の理解に強みを持ち、特定の業界向けにカスタマイズされたソリューションを提供
生成AIに初心者向けの大規模言語モデルの解説をしてもらった

AI製品の開発のために大規模言語モデルやそれをどう開発するかの勉強をはじめました。
まずはAIサービスを様々触ってみるというところで記事作成も兼ねていろいろ試してみます。
(利用モデルはGPT-4oです)

---

本記事は生成AIを利用して作成してみました！（※内容が誤っていないか確認して投稿しています）
生成AIを活用するとこのような記事が手軽に作成できます！

ちなみに生成AIには、以下のように指示してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/70721a4f-fcb9-87f6-65b2-ccf574a3322c.png)

以下生成AIが作成した記事です。（理解の補助のため画像は別途追加しました）

## はじめに

近年、人工知能（AI）の分野で注目を集めている「大規模言語モデル」（LLM）という技術をご存知でしょうか？これは、膨大な量のテキストデータを学習し、自然な言語での対話や文章生成ができる高度なAIです。本記事では、初心者の方でも理解しやすいように、大規模言語モデルの基本的な概念から、そのアーキテクチャや生成AIとの違いについて解説していきます。

## 大規模言語モデルとは

大規模言語モデル（Large Language Model、LLM）は、テキストデータを大量に学習することで、言葉の使い方や文脈を理解し、新しい文章を生成できるAIモデルです。たとえば、質問に答えたり、記事を書いたり、テキストの翻訳を行ったりすることができます。

### 特徴

- **広範な知識**: インターネット上の膨大な文章データを学習しているため、様々なトピックに関する知識を持っています。
- **自然な文章生成**: 人間が書いたような自然な文章を生成する能力があります。
- **多用途**: チャットボット、翻訳、文章生成など、幅広い用途に利用されています。

## LLMのアーキテクチャ

大規模言語モデルの中核を担う技術は「トランスフォーマー」と呼ばれるものです。このトランスフォーマーは、文章中の単語同士の関係を理解し、次に来る単語を予測することで、文全体を理解・生成します。

### トランスフォーマーとは？

トランスフォーマーは、AIがテキストを学習するために使うモデルで、以下のような特徴があります。

- **自己注意機構**: テキスト内のどの単語が重要かを判断し、文脈に応じて適切な単語を選びます。
- **エンコーダーとデコーダー**: エンコーダーが入力文を理解し、デコーダーがその理解を基に新しい文を生成します。

このアーキテクチャのおかげで、LLMは長い文脈を理解し、複雑な文章を生成できるようになっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/4c404d77-42c8-9de2-89f1-9afb07ae177d.png)

単語の予測のイメージは以下となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/62e40800-e8b5-7a32-e103-c229fb695d56.png)

## 生成AIとの違い

生成AI（Generative AI）は、何か新しいものを生成するAIの総称です。その中には、大規模言語モデルを用いてテキストを生成するものも含まれますが、生成AIには他にも画像や音声を生成するAIが含まれます。

### 違いのポイント

- **LLM**: 主にテキストデータを学習し、文章を生成するモデル。言語処理に特化しています。
- **生成AI**: テキスト以外にも、画像、音声、映像などを生成するAI。創造的なコンテンツを生成するために使われます。

つまり、LLMは生成AIの一部であり、言語に関する特定のタスクに特化しているのが特徴です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1062357/c2a0c0c4-61f1-8f8d-5ddd-2801577dc0e9.png)

## まとめ

大規模言語モデル（LLM）は、膨大な量のテキストデータを学習することで、自然な文章生成や対話ができる高度なAI技術です。トランスフォーマーと呼ばれるアーキテクチャを基にしており、生成AIの一部として、テキストに特化した役割を担っています。今後もLLMは進化を続け、私たちの日常生活やビジネスにおいてますます重要な存在となるでしょう。
『プログラミングの基礎』第5章 条件分岐

# 条件分岐
OCamlにおいて条件分岐は以下のように記述する。
 ```OCaml:条件分岐
 if 条件 then 式 else 式
 ```

 # コード例
 #### 例① 入力される実数 x の絶対値を計算する
 ```OCaml
 (* 目的：入力される実数 x の絶対値を計算する *)
let abs_value x =
  if x > 0.0 then x 
             else -. x;;
```
実行例と実行結果は以下のようになる。
 ```OCaml
# abs_value (-2.0) ;;
- : float = 2.

# abs_value 1.5 ;;
- : float = 1.5
```
#### 例② 入力される時刻 x が午前か午後を判定する
```OCaml
(* 目的：入力される時刻 x に応じて午前か午後を出力する *)
let am_or_pm x =
  if x < 12 then "午前"
            else "午後";;
```
実行例と実行結果は以下のようになる。
```OCaml
# am_or_pm 9 ;;
- : string = "午前"

# am_or_pm 15 ;;
- : string = "午後"
```
Thumbs.dbを右クリックで削除する

画像が入っているフォルダを削除しようとして、このような画面が表示されたことはありませんか？
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/073317b1-1628-7bf8-c1de-0f72ecd7fbd2.png)

何やら脅されてきますが、フォルダを削除したいので「はい」を押します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/62a5966c-8fd4-7c15-a080-46cf04f7116b.png)

このように表示され、フォルダが削除できない思いをしたことがある人は多いのではないでしょうか？
他の画像ファイルは綺麗に削除されてしまっているので、下記のようなThumbs.dbだけが残るフォルダが出来上がります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/556091/1963520f-4ec9-44c1-efc9-dec48dc266e4.png)


この忌々しきThumbs.dbを右クリックで簡単に削除できるレジストリ設定ファイルを作成しました。

## ThumbsCleaner
下記リポジトリから`install-thumbs-cleaner.reg`を取得するか、下記内容の`.reg`ファイルを作成し、実行してください。

https://github.com/Basio0916/thumbs-cleaner

```
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\dbfile\shell\ThumbsCleaner]
@="Delete Thumbs.db"

[HKEY_CLASSES_ROOT\dbfile\shell\ThumbsCleaner\command]
@="cmd.exe /c del /q /a:h \"%1\""

[HKEY_CLASSES_ROOT\dbfile\shell\ThumbsCleaner\InProcServer32]
@=""

[HKEY_CLASSES_ROOT\Directory\shell\ThumbsCleaner]
@="Delete Thumbs.db Recursively"

[HKEY_CLASSES_ROOT\Directory\shell\ThumbsCleaner\command]
@="cmd.exe /c del /s /q /ah \"%1\\Thumbs.db\""

[HKEY_CLASSES_ROOT\Directory\background\shell\ThumbsCleaner]
@="Delete Thumbs.db Recursively"

[HKEY_CLASSES_ROOT\Directory\background\shell\ThumbsCleaner\command]
@="cmd.exe /c del /s /q /ah \"%V\\Thumbs.db\""

```

すると、Thumbs.dbを右クリックすると「Delete Thumbs.db」が表示されるようになるので、これをクリックするとThumbs.dbが削除できます。
また、フォルダやエクスプローラーの空いている場所を右クリックすると「Delete Thumbs.db Recursively」が表示され、そのフォルダ配下のThumbs.dbを再帰的に削除することができます。

## まとめ
Thumbs.dbを右クリックから削除できるようにするレジストリ設定ファイルを作成しました。
役に立てば幸いです。
Raspberry Pi で Gem sqlite3 をインストールしようとするとエラーになる

## 問題

Raspberry Pi で [sqlite3](https://github.com/sparklemotion/sqlite3-ruby) を bundle install し、いざ使用しようとすると以下のエラーが発生する。

```
cannot load such file -- sqlite3/sqlite3_native (LoadError)
```

## 解決方法

コンパイル済みのものをインストールするのではなく、自分でコンパイルするようにする。

```shell-session
$ bundle config set force_ruby_platform true
```

## バージョン情報

```shell-session
$ cat /proc/cpuinfo | sed -n -e 's/Model\s*:\s*\(\w\+\)/\1/p'
Raspberry Pi 3 Model B Rev 1.2

$ cat /etc/debian_version
10.13

$ ruby -v
ruby 3.3.4 (2024-07-09 revision be1089c8ec) [armv7l-linux-eabihf]
```
App ServiceでAzure Open AIをキーなしで実行する方法

# 概要
ユーザー割り当てマネージドIDを使用して、認証トークンを取得し、App Serviceで利用する方法

# App Serviceの設定
1. 新規にユーザー割り当てマネージドID作成
1. ポータルでOpenAIのリソースへ移動し、1.のIDに「Cognitive Services OpenAI User」を付与
1. ポータルでApp Serviceのリソースへ移動し、「設定」>「ID」>「ユーザー割り当て済み」タブから1.のIDを設定
1. App Serviceの「設定」>「環境変数」にて、あらかじめコードで設定しておいたCLIENT_ID=[1.のID]のとして設定
1. 他環境変数についても設定する

 
# コード側の設定

```python
from openai import AzureOpenAI
from azure.identity import ManagedIdentityCredential, get_bearer_token_provider 

# Azure OpenAI設定
endpoint = os.getenv("AZURE_OPENAI_ENDPOINT")
api_version = os.getenv("AZURE_OPENAI_API_VERSION")

# デプロイ名　※モデル名ではない​
deployment_name = os.getenv("AZURE_OPENAI_DEPLOYMENT_NAME"

# ユーザー割り当てマネージドIDのクライアントID​
client_id=os.getenv("CLIENT_ID")

def send_openai_request(system_prompt, chat_prompt, temperature):
    token_provider = get_bearer_token_provider(
        ManagedIdentityCredential(client_id=client_id),
        "https://cognitiveservices.azure.com/.default"
    )
    client = AzureOpenAI(
        azure_ad_token_provider=token_provider,
        azure_endpoint=endpoint,
        api_version=api_version,
    )
    
    try:
        response = client.chat.completions.create(
            model=deployment_name,
            messages=[
                {"role": "system", "content": system_prompt},
                {"role": "user", "content": chat_prompt}
            ],
            max_tokens=5000,
            temperature=temperature
        )
        
        return response.choices[0].message.content
    except Exception as e:
        print(f"エラーが発生しました: {e}")
        return None
```