OmniAICreator/Qiita-1.07M huggingface dataset:
【Tensorflow】import tensorflow_hub実施時に、'register_load_context_function’に関するエラーが出力される。

# 開発環境

- Google Colab

# 事象
* TensorFlowに関連したライブラリを`pip install`しました。
```shell
pip! install tensorflow-text
```

* 上記操作後、Pythonをコーディングする際、`import tensorflow_hub`にて下記に示すメッセージが出力されました。
> AttributeError: module 'tensorflow._api.v2.compat.v2.__internal__' has no attribute 'register_load_context_function'

```python
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-5c017171c13e> in <cell line: 1>()
----> 1 import tensorflow_hub as hub

13 frames
/usr/local/lib/python3.10/dist-packages/tf_keras/src/saving/legacy/saved_model/load_context.py in <module>
     66 
     67 
---> 68 tf.__internal__.register_load_context_function(in_load_context)
     69 

AttributeError: module 'tensorflow._api.v2.compat.v2.__internal__' has no attribute 'register_load_context_function'
```

# 原因
- TensorFlowのバージョンとtf-kerasのバージョンが一致していないため。
    - 公式フォーラムによると、TensorFlow、tf-kerasを同一のバージョンで統一させる必要があるとのことです。
    - `pip! install tensorflow-text`によって、tensorflowが2.16.1になったにも関わらず、tf-kerasが2.15.1のままであるために、バージョンに差異があります。

## 参考リンク
[Unable to import tensorflow_hub - Been stuck on this all evening](https://discuss.tensorflow.org/t/unable-to-import-tensorflow-hub-been-stuck-on-this-all-evening/23061)



# 解決策
- TensorFlowのバージョンとtf-kerasのバージョンを一致させる。本ケースでは、TensorFlowがバージョン2.16.1であったために、それに合わせてtf-kerasを`pip install`しました。
```python
# TensorFlowのバージョンを確認する。
!python3 -m pip list | grep tensorflow | grep -v tensorflow-
tensorflow                       2.16.1

# tf_kerasのバージョンを確認する。
!python3 -m pip list | grep tf_keras
tf_keras                         2.15.1


# バージョンが不一致なために、tf-kerasをpip installする。
!pip install tf-keras==2.16.0rc0
```
AtCoder Beginner Contest 328 振り返り

# ABC328

## 概要

https://atcoder.jp/contests/abc328

## A - Not Too Hard

**考えてたこと**
全探索

**提出したもの**

```c++:a.cpp
int main() {
    int n, x;
    int points = 0;

    cin >> n >> x;

    for (int i = 0; i < n; i++) {
        int s;
        cin >> s;
        if (s <= x) {
            points += s;
        }
    }
    cout << points << endl;
    return 0;
}
```

**振り返り**
特になし。

## B - 11/11

**考えてたこと**
全探索、月日を一文字ずつsetに入れてsetの中身が1の時、全ての値が同じ、つまりゾロ目。

**提出したもの**

```c++:b.cpp
int main() {
    int n;
    cin >> n;

    int cnt = 0;

    for (int i = 1; i <= n; i++) {
        int d;
        cin >> d;
        for (int date = 1; date <= d; date++) {
            set<char> set;
            fore(j, to_string(i)) {
                set.insert(j);
            }

            fore(k, to_string(date)) {
                set.insert(k);
            }

            if (set.size() == 1) {
                cnt++;
            }
        }
    }

    cout << cnt << endl;
    return 0;
}
```

**振り返り**
特になし。

## C - Consecutive

**考えてたこと**
累積和、毎回全探索していたら計算量が足りないけど先に保持しておけば十分足りる。

**提出したもの**

```c++:c.cpp
int main() {
    int n, q;
    cin >> n >> q;

    string s;
    cin >> s;

    vector<int> vec(n + 1);
    vec[0] = 0;
    vec[1] = 0;
    for (int i = 2; i <= n; i++) {
        if (s[i - 2] == s[i - 1]) {
            vec[i] = vec[i - 1] + 1;
        } else {
            vec[i] = vec[i - 1];
        }
    }
    for (int i = 0; i < q; i++) {
        int l, r;
        cin >> l >> r;

        cout << vec[r] - vec[l] << endl;
    }

    return 0;
}

```

**振り返り**
最近解いたから累積和ってすぐに気づいて解けたけど、実際に328が開催されていた頃だと解けなかった気がする、成長。

## D - Take ABC

**考えてたこと**
ABCを都度消すと文字列の都合的に計算量が足りなそうだからそれを解決する問題なのかなぁと推測。文字列を一文字ずつ確認してABCの並びになる時だけ別の文字列に足していって最終的に完成するその文字列を出力。しかしWA。

**提出したもの**
```c++:d.cpp
int main() {
    string s;
    cin >> s;

    string ans;

    for (int i = 0; i < s.size(); i++) {
        if (s[i] == 'A') {
            if (i + 1 < s.size() && s[i + 1] == 'B') {
                if (i + 2 < s.size() && s[i + 2] == 'C') {
                    i += 2;
                } else {
                    ans += s[i];
                }
            } else {
                ans += s[i];
            }
        } else {
            ans += s[i];
        }
    }

    cout << ans << endl;
    return 0;
}
```
**考えてたこと(2回目)**
どうにもABCを消した後にABCが作成される際に問題になるらしい。(例えば、AABCBCのような場合、AABCBC -> ABCで処理が終了してしまう。)
何周か回せば解決する問題ではありそうだけど、その何周がどれくらいかかるかも分からず結局うまく実装できなかった。

**振り返り**
解答を見た上での振り返り。適合したものを別の変数に入れていくのではなく、とりあえず別の変数に入れて末尾をその都度確認するという方針だった。確かにこの方針なら削除する文字列以外の文字列の移動が発生しないから計算量も十分に足りそう。

## 感想
D問題がめちゃくちゃ悔しい、大体方針はあっていたけど後一捻り考えられなかった、精進。
telnetの基礎

## telnetとは
ネットワーク上の他のコンピュータにリモートで接続する際に使用されるプロトコルのこと

## telnetの特徴
- かなり昔に作られHTTPやSMTPの原型になったプロトコル
- TCP/IPがベースを利用して作成されている
- プリンタなどのコンピュータでもtelnetが入ってさえいれば接続が可能となる
- ログインIDとパスワードさえあれば他のコンピュータに接続し、CUIで操作が可能となる
- telnetを使用すればHTTPやメールのようにリクエストを送りレスポンスを得ることができる
- ポートはデフォルトで２３番を使用する
- 接続する側をローカルホスト、接続される側がリモートホスト

## 最後に
ネットワークの強みは、telnetのように他のコンピュータに接続してリソースを活用できるというのがありますね。
僕は、リモートで他のコンピュータに接続しただけでやってやったぜみたいな気分になっちゃいます。
リモート接続だとSSHとかも聞いたこと使用した経験がありますが、何が何だか分かってないので調査してみたいです。

## 参照記事

https://www5e.biglobe.ne.jp/~aji/3min/53.html
【TIPs】 Tabキーの逆操作

# 備忘録
Tabキーでweb アプリケーション上の項目を移動することはできるが、その逆の操作を知りませんでした。逆の操作とは、tabキーで本来操作したかった項目の先を選択してしまった時に1つ前の項目に戻る操作のことです。
そんな時は、```shift + tabキー```を押せば戻ります！
Excel VBA 国土地理院地図のgeojsonから緯度と経度を取得する

# 国土地理院地図のツール
このように手書きで図形が書けます。これをgeojsonで出力します。
手書きなので測量図のような精度はありませんが、一度記録すると再び読み込ませて表示することができるため、大変便利です。
https://maps.gsi.go.jp/#5/36.104611/140.084556/&
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126919/2828f90a-1978-0124-a39b-61f5119127c9.png)

# Geojsonから読み込む
書き出すのは多いけど、読み込むのはないので。
あと、あまり多段になっているのは自信ないです。
シンプルなものだけですね。

# 参照設定
## Adodb.Stream
Geojsonはutf-8、改行コードがLfということなのでAdodb.streamを使います

## VBScript.RegExp
ここでいうgeojsonファイルは多角形のPolygonです。
中身を見ると、
スペース 経度 コンマ LF スペース　緯度
となっているので、これを切って抜いていきます。
Qiitaでは &yen; は \で表示されています。
取得できない(0)場合はエラーで終了します。
また、geojsonファイルは`C:\hoge\hoge.gejson`にあるとしています。
ワークシートはActiveではなく、新たに追加する形にしています。
連打するとワークシートが増えるので注意してください。

```vb
Sub Macro1()
Dim sr As New ADODB.Stream
Dim sbuf As String
Dim FSO As New Scripting.FileSystemObject, oFile As File, ofolder As Folder, sPath As String, sFilename As String, sfullname As String
Dim Reg As New RegExp, MC As MatchCollection, M As Match, sBMs As SubMatches, iM As Long, rBuf As String
Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets.Add
Dim irow As Long, icol As Long
sfullname = "C:\hoge\hoge.geojson"
With sr
.Mode = adModeReadWrite
.LineSeparator = adLF
.Charset = "utf-8"
.Type = adTypeText
.Open
.LoadFromFile sfullname
sbuf = .ReadText(adReadAll)
End With
With Reg
.Global = True
.MultiLine = True
.Pattern = "(\s+)([\d]{1,3}\.[\d]{1,})(,\n)(\s+)([\d]{1,3}\.[\d]{1,})"
Set MC = .Execute(sbuf)
If MC.Count = 0 Then
MsgBox "エラー、座標を取得できません", vbCritical + vbOKOnly, "終了"
sr.Close
Exit Sub
End If
ws.Cells(1, 1) = "緯度"
ws.Cells(1, 2) = "経度"
For iM = 0 To MC.Count - 1
Set M = MC(iM)
Debug.Print M.Value
ws.Cells(iM + 2, 1) = M.SubMatches(4) '緯度
ws.Cells(iM + 2, 2) = M.SubMatches(1) '経度
Next
End With
sr.Close
End Sub
```

