OmniAICreator/Qiita-1.07M huggingface dataset:
【分散処理】RownumberとWindows関数の備忘のメモ

下記のようなWindow関数に対して、Pysparkで書く場合の備忘メモを残します。

```SQL.sql
SELECT
  *,
  ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS row_num
FROM employees;
```

pysparkにすると下記のような形になります。
これはつまり、Window関数を呼び出して、ナンバリングしてるってわけ。

```python.py
# 3. ウィンドウ定義（部署ごとに分けて、給料で降順に並べる）
window_spec = Window.partitionBy("department").orderBy(df["salary"].desc())

# 4. row_numberを追加
df_with_rownum = df.withColumn("row_num", row_number().over(window_spec))
```
ここでoverはこの範囲でWindow関数を適用するという意味で、row_numberを適用する範囲を決めています。

　ちなみにこのような処理の裏ではSparkの分散処理によって複数のノードで分散処理が実施されています。
【Claude × Slack】 MCPでナレッジ検索を試してみる

# はじめに

こちらの記事の続きです！

https://qiita.com/does_not_exist/items/47a072bd723cb0361a93


# 試してみた

Slackに質問メッセージを投稿し、各メッセージのスレッドに回答を投稿します。

![スクリーンショット 2025-04-16 22.49.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/0e39b318-61ed-4686-a948-e2acd7256a10.png)

このメッセージに対する回答を取得するような質問をしてみます。

```
とあるシステムで、ユーザーがパスワードを3回間違えたらアカウントがロックされる仕様になっています。このロックを自動解除するにはどうすればいいですか？
```


```
#testチャンネルに対して以下の質問に類似するメッセージを探し、
そのスレッドのメッセージを回答として出力してください

アカウントロックされました、どうすればいいですか
```


![スクリーンショット 2025-04-16 22.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/7ba12522-e01d-498e-aecc-1829156e9b88.png)

スレッドの回答を入れ替えて投稿していたのですが、それも判定されました！

![スクリーンショット 2025-04-16 22.55.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/93a8d7b7-864e-483a-9333-839705c3225a.png)

次はもう少し複雑な文章で試してみます。
文章の書き方は似ているが、様々な単語が使われていて、一部共通の単語もあるような文章にしてみました。


![スクリーンショット 2025-04-16 23.15.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/b50a89a1-aee8-4a88-b13e-ace3073ba00f.png)

このメッセージに対する回答を取得したいです。

```
とある業務システムの刷新にあたり、クラウドサービスの導入を前提とした運用設計を初期フェーズから進めています。可用性やスケーラビリティの確保に加えて、運用負荷の軽減やインシデント対応の標準化といった観点も重要視していますが、この段階で意識すべき設計上の優先事項について、ご教示いただけますでしょうか。
```

```
#testチャンネルに対して以下の質問に類似するメッセージを探し、
そのスレッドのメッセージを回答として出力してください
A社でクラウドサービスの導入を検討しています、まずやるべきことはなんですか
```

すごい、的確に回答を返してくれました。

![スクリーンショット 2025-04-16 22.53.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/c6e76153-feeb-4b7c-89ad-439bd4936aa9.png)


# おわりに
データ数を増やして試してみたいですね。
ナレッジ検索における類似文検索の実装が不要になりそうな期待があります。
Linuxはじめました

私はLinux自体は2000年くらいから触っていましたが、それまではセットアップして満足する程度で全然使っていませんでした。

2024年頃からMicrosoft(Windows)の動きがいろいろと怪しいのと、今のサービスはほとんどWEBアプリが主体になっているため、Windowsにこだわる必要もなく、Linuxを本格的に使い始めてみることとしました。

あと業務で必要となるOfficeにおけるLibreOfficeが、随分安定しているようで、アップデートもこまめに行われているので、Officeの心配もなさそう。

とりあえず空いてるPCとノートPCにUbuntuを突っ込み、先駆者の様々な情報やお知恵をお借りし、いろいろと操作を試していきます。

私が提供できる情報は皆無ですが、備忘録として記録を残してみたい所存。

不定期のノンビリペースですが、どうぞよろしくお願いします。

なお、明日はUbuntu 25.04の公開とかなんとか。24.04を入れちゃったよ。
Nest.js　その１　main.ts

＜サーバーサイドの流れ＞
1. main.ts


```typescript
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { ValidationPipe } from '@nestjs/common';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useGlobalPipes(new ValidationPipe());
  app.enableCors({
    origin: 'http://localhost:3000', // Next.js のフロントエンドのURL
    credentials: true, // Cookieの送受信を許可
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], // 許可するHTTPメソッド
    allowedHeaders: ['Content-Type', 'Authorization'], // 許可するヘッダー
  });
  await app.listen(process.env.PORT ?? 8000);
}
bootstrap();
```
<br><br>Nest.jsの開始
このコードがAppの始まり。これがないと始まりません。
```typescript
const app = await NestFactory.create(AppModule);
```



<br><br>AppModuleの中身
AppModuleが大枠。その中にUserModuleなど必要なものをインポートしていく。

```typescript
imports: [
    UserModule,
    TodoModule,
    NewsModule,
    TypeOrmModule.forRoot(AppDataSource.options),
  ],
  ```

<br><br>リクエスト(フロントエンドからバックエンドに情報を渡す時）のバリデーション（入力チェック）をアプリ全体で有効にする設定
間違えていたら自動でエラーを返してくれる。
```typescript
app.useGlobalPipes(new ValidationPipe());
```


<br><br><br>他のドメイン（例：Next.js）から NestJS API に通信を許可するため。
<br>CORSとは
異なるドメイン間での通信を解除するために必要
```typescript
app.enableCors({
    origin: 'http://localhost:3000', // Next.js のフロントエンドのURL
    credentials: true, // Cookieの送受信を許可
    methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], // 許可するHTTPメソッド
    allowedHeaders: ['Content-Type', 'Authorization'], // 許可するヘッダー
  });
  ```

  <br><br><br><br>NestJS アプリケーションで サーバーを起動してポートを指定して待ち受けるために必要なコード
<br>await app listen(...)
NestJS サーバーを起動してリクエストを受け付けるため
これを呼び出さないと外部からのアクセスに応答しない
main.tsの最後に１回だけ書く
await を付けることで、アプリが完全に起動するまで次の処理に進まないようにしてる。

<br>process.env.PORT
envファイルや環境変数に設定された PORT の値を読み取る。
.env に PORT=3000 と書いてあれば、3000番ポートで起動
?? 8000
PORT が undefined（未定義）や null の場合に 8000番ポートを使う（Null合体演算子）

undefinedになる時
envファイルにPORTがないとき
.env を読み込んでいない
実行環境で PORT を設定していない

nullになる時
process.env.PORT が null になるのはまれですが、明示的に null を代入した場合のみ
PORT=null node dist/main.js
ただし環境変数はすべて「文字列」として扱われるので、
上記の場合は実際には "null"（文字列）として読み込まれます。
  ```typescript
  await app.listen(process.env.PORT ?? 8000);
  ```

<br><br>定義した bootstrap 関数を実行するために書く。
通常 main.ts ファイルに書かれている。
```typescript
  bootstrap();
  ```
WindowsにRedmine6をセットアップ

Webサーバの性能を考えますと、Redmineは、Linux に準備すべきと思うのですが、どうしても、Windowsサーバを使いなさいとの指示で、勉強してみました。
以前、Linux（debian想定）に準備したときの資料を参考にします。
[RaspberryにRedmine6を立てる](https://qiita.com/MasahiroShouya/items/b49929443d5aaab3d72c "以前の記事")

**Postgres**
ダウンロードして、Installしましょう
https://www.postgresql.org/download/windows/
※何を使うにしても、新しいバージョン程、望ましいと思いますが、セットアップするRedmineが対応しているかも重要です。（私は17で作業しています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/7e72070e-0d04-4b53-aec7-904072e730d0.png)

Install作業は、概ね、デフォルトのままで問題ありません。
インストールが終わると、「pgAdmin4」という管理画面機能がありますが、
「SQL Shell (psql)」という機能も用意されており、Linuxのコマンド操作に慣れている方は、こちらが御勧めです。
という事で、私は後者のコマンド作業です。
CREATE ROLE redmine LOGIN ENCRYPTED PASSWORD 'password' NOINHERIT VALID UNTIL 'infinity';
※個人的には見慣れないオプションがあるので解説です
　　ENCRYPTED: 指定されたパスワードが暗号化されて保存されます
　　NOINHERIT: 権限を自動的に継承せず、GRANTコマンドで権限を付与する必要あり
　　VALID UNTIL 'infinity': パスワードの有効期限が無期限です
CREATE DATABASE redmine WITH ENCODING='UTF8' OWNER=redmine;
redmine用のロールを作成し、データベースも作成します。

**Ruby**
ダウンロードして、Installしましょう
https://rubyinstaller.org/downloads/
Redmine6のrubyの対応は、3.3がmaxのようでした。
Install作業は、概ね、デフォルトのままで問題ありません。最後に、MSYS2のSetUpを行うようにしましょう。
MSYS2のセットアップ画面は、DOS窓になってます。とりあえず、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/f1488d69-469f-4b57-b9b8-6c9adb7e6ceb.png)
１．base installation
２．system update
の２つを順に実行しておきましょう。

