OmniAICreator/Qiita-1.07M huggingface dataset:
dSPACEエンコーダ使い方まとめ

## 1. はじめに
dSPACEでエンコーダを扱うために必要な知識をまとめました．
プラットフォーム(MicroLabBox)専用のブロックを使う方法とSimulinkでブロックを組み合わせたロジックを説明します．

## 2. 配線
- プルアップ抵抗 3kΩくらい
- エンコーダ(A/Bパルスタイプ)

![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/2488cca3-c20b-a25b-cfbd-7a957cdb128d.png)



## 3. Encoderブロック
[こちらの記事](https://qiita.com/3084LAB/items/2ab89d8b060d134a605e)を参考にしてください．

## 4. ロジック
Encoderブロックはdigital信号を使用しますが，ノイズが乗ったとき使い物にならなくなります．
アナログADCをA,B相用に2チャンネル使用してパルスカウントする方法です．
Pulse出力の先にPPRによる角度への変換をつければ完成です．

全体構成↓
![スクリーンショット 2024-12-25 203805.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/19541b5b-d337-c8be-f3b7-15fc88c8a574.png)

pulse_merge_1と2のサブシステムの中身↓
![スクリーンショット 2024-12-25 203918.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/3d36c434-9727-aecc-3440-52c89dca88ec.png)

pulse_implicationサブシステムの中身↓
![スクリーンショット 2024-12-25 203948.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2654082/b622c028-8963-0d0c-8702-1a0e07774d72.png)
Reactでスクロールを検知して処理をする[クリーンアップ関数]

## Reactでスクロールを検知して処理をする
## やりたいこと
ユーザーが画面下までスクロールしたことを検知してなんらかの処理を行う

## 実装
```typescript
  useEffect(() => {
    const handleScroll = () => {
      const userPosition = window.scrollY;
      const windowHeight = window.innerHeight;
      const documentHeight = document.documentElement.scrollHeight;

      if (userPosition + windowHeight >= documentHeight) {
        doSomething();
      }
    };

    window.addEventListener("scroll", handleScroll);

    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, []);
  ```

## 解説
まずはwondow.addEventListenerでスクロール位置を関します。
スクロールされる度にhandleScrollが呼び出されます。
```typescript
window.addEventListener("scroll", handleScroll);
```
以下がhandleScrollの中身です。
ユーザーのスクロール位置、画面の幅を取得します。
```typescript
const userPosition = window.scrollY; //ユーザーの位置を取得
const windowHeight = window.innerHeight; //ユーザーの画面領域を取得(端末の表示できる画面)
const documentHeight = document.documentElement.scrollHeight; //アプリの全領域を取得
```
アプリの全領域よりもユーザーのスクロール位置＋ユーザーの画面の表示領域が大きい場合、画面最下部までスクロールされたと判断する
```typescript
if (userPosition + windowHeight >= documentHeight) {
    doSomething();
}
```
最後に以下の処理が重要です。
Reactのクリーンアップ関数でコンポーネントがアンマウントされた後にスクロールの監視をやめます。
この処理をしないとhandleScrollが発火した後も、handleScrollを繰り返し続けます。
```typescript
return () => {
  window.removeEventListener("scroll", handleScroll);
};
```
:::note info
用語の解説
クリーンアップ関数...useEffectが実行される直前もしくは、コンポーネントがアンマウントされる時に実行される関数。
アンマウント...DOMからコンポーネントが削除されること
:::

## 最後に
クリーンアップ関数の必要性＆存在を知らずに永遠と繰り返される処理に詰まってしまいましたが、Reactの勉強になりました。
この記事が誰かの助けになれば幸いです。
Flutterのチュートリアルを学んでみた(5)

# Flutterで無限スクロールを作ろう！ 📱

## 今日は何を作るの？ 🎯

SNSアプリのように、下にスクロールすると次々と新しい内容が表示される画面を作ります！
これを「無限スクロール」と呼びます。

![01_ListView.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3929117/a2e9ba7c-a0bc-cb31-9b25-72657533c5f7.png)
引用:https://flutter.ctrnost.com/tutorial/tutorial06/

## 準備しよう！ 🚀

### Step 1: 単語を保存する箱を作る 📦

まず、たくさんの単語を保存できる箱と、文字の大きさを決める設定を作ります：

```dart
class RandomWordsState extends State<RandomWords> {
  final _suggestions = <WordPair>[];              // 単語を保存する箱
  final _biggerFont = const TextStyle(fontSize: 18.0);  // 文字の大きさ設定
}
```

> 💡 **豆知識**: 変数名の前の`_`（アンダースコア）は「内緒の変数」という意味です。
> この変数は、このクラスの中でだけ使える特別な変数になります！

### Step 2: リストを作る魔法 ✨

次に、スクロールできるリストを作る魔法（メソッド）を作ります：

```dart
Widget _buildSuggestions() {
  return ListView.builder(
    padding: const EdgeInsets.all(16.0),
    itemBuilder: (context, i) {
      // リストの項目を作る魔法！
      if (i.isOdd) return Divider();    // 奇数番目には線を引く
      
      final index = i ~/ 2;   // 実際の単語の番号を計算
      
      // もし単語が足りなくなったら
      if (index >= _suggestions.length) {
        // 新しい単語を10個追加！
        _suggestions.addAll(generateWordPairs().take(10));
      }
      
      // 単語を表示用に整形
      return _buildRow(_suggestions[index]);
    }
  );
}
```

#### どうやって動いているの？ 🤔

想像してみてください：
1. スクロールするたびに`itemBuilder`が呼ばれます
2. 偶数番目（0, 2, 4...）には単語を表示
3. 奇数番目（1, 3, 5...）には線を引く
4. 単語が足りなくなったら、新しい単語を追加！

これは、まるで魔法の本のように、ページをめくるたびに新しい内容が現れるようなものです！

### Step 3: 単語を見やすく表示する 👀

各単語をきれいに表示するための方法を作ります：

```dart
Widget _buildRow(WordPair pair) {
  return ListTile(
    title: Text(
      pair.asPascalCase,    // 単語をきれいな形式で表示
      style: _biggerFont,   // 大きな文字で表示
    ),
  );
}
```

### Step 4: 画面全体を組み立てる 🏗

now、全体を組み立てましょう：

```dart
@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('面白い単語ジェネレーター'),  // 上のバーのタイトル
    ),
    body: _buildSuggestions(),  // リストを表示
  );
}
```

### Step 5: メインの画面を設定 🎨

最後に、アプリのメイン画面を設定します：

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: '面白い単語ジェネレーター',
      home: RandomWords()
    );
  }
}
```

## 動かしてみよう！ 🎮

1. コードを保存する
2. ホットリロードが実行されるのを待つ
3. 画面を下にスクロール
4. どんどん新しい単語が表示されるよ！

## やってみよう！ 🌟

1. 文字の大きさを変えてみる
2. 線の代わりに別の区切りを入れてみる
3. 表示する単語の数を変えてみる

## 困ったときは？ 🆘

- リストが表示されない
  → buildメソッドの中身を確認しよう
- スクロールできない
  → ListViewがちゃんと設定されているか確認しよう
- 新しい単語が追加されない
  → if文の条件を確認しよう

## 大切なポイント ⭐️

1. ListView.builderは必要なときだけ項目を作る賢い仕組み
2. スクロールに応じて自動的に新しい内容を表示
3. Dividerで見やすく区切りを入れる
4. privateな変数は_（アンダースコア）をつける



## チャレンジしてみよう！ 🚀

1. 表示する単語の色をランダムに変える
2. 奇数番目と偶数番目で背景色を変える
3. タップしたらアラートを表示する

さぁ、あなただけの無限スクロールを作ってみましょう！ 💪
電子工作の基礎となる電気の知識

## 電気回路
電気が流れる道のりのことを電気回路と呼ぶ。

## 電流
1秒間に流れる電子の粒の数のことで、単位はアンペア（A）

## 電圧
電子1粒のいきおいのことで、単位はボルト（V）

## 参考文献
https://www.try-it.jp/chapters-1944/sections-1945/
WebXR APIについて

# WebXR APIについて：未来をつかむVR/ARの窓口

VR（仮想現実）の世界にどっぷり浸かりたいけど、高価な専用機器や技術の壁が高いと感じている皆さん、朗報です！そんな未来のエンターテインメントをもっと手軽に実現する技術が **WebXR API**。この記事では、WebXR APIが何なのか、そしてどう私たちの日常や娯楽に影響を与えるのかを解説していきます！

---

## WebXR APIとは？
簡単に言えば、「ウェブブラウザからVRやAR体験を提供するための技術」です。  
「ブラウザからVR？ゲーム用の大きなヘッドセットと何が違うの？」と思った方もいるでしょう。その違いは、手軽さと互換性！  
従来のVRシステムは専用のアプリケーションやハードウェアが必要でしたが、WebXR APIならブラウザを通じて動作するため、対応したPCやスマートフォンがあれば特別なアプリをインストールしなくてもすぐにVR/AR体験ができます。

---

## どんなことができるの？
- **ゲーム**: ブラウザベースのVRゲームが可能に！リンクをクリックするだけで、迫力ある3Dの世界にジャンプ。課金しないとアイテムがもらえない現実から一時脱出できます。
- **ショッピング**: 実物サイズの家具や洋服をAR空間でチェック。買い物で失敗しなくなるかも（あ、送料は除きます）。
- **教育・仕事**: 仮想教室やバーチャル会議室に簡単アクセス。これなら部屋着で会議に出てもばれません！

---

## WebXR APIの仕組み
基本的には、WebXR APIはVR/AR対応デバイス（ヘッドマウントディスプレイやコントローラー）とブラウザをつなぐ橋渡しのようなものです。このAPIは以下の3つの重要な要素で成り立っています：

1. **センサーアクセス**: デバイスの動きをトラッキングし、ユーザーの位置情報を正確に把握。
2. **ディスプレイ描画**: 3DシーンやARオブジェクトをリアルタイムでレンダリング。
3. **ユーザー入力**: コントローラー、キーボード、さらには音声入力を処理。

Web開発者にとっては使いやすい設計であり、UnityやA-Frameなどのライブラリを使えば、初心者でも比較的簡単にVR/ARコンテンツが作れます。

---

## WebXR APIの現状と未来
**WebXR APIは、2020年に廃止されたWebVR APIの進化版です。** WebXRはVR（仮想現実）だけでなく、AR（拡張現実）もサポートしており、より幅広い応用が可能です。これにより、ブラウザ上でのインタラクティブな体験がさらに多様化し、私たちの日常生活やエンターテインメントに大きな変革をもたらすでしょう。

---

## 最後に
WebXR APIは、未来のインターネット体験を形作る重要な技術です。その可能性は無限大。次にブラウザを開いたとき、「これがVRやARに使えるかな？」と考えると、少しワクワクしませんか？

興味が湧いたら、[WebXR公式ドキュメント](https://immersive-web.github.io/webxr/)や「WebXR サンプル」で検索して体験を試してみましょう！
Flutterのチュートリアルを学んでみた(4)

# Flutterの状態管理を学ぼう！StatefulWidgetの冒険 🎮

## StatefulWidgetって何だろう？ 🤔

みなさん、ゲームで遊んだことありますよね？
ゲームには「スコア」や「ライフ」など、プレイ中に変わる値がありますよね。
Flutterでも同じように、アプリの中で変わる値を扱いたいことがあります。
そんなとき使うのが「StatefulWidget（ステートフルウィジェット）」です！

## StatelessWidgetとの違い 📊

### StatelessWidget（変わらない箱）
- 一度決めた値は変えられない
- 表示するだけの簡単な画面に使う
- 例：ただテキストを表示するだけの画面

### StatefulWidget（変わる箱）
- 値を変更できる
- ユーザーの操作で変わる画面に使う
- 例：カウンターアプリ、ゲームの得点表示

## 魔法の箱を作ってみよう！ 🎁

### Step 1: State（状態）クラスを作る 📝
まず、値を保存できる箱を作ります：

```dart
class RandomWordsState extends State<RandomWords> {
}
```

これは、「RandomWordsの状態を保存する箱」というような意味です。
まだ中身は空っぽですが、これから色々入れていきます！

### Step 2: StatefulWidgetを作る 🏗
次に、その箱を使うためのウィジェットを作ります：

```dart
class RandomWords extends StatefulWidget {
  @override
  RandomWordsState createState() => RandomWordsState();
}
```

これは「RandomWordsStateという箱を使うよ」と宣言しているようなものです。

### Step 3: 画面の見た目を作る 🎨
状態を保存する箱に、画面の見た目を追加します：

```dart
class RandomWordsState extends State<RandomWords> {
  @override
  Widget build(BuildContext context) {
    final wordPair = WordPair.random();
    return Text(wordPair.asPascalCase);
  }
}
```

これで、ランダムな英単語を表示する部分ができました！

### Step 4: メインの画面で使う 🖼
最後に、作ったウィジェットをアプリで使えるようにします：

```dart
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: RandomWords(),  // ここで使います！
        ),
      ),
    );
  }
}
```

## どうして2つのクラスが必要なの？ 🤓

想像してみてください：
1. `RandomWords`（StatefulWidget）は「設計図」みたいなもの
2. `RandomWordsState`は実際に値を保存する「箱」みたいなもの

両方あることで：
- 設計図（どんな機能が必要か）
- 実際の保存場所（値をどう保存するか）
が分かれて、整理しやすくなります！

## やってみよう！ 🌟

1. RandomWordsStateに新しい変数を追加してみよう
   ```dart
   final List<WordPair> words = [];  // 単語を保存するリスト
   ```

2. buildメソッドで使ってみよう
   ```dart
   words.add(WordPair.random());  // 新しい単語を追加
   ```

3. 保存した単語を表示してみよう

## 大切なポイント ⭐️

1. StatefulWidgetは値が変わる部分に使う
2. Stateクラスでその値を保存する
3. 2つのクラスが必要（設計図と保存箱）
4. buildメソッドで画面の見た目を作る

## 次は何ができる？ 🎯

- カウンターアプリを作る
- お気に入りリストを作る
- ゲームのスコアを表示する

StatefulWidgetを使えば、もっとインタラクティブな
アプリが作れるようになりますよ！

## 実験してみよう！ 🔬

1. 違う種類の値を保存してみる
2. ボタンを押したら値が変わるようにする
3. 保存した値を別の方法で表示してみる

さぁ、StatefulWidgetの世界で遊んでみましょう！ 
これであなたも状態管理の達人です！ 🎉
Flutterのチュートリアルを学んでみた(3)

# Flutterで外部パッケージを使ってみよう！ 📦

## パッケージって何だろう？ 🤔

みなさん、スマートフォンでアプリを使うとき、新しい機能が必要になったら全部自分で作りますか？
そうですね、普通は必要な機能をダウンロードして使いますよね！

Flutterでも同じように、便利な機能をダウンロードして使うことができます。
これを「パッケージ」と呼びます。パッケージは、誰かが作った便利な道具箱のようなものです！

## 今日使うパッケージの紹介 📝

今回は `english_words` というパッケージを使ってみましょう。
このパッケージは、ランダムに英単語を作り出してくれる魔法の箱です！

## パッケージの追加方法 🎯

### Step 1: パッケージを教える 📚
まず、私たちのアプリに「english_words」というパッケージを使いたいと教えます。
`pubspec.yaml`というファイルを開いて、以下のように書き足します：

```yaml
dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2
  english_words: ^3.1.0  # これを追加！
