OmniAICreator/Qiita-1.07M huggingface dataset:
SwiftLintをSPMで導入・設定する（Xcode ビルド時）

## 環境

Xcode 15.4
MacOS Sonoma 14.2

## 手順

1. SPMでSwiftLintを入れる
1. Build Pahasesに追加する
1. `.swiftlint.yml`をプロジェクトに追加する
1. 確認する

### 1.SPMでSwiftLintを入れる

<img width="600" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281147/21ac2575-7504-5568-0d00-9d58376ab680.png">

<img width="500" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281147/e6e49817-1cde-39e4-8a74-e6af830db49e.png">

`https://github.com/SimplyDanny/SwiftLintPlugins`を追加する

### 2.Build Pahasesに追加する

<img width="600" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281147/0393e29e-e9b3-d095-565c-f97cf270eb4a.png">

<img width="300" alt="スクリーンショット" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281147/435c4968-8ac0-6f89-2307-82ba0f4fd2a3.png">


### 3.`.swiftlint.yml`をプロジェクトに追加する

プロジェクト配下に`.swiftlint.yml`を追加し、お好みのルールを追加しましょう！
ルールについては SwiftLintのGitHubや以下を参考にしましょう
https://realm.github.io/SwiftLint/rule-directory.html

### 4.確認する

ちゃんと怒られました！

![スクリーンショット 2024-07-28 1.18.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281147/dfa6070b-901c-5ea8-fc50-b20b512426b4.png)

## 遭遇した問題

`SourceKittenFramework/library_wrapper.swift:31: Fatal error`のようなエラーが出ましたが、以下の内容で解決しました。

https://github.com/realm/SwiftLint/issues/4602

https://github.com/realm/SwiftLint/issues/1466#issuecomment-297265863

## 参考

https://github.com/realm/SwiftLint

https://qiita.com/naginx/items/92a647a76df6c3688302

## あとがき

結構楽々設定ですね！
iOSの情報は中々出てこなかったり、あってもアップデートに追いついてなかったりするため自分は結構苦労しました。
どなたかのお力となれば...!
参考になったなどよろしければいいねを下さい！モチベが上がります！
間違いや、激励、気になってるiOS開発のトピックがあればコメントお願いします。
OpenAIクレジット2500ドルの最適な活用法：アイデアと可能性を探る

## はじめに

OpenAIのAPI利用クレジット2500ドルを手に入れたとき、どのように活用すれば最大の効果が得られるでしょうか？本記事では、Reddit上で議論された様々なアイデアを紹介しながら、OpenAIのクレジットを効果的に使用する方法について探ります。

## 合成データの生成

### プロンプトとタグの生成

最も人気のあった提案の一つは、合成データの生成でした。特に、生のデータに対するプロンプトやタグの生成が注目を集めています。

> **解説**：合成データとは、実際のデータを模倣して人工的に作成されたデータのことです。これは、機械学習モデルのトレーニングやテストに使用され、実データの不足を補ったり、プライバシーの問題を回避したりするのに役立ちます。

### 画像キャプションデータセットの作成

画像キャプションのデータセット作成も興味深い提案でした。特に、既存のモデル（例：Llava）の奇妙な表現を修正するような会話型データセットの生成が提案されています。

> **注意点**：OpenAIの利用規約に違反する可能性がある使用方法もありますので、実際に使用する際は規約を確認し、適切に利用することが重要です。

## エンベディングの作成

多くの文書に対してエンベディングを作成するという提案もありました。

> **解説**：エンベディングとは、テキストや画像などの複雑なデータを数値のベクトルに変換したものです。これにより、機械学習モデルがデータを効率的に処理できるようになります。大量の文書のエンベディングを作成することで、高度な検索システムや推薦システムの構築が可能になります。

## モデルのファインチューニング

既存のモデルを特定のタスクや領域に特化させるファインチューニングも、クレジットの有効な使用方法の一つです。

### 小説の続編生成

例えば、人気小説シリーズの未発表の続編を生成するためのモデルをファインチューニングする案が提案されています。

> **解説**：ファインチューニングとは、事前学習済みの大規模言語モデルを、特定のタスクや領域のデータを使って追加学習させることです。これにより、モデルの性能を特定の用途に最適化することができます。

## 実用的なアプリケーションの開発

### コーディングアシスタント

AWS Bedrockを使用してClaude 3.5 SonnetのAPIを利用し、Jetbrainとの連携でコーディングアシスタントを作成するという実例も紹介されています。

### レシピ生成

AIを使用して新しい料理レシピを生成するというアイデアも提案されています。

## ビジネス向けソリューションの開発

### RPA（Robotic Process Automation）エージェントの構築

Edgechainsを使用してRPAエージェントを構築し、オフィスでの自動化を実現する提案がありました。これにより、企業のコスト削減の可能性を示すことができます。

> **解説**：RPAとは、ビジネスプロセスを自動化するテクノロジーです。人間が行う反復的な作業をソフトウェアロボットが代行することで、業務効率を大幅に向上させることができます。

## 研究と教育

### 学生向け学習支援ツール

過去の試験問題を分析し、傾向に基づいて新しい問題を生成する学習支援ツールの開発という具体的な使用例も紹介されています。

## まとめ

OpenAIのAPIクレジットは、データ生成、モデルのファインチューニング、実用的なアプリケーション開発など、様々な用途に活用できます。重要なのは、自分のプロジェクトや目的に合わせて最適な使用方法を選択することです。また、常にOpenAIの利用規約を遵守し、倫理的に適切な方法で利用することを忘れないでください。

クレジットの有効活用は、AIテクノロジーの可能性を探求し、革新的なソリューションを生み出す素晴らしい機会となるでしょう。

## 参考サイト

https://www.reddit.com/r/LocalLLaMA/comments/1ed9nt6/2500_openai_credits_possible_use_cases/
JavaScriptからRubyへ：初心者が感じた違いと学び

# JavaScriptからRubyへ：初心者が感じた違いと学び

JavaScriptとRubyは、どちらも人気の高いプログラミング言語ですが、その書き方や使用方法には多くの違いがあります。JavaScriptからRubyを学び始めた初心者として、感じた違いや学びを共有したいと思います。

#### 1. 文法の違い
JavaScriptは、セミコロンでステートメントを区切ります。また、{}を使ってブロックを定義します。対して、Rubyはよりシンプルで、endを使ってブロックを終了します。この違いにより、Rubyのコードは読みやすくなっています。

#### 2. 標準ライブラリとフレームワーク
JavaScriptには豊富なフレームワーク（React, Angular, Vueなど）が存在しますが、Rubyには特にWeb開発に強力なフレームワークであるRailsが存在します。


# JavaScriptエンジニアがRubyを学んで驚いたポイント４選
JavaScriptエンジニアとしての経験を持つ私が、Rubyを学び始めて驚いたポイントを10選紹介します。

#### 文法の簡潔さ
Rubyの文法は非常に簡潔で読みやすく、書いていて楽しいと感じました。特にブロックの定義方法や、セミコロンが不要な点が新鮮でした。

#### 全てがオブジェクト
Rubyでは、全てがオブジェクトとして扱われます。これはJavaScriptでも同様ですが、Rubyの方がより厳密にオブジェクト指向が貫かれている印象です。

#### ブロックとイテレータ
Rubyのブロックやイテレータは強力で、コードの可読性と再利用性を高めてくれます。eachメソッドやブロック付きメソッドが特に便利です。

#### コミュニティの温かさ
Rubyが日本人によって作られた言語なこともあり、コミュニティや本が多く、初心者に対するサポートも充実しています。ドキュメントやチュートリアルが豊富で、学習がしやすい環境が整っています。

# JavaScriptとRuby：どちらを学ぶべきか？

##### フロントエンド開発:
JavaScriptはブラウザ上で動作する唯一の言語であり、ReactやVue.jsなどのフレームワークを使用して、インタラクティブなウェブアプリケーションを開発するのに適しています。
##### バックエンド開発:
RubyはRailsを使ったサーバーサイド開発に強みがあります。ただ、最近ではバックエンドエンジニアもJavaScriptを学ぶことが多くなっています。


読んでいただき、ありがとうございました！
入茶報告

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847324/f20dabfc-a6b0-c508-1815-f6f3ce527663.png)
# 誰
37歳
非IT系事務職
大学理学部中退
# いつ
2024 7/27 ABC364
2024 5/25 ABC355が初参加なので、丸2か月で参加10回目
# なぜ
2024 1/7からIPAの情報処理技術者試験を受け始める
(始めた理由は特になし、教材は全てUdemy)
IP→FE→SG→APで試験は一区切り(全部受かったので次はSCを受ける予定)
手持無沙汰になったので知識定着を兼ねてプログラミングでも始めようとpaizaに登録
言語は流行っているらしいpythonを選択
10日かけてBランクで満足しAtcorderに登録

# 何を
とりあえず

https://qiita.com/drken/items/fd4e5e3630d0f5859067

を読んでコンテスト参加開始、この時点で過去問精選7問目までは解ける状態
エディタはhttps://paiza.io/ja

参加した結果C問題がさっぱり解けず、どうやら勉強が必要らしい
ここから試行錯誤期間

https://atcoder.jp/contests/math-and-algorithm

練習問題集だと思って途中まで取り組んだ
どうやら書籍が先にあってその演習問題だったらしい

https://qiita.com/e869120/items/f1c6f98364d1443148b3

その書籍の著者の記事
とりあえずAOJは全部解いた

https://qiita.com/drken/items/56a6b68edef8fc605821

典型的な問題に対する典型的な解法（アルゴリズム）があるらしく
それらを理解できる範囲でいくつか覚えた

