OmniAICreator/Qiita-1.07M huggingface dataset:
KinoSpeakerDeck で Livebook にスライドを表示する

## はじめに

SpeakerDeck はスライドを共有できるサービスです

https://speakerdeck.com/

例えばこんな感じに Web 上でスライドを表示できます

<script defer class="speakerdeck-embed" data-id="a5e10aa5d31643be888b9a9f215e87b9" data-ratio="1.7777777777777777" src="//speakerdeck.com/assets/embed.js"></script>

Livebook にもスライドを埋め込むため、 KinoSpeakerDeck を実装しました

https://github.com/RyoWakabayashi/kino_speaker_deck

ノートブックでの利用例はこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/kino/kino_speaker_deck.livemd

## セットアップ

ノートブックのセットアップセルで KinoSpeakerDeck をインストールします

```elixir
Mix.install([
  {:kino_speaker_deck, "~> 0.1"}
])
```

## スライドの表示

SpeakerDeck のスライド URL を指定するだけで表示できます

```elixir
KinoSpeakerDeck.new("https://speakerdeck.com/ryowakabayashi/livebookde-wei-xing-detawoxi-u")
```

![kino_speaker_deck.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/2c229a5a-f286-94f1-e835-3ebc2e967049.gif)

## 仕組み

SpeakerDeck は oEmbed という埋め込みのための共通仕様に対応しています

https://oembed.com/

https://help.speakerdeck.com/help/how-do-i-use-oembed-to-display-a-deck-on-my-site

`https://speakerdeck.com/oembed.json?url=<スライドURL>` にアクセスすることで、埋め込み用の HTML が取得できます 

```elixir
defmodule KinoSpeakerDeck do
  @moduledoc """
  A simple Kino for display Speaker Deck presentations on Livebook.
  """
  use Kino.JS

  def new(deck_url, opts \\ []) do
    case Req.get("https://speakerdeck.com/oembed.json?url=#{deck_url}") do
      {:ok, %Req.Response{status: 200, body: body}} ->
        width = opts[:width] || "100%"
        height = opts[:height] || "auto"

        body
        |> Map.get("html")
        |> String.replace(~r/width="\d*"/, "width=\"#{width}\"")
        |> String.replace(~r/height="\d*"/, "height=\"#{height}\"")
        |> Kino.HTML.new()

      {:ok, _} ->
        Kino.HTML.new("Invalid URL")

      {:error, _} ->
        Kino.HTML.new("Something went wrong")
    end
  end

  asset "main.js" do
    """
    export function init(ctx, iframe) {
      ctx.root.innerHTML = iframe;
    }
    """
  end
end
```

## まとめ

KinoSpeakerDeck で Livebook にスライドを埋め込むことができました

Livebook 上に動画やスライド、プロトタイプなどを埋め込むことで、プレゼンテーションの幅が広がりますね
InstanaのOpenAPIを使ってCSVを出力する

# Instana APIを使用してCSVをダウンロードしてみる

## はじめに

InstanaのAPIで取得できる内容がjsonしかないので、  
素人なりにサービスのリクエストの分析結果をCSVに加工してダウンロードするAPIをnode.js作ってみました。  
それを使ってCSVをダウンロードしてみるといった内容になります。  
  
素人がこのAPIをどうやって作ったの？　という内容は別記事にしたいと思います。  
軽く触れておくとChatGPTパワーです。

## 注意事項

著者が普段開発する技術者ではなく、ChatGPTにほぼ全て書かせたものなので今回使うものは高品質なソースコードではありません。  
ツッコミどころ満載ですが、目を瞑っていただけると……。

## 前提条件

以下がインストールされていること(インストール手順は本記事では割愛します)

+ node.js
  + versionは何でもいいです
  + 今回は v20.11.1 を使用しています
+ git

## 本題

### 事前準備

#### ダウンロード

Gitにアップロードしているので、任意のディレクトリにcloneします  
以下のコマンドを実行します。

`
git clone https://github.com/shunyu-tamura/instana-endpoint-analysis.git
`

cloneされたらディレクトリ内で必要なパッケージをインストールします。  
以下のコマンドを実行します。
`
cd instana-endpoint-analysis
npm install
`

#### 設定ファイルの修正

config.jsonの以下の箇所を修正します

+ "host": "api.example.com"
  + Instanaのホスト
+ "token": "your_api_token"
  + InstanaのAPIトークン
    + 公式ドキュメント：<https://www.ibm.com/docs/ja/instana-observability/current?topic=apis-web-rest-api>

#### 起動

以下のコマンドで起動します。  

`
npm start
`

以下のような結果が返ってきたら問題なく起動できています


> \> instana-endpoint-analysis@1.0.0 start
> \> node ./src/main.js
>
>Server is running at http://localhost:3000

### CSVをダウンロードしてみる

#### 前日分の結果をダウンロード

ブラウザで以下にアクセスします。  
※xxxの部分は分析対象にしたいサービスを入れます  

<http://localhost:3000/analysis/service/xxx>

前日分のサービス内のAPIの分析結果のCSVがダウンロードされるはずです

#### 日付を指定してダウンロード

指定する場合は以下のようにクエリパラメータを追加します  
※yyyymmddの部分は分析対象にしたい日付を入れます  

<http://localhost:3000/analysis/service/xxx?date=yyyymmdd>

## 最後に

そこまで時間をかけて作ったものではないので品質は良くないですが、社内ツールとして使う程度には十分なものではあると思います。  

実はこのコードは１年近く前に作ったので、今はもっと高品質なコードで作れるのですが、時間がなかったのでご勘弁……。
【初心者向け】超簡単！AWS AmplifyでWebアプリをデプロイしてみた

## はじめに
AWS初心者です。AWSの基本知識をキャッチアップすべく、色々触りながら学習中です。<br>今回は、モバイルアプリやウェブアプリを構築するためのAWSのサービスであるAWS Amplifyを触ってWebアプリをどのくらい簡単にデプロイできるか試した内容を記事にしました。初心者向けの内容となっておりますので、温かい目で見て頂ければ幸いです。

## 想定読者
 - AWS初心者で、基本機能を色々触ってみたい方

## 概要
本ページでは、ローカルで用意した簡易WebアプリをAWS Amplifyにデプロイしてアクセスするところまでの手順をまとめています。

## チュートリアル

### 簡易Webアプリの作成
今回あまり本質ではない部分なので、[初めてのNext.jsサンプルプログラム作成](https://qiita.com/a-miura/items/3b629405436aa833e1e1)を参考にさせていただきました。とても分かりやすかったです。開発環境は揃っていたので、5分程度でサンプルプログラムを準備できました。

### Amplifyにデプロイするための対応
後述でも出てきますが、Amplifyにデプロイするフォルダの構成/形式として以下のような注意書きがありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/247a9562-37d2-dd67-faaa-df7aa2d701ca.png)

調べてみた結果、Amplifyにデプロイするには`next export`を使用して静的サイトとして出力したうえで、zip化する必要があることが分かったため、以下の手順を追加で行いました。

「package.json」のスクリプト定義
以下のスクリプトを追加
```package.json
"scripts": {
    "export": "next build && next export"
```
「next.config.ts」への設定追加
静的エクスポート用の設定を追加
```next.config.ts
module.exports = {
  output: 'export', // 静的エクスポート用の設定
};
```
buildとexportの実行
```Terminal
cd my-app
npm run export
```
出力フォルダ(out)をzip化
```
zip -r amplifyDeploy.zip ./out
```

デプロイするWebアプリの準備はこれで完了です。

### AWS Amplifyへのデプロイ
AWSコンソールへログインし、AWS Amplifyの「アプリケーションのデプロイ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/11d756cb-b610-18d6-2871-d10dc6c41722.png)

今回は、「Gitなしでデプロイ」を選択して、「次へ」へ進みます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/d121dcad-a96e-3561-292f-c3f62ee885f7.png)
※本当は今後に向けて、CodeCommitと連携したデプロイをやりたかったですが、新規利用のサポートが終了しているため、諦めました。

前述で作成したzipファイルをドラッグ＆ドロップして、「保存してデプロイ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/af64839b-29c7-e6fa-7ce3-98b3086843de.png)

数秒でデプロイが完了しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/a1c8f0f9-4698-ab5c-cb30-681e4fb25800.png)

右上の「デプロイされたURLにアクセス」を選択すると、作成した簡易Webアプリにアクセスできることを確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/362e1a8a-a839-ad95-13a9-c35c41bd36d6.png)

##　アプリの設定（おまけ）
デプロイしたアプリに対して、アクセスコントールやリダイレクト、カスタムドメイン(Amazon Route53と連携)などGUIで設定が可能となっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/b3e5b84f-3d56-afa7-cd78-8059c8a110a6.png)

試しにアクセスコントロールで対象ブランチにアクセス権を設定してみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/1a12cbd0-bf3d-c852-58ed-ea7a740cb088.png)
再度、Webアプリにアクセスするとユーザ名とパスワードが要求される動作を確認することができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3936702/57a1cb97-5918-8a33-9a99-1e7d2e33c76a.png)

## まとめ
AWS Amplifyを使って、Webアプリのデプロイをどれくらい簡単にできるのか試してみました。AWS Amplifyを使えば、初心者でも簡単にWebアプリのデプロイと動作確認することができました。
ftplibをPC1台で試す

# はじめに
PC1台でftplibの動作を確認したときのメモです。
dockerを使用してFTPサーバを作成し、ローカルのディレクトリとdockerコンテナ内のディレクトリでファイルのやり取りをすることを目的とします。

# 環境
- MacBook Pro
  - プロセッサ：1.4 GHz クアッドコアIntel Core i5
  - メモリ：16 GB