```

これは、お買い物リストのようなもので、「このアプリには these packages が必要です！」と書いているんです。

### Step 2: パッケージをダウンロード 🚀
パッケージを実際に手に入れましょう！

通常は`pubspec.yaml`を保存すると自動でダウンロードが始まります。
もし自動でダウンロードされない場合は、以下のコマンドを使います：

```bash
flutter packages get
```

これは、「パッケージさん、来てください！」とお願いするようなものです。

### Step 3: パッケージを使う準備 📱
次に、私たちのプログラムでパッケージを使えるようにします。
`lib/main.dart`の一番上に以下の行を追加します：

```dart
import 'package:flutter/material.dart';
import 'package:english_words/english_words.dart';  // 新しい行を追加！
```

これは、「english_wordsパッケージを使わせてください！」とお願いしているようなものです。

## パッケージを使ってみよう！ 🎮

では、実際にランダムな英単語を表示してみましょう。
以下のように`main.dart`を変更します：

```dart
@override
Widget build(BuildContext context) {
  final wordPair = WordPair.random();  // ランダムな英単語を生成！
  return MaterialApp(
    title: 'Welcome to Flutter',
    home: Scaffold(
      appBar: AppBar(
        title: Text('Welcome to Flutter'),
      ),
      body: Center(
        child: Text(wordPair.asPascalCase),  // 生成した単語を表示！
      ),
    ),
  );
}
```

### 何が変わったの？ 🔄

1. `WordPair.random()`で、ランダムな英単語のペアを作ります
2. `.asPascalCase`で、きれいな形式で表示します（例：'CoolWords'）
3. アプリを更新するたびに、新しい単語が表示されます！

## 面白い発見 💡

- 画面を更新するたびに新しい単語が表示されるのは、`build`メソッドが呼ばれるたびに新しい単語を生成しているからです
- これは、おもちゃのガチャガチャのように、回すたびに新しいものが出てくるようなものです！

## やってみよう！ 🌟

1. アプリを何回か更新して、どんな単語が出てくるか見てみよう
2. 表示される単語の形式を変えてみよう（`.asPascalCase`を`.asLowerCase`に変えてみる）
3. 自分で好きな単語を表示してみよう

## 他のパッケージを探してみよう 🔍

Flutterには、たくさんの便利なパッケージがあります！
[Flutter Packages](https://pub.dev/flutter)で探してみましょう。

- 画像を表示するパッケージ
- 音楽を再生するパッケージ
- アニメーションを作るパッケージ
など、いろいろあります！

## 大切なポイント ⭐️

1. パッケージは便利な道具箱
2. `pubspec.yaml`でパッケージを追加
3. `import`で使えるようにする
4. たくさんのパッケージを組み合わせて素敵なアプリを作ろう！



パッケージを使えば、もっともっと楽しいアプリが作れるようになりますよ！ 
がんばって実験してみましょう！ 💪
Polarsで、バスの時刻から時刻表を作成

Polarsのlistを使ったサンプルです。

下記のようなバスの到着時刻の表があります。

```python
import polars as pl

