OmniAICreator/Qiita-1.07M huggingface dataset:
MacでWord2Vecを使うまでの流れ(覚え書き)

Macで仮想環境を使ってWord2Vecを使うのに少しつまづいたので覚え書き
誰かのお役に立てますように


### 前提条件
・Homebrewがインストールされていること
・pipenvとmecabがインストールされていること

### データセットのダウンロード
まずは，Wikipediaよりデータセットをダウンロードする

https://dumps.wikimedia.org/jawiki/latest/

最新版である「jawiki-latest-pages-articles.xml.bz」をダウンロードして展開する

### Pythonの仮想環境構築
wikiextractorがPython3.10より後だと正規表現のルールが厳格になったためバージョンを指定して環境を構築する

```bash
pipenv install --python 3.10 wikiextractor gensim ptpython
```
### 記事ごとに文章を抽出する

```bash
pipenv run python -m wikiextractor.WikiExtractor jawiki-latest-pages-articles.xml
```
しばらく時間がかかる

<br>
<br>

完了したら出力結果を結合する

```bash
cat text/*/* > jawiki-latest-pages-articles.txt
```

### mecabを使って分ち書きを行う

```bash
 mecab -Owakati jawiki-latest-pages-articles.txt -o jawiki-latest-pages-articles.text8 -b 200000
```
これもしばらく時間がかかる
<br>
<br>
### gensimを使って単語を学習させる

```Python:train.py
import logging
from gensim.models import word2vec


def main():
    logging.basicConfig(format='%(asctime)s : %(levelname)s : %(message)s', level=logging.INFO)
    sentences = word2vec.Text8Corpus("jawiki-latest-pages-articles.text8")
    model = word2vec.Word2Vec(sentences, vector_size=200, min_count=20, window=15)
    model.save("jawiki-latest-pages-articles.model")


if __name__ == "__main__":
    main()
```

```bash
pipenv run python train.py
```
これもまた時間がかかる

### Word2Vecを使う

まず仮想環境のシェルに入る
```bash
pipenv shell
```
Ptpythonを使ってWord2Vecを使う
```bash
ptpython
```
```python
>>> from gensim.models import word2vec
>>> model = word2vec.Word2Vec.load("jawiki-latest-pages-articles.model")
>>> model.wv.most_similar(positive=["円","アメリカ"], negative=["日本"], topn=1)
[('ドル', 0.7449465990066528)]
```

### 参考文献
ラムダ技術部. “【数値化】言葉の足し算をするAIで遊んでみた.”  YouTube, 2020年11月7日,

https://youtu.be/sK3HqLwag_w?si=UooEsiJktW5Pqv1N
DDR5の異サイズ4枚刺ししてみた

# はじめに

短いですが、内容がだいぶ違うため記事を前後編に分けました
この記事は前編になります→後編は[こちら](https://qiita.com/dragoon2014/items/1ac3e7970a41636e6899)（Linuxでのお話です）
（AdCに自作PCみたいなカテゴリがあれば登録しようと思ったらがなかった、残念）

[少し前](https://misskey.fusenstage.com/notes/a1hqvvnz96)、すごい無茶な構成であることは承知な上で
メインPCにメモリをあとから追加し、
DDR5の異サイズ4枚の160GB構成にして運用していました

# 構成

主要構成だけ記載します

CPU: AMD Ryzen 7 7700X
M/B: MSI MAG B650M MORTAR WIFI
Mem: Crucial 32GB DDR5-4800 UDIMM x2
Mem（追加分）: Crucial Pro 48GB DDR5-5600 UDIMM x2
（dGPUなし）

しばらくは使えていたのですが、
メモリを食っていくとクラッシュが頻発してしまって調べた結果

![out0.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51482/47c70618-b657-9c0f-5900-0f99027a2847.jpeg)

はい、メモリエラーが出まくっていてそりゃクラッシュしますわなといった状態になっていました
ところがその後、2枚ずつ指してエラーチェックをしたところ
それぞれエラーは出なかったため相性かスロットが腐ってるのかな？と思い一旦諦めてしばらく96Gで運用していたのですが
最近改めて4枚挿しに挑戦しました

# メモリの挿し方の変更

メーカーのサイトから最新のBIOSを落として更新してみましたがあいかわらずエラーがおき、
いろいろ挿し方を変えたところ以下のような形にすることでなぜかエラーなくテストが走りきりました

```
スロットを上から見た図
NG(本来こうしたいが)     OK(こうしないと通らない)
[ 32G ]                 [ 48G ]
[ 48G ]                 [ 48G ]
[ 32G ]                 [ 32G ]
[ 48G ]                 [ 32G ]
```

デュアルチャネルを活かすため、本来はチャネルごとにメモリをペアにするべきなのですが動かないのでやむを得ません

![out1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51482/01cc4e16-7ae6-b485-c1c4-2a0102054e76.gif)

見にくいかもしれませんが、128GBを超えた領域が少しゆっくりになるという面白い挙動が確認できます
部分的にデュアルチャネルが効いているであろうことが視覚的にわかりますね
なお143Gしかないように見えますが、（無駄に最大値の）16GBをVRAMに振っているためこうなっています

後半は実際にLinuxを起動して動かしていく流れになります
Linuxに興味ない方向けにまとめると、4週間つけっぱで大体動作しました、という話です

DDR5でもちょっと問題があるものの4枚で動作できました
どうしても4枚で動かしたい、といった方は参考にしてみてください

**後編は[こちら](https://qiita.com/dragoon2014/items/1ac3e7970a41636e6899)**（Linuxでのお話です）

# おまけ1: DDR5を異種混合は危険？

なお「DDR5はメモリに電源回路があるから別ロットを混ぜると危険」といった話がよく聞かれましたが
元になったと思われるメーカーのツイートによると「JEDECに準拠していれば問題ない」との解釈がなされています
すでに元ツイートは取り下げられたようです

https://x.com/AsrockJ/status/1640690671291080707

今回使用したメモリはどちらもJEDEC準拠な認識です

# おまけ2: MSIのマザーボードで設定が保存できない問題の対処方法

https://forum-en.msi.com/index.php?threads/mag-b650m-mortar-wifi-not-able-to-save-bios-settings-in-menu-or-through-f10.388854/

私の使っているマザボはBIOSの設定をいじったあと、SSDつけっぱでは何をどうやってもほとんど保存ができない、
まれに保存できるといったよくわからない状態だったのですが
流石に毎度SSD等をつけたり外したりはしたくなかったのでいろいろ試した結果対処法がわかりました

結論から言うと、再起動直後にDEL連打ですぐにBIOSメニューに入れば保存できました

EFI環境だと、GRUB（Linuxのブートローダー）でexitをしてあげるとそのままBIOSメニューに入れるのでそのまま編集していたのですが
どうも一度ブートローダまで回ってしまうと保存が効かないといった挙動になるようです

同様の事象が起きた方は参考にどうぞ
TiDB CloudのZapier連携を試す

## はじめに

TiDB Cloudには3rd Partyツールとの連携機能があり、現時点で下記5つのサービスとの連携が可能です。

- Vercel
- DataDog
- Prometheus
- NewRelic
- Zapier

この中でメトリクスを連携するDataDogやNewRelicはよく使われますが、Zapier連携は使ったことがなかったので何ができるのか調べて使ってみました。

## Zapier連携でできること

Zapierは様々なツールを連携して一連の自動化ワークフローを作成できるツールです。イベントソースとなるサービスからイベントを受け取り、他のサービスに連携させることで様々な組み合わせを実現できます。

TiDBからのイベント発火（トリガー）と、TiDBへのイベントに応じた実行（アクション）が定義されていて、詳細は下記のドキュメントから確認できます。

https://docs.pingcap.com/ja/tidbcloud/integrate-tidbcloud-with-zapier#triggers-x26-actions

:::note warn
アクションの対象はTiDB Cloud Serverlessに限定されているようです
:::

本記事では、たまに聞かれる「TiDB Cloudで誰かがクラスタを作成したら通知してほしい」という機能を実現してみます。TiDB Cloudのトリガーとしてクラスタの作成があるので、クラスタ作成されたらメールが飛ぶようにしてみます。

## TiDB Cloud側での設定

### APIキーの作成

Zapier連携時に利用するため、APIキーを作成しておきます。`Organization Settings>API Keys`で、キーを作成し、表示されたPUBLIC KEYとPRIVATE KEYをメモしておきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/1e911288-98a6-a56e-b052-f78588ba75a1.png)


### Zapierインテグレーションの選択

`Project Settings` から Zapier連携を選択するだけです。Zapierの画面に遷移するので、アカウントの作成もしくはログインを行います。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/0ce1cb82-5b7a-d63c-053e-64c889d7ad5d.png" width="75%"/>

## Zapierの設定

Zapier側でZap(ワークフロー）の設定画面になるので設定をしていきます。図のようなZapを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/9faa5f55-726b-ebab-5f81-8bbdff6e2d30.png)


### トリガーの設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/efe8c979-8fa4-57e5-90f5-dd112547f47f.png)

- Trigger event は New Clusterを選択します。クラスタ作成するとこのトリガーが発生します
- Accountでは、TiDB CloudのAPIキーを設定します

次のConfigure画面では、トリガーの対象となるTiDB Cloudのプロジェクトを選択します。

Testで、実際にこの設定でクラスタが取得できるか確認することができます。

### アクションの設定

アクションは任意ですが、ここではEmailを使ってみました。アクションを追加する際に、`Email`で検索すると`Email by Zaiper`が選択できると思います。

Setupでは、Actionとして `Send Outbound Email` を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/0f98a80e-60d8-72ba-1f37-7205d30abf33.png)

Configureでは、メールの宛先とメール本文を設定します。メール本文では、`/`を入力することでイベントの内容を埋め込むことができます。ここでは、クラスタ名、組織id、リージョンを埋め込みました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/4515f01b-2325-5ba6-b5ca-dfd0b58e6181.png)

