OmniAICreator/Qiita-1.07M huggingface dataset:
AIボイスチェンジで実況をしようとしたときの苦労点

# ゴール
AI音声実況を作ること

---

# 今回の実況プロセス
実況音声を前撮り→AIボイスチェンジャー
※リアルタイム変換や歌の変換は面白いけど対象外

---

# 技術選定
・ゴールが実現できればなんでもいい！
・自分の声にマッチする

---

# 自分の声について
・低い（バリトンくらいはある）
・滑舌に問題はない

---

# ①Parakeet voice changer
・アルファ版でUIが安定しない
・割と早期に有料化しそう
・使ってみたけどそもそも出力結果が安定しない
・総じて学習コストの高さを感じる

---

# ②NEUTRINO Diffusion
・調査段階で実況に使っている事例が少ない印象
・公式ページを見ても使用感をイメージできない
・調査段階で早々に断念

---

# ③RVC WEBUI（これに決定）
・オープンソース
・リアルタイムボイスチェンジに焦点
・録音もいける
・学習データが作れる
・事例も豊富

---

# ④Style-Bert-VITS-2
・AIゆっくり実況
・ボイスチェンジではない
・実況生成AI
・実況生成なのに抑揚があって面白いが、今回のゴールとは異なる
・使用感…自分で一切発声したくない人には最高

---

# RVCの参考記事①
https://pcniki.com/retrieval-based-voice-conversion-webui/
・インストール
・モデルの作成
・声とBGMの分離
・ボイスチェンジ
の方法が書かれている。
歌を歌わせることはできるが、アカペラが出力される。
アカペラと伴奏の合成、モデルマージ（推論の精度を上げる）、実況のボイスチェンジについてはほぼ書かれていない。

---

# RVCの参考記事②
https://note.com/05180219/n/n78c84c232414
・①よりも新しくて網羅的
・モデルマージの方法も書かれている

---

# 参考にしたうえで苦労する点
・素材が見つからない→BGMと声が分離され、対象のみが切り抜かれた動画/音声なんて見つかるはずがない→自分で素材を集め、編集して切り抜き動画/音声を作るくらいは必要である
・ファイルを追加した後、適切に動作しないことがある→アプリをスーパーリロードないし再起動する
・とにかく時間がかかる→素材集めはこだわれば終わりがなく最も大変な作業である。とりあえず1分ぶんのセリフを用意できれば始めて良いと思う
・学習結果の質や声質や声音によってはボイスチェンジが機能しないこともある。機能しなかった際の問題の切り分けが難しい
（TF2.16）TensorFlowのバージョンを上げたらKeras3も落ちてきて、古い saved model が読み込めなくて、Keras2互換にして対処した件

# 何が起きた
わい「GWやし趣味開発しよ。さいつよモデル作るんや。」

わい「もうTensorFlowも2.16か～。せや、お古のモデル、読み込んでみよ。」

TensorFlow・Keras「お前のモデル古すぎワロタ。時代は.keras 形式やで。出直せや。」

結論からいうと、
* **TensorFlow2.16**から**Keras3**が使われるようになった
* Keras3でsaved_modelをtf.keras.model.load_modelで読み込めなくなった
* 解決には、別のAPIを使うかKeras2を使う必要がある（**後でKeras2を使う方法を詳述**）

モデルの読み込み以外でも参考になると思い、筆を執りました。

<details> <summary> 詳しい設定・エラーメッセージはこちら。</summary>

## 設定

|項目|値|
|---|---|
|モデル作成時TensorFlowバージョン|2.8.2|
|モデル作成時Kerasバージョン|2.8.0|
|モデル形式|keras.Model.saveでsave_format="tf"として保存したsaved model形式|
|読み込み時TensorFlowバージョン|2.16.1|
|読み込み時Kerasバージョン|3.0.5|
|読み込み方法|tf.keras.models.load_model|

## エラーメッセージ
```
Traceback (most recent call last):
  File {ファイルパス}, line {行数}, in <module>
    m = tf.keras.models.load_model({モデルのパス})
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/usr/local/lib/python3.11/dist-packages/keras/src/saving/saving_api.py", line 191, in load_model
    raise ValueError(
ValueError: File format not supported: filepath={モデルのパス}. Keras 3 only supports V3 `.keras` files and legacy H5 format files (`.h5` extension). Note that the legacy SavedModel format is not supported by `load_model()` in Keras 3. In order to reload a TensorFlow SavedModel as an inference-only layer in Keras 3, use `keras.layers.TFSMLayer({モデルのパス}, call_endpoint='serving_default')` (note that your `call_endpoint` might have a different name).
```
</details>

# 解決策
解決には、別のAPIを使うかKeras2を使うアプローチがあります。
別のAPIを使う方法は、エラーメッセージに従ってTFSMLayerを使う方法や、tf.saved_model.loadを使う方法です。ただ、今回試したモデルでは上手くいかなかったので、これは諦めました。

ということで、Keras2を使う方法です。

## Keras2を使う方法
以下のリリースノートの「To continue using Keras 2.0, do the following.」のくだりを参考にしました。

https://github.com/tensorflow/tensorflow/releases/tag/v2.16.1

リリースノートに、以下のようにtf-kerasを介してKeras2を使う方法が説明されています。

* （共通） tf-kerasをインストール（pip install tf-keras~=2.16等）
* （方法1）環境変数の設定（TF_USE_LEGACY_KERAS=1）を行って実行する
* （方法2）tf.keras の代わりに import tf_keras してtf_kerasを用いる

方法1も方法2もtf-kerasのインストールが必要です。方法1は、環境変数でtf.kerasの実体をtf_kerasに変更している感じです。

以上。
Data Structure

## Data Structure
### Topics
- List
- Set
- Map
- Stack 
- Queue
## Why do we learn Data structure?
- to store data and process data efficiently.
-
![Screenshot 2024-04-27 at 14.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/6ca9d80b-3a1e-7b90-a204-5aa664a1850f.png)

![Screenshot 2024-04-27 at 14.50.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/75d530dd-7706-1e9e-4f9e-95054675d308.png)

## List
Can store single data type of many object
### Two Types of Lists
- Array List
- Linked List

### Array List
List that uses Array as internal function.
var array = new int[10];
### Pros
O(1)
- To get
- To access
### Cons 
O(n)
- Insersation
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/b8cfc5cf-9306-03d3-1d30-94516f20cad0.png)

- Deletion -> has to shift values
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/d9d11293-3631-2cdc-8a7c-1c86199489b8.png)

- Search

### Lincked List
List that uses "Node" as internal function

### Pros
O(n)*O(1)
- Insertion
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/60d60f75-7ed0-a47b-327d-9c2d2f408411.png)

- Deletion
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/2153a4b7-4533-c333-2042-46e66e05a204.png)

- Append

### Cons 
O(n)
- Get
- Search 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779552/d48f8b2e-ea33-a0cf-d53d-451cb3215f8e.png)

### Two Types of Lincked Lists
Singly Lincked List
- Head

Doubly Lincked List
-Head 
-Tail
### Set
- Orderless
- no duplicates

What cases we can use?
Ex) Types of car, cakes...

Map
- Orderless
Dictionary in pyton

Key-Value Set

cakePriceMap = {"CheesesCake": 190, "ChocolateCake": 220, "PlainCake": "120", "StroberryCake": 250}

cakePriceMap.get("CheesesCake") returns 190

CalculateMemoryPosition("CheesesCake") -> Memory Position

### **Runtime**

cakeList = ["CheesesCake", "ChocolateCake", "PlainCake", "StroberryCake"] priceList = [190, 220, 250, 320]

List Search -> O(n)

Map Search -> O(1)

Search -> O(1) Insertion -> O(1) Deletion -> O(1) Access -> O(1)

### **Cons**

- Lower storage efficiency
- Collision
    - Lower runtime
    - 75 %
    - depends on Quolity of Hash function
- Orderless

### **HashMap**

Uses Hash function to calculate memory position

## **Stack**

FILO

LIFO

積み重ねる

## **Queue**

FIFO
Unveiling the Future of Web Design in Qatar

In the heart of the Middle East, Qatar stands as a beacon of innovation and progress. As the digital landscape continues to evolve, so too does the realm of web design. In Qatar, web design is not merely about aesthetics; it's a reflection of the nation's ambition and vision for the future. In this article, we delve into the intricacies of web design in Qatar, exploring its current state and envisioning its future trajectory.

Embracing Cultural Identity in Web Design
Web design in Qatar is deeply rooted in the nation's rich cultural heritage. From the vibrant colors of traditional Qatari architecture to the elegant calligraphy of the Arabic language, Qatar's web designers draw inspiration from their surroundings to create visually captivating digital experiences. By seamlessly integrating cultural elements into their designs, they not only pay homage to their heritage but also foster a sense of pride and identity among users.