times = ["07:20", "07:45", "08:10", "08:30", "08:50", "09:10", "09:30", "09:50"]
df_time = pl.Series("time", times).str.to_time("%H:%M").to_frame()
df_time
```

<small>shape: (8, 1)</small><table border="1" class="dataframe"><thead><tr><th>time</th></tr><tr><td>time</td></tr></thead><tbody><tr><td>07:20:00</td></tr><tr><td>07:45:00</td></tr><tr><td>08:10:00</td></tr><tr><td>08:30:00</td></tr><tr><td>08:50:00</td></tr><tr><td>09:10:00</td></tr><tr><td>09:30:00</td></tr><tr><td>09:50:00</td></tr></tbody></table>

この表からバスの時刻表を作成してみましょう。
バスの時刻表は、時間ごとに、分をリストで表現します。

Polarsでは次のようにできます。

```python
df_dia = df_time.group_by(
    hour=pl.col("time").dt.hour(), maintain_order=True
).agg(minute=pl.col("time").dt.minute())
df_dia
```

<small>shape: (3, 2)</small><table border="1" class="dataframe"><thead><tr><th>hour</th><th>minute</th></tr><tr><td>i8</td><td>list[i8]</td></tr></thead><tbody><tr><td>7</td><td>[20, 45]</td></tr><tr><td>8</td><td>[10, 30, 50]</td></tr><tr><td>9</td><td>[10, 30, 50]</td></tr></tbody></table>

**ポイント**

Polarsではエクスプレッションでグルーピングできます。ここでは、列timeの`dt.hour()`を使ってグルーピングしています。
`agg()`で`dt.minute()`を指定すると、分のリストになります。

元の時刻に戻すには次のようにします。

```python
df_dia.explode("minute").select(time=pl.time("hour", "minute"))
```

<small>shape: (8, 1)</small><table border="1" class="dataframe"><thead><tr><th>time</th></tr><tr><td>time</td></tr></thead><tbody><tr><td>07:20:00</td></tr><tr><td>07:45:00</td></tr><tr><td>08:10:00</td></tr><tr><td>08:30:00</td></tr><tr><td>08:50:00</td></tr><tr><td>09:10:00</td></tr><tr><td>09:30:00</td></tr><tr><td>09:50:00</td></tr></tbody></table>

**ポイント**

`explode()`でlistを行に分解します。
分解したhourとminuteから`pl.time()`で時刻を作成できます。

**参考**

https://qiita.com/SaitoTsutomu/items/ec6dbb5d6f35214dfbee

以上
R6秋　応用情報　午後プログラミング3

# 応用情報のプログラミング問題
素数を列挙するアルゴリズムの実装です。ここでは、20以下の素数とします。
Cなので、関数で配列を直接返せないので、問題のものからいくつか変数を追加しています。

# 改良2
4以上の偶数は全て2の倍数であるので、素数ではありません。よって、2以外の素数は奇数となります。これを利用したのが関数prime3です。

```C:prime3.c
#include <stdio.h>

