OmniAICreator/Qiita-1.07M huggingface dataset:
LaravelのIlluminateコンポーネントまとめ

Laravelの`Illuminate`は、フレームワークの基盤を構成する主要なコンポーネント群です。  
これらのコンポーネントは`Illuminate`名前空間の下に整理されており、それぞれの機能を提供しています。

## 📌 主なIlluminateコンポーネント一覧

### 🔐 認証・認可関連
- **`Illuminate\Auth`** - 認証機能を提供（ログイン・認可）
- **`Illuminate\Encryption`** - データの暗号化・復号化

### 🚀 フレームワークの基盤
- **`Illuminate\Container`** - サービスコンテナ（依存性注入）
- **`Illuminate\Foundation`** - Laravelの基盤となる機能
- **`Illuminate\Support`** - コレクションやヘルパー関数

### 🌐 HTTP関連
- **`Illuminate\Http`** - HTTPリクエスト・レスポンスの管理
- **`Illuminate\Routing`** - URLルーティングの管理
- **`Illuminate\Cookie`** - HTTPクッキーの管理
- **`Illuminate\Session`** - セッション管理

### 🔄 データベース関連
- **`Illuminate\Database`** - データベース操作（Eloquent ORM、クエリビルダ）
- **`Illuminate\Redis`** - Redisデータベースのインターフェース

### 🔄 キュー・イベント関連
- **`Illuminate\Bus`** - コマンドバスパターン（ジョブのディスパッチ）
- **`Illuminate\Queue`** - キューを使用した非同期処理
- **`Illuminate\Events`** - イベントシステム

### 🏗️ ファイル・ストレージ関連
- **`Illuminate\Filesystem`** - ファイルシステムの操作（ローカル・クラウド）
- **`Illuminate\Cache`** - キャッシュ機能

### 📩 メール・通知
- **`Illuminate\Mail`** - メール送信機能（SMTPなど）
- **`Illuminate\Notifications`** - メールやSlackなどへの通知

### 🛠️ その他
- **`Illuminate\Config`** - 設定ファイルの管理
- **`Illuminate\Console`** - Artisanコマンドの管理
- **`Illuminate\Log`** - ログの記録
- **`Illuminate\Hashing`** - パスワードのハッシュ化
- **`Illuminate\Translation`** - 多言語対応
- **`Illuminate\Validation`** - バリデーション機能
- **`Illuminate\View`** - Bladeテンプレートエンジン
- **`Illuminate\Pagination`** - ページネーション機能
- **`Illuminate\Broadcasting`** - イベントのブロードキャスト
- **`Illuminate\Pipeline`** - データのパイプライン処理

## 🎯 まとめ
`Illuminate`コンポーネントは、Laravelの各種機能を支える基盤となっています。  
これらはLaravelのアプリ開発で必要不可欠な要素ですが、個別に利用することも可能です。  
各コンポーネントの詳細は公式ドキュメントを参照してください。

📚 **公式ドキュメント**  
👉 [Laravel Documentation](https://laravel.com/docs/)

---

### 📝 この記事が役に立ったら「LGTM」お願いします！👍
ABC393をPythonで（A～D、F）

AtCoder Beginner Contest 393の解答等の速報的まとめ

https://atcoder.jp/contests/abc393



# A問題
https://atcoder.jp/contests/abc393/tasks/abc393_a

条件を満たすように答えを計算した
- 高橋君がfineのとき
    - 答えは３か４
- 青木君がfineのとき
    - 答えは２か４
```python:A
s1, s2 = input().split()

ans = 1
if s1 == "fine":
    ans += 2
if s2 == "fine":
    ans += 1

print(ans)
```
# B問題
https://atcoder.jp/contests/abc393/tasks/abc393_b

可能性があるパターンを全て調べる
```python:B
s = input()

ans = 0
for i in range(len(s)):
    if s[i] != "A":
        continue
    for j in range(i + 1, len(s)):
        if s[j] != "B":
            continue
        k = j * 2 - i
        if k < len(s) and s[k] == "C":
            ans += 1

print(ans)
```
# C問題
https://atcoder.jp/contests/abc393/tasks/abc393_c

始点と終点の組み合わせがすでに登場したものと一致するか$u_i = v_i$である辺の数を数える
```python:C
n, m = map(int, input().split())
s = set()
ans = 0
for _ in range(m):
    e_i = tuple(sorted(map(int, input().split())))
    if e_i in s or e_i[0] == e_i[1]:
        ans += 1
    else:
        s.add(e_i)

print(ans)
```
# D問題
https://atcoder.jp/contests/abc393/tasks/abc393_d

外側の１から順番に内側へ移動させる
```python:D
from collections import deque

n = int(input())
s = input()

d = deque([i for i in range(n) if s[i] == "1"])
ans = 0
cnt_front, cnt_back = 0, 0
while len(d) > 1:
    if cnt_front <= cnt_back:
        now = d.popleft()
        cnt_front += 1
        target = d[0]
        dist = target - now - 1
        ans += dist * cnt_front
    else:
        now = d.pop()
        cnt_back += 1
        target = d[-1]
        dist = now - target - 1
        ans += dist * cnt_front

print(ans)
```
# E問題
https://atcoder.jp/contests/abc393/tasks/abc393_e

まったくわからなかった

# F問題
https://atcoder.jp/contests/abc393/tasks/abc393_f

LISを求めるDPで、$i$番目まで実施したDPの各要素$dp_j$は長さが$j$の狭義単調部分列の最大値の下限である
よってクエリを$R_i$でソートしてDPをしながら答えを記録すればよい
```python:F
from bisect import bisect_left, bisect

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

d = dict()
for i, q_i in enumerate(query):
    if q_i not in d:
        d[q_i] = list()
    d[q_i].append(i)

lst = sorted(d.keys())
search = 0
ans = [0] * q
lis = []
for i, a_i in enumerate(a):
    ind = bisect_left(lis, a_i)
    if len(lis) <= ind:
        lis.append(a_i)
    else:
        lis[ind] = a_i
    while search < len(lst) and lst[search][0] == i + 1:
        ans_i = bisect(lis, lst[search][1])
        # print(ans_i)
        for s_i in d[lst[search]]:
            ans[s_i] = ans_i
        search += 1

for ans_i in ans:
    print(ans_i)
```
コマンドの終了ステータスを毎回表示したい理由

https://qiita.com/takayuki206/items/f4d0dbb45e5ee2ee698e

これを読みました。

## 記事を読んで

終了ステータスを活用する場面はシェルスクリプトなどが多いかと思いますが、上記の記事ではターミナルに毎回表示するとのこと。

ここで疑問が生まれました。

これをやって何が嬉しいのか・・・？　コマンドのエラー内容自体はコマンドのエラー文を読めばいいし。確かにこの実装を行った理由は元記事にも書いてあるけど、いまいちこれを行うメリットが自分の中で見つかりませんでした。　しかし！

**結果的に言うと、これとても嬉しいメリットがありました！**

以下の写真のような場合、パイプでつなげての実行でどこがおかしいか一目で確認できる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3653843/9bc80dca-5934-4c90-99ac-0c5a7c0cc2a4.png)

これ便利！うれしい！！！

ということでnerdfontsでかわいくデコってみました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3653843/ec1eba08-cc34-4bde-8a72-c6974495d319.png)

## 基本的な終了ステータス番号

終了ステータスは基本的に以下のようになっている（細かいものはコマンドによって異なる）

| 終了ステータス | 意味 |
|--------------|----------------------|
| `0`         | 正常終了（成功） |
| `1`         | 一般的なエラー（何らかの問題で失敗） |
| `2`         | より詳細なエラー（ファイルがない、権限がない など） |
| `126`       | 実行不可（権限なし） |
| `127`       | コマンドが見つからない |
| `128`       | 無効な引数によるエラー |
| `130`       | `Ctrl+C` による強制終了 |
| `137`       | `kill -9` による強制終了 |
【備忘録】PythonをWindows11にグローバルインストールする

## はじめに
先日パソコンを買い替えたので、環境を再構築しています。
初めてプログラミングをしようとした際、Pythonの環境構築に苦戦したことを思い出したので、手順を書き残しておきたいと思います。

## グローバルインストールとは
インストールするPCの「全ユーザ｣が共用できるようにインストールすることです。
逆に個別のプロジェクトごとにインストールすることをローカルインストールといいます。

今回はストレージの逼迫を避けるために、グローバルインストールします。

## インストール方法
まずはPython公式サイトからインストーラをダウンロードします。
以下ページ中程の「download」から、ご利用中のOSに合わせてインストーラを取得できます。
https://www.python.org/