The Intersection of Technology and Innovation
As a leading hub for technology and innovation in the region, Qatar is at the forefront of web design trends. With a strong emphasis on user experience and accessibility, Qatari designers leverage cutting-edge technologies such as responsive design and interactive interfaces to deliver seamless browsing experiences across devices. Moreover, Qatar's commitment to sustainability is reflected in web design, with an increasing focus on energy-efficient practices and eco-friendly design principles.

Navigating the Digital Landscape
In a rapidly evolving digital landscape, Qatari businesses recognize the importance of establishing a strong online presence. Web design plays a pivotal role in shaping the perception of brands and businesses, serving as a virtual storefront that welcomes visitors from around the globe. With user engagement and conversion rates at the forefront of their priorities, Qatar's businesses invest in web design strategies that not only captivate audiences but also drive measurable results.

The Future Outlook: Innovating Beyond Boundaries
Looking ahead, the future of web design in Qatar is filled with boundless possibilities. As emerging technologies such as artificial intelligence and virtual reality continue to reshape the digital landscape, Qatari designers are poised to push the boundaries of creativity and innovation further. From immersive storytelling experiences to personalized user interfaces, the future of web design in Qatar promises to be both exhilarating and transformative.

Conclusion: Shaping the Digital Destiny of Qatar
In conclusion, web design in Qatar is a dynamic and ever-evolving field that reflects the nation's spirit of innovation and progress. By embracing cultural identity, leveraging technology, and embracing sustainability, Qatar's designers are charting a course towards a digital future that is as inspiring as it is impactful. As we look towards the horizon, one thing is certain: the future of https://www.go-globe.com/web-design-qatar.phpis bright and full of promise.
繰り返し処理と並列処理の簡単な比較

## はじめに

ある処理について、複数回の実行を要する場面があります。このとき、処理間の前後関係に制約がない場合は、繰り返し処理（for文やwhile文）や並列処理がその実現方法として挙げられます。今回は、繰り返し処理と並列処理の簡単な比較として、コードと実行時間の違いについて紹介します。

:::note info
以降に挙げる例はGoogle Colaboratory[^1]で実行しています。
:::

[^1]:https://colab.google/

## 複数回の実行を要する処理の例

```python:複数回の実行を要する処理の例
import random
import time


def process(num):
    """
    本記事におけるある処理。
    ある程度の時間がかかる処理と仮定し、1msの一時停止をした後にランダムな数値を出力する。
    """
    time.sleep(0.001)
    random.seed(num)
    return num, random.random()
```

## 繰り返し処理の例

```python:繰り返し処理の例+時間計測
%%timeit

if __name__ == "__main__":
    nums = range(1, 1_001)
    results = []
    for num in nums:
        result = process(num)
        results.append(result)
```

```sh
1.13 s ± 7.37 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

## 並列処理の例

今回、並列処理は`concurrent.futures.ProcessPoolExecutor`[^2]というクラス（以降、`ProcessPoolExecutor`）により実現させます。

[^2]:https://docs.python.org/ja/3/library/concurrent.futures.html#concurrent.futures.ProcessPoolExecutor

今回の実行環境において、利用可能なCPUのコア数は2となります。

```python:実行環境における利用可能なCPUのコア数の確認
import os


os.cpu_count()
```

```sh
2
```

`ProcessPoolExecutor`で指定する並列数は、そのまま利用可能なCPUのコア数（2）とします。

```python:並列処理の例+時間計測
%%timeit

import concurrent.futures


if __name__ == "__main__":
    nums = range(1, 1_001)
    results = []
    with concurrent.futures.ProcessPoolExecutor(max_workers=os.cpu_count()) as executor:
        futures = [executor.submit(process, num) for num in nums]
        for future in concurrent.futures.as_completed(futures):
            if future.exception():
                raise Exception(f"{future.exception()}")
            else:
                results.append(future.result())
```

```sh
702 ms ± 17.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
```

実行時間について、繰り返し処理では平均で1.13msでしたが、並列処理の場合は平均で702msでした。つまり、今回の例においては、繰り返し処理を並列処理に書き換えることによって、実行時間の短縮という恩恵が得られます。

今回の例に基づいて、繰り返し処理から並列処理に書き換える場合の差分は以下となります。

```diff_python:差分（繰り返し処理から並列処理に書き換える場合）
+ import concurrent.futures
+
+
  if __name__ == "__main__":
      nums = range(1, 1_001)
      results = []
-     for num in nums:
-         result = process(num)
-         results.append(result)
+     with concurrent.futures.ProcessPoolExecutor(max_workers=os.cpu_count()) as executor:
+         futures = [executor.submit(process, num) for num in data]
+         for future in concurrent.futures.as_completed(futures):
+             if future.exception():
+                 raise Exception(f"{future.exception()}")
+             else:
+                 results.append(future.result())
```

## まとめ

繰り返し処理と並列処理の簡単な比較として、コードと実行時間の違いについて紹介しました。今回の例においては、実行時間の観点で、並列処理の方が優れていました。ただ、要件や制約によってどちらが望ましいかが変わるため、それらの整理や計測を踏まえて判断することを推奨します。
ubuntu24.04 に rfriends3 を インストールして ラジオを録音する。

#ラジオの録音サーバを ubuntu24.04で 作る

今回設定する rfriends3 は いろんな OS に 対応してるので、余ってるPC等にインストールすることが できる。

https://rfriends.hatenablog.com/entry/2023/07/13/152412


今回は ubuntu24.04 が リリースされたので ubuntu用の 手順で 試してみます。

https://rfriends.hatenablog.com/entry/2024/02/23/173528

今回は proxmox VEの vm として ubuntu server を インストールしました。

https://ubuntu.com/download/server

から ISOファイルを ダウンロードして ISOフォルダに アップロードして新しいvmを 作成しました。

https://releases.ubuntu.com/24.04/ubuntu-24.04-live-server-amd64.iso を 指定して ダウンロードすることも できますね。

さて、OS を インストールする途中で openssh-server を 使う設定にしてsshで アクセスできるようにしておきました。

あとは sshで 接続して 設定します。

２．確認事項 の 時刻の確認で GMTだったので次のコマンドで JSTにしました。

```shell
sudo timedatectl set-timezone Asia/Tokyo 
```
説明には sudo なかったんだけど つけて実行しました。

あとは 説明通り

```shell
cd ~
sudo apt install -y wget unzip
wget http://rfriends.s1009.xrea.com/files3/rfriends3_ubuntu_full.zip
unzip rfriends3_ubuntu_full.zip
cd rfriends3_ubuntu_full
sh rfriends3_ubuntu_full.sh
```

と 実行して

ip addr で IP アドレスを 確認して
出力された IPv4アドレスのポート8000 へ  ブラウザで アクセスします。

```shell
shooskay@ubuntu:~/rfriends3_ubuntu_full$ ip -4 addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: ens18: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    altname enp0s18
    inet 10.11.8.122/24 brd 10.11.8.255 scope global ens18
       valid_lft forever preferred_lft forever
```
と表示されたので `http://10.11.8.12:8000` に  アクセスします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125882/d1ee6f20-b2bd-284e-702f-9e38cad7ab04.png)

こんなかんじで 表示できれば OKです。（画像は 借り物です。）

共通 の キーワードファイルに アニソンを 設定して 放置プレイ しておきます。
AWS EventBridgeスケジューラが便利すぎた！

## 概要

AWSを使っていたら、いつの間にかEventBridgeにスケジューラという機能が追加されていたので、使ってみたら便利すぎたって話！

2022年末にリリースされていたみたいです。

