OmniAICreator/Qiita-1.07M huggingface dataset:
ChatdollKitで音声対話エージェントのQuest2単機デプロイに挑戦し挫折する

ひょんな切っ掛けでchatGPTを使った対話型AIをVRでデプロイしなければならなくなりました。
偶然見つけた下記記事から出来るかも？と思い挑戦。

https://qiita.com/uezo/items/7ff1566f05c0a1c74a46

ITパスポートレベルの知識＆プログラミング3日坊主で挫折した私ですが、今度ばかりは逃げられない。
実施手順と当たった壁、各種疑問点について備忘＆誰かの為になると信じて残します。

# 環境・前提条件
Unity 2021.3.21f1 LTS
[ChatdollKit v0.6](https://github.com/uezo/ChatdollKit "ChatdollKit")
Burst v1.6.6
[UniTask v2.3.1](https://github.com/Cysharp/UniTask "UniTask")
[uLipSync v2.6.1](https://github.com/Cysharp/UniTask "uLipSync")
[UniVRM v0.89.0](https://github.com/vrm-c/UniVRM/releases/tag/v0.89.0 "UniVRM")
[VRMExtension](https://github.com/uezo/ChatdollKit/releases "VRMExtension")
Newtonsoft Json v3.0.2
[Oculus Integration v53.1](https://assetstore.unity.com/packages/tools/integration/oculus-integration-82022 "Oculus Integration")
XR Plugin Management v4.3.3


# 実施手順
1\. 下記サイトを参考に、ChatdollkitのREADME指定の各種パッケージを導入し、「動作確認」まで実施

https://github.com/uezo/ChatdollKit/blob/master/README.ja.md

2\. 下記サイトを参考にビルド・実行手前まで実施 ついでに[Meta Quest Developer Hub](https://developer.oculus.com/meta-quest-developer-hub/ "Meta Quest Developer Hub")もインストール
Edit > Project Settings > Oculusに表示される要対応項目はよくわからぬままFixしまくり

https://tech.framesynthesis.co.jp/unity/metaquest/

3\. Build SettingsでTexture CompressionをASTCに変更し、Quest2をつないだ状態でBuild And Run

# 発生したエラー
そして現れたのは下記のようなエラーでした。
![FwdZQsVacAQ-ndH.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477084/c141d2ea-c5ed-6bf3-823c-2b5c7d736691.png)

reference先が定義されてないということは何かインポートし忘れた？とは理解したものの、具体的に何かわからずchatGPTに相談しながら理解を進めました。

多分デプロイ時にC#からC++にトランスパイルする際、
ChatdollKit内のWebGLMicrophoneにある関数が見つからなかったということと思います。
しかし、Assets/ChatdollKit/Scripts/IO/WebGLMicrophone.cs及びその中に該当する関数は確かに存在しており、エラー原因は掴めず。

# 対処してみる
原因を確かめるため、以下のように触ってみましたが問題の解決に至りませんでした。

* 下記Qiitaによるとサイズ超過時に出るそう
Build Settings > IL2CPP Code Generationを Faster (smaller) builds に切り替えてみる
**⇒変化なし**

https://qiita.com/megumu-u/items/4565960af3f1aa586cd2

* WebGLがChatdollKitのコンポーネントに入ってないのが原因と推定（んなわけ
WebGLMicrophone.csをscene内のChatdollKitにコンポーネントとして追加
**⇒当然無意味**
	
# 解決
そもそもエラー出しているIL2CPPとは…を調べていたら、どうやらMonoというコンパイラもあるそうで。

試しにProject Settings > Player > Android > Configuration > Scripting BackendをMonoに変更して、TargetArchitecturesをARMv7にしたところ、Quest2でデプロイ成功！問題はコンパイラだった？

ただし、FPSも低くかなり動きはもっさり。一言二言会話したらアプリが落ちちゃいました。

# 気になる事と今後の展望
IL2CPPとMonoの違いを調べたところ、
MonoはJITコンパイラでランタイム性能がC/C++に追い付かないそうです。

https://qiita.com/4_mio_11/items/d5d7b4e879a8341595cd

逆に言うとJITだからBuild時最低限の変換で済みデプロイできたと考えられ、「対処してみる」の初手で実施したアプローチの通りそもそもProjectが重すぎることが原因なのではないか？という説が濃厚に。

表に出ているエラーメッセージにそんな気配はないので、果たして本当にそうか疑問は残りますが。
Quest対応変換したアバターに切り替えたりしたらうまくいくかも？

更に困った事にUnityを再起動してProjectを読み直したらこんなエラーが。
Quest2としてはIL2CPPを使って、ARMv7ではなくARM64にしてほしいとのこと。
困っちゃったわね…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477084/6c144357-ee50-e7d8-bdb9-1c2da9844b2d.png)

IL2CPP、ARM64で出来ればいいのですが…引き続き格闘です。
何か良いアイデアあれば頂きたいです…
【PHP】PDO：「query」と「prepare/bindValue/execute」の使い分け②

## 初めに

- PHP/Mysqlを使用して１年ほど
- Symfony：ORM(doctorin)やLaravelを半年ずつほど

## 概要

①では使い分けの基準を投稿いたしました。

https://qiita.com/siroisitaka/items/9bf54ee75f940c141429

②では「query」の処理内容にフォーカス当てて記載いたします。

## 1. queryについて

まずは静的なSQL文に使用する「query」について調べてみました。

PHPドキュメントでは以下のように記載があります。

:::note info
**PDO::query()** は、一回の関数コールの中で SQL ステートメントを準備して実行し、 結果を PDOStatement オブジェクトとして返します。
※[PDOStatement](https://www.php.net/manual/ja/class.pdostatement.php) オブジェクトについて
:::

要するにSQLは実行されるが、戻り値が **PDOStatement** なので値は取り出せていない状態です。(雑ですみません…)

値を取り出すには **PDOStatement** クラスで用意されている「fetch」や「fetchAll」を使います。

## 2. fetch/fetchAll について

「fetch」「fetchAll」についてざっくり解説

:::note info
「query」などで取得した**PDOStatement** を使用してSQL結果を取得する際に使用します。
① fetch() : データを一行返す
② fetchAll : データを全て配列で返す
:::

実際の記述例を下記に記載します。

```php
$sql = 'select * from test where id = 1';
$Statement = $pdo->query($sql); //$sqlに格納したSQL文が実行される
$return = $Statement->fetch(); //$StatementからSQL文の結果を1レコード取得する
$return2 = $Statement->fetchAll(); //$StatementからSQL文の結果を全て取得する
```

## まとめ

- 「**query**」の戻り値は**PDOStatement** となるため値(データ)が直接取得できるわけではない。
- **PDOStatement** から値を取得するには「fetch」や「fetchAll」を使用する。
- 「**fetch**」はデータを一行、 「**fetchAll**」はデータを全て配列で返す。
- 使用イメージはこんな感じで考えています、「**query**」(SQL文実行)→「**fetch**」OR「**fetchAll**」(実行データ取得)
- 概要だけでも理解していると違うかも？人に説明ができるまで落とし込みたいです。
[UE5] UE5.2以降、EditorUtilityWidgetがエディタ実行中に動作しなくなった時に確認すべきこと ( Is Enabled in PIE プロパティ )

# はじめに
UE5.2から、**『デフォルト設定では』エディタ実行（PIE）中はEditor Utility Widget（EUW）が無効状態になる**仕様になりました。

これは、**UE5.2から EUWでもBreakPointによるデバッグがサポートされるようになった**のですが、それによりゲーム側のBreakPointとEditorUtility側のBreakPointがPIE中に混在することによる問題に対しての対策として追加された仕様です。

しかし、PIE中にEUWから各パラメータを変更したいケースでこの挙動は非常に困ります。

# PIE中でもEUWを動作させる方法
そこで用意されたのが、EUWのClass設定にある**Is Enabled in PIE** プロパティです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/363889/725e1c3b-7b29-9165-e543-e05a90906d19.png)
```cpp:\Engine\Source\Editor\Blutility\Classes\EditorUtilityWidgetBlueprint.h
UCLASS()
class BLUTILITY_API UEditorUtilityWidgetBlueprint : public UWidgetBlueprint
{
...
private:
	// Should the widget be enabled when running PIE
	UPROPERTY(Category = Settings, EditDefaultsOnly)
	bool bIsEnabledInPIE = false;

	// Should the widget be enabled when debugging BP
	UPROPERTY(Category = Settings, EditDefaultsOnly)
	bool bIsEnabledInDebugging = false;
...
```

こちらを有効にすると、UE5.1以前と同様にPIE中でもEUWが有効になります。また、その下にある **Is Enabled in Debugging** も有効にすると、PIE中かつBreakPointで停止している間もEUWが機能するようになります。

ただし、EUWでもBreakPointを使っている場合は意図せぬ挙動が発生したり、ゲーム側とEditorUtility側とで交互にBreakPointが反応したりとデバッグ作業の支障になる可能性があります。そのため、必要に応じて適宜これらのフラグをONOFFするのが良いかと思います。

ちょっとした内容でしたがご参考になれば幸いです。
おしまい
GitHubでリポジトリの設定を見ていたら 環境変数（Environment variables）なるものが追加されていたので使ってみた

自作しているAPIのデプロイ周りを変えようとしていましたら、なんか`Environment variables` ってものが追加されていたので使ってみました

GitHub > リポジトリ > Settings > Environments の中にある環境変数です
GitHub Actionsとかで使えるあれです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674343/38735cb1-c84d-22cc-5283-ee69286453ef.png)

何の参考にもならないと思いますが、テストで作ったリポジトリはこちらです

https://github.com/chihiros/ga-trial-env-secrets


### シークレット と 環境変数 にはこんな値を設定しています
| Environment secrets | Environment variables |
| --- | --- |
| ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674343/873595de-14ff-0972-5aec-84bb8e2665aa.png) | ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674343/2d6c9bd5-6ad8-6c2f-f188-6816d00f0238.png) |

### actionsの実行ファイル
```yml
name: Environment の secrets と variables の違いを見るテスト
on: push

env:
  THIS_IS_ENVIRONMENT_SECRETS: ${{ secrets.THIS_IS_ENVIRONMENT_SECRETS }}
  THIS_IS_ENVIRONMENT_VARIABLES: ${{ vars.THIS_IS_ENVIRONMENT_VARIABLES }}

jobs:
  echo:
    runs-on: ubuntu-latest
    environment: PROD

    steps:
      - name: THIS_IS_ENVIRONMENT_SECRETS の 値を表示
        run: echo ${THIS_IS_ENVIRONMENT_SECRETS}

      - name: THIS_IS_ENVIRONMENT_VARIABLES の 値を表示
        run: echo ${THIS_IS_ENVIRONMENT_VARIABLES}

```

環境変数（`Environment variables`） を取得する場合は、`vars.***`を使って参照するみたいです

https://docs.github.com/ja/actions/learn-github-actions/contexts#vars-context

### GitHub Actionsを実行してみた結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674343/6a63f880-8703-6c79-142a-79797970fb70.png)

| 結果 | | 
| --- | -- |
| Environments secrets | 値がマスクされる（＊＊＊） |
| Environments variables | 値がそのまま表示される |

### まとめ
- secrets はGAで利用しても値はマスクされるみたいです（前々からですね）
- variables はGAで利用する場合でも値はそのまま表示されるみたいです  
また、環境変数の方は設定されている値を設定画面からも確認することが出来るみたいです

Publicリポジトリで開発している場合ですと、AWSやGCPのトークンが見えてしまうのは問題ですが
Privateリポジトリ（とくに会社や組織）で開発している場合ですと、secretsで登録したやつは値が見えないため、別途社内Wikiとかにシークレットの内容を記載しているなら、variablesを使ってみるのもありかもしれません

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/674343/ee4057a8-e398-ee2c-0c0a-8787c51ae02c.png)
[AWS Q&A 365][SES]AWSのよくある問題の毎日5選 #63

# 1. Amazon Simple Email Serviceの価格モデルは何ですか？
A: Amazon SESの価格は、送信されたメールの数に基づいており、最初の62,000通のメールは無料で、その後の追加のメールは1通あたりの料金が適用されます。

# 2. Amazon SESには追加費用が関連していますか？
A: 専用のIPアドレスやVirtual Deliverability Managerのような機能を使用するための追加費用が発生する場合があります。ただし、これらはオプションであり、コストを管理するために管理できます。

# 3. Amazon SESを使用するための費用をどのように計算しますか？
A: Amazon SESの使用コストは、送信されたメールの数と使用した追加の機能に基づいて計算することができます。Amazonはコストを見積もるための価格計算ツールを提供しています。

# 4. Amazon SESを使用するための最低料金はありますか？
A: いいえ、Amazon SESを使用するための最低料金はありません。ユーザーは、送信したメールと使用した追加の機能に対してのみ支払います。

# 5. 大量の送信者に利用可能な割引はありますか？
A: はい、Amazonは大量のメールを送信する顧客に対してボリュームベースの割引を提供しています。これらの割引は、Amazon SESチームに連絡することで適用することができます。
[AWS Q&A 365][SES]Daily Five Common Questions #63

# 1. What is the pricing model for Amazon Simple Email Service? 
A: Amazon SES pricing is based on the number of emails sent, with a free tier for the first 62,000 emails per month and then a per-email fee for additional emails. 

# 2. Are there any additional costs associated with Amazon SES? 
A: There may be additional costs for using features such as dedicated IP addresses or Virtual Deliverability Manager. However, these are optional and can be managed to control costs. 

# 3. How do I calculate my costs for using Amazon SES? 
A: The cost of using Amazon SES can be calculated based on the number of emails sent and any additional features used. Amazon provides a pricing calculator tool to estimate costs. 

# 4. Is there a minimum fee for using Amazon SES? 
A: No, there is no minimum fee for using Amazon SES. Users only pay for the emails they send and any additional features they use. 

# 5. Are there any discounts available for high-volume senders? 
A: Yes, Amazon offers volume-based discounts for customers who send large volumes of emails. These discounts can be applied by contacting the Amazon SES team.
GitHubにリポジトリ作成から任意のファイル等をプッシュするまで

# 概要
GitHubでリポジトリ作成して最初のファイル等をプッシュするまでの備忘録です

# 手順
### 1. GitHubでリポジトリ作成する
[こちら](https://docs.github.com/ja/get-started/quickstart/create-a-repo)を参照

### 2. 初期化
```
git init
```

### 3. Git管理の対象に入れるファイルを指定する
```
git add xxxx
```
またすべて指定する場合は下記
```
git add .
```

### 4. コミットメッセージを書く
```
git commit -m "何かしらのコメント"
```

### 5. リモートを追加
```
git remote add origin リポジトリのURL
```

### 6. 現在のブランチの名前を master に強制的に変更
```
git branch -M master
```

### 7. プッシュする
```
git push -u origin master
```
iTerm2を使う上で実施した設定（プロンプト_ログ_デフォルトディレクトリ_ウィンドウサイズ_色_カーソル単語飛ばし）

# はじめに
iTermを使う上で実施した設定をまとめていく
順次更新
# 実現できる状態
1. 常に指定したディレクトリで起動される
1. iTerm2のLogが指定したディレクトリ配下に保存される
1. プロンプトの表示とサイズがいい感じになる
1. カーソル移動を単語単位で飛ばせるようになる
![Image 2023-05-23 at 12.50.53 AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/1c597954-83af-bb6a-6407-054e2c7c5ed6.jpeg)
# 設定
## 1. 初回起動時のディレクトリ指定
### モチベーション
毎回ディレクトリを移動するのは面倒なので、iTerm立ち上げ時に常に指定したDirectoryから起動するようにする
### 設定方法
iTerm2 > Settings > Profiles > General
Working Directory
"Directory"を選択し、初回起動時に立ち上げたいディレクトリパスを記載
![Image 2023-05-23 at 12.35.20 AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/09ebc230-6d4f-f243-a761-bba77acb1ac6.jpeg)

## 2. iTermのLog出力
### モチベーション
デフォルトだと無効化されている
証跡、および作業内容の振り返りのために出力するようにする
### 設定方法
iTerm2 > Settings > Profiles > Session
Miscellaneous
"Automatically log session input to files in:"を選択し、ログ出力させるパスを記載
![Image 2023-05-23 at 12.17.41 AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/ff6c644c-88dc-e3bd-a515-21ef1e166a8e.jpeg)
*Log Plain Textにチェックをいれておくことで、次のプロンプトの装飾などをしても可読性のあるログが出力されていそう

## 3. プロンプトの表示変更
### モチベーション
なんか周りにいい感じのプロンプト使っている人が増えた
自分もやりたい　テンション上げたい
k8s,git,dockerなどなど、作業環境を可能な限り可視化したい
### 設定方法
下記のGetting-Startedに従い、"powerlevel10k"を設定
https://github.com/romkatv/powerlevel10k#getting-started
*1
Optionalと書いてあるが、フォントも合わせないといい感じにならない
ダウンロードしたフォントは、iTerm2 > Settings > Profiles > TextのFontで"MesloLGS NF"を選択
![Image 2023-05-23 at 12.10.23 AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/1a2be278-4fd9-a4df-2d3d-bdf57fe10f38.jpeg)
*2
```p10k configure```で、設定はやり直せる

*3
インストールパスがデフォルトだとホームディレクトリ直下になっているのでよしなに変えておくとよさそう
```zsh
git clone --depth=1 https://github.com/romkatv/powerlevel10k.git ~/powerlevel10k
echo 'source ~/powerlevel10k/powerlevel10k.zsh-theme' >>~/.zshrc
```

参考：https://namileriblog.com/terminal/iterm2/

## 4. デフォルトのウィンドウサイズ
### モチベーション
ちょっとちっちゃい
横長の方がしっくりくる
### 設定方法
iTerm2 > Settings > Profiles > Window
Setting for New Windows
```Columns:150```、```Rows:35```に設定(暫定)
設定後はこんな感じ
![Image 2023-05-23 at 12.50.53 AM.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/1c597954-83af-bb6a-6407-054e2c7c5ed6.jpeg)

## 5. ウィンドウの色
### モチベーション
複数環境扱う際に色変えたい
### 設定方法
iTerm2 > Settings > Profiles > Colors
Defaultを複製
Backgroundの色を変更　*右側のANSI Colors配下のカラーパレットで好きな色に変更し、ドラッグ&ドロップで配置すると楽です
![Screenshot 2024-01-27 at 10.31.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/99916948-b511-98a6-120b-105f06b55810.png)

頻度が増えたら自動化します
参考：https://aakira.app/blog/2018/08/terminal-bg/

## 6. 単語飛ばしでカーソルを移動
### モチベーション
historyからちょっとコマンド変えて打ったり、タイポ後にコマンド変えて打つ際に、
カーソル移動待つのいやだ
### 設定方法
iTerm2 > Settings > Profiles > Keys
Left Option key: NormalからEsc+に変更
Right Option key: NormalからEsc+に変更
![Screenshot 2024-01-27 at 9.25.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2727432/296d7337-8a94-2a8b-b36d-fc2789124255.png)

変更後は、Option+bで一単語戻り、Option+fで一単語前に飛べます

参考：https://yanagida-web.com/2023/02/06/iterm2-settings/


他にもおすすめがあれば教えてください。
Jenkinsでの環境変数設定

# Jenkinsでの環境変数設定

Jenkinsでの環境変数設定には、全体的な設定と特定のジョブでの設定の2つの方法があります。

## 全体的な環境変数の設定

これらの変数は全てのジョブに適用されます。

1. Jenkinsのメイン画面から「Manage Jenkins」を選択します。
2. 「Configure System」を選択します。
3. スクロールダウンして「Global Properties」セクションに到達します。
4. 「Environment variables」のチェックボックスを選択します。
5. 「Add」ボタンをクリックして新しい環境変数を追加します。それぞれの名前と値を設定します。
6. 変更を保存します。

## 特定のジョブの環境変数の設定

これらの変数は特定のジョブにのみ適用されます。

1. ジョブの設定画面を開きます。
2. 「Build Environment」セクションをスクロールダウンして探します。
3. 「Inject environment variables to the build process」のチェックボックスを選択します。
4. 「Properties Content」フィールドに変数を入力します。これは "KEY=value" 形式で、各変数は新しい行に配置します。
5. 変更を保存します。

> **注意:** 特定のジョブに環境変数を設定する場合、そのジョブが環境変数を受け入れるように設定されていることを確認してください。

"Inject environment variables to the build process"オプションが見つからない場合、それは "Environment Injector Plugin"がインストールされていない可能性があります。このプラグインをインストールするには以下の手順を行います。

## Environment Injector Pluginのインストール

1. Jenkinsのメイン画面から「Manage Jenkins」を選択します。
2. 「Manage Plugins」を選択します。
3. 「Available」タブを選択し、「Environment Injector」または「EnvInject」を検索します。
4. それを選択し、「Install without restart」または「Download now and install after restart」を選択します。

プラグインがインストールされた後、再度ジョブの設定ページを開き、"Inject environment variables to the build process"オプションが表示されていることを確認してください。

## その他の注意点

プラグインが見つからない場合、または使用できない場合は、パイプラインスクリプトで環境変数を設定することを検討してみてください。
ショートカットキーの仕組み

## ショートカットキーの仕組み

キーボード上の特定のキーまたはキーコンビネーションを押すことで、特定の機能や操作を素早く実行するための仕組み

::: note
ショートカットキーは、特定の機能や操作にキーバインディングが設定されている
キーバインディング：ソフトウェアやオペレーティングシステムによって管理
→ユーザーが特定のキーまたはキーコンビネーションを押すと、対応する機能がトリガーされる
また、アクセスキーを使用すると、キーボードだけでインタフェース要素を操作することもできる
:::

- キーバインディング: ショートカットキーは、特定の機能や操作に対してキーバインディング（キーと機能の関連付け）が設定されています。キーバインディングは、ソフトウェアやオペレーティングシステムによって管理され、ユーザーが特定のキーを押すと、対応する機能がトリガーされます。

- キーコンビネーション: ショートカットキーは、単一のキーだけでなく、複数のキーを同時に押すことによっても機能します。これをキーコンビネーションと呼びます。例えば、「Ctrl+C」は、コントロールキー（Ctrl）とCキーを同時に押すことで、テキストのコピー操作を実行します。

- アクセスキー: アクセスキーは、メニューやボタンなどのインタフェース要素に関連付けられたキーバインディングです。アクセスキーを使用すると、特定の要素にフォーカスを移動させることなく、キーボードだけで操作を実行することができます。例えば、メニューバーには各メニュー項目にアンダースコアで示されたアクセスキーがあり、Altキーとアクセスキーを順番に押すことでメニューを開くことができます。

- カスタマイズ可能性: 多くのソフトウェアやオペレーティングシステムでは、ユーザーがショートカットキーをカスタマイズすることができます。これにより、個々のユーザーの好みや作業フローに合わせてショートカットキーを設定できます。
redisの値を確認する方法

redisの値を確認する際に毎回ググってしまっていたので、備忘録として残します。

## キーを取得する
```redis
> keys *
1) hogeKey
2) fugaKey
3) piyoKey
> keys hoge*  //ワイルドカードも使用可能
1) hogeKey
```

## キーのタイプを取得する
```redis
> type hogeKey
```
判明したタイプによって値を確認してください

hashだった場合は
```redis
> hgetall hogeKey
```
など。
【シェルスクリプト】変数のデフォルト値を設定する方法

## `:+`
変数が定義されている場合にデフォルト値となる。
空文字の場合はそのまま。

```zsh
hoge=Hello
foo=""
 
echo ${hoge:+exist}
# exist
echo ${foo:+empty}
#
echo ${bar:+undefined}
#
```

## `+`

変数が定義されている場合にデフォルト値となる。

```zsh
hoge=Hello
foo=""

echo ${hoge+exist}
# exist
echo ${foo+empty}
# empty
echo ${bar+undefined}
#
```

## `:-`

空文字の場合と変数が未定義の場合にはデフォルト値となる。

```zsh
hoge=Hello
foo=""

echo ${hoge:-exist}
# Hello
echo ${foo:-empty}
# empty
echo ${bar:-undefined}
# undefined
```

## `-`

変数が定義されていない場合のみデフォルト値となる。

```zsh
hoge=Hello
foo=""

echo ${hoge-exist}
# Hello
echo ${foo-empty}
#
echo ${bar-undefined}
# undefined
```
昔のALMAデータのキャリブレーションでValueError: invalid literal for int() with base 10: ''が出て止まるとき

大昔のALMA観測データを解析したいことってよくありますよね。

Cycle 4以前くらいの有史以前のデータを落として`scriptForPI.py`を実行するときにはこんなエラーが出ることがあります。

```
ValueError: invalid literal for int() with base 10: ''
```

これは`scriptForPI.py`の中でディスクの空き容量を見積もる処理
```python
tmppipe = os.popen("du -smc ../* | grep total | tail -n 1 | cut -f1")
packspace = int((tmppipe.readline()).rstrip('\n'))
tmppipe.close()
```
の`os.popen()`内のduコマンドが、日本語環境下で正しくディスクの現在の使用量を返していないのが原因です。

このduコマンドは結構力ずくの処理をしていて、いったん全部の使用量を出してから最後の合計を表示している行を`grep total`で抜こうとしています。しかし、環境が日本語だと、"total"ではなくて漢字で「合計」と表示されてしまいます。従って、検索結果が空となり、数値ではなく`''`が`tmppipe`に代入されてしまい、上記`ValueError`が発生するのです。

これを応急処置的に解決するためには、`scriptForPI.py`の上のほうで
```python
os.environ["LANG"] = "C"
```
とやって、日本語への翻訳を切れば良いです。ちなみに、ちゃんと動く`scriptForPI.py`にはこれが最初から書き込まれています。

ネット上に文献が見当たらなかったのでメモ。
[初心者向け]プログラミング初学者がチーム開発する時に気をつけたいこと

## はじめに
先日[株式会社ハックツ](https://hackz.team/)さんが主催するハッカソン [ツマグロカップ](https://hackz.team/news/1Wlq1S0W8ur57mrN466hsp)に参加させていただきました。
この場を借りてこのような機会を設けていただいたことを感謝申し上げます。

そのハッカソンにおいて開発を行っている際にこれを記事にしようと思ったことがあったので、自分への戒めも含め今回記事にしました。

## PRを送る前にする5つのこと
1. 不要なコメントアウトの削除
2. 不要な標準出力の削除
3. 変更点の確認
4. ローカルビルド
5. 不要な宣言の削除

### 1.不要なコメントアウトの削除

まずは`1.不要なコメントアウトの削除`について

コメントアウトはプログラムに影響を与えない開発者が分かるように書くメモのことである。
プログラムに影響を与えないという点から、一時的なコードの無効化にも使用される。
コメントアウトを消せ！という話ではなく、あくまで不要なものを削除するべきという話である。
例えば`html`において一部要素を一時的に削除したのち、新たに要素を実装するということは多々ある。
その際に一時的に削除した要素をもう一度表示させるのか消すのかをはっきりさせなければいけない。
必要がなければ、削除する。必要ならばコメントアウトを解除し、要素として出力させる必要がある。
つまりコメントアウトを解除した場合それがプログラムに直接影響を与えるものである場合、そのままにするのではなく削除、またはコメントアウトを解除する必要がある。


### 2.不要な標準出力の削除
次に`2.不要な標準出力の削除`について

プログラムを書いていると、コードがエラーを吐く、予期した通りに動かないということは多くある。ないに越したことはないがプログラムを書いている以上ほぼ確実に起きるものなので仕方がないと言えば仕方がない。
その際になぜ動かないのかデバックするために標準出力を用いてデータの中身などをコンソールに出力することがあるだろう。
その結果、なぜ動かないのかがわかって解決!そのままマージ！！とはならない。
そのままにしてしまうと本来コンソールに出力される必要のないものまで出力することになってしまうからである。
必要ない出力は消しましょう

### 3.変更点の確認
次に`3.変更点の確認`である。

##### 3.1 作業内容の厳格化
これが今回割と大きな問題になっていた。

例えば「Headerの作成」という`issue`に対してHeaderコンポーネントを作るついでにindex.tsxに不具合が見つかったからついでに修正しようなどと言って同一issue同一ブランチでこの作業を行ってはいけない。
なぜなら作業内容は「Headerの作成」であって「index.tsxの修正」ではないからである。

個人で修正する分には構わないがそれを`commit`に含めるべきではない
修正したとしてもスタッシュしたのち、`issue`を切ってブランチを生やして作業を行おう。

##### 3.2 フォーマッター
またこれもよくあるのだが、開発者のフォーマッターの設定の違いによるコード変更である。
開発者の多くがフォーマッターを使うと思うがこれらの設定は人によって違う。
普通はプロジェクトごとにフォーマッターを設定するものだが、されてないものもある。
これによって自動フォーマットが働き編集したつもりが無いファイルでも保存によるフォーマットでコードが書き変わってしまうことがある。
自動でフォーマットされたファイルも変更点がないならば`commit`に含めるべきでは無い

### 4.ローカルビルド
次に`4.ローカルビルド`について
ビルドとは
> 「ビルド」とはソースコード上に問題がないかどうかを解析を行った上で、問題がなければオブジェクトコードに変換し、複数のオブジェクトファイルを1つにまとめて実行可能なファイルを作成する作業を指します 

引用:[コンパイル、ビルド、デプロイの違いを解説](https://cloudnavi.nhn-techorus.com/archives/2722#:~:text=%E6%8A%80%E8%A1%93%E6%94%AF%E6%8F%B4%E3%83%BB%E3%82%B3%E3%83%B3%E3%82%B5%E3%83%AB%E3%83%86%E3%82%A3%E3%83%B3%E3%82%B0-,%E3%83%93%E3%83%AB%E3%83%89%E3%81%A8%E3%81%AF,%E9%9B%86%E7%B4%84%E3%81%97%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%81%BE%E3%81%99%E3%80%82)

つまりソースコードに問題がないかを見ることを兼ねた処理である
まあビルドとは言ったが要はコードがエラーを起こさないか見るべきであるという話である。
大型のプロジェクトではCICDを組んでテストをしているものだが一応ローカルでも実行して直しておくと手間が減る。

### 5.不要な宣言の削除
最後に`5.不要な宣言の削除`である
よくありがちなのが使用していない関数などの`import`である
また削除していないスタイルの適用 `style={{}}`のような意味のないコードである。
このようなものは意味をなしていないコードなので削除しましょう。



## 結論
意味のないコード、変更は削除しましょう。
著者はプログラミングを始めて日が浅いため、何かしら間違ったことを言ってたら申し訳ありません。
また他にもこのようなことをやっておくべきだっていうことがありましたら後学のためにも是非教えていただきたいです。
MySQLにおける集計関数(SUM等)とグループ化(GROUP BY)はなにをしているのか

集計関数とグループ化はセットで
使われているのを見ますが、
どんな動きをしているのでしょうか？

イメージとして伝えますと、
集計関数は列にある全てのデータ(値)を
ギュッと1行に凝縮するものです:fist:

そして、グループ化(GROUP BY)は
絞られたものから、また分けていくイメージです:point_up:


集計関数とグループ化(GROUP BY)については
具体的な解説は今からします！

-------
<h3>集計関数とは？グループ化とは？</h3>

例えば、このような表があったとします
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113349/1e81ce81-8c92-00a0-b0c3-03522e770f59.png" width="300">

先程の表を集計関数のSUMを行うとこのようになります
これがイメージでいうギュッと1行に凝縮するものです
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113349/c8f5de89-ea03-571c-2eaf-8db03f51e8db.png" width="300">

これを以下のように部署毎にグループ化して分けると以下のようになります
```sql:
SELECT 部署名, SUM(給与) AS 合計給与
FROM テーブル
GROUP BY 部署名;
```
部署ごとに合計給与がでました
これがまたイメージでいうと絞られたものから、また分けられていますね
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113349/c7788dfd-8301-e83d-d2ad-93e7b25e2b13.png" width="400">

-----
<h4>集約関数とは</h4>
先程と同じように1行に数字が集まるものを指します:writing_hand:

:::note info
集約関数のリストはこちら
<details><summary>リスト</summary>
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3113349/790fec27-bc93-e006-fe14-4b8ade463f69.png" width="500">
</details>
:::
------

以上が集約関数とグループ化の動きになります！
OT(Operational Technology)について

# はじめに
毎週1本様々な技術に関する記事を投稿しています。
もし興味のある方は下のリンクから他の記事も見ていただければ幸いです。
 [@7_inai_](https://qiixta.com/7_inai_)

# OT(Operational Technology)とは
Operational Technologyとは、`製造業、エネルギー、交通など、様々な産業分野での運用プロセスやシステムにおける技術の利用`を表します。

# OTセキュリティ
OTセキュリティとは、__OTシステムの安全性を確保するための対策__ を指します。OTシステムは、重大なインフラ設備や、製造業における生産プロセスに使用されているため、もしも停止した場合は、__社会全体や企業に対して重大な被害__ を与えます。また、以前までの産業システムは、インターネットや社内LANから切り離されていたため、システム内のみで完結するクローズドな状態でした。しかし、__IoTやクラウド技術の発達により、産業システムで取得したデータをクラウドに送る__ ことが一般的となりました。そのため、外部からの不正アクセスに備えたセキュリティ対策が必要となり、OTセキュリティは注目されるようになりました。

# OTの活用事例
- 製造業
生産ラインの自動化や制御、品質管理、在庫管理など、生産プロセス全体の効率性と品質向上を実現します。
- エネルギーおよび公益事業
電力供給や水道処理、ガス供給などのインフラストラクチャの監視と制御に活用されます。
- 交通および物流
交通制御システムや物流管理システムにOTが活用されます。交通信号の制御、道路監視カメラの遠隔監視、運送ルートの最適化、輸送トラブルの早期検知などに役立ちます。

# 終わりに
OTは前述した通り、産業分野において重要な役割を果たしていますが、セキュリティの重要性も忘れてはなりません。適切なセキュリティ対策を講じながら、効率性向上や品質管理、安全性確保などのメリットを最大限に活かし、持続可能な産業社会の実現に向けて進んでいきましょう。

最後までお付き合いくださりありがとうございました。
Forgejoをwsl上のdocker-composeで動かす

# Forgejoとは
freeで使える軽量なセルフホスト型のフォージソフトウェア
平たく言えばgiteaの派生。


# 参考
- （公式サイト）https://forgejo.org/
- https://codezine.jp/article/detail/17071
- https://blog.css-net.co.jp/entry/2023/04/26/135209

# 前提
- windowsPCを使うこと。
- windowsPCにWSLをインストールしておくこと
- dockerをあらかじめインストールすること


# Forgejo実行
docker-composeを書いて、実行するまでを記す。
wsl上で下記のコマンドを実行して、```docker-compose.yml```を作成する

```bash
mkdir forgejo
cd forgejo
touch docker-compose.yml
```
何らかのテキストエディタで```docker-compose.yml```を開く
中身はgiteaのものをベースにして作ればOK。例えば下記。

```yaml
version: "3"

networks:
  gitea:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:1.19.3-0
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
      - GITEA__database__DB_TYPE=postgres
      - GITEA__database__HOST=db:5432
      - GITEA__database__NAME=mydb # 適宜修正
      - GITEA__database__USER=myuser # 適宜修正
      - GITEA__database__PASSWD=mypassword # 適宜修正
    restart: always
    networks:
      - gitea
    volumes:
      - ./dddd:/data # 適宜修正
    ports:
      - "xxxx:3000" # 適宜修正
      - "yyyy:22"   # 適宜修正
    depends_on:
      - db

  db:
    image: postgres:14
    restart: always
    environment:
      - POSTGRES_USER=myuse # 適宜修正
      - POSTGRES_PASSWORD=mypassword # 適宜修正
      - POSTGRES_DB=mydb # 適宜修正
    networks:
      - gitea
    volumes:
      - ./postgres:/var/lib/postgresql/data

```

パスワードとかユーザ名は適宜変える。見てわかる通り、DBにはpostgresを使っている
書き終えたら下記を実行

```bash
docker compose up
```
フロントグラウンド処理になるのでバックグラウンドで動かしたいなら``-d```オプションをつける
最初はちゃんと動いているのを確認するためにオプションはつけないほうがいいかも？

```accept connection```が表示されればOK
ブラウザで下記URLにアクセスしたら表示される
```
http://localhost:xxxx
```

初期設定画面が表示されるが、特にいじらなくていい。
「forgejoをインストール」をクリックしてしばらく待つ。
インストールできれば、アカウント登録して利用したらいい。


# ポート設定
localで使う分には設定がいらないが、lan内から使うにはポートの設定が必要。
主に下記の2つ

- WSLのポートフォワーディング設定
- windowファイアーウォール設定

## wslのポートフォワーディング設定

wsl上で下記を実行する。
```bash
ifconfig
```
eth0のネットワークにwslのipアドレスがあるので記憶しておく。
次に、パワーシェルを管理者として開き、下記を実行する。

```powershell
netsh interface portproxy add v4tov4 listenport="windowsのポート" connectport="WSLのポート(forgejoのポート)" connectaddress="wslのipアドレス"
```

下記を実行して、設定が反映されていればOK

```powershell
netsh interface portproxy show all
```


## windowsファイアーウォール設定

https://pc-karuma.net/windows-10-firewall-open-port/
OpenCALMをGoogleColabでfine-tuningする

# 概要
OpenCALMを[tloen/alpaca-lora](https://github.com/tloen/alpaca-lora)でファインチューニングします。
`finetuning.py`をそのまま実行するとエラーが出るので、LlamaForCausalLM、LlamaTokenizerをそれぞれAutoModelForCausalLM、AutoTokenizerに書き換えるとうまくいきます。

その他、全体的なやり方は以下を参考にさせていただきました。
[CyberAgent社の日本語LLM OpenCALMの対話モデル用途のfinetune検証](https://tech.acesinc.co.jp/entry/2023/05/19/181407)

2023-05-23 追記：
おそらく以下リンクの方法のほうがよさそうです。本記事の方法は学習に時間がかかりすぎる上、結果も微妙なので。ハイパラの問題かもですが...
https://twitter.com/niw/status/1660126333962452992?s=20

# 環境
GoogleColab (Pro) A100
# 手順
## 準備

google driveをマウントします。必須ではありませんが、ランタイム切断に伴う学習結果の意図せぬ削除を防ぐため、学習結果はMyDrive下に保存することを勧めます。

```
from google.colab import drive
drive.mount('/content/drive')
```

alpaca-loraリポジトリをクローンします。

```
!git clone https://github.com/tloen/alpaca-lora.git
```

フォルダに移動してライブラリをインストールします。

```
%cd /content/alpaca-lora
!pip install -r requirements.txt
```

モデル名と出力フォルダを定義します。

```
OUTPUT_DIR = "../drive/MyDrive/calm-lora-alpaca" #generate.pyの引数に指定するときに相対パスでないとエラーになる
MODEL = 'cyberagent/open-calm-7b'
```

## 学習

`finetune.py`の中のライブラリ名を書き換えます。OpenCALMはLlamaのモデルやトーカナイザに対応していないため、書き換える必要があります。

```
!sed -i 's/LlamaForCausalLM/AutoModelForCausalLM/g' finetune.py
!sed -i 's/LlamaTokenizer/AutoTokenizer/g' finetune.py
```

実行します。
教師データに[kunishou/databricks-dolly-15k-ja](https://github.com/kunishou/databricks-dolly-15k-ja)を使っています。

```
!python finetune.py \
    --base_model $MODEL \
    --data_path 'kunishou/databricks-dolly-15k-ja' \
    --output_dir $OUTPUT_DIR \
    --lora_target_modules ['query_key_value'] \
    --add_eos_token True
```

モデルのダウンロード後、学習が始まるところまでエラーなく実行できれば成功です。

## 生成

`generate.py`を使います。
`finetune.py`同様にライブラリ名を置換します。

```
!sed -i 's/LlamaForCausalLM/AutoModelForCausalLM/g' generate.py
!sed -i 's/LlamaTokenizer/AutoTokenizer/g' generate.py
```

実行します。

```
!python generate.py \
    --load_8bit \
    --base_model $MODEL \
    --lora_weights $OUTPUT_DIR \
    --share_gradio True
```

実行後、少し待つと、gradioのリンクが生成されるので、クリックし、Webアプリ上で出力を確認することができます。

# 補足

- デフォルトのパラメータの場合、学習に5~6時間かかりました。学習終了後、うっかり放置しすぎると、ランタイムが切断されます。保存先をMyDrive下にしていない場合は学習結果が削除されるため注意してください。
- 自前データで学習させたい場合は、[kunishou/databricks-dolly-15k-ja](https://huggingface.co/datasets/kunishou/databricks-dolly-15k-ja)に倣い、`instruction` `output`にそれぞれ入力、出力を格納したjson形式のデータを用意して、`finetune.py`の`--data_path`で指定するとよさそうです。
【Mac】ローカル環境下のMySQLをアンインストールする

## はじめに
- Mac環境を前提とした内容です。
- MySQLのインストールにはHomebrewを利用しました。
- 記事中のコマンドの実行は全てターミナルで行なっています。

実行時のMacバージョン（2023/05/22時点）
```
$ sw_vers
ProductName:		macOS
ProductVersion:		13.2.1
BuildVersion:		22D68
```
## コマンド
### 注意


:::note warn
重要なデータがある場合は先にバックアップを取ってください
:::
　　
※**MySQLの停止**
```
$　mysql.server　stop
```


### HomebrewでMySQLをアンインストール



以下のコマンドを実行します。

```
$　brew unstall mysql
```
キャッシュを削除したい場合は以下も実行してください。
```
$　brew cleanup
```

### アンインストールできたかの確認

以下のコマンドを実行し、Homebrewでインストールした formula の一覧に`mysql`が無いことを確認する。
```
$　brew list
```
または、以下のコマンドを実行し`mysql`コマンドが利用できないことを確認する。
```
$　mysql --version
```
出力例： `zsh: command not found: mysql`

- - -
この時点で、**MySQLの実行ファイル**や**ライブラリ**などが削除されています。
ただし、MySQLの**データファイル**や**設定ファイル**は、上記のコマンドでは削除されません。
これらのファイルやディレクトリは手動で削除する必要があります。

### 設定ファイル等の削除

下記のコマンドは一般的なものであり、実際のパスはシステムや設定により異なる場合があります。
```
sudo rm -rf /usr/local/Cellar/mysql*
sudo rm -rf /usr/local/bin/mysql*
sudo rm -rf /usr/local/var/mysql*
sudo rm -rf /usr/local/etc/my.cnf
sudo rm -rf /usr/local/share/mysql*
sudo rm -rf /usr/local/opt/mysql*
sudo rm -rf /etc/my.cnf
```

　　
必要に応じて`find`コマンドなどを使って他の場所にMySQL関連のファイルが残っていないかを確認してください。


## おわりに
MySQLの学習用にローカルにインストールした後、Dockerを使って環境構築することに方針を変えたためアンインストールを行いました。

内容に不備がありましたら遠慮なくご指摘いただけると嬉しいです。


## 参考文献

- [macOSにHomebrewでインストールしたMySQL5.7, MySQL8.0をアンインストールする方法](https://example.com/source-article-1)
- [どうしよう！困った時のMac上のMySQLのアンインストール＆再インストール、動作確認手順](https://example.com/source-article-2)
Rustに入門したので電卓を作ってみた (その1)

## 導入

最近、Rustを使うことが多くなってきました。ので、今更ながらに勉強をはじめました。

***

## Rustで実際に開発をした感想

コンパイルが通ればそれなりに動く、というのは素敵だなぁ、と思います。その他はとりたてて感想はありません。

***

## ところで、電卓っていうと

Rustで電卓を書くというと、やはりナウなヤングは、パーサコンビネータで文法を書いてバカうけ、という感じなのでしょうか？

***

## ところで、電卓っていうと

残念ながら私はそんなことはできないので、古風なアプローチをしようと思います。

***

## hocというコマンドを知っていますか?

「UNIXプログラミング環境」という本に出てくる、結構高性能な電卓です。

*** 

## hocというコマンドを知っていますか?

「UNIXプログラミング環境」という本の中では、5回に渡って機能を追加してく作業が描かれています。

***

## hocというコマンドを知っていますか?

全く関係ないのですが、Plan9では標準コマンドで、man 1 hocにきちんと記されています。

![hoc_man_plan9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317920/e2efdd3f-ecd4-851e-bbcf-9a1d1811f5fd.png)

***

## hocというコマンドを知っていますか?

これをRustで5回に分けて作ってみようと思います。 

***

## hocというコマンドを知っていますか?

5回分のネタをゲットしたぜ！

*** 

## hocというコマンドを知っていますか?

前述の本の中では、yaccで文法が書かれているのですが、Rustでこれが書けないかなぁ、と、Rustでyaccを使う方法をググってみました。

***

## grmtoolsというのがあるのですね

クイックスタートガイドもあって最高じゃないですか!

![2023-05-22 21.43.28 softdevteam.github.io 3184bf4a1542.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/317920/9497f914-c95f-3e56-7706-4f867d4e62f0.png)

***

## とりあえずコピペして動かしてみました

デモ

***

## 「UNIXプログラミング環境」での第一回の文法は下記の通り(以下引用です)

```
$ cat hoc.y
%{
#define YYSTYPE double /* data type of yacc stack */
}
%token NUMBER
%left  '+' '-' /* left associative, same precadence */
%left  '*' '/' /* left assoc., higher precedence */
%%
list:    /* nothing */
         | list '\n'
         | list expr '\n'    { printf("\t%.8g\n", $2); }
         ;
expr:      NUMBER            { $$ = $1; }
         | expr '+' expr     { $$ = $1 + $3; }
         | expr '-' expr     { $$ = $1 - $3; }
         | expr '*' expr     { $$ = $1 * $3; }
         | expr '/' expr     { $$ = $1 / $3; }
         ;
$$
```

***

## grmtoolsとQuickstart Guideにある文法は下記の通り

```
%start Expr
%%
Expr -> Result<u64, ()>:
      Expr '+' Term { Ok($1? + $3?) }
    | Term { $1 }
    ;

Term -> Result<u64, ()>:
      Term '*' Factor { Ok($1? * $3?) }
    | Factor { $1 }
    ;

Factor -> Result<u64, ()>:
      '(' Expr ')' { $2 }
    | 'INT'
      {
          let v = $1.map_err(|_| ())?;
          parse_int($lexer.span_str(v.span()))
      }
    ;
%%
```

***

## これに、「UNIXプログラミング環境」のhocの解説の第1回と同様、MINUSを付け加えた

デモ

***

## 参考文献

1. UNIXプログラミング環境 B. Kernighan, R. Pike, (訳 石田晴久)
1. grmtoolsドキュメント https://softdevteam.github.io/grmtools/master/book/index.html

***

### とりあげたソースコード

https://www.snthtns.jp/gitea/hhh/pseudo_hoc (←自宅サーバなので、いつまであるか分からないです)

***

## ご清聴

ありがとうございました。
Kotlin勉強メモ

**「Kotlinサーバーサイドプログラミング実践開発」を読んで勉強していく過程で、気付いたことや覚えておきたいことを、後で見返すようにまとめていく。**

# 目次
* [@ラベル](#@ラベル)
* [非同期処理まとめ](#非同期処理まとめ)

## @ラベル

```kotlin
fun main() {
    val test = listOf("test1", "test2", "test3")

	test.map { it ->
    	if (it == "test2") return
        println(it)
    }

    println("end")
}
```

上記のコードの実行結果は下記のようになる。

```
test1
```

`if (it == "test2") return`で一致した場合に return をして、main 関数の処理自体を終わらせてしまっているため、`printlen("end")`が実行されることもない。

`if (it == "test2") return`で一致した処理のみを終了して、次からのループ処理は実行したいという場合には、@ラベルを使って下記のように書く。

```kotlin
fun main() {
    val test = listOf("test1", "test2", "test3")

	test.map { it ->
    	if (it == "test2") return@map
        println(it)
    }

    println("end")
}
```

```
test1
test3
end
```

<br>

## 非同期処理まとめ
### 通常の同期処理

```kotlin
fun main() {
	println("test1")
    println("test2")
}
```

```
test1
test2
```

<br>

### launch で非同期処理

```kotlin
fun main() {
	GlobalScope.launch{
        delay(1000L)
        println("test1")
    }
	println("test2")
}
```

```
test2
```

`println("test1")`の処理が 1 秒待機している間に、`println("test2")`が実行されて処理が終わってしまうため、`test1`は出力されない。

<br>

### runBlocking でスレッドをブロック

```kotlin
fun main() {
    runBlocking{
        delay(1000L)
        println("test1")
    }

	println("test2")
}
```

```
test1
test2
```

runBlocking 内の処理が終わるのを待ってから、`println("test2")`を実行している。

<br>

### runBlocking で非同期処理

```kotlin
fun main() {
    runBlocking {
        launch {
            delay(1000L)
            println("test1")
        }

        println("test2")
    }
}
```

```
test2
test1
```

runBlocking でスレッドをブロックしているため、`println("test2")`が実行された後も処理が続き`println("test1")`も問題なく実行される。

<br>

### runBlocking で非同期処理の中で同期処理

```kotlin
import kotlinx.coroutines.*

fun main() {
    runBlocking {
        val test1 = async {
            delay(2000L) //2秒待機
            "test1" //返り値
        }

        // test1の処理中に非同期的に処理を行う
        println("test2")

        // test1の処理が終わるのを待つ
        val result = test1.await()

        println(result)


        println("test3")

    }

    println("test4")
}
```

```
test2
test1
test3
test4
```

runBlockin 内では基本的に非同期で処理が行われる。  
そのため、test1 の処理中に先に`println("test2")`が実行される。  
ただし、`val result = test1.await()`の部分で test1 の処理が終わるのを待っているため（同期処理）、`println("test3")`が実行されるのは、`test1`が出力された後になる。

<br>
今後も更新予定...
Object Tracking 物体追跡

# 簡単に動画内の物体を追跡
![May-22-2023 22-08-05.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/235259/ba963913-12b3-6389-678d-a2fbcbc02523.gif)
動画や連続した画像内の物体を追跡して、物体の連続性を認識できるObjectTracking。
簡単に使えます。

(Object Detectionが各フレームに対して)

# 使い方　yolov8_tracking
以下のリポジトリを使います。
https://github.com/mikel-brostrom/yolov8_tracking

インストール

```shell
git clone https://github.com/mikel-brostrom/yolov8_tracking.git
cd yolov8_tracking
pip install -r requirements.txt  # install dependencies
pip install boxmot
```

実行

```shell
python examples/track.py --source penguin.mp4 --save --yolo-model yolov8n.pt
```

🐣
****
フリーランスエンジニアです。
AIについて色々記事を書いていますのでよかったらプロフィールを見てみてください。

もし以下のようなご要望をお持ちでしたらお気軽にご相談ください。
AIサービスを開発したい、ビジネスにAIを組み込んで効率化したい、AIを使ったスマホアプリを開発したい、
ARを使ったアプリケーションを作りたい、スマホアプリを作りたいけどどこに相談したらいいかわからない…

いずれも中間コストを省いたリーズナブルな価格でお請けできます。

お仕事のご相談はこちらまで
rockyshikoku@gmail.com

機械学習やAR技術を使ったアプリケーションを作っています。
機械学習／AR関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
[GitHub](https://github.com/john-rocky)
ChatGPTと一緒に学ぶ: Flaskの動作原理と簡単なWebアプリ作成

Flaskは、PythonでWebアプリケーションを開発するための機能を提供する。

今回は、Flaskを使用して2つのパラメータを受け取り、それらを足し算するシンプルなWebアプリケーションの作成を通じて、Flaskの動作原理を学んでいく。

Webアプリケーションの実装はchatGPTに書いてもらった。

## Flaskをインストール
まず、Flaskをインストールする。ターミナルで以下のコマンドを実行する。
```python
pip3 install flask
```

## アプリケーションの作成
次に、VSCodeなどのエディタを開き、新しいPythonファイル（例: app.py）を作成する。

app.py:
```Python
from flask import Flask, request

app = Flask(__name__)

@app.route('/add')
def add():
    num1 = request.args.get('num1')
    num2 = request.args.get('num2')

    if num1 is None or num2 is None:
        return "Please provide both num1 and num2 parameters.", 400

    try:
        num1, num2 = int(num1), int(num2)
    except ValueError:
        return "Both num1 and num2 need to be convertible to integers.", 400

    result = num1 + num2

    return f"The sum of {num1} and {num2} is {result}."

if __name__ == '__main__':
    app.run()

```
 /addというURLパスを持つルートを定義している。このルートでは、URLパラメータとしてnum1とnum2を受け取り、それらを足し算して結果を返す処理を行う。また、URLパラメータが提供されていない場合や、整数として解釈できない値が提供された場合のエラーハンドリングも行っている。
 
## アプリケーションの起動
次に、ターミナルで以下のコマンドを実行してアプリケーションを起動する。
```shell
python app.py
```
これでローカルのポート5000でFlaskアプリケーションが実行さレル。Webブラウザを開き、http://localhost:5000/add?num1=3&num2=5 というURLにアクセスすると、 The sum of 3 and 5 is 8 という結果が表示される。

## ここで行った手順はFlaskの動作原理を理解するのに重要である：

1. サーバの起動: Flaskアプリケーションを実行すると、app.pyというファイル内で定義されているappオブジェクトが作成される。app.run()メソッドを呼び出すことで、Flaskサーバが起動し、指定されたポート（デフォルトでは5000）でリクエストを待ち受ける。

2. ルーティングの設定: @app.route('/add')というデコレータを使用して、/addというURLパスを受け取るルート（エンドポイント）を設定する。このルートにアクセスされると、add()関数が呼び出される。

3. リクエストの処理: クライアントからのHTTPリクエストがサーバに到達すると、Flaskはそれを解析する。この例では、/addにアクセスする際にURLパラメータnum1とnum2を指定することで、クライアントは2つの数値をサーバに送信する。

4. ビューの実行: リクエストが受け取られると、Flaskはルートにマッチするビュー関数であるadd()関数を実行する。この関数では、requestオブジェクトを使用してURLパラメータの値を取得し、数値として変換する。こ値が提供されていない場合や、整数として解釈できない場合のエラーハンドリングも行う。

5. レスポンスの生成: num1とnum2の値を足し算し、結果を含むレスポンスを生成する。

6. クライアントへのレスポンス: Flaskはビュー関数が返したレスポンスを受け取り、それをHTTPレスポンスとしてクライアントに送信する。この例では、この例では、ブラウザにはThe sum of 3 and 5 is 8と表示される。

Flaskの動作原理は、ルーティングの設定から関数の実行、レスポンスの生成、そしてクライアントへのレスポンス送信という一連の流れから成り立っている。これらの基本を理解することで、さまざまなWebアプリケーションの開発に取り組むことが可能になる。今回のような簡単な例から始めて、少しずつ複雑なアプリケーションへと挑戦していきたい。
VSCode prettierの設定～自分用メモ

# はじめに
VSCodeは便利な拡張機能がたくさん公開されている。
prettierもそのひとつだ。prettierがあれば自動でコードをきれいな形に整形してくれる。
今回はprettierの設定をいくつか自分用にまとめてみる。

# Default Formatterの設定

OSがWindowsなら、VSCodeでドキュメントを開いている状態で右クリックすると、
「ドキュメントのフォーマット」が選択可能になっていると思う。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/ba72e9bb-1c27-27fc-3666-b3c5f0e4b97b.png)

ただ、デフォルトのフォーマッタを設定していないと、以下のようにフォーマッタの選択が表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/98a7293a-864e-e166-4ca7-cb9f91d77300.png)

いちいち選択するのも利便性に欠ける。
なので、デフォルトのフォーマッタを設定しておく。

## 手順

1.ファイル＞ユーザー設定　から「設定」を開く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/30d888e9-9ad3-4af8-2196-752db16997d1.png)

2.検索欄に「default formatter」と入力する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/6666c3ce-a1d7-87d0-ef4f-66b45917d52b.png)

3.候補から「Prettier - Code formatter」を選択する
これでデフォルトのフォーマッタをprettierに設定することができた！

# Format On Save を有効にする

保存時にドキュメントをフォーマットするように設定する。
この設定を行うことで、ctrl + Sすれば勝手にコードを整形してくれるようにできる。

## 手順

1.「Default Formatterの設定」と同様の手順で、
　　設定の検索欄を表示させてから「Format on Save」と検索、チェックを入れる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/a983dbb7-0049-8e46-d300-84cee39e4df7.png)


# (その他)WhiteSpaceの設定

prettierの設定っていうわけじゃないけど、WhiteSpaceもコードの見やすくしてくれそうなので設定する。

## 手順

1.「Default Formatterの設定」と同様の手順で、
　　設定の検索欄を表示させてから「whitespace」と入力、「all」を選択する。
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3365366/34e17874-be36-73b7-4557-42724655570d.png)

※1 allにすると常に半角スペースがdotみたく表示される
※2 Defaultはselected。選択時のみ半角スペースをdotみたく表示させる。~~見にくいから嫌い~~


・・・便利な設定やら勉強したときの気づきがあったらまたまとめていこうと思う
HaskellでHelloWorldプログラムを実装してみた

# 概要
HaskellでHelloWorldプログラムを実装してみました。以下のページを参考にしました。

https://www.tohoho-web.com/ex/haskell.html

# プログラム作成
以下の通りソースコードを記述しました。
```hello.hs
main = putStrLn "Hello World!"
```

# コンパイル
以下のコマンドを実行しました。
```
$ ghc hello.hs 
[1 of 1] Compiling Main             ( hello.hs, hello.o )
Linking hello ...
```

# プログラム実行その１
以下のようにコマンドとして実行することができます。
```
$ ./hello 
Hello World!
```

# プログラム実行その２
以下のようにソースコードをそのまま実行することもできます。
```
$ runghc hello.hs 
Hello World!
```

# まとめ
何かの役に立てばと。
[Flutter]TextFieldを２行に指定する方法

![Group 51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/672609/e09b7fc5-67fa-d96b-27d3-d4f714335198.png)




こんにちわ。

今日も元気に記事を書いていきます。基礎固めをしたいと思い、Flutterの基礎を勉強し始めています。

さあ、今回は個人開発で役立った方法を紹介します。

# 主題

TextFieldを使っていると１行のみに制限したい場合や、複数行にしたい場合があります。

- １行のみにしたい場合
- 複数行にしたい場合

この２つはとても簡単です。以下に例をご紹介します。

#### １行のみのTextField

```dart
const TextField(
  maxLines: 1,
),
```

#### MaxLinesを２行に設定した
- maxLinesを２にしたのに、３行以上になってしまう？？
- 理由は現在解明中(理由を知っている方がいたら教えてください！)

```dart
const TextField(
  maxLines: 2,
),
```

# 本題

#### ２行に指定する方法

２行にしたい場合は、ちょっとした工夫が必要になります。
以下が工夫したコードとなります。

```dart
TextField(
  maxLines: 2,
  inputFormatters: [
    TextInputFormatter.withFunction(
      (TextEditingValue oldValue, TextEditingValue newValue) {
        int numLines = '\n'.allMatches(newValue.text).length;
        if (numLines > 1) {
           return oldValue;
        }
        return newValue;
      },
    ),
  ],
 ),
```
# 解説
このコードの解説の前にやりたいことを挙げてみます。
- TextFieldを２行以上にしたい
- TextFieldが３行になったときに、２行になるように修正したい。

```dart
//ユーザーがTextFieldに入力する内容を制御するためのフォーマッター
TextInputFormatter.withFunction(
  //oldValue・・・変更前のテキスト　
  //newValue・・・ユーザーが入力しようとしているテキスト
  (TextEditingValue oldValue, TextEditingValue newValue) {
    //TextFieldの改行数をカウントしている。
    int numLines = '\n'.allMatches(newValue.text).length;
    //ユーザーが入力しようとしているテキストが２行以内である場合は、oldValueのまま
    if (numLines > 1) {
      return oldValue;
    }
    return newValue;
  },
),
```

どうでしょうか？僕なりに解説をしてみました。言葉で解説すると、
<b>
１、変更前のテキスト(oldValue)とユーザーが入力しようとしているテキスト(newValue)を比較する。
２、ユーザーが入力しようとしているテキストの改行数をカウントする
３、改行数が３行以上であれば、oldValueのままにする。
４、改行数が２行以内であれば、newValueの値になる。
</b>

ということです。



# 最後に
Widgetひとつとっても、調べれば調べるほど深いですね。面白い。
全然知らなかったのでとても勉強になりました。

少しでもいいUIができればいいなと思います。いいFlutterライフを送りましょう。


# アプリの宣伝

#### アプリ名

### 「大喜利メーカー」

#### アプリの概要
- 一本グランプリ風の画像を自由に生成することができる
- 自分の考えたお題を投稿することができる
- 文字の位置や大きさを自由自在に変更することができる

iOSのリンク

https://apps.apple.com/jp/app/%E5%A4%A7%E5%96%9C%E5%88%A9%E3%83%A1%E3%83%BC%E3%82%AB%E3%83%BC/id1591916858

Androidはリリースするの忘れていたので、後日リリース予定です。
テーブル設計の方法

## テーブル設計の目的
- データの冗長性を排除して、使用すすデスクスペースを減らす
- テーブル内のデータの正確さを維持する
- 適切にテーブル分割して、効率的にアクセスできるようにする

## データ中身アプローチ(DOA)とは
システム設計の考え方の一つ。まずどういうデータを利用するのかを洗い出す。次にどのようにデータを扱うのかを考えて処理を書き出すアプローチ

### データ型

#### 文字列型
- CHAR(固定長文字列)　あらかじめ格納するデータの領域が固定で確保される
- VARCHAR（可変長文字列）データに応じて確保されるディスク領域を調整する
- TEXT VARCHARで格納できないサイズの文字列を格納する。＊インデックスを作成することができない。

文字列の長さが固定されている場合（電話番号、社員番号）にはCHAR型を用いる。主キーとして用いる　、それ以外はVARCHAR
「TEXTを使う場合」VARCHARでは扱えない大容量のデータを格納する場合(65535以上)、絞り込みに利用しない

#### 整数型　＊UNSIGNEDをつけると正の値のみ扱う
- TINYINT -128~127
- SMALLINT -32768~32767
- MEDIAMINT -8388608~8388608
- INT -2147483648~2147483648
- BIGINT それ以上

#### 浮動小数型 実数を扱う。**近似値を扱われ、数値が大きくなると正確な値にならない**
#### 固定小数型　正確な浮動小数を扱う
DECIMAL(5,2)整数部と少数部を合わせて5桁、少数部が2桁

*データ数が大きいと使用する型によってデータ容量が全く変わってくるので、気をつける必要がある。

①金融系のシステムなどで正確な値が必要な場合はDECIMAL
②WHEREで比較を行うカラムではDECIMAL
③概算地でのデータ容量を抑えたい場合は、FLOAT,DOUBLE

#### 日時型
- DATE　日付を扱う。時刻のない日付のみのデータを挿入したい場合に用いる
- TIME 時刻を扱う、日付のない時刻のみのデータを挿入したい場合に用いる。
- DATETIME 日付と時刻を扱う。正確な日付と時刻を扱いたい時
- TIMESTAMP 日付と時刻を扱う。データ容量がDATETIMEより若干少ない

＊TIMESTAMPはレコードの挿入時刻や更新時刻を記述するカラムに使用される。デバックする際に非常に便利

### テーブル定義のコツ
- 主キーは必ずつける。主キーには数値型(INT型)または固定長文字列(CHAR)を用いる
- レコードが挿入された時刻を表す（create_at)とレコードが変更された時刻を表す(update_at)は必ずつける
- 文字列型や数値型は大きすぎる値を設定しない
- カラムの制約、デフォルト値、コメントはきちんとする
制約やデフォルト値、コメント文の記述はきちんとする。
Ansibleでユーザ作成

ユーザ作成コマンド
```
ansible-playbook -i 192.168.2.180, useradd_playbook.yml
```

useradd_playbook.yml

```
---
- hosts: all
  become: yes
  tasks:

  - name: previous 'cat /etc/passwd'
    shell: cat /etc/passwd
    register: before_result_passwd

  - name: show previous 'cat /etc/passwd'
    debug:
         msg: "{{ before_result_passwd }}"

  - name: previous 'cat /etc/group'
    shell: cat /etc/group
    register: before_result_group

  - name: show previous 'cat /etc/group' stdout
    debug:
         msg: "{{ before_result_group }}"

  - name: previous 'cat /etc/shadow'
    shell: cat /etc/shadow
    register: before_result_shadow

  - name: show previous 'cat /etc/shadow' stdout
    debug:
         msg: "{{ before_result_shadow }}"

  - name: Add user 'example-user'
    ansible.builtin.user:
      name: test001
      group: googoo
      groups: ihs,was
      shell: /bin/bash
      password_lock: yes
      home: /home/test001
      uid: 10400
      password_lock: true
      password: "{{ 'P@ssw0rd' | password_hash('sha512') }}"

  - name: chage user 'chage'
    command:
         cmd: chage -M 28 -W 7  test001

  - name: chage user 'chage1'
    shell: chage -l test001
    register: result

  - name: show previous shell stdout
    debug:
         msg: "{{ result }}"

  - name: execute shell
    shell: cat /etc/passwd | grep test001
    register: return_from_shell
    changed_when: no

  - name: show previous shell stdout
    debug:
         msg: "{{ return_from_shell.stdout }}"

  - name: after 'cat /etc/shadow'
    shell: cat /etc/shadow
    register: after_result_shadow

  - name: show after 'cat /etc/shadow' stdout
    debug:
         msg: "{{ after_result_shadow }}"

  - name: after 'cat /etc/passwd'
    shell: cat /etc/passwd
    register: after_result_passwd

  - name: show after 'cat /etc/shadow' stdout
    debug:
         msg: "{{ after_result_passwd }}"

  - name: after 'cat /etc/group'
    shell: cat /etc/group
    register: after_result_group

 
  -  - name: show after 'cat /etc/group' stdout
    debug:
         msg: "{{ after_result_group }}"

  - name: Show the difference in yaml format
    ansible.utils.fact_diff:
         before: "{{ before_result_passwd }}"
         after: "{{  after_result_passwd }}"

  - name: Show the difference in yaml format
    ansible.utils.fact_diff:
         before: "{{ before_result_group }}"
         after: "{{  after_result_group }}"

  - name: Show the difference in yaml format
    ansible.utils.fact_diff:
         before: "{{ before_result_shadow }}"
         after: "{{  after_result_shadow }}"
```
Azure登録から始める、Azure OpenAI Serviceの使用手順

# はじめに
社内でChatGPTを組み込んだアプリを作成しようと活動をしています。
企業での利用を視野に入れるため、今回はAzure OpenAI Serviceについて調査しました。

# Azure OpenAI Service とは
OpenAIのAIモデルを、Azure経由のAPIとして利用することができるサービスです。
OpenAI API との違いとして、Microsoftが掲げる"[責任あるAI](https://www.microsoft.com/ja-jp/ai/responsible-ai?rtc=1&activetab=pivot1:primaryr6)"の原則に従った利用が可能であることが特徴となります。

> Azure OpenAI Service では、GPT-3、Codex、Embeddings モデル シリーズなど OpenAI の強力な言語モデルを REST API として使用できます。 さらに、新しい GPT-4 および ChatGPT (gpt-35-turbo) モデル シリーズがプレビューで利用可能になりました。 これらのモデルは、特定のタスクに合わせて簡単に調整できます。たとえば、コンテンツの生成、まとめ、セマンティック検索、自然言語からコードへの翻訳などです。 ユーザーは、REST API、Python SDK、または Azure OpenAI Studio の Web ベースのインターフェイスを介してサービスにアクセスできます。
[Azure OpenAI Service とは (Microsoft 公式)](https://learn.microsoft.com/ja-JP/azure/cognitive-services/openai/overview)

また、[データの取り扱い](https://learn.microsoft.com/ja-jp/legal/cognitive-services/openai/data-privacy?context=%2Fazure%2Fcognitive-services%2Fopenai%2Fcontext%2Fcontext)について確認したところ、
プロンプトなどの入力や、fine-tuningモデルへのトレーニングデータについては、AIモデルの学習に用いられることはないようです。

# 手順
1. Azure アカウント作成
2. Azure OpenAI Service へのアクセス申請
   - （必要であれば）GPT-4 への利用申請
3. モデルのデプロイ

# Azure アカウント作成
#### ＜必要事項＞
- Microsoftアカウント（取得済みでない方は[コチラ](https://www.microsoft.com/ja-jp/welcome)）
- 電話番号
- クレジットカード

#### ＜手順＞
1. [Azureアカウント作成画面](https://azure.microsoft.com/ja-jp/free/cognitive-services/?azure-portal=true)を表示します。
2. [無料で始める]をクリックします。
![Azureポータル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3447766/140db300-6067-745d-6d91-80b1ae9231a5.png)
3. Azureアカウント作成画面が表示されるので、必要事項を入力します。
![アカウント情報入力.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3447766/90ed9356-4b95-864e-65e4-cf2d6c06f454.png)
4. クレジットカードを登録します。
5. Azureアカウントの作成後、Azureポータルに移動します。
![Azureアカウント作成後.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3447766/f54a31f8-03ee-6962-2655-07db6dbc651f.png)

# Azure OpenAI Service へのアクセス申請
#### ＜必要事項＞
- Azureアカウント（サブスクリプション）
- 会社情報
  - 会社名
  - 住所
  - 郵便番号
  - Webサイト
  - 電話番号
  - 会社規模
  - 業種・業界
 
申請は[コチラ](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xUOFA5Qk1UWDRBMjg0WFhPMkIzTzhKQ1dWNyQlQCN0PWcu)から、フォームへ回答します。
承認までにどれくらい時間がかかるかは[明記されていません](https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/faq#azure-openai----------------------:~:text=%E7%8F%BE%E5%9C%A8%E3%80%81%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%89%BF%E8%AA%8D%E3%81%AE%E3%82%BF%E3%82%A4%E3%83%A0%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%AF%E6%8F%90%E4%BE%9B%E3%81%95%E3%82%8C%E3%81%A6%E3%81%84%E3%81%BE%E3%81%9B%E3%82%93%E3%80%82)でした。

# GPT-4 の利用申請
#### ＜必要事項＞
- Azureアカウント（サブスクリプション）

申請は[コチラ](https://customervoice.microsoft.com/Pages/ResponsePage.aspx?id=v4j5cvGGr0GRqy180BHbR7en2Ais5pxKtso_Pz4b1_xURjE4QlhVUERGQ1NXOTlNT0w1NldTWjJCMSQlQCN0PWcu)から。

# 利用可能なモデルと、料金について
こちらの記事で解説します。
→[Azure OpenAI Service で使用可能なモデルと料金](https://qiita.com/shmp-dev/items/ab59012738781892a08c)

# モデルのデプロイ
Azure OpenAI Service では、使用するAIモデルを事前にデプロイする必要があります。
[追記予定]

# Azure OpenAI Studio
Azure OpenAI Studio から、デプロイしたモデルを操作することが可能です。
[追記予定]
CSSの詳細度について

# はじめに

CSSを使ってウェブサイトをデザインする際には、同じ要素に対して複数のスタイルルールが適用されることがよくあります。しかし、どのルールが優先され、最終的に適用されるのでしょうか？ その答えは「詳細度（Specificity）」にあります。今回はこの詳細度について、その種類と優先順位、適用順序の原則、そして具体的な例を通じて解説します。

## 詳細度とは何か？

詳細度は、CSSのセレクタがどれだけ「具体的」で「特定の」要素を指しているかを表す数値です。高い詳細度を持つスタイルルールは、低い詳細度のスタイルルールよりも優先されます。

## 詳細度の種類と優先順位

以下に、詳細度の種類とそれらの優先順位を示します。

1. **インラインスタイル（Inline Styles）**: インラインスタイルは、要素に直接適用されるスタイルです。これが最も詳細度が高いとされています。
```html
<p style="color: red;">This is an inline style.</p>
```

2. **IDセレクタ（ID Selectors）**: IDセレクタは、HTML要素のID属性を対象にします。詳細度はインラインスタイルに次いで高いです。
```css
#myID {
    color: blue;
}
```

3. **クラスセレクタ、属性セレクタ、擬似クラス（Class Selectors, Attribute Selectors, Pseudo-classes）**: これらのセレクタは詳細度がIDセレクタよりも低いです。
```css
.myClass {
    color: green;
}

[data-attr="value"] {
    color: purple;
}

a:hover {
    color: orange;
}
```

4. **要素セレクタ（Element Selectors）**: 要素セレクタは、すべての要素（p, div, aなど）に対して適用されます。これが最も詳細度が低いとされています。
```css
p {
    color: yellow;
}
```

## 詳細度の比較と適用順序の原則

上述の詳細度の優先順位を頭に入れておくと、スタイルの適用順序を理解するのが簡単になります。

1. **詳細度が高いルールが優先される**: 

複数のルールが同一要素に対して適用された場合、詳細度が最も高いルールが優先されます。

2. **詳細度が同じ場合、後から書かれたルールが適用される**: 

同じ詳細度を持つルールがある場合、スタイルシート内で後に記述されたルールが優先されます。

## 実例による詳細度の理解

以下に具体的な例を挙げて詳細度の理解を深めます。

**実例1: クラスセレクタ vs. IDセレクタ**

```html
<p id="myID" class="myClass">Hello, world!</p>

<style>
.myClass {
    color: green;
}

#myID {
    color: blue;
}
</style>
```

上記の例では、`<p>`タグが`myClass`というクラスと`myID`というIDを持っています。クラスセレクタよりIDセレクタの詳細度が高いため、テキストの色は青色になります。

**実例2: スタイルルールの順序による適用優先度の変化**

```html
<p class="myClass">Hello, world!</p>

<style>
.myClass {
    color: green;
}

.myClass {
    color: blue;
}
</style>
```

この例では、`myClass`クラスが二度定義されています。詳細度は同じですが、後に定義された`color: blue;`が適用されるため、テキストの色は青色になります。

## さいごに

CSSの詳細度は、複数のスタイルルールが同一要素に適用された場合の優先順位を決める重要な概念です。詳細度の原則を理解しておけば、予期せぬスタイリングの問題を避けることができます。初めて学ぶときは少し複雑に感じるかもしれませんが、具体的な例を通じて練習し、理解を深めていきましょう。