OmniAICreator/Qiita-1.07M huggingface dataset:
046 AI屋さんの　ペンフレンドは　LLMにトークン全文入力　クライアント編

046 AI屋さんの　ペンフレンドは　LLMにトークン全文入力　クライアント編


pythonやLLMやAIエージェントを使って
メール経由で、受信も送信も出来ることが確認できました。

クライアントとして、分かりやすい
「お客様からの問い合わせ窓口」　を想定していますが、
ここまでできれば、クライアントの応用は色々できます。

pythonとメールがあれば、ネットワークは十分です。
webアプリもwebAPIもDBもストレージも　なくても問題ありません。
既存のメールのみでシステム構築可能です。

クライアント側は、
　カメラで撮影してopenCVとpythonで処理します。
　測定器の値をDLLとpythonで処理します。
　スマホのメールでQRコード帳票も処理できます。
あとは、処理後にメール送信してあげれば
クライアント側は、完了です。


---
---


pythonと　powerシリーズ連携


https://qiita.com/bono0/items/49f76d215a0d118cc27b



サーバー側での
メールの受信後の処理は、前回同等です。
さらに、企業でのマイクロソフト製品による
メール連携は容易に可能です。




Azure、powerシリーズとの連携も

　メール受信
　　→　ONEDRIVE
　　→　python 

で　追加料金不要で利用可能です。
完璧です。
もちろん、pythonを使わなくても、okです。
これ以外のコネクタでも、色々応用可能です。
お好みでお選びください。



---


目次

https://qiita.com/bono0/items/dc1d000c98af7e07c9a7


メールを用いた、クライアントアプリの開発も

　046 AI屋さんの　ペンフレンドは　LLMにトークン全文入力　クライアント編

完成です。おめでとうございます。



ー以上ー
自分カンペ制作用Qiitaメモ

G検定・DS検定の学習＆カンペ作りの過程で作りました。随時増やします

## ※よく参照させてもらっているページ

https://qiita.com/hennin/items/7ee58dd7d7c013a23be7

## +＠の覚え書き

## ①ページ内リンクに丸数字は不要

たとえば、これに対して、ページ内リンクをつける場合
```
[①ページ内リンクに丸数字は不要](#①ページ内リンクに丸数字は不要)　👈　いけない
[①ページ内リンクに丸数字は不要](#ページ内リンクに丸数字は不要)　👈　いける
```

## ②ページ内リンクを付ける際、半角スペースは「-（ハイフン）」、全角スペース・全角括弧は省略
```
## LSTM（Long Short Term Memory）
```
にリンクさせたい場合、以下のように記述する
```
[LSTM](#lstmlong-short-term-memory)
```

## ③数式の括弧を良い感じに引き伸ばす

例えば、$\left( \frac{1}{x^2 + 1} \right)$ みたいに書きたい場合

```
\left( \frac{1}{x^2 + 1} \right)
```

## ④他のQiitaの見出しにリンクをつける
### 〇記事A
```
<h2 id="見出し2">見出し2</h2>
```
もしくは
```
###・・・　見出し2
```
となっている場合に

### 〇記事B
```
[別記事の見出しへ](https://qiita.com/ユーザー名/items/記事ID#見出し2)
```
と記述すると他記事の見出しにリンクできる。

### 参考

https://qiita.com/thinking-weed/items/39a889709da8d4d3fab0