実際にコスト削減に成功した話は、こちらをご覧ください。↓
**[AWS EventBridgeスケジューラで圧倒的コスト削減に成功した話](https://qiita.com/Nightley_dev/items/54ce272509f2a9a48b30)**

## EventBridgeスケジューラとは

EventBridgeスケジューラとは、定期的なイベントを、自動的にトリガーするためのサービスです。「毎日」「何時間ごと」など、時間に依存したタスクを事前にスケジューリングすることで、タスクを自動で管理することができます。スケジュールは、cron式、あるいはレート式を使用して設定します。スケジューラを使用することで、手動でタスクを管理するときに生じる人為的なミスを防ぎ、簡単にタスクを管理することができます。

## EventBridgeルールとの違い

EventBridgeルールは、イベントパターンやスケジュールに基づいてタスクを管理する機能です。EventBridgeスケジューラは、EventBridgeの機能のひとつで、スケジュールに基づくタスク管理に特化しています。

EventBridgeルールと比較して、扱えるAWSリソースが多いため、時間依存の実行タスクについては、EventBridgeスケジューラを活用することで、最適な運用を目指すことができます。

EventBridgeスケジューラは、UTC以外の様々なタイムゾーン・サマータイムをサポートしており、270以上のサービス、6000以上のAPIをターゲットとして指定できます。

## EventBridgeスケジューラ使用してコスト削減してみたリソース

- ECS
    - devやstg環境で夜間帯のタスクを0に変更、本番環境のタスクを減少
- RDS
    - devやstg環境で夜間帯インスタンスをダウン
- VPCエンドポイント
    - devやstg環境で夜間帯インターフェイスタイプのVPCエンドポイントを削除

などです。

大きなコスト削減効果が見込めるほか、オートスケーリングに加えて積極的なスケーリングにより、パフォーマンスを安定させることが可能です。

詳細は別の記事で紹介します！

## Lambdaは不要？

以前はEventBridgeルールとLambdaでコントロールしていましたが、EventBridgeスケジューラのAWSリソースのカバレッジが広いため、Lambdaは不要か？というとそんなことはありません。

前述のVPCエンドポイントの削除→作成ステップを実現する場合、EventBridgeスケジューラだけでは新しく作成されたVPCエンドポイントを削除時に特定することができません。

タグなどでフィルタして特定できれば良かったのですが、パラメータが対応していませんでした。

上記のようなケースでは本記事作成時点で、やはりLambdaやStepFunctionsを使うしかないのかなと思います。

![スクリーンショット 2024-04-22 12.37.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2981403/a34e08b4-7dcb-662e-865f-62189d748c3d.png)


## 最後に

本機能を知ってからというもの便利すぎて使い倒しております！

やはりお手軽かつ多様なAWSリソースをコントロールできるのがいいですね。

EventBridgeスケジューラを使用して、コスト削減した際のコードを見たい方は、次の記事をご覧ください！↓

**[AWS EventBridgeスケジューラで圧倒的コスト削減に成功した話](https://qiita.com/Nightley_dev/items/54ce272509f2a9a48b30)**
Elixirでシングルコア／マルチコア性能ベンチマークを走らせてみたらM3 Maxの方がM1 Ultraより速かった

[ElixirのCPUバウンド並列処理ベンチマーク](https://qiita.com/zacky1972/items/fc317a7aa4a132a33ef3)を使って，M3 Max 全部入りとM1 Ultra全部入りのシングルコア／マルチコア性能を比較してみたところ，M3 Maxの方がマルチコア性能で2.5倍，シングルコア性能で1.24倍速かったです！


```elixir:bench.exs
Mix.install([:flow, :benchee])

Benchee.run(
  %{
    "sequential execution" => fn -> 1..1_000_000 |> Enum.map(fn _ -> :crypto.strong_rand_bytes(1000) end) |> Enum.map(& Base.encode32(&1, case: :lower)) end,
    "parallel execution" => fn -> 1..1_000_000 |> Flow.from_enumerable() |> Flow.map(fn _ -> :crypto.strong_rand_bytes(1000) end) |> Flow.map(& Base.encode32(&1, case: :lower)) |> Enum.to_list() end
  }
)
```

```zsh: elixir -v on M3 Max
Erlang/OTP 26 [erts-14.2.4] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit]

Elixir 1.16.2 (compiled with Erlang/OTP 26)
```

```txt:benchmark results (M3 Max)
Operating System: macOS
CPU Information: Apple M3 Max
Number of Available Cores: 16
Available memory: 128 GB
Elixir 1.16.2
Erlang 26.2.4
JIT enabled: true

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s

Benchmarking parallel execution ...
Benchmarking sequential execution ...
Calculating statistics...
Formatting results...

Name                           ips        average  deviation         median         99th %
parallel execution            2.55         0.39 s     ±2.48%         0.39 s         0.40 s
sequential execution          0.36         2.76 s     ±4.98%         2.76 s         2.86 s

Comparison: 
parallel execution            2.55
sequential execution          0.36 - 7.06x slower +2.37 s
```

```zsh: elixir -v on M1 Ultra
Erlang/OTP 26 [erts-14.2.4] [source] [64-bit] [smp:20:20] [ds:20:20:10] [async-threads:1] [jit]

Elixir 1.16.2 (compiled with Erlang/OTP 26)
```


```txt:benchmark results (M1 Ultra)
Operating System: macOS
CPU Information: Apple M1 Ultra
Number of Available Cores: 20
Available memory: 128 GB
Elixir 1.16.2
Erlang 26.2.4
JIT enabled: true

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 5 s
memory time: 0 ns
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 14 s

Benchmarking parallel execution ...
Benchmarking sequential execution ...
Calculating statistics...
Formatting results...

Name                           ips        average  deviation         median         99th %
parallel execution            1.02         0.98 s     ±5.48%         1.00 s         1.01 s
sequential execution          0.29         3.41 s     ±3.94%         3.41 s         3.50 s

Comparison: 
parallel execution            1.02
sequential execution          0.29 - 3.47x slower +2.42 s
```
【Vue.js】Vue Routerでスクロール位置を制御しよう【初心者向け】

# はじめに
Vue.jsを使用して実装している最中に、こんな状況に陥ったことはありませんか？

「ページ遷移した際に、前ページのスクロール位置が引き継がれてしまい、新しいページが最上部から表示されない」

私自身はVue.jsを学習し始めて3ヶ月程度の時にこの課題に直面し、JavaScriptの`scrollTop()`や`scrollIntoView()`などを使って試行錯誤を繰り返していましたが、なかなか上手くいかなかった記憶があります...

### 結論
この課題に対しては`Vue Router`の`scrollBehavior()`を使用して解決可能です。

# そもそも何故前ページのスクロール位置が引き継がれるの？

この挙動は、ブラウザのデフォルトの挙動によるものです。Vue.jsやその他のSPA(シングルページアプリケーション)では、JavaScriptを使用して動的にコンテンツを読み込むため、挙動が異なります。

### ブラウザとSPAにおける挙動の違い
ブラウザは通常、ユーザーがページを離れたときのスクロール位置を記憶し、同じページに戻った時にその位置に自動で戻る機能を持っています。これは、同一ページ内でリンクをたどったり、ページを再訪したりする場合に便利です。この機能は、HTMLの仕様である `History API` の一部として実装されています。しかし、SPAではページ間の遷移が実質的には同一ページ内でのビューの切り替えとなるため、ブラウザは自動的にスクロール位置をリセットしません。これは、ページ遷移が物理的に新しいページへの移動として認識されないためです。


# 解決方法
`Vue-Router`の`ScrollBehavior()`関数を活用してこの課題を解決しましょう。


既存の`createRouter()`内の処理に`scrollBehavior()`の処理を追加します。

以下はページ遷移時に必ずページの最上部から表示させるための例です。

```typescript
const router = createRouter({
  scrollBehavior(to, from, savedPosition) {
    return { top: 0 }
  },
})

```

`scrollBehavior()`内の引数はそれぞれ以下を指しています。

1. to: 遷移先のルートオブジェクト
2. from: 遷移元のルートオブジェクト
3. savedPosition: ブラウザの進む・戻る操作によるページ遷移で、以前のスクロール位置が保存されている場合にこの位置情報を含むオブジェクト

https://router.vuejs.org/guide/advanced/scroll-behavior

# おわりに
`Vue Router`の`scrollBehavior()`を適切に利用することで、SPAにおけるスクロール位置を制御し、ナビゲーションのユーザーエクスペリエンスを大きく向上させることができます。今回紹介した基本的な例から始めて、要件に応じてカスタマイズを進めてみてください。
docker-composeでPostgreSQLを実行したらinit.sqlが実行されなかった

## 今回の事象
docker-compose.ymlに記述したPostgreSQLのinit.sqlが起動時に実行されなかった。
下記の記事を見てvolumesの削除を試みたが、何も変わらなかった状態。
https://qiita.com/kondo0602/items/ab0a85fb1e731234eb1a

```
(抜粋)docker-compose.yml
postgres:
    image: postgres:latest
    container_name: my_postgres
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - ./data:/var/lib/postgresql/data
      - ./init:/docker-entrypoint-initdb.d
```
```
init.sql
-- テーブル作成
CREATE TABLE my_table (
    id serial PRIMARY KEY,
    name VARCHAR (100) NOT NULL
);

-- サンプルデータの登録
INSERT INTO my_table (name) VALUES ('John Doe');
```

## 原因
どうやら下記の記事によるとdataディレクトリ配下にファイルがあるとinit.sqlは実行されないとのこと。
恐らくパスの指定ミスでdocker-compose up時にinit.sqlが実行されずdataディレクトリ配下にファイルが作成されたことが原因。コンテナを再実行しても初期化がスキップされていた。
https://stackoverflow.com/questions/59715622/docker-compose-and-create-db-in-postgres-on-init

### 補足
docker-compose logsで下記のエラーが表示されていたら初期化はスキップされています。（dataディレクトリ配下にファイルが存在する状態）
PostgreSQL Database directory appears to contain a database; Skipping initialization

## 対処
data配下のファイルを全て削除した上で、docker-compose upを再実行。
→psqlを叩くと無事解消されていた。

```
postgres=# \dt
             リレーション一覧
 スキーマ |   名前   |  タイプ  |  所有者  
----------+----------+----------+----------
 public   | my_table | テーブル | postgres
(1 行)
```
Sambaファイルサーバーの構築

# 概要
今回はSambaファイルサーバーの構築を行いました。
メモ程度で記載しているためご了承ください。
構築したSambaファイルサーバへなかなかアクセスできず
苦戦いたしましたが、以下の２の参考記事により解決いたしました。

## 実行環境
・Linux:Ubuntu 22.04.4 LTS
・windows：Windows11Pro 23H2
## 参考記事
１.Linux(ubuntu)でSambaファイルサーバを構築していきます。
以下を参考にしました。

https://aquarius-train.hatenablog.com/entry/Samba%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E8%A8%AD%E5%AE%9A%E6%89%8B%E9%A0%86%E3%81%A8Windows%E3%81%8B%E3%82%89%E3%81%AE%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E6%96%B9%E6%B3%95

https://qiita.com/NaoyaOgura/items/f9fa3ab45e26f543ecc9

※以下のようにsmbd,nmbdとすると正常に実行されましたが、
　smb,nmbとするとエラーにより実行されませんでした。
$ systemctl enable smbd
$ systemctl enable nmbd



２.Sambaファイルサーバにアクセスできなかったため以下の記事を参考にしたらアクセスができました。

https://qiita.com/tatsuya-k_net/items/5f41aa0f84c039a99efa

※以下を順番に実行しました。
>net use \\サーバー名 /delete　
>net use \\サーバー名 /user:ユーザー名

(例)
>net use \\\○○.○○.○○.○○\hogehoge /delete
グラフニューラルネットワーク Chapter2 準備


研究室の輪講用にスライドを作成したので公開します．
具体例を多めに載せて可能な限りわかりやすくしました．
ただし， 「2.3 古典的なグラフ機械学習手法」は証明などを省いています．


https://speakerdeck.com/snoo_py/gurahulun-jiang-gurahuniyurarunetutowaku-chapter2-zhun-bei

間違いがあればご指摘を頂けると幸いです．
【AWS】CLIでスイッチロールする際MFA認証を強制する方法

## 前置き
コンソールからログインする際、MFA認証をするよう設定しているのですが、
CLIからアクセスする際、コンソールに合わせてMFA認証を強制した場合、
スイッチロールする時のコマンド分からなかったので調べてみました。

## 前提条件
・IAMの多要素認証(MFA)でデバイスの割り当てが完了していること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522793/92a04597-05df-1bc0-63c7-bdcbf4b69c63.png)
・AWS CLIがローカルPCにインストール済みであること
(以下のコマンドで確認。バージョンが表示されればインストール済み。)
```ターミナル
aws --version
```

## 設定方法
まずはスイッチロールの設定から。スイッチロール先(アカウントBとする)のIAMで
ロールを作成してアタッチします。許可ポリシーは任意で設定してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522793/ee6545e7-12d7-a47e-87af-d1ab22bbc746.png)
信頼関係タブをクリックし、信頼ポリシーを以下のように編集します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522793/9b97bc06-310c-09a0-804c-5f4c590d543b.png)
スイッチロール元(アカウントAとする)のIAMでポリシーを作成してアタッチします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3522793/828e679a-b0de-62a9-7004-3ebb4d439611.png)
~/.aws/configを以下のように編集します。
```
[profile アカウントA]
region = ap-northeast-1
output = json

[profile アカウントB]
source_profile = アカウントA
role_arn = arn:aws:iam::【アカウントBのアカウントID】:role/【作成したロール名】
mfa_serial = arn:aws:iam::【アカウントAのアカウントID】:mfa/【MFA認証デバイス名】
region = ap-northeast-1
output = json
```
~/.aws/credentialsを以下のように編集します。
```
[アカウントA]
aws_access_key_id = 【アクセスキー】
aws_secret_access_key = 【シークレットアクセスキー】
```