**Redmine**
ダウンロードして、解凍しましょう
https://www.redmine.org/projects/redmine/wiki/Download
データベースの設定ファイルを更新しましょう
```diff_conf:…redmine/config/database.yml
production:
  adapter: postgresql
  database: redmine
  host: localhost
  username: redmine
  password: "password"
  encoding: utf8
```
PowerShellを管理者で実行します。
カレントディレクトリをredmineのホームへ変更して、順にコマンドを実行します。
gem install bundler
bundle install
bundle exec rake generate_secret_token
bundle exec rake db:migrate RAILS_ENV=production
bundle exec rake redmine:load_default_data RAILS_ENV=production

**起動して確認**
$env:RAILS_ENV="production"
bundle exec puma -p 3001
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/ab0bd059-3836-45b2-9d45-3baf91209f93.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3878922/028fb118-3431-4f09-9a65-2856af7d59aa.png)


※以前のRedmineのバージョンでは、Webサーバはwebricが用意されていました。
ただ、webricは、シングルスレッドで動作するため、同時リクエストの処理能力が低く、採用されなくなったのかなぁ...と。
現在採用されているのは、「puma」なのですが、windowsでは並行処理モードがサポートされず、並行処理能力が制限されています。　（これが冒頭のLinuxが良いと感じる理由です）
ちなみに、webサーバの設定を変更したい場合は、Redmineホームの「config.ru」を編集しましょう。

対応例）RestAPIで他のWebに利用したい場合の、「CORS」エラーへの対応
① Redmineのホームの「Gemfile」の最終行に、「gem 'rack-cors'」を追加
② bundle install
③ Redmineのホームの「config.ru」を編集　（utf8で更新しましょう）
```diff_conf:…redmine/config.ru
require_relative 'config/environment'
require ::File.expand_path('../config/environment',  __FILE__)
require 'rack/cors'
use Rack::Cors do
  allow do
    origins 'http://localhost:3000'   # RestAPIを利用するサイト
    resource '/users.json', :headers => :any, :methods => [:get, :post, :options]   # 許可するリソースとHTTPメソッドを指定
  end
end
run Rails.application
```
以上の作業後、Redmineを再起動する事で、CORSエラーが解消します。

お疲れさまでした～。
C_TS422_2023 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（8/100）

【8日目】
トピック 2：SAPS/4HANA生産計画の概要（2/5）

≪問題8≫
生産の作業期間を決定するデータはどこで設定しますか。
（２つ選択）
□部品表/配合表（BOM）
□作業手順
□作業区
□品目マスタ

≪解答≫
□部品表/配合表（BOM）
■作業手順
■作業区
□品目マスタ

≪解説≫
生産における作業期間は、作業手順（Routing）と作業区（WorkCenter）に設定されます。これらのデータにより、各工程に必要な時間が定義され、生産スケジュールが最適化されます。
How to Change the Root Directory of Jupyter Notebook (on Windows with Anaconda)


## Introduction

As a part of customizing my development environment, I configured Jupyter Notebook to start in a specific working directory on Windows using Anaconda.  
This hands-on setup involved manually editing the `jupyter_notebook_config.py` file and deepened my understanding of Python environments and configuration files.  

Documenting this process in English allows me to share practical know-how with beginners and contribute to the community. This also demonstrates my ability to troubleshoot setup issues and tailor environments to project needs.

## Step-by-Step
If "TLyticsInsight" is the PC username, the default location for Jupyter Notebook is the following directory:  
`C:\Users\TLyticsInsight\.jupyter\jupyter_notebook_config.py`

1. Create the folder you want to set as the root for Jupyter Notebook  
    1. Open Anaconda Prompt, navigate to the folder you want to set as the root, and run the following command to generate the configuration file:  
       ```bash
       jupyter notebook --generate-config
       ```  
       This will generate the configuration file `jupyter_notebook_config.py` for Jupyter Notebook.

2. Change the root directory  
    1. Open the configuration file in an editor  
        - Open the `jupyter_notebook_config.py` file with a text editor (e.g., Notepad or VSCode).  
    2. Edit the settings to change the directory  
        - Look for the setting `c.NotebookApp.notebook_dir` in the configuration file.  
        - If you cannot find it, add the following line at the very bottom of the file.  
        - To change the directory to a new path (e.g., `C:\Users\TLyticsInsight\Documents\JupyterNotebooks`), write:  
          ```python
          # Change the default working directory
          c.NotebookApp.notebook_dir = r'C:\Users\TLyticsInsight\Documents\JupyterNotebooks'
          ```  
        - Add the `r` prefix to specify the Windows path without escaping characters.

3. Restart Jupyter Notebook  
After saving the configuration, restart Jupyter Notebook.  
    • How to restart:  
        1. In the Anaconda Prompt, run the following command:  
           ```bash
           jupyter notebook
           ```  
    • With this setup, when you open Jupyter Notebook, the specified folder  
      **`C:\Users\TLyticsInsight\Documents\JupyterNotebooks`** will be the root directory, and you will be able to manage your notebooks from there.
Rider 2025.1で追加された「Debug LINQ expressions」について

C#のLINQメソッドチェインで思った通りの結果にならない時、途中結果を確認できたら便利ですよね。

この投稿ではRider 2025.1から追加された「Debug LINQ expressions」で、LINQのメソッドチェインの途中結果を効率的に確認する方法を紹介します。

* この投稿のスクリーンショットは、Rider 2025.1 RC1のものです
* この投稿では、次の様なコードを使って説明します

```csharp
public static class Program
{
    public static void Main(string[] args)
    {
        var persons = new List<Person>
        {
            new ("田中太郎", 35),
            new ("鈴木花子", 28),
            new ("佐藤一郎", 42),
            new ("山田梅子", 29),
            new ("田中二郎", 32)
        };

        var names = persons
            .Where(p => p.Age > 30)
            .Select(p => p.Name)
            .Order();

        foreach (var name in names)
        {
            Console.WriteLine(name);
        }

    }
}

record struct Person(string Name, int Age);
```

---

LINQの処理をする行でブレークポイントを貼り、デバッグ実行します。すると、「Explore LINQ」というInlay hintsが出てきます。

![スクリーンショット 2025-04-16 22.44.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/c2c9f113-a8f0-4d1d-a706-dde60ad0cfaa.png)


「Explore LINQ」をクリックすると、次の様な「Stream Trace」というタイトルのウィンドウが表示されます。ウィンドウには、データソースとなるpersonsが表示されています。

![スクリーンショット 2025-04-16 22.46.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/30bed6de-0ee4-4d18-a956-985f222cf4ed.png)

次の画像は、Whereタブを選択した状態です。Whereメソッドで選択している様子を確認できます。

![スクリーンショット 2025-04-16 22.46.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/876607c3-ea61-46ff-9fb4-7b2316c6ab3f.png)

次の画像は、Selectタブを選択した状態です。Selectメソッドで射影している様子を確認できます。

![スクリーンショット 2025-04-16 22.46.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/55a0e9bf-b7f7-41fe-b7ad-847a11cd5d4d.png)

次の画像は、Orderタブを選択した状態です。Orderメソッドで並び替えしている様子を確認できます。

![スクリーンショット 2025-04-16 22.46.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/23b964d4-08a9-47ea-88e1-61266cf52c92.png)

「Flat Modeボタン」を押すと、すべてをまとめて表示することもできます。

![スクリーンショット 2025-04-16 22.46.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/bf5ce1c7-f3d3-4923-9935-76821464d9e0.png)

この様に、効率的にRider 2025.1から追加された「Debug LINQ expressions」で、LINQのメソッドチェインの途中結果を効率的に確認できます。


# リンク集

https://www.jetbrains.com/help/rider/Debug_LINQ.html

# 補足

Rider 2025.1 RCでは、Top-level statementsだと「Explore LINQ」というInlay hintsが出てこないかもしれません。（不具合？バグ報告予定です。）

![スクリーンショット 2025-04-16 22.55.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4125/b9e9de4c-6c51-42f2-b09b-c452d3333928.png)
コマンドラインを華やかにしたい

# 初めに
無機質なCUIに疲れた皆さん、こんにちは（あるいはこんばんは）。ターミナルに花を添えましょう。

今回はAAをコマンドラインに表示する方法について紹介します。

# AAの作成
まず、AAを作成します。といっても人力でAAを作成するほど暇ではないので画像からAAを作成するサイトを使用します。

https://tool-taro.com/image_to_ascii/

製作者様が実装についても紹介しているブログがあるので、併せて紹介させていただきます。

https://tool-taro.com/blog/java/230/

言うまでもありませんが、AAを作成する際には行数、列数に注意しましょう。一度にすべてが表示されないと虚しいので。

# 実装

別に難しいことは何もないです。使用しているshellに合わせて次のコマンドを実行するだけです。

```shell
echo [AAのコピぺ] > AA.txt
```
上のコマンドでは、アスキーアートを保存したファイルを作成します。今回は、ホームディレクトリ`~/`に`AA.txt`として保存しています。(各人のお好みのエディタでファイルを作成ください。)

一応確認をしておきましょう。

```shell
$cat AA.txt
  ``  ``   `   `   ``  ``  ` ..-..  `   `   ``  ``