# dockerの準備
作業用のディレクトリを作成し、その中にdocker-compose.ymlを作成する。下記のサイトを参考に作成する。
https://github.com/stilliard/docker-pure-ftpd/tree/master

```
version: '3'

services:
  ftpd_server:
    image: stilliard/pure-ftpd
    container_name: pure-ftpd
    ports:
      - "21:21"
      - "30000-30009:30000-30009"

    environment:
      PUBLICHOST: "localhost"
      FTP_USER_NAME: testuser
      FTP_USER_PASS: password
      FTP_USER_HOME: /home/testuser

    restart: always
```

# 送信するファイルなどの準備
送信するファイルなどを準備する。
## ローカルPC
ftp-testというディレクトリを作成し、この中に必要なファイルを作成する。
```
ftp-test ____ docker-compose.yml
          |__ put-test.txt
```
## dockerコンテナ
/home/testuser下に必要なファイルを作成する。
```
testuser ___ get-test.txt
```

# ftplibの動作確認
下記コマンドでdockerコンテナの作成＆起動を行う。
```
cd ftp-test
docker compose up -d
```
## 接続
pythonで下記を実行し、ホストに接続
パラメータはdocker-compose.ymlに設定したもの
```
from ftplib import FTP
ftp = FTP(host='localhost', user='testuser', passwd='password')
```

## ディレクトリの中身を取得
下記コマンドを実行すると、コンテナの/home/testuserディレクトリ下のファイルやフォルダを見ることができる。
```
ftp.retrlines('LIST')
```
```
-rw-r--r--    1 0          0                   9 Nov 28 14:02 get-test.txt
'226-Options: -l \n226 1 matches total'
```
## コンテナにあるファイルをPCにコピー
下記コマンドを実行すると、コンテナにあるget-test.txtをPCのftp-test下にget-test2.txtとして保存することができる。
```
with open('get-test2.txt', 'wb') as f:
    ftp.retrbinary('RETR get-test.txt', f.write)
```
```
'226-File successfully transferred\n226 0.000 seconds (measured here), 42.03 Kbytes per second'
```

## PCにあるファイルをコンテナにコピー
下記コマンドを実行すると、PCにあるput-test.txtをコンテナの/home/testuser下にput-test2.txtとして保存することができる。
```
with open('put-test.txt', 'rb') as f:
    ftp.storbinary('STOR put-test2.txt', f)
```
```
'226-File successfully transferred\n226 0.001 seconds (measured here), 8.00 Kbytes per second'
```
ftp.retrlines('LIST')を実行すると、コンテナ内にput-test2.txtとして保存されていることを確認することができる。

```
ftp.retrlines('LIST')
```
```
-rw-r--r--    1 0          0                   9 Nov 28 14:02 get-test.txt
-rw-r--r--    1 1000       ftpgroup            8 Nov 28 14:24 put-test2.txt
'226-Options: -l \n226 2 matches total'
```

# dockerの停止
下記コマンドでコンテナの停止＆イメージの削除を行う。
```
docker compose down --rmi all
```

# おわりに
手元にあるPCで完結できてよかったです。
公式ドキュメントにもっと使用例とか載せて欲しい。。。

# 参考記事
- https://github.com/stilliard/docker-pure-ftpd/tree/master
- https://docs.python.org/ja/3/library/ftplib.html
VoIP/SIPを扱う自社開発企業に転職して半年が経ちました

# はじめに
本記事は自分のためでしかないアドベントカレンダー2024の記事です。
記事は２５記事書くと思いますが期待はせずにお願いします。

# 入社の経緯
前職はSIer、というかSESでした。
SESという働き方が自分に合わなかったこともあり、転職を決意しました。
転職活動を１ヶ月ほど行い、よさげな自社開発企業から内定を頂いたので現在お世話になっております。

# 現在取り組んでいること。
RustでVoIP/SIPの開発を行っています。
現行品のリプレス、不具合修正などがメインですね。
リプレスはRust言語で開発しています、Rustなにもわからん。
IVRとか、迷惑電話受取拒否とかそういうのもやってます。

# 今後
生成AI使ったり作ったりしてみたいです。
というか競合がやっているのでやらざるを得なくなることでしょう。
現在は現職の業務の勉強に加え生成AIの勉強もしています。
来年は生成AIもやってみたいなあ。
あとRustの書き方わからないのでもっと知りたい。

# 最後に
この記事10分で書きました
テニスたのしい

# こんちは

クリスマス当日にこの記事を読んでくれてありがとう。
俺の名前はAmakawaだ。
この記事は、他のみんなが書いているような真面目でためになるような話じゃあない。
この記事は俺の未来について書こうと思う。
# 振られそう
俺の人生は今危機に瀕している。
みんな予想していると思うが、彼女に振られるかもしれない。
いや、いつ振られてもおかしくない状況にある。
そこで、俺は考えた。
## クリスマスまでにデートすればいいんじゃね？
みたいな....
俺は今まで一度もデートをしていない。
というか、ほとんど俺が休日に外に出るのが面倒で誘ってすらいなく、結局一緒にゲームをして終わることが定番の流れにっている。
俺も彼女と付き合ってもう１年４ヶ月くらいだ。
そろそろデートに誘わないとまずい。というか行きたくなってきた。
俺の中で、初デートは「絶対に映画を見ていい感じの雰囲気になってハグをして帰る」というものにしたいという願望がとても強くある。
なので！
実際に誘って、もしデートに行けたら下にデートの感想を書こうと思う。
書かれてなかったら.....察してくれ。
# デートの結果
たのしかった。
最初考えてたデートプランは、映画に行くというプランだったけど彼女とどの映画を見ているか相談しているうちに映画ではなく運動がしたくなり、結果彼女とテニスをすることになった。
自慢じゃないが、俺の彼女は強い。物理的にも、精神的にも。
最初こそはボールを打っても上に行くボールばかりだったが、最終的には軽く打ち合えるレベルまで成長していた。
# 最後に
思い切って外に出て遊ぶのも良いものだと理解できた。
外で遊ぶより、絶対中でゲームしてるほうが楽しいと思ってたけど、友達や彼女と遊ぶほうが楽しいと気づけた。
みんなもクリスマスデートにぜひ行ってみてくれ。

それでは。
【New Relic】NerdGraphでユーザーキー・ライセンスキーを取得する

## はじめに 
2024/9/25よりセキュリティ向上のため `INGEST LICENSE key`, `User key` は作成時以外はValueをUI上から参照できなくなっています。（Copy Keyが使えなくなりました）
代替策としてNerdGraphを利用してKey取得することになります。