# VBAの正規表現の改行
改行は`\n`ですが、ファイルの改行コードがLFでもCrLFでも改行判定しているようです。
dockerでmountしたファイルを更新しても、更新内容が反映されないのはファイルシステムが原因みたい。

docker-compose.yamlでmountしたファイルを更新しても、更新内容が反映されなかったために、原因調査の備忘録です。

# 困ったこと
docker-compose.yamlでmountしたファイルを更新しても、更新内容が反映されなかった。
※以下は、サンプルコードです。
```yaml
service:
    image: image-sample
        container_name: "container-sample"
        volumes:
            - ./yamls/sample.yaml:/yamls/sample.yaml
```

# 原因
volumensでファイル指定をしていたために、ファイルの内容を変更後のファイル情報が変更されてしまうために変更後のファイルを参照できていなかった。

# 分かったこと
dockerでマウントしている時は、inodeと呼ばれるファイルに関するデータ構造を参照しているらしい。

そのため、ファイル内容を変更するとinode情報も変更されるために、変更前のファイル情報を参照してしまう。

### ▽原因説明してくれてるコメント
>ここで何が起こっているか、私には分かるかもしれません…
>
>もしvimのようなエディタを使っている場合、ファイルを保存するときに直接ファイルを保存するのではなく、新しいファイルを作成してその場にコピーします。これはinodeに基づいたバインドマウントを破壊します。ファイルを保存することは実質的にinodeを変更するため、変更はコンテナに伝搬しません。コンテナを再起動すると新しいinodeです。ファイルをその場で編集すれば、変更が伝搬するのを見ることができるはずです。
>
>これはファイルマウントの既知の制限であり、修正は不可能です。
>
>この説明は問題を正確に表していますか？

https://github.com/moby/moby/issues/15793#issuecomment-135411504

# inodeを実際に確認
1.テストフォルダ作成
```zsh
$ mkdir test-inode
```

2.inode情報確認 
```zsh
$ ls -ial

24968113 drwxr-xr-x  2 ryotaro  staff    64 Mar 18 22:48 test-inode
```

3.フォルダに内移動  
```zsh
cd test-inode
```

4.ファイル作成
```zsh
$ touch a.txt
```

5.inode情報確認
```zsh
$ ls -ial

24968113 drwxr-xr-x  3 ryotaro  staff   96 Mar 18 22:53 .
24968756 -rw-r--r--  1 ryotaro  staff    0 Mar 18 22:53 a.txt
```

6.ファイル内容変更後確認 
inode情報が、24968756から24968973へ変更されているが、
現在のディレクトリのinode情報は変更されていないことが確認できる。
```zsh
$ vim
$ ls -ial

24968113 drwxr-xr-x  3 ryotaro  staff   96 Mar 18 22:54 .
24968973 -rw-r--r--  1 ryotaro  staff    2 Mar 18 22:54 a.txt
```

# 解決策
volumesの箇所を、ディレクトリ指定に変更することで、ディレクトリ内の変更内容が反映される。
```yaml
service:
    image: image-sample
        container_name: "container-sample"
        volumes:
            - ./yamls:/yamls
```

これまでLinuxのファイルシステムを見る際には、主に権限設定に注目してきましたが、inodeという概念を知ることができて良かったです。この知識を直接使用する機会は少ないかもしれませんが、もっと多くを学んでいれば、問題の原因調査をより迅速に行えるようになるのではないかと思います。