の[勾配降下法（Gradient Descent）](https://qiita.com/thinking-weed/items/39a889709da8d4d3fab0#%E5%8B%BE%E9%85%8D%E9%99%8D%E4%B8%8B%E6%B3%95gradient-descent)に下記のリンクをつけた場合
```
https://qiita.com/thinking-weed/items/39a889709da8d4d3fab0#%E5%8B%BE%E9%85%8D%E9%99%8D%E4%B8%8B%E6%B3%95gradient-descent
```
排他的論理和( XOR )の基本 ^

「論理演算」シリーズから、今回は`XOR`（ビット排他的論理和）の基本をメモ。

## <br>🧩 問題ざっくり紹介

入力された `0` と `1` の2つの値を`XOR`して、結果（`0`または`1`）を出力。

例：`0 1` → `1`、 `1 1` → `0`

## <br>✅ 論理和と何が違う？

### 😵 NG例：論理和で無理やり書いてみた
```js
console.log(A && !B || !A && B); 
// → 一応動くけど、読みにくいし型が boolean
```

### <br>✅ OK例：ビット演算でスッキリ
```js
console.log(A ^ B); 
// → AとBが「違ってたら1」
```
JavaScriptでは `^` は ビット単位のXOR演算子。

#### 🔑 ポイント：
- OR（論理和）は どっちかが `1` なら `1`
- XOR（排他的論理和）は 違ってたら `1` 、同じなら `0`

## <br><br> おまけ　🔁 応用ワザ3選（全部XORでできる）

- ユニークな値を1個抽出
```js
const arr = [2, 3, 5, 3, 2];
console.log(arr.reduce((a, b) => a ^ b)); // → 5
```


<br>

- フラグのON/OFF切り替え
```js
let flag = 0;
flag = flag ^ 1; // 0→1
flag = flag ^ 1; // 1→0
```
<br>

- 変数スワップ（aとbを入れ替える）

```js
let a = 5;
let b = 10;

a = a ^ b;
b = a ^ b;
a = a ^ b;

console.log(a, b); // → 10, 5
```
通常のスワップ（`[a, b] = [b, a]`）



<br><br>[🐻僕の失敗談と解決話！🐈](https://paizabeginner.wordpress.com/2025/04/26/paiza%e3%81%a7%e5%9f%ba%e6%9c%ac%e3%83%9e%e3%82%b9%e3%82%bf%e3%83%bc%ef%bc%9a%e6%8e%92%e4%bb%96%e7%9a%84%e8%ab%96%e7%90%86%e5%92%8c-xor-%e3%81%ae%e5%9f%ba%e6%9c%ac/)

<br><br><br><br><br>

### ※追記： 　 ユニークな値を1個抽出　について
```js
const arr = [2, 3, 5, 3, 2];
console.log(arr.reduce((a, b) => a ^ b)); // → 5
```



この方法で見つかるのは、「ユニークな値」というより、

「奇数回出現した値」

なんです！！

なぜかというと、

- 同じ値同士を XOR すると 0 になる
- 0 と値を XOR すると、その値そのままになる

から。

たとえば：
```
2 ^ 2 = 0
3 ^ 3 = 0
0 ^ 5 = 5
```
こうして、偶数回出現したものは全部消えて、奇数回出たものだけ残るわけですね！
<br>

🧪 例：ちょっと複雑な配列
```js
const arr = [2, 3, 2, 5, 2, 5, 3, 5];
console.log(arr.reduce((a, b) => a ^ b)); // → 7
```

この配列、よく見ると…

- 2 は 3回
- 3 は 2回
- 5 は 3回

つまり、

2 と 5 が「奇数回出現」してる！

そして、2 と 5 を XORすると：
```js
2 ^ 5 
```

計算

2 を2進数で書くと → 10
5 を2進数で書くと → 101

これをXORすると…
```
  010
^ 101
＝111
```
つまり、7！

✅ なので、出力結果は 7 になるんです！

<br>
まとめると、

- 偶数回出現する数はXORで打ち消しあう（0になる）
- 奇数回出現する数だけ残る
- 最後に残った数同士をXORする！



#### 🚨 注意点まとめ

ユニークな値（1回だけ出た値）を取り出している　
→　奇数回出現した値を XORでまとめた結果

つまり、

「奇数回出現する値が1個だけ」なら、その値がそのまま結果になる。

でも、

奇数回出現する値が2個以上あると、XORのルールに従ってビット単位で計算された結果になる。

@ffgogfb454　さん　コメントで教えてくれてありがとうございました(^^ゞ
TweetApp製作記

# １．はじめに
こんにちは、普段は競プロを中心に活動しているmikan0131です。

普段はC++を愛用していますが、今回は、Webアプリケーションに興味を持ったので、PythonのモジュールFlaskを使ってSNS「TweetApp」の開発をしていこうと思います。（ちなみに「TweetApp」という名前はプログラミング学習サイト「Progate」のコースのなかで実践用として開発するアプリに名前から付けました。「Progate」は初心者にもお勧めです！ぜひ使ってみてください！）

※ただし、この記事は、2025年灘校文化祭「weave」のパソコン部部誌の記事を詳細にしたものなので、そちらを先にみていただくとわかりやすいかもしれません。

# ２．今回作るアプリ「TweetApp」の詳細
今回は、「動的なWebサイト」、つまりWebアプリケーションを作っていくわけですが、この言葉の定義はご存じでしょうか？
 
「動的なWebサイト」は、「静的なWebサイト」と違って、閲覧者によってレスポンスが違うWebサイトのことです、例えば、今回開発するSNSやFacebook、Instagramなどのブログなど、ログイン機能がついてるものは大体そうです。そのレスポンスはWebサーバーのデータベースやブラウザのセッション（Cookie）からデータを引き出して作成されます。

![img_one.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3757120/64a38fda-2316-47e9-af80-509b1cb67eb7.png "静的なWebサイトと動的なWebサイトの違い")

では、実際に「TweetApp」を作っていきましょう！

# ３．機能説明
では、具体的にどのような機能を付けるか説明します。箇条書きにすると、こんな感じです。
```
ログイン機能
├── アカウント登録
├── ログイン認証
└── ユーザーの情報管理
掲示板機能
├── グループの作成
├── メッセージ送信
├── メッセージ編集・削除
├── グループへの招待
└── グループの退会
個人チャット機能
├── メッセージ送信
├── ともだちを削除
├── ともだち申請
└── 申請受け入れ・拒否
ともだち・グループ検索
```
いやー、かなりたくさんありますね。でも、やろうと思った当時はこんなに大変とは思ってなかったわけですから、我ながら向こう見ずでしたね(笑)
機能がたくさんあって一つの記事では書けないので、いくつかの記事に分割しようと思います！それでは、長い記事になりますが、よろしくお願いします！

# ４．記事一覧
事前準備・ホームページを作ろう！

# ５．「TweetApp」のソースコードについて
今回作成したアプリはGithubに公開してるので、ぜひ、見てみてください！

https://github.com/mikan0131/TweetApp
PythonのLoggingについて（基本編）

## Loggingとは
Python標準搭載のログ機能のモジュール。
ログレベルを制御できたり、出力するメッセージや出力先を柔軟に変更できて便利です。
公式ドキュメントを読みながら、実際に手を動かしました。
https://github.com/shunyonai1996/python_logging

pythonの実行環境がある方なら
`basic_logging.py`の見たい箇所のコメントアウトを解除して、
`python basic_logging.py`を実行すると、出力結果の確認ができます。

[logging — Logging facility for Python](https://docs.python.org/3/library/logging.html)

## 基本
### 標準出力にログを出力
```python
import logging

logging.debug('Detailed information, typically of interest only when diagnosing problems.')
logging.info('Confirmation that things are working as expected.')
logging.warning('An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.')
logging.error('Due to a more serious problem, the software has not been able to perform some function.')
logging.critical('A serious error, indicating that the program itself may be unable to continue running.')
```
標準出力
```bash
$ python basic_logging.py
WARNING:root:An indication that something unexpected happened, or indicative of some problem in the near future (e.g. ‘disk space low’). The software is still working as expected.
ERROR:root:Due to a more serious problem, the software has not been able to perform some function.
CRITICAL:root:A serious error, indicating that the program itself may be unable to continue running.
```

### 特定のファイルに出力
```python
import logging

logger = logging.getLogger(__name__)
# 以下で出力先やログレベルを制御
logging.basicConfig(filename='./logs/example.log', encoding='utf-8', level=logging.DEBUG)
logger.debug('This message should go to the log file')
logger.info('So should this')
logger.warning('And this, too')
logger.error('And non-ASCII stuff, too, like Øresund and Malmö')
```
example.logに出力
```example.log
DEBUG:__main__:This message should go to the log file
INFO:__main__:So should this
WARNING:__main__:And this, too
ERROR:__main__:And non-ASCII stuff, too, like Øresund and Malmö
```
※補足：
`basicConfig()`は1度しか読み込まれません。
途中から別の設定を定義しようとしても、その定義は無効化されます。
既存のハンドラ削除してから再度定義し直すことは可能ですが、ここでは触れません。

## 具体的な出力フォーマット
### 変数埋め込み
```python
import logging

variable = '真ん中（変数）'
logging.warning('%s variable %s', '最初', '最後')
```

標準出力
```bash
$ python basic_logging.py
WARNING:root:最初 真ん中 最後
WARNING:root:最初 真ん中（変数） 最後
```
※`%s`はプレースホルダー。Loggingが古いモジュールのため、`str.format()`などの関数に対応していない（対応させる方法もあるが、ここでは割愛）。

### 動的に出力内容を変える
Loggingがあらかじめ用意している属性を設定可能。

公式に詳しい属性が書いてます。気になる方は参考にしてください。
[LogRecord attributes](https://docs.python.org/3/library/logging.html#logrecord-attributes)

```python
logging.basicConfig(format='%(asctime)s:%(levelname)s:%(message)s',
                    datefmt='%Y-%m-%d %H:%M:%S',
                    level=logging.DEBUG
                    )
logging.debug('debugのmessage')
logging.info('infoのmessage')
logging.warning('warningのmessage')
```
標準出力
```bash
$ python basic_logging.py
2025-04-26 16:54:19:DEBUG:debugのmessage
2025-04-26 16:54:19:INFO:infoのmessage
2025-04-26 16:54:19:WARNING:warningのmessage
```

Advanded Tutorialについての記事も後日投稿予定です。
理訓許段神はrik un kotan kamuyなのか

金田一京介『言語研究』(東京: 河出書房、昭和8年11月)のp.249には、以下の記述がある。

> 倭名鈔式内の神社の中で、奥州濱街道最北のものが、氣仙郡の理訓許段の社である。リクンコタンは多分地名であらうが、今のアイヌ語では、リクンコタン(rik-un-kotan)は「上の村」「高い所に在る村」である。釧路厚岸郡にあるリコタン「上村」「高村」といふも同じである。北海道では釧路の足寄郡にある陸別のRik-unがそれで、高川の意味である。理訓許段の社は今の氷上山の神社に比定され、高處にある故さういふ名が附いてゐることは、合點し得るのである。

私(安岡孝一)は、この説明に合点がいかない。というのも、氷上山頂西側の[理訓許段神社](https://maps.gsi.go.jp/#15/39.056700/141.650979/)は、元々は麓にあった神社を山頂に移設したもので、最初から氷上山にあったわけではない(cf.新野直吉: 理訓許段神社, 式内社調査報告, 第14巻(昭和61年2月), pp.998-1004)。ただ、麓のどこにあったのかは議論があって、高田町長砂の[本宮神社](https://maps.gsi.go.jp/#15/39.015566/141.637728/)(cf.上部郁雄『神道大系　氷上神社・社記抜粋』(高田町: 氷上神社、平成19年5月))と、赤崎町鳥沢の[尾崎神社奥宮](https://maps.gsi.go.jp/#15/39.025741/141.736993/)(cf.岩崎淺之助『赤崎村史料』(赤崎村: 山本周太郎、大正8年5月))が、それぞれに理訓許段神社の「跡地」を主張しており、尾崎神社には宝物としてinawが収められている。

正直どっちなのかわからないので、両方とも現地に行ってみた。行ってみたところ、どちらも小高い丘の急斜面にあり、いずれも海が見えるものの、斜面がきつくて「村」(kotan)など作れそうにない。これ、どちらも違うんじゃないか、と思ったのだが、ハタと別の可能性に気づいた。理訓許段を「上の村」(rik un kotan)と読む、という説(cf.竹内運平『東北開發史』(東京: 現代之科學社、大正7年7月), p.117)がそもそも間違っているのであって、仮にアイヌ語だとしても、たとえばrik un kotorなど、他の可能性を考えるべきなのではないか。

だとすると、そもそも理訓許段神とは何なのか、という問題に突き当たる。私個人としては、[アイヌ語訳『五倫名義解』](http://hdl.handle.net/2433/286023)に出てくるレクトコトカモイ(rik to kotor kamuy)が気になるところだが、微妙に響きが違う上に、別海町は離れすぎている。さて、フリダシに戻った感じなのだが、どう調べていけばいいかな。
リスト追加

リストの追加を実施。
現状はリストとｓDictionary型を使用。キーが存在する場合は更新指定に従う。
~~~
'------------------------------------------------------------------------------
' リスト追加
'------------------------------------------------------------------------------
Public Function F_List_GetAdd( _
        ByRef aRtn As Dictionary, _
        ByVal aKey As Variant, _
        ByVal aItem As Variant, _
        Optional ByVal aUpdtFlg As Boolean = True) As Boolean
    Dim wkRtn As Dictionary: Set wkRtn = aRtn
    
    '引数チェック
    Select Case VarType(aKey)
        Case vbEmpty, vbNull
            '上記以外にもあるがそもそも指定しないので問題なし
            Exit Function
        Case Else
            '問題なし
    End Select
    
    'リスト生成
    If wkRtn Is Nothing Then
        Set wkRtn = New Dictionary
    End If
    
    With wkRtn
        'キーが存在しない場合
        If .Exists(aKey) <> True Then
            .Add aKey, aItem
        'キーが存在する場合
        Else
            '更新許可ならば上書き
            If aUpdtFlg = True Then
                M_Common.S_SetItem .Item(aKey), aItem
            Else
                Exit Function
            End If
        End If
    End With
    
    Set aRtn = wkRtn
    F_List_GetAdd = True
End Function
~~~
ssh Tips

# ssh接続手順
1. クライアントPCとサーバPCにsshインストール(sshクライアントとsshd)
    ```bash
    sudo apt update
    sudo apt install -y ssh
    ```
1. クライアントからサーバへssh接続できるか確認
    ```bash
    ssh <username>@<ipaddr>
    ```
1. 鍵設定
    1. クライアントで鍵生成
        ```bash
        ssh-keygen -t rsa -b 4096
        ```
    1. クライアントからサーバへ公開鍵をコピー
        ```bash
        ssh-copy-id -i ~/.ssh/id_rsa.pub <username>@<ipaddr>
        ```
1. クライアントからサーバへパスワード無しでssh接続できるか確認
    ```bash
    ssh <username>@<ipaddr>
    ```
VSCodeのVim拡張で日本語入力時の問題を解決する

# VSCodeのVim拡張で日本語入力時の問題を解決する

VSCodeでVim拡張機能を使っている日本語ユーザーにとって、全角入力モードからのNormalモード移行は非常にストレスになります。  
この記事では、AutoHotKeyを使ってこの問題を解決する方法を紹介します。

## 問題の背景

VSCodeでVim拡張を使用している際、特に日本語ユーザーが直面する典型的な問題があります：

- 全角入力モードでテキストを入力した後、Escキーを押してNormalモードに移行する
- しかし、IMEは依然として全角モードのままなので、Vimコマンドが正常に機能しない
- コマンドを入力するには、毎回手動でIMEを半角モードに切り替える必要がある

この追加操作は非常に煩わしく、Vimの効率性を大きく損なっています。

## AutoHotKeyによる解決策

以下の手順で、EscキーでIMEを自動的にオフにする設定を行います：

### 準備：Windowsの設定

1. Windowsの設定から「IMEの設定」を開く
2. 「キーとタッチのカスタマイズ」を選択
3. キーの割り当てをオンにし、変換キーの割り当てを「IME-オフ」に設定

![imesetting.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1684949/26640d4e-697c-492f-bebe-cb42de808d50.png)

### AutoHotKeyのセットアップ

1. [AutoHotKey v1.1系（バージョン2.0未満）](https://www.autohotkey.com/)をダウンロードしてインストール
2. 以下のスクリプトを含む`XXXX.ahk`ファイルを作成

```
#IfWinActive ahk_exe Code.exe  ; Visual Studio Codeがアクティブなときのみ動作

~Esc::
    ; Escキーを送信
    Send {Esc}
    
    ; 変換キーを送信 (IMEオフを割り当て済み)
    Send {vk1Csc079}  ; 変換キーでIMEをオフにする
    return

#IfWinActive
```

3. `Win + R`キーを押し、`shell:startup`と入力してスタートアップフォルダを開く
4. 作成した`.ahk`ファイルをこのフォルダに配置する
5. `.ahk`ファイルをダブルクリックして実行する

これ以降、システム起動時に自動的にスクリプトが実行されるようになります。

## スクリプトの解説

このAutoHotKeyスクリプトの仕組みを解説します：

- `#IfWinActive ahk_exe Code.exe` - このコマンドは、以下のショートカットがVSCode（Code.exe）がアクティブなウィンドウの場合のみ有効になるよう指定します。
- `~Esc::` - チルダ記号（~）は、Escキーの元々の機能を維持したまま、追加の処理を行うことを意味します。
- `Send {Esc}` - Escキーの通常の機能を実行します（Vimのノーマルモードへの移行など）。
- `Send {vk1Csc079}` - この命令は「変換キー」に相当するキーコードを送信し、既に設定済みのIMEオフ機能を実行します。
- `return` - スクリプトの処理を終了します。
- `#IfWinActive` - 条件付きホットキーの終了を示します。

## 注意点

このスクリプトは、VSCodeがアクティブな間は常に機能します。つまり、VSCode内でEscキーを押すと、自動的にIMEがオフになります。これはVim操作においては理想的な動作ですが、場合によっては不便に感じることもあるかもしれません。

より高度なカスタマイズが必要な場合は、VSCode拡張機能の開発も検討する必要があります。

## まとめ

この簡単な設定により、VSCodeのVim拡張機能を使用する際のIME切り替えのストレスから私は解放されました。  
特に日本語入力を頻繁に行うプログラマーにとって、この小さな改善が大きな生産性向上につながると思います!
CLIでカードゲーム「War Game」を作った話

**はじめに**

本記事では、プログラミングスクール「アプレンティス」でチーム開発として制作したカードゲーム『War Game』を紹介します。
<br>
開発リポジトリはこちらです：
👉 [https://github.com/zen4399/war-game](https://github.com/zen4399/war-game)
<br>
**War Gameとは？**

『War Game』は、シンプルで直感的なルールを持つCLI（コマンドラインインターフェース）ベースのカードゲームです。

プレイヤー同士がカードを出し合い、カードの強さを比較して勝敗を決定します。

ゲームは2〜5人まで同時プレイ可能。

ターン制で進行し、カードが尽きるまで続きます。

使用した技術

言語：Python

開発環境：VSCode、WSL

<br>

**プロジェクトの構成**

プロジェクトはモジュール化され、以下の構成になっています：
war_game/
├── core/
│   ├── base_game.py
│   ├── card.py
│   ├── deck.py
│   └── player.py
└── steps/
    ├── step1_game.py
    ├── step2_game.py

core: ゲームのロジックやカード、プレイヤーの基礎クラスを管理。

steps: 段階的に機能を追加した実行用のスクリプト。
<br>

**開発で工夫した点**

モジュール化

ゲームの基本的なロジックを再利用可能なモジュールに分割し、段階的に機能を拡張する設計を取りました。これにより、新しいルールの追加やバグ修正が簡単に行えるようになりました。
AI駆動開発を体験してみた（初心者用）

## はじめに
今回は前回の記事で作成したアプリを実際にCursorを使ってAI駆動開発を体験していこうと思います
前回の記事はこちら！
https://qiita.com/totacho/items/dc1c3f82164b759c88d5

## 要件
文字並び替えクイズのアプリを作っているのですが、現在は"たこやき"の１問のみ…
このままではとんだクソアプリなので、jsonファイルから呼び出すようにしましょう！

## アプリの修正
ということでとりあえず、プロジェクト内にassetsフォルダを作成してこの中に以下のようなJSONファイルを用意しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/8f3e8a91-7931-4d22-a772-0f4d71a2644b.png)

他のソースは何もいじっていません。
ここからCursorに移動して、下記のようにざっくりなプロンプトを入力して…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/ebd0c0fd-0c8e-4fc0-81b9-8a8e995cfd88.png)

実行すると、下記のようにヒントをくれたのかなと思っていたら…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/6e4986a4-8d12-4673-be8b-be66a418e3f9.png)

なんと修正までしてくれてます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/5b815656-5e90-4c60-bc77-40ce6d6497aa.png)

yamlファイルまで修正していました。
プロジェクト内全体が修正範囲なんですね！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/e81479c9-c67b-4543-b5f3-33aeeebe089d.png)

動作確認してませんが、ポテンシャルを引き出すために追い打ちかけましょう（笑）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/f8614bd2-3961-4b8c-8ef1-8819cf21d9b1.png)

素直に応じるCursor
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/0be3b0d7-d48d-40b3-a652-216f73456122.png)

それでは動作確認してみましょう。

## 動作確認
動作確認してみます。
こちらが修正前
![maegazou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/e22fb166-999c-42ae-8493-b04df6be9cef.png)


そしてこちらが修正後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1076167/e058d267-62a3-4740-a8c6-63509902d9e6.png)


圧巻です…
まず、問題が"たこやき"ではなくなっているのでJSONファイルが読み込まれていますね！
UIも指示したことは適用されています！（余計なものもついてますが）
つまり今回のプロンプトはすべて達成されていると言えるでしょう！

## 最後に
今回は簡単にAI駆動開発を体験してみました。
感想を一言で表すなら「衝撃」でした。
AI駆動開発というトレンドについて少し遅めではありますが、とても貴重な体験でした。
ただ最近はAI依存なんかの言葉もよく耳にするようになり、「使い過ぎはよくない」とは言いませんが、
自信の『コーディングスキルが低下しそう』や思わぬ『脆弱性が作りこまれている可能性』もあるなぁと思っています。これらのことを踏まえてコード修正後は必ず確認することは欠かせません。
あとは複雑な処理となるとプロンプトの組み方にかなり苦戦しました。Cursor用のプロンプトはChatGPTで具体例を投げて作成していたんですが、最終的に自分で実装していました…
今後のエンジニア、プログラマが目指すべきところが少しわかった気がします。

最後に今回のツール、サービス等は基本無料（無料枠内）ですが、使う前にコスト（お金）については十分調査しましょう。
ということで以上！
『マスタリングTCP/IP 入門編』学習記録とTCPの整理

## はじめに

ネットワークについて学びたいと思い、いろいろと調べてみたところ、本書『マスタリングTCP/IP 入門編』がよくおすすめされていたため、手に取ってみました。

本記事では、特にTCPに関する部分について、自分が気になった点や重要だと感じたポイントを、自分なりに整理してまとめていきます。

## TCP (Transmission Control Protocol) 

TCP/IPには、TCPとUDPという2つの代表的なトランスポートプロトコルが使われています。

TCPは、接続の確立や確認応答などを通じて信頼性の高い通信を提供するプロトコルである一方、UDPは、接続の確立を行わずにデータを送受信する軽量なプロトコルです。

本記事では、TCPの信頼性を支える仕組み、通信性能を向上させるための制御機構、ネットワークの利用効率を高める仕組みについて整理していきます。

## 信頼性を実現する仕組み

### シーケンス番号と確認応答（ACK）

TCPでは、**シーケンス番号**と**ACK（確認応答）**を用いて、送信データが正しく届いたかどうかを確認しながら通信を行います。

シーケンス番号とは、送信されるデータ部分の先頭バイトを示す番号です。これにより、受信側はパケットの順序を正しく並べ替え、欠落したデータを検知できます。

ACK（Acknowledgement）とは、受信側がデータを正しく受け取ったことを送信側に知らせる応答であり、次に期待するシーケンス番号を送信側に通知します。

具体的な流れは以下の通りです。

1. 送信側が「シーケンス番号1、データ長200」のデータを送信
2. 受信側は、1〜200バイト分のデータを受信し、「次に期待するシーケンス番号＝201」としてACKを返す
3. 送信側はACKを受け取り、次に「シーケンス番号201、データ長300」のデータを送信
4. 受信側は、201〜500バイト分のデータを受信し、「次に期待するシーケンス番号＝501」としてACKを返す

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3841606/973e609f-ed99-4d67-ae33-fd28b976bfb5.png)

