OmniAICreator/Qiita-1.07M huggingface dataset:
Git sync使用検討結果

# はじめに

2023年のRe:inventにて登場したgit sync。CloudFormationとスムーズな接続ができる魅力的な機能です。社内の開発で導入しようと思いましたが、先輩方と相談しながら検討した結果、要件に合わず導入を諦めることになりましたので、その理由を記載したいと思います。

↓ Git Sync追加のアナウンス

https://aws.amazon.com/jp/about-aws/whats-new/2023/11/aws-cloudformation-git-management-stacks/

## Git Syncとは
GitHub、GitHub Enterprise、GitLab、BitbucketからCloudFormationに接続できる仕組み。

> テンプレートまたはデプロイファイルへの変更をコミットすると、CloudFormation はスタックを自動的に更新します。これにより、プルリクエストとバージョントラッキングを使用して、一元化された場所から CloudFormation スタックの設定、デプロイ、更新を行うことができます。


https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/git-sync.html


## 検討から諦めまで
今回Git Syncの導入を検討していたのは、GitHubで管理しているIAMリソースを複数のAWSアカウントに展開する自動デプロイの開発です。

### Git Sync → CloudFormation StackSets
具体的には、GitHubで管理しているIAMのコードが更新されたら、CloudFormation StackSets（以下、StackSets）で複数のアカウントに展開するというアーキテクチャの中で使用を検討していました。
しかし、2024年6月20日現在、Git Syncは、Gitから直接StackSetsへは接続できないことが分かりました。

### Git Sync → CloudFormationスタック → CloudFormation StackSets
ただ、Git SyncとStackSetsの間に、StackSets用のCloudFormationスタックを作ることで、Git Syncの利用は可能とのことでした。

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-stackset.html

しかし、それだと、StackSetsを作るCloudFormationスタック用のCloudFormationテンプレートと、そのテンプレートを置くS3バケット[^1]が必要になります。そして、そのS3に置くテンプレートもGitHub管理であれば、GitHub Actionsが必要になります。このように、Git Syncを実現するために、もう一つGitの接続が必要という、やや無理やりな実現方法になってしまいます。

https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-cloudformation-stackset.html#cfn-cloudformation-stackset-templateurl

[^1]:S3バケットではなく直接TemplateBodyを指定しても良いのですが、使用したいテンプレートが制限である51200文字を超えていたので、弊社のケースではできなそうでした。

### 各AWSアカウントにGit Syncする

それを受けて、IAMを展開したい複数のアカウントそれぞれにCloudFormationスタックとGit Syncを作るのはどうかという案が出ました。しかし、その案には2つの懸念点がありました。

#### ①新AWSアカウントを作成するたびに、git syncを作成する必要がある
定期的にAWSアカウントが増加する弊社には作業コストが高いと考えました。

#### ②git syncの成功を各アカウントで管理しなくてはいけない
この案だと、git syncの成功はデプロイ先の各アカウントを見に行かないと確認できません。複数アカウントへのデプロイの結果確認を一元的に行いたい場合、他のサービスを使わなければならず、不便だと考えました。

### 最終的には？
セキュリティと管理リソースの少なさを鑑みて、GitHub → CodePipeline → StackSets となりました。

https://docs.aws.amazon.com/ja_jp/codepipeline/latest/userguide/connections-github.html

### Git Syncはどういう要件に合う？
以上の検討を経て、今現在のGit Syncは以下の要件に合うのでは？と思います

- GitとCloudFormationスタック1対1の接続
- 複数のアカウントの場合
    - 基本は他の手段のほうがいい
        - 各アカウントでそれぞれgit syncを接続しても、git syncの実行結果を一元的に確認できないので不便。
    - 各アカウントにそれぞれ接続でOK or 複数アカウントの数が少なく、増加の予定もない、などならありかもしれない？


以上です。ありがとうございました。
GitHubで個人アクセストークンを発行する方法

## はじめに
GitHubの個人アクセストークン（Personal Access Token、以下PAT）は、APIやCLIツールを使ってGitHubのリポジトリにアクセスする際に必要となる重要な認証手段です。この記事では、GitHubで個人アクセストークンを発行する手順と設定方法について説明します。

## 1. 個人アクセストークンとは

個人アクセストークンは、GitHubアカウントのユーザー名とパスワードの代わりに使用することができる認証トークンです。これにより、API呼び出しや、Gitコマンドの実行時にセキュアにアクセスすることができます。
例えば、VertexAIワークベンチのコード管理やlookerのモデル管理をしたい場合に使用します。

## 2. 個人アクセストークンの用途

個人アクセストークンは、以下のような用途に使用されます：
- GitHub APIの認証
- Gitコマンドでリポジトリにアクセスするため
- CI/CDパイプラインでの自動化ツールによる認証
- その他のツールやサービスがGitHubリポジトリにアクセスする際の認証

## 3. 個人アクセストークンを発行する手順

1. **GitHubにログイン**：GitHubのアカウントにログインします。
2. **設定ページに移動**：右上のプロフィールアイコンをクリックし、`Settings`を選択します。
3. **Developer settings**：左側のメニューから`Developer settings`を選択します。
![スクリーンショット 2024-06-20 15.35.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/6f6329e0-2687-d7ca-942f-c546e802e048.png)

4. **Personal access tokens**：`Personal access tokens`をクリックし、`Tokens (classic)`を選択します。
![スクリーンショット 2024-06-20 15.34.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/2d5eca97-a07f-a554-cdc1-2c36c3aa7dbc.png)

5. **新しいトークンを生成**：`Generate new token`ボタンをクリックします。
![スクリーンショット 2024-06-20 15.37.06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/5d51aa31-f369-c05b-b886-0a09e078d641.png)

6. **トークンの設定**：トークンに名前を付け、有効期限とスコープを設定します（以下で詳細説明）。

## 4. トークンの設定項目

### 有効期限（Expiration）

トークンの有効期限を設定します。デフォルトは30日間です。有効期限が過ぎるとトークンは無効になります。例えば、「The token will expire on Sat, Jul 20 2024」と表示される場合、その日付にトークンが無効になります。
![スクリーンショット 2024-06-20 15.33.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3364428/bc4641bb-63da-624f-df61-67834084aa6d.png)


### スコープ（Scopes）

スコープは、トークンがアクセスできるリソースと操作の範囲を定義します。以下に主要なスコープとその説明を示します：