## 参考資料
・[Linuxの「inode」とは？概要や確認方法をご紹介](https://rainbow-engine.com/linux-inode-intro/)
・[File mount does not update with changes from host #15793](https://github.com/moby/moby/issues/15793)
貢献は力強く、名誉は永遠に、そしてサーバーは空を飛ぶ

# はじめに
私はASUSのROG Flow Z13という虹色に輝くゲーミングタブレットPCを使用しています。厚み1cm程度のタブレットにIntel Core i9とNVIDIA GeForce RTX 3050 Tiが入っているこの素敵な板はWindows 11の他にもAlma LinuxやUbuntuも動作しています。Linuxエンジニアですから。

# Linuxのエンジニアであることの意義
一般にパソコンを購入する、使用するというときイメージしているパソコンとはWindows OSではないでしょうか。家電量販店に行ってもWindows PCかMacくらいしか目にすることはないでしょう。それでも我々がLinuxのエンジニアであることの意義とは何でしょうか？パソコンのほとんどがWindows OSであっても、Linuxのエンジニアであることにはいくつかの意義があります。

1. 柔軟性とカスタマイズ性
Linuxはオープンソースであり、カスタマイズ性が高いため、エンジニアはシステムを自分あるいは自社や顧客のニーズに合わせて調整することができます。これにより、特定の要件に応じてシステムを最適化し効率的に動作させることが可能です。

2. セキュリティ
Linuxはセキュリティ面で優れており、オープンソースの自由な監査とコミュニティのサポートにより、セキュリティの脆弱性が早期に発見され修正されます。そのため、セキュリティ要件の厳しい環境での使用やセキュリティに関する専門知識の獲得が求められる場面で優位に立つことができます。

3. コマンドライン操作のスキル
Linuxはコマンドラインを通じて操作されることが多く、この操作に慣れることで効率的なタスクの実行が可能となります。また、シェルスクリプトや自動化ツールの開発など、コマンドラインスキルはエンジニアリングにおける重要な能力です。

4. クラウドとの親和性
多くのクラウドプロバイダーがLinuxベースのサービスを提供しており、クラウド環境の設定や管理にはLinuxの知識が不可欠です。したがって、クラウドエンジニアやDevOpsエンジニアとしてのキャリアを構築する上でLinuxのスキルは非常に重要です。

5. エコシステムとコミュニティの活用
Linuxには広範なエコシステムと活発なコミュニティが存在し、問題解決や学習のためのリソースが豊富です。Linuxのエンジニアは、このエコシステムとコミュニティを活用することでスキルの向上やプロジェクトの推進を支援することができます。

これらの要因から、パソコンの大半がWindowsであっても、Linuxのエンジニアであることは、柔軟性、セキュリティ、効率性、クラウドとの親和性など、さまざまな面で価値を提供します。

# パワーがあるからいつでもどこでもオープンソースムーブメント
前述のパワフルなタブレットは個人のオープンソースムーブメントに機動力をもたらします。非力な端末でも動作するディストリビューションもあるLinuxですが、それでもパワーのある端末を利用することのメリットをいくつか示します。

1. 開発とテストの効率化
パワフルなPCを使用することで、開発者は高速なコンパイルや実行が可能となります。これにより、ソフトウェアの開発、テスト、デバッグのプロセスが迅速化され、プロジェクトの進行がスムーズになります。

2. 複数の仮想環境の構築
パワフルなPCを使用することで、仮想化技術を活用して複数の仮想マシンを同時に実行することが可能となります。これにより、異なるLinuxディストリビューションや環境を簡単に構築しテストすることができます。

3. 大規模なデータ処理
パワフルなPCを使用することで、大規模なデータセットの処理や解析を行うことができます。これは、機械学習やデータ分析などのプロジェクトにおいて特に重要です。

4. リモート作業のサポート
パワフルなPCを使用することで、リモートワーカーや分散チームのメンバーとの協業が容易になります。高性能なPCを持つことでリモート環境でも快適な作業が可能となり柔軟性が向上します。

これらの要因により、LinuxエンジニアがパワフルなPCを使用することでオープンソースムーブメントの活動においてより効果的に作業し、機動力を発揮することができます。

# さいごに
オープンソースムーブメントにおいて、より速く、より多く、より高品質に貢献を継続していくためにも道具は良いものを選びましょう。ここに費やすコストはオープンソースムーブメントによって得られる名誉が回収してくれます。一見ただ働きのように思えるボランタリティが最大の投資になる瞬間を体感しましょう。

# おまけ
Linuxエンジニアも体力が要ります。ご存じのとおり、Linuxエンジニアとはサーバーで稼ぎ、サーバーで体を鍛える職業を言います。私も参加したことのあるEOGではサーバーを投げます。とにかく投げます。いっぱい投げました。
そう、約半世紀ずっーーーーーと引きこもりで地球から一歩も出ていない石ころでも。
次回開催の時にはみんなで競いましょう。

参考：

https://dailyportalz.jp/kiji/engineer-sportsday

https://www.itmedia.co.jp/news/articles/2403/04/news124.html
特定の文字列の間の範囲で文字列を置換する

1. 特定の文字列Aが含まれる行の行数を取得します。
2. 取得した行数をペアにして、それぞれのペアの範囲で特定の文字列Bを文字列Cに置換します。

このスクリプト例では、`awk` と `sed` を使用しています。スクリプトの構造は以下の通りです：

```bash
#!/bin/bash

# ファイル名、検索文字列A、置換前文字列B、置換後文字列Cを指定
file="example.txt"
stringA="特定の文字列A"
stringB="特定の文字列B"
stringC="文字列C"

# 文字列Aが含まれる行の行数を取得
line_numbers=($(grep -n "$stringA" "$file" | cut -d: -f1))

# 行数のペアを作成して、それぞれの範囲で文字列Bを文字列Cに置換
for ((i=0; i<${#line_numbers[@]}-1; i++)); do
    start=${line_numbers[$i]}
    end=${line_numbers[$i+1]}
    # sedを使って範囲内の文字列を置換（ここではファイルは上書きされない）
    sed "${start},${end}s/$stringB/$stringC/g" "$file"
done
```

このスクリプトでは、次のことを行っています：

- `grep -n` を使用して、特定の文字列Aが含まれる行の行数を取得し、`cut` を使って行数の部分だけを抽出します。
- 抽出した行数を配列 `line_numbers` に格納します。
- 配列 `line_numbers` をループし、隣接する要素をペアとして扱い、それぞれのペアで指定した範囲内の文字列Bを文字列Cに置換します。この例では、`sed` コマンドが範囲指定された置換を行いますが、ファイルは実際には上書きされません。

注意点として、このスクリプト例では置換結果がファイルに直接反映されないため、実際にファイルを更新するには `sed` コマンドに `-i` オプションを追加する必要があります。しかし、`-i` オプションを使用する際は、元のファイルが変更されるため、注意してください。また、このスクリプトは基本的な例であり、特定のニーズに合わせて調整する必要があります。
【初学者】Bunについて調べたら根本的に何もわかってなかった話

## Q1:Bunってなんやねん
### A1:なんかめっちゃ速い肉まん。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3736578/c6bc1e9f-52fd-c602-7d58-1ddd54210d21.png)

これだとエンジニアとして失格やと思うから頑張って調べてみた。
以下調査結果。たぶん初学者向け。

<hr>

Bunは、JavaScriptとTypeScriptのための新しいランタイム環境。
Node.jsの代替品と言われることが多い。
ランタイムだけではなく、バンドル、トランスパイラ、パッケージマネージャーなどを含むオールインワン・ツールキット。

エンジンはJavaScriptCore。（Node.jsはV8）
言語はZig.（Node.jsはC、C++、JavaScript）

:::note alert
警告：専門用語が大量発生しています。
:::


### まぁ慌てなさんな。

## Q2:ランタイムってなんやねん
### A2:プログラムを実行するときに必要な物、あるいはその実行時のこと。
イメージするなら、OSみたいな感じ。iPhoneで天気アプリをタップしたら、iOSが天気アプリを起動するためのプログラムを実行してくれる。だから天気アプリが起動する。
Node.jsは、サーバーサイドでJavaScriptを実行するためのランタイム環境。
Bunも同じ。

## Q3:バンドルってなんやねん
### A3:複数のファイルやモジュール（部品）を１つのファイルに出力すること
Webページを読み込む時、JavaScriptのファイルがたくさんあったら何回もサーバーに取りに行かなあかんから、1つにまとめておく方がいい。それをしてくれるのがバンドラー。Webpack、Rollup、Parcel、esbuild、Viteとか色々ある。Bunもバンドラー。

## Q4:トランスパイラってなんやねん
### A4:通訳者みたいなもん
例えばReactでJSXを書いた場合、そのままじゃブラウザで動かんからJavaScriptに変換する必要がある。BabelというトランスパイラーがJSXをJavaScriptに変換してくれている。
Bunにもそういうトランスパイラの機能が入ってる。

## Q5:パッケージマネージャーってなんやねん
### A5:世界中の開発者が作った便利グッズを集めて管理する敏腕マネージャー
WEBの世界って基本的に世界中のいろんな人が作ったものをうまいことつなげながら作られてるんやけど、作った人は他のものといつでもうまくつながるように作ってるわけではない。だから、別々の人が作ったものをまとめて、いい感じにつなげる仲介人が必要になる。パッケージマネージャーはそんなイメージ。npm、yarn、pnpmに続いてBunもパッケージマネージャー。

## Q6:結局Bunって何がすごいん？
### A6:処理がめっちゃ速い。あと肉まんがかわいい。

## 終わりに
Bunは良いぞ。



## 参考記事
https://bun.sh/

https://zenn.dev/k41531/articles/dbedb88f06898a

https://github.com/yytypescript/book/issues/530

https://qiita.com/micropig3402/items/064394428791144f5488

https://developer.mozilla.org/ja/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%83%BC%E3%81%A8%E3%81%AF%E6%AD%A3%E7%A2%BA%E3%81%AB%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B%EF%BC%9F

https://kinsta.com/jp/blog/bun-sh/
PHPカンファレンス2024

# はじめに
入社して半月が経ちました。今回が初投稿になります。
少し前になりますが[PHPカンファレンス関西2024](https://2024.kphpug.jp/)に参加しましたので感想を書きたいと思います。

# 参加したセッション
#### レガシーシステムへのPHPStan導入から半年での課題と効果
https://fortee.jp/phpcon-kansai2024/proposal/10c6f1ac-ec4b-4895-8db7-39b9a13c84bb

このセッションでPHPStanを知り、どのように運用しているかを学べたので良かったです。
現在研修で作成しているアプリケーションにも導入し、最初はレベル9でしたが、
時間的に間に合わないと判断しレベル8に下げました。
これ以上レベルを下げないようにしたいです。
#### 「"品質"が高いコード」って何？
https://fortee.jp/phpcon-kansai2024/proposal/a60c9e18-bc61-4f60-80d0-0a0ea7a205c4

コードの品質についての認識を改めさせられるセッションでした。
高品質の定義が「要求を満たしている」で未満も超過もダメということは覚えておこうと思いました。
PHPUnit等のツールを治具として活用するという考えが面白いと思いました。
#### レガシーとモダンなシステムが混在する開発環境を改善しよう
https://fortee.jp/phpcon-kansai2024/proposal/bf2fe2a3-cd7d-4eaa-b7e5-0f63355423b6

レガシーな開発環境の経験があったのでこのセッションは共感できるところが多かったです。セッション同様、現在はDockerで開発をしているので以前あった課題が解消されたので良かったです。
#### コードを自在に操るためのPHP文法入門
https://fortee.jp/phpcon-kansai2024/proposal/1cb30b96-0bc9-43a0-b7ea-d3e19348c021

PHPがどのようにコードを解析して実行しているかを学べたセッションでした。
今まであまり考えたことがなかったので「構文木」についても今後勉強してみようかなと思いました。
#### その条件分岐って本当に必要？
https://fortee.jp/phpcon-kansai2024/proposal/d2406310-e9dc-4866-851c-20662ae04fa8

セッションのアンチパターンにもありましたが、ディープネストにかなり苦しめられたことがあったので自分自身も改めて気を付けようと思いました。
条件分岐禁止バンド面白かったです。
#### 実践、Interface
https://fortee.jp/phpcon-kansai2024/proposal/a71a2778-826d-480c-bb0f-153df97f3448

セッションで紹介されていたようなダメなパターンに似たような実装をしてしまったことがあったので今後そのような実装になりそうな時は学んだことを活かしたいと思います。
#### モデルとは何か
https://fortee.jp/phpcon-kansai2024/proposal/b3f6ed97-8551-40da-90b1-3a14697df303

本来のモデルがどういうものかを学べたセッションでした。
これを理解していればControllerにビジネスロジックを書かないという話がすんなり理解できると思いました。
#### PHPで学ぶ、セッションの基本と応用
https://fortee.jp/phpcon-kansai2024/proposal/de8a6738-b97c-466c-a1af-e09267250cc9

セッションの生い立ちから使用の際の注意点まで説明があり、知らなかったことが多く勉強になりました。セッションのことだけでなく、セキュリティについても勉強不足だと感じたので頑張ろうと思いました。
#### 擬人化で完全に理解するクリーンアーキテクチャ
https://fortee.jp/phpcon-kansai2024/proposal/0d9231ed-2f64-4908-bd16-863922f56c0f

よく見る同心円よりも分かりやすかったので理解しやすかったです。
依存の向きに気を付けて実装しようと思います。

# 最後に
初めてのカンファレンスでしたが、いろんな方の経験を聞けて学びになりました。
どのセッションも面白く、時間があっという間に過ぎました。
今後もこのようなイベントに参加し、知識を深め、スキルを磨いていきたいと思います。
【Rust】順序付きマップを定数で使用したい場合の対応方法

## 概要
Rustにおいて順序付きマップは、2024年の3月時点で標準の機能としては実装されていません。おそらくライブラリ等を使用して順序付きマップを実現することが多いと思いますが、では順序付きマップを定数で使用したい場合にどういうやり方があるのかというメモ書きです。

## 対応方針
そもそも、HashMapを定数で管理したい場合どうすれば良いかという点について、いくつかやり方が挙げられると思いますが、今回は[Rustの便利クレート](https://qiita.com/qryxip/items/7c16ab9ef3072c1d7199#phf)で紹介されている`phf`というライブラリを使用したいと思います。このphfですが、[Module phf::ordered_map](https://docs.rs/phf/latest/phf/ordered_map/index.html)のドキュメントで紹介されている通り、順序付きマップの機能もあります。

## 前提
* 使用したrustcのバージョンは`1.76.0`です。
* 使用したphfのバージョンは`0.11`です。

## 実装サンプル

```rust
use phf::phf_ordered_map;

pub const TEST_ORDERED_MAP: phf::OrderedMap<&'static str, &'static str> = phf_ordered_map! {
    "key1" => "val1",
    "key2" => "val2",
    "key3" => "val3",
};
```

## その他参考
[RustでGlobal ConstなHashMapを使おうと思ったらはまった](https://qiita.com/tagawa0525/items/cfa4139470a64dc6b70b)
【Windows】CMake 導入

## CMake とは
CMake は、コンパイラに依存しないビルド自動化ツール。
実際には、CMake によってコンパイラに依存するビルド手順を生成し、 ビルドの実行はその手順を元に他のツールが行う。

## CMake インストール手順
### 1. 下記 URL にアクセスする
　https://cmake.org/download/
### 2. Windows 64bit のインストーラをダウンロードする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/8848faea-c6dd-c5e7-3a16-8b8c139be982.png)
### 3. インストーラを実行し、キャプチャの通りにインストールを進める
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/3dcf9e21-977a-499a-706e-bf0848656113.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/2f6db2df-2812-ddf8-cb15-0e18e28e215e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/d9c89e1a-687d-6609-8993-4e32ecfad23e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/f978eed7-56f9-c0d5-4204-12f962e81a5f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/56d2be4e-bf98-b3b5-8125-60c2bd8876fe.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/264de1f9-bd94-aab3-7b9a-750402b03f4f.png)

## CMake 動作確認
### パスが通っていることを確認する
以下のコマンドラインを実行する
```
where cmake
where cmake-gui
```
次のように表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/a420d48d-426b-6ecf-e681-413d3085317e.png)
### CMake を実行できることを確認する
以下のコマンドラインを実行する
```
cmake
```
次のように表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3749137/f0cafe6b-45a3-7c2d-fda7-4596810341cc.png)
Cloud Pak for AIOps について調べてみました

## はじめに
私はサーバやネットワークを監視するシステムの構築や運用管理の業務に携わってきました。
その最新情報を調べていると、AI+運用管理 というキーワードがよく出てくるようになり、どうしてもそこを避けては通れないなと思うようになりました。

私が所属しているユーザ会JIMUCではIBMのミドルウェアをメインに調査・研究を行っていますので、IBMのAIを使った運用管理製品であるCloud Pak for AIOpsについて調査を進めてきました。
今回はその調査結果についてまとめてみたいと思います。

## Cloud Pak for AIOpsについて
### コンポーネントについて
Cloud Pak for AIOpsは、2020年5月にリリースされた製品で、以下の画像のようなコンポーネントとなっていました。
※過去のリリースされたITSM製品の組み合わせになっているようでした。
![画像1new.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356497/f0501aa1-1ec9-cd9a-f145-b18c21a2ae64.png)

### コンポーネント間連携について
コンポーネント間では、以下のように連携を行っています。
・MetricManagerはNetcoolの機能であるProbeを使ってEventManagerへイベント転送を行う。
・NOIからAI ManagerへはKafkaを使ってイベントデータの取り込みを行う。
・AI ManagerはREST APIでTopologyから機器情報やネットワーク情報を取得する。
・AI ManagerはAPIでSlackやTeamsなどの外部ツールと連携する。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356497/a1f6b652-02e3-5ad7-94ec-1de228ea9139.png)
いろいろな方法でデータをやり取りしているのがわかります。

### Cloud Pak for AIOpsの最新の構成（4.2.1）
以前は従来IBMが持っていた製品を組み合わせていましたが、最新のバージョンでは0ベースで以下のようなコンポーネントとなっています。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356497/a42cd362-b550-8b75-cc74-9a4d0d2eb184.png)