https://qiita.com/drken/items/872ebc3a2b5caaa4a0d0

計算量の概念を把握、アルゴリズムの習得と合わせて
問題を読む→Nの範囲を確認→許容される計算量から成り立つ解法を逆算
ができるようになった

https://kenkoooo.com/atcoder/

結局このAtcorder problemsに登録しtrainingをEasyから始めたのが一番よかったかも
現在の進捗はMedium30%
続けていくうちに上達しているのか、ほぼ一発ACできて解いていくのが楽しい

結果、7月からは3完できるようになり無事入茶

# どうする
パフォーマンス的には入緑に届きそうなので引き続き勉強を続けたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3847324/6435511a-f749-67f2-1b8c-9edb76f3b8cf.png)

具体的にはtrainingをHardまで進めて、以降は

https://atcoder.jp/contests/typical90

を埋め、その後はRecommendationをこなしていく所存
もしもRecommendationが尽きたらまた考える(その前に飽きそう)
アルゴリズムの習得は並行して進める
(木とグラフは一つも理解しておらずBFSとDFSやダイクストラ法は必要ありそう
 それとDPも頑張る)

paizaもAランクに上がったのでそのうちSにチャレンジしたい

コードだけ書けても意味がないとされているので
何かしらのアウトプットをしたいとも考えている
（アウトプットとしてどういう形式が存在するのかを調べるところから）
# まとめ
なんにせよAtcorderは楽しい
自身の入力が判定され、客観的な基準で数値化される
というのがゲーミフィケーションの根本的な部分だと思っていて(全然違うかも)
始めたてということもあり
自身の数値の上昇が確認できるところが良いのだと思う
停滞し始めたら途端に飽きるかもしれないが当面はハマってそう

ちなみに、IPAの資格と競プロとは全然関係なかったため
勉強して詰め込んだ知識は春の淡雪のごとく消えていきました
LLaMA 3.1 70b-instructモデルを使ったAIチャットボットの作成：初心者向けガイド

## はじめに

この記事では、Meta社が開発した最新の大規模言語モデル「LLaMA 3.1」を使って、AIチャットボットを作成する方法を解説します。LLaMA 3.1は多言語対応の強力なモデルで、様々なタスクに適用できます。今回は、海賊風に話すチャットボットを例に、モデルの使用方法を学んでいきましょう。

## 1. 環境設定

まずは必要なライブラリをインストールし、環境を整えます。

```python
# transformersライブラリを最新バージョンにアップグレード
!pip install --upgrade transformers

# 必要なライブラリをインポート
import transformers
import torch

# CUDA関連の設定（メモリ効率化のため）
torch.backends.cuda.enable_mem_efficient_sdp(False)
torch.backends.cuda.enable_flash_sdp(False)
```

このコードブロックでは、以下の作業を行っています：
1. `transformers`ライブラリを最新版にアップグレード
2. 必要なライブラリ（`transformers`と`torch`）をインポート
3. CUDAの設定を行い、メモリ使用を最適化

## 2. モデルとトークナイザーの準備

次に、LLaMA 3.1モデルとそのトークナイザーをロードします。

```python
# 必要なクラスをインポート
from transformers import AutoTokenizer, AutoModelForCausalLM

# モデルのパスを指定
model_id = "/kaggle/input/llama-3.1/transformers/70b-instruct/1"

# トークナイザーをロード
tokenizer = AutoTokenizer.from_pretrained(model_id)

# モデルをロード（CPU offloadingを使用）
model = AutoModelForCausalLM.from_pretrained(
    model_id,
    torch_dtype=torch.bfloat16,  # bfloat16形式で計算を行い、精度と速度のバランスを取る
    device_map="auto",  # 利用可能なデバイスに自動的にモデルを配置
    offload_folder="offload",  # オフロード用のフォルダを指定
    offload_state_dict=True,  # state_dictをオフロード
    low_cpu_mem_usage=True,  # CPU消費メモリを抑える
)
```

このセクションでは：
1. モデルとトークナイザーをロードするためのクラスをインポート
2. モデルのパスを指定（この例ではKaggle上のパスを使用）
3. トークナイザーをロード
4. モデルをロード（メモリ使用を最適化するオプションを使用）

## 3. テキスト生成パイプラインの作成

モデルとトークナイザーを使って、テキスト生成のパイプラインを作成します。

```python
# テキスト生成パイプラインを作成
pipeline = transformers.pipeline(
    "text-generation",  # タスクを指定（ここではテキスト生成）
    model=model,  # 使用するモデル
    tokenizer=tokenizer,  # 使用するトークナイザー
    device_map="auto",  # デバイスの自動割り当て
)
```

このパイプラインは、入力されたプロンプトに基づいてテキストを生成するために使用されます。

## 4. チャットメッセージの準備

AIに与える指示と、ユーザーからの入力を準備します。

```python
# チャットメッセージを準備
messages = [
    {"role": "system", "content": "You are a pirate chatbot who always responds in pirate speak!"},
    {"role": "user", "content": "Who are you?"},
]

# メッセージをトークナイザーのテンプレートに適用
prompt = tokenizer.apply_chat_template(messages, tokenize=False, add_generation_prompt=True)
```

ここでは：
1. システムメッセージ（AIの役割指示）とユーザーメッセージを準備
2. これらのメッセージをトークナイザーのチャットテンプレートに適用して、モデルへの入力形式に変換

## 5. テキスト生成の実行

準備したプロンプトを使って、テキストを生成します。

```python
# テキスト生成を実行
outputs = pipeline(
    prompt,
    max_new_tokens=40,  # 生成する最大トークン数
    do_sample=True,  # サンプリングを有効にして多様な出力を得る
    temperature=0.7,  # 生成の多様性を調整（高いほど多様、低いほど決定的）
    top_p=0.95,  # 累積確率に基づくサンプリングの閾値
)

# 生成されたテキストを表示
print(outputs[0]["generated_text"])
```

このコードでは：
1. 準備したプロンプトを使ってテキストを生成
2. 生成パラメータ（最大トークン数、温度、top_p値など）を設定
3. 生成されたテキストを表示

## まとめ

以上が、LLaMA 3.1モデルを使ったAIチャットボットの基本的な作成方法です。このコードを実行すると、海賊風に話すAIチャットボットが「Who are you?」という質問に答えるでしょう。

このサンプルコードを基に、システムメッセージやユーザー入力を変更することで、様々な性格や知識を持つチャットボットを作成できます。また、生成パラメータを調整することで、出力の多様性や一貫性を制御することができます。

LLaMA 3.1は非常に強力なモデルですが、適切に使用するには練習が必要です。このコードを出発点として、さまざまな実験を行い、AIモデルの挙動や特性について理解を深めていってください。

## Kaggleノートブック

https://www.kaggle.com/code/makimakiai/jp-llama-3-1-70b-instruct-base-chat-template

## 参考サイト

https://www.kaggle.com/code/samyakkhetan/llama-3-1-70b-instruct-base-chat-template
tkinterdnd2を利用したPythonプログラムがexe化に失敗したときの対応

# 標準ではないライブラリを使用しているPythonプログラムをexe化する
友人が作成したPythonプログラムのexe化に難航したので対応をまとめておきます。
exe化にはPyInstallerを使用しました。
仮想環境の構築にはPipenvを使用しました。

## 実行環境
* Windows11
* PowerShell
* Python 3.10.6
 
## 目次
* 手順
* 失敗したときのこと
* 参考サイト

# 手順
2. Python3がインストールされていることの確認する
2. Pipenvをインストールする
2. 仮想環境を構築する
2. .pyプログラムに記載されているもののうち、必要なライブラリをインストールする
2. PyInstallerをインストールする
2. PyInstallerでpyファイルをexe化する
2. 仮想環境を削除する

## 1.Python3がインストールされていることを確認する
PowerShellを起動します。Python3がインストールされているか確認します。
```
python3 --version
```
インストールされていない場合はPython3をインストールします（手順は割愛）。

## 2.Pipenvをインストールする
Pipenvがインストールされているか確認します。
```
pipenv --version
```
インストール済なら以下のコマンド実行はスキップし、手順3へ。
以下のコマンドでPipenvをインストールします。
```
pip install pipenv
```
## 3.仮想環境を構築する
仮想環境を作るフォルダ（.pyが置いてある）パスへ移動します。
```
cd [フォルダパス]
```

仮想環境を有効化します。
```
pipenv --python 3.10
pipenv shell
```

## 4. .pyプログラムに記載されているもののうち、必要なライブラリをインストールする
今回使ったライブラリは以下の通りです。うち太字のものは追加インストールが必要なため、pipを利用してインストールします。
* tkinter
* **tkinterdnd2**
* **Pillow**
* **pyperclip**
* os

```
pip install tkinterdnd2 Pillow pyperclip
```

## 5. PyInstallerをインストールする
以下のコマンドでPyInstallerをインストールします。
```
pip install pyinstaller
```

## 6. PyInstallerでpyファイルをexe化する
以下のコマンドでexeファイルを生成します。distフォルダ内に.exeができます。
生成されたexeは単体で実行可能です。
```
pyinstaller color_picker.py --onefile --collect-data tkinterdnd2
```
**オプションについて**

* --onefile
distフォルダに出力されるexeを1ファイルにまとめます。

* --collect-date
tkinterdnd2をパッケージ化するのに必要です。このオプションを付けずに生成したexeを実行した際、ライブラリの読み込みに失敗します。

## 7. 仮想環境を削除する
仮想環境のshellから抜け、仮想環境を削除します。
```
exit
pipenv --rm
```

