OmniAICreator/Qiita-1.07M huggingface dataset:
CIを回してブラウズ上で完結するLaTeXの書き方

## 前提条件
- GitHubアカウントをお持ちであること。

## 環境構築手順

### リポジトリの作成
1. [テンプレートリポジトリ](https://github.com/TakanoTaiga/temp_latex_report)にアクセスします。
2. リポジトリの作成方法は[GitHubドキュメント](https://docs.github.com/ja/repositories/creating-and-managing-repositories/creating-a-repository-from-a-template#creating-a-repository-from-a-template)を参照し、テンプレートから新しいリポジトリを作成してください。

### ワークフロー権限の設定
1. 作成したリポジトリに移動し、`Settings` > `Actions` > `General` > `Workflow permissions`の順にアクセスします。
2. `Read and write permissions`にチェックを入れ、`Save`ボタンをクリックします。

    画像参考：`"Workflow permissions"`の設定画面 
    ![Workflow Permissions Image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/899689/0e41086b-e91e-2e2f-2020-68b0f75f7eaf.png)

### 動作確認
1. 最初のコミット後、CI (Continuous Integration) が自動的に起動し、エラーが生じる可能性があります。`Actions`タブを選択し、`Initial commit`の詳細ページに進んでください。
2. `Re-run failed jobs`をクリックします。
   
   ![Re-run Failed Jobs](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/899689/6331aa5c-9334-f06b-f13f-8215e4715297.png)

3. 表示されたポップアップにて、`Re-run jobs`ボタンをクリックし、CIを再実行します。

    ![Re-run Jobs](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/899689/20a84cca-5d70-62eb-f8e0-cf821ad533cd.png)

4. 数秒後、ビルドが完了し、`pdf`ブランチが生成され、`demo.pdf`ファイルが確認できるです。

    ![Build Completed](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/899689/7764d54e-3b0e-c228-8fbf-30f888ce8a06.png)


## ファイルの追加

新しいファイルの追加やファイル名の変更を行いたい場合、`.github/workflows/build.yml`を編集する必要があります。

```yaml
name: 'Build LaTex Document'
on:
  push:
    branches: [ main ]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout
        uses: actions/checkout@v4
      - uses: actions/cache@v3
        name: Tectonic Cache
        with:
          path: ~/.cache/Tectonic
          key: ${{ runner.os }}-tectonic-${{ hashFiles('**/*.tex') }}
          restore-keys: |
            ${{ runner.os }}-tectonic-
      - uses: wtfjoke/setup-tectonic@v3
        with:
          github-token: ${{ secrets.GITHUB_TOKEN }}

      - name: make build workspace
        run: mkdir ./build

      - name: Run Tectonic 1
        run: tectonic <この部分のpathを変更する> --outdir ./build
      - name: Run Tectonic 2
        run: tectonic <n個あっても良い。ただファイル名は変える> --outdir ./build
      - name: Run Tectonic 3
        run: tectonic ./example/hello.tex --outdir ./build

      - name: Update
        uses: s0/git-publish-subdir-action@develop
        env:
          REPO: self
          BRANCH: pdf
          FOLDER: build
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
```

### 変更のポイント: 
ファイルパスのみを変更してください。`run: tectonic`や`--outdir ./build`の部分はそのまま保持してください。例えば：
```
- name: Run Tectonic 3
        run: tectonic ./example/hello.tex --outdir ./build
```

## ファイルの編集

こちらの[リンク](https://docs.github.com/ja/codespaces/the-githubdev-web-based-editor#githubdev-%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E3%83%BC%E3%82%92%E9%96%8B%E3%81%8F)にある方法でWebブラウザ上での編集が簡単に行うことができます。

## 最後に
コミットすれば自動でpdfが生成されます。Pull Request対応用のpr.ymlもあるのmainをプロテクトして使いたい人はそちらをルールに追加してご使用ください。何かトラブルがあればIssueを飛ばすかXのDMにでも投げていただけるとありがたいです。
良いLaTeXライフを。
ItemsRepeaterを末尾までスクロールすると震える問題

### 前提条件

* Microsoft.NETCore.UniversalWindowsPlatform 6.2.14
* Microsoft.UI.Xaml 2.8.5
* ターゲットバージョン Windows 11 ビルド 22000
* 最小バージョン Windows 10, version 2004 ビルド 19041
* Visual Studio 17.7.5

### 問題

* ScrollViewer + ItemsRepeaterで構成したリスト表示の末尾部分にスクロールしようとした時に
* 意図せず「スクロールが少し戻る → マウススクロールで進もうとする → スクロールが少し戻る」と動作し
* 末尾にスクロールすることが困難になる

以下、この症状を「スクロールが震える」などと表現します。

### 原因の推測

* ItemsRepeaterに指定される StackLayout などは仮想化をサポートしています。
* 仮想化は、表示範囲にある項目のみをインスタンス化し、表示範囲外に行った要素を使い回すことで少ないリソースで大きなリスト構造を表示することができます。
* 要素をインスタンス化する範囲は HorizontalCacheLength 等で管理され、例えば2を指定した場合にはビューポートの2倍分、現在表示している分+200%の範囲をバッファします。

https://learn.microsoft.com/ja-jp/windows/windows-app-sdk/api/winrt/microsoft.ui.xaml.controls.itemsrepeater.horizontalcachelength?view=windows-app-sdk-1.4

これらと実際に見た動作を勘案してスクロールが震える症状の原因を推測すると……

1. マウススクロールによってバッファ表示区間から要素が外れて消される
1. 消された要素の幅に応じてスクロール位置が戻される
1. スクロール位置が戻ることで消した要素が再びバッファ表示区間内に収まってしまい再表示される（この時スクロール位置は変わらず）
1. これらが合わさって末尾にマウススクロール出来ない症状やスクロールが震える症状となって現れる


### 対処法１：バッファ表示区間を拡張する

HorizontalCacheLength="3"とするなどバッファ表示区間を大きくすることで震える症状が現れる確率を低減できました。過大に指定すると仮想化による恩恵は受けられなくなるので注意が必要です。

最適？なLengthは、要素幅の最大サイズとItemRepeaterの表示領域に依存します。

例えば幅の大きな要素がバッファ表示区間から消えた場合、その幅の分だけスクロールが戻るため（震える症状は出ませんが）末尾にスクロールを合わせられない症状は変わらず現れます。

### 対処法２：グループ化せず子アイテムのみで構成する（ネストしている場合）

ネストしたItemsRepeaterを用いて構成することで震える症状が出ている場合は、グループ化解除を検討します。

グループのヘッダーやフッターは子アイテムのグループ内の位置で表示・非表示を判定するようにして子アイテムのみで賄えるようにします。

### 対処法３：ListViewなどに置き換える

ItemsRepeaterの利用を回避することで問題も回避できます。

### 対処法４：VirtualizingLayoutをカスタムしてサイズ計算をマニュアルで行う（未検証）

https://learn.microsoft.com/ja-jp/windows/apps/design/layout/attached-layouts#virtualizing-layouts
Dataform の Unit test で UNION ALL を書くのが辛くて JavaScript の wrapper を書いた話


## はじめに

Dataform には unit test を記述出来ます。
ただし、テストに用いるデータは SQL で書く必要があり冗長なものになりがちです。
Dataform　は　JavaScript を記述、読込みできるので wrapper を書きました。

## Dataform の Unit test について

Dataform の Unit test はこのように記述できます。
`example_originals` table からデータを参照する `example.sqlx` があったとします。

```sqlx:foo/example.sqlx
config {
  type: "view",
  name: "example_tables"
}

SELECT
  id,
  title
FROM
  ${ref("example_originals")}
```

この `example.sqlx` に対する Unit test を用意すると以下のようになります。

```sqlx:foo/test_example.sqlx
config {
  type: "test",
  dataset: "example_tables"
}

SELECT
  1 AS id,
  "title1" AS title
UNION ALL
SELECT
  2 AS id,
  "title2" AS title
UNION ALL
SELECT
  3 AS id,
  "title3" AS title

input "example_originals" {
  SELECT
    1 AS id,
    "title1" AS title
  UNION ALL
  SELECT
    2 AS id,
    "title2" AS title
  UNION ALL
  SELECT
    3 AS id,
    "title3" AS title
}
```

test データを用意したいだけですが、 `UNION ALL` を何度も記載する必要があります。
面倒ですし、可読性も悪い状態になってしまいます。

苦し紛れではありますが、JavaScript を用いて `UNION ALL` のラッパー関数を作成しました。

## JavaScript の wrapper を書いた

Dataform は `includes` 以下の ディレクトリに JavaScript ファイルを置くことで、
SQLX 内から JavaScript に記載した処理を呼び出すことができます。

作成した JavaScript はこちらです。
渡されたデータを `UNION ALL` で `join` するだけの簡単な処理です。

:::note warn
エスケープ処理等いくつか省略しています。
:::

```js:includes/sql.js
function build(data) {
  if (data.length === 0) {
    return "";
  }

  const keys = Object.keys(data[0]);
  return data.map((item) => {
    const values = keys.map((key) => {
      if (typeof item[key] !== "string") {
        return `${item[key]} AS ${key}`;
      }
      return `'${item[key]}' AS ${key}`;
    });

    return `SELECT ${values.join(", ")}`;
  }).join(" UNION ALL ");
}

module.exports = {
  build,
};
```

SQLX ファイルから処理を呼び出す場合は以下のように記載します。

```sqlx:foo/bar.sqlx
${
  sql.build([
    { id: 1, title: "title1" },
    { id: 2, title: "title2" }
  ])
}
```

すると以下のような SQL に変換します。

```sql
SELECT
  1 as id,
  "title1" as title
UNION ALL
SELECT
  2 as id,
  "title2" as title
```

## 最後に

今回記事を書くために記載したテストデータの件数は3件程でした。
Dataform で処理するデータ次第ですが、テストデータの件数はもっと多くなるはず。

ちょっとした JavaScript を書くだけで、すこしメンテナンスしやすなります。
いい塩梅が求められる部分なので、やり過ぎは禁物です。

## References

https://docs.dataform.co/guides/tests

https://cloud.google.com/blog/ja/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs?hl=ja

https://cloud.google.com/blog/topics/data-warehousing/learn-how-to-use-the-dataform-cli-tool-to-unit-test-udfs/
Rails DeviseのReply-Toを消す

# DeviseのデフォルトだとFromがReply-Toになる
デフォルト設定のままだとReply-ToにFromのアドレスが入ってしまう。
邪魔だなあ。どうにかしたいなあ。そんなあなたへの解です。

![スクリーンショット_2023-09-06_16_39_48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147005/795c839c-4a46-244e-c55f-c12072ab89d0.png)

この状態のinitializerはこちら

```config/initializers/devise.rb
Devise.setup do |config|
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  google = Rails.application.secrets.google
  config.omniauth :google_oauth2, google[:client_id], google[:client_secret], { name: :google, scope: %w[email profile] }
  config.mailer_sender = '"TEST" <noreply@test.com>'
  config.confirm_within = 1.day
end
```

# 対応

`` Devise::Mailer.default reply_to: nil``を追記するだけ。

```config/initializers/devise.rb
Devise.setup do |config|
  # ==> OmniAuth
  # Add a new OmniAuth provider. Check the wiki for more information on setting
  # up on your models and hooks.
  google = Rails.application.secrets.google
  config.omniauth :google_oauth2, google[:client_id], google[:client_secret], { name: :google, scope: %w[email profile] }
  Devise::Mailer.default reply_to: nil
  Devise::Mailer.default from: '"TEST" <noreply@test.com>'
  config.confirm_within = 1.day
end
```

![スクリーンショット_2023-09-06_16_41_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147005/5926ea93-83be-4ae8-e5bd-97523b9d7378.png)

一行追加、それだけ。。。
なぜハッシュ値は元の値を復元できないのか、SHA-256を実装してみる

# はじめに
ハッシュ関数はデータの整合性確認や暗号学的な用途でよく使用されます。この記事では、ハッシュ関数の中でもよく使われるSHA-256を自分で実装しつつ、なぜ元の値を復元できない（不可逆性）の性質を持つのか確認します。

結論はハッシュ関数の不可逆性は、情報の喪失により実現されています。

また、今回sha256を実装したRustのコードは以下です。
https://github.com/akira-19/algorithms_rust/tree/main/sha-256

# SHA-256のフロー
不可逆性がわかるところまでのSHA-256のフローは以下のようになっています。

"msg"という文字列をハッシュ化します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/621c3344-de08-1907-f8f1-302ef331852d.png)

1. まずmsgという文字列を文字コードに置き換えます。（16進数表記）
2. 次に、メッセージを64バイトの1つのまとまりにします。この際に、元のメッセージのすぐ後ろに0x80を追加し、64バイトの最後の8バイトには元のメッセージのバイナリでの長さを追加します。つまり、msgは3バイトなので、バイナリでは長さは24（bit）になります。16進数表記では18となります。追加した0x80とメッセージの長さの間は全て0でパディングします。

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/947f8b24-6c19-0e83-1109-f0961357aaf9.png)

3. 64バイトのまとまりを、4バイトずつ分けます（表記が16進数から10進数に変わっているので注意して下さい）。つまり、最初の6d 73 67 80がまとまって、6d736780になります（こちら10進数に直すと1836279680となります）。

4. Wという値を計算するのですが、この中で不可逆な処理をしています。以下Rustでのサンプルコードです（処理は一部分のみ）。

   ```rust
   fn calc_w(msg: [u32; 16]) -> [u32; 64] {
       let mut w = vec![0; 64];

       for i in 0..16 {
           w[i] = msg[i];
       }
   
       for i in 16..64 {
        w[i] = lower_sigma_1(w[i - 2])
            .wrapping_add(w[i - 7])
            .wrapping_add(lower_sigma_0(w[i - 15]))
            .wrapping_add(w[i - 16]);
       }
   
       w
   }
   
   fn lower_sigma_1(x: u32) -> u32 {
       rotr(x, 17) ^ rotr(x, 19) ^ shr(x, 10)
   }

   fn rotr(x: u32, n: u32) -> u32 {
    (x >> n) | (x << (32 - n))
   }

   fn shr(x: u32, n: u32) -> u32 {
     x >> n
   }
   ```


   `calc_w`の中で`lower_sigma_1`という関数を呼んでおり、さらにその中で`rotr`という関数を呼んでいます。こちらを図解します。

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/d311da0c-6c61-e5b2-e9d5-372d6d0b2db1.png)


