OmniAICreator/Qiita-1.07M huggingface dataset:
Astroを使い始めるための準備【環境構築時のエラー対応 】

Astro。2022年に生まれたフロントエンドフレームワークです。  

もう名前がかっこいいですよね。とにかく速い動作が特徴で、公式が"Astroを使えば、遅いウェブサイトを作るのはほぼ不可能になる"と宣言しているほどです。素敵。

さて、公式の開発環境準備のドキュメントの手順通りにAstroを組み込んだプロジェクトを作成していくわけですが、プロジェクトの作成時、そしてプロジェクト実行時にそれぞれエラーが発生しました。  
エラー発生した状況とその対応策をご紹介しますので、皆さんの助けになれば幸いです。
公式ドキュメント：https://docs.astro.build/ja/tutorial/1-setup/1/

## エラーその１：依存関係のインストールに失敗  
指定されたバージョン以上のNode.jsをインストールした後、任意のフォルダでcreate astroのコマンドを実行しますが、その際に依存関係のインストールに失敗というエラーが発生しました。
```
C:\Users\astro練習>npm create astro@latest

> npx
> create-astro


 astro   Launch sequence initiated.

   dir   Where should we create your new project?
         ./super-singularity

  tmpl   How would you like to start your new project?
         A basic, minimal starter

  deps   Install dependencies?
         Yes

   git   Initialize a new git repository?
         Yes

      ▲  error Error
      ▲  error Dependencies failed to install, please run npm install to install them manually after setup.
      ✔  Project initialized!
         ■ Template copied
         ■ Dependencies installed
         ■ Git initialized

  next   Liftoff confirmed. Explore your project!

         Enter your project directory using cd ./super-singularity
         Run npm run dev to start the dev server. CTRL+C to stop.
         Add frameworks like react or tailwind using astro add.

         Stuck? Join us at https://astro.build/chat
```
このエラーの原因ですが、 **プロジェクトを作成するフォルダのパスに日本語が入っていること** でした。
今回の場合だと、astro練習の名前をアルファベットのみに変更すれば、問題なくプロジェクトが作成できました。

## エラーその２：astroのコマンドが認識されない
astroのプロジェクトが作成できたら、とりあえず実行してローカルサーバーを起動してみると思います。その際astroというコマンドが認識されない事象に遭遇しました。
```
C:\Users\astroPractice\solar-singularity> npm run dev

> solar-singularity@0.0.1 dev
> astro dev

'astro' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```
node_modulesの中を見るとあら不思議、astro関連のフォルダが全然入っていませんでした。
この場合の対処ですが、astroをグローバルにインストールしてから「npm create astro@latest」でプロジェクト作成すると、自動的にastroの依存関係もインストールしてくれます。

↓astroのグローバルインストール
```
npm install -g astro
```

astroのグローバルインストール後に作成したプロジェクトで再度「npm run dev」で実行すると、ローカルでサーバーが立ち上がり、画面が表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3954006/0d44b57e-b99a-d8e4-f300-cdc31cc6af5d.png)
 *beautiful* 

後はreactやVueみたいに開発していくだけですね。
皆様が良いastroライフを送れますように。
SpringBoot + React + MySQL マルチコンテナでサービスを起動する際に、DB起動を待ちきれずエラーになる


こんにちは、hidepon4649 です。
マルチコンテナで、DB が完全に起動する前にバックエンドサービスが起動しテーブルが読めないエラーが発生しハマったのでメモします。

DB は MySQL に限らず、他の DBMS 製品でも同じ理屈だと思います。

# 発生したエラー

- schema.sql で create 文があるのに、一部のテーブルが読めない。
- data.sql で insert 文があるのに、データが読めない。

```エラーログ
SQL Error: 1146, SQLState: 42S02
Table 'データベース名.テーブル名' doesn't exist
```

DB が完全に起動する前(注 1)にバックエンドサービスが起動しているようです。
(注 1)schema.sql, data.sql が完全に実施される前

# 構成

- frontend, React
- backend, SpringBoot
- db, MySQL

デバッグの前後で構成は変えていません。変更したのは docker-compose.yml のみ。

# デバッグ対応

対応内容

- 1 .depends_on の db に「condition: service_healthy」 を付ける。(healthcheck と連動)
- 2 .depends_on の flyway に「condition: service_completed_successfully」 を付ける。(flyway を使っている場合のみ)

パラメータの詳細は下記ドキュメントを参照
<https://docs.docker.jp/compose/compose-file/compose-file-v3.html#depends-on>

- service_healthy: 依存サービスを開始する前に、依存関係が(healthcheck)によって示されるように、"healthy"であることが期待されます。
- service_completed_successfully: 依存サービスを開始する前に、依存関係が正常に終了していることを指定できる

以下がデバッグ対応です。

## デバッグ前

(注：エラーに関係無い箇所は記述を省略しています)

```docker-compose.yml
version: '3'
services:
  backend:
    depends_on:
      - db
      - flyway

  frontend:

  db:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "db", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}"]
      interval: 10s
      retries: 3

  flyway:
    depends_on:
      - db
```

## デバッグ後

(注：エラーに関係無い箇所は記述を省略しています)

```docker-compose.yml
version: '3'
services:
  backend:
    depends_on:
      # ---- 変化点 ----
      db:
        condition: service_healthy
      # ---- 変化点 ----
      flyway:
        condition: service_completed_successfully

  frontend:

  db:
    healthcheck:
      test: ["CMD", "mysqladmin", "ping", "-h", "db", "-u", "root", "-p$${MYSQL_ROOT_PASSWORD}"]
      interval: 10s
      retries: 3

  flyway:
    depends_on:
      # ---- 変化点 ----
      db:
        condition: service_healthy
```

以上

私が上述のエラーでハマった際に、
condition が肝だという情報がなかなか見つけられなくて無駄に時間を費やしてしまいました。誰かのお役に立てれば幸いです。(私の検索能力が低いだけかも‥？)
生成AIと管理者権限ないけど現場でキャッシュクリアさせたいお話

ChatGPTが出てきてから様々なツールが誕生して、それぞれの職種での使い方が日進月歩な状態で時間が経過している。

これまではDrupalを利用していて手詰まったら、海外サイトで検索したり、Drupal.orgでのIssueで同様なことがないか探したり、自分で解決する必要性が高かった。日本語での情報がなく、時間だけが過ぎていくことも度々あった。

ところがChatGPTがDrupalについて聞けば何でも答えてくれる時代に変わった。2023年まではイマイチな状態であったが2024年になったら、一応業務でも使える認識へと、心の中では変わっていた。

生成AIと向かいあえば、自分が作りたいモジュールも完成できるレベルになったのは嬉しいし、ありがたい。豊富なアプローチ方法や考えつかなかった方法も教えてくれる。

Drupalを利活用している身としては、この体験や情報をアウトプットする必要があると感じていた。

この知見を自分の中で閉まっておくと何も残らない⋯。

他業界のセミナーやイベントに行ってもDrupalの認知はされていても、日本語でのリソース不足との意見は多かった。

Google検索ではDrupalはブルーオーシャンでコンテンツを待っている状態だ。

Drupalの活用方法や事例を共有することに、取り組んで行かなければと思った2024年末。

***

閑話休題、Advent Calendarのお話です。

社内などでDrupalを使っていると、「コンテンツ更新しても反映されません」とか「差し替えた写真が反映されません」とか、エスカレーションされる体験をよくします。

別ブラウザで確認してもらったり、ブラウザキャッシュをクリアして反映できれば話は終わるのですが、話が終わらない場合もあります。そうなるとDrupalのキャッシュクリアしないと解決しません。

サイトの規模感によりますが、Drupalの管理者権限を与えていれば各自でキャッシュクリアしてもらえば解決できます。しかし、最小限の役割（ロール）権限しか与えていない場合、現場では解決できないのでエスカレーションが来てしまいます。

今回はいつでも全キャッシュクリアできる小規模感サイト向けの話題です。

そんな訳で最小限のロール権限でもキャッシュクリアできるカスタムモジュールをChatGPTとデバッグ含めて７回ほどやり取りして作ってもらいました⋯。
匿名ユーザーでは実行できないこと・付与したロール権限でキャッシュクリアできることを検証。

https://gitlab.com/bassline121/custom-cache-clear


![_スクリーンショット-2024-12-14-1.01.31.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59566/30c90cfb-ff7f-58e5-fcf2-08f75b0396c3.jpeg)
使い方は、モジュールをインストールしたら実行させたいロールに権限を付与します。

キャッシュクリアするpathは
/admin/custom-clear-cache
です。

![___スクリーンショット-2024-12-14-1.07.55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59566/a33bb5a2-bbfc-9c09-3e7c-4ef885319593.jpeg)

カスタムブロックライブラリで編集権限向けのブロックを作成します。ブロックレイアウトで各テーマに作成したブロックを置きたい箇所に配置します。


![スクリーンショット-2024-12-13-23.02.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59566/cf8a0769-daf1-a58a-9da2-4e0979dbd473.jpeg)

思いついて10分程度でカスタムモジュールを作成しました。これでエスカレーション回数が減ったら嬉しい。

今後は生産性や利用する側のスキルが求められます。
ShouldBindJSONの内部処理

```go

func SubmitUserDetail(c *gin.Context) {
    UserDetail := &models.UserDetail{}
    if err := c.ShouldBindJSON(UserDetail); err != nil { 
        c.JSON(http.StatusBadRequest, gin.H{"message": "不正なリクエストです"})
        return
    }
    if err := models.RegisterUserDetail(db, UserDetail); err != nil {
        c.JSON(http.StatusInternalServerError, gin.H{"err": "ユーザー情報登録できませんでした"})
        return
    }

    c.JSON(http.StatusOK, gin.H{"message": "登録が成功しました"})
}
```

このコードだが、
```go
gin.Context) {
    var   UserDetail ＊UserDetail
```

これでもバインド出来る。
これだとUserDetailに初期値nilが入るため構造体にバインド出来ないように思えるが、
ShouldBindJSONは引数がnilの場合、メモリ上に新たに構造体オブジェクトを作成しバインドするのだ。
もうプレゼンで緊張する必要はない！！