ここまでできたら、`Publish`ボタンを押してこのZapを有効化します。

## 実際に動かしてみる

このZapをためしてみます。指定したプロジェクトでServerlessクラスタを新規で立ち上げて、しばらくするとメールが届きます。メール本文にはクラスタ名が記載されていて正しく動作することがわかります。

今回はメールでしたが、SlackやSMSにも連携することができるので、会社で利用する際などに使えるかもしれません。（クラスタの削除のトリガーとかもほしい気がしますが）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/12495/adb4025a-df32-b752-6032-a939df933daa.png)

## おわりに

他にもデータベースが作成されたときや、データベースに行が挿入されたとき、といったトリガが設定可能です。データベースからイベントを発生させる連携は珍しいので、ぜひ色々ためしてみてください！
DDJ-FLX4のPadで「モグラたたきゲーム」を作ろう

# 目標
- Elixirでモグラたたきを作る
- PioneerDjのDDJ-FLX4を使う

# 仕様
- Pad1〜Pad8のランダムでLED点灯
- LEDが点灯したPadを押すとカウント対象
- 1Padの点灯時間は500ミリ秒
- 30回点灯する

# ソース

DDJ-FLX4のライブラリ
```elixir:lib/ddj.ex
defmodule Ddj do
  @moduledoc """
  Documentation for `Ddj`.
  """

  def led_on, do: "7F"
  def led_off, do: "00"

  def pad1, do: "00"
  def pad2, do: "01"
  def pad3, do: "02"
  def pad4, do: "03"
  def pad5, do: "04"
  def pad6, do: "05"
  def pad7, do: "06"
  def pad8, do: "07"

  def deck1, do: "97"
  def deck2, do: "99"

  def pad_list, do: [pad1(), pad2(), pad3(), pad4(), pad5(), pad6(), pad7(), pad8()]

  def open(inout \\ :output) do
    {_, output} = PortMidi.open(inout, "DDJ-FLX4 MIDI 1")
    output
  end

  def close(output, inout \\ :output) do
    PortMidi.close(inout, output)
  end

  def send_midi(v, output) do
    Enum.map(v, fn x -> hex_to_dec(x) end)
    |> List.to_tuple()
    |> then(&PortMidi.write(output, &1))
  end

  def hex_to_dec(hex), do: String.to_integer(hex, 16)

  def pad_led(output, deck, pad, led_sw) do
    [deck, pad, led_sw]
    |> send_midi(output)
  end
end

```

モグラたたきゲーム本体
```elixir
defmodule Mogu do
  @moduledoc """
  Documentation for `Mogu`.
  """
  import Ddj

  def start() do
    output = open()
    input = open(:input)
    PortMidi.listen(input, self())

    pad_randoms(output, input)
    |> Enum.count(fn x -> x end)
    |> IO.inspect()

    close(input, :input)
    close(output)
  end

  def pad_randoms(output, input) do
    1..30
    |> Enum.map(fn _ ->
      pad_random(output, input)
    end)
  end

  def pad_random(output, input) do
    no = Enum.random(0..7)

    pad_list()
    |> Enum.at(no)
    |> then(&pad_led(output, deck1(), &1, led_on()))

    ret = midi_in(input)
    pag_all_off(output)
    (ret == no)
    |> IO.inspect()
  end

  def pag_all_off(output) do
    pad_list()
    |> Enum.map(fn x ->
      pad_led(output, deck1(), x, led_off())
    end)
  end

  def midi_in(input) do
    receive do
      {^input, []} ->
        midi_in(input)

      {^input, [{{_, _, 0}, _}]} ->
        midi_in(input)

      {^input, [{{_, no, 127}, _}]} ->
        Process.sleep(500)
        no

      _ ->
        nil
    after
      500 ->
        nil
    end
  end
end

```

# 課題
`midi_in(input)`関数の`receive do`で
たまに受信データ`[]`が大量に飛んでくる

暫定で再度`midi_in(input)`関数を呼び出している
フリーズしてしまう時もある

# 動作動画

<iframe width="560" height="315" src="https://www.youtube.com/embed/IMrumMdhD8g?si=0Ndyzj3ibnBGnVRm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
【さくらのクラウド】暗号化ディスクで動作しているDBアプライアンスのベンチマーク測定をしてみる

# はじめに

こちらはさくらインターネット Advent Calendar 2024 の 7日目の記事です。

https://qiita.com/advent-calendar/2024/sakura

初めまして。バックエンドチームでDBアプライアンスのテックリードとして働いています松浦 裕哉と申します。

自分のプロフィールや働き方などは以下のインタビュー記事で色々と書いています

https://sakumaga.sakura.ad.jp/entry/rds-engineer/

# 概要

今年の6月27日にDBアプライアンスのディスク暗号化機能を提供開始しました

https://cloud.sakura.ad.jp/news/2024/06/27/db-disk-encryption/

こちらは去年リリースいたしましたさくらの「クラウドディスク暗号化機能」を用いてDBアプライアンスに紐づくディスクを暗号化することができる機能となっております

「クラウドディスク暗号化機能」に関しましては以下の記事を参照ください

https://qiita.com/jh1vxw/items/35da1610fb321048ca01