5. ここでは例としてx=31, n=3とします。31は2進数で11111です。xもnも符号なしの32bit整数ですので、データ上は000..000011111（0が27個）となります。

   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312001/87e4b4e5-df11-b47c-4789-94825f08030c.png)

6. `x >> n`はxをnだけ右にビットシフトする処理ですので、左側に000を追加して、後ろの111を削除します。
7. 同様に`x << (32-n)`はxを右に32-3=29個だけシフトさせますので、最初の3つは111となり、あとは0になります。
8. 最後に6と7のビット論理和をとるので、111000...0011のようになります。

~~ポイントは6,7,8の処理です。例えば6の処理で`x=30`、`n=3`とします。すると、000..0011110を右に3つシフトするので、000..011となり、`x=31`の時と同じ返り値になります。~~

~~今回の例では3ビット分の情報が失われているので、2進数で000~111（10進数で0~7）までの情報が失われているため、この処理だけ見てもxが24~31の間のどの数値か分からなくなります。~~

上記のrotrだけだと、右側にシフトして喪失した分は左側のシフトで残っているので情報喪失していないですね。（右にシフトして消えた分のビットが左側に戻ってくる）

情報が喪失するのは、shrでした。6の処理だけを行なっているので、右側にシフトして消えた分は元には戻せません。

また、`lower_sigma_1`の中で、`rotr(x, 17) ^ rotr(x, 19)`という処理をしていますが、これも情報を喪失していますね。すごい簡略化した例で説明するとこの処理は、10000を右に1ビットずらしたものと2ビットずらしたものの論理積をとっているようなもので、`01000 ^ 00100 = 00000`となります。これだと、元の値が00000だとしても同じ結果になります。

このような処理を繰り返すことで、元の値を復元できなくさせます。

# まとめ
ハッシュ値は元の値を取得するのが難しいのではなく、原理的にはアルゴリズムで元の値を得るのは不可能ということがわかりました。もちろん、sha256の出力は32バイト（256ビット）なので、32バイト以内の入力であれば無限の計算能力があるコンピュータがあれば、2^256通りの入力を確かめることで、元の値を得ることはできます。（入力と出力が32バイト内で全て1対1対応する前提です）

# 参考文献
- https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
- https://zenn.dev/kota_yata/articles/ce45080b2e8cae
【Flutter初学者向け】printでデバック時のログ、辿れちゃいます...!

こんにちは！
最近寒くなってきたので、朝はなかなか布団から出られません、、、
冬が近づいている証拠ですね...!

さて今回は、printを使ってデバック時のログを確認する方法やメリットを紹介したいと思います！
最後まで読んでいただけたら、嬉しいです！

## 1.そもそもデバックログの重要性って！？
### ・問題の特定
デバッグログはアプリケーションの実行中に何が起こっているかを把握するための窓口です。コードのどの部分でエラーが発生しているかを特定するのに役立ちます。

### ・バグの修正
バグが発生したとき、デバッグログを使用してその原因を特定できます。ログには変数の値やイベントのタイムスタンプなどが含まれ、バグの再現や修正に役立ちます。

### ・コードの検証
デバッグログを使用してコードの正確性を確認できます。変数の値や制御フローを確認し、期待どおりに動作するかどうかを検証できます。

### ・テストと品質保証
デバッグログはテストと品質保証のプロセスで重要な役割を果たします。テストケースが期待どおりに動作していることを確認するためにログを使用できます。

### ・学習と成長
デバッグログは開発者自身の学習と成長にも役立ちます。問題の解決プロセスやコードの理解を深めるのに役立つ情報を提供します。




## 2.print関数の基本的な使い方とは。。。
### 
```php
print("みなさん、こんにちわ");
```
![スクリーンショット 2023-10-13 16.51.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3524127/7844bc9f-4bee-df82-d2e7-56e7da796f46.png)

上記のコードは "みなさん、こんにちわ" というテキストをコンソールに表示します。単なるテキストの表示だけでなく、変数の内容や計算結果なども表示することができます。