このように、どこまでデータを受信したかを明示的にやり取りすることで、信頼性の高い通信を実現しています。

また、データやACKがネットワークの途中で失われた場合には、後述する再送制御によって、失われた情報の補完が行われます。

### 再送制御

TCPでは、データやACKが途中で失われた場合に備えて、再送の仕組みが用意されています。主なパターンは次の2つです。

ケース1：送信データが消失した場合

1. 送信側がパケットを送信
2. パケットがネットワーク上で消失
3. 受信側は何も受信しないため、ACKを返さない
4. 送信側はACKを待つが来ないため、一定時間後に再送
5. 受信側が再送されたパケットを受信し、ACKを返す

ケース2：ACKが消失した場合

1. 送信側がパケットを送信
2. 受信側がACKを返す
3. ACKがネットワーク上で消失
4. 送信側はACKを待つが来ないため、一定時間後に再送
5. 受信側はすでに受信済みのデータを再度受け取るが、シーケンス番号に基づいて重複と認識して無視し、ACKを返す

このように、ACKが返ってこなければ何らかの問題が発生したと判断し、送信をやり直すことで、確実な通信を可能にしています。

## 性能を向上させる制御機構

### ウィンドウ制御

パケットを1つ送るごとにACKを待っていたのでは、通信効率が非常に悪くなります。

