OmniAICreator/Qiita-1.07M huggingface dataset:
お手持ちのMacのあまねくbomなしUTF-8 CSVを撲滅し、"bomあり"に生まれ変わらせるクイックアクションの作り方

ほぼ参考文献を組み合わせただけなので新規性はあまりないです。

# 完成品

こういうクイックアクションを作り、テキストファイルやCSVファイルのエンコードをbomつきUTF-8に置き換える。

![スクリーンショット 2023-12-28 20.21.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/614520/03d6bfd9-8cc4-6f51-fd12-7efc9814791f.png)

# 手順

## 1. Homebrewのインストール

https://brew.sh/ja/

いつもの。最近はコマンドラインからのインストールだけでなく、pkgファイルでのインストール（一般的なmacOSアプリのインストール方法の1つ）ができるようになっている。

<details><summary>テックな事柄に明るくない人向けに手順をざっくり</summary>

1. 上記のサイトにアクセスする
1. ページの「macOSをお使いの場合は新しい.pkgインストーラーをお試し下さい。」の右側にあるGitHubへのリンクを押す
1. ページ最下部の「Homebrew-4.2.1.pkg」みたいなpkgファイルをクリックしダウンロード
1. ダウンロードが終わったらダブルクリックで実行し、指示にしたがってインストールを完了させる

※筆者はコマンドラインでインストールしたので細部が違ったらすみません。
</details>

インストールには30〜60分ほどかかることが多いです。コーヒーでも淹れてのんびり待ちましょう。

## 2. nkfコマンドのインストール

```shell
brew install nkf
```

## 3. Automatorでクイックアクションを作成

macOSにはじめからインストールされている Automator.app を開き、「新規書類」→「クイックアクション」を選択。

### ワークフローの設定

| 設定項目 | 設定値 |
| :-- | :-- |
| 受け取る項目 | ファイルとフォルダ |
| 検索対象 | Finder.app |
| 画像 | お好み |

### ワークフローの中身

左側のサイドメニューから「シェルスクリプトを実行」をドラッグ＆ドロップします。

| 設定項目 | 設定値 |
| :-- | :-- |
| シェル | /bin/bash |
| 入力の引き渡し方法 | 引数として |

```bash:このコードをコピペする
for f in "$@"
do
  if [ ${f##*.} = "csv" -o ${f##*.} = "txt" ]; then
  	/opt/homebrew/bin/nkf --oc=UTF-8-BOM --overwrite "$f"
  fi
done
```

保存時にアクション名の指定を求められるので、お好みで設定して保存してください。

## 4. 右クリックメニューに出てくるように設定（出てこない場合）

1. 記事の最初の画像で開いているメニューにある「カスタマイズ」を選択するか、システム設定を開いて「セキュリティとプライバシー>機能拡張>Finder」と選択する
1. 作成したワークフローにチェックを入れる

※作成したワークフローが表示されない場合、正しい場所に保存できていない可能性があります。 `~/Library/Services` にワークフローが保存されているかどうかを確認し、ない場合は気合いでワークフローのありかを探し出してこのフォルダに格納してください。

# 雑感

バイト先で使うシステムがUnicodeに対応しているのは嬉しいのですが、エクスポートするCSVがどれもこれもbomなしなので、Excelで開くとすぐに文字化けしてしまいます。自分だけなら適当なビューワを入れるだけですが、そのファイルを他の人に丸ごと転送するシチュエーションも多いので、できれば相手の環境でスムーズに中身を確認できる状態にしたいという気持ちで作成しました。

# 参考文献

https://freeelover.com/2023/04/mac/automator/1296/

Shift JISに変換するバージョン。ただ、Unicode系はShift JISに変換できない文字がときどき含まれるので、あまりやりたくなかった。

https://qiita.com/lilpacy/items/977410fc2317446ee455

nkfコマンドみりしらだったので調べた。

https://qiita.com/mriho/items/b30b3a33e8d2e25e94a8

bashは基本文法も怪しいので調べた。
高速・柔軟・型安全！Astro＋TailwindCSS＋TypeScriptの実践事例✨

## 🌟 **概要**
Astro、TailwindCSS、TypeScriptなどの最新Webテクノロジーを活用し、高速かつSEOに優れたモダンなウェブサイトを構築しました。これらの技術を組み合わせることで、パフォーマンス、メンテナンス性、そしてユーザー体験の向上を目指しています。

🔗 **プロジェクト名：** プロドウガ公式サイト  
🌐 **ウェブサイト：** [https://prodouga.com/]

---

## 🛠️ **使用技術**
- **Astro**: 静的サイトジェネレーター（最新バージョン1.33.0）で、高速なページロードとSEO最適化を実現。
- **TailwindCSS**: CSSフレームワーク（v4.0）で、効率的かつ柔軟なデザイン構築が可能。
- **TypeScript**: 型安全性を確保し、開発効率とコード品質を向上。

---

## 🎯 **制作意図**
1. 🌱 **最新技術の習得**: AstroやTailwindCSS v4.0などの新しいツールを実際に使用し、実践的なスキルを磨く。
2. ⚡ **高速でSEOに優れたサイト構築**: 静的レンダリングと最適化されたCSSで、検索エンジンとユーザー双方にアピール。
3. 🔧 **メンテナンス性の向上**: モジュール化された構造とDockerによる環境管理で、長期的な運用を見据えた設計。

---

## ✨ **こだわりポイント**
### 1️⃣ **Astro + TailwindCSS + TypeScript の組み合わせ**
- Astroは静的サイト生成に特化しており、ReactやVueなど複数のフレームワークと統合可能。
- TailwindCSS v4.0では「CSS-first」設定が導入され、デザイントークンやカスタムユーティリティが直接CSS内で管理可能に。
- TypeScriptは型推論やジェネリクスを活用し、大規模プロジェクトでも堅牢性を確保。

### 2️⃣ **プロジェクト構造の分割と整理**
以下のようにディレクトリ構造を整理し、可読性と拡張性を重視しました：
```bash
.
├── src/
│   ├── pages/       # ページコンポーネント
│   ├── layouts/     # レイアウトテンプレート
│   ├── styles/      # TailwindCSS設定
│   ├── lib/         # ヘルパー関数
│   └── types/       # 型定義ファイル
├── public/           # 公開用静的ファイル
├── astro.config.mjs  # Astro設定ファイル
└── tailwind.config.js # TailwindCSS設定ファイル
```

### 3️⃣ **Dockerによる開発環境構築**
Dockerを使用して開発環境を統一。以下のコマンドで簡単にセットアップ可能です：
```bash
docker build -t prodouga-site .
docker run -p 3000:3000 prodouga-site
```

---

## 🌐 **技術アップデート（2025年版）**
### 🚀 **Astro 1.33.0 の新機能**
- **パフォーマンス最適化**: 最新ランタイム（v12.6.0）によりビルド速度が向上。
- **SEO強化**: 自動生成されるXMLサイトマップやメタタグ管理機能が追加。

### 🎨 **TailwindCSS v4.0 の進化**
- **ネイティブCSS対応**: `@theme`ルールによるデザイントークン管理。
- **コンテナクエリ対応**: レスポンシブデザインがさらに柔軟に。
- **パフォーマンス向上**: フルビルドが5倍高速化、インクリメンタルビルドは100倍高速化。

### 🛡️ **TypeScript の普及**
- 2025年現在、90%以上のフロントエンド開発者がTypeScriptを採用。
- 型安全性とスケーラビリティにより、大規模プロジェクトでの採用が増加中。

---

## 💡 **まとめ**
このプロジェクトでは、以下の成果を達成しました：
1. Astroによる静的レンダリングで高速かつSEO最適化されたウェブサイトを実現。
2. TailwindCSS v4.0の新機能を活用し、効率的かつ柔軟なデザイン設計。
3. TypeScriptによる型安全性確保でバグ削減＆開発効率向上。

これらの経験を通じて、モダンなWeb技術の可能性を最大限に引き出す方法を学びました。今後もこれらのスキルを活用し、新しいプロジェクトに挑戦していきます！ 😊
【Angular】Firebase にデプロイする時にバジェットの上限に引っかかってエラーになった話

## 概要
Angular で初期設定のまま作業してるとよく発生するエラーについての原因と対処法の備忘録

### 前提

- バージョン
  - Angular 17

## 事象
`ng deploy`, `firebase deploy` などのデプロイ時や、 `ng build` などのビルド時に以下の様な **「exceeded maximum budget」** エラーが発生する（css ファイル起因の例）。

```bash
# ワーニング系
▲ [WARNING] src/**/**.component.css exceeded maximum budget. Budget 2.00 kB was not met by 14.62 kB with a total of 16.62 kB.
```
または
```bash
#エラー系
✘ [ERROR] src/**/**.component.css exceeded maximum budget. Budget 4.00 kB was not met by 12.62 kB with a total of 16.62 kB.
```

## 原因
この **「exceeded maximum budget」** 系のエラーは、バジェットの制限をしている設定に抵触したためです。

デフォルトでは `angular.json` ファイルに、本番用（Production モード）のビルドのバジェット制限が以下のように設定されています。
```json-doc:angular.json
"configurations": {
  "production": {
    "budgets": [
      {
        "type": "initial",
        "maximumWarning": "500kb",
        "maximumError": "1mb"
      },
      {
        "type": "anyComponentStyle",
        "maximumWarning": "2kb",  // ここで Warning に引っかかる
        "maximumError": "4kb"     // ここで Error になる
      }
    ],

    :
},
```

## 対処法
設定ファイルのバジェット設定の **「maximumWarning」「maximumError」** の値を大きくすればエラーは解消します。

今回は、ビルド時に「4 kB」であるべきサイズが「16.62 kB」になっていたので、以下の様に修正してみます。

```diff_json:angular.json
    "budgets": [
      {
        "type": "initial",
        "maximumWarning": "500kb",
        "maximumError": "1mb"
      },
      {
        "type": "anyComponentStyle",
+       "maximumWarning": "18kb",
+       "maximumError": "20kb" 
      }
    ],
},
```

すると、無事にビルドが通りました。

```bash
> ng build

Prerendered 14 static routes.


Initial Chunk Files   | Names         |  Raw Size | Estimated Transfer Size
main-PN7ZVHDG.js      | main          | 351.26 kB |                77.84 kB
polyfills-LZBJRJJE.js | polyfills     |  32.69 kB |                10.59 kB
styles-7H3E6A7Z.css   | styles        |  15.51 kB |                 3.40 kB

                      | Initial Total | 399.47 kB |                91.83 kB

# ビルド成功
Application bundle generation complete. [7.083 seconds]
```
この後、無事にデプロイも成功しました✨

ただ、パフォーマンスやサーバのコストに影響するため、できるだけこのサイズは大きくしない方が良いので、安易に大きくしすぎないようにソースコードやロジック・仕様を改善できないかも、後で検討してみましょう。
構造体のサイズを動的に変更したい

# やりたいこと
構造体に長さが不定の文字列を入れたい

# 案その1

構造体の中にポインタを入れておいて文字列の先頭ポインタを格納する。

### メリット
- 構造体の配列を作ることができる(管理しやすい)
- 複数の可変長配列を管理できる


### デメリット
- 場合によっては構造体の本体をmalloc()、文字列のメモリをmalloc()と二度手間が発生する

```C
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct {
    char* p_next;
    //ほかにもなんかいろいろデータが入ってる
    char* str;
}mozi;


int main(void) {
    //構造体を宣言
    mozi mozi1;
    char str[] = "文字列";//格納したい文字列(固定長じゃねえかってツッコミは無しで)

        //可変長文字列の長さ
        int str_size = strlen(str) + 1;

    //文字列のメモリを確保
    mozi1.str = (char*)malloc(str_size);
    if (!mozi1.str) {
        exit(1);
    }

    strcpy(mozi1.str, str);

    printf("%s\n", mozi.str);

    free(mozi1.str);
}
```

# 案その2(非推奨)

構造体のサイズを直接変える。

### 仕組み

構造体の一番後ろの要素に配列を入れることを考える。
構造体で宣言した配列の長さ以上の配列をそのまま入れると当然メモリ破壊を引きおこす。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944355/fe2345db-4b42-55dc-087f-2a2bcfa9d65a.png)