# 失敗したときのこと
2つの理由でexe化に難航しました。
1. PyInstallerオプションの「--collect-date」がなかなか見つからなかった
2. ChatGPT3.5に質問したら、「.specの設定を変更する」を案内されたが、うまくいかなかった

「--collect-data」オプションを付けずに生成したexeは、ライブラリの読み込みで失敗していることが分かりました。
「4. .pyプログラムに記載されているもののうち、必要なライブラリをインストールする」で、ライブラリのインストールは完了していたため、PyInstallerでexe化する際に何らかの失敗しているのだと考えました。
そこで、ChatGPT3.5にエラー内容とその解消方法を質問したところ、.specを編集する方法を案内されました。内容は以下の通りです。
* PyInstallerのオプションに「--hidden-import」を設定
* .specを編集し、hiddenimportsにライブラリを記載する
しかし、案内された方法で生成したexeは、同じライブラリ読み込み失敗エラーとなりました。

まず前提として、ChatGPTでプログラムを書いていました。そのため、プログラムに関する質問はChatGPTに質問する形で修正していました。
しかし何度聞いても上記以外の回答は得られず、結局ググって「--collect-date」が最適だとわかりました。

# 参考サイト
ありがとうございました！

[PyinstallerでPythonプログラムをexe化する手順書（Windows編）](https://qiita.com/nal_dal_dere/items/95e173068af399e61981)

[tkinter でドラッグアンドドロップ!](
https://qiita.com/bassan/items/0094379024a3e88d4d23)
Amazon Kendraに電子帳簿保存法の質問をしてみる

[前回](https://qiita.com/mine820/items/ff4a02bfb8b7730eeed0)、Amazon Kendraの勉強をしたので、早速改造してみます。
今回は、電子帳簿保存法の「一問一答」のPDFを検索したいと思います。

# 電子帳簿保存法　一問一答
URLはこちらになります。
- [電子帳簿・電子書類関係](https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/pdf/0024005-113_r601.pdf)
- [スキャナ保存関係](https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/pdf/0024005-113_r602.pdf)
- [電子取引関係](https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/pdf/0024005-113_r603.pdf)

電子帳簿保存法の[法律](https://elaws.e-gov.go.jp/document?lawid=410AC0000000025)や[施行令](https://elaws.e-gov.go.jp/document?lawid=503CO0000000128)などはやたらと難しいのですが、[一問一答](https://www.nta.go.jp/law/joho-zeikaishaku/sonota/jirei/4-3.htm)は具体的で、普通の人が読んでも非常にわかりやすいドキュメントとなっています。そのため、これならAmazon Kendraでの検索に使えるのではないかと思いました。

なお今回はお試しで上記ファイルを検索に使いますが、おそらく実際のシステムに組み込んだりしたらダメです。
（Amazon Kendraの注意事項として「Remember that you must only use Amazon Kendra Web Crawler to index your own web pages, or web pages that you have authorization to index. 」となってます）
法令は著作権の対象外ですが、法令の解説やコメントなどの二次的な著作物は著作権の対象になる可能性があるそうです。
この辺りは国税庁の見解待ちですね。

# データソースをWebにして試してみる
前回は、データソースとしてS3にあるPDFとWeb Crawlerの両方を試しましたが、今回はWeb Crawlerだけで試してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/40398afe-e522-856b-8925-033ccb3cf97b.png)

参照するファイルが違うだけで、ほかの設定は同じです。
「Default language」は「Japanese (ja)」にしておきます。
「Source URLs」に上記3つのURLを設定し、「Sync domain range」は「Sync domains only」、「Crawl depth」は「1」、「Sync run schedule」は「Run on demand」にしておきます。
（「Crawl depth」は「0」でも良さそうな気がします）

相変わらず、Syncが終わるのに、結構な時間がかかります。

# ところが．．．
syncが正常に終了し、さて試しに検索してみようかなと思ったら．．．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/d5f2eb2c-e402-8a56-ecb0-01f4ac70864b.png)
．．．スキャンしたファイルが0？
もしかしてWebだとPDFファイルは読み込めないのかな？
いろいろ設定を変更して試してみましたが、うまくいきませんでした。

ということで、とりあえずこちらの方法はあきらめることにします。

# データソースをS3にしてみる
今度は、参照先のPDFファイルをダウンロードしてきて、S3に置いてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/8cfeb97c-1e91-4039-fe04-580c6b926caa.png)

で、データソースをS3にして読み込んでみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/d36d0bc4-ddb4-65e0-6eff-33244bcffd37.png)

# 質問してみる
早速試してみます。
（Webアプリからではなく、直接参照してみます）

- 「金額をマイナスで入力してもよいですか？」と聞いてみたら、こうなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/1019d063-a0d4-0ebd-d957-dc893d03a3da.png)

- 「スキャナ保存時の解像度は？」と聞いてみたら、こうなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/31287ef1-bdfb-d312-c836-7219cb29281a.png)

- 「請求書をデータベースに保存できますか？」と聞いてみたら、こうなりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130771/ebe7789a-7c62-7ddd-f5fb-0bcb6cf487ee.png)

一応、期待するPDFファイルから期待する回答を選んできているから、合っているような気がします。

# まとめ
調べるのにめんどくさい法律関連も、これで調べやすくなるような気がします。ただこれだけだとただの検索システムなので、もう一歩進めたいです。
（感覚的には、キーワード検索から自然言語検索になっただけ）
例えば、自社サービスの情報も突っ込み、LLMと組み合わせれば「自社サービスは電子帳簿保存法に適合してますか？」とか質問できるような気がします。そこまでいければ「使える」と言えるのではないかと思います。
（期待しすぎかな？）

よし、次はBedrockを勉強して、RAGを実現しよう！
MLBピッチャーのデータ分析：今永昇太選手の投球を解剖する（第1回）

# MLBピッチャーのデータ分析：今永昇太選手の投球を解剖する（第1回）

こんにちは、野球データアナリストの shogaku です。今回から、シカゴ・カブスの日本人左腕、今永昇太選手のMLBでの投球データを詳細に分析するシリーズを始めます。

## はじめに

今永昇太選手は2024年シーズン、MLBデビューを果たしました。日本のプロ野球で培った技術がMLBでどのように通用するのか、データを通じて見ていきましょう。

## データの概要

今回の分析では、MLB公式のStatcastデータを使用します。Statcastは、球場に設置された高速カメラとレーダーによって、投球や打球の詳細なデータを取得するシステムです。

分析対象期間は2024年4月1日から7月21日までです。以下のPythonコードで、pybaseballライブラリを使ってデータを取得しました。

```python
!pip install pybaseball

from pybaseball import statcast
import pandas as pd

dates = [
    '2024-04-01', '2024-04-07', '2024-04-13', '2024-04-20',
    '2024-04-26', '2024-05-01', '2024-05-07', '2024-05-13',
    '2024-05-18', '2024-05-29', '2024-06-04', '2024-06-09',
    '2024-06-15', '2024-06-21', '2024-06-27', '2024-07-03',
    '2024-07-10', '2024-07-21'
]

df_684007_all_dates = pd.DataFrame()

for date in dates:
    df_single_day = statcast(start_dt=date, end_dt=date)
    df_684007_single_day = df_single_day[df_single_day['pitcher'] == 684007]
    df_684007_all_dates = pd.concat([df_684007_all_dates, df_684007_single_day])

df_684007_all_dates.reset_index(drop=True, inplace=True)
```

このコードで、今永選手（ID: 684007）の全投球データを取得しました。

## 分析の目的

1.  今永選手の投球の特徴や傾向を明らかにする
2.  シーズンを通じてのパフォーマンスの変化を追跡する
3.  投球メカニクスの理解を深める

## 使用するツールと手法

分析にはPythonを使用し、主にpandas、matplotlib、seabornライブラリを活用します。例えば、以下のコードで投球種類の分布を可視化できます：

```python
import matplotlib.pyplot as plt

def plot_pitch_distribution(df, date):
    df_L = df[df['stand'] == 'L']
    df_R = df[df['stand'] == 'R']

    fig, axs = plt.subplots(1, 3, figsize=(18, 6))
    plt.suptitle(f'Pitch Distribution on {date}')

    colors = {'FF': 'blue', 'SL': 'red', 'CU': 'purple', 'CH': 'green', 'PO': 'orange', 'ST': 'cyan', 'FS': 'yellow', 'SI': 'pink'}
    
    df['pitch_type'].value_counts().plot(kind='pie', ax=axs[0], autopct='%.1f%%', colors=[colors.get(key, 'grey') for key in df['pitch_type'].value_counts().index])
    axs[0].set_title('Total')
    axs[0].set_ylabel('')

    df_L['pitch_type'].value_counts().plot(kind='pie', ax=axs[1], autopct='%.1f%%', colors=[colors.get(key, 'grey') for key in df_L['pitch_type'].value_counts().index])
    axs[1].set_title('vs Left batter')
    axs[1].set_ylabel('')

    df_R['pitch_type'].value_counts().plot(kind='pie', ax=axs[2], autopct='%.1f%%', colors=[colors.get(key, 'grey') for key in df_R['pitch_type'].value_counts().index])
    axs[2].set_title('vs Right batter')
    axs[2].set_ylabel('')

    plt.show()

# 例：最新の試合日のデータで投球分布を表示
latest_date = df_684007_all_dates['game_date'].max()
df_latest = df_684007_all_dates[df_684007_all_dates['game_date'] == latest_date]
plot_pitch_distribution(df_latest, latest_date)
```

このコードを実行すると、最新の試合日における投球種類の分布が表示されます。

