OmniAICreator/Qiita-1.07M huggingface dataset:
波形可視化と解析信号の視覚表現

とりあえずまずは使ってみてや。👋
別タブで開いてる音を解析信号にして可視化します

https://summer498.github.io/analytic-signal/

<img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2676125/e8ec7047-8f68-4911-a07c-739c062dd6a8.png">

<img width="45%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2676125/65414c90-3fda-4616-b2c2-9e9543be20ba.png">

このプロジェクトでは、ブラウザ上で入力音声の波形を取得し、  
その解析信号（analytic signal）を生成して、複素数平面上に可視化します。

## 解析信号（Analytic Signal）

解析信号とは、元の実数信号から得られる複素数値信号であり、  
時間領域信号の振幅包絡や瞬時位相を取り出すために使われます。

ある実数信号 $x(t)$ に対して、その解析信号 $z(t)$ は以下の形で定義されます：

$$
z(t) = x(t) + i \cdot \mathcal{H}[x(t)]
$$

ここで $\mathcal{H}[x(t)]$ は ヒルベルト変換（Hilbert Transform）です。

解析信号の性質：

- 実部： 元の信号そのもの
- 虚部： 元信号のヒルベルト変換（＝90度位相シフトされた信号）
- 絶対値： 瞬時振幅 $|z(t)|$
- 偏角（角度）： 瞬時位相 $\arg z(t)$

## ヒルベルト変換

ヒルベルト変換は、信号に対してすべての周波数成分を $-90^\circ$ 位相シフトさせる変換です。  
時間領域での畳み込みとしても定義されますが、実際には周波数領域で効率よく行うのが一般的です。

### 周波数領域での定義：

1. 信号 $x(t)$ をフーリエ変換して $X(f)$ を得る
2. 周波数領域で以下のようにフィルタをかける：

$$
H(f) =
\begin{cases}
1 & (f = 0) \\\\
2 & (f > 0) \\\\
0 & (f < 0)
\end{cases}
$$

3. $X(f) \cdot H(f)$ に対して逆フーリエ変換することで、$z(t)$ を得る

## 何が見えているのか

- 正弦波 → 真円
- 複数の周波数 → 複雑なスパイラル構造
- 振幅変調（AM） → 回転半径が変化
- 周波数変調（FM） → 回転速度が変化

これにより、時間波形では見えなかった信号の構造を、
幾何学的な軌跡として可視化できます。

## 実装上のポイント

- `getDisplayMedia({ audio: true })` によって音声入力を取得
- `AnalyserNode.getFloatTimeDomainData()` によって時間波形を取得
- 外部ライブラリ（または自作関数）で **FFT → ヒルベルト変換 → IFFT**
- キャンバス上で **Re vs. Im** を複素平面上に描画

## 📦 参考文献・資料

