OmniAICreator/Qiita-1.07M huggingface dataset:
ElixirでPAY.JPのライブラリ作成シリーズ④ ドキュメントに設計


https://qiita.com/Yoosuke/private/4e29b725b50117bc4616

こちらの続きです。

さて、シリーズ①で作成したプロジェクトを開くとデフォルトで以下のコードが生成されています。
これをベースに実装していきましょう。

```elixir
defmodule Payjpex do
  @moduledoc """
  PAY.JP API client for Elixir.
  Documentation for `Payjpex`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> Payjpex.hello()
      :world

  """
  def hello do
    :world
  end
end
```

テストコードも同様に用意されているのでこちらを書き換えていきます。

```elixir
defmodule PayjpexTest do
  use ExUnit.Case
  doctest Payjpex

  test "greets the world" do
    assert Payjpex.hello() == :world
  end
end
```

## ドキュメント使って簡単な設計

まずは、Let it crushに基づいて、スーパーバイザツリーを実装していきます。
基本的な方針として、API連携を管理するConfigと、実際に操作するApiclientを実装するモジュールを追加していきます。

まず初めに、大まかな動作イメージをドキュメントとして書いていきます。設計ですね。もしかしたら後で変えるかも知れません。が、そんな事はお構いなく、現時点での設計イメージをドキュメントにしておきます。

PAY.JPは日本語のドキュメントがしっかりしてる所がポイントな気がしたので、Elixirのライブラリもしっかり日本語にしてみました。

```elixir
defmodule Payjpex do
  @moduledoc """
    PAY.JP API用のElixirクライアントライブラリ。

    このモジュールはPAY.JP APIクライアントのメインアプリケーションモジュールです。
    設定管理とAPIクライアントプロセスを含むスーパービジョンツリーを管理します。

    ## アプリケーション構造

    起動時、このアプリケーションは以下のプロセスを含むスーパービジョンツリーを開始します：
      * `Payjpex.Config` - Agent プロセスを使用して設定値を管理
      * `Payjpex.ApiClient` - PAY.JP との API 通信を処理

    ## 設定方法

    設定は設定ファイルで指定できます：

        config :payjpex,
          api_key: "sk_test_xxxxxxxxxxxxxxxxxxxxxxxx",
          api_base: "https://api.pay.jp",
          api_version: "2024-01-01"

    または、実行時に動的に設定することもできます：

        Payjpex.Config.put(:api_key, "sk_test_xxxxxxxxxxxxxxxxxxxxxxxx")

    ## スーパービジョン

    `:one_for_one`戦略を使用しています。これは、子プロセスが終了した場合、
    スーパーバイザーによってそのプロセスのみが再起動されることを意味します。
  """

  use Application

  @doc """
  PAY.JP APIクライアントアプリケーションを起動します。

  この関数はOTPアプリケーションマネージャーによって自動的に呼び出されます。
  設定とAPIクライアントプロセスを含むスーパービジョンツリーを初期化します。

  ## パラメータ

    * `type` - 起動タイプ (:normal、:failover、または{:takeover, node_name})
    * `args` - 引数のリスト（通常は空）

  ## 戻り値

    * `{:ok, pid}` - スーパーバイザーが正常に起動した場合
    * `{:error, term()}` - スーパーバイザーの起動に失敗した場合

  """

 def start(_type, _args) do
   children = [
     {Payjpex.Config, []},
     {Payjpex.ApiClient, []}
   ]

   opts = [strategy: :one_for_one, name: Payjpex.Supervisor]
   Supervisor.start_link(children, opts)
 end
end
```

続いて、テストを書いていきます。

```elixir
defmodule PayjpexTest do
  use ExUnit.Case
  doctest Payjpex

  describe "アプリケーションの起動" do
    test "スーパーバイザーが正常に起動すること" do
      # Application.start(:payjpex)は不要 - mix test が自動的に開始

      # スーパーバイザーが起動していることを確認
      assert Process.whereis(Payjpex.Supervisor) != nil
    end

    test "Config プロセスが起動していること" do
      assert Process.whereis(Payjpex.Config) != nil
    end

    test "ApiClient プロセスが起動していること" do
      assert Process.whereis(Payjpex.ApiClient) != nil
    end
  end
end
```

それでは次に、ConfigとApiclientを実装していきましょう。と言いたいところですが、長くなるので次回にします。
Ark UIのField.ErrorTextはinvalidを受け取ったときだけ表示される

## この記事の概要

Ark UIのFieldコンポーネントを触っていて、初見の際に困ったことがあったので備忘録がてら記事にしました。

ほぼタイトル通りですが`Field.ErrorText`は`Field.Root`に`invalid`が渡っていないと表示されません。

:::note warn
Ark UIは色々なフレームワークで使えますが、この記事での例示コードはReactです。
:::

### コード