記事でも書かれていますが、[IOパフォーマンスの低下(レイテンシの増加)もほとんど発生せず、許容可能な範囲に収まることを確認されてはいます](https://qiita.com/jh1vxw/items/35da1610fb321048ca01#%E3%83%9B%E3%82%B9%E3%83%88%E3%82%B5%E3%83%BC%E3%83%90%E4%B8%8A%E3%81%A7%E3%81%AE%E6%9A%97%E5%8F%B7%E5%8C%96%E5%BE%A9%E5%8F%B7%E5%87%A6%E7%90%86%E3%81%AE%E5%AE%9F%E8%A3%85%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6)が、実際にそうなのか気になったのでベンチマークソフトを用いて実際にどの程度のパフォーマンス影響の発生を確認するというのが本記事のテーマとなります。

:::note warn
こちらの記事は執筆時点でのサービス構成による独自の検証となっております
動作を保証するものではないことをご留意ください
:::

# 準備

## 計測対象

対象のDBアプライアンスは東京第二ゾーンで作成したPostgreSQLリソースの30GBプラン、90GBプラン、240GBプランを採用します。

なぜこの3つかと言いますと、DBアプライアンスは現状、ディスク容量において紐づくVMのスペックが異なります。

https://cloud.sakura.ad.jp/products/database-appliance/

一番スペックの低い10GBとディスクの容量が非常に大きい500GB、1TBプランを排除した形となります。

## 条件やコマンドなど

下記のコマンドで各リソースごとに実施

```
SCALE=100
CLIENTS=100
TRANSACTIONS=10000

pgbench -i -s $SCALE -h $HOST -p $PORT -U $USER $NAME
pgbench -c $CLIENTS -j $CLIENTS -t $TRANSACTIONS -h $HOST -p $PORT 
```

以下のような出力になります

```
transaction type: <builtin: TPC-B (sort of)>
scaling factor: 100
query mode: simple
number of clients: 100
number of threads: 100
number of transactions per client: 10000
number of transactions actually processed: 1000000/1000000
latency average = 69.173 ms
tps = 1445.645112 (including connections establishing)
tps = 1446.064715 (excluding connections establishing)
```

また、DB側のパラメータは`max_connections`のみ`150`へ変更。それ以外はDBアプライアンスのデフォルトを利用しております。

# 結果

各テスト結果のlatency average及びtpsを表にまとめました。

| 構成 | latency average | tps (including connections establishing) | tps (excluding connections establishing) |
| ---- | ---- | ---- | ---- |
| 30GBプラン	ディスク暗号化無し | 69.173 | 1445.645112 | 1446.064715 |
| 30GBプラン	ディスク暗号化有り | 70.196 | 1424.591209 | 1425.105450 |
| 90GBプラン	ディスク暗号化無し | 31.416 | 3183.081319 | 3184.814539 |
| 90GBプラン	ディスク暗号化有り | 31.325 | 3192.378138 | 3193.853041 |
| 240GBプラン ディスク暗号化無し | 22.370 | 4470.280996 | 4471.112637 |
| 240GBプラン ディスク暗号化有り | 22.427 | 4458.848276 | 4459.651519 |

## 考察

30GBプランと240GBプランは想定通りに暗号化無しよりも暗号化有りの方がパフォーマンス低下を確認できた。
90GBプランは逆転しているため、ホストの影響などベンチマーク時に何か阻害要因があったのかなど調べたい。
いずれの結果にしても誤差範囲であることが確認できる。

# あとがき

今回はアドベントカレンダー向けの簡易計測なのでRDBMSや環境も絞った形となりますが、何かのタイミングでパターンを増やしたりベンチマーク測定方法の見直しなどを行い、より正確な検証結果を公表できればと思っております。
Babylon.jsでglTFの組み込みカメラで遊んでみよう

この記事は[Babylon.js Advent Calendar 2024](https://qiita.com/advent-calendar/2024/babylonjs)の7日目の記事です。

### はじめに

3D モデルのフォーマット glTF の仕様を策定している Khronos Group のリポジトリで多くのサンプルモデルを公開しています。

今回は glTF 1.0 の頃からある `Virtual City` モデルを使ってみようと思います。 `Virtual City` モデルは15個の組み込みカメラが設定されている興味深いモデルになります。

https://github.com/KhronosGroup/glTF-Sample-Assets/blob/main/Models/VirtualCity/README.md

### 今回の実行結果

以下は Camera Gizmo を使ったサンプルの実行結果になります。

https://playground.babylonjs.com/#P81SPG#17
![babylonjs_camera_gizmo_test_001.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26094/6b0ac8cc-2269-0caa-b348-d141afba55da.gif)

### Camera Gizmo について

Camera Gizmo はカメラの設定内容を視覚的に表示することが出来る機能です。残念ながら公式ドキュメントにサンプルが無かった為、どうやって表示するのかが疑問だったのですが最近使い方を発見しました。
使い方は簡単です。`CameraGizmo` のインスタンスを作成し `camera` プロパティに追随したいカメラをセットするだけです。

```JavaScript
  // "camera6" を検索
  const camera6 = scene.cameras.find(cam => cam.name === "camera6");
  const cameraGizmo = new BABYLON.CameraGizmo();
  cameraGizmo.camera = camera6;  // Camera Gizmo を表示
```

### Camera Gizmo のその他のオプションについて

Camera Gizmo にいくつかのオプションが用意されています。
カメラや視錐台の色、Gizmo のサイズを変更するといったことも可能なようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26094/d9f71a7f-7683-52f1-7009-6dd3e0e4f84a.png)

```JavaScript
 const utilLayer = new BABYLON.UtilityLayerRenderer(scene);    // Gizmo 用のレンダラー
 utilLayer.utilityLayerScene.autoClearDepthAndStencil = false; // Gizmo を既存のシーンに埋め込む場合は「false」
 const gizmoColor = new BABYLON.Color3(1, 0, 0);               // カメラの色
 const frustumLinesColor = new BABYLON.Color3(1, 1, 0);        // 視錐台の色
 const cameraGizmo = new BABYLON.CameraGizmo(utilLayer, gizmoColor, frustumLinesColor);
 cameraGizmo.scaleRatio = 0.5;                                 // Gizmo のサイズを変更
```

### おまけ（複数のカメラを同時に使ってみよう）

https://playground.babylonjs.com/#P81SPG#1
![babylonjs_animation_test_008.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/26094/7cf02fc2-df5d-495d-9134-16788f392e65.gif)

複数のカメラにそれぞれViewportを割り当てることで同時に複数のカメラを表示することが可能です。
Viewportの指定は左下隅を基準としてx,y座標とwidth,heightで行います。指定はそれぞれの割合を表す0～1の値を指定します。

```JavaScript
 // +---------+---------+
 // | camera2 | camera3 |
 // +---------+---------+
 // |      camera1      |
 // +-------------------+
 camera1.viewport = new BABYLON.Viewport(0.0, 0.0, 1.0, 0.5);
 camera2.viewport = new BABYLON.Viewport(0.0, 0.5, 0.5, 0.5);
 camera3.viewport = new BABYLON.Viewport(0.5, 0.5, 0.5, 1.0);
 scene.activeCameras.push(camera1);
 scene.activeCameras.push(camera2);
 scene.activeCameras.push(camera3);
```

### おわりに

`Virtual City` モデルはだいぶ古臭いモデルですが、カメラワーク等参考になることも多いです。
glTF サンプルモデルには組み込みカメラが設定されているものがいくつかあるので探してみるのも良いかもしれません。
Kotlin　Surfaceのインポート

# 初めてのAndroidアプリを作成するをなめていた
https://developer.android.com/codelabs/basic-android-kotlin-compose-first-app?continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-compose-unit-1-pathway-2%3Findex%3D..%2F..android-kotlin-fundamentals&hl=ja#0

このチュートリアルにしたがって進めていたわけですが、超初心者のため、ほんと躓きまくりました。
あとで困らないように記録しておきます。

文字の背景色を変更するために、Surface()を設定したら、文字が赤くなって怒られました。
どうやらパッケージ的なものがインポートされてないっぽいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/6813518b-6547-2673-45f9-6007943adec6.png)

で、インポートしようとしたら選択しが3つ出てきました。
どれなん。。。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/0ddf003e-13e8-7ca3-1463-3d72438dcac7.png)

感で一番上のを選択したら当たりだったっぽいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556392/a5fd75a8-556e-e696-4f0a-8d30668a255a.png)

おお・・・！
とりま、今日はこの辺で許そう。
git submodule を最新状態にする

# 前提
プロジェクトのリポジトリAで、外部のリポジトリBをsubmoduleとして登録しています。
今、リポジトリB側のリモートリポジトリのmainブランチに新しいコミットがマージされました。
リポジトリAにもリポジトリBの更新を反映させたいとします。

# 方法
1. 最新状態にしたいサブモジュールに移動する
    ```bash
    cd path/to/project_B
    ```

2. サブモジュールのブランチを`main`にする
    ```bash
     git checkout main
     ```
3. リモートリポジトリのmainブランチの最新を反映させる
    ```bash
    git pull origin main
    ```
4. リポジトリAに戻る
    ```bash
    cd path/to/project_A
    ```
これで完了です。`git status`で確認してみてください。
Android Studio でアプリを作ってみる

# 背景

娘が Scrach Jr で楽しんでいた。
パパも、新しいことしてみるか、と思い、Android Studio を楽しむことにした

とか言ってやってたけど、同僚にどうせやるなら Flutter でしょとそそのかされて、途中で切り替えることとなった :sweat_smile: 

# 躓き記録 on Flutter with VSCode

https://docs.flutter.dev/get-started/codelab

ということで、あとは CodeLab を学ぶことにして一旦リセット

https://codelabs.developers.google.com/codelabs/flutter-codelab-first?hl=ja&authuser=1#2

## 

# 旧躓き記録 on Android Studio

## implementation(libs.androidx.lifecycle.viewmodel.compose) が Unresolved reference to version catalog

libs.versions.toml　にて、以下を定義

```toml: libs.versions.toml
[versions]
androidxLifecycleViewModelCompose = "2.8.7"

[libraries]
androidx-lifecycle-viewmodel-compose = { module = "androidx.lifecycle:lifecycle-viewmodel-compose", version.ref = "androidxLifecycleViewModelCompose" }
```


## viewModel ってどうやってつかうん？

build.gradle.kts(Module :app) に追加するっぽい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/3345e61f-22f5-f56c-1db3-66918fe56781.png)


> implementation(androidx.lifecycle:lifecycle-viewmodel-compose:2.4.0")

みたいかと思ったら、なんか書き方違う

バージョン指定

> implementation(libs.androidx.lifecycle.viewmodel.compose.v262)

これは最新版

> implementation(libs.androidx.lifecycle.viewmodel.compose)


https://developer.android.com/jetpack/androidx/releases/lifecycle?hl=ja#lifecycle-viewmodel-compose-1.0.0-alpha01

## KeyboardActions, Options もないんだけど？

https://developer.android.com/reference/kotlin/androidx/compose/foundation/text/KeyboardActions

ん－、Jetpack Compose だとやり方が違うってことかな

https://developer.android.com/develop/ui/compose/touch-input/keyboard-input/commands

## log ってどこでみるん？

画面左下に、ネコさんがいた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/0938b310-0546-9e6c-5dd4-5f0908729481.png)

## あれ？xml ないとなると、デザインって動くまでわからないん？

右上によくある design 確認ボタンがあった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/5acb2020-ded5-7471-b834-c52d85ca2f84.png)

## android.content.ActivityNotFoundException: Unable to find explicit activity class {com.example.botomation/com.example.botomation.EditScriptActivity}; have you declared this activity in your AndroidManifest.xml, or does your intent not match its declared <intent-filter>?

いや、してませんでしたね :sweat: 

ってことで、

- AndroidManifest.xml に　<code>\<activity android:name=".EditScriptActivity" /></code> を追加

## res/layout/activity_main.xml がない

追加して、xml 定義していくかぁ・・と UI を配置してたが・・

なんか、今どきは xml 操作なんてしねーよってことに途中で気付く。
Jetpack Compose で書くらしいとのこと。
この辺は react の component みたいなイメージなんだろうか？

まぁ、新しいものの方が基本は楽なので、素直に xml を廃棄して、Jetpack Compose で書いていく

https://developer.android.com/develop/ui/compose/tutorial?hl=ja

# あとがき

ほんとは娘の学習アプリをサクッと作って終わろうとしたんだけど、
kotlin から Flutter に変えることになったのでいったん終了 :sweat: 

辿り着くのだろうか・・
困りごと：Apple Silicon MacのRyeでNexaを適切にインストールできない件