## 3.ログレベルって！？
下記の異なるログレベルは、アプリケーションのトラブルシューティングや監視、品質管理、バグの特定、性能の最適化など、開発プロセスの異なる側面で役立ちます。ログの適切なレベルを選択し、メッセージを適切に記録することで、アプリケーションの品質を向上させるのに役立ちます。

### デバッグ (Debug)
デバッグログは、アプリケーションの動作や特定のステップの詳細情報を提供します。
通常、デバッグ目的でコードに挿入され、デバッグ中にのみ表示されることがあります。
一般的なログ出力は含みません。代わりに、変数の値、関数の呼び出し、条件分岐などの詳細情報が含まれます。

### 情報 (Info):
情報ログは、アプリケーションが正常に実行されていることを示すために使用されます。
一般的に、アプリケーションの主要なマイルストーン、特定の操作の完了、リソースのロードなどの情報を記録します。

### 警告 (Warning)
警告ログは、問題やエラーが発生しそうであるが、まだ発生していない場合に使用されます。
これは潜在的な問題を特定し、事前に注意を引きつけるのに役立ちます。アプリケーションは正常に動作していますが、問題の兆候がある場合に警告を記録します。

### エラー (Error)
エラーログは、アプリケーションの実行中に問題やエラーが発生したことを示します。
一般的に、クラッシュ、例外、予期しないエラー条件など、重要な問題に関連する情報を提供します。


## 4.最後に
本日も最後まで見ていただきありがとうございました！
では、また次の記事で〜！
【MySQL】エラー「Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded...」の原因

# 概要

MySQLデータベースでストアドプロシージャを実行したら、以下のエラーが発生しました。

```
ERROR 1456 (HY000) at line 1: Recursive limit 0 (as set by the max_sp_recursion_depth variable) was exceeded for routine TestProcedure01
```

# 原因と解決方法
`Recursive limit 0`は再帰呼び出しの制限を示しています。
（`ERROR 1456`は再帰呼び出しの制限に関連するエラーらしい）

再帰？と思って該当のプロシージャをよく見ると、以下がエラーの原因でした。

```sql
  -- 次のプロシージャを呼び出す
  CALL TestProcedure01();
```

`TestProcedure01`が終わったら`TestProcedure02`を呼び出すようにしていたのですが、誤って、ここを自身のプロシージャ名にしていました...。つまり、自身を再帰的に呼び出していたことが原因でこのエラーが発生したのです。

ということで、上記を修正したらエラーは無くなりました。

# 備考
大量のテーブルを一つのプロシージャで削除しようとすると、大規模なトランザクションとなり、データベースに対するロックが長時間続く可能性があり、パフォーマンスに問題を引き起こすことがあるよう。
そんな時、プロシージャを複数のステップに分割すると良い（もちろん、CPU、メモリ、ストレージなどのスペックにもよる）。
MySQLのサポート期限


* (Extended Support Ends = 事実上のEOL)
  * MySQL 5.7 2023年10月21日 (GA:2015年10月21日から8年後)
  * MySQL 8.0 2026年4月19日 (GA:2018年4月19日から8年後)

https://www.oracle.com/us/assets/lifetime-support-technology-069183.pdf
> ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/109904/b370ba73-6bcc-7dff-aed9-a2d86004a0b7.png)

# 結果

* https://www.mysql.com/support/eol-notice.html
  * (機械翻訳)
    > 2023年10月25日
    > MySQL 5.7は、Oracle Lifetime Sustaining Supportの対象となります。

# 情報源

* MySQL :: MySQL テクニカル・サポート
https://www.mysql.com/jp/support/
  > * MySQL Premier Support
正式(GA)リリースより5年間、MySQLメンテナンス・リリース、アップデート、バグ修正（エラー修正)およびセキュリティ情報を提供します。
  > * MySQL Extended Support
Premier Support期間エラー修正を含む、Premier Support期間終了後3年間、特定のMySQLリリースに対する追加サポートを提供します。MySQLメンテナンス・リリース、アップデート、バグ修正（エラー修正)およびセキュリティ情報を提供します。
  > * MySQL Sustaining Support
Premier Support 期間終了後の任意の期間、2010年11月１日以降のPremier Support対象のすべてのMySQLリリースについて提供します。サポート・エンジニアからのサポートを受けることができます。新規リリース、新規バグ修正（新規案件に対するエラー修正）、新規アップデートを **【含みません】**。既存のアップデート、修正、セキュリティ情報のみ提供します。
* https://www.oracle.com/jp/a/ocom/docs/software-technical-support-policies-079764-ja.pdf
  * > 特定のプログラム・リリース向けのPremier Support は、後述の特例に定める場合を除き、ライフタイム・サポートの対象範囲に関するドキュメント
に記載の通り、当該オラクル・プログラムのリリースの一般提供開始（GA）日から 5年間ご利用になれます。
* https://ja.wikipedia.org/wiki/MySQL#歴史
  * > 2015年10月21日 - Version 5.7 プロダクションリリース（5.7.9よりGA）。
2018年4月19日 - Version 8.0 プロダクションリリース（8.0.11よりGA）
* MySQL :: MySQL Product Support EOL Announcements（MySQL 製品サポートのサポート終了のお知らせ）
https://www.mysql.com/jp/support/eol-notice.html

# 参考

* MySQLのサポート期間 (EOL) – Kenchant
https://senooken.jp/post/2020/09/06/

# 雑感

サポート終了期限はわかるけど、公式の情報源を記載した記事があまり見当たらなかったため記載しました。
[vite] プロジェクトの立ち上げたら「Cannot find module '...' Did you mean to set the 'moduleResolution' option to 'node' ...」が出てきてしまう件について

## 始めに
フロントエンドの勉強中にviteを使ってなんか作ってみよーと思ったのが、ことの発端です。
プロジェクトを立ち上げてファイルを開いてみるとタイトルにあるようなエラー(?)が出てきたので、
対処してみました。

## 結論
プロジェクトディレクトリ直下の`tsconfig.json`と`tsconfig.node.json`ファイルを以下のように変更するだけ！

```json
/* tsconfig.jsonファイルにて */

"moduleResolution": "node", /* ←変更 */
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",

……………

/* tsconfig.node.jsonファイルにて */

{
  "compilerOptions": {
    "composite": true,
    "skipLibCheck": true,
    "module": "ESNext",
    "moduleResolution": "node",　 /* ←変更 */
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}
```

## 追記〜！
プロジェクト立ち上げ後に以下コマンドを打って必要なライブラリをインストールしてもいけた
```
$ yarn
```

## まとめ
簡単ですが、とりあえずこのように記載することでエラー(?)文を出さなくすることはできました。
何か間違い等ありましたら、ご指摘お待ちしています。
特定のディレクトリ配下のリソースのみterraformを実行する方法

# やりたいこと
・AWSリソースのtfファイルを複数のフォルダで分けて格納しているが、あるフォルダ配下のものだけ、terraform planとterraform applyを実行したい

# ディレクトリ構成
ざっくりしたイメージですが、
業務中AWSのリソースが開発環境や本番環境で分かれて、リソースのtfファイルがフォルダ別で格納されている
それぞれのリソースをパス指定で、terraform planとterraform applyを実行したい

```ruby:qiita.rb
root
  ┣━ dev
  ┃  ┗━ env1
  ┃     ┗━ s3
  ┃        ┗━ s3.tf    　
  ┃  ┗━ env2
  ┃     ┗━ s3
  ┃        ┗━ s3.tf 
  ┣━ prod
  ┃  ┗━ env1
  ┃     ┗━ s3
  ┃        ┗━ s3.tf 
```

# やり方

## ①-chdirオプションを入れてください

rootにいる状態で、-chdirオプションを入れてください～

```ruby:terraform plan
terraform -chdir=dev/env1/s3 plan 
```

```ruby:terraform apply
terraform -chdir=dev/env1/s3 apply 
```
terraformコマンドは本来同じフォルダ階層内にあるtfファイルでしか読み込めないが、パス指定して実行するとほかの場所にあるtfファイルに対して実行できるようになった。

特定の場所のみ実行したい場合、-chdirオプションが便利ですね！

## ②さらにシェルスクリプトにする
今回は業務中で、コマンドをシェルスクリプトにして、各場所にあるtfファイルを順番で実行する必要があるので、このようにシェルスクリプトを作った！

```ruby:terraform.sh
terraform -chdir=$1 plan 
terraform -chdir=$1 apply 
```
実行するときは、こんな感じでパスを引数として渡してあげればいい～
```
sh terraform.sh dev/env1/s3
```

# 終わりに
今回は短い記事で終わりました！
terraformもパス指定で特定のフォルダ配下のみ実行できるのを勉強しました！
【SQL】Oracleデータベースにおける未コミットデータとトランザクション隔離レベルのメモ

日本語に苦戦しているSYOです。

このメモは`ChatGPT`を利用して作成されました。

# 事象

最近、``Oracle``データベースを使用して作業しており、管理ツールとして``Oracle SQL Developer``を利用しています。

ある時、``CMD``のセッションでデータベースに``INSERT``操作を実行しました。