これでスイッチロールをするための権限の付与と、MFA認証の強制が設定できました。
次にCLIでアクセスしてみます。

## コマンド
MFA認証をパスし、一時認証情報を取得します。
```
aws sts assume-role --role-arn arn:aws:iam::【アカウントBのアカウントID】:role/【アカウントBで作成したロール】 --role-session-name 【任意のセッション名】 --profile 【アカウントAのProfile名】 --serial-number arn:aws:iam::【アカウントAのアカウントID】:mfa/【アカウントAのMFAデバイス名】--token-code 【6桁のMFA認証コード】
```
※アカウントA = スイッチロール元のアカウント
※アカウントB = スイッチロール先のアカウント

出力結果
```
{
    "Credentials": {
        "AccessKeyId": "XXXXXXXX",
        "SecretAccessKey": "XXXXXXXX",
        "SessionToken": "XXXXXXXX",
        "Expiration": "XXXX-XX-XXTXX:XX:XXZ"
    },
    "AssumedRoleUser": {
        "AssumedRoleId": "XXXXXXXX:スイッチロール先のプロファイル名",
        "Arn": "arn:aws:sts::アカウントBのアカウントID:assumed-role/アカウントBで作成したロール/XXXXXXXX"
    }
}
```
環境変数に出力された情報を設定します。
```
export AWS_PROFILE=【スイッチロール先のプロファイル名】
export AWS_ACCESS_KEY_ID=【出力されたAccessKeyId】
export AWS_SECRET_ACCESS_KEY=【出力されたSecretAccessKey】
export AWS_SESSION_TOKEN=【出力されたSessionToken】
```
以下のコマンドでスイッチロールできたか確認します。
(Accountがスイッチロール先のアカウントIDになっており、
アカウントBのS3バケットが表示されればOK)
```
aws sts get-caller-identity
aws s3 ls --profile 【アカウントBのProfile名】
```
## 踏み台アカウント(アカウントA)を操作する場合
以下のコマンドで一時トークン発行し、アクセスできます。
```
aws sts get-session-token --serial-number arn:aws:iam::【アカウントAのアカウントID】:mfa/【MFA認証デバイス名】 --token-code 【6桁のMFA認証コード】 --profile 【アカウントAのProfile名】
```
コンピュータはindexというファイルしか気を利かせて読み込まない

この記事ではGitHub Pagesやレンタルサーバーで初めてデプロイ(サービスリリース)した人が
```
「ちゃんとデプロイできてるはずなのにうまく表示されない！涙😭」
```
と悲しんでいるので、そんな人を1人でも減らすための記事になります。

チュートリアル通りデプロイの手順を踏めているはずなのに、GitHub Pagesで発行されたリンクはアクセスしても404エラー(ファイルが存在しない)になっている。そういった方は、rootディレクトリのトップ(githubのリポジトリの一番上の階層)に**index.html**というファイルが存在しているかを確認し直してください。

ちなみにgithub上でのrootディレクトリがどれに相当するかというと


![スクリーンショット 2024-04-30 17.53.01.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/566867/bfad9424-3df9-8cd8-867e-75bb7927732a.jpeg)


の赤枠の部分のファイルの階層のことを指します。
例えば、このリポジトリのcssやjsのフォルダ内はrootディレクトリから外れた階層になります。
なかなかrootディレクトリの考え方が頭に入ってこないということもあるかと思いますが、「そういうルールか」と頭の隅にでも留めておきましょう。

コンピュータは決められたファイル名(index.htmlやindex.php)のものがある場合は、
1. そのファイルを自動で読み込む
1. そのファイル名を省略して表示する
ことが可能です。

index.htmlというファイル名はURLでは省略されていますが、これはURLに打ってもちゃんとブラウザに表示されます。

一番初めに表示させたいファイルは明示的にするためにもindexとつけるようにしましょう。



(参照リンク)

http://honttoni.blog74.fc2.com/blog-entry-120.html 

https://e-words.jp/w/%E3%83%AB%E3%83%BC%E3%83%88%E3%83%87%E3%82%A3%E3%83%AC%E3%82%AF%E3%83%88%E3%83%AA.html
transformers用のREST API（FastAPI）

昨今のLLMの性能向上でそろそろcopilotをローカルに移行できるかも？と思ってfauxpilotを試してみました。

参考

https://qiita.com/tand826/items/0589cd78b3671f77b037