### 予兆検知機能について
AIOpsの機能の中に予兆検知という機能がありますが、従来の監視では触れることがなかったため、どういう動きをするのか詳しく調べてみました。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356497/f17258b5-f22c-8e7c-9cf8-d5b10d4b5fe2.png)
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3356497/93cccd2e-fbc3-9946-417b-30c585c46e34.png)
Cloud Pak for AIOpsの予兆検知機能は、性能データを含むCSVファイルやデータベースから情報を取込みます。
※CSVは過去データの分析に向いています。リアルタイム分析を行う場合は、DBと連携が必要になります。
仕組みとしては、以下のようになります。
・取り込んだデータ（最低過去1週間分）をもとに正常パターンを作成
・そのパターンから外れた値を検知したらアラートを通知する
・正常パターンは1日ごとに更新される
・単一データだけではなく、複数データ間の相関関係からも異常を検知できる

## まとめ
Cloud pak for AIOpsを使うと運用方法が以下のように変わると思われます。
・閾値監視
過去の経験から手動で設定
　→　運用しながら自動設定
 
・予兆検知
保管した性能データを手動でグラフ化し傾向を予想
　→　リアルタイムでグラフ化し、自動的にイベント通知
 
・障害対応
あらかじめ作成した障害時フローに従って運用手順を実施。
作業は運用拠点で作業者が実施。
　→　AIにより自動的に運用手順をリストアップ。
 　　　Runbookで定型作業をリモート対応or自動的に回復処理実行。
    
・イベント画面
1つの障害に対して複数イベントが発生し、大量のイベントを確認
　→　グルーピングにより関連するイベントは一つのインシデントに集約。
 
外部連携
主にメール
　→チャット・メールなど多くの手段有り。メッセージ内のリンクから
 　　監視システムにアクセスし、詳細情報を参照。

Cloud pak for AIOpsだけでなく、AIや機械学習を使った運用管理というシステムは今後増えていくと思われます。
今後もAIを使った運用製品をどのように利用していけばいいか調査を進めていきたいと思います。
Gpg4winとGit for Windowsでgithubを使う①：環境整備

## はじめに
この記事は，githubにsshアクセスし，gpgで署名付きのコミットを行うための環境整備手順です。

## やりたいこと
鍵管理はGpg4winに集中させたいと思います。ssh鍵は、gpgの副鍵の一つとして扱いたいです。
また，Git for Windowsでgithubにsshアクセスできるようにもしたいと思います。

## インストール
### Gpg4win
普通にインストールするだけです。
### Git for Windows
普通にインストールするだけですが，「Choosing the SSH executable」で「Use exteral OpenSSH」を選びます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738861/218564b9-bd4d-0f4c-ab86-b9dea8f18d90.png)

OpenSSHを別途準備するのは，Git for Windows はMSYS2ベースで、内蔵の OpenSSH が ssh-agent と通信しようとする方法が，Gpg4win の期待する方法と異なるためです。

### Win32-OpenSSH
[Win32-OpenSSH](https://github.com/PowerShell/Win32-OpenSSH/releases)をインストールします。

### wsl-ssh-pagent
[wsl-ssh-pagent](https://github.com/benpye/wsl-ssh-pageant/releases)をインストールします。
NamedPipeでの接続を待ち受け，pagent_shmを使ってGpg4winの提供するssh-agentに接続します。

## 設定
### wsl-ssh-pagent 
wsl-ssh-pagent-amd64-guiを以下のパラメータで自動起動するように設定します。
```
> wsl-ssh-pageant-amd64-gui.exe  --winssh ssh-pageant --systray
```

-gui付きのバイナリはコマンドウィンドウを出さないバージョンなので，`--systray` オプションを付けます。
OpenSSHはNamed Pipeの`ssh-pagent`に接続すれば、wsl-ssh-pagent 経由でGpg4winと通信できるようになります。

なお今回は、WSLからの接続を中継するための機能は使いません。WSL2の中継が必要であれば，また別のプログラムが必要です。

### OpenSSH
環境変数を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3738861/41afa7ee-71fd-d6d5-d20b-4ff28cb278d2.png)

この設定により、Win32-OpenSSHがNamed Pipeの`ssh-pagent` に接続するようになります。

## 参考
[混沌を極めるWindowsのssh-agent事情](https://qiita.com/slotport/items/e1d5a5dbd3aa7c6a2a24)
[GPG + Git SSH Authentication and Signing on Windows 10](https://gist.github.com/matusnovak/302c7b003043849337f94518a71df777)
[Nuxt]SSRを画面上で確認

# はじめに

Nuxtを採用する理由としてSSR（ServerSideRendering)が挙げられるが、画面上で確認ができず、動きがいまいち腑に落ちなかった。
Cromeブラウザの検証 > ネットワークタブにあるプレビューを利用すれば確認できたのでその記録。

# SSRとは

* ServerSideRenderingの略
* SSRを実現するためにはNuxtが必要（ライブラリの組み合わせによっては実現できるようだが、通常はNuxtを採用する）
* サーバサイドで描画されるため、レスポンスデータの段階で画面情報が作られる
* そのため、Googleのクローラーが取得できる情報となり、SEO対策として有効
* 対比する仕組みはCSR(ClientSideRendring）
* 注意点として、SSRとSPAは排他的な関係ではない
  * 最初のページ（SinglePage）をSSRで描画し、以降、SPAで動作するようになる
  * Nuxtでは上記がデフォルトの動作で、これを`ユニバーサルレンダリング`と呼ぶ

# SSRの確認

* `<script setup>` 内に記載した処理はサーバサイドでレンダリング（SSR)される
* クライアントサイドでレンダリングしたい場合（CSR)は、onMounted内に処理を書く
* コンポーネント自体をCSRとしたい場合は`<ClinentOnly>`タグで括る

```vue:app.vue
<script setup lang="ts">
const title = ref<string>('SSR-title');
onMounted(() => {
  title.value = 'CSR-title';
});
</script>
<template>
  <div>
    <h1>{{ title }}</h1>
    <ClientOnly fallback-tag="div" fallback="loading csr">
      <div style="border: 2px solid red">
        <h1>CSR AREA</h1>
      </div>
    </ClientOnly>
  </div>
</template>
```

* 検証 > ネットワークタブから、ページのリクエストを選択し、プレビュータブを表示する
  * 左（画面）：SSR→CSRまで描画 / 右（プレビュー）：SSRまで描画
  * `title`はSSR時のものがCSR時に更新されている。（`onMounted`処理で更新）
  * `CSR AREA`はCSR時に描画されている。（`<ClinetOnly>`の機能）

![スクリーンショット 2024-03-18 21.47.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3414442/f2703002-56fc-abbd-0ba3-f5f79bd8ff2b.png)
ニューラルネットワークを用いた、汎用的な数値予測プログラムを作ってみた

# はじめに
- 今回は、scikit-learnの**MLPClassifier**を使って、様々な数値予測に使える雛形的なコードを書いてみました
- 記事上では、例として株価の予測を行っていますが、データセットと変数を書き変えることで、様々な予測ができる。…はず
- 説明変数の標準化も実行されるようにしてます

## 想定読者
- scikit-learnのMLPClassifierを使った数値予測に興味がある人
- 「データセットは準備できた。あとは必要最低限のカスタマイズで、予測を実行できるようなコードが転がっていればな～」という人

## 前提
- Pythonの動作環境
- Scikit-learnと、Pandasがインストール済み

# 学習用データセットの形式
- ルール
1. 目的変数と、必要な説明変数のみが記載されたcsvファイルであること
2. １行目にカラム名が英語で記載されていること
3. 全データの数値化や、欠損値・外れ値の処理が実施済みであること 

■サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480554/a198ada0-bbe8-c16c-baf6-0b65cb43e9e0.png)