驚いたことに、この操作を``CMD``で実行した後、``COMMIT``を行わないにも関わらず、``CMD``からはそのデータを問い合わせることができました。

しかしながら、同じデータは``Oracle SQL Developer``では表示されませんでした。

# 原因

``Oracle``データベースのデフォルト設定では、トランザクション隔離レベルは「``READ COMMITTED``」となっており、これによりトランザクション内で行われた未コミットの変更は他のセッションからは非表示となります。

``INSERT``操作は、``DML``（データ操作言語）の一環として即時にテーブルに反映されます。

このため、``CMD``で``INSERT``を行うと、同一セッション内ではその未コミットデータが参照可能です。

対照的に、``Oracle SQL Developer``のようなクライアントツールでは、異なるトランザクション隔離レベルやセッションの管理手法が採用されていることが多いです。

そのため、``CMD``での未コミットデータが参照できたとしても、``Oracle SQL Developer``のような別のクライアントツールでそのデータが表示されない場合もあります。

# まとめ

データの一貫性を確保するためには、データ変更後は速やかに``COMMIT``を実施することが推奨されます。

未コミットデータを他のセッションと共有したい場合には、トランザクション隔離レベルの調整やその他の手法を検討することが求められますが、これらの変更は慎重に行われるべきです。

# 参考

[ChatGPT](https://chat.openai.com/auth/login)
Javaで「スキャナの入力ストリームにまだ値が残っているか確認する」の動作を確認してみた

# 概要

Javaで「スキャナの入力ストリームにまだ値が残っているか確認する」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/start/scanner/index6.html

# 実装

以下のファイルを作成しました。
```JSample6_5.java
import java.util.Scanner;
import java.util.regex.Pattern;

class JSample6_5{
  public static void main(String[] args){
    String regex = "[A-Z0-9]{2}";
    var p = Pattern.compile(regex);

    Scanner scanner = new Scanner("AB 7B DEB A5");

    while (scanner.hasNext(p)){
      System.out.println(scanner.next());
    }
  }
}
```

以下のコマンドを実行しました。
```
$ javac JSample6_5.java 
$ java JSample6_5 
AB
7B
```

# まとめ

何かの役に立てばと。
XPathでFizzBuzz

皆さんはXPathでFizzBuzzが書けることをご存じですか？

ほとんどの方はXPathと聞くとXMLやHTMLから特定の文字列などを取り出すもの、と認識しているはずです。
それも間違いではないのですが、それしかできないと思うのは完全な間違いです。
実はXPathでもプログラミング言語でよく行われる、 **FizzBuzzができる** のです。
まずはこのXPathコードを見てください。

```xpath
let $data := 1 to 100
return 
for $i in $data
return
if(($i mod 3 = 0) and ($i mod 5 eq 0))
then "fizzbuzz"
else if($i mod 3 = 0) then "fizz"
else if($i mod 5 = 0) then "buzz"
else $i
```

「え？これがXPath？」と、ほとんどの方は驚くでしょう。
残念なことに、よく知られているXPathはXPath1.0で、これはFizzBuzzはできません。

しかし、実は現時点で最新のXPathは **3.1** です。
そう、XPathにも **バージョンがある** のです。

上記コードの実行結果はこちらのコンソールから見れます。

https://inomoto-hironobu.github.io/labo/xpath3/fizzbuzz.xhtml

それでは、どうやって最新のXPathを実行するか、まずはXHTMLを見てみましょう。
```xml
<?xml version="1.0"?>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8"/>
<title>XPathでFizzBuzz</title>
<script src="../../components/lib/SaxonJS2.js"></script>
<script src="fizzbuzz.js"></script>
</head>
<body>
<h1>XPathでFizzBuzz</h1>
<p>XPathでFizzBuzzを実行します。開発者パネルのコンソールを見てください。</p>
</body>
</html>
```
まず、XPath3.1をウェブで実行するにはSaxonJSが必要です。
Saxonicaのウェブサイトからダウンロードします。

https://www.saxonica.com/download/javascript.xml

次にJavaScriptです。

```javascript
const xpath = `
let $data := 1 to 100
return 
for $i in $data
return
if(($i mod 3 = 0) and ($i mod 5 = 0))
then "fizzbuzz"
else if($i mod 3 = 0) then "fizz"
else if($i mod 5 = 0) then "buzz"
else $i
`;

window.addEventListener("load", function() {
	console.log(xpath);
	dataset = SaxonJS.XPath.evaluate(xpath, null);
	console.log(dataset);
});
```
先ほどのXPathをただ実行しているだけです。`SaxonJS.XPath.evaluate(xpath, null)`がSaxonJSでXPathを実行するための基本となります。

いかがでしたか。
XPathは一般のイメージと違って実質プログラミング言語です。
なので、かなり強力な処理ができます。
ぜひとも、どしどし使っていただきたいと思います。
HTMLとWebアプリケーションの基本

JSONを使用することによってDOMを介する必要がなくなる。

Webブラウザ ⇔ Webサーバー ⇔ APサーバー ⇔ DBサーバー

MVCモデル
Model：アプリケーションの扱うデータと業務処理
View：ユーザへの出力処理
Controller：必要な処理をModelとViewに伝える

DBMS：データベース管理システム
Laravel Breeze認証 でログイン後に遷移するページをカスタマイズする

# この記事でやること
Laravel Breezeを使った認証機能で、デフォルトでは登録・ログイン後に`/dashboard`のパスに遷移するよう設定されていますが、それを**指定のパスに遷移するようカスタマイズする方法**を解説します。

## 動作環境
- macOS    13.5.2
- PHP 8.2.11
- Laravel Framework 10.28.0
- Laravel Breeze v1.25.0
- laravel/sail v1.25.0
- Composer 2.6.5

## 本題
登録・ログイン後にどのパスに遷移するかは、`app/Providers/RouteServiceProvider.php`の`HOME変数`で設定されています。
デフォルトでは`/dashboard`となっているので、これを指定したい任意のパスに変更するだけでOKです。
~~~RouteServiceProvider.php
public const HOME = '/home';
~~~
（上記のコードでは、`/home`パスに遷移するように設定しています。）

以上です。

## 参考
https://amzn.asia/d/9oduEHe
Power Automate で メールアドレスからグループID等の情報を取得する方法

# はじめに

Power Automate の 「Office 365 Groups」や「Microsoft Teams」コネクタなど、グループID（Microsoft 365 グループID）を求めるアクションは多いです。

これらのコネクタを利用するうえで、グループのプライマリメールアドレスからグループIDを取得する状況は多いと思います。
簡単に取得が可能ですので記載します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/492ec502-e6df-8473-ffb4-00a110e9b1f1.png)


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/32a67143-5ed6-f9d6-5acb-ef3ca0aa5871.png)


# プライマリメールアドレスからグループIDを取得する方法

「Office 365 Groups」コネクタの「グループの一覧」アクションを利用します。

:::note info
Microsoft 365グループ のみならず、メールが有効なセキュリティグループ や 配布リスト の情報も取得可能です
:::


詳細オプションの「行のフィルター」

```
mail eq '[メールアドレス]'
```

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/6766d641-cbf6-7e11-0228-a6da2c22e3fa.png)


後続の処理では、

「グループ ID」として動的なコンテンツで取得できます。
※配列内の要素を取得するため、参照時には「Apply to each」で囲まれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/611e33a9-fe9b-27e6-9621-5f8edabef800.png)

「Apply to each」で囲まれたくない場合は、以下の値を入力してください。

```
@body('グループの一覧')?['value']?[0]?['id']
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/67d82d29-db92-69d3-347b-0f96877f50e1.png)



# グループID 以外に取得できる項目

グループの種類によりますが、mailNickname や resourceProvisioningOptions など取得でき便利です。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/480768/2e5c0a58-b5b8-e9b9-f639-5b4d0fec3bbe.png)



# まとめ
フロー作成時のご参考になれば幸いです。
【Salesforce】このページを表示できません。権限がないか、ページがモバイルデバイスでサポートされていません。エラーを解決したい

# 問題

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/76f6c799-08f4-b45e-b24f-5ad711d38247.png)

「すべて表示」リンク押下

↓

![スクリーンショット 2023-10-13 160433.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/132c868a-fb59-ed71-cedc-3b73a77e534c.png)

( ﾟДﾟ)

# 解決策

ページレイアウトの関連リストに「活動履歴」を追加する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/ddd7d325-9068-a13c-8778-64164d3f640d.png)

# 参考リンク

[すべての活動を表示する際に「アクセス権がありません」エラー](https://help.salesforce.com/s/articleView?id=000387112&type=1)

# 余談

Classicでしか表示されないっぽい。

Classicの「すべて表示」ボタンがLightningだと「すべて表示」リンクになったっぽい？

それでページレイアウト上にトリガとなる機能が無いからエラーになったのかな？

![スクリーンショット 2023-10-13 164646.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/492812/0c565052-04b5-df3d-fa9d-59c0edb556d7.png)
Spring Thymeleaf css/js No mapping for GET 404 対策メモ

## Spring Thymeleafでstatic以下のcss/jsが読めない場合

resouces/static など固定のパスを読めるようにする

例
```java
@Configuration
public class CustomWebMvcConfigurationSupport extends WebMvcConfigurationSupport {