そこでTCPでは、一定範囲内で複数のパケットを連続して送信するウィンドウ制御が行われます。これにより、ACKを待たずに複数のデータを送ることが可能となり、パフォーマンスが大きく向上します。

ACKによって受信状況は正しく把握されるため、信頼性も保たれます。

### フロー制御

受信側が処理できる以上の量のデータを送信されてしまうと、バッファが溢れ、再送が必要になり、逆に効率が落ちてしまいます。そこで、受信側が自分の受信可能なバッファサイズを送信側に通知することで、過剰な送信を抑制します。これがフロー制御です。

### 輻輳制御

ネットワークがすでに混雑している場合に、さらに大量のデータを送信すると、輻輳が悪化し、全体の通信効率が低下します。

TCPでは、初めは少量のデータを送り、問題がなければ徐々に送信量を増やすという仕組みで輻輳を回避します。これが輻輳制御です。

## ネットワークの利用効率を高める仕組み

### Nagleアルゴリズム

送信すべきデータがあったとしても、そのデータ量が少ない場合にすぐ送信してしまうと、送信回数が増えてしまいます。

そのため、送信を遅らせることになり、ある程度の遅延時間が発生してしまいますが、最大セグメント長（MSS）に達したデータをまとめて送信することで、ネットワークの利用効率を向上させることができます。

### 遅延確認応答

データを受信した瞬間にACKを送信すると、ACKが何度も送られてしまい、ネットワークの利用効率が低下してしまいます。

ACKは「どこまでのデータを受信したか」を伝えるだけなので、複数のデータを受信した場合には、最新の「どこまでのデータを受信したか」の情報があれば十分です。

そのため、データを受信してもすぐにACKを送信せず、少し遅らせることで、ACKの送信回数を減らし、ネットワークの利用効率を向上させます。

### ピギーバック

ピギーバックとは、簡単に言えば、データの送信を相乗りさせる仕組みです。

送信したいデータと、返信としてのACKやその他のデータを1つのパケットにまとめて送信することで、ネットワークの利用効率を高めることができます。

## 感想

- ネットワークの体系的な知識だけでなく、さまざまなプロトコルについても幅広く紹介されていたため、理解が深まりました
- TCPに関しては、信頼性や効率を支える様々な工夫を知ることができました
css 要素がヘッダーの後ろに隠れてしまう(position: fixed、position: sticky)

# 問題
メッセージを入力すると、入力したメッセージが、ヘッダーの後ろに隠れてしまっていた。

メッセージが隠れている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881019/e8402be2-9a13-422e-bde8-8b2430cd8284.png)

```
position: fixedの場合
/* position: fixed
要素はビューポート（画面の表示領域）を基準に配置される
headerはbodyのレイアウトに影響を与えず、bodyの高さには含まれなくなる  */

header {
	// 他省略
	position: fixed;
}
```
# 原因
position: fixed;を使用しているため、ヘッダーが通常のレイアウトフローから外れ、bodyの高さに含まれなくなっている。
その結果、chat-containerのmargin-topが正しく適用されず、メッセージがヘッダーの後ろに隠れてしまう。


# 解決方法
```
position: sticky;を使う

/* position: sticky;
要素がスクロールに応じて動き、特定の位置で固定される
親要素の範囲内でのみ固定される 
*/

header {
	// 他省略
	position: sticky;
}
```

メッセージを表示できた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3881019/04eccbc0-8672-4d55-bf65-c60af966cc5f.png)

# 終わりに
devツールを使いながら細かい部分まで見ることになり、勉強になりました！
Apple Silicon Mac で Neovim v0.9.5 をローカルビルドする手順

## はじめに

vscodeやcursorの拡張機能からnvimを使っているが、v10からnvimとの同期がちょくちょく切れる。
v0.9.5に戻せばこの現象が回避できる模様なので、個人的なメモとして残す。

## 前提
	•	M1 Mac (Apple Silicon)
	•	OS: macOS Sonoma
	•	Homebrewがインストール済み
	•	Neovimの init.lua など設定準備済み

## やること一覧

### 1. 必要パッケージのインストール

```
brew install ninja cmake gettext
brew install libtool automake cmake pkg-config unzip curl doxygen
brew install luv libtermkey libvterm tree-sitter msgpack
brew install luajit
```

### 2. luarocks で Lua module (lpeg, mpack) をインストール

```
brew install luarocks
```

# luarocks でインストール

```
luarocks --lua-dir=/opt/homebrew/opt/luajit install lpeg
luarocks --lua-dir=/opt/homebrew/opt/luajit install mpack
luarocks --lua-dir=/opt/homebrew/opt/luajit install lpeg
```

### 3. Neovim ソースコードをクローン

```
git clone https://github.com/neovim/neovim.git
cd neovim
git checkout v0.9.5
```

### 4. CMakeで設定 (build)

```
make CMAKE_BUILD_TYPE=RelWithDebInfo USE_BUNDLED=OFF
```

【ポイント】
	•	USE_BUNDLED=OFFにするとローカルのbrewパッケージを使う
	•	これでダウンロードなしでビルドだけする

### 5. ビルド

```
cd build
ninja
```

### 6. インストール

```
sudo ninja install
```

(【注意】 make installだと.depsもやり直すのでNG)

### 7. バージョン確認

```
nvim --version
```

以下が出れば成功。
```
NVIM v0.9.5
LuaJIT 2.1.xxxxxxxx
```

### 8. settings.jsonの変更

```
which nvim
/usr/local/bin/nvim
```
の場合、vscodeのsettings.jsonの以下を変更

```
 "vscode-neovim.neovimExecutablePaths.darwin": "/usr/local/bin/nvim",
```
MCP を使って Google Analytics とサーチコンソールのデータを取得・分析してみる

こんにちは。最近、Model Context Protocol（MCP）に関心を持っています。
LLMの進化には日々驚かされていますが、せっかくなら業務に役立つ形で活用したいと考えました。
そこで今回は、MCP（Model Context Protocol）を使って Google Analytics（GA4）と Googleサーチコンソール（GSC）のデータを取得し、サイト分析に活かせるか を検証してみました。

---

## 検証の目的

- MCP（Model Context Protocol）を利用して、LLMから外部データへアクセスする方法を試す  
- Google Analytics と サーチコンソール のアクセスデータを取得する  
- これらを組み合わせてサイトのアクセス数やユーザー数を分析する  

---

## 検証環境

| 項目 | 内容 |
|------|------|
| OS | Windows 11 |
| LLMクライアント | Claude Desktop |
| Node.js | v20.x |

---

## セットアップ手順

### 1. Claude Desktop のインストール

以下の公式ページよりダウンロード可能です。  
<https://claude.ai/download>

### 2. Node.js のインストール

<https://nodejs.org/ja/download/>

インストール後、コマンドプロンプトを立ち上げ、以下のコマンドでパスが正しく通っているかを確認してください。

```cmd
where node
where npx
```

出力がない場合は、環境変数へのパス追加が必要です。

---

## MCP サーバの構成

### Google Analytics（GA4）用 MCP サーバ

GitHub リポジトリ：  
<https://github.com/eno-graph/mcp-server-google-analytics>

#### `config.json` の例

```json
"google-analytics": {
  "command": "node",
  "args": ["C:\\Users\\ユーザー名\\mcp-server-google-analytics\\build\\index.js"],
  "env": {
    "GOOGLE_CLIENT_EMAIL": "xxx@xxx",
    "GOOGLE_PRIVATE_KEY": "-----BEGIN PRIVATE KEY-----\\nxxx\\n-----END PRIVATE KEY-----\\n",
    "GA_PROPERTY_ID": "xxxxxxxx"
  }
}
```

### サーチコンソール（GSC）用 MCP サーバ

GitHub リポジトリ：  
<https://github.com/ahonn/mcp-server-gsc>

```json
"gsc": {
  "command": "npx",
  "args": ["-y", "mcp-server-gsc"],
  "env": {
    "GOOGLE_APPLICATION_CREDENTIALS": "C:\\Users\\ユーザー名\\intense-reactor-xxx.json"
  }
}
```

#### Claude Desktop 利用時の注意点

- 再起動は「タスクトレイのアイコン → メニューから終了 → 再起動」によって行う必要があります  
- no such file or directory, lstat 'C:\Users\ユーザー名\AppData\Local\AnthropicClaude\app-0.9.2\${APPDATA}'というエラーが出る場合は、
　先ほどのjsonの設定ファイルのenvに"APPDATA": "C:\\Users\\ユーザー名\\AppData\\Roaming"を追加してみてください

---

## 実際に試してみた内容

今回は会社のサイトではなく個人で実験的に持ってるサイトで試してみました。
Claude Desktopには以下のように入力します

```
過去1か月でPVが減った原因って分かる？
```

これにより、