## はじめに
M4 Mac miniを最近買いました。
せっかく24GB RAMを買ったためLLMでなにかしようと思いました。
そこで[Nexa sdk](https://github.com/NexaAI/nexa-sdk)を使って完全ローカルリアルタイム音声会話システムの開発を始めました。
いつもだったらDockerを使って環境構築をしますが、MacのGPUはコンテナからアクセスできないっぽいので、（Anacondaの規約が変更され使いづらくなったため）Ryeの勉強を込めて[Rye](https://rye.astral.sh/)で環境構築を始めました。

### 結局？
Ryeで簡単にインストールされるが、nexa公式インストール方法でないためcpuで推論されとても遅い。いい方法ないですかね。

## 起きている問題
環境を作ったあとインストールのために以下のコマンドを実行しました。
```zsh
rye add nexaai
rye sync
```
正常にインストールされ、実際にサンプルコードを動かしました。
```python
from nexa.gguf import NexaTextInference

if __name__ == "__main__":
    
    # model_path = "llama2"
    model_path = "gemma-2-9b-instruct:q4_K_M"
    inference = NexaTextInference(
        model_path=model_path,
    )
    
    # create_chat_completion(messages)
    response = inference.create_chat_completion(
        messages=[{"role": "user", "content": "write a long 1000 word story about a detective"}]
    )
    print(response)
```

動きましたが、とても遅い。`asitop`を使ってモニターしてみるとGPU、ニューラルエンジンがともに使われていませんでした。

MacOSのインストーラーを使用して`nexa run model_name`したときはGPUが使われるため、nexaの問題ではないはずです。

公式サイトをよく見るとpythonライブラリ版をmacで使う場合には、以下のコマンドを打てとかいてあります。
```zsh
CMAKE_ARGS="-DGGML_METAL=ON -DSD_METAL=ON" pip install nexaai --prefer-binary --index-url https://nexaai.github.io/nexa-sdk/whl/metal --extra-index-url https://pypi.org/simple --no-cache-dir
```

しかし今回はryeを使う縛りがあるため、`pip`は使えません（rye環境にはインストールすらされないっぽい)。


## 私にryeはまだ早い？
これを解決できない私にモダンな開発環境はまだ早いのでしょうかね。
テスト117

```vb

Option Explicit

Public Declare PtrSafe Sub keybd_event Lib "user32" (ByVal bVk As Byte, _
                                                    ByVal bScan As Byte, _
                                                    ByVal dwFlags As Long, _
                                                    ByVal dwExtraInfo As Long)

Const ALT_KEY = &HA4            '//［Alt］キー
Const PRINT_SCRN_KEY = &H2C     '//［PrintScrn］キー
Const KEY_DOWN = &H1            '// キーを押す
Const KEY_UP = &H2              '// キーを放す

Private File_Path As String
Private FSO As Scripting.FileSystemObject

Public Sub AAA()

Dim saveFolderPath  As String
Dim imgFileName     As String
Dim imgType         As String

Set FSO = New Scripting.FileSystemObject

saveFolderPath = "C:\Users\User\Desktop\画像保存"
imgFileName = "test.png"
imgType = "png"

File_Path = FSO.BuildPath(saveFolderPath, imgFileName)

Call ScreenShot(imgType, True)

With ThisWorkbook.Sheets("貼り付け")
    '作成したスクショ画像の貼り付け
    .Activate
    .Range("A1").Select
    .Pictures.Insert(File_Path).Select

End With

MsgBox "[貼り付け]シートにスクショ画像を貼り付けました。", vbInformation, "画像"

End Sub

'// クリップボードの画像を保存する
Sub ScreenShot(ByVal img_type As String, _
               Optional ByVal alt As Boolean)

Dim psCmdStr    As String   '// PowerShellコマンド

''特定のファイルをスクショする
'Workbooks("bbb.xlsx").Activate

If alt Then keybd_event ALT_KEY, 0, KEY_DOWN, 0

keybd_event PRINT_SCRN_KEY, 0, KEY_DOWN, 0

keybd_event PRINT_SCRN_KEY, 0, KEY_DOWN Or KEY_UP, 0

If alt Then keybd_event ALT_KEY, 0, KEY_DOWN Or KEY_UP, 0

'// PowerShellのクリップボード画像保存コマンド
psCmdStr = "powershell Add-Type -AssemblyName System.Windows.Forms;$ImagePath = '" & File_Path & _
           "';  [Windows.Forms.Clipboard]::GetImage().Save($ImagePath, [System.Drawing.Imaging.ImageFormat]::" & _
           img_type & ")"

'// PowerShellコマンド実行
CreateObject("WScript.Shell").Run Command:=psCmdStr, WindowStyle:=0, WaitOnReturn:=True

End Sub
ConfluenceのAIと自動化で議事録のAI要約をslackに流すようにしてみた

# はじめに
この投稿は Atlassian Advent Calendar 2024 の7日目です。

# この記事は
Atlassian Intelligence(AtlassianのAI)が登場して1年、Atlassian Rovoという新たなAIツールも出ていますが、この記事ではConfluenceに搭載されているAtlassian InteliigenceとConfluenceの自動化を組み合わせて議事録の要約を簡単2ステップでSlackに送信してみたいと思います。

# 用意するもの
Confluence Premium
Slack

# 本Tipsのトピック
* ConfluenceのAIでページを要約できる
* 自動化アクションにAI要約を組み込んでいる

# 手順

## 議事録を準備しましょう
Confluenceにさらっと議事録を書いてください。

<img width="30%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/462b47e0-9e3a-92a5-4a22-7a92204df4f0.png">

## Confluenceの自動化を設定する

### 1. Confluenceの自動化は以下からアクセスします
![ルール_ビルダー_-_自動化_-_Kunihiro_Takahashi_-_Confluence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/71a42d71-fb79-e25a-0edf-01f8fe7fb563.png)

### 2. ルールを作成する
![ルール_-_自動化_-_Kunihiro_Takahashi_-_Confluence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/d40ccafd-628a-28be-f841-e9faac7b17be.png)



### 3. ルールが発動する条件を指定します
ここでは手動トリガーで動かすようにしています。その他、ページが作成されたときや、定期実行などの条件が設定できます。
![ルール_ビルダー_-_自動化_-_Kunihiro_Takahashi_-_Confluence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/7fca6b8b-a453-a377-e6e7-c595f40c64b8.png)

### 4. Slackに送信のアクションを設定します。
ここで画像のようにslack のメッセージに 
```
{{page.aiSummary}}
```
と入力します。これでconfluenceページのAI要約を取得できます。
おまけでページのURLも載せておきましょう。

![ルール_ビルダー_-_自動化_-_Kunihiro_Takahashi_-_Confluence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/88d09cd2-4de4-6c7b-5c9b-542e124184ad.png)


これで設定は完了です。簡単ですね。



# 実行
下記のようにページ上部にある自動化ボタンから実行します。
![2024-12-07_ミーティング議事録_-_Kunihiro_Takahashi_-_Confluence.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/222512a7-dcd5-bb07-749f-c93efa004810.png)



# 確認
こんな感じでSlackに送信されます。
![Cursor_と_kunny（DM）_-_acetokyo_-_Slack.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103246/e2112d52-ba53-7f37-82f2-3bbe6eb8f7b5.png)


# 補足情報
* AI要約は実行するたびに多少内容が異なります。それも面白さですね。
* 他にもAI関連の自動化メニューが用意されています。詳しくは下記を参考にしてください。
* https://support.atlassian.com/ja/cloud-automation/docs/actions-in-confluence-automation/

# 最後に
AtlassianのJiraとConfluenceに組み込まれている自動化および自動化に使えるsmartvalueを調べると色々なことができると思いますぜひお試しください。
また、最近発表されたAtlassian Rovoもこの自動化に組み込むことができるようです。たとえば校正をしてくれるエージェントなんかを作り、毎日夜間にその日に作られたconfluenceページを校正するなんてことができるかもしれません。
Aurora MySQLにおけるクエリの改善ステップ

:::note info
これは [ZOZO Advent Calendar 2024](https://qiita.com/advent-calendar/2024/zozo) カレンダー Vol.10 の 7日目の記事です
:::

現在、自分が所属しているチームでは、Aurora MySQLを使ったマイクロサービスの運用を行っています。マイクロサービスの性能を維持・向上するためには、**データベースのクエリチューニング**が欠かせません。

今回は、普段自チームで実践しているクエリチューニングの改善ステップをご紹介します。
1. 対象SQLの特定
2. 実行計画の確認・問題点の把握
3. 改修案の検討・検証
4. 本番リリース・経過観察


## 1. 対象SQLの特定
パフォーマンスの悪いクエリを特定するために、以下のツールを活用します。

### Slow Query Log
- ログを出力することで、特定の時間帯に発生するパフォーマンス問題も把握しやすくなります。
```sql
SET GLOBAL slow_query_log = 1;
SET GLOBAL long_query_time = 1;  -- 1秒以上のクエリを記録
```

### Datadog APM / Database Monitoring（DBM）
- Datadogを使用して、API単位やクエリ単位で遅いクエリを特定します。
  - **APIベース（Datadog APM）**：遅いAPIエンドポイントから問題のクエリを絞り込みます。
  - **クエリベース（Database Monitoring（DBM）**：データベース全体で遅いクエリを監視します。
- 以下の記事でのように、私のチームも以下ブログで紹介しているような形でDBおよびクエリの状況をDBMで見れるようにしています。

参考：[Splunkと Datadog Database Monitoringを用いたDBパフォーマンスの可視化](https://techblog.zozo.com/entry/visualize-sqlserver-performance)

### Performance Insights
- AWSのGUIを確認して、アクティブセッション上位のSQLは常に確認するようにしています。
- インスタンスサイズによってはPerformance Insightsが使えないこともありますが、可能な限り活用するようにしています。

参考：[AWS Performance Insights](https://aws.amazon.com/jp/rds/performance-insights/)

**サービス要件に満たしていないクエリがないか、日々確認・スロークエリを発見したらすぐにチューニングの検討を始めます。**

## 2. 実行計画の確認・問題点の把握
- 対象SQLが見つかったら、実行計画を確認し、問題点を洗い出します。
- `EXPLAIN`ステートメントでアクセスパターンやインデックスの利用状況を確認します。
- 実行計画の見方や分析方法についてはここでは割愛しますが、詳細な分析を行い、クエリのボトルネックを特定します。

## ３. 改修案の検討・検証
- 実行計画から得た情報をもとに、以下のアプローチでクエリを改善します。
  - インデックス最適化
  - 結合の最適化：駆動表の選択や不要な結合の見直し
  - リードモデル（参照系の場合は、そのクエリの参照に特化したテーブルを作成するなどの対応をする）

## 4.本番リリース・経過観察
- 改善したクエリを本番にリリースし、以下のツールで経過観察を行います。

### Datadog APM / Database Monitoring（DBM）
- **Datadog APM**：遅いAPIエンドポイントのレスポンス改善を確認します。
- **Database Monitoring（DBM）**：クエリの実行時間やデータベース負荷を監視し、改善効果を検証します。

#### 確認ポイント
- 1〜2週間の間、対応前後のパフォーマンスを比較
  - 効果が見られれば対応終了。改善が不十分なら、再度**1.対象SQLの特定**から改善サイクルを回します。

## 最後に
- ZOZOTOWNを支える重要なサービスを運用する中で、データベースのパフォーマンスは常に意識しています。
- **日々の地道な監視と改善のサイクル**を回し続けることで、安定したサービス提供を実現しています。
Gitエイリアスでショートカットコマンドを作る

# はじめに
Gitコマンド、慣れていても、**長いコマンド打ちたくない**ですよね...

ということで、今回は`Gitエイリアス`を使用してショートカットコマンドを作っていきたいと思います。

# Gitエイリアスとは
公式によると、
> `Git`の使い勝手をシンプルに、簡単に、わかりやすくしてくれる、エイリアス

長く複雑な Git コマンドに短い、覚えやすい名前をつける機能ですね。
開発者の作業効率を大幅に改善し、**日常的なGit操作をよりスムーズにしてくれる便利機能！**

# エイリアスの基本的な作り方
Gitエイリアスは主に2つの方法で設定できます：

### 1. グローバルに設定する
グローバル設定は、**すべてのGitリポジトリ**で有効になります。

```bash
git config --global alias.エイリアス名 "元のコマンド"
```

### 2. ローカル(特定のリポジトリ)に設定する
**特定のリポジトリにのみ**適用される設定です。
```bash
git config --local alias.エイリアス名 "元のコマンド"
```

# ショートカットコマンドを作る
ここからは、実際に作ってみましょう。

:::note warn
個人の好みや作業スタイルに合わせてエイリアス名をカスタマイズしてください!!
:::

## 基本的なショートカット
```bash
# 変更をステージングする
git config --global alias.a 'add'

# ステータス確認を簡略化
git config --global alias.st 'status'

# ブランチ一覧
git config --global alias.br 'branch'

# チェックアウト
git config --global alias.co 'checkout'
```

これを実行すると、`git st`と打つだけで`git status`と同義の操作になります。

## オプションを含めたショートカット
```bash
# コメントをつけてコミットする
git config --global alias.cm 'commit -m'

# 最近のコミット3件を一行で表示
git config --global alias.last 'log -3 --oneline'

# 変更されたファイルと変更内容を同時に確認
git config --global alias.changes 'diff --name-status'

# 全ブランチのログを見やすく表示
git config --global alias.tree 'log --graph --oneline --all --decorate'
```

このように今まで長々と打っていたオプションまでも簡単に！

# エイリアスの管理
## エイリアスの一覧表示
```bash
git config --global --list | grep alias
```
## エイリアスの削除
```bash
git config --global --unset alias.エイリアス名
```

# 確認と注意点
- 覚えやすく、直感的な名前を選ぶ
- エイリアスは ~/.gitconfig に保存されます
- チームで共有する場合は、設定スクリプトやドキュメントで共有することをおすすめ

# おわりに
Gitエイリアスは、開発効率を上げるためにとても便利なツールです。
自分の作業スタイルに合わせて、少しずつカスタマイズしていくといいでしょう。
jsr:@kt3k/pack を使って Deno 互換スクリプトを手軽にバンドルする

Deno Advent Calendar [13日目の記事](https://qiita.com/kt3k/items/408ea886712abaa90e67)で、[esbuild-deno-loader](https://jsr.io/@luca/esbuild-deno-loader) を使って Deno 互換スクリプトをバンドルする例を紹介しました。

これでも良いのですが、API 呼び出しが複雑なため、毎回この記述を思い出す・調べるのは少し面倒です。個人的には、毎回 esbuild を設定しなくても良いように、esbuild + esbuild-deno-loader の設定を入れた簡単なラッパー CLI を用意して、それを使ってフロントエンドのビルドをしています。

https://github.com/kt3k/pack

`pack` というツールで、以下のようにして Deno から使えます。

```shell-session
deno -A jsr:@kt3k/pack script.ts -o script.js
```

以上の呼び出しで、`script.ts` がバンドルされて、`script.js` にファイルが保存されます。

Deno とほぼ互換なモジュール解決が出来て、以下のような Deno のモジュール機能に対応しています
- URL import
- `jsr:` import
- `node:` import
- `npm:` import
- import map

Deno 互換の書き方でフロントエンド(ブラウザ)やその他のランタイム上でプログラムを動かしたい場合に上記ツールでバンドルするのが便利です。

Happy Isomorphic Deno Programming!
クリニックの番号呼び出しシステムをつくっただけ（不採用）の話

ふと思い立ち、クリニックの番号呼び出しシステムをつくろうと思いました。
つくりましたが、実際には採用されていません。

『ふと思い立ち』の経緯は以下のような感じ。

# 経緯

親戚がクリニックを開院することになって、Webサイト作成を依頼された。

この出来事があって、じゃあ番号呼び出しシステムが必要になるかな？と思い、つくった次第です。

でも、小規模かつ完全予約制のため、そういうシステムがなくても運営に支障がないということで採用はされませんでした。

まあ、実際に運用されるとなると、多少ネットワークを経由するシステムということがネックとなり、他者の構築したネットワークへの適用に四苦八苦することになったろうと予想されます。
ですから、むしろ採用されなくて一安心というところもあります。

基本的に、勉強の題材としてつくったということです。

でも、つくっただけではもったいないため、このシステムについてのあれこれを記事にして、わたしの備忘録を兼ねたいと思います。

# 完成形

では、まずはどんなシステムができあがったかを掲載しておきます。

## 番号呼び出しディスプレイ

こちらが番号呼び出しのディスプレイ画面側です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821654/efae1687-f194-bbfe-83b0-64ab87a2b782.png)

普段は「診療中です」と表示されており、管理画面で呼び出しをすると、上記の画面になります。

ぴんぽーんって間の抜けた音も鳴ります。

ご覧いただけるとわかりますが、システムとかディスプレイとかかっこつけて表現していますが、単なるWebページです。

ただ、ブラウザのフルスクリーン機能を使用することで、ツールバーを削除したフルスクリーンにすることができるため、それっぽい見た目にはなります。

クリニックの待合室には、なんらかのパソコン、モニター、スピーカーを設置して、この画面を表示しておくというわけです。

## 管理画面

管理画面もWebページです。

診察室にいる医師は、こちらのページから番号呼び出しを行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821654/c9cfd3c9-9784-450b-3256-59bb3bc999e7.png)

上記二種類のWebページを使うことで、クリニックにおける番号呼び出しを実現します。

# 仕組み

このシステムはWebページのシステムということで、フロントエンドとサーバーサイドを組み合わせて構築しています。

## フロントエンド

フロントエンドはJS、CDNのVue.js、axiosを用いて、サーバーサイドと通信をしています。

Webページは、

- 管理ページ
- 番号呼び出しのディスプレイページ
- ログページ

の三つのページを作成しました。

各ページは独立しています。

ページ間の通信は行わず、あくまでサーバーサイドを経由してデータをやりとりします。

## サーバーサイド

サーバーサイドはPython、Flask、SQLAlchemyを用いています。

Flaskを用いることで、サーバーを立ててAPIのエンドポイントも準備できました。

データはSQLAlchemyにより、SQLiteデータベースに保存するシンプルなつくりです。

最低限保持すべきデータは「待ち状態にある番号」で、サーバーを再起動してもデータを保持する必要があるため、データベースを準備しました。

このような構成でシステムを実現しています。

# 気をつけたこと

ちなみに、このシステムを構築する上で気をつけたことは、『個人情報を保持しないこと』です。
名前も診察番号も、このシステムでは管理しません。

あくまで、その日限りで有効な受付番号だけ、を保持し、セキュリティ事故が起こるリスクを限りなく下げたつもりです。

電子カルテシステム等と接続するシステムであれば、要求されるセキュリティレベルは高いと思います。
ですが、入門者レベルの私の知識ではじゅうぶんなセキュリティ対策は不可能なため、最初からリスクのあるものは取り扱わないことにしました。

おかげで、システムはシンプルになってつくりやすかったです。

# 終わりに

こんなシステムを途中までつくりました。

完成はしていませんが、基本的な番号呼び出し機能は動作する状態です。

完成していないというのは、あれこれ考えながら継ぎ足していったため、ソースコードが散らかっている点や、データ構造がふわふわな点、バグ出しをしていない点から、完成していないと評価している状態です。

さらに欲を言えば、もっと細かい機能を付け足したいなとも思っています。
いつかいい感じに仕上がったら、リリースできたらいいな、とも思っています。

使う状況をクリニックに限定するのではなく、何かしらの順番待ちの状況で使えるような形が目標です。

実際にリリースする可能性はほぼないですが、現実的な題材は勉強にちょうどよいため、引き続き開発して、かつ、技術メモのような形のアウトプットもしていきたいと思います。

いろいろ夢は膨らみながら、まもなく年末。
アドベントカレンダーのさぼった分を必死に追っている師走です。

ここまで、読んでくださってありがとうございました。
出力: 車輪を動かす　その1

### 背景
車輪を付け替えたのでSpheroを動かすことができるようになりました。
動作のブロックの一部を試してみます。

### Scratch

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/6bd61732-f90f-540a-3590-1c49d2e27fe0.png)

「ゼロ度の方角に向かってスピード100で0.5秒間動かす」

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103446/688ebb21-0a31-c58c-6c3e-64a4396969c3.png)


図の左側に使っている一つのブロックの内容をそれぞれの値で分解して、図の右側のブロックのようにできるようです。
方向の指定の後のディレイは不要かもしれませんが、何となく気になるので入れました。


### spheroV2
sphero_edu.pyのメソッドを参考に同様な動作をするスクリプトを作成しました。

```
import time

from spherov2 import scanner
from spherov2.sphero_edu import EventType, SpheroEduAPI
from spherov2.types import Color

print("Testing Starting...")
print("Connecting to Bolt...")
toy = scanner.find_BOLT()

if toy is not None:
    print("Connected.")
    with SpheroEduAPI(toy) as droid:
        print("Testing Start...")
        
        print("go heading: 0, speed: 100, duration: 0.5s")
        droid.roll(0, 100, 0.5)

        # droid.set_heading(0)
        # time.sleep(0.2)
        # droid.set_speed(100)
        # time.sleep(0.5)
        # droid.stop_roll()

        print("Testing End...")
```

実行結果はこちらのようになりました。
```
git\spherov2.py\spherov2\test>python BoltTest_motor1.py
Testing Starting...
Connecting to Bolt...
Connected.
Testing Start...
go heading: 0, speed: 100, duration: 0.5s
Testing End...
```

### まとめ
spheroV2を用いて、sphero boltをpythonで動かすことができました。
キーボードやゲームパッドを使った入力とつなげると楽しめそうです。
【Rails】マイページの作成と更新

# 記事概要
Railsでマイページを作成する方法とユーザー情報の更新方法をまとめる。

# 言語やフレームワーク
|| 使用技術 |
| ---- | ---- |
| フロントエンド | HTML |
| バックエンド | Ruby 3.2.0 <br> Ruby on Rails 7.0.8.6 |
| データベース | MySQL |
| インフラ | - |
| API | - |
| その他 | Devise(Gem) |

# 前提
- GemのDeviseを適用している
- app/views/shared/_error_messages.html.erbにエラーメッセージ表示用の部分テンプレートを用意している

# 手順(ルーティングの設定)
config/routes.rbに、マイページを表示するためのルーティングを設定
```routes.rb
# 中略
resources :users, only: :show
# 中略
```

# 手順(コントローラーの作成＋設定)
コントローラーを作成するため、ターミナルで下記を実行
```
rails g controller users
```
app/controllers/users_controller.rbを下記のように編集
```
class UsersController < ApplicationController
  def show
    @user = User.find(params[:id])
  end
end
```

# 手順(マイページ用ビューファイルの作成＋設定)
app/views/usersフォルダに`show.html.erb`を手動作成し、ビューファイルを編集(マイページとなる)
```erb
<h2><%= @user.nickname %>さんのマイページ</h2>

<!-- ログインユーザーかつ自身のマイページの場合のみ表示される -->
<% if user_signed_in? %>
  <% if @user.id == current_user.id %>
    <table>
      <tbody>
        <tr>
          <th>ニックネーム</th>
          <td><%= @user.nickname %></td>
        </tr>
        <tr>
          <th>メールアドレス</th>
          <td><%= @user.email %></td>
        </tr>
      </tbody>
    </table>
  <% end %>
<% end %>
<!-- ログインユーザーかつ自身のマイページの場合のみ表示される -->
```

# 手順(deviseのパラメーターを追加)
app/controllers/application_controller.rbを編集
```application_controller.rb
# 中略
private
devise_parameter_sanitizer.permit(:account_update, keys: [:nickname])
# 中略
```

# 手順(Userモデルを修正)
passwordのバリデーションに`on: :create`を追記
```user.rb
validates :password, presence: true, on: :create
```

# 手順(ユーザー情報更新用ビューファイルの編集)
deviseのビューファイルを作成するため、下記をターミナルで実行
```
# アプリのディレクトリにいることを確認
% pwd
/~/[アプリ名]

# deviseに用意されたビューファイルをコピーし、app/viewsの配下に配置
% rails g devise:views
```

app/views/devise/registrations/edit.html.erbを必要に応じて編集
(現在のパスワードを入力することで、ユーザー情報の更新が可能)
```erb
<%= @user.nickname %>さんの会員情報変更

<%= form_with model: @user, url: "/users", local: true do |f| %>
	<%= render 'shared/error_messages', model: f.object %>
	<label>ニックネーム</label>
	<%= f.text_area :nickname, placeholder:"例) taro" %>

	<label>メールアドレス</label>
	<%= f.email_field :email, placeholder:"PC・携帯どちらでも可" %>

	<label>パスワード</label>
	<%= f.password_field :password, placeholder:"6文字以上の半角英数字" %>
	<p>※パスワード変更時のみ入力ください</p>

	<label>パスワード(確認)</label>
	<%= f.password_field :password_confirmation, placeholder:"同じパスワードを入力して下さい" %>
	<p>※パスワード変更時のみ入力ください</p>

	<label>現在のパスワード</label>
	<%= f.password_field :current_password, placeholder:"現在のパスワードを入力して下さい" %>
<%= f.submit "更新" %>
```

# 備考
- usersコントローラー配下にeditアクションを作成してユーザー情報を更新した場合、renderで表示される画面が「devise/registrations#edit」になる
cscの作法 その541

# 概要
cscの作法、調べてみた。
練習問題やってみた。

# 練習問題
ボタンのフォントサイズを大きくせよ。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/81f51bb6-b977-ab9a-8ea7-dc57fd30b729.png)


# サンプルコード

```

using System;
using System.Windows.Forms;
using System.Drawing;

class form1: Form {
	form1() {
		Text = "font";
		ClientSize = new Size(300, 200);
		Button btn1 = new Button();
		btn1.Font = new Font(btn1.Font.OriginalFontName, 18f);
		btn1.Location = new Point(50, 50);
		btn1.Size = new Size(200, 60);
		btn1.Text = "アケオメ";
		btn1.Click += btn1_Click;
		Controls.AddRange(new Control[] {
			btn1
		});
	}
	void btn1_Click(object sender, System.EventArgs e) {
		MessageBox.Show("Hello World", "こんちわ");
	}
	[STAThread]
	public static void Main() {
		Application.Run(new form1());
	}
}


```

以上
怒り方が下手な先生の特徴

# はじめに
ぼくはQiitaの記事の書き方が全くわかりません。
わかりにくかったらごめんなさい。

# 本題

### 一個目

**矛盾点をつくるな**

そりゃ先生への信頼もなくなりますし、何より何いってんだこいつ記憶ねえのかよってなるので。

### 二個目

**話が長い**

頭に話が入ってこないし無駄な時間増やすなよって思われます。
生徒の時間を奪うな。

### 三個目

**喧嘩などで片方の生徒の話を聞かない**

より生徒の不満が溜まったり、先生への信頼がなくなります。
話をちゃんと聞いて下さい。はい。

### 四個目

**高圧的な態度**

先生が苛ついたところで生徒は何も思いません。

### 五個目

**泣くな**

うざがられるだけです。ちっさいことで泣くなまじで。

# 終わり

少しでも共感してくれたら嬉しいです。
投稿遅くなってごめんなさい
Pythonインストールツールを刷新した時に気付いたこと【自作ツール】

# 1.Pythonインストールについて
Pythonをインストールする時って、大体[公式サイト](https://www.python.org)から
インストーラーをダウンロードして、セットアップを終わらして...と結構大変だと思います。Pythonのインストールがうまくいかなくて困っている友達もいました。なのでインストールを単純化するため**シンプルなツール**を作ることにしました。
# 2.最初はCUI
高速さ、単純さなどの点から最初はターミナル上で動作するCUIのアプリを作りました。
作っていて思ったのが、 **CUIってむずくね？** ということです
結局キーボードでしか操作できないCUIなら、マウスを使ってインストールできる通常の方法の方が簡単という全く意味のないアプリになってしまいます。
# 3.決断と変更
やっぱり、GUI化をすることにしました。主な理由は、
- 使いやすさ
- 親しみやすさ
- シンプルさ
という感じでしょうか。
で、結果的にできたのが[これ](https://github.com/Cheesecake2960/get-the-py)です。GUI化した方が開発、使用ともにうまくいき、**アプリ全体を大きく変えることに意味がある**ということに気付きました。あまり変えすぎても、ユーザーが使いずらくなる原因になりますが。一応、CUIも残しておきました。

https://github.com/Cheesecake2960/get-the-py

# 4.GUI化した感想
> GUI化した方が開発、使用ともにうまくいき、**アプリ全体を大きく変えることに意味がある**ということに気付きました。

常にツールは新しく、便利であることが重要だと思いました。
最後まで読んでいただきありがとうございました。
vue.jsで初めに覚えておくと良いポイント

## はじめに
vue.jsをやったことがない人、仕事でやることになった人が初めに覚えておくと良いポイントについて自分の経験をもとに記載します。


## ライフサイクル
Vue.js には ライフサイクル という概念があり、作られたページはこのライフサイクルをもとに処理が実行されていく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3937998/4eb14bd3-af06-a910-9fef-917f167896df.png)

- setup():
コンポーネントの作成を開始し、beforeCreate と created の前に実行され、data と method を作成します。
(vue2まで記載していたdata, methods, computedはsetup内ですべて表現可能)

- onBeforeMount():
コンポーネントがノードにマウントされる前に実行される関数です。

- onMounted():
コンポーネントがマウントされた後に実行される関数です。

- onBeforeUpdate():
コンポーネントが更新される前に実行される関数です。

- onUpdated():
コンポーネントが更新された後に実行される関数です。

- onBeforeUnmount():
コンポーネントがアンマウントされる前に実行される関数です。

- onUnmounted():
コンポーネントがアンマウントされた後に実行される関数です。

- onActivated():
<keep-alive> に含まれるコンポーネントには、2つのライフサイクルフックが追加され、アクティブ化されたときに実行されます。

- onDeactivated():
A コンポーネントから B コンポーネントに切り替えた場合、A コンポーネントが消えるときに実行されます。

- onErrorCaptured():
子孫コンポーネントからの例外をキャッチしたときにアクティブ化されるフック関数です

## ディレクティブ
Vue.jsをさわる上で基本となるのがマスタッシュ記法(v-text),v-if, v-show, v-for,v-bind, v-on, v-modelといったディレクティブとなりHTMLに対して独自の属性を追加することでDOM操作を行うことをいいます。

- マスタッシュ記法(v-text)
要素の textContent プロパティをセットする動作、基本的にはマスタッシュ記法{{hoge}}で書かれていることが多いがv-textで書かれているプロジェクトもたまにあるのでv-textは何となく覚えておくとよい。
```
<span v-text="msg"></span>
<!-- ↓マスタッシュ記法 -->
<span>{{msg}}</span>
```

- v-ifとv-show
v-showは式の値の真偽に基づいて、要素の可視性を切り替えます。v-ifは式の値の真偽に基づいて、要素またはテンプレートフラグメントを条件付きでレンダリングします。どちらも表示と非表示を切り替えるものだがv-ifはDOM要素の追加と削除、v-showはdisplayプロパティの値の変更によって実現しています。
```
<span v-if="true"></span>

<span　v-show="false"></span>
```

- v-for
元となるデータに基づいて、要素またはテンプレートブロックを複数回レンダリングします。
```
<div v-for="item in items">
  {{ item.text }}
</div>

```
配列のindexが必要な場合
```
<div v-for="(item, index) in items">
  {{ item.text }}
</div>
```

- v-bind
v-bindはHTML要素の属性に、特定のデータを渡す際に利用できます。
```
<img v-bind:src="imageSrc" />
<!-- ↓":"で省略記法 -->
<img :src="imageSrc" />
```

- v-on
要素にイベントリスナーを追加します。
```
<button v-on:click="doThis"></button>
<!-- ↓"@"で省略記法 -->
<button @click="doThis"></button>
```

- v-model
フォーム入力要素またはコンポーネントに双方向バインディングを作成します。
DOMで変更があった時、その値をVueインスタンスのデータとして更新します。
Vueインスタンスのデータに変更があった時、DOMを更新します。
```
<input v-model="hoge">
```

## 最後に
今回はvue.jsの初心者向けに覚えておくと良いポイントについて記載しました。初歩的なことですが仕事でソースコードを見ることになった時などに覚えておけばある程度理解ができるのではないかと思います。
応用すればできることが色々あるので興味があったら調べてみてください。
PHP公式マニュアルに素敵機能が実装された

PHP公式マニュアルに2024年12月3日、新しい機能が実装されました！

実装したAntoine Bluchet氏のポスト：

https://x.com/s0yuka/status/1863908809317486635

というわけで、この新機能を紹介したいと思います。

## 新機能：サンプルコードをその場で実行できる
マニュアルのサンプルコードの上に [Run code] ボタンが追加されました。
これをクリックしてみると、"Output (PHP 8.4.0-dev):"という表示とともに、コードの実行結果が表示されます。
[`str_repeat()`のページ](https://www.php.net/manual/ja/function.str-repeat.php)だと以下のようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120475/4fbd848b-c1fd-f78c-9ffd-7bc9211db0a3.png)

さらに、このサンプルコードは書き換えることができ、書き換え後のコードの実行結果も見ることができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120475/f5cd51e9-a6bd-eae6-4a1e-759e4c828a71.png)

## どうやって動いてる？
通常はサーバー上で動くPHPですが、この"Run code"機能はブラウザ上でPHPを動作させています。
PHPインタプリタをWebAssemblyにコンパイルした[soyuka/php-wasm](https://github.com/soyuka/php-wasm)を利用しています。

そのため、実行ボタンを押してから一瞬で結果が出力されます（初回のみwasmバイナリのダウンロードが走るようで少し時間がかかります）。

---
ちょっとした動作確認のためにわざわざターミナルを立ち上げたりせずともPHPコードを実行できるようになり便利ですね！

ちなみに、php.netの開発はGitHub上で行われているので、この機能に関して何か問題や改善点があれば、Issueを立ててみると取り入れられるかもしれません。

https://github.com/php/web-php
appディレクトリ

# appディレクトリの内容を知る
>RailsはMVCアーキテクチャを採用しているため、アプリケーションコードは基本的にModel、View、Controllerの三階層に分かれます。この基本となる3階層がそれぞれmodels,views,controllersの３つのディレクトリです。これらに加えて`Viewで利用するヘルパースクリプトを格納するhelper`を合わせた4つのディレクトリがRubyで記述するサーバサイドアプリケーションとしてよく利用することになるディレクトリです。
　また、`フロントエンド関連のソースコードはjavaScriptのソースコードをまとめるJavascript`、`CSSなどをまとめるassetsディレクトリ`があります。これは詳細は「４章　フロントエンドの開発手法」で詳しく解説します。
　それ以外の`channelsやjobs、mailerなどはRailsが用意している特定の機能向けコンポーネントに関するソースコードを格納する場所`です。これらについては「５章　Raiils標準の機能を活用して素早く機能実装する」で解説しますが、それぞれのコンポーネントを使わないシンプルなrailsアプリケーションではこれらのディクトリ内を編集することは少ないでしょう。
p30~31


 https://gihyo.jp/book/2020/978-4-297-11462-6

# 以下に対してどんなコードを書くのか知りたい
 * `Viewで利用するヘルパースクリプトを格納するhelper
 * フロントエンド関連のソースコードはjavaScriptのソースコードをまとめるJavascript
 * channelsやjobs、mailerなどはRailsが用意している特定の機能向けコンポーネントに関するソースコードを格納する場所

# 独自のヘルパーメソッドの定義
>Rails組み込みのヘルパーメソッドでは用途に合わない場合は`自分で実装する必要`が出てくるでしょう。HTMLタグの付与や生計などビューに特有の加工をする場合は、モデルクラスに変換処理がを書くより、ヘルパーメソッドを利用するやり方が一般的にです。ここでは独自のヘルパーメソッドの定義方法について説明する。
 ヘルパーメソッドを定義するためのモジュールは、「app/helpers」というディレクトリの配下に定義します。アプリケーション全体で使うものであれば「app/helpers/application_helper.rb」に実装し、コントローラ毎に使うようなものであれば「app/helpers/books_helper.rb」のようにコントローラに対応するhelper用のファイルを用意します。
p106

### helperオブジェクトでヘルパーを呼び出す
```rb
odule ApplicationHelper
  def to_hankaku(str)
    str.tr("Ａ-Ｚａ-ｚ", "A-Za-z")
  end
end
```
```rb
*******> helper.to_hankaku("ＲＵ")
=> "RU"
```
#### helper出ないといけない
```rb
 helpe.to_hankaku("ＲＵ")
*******:2:in `<main>': undefined local variable or method `helpe' for main:Object (NameError)
Did you mean?  helper
```
### /mailersはAction Mailer
>Action Mailerを使うと、アプリケーションからメールを送信できるようになります。

# 感想
他のディレクトリは情報技術に関する基礎が必要だと考える。
説明を見たが理解できなかった。
ミスってトークンをグループLINEに公開した話

# セキュリティは常に気を付けないといけない
忘れたころに、セキュリティは脅威が訪れます。
それがすぐに対処出来たらいいですが...:ghost:

# 何をやらかしたのか
LINEのボットを作っていた時、友達にコードを見せてほしいと言われ、
グループに送信したらそこにはなんとトークンが入っている！(不注意)
慌てて再発行しました:sweat:

# 改善策
- **環境変数にトークンを保管する (推奨)**
- 別ファイルにトークンを保管する
- そもそも人にコードを送らない

# 思ったこと
今回は友達しかいないグループラインだったので事なきを得ましたが
これがパブリックな所に公開していたら...:fearful:
今頃ボットは大変なことになってたかもしれません。
セキュリティの大切さを知りました。
今後も勉強していこうと思います。
最後まで読んでくれてありがとうございます。
チャンク単位のフィルタリングでRAGの精度を向上する手法：ChunkRAGについて

最近、RAGの精度を向上させる新たな手法「ChunkRAG」を扱った論文を読みました。内容がなかなか興味深かったので、ここで簡単にまとめてご紹介します。

https://arxiv.org/abs/2410.19572

ChunkRAGは、RAGにおける回答精度向上を目的としたアプローチです。ざっくり言うと、RAGが取得した「チャンク（文章の断片）」をLLMで評価し、関連性が低いチャンクを除去することで、最終的な回答の品質を高める手法です。

従来、RAGでは取得した文書をそのままLLMに渡すことが多く、余計な情報が入り込み、回答が冗長になったり的外れになったりする問題がありました。ChunkRAGは、文書を細かく区切ってから役に立たない部分を取り除くことで、この問題を解決しようとしています。

下記の図は、その効果をわかりやすく示しています。左側は不要な情報が混入して回答が冗長になっていますが、右側では事前の分割とフィルタリングによって回答が簡潔かつ的確になっています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/9e978eef-54d0-a52f-7c0d-d4fa714141a6.png)


続いて、ChunkRAG全体のフローチャートがこちらです。（下図参照）
これを踏まえつつ、各ステップを簡単に説明します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/8bed9d55-890f-6abf-774d-044f4f6213ce.png)


# 1. Semantic Chunking
まず、文章全体をsent_tokenizeなどで文ごとに分割し、隣り合う文同士の類似度（0.7以上など）に基づいてチャンクとしてまとめます。この際、チャンクが大きくなりすぎないよう、500文字以内などの制約も設けています。
こうしたやり方で意味的につながりがある文をひとまとめにし、余計な情報が混在しないチャンクを作成します。

# 2. Query Rewriting
次に、ユーザの問い合わせ（クエリ）をより明確で検索しやすい形に書き直します。
これはRAGでよく使われる手法で、曖昧なクエリを明確化して、以降の処理をしやすくする役割があります。

# 3. Filtering
続いて、取得したチャンクをフィルタリングします。
まずはチャンク間の類似度が0.9以上になった場合、重複とみなして除去し、冗長な情報をカットします。
その後、LLMを用いて各チャンクとクエリの関連度をスコアリングします。
ここでSelf-Reflection（LLMが自分の評価を見直す）やCritic LLM Scoring（別のLLMが評価の妥当性を判断）といった手法も使い、チャンクの関連度評価をより正確にします。
最終的に一定の基準を下回るチャンクは「関連性が低い」として除外します。

# 4. Hybrid Search and Rerank
その後、ベクトル検索結果を補強するため、キーワードベースの検索結果を0.5:0.5の比率で組み合わせるハイブリッド検索を行い、結果を統合します。（キーワード検索は固有名詞などに強いため、ベクトル検索が弱い質問をカバーします）
最後にCohereなどのrerankモデルを用いて並べ替えを行い、最終的にLLMが回答を生成します。

# 5. Evaluation　
この一連の処理によって、ChunkRAGは既存手法より10〜15％程度の精度向上を達成したと報告されています（評価にはPopQAというRAG評価で有名なオープンデータセットが用いられています）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/efe56ea3-e34f-2259-530d-e18aa7fefde6.png)

# まとめ（懸念事項）：

1. 小規模モデル（7B、13Bクラス）ではChunkRAGの効果が顕著ですが、高性能なモデル（例：GPT-4）では、もともとモデル自体がある程度情報選別可能なため、フィルタリングの効果は相対的に小さくなる可能性が高いと思われます。
2. また、コスト面の問題もあります。すべてのチャンクに対してLLMでスコアリングするため、処理時間やAPIコストがかなり膨大になります。

とはいえ、この論文を読むことでRAGの基本的な問題点や改善手法を学ぶことができるため、一読の価値はあると思います。

興味ある方：

https://arxiv.org/abs/2410.19572
KDE 環境で一部の Qt 系アプリケーションで日本語入力ができない


[Linux Advent Calendar 2024](https://qiita.com/advent-calendar/2024/linux) 8日目の記事です。

## 入力ができない

タイトル通りなのですが、KDE Plasma 6 の環境下で、Qt 系のアプリケーションの入力が一部できなくて困っていました。

具体的には Lokalize と Krita です。Qt 系でも Dolphin や Konsole などの他の殆どのアプリケーションは日本語入力ができるので、謎です。

## 解決策

### CUI

起動時に環境変数を使えば、日本語入力が正常にできるようになります。

```sh
QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx アプリケーション
# 例: QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx krita
```

### GUI

GUI では、以下のように設定します。

アプリケーションランチャーを開き、設定するアプリケーション (今回は Lokalize) を右クリックします。その中の項目から、"アプリケーションを選択"をクリックします。

![Screenshot_20241207_194721.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769460/209817b4-136d-438e-c5e8-b2d622dda1e6.png)

アプリケーションのプロパティが出てくるので、上のタブから"アプリケーション"を選択し、上から4個目の"環境変数"に `QT_IM_MODULE=fcitx XMODIFIERS=@im=fcitx` を追加します。

![Screenshot_20241207_194752.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2769460/241212b9-6e09-6ca0-6407-34600098e021.png)

以上です。この状態でアプリケーションを起動すると日本語が入力できるようになっているはずです。

## 原因

根本的な原因はよくわかりませんが、おそらく Plasma 6 になったときに日本語の設定方法が変更されたからだと思います。

Plasma 6 では、環境変数の `QT_IM_MODULE` と `GTK_IM_MODULE` を空にすることが推奨されています。([Plasma 6 の日本語環境設定方法](https://zenn.dev/phanect/articles/b71be371a061ff#3.-確認))

しかし、Lokalize や Krita などの一部のアプリケーションではこれらの環境変数が `fctix` になっていないといけない?ようです…

Krita は KDE Frameworks 5 (Qt5) ベースなので、バージョンによる問題か…?と思ったのですが、Lokalize は KDE Frameworks 6 (Qt6) ベースっぽいので、特に関係なさそうですね。謎です。
自動化導入時の挑戦と学び

##  導入前の準備と専門用語の壁
テスト自動化を導入する際には、まずその概念や必要なツール、フレームワークについて学ばなければなりません。これらはすべて専門的な用語や技術に基づいており、初めて触れる人にとってはかなりハードルが高いと感じます。特に「CI/CD」や「バージョン管理」、「テストランナー」といった言葉が飛び交う中で、何から手をつけてよいのか分からず、ネットで調べることが多くありましたが、導入出来たらとても良い感じでした。
【AWS】Railsの自動デプロイ

# 記事概要
AWSサーバーを本番環境として利用している場合のデプロイ方法を説明する。

# 言語やフレームワーク
|| 使用技術 |
| ---- | ---- |
| フロントエンド | HTML |
| バックエンド | Ruby 3.2.0 <br> Ruby on Rails 7.0.8.6 |
| データベース | MySQL(mariadb) |
| インフラ | AWS |
| API | - |
| その他 | Capistrano(Gem) <br> Unicorn(Gem) |

# 前提
- 1度AWSサーバーにデプロイ済みである
- GemのCapistranoを適用している
- GemのUnicornを適用している
- GitHubのリポジトリを連携している

# パターン別のデプロイ手順
| 状況 | 参照手順 |
| ---- | ---- |
| ローカルでVSCodeを修正 | ①③ |
| ローカルでデータベース関連の内容を修正 | ①②③ |
| 本番環境でサーバーを再起動 | ③ |
| Nginxを修正 | ④ |


# 手順①
1. 変更点をリモートリポジトリにcommit→pushの実行
1. mergeの実行
1. ローカルリポジトリにpullの実行

# 手順②(DB再起動)
1. EC2にログインするため、ターミナルにて下記を実行
    ```
    % ssh -i ~/.ssh/my-key-pair.pem ec2-user@<EC2インスタンスに紐付けたElastic IP>
    ```
1. 本番環境のDBを再起動するため、EC2ユーザーでターミナルにて下記を実行
    ```
    % RAILS_ENV=production DISABLE_DATABASE_ENVIRONMENT_CHECK=1 bundle exec rails db:drop
    % rails db:create RAILS_ENV=production
    % rails db:migrate RAILS_ENV=production
    ```
1. シード値の適用が必要な場合、下記記事を参照
    https://qiita.com/likapantrip/items/a49c004bccbc1fd5f6fe

# 手順③(デプロイの実行)
1. EC2にログインするため、ターミナルにて下記を実行
    ```
    % ssh -i ~/.ssh/my-key-pair.pem ec2-user@<EC2インスタンスに紐付けたElastic IP>
    ```
1. Unicornのプロセスを停止するため、EC2ユーザーでターミナルにて下記を実行
    ```
    # 実行中のプロセスを確認
    % ps aux | grep unicorn

    # プロセスを停止
    % kill <確認したunicorn rails masterのプロセスid>

    # Unicornのプロセスが停止していることを確認
    % ps aux | grep unicorn
    #=> ec2-user   758  0.0  0.0 119436   920 pts/0    S+   10:07   0:00 grep --color=auto unicorn

    # 「ps aux | grep unicorn」コマンドのプロセスが存在するため、上記のような結果が1行返ってくる
    ```
1. ログアウトするため、EC2ユーザーでターミナルにて下記を実行
    ```
    % exit
    ```
1. デプロイするため、ターミナルにて下記を実行
    ```
    # アプリのディレクトリにいることを確認
    % pwd
    /~/[アプリ名]
    
    % bundle exec cap production deploy
    ```

# 手順④(Nginxを適用)
1. EC2にログインするため、ターミナルにて下記を実行
    ```
    % ssh -i ~/.ssh/my-key-pair.pem ec2-user@<EC2インスタンスに紐付けたElastic IP>
    ```
1. Nginxを再起動するため、EC2ユーザーでターミナルにて下記を実行
    ```
    % sudo systemctl restart nginx
    ```