https://qiita.com/taqu/items/ad3e71814e3ad27ec76a

これらを試してみたところ、fauxpilotの公式はtritonサーバーを使っているのですが、これがとても重くて使いにくいなぁとなりました。

というわけでhuggingface transformersを簡単なRESTサーバーとして起動するサンプルを作ってみました。
もちろんただのREST APIなのでfauxpilot用途以外にも使えます。

ソースはここです。

https://github.com/dev999900001111/transformers-simple-rest-api

ポイントは以下の通りです。

- FastAPIを使用してRESTful APIを提供
- OpenAIのAPIと同様のリクエスト・レスポンス形式
- テキスト生成のストリーミングをサポート
- 複数のモデルに対応（モデルパスを引数で指定）
- マルチスレッディングを利用した高速な推論処理

使い方は大体README.mdに書いてある通りです。
これでcodellama2-7b辺りを上げておくと、それなりに補完がされます。
とはいえ、、ちょっとまだcopilotとは張り合えそうにないので、まだしばらくはcopilotに課金です。。。
Bootstrapでフッターを下部に固定したいときの書き方

# はじめに
Bootstrap4.6を使用してサイトを作成した際に、<&#8203;body><&#8203;/body>の中のコンテンツが少ないと中身に合わせてフッターの位置が上に上がってしまっていました。
こんな感じです。

![2024-04-30-Bootstrapのフッター02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/ea446814-ad5a-94c1-b1cf-b41ec06f948a.png)

下に空間があってなんとなくかっこ付かないので、この表示を解消する方法を探してみることにしました。


# ちょっと違う…となったやり方
「Bootstrap　フッター　固定」というような内容で検索して良く見つかるのが「fixed-bottom」を設定するという方法です。
実際にfotterタグの部分に追加してみました。
```html:app/views/layouts/_footer.html.erb
<footer class="bg-dark fixed-bottom">
  <div class='container mt-5'>
  	<div class='row'>
    	<div class='mx-auto text-white'>
    	　<p>Copyright © sample All Rights Reserved.</p>
    	</div>
    </div>
  </div>
</footer>
```
確かにさっきのログインページで見たらきちんとページの最下部に配置されましたが、コンテンツが多くなるとこんな表示になってしまいました。

![2024-04-30-Bootstrapのフッター03.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/ec9c7856-0d99-2ac5-e6f6-3bc9a34c6987.gif)

確かに下に固定されています。
ただ、画面が狭くなってしまい、私がやりたかった表示方法とはちょっと違いました。
また、下に余白がないとコンテンツが隠れてしまったり、この表示を採用する際は少し調整が必要そうです。

# 結論…やりたかったのはこれ
試した結果一番しっくり来たのはこの方法でした。
先ほどはfooterのclassに記述を追加しましたが、こちらの方法ではbody全体のclassに記述しています。
```html:app/views/layouts/application.html.erb
<body class="d-flex flex-column vh-100">
  <%= render 'layouts/header' %>
  <main class="mb-auto">
    <%= yield %>
  </main>
  <%= render 'layouts/footer' %>
</body>
```
bodyの中に、
「header（部分テンプレート）」
「main」
「footer（部分テンプレート）」
が並んでいる形になります。

これらを「d-flex flex-column」で上から順番に並べて、body自体の高さをvh（ビューポート単位のheight）を100%で指定しています。
これだけだとまだfooterの位置を指定できていないので、mainに「mb-auto」を設定してコンテンツを下端まで寄せます。

ちなみに特に触っていませんが、フッターの中はこうなっています。
さっきの「fixed-bottom」をなくしたバージョンです。
```html:app/views/layouts/_footer.html.erb（部分テンプレート）
<footer class="bg-dark">
  <div class='container mt-5'>
  	<div class='row'>
    	<div class='mx-auto text-white'>
    	　<p>Copyright © sample All Rights Reserved.</p>
    	</div>
    </div>
  </div>
</footer>
```

この記述で、ようやくフッターを下に配置することが出来ました…！

![2024-04-30-Bootstrapのフッター.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/c9ae7f73-3d0e-8686-e005-3307362680be.png)

コンテンツの中身が多くなったときはこんな感じの動きになります。

![2024-04-30-Bootstrapのフッター04.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762011/d3afae76-b5f3-ea35-4dc6-7797d28bd642.gif)


# おわりに
CSSに記述する方法もあったのですが、せっかくBootstrapを使っているからBootstrapで解決させたいと思って試行錯誤してみました。

コンテンツの中央寄せや横並びなど、配置の動かし方がいまいち理解しきれていない部分があるので、タグの設定や理屈を理解して上手に活用できるようにしたいです。
ホームページ制作の準備について

##ペルソナを決める
ペルソナとは、架空の人物である。Webサイトを利用する人を、年齢、性別、職業、家族構成、趣味などを具体的に設定します。
ターゲットとはユーザー層であり、クライアントが想定している人です。
ペルソナターゲットに比べて、ピンポイントな人です。

##ライティング、ブランディングをする
ライティングは、掲載する文章のことです。
できるだけリフレーミングして書くことが大切です。Webサイトにおける文章はタイトル、ヘディング、本文に分かれており、どのようにコーディングしていくかを文章を構成する段階で考えとかなければならない。
ブランディングは、商品コンセプトを決めることです。
商品イメージを構成段階で具体的にしていくことです。これにより素早くデザインを行うことができます。

##デザインをする
デザインは、グレースケールでのデザインから始まります。
メニュー、ロゴ、ヘッダー、フッター等をレイアウトします。新規サイト、ブランドサイト、コーポレートサイト、デザインサイトなど決めてから行います。
これによってレイアウトは、基本はZ型、LPであればF型など決まっていきます。
#要素をあらかじめ決める
素早くコーディングを行うにはデザインの段階で要素の大きさなどを決めておく事がたいせつである。
例
・フォントサイズ
50px 42px 36px 20px 16px 8px
・マージン
20px 30px
コンテンツに対してtop:20px bottom:30px　
・ボックス
角丸 5px or 20px
・ヘディング
h1 h2 h3 h4 h5 h6
・レスポンシブ(コンテナ幅)
PC 1000px タブレット 600px スマホ 360px
・ブレークポイント
1920px 1440px 1366px 1280px 1000px 390px
※ブレークポイントは会社によって違います。
【Power Automate】変数を更新する際のエラー対処（自己参照の回避方法）

## はじめに
Power Automate では、変数の値を更新するときにその変数を自己参照ができません。例えば、ループ変数の更新のような「x=x+1」という処理をそのまま書くことができません。そこで、この記事ではこの対処方法について2つのパターン分けて紹介します。

## 変数の自己参照によるエラー

1で初期化した変数xに1を足してx=2に更新する、先ほど例に挙げた「x=x+1」の処理をするフローを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/63dc0b37-2f9f-eba5-9a9a-48d48e42006f.png)

``` :変数の設定：値
add(variables('x'),1)
```

すると、変数の自己参照を含むこのフローを保存するときに下記のエラーが出ます。変数xの更新においてその変数の自己参照はサポートされていないという内容です。

``
The inputs of workflow run action '変数の設定' of type 'SetVariable' are not valid. Self reference is not supported when updating the value of variable 'x'.
``

それでは、このエラーにどのように対処すればいいのでしょうか？

## 足し算と引き算の場合
足し算、引き算には専用のアクションがあるため、以下の2つを使用することで自己参照を避けることができます。
### ① アクション：変数の値を増やす（足し算）
フロー：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/aabdbeaf-529b-dfa0-e72d-4d39b05618dd.png)

実行結果：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/00a9eab1-390c-414d-8fa9-7eb98880bc6d.png)


### ② アクション：変数の値を減らす（引き算）
フロー：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/1e89004d-24ad-307b-20bf-b930b82915bf.png)

実行結果：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/11383aa8-86d3-85c7-e1ff-58562586b875.png)


::: note info
「変数の値を増やす」と「変数の値を減らす」には負の値を入力することもできます。入力する値が常に絶対値で与えられる場合はこの2つを使い分ければいいですが、そうでない（負の値をもつ）場合はどちらかに統一して使用することが望ましいです。
:::

## 掛け算と割り算の場合
掛け算と割り算には専用のアクションがないため、一度、対象の変数の値をコピーして再利用することで自己参照を避けることができます。ここでは、変数の値をコピーする方法を2つ紹介します。

### ① アクション：作成
フロー：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/835cc753-a509-8a9c-819e-e82706b43373.png)

``` :変数の設定：値
mul(output('出力'),2) // output('出力')に2を掛ける -> 1×2=2
```

実行結果：
<img width=500 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/02c6266c-ca9c-cb11-944b-33b5b9103f6b.png")>