例では
とある企業の**明日の株価（終値）の予測**を目的に
目的変数：closing_price_today（当日の終値[円]）
説明変数：7days_ago～1day_ago（7~1日前までの終値[円]）
のデータセットを１年分用意している

（データの抽出元：https://finance.yahoo.co.jp/quote/2181.T/history）

# 学習済みモデルに予測させる入力データの形式
- ルール
1. 目的変数のカラムが不要なこと以外は、学習用データセットの形式と同様

■サンプル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3480554/56ca1806-e36d-4208-09bc-985824ad91a1.png)


# コード
- 上記の学習用データ、入力データが準備できたら、以下のコードをカスタマイズして実行する
- カスタマイズできる個所は、コメントアウトに【カスタムN】と記載のある５個所

```python:main
from sklearn.model_selection import train_test_split
import pandas as pd
from sklearn.neural_network import MLPClassifier
from sklearn import metrics 
from sklearn.preprocessing import StandardScaler

# 【カスタム1】学習用データセットのパス
csv_file_path_learning = "./learning_data.csv"
# 【カスタム2】学習済みモデルに予測させる入力データのパス
csv_file_path_actual = "./actual_data.csv"
# 【カスタム3】目的変数のカラム名
mokuteki_label = 'today'
# 【カスタム4】学習用データのうち、テストデータにする割合
ratio_for_test_data = 0.2
# 【カスタム5】隠れ層の数
layer_size=(100,100,100)

# 学習用データを説明・目的変数に分割
csv_data_learning=pd.read_csv(filepath_or_buffer=csv_file_path_learning, encoding="utf-8", sep=",")
setsumei_data = csv_data_learning.drop([mokuteki_label],axis=1)
mokuteki_data = csv_data_learning[mokuteki_label]

# 説明変数の標準化
sc = StandardScaler()
sc.fit(setsumei_data)
scaled_setsumei_data = sc.transform(setsumei_data)

# 学習用データを、トレーニング用とテスト用に分割
setsumei_data_for_training, setsumei_data_for_test, mokuteki_data_for_training, mokuteki_data_for_test = train_test_split(scaled_setsumei_data, mokuteki_data, test_size=ratio_for_test_data, random_state=42)

# ニューラルネットワークの定義
clf = MLPClassifier(
    hidden_layer_sizes=layer_size)

int_mokuteki_data_for_training = mokuteki_data_for_training.astype('int')
int_mokuteki_data_for_test = mokuteki_data_for_test.astype('int')

# モデルの学習、精度の計測
clf.fit(setsumei_data_for_training, int_mokuteki_data_for_training)
predict = clf.predict(setsumei_data_for_test)
score = metrics.r2_score(int_mokuteki_data_for_test, predict)
print("モデルの精度：", score)

# 入力データから予測
data_actual = pd.read_csv(filepath_or_buffer=csv_file_path_actual, encoding="utf-8", sep=",")
setsumei_data_actual = sc.transform(data_actual) 
print("予測結果：", clf.predict(setsumei_data_actual))
```

## サンプルデータの実行結果
```
モデルの精度： 0.8832801846947363
予測結果： [201]
```
ちなみに該当日の、実際の株価は **202.8円** でした
まずまずの精度かと思います

# 最後に
- 今回、わかりやすさ重視のため、モデルの精度を高めるためのカスタム要素を①テストデータの割合と②隠れ層の数に限定しています
もっと自由にカスタマイズしたい場合は、ニューラルネットワークの定義箇所で、MLPClassifierの引数に様々なパラメータを設定できますので、試してみてください。
- 株価の予測というサンプルは、完全な筆者の好みです
他にも、説明変数の検討やデータ収集がうまくいけば、プロジェクトの工数を予測したりするのも面白そうだなーと思ってます
 まあ、何より大変なのはそのデータ収集と前処理なんですけどね…
Controllerのテスト時にMockMvcでアクセス元IPアドレスをモックする

# 結論
`RequestPostProcessor`を実装してテスト実行時にremoteAddrを上書きすれば良い。

## 環境
- kotlin 1.9.22
- spring-boot 3.2.1
- spring-security 6.2.1

SpringSecurityの設定は以下だとします。

```kotlin: SecurityConfig
@Bean
fun securityFilterChain(http: HttpSecurity): SecurityFilterChain {
    http.authorizeHttpRequests { authorizationManagerRequestMatcherRegistry ->
        authorizationManagerRequestMatcherRegistry
            // /dummyへのアクセスは特定のIP(仮にxxx.xxx.xxx.xxxとする)の場合だけ許可する
            .requestMatchers("/dummy")
            .access(WebExpressionAuthorizationManager("hasIpAddress('xxx.xxx.xxx.xxx')"))
            // その他のURLは全て許可する
            .anyRequest().permitAll()
    return http.build()
}
```

※Controllerのコードは今回重要でないので割愛します。

## テストコード
まずIP制限を考慮せずにUnitTestをMockMvcで以下の様に実装します。

```kotlin:HogeControllerTest
@Test
fun test_ip_restrictions() {
    mockMvc
        .get("/dummy")
        .andExpect {
            status { isOk() }
        }
}
```

上記のテストを実行するとIP制限されているためHTTPステータスが403となりテストが失敗します。IP制限を通過させるためにはアクセス元IPをモックする必要があります。

アクセス元IPをモックするには以下の`RequestPostProcessor`を実装してrequestをモックする必要がありました。
```java:RequestPostProcessor
package org.springframework.test.web.servlet.request;

import org.springframework.mock.web.MockHttpServletRequest;

@FunctionalInterface
public interface RequestPostProcessor {
    MockHttpServletRequest postProcessRequest(MockHttpServletRequest request);
}
```
今回はRequestUtilsというテスト用のユーティリティーobjectを作成してIPアドレスをモック出来るようにしました。

```kotlin
object RequestUtils {
    fun remoteAddr(remoteAddr: String): RequestPostProcessor = RequestPostProcessor { request ->
        request.remoteAddr = remoteAddr
        request
    }
}
```

先ほどのテストケースを以下の様に修正します。
```kotlin:HogeControllerTest
@Test
fun test_ip_restrictions() {
    mockMvc
        .get("/dummy") {
             // 許可されているIPアドレスを指定する
            with(remoteAddr("xxx.xxx.xxx.xxx"))
        }
        .andExpect {
            status { isOk() }
        }
}
```
こうする事でテスト時にIP制限されたURLへのテストを通過させることができます。

許可されているIPアドレス以外からは403エラーとなるテストも書くと良いです。
```kotlin:HogeControllerTest
@Test
fun test_ip_restrictions_forbidden() {
    mockMvc
        .get("/dummy") {
             // 許可されていないIPアドレスを指定する
            with(remoteAddr("yyy.yyy.yyy.yyy"))
        }
        .andExpect {
            // 403 error
            status { isForbidden() }
        }
}
```

以上です。
【基本情報技術者試験】非IT系職でも１ヶ月で合格できました。


2024年1月からエンジニア転職を目指して学習中です。

自分は30代未経験転職しようとしているため、少しでも履歴書に書ける内容を増やしておきたいという気持ちで受験しました。

あまり時間を取られたくないと思い、学習期間は1ヶ月と決めて試験を受けました。

私の体験がこれから受ける方の参考になれば嬉しいし、自身の振り返りも含め記事にしてみました。


## 自己紹介

試験申し込み時点での私のステータス。

・国立大卒（文よりの理）
・非IT系職種
・平日ワンオペ育児中の時短勤務
・progate1ヶ月契約し、web開発コース、SQL、Ruby修了

高校では理系クラスで数IIまではガッツリやっていた。
大学以降は皆無。


## 学習開始当初のレベル

学習開始し、テキスト初っ端の基礎理論で2進数の意味を初めて知って、数字＝10進数の常識が覆されて驚いた。
log、集合、確率などの計算も忘れていた。
知らない横文字ばかりで初めて聞く単語だらけ。

SQLや科目Bのプログラミングは、試験前に1ヶ月やってたprogateのおかげでなんとなくは理解。
しかし、実際のアルゴリズムのトレースは何度も迷子になった。

参考書を１冊読んだ後、過去問道場で科目Aの過去問を解き始めた時は、正答率30％台。

2週間後くらいに60％台、試験直前は80％台まで上がった。


## 学習に使用したもの

①「かんたん合格基本情報技術者教科書　令和2年度」
②「イメージ＆クレバー方式でよくわかる栢木先生の基本情報技術者教室 令和04年度」
③過去問道場
④youtube解説動画

①②のテキストは図書館で借りた。
なんと学習費用ゼロ円のケチっぷり。

過去問で理解を深める方が重要と考え、テキストはどういう内容がふくまれるか確認できればよかったので課金せず。
２冊借りたのは、図書館の返却期限の関係上、違う参考書を読むことになってしまったため。