**じゃあ予め溢れる前提でメモリを確保すれば…？**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2944355/7e64fc9d-0475-f80b-a376-c007404e3f02.png)

問題ありませんね。
**可変長にしたい要素をいちばん後ろに置くのがミソ。**
構造体の要素は宣言したときの順にメモリに配置されるので、いちばん後ろの要素を可変長にしておけば構造体の他の要素を上書きする心配もありません。

### メリット
- 場合によってはmalloc()を一回で済ませることができる

### デメリット
- 可変長にできるのは1要素のみ
- 変なバグを作りこみそう(主観)
- 言語仕様的にはよろしくないっぽい

```C
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct {
    char* p_next;
    //ほかにもなんかいろいろデータが入ってる
    char str;
}mozi;


int main(void) {

    char str[] = "文字列";//格納したい文字列(固定長じゃねえかってツッコミは無しで)

    mozi * p_mozi = malloc(sizeof(mozi) + strlen(str));//構造体の分と、文字列が構造体から溢れる分を確保

    if (!p_mozi) {
        exit(1);
    }

    strcpy(&p_mozi->str, str);

    printf("%s\n", &p_mozi->str);

    free(p_mozi);
    
}
```
# 案その3

**コメントで教えてもらいました。**
フレキシブル配列メンバという機能がありまして…

```C
#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct {
    size_t p_num;
    char str[];
    //ほかにもなんかいろいろデータが入ってる
}mozi;

const int str_num = 2;//文字列の数

int main(void) {

    char str1[] = "文字列";//格納したい文字列(固定長じゃねえかってツッコミは無しで)
    char str2[] = "もじれつ";

    mozi* mozi1;

    //ポインタの数を入れるsize_t,文字列の位置を示すchar*,文字列本体
    mozi1 = (mozi*)calloc(1,sizeof(size_t) + (sizeof(char*) * str_num) + strlen(str1) + 1);
    
    if (!mozi1) {
        exit(1);
    }

    strcpy(mozi1->str, str1);
    printf("mozi1:%s\n", mozi1->str);

    free(mozi1);
}
```
### メリット

- malloc()を一回で済ませることができる

### デメリット

- 初見の人が混乱しそう



# まとめ

デバッグの手間などを考えると素直に2回mallocかフレキシブル配列メンバでいいと思います。
【Vue 3】連想配列を IndexedDBに格納する方法

## 結論
1. toRaw関数に連想配列を引き渡す。
2. 「1」の戻り値をIndexedDBに格納する。

## 前提
Node.jsが利用できない環境のため、
以下のコードの通り、CDNより、Vue 3を読み込んで利用している。

``` HTML
<html lang="ja">
    <head>
        <script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
    </head>
<!--- 以下省略 --->
```

※ 検証した時のバージョンは、「3.3.13」である。

## 詳細
Vue 3では、連想配列がリアクティブオブジェクトとして扱われているため、
一度、ピュアオブジェクトに変換してから、IndexedDBに格納する必要がある。

以下にサンプルコードを提示する。
``` js
vue.createApp({
    data : {
        productInformation = { item : 'しらす' , from : '静岡' }
    },
    method : {
        Insert : () => {
            const productInformationOfRaw = vue.toRaw(this.productInformation)
            // productInformationOfRawをIndexedDBに格納する処理（省略）
    },
    // 以下省略
}).mount('#app')
```

## 参考文献
https://blog.udyest.net/posts/idb-with-vue3-proxy/

https://ja.vuejs.org/api/reactivity-advanced

https://ja.vuejs.org/guide/quick-start

## 余談
Vue 2（バージョン 2.7）では、連想配列をそのまま、IndexedDBに格納できた。
NT Auth ストア へ ルート証明書 をインポートする

# はじめに
Windows 環境 で 802.1x 認証を行う際に、この対応が必要です。

- PEAP (MS-CHAPv2) を使う場合に、証明書 の "確認画面" を抑制したい場合（任意）
- EAP-TLS または PEAP (EAP-TLS) を使って認証したい場合（必須）

:::note warn
PEAP (MS-CHAPv2) の場合は、クライアント側の ウザイ確認画面の抑制のためだけですが、EAP-TLS , PEAP (EAP-TLS) の場合は、NPS サーバー側で クライアント証明書 のチェックの際に利用されるため、必須の作業となります。
:::

:::note info
以下の記事で、NPS + WiFi + 802.1x 認証 を行うための手順について解説しており、その中で、NT Auth ストア の件も出てきますので、まずは このサイトを参照ください。
:::

https://qiita.com/carol0226/items/05d8ef17a6d25018cd4e

# 1. 事前準備
1. ブラウザで http:// [ADCSのIP] /certsrv へアクセス
1. ルート証明書をダウンロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/8d231d7b-e718-e1fe-443a-c757ffdc98fd.png)

## 2. NT Auth ストア への インポート 方法
### 2-1. ドメイン環境 の 場合
ドメイン環境の場合は、ドメインコントローラー へ インポートすることで、ドメインに参加したコンピューターへ配布されます。

1. ドメインコントローラー へ ログオン
1. コマンドプロンプトを管理者実行し、証明書を DL したフォルダへ移動、以下のコマンドを実行
~~~
certutil -dspublish -f [ルート証明書のファイル名] NTAuthCA
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/ebe02dd5-0ac6-5d32-a016-8790b9b61dea.png)

3．"gpupdate /force" コマンド を実行して ポリシー を反映させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/ac5d6962-4daf-83d4-83ca-2e342b90e386.png)

結果は、3 章 の 確認方法を参照してください。

### 2-2. ドメイン外 の クライアント・NPSサーバー の 場合
ドメイン外 とは、WORKGROUP だったり 別のドメインに参加している 場合を指します。

以下の EAP を利用する際に、各 ホスト毎に 作業が必要です。
- PEAP (MSCHAPv2) ： すべての クライアント PC
- EAP-TLS , PEAP (EAP-TLS) ： すべての クライアント PC , NPS サーバー
1. クライアント へ ログオン
1. コマンドプロンプトを管理者実行し、証明書を DL したフォルダへ移動、以下のコマンドを実行
~~~
certutil -enterprise -addstore NTAuth [ルート証明書のファイル名]
~~~

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/4a52f4ec-febe-e587-96a4-2dbff3c02bfb.png)

# 3. 確認方法
各ホストの NT Auth ストア に配布されたレジストリ値と ルート証明書の 拇印 が一致していることを確認します。

## 3-1. 配布確認
ルート証明書 の 拇印 が ちゃんと配布されたのかどうかは、配布先のホストで 以下のレジストリを確認します。
※ドメイン環境で配布されていなかった場合、"gpupdate /force" を実行しましょう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/a2f2f050-1d47-5fd7-71b6-bc1390a2e4cd.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/0e74f45e-c8a1-0e06-0d89-c569be2bbe6d.png)

## 3-2. 一致確認
レジストリに配布された値と、"信頼されたルート証明機関" にインポートされている ルート証明書 の 拇印 の値が一致していることも確認しましょう。
ココがズレていると、意味がありません。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1619637/72d6e53b-0212-ab2a-b304-cc7ee600bb05.png)