## PCへのインストール
今回はWindows11 Homeにインストールしていきます。
サイトから取得したインストーラを、ダブルクリックして開きます。
![IMG_1142.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949751/c4c08c70-4211-4701-a0d0-36247e160c1a.jpeg)
一番下の「Add python.exe to PATH」にチェックを入れます。これで環境変数に追加する手間が省けます。
その後、「Customize installation」をクリックします。
(P.S. Install Nowを選ぶと自動的にローカルインストールされます)

![スクリーンショット 2025-02-15 211300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949751/2784a7bf-1ad7-4e7c-bd26-642a30023235.png)
右下の「for all users｣にチェックを入れます。
その後「Next｣をクリックします。

![スクリーンショット 2025-02-15 211522.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949751/f6e70359-713d-4978-94c8-b32878d5f5f4.png)
インストールが始まるので、終わるまで待ちます。

![スクリーンショット 2025-02-15 211818.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3949751/d33efeab-741a-49ac-afc1-009c7de68058.png)
この画面が出たらインストール完了です。
「Close｣をクリックして終了です。

## インストールの確認方法
コマンドプロンプトで以下コマンドを実行します。

```rb
python --version
```
バージョンが表示されたらOKです。

## おわりに
何度かPythonの環境構築をしましたが、この方法が一番やりやすいと感じました。
どなたかの参考になれば幸いです。
collectionとarray & どちらを使うべきか？

# **LaravelのCollectionとArrayの違い – どちらを使うべきか？**
Laravelでは、データを扱う際に **Collection** と **Array** の両方を使用できます。しかし、それぞれの特徴や利点が異なります。以下で詳細を比較し、適切な場面で使い分けましょう。

## **1. CollectionとArrayの違い**
| 特徴                | Collection (`Illuminate\Support\Collection`) | Array (`array`) |
|------------------|-----------------------------------|--------------|
| **データ構造**      | オブジェクト (`object`)          | 配列 (`[]`)  |
| **便利なメソッド** | ✅ `map()`, `filter()`, `pluck()`, `each()` など | `array_map()`, `array_filter()`, `array_reduce()`など |
| **イミュータブル** | ✅ 変更不可な場合あり | ❌ 変更可能 |
| **JSONとの互換性** | ✅ `toJson()` | ✅ `json_encode()` |
| **Eloquentとの互換性** | ✅ `User::all()` で取得可 | ❌ 直接は不可 |

## **2. Collectionを使うべき場合**
### **2.1. データを柔軟に操作したいとき**
Collectionは多くの便利なメソッドを提供しており、データを簡単に操作できます。

```php
$users = collect([
    ['name' => 'A', 'age' => 25],
    ['name' => 'B', 'age' => 30],
    ['name' => 'C', 'age' => 20],
]);

// 25歳以上のユーザーを取得
$filtered = $users->filter(fn($user) => $user['age'] > 25);
dd($filtered->all()); // [['name' => 'B', 'age' => 30]]
```
### **2.2. Eloquentモデルを扱うとき**
EloquentはデフォルトでCollectionを返します。

```php
$users = User::all(); // Collectionが返る
$names = $users->pluck('name'); // 名前のリストを取得
```
### **2.3. map, reduce, filter, sort などの処理を簡単にしたいとき**
```php
$numbers = collect([1, 2, 3, 4, 5]);

$squared = $numbers->map(fn($num) => $num * $num); // 各数値を2乗
dd($squared->all()); // [1, 4, 9, 16, 25]
```

## **3. Arrayを使うべき場合**
### **3.1. 小規模データでシンプルな処理をしたいとき**
特にデータの変換などが不要な場合、Arrayで十分です。

```php
$users = [
    ['name' => 'Alice', 'age' => 25],
    ['name' => 'Bob', 'age' => 30],
];

foreach ($users as $user) {
    echo $user['name'] . "\n";
}
```
### **3.2. パフォーマンスを重視するとき**
Collectionはオブジェクトのため、Arrayの方がメモリ消費が少なく、処理が速いことがあります。
### **3.3. APIレスポンスとしてデータを返すとき**
Collectionの toJson() も使えますが、場合によってはArrayの方が扱いやすいことがあります。

```php
$users = User::all()->toArray(); // Collection → Arrayに変換
return response()->json($users);
```
## **4. 結論**
| **ケース** | **推奨するデータ型** |
|-----------|-----------------|
| データをフィルタリング・マッピング・ソートしたい | ✅ Collection |
| シンプルなデータ処理（ループのみ） | ✅ Array |
| Eloquentのデータを扱う | ✅ Collection |
| JSONレスポンスを返す | ✅ ArrayまたはCollection (`toJson()`) |

---

### **👉 まとめ**
- **データを柔軟に処理するなら** → **Collection**  
- **シンプルな処理やパフォーマンス重視なら** → **Array** 

**以上。**
WSL2

https://qiita.com/_masa_u/items/d3c1fa7898b0783bc3ed

## WSLの再起動

```powershell:ホスト側 (Windows PowerShell)
wsl --shutdown
```