①より②の方が情報量多く、出題範囲がよく網羅されてた。

③過去問道場は本当にお世話になりました！！！！

無料だし、解説もあるし、隙間時間でもポチポチ学習できるので助かる。

④のyoutubeも然り。いい時代に生まれた。


## 学習方法

【１週目】
テキストを１周読んで、試験範囲を把握。

【２週目】
過去問道場で科目A対策＆令和5年科目B公開問題とサンプル問題で科目B対策

科目Aは過去問回して、解説読んで、テキストで確認して、わからなければネットで調べる。

科目Bは試験形式が2023から変更になっているため、それ以前の過去問は解かず。
１つずつ、何が定義されているのか、どうしてこの順番なのか理解できるまで調べた。
youtubeの解説がわかりやすく、全問確認した。
（ちなみに、わかりやすくてもわからないことあってすごい調べるの時間かかった気がする。）

【３週目】
過去問道場で科目Aをひたすら解く＆テキスト２冊目を読む

【４週目】
科目Aの苦手分野解く＆科目A未回答問題実施＆科目Bのサンプル問題確認

過去問道場で分野絞って実施
科目Bのサンプル問題を自分の力で解いていき、理解チェック



 計算問題など理解できず調べたりしていて時間がかかり、思ったより数こなせず。
 過去問道場の総解答数は250問くらいだった。（過去問道場で★おすすめにチェック入れて問題始めると800問あるので1/4強）

 総学習時間は不明。
 育児しながらなので、まとまって時間が取れるのは、平日は朝夕の子どもが寝ている間、休日は朝夕＋出かけなければ昼寝中。
 とにかく科目Aは隙間時間を活用。昼休み、料理中、寝かしつけ中、隙あらば過去問解く日々だった。


## 受けてみて

【科目A】
600点ギリギリだなあという印象で、解きながら冷や冷やした。
知ってる語句や内容だとしても、問われる角度が変わるとわからない。
確実に取れる問題を確実に解いていくことに集中した。
過去問を解きながら問われてる内容の理解を深めていくのが重要だと感じた。
全然わからないと思っても落ち着いて選択肢を読んでみると、明らかに違うだろうというので２択くらいには絞れて、問われている内容から推測できるものもあったため諦めない気持ちは大事。
時間は余ったので、一度全部回答⇨見直す問題のみ回答⇨全部見直しまでできた。

【科目B】
先に選択肢を見ておくのが重要。トレースしなくても解けたりするのもあったりした。
見積もりで間違うのが不安だったので、丁寧にトレースした。
問題解くのが楽しくなってしまい、途中から綺麗にトレースすることが目的になり、気づけば４問手付かずになってしまった。（適当に選択はした）
これは600点越えたなという感触があったために、問題一覧を見た時に見直し＆未回答問題が意外と多くて焦った。
時間配分大事。


## まとめ

試験形式が変わっても過去問をベースに知識獲得していくのは有用でした。

また、プログラミング学習を始めていたのは大きかった・・・
非IT系人間が科目Bを一から理解する場合、1ヶ月は無理！という印象でした。

よく業務に使えないとか言われるけど、全く情報系の学習をしていない私としては、体系的に幅広い知識を得られたので良かったです。
SequelizeのonUpdateはPostgreSQLで機能しない

## 今回、罠にハマった問題
データベースがPostgreSQL、ORMにsequelizeを使った環境で、migrate機能を使ってテーブルを作成しました。
データの更新日時を記録したかったので、updated_atのカラムを追加したのですが、UPDATE文を発行してもupdated_atは更新されませんでした。

``` migration.js
updated_at: {
    allowNull: false,
    type: Sequelize.DATE,
    defaultValue: Sequelize.literal('CURRENT_TIMESTAMP'),
    onUpdate: Sequelize.literal('CURRENT_TIMESTAMP')
}
```

（onUpdateがあるので日時は自動更新されそうな雰囲気ですが）

## 原因
PostgreSQLには、データの変更時に日時を更新する機能が備わっていない為、Sequelizeのmigrationファイルで設定してもデータベースには何も反映されていないと考えられます。

## 解決策
SQLでUPDATE文を発行する際に、手動でupdate_atの更新を行いました。
CURRENT_TIMESTAMPで現在時刻が取得できます。

``` sample.sql
UPDATE users SET name = taro, updated_at = CURRENT_TIMESTAMP WHERE id = 1
```

PostgreSQLのトリガー機能を使って実装すると、データベース側で自動更新できるようですが、今回はアプリ側が発行するSQLで対処しました。
UNIX Linux macOS Windowsの違い

# はじめに

「MacはUNIX系のOSらしい」
「Linuxコマンドがデフォルトで使えるらしい」
「WindowsはLinuxコマンドが使えないからWSLを使おう」

・・・などと聞いたことがありますが、それぞれの関係を説明できるでしょうか？
僕はできません。ということで調べました。

# それぞれの関係

```mermaid
graph TD;
  UNIX-->B(Linux)
  Windows
  E-->B
  subgraph UNIX
    D(macOS)
  end
  subgraph Windows
    E(WSL)
  end
```
少し誤解を招く図になっているので、補足します。

- macOSはUNIXシステムの一つ
- LinuxはUNIXをもとにつくられたもの。「改造」というよりは「1から作った」と言えるものらしい。
- Windowsは別枠。WSLという機能を使うと、Windows上でLinuxを動作させることができます。
  知らなかったんですが、WSLはWindowsの「機能」なんですね。アプリケーションではなく。
  [Linux 用 Windows サブシステムとは | Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/wsl/about)
# おまけ：「MacOS」は間違い

しっかりと調べたわけではないのですが、「MacOS」は間違いで、「macOS（mが小文字）」が正解のようです。

[macOS Sonoma - Apple（日本）](https://www.apple.com/jp/macos/sonoma/)
Apple公式を見てもmacOSと記載されています。

AppleのOSの歴史も関係してきそうです。
## macOSの歴史
もともとは「MacOS 9」あるいは「MacOS X」だったようです。UNIXとは別の、オリジナルのOSでした。

しかし、歴史を重ねるにつれ、旧型のPCから使い続けてきたMacOSは肥大化していきました。

そこで、スティーブ・ジョブズ（一時はAppleから追い出されていた）が返り咲いたとき、ジョブズがAppleの外で作っていたNEXTSTEPというOSをもとに、MacのOSも入れ替えることになったようです。

ということで、"m"acOSという記載が現在は正しいということになるようです。

# 参考
https://qiita.com/tsudaryo1715/items/485f3521e3b9348879e3

https://eng-entrance.com/unix_linux

https://learn.microsoft.com/ja-jp/windows/wsl/about
PowerAutomate Sharepointのサブサイトでフォルダの作成方法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/b3d91e48-1d28-c6ac-3c04-9f3eb8923910.png)

Uri: _api/Web/Folders/add('shared documents/flowfolder1/subfolder1')
Headers:
Accept application/json;odata=verbose
Content-Type application/json;odata=verbose

# 参考サイト
https://powerusers.microsoft.com/t5/General-Power-Automate/Create-a-folder-structure-in-library-using-REST-API/td-p/967669
PowerAutomate Sharepointのサブサイトの作成方法

# Sharepointデフォルトのテンプレートの場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/22c6cb98-b27c-903c-e5e0-16196ea49ec0.png)

設定方法
```
a. サイトURL:https://test.com/sites/test/Projects/

b. POST 

c. Uri: /_api/web/webinfos/add 

d. Headers: Use the following header key-value pairs 
Accept application/json;odata=verbose 

Content-Type application/json;odata=verbose 

e. Body: Copy-paste following JSON to the Body input box 
{ '__metadata': 

{ 'type': 'SP.WebInfoCreationInformation' }, 

'Url':'@{variables('SiteURL')}', 

'Title':'@{variables('Site Title')}', 

'Description':'Project Site', 

'Language':'1033', （日本語1041）

'WebTemplate':'STS#3', 

'UseUniquePermissions':false 

} 

} 
```
# sharepointonline カスタマサイトテンプレートの場合
1.手動でサブサイトを作成

2.作成されたサイトをテンプレートとして設定
設定手順：
  サブサイト→サイトの設定
  →テンプレートとしてサイトを保存
  →ファイル名、テンプレート名、コンテンツを含むを入力
  →OKボタンをクリックして保存

3.サイトテンプレートIDを取得
※テンプレートが英語の場合、「言語の選択」を英語に変更しないと、下記の「Custom」タブが出ません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/4db0c18d-c155-734c-9eaa-9c1a5c695bc7.png)

:::note info
Finding the SiteTemplate GUID
The quickest way to get the GUID of a site template is to start creating a new site. When prompted to select the template open the “Custom” tab so that your template is shown. Press F12 in IE to open the developer bar and search for the template name.

参考サイト：https://www.dmcinfo.com/latest-thinking/blog/id/8661/create-site-from-template-using-sharepoint-2013-workflow
:::



4.テンプレートIDをフローに設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/b4494ff1-6ad5-a657-b782-f09abe8ffb2b.png)
設定方法
```
a. サイトURL:https://test.com/sites/test/Projects/

b. POST 

c. Uri: /_api/web/webinfos/add 

d. Headers: Use the following header key-value pairs 
Accept application/json;odata=verbose 

Content-Type application/json;odata=verbose 

e. Body: Copy-paste following JSON to the Body input box 
{ '__metadata': 

{ 'type': 'SP.WebInfoCreationInformation' }, 

'Url':'@{variables('SiteURL')}', 

'Title':'@{variables('Site Title')}', 

'Description':'Project Site', 

'Language':'1033', （日本語1041）

'WebTemplate':'{84659096-89AD-4CC4-B1E2-5048DE9EDA46}#ProjectSiteTemplate', 

'UseUniquePermissions':false 

} 

} 
```