:::note warn
この手順では、ルート証明書 が "NT Auth ストア" にインポートされるのみで、"信頼されたルート証明機関" にインポート はされません。別途の作業にて ルート証明書 を 、"信頼されたルート証明機関" に インポートしてください。
:::

# 参考情報
（公開情報）
私の記事では、以下の公開情報のうち「方法 2 - Certutil.exeを使用して証明書をインポートする」の手順を採用して記載しています。

https://learn.microsoft.com/ja-jp/troubleshoot/windows-server/windows-security/import-third-party-ca-to-enterprise-ntauth-store
Tableau と Power BI DAY3 (NETWORKDAYS)

# 説明

Tableau で作成した内容をPower BIで再現しようとしたらどうなるかやってみた

# 参考にしたサイト

Tableau 極める Day3

https://zenn.dev/rsugimura/articles/fc78ad57228350#day3

# 設問
注文日と出荷日を営業日ベースで日数計算する

# 解き方
### Tableau
曜日ごとに土日の数をカウントしてひく

~~~
CASE DATEPART("weekday",[注文日])
　　WHEN 7 THEN DATEDIFF("day",[注文日],[出荷日]) - 2 * ( DATEDIFF("week",[注文日],[出荷日],"monday") -1) -1 //土曜日
　　WHEN 1 THEN DATEDIFF("day",[注文日],[出荷日]) - 2 * ( DATEDIFF("week",[注文日],[出荷日],"monday") -1) -0 //日曜日
　　ELSE DATEDIFF("day",[注文日],[出荷日]) - 2 * DATEDIFF("week",[注文日],[出荷日],"monday") //それ以外
END
~~~

### Power BI
NETWORKDAYS関数で営業日数をカウントする

~~~
作業日数 = NETWORKDAYS(DATEADD([注文日],1,DAY),[出荷日],1)
~~~

* NETWORKDAYS(<start_date>, <end_date>[, <weekend>, <holidays>])
weekendは、start_date と end_date の間の全稼働日数に含まれない曜日を指定します。
番号の各値は、次の週末を示します:
1 または省略: 土曜日、日曜日
2: 日曜日、月曜日
3: 月曜日、火曜日
4: 火曜日、水曜日
5: 水曜日、木曜日
6: 木曜日、金曜日
7: 金曜日、土曜日
11: 日曜日のみ
12: 月曜日のみ
13: 火曜日のみ
14: 水曜日のみ
15: 木曜日のみ
16: 金曜日のみ
17: 土曜日のみ

holidaysは、稼働日カレンダーから除外する祝日の日付を指定します。
NETWORKDAYS([注文日],[出荷日],1,{DATE(2021,9,20), DATE(2021,9,23)})
    
# 最後に
NETWORKDAYS関数は便利ですね。
Power BIは現在勉強中のため、もっと良いやり方あればぜひ教えてください。
Tableau と Power BI DAY2 (DATEADD/DATEDIFF)

# 説明

Tableau で作成した内容をPower BIで再現しようとしたらどうなるかやってみた

# 参考にしたサイト

Tableau 極める Day2

https://zenn.dev/rsugimura/articles/fc78ad57228350#day2

# 設問
指定した期間の前年同期間のオーダー日データを計算してください。

# 解き方
### Tableau
オーダー日を、指定した期間の年月データに変換したフィールドを作り、作成したフィールドで集計を行う

~~~
DATEADD("year",DATEDIFF("year",[オーダー日],[TODAY]),[オーダー日])
~~~

* DATEADD(date_part, interval, date)
dateにdate_partの単位で、Intervalを足して戻す


### Power BI
オーダー日を、指定した期間の年月データに変換したフィールドを作り、作成したフィールドで集計を行う

~~~
DATEADD([オーダー日],DATEDIFF([オーダー日],[TODAY],YEAR),YEAR)
~~~

* DATEADD(date1,number_of_intervals,interval)  
dateにintervalの単位で、number_of_intervalsを足して戻す

* DATEDIFF(Date1, Date2, Interval)  
date1とdate2の差をIntervalの単位で戻す


# 最後に
同じDATEADDやDATEDIFFを使っているが、構文上単位を明示する場所が違うので、注意
Power BIは現在勉強中のため、もっと良いやり方あればぜひ教えてください。
docker-composeを使ってWindows11でTensorflowの環境構築

# 概要
Windows11搭載のPCにおいて，`docker compose`でPython + Tensorflow の環境（コンテナ1つ）を作るときの手順です．

私の場合オリジナルのデータセットをすべて外付けSSDに入れており，ドライブをマウントする必要があるのでそれも手順に加えました．

## 環境
- Windows11
- WSL2
- Docker Desktop 4.26.1

（追記：2023/12/29）Windows11 に Docker をインストールする方法はこの記事にまとめました．

https://qiita.com/naokey1228/items/2ece9f9b06982db5bcf7

# 手順
## ドライブのマウント
`[D:]`は外付けドライブのパス．パソコンによって違うためエクスプローラーから確認．
```bash
sudo mkdir /mnt/usb1
sudo mount -t drvfs [D:] /mnt/usb1
```

マウントできているか確認
```bash
df -h
```

実行して，以下のように`D:`が表示されていれば成功！

```
Filesystem                                Size  Used Avail Use% Mounted on
none                                      3.8G  4.0K  3.8G   1% /mnt/wsl
none                                      953G  267G  687G  28% /usr/lib/wsl/drivers
/dev/sdc                                 1007G  1.8G  954G   1% /
.
.
.
D:                                        954G   30G  925G   4% /mnt/usb1
```

## `docker-compose.yml`の作成

ディレクトリ構成．ワーキングディレクトリの直下に作成
```
workdir
├── src
├── Dockerfile (今回は使わなかった)
├── docker-compose.yml
└── etc.
```