    private static final String[] CLASSPATH_RESOURCE_LOCATIONS = {
			"classpath:/META-INF/resources/", "classpath:/resources/",
			"classpath:/static/", "classpath:/public/" };

    @Override
	protected void addResourceHandlers(ResourceHandlerRegistry registry) {
		if (!registry.hasMappingForPattern("/webjars/**")) {
			registry.addResourceHandler("/webjars/**")
					.addResourceLocations("classpath:/META-INF/resources/webjars/");
		}
		if (!registry.hasMappingForPattern("/**")) {
			registry.addResourceHandler("/**")
					.addResourceLocations(CLASSPATH_RESOURCE_LOCATIONS);
		}
	}
}
```
Android Studio: println の使い方

## MainActivity.kt に println を挿入

```kt:MainActivity.kt
package com.example.jpeg03

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.ImageView

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        println("*** start ***")

        for (i in 1..5) {
            println(i)
        }
        println("*** end ***")
    }

}
```

## 実行

View -> Tool Windows -> Logcat

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179446/7cdc37dd-acd8-3768-2818-064e9de87dd4.png)

次のようにメッセージが表示されます。

```text
2023-10-13 16:04:15.882  8504-8504  System.out              com.example.jpeg03                   I  *** start ***
2023-10-13 16:04:15.882  8504-8504  System.out              com.example.jpeg03                   I  1
2023-10-13 16:04:15.882  8504-8504  System.out              com.example.jpeg03                   I  2
2023-10-13 16:04:15.883  8504-8504  System.out              com.example.jpeg03                   I  3
2023-10-13 16:04:15.883  8504-8504  System.out              com.example.jpeg03                   I  4
2023-10-13 16:04:15.883  8504-8504  System.out              com.example.jpeg03                   I  5
2023-10-13 16:04:15.883  8504-8504  System.out              com.example.jpeg03                   I  *** end ***
```
MonacaとNCMBで通貨換算アプリを作る（その3: 履歴の一覧表示）

2023年現在、円安が止まりません。そのため、海外旅行していて気になるのは、表記されている金額が円にすると幾らになるかではないでしょうか。昔は気にならなかった金額換算も、今ではびっくりするくらいの金額になっているかも知れません。

スマホアプリとして通貨換算アプリは幾つかありますが、今回はその簡易版をMonacaアプリで開発してみます。換算履歴はNCMBのデータストアに保存し、後で確認できるようにします。

[前回は通貨換算処理と、結果の保存](https://qiita.com/goofmint/items/f7740429904d263289b0)しましたので、今回は履歴を一覧表示する処理を実装していきます。

## コードについて

今回のコードは[currency-converter-monaca](https://github.com/NCMBMania/currency-converter-monaca) にアップロードしてあります。実装時の参考にしてください。

## 履歴表示画面について

この処理は `www/history.html` にて実装します。画面は以下のようになっています。履歴はFramework7のデータテーブルを利用して表示します。

```html
<template>
  <div class="page" data-name="convert">
		<div class="navbar">
			<div class="navbar-bg"></div>
			<div class="navbar-inner sliding">
				<div class="title">変換履歴</div>
			</div>
		</div>
		<div class="page-content">
			<div class="data-table">
				<table>
					<thead>
						<tr>
							<th class="label-cell">元</th>
							<th class="label-cell"></th>
							<th class="label-cell">後</th>
						</tr>
					</thead>
					<tbody>
						${ histories.map(history =>  $h`
							<tr>
								<td class="label-cell">${toEmoji(history.originCurrency)} ${history.originNumber.toLocaleString()}${history.originCurrency}</td>
								<td class="label-cell">→</td>
								<td class="label-cell">${toEmoji(history.targetCurrency)} ${history.targetNumber.toLocaleString()}${history.targetCurrency}</td>
							</tr>
						`)}
					</tbody>
				</table>
			</div>
    </div>
  </div>
</template>
```

## JavaScriptの実装

history.htmlでのJavaScript実装について紹介します。まず、Framework7の作法に沿ってscriptタグを定義します。

```html
<script>
  export default (props, { $on, $store, $update }) => {
		// この中に処理を書きます
    return $render;
  }
</script>
```

### 変数の取得、定義

まず履歴画面で使う変数を取得、定義します。

```js
// ストアから通貨の一覧を取得
const { currencies } = $store.getters;
// 履歴を入れる変数
const histories = [];
```

### 画面を表示した際の処理

履歴画面で、通貨換算画面のように `onMounted` 関数を使うと、マウントされた際の一度しか実行されません。タブを切り替える度に履歴を取得して欲しい時には `page:tabshow` イベントを使います。

```js
// タブを切り替える度に呼び出し
$on('page:tabshow', () => {
	// 履歴を取得する
	getHistory();
});
```

`getHistory` 関数の内容は以下の通りです。取得した結果は、 `histories` 変数に入れています。その後、表示を更新しています。

```js
// NCMBから変換履歴を取得
const getHistory = async () => {
	// Historyクラス（RDBMSでいうテーブル相当）を定義
	const History = ncmb.DataStore('History');
	// 検索実行（今回は最大10件）
	const results = await History
		.order('createDate', true)
		.limit(10)
		.fetchAll();
	// 既存データの削除
	histories.splice(0, histories.length);
	// 結果を履歴に入れる
	results.forEach(result => histories.push(result));
	// 表示更新
	$update();
};
```

これで履歴表示処理は完成です。

![1660 localhost - 1009010212.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/cec89f13-6f9d-17cb-8cc6-5f15999108fc.jpeg)


## 今回利用したNCMBの機能

この地図メモアプリでは、NCMBの以下の機能を利用しました。

- データストア
  - データ登録
  - データ取得

NCMBには他にも認証、スクリプト、ファイルストア、プッシュ通知などの機能があります。ぜひそれらの機能も利用してください。

## まとめ

今回はMonacaとExchangeRate-APIを組み合わせて、通貨換算アプリを作成しました。APIを使えば簡単にアプリが作れるので、ぜひNCMBとともにアプリ開発にトライしてください。

[ドキュメント : 開発者向けドキュメント | ニフクラ mobile backend](https://mbaas.nifcloud.com/doc/current/#/JavaScript)
開発者ならばこのquicklook pluginを入れるべきである



# SourceCodeSyntaxHighlightインストール

- 紹介不要。とにかく良くできているquick look plugin:  https://github.com/sbarex/SourceCodeSyntaxHighlight

- [Releases pages](https://github.com/sbarex/SourceCodeSyntaxHighlight/releases) に行き、binaryをダウンロード  .appファイルを /Applicationsに移動

- notarizedではないらしいので 自分でquarantine属性を剥がす: `xattr -r -d com.apple.quarantine /Applications/Syntax\ Highlight.app`

# アプリを起動

起動するとカスタマイズできる。

# Settings.appから存在確認できる

Privacy & Security > Extensions > Quicklook > 



新しいPCになった時に、環境整いたい時に役に立てれば幸い. See you later!
Active Directory パスワードポリシーに関するメモ

パスワードポリシーでパスワードの最小文字数を変更する際にちょっとハマったのでメモ

# グループポリシーのコンピュータポリシーがVPN接続化だと適用されない事件
https://learn.microsoft.com/ja-jp/troubleshoot/windows-client/group-policy/group-membership-changes-not-updating-over-some-vpn-connections

サインインした後にVPNを接続するような感じだと、コンピュータポリシーが適用されるタイミングを逃してしまう。
これまでそんな状況下で使ったことが無かったので知らなかった。

ユーザAでVPN張って、ユーザBにユーザ切替をしてもダメ

PC起動時にADとやり取りできないと適用されないっぽい

# グループポリシー以外に適用する方法はないのか

調査するとグループポリシーの他に
- FGPP
- PSO(Password Setting Object)

という方法があった。

PSOが後発で設定しやすそうなのでそちらを使うことに

# PSO調べたことのざっくりまとめ
詳細は調査してください。
操作も簡単なので割愛

- Windows Server 2008から登場、当時はADSI editで設定する必要があった。
    - なのでStackOverflowなどにADSI edit使うべしって記述がある
- Windows Server 2012からGUIが発達して使いやすくなった。
- GPOよりもPSOが優先される
- PSOを設定したらどうなるか
    - 既存の認証には影響なし
    - PSO設定後のパスワード変更時から適用される
        - 上記から既存ユーザにパスワードを変更させる必要がある。
- PSOの適用状況はサーバから確認できる。ユーザ側での確認方法で簡単なものは見つけられなかった。
- ユーザ又はグローバルグループに適用可能。
    - GPOのためセキュリティグループを発行していると思うので、基本それを活用できる。
Django+Postgresqlをdockerで環境構築したらDBに接続できなかった

## 起きたこと

Django+PostgreSQLの開発環境をDockerで作ろうとしていたら，Django側で以下のエラーが出た.
```
2023-10-13 15:03:01 django.db.utils.OperationalError: connection to server at "db" (172.30.0.2), port 5432 failed: Connection refused
2023-10-13 15:03:01     Is the server running on that host and accepting TCP/IP connections?
```

構築は以下の記事を参考にした．

https://zenn.dev/iroristudio/articles/0216072d2d1f24

`docker-compose.yml`はこんな感じ．
```yml
version: "3"
services:
  db:
    image: postgres:16.0
    env_file: .env
    ports:
      - "54320:5432"
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    env_file: .env
    volumes:
      - ./src:/src
    ports:
      - "8000:8000"
    depends_on:
    - db