- GA4 に問い合わせて、ページごとのPVや動向を取得  
- GSC に問い合わせて、検索キーワードやクリック数を取得  

といった処理が自動で行われ、それらの情報をもとに **自然言語での分析結果** が返されます
結果は以下の画像の通りです

![claude1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820284/642c8a82-b92d-4093-b4b6-b113c8817ba6.png)
![claude2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3820284/91b734c1-fd24-4b97-a9e6-6bab35196034.png)

get_reportがGA4に問い合わせている部分
search_analyticsがGSCに問い合わせている部分になります

サイトが特定できそうな部分は白く塗りました
中は詳細なURLだったり、流入した検索キーワードだったりするので、
適当に置き換えて読んでみてください


---

## 所感と考察

- MCP を経由して **LLMが外部データへアクセス可能になる** ことで、分析作業の自動化が大きく前進する  
- よく使う分析パターンはプロンプトをテンプレート化することで、さらに効率化が見込める  
- GSC 用の MCP サーバはやや不安定な気もするので今後の改善に期待  
- 他のデータソース（ECサイト、広告、CRMなど）との連携を視野に入れると、さらに応用範囲が広がる  

---

## まとめ

今回は MCP を活用して、Google Analytics と Google サーチコンソールのデータを取得し、サイトアクセスの傾向分析を行うプロセスを検証しました。

業務への応用を前提とした実験でしたが、  
**十分な実用性と今後の可能性を感じる結果**となりました。

他の BIツールとの統合や、広告パフォーマンスの分析への応用なども検討していきたいと考えています。
WSL Tips

# 外部からwsl上のサービスにアクセスする方法
1. wsl上のIPアドレス確認
    ```bash
    $ ifconfig
    eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1472
            inet 172.20.177.100  netmask 255.255.240.0  broadcast 172.20.191.255
    ```
1. powershell（管理者権限で実行）でポートフォワーディング設定
    ※外部の全アドレスからの2222ポートアクセスを172.20.177.100の22ポートに送る
    ```powershell
    netsh interface portproxy add v4tov4 listenaddress=* listenport=2222 connectaddress=172.20.177.100 connectport=22
    
    netsh interface portproxy show all
    
    ipv4 をリッスンする:         ipv4 に接続する:
    
    Address         Port        Address         Port
    --------------- ----------  --------------- ----------
    *               2222        172.20.177.100  22
    ```