- **repo**：プライベートリポジトリへの完全なアクセス
- **repo:status**：コミットステータスへのアクセス
- **public_repo**：パブリックリポジトリへのアクセス
- **repo:invite**：リポジトリ招待へのアクセス
- **workflow**：GitHub Actionsのワークフローの更新
- **write:packages**：パッケージのアップロード
- **read:packages**：パッケージのダウンロード
- **delete:packages**：パッケージの削除
- **admin:org**：組織とチームの完全な管理
- **write:org**：組織とチームメンバーシップの読み書き
- **read:org**：組織とチームメンバーシップの読み取り
- **gist**：Gistの作成
- **notifications**：通知へのアクセス
- **user**：ユーザーデータの更新
- **read:user**：ユーザープロファイルデータの読み取り
- **delete_repo**：リポジトリの削除

適切なスコープを選択し、トークンの使用目的に応じたアクセス権限を設定します。

## 5. トークンの管理とセキュリティ

- **安全な保管**：トークンはパスワードと同様に安全に保管します。第三者に漏れないように注意しましょう。
- **必要最小限の権限**：必要最低限のスコープだけを付与することでセキュリティリスクを軽減します。
- **定期的な更新**：定期的にトークンを更新し、不要なトークンは削除します。

## 6. まとめ

GitHubの個人アクセストークンは、リポジトリへのセキュアなアクセスを提供する便利なツールです。トークンを発行し、適切なスコープと有効期限を設定することで、効率的かつ安全にGitHubを利用することができます。トークンの管理とセキュリティにも十分注意しましょう。

このガイドが、GitHubで個人アクセストークンを発行する際の参考になれば幸いです。
改行したいところで　PHP_EOL (PHP End Of Line)

### 発見
コードを読んでいたら、テキストでも代数でもない何か（PHP_EOL）が echo されていたので、調べたところ『改行』を表す、定義済み定数だった。ので、忘備録。

### 使用例
```
<?php

echo "Hello, World!" . PHP_EOL;
echo "This is a new line." . PHP_EOL;

?>
```

### 利点
OSが違うと、改行コードの認識も変わります。
* Unix/Linus: \n (newline character の意味)
* Windows: \r\n (carriage return followed by a newline character の意味)
* クラシックなMac OS: \r (carriage return の意味)

`PHP_EOL` の使用は、プラットフォームに関わらずに改行を表すことが可能なので、コードがより便利に使えることになります。

違ったOSでのアウトプットを扱う場合は特に、`PHP_EOL`を使うのがベストプラクティスのようですね。

### 追記
#### 定義済み定数
https://www.php.net/manual/ja/reserved.constants.php

#### (魔法の定数??/英語のページ)
https://www.w3schools.com/php/php_magic_constants.asp

https://www.javatpoint.com/php-magic-constants
Flutterで分割QRコード

# はじめに
QRコードには分割QRコード（連結QRコード）という種類があり、それを判定するためにQRヘッダで読み取る必要があった。

分割QRコードの情報は通常QRコードに比べて少ないため、需要は少ない感じがした。
※画像などの分割せざるを得ない大きいデータを分割するのはまだ理解できるが、単体で読める前提の上限数十バイト程度の文字列を分割QRコードで実装する設計はバッドプラティクスだと思う。通常QRを普通に複数使って、それぞれにKeyをつけて判定させれば事足る。

# 結論
「qr_code_scanner 1.0.1」を採用することにした。
ヘッダ情報を含めたBinaryで取得が可能であるため。
最終更新は2年近く前だが、QR読み取り機能は枯れた技術なので問題ないでしょう。

「mobile_scanner 5.1.1」を試してみたが、ヘッダ情報を取得することができなかった。
Binaryは取得できるのだが、ヘッダが含まれていない本体データのみのBinaryだった。
更新が高頻度でされているので、そのうち取得できるように対応されるかもしれない。

ヘッダの先頭4bitが「0011」の場合、分割QRコードである。
その他の詳細は、参考リンクを参照してください。

# 参考リンク

## 分割QRコードについて
https://qiita.com/c-flat/items/3dd4ca512632ce97fdca

https://qiita.com/f_uto/items/319c76fa1807e3f70d63

https://zenn.dev/seya/articles/40b50f845bc136

## 実装

https://pub.dev/packages/qr_code_scanner

https://pub.dev/packages/mobile_scanner

https://blog.kinto-technologies.com/posts/2023-12-13-Factory-scan-qr-code-on-inspection-cerificate/

https://zenn.dev/seya/articles/6e15432cfe327d

https://zenn.dev/tko_kasai/articles/a6abcefb8e9a3f#2.mobile_scanner-947likes

https://qiita.com/phyblas/items/3b0be832cc3f6792e5e0
【PostgreSQL】メタコマンド〜\watch〜

## 初めに

Qiita Engineer Festa 2024に参加中。完走目指してます。
他のメタコマンドについては以下から読んでください。