[公式ドキュメント](https://ark-ui.com/react/docs/components/field)に記載されているコードは以下の通りです。

```tsx:Input.tsx
import { Field } from '@ark-ui/react/field'

export const Input = () => {
  return (
    <Field.Root>
      <Field.Label>Label</Field.Label>
      <Field.Input />
      <Field.HelperText>Some additional Info</Field.HelperText>
      <Field.ErrorText>Error Info</Field.ErrorText>
    </Field.Root>
  )
}
```

こうして作成したコンポーネントを単に呼び出した場合`HelperText`は表示されますが`ErrorText`は表示されません。

```tsx:SomePage.tsx
import { Input } from "path/to/Input"

const SomePage = () => {
  return (
    // 他の要素
    <Input />
  )
}
```

`Field.Root`に`invalid`が渡って初めて`ErrorText`が描画されます。

```diff_tsx:Input.tsx
  import { Field } from '@ark-ui/react/field'

- export const Input = () => {
+ export const Input = (props: Field.RootProps) => { 
    return (
-     <Field.Root>
+     <Field.Root invalid={props.invalid}>
        <Field.Label>Label</Field.Label>
        <Field.Input />
        <Field.HelperText>Some additional Info</Field.HelperText>
        <Field.ErrorText>Error Info</Field.ErrorText>
      </Field.Root>
    )
  }
```

```diff_tsx:SomePage.tsx
  import { Input } from "path/to/Input"

  const SomePage = () => {
    return (
      // 他の要素
-     <Input />
+     <Input invalid />
    )
  }
```

:::note warn
実際は`invalid`を渡す際はstateなりcontextなりの値を使用すると思いますが、簡略化しています。
:::

## 参考

https://ark-ui.com/react/docs/components/field

https://github.com/chakra-ui/ark/blob/main/packages/react/src/components/field/field-error-text.tsx
git(0) list 

git関連記事の一覧作成中

|No.|Title, Link|Views|Likes|Stocks|
|:----|:----|:----|:----|:----|
|1|git(19)labのメール通知の設定 https://qiita.com/kaizen_nagoya/items/754e88d311cc1985e1c0|31,017 |4|6|
|2|bitbucket/git(16)hub/gitlab連携環境構築 悪戦苦闘 https://qiita.com/kaizen_nagoya/items/87352fe88ceed2c1732d|7,601 |10|9|
|3|unknown option `initial-branch=main', 今日のgit(6) error(34) https://qiita.com/kaizen_nagoya/items/208d538716bea14800cc|5,811 |3|1|
|4|卒業論文、修士論文、博士論文はgit(17)hub/gitlab/bitbacketのprivate利用をお勧め LaTeX(10) https://qiita.com/kaizen_nagoya/items/eb9945a2649f6f3eabd0|5,722 |6|8|
|5|アジャイルサムライ & 公開算譜は機敏だ(An Open Source Project is Agile)Git(12)Hub with Docker。仮説(51), Youtube(2) https://qiita.com/kaizen_nagoya/items/5dd49a046b5991af3a5e|5,493 |8|3|
|6|「未経験者が認識してなさそうなTIPS」で同意したいこと git(14) https://qiita.com/kaizen_nagoya/items/9759de698df880eb1f77|4,205 |13|9|
|7|open な issue がどんどん溜まる現象を解決するために。仮説(96) git(21)   https://qiita.com/kaizen_nagoya/items/efe22d9a23ad2e9934d6|3,017 |2|1|
|8|今日git(2)でしくったこと: Initialized empty Git repository, warning: adding embedded git repository, error(122) https://qiita.com/kaizen_nagoya/items/63ce0be02b20e1860c2a|2,952 |0|2|
|9|Git(13)Hub, bitbucket 事始め＆名古屋のIoTは名古屋のOSで https://qiita.com/kaizen_nagoya/items/198c4dc14b12e86d8b3e|2,660 |7|5|
|10|設計はgit(5), docker(13)で。https://qiita.com/kaizen_nagoya/items/5e85a825709f7f5f56ee|2,648 |3|3|
|11|Git(10)hub archive programって何ですか？ https://qiita.com/kaizen_nagoya/items/27cb1a6e3529a71b18a9|2,380 |2|2|
|12|Microsoftとの歴史　Basicに始まり、Cコンパイラ、Windows95、Git(9)hubまで https://qiita.com/kaizen_nagoya/items/d7c0cc257e99de0573cf|2,276 |20|11|
|13|Git(8)Hub入門 (1) 入門 https://qiita.com/kaizen_nagoya/items/b6f5b1532fd21fec79c8|2,224 |2|5|
|14|Git(20)Lab入門 (1) 入門 https://qiita.com/kaizen_nagoya/items/e8b9f4f0619e317db862|2,064 |0|1|
|15|Git(11)hubとdocker。docker(59) https://qiita.com/kaizen_nagoya/items/f7e142cd283a1c314234|2,045 |2|5|
|16|ありがとうGit(15)lab https://qiita.com/kaizen_nagoya/items/05a39cee0eb3a2de1106|1,657 |3|3|
|17|Git(22) Hub入門 (2) ソースとスクリプトを上げてみる。docker(127) https://qiita.com/kaizen_nagoya/items/c6a54925fd3510dc0710|1,260 |1|1|
|18|wireshark (13) @git(18)lab https://qiita.com/kaizen_nagoya/items/ec79b5607f4159163b3b|1,101 |0|1|
|19|PIP fatal: unable to connect to github.com: 今日のgit(3)hub error(89) coding(58) https://qiita.com/kaizen_nagoya/items/035913eb7159a2340322|1,050 |0|1|
|20|failed to push, Invalid username, 今日の作業記録 git(7) error(5) https://qiita.com/kaizen_nagoya/items/a7eb79f428466104fa38|1,017 |0|1|
|21|git(4) day job(ぎっとだいじょうぶ） https://qiita.com/kaizen_nagoya/items/e2a95acdd1e30ab90ce6|922 |1|1|
|22|git(1)lab server install and so on, error(143) https://qiita.com/kaizen_nagoya/items/1d69811fae7ca2704454|317 |0|1|
|23|git連携すればO.K. https://qiita.com/kaizen_nagoya/items/856554693c0fa802784d|212 |0|1|
|24|.git感想文 https://qiita.com/kaizen_nagoya/items/a8408328430b1e248666|13 |0|1|
|25|git(0) list https://qiita.com/kaizen_nagoya/items/da6e6990a569808e9623|13 |0|1|
| |合計|89,677 |87|83|
AWSログ調査

AWS のログ調査には 様々なツールがあります。
最近、一時的に開発より保守業務が増え、ログ調査の回数が増大し、いろんなツールを使いました。
ここでは**CloudWatch Logs Insights**、**Amazon Athena**、**CLI `filter-log-events`** を紹介しながらそれぞれのツールの特性を比較し、利用シーンや利便性を整理していきます。
適切に使って楽に安く使っていきましょう。

---

## **CloudWatch Logs Insights**
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/logs/AnalyzingLogData.html

料金さえ安ければ一番使い勝手が良いなあと思ってます。
（使い勝手良いから高いんでしょうけど）

### 特徴
- **料金**  
  - 0.005 USD/GB（解凍後のデータサイズが対象なので思っていたよりもかかります）。月5GBまで無料で使用可能
- **クエリ機能**  
  - 集計や計算式、正規表現、複数ロググループへの同時クエリが可能
- **操作性**  
  - ブラウザ上で直感的に操作できる。実行履歴の保存や結果のグラフ化も可能
- **データ量の処理性能**  
  - スケールする仕組みがあり、大量のデータでも効率的に処理可能
- **複数ロググループの処理**  
  - 複数ロググループを同時にクエリ可能
- **可視化**  
  - クエリ結果をグラフ化する機能を標準で提供
- **初期学習コスト**  
  - 専用のクエリ言語（Insight クエリ言語）を学ぶ必要があるが、比較的簡単に習得可能
- **利用シーン**  
  - 複雑なログ分析や大量データの処理、グラフ化が必要な場合に最適

### メリット
- 高度な分析が可能で、即座にグラフ化できるため、ユーザーの視覚的な理解を助けてくれる
- 複数ロググループを同時に処理できる

### デメリット
- クエリデータ量が多いとコストが高くなる
- 過去の長期間にわたるログを分析する場合にはコストやデータの制限に注意が必要

---

## **Amazon Athena**
https://aws.amazon.com/jp/athena/

基本はこっちを使っていきたい

### 特徴
- **料金**  
  - スキャンしたデータ量に基づき課金（5 USD/TB）。保存コストは S3 に準拠。
- **クエリ機能**  
  - 標準 SQL を使用可能。複雑な集計、結合、フィルタリングが可能。
- **操作性**  
  - ブラウザや CLI で利用可能。S3 に保存されたデータにクエリを実行。
- **データ量の処理性能**  
  - 大量データの処理に特化し、高速かつスケーラブル。
- **複数ロググループの処理**  
  - S3 に保存された複数のログファイルを横断的に処理可能。
- **可視化**  
  - 結果の可視化はサポートされておらず、QuickSight などの外部ツールと連携する必要がある。
- **初期学習コスト**  
  - SQL ベースのクエリが使えるため、一般的なデータ分析スキルで対応可能。
- **利用シーン**  
  - 長期間保存されたログの分析、ログと他データの結合分析に最適。

### メリット
- 大量データや長期間保存されたデータの分析に適している。
- SQL を使用するため、既存のスキルで簡単に利用可能。

### デメリット
- データのスキャン量に応じたコストが発生する。
- 可視化機能がなく、分析結果をグラフ化する場合は外部ツールが必要。

---

## **CLI `filter-log-events`**
https://docs.aws.amazon.com/cli/latest/reference/logs/filter-log-events.html

### 特徴
- **料金**  
  - クエリ自体には追加料金が発生しない。保存コストとデータ転送コストのみ適用。
- **クエリ機能**  
  - 単純な文字列フィルタのみ対応。複雑なクエリや集計は不可。
- **操作性**  
  - CLI で即座に実行可能。スクリプトや自動化に適している。
- **データ量の処理性能**  
  - 小規模データ向け。大量データの処理速度が遅くなる場合がある。
- **複数ロググループの処理**  
  - スクリプトやループ処理で対応する必要がある。
- **可視化**  
  - 結果の可視化機能はなし。外部ツールを使用して対応。
- **初期学習コスト**  
  - シンプルなフィルタリング機能のため、学習不要。
- **利用シーン**  
  - 小規模データの簡易フィルタリングやスクリプト運用に最適。

### メリット
- クエリ実行自体にコストがかからない
- 簡単な文字列フィルタリングに最適で、スクリプトへの組み込みが容易

### デメリット
- 大規模データや複雑なクエリには向いていない
- 結果の可視化機能がないため、データの分析や共有に外部ツールが必要

### 備考
個人的には複数のロググループを指定できないのがネックでした。
まあ、そんなに面倒ではないので必要回数分取得したり、頻度の高いグループの組み合わせは作っておくのが良いのかなと思っています。

こういった個々人の要望に合わせたカスタマイズ性が高いのは魅力ですね。


---

### **まとめ**

#### ツールごとの適用シーン

| **利用シーン**           | **推奨ツール**                                                                            |
|--------------------------|------------------------------------------------------------------------------------------|
| **リアルタイム分析**      | CloudWatch Logs Insights                                                                 |
| **長期間保存データの分析/調査** | Amazon Athena                                                                           |
| **短期的なログ調査やスクリプト運用**         | CLI `filter-log-events`                                                                 |

お金×利便性から最適なものを選択していきましょう。
余計なものまで見ないことがセキュリティ上も、金銭面でも大事。
慣れるとCLIで大体事足りるかも？
AnthropicのClaude.ai新機能”スタイル”を検証！自分オリジナル回答スタイルを追加してピーマン星人にする

# Claudeの新機能　回答スタイルの作成

ピーマン星人にだって出来ちゃう
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/bac8e116-8e21-dabb-c9c0-23d55b380e6a.png)

# 手順

## 0から知りたい人向け

https://qiita.com/Jasmine_teeeeee/items/c10f6f5a1fe80d5b8738

## 本編

赤枠箇所にレスポンス形式の選択エリアが追加されました！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/f7a8424b-87f0-2c6d-92ce-b6d2d869bac6.png)

選べるスタイルは以下です。

* normal
* concise（簡潔）
* explanatory（説明的）

ここからデフォルトの回答スタイルを選択してもよし！
オリジナルのスタイルを作成してもよし！

# デフォルトスタイル比較

## normal

情報量は多すぎず少なすぎず、普通ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/027013b8-9162-4f4d-e73f-8535db592654.png)

## concise（簡潔）

normalより情報量が減って、さらに文章的ではなく単語で記載されており、ぱっと見で理解できるような回答ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/9447765f-7f2e-8848-9267-8862fe74c498.png)

## explanatory（説明的）

情報が詳しく記載されていますね。１質問すると１００返ってくるタイプの子ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/3456ced5-418e-492f-7cc7-e0a2a10580e5.png)

## formal（正式？堅苦しい？）

文章量はnormalと同じくらいですが、感情がなく、公式HPのようなお客様説明資料のような文章での回答ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/0c35c8f3-ea13-f87c-6528-28215e3c86c2.png)

# オリジナルスタイル作成方法

赤枠から自分オリジナルスタイルの登録を行っていきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/10b77bd8-37ed-1741-277e-872c81ab7b30.png)

画面下部のボタンを押下

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/475e86c4-d996-c3e1-bc0f-5f0f7edf7dc0.png)

ファイルを登録できる画面になるので、
ドラックアンドドロップまたはエクスプローラー立ち上げボタンを押下してファイルをアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/94af2ecc-78ed-1810-72eb-ffa5f7fc8b35.png)

または直接書き込むことも可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/cd2f7eef-a975-2a34-da8f-5cde7a7fd3ad.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/a2d59b8f-55b9-50d2-bb06-825c3304d278.png)

今回は事前に作成したファイルをアップロードして、猫にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/52730aed-2f77-95a4-9ea3-be72236d1326.png)

ファイルをアップロード中・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/33fb7438-d3e8-0073-ce57-699e6c0de7c1.png)

アップロードが完了するとこんな感じで
オプションを付けたり、プレビューしたり説明を編集できる画面が表示されます。
特に変更なければ、画面上部の「←」ボタンを押下して、スタイル選択画面に戻ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/fbc98d3d-8cf8-a104-fa69-68f94719eb63.png)

追加されましたね。「×」ボタンで元の画面に戻ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/5b37c091-0464-f318-438b-9fa08b547e82.png)

追加されたオリジナルスタイルを選択し、同じ質問をしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/4cd1605e-4491-b3e2-29a8-43dc7e648bd5.png)

はい。完全に猫ですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/dc83a9ef-6b8c-bbc7-0c14-86a2fb64ffc2.png)

# 自分もピーマン星人にしたい！という変な人向け

いいねやご要望あれば、あとでここにプロンプト貼っておきますw
ABC329 Fの解法メモ【Ruby】

入水目指して過去挑戦して解けてないAtCoder Problems上でDifficultyが水色の問題を解いていく。

# [ABC329 F: Colored Ball](https://atcoder.jp/contests/abc329/tasks/abc329_f)概要

N個の箱に1つずつ色のついたボール(色の重複はあり)が入っていて、指定された箱から全てのボールを別の箱に移動させて色の種類数を求めることをQ回実施する問題。

# 解法イメージ

### 愚直な方針

まず、問題文の通りに解くことを考えてみる。

N個の箱に1つずつボールが入っているので、1つのボールが入っている配列の配列を作成する。($ \mathcal{O}(N) $)
その後Q個のクエリを処理する。($ \mathcal{O}(N+Q) $)
各クエリに対して、箱aに入っているボール(最大N個)を全て箱bに移動させる。($ \mathcal{O}(N+QN) $)
移動させた後、箱bに入っているボールの色の種類数を求めるて出力する。($ \mathcal{O}(N+QN^2) $)

という感じで、そのまま解くと$ \mathcal{O}(QN^2) $となり、$ 1 \le N,Q \le 2 * 10^5 $の制約から当然間に合わない。

### 種類数の計算の効率化

計算量の削減を考えた時に、ボールを移動する際は全てのボールを移動させるためそれぞれの色について何個入っているかを考える必要はない。
よって、色の種類数のみを保持してあげれば良いので、Set等のオブジェクトで持ってあげてボールを移動させる際に色の種類が増えたかどうかを求めてその箱の種類数を管理してあげることで箱に入っている色の種類数を$ \mathcal{O}(1) $で求めることができる。(計算量$ \mathcal{O}(N+QN) $)

### ボールの移動方法の効率化

あとはボールの移動の計算量が$ \mathcal{O}(QN) $になっている部分を改善できれば良さそう。
移動する時の回数がNになるような移動方法を考えてみると、
　箱1→箱2
　箱2→箱3
　...
　箱N-1→箱N
　箱N→箱1
　...(以下略)
のように一番ボールが多い箱の移動をしていくケースが考えられる。

このケースを考える時に、移動元の箱にはたくさんボールが入っているが、移動先の箱には1個しか入っていない状態になっている。
それなら、移動先のボールを移動元に移動させて、箱のラベルの張り替えをした方が移動回数は減らせそうに見える。
実際に上記のケースを考えると、`箱N-1→箱N`の移動までは移動先のボール一つを移動元に移動させてラベルの張り替える2ステップで良く。それ以降は全てのボールが一つの箱に集まっているためラベルの張り替えのステップのみで済むため$ \mathcal{O}(Q) $となる。

これは効率のいいケースなので、一番移動回数が多くなりそうなケースを考えてみる。
ボールの移動する回数を増やすには、移動先と移動元のボールの数の小さい方の数を大きくすれば良いので、これを最大化させるには移動先と移動元のボールの数を同数にすることを考える。
初期状態では全て1つずつ箱に入っているため、それぞれ1つの箱から1つの箱に移動させてボールが2つの箱ができる。それらの箱に対して、2つずつ入っている箱同士で移動させ4つの箱を作る。というのを繰り返していくと、$ 2^k $個のボールの箱ができるまでに

 $$ 1(個) \times \frac{N}{2}(箱) + 2(個) \times \frac{N}{4}(箱) + ... + 2^{K-1}(個) \times \frac{N}{2^K}(箱) = \frac{N}{2} + \frac{N}{2} + ... + \frac{N}{2} = \frac{KN}{2} $$

から$ \frac{KN}{2} $回のボールの移動が発生する。
この移動に必要なクエリの回数は、指定した箱数と一致するので$ \Sigma_{i=1}^{K}\frac{N}{2^{i}} = NK(1-\frac{1}{2^K}) $となる。
よって1回のクエリあたり $ 2 - \frac{1}{2^{K-1}} $個のボールが移動することになるので、こちらで考えても$ \mathcal{O}(Q) $で処理ができる。

※実際にはここまで考える必要はなくて、石が移動するクエリの回数は1回進めるごとに半減していくため、$ \mathcal{O}(\log{N}) $であり、それぞれの移動は最大でもN個なので$ \mathcal{O}(N\log{N}) $で済む。これだけでも、$ \mathcal{O}(Q+N\log{N}) $程度で収まることが分かるので間に合うことは分かる。

よって、ボールの移動は数が少ない箱から数が多い箱へ移動し、移動した箱を移動先の箱としてラベリングしてあげればよい。

# 実装例

```ruby
require "set"

n, q = gets.split.map(&:to_i)
arr = gets.split.map(&:to_i)

hash = {}
arr.each_with_index do |a, i|
  hash[i + 1] = Set.new([a])
end

q.times do
  a, b = gets.split.map(&:to_i)
  if hash[b].length > hash[a].length
    hash[b].merge(hash[a])
  else
    hash[a].merge(hash[b])
    hash[b] = hash[a]
  end
  hash[a] = Set.new
  puts hash[b].length
end
```
博士進学するか悩む君へ。~博士が就職困難って本当?~

# 博士号を取って本当に良かった。

私は2015年4月に大阪大学 基礎工学部 システム科学科に合格し、そのまま大学院へ進学、2024年春に博士課程を卒業しました。
卒業要件(=論文の件数)がギリギリなのが少し恥ずかしいですが、一応ストレート卒業です。

実は学部3年生までは、修士で卒業して三菱重工で戦闘機やロケットの制御に関わる事が「現実的な」夢でした。
しかし __博士を取ったおかげで、__ 今は「小学生の頃からの夢」であるヒューマノイドの研究・開発を仕事にしています。

一般的な企業は旧帝大の修士卒でも配属部署ガチャがあります。
しかし博士は中途採用枠だったため、公募があれば狙ったポジション(=研究チーム)に一点賭けでエントリーできます。これは修士では決して出来ない、 __超贅沢かつ私の生涯で最も価値のある「選択権」__ でした。

配属ガチャ免除です。自分の人生を運に任せず、100%自分でコントロールできます。この価値が分かる人は博士行くべきです。


# 博士が就職困難という噂

恐らくウソです。
私の主観ですが、周囲の博士は就職に困っていません。恐らく工学系・情報系だからです。
文系の博士は企業にとって戦力になりづらいと聞きます。その話の主語が大きくなったんじゃないかな、と。


私の周囲の博士卒業後の進路は、

大企業に就職：3名 (NTT,トヨタ)
大学でポスドク：1名 (阪大)
政府の研究機関：3名 (産総研)
ベンチャー企業：6名 (うち5名が東京)
海外：2名 (カナダ)

という感じです。

ベンチャー企業に就職する博士は結構多いです。
これも冒頭の「選択権」と同じ話で、博士のような尖った人達が目指す「やりたい仕事」、「挑戦したい開発」がベンチャー企業の方が多いため、皆さん業務内容に比重を置いてエントリーする傾向があるんだと思います。


# 博士に行くべき人、行かないべき人


・今の研究テーマが好き
・夢がある
・徹夜で研究してる
・教授から背中を押される

上記１つでも当てはまれば博士に行って良いと思います。
少なくとも私の周りで「博士行って後悔した～」って話は聞いたことがありません。行っていいんです。


# 博士の就活

学部卒や修士卒の人は、旧帝大院の理系だろうが「SPI試験」だの「夏季インターン」だの「就職説明会」だの、いわゆる日本の就活をします。

私は何もしませんでした。
ただ目の前のロボットを歩かせる事で頭が一杯で、毎日研究室でC++と論文を書いてました。
世間知らずの馬鹿すぎて就職なんて目もくれてませんでした。

トヨタ未来創生センターを知ったのは博士2年の10月末、IROS2022(京都)の企業展示ブースで、WovenCityと並んでロボットを展示していました。Wovenのロボットの方がカッコよくて、当時はWovenの社員さんと名刺交換&研究紹介してました。
その1ヵ月後、YouTubeでトヨタのロボット開発のライブ配信があると噂があり、これが決め手となってエントリーしました。

https://www.youtube.com/live/jqAXF1vulXs?si=aY9r75zaRwmtrnNv


__入社前に自分の上司を選べた事が最大の決め手です。__

この人たち全員天才だって直観で感じました。
今では毎日話す仲ですが、やはり皆さん本当に凄いです。僕なんかデコピンで吹き飛びます。

以上のように、博士の就活がトリッキーなのは本当だと思います。群れの流れに乗って新卒向け企業説明会とか行く次元じゃないです。
自分で考え、単独で行動に移せる人じゃないと厳しいと思います。



# 最後に

博士に行くか悩んでいる、という後輩からよく相談を受けます。
自分の研究室レベルで結構いるという事は、日本中にもっと沢山いるんだと思います。

悩める学生の判断材料になる情報が非常に少ないため、本記事が何らかの助けになれば幸いです。
chrome-extensionのmanifest.jsonの簡易解説

## この記事を通して学べる事
- ブラウザ拡張機能を管理するmanifest.jsonについて、どの記述がどの機能に紐づいているか理解できる
全部分はchrome公式をご覧ください: 

https://developer.chrome.com/docs/extensions/reference/manifest?hl=ja

## manifest.json例
```json:manifest.json
{
  "manifest_version": 3,
  "name": "Extension Sample",
  "version": "1.0",
  "description": "Extension Sample.",
  "permissions": ["activeTab", "scripting", "contextMenus"],
  "host_permissions": ["<all_urls>"],
  "icons": {
    "16": "icons/icon-16.png",
    "48": "icons/icon-48.png",
    "128": "icons/icon-128.png"
  },
  "action": {
    "default_popup": "popup.html",
    "default_icon": {
      "16": "icons/icon-16.png",
      "48": "icons/icon-48.png",
      "128": "icons/icon-128.png"
    }
  },
  "content_scripts": [
    {
      "matches": ["https://*.example.com/*", "http://*.example.com/*"],
      "js": ["scripts/content-script.js"],
      "css": ["styles/content-style.css"]
    }
  ],
  "options_page": "options.html",
  "web_accessible_resources": [
    {
      "resources": ["images/*", "scripts/injected.js"],
      "matches": ["<all_urls>"]
    }
  ]
}
```

### action→default_popup
拡張機能をブラウザのurl/検索欄の脇に固定し、アイコンをクリックしたときに出てくるhtml

### permissions
- activeTab
現在開いているタブに対する権限
- scripting
スクリプト注入に対する権限
- contextMenus
コンテキストメニュー(右クリック時のメニューのこと)に追加するための権限

### content_scripts
スクリプトやCSSなどの注入設定
matchesのurlパターンにマッチしたとき、resourcesに指定したファイルを使用

### options_page
開発者が提供する拡張機能のオプション(設定)ページ

### web_accessible_resources
content_scriptsから`chrome.runtime.getURL("resource_path")`使用時、アクセス許可の設定
Python グローバル変数とローカル変数について

Pythonでは、変数のスコープ（有効範囲）によって、グローバル変数とローカル変数に分類されます。これらの違いや使い分けを正しく理解することは、効率的で読みやすいコードを書くために理解を深めておく。

目次
1.グローバル変数とは
2.ローカル変数とは
3.グローバル変数を関数内で変更する
4.nonlocalキーワードについて
5.まとめ

1.グローバル変数とは
-
グローバル変数は、プログラム全体でアクセスできる変数です。関数の外側で定義され、関数内からもアクセス可能ですが、関数内で変更するためには特別な宣言が必要です。
```python:example.py
x = 10  # グローバル変数

def display_global():
    print(f"グローバル変数 x の値: {x}")

display_global() # 出力 ⇒ グローバル変数 x の値: 10
```
2.ローカル変数とは
-
ローカル変数は、関数やブロック内で定義される変数で、そのスコープは定義された関数またはブロック内に限定されます。同じ名前のグローバル変数があったとしても、ローカル変数が優先されます。
```python:example.py
x = 20  # グローバル変数

def local_example():
    x = 5  # ローカル変数
    print(f"ローカル変数 x の値: {x}")

local_example() # 出力 ⇒ ローカル変数 x の値: 5
print(f"グローバル変数 x の値: {x}") # 出力 ⇒ グローバル変数 x の値: 20
```
3.グローバル変数を関数内で変更する
-
関数内でグローバル変数を変更する場合、globalキーワードを使用します。ただし、この方法は可読性やデバッグの難しさを引き起こすことがあるため、乱用は禁物。
```python:example.py
counter = 0  # グローバル変数

def increment_counter():
    global counter  # グローバル変数を変更
    counter += 1
    print(f"関数内の counter: {counter}")

increment_counter() # 出力 ⇒ 関数内の counter: 1
print(f"関数外の counter: {counter}") # 出力 ⇒ 関数外の counter: 1
```
4.nonlocalキーワードについて
-
nonlocalキーワードは、ネストされた関数（関数内の関数）で、親関数のローカル変数を変更するために使用されます。
```python:example.py
def outer():
    y = 10  # 親関数のローカル変数

    def inner():
        nonlocal y  # 親関数のローカル変数を参照
        y += 1
        print(f"inner関数内の y: {y}")
    
    inner() # 出力 ⇒ inner関数内の y: 11
    print(f"outer関数内の y: {y}") # 出力 ⇒ outer関数内の y: 11

outer()
```

4.まとめ
-
グローバル変数はプログラム全体で共有されるが、関数内で変更する場合はglobalが必要。
ローカル変数は関数やブロック内でのみ有効。
ネストされた関数内で親のローカル変数を操作する場合はnonlocalを使用。
適切なスコープを活用することで、プログラムの可読性や保守性が向上します。グローバル変数の乱用を避け、必要に応じてローカル変数や引数、戻り値を活用しましょう。
【VScode】ショートカットキー編集方法（Python3編）

# はじめに
最近、VScodeでPython3の学習を始めました！
これまで、eclipseをメインに他の言語を触っていたため、VScodeでの実行時のショートカットキーが分かりませんでした。
ネットで検索しましたが、少し時間がかかったため、同じような悩みを持つ方のためになればと思い、残します。

# ショートカットキー編集方法

VScodeの左下の歯車マークをクリック＞「キーボードショートカット」をクリックすると、たくさんのショートカットキー一覧が表示されます。
下の方に行くと、コマンド欄に「Python: ターミナルで Python ファイルを実行する」があるかと思います。
カーソルを合わせると、左側に鉛筆マークが出現するので、クリックします。
子画面が出現し、任意のショートカットキーを設定することができますので、最後にENTERをクリックします。
これで設定は完了です。

※ちなみに、設定したキーの組み合わせがすでに存在していると、警告が表示されるようになっています。便利！

何かソースを記述したあと、ご自身が設定したショートカットキーを入力してみてください。ターミナルに実行結果が表示されるようになっています！

# おわりに
カーソルで実行ボタンを押す煩わしさから解放されて、学習がはかどりそうです。
設定画面と同じ画面の、キーバインド欄にキーの組み合わせが表示されており、いつでも確認できるので、設定したキーを忘れてしまった場合でも安心です。
筋肉は全てを解決する

本記事は、 [mediba Advent Calender2024](https://qiita.com/advent-calendar/2024/mediba ) の2日目の記事になります。

## 突然ですが皆さん筋トレしていますか？
筋トレは体を鍛えて、運動をするときのパフォーマンスを上げたり、体型を維持したりというイメージはパッと思いつくと思います

今回は筋トレをするとなぜいいのかを皆さんに紹介できればと思っています

## いきなりですが、こんな症状出ていませんか？
* 体の歪みが出ている（肩の高さが左右で違う、など）
* 低気圧になると首に痛みや頭痛がでる
* 日常的に首や腰に痛みが出ている

実は上記の症状は、運動不足が原因になっていることが多いのです

### なぜ、その症状がおきるのか？
* 運動不足による身体の可動域の低下
* 運動後ストレッチ不足による、体が固くなる
* 日常的な癖があり（モニターが左にあり、左をよく見るなど）筋肉の稼働域が限定される

もっと詳しく説明すると
人体は正しい姿勢に戻そうとする時に筋肉が使われます、さらに筋肉で修正できなくなると骨がずれていきます、そうなると、体の歪みが顕著にでてきます
### 痛み、不調の原因
* 筋肉の緊張、骨の歪みによる神経を圧迫することによる痛み
    * かなり症状が進んでいる
* 日常から筋肉が緊張（硬くなる）していて低気圧時に血管が膨張し、神経を圧迫して痛みがでる
    * 早めの対策で解決

なので、日ごろの運動で筋肉の稼働域を広げる、運動による血行促進などで解決・予防できます

### まずは体をリセットしよう
痛みが出てしまっている場合は、筋トレだけしても解決しないので
整体で体の筋肉の緊張、骨の位置を正しく戻すことが大事になっていきます
#### カイロプラクティック整体がおすすめ
[カイロプラクティック整体](https://jac-chiro.org/aboutchiro/)とは、筋肉の緊張をほぐし、体の骨を正しい位置に戻すことができる施術です、施術をうけることにより、本来の正しい姿勢に戻すことが可能です

自分は施術を月一受けていて、ストレートネック、肩の左右の高さが違う、低気圧時の頭痛全て解決しましたw

## どこを鍛えるべきか
以下の二つは特に今回おすすめなのでやってみてください

背中を鍛える
* 姿勢の改善
* 頭痛肩こりの改善
* 引っ張る、持ち上げるなどの日常生活においてよく使う動作に効果

種目
* [ラットプルダウン](https://youtu.be/G9-OXCE8mds?si=IIa0MxDCV1EdMX11)
* [シーテッドプーリーロー](https://youtu.be/xq0YDRk__Og?si=zZO3v56jyx6Z1uVf)
* [チンニング(懸垂)](https://youtu.be/__dY0cJ5HRY?si=vGlIUQA61Dz2hsxb)

内転筋を鍛える
* 骨盤の安定
* O脚改善
* 歩行、ランニングのパフォーマンスアップ

種目
* [サイドスクワット](https://youtu.be/I5biGSH9DxE?si=hohHB0ShGbgqomH1)
* [ヒップアダクション](https://youtu.be/Ww009sBujI4?si=8js42_CTdgkxlxS_)

## さいごに
本来であればもっと筋トレを紹介したかったのですが、いきなり大ボリュームだと引かれてしまうので今回はここまでにします（笑）
体は全てにおいて資本となるものです、なので日ごろからメンテナンスや筋トレを行い、快適な日常生活を送っていきましょう
朝会（夕会）をなんとなくやっていませんか？

[ZOZOのアドカレは今年11シリーズまであります](https://qiita.com/advent-calendar/2024/zozo)。
アドカレと言えば、この記事はシリーズ◯のX日目の記事ですと書くのが定番ですが、この◯シリーズの◯を探すのが今年は大変です。この記事は[ZOZOアドベントカレンダー2024](https://qiita.com/advent-calendar/2024/zozo)シリーズ「８」の３日目の記事です。

# 朝会（夕会）ってなんでやってるの？

朝会や夕会やっていますか？
リモートワークでも出社していても一日のうち全員集まるのが朝会や夕会だけ。というチームも少なくないでしょう。なので、なんとなく集まって、活動報告して、今日も一日がんばろー（またはお疲れ様でした）！これだけでも士気が上がるし貴重な時間でしょう。そういう意味では価値のある活動かもしれません。

しかし、今一度朝会や夕会のある意味を考えてみませんか？
見方を変えれば、チーム全員の時間を15分なり30分なり強制的に奪っているとも言えます。その貴重な時間になんとなく集まるというのは非常にもったいない。そもそもあらゆる会議や（仕事上の）会話には、ゴール・成果物・期待する結果が明確に定義されているべきです。

# スクラムのデイリースクラムの定義

スクラムにはスプリント中のイベントの一つとして「デイリースクラム」があります。デイリースクラムの定義は以下のように定義されています。（以下は、[スクラムガイド2020](https://scrumguides.org/docs/scrumguide/v2020/2020-Scrum-Guide-Japanese.pdf)から抜粋したものですが、全体としても14行しかありませんのでぜひ読んでみてください）

```
デイリースクラムの⽬的は、計画された今後の作業を調整しながら、スプリントゴールに対す
る進捗を検査し、必要に応じてスプリントバックログを適応させることである。
```

```
開発者は、デイリースクラムがスプリントゴールの進捗に焦点をあて、これからの 1 ⽇の作業
の実⾏可能な計画を作成する限り、必要な構造とやり⽅を選択できる。これは集中を⽣み出し、
⾃⼰管理を促進する。
デイリースクラムは、コミュニケーションを改善し、障害物を特定し、迅速な意思決定を促進
する。その結果、他の会議を不要にする。
```

つまり、スクラムにおいてデイリースクラムは
***ゴール***・・・必要に応じてスプリントバックログを適応させること
***成果物***・・・1日の作業の実行可能な計画、スプリントゴールの進捗、障害物の特定
***期待する結果***・・・コミュニケーションを改善し、障害物を特定し、迅速な意思決定が促進されていること
と言えるでしょう。

# うちのチームの朝会

デイリースクラムの定義では具体的にこうして進行しましょうみたいな具体例はありません。それぞれのチームの都合や状況に合わせ、かつデイリースクラムの定義されていることを達成できるように進行するべしということです。

うちのチームは現在スクラムをやっているわけではないのですが、参考までにどんなことをやっているか紹介します。

### 理想のチームの確認

以前ワークで全員が参加して決めた理想のチームとは何かを確認します。週末の振り返りではどれくらい理想のチームに近づけたかを点数つけて計測しています。

### 今週のTRYの確認

前週末の振り返りで決めた、今週のTRYの確認をします。できているか、できていなければどうするか？を確認します。

### にこにこカレンダーと昨日やったこと、今日やることの確認。困っていることの確認。

曇りなら怪しい。雨なら手遅れだけどなんとかしたい。これに困っている。などの確認です。解決に時間がかかれば、別途時間をとって解決します。

あとは全社共有とか休暇の共有などもここでしますが、それはついでです。
Pre-render error: {keys: ..., values: ..., up: function s, down: ..., between: ..., only: ..., not: ..., unit: ...}

Next.jsでMUIのテーマAPIを使おうとした際のエラー

## 環境
- MUI 6.1.9
- Next.js 15.0.3
- React 18.2.0
- Vercelへのデプロイ

## コード
```layout.tsx
// 省略
import { createTheme } from '@mui/material/styles';

const theme = createTheme({
  colorSchemes: {
    light: {},
    dark: {},
  },
});
// 以下略
```

## エラー
```.stdout
Error occurred prerendering page "/". Read more: https://nextjs.org/docs/messages/prerender-error
Error: Functions cannot be passed directly to Client Components unless you explicitly expose it by marking it with "use server". Or maybe you meant to call this function rather than return it.
  {keys: ..., values: ..., up: function s, down: ..., between: ..., only: ..., not: ..., unit: ...}
                               ^^^^^^^^^^
    at eO (/vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:23766)
    at Object.toJSON (/vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:14915)
    at stringify (<anonymous>)
    at eU (/vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:26272)
    at eB (/vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:26502)
    at eq (/vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:27056)
    at AsyncLocalStorage.run (node:internal/async_local_storage/async_hooks:91:14)
    at /vercel/path0/node_modules/next/dist/compiled/next-server/app-page.runtime.prod.js:84:39749
    at node:internal/process/task_queues:151:7
    at AsyncResource.runInAsyncScope (node:async_hooks:211:14)
Export encountered an error on /page: /, exiting the build.
 ⨯ Static worker exited with code: 1 and signal: null
Error: Command "npm run build" exited with 1
```

## 原因
MUIの`createTheme`の部分が関数を返すことが原因。
<details>

[`createTheme()`](https://github.com/mui/material-ui/blob/e1b3bfa687e75d62db6f9a545f1f865f0a7e9273/packages/mui-system/src/createTheme/createTheme.js#L33)の定義で、`cssContainerQueries()`の結果が返されるようになっている。
[`cssContainerQueries()`](https://github.com/mui/material-ui/blob/e1b3bfa687e75d62db6f9a545f1f865f0a7e9273/packages/mui-system/src/cssContainerQueries/cssContainerQueries.ts#L74)の定義では`containerQueries`の`up`, `down`, `between`, `only`, `not`プロパティに対して関数が割り当てられている。
おそらく、トレースバックの`{keys: ..., values: ..., up: function s, down: ..., between: ..., only: ..., not: ..., unit: ...}`の部分はこれ。

</details>

Next.jsは関数を含むコンポーネントをSSRできないため、エラーが出る。
今回の場合、
> Layouts are Server Components by default but can be set to a Client Component.

[とある](https://nextjs.org/docs/app/building-your-application/routing/layouts-and-templates)ように、`layout.tsx`は強制的にサーバーコンポーネントになるので、`createTheme`もSSRすることになりエラーになる。

## 解決策
`createTheme`を別ファイルに移す。
[bash] ディレクトリ文字列のリネーム処理

# shのrename処理を行うコードをcopilotに聞いてみた結果
#### 実現したいこと
a/b/c/name.csv c/name.csv name.csv
↓
name_a_b_c.csv name_c.csv name.csv


```bash:rename.sh
#!/bin/bash
# ファイルパスのリスト
 file_paths=("a/b/c/name.csv" "c/name.csv" "name.csv") 
# 各ファイルパスを処理
 for path in "${file_paths[@]}"; do 
# ファイル名を抽出 
 filename=$(basename "$path") 
# ディレクトリパスを抽出し、'_'で結合 
 dir_path=$(dirname "$path" | tr '/' '_') 
# ディレクトリパスが空でない場合、ファイル名に追加 
if [ "$dir_path" != "." ]; then 
 new_filename="${filename%.csv}_${dir_path}.csv" 
else 
 new_filename="$filename" 
fi
 echo "$new_filename" 
done
```

以上。

edgeのcopilot優秀で驚きます。
つくるのたのしいヨン（4つのつくるたのしさ）

# メイカーは なぜつくるのか🤔
電子工作やアプリ開発など いろいろつくる
趣味として 仕事から帰ってから または 休日につくる
つくったものを公開して コンテストに応募する
展示会へ出展する　別に物を売って儲けるとかじゃない　交通費や出展料もかかる

メイカーたちのこのエネルギーは 一体なんなのか？なにがたのしいのか！？
メイカーじゃないひとには理解するのがむずかしい

# つくるのたのしいヨン4️⃣✨
つくるたのしさを4つに類型化してみました

## 1. つくる
つくりたかったものが形になっていくたのしさ
以前はつくれなかったものが つくれるようになるたのしさ
ひとりで もくもくもいいけど みんなでつくるのもたのしい

## 2. みせる
X（Twitter）で製作過程からみせて リアクションをもらったり
展示会でみせて あそんでもらったり
見たひとが面白がってくれて さらに良さを引き出してくれるたのしさ
こだわりを語るたのしさ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239549/e8b6724c-b405-d9ef-4b2c-3565f09b5a71.png" width=50%>

## 3. リミックス
コラボレーション または マッシュアップと呼んでもよいかも
ほかのひとのアイデアや技術を組み合わせて
自分ひとりでは想像できなかったものが爆誕するたのしさ
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239549/7097a417-23f5-85c5-1b07-906bf70cd61c.png" width=50%>

## 4. つかってもらう
自分のつくったものを他のひとがつかって
役に立ったり かわいがってもらう
それがつくるモチベーションにつながる
「自分もつくってみよう」という 他のひとの”1.つくる”につながる
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/239549/a36b3731-4971-953c-fef8-3973cb47506e.png" width=50%>


# おわりに
いろんなタイプのメイカーがいると思います

「自分は”2.見せる”は あんまり興味ないかなー」とか？
「おれは"3.リミックス"が大好き」とか？
みなさんは どこに特にたのしさを感じますか？

わたしは ”2.みせる"がたまらない 今後は"3.リミックス"をトライしたい

つくったものは どんどん #protopedia に投稿しよう
つくったものは どんどん #ヒーローズリーグ に応募しよう
いつも面白がってくれるみなさまに感謝⭐️
Salesforceオブジェクトのイベントベース変更データキャプチャに関して（Heroku Connectあれこれ）

Heroku EnterpriseにはHeroku Connectという名のSalesforceオブジェクトをHeroku Postgresに同期する機能があります。
Heroku Connectは、標準設定では2分間隔でのポーリング（定期確認）が最短なので、ユースケースによっては、Salesforceでのレコード変更が即座にデータベースに反映されない、ということが問題になることがあります。
そこで、加速ポーリング（https://devcenter.heroku.com/ja/articles/mapping-configuration-options#accelerated-polling-of-salesforce ）を有効にするとStreaming APIを活用して、ベストエフォートながらニアリアルタイムでSalesforceオブジェクトのレコード変更に応じて、Heroku Postgresに同期を図ることができます。
流行り言葉でいえば、イベントベースの変更データキャプチャということで、公式のブログの2014年の記事が再掲されています。

https://blog.heroku.com/sf-streaming-api

この記事にあるようにSalesforce側では PushTopic という標準オブジェクトも使うので、Heroku ConnectのSalesforce接続に使うユーザーは PushTopic へのアクセス権が必要になります。

行数ブロック課金のHeroku Connectでは、SalesforceのAPIアクセス量の制約から解放されるというのがウリですが、この加速ポーリングを前提として構成したシステムで、肝心な時に加速ポーリングが無効な状態に戻ってしまうという現象で、大変な目にあったことがあります。

https://qiita.com/schubertosamo/items/86dfcc64c31ccf658f1e 

と同じ症状でした。まあこの辺は改善されたという話があるなら聞きたいところです。

Salesforceオブジェクトの変更データキャプチャで、同期先をRDBにできるのは、たぶんHeroku Connectだけなので、活用ポイントはそれなりにあるのかなと思います。

# 閑話休題

Salesforceのデータを顧客へ繋げる定番としてのHerokuとして、Dreamforce2024でのランボルギーニ社の事例には、Herokuの明るい未来がたくさーん詰まっていますが、生成AIも頑張らないといけない東京の正面からはあまりお話がないのは寂しいよな。

https://www.salesforce.com/plus/experience/dreamforce_2024/series/it_at_dreamforce_2024/episode/episode-s1e29

そんな中、先日のコミュニティでは、Jonathan BrownさんがDreamforceの復習をしてくれて、大変良い機会でした。

https://trailblazercommunitygroups.com/events/details/salesforce-salesforce-developer-group-tokyo-japan-presents-ohurainkai-cui-salesforce-developers-meetup-34-heroku-pm-nise-zhi-wen-shitemiyounohui/

Streaming APIですが、時代はPub/Sub APIですよねと公式にも書いてありますが、まだMuleのコネクタしかないなあとか、仙台の方に頑張ってもらいたいとか思って念を送っておきます…

https://developer.salesforce.com/docs/atlas.ja-jp.api_streaming.meta/api_streaming/intro_stream.htm
Sequence Makerで計測器が無くてもシーケンスを開始する裏技

## はじめに
Sequence MakerはExcelから測定器を制御可能にするアドインです。Sequence Makerは様々なシーケンスを自由に組むことができますが、シーケンスを開始するためには1台以上の測定器が必要になります。しかし、例えばCONTECのデジタル入出力ユニットだけを使いたいような場合にわざわざ測定器を用意するのは面倒です。この記事では計測器が無くてもシーケンスを開始してしまう裏技？を紹介します。なお、Sequence Makerについての詳細は以下の記事を参照ください。

https://qiita.com/sequencemaker/items/8e6a370ab0a793a06a3b

:::note warn
***お断り***
本記事の内容はSequence Maker開発元の公式見解ではなく、あくまでも個人が趣味の範囲内で執筆しているものです。記事の内容について開発元へ問い合わせることはお控えください。ご質問・要望などは各記事のコメント欄へお願いいたします。
:::

## 結論！
いきなりですが結論からです。
インターフェイス#1の設定 **「LAN」** にして、IPアドレスを **「1.1.1.1」** 、ポート番号を **「80」** にするだけです。
こんな感じです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/627ebbe8-8da3-1c6e-7a33-c466e769c2ab.png)

すると、「コマンド送受信」ボタンを押してシーケンスを開始できます。もちろんCONTECのデジタル入出力ユニットだけを使うこともできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/8a9bb7f5-38bf-3828-661c-bbaea4015805.png)

:::note alert
この方法を使うためには、インターネット接続が必要です。
:::

## なぜこんなことができるか
上記の方法では、シーケンス開始時に1.1.1.1（https://one.one.one.one/ ）というサイトのWebサーバーのポート80番に接続しています。

https://one.one.one.one/

80番ポートというのは、通常であればWebブラウザがWebサーバーに接続してWebページを表示するためのものですが、ポートをオープンするだけならSequence Makerでもできてしまいます。なお、WebサーバーのIPアドレスであれば、1.1.1.1以外でも大丈夫です。例えばYahoo!なら74.6.231.21とかGoogleなら142.251.42.206とかQiitaなら18.65.207.93とか、お好きなIPアドレスを使ってください。
もしインターネット接続されていない環境でも、ローカルなネットワーク上にWebサーバーがあれば、そのIPでも良いです。
ちなみにIPアドレスを調べるときはURLに対してPingを打てばすぐにわかります。
```
C:\Users>ping qiita.com

qiita.com [18.65.207.93]に ping を送信しています 32 バイトのデータ:
18.65.207.93 からの応答: バイト数 =32 時間 =11ms TTL=249
```

## もっと別の方法
ちょっとLANのことはよくわからないとか、適当なWebサーバが無い、という場合は別の方法を使いましょう。
Sequence MakerはRS-232C通信が可能なので、手元にUSB-RS232C変換器があれば、それを接続しておくのも良いでしょう。またはArduinoなんかでも良いです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/3fe4efc8-86cf-d6c7-82ed-d6ff8a94951e.png)
（https://www.iodata.jp/product/interface/rs232c/usb-rsaq6/spec.htm より引用）

インターフェイスの設定で「RS-232C/USB」を選択し、認識しているCOMポートを選んでおけばOKです。最近だとBluetoothとかLTEとかのCOMポートがあったりするので、それらを使うのも手です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3821782/6ea75d01-71f3-c505-7e9c-cc0d5c6ea9e8.png)


## まとめ
今回は測定器を使用せずにシーケンスをスタートする方法を紹介してみました。普通測定器の1台や2台ぐらい手元にあるだろうと言われるかもしれませんが、まぁこんな方法もあるということで。
Terraformの繰り返し処理の使い分けについて考える

# はじめに
この記事では三ヶ月ほどTerraformに触れてきた人間から見た、Terraformにおける繰り返し処理の使い分けについて記述していく。

# Terraformにおける繰り返し処理
Terraformにはcount, for_each, for の三つの繰り返し処理構文が存在する。
それぞれの繰り返し処理についてこれから解説していこうと思う。

## count
countは他の中でも直感的でシンプルな繰り返しと言えるのではないかと思う。
同じリソースを単純に複数作成したいときや、数値でのスケーリングが適している場合に向いている。

以下の例ではawsのサーバー用のインスタンスを三つ作成するものである。

```
resource "aws_instance" "server" {
  count = 3
  ami   = "ami-123456"
  instance_type = "t2.micro"
  tags = {
    Name = "server-${count.index}"
  }
}
```

## for_each
for_eachはmapを使用して繰り返しを行う。
リソースごとに異なる設定が必要な場合や、安全な追加・削除が重要な場合に向いている。

以下の例では異なる用途ごとに異なるインスタンスタイプのインスタンスを三つ作成するものである。

```
resource "aws_instance" "server" {
  for_each = {
    "web"  = "t2.micro"
    "api"  = "t2.small"
    "db"   = "t2.medium"
  }
  ami           = "ami-123456"
  instance_type = each.value
  tags = {
    Name = "server-${each.key}"
  }
}
```

## for
forは主に変数の加工に使用される。
多くのプログラミング言語に触れていると「繰り返し=for文(やwhile文)」と思われるかもしれないが(少なくとも自分はそう思っていた) Terraformにおいてはforは制御構造を持っていない。主にデータ操作のために設計されたものである。
そのためリソースの作成にはcount, for_eachを使い、その前段階としてforを使って値を生成するというのがTerraformにおける繰り返しの書き方となる。

```
# forの適切な使用例
locals {
  environments = ["Development", "Staging", "Production"]
  
  tags = {
    for env in local.environments :
    env => {
      Environment = env
    }
  }
}

resource "aws_instance" "servers" {
  for_each = local.tags
  
  ami           = "ami-123456"
  instance_type = "t2.micro"
  tags          = each.value
}

# このような書き方は文法エラーとなる
resource "aws_instance" "server" {
  for env in local.environments {  
    ami = "ami-123456"
    instance_type = "t2.micro"
    tags          = {
      Environment = env
    }
  }
}

```

## for_eachとcountの削除時の動作について
主にリソースを作成するfor_eachとcountの使い分けについて考えていく。
実際に仕事でTerraformを使用しているときにcountを使っている場所を自分はほぼ見かけない、その一番の理由は削除の安全性にあるのではないかと思う。

実際に三つのインスタンスを生成する例における削除時の動作について見てみる。
- countの場合

```
locals{
  service = [
    "web",
    "api",
    "db"
  ]
}
resource "aws_instance" "server" {
  count = length(local.services)
  ami   = "ami-123456"
  tags  = {
    Name = "server-${local.services[count.index]}"
  }
}
```
この状態からapiのインスタンスが不要になったとする。
この時、local変数からapiを削除すると残りのリソースの再作成が発生する。なぜならばindexの振り直しが発生するからだ。

上記リソースは作成時には下記のようなリソース名で作成されている。
```
# web
aws_instance[0]
# api
aws_instance[1]
# db
aws_instance[2]
```
ここからapiを削除する場合、dbのインスタンスのindexは振り直しになってしまいリソース名が変わってしまう。リソース名が変わるとTerraformでは完全に別物となってしまうのでリソースの再作成が発生してしまい実際のサービスでは瞬断等が発生する原因となる。

- for_eachの場合
```
resource "aws_instance" "server" {
  for_each = {
    "web"  = "t2.micro"
    "api"  = "t2.small"
    "db"   = "t2.medium"
  }
  ami           = "ami-123456"
  instance_type = each.value
  tags = {
    Name = "server-${each.key}"
  }
}
```
この状態からapi用のインスタンスを削除する。
for_eachではキーで識別され、apiのリソースのみが削除され他のリソースは影響を受けることがない。

以上からリソースの追加・削除が行われる業務上でのTerraformではfor_eachがよく使われているのだと考えている。

# まとめ
繰り返しはコードの重複を削減したり変更管理の効率化をする上で便利である。
一方で変更による影響範囲の制御等デメリットも存在する。
適切に使い分けながらいいコードを書けるよう私も精進していきたい。
AstroでMarkdownファイルをhtmlとしてレンダリングしたい

## 前提
とある知り合いからの依頼でAstroを使い、CMS機能を含む静的サイトを作っている中で、投稿をTwitterのように縦に並べて表示したいという希望があった。
元々[...slug].astro内で各記事ごとにmarkdownファイルをHTML形式でレンダリングする部分は既にテンプレート内で実装されていたため、その内容を参考にタイムラインページを実装した際、勉強になった部分をこの記事では説明していく。

:::note info
※この記事では、Astroについての説明や環境構築などには触れません。
Astroについての説明が気になる方は、下記の公式ドキュメントをご参照ください。
https://docs.astro.build/ja/getting-started/
:::

## 環境
OS: MacOS Sequoia
node.js: v18.18.0
パッケージ管理ツール: yarn
Astro: 4.16.12
TypeScript: 5.6.3

## 結論
今回実装したソースコードは下記の通りである。なお、CSSや一部関係のないソースコードは割愛している。

```jsx
---
import { getCollection } from "astro:content";

import FormattedDate from "../../components/FormattedDate.astro";

const rawPosts = await getCollection("blog");

const posts = await Promise.all(
  rawPosts.map(async (post) => {
    const { Content } = await post.render();
    return { ...post, Content };
  })
);

posts.sort((a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf());
---

      <section>
        <ul>
          {posts.map((post) => (
            <li>
              <a href={`/blog/${post.slug}/`}>
                <h4 class="title">{post.data.title}</h4>
                <p class="date">
                  <FormattedDate date={post.data.pubDate} />
                </p>
              </a>
                <post.Content />
            </li>
          ))}
        </ul>
      </section>
```

## 解説
### getCollection
冒頭でrawPostsに対して行なっているgetCollectionという関数は、astroプロジェクト内で使用できる、あるディレクトリ配下のファイルを全て取得するという関数である。
この関数を使用すると、`src/content`配下のmarkdownファイルやMDXファイルなどを取得することができる。
今回は、`src/conrent/blog`配下のmarkdownファイルを取得したかったため、`getCollection("blog")`と指定している。

## post.render
render関数とは、Astroプロジェクト内で使用できる、MarkdownおよびMDXファイルをHTMLにレンダリングできる関数である。
この関数を使うことで、レンダリングされた記事の内容を取得することができる。
その後、`post`オブジェクトに`Content`を追加し、最終的にpostsにレンダリングされた内容を含む配列が格納される。

## post.sort
pubDateとは、markdownファイル内で定義している日時である。その日時の値を元に、投稿順が新着順になるようソートしている。

## 所感
今までReactやWordPressなどで同様の機能を実装したことはあったが、Astroはmarkdownファイルを配置すれば内部で使用できる関数を使用することでCMS機能がついたサイトを実装することができた。
また、AstroはNetlifyなどのホスティングサービスとも相性が良いため、ビルドやリリース管理も非常に簡単に行うことができ使用感はとても良い。
shadcn/uiと相性抜群!! 便利な拡張サイト3選

# はじめに
皆さんは  `shadcn/ui` をご存じでしょうか？
`shadcn/ui` は、`Radix UI` や `Tailwind CSS` を基盤としたUIコンポーネントのセットで、デザインと機能性に非常に優れています。

https://ui.shadcn.com/

私は `shadcn/ui` が非常に好きで使っているのですが、例えば `MUI` などの老舗UIライブラリと比べると、コンポーネントの種類が少なめだと感じることがあります。実際、開発中に `Time Picker` を使いたい場面があったのですが、`shadcn/ui` にはありませんでした。

しかし、「**shadcn/ui time picker**」と検索してみたところ、以下のようなサイトを見つけました。これらは `shadcn/ui` のデザインに近いUIコンポーネントを提供していました。

https://time.openstatus.dev/

https://time.rdsx.dev/

他にも同様のサイトがないか調べたところ、いくつか見つかったので、3つをご紹介します。

# サイト紹介

## Shadcn Extension

https://shadcn-extension.vercel.app/

## shadcn/ui expansions

https://shadcnui-expansions.typeart.cc/

## Magic UI

https://magicui.design/

ちなみに `Magic UI` は上の二つとは違って、 `shadcn` という名前がサイト名に入っていませんが、トップページをみると、「**Perfect companion for shadcn/ui**（shadcn/uiにとって完璧な相棒）」と書かれていて、相性の良さがわかります。

![スクリーンショット 2024-12-01 22.26.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3750522/4addf64a-f62d-fc60-ec5a-dd87f6ab676f.png)

ちなみに、私は最近この `Magic UI` めちゃくちゃ使ってます。

# まとめ
今回は、`shadcn/ui` を拡張する際に役立つおすすめサイトを3つご紹介しました。
`shadcn/ui` を愛用している方は、ぜひ今回取り上げたサイトのコンポーネントも活用してみてください。きっと、開発の幅がさらに広がるはずです!!
プルリクエスト作るとき、 reviewers にメンバー指定するのめんどい

# 概要
プルリクエストを作成する際、テンプレート使っててもタイトルと詳細を書くのは大変なのに、それに加えて reviewers も指定しなきゃならない？超面倒なので自動で何とかしたい

# 解決策
どうやら .github ディレクトリ直下に CODEOWNERS という設定ファイルを配置してパスとオーナーとなるユーザーを書いておけば、そのオーナーとなるユーザーが reviewers に自動で入る模様

![スクリーンショット 2024-12-01 225634.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76272/49516692-fb83-d186-bbaa-98d3c6ad21b2.png)


## CODEOWNERS ファイルの設定方法サンプル

```
# リポジトリ全てを設定したい場合
* @kazumacchi
```

```
# srcディレクトリ以下
src/* @kazumacchi
```

```
# 複数オーナーを指定する場合はスペース区切りで
public/* @kanagama @kazumacchi
```

# 感想
結構簡単だった。

ランダムで選びたいとかなるとさすがに GitHub Actions でゴニョゴニョするしかなさそうだけど、小チームかつ全員でレビューする、もしくは有識者だけやってくれればいいや、という場合には有効そう。
JSでDOM処理の関数を作る際の事前確認

最近、JSの学習を始めていました。
ブラウザ上で動かす言語として、
処理を書く前に、以下のことをやると、のちに便利だと知りました。

例えば、inputテキストの値を取得する関数を作成したとします。
```
const onClickAdd = () => {
  const inputText = document.getElementById("add-text").value;
}
```
値を取得して、この後に、本処理を書くのですが、
書き切った後に、変数が正しく取れていないとか起こると、
その後の、原因調査が大変で時間を取られます。

なので、alert()を使用して、
視覚的に、取れているかを確認すると便利だと学びました。

```
const onClickAdd = () => {
  const inputText = document.getElementById("add-text").value;
  alert(inputText);
}
```

単に、JSだけで完結する変数や配列とかであれば、
node.jsで実行して、バックエンド側で確認することも楽なのですが、
htmlから取得した要素を使うdom操作とかだと、そうはいかなそう。

こういう、小さな確認が大事になる時もありますからね。
今回は以上。
SAC-Craft（Vキャス内◯ine◯raft）の設計図を作る

「VキャスのVCIで◯ine◯raftっぽいもの作る Advent Calendar 2024」1日目

Vキャス内で、穴を掘って、石を砕き、木を切って、組み合わせて武器を作って、何なら出てくる敵を倒して・・・
そんなことをやりたいなぁっていう試みを12月でできるところまで行こうというカレンダーの1日目です！

## 設計図を書く
まずは、設計図を作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222644/432664d2-bc6d-9af7-00d3-5988d61804ef.png)
この図は[miro](https://miro.com)というWebツールで描いています。
無料で3シートまで使えてとても直感的に使えるのでおすすめですよ！

このクラフトの仕組みを、以前作りかけだったSAC-Craftと名付けました。

## 設計の説明

### 構成
3種のVCIによって成り立つことを考えます。

VキャスのVCIの仕組みには、[VCIStorage](https://developer.virtualcast.jp/vci-docs/manual/networking/vci_storage.html)という、ルームを跨いでも、ルームへの入退出をしたあとでもそのVCIに紐づけられた情報を保存できる仕組みがあります。
何ができるかというと、ルームを跨いだレベルアップの仕組みを作ってVキャス自体にRPGみたいにしたり、例えば得点が競えるゲームの結果をルームを跨いで保存することで、知らないユーザーと競えるようにしたり。そんな事ができます。
ただし制約として、1つのVCIストレージには最大1000個のKey-Valueペアまでの制限があります。

今回作りたいSAC-Craftは、ユーザーの情報としてレベルだったりステータス、職種みたいなものも後々管理したいと考えています。更に、アイテムの制御もやりたい。そしてそれはちゃんとデータで残しておきたい。
そんな事を考えているので、1つのVCIの種類が管理できる「1000個のKey-Valueペア」では足りなくなりそうです。

そこで、この3種構造を考えます。
① ユーザーを管理するVCI
② ステータスを管理するVCI
③ アイテムや敵のような実態のVCI
役割の種類で３つに分けようという考えです。


### ① ユーザーを管理するVCI
このVCIでは、ユーザーのIDだけを管理します。
ルーム内でユーザーが一意に持つIDがあるので、それを保存していきます。
このVCIは前提VCIとなるので、SAC-Craftを使うためには必ず必要なVCIに位置づけます。
よって①のVCIは1つだけになると思われます。

### ② ステータスを管理するVCI
このVCIでは、ユーザーだったりルームだったりのステータスの管理を想定します。
例えば、Aさんは職業が剣士で、レベルが10で、HPは100で・・・みたいな情報を制御することを考えます。
また同じ種類だが別VCIでは、このルームでこの箱はこの位置にあって、クラフトの結果つるはしがあって、つるはしは壊れるまであと54回で・・・みたいな情報制御を考えます。
②のVCIは、ユーザーのステータス管理だったりをするものと、ルームの管理だったり複数のVCIがあり得ると考えておきます。
また、ステータスの書き換えとかはこのVCIで制御してほかで不正ができないようにします。

### ③ アイテムや敵のような実態のVCI 
このVCIは、無限に存在することを想定します。
例えば土、例えば木、例えば敵キャラ、おそらく遊ぶユーザーが触ったり色々するのはこのVCIです。

## おわりに
まずは設計をざっとしてみました。
作っていく中で、これでは無理というような局面が出てきたらまた変えていきますが、まずは手を動かすための前提とします。


明日は、まずはテンションを上げるために③のアイテムを作ってみます。
画面のページング実現のためにOVER句を使った話


## はじめに

Webアプリケーションや管理画面でデータを表示する際、ページング処理はユーザーエクスペリエンスを向上させるために重要な機能です。しかし、ページング処理を実装する際に、データの取得順序と表示順序が異なる場合、一般的なLIMITとOFFSETを使った方法では問題が生じることがあります。

今回は、SQLの**OVER句**とウィンドウ関数を活用して、データの取得順序と表示順序が異なる場合でも効率的にページングを実現する方法をご紹介します。

## ページングと表示順序が異なる場合の問題点

### 問題点

- ページングの基準となる順序と、最終的な表示順序が異なる場合、LIMITとOFFSETでは実現が困難です。
- 例として、登録日の昇順でページングし、各ページ内ではスコアの降順で表示したい場合を考えます。
- この場合、LIMITとOFFSETを使用すると、データの重複や欠落が発生する可能性があります。

### 解決策

- OVER句でページング用の順序を指定し、外側のクエリで表示用のORDER BYを指定する。
- これにより、データの取得順序と表示順序を分離し、正確なページングを実現できます。

## 実装方法

以下のSQLクエリは、登録日の昇順でページングし、各ページ内ではスコアの降順で表示する例です。

```sql
SELECT
    user_id,
    registration_date,
    score
FROM (
    SELECT
        user_id,
        registration_date,
        score,
        ROW_NUMBER() OVER (ORDER BY registration_date ASC) AS row_num
    FROM
        users
) sub
WHERE
    row_num BETWEEN :start AND :end
ORDER BY
    score DESC;
```

### クエリの解説

1. **内部サブクエリで行番号を付与**

```sql
SELECT
    user_id,
    registration_date,
    score,
    ROW_NUMBER() OVER (ORDER BY registration_date ASC) AS row_num
FROM
    users
```

- ROW_NUMBER()ウィンドウ関数とOVER句を使用して、登録日の昇順で各行に行番号row_numを付与します。
- これにより、登録日の順序でデータをページングする基準が作られます。

2. **外側のクエリでページング範囲を指定**

```sql
WHERE
    row_num BETWEEN :start AND :end
```

- :startと:endには表示したいページの開始行と終了行の番号を指定します。
- 例えば、1ページに20件表示し、ページ番号がpageの場合:
  - :start = (page - 1) * 20 + 1
  - :end = page * 20

3. **最終的な表示順序を指定**

```sql
ORDER BY
    score DESC;
```

- 外側のORDER BYでスコアの降順を指定し、ページ内のデータを希望の順序で表示します。

## なぜOVER句を使うのか？
### パフォーマンス向上
OFFSETの問題点：OFFSETを使うと、指定した行数分のデータをスキップしますが、このスキップもコストがかかります。

ROW_NUMBER()の利点：行番号を直接指定できるため、大量データでもパフォーマンスが安定します。

### LIMITとOFFSETでは解決できない理由


- **データの重複や欠落のリスク**：データの追加や削除が行われると、OFFSETの位置がずれ、同じデータが複数のページに表示されたり、表示されなくなったりする可能性があります。
- **表示順序の不一致**：LIMITとOFFSETはクエリ全体のORDER BYに依存するため、取得したデータを別の順序で表示することが難しいです。

### OVER句を使うメリット

- **取得順序と表示順序の分離**：OVER句でページング用の順序を指定し、外側のORDER BYで表示用の順序を指定できます。
- **安定したページング**：ROW_NUMBER()を使用することで、データの変動があっても行番号に基づいて正確にページングできます。

## 実際の適用例

### シナリオ

- ユーザー登録情報を管理画面で表示する。
- 登録日の昇順でページングし、各ページ内ではスコアの降順でユーザーを表示する。
- 1ページあたり20件表示する。

### SQLクエリ

```sql
SELECT
    user_id,
    registration_date,
    score
FROM (
    SELECT
        user_id,
        registration_date,
        score,
        ROW_NUMBER() OVER (ORDER BY registration_date ASC) AS row_num
    FROM
        users
) sub
WHERE
    row_num BETWEEN (:page - 1) * 20 + 1 AND :page * 20
ORDER BY
    score DESC;
```

- :pageには表示したいページ番号を指定します。

### クエリのポイント

- **行番号の計算**：ROW_NUMBER()で行番号を付与し、ページングの範囲を正確に指定します。
- **表示順序の指定**：外側のORDER BYでスコアの降順を指定し、ページ内の表示順序を制御します。

## 注意点とベストプラクティス

### インデックスの活用

- パフォーマンス向上のため、registration_dateとscoreに適切なインデックスを設定することをおすすめします。

### データベースの対応状況

- ROW_NUMBER()とOVER句がサポートされているか確認しましょう。主要なデータベース（MySQL 8.0以降、PostgreSQL、SQL Server、Oracleなど）ではサポートされています。

### データの一貫性

- データの変更による影響を考慮し、必要に応じてトランザクションやデータのスナップショットを使用して、一貫性のある結果を提供します。

## まとめ

OVER句とウィンドウ関数を活用することで、データの取得順序と表示順序が異なる場合でも、正確で効率的なページングを実現できます。これにより、ユーザーにとって使いやすい画面を提供でき、ビジネス要件にも柔軟に対応できます。


## おわりに

画面のページング実現のためにOVER句を使った方法をご紹介しました。データベースの機能を最大限に活用し、効率的なデータ取得と柔軟な表示を実現しましょう。

ご質問やフィードバックがありましたら、お気軽にコメントしてください！
プリザンターのDBバックアップを他環境にリストアした時に_rdsが実行出来ない時の対処法

:::note info
本記事はSQL Server限定となります。MySQLやPostgreSQLの場合はこの方法は使えません。
:::

## はじめに
サーバ移行などで、バックアップしたDBを別環境にリストア後、`Implem.CodeDefiner.dll _rds`を実行すると、`'Implem.Pleasanter_Owner' はログインできませんでした。`と表示されるときの対処法です。
2024/12/01現在、公式マニュアルに記載されている方法は今後非推奨となる方法が含まれている＆対応しきれないので、こちらの方法を使う方がすんなり対応出来ます。

## ユーザ情報を調べる
`Implem.Pleasanter_Owner`と`Implem.Pleasanter_User`が孤立ユーザになっているのが原因なので、まずは孤立ユーザを調べます。
SSMSなどで下記のコマンドを実行します。
```sql
USE [master];
SELECT dp.type_desc, dp.sid, dp.name AS user_name  
FROM sys.database_principals AS dp  
LEFT JOIN sys.server_principals AS sp  
    ON dp.sid = sp.sid  
WHERE sp.sid IS NULL  
    AND dp.authentication_type_desc = 'INSTANCE';  
```
`Implem.Pleasanter_Owner`と`Implem.Pleasanter_User`の2レコードが表示されると思います。
ここで重要なのはSIDです。SIDをメモしてください。

## ユーザを新規で作ってSIDで紐付け
前項の方法で取得したSIDを使って、新規でユーザを作成しリストアしたDBに含まれるユーザ情報と統合します。
```sql
USE [master];
CREATE LOGIN [Implem.Pleasanter_Owner]
WITH PASSWORD = <Rds.jsonに記載しているImplem.Pleasanter_Ownerのパスワード>,  
SID = <取得したImplem.Pleasanter_OwnerのSID>;
CREATE LOGIN [Implem.Pleasanter_User]
WITH PASSWORD = <Rds.jsonに記載しているImplem.Pleasanter_Userのパスワード>,  
SID = <取得したImplem.Pleasanter_UserのSID>;
```
これで完了です。再度`Implem.CodeDefiner.dll _rds`を実行してみてください。
【論文読み】日本企業データを用いた機械学習による利益変化の予測

## はじめに
こんにちは。論文を読んだ結果の紹介記事です。  
今回紹介するのは、「システム健全性管理のための時系列処理の課題とアプローチ」という論文です。  

- タイトル： システム健全性管理のための時系列処理の課題とアプローチ
- 出典： 人工知能学会第二種研究会資料/2024 巻 (2024) SMSHM-001 号
- URL： https://www.jstage.jst.go.jp/article/jsaisigtwo/2024/SMSHM-001/2024_39/_pdf/-char/ja


## 概要
センサー時系列処理の課題とその解決アプローチを概観する。


## 特徴
- センサー時系列の特徴
    - 画像が同質な二次元で平行移動不変性をもつのに対して、次元毎に不均質で次元の順序には意味がない
    - 時間的な多様なスケール
    - 物理/化学法則が必要なサンプリング周期依存性
    - センサ値の変動パターン（何がノイズで何が信号であるかは対象の物理やセンサーの機能から決まる、など）
    - 運転者の意図に従った操作系列によるレジーム変化
    - 新たなデータの観測に伴い結果を修正していく必要があるオンライン性

- 時系列処理のアプローチ
    - フーリエ解析に代表される基底関数展開アプローチ
        フーリエ解析は、振動データのように、時系列を生成する方程式の解がフーリエ級数で近似的に表現できる場合に向いている
    - ARモデルに代表されるシステム同定アプローチ
        適切な窓サイズがわかっている定常データに適する
    - 単語の出現傾向や並びで時系列を表現するボキャブラリアプローチ
        時系列のMotif発見、異常検知、セグメンテーションなどに応用
    - Spikeletアプローチ
        時系列をスパイク状のパターンに分解して、スパイクの並びの類似性を用いて、Motifを抽出する。
        基本的なアイデアは、「時系列の山と谷を照合するパスは、DTW 距離が小さくなる」に注目して、時間方向に同じ長さのセグメントを切り出すのではなく、値方向の変動に応じた時間幅を切り出すことにある。


## 想定される適用例
- センサー時系列の分析全般
- 異常検知や寿命予測など


## 参考
- [システム健全性管理のための時系列処理の課題とアプローチ](https://www.jstage.jst.go.jp/article/jsaisigtwo/2024/SMSHM-001/2024_39/_pdf/-char/ja)