### ② アクション：変数の初期化
フロー：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/3b370727-b140-332c-b49f-eb57aac8d327.png)

``` :変数の設定_2：値
div(variables('temp'),2) // variables('temp')を2で割る -> 2÷2=1
```

実行結果：
<img width=500 alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3478860/6d485849-f883-70dc-2850-a76caa9db9fb.png")>

::: note info
複数の処理で変数の値をコピーする場合は「変数の初期化」で変数temp(temporary)を定義して繰り返し使用する、そうでない場合は「作成」で一度だけ使用するなどの使い分けが考えられます。
:::

## おわりに
今回は、Power Automate で変数を自己参照した際のエラーとその対処方法について紹介しました。Power Automate では直接的な自己参照がサポートされていないため、特定のアクションを使って間接的に変数操作を行う必要があります。この記事が少しでも皆さんの課題解決に繋がれば幸いです。
[さくらVPS+Ubuntu]mysqlのインストール

プロジェクトの本番環境構築時、公式見よう見まねでやったもののちょっと躓いたのでメモ。

## 環境
- さくらVPSの1Gを契約している
- OSはUbuntu(22.04)

## 手順

### mysqlのインストール

初期状態ではmysqlがインストールされていないので、入れる。
その前にシステムアップデートをしておく。

```さくらVPS
sudo apt update -y
sudo apt upgrade -y
```

aptコマンドでmysql-serverをインストール

```さくらVPS
sudo apt install mysql-server -y
```

### mysqlのセットアップ

セキュリティ設定ウィザードを起動

```さくらVPS
sudo mysql_secure_installation
```

:::note warn
`sudo`を忘れるとパスワードの入力を求められるので、必ず`sudo`をつける。初期生成されるユーザはパスワード無しで生成されるので、入力する値が存在せず、無駄に時間を食った。
:::

VALIDATE PASSWORDプラグインを入れるか聞かれる。
`y`を入力するとユーザーのパスワードとして設定できる文字列に一定の制限をかけることができる。

私は不要なのでEnterキー押下。

```さくらVPS
Securing the MySQL server deployment.

Connecting to MySQL using a blank password.

VALIDATE PASSWORD COMPONENT can be used to test passwords
and improve security. It checks the strength of password
and allows the users to set only those passwords which are
secure enough. Would you like to setup VALIDATE PASSWORD component?

Press y|Y for Yes, any other key for No:
```

匿名ユーザを削除するか聞かれる。
匿名ユーザが存在するとユーザ名やパスワードなしてmysqlに接続できてしまうので削除する。
`y`を入力してEnter

```さくらVPS
By default, a MySQL installation has an anonymous user,
allowing anyone to log into MySQL without having to have
a user account created for them. This is intended only for
testing, and to make the installation go a bit smoother.
You should remove them before moving into a production
environment.

Remove anonymous users? (Press y|Y for Yes, any other key for No)  :
```

rootによるリモート接続を許可しないか聞かれる。
許可すると、どこからでもrootでmysqlに接続できちゃうのでめちゃくちゃダメ。
`y`を入力してEnter

```さくらVPS
Normally, root should only be allowed to connect from
'localhost'. This ensures that someone cannot guess at
the root password from the network.

Disallow root login remotely? (Press y|Y for Yes, any other key for No) :
```

testデータベースを削除するか聞かれる。
testデータベースはmysqlの親切で、勝手に作られる。
いらないので`y`を入力してEnter

```さくらVPS
By default, MySQL comes with a database named 'test' that
anyone can access. This is also intended only for testing,
and should be removed before moving into a production
environment.

Remove test database and access to it? (Press y|Y for Yes, any other key for No) :
```

権限テーブルをリロードするか聞かれる。
リロードすると今までの設定をすぐ読み込んでくれるようだ。
`y`を入力してEnter

```さくらVPS
Reloading the privilege tables will ensure that all changes
made so far will take effect immediately.

Reload privilege tables now? (Press y|Y for Yes, any other key for No) :
```

あとはmysqlに接続して好きにやる。

## 参考

さくらは公式マニュアル豊富かつ読みやすくて最高なのだ。ありがとうございます。

https://knowledge.sakura.ad.jp/36045/
【RotorHazard】/boot/firmware/config.txtの整理と精査

# 32. 汚れたconfig.txtをキレイにぃ！

### 32-1. RotorHazard Install-Managerで勝手に書き換えられちゃった内容を最適化しておこう

忘れないように記事に書いておきます。ワイはこちらを執筆しているときには、ラズパイ3Bはひとつ前のレガシー版を使っていましたが、2024-03-15に **Debian 12: (bookworm)** のバージョンとしてリリースされました。Qiitaに記事を残しておこうと、本当に最初から作り直しをしていたのですが、実は昨日結構ハマりまして、RotorHazard Install-Managerがちゃんとインストールできない、途中でコケてしまう症状に見舞われました。Pythonのバージョンの関係で起きてしまっているのか正直わからずでしたが、途中で新しいものが出ていることに気付き、せっかくなのでこれをベースにちゃんと手順書として残しておこうと思った次第です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/500291/2a925eac-79c0-49ea-7f85-4f95499d4bcd.png)

結果として、こちらのbookworm 64-bit版で設定しますと特に問題なくインストールが完了しました。ですが、RotorHazard Install-Managerは、ウィザードを使ってインストール時に必要なパラメータを各種ファイルへ反映させますが、**/boot/firmware/config.txt** 内に余計な行や何回も設定すると同一パラメータを何行も追加してしまうのです。なので、最後の最後ではこの **config.txt**をキレイにしてあげる必要があります。


### 32-2. まあ、パラメータの並び順はそこまで気にせずともOK！

それではさっそく編集していきましょう。ちなみにですが **/boot/config.txt ⇒ /boot/firmware/config.txt** とBookworm版は場所が変わっていますのでご注意ください。(過去記事も修正をある程度入れました。)

```
sudo vi /boot/firmware/config.txt
```
```/boot/firmware/config.txtの編集
※下記が今まで含め、新しく行として追加したものの纏め

dtparam=i2c_baudrate=75000
dtparam=uart0=on  　　　　　　　　　　　　# Bookworm and newer
dtoverlay=miniuart-bt
dtoverlay=i2c-rtc,ds3231
dtoverlay=gpio-shutdown,gpio_pin=21,debounce=2000
core_freq=250
enable_uart=1
i2c-bcm2708
i2c-dev

dtparam=pwr_led_trigger=mmc0            # microSD for red
#dtparam=pwr_led_trigger=mmc1           # SSD for red
dtparam=act_led_trigger=heartbeat       # heartbeat for green
#dtparam=act_led_trigger=timer          # slow blink for green

program_usb_boot_mode=1
program_usb_boot_timeout=1
```
整理をしてこうやって見れば、そこまで悩ましい記述はないものと気付いていただけたのではないかと思います。(今後確認したいところとして **i2c-dev** が入っている根拠は今のところ不明ですｗ)

ラズパイ構築編のつづきはこちら

https://qiita.com/tmac116/items/23b539f502914d0638e3
楽天モバイルを固定回線化してspeedtest-cliで回線速度を定点観測

# はじめに
新しい家へ引っ越しした。手っ取り早く通信環境がほしい。光回線の工事が込み合う時期だったのですぐ工事＆開通というわけもいかず、楽天モバイルが約3000円/月で使えるというので、モバイルルーターを手に入れて固定回線化し、speedtest-cliを定期的に走らせて回線速度を測ってみた。

## NW構成
楽天モバイルの端末（Rakuten WiFi Pocket 2C）を固定化、全部有線接続。モバイル回線を安定させせるために、端末はカーテンレールから釣って窓中央になるよう設置した。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/6be7ab64-9a08-f5ab-d9be-605c97c17ea8.png)

## 計測方法
- speedtest-cliを利用
https://www.speedtest.net/ja/apps/cli
- 計測リトライは5回まで
- 10分間隔で3週間定点観測
## 結果
先に結果から。
### 全区間トレンド
- 速度  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/ab9b201e-34c7-17c1-0ec8-310ea2c5b352.png)

- レイテンシ  　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/30d2b94a-64cc-c5f2-a3e0-24e536864b6b.png)

### 曜日、時間帯別トレンド
点群は実データ、実線は各週・時間ごとの中央値を繋いだものである。
- 速度（下り）  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/2b3c6fb2-7f61-d6e4-8880-1888d863d941.png)

- 速度（上り）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/c64bb608-7d66-3c35-f7ea-c9d878a3ced6.png)

- レイテンシ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/a50ad8a1-432a-3843-ba4a-b3f60bba2b45.png)

12時~13時ごろに速度もレイテンシも悪くなる傾向にあることがわかった。速度については、上りは比較的安定しているが、下りは明け方に早く、夕方から深夜にかけては落ち込むことが分かった。