# 参考サイト:
https://www.annajhaveri.com/sharepoint/create-a-sharepoint-online-subsite-from-power-automate-flow

https://www.dmcinfo.com/latest-thinking/blog/id/8661/create-site-from-template-using-sharepoint-2013-workflow

https://powerusers.microsoft.com/t5/Building-Flows/How-to-find-custom-Site-WebTemplate-ID-in-order-to-automate-site/td-p/421454

https://blog.binaryrepublik.com/2017/06/create-subsite-programmatically-using.html
react-testing-libraryでquerySelectorAllを使ってデータを取得する

# はじめに
react-testing-libraryを使ってテストを書いていたのですが、データを取得する際に**querySelectorAllというメソッドに出会った**ので、メモとして残します。
# 問題
テスト実装過程で下記の処理を行いましたが、**データが取得できていませんでした。**
```tsx:tsx
// データ数を取得
const initialRecords = screen.getByTestId("table");
```
今回取得したいデータはこちらです。
```tsx:tsx
<Tbody>
    {records.map((record) => (      
      <Tr data-testid="tr" key={record.id}>
        <Td>{record.studyContent}</Td>
        <Td>{record.studyTime}</Td>
        <Td>{record.createDate}</Td>
        <Td>
          <Button 
          data-testid="delete" 
          onClick={() => onClickDelete(record.id) } 
          colorScheme='teal' 
          variant='outline'>削除
          </Button>
        </Td>
      </Tr>
            ))}
</Tbody>
```
# 解決方法
`querySelectorAll`を使用すると、適切にデータを取得できました。
```tsx:tsx
// データ数を取得
const initialRecords = screen.getByTestId("table").querySelectorAll("tr");
```
# おわりに
**`querySelectorAll`とは**
**DOM要素からマッチするすべての子要素を取得するためのメソッド**です。

今回の場合、`screen.getByTestId("table")`で取得したDOM要素がテーブルであると仮定すると、**`querySelectorAll("tr")`はそのテーブル内のすべての`<tr>`要素を取得します。**

 `screen.getByTestId("table")`だけだと、**テーブル自体の要素を取得しますが、その子要素までは取得できない**ということです。
実数を分数で近似する

例えば、円周率$\pi$は$3.14\ldots$なので$314/100$という分数で近似するということもできるが、$22/7=3.1428\ldots$の方が314や100よりも小さい数で近似できていて「良い」と言える。このような分数を見つける方法として、連分数を利用する方法が知られている。

```python
from itertools import islice
from sympy import pi, continued_fraction_iterator, continued_fraction_convergents

list(continued_fraction_convergents(islice(continued_fraction_iterator(pi), 10)))
```
    [3,
     22/7,
     333/106,
     355/113,
     103993/33102,
     104348/33215,
     208341/66317,
     312689/99532,
     833719/265381,
     1146408/364913]

少し調べれば分かるが、$\pi$よりも小さい値と大きい値が交互に現れる。つまり、$3<\pi<22/7$, $333/106<\pi<355/113$というようにして、真の値$\pi$に近づいていく。そして、これが分数での「最良」の近似であることも知られている(どういう意味で「良い」のかの説明は専門書に譲る)。

どんな実数でも連分数を使うことが可能だが、特に(平方数でない$d$について)$\sqrt{d}$のような数において著しい特徴がある。循環小数では表せないが、循環連分数では表せるのだ。

```python
continued_fraction_periodic(0, 1, 2)
```
    [1, [2]]

は、$\sqrt{2}$が
$$
1+\frac{1}{2 + \frac{1}{2 + \frac{1}{2+\ddots}}}
$$
と表せることを意味している。

なお、sympy 1.13からは`continued_fraction_convergents`に`[1, [2]]`のような形で連分数を指定することもできる。
Elixirでのポリモーフィズム


# Elixirでのポリモーフィズム

Elixirでもポリモーフィズムを使うことができる。言語の機能として提供されているのはプロトコルだが、似たような使い道で、動的ディスパッチや、パターンマッチ、高階関数、プロセスなどが選択肢にのぼる。ユースケースのテストでIOへの依存を取り除く目的ではプロトコルと構造体、ビジネスルールを適切な依存関係にするためには高階関数が使えると思う。疎結合にする目的ではプロセスが良いのではないかというのが個人的な見解。

#### 取り扱うテクニック
- 動的ディスパッチ
- プロトコルと構造体／ビヘイビア
- ガード節とパターンマッチ
- 高階関数
- プロセス

#### 動的ディスパッチ

モジュールはElixirにおいて atom であり、変数に束縛させることも、関数の引数として与えることもできる。モジュールの関数は、モジュール名を使うだけではなく、束縛された変数や、受け取った引数に`argument.function()`のようにドット関数名を続けて呼び出すことができる。

動的ディスパッチの場合には、型が atom としてしかチェックされないので、ほぼ静的型付けの恩恵を受けられない。モジュールに束縛された変数から関数を呼び出すまでは、関数が定義されているかどうかはわからず、ランタイムに関数が定義されていなかったときにエラーとなる。

動的ディスパッチは簡易な実装としては便利だが、プロトコルと構造体／ビヘイビアに成長させるのが良いだろうと思う。

#### プロトコルと構造体／ビヘイビア

プロトコルと構造体の組み合わせによりポリモーフィズムをElixirで実現する。プロトコルで定義した関数を構造体で実装する。`defprotocol`によってプロトコルの定義を宣言し、`defimpl`によってプロトコルの実装を行う。「プロトコルと型」の組み合わせで行う方法と、「構造体へプロトコルを実装する方法」の二つの実装方法がある。

`defimpl <protocol>, for:`に続けて型を指定することができる。つまり、「プロトコルと型」の組み合わせごとに実装を行うことができる。モジュールの中に置く必要はない。

構造体のモジュールのスコープ内で`defimpl <protocol>`を実装することもできる。`defmodule`と`defstruct`によって定義された構造体に、`defimpl`のブロック内で、プロトコルで定義した関数を付け加える。これによって、プロトコルを構造体に実装することができる。`, for: <type>`は不要。オブジェクト指向言語でいうと、クラスがインタフェースを実装するようなものといえる。プロトコルで定義された関数のシグニチャは、ビヘイビアの受け入れのための属性定義 `@behaviour <behaviour>`と同様に`defimpl`での定義がされていないと警告がされる。なので、ビヘイビアを組み合わせて使う必要はない。

ビヘイビアは、`@callback` 属性に指定された関数の定義に対し、`@behaviour <module>`属性を定義したモジュールで関数の実装を強制する仕組みである。

プロトコルは、オブジェクト指向プログラミングでいうところのストラテジーパターンや、コンポジットパターン、ヌルオブジェクトパターンなどに使えると思う。テストのためのモックを与える仕組みとして使うこともできる。ビヘイビアは、デザインパターンのテンプレートパターンと類似したものと考えることができる。

#### ガード節とパターンマッチ

関数のガード節を用いたり、引数のパターンマッチを書くことで、引数により処理を分けることができる。同じモジュール内で実装しなければならない。同じモジュールである制約から、モジュールをデータ処理プロセスとしてひとかたまりにする必要がある。引数のパターンマッチの作り方によっては、内部実装を知る必要が生じてしまう。`@spec`の型システムによるドキュメンテーションにより、クライアント側の実装に必要な情報の開示ができる。第一引数にatom取って、コンテキストに応じた処理の切り分けを行うことが慣例化している。VSCodeで関数名を書くと、選択可能なatomがエディター上で表示されるという開発者体験となる。残念ながら、選択肢にないatomを選択してもDialyzerによる静的解析においては、エラーにはならない。

#### 高階関数

関数を引数として関数に渡し、実装を行う方法。引数として渡される関数はコールバック関数と呼ばれる。この方法はビジターパターンのようにデータ（例えばリストなど）を保持している関数に、データ処理ロジックを与える場合に使うことができる。

初歩的な例だと、関数はデータ処理ロジックであり、引数にデータを取る。これを逆転させ、関数にデータを取り、引数に処理ロジックを取るという逆転がしたい。この時、高階関数が使われる。

疑問に感じるかもしれない。Elixirのパイプラインは、IOに始まりIOで終わるものだとすると、パイプラインで受け渡されるのはデータである。そのため、関数をパイプラインでつなぎ、引数にデータをとれば十分だ。また、データの型によってデータ処理内容が変わるのであれば、プロトコルを使えばよい。

処理対象データではないデータはパイプラインにはのらない。パイプライン上引き渡されないデータには、マスタデータであったり、環境変数などのコンテキスト情報が考え付く。これらの情報を渡すために高階関数を用いることが考えられる。

データ処理ロジックと、ビジネスロジックを分離したいかもしれない。ビジネスロジックはパイプラインに埋め込まれてしまうと、他の大したことのないロジックと混在してしまって見つけにくくなってしまう。この時ビジネスルールを関数化して引数として渡すということが考えられる。ビジネスルールの関数やモジュールの命名を工夫すれば、パイプライン上特別な位置づけだとわかる。

詳細への依存性を外部から注入したいかもしれない。外部APIの呼び出しを高階関数によって実現することも考えられる。関数型プログラミングのテクニックが使える。

#### プロセス

