OmniAICreator/Qiita-1.07M huggingface dataset:
Kubernetesコンテナでulimit -n("file open")の値を増やしたい

# はじめに

これは主にkubesprayでKubernetesクラスターを構築した人向けの記事です。

Deepfence社のThreatMapperをk8s環境で起動しようとしたところ次のようなエラーが発生して起動に失敗しました。

```text:
$ sudo kubectl -n deepfence logs deepfence-console-router-76f584f46d-pl46d 
Starting router
[NOTICE]   (1) : haproxy version is 2.8.5-aaba8d0
[ALERT]    (1) : [haproxy.main()] Cannot raise FD limit to 1000051, limit is 65535.
```

なんでこんなに低いんだろうとは思いながらも検索すると、次のような記事がみつかり、/etc/containerd/cri-base.jsonの設定値を変更することで対応できました。

* [github/kind - limit of file descriptors inside a container always is 1024 #2532](https://github.com/kubernetes-sigs/kind/issues/2532)

containerdを再起動してからPodを再作成すると無事にPodが立ち上がりました。

```text:
Starting router
[NOTICE]   (1) : New worker (11) forked
[NOTICE]   (1) : Loading success.
```

# 背景の調査

対応方法にはすぐに到達しましたが、後学のために少し調べておきます。

## OSレベルでの設定の確認

設定方法はいくつもありますがデフォルトの状態であれば関連するのは、/etc/sysctl.conf周辺と、/etc/security/limits.confの2点だと思います。

## /etc/sysctl.conf

設定については例えば次の記事をみると関連する設定が分かります。

* [Azure Kubernetes Service(AKS)ノードプールのノード構成をカスタマイズする - ファイルハンドルの制限](https://learn.microsoft.com/ja-jp/azure/aks/custom-node-configuration?tabs=linux-node-pools)

* fs.file-max
* fs.inotify.max_user_watches
* fs.aio-max-nr
* fs.nr_open

今回のエラーに対応するには``fs.nr_open``が十分に確保されていれば良さそうです。

確認するとこの数値はデフォルトの``1048576``に設定されているので問題はなさそうです。

## /etc/security/limits.conf

設定を確認すると、次のような設定だけが入っていました。

```text:/etc/security/limits.conf
* soft nofile 5120
```

hardではないので変更する必要はないのですが、VSCodeかIntelliJを使った時に問題があったので増やしたような気がします。

いまとなっては65536程度に増やしても問題ないですが、これはこのままにしておきます。

結果的にOSレベルでは問題はありませんでした。

# Kubesprayでの設定の確認

手動でファイルを編集するのは冪等性が維持できず良くないので、Ansibleでの設定方法について確認しておきます。

findでgrepをかけて回るとcri-base.jsonファイルに関係する設定がいくつか確認でき、パラメータで検索すると次のように初期値が設定されていることが分かります。

```yaml:roles/container-engine/containerd/defaults/main.ymlからの抜粋
...
containerd_base_runtime_spec_rlimit_nofile: 65535
...
containerd_default_base_runtime_spec_patch:
  process:
    rlimits:
      - type: RLIMIT_NOFILE
        hard: "{{ containerd_base_runtime_spec_rlimit_nofile }}"
        soft: "{{ containerd_base_runtime_spec_rlimit_nofile }}"
```

というわけでansible-playbookの"-e"オプションで設定したシステムのリミットを越えない範囲で十分に大きな数字を設定することにします。

```bash:
$ ansible-playbook ... -e containerd_base_runtime_spec_rlimit_nofile=1048576 upgrade-cluster.yml
```

:::note warn
v2.24.2では``-e containerd_base_runtime_spec_rlimit_nofile=1048576``を指定したことによって、/etc/containerd/cri-base.jsonの中に数値ではなく文字列として1048576が反映されたことでcontainerdが正常に稼動しないエラーになりました。``sudo crictl info``が該当ノードで正常に動作しない場合にはこのファイルの修正を試みてください。
:::

以上
Microsoft Formsでフォームの初期値を指定する

今回は実のところただの製品機能紹介なのですが、待ち望んでいた機能でとても便利なものなのでこの場で紹介させてもらいます。

# Background

Microsoft Formsで組織内のメンバーを対象者とするアンケートフォームを構築・運用している。
アンケートは組織内で開催されている各種の勉強会について参加者に入力を求めるもの。個々の勉強会にはIDが振られている。アンケートフォーム冒頭には回答（評価）の対象となる勉強会のIDを入力する欄がある。

# Problem

フォーム冒頭の入力欄（勉強会のIDを入力）に入力すべき内容は、アンケート回答を依頼する（フォームURLを案内する）時点で決まっているのだが、その入力は個々の回答者任せになっているため、手間がかかるうえ誤入力が後を絶たない。

# Solution

「事前入力済みURL」機能を利用する。

フォーム編集画面右上「…」→「事前入力済みURLの取得」をクリック：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/16199eff-af12-8a43-cd95-159c362feeb8.png)

「事前入力済みの回答を有効にする」をオン、回答を入力し、「事前入力されたリンクを取得する」をクリック：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/9a673406-188e-8e7f-0455-9a077e4ec520.png)

すると `https://forms.office.com/Pages/ResponsePage.aspx?id=(フォームID)&(質問ID)=(事前入力した内容)`形式のURLが得られる。

このURLでアクセスをすると、「事前入力した内容」が初期値として指定された状態のフォームが表示される：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/e294f5ae-9d2e-0138-f700-8704ae3391d8.png)

上記URLからすぐ想像がつく通り、フォームURLの「事前入力した内容」の部分を直接書き換えてアンケート対象者に配布することで、任意の内容を初期値として指定することができる（Microsoft Formsのフォーム編集画面を経ずに、動的に初期値を指定できる）。

従来（私の知っている限り2023年くらいまで）はこのような仕組みがなかったため、Problemで延べたような問題が生じていた。この機能を用いることで問題を回避することが可能になる（といいつつ、まだ実戦投入はしていない）。

:::note warn
注意点として、次のような2つの事前入力内容を指定するURLがあったとき・・・

* 初期値「AAA」　`https://forms.office.com/Pages/ResponsePage.aspx?id=(フォームID)&(質問ID)=AAA`
* 初期値「BBB」　`https://forms.office.com/Pages/ResponsePage.aspx?id=(フォームID)&(質問ID)=BBB`

「AAA」のURLでフォームにアクセスした後、そのフォームを送信したりフォームの初期値をあえてクリア（削除）したりする前に、矢継ぎ早に「BBB」のURLでフォームにアクセスすると、URLで指定した値（「BBB」）は無視され、初期値としては「AAA」が採用される。
:::
基本情報技術者の壁2

# 頭に「？」がいっぱい
---
前回の投稿で**基数変換**について記述しましたが、ちょっと深掘りしていこうと思います。
試験の過去問でも基数変換の問題は割と出てきます。私はすこぶる苦手です。
私自身小難しいのが苦手なのでふわっとした感じで表記します。

## 1.まずは2進数の仕組み
---<font color="Red">2進数とは</font>---
コンピュータは人間と違って言葉を話すわけではありません。
コンピュータは独自の言葉で様々なことを認識します。その独自の言葉が「**2進数**」です。
2進数は「0」と「1」で構成されています。
ざっくりした認識は「**いい**」か「**わるい**」みたいな感じです。
人間みたいに「**微妙**」とかっていうのがない感じです。
## 2.2進数から10進数の変換
---<font color="Blue">足し算します</font>---

まず2進数の**桁の重み**の表を記します。
![スクリーンショット 2024-06-05 112612.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807012/5faf9f9f-4c72-8e52-6aee-9eb7031c8b69.png)

これ、ぱっと見じゃ何が何だか分からん！と私は思いました。
なので私は自分の分かりやすい認識で考えることにしました。
表に記載されている2の〇乗っていうのを賢くない私がいちいち計算できないので
下の「1.2.4.8~~」の部分に着目しました。
その上での認識として右の数字に×2したら左の数字になると認識しました。
2の6乗＝64　2の7乗＝128　64×2＝128　といった感じです。

この「11111111」を10進数に変換すると「255」のなります。
計算としては「128+64+32+16+8+4+2+1」です。
単純に表の下部の数字を足していくだけですね。

そのうえで次の2進数の例を10進数に変換します。

#### **11110000**

これを10進数に変換すると

#### **240** になります。

ざっくりいうと「1」の表記がある「**桁の重み**」を「<font color="Blue">足し算</font>」するだけです。
上記の表で見ると「128+64+32+16」の足し算の合計になります。

## 3.10進数から2進数の変換
---<font color="green">割り算します</font>---

上記で足し算を行ったので、「だったら引き算！」とはなりませんでした。
ここで私は躓きました。引き算じゃないんかい...

10進数から2進数に変換するときは「<font color="green">割り算</font>」
ここ大事です。

下部に変換の例を記します。
10進数「240」を2進数にしてみます。
![スクリーンショット 2024-06-05 134022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3807012/2ab24978-0519-13df-214f-70d64db83e08.png)

240をどんどん2で割っていきます。
割れなくなったらそこで終わりです。
この計算の中で余りが出ますが、その余りが2進数でいう「1」の部分です。
上から順にみていくと「00001111」になります。
ですが、この場合「上から」ではなく「<font color="Red">下から</font>」記載します。
そういうルールなんだなっていう感じで覚えましょう。
なのでこの場合下から記載して