1. windowsのファイアウォール設定で2222ポートをあける
[＜Windows10・11＞ファイアウォールのポートの開放](http://www.fc-center.jp/support/index.php?%A5%CD%A5%C3%A5%C8%A5%EF%A1%BC%A5%AF%A5%BF%A5%A4%A5%D7/windows%A5%D5%A5%A1%A5%A4%A5%A2%A5%A6%A5%A9%A1%BC%A5%EB%A4%CE%A5%DD%A1%BC%A5%C8%A4%CE%B3%AB%CA%FC/Windows10%A1%A611%A5%D5%A5%A1%A5%A4%A5%A2%A5%A6%A5%A9%A1%BC%A5%EB%A4%CE%A5%DD%A1%BC%A5%C8%A4%CE%B3%AB%CA%FC#:~:text=%E3%80%8C%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%91%E3%83%8D%E3%83%AB%E3%80%8D%E7%94%BB%E9%9D%A2%E3%81%8C%E9%96%8B%E3%81%8D,%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%80%8D%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%8A%E4%BD%BF%E3%81%84%E3%81%AE%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BC%E3%82%BD%E3%83%95%E3%83%88,%E9%96%8B%E6%94%BE%E3%82%92%E8%A1%8C%E3%81%A3%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82)参照

# vscodeでデフォルトアタッチするユーザ指定
1. wsl2内で、以下を設定
    ```text:/etc/wsl.conf
    [user]
    default=<ユーザ名>
    ```
1. 以下で一度停止させ、vscodeでアタッチ
    ```powershell
    wsl -t <ディストリビューション名>
    ```

# 参考
* [【WSL2】外部からWSL2のサービスに接続する](https://zenn.dev/splusl_at/articles/wsl2-connect-outside)
* [VSCodeでRemote WSL2した時にrootユーザとして実行されるのを変更する](https://scrapbox.io/jiro4989/VSCode%E3%81%A7Remote_WSL2%E3%81%97%E3%81%9F%E6%99%82%E3%81%ABroot%E3%83%A6%E3%83%BC%E3%82%B6%E3%81%A8%E3%81%97%E3%81%A6%E5%AE%9F%E8%A1%8C%E3%81%95%E3%82%8C%E3%82%8B%E3%81%AE%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B)
* [WSLで同じUbuntuバージョンの仮想環境を複数作る方法](https://dx-tech.blog/web/wsl-multi-ubuntu-vm/)
* [＜Windows10・11＞ファイアウォールのポートの開放](http://www.fc-center.jp/support/index.php?%A5%CD%A5%C3%A5%C8%A5%EF%A1%BC%A5%AF%A5%BF%A5%A4%A5%D7/windows%A5%D5%A5%A1%A5%A4%A5%A2%A5%A6%A5%A9%A1%BC%A5%EB%A4%CE%A5%DD%A1%BC%A5%C8%A4%CE%B3%AB%CA%FC/Windows10%A1%A611%A5%D5%A5%A1%A5%A4%A5%A2%A5%A6%A5%A9%A1%BC%A5%EB%A4%CE%A5%DD%A1%BC%A5%C8%A4%CE%B3%AB%CA%FC#:~:text=%E3%80%8C%E3%82%B3%E3%83%B3%E3%83%88%E3%83%AD%E3%83%BC%E3%83%AB%E3%83%91%E3%83%8D%E3%83%AB%E3%80%8D%E7%94%BB%E9%9D%A2%E3%81%8C%E9%96%8B%E3%81%8D,%E3%83%95%E3%82%A1%E3%82%A4%E3%82%A2%E3%82%A6%E3%82%A9%E3%83%BC%E3%83%AB%E3%80%8D%E3%82%92%E3%82%AF%E3%83%AA%E3%83%83%E3%82%AF%E3%81%97%E3%81%BE%E3%81%99%E3%80%82&text=%E3%81%8A%E4%BD%BF%E3%81%84%E3%81%AE%E3%82%BB%E3%82%AD%E3%83%A5%E3%83%AA%E3%83%86%E3%82%A3%E3%83%BC%E3%82%BD%E3%83%95%E3%83%88,%E9%96%8B%E6%94%BE%E3%82%92%E8%A1%8C%E3%81%A3%E3%81%A6%E3%81%8F%E3%81%A0%E3%81%95%E3%81%84%E3%80%82)
【2025年度版】WSL2のubuntuにapacheとphpをインストールしてバージョン管理

この記事は[WSL2のubuntuにapacheとphpをインストールしてバージョン管理](https://zenn.dev/sakots/articles/a4217c84e10a41)の2025年度版となります。

## はじめに

### windowsならLaragon使え

- 自動SSL
- php、DB、apache、node、pythonのバージョン管理

[https://laragon.org/]

非商用なら年11ドルだ

## それでも行くというのなら

前回の記事の加筆修正版となります。

### この記事をもとにphpをインストール

[ubuntu20.04.1 phpのバージョンを切り替える](https://mebee.info/2020/08/17/post-16891/)

ubuntu24.04でも使える模様。
phpは現状8.1～8.4くらいを入れよう。

```bash
sudo apt install -y software-properties-common
sudo add-apt-repository -y ppa:ondrej/php
sudo apt update
sudo apt install -y php8.1 php8.1-fpm php8.1-mbstring php8.1-zip php8.1-mysql php8.1-xml
sudo apt install -y php8.2 php8.2-fpm php8.2-mbstring php8.2-zip php8.2-mysql php8.2-xml
sudo apt install -y php8.3 php8.3-fpm php8.3-mbstring php8.3-zip php8.3-mysql php8.3-xml
sudo apt install -y php8.1 php8.4-fpm php8.4-mbstring php8.4-zip php8.4-mysql php8.4-xml
```

### apacheインストール

```bash
sudo apt install -y apache2
sudo apt install -y libapache2-mod-php libapache2-mod-php8.1 libapache2-mod-php8.2 libapache2-mod-php8.3 libapache2-mod-php8.4
```

### apacheのphpのバージョンを入れ替える場合

モジュールを無効化/有効化し、apacheを再起動

例

```bash
sudo a2dismod php8.4
sudo a2enmod php8.2
sudo systemctl restart apache2
```

## ドキュメントルート変更はしない2025

どうもうまく動かなくなることが多い。ので、処理ディレクトリのパーミッション変更を行う。

```bash
cd /var/www/html
sudo chown -R [username] /var/www/html
```

これで、Ubuntuのデフォルトユーザーで/var/www/html内を自由に編集できる。

## ssl設定

### ssl設定はドメインを取ってcertbotを使おう？

どうもwslではうまくいかない模様

[ローカル環境をSSL化する](https://zenn.dev/chot/articles/c1bed03b43e6de)

### default-ssl.conf 編集

`/etc/apache2/sites-available/default-ssl.conf` をviなりnanoなりで編集

```nano
SSLCertificateFile	/etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
```

を

```nano
SSLCertificateFile	/etc/ssl/myssl.crt
SSLCertificateKeyFile /etc/ssl/myssl.key
```

とかに変更。

### openssl-san

[XAMPP for WindowsでSSLを有効にする](https://qiita.com/sutara79/items/21a068494bc3a08a4803)を参考に

`/etc/ssl/`内で`openssl.cnf`をコピーして`openssl-san.cnf`を作成、

```openssl-san.cnf
[ SAN ]
subjectAltName = @alt_names

[ alt_names ]
DNS.1 = localhost
DNS.2 = <他に認証したいドメインがあれば>
DNS.3 = <他に認証したいドメインがあれば>
```

と追加する。

### opensslコマンド実行

これも`/etc/ssl/`内で

```openssl
$ sudo openssl req \
    -newkey     rsa:4096 \
    -keyout     myssl.key \
    -x509 \
    -nodes \
    -out        myssl.crt \
    -subj       "/CN=localhost" \
    -reqexts    SAN \
    -extensions SAN \
    -config     openssl-san.cnf \
    -days       365000
```

エクスプローラからwindowsに証明書をインストールする。

### apache再起動

```bash
sudo a2dissite default-ssl.conf
sudo a2ensite default-ssl.conf
```

のあと

```bash
sudo service apache2 restart
```

OKだ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569616/20d2a4e0-0353-4417-bd33-801d8ce748e7.png)

## 結論

laragon使おうぜ？
docker コマンド 基本のキ（nginx のコンテナを実行してみる）[2025年4月最新]

こんにちは。
[Docker のエラー](https://www.dockerstatus.com/pages/incident/533c6539221ae15e3f000031/677dd6e2108ba105c8d0258c)を放置したまま3ヶ月以上過ごしてしまった者です。
さきほど、やっと Docker Desktop と macOS を最新版にアップデートすることができたので、今回はその環境を使って基本的な docker コマンドを復習したいと思います。

# 環境
* MacBook Air (Intel Core i5)
* macOS Sequoia 15.4
* Docker Desktop 4.40.0

# 準備
Docker Desktop は起動しているものとします。

![スクリーンショット 2025-04-26 15.08.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83323/bfd9783a-3c7b-460a-a736-0ec2eb2c5f2a.png)

# Docker イメージの取得
`docker pull` で [Docker Hub から nginx の Docker イメージ](https://hub.docker.com/_/nginx/)を取得します。

```
% docker pull nginx:latest
```

取得済みのイメージは `docker images` で確認できます。

```
% docker images

REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
nginx        latest    4e1b6bae1e48   9 days ago   192MB
```

# コンテナの作成と実行
`docker run` でコンテナを作成して実行します。

```
% docker run --name my-nginx -d -p 8080:80 nginx:latest
```

# コンテナの状態確認
`docker ps` でコンテナの状態を確認します。

```
% docker ps

CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS         PORTS                  NAMES
f63d1ca2ff9e   nginx:latest   "/docker-entrypoint.…"   7 seconds ago   Up 6 seconds   0.0.0.0:8080->80/tcp   my-nginx
```

# nginx の動作確認
ブラウザで http://localhost:8080 へアクセスします。
ポート番号は `docker run` で指定した8080番です。
Welcome to nginx! で歓迎されたら成功です。

![スクリーンショット 2025-04-26 15.12.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/83323/35ce0175-7609-4692-b9a2-88f086578264.png)

# コンテナの停止
`docker stop` でコンテナを停止します。

```
% docker stop my-nginx
```

```
% docker ps

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

`-a` オプションを付けると、停止したコンテナを確認できます。

```
% docker ps -a

CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS                      PORTS     NAMES
f63d1ca2ff9e   nginx:latest   "/docker-entrypoint.…"   2 minutes ago   Exited (0) 43 seconds ago             my-nginx
```

# コンテナの再実行
停止したコンテナは再度実行できます。

```
% docker start my-nginx
```

```
% docker ps

CONTAINER ID   IMAGE          COMMAND                   CREATED         STATUS         PORTS                  NAMES
f63d1ca2ff9e   nginx:latest   "/docker-entrypoint.…"   3 minutes ago   Up 4 seconds   0.0.0.0:8080->80/tcp   my-nginx
```

起動を確認できたら、再度停止しておきます。

```
% docker stop my-nginx 
```

```
% docker ps

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

# コンテナの削除
`docker rm` でコンテナを削除します。

```
% docker rm my-nginx
```

```
% docker ps -a

CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
```

# Docker イメージの削除
`docker rmi` で Docker イメージを削除します。

```
% docker images

REPOSITORY   TAG       IMAGE ID       CREATED      SIZE
nginx        latest    4e1b6bae1e48   9 days ago   192MB
```

```
% docker rmi nginx:latest
```
```
% docker images

REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
```

# まとめ
Docker イメージの取得からコンテナの実行と停止、イメージ削除までの一連の作業を確認できました。慣れるまでは多少わかりにくいので、コンテナのライフサイクルをご自分で絵に描いてみると理解が深まると思います。
Springのキャッシュが原因でRSpecのスタブが正しく動作しない？

Railsアプリケーションを8.0にアップデートした際、RSpecのテストが個別実行では正常に動作するものの、テストスイート全体の実行ではスタブが効かなくなるという問題に遭遇しました。本記事では、遭遇した問題とその解決までの過程をまとめます。

# 遭遇したエラー
Rails 8.0へバージョンアップ後、RSpecを用いたテストで次のような現象に遭遇しました。
- テストを個別に実行した場合は正常にパスする
- テストスイート実行時には一部のスタブやモックが正しく機能せず、テストが失敗する
- タイミングによっては稀にテストがパスすることもある

特にテストスイートを実行した際に、スタブが効かなくなり、特定のテストで期待した挙動が得られないケースが発生しました。

具体的には、以下のような認証機構を持つコントローラに対して、`logged_in?` メソッドのスタブが効かなくなるケースに遭遇しました。


```ruby
# コントローラ例
# app/controllers/addresses_controller.rb
class AddressesController < ApplicationController
  def index
    # ログインしていない場合は401を返す
    render status: :unauthorized unless logged_in?

    address = Address.where(user_id: params[:user_id])
    render json: { addresses: address }
  end

  private

  # user_idが存在するか確認し、ログイン判定実施
  def logged_in?
    session[:user_id].present?
  end
end
```

```ruby
# テスト例
# spec/requests/address_spec.rb

require 'rails_helper'

RSpec.describe "Addresses API", type: :request do
  describe "GET /addresses" do
    let(:user) { create(:user) }
    
    before do
      create(:address, user: user)
      allow_any_instance_of(AddressesController).to receive(:logged_in?).and_return(true)
    end

    context "ログインしている場合" do
      it 'Addressの取得に成功すること' do
        get '/addresses', params: { user_id: user.id }

        expect(response).to have_http_status(:ok)
        expect(JSON.parse(response.body)['addresses'].size).to eq(3)
      end
    end
  end
end
```

このテストでは、logged_in? をスタブして強制的にログイン状態を作り、`/addresses` エンドポイントのレスポンスを確認する流れになっています。

# エラーの原因
今回のエラーの根本原因は、次の2点にありました。
- Springがアプリケーションプロセスをキャッシュしていること
- Rails 8.0の[Zeitwerk](https://github.com/fxn/zeitwerk)オートローダーがコード変更をリアルタイムに反映しない場合があること

これにより、テストスイート実行時に古いコードが使われ、スタブが正しく効かない現象が発生していました。

## Springの役割
Springは、Railsアプリケーションの起動時間を短縮するために、プロセスを常駐させて高速化を図るツールです。
通常、Railsアプリは起動に時間がかかりますが、Springを利用することで、プロセスを再利用し、起動時間を大幅に短縮できます。

https://github.com/rails/spring

ただしこの仕組みは、
- アプリケーションコードや設定が変更されても即時反映されない
- 古い状態のプロセスが残り続ける

といったリスクを抱えています。

特に、テストスイートをまとめて実行する際には、キャッシュされた古いコードが原因でスタブやモックが効かない問題に繋がることがあります。

# エラーの解決方法
この問題を解決するため、SpringのプロセスがforkされるタイミングでRailsアプリケーションを明示的にリロードする設定を追加しました。

```ruby
# config/spring.rb

Spring.after_fork do
  Rails.application.reloader.reload!
end
```

この設定により、Springがプロセスをforkするたびに、Railsのコードや定数が最新の状態にリロードされるようになり、テストスイート実行時でもスタブが正しく機能するようになりました。

## まとめ
Rails 8.0へのアップデートに伴い、RSpecでスタブが効かなくなる問題に遭遇しましたが、SpringのキャッシュとZeitwerkオートローダーの動作に原因があることを突き止めました。

Springのafter_forkフックを利用して、アプリケーションコードを毎回リロードすることで、スタブやモックが正常に機能するようになり、問題を無事に解決できました。

同様の問題に遭遇した方は、ぜひこの方法を試してみてください！
【復習メモ】Recursionのシステム設計入門で学んだスケーラビリティの基礎

## サーバー1台運用のリスク

- **ハードウェア負担が大きい**
- **サーバー障害によるシステム停止**

### ハードウェア負担の例
- CPU処理能力を超えるリクエストが来る
- キャッシュ・ストレージ容量を超えるデータ保存が発生

結果、**システムダウン**に繋がる可能性がある。
さらに、**サーバーが1台だけだと**、システム全体が停止してしまう。

---

## 対策1：垂直スケーリング

- サーバーの性能を上げる（CPU・メモリ・ストレージを強化）
- しかし，**物理的な限界**がある

---

## 対策2：水平スケーリング

- サーバーの**数を増やす**ことで負荷を分散

---

# アプリケーションレベルのスケーラビリティ

## 水平スケーリングで必要な技術

### 1. ロードバランサー

- 複数サーバーへリクエストを**適切に振り分ける**
- 代表的：**ラウンドロビン方式**（順番に振り分ける）

### 2. キャッシング

- 一度取得したデータを**メモリに保存**し、再利用
- **DBアクセス減らし＆速度向上**

### 3. CDN（コンテンツデリバリーネット）

- 世界中に設置されたサーバーに**静的ファイル**を保存
- ユーザーは**最寄りのサーバー**からデータ取得
  → アプリケーションサーバーの負荷軽減

---

## 水平スケーリング特有の課題と対策

### キャッシュデータの問題

- サーバー間で**共有できない**問題

#### 対策：スティッキーセッション

- **ロードバランサーがユーザーとサーバーを固定**して管理
- だけど負荷偏りリスクもある

---

## ステートレスサーバーとトークン認証

- サーバーは**セッションを保持しない**
- **トークンベース認証**（JWTなど）を利用
- デメリット：**毎回認証が必要**

---

## サービスアーキテクチャ（マイクロサービス化）

- サービスごとに**サーバーを分ける**
- メリット：**負荷分散**
- デメリット：**API連携実装コスト増大**

---

# データベースレベルのスケーラビリティ対策

## 1. マスター・スレーブレプリケーション

- 書き込み専用DB（マスター）
- 読み取り専用DB（スレーブ）複数
- 読み課題をスレーブに振り分けて負荷分散

## 2. データベースシャーディング

- **用途ごと**にDBを分ける（例：投稿DB、決済DB、ユーザーDB）
- デメリット：**システム設計複雑化**

---

# 単一障害点（SPOF）

- 1つ壊れると全体が停止するポイント
  - 例：ロードバランサー，書き込み用DB
- 完全な排除は難しいが、**可能な限りシンプルに設計する**

---

# まとめ：スケールの考え方

- **コピーして増やす（水平スケーリング）**
- **役割ごとに分けて増やす（シャーディング）**

### バックエンド開発者として大切なこと

- **要件によって設計は変わる**
- **背景知識があると開発の意図が理解できる**
自分のmemo

Windowsのサービス、hotfix、アプリ一覧を各csvで出力する

```PS
# 実行ポリシーの変更
Set-ExecutionPolicy Bypass -Scope Process -Force

# サービス一覧を取得
$triggers = Get-ChildItem "HKLM:\SYSTEM\CurrentControlSet\Services" |
    Where-Object { $_.GetSubkeyNames().Contains("TriggerInfo") } |
    ForEach-Object { $_.Name.Split("\")[-1] }

$startMode = @{ Manual = "手動"; Disabled = "無効"; Auto = "自動"; Unknown = "不明" }
$startOption = @{ 01 = " (トリガー開始)"; 10 = " (遅延開始)"; 11 = " (遅延開始、トリガー開始)" }

$serviceData = Get-CimInstance -ClassName Win32_Service | Select-Object @(
    @{ n = "表示名";              e = { $_.DisplayName } }
    @{ n = "サービス名";          e = { $_.Name } }
    @{ n = "スタートアップの種類"; e = { $startMode[$_.StartMode] + $startOption[10 * ($_.StartMode -eq "Auto" -and $_.DelayedAutoStart) + $triggers.Contains($_.Name)] } }
    @{ n = "状態";                e = { if($_.State -eq "Running") { "実行" } else { "-" } } }
)

# 取得したサービス一覧をcsvに出力
$serviceData | select 表示名,状態,スタートアップの種類 | sort -Property 表示名 | Export-Csv $PSScriptRoot\services.csv -Encoding Default

# 取得したHotFix一覧をcsvに出力
Get-HotFix | select HotFixID,InstalledOn | sort -Property HotFixID | Export-Csv $PSScriptRoot\hotfix.csv -Encoding Default

# インストールされたアプリケーション一覧をcsvに出力
$base = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
$wow64 = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
$path = @(("HKLM:" + $base), ("HKCU:" + $base))
if(Test-Path $wow64){
    $path += $wow64
}

$programs = @()

Get-ChildItem -Path $path | 
    ForEach-Object {
        $properties = Get-ItemProperty -Path $_.PsPath
        if ($properties.systemcomponent -ne 1 -and $properties.parentkeyname -eq $null -and $properties.DisplayName -ne $null) {
            $programs += [PSCustomObject]@{
                DisplayName = $properties.DisplayName
                Publisher = $properties.Publisher
                DisplayVersion = $properties.DisplayVersion
            }
        }
    }

$sortPG = $programs | Sort-Object DisplayName

# CSVファイルのパスを指定
$csvPath = "application.csv"

# CSVファイルのヘッダーを作成
$sortPG | Export-Csv -Path $csvPath -NoTypeInformation
```
Astro × Cloudflare R2でファイルを配布できる仕組みを作る

## 概要

AstroとCloudflare R2（S3互換ストレージ）を組み合わせてファイルを配布できる仕組みを作ったので、備忘録がてら記事にまとめました。

署名付きURLでセキュアに一時的なダウンロードリンクを発行できるのと、データベースが不要なのでサクッと作れるのが良い点かと思っています。

ただし、大規模なものではなく、ちょっとしたデータ配布をするとき用の構成です。
用途の具体例としては、イベント限定配布や期間限定公開の素材など「数種類だけのデータを手軽に配布したい」ケースを想定しています。

## 全体の流れ

1. Cloudflare R2にファイルをアップロード
1. 環境変数の設定
1. AstroのAPI Routeで署名付きURLを発行
1. フロントエンドからAPI Routeを叩き、R2のファイルをダウンロード

## Cloudflare R2にファイルをアップロード

Cloudflare R2のバケットを作成し、管理画面やターミナルからファイルをアップロードします。

管理画面からアップロードする場合、作成したバケットのページに行って`アップロード`ボタンからアップロードするだけです。

詳細は公式ドキュメントをご覧ください。

https://developers.cloudflare.com/r2/get-started/

ターミナルからアップロードする場合、R2はAWS S3互換APIがあるので、AWS CLIを利用できます。

```sh
aws s3 cp ./sample.zip s3://your-bucket/your-folder/sample.zip --endpoint-url=https://<your-account-id>.r2.cloudflarestorage.com
```

こちらも詳細は公式ドキュメントをご覧ください。

https://developers.cloudflare.com/r2/api/s3/api/

## AstroのAPI Routeで署名付きURLを発行

AstroのAPI Route（`src/pages/api/download/[id].ts`といったファイル）で、R2上のファイルに対して「一時的に有効なダウンロードURL」を発行し、リダイレクトします。

```typescript
import { GetObjectCommand, S3Client } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import type { APIRoute } from "astro";

export const prerender = false;

export const GET: APIRoute = async ({ params, redirect, locals }) => {
  const s3Client = new S3Client({
    region: "auto",
    endpoint: locals.runtime.env.AWS_ENDPOINT,
    credentials: {
      accessKeyId: locals.runtime.env.AWS_ACCESS_KEY_ID,
      secretAccessKey: locals.runtime.env.AWS_SECRET_ACCESS_KEY,
    },
  });

  const command = new GetObjectCommand({
    Bucket: "your-bucket",
    Key: `your-folder/${params.id}.zip`,
  });

  const signedUrl = await getSignedUrl(s3Client, command, { expiresIn: 86400 });

  return redirect(signedUrl);
};
```

署名付きURLで、直リンクを晒さず有効期限付きで安全に配布できます。
また先ほども記載したとおりS3互換なので、AWS SDKがそのまま使えます。

## 環境変数の設定

`.dev.vars`に環境変数を設定します。

```
AWS_ENDPOINT=https://<your-account-id>.r2.cloudflarestorage.com
AWS_ACCESS_KEY_ID=xxxxxxxxxxxxxxxxxxxx
AWS_SECRET_ACCESS_KEY=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
```

それぞれの値の取得の方法は公式ドキュメントを確認してください。

https://developers.cloudflare.com/r2/api/tokens/

## フロントエンドからAPI Routeを叩き、R2のファイルをダウンロード

Astroのページ内で、API Routeへのリンクをダウンロードボタンとして設置します。

```astro:src/pages/[id].astro
---
import { getCollection } from "astro:content";
import type { APIRoute } from "astro";

export async function getStaticPaths() {
  const items = await getCollection("exampleCollection");
  return items.map((item) => ({
    params: { id: item.id },
    props: { item },
  }));
}

const { item } = Astro.props;
---

<a
  download
  href={`/api/download/${item.id}`}
>
  ダウンロード
</a>
```

## まとめ

- Astro × Cloudflare R2で、サーバーレスでセキュアにファイルを配布できる仕組みが作れる
- データベース不要、運用コストも最小限
- 署名付きURLで安全に配布できるので、素材配布や限定ファイルの配布にも最適
rbenvでrails newをできなかった話。

## 1. 目次
[2. 発生事項](#2-発生事項)
[3. 解決までの行動](#3-解決までの行動)
[4. 考察](#4-考察)
[5. 結論](#5-結論)
## 2. 発生事項
rbenvを使用してrubyバージョンを管理していた時のこと。
事前に以下のバージョンのrubyおよびrailsをインストール済み状態であった。
* ruby: 3.1.1
* rails: 8.0.2

ここで、[railsチュートリアル](https://railstutorial.jp/)をしようと思い、
以下のrubyおよびrailsをインストールした。
* ruby: 3.2.8
* rails: 7.0.4.3

インストールまでは順調に実行できた。
`rbenv local 3.2.8`をprojectのディレクトリで実行した。
しかし、`rails _7.0.4.3_ new sample_app`を実行したときに
以下のような問題が発生した。
```
initialized constant ActiveSupport::LoggerThreadSafeLevel::Logger (NameError)

    Logger::Severity.constants.each do |severity|
```
chatGPTによると以下の意味を示している
`initialized constant ActiveSupport::LoggerThreadSafeLevel::Logger (NameError)`は、Logger というクラス（またはモジュール）が見つからない＝未定義の定数として扱われていることを意味する。
`Logger::Severity.constants.each do |severity|`は、標準ライブラリの Logger クラスの中の Severity（ログのレベル：INFO, WARN など）から定数一覧を取得して処理しようとしている行である。

ちなみに、
* rails: 7.2.2, 8.0.2

では`rails new`を成功できている。

## 3. 解決までの行動
### 手動でのrails依存関係の作成
```
bundle init
echo "gem 'rails', '7.0.4.3'" >> Gemfile
bundle install

bundle exec rails new . --force --skip-bundle

bundle install
```
上記のコマンドを実行すると手動で`rails new`の代わりをできるらしい。
しかし、この方法では今回の問題は解決できなかった。
### 他のrubyバージョンで実行
ruby: 3.1.4
でrails `rails _7.0.4.3_ new sample_app`を実行した。
しかし、状況はからわず。
### rubyの再インストール
rubyのビルド時に問題が発生していると考え、
rubyの再インストールを試した。
しかし、状況はからわず。
### ruby-build時の外部ライブラリへの正しいリンク指定
~/.zshrcの内容を修正してみた。
目的はmac内部のrubyとの競合を解消するため。
しかし、状況は変わらず。
### railsの複数バージョンインストールによる競合の解消
全てのrubyをアンインストールしてgemファイルが初期化されていることを確認した後、
* 7.0.8.6
* 7.2.2
* 8.0.2

のそれぞれに対してrailsのインストールと`rails new`を行った。
しかし、状況は変わらず。
* 7.2.2
* 8.0.2

は成功した。

## 4. 考察
* 7.0.8.6
* 7.2.2
* 8.0.2

のうち
* 7.2.2
* 8.0.2

は成功ことにより以下のように判断する。
* rails 7.0.x系列では追加で必要な処理がある

## 5. 結論
以下のことがわかった。
|バージョン|結果|
|---|---|
|7.0.4.3|不成功|
|7.0.8.6|不成功|
|7.2.2|成功|
|8.0.2|成功|

今後も調査を進める。
入茶記事といふものを、書いてみんとするなり

# Hello World.
どうもこんにちは。Un_tlitledといいます。
この度ABC401で入茶させていただきまして、人生で初めて記事というものを書いてみております。稚拙な文章ですが読んでいただけると幸いです。
# 簡単に自己紹介
なんかその辺で学生をしてます。
プログラミングの経験は ~~義務教育でスクラッチを触ったことがある程度で~~ ほぼ０です。
まず言語を学び始めるところからスタートして、約１年で入茶しました。
# 入茶になにが必要だった？
おおまかにわけて
* 言語の習得
* 競技プログラミングを身に着ける方法を知る
* 初歩的なアルゴリズムの理解
の３つが必要だったと思います。
もちろん、もっと効率よく入茶した方もインターネット上には多くいらっしゃいます。まぁ、私はこの３つを身に着けるために１年という時間がかかりましたという参考としてください。
### 言語の習得
C++をAPG4bで勉強しました。出力ってなんですか？から始まりましたけど、第一章まで終わればABCのAは解けると思います。
ただ、これが大変でして、setやmapといった、重要な型を学ばずに中途半端なところでAPG4b中断してしまいました。 ~~これがバカでした。このせいで入茶が３か月おそくなったといっても過言ではないでしょう。~~
これから競プロ始めたいよという方は、これらの型をしっかり学んでから、アルゴリズムの学習を本格的に始めることを強く推奨します。
### 競技プログラミングを身に着ける方法を知る
精進の方法を知る必要があります。私は知りませんでした。
最も効果的な勉強方法は、ABCなどに出て、とけなかった問題を次の日とかに確認することですが、やはり練習問題は必要です。
個人的なおすすめはNovistepsです。5～7Qを中心に解いていました。
またJOIの過去問埋めも効果はあると思います。
アルゴ式は今のところあまり触ってないのでわかりませんが、文字列のところはとても楽しいです。
### 初歩的なアルゴリズムの理解
鉄則を購入するのが手っ取り早いと思います。わからないところがあれば、APG4bに戻ったり、ぐぐって強い方の記事を読んだりするのがいいと思います。
個人的に二分探索のlower_bound関連で躓いたので、その辺はいつか記事にする予定です。
# 入茶までに身についたこと
AtCoder ProblemsのAchievementはこんな感じです（入茶から１週間たったくらいに撮ったものなので厳密に灰色の時だけではありません）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049382/0aef6fe0-81db-4c41-88d7-baf9aa513c26.png)
NoviStepsです。ここで難易度を確認して解いたものは記録してますが、普段のABCの問題を記録してはないので相当AC数少なめです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049382/bdadc340-784a-4b1b-9108-33b52574086e.png)
JOI過去問です。言語学び始めの時に難易度1〜2あたりを埋めまくっていた記憶があります。

![statistics.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4049382/fd21f839-bfd6-44c4-8eef-d7dfcdb77424.png)

#### 言語面
C++はなんとなくかけるようにはなりました。深部はなにも理解していません。pythonはやろうと思って手をつけられていないので、これからやっていきたいです
#### アルゴリズム
* bit全探索
* 累積和
* 二分探索
* DP（動的計画法）

の４つの基本は押さえました。
木（BFS、DFSなど）はこれからやる予定です。
# 精進のためのサイトなど
#### AtCoder Problems
https://kenkoooo.com/atcoder/#/table/

diffと自分の提出状況が一目でわかります。ABC後の復習におすすめです。
#### AtCoder NoviSteps
https://atcoder-novisteps.vercel.app/

普段の精進におすすめです。レベルに分けて問題がみられるだけでなく、解法ごとに問題がまとまっている機能もあります。
# 最後に
初めての記事で長々と駄文を連ねてしまいましたが、最後まで読んでいただきありがとうございます。
また日頃TwitterでたくさんアドバイスをくださってるFFの皆様には感謝でいっぱいです！
今後とも私Un_titled全力で競プロを楽しんでいきますので、よろしくお願いします！
SQLAcademy 初期設定

# ディレクトリ構造 これにしてないと、DB動かない

![スクリーンショット 2025-04-27 16.59.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/628823/d1b61841-a21c-471e-aea5-d6a5e1961443.png)


# インスト

```ruby:
  pip install Flask-SQLAlchemy
```

# app.pyにこれ書く

```ruby:
from flask_sqlalchemy import SQLAlchemy
from flask import Flask, request, redirect, render_template_string
```

# run.appにimport文追加

```ruby:
from app.app import db
```

## app.py [app = Flask(__name__)]下に、これ追加

```ruby:
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///books.db'
db = SQLAlchemy(app)
```

## app.py [db = SQLAlchemy(app)]下に、モデル定義 "登録したいものがタイトルと著者なら、二つ書く"

```ruby:
class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    author = db.Column(db.String(100))
```
# run.py[if __name__ == "__main__":]下に、これ書く

```ruby:
with app.app_context():
        db.create_all()
    app.run(debug=True, use_reloader=True)
```

## ここまでのcode 全文(app.py)

```ruby:
from flask import Flask, render_template, request, redirect, url_for
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///books.db'
db = SQLAlchemy(app)

class Book(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    title = db.Column(db.String(100))
    author = db.Column(db.String(100))
```

# run.app 全文

```ruby:
from app.app import app
from app.app import db

if __name__ == "__main__":
    with app.app_context():
        db.create_all()
    app.run(debug=True, use_reloader=True)
```
Grafanaのダッシュボードで画像を表示が簡単だった


# Grafanaのダッシュボードで画像を表示する方法

Grafanaを使ってセンサーデータをグラフ化しているんですが、  
「**アナログ計器の写真や機械の状況写真も一緒に表示できたら便利じゃないか？**」  
と思ったことがありました。

数値データだけじゃなく、現場の様子が一目でわかると便利だし、  
確認する側としてもイメージがつきやすいかなと。

というわけで、**Grafanaに画像を表示する方法**を調べて試してみました。  
やってみると結構簡単だったので、メモがてら記事にしておきます。

---

## 画像データの保存場所（簡易版）

まずは、**Grafanaが動いているサーバー内に画像ファイルを直接配置する方法**です。  
自分はとりあえず以下の場所に画像を置きました。

```
/usr/share/grafana/public/img
```

ここに例えば `random.jpg` という画像を置いておくと、  
以下のURLでアクセスできます👇

```
http://<Grafanaのアドレス>:3000/public/img/random.jpg
```

---

## Grafanaで画像を表示する

Grafanaの**Textパネル**を使って、Markdown記法で画像を表示します。

パネル内で以下のように書きました👇

```markdown
![meter](http://<Grafanaのアドレス>:3000/public/img/random.jpg)
```
こっちでも可。

```markdown
![meter](/public/img/random.jpg)
```

![スクリーンショット 2025-04-26 144730.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/711722/dbdd3cf3-f148-4ba0-bb7c-3a9cf096395f.png)



これで、**ダッシュボード上に画像が表示されました**。  
シンプルにこれだけでOK。

---

## 補足：画像の保存場所を別の方法にしたい場合

今回は**Grafanaサーバー内に画像を置く方法**でやりましたが、  
他にも以下の方法が考えられます。

- 自分のWebサーバーに画像を置いて、そのURLを指定する
- 画像ホスティングサービス

Grafana側では**MarkdownでURLを指定して表示するだけ**なので、表示元は自由に選べます。

---

## まとめ

- **画像はGrafanaサーバー内の `/usr/share/grafana/public/img/` に置ける**
- TextパネルでMarkdownを書くだけで画像表示できる
- 外部のサーバーを使うことも可能

データのグラフと一緒に、**現場の写真を並べて表示**できると、  
より直感的に状況がわかるようになりそうです。