参考： [UI から API Key をコピーができなくなります](https://newrelic.com/jp/blog/nerdlog/api-key-ui-eol)

## NerdGraphとは
New Relicのデータの参照や各種機能の設定を行うためのGraphQL形式のAPI。

参考：[NerdGraphの紹介](https://docs.newrelic.com/jp/docs/apis/nerdgraph/get-started/introduction-new-relic-nerdgraph/)

## New Relic API キーを作成する
NerdGraphの認証にはUser API Keyが利用されます。以下の手順でこのAPIキーを作成します。
1．New RelicのUI→画面左下の「ユーザ名」→「API Keys」を押下
![CleanShot-2024-11-28-at-21.44.59@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/fe7fbd1b-cdb2-e61a-74e0-267cd2965e3a.png)

2．「Create a key」を押下
![CleanShot-2024-11-28-at-21.48.10@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/04e6e45e-9237-cf56-8086-8b1269dbd1ff.png)

3．下図のように選択、入力する→「Create a key」を押下
![CleanShot-2024-11-28-at-21.52.12@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/f1feb40c-6ef6-1529-064b-4c14f1f2d513.png)

4．「Copy Key」を押下し、User API Keyを控えておく
![CleanShot-2024-11-28-at-21.56.38@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/8519f65e-3171-ffcb-e26c-166188eedf1a.png)


参考：[New Relic API キー](https://docs.newrelic.com/jp/docs/apis/intro-apis/new-relic-api-keys/)

## NerdGraph GraphQL Explorerでクエリする
NerdGraph GraphQL Explorerを利用する。ブラウザ上（New Relic UI上）で実行が可能。

1．「All Capabilities」→「Apps」
![CleanShot-2024-11-28-at-22.07.32@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/cf84ee6c-56e2-2763-618b-eee3f54b7ac3.png)

2．「NerdGraph API Explorer」を押下
![CleanShot-2024-11-28-at-22.09.04@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/60dd36f7-3042-90a4-c069-ee346114ec81.png)
> 見当たらなければ、「Go to Apps and Visualizations」から追加できます

3．「User key」をペースト→「Submit」を押下
![CleanShot-2024-11-28-at-22.11.42@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/3c17e3d7-38a3-d529-e991-9b849b721999.png)

4．以下のように記述する（左側のQuery Builderのチェックボックス選択でもOK）→「Execute query」


```
#単一の API Key を取得
query {
  actor {
    apiAccess {
      key(id: INGEST_KEY_ID, keyType: INGEST) {
        key
        name
        type
        ... on ApiAccessIngestKey {
          ingestType
        }
      }
    }
  }
}
```
または
```
#複数の API Key を取得
query {
  actor {
    apiAccess {
      keySearch(query: {types: INGEST, scope: {ingestTypes:  LICENSE}}) {
        keys {
          name
          key
          type
          ... on ApiAccessIngestKey {
            ingestType
          }
        }
      }
    }
  }
}

```

> 「`id`」は、API Keysの画面から下図のようにコピーする
> ![CleanShot-2024-11-28-at-22.28.00@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/d414fdeb-7497-36b0-2a97-3964ca30cc91.png)

5．実行結果を確認する（下図の赤枠部分がライセンスキー）
![CleanShot-2024-11-28-at-23.03.57@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3693999/70e95b0c-f650-7999-a0e9-6e9ffbf4c2af.png)



参考：[NerdGraph API エクスプローラーのチュートリアル](https://docs.newrelic.com/jp/docs/apis/nerdgraph/get-started/nerdgraph-explorer/)
【Langflow】検索拡張生成(RAG)を使ってみた

# はじめに
こちらの続きです！

https://qiita.com/does_not_exist/items/afc9e0ba5cd0ec26e9f4

Langflowで以下のフローを作成し、RAGの動きを実際に試してみました！

![スクリーンショット 2024-11-23 19.55.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/80bf88e7-d9b1-31ad-6a9f-0efda831fbeb.png)

作成にあたって以下記事を参考にさせていただきました:pray:
~~ほぼ同じですが~~

https://milvus.io/docs/ja/rag_with_langflow.md

# RAGとは

:::note
(ChatGPTより)
RAG（検索拡張生成、Retrieval-Augmented Generation）は、生成型AI（例えば、GPTのような言語モデル）と情報検索システムを組み合わせた技術です。このアプローチでは、AIがユーザーの質問に対して回答を生成する際に、事前に用意された大規模な文書データベースやインターネット上の情報から関連する情報を検索し、その検索結果を基にして回答を生成します。
:::

# 学習モデルを使うのと何が違うの？
RAGに関してはデータベースを用意するということで最新の情報を取り扱える点、加えて事実ベースの情報集合となるためハルシネーションを抑制できる点が大きな魅力かと思います。

# 試してみた

事前に以下のデータをデータベースに登録させておきます。

```
以下は弊社のおこおこシステムでコンテンツの情報を更新する手順です。

手順：
1. ログイン画面でIDとパスワードを入力してログイン
2. ログイン後、コンテンツ一覧画面から情報を更新したいコンテンツ画像をクリック
3. コンテンツ情報を編集したら保存ボタンをクリック
4. 保存が完了すると、コンテンツ一覧画面に戻ります

よくある質問：

Q.ログインできません
A.入力したIDまたはパスワードが正しくない可能性があります。再度入力を試しても解決しない場合は管理者Aまでお問い合わせください。

Q.スマホからアクセスすると画面のレイアウトが崩れます
A.スマホ対応していません。スマホ対応をご希望される場合は弊社カスタマーサポートまでお問い合わせください。
```

格好つけるためにプロンプトも用意しておきました。

```
回答は以下の形式で

### 事象発生の要因

### 解決方法

### 解決しないときの問い合わせ先

```

まずは「スマホ対応してないんだけど:triumph:」と問い合わせしてみました。(スクショ撮り忘れました)

学習させた内容に基づいて回答してくれていますね...!

![スクリーンショット 2024-11-24 10.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/43feefc1-d7ca-cb6c-8068-ce8d41d43831.png)

次に学習させていないことについても聞いてみました。

![スクリーンショット 2024-11-24 10.32.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/6b652e18-56c9-24e9-5ba7-812eff452ec5.png)

学習させていない内容については答えられていないですね。
あえて学習させた単語に似ている単語を使ってみたのですが、適当な回答をするのではなく、分からないことは分からないと答えてくれています。

# おわりに
自分でデータを用意して回答精度を試せると面白いですね。
LLMはGeminiを使っています。無料でAPI Keyを取得できます！(記事執筆時点では)
「未開の地」で気づいた、自分の中の思い込み

プログラマーとして働く中で、最も大きな転機となった経験について書きたいと思います。それは、大学2年の夏に参加したベトナムでのインターンシップでした。

## 「解決策」を持って現地へ

当時の私には、日本での経験から培われた「確信」がありました。ベトナムの交通渋滞を解決するために、システム改善と効率的な交通網の整備を提案しようと。そう、私の中には既に「答え」があったのです。

今思えば、それは私の中の無意識の思い込み―アンコンシャスバイアスでした。「先進国である日本の方が、解決策を見出しやすい」という思い込み。「未開の地」という偏見。

## 現実は違った

現地調査を進める中で、私の「わかっているつもり」は徐々に崩れていきました。
地域住民との対話を重ねるうちに見えてきたのは、渋滞よりもはるかに切実な問題でした。排気ガスによる健康被害。それは、彼らの日常生活に直接的な影響を及ぼしていたのです。

同様の調査は日本国内でもできたはずです。でも、あえてベトナムという、経済発展の段階が異なる国に足を運んだからこそ、自分の思い込みから解放されることができました。

## 言葉の壁が教えてくれたこと

言語が通じにくい環境は、むしろ私にとって幸運でした。

言葉が通じないからこそ、より丁寧に、より深く相手の話に耳を傾けました。非言語コミュニケーションを駆使し、真摯に理解しようとする姿勢が、新しい発見につながっていったのです。

日本では当たり前すぎて気づけない社会課題や、その解決に向けたアプローチの多様性。それは、「未開の地」と思い込んでいた場所で、私の固定観念を覆してくれた貴重な学びとなりました。

## 「なりたい」の呪縛から解放されて

実は、当時の私には「問題解決のスペシャリストになりたい」という思いがありました。しかし、その「なりたい」という思いが、かえって本質的な課題を見えづらくしていたのかもしれません。

「なりたい」に囚われると、自分の中の「正解」を探してしまう。でも、本当に必要なのは「知りたい」「理解したい」という素直な気持ちでした。

## 今、モノづくりに活きていること

この経験は、現在の私のモノづくりの根幹となっています。

作る前に、まず知ること。
理解する前に、まず疑うこと。
そして何より、自分の中の無意識の思い込みに気づくこと。

それは時として遠回りに見えるかもしれません。でも、その過程こそが、本質的な価値を生み出す土台になるのだと信じています。

## おわりに

私たちの中には、気づかないうちに多くのアンコンシャスバイアスが潜んでいます。それに気づき、克服していくことは簡単ではありません。

でも、「なりたい」という思いに囚われず、まずは目の前の「知りたい」「理解したい」という気持ちに素直に向き合うこと。それが、バイアスから解放される第一歩なのかもしれません。
KinoCodePen で HTML、CSS、JS のサンプル実装を Livebook に表示する

## はじめに

CodePen は HTML、CSS、JS のコードと実装結果を共有できるサービスです

https://codepen.io/

例えばこんな感じに、コードと結果を並べて表示できます

<p class="codepen" data-height="300" data-default-tab="html,result" data-slug-hash="ExdeaRL" data-pen-title="jQuery" data-editable="true" data-user="ryowakabayashi" style="height: 300px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;">
  <span>See the Pen <a href="https://codepen.io/ryowakabayashi/pen/ExdeaRL">
  jQuery</a> by Ryo Wakabayashi (<a href="https://codepen.io/ryowakabayashi">@ryowakabayashi</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://cpwebassets.codepen.io/assets/embed/ei.js"></script>

CodePen では上記のような一つの実装の単位を「ペン」と呼んでいます

Web フロントエンドの学習や知識共有に使えるサービスで、しかも無料で使えます

私も以前、 CodePen を使った記事を書いています

https://qiita.com/RyoWakabayashi/items/e15a0da7105320127213

https://qiita.com/RyoWakabayashi/items/c2d5db339e3bc4811deb

この CodePen を Livebook に埋め込むため、 KinoCodePen を作りました

https://github.com/RyoWakabayashi/kino_code_pen

ノートブックでの使用例はこちら

https://github.com/RyoWakabayashi/elixir-learning/blob/main/livebooks/kino/kino_code_pen.livemd

## セットアップ

ノートブックのセットアップセルで KinoCodePen をインストールします

```elixir
Mix.install([
  {:kino_code_pen, "~> 0.1"}
])
```

## ペンの表示

CodePen のユーザー名とペンID（URL の赤枠部分）を指定します

![スクリーンショット 2024-11-28 22.48.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/b434ba3d-115f-c893-74dd-11515f8cdff7.png)

```elixir
KinoCodePen.new("ryowakabayashi", "ExdeaRL")
```

実行結果

![kino_code_pen.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1485835/435173e9-40b4-2dbf-9157-c1be18813ffc.gif)

ペンを表示し、操作することもできました

URL を指定して表示することもできます

```elixir
KinoCodePen.url("https://codepen.io/ryowakabayashi/pen/ExdeaRL")
```

## まとめ

フロントエンドの実装例を共有する際などに使えそうですね
ランダムなパスワード作成スクリプト

記事というよりも、完全に個人的なメモ用ですが、PowerShellを使用してランダムな文字でパスワードを作成するスクリプトです。パスワードを作成するときに、適当にPCのキーボードを打つというのもありですが、癖もあって同じような文字列になりがちでした。
そこでPowerShellでランダムにパスワードを作成するようにしました。
生成されたものをコピペで使用しようかなと思っていますwww

- 記号も使う場合は、コメントになっている$charsを替わりに使用してください
- $passwordlengthでパスワードの長さを指定しています

# パスワード作成
```powershell
# 定数の設定
# 記号も使用する場合
#$chars = @('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
#           'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
#           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
#           '!', '#', '$', '%', '&', '(', ')', '{', '{', '@', '[', ']', '+', ';', ':', '*', '\', '-', '=')

# 英数字のみ
$chars = @('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
           'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
           '0', '1', '2', '3', '4', '5', '6', '7', '8', '9')

$charCount = $chars.Length
$passwordLength = 20

# パスワード生成用の配列
$pass = @()

# ランダムな文字を配列に追加
for ($cnt = 0; $cnt -lt $passwordLength; $cnt++) {
    $pass += $chars[(Get-Random -Minimum 0 -Maximum $charCount)]
}

# パスワードを生成
$PASSWORD = -join $pass

# 結果を出力
Write-Output "ランダム作成されたパスワード"
Write-Output $PASSWORD
```
Rondhuitが公開しているLivedoorのニュース記事データをElasticsearchにインデックスするツールを作った

# はじめに

タイトルの通りです。Rondhuitが公開しているLivedoorのニュース記事データをElasticsearchにインデックスするツールを作ったので紹介します。

https://github.com/daixque/livedoor_corpus_ingester

検索系の開発をする場合、検索の精度を確認するためにはある程度のテストデータが必要で、それを用意するのは意外と手間がかかります。そこでRondhuit社様がそのような迷える子羊たちのためにテストデータを公開してくださっています。ありがたや。

- [livedoor ニュースコーパス](https://www.rondhuit.com/download.html#news%20corpus)

RondhuitさんはApache Solrを扱う会社なのでSolr向けのXMLデータが提供されていますが、それと同時にプレーンテキスト形式も公開されています。そこでこちらのデータをダウンロードしてElasticsearchにアップロードするまでを簡単に行うツールにして、上記のリポジトリで公開しました。

当然データの著作権等についてはこちらの責任範囲外ですので、上記Rondhuit社のWebページにある記載を確認の上ご利用ください。

# 使い方

使い方はリポジトリのREADMEに書いてあるとおりですし、何より極めてシンプルなスクリプトなのでご自由に改変して使ってください。

とはいえ、一連の流れについては一応ここにも書いておきます。

## データのダウンロードと展開

とりあえずリポジトリをクローンしてください。

```
$ git clone git@github.com:daixque/livedoor_corpus_ingester.git
```

リポジトリのトップディレクトリに移動の上、以下のようにスクリプトを実行してください。

```sh
$ ./download_corpus.sh
```

するとdataディレクトリが作成され、その中にダウンロードした記事データが展開されます。

## Elasticsearchへの接続情報の設定

`env.sample`ファイルを`.env`にリネームの上、`ES_CLOUD_ID`と`ES_API_KEY`を適切なものに設定してください。
ちょっと記事を書いている時点ではアクセス先の設定はCloud IDとAPI Keyしか対応していません。他の方法で繋ぎたい場合は、Pythonスクリプトをささっと書き換えてください。upload.pyのここです。

```py
es_client = Elasticsearch(
    cloud_id=ES_CLOUD_ID,
    api_key=ES_API_KEY,
    request_timeout=60,
)
```

## 記事データのアップロード

Pythonはインストールされているものとします。その上で依存ライブラリをインストールします。

```
$ pip install -r requirements.txt
```

では記事をアップロードしましょう。以下のコマンドを実行します。

```
$ python upload.py {corpus_name}
```

ここで、コーパス名(corpus_name)は以下が選択できます。

- dokujo-tsushin
- it-life-hack
- kaden-channel
- livedoor-homme
- movie-enter
- peachy
- smax
- sports-watch
- topic-news

# データ構造

アップロードされるインデックス名は以下のようになっています。

```
livedoor_corpus_{corpus_name}
```

インデックスされるそれぞれのドキュメントは以下のフィールドを持ちます:

  - id: ドキュメントID
  - url: 記事のURL
  - date: 日付
  - title: タイトル
  - content: 本文

indexディレクトリにインデックステンプレートのサンプルがあるので、そちらも参考にしてください。

# おわりに

今回はデータを自分で準備したわけでも、何か新しい機能を紹介したわけでもありませんが、テストデータの準備という頻繁にやらないといけない作業を少し楽にするツールを公開、紹介しました。地味に便利だと思いますので新機能の検証などの際に利用してください。
.NET Parallel LINQ (PLINQ) 

# Parallel LINQ (PLINQ)
https://learn.microsoft.com/ja-jp/dotnet/standard/parallel-programming/introduction-to-plinq

> Parallel LINQ (PLINQ) は、統合言語クエリ (LINQ) パターンの並列実装です。 PLINQ は、LINQ 標準クエリ演算子の完全なセットを System.Linq 名前空間の拡張メソッドとして実装し、並列操作用の追加演算子も備えています。 PLINQ は、LINQ 構文の単純さと読みやすさに加え、並列プログラミングのパワーを兼ね備えています。

やってみよう。

# ノーマル LINQ
```csharp:Program.cs
var source1 = Enumerable.Range(1, 1000000);
var source2 = Enumerable.Range(1, 1000000);

var ret = from r1 in source1
           join r2 in source2
           on r1 equals r2
           where r1 % 2 == 0 && r2 % 3 == 0
           orderby r1
           select r1;
           
Console.WriteLine($"{ret.Count()} {ret.First()}  {ret.Last()}");
// 166666 6 999996
```
# パラレル LINQ
```csharp:Program.cs
var source1 = Enumerable.Range(1, 1000000);
var source2 = Enumerable.Range(1, 1000000);

var ret = from r1 in source1.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism).WithDegreeOfParallelism(4)
           join r2 in source2.AsParallel()
           on r1 equals r2
           where r1 % 2 == 0 && r2 % 3 == 0
           orderby r1
           select r1;
           
Console.WriteLine($"{ret.Count()} {ret.First()}  {ret.Last()}");
// 166666 6 999996
```
・`AsParallel()` で並列化
・`WithExecutionMode(ParallelExecutionMode.ForceParallelism)` で強制する
・`WithDegreeOfParallelism(4)` で並列数を4にする

# ノーマル LINQ (改)
`where r1 % 2 == 0 && r2 % 3 == 0` だとJOIN後なので効率悪いのでは？

```csharp:Program.cs
var source1 = Enumerable.Range(1, 1000000);
var source2 = Enumerable.Range(1, 1000000);

var ret = from r1 in (from r3 in source1
                       where r3 % 2 == 0
                       select r3)
           join r2 in (from r4 in source2
                       where r4 % 3 == 0
                       select r4)
           on r1 equals r2
           orderby r1
           select r1;
           
Console.WriteLine($"{ret.Count()} {ret.First()}  {ret.Last()}");
// 166666 6 999996
```

# パラレル LINQ (改)
同上
```csharp:Program.cs
var source1 = Enumerable.Range(1, 1000000);
var source2 = Enumerable.Range(1, 1000000);

var ret = from r1 in (from r3 in source1.AsParallel().WithExecutionMode(ParallelExecutionMode.ForceParallelism).WithDegreeOfParallelism(4) 
                       where r3 % 2 == 0
                       select r3)
           join r2 in (from r4 in source2.AsParallel()
                       where r4 % 3 == 0
                       select r4)
           on r1 equals r2
           orderby r1
           select r1;
           
Console.WriteLine($"{ret.Count()} {ret.First()}  {ret.Last()}");
// 166666 6 999996
```

# 性能比較 
50回試行の平均
| 種類 | ミリ秒 |
|:--|--:|
| [ノーマル LINQ](#ノーマル-linq)  | 906.2 |
| [パラレル LINQ](#パラレル-linq) (並列数4) | 190.5 |
| [ノーマル LINQ (改)](#ノーマル-linq-改)  | 337.8 |
| [パラレル LINQ (改)](#パラレル-linq-改) (並列数4) | 94.6 |
【Next.js】middlewareでリダイレクトする際にcookieを設定する方法

以下のように記述するとリダイレクト時にcookieをセットできます。


```middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const testUrl = new URL('/test', req.url)
  const response = NextResponse.redirect(testUrl)
  response.cookies.set('some-cookie', 'hello')

  return response
}
```

上記では値が`hello`で`some-cookie`という名称のCookieがセットされます。

また、以下のように記述するとcookieの詳細な設定ができます。

```middleware.js
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const testUrl = new URL('/test', req.url)
  const response = NextResponse.redirect(testUrl)
  response.cookies.set({
    name: 'some-cookie',
    value: 'hello',
    path: '/',
  })

  return response
}

```

https://nextjs.org/docs/app/building-your-application/routing/middleware#using-cookies
GASによる参考文献一覧の文献ID制御

Google Spreadsheetにまとめている[ゆる音楽学ラジオ参考文献一覧](https://docs.google.com/spreadsheets/d/1BBnRDZjznC0IsGdwzJzfae6-uLb8VZTUZtW4eLJT72U/edit?gid=410857103#gid=410857103)ですが、文献を途中に追加したいとき、文献No.を一斉にずらす必要があり、マクロの使用が必要になっていました。
この問題を解決するGASをChatGPTに生成してもらいました。

```Javascript
function incrementCellsAboveThreshold() {
  // スプレッドシートのアクティブなシートを取得
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("動画別出典一覧"); // "Sheet1" をシート名に変更してください
  
  // 閾値を設定します（この値以上のセルに1を加えます）
  var threshold = 670; // ここを変更して閾値を設定してください
  
  // シートのD列のデータを取得
  var data = sheet.getRange("D:D").getValues();
  
  // データをループして閾値以上のセルに1を加える
  for (var i = 0; i < data.length; i++) {
    if (data[i][0] >= threshold) {
      // 閾値以上のセルに1を加える
      sheet.getRange(i + 1, 4).setValue(data[i][0] + 1);
    }
  }
}

```

同様にして文献を削除する場合も実装できます。
Ubuntu22.04でNetgear A8000を使う

# はじめに  
ロボコン界隈で最近注目を浴びつつある、というかだんだん必須になりつつある6GHz、皆さん使いたいですよね(?)
ここ最近発売されたPCは、あらかた6GHzに対応してくれてますが、買い換えるタイミングと合わなかったり、ラズパイとかJetsonとかでも使いたくなるじゃないですか()
と、いうことで用意するものがこちらです。↓  

- Wifi6E対応ルーター
- Ubuntu22.04の入ったPC
- NetGear A8000

Wifi6E対応ルーターが一番コストかかります。道端に生えてることを祈りましょう。

:::note info
A8000は、RaspberryPi OS - Bullseye(kernel 6.1)での動作も確認しています。
時間があればUbuntu22.04 on RaspberryPiでも動かしてみたいですね。
:::

## A8000がmt7921uドライバに認識されるようにする
`/etc/udev/rules.d/90-usb-0846:9060-mt7921u.rules`を作成して以下の中身を書き込みます。
```
ACTION=="add", \
	SUBSYSTEM=="usb", \
	ENV{ID_VENDOR_ID}=="0846", \
	ENV{ID_MODEL_ID}=="9060", \
	RUN+="/usr/sbin/modprobe mt7921u", \
	RUN+="/bin/sh -c 'echo 0846 9060 > /sys/bus/usb/drivers/mt7921u/new_id'"
```
再起動したら5GHzと2.4GHzは認識されてます。多分。

## Linuxの無線規制データベースを最新化する
```sh
wget https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/plain/regulatory.db
wget https://git.kernel.org/pub/scm/linux/kernel/git/sforshee/wireless-regdb.git/plain/regulatory.db.p7s

sudo cp regulatory.db /lib/firmware/
sudo cp regulatory.db.p7s /lib/firmware/
```

wgetで取ってきて、いい感じにコピーしてるだけです。

# 起動時にCountryCodeが設定されるようにする
なぜか初期設定だとJPに設定されてないので設定します。

別にJP以外に設定しても動きますが、
法に触れそうなのでやりません。
```sh
sudo nano /etc/rc.local
```
rc.localは、既になにか書いてある人はそれに`iw reg set JP`を書き足してください。
```rc.local
#!/bin/bash
iw reg set JP
exit 0
```

```sh
sudo chmod +x /etc/rc.local
reboot
```

rc.localを書いて、`iw`コマンドで地域を設定して、実行権限を付与しています。

# 確認してみる

再起動後、
```sh
iw reg get
```
を実行して、
```sh
global
country JP: DFS-JP
	(2402 - 2482 @ 40), (N/A, 20), (N/A)
	(2474 - 2494 @ 20), (N/A, 20), (N/A), NO-OFDM
	(4910 - 4990 @ 40), (N/A, 23), (N/A)
	(5170 - 5250 @ 80), (N/A, 20), (N/A), AUTO-BW
	(5250 - 5330 @ 80), (N/A, 20), (0 ms), DFS, AUTO-BW
	(5490 - 5730 @ 160), (N/A, 23), (0 ms), DFS
	(5925 - 6425 @ 160), (N/A, 23), (N/A), NO-OUTDOOR
	(57000 - 66000 @ 2160), (N/A, 10), (N/A)
```

のように出ていたら大成功です。
いつもどおりwifiの接続設定をすれば6GHzのSSIDが爆誕しているでしょう。

Raspbianの場合、そのままだとWPA3のSSIDに接続できなかったりします。
別途設定してください(気が向いたら書きます)

# 参考させていただいたサイト様
- https://qiita.com/wataniguchi/items/e61130686f3f3e97bde0
- https://zenn.dev/zuzuzu/articles/ubuntu_startup_command

# おわりに
~~そろそろ全国大会ですね。国技館の魔物と電波ヤクザには気をつけて競技をしましょう()~~
記事書くの遅すぎてもう大会終わってますね。
【Langflow】無料でかんたんにチャットボットをつくれてしまう

# はじめに

ひょんなことからチャットボットを触ってみようと思い、色々調べていると「Langflow」に出会いました。

# Langflowとは

https://www.langflow.org/

ChatGPTより

:::note info 
Langflowは、自然言語処理（NLP）のタスクを簡単に構築・デプロイするためのフレームワークで、特に、大規模言語モデル（LLM）を利用したアプリケーションやワークフローの作成を支援します。Langflowは、データの流れをビジュアルに設計できるインターフェースを提供し、ユーザーが簡単にモデルの入出力を管理できるようにします。
:::

LLMを使ったシステムをノーコードで作れてしまうらしいです！


## 環境と手順
- MacBook Air M2
- macOS Sonoma 14.6
- Python version 3.11
- Langflow version 1.1.0

こちらの記事を参考にさせていただきました。

https://liginc.co.jp/643493

以下のコマンドを実行するだけでLangflowを起動できます...!

```
python3 -m venv langflow
source langflow/bin/activate
pip install langflow
langflow run
```

アクセスし、プロジェクトの新規作成を行うとすでにテンプレートが用意されていました。

![スクリーンショット 2024-11-23 12.35.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/60f3971c-86fa-cfeb-7600-5a63a4c3646c.png)

試しに「Memory Chatbot」を選択してみます。


![スクリーンショット 2024-11-23 12.33.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/a2e5ecc0-9d7c-4f9c-a296-28b300b49926.png)

わかりやすいフローになっていました！

画面右上の「Playground」をクリックすると、チャット画面が表示されました。

![スクリーンショット 2024-11-23 12.39.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2889192/14c4d3c4-2e93-cac2-436f-16ff52d18d58.png)

※チャットする際は、OpenAIのAPI Keyを設定する必要があります。

OpenAIに関してはクレジット情報の登録を行い、事前にいくらか支払う必要があります。
今回はお試しで触りたかっただけなので、Geminiを使いました。

https://ai.google.dev/gemini-api/docs/api-key?hl=ja


# おわりに
LLMの学習データづくりを手軽に体験したかったので、Langflowのような環境を使えることはほんとにありがたいです:pray:
React勉強中の人はマインスイーパーを作ってみると良いかもしれない（提案）

# はじめに

React を勉強しているけど、良い題材がないって人は結構いるんじゃないかなと思っています。
TODO リストを作った後はどうしよう、みたいな。
そこで提案です。
マインスイーパーを作ろう！

### マインスイーパーとは

昔の Windows に初期装備されていた地雷探しゲームです。
ググってみると懐かしい画像がたくさん出てきます。

遊び方としては、n 行 * m 列 のマスが表示されていて、マスをクリックして開いていきます。
開いたマスに爆弾があるとゲームオーバーです。
爆弾ではないマスを開くと、いくつの爆弾に隣接しているかの数字が表示されます。
数字をヒントに爆弾以外のマスを全て開き終わるとクリアです。
開いていないマスには爆弾があるかもしれないという目印の旗を立てることができます。

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244354/d96fe4fb-95f7-5927-2745-72c7f893faea.png"/>

詳細なルール: [wikipedia](https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%A4%E3%83%B3%E3%82%B9%E3%82%A4%E3%83%BC%E3%83%91)

マインスイーパーを作ってみることで以下の学びを得られる可能性があります。
- 状態管理をどうするか
- 二重になっているリストの取り扱い
- ゲームっぽく見せるためのスタイリング
- 盤面作成とクリック時のアルゴリズム

# 仕様

ルールに則って以下のような仕様で作成します

- 行数 n は input で指定可能
- 列数 m は input で指定可能
- 爆弾数 l は input で指定可能
- START ボタンクリックで盤面が表示される
- マスをクリックして開く
  - 開いたマスが爆弾だったらゲームオーバー
    - 初手に爆弾を引くとただの運ゲーなので、初手爆弾にはならないように実装する
  - 開いたマスが爆弾以外だったら隣接する爆弾の数を表示
    - 隣接する爆弾がない場合、開いたマスに隣接するマスも開く
      - その開いたマスに隣接する爆弾がない場合、さらに隣接するマスも開く
        - endless...
        - 旗が立っていても開く
  - 爆弾以外の全てのマスを開くとゲームクリア
- マスを右クリックして旗を立てる
  - 既に旗が立っている場合は旗を消す

### 余力がある場合

私は余力がなかったので以下の一つ目（一番簡単なやつ）しか実装していません。

- 「初級」「中級」「上級」ボタンを用意し、クリックすると以下の設定になる
  - 初級: 行数 9, 列数 9, 爆弾数 10
  - 初級: 行数 16, 列数 16, 爆弾数 40
  - 初級: 行数 16, 列数 30, 爆弾数 99
- 既に開かれた数字マスを右クリックしたとき、マスの数字と同数の旗と隣接している場合に限り、マスに隣接する全ての閉じたマスを開くことができる
- 一手戻る、一手進むボタンの実装
- 盤面作成時の乱数をシード固定できるようにする

### 参考実装

私の実装です（参考になるかは不明）。

https://github.com/ahyaemon/minesweeper

デプロイしてあるので実際に遊べます↓

https://minesweeper.ahyaemon.com/

ゲームの状態には class ではなく object を使うようにしました。
盤面クリックなどで状態を変化させる時は、関数の引数として Game オブジェクトを渡す形です。

```typescript
// こんな感じ
click_cell(game)

// もしクラスで書くとこんな感じ
game.click_cell()
```

なんとなく状態管理するときに object の方が楽かな〜と思って class にするのはやめたのですが、ちょっとコードが読みづらくなった気もします。
でも class にした時って状態管理ライブライにインスタンスを渡すのが良いのかとかベストプラクティスがわからないので、もし詳しい方がいたら教えてください:bow:
状態管理には [jotai](https://jotai.org/) を使わせていただきました。

あと無駄なレンダリングを抑えるためにあれこれやっていたときに遭遇して悩まされたんですが、これってもしかして当たり前の挙動なんでしょうか。

https://gist.github.com/ahyaemon/aa040b00ddd5d09eb91961de42cf7690

# 終わりに

人によっていろんな実装があると思います。
他の人の実装も見てみたい（切実）。
もし実装された方がいらっしゃいましたらコメントくださると嬉しいです。
見に行きます。
はじめての転職活動をふりかえる

# はじめに
転職して数ヶ月が経ったので、これまでの活動を振り返っておきたいと思います。
ゆっくりペースで活動していました。

# 経歴
もともとデータ分析をしている人間でした
活動開始時の開発経験年数：2年（言語はバラバラです）
活動開始時の経験技術：Go/Python/Ruby/TypeScript、その他インフラを触り程度


# 活動期間
・約1年半
活動期間を序盤・中盤・終盤に分けて振り返りたいと思います。

# 序盤
## やったこと
・職務経歴の棚卸し
・転職ドラフトのレジュメを作成
・カジュアル面談
・コーディング試験

## 結果
・レジュメの審査が通過
・初月の指名件数は4件
・1位指名あり
・掲示年収は450万〜600万
・選考辞退 or 2次面接でお祈り

# 序盤の振り返り
## 気づき
・思ってたより指名もらえて嬉しい
指名通知メールをお気に入りにするレベルでした。1位指名なんか「何かの間違いでは」と思いつつ飛び上がりました。

・思ってたより掲示年収が高い
経歴も特殊なため市場価値が分からなかったのもありますが、高めに感じる年収額で指名をもらえました。もちろん高い理由があり、企業が儲かっていて採用に投資しているから高いパターンもあれば、これからプロダクトを成長させたくて即戦力のリードポジションが欲しいから高いパターンもありました。選考を受ける際はこの辺りの温度感を把握した上で望むとミスマッチを避けられると思います。

・思ってたよりコーディング試験が難しい
企業によって試験量や難易度はバラバラでしたが、リードポジションで指名をもらった企業の試験は難しかったです。

### 試験の種類
・オンラインコーディングタイプ
指定のサイトにアクセスして、制限時間内に回答する内容でした。
私が受けたのは、技術に関する文章問題とプログラミング問題で構成されていました。

・宿題タイプ
指定のリポジトリからAPIをクローンして続きを実装し、リポジトリにコミットする内容や、
テーブル設計、アルゴリズムを考えてプログラムを作成する内容もありました。


# 中盤
## やったこと
・自己分析や転職軸をかためる
・面接対策
・Qiitaへのアウトプット
個人開発や業務で学んだことや詰まったこと、体験したことをアウトプットするようにしました。
頭の中を整理して理解を深めることが着実な成長に繋がれば良いなと思ってやっていました。

## 結果
・掲示年収は550万〜750万
・同企業から1位指名が2回

# 中盤の振り返り
## 気づき
・データ分析とエンジニアという経験をもつ人材は貴重
・プロダクトリリースして数年経ったことでデータが溜まり、活用したいニーズを持っている企業が多い
・転職ドラフトに参加している企業はスタートアップやベンチャーが多い
・指名をもらえるかどうかはタイミングもある（指名0の回もありました）
・企業側は直近でやりたいことがあって採用活動しているので、選考を急いでいない場合は採用枠が埋まってお祈りされる場合もある
・少ない面接回数で転職先決めるの難しい

# 終盤
## やったこと
・転職の覚悟をきめる
・キャリアドラフトの視聴（モチベーションを保つため）
・引き続きQiitaへアウトプット
・社内でワークショップを開催
・別サービスの併用（BR）
・面接官へ質問しまくる

## 結果
・内定🎉
・掲示年収は600万〜700万（BRだと500万〜600万）

# 終盤の振り返り
## 気づき
・採用担当・現場メンバーと役職陣で採用温度感が異なることが多い（あまりコミュニケーションとれてなさそうな印象を受けたので、入社してからも大変そうに感じてしまいました）

・企業によって文化や求めている能力がちがう（企業Aにはウケた取り組みや考えが、企業Bには疑問に思われることもありました）

・面接官からの質問には意図がある
直近で困っていることがありそれを解決できるスキルをもっているか、これまでやめていった人に共通する考えや行動特性をもっていないか、などを把握するための質問を柔らかい言い回しでしてきます。

・エージェント経由だと高年収の案件を紹介してもらいやすいが、内定確率が高いということではない
余談ですが、BRで紹介してもらった企業の中に転職ドラフトから1回も指名もらったことない企業が数社ありました。逆に指名をもらったことがある企業もありました。

# おわりに
転職活動される（されている）みなさんの参考になればと思います。
Vimを始めるために知っておくこと

> この記事は、「K47deのひとりぼっち Advent Calendar 2024」の Day 3 です。

## 概要

Vimを使い始めて２年目のライトユーザーが伝えるVimの良さと初心者がやるべきこと解説

## 対象と目標
対象者 : これからvimを使い始めようという人
目標 : vimが少しでも好きになる

## Vimのいいところ

- コマンドライン操作
- モードという概念
- カスタマイズ性
- 軽量動作

### コマンドライン操作

コマンドを利用することで様々な操作を高速に実施することが可能になります。後に紹介しますが、テキストエディタ上の移動・編集・ファイル操作などその殆どを独自のコマンドにて操作して行きます。
特に、「:10+コマンド」のように打ち込めば、その該当のコマンドの操作を10回分行えます。
ぱっと聞くだけでなんとなく高速化できそうなのはわかると思います。

### モードという概念

Vim（Vi）にはコマンドモードというもので操作を切り替える事ができ、これによりキーボードから手を離すこと無くほぼ全ての操作が可能になります。
文字の編集や加筆を行う「インサートモード」で文字を編集し、移動や編集コマンドを実行するときには「コマンドモード」に変更するといった感じです。

### カスタマイズ性

特にVimにおいてはVimScriptというもので、Vimの拡張を自分で書けます。
プラグインで操作性を向上させたり、自分なりに使いやすいように作り変えていけます。

### 軽量動作

カスタマイズ次第で特定の開発などに特化した統合開発環境、通称IDEに近い性能を発揮しますが、起動スピードや操作は他のIDEの追随を許しません。

## 初心者が知っておくべき操作

Vimには主に4つのモードがあります。

- Normal
- Insert
- Command
- Visual


### Normal

基本のモードです。
起動時はこのモードになります。
カーソル移動などが行えます。

### Insert

入力状態です。
ファイルに対して文字を追加できます

IやAなどでNormalからInsertへ
InsertでEscキーでNormalへ戻ります

### Command

コマンドモードです。
ファイルへの書き込み。ファイルを開くなどができます。

:でNormalからCommand
EscでNormalに戻るか、コマンド終了時にもNormalに戻ります

### Visual

文字を選択するモードです。

vでNormalからVisual
EscでNormalに戻ります

## 私が使う理由

細かいコマンドや移動方法は他の記事などで解説されてるので省きます。

私が使う理由は唯一つ。
**「慣れてしまったから」**

ナレッテコワイネ

## やるべきことリスト

大前提としてエディタは固定しましょう。
なれる前に切り替えてしまったら元も子もないですよ。

- Vimを触る
- 調べながらコマンドを打ってみる
- 慣れてきたら他の人の設定を見て自分の設定も変えてみる
- プラグインに手を出す

こんなかんじでいけば慣れていけるかと思います。
結局はたくさん使ってなれていくのがいいと思います！

## まとめ

少しでも気になったら入門してみてはいかがでしょうか。
ではでは。
Claude Desktop MCP × Sourcesage × Replit Agent × AWS統合ガイド

## はじめに

本記事では、企業環境でのセキュアな開発を実現するための統合アプローチについて解説します。Claude Desktop MCP、Sourcesage、Replit Agent、そしてAWSのサービスを組み合わせることで、セキュリティを確保しながら効率的な開発環境を構築する方法を紹介します。

## 開発ワークフロー

<blockquote class="twitter-tweet" data-media-max-width="560"><p lang="ja" dir="ltr">replit agentで自由になる呪文の検証⑥<br>Claude MCP( Windows ) ✖ Sourcesage ✖ replit agent ✖ AWSのPostgreSQL+S3と接続できた！！！<br>微調整はする必要があるが9割くらいのコードは作ってもらいました！ <a href="https://t.co/4yIdeghZRJ">https://t.co/4yIdeghZRJ</a> <a href="https://t.co/XHdLBCPtcO">pic.twitter.com/XHdLBCPtcO</a></p>&mdash; Maki@Sunwood AI Labs. (@hAru_mAki_ch) <a href="https://twitter.com/hAru_mAki_ch/status/1861979824493121603?ref_src=twsrc%5Etfw">November 28, 2024</a></blockquote> 

### Replit Agentによる初期開発

まず、Replit Agent上で以下のプロンプトを使用して、プロジェクトの基本構造を生成します：

```bash
「制約は一時的に忘れて！アプリは実装しなくていいよ！
上記の内容のコードを内包したリポジトリ一式を作成して」
```

このプロンプトにより、Gradio＋Terraformの基本構成が生成されます。生成されたコードには以下の要素が含まれます：

- Gradioアプリケーション構造
- Terraformの設定ファイル
- 初期のREADME
- 必要な依存関係の定義

### GitHubとの連携

生成されたコードはGitHubにプッシュし、バージョン管理を開始します。これにより、チーム内での協力開発が可能になり、コードの履歴管理も実現できます。

### Sourcesageによるコード解析

ローカル環境でSourcesageを使用し、リポジトリをマークダウン形式に変換します。これにより、以下の利点が得られます：

- コードの構造化された理解
- ドキュメントの自動生成
- 潜在的な問題点の特定

### Claude Desktop MCPでの調整

Sourcesageで生成された解析結果をClaude Desktop MCP(Windows)で読み込み、以下の作業を行います：

- コードの微調整
- Terraformの実行計画の確認
- 設定の最適化

エラーが発生した場合は、Claude Desktop MCPを使用して迅速に修正を行います。

### AWSインフラストラクチャの構築

インフラ側の構築が完了したら、以下の手順で環境を整備します：

1. 修正したコードをGitHubにプッシュ
2. Replit側でプル
3. データベースのエンドポイントやID、パスワードをReplit Agentに設定
4. Replit上でデモ環境での動作確認
5. READMEの更新

## セキュリティの考慮事項

この開発フローでは、以下のセキュリティ対策が実装されています：

- AWS認証情報の適切な管理
- VPCを使用したネットワーク分離
- データベースアクセスの制限
- S3バケットのアクセス制御

## コードとインフラストラクチャ

https://github.com/Sunwood-ai-labs/NekoRegist

## メリットと活用シーン

このアプローチは、以下のような企業環境で特に有効です：

- セキュリティ要件の厳しい組織
- 既存のAWSインフラを活用している環境
- チーム開発が必要なプロジェクト
- データの機密性が重要な案件

## まとめ

このワークフローを採用することで、以下の目標を達成できます：

1. セキュリティを確保した開発環境の実現
2. 効率的なコード生成と管理プロセス
3. チーム間のスムーズな連携
4. 本番環境に向けた段階的な開発

企業の既存のAWSインフラストラクチャを活用しながら、セキュアかつ効率的な開発環境を構築することが可能です。


<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
24/11/28 読書記録 ~ソフトウェアテストの教科書~

# 書籍
[【この1冊でよくわかる】 ソフトウェアテストの教科書](https://amzn.asia/d/6jSYRVM)

# 書籍を読む目的

 - [ ] 「品質」を理解する
 - [ ] 品質を担保できるテストを理解する


## Chap03. ホワイトボックステストとブラックボックステスト

### 学び 📝

#### 制御フローテスト

単体テストを記載する時、意識したい考え方。
カバレッジレベルは特に重要。
デシジョンカバレッジを意識することが多い。

複合条件カバレッジは、モジュールの大きさによって複雑化するイメージがある。
みんながどの基準を設けているかは気になる。

### Chap3 感想 :writing_hand_tone5:

制御フローテストは学びがあり、カバレッジ基準は覚えていきたい。
テストを書く時はカバレッジ意識して記載したい。

# Part2. さまざまなテスト技法
## Chap04. 同値分割テスト・境界値テスト

### 同値分割テスト

単体テストを作成する中で、有効値はどうなるか？無効値はどうなるか？は考えるべきだと思う。
境界値テストと異なり連続した値になるとは限らない、というのも学び。

### Chap4 感想 :writing_hand_tone5:

ホワイトボックステストの中で必要となる考え方が述べられていた。
単体テストを記載する時は基本的に境界値を把握し、無効値、有効値の両方を担保する記載が望ましいのだと思う。
生成AIを利用すれば、特に気にせず担保できそう。

## Chap05. デシジョンテーブルテスト

### 学び 📝

#### デシジョンテーブルテスト
ソフトウェアの動作が複雑に関係し合う場合の漏れの確認に有効なテスト。
でも、実際実施している企業はいるのかが気になる。
これまでの業務で経験したことのないテスト。

しかし、複雑な条件が必要である場合は思考の抜け漏れに気づくためにも実施を試みるのも良いかも。

### Chap5 感想 :writing_hand_tone5:

利用する場面も限られているので、必要となり次第読み返したい。
勉強した結果を恥ずかしいと思う必要はないでしょ

# 概要
「勉強した結果を恥ずかしいと思う必要はないでしょ」・・・私が上司に言われた言葉です。
勉強への姿勢が少し変わった気がするので、色々振り返ってみます。

# 経緯
他チームの人「すみません、これこれこういうことがやりたいんですがわかりますか？」
私「え、うーん…わかんないのでぐぐります…」
私「えっと…これとかどうですか…？」
他チームの人「それはもう試したんすよね…」
私「ｴﾄ…ｴﾄ…」
他チームの人「すみません、ありがとうございます。自分らで見てみます」
私「ﾜｧ…」

私「せっかく有識者的な扱いしてもらってるのに答えられないと恥ずかしいですね」
**上司「勉強した結果を恥ずかしいと思う必要はないでしょ」**
私「！！！」

# 有識者として扱ってもらえるのはこれまでの私の勉強の結果
これは盲点でした。
そもそも有識者扱いされてなければ質問もされてなかった。

# 勉強してきてよかった
資格取得の記事にもちょこちょこ書いてますが、「資格取得はセルフブランディング程度にしかならないのでは？」というのが私の主張でした。
ところが、例えば以下のように、ちょっと振り返ってみたら役に立った瞬間があったのです。
| 資格名| 役立ちポイント |
|:-:|:-:|
|  LinuC1 | 基本コマンドがわからないと仕事にならない  |
| LinuC2  | ACL設定でトラブル踏んだ時に一瞬で原因にたどり着いて対処できた  |
| LinuC304  | 業務で触るHA構成サーバのことがよくわかる  |
| OSSDB silver  | 「何も考えずにこれを流せ」と渡されたSQLがエラー吐いてきた時に対応できた  |

私の勉強の目的は大体こうです
- 報奨金欲しいなぁ
- 今後転職するときは良いところ行きたいし多少有利かなぁ
- 評価上がらないかなぁ
つまり自己満足と自己実現の世界に閉じていました。また、自己実現が成るのもまだ当分先になるのでいつまでも欲求が満たされてなかったのです。
それが今回の言葉で少し救われた気がしました。

# 何が言いたいかというと
- 資格取って有識者扱いされている現状が既に自己実現の一歩だった
- 満たされない欲が満たされた
- ~~アドカレ25日完走分の記事を書くのにはネタが足りない~~
[Vue.js]refのオブジェクトにプロパティ追加した時にwatchが走らない？


vueアドベントカレンダー3日目です!

https://qiita.com/advent-calendar/2024/vue

# サンプル

ボタンをクリックすると動的にプロパティを追加するコードがあるとします


```vue
<script setup>
import { watch, ref } from 'vue'

const refObj = ref({})

function add() {
  refObj.value["add"] = "hello"
}

// addしても動かない
watch(refObj, () => {
  console.log("watch ref", refObj.value)
})
</script>

<template>
  <div>{{refObj}}</div>
  <button @click="add">add</button>
</template>
```

このwatchはプロパティ追加時には動作しません


deep:trueをつければwatchが動きます

```js
watch(refObj, () => {
  console.log("watch ref", refObj.value)
}, {deep: true})
```

もしくは、reactiveにしてもプロパティ追加をwatchできます

```js
const reactiveObj = reactive({})

function add() {
  reactiveObj["add"] = "hello"
}

watch(reactiveObj, () => {
  console.log("watch reactiveObj", reactiveObj)
})
```


なぜ？ :thinking: 

# watchのソースを読みます

https://github.com/vuejs/core/blob/main/packages/reactivity/src/watch.ts

## watchの対象がrefのとき

このgetterを監視してcallbackを呼ぶようです

.valueが変わらないのでプロパティ追加してもcallbackは呼ばれません

```js
  if (isRef(source)) {
    getter = () => source.value
```
https://github.com/vuejs/core/blob/5a5406d002f568e928489920d0dcc7086c808a8d/packages/reactivity/src/watch.ts#L153-L154

つまりこのように.valueに新しいobjを入れれば動作します
```js
function add() {
  refObj.value["add"] = "hello"
  // valueが変わるのでwatchが動く
  refObj.value = {...refObj.value}
}
```


## deep=trueの場合

traverseで再帰的にプロパティを見ているので追加してもわかります

```js
  if (cb && deep) {
    const baseGetter = getter
    const depth = deep === true ? Infinity : deep
    getter = () => traverse(baseGetter(), depth)
  }
```
https://github.com/vuejs/core/blob/5a5406d002f568e928489920d0dcc7086c808a8d/packages/reactivity/src/watch.ts#L207-L211

そしてcallbackを呼ぶ条件に、deepがあるのでcallbackが呼ばれます
```js
      if (
        deep ||
        forceTrigger ||
        (isMultiSource
          ? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
          : hasChanged(newValue, oldValue))
      ) {
```
https://github.com/vuejs/core/blob/5a5406d002f568e928489920d0dcc7086c808a8d/packages/reactivity/src/watch.ts#L243-L249

## reactiveのとき

こちらはreactiveのときの条件です
reactiveGetterの中でtraverseしています

```js
  } else if (isReactive(source)) {
    getter = () => reactiveGetter(source)
    forceTrigger = true
```
https://github.com/vuejs/core/blob/5a5406d002f568e928489920d0dcc7086c808a8d/packages/reactivity/src/watch.ts#L156-L158

そして先程のcallbackを呼ぶ箇所で、forceTrigger=trueなのでcallbackが呼ばれます

```js
      if (
        deep ||
        forceTrigger ||
        (isMultiSource
          ? (newValue as any[]).some((v, i) => hasChanged(v, oldValue[i]))
          : hasChanged(newValue, oldValue))
      ) {
```
https://github.com/vuejs/core/blob/5a5406d002f568e928489920d0dcc7086c808a8d/packages/reactivity/src/watch.ts#L243-L249

# おわり

動作は変わる可能性もあるので注意して下さい :astonished: 

明日は @kosuke-naito さんです!
FancyWMとWindHawkで快適なWindowsを作る

> この記事は、「K47deのひとりぼっち Advent Calendar 2024」の Day 2 です。

## 概要

FancyWM と　WindHawk を導入して、かっこいい環境を作った。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821686/51e1b881-d60b-4032-e482-3b5aa7311b07.png)
こんなかんじ

## FancyWM

https://github.com/FancyWM/fancywm

> FancyWM - Windows用ダイナミックタイルウィンドウマネージャ

これは、Linuxのi3-wmのようにタイル状にウィンドウを配置するためのソフト
設定が多くて思ったよりもカスタマイズできる

## WindHawk

https://windhawk.net/

Windowsの細かい部分をカスタマイズできるソフト
私はタスクバー周りのカスタマイズに使用

## リザルト

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821686/51e1b881-d60b-4032-e482-3b5aa7311b07.png)

## こだわってるところ

i3gapsのようにちょっと大きめのギャプをつけて見やすく
分割数は最小限に
Windows11の真ん中のタスクバーはそのままに

## まとめ

みなさんもぜひ自分なりの快適な環境を作ってみてください！
Expanding Symbol beyond Japan!

## Symbolを日本国外にも知らしめたい！ ~ English version Symbol Payment Shoplist, "Symbol Payment Map"~
### EN
One of the use cases for Symbol is payment, and it is known that there are shops that accept Symbol payment. 
And a site "Everyday Symbol" is the site that lists such shops, but there was no site in English.
I think payments is the most obvious use case for the average non-technical person to showcase the Symbol blockchain, so I created a list of payment shop website, [Symbol Payment Map](https://lab-radiointerference-symbol.my.canva.site/symbol-payment-map) as an opportunity to expand Symbol outside of Japan.

### JP
ブロックチェーンのユースケースとして非技術者であっても一番わかりやすいものは、「決済」。
日本では結構決済できる店舗がありますね。すでに日本語で店舗を紹介している「Everyday Symbol」もあります。
ということで、英語にてSymbol決済店舗まとめサイト、[Symbol Payment Map](https://lab-radiointerference-symbol.my.canva.site/symbol-payment-map) を作ってみました。

---
### All of you, spread the Symbol around the world! さぁみなさん拡散の時間です！ →→→ [Symbol Payment Map](https://lab-radiointerference-symbol.my.canva.site/symbol-payment-map)
スクラムマスターにおけるチームの障害物の取り除き方

この記事はZOZOアドベントカレンダーSeries8の初日の記事です。

# 障害物の除去はスクラムマスターのしごとの一つ

「ここの仕様が曖昧で実装できない。どうなっていますか？」「この実装をするには他部署への連携が必要だ」「ミーティングが多く時間を取れない」などなどスクラムチームが仕事をしていく上での障害を取り除いていくのはスクラムマスターのしごとです。

ここで、スクラムマスターはPOに仕様を聞きにいく、他部署のメンバーにアクセスする、ミーティングを減らすよう働きかける。ということをするのは良いこととは言えません。


# むしろ移譲してしまおう

スクラムマスターはスクラムチームにティーチングやコーチングを駆使してチームのパフォーマンスを上げていくことが大事です。
スクラムマスターが自ら動いて障害物を取り除いていくのではなく、チームに責任、活動、オーナーシップを移譲するように働きかけ、チームが自ら動いていけるようにしていくのが良いです。障害物を取り除いていくために必要な権限を移譲していくのです。

自分たちで問題を解決していけるために権限を移譲し、スクラムマスターは良い解決策を見つけるのを手助けする、コーチングする、ティーチングすることによって、チームは自己組織化していきます。

# サーバントリーダーは難しい

スクラムマスターはサーバントリーダーだと言われています。サーバントリーダーシップという言葉は決して新しい言葉ではないですが、未だにただただ奉仕するリーダーと思われている節もあったりする用語です。
スクラムガイド2020では、サーバントリーダーという言葉から真のリーダーという言葉に置き換えられました（ジェフサザーランド曰く本質的には同じ意味とのこと）。
チームがどうしたらもっとうまくいくだろう。チームだけでいかに完結できるようにしていけるだろう。ということを考えていくと、自ら動いてあれこれチームに与えるより、権限を移譲しチームが自身で考えて結論を出してもらうことでチームがより良く回っていくことがわかってきます。
これはタスクをメンバーに振ったり、指示したりというこれまでのマネージャー的なリーダーシップとはまた違ったリーダーシップの形です。
コーヒーを入れたり、お菓子を用意したり、ただミーティングの司会をしたりするのもまた違います。

スクラムチームが自己組織化して自ら問題を解決していくように成長していくことはスクラムで開発していく上で必須のことです。これが実現しないと、プロダクトオーナーがスクラムチームに付きっきりとなりビジネス面が疎かになったり、スクラムチーム内でなかなか自己完結せず伝達・やり取りが増えたりしてチームとして価値が出しづらくなっていきます。

スクラムマスターの役割はこの点で大変重要な役割であったりするわけですね。
[初学者用] JavaScriptの配列　要素の追加、更新

# 初学者のメモ

自分が忘れないようにするためのメモ書きです。
今回は、 **JavaScriptの配列**に関してです。特に、要素の出力、更新、追加に関してです。あくまで、自分の知識の確認ですので、未完成です。ご容赦ください。

# 配列及び要素とは

まず、**配列**とは、以下のように記述し、複数の値を管理する箱のようなものです。また、**要素**とは、配列の中の各々の値のことです。
```JavaScript: 配列
配列名 = [値1, 値2, 値3];
// 要素を[]で囲む
// 値は , で区切る

```

配列の要素には、区別するための**インデックス番号**が付いています。
これは、for文、if文などで使えますがこれについては次回以降の記事で。

# 配列の要素の追加及び更新

配列の要素を後ろに**追加**したり、要素の値を **更新**することができます。
以下のような記述方法です。
__<font color="red">※どちらもインデックス番号に気を付けること！</font>__

```JavaScript: 要素の追加、更新
//追加(値4を追加)
let add = [値1, 値2, 値3];
//add[3] = "値4";   左のような書き方もあるが、以下を推奨する

add.push("値4"); //これで末尾に追加
console.log(add); //[値1, 値2, 値3, 値4]

add.unshift("値5") //これで先頭に追加
console.log(add); //[値5, 値1, 値2, 値3]


//更新(値3を値6に更新)
let change = [値1, 値2, 値3];
change[2] = "値6";
console.log(change); //[値1, 値2, 値6]
```

# おわりに

今回は配列についてまとめました。for文とかif文の使い方も書こうと思ったんですけど、長くなりそうなのでまたの機会に。（書いたらurl貼ります）

今度は繰り返し処理、条件分岐でも書こうかな。

それでは、ばいなら～

#

2024.11.28 執筆
2024.11.29 加筆修正 **要素の追加**に関する記述をより分かりやすく (@juner 様からのご指摘)
【PHP】Traitって何？

## はじめに
1月から実務でPHP、Laravelを扱うことになり、キャッチアップに勤しんでおります。
Sanctumを使って認証機能を実装しようとした時にTraitという言葉が出てきて恥ずかしながら何のことかわかりませんでした笑
その時に軽く調べたことをメモとして残します！

### きっかけ
`php artisan install:api` コマンドでSanctumをインストールしたことが始まりでした。

```php
INFO  API scaffolding installed. Please add the [Laravel\Sanctum\HasApiTokens] 
trait to your User model.
```

HasApiTokensというtraitをUserモデルに追加しろよというメッセージが出力されておりました。

## Traitって何？
簡単にまとめます

1. **Traitはモジュール的なもの**
    - クラスに再利用可能なコードを提供する仕組み
    - 複数のクラス間で共有したい機能をまとめて定義したい時に使う
    
2. **Trait内のメソッドがクラスで使えるようになる仕組み**
    - **`use`** キーワードでクラスにTraitを「組み込む」ことで、そのクラスの一部のように振る舞う
    - Trait内で定義されたメソッドやプロパティは、`use` したクラスのインスタンスからそのまま呼び出せる


クラスに部品を埋め込むようなイメージですね！

### Traitの定義
```php
trait HogeTrait {

Public function hoge() : void {
  print 'hoge!!'
}

}

```php
### Traitの使用

```bash
class Foo
{
    use HogeTrait;

    public function callHoge()
    {
        $this->hoge();
    }
}
```
上記のようにuseで指定することでそのクラスのインスタンスからtraitのhoge関数を呼び出せる

**Traitの制約や特徴**
- ~~定数は持つことができない~~　誤った情報でした(失礼しました）
    - コメントにて教えていただけたのですがPHP8.2以降ではtraitが定数を持てるようになっているようです
- プロパティ、抽象/静的/インスタンスメソッドのみ使用可能
- クラスの継承、インターフェイスの実装はできない
- トレイとそのものをインスタンス化することはできない
- useはtraitブロックの中でも利用できるので、他のtraitを利用して別のtraitを実装することも可能
- Traitはカンマ区切りで複数指定することも可能　**例:**`use HogeTrait, FooTrait, PyoTrait;`
- Traitは型を持たない、実装のみ提供


## Traitの注意点
### 1.型は持たない
型を持つことができないので
interfaceとあわせて利用するのがお作法となるようですね。
Traitで定義されたメソッドを持つinterfaceを定義
```php
Ihoge {
function hoge();
}

class Foo implements Ihoge {
use HogeTrait
}
```
こうすることで
- 型チェックが可能になる
LoggerInterface を使うことで、instanceof やメソッドの型引数で型の安全性を担保
- コードの再利用と型保証の両立
Traitで共通ロジックを提供しつつ、インターフェースで型を保証する設計にする
- メソッドシグネチャの契約
インターフェースに記述したメソッドのシグネチャが統一され、予測可能なコードに

保守性や予測可能性をTraitを使用しつつも担保できるようになります。

### 2.名前衝突に注意する必要がある
クラス、トレイトと複数使用することで名前衝突が起きる可能性に留意しなければなりません。
名前が衝突した場合は下記の優先順位で動作します。
- 現在のクラスのメンバー
- トレイトのメンバー
- 親クラスのメンバー

トレイト同士で衝突したらエラーになります。

### まとめ
簡単にですが以上になります。
Traitは抽象化クラスで表現することが難しい処理やプロパティを切り出したい時や複数のクラスで共有されるような処理やプロパティをまとめたい時に利用されることが多い機能のようですね。
今回の例では、HasApiTokens という Token生成に関わる処理やプロパティを持つTrait を User モデルに組み込むことで、認証に必要な機能を備えたUserモデルを簡単に実現するために利用している感じでした。

### 参考

https://www.shoeisha.co.jp/book/detail/9784798168494