皆さんこんにちは。AIが好きなエンジニアです。（得意ではない）
私の部署では四半期ごとに成果を発表するプレゼンがあります。

しかーーーーし！！私は極度の緊張しぃで発表するのがとても苦痛です。
そんなあなたにご紹介するのがAIアバター作成の「HeyGen」です。

# HeyGenとは？
AI技術を活用して、簡単かつ迅速にプロフェッショナルな動画を生成できるクラウドベースのプラットフォーム。このサービスの最大の特徴は、ユーザーが入力したテキストを基にリアルなAIアバターが話す動画を自動生成する点。複雑な編集作業や高価な機材を必要とせず、直感的な操作で短時間に高品質な動画を作成できるっ！！

## 自分のAIアバターを作ってみよう
[HeyGen](https://app.heygen.com/get-started)
↑まずはアクセスをして、Get startedから作成をしましょう。

お恥ずかしいので私の作成結果を添付することはできませんが
あっという間にできました。
ちなみに私がプレゼンじにAIアバターに話させた内容はこんな感じです。↓
![スクリーンショット 2024-12-14 1.11.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2360194/37f4c6b2-103c-b065-f9ef-2c803c8a7eae.png)
漢字を訓読みで読んでしまうところがあるみたいなので、そこは実際に聞きながら調整をかけて適宜ひらがなで指定する感じです。

# 使ってみた感想
言うまでもなく、発表が楽（何もしていない）のもありますが、逆に言うと「これだけは伝えたい」ものを言い忘れることがありません。
まだまだ日本語の発音がおかしいところはところどころあるのと、私のネイティブ関西弁が標準語に置き換わっていた悔しさはありましたが概ね合格点かと思います。
「顧客定例などの報告で使えるのでは〜」といった声が早速上がっているので嬉しい限りです。
これからも私たちエンジニアは「AIを使い倒す側」として活用していきましょう。

おわり
文系大学生がエンジニアっぽいなにかになろうとした①

## エンジニアとはなんぞ

そこのあなた、エンジニアですか？

そうですよね、だと思いました。
ということで（おそらくエンジニアであろう）そこのあなたにお伺いします。

***エンジニアってなんですか？***

自分は今までエンジニアと関わったことはありませんでした。
というか関わるとはこれっぽっちも思ってませんでした。
そんな自分が約2年間、エンジニアスクールに通い、友達と一緒にPC並べてC言語書くことになるとは一体誰が想像したでしょう。

文系で完全に知識ゼロの人間から見た『えんじにあ』という職、世界。
何もかもが新鮮で、それは驚きと発見の連続でした。
せっかくなので、エンジニアとはなんぞ？　という所から始めてみましょう。
この記事がこれからエンジニアになりたい人、でも一歩踏み出せない人の参考になれば幸いです。

## 数学ができない。
本当に数学ができなかった。
微積とか、関数とか、ぶっちゃけ単語を見るだけでアレルギー。
模試は20点くらい、ひどいと10点とか（200点満点）

それでもソードアートオンラインの影響で天才科学者 茅場には憧れていた。
そんな典型的な文系でした。

sate,
勘が良いみなさんのことです。
エンジニアにとって数学は必須スキルではない（と思いたい）、と思うでしょう。
しかしド文系からすると、そんなこと知る由などありません。

というか当時の自分（高校生）はエンジニアと聞いたら、マトリックスみたいに文字がビャー！　って出てくるアレとフード被ったなんか賢そうな人、みたいなイメージしかありませんでした。

理系コースの人が物理だの数3をやっている間、我々文系は”アルカイックスマイル”とか、”ヴィットーリオ・エマヌエーレ3世”とか、”マルクス・アウレリウス・アントニヌス”とかを頭に叩き込んでいた訳です。そんな自分もなんやかんや大学生になったのですが、新型コロナの影響で家から出られない生活が始まります。

まぁ暇です。

何もできないし、とにかく家で小説を読み、映画を見て、音楽をするという何とも文化的な生活を送っていました。

## ”エンジニア”との邂逅

ある日の深夜、何気なくテレビを垂れ流していました。
するとカッコいい近未来的な音楽と、ピクトグラムを使ったオシャレなCMが。

「問題解決型学習」「エンジニア養成機関」「学び方の学び方」

「誰でも挑戦できる学校 42Tokyo。」
<iframe width="560" height="315" src="https://www.youtube.com/embed/i9h8Jy8Zy0I?si=uSfN7SBRqaqczQfF" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>


そう締めくくられた1,2分程度のCMが切れた瞬間、ビビッときちゃったんです。
この時ばかりは、生活リズムが狂いに狂っていた自分を褒めてあげたいですね。

寝る前に「42Tokyo」を検索して、この時初めて『エンジニア』という職種が頭の中にやってきた訳です。

さて、エンジニアという単語と出会ったものの、未だド文系には多くのハードルが立ちはだかります。実はここからスクールを受験するまで、約半年以上空くのですがそれはまた別のお話。

次回は「僕と試験と42」です。
またお会いしましょう。
Unreal Engine 5.5.0でMidiファイルを読み込んで再生するプラグインを作りました

# はじめに

おはようございます。Sigcomのleicoです。今回は [Unreal Engine Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ue) に参加させていただきました。  
この記事では、UE5.5で作成したMIDIを再生するプラグインの紹介と、今後の展望についてお話しします。

# 製作の背景

Sigcomでは、[BEAT AIMER!](https://beataimer.com/ja/) というリズムシューティングゲームを開発・発売しています。
![BEAT AIMER!](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172384/835b78be-fb69-8f7d-e0e5-671f90b1ca2c.png)

このゲームの譜面制御にMIDIファイルを使用していますが、以下のような課題がありました。

1. プラグインがUE5非対応 
    利用していた外部プラグインがUE5に対応しておらず、移行が困難でした

2. Harmonixの制約
   UE5から公式プラグインでHarmonixが提供されていますが、以下の理由で要件を満たせませんでした:
   - Beta版のため、既存のMIDI譜面の再生が不安定
   - MetaSoundプラグインであるため、MetaSound外での操作が制限され、オブジェクト制御が煩雑

これらの課題を解決するため、自社でMIDIプラグインの製作をすることとなりました。

# プラグインの配布場所
Fab.comの審査通りました🙌

こちらから入手できます↓↓↓
https://fab.com/s/8d448a873b22

# プラグインの概要

本プラグインは、[MidiFile](https://midifile.sapp.org/) ライブラリを使用してMIDIファイルの読み込みとメッセージ処理を実現しています。
プラグインでは、以下の7つのBlueprintノードを提供しています。

![プラグインが提供するブループリントノード](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172384/fcc8796c-22a8-e8e5-35eb-0591729a3afc.png)

以下は、このプラグインを使用してMIDIの再生から`NoteOn`/`NoteOff`/`CC`メッセージをパースし、デバッグ出力するまでのサンプルです。

![プラグインを用いてMidiファイルを再生するサンプル](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172384/95741597-743a-ac77-f3f9-6d3e52de6e4f.png)

このプログラムで、Web上で配布されているMidiを無作為に選んで再生してみました。
[フリーのBGM用音楽素材\[MIDI\]](https://www.ne.jp/asahi/music/myuu/midi/midi.htm)からアイネ・クライネ・ナハトムジークを再生した時の画像です。
![debug.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172384/b61b8b1d-7877-0718-2547-0682de0ba9fc.gif)

この例ではレベルブループリントで実行していますが、アクターブループリントやその他のブループリントでも同様に、MIDIファイルの読み込みや再生が可能です。

# プラグイン製作で得られた知見

多くの断片化された情報を集約しながら実装を進める必要がありましたが、結果的にUnreal Engineプラグイン開発に必要となる以下の知識を網羅的に習得できたのではと思っています。

1. サードパーティライブラリの統合
   プロジェクトに外部ライブラリを組み込み、利用可能にする手順
2. エディタ機能の拡張
   - MIDIファイルをインポートし、`uasset`としてプロジェクトに保持する
   - インポートした`uasset`を読み込み、Blueprintで利用する
3. ランタイム機能の拡張
   - MIDIの再生機能を実装
   - 以下のようなBlueprintノードを実装する:
     - 複数の戻り値を持つ
     - 複数の実行ピンを持つ
     - 配列を戻り値とする
4. モジュール化
   各機能をモジュール化し、一つのプラグインとして統合

本来、クラスが別れていればよい程度の構造化で済む内容だと思うのですが、
4.のモジュール化は2.のエディタ拡張と3.のランタイム拡張を1つのプラグインに統合するためには必須の知識と実装方法でした。

# 「作って覚えるUnreal Engineプラグイン開発」執筆計画

作り終えて、Midiプラグイン開発は一般的なプラグイン開発の知識に加えて

1. 断片化されてまとまっていない
2. リファレンスにも書かれてない
3. ほとんどのプラグイン開発には不要
4. だが年1くらい必要になる

知識をちょうどいい難易度で学習できる良い機会になるのでは？ と感じました。
~~Zenn辺りで、このMidiプラグインを実際に作りながら学べる「UE5作って覚えるUnreal Engineプラグイン開発(仮)」を書こうかと計画中です。~~
~~進展ありましたらこちらにまた追記します。~~

まだ途中までですが、本を公開しました！
[作って覚えるBlueprintプラグイン開発](https://zenn.dev/leico/books/ue_midi_file_plugin)

[SigcomのXアカウント](https://x.com/sigcomstudio) でもポストすると思いますので、興味ありましたらフォローいただけるとありがたいです。
プラグイン開発に関する質問や相談もお気軽に、可能な範囲でお答えします。

開発のご依頼やコラボレーションのご提案も大歓迎です。お気軽にお問い合わせください。
ウラムの螺旋（Mathematica）

　整数を螺旋状に並べて・・・
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/e86d4a60-a569-6996-6ca6-46b4d7c7b5c0.png)

素数のマスを黒く塗る
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/a78cba64-8a3f-fd61-80cd-0aa03c9410f5.png)

　行列を4つに分けて、数値をずらす&回転して足し合わせると螺旋状の整数行列になります。素数判定は組み込み関数のPrimeQを使用します↓

```wl:UlamSpiral
n = 100; (* 2n+1 x 2n+1 *)

{m1, m2, m3, m4} = 
  Table[If[
      j + 1 <= i <= 2 n + 2 - j, (2 (n - j + 1) - 1)^2 + 
       2 # (n - j + 1) + i - j - 1, 0], {i, 2 n + 1}, {j, 
      2 n + 1}] & /@ {0, 1, 2, 3};
m2 = Reverse[Transpose[m2]];
m3 = Reverse[Transpose[Reverse[Transpose[m3]]]];
m4 = Transpose[Reverse[m4]];
m = m1 + m2 + m3 + m4;

a = Table[If[PrimeQ[m[[i, j]]], 1, 0], {i, 2 n + 1}, {j, 2 n + 1}];
ArrayPlot[a]
```

ウラムの螺旋（201x201）
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/395c53f5-1c0e-3712-4981-e1cc2e4a37c7.png)

ウラムの螺旋（401x401）
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3278375/c17e6ea4-e116-8297-3e66-a1fc401b5e94.png)

　素数が多く分布する斜め45度の直線がはっきり見て取れます。同じ密度でランダムに奇数を黒く塗った場合、このようには見えません。

 https://ja.wikipedia.org/wiki/%E3%82%A6%E3%83%A9%E3%83%A0%E3%81%AE%E8%9E%BA%E6%97%8B
シェルスクリプトで並列処理

シェルスクリプトでコマンドを並列実行する方法を2つ紹介します。

## 1. `&` (バックグラウンド実行) と `wait`

最もシンプルな並列処理の方法です。コマンドの末尾に `&` を付けると、そのコマンドはバックグラウンドで実行されます。`wait` コマンドは、バックグラウンドで実行中のすべてのプロセスが終了するまで待機します。

```bash
#!/bin/bash

command1 &
command2 &
command3 &

wait

echo "All commands finished."
```

`command1`、`command2`、`command3` はそれぞれ別のプロセスとしてバックグラウンドで実行されます。`wait` コマンドによって、すべての処理が完了するまでスクリプトの実行が一時停止します。 全てのコマンドの実行が完了した後、"All commands finished." が出力されます。


## 2. 制限付き並列処理

配列と `wait -n` を組み合わせることで、並列実行数を制限した処理が可能です。

```bash
#!/bin/bash

commands=("command1 arg1" "command2 arg2" "command3 arg3")
max_parallel=2  # 最大並列数
running=0       # 現在実行中のプロセス数

for command in "${commands[@]}"; do
  while [[ $running -ge $max_parallel ]]; do
    wait -n  # いずれかのバックグラウンドプロセスが終了するまで待機
    running=$((running - 1)) # 終了したプロセス数を減算
  done

  eval "$command" &  # コマンドをバックグラウンドで実行
  running=$((running + 1)) # 実行中のプロセス数を加算
done

wait # 全てのバックグラウンドプロセスが終了するまで待機
```

`commands` 配列に実行したいコマンドを格納します。 `max_parallel` で並列実行数を制限します。 `running` 変数で現在実行中のプロセス数を追跡します。

`for` ループでコマンドを一つずつ取り出し、`while` ループで実行中のプロセス数が `max_parallel` を超えないように制御します。 `wait -n` は、いずれかのバックグラウンドプロセスが終了するまで待機します。プロセスが終了すると、`running` をデクリメントし、次のコマンドを実行します。 `eval` は、文字列として格納されたコマンドを実行するために使用します。


この方法では、最大並列数を `max_parallel` で指定した値に制限しながらコマンドを実行できます。 `wait -n` を使うことで、プロセスが終了するたびに次のコマンドを実行するため、効率的に並列処理を行うことができます。  最後に `wait` で全てのバックグラウンドプロセスが完了するまで待機します。
[エラー]文字列の見た目が同じなのに異なる文字列判定が起こる

# はじめに
PDFから抽出した文字列を用いて学習を行っていた時に以下のエラーに遭遇．

# 環境
Python 3.9.13

# エラー事項
以下のように，同じに見える文字列を比較しているのに，文字列比較をするとFalseが返ってくる．
```
'ランプ' == 'ランプ'
-->  False
```

# 原因
原因は「プ」にあった.
どうやら左側にあった「プ」は「フ」と「\u309a(半濁点)」で分かれいたようだ．これは同様に「ブ」のような濁点の時も見られた．

```
l = 'プ'
print(f'char:{l}, len:{len(l)}, code:{ascii(l)}')
-->  char:プ, len:2, code:'\u30d5\u309a'

r = 'プ'
print(f'char:{r}, len:{len(r)}, code:{ascii(r)}')
-->  char:プ, len:1, code:'\u30d7'
```

# おわりに
データを眺めているだけだと気がつけない誤りだった．
きちんとassert文などを用いて検証する大切さを痛感した．
Issueを自動でクローズし、集中すべきIssueを選択できるように

バグや今すぐ解決できないが将来的には改善したいことをIssue化しておくことがあると思いますが、現実はIssueをクローズするよりもIssueが増えていくスピードのほうがはやく、残り続けてしまうことがあります。

その結果、現時点で過去に抱えていた問題がすでに解決されていたり、昔過ぎて何に課題感を感じていたのかがわからないIssueが出てきます。

それに対して、自動でIssueをクローズする仕組みを試してみているので、それについて書きます。

## 古いIssueが残っていることによる課題

古いIssueが残り続けることに、以下のような課題があると考えています。

- Issueが把握できなくなる負のサイクルが生まれる
- 現時点で解決すべき問題が見えにくくなる

### 問題が把握できなくなる負のサイクルが生まれる

チームや個人が認知できるIssueの数には限界があります。
Issueが認知できる数を超えている状態の場合、すでに同じ課題を解決したいIssueがあるが、それがあることに気が付かず同じ課題を解決するIssueを作成してしまいます。
その結果、Issue数がさらに増加し、より把握できない状態になってしまいます。

そして、同じ課題を解決するIssueが複数あることで、課題の詳細な情報や関連情報、アイディアなどが各Issueに分散してしまい、Issueに情報を蓄積しても無駄になります。

### 現時点で解決すべき問題が見えにくくなる

Issueの数が多い場合、古くからずっと残っているパターンあります。
古くから残っているIssueは、現時点で価値があるかはわかりません。すでに課題が解決されている場合やIssue作成者が感じていた課題感を忘れてしまっていたりします。

また、膨大なIssueの山に埋もれることで、直近で解決すべき課題が見えづらくなり見落とされてしまいかねません。

上記の問題を解決すべく、直近で解決したいIssueを置く場をつくったとしても、直近で解決したいIssue置き場がIssueで溢れかえってきたり、次の1 ~ 2週間ではやらないけど1ヶ月後にはやるようなIssueをこれまでのIssue置き場に置くしかなくなり、山に埋もれてしまうことが起こると思います。

## どう解決するか

一定期間Issueのアクティビティがないものは自動でクローズしていく仕組みが良いのではと思っています。
そう考えている理由は以下です。

- 課題がすでに解決しているかをすべて調べるのに時間を使うのは有用でない
- クローズすべき理由を考える、見つける人が疲弊しないようにする

そして、実際に使えそうなものはGitHubが公開してくれています。

https://github.com/actions/stale

一定期間アクティビティがないものに`Stale`ラベルを付与し、ラベル付与からさらに一定期間経過したら自動でクローズするようにできます。

クローズ前に`Stale`ラベルをつけてくれるため、本当に必要なIssueの場合、作成者や他のメンバーがクローズされないようにしたりすると思います。
逆に、ラベル付与されても何もアクティビティがない場合は、本当に解決すべき課題でないことがほとんどなのではと考えています。

そのため、思い切って厳し目のルールで導入してみるのは良いと思います。

## さいごに

Issue置き場を定期的に掃除をし、必要なものを取り出せるようにしましょう。

## Ref

- [actions/stale: Marks issues and pull requests that have not had recent interaction](https://github.com/actions/stale)
- [非アクティブな Issue をクローズする - GitHub Docs](https://docs.github.com/ja/actions/use-cases-and-examples/project-management/closing-inactive-issues)
- [actions/staleを使って放置されたPRをクローズしよう](https://zenn.dev/readyfor_blog/articles/f5a627f632fffd)
- [開発基盤のIssueチケットを300個から50個まで減らした話 - Speee DEVELOPER BLOG](https://tech.speee.jp/entry/dx-platform-issue)
【TypeScript】type-challenges 初級編 3060・Unshift 解説

## お題
`Array.unshift`の型バージョン`Unshift`を実装する（配列の先頭に要素を追加する）。

## やりたいこと
```typescript
type Result = Unshift<[1, 2], 0>;  // => [0, 1, 2]
```

## 解答
```typescript
type Unshift<T extends unknown[], U> = [U, ...T];
```

## 解説
### 処理の流れ
- `<T extends unknown[], U>`
`T`に配列を受け取るように制限。`U`は先頭に追加する要素を受け取る。
- `[U, ...T]`
`U`を先頭に置いて、スプレッド構文で`T`の要素を展開し、`[]`でラッピングする。

### スプレッド構文とは...
https://qiita.com/yuto99999/items/f77e22e0a1e80b867ee5#%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%A7%8B%E6%96%87%E3%81%A8%E3%81%AF

## 今回の問題
https://github.com/type-challenges/type-challenges/blob/main/questions/03060-easy-unshift/README.ja.md
いかにして10ヶ月で90記事書いたのか〜子育てと自己研鑽の両立〜

## はじめに
今年の2月頭から今日までの約10ヶ月で、Qiitaの記事を80記事（当記事含む）、Wantedlyで8記事、合わせて90近い記事を書いてきました。
※Wantedlyの記事は所属会社の名義で書いており、course_kのアカウントには紐づけていません。

中には内容的に未熟なものもありますが、大体平均して3、4日で1本の記事を書いてきた計算になります。

どのようにして継続的に記事を書いてきたのか、私なりの方法を紹介します。
（過去に書いた[こちらの記事](https://qiita.com/course_k/items/258f551c7599101153ce)と重複する部分もありますが、よりブラッシュアップした形で記載します。）

なお、本記事は、[TechCommit AdventCalendar2024](https://adventar.org/calendars/10584) の14日目の記事となります。

## 子育てと自己研鑽の両立のために
### 可処分時間を計算する
うまく貯金をするためには、余ったお金を貯金に回すのではなく、あらかじめ貯金用にお金を確保することだといいます。

自己研鑽のための時間も同じです。
余った時間でやるのではなく、あらかじめ何時間分あてられるのかを決めておきます。

そのためには可処分時間を計算する必要があります。
可処分時間とは生活に欠かせない諸々の時間を差し引いた、自分で自由に使える時間のことをいいます。

私の場合、平日の生活に必要な時間は以下のとおりです。
* 朝6時〜8時15分くらい
朝ご飯の準備やお弁当づくり、それらの片付け、洗濯、子どもを保育園へ送る

* 9時〜18時
仕事（基本残業はなし、フルリモートのため通勤もなし）

* 18時〜21時
晩御飯の準備、それらの片付け、子どものお風呂
* 22時〜
就寝

そうなると、可処分時間は始業の9時までの時間、22時の就寝までの時間くらいになります。
大体1時間半くらいですね。

それに加えて、朝4時〜5時のあいだで起きることができれば大体1時間〜1時間半くらいの時間が確保できます。
22時くらいには就寝しており、睡眠時間としては6時間は確保できるのでそこまで辛くはありません。

そうなると、大体2〜3時間くらいが最終的な可処分時間になります。

これを、あとはやりたいことに振り分けるだけです。

なお、休日はどうしているかというと、休日は仕事がないだけで家のやることは盛り沢山なので、結局平日と変わらないくらいの可処分時間となっています。

### 絶対に止めない
続けるためのコツは、続けることです。
トートロジーのようですが、これが真理だと思います。

一度中断してしまったものを再び始めるには、新しく始めるよりも多くのエネルギーが必要です。

ポイントはコンスタントに細く長く続けることです。
特に子育てしながらの場合は、可処分時間を見積もってもその通りにいかないことも多いので、続けやすいものにすることが重要です。

私の場合は何が何でも週1回はQiitaの記事を上げることを最低限のラインにしてました。
どんなにしんどくても、これだけは絶対に死守してきたので、現時点で46週連続での更新を維持しています。

続けるサイクルができると、そこまで大きな労力を費やさずとも、習慣になっているので継続しやすいです。

先に上げた可処分時間が大体2時間ありましたが、別に「毎日2時間自己研鑽する」という目標にする必要はないわけです。

私は記事執筆以外にもUdemyなどでインプットしたりもしてますが、毎日ずっとやれているわけではありません。日に20分すらできないときもあります。

それでも、週1のQiitaの更新は続けてきました。
最低限ラインが守れれば、それに付随した細々としたものも少しずつ続けることができます。

### 他人にアピールする
一人で黙々とやるより、他人に自分がやっていることを表明するほうが、強制力が働くので続けやすくなります。
言ってしまった手前、やらざるを得ないといった感じです。

私の場合は、会社のSlackに個人チャンネルを作成し、そこで日々のやったことをほそぼそと投稿しています。14名の方が参加してくれています。社員数が70名くらいなので5人に1人は参加している感じです。

うまくできても、できなくてもとりあえずこんなことしました（もしくはできませんでした）ということを投稿し続けています。
それ自体が自己研鑽を続けるための布石になりますし、自分自身で振り返るきっかけにもなります。

どうしても自分の中だけにとどめておくとできなくなってきたときに「まあ、いっか」となりがちですが、周りを巻き込むことで「見られている」という意識が生まれるので、「やろうかな」という気持ちになります。

あと単純に、たまに反応をもらえたり応援してもらえたりすることがあるので、それ自体が続けるモチベーションになります。
反応そのものをモチベーションにすると、反応がないと辛くなって逆効果なのですが、ボーナス的な気持ちでいると気分がアガるので、続けるためのアクセントになります。

## まとめ
子育ての事情は各家庭によって異なるので、あえて細かい部分にはフォーカスをあてませんでした。

この記事では
* 使う時間を決めること（可処分時間）
* 続けやすい仕組みをつくること（止めないこと、アピール）
について私個人の経験をまとめています。

子育て自体は一大プロジェクトで、途方もない労力がかかります。
全く予測ができないですし、計画通りにいきません。

そのため、自分のための時間を作ることが難しいです。
そもそも自分のために時間を使っていいのか？という気持ちになります。
私も日々葛藤しています。

当記事に、自己研鑽すること自体を礼賛したり、できていないことを揶揄したりする意図はありません。
エンジニアなら自己研鑽して当然、とかできないのは自己管理の問題だ、とかそういうのはないです。
やってもやらなくてもいいことだと思っているので、やってるひとがマウントを取る理由にはならないですし、やってないひとを貶める理由にもなりません。

やりたい、かつできるひとはやればいいものだと思っています。
そんなひとにとって、少しでもお役に立つものになっていればいいなと思います。
【react-modal】App element is not defined. の解決方法

# はじめに
本記事では、Reactアプリでreact-modalを使用した際に発生する「***Warning: react-modal: App element is not defined.***」という警告を解消する方法を紹介します。このワーニングがなぜ発生するのか、そして正しい対処法について具体的に解説します。

https://github.com/reactjs/react-modal

:::note warn
***この記事は<font color="Red">個人的なアウトプット</font>を目的として作成したものです。そのため、誤った情報や不足している内容が含まれている可能性があります。もし間違いや気になる点がございましたら、ぜひご指摘いただけますと幸いです***。
:::

# 事象
以下のコードでは、react-modalを使用してモーダルを作成し、ボタンをクリックするとモーダルが表示されます。しかし、実行時に次のワーニングが発生しました。

```
Warning: react-modal: App element is not defined. Please use `Modal.setAppElement(el)` or set `appElement={el}`. This is needed so screen readers don't see main content when modal is opened. It is not recommended, but you can opt-out by setting `ariaHideApp={false}`.
```
ワーニングは動作に影響を与えませんが、解消しておくことが推奨されます。

# 原因
このワーニングは、`react-modal`がアクセシビリティ対応の一環として、モーダル以外のアプリケーション部分を非表示にする要素を指定していない場合に発生します。
react-modalの公式ドキュメントによると、`Modal.setAppElement`で非表示にするルート要素を指定する必要があります。

https://reactcommunity.org/react-modal/accessibility/

# 解消方法
ワーニングを解消する方法は主に2つあります。
## 方法1: Modal.setAppElementを使用する（推奨）

以下のようにmain.tsxに記述します。
```react
Modal.setAppElement("#root"); // ルート要素を指定
```

## 方法2: ariaHideApp={false}を使用する（非推奨）
一時的に解決するための方法です。

```react
<Modal isOpen={modalisOpen} ariaHideApp={false}>
```

#　終わりに
`react-modal`を使用した際の「***Warning: react-modal: App element is not defined.***」というワーニングは、`Modal.setAppElement`を適切に設定することで解消できます。この設定はアクセシビリティ対応として重要であり、推奨される方法です。一時的な対応として`ariaHideApp={false}`を使用する方法もありますが、長期的には推奨されません。

# 参考

https://reactcommunity.org/react-modal/accessibility/

『react-modalからの警告`Warning: react-modal: App element is not defined.`を解決する』Qiita

https://qiita.com/SBS_Takumi/items/9c7583bb4ca6cc503eb8
コマンド5行以内でLlama3.3を起動して使う

## 概要

何らかの理由でオープンソースLLMを使いたい場合は、Ollamaが登場する前にかなり工夫しないといけないけど、時代の進化で現在はVM立ち上げからモデルが使えるまで僅か数分で設定できます。早速見ていきましょう。

## スペック確認

今回はAWSでやってみます。現時点日本リージョンで最新のGPU付きEC2はg5で、A10GのGPUで、24GB／96G／192GBの3択しかないです。Llama3.3は絶対に24GBで足りないので、g5.12xlargeにします。

![Screenshot from 2024-12-09 21-26-34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/b303a574-b583-dca0-517b-1d28e364626c.png)

そして費用ですが、USリージョンよりやや高くて、東京はUSD8.2 / 1時間となっています。

![Screenshot from 2024-12-09 21-27-13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/9816fce9-04e9-c089-b053-17be8ebac856.png)

モデルのスペックは、ollamaに載せている、llama3.3のQ4_K_Mにします。43GBなのでg5.12xlargeで動けるはずです。

![Screenshot from 2024-12-09 21-27-29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/f88e766e-95de-5a5b-c6c4-bc7b5bf97b23.png)

## EC2設置

EC2のAMIは、画像のようにNvidiaドライバーが入っているものをおすすめです。ゼロからインストールの場合だと、30分〜1時間がかかる可能性があります。

![Screenshot from 2024-12-09 22-33-33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/dc685509-edd7-4360-4533-665118e185e7.png)


## コマンド

1 . 念の為、rootレベル権限を取得します。

```
sudo bash
```

2 . Ollamaをダウンロードしてインストールします。

```
curl -fsSL https://ollama.com/install.sh | sh
```

3 . Llama3.3モデルをダウンロードします。

```
ollama pull llama3.3
```

4 . これで設置完了なので、1回生成リクエストを送ってみます。

```
curl http://localhost:11434/api/generate -d '{"model": "llama3.3","prompt": "Give me sample source code for training a lstm network using pytorch"}'
```

![Screenshot from 2024-12-09 22-41-56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/d3b7dd71-4a1b-473b-725b-faa1de0e1bb4.png)

![Screenshot from 2024-12-09 22-42-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/753f5e94-b798-e07e-a3e1-6cc77f4bfe6a.png)

これだけで使えるようになりました。セキュリティグループなどの設定をいじれば、外部に公開することももちろんできます。

---

最後に、GPUのリソースも確認してみます。

```
nvidia-smi
```

![Screenshot from 2024-12-09 22-40-15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893830/12a41f75-bfda-b4ca-db29-2bfaf977dd79.png)

半分ぐらい占用されていますね。ネットで48GBのGPUでもギリギリ動けるとの報告もありましたけど、コンスーマレベルのGPUだとやはり生成スピードが遅くて、実用性が疑問になります。
【VSCode】ターミナルで合字を使用する方法

`terminal.integrated.fontLigatures`を`true`にすることでターミナルで合字が表示されるようになります。

```settings.json
{
  "terminal.integrated.fontLigatures": true
}
```

![terminal-ligatures.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2342443/d8198e60-45b7-c645-56f6-0715af228846.png)
〜Viewにロジック書くの厳しいって〜RailsでUIとロジックを分けるためのPresenter/Decoratorパターンを実例付きで解説❗️

この記事は [ex-crowdworks Advent Calendar 2024](https://qiita.com/advent-calendar/2024/ex-cw)の14日目の記事です。

# はじめに
今年、株式会社クラウドワークスを退職した@nisyuuです。寒くなってきたのでこたつを出しました。
エンジニアとしてクラウドワークステック（旧クラウドテック）というフリーランスと企業をマッチングするエージェントサービスを開発していました。

Ruby on Railsを利用してアプリを開発していると、ビューロジックが調整されていないため、コードが複雑になる場合があります。
そのような場面で、PresenterやDecoratorの機構を使用することでコードをクリーンにし、管理しやすくすることができます。

本記事では、PresenterとDecoratorの基本的な概念について紹介し、それぞれのメリット、デメリット、実装例を見ていきます。

# Presenterとは

Presenterは、モデルに属する表示ロジックを隠蔽するためのクラスです。ビューの責務を分離し、ビューのロジックをコントローラから切り離すことができます。

## Presenterのメリットとデメリット

### メリット
- ロジックを分離することでコードの読みやすさが向上する
- ビューロジックがモデルに依存しなくなる

### デメリット
- 新たなクラスを追加するため、プロジェクトが複雑に見える可能性がある
- 実装コストが増える

## Presenterの実装例

下記は、Presenterを実装するための基本的なコード例です。

```ruby
class ProductPresenter
  def initialize(product)
    @product = product
  end

  def display_price
    "\#{formatted_price}"
  end

  def stock_status
    @product.stock > 0 ? 'In Stock' : 'Out of Stock'
  end

  private

  def formatted_price
    sprintf('%.2f', @product.price)
  end

  attr_reader :product
end
```

# Decoratorとは

Decoratorは、コンポーネントの機能を拡張するために使用され、クラスの負担を小さくし、純粋な機能に集中することができます。
Railsでは`active_decorator`gemが普及しており、それを利用することが推奨されます。

https://github.com/amatsuda/active_decorator

## Decoratorのメリットとデメリット

### メリット
- ロジックを再利用しながら、モデルの機能を拡張できる
- コンポーネントを実装している程度でビューへのロジック転射を調整できる

### デメリット
- 実装するにはDecoratorに関する十分な知識が必要
- コンポーネントを拡張しすぎると、利用性が低下する可能性がある

## Decoratorの実装例

下記は`active_decorator`gemを使用したDecoratorの基本的なコード例です。

```ruby
class UserDecorator < Draper::Decorator
  delegate_all

  def formatted_name
    "#{object.first_name} #{object.last_name}".titleize
  end
end
```

# Helperを使わずにPresenterとDecoratorを使う理由

RailsのHelperは、ビュー内のロジックを簡潔に記述するための便利な機能ですが、以下のような理由でPresenterやDecoratorを使うことが推奨される場合があります。

## 再利用性の向上

Helperはビューごとに特化した内容になりがちで、再利用が難しいことがあります。PresenterやDecoratorを使用することで、モデルに紐づくロジックを再利用可能な形で整理できます。

## テストのしやすさ

Helperは一般的にテストが困難ですが、PresenterやDecoratorは独立したクラスであるため、単体テストが容易です。

## コードの可読性の向上

Helperにロジックを詰め込みすぎると可読性が低下する場合があります。PresenterやDecoratorを導入することで、ロジックを整理し、コードの構造を明確にできます。

## 責務の分離

Presenterは表示ロジック、Decoratorはモデルの拡張といったように、役割が明確になります。これにより、コード全体の責務が分離され、管理しやすくなります。

# おわりに

PresenterとDecoratorは、Railsアプリを深いレベルでカスタマイズするための重要な機構です。Presenterはビューロジックを分離し、Decoratorはモデルの機能を拡張するという個別の役割を持っています。これらを適切に使い分けることで、コードの読みやすさや保守性も高められるでしょう。
const fnで浮動小数点演算が可能になった

## Rust 1.82でconst fn内での不動小数点演算が可能になった
ついに`const_fn_floating_point_arithmetic`が安定化され`const fn`内での浮動小数点演算が可能になりました。  
おそらく全Rustaceanが待ち望んでいた機能だと思います。

```rs
const fn foo(a: f32, b: f32) -> f32 {
    a + b
}
```
こういうコードがstable環境で書けるようになりました。

### 使用可能な関数
記事を書いている時点で使用できる関数は
`{float}::is_infinite`
`{float}::is_finite`
`{float}::is_subnormal`
`{float}::is_normal`
`{float}::classify`
`{float}::is_sign_positive`
`{float}::is_sign_negative`
`{float}::to_bits`
`{float}::from_bits`
`{float}::to_be_bytes`
`{float}::to_le_bytes`
`{float}::to_ne_bytes`
`{float}::from_be_bytes`
`{float}::from_le_bytes`
`{float}::from_ne_bytes`
です。

## const genericsの引数に浮動小数点型を使うことができなくもないようになった
`to_bits`が使用できるので下記のように結果を整数型に代入しておけばコンパイルは通ります。
```rs
struct Type<const Value: u32>;

const V: u32 =  1.0_f32.to_bits() ;
type OneF32Type = Type<V>;
```
使い所あったら教えてください。

## おわりに
待ちに待った機能が安定化されてとても幸せな年末を迎えられました。
コンパイル時に計算できるものが増えるのは良いことです。
かんたん可視判定(2D/3D)

# かんたん可視判定(2D/3D)
今日は単純な可視判定について考えます。
ある点Pが、特定のキャラクター(カメラ)の可視範囲内にあるのかどうなのかを判定する方法です。

相手が「点」なら簡単なんです。点ならね。
画角がθだとして、視点の座標をE、見える範囲をdだとすると

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275040/a2af31e7-e090-587c-0625-6fd3a14f3bdc.png)

こんな感じの図になるとします。という事はまず視点Eから点Pまでの距離$$\|\vec{EP}\|$$がd以下であることが必要ですね。

```math
\|\vec{EP}\|\le d
```

しかしそれだけでは、画角からはみ出た場合に判定できませんので、画角からはみ出ているかどうかを判定します。
これには、内積の性質$$\vec{A}\cdot \vec{B}=\|\vec{A}\|\|\vec{B}\|cosθ$$を利用します。
この式を変形すると

```math
cosθ=\frac{\vec{A}\cdot \vec{B}}{\|\vec{A}\|\|\vec{B}\|}
```
これで得られたcosθは角度が広がれば広がるほど小さくなります。90°以上に広がるとマイナスになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275040/c7aa568c-a446-45bc-938d-2fcf5d2a5081.png)
という事は、視線ベクトルとEPベクトルの内積結果を視線ベクトルの大きさおよびEPベクトルで割ったものをcosφとすると
cosφ≦cosθ (θは画角)
になればよい。つまり

```math
\frac{\vec{EP}\cdot\vec{R}}{\|\vec{EP}\|\|\vec{R}\|} \le cosθ
```
になる。
先述の距離の計算と、このcosの計算が成り立てば、その特定の点は視線方向を中心とした画角θの範囲内に入り、半径dの範囲内に入るという事になります。

まとめると
```math
\|\vec{EP}\|\le d
```
```math
\frac{\vec{EP}\cdot\vec{R}}{\|\vec{EP}\|\|\vec{R}\|} \le cosθ
```
の式双方が成り立っていれば、ある点は可視オブジェクトであると言えます。

しかし、これが点でなく大きさを持った円(もしくは球)となるとなかなかヤヤコシイ

## 判定したいのが点ではなく円の場合(2D)
3Dになるとだいぶややこしいのですが、2Dの場合はまだ比較的簡単です。まず視野角が決まっている場合視野角の恥を表すベクトルは２つになりますが、そのうち近い方をVとします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/275040/47eb486a-6176-7277-2ae0-9717c37e22f0.png)

で、このとき点Pから垂線をVにおろします。この垂線が円の半径r以内ならVに触れる事になります。
通常、垂線を作るには外積を使うか、射影ベクトルを使いますが、今回は射影ベクトルを使いましょう。

射影ベクトルとは、Vベクトルの方向を向きつつ、点Pから垂線を下したところまでの長さを表します。これをたとえば

```math
\vec{W}=\frac{\vec{EP}\cdot \vec{V}}{\|\vec{V}\|}
```

とすると、垂線ベクトルはEPベクトルからこのWを引けばいいため垂線ベクトルをTとすると
```math
\vec{T}=\vec{EP}-\vec{W}
```
になります。このベクトルTの長さを求めて、半径ｒと比較すればすべてうまくいくように思えますが、それはあくまでも垂線を下したのがVの長さの範囲内に入っている場合です。Ｖの長さの範囲外の場合もあるためＷの計算を書き換えます。

```math
\vec{W}=clamp(\frac{\vec{EP}\cdot \vec{V}}{\|\vec{V}^2\|},0,1)\|\vec{V}\|
```
式のようにさらにＶの大きさで割る事でＶベクトルの範囲内にあるなら、値が0～1になります。Ｖの範囲を超えると1以上もしくは0未満になります。これをclamp関数(特定の値を超えたら指定の値にしてしまう)で範囲を限定したうえで、さらにVの大きさをかけることで、Ｗの範囲がＶの長さの範囲内にとどまります。

あとはこれでできたＷから差分ベクトルＴを求めれば、ＷがＶの範囲内なら垂線に、ＷがＶの範囲を超えたなら単純な単店との距離になります。つまりここまでやった
```math
\vec{T}=\vec{EP}-\vec{W}
```
の長さと半径を比較します
```math
\|\vec{T}\| \le r
```
が、2Dにおける視野内に円が入ってるかどうかの判定になります。

というよりこうなると扇形と円の当たり判定ですね。

3Dの場合はコーン(円錐)と球の当たり判定になり、急に難易度が上がるので、それは次の機会にしましょう。

それではさようなら
ViperIDEを使ってみる③：BLE REPLを使ってみる

# BLE REPL

ViperIDE では Raspberry Pi Pico W と ESP32 で BLE 経由の REPL をサポートしている。

# 前準備

## viper-tools

パッケージマネージャーから `viper-tools` をインストールする。

![スクリーンショット 2024-12-13 23.08.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/2fe4513b-b53d-20cd-97cc-bcb988fd7518.png)

インストール後、ファイルマネージャを見ると lib 配下に次のものが入っていた。

![スクリーンショット 2024-12-13 23.09.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/e39026c3-dcb0-3b6c-361b-99de4838174f.png)

## main.py

`main.py` に次の２行を入れておく。

```python
import ble_repl
ble_repl.start()
```

![スクリーンショット 2024-12-13 23.11.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/9f37eeb8-7c93-e881-6a62-717838d32096.png)

# 繋ぐ

右上の Bluetooth アイコンをクリックすると、自動的にデバイスを探してペア設定を要求してくる。mpy-repl を選んで「ペア設定」をクリックする。

![スクリーンショット 2024-12-13 23.13.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/e0dcbc53-112f-18e6-563d-27841de635fb.png)

ターミナルに REPL が表示されれば成功。

![スクリーンショット 2024-12-13 23.23.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106817/54f94837-f949-c667-d965-b79f96cb90de.png)

普通に REPL として使える。Ctrl-D でリセットをかけると、接続も切れて再接続が必要になるのは要注意。
自身のYoutube台本をベースに作成したAITuberのシステム概要

# 総論

現在運用しているAITuber"[読書家AIみにこねこ](https://www.youtube.com/@%E8%AA%AD%E6%9B%B8%E5%AE%B6AI%E3%81%BF%E3%81%AB%E3%81%93%E3%81%AD%E3%81%93/videos)"のシステム概要について述べる。

https://www.youtube.com/@%E8%AA%AD%E6%9B%B8%E5%AE%B6AI%E3%81%BF%E3%81%AB%E3%81%93%E3%81%AD%E3%81%93/videos

https://www.youtube.com/playlist?list=PLVhMoEaJsUv54rKmFy5WgC0tD0uJpKNMM

## 開発の経緯

元々自身がYoutubeにて本紹介の動画を5年に渡り投稿していた。

https://www.youtube.com/channel/UC8XWegWIsSfHuobu8lIBzhg

しかし、自身で動画を撮ることに対する時間の制約、および「可愛いキャラクターが本紹介をした方が伸びるのではないか」という思いがあった。

そんな折、OpenAI社よりchatGPT(GPT3.5)が世に輩出され、AITuberの実現性がいよいよ高くなったように感じた。私自身はExcelVBAくらいしか書けなかったが、chatGPTによりPython等のプログラミング言語を学びやすくなったことで、技術的なハードルも下がった。

以上の理由により、2023年1月頃よりAITuberの開発を始め、いくつかのバージョンを経た上で、現在に至っている。

## AITuberシステムの構成
AITuberシステムの構成は、大別して以下に分かれる。
1. テキスト生成
2. AITuberのコントロール

![図1読書家AITuberみにこねこのシステム構成図.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3934764/1f64f558-06c8-1f87-c20e-35a9e1b46444.jpeg)

以下それぞれについて記載する。
なお、システムはPythonでローカルに構築されている。

1. テキスト生成
    1. コメント取得
Youtube Data APIより視聴者のコメントを取得する。
なお、視聴者のコメントがない場合は、「オススメの本について教えて」「読んだ本について教えて」等の仮想コメントが定期的に作られるようになっている。
    1. ベクトル検索
視聴者コメントを元に、OpenAI社の"text-embedding-3-small"を用いてベクトル検索を用いて、自身のYoutube動画の台本である約1400のtxtファイルから、最大8つ選択して取得する。
なお台本データは1ファイルにつき4000文字程度である。
    1. テキスト生成
    視聴者のコメント、取得した台本データ、会話履歴(過去10回分)、およびAITuberの性格情報をプロンプトに組み込み、OpenAI社の"gpt-4o-mini"を用いてテキストを生成する。
    生成されたテキストは会話履歴に格納される。
1. AITuberのコントロール
    1. 音声合成
    生成されたテキストを元に、"[style-bert-vits2](https://zenn.dev/litagin/articles/034819a5256ff4)"を用いて音声合成を行う。
VRMを操作可能なソフトウェアである"[3tene](https://3tene.com/pro/)"を用いて、合成された音声を元にリップシンクを行う。
なお、VRMは"[VRoid Studio](https://vroid.com/studio)"を用いて作成した。
    1. モーション、表情抽出
生成されたテキストから、OpenAI社の"gpt-4o-mini"のFunction Callingを用いて、モーション(speech,dance等)および表情(happy,angry等)を抽出する。
    抽出したモーション、表情を仮想midiの入力に変換し、"3tene"上でVRMを操作する。
3teneでは100近いモーションや5種類の表情があらかじめ登録されており、キーボードやJoyPad、midiなどで操作可能なため、AITuberのコントロールに非常に有用である。
    1. 本の題名取得
生成されたテキストから、OpenAI社の"gpt-4o-mini"のFunction Callingを用いて、本の題名を抽出する。それを元に本の写真データを表示する。
    1. 配信
音声、VRM、本の写真、その他のデータを配信ソフトである"OBS Studio"にまとめて配信する。

## 今後の課題

### ニッチなターゲット
ターゲットを「海外古典文学」and「AITuber」に置いているが、そもそも両分野が共に狭いため、掛け合わされたものが非常にニッチになってしまっている。
「海外古典文学」or「AITuber」をターゲットとできるような成果物を作成していく必要がある。

### 真の価値提供
現在提供できている価値は「本についてのお喋りを楽しむ」「オススメの本を知ることができる」であると思われるが、AITuberが提供する価値として、それが正しいか疑問である。
AITuberだからこそ提供できる本質的な価値、を見極めて、それを成果物に反映させていく必要がある。

## 最後に
硬く書きましたが、AITuberについて考えている時(+良書を読んでいる時)が、一番楽しいです。今後も試行錯誤しながら、理想のAITuberの開発に勤しんでいきたいと思います。
また、ここに至るまでに、いろんな先人の皆様方のサイトを参考にさせていただきました。本記事が、AITuberの普及に少しでも役立てば幸いです。
Pythonを基礎から学ぶその2　numpyについて学ぶ

この記事は、[JavaとPythonを基礎から学びたい私のための Advent Calendar 2024](https://qiita.com/advent-calendar/2024/aruhitonocalendar)の14日目の記事です。numpyは奥が深く、すべてを１日で学習することはできないと判断しました。今日勉強したことについて書いています。
# numpy
Pythonの標準ライブラリの一つです。Pythonにはたくさんのライブラリが用意されているようですが、その中でもnumpyは計算のためのやつです。
## できること
### 配列を使った計算
昨日勉強した配列（[]←これ）を使って、計算ができるようになるみたいです。
numpyを入れていないときは、
```
A=[1,2,3,3,5]
B=[4,3,2,1,7]
print(A+B)
```
結果:[1, 2, 3, 3, 5, 4, 3, 2, 1, 7]
numpyをれていない場合は、配列の中の計算ができないため、一つの大きな配列となりました。
また、
```
A=[1,2,3,3,5]
B=5
print(A*B)
```
結果:[1, 2, 3, 3, 5, 1, 2, 3, 3, 5, 1, 2, 3, 3, 5, 1, 2, 3, 3, 5, 1, 2, 3, 3, 5]
配列と整数を掛け合わせた場合は配列が整数の数だけ増殖してしまいます。
numpyを使うときは
```
import numpy as np
A=np.array([1,2,3,3,5])
B=5
print(A*B)
```
結果:[ 5 10 15 15 25]
numpyの配列は、np.array([配列の中身])となるみたいです。また、これの計算結果についても配列の中の要素に対して掛け算されるようになりました。
```
import numpy as np
A=np.array([1,2,3,3,5])
B=np.array([4,3,2,1,7])
print(A+B)
```
結果:[ 5  5  5  4 12]
numpyを入れる前は長い一つの配列になっていましたが、配列同士が足し合わされるようになりました。ちなみに一つの配列にするときは、np.concatenate()を使うようです。
```
import numpy as np

A=np.array([1,2,3,3,5])
B=np.array([4,3,2,1,7])
print (np.concatenate((A,B)))
```
結果:[1 2 3 3 5 4 3 2 1 7]
結果的に()は<b>2重</b>につける必要があるっぽいです。
このconcatenateを使う際は、()の数に気を付けた方がいいと思います。上のように、2個も3個も”）”を付けていると、結構見づらいです。
## 配列の並び替え
配列の中身を並び替えることができるそうです

```
B=np.array([4,3,2,1,7])
print (np.sort(B))
```
結果:[1 2 3 4 7]
簡単に並べ替えられます。一から順番に並ぶようです。
# array()の中の配列を増やす
array()の中の配列を2個以上に増やすことができるようです。
```
A=np.array([[1,2,3,],[2,3,4],[3,4,5]])
B=np.array([[3,4,5],[2,3,4],[1,2,3]])
print (A+B)
```
結果:[[4 6 8]
 [4 6 8]
 [4 6 8]]
 array()の中の配列を増やす際は、()内のすべての配列を[]でくくってあげる必要があるようです。
行列の計算をするときには、とても便利な機能です。
# 配列の中身
中身の合計や最大、最小値を求めることができるようです。
```
import numpy as np

A=np.array([[1,2,3,],[2,3,4],[3,4,5]])
print (np.sum(A))
print (np.max(A))
print (np.min(A))
print (np.mean(A))
```
結果:27
5
1
3.0
上から順に合計、最大値、最小値、平均となっています。配列が一つの場合はnumpyを使わなくても平均以外は出すことができました(max(A)など)。numpyを使うことで平均が簡単に求まるほか、配列が2つ以上くっついているときにも対応しています。
```
import numpy as np

A=np.array([[1,3,5,],[2,3,4],[3,4,5]])
print(np.sum(A,axis=0))
print(np.sum(A,axis=1))
```
sumの()の、","の右側にaxis=を付けることで行だけ、列だけといった細かな指定もできるようです。
# まとめ
numpyは主に配列を扱うことができます。
配列が楽になりました。2つ以上の配列をまとめて使うことで、行列の計算にも対応しています。要素を並び替えることもできます。
# 参考文献

https://www.kikagaku.co.jp/kikagaku-blog/numpy-base/

https://numpy.org/doc/stable/user/absolute_beginners.html

https://note.nkmk.me/python-numpy-ndarray-sum-mean-axis/
読書：すぐやる人とやれない人の習慣

![Gem300TbcAAxHn2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/351901/cd8ce6c3-464c-7f2d-eee2-13c9286c1bec.jpeg)

パラパラ読みで，少しずつアップデートしていく形をとります．

記載されていた重要な部分だけメモっておいて，クイズ・想起的にこの記事を個人的に読み返すためのものです．

# なぜ読んだ？
「すぐやる人」になりたいと思ったから

# 重要なこと
- 目標とモチベーションを掛け合わせる
- 作業をつまみ食いして作業興奮を起こす
- 動くタイミングでは余計な思考は脳から吐き出しておく
- やる気スイッチも大事
- 自分自身をマネジメントするという感覚

ここら辺を気をつけとけば良さそう
第一言語がPythonのエンジニアがWeb開発の土台をつくるのに使った教材

## Pythonが初めてのプログラミング言語
私は社会人になってから初めてプログラミングを学びました。言語は**Python**でEDA (Explanatory Data Analysis, 探索的データ解析) や機械学習モデルをつくる所からスタートしました。

しかし、アプリ開発については知識ゼロだったので、独学で学び始めました。
現在はフリーランスで、フロントエンドやインフラ、ミドルウェアの仕事にも携わっています。

そんな私のWeb開発周りの基礎をつくった **Udemy** の講座を紹介します！Pythonが第一言語でステップアップしたい方に読んでいただきたいです！


## 【JavaScript＆CSS】ガチで学びたい人のためのWEB開発実践入門（フロントエンド編）

https://www.udemy.com/course/front-dev-tutorial/

[**DodeMafia**さん](https://x.com/codemafia0000)のWeb開発講座のフロントエンド編です！
動的ではなく静的ページの開発なので、バックエンド側は触れないですが、**約24時間分**のボリュームたっぷりのコースです！毎日仕事終わりに少しずつ進めていました。

当時は型宣言もわかってなかったので、JavaScriptの基礎やWebサイトの仕組みを理解するのにも役に立ちましたが、個人的には特に以下のことが助けになりました。

:::note
- クラスを用いたオブジェクト指向型のプログラミング
- Visual Studio Codeでの開発
- アロー関数などの省略記法
- コールバック関数
:::

私がこの講座を購入したのは4年ほど前ですが、現在は**更新版**となっています。
**ChatGPT**などにも触れているみたいなので、これからWeb開発を学ぶ方にもおすすめです！

## AWS：ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得

https://www.udemy.com/course/aws-and-infra/

こちらの講座ではインフラの基礎を学びました。
[**山浦清透**さん](https://kiyotoyamaura.jp/)は初学者向けに丁寧に教えてくれる講座が多い印象です。
こちらの講座でも**S3**、**EC2**、**VPC**、**RDS** などの代表的なコンポーネントを網羅的に扱っているので、Lambda や Bedrock など自走して他のコンポーネントを習得するのにも役立ったと思います。

個人的に良かったところです。

:::note
- WebサーバーからRDSへのつなぎ込み
- ルーティング
- SSHと公開鍵認証
:::

## おまけ：Udemy以外にも
### FastAPI はチュートリアルでかなり満足
Pythonが一番使う言語だったので、webフレームワークとして**FastAPI**を学びました。
FastAPIの開発者は[**Sebastián Ramírez**さん](https://x.com/tiangolo)というエンジニアです。
こちらはチュートリアルが十分なくらい充実していました。

https://fastapi.tiangolo.com/tutorial/

出始めの時は英語だけだったでしたが、すぐに日本語のサイトもできたような記憶があります。

https://fastapi.tiangolo.com/ja/tutorial/

FastAPI はAPIドキュメントが即座に用意できるのが良いですね！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/4364bca2-9ff7-76d8-38d6-f0ca869f25ff.png)
VSCodeで自分が良く使用しているショートカットキー

## はじめに
この記事はIPFactory Advent Calender 2024 13日目の記事です。
https://qiita.com/advent-calendar/2024/ipfactory

最近ショートカットキーを使用してVSCodeでコーディングをすることに慣れてきて、
マウスを使用する頻度が明らかに減り、作業速度が格段に上がりました。
なので、
知らなかった方もすでに知っているけど使用していない方も
ショートカットキーを使用してほしいと思い、共有したいと思います。


※すみません、自分はWindowsで開発を行っているので、Windows版のショートカットキーを紹介します。

## さっそく紹介
## カーソル操作・選択
カーソル操作は、Shift選択と組み合わせることができます。
※`Home`、`End`キーがない場合、`Fn`キーを押しながら、左右の矢印キーです。指が三本以上必要です。

| コマンド | 説明 |
|:---:|:---|
| Shift + ←/→ | カーソル位置から文字単位で選択を拡張します。 |
| Ctrl + Shift + ←/→ | カーソル位置から単語単位で選択を拡張します。 |
| Ctrl + Home | カーソルをファイルの先頭に移動します。  |
| Ctrl + End | カーソルをファイルの末尾に移動します。 |
| Ctrl + D              | 現在のカーソル位置にある単語を選択し、次の一致する単語も選択します。マルチカーソルに便利です。 |
| Ctrl + L              | 現在の行全体を選択します。                                           |


## 操作
舐めたこと書いてすみません。
| コマンド | 説明 |
|:---:|:---|
| Ctrl + C             | 選択したテキストをコピーします。                                   |
| Ctrl + X             | 選択したテキストをカット（切り取り）します。                       |
| Ctrl + V             | コピーまたはカットしたテキストをペーストします。                   |
| Ctrl + F             | 現在のファイル内で文字列を検索します。                             |
| Ctrl + Shift + F     | ワークスペース全体で文字列を検索します。                           |
| Ctrl + H             | 現在のファイル内で文字列を検索し、置換します。                     |
| Ctrl + /             | 現在の行または選択範囲をコメントアウトまたは解除します。           |
| Alt + ↑/↓            | 現在の行または選択範囲を上下に移動します。                         |
| Alt + Shift + ↑/↓     | 現在の行または選択範囲をコピーして上下に複製します。                 |
| Ctrl + Shift + K      | 現在の行を削除します（範囲選択不要）。                              |


## その他
その他でまとめてしまいすみません。

| コマンド | 説明 |
|:---:|:---|
| F1                   | コマンドパレットを開きます。                                        |
| F12                  | カーソル位置の関数や変数の定義にジャンプします。                   |
| Ctrl + @ | 統合ターミナルを表示・非表示します。 |
| Ctrl + Shift + @      | 新しいターミナルを開きます。                                        |
| Ctrl + P             | ファイル名で素早くファイルを検索して開きます。                      |
| Ctrl + S | 保存。絶対必要。設定から自動で保存することも可能です。 |

### 使いそうで使わなかった

| コマンド | 説明 |
|:---:|:---|
| Ctrl + N | 新しいファイル。右クリで作成する方が、フォルダを指定して、名前を付けられる。 |
| Ctrl + Alt + ↑/↓ | 複数行編集用のマルチカーソルを上下に追加します。 |


## まとめ
個人的に、Home、Endキーが革命でした。
この他にもショートカットキーはたくさんあるので、興味のある方は調べてみてください！おすすめのショートカットキーがあったら教えてください＾＾
**ショートカットキーをマスターして、マウス離れをしよう！！**
day14 『アジャイルサムライ』達人開発者への道

## はじめに
　当初、この書籍と出会ったときは、アジャイル開発の主要な部分と概念にもれなく触れた良い書籍だと思いました。今見ても挿絵が良く、読みやすい書籍だと思います。が。

![アジャイルサムライ 目次2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533414/2264b3ae-58d9-91ba-a888-bb0bb93c23e6.png)

## ポイント
### ３つの真実
- プロジェクトの開始時点にすべての要求を集めることはできない。
- 集めたところで、要求はどれも必ずといっていいほど変わる。
- やるべきことはいつだって、与えられた時間と資金よりも多い。

### どんな書籍も手法も、君が必要とするありとあらゆるものを用意することなんてできない。だから、自分の頭で考えるのを止めちゃだめだ！

### 顧客（実はこれができる顧客は少数派？）
- 開発チームから質問を受け付けるための時間を毎日１時間は避けること。
- フィードバックのために週に１度はミーティングできること。
- プロジェクトチームの方向性を自ら示すことができ、プロジェクトにまつわる決定を下せること。

### 見積り：当てずっぽうの奥義
- ここでも不確実性コーン登場。初期の段階で守れない約束をしちゃダメだ！ 
- 概算見積りなんて当てずっぽうだ。（本当にテキトウだし、しかも楽観的すぎる）
- 見積り手法として求められるもの。
    - 今後の計画を立てられる。
    - 見積りは当てずっぽうだという前提を踏まえている。
    - ソフトウェア開発の複雑さを認めている。

### 紹介キーワードに対する当アドカレ著者の経験的評価
　以下のようなキーワードにも触れられています。そして、本著者の主張とは異なってしまいますが、現時点では半分も指示できないキーワードになっています。ペアプロは未だ費用対効果を悩み中です。

##### x プランニングポーカー
##### x ベロシティ
##### x バーンダウンチャート
##### o デイリースタンドアップ（立ったまま朝の打ち合わせ）
##### ? ペアプロ
##### o 技術的負債
##### o リファクタリング
##### x テスト駆動開発
##### o 継続的インテグレーション

## 書誌情報
- 書籍名：アジャイルサムライ
- 著者：Jonathan Rasmusson
- 出版社：オーム社
- ISBN：978-4-274-06856-0
## 参考
-
いい機会なので、技術広報についての考えを整理する

この記事は、「[技術広報 Advent Calendar 2024](https://qiita.com/advent-calendar/2024/tech_pr)」の17日目の記事です。

夏から技術広報チームの立ち上げをしてきて、やっと軌道に乗ってきたと感じているところです。
あくまで個人として、（ソフトウェア企業の）技術広報に対しての考えを書いていきます。

# 外部への効果はゆっくり、内部には割とすぐ効く

技術広報である以上、主目的は外部への働きかけでしょう。例えば技術ブログを立ち上げたり、カンファレンスに参加したりすることが外部への働きかけにあたります。効果としては、採用時にリーチできる範囲の拡大や顧客の獲得といった面でプラスに働くことでしょうか。

これらの効果は、大バズりでもしない限り少しずつしか出ません。情報が溢れる中でターゲット層の目に触れる機会を作るのは容易なことではありません。

一方で、技術広報に取り組むこと自体が内部に効果を与え、それは外部よりも早く表れることでしょう。
ブログの執筆やカンファレンスへの参加・登壇はメンバーにとっての経験となり、チームにとっての文化になります。さらに、アウトプットにはインプットが必要となるため、自発的なインプットが生まれます。

# 理想的な状態

最初に決めたことに漠然と取り組んでしまうこともありますが、理想状態は一定確認したいものです。

## 技術広報の結果として、外部の人に持ってもらいたい感想
会社としては採用や顧客の獲得に向けて、以下のような感想を持ってもらえる状態が理想であると思います。

- この技術について調べるといつもこの会社のページが出てくる
- あの会社、こんなすごいことやってるんだ
- あの会社にはすごい人がいるな

## 技術広報に対する内部の状態

仕組みとして継続的に発展するためには、メンバーが自発的に動ける環境作りが必要です。このあたりが実現できれば自然に伸ばしていけるのではないか？と考えています。

- アウトプットをする習慣がついているメンバーがいる
- アウトプット経験がない人にとって、初回を経験する機会が設けられている
- 日々の業務の中でアウトプットに値すると思える取り組みをして、自発的にアウトプットをしようと思える

## 技術広報チームの動き

最後に、これらを踏まえて自分自身がどう動いていきたいかについてです。

アウトプットは自発的に動いてもらうのが理想ですが、まぁ人間そうはいきません。そりゃやることなんて少ないほうがいいに決まっていますから。

技術広報チームの役割はあくまで「促進」でありたいと思っています。
「なんか書いてよ」ではなくて、「え、そんなすごいことやってるならぜひ発表しようよ」という感じでやる気を出してもらうような動きをしていきたいものです。
こういった動きをするには、メンバーがどんなことをしているのかにアンテナを張っていないといけませんね。
Ubuntuサーバで独自コマンドを定義する

<!-- Ubuntuサーバで独自コマンドを定義する -->

※この記事は[Udon Advent Calendar 2024 - Adventar](https://adventar.org/calendars/10764)の13日目の記事です。

## はじめに

マジでごめんなさい。今日もギリギリの投稿になりました。書き溜めておくべきだった、、、

では気を取り直して、今日はUbuntuサーバで独自コマンドを定義する方法の覚え書きをしていこうかなと思います。

サーバをいじっていると、複数のよく使う操作をまとめて一つのコマンドとしたいときがあります。そのようなとき、自分でコマンドを定義することができます。

## 独自コマンドの作り方

独自コマンドの作り方にはいくつかあります。状況に応じて適した方法を選んでいくこととなります。

### シェルスクリプトで作る

もっともよく使う方法です。

既存のコマンドを組み合わせることによって、新しいコマンドを作成することができます。長くて覚えづらいコマンドなどはわかりやすい名前にしておくことができます。

例えば、現在実行されているプロセスのうち、Pythonに関するものを表示するコマンドは以下のように書くことができます。

```sh
#!/bin/sh

ps -ef | grep .py
```

引数を指定することもできますが、ここでは割愛します。別の記事で紹介できたらいいかなと思います。

### Cなどで作る

Cなどでプログラミングを行い、実行形式を作成してからそれをコマンドとして呼び出す方法です。

Pythonなど、コンパイルしない言語の場合は「Pythonファイルを実行する」シェルスクリプトを組んであげればよいです。

この辺も別の記事にまとめたいです。ネタが尽きない。

## 具体的な方法

### ``/usr/local/bin``にスクリプトを配置する

元々パスが通っているディレクトリにスクリプトを配置する方法です。

サーバの共通部分に配置するので、ユーザ同士で共有したいコマンドを定義することができます。

``sudo``権限が必要です。``[your_command]``には自分で定義したコマンド名を入れてください。

```bash
cd /usr/local/bin
sudo vim [your_command]
sudo chmod 755 [your_command]
```

最後に実行権限を与えておくことを忘れないようにします(``sudo``が必要なコマンドならこの限りではない)。これですぐにコマンドを呼び出すことができます。

ここに生のスクリプトを置きたくない場合は、別の場所に作った後シンボリックリンクを張ることもできます。自作コマンドを作った場所で以下のコマンドを実行します。

```bash
sudo ln -s [your_command] /usr/local/bin/[your_command]
```

もちろん、元ファイルに実行権限が必要です。

### スクリプトがあるディレクトリをパスに追加する

スクリプトがあるディレクトリをパスに追加する方法です。この設定はユーザごとに行われるものなので、自分だけが使いたいコマンドを定義することができます。

```bash
echo 'export PATH=$PATH:/path/to/your/script' >> ~/.profile
source ~/.profile
```

``>>``を使うとファイルの末尾に追記することができます。

``.profile``はログインシェルが起動されたときに読み込まれるファイルです。上記の設定を反映したい場合はログインしなおすか、以下のコマンドを実行します。

```bash
source ~/.profile
```

これで自作コマンドを呼び出すことができるようになります。

ちなみに、``.bashrc``に書く方法もあります。

## まとめ

とりあえず簡単なところだけをまとめてみました。ほかにもアライアスを設定するなどいろいろな方法が存在しています。

では今日はここまでになります。また明日の記事でお会いしましょう。

## 参考文献

[UbuntuのPATHの設定方法 #Ubuntu - Qiita](https://qiita.com/takanemu/items/6027291be8a2a6af9adc)

[シンボリックリンクの作成と削除 #Linux - Qiita](https://qiita.com/colorrabbit/items/2e99304bd92201261c60)
OpenShiftでECRプライベートリポジトリからコンテナイメージをプルする

この記事は **[セゾンテクノロジー Advent Calendar 2024](https://qiita.com/advent-calendar/2024/saison-tech)** 12日目の記事です。

シリーズ2は **[HULFT10](https://www.hulft.com/software/hulft-10)** のエンジニアによる投稿をお届けします。

## はじめに

皆さんKubernetesやOpenShift上でプライベートリポジトリのコンテナをpullしたいことありませんか？

例えば、開発中のコンテナアプリケーションはプライベートリポジトリで管理していて、それをpullしたいとか。

今回はECRを例にOpenShiftでプライベートリポジトリからのコンテナイメージをプルする方法を書き残します。

## 前提条件

- OpenShiftクラスタが準備できている
- ocコマンドがインストールされている
- AWSアカウントを持っている
- Amazon ECRのプライベートリポジトリにコンテナイメージを保管している

## 手順

### AWS認証情報を取得する

ocコマンドを実行する環境でAWSの認証情報を環境変数にセットします。
具体的には以下3つを準備します。

```shell
ecport AWS_ACCOUNT_ID="AWSのアカウントID"
export AWS_ACCESS_KEY_ID="AWSのアクセスキー"
export AWS_SECRET_ACCESS_KEY="AWSのシークレットアクセスキー"
```

### Secretを作る

プライベートリポジトリの認証情報を保持するイメージプルシークレットを作成します。

ECRからpullする場合は、docker-passwordとしてECRの認可トークンをセットする必要があるので、直接aws ecr get-login-passwordを呼び出してパスワードとしてセットします。

```shell
oc create secret docker-registry private-image-pull-secret \
   --docker-server=${AWS_ACCOUNT_ID}.dkr.ecr.ap-northeast-1.amazonaws.com \
   --docker-username=AWS --docker-password=$(aws ecr get-login-password)
```

### Podを実行する

Podのマニフェストファイルを作成します。
このとき先ほど作ったイメージプルシークレットをimagePullSecretsとして紐づけます。

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: test-pod
spec:
  imagePullSecrets:
    - name: private-image-pull-secret # 事前に作成したイメージプルシークレット名
  containers:
    - name: test
      image: ecr-pull-image:latest # 任意のECRのコンテナイメージ名
```

以下のコマンドでPodを作成します。

```shell
oc apply -f test-pod.yaml
```

### Podの起動確認

Podが正常に起動しているかを確認してみます

```shell
oc get pod test-pod
```

Runningとなっており、無事プライベートリポジトリからイメージをpullしてコンテナを起動できていることが分かりました。

```shell
NAME       READY   STATUS    RESTARTS   AGE
test-pod   1/1     Running   0          27s
```

## 注意事項

このイメージプルシークレットは永続利用できません。
なぜならECRの認可トークンには12時間の有効期限があるからです。

https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/registry_auth.html#registry-auth-token

そのためECRからプルする場合は12時間ごとにイメージプルシークレットの再登録が必要になります。
この更新を手動でやるのはあまりにも面倒なのでCronJobなどで自動化すると良いんじゃないかな思います。

## 最後に

今回はシンプルにするためにPodに直接紐づけてECRプライベートリポジトリからプルしました。

実際にはPodに直接イメージプルシークレットを紐づけることはあんまりなく、DeploymentやJob, 各種カスタムリソースなどのPodの上位リソースのimagePullSecretsに紐づけたり、それら上位リソースに紐づくServiceAccountのimagePullSecretsに紐づけたりして、最終的にPodまで伝播させるほうが一般的なんじゃないかなと思います。

ECRのプライベートリポジトリをプルする際の参考にしてみてください。

### 余談

OpenShiftはKubernetesと互換性があるので、ocの部分をkubectlに入れ替えるだけでKubernetesでも同様の手順でECRプライベートリポジトリからpullできると思います。（動作確認はしてないですがおそらくいけるはず）