[【PostgreSQL】メタコマンドを纏めていく](https://qiita.com/dai_chi/items/04f5339d54130f070671)

## \watchとは

> 中断するか問い合わせが失敗するまで、現在の問い合わせバッファを繰り返し（`\g`と同じように）実行します。 実行の間に指定秒数(デフォルトは2)の休止が入ります。 各問い合わせの結果には、`\pset title`の文字列（あれば）、問い合わせ開始時の時刻、および遅延間隔を含むヘッダとともに表示されます。
> 
> 
> 現在の問い合わせバッファが空の場合、最も最近に送信された問い合わせが再実行されます。
> 

[\watchについて](https://www.postgresql.jp/document/10/html/app-psql.html#:~:text=%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82-,%5Cwatch%20%5B%20seconds%20%5D,-%E4%B8%AD%E6%96%AD%E3%81%99%E3%82%8B%E3%81%8B)

## 試してみた

アクティブな接続状況を5秒ごとに更新しながら確認する

```sql
SELECT * FROM pg_stat_activity;
\watch 5
Thu 20 Jun 2024 06:28:28 AM UTC (every 5s)

-[ RECORD 1 ]----+------------------------------------------------------------------
datid            | 
datname          | 
pid              | 31
leader_pid       | 
usesysid         | 
usename          | 
application_name | 
client_addr      | 
client_hostname  | 
client_port      | 
backend_start    | 2024-06-20 06:26:19.653923+00
xact_start       | 
query_start      | 
state_change     | 
wait_event_type  | Activity
wait_event       | AutoVacuumMain
state            | 
backend_xid      | 
backend_xmin     | 
query_id         | 
query            | 
backend_type     | autovacuum launcher
-[ RECORD 2 ]----+------------------------------------------------------------------
datid            | 
datname          | 
pid              | 32
leader_pid       | 
usesysid         | 10
~~~~ 省略 ~~~~
```

Ctrl+cで中断できる

## まとめ

実務の中ではストリーミングレプリケーションの設定をしているときに同期ができているかの確認で利用していました。
あとは障害時にpg_stat_activityを流し続けていたりと活用シーンは割とあります。
[体験談] 短大から大学編入をした経験について ~ 短大を卒業してから現在

# はじめに
こんにちは，Umamusume22です．前回は編入学試験の体験談について書きました．今回は編入学試験が終わってからどう過ごしたか，就活でどう評価されたのかなどを書きます．

# 編入学試験が終わった後 (短大時代)
残りの短大生活では卒業研究と沢山の授業を履修していました．授業は世界史や電子回路などの一般科目と専門科目です．短大を卒業するのに必要な単位は既に取得済みでした．しかし，編入後の認定単位がどうなるか分からないため，とりあえず多くの授業を履修していました．ちなみに短大から初めて実績が生まれた大学に編入する予定でした．
卒業研究は正直大変でした．年末年始も学校に来ていました．解読が難しいソースコード(C++，Javaなど)と戦ったのは良い思い出です．また，研究の大変さを痛感しました．勉強の方が研究より楽だと思いました．この時期，ロボコンはやっていません．

# 編入後 (大学)
短大を卒業して大学の3年次に編入しました．単位認定数は72単位だったと思います．２年次の必須科目(フーリエ変換とか)は短大ではやっていなかったため，履修しなければなりませんでした．必須科目を一つでも落とすと留年確定なので必死で勉強していました．家に引きこもって勉強ばっかりしていました．何とか留年は免れましたが．編入して驚いたことはArduinoを使って実験する授業やPythonで画像処理などを行う授業が簡単に感じたことです．ソースコードを書くのが楽でした．恐らく短大で実践的な所が鍛えられて力がついたのだと思います．B1から入学していた場合はこんなにソースコードが書けなかったと思います．関数？オブジェクト指向？状態だったでしょう

# 現在
今は修士卒でメーカーに就職しました．今でも物理や数学などは少し苦手ですがラズパイを使って何か作ることやプログラミングは得意です．よく周りからプログラミングできるねと言われます．短大でかなりプログラミングの勉強をしてきた経験があったから伸びたのだと思います．

# 就活
就活の時，編入に関してマイナスな印象を持たれたことはありませんでした．どんな短大に行っていたのか，短大でどんなことをしていたのかなど逆に興味を持たれたと思います．

# 短大生活を振り返って
4年制大学に1年から入学していないので比較できませんが恐らく1年から入学しても私は何も取り組んでいなかったと思います．今ほどプログラミングもできなかったと思います．短大で２年間頑張った経験を持ったからこそプログラミンが得意になりました

# さいごに
編入学試験は認知度が低くて不確定要素が強いため，敬遠されがちだと思います．確かに私も周囲から反対されました．しかし，数３や物理を取得していない商業高校出身の方も国立大学に編入で合格しています．また，私が通っていた短大は進路が未確定でもさらに1年間無料で短大に通える制度がありました．(進路保証制度)
もし，大学受験に失敗して浪人するか悩んでいる高校生や浪人生は編入も一つの進路選択に知っていただけたら嬉しいです．
今回は記事の執筆をここまでにします．長い体験談でしたが読んでいただきありがとうございました．
diffコマンドのオプションと実行例をまとめてみた

## 背景
diffコマンドのオプション、意外と知らんな…。
調べてみよう。

## オプション一覧

|オプション|説明|
|---|---|
|-c|context形式で差分を表示
|-u|unified形式で差分を表示
|-y <br>--side-by-side|横並びで差分を表示
|-q <br>--brief|差分があれば、差分がある旨メッセージを出力<br>※差分は出ない<br> ※差分がなければ出力もなし
|-s|3差分があれば、差分を出力<br>無ければ、差分がない旨メッセージを出力
|-b|空白差分は無視
|-i <br>--ignore-case|大文字小文字の区別をしない
|--suppress-common-lines|共通行を表示しない<br> ※-yオプションと併用で効果あり
|-W <br>--width=${NUM}|表示幅を指定する <br>※-yオプションと併用で効果あり<br>(指定なし:130カラム)
|--color|色付きで差分表示する|


## ファイルの準備

``` text01.txt
$ cat text01.txt
aaa
bbb
ccc
ddd
eee
fff
```


```text02.txt
$ cat text02.txt
aa11a
bbb
ccc222
ddd
eee333
fff
```


## -c

```
$ diff -c text01.txt text02.txt
*** text01.txt  Wed Jun 19 14:35:42 2024
--- text02.txt  Wed Jun 19 14:36:04 2024
***************
*** 1,6 ****
! aaa
  bbb
! ccc
  ddd
! eee
  fff
--- 1,6 ----
! aa11a
  bbb
! ccc222
  ddd
! eee333
  fff
```

## -u

```
$ diff -u text01.txt text02.txt
--- text01.txt  2024-06-19 14:35:42
+++ text02.txt  2024-06-19 14:36:04
@@ -1,6 +1,6 @@
-aaa
+aa11a
 bbb
-ccc
+ccc222
 ddd
-eee
+eee333
 fff
```

## -y (もしくは--side-by-side)

```
$ diff -y text01.txt text02.txt
$ diff --side-by-side text01.txt text02.txt

aaa                             |       aa11a
bbb                                 bbb
ccc                             |       ccc222
ddd                                 ddd
eee                             |       eee333
fff                                 fff
```


## -q (もしくは-brief) 

```
$ diff -q text01.txt text02.txt

Files text01.txt and text02.txt differ
```

## -s

```差分あり.
$ diff -s text01.txt text02.txt

1c1
< aaa
---
> aa11a
3c3
< ccc
---
> ccc222
5c5
< eee
---
> eee333
```

```差分なし.
$ diff -s text01.txt text01_copy.txt

Files text01.txt and text01_copy.txt are identical
```


## -b

```
$ diff -b text01.txt text02.txt

1c1
< aaa
---
> aa11a
3c3
< ccc
---
> ccc222
5c5
< eee
---
> eee333

```

## -i (もしくは--ignore-case) 

text01.txtをベースに以下を作成(1, 3, 5行目だけ大文字にした)

```text01_uppercase.txt
AAA
bbb
CCC
ddd
EEE
fff
```

```
$ diff -i text01.txt text01_uppercase.txt
# (差分はないので結果なし)
# オプションがないと差分が出ます

```

## --suppress-common-lines

```
$ diff --suppress-common-lines text01.txt text02.txt

1c1
< aaa
---
> aa11a
3c3
< ccc
---
> ccc222
5c5
< eee
---
> eee333

```

## -W (もしくは--width=${NUM})

```
$ diff --side-by-side -W 100 text01_long.txt text02_long.txt
```

![スクリーンショット 2024-06-19 18.10.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/4bca9aed-3893-0fb5-6d25-76af11429dff.png)

```
$ diff --side-by-side -W 50 text01_long.txt text02_long.txt
```

![スクリーンショット 2024-06-19 18.10.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/5594e05b-7011-9b09-097d-9f574533ae1b.png)

```
$ diff --side-by-side -W 25 text01_long.txt text02_long.txt
```

![スクリーンショット 2024-06-19 18.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327773/6a9c92aa-00bb-22d8-16c7-40f9310a60b3.png)



## --color 

```
$ diff --color  text01.txt text02.txt
```
添付画像を参照


<hr>

こんな感じです

# 参考記事

https://qiita.com/aramasa_ash/items/c21909823b9083cdbf38
Dahua VTH / VTO + Asterisk + Scrypted でセキュアなインターホン環境を構築 Vol. 5

# あらすじ
ちょうど２年前、Dahua VTH / VTO + Asterisk + Homebridge でセキュアなインターホン環境を構築しようといろいろとやっていました。
しばらく運用をしていましたが、SIPクライアントで通話前に画像のプレビューができないことがネックになっていました。
最終的な目標はHome App上で通話することでしたが、当時の調査した範囲ではなく手段がみつけられず諦めていましたが時間も経過したため再調査をしました。

Homebridgeのプラグインでインターホンのストリーミング映像を表示させていた部分をScryptedを利用することで簡単に解消できました。

# Scryprtedとは
公式HP：https://www.scrypted.app/
Docs：https://docs.scrypted.app/

Scrypted は、ホームビデオの統合プラットフォームです。主に監視カメラの映像のインテグレーションを目的に作られていますが、デバイスのタイプを変更することで監視カメラにも対応ができます。
Homebrigeと同様にプラグイン方式で容易に機能追加が可能であり、Homekit/Google Home/Alexaとの連携やモーション検知、WebHook対応も簡単に行えます。


# 導入
今回はDocker上に導入を行いました。
インストールスクリプトが提供されているためそれをそのまま実行するだけでインストール可能でした。
途中Docker/Avahiのインストール要否を聞かれますので環境に合わせてご選択ください。

```shell
curl -s https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-scrypted-docker-compose.sh > ~/install-scrypted-docker-compose.sh 
sudo SERVICE_USER=$USER bash ~/install-scrypted-docker-compose.sh
rm ~/install-scrypted-docker-compose.sh
```

# 設定(Scrypted)

* 必要なプラグイン
Homekit
Amcrest
Webhook
OpenCV Motion Detection
Dummy Switch

後ほど詳細を記載
アプリへのフローの追加　理解できない

新しいことをやろうとヘルプを読むのですが、全く理解できません。日本語で書いてあっても分からないですね。

https://learn.microsoft.com/ja-jp/power-apps/maker/canvas-apps/using-logic-flows

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ae479033-4032-832f-01c8-339c2a4dabee.png)

ステップ7で作ったフローを選択するのは分かる。その後の数式バーで、選択した....

そもそも数式バーってどこにある？

もしかして、これかな？　ここにフロー名.Run(変数1,変数2,変数3)書くのだろうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/a3c21e1b-deb3-d61d-405d-91952ed83577.png)