```

## 解決方法

クライアントツールを使ってホスト側から接続すると，接続できた．

```shell
psql -U postgres --port=54320 -h localhost
```
PostgreSQLが立ち上がる前にDjangoがDBに接続しようとしてて，それが原因で落ちていたらしい．
（教えてくれた友達ありがとう）

`docker-compose.yml`にヘルスチェックを追加して次のように書き直したらうまく起動した．

```yml
version: "3"
services:
  db:
    image: postgres:16.0
    env_file: .env
    ports:
      - "54320:5432"
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    env_file: .env
    volumes:
      - ./src:/src
    ports:
      - "8000:8000"
    depends_on:
      db:
        condition: service_healthy
```
エラーを「吐き」たい　【VRChat・パーティクル】

# はじめ

こんにちは。
ジョジョ好きなXRクリエイターの [もふるね](https://twitter.com/mofurune_k) です。

この記事のタイトルを見て皆様こう思ったことでしょう。
「え、何したいのコイツ」
はい、その通りです。
その通りなのですが、事のあらましを聞いたらきっと納得できると思います。

Unity作業をしていたある日のこと。
実行して確認しようと再生ボタンを押すと突然・・・
<img width="300" alt="er01.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/2310b343-dea5-3ba8-619d-1fa97e384b15.png">
ﾄﾞｩﾝ（低音）
見るだけで背筋が凍りそうなウィンドウが表示され、Unityが落ちてしまったんです。
保存してないのに。
数時間分の作業データを。

・・・

**やってやろうじゃねえかよ この野郎！**
私の方が多くエラー吐けますけど？！？？？！！！！！！（対抗心）


# 制作開始

・・・というわけでエラーを作っていきます。
仕組みは簡単！
エラーパーティクルを作って、人型アバターの口元から放出するだけ！


## エラー画像を作る

ペイントソフトなどを使って自分が吐きたいエラーを作りましょう。
ウィンドウの角の丸みを作りたい場合は、透過画像として作ります。


## パーティクルを作る

Unityに先程作った画像をインポートします。
Alpha SourceをInput Texture AlphaにしてApplyを押します。
これで画像の透明度を扱えるようになります。
![er02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/3d276452-3d50-ba03-d106-4d9895927758.jpeg)


次にマテリアルを作ります。
画像ではVRChat想定で作っていますが、それ以外で使う場合は「Mobile/Particles/Alpha Blended」にします。
Alpha Blendedとは、透明な画像を扱えるマテリアルです。
![er03.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3518924/7ce3e4df-e272-be68-5e7b-f0ed041c6bb6.jpeg)

最後にパーティクルを作ります。
設定は
　Start Lifetime：2
　Gravity Modifier：0.1
Emission
　そのまま
Shape
　Shape：Box
　Emit from：Shell
　Scale：xyz全て0.000001
Renderer
　Render Mode：Vertical Billboard
　Maaterial：先程作ったマテリアルを適用
　Sort Mode：By Distance

出現してから重力で落ちながら前方に進んでほしいので、Gravity Modifierの値を0.1にしました。
また、出現箇所を一箇所にしぼりたかったので、ShapeをBoxにし、Scaleを極小にしています。
そして、視点をRoll方向に傾けてもエラー画像は傾かないようにしたかったので、Render ModeをVertical Billboardにしました。

## VRChatで使う場合
先程作ったエラーパーティクルをアバターに仕込んでいきます。
Armature> Hips> Spine> Chest> Neck> Headの配下にパーティクルを置きます。

# まとめ

1. エラー画像を描く
2. パーティクルを作る
3. 人型アバターに仕込む

そうして出来上がったものがこちらになります。

<iframe width="560" height="400" src="https://www.youtube.com/embed/7nTFisRuILQ?si=mBmXqwe5yyUIMp2U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

作ったものはBoothで販売してますので興味が出た方は使ってみて下さい。
自作できる方は自分で作っちゃって良いと思います。
みんなも！　エラー！　吐こうね！

https://booth.pm/ja/items/4725286
【Laravel】フォームリクエストで複数フィールドをまとめてバリーでションする方法

## 環境
Laravel v8

## 問題

以下のように電話番号をブロックごとに分けて管理しているとします。
tel1 - tel2 - tel3

今回の例ではこの3つのフィールドを合わせて11桁までにするといったバリデーションをかけたいとします。

その場合、3つのフィールドを一つのものとして扱う必要がありますが、Laravelの標準バリデーションルールにはそのようなものに対応する方法はありません。

## 解決法
### 方針
- リクエストクラス内で三つのフィールドをくっつけた値を追加する。
- 追加された値に対してrules配列の中で適応したいルールを記述する。

### 実装
**リクエストクラス**
validationData メソッドをオーバーライドし、リクエストがバリデーションされる直前に3つの値をくっつけて新たな値を作り、それをマージするといった段取りです。

```php
public function attributes()
{
    return [
        "tel_all" => "電話番号",
    ];
}

/**
 * @inheritDoc
 */
public function validationData()
{
    $this->addTelAll();
    return parent::validationData();
}

/**
 * To validate for whole tel number
 */
private function addTelAll()
{
    $tel1 = $this->request->get('tel1');
    $tel2 = $this->request->get('tel2');
    $tel3 = $this->request->get('tel3');

    $telAll = $tel1 . $tel2 . $tel3;
    $this->merge([
        'tel_all' => $telAll,
    ]);
}

public function rules()
{
		$rules = [
			'tel_all' => 'required|numeric|digits_between:1,11',
		];

		return $rules;
}
```

## 参考
https://qiita.com/sh-ogawa/items/3b6611f7400f5d910e77
Ubuntu の Live USB で pigz をインストール

## あらまし
Ubuntu Linux の LiveUSBで起動し、外付けHDDへシステムバックアップを取ろうと思ったら、pigzが無かった。

そこで下記のようにいストールを試みるも、
``` sudo apt install pigz ``` 
との表示で、パッケージが見つからないのか、インストールに失敗してしまう。

## 行なったこと
そのため apt のパッケージ参照先を追加した。

```sudo add-apt-repository universe```

そして pigz をインストール。
``` sudo apt install pigz ``` 

# 結果
で dd を用いシステムバックアップをとる。

```sudo dd if=/dev/nvme0n1 bs=16MB iflag=nocache oflag=nocache,dsync |pv| pigz=/media/ubuntu/externalHDD/backup.tar.gz```
An error occurred when attempting to parse HtmlEmailBody content for HTML content.

+ [メール関係でのエラーに戻る](https://qiita.com/Keiji_otsubo/items/d8d09c86d471875661a5)


+ [I need help! ](https://trailhead.salesforce.com/trailblazer-community/feed/0D53A00004cTi4LSAS)

:::note alert
An error occurred when attempting to parse HtmlEmailBody content for HTML content. MemberID: 10311542 JobID: 0 ListID: 0 Content Begins With: {{.block 3vz5exdejk htmlblock}}{{.data}}{ "email": { "options": { "generateFrom": ""

The SET variable value expression is invalid. See inner exception for detail. Script: SET @Rows2 = LookupOrderedRows("Usage_Reports_SMB", 0, "AccountID", "GroupID", @GroupID) Variable Name: @Rows2 Index: 33415 ListID: 0
:::

+ [Error testing my email](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007MYydjSAD)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/8ea3f8dc-a5ec-0e92-eaf4-741abf26ab51.png)
es6のテンプレートリテラルを使って、行頭のインデントを削除

## コードの見栄えとして、テンプレート文字列でも、行頭にインデントを入れたい

そんな時用。

注意点は、行頭のスペースとタブを単純に削除するだけなので、全部のインデントが消えます。

そのため、HTMLなどのテンプレートとして使いたい時は、インデントが消えてしまうので注意です。

その他、定型文などで整形する時も気をつけて使いましょう。

```JavaScript

// テンプレート文字列の行頭のスペースまたはタブを削除
const escapeIndent = (strs, ...keys) => {
  let result = [];
  strs.forEach((_, i)=>{
    result.push(strs[i].replace(/^(  |\t)+/, '').replace(/\n(  |\t)+/g, '\n'));
    if(i < strs.length - 1) result.push(keys[i]);
  });
  return result.join('');
};

const x = '<XXX>';
const y = '<YYY>';

const text = escapeIndent`aaa
    bbb${x}
        ccc
    ${y}

    ddd`;

console.log(text);