[8秒待機](https://learn.microsoft.com/ja-jp/windows/wsl/wsl-config#the-8-second-rule-for-configuration-changes)して，WSLに再接続

WSLが終了されたかは以下のコマンドで確認

```powershell:ホスト側 (Windows PowerShell)
wsl --list --running
```
【Supabase】一度更新したステータスが勝手に元に戻る？ 〜トリガーの自動更新が原因だった話〜

## 前置き
Supabase + フロントエンド(Reactなど)でアプリを作っていて、データの「ステータス」を 「inactive（キャンセル）」 に更新したはずが、なぜか再度 「searching（募集状態）」 に戻ってしまう

そんな現象に悩まされた場合の原因と対処法を解説します。

## 結論：トリガーがステータスを「searching」or「full」に強制更新していた

DB 側に、以下のようなテーブルとトリガー関数が設定されているケースです。

* テーブル例: ```activities```
* 参加者を管理する中間テーブル: ```activity_participants```
* ステータス管理用カラム: ```phase```
* トリガー関数: ```on_activity_created or on_participant_change```


このトリガー関数の中で、参加者数をカウントし、

```sql
UPDATE activities
SET 
  current_people = <参加者数>,
  phase = CASE
    WHEN <参加者数> >= max_people THEN 'full'
    ELSE 'searching'
  END
WHERE id = ...
```

…という処理が走っていると、いくらフロントエンドで ```phase = 'inactive'``` に更新しても、その後に参加者が増減すると 再度 ```phase = 'searching'（または full）```に書き戻されてしまう のです。

## なぜ「inactive」にしても「searching」に戻ってしまうのか

1.フロントエンドで ```UPDATE activities SET phase = 'inactive' ```する
2.しかしその後、参加者の追加・削除など、activity_participants に変化があるとトリガーが発火
3.トリガー内で無条件に
```sql
phase = CASE
  WHEN participant_count >= max_people THEN 'full'
  ELSE 'searching'
END
```
と書き換えてしまい、“inactive” が “searching” に上書きされる

4.結果として、「1回更新したのに、いつの間にかステータスが戻っている」状況になる


## 対処法

1. すでに「inactive」や「done」になったレコードは上書きしない
トリガー関数のロジックを変更し、「現在すでに phase が “inactive” (or “done”) の場合は更新しない」 という分岐を追加します。

```sql
DECLARE
  participant_count integer;
  current_phase text;
BEGIN
  -- まず現在のステータスを取得
  SELECT phase
    INTO current_phase
  FROM activities
  WHERE id = COALESCE(NEW.activity_id, OLD.activity_id);

  -- すでにinactive or done なら上書きしない
  IF current_phase IN ('inactive', 'done') THEN
    RETURN NULL;
  END IF;

  -- 参加者数をカウント
  SELECT COUNT(*) INTO participant_count
  FROM activity_participants
  WHERE activity_id = COALESCE(NEW.activity_id, OLD.activity_id);

  -- 参加者数に応じてステータスを更新
  UPDATE activities
  SET
    current_people = participant_count,
    phase = CASE
      WHEN participant_count >= max_people THEN 'full'
      ELSE 'searching'
    END
  WHERE id = COALESCE(NEW.activity_id, OLD.activity_id);

  RETURN NULL;
END;
```

これで、一度「inactive」や「done」にしたアクティビティは、参加者数が変わっても自動更新の対象外 となり、ステータスが勝手に戻ることはありません。


2.フロントエンドでも「キャンセルされたデータへの操作」を制御する

いったん「inactive」にした後は、参加受付を無効にする
UI 上からは「inactive」状態のアクティビティを表示しない・操作できないようにする
など、ユーザーがキャンセル後に再度参加/離脱リクエストを送れない仕組み を組み込みましょう。こうすることで、上記トリガーが発火するシーン自体がなくなり、アクティビティが「inactive」状態のまま保たれます。

3.そもそもトリガーを分割 or 廃止する

「アクティビティ作成時に初期設定をする」「参加者数に応じて自動的にステータスを切り替える」という機能があまり必要なければ、思い切ってトリガーをなくしてしまう のも選択肢です。カウントやステータス制御をすべてフロントロジックで行う方が分かりやすくなる場合もあります。


## まとめ

1. ステータスが意図せず上書きされている理由: 裏で走っているトリガー関数が、参加者数をもとに一律 「searching」「full」に更新していた

2. 解決策: トリガー内で「すでに phase が “inactive” や “done” になっている場合は上書きしない」などの条件を追加

3. 注意点: キャンセル後に参加者が動かないよう、フロントエンドでも操作制御を行う

Supabase や Postgres でトリガーを使う際は、中の関数が「無条件にカラムを更新していないか」を必ずチェックしましょう。一度ステータスを更新しても、今回のように勝手に戻る現象が起きる場合は、「実はトリガーが裏で書き換えていた」 ことがよくある原因です。
正規表現の腕前を競う「正規表現レース」サイトを作った

## 正規表現の練習ができる「楽しい」サービスが欲しい
正規表現の練習ができるサービスは、あまり多くはありません。
あっても、あまりにも飾り気のない質素なものだったりします。[^1]
[^1]: 以前 [Regex Hunting](https://qiita.com/yukiHaga/items/8ef2051036e126eb00c6) という激おもろプロダクトが人気を博していたのですが、（おそらくサーバー保守等の理由で）閉鎖されてしまいました。残念。

「もっとゲームとして楽しめるような、楽しい練習サイトがあったらいいな」と、私自身思っていました。

## 正規表現の腕前を競う Web サービスを作りました
今回、[**RegCoder**](https://dev.shared-idea.net/RegCoder) という Web サイトを作成しました。

https://dev.shared-idea.net/RegCoder

このプロダクトは、**「競技正規表現」** のコンセプトのもと、正規表現コーディングの「速さ」と「美しさ」を競うゲームサイトです。

### ゲーム画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/37669ee4-0c54-4056-b37d-232a28e5e8d5.png)

左側のカラム「Include」のワードにはマッチし、右側のカラム「Exclude」にはマッチしない正規表現を打ち込めたら、その問題は正解になります。

完成した正規表現の文字数が短いほど高得点になり、制限時間内により多くのスコアを獲得することが目標になります。

### 結果画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/d97117f7-4e0e-413f-9e48-22a95329cc83.png)
結果画面では、最終的なスコアと順位が表示されます。
それに加えて、自分の解答と全てのプレーヤーの解答を比較することができます。

### レベル設定
問題の難易度によって、Easy / Medium / Hard の 3 つに分かれています。
正規表現そのものの複雑さや、想定される解答の長さなどから、各問題に難易度を割り当てました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/30a8e510-f3eb-4692-b443-4f8639f4b379.png)

### 問題リクエスト機能
自作の問題をリクエストする機能もあります。
「これは他のプレーヤーには絶対に解けないだろ！」と思うような問題を、お気軽に投稿してみてください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/504a4571-bbc9-42e5-ad0b-7d491d1a333c.png)

## 今後の実装予定

### プレイモードの追加
現在は、「目的のワードにマッチする正規表現を解答する」というルールのみですが、今後は、「指定のワードに書き換える」「与えられた正規表現でマッチするワードを選ぶ」などのモードも追加したいと考えています。

### 使用できる処理系の追加
現在は、[.Net の正規表現](https://learn.microsoft.com/ja-jp/dotnet/standard/base-types/regular-expressions) のみに対応していますが、今後 Perl や JavaScript など、仕様の異なる処理系も追加予定です。

## 問題募集中
執筆時点で、問題が **14 問** しかありません。圧倒的に足りない！
1 度プレイしてみて、もし気に入っていただけたなら、**「Proposal」** ボタンから、問題のリクエストをお願いします！！
大懇願中です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/ffad27f7-b483-4ae8-b45b-b633597fb976.png)

## Mac デバッガー募集中
Macデバイスが手元になく、デバッグができていない状態です。
特に、ショートカットキーに Windows との挙動の違いがあり、その点が全く自信ないです。
そのため、「Mac でも動いたよ！ / 動かないよ！！」というフィードバックをいただけると大変ありがたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3080922/1aba2f45-e565-4b71-b47f-5319dc2df33a.png)
Command + F で、^$ と入力される…はず…


## 終わりに
正規表現に苦手意識を持っている方は、ぜひこのサイトで楽しく苦手を克服してみてください！
【rails】ゲストログイン機能の導入について

# はじめに
現状としては、`devise`と`omniauth`にて、Google認証のみのログイン機能を作成しています。ポートフォリオとして作成しておりますので、見てくださる方が確認しやすいようにゲストログインの機能を準備していきたいと思います。`devise`の追加や`Google認証`については、私が準備した以下の記事をご覧ください。

https://qiita.com/hrr0512basket/items/63e8d18a09da795e85ff

# 手順
#### １ コントローラーの準備
まずは、ルーティングの設定をしていきたいと思います。
```php:routes.rb
devise_scope :user do
  post 'users/guest_sign_in', to: 'users/sessions#guest_sign_in'
end
```
`devise_scope`はdeviseの標準ルート以外である、独自機能をスコープ内で定義するための記述です。`sessionsコントローラ`に`guest_sign_in`アクションを追加しています。このアクションの記述は後ほど行います。

:::note info
スコープとは（Chatgptより）
例えば、あなたが大きなスポーツ施設にいるとします。この施設には「野球エリア」と「サッカーエリア」があります。

野球エリアでは、野球のルールだけが有効です。サッカーエリアでは、サッカーのルールだけが有効です。
つまり、エリアごとにルールが決まっているのです。この「エリア」をプログラムの世界では 「スコープ」 と呼びます。
:::
`post 'users/guest_sign_in'`により`guest_sign_in`アクションにゲストデータのリクエストが送られます。

#### ２ コントローラについて
以下はコントローラに記述するコードです。
```php:users/sessions_controller.rb
class Users::SessionsController < Devise::SessionsController
  def guest_sign_in
    user = User.find_or_create_by(email: 'guest@example.com') do |user|
      user.password = SecureRandom.urlsafe_base64
      user.name = 'ゲストユーザー'
      user.profile = '未設定'
      user.muscle_training_history = 0
      user.uid = nil # Google認証と混ざらないようにする
      user.provider = nil
    end
    sign_in user
    redirect_to edit_user_registration_path, success: 'ゲストユーザーとしてログインしました'
  end
end
```
先ほどのリクエストを受けて、これらの処理が働きます。
まずは`guest_sign_in`メソッドを作成し、`User.find_or_create_by`にて、usersテーブルにemailが「guest@example.com」がないか探します。もし存在すればそれらのデータを取得し、見つからなければ新規作成されます。
また、`user =`の部分の`user`にはユーザーオブジェクトが入ります。

:::note info
オブジェクトとは
わかりやすく説明すると、クラスは「設計図」で、同じ設計図からは何軒でも家（オブジェクト）を建てられます。つまりここでは、１つの人（user）を作成しています。
:::
それらのオブジェクトに必要な情報を入れていきます。もしユーザーオブジェクトが新たに作成された場合は、それを一時的に`|user|`として保管します。それにより、`user.password`や`user.name`を記述することで、オブジェクトにデータを追加していけます。パスワードは何でも良いので、ランダムに作成させています。
私はGoogle認証をしているので、`uid`や`provider`にデータが入っていると、Google認証と混同してはいけないと思い、`nil`にしています。
```php
sign_in user
redirect_to edit_user_registration_path, success: 'ゲストユーザーとしてログインしました'
```
上記の部分では、先ほど`user =`の変数を`Devise`の`sign_in`メソッドを活用して、ログイン状態にしています。
その後に`redirect_to`によりユーザーの編集画面にリンクするように設定しています。

#### ３ ビューの準備
```php
<%= link_to "ゲストログイン", users_guest_sign_in_path, method: :post %>
```
上記のコードをゲストログインの配置したいところに、記述してください。それをクリックすることでゲストログインが可能になります。注意点としては、`link_to`は基本的に`get`メソッドとして機能するため、明示的に`method: :post`を記述しています。