#### **240**　→　**11110000**

となります。
ざっくりいうと「10進数の数字」を「2」で割っていきます。
すると0と1の答えが並ぶので2進数の特徴である0と1の羅列ができます。
下から順に並べると毎度おなじみ2進数です。

重要なのは「<font color="green">割り算</font>」して「<font color="Red">下から</font>」並べるということです。

8進数や16進数の変換はややこしくなるので次の機会に...

---
全くの初心者の私にとっては難しいことばかりで同じ境遇の方は躓くのではないか、と思います。
今後も学習を行う中で初心者が躓きそうなものを更新していこうと思います。
[参考文献:栢木先生の基本情報技術者教室](https://www.amazon.co.jp/%E4%BB%A4%E5%92%8C05%E5%B9%B4-%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%EF%BC%86%E3%82%AF%E3%83%AC%E3%83%90%E3%83%BC%E6%96%B9%E5%BC%8F%E3%81%A7%E3%82%88%E3%81%8F%E3%82%8F%E3%81%8B%E3%82%8B-%E6%A0%A2%E6%9C%A8%E5%85%88%E7%94%9F%E3%81%AE%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85%E6%95%99%E5%AE%A4-%E6%83%85%E5%A0%B1%E5%87%A6%E7%90%86%E6%8A%80%E8%A1%93%E8%80%85%E8%A9%A6%E9%A8%93-%E6%A0%A2%E6%9C%A8/dp/4297131307)
【curl】Redmine APIを実行してチケット情報を取得する

# はじめに
Redmineのチケット自動作成ツールを開発している際に、チケットのデータ構造やプルダウンのkey valueの値を知りたいタイミングがありました。
そこで、Redmine APIをcurlで実行して確認したので備忘録です。

# チケット番号を指定してチケットのデータを取得
```bash
curl -H "X-Redmine-API-Key: {APIkey}" -X GET "https://{RedmineURL}/issues/{チケット番号}.json"
```
json形式でチケットのデータが出力されます。


# プルダウン項目（トラッカーなど）のIDを確認する
```bash
curl -H "X-Redmine-API-Key: {APIkey}" -X GET "https:/{RedmineURL}/{項目名}.json"
```

項目名の部分に確認したい項目名を指定してください。

例）トラッカー：tracker
　　ステータス：status
　　優先度：priority

# カスタムフィールドのIDを確認する
```bash
curl -H "X-Redmine-API-Key: {APIkey}" -X GET "https://{RedmineURL}/custom_fields.json"
```
カスタムフィールドの一覧を取得します。
筋肉にはタンパク質を。脳には、、。

## はじめに
マンガやアニメにでてくる頭脳派キャラってかっこいい！！！と憧れていたら、気づいたらここに流れ着いていていました、新人未経験エンジニアのいかです。(｀・ω・´)

偏見もあると思うのですが、エンジニアのみなさんにとって脳は最大の武器であると思うのです、、！！

ですが、脳を鍛えている人はいても、脳をケアしている人は体感あまりいないように思います。

脳を大切にしたいと思った方！ちらっとでもご覧いただけたら幸いです。(^^

ひと言でいうと、
「脳にもごはんをあげたい」というつぶやきです。

## 筋肉にはタンパク質を。脳には、、。

筋トレって一般的な言葉ですよね。
そして筋トレをする人は、意識的にタンパク質を多くとっている方が多くいらっしゃると思うのです。

脳トレもよくある言葉だと思います。
ですが脳トレをする人は、脳を育てるために意識的に栄養をとっているかと言われると、、
少なくとも私の周りではあまり見ないような気がするのです。

脳の栄養、みなさんはなんだと思いますか？
私は**DHA**だと思っています。

## DHAは脳内に入ることができる！
DHA（ドコサヘキサエン酸）。
どこかで見聞きしたことがある人も多いと思います。

脳には、有害なものが外部から入らないようにするフィルターのようなものがあり、脳内に入れる成分と入れない成分を選別しています。
**DHAはそのフィルターを通過することができる**成分なのです！

DHAは脳を構成する**約140億個の脳細胞の膜に存在**しています。
脳内でも特に記憶や学習に関わる海馬に多く集まっています。
DHAは脳を活性化する働きがあるため、海馬のDHA量が頭の良さに関わっているといわれており、**脳の栄養素**とも呼ばれています。

## DHAは具体的に脳で何してるの？
DHAには次の効果があります！

**1. 脳神経の再生**
脳神経を再生する。

**2. 神経の保護**
脳神経の酸化障害から保護する。

**3. 情報伝達の潤滑油**
潤滑油のような働きで、脳神経間の情報伝達を滑らかにする。

**4. 脳細胞の活性化**
ヘモグロビンの量を上昇させ、脳細胞を活性化する。

**5. 神経の保護**
アミロイド蛋白質βの大脳皮質への沈着を減少させることで神経保護する。


>次のような研究結果も、、！[参考サイト](https://tokuteikenshin-hokensidou.jp/news/2022/011621.php)
>
>魚を多く食べている人は、ほとんど食べていない人に比べ、思考スキルが優れており、脳の構造も健康である傾向があるという研究を、米国神経学会(AAN)が発表。
>DHAの値がもっとも高かったグループでは、思考力テストの平均スコアが高く、とくに抽象的推論が優れ、さらに、記憶で重要な役割を果たしている脳の海馬領域の平均体積も大きかった。


## DHAは体内でつくれない、、

DHAのことで覚えおいてほしいのが

**①体内ではほとんど作られない！！** のに、
**②魚以外の食材では十分に摂取できない！！**
ことです。

油や野菜にはほぼ皆無、肉類・乳製品には少量しか含まれていません。

脳はエンジニアのお仕事にとって、特に大切しなきゃいけないパートナーだと思うのです。

ぜひ！！今日から！！
魚を、とくに青魚を刺身で（加熱処理しないで）食べてみてください。
美味しい魚を食べて脳も体も心もはっぴーにしてください！


#### *余談です。
いかの脳はめっちゃ小さいです。
いかの脳は目と目の間にあります。
*ひれのついている筒状の部分は胴体ですので、あの部分に脳は入っていないです。

直径は1㎝にも満たないです。悲しい、、。笑

ですが、、！
みなさんには大きな脳があります！！
それだけの記憶と情報同士を結びつけられる脳をもっているんです。

羨ましい。笑

ぜひみなさんの大切な武器である脳を立派に育ててください。
 *青魚をたくさん食べてるイカですが、イカにはさほど多くのDHA・EPAは含まれていません。
ですからイカではなく魚を食べてください。(;´･ω･)

私のメンターさんが「エンジニアは体調不良になりがち。」とつぶやいていました。みなさんの健康に役立てていただけたら幸いです、、！

## 執筆者より
はじめまして！新人未経験エンジニアのいかです。

未経験者がおこがましい限りですが、頭をたくさん働かせて仕事をしているエンジニアのみなさんに少しでも有益になりそうなテーマを考えてみました。

私は水産学を専攻していたので、その知識を交えながらお話させていただきました。

正確な情報発信に努めてまいりますが、専門家ではないのでその点ご配慮いただけると幸いです、、。(-_-;)

## 参考
わかさの秘密
https://himitsu.wakasa.jp/contents/dha/

保健指導リソースガイド
https://tokuteikenshin-hokensidou.jp/news/2022/011621.php

ニッスイ
https://www.nissui.co.jp/product/epalife/memory/index.html

SUNTORY
https://www.suntory-kenko.com/contents/brands/dha/meal/except_fish.aspx

DHA・EPA協議会
https://www.dhaepa.org/q_and_a.html
Meta Quest で Azure Remote Rendering を動作させる手順

Meta Quest で Azure Remote Rendering を動作させる手順を調査していきます。

# 注意事項
Azure Remote Rendering の Meta Quest 2 / Meta Quest Pro サポートは、現在 Public Preview 段階です。PC / HoloLens と比較して、機能が制限されています。

- **サポート対象の Unity の最小バージョンは 2020.3.です。**
- Unity の OpenXR プラグインのみがサポートされています。
- Unity のユニバーサル レンダリング パイプライン (URP) を使用することをお勧めします。
- Vulkan レンダリング API のみがサポートされています。 OpenGL はサポートされていません。
- **Microsoft 認証ライブラリ(MSAL) は Quest デバイスでは動作しません。**
- **Quest デバイスがスリープ状態になり、再びスリープ解除された場合、リモート コンテンツがまったく再開されないか、回復に時間がかかる場合があります。**
- ArrInspector ツールはサポートされていません。

- [システム要件 - Quest 2 / Quest Pro](https://learn.microsoft.com/ja-jp/azure/remote-rendering/overview/system-requirements#quest-2-and-quest-pro)

# 検証環境
- 開発PC ( OS : Windows 11 Pro )
- Unity 2022.3.30f1 [with Unity Hub]
   - Android Build サポートモジュールインストール済み  
 - Android SDK [with Android Studio]
 - Azure Remote Rendering アカウントを作成済みであること

※ adb コマンドを使用する際は ``Android SDK Platform-Tools`` の PATH を通す必要があります。

# 手順
こちらの手順は、Azure Remote Rendering 公式ドキュメント  [クイック スタート: Unity サンプルを Quest 2 または Quest Pro にデプロイする](https://learn.microsoft.com/ja-jp/azure/remote-rendering/quickstarts/deploy-to-quest) に基づいています。

- GitHub からサンプルプロジェクトを Clone します
- 依存関係のあるパッケージを powershell スクリプトでダウンロードします

```cmd
> mkdir ARR
> cd ARR
> git clone https://github.com/Azure/azure-remote-rendering
> powershell -ExecutionPolicy RemoteSigned -File azure-remote-rendering\Scripts\DownloadUnityPackages.ps1
```

- Unity Hub から Unity プロジェクトを追加します (Unity/Quickstart)
- Unity プロジェクトが起動したら、Assets/Scenes/Quickstart シーンを開きます
- ヒエラルキービューから RemoteRendering ゲームオブジェクトを選択します
- RemoteRendering (Component) の ARR 認証情報を入力します
※ Azure Remote Rendering の アカウントID、キーは Azure Portal で確認することができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/3922fc73-985f-e53e-32f1-a4626ddab320.png)

| 入力項目 | 値 |
| --- | --- |
| Remote Rendering Region | リモートレンダリングリージョン |
| Account Domain | アカウントドメイン |
| Account ID | アカウントID |
| Account Key | アカウントキー  |

- 動作確認のため、Unity Editor で ゲーム再生を実行して、ARR モデルを読み込みます

以下の画像のように標準のエンジンのモデルが読み込まれれば、正しく設定ができています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/0065050d-6f25-c537-37ef-1856dadc8719.png)

Meta Quest 用に プロジェクト のビルド設定を行います

- Build Settings を開き、Android を選択した後、Switch Platform を実行します
- Meta Quest Pro を PC に USB 接続します
- Run Device で 接続した Meta Quest デバイスを選択して Build & Run を実行します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/180432/fbb3d75c-89b3-dd79-aafc-09e5085ee9ea.png)

Meta Quest 上で Azure Remote Rendering を動作させることができました。
ただ、Azure Remote Rendering で 3D モデルを読み込んだだけで、モデルの操作等はできないので、次回以降の記事でパススルーやモデルの操作について実現する方法を調査したいと思います。

# 参考文献
- [クイック スタート: Unity サンプルを Quest 2 または Quest Pro にデプロイする](https://learn.microsoft.com/ja-jp/azure/remote-rendering/quickstarts/deploy-to-quest)
- [サポートされているプラットフォームとデバイス](https://learn.microsoft.com/ja-jp/azure/remote-rendering/overview/system-requirements#supported-platforms-and-devices)
ZED SDK のステレオカメラでdepth計算の再現実験をする

ステレオカメラでのdepthの計算には、さまざまなパラメータが影響してくる。
そこで、その評価をしやすいように、再現実験ができる機能がZED　SDKにはあるので、それを紹介する。

## 同一カメラ動画で処理したときに、パラメータの違いを評価する
- ZED SDK では、対応カメラのデータを一つのファイルに保存できる。
- そのファイルを入力とすることで、ZED2iなどのカメラの入力に置換えて動作できる。

## 想定する読者
stereolabsのzed2, zed mini, zed z などのステレオカメラの利用者
いまどきのステレオカメラは何ができるのかを知りたい人

## 動作させた環境 
- ZED SDK 4.1 
- ZED2i Camera (StereoLabs)
- NVIDIA Jetson AGX Orin
- JetPack 5.1(=LT4 352.)
- Python3

## 使用例
```
# 動画ファイルの保存方法(SDKで用意されているスクリプト)
python3 svo_recording.py -h
python3 svo_recording.py --output_svo_file bottles.svo2
# 動画ファイルの再生方法(SDKで用意されているスクリプト)
python3 svo_playback.py -h
python3 svo_playback.py --input_svo_file bottles.svo2 
python3 your_sample.py --input_svo_file bottles.svo2
```

## コピー元のファイル
### ZED SDK - SVO Recording
https://github.com/stereolabs/zed-sdk/blob/master/recording/recording/mono/python/svo_recording.py

### ZED SDK - SVO Playback
https://github.com/stereolabs/zed-sdk/blob/master/recording/playback/mono/python/svo_playback.py

## your_sample.py で`--input_svo_file`　が動作するように作るには
- ZED SDK にあるサンプルプログラムには、`--input_svo_file`　のコマンドライン引数に対応しているのが多い。
- それを元に、自作サンプルyour_sample.py を作る。

## その他の利点
- ZED2i などのカメラが接続されていない状況でも、その動画ファイルを入力としたプログラムを実行できる。
- そのため、テストが実行しやすくなる。
- ZED SDK はライセンスがフリーなので、CircleCIなどで自動化テストできるかもしれない。
Spring BootでMyBatisログを出力する

# はじめに

こんにちは、Gakken LEAP のバックエンドエンジニアの Matsuura です。

Spring(Java)でDB操作の処理を実装する際には、MyBatisを採用することが多いですね。
ただ、MyBatisの初期設定では、クエリの実行内容や実行結果が確認できず、正しい結果が得られているかすぐには分かりません。
そのため本記事では、クエリの実行結果をコンソールログとして出力する方法をご紹介します。

# 方法

## ディレクトリ構成

ディレクトリ構成は以下の通りとします。

```text
src/
├─ main/
│  ├─ java/
│  │  ├─ com/
│  │  │  ├─ example/
│  │  │  │  ├─ mapper/
│  │  │  │  │  ├─ HogeDao.java
│  │  │  │  │  ├─ HogeDao.xml
│  ├─ resources/
│  │  ├─ application.yml
```

## 設定内容

対象となる`@Mapper`インターフェイスが格納されているディレクトリに対して、ロギングレベルを設定します。
今回の例であれば、com.example.mapper下のファイルをログ出力対象とします。
application.ymlに以下のように記述することで、クエリ実行ログ(SQLステートメント)がコンソールに出力されるようになります。

```yml:application.yml
logging:
  level:
    com.example.mapper: DEBUG
```

ちなみにapplication.ymlではなく、application.propertiesを利用している場合は、以下のように設定してください。

```properties:application.properties
logging.level.com.example.mapper=DEBUG
```

また、`DEBUG`の代わりに`TRACE`を設定すると、クエリの実行結果をコンソールに出力することが可能になります。

# おわりに

数行で設定できるので、ぜひMyBatisを利用する際は設定してみてください!

---

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています！！

https://gakken-leap.co.jp/recruit/
MT:Forを入れ子にした時の実行順

MT:Forを重ねて記載した時の実行順は記載した順ではなく入れ子の内側からになる。


例えばこんな感じで重ねまくってhtmlタグを除去してテキストだけにしたい場合
```
<mt:For regex_replace="/<("[^"]*"|'[^']*'|[^'">])*>/gm","">
<mt:For regex_replace="/<style.*</style>/gm","">
<mt:For regex_replace="/<script.*</script>/gm","">
<mt:For regex_replace="/(?:\n|\r|\r\n|\t)/mg","">
<p>テキストだよ</p>
<script>
スクリプトだよ
</script>
<style>
スタイルだよ
</style>
</mt:For>
</mt:For>
</mt:For>
</mt:For>
```

感覚では
`<mt:For regex_replace="/<("[^"]*"|'[^']*'|[^'">])*>/gm","">`
から、下に向かって順番に実行されるように勘違いしてしまった。

実際には
`<mt:For regex_replace="/(?:\n|\r|\r\n|\t)/mg","">`
から上に向かって順番に実行される。


#### 戒め

段階を分けて順番に置換して行く時って、実行順間違えると意図通りに動かなくなるので、どのような順番で動くのか意識していないとやらかす。

よくよく考えると当たり前なんだけど通常のプログラムばっかり書いていて久しぶりにMT触って混乱した点でした。




#### 余談
アウトプットって難しい。精進します。
VSCodeを使ったGoogle Apps Script開発の環境構築

## はじめに
この記事では、VSCodeでGoogle Apps Script（以下`GAS`）開発の環境を構築する方法を紹介します。GASを開発するためにはGoogleアカウントが必要になるので、もしお持ちでない方は先に作成してください。また、ローカルからGoogleアカウントにアクセスするために`clasp`というNode.jsパッケージを使うので、Node.jsも必要になります。詳細は以下のドキュメントをご覧ください。

https://developers.google.com/apps-script?hl=ja

https://github.com/google/clasp

<br>

### 最終的なディレクトリ構成
```
myApp/
├── .clasp.json
├── .claspignore
├── appsscript.json
└── main.js
```

<br>

### Google Apps Script APIを有効にする
まずはGAS APIを有効にしましょう。使いたいアカウントにログインした上で設定してください。以下からアクセスできます。

https://script.google.com/home/usersettings

![スクリーンショット 2024-06-07 0.32.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1016415/f94554e9-b602-5572-f50e-0fe62c64a71c.png)

<br>

### プロジェクトディレクトリの作成とパッケージのインストール
```bash
mkdir myApp
cd _$
npm init -y
npm i -g @google/clasp # claspはグローバルにインストールする
```

<br>

### claspでGoogleアカウントにログインする
```bash
clasp login
```
このコマンドを実行するとブラウザでアカウント認証画面が開きます。先程のGAS APIを有効にしたアカウントを選択し、指示に従って進めてください。成功すると以下のようなメッセージが表示されます。以降はclaspコマンドでローカルからGoogleアカウントにアクセスして、GASソースコードのアップロード・ダウンロードなどができるようになります。

![スクリーンショット 2024-06-06 16.53.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1016415/8515a5e3-731c-7f2a-0aaa-be871e06b36a.png)


<br>

### アプリケーションの新規作成と設定
以下のコマンドで新しくアプリケーションを作成します。
```bash
clasp create --type standalone
```

するとプロジェクトルートに以下のファイルが作成されます。

- `.clasp.json` claspの設定ファイル
- `appsscript.json` GASの設定ファイル

またアカウントのGoogle Driveにもアプリケーションが作成されているので確認してみてください。

<br>

`appsscript.json`のtimeZoneを日本に変更します。
```diff_json:appsscript.json
{
+ "timeZone": "Asia/Tokyo",
  "dependencies": {
  },
  "exceptionLogging": "STACKDRIVER",
  "runtimeVersion": "V8"
}
```

<br>

`.claspignore`ファイルを作成します。

後でアプリケーションをGoogleにアップロードする工程があるのですが、これはその時にアップロードしたくないファイルやディレクトリを指定するためのものです。`.gitignore`のようなものですね。

以下は`main.js`と`appsscript.json`以外の全てを無視する設定です。
```
**/**
!main.js
!appsscript.json
```

<br>

main.jsを作成します。今回はログを出力するだけの簡単なコードです。
```js:main.js
const test = () => {
  console.log("Hello GAS!");
}
```

<br>

### Googleにアプリケーションをアップロードする

ではいよいよ、Googleにアプリケーションをアップロードします。
```bash
clasp push
```


成功すると以下のようなメッセージが表示されます。

![スクリーンショット 2024-06-07 13.55.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1016415/2b6b8580-85d5-f394-634f-d4feaf074d5c.png)


<br>

次に以下のコマンドを実行すると、今アップロードしたGASのwebエディターがブラウザで開きます。
```bash
clasp open
```

<br>

この時、`main.js`は`main.gs`へ自動的に変換されています。実行ボタンを押してログが表示されれば成功です🎉 お疲れ様でした！

![スクリーンショット 2024-06-06 17.26.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1016415/f76f4acc-e3b2-d781-0198-58622c0121fe.png)

<br>

## おわりに
ローカルで開発すればエディターによる拡張機能の恩恵も受けられますし、Githubでのコード管理も楽になると思います。ぜひやってみてください。
最後まで読んでいただきありがとうございました!!
フェーズ３まとめ

作品名：読み込みちゃん
IT研修最終発表に向け、私たちは読み込みちゃんというシステムを作成しました。問題として、弊社ではファイルの数が多く、製品の過去データを確認する作業が多く、pdfを開いて確認しなければならないことも多く、確認の効率が悪いということがありました。
![6cdiMixadRhzTUZ1717739186_1717739279.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/881fe246-bdd6-635b-8b6c-4c9b5cc92423.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/9d7e6c24-91b8-e17f-1a99-4dfc654abbf9.png)
これを、一覧で確認できるようにし、pdfを開かなくても自動で情報を取り出せるシステムを作りたいと考えました。
解決策の一つ目として、teamsに製品コードを送ると、その製品に対応する情報を教えてくれ、さらにそのファイルも添付してくれるシステムを作ろうと考えました。
解決策の２つ目として、シェアポイントにpdfのファイル名の情報とpdfの収率をエクセルに出力できるシステムを作ろうと考えました。これにより、pdfを開かなくても情報を取り出すことができると考えました。
実装方法の一つ目として、teamsにコードを送ると、それに対応する製品情報とファイルを送ってくれるフローを作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/ddcdae33-b441-aaf3-72bc-5b291eed6530.png)
![4BVcpYFS7Anqodi1717739528_1717739556.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/8f6bb236-7440-183f-629c-9a44e4d49d3e.png)

teamsで送られてきたファイルをクリックするとファイルを開くことができます。

power automateを使用してShare pointに保存されているPDFのファイル名から情報を抜き出しExcelの表に出力しました。
今回ファイル名は「コード-製造場所-ファイルタイプ-製造タイプ-日付」となっていたので、それぞれ変数で処理しました。
 ![最終制作 (1).PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/8ce8edf5-c080-191c-1d38-927a0ecf2a7c.png)

次にPDFファイルの中に書かれている収率を抜き出しExcelの表に出力します。
PDFファイルから画像認識ができなかったので、一度PDFをJPGに保存しなおす過程を挟みました
 ![最終制作3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/96586a3b-85e6-c36a-9218-7ca7a1adc248.png)

JSON解析を挟み最後に「コード、製造場所、ファイルタイプ、製造タイプ、日付、収率」をExcelに追加しました。
![最終制作2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810310/cd7ea3e3-942c-8789-0de1-aa50148e40e7.png)

苦労した点は、teamsでコードを送ったときに、一緒にファイルも送ってくれるようにした点、PDFの内容から収率を取得してエクセルの表に出力するようにした点、トリガーをshare pointにファイルが作成されたときに変更する点です。この作業はなかなかうまくいかなくて、本当に大変でした。
フィードバックと改善から得られた学び
フィードバックとして、teamsでファイルのリンクも送られてほしいというところと、情報の多くはファイル名から持ってくることができるということをフィードバックとして得られました。このことから、最初に課題を聞く段階と後日にフィードバックをもらう段階で、自分たちが求められているものと想像していたものには違いがあったことを知りました。
最初の段階で相手がどんなものを求めているのかを知ることが必要でした。
今後のデジタル活用への思い
chatGPTにとてもお世話になりました。もはや技術ではなく、どれだけAIを活用することができるのか、どれだけうまく巨人の肩に乗ることができるのかが重要になってくると思いました。つまり、誰でも作ろうと思えば作れるということを伝えたいです。
最初は知らなかったツールばかりで自分に扱えるか不安だったが、とにかく触ってみるを意識していろいろ試してみることで、研修前より知識を蓄えることができました。
今後も、様々なツールにチャレンジして知識を増やしたいと思いました。
Python文法まとめ【list型】

# はじめに
こちらの記事でPythonの型についていくつかご紹介しました。
[四則演算と型](https://qiita.com/mochi_541/items/9d261e2b434795d48471 "Qiita内")
上記は値単体についての型ですが、
この記事では複数の要素を含む型について記述します。

# list型
```Python:
変数 = [] # 空のリスト
```
```Python:
変数 = [n1, n2, n3]
```
の形で、複数の要素を扱うことができます。
`[]` (角括弧/ブラケット)内で`,`で要素を区切ります。

```Python:サンプル
score = [3, 20, 11, 5, 2]
daifuku = ['いちご', '豆', 'クリーム']
print(score)
print(daifuku)
```
```:実行結果
[3, 20, 11, 5, 2]
['いちご', '豆', 'クリーム']
```
```Python:サンプル
title = '三四郎'
age = 23
book = [title, age, '夏目漱石', 1908]
print(book)
```
```:実行結果
['三四郎', 23, '夏目漱石', 1908]
```
整数や変数など、ことなる型を同時に格納できます。

### リスト同士の操作
```Python:サンプル
sat = [1, 8, 15, 22, 29]
sun = [2, 9, 16, 23, 30]
s_s = [sat, sun]
hd = sat + sun
print(s_s)
print(hd)
```
```:実行結果
[[1, 8, 15, 22, 29], [2, 9, 16, 23, 30]]
[1, 8, 15, 22, 29, 2, 9, 16, 23, 30]
```
カンマで区切るとそれぞれのリストを保持したリストを生成します。
足し算の形式で記述すると、それぞれのリストの要素を結合したひとつのリストを生成します。

### インデックス
リストの中に要素がいくつ存在するか調べるには、len()を使います。
```Python:サンプル
ice = [1, 3, 7, 8, 10, 11]
len(ice)
```
```:実行結果
6
```
リストの中から要素をひとつ取り出したい場合、
インデックスを指定します。
先のリストで、3番目の要素はなんでしょうか？
```Python:サンプル
print(f'リストの3番目は{ice[3]}です。')
```
```:実行結果
リストの3番目は8です。
```
リストの要素は、`先頭をゼロ番目`と数えます。
要素の数が6の場合、末尾のインデックスは5です。

### 要素の操作
要素をひとつ増やしたい場合、append()を利用します。
```Python:サンプル
ice = [1, 3, 7, 8, 10, 11]
ice.append(12)
print(ice)
```
```:実行結果
[1, 3, 7, 8, 10, 11, 12]
```
インデックスを指定して増やす場合、insert()を利用します。
```Python:サンプル
ice.insert(2, 5)  # 2番目に5を挿入する
print(ice)
```
```:実行結果
[1, 3, 5, 7, 8, 10, 11, 12]
```
要素を削除したい場合、remove()を利用します。
```Python:サンプル
ice.remove(11)
print(ice)
```
```:実行結果
[1, 3, 5, 7, 8, 10, 12]
```
### forと組み合わせる
リストの要素をひとつずつ順に表示するプログラムです。
```Python:サンプル
for i in ice:
  print(i)
```
```:実行結果
1
3
5
7
8
10
12
```

複数要素を扱う型はこの他に、dict型やtuple型、set型などがあります。
# おわり
お役に立てたら幸いです。
Flutter Android: could not create task ' generatelockfiles' エラーが表示された時。

# エラー内容
VScode＋Flutterで開発をしている時に、
下の画像のようなAndroidのエラーが表示された。
![スクリーンショット 2024-06-07 13.57.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2961391/caea124d-f5bd-2bef-4b15-b5eec221db9a.png)
# 対処方法
下記を参考に解決した。

https://stackoverflow.com/questions/73357365/build-gradle-error-could-not-create-tastk-generatelockfiles-in-flutter-proj

原因はjavaとgradleのバージョン不一致で、Flutterプロジェクトで参照しているgradleを自環境のjava versionに合わせて変更してやる必要がある。

1.コマンドでjavaバージョンの確認する。
ターミナルで実行。
```
javac -version
> javac 19.0.1
```
2.java versionと一致するgradle varsionを確認する。
下記のサイトに対応表が載っています。

https://docs.gradle.org/current/userguide/compatibility.html

3.設定ファイルを書き換える。
"Project root" > android > gradle > gradle-wrapper.properties
上記ファイルの”distributionUrl”を書き換える。
>java -version が 19だった場合：
>distributionUrl=https\://services.gradle.org/distributions/**gradle-7.6-all**.zip
>java -version が 21だった場合：
>distributionUrl=https\://services.gradle.org/distributions/**gradle-8.4-all**.zip

4.新しいgradleをインストールする。
ターミナルで実行。
```
flutter pub get
```

5.プロジェクトを開き直すとエラーが消える。
完了！

## gradle-wrapper.propertiesが見つからない時
ターミナルから ./android/gradlew を実行する
または
"Project root" > androidをAndroidStudioで開く
物理量などを適切な有効数字で誤差とともに表示する

## 解決したい問題
あるデータをガウシアンでフィットした場合など、得られるパラメータの値と誤差の桁はパラメータによって大きく違うことがある。
$$ p_1 \exp \left(- \frac{(x-p_2)^2}{2p_3^2} \right)$$

例えば `scipy.optimizee.leastsq`　で得られた値を
$p_1 = 1000 \pm 20$
$p_2 = 300.3 \pm 0.4$
$p_3 = 5.05 \pm 0.06$
のように表示したくても、パラメータの桁数を指定する方法では
`p1 = 1000.00 +- 20.34`
`p2 = 300.30 +- 0.45`
`p3 = 5.05 +- 0.06`
と不恰好になるし、指数表示でも
`p1 = 1.000+e03 +- 2.034+e01`
などのように不要な桁が現れる。
## お手製の解決法 

```python
def format_with_error(p, dp):
    if dp == 0:
        return f"{p}"
    
    if dp >= 1:
        return f"{p:.0f} ± {dp:.0f}"
    
    dp_str = f"{dp:.10f}"  
    decimal_places = len(dp_str.split('.')[1].rstrip('0'))
    
    return f"{p:.{decimal_places}f} ± {dp:.{decimal_places}f}"
```
## 専用のライブラリ`uncertainties`
```python
from uncertainties import ufloat
v = ufloat(p,dp)
print(f"{v:.1u}")
```
可読性が上がった
MTテンプレート内でダブルクォートを置換したい時

regrex_replaceでダブルクォート（"）をJSON用にエスケープ（¥"）しようとしたら
下記のような記述ではうまくできなかった
```
regex_replace="/¥"/g","¥¥""
```

シングルクォートを使えばいけました
```
regex_replace='/"/g','¥"'
```

参考

https://product.skyarc.co.jp/engineerblog/entry/regex_replace_1.html


ダブルクォートとシングルクォートが混在する場合はこうすればいいらしい

```
<MTSetVarBlock name="regex0">/["']/g</MTSetVarBlock>
<MTSetVarBlock name="regex1">***</MTSetVarBlock>
<MTUnless regex_replace="$regex0","$regex1">"Tom and Jerry"</MTUnless>
→ ***Tom and Jerry***
```

めちゃくちゃ助かる
[備忘録]forとwhileの使い分け(Java)

プログラミングを初めて３日目。
そろそろ処理を繰り返したいぞとなった私は２つの処理を学習しました。

**for**　 と 　**while**
(do～whileはおそらくしばらく登場しないので次の機会に)

いつ、どちらを使えばいいの？？？
ということでまとめてみました。

**・forとは**
```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {

for (初期値; 条件式; 増減式) {
　　繰り返し処理
    }
}
```
for 文は冒頭で初期値、条件式、増減式の3つを設定する。
ここで**繰り返しを何回行うか**について設定するのがよくある方法。

**・whileとは**
```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
while (条件式) {
繰り返し処理
    }    
}
```

while文は冒頭で条件式のみを設定する。
**繰り返したい特定の条件**について設定するのがよくある方法。

**・結局何が違うの？**

まとめると

条件として回数を指定した処理を行いたい場合**for**
条件を満たしている限り処理を繰り返したい場合は**while**

ということになる。

リンゴの数だけ処理をしたいときがfor
whileはそのリンゴのうち、一度に食べられたリンゴの数だけ処理をしたいとき
という解釈で合っているのだろうか。

**繰り返したい基準が数なのか条件なのか**

こんなことまで考えながらコードを書ける、素敵なプログラマになりたい。
【メモ】Labmdaの作成済みレイヤー

https://github.com/keithrozario/Klayers?tab=readme-ov-file

pythonのrequestsライブラリーひとつ、自分のローカル環境でpip install -t . してzipを作って、、ってやるのは大変面倒です。上のgithubでは作成済みのレイヤーが公開されています。その中から選んで、Lambdaのレイヤー設定「ARN を指定」で入力することで、必要なライブラリがセットアップされます。
有名ライブラリしか載っていませんが、かなり重宝します。
Typescriptのオーバーロード関数を理解したい！

## :writing_hand: オーバーロード関数（Function Overloading）

オーバーロード関数とは、同じ名前で引数の型や戻り値の型が異なる複数の関数シグネチャをもつ関数のことです。  
文字だけツラツラと並べられても、何のことやらと頭の上に？を浮かべる人もいると思いますので、さっそく例をお見せしたいと思います。

```ts
// オーバーロード関数
function multipleA(a: number, b: number): number; // 関数シグネチャ1
function multipleA(a: string, b: number): string; // 関数シグネチャ2
function multipleA(a: any, b: any): any {
  if (typeof a === "number" && typeof b === "number") {
    return a * b;
  } else {
    return a.repeat(b);
  }
}

console.log(multipleA(2, 2)); // 出力1：4（number型）
console.log(multipleA("hello", 2)); // 出力2：'hellohello'（string型）

// オーバーロード関数を使用しない場合
function multipleB(a: number | string, b: number): number | string {
  if (typeof a === "number") {
    return a * b;
  } else if (typeof a === "string") {
    return a.repeat(b);
  } else {
    return "";
  }
}

console.log(multipleB(2, 2)); // 出力1：4（numberとstringのユニオン型）
console.log(multipleB("hello", 2)); // 出力2：'hellohello'（numberとstringのユニオン型）
```

例では、オーバーロード関数「multipleA」とそうでない関数「multipleB」を定義しました。

「multipleA」は、以下の２つの関数シグネチャがあります。  
関数シグネチャ 1: 2 つの number 型の引数を受け取り、number 型の値を返す  
関数シグネチャ 2: string 型と number 型の引数を受け取り、string 型の値を返す

一方、「multipleB」は、2 つの引数を受け取りますが、第一引数は number と string のユニオン型、第二引数は number 型となり、number と string のユニオン型の値を返します。

## :v: オーバーロード関数の素晴らしいところ

さて、２つの関数を引き合いに出しましたが、オーバーロード関数の魅力をお伝えしたいと思います。

結論から言うと、オーバーロード関数は、**引数の型に応じて戻り値の型を推論**します。  

どういういことかと言いますと、「multipleA」の出力１、出力２はそれぞれ『string 型』、『number 型』の値を返すようになっています。  
しかし、「multipleB」の出力１、出力２はどちらも『number と string のユニオン型』の値を返すため、戻り値が string 型なのか number 型なのか明示的に決まっているわけではありません。なので、もし、「multipleB」の戻り値を他の処理で使用したいときには、また型ガードをしなければならないケースが生じてきます。

ぜひ、Typescript の公式 [Playground](https://www.typescriptlang.org/play/?#code/PTAEiqGQfhkBYZMW4ZKEmGQRamAdTAUAMwK4DsDGALgJYD2uoAttgDYkAONApgIIAUAhgFyi7aUAjJgCcANKAE8+gkQEop-IcIDcoEKDSB2hkANDIFmGQIMMgY4YAjFjxEyFanWKNWnHgGdCw4rgDm4yb0VynLt3dVdS09IwAmMwIScipaBmZ2blAOXABPLx5UtPkU9NAAb3RQUGJMUDZCNPomUnKOUABeZtAAImklVtAAMm7QKpq6iSaW9t9hVtlC4pLQYSZCbGEKBoAqCWUZgF9QJhpHJmnZuYWllYA6eZqOQjYBWU2SrfRn9HxyR1Jmc5pSdzZrAl7OFxOFZA81GBAF+KgGylYyALH+ACyACH+OiJANHqgEh-t4fL5MH5-AHxWyJNitAAWe1+rVB4OC0Jh4XhAHJKTRfmzfszkc5XB4seh0OooLAEChUIAkhkA-vKACldAOoMgCsGQAiDIAWDUAECpRCyxQEkpgAIQcPhkwlAAB9QLzApkjUpcmiTebLR4jqVypVqrV6iNGm17ZMXSV5otlilQOsBI9QDs9gdXRUBp7Q80fa0ne5-UVjkGzilLkxrrd7pHo-tDpnZtmQ61WsWXoL3rhPt9fv8dXYDSDQGCIepYQiUfbABYMacAdgyAM4ZANMM4EAzwwChtN-Etok2dtkzmkGldumQ0CwpmsqmkdfcoejyczrFAA) で、実際にどうなっているか確認してみてください。
【TryHackMe】Getting Started：Walkthrough

# 概要

TryHackMe「Getting Started」のWalkthroughです。

https://tryhackme.com/r/room/gettingstarted

# Task1

## **Q1**.*What is the name of the hidden admin page?*

**Hint**.*Don't forget to include the "/" character in your answer.*

`nmap`でポートスキャンを実行します。

```
$ nmap -sC -A -T4 -sV 10.10.88.136        
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-06-07 01:50 EDT
Nmap scan report for 10.10.88.136
Host is up (0.24s latency).
Not shown: 996 closed tcp ports (conn-refused)
PORT     STATE    SERVICE        VERSION
22/tcp   open     ssh            OpenSSH 8.2p1 Ubuntu 4ubuntu0.1 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   3072 42:6c:06:53:f1:c0:41:8d:50:81:c5:3b:46:1e:c4:22 (RSA)
|   256 87:0b:64:ae:2c:a8:0f:ae:94:c3:0e:a1:8a:a3:1d:14 (ECDSA)
|_  256 d3:e5:aa:a2:43:90:3d:95:43:24:46:f4:aa:58:33:a1 (ED25519)
80/tcp   open     http           Node.js (Express middleware)
|_http-title: BFFs
3000/tcp open     http           Node.js (Express middleware)
|_http-title: BFFs
3017/tcp filtered event_listener
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 48.44 seconds
```

Webページを開きます。

![web home.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/7ac9c9d9-6875-1610-4ea4-77f210498c2b.png)

開発者ツールでソースコードを見るとコメントアウトでパスを発見しました。

```html
<!--  don't forget to remove admin page on /test-admin -->
```

アクセスするとテスト用の管理者ページが表示されました。

![test admin form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/1ea9c1d3-4369-975d-1807-76203026fdc3.png)

**A**.**/test-admin**

# Task2

## **Q1**.*What is the username and password in the form username:password?*

`Username: admin`,`Password: admin`でログインすることができました。

![admin portal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/b633d48e-855c-0c5a-5dc7-0d93733024c8.png)

**A**.**admin:admin**

## **Q2**.*How many user are signed up to the application?*

ポータル画面の右側にサインアップしているユーザーが表示されています。

![sign up user.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3005822/125dff8c-8960-0bea-1b04-9b479888d9af.png)

**A**.**3**
Makeファイルマジック：コマンドライン辞書を作成しよう

# はじめに
2022年からのWebエンジニアをしているえいちゃもです。
現在は[自社開発企業](https://www.futurewoods.co.jp/)でエンジニアとして勤めています。
今回は業務をしていく上で便利だった`Makeファイル`を紹介しようと思います。
`Makeファイル`は私がはじめてアサインされたプロジェクトで使われているのを見かけ、それをきっかけにどのプロジェクトでも使っています。
この記事を見てまだ使ったことない人は便利なのでぜひ使ってみて欲しいです。また、リポジトリにまだないって人はぜひチームメンバーを巻き込んで提案してみてください。

# Makeファイルとは
`Makeファイル`とは、ビルドプロセスを自動化するための設定ファイルです。
MacやLinuxでは`GNU Make`が標準でインストールされているのですが、Windowsではされていないので、`choco install make`などでインストールすることで使用することができます。
ディレクトリ直下に`Makefile`というファイルを作成することで使用することができます。

# Makefileを使うメリット
いろんなメリットはあると思うのですが、初学者にとってのメリットを紹介します。

### 1. コマンドの簡略化
長くて覚えにくいコマンドって多いですよね。
そんな時に`Makeコマンド`を使ってください。
Makeコマンドを作る際に勉強にもなるので自作することをおすすめします。
私は特にDockerコマンドを簡略化するために使ってます。

例）コンテナ内でのコマンド実行したい時に使うコマンド

通常
```terminal
$ docker compose exec #{container} ${command}
```

Makeコマンドを実行する場合
```terminal
$ make up
```

Makefileでどのように記述するか
```makefile
.PHONY: up
up:
	docker compose --profile all up
```

### 2. 複数のコマンドを同時に実行できる
セットで使うコマンド多くて大変ですよね。
そんな時に`Makeコマンド`を使ってください。
環境構築のドキュメントを作る時やチームメンバーに`このコマンド実行しといてください`など伝える時に便利です。

:::note info
Railsを使っております
:::

例）初回のデータベースを作成、更新などをしたい時に使うコマンド

通常
```terminal
$ docker-compose exec #{container} bin/rails db:create
$ docker-compose exec #{container} bin/rails db：migrate
$ docker-compose exec #{container} bin/rails db:seed
```

Makeコマンドを実行する場合
```terminal
$ make db
```

Makefileでどのように記述するか
```
.PHONY: db
db:
	docker-compose exec web bin/rails db:create
	docker-compose exec web bin/rails ridgepole:apply
	docker-compose exec web bin/rails db:seed
```

### 3. コマンドの辞書として使うことができる
コマンドを忘れた時ってGoogle検索かChatGPTなどに聞かないといけなくてめんどくさいですよね。
そんな時に`Makeコマンド`を使ってください。
実際に私が業務で使用している`Makefile`を載せておきます。(Rails)

```
.PHONY: up ps app migrate seed console routes rubocop rspec db sql redis remove-all-containers
install:
	docker network create fs-network
	docker compose run --rm frontend yarn
	docker compose --profile all up -d
	docker-compose exec web bin/rails db:create
	docker-compose exec web bin/rails ridgepole:apply
	docker-compose exec web bin/rails db:seed
	docker-compose exec web bin/rails ridgepole:apply RAILS_ENV=test
	docker-compose exec web bin/rails db:seed RAILS_ENV=test
up:
	docker compose --profile all up
ps:
	docker compose ps
app:
	docker compose exec web /bin/sh
ridgepole:
	docker compose exec web bin/rails db:ridgepole
seed:
	docker compose exec web bin/rails db:seed
console:
	docker compose exec web bin/rails console
routes:
	docker compose exec web bin/rails routes
rubocop:
	docker compose exec web rubocop
rspec:
	docker compose exec web bin/rspec
db:
	docker compose exec mysql /bin/sh
sql:
	docker compose exec mysql /bin/sh -c 'mysql -u $$MYSQL_USER -p$$MYSQL_ROOT_PASSWORD $$MYSQL_DATABASE'
create-dump-%:
	# ex: make create-dump-20201231
	docker compose exec mysql bash -c 'mysqldump -u $$MYSQL_USER -p$$MYSQL_ROOT_PASSWORD $$MYSQL_DATABASE' > "${@:create-dump-%=%}_dump.sql"
redis:
	docker compose exec redis redis-cli
remove-all-containers:
	docker rm $$(docker ps -aq)
task-%:
	docker compose exec web bin/rails ${@:task-%=%}
```

# おわりに
`Makeファイル`を一通り説明したのですが、いかがだったでしょうか？
使ってみると恩恵がわかるので、まずは触ってみて使用感を確かめてみてください。
LaTeXで参考文献の表示をbstファイルを使って変える方法

~~タイトル通りです。~~ タイトル変えました。

個人的な備忘録として、bstファイルを弄って参考文献の表示方法を変えるTipsを書き残しておきます。

# 問題1：タイトル大文字小文字 編
某学会が公式で出しているLaTeXソースファイルに含まれる.bstファイルを使うと、**タイトルが先頭文字以外全て小文字になる**。
- もちろん、文献情報を記載した場所（自分の場合は.bibファイルですが）では、適切に大文字が指定されています

## 問題の発現例
本当はこうなってほしい：
`Hoge, F. (2024). The Impact of Hogehoge: Who Am I?. Journal of Internet Rojinkai, 1(1), 1-99.`

でもなぜかこうなる：
`Hoge, F. (2024). The impact of hogehoge: who am i?. Journal of Internet Rojinkai, 1(1), 1-99.`

## 対策

自分が使用している.bstファイルには、次のような関数が設定されていました。
```
FUNCTION {format.title}
{ title
  duplicate$ empty$ 'skip$
    { "t" change.case$ }
  if$
  "title" bibinfo.check
}
```

あまり.bstファイルの書き方には詳しくないのですが、ちょうど中段の
```
    { "t" change.case$ }
```
で、`change.case$` という関数（？）が、"t"という引数を取っています（引数が前に来るとか初めての感覚……）。
これが「先頭文字と、bibtex等で文字が{}で囲われていない文字以外全てを小文字にする」という処理なのだそう。

（↓参考にしました）

https://tex.stackexchange.com/questions/76408/transforming-the-bst-file-to-get-lower-cases

なので、上のコードを次のように修正しました：

```
FUNCTION {format.title}
{ title
  duplicate$ empty$ 'skip$
    { }    % 中身を消す
  if$
  "title" bibinfo.check
}
```

対症療法ですが、これで何とかなりました。


# 問題2：著者名とハイフン 編
著者名にハイフンが含まれているのに、**ハイフンが表示されない**（APA準拠だとハイフンが必要）。

## 問題の発現例
著者名が`Hoge-Fuga P Hogera`の場合……

本当はこうなってほしい：`Hogera, H.-F. P.`
でもなぜかこうなる：`Hogera, H.F.P.`


## 対策
`FUNCTION {format.names}`を変更します。

```元ファイル.bst
{ s nameptr                     % nameptr はイテレータ
   "{vv~}{ll}{, jj}{, f{.}.}"   % フォーマット
   format.name$
   bibinfo bibinfo.check
   't :=                        % 名前をtに保存

（以下略）
```

~~マジで意味分からん関数してるﾀｽｹﾃ~~


2行目のフォーマットが次のような意味を持っているのだそう。
- `{vv~}`：名前の接頭辞（例： "van", "de" など）
- `{ll}`：フルファミリーネーム（姓）
- `{, jj}`：接尾辞（例： "Jr.", "III" など）
- `{, f{.}.}`：ファーストネーム（名）／ミドルネームのイニシャル

（perplexityに聞きました。[日本では「パープレ」という略称で広めたいらしい](https://www.itmedia.co.jp/mobile/articles/2406/17/news125.html)）

で、最後の`{, f{.}.}`を`{, f.}`に変えるとうまくいきました。~~なんで？？？？？？~~

つまり、こう変える↓
```変更後ファイル.bst
{ s nameptr                     % nameptr はイテレータ
   "{vv~}{ll}{, jj}{, f.}"   % フォーマット
   format.name$
   bibinfo bibinfo.check
   't :=                        % 名前をtに保存

（以下略）
```

参考にしました↓

https://www.ctan.org/pkg/apabst



# 雑記
あー、.clsファイルとか.bstファイルとかちゃんと書き方覚えたいなー（10年前からずっと言ってる）。
誰かいい感じの教本とかWebサイトとか教えてくれないかなー（他力本願寺）
javascript new Date('2000-05-25')は日本時間の朝9時

# 1. はじめに 
知っておかないと怖いなぁと思ったことを記事にしました。

# 2. Javascript の new Date()
テーブルやローカルストレージに日付のデータを格納するとき、文字列で`2000/05/25`や`2000-05-25`で格納したりするときがありますよね。

このデータをDate型で扱いたいとき
 ```javascript
 dateString = db.getDate();
 date = new Date(dataString);
```
ってしてませんか？コレ実は怖いんです。

# 3. 実行結果
まずは`2000/05/25`を確認しましょう。
 ```javascript
 date = new Date(`2000/05/25`);
 console.log('date=' + date.toLocalString());
```
きっと
 ```
 date=2000/5/25 0:00:00
```
と出力されるでしょう。想定どおりですよね？

次に、`2000-05-25`を確認しましょう。
 ```javascript
 date = new Date(`2000-05-25`);
 console.log('date=' + date.toLocalString());
```
以下のように出力されます。
 ```
 date=2000/5/25 9:00:00
```
朝9時です。想定どおりでしょうか？

# 4. こんなバグに
`2000-05-25`の表示形式の文字列をnew Date()で変換した場合、朝9時になるって知っていました？

知っておかないと
 - カレンダーに朝9時の日付をセットしてしまう
 - 現在日時と朝9時の日時を比較してしまう

など、バグを埋め込んでしまいますよ。
怖いと思った方は気をつけましょう。
解決「vue3+Firestore　Web画面初期表示で接続エラー」

# 1.はじめに

Vue3でWeb画面を作成しFirestoreに接続したとき原因不明のエラーで困ったことと、そのときの対処方法を紹介します。

# 2.準備は万端

Vue3でFirestoreに接続したいとき、ネットで検索し

1. プロジェクトを作成
  
2. FirebaseSDKをインストール
  
3. Firebase接続設定情報を登録
  
4. Firebase接続処理の実装
  
5. VueコンポーネントからFirestoreに接続し、データを取得する処理を実装
  
6. UIの実装
  
7. 最後に実行
  

と、していきますよね。

# 3.エラー発生

実行時にエラーが発生した場合、どこが間違えているか確認しつつ、エラーを取り除いていきます。が、以下のエラーが発生し、原因不明で解決できませんでした。

`500 Firebase: No Firebase App '[DEFAULT]' has been created - call initializeApp() first (app/no-app).`

「initializeAppを最初に呼びなさい」と怒られているようです。

エラー内容からいろいろ調べてみたのですが、インストールも万全、接続設定もあっている、実装も問題なさそう、そもそもinitializeAppを最初に呼び出しているはず、なのにエラーが消えないという状況に陥りました。

# 4.対処方法

結論からいうと、画面初期表示時に、以下の実装をしていたのが問題だったのです。

```javascript
await useFirestore().getUsers()
```


これを

```javascript
onMounted(async () => {
 await useFirestore().getUsers()
})
```

とすると解決しました。

そう、画面初期表示時は`onMounted`の中で呼び出さないとエラーになるのです。

ネットで検索しても見つけられなかった対処法なので記事にしました。

同じ問題で困ったいる方への参考になれば幸いです。
gitでブランチ分岐をグラフ表示の履歴に残す方法

# gitでブランチ分岐をグラフ表示の履歴に残す方法

## やりたいこと

- 以下のような感じで分岐してマージしたという履歴を残したい

```sh
$ git log --graph
*   commit 7ca02b4e006886117d6a509f371f670729bd2515
|\  Merge: 798df58 181e05e
| | Author: You <you@example.com>
| | Date:   Fri Jun 7 12:11:31 2024 +0900
| | 
| |     Merge branch 'example-branch'
| | 
| * commit 181e05e9a31667c0dcf0093b2aa10accc8fe1853
| | Author: You <you@example.com>
| | Date:   Fri Jun 7 12:06:18 2024 +0900
| | 
| |     commit message 2
| | 
| * commit e3a4d6eb74229b6ab06da4a3d083e173f4a1091c
| | Author: You <you@example.com>
| | Date:   Fri Jun 7 12:05:50 2024 +0900
| | 
| |     commit message 1
| | 
```

## 結論

- `git merge --no-ff [branch]`
- `git branch -d [branch]`

```sh
git switch -c [マージ元ブランチ]
echo "hello world" > hello.txt
git add hello.txt
git commit -m "add hello"
git switch [マージ先ブランチ]
git merge --no-ff --no-edit [マージ元ブランチ]
git branch -d [マージ元ブランチ]
```

## 補足

- `git config --global --add merge.ff false` でデフォルト設定を `--no-ff` にしておくと便利
  - ただし `--global` は任意
- `git merge --no-ff` を実行するとマージメッセージをeditorで設定することができる
  - `--no-edit` にすると、editorが開かずにデフォルトのマージメッセージが設定される
- `git branch -d [branch]` はブランチを削除するコマンド
  - `-D` オプションだと、履歴ごと消える
    - reflogにも残らないから消えてしまう
Azure DevOpsでチェックイン時に TF10169エラー

Azure DevOpsを使用してソース管理を行っています。
VisualStudio2022環境でソースをチェックインすると下記のエラーが表示されます。

TF10169: サポートされていない保留中の変更が、チーム プロジェクト フォルダー $/Test で試行されました。チーム エクスプローラーのプロジェクト作成ウィザードを使用してプロジェクトを作成するか、またはチーム プロジェクト削除ツールを使用してプロジェクトを削除してください。

実施した作業は以下になります。

①既存のチームコレクションのSystem1のソースをコピーして、VisualStudio2022でTestというプロジェクトを作成しました。
※以前のソース管理情報はソースから削除。

②Azure DevOpsサーバー管理コンソールでSystem2というコレクションを作成し、Testというプロジェクトを追加しました。

③Azure DevOpsのSystem2コレクションにアクセス権限を付与しました。

④VisualStudio2022環境の「接続の管理」から作成したサーバー上のコレクションのSystem2\TESTを選択し接続。

⑤①で作成したソースが「保留中の変更」の「含まれる変更」に入っていることを確認し、「チェックイン」ボタンをクリック。
この段階でエラーが出ます。

こちらの情報を参考にしました。
https://devblogs.microsoft.com/devops/how-to-recreate-the-tfvc-team-project-folder/

コレクションを一度削除して別の名前で再作成等ためしましたが、解決策が見つかっていません。ご教授お願い致します。
掛け持ちオタクが作る予定自動登録アプリ

　私は掛け持ちオタクの会社員です:heartbeat:
 
　私の最近の悩みは **推しのスケジュール(テレビ出演、雑誌、ライブなど)を調べて自分のスケジュール帳に入力するのが面倒** :tired_face:で、これをなんとかしたい！という思いからこのアプリを作りました。

 今回使ったのは、chat GPT-4oとPower Automate、power Apps、excelです。

# 手順
 
 1. 推しの予定をまとめているサイトを検索する。
 
 2. chat GPT-4oにサイトの情報をコピーしてexcel形式にできるような表を
 作ってもらうように( **見出しを日付、タイトルにして** などと送るとよい！)チャットに送る。
 
 3. 2.でとってきたデータをexcelの表にして、Share Pointに保存する(見出しは日付、タイトル)。
 
 4. Power Automateで自動化したフローを作成をクリック、トリガーとアクションを以下のように設定します。
 ![スクリーンショット 2024-05-31 162922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810392/404f7d0d-db46-a4f8-0de6-ca4d19c2ff2a.png)

 5. Power Apps(デザインなどはお好みでカスタマイズok)でShare Pointのexcelデータと連携する。

 ここまでで自分のスケジュールをPower Appsで入力したら、excelに反映されるようになります:open_hands:

実際に動かしたときの画面↓
日程を入力すると....
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810392/fc8b48f2-85a1-a533-39a7-a55cc0351cd9.png)

Excelの表に反映されました(なぜか日程がずれてしまいますが...)↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3810392/f9c7df12-86c0-630f-43d8-ffa86755949b.png)

ここからメールのスケジュールに連携するところまで行きたいのですが、、、鋭意制作中ということで
今回はここまでとさせていただきます。次回またお会いしましょう:raised_hand:
【初心者備忘録】Gitのcommit履歴を1つにまとめる方法

# Gitで直近の複数のコミットを1つにまとめる方法

Gitで作業していると、直近のコミットを1つにまとめたいことがあります。この記事では、直近の2つのコミットを1つにまとめる方法を解説します。

## 手順

### 1. インタラクティブなリベースを開始する

まず、ターミナルで以下のコマンドを実行して、インタラクティブなリベースを開始します。

```bash
git rebase -i HEAD~2
```
このコマンドは、直近の2つのコミットに対してインタラクティブなリベースを開始します。
### コミットをスクワッシュする
先ほどのgit rebaseコマンドを実行すると、デフォルトのエディタが開かれます。ここで、コミットを1つにまとめる（スクワッシュする）ための編集を行います。
```bash
pick <commit-hash> First commit message
pick <commit-hash> Second commit message
```
コミットメッセージを残したいものだけ、<code>pick</code>にして残りは<code>squash</code>に変更しましょう。

＜変更例（最初にコミットしたメッセージを利用したい場合）＞
```bash
pick <commit-hash> First commit message
squash <commit-hash> Second commit message
```
保存ができたら最後のステップです。

### リモートリポジトリに強制プッシュする
```bash
git push --force
```
`--force` オプションを使用すると、リモートリポジトリの履歴が上書きされます。他の人と作業している場合は、慎重に行ってください。
## まとめ
これで、直近の2つのコミットを1つにまとめることができました。インタラクティブなリベースは、コミット履歴を整理するのに非常に便利な機能です。ぜひ活用してみてください。

以上、Gitで直近の2つのコミットを1つにまとめる方法でした。質問やフィードバックがあればコメントしてください。
MrtgログでGnuplotグラフを作る（Linux）

## Linux シェルスクリプト編

### はじめに
サーバ－監視ツールの中で監視対象ホストのCPU、Memory、Diskを統合したGnuplotグラフを作る際、すでに作成しているMrtgグラフのログを使うことにしたので考え方を書き置きます。

#### 作成手順

1. Mrtgで作成されたCPU、Memory、Diskのログを用意します
1. 各ログを上から任意の行数(注1)を読み、unixtimeを時間に変更した統合ログを時間に変換し古い順（正順）に最適行(注2)作成します  
1. グラフ作成テンプレートへ渡す変数を組み込んだhost.exeファイルを作成します
1. host.exeファイルを実行し、svgイメージファイルを作成します

   (注1)gnuplotグラフのX軸を24時間とした場合の経験値は400行、(注2)は28行ですが、適宜調整します

#### Mrtgログと統合ログ
　   <a href="http://www.mrtg.jp/doc/logfile.html">mrtgログドキュメント</a>
```DOC

* Mrtgログフォーマット　
host.cpu.log                host.ram.log                 host.disk.log
1716375662 6 100            1716375662 31 100            1716375662 47 100
1716375662 6 100 6 100      1716375662 31 100 31 100     1716375662 47 100 47 100
1716375062 2 100 2 100      1716375062 26 100 26 100     1716375662 47 100 47 100
1716375000 2 100 2 100      1716375000 26 100 26 100     1716375000 47 100 47 100
1716374700 4 100 14 100     1716374700 30 100 42 100     1716374700 47 100 47 100 
各ログの1列目:unixtime, 2列目:CPU使用率、Memory使用率、Disk使用率

* 統合ログフォーマット（1列目時間の正順）
1列目:時間、2列目:CPU、3列目:Memory、4列目:Disk
host.log
18 4 31 47
19 2 26 47
20 6 30 47
```

#### グラフテンプレートとexeファイル

```DOC
* サンプル画像用テンプレート　mkplot.plt
 set title ghost." Load Average"
 set xlabel "Time Hour"
 set ylabel "Load %"
 set yrange [0:100]
 set size 1 , 0.9
 set terminal svg
 set output path."/".ghost.".svg"
 plot path."/".ghost.".ok" using 2:xticlabels(1) with lines title "CPU", path."/".ghost.".ok" using 3 with lines title "Memory", path."/".ghost.".ok" using 4 with lines title "Disk"
 unset output
 quit
```
```DOC
* 実行ファイル　host.exe
/usr/bin/gnuplot -e 'path="plot"; ghost="host"' bin/mkplot.plt

変数pathはCPU,Memory,Diskの統合ログのパス、変数ghostはグラフを描くホスト名
```
```Bash
* 実行
$ host.exe

```
* サンプル画像
![gnuplotsample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714448/8af3bf0e-0e52-abe4-6952-0a6bb6c6e0cf.png)

#### ソースとサンプルデータ

<a href="https://github.com/ossiansunny/visualmonitor">ここの</a>graphsample/linuxにあります。ソースはシェルスクリプトで書いており、mrtgログが複数のホストにより任意の間隔で採られることから、これに合わせたタイミングでグラフを作成するようcrontab等で自動作成することが出来ます。

### おわりに
mrtgグラフを作成していたので利用することにしました。このグラフはサーバ監視システムの機能の一部として動作させています。興味ある方は<a href="https://github.com/ossiansunny/visualmonitor">ここから</a>どうぞ。
MrtgログでGnuplotグラフを作る（Windows）

## Windows VBスクリプト編

### はじめに
サーバ－監視ツールの中で監視対象ホストのCPU、Memory、Diskを統合したGnuplotグラフを作る際、すでに作成しているMrtgグラフのログを使うことにしたので考え方を書き置きます。

#### 作成手順

1. Mrtgで作成されたCPU、Memory、Diskのログを用意します
1. 各ログを上から任意の行数(注1)を読み、unixtimeを時間に変更した統合ログを時間に変換し古い順（正順）に最適行(注2)作成します  
1. グラフ作成テンプレートへ渡す変数を組み込んだhost.exeファイルを作成します
1. host.exeファイルを実行し、svgイメージファイルを作成します

   (注1)gnuplotグラフのX軸を24時間とした場合の経験値はは400行、(注2)は28行ですが、適宜調整して下さい

#### Mrtgログと統合ログ
　   <a href="http://www.mrtg.jp/doc/logfile.html">mrtgログドキュメント</a>
```DOC

* Mrtgログフォーマット　
host.cpu.log                host.ram.log                 host.disk.log
1716375662 6 100            1716375662 31 100            1716375662 47 100
1716375662 6 100 6 100      1716375662 31 100 31 100     1716375662 47 100 47 100
1716375062 2 100 2 100      1716375062 26 100 26 100     1716375662 47 100 47 100
1716375000 2 100 2 100      1716375000 26 100 26 100     1716375000 47 100 47 100
1716374700 4 100 14 100     1716374700 30 100 42 100     1716374700 47 100 47 100 
各ログの1列目:unixtime, 2列目:CPU使用率、Memory使用率、Disk使用率

* 統合ログフォーマット（1列目時間の正順）

host.log
18 4 31 47
19 2 26 47
20 6 30 47
1列目:時間、2列目:CPU、3列目:Memory、4列目:Disk
```

#### グラフテンプレートとexeファイル

```DOC
* 画像用テンプレート　mkplot.plt
 set title ghost." Load Average"
 set xlabel "Time Hour"
 set ylabel "Load %"
 set yrange [0:100]
 set size 1 , 0.9
 set terminal svg
 set output path."/".ghost.".svg"
 plot path."/".ghost.".ok" using 2:xticlabels(1) with lines title "CPU", path."/".ghost.".ok" using 3 with lines title "Memory", path."/".ghost.".ok" using 4 with lines title "Disk"
 unset output
 quit
```
```DOC
* 実行ファイル　host.exe
 path="c:\\mypath\\plot\\"
 ghost="host"
 set title ghost." Load Average"
 set xlabel "Time Hour"
 set ylabel "Load %"
 set yrange [0:100]
 set size 1 , 0.9
 set terminal svg
 set output path."/".ghost.".svg"
 plot path."/".ghost.".ok" using 2:xticlabels(1) with lines title "CPU", path."/".ghost.".ok" using 3 with lines title "Memory", path."/".ghost.".ok" using 4 with lines title "Disk"
 unset output
 quit
変数pathはCPU,Memory,Diskの統合ログのパス、変数ghostはグラフを描くホスト名
```

```Bash
* 実行
> gnuplot c:\mypath\plot\host.exe
```

* サンプル画像
![gnuplotsample.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3714448/8af3bf0e-0e52-abe4-6952-0a6bb6c6e0cf.png)

#### ソースとサンプルデータ


<a href="https://github.com/ossiansunny/visualmonitor">ここの</a>graphsample/windowsにあります。
ソースはvbsスクリプトで書いており、mrtgログが複数のホストにより任意の間隔で採られることから、これに合わせたタイミングでグラフを作成するようタスクスケジューラ等で自動作成することが出来ます。

### おわりに
mrtgグラフを作成していたので利用することにしました。このグラフはサーバ監視システムの機能の一部として動作させています。興味ある方は<a href="https://github.com/ossiansunny/visualmonitor">ここから</a>どうぞ。