#### 補足
※speedtestでは、計測先のサーバーがかなり離れたサーバーを指定してしまう場合がある。モバイル回線の測定にフォーカスするため、曜日別のトレンド分析には200km以内のデータを採用した。

サーバーまでの距離とレイテンシの関係
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54100/550165a3-2fa9-a70e-05d4-fd888ab60e2c.png)


# 詳細
speedtest-cliはセキュアモードで利用した。取得データはAWS API Gatewayに打ち上げてAWS側で処理できるようにした。（`--json`オプションでjson形式で結果を取得できることは後から分かった。API Gatewayの裏側のLambdaでペイロードを正規表現で処理するロジックを作ってしまった･･･)
```bash:app/speedtest/checkspeed.bash
testres=$(speedtest-cli --secure)

# retry
for i in {1..5} ; do
 if [[ "$testres" == *Download* ]]; then
   break
 else
  testres=$(speedtest-cli --secure)
 fi
done

curl -X POST -H "Content-Type: application/json" -d "${testres}" "https://xxx.execute-api.ap-northeast-1.amazonaws.com/xxx"
```

systemdでbashを実行するためのserviceファイル
```systemd:/etc/systemd/system/bootstrap.service
[Unit]
Description=bootstrap service
After=network-online.target

[Service]
User=ubuntu
ExecStart=/bin/bash /home/ubuntu/app/speedtest/checkspeed.bash
Restart=on-failure
Type=simple

[Install]
WantedBy=multi-user.target
```
10分毎に定期的に実行するためのtimerファイル

```systemd:/etc/systemd/system/bootstrap.timer
[Unit]
Description=bootstrap service
After=network-online.target

[Timer]
OnCalendar=*:0/10

[Install]
WantedBy=timers.target
```

## おわりに
それなりの回線をパパっと用意できたし、3000円/月ならこの質で十分な気もしている。Rakuten WiFi Pocket 2Cは4Gまでの対応だが、5G対応端末に変えたらもっと速度は出るのかもしれない。レイテンシが悪いのが気になるが、YouTube見たりネットサーフィンしているような通常ユースでそこまで困らないので、今のところこの回線で良いかな･･･。
君は論理演算子を知っているか

## はじめに
JavaScript, TypeScriptで論理演算子を利用するときにいつもどっちがどっちだっけ？とわからなくなってしまうのでちゃんと理解するためにまとめようと思います

:::note info
この記事に登場するコードはNode.js v21.4.0で確認しています
:::

## JavaScriptにおける論理演算子
最初に論理積（`&&`）や論理和（`||`）を習う時は以下のように考えがちですが厳密には違います。

- 論理積: どちらもtrueの場合trueが返却される
- 論理和: どちらか一方でもtrueの場合trueが返却される

実際に実行してみると以下のようになります。
```jsx
const test = 10 || true;
console.log(test); // 10
```

どちらもTruthyなデータのため上記のように考えているとtrueが返却されるように思われますが、実際には10が返却されます。

また論理積で試してみると以下のようになります。

```jsx
const test = 10 && 20;
console.log(test); // 20
```

こちらもtrueが返却されるように思われますが、実際は20が返却されます。

本来の論理積、論理和演算子の意味は以下の通りです。
- 論理積: AがFalsyなデータの場合その時点で返却される
- 論理和: AがTruthyなデータの場合その時点で返却される

これを踏まえていくつかパターンを見てみましょう。
```jsx
// 論理積
console.log(10 && 20) // 20
console.log(null && 20) // null
console.log(10 && null) // null
console.log(null && null && 30) // null
console.log((null && null) && 30) // null
console.log((null && 20) && 30) // null
console.log((null && null) && (30 && 40)) // null
console.log((10 && 20) && (30 && 40)) // 40

// 論理和
console.log(10 || 20) // 10
console.log(null || 20) // 20
console.log(10 || null) // 10
console.log(null || null) // null
console.log(null || null || 30) // 30
console.log((null || null) || 30) // 30
console.log((null || 20) || 30) // 20
console.log((null || null) || (30 || 40)) // 30
console.log((10 || 20) || (30 || 40)) // 10
```

## その他の論理演算子

### NULL合体演算子(`A ?? B`)

Aがnullまたはundefinedの場合にBを返却し、それ以外の場合にAを返却します。
論理和との違いとして論理和はAがFalsyの場合にBを返却しますが、NULL合体演算子はAがnullまたはundefinedの場合にBを返却します。

```jsx
console.log((null || 0) || 10) // 10 0はFalsyなデータになるので0を返却したい場合は??を利用する必要があります
console.log((null || 0) ?? 10) // 0
```

### 論理否定(`!A`)
基本的にはみなさんが学んだ通りの使い方で真値を取ると偽値になり、偽値を取ると真値になります。
二重否定(`!!`)をすることでboolean型以外のデータ型をboolean型に変換できます。

## ちなみに
- これらの演算子は基本的に左から順に実行され、trueまたはfalseがあった時点でそれ以降の処理は行いません
- ただ論理演算子も四則演算のように実行順があるため注意が必要です

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Operator_precedence


## 参考資料
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Logical_OR

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Logical_AND

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Nullish_coalescing
waitFor か findBy か


# 前提
Webアプリ開発をしています。
フロントエンドは TypeScript / React で書いています。
TDD 開発をしていて、Testing Library を使っています。


# 事の発端
フロントエンドでとあるテストを実行したとき・・・
```
Warning: An update to DefectCollectionPage inside a test was not wrapped in act(...).

When testing, code that causes React state updates should be wrapped into act(...):

act(() => {
  /* fire events that update state */
});
/* assert on the output */

This ensures that you're testing the behavior the user would see in the browser.
Learn more at https://reactjs.org/link/wrap-tests-with-act
```
いつの間にか見慣れた警告。
言われた通りに `act()` で囲っても警告は出たままだし・・・
未だに対応方法を理解していないので**お勉強タイム**です！！

# この警告なぁに？

警告の内容としては、テストが React コンポーネントの状態変更を正しく処理していないことを教えてくれているみたい。
`act()` で囲うといいよって書いてあって、親切に Web ページも提供してくれてる。
ページを開くと、**更新が終了している** React の公式ドキュメントに遷移した。

親切に教えてくれた、**更新が終了している** React の公式ドキュメントを開き、
とりあえず act() の部分だけ読んでみる。
なんとなくの理解だけど、非同期処理もちゃんと終わらせた状態を作りたいよねって感じかな。
そしてこんな一文も。
`You can use a library like React Testing Library to reduce the boilerplate code.`
(React Testing Libraryのようなライブラリを使えば、定型的なコードを減らすことができる。)
あぁ・・・。その手があったか！！！

# 非同期処理を待機する
Testing Library で非同期処理を待機してくれそうなやつ。
公式ドキュメントに書いてあった・・・

https://testing-library.com/docs/dom-testing-library/api-async/

`findBy` は、要素が表示されることを期待しているけど、DOMへの変更がすぐには起こらないかもしれない場合に動作してくれる。
そして、`findBy` は、`getByクエリ` と `waitFor` を組み合わせたものとのことです。

`waitFor` は、`findBy` ではカバーできない非同期操作の完了を待機できる。
タイムアウトするまで何度もコールバックを実行することができるらしい。
デフォルトのコールバックの間隔は 50ms。
デフォルトのタイムアウトは 1000ms。


# 結論
act() で囲ってねって言われたら、`findBy` か `waitFor` を使うことを検討します。
今回やりたかったテストでは DOM 要素を取得するものだったので、`findBy` で解決します！

# おまけ
`waitForElementToBeRemoved` ってのもあるらしい。
DOMから要素が削除されるのを待つことができるんだって。
Assistants API v2の新機能紹介とコードサンプル