# さいごに
これでゲストログイン機能を作成することができました。比較的簡単にできましたが、コードの１つ１つを理解することが大切だなと改めて感じる機能でした。私自身が初心者のため、間違えたことを記載していたら、コメントなどでご教示くださいますようお願いします。
最後まで閲覧いただきありがとうございました。
#17.S3syncでファイルのアップロード

# はじめに
少し前から、AWSに少し触れており、今回はS3syncを使用してファイルのアップロードをしてみたので忘備録として記事にしました。

※動作環境はWSL2のubuntuを使用してます。

# S3syncとは
`S3Sync`とは、AWSのS3にオンプレミスやクラウド上のデータを同期する機能です。
これにより、`ファイルの削除`、`ファイルのアップロード・ダウンロード`が簡単に行えます。

今回は、ローカルのディレクトリ内のデータをAWSのS3アップロードしました。


# 初回セットアップ＋設定
前回Terraformの記事を書いた際、一緒に書けばよかったのですが、
AWSのコンソールを操作する際に`awscli`を使用します。
導入方法は以下の通りです。

- aws cliのインストール
```
# curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
# unzip awscliv2.zip
# sudo ./aws/install
# aws cli install
```

# AWSコンソールでアカウントを作成

以下の公式サイトを参考にアカウントを作成していきましょう。

https://aws.amazon.com/jp/register-flow/

# AWSアカウントとの連携設定
AWSアカウントで IAMユーザー を作成し、`アクセスキー`と`シークレットキー`を発行します。
IAMユーザーの作成方法については、以下の記事が分かりやすいです。


https://dev.classmethod.jp/articles/iam_user_create_access_keys_2023/


IAMユーザーを作成後、`~/.aws/`から`credentials`と`config`の設定を行いましょう。
※ファイルがない場合は作成。
```
vi ~/.aws/credentials

[default]
aws_access_key_id = {コンソール上のアクセスキー｝
aws_secret_access_key = ｛コンソール上のシークレットキー｝
```
```
vi ~/.aws/config

[default]
region = ｛設定されてるregion｝
output = json
```

`output`は、CLIでAWSのデータを取得した際の出力フォーマットを指定する設定です。
`IAMポリシー`は基本的に`json`形式で定義されているため、`json`を指定しておきましょう。

# S3sync

- S3バケットの作成＋ポリシーの設定

以下のリンクからS3バケットの作成。

https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/GetStartedWithS3.html

IAMポリシーの例だけこちらに載せておきます。

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:ListBucket",
                "s3:GetObject",
                "s3:PutObject",
                "s3:DeleteObject"
            ],
            "Resource": [
                "arn:aws:s3:::tfstate-backet-tokyo",
                "arn:aws:s3:::tfstate-backet-tokyo/*"
            ]
        }
    ]
}
```

`s3:ListBucket` バケット内のオブジェクト一覧を取得する
`s3:GetObject` バケット内のオブジェクトを取得（ダウンロード）する
`s3:PutObject` バケットにオブジェクトをアップロードする
`s3:DeleteObject` バケット内のオブジェクトを削除する
`Resource` 権限対象の指定

今回の例でいうと、ローカル→AWS（S3へのアップロード）なので、
`s3:ListBucket`と`s3:PutObject`の権限だけでも問題ありません。しかし、双方向のやり取りをスムーズにするために、`s3:GetObject`や`s3:DeleteObject`も含めた4つの権限を設定しておくことをおすすめします。

- S3syncの実行
```
# aws s3 sync nayanaya s3://tfstate-basket-tokyo
```
以下の画像のように、あくまでストレージの同期というところなので、直接ファイルのみを指定しても同期はできないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3904736/24beb7fd-d272-4d7c-92c3-199634ce048d.png)

```
# aws s3 sync naya_dir/ s3://tfstate-basket-tokyo
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3904736/30ef0ecb-165c-4f37-b89e-61f960c99e64.png)

- コンソールの画像

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3904736/dee9a7a0-671f-4b9f-8edc-279d690f7d2c.png)


ファイルが同期されていますね。


# まとめ
AWSに限った話ではありませんが、アウトプットとインプットのバランスは非常に重要だと感じました。
AWSについては、資格の勉強（ハンズオンなし）や書籍を読むだけで学習していたのですが、実際に手を動かしてみると「ナニコレ？」と思うことが多くあります。

また、要件を整理するときに構成図がないとイメージしづらいことがありますが、作図ツールを使って視覚化すると、理解が深まり非常にわかりやすくなるなと感じました。
個人的におすすめなのは**Cacoo**です。

参考までにリンクを貼っておきます。

https://cacoo.com/ja/home

さらに、3/15にKubernetesについてLTをすることになったので、良かったら遊びに来てください～

https://techbull.connpass.com/event/345494/
自由エネルギー原理：AIに興味を持つならば脳科学にも興味を持とうということです

生成AIって言ったらAI専門家は嫌がるのね深層生成学習はあるけど生成AI is 何？

とか言いながら未来を見たいならばCRDSレポートですよ

機械学習本コレクターの青木健一なんて信用できないでしょう。わかる。わかりみ。