Elixirの場合、アクターモデルで並行プログラミングが実現される。プロセスはオブジェクト指向言語のオブジェクトのような気軽さで作れる。なのであれば、ポリモーフィズムもプロセス（PID）を使って実装するというのも良い。依存性逆転をするだけではなく、プロセスからも切り離すことができる。データベース更新やメール送信などのプロセスを別のプロセスとして spawn しておき（オブジェクト指向のファクトリーのようなもの）、渡されたPIDに対してメッセージを送るという仕組みであれば、結合度が低いし、簡単。

Elixirの並行プログラミング指向のよさを生かすとすると、システムの詳細（ファイルへのアクセス、データベースへのアクセス、外部APIの呼び出しの処理）についてはカジュアルに分けてしまうのがよさそう。プロセス間ではメッセージを atom でやり取りするのがよくつかわれる方法だが、OTPを使えばより簡単かつ本格的に対応することができる。

ただ、並行プロセスをテストするのは一段難しいので、テストダブルを作る目的でプロセスを使うことはないだろうと思う。
Powershellの文字コードについて

#### コンソールの文字化けを防ぐ
- PowerhsellファイルをUTF-8 BOMありで保存する(Shift JISで保存した場合、Shift JIS定義内でも日本語含むパスが文字化けする)
- Powershellのコンソールで日本語を含む文字コードになっていることを確認する(MSゴシックなど)
- Powerhsellファイルに「chcp 65001」を記載する（不要?）
#### ファイルの文字化けを防ぐ
- Powershell 5.1(2024/03時点デフォルト?)でSet-Contentを使用するとShift JISやUTF-8 BOMなしでのファイル出力がうまくいかない(ただし、PowerShell 7.0以降でutf8NoBOM追加)
- Get-ContentでUTF-8は読み込めたが、Shift JISの読み込みはうまくいかない
- そのためSystem.IO.Fileを使用する。以下正規表現で置換するサンプル
```powershell:UTF-8 BOMありで保存すること!
$path = 'C:\Users\user\Documents\test.txt'
$sjis = [System.Text.Encoding]::GetEncoding(932)
$utf8_bomless = New-Object System.Text.UTF8Encoding $False
$lines = [System.IO.File]::ReadAllLines($path, $sjis)
$result = @()
foreach ($line in $lines) {
    $result += $line -replace '^bar1$', 'bar①' # 正規表現で置換する場合
    if ($line -match '^bar2$') {
        # 正規表現に一致した行の下に追加する場合
        $result += $line
        $result += 'bar2.1'
        $result += 'bar2.2'
    }
}
### ここから、改行コードと最終行が空行かどうかの判定のためだけの処理
$text = [System.IO.File]::ReadAllText($path, $sjis)
$split = $text.Split("`r")
$s = ''
if ($split.Length -gt 1) {
    if ($split[1].StartsWith("`n")) {
        $s = "`r`n"
    } else {
        $s = "`r"
    }
} else {
    $s = "`n"
}
$output = $result -join $s
if ($text -match ($s + "$")) { # 最終行が空行の場合追加する
    $output = $output + $s
}
### ここまで

[System.IO.File]::WriteAllText($path, $output, $utf8_bomless)
# WriteAllLinesは最後に空行が追加されること、改行コードがCRLFに変わることから使用できない
```
```powershell:ReadAllTextのみで実現する場合より複雑になる
$path = 'C:\Users\user\Documents\test.txt'
$sjis = [System.Text.Encoding]::GetEncoding(932)
$utf8_bomless = New-Object System.Text.UTF8Encoding $False
$text = [System.IO.File]::ReadAllText($path, $sjis)
$split = $text.Split("`r")
$s = ''
if ($split.Length -gt 1) {
    if ($split[1].StartsWith("`n")) {
        $s = "`r`n"
    } else {
        $s = "`r"
    }
} else {
    $s = "`n"
}

$array = @(
    ('bar1', 'bar①'),
    ('bar2', @'
bar2
bar2.1
bar2.2
'@
    ), ('foo1', 'foo①'))

foreach ($item in $array) {
    # この順番だと恐らくうまくいく
    $text = $text -replace ($s + $item[0] + $s), ($s + ($item[1] -join $s) + $s)
    $text = $text -replace ('^' + $item[0] + $s), (($item[1] -join $s) + $s)
    $text = $text -replace ($s + $item[0] + '$'), ($s + ($item[1] -join $s))
    $text = $text -replace ('^' + $item[0] + '$'), ($item[1] -join $s)
}

[System.IO.File]::WriteAllText($path, $text, $utf8_bomless)
```
20240317 SlimBlade設定あれこれ、RR-automate改善（ちょっと）

### 自動コープツールの準備

いろんなボタンがあるので、それらをとりあえず記録しないと

### Slimbladeの設定

あまり凝った設定にするとわからなくなるのでバックと右クリックの位置を変えたのと、した二つ同時押しを右タブ、右二つ同時押しを左タブに移動、に設定した

気になるのがこのアプリ
[X-Mouse Button Control のインストール | Nonsubject](http://nonsubject.arinco.org/2011/11/x-mouse-button-control.html)

### RR-automate改善

UnitとHeroのImageクラスを消したのであれこれやらないとだ。使ってないと思っていたが間違いで使いまくっていた
今まで名前でソートしていたけど、この際なので種別→レアリティでソートすることにする
さらにアタッカーでの集計とかもできそうな気がする

けど時間がかかりそう
なので今一つ動いてないこれを使うのはやめて、githubの最近のでとりあえずやることにする、と思ったが

#### git fetch originで面倒くさそうなエラー fatal: Could not read from remote repository. が出た

WindowsのPowershell開いて最新のにしようとおもったらそんな一筋縄ではやらせないという魂胆らしい

```
> git fetch origin
The authenticity of host 'github.com (20.27.177.113)' can't be established.
ED25519 key fingerprint is SHA256:+DiY3wvvV6TuJJh**************************.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'github.com' (ED25519) to the list of known hosts.
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
だいたいわかります。普段使っているwslの方ではsshのカギを.sshの下にいれてconfigでgithub.comのアクセスにはそのカギを使うように設定している
こんな風に
```
host github.com
  HostName ssh.github.com
  IdentityFile ~/.ssh/git_private_key
  Port 443
```
けどWindows側ではそんな設定していない、だから、いい機会なのでキーを%HOME%/.sshの下に置いて、configも同様な設定にした。IdentityFileにはCドライブから書くのがいいのかよくわからなかったけど、.sshから始めたら動かなかったので安全のためCドライブから書いた、そしたら無事に動いた

参考：[git: fatal: Could not read from remote repository - Stack Overflow](https://stackoverflow.com/questions/13509293/git-fatal-could-not-read-from-remote-repository)

#### クラスについて

ユニット、ヒーローのクラスはほとんど同じ
ところで

##### 全然関係ないけどMaple Monoフォントすごいいい
文字に癖ないだけでなく、斜体がスクリプティックだし、TODOを見やすく書ける（２）し、リガチャがとてもきれい（３）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3740499/1a3d7595-dcb1-73b5-fd35-40579f50e614.png)

中国の人が作ったので漢字・平仮名も問題なしです
（たぶんハングルも）

クラスの構成はこんな
ベースとなるCardBase、それを派生したUnit、Heroがある

CardBase
    key
    key_max
    raritey
    name
    name_jp
    images
    image_path（なんだっけ、これ？、、、そうそうヒーローやユニットの画像へのパスだ）

Unit(CardBase)
    type
    toxic

Hero(CardBase)
    （CardBaseとの違いは特になし）

#### 自作のソートを作る

`__lt__(self, other)`と`__gt__(self, other)`を作るとよいっぽい
ltのほうは `self < other`なら`True`、gtはその逆

### Kensignton SlimBlade、回来了(合ってる？)

ブラウザはVimiumCを使って操作してるんだけど、SlimBladeから手を放さずあれこれしたいという欲張りな気持ちになってきた
ページのスクロールやタブを前後に移るのは左手一つで、またfを押したときのリンクへのショートカットも左手でカバーできる範囲にとどめることにした

Vimium Cの設定はこんな感じ
```
# キーマップ
unmap d
map a previousTab
map d nextTab
map w scrollUp
map s scrollDown
map ea goBack
map ed goForward
mapKey <c-q> <esc>

# リンクへのショートカット
# もともと：sadjklewcmpgh
# 小指はつりそうになるので酷使しない設定
asdfxcvwer
```

やっぱり投稿したのは翌日の3/18になってしまった
Eclipse 2024-03とLombok Plugin(1.18.30)の問題の回避策

## 最新のEclipseでLombokがエラーを出力する
Eclipse(2024-03)とLombok　Plugin(1.18.30)の組み合わせでは、エラーが発生してコードに警告が出たり、コンパイル不能なケースがあるようです。
Gradleを使用しているとエラーの警告が表示されているのにコンパイルは通るという状態になります。
### (2024/4/26 追記)
v1.18.32 (March 20th, 2024)で解決しているようです。記事作ってすぐに解決してました。悲しい。

## 回避策
マーケットプレイスのプラグインは使用せず、 **[edgeバージョン](https://projectlombok.org/download-edge)をダウンロードして使用します** 。インストールの方法は通常版と同じです。
Windowsでダブルクリックで起動できない場合は、コマンドプロンプトから直接起動させてください。
```batch
java -jar <path to edge.jar>
```

また、慣れている方は`.ini`に`-javaagent:<path to edge.jar>`で手動で指定しても良いでしょう。
インストール後にEclipseを再起動してから、ビルドを試してください。

## 今回の情報源
[Internal package changes in ECJ will break Lombok.](https://github.com/projectlombok/lombok/issues/3564)
どうやらLombok側でEclipseの意図していない内部クラスを使用していたことが原因のようです。
ただ、いつプラグインやMavenリポジトリに反映されるかは見通しが立っていないようです。

ひとまずエラー解決の助けになれば幸いです。