int* prime3(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    primes[i++] = 2; // 素数2を格納
    int isPrime[21] = {0};

    int c = 3;
    int cindex = 1;
    int d = 3;
    int t;
    while(c <= N){
        isPrime[cindex++] = 1;
        c += 2;
    }
    while(d <= N){
        if(isPrime[(d-1)/2] == 1){
            primes[i++] = d;
            t = d * d;
            while(t <= N){
                isPrime[(t-1)/2] = 0;
                t += 2 * d;
            }
        }
        d += 2;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int main() {
    int N = 20;
    int primes[N];
    int count;
    int* prime_list = prime3(N, primes, &count);

    // 素数のリストを表示
    for (int i = 0; i < count; i++) {
        printf("%d ", prime_list[i]);
    }
    printf("\n");

    return 0;
}
```

余談ですが、```cindex = 0;```だと、最後の素数が出ないという結果になったのですが、```cindex = 1;```にすると、修正できました。
問題文中のインデックスが$1$始まりなので、地味に頭の中がややこしくなります。
【Base64 を利用】音声ファイルを HTML ファイルに直接記述する方法

# はじめに
HTML ファイルには CSS や JavaScript を直接記述することができますが、**音声ファイル**も工夫すればファイル内に直接記述することができます。

本記事では、`Base64` を利用した方法を紹介します。

# 実装
まずは、音声ファイルを `Base64` 形式の文字列に変換します。

検索すると、オンライン上で変換できるページがすぐに見つかると思います。

あとは、その文字列の前に `'data:audio/mp3;base64,'` をつけるだけで完成です。

```html
<script>
const audioBase64String = 'Base64 形式の音声ファイル';
const audioDataUri = 'data:audio/mp3;base64,' + audioBase64String;
const sound = new Audio(audioDataUri);
sound.play();
</script>
```

ただ、この方法は Web ページの読み込み速度が遅くなるため、用途に限られます。
マルチGPUマシンでWindowsはやめとけ

[ちゅらアドベントカレンダー](https://qiita.com/advent-calendar/2024/churadata) 25日目最終日の記事です。

# 軽く自己紹介
初投稿です。
どうもこんにちは、ちゅらデータでデータサイエンティストをしております、クリスマスの午前に健康診断を申し込んだところクリスマスイブにろくなものを食えない思いをしたkon03と言います。
今回まさかのトリを飾ることになりました。
Qiitaも書いたことないようなペーペーの人間が、社長などに一切気を使わずに最終日をもらえる(早い者勝ちなのは内緒)ところから弊社がいかにフラットな組織であるかを、声を大にしてお伝えしたい次第です。
ちなみにそんな会社を作った社長は、去年トリでしたが、まだ投稿されていません...(2024/12/25 19時現在)

# はじめに
弊社では、[ちゅらいと](https://datumstudio.jp/chuwrite/)と呼ばれるAI文章校正ツールをリリースしています。この中で私は、主にAIモデルの改善に勤しんでおります。
このモデル改善のために、弊社では今年の6月にGPUマシンを購入いたしました。RTX6000Ada×4枚を積んだ、かなり強力なマシンです。
このマシンにはOSとしてWindows11 Proが入っており、当初はWSLにて環境を作っておりましたが、そこで起きた不具合について、日本語の記事がないのでまとめさせていただきます。

# この記事で書かないこと
- マルチGPUマシンの詳細なセッティング手順

# 最初にまとめ
- WSLは描画で使っているGPUを学習に使ってくれない
    - sshやネットワークの設定していない状態でこうなると、会社で使うときに死ぬほど困る
- 大人しく、Ubutntuをデュアルブートしよう!

# 経緯
弊社でGPUマシンを買おうとなったのは去年の11月頃です。それから業者の選定・見積もり・社内の調整を経て、ようやく今年の6月に購入することができました。その後、3ヶ月ほど電源などの事情により動かせない時間が続き、結局稼働したのは今年の9月でした。
私はこのマシンの手配をしたため、自動的に管理者のようなものになっており、このマシンにて学習環境を整えることは急務でした。
WSLを入れ、Dockerを入れ、cudaを入れとやっていくと、以下のような不具合に直面しました。

# マルチGPUマシンでWSLで起きている不具合
簡単なpytorchのコードを用意しました。
```python
import torch

print(f"CUDA is available: {torch.cuda.is_available()}")
print(f"CUDA device count: {torch.cuda.device_count()}")
print(f"CUDA version: {torch.version.cuda}")
if torch.cuda.is_available():
    device = torch.device("cuda")
    x = torch.randn(1000, 1000, device=device)
    print("CUDA tensor created successfully")
```

4枚のGPUがあるので、以下のように表示してくれるとちゃんと設定できるわけです。
```python
CUDA is available: True
CUDA device count: 4
CUDA version: 12.1
CUDA tensor created successfully
```

しかし、実際には以下のエラーが出てきます。
```python
/home/kon03/.local/lib/python3.10/site-packages/torch/cuda/__init__.py:118: UserWarning: CUDA initialization: Unexpected error from cudaGetDeviceCount(). Did you run some cuda functions before calling NumCudaDevices() that might have already set an error? Error 2: out of memory (Triggered internally at ../c10/cuda/CUDAFunctions.cpp:108.)
  return torch._C._cuda_getDeviceCount() > 0
CUDA is available: False
CUDA device count: 4
CUDA version: 12.1
```
ここで問題なのは`CUDA is available: False`です。`nvidia-smi`を実行してもちゃんとGPUは4つありますし、nvccなんかもインストールしています。
環境の再構築をしてもエラーは変わりません。GoogleさんやChatGPTといったLLMくんに聞いても、環境の再構築ぐらいしかまともそうな答えが返ってきません。
半ば諦めかけていた時に、ふと思いました。

「もしかしてGPUで壊れているものがある?」

と、
試しに以下で実行してみたところビンゴでした。
```python
$ export CUDA_VISIBLE_DEVICES=1,2,3
$ python3 test.py
CUDA is available: True
CUDA device count: 3
CUDA version: 12.1
CUDA tensor created successfully
```
つまり0番のGPUだけが使えないというわけです。ここまで来るとGoogleさんに聞くことも違ってくるので、同様の問題を発見することができました。
https://forums.developer.nvidia.com/t/quad-4x-a6000-wsl2-cuda-init-errors/238106
https://github.com/docker/for-win/issues/13658
この人たちもGPUの番号は違いますが、同じ問題に直面しています。

# 解決方法
Ubutntuをデュアルブートする。
以上。

# 余談
私はこれで土日を潰しました。

-----
この記事は[ちゅらいと](https://datumstudio.jp/chuwrite/)にて校正されています。
Rust deriveマクロRTA (最小構成のderiveマクロ)


こちらの記事は [Rustマクロ冬期講習アドベントカレンダー](https://qiita.com/advent-calendar/2024/rust-macro) 18日目の記事です！

> アドカレまとめ記事はこちら！: [Rustマクロ作成チートシート！](https://qiita.com/namn1125/items/d601d2cbbf2cc7b5d3dc)

属性風マクロはRustの手続きマクロの一種です。では作っていきます。

# 最小構成のderiveマクロ

ライブラリクレートを作成します。

```bash
cargo new --lib derive_macro
cd derive_macro
```

`Cargo.toml` を書き換えます。

```diff_toml:Cargo.toml
[package]
name = "derive_macro"
version = "0.1.0"
edition = "2021"

[lib]
proc-macro = true

[dependencies]
```

`src/lib.rs` を書き換えます。deriveマクロは **追記する** マクロで入力の構造体/列挙体を食わないので、空のトークンストリームを吐くことにします。

```rust:src/lib.rs
use proc_macro::TokenStream as S;

#[proc_macro_derive(D)]
pub fn d(_: S) -> S {
    S::new()
}
```

動作確認します。

```rust:src/main.rs
use derive_macro::D;

#[derive(D)]
struct S;

fn main() {}
```

```bash
cargo run
```

無事にコンパイルされたところでタイマーストップ。

# まとめ・所感

記録は1分46秒10でした。事前に書き方を予習できたのが良かったですね。

...というわけでRTAとかいう冗談は今回までにして、次回以降はもう少しだけちゃんとそれぞれのマクロについて取り組みたいと思います！
【Unity】Timelineを使うと座標が中心に戻される問題の解決方法

# はじめに
この記事は[Hamster Output Advent Calendar 2024](https://qiita.com/advent-calendar/2024/game_hamster)の19日目の記事です！

Timelienを使ってAnimationの再生を行っている時に座標が中心に戻されることがあり、解決に少し時間がかかったのでメモ書きとして記事にしたいと思います。

# 結論
TrackOffsetsの設定をAutoに設定すると座標が戻されなくなる！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/6a7ce50f-c899-4b1f-482c-9fc8bc0e1ee2.png)

# 解決までに試したこと
座標移動がおかしい...という部分で最初はAnimatorの設定が変なのかなのと思い、設定を見直しました。

### ・AnimatorのApplyRootMotionのチェックを外す
Animation　座標が移動するという内容を検索すると大体この設定項目をoffにする内容がでてきます。今回の場合、元からoffになっていたので違いました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/802ae661-e606-8584-3a22-5031bf48ef49.png)

### ・AnimationのBakeIntoPose(X,Y,Z)の設定にチェックが入っていない
Animationクリップの設定にある、BakeIntoPoseも座標移動に関係があるみたいでチェックを入れると治る場合がある見たいです。ただ、今回の場合は関係なかったです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/886cde2c-1a6a-08c8-8e03-de493513f55f.png)

### ・TimelineのWrapModeの設定
といっても、WrapModeは座標というよりかはTimelineの最後の再生状態を維持したり、ループ再生したりなど座標に関連するものではなかったので違いました。

### ・TimelineのTrackOffsetsの設定
最初の結論にも書きましたが、犯人はコイツでした。

TrackOffsetsには3つの設定があり、それぞれが座標に関連する設定で

#### ・ApplyTransformOffsets
Animationの座標を基準に再生する(これがワープの原因だった)

#### ・ApplySceneOffsets
キャラクターの現在の座標を元に再生する(アニメーションでずれた座標と現在値が同じになる)

#### ・Auto
現在の座標に合わせてくれる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3588406/d4e87ac2-f756-1fa8-a845-db47d72b0da4.png)

# まとめ
犯人はTimelineのTrackOffsetだった
Flutterのチュートリアルを学んでみた(2)

# Flutterで始めよう！初めてのアプリ作り 🎨

今日はFlutterのチュートリアルを学んでみた(2)
まずは、簡単なアプリを作って、Flutterの基本を学んでいきます。

## はじめ

まず最初に、`lib/main.dart`というファイルの中身を全部消して、新しく書き直します。
これは、お絵かきで新しい紙を用意するようなものですね！

## コードを書いてみよう ✨

```dart
import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Welcome to Flutter',
      home: Scaffold(
        appBar: AppBar(
          title: Text('Welcome to Flutter'),
        ),
        body: Center(
          child: Text('Hello World'),
        ),
      ),
    );
  }
}
```

## どうしてこんなコードになるの？ 🤔

このコードは、レゴブロックを組み立てるように、少しずつパーツを組み合わせて作られています。
一つずつ見ていきましょう！

### 1. アプリの入り口 🚪
```dart
void main() => runApp(MyApp());
```
これはアプリの入り口です！お家の玄関みたいなものですね。
「=>」という矢印は、「これをやってね」という短い書き方です。

普通に書くとこんな感じ：
```dart
void main() {
  runApp(MyApp());
}
```

### 2. アプリの基本設計図 📝
```dart
class MyApp extends StatelessWidget {
```
これは「私のアプリはStatelessWidgetという種類のものです」と宣言しているんです。
StatelessWidgetは、変わらない飾り付けをするための道具箱みたいなものです。

### 3. アプリの見た目を作る 🎨
```dart
Widget build(BuildContext context) {
```
buildは「作る」という意味です。ここでアプリの見た目を作っていきます！

### 4. マテリアルデザインを使う 🎯
```dart
return MaterialApp(
```
GoogleさんがデザインしたきれいなUIパーツを使えるようにします。
スマホアプリらしい見た目になりますよ！

### 5. アプリの骨組みを作る 🏗
```dart
home: Scaffold(
```
Scaffoldは「足場」という意味です。アプリの基本的な構造を作ります。
お家を建てるときの骨組みみたいなものですね。

### 6. 上のバーを付ける 📱
```dart
appBar: AppBar(
  title: Text('Welcome to Flutter'),
),
```
アプリの上の部分に青いバーを付けて、その中に文字を表示します。
これがあると、本当のアプリみたいに見えますね！

### 7. 真ん中にメッセージを表示 📝
```dart
body: Center(
  child: Text('Hello World'),
),
```
画面の真ん中に「Hello World」という文字を表示します。
`Center`は「真ん中に置いてね」という意味です。

## 実行してみよう！ 🚀

このコードを実行すると、こんなアプリが出来上がります：
- 上に青いバーがある
- バーには「Welcome to Flutter」と書いてある
- 画面の真ん中に「Hello World」と表示される

## やってみよう！ 🌟

1. 「Hello World」の文字を自分の好きな言葉に変えてみよう
2. 上のバーの文字も変えてみよう
3. 違う色を試してみよう

## 大切なポイント 💡

- Flutterでは、すべてが「Widget（ウィジェット）」という部品でできています
- 部品を組み合わせて、自分の好きなアプリを作ることができます
- 少しずつ変更して、どう変わるか試してみるのが上達のコツです！




さぁ、アプリ作りの冒険を始めましょう！ 🚀
皆さんなら、きっと素敵なアプリが作れますよ！ 💪
エンジニアのためのアイデア出しメソッド

N/S 高等学校でプログラミング講師をしている doima_ です。
本記事は、[N高グループ・N中等部 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/nhighschool-njuniorhighschool) の23日目の記事です。

エンジニアとしてプロダクト制作に携わっていると、さまざまな困難にぶつかります。
難しい仕様決め、解決できないバグ、浮かばない実装方法など。。。

そんな困難を突破するのには、**発想力** がとても大事になります。
ポール・ヴァレリーという人の言葉に **「アイデアいっぱいの人は深刻化しない」** というものがあります。
悩んだときには、とにかく現状を打破するアイデアが大事になります。

エンジニアを含め、ものづくりに携わる人が困難にぶつかった時のアイデアの出し方をいくつか紹介します。

# アイデア出しのメソッド

## マンダラート法

マンダラートでは、3×3のマスの真ん中に、考えるべきテーマを書いて、そこから連想することをそれ以外のマスに書きます。
8つの全部マスが埋まったら、そのマスの内容を中心に持ってきた3×3のマスを8つ作ります。
これを埋めると、合計64個の新しいアイデアを考えることができます。

![スクリーンショット 2024-12-25 19.54.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3970568/06fa1f0c-1d66-d416-f676-6a2b583221eb.png)

こちらでは「メガネ」という言葉から8つの言葉を連想し、そこからさらに8つのワードを連想しています(実際にはこれを全マス分繰り返します)
大谷翔平が類似の手法で、目的を達成するのに利用したというエピソードがあります。

## NM法

NM法は、それに類似するものを想像し、テーマに強引にくっつけてみる手法です。
類推(アナロジー)や比喩(メタファー)を活用した考え方です。

![スクリーンショット 2024-12-25 19.54.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3970568/9027bba9-4a68-4ab2-573a-bd2bde9b7517.png)

こういった考えは、ライブラリの選定などでドンピシャなものがなくても、近しい役割を持ったものを引っ張り出してくる、などで使えるかもしれません。

## オズボーンのチェックリスト

オズボーンのチェックリストはテーマに対して、以下の9つの切り口で考え、アイデアを出していく手法です。

- 転用（例：他に使い道はないか？他に活躍できる分野・領域はないか？）
- 応用（例：他の業種・分野からアイデアを借りられないか？）
- 変更（例：形・機能を変えてみたらどうか？）
- 拡大（例：時間・頻度・高さ・長さ・強さなどを拡大してみたらどうか？）
- 縮小（例：携帯化できるか？短くできるか？軽くできるか？省略できるか？）
- 代用（例：他のもので代用できないか？）
- 置換（例：要素・パターン・配列・ペース・スケジュールなどを変えられないか？）
- 逆転（例：マイナスをプラスにできないか？役割を逆にできないか？）
- 結合（例：組み合わせてみたらどうか？ 目的や考えを結合できないか？ ）

例えば技術的な困難に直面したときに、あるテクニックを他に応用できないか考えてみたり、
別の手段を使ってみたり、などといったことは頻繁に行われることだと思いますが、
改めてこのリストにあたることによってアイデアが出てくるかもしれません。

# アイデアを出すプロセス

ここまでメソッドを紹介しましたが、アイデアが生まれるプロセスについて、ジェームス・W・ヤングは「アイデアのつくり方」で、以下のように説明しています。

1. 資料集め 
2. 資料の加工
3. 努力の放棄（無意識に任せる）
4. アイデアの誕生（ひらめき）
5. アイデアのチェック

紹介したものも含め、アイデア出しのメソッドに関しては、資料集め、資料の加工にあたるプロセスがほとんどです。
一番大事なことは努力の放棄、しかも **資料を集めて考え抜いた末の努力の放棄** です。

この無意識に任せるには **寝るのが一番** です！！

みなさんも、ひたすら考え抜いて考え抜いて、**そして寝ましょう！！！**


![hammock.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19246/32b11781-c2ee-46eb-6ee8-3d33e66d90f8.png)
※エンジニアが本当に必要だったもの
Elixirでraylibを使ってグラフィック描画してみる その4 〜 3DのBoxを描画 〜

# 前回
命令を拡張して円を描きました

https://qiita.com/t-yamanashi/items/d45f8a74cc16cd643834

# 今回
3DのBoxを描きます

### 仕様

- main
    - 画面を800x800
    - FPSは10に制限
    -  main_loopでループする

- main_loop
  - 3DのBoxの座標計算
  - 描画開始宣言 
  - drawで描画処理
  - 描画終了宣言
  - main_loopループ

- draw
  - カメラの位置
  - 3D開始
  - 3DのBox描画（座標はx,yを-10〜10まで動く　計算はmain_loop）
  - 11個のBoxを座標をランダムに表示(cubu関数)

# ソース

```elixir:lib/rayex_3d.ex
defmodule Rayex3d do
  alias Rayex.Structs, as: S
  use Rayex

  @color_white %S.Color{r: 245, g: 245, b: 245, a: 255}
  @color_gray %S.Color{r: 130, g: 130, b: 130, a: 255}

  def main() do
    init_window(800, 800, "window name")
    set_target_fps(10)
    main_loop(true, -10.0)
  end

  defp main_loop(true, c) do
    c = if c > 10, do: -10.0, else: c + 0.1

    begin_drawing()
    draw(c)
    end_drawing()
    main_loop(!window_should_close(), c)
  end

  defp main_loop(_, _), do: nil

  defp draw(c) do
    # clear_background(@color_white)

    camera = %S.Camera3D{
      position: %S.Vector3{x: 10.0, y: 10.0, z: 10.0},
      target: %S.Vector3{x: 0.0, y: 0.0, z: 0.0},
      up: %S.Vector3{x: 0.0, y: 1.0, z: 0.0},
      fovy: 45.0,
      projection: 0
    }

    update_camera(camera, 4)
    cube_position = %S.Vector3{x: c, y: c, z: 1.0}
    begin_mode_3d(camera)
    draw_cube(cube_position, 0.1, 0.1, 0.1, @color_gray)

    1..10
    |> Enum.each(fn _ ->
      cube()
    end)

    draw_grid(100, 1.0)
    end_mode_3d()
  end

  def cube() do
    x = Enum.random(-100..100) * 0.1
    y = Enum.random(-100..100) * 0.1
    z = Enum.random(-100..100) * 0.1
    cube_position = %S.Vector3{x: x, y: y, z: z}
    draw_cube(cube_position, 0.1, 0.1, 0.1, @color_gray)
  end
end
```
# 実行
```sh
$ mix run --eval "Rayex3d.main()"
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/b00199ad-6452-cef7-0b35-eeaa1a9f4287.png)


`defp draw(c) do`　の

 `clear_background(@color_white)`を有効にすると1フレームごと画面がリセットします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/295814/3a015e57-402c-efd3-2f4e-97e1068d6d7a.png)
スプラッシュスクリーン を JavaScript で実装

# はじめに
本記事では、`JavaScript` を使用して、Web ページの読み込み時に表示される「**スプラッシュスクリーン**」を実装しています。

# スプラッシュスクリーンとは

スプラッシュスクリーンは、Web ページの読み込みが完了するまでの間、ユーザーに短いアニメーションやメッセージを表示する画面です。これにより、ユーザーに読み込み中のことを伝え、ストレスを軽減することができます。

# 実装


```html
<div id="splash-screen" style="height: 100vh; width: 100vw; position: fixed; z-index: 999; top: 0; bottom: 0; left: 0; right: 0; display: flex;  align-items: center; justify-content: center; background-color: #00aee2; overflow: hidden;">
    <div style="font-size: 4rem;">ロゴ等</div>
</div>
<script>
    const delay = (ms) => {
        return new Promise((resolve) => {
            setTimeout(resolve, ms)
        })
    };

    const hideSplashScreen = async () => {
        await delay(1900);
        document.getElementById('splash-screen').style.display = 'none';
    };
    hideSplashScreen();
</script>
```
1. `HTML`
   - `<div id="splash-screen">`: スプラッシュスクリーンの要素を定義します。
   - `height: 100vh; width: 100vw;`: 画面全体を覆うようにサイズを指定します。
2. `JavaScript`
   - `delay(ms)` 関数: 引数で指定されたミリ秒間、処理を一時停止する関数です。
   - `hideSplashScreen()` 関数: スプラッシュスクリーンの表示を非表示にします。
Aurora MySQL → Aurora Serverlessを検討してみた

この記事は、[Ateam LifeDesign Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ateam-life-design) の記事になります。

# はじめに

現在、[Aurora MySQL](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/Aurora.AuroraMySQL.Overview.html)を使用しており、毎年12月時点でリザーブドインスタンスを購入していました。

:::note warn
今後、リザーブドインスタンスのことを、`RI`と記載させていただきます。
:::

今年もRIを購入しようとしたとき、ふとチームで「Serverlessにしたらどうかな？」と声が上がりました。
`Serverless`に関して、何となく料金が安くなる？ぐらいしか理解できていなかったので、これを機に調査して、乗り換えるか検討をしてみました。

本記事では、Serverlessに乗り換えるかを検討した内容を記載させていただきます。

## 本記事の対象者
:::note
- Serverlessについて、ざっくり理解したい方
- Serverlessに乗り換えを検討している方
:::

## 解説していないこと
:::note alert
- Serverlessの構築手順
- 実際の運用例
:::

# 結論
最初に結論ですが、**今回は`Serverless`ではなく、`RI`を購入しました。**
「今回は」と記載したように、乗り換えを全て諦めたわけではないです！

ただ、なぜ`RI`を購入したかの理由を、以下に記載していきます。

# Aurora Serverless とは

その前にまずは、ざっくりと`Serverless`を解説いたします。

https://aws.amazon.com/jp/rds/aurora/serverless/

> Amazon Aurora のオンデマンドの自動スケーリング設定です。アプリケーションニーズに応じて、自動的に起動、シャットダウン、および容量をスケールアップまたはスケールダウンします。

記載の通り、`Serverless`では、自動的にスケーリングを行います。
これにより、需要に応じてリソースが動的に割り当てられ、高負荷時にもパフォーマンスが維持されます。一方、オンデマンドインスタンスを使用する場合、手動でインスタンスを追加しなければならないことがあります。容量が不足するとインスタンスを追加する必要があり、逆に容量が余っているときにはリソースを無駄にしてしまう可能性があります。

↑ 上記を見るだけだと、「お、料金安くなりそうだなぁ」と思いますよね。
次に料金を見ていきます。

# 料金

https://aws.amazon.com/jp/rds/aurora/pricing/

（※ Serverless v2の料金で見ていきます。）

|測定|リージョン|Aurora Standard（ACU時間あたり）|
| --- | --- | --- |
|Auroraキャパシティーユニット|アジアパシフィック（東京）|USD 0.15|

上記のようになります。
ここで、`ACU`という単位が出てきたので、調べてみます。

## ACU

https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/AuroraUserGuide/aurora-serverless-v2.how-it-works.html

Aurora Serverless v2 の単位は Aurora 容量単位 (ACU)になります。
各 ACU では、約 2 ギビバイト (GiB) のメモリに相当します。

となると、オンデマンドインスタンスと比較すると、以下の通りになります。

|オンデマンド|Serverless|
| --- | --- |
|db.t4g.medium(4GiB)|2ACU|
|db.r7g.large(16GiB)|8ACU|

なので、現在使用しているインスタンスと比較して、計算してみると良いかなと思います。

ここまでわかったら試算！と行きたいところですが、先ほど記載したように、Serverlessは、自動でスケーリングしてくれます。
なので、次はスケーリングに考慮していきます。

## スケーリング

オンデマンドインスタンスは、`db.t4g.medium`でいうと、常時4GiBを使用しています。
Serverlessは、常時ではなく、使用量によってスケーリングしてくれます。

では、どのようにスケーリングを想定していくかというと...。
こればかりは、実際に運用してみないとわかりませんでした。

:::note warn
Cloud Watchなどで、CPU利用率などをみて判断することは一定できますが、実際Serverlessが、どういう挙動でスケーリングするかは、調べてもわかりませんでした。
:::

ここでは、以下のように仮定しようと思います。

- 9:00 ~ 20:00の11時間は、営業時間に該当するため、`2ACU`とする
- 残りの時間は、`1ACU`とする

ここまで出せたら、いよいよ試算になります。

# 試算
オンデマンドとServerlessで、`db.t4g.medium`をもとに、それぞれ比較してみようと思います。

:::note warn
ストレージ使用量やI/Oも料金に含まれますが、インスタンスによって料金が変わる箇所ではないので、試算には含んでいません。
:::

## オンデマンド

```
RI：710 USD/年 = 約60 USD/月
```

## Serverless

```
(2ACU × 11時間 × 0.15USD) + (1ACU × 13時間 × 0.15USD) = 3.3USD + 1.95USD = 5.25USD/日

5.25USD/日 = 162.75 USD/月
```

月で比較すると、`約100 USD分`、Serverlessの方が高くなります。
1 USDを160円で計算すると、月で16,000円になります。

料金は高くなっていますが、Serverlessのメリットと比較しても、許容できる料金かなとは思いました。

# まとめ
ただ、まだわかっていないこともあります。

- Serverlessに移行する際の開発工数
- 今後の保守性

料金試算と上記あたりを事業と会話して、今回はRI購入という結論になりました。
RIは1年間の購入にしたので、この1年間でstaging等での検証をしていこうと思います。


# 最後に

今回は、`db.t4g.medium`で比較してみましたが、実際の運用しているサービスで比較する材料になっていただければ、幸いです。

最後までご覧いただき、ありがとうございました。
R6秋　応用情報　午後プログラミング2

# 応用情報のプログラミング問題
素数を列挙するアルゴリズムの実装です。ここでは、20以下の素数とします。
Cなので、関数で配列を直接返せないので、問題のものからいくつか変数を追加しています。

# 改良1
単純な方法だと計算量は$O(N^2)$でした。
素数の定義によって、2以上の自然数sについて、s自身を除くsの正の倍数uは、1とu以外にsも約数に含むので素数ではありません。この性質を利用したのが関数prime2です。

```C:prime2.c
#include <stdio.h>

int* prime2(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    int isPrime[21] = {0};

    int c = 2;
    int d = 2;
    int t;
    while(c <= N){
        isPrime[c] = 1;
        c++;
    }
    while(d <= N){
        if(isPrime[d] == 1){
            primes[i++] = d;
            t = d * d;
            while(t <= N){
                isPrime[t] = 0;
                t += d;
            }
        }
        d++;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int main() {
    int primes[20];
    int count;
    int* prime_list = prime2(20, primes, &count);

    // 素数のリストを表示
    for (int i = 0; i < count; i++) {
        printf("%d ", prime_list[i]);
    }
    printf("\n");

    return 0;
}
```
dが素数なら、次は```t = d * d;```が実行されます。```d = 2のときt = 4, d = 3のときt = 9```です。間の5,6,7,8のうち、5,7は素数だからいいとして、6,8については、d = 2のときFalseになるので非素数として記録されます。

当初、なぜ、```t = d + d;```ではないのか悩んだのですが、よく考えるとprime2は成り立つことがわかります。これにより、prime1よりも少ない計算量で済みます。
PHPの関数型ヒントで勝手にキャストされる

年末をゆるくお過ごしの皆様も、師走を身に染みて感じている皆様もこんにちは。
jof-fumiです。
この記事は、[よりそうアドベントカレンダー](https://qiita.com/advent-calendar/2024)の25日目の記事となります。


実はこの記事、さっき仕事中に見つけた事象をそのまま記事にしてみました。

---

## PHPの関数の`return`の型ヒント(`bool`)を指定すると、暗黙変換される


以下のような関数があります。  
この関数は、斎場の見学可否について、別システムから送られてくる値をコード値に変換するものです。

```php
    private function getKengakuTypeId(?string $value): bool
    {
        return match ($value) {
            null => 1,
            '可' => 2,
            '不可' => 3,
            '条件付き' => 4,
            default => 1,
        };
    }
```

この関数に `'可'` を渡しているはずなのに、データベースを見ると`1`が登録されるという事象が発生しました。

## 原因の特定
この原因は、以下の通りです：

1. match 関数は適切に 2 を返していた
1. 型ヒント : bool によって、返り値が boolean 型にキャストされていた
    - その結果、getKengakuTypeId は true を返していた
1. DB登録時に、さらに int 型にキャストされて 1 として登録された

つまり、match 関数の結果そのものには問題がなく、return の型ヒントによるキャストが原因でした。



# テスト
以下のユニットテストを書いていたのですが、これが全てパスしてしまいました。


```php
// tests/Unit/Test.php

namespace Tests\Unit;

use PHPUnit\Framework\TestCase;
use App\Models\Saijo;

class SaijoTest extends TestCase
{
    public function testGetKengakuTypeId()
    {
        $saijo = new Saijo();

        // '可' の場合
        $this->assertEquals(
            2,
            $saijo->getKengakuTypeId('可')
        );

        // '不可' の場合
        $this->assertEquals(
            3,
            $saijo->getKengakuTypeId('不可')
        );

        // '条件付き' の場合
        $this->assertEquals(
            4,
            $saijo->getKengakuTypeId('条件付き')
        );

        // null の場合
        $this->assertEquals(
            1,
            $saijo->getKengakuTypeId(null)
        );

        // その他の値の場合
        $this->assertEquals(
            1,
            $saijo->getKengakuTypeId('その他')
        );
    }
}
```
## なぜパスしてしまうのか？
これは、`assertEquals` を使用しているためです。

例えば、`true` と `2` は型が異なりますが、`assertEquals` では等しいと判断されます。
型も含めて厳密に検査したい場合は、`assertSame` を使用する必要があります。

以下の通りですね。
```bash
% php -r "var_dump(3 == true);"
bool(true)
% php -r "var_dump(3 === true);"
bool(false)
```

## 結論
assertEqualsは使うな。

以上、皆様もお気をつけください。
社内勉強会を定期的に開催するノウハウ

# 概要
社内勉強会は楽しい！
社内エンジニアの交流の場にもなるし、自分が関わっていないプロジェクトの話も聞けます

ただ、運営がとても大変です...

数年前に社内勉強会を3回ほど開催したのですが、関わっていたプロジェクトが忙しくなったこともあり、そこから開催できていませんでした

そこで勉強会の運用体制を整え、8月ごろから現在まで定期的に10回開催することができたので、そのノウハウをまとめます

***
***
***

# 2回先のスケジュールを押さえろ
勉強会の開催をする上で、一番ネックになるのがスケジュールです

「次の開催はいつにしよう....」とか「あの人の空いてる日を聞いてからにしよう...」とかごまごましていると、すぐ自分が忙しくなってスケジュールを立てられなくなります

また、直前にスケジュールを立てても来れる人が少なくなり、開催する意味が薄れます

色々試した結果、2回先のスケジュールを決めるのが一番良かったです
発表者も準備しやすく、直前でまごつきません

勉強会の最後で2回先の発表者を決めてしまうのもいいでしょう

![名称未設定ファイル.drawio (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/100503/dae69044-9ba4-2c64-7950-1ba877af41c6.png)

# 内職を許す
基本的にみんな忙しいです
できることなら、自分の業務を進めたいと考えています

色々な共有のためにも、
業務が忙しい人, そうでない人も、できれば一緒の空間にはいて欲しいです

参加者が多いことに越したことはありません

# リアルでやる
自分が開催する勉強会は、リモートでの開催を許していません
これは、単なるLT発表会になってしまうことを防ぐだけでなく、さまざまなコミュニケーションを行なって欲しいからです

発表者だけが喋る勉強会は非常に印象が薄くなります
みんなでああでもない、こうでもないと喋って思考を深めましょう

# 発表者は3人押さえとく
リリースや不具合調査など、エンジニアのスケジュールは突発的に押さえられる時があります
そういった時に発表者が少なくなりすぎないよう、3人は押さえておきましょう

また、自分はいつでも発表できるよう、ネタスライドをいくつかストックしています
「人が少なすぎるな」とか「今回は終わるのが早すぎるな」という時には積極的に自分が発表しましょう

# ハードルは低く
```
発表内容はなんでもオッケー
発表時間は2分以上
スライドなし可
```
としています

まずは発表をみんなに慣れてもらいましょう
参加しているんだぞという一体感が組織を強めます

# リマインドする
勉強会が近づいたらあらかじめ「勉強会が近づいてきたので、発表の準備をお願いします」とリマインドしましょう

発表者の一夜漬けをある程度ふせいでくれるはず...！

# 辛くなったらスケジューリングを依頼する
どうしても自分が動けない時があります
そういう時は誰かに頼んじゃいましょう

自分は一人でやろうとしすぎて頓挫しました

# 発表内容を実践したら、発表者に伝えにいく
発表で聞いた内容は、できれば自分で一回動かしてみましょう
発表した人も嬉しいはずです

こういった勉強会を通したコミュニケーションを続けていくことで、そこから次回の発表者になってくれたりします

***
***
***

# まとめ
社内勉強会を定期的に開催するのは結構きついです
自分が時間があるうちはいいのですが、忙しくなるとどうしても開催できません

社内で開催のノウハウをつけ、エンジニアみんなで文化にしていけるといいですね
Pythonの変数への代入について


# Pythonの変数への代入について

Pythonでは、**変数**を使ってデータをプログラム内で保存し、後で再利用できます。変数への代入について学んだ内容を以下に整理します。

---

## **1. 変数の代入とは？**
- **右側の値を左側の変数に保存する**操作です。
- 数学のイコール（=）の意味ではなく、「代入」という特別な意味を持ちます。

~~~python:例
a = "Hello World"
print(a)
~~~

~~~python:出力
Hello World
~~~

::: note info
ポイント: `a` を参照すると、メモリに保存された `"Hello World"` を呼び出すことができます。
:::

---

## **2. 変数を作ること（変数を宣言する/定義する）**
- **変数を宣言する**、または**変数を定義する**という表現を使います。
- 変数を使うことで、コードを簡潔にし、後から値を変更しやすくなります。

~~~python:例
greeting = "Hello"
print(greeting)

# 変数の値を変更
greeting = "Hi"
print(greeting)
~~~

~~~python:出力
Hello
Hi
~~~

::: note info
ポイント: 変数の値を変更しても、他のコードを大きく変更する必要がありません。
:::

---

## **3. 変数を利用した計算や連結**
- 変数は、計算や文字列の連結にも利用できます。

~~~python:例1:数値の計算
x = 5
y = 10
print(x + y)
~~~

~~~python:出力
15
~~~

~~~python:例2:文字列の連結
a = "Hello"
b = "World"
print(a + " " + b)
~~~

~~~python:出力
Hello World
~~~

---

::: note info
### VSCodeで変数名を一括で変更することができる
- **方法**:
  - 変更したい変数名を選択
  - **右クリック → シンボルの名前変更**を選択
  - すべての該当する変数名が一括で変更されます
:::
---

## **4. 変数の命名規則**

::: note info
### Pythonの変数を命名する際には、以下の規則に従う必要があります

1. **snake_case** を使う（例: `my_variable`）。
2. **文字から始める**必要がある（数字から始めることはできない）。
3. 変数名には、**文字**、**数字**、**アンダースコア**(_)のみを使用できる。
4. **大文字と小文字を区別する**（例: `Hello` と `hello` は別の変数）。
:::

~~~python:良い例
my_variable = 10
user_name = "Alice"
~~~

~~~python:悪い例
2variable = 10   # 数字で始めているためエラー
user-name = "Bob" # ハイフンは使用できないためエラー
~~~

---

## **5. 出力される流れ**
変数を出力するとき、Pythonは以下の流れで動作します：
1. **print** 文で変数が指定される。
2. Pythonは「変数名（例: `a`）が何だったかな？」とメモリを探す。
3. メモリに保存されている値（例: `"Hello World"`）を出力する。

~~~python:例
a = "Hello World"
print(a)
~~~

~~~python:出力
Hello World
~~~

---

## **6. 変数を使うメリット**
1. **再利用可能**:
   - 一度変数に値を代入すると、プログラム内で何度も利用できます。

2. **値を変更しやすい**:
   - 変数の値を変更するだけで、他のコードを変更せずに動作を調整可能です。

3. **コードが読みやすくなる**:
   - 何を表しているのか分かりやすい名前を使うことで、可読性が向上します。
Rust 属性風マクロRTA (最小構成の属性風マクロ)


こちらの記事は [Rustマクロ冬期講習アドベントカレンダー](https://qiita.com/advent-calendar/2024/rust-macro) 17日目の記事です！

> アドカレまとめ記事はこちら！: [Rustマクロ作成チートシート！](https://qiita.com/namn1125/items/d601d2cbbf2cc7b5d3dc)

属性風マクロはRustの手続きマクロの一種です。では作っていきます。

# 最小構成の属性風マクロ

ライブラリクレートを作成します。

```bash
cargo new --lib attr_macro
cd attr_macro
```

`Cargo.toml` を書き換えます。

```diff_toml:Cargo.toml
[package]
name = "attr_macro"
version = "0.1.0"
edition = "2021"

+[lib]
+proc-macro = true

[dependencies]
```

`src/lib.rs` を書き換えます。[関数風マクロの時](https://qiita.com/namn1125/items/fc5aa71690fcb5109cf0)と同様入力をそのまま出力してしまうことにします！

```rust:src/lib.rs
use proc_macro::TokenStream as S;

#[proc_macro_attribute]
pub fn a(_attr: S, item: S) -> S {
    item
}
```

動作確認します。

```rust:src/main.rs
use attr_macro::a;

#[a]
fn main() {
    println!("Hello, world!");
}
```

```bash
cargo run
```

無事にコンパイルされたところでタイマーストップ。

# まとめ・所感

記録は2分22秒ほどでした。マクロの引数について、開始前にメタとアイテムどちらが先に来るか確認しておくべきでしたね...deriveマクロではもう少し早い記録を狙いたいです！でわ
FlexMessageでテキストリンクを設定する方法

## 目的

FlexMessageにテキストリンクを仕込む方法を紹介します。

実際はテキストリンクに見えるように実装しているだけなので、要件に満たすか検討して使用してください。

FlexMessageSimulatorを使用して基本的に実装を行いますので、説明の中でboxにtextを置いて（追加して）などという日本語が登場します。Simulatorの（+）ボタンのことです。

## 直接リンクが書いている場合

下記の画像のようなイメージです

![スクリーンショット 2024-12-25 19.34.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734276/fa5a7f8e-f1fa-4695-82ed-9f819667a762.png)

```json
{
  "type": "bubble",
  "body": {
    "type": "box",
    "layout": "vertical",
    "contents": [
      {
        "type": "text",
        "text": "https://qiita.com/",
        "color": "#0000ee",
        "decoration": "underline",
        "action": {
          "type": "uri",
          "label": "https://qiita.com/",
          "uri": "https://qiita.com/"
        },
        "contents": []
      }
    ]
  }
}
```

### 実装方法
1. boxにtextを設置する
1. colorをリンクの青色にする
1. decorationでunderlineを指定して下線を入れる
1. actionをuriで設定する

以上です！

## 文章中の「こちら」のように仕込む方法

下記のようなイメージです

![スクリーンショット 2024-12-25 19.45.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3734276/5a67a121-d53e-a980-d1be-b5e3810ab0d5.png)

```json
{
  "type": "bubble",
  "body": {
    "type": "box",
    "layout": "vertical",
    "contents": [
      {
        "type": "text",
        "text": "コードを書いていると、つまづくこ",
        "contents": [],
        "wrap": true
      },
      {
        "type": "box",
        "layout": "vertical",
        "contents": [
          {
            "type": "text",
            "text": "とありますよね、そんな時は",
            "flex": 1
          },
          {
            "type": "text",
            "text": "こちら",
            "flex": 1,
            "position": "absolute",
            "offsetTop": "none",
            "offsetEnd": "4px",
            "action": {
              "type": "uri",
              "label": "action",
              "uri": "https://qiita.com/"
            },
            "color": "#0000ee",
            "decoration": "underline"
          }
        ],
        "position": "relative"
      },
      {
        "type": "box",
        "layout": "vertical",
        "contents": [
          {
            "type": "text",
            "text": "で検索をして解決しましょう！"
          }
        ]
      }
    ]
  }
}
```

### 制約
1. テキストリンクは改行ができない（文章に制限が生まれます）
1. 正攻法ではなくゴリ押しでの実装になるので端末による差分が発生する可能性あり

### 実装方法
1. 改行はboxで分割して実装する
1. リンクを仕込む行のBoxにtextを２つ設置する
1. absolute,またはflexを使用して適切な位置にテキストリンクを担当するtextを置く
1. テキストリンクを担当するtextには上で紹介した手順でテキストリンクにする
1. boxを追加し、あとは残りの文章を書いて完了になります

## まとめ

結構自由度の高いレイアウトでトーク画面にメッセージを送信できるので私は、FlexMessageが結構好きです。最初は分かりづらく感じていましたが、今後も色々な表現ができるように色々模索しようと思います。
is_expected 

### `is_expected`は`expect(subject)`として定義できる 綺麗に読める
`is_expected`は簡単に`expect(subject)`として定義され、より新しい`expect`ベースの構文を使って`rspec-expectations`を使っているときのために設計される

>`is_expected` is defined simply as `expect(subject)` and is designed for
  when you are using rspec-expectations with its newer expect-based syntax.

  https://rspec.info/features/3-12/rspec-core/subject/one-liner-syntax/#:~:text=%60is_expected%60%20is%20defined%20simply%20as%20%60expect(subject)%60%20and%20is%20designed%20for%0A%20%20when%20you%20are%20using%20rspec%2Dexpectations%20with%20its%20newer%20expect%2Dbased%20syntax

>- (void) is_expected

予期の対象にするために`expect`で`subject`を包む
>Wraps the subject in expect to make it the target of an expectation.

https://rspec.info/documentation/3.2/rspec-core/RSpec/Core/MemoizedHelpers.html#:~:text=(collapse)-,%2D%20(void)%20is_expected,subject%20in%20expect%20to%20make%20it%20the%20target%20of%20an%20expectation.,-%2D%20(void)%20should

>- (void) is_expected

もし`rspec-expectations`を使っているとき、これは唯一の仕事です。
期待の対象にするために`expect`で`subject`を包む。1行で綺麗に読めるように設計される
>Note: This only works if you are using rspec-expectations.
Wraps the subject in expect to make it the target of an expectation. Designed to read nicely for one-liners.

Examples:

```rb
describe [1, 2, 3] do
  it { is_expected.to be_an Array }
  it { is_expected.not_to include 4 }
end
```
```
Testing started at 19:53 ...
2 examples, 0 failures, 2 passed
```
https://rspec.info/documentation/3.2/rspec-core/RSpec/Core/MemoizedHelpers.html#:~:text=Instance%20Method%20Details-,%2D%20(void)%20is_expected,Array%20%7D%0A%20%20it%20%7B%20is_expected.not_to%20include%204%20%7D%0Aend,-See%20Also%3A
R6秋　応用情報　プログラミング

# 応用情報のプログラミング問題
素数を列挙するアルゴリズムの実装です。ここでは、20以下の素数とします。
Cなので、関数で配列を直接返せないので、問題のものからいくつか変数を追加しています。

# 単純な方法
```C: prime1.c
#include <stdio.h>

int* prime1(int N, int primes[], int* count){
    int i = 0;  // primesの末尾インデックス
    int isPrime; // 1:True(prime), 0:False(not prime)

    int d = 2;
    int t;
    while(d <= N){
        isPrime = 1; // True, 素数と仮定
        t = 2;
        while(t < d){
            if(d % t == 0){
                isPrime = 0; // False
            }
            t++;
        }
        if(isPrime == 1){
            primes[i++] = d;
        }
        d++;
    }

    *count = i;  // 素数の個数をカウント
    return primes;
}

int main() {
    int primes[20];
    int count;
    int* prime_list = prime1(20, primes, &count);

    // 素数のリストを表示
    for (int i = 0; i < count; i++) {
        printf("%d ", prime_list[i]);
    }
    printf("\n");

    return 0;
}
```
実行結果
```
2 3 5 7 11 13 17 19 
```

外側のwhile: d = 2 ~ N
内側のwhile: d = 2のとき0回, d = 3のとき1回, d = 4のとき2回,...,d = N-1のときN-3回
-> $0 + 1 + 2 + ... + N-3 = \frac{(N-3)(N-2)}{2} = N^2-5N+6 $
-> $O(N^2)$

関数prime1の時間計算量は$O(N^2)$となります。
囚人のジレンマ （矛盾編 - ナッシュ均衡）｜文章題で身に付くプログラミング思考入門️（24/25）

## はじめに

[前回](https://qiita.com/yuki_thewaggle/items/3c9ca605f723ceaac6be)の続きです。
囚人のジレンマについてパレート最適を考えた時に湧いてきた疑問

「二人とも刑罰を受けることが、本当に一番良い選択肢だと言えるのだろうか？」

について、ナッシュ均衡の観点を紹介します。

『文章題で身に付くプログラミング思考入門️』は、日常や文章問題からプログラミング思考を身に付けていく、簡単で身近で、あなたをちょっと輝かせてくれるシリーズです。

## これまでのまとめ

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

## 対象者
- プログラミングの考え方を学びたい人
- プログラミングに挫折したことのある人
- 論理的思考を鍛えたい人
- 文系の人
- エンジニアの思考を理解したい人

## 振り返り

### 囚人のジレンマとは
```
2人の囚人が別々に隔離されて尋問を受けている。
両者が「協力（黙秘）」すれば、2人とも軽い刑罰。
一方が「裏切り（自白）」、もう一方が「協力（黙秘）」すると、裏切った囚人は釈放、黙秘した囚人は重い刑罰。
両者が「裏切り（自白）」なら、中程度の刑罰。
```

### 囚人のジレンマのパレート最適（全体最適）
お互いを信じ、両者とも協力（黙秘）して、軽い刑罰を受けること

### パレート最適とは
- 他の誰かの利益を損なうことなく、誰かの状況を改善できない状態
- 全員が得をする選択肢がこれ以上ない、全体として最適な状態


## ナッシュ均衡とは

さて、本題です。

囚人のジレンマに戻って考えた時、全体のことを考えたら確かに黙秘するのが一番点数が良かったわけですが、囚人本人にとってみれば刑罰を受けない選択肢が他にあるわけですから、そりゃあ釈放された方が嬉しいですよね。

**大事な前提として、囚人のジレンマでは、各プレーヤーが自分の利益を最大化する行動を取ります。**

これがナッシュ均衡です。

ナッシュ均衡とは、ゲームのプレイヤー全員が自分の行動を最適化した状態を指します。
自分が他の選択肢を選んだとしても、全員が現状より良くなる選択肢がない状態です。

囚人は、「協力（黙秘）」か「裏切り（自白）」のどちらかを選択することができます。

それぞれの選択肢によってどのような点数を得られるのか、表にしてみましょう。

|自分が＼相手が|相手が協力（黙秘）|相手が裏切り（自白）|
|---|---|---|
|協力（黙秘）|軽い刑罰 **3点**|重い刑罰 **0点**|
|裏切り（自白）|釈放 **5点**|中程度の刑罰 **1点**|

つまり、
- 自分が協力すると
    - 相手が裏切った場合に 0点（最大の損） を受けるリスクがある
- 自分が裏切ると
    - 相手が協力した場合に 5点（最大の利益） を得られるし、相手が裏切っても 1点（軽い損） を得る

というところで、裏切る選択肢を取る方が合理的なわけです。

相手も、自分と同じように、本人にとって最も合理的な選択肢をとってくることがわかっているわけですから、相手も裏切ってくるでしょう。

結論として、
- 自分も相手も「裏切る」選択をすることで、中程度の刑罰（1点） に落ち着く
- どちらも戦略を変える理由がなくなる
    - 「協力する」選択をしたところで相手は「裏切る」のが合理的なので裏切ってくる。であれば、自分にとって「協力する」理由がない

**このように、自分が他の選択肢を選んだとしても、全員が現状より良くなる選択肢がない状態がナッシュ均衡です。**

囚人のジレンマの場合は、個人の合理性が全体の非合理性を引き起こします。

 
こうして見てみると、自分にとっては裏切りが合理的です。
一方、相手にとっても点数の条件は一緒なので、相手にとっても裏切りが合理的な選択肢です。

**要するに、両者とも裏切り（自白）を選ぶことが、ナッシュ均衡です。**

## 囚人のジレンマからわかること

繰り返す囚人のジレンマで、どのような戦略が強かったかを[こちらの記事](https://qiita.com/yuki_thewaggle/items/eb4ad0ee4c6dafb4126c)から思い出してみましょう。

> しっぺ返し（Tit-for-Tat） が一番強かったそうです。
> 
> - まずは友好的関係を構築する
> - 相手が裏切ってきたら、こちらも許さないという態度をはっきりとる
> - 相手が歩み寄ってきたら、こちらも歩み寄る。根に持たない
> 
> つまり、状況に応じて柔軟に対応できる方が強かったわけです。

ここからわかるのは、信頼とコミュニケーションの重要性です。

## まとめ

囚人のジレンマで全員が生き残るには、お互いに相手が裏切らないという信頼関係が必要です。
そして、そもそもこれは、繰り返されることが前提とされたコミュニケーションなのです。

たった一回だけの相手ならば、裏切った方がお得なわけです。
ですが、現実の人間関係は、コミュニケーションの繰り返しによって生まれます。

まずは友好的に歩み寄る。
一度うまくいかなくても、許し、許され、関係性を作っていこうとする前向きさが、お互いの利益を生むのです。

そして何より、適応するものが生き残るのです。
そのために、柔軟であろうとしましょう。

これが、囚人のジレンマからわかる、大切なことです。

## 最後に
ここまで読んでくださってありがとうございます！
よかったら「いいね」をください。続ける励みになります！
オームの法則について学ぶ

オームの法則とは、電気回路の振る舞いを記述する法則。

具体的には、電圧(V)、電流(I)、抵抗(R)の関係を表す法則で以下の式である。

```
V = I * R
```

V は電圧（単位：ボルト[V]）
I は電流（単位：アンペア[A]）
R は抵抗（単位：オーム[Ω]）

これらを計算せずに過電流や過電圧を流すと、電気回路を壊してしまうことになる。
ReactによるTodoアプリ個人開発しての気づき

# はじめに
　今回、よくある小規模なTodoアプリ開発をReactで行いました。そこで学んだことを中心に投稿させていただきます。
　こちらの記事を読んでいただいた方の何かしらの気づきのきっかけになれば幸いです。

# 行ったこと
* Firebase、Supabase、GitHub Actions(CI/CD)、Jest、vitestでの実装。
* 最初からAIを頼らず、脳負荷を意識し、まずは考え調べてみて自分なりの実装を行いエラー内容を見てまた調べることを心掛けました。それでも作業が進まない時はAIに助けてもらい、実装内容が納得いくまで対話し公式ドキュメントも確認するようにしました。

https://qiita.com/shisshi_engineer/items/edcb45246dcefaa56091

* CI実装する際、Jestの互換問題をどうしても解決することができず、今回vitestで対応しました。またテストコードはドキュメントだけでは解決できずAIに手伝ってもらいました。そもそもCI/CDとは？からのスタートでした。
```
  ReferenceError: require is not defined
```
上記のエラーは、JestがテストファイルをESM (ECMAScript Modules) として正しく認識していない場合に発生するようで、今回jest、babelなどの設定周り、テストコードの記述を調整してもなかなか解決できそうになかったためvitestで対応しました。

# 学んだこと
* ドキュメントは丁寧に解説しているわけではなく、また翻訳機能の性能によって解釈の仕方が異なってくるため、難しいことが書いてある内容だとドキュメントだけで理解するのは難しく、その際はAIに手伝ってもらいました。が、ドキュメントを読む癖が着くことで、問題打開能力が付く気がします。これからも真っ先にドキュメントを読もうと思います。また、ドキュメント以外でもエンジニア先輩方々の過去のQiita投稿記事もとても参考になりました。
* 今回初めてCursor使ってみました。AIとの対話はGPTより、Cursorの方がコード貼り付けが容易で、回答の仕方もエンジニア向けな気がして対話の時短になると思いました。ただ上記添付のとおりAIを使うタイミングはとても重要だと思っています。
* 今までherokuにしかデプロイしたことがなく、今回初めてFirebaseを使用しましたが比較的簡単だった印象です。
* 機能実装することより、環境開発、データベース設定、デプロイ設定、CI/CD設定などの方が実施する回数が圧倒的に少なく苦手意識が強い方が多いのではないでしょうか？そこを解決するには数多くアプリ開発をすることが必要で、大きなアプリを開発するより小さい規模のアプリを数多く作ることでそれらの経験値を沢山得れると思います。小さなアプリの個人開発の重要性を理解することができました。
* 前回も同じような投稿をしましたがUdemyだけで終了するより個人開発をした方が圧倒的に学びが多くなります。

# 終わりに
これからも個人開発を継続して、壁に当たることでスキル向上を計っていきます。
そして、最新スキルのキャッチアップをしている現役エンジニアの方が一緒に伴走してくれるJISOUの環境に感謝しています。

# JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてくださ！
:point_down::point_down::point_down:

https://projisou.jp