ここに書いたらボタンをクリックするとメールが飛んできた

# タイマーもどこにあるか、さっぱり分かりません。

https://mitsunooon.hatenablog.com/entry/2020/02/23/154940


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2fc65d56-341c-cd74-c38e-ba68ee141ae6.png)

画面が全然ちがうな。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/e3e19399-c032-eb29-52c8-fe338368e2d3.png)

みんなすごいですよね。こんなに何がどこにあるかが全く分からないUIを使えるなんて...

30分かかってやっと出てきた。　このUIマジでムカつく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/c9f13814-ca3b-7600-0b9f-5c7ff7397af2.png)


# 複製をつくる


別名で保存すればいいらしいけど... やはり探すのが大変です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/29cf8283-8498-758b-b6b3-a982ca0769ef.png)

# 名前の変更

これも探した。　設定をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/20f6b659-69ae-2a45-5eab-f8a42099f22e.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/56ad45a3-5a73-5dc0-3973-40af65978405.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1abfedcf-5d34-5ce5-d5f1-4b036bd77e1f.png)

# Failed to create or join session (API: NewInstance)xhr error. Status: 504, response: 

まただな。　このシステムはまともに動いているんだろうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1b71e8ba-8f23-e36d-17e1-be7d738c66f5.png)



![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/47249ffe-dab2-d402-3b34-6d5c15ce0f7c.png)

2024/06/27現在、新規作成もできませんね。本当に使えない仕組みです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8e0944f4-fec2-881a-fad3-89f08e858af9.png)


これかな？

https://mypage.otsuka-shokai.co.jp/news/detail?linkBeforeScreenId=OMP20F0102S01P&oshiraseNo=0000004632
【flutter】サイドバーに動きをつけたい

こんにちは！
今回はサイドバーに動きをつけた内容を紹介します。

# 使用パッケージ

https://pub.dev/packages/hidden_drawer_menu/changelog

# 実装内容

![Qiita.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/4804d9fa-6153-a16e-4942-d2571d1d0417.gif)

# 実際のコード
```php
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: SimpleHiddenDrawer(
        menu: const InnerDrawerOne(),//サイドメニューの内容を定義
        screenSelectedBuilder: //メインのコンテンツをビルドするためのコールバック
            (position, controller) {
              Widget screenCurrent;

          switch (position) { //値に応じて、選択された画面を決定
            case 0:
              screenCurrent = const Newfile();//クラスを指定
              break;
            case 1:
              screenCurrent = DateSelect();//クラスを指定
              break;
            case 2:
              screenCurrent = const QiitaSample1();//クラスを指定
              break;
            default:
              screenCurrent = const Newfile(); // デフォルトのウィジェットを設定
              break;
          }

          return Scaffold(
            backgroundColor: Colors.yellow,
            appBar: AppBar(
              leading: IconButton(
                icon: const Icon(Icons.menu),
                onPressed: () {
                  controller.toggle();
                },
              ),
            ),
            body: screenCurrent,
          );
        },
      ),
    );
  }
}
```