# 背景
- OpenAiからAssistantsAPIのVersion2の公開が発表されました
  - [What's new in v2?](https://platform.openai.com/docs/assistants/whats-new)
- Version2で新しくなった点と、簡単な使い方を書いていきます
- assistantにVector Storeを紐づける方法と、threadに紐づける方法の2通りあります
  - assistantに紐づける場合は、Vector Storeを作成し紐付けます
  - threadに紐づける場合は、Fileをuploadすると自動でVector Storeが作成され、紐付けが行われます
- 今回はthreadに紐づけるサンプルコードを書きます

# Version2で変わった点
[What's new in v2?](https://platform.openai.com/docs/assistants/whats-new)にまとまっていますが

- file_search(旧 retrieval)
  - 10,000files/assistant
  - 並列クエリOK
- vector_store
  - 自動でparse, chuck, embeddingされる
    - token制御、response_formatなど
- response_formatが指定できるように
  - json指定が可能に 

# File Search(旧 retrieval)詳細

https://platform.openai.com/docs/assistants/tools/file-search

### 特徴
- クエリを検索に最適化する
- 複雑なクエリを複数に分割し並列で実行する
- キーワード検索とセマンティック検索を両方する
- 最終レスポンスの生成前に、検索結果を再度ランキングする


### 今後良くなっていくもの(現在は制限中)
- chunkやembeddingやその他の検索系の設定
- 検索前のフィルタ
- 画像のパース
- 構造データの検索
- 要約機能

# Vector Store
- threadのvector storeにおいては、最大1分までfileのprocessを待ってくれる

# 実装
- threadにfileを紐づける方法です
- 自動的にvector storeが作成され、threadに紐付きgroundingされます

```py
client = OpenAI()

# assistantの作成
assistant = client.beta.assistants.create(
  name="CTR Analyst",
  instructions="You are an expert ad CTR analyst. Use you knowledge base to answer questions about audited digital advetise statements.",
  model="gpt-4-turbo",
  tools=[{"type": "file_search"}],
)

# fileをupload
file_ids = []
for file in YOUR_FILES:
    file = client.files.create(file=file.name, purpose="assistants")
    file_ids.append(file.id)

# attachmentsの作成
attachements = []
for file_id in file_ids:
    attachements.append({
        "file_id": file_id,
        "tools": [{"type": "file_search"}]
    })

# このタイミングでvector storeも作成され、threadに紐づく
thread = client.beta.threads.create(
    messages=[{
        "role": "user",
        "content": "attachmentsのファイルは[related files]です",
        "attachments": attachements
    }]
)

# 実行
run = client.beta.threads.runs.create_and_poll(
    thread_id=thread_id,
    assistant_id=assistant.id,
    instructions="create CTR report from [related files]"
)

if run.status == 'completed': 
  messages = client.beta.threads.messages.list(
    thread_id=thread.id
  )
  print(messages)
else:
  print(run.status)
```

# 参照

https://platform.openai.com/docs/assistants/overview

https://help.openai.com/en/articles/8550641-assistants-api-v2-faq

https://platform.openai.com/docs/assistants/migration
【Spring Boot】コミットすべきでないファイルやディレクトリなど

# はじめに
　チーム開発においてGitやSVN等でソースコードの管理をする際、プロジェクトフォルダ内にはリモートリポジトリにコミットすべきではない(コミットが非推奨)のファイルやディレクトリが存在するので、まとめました。

　また、内容はJavaのSpring Bootでの開発を前提としていることをご了承ください。

### 開発環境

|項目 |バージョン|
|:-:|:-:|
| 言語  |Java 21   |
|フレームワーク   |Spring Boot   |
| ビルドツール　| Maven |
| IDE  | IntelliJ IDEA 2024.1 (Community Edition) |
|  git | version 2.33.0.windows.2  |

# コミットすべきでないファイル


#### 1.ユーザー名やパスワードなどの秘密情報が入力されるファイル

* application.propeties　(DBのユーザー名、パスワード)
* dataSources.ids(IntelliJ IDEA 13以前)　(DBのパスワード)
* datasources.xml(IntelliJ IDEA 13以前)　(DBのパスワード)
* 署名付きビルドを生成する Android アーティファクト　(キーストアのパスワード)

#### 2.チームの開発で必要ではないファイル

* *.class
* *.log

#### 3-1.チーム内で異なるIDEを使用している場合
　チーム内で異なるIDEを使用している場合は、IDE固有のディレクトリを外すことを検討した方が良いかもしれません。
* .idea/ (IntelliJ IDEA固有のディレクトリ)
* .settings/(Eclipse固有のディレクトリ)
* *.classpath (Eclipse固有のファイル)

#### 3-2.チーム共通でIntelliJ IDEAを使用している場合
　公式ドキュメントによると、以下のように設定するとベストプラクティスのようです。
 
##### 共有すべきファイル
 * .ideaディレクトリ内のworkspace.xml、usage.statistics.xml、tasks.xml **以外**のファイル
 * すべての.imlモジュールファイル (IntelliJ IDEAの場合)

##### 共有から除外しても良いファイル
* GradleまたはMavenベースのプロジェクトにおける*.imlファイル、.idea/modules.xmlファイル(プロジェクトファイルから自動生成される為)
* gradle.xml ([こちらを参照](https://youtrack.jetbrains.com/issue/IDEA-55923?_ga=2.246741188.1952362510.1714459198-1081058003.1713615001&_gl=1*8l1srb*_ga*MTA4MTA1ODAwMy4xNzEzNjE1MDAx*_ga_9J976DJZ68*MTcxNDQ1OTE5OC4yLjEuMTcxNDQ2MDgxNy4wLjAuMA..))
* ユーザー辞書フォルダ (他の開発者が同じ名前を持っている場合の競合を避けるため)
* .idea /libraries下の.xmlファイル(Gradle または Mavenプロジェクトから生成された場合)

↓公式ドキュメント

https://intellij-support.jetbrains.com/hc/en-us/articles/206544839-How-to-manage-projects-under-Version-Control-Systems

# .gitignore
　.gitignoreで指定されたファイルは、次回のコミット以降にコミット対象から外すことができます。筆者環境では以下のような記述になりました。
 ```.gitignore
target/classes/application.properties
src/main/resources/application.properties
*.class
*.log
.idea/workspace.xml
*.iml
 ```
 
 　.gitignoreを先にコミットすれば、以降はUnversioned Filesの一覧に表示されなくなります。
 
 ![スクリーンショット (54).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3774406/5139e07e-2dcc-473d-9dac-4350c052e377.png)

# まとめ
　.gitignoreに適切なファイル設定をして、きれいなリポジトリを目指しましょう。追加項目があればまた更新いたします。
実機でシステムの安定性を確認する際の観点【初心者向け】

# 実機でシステムの安定性を確認する際の観点について
システムの安定性を確認したいときに、とりあえずやっておきたいテストを纏めた。特にステップ応答テストとか周波数応答テストは定番。

#### ①ステップ応答テスト
目標値を急に変更して、システムの応答を観察する。応答が過大なオーバーシュートや振動なく、定常状態に収束する場合、システムは安定していると考えられる。

#### ②周波数応答テスト
目標値を様々な周波数で振動させ、システムがどのように追従するかを観察する。システムが安定していれば、高周波での応答は減衰し、低周波での追従が良好になる。

#### ③ロバスト性テスト
外乱やパラメータの変動を意図的に導入し、システムがそれらに対してどのように振る舞うかをテストする。外乱に対するシステムの反応が適切であれば、システムはロバストであると言える。

#### ④ゲインマージンと位相マージンのテスト
システムの開ループ伝達関数のゲインと位相を測定し、ボード線図を書いてみる。そして、ゲイン余裕と位相余裕を確認する。これらのマージンが十分に大きければ、システムは安定であると言える。（あくまで開ループ伝達関数のゲイン/位相の測定であるため、フィードバック制御を切断した状態でテストすること。）

#### ⑤センサ誤差乗せテスト
上記の①～④のようなテストを、ソフトウェア側で敢えてセンサに誤差を乗せた状態で、テストを実施する。
複数のセンサを使ってるような制御の場合は、たくさんのセンサ誤差の組み合わせでテストを行います。それが量産開発というものです。それくらい気合い入れてテストをしないと、量産に耐えうるような品質の製品は作れないってことなんです。


# 参考ページ
https://controlabo.com/stability-margin/
連休の谷間にサクッとまとめ読み！ 『メタ思考～「頭のいい人」の思考法を身につける』著者 プレゼンの神「澤 円」さん記事まとめ

こんにちは！
エンジニアtype編集部です。

GWの中日、いかがお過ごしでしょうか。
日々の仕事やキャリアに役立つ記事をご紹介します！

今回は、『メタ思考～「頭のいい人」の思考法を身につける』著者
プレゼンの神「澤 円」さんの関連記事です！

https://type.jp/et/feature/25262/

https://type.jp/et/feature/22837/

【澤さん記事一覧】

https://type.jp/et/feature/tag/sawamadoka/
連休の谷間にサクッとまとめ読み！ 『シリコンバレーのエンジニアはWeb3の未来に何を見るのか』著者 「中島 聡」さん記事まとめ

こんにちは！
エンジニアtype編集部です。

GWの中日、いかがお過ごしでしょうか。
日々の仕事やキャリアに役立つ記事をご紹介します！

今回は、
『シリコンバレーのエンジニアはWeb3の未来に何を見るのか』著者
「中島 聡」さんの関連記事です！

https://type.jp/et/feature/21792/

【中島さん記事一覧】

https://type.jp/et/feature/tag/nakajimasatoshi/