``  ``   `  .<;+<;;;;<-. `.?<1<+?;;;<-.   ``  ``
  ``  `` .(;;;:::;;;>>>><-!   1! ?+>???-`  ```  ``
``  ``  (;;;;;::::;;;>>???1("[    (====>  ``  ``
  ``   (>>>;;;;;;;;;>>>???=l#``.Z4,lllt>`   ``````
``  ``.?>>>>>;;;;;>>>???==lll..MHMtttrv!  ``  `` `
      <?????????>????====lltO_(MM=JwwXXl
      +========?====llllttrwzI<--(OwuWk{
      (ttllllllllllttttrvzuuXI>+?===+f^
       OvrrrttttrrrrrvzuuuuQWC????<1+.
       .OuuzzzzuuuuuXZyZZXX0C   ````_jO.
  ``    `?UZyyyyZyyyyyyyQH0O!````..._(z{`   ``  ``
`` .(>+d&.. ?TUZZZyyWQNM#0O>--_____(+?^   ``  ``
  ,+1+zIXpW.   ` dMMMHMM0tl<:_(+<++=:   `   `` ```
 js+zdXHkbH} `  .ZMMUUIllll++zzlttOZ  `   `` ```
 1vUWWIzwXf`   ` ?1zzzuAwwwwwwwvwVY!`   `  ```  ``
` ?wzzlllZi. `   ` .(7?!~?UW0...---.. `   ``  ``
  `` ?WXOttW&.JdV^ `   .>>>>>;;;<<;;:;:_-... `  ``
``  `` _4wrtXbK^       ;;::<+1zzwAz++<:::::;;;<-
  ``` ``  ?TT7``      (;;>+zwXUXX- ?7I<;::::;>>j&`
``  ``   `   `        ;;>?=OXr`jwz`  .z>++<(;>zzv`
  ``  ``   ``         ;;>>?=zdo-jr  ` Oz1zwAzzvw:`
``  ``   `  `` `   ._(<>++?=llZk+-` ..(wwwSVSOO!
  ``    `.... `` .;:::;;>??==llzvz1Ov{  ?"7?7^  ``
      .(;>>???+.(;;:::;>??====l===??z!
     (;;><~~<???>>++<<+zwllllttllllz>
    .--_~<<<+????zz+??zOktttrrrOtOw>
    (>>>><--<?==lz0wwzzzSvvwwuuwwZ'
  `` _+?????<.?trrIzzZXwwyyZZZZV^   `   `   ``  ``
``  ```_1?????<?rOz???dUvrrwwwdWA<-.. `   ``  ``
  ``  `` _1====1_1l=lzwVVyyyyZZWC?=??<. `   ``  ``
``  ``   ` ?1=ll=<-1Ow74VVyyUZOZ<z~<??>   `` ```
  ``` ``   ` _?1ll=+?! ` ?"UXXZ1zz+?==> `  ```  ``
``  ``   `   `   _~` ``  ``.1wAZI1===v_   ``  ``
  ``  ``   `   `   ``  `` .(+tv1?<+?z!  `   ``  ``
``  ```  `   `   ``  `` .1?=<<<????1> `   ``  ``
  ``` ``   `   `   ``  `.Oz=+(+??==>    `   `` ```
``  ``   `   `   `` ```  jwOtllltv!   `   `` ```
  ``  ``   `   `   `` ``` ~~~~``    `   `   ``  ``
```
可愛いヨッシーを見ることができます。行列のサイズを確認した後、コマンドを決めましょう。ここでは`AA`でヨッシーを表示することにします。
```shell
echo alias AA='cat ~/AA.txt > ~/.bashrc [or .zshrc]'
```

`source`コマンドで設定ファイルを読み込むか、shellを再起動することでコマンドが利用可能になります。

# まとめ
こんなものを上長の前で表示した日には日当たりの良い窓際で日光浴ができることでしょう。。。
Astro 新着記事一覧を最大5件で表示する

ブログのトップページに最新の記事が表示されていると、訪問者が新しい情報をすぐに見つけられて便利です。ここでは、Content Collections APIで管理しているブログ記事の中から、最新の5件をトップページ (`src/pages/index.astro`) に表示する手順を紹介します。

**前提:**

* Content Collections APIを使ってブログ記事 (`blog` コレクション) を管理している。
* 各記事のMarkdownファイルのフロントマターに `pubDate` (公開日) が設定されている。
* 個別記事ページへのURL生成ロジックが確立している

## トップページへの新着記事一覧表示手順

### 1.トップページファイル (`src/pages/index.astro`) を開く

プロジェクトの `src/pages/index.astro` ファイルをエディタで開きます。これがサイトのトップページに対応するファイルです。

### 2.記事データの取得、ソート、件数制限

ファイルの先頭にあるフロントマター部分 (`---` で囲まれたエリア) に、記事データを取得し、並び替えて、件数を絞り込むコードを追加します。

```astro
---
// src/pages/index.astro
import { getCollection } from 'astro:content';
import BaseLayout from '../layouts/BaseLayout.astro'; // 適切なレイアウトを指定

// 1. 'blog'コレクションの記事をすべて取得
const allPosts = await getCollection('blog');

// 2. 公開日 (pubDate) の新しい順に記事をソート
//    new Date() を使って日付として比較する
const sortedPosts = allPosts.sort((a, b) =>
  b.data.pubDate.valueOf() - a.data.pubDate.valueOf()
);

// 3. 最新の5件だけを取得 (sliceを使用)
const recentPosts = sortedPosts.slice(0, 5);

// 4. 個別記事ページへのURLを生成するヘルパー関数 (前の手順で作成したものを再利用または同様のロジックを記述)
function getPostUrl(post) {
  if (post.data.url) {
    // フロントマターにurlがあれば、ルートからのパスを返す
    return `/${post.data.url}/`;
  }
  // なければファイルパスに基づくデフォルトのパスを返す
  return `/blog/${post.slug}/`;
}

// 他のトップページ用データなど...
const pageTitle = "ようこそ！";
---
```
* `getCollection('blog')` で全記事を取得します。
* `sort()` メソッドで `pubDate` を基準に降順（新しいものが先頭）に並び替えます。`valueOf()` または `getTime()` を使って数値として比較するのが確実です。
* `slice(0, 5)` で、ソート後の配列の先頭から5件分の記事データを取り出します。
* 個別記事ページへのリンク生成用に、以前の手順で `src/pages/tags/[tag].astro` や `src/pages/blog/index.astro` で使った `getPostUrl` 関数（または同様のロジック）をここにも記述します。

### 3.記事リストの表示

フロントマター部分の下にあるHTMLテンプレート部分に、取得した `recentPosts` を使って記事リストを表示するコードを追加します。

```astro
---
// --- 上記のフロントマターコード ---
---
<BaseLayout title={pageTitle}>
  <h1>{pageTitle}</h1>
  <p>このサイトのトップページです。</p>

  {/* ↓ ここから新着記事一覧を追加 */}
  <h2>新着記事</h2>
  <ul>
    {recentPosts.map((post) => (
      <li>
        {/* getPostUrlヘルパーでリンク先URLを生成 */}
        <a href={getPostUrl(post)}>{post.data.title}</a>
        <span style="font-size: 0.8em; margin-left: 8px;">
          ({post.data.pubDate.toLocaleDateString()})
        </span>
      </li>
    ))}
  </ul>
  {/* ↑ ここまで新着記事一覧 */}

  {/* 他のトップページのコンテンツ... */}
</BaseLayout>
```
* `recentPosts` 配列を `map()` でループ処理します。
* 各記事 (`post`) について、タイトル (`post.data.title`) と公開日 (`post.data.pubDate`) を表示します。日付は `toLocaleDateString()` などで読みやすい形式に変換すると良いでしょう。
* `<a>` タグの `href` 属性には、ステップ2で用意した `getPostUrl(post)` 関数を使って正しい記事ページのURLを設定します。
* ページ全体を適切なレイアウトコンポーネント (`<BaseLayout>` など) で囲みます。

### 4.開発サーバーで確認

ターミナルで開発サーバーを起動します。

```bash
npm run dev
# または pnpm dev, yarn dev
```

ブラウザでサイトのトップページ (`http://localhost:4321/` など) にアクセスしてください。

「新着記事」セクションが表示され、公開日の新しい順に最大5件の記事がリストアップされていれば成功です。各記事のリンクをクリックして、正しい個別記事ページに移動できるかも確認しましょう。
Nuxt3プロジェクトを作成し、Vuetifyを入れる方法

# Nuxt3のプロジェクト作成

#### ■公式サイト(↓)の手順紙したがって作成する。

https://nuxt.com/docs/getting-started/installation

```
npm create nuxt <project-name>
```

上記のコマンドを入力すると、以降色々聞かれますが、私は下記のように回答しました。

|Nuxt3からのプロジェクト作成にあたっての質問|プロジェクト作成にあたっての回答|
|---------------------------------------|------------------------------|
|どのパッケージ管理ツールを使用するか？    |npm                           |
|Gitを初期化する？(Initialize git repository)|Yes                       |
|ツールは何を入れるか？(Would you like to install any of the official modules?)                   |@nuxt/eslint – Project-aware, easy-to-use, extensible and future-proof ESLint integration   |

これでNuxt3プロジェクトは作成できました。

# TypeScriptの導入
つぎに`typeScript`を導入していきます。

導入方法は下記の公式サイトを参考にします。

https://nuxt.com/docs/guide/concepts/typescript

#### Vue-tscとTypeScriptをインストールする
```
npm install --save-dev vue-tsc typescript
```

#### `nuxt typecheck`を実行
```
npx nuxi typecheck
```

これで、`TypeScript`のインストールできました。

# vuetify-nuxt-moduleの導入

https://nuxt.com/modules/vuetify-nuxt-module

`Nuxt3`に`Vuetify`を入れるためには`vuetify-nuxt-module`が必要です。

さっそく導入していきましょう。

```
npx nuxi@latest module add vuetify-nuxt-module
```



# 参考サイト
#### vuetify-nuxt-moduleの公式サイト

https://nuxt.com/modules/vuetify-nuxt-module

#### Nuxt3 で Vuetify3 を使う

https://qiita.com/mml/items/9936471c551ee3f15218

#### Vuetifyのコンポーネント

https://vuetifyjs.com/en/components/file-inputs/#usage
Symbolの証明書を見るスクリプト


インストール済だとは思いますが OpenSSL が必要です。

CA 証明書と Node 証明書のどちらも参照できます。

```bash:check_certs.sh
#!/bin/bash

set -e

# 引数チェック
if [ $# -lt 1 ]; then
    echo "Usage: $0 <host> [port]"
    exit 1
fi

HOST="$1"
PORT="${2:-7900}"  # デフォルト7900

# 一時ディレクトリ作成（trapで自動削除）
WORKDIR=$(mktemp -d)
CERTFILE="$WORKDIR/all_certs.pem"

# スクリプト終了時に一時ファイル削除
cleanup() {
    rm -rf "$WORKDIR"
}
trap cleanup EXIT

# 証明書チェーンを取得
echo | openssl s_client -showcerts -connect "${HOST}:${PORT}" </dev/null 2>/dev/null \
     | awk '/-----BEGIN CERTIFICATE-----/,/-----END CERTIFICATE-----/' > "$CERTFILE"

# 分割
csplit -sf "$WORKDIR/cert" -b "%02d.pem" "$CERTFILE" '/-----BEGIN CERTIFICATE-----/' '{*}' > /dev/null || true

# 各証明書を表示
for cert in "$WORKDIR"/cert*.pem; do
    if [ -s "$cert" ]; then
        echo "===== $cert ====="
        openssl x509 -in "$cert" -noout -text || echo "Failed to read certificate: $cert"
        echo
    fi
done
```

## 使い方

引数にホストを指定してください。

```bash
./check_certs.sh luca.harvestasya.com
```

ポートを変更している場合は、ホスト名に続けてポート番号を指定してください。

```bash
./check_certs.sh rerena.harvestasya.com 7990
```
Python入門 - 学習記録

# Python学習記録
2025.04.16

やったこと
- pythonの基本的な書き方を学ぶ
- リストについて
- 辞書について
- 制御構文ついて

学んだこと
```
print(100 + 2000 + \
      1000)
>>> 3100
```
- \の前後は改行していても1行だと見なされる
- 変数とは値を入れる箱のようなもの
```
x = 'バナナ'
print(x)
>>> バナナ
```
- 変数は上書きされていく
```
x = 'バナナ'
x = 'りんご'
print(x)
>>> りんご
```
- Pythonは変数の型が自動で決まる
- リストとは変数をまとめたもの
- リストの中の1つ1つの値を要素という
- 0から順番、インデックスと呼ぶ
- リストは[]で表す
```
weather = ['sunny', 'cloudy', 'rainy']
```
- リストの中は同じ型でなくても良い
- リストに何も入れないと空のリストが作れる
- リストの要素の数はlenを使う
```
weather = ['sunny', 'cloudy', 'rainy']
ptint(len(weather))
>>> 3
```
- リストの中の要素を取り出したいときはインデックスを指定する
```
weather = ['sunny', 'cloudy', 'rainy']
ptint(weather(1))
>>> cloudy
```
- リストの後ろに要素を追加したい場合はappendを使う
```
weather = ['sunny', 'cloudy', 'rainy']
weather.append('snow')
ptint(weather)
>>> ['sunny', 'cloudy', 'rainy', 'snow']
```
- 要素の削除にはremoveを使う
- リストの結合にはextendを使う
```
x = ['a', 'b', 'c']
y = ['d', 'e', 'f']
x.extend(y)
print(x)
```
- または+でも結合可能　＊新たにリストが作成される
- リストを分割することも可能
```
x = ['a', 'b', 'c', 'd', 'e']
print(x[1:4])
>>> ['b', 'c', 'd']
```
- 辞書型の変数はキーと値がペアになってる
- 辞書を使用するときは{}を使用する
```
x = {'a': 0, 'b':1, 'c':2}
sec = x['b']
print(sec)
>>> 1
```
- 追加も可能
```
x['d'] = 3
```
- 変更も可能
```
x['a'] = 100
```
- 二つの辞書を結合するときはupdateを使う
```
x.update(y)
```
- バーティカルバー(|)を使うことも可能 *Python3.9以降
```
z = x | y
```
- リストと同じく要素数をlenで取得できる
- if, elseを使うと条件分岐可能
```
x = 16
if x >= 10:
    print('10以上')
else:
    print('10未満')
```
- elifでさらに条件分岐が可能
- forで繰り返しが可能
```
x_list = [100, 190, 2980]
for x in x_list:
    x_yen = str(x) + '円'
    print(x_yen)
```
- 辞書の場合はinの後に辞書items()とする
```
x_dict = {'apple': 100, 'banana': 350}
for key, value in x_dict.items():
    text = key + 'は' + str(value) + '円です'
    print(text)
```
- range()は連番の整数を作れる *繰り返す回数が決まっている時に使う
```
for x in range(10):
    print(x)
```
Internxt は Windows だときつい

容量はまったくきつくないし CLI で使っているには問題ないのだが、Windows 用のデスクトップアプリ (Internxt Drive) がどうもいけない。Electron に ffmpeg や clamd が悪魔合体したアプリらしくインストーラーが430MB、起動すれば CPU を50%以上持っていき、しかもまったく同期が進まない。全然ダメ。Linux 版の Drive ではこうした問題はない。Windows と縁を切るにはよいのかもしれない。とはいえこれではだめだろう。
Dojo Tookit のdijit/Dialog


Dojo Toolkit の dijit/Dialog を利用した疑似モーダルダイアログの表示方法について、以下のポイントを確認できます。
1. dijit/Dialog の基本的な使い方
dijit/Dialog は Dojo Toolkit の UI コンポーネントで、モーダルダイアログを簡単に作成できます。
プログラムでインスタンスを作成する場合、以下のように記述します

```Javascript:Javascript
require(["dijit/Dialog", "dojo/domReady!"], function(Dialog){
    var myDialog = new Dialog({
        title: "My Dialog",
        content: "Test content.",
        style: "width: 300px"
    });

    // ダイアログを表示するボタン
    document.getElementById("showDialogBtn").onclick = function() {
        myDialog.show();
    };
});

```

また、HTML の data-dojo-type を使用してマークアップで定義することも可能です。

```HTLM:HTLM
<div data-dojo-type="dijit/Dialog" data-dojo-id="myDialog" title="Sample Dialog">
    <p>ダイアログの内容</p>
    <button data-dojo-type="dijit/form/Button" type="button" data-dojo-props="onClick:function(){myDialog.hide();}">
        閉じる
    </button>
</div>
<button data-dojo-type="dijit/form/Button" type="button" onClick="myDialog.show();">ダイアログを開く</button>

```
2\. dijit/registry を使用したインスタンス管理
dijit/registry を利用すると、ページ内の dijit インスタンスを管理できます。


```Javascript:Javascript
require(["dijit/registry"], function(registry){
    var dialogInstance = registry.byId("myDialog");
    dialogInstance.show();
});

```
この方法を使うことで、DOM ノードから dijit/Dialog のインスタンスを取得し、操作することが可能です。




dijit/Dialog 内に dijit のウィジェットを配置した場合、それらのウィジェットは dijit/Dialog の domNode 内に含まれます。管理のポイントは以下の通りです。

1. dijit/Dialog 内のウィジェットの管理
- dijit/Dialog は DOM に追加された後にウィジェットをパース するため、内部の dijit ウィジェットは 通常通り動作 します。
- dijit/registry を使用すると、ダイアログ内のウィジェットを取得できます。

```Javascript:Javascript
require(["dijit/registry"], function(registry){
    var widgetInstance = registry.byId("myWidget");
    console.log(widgetInstance);
});
```
2\. dijit/Dialog の startup() の影響
- dijit/Dialog を プログラムで作成 した場合、内部のウィジェットは startup() を呼び出すことで適切に初期化されます

```Javascript:Javascript
require(["dijit/Dialog", "dijit/form/TextBox", "dojo/domReady!"], function(Dialog, TextBox){
    var myDialog = new Dialog({
        title: "Sample Dialog",
        content: '<input data-dojo-type="dijit/form/TextBox" id="myWidget" />',
        style: "width: 300px"
    });

    myDialog.startup(); // 内部ウィジェットの初期化
    myDialog.show();
});
```
3\. destroyRecursive() を使用したクリーンアップ
- dijit/Dialog を 削除する際 は、内部のウィジェットも適切に破棄する必要があります。

```Javascript:Javascript
require(["dijit/registry"], function(registry){
    var dialogInstance = registry.byId("myDialog");
    dialogInstance.destroyRecursive(); // 内部ウィジェットも含めて削除
});
```
SAPUI5 BTP Fiori m.tableでgrowing（無限スクロール）を実装する方法


---

# SMARTTABLEでプロパティを設定すると実装できるgrowingをm.tableで実装するとつまったのでまとめました

## はじめに

`SAPUI5`の`SMARTTABLE`では、`growing`プロパティを使えば簡単に「もっと見る」形式のページング（Lazy Loading）が実装できます。

```xml
<SmartTable
    id="smartTable"
    entitySet="Products"
    tableType="ResponsiveTable"
    useExportToExcel="true"
    useVariantManagement="true"
    useTablePersonalisation="true"
    header="Products"
    showRowCount="true"
    growing="true" />
```

このように、`growing="true"` をつけるだけでスクロールや「もっと見る」ボタンによるロードが可能です。

しかし、`m.Table`で同様の挙動を実装しようとしたときに、思ったより手こずったので、その方法と詰まったポイントをまとめます。

---

## 前提

- UI5 バージョン: 1.108
- 使用コンポーネント: `sap.m.Table`
- データ取得方法: OData V2（`JSONModel`でも応用可）

---

## m.Tableでgrowingを実装する基本

### まずは基本のm.Table定義

```xml
<Table
    id="productTable"
    growing="true"
    growingScrollToLoad="true"
    items="{
        path: '/Products'
    }">
    <columns>
        <Column>
            <Text text="Product ID" />
        </Column>
        <Column>
            <Text text="Name" />
        </Column>
    </columns>
    <items>
        <ColumnListItem>
            <cells>
                <Text text="{ProductID}" />
                <Text text="{Name}" />
            </cells>
        </ColumnListItem>
    </items>
</Table>
```

ここで重要なのは以下の2つのプロパティ：

- `growing="true"`：growing機能を有効にする
- `growingScrollToLoad="true"`：スクロールで自動ロード（falseの場合は「もっと見る」ボタン）

---

## 詰まったポイント

### 1. growingが効かない！

最初にgrowingを設定してもうまく機能せず…。

#### 原因：
- バインディング先が静的データだった（growingは基本的にバックエンドとの連携で効果を発揮）
- `growingThreshold`が設定されていなかった
- Modelに設定したデータ量が少なすぎた（そもそもgrowingする必要がなかった）

#### 対処：
- 適切なデータ件数（例：50件以上）を用意
- `growingThreshold`を明示的に設定

```xml
growingThreshold="20"
```

---

### 2. テーブルが更新されない

スクロールしてもデータが増えない…。ロードのトリガーが発火しない。

#### 原因：
- コントローラー側でデータの追加ロード処理を書いていなかった
- Modelに全部のデータを最初から読み込んでいた

#### 対処：
- ODataの場合、`$top`や`$skip`パラメータでサーバーから段階的に取得
- `onUpdateFinished`イベントなどで状態を確認

---

## まとめ

- `SmartTable`は非常に便利だが、自動で色々やってくれる分「ブラックボックス」的な部分もある。
- `m.Table`は手間はかかるけど、細かく制御したいときには柔軟。
- `growing`を有効にするには、データの準備とバインディング方法が非常に重要。

---

## おまけ：JSONModelでのgrowing例

```js
onInit: function () {
    var oData = {
        Products: []
    };

    for (var i = 0; i < 100; i++) {
        oData.Products.push({
            ProductID: i + 1,
            Name: "Product " + (i + 1)
        });
    }

    var oModel = new JSONModel(oData);
    this.getView().setModel(oModel);
}
```

これでスクロールに応じて読み込みが行われるようになります。

---

## さいごに

`m.Table`で`growing`を使うには、いくつかハマりどころがありますが、仕組みがわかれば`SmartTable`よりも柔軟に使える場面が増えます。  
この記事が誰かの「ハマりポイント回避」に役立てば幸いです！

---
AutoHotkeyが動かなくなった

### ahkが急に動かなくなった時に確認することの一つ

ブロックを一行で記述しようとすると動かない。
エラーがでず、実行もされないため非常にわかりにくい。

```ahk
; sc07B & d::{ MouseMove A_ScreenWidth // 2, A_ScreenHeight // 2, 0 } ; NG

sc07B & d::{
    MouseMove A_ScreenWidth // 2, A_ScreenHeight // 2, 0
}
```

PCの再起動とかahkの再インストールも試したけどだめで焦った。

あとこれも↓
https://qiita.com/kerupani129/items/d7894dbf789758f05e12
変換・無変換・カタカナひらがな　のキーはレジストリで変更した方がいいかもしれない。
自ら考え、行動するAI：エージェント型AIがビジネスを再構築する



## 🧠 **自律型AIが変革するビジネスプロセス：実践事例と実装ガイド**

### 1. 📌 はじめに：AIは「命令される存在」から「自律的なエージェント」へ

これまでのAIは、与えられたタスクを「決められた通りにこなす」ツールにすぎませんでした。しかし、**自律型AI（エージェンティックAI）**の登場によって、AIは自ら判断し、目標達成のためにタスクを分解・実行・調整する“行動主体”になりつつあります。

企業がこのAIを活用すれば、業務プロセスの**効率化・自動化・再構築**が可能になります。

> 💡 実際に私がで関わったプロジェクトでも、営業レポートの自動生成、障害対応プロセスの自動最適化に自律型AIを活用し、大幅な工数削減と品質向上を実現しました。

---

### 2. 🚀 自律型AIの仕組みとは？

自律型AIは、大きく以下のコンポーネントで構成されます：

- **目標設定（Goal Setting）**：人間が「こうなってほしい」という目的を与える。
- **タスク分解（Task Planning）**：目的を達成するために必要なタスクを自動で分割。
- **アクション実行（Tool Use）**：APIやデータベース、社内ツールを使ってタスクを実行。
- **状態認識・自己調整（Memory & Feedback）**：進捗や失敗を把握し、必要に応じて修正。

> 📌 よく使われるフレームワーク例：
> - **LangChain + OpenAI Function Calling**
> - **AutoGPT / AgentGPT**
> - **CrewAI / AutoGen (マルチエージェント対応)**

---

### 3. 🛠️ 実装例：営業レポートの自動生成エージェント（LangChain + GPT-4）

#### 📎 ユースケース概要：
毎週の営業レポート作成を人手でやると工数が大きく、ヒューマンエラーも多い。→ GPT-4 + LangChain を使って、自動でデータ集計＋分析＋レポート出力まで行うエージェントを構築。

#### ✅ 使用技術：
- LangChain (Python)
- GPT-4 API
- Google Sheets API
- Streamlit（UI）

#### 🔧 コード概要：

```python
from langchain.agents import initialize_agent, Tool
from langchain.llms import OpenAI
from langchain.tools import GoogleSheetsTool, PythonREPLTool

llm = OpenAI(temperature=0.3)

tools = [
    GoogleSheetsTool(credentials_path="credentials.json"),
    PythonREPLTool()
]

agent = initialize_agent(
    tools=tools,
    llm=llm,
    agent="zero-shot-react-description",
    verbose=True
)

agent.run("営業チームのKPIをGoogle Sheetsから取得して、週次レポートを生成してください。")
```

> 🖼️ *[Hình ảnh minh họa luồng xử lý: mục tiêu → tác vụ → truy cập dữ liệu → tạo báo cáo]*

---

### 4. 💡 実務でのTipsと落とし穴

#### ✅ 成功のためのポイント：
- **制約条件の明確化**：AIに「何をしてよくて、何をしてはいけないか」を明示する
- **トークン制限とAPIコスト**：長期記憶や複雑な推論を多用するとすぐにコストが膨らむ
- **ツール信頼性**：外部APIとの連携部分はtry-exceptで堅牢に構築

#### ⚠️ よくある失敗：
- タスク設計が曖昧 → AIが迷走する
- 実行エラー時のリカバリー設計がない → システムが止まる

---

### 5. 🔄 応用展開：マルチエージェント＋外部データ連携へ

以下のような拡張も可能です：

- 🧑‍🤝‍🧑 **複数エージェントの協調作業（例：営業＋経理）**
- 📡 **社内DB・Notion・Slackとの連携によるタスク統合**
- 📅 **スケジューラ連携による定期自動処理**

---

### 6. ✅ まとめ：自律型AIがもたらす未来

| メリット | デメリット |
|----------|------------|
| タスクの自動実行・自己最適化 | 設計の難しさ・不透明な振る舞い |
| 人的コストの削減 | APIコスト・制御の複雑さ |
| 柔軟性・汎用性の高さ | セキュリティ設計の必要性 |

自律型AIは、単なる自動化を超えて、**ビジネスの「頭脳」となりうる存在**です。今後の業務設計において、こうした“考えるAI”の導入は避けて通れない時代が来ています。
pgadminキャプチャ

ダッシュボード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138626/f047b229-d0ae-463b-84e8-514a426e370c.png)
◾️セッション情報

現在サーバーに接続しているセッション数やユーザー数を表示します。
どのユーザーがデータベースを使用しているかを確認可能。

◾️クエリの状況

実行中のクエリや最近実行されたクエリを一覧表示。
パフォーマンスに影響している長時間実行されているクエリを特定。

◾️統計情報

データベース内のテーブルごとの行数、サイズ、トランザクション数。
インデックスの使用状況やクエリのヒット率を確認。

◾️リソース使用状況

CPUやメモリの使用率を監視し、サーバーの負荷状態を把握。
ディスクI/Oやキャッシュの効率性も確認可能。

◾️エラーログと通知

サーバーやデータベース内で発生したエラーや問題をリアルタイムで表示。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138626/12d3506d-3c2d-496c-a07f-57ebbfe44d7e.png)
プリペアトランザクション（Prepared Transaction）は、PostgreSQLなどのデータベース管理システムで、分散トランザクションや長期間ロックを保持するような特殊な状況で使用されるトランザクションの一形態です。"二段階コミット"（Two-Phase Commit, 2PC）プロトコルを活用しており、一部の操作を一旦「準備状態」にしておくことで、安全性と整合性を保ちながらトランザクションを完了できます。

実行計画を確認
問題のあるクエリを再実行して実行計画を確認（A5でもできる）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138626/1728161a-46f3-4a58-9de5-7a1a68865110.png)
必要な場合はanalyzeもできる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138626/1173f27b-b0e0-42b8-b7c3-3d38d25a9592.png)
クエリの状況
実行中のクエリや最近実行されたクエリを一覧表示。
パフォーマンスに影響している長時間実行されているクエリを特定。
【📸マルチモーダルAI 】🧠 自律型AIとは何か？エージェンティックAIの核心とその進化する可能性


---

# 🧠 自律型AIとは何か？  
## ─ エージェンティックAIの基本概念と進化する知能の可能性

---

## 1. 🔍 はじめに：ChatGPTの次は何か？

近年、ChatGPTなどの大規模言語モデル（LLM）が急速に普及し、自然言語の理解と生成能力が飛躍的に向上しています。しかし、**「能動的に行動し、タスクを自己完結できるAI」**が次の大きなパラダイムであると、私たち現場のエンジニアたちは感じ始めています。

それがまさに、**エージェンティックAI（Agentic AI）＝ 自律型AI**というコンセプトです。

---

## 2. 🧠 エージェンティックAIとは？

エージェンティックAIとは、「目的を与えられると、自ら考え、行動計画を立て、必要なツールを使いこなし、最終的にタスクを完了させるAI」です。

これは、従来の「プロンプト→応答」型のAIとは明確に異なります。

### 🔑 特徴：
- **目標志向（Goal-Oriented）**
- **計画的行動（Planning and Reasoning）**
- **ツール使用（Tool Integration）**
- **メモリ活用（Memory Management）**

例えば、「競合他社の最新プロダクト情報を調べ、表にまとめて」という指示を出せば、ブラウザを使って調査し、Google Sheetsに整理し、PDFで報告するところまでを**自律的に**やってくれる、という世界です。

---

## 3. 🛠️ 実装例：LangChain + OpenAI API を使ったエージェントの構築

ここでは、最もシンプルな構成でエージェントを構築してみましょう。

### ✅ 使用スタック：
- `Python`
- `LangChain`
- `OpenAI API`
- `DuckDuckGo Search Tool`
- `Pandas` / `Text-to-Markdown`

### 📄 サンプルコード（要点抜粋）：

```python
from langchain.agents import initialize_agent, Tool
from langchain.llms import OpenAI
from langchain.tools import DuckDuckGoSearchRun

search = DuckDuckGoSearchRun()
tools = [Tool(name="Search", func=search.run, description="Use for web search")]

llm = OpenAI(temperature=0.5)
agent = initialize_agent(tools, llm, agent="zero-shot-react-description", verbose=True)

agent.run("最新のAIスタートアップ3社を調べて、特徴を比較してください。")
```

🧪 これを実行するだけで、LLMが検索→要約→比較表作成までを「考えながら」実行します。

---

## 4. ⚠️ よくある課題とTips

### ❗ 問題点：
- **Hallucination（事実ではないことを生成）**
- **長時間の対話における「文脈忘却」**
- **外部ツール統合時のエラー処理が難しい**

### 💡 解決のヒント：
- Agentに「再確認」「検証」「複数視点で分析」といったChain of Thoughtを追加する
- `Memory`オブジェクトを活用し、会話履歴を保持する
- エラー処理に対してFallbackルールを用意する

---

## 5. 🚀 応用例と今後の可能性

| 業界 | ユースケース | エージェントの役割 |
|------|--------------|-------------------|
| マーケティング | 市場分析 & コンテンツ生成 | 自動レポート作成、ブログ下書き |
| エンジニアリング | GitHub Issue対応 | コード参照、提案の自動作成 |
| カスタマーサポート | FAQ・チケット対応 | チャット履歴分析、自動返信 |

今後は、**マルチモーダル対応のエージェント（画像・音声含む）**や、**クラウド上で連続実行可能なエージェントOS（例：Auto-GPT, Agent-LLM）**の発展が注目されています。

---

## 6. 🧭 まとめ

| 項目 | 内容 |
|------|------|
| メリット | タスクの自動化、人的リソース削減、複雑作業の効率化 |
| デメリット | 安定性、セキュリティ、法的リスク |
| 展望 | エージェントの民主化と「AIに指示するだけの仕事」の実現 |

---

## 📌 最後に

自律型AIは、単なるバズワードではなく、**実務で既に使える段階に入ってきています**。これを「ツール」としてだけでなく、「同僚」として使う時代が、すぐそこに来ているのです。

---
Git-ブランチを切るときにその前につける修飾子

| Prefix | Meaing |
|----------------|----------------------------------------------|
| `feature/`     | 新しい機能の追加用ブランチ。例: `feature/login-ui` |
| `bugfix/`      | バグ修正用のブランチ。例: `bugfix/fix-login-crash` |
| `refactor/`    | 機能もバグも変えず、コードだけをキレイにする用のブランチ。例: `refactor/split-player-class`|
| `hotfix/`      | 緊急で本番環境に修正を入れるとき。例: `hotfix/memory-leak` |
| `release/`     | リリース前の調整や検証のためのブランチ。例: `release/v1.0.0` |
| `chore/`       | 細かい修正・リファクタ・依存関係のアップデートなど。例: `chore/update-eslint` |
| `test/`        | テスト用ブランチ。例: `test/experimental-ui` |
| `doc/`         | ドキュメントの修正。例: `doc/readme-update` |
#プログラミング #Javascript # バグネタ

自分のバグを生みそう・生んだもの。

なんかエンジン(Chrome)や言語のバグのような気もするけど。。。
※仕様。(記事コメントより)
　ただ、そうなると仕様の意図がわからんな。
　それじゃ配列にする意味がないだろうに:sweat_smile:
とりあえずこれはChrome上だけど、多分Node.jsとかでも同じになる気がする。
fillメソッドの引数はforeachとかみたいに毎回実行されるのではなく、最初に用意して使いまわすってことっぽい。
(配列内は同一オブジェクトを参照してる。)

![スクリーンショット 2025-04-16 053056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/eeae9a42-2e22-4abf-a58d-380b1c88fa5d.png)

ちなみにそういう初期化をしようとして更に気づいたのはこれ。
何故かmapメソッドは機能しない。
fillメソッドは「new Array(5).fill～」としても使える。
※fillメソッドは疎配列に対応してるため。(記事コメントより)

![スクリーンショット 2025-04-16 053822.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397476/fd713e75-0ab9-4b41-9bae-73654943a97a.png)

既知だと思うけど、JSの要素が無いことと中身がないことは別のこと。
長さ3のaという配列で、delete a[1]とするとa[1]はundefinedになるが、その要素は存在し、中身が無いだけ。
(要素が存在するという根拠は、aの長さは3のままになるので。)
ただ、a[3]もundefinedになるから、挙動が曖昧な気もちょっとするけど。。。
中身がなくても要素があればfillもmapも機能すると思うんだけどね～。
ま、敢えてなら、mapは「元を利用して」だから、中身も無いとって解釈もできるけど。
掲示板もしくはSNSっぽいアプリのデータモデリング

# はじめに
最近ハッカソンで初めてちゃんとDB設計をしました。開発したアプリ自体は必要最低限の機能に絞っていたので複雑な設計ではないのですが、個人的に学ぶ事が多かったので感想ベースで備忘録としてまとめます。
「初心者がDB設計しようとするとこうなる」みたいな一つの例として参考になれば幸いです。

# アプリの基本機能
### アプリ概要
大学内での豆知識共有サービス。アプリの性質的には掲示板かSNSに近い。
### DBに関わる主な機能
- 豆知識の投稿（タイトル、本文、カテゴリ選択）。本文はNULL許容。
- 豆知識の削除
- 他人の豆知識に対するいいね
- ログイン/ログアウト
- 自分がされているいいね数でランクが上がる

# 詰まった点
### 良いね数によるランク変化の表現方法
方法としては
1. usersテーブルに良いね数カラムを作って、「AさんのユーザーIDに紐づく豆知識」が豆知識テーブルに新たに挿入される度に、usersテーブルのAさんの良いね数カラムが加算され、その値をレスポンスする方法
2. いいね数カラムは概念スキーマ内に作らず、リクエストがくるたびに豆知識テーブルにあるAさんの豆知識の数を一覧取得しレスポンスする方法

の2つを考えました。2個目の方法で良いね数が表現できる時点で、1個目の良いね数カラムは冗長的なデータとなると思います。そのため1個目の方法はDB設計的にあまり適さない方法ですし、豆知識挿入と良いね数加算は同時に行う操作なので、整合性を取るために同一トランザクションに含める必要があり、Typesccriptでのトランザクション管理の学習コストが発生しますが、今回のハッカソンでは概念実証的な感じで開発していたので、「良いね数カラムがあった方がわかりやすいし多少の非整合性は許容してコア機能の開発をしよう」ということで1個目の方法を選びました。

ただ、遅いと言われるJOINを豆知識テーブルを使って算出した良いね数に対して使うことも無さそうなため、あえて良いね数カラム作って非正規化させるメリットもないですし、今思うとそこまで良いね数カラムを設けても嬉しい開発体験は生まれなかったので最初から冗長性は無くしても良かったと思いました。そのため今後はその部分を修正する予定です。
<details><summary>設計時のメモ</summary>

![スクリーンショット 2025-04-16 19.18.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3654936/6b6c8362-8b3d-475e-aaf7-e5867b734f3b.png)
</details>
↑はDB設計の概要をチームメンバー用にドキュメントとしてまとめたものなのですが、ドキュメントとしてまとめると後から当時自分考えていたことを思い出せるので自分にとっても嬉しいことが多く積極的にやるべきだなと感じました。

詳細は以下のNotionリンクにまとめていました。なるべく事前知識のない人でも理解できることを意識したつもりでしたが、改めて読むとわかりにくい部分が多いなと感じます...
[テーブル設計](https://sedate-record-cb9.notion.site/1c6438b6fd09803c8219e312d9cb4175?pvs=4/ "")


# 学んだ点
### 中間テーブルの概念
良いね数という概念で中間テーブルに触れられたのでとてもいい経験になった。

# 今後の方向性（余談）
テーブル構造の今後の変更としては以下
- 上述した良いね数カラムの削除
- カテゴリーは一般ユーザーは干渉できず管理者だけが操作できる存在にしているのですが、現状管理者画面は未実装で管理者権限での豆知識カテゴリーの追加編集削除等はできないので、それができるようにcategoriesテーブルにuser_idというカラムを追加し、そのuser_idにusersテーブルのidを参照する外部キーを設定するなどして管理者画面上でUIでカテゴリーを管理できるようにする予定です。
- 最近Goを使って「豆知識毎にチャットルームを設け、チャットルーム内で豆知識についてリアルタイムでお話できる機能」を作っているのですが、**SupabaseのDB**と**チャットというユースケース用のDB**が独立してしまっているので、どうにかして2つのDB間で整合性を担保できるようにするか、Supabaseで行っている役割を全てGo側に置き換えるなどして対処する予定です。

# 参考
[SQL 第2版: ゼロからはじめるデータベース操作](https://www.amazon.co.jp/SQL-%E7%AC%AC2%E7%89%88-%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%81%AF%E3%81%98%E3%82%81%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E6%93%8D%E4%BD%9C-%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AD%A6%E7%BF%92%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E3%83%9F%E3%83%83%E3%82%AF/dp/4798144452/ "")
積読状態だったので読みました。いざSQLを書こうとすると自力で書けなかったので辞書的に読みました。知りたいSQL構文周辺の基礎知識を知れるのでとても助かりました。


[達人に学ぶDB設計徹底指南書 第2版](https://www.shoeisha.co.jp/book/detail/9784798186627/ "")
今回のハッカソンのDB設計ではこちらの書籍に非常に助けられました。どういう設計がなぜ良くてなぜだめなのかが全然分からない自分からすると最高の書籍でした。まだ十分に読み切れていなかったり、意図を汲み取れていない部分もあると思うのでしっかり読んでいきたいです。
また、こちらの書籍の著者であるミック氏がX上でありがたすぎるDB周りのガイドマップを作成してくださっているので、今後はこれに沿って理解を深めていけたらなと思います。

https://x.com/copinemickmack/status/1910880555585147043

[Web API: The Good Parts](https://www.oreilly.co.jp/books/9784873116860// "")
直接的にDB設計がしやすくなったという訳ではないのですが、API設計の概要を掴んでからDB設計するとアプリ全体のデータの流れをイメージしながらDB設計ができる気がしたので読んで良かったなと思います。こちらの書籍も全然読み切れていないのでしっかり読んでいきたいです。

# さいごに
今後はより複雑な要件のデータモデリングも経験してみたいと思いました。
NandGameデータ移行

# はじめに
## 背景
最近また [NandGame](https://nandgame.com) を見直していたのですが、そういえばブラウザ間のデータ移行ってできるのかな、と調べて自環境でできたのでまとめたものです。

## 前提
昔、進捗・回路データはサーバで保存している ( クッキーでキーだけ管理する ) のかと勘違いしていたのですが、実はローカルストレージに保存しているものでした。
なので、ブラウザのローカルストレージを操作することができれば、どのブラウザでもできると思います。

## 環境
この記事では Windows11(amd64) + Firefox(記事時点で137) + [Local Storage Editorアドオン](https://addons.mozilla.org/en-US/firefox/addon/localstorage-editor/) で行った状況を記事にしています。
※注: あくまで as-is の情報であるため、**手順再現のための環境の整備、特にアドオンの導入については自己責任**でお願いします。

# 手順
ここでは簡単のため、同一のPC上で [nandgame.com](https://nandgame.com)用のデータを [www.nandgame.com](https://www.nandgame.com) に移行する手順を示します。
※同一のサイトながら、データ管理が別扱いになるように見えるからです。

* 移行元でのデータのコピー  
  移行元の nandgame のページを開いて、Firefoxの画面右上の SL のアイコンでアドオンの画面が表示されます。  
  そこで、全項目を選択し、CopyボタンでクリップボードへJSONデータを一式コピーします。  
  ※別PCへ移す場合は、代わりにDownloadボタンでJSONファイルをダウンロードします。( ダウンロードはブラウザの方で管理されます )
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74396/a4fe91f5-ac55-4240-a15f-61b293942f7e.png)
* 移行先へのデータの書き込み  
  移行先の nandgame のページを開いて、同じくアドオンの画面から、全項目を選択してDelete(削除) → Import(インポート) → Submit(保存) と操作していきます。  
  PC間の移行の場合は、ダウンロードしたJSONファイルをエディタで開いてクリップボードにファイル内の全テキストをクリップボードにコピーしてから Import を選択します。  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74396/15701abe-2cd3-4658-b6fc-09c2e891d141.png)  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74396/f757f4fb-275d-4fdd-92be-065f4ebf8c85.png)  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74396/884a9a06-84af-44ed-ae88-ac659744a483.png)
* 確認  
  改めて移行先のページを開くと、進捗等が移行されていることが分かります。  
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/74396/97ef2daa-95a3-4883-96ab-da8e330f7e55.png)

# 終わりに
簡単ですが手順を記しました。ざっと探してみて移行の情報を書いているサイト等が見当たらなかったため、参考になれば幸いです。
Unityの2DRendererとCustomLitShaderのライティング実装（2DRenderer前編）

# もくじ

2DRenderer中編

https://qiita.com/dieblondebestie/items/3e2a2414a0806df17518

2DRenderer後編

https://qiita.com/dieblondebestie/items/57b6e618490ba7b21c0c

# 概要
自分が作成してる2Dベルトアクションゲームで2DRendererを採用したのでその際の事例を紹介します。
### 2DRendererとは
Unityが2Dゲーム向けに提供しているURPの2D機能。2DLightやShadowCaster2Dなどが対応しており、2Dでのライティング表現の幅が広がる機能を有しています。
Unityはほかにも2D向けの機能があるので詳しくは[マニュアルの2D部分](https://docs.unity3d.com/6000.0/Documentation/Manual/Unity2D.html)を読んでください。

### 2DRendererの採用理由
2DrendererはLightBlendStylesを活用してShaderGraphで最大4つまでLightTextureを受け取れるというのが最大の理由です。
3DRendererではメインのDirectionalLightは容易にShaderGraphで受け取れますが、その他のAdditionalLightを受け取るのはCustomFanctionなど駆使しても自分の知識では難しかったので、Lightの値を色々できる2DRendererにしました。もちろんLitShaderでは3Dでも全てのLightが反映されますが、ShaderGraphで色々いじれないので除外です。

# 環境・導入
- Unity 6000.0.23f1

# 実装
目指したライティングとしては、2Dとはいえ奥行き表現にはこだわりたいので、インゲームを背景、遠景、キャラクターの地点、前景と4軸に分けてそれぞれの軸のライトがそれぞれ別のLightTextureになるようにし、その軸の手前のライトからは順光、奥のライトからは逆光となるようにしました。

イメージ図
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054619/19022c9e-b87f-4803-9540-709b2d1d58be.png)

具体的には2DLightは位置によってBlendStyleを設定。objectのShederには位置によってLightTextureの中から順光として受け取るColorを合計したものと逆光として受け取るColorをそれぞれ出力するSubGraphを作成。順光はそのままテクスチャのColorと乗算、逆光は以前紹介したフレネルの処理を通して加算するようにしました。

オブジェクトのShader
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054619/ac1e9af0-5226-458e-bfba-12b46e7997e1.png)

描画結果
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4054619/e8c7c1f8-e66d-400d-a5fc-0ed4d64a53f1.png)

:::note alert
2DRendererのデメリット
落ちる葉っぱをVisualEffectGraphで実装しようと思いましたが、VFXGraphでは2DRendererのLightTextureを受け取れないようになってたのでParticleSystemにしました。
:::

# まとめ
2DRendererはLightを色々できるところは良いですが、それなりにデメリットもあるのでその辺も記事書けたらと思います。
[Python] フレームワーク

# まとめ

| **分類** | **フレームワーク** | **特徴** |
|----------|--------------------|----------|
| フルスタックフレームワーク | Django | 高機能で大規模開発に適している。管理画面や認証機能が充実 |
| マイクロフレームワーク | Flask | 軽量で柔軟。小規模プロジェクトに適している |
| API開発フレームワーク | FastAPI | 高速なAPI開発に特化。非同期処理をサポート |
| データ可視化フレームワーク | Streamlit | データサイエンスや機械学習のアプリケーションに適している<br>- `HTML`, `CSS`不要 |
| リアルタイムフレームワーク | Tornado | 非同期I/Oをベースにした高パフォーマンスフレームワーク。リアルタイムアプリケーションに適している |
| **デスクトップアプリフレームワーク** | Tkinter | Python標準ライブラリに含まれるGUIツールキット。簡単なGUIアプリの開発に向いている |
|  | PyQt | QtフレームワークをPythonで利用。洗練されたUIが作れる |
|  | Kivy | マルチタッチ対応で、モバイルアプリの開発にも使える |
| **機械学習フレームワーク** | TensorFlow | Googleが開発した深層学習フレームワーク。Kerasと組み合わせて使うことが多い |
|  | PyTorch | Facebookが開発。動的グラフに対応し、研究者に人気 |
|  | Scikit-learn | 機械学習の基本的なアルゴリズムを提供。教育用途にも人気 |


# 使用例
## **Webアプリケーション**
**目的**: 高速なAPIとリッチなWebインターフェースを提供する  
**フレームワーク**:
- **FastAPI**: 高速なAPI開発に使用。非同期処理をサポートし、パフォーマンスが高い
- **Django**: Webインターフェースの構築に使用。豊富な機能と強力な管理画面を提供

## **データ分析ツール**
**目的**: データの収集、分析、可視化を行う  
**フレームワーク**:
- **Flask**: 軽量なWebフレームワークとして使用。シンプルで拡張性が高い
- **Dash**: データの可視化に特化したフレームワーク。インタラクティブなグラフやダッシュボードを簡単に作成できる

## **IoTアプリケーション**
**目的**: センサーデータの収集とリアルタイム表示  
**フレームワーク**:
- **Tornado**: 高速な非同期処理をサポートするWebフレームワーク。リアルタイムデータ処理に適している
- **Flask**: シンプルなWebインターフェースの構築に使用

## **教育用アプリケーション**
**目的**: プログラミング学習を支援するインタラクティブなツール  
**フレームワーク**:
- **Django**: ユーザー管理やデータベース操作に使用
- **React (JavaScriptライブラリ)**: フロントエンドのインタラクティブなUIを構築するために使用

## **データサイエンスダッシュボード**
**目的**: データの収集、分析、可視化を行うインタラクティブなダッシュボードを提供する  
**フレームワーク**:
- **Streamlit**: インタラクティブなUIを簡単に構築し、データの可視化を行う

## **機械学習モデルのデプロイ**
**目的**: 機械学習モデルをデプロイし、ユーザーがリアルタイムで予測を行えるようにする  
**フレームワーク**:
- **Streamlit**: ユーザーがモデルに入力を提供し、予測結果をリアルタイムで表示するインターフェースを構築
- **FastAPI**: 高速なAPIを提供し、モデルの予測を処理



# 参考リンク
- [Pythonのフレームワーク完全ガイド｜人気フレームワークと選び方を徹底解説](https://saiseich.com/nextgeneration/python/python_framework/)
- [Pythonのフレームワークの種類と特性 〜2024年のトレンドを徹底解説〜](https://blog.greeden.me/2024/02/08/python%E3%81%AE%E3%83%95%E3%83%AC%E3%83%BC%E3%83%A0%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%AE%E7%A8%AE%E9%A1%9E%E3%81%A8%E7%89%B9%E6%80%A7-%E3%80%9C2024%E5%B9%B4%E3%81%AE%E3%83%88%E3%83%AC%E3%83%B3%E3%83%89/)
- [【2024年版】Pythonフレームワーク徹底比較！おすすめ7選](https://techmania.jp/blog/python-fw/)
- [【Python】アプリ開発の練習方法｜初心者向け](https://trends.codecamp.jp/blogs/media/column255)
【Tableau】第1回 初心者が挑むBIツール 今日は環境構築

## 今日はTableau
こんばんは！毎日一人前のデータアナリスト、
データエンジニアになるべく勉強しております

今日はBIツールであるTableauを自分の下で
動かすために設定をしていきます
なんか研修スピードがとんでもなく速く
今日一日でTableauの基本的な部分を叩き込みました

それを確認するべく自主学習も一緒に進めよう！
と思った矢先、ある重大なことに気が付きます...

### Tableauってライセンス料めっちゃ高いやんけ！！！
全然車買えます...約16万...
ということでどうやって自主学習をしようかと
思案するところから始まりました

## Tableau Public
なんと少し調べてみるとTableau Publicなるものは
ライセンス料がかからないらしく
個人利用であれば事実上無料で扱えるらしい...

### 激アツすぎる！！！
ということで早速Tableau Publicから
アカウント作成からのインストール！
マジで俺のPCにTableauが！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/1ab47d4d-67b2-40af-b80f-8bf3164c86c5.png)
早速勉強！と思ったらここでまたある壁に当たります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/cebec203-14e6-4a70-a863-83b40151cb5a.png)
### データがねぇ！！
でも考えれば至極当然ですよね
今インストールしたばっかりでデータが
BIツールに入っているわけがないですよね

ということでTableauには素晴らしいものが
用意されていることを私は知っておりましたので
それをダウンロードしに行きます

↓スーパーストア - サンプルデータソース
https://drive.google.com/drive/u/0/folders/1kXSb3fqPTt3VcPjGUSgOmrztlRfvvpMH

なんてすばらしいのでしょう
Tableau側でデータを用意してくれてます
私はこれをDLしてTableauに突っ込みました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053502/74e8a1eb-6f54-4159-89b5-e315ee777355.png)
すげー！
ちゃんとデータが用意されてすぐにTableauが
使用できるようになっているこの環境...！！
なんて素晴らしいんだ...
早速色々いじってみますか！


というのは明日に取っておきましょう
明日ゴリゴリやっていきます！
SQLも忘れずに...
初めてサイトを作ったので共有する

# 初めてサイトを作ったので共有する

## 経緯

大学にまめちしきなどの情報を取りまとめて、発信している個人のツイッターがある。
その人に頼まれて、豆知識をまとめる形でサイト制作を依頼された。

## 採用技術および使用ツール

１００％Next.jsで作成
VPSにホスティング（今思えばVercelでも良かったかも）
Supabaseをデータベースとして採用。
　（Team機能などで部活全体で管理がしやすい。）

https://hamubasu.com
![スクリーンショット 2025-04-16 194546.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853935/61ca3f1e-0392-472f-9406-e5b40d61e946.png)



## 全体の構造

コンポーネント開発を基本とする。再利用できるものが多かった。
https://hamubasu.com

![スクリーンショット 2025-04-16 135429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3853935/fe206a85-a983-44bd-bab5-ec8e08e0aa6e.png)



## Next.jsについて

AppRouterを採用しました。
PagesRouterの問題の一つであるバケツリレー（Props Drilling）が起きやすそうな構造。
(実際は、page.tsxでデータフェッチしてそれをpropsでArticleListのコンポーネントに渡していてバケツリレーしてしまった)

サーバー側での処理（データフェッチ等）がメインだったので、ＲＳＣの思想とも合致する。


## 改善点

> App RouterではServer Componentsでのデータフェッチが利用可能なので、
> できるだけ末端のコンポーネントへデータフェッチをコロケーションすることを推奨しています

とあるのでpage.tsxでするのはあまりよろしくないと思う。

RouteHandlerをサーバーサイドで使ってしまっている。

機能追加として、検索機能をつけたい。（フォームからサーバーに送って部分レンダリングする形にするつもり）


## 感想

AIを使ったので、全体の規模が大きくなるにつれてど最適じゃない答えがあった気がする。

参考資料のキャッシュの部分が難しかった。


## 参考資料

https://zenn.dev/akfm/books/nextjs-basic-principle/viewer/intro
PHP勉強メモ20250416 (配列の要素取得、キャメルケースかアンダースコアか）

## 前回
https://qiita.com/sioiriomame/items/766d35319afd785437b2

## 配列の要素取得
- 配列の要素取得は、基本的にキー名で行う
~~~php
$array = [
    'apple' => 100,
    'banana' => 150,
    'orange' => 200,
];

echo $array['banana'];
~~~

- index(何個目の要素か）で取得したい場合
以下のように`array_values`を使えば取り出せるらしい。
[array_values() は、配列 array から全ての値を取り出し、数値添字をつけた配列を返します。](https://www.php.net/manual/ja/function.array-values.php)
```php
array_values($array)[1]
```


- キーのない配列の場合、自動でindexの数値のキーが振られるらしい

~~~php
$array = ['a', 'b', 'c'];

echo $array[0]; // 出力: a
~~~

## 変数名はキャメルケースが書くかagain
前回も書いていたけれど、忘れていたのでもう一度。

https://qiita.com/sioiriomame/items/766d35319afd785437b2

CakePHPの場合は、変数名・メソッド名はキャメルケースで書く。
また、昔はメソッドがprivateの場合は`_`を頭につけていたが、今は`private`とつけられるので、メソッド名の頭の`_`は不要とのこと。