- [Analytic signal - Wikipedia](https://en.wikipedia.org/wiki/Analytic_signal)
- [Hilbert transform - Wikipedia](https://en.wikipedia.org/wiki/Hilbert_transform)
- [ヒルベルト変換 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%92%E3%83%AB%E3%83%99%E3%83%AB%E3%83%88%E5%A4%89%E6%8F%9B)
- @yamadasuzaku, [ヒルベルト変換の意味を理解する : Analytic signal、関数の偶奇性、負の周波数の意味](https://qiita.com/yamadasuzaku/items/1c707dbda651a1811206)
- [https://www.onosokki.co.jp/HP-WK/eMM_back/emm180.pdf](https://www.onosokki.co.jp/HP-WK/eMM_back/emm180.pdf)
音声認識　CI-03T　声源定位

#### 初めに
M5Stack Unit ASR に内蔵されている基板（CI-03T）は 単マイク対応品ですがMIC2の端子も引き出されているので2マイクで声源定位の動作確認を行いました。

#### プログラム作成
40㎜間隔でマイクを取り付けたボードを作成し基板に接続します。
AEC用にスピーカ―出力とMIC2間に抵抗が繋がっていますが影響なしと勝手に判断し、そのままにしておきます。（外すのが面倒なので・・・）
まず中国語版で確認し その後、日本語に置換えましたが出力される音声が不明瞭なので英語版としました。　
話すスピードを遅く設定して分かりやすくしています。
2秒の遅延を入れているので少し間をおいて方角を言います。

#### 動作確認
声の方角を10度刻みで音声報知してくれます。
まずまずだと思いますが、何に使うかですね？
（人形の首を声の方向に向かせる等・・・）
#### 動作確認動画
https://youtu.be/YX3e1p9o5AA
#### メーカーサイト
https://help.aimachip.com/docs/question/question-1fu592ijihm6l
https://help.aimachip.com/docs/tutorials-and-sample-firmware/tutorials-and-sample-firmware-1ga9sd31mu101
#### 音声認識モジュールの入手先　
CI-03T （2㎜ → 2.54㎜ピッチ変換基板もあり）
https://www.aitendo.com/product-list/1259
ASRPRO (ASRPRO-CORE 4M も入手できます) 
https://ja.aliexpress.com/w/wholesale-ASRPRO.html?spm=a2g0o.home.search.0
Googleスプレッドシートを型付きデータベースにすると仕事が捗る - NPMモジュール紹介

## 中くらいのデータベース欲しい問題

バッチ処理的なプログラムを作ると、データの入出力と永続化をどうするか考えなければなりません。

シンプルで小規模であればテキストファイル(CSV)を使い、複雑で大規模になるとデータベースを用意しますが、その間の「中くらいのプロジェクト」で頭を悩ませてきました。

テキストファイルだと物足りず、少し複雑になるたびプログラム記述が増えるが、わざわざデータベースを用意するほどでもない、みたいなケースです。私はどうもそういう機会が多いです。

## Googleスプレッドシートをデータベースにする

そこでGoogleスプレッドシートを活用できないか考え、こんなNPMモジュールを開発しました。

- [node-google-spreadsheet-tables 日本語README](https://github.com/ideamans/node-google-spreadsheet-tables/blob/main/README.ja.md)

モジュールをインストールすると、

```bash
pnpm add google-spreadsheet-tables
```

こんな感じで名前、年齢、性別、勤務先の列からなるスプレッドシートを入出力可能なデータベースとして利用し、Zodスキーマで型安全なプログラミングができます。

```typescript
const { doc } = useWorksheetWithServiceAccountFile('スプレッドシートID', './service-account.json')

const userSchema = z.object({
  名前: z.string(),
  年齢: z.coerce.number(),
  性別: z.enum(['男性', '女性', 'その他']),
  勤務先: z.string().optional(),
})

const { get, patch, snapshot } = await useDocumentsSheet(
  doc,
  'ユーザー',
  userSchema
)

const allUsers = await snapshot()
const aUser = await get(2)
await patch(2, { 年齢: 31, 勤務先: 'CompanyA' })

```

Googleスプレッドシートを使うとなると、OAuth2でアクセストークンを取得して…と遠回りな印象ですが、サービスアカウントとJSON鍵ファイルでも可能です。

## 仕事が捗る！

Googleスプレッドシートを直接、簡易データベースにしてみると開発および作業体験が劇的に向上しました。

### データが見やすい

幅を調整したり、フィルタをかけたりと自由にレイアウトや見た目を調整できるのでデータが見やすいです。

### 入力・調整・加工がしやすい

データを手作業で入力したり、ちょっと修正したり、カラムを追加して関数などで少し加工したりがすぐにできます。

### 分散処理できる

ローカルファイルだと分散処理が難しいですが、Googleスプレッドシートであれば簡単です。

### 前工程・後工程とシームレスに繋がる

何かのバッチ処理が単独で業務として成立することはほとんどなく、ふつうは前工程・後工程のある業務の一部です。

今まではバッチ処理用のCSVに変換したり、データベースに取り込む作業が発生していました。そして元データに修正が入ったりすると、それもマージしなければいけなかったり…

受け取ったデータをそのまま処理に回し、できあがったデータをそのまま次に渡せるのが最大のメリットでした。

## どんどん使っていきたい

今までバッチ処理のアイデアがあっても、データ管理どうするかな…と億劫になることがありましたが、Googleスプレッドシートを直接データベースにするアイデアでその心配がなくなりました。

今度からは小規模なバッチ処理案件でも、積極的に使っていきたいなと思っています。
XIAO ESP32C6+SSD1306、高さ3の線を書いて遊ぶ(例題)


目的
----

点に分解して線を書く

アイディアの基本は、分割した単位に達するとYを1UPする



結果
----

![o_coq890.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/35a4b05d-a39a-4478-bbea-3942dd78626c.jpeg)



プログラム
----

```c++


//OLED_SSD1331_line_0_XIAO_ESP32C6


//ヘッダーファイル
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128     // OLED display width, in pixels
#define SCREEN_HEIGHT 64     // OLED display height, in pixels
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(D9, D10);  //XIAO ESP32C6+SSD1306
  //Wire.begin(D10,D9); //XIAO ESP32C6+GROVE

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

}  //setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.clearDisplay();

  int o = (60 / 3);
  int p = o;
  int y = 0;

  for (int x = 0; x < 60; x++) {
    if (x > p) {
      y = y + 1;
      p = p + o;
      display.display();
      delay(750);
    }  //if
    display.drawPixel(x, y, WHITE);
  }  //for

  // 描画バッファの内容を画面に表示
  display.display();

  delay(5000);  //5秒待つ

}  //loop



```
ツーリングどこ行く？を解決！７県の観光スポットまとめました！

# ツーリングに行こう
こんにちはプログラミング超初心者のしらせです
ツーリングどこ行くか困っていませんか？私はバイクに乗るのですが、毎回行く場所に困ります、、、。そんな悩みを解決するためのLINE Botを作りました！対象は７県に絞りました（私の会社が７県に展開しているため）愛知、岐阜、三重、滋賀、静岡、山梨、神奈川です
初めてのことに挑戦！
## 目次
<ul>
<li><a href="#feature">使用ツール</a></li>
<li><a href="#how-to-use">完成品</a></li>
<li><a href="#reviews">作成開始</a></li>
<li><a href="#reviews">やりたいと思ったこと</a></li>
<li><a href="#reviews">最後に</a></li>
</ul>
<h2 id="feature">使用ツール</h2>
Googleスプレッドシート、LINE Bot　LINE公式アカウント

<h2 id="feature">完成品</h2>

https://x.com/Ic8ICt6crO343/status/1915404259841155249

全体の構成図
![スクリーンショット (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/ddd4e184-9196-4ed7-a9c6-3814c1e6f4c2.png)

<h2 id="feature">作成開始</h2>
1スプレッドシートを作成し県名（A)、おすすめスポット（B)のURLを記載した。

![スクリーンショット (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/7f2459e0-3d35-4758-86ea-e519715481f1.png)

LINE公式アカウントを作成する。

LINE Official Account Managerにアクセスします
アカウントリストでさきほど作ったアカウントを選択します
「同意」を求められるので、「同意」をクリックします
画面右上の「設定」ボタンをクリックします
画面左の「Messaging API」をクリックします
「Messaging APIを利用する」をクリックします
プロバイダーを作成で「自分が設定する名前」を入力し「同意する」>「OK」>「OK」

Makeのアプリを起動し（会員登録必須）Scenariosを選択し　+create a new scenarioをクリックする（PCだと右上の紫+）
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/b2e586a3-fa43-4fa3-b06e-a105565f3603.png)


LINEのモジュールを選択→WhatchEventsを起動しLINE Developersを起動しチャネルアクセストークンを獲得する。事前にチャンネルを作成したアイコンを選択する→Message API設定の欄を下にスクロール→チャネルアクセストークンをコピー
![スクリーンショット (9).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/53b8ea71-fc89-4fe6-91dc-2893eea9335e.png)

チャネルアクセストークンをMakeにもどり新たなLINEのモジュールを追加send a reply messageを選択しChnnel A㏄ess Tokenに先ほどコピーしたチャネルを繋げた!
WebhookのURLをコピー（青の線で隠している部分）しLINE Developersに戻りMessage API設定の欄にWebhookの設定がるので編集ボタンをクリックし、先ほどのURLをぺーストする→更新Webhook利用ボタンを緑にする![スクリーンショット (5).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/2d715a23-1a02-4ef2-b9b6-bf0325fe8e79.png)![スクリーンショット (7).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/e05f2e30-331f-4fc3-9c94-f1021b165a44.png)
Goole Sheetのモジュールを追加しA,B,Cの項目が出るように設定しました（スプレッドシートで設定した項目）
![スクリーンショット (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/aa751b53-486c-44ae-9dd6-6bd3b1914fc9.png)
最後にMakeのRun　onceをクリックし、試行できます永続化する場合は赤線で囲ってあるところをクリック

![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4051643/2e15a6a9-9dc2-4acc-84f1-e2bba23484b4.png)

<h2 id="feature">やりたいと思ったこと</h2>

現在地から往復100キロまでにあるスポットを紹介する
47都道府県すべて検索できる。
日帰り、宿泊ルートで分ける
行く日にちの天気がわかる
<h2 id="feature">最後に</h2>
初めてながらに色々サイトを調べたり、模索しました。
実力不足が良くわかりました。まだまだ頑張るぞ！
時間が欲しいです　あとからこんなことできたらいいなと思い、結局やり方がわからずじまい
もっと効率的に動きたいです

拝見いただきありがとうございました。しらせでした。
XIAO ESP32C6+SSD1306、水平の線を書いて遊ぶ(例題)


結果
----

![o_coq891.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/26f1e72b-1972-4fa7-a97e-2915de8b7408.jpeg)


プログラム
----

```c++



//OLED_SSD1331_line_0_XIAO_ESP32C6


//ヘッダーファイル
#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>


//定義
#define SCREEN_WIDTH 128     // OLED display width, in pixels
#define SCREEN_HEIGHT 64     // OLED display height, in pixels
#define OLED_RESET -1        // Reset pin # (or -1 if sharing Arduino reset pin)
#define SCREEN_ADDRESS 0x3C  ///< See datasheet for Address; 0x3D for 128x64, 0x3C for 128x32
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);


//初期化
void setup() {

  //I2Cの初期化
  Wire.begin(D9, D10);  //XIAO ESP32C6+SSD1306
  //Wire.begin(D10,D9); //XIAO ESP32C6+GROVE

  // I2Cアドレスは使用するディスプレイに合わせて変更する
  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);

}  //setup


//メインループ
void loop() {

  // 画面表示をクリア
  display.clearDisplay();


  for (int x = 0; x < 60; x++) {
    display.drawPixel(x, 0, WHITE);
  }

  // 描画バッファの内容を画面に表示
  display.display();


  delay(3000);  //3秒待つ

}  //loop



```
Docker コンテナ内での Ruby バージョン不一致エラーの解決方法

## はじめに
Docker を使用して Ruby on Rails アプリケーションを開発していると、よく遭遇するエラーの一つが「Ruby のバージョン不一致」に関する問題です。特に docker-compose up --build や bundle install の際に、Gemfile に指定された Ruby バージョンと Docker コンテナ内で実行されている Ruby バージョンが異なると、エラーが発生します。この記事では、このエラーを解決する方法をステップバイステップで解説します。

## エラーの例
例えば、次のようなエラーメッセージが表示されることがあります

```
Your Ruby version is 3.2.8, but your Gemfile specified 3.4.3
```
このエラーメッセージが示しているのは、Gemfile に記載された Ruby バージョンが現在の環境と異なっている ということです。これを解決するためには、Ruby のバージョンを一致させる必要があります。
## 解決方法

### 1.Gemfile の Ruby バージョンを修正
まず最初に、Gemfile 内で指定している Ruby バージョンを、コンテナで使用しているバージョンに合わせる必要があります。エラーメッセージに ruby "3.2.8" とあった場合、Gemfile の内容を次のように変更します。

修正前：
```
ruby "3.4.3"
```
修正後：
```
ruby "3.2.8"
```

### 2.bundle install の実行
```
bundle install
```
### 3. Docker コンテナを再ビルド
```
docker-compose up --build
```

## まとめ
このエラーは、Gemfile に記載された Ruby バージョンと Docker コンテナ内で実行される Ruby バージョンが異なることによって発生します。バージョンを一致させることで解決できるので、Gemfile を修正して、bundle install を再実行し、Docker コンテナを再ビルドすることで問題が解消されます。
(途中)空間図形「(その4/5)2025愛知公立高校入試図形 最後の問題3(3)」様を参考にsympyの空間の座標変換の計算で。

・(その5/5)作成中。積分は未です。

:::note info
[(その1/5) sympyとFreeCADで](https://qiita.com/mrrclb48z/items/f03cfc6a7b9375fc4b63)
[(その2/5) 三角柱で](https://qiita.com/mrrclb48z/items/ce12576a952ef9423795)
[(その3/5) ３つの球の交点計算で](https://qiita.com/mrrclb48z/items/4a292fbbba5a4deab23c)
(その4/5) 本ページ
[(その5/5) 作成中]()
:::

・作図はありません。
・**空間の座標変換の計算後のz座標を四角錐の高さにしています。**
　**ここまできたら、みんな同じに見えてきました。**
　変換後の全座標で体積を計算した方がよかったカモ。

・次は(その1/5)を見て下さい。
　オリジナル
　sympyのweb上での実行方法
　
# sympyで
#### ver0.1 
```python
from sympy import *
def get_plane_to_xy_transform(A: Point3D, B: Point3D, C: Point3D):
    # ベクトル AB, AC を計算
    u = Matrix(B - A)
    v = Matrix(C - A)

    # 法線ベクトル（平面の法線）
    n = u.cross(v)
    n_unit = n / n.norm()

    # Z軸ベクトル
    z_axis = Matrix([0, 0, 1])

    # 回転軸（n と Z軸の外積）
    axis = n_unit.cross(z_axis)
    axis_norm = axis.norm()

    # 回転角
    cos_theta = n_unit.dot(z_axis)
    theta = acos(cos_theta)

    # Rodriguesの回転行列
    def rotation_matrix(axis, theta):
        axis = axis / axis.norm()
        x, y, z = axis
        c = cos(theta)
        s = sin(theta)
        C = 1 - c
        return Matrix([
            [x*x*C + c,   x*y*C - z*s, x*z*C + y*s],
            [y*x*C + z*s, y*y*C + c,   y*z*C - x*s],
            [z*x*C - y*s, z*y*C + x*s, z*z*C + c  ]
        ])

    # 回転行列（軸がゼロ＝すでにXY平面の場合は単位行列）
    R = eye(3) if axis_norm == 0 else rotation_matrix(axis, theta)

    # 平行移動ベクトル（点Aを原点へ）
    t = -R * Matrix(A)

    # 同次変換行列（4x4）
    T = R.row_join(t)
    T = T.col_join(Matrix([[0, 0, 0, 1]]))

    return T

# === 使用例 ===
if __name__ == "__main__":
    OA,AB=12,6
    d=AB*Rational(1,2)
    h=sqrt(OA**2-((d*sqrt(2))**2))   
    O=Point(0,0,0)
    A,B,C,D=map(Point,[(-d,-d,-h),(d,-d,-h),(d,d,-h),(-d,d,-h)]) 
    E=O+Rational(2,3)*(A-O)
    F=O+Rational(1,2)*(B-O)
    G=O+Rational(1,2)*(C-O)
    H=O+Rational(2,3)*(D-O)
    print("#",  Rational(1,3)*(get_plane_to_xy_transform(E,F,G)*Matrix([0, 0, 0, 1]))[2] \
              *( Triangle(sss=(E.distance(F),F.distance(H),H.distance(E))).area
                +Triangle(sss=(F.distance(G),G.distance(H),H.distance(F))).area
              ))
# 7*sqrt(14)
```

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
#### Qiita 内

https://qiita.com/mrrclb48z/items/07917603fa3958775f1c
多分世界で初めてSPIRAL Ver.1でローコードズンドコチェックを作ってみた。

## はじめに：ズンドコチェックとは？
改めて記事を検索してると、初回投稿はなんともう10年近くも前なんですね。
2020年前後で激アツだった「ズンドコチェック」なるものがございまして。

>Javaの講義、試験が「自作関数を作り記述しなさい」って問題だったから
「ズン」「ドコ」のいずれかをランダムで出力し続けて「ズン」「ズン」「ズン」「ズン」「ドコ」の配列が出たら「キ・ヨ・シ！」って出力した後終了って関数作ったら満点で単位貰ってた
>
>— てくも (@kumiromilk) March 9, 2016

という当時Twitterの投稿から端を発したこのブームは、様々な言語、ツールで再現が行われました。
そのまとめは[こちら](https://qiita.com/shunsugai@github/items/971a15461de29563bf90 "ズンドコキヨシまとめ")の記事にまとめてあります。




で、ふと思ったんですよ。  
**「これ、SPIRALで作れるのでは？」**

ちょっとふざけたテーマですが、基本機能だけで完結するノーコード実装としては面白い事例かなと思ってます。

---

## 自己紹介

三谷章太郎（みたに・しょうたろう）と申します。  
福岡県久留米市出身です。

- 学歴：九州大学芸術工学部 卒業 → 同大学院芸術工学府 修士課程 修了  
- 前職：Web集客系のコンサル会社にて、WordPressベースのCMS開発を担当  
- 入社：2017年 株式会社パイプドビッツ（現：スパイラル株式会社）へ  
- 経歴：福岡支店長 → ソリューション品質本部長 → 品質推進本部長  
- 現在：**プラットフォーム活用推進本部長**としてSPIRALの利用促進に奮闘中

---

## ズンドコチェックの仕様（おさらい）

今回つくった「SPIRAL版ズンドコチェック」は、以下の仕様です。

- 「ズン」か「ドコ」をランダムに出力
- 過去5回の出力を保持
- 「ズン」「ズン」「ズン」「ズン」「ドコ」が揃ったら「キ・ヨ・シ！」と表示
- そのタイミングで履歴をリセット
- 入力フォーム送信ごとにチェック＆表示
- セキュリティは深く考えず、**基本機能だけでやる**のがルール

---

## 画面とデータの流れ

処理の流れを図にしてみました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201694/9a40a099-57f5-4f76-a033-67a76efb3d58.png)



この図のとおり、送信→ランダム生成→履歴チェック→表示 or リセット、という構成です。

---

## テーブル構成

今回使ったテーブルは2つだけ。

- `ズンドコ_DB`（履歴保存）
- `ズンドコ_TRDB`（一時データ＆トリガ判定）

構成イメージはこんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201694/7f23568b-909c-40d0-b3cb-004a7bcb4539.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/201694/927df93d-743a-4ce1-ac45-4fa373e45e25.png)



---

## 実装のポイント

今回、SPIRALの**基本機能**（ほぼ**ノーコード**）だけで組みました。ポイントはこんな感じ。

- **自動生成トリガ**で乱数生成 → 「ズン」「ドコ」を分岐
- **ルックアップトリガ**で履歴を1件ずつ参照
- **演算トリガ**で一致判定
- 成功パターンが揃ったら「キ・ヨ・シ！」表示＋**レコード削除アクション**

「ズラしてルックアップ」「別DBで履歴管理」あたりは、SPIRALらしい構成かもです。

---
## 実際のズンドコチェックby SPIRAL Ver.1

https://www.pi-pe.co.jp/regist/is?SMPFORM=lfla-mglbld-e0d8096fed46cd7dcbffc9caec6c0abd

履歴は全員で共有してるので、もしかしたら誰かに「キ・ヨ・シ！」取られるかも？

---

## おわりに

完全にネタですが、「こういうことがSPIRALでできるのか！」という驚きが伝わればうれしいです。  
ノーコードでもここまでやれるよ、という実験的なトライでした。
ネタとしてはお遊びですが、実践でも使えるスキルが実はてんこ盛りです。

そして、
「**おれならもっとスタイリッシュに設計できるぜ！**」
「**やっぱり自動実行しなきゃズンドコじゃないでしょ！**」

という方、**挑戦者求ム！！**
↓↓無料トライアルで作れますので、是非チャレンジしてみてください！↓↓

https://www.pi-pe.co.jp/regist/is?SMPFORM=man-lanerf-2473a633d82734eb22aa64cad426ae23&f000099824=https://www.spiral-platform.co.jp/service/spiralv1/&f000099864=Qiita%E8%A8%98%E4%BA%8B%E7%B5%8C%E7%94%B1%E3%81%AE%E7%94%B3%E3%81%97%E8%BE%BC%E3%81%BF%E3%81%A7%E3%81%99%E3%80%82&sales_flg=2
 
使い方はこちらもご参照を！👇
 
https://knowledge.spirers.jp/

こうした事例をもっと発信していけたらと思ってるので、よかったら  
**Qiitaフォローや「SPIRALナレッジサイト」もチェックしてみてください！**

- [Qiita: #spiral タグ](https://qiita.com/tags/spiral)
- [SPIRAL ナレッジサイト](https://knowledge.spirers.jp/)

---
ブロックパズルゲーム「Block Blast」に学ぶUI設計とゲームロジックの思考法

パズルゲームは単なる娯楽ではなく、ユーザーインターフェース設計やアルゴリズム思考の観点からも多くを学べるジャンルです。特に「Block Blast」のようなブロックパズルゲームは、ロジックと直感のバランスが取れた設計が求められます。

ブロック配置の最適化ロジック
「Block Blast」では、ユーザーがさまざまな形のブロックをグリッド上に配置し、縦横のラインを完成させてスコアを稼ぎます。このプロセスは、実際にアルゴリズム設計やAIによる自動最適化に応用できる考え方に似ています。

ユーザー入力の予測

限られたスペースの中でのパターン認識

次のブロック出現に対する戦略的判断

UI/UX設計におけるヒント
「Block Blast」のようなカジュアルゲームにおいては、シンプルで直感的なUI が成功の鍵です。ボタン配置、色使い、効果音や視覚的フィードバックなど、すべてがユーザーの集中力と快適さをサポートするように設計されています。

エンジニアのための実践的学び
このようなゲームの構造を分析することは、ReactやUnityでアプリケーションを開発するエンジニアにとっても貴重な学びとなります。特に、ロジック実装・状態管理・リアルタイムフィードバックの設計には、ゲーム開発の視点が活かせます。

🎮 「Block Blast」ゲームとその背後にあるデザイン思考の詳細はこちら： https://blockblastmodapk.com/
【注意喚起】Google MapsのiOSアプリの共有機能で開発中のアプリのBundle Identifierがバレるから気をつけよ！

# どういうことか

今担当している案件で、他アプリからの場所共有を受け取りたいから、その動作確認の一環としてGoogle Mapsからどんなデータが共有されるかを実際試してみましたら、共有先のアプリ、つまり自分自身のアプリのBundle IdentifierがしれっとGoogle Mapsの共有データの中に埋め込まれていることが発覚しました。

| ![証拠のスクショ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/63998/4cc563ba-dd17-4ef2-b7d2-a4e66aec2abd.png) |
|:---:|
| ↑こちら自分の個人アプリで確認したものですが、しれっとそのアプリのShare ExtensionのBundle Identifierが埋め込まれています |

# 何がまずいか

自分が思いつく限り、2つほどやばいことがあります：

## まだ未公開のアプリ／機能がGoogle Mapsチームにバレてしまう

こちら完全にコンプライアンス的にまずいことだと思いますが、もしそのまま共有アドレスにアクセスしてしまうと、そのBundle IdentifierもGoogleのサーバに送信されてしまうから、まだ水面下で開発しているアプリとか、もしくはアプリとして既に公開済みだけどShare Extensionの対応がまだ公開されていないアプリの場合、その事実がGoogle Mapsチームにバレてしまいます。特にBundle Identifierは構成上、ほとんどの場合会社名が含まれてしまい、またアプリ名からこのアプリは何をするものなのか想像がつくことも多いので、そのBundle Identifierだけで「お、今その会社がこんなアプリ作ってるんだな」ということがGoogle Mapsのチームにバレることになります。

「大丈夫どうせうちAndroidアプリの開発もやってるからGoogleにとって既に把握してる情報」と考えることもできなくはないかもしれませんが、AndroidチームはAndroidチーム、Google MapsチームはGoogle Mapsチーム。同じ会社と言っても、部署が違うからそれぞれにとっての機密情報は簡単に共有されてはいけないはずです。

## 個人のアプリインストール情報がGoogleにバレてしまう

もちろんこれ一般的なユーザにもまずいことがあると思います。対象アプリがShare Extensionを対応している前提ではありますが、Google Mapsにログインして使ってるユーザなら、Google Mapsから場所を特定のアプリに共有すると、「お、このユーザはこのアプリインストールしてるんだね」ということがバレる可能性もあります。まあ大した個人情報ではないですが、そもそもこれはGoogleにとって知る必要がないはずの情報です。

# どのようにBundle Identifierを取得したのか

実際のGoogle Mapsのソースコードを見れるわけではないので、あくまで推測の領域ですが、これはiOSの [`UIActivity.ActivityType`](https://developer.apple.com/documentation/uikit/uiactivity/activitytype-swift.struct) を悪用したものかと思います。この機能は本来、例えばSNSにユーザが共有したい情報を書き出すとき、プラットフォームに応じて最適な情報をアプリ内で処理させるためのものです：例えばTwitterに書き出すときは文字数が140文字以内で画像が4枚まで、Vimeoに書き出すなら動画データのみを書き出す、などのような処理です。これは共有先をまず決めないとできない処理なので、iOSでは共有先を決めてから共有元アプリにこのような処理を依頼することが可能になっています。しかしGoogleをこの機能を悪用して全ての共有先のBundle Identifierを吸い取って共有リンクに埋め込んだと思われます。

# ではどうすればいいのか

正直これAppleの落ち度もないとは言い切れないと思います。元々は限定されたプラットフォームへの共有機能ですが、それを一般化した際に、このようなBundle Identifierを隠せなかったのが根本的な問題だと思います。そして既にこうなってしまった以上、我々ができることはとても限られています。

まず開発者として、Share Extensionの対応を行うとき、共有データの中に自分自身のBundle Identifierが含まれていないかチェックするしかないかと思います。もし含まれてしまったら、それを完全に消すか、ランダムな文字列で置き換えることをお勧めします。

そして一般ユーザとして、もし本当に自分のインストール済みのアプリをGoogleにバレて欲しくなければ、そもそもGoogle Mapsの共有機能でそのまま対象のアプリに共有せずに、リンクだけコピーして共有したいアプリを立ち上げて直接ペーストするのが一番手っ取り早いでしょう。まあ一番のお勧めはそもそもGoogle Mapsを使わないことかと思います。[Googleは既にこれまで何度も個人情報の収集で問題を起こしてきた](https://chatgpt.com/share/680b5f08-a114-800f-b044-5f5cd5838d1d)ので、安心して使えるサービスとは言い難いではないかと思います。
(途中)空間図形「(その3/5)2025愛知公立高校入試図形 最後の問題3(3)」様を参考にsympyの３つの球の交点計算で。

・(その5/5)作成中。積分は未です。

:::note info
[(その1/5) sympyとFreeCADで](https://qiita.com/mrrclb48z/items/f03cfc6a7b9375fc4b63)
[(その2/5) 三角柱で](https://qiita.com/mrrclb48z/items/ce12576a952ef9423795)
(その3/5) 本ページ
[(その4/5) 空間の座標変換の計算で](https://qiita.com/mrrclb48z/items/f414a4c36fef18c33a9f)
[(その5/5) 作成中]()
:::

・作図はありません。
・**変換後?の３つの球の交点計算で、交点のz座標を四角錐の高さとしました。**
　**ここまできたら、みんな同じに見えてきました。**

・次は(その1/5)を見て下さい。
　オリジナル
　sympyのweb上での実行方法
　
# sympyで
#### ver0.1 
```python
# 3つの球 
from sympy import *
var('x y z')
def mySphereFormula(myP,myR):
    return ((x-myP.x)**2+(y-myP.y)**2+(z-myP.z)**2-myR**2).expand()
OA,AB=12,6
d=AB*Rational(1,2)
h=sqrt(OA**2-((d*sqrt(2))**2))   
O=Point(0,0,0)
A,B,C,D=map(Point,[(-d,-d,-h),(d,-d,-h),(d,d,-h),(-d,d,-h)])
E=O+Rational(2,3)*(A-O)
F=O+Rational(1,2)*(B-O)
G=O+Rational(1,2)*(C-O)
H=O+Rational(2,3)*(D-O)
trEFH=Triangle(sss=(E.distance(F),F.distance(H),H.distance(E)))
EFH_E=Point   (trEFH.vertices[0].x,trEFH.vertices[0].y,0)
EFH_F=Point   (trEFH.vertices[1].x,trEFH.vertices[1].y,0)
EFH_H=Point   (trEFH.vertices[2].x,trEFH.vertices[2].y,0)
EFH_O=Point   (solve([mySphereFormula(EFH_E,E.distance(O)),
                      mySphereFormula(EFH_F,F.distance(O)),
                      mySphereFormula(EFH_H,H.distance(O))],[x,y,z])[1])
trFGH=Triangle(sss=(F.distance(G),G.distance(H),H.distance(F)))
print("#",Rational(1,3)*EFH_O.z*(trEFH.area+trFGH.area))
# 7*sqrt(14)
```

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

# いつもと違うおすすめです。
#### Qiita 内
・3つの球の交点計算していました。

https://qiita.com/mrrclb48z/items/2bece4f967bcd3bf126a
週末にゲーム制作してみませんか？



こんばんは、韓国在住のsanaです！

今日は金曜日ですね、一週間お疲れ間瀬です！ 週末にプログラミングや開発に挑戦するかた多いと思います。
今月から、週末に合わせてプログラミングや開発関連の講座をおすすめしているのですが、今週はゲーム開発の講座を紹介します！:v_tone1:


https://u.inf.run/3S3tBsO

https://u.inf.run/3Yf8JlW

https://u.inf.run/4jTNIpn

すべて無料で見れるので自分の好みにあったゲームスタイルを選んでぜひ試してください！

あと私の投稿した記事の中で反響あったものいくつか紹介します！こちらの方もぜひのぞいてみてください！


https://qiita.com/sana89/items/82f8c765885da82195cf

https://qiita.com/sana89/items/9398c4873676d1a5a9a6
TS未経験でも３ヶ月で新機能を開発した話 [登壇レポート]

## はじめに

こんにちは！先日開催されたエンジニア向けイベント「[フルスタックTypeScriptの現在地：3社が本音を語るハイブリッド勉強会](https://toggle.connpass.com/event/349725/)」にて、「TS未経験から３ヶ月で新機能開発した話」というタイトルで登壇させていただきました。

この記事では、発表内容の概要と、フルスタックTypeScript開発で感じたメリットについてご紹介します。

## 発表資料

当日の発表資料はこちらで公開しています。詳細はこちらをご覧ください。

[https://speakerdeck.com/haya1o/tswei-jing-yan-kara-3keyue-de-xin-ji-neng-kai-fa-sitahua](https://speakerdeck.com/haya1o/tswei-jing-yan-kara-3keyue-de-xin-ji-neng-kai-fa-sitahua)

## 発表概要

### どんな話？

プログラミング経験はあるものの、TypeScriptやモダンなフロントエンド・バックエンド開発は未経験だった私が、インターンとしてトグルホールディングス株式会社にジョインし、3ヶ月間でフルスタックTypeScript（React, Hono, Prisma, Zodなど）を用いた開発に挑戦し、最終的に新機能開発まで担当した経験についてお話ししました。

### 3ヶ月の道のり

限られた時間（週15時間）の中で、以下のようなタスクに取り組みました。

1.  **最初のタスク（フロントエンド改修）**:
    * 簡単なボタンのデザイン変更からスタート。
    * GitHub Codespaceやホットリローディングのおかげで、1営業日でPull Requestを作成。
2.  **2つ目のタスク（バックエンド改修）**:
    * 「タグ更新時に更新日時が変わらない」バグの修正。
    * バックエンド経験ゼロでも、フロントエンドと同じTypeScript（Hono, Prisma）だったため、構文の壁がなく学習に集中できた。
3.  **様々なバグ修正**:
    * PDF出力、権限チェック漏れ、エラー表示など、複数のバグ修正を担当。
    * フルスタックTypeScriptだとフロントエンドからバックエンドまで一気通貫で見通せるため、原因特定や修正がしやすいと感じた。
4.  **集大成：新機能開発**:
    * ユーザー利用状況（物件登録数、VC実行数）を集計・表示する機能の開発を担当。
    * 要件理解からフロントエンド・バックエンド実装まで一通り経験。
    * Zodによる型定義と型推論のおかげで、API境界での不安が少なく開発を進められた。

### フルスタックTypeScriptで感じたメリット

今回の経験を通して、特に以下の3つのメリットを強く感じました。

1.  **学びやすい！**
    * フロントエンドとバックエンドで言語（TypeScript）が共通なため、学習コストが低い。
    * 環境構築が容易（GitHub Codespaceなど）。
    * ホットリローディングで試行錯誤しやすい。
    * Reactなどのモダンなフレームワークは、Web開発の基礎があればキャッチアップしやすい。
2.  **全体像の把握がしやすい！**
    * フロントエンドからバックエンドまで同じ言語・型で追えるため、処理の流れや依存関係を理解しやすい。
    * バグ発生時も、問題箇所の特定が比較的容易。
    * レイヤードアーキテクチャなどを意識した設計の理解も進む。
3.  **型定義が怖くない！**
    * TypeScriptの静的型付けにより、開発中のエラーを早期に発見できる。
    * 特にZodを使ったスキーマ定義と型推論は、API境界でのデータの整合性を保つのに非常に役立ち、安心して開発を進められた。

## まとめ

TypeScript未経験からスタートしましたが、フルスタックTypeScriptという技術スタックのおかげで、3ヶ月という期間で多くのことを学び、新機能開発まで達成することができました。

フルスタックTypeScriptは、学習コストの低さ、開発効率の高さ、コードの堅牢性といった面で、個人開発にもチーム開発にもおすすめできる選択肢だと実感しています。

詳細や具体的なコード例については、ぜひ上記のSpeaker Deck資料をご覧ください。

最後までお読みいただきありがとうございました！

## 懇親会
懇親会にて、多くの方とお話しさせていただきました！AIエージェントによってエンジニアという職業がどうなっていくのか？というのは新卒の自分としては考えておかないといけないテーマだなと感じました。
AIツールのキャッチアップをしっかりしつつ、爆速で開発できるエンジニアを目指していきます！
組込みシステムにおけるウォッチドッグタイマについて

## ウォッチドッグタイマ
　ウォッチドッグタイマとは、システムに異常が発生したときにその異常を検知するためのタイマ。

　このタイマはダウンカウント方式で、システムの動作中は常にカウントを続けている。そのカウントを定期的にリセットすることで、通常はカウントが0にならないようにしている。しかし、システムに異常が発生した場合はリセットが行われずカウンタが0になるので、このとき即座に異常を知らせる割り込み（ノンマスカブル割り込み）を発生させる。
Pythonで実現するExcelセルのロックと保護

日常の業務や自動化されたレポート作成の中で、Excel ワークシートの重要なセルの内容を誤って変更されないように保護することは、データの安全性と整合性を確保するための基本的な要件です。手動で保護を設定する方法に比べて、Python を使用してワークシートを自動的にロックすることで、作業の効率を大幅に向上させるだけでなく、複数のファイルやテンプレートに一括適用することも可能です。

本記事では、**Python を使って Excel ワークシート内のセルをロックする方法**について解説し、保護の種類をカスタマイズする方法、パスワードの設定、特定の範囲のみ編集を許可する方法など、便利な機能も紹介します。

- Pythonで特定のセルをロックする方法  
- Pythonでワークシート保護オプションとパスワードを設定する方法  
- Pythonで編集可能な範囲を設定する方法  

使用ライブラリ：[Free Spire.XLS for Python](https://jp.e-iceblue.com/introduce/introduce-free-xls-for-python.html)  
インストールコマンド：`pip install spire.xls.free`

## Pythonでワークシート内の特定のセルをロックする

Excel のセルは既定で「ロック」状態ですが、実際にロックが有効になるのは、ワークシート保護を有効にした場合のみです。そのため、特定のセルのみをロックしたい場合は、まずすべてのセルのロックを解除し、対象セルのみをロック状態に設定する必要があります。手順は以下の通りです：

1. `Workbook` インスタンスを作成し、ワークシートを新規作成または読み込みます  
2. ワークシート内のすべてのセルの `.Style.Locked = False` を設定してロックを解除します  
3. 対象セルのみ `.Style.Locked = True` を設定してロックします  
4. `sheet.Protect(password, SheetProtectionType)` を使用して保護を有効にします  

**コード例**
```python
from spire.xls import Workbook, ExcelVersion, SheetProtectionType

# ワークブックを作成してワークシートを追加します
workbook = Workbook()
workbook.CreateEmptySheets(1)
sheet = workbook.Worksheets.get_Item(0)

# セルの内容を設定します
sheet.Range.get_Item("A1").Text = "保護されたセル"
sheet.Range.get_Item("A2").Text = "編集可能なセル"

# デフォルトのロック状態を解除します
sheet.Range.Style.Locked = False

# 特定のセルをロックします
sheet.Range.get_Item("A1").Style.Locked = True

# パスワードを使用してワークシート保護を有効にし、保護タイプを設定します
sheet.Protect("123456", SheetProtectionType.All)

# 書式を調整します
sheet.Range.get_Item(1, 1, 2, 1).Style.Font.FontName = "Yu Gothic UI"
sheet.Range.get_Item(1, 1, 2, 1).Style.Font.Size = 12.0
sheet.AutoFitColumn(1)

# ファイルを保存します
workbook.SaveToFile("output/LockedCells.xlsx", ExcelVersion.Version2016)
workbook.Dispose()
```

生成されたファイルでは、セル A1 のみが編集不可となり、B1 は編集可能です。

![Pythonでワークシート内の特定のセルをロックする](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/f27e3ebc-37c9-4994-adff-9968bdba3867.png)


## Python でワークシートの保護オプションを設定する

Spire.XLS では、柔軟な保護オプションを `SheetProtectionType` 列挙体で提供しており、ユーザーの操作を細かく制御できます。以下は代表的な保護オプションです：

- `All`: すべての操作を制限  
- `Content`: セルの内容のみを保護  
- `FormattingCells`, `FormattingRows`, `FormattingColumns`: 書式設定の変更を制限  
- `InsertingRows`, `DeletingRows`: 行の挿入や削除を禁止  
- `Objects`: 図形や画像などのオブジェクトの編集を禁止  
- `Sorting`, `Filtering`: 並べ替えやフィルターの使用を制限  
- `UsingPivotTables`: ピボットテーブルの操作を禁止  

例えば、セルの入力は許可しつつ書式変更のみを制限したい場合は以下のように指定します：

```python
sheet.Protect("123456", SheetProtectionType.FormattingCells)
```

## Python で編集を許可する範囲を設定する

ワークシート全体を保護していても、一部のセルはユーザーに自由に入力させたいケースがあります。そのような場合は、`AddAllowEditRange()` メソッドを使用して特定のセル範囲に編集を許可できます。

```python
# 編集を許可する範囲を追加
sheet.AddAllowEditRange("EditableRange", sheet.Range.get_Item("B1"))
```

この設定により、ワークシートに保護がかかっていても、セル B1 はパスワードなしで編集できます。

---

上記の手順により、Python スクリプトを使って Excel のセルに対する細かなロック設定や権限制御を実現できます。自動レポート生成やテンプレート保護、社内データ共有など、さまざまなシーンで活用でき、データの安全性と業務効率の向上に貢献します。

さらに詳しい情報は、Spire.XLS の[公式ドキュメント](https://jp.e-iceblue.com/spire-xls-python/xls-python-program-guide-content.html)をご参照ください。
google adk（Agent Development Kit）って、こんなに簡単にスタートできるの？

# google adk（Agent Development Kit）って、こんなに簡単にスタートできるの？

## google adk（Agent Development Kit）を早速触ってみました。
といっても、私の場合はドキュメントを読み込んで作業するなんてことはできません。
ドキュメント類は、まとめてありますので、以下を参考にしてください。

こんなかんじで動きます
https://www.youtube.com/watch?v=rsDqyQr0L5E


## 私がやったことは以下の通りです。（全部、リンクがありますので参考にしてください）
1. `https://google.github.io/adk-docs/`　のすべての情報を１つのテキストに集約

2. `https://google.github.io/adk-docs/api-reference/`　のすべての情報を１つのテキストに集約（jsonもあり）

3. 上記１，２をGeminiに投げて、詳細に理解してもらう

4. スモールステップで、一番簡単なエージェントアプリを作ってみたい。と指示して、教えてもらった通りにアプリを作る
＝＞現在の時刻を教えてくれる　エージェントアプリが完成（数分で完成）

5. 他にどんなエージェントができるのか、事前に概要を知りたい
＝＞
** 1. 情報収集・要約エージェント
** 2. タスク自動化エージェント
** 3. 対話型アシスタント / チャットボット
** 4. コード生成・実行エージェント
** 5. マルチエージェントシステム (専門家チーム)
** 6. データ分析・レポート生成エージェント
** 7. パーソナライズドエージェント
ができるとのこと（あくまでもサンプル）

6. 上記  1. 情報収集・要約エージェント　をスモールステップで作りたい
＝＞https://google.github.io/adk-docs/ の内容を要約して　に返答できるエージェントアプリが完成（数分で完成）


## 詳細内容は、以下のGeminiとの会話の通りです。

https://aistudio.google.com/app/prompts?state=%7B%22ids%22:%5B%221AKJzH4zrYJUt-jx3PCHGK4gXN8bYnuKN%22%5D,%22action%22:%22open%22,%22userId%22:%22106828038085899767412%22,%22resourceKeys%22:%7B%7D%7D&usp=sharing

## 上記1. `https://google.github.io/adk-docs/`　のすべての情報を１つのテキストに集約
＝＞　https://docs.google.com/document/d/1w1q36_GvRCfwB8kA2EzzoBht1izO2mlz_G6vAqYMcJs/edit?usp=sharing

## 上記2. `https://google.github.io/adk-docs/api-reference/`　のすべての情報を１つのテキストに集約（jsonもあり）
＝＞　https://docs.google.com/document/d/1e0X0IcvfWIV7QGHO9tJjT_vnd7bcA_mA_LhiSa_ui-4/edit?usp=sharing

### なにも分からなくても、とりあえずエージェントアプリができました！！
【Typescript】ブラウザバックの落とし穴

## 概要
実案件でbfcacheについて色々大変だったことがあるのでメモがてら記事にしました。


## bfcacheって知ってる？
bfcacheとはブラウザバックしたときに、直前のページの状態をそのまま使っちゃうもの。

![bfcache.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/1dac1be6-3151-4f36-87a7-a6125089fcaf.png)
bfcacheがあるおかげで、ページ遷移が爆速になって無駄なロードをさせないっていうめっちゃ利点ばっかなんだけど、今回はそれがたまたま邪魔してきた。。。

## 「DOM上の正確な値を表示」
### 問題
例えば「今の時間（サーバーの時間）」を使ったプログラムを書くとき。
DOM上にサーバーからの時間（サーバーの今の時間）を描画し、jsでその値を元にプログラムを組む場合。
![example.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3640746/aaed56ba-0015-4fbe-a96c-5af6074a3094.png)

ページロード時は正常な値が描画されるけど、ブラウザバッグしたときは正常な値が出ない。。。

### 解決策
そのページにこのjsを入れる。
``` typescript
window.addEventListener('beforeunload', () => {});
```
:::note alert
※最適解ではないです
:::
最適解ではない理由は**そのページにおいてbfcacheを完全に無効にする**からです。
ユーザー体験的にはbfcacheを無効にするのは絶対良くない。。。

### 最適解
おそらく一番良いのはバックエンドがわでAPIを用意し、ブラウザバックの時に叩いて置き換えるというもの。
```typescript
 window.addEventListener('pageshow', (event) => {
     // bfcacheかそうじゃないか
    if (event.persisted) {
      // API叩くコマンド
    }
  });
```
pageshowイベントの中で、bfcacheがあるかないかが内包されてるので、それを条件にAPI叩いくのがいいと思います！

## まとめ
bfcacheをさせないようにするのは結構簡単にできる。
ただし、ユーザー体験は落ちてしまうのでなるべくしないほうがいい。
逆にbfcacheを有効にしたい人向けのおすすめの記事を貼っておきます。
https://techblog.yahoo.co.jp/entry/2023072430429932/
理解に時間をかける大切さを知って救われた話

### はじめに
先日、[Qiita Bash](https://increments.connpass.com/event/347388/)というイベントに登壇し、「良い記事は誰かを救う！読んで良かった記事 と 書くときの工夫」というテーマでお話しさせていただきました。今回はそこで私がお話しした内容を記事にまとめました。

https://increments.connpass.com/event/347388/

### 登壇資料

**理解に時間をかける大切さを知って救われた話**

https://speakerdeck.com/mercury_dev0517/qiita-bash

### どんなことを話したか

今回のQiita Bashは「**良い記事は誰かを救う！読んで良かった記事 と 書くときの工夫**」というテーマだったので、私が読んでよかったと思った記事の紹介と、どうすれば「読んでよかった」と思ってもらえる記事が書けるのかについて、考えていることをお話ししました。

イベントの開催時期が4月で新生活シーズンということもあり、特に新社会人やエンジニアとしての経験が浅い方に向けて、少しでも参加して良かったと思える内容にしたいと思いつつ、話す内容を決めていきました。

### 私が読んでよかったと思う記事

「**プログラミングというより物事が出来るようになる思考法**」

https://note.com/simplearchitect/n/n388201603a28

かなり有名な記事なので、読んだことがある方も多いかもしれません。

この記事では、**理解には時間がかかる**という前提で時間をかけて**徹底的に理解を深める習慣**について紹介されています。

![理解に時間をかける大切さを知って救われた話.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/546fe427-86f0-422d-bb6b-97655aba4f9c.png)

私が新卒の頃を思い出してみると、分からないことが多くて色々と悩みながらキャッチアップしていた記憶があるので、この記事で紹介されている内容にはとても救われました。

「理解に時間がかかるのは悪いことだと思っていたけど、時間をかけても良いのか」と思えて、それらは現在仕事をする上でも大事な考え方の1つになっています。

![理解に時間をかける大切さを知って救われた話 (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/f9150a6c-b822-4272-a5ce-dc12ca10b665.png)

### 記事を読んで実践していること

この記事を読んで実践していることについてもいくつか紹介します。

#### ドキュメントを丁寧に読み解く
例えば、新たにライブラリを導入する時など、ドキュメントを読む必要がある場合に、繰り返し読み返して徹底的に理解を深める様にしています。
英語のドキュメントだったり1回で理解できなかった場合でも、繰り返し読み返すことで理解できる様になることも多いです。

#### コードへの理解を深める
転職や異動、副業などで新規プロジェクトに参加する場合にも、全体像を把握する為に時間をしっかり取って丁寧にコードを読み解く様にしています。こちらも一度に全てを理解するのではなく、時間をかけて何度も読み返したり、分からないところを1つずつ解消していくことを意識しています。こういった作業の積み重ねで理解が深まります。

#### 育成を行う際に繰り返し時間をかけて理解してもらう
自分以外のメンバーに対しても、「理解には時間がかかる」という前提で考えることは大事だと思います。周りのメンバーが理解につまづいている様に見えた時には、丁寧に時間をかけて着実に理解してもらうことを促すと良いかもしれません。

![理解に時間をかける大切さを知って救われた話 (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/0d55fcdd-6b90-4460-940a-7f38c091e2c3.png)

#### 見つめる鍋は煮えない

記事では直接言及されていないのですが、私が好きな『思考の整理学』という本では「**見つめる鍋は煮えない**」ということわざが紹介されています。時間をかけて丁寧に取り組んだけど上手くいかない、という時には少し休んでみるのも大事だと思います。突然解決のヒントが浮かんでくるかもしれません。

https://www.chikumashobo.co.jp/product/9784480020475/

### どういう記事を読みたくなるのか

「プログラミングというより物事が出来るようになる思考法」は私にとって、読んでよかった記事として今でも定期的に見返す記事となっているのですが、この記事を参考に、どんな記事だったら「読んでよかった」と読者に思ってもらえるのかについても考えてみました。

#### 自分が苦手な部分を正直にさらけ出す

出来ないことや出来なかったことを正直にさらけ出すのはとても勇気が要ることですが、そういった苦手を克服した記事は多くの人の心を動かすことがあります。

![理解に時間をかける大切さを知って救われた話 (3).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/91827699-4c22-49de-b503-8567e39e27ec.png)

#### 解決策の提示だけでなく、プロセスについても書く

ただ解決策を提示するだけでなく、どういった考えてそこに至ったのか等のプロセスが書かれていると、より印象に残りやすく共感を得られる記事になると思います。

![理解に時間をかける大切さを知って救われた話 (4).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1793562/fed10629-6e22-4239-8135-d318b8120e2e.png)

### まとめ
「プログラミングというより物事が出来るようになる思考法」は、プログラミングに限らず、様々な物事の理解を深める上で大事なことが書かれている素晴らしい記事なので、まだ読んだことがない方はぜひこの機会に読んでみてください。

この記事の様に、私も自分の苦手を正直にさらけ出してそれを解決するまでのプロセスをアウトプットすることで、誰かを救う記事を書いていきたいです！

### 参考

- 「[プログラミングというより物事が出来るようになる思考法](https://note.com/simplearchitect/n/n388201603a28)」牛尾剛
- 『[思考の整理学 (ちくま文庫)](https://www.chikumashobo.co.jp/product/9784480020475/) 』外山滋比古
個人的備忘録：ホットリロード対応！Next.jsのDocker環境構築メモを整理してみた

## はじめに

この記事では、Next.js アプリケーションを Docker 上で開発するための `docker-compose.yml` ファイルの構成について、自分用の備忘録としてまとめています。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

主に開発環境を整える目的で記述しており、ホットリロードの対応や依存関係の管理も管理しています。

## 書こうと思ったきっかけ

チーム開発や複数環境での動作確認を行う際、開発環境を統一するために Docker 化が有効です。特に Next.js のようなフロントエンドフレームワークでは、ホットリロードや依存ライブラリの管理に工夫が必要です。

***そこで、最小構成で使いやすい `docker-compose.yml` の中身を整理しておきたいと思いました。***

## docker-compose.yml の解説

```yaml
version: '3.8'

services:
  next-app:
    container_name: next-app
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/app
      - /app/node_modules
    environment:
      - CHOKIDAR_USEPOLLING=true
```

**今回作成したファイル**

https://github.com/2025SpringTeamA/frontend/blob/main/docker-compose.yml

### 各項目の説明

| 設定項目 | 説明 |
|----------|------|
| `version: '3.8'` | Docker Compose のバージョン指定。安定性と互換性を兼ね備えたバージョンです。 |
| `services:` | 起動するサービス（＝コンテナ）を定義します。ここでは `next-app` という名前のサービスを用意しています。 |
| `container_name` | コンテナ名を明示的に `next-app` と指定します。省略時はサービス名が使われます。 |
| `build: .` | 現在のディレクトリにある Dockerfile を元にビルドを行います。 |
| `ports` | ホストの `3000` 番ポートを、コンテナ内の `3000` 番ポートにバインドします。Next.js の開発サーバーが使う標準ポートです。 |

  - `.:/app`: ホストのカレントディレクトリをコンテナ内の `/app` にマウントし、ソースコードの変更をリアルタイムに反映します。
  - `/app/node_modules`: 匿名ボリュームとして定義し、ホスト側の node_modules と分離してトラブルを避けます。 |
| `environment` | `CHOKIDAR_USEPOLLING=true` を指定し、ファイル変更の検知をポーリング方式に変更。WSL や Docker Desktop で安定して動作させるための工夫です。 |

## まとめ

この構成により、Next.js アプリの開発環境を Docker 上で快適に構築できます。

:::note warn
**特にホットリロードや依存管理の面でトラブルが少なく、チーム開発やマシン間での再現性も高くなります。**
:::

今後は、環境変数の `.env` ファイル化や MySQL との連携なども検討していく予定です...！
レビューがだるいので、レビューコメントをChatGPTにレビューしてもらう拡張を作った

# はじめに
みなさんコードレビューしていますか？
私は最近仕事でレビューすることが多くて、めんどうくせぇってなっています。

当たり前のことですが相手をいかに不快にさせないよう指摘をするかキモですが、私は面倒くさりなのでそこまで考えるのが超絶面倒です。

そんな中、ふと思いました。

脳死でササッっとコメントを書いて、そのコメントをAIに優しくなるように添削してもらえれば平和な世の中になるのではないかと。

ということで、Chrome拡張を作りました。

# 何ができるの？
GitHubのPull Requestで、レビューコメントにChatGPTが添削してくれます。

たとえば、

「出直せ」→「もう少し考えたいですね☺」

みたいな添削をAIが行ってくれます。
要するに、「レビューのレビュー」をやってくれます。

# 使い方
ChatGPTのAPIキーを設定（拡張機能の設定画面から）

GitHubでPRを開く

レビューコメントの横に「ChatGPTに聞く」ボタンが出る

押すと、そのコメントをAIがレビューしてくれる

# 終わりに
レビューに気を使いすぎず、レビュー文化がマイルドになればいいな。。。と酒をたしなみながら数時間で作ったネタ拡張機能です。

自己責任でご利用ください。

興味ある人はぜひ触ってみてください👇
[chatreview](https://chromewebstore.google.com/detail/chatreview/mmilemfbpioehkfpahdcfahjoblidlel?authuser=3&hl=ja&pli=1)

（そういえばチャット関係ないなーと気づきました）
Go学習記録5日目　レスポンスタイムを計測するCLIツールの作成③

Go言語学習の5日目です。

今日も前回の続きです。Webサービスのレスポンスタイムを計測するCLIツールに、並行処理を実装しました。

https://qiita.com/rickeysan95/items/163e23a8f934c2c672b0

並行処理を実装するための方法として、1).sync.WaitGroupを使う方法と、2).バッファなしチャネルを使う方法があります。

### sync.WatiGroupを使って実装
```
    // tryGetUrlはurlに対してGetメソッドを叩いて結果を出力するメソッドです
	var wg sync.WaitGroup	

	for _, url := range urls {
		wg.Add(1)
		go func(){
			defer wg.Done()
			tryGetUrl(url)
		}()
	}
	wg.Wait()
```
まずはまったポイントとして、Goの無名関数の書き方があります。``` func() {...}()```とあり、1つ目の()は引数、{}は処理の中身だとすぐに理解できました。ただ、最後の()の意味が分かりませんでした。これは無名関数を即座に実行するためのものです。
```
// 実行コマンド
go run . https://example.com https://google.com https://yahoo.co.jp
// 実行結果
[✓]{https://yahoo.co.jp} -200 OK -132ms
[✓]{https://example.com} -200 OK -354ms
[✓]{https://google.com} -200 OK -386ms
```
前回のforで回していた時は、引数の順番通りにexample.comからGetアクセスして結果を出力していました。並列処理を取り入れた今回は、必ずしもその順番で出力されるわけではありません。

### チャネルを使った実装
今度はチャネルを使って、同じような処理を実装してみました。最初私は下記のように書きました（間違っています）
```
	results := []Result{}

	for _, url := range urls {
		c := make(chan Result)
		go tryGetUrl(c,url)

		result := <-c

		results = append(results, result)
	}

	fmt.Println(results)
	fmt.Println("プログラム終了------")
```
各URLに対してゴールーチンを起動していますが、チャネルを使って結果を受け取る部分が各ゴールーチンの直後にあるため、実質的に逐次処理になってしまいます。
```
// 実行コマンド
 go run . https://example.com https://google.com https://yahoo.co.jp
// 出力結果
[{https://example.com 200 OK 377} {https://google.com 200 OK 383} {https://yahoo.co.jp 200 OK 144}]
```
正しく並行処理を実装するために、すべてのゴールーチンを起動した後に結果を集めるようにします。

```
	results := []Result{}
	c := make(chan Result) 
	
	for _, url := range urls {
		go tryGetUrl(c, url)
	}
	
	for range urls {
		result := <-c
		results = append(results, result)
	}
	
	fmt.Println(results)
	fmt.Println("プログラム終了------")
```
また、チャネルをバッファなしにするか、バッファありにするかという問題があります。まだこれらにどのような違いがあるのか分かっていません。今後、勉強していきます。

次回はEbitengineを使って2Dゲームを作ってみようと思います。
PythonでExcelファイル内の画像を抽出する方法

データの可視化や業務の自動化が進む中、Excelファイルに埋め込まれた画像（グラフのスナップショット、製品写真、ロゴなど）は、多くの重要な情報を担っています。これらの画像を手動で抽出するのは手間がかかり、複数ファイルを扱う場合は非効率です。Pythonスクリプトを活用することで、Excel内の画像を自動的に抽出・保存でき、アーカイブ、レポート作成、画像処理など幅広い用途に活用できます。

本記事では、**Pythonを使ってExcelファイル内の画像を抽出・保存する方法**をご紹介します。

使用ライブラリ：[Free Spire.XLS for Python](https://jp.e-iceblue.com/introduce/introduce-free-xls-for-python.html)  
インストール（PyPI）：`pip install spire.xls.free`

---

## PythonでExcel内の画像を抽出・保存する手順

Spire.XLSが提供するインターフェースを使用すれば、各ワークシートに埋め込まれた画像を1つずつ取得して、画像ファイルとして保存できます。この手法はシンプルで効率的なため、バッチ処理にも最適です。

### 操作手順

1. `Workbook` オブジェクトを作成し、`LoadFromFile()` メソッドで対象のExcelファイルを読み込みます。  
2. すべてのワークシートをループ処理で取得し、`Workbook.Worksheets.get_Item()` で現在のワークシートを参照します。  
3. `Worksheet.Pictures` プロパティを使ってワークシート内の画像コレクションを取得し、順に処理します。  
4. `Worksheet.Pictures.get_Item()` で各画像を取得し、`XlsBitmapShape.SaveToImage()` メソッドでローカル画像ファイル（例：PNG形式）として保存します。  
5. ファイル名にシート番号と画像番号を付与して重複を避け、管理しやすくします。  
6. 最後にリソースを解放します。

---

### サンプルコード

```python
from spire.xls import Workbook

# Workbook オブジェクトを作成します
workbook = Workbook()

# Excel ファイルを読み込みます
workbook.LoadFromFile("Sample.xlsx")

# ワークブック内のワークシートを順に処理します
for i in range(workbook.Worksheets.Count):
    # 現在のワークシートを取得します
    sheet = workbook.Worksheets.get_Item(i)
    # ワークシート内の画像を順に処理します
    for j in range(sheet.Pictures.Count):
        # 現在の画像を取得します
        pic = sheet.Pictures.get_Item(j)
        # 画像をファイルとして保存します
        pic.SaveToImage("output/ExcelImages/Sheet_" + str(i) + "Image_" + str(j) + ".png")

# リソースを解放します
workbook.Dispose()
```

---

## 出力結果（画像ファイル）

![Pythonを使ってExcelワークシートから画像を抽出](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/278784/ff4da338-3e50-4792-8b05-7a148a5ac996.png)


---

この記事では、Pythonを用いてExcelファイル内の画像を一括で抽出し、ローカルに保存する方法をご紹介しました。このアプローチは、業務効率化、ドキュメント整理、画像アーカイブなどの多様なニーズに対応でき、拡張性・実用性ともに優れています。

さらに高度な処理（画像の分類管理、形式変換、メタデータの取得など）を行いたい場合は、Pillowなどの画像処理ライブラリと組み合わせて開発することも可能です。
WindowsでVimを使う

<!-- WindowsでVimを使う -->

## はじめに

Windowsをいじっているとき、コマンドラインエディタが欲しくなります(.ssh/configの編集時など）。)

WSLやGit Bashを使えばVimを使うことができるので、いったんそれらに切り替える手もありますが、今回はあえてWindows上でVimを使う方法を調べてみました。

## インストール

ひとまずインストールが必要です。以下のサイトからインストーラをダウンロードします。

https://www.vim.org/download.php

自分は「gvim_9.1.0_x64_signed.exe」をダウンロードしました

ダウンロード後、インストーラを起動してインストールを進めます。基本的に全てデフォルトのままで問題ないと思います。

インストール後、環境変数にVimのパスを追加します。インストール時に特に何も指定していなければ、``C:\Program Files\Vim\vim91``を通せば大丈夫です。

## 使ってみる

コマンドプロンプトかPowerShellを開き、適当なディレクトリで以下のコマンドを実行してみます。

```bash
> vim [file name]
```

無事Vimでファイルを編集できるはずです。

ちなみに、このままだと編集後に``~``ファイルや``un~``ファイルが作成されてしまいます。これらはバックアップファイルやアンドゥファイルであり、一応役割がないわけではないですが、カレントディレクトリが少し汚れてしまいます。

この対策のために、``~/.vimrc``に設定をしましょう。

```bash
> vim ~/.vimrc
```

以下の事を追記してください。

```vim
set nobackup
set noundofile
```

これで、バックアップファイルおよびアンドゥファイルが作成されないようになります。

ただ、これらのファイルが万一の時に必要となる場合があります。それが心配なら、以下のような設定をすることでこれらのファイルを邪魔にならない場所へ保存しておくことができます。

```vim
set backupdir=/path/to/directory
set undodir=/path/to/directory
```

他にも、``~/.vimrc``に様々な設定を書き込み、Vimを便利にすることができます。

## おわりに

Windowsを使っているとインストーラを使わないといけなかったり、パスを通す必要があるので少し面倒だと感じました。WSLだとこの辺はaptなどですぐに出来ますね。

ただ、WSLを起動しなくても良くなるので、一回やってしまえば便利になると思います。

## 参考文献

[テキストエディタ「Vim」をWindowsでも使う方法 | コンピューターシステム(株)|愛媛県松山市のソフトウェア・アプリ開発会社](https://www.jcsc.co.jp/news/p404/)

[vimで作られるファイルへの対処法 .swp .un~ .*~ #Vim - Qiita](https://qiita.com/chihiro/items/3b8d643474f3accc9b3c)
小さな会長の大きな挑戦：そこで見えたコミュニティ運営の基本。

こんにちは！
コミュニケーションやコミュニティを通じて人や活動がつながり、新しい世界を作る活動をしています。森田です。

今回は、
息子（小2）が友達との集まりをアレンジしているを横で見ていました。
彼の興奮、悩み、そして寂しさは、まさにコミュニティ運営そのもので、共感しかなかった！
そんな話です。

## 突如始まったコミュニティ
ある平日の夜のこと、息子が「日曜日の習い事のあとにＡ公園で友達と遊ぶ！」と言い出した。
この年代の子どもたちだけの約束は実現しにくいものだけれど、息子は自信満々。
「みんな来るよ！クラスの友達でＡ会を立ち上げたんだ。全員で6人、僕が会長だよ。」
ちょっと自慢げに、そしてわくわくが止まらない様子で、部屋の中をぴょんぴょん飛びながら教えてくれた。

「会を作ったの！？スゴイね！」
「もう決めたんだ！行ってもいいでしょう？」

まあ習い事の帰り道だし、誰かいたらラッキーいなければちょっと遊んで帰ればいいか…。

「絶対来るよ！だって約束したんだ！」

## 初めての日曜日
果たして日曜日、Ａ公園へ行ってみると…　みんないるー！

「すごいね、みんな来てるね！」
「ね、言ったとおりでしょ？」
と自慢げに言うと、息子は友達のところへ飛んで行ってしまった。

共通の目的があると人は自然と集まるものなんだな。
そうか、Ａ会はコミュニティなんだ。

それから毎週日曜日は、Ａ会が開催された。

## 雨の日とコミュニティ運営
ある日曜日は雨。
「今日はきっと誰も来ないね」と息子は行かなかったけれど、実は来た子がいたみたい。
なぜ公園に来なかったのかと、週明け学校で言われたよう。
「責められて弱っちゃったよ。だから、雨の日は公園に行かないこと、金曜日に予定を確認することを決めた。」

それは運営ルールだね。みんな楽しく過ごしたいもんね。
「うん。わたしは会長だからね、みんなが楽しめるようにしないとね。」
あらら。会長の意識もバッチリ。

## コミュニティの停滞
それから少しして、息子がなんだか悩み顔。
「Ａ会が難しくなってきちゃって。」

公園が家からちょっと遠いとか、用事があるとか、飽きちゃったとか、みんな前ほど熱意がないみたい。
開始時は特別感やワクワクがあったけど、回を重ねると日常になってきて、優先順位が下がってくる。分かるぅ。

「予定や用事は仕方ないし、何だかんだ誰かは毎週いるし、集まれるときに遊んだらいいのでは？」
「そうなんだけどねぇ。僕は会長だから、みんなが楽しく過ごしてほしいんだよね。」

その後の日曜日のＡ会は1人や2人。
公園の他のお友達も一緒に遊ぶので人数的には支障はないけれど、でもＡ会メンバが少なくて残念な息子。
コミュニティ停滞期のテコ入れって悩ましいよね…。

## そしてコミュニティが終わる
実はこのＡ会が始まったのは1月。3学期。
春休みがきて、新学年になって、新しいクラスになる。
ちょうどいい終わり方かもなぁ…。

そして春休みの日曜日。
息子はいつも通り習い事が済ませ、そして帰り道に公園へ行きたいと言う。
「誰もいないと思うんだけど、でも念のためにいないってことを確認したいんだよ。」
そうね、会長としては確認したいね。

そして公園へ。やっぱり Ａ会の子はいなかった。
「うん、いないね。じゃあ、帰ろう！」
どういう気持ちなんだろうと思ったけど、すっきりさっぱりした表情。
3か月も続いてすごいね。会長頑張ったね。

こうして新学年を控えた3月、Ａ会は自然と終息を迎えた。

## 横で見ていて思ったこと
公園で遊びたいと毎週集まる6人のクラスメイト達、進級のタイミングで解散。
ただそれだけの事だけど、コミュニティの本質を見た気がします。

１つ目はコミュニティの自然発生。共通の目的（公園で遊ぶこと）があると人は集まるという、コミュニティの基本原則ですね。

2つ目は運営の課題と対応。小さなトラブルや時間とともに熱意が薄れる現象をどうするか。ルール作りや参加動機は、どのコミュニティでも見られる課題です。

3つ目はコミュニティのライフサイクル。目的を達成するか、目的がなくなればコミュニティは終わるのだから、やみくもなコミュニティ延命はしないほうがよいかもです。

だから指示で始まったコミュニティは盛り上がらない。
盛り上がらない原因をコミュニティ運営に求めるんだけど、そもそもそ最初にコミュニティの目的を確認しないといけない。

当たり前ですよね。でも忘れがちな気がします。
小さな集いとあなどるなかれ。学ばせていただきました！
OCI Compute(Oracle Linux 8) の SSH接続 がタイムアウトですぐ切れるので、防止するためにやった事メモ(Oracle Cloud Infrastructure)

下記の SSH接続 がデフォルトだと割と短時間(1分くらい？)で切れちゃうので、色々設定したことをメモしときます。
彡(ﾟ)(ﾟ)

```
PC → (Internet, SSH) → Public(踏み台) Compute(OL8) → (SSH) → Private Compute(OL8)
```

# やった事

(1). /etc/ssh/sshd_config の ClientAliveInterval と ClientAliveCountMax を 有効化した(30秒3回)。踏み台 と Private Compute の 両方で変更
(2). /etc/ssh/sshd_config の TCPKeepAlive を Yes にした。踏み台 と Private Compute の 両方で変更
(3). /home/opc/.ssh/config で ServerAliveInterval と ServerAliveCountMax を有効化した。踏み台で下記を設定
```shell
Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
```
(4). 上記の SSH設定を有効化するために Compute を再起動した。sshd の再起動でも良いのですが、念のため
(5). ターミナルソフト(※ワイの場合は Tera Term)の TCP KeepAlive を設定した。設定の保存を忘れずに。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110066/f4d79a3c-7280-495f-b47a-f542970b78bd.png)
(6). (追記) OCI BaseDB では /etc/profile の TMOUT を 600 → 86400 にすると良いという情報をいただきました。


以上です。他のオススメ設定が有ればコメントくださいね彡(^)(^)
並行処理の本質を理解するには？CPU・OS・スレッド・プロセスの仕組みから整理してみた

## はじめに

並行処理や並列処理という言葉を聞いたときに、  
「実際にどんな仕組みで処理されているのか？」と疑問を持ちました。

特にGoやNode.jsといった言語の「軽量スレッド」や「イベントループ」を理解するには、  
**そもそもCPUやOSの視点から処理の流れを捉えることが重要**だと感じました。

---

## 処理はどうやって実行されるのか？

最終的にプログラムの命令を実行するのは**CPU**です。  
CPUは電圧の高低（0と1）を読み取り、命令を1つずつ「カチカチ」と処理していきます。

このときCPUが実行する単位はスレッド（thread）です。

- **スレッド**：命令の流れそのもの（プログラムカウンタやスタック情報などを持つ）
- **プロセス**：スレッドを含む実行単位であり、メモリ空間やファイルディスクリプタなどの資源を持つ

つまり、実際にCPUで動いているのはスレッドであり、  
**プロセスは「スレッドが実行するための情報」を保持する器**ともいえます。

---

## マルチプロセスとマルチスレッドの違い

| 種類 | 実態 | メモリ共有 | 特徴 |
|------|------|-------------|------|
| **マルチプロセス** | 複数のプロセスを同時に実行 | ❌ 共有しない（完全分離） | 安定性が高いが切り替えコスト大 |
| **マルチスレッド** | 同一プロセス内の複数スレッドを実行 | ✅ メモリ共有する | 高速だが同期や排他制御が必要 |

---

## 誰がスレッドやプロセスを管理しているのか？

それはOS（カーネル）です。  
OSの中核にある「スケジューラ」が以下を管理しています。

- どのスレッド（またはプロセス）をいつCPUに割り当てるか？
- ブロックしたスレッドをどう再開するか？
- 複数のCPUコアがある場合、どのスレッドをどのコアで処理するか？

この仕組みを**コンテキストスイッチ**と呼びます。

> ✅ CPUコアが1つでも、スレッドを高速に切り替えることで「同時に動いているように見せる」  
> → これが **並行処理**

> ✅ 複数のCPUコアでスレッドを実際に同時に実行する  
> → これが **並列処理**

---

## まとめ：並行処理を支える土台

- **CPUはスレッド単位で処理を実行**
- **スレッドはプロセス内に所属**
- **プロセスはリソース（メモリやファイル）を持つ入れ物**
- **それらの切り替えや実行管理はOSカーネルが行う**
- **マルチスレッドもマルチプロセスも、最終的にはカーネルのスケジューラで制御されている**
【定性と定量、主観と客観に関する一考察】

定量は数字で表現される（ことが多い）。
だから、その数字が意味するもの（仮説）を汲み取ってあげる必要がある。
その代わり数字で示す分、客観性が高い。

一方で定性は、意味合いが直感的でわかりやすい。
その代わり人や状況によって意味合いが変わるので、客観性に欠ける。

じゃあ定量は定性に勝るか？
→Noだと思う。
仕事において客観的であることは重要だが、データを眺めるだけでは見えないものもあり、
比較できるものじゃない というのが自分の考え。

じゃあ定量と定性の関係性とは何か？
→「何をどう伝えるか」における役割の違いだと思う。
定性が「何を（伝えるか）」を担い、定量が「どう（伝えるか）」を担う。
だから、定性的なことは周りが納得しやすいよう定量的に伝えてあげる必要があり
定量的なことは何を伝えているのかを正確に汲み取る必要がある。

これが今のところ一番しっくりくる答え。
「空間上の3点をxy平面上に移動する変換行列を教えて下さい。」をAI先生に聞きました。sympyのソースコードで。 

# (本日の)ChatGPT先生へ
#### 質問リスト
```
# 質問リスト
1. 空間上の3点をxy平面上に移動する変換行列を教えて下さい。
2. sympyのソースコードを教えて下さい。
3. 上記の条件で、ユーザー定義関数で、入力の引数は、sympyのPointでお願いします。
4. ソースコードを１つにして下さい。
5. 私の質問をMarkdown形式でリスト化して出力して。Markdown形式でリストからアスタリスクは削除して。1行目に、# 質問リスト の文字を出力して。最後の質問も追加して下さい。追番を追加して下さい。Markdown形式で。
```
>実行結果の概要：
このスクリプトを実行すると、与えた3点の張る平面を XY 平面に一致させるための 4×4の同次変換行列 T が表示されます。
必要なら、この行列で他の点を変換する方法も追加できます！お気軽にどうぞ。

```python
import sympy as sp
from sympy.geometry import Point3D

def get_plane_to_xy_transform(A: Point3D, B: Point3D, C: Point3D):
    # ベクトル AB, AC を計算
    u = sp.Matrix(B - A)
    v = sp.Matrix(C - A)

    # 法線ベクトル（平面の法線）
    n = u.cross(v)
    n_unit = n / n.norm()

    # Z軸ベクトル
    z_axis = sp.Matrix([0, 0, 1])

    # 回転軸（n と Z軸の外積）
    axis = n_unit.cross(z_axis)
    axis_norm = axis.norm()

    # 回転角
    cos_theta = n_unit.dot(z_axis)
    theta = sp.acos(cos_theta)

    # Rodriguesの回転行列
    def rotation_matrix(axis, theta):
        axis = axis / axis.norm()
        x, y, z = axis
        c = sp.cos(theta)
        s = sp.sin(theta)
        C = 1 - c
        return sp.Matrix([
            [x*x*C + c,   x*y*C - z*s, x*z*C + y*s],
            [y*x*C + z*s, y*y*C + c,   y*z*C - x*s],
            [z*x*C - y*s, z*y*C + x*s, z*z*C + c  ]
        ])

    # 回転行列（軸がゼロ＝すでにXY平面の場合は単位行列）
    R = sp.eye(3) if axis_norm == 0 else rotation_matrix(axis, theta)

    # 平行移動ベクトル（点Aを原点へ）
    t = -R * sp.Matrix(A)

    # 同次変換行列（4x4）
    T = R.row_join(t)
    T = T.col_join(sp.Matrix([[0, 0, 0, 1]]))

    return T

# === 使用例 ===
if __name__ == "__main__":
    A = Point3D(1, 2, 3)
    B = Point3D(4, 5, 6)
    C = Point3D(7, 8, 10)

    T = get_plane_to_xy_transform(A, B, C)

    print("変換行列 T:")
    sp.pprint(T, use_unicode=True)
```

# Gemini先生へ

# copilot先生へ

# いつもの? sympyの実行環境と 参考のおすすめです。
[(テンプレート)](https://qiita.com/mrrclb48z/items/00dd08b0317069be9342)

https://qiita.com/mrrclb48z/items/b6351b48e47bcf6265c0

# いつもと違うおすすめです。
### wikipedia
Tailwind CSS を導入しただけなのに詰んだ話（macOS + Node.js + M1）

はじめに

最近、FastAPI と連携するための簡単なフロントを Tailwind CSS で作ろうとしたんですが、
ただ CLI を使って導入したいだけなのに、思った以上にハマってしまったので備忘録としてまとめておきます。

環境はこちら：
	•	macOS（M1チップ）
	•	Node.js v18.20.2（n で管理）
	•	Tailwind CLI を使って output.css をビルドするシンプル構成


結論から言うと

npm 経由ではどう頑張っても CLI が使える状態にならなかったので、公式のバイナリを直に落としてきて解決しました。

ハマったポイント

① Node.js のバージョン、なぜか切り替わらない？

普段どおりに `n` で v18.20.2 を入れたはずなのに、
`node -v` してみたら…まさかの v18.15.0。なんで？！

```bash.
node -v
# => v18.15.0
```

```zsh.
export PATH="/usr/local/n/versions/node/18.20.2/bin:$PATH"
```

その後 source ~/.zshrc で反映。

② npx tailwindcss init -p がエラーになる

```bash.
npm ERR! could not determine executable to run
```
→ tailwindcss をインストールしたはずなのに、node_modules/.bin/tailwindcss が存在しない。


```bash.
ls node_modules/.bin/tailwindcss
```
=> No such file or directory

npm uninstall → install を何度繰り返しても改善されず、依存関係も問題なさそうなのに解決しない…。

解決策：バイナリを直で落とす
結局、以下の手順で公式 CLI を手動でセットアップ。
```bash.
mkdir -p ./bin

curl -sLO https://github.com/tailwindlabs/tailwindcss/releases/latest/download/tailwindcss-macos-arm64

mv tailwindcss-macos-arm64 ./bin/tailwindcss

chmod +x ./bin/tailwindcss
```
無事、./bin/tailwindcss が動作。やっと一息…！


```bash.
./bin/tailwindcss -i ./src/input.css -o ./dist/output.css --watch
```

| 詰まったポイント                        | 原因                                                       | 解決法                                                                 |
|----------------------------------------|------------------------------------------------------------|------------------------------------------------------------------------|
| Node.jsのバージョンが切り替わらない    | Anacondaの `/bin/node` が優先されていた                   | `export PATH=...` を `.zshrc` に追記し、`source ~/.zshrc` で反映       |
| `npx tailwindcss init -p` が動かない   | tailwindcss の CLI が `node_modules/.bin` に存在しない     | `tailwindcss` の公式バイナリをDLし、`./bin/tailwindcss` に手動配置    |
| `open index.html` が開けない           | ファイルのパスが違っていた or 作成されていなかった         | `dist/index.html` を明示的に開く or 事前に自分で作成                  |



さいごに

たった1つのツール導入でも、環境によってはこんなに時間を取られるんだと痛感しました。
この記事が同じように詰まってる方の助けになれば幸いです🙏