/*
aaa
bbb<XXX>
ccc
<YYY>

ddd
*/
```
ElastiCache for Redisの設定についてまとめてみた

## はじめに
Amazon Web Services (AWS) の ElastiCache for Redis は、高速なインメモリデータストアとして人気があります。このサービスを最大限に活用するためには、その設定方法を理解することが不可欠です。

本記事ではElastiCache for Redisの設定について説明していきます。

![ 2023-10-13 14.10.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/fb48b095-a346-32f6-3e6d-aa1bb6f66e99.png)

## ElastiCache for Redisの設定
### クラスターモード
クラスターモードを有効にすると、データを複数のシャードに分散して保存することができます。これにより、大量のデータを効率的に管理し、高いスループットと低レイテンシを実現することが可能になります。クラスターモードが無効の場合、すべてのデータは単一のシャードに保存されます。

#### シャード
シャードは、データベースのデータを分割し、異なるサーバーやクラスターに保存するための単位です。シャードを使用することで、データベースの読み書きの負荷を分散させることができ、大量のアクセスがある場合でも高速なレスポンスを維持することができます。ElastiCache for Redisの場合、シャードはRedisのノード群として実装され、各シャードは複数のレプリカを持つことができます。

![ 2023-10-13 13.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/487820/2468fb69-dafb-248d-da43-cf1a9f183bb9.png)

### ロケーションの設定
ロケーションにAWS クラウドを設定するとマルチAZと自動フェイルオーバーの設定を選ぶことができます。

#### マルチAZ
マルチAZは、Amazon Web Services (AWS) の高可用性ソリューションの一部として提供されています。
マルチAZを有効にすると、プライマリノードと同じデータを持つレプリカノードが異なるアベイラビリティゾーン(AZ)に自動的に作成されます。これにより、一つのAZに障害が発生した場合でも、別のAZにあるレプリカがサービスの継続をサポートします。

#### 自動フェイルオーバー
自動フェイルオーバーは、プライマリノードに障害が発生した場合に、自動的にレプリカノードを新しいプライマリノードとして昇格させる機能です。
ElastiCache for RedisのマルチAZを有効にしている場合、この自動フェイルオーバーが行われると、異なるAZにあるレプリカが新しいプライマリノードとして動作を開始します。これにより、サービスのダウンタイムを最小限に抑えることができます。

### クラスター設定
エンジンバージョン、ポート、パラメータグループ、ノードのタイプ、レプリケーション数を設定できます。
以下ではパラメータグループとレプリケーション数について述べます。

#### パラメータグループ
パラメータグループは、ElastiCache for Redisクラスターの動作を制御するためのパラメータの集合です。これには、Redisの設定項目（例：timeout、maxmemory-policy など）が含まれます。パラメータグループを使用することで、特定のユースケースや要件に合わせてRedisの動作をカスタマイズすることができます。新しいパラメータグループを作成したり、既存のものを変更したりすることが可能ですが、変更を反映させるためにはクラスターの再起動が必要な場合があります。

#### レプリケーション数
レプリケーション数は、プライマリノードのデータをコピーして保持するレプリカノードの数を指します。レプリカノードは、読み取りのスケーラビリティを向上させるためや、障害時の自動フェイルオーバーの際に新しいプライマリノードとして昇格するために使用されます。レプリケーション数を増やすことで、読み取りのスループットを向上させることができますが、コストも増加します。また、レプリケーション数を増やすことで、障害時のリスクを分散させることができます。

レプリケーション数を0にするとマルチAZの設定ができなくなります。

### 接続性
ネットワークタイプ(IPv4)、サブネットグループを設定します。

#### サブネットグループ
サブネットグループは、複数のサブネットを論理的にグループ化するものです。これは、特定のAWSサービスのデータベースやクラスターを特定のサブネット内に配置するために使用されます。

### セキュリティ
暗号化について有効化するかどうかとセキュリティグループの設定ができます。


### メンテナンス
メンテナンスでは期間、自動アップグレード、Amazon SNSへの通知が設定できます。

### ログ
ログの形式、ログ送信先タイプ(CloudWatch Logs)、ログの送信先を設定できます。
スローログとエンジンログの設定ができます。

#### スローログ
スローログは、Redisの実行に時間がかかったコマンドを追跡・記録するための機能です。
パフォーマンスのボトルネックや過度に時間のかかる操作を特定するのに役立ちます。

#### エンジンログ 
エンジンログは、Redisサーバーの動作、エラー、警告、およびその他の重要な情報をキャプチャするためのものです。
システムの動作を監視し、問題や異常が発生した場合の診断に役立ちます。エンジンログには、クライアントの接続/切断、コマンドのエラー、レプリケーションの状態、設定の変更などの情報が含まれます。


## 終わりに
ElastiCache for Redisは、高速なインメモリデータストアとしての強力な機能を使いこなすには、適切な設定と管理が不可欠です。本記事を通じて、ElastiCache for Redisの主要な設定項目について確認できれば幸いです。

https://docs.aws.amazon.com/ja_jp/AmazonElastiCache/latest/red-ug/WhatIs.html
ダブルアレイはインデックスから文字列を取り出せます

# はじめに

先日、ちょっとした飲み会で、知り合いに、ダブルアレイのことを聞かれました。ダブルアレイはインデックスされた文字列を取り出せるのかと。

確かに、よく見る記事には
- 基本構造
- 検索方法
- 構築方法
- 高速検索の性質

あたりは書かれておりますが、Leaf ノードから Root にたどってインデックスされた文字列を取り出す話はあまりありません。

[元論文:An Efficient Digital Search Algorithm by Using a Doble-Array Strcuture](https://web.archive.org/web/20120709215831id_/http://www.syst.cs.kumamoto-u.ac.jp:80/~masato/cgi-bin/rp/files/e1066.pdf)
にもざっと見たところ説明がないような気がしました。

# 基本的なダブルアレイの説明はすっ飛ばしますが、

簡単な説明だけ。
- ダブルアレイはトライ木の実装の一つ。
- トライ木とは、ノードにラベルのついたtree構造で、テキスト辞書などに使われる
- ダブルアレイとはトライ木を、二つの値の配列で表現し、ラベルの値から子ノードの位置が計算できるように実装されている。そのため検索が非常に高速である

# サンプルデータ

ここでは、ラベル(文字)と文字コードの対応を {NUL}=0, 'a'=1, 'b'=2, 'c'=3 とします。
また、インデックスに a, ac, b, ba の文字列を格納し、それぞれ文字列が指すデータへのオフセットを DataOffset(x) とします。
これをダブルアレイのメモリイメージにすると以下になります。

| Address | Base | Check | comment |
|---|---|---|---|
| 0 | 0    | 0     | Rootノード |
| 1 | 3    | 0     | aのノード、Address3 が a の子ノードの先頭 |
| 2 | 4    | 0     | bのノード、Adresss4 が b の子ノードの先頭 |
| 3 | -DataOffset(a) | 1 | a{NUL} のノード |
| 4 | -DataOffset(b) | 2 | b{NUL} のノード |
| 5 | -DataOffset(ba) | 2 | ba のノード |
| 6 | -DataOffset(ac) | 1 | ac のノード |

この構造で、ba を検索するには、root ノードのAddress 0から始めて
Base(0 + 'b') = Base(2) = 4 を取得します。また、Check(0 + 'b') = 0 なので到達可能。
次に a を検索します。
Base(Base(0 + 'b') + 'a') = Base(4 + 'a') = Base(5) となり、データへのオフセット -DataOffset(ba) を取得し、負数なのでデータオフセットとして処理をします。
また、Check(Base(0 + 'b') + 'a') = Check(4 + 'a') = Check(5) = 2 これは、親ノードの "b" のアドレスと等しいので到達可能です。

気をつけてほしいのが、check には親ノードのアドレスを持たせているところです。

# では、Leaf から辿ってみましょう

Leafノードのアドレス 5 から、ラベルを取得しながら、root にたどっていきましょう。
Check(5) = 2は親ノードのアドレスです。Base(2) = 4 が、親ノードから見た子ノードの先頭を表します。したがって、子ノードの先頭アドレスから、Leaf ノードのアドレスを引けば、Leaf ノードの文字コードが取得できます。
つまり、(5 - 4) = 1 となり、最後の文字の 'a' の文字コードを取得できました。
すなわち (NodeAddress - Base(Check(NodeAddress))) を計算することで、NodeAddress の文字コードが取得できることになります。
次に、一つ親のノードのアドレスが 2 だとわかったので、(2 - Base(Check(2))) = 2 となり、'b' の文字コードが取得できました。
その次は、Check(2) が 0 で、ルートに到達したので終わりです。

サンプルコードで表すと、以下のような感じでしょうか。
```C++
std::string GetStringFromLeafNode(int nodeId)
{
  std::string keyString;
  while (nodeId != 0) {
    int ch = nodeId - Base(Check(nodeId));
    keyString += ch;
    nodeId = Check(nodeId);
  }
  std::reverse(keyString.begin(), keyString.end());
  return keyString;
}
```

# 使い道

日本語辞書のように、読みから漢字、漢字から読みの両方を引けるようにしたいときに、読みには漢字インデックスの終端ノードアドレス、漢字には、読みインデックスの終端ノードアドレスを入れることで、文字列データを別の場所に保存する必要がなくなります。

# まとめ

- ダブルアレイで、ノードのアドレスから、そのノードに対応するインデックスされた文字列を取得する方法を示した。
Fortranにおけるメモ

# Fortran Codingにおけるメモ
Fortranで数値計算用コードを書く時に、気をつけるべきことを自分が見返すようにメモを残しておきます。
間違い・補足等あれば、指摘していただけると幸いです。

## 多次元配列へのアクセス
Fortranでは、配列の格納方向が列方向(Column major)になっている。そのため多重ループを使う時には、キャッシュミスに配慮したループを書く必要がある。
```fortran
do k=1, 100
do j=1, 100
do i=1, 100
    !多重ループ処理