![](https://pbs.twimg.com/media/GTgNyhwaIAAAAOo?format=jpg\&name=large)

## シリーズの構成

これから７回に分ける

1.  イントロダクション（本記事）
2.  投球タイプの分布分析
3.  リリース特性の分析
4.  ボールの動きの分析
5.  相関分析
6.  特定日付の詳細分析
7.  結論と今後の展望

## おわりに

このシリーズを通じて、今永選手の投球の特徴や、MLBでの適応過程を詳細に見ていきます。次回は投球タイプの分布について、より詳しく分析していきます。

***
magic formula tyre modelを使ってタイヤの最大横力を計算する

# はじめに
大学生活のなかで，タイヤの発生できる最大の横力を出力したいときが来るはずです。そんなときのために最大横力とそれを発生する横滑り角を出力する関数を作成しました。

# 環境
<dl>
  <dt>使用ソフト</dt>
  <dd>MATLAB R2023 a</dd>
  <dt>使用したアドオン</dt>
  <dd><a href="https://jp.mathworks.com/matlabcentral/fileexchange/110955-magic-formula-tyre-library">Magic Formula Tyre Library</a></dd>
</dl>

# 関数作成
今回はMagic Formula Tyre Libraryの関数で求められる入力に従って(MF係数，タイヤにかかる荷重，タイヤ内圧，キャンバー角，速度，左右）を引数とする関数にします。

| 入力 | 単位 |
| --- | --- |
|タイヤ荷重| N |
|タイヤ内圧|Pa|
|キャンバー角| rad|
|速度|m/s|
|左/右|`0`/`1`|

座標系は「DIN ISO 8855:2011」に従うそうです。[Vehicle Dynamics Blockset の座標系](https://jp.mathworks.com/help/vdynblks/ug/coordinate-systems-in-vehicle-dynamics-blockset.html)と同じです。キャンバー角の向きがわかりにくいですが，ネガキャンが正方向。多分。

今回はFyが正となる方向（進行方向左）のみを考えることとしました。




```matlab:FYmax.m
function [FY_max, sa] = FYmax(tireParams,FZ,IP, IA, vel,side)
    SA_deg = linspace(-12, 12);%横滑り角の範囲を-12°~ 12°として計算
    SA_rad = SA_deg / 180 *pi;%degをradに変換
    [~,FY] = magicformula(tireParams,0,SA_rad, FZ, IP, IA, vel, side);%横力計算
    [FY_max,sa_index] = max(FY);%最大横力と，それを与える横滑り角のindexを出力
    sa = SA_rad(sa_index);%最大横力を与える横滑り角を計算
end
```

# 注意事項
大スリップアングル領域での減衰を上手くフィッティングできていないと過大な横力が出力されるのでよく確認してから使った方がいいです。うまくフィッティングできていなかったときは，
 * MF係数の修正
 * (MF係数の修正が難しい場合)　横G実測値などから実際に使えている横滑り角を見積り，関数の`SA_deg`の範囲をそれにあわせる

のどちらかによって対応しましょう。

# おわり
今回作成した関数を使うことで簡単なタイム計算を行うことができるようになります。（今後作成予定）
【Claude×CodePen】あなたにぴったりのワイン教えます！

# お客さまからどれがおすすめ？って聞かれて困ったスーパー店員のためのアプリ

## ClaudeとCodePen使用


### 完成品
https://669e8169c5a5a16c77b1a6bf--friendly-figolla-9d4dba.netlify.app/


### 作成方法
**:one:spreadsheetを使って店舗の取り扱いワインの一覧の作成
:two:商品詳細を記入→味わい、産地、種類**

![スクリーンショット 2024-07-27 234959.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777269/14d3a1b1-5f32-629d-e422-d24b909c7b5e.png)

**:three:Claudeにプロンプト投げかけコードを作成→CodePenに添付**

![スクリーンショット 2024-07-13 191001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777269/f95b64f6-9402-4787-7f39-cdb34a02fc45.png)


Claudeが書いてくれたコード
![スクリーンショット 2024-07-13 004111.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777269/bd6ac016-67b8-7fce-a023-617f3c0c00cc.png)

**:four:理想形を求めてコードの修正
:five:完成！**



完成品のトップページ
![スクリーンショット 2024-07-18 115156.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3777269/467de572-aa29-d6ce-4bc2-65036871f4b9.png)


## 完成品とはいってはいるが…
実は全然完成していません…
まだまだ発展途上で、同僚や仲間たちからもらったフィードバックを全然生かせていません。
今後はもっと完成に近づけ、職場で使えるような状態にしていきたいです。


**※今回はアイディアと自分の振り返りのために記事を書きました。
読んでいた方、内容ペラペラですみません…。**
AWS SAP試験対策＆合格体験記

# はじめに
AWS Certified Solutions Architect - Professional 認定を取得するように上司から圧力をかけられている社会人2年目のITエンジニアです．
これもいい機会だと思い，折角なので資格取得までの道のりを体験記として残しておこうと思い立ちました．
7月中旬から約2か月間勉強し，9月20日に取得しました．
勉強していく中で頻出語句，問題等をまとめたいと思います．
本記事がどなたかのモチベーションアップや勉強方法の一助になれば嬉しいです．

# 筆者の技術レベル
業務でAWS案件に1年間従事（現在進行形で従事中）．
SAPro取得前は以下の資格を保有していました．
- AWS Certified Cloud Practitioner
- AWS Certified Solutions Architect - Associate (SAA)
- AWS Certified Developer - Associate (DVA)
- AWS Certified SysOps Administrator - Associate (SOA)
- AWS Certified Security - Specialty (SCS)
- 基本情報技術者

# 主な勉強コンテンツ
- AWS認定資格試験テキスト＆問題集　AWS認定ソリューションアーキテクト - プロフェッショナル　改訂第2版
- Cloud Lisence (旧黒本)
- Black Belt

# 頻出AWSサービス
試験に頻出し，重要度が高いと思われるサービスです．（筆者の主観です）
ここら辺のサービスは何かできるか，どういった時に必要とされるかなどまで覚えると本番で役に立つかと思います．
- **AWS Database Migration Service (DMS)**
  - オンプレのDBからAWSのデータベースサービス（RDS，DocumentDBなど）にデータ移行する際に使用．
  - オンプレとVPC間でVPN接続を確立して使用することが望ましい．（インターネット経由でも使用可能だがセキュリティ面が不安）
  - 変更データキャプチャ（CDC）で既存のDBの変更内容をリアルタイムで反映可能．
- **Service Catalog**
  - デプロイできるリソース（AMIなど）を承認されたものに制限できる．
- **VM Import/Export**
  - オンプレのVMをAWSにコピーできる．
  - オンプレからアプリケーションやワークロードごと移行する際に使用する．
- **AWS Storage Gateway**
  - オンプレからクラウドストレージにアクセスを提供するサービス．文字通りストレージへの出入り口を提供する．
  - S3 ファイルゲートウェイ　→NFSやSMBプロトコルを使用して，S3に保管する
  - FSx ファイルゲートウェイ　→SMBプロトコルを使用して，FSxに保管する
  - テープゲートウェイ　→テープを保存する
  - ボリュームゲートウェイ　→EBSスナップショットとして保管できる
- **Direct Connect 仮想インターフェース**
  - プライベート仮想インターフェース　→プライベートIPを使用してVPC内のリソースにアクセス
  - パブリック仮想インターフェース　→パブリックIPを使用してすべてのAWSサービスにアクセス
  - トランジット仮想インターフェース　→Trangit Gatewayにアクセス
- **AWS Snowball**
  - オンプレからS3に大量のデータを迅速に移行できる．（テラバイト規模を1週間程度）
  - コスト効率がいいこと，データ移行完了までの期間が短い要件の時に使用する．
- **AWS Elastic Beanstalk**
  - アプリケーションのデプロイや管理環境を提供するサービス．
  - ワーカー環境　→AutoScalingグループ，EC2，IAMロールなどが含まれた環境
- **AWS IoT Core**
  - IoTデバイスからのデータを集約，管理するサービス
- **AWS IoT Greengrass**
  - IoTエッジデバイス用のサービス．

# 頻出ユースケース
ある程度勉強をしていくと，ある特定の要件があるときはこのサービスを使うといった暗記的な覚え方で解けるものが見えてくるかと思います．（あまりよくない覚え方かもしれませんが．．．）
そのような定型的なユースケースをまとめます．

- **インターネットに接続せずに他サービスのあるVPCにアクセス**
  - VPC-Aにアプリケーションがあり，VPC-BにあるDBやAPIにアクセスしたいが，インターネットを経由したくないという要件の場合は，VPCインターフェース型エンドポイントを利用します．
  - オンプレ→VPC間はインターフェースエンドポイントでは通信ができないことには注意が必要です．
- **インターネットを経由せずにS3にアクセス**
  - S3ゲートウェイ型VPCエンドポイントを利用します．
- **順序性を保つキューイング**
  - SQSのFIFOキューを使用する．（定番）
- **EC2のステータスチェックエラーの解消**
  - EBS-backd AMIの場合　→インスタンスを停止して再開する．（特に指定がない場合はこっち）
  - instance-store backed AMIの場合　→インスタンスを終了（削除）し，代わりのインスタンスを起動する．
- **APIキーやDB認証情報をローテーション**
  2パターンあります．
  - Secret Manager　
    - 運用の手間を最小化する場合に使用
  - System Manager Parameter Store + Lambda 
    - コスト効率よく実現する場合に使用

# まとめ
AWS SAProまで取得できればほとんどのAWS案件は対応できるみたいな風潮がありますが，取得だけではやはり厳しい気がします．
実務に経験に勝る知識なしということを日々痛感しているので，今後はハンズオンや自分で気になったサービスを使ってみた記事を書いていくつもりです．
【Gradle】マルチモジュールプロジェクトをversion catalog移行した際、GitHub Packagesの依存がDependabotに反応しなくなった問題への対処

# TL;DR
- `Dependabot`が`version catalog`に対して更新対象を検索する場合、`repositories`設定はルートに定義された値が参照されるらしい
- 当該プロジェクトでは、`GitHub Packages`へのアクセス設定が各サブモジュールにしか定義されておらず、検索が失敗していた
  - 見つからない依存が有った場合も、`Dependabot`のアクションは失敗にならないようだった

# 状況
`gradle`のマルチモジュールプロジェクトを`version catalog`移行した際、社内の`GitHub Packages`に置かれた依存に対して`Dependabot`が反応しませんでした。
ログを見た所、ステータスそのものは正常終了となっていましたが、当該依存に関する検索結果が`404`になっていました。

# 原因と対処
`GitHub Packages`に置かれた依存を使うためには、[通常では`repositories`にシークレット関連の設定が必要](https://github.com/orgs/community/discussions/26634)[^pat]です。  
当該リポジトリでは、それらのシークレット設定は各サブモジュールに書かれていました。

[^pat]: [この制約をハックで何とかされている方がいらっしゃいます](https://github.com/orgs/community/discussions/26634#discussioncomment-9870811)。

これまでの`Dependabot`設定ではモジュール毎に指定が有ったためか、この状態で問題無く動いていましたが、`version catalog`化後の設定では、プロジェクトルートにもこの設定が必要となるようです。
弊チームでは、`allProjects`に一括設定する方針としました。

```kotlin
allprojects {
    repositories {
        mavenCentral()
        // dependabotが社内GitHub Packagesの依存を検索できるようにする設定
        maven {
            /* シークレット設定 */
        }
    }
}
```
投稿 27 HTTPS SSH 2024/07/27

本日の勉強時間　4H

【HTTPS】
アカウント情報だけでリポジトリに書き込めるので、どこからでも簡単にアクセスできる。
すべてのファイアウォールで公開されている。
GitHub公式が推奨している通信。
【SSH】
情報漏えい対策としては最適解。
鍵がハードディスク上のユーザアクセスが可能なファイルとして保存されることが欠点。
【cron】VSCodeでcrontabを編集する方法


crontab のエディタは`EDITOR`変数で変更できます。
`~/.zshrc`に以下のように記述すると vim に変更されます。
```~/.zshrc
export EDITOR=vim
```

しかしVSCodeに変更する際に以下のように記述するとVSCodeは開きますが、編集前に`crontab -e`コマンドが終了してしまうためcorntabの編集ができません。

```~/.zshrc
export EDITOR=code
```

```zsh:ターミナル
$ crontab -e
crontab: no changes made to crontab
```

編集前に`corntab -e`コマンドが終了してしまうのを回避するために以下のようにします。

まず以下の内容で`code-wait.sh`を作成します。

```code-wait.sh
#!/bin/zsh
code --wait "$@"
```

次に`code-wait.sh`に実行権限を与えます。

```zsh:ターミナル
sudo chmod +x /path/to/code-wait.sh
```
または
```zsh:ターミナル
sudo chmod 755 /path/to/code-wait.sh
```

そして`~/.zshrc`に以下を追記します。

```~/.zshrc
export EDITOR=/path/to/code-wait.sh
```

すると編集前に`corntab -e`コマンドが終了してしまうのを回避できます。

![スクリーンショット 2022-09-16 18.27.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/171d1539-16f6-ffde-50dc-c32bc91313da.png)
Next.js+rails7+mysql8.0で環境を構築する

https://qiita.com/gabakugik/items/edcc2f4950e5cd94185a
これの続きです。

railsの構築

ツリー構造
```
|-- backend
|   |-- Dockerfile
|   |-- Gemfile
|   |-- Gemfile.lock
|   |-- README.md
|   |-- Rakefile
|   |-- app
|   |-- bin
|   |-- config
|   |-- config.ru
|   |-- db
|   |-- lib
|   |-- log
|   |-- public
|   |-- storage
|   |-- test
|   |-- tmp
|   `-- vendor
|-- docker-compose.yml
`-- frontend
    |`-- app
`-- Dockerfile(フロント用）
```

backendの中に入り

```Dockerfile:Dockerfile
FROM ruby:3.2

ENV LANG=C.UTF-8 \
  TZ=Asia/Tokyo

WORKDIR /app
RUN apt-get update -qq && apt-get install -y nodejs default-mysql-client
COPY Gemfile /app/Gemfile
COPY Gemfile.lock /app/Gemfile.lock
RUN bundle install

CMD ["rails", "server", "-b", "0.0.0.0"]

```

```backend/Gemfile:backend/Gemfile
source 'https://rubygems.org'
gem 'rails', '~> 7.0.5'
```

docker-compose.ymlに戻り
修正
```docker-compose.yml

version: '3.8'
services:
  db:
    image: mysql:8.0
    command: --default-authentication-plugin=mysql_native_password
    environment:
      MYSQL_ROOT_PASSWORD: password
    ports:
      - 3306:3306
    volumes:
      - mysql-db:/var/lib/mysql
  backend:
    tty: true
    depends_on:
      - db
    build:
      context: ./backend/
      dockerfile: Dockerfile
    ports:
      - 3000:3000
    volumes:
      - ./backend:/app
    command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
  frontend:
    build:
      context: ./frontend/
      dockerfile: Dockerfile
    volumes:
      - ./frontend:/app
    command: 'yarn dev'
    ports:
      - '3001:3001'
volumes:
  mysql-db:
    driver: local
```

```
docker compose run backend rails new . --api --force --no-deps --database=mysql
```

```./backend/config/database.yml
default: &default
  adapter: mysql2
  encoding: utf8mb4
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>
  username: root
  password: password # デフォルトだと空欄になっているはずなので変更
  host: db # デフォルトだとlocalhostになっているはずなので変更

development:
  <<: *default
  database: myapp_development

test:
  <<: *default
  database: myapp_test

production:
  <<: *default
  database: <%= ENV["DATABASE_NAME"] %>
  username: <%= ENV["DATABASE_USERNAME"] %>
  password: <%= ENV["DATABASE_PASSWORD"] %>
```

```
$ docker compose build
$ docker compose up -d
$ docker compose run backend bundle exec rails db:create
```

これでcompose.ymlでlocalhost:3001でnext.js、localhost:3000でrailsが表示されるはずです。

ぜひやってみてください。
通信速度の取得方法【C#】

# はじめに

こんにちは。
ジョジョ好きなXRクリエイターの [もふるね](https://twitter.com/mofurune_k) です。

VRChatをしてるときにラグくなることがあるので、通信速度を可視化しようと思いました。

環境
・Windows
・Visual Studio 2022


# 通信速度の取得

## 手法まとめ

通信速度を測る方法はいくつかあって

- ダウンロード/アップロードテスト
    - インターネットから大きなファイルをダウンロードしたり、サーバーにアップロードしたりして、その時間を測定する
- Network Performance Counters (ネットワークパフォーマンスカウンター)
    - ネットワークパフォーマンスカウンターを使用してインターフェースの送受信バイト数やパケット数などを取得する。これらのカウンターを定期的にサンプリングすることで、通信速度を計算する。

ダウンロード/アップロードテストはアップロード場所の確保など実装が大変そうなので、今回はネットワークパフォーマンスカウンターの手法を採用します。


## Network Performance Counters (ネットワークパフォーマンスカウンター)

参考にしたサイト：
[ネットワークインターフェイスの構成、統計情報を取得する](https://dobon.net/vb/dotnet/internet/networkinterface.html)



コードで書くとこんなふう
```cs:
using System.Net.NetworkInformation;

// ネットワークインターフェイスを取得する
NetworkInterface networkInterface = NetworkInterface.GetAllNetworkInterfaces().FirstOrDefault();
Console.WriteLine("説明:{0}", networkInterface.Description);

// 送受信バイト数を取得するパフォーマンスカウンターを作成
PerformanceCounter bytesSentCounter = new PerformanceCounter("Network Interface", "Bytes Sent/sec", networkInterface.Description);
PerformanceCounter bytesReceivedCounter = new PerformanceCounter("Network Interface", "Bytes Received/sec", networkInterface.Description);

while (true)
{
    // 現在の送信と受信のバイト数を取得
    float bytesSentPerSec = bytesSentCounter.NextValue();
    float bytesReceivedPerSec = bytesReceivedCounter.NextValue();

    // 通信速度を表示
    Console.WriteLine($"送信速度: {bytesSentPerSec / 1024} KB/s, 受信速度: {bytesReceivedPerSec / 1024} KB/s");

    // 1秒ごとに更新
    Thread.Sleep(1000);
}
```

自分の環境で実行してみたらこうなった。

```
説明:Killer E3100G 2.5 Gigabit Ethernet Controller
送信速度: 0 KB/s, 受信速度: 0 KB/s
送信速度: 6.703342 KB/s, 受信速度: 0.4097682 KB/s
送信速度: 0.149864 KB/s, 受信速度: 0.635009 KB/s
送信速度: 0.1967771 KB/s, 受信速度: 0.5123546 KB/s
```

youtubeを高画質でみたりすると受信速度が変化するので試してみてください。
HD画質で見たら100KB/sくらいでたよ。


# 振り返り

現在の送受信の速度は取れたけど、ラグいかどうかの判定の仕方はわからなかった(´・ω・｀)
Pythonで自作クラスのオブジェクト同士を比較する方法。 [ TypeError: '<' not supported between instances of 'Hoge' and 'Hoge' ] の解決方法。

## はじめに
自作class (ユーザー定義クラス)のオブジェクト同士を比較する方法を勉強したので、その備忘録です。
さっさとコードだけ見たい人は、目次の「定義方法　(解決した具体的なコード)」をどうぞ。

## 今回解決できるエラー
* TypeError: '<' not supported between instances of 'Hoge' and 'Hoge'
* TypeError: '>=' not supported between instances of 'Hoge' and 'Hoge'

## 本文
### 起こった問題
下記のようなコードを実行したところ、冒頭のエラーがでました。
```python
class Hoge:
    def __init__(self,age,name):
        self.age  = age
        self.name = name
        
a = Hoge(20,"A 君")
b = Hoge(21,"B 君")
c = Hoge(18,"C 君")

print("最年少者 :",min([a,b,c]).name)
```
<br>

### 解決策
#### ダンダーメソッドを使う
>**ダンダーとは**
>Double Underの略で、underscore( _ )を二つ繋げた( __ )のことです。
><br>
>
> **ダンダーメソッドとは**
> ダンダーで囲い定義するメソッドのことで、「特殊メソッド」とも呼ばれる。
>
> 例)コンストラクタ
> ```python
> def __init__(self, age, name):
>     self.age  = age
>     self.name = name
> ```

今回使うダンダーメソッドは、下記の二つです。
* \_\_lt__
* \_\_le__
<br>

##### \_\_lt__ とは
オブジェクト同士を、**A < B** のように比較した時に呼び出されるものです。

##### \_\_le__ とは
オブジェクト同士を、**A <= B** のように比較した時に呼び出されるものです

:::note warn
本来、**A > B** や **A >= B** などの逆を評価する専用のダンダーメソッドがありますが、Pythonは片方を書くともう片方は暗黙的に解釈してくれるみたいです。
(ありがとう Python)
:::

#### 定義方法　(解決した具体的なコード)
比較したいオブジェクトのクラスを定義するところに書き加えます。

```python
class Hoge:
    def __init__(self,age,name) -> None:
        self.age = age
        self.name = name

    # A < B の時に呼び出される
    def __lt__(self, other):
        print("__lt__呼んだ")
        return self.age < other.age

    # A <= B の時に呼び出される
    def __le__(self, other):
        print("__le__呼んだ")
        return self.age <= other.age
        
a = Hoge(20,"A 君")
b = Hoge(21,"B 君")
c = Hoge(18,"C 君")

print("最年少者 :",min([a,b,c]).name)
```
この状態で実行してみると...
```bat
__lt__呼んだ
__lt__呼んだ
最年少者 : C 君
```
しっかりと上記のように比較できます。
min()の内部で２回\_\_lt__を呼び出してるみたいですね。面白い。
<br>

## 最後に
今回紹介したダンダーメソッド以外にも面白いものはたくさんあるので、気になる方は下記も見てみてください。

https://qiita.com/kosupe/items/58b665bd81125a14deba
PostgrestFilterBuilder についての備忘録

`Supabase`の`PostgreSQL`を操作できる`PostgrestFilterBuilder`の使い方について、わかりづらいところがあったため、そのメモです。
公式ドキュメントは、以下ページです

https://supabase.com/docs/reference/javascript/using-filters

## 関数一覧
関数を、メソッドチェーン形式で呼び出すことで、And 条件で検索が可能

##### 等しい（列名 = 値）
`.eq(列名, 値);`

##### 等しくない（列名 != 値）
`.neq(列名, 値);`
※列の値が`null`のレコードが取得されなくなる
→ `null`のレコードを取得できる様にするには、`.neq()`を使用せず、
　`or("列名.is.null,列名.eq.値")`の様な実装が必要

##### より大きい（値 < 列名）
`.gt(列名, 値)`

##### 以上（値 <= 列名）
`.gte(列名, 値)`

##### より小さい（列名 < 値）
`.lt(列名, 値)`

##### 以下（列名 <= 値）
`.lte(列名, 値)`

##### パターンに一致（列名 like パターン）
`.like(列名, パターン）`

##### 列が null（列名 is null）
`.is(列名, null)`

##### 列がいずれかの値に一致する（列 in (値1,値2)
`.in(列名, [値1, 値2])`

##### or 条件（列1 = 値1 or 列2 = 値2）
`.or("列1.eq.値1,列2.eq.列2")`
※`「列名.関数.値」`を`,`区切りで記載することで、`or`検索ができる

### 戻り値の型定義
`.returns<{typeを設定}>();`
→ 実行結果の`data`が`<type>`と同じ型になる
　→ `.select()`で複数件取得する場合は、配列であることを明記すること！
＜例＞ `~.from('table').select('*').returns<{name:string}[]>();`
Kaggleなどのnotebookのメモリ対策

Kaggleなどのノートブックで大規模データを使うと、頻繁にメモリクラッシュを起こしてしまい、その都度毎回調べ直しているのでメモを残しておく。適宜追記していく予定。
# notebook上の邪魔な変数を一掃する
使用したいデータフレーム名と変数名(`variables_to_keep`)をすべて保持しておき、それ以外の他の変数をすべて削除する。 
また、変数'_oh'はjupyter notebookのいくつかの機能（表示など）に使用されるため、残しておく必要がある。
余計な情報がメモリを圧迫しないように、必要なものだけ残しておくことができる。
ただし、importしたライブラリ類(`numpy`や`pandas`なども)消されてしまうため、適宜`variables_to_keep`に含める必要はある。
```Python
all_vars = list(globals().keys())
variables_to_keep = ['train_x', 'test_x', 'features','str_cols','_oh']
variables_to_delete = [var for var in all_vars if var not in variables_to_keep]
for var in variables_to_delete:
    del globals()[var]
```

# データフレームのサイズ(ギガバイト数)を確認する
気がつくとデータフレームのデータ量が増大することもしばしばであるため、人間の目でわかりやすく表示させておく。
```Python
memory_usage_bytes = df.memory_usage(deep=True).sum()
gigabytes_size = memory_usage_bytes / (1024 ** 3)
print(f'DataFrameのメモリ使用量: {gigabytes_size} GB')
```
Android で Gemini Nano を使ってみる：オンデバイス AI の新時代

## はじめに

AndroidスマートフォンでAI機能を活用する新しい方法が登場しました。それが「Gemini Nano」です。この記事では、Gemini Nanoとは何か、どのように使えるのか、そしてなぜ重要なのかを、初心者の方にも分かりやすく解説していきます。

## Gemini Nanoとは？

Gemini Nanoは、GoogleがAndroid向けに開発した小型のAIモデルです。「小型」といっても、その能力は侮れません。大きな特徴は、スマートフォン上で直接動作するということです。

### なぜスマートフォン上で動くAIが重要なの？

1. プライバシーの保護：データをクラウドに送る必要がありません。
2. オフラインでも使える：インターネット接続がなくてもAI機能が使えます。
3. 低遅延：クラウドとのやり取りがないので、応答が速いです。
4. コスト削減：クラウドの使用料がかからないので、開発者にとってはコスト面でメリットがあります。

## Gemini Nanoの仕組み

Gemini Nanoがどのように動作するのか、簡単な図で説明しましょう。

```mermaid
%%{init:{'theme':'base'}}%%
graph TD
    A[あなたのアプリ] --> B[Google AI Edge SDK]
    B --> C[Android AICore]
    C --> D[Gemini Nano]
    D --> E[デバイスのハードウェア]
```

1. あなたのアプリが、Google AI Edge SDKを通じてリクエストを送ります。
2. そのリクエストがAndroid AICoreに渡されます。
3. AICoreがGemini Nanoモデルを使って処理します。
4. 結果がデバイスのハードウェアを使って高速に計算されます。

## Gemini Nanoの特徴

### 1. オンデバイス処理

Gemini Nanoの最大の特徴は、全ての処理がスマートフォン上で行われることです。これにより、以下のようなメリットがあります：

- データのプライバシー保護
- インターネット接続なしでの動作
- 低遅延での応答

### 2. AICore統合

Gemini NanoはAndroidのAICoreシステムサービスと統合されています。これにより：

- デバイスのハードウェアを最大限に活用
- モデルの自動更新
- アプリ開発者の負担軽減

### 3. 安全性

AICoreには複数の安全性機能が組み込まれています：

```mermaid
%%{init:{'theme':'base'}}%%
graph TD
    A[AICore] --> B[制限付きパッケージバインディング]
    A --> C[間接的なインターネットアクセス]
    A --> D[プライバシー中心のAPI]
```

- 制限付きパッケージバインディング：他のパッケージからの分離
- 間接的なインターネットアクセス：直接のネットワークアクセスを制限
- プライバシー中心のAPI：データ保護を重視

## Gemini Nanoの使用例

Gemini Nanoを使うと、以下のような機能をアプリに追加できます：

1. テキスト要約
2. 質問応答
3. 文章の校正・文法チェック
4. スマートリプライ（文脈に応じた返信候補の提示）
5. 感情分析

例えば、Googleの「Pixel Voice Recorder」アプリでは、Gemini Nanoを使って録音した音声の要約を生成しています。また、GboardではAIを活用したスマートリプライ機能を提供しています。

## 開発者向け情報

Gemini Nanoを使ったアプリ開発に興味がある方向けの情報です：

- 対応デバイス：現在はGoogle Pixel 8 Pro、Pixel 8、Pixel 8a、Samsung S24シリーズで利用可能
- 開発ツール：Google AI Edge SDKを使用
- サポートするモダリティ：現在はテキストのみ（将来的に拡張予定）

```mermaid
%%{init:{'theme':'base'}}%%
graph TD
    A[開発者] --> B[Google AI Edge SDK]
    B --> C[AICore]
    C --> D[Gemini Nano]
    D --> E[アプリの機能]
```

## まとめ

Gemini Nanoは、AndroidデバイスでのAI活用に新しい可能性をもたらします。プライバシーを守りながら、高度なAI機能をスマートフォン上で実現できるこの技術は、今後のアプリ開発の方向性を大きく変える可能性があります。

スマートフォンがより「賢く」なることで、私たちの日常生活がどのように変わっていくのか、これからの展開が楽しみですね。

## 参考サイト

https://developer.android.com/ai/aicore

https://ai.google.dev/gemini-api/docs/get-started/android_aicore?hl=ja
AtCoder 勉強記録[C++] その33

AtCoderで入茶を目指して勉強しています。
勉強を継続するために投稿を始めました。
もともとアカウントを作成していましたが、今年の4月から本格的に勉強を始めました。
一応自分用に解法を書いていますが雑です、自分で読み返して困ったら修正します。
[私のアカウント](https://atcoder.jp/users/nanami_brother)
[解いた問題](https://kenkoooo.com/atcoder/#/table/nanami_brother)
# 本日解いた問題
AtCoder Beginner Contest 364に参加した。参加登録したにもかかわらず寝過ごす失態を犯した。先週うまくいっただけにショックが大きいが勉強代として割り切りたい。
## A - Glutton Takahashi
[A - Glutton Takahashi](https://atcoder.jp/contests/abc364/tasks/abc364_a)
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll n;
  cin >> n;
  vector<string> s(n);
  rep(i, n) cin >> s[i];
  for(int i = 0; i < n-2; i++){
    if(s[i]=="sweet"&&s[i+1]=="sweet"){
      cout << "No" << endl;
      exit(0);
    }
  }
  cout << "Yes" << endl;
}
```
### 解法
最後の2回の食事は連続で`sweet`でも問題ないため、最後2回までに連続で`sweet`となるかを判定する。
## B - Grid Walk
[B - Grid Walk](https://atcoder.jp/contests/abc364/tasks/abc364_b)
解答
```c++
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using vec = vector<ll>;
#define rep(i, n) for (int i = 0; i < (int)(n); i++)

int main() {
  ll h, w, si, sj;
  cin >> h >> w >> si >> sj;
  si--,sj--;
  vector<string> c(h);
  rep(i, h) {
    cin >> c[i];
  }
  string x;
  cin >> x;
  for(int i = 0; i < x.size(); i++){
    ll a = si, b = sj;
    if(x[i] == 'L' ) b--;
    else if(x[i] == 'R') b++;
    else if(x[i] == 'U') a--;
    else if(x[i] == 'D') a++;
    if(a>=0&&a<h&&b>=0&&b<w&&c[a][b]=='.') si=a, sj=b;
  }
  cout << si+1 << " " << sj+1 << endl;
}
```
### 解法
仮に移動する変数を用意し、1度マスを移動しておき移動先がグリッドの範囲外もしくは空きマスではない場合は移動せず、そうでない場合は移動することで結果が求まる。
外部エンティティを含むxmlファイルを読み込んだ際、ノードや要素がどの外部エンティティに記載されているかを取得したい

employee1.xmlは従業員情報を記録したファイルです。このemployee1.xmlは外部エンティティとしてemployee2.xmlとemployee3.xmlを参照しています。

```employee1.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE employees [
  <!ENTITY employee2 SYSTEM "./employee2.xml">
  <!ENTITY employee3 SYSTEM "./employee3.xml">
]>

<employees>
  <employee>佐藤一郎</employee>
  <employee>鈴木一郎</employee>
  &employee2;
  &employee3;
</employees>
```

```employee2.xml
<employee>高橋二郎</employee>
<employee>田中二郎</employee>
```

```employee3.xml
<employee>伊藤三郎</employee>
<employee>渡辺三郎</employee>
```

このemployee1.xmlファイルをパースして、従業員の名前一覧を取得しつつ、その従業員がどのファイルに記載されているのかを知りたいとします。たとえば「高橋二郎」であればemployee2.xml、「渡辺三郎」であればemployee3.xmlに記載されているという情報をとりたいわけです。どのように実現すればよいでしょうか?

__結論を述べると、ノードや要素がどのファイルに記載されているかを取得したい場合、NodeクラスのgetBaseURIメソッドを利用します。__ 

```java
String xmlPath = "D:\\tmp\\employee1.xml";
try (InputStream is = Files.newInputStream(Paths.get(xmlPath))) {
	Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(is, xmlPath);
	
	NodeList childNodes = document.getDocumentElement().getChildNodes();
	for (int i = 0; i < childNodes.getLength(); i++) {
		Node childNode = childNodes.item(i);
		if (childNode.getNodeType() == Node.ELEMENT_NODE) {
			Element element = (Element) childNode;
			
			String textContent = element.getTextContent();
			String baseURI = element.getBaseURI();
			System.out.printf("textContent=%s, baseURI=%s%n", textContent, baseURI);
		}
	}
} catch (IOException | SAXException | ParserConfigurationException e) {
	e.printStackTrace();
}
```

このプログラムを実行すると、以下のような結果が得られます。

```
textContent=佐藤一郎, baseURI=file:///D:/tmp/employee1.xml
textContent=鈴木一郎, baseURI=file:///D:/tmp/employee1.xml
textContent=高橋二郎, baseURI=file:///D:/tmp/employee2.xml
textContent=田中二郎, baseURI=file:///D:/tmp/employee2.xml
textContent=伊藤三郎, baseURI=file:///D:/tmp/employee3.xml
textContent=渡辺三郎, baseURI=file:///D:/tmp/employee3.xml
```

NodeクラスのgetBaseURIメソッドにより、ノードや要素がどのファイルに記載されているのかを取得できることが確認できました。

**環境情報**

```
D:\>java -version
openjdk version "17.0.3" 2022-04-19
OpenJDK Runtime Environment Temurin-17.0.3+7 (build 17.0.3+7)
OpenJDK 64-Bit Server VM Temurin-17.0.3+7 (build 17.0.3+7, mixed mode, sharing)

D:\>javac -version
javac 17.0.3
```
unityでガード機能を作る方法



初めにガードモーションをつける

![無題の動画 ‐ Clipchampで作成.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/b93037c0-f417-8be7-fa6e-9e5ac39f50f8.gif)




このままではガードのモーションがついただけなので次にガード判定を作る

BoxColliderのiS Triggerにチェックをつける
![test1 - demoScene_free - Windows, Mac, Linux - Unity 2022.3.20f1_ _DX11_ 2024_07_27 22_13_56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/89929e3f-6a10-2b9e-0d67-cc145183f0f7.png)



ガードボタンを押したときにガードの判定が発生するようにする



PlayerShieldにはさっき作ったガード判定を割り当てる
![test1 - Microsoft Visual Studio 2024_07_27 21_59_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/8b7a4663-ca15-09e6-302b-e7d49c661e82.png)



敵の武器のタグ名をEnemyWeaponにする

![test1 - demoScene_free - Windows, Mac, Linux - Unity 2022.3.20f1_ _DX11_ 2024_07_27 22_25_00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/432ddfd5-b954-6367-804f-b22c48976426.png)







次に敵の武器が盾に当たった時にダメージを無効化するプログラムをかく

![test1 - Microsoft Visual Studio 2024_07_27 22_34_46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/7fed3bba-fa42-6067-2ba9-310fe04651f9.png)

StatusはPlayerのあたり判定

EnemyWeaponのタグが付いたオブジェクトがシールドに当たった時Statusのあたり判定を消すプログラム

出来たら、ガード判定のオブジェクトにアタッチする。


最後にガードをやめた時にStatusを復活させる
![test1 - Microsoft Visual Studio 2024_07_27 22_44_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/12b406d1-51fc-c254-c914-be4452a579ca.png)

ここからエフェクトやガードゲージを追加したらさらによくなるかも
[初学者 - 備忘録] Reactのパフォーマンス最適化

:::note info
再レンダリングを防ぐことでパフォーマンスを向上する方法(関数)についての備忘録
:::

# React.memo()
コンポーネントの再レンダリングを防ぐための高階コンポーネント。
受け取ったpropsの値が同じであれば再レンダリングをスキップする機能がある。
propsの変更を判定し、変更があった場合のみ再レンダリングをする。
![Frame 45 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/890419/6633888d-81a6-3b35-cae6-7a50fe52393c.png)


# usecCallback()
関数をメモ化（キャッシュ）するためのフック。
コンポーネント内で定義した関数をメモして再利用し、レンダリングのたびに生成されることを防ぐ。
子コンポーネントに関数を渡している場合に、不要のレンダリングを防ぐことができる。
イベントハンドラーを毎回新しく作らないようにできる。

# useMemo()
値をメモ化するためのフック。
コンポーネントだけではなく値をメモすることが可能。コストの高い処理などをメモ化する。
useMemo自体の実行にもコストがかかるため、重い処理にのみ使用する。
ABC364をPythonで（A～D）

日本レジストリサービス（JPRS）プログラミングコンテスト2024#2（AtCoder Beginner Contest 364）の解答等のまとめ

https://atcoder.jp/contests/abc364



# A問題
https://atcoder.jp/contests/abc364/tasks/abc364_a

気持ち悪くなるフラグを用意して、直前がsweetか否かと合わせて判定していけばいい
```python:A
n = int(input())
flag = False
flag2 = False
ans = "Yes"
for i in range(n):
    s = input()
    if flag2:
        ans = "No"
    elif s == "sweet":
        if flag:
            flag2 = True
        else:
            flag = True
    else:
        flag = False

print(ans)
```

# B問題
https://atcoder.jp/contests/abc364/tasks/abc364_b

問題文のまま動かせばいい
配列は0基準なのを間違えないように気を付ける
```python:B
h, w = map(int, input().split())
i, j = map(lambda x:int(x) - 1, input().split())
c = [input() for _ in range(h)]
x = input()

array = {"L":(0, -1), "R":(0, 1), "U":(-1, 0), "D":(1, 0)}

for x_i in x:
    dx, dy = array[x_i]
    if 0 <= i + dx < h and 0 <= j + dy < w and c[i + dx][j + dy] == ".":
        i += dx
        j += dy

print(i + 1, j + 1)
```

# C問題
https://atcoder.jp/contests/abc364/tasks/abc364_c

より甘いものからいくつ食べられるかと
よりしょっぱいものからいくつ食べられるかを比較する
```python:C
n, x, y = map(int, input().split())
a = list(map(int, input().split()))
b = list(map(int, input().split()))

a.sort(reverse=True)
b.sort(reverse=True)

INF = float("inf")


def calc(a, x):
    x_a = 0
    for i, a_i in enumerate(a, 1):
        x_a += a_i
        if x_a > x:
            return i
    return len(a)


print(min(calc(a, x), calc(b, y), n))
```

# D問題
https://atcoder.jp/contests/abc364/tasks/abc364_d

$A$をソートして$b_j$から$d$離れた地点、すなわち$b_j - d$と$b_j + d$の間にある点の個数で2分探索をすればいい

（下のコードは$b$をソートしているけどしなくていい）
```python:D
from bisect import bisect, bisect_left

n, q = map(int, input().split())
a = sorted(map(int, input().split()))
b = [list(map(int, input().split())) for _ in range(q)]

data = [(b_i, k_i, i) for i, (b_i, k_i) in enumerate(b)]
data.sort()
ans = [0] * q

for b_i, k_i, i in data:
    ok, ng = 3 * 10 ** 8, -1
    while abs(ok - ng) > 1:
        mid = (ok + ng) // 2
        mini = bisect_left(a, b_i - mid)
        maxi = bisect(a, b_i + mid)
        if maxi - mini >= k_i:
            ok = mid
        else:
            ng = mid

    ans[i] = ok

for ans_i in ans:
    print(ans_i)
```
AWS認定DevOpsエンジニア・プロフェッショナル受験談&学習法

## 概要
2024年7月27日にAWS認定DevOpsエンジニア・プロフェッショナルの試験を受けて合格しましたので、学習したこと等を情報共有として書いていきます。
合格基準750点のところ818点でした〜今回は落ちたかと思っていましたが、合格できて中々点数も取れていてビックリしました。

## 前提の知識と経験
アソシエイトの3つとセキュリティのスペシャリティの資格を合格している状態で、この試験を受けました。
DevOpsエンジニア・プロフェッショナルはマルチリージョンやマルチアカウントの問題が多いですが、そのレベルの案件参加経験はなく、この学習のみですね〜

## 学習期間
今回も大体1ヶ月くらいで、平日は1日2〜3時間、休日は5〜6時間くらいです。ここも、これまでと変わらず。
ちなみに同じ会社のMathew Chanさんは10日間。やっぱり、すごい:smile:

https://note.com/mathew_chan/n/n23ea73a0f445

## 学習教材
本当に教材がないですね〜書籍は無いです、、、作ってやろうか（嘘）

### 1. AWS Certified DevOps Engineer Professional 2024 - DOP-C02
Udemyの動画教材です。日本語字幕付きで、試験範囲を網羅しています。
ただ、各サービスの概要ですので、1回通して観て、それで終わりましたね。

https://www.udemy.com/course/aws-certified-devops-engineer-professional-hands-on/

### 2. AWS認定 DevOpsエンジニア プロフェッショナル 模擬問題集＋詳解
Udemyの日本語の模試問題集で、解説付きは、この教材だけですね〜レベルですが、本番試験より難しいですので、これが分かれば、合格できるかも。
私は答えを一通り見て、テストを3回繰り返し、あとは間違ったところを重点的に復習したくらいです。

https://www.udemy.com/course/dop-c02aws-devops-2024


### 3. AWS Skill Builder
今回もAWS Skill Builderの有料プランも実践してみました。本番模試は有料ですが、他の２０問模試やサンプル模試は無料です。
合計で100問近くありますが、90％くらいできるまで、やり込んだ感じですね。

https://skillbuilder.aws/jp

## 本番試験
180分の試験時間で180分、フルで使いました。通しで160分、残り20分で見直しという感じです。
確実に分からない問題や見たことのない問題は、得点されない問題と踏んで諦めていて、得点になりそうな問題に時間をかけていましたが、結構時間がかかりましたね。
OrganizationsとConfig、Code4兄弟、CloudFormation、マルチリージョン構成、マルチアカウント運用あたりは試験範囲通りの出題でしたね〜
特にひねった問題はなく、ひねり過ぎて分からない問題は得点除外問題として捨てました。
ただ、問題文と選択肢の文は長かったですね〜読むのがしんどいです。ですので、時間配分は大切に。

## 最後に
AWS認定DevOpsエンジニア・プロフェッショナルに合格して、嬉しいのですが、やはり実際はまだ分からないことが多く、案件で活躍レベルには程遠い感じがします。一応、スタートラインには立てるかなと。
やはり、実践と基礎力は大事で、この試験でAWSのことは理解できても、ちょっとは意味があるかもですが、仕事で使える力になったかは別問題。まだまだやらないといけないことが多そうですね〜
GCP Storage遊びのメモ #無料枠

### インターネットへの公開設定

[Google Cloud コンソール](https://cloud.google.com/storage/docs/cloud-console)
Cloudコンソールでバケットを制作(リージョンについての注意は後述)

権限タブで
公開アクセス
-> 保護を無効化
アクセス権の付与
-> allUsers + Storage レガシー オブジェクト読み取り

```
https://storage.googleapis.com/$bucketname/$filename
```
でアクセスできる

### CLI

[gcloud CLI をインストールする](https://cloud.google.com/sdk/docs/install?hl=ja#deb)
[gcloud storage cp  |  Google Cloud CLI Documentation](https://cloud.google.com/sdk/gcloud/reference/storage/cp#FLAGS)
[ファイル システムからオブジェクトをアップロードする  |  Cloud Storage  |  Google Cloud](https://cloud.google.com/storage/docs/uploading-objects?hl=ja)

```
gcloud storage cp ~/file.txt gs://bucketname --content-type "text/plain"
```

基本はOCIも同じ
[OCI CLIメモ](https://qiita.com/WhiteCat6142/items/1b5c2e46e45204bd0515)

### 料金の節約について

HTTPの転送にはgzipを用いることができるがnginxのgzip_staticのようにgzipで保存して必要に応じて展開することで容量を節約できる
[gzip 圧縮ファイルのトランス コーディング](https://cloud.google.com/storage/docs/transcoding?hl=ja)

信用性が低い代わりに料金の安い単一リージョンにすること、と設定するリージョンには気をつけること

> * 5 GB 月の Regional Storage（米国リージョンのみ）
> * 5,000 回のクラス A オペレーション（1 か月あたり）
> * 50,000 回のクラス B オペレーション（1 か月あたり）
> * 1 GB の北米から全リージョン宛ての下りネットワーク（1 か月あたり、中国とオーストラリアを除く）
> 
> 無料枠を利用できるのは us-east1、us-west1、us-central1 リージョンのみです。使用量の計算は、これらのリージョンすべての合計が集計されます。

[Google Cloud の無料プログラム](https://cloud.google.com/free/docs/free-cloud-features?hl=ja#storage)

[ちょっと待って！そのGCP、本当に無料枠？](https://qiita.com/99no_exit/items/b36f74170df4dbdaa9ba)

### Tips

gcpにはいろいろな保護機能がある
たとえばsoft-deleteは以下のようなふるまいをする

>最近削除または上書きされたすべてのオブジェクトを一定期間保持することで、偶発的な削除や悪意のある削除からデータを保護します

[削除（復元可能）](https://cloud.google.com/storage/docs/soft-delete?hl=ja)
Blueskyの独自ドメイン設定

# まず、ドメインを買います

以下略。

https://www.value-domain.com/

# 適当なハンドルでBlueskyのアカウントを作成

以下略。

https://bsky.app/

# Blueskyの設定画面からハンドルに独自ドメインを設定

## Bluesky側の設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/20c70388-1b3a-cd4d-8838-ca8e89cc0c0a.png)

高度な設定→ハンドルを変更→「自分のドメインを持っています」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/122d9509-cae0-5e97-c8d8-79728e9cd593.png)

使用するドメインを入力。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/58a4133b-3d09-1e8c-29fe-69adfe5c6de7.png)

「次のDNSレコードをドメインに追加してください」の部分に以下のような謎の文字列が表示される。

```
ホスト：
_atproto
タイプ：
TXT
値：
did=did:plc:xxx...
```

## バリュードメイン側の設定

ドメインの設定操作を選択。

https://www.value-domain.com/modall.php

以下のようなボタンが表示されるはずなので、DNS/URLを選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/4daf5da3-3e2a-a2b6-dd83-2d801684d5f3.png)

先ほどの謎の文字列は、バリュードメイン側で以下のように入力せよという意味。

```
txt _atproto did=did:plc:xxx...
```

設定を保存して、バリュードメイン側の設定は終了。

## Bluesky側の設定

「DNSレコードを確認」ボタンを押下、問題なければ以下のような表示となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147207/bb605ad1-0170-81b1-1197-8cfd8a347e5b.png)

「【自分のドメイン】に更新」を選択して終了。