---
`docker-compose.yml`の中身．
```yml:docker-compose.yml
services:
  dk_ml:
    image: tensorflow/tensorflow:2.13.0rc0-gpu
    # build: .
    volumes:    # ボリュームマウント
      - /mnt/usb1/vanguard:/mnt
      - .:/app
    ports:      # portの公開
      - "6006:6006"
    deploy:     # GPUの利用
      resources:
        reservations:
          devices:
            - capabilities: [gpu]
    shm_size: "256mb"
    tty: true

```
portは Tensorboard 用に公開．GPUを利用できるようにするのが手間取りました．`docker run`なら引数に`--gpus=all`を加えるだけだったので，複数行使うのが少し煩雑に感じました．
また，`tty: true`を入れないと，コンテナが終了してしまいました．こちらのサイトを参考にしました．
[docker-compose で exit with status 0 の解決法](https://zenn.dev/torkralle/articles/388ae878cb5f8b)

## コンテナの作成
WSLのターミナルから以下のコマンドを実行．
```bash
cd workdir
docker compose up -d
```
これでコンテナが作成されたので，あとはVSCodeからAttachすれば完了！

動いているサービスを確認するコマンドは以下
```bash
docker compose ps
```

サービスの停止
```bash
docker compose stop
```

サービスの開始
```bash
docker compose start
```

### （比較）`docker run`を使う場合
今までは`docker compose`を使わずに`docker run`でコンテナを作成してました．

```bash
docker run -it \
    -v /mnt/usb1:/mnt \
    -v $PWD:/app \
    -p 6006:6006 \
    --gpus all \
    --shm-size 256m \
    --name dk_ml \
    tensorflow/tensorflow:2.13.0rc0-gpu bash
```
コンテナを作成する毎に上のコマンドを打ってたので結構大変で，間違えて入力してしまうこともしばしば，，，

`docker compose`を使えば yml を作るだけでコマンドで楽できてありがたい．

でも yml 作るのはそれなりに手間なので，コンテナ1つだけなら結局どっちがいいのでしょうか？

# 参考
以下のサイトを参考にさせていただきました（参照日はいずれも2023/12/28）．
- [docker-compose で exit with status 0 の解決法](https://zenn.dev/torkralle/articles/388ae878cb5f8b)
- [Compose で GPU アクセスの有効化―Docker-docs-ja 24.0 ドキュメント](https://docs.docker.jp/compose/gpu-support.html)
- [（備忘録）Docker Compose（1コンテナだけ）でTensor Flow環境構築時のメモ #Python - Qiita](https://qiita.com/okubo1504/items/33e7bd7f17b8b44fccc0)
2023年emacs-twistの振り返り

（[先日のポスト](https://qiita.com/akirak/items/517b26a14a54d43f3652)の一部として既に投稿した内容ですが、元のポストが長く、内容としても独立していると思ったので分離させました。12月25日のポストを既に読んだ方は、内容は同一ですので無視してください。）

[Twist.nix](https://qiita.com/akirak/items/9920616bd3eff26eb6c0)は、2年前から今でもまだalpha版です。 alpha版とはどういうことかというと、一般ユーザが試用することを想定しておらず、内部的に探求しながら開発を進めている段階（要は私が個人的に使っているだけ）です。 具体的には、公式なuser documentationがないため、使ってみたい人は手探りで試してねという状態です。 私自身のEmacsはtwistに全面的に依存しているし、有望な代替は今のところないので、私が死なない限りtwist.nixが突然終了することはないでしょう。

2023年のemacs-twistの主な進捗は、以下の通りです。

-   twist.nix本体の、細かなAPIの変更や追加。
-   Emacsを再起動せずにパッケージを更新するための[twist.el](https://github.com/emacs-twist/twist.el)ができた。
-   FigmaとAstroで[ウェブサイト](https://emacs-twist.github.io/)を試作した（ほぼフロントエンドの練習目的）。
-   [twist-archiver](https://github.com/emacs-twist/twist-archiver)など、周辺ツールやライブラリーがちょっと増えた。

進捗は少ないです。 プロジェクト自体が長期的な持続可能性とメンテナンスの少なさを重視していますし、Nix全体のエコシステムはコミュニティによって着実に進歩していくので、なるべくただ乗りしていく方針です（NixOS Foundationには微額ながら[寄付している](https://opencollective.com/akira-komamura)ので、厳密にはただ乗りではないかもしれませんが）。 

## OCaml採用の機運

emacs-twistは（現状では事実上）私の一人プロジェクト（one-man band）ですし、私個人のスキル形成という観点で、NixとEmacs以外の技術も導入しようとしています。

具体的には、2023年に流行したOCamlの利用を検討しています。 OCamlは、OCaml 5.0で[multicore OCaml](https://github.com/ocaml-multicore)となり[algebraic effects](https://discuss.ocaml.org/t/how-is-algebraic-effects-better-than-adding-a-parameter/13655/4)にも対応しました。 さらにJane Streetが[Rustスタイルの所有権](https://blog.janestreet.com/oxidizing-ocaml-ownership/)などの拡張機能に取り組んでいます。 Microsoft Researchの[Koka](https://koka-lang.github.io/koka/doc/book.html)も先進的な機能を備えた言語であり、今後に期待したいところですが、現時点ではまだproduction-readyとはいえないでしょう。

https://twitter.com/ChShersh/status/1707142750464856541

日本国内ではOCamlはHaskellほど話題になっておらず、なぜHaskellではなくOCaml？と思うかもしれません。 Haskellは私が10年以上昔に学習した言語ですが、長期的な保守性（コンパイラのバージョンが上がったときにコードを書き換える手間等）という点で不安があり、現在一人では使わないことにしています。 

https://x.com/public_ai000ya/status/1884152516298039757

Haskellを実際のプロジェクトに使うことの利点と欠点は以下のビデオで説明されていますが、Twistは競争していないので、速く確実にリファクタリングできるというHaskellの強みは活かされないと思います。 OCamlはHaskellよりも後方互換性を大切にする文化らしいので、Emacsのプロジェクトと相性がいいと思います。

https://www.youtube.com/watch?v=qw4S_6FXsp4

HaskellとOCamlの経験がある人による両言語の比較は以下の記事にあります。

https://dev.to/chshersh/8-months-of-ocaml-after-8-years-of-haskell-in-production-h96

すべてのプログラミング言語はチューリング等価ですが、開発者にとって同じではありません。

https://twitter.com/mbacarella/status/1738988360784588805

## Nix flakesが普及し始めている

そのほか、emacs-twistとは関係ありませんが、私個人の実績として、今年は2〜3のプロジェクトでNixを使ったCIの構築に貢献しました。

-   [Switch from niv to flakes by purcell · Pull Request #183 · purcell/nix-emacs-ci · GitHub](https://github.com/purcell/nix-emacs-ci/pull/183)
-   [Use Nix to install a custom build of Emacs on CI by akirak · Pull Request #20 · emacs-php/php-ts-mode · GitHub](https://github.com/emacs-php/php-ts-mode/pull/20)
-   [Improve flake.nix to save build time, make \`nix run\` work again, and check builds on CI by akirak · Pull Request #312 · elixir-tools/next-ls · GitHub](https://github.com/elixir-tools/next-ls/pull/312)

後の2つは、Nixとは直接的な関係がないプロジェクトですが、`flake.nix`が入りました。Nix以外の様々な言語のリポジトリに、`flake.nix`が入り始めているのが最近の流れです。
空の Tuple は ( , ) ではない

## この文書の目的

一要素の Tuple は (1,) と書くのに空 Tuple は (,) ではなく ( ) と書くことを知った時の驚きを書き残したい、という、だけ、のものです。
（ああ話が終わってしまった）

## つまり

Python の Tuple は、

* 三要素の Tuple は (1, 2, 3) と書く 　　 ← わかる
* 二要素の Tuple は (1, 2) と書く 　　 ← わかる
* 一要素の Tuple は (1, ) と書く 　　 ← ええええ
    * ( 1 ) と書くと int の 1 だと認識される 　　 ← なるほど仕方ない
    * (1, ) と書くことで一要素の Tuple だと認識される 　　 ← ええええ

そうか「 , 」があることが Tuple を産むのか、と思いきや、

* 空の Tuple は ( , ) ではなく ( ) と書く 　　 ← なんということ
    * ( ) と書くと空 Tuple 　　 ← ほうそう来たか
    * ( , ) と書くと文法エラー 　　 ← ええええ 

直感的には、
* ( ,1) と書くと今は文法エラーだが、これも一要素の Tuple とすることにして、
* (,) と書くと空 Tuple になる

方がしっくりくる感じもあるが、まあ仕方ないか。

## 補足

なお a = 1, 2 のように、曖昧さなくこれは Tuple だと判断できる場合は ( ) は不要です。
type(1, 2) と書くとしかし type( ) 関数に引数が二つあると解釈されてしまうので、こうした場合は type( (1, 2) ) と書かねばなりません。
Tableau と Power BI DAY1 (DATETRUNC/EOMONTH)

# 説明

Tableau で作成した内容をPower BIで再現しようとしたらどうなるかやってみた

# 参考にしたサイト

Tableau 極める Day1

https://zenn.dev/rsugimura/articles/fc78ad57228350#day1

# 設問
すべての注文IDについて、オーダー日から月末(月末を含む)までの日数を計算してください。

# 解き方
### Tableau
オーダー日の月末を求めて、オーダー日と月末との差を求める
~~~
DATEDIFF('day',[オーダー日],DATEADD('day',-1,DATETRUNC('month',DATEADD('month',1,[オーダー日]))))
~~~

* DATEDIFF(date_part, date1, date2, [start_of_week])
date1とdate2の差をdate_partの単位で戻す

* DATEADD(date_part, interval, date)
dateにdate_partの単位で、Intervalを足して戻す

* DATETRUNC(date_part, date, [start_of_week])
dateをdate_partの単位に丸めて戻す


### Power BI
オーダー日の月末を求めて、オーダー日と月末との差を求める
計算を二つに分けて作成してみた

~~~
オーダー日(月末) = EOMONTH([オーダー日],0)
オーダー日(月末までの日数) = DATEDIFF([オーダー日],[オーダー日(月末)],DAY)
~~~

* EOMONTH(start_date, months) 
start_dateからmonths月数後の月末日を戻す。<months>を0にすると当月となる。

* DATEDIFF(Date1, Date2, Interval)  
date1とdate2の差をIntervalの単位で戻す


# 最後に
Power BIは現在勉強中のため、もっと良いやり方あればぜひ教えてください。
Next.jsの概念を図解と表解でまとめてみた

# はじめに

これまでNext.jsの勉強をしたことがなかったので、最近少し動画を見ながら勉強をしてみました。今回はソースコードの内部的な話ではなく、「そもそもNext.jsはどういった仕組みか？」とか「どういったときに使用するのが便利か？」といった、概念に関わる知識をまとめようと思います。

※勉強に使用した動画「日本一わかりやすいNext.js入門」：https://www.youtube.com/watch?v=F77RUjHZEAc&list=PLX8Rsrpnn3IUGEyanrHYGjY1WOzNe7Jd-

# Next.jsとは？

Next.jsにはそれぞれ以下のような特徴があります。

|項目|内容|
|---|---|
|意味|React(フロントエンド)のフレームワーク|
|利点|多様な大規模なアプリ開発に便利|
|特徴|SSGとSSRを用途に応じて使い分けることができる。|

Next.jsはReact言語をベースにアプリ開発をサポートするフレームワークになっており、多様な大規模アプリを作成するためのツールとして優れています。その優れている点で大きな特徴として挙げられるのが「SSG」と「SSR」といった特徴になります。

# SSGとSSRとは？

### SSG(Static Site Generation)

SSGの特徴と流れは以下のようになります。

|項目|内容|
|:-:|---|
|意味|静的なコンテンツを生成するアーキテクチャ|
|利点|静的なコンテンツを高速で表示できる。|
|欠点|リアルタイム性は担保できない。|
|用途|画面の更新頻度が低いコンテンツに利用(例：ブログ, お問合せフォーム)。|

![SSG.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/35fbfbc8-3ce5-3dea-26d7-8c954baa8270.png)

SSGは、サーバ構築時にコンテンツを生成することで、リクエスト時にコンテンツを表示できる仕組みとなっています。事前にサーバ構築を完了させておくことで、画面遷移時のコンテンツも高速で表示することができます。しかし、あらかじめサーバ内でコンテンツを事前作成するため、リアルタイムなデータが欲しい場合には不向きとなっています。
そのため、ブログやとお問合せフォームなどの画面の更新頻度が低いコンテンツに利用されます。

### SSR(Static Server Rendering)

SSRの特徴と流れは以下のようになります。

|項目|内容|
|:-:|---|
|意味|リクエストごとにサーバ側でHTMLファイルを作成するアーキテクチャ|
|利点|①動的なコンテンツを表示できる。<br>②リアルタイム性も担保してくれる。|
|欠点|画面表示の読み込みに時間がかかる|
|用途|データの更新頻度が高いコンテンツに利用(例：SNS, Youtube)。|

![SSR.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/c558ff90-1375-bacd-8466-6625a10a8362.png)

SSRは、クライアントサイドがリクエストを投げるタイミングでサーバ側でコンテンツを作成する仕組みとなっています。リクエストごとに画面表示処理を行うため、動的なコンテンツにも対応ができる利点があります。また、DBにも随時アクセスすることで、リアルタイム性も担保できます。その一方でSSGと比較して、逐次サーバ側でコンテンツを生成するために、画面表示の読み込みに時間がかかる欠点もあります。
そのため、SNSやYoutubeなどのデータの更新頻度が高いコンテンツに利用されます。
<br>

![SSR(async).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3661690/2b05a5c8-5a21-ae3f-aff5-c2e921bdbe50.png)

また、上図のように非同期通信を適用することで、コンテンツを作成するwebサーバを経由せずにデータの送受信のみを行うことができるため、より高速にリアルタイム性の担保が実現できます。

# リクエスト先指定方法

SSG,SSRどちらのアーキテクチャでもクライアントサイドからリクエストを送信するのですが、そのリクエスト先を指定する方法として、大きく2種類あります。

### 静的なルーティング

|項目|内容|
|:-:|---|
|特徴|1つのファイルを1つのURLに紐付ける方法|
|用途|一覧画面やTOP画面|

ここでは、1つのファイルに対して1つのURLを指定する方法になります。用途として、一覧画面やTOP画面などコンテンツの一覧やベースとなる画面に対して用いることが多いです。

### 動的なルーティング(ダイナミックルーティング)

|項目|内容|
|:-:|---|
|特徴|1つのファイルを複数のURLに紐付ける方法|
|用途|詳細画面|

静的なルーティングとは対称的に、1つのファイルに対して複数のURLを指定する方法になります。このルーティングを**ダイナミックルーティング**と呼びます。また、特に深い層までURLを指定するルーティングを**Catch all route**と呼びます。用途として、詳細画面などコンテンツの中身を作成する画面に対して用いることが多いです。

# 最後に

Next.jsについて、上記動画を軸に色々調べながらまとめてみました。これで、Next.jsの大枠の概念はある程度把握できる(気がする)ので、今後は「TypeScriptの導入方法」や「実際に模写コーディングしてみる」ことをやって更なる理解を深めていければと思っています。
Jest+TypeScriptでimportが出来なくてハマったのでメモ

## 開発環境
- Visual Studio Code (Version: 1.85.1)
- Node.js: 21.5.0
- @types/jest: 29.5.11
- jest: 29.7.0
- ts-jest: 29.1.1
- ts-node: 10.9.2
- typescript: 5.3.3

## 問題:
- Jestを使用していました。
- テスト用のTypeScriptファイルからimportしようとすると、以下のエラーが発生しました。

```shell
    SyntaxError: Cannot use import statement outside a module

      at Runtime.createScriptFromCode (node_modules/jest-runtime/build/index.js:1505:14)

Test Suites: 1 failed, 1 total
Tests:       0 total
Snapshots:   0 total
Time:        0.179 s
Ran all test suites.
```

### 解決法:

`jest.config.ts` ファイルに `preset: 'ts-jest'` を追加することで解決しました。

```typescript
// jest.config.ts
import type { Config } from "jest";

const config: Config = {
  preset: 'ts-jest',
  // ...
};
```

※ts-jestがインストールされていない場合は、以下のコマンドでインストールする必要があります。

```shell
npm i -D ts-jest
```

以下のようにテストが通るようになりました。

```shell
$ npx jest

 PASS  __tests__/sum.test.ts
  ✓ 4と5を足すと9 (1 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.702 s
Ran all test suites.
```
[Python][Julia]Project euler3 (プロジェクトオイラー3)

### Project euler Ploblem 3 (プロジェクトオイラー3)
#### Largest Prime Factor

備忘のために残しておく。

2023/12/29 コメントで指摘の通り、誤ったコードを書いていたので修正しました。
（コメントありがとうございます)

## 問題文
13195の素因数は5,7,13,29である。
600851475143の最大の素因数は？


(原文)
The prime factors of 13195 are 5,7,13 and 29.
What is the largest prime factor of the number 600851475143?


## 解答

#### 答え
<b>6857</b>

#### 解答の方針
求める値の平方数までの素因数を前から順にリストに追加する。
例えば、12の場合だと[3,2]、25の場合だと[5]。
今回の場合は、[6857, 1471, 839, 71]
リストの一番前が、最大の素因数となる。
素数の判定アルゴリズムに「エラトステネスの篩」があるが、今回は使用しなかった
参考：[エラトステネスの篩](https://qiita.com/drken/items/3beb679e54266f20ab63)


#### Pythonのコード
```Python: Python(Ploblem3)
def largest_prime_factor(num: int) -> int:
    divisor =[]
    temp = num
    for i in range(2, int(num**0.5) + 1):
        if temp % i == 0:
            while temp % i == 0:
                temp //= i
            divisor.insert(0,i)
    if temp != 1:
        divisor.insert(0,temp)
    if divisor == []:
        divisor.insert(0,temp)
    return divisor[0]

num = 600851475143
print(largest_prime_factor(num))
```
#### Juliaのコード
```Julia: Julia(Ploblem3)
function largest_prime_factor(num::Int64)::Int64
    temp = num
    divisor = []
    for i in 2:ceil(num^0.5)
        if temp % i == 0
            while temp % i == 0
                temp ÷= i
            end
            insert!(divisor, 1, i)
        end
    end
    if temp != 1
        insert!(divisor, 1, temp)
    end
    if divisor == []
        insert!(divisor, 1, temp)
    end
    return divisor[1]
end
num = 600851475143
println(largest_prime_factor(num))
```
AWS初心者におすすめの3つのサービス（2025年版）✨


## 🌟 **概要**
AWS（Amazon Web Services）は、Amazonが提供するクラウドコンピューティングサービスで、サーバー、ストレージ、データベース、ネットワーク、分析、機械学習など、多岐にわたるサービスを提供しています。2025年現在、AWSはさらに進化し、新機能やコスト最適化のオプションが充実しています。

本記事では、AWS初心者におすすめの3つのサービス「S3」「EC2」「RDS」を最新情報を交えて解説します。これらのサービスは、クラウド活用の基礎を学ぶ上で最適です！

---

## 🚀 **1. S3（シンプルストレージサービス）**
S3はAWSのオブジェクトストレージサービスで、ファイルの保存や共有に便利です。2025年には新機能が追加され、さらに強力になりました。

### ✅ **特徴**
- 容量無制限で利用可能。
- **S3 Intelligent-Tiering**: データアクセス頻度に応じてコストを自動最適化。
- **S3 Glacier Deep Archive**: 長期保存用データに最適な低コストオプション（$0.00099/GB/月）。
- **S3 Tables**: Apache Iceberg対応で、大規模データ解析が容易に。

### 🔄 **新機能（2025年版）**
- **S3 Tables**: データレイク向けの高速クエリとスナップショット管理。
- **S3 Metadata**: データガバナンスを強化するメタデータ管理。

### 💡 **利用例**
- ウェブサイトの画像や動画ホスティング。
- バックアップやアーカイブ。
- データ分析基盤としてAthenaやRedshiftと連携。

---

## 💻 **2. EC2（エラスティックコンピューティングクラウド）**
EC2はAWSの仮想サーバーサービスで、柔軟なコンピューティング環境を提供します。2025年には新しいインスタンスタイプが追加され、さらに効率的な運用が可能です。

### ✅ **特徴**
- 必要に応じてスペックや台数を自由に変更可能。
- オンデマンド、予約インスタンス、スポットインスタンスなど多様な料金体系。
- Graviton3プロセッサ搭載インスタンスで最大25%のコスト削減。

### 🔄 **新機能（2025年版）**
- **Flexインスタンス**: 新しい12xlargeおよび16xlargeサイズが追加。
- **t4g.small無料利用枠延長**: Graviton2搭載インスタンスが2025年末まで無料（750時間/月）。

### 💡 **利用例**
- ウェブアプリケーションやゲームサーバーのホスティング。
- 機械学習モデルのトレーニング。
- IoTデバイスからのデータ処理。

---

## 🗄️ **3. RDS（リレーショナルデータベースサービス）**
RDSはMySQLやPostgreSQLなどのリレーショナルデータベースを簡単に構築・運用できるマネージドサービスです。2025年には最新バージョンへの対応が進み、さらなるパフォーマンス向上が図られています。

### ✅ **特徴**
- 自動バックアップとセキュリティ管理。
- マルチAZ配置による高可用性。
- MariaDB 11.7など最新データベースエンジンへの対応。

### 🔄 **新機能（2025年版）**
- MariaDB 11.7対応: ベクターデータ型や高速検索機能をサポート。
- RDS Extended Support: サポート終了後も最大3年間延長可能。

### 💡 **利用例**
- ウェブサイトやアプリケーションのデータベース。
- ビジネスインテリジェンスツールとの連携。
- データ分析や機械学習用データストア。

---

## 💰 **料金体系と無料利用枠**
AWSは「使った分だけ支払う」料金体系を採用しており、以下のようなオプションがあります：
1. **オンデマンド**: 使用量に応じた従量課金。
2. **予約インスタンス**: 長期契約で割引適用（最大72%）。
3. **スポットインスタンス**: 空きリソースを競売形式で利用。

さらに、多くのサービスには無料利用枠があります：
- S3: 5GBまで無料。
- EC2: t4g.smallインスタンス750時間/月無料（2025年末まで）。
- RDS: 750時間/月無料（db.t2.micro）。

---

## 🎯 **まとめ**
AWS初心者には「S3」「EC2」「RDS」の3つのサービスがおすすめです。それぞれが提供する柔軟性と拡張性を活用しながら、クラウド活用スキルを磨くことができます。2025年現在、新機能やコスト最適化オプションも充実しており、これらを活用することで効率的な運用が可能です。

ぜひこれらのサービスから始めてみてください！🌟
MariaDBのバイナリーログ基礎知識（出力場所や保存期間など）

# 前提

Windows10にインストールしたMariaDBに対する情報となります。

# バイナリーログとはなんぞや

主に下記で使われることが多いログです。

* レプリケーション。
* 世代バックアップからのロールフォワード。

CREATEやUPDATEなどのデータベースに変更が加わる全てのイベント（SQL）が記録されています。

# 公式サイト

https://mariadb.com/kb/ja/overview-of-mariadb-logs/

https://mariadb.com/kb/en/overview-of-the-binary-log/

https://mariadb.com/docs/server/ref/mdb/system-variables/expire_logs_days/

# my.ini

* バイナリーログを出力するかどうか。
* バイナリーログのファイル名。
* バイナリーログの保存期間。

上記のような設定をしたい時はmy.iniに書きます。

```:my.iniがある場所
C:\Program Files\MariaDB 10.5\data
```

# 出力設定

まず前提としてバイナリーログは **出力しないがデフォルト** になっています。

my.iniに **設定を書いて初めて出力** され始めます。

そして、例えば設定が下記なら…
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/a96502d1-a364-7791-ed0a-85896840f7cc.png)

こう出ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/f0f3124f-b7d2-be69-fe3a-e6d85e88dcee.png)

# ログ保存期間

まず前提として **ログ保存期間を設定しないとバイナリーログが溜まり続けます** 。

例えば設定が下記なら **3日間はバイナリーログを保存** になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/87d49b7c-4f69-b5d4-73fe-0497a3a7ffe2.png)

# バージョン

Microsoft Windows [Version 10.0.19045.3803]
MariaDB 10.5.4
PowerAutomateフローのテスト実行でエラー "Cannot read properties of undefined (reading 'config')" 

2023年11月ころから（？）、PowerAutomate にアップデートが行われて「新しいデザイナー」が導入されました。
今回はその「新しいデザイナー」使用中に遭遇したエラーの対処法です。

# Problem

PowerAutomateの新UIでワークフローを編集中、テスト実行をしようとしたところでこのようなエラーが表示されました。エラーが発生し、テスト実行ができません：

> Cannot read properties of undefined (reading 'config')

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50571/38a8ac96-69fe-7c80-450c-839b08b8cab1.png)

編集画面に入り直しても、直前の編集内容をロールバックしたり、フローの複製を作成したりしましたが、状況は変わらず。。。😥

# Solution

ブラウザのキャッシュをクリアして画面を再読み込みします。
以上です。

これで治ったので、個々のワークフローの問題ではなく、PowerAutomateの新UIに混入している不具合が原因のようです。
Prismaで存在しないレコードを削除するときに注意すること

## はじめに
Prismaをご存知でしょうか？PrismaはオープンソースのORM(Object-relational mapping)で、SQLを書かずにDBを操作できるツールです。

## 実装内容
book_mstというテーブルがあり、bookIdというカラムを持っています。
指定したbookIdを持つレコードがある場合は該当のレコードを消し、指定したbookIdを持つレコードがない場合は何もしないという処理を実装しようとしていました。


## 遭遇した課題
Prismaで以下のようなクエリを用意しました。

```ts:sql
prisma.book.delete({
  where: {
    bookId: bookId,
  },
});
```
しかし該当するbookIdがない場合以下のようなエラーが出現しました。

```:error
An operation failed because it depends on one or more records that were required but not found. Record to delete does not exist.
```

SQLでは、DELETE文でWHERE句を使用してレコードを削除する際、指定した条件に一致するレコードが存在しない場合でもエラーは発生しないはずです。単に削除対象のレコードが存在しないだけでクエリは正常に完了します。

```sql:sql
DELETE FROM book_mst WHERE bookId = 123;
```


オープンソースを確認すると、この箇所の改善要請は上がっているみたいですがまだ修正されていないようです。
https://github.com/prisma/prisma/issues/4072


## 解決策

以下のようにレコードの存在確認をしてからクエリを通したらエラーに遭遇しなくなりました！

```ts:sql
const existingRecord = prisma.book.findUnique({
    where: {
      bookId: bookId,
    },
});
    
if (existingRecord) {
    prisma.book.delete({
        where: {
            bookId: bookId,
        },
    });
}
 ```
Talend API Testerを使ってAPIの動作確認

## 概要
* Chromeの拡張機能「Talend API Tester」を追加し、作成したAPIの動作を確認する手順を記述。
* PowerShellにてcurlコマンドを用いて動作確認する方法も併せて記述。
* [Spring bootでHelloWorldするまでの手順](https://qiita.com/momomo1998/items/37e48a3196b4761534c9)内で使用したコードを使用。
* 使用環境：Windows 11 Pro、Chrome、PowerShell

## API (Application Programming Interface)
>その機能とは無関係なプログラムとかからその機能を利用できるようにするために用意されている、その機能にお仕事を依頼するための窓口（の使い方に関する決まり事）のことです。

[APIとは - 「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/word12428.html)

## Talend API Tester
>* Webクライアントツール
>* Webブラウザ上で簡単にAPIコールすることができる
>* Google Chromeの拡張機能
>* 無料で使える
>* リクエスト情報を複数保管しておける（再利用できる）
>* リクエスト情報をカテゴリ分けして整理することができる

[【Web API】Talend API Testerを使ってみた - isoroot開発者ブログ](https://www.isoroot.jp/blog/4241/)

* 公式ストア
[Talend API Tester - Free Edition - chrome ウェブストア](https://chromewebstore.google.com/detail/talend-api-tester-free-ed/aejoelaoggembcahagimdiliamlcdmfm?hl=ja&pli=1)

## 拡張機能の追加方法

* Chromeを起動。`拡張機能`→`Chromeウェブストアにアクセス`の順で選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/2d0a7433-731b-6b5f-be49-a31e92657c3e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/d3e53eba-6a65-7fe9-e560-c847521bc37f.png)
* `Chromeに追加`を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/100db0c8-b0e7-7be2-7941-ce734a22d407.png)

* Spring Bootの起動。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/c2748d72-35a6-1701-f228-f1d99e084477.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/97083e44-d63c-4ac8-23dd-672d98be1df8.png)

## Talend API Testerへのアクセス
* Chromeにて拡張機能のアイコンを押し、`Talend API Tester`を押す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/91275ec1-03ae-e040-c165-17c8255e88c5.png)

## APIの動作確認
* `GET`を選択し、希望のURLを入力。今回「hello」「test api」それぞれのResponseがあるか確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/083d1642-9a6d-161d-8f31-9911276e40cb.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/59e7ff87-9391-7b51-a124-e4bbed8a6893.png)
:::note warn
Spring Bootを起動していなかった場合や指定しているURLが間違っていた場合は以下のような表示がでる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/a6518976-c91f-416d-2501-5628c7afc437.png)
:::

### PowerShellにて確認する方法
* curlコマンドを使用。Spring Boot起動時。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/90c8accd-086e-7ba2-1e6e-84a3740cf0c4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/c4408108-f946-8298-44bd-cb4a7ea9f381.png)

:::note warn
Talend API Tester同様、Spring Bootを起動していなかった場合や指定しているURLが間違っていた場合は以下のようなエラー表示がでる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3624672/8478e924-4b4b-8ed8-a2a5-9669419d8f5a.png)
:::
SRE - SLI/SLP/SLAまとめ

# SREの重要な指標: SLI, SLA, SLO

## 目次

- 概要
- 機能と詳細
- なぜ必要か
- まとめ

## 概要

SRE（サイトリライアビリティエンジニアリング）は、システムの信頼性や可用性を確保するための方法論です。SREでは、システムのモニタリングや分析を通じて、適切なサービスレベルを維持するための指標を定義します。ここでは、SREで重要な指標であるSLI、SLA、SLOについて詳しく説明します。

## 機能と詳細

### 1. SLI（Service-Level Indicator）

- 機能: サービスの性能や品質を測定するための指標です。
- 詳細: SLIは、ユーザー体験やシステムの正常動作に関連するさまざまなメトリクスを表しています。例えば、レスポンスタイム、エラーレート、スループットなどが挙げられます。これらのメトリクスは、システムの健全性やパフォーマンスを定量的に評価するために使用されます。

### 2. SLA（Service-Level Agreement）

- 機能: サービス提供者とユーザーの間で合意されたサービス品質レベルを定義する契約です。
- 詳細: SLAは、サービスの最低限の品質基準や約束事を明確にするために使用されます。例えば、SLAでは、最大のダウンタイム、最小の応答時間、契約違反時の補償などが定められることがあります。SLAにより、サービス提供者とユーザーは互いの期待を明確にし、責任を共有することができます。

### 3. SLO（Service-Level Objective）

- 機能: サービスの品質目標を設定するための定量的な目標値です。
- 詳細: SLOは、SLAで定義された品質基準を達成するために設定される目標です。SLOは、SLI（メトリクス）の目標値を具体化し、測定可能な形で表現します。例えば、SLOでは、99.9%の稼働率、1秒以内の応答時間などを定めることがあります。SLOにより、SREチームは具体的な目標に合わせてシステムを監視・改善することができます。

## なぜ必要か

SREでは、信頼性と可用性の確保が重要です。SLI、SLA、SLOの導入には以下のような理由があります。

- SLI: システムのパフォーマンスを定量的に評価し、状況把握を容易にするため。
- SLA: サービス提供者とユーザーの間で品質基準を合意し、明確な責任範囲を設定するため。
- SLO: SLAで合意された品質基準を達成するために具体的な目標を設定し、品質向上や運用管理の方針を効果的に策定するため。

SLI、SLA、SLOの継続的なモニタリングと改善により、システムの信頼性を高め、ユーザー満足度を向上させることができます。

## まとめ

SREで重要な指標であるSLI、SLA、SLOは、サービスの品質や可用性を評価し、合意された品質基準を達成するために使用されます。SLIはシステムのパフォーマンスを定量的に評価するためのメトリクスであり、SLAはサービス提供者とユーザーの間で合意された品質基準を定める契約です。また、SLOはSLAで定義された品質基準を達成するために設定される具体的な目標です。これらの指標の導入により、SREチームはシステムの監視・改善を効果的に行い、信頼性と可用性を向上させることができます。
発火率モデルについて調べた感想

## 注意
この記事は筆者が思いつきで適当に想像したことの備忘録ポエムです。ご了承ください。

## はじめに
生物学的なニューロンをシミュレーションする手法として, ニューラルネットワーク分野では発火率モデルが扱われることが多い. 
発火率モデルでは, 細胞の静止膜電流$I_m$に対して, 入力信号$I_{ipt}$が与えられた時, その合計が閾値を超えると必ず発火するというものである. この式は, 次式のようになる.
$f(I_{ipt}) = 1\ \ \mathrm{if} \  I_{ipt}+I_m>I_{bias}, \mathrm{otherwize}\ 0$
ニューラルネットワークではしばしばStep関数により実装されるため, 次式で見ることが多い.
$f(x) = 1\ \ \mathrm{if} \  x>0, \mathrm{otherwize}\ 0$
そんな発火率モデルであるが, 派生として次式に示されるSigmoid関数が存在する.
$$\sigma(x) = \frac{1}{1+e^{-x}}$$
Sigmoid関数は発火率モデルを誤差逆伝播法に対応可能な形にしたものだが, 微分値が小さいことから近年の深層ニューラルネットワークに用いられることはほとんどない.

今回疑問に思ったのは, 発火率の計算においてStep関数では純粋に閾値を超えた瞬間必ず1になるということである.
そこでほかの発火率モデルである積分発火方式を調べてみた.

## 積分発火モデルの概要
発火率モデルのほかにもバイオニューロンの発火に関する様々な手法があるらしい.その一つに積分発火モデル(LIF)があった. 次式が積分発火モデルの式である.
ニューロンを抵抗$R$とコンデンサ$C$を合わせた回路に近似することで, 下の式に従い, 膜電位$V(t)$が変動する.
$$CR\frac{dV(t)}{dt} = RI(t)-(V(t)-V_{reset})$$
$V_{reset}$が静止膜電位であり, $V(t)$がだんだん増加しある閾値$V_{peak}$に達すると発火するというものである.
発火すると再び$V_{reset}$に電位が戻り, $t_{cool}$のクールタイムが発生する.

## 簡略化
今回は直流電流に絞って考えてみる. さて, 先ほどの式の括弧の中$(V(t)-V_{reset})$では, 基準電位に対する上昇あるいは減少量だけ変化する値を抑制している.
基準との差だけを見ればよいので$V(t)$は$0$から始まり, バイアス値$b=V_{peak}$で発火することにすれば簡略化されるだろう.
基準点が0になるため, 静止膜電位の部分が消え次式のようになる.
$$CR\frac{dV(t)}{dt} = RI(t)-V(t)$$
あとは簡略化ではないが, 左辺の係数$CR$を右辺に移項する.
$$\frac{dV(t)}{dt} = \frac{RI(t)-V(t)}{CR}$$

## 計算：発火の閾値と最大発火率
$C, R, b$をパラメータとした微分方程式が完成した.
計算機によるシミュレーションなので, これに加えて, $dt$もステップパラメータとして, $dV(t)$に関する式に変形しておく.
$$dV(t) = \frac{RI(t)-V(t)}{CR}dt$$
さて, 発火するためには, 抑制項$-V(t)$が最大値$b$を迎えるまでの間$RI(t)-V(t)$が正でなければならない.
したがって, 発火率が存在する領域は$RI(t)>b$である.
また, 発火率の上限は, 1ステップで増加する膜電位が$dV(t)=b$であるときだろう.そのため, 計算すると, 最大発火率となる$I(t)$は$$I(t)>bC\cdot dt$$の領域であることがわかる.
このときの発火率はクールタイムを含めた$1+t_{cool}$に対して, 1度のパルスを発生させるため$\frac{1}{1+t_{cool}}$となる.

## 結論・今後
入力を直流電流に絞ったうえで積分発火モデル(LIF)の発火率の範囲を調べたところ, $\frac{b}{R}<I(t)<bC \cdot dt$の範囲で, 発火率が$0$から$\frac{1}{1+t_{cool}}$まで単純増加するだろうということがわかった.

今回は何となく思いついたようにやってみたものの, 実際の場面では, 入力が他のニューロンの出力であれば直流ではないし, 単純増加の部分の具体的な関数についてもシミュレーションする余地がある. 今後も筆者の興味が続けば研究材料としてみていきたい

## 最後に
某収容所による矯正の名残か, 普通に書いたつもりがレポート感あふれる書体になってしまいました.
適当に書き納めしとこうと思い書いてみました. ありがとうございました.
KeycloakとGrowiの連携を自動化

## 目的
DockerでKeycloakとGrowiを立ち上げ、SAML認証のお互いの設定をスクリプトで行う。
ソースコードは[https://github.com/kaiseimima/keycloak-growi.git](https://github.com/kaiseimima/keycloak-growi.git)で公開しています。


## KeycloakとGrowiの初期設定


`paramas.json`に初期設定を書き込んでください。

`python-app/`にある`setjson.py`を実行することでgrowi, keycloakの初期設定やSAML設定に関する情報をjsonファイルに自動的に書き込んでくれます。
```params.json
{
    "realmName": "test04",
    "keycloakUsername": "ssouser",
    "keycloakPassword": "ssopass",
    "keycloakUrl": "https://keycloak_mima.com",
    "growiUrl": "https://growimima.com",
    "growiUsername": "username",
    "growiName": "name",
    "growiEmail": "email@gmail.com",
    "growiPassword": "password"
}
```
### keycloakに関する設定 ###
* realmName

にkeycloakに作成するRealmの名前を設定してください。
* keycloakUsername
* keucloakPassword

にそれぞれSAML認証のためのusernameとpasswordをそれぞれ設定してください。
* keycloakUrl

にkeycloakのurlを設定してください。


### growiに関する設定 ###
* growiUrl

にgrowiのurlを設定してください。
* growiUsername
* growiName
* growiEmail
* growiPassword

ではgrowiのアカウントのusername, name, emailアドレス, passwordをそれぞれ設定してください。


## pythonの設定と実行方法
pythonはDockerの公式イメージのpython3を使用しました。

`python-app/`の`Dockerfile`でpython3をコンテナ内で立ち上げ、`requirements.txt`で必要ないくつかのpythonのライブラリをインストールしています。

ターミナルでコンテナを立ち上げて、pythonが立ち上がっているコンテナ(ここではpython-app)へ`docker-compose exec python-app bash`で入って以下のようにpythonを実行してください。
```bash
docker-compose up -d
docker-compose exec python-app bash

python setjson.py
python setKeycloak.py 
python setGrowi.py
```
### 注意
GrowiでSAMLの設定をする際に、Keycloakのrealmに関するX.509証明書が必要になるので先に、KeycloakのSAML設定を行ってください。(python setKeycloak.pyをおこなってから、python setGrowi.pyをおこなってください。)

### setKeycloak.py

* `setKeycloak.py`のkeycloak_urlはdocker-compose.ymlでkeycloakを立ち上げているサービス名、ポート番号で設定してください。(ここでは、サービス名は'keyclaok', ポート番号は'8080')
* `create_realm()`, `create_client()`, `create_users()`関数でrealm, client, userを設定しています。
また、`get_cert()`, `write_realm_to_growijson(realmName)`でGrowiのSAML認証の設定に必要な設定を`growi/`下のjsonファイルに書き込むので、先にこちらを実行してください。


### setGrowi.py
* `setGrowi.py`でも同じように、以下のurlはdocker-compose.ymlでgrowiを立ち上げているサービス名、ポート番号で設定してください(ここでは、サービス名は'app', ポート番号は'3000')
* 初めて`setGrowi.py`を実行する際にはログインをする`set_login()`を実行する必要はありません。`set_install()`で初期設定が行われます。2回目からは`set_install()`ではなく`set_login()`でログインしてください。


# 参考

KeycloakとGrowiの設定は次の記事を参考にさせていただきました。[シングルサインオンサービスKeycloakとWikiシステムGrowiを連携する](https://qiita.com/myoshimi/items/f26cf3f179602a12a5ac)

ありがとうございます。
ChatGPTにExcelVBAを習ったら試行錯誤がぱねェ（テキストの読み込み他

# 要約
ChatGPTにExcelVBAを習った。
テキストファイルの読み込みについて３つ方法を習った。最後の１個がうまくいった。
# 詳細
最初習ったのはInput$関数というのを使う。
```
    filePath = "C:\foo\bar.txt"
    fileNumber = FreeFile
    Open filePath For Input As fileNumber
    fileContent = Input$(LOF(fileNumber), fileNumber)
    Close fileNumber
```

しかしこれだとInput$関数において
```
　Run-time error '62':
  input past end of file
```
というエラーになる。
fileContentは""、LOF(fileNumber)はbar.txtの正しいファイルサイズ）。

次に習ったのはLine Inputを使う。
```
    filePath = "C:\foo\bar.txt"
    fileNumber = FreeFile
    Open filePath For Input As fileNumber
    Do Until EOF(fileNumber)
        Line Input #fileNumber, fileContent
    Loop
    Close fileNumber
```
正常に実行されるが、fileContentは累積されず、"The End"（foo.txtの末尾行）になる。

最後にバイナリーモードでOpenし、Getというのを使った。
```
    filePath = "C:\foo\bar.txt"
    fileNumber = FreeFile
    Open filePath For Binary As fileNumber
    fileContent = Space$(LOF(fileNumber))
    Get #fileNumber, , fileContent
    Close fileNumber
```
これだと上手く言った。
なんでやねん。

> VBAのファイル読み込み処理は、環境やバージョンの差異、ファイルのエンコーディングなどにより挙動が変わることがあります。バイナリモードで読み込むことで、テキストファイルのエンコーディングに関わらず安定してファイルを読み込むことができる場合があります。

へぇー。
# 余談
もう１個、VBAモジュールを取得するということをやっていて、

```
Set vbComponent = destinationWorkbook.VBProject.VBComponents.Add(vbext_ct_StdModule)
```
だとうまくいかない。
自分でウォッチ式を使って調べたら、Microsoft Excel VBAによって事前定義されているべきvbext_ct_StdModuleがemptyになっていたので、
```
        Set vbComponent = destinationWorkbook.VBProject.VBComponents.Add(1)
```
と数字リテラル1を指定したら動作した。

> 大変申し訳ありません。VBAエディタのバージョンや環境によって、vbext_ct_StdModule が正常に認識されないことがあります。ご指摘いただき、ありがとうございます。
> 
> おっしゃる通り、vbext_ct_StdModule が定義されていない場合は、数値リテラルを使用してモジュールを追加する方法が有効です。以下がその修正版のコードです。

だって。
# 感想
思ったより時間がかかってしまったが、懲りずにあれこれ方法を考えてくれるのはいいやつだなと思った。

***（終わり）***
【初心者向け】Cisco Packet Tracerで実施したネットワーク構築の手順を、一目でわかるようにまとめてみました

### ①複数のLANを跨いだルーティング 
![複数のLANを跨いだルーティング.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/8c9fc722-3ad7-8102-168b-08feface24e0.png)

### ②DHCPサーバ構築 
![DHCPサーバ構築.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/5526d5c8-33db-be5c-6750-176319a8fdb4.png)

### ③ファイアウォールの設定 
![アクセス制御の設定： ファイアウォール編.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/47efecf3-38ed-6496-1126-4a20cebd874e.png)

### ④アクセスリストの設定
![アクセス制御の設定： ACL編.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/951bdd72-19fe-d272-75d6-7063ea6a2501.png)

### ⑤SSH接続の設定 
![SSH接続の設定.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/8c3b3104-2bd9-d44c-77b2-1fd8d754db04.png)

### ⑥VLAN構築
![VLAN構築.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3620644/583580e7-7fc3-49bc-c960-36c70849c717.png)
Docker で Apache を 利用する

# はじめに
Dockerを触り始めたころから、基本的にWebサーバーはNginx一択でしたので、触ってみました＆書き残しメモ。


# 今後の課題
- 開発用(http)での構築方法となっています(オレオレ認証でのhttps設定方法は[こちら](https://qiita.com/naozo-se/items/1b29e69249e306fa1d6f))
- rootless ですが、設定ユーザーとしている `www-data` をホスト側の実行ユーザーと同じGID,UIDにするように設定しています


# 確認環境
- WSL2(Ubuntu22.04.3 LTS)
- Docker (24.0.6)
- Docker Compose (2.4.1)
- Apache (2.4.58)

# フォルダ構成

```
[projectfolder]
 ├─ compose.yml
 ├─ Dockerfile
 ├─ conf
 │    └─ (コンテナからコピー)
 ├─ logs
 │    └─ (アクセスログを格納)
 └─ htdocs
    └─ index.html (表示確認サンプル)
```

## 設定ファイルをコンテナからコピーする
nginxみたいに、confファイルを指定のフォルダ以下に置いたら勝手に読み込んでくれる様な構成ではないため、以下の方法でコピーする
```shell:shell実行
# プロジェクトフォルダに移動
cd {projectfolder}
# コンテナを仮立ち上げ
docker run --name httpd-temp -itd httpd:2.4.58
# 設定ファイルをコピー
docker cp httpd-temp:/usr/local/apache2/conf conf
# 仮コンテナを削除
docker rm -f httpd-temp
```
※コンテナ構築時に自動でボリューム設定しているフォルダを作成する形にすると、root権限になる可能性があるため、他のフォルダも事前に作成する(この構成だと、logフォルダの作成を忘れがちなため、注意する)

# コード
```yaml:compose.yml
services:
  apache:
    build:
      context: .
    ports:
      # ポート設定
      - '80:80'
    environment:
      # タイムゾーン
      - TZ=Asia/Tokyo
    volumes:
      # ドキュメントルート
      - ./htdocs:/usr/local/apache2/htdocs
      # 設定ファイル
      - ./conf:/usr/local/apache2/conf
      # アクセスログ
      - ./logs/:/usr/local/apache2/logs
```

```Dockerfile:Dockerfile
# Apache を指定
FROM httpd:2.4.58

# GID,UID変更(ログフォルダのマウントのため、アプリケーションの実行ユーザーに変更)
RUN groupmod -g 1000 www-data
RUN usermod -u 1000 www-data

# pidのデフォルト設定場所の所有者を変更
RUN chown -R www-data:www-data /usr/local/apache2/logs

# ユーザー変更
USER www-data
```

```diff:conf/httpd.conf ※差分のみ
-    #CustomLog "logs/access_log" combined
+    CustomLog "logs/access_log" combined
```

```html:index.html（確認用ですのでお好きに）
<html>
    <h1>IT'S WORKS!!</h1>
</html>
```



# 立ち上げコマンド
```shell:shell実行
docker compose up -d
```
※立ち上げ後、ブラウザから `localhost` に接続して、`index.html` の内容が表示されていたら、OKです

# 注意点
- `conf/extra/` 以下の設定ファイルは、デフォルトではほとんど読み込まれていません (`conf/original/` も含め不要であれば削除することを推奨します)
~~- ログは `docker compose logs -f --tail=999` とかでタイムリーに見たり、`docker inspect {コンテナ名}| grep 'LogPath'` で確認することはできます~~
- ログは `./logs/access_log` のファイルに出力されます
- GID,UID の 1000 については、アプリケーションの実行ユーザーに合わせてください
  ※idコマンド等で確認してください

# 最後に
~~Nginxも含めですが、リバースプロキシとか、SSLとかも色々設定方法も記事にしたい…。~~
[SSL](https://qiita.com/naozo-se/items/1b29e69249e306fa1d6f)（オレオレ認証ですが）とか、[リバースプロキシ](https://qiita.com/naozo-se/items/526305342dd97f69d7d6)(uWSGIで若干わかりにくいですが)もありますので、参考にしてください。
wslでelixir その123

# 概要
wsl(wsl2じゃない)で、elixirやってみた。
Livebookでectoを使わないで、データを永続化したい。
でも、datatableは、使いたい。

# 方針
- ファイルを使う。
- jasonを使う。
- マップのリスト使う。
- saveとloadを実装。

# 写真

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/8996ce8e-8aec-2214-3200-c944970125b4.png)

# セットアップ

```
Mix.install([
  {:jason, "~> 1.4"},
  {:kino, "~> 0.10.0"}
])
```

# サンプルコード

```


defmodule Ecto2 do
	def insert(db, v) do
		db = db ++ [v]
	end
	def update(db, v) do
		i = Enum.filter_map(Enum.with_index(db), fn {x, _} -> 
			x.id == v.id 
		end, fn {_, i} -> 
			i 
		end)
		|> Enum.at(0)
		db = List.replace_at(db, i, v)
	end
	def delete(db, v) do
		db = List.delete(db, v)
	end
	def print(db) do
		Enum.map(db, fn x -> 
			[ x.id,  x.name]
		end)
		|>IO.inspect
	end
  def load(db) do
    File.read!("db.json")
	  |> Jason.decode!(keys: :atoms)
  end
  def save(db) do
    json = Jason.encode!(db)
    File.write!("db.json", json)
  end
end
now = NaiveDateTime.utc_now()
	|> NaiveDateTime.truncate(:second)
	
db = [
  %{
	id: 1,
	name: "ryu",
	age: 10,
	gaku: "s",
	inserted_at: ~N[2023-10-31 05:35:23],
	updated_at: ~N[2023-11-30 05:35:37]
  },
  %{
	id: 2,
	name: "ryo",
	age: 20,
	gaku: "s",
	inserted_at: ~N[2023-10-31 05:35:23],
	updated_at: ~N[2023-11-30 05:35:37]
  },
  %{
	id: 3,
	name: "alice",
	age: 20,
	gaku: "s",
	inserted_at: ~N[2023-10-31 05:35:23],
	updated_at: ~N[2023-11-30 05:35:37]
  },
  %{
	id: 4,
	name: "kent",
	age: 30,
	gaku: "s",
	inserted_at: ~N[2023-10-31 05:35:23],
	updated_at: ~N[2023-11-30 05:35:37]
  }
]
Ecto2.save(db)
db = Ecto2.load(db)
Kino.DataTable.new(db)

Ecto2.print(db)
db = Ecto2.insert(db,   %{
	id: 5,
	name: "kent",
	age: 30,
	gaku: "s",
	inserted_at: now,
	updated_at: now
  }
)
Ecto2.print(db)


Kino.DataTable.new(db)

db = Ecto2.delete(db,   %{
	id: 5,
	name: "kent",
	age: 30,
	gaku: "s",
	inserted_at: now,
	updated_at: now
  }
)
Ecto2.print(db)
Kino.DataTable.new(db)
db = Ecto2.update(db,   %{
	id: 1,
	name: "yoko",
	age: 30,
	gaku: "s",
	inserted_at: now,
	updated_at: now
  }
)
Ecto2.print(db)
Kino.DataTable.new(db)
```

以上