end do
end do
end do
```
詳しくは以下のサイト"5.9.2Column majorとRow major"を参考

https://amanotk.github.io/fortran-resume-public/chap05.html

## 動的確保
### 基本動作
プログラム実行中に配列の大きさを変更する時に、*allocatable*属性を付けることで、動的にメモリを確保することができる。
```fortran
!動的な倍精度1次元配列の宣言
real(8), allotable :: array(:)
!メモリの割り付け
allocate(array(100))
!メモリの解放
deallocate(array)
```
### 使うべきとき
#### 1. 大規模配列の利用
通常の(静的)配列では、保存場所(スタック領域)の都合により大規模な配列は格納できないようになっている。そこで、動的配列と確保すると、保存場所が変わるため(スタック領域->ヒープ領域)、より大きな配列を宣言することができる。ただ、その分メモリへのアクセうが遅くなってしまうことは留意していてほしい。

詳しくは以下のサイトを参照

https://amanotk.github.io/fortran-resume-public/chap05.html

->"5.9.1.メモリ領域"

https://www.momoyama-usagi.com/entry/info-calc-sys13

#### 2. MPI通信を用いた並列化
MPI通信を用いてプロセス並列を行うときに、メモリの無駄を省くため各プロセスで担当する範囲分だけメモリを確保する時に、メモリを動的確保すると良い。

詳しくは以下のサイトp11-p14を参照

http://exp.cs.kobe-u.ac.jp/wiki/comp_practice/index.php?plugin=attach&refer=6.MPI%A4%F2%CD%D1%A4%A4%A4%BF%CA%C2%CE%F3%B7%D7%BB%BB&openfile=Lecture20150618.pdf

## 型(構造体)の利用
物理量などをまとめて型として扱うことで、シンプルかつ効率的なコードを書くことができる。長いコードを書く際には推奨される書き方である。ただ、高速化という観点でメリットはそこまで大きくないと思われる。

詳しくは以下のサイトを参照

https://qiita.com/implicit_none/items/12c5404a11e6c237d100#構造体の配列array-of-structureと配列の構造体structure-of-array
OpenVPN 接続時  failed to negotiate cipher with server になる

# 概要
- Windows11 でOpenVPNを使って接続を試したところ、下記のエラーが赤字で表示されて接続できない
```
2023-10-13 13:07:20 OPTIONS ERROR: failed to negotiate cipher with server.  Add the server's cipher ('AES-128-CBC') to --data-ciphers (currently 'AES-256-GCM:AES-128-GCM:CHACHA20-POLY1305') if you want to connect to this server.
2023-10-13 13:07:20 ERROR: Failed to apply push options
2023-10-13 13:07:20 Failed to open tun/tap interface
```
- ※iPhoneアプリでは問題なく接続できたので、サーバ側の設定は問題なさそうだった。


# 原因
- 原因はOpenVPN 2.6系になってからOpenSSL 3.0 が使われるようになったようで、幾つかの cipher がデフォルトの設定がつかえなくなったらしい。

# 解決策
- OpenVPNの接続用コンフィグの末尾に
```
data-ciphers AES-128-CBC
```
を記載するだけで解決する

# 参考サイト
- https://s3b.astro.ncu.edu.tw/~daisuke/notebook/Computer___Network/20230516_00.html
  (Kinoshita Daisukeさん、ありがとうございます。)
Liberty接続プールトレース取得

Libertyにおける、トレース構成方法のマニュアルページはこちらにあります。
[ロギングおよびトレース](https://www.ibm.com/docs/ja/was-liberty/base?topic=SSEQTP_liberty/com.ibm.websphere.wlp.zseries.doc/ae/rwlp_logging.htm)

しかし、接続プールコンポーネントに限定してトレースを出させる指定方法は書かれていません。
「traceSpecification="*=all"」(全コンポーネント対象全出力)などと指定すると、大変な出力量になってしまいます。
詳しくは書きませんが出力の多さだけでなく何やらバグを踏んでしまったのか、Liberty起動が途中でフリーズして止まったりするなどのアクシデントもあり、全取得構成は簡単なようでむしろハードルが高かった、という印象です。。。


結論としては、Libertyにおいても、tWASと同じ指定文字列で取得できました。
[How to Enable a Connection Pool Trace for Websphere Application Server](https://www.ibm.com/support/pages/how-enable-connection-pool-trace-websphere-application-server)


### 設定方法

#### 環境
 * WebSphere Application Server 22.0.0.7 (wlp-1.0.66.cl220720220620-2217)
* JDBC Driver: IBM Data Server Driver for JDBC and SQLJ 4.31.10
* Db2 Server: Db2 11.5.7.0

#### 設定
server.xmlに、下記のトレース文字列を設定します
`*=info:WAS.j2c=all:RRA=all:Transaction=all`

一例：
```xml:server.xml(トレース取得のために必要な記述内容)
<logging traceSpecification="*=info:WAS.j2c=all:RRA=all:Transaction=all" maxFileSize="1000" maxFiles="50"/>
```

トレース有効化には、Libertyの再起動が必要でした。

#### トレースの止め方
以下どちらの方法でも止めることができました。
1.server.xml編集（logging traceSpecification … 部分を削除）、再起動
2.トレースファイルの削除

2.の方法だと、Liberty再起動が不要であるのと、出力再開したいときに同じ名前の空ファイルを作成するだけで良かったので、お手軽でした。
たぶん、あまりお行儀のよい方法ではありませんが。
性格悪いLLMを偶然にfinetuningで作りました。

最近LLMのモデルにハマって、いろんなモデルのfinetuningをしています。

昨日すごい面白いモデルを偶然に作りました。
要約機能を強化するモデルを作りたいと思って、論文や記事のデータで、とりあえず10000stepをトレーニングしました。（GPUはv100で25時間)
なぜかモデルの性格がすごい悪くなってしまい、質問（please summarize this article）に対して「時間ないから、他の人に聞いて」といった回答が返ってきます。
![1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3556459/26415226-d11d-8fe8-3e4b-a81b70bd631a.jpeg)
（写真には全文が入っていませんが、後半は「You can read the article yourself or ask someone else」という内容です。）
他に「会話を終了したいです、プログラミング以外の質問は、私に聞かないで」みたいな回答もありました。

原因は正直わからないですが、バッチサイズを小さく設定してしまったことが最大の原因ではないかと考えています。
一般的なトレーニング失敗の例としては、同じ内容を繰り返して話すことや、関連ない話（質問を理解できない）をすることなどが挙げられますが、今回の状況は初めてです。

学習データはすべて論文や記事であり、こういった性格になる要素は特に含まれていないと思います。
*100stepごとにモデルを保存していました。lossを見ると、もっとも低かったのは2000ステップの時点だったので、その時のモデルに同じ質問を投げてみたところ、質問を理解できないようで、まったく関係ない話を始めました。なので、この時点のモデルはまだ普通にトレーニング失敗したモデルですね。

わかる方いらっしゃれば、ぜひ教えていただきたいです。
モデルは:Llama2-7bです
オブジェクト指向とはなんなのか

本記事で言っているのはオブジェクトであってオブジェクト指向ではない（オブジェクトはあくまでオブジェクト指向の要素の一つである）という指摘がありましたが、その通りだと思います。記事は変更しませんがご了承ください。

---

**オブジェクト指向とは変数と関数をまとめたものである**

なぜこの一言が言えないのだろうか？オブジェクト指向に関する説明はググれば鬼のように出てくるが分かりやすいものはほとんどない。以下のような説明を見たことがある人は多いであろう。

「オブジェクト指向とは『ある役割を持ったモノ』ごとにクラス（プログラム全体の設計図）を分割し、モノとモノとの関係性を定義していくことでシステムを作り上げようとするシステム構成の考え方のこと」 [^1]

[^1]: https://robo-done.com/blog/2023/04/doneship_object_oriented/

「オブジェクト指向とは『モノ』を組み立てるように表現して、コンピュータに動作をさせること」 [^2]

[^2]: https://www.sejuku.net/blog/5973

「オブジェクト指向とは、『属性（構成するデータ）』と『メソッド（指示に対する振る舞い）』を1つにまとめた『オブジェクト』の定義ごとに『クラス』を分類し、そのクラス同士を組み合わせてシステムを組み立てる、システム設計やコーディングにおける考え方です」 [^3]

[^3]: https://techmania.jp/blog/programming0004/

**何言ってんの？**

なぜこのような分かりづらい説明が横行するのか。それはおそらく、全くの初心者に向けて説明をしているからだろう。しかし、変数や関数の概念も理解していない人にオブジェクト指向の説明をするほうが間違っているのだ。

---

また、そもそもオブジェクト指向自体がオワコンであるという主張があるが、今回は触れない。

https://qiita.com/baby-degu/items/ae5777dad23ee6624ce2
Mac + Alfred + Snippet でランダムなメールアドレスをペーストする

# 設定の例

Snippetに `{random:UUID}@example.com` を登録する

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/7f3420f7-eebf-427c-963b-84172318a32e)


# ペーストされるテキストの例

```
30AD558E-E5C7-4C60-8333-020ED968FDF7@example.com
```


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# Twitter

https://twitter.com/YumaInaura