東大松尾研の鈴木雅広氏が言っているならどうよ？YouTube動画があります。
[【鈴木雅大】深層学習:深層生成モデルの概要と世界モデルへの発展【神経回路学会2023サテライト】](https://www.youtube.com/watch?v=aRGfykzlOg4)

https://www.youtube.com/watch?v=aRGfykzlOg4

ここの最後で読みましょうと推奨されているレポートがこれ

[人工知能研究の新潮流２ ～基盤モデル・生成 AI のインパクト～](https://www.jst.go.jp/crds/pdf/2023/RR/CRDS-FY2023-RR-02.pdf)

https://www.jst.go.jp/crds/pdf/2023/RR/CRDS-FY2023-RR-02.pdf

最新だと

[CRDSの研究動向レポート計算脳科学](https://www.jst.go.jp/crds/pdf/2024/FR/CRDS-FY2024-FR-03/CRDS-FY2024-FR-03_20107.pdf)

https://www.jst.go.jp/crds/pdf/2024/FR/CRDS-FY2024-FR-03/CRDS-FY2024-FR-03_20107.pdf

というレポートもあって大体同じ。

- 自由エネルギー原理
    - 予測符号化理論（これは自由エネルギー原理の範疇）
- 統合情報理論
- グローバルニューロナルワークスペース
- （引用に挙がっている）「1000の脳」理論

などが脳科学で「認識」や「意識」などを理論化している有力な仮説らしいのよ。

同じく、鈴木雅広氏の世界モデルサーベイ

https://arxiv.org/pdf/2301.05832

によると（世界モデルっていうのはざっくりいうと、AIが世界をどう認識するかの仕組み。ChatGPTみたいにこちらから問いかけだったらいいけれど、今年はエージェントって言われているじゃない。ブラウザ上の作業を自動化するとか、アプリ作業を自動化するとか。もっと言うと、動き出して人間の指示によって作業を自動化してくれるのがエージェント。ということは世界がどういうものか認識しなきゃいけないのよ、その仕組みが世界モデル）、世界モデルで脳科学の考え方として参考にされているのは、

- 自由エネルギー原理

そしてその派生として、
- 予測符号化理論
- アクティブインファレンス
- ベイズ脳仮説
など。

- 自由エネルギー原理 (Free Energy Principle)とは、
    - Friston が提唱している理論で、脳が変分自由エネルギー（予測誤差を含む指標）を最小化することで、環境の不確実性や驚きを抑え、効率的な情報処理を実現している

その派生としてある、

- 予測符号化理論 (Predictive Coding Theory)は、
    - 脳は常に外界からの入力を予測し、その予測と実際の感覚入力との差（予測誤差）を最小化することで内部モデルを更新するという考え方

らしいです。

脳科学とAIでつながる「自由エネルギー原理」

Fristonの翻訳が出ていて

[能動的推論:心、脳、行動の自由エネルギー原理](https://amzn.to/4hYWzVB)
<a href="https://amzn.to/4hYWzVB" target="_blank"><img src="https://m.media-amazon.com/images/I/5186-M52VuL._SY522_.jpg" width=150 /></a>

ここまで言ってもまだ、あまり関心がなそそうですね！？ではこれは？この本の中にある「能動的推論への2つの道：王道（右上から始まる）と常道（左下から始まる）」をMemaidで書き直してみました。左が王道で右が常道です。


```mermaid
graph
    subgraph 王道
        自由エネルギー原理 --> 自己組織化 --> サプライズの最小化 --> マルコフブランケット --> 予測処理 --> 自己証明 --> オートポイエーシスとニッチ構築
    end
    subgraph 常道
        ベイズの定理 --> 生成モデル --> 推論としての知覚 --> 予測符号化 --> 推論としての行動計画 --> ベイズ脳 --> 変分ベイズ
    end
    オートポイエーシスとニッチ構築 & 変分ベイズ --> 能動的推論
```

この仮説が正しければ、ですが、生成モデルがあって変分ベイズですよ。もう機械学習ないっすか。

今年はAIエージェントの年、そしてそれには世界モデルが必要。そして参照されている脳科学理論で有力な自由エネルギー原理、は機械学習（ベイズ）に親和性が高い！

もう、学ぶしかないでしょう！

Qiitaでも関連記事はまだ数件しかないですよ。今がチャンス。
Googleタイムラインのデータをgpxに変換する方法(マッピング!でインポート可能)

### モチベーション
以下でおすすめされているマッピング!にGoogleタイムラインのデータをインポートしたかった
https://b.hatena.ne.jp/entry/4766225990155446401/comment/Fushihara

### 参考としたコード
Googleタイムラインのjsonをkmlに変換する方法 :
https://anond.hatelabo.jp/20250214150133

しかしながら、マッピング!でkmlが正常にインポートされなかった。。。gpxで試したらいけました。

### 手順
#### まず、Googleタイムラインをエクスポートする
Androidの場合の方法
https://qiita.com/kumakumao/items/f3e8b7b0aa2a1f99c465


#### 以下のスクリプトでgpxファイルに変換する
```python
import json
import os
from xml.etree.ElementTree import Element, SubElement, tostring
from xml.dom.minidom import parseString

# JSONファイルの読み込み
with open("タイムライン.json", "r", encoding="utf-8") as f:
    data = json.load(f)

# 出力フォルダ作成
output_folder = "gpx_output"
os.makedirs(output_folder, exist_ok=True)

# GPXのルート要素を作成
gpx = Element("gpx",
    version="1.1",
    creator="Python Script",
    xmlns="http://www.topografix.com/GPX/1/1",
    xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance",
    xsi_schemaLocation="http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd"
)

# トラックを作成
trk = SubElement(gpx, "trk")
name = SubElement(trk, "name")
name.text = "Timeline Track"
trkseg = SubElement(trk, "trkseg")

# `semanticSegments` に移動データが含まれている
if "semanticSegments" in data:
    for segment in data["semanticSegments"]:
        if "timelinePath" in segment:
            for point in segment["timelinePath"]:
                coords = point["point"].replace("°", "")
                time = point.get("time", "Unknown Time")

                # トラックポイントを作成
                trkpt = SubElement(trkseg, "trkpt")
                lat, lon = coords.split(", ")
                trkpt.set("lat", lat)
                trkpt.set("lon", lon)

                # 時間を設定
                time_element = SubElement(trkpt, "time")
                time_element.text = time

# GPXデータをフォーマット
gpx_str = tostring(gpx, encoding="utf-8")
formatted_gpx = parseString(gpx_str).toprettyxml(indent=" ")

# GPXファイルに保存
gpx_filename = os.path.join(output_folder, "timeline.gpx")
with open(gpx_filename, "w", encoding="utf-8") as f:
    f.write(formatted_gpx)

print(f"GPXファイルを出力しました: {gpx_filename}")

```
おわり

#### マッピング!でのインポート方法
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/f73cae49-9aeb-4f08-81d4-658b143ed365.jpeg" width= "300px" >

### しばし待つと、、、
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/0fe566ca-f9c3-414f-9dda-8c7e7971065f.jpeg" width= "300px" >
ABC392Eを解いた【UnionFind】


筆者はレート800前後の茶～緑コーダ

ABC392のE問題を解いていく
    
https://atcoder.jp/contests/abc392/tasks/abc392_e

# 実装コード

UnionFindを使い、クラスタ同士もしくは自己ループをスペアとみなし、判別する。

また、つなげかえる回数はUnionFindのクラスタ数-1で、
スペアのケーブルをクラスタ別に分け、
多い順から、別のクラスタにつなげかえる、
もし使い切ったら、次に多いクラスタにあるケーブルを使えばOK

```python:main.py
from sortedcontainers import SortedSet

from bisect import bisect_left, bisect_right, insort_left, insort_right
from collections import defaultdict, Counter, deque
from functools import reduce, lru_cache
from itertools import product, accumulate, groupby, combinations
import sys
import os
def rI(): return int(sys.stdin.readline().rstrip())
def rLI(): return list(map(int,sys.stdin.readline().rstrip().split()))
def rI1(): return (int(sys.stdin.readline().rstrip())-1)
def rLI1(): return list(map(lambda a:int(a)-1,sys.stdin.readline().rstrip().split()))
def rS(): return sys.stdin.readline().rstrip()
def rLS(): return list(sys.stdin.readline().rstrip().split())
IS_LOCAL = int(os.getenv("ATCODER", "0"))==0
err = (lambda *args, **kwargs: print(*args, **kwargs, file=sys.stderr)) if IS_LOCAL else (lambda *args, **kwargs: None)

class UnionFind:
    def __init__(self, n):
        self.parent = [-1] * -~n
        self.rank = [1] * -~n
        self.roots= set([-~i for i in range(n)])
        self.count = n
    def root(self, x):
        while (p:=self.parent[x]) != -1:
            x = p
        return x
    def union(self, x, y):
        xr = self.root(x)
        yr = self.root(y)
        if xr == yr: return
        elif (rx:=self.rank[xr]) < (ry:=self.rank[yr]):
            self.parent[xr] = yr
            self.rank[yr] += rx
            self.roots.remove(xr)
        else:
            self.parent[yr] = xr
            self.rank[xr] += ry
            self.roots.remove(yr)
        self.count -= 1
    def same(self,x,y):
        # err(self.root(x), self.root(y))
        return self.root(x) == self.root(y)

def main():
    N, M = rLI()
    UF = UnionFind(N)
    spare = []
    for i0 in range(M):
        i = -~i0
        a,b = rLI()
        # スペアの判別
        if a!=b and UF.root(a) != UF.root(b):
            UF.union(a,b)
        else:
            spare.append((i,a,b))
    # つなげる個数
    print(UF.count-1)
    # err(*UF.roots)
    # err(*spare)
    if UF.count > 1:
        
        # スペアをクラスタ別に分ける
        r = defaultdict(deque)
        c = defaultdict(lambda: 0)
        for s in spare:
            i,u,_ = s
            ru = UF.root(u)
            r[ru].append(s)
            c[ru]+=1
        # err(dict(r))
        
        # 多いクラスタから使う
        K = list(sorted((k for k in UF.roots),reverse=True, key=lambda x: c[x]))
        x = K[0]
        cur = 0
        # err(K)
        
        # 付け替え
        for y in K[1:]:
            # err(UF.count,x,y)
            # err(UF.count,xr,yr)
            # 使い切ったらクラスタ変える
            if len(r[x]) == 0:
                cur += 1
                x = K[cur]
            i,a,b = r[x].popleft()
            print(i,b,y)
            
if __name__ == '__main__':
    main()

```

# コメント

ケーブルの付け替えの実装で,TLE,REを多数だしたが、
余りが多いクラスタから付け替えるという発想は目からウロコだった
プロダクトオーナーの意思決定を加速させる方法と実践

### **はじめに**

最近、スクラムの案件に取り組む中で、プロダクトオーナーの意思決定を促すことの難しさを実感しました。決定に迷いや遅れが生じることで、開発スケジュールに影響が出る場面もありました。そのため、意思決定をスムーズに進めるためのアプローチを模索し、先輩のフォローを受けながら調査・実践を重ねました。本記事では、その取り組みの記録と、意思決定を加速させるための具体的な手法を紹介します。

### **1. 意思決定の遅れを生む要因**
プロダクトの仕様決定に時間がかかる要因は、大きく以下の3つに分けられます。

- **情報不足**：判断に必要な情報が揃っていない。
- **選択肢の多さ**：どの案を選ぶべきか迷う。
- **リスクが不明確**：決断した場合・しなかった場合の影響が見えにくい。

この課題を解決するために、以下のアプローチを実践しました。

---

### **2. 調査で分かった意思決定のアプローチ**

#### **(1) 選択肢を「二者択一」にする**
「A案とB案のどちらが良いですか？」と問うよりも、

**「A案で進めて問題ないでしょうか？もしB案が必要なら理由を教えてください」**

のように提案型にすることで、意思決定のスピードを上げることができます。

#### **(2) プロダクトオーナーの決定軸を整理する**
プロダクトオーナーがどの基準で判断するのかを整理し、

- ユーザビリティを優先するのか？
- 品質を優先するのか？
- 開発コストを抑えるのか？

といった観点を明確にすると、適切な選択肢を示しやすくなります。

#### **(3) リスクを見える化する**
決断しないこと自体がリスクになるケースもあります。
例えば、

**「他チームに影響する可能性があります」**

**「次のスプリントで開発できずリリースに影響します」**

と影響力や期限を示すことで、意思決定を促せます。

---

### **3. プロジェクトでの実践事例**

私が仕様検討を進める際には、次のポイントを意識しました。

#### **(1) 一つの案を明確に提示する**
仕様に複数の選択肢がある場合、**限られた工数で実現可能**かつ**ユーザーのニーズを満たせる案**を優先して提示しました。
特に主要な機能については、**頻繁に使われるか**を考え、ユーザーニーズを満たすかどうかを慎重に検討しました。
また、品質を重視するにあたり、影響範囲の把握、デグレーションリスクの抑制、およびメンテナンスコストの最小化を意識して提案しました。

#### **(2) 仕様を決める専門家との対話を重視する**
私は仕様の専門家ではないため、**仕様に精通した人との対話**を大切にしました。
その際、ユーザーストーリーの**3C（Card, Conversation, Confirmation）** を意識し、

- **Conversation（会話）** を通じて多角的な視点を取り入れる。
- プロトタイプを提示し、「実際に触ってみるとどうか？」と問いかける。

といったアプローチを取りました。

#### **(3) 他の案を選ばなかった理由を用意する**
選択しなかった案についても、**明確な理由を整理**しておくことが重要です。

- **技術的に実現が困難**
- **工数的に間に合わない**
- **ユーザーのニーズに合わない**

こうした説明を準備しておくことで、プロダクトや関係者との合意形成がスムーズになりました。

#### **(4) 要求や仕様書を“絶対”と考えない**
プロダクトに仕様書が存在する場合、開発者の多くはそれを神様のように絶対的なものと考えがちです。しかし、**あくまで人間が作ったもの**であり、常に改善の余地があります。
「できないこと」を批判されるのではなく、**別の方法を提案できるかが重要**です。

---

### **4. スクラムの特性を活かす**

スクラムの特性を最大限に活かし、

- **仕様考案者と開発者が切磋琢磨する**
- **対話を重視し、柔軟に仕様を調整する**
- **リスクと判断軸を整理し、プロダクトオーナーの意思決定をサポートする**

こうした取り組みを通じて、より良いプロダクトを作れることを実感しました。

**仕様決定に悩むプロダクトオーナーにとって、開発者が適切な情報を提供することが、意思決定を加速させる鍵になるのではないでしょうか？**
【Vue3】genericを使用した型安全なラジオボタンコントロール


## 完成イメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/66405/47f9eefc-ad4f-4a76-abe0-62b5a5c4eb22.png)

## コンポーネント
```vuejs:RadioButton.vue
<template>
  <div class="border rounded border-success-subtle">
    <div v-for="item in items" :key="item.id">
      <input
        type="radio"
        :id="item.id"
        :name="props.name"
        :value="item.value"
        v-model="modelValue"
        :required="props.required"
      />
      <label :for="item.id">{{ item.labelName }}</label>
    </div>
  </div>
</template>

<script setup lang="ts" generic="T extends string | boolean | undefined">
export interface InputRadioItem<T> {
  id: string;
  labelName: string;
  value: T;
}

const props = defineProps<{
  modelValue: T;
  name: string;
  items: InputRadioItem<T>[];
  required?: boolean;
}>();

interface Emits {
  (e: "update:modelValue", value: T): void;
}
const emits = defineEmits<Emits>();

const modelValue = computed({
  get: () => props.modelValue,
  set: (value) => {
    emits("update:modelValue", value);
  },
});
</script>

```

* generic="T"を定義する
* 許容したい型をextendsに定義する

## 使用側
```vuejs:index.vue
<template>
   <form>
       <RadioButton :items="listItems" v-model="selectedValue" name="fruitsRadio" />
       selected: {{ selectedValue }}
   </form>
</template>

<script setup lang="ts">
import type { InputRadioItem } from "~/components/RadioButton.vue";
const radioItems: InputRadioItem<string>[] = [
  { id: "apple", labelName: "りんご", value: "apple" },
  { id: "banana", labelName: "バナナ", value: "banana" },
  { id: "oranage", labelName: "みかん", value: "oranage" },
];

const selectedValue = ref(undefined);
</script>
```

* InputRadioItemでvalueに使用したい型を指定することで、modelValueの型と連動する
* valueとselectedValueが異なるとコンパイルエラーが出る
effect-tsで入力チェック３ - Schema

入力チェックのやり方のメモ
Schema.Unionにおいて取り扱い注意事項が存在する

# effect-ts : Schema

https://effect.website/docs/schema/basic-usage/#union-member-evaluation-order

## 前回

https://qiita.com/kuangzhixitian3/items/b80d77f3e36f1fd8e05c

### 引数の順番で結果が変わるもの

Schema.Union は 引数の順番で結果が変わる
このような現象はpipe周りでも多く発生している気がする
本来はeither型を使用するなどして、使用者側で修正できるようにすべきだと思うが
そうではないため、暫定的な対処方法を記載しておく


```ts
import { describe, it } from 'vitest'
import { Schema, SchemaAST, Array, Order } from 'effect'

describe('effect-ts 入力検証 - Union', () => {
  const Member1 = Schema.Struct({
    a: Schema.String
  })

  const Member2 = Schema.Struct({
    a: Schema.String,
    b: Schema.Number
  })

  const Bad = Schema.Union(Member1, Member2)
  const Good = Schema.Union(Member2, Member1)

  const NotBad = Schema_Union(Member1, Member2)
  const Good2 = Schema_Union(Member2, Member1)

  function Schema_Union<
    Struct extends Schema.Struct<any>,
    Members extends SchemaAST.Members<Struct>
  >(...members: Members) {
    const ordered_members = Array.sort(
      members,
      Order.reverse(Order.mapInput(Order.number, (item: Struct) => Object.keys(item.fields).length))
    )

    const union = Schema.Union(...members)
    return Schema.Union(...ordered_members) as typeof union
  }

  it('サイトにあったやり方と改良したもの - decode', () => {
    const testData = {
      a: 'a',
      b: 12
    }
    console.log(Schema.decodeUnknownSync(Bad)(testData))
    console.log(Schema.decodeUnknownSync(Good)(testData))
    console.log('------')
    console.log(Schema.decodeUnknownSync(NotBad)(testData))
    console.log(Schema.decodeUnknownSync(Good2)(testData))
  })
})
```

実行結果
```ts
{ a: 'a' }
{ a: 'a', b: 12 }
------
{ a: 'a', b: 12 }
{ a: 'a', b: 12 }
```
◯マスを Arch Linux でやりたい

# 背景
私の Android がかすすぎて ◯マス がうごかない。
なんか、[NOX](https://jp.bignox.com/) みたいなのが Linux にもないのかな？

ということで、Genymotion や android の iso ファイルをダウンロードして VM で動かす等色々やったが、うまくいかず1週間ほど試行錯誤してたら、こんな簡単にうまく行った。しかも驚くほど軽量。

# Waydroid とは
> Waydroid は、Linux システム上のコンテナ化された環境で Android を実行できるようにするコンテナベースのメソッド。 

らしい([wiki](https://en.wikipedia.org/wiki/Waydroid))。 Emulator という認識でいいのかな？

# Install & Init
\# Bug のセクションまでは、こちらを参照したほうがわかりやすい。

https://slacknotebook.com/linux-use-waydroid-to-run-android-apps/

### install 
```shell
yay -S waydroid
```

### run(init)
```shell
waydroid
```

VANILLA ... 何もインストールされていない状態
GAPPS ... Googleストア同梱版 の2つがある。

もちろん GAPPS を選択。

# Run

run
```shell
waydroid show-full-ui
```
もしくは rofi 等から開くと、デフォルトで show-full-ui で開かれるはず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667904/d811313b-d39f-4e2d-b26e-a5b4129a63fc.png)

めちゃくちゃ軽量でびっくりした。

# Certify

まずは Waydroid のシェルを起動。
```
sudo waydroid shell
```
起動後、以下を入力
```shell
ANDROID_RUNTIME_ROOT=/apex/com.android.runtime ANDROID_DATA=/data ANDROID_TZDATA_ROOT=/apex/com.android.tzdata ANDROID_I18N_ROOT=/apex/com.android.i18n sqlite3 /data/data/com.google.android.gsf/databases/gservices.db "select * from main where name = \"android_id\";"
```

出力された android_id | 後の ID を [Google Play デバイス登録ページ](https://www.google.com/android/uncertified)にペーストする。


# Bug (つまづいた)
さっそく google play からインストールしようとすると、、、

青色の install ボタンがなく、
`This tablet isn't compatible with this app`
と書かれている。

https://github.com/waydroid/waydroid/issues/1609

Issue にも書かれてるように
`There are many ways to install arm translation...`
らしく、どうやら ARM translation というものが必要だそう。
以下２つの LINK が貼られていたが、GUI でよさげな waydroid-helper のほうは、Extension の install が遅すぎたので、最終的には waydroid_script の方で行った。 
#### うまくいった
https://github.com/casualsnek/waydroid_script
#### うまくいかなかった
https://github.com/ayasa520/waydroid-helper/

# Install waydroid_script
リポジトリに書いてる通り、下記コマンドでインストールする
```
git clone https://github.com/casualsnek/waydroid_script
cd waydroid_script
python3 -m venv venv
venv/bin/pip install -r requirements.txt
```

# Install Extension

### libhoudini
(READMEを見ながら...) 
とりあえずいかにもそれっぽさそうな　`libhoudini arm translation` を入れてみる

waydroid_script (main.pyが見えるところ)の下に移動して、
```shell
sudo venv/bin/python3 main.py install libhoudini
```
をすると、おお、自動で再起動した。

直ってるかと思いきやまた青色の install ボタンはなかった。

### widevine

README の次にあった　`Integrate Widevine DRM (L3)` を入れてみた
```shell
sudo venv/bin/python3 main.py install widevine
```

同様に自動で再起動され、play store のそこには青色の install ボタンが...!!

無事起動もでき、問題なく動いている。

(`libhoudini` を記事に載せたのはもしかしたらどちらも必要だったかもしれないということで)

# 画面解像度の固定(指定)
先程紹介した `waydroid-helper` の settings タブにある。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667904/6fcb1e64-d417-4b80-b54d-816f819d8d00.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2667904/27806391-7852-4102-82f6-e9698aa251ce.png)

がくますやれよ

# 参考文献
https://slacknotebook.com/linux-use-waydroid-to-run-android-apps/

https://github.com/waydroid/waydroid/issues/1609
How to Set Configuration Only for the CI Environment

## Overview
This post report a way to set configuration only for the CI Envirionment. Rails application flequently use RSpec in CI/CD pipeline. Like many others I also follow this approach in Rails application development.

One day, I found numerous logs displayed in the GitHub Actions output during the RSpec process.Following error code is diplayed in real.
```
log writing failed. "\xE4" from ASCII-8BIT to UTF-8
log writing failed. "\xE4" from ASCII-8BIT to UTF-8
・
・
・
```
I researched reason why this error occurred. As a result, I found that the process of handling CSV in RSpec caused this error. However, I couldn't stop using the existing RSpec. So I tried resolve this error.

## What is the reason?
I investigated the output when running RSpec in my local development environment and found that the above error occurred when Rails attempted to write execution logs to the local storage of the Docker container. Both my local and CI environments used UTF-8 encoding. However, RSpec attempted to write logs in ASCII-8BIT while handling CSV files.

Resolving each error one by one would require significant effort. Therefore, I decided to disable log writing to log/development.log in local storage. At first glance, this decision may seem like an act of laziness or an attempt to avoid solving the problem. However, it not only resolves the previously mentioned issue but also helps reduce CI execution time.

RSpec runs inside a Docker container as defined in the CI.yml file. Logs written inside the container during CI execution cannot be viewed unless they are transferred to another environment. However, this is hardly a problem.


## How to make Rails identify CI environment

Simply add the following code to the appropriate configuration file:

```
 if ENV['CI']
    config.logger = ActiveSupport::TaggedLogging.new(Logger.new(nil))
 end
```
ENV['CI'] is set by CI/CD tools by default.
数学のめっちゃ計算する問題をC言語でやってみた

₃₀C₂₁(1/2)²¹(1/2)⁹ + ₃₀C₂₂(1/2)²²(1/2)⁸ + ... + ₃₀C₂₉(1/2)²⁹(1/2)¹ + ₃₀C₃₀(1/2)³⁰
を計算する問題（ではないけど）があったので、コンピュータにやらせちゃおうと思いました。

```C:main.c
#include <stdio.h>
#include <stdlib.h>

void bunsu_tasizan(long,long,long,long,long*,long*);
void yakubun(long*,long*);
void C_keisan(long,long,long*,long*);
long yukurido(long, long);

int main() {
    long double shousu;
    int x = 30,y = 21;
	int kou_size = x - y + 1;
    long bunsi;
    long bunbo;
    long *kakubunsi = (long*)malloc(sizeof(long) * kou_size);
    long *kakubunbo = (long*)malloc(sizeof(long) * kou_size);
    long kekka_bunsi;
    long kekka_bunbo;
    long ni_sanjujou = 1;
    int i;

    for(i = 0;i < 30;i++){
        ni_sanjujou *= 2;
    }

    for(i = 0;i < (kou_size);i++){
        C_keisan(x,y + i,&bunsi,&bunbo);
        kakubunsi[i] = bunsi;
        kakubunbo[i] = bunbo * ni_sanjujou;
    }

    kekka_bunsi = kakubunsi[0];
    kekka_bunbo = kakubunbo[0];
    for(i = 0;i < (x - y);i++){
        bunsu_tasizan(kekka_bunsi,kekka_bunbo,kakubunsi[i+1],kakubunbo[i+1],&kekka_bunsi,&kekka_bunbo);
    }

    printf("%ld/%ld\n",kekka_bunsi,kekka_bunbo);

    shousu = (long double)kekka_bunsi / (long double)kekka_bunbo;
    printf("%.15Lf\n",shousu);

	free(kakubunsi);
	free(kakubunbo);

    return 0;
}

void bunsu_tasizan(long bunsi1,long bunbo1,long bunsi2,long bunbo2,long *bunsi,long *bunbo){
    if(bunbo1 != bunbo2){
        long a;
        a = yukurido(bunbo1,bunbo2);
		long tsubun_bunbo = bunbo1 / a;
        bunbo1 *= (bunbo2 / a);
        bunsi1 *= (bunbo2 / a);
        bunsi2 *= (tsubun_bunbo);
    }
    (*bunbo) = bunbo1;
    (*bunsi) = bunsi1 + bunsi2;
    yakubun(bunsi,bunbo);
}

void C_keisan(long n,long m,long *bunsi,long *bunbo){
	long bunsi2 = 1;
	long bunbo2 = 1;

    if(n - m < m){
        m = n - m;
    }
	int kou_size = m;
    long *bunsi1 = (long*)malloc(sizeof(long)*kou_size);
    long *bunbo1 = (long*)malloc(sizeof(long)*kou_size);

    for (int i = 0;i < m;i++){
        bunsi1[i] = (n - i);
        bunbo1[i] = (m - i);
    }
	for(int i = 0;i < m;i++){
		for(int j = 0;j<m;j++){
			if(*(bunsi+i) == 1){
				j = m;
			}
			else{
				yakubun(bunsi1+i,bunbo1+j);
			}
		}
	}
	for(int i = 0;i < m;i++){
		bunsi2 *= *(bunsi1+i);
		bunbo2 *= *(bunbo1+i);
	}

	free(bunsi1);
	free(bunbo1);

	yakubun(&bunsi2,&bunbo2);
	(*bunsi) = bunsi2;
	(*bunbo) = bunbo2;
}

void yakubun(long *bunsi,long *bunbo){
    long maxkouyakusu;
    maxkouyakusu = yukurido(*bunsi,*bunbo);

    (*bunsi) /= maxkouyakusu;
    (*bunbo) /= maxkouyakusu;
}

long yukurido(long x,long y){
    long temp;
    if(x < y){
        temp = x;
        x = y;
        y = temp;
    }

    long r = x % y;
    while(r != 0){
        x = y;
        y = r;
        r = x % y;
    }
    return y;
}
```

``` C:実行結果
22964087/1073741824
0.021386972628534
```

無駄な部分がめちゃくちゃ多いと思うけど、修正するの大変なので許してください。

今回コードを書いてみて、C言語のポインタの便利さがめっちゃわかりました。
[2025年2月時点] Google タイムラインのデータエクスポート方法 [Android]

他に書く場所がなく、誰かの役に立てばということでここに置いておきます。

gpxへの変換や、マッピング!へのインポート方法はこちら
https://qiita.com/kumakumao/items/f82bdd9b28228ffc9b6e


## 前提
Android14, OneUI 6.1 (Galaxy)のケースです。
執筆時点では、Google Mapアプリや、Google takeoutではエクスポートできませんでした。

## 手順
#### 「端末」の設定画面を開く
googlemapアプリではなく、端末の設定なことに注意
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/19fb5cd4-4624-4aa8-887a-91af87fa0062.jpeg" width= "300px" >

#### 「位置情報」をタップ
 <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/87a0b6a6-fad2-42f7-96cf-52bf5e4780a7.jpeg" width= "300px" >

#### 「位置情報サービス」をタップ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/58664106-f73d-478d-936c-cf565e961c35.jpeg" width= "300px" >

#### 「タイムライン」をタップ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/9721ff8e-aff3-46b7-8bee-5ccef806118d.jpeg" width= "300px" >

#### 「タイムラインをエクスポート」をタップ
json形式でエクスポートできます(私の場合は80MB程度でした)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1019457/a7fad0ae-65e4-413d-a114-c7b248b92fb9.jpeg" width= "300px" >
Zabbixの監視構造について

今回はZabbixに関して、なんだか湧いてきた疑問から、監視構造の理解を深めたいと思います。
それではさっそく。

## Zabbixはどうやってインストールしたサーバで監視を行っているのか

結論からいうと、サーバにZabbixエージェントを導入すると稼働データをローカルに保存し、そのデータをZabbixサーバ側に送信します。
その際、エージェント側ではデータの処理をせず、サーバ側に送信した後、データを処理しています。



また、処理する際には、JSON ベースの通信プロトコルを使用して、サーバとZabbix エージェントとの間で通信を行っています。
※この送信サイズには上限もありますので、詳しくは、公式のドキュメントを確認してください。

https://www.zabbix.com/documentation/2.2/jp/manual/appendix/items/activepassive



このJSONベースの通信プロトコルには２種類あり、ポート番号も異なります。
パッシブチェックとアクティブチェックです。

・パッシブチェック（ポート番号：10050）
サーバ側から問い合わせを行い、エージェントが結果を返します。

・アクティブチェック（ポート番号：10051）
Zabbixエージェントは、個々の処理のために、最初にZabbixサーバからアイテムのリストを検索します。 その後、更新された値をサーバに定期送信します。
つまり、エージェントは設定ファイル（zabbix_agentd.conf）の中身を見て、そのデータをサーバ側に送っています。



※7.0.0以降、Asynchronous Pollerという新機能を追加して非同期でのデータ処理が可能になったようです。
 
 https://www.cybertrust.co.jp/blog/linux-oss/system-monitoring/tech-lounge/zabbix70-asynchronous-poller.html



また、ポートについては監視するアイテムによって違います。以下も参考にしてみてください。


https://manual.iij.jp/uom/usersguide-managedmonitoringforzabbix/50642154.html




今回は、Zabbixサーバとエージェントがどのような監視を行うかを調べることで、
監視方法や通信プロトコルに何が使われてるのかを理解することができました。



次回は、ZabbixのDBの理解深め、収集したデータをどのように処理しているのかを調査したいと思います！


参考：
https://www.zabbix.com/documentation/2.2/jp/manual/concepts/agent
https://satimo.org/2021/02/zabbix-passive-active-check/
ChatGPTは

ChatGPTは、自然な文章を生成し、質問に答えることができる高度なAIモデルです。OpenAIによって開発され、さまざまな分野で活用されています。

ChatGPTの特徴:
多言語対応：日本語、アラビア語、英語などをサポート。
高品質なコンテンツ生成：記事、レポート、ストーリーの作成が可能。
迅速で正確な回答：あらゆる質問に対応。
データ分析とプログラミング支援：開発者にとって有益。
ChatGPTの活用例:
教育とリサーチ：学生や研究者が情報を素早く取得。
コンテンツ制作：ジャーナリストやライター向けの執筆支援。
カスタマーサポート：自動応答システムとして利用可能。
デジタルマーケティング：広告文の作成や市場分析に役立つ。
個人的に気になる2025年2月新刊一覧【IT・セキュリティ・データサイエンス】

## まえがき

2025年2月発売の新刊から、気になったものをピックアップしました。

- 2025年2月に出版される本（改訂・新装丁版込）
- 個人的に興味を持ったもの
- ジャンルや順番は適当

読んでいないため内容の保証はできませんが、参考になれば幸いです。

リンクはアフィリエイトではありません。できる限り出版社のURLを貼っていますが、Amazonでしか見当たらなかったものや予約不可などになっている場合は、渋々AmazonのURLを採用しています。

## IT

### Gitハンズオンラーニング

https://www.oreilly.co.jp/books/9784814401048/

発売日: 2025年2月5日  

### ストリートコーダー

https://www.amazon.co.jp/dp/4798073458  

発売日: 2025年2月26日  

### ROS2とPythonで作って学ぶAIロボット入門 改訂第2版

https://bookclub.kodansha.co.jp/product?item=0000407871  

発売日: 2025年2月14日  

### システム設計面接の傾向と対策

https://www.shuwasystem.co.jp/book/9784798072791.html  

発売日: 2025年2月1日  

### DApps開発入門

https://www.amazon.co.jp/dp/4863544669  

発売日: 2025年2月11日  

### エンジニア選書シリーズ［詳解］AWS Infrastructure as Code――使って比べるTerraform＆AWS CDK

https://gihyo.jp/book/2025/978-4-297-14724-2  

発売日: 2025年2月12日  

### 仕組みからわかる大規模言語モデル 生成AI時代のソフトウェア開発入門

https://www.shoeisha.co.jp/book/detail/9784798185262  

発売日: 2025年2月17日  

### Kubernetesで実践する Platform Engineering

https://www.shoeisha.co.jp/book/detail/9784798188379  

発売日: 2025年2月19日  

### 実務で役立つ バックアップの教科書 基本の考え方からツール活用・差分管理・世代管理・データ保全・リストア・リカバリー・可用性の確保まで

https://www.shoeisha.co.jp/book/detail/9784798188386  

発売日: 2025年2月19日  

## セキュリティ

### 能動的サイバー防御　日本の国家安全保障戦略の進化

https://bookplus.nikkei.com/atcl/catalog/25/01/08/01804/  

発売日: 2025年2月17日  

### イラスト図解式 この一冊で全部わかるセキュリティの基本 第２版

https://www.sbcr.jp/product/4815629373/  

発売日: 2025年2月12日  

### AI・量子コンピュータにかかわるリスク管理　セキュリティからガバナンスヘ

https://www.ohmsha.co.jp/book/9784274233098/  

発売日: 2025年2月7日  

### セキュリティエンジニアの知識地図

https://gihyo.jp/book/2025/978-4-297-14748-8  

発売日: 2025年2月25日  

## データサイエンス

### 応用基礎としてのデータサイエンス　改訂第２版　ＡＩ×データ活用の実践

https://bookclub.kodansha.co.jp/product?item=0000407872

発売日: 2025年2月14日  

### やさしく学ぶLLMエージェント　基本からマルチエージェント構築まで

https://www.ohmsha.co.jp/book/9784274233166/

発売日: 2025年2月15日  

### データのつながりを活かす技術〜ネットワーク／グラフデータの機械学習から得られる新視点

https://gihyo.jp/book/2025/978-4-297-14784-6

発売日: 2025年2月25日  

### つくりながら学ぶ！LLM 自作入門

https://book.mynavi.jp/ec/products/detail/id=146901

出版予定日がAmazonでは2/27、マイナビでは3/3と異なっている。  

### グランドマスター三冠のKaggleノートブック開発術　単変量解析から地理情報分析／偽動画検出／LLMまで

https://book.impress.co.jp/books/1124101036

発売日: 2025年2月19日  

### ノンパラメトリック法―カーネル型推定による統計的推測―

https://www.kyoritsu-pub.co.jp/book/b10107170.html

発売日: 2025年2月5日
Delphi12 Community Ed.でのJEDI JCL JVCLのインストール方法つづき

## その後の話

前回12/13にこんな記事を書きました。  
https://qiita.com/jr8ppg/items/95f4dc934942a30794a7

この中にJVCLのソースが壊れていると記載しています。  

今日になって、再度Delphi12CEをインストールすることになったのですが、  
なんと、12/15付けの[コミット](https://github.com/project-jedi/jvcl/commit/c3f2093220d4b3ed28713270528c4d7675acf7e6)で直っています。  

イエー  

これで面倒なこと無しにビルドできます。