参考サイト

https://www.flutter4u.com/drawer-menu-feature-with-animation-in-flutter/


# 終わり
今回の紹介は以上になります。
今回も読んでいただき、ありがとうございました。
Photoshop UXP Plugin 入門備忘録


# 概要

Photoshop 拡張において、そろそろ Adobe ExtendScript を卒業したく、最新の選択肢である UXP に辿り着く。
UXP 開発のファーストステップの備忘録を残す。

## 参考文献

- [UXP for Adobe Photoshop 公式リファレンス](https://developer.adobe.com/photoshop/uxp/2022/)
  - [Plugins Quickstart Guide](https://developer.adobe.com/photoshop/uxp/2022/guides/)
  - [Photoshop API](https://developer.adobe.com/photoshop/uxp/2022/ps_reference/)
  - [UXP API](https://developer.adobe.com/photoshop/uxp/2022/uxp-api/)
- QualiArts engineer blog Photoshop UXP への移行について
  - [前編](https://technote.qualiarts.jp/article/61/) 、 [後編](https://technote.qualiarts.jp/article/64/)
- [Photoshop UXP ことはじめ 環境構築
](https://qiita.com/yukad2/items/a8ea5c1727305ea499bd)


## 成果物

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308883/821b708a-b5c3-18b2-55b6-3f2756427c48.png)

複数選択したレイヤー（レイヤーマスク）を対象に移動、回転、スケールを一括で行うツール。

https://github.com/fo-ta/photoshop_sandbox/tree/main/uxpPlugins/multiLayerTransform/source

# 備忘録

## 言語

JavaScript + HTML + CSS
ExtendedScript と違い、モダンな Javascript が書ける。今回は使ってないが、フレームワークも使用可能な模様。
また、今回は触れないが [C++ と連携したハイブリッド Plugin](https://developer.adobe.com/photoshop/uxp/2022/guides/hybrid-plugins/) も作れる模様。

## 開発環境

任意の IDE + UXP Developer Tools (Debuger) の組み合わせですんなり構築できるのでハードルが低い。
Develpler Tools も Adobe Creative Cloud Desktop からインストールできる。

## API

API は発展途上期らしく、バージョン毎にわりと大きな更新が入っている模様。
今回は最初期のバージョンである 2022(23.5.5) を対象に成果物を作ったが、このバージョンはリファレンスに書かれているが使えい、あるいは使い方が最新と違う API が多く存在しており、ほとんどを `batchPlay` で実装した。

例）
- `Document.selection` が `undefined`
- `Document.createLayer` のレイヤーモードの指定方法が違う

### [BatchPlay](https://developer.adobe.com/photoshop/uxp/2022/ps_reference/media/batchplay/)

Photoshop 上のアクションからコマンドを生成することができる（UI上でコピーできる）。
コマンドは Object なので改造も可能。 Maya の Mel のような作り方ができるので実装がとても簡単。

```javascript
// example レイヤーを選択
const command = {
  _obj: "select",
  makeVisible: false,
  _target: [{
    _ref: "layer",
    _id: id
  }]
};
```

## 細かい Tips

### テーマ毎のカラー

PhotoShop はユーザーが UI テーマ (light, dark 等) を設定できるため、固定色を指定するとテーマによっては視認性が悪くなる。
あらかじめテーマ毎のカラーが用意されているので、それらを使うと良い。
```css
/* example */
.hoge {
  color: var(--uxp-host-text-color-secondary)
}
```

https://developer.adobe.com/photoshop/uxp/2022/guides/theme-awareness/


### sp-dropdown

```sp-dropdown is deprecated. Please use sp-picker instead.```
`sp-dropdown` を使用すると、非推奨だから `sp-picker` を使ってくれ、と注意される。
しかし、 sp-picker は少なくとも本環境下では正しく動作しない（選択したメニューが正しく表示されない）し[公式リファレンスにも sp-dropdown が記載されている](https://developer.adobe.com/photoshop/uxp/2022/uxp-api/reference-spectrum/Spectrum%20UXP%20Widgets/User%20Interface/sp-dropdown/)ので無視とする。


## 懸念点、要検証点

### Plugins の配布

Package した `.ccx` ファイルをダブルクリックでインストール、またはマーケットプレイスからインストールが主な導入方法らしい。
導入にユーザーアクションが必要なので、社内ツール配布はちょっと手間が掛かりそう。

# 最後に

まだ新しい仕組みということで痒いところに手が届ききらない印象はあるものの、 ExtendedScript に比べて開発環境は格段に便利になったし、これならどんどんプラグインを作りたい気持ちも湧いてきます。
今後の成長にも期待できるので、楽しみです。
artisanコマンドの作成

## **Laravelでカスタムコマンドの作成**

Laravelではカスタムコマンドを作成することで、繰り返し行うタスクを自動化することができます。これにより、開発者はより効率的に作業を進めることができます。

### コマンドの作成

以下のコマンドで、任意の名前でカスタムコマンドを作成できます。作成されたファイルは `app/Console/Commands` ディレクトリに配置されます。

```bash
php artisan make:command コマンド名

```

例：

```bash
php artisan make:command StudyCheckCommand

```

### コマンドの実行

作成したカスタムコマンドは、以下のコマンドで実行できます。

```bash
php artisan コマンド名

```

例：

```bash
php artisan study:check

```

### カスタムコマンドファイルのコード一部

以下はカスタムコマンドファイル (`app/Console/Commands/StudyCheckCommand.php`) の一部の例です：

```php
namespace App\Console\Commands;

use Illuminate\Console\Command;

class StudyCheckCommand extends Command
{
    // コマンドのシグネチャ
    protected $signature = 'study:check';

    // コマンドの説明
    protected $description = 'Check unnotified and unfulfilled requests and notify them via chat';

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        // コマンドの実行ロジックをここに記述
        $this->info('Study check executed successfully!');
        return 0;
    }
}

```

- `$signature`: コマンド実行時に使用するシグネチャ。例：`study:check`
- `$description`: `php artisan list` でコマンドの説明として表示される部分。

### コマンドのロジック

`handle` メソッド内にコマンドの実行ロジックを記述します。例えば、特定のデータをチェックして通知を送る処理などをここに実装します。

### Artisanコマンドの活用

カスタムコマンドは、スケジューリングと組み合わせることで定期的に実行させることもできます。例えば、`app/Console/Kernel.php` に以下のように記述します：

```php
protected function schedule(Schedule $schedule)
{
    $schedule->command('study:check')->daily();
}

```

この例では、`study:check` コマンドが毎日実行されるようにスケジュールされています。
pl.LightningModuleでWarmup Cosine Decay Schedulerをステップ単位で更新

pytorch-lightningの学習サイクルで，WarmupCosineLRSchedulerを使った学習率設定を紹介．
ここでは，エポック単位ではなくてステップ単位の更新を説明します．

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/691046/65bd30f0-c418-9265-99e5-7e17a584b3b2.png" width="50%">

## 準備
### timmのインストール
`timm`の`CosineLRScheduler`を使います．
[pytorch image models](https://github.com/huggingface/pytorch-image-models/tree/main)という画像認識用のライブラリです

```sh
pip install timm
```

timmのWarmup付き，CosineLRSchedulerクラス自体の使い方は次のサイトがわかりやすいです．

https://blog.shikoan.com/timm-cosine-lr-scheduler/



※lightning-boltパッケージにも，WarmupCosineLRReducerがありますがアップデートが全くされておらず，最新のlightningに対応していないので非推奨です． 

## 実装: pl.LightningModuleで使用

### Scheduler インスタンスの生成とステップ単位の更新

`pl.configure_optimizers`メソッドでschedulerのインスタンスを生成して，`pl.lr_scheduler_step`で`step`メソッドを呼び出すようにしたら完了です．

```py
from timm.scheduler import CosineLRScheduler

class MyLightningModule(pl.LightningModule):
    def __init__(self, model, num_epoch, exp_name) -> None:
        ...
        
        num_dataloader = len(dataloader) # 1epochあたりのバッチ数
        self.total_steps = num_epoch * num_dataloader # 合計step数
        self.current_step = 0

    def configure_optimizers(self):
        optimizer = torch.optim.AdamW(
            self.models, base_lr=1e-4
        )

        warmup_rate = 0.1
        warmup_t = int(self.total_steps * warmup_rate) # warmup step数
        scheduler = CosineLRScheduler(
            optimizer, t_initial=self.total_steps, warmup_t=warmup_t, warmup_prefix=True
        )
        return {
            "optimizer": optimizer,
            "lr_scheduler": {
                "scheduler": scheduler,
                "interval": "step",
                "frequency": 1,
            }
        }

    def lr_scheduler_step(self, scheduler, metric) -> None:
        self.current_step += 1
        scheduler.step(self.current_step)

    ...

```

設定している`CosineLRScheduler`の引数
- t_initial: 総ステップ数　（本来の意味は最初のサイクルのステップ数）
- warmup_t: warmupに使うstep数
- warmup_prefix: Trueなら，warmup終了時の学習率がOptimizerに設定した値になります

詳細はこちらから

https://timm.fast.ai/SGDR

また，返り値のdictではschedulerの更新タイミングや頻度を設定することができます．
```py
"lr_scheduler": {
    "scheduler": scheduler,
    "interval": "step",
    "frequency": 1,
}
```
今回はstep単位で学習率を更新したいため，`"interval": "step"`にします．デフォルトは`"epoch"`なので，この指定は必ず必要です．


最後に，`step`メソッドの呼び出しは，`LightningModule.lr_scheduler_step`をオーバーライドして実装します．（Pytorchの`LRScheduler`か`lightning-bolt`以外のSchedulerを使う場合はオーバーライドして`step`の処理を書く必要があります．）
この関数はschedulerの更新のタイミングで呼ばれるようになっています．

## 関連
#### schedulerについてはこちら

https://qiita.com/kma-jp/items/81db6d5c549e50707e30

#### LightningModuleとは

LighgningModuleでは， trainステップ， valステップを作成したり，学習におけるサイクルのhooksに任意の処理を追加するAPIが提供されています．
基本的な使い方はこちらの記事をどうぞ

https://qiita.com/ground0state/items/c1d705ca2ee329cdfae4
ZED SDK でROIを設定する  〜試行錯誤中〜


## 想定する読者
[stereolabs](https://www.stereolabs.com/)のzed2i, zed mini, zed x などのステレオカメラの利用者
いまどきのステレオカメラは何ができるのかを知りたい人

## 前提
ZED SDK 4.1
Ubuntu 20.04
ZED2i
Python 版のAPI


```
Camera.get_region_of_interest(self, Mat py_mat: Mat, resolution=Resolution(0, 0), module=MODULE.ALL) -> ERROR_CODE
Camera.get_region_of_interest_auto_detection_status(self) -> REGION_OF_INTEREST_AUTO_DETECTION_STATE
Camera.set_region_of_interest(self, Mat py_mat: Mat, modules=[MODULE.ALL]) -> ERROR_CODE
Camera.start_region_of_interest_auto_detection(self, roi_param=RegionOfInterestParameters()) -> ERROR_CODE
```

## 参考にすべきコード
https://github.com/stereolabs/zed-sdk/blob/master/depth%20sensing/automatic%20region%20of%20interest/python/automatic_region_of_interest.py

## trouble
### python 版
```
zed-sdk/depth sensing/automatic region of interest/python$ python3 automatic_region_of_interest.py 
[Sample] Using default resolution
[2024-06-20 09:32:21 UTC][ZED][INFO] Logging level INFO
[2024-06-20 09:32:22 UTC][ZED][INFO] Using USB input... Switched to default resolution HD720
[2024-06-20 09:32:22 UTC][ZED][INFO] [Init]  Depth mode: NEURAL
[2024-06-20 09:32:23 UTC][ZED][INFO] [Init]  Camera successfully opened.
[2024-06-20 09:32:23 UTC][ZED][INFO] [Init]  Camera FW version: 1523
[2024-06-20 09:32:23 UTC][ZED][INFO] [Init]  Video mode: HD720@60
[2024-06-20 09:32:23 UTC][ZED][INFO] [Init]  Serial Number: S/N 32045770
Press 'a' to apply the ROI
Press 'r' to reset the ROI
Press 's' to save the ROI as image file to reload it later
Press 'l' to load the ROI from an image file
Traceback (most recent call last):
  File "automatic_region_of_interest.py", line 173, in <module>
    main()
  File "automatic_region_of_interest.py", line 108, in main
    roi_param.auto_apply = True
AttributeError: 'pyzed.sl.RegionOfInterestParameters' object has no attribute 'auto_apply'
```

### C++ 版でも不具合

```
zed-sdk/depth sensing/automatic region of interest/cpp/build$ make
[ 50%] Building CXX object CMakeFiles/ZED_Auto_Sensing_ROI.dir/src/main.cpp.o
/home/waragai/github/zed-sdk/depth sensing/automatic region of interest/cpp/src/main.cpp: In function ‘int main(int, char**)’:
/home/waragai/github/zed-sdk/depth sensing/automatic region of interest/cpp/src/main.cpp:88:15: error: ‘struct sl::RegionOfInterestParameters’ has no member named ‘auto_apply’
   88 |     roi_param.auto_apply = true;
      |               ^~~~~~~~~~
make[2]: *** [CMakeFiles/ZED_Auto_Sensing_ROI.dir/build.make:76: CMakeFiles/ZED_Auto_Sensing_ROI.dir/src/main.cpp.o] Error 1
make[1]: *** [CMakeFiles/Makefile2:83: CMakeFiles/ZED_Auto_Sensing_ROI.dir/all] Error 2
make: *** [Makefile:91: all] Error 2
```

どちらとも、StereoLabsのコードなので、本家の対応待ちの状態である。
watsonx.data: Milvus接続情報の取得

watsonx.dataでベクトルデータベースMilvusを使えるようになりました。
[pymilvus](https://github.com/milvus-io/pymilvus)や[Attu](https://github.com/zilliztech/attu)から接続する際の、接続情報の取得方法について説明します。

IBM Cloudのwatsonx.data SaaS版で確認しています。

## 1. インフラストラクチャー・マネージャーを表示します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/84f094ca-9654-26e6-a2ef-5688c166b5c0.png)

## 2. 接続情報を取得したいMilvusエンジンのアイコンをクリックし、サービスの詳細を表示
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/3bd66284-7d57-6387-17bc-8982e38eab7c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/8775f27b-843d-e178-96b4-1aca1dd1b910.png)

## 3. 「GRPCホスト」の値をコピーアイコンをクリックしてクリップボードにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294516/acebed31-37f3-06ef-2c63-248c5a3b2e57.png)

全部表示されていないのですが以下のようなフォーマットになっています：
`xxxxx.xxxxx.xxxxx.xxxxx.xxxxx:30625`
- xxxxx.xxxxx.xxxxx.xxxxx.xxxxxの部分: ホスト名
- 数字の部分: ポート番号です

テキストエディタ等にペーストして、確認してください。

### [pymilvus](https://github.com/milvus-io/pymilvus)　で接続する場合
コピーした値を使用して
- **secure=True**
- host=`ホスト名`
- port=`ポート番号`

で指定してください。

参考までに、APIキーを利用したuseridとpaswordは以下になります:

- userid: ibmlhapikey
- pasword: APIキーの値

### [Attu](https://github.com/zilliztech/attu)で接続する場合

- Milvus Address: **https://**`ホスト名`:`ポート番号`

を指定してください。

APIキーを利用したuseridとpaswordは以下になります:
- userid: ibmlhapikey
- pasword: APIキーの値



以上です。
iOSにおける画面サイズとインターフェースのバリエーションを探る

### はじめに

iOSアプリ開発では、多様な画面サイズに対応する柔軟なインターフェース設計が重要です。

### 記事の目的

"wC", "wR", "hC"などの値に戸惑ったことはありませんか？この記事を読むと、Size Classの概念や、インターフェース設計での利用方法、そしてあらゆるデバイスで適応するユーザーインターフェースを作成するためのヒントを理解できるようになります。

### 概念

#### 1. Size Class

**Size Class**は、iOSで異なる画面サイズに対応するためのシステムです。画面サイズを次の2つの軸に分けて管理します：

- **横幅 (Width)**
- **縦幅 (Height)**

各軸には2つのタイプがあります：

- **Compact**: 小さいサイズ (例：縦向きのiPhone)
- **Regular**: 大きいサイズ (例：横向きのiPad)

例：横向きのiPadは、横幅と縦幅の両方がRegularなSize Classを持ちます。一方、縦向きのiPhoneは横幅がCompactで縦幅がRegularなSize Classを持ちます。

#### 2. Trait Variations

**Trait Variations**は、異なるSize Classesに基づいてユーザーインターフェースを調整するための機能です。各Size Classに特化した制約、サイズ、間隔、その他のビュー属性のバリエーションを作成できます。これにより、デバイスの種類や画面の向きに合わせてユーザーインターフェースを最適化できます。

参考資料によると、CompactとRegularの変換点は600ピクセルです。

### 使用方法

簡単な例で理解を深めましょう。Size Classを使って、iPhoneのデバイスが横向きか縦向きかでUILabelのテキストを変更してみます。

```swift
class ViewController: UIViewController {

    @IBOutlet weak var textLabel: UILabel! // Interface BuilderからUILabelへのIBOutlet接続

    override func viewDidLoad() {
        super.viewDidLoad()
        // 画面サイズに基づいてラベルのテキストを変更
        updateLabelForOrientation()
    }

    override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
        super.traitCollectionDidChange(previousTraitCollection)
        // 画面サイズが変わったときにラベルのテキストを更新
        updateLabelForOrientation()
    }

    func updateLabelForOrientation() {
        if traitCollection.verticalSizeClass == .compact && traitCollection.horizontalSizeClass == .regular {
            // デバイスが横向き
            textLabel.text = "Landscape Mode"
        } else if traitCollection.verticalSizeClass == .regular && traitCollection.horizontalSizeClass == .compact {
            // デバイスが縦向き
            textLabel.text = "Portrait Mode"
        }
    }
}
```

上記のコードでは、`updateLabelForOrientation()`関数で：

- **縦向き**: 縦軸（vertical）が大きいため`regular`、横軸（horizontal）は狭いため`compact`です。
- **横向き**: 縦軸（vertical）が狭いため`compact`、横軸（horizontal）は広いため`regular`です。

`traitCollection`のSize Classを確認し、デバイスが横向きか縦向きかを判断し、それに応じてUILabelのテキストを変更します。デバイスの向きを変えると、UILabelのテキストが自動的に更新されます。

### Interface Builderでの使用

記事の最初に挙げた略称を思い出してください。これらはSize Classの略です：

- **wC**: Width-Compact
- **wR**: Width-Regular
- **hC**: Height-Compact
- **hR**: Height-Regular

Interface BuilderでSize Classを利用するには、以下の手順で先ほどの例を再現します：

**ステップ 1**: Xcodeで新しいプロジェクトを作成し、Interface Builderで1つのラベルをViewにドラッグします。

**ステップ 2**: ラベルのテキストを属性テキストに変更します。

**ステップ 3**: Size Classesの制約を作成します：
- 「+」ボタンを選択し、各値を選択して「Add Variation」ボタンをクリックします。
  - **縦向き**：
    - 縦軸 (vertical): regular
    - 横軸 (horizontal): compact
  - **横向き**：
    - 縦軸 (vertical): compact
    - 横軸 (horizontal): regular

設定後の制約：

アプリをビルドして結果を確認しましょう。

### 結論

Size Classは、様々なiOSデバイスに適応する柔軟なインターフェースを作成するための強力なツールです。Size Classを理解し適切に使用することで、ユーザーフレンドリーなアプリを開発できます。現在のプロジェクトにSize Classを適用してみて、Auto LayoutやTrait Variationsについてさらに学びましょう。Size Classの使用でお困りの際は、コメント欄に質問を残していただければお答えします！
railsでdistinctとin_batchesを同時に利用するのはアンチパターン

# 背景
railsでdistinctとin_batchesを同時に利用すると、正しい値が取得できなかったので解説する

# 内容
`User.select(:user_id).distinct.in_batches(of: 2) { p _1.pluck(:id)}` の挙動について

usersテーブルに1~5のidを持つレコードが格納されているとした時、

```
[1,2]
[3,4]
[5]
```

と出力されると期待していたが

```
[1,3]
[1,2]
[4,5]
```

のように値が重複して出力されてしまった

`User.select(:user_id).distinct.in_batches(of: 2) { p _1.pluck(:id)}` の挙動について

ChatGPTに確認したところ、
> ActiveRecordでdistinctを使用して一意なレコードを取得した後にin_batchesを使用すると、クエリの処理方法によっては重複した値が含まれる場合があります。これは、in_batchesがページング処理を行う際にdistinctが適用される前の段階で重複が発生することが原因です。

ということだったので、

```
User.select(:id).distinct.offset(offset).limit(batch_size).pluck(:user_id)
```

のように書き直しました


# 結論
distinctを使用する場合は、limit, offsetを使いましょう
GeminiのAPIがタダなので論文を自動で要約

GeminiのAPIがタダなので、論文をたくさんダウンロードしてスクリプトを回しておけば、事前に設定したプロンプトで論文の内容を説明してくれるやつをやりました。

https://github.com/shogo-d-nakamura/gemini_auto_summarize

自分はmain.pyのpath/to/pdfにwindowsのCドライブのDownloadsまでのパスを入れていて、ネットサーフィンしてダウンロードした論文たちをDownloads配下のフォルダにまとめて --batch [dir_name]を指定して、帰る前にmain.pyしています。

"path/to/pdf" -> "/mnt/c/Users/username/Downloads/"
論文をダウンロードするときにDownloadsがデフォルトになっているのでここにしています。

/mnt/c/Users/username/Downloads/article.pdfを説明させるときは
```
python main.py -i article.pdf
```

複数のpdfをbatchという名前のフォルダに入れて/mnt/c/Users/username/Downloads/batch/の中のpdfを全て説明させるときは
```
python main.py -b batch
```
みたいな感じです。

Gemini 1.5 proは2 rpmと書いていますがtime.sleep()を適当に挟んでもなぜかrate limitのエラーが出るので基本Gemini Flashの方しか使っていません。が、一応-pを入れれば最新版の1.5 proを指定できるようにしています。
トレイトについて

PHPではクラスの多重継承はできない。
例えば、クラスTestAとクラスTestBを作成してそれら二つを継承するクラスTestCを書くとする。

```php
<?php
class TestC extends TestA,TestB {
...
}
?>
```

これはエラーになる。

しかしPHP5.4から**トレイト**という仕組みができたらしい

クラスをトレイトに置き換えることで多重継承ができるようになる。

TestAとTestBのクラスをトレイトに置きかえ、TestCで多重継承してみる。

```php
<?php
trait TestA
{
  function get_text1()
  {
  echo "トレイトTestA：get_text1メソッド　コール成功！<br>";
  }
}
 
trait TestB
{
  function get_text2()
  {
  echo "トレイトTestB：get_text2メソッド　コール成功！<br>";
  }
}
 
class TestC
{
  use TestA,TestB; //多重継承
  function get_text3()
  {
  echo "クラスTestC：get_text3メソッド　コール成功！";
  }
}
```

【解説】
クラスTestCのように、トレイトを使った多重継承をする場合はuseを使ってカンマ区切りで追加していきます。

TestCのインスタンスを生成して継承元のメソッドをコールしてみる。

```php
$display = new TestC();
$display->get_text1();
$display->get_text2();
$display->get_text3();
```


継承元のトレイトTestAのメソッドとトレイトTestBのメソッドを呼び出すことができた。
→多重継承は成功。

【注意】
トレイト自体のインスタンスは出来ない。
つまりトレイトTestAやトレイトTestBを単独で使用することは出来ない。

# **Laravelでの使用例**

---

CommonModelというモデルを作成し共通処理を記述。

各モデル（TestModel1.php、TestModel2.php）はCommonModelを継承する場合

```php
common.php

<?php
 
trait CommonModel {
 
  // 共通処理
 
}
```

```php
TestModel1.php

class TestModel1 extends Eloquent {
 
  use CommonModel;
 
}
```

```php
TestModel2.php

class TestModel2 extends Eloquent {
 
  use CommonModel;
 
}
```

このようにトレイトを使うことで多重継承ができる。そのため、CommonModel.phpのクラスに依存しなくても済むようになる。
リレーションって何

# **Laravelのリレーション**

Laravelのリレーションはモデルに書くことで定義するらしい
・1対1
・1対多
・多対多
パターンはこの3種くらいか。

## 1対1

```php
public function ○○○○○(){
return $this->hasOne('App\Models\○○○○○');
}
```

```php
public function □□□□□(){
return $this->belongsTo('App\Models\□□□□□');
}
```

## **1対多**

```php
public function ○○○○○(){
return $this->hasMany('App\Models\○○○○○');
}
```

```php
public function □□□□□(){
return $this->belongsTo('App\Models\□□□□□');
}
```

## 多対多

```php
Public function roles()
{
    return $this->belognsToMany(Role::class);
}
```

```php
return $this->belongsToMany(Role::class, 'role_user', 'user_id', 'role_id')
```

---
↓このあたりを使い分けるっぽい
hasOne
belongsTo
hasMany
belognsToMany