OmniAICreator/Qiita-1.07M huggingface dataset:
ROS2のC++でActionサーバーのコールバック関数を書く際の便利なテクニック

ROS2（Robot Operating System 2）は、ロボットアプリケーションの開発に広く使用されている柔軟なフレームワークです。C++を使用してROS2アプリケーションを開発する際には、パフォーマンスと柔軟性のバランスを取ることが重要です。特に、Actionサーバーのコールバック関数を定義する際には、効率的かつ直感的な方法が求められます。この記事では、[this]キャプチャを持つlambda式を用いてコールバック関数を記述する利点について解説します。
# Lambda式とは？
Lambda式は、匿名関数を簡潔に記述するための機能です。C++11以降でサポートされており、関数オブジェクトを直接定義して渡すことができます。これにより、コードの可読性が向上し、コールバック関数をより柔軟に扱うことが可能になります。
# [this]キャプチャの利用
クラスメンバ関数内でLambda式を定義する際に[this]キャプチャを使用すると、Lambda式内からそのクラスのメンバ変数やメンバ関数にアクセスできるようになります。これは、Actionサーバーのコールバック関数を実装する際に特に有用です。
# Actionサーバーでの応用
ROS2でActionサーバーを実装する際、コールバック関数を設定する必要があります。このコールバック関数内でクラスのメンバ変数やメンバ関数にアクセスする場合、[this]キャプチャを持つLambda式を使用すると、コードが非常に簡潔かつ直感的になります。
サンプルソースを以下に示します。（擬似コード）
```
class MyActionServer
{
public:
    MyActionServer()
    {
        action_server_ = rclcpp_action::create_server<MyAction>(
            this,
            "~/my_action",
            [this](const rclcpp_action::GoalUUID & uuid, const auto goal_handle) {
                (void)uuid;
                (void)goal_handle;
                return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
            },
            [this](const auto goal_handle) {
                (void)goal_handle;
                return rclcpp_action::GoalResponse::ACCEPT;
            },
            [this](const auto goal_handle) {
                // 別スレッドで実行
                auto execute_in_thread = [this, goal_handle](){this->execute_goal(goal_handle);};
                std::thread{execute_in_thread}.detach();
            });
    }

private:
    rclcpp_action::Server<MyAction>::SharedPtr action_server_;

    void execute_goal(
        const std::shared_ptr<const MyAction::Goal> goal_handle)
    {
        // 受け入れられたゴールの処理
    }
};
```
この方法では、コールバック関数内で直接クラスのメンバ変数やメンバ関数にアクセスすることができ、コードの再利用性と整理が容易になります。また、Lambda式を使用することで、コードの見通しを良くし、メンテナンス性を高めることができます。

# まとめ
ROS2のC++でActionサーバーを実装する際に、[this]キャプチャを持つLambda式を用いることは、コードの簡潔性、可読性、メンテナンス性を向上させる有効な手法です。実際のアプリケーション開発において、このテクニックを活用して、より効率的で理解しやすいコードを書くことをお勧めします。
ガチの初心者がNext.jsでサイトを作る

# どのくらい初心者か
js、jsx、ts、tsxの違いがわからない

# 使用する言語、フレームワーク、サービス
- Next.js 14.1.0
    - 一通りの流れを掴みたいのでjsで作成していく
    - CSS Modulesをスタイリングに使用
- Cloudflare 

# 何を作るの？
- 静的サイト
    - 画像を掲載する個人サイトを作成する
    - 個人サイトなのでデータベースやCDNは使用しない予定

# 学習したチュートリアル
https://ja.react.dev/learn/tutorial-tic-tac-toe

Next.js チュートリアル　Assets, Metadata, and CSS　まで

https://nextjs.org/learn-pages-router/basics/assets-metadata-css

頑張るぞ
Proxmox上のVMにあるUbuntuサーバからトンネルを通ってSSH接続できるようにした

# やりたいこと
Proxmox上のVMにあるUbuntuサーバからトンネルを通ってSSH接続できるようにしたい

# 環境
| サーバ | FMKTEC NUCBOX3 |
| ------ | -------------- |
| 接続先（サーバ）OS     | Ubuntu（x86_64）       |
| 接続元（クライアント）OS     | Mac OS（Venture 13.5.1 M1チップ）       |

現在のOSがどのシステムアーキテクチャか調べるには`uname -m`コマンドを打ちます

# ProxmoxにUbuntuVMをぶちこむ
以下動画通りにやります

https://www.youtube.com/watch?v=i-ZGKBSVpeg&t=2s&ab_channel=Niwaka_CatCraft

https://www.youtube.com/watch?v=Mx6rJ-jRu2Y&t=195s&ab_channel=Niwaka_CatCraft

https://www.youtube.com/watch?v=jQIsbZ1_Jag&ab_channel=Niwaka_CatCraft

# 接続先（サーバ）OSでやること
## 1. `openssh-server`のインストール
```bash
sudo apt -y update
sudo apt -y install openssh-server
```
## 2. `/etc/ssh/sshd_config`の設定
以下の項目を探して修正します
```bash
PublickeyAuthentication yes

PasswordAuthentication no
```

修正したら以下のコマンドで再読み込みします
```bash
sudo systemctl restart ssh
```

## ssh用の鍵を生成する
```bash
ssh-keygen -t rsa
```
なんか色々聞かれますが、全部`Enter`を押します

id_rsa.pubについては、ファイル名を`authorized_keys`に変更します
```bash
cd .ssh

mv id_rsa.pub authorized_keys
```

権限を変更する
```bash
sudo chmod 600 authorized_keys
```

## 3. cloudflaredのインストール
```bash
wget https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-amd64.deb

sudo dpkg -i cloudflared-linux-amd64.deb
```


# Cloudflareの設定
こちらはクライアントOSで行います
雑ですが以下の記事の「SSH configファイルを設定する」まで行います

https://zenn.dev/jij_inc/articles/659fe35813b940#2.-ssh-config%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%99%E3%82%8B


# 接続元（クライアント）OSでやること
## 1. キーペア（公開鍵と秘密鍵）の生成
```bash
cd ~/.ssh

# もし~/.sshディレクトリを作成していなかった場合
mkdir ~/.ssh
```

`~/.ssh`直下で
```bash
ssh-keygen -t ed25519 -m PEM -C ''
```
そうすると、`id_ed25519`と`id_ed25519.pub`の2つのファイルが生成されます
`.pub`拡張子のついている方が公開鍵です（Publicのpub）


## 2. SSHキーをトンネルを通して接続元（サーバ）OSに公開鍵を登録する
```bash
ssh-copy-id -i ~/.ssh/id_ed25519.pub <ユーザ名>@<Cloudflareで登録したHostName>
 ```

:::note warn
もし権限の関係で書き込めなかった場合
:::
接続先（サーバ）OSにクライアントOSの`~/.ssh/id_ed25519.pub`の内容を`authorized_keys`に追加します
ちなみに中身は`cat`だったり、`vim`だったりで見れます


## 3. サーバにSSH接続する
```bash
ssh <ユーザ名>@<Cloudflareで登録したHostName>
 ```
以上です！

# 参考
https://zenn.dev/grarich/articles/2735b5b1b2f91f

https://www.kkaneko.jp/tools/server/pubkey.html
FlutterのUnsafeAreaのボタンが働かない対処方法

ステータスバーの文字が消えるのは、ネイティブアプリも同じ挙動なのでダイナミックアイランドを保護したシステム的な仕様かもしれないです。

Flutter 3.16.9
https://github.com/flutter/flutter/issues/51345#issuecomment-1948579004

```dart
void main() {
  // MediaQuery.removePadding removeTopと
  // 併用でセーフエリアのボタンを有効にする。
  SystemChrome.setEnabledSystemUIMode(
      SystemUiMode.immersiveSticky);

  runApp(const App());
}
```

```dart
class HomePage extends HookConsumerWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    ...
    return MediaQuery.removePadding(
        context: context,
        removeTop: true,
        child: scaffold
    )
  }
}
```
SynthV scriptを書くときの覚え書き

JavaScriptがわからん。
しかしLuaはもっとわからん。


# SynthV scriptとはなんぞや
Synthesizer Vというソフトを拡張するためのスクリプト。
ノートの操作だけでなく選択や再生、果ては画面操作まで何でもできる。
何でもできすぎて逆に不安になる。


# この記事は何
スクリプトを書くたびに毎回既存のコードやらサンプルコードやらからコピペしているので
いいかげん真面目にメモを作ろうと思った。

筆者は基本C#しか書けないというかC#もまともに教わったことないので
いわゆる「お作法」みたいなものは何もわからない。


# とりあえず最初に書くやつ
```javascript
function getClientInfo() {
  return {
    "name": SV.T("Title"),
    "author": "Maiko", // 作者名
    "versionNumber": 1.00,
    "minEditorVersion": 65537, // 実は「ライセンスとアップデート」のとこで見れる本体バージョン
    "category": "Playback"
  };
}

function getTranslations(langCode) {
  if (langCode == "ja-jp") {
    return [
      ["Title", "タイトル"]
    ];
  }
  return [];
}
```

画面上に表示される文字は一応`SV.T("")`で囲って翻訳できるようにしておく。
（[SynthV Forum](https://forum.synthesizerv.com/)に翻訳作って～と投げると誰かがやってくれる可能性あり）
カテゴリは適当。


# よく使うオブジェクトまとめ
### ノート関連
```javascript
var groupReference = SV.getMainEditor().getCurrentGroup(); // 操作中のグループ（配置されてるやつ）
var group = groupReference.getTarget(); // 親グループ（音符の位置はグループ頭からの位置）
var selection = SV.getMainEditor().getSelection(); // 選択状態を取得したり操作したりするやつ
var selectedNotes = selection.getSelectedNotes(); // 今選択されてるノート
```
どうも、SynthVにもボカロやOpenUtauでいうパートみたいなものがあるらしい。DAWでいうクリップというか、ピアプロスタジオでいうリージョンというか。
それが`NoteGroup`と呼ばれるもので、やっかいなことにこれはトラック上に同じグループを複数配置できる。編集の中身も共有される。
ので、親グループ・子グループみたいな概念が存在する。

仮に、配置されているものが子グループ、それらが共有しているノート情報が親グループとして、トラック上の（正確にはグループ内の）すべてのノートにアクセスしたいなら親グループから、今操作しているグループの開始位置とかを取得したいなら子グループから取得する。
選択しているノートを取得するだけならグループ情報は必要なく、このコードでいう`selectedNotes`だけあればいい。

ちなみに[スクリプトマニュアル](https://resource.dreamtonics.com/scripting/ja/NoteGroupReference.html)では子グループは`NoteGroupReference`と書かれている。


### その他のオブジェクト
```javascript
// 再生状態を取得したり操作したりするやつ
var playback = SV.getPlayback();

// 分秒とBlickを変換したりするやつ
var timeAxis = SV.getProject().getTimeAxis();

// トラック
var track = SV.getMainEditor().getCurrentTrack();

// スクロール関連(CoordinateSystem)
var mainCoordSystem = SV.getMainEditor().getNavigation(); // ピアノロール
var trackCoordSystem = SV.getArrangement().getNavigation(); // トラック
```

- BlickはMIDIでいうTickみたいなやつで、SynthV独自の単位？みたい。
Tickが一般的に4分音符=480なのに対しBlickの数字はめちゃくちゃ細かい。

- ノートの項で書いたがノートの位置はノートグループ内での相対位置なので、再生バーの位置とノートの位置を比較する場合などは`playback.getPlayhead()`を`TimeAxis`使ってBlickに直し、
(NoteGroupReferenceの開始位置＋グループ内でのノートの位置)と比較する。

- PlaybackControlは再生状態の取得も制御もできるし、CoordinateSystemは画面の表示範囲の取得もスクロール・ズームの制御もできる。

- `Arrangement`というワードがでてきたらだいたいトラックエリアの話。

# 他、覚え書き
```javascript
// デバッグに詰まったらとりあえず出してみる
SV.showMessageBox("title", "message");

// 4分音符ぶんのBlick
var quarter = SV.QUARTER;

// パラメータパネルのオートメーション取得例
var pitch = group.getParameter("pitchDelta");

// 最後に絶対書くやつ
SV.finish();
```

# できないこと
初期値の取得。
たとえば、ノートにパラメータ（マニュアルのビブラートとか）が設定されていないときはトラック（グループ？）のデフォルト値が使われるが、ノートからビブラートの情報を取得しようと思ってもUndefinedしか返ってこない。
何より、音素が未編集のとき取得できないのが一番やっかい。

また、歌唱モードだのマニュアルモードだのをはじめとする最近の機能絡みのパラメータもたぶん取得できない。
Kotlin x Thymleafで Bean property 'isXXX' is not readable or has an invalid getter method

## 事象
Kotlinのdata classで プロパティ名がis始まりだとThymleaf側でgetterがないと怒られる

```kotlin:testClass
data class TestForm(
    var id: Int = 0,
    var isPublished: Boolean = false  // これに対してgetterがないよと言われる。
}
```

```html:thymleafのview
<div th:value="${testForm.isPublished}"></div>
```

```log:error
Bean property 'isPublished' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
```

## 原因
is始まりの場合は、getter、setterの命名規則が違うから。

| プロパティ名 | getter |setter |
|:-:|:-:|:-:|
|hoge|getHoge|setHoge|
|isHoge|isHoge|setHoge|

## どうしてこうなってるのか
- Java の Bean規約に従っているため

以下でダウンロードできる。
https://download.oracle.com/otndocs/jcp/7224-javabeans-1.01-fr-spec-oth-JSpec/

上記から抜粋したもの
```
8.3.2 Boolean properties
In addition, for boolean properties, we allow a getter method to match the pattern:
public boolean is<PropertyName>();
This “is<PropertyName>” method may be provided instead of a “get<PropertyName>” method, or it may be provided in addition to a “get<PropertyName>” method.
In either case, if the “is<PropertyName>” method is present for a boolean property then we will
use the “is<PropertyName>” method to read the property value.
An example boolean property might be:
public boolean isMarsupial();
public void setMarsupial(boolean m);
```

`is`始まりと言ったらbooleanだよね。だったらbooleanのプロパティのgetterも`is`始まりにするね。
的なことが書かれている。

### という理解で大体OKだが、自分の中で少し気になったので書いておく↓
今回のケースをもう少し厳密にかくと、
Kotlinは実行するためにJavaコードに変換している。
そのときのルールというのも一応ある。基本的には、上記JavaBeansの規約とほぼ同等。
https://kotlinlang.org/docs/java-to-kotlin-interop.html#properties

ほぼと言っているのは、Javaではbooleanのgetterは全てis始まりにするというのが軸になっている(風に見受けられる）が、kotlinのData ClassからJavaに変換する際は、boolenaかどうかではなく、単純に名前が`is`始まりかを見ているから。
実際にkotlinのdata classをjavaのコードに変換してみてみるとわかりやすいです。
https://qiita.com/ke__kyukyun1828/items/384972110df2152bf530

例えば、booleanのtestFlagというプロパティのgetterは、JavaBeansの思想だと`isTestFlag`になりそうだが、kotlin to Javaにおいては `getTestFlag`とシンプルにgetを接頭辞につけたものになる。

## 対策
- getterを自分で作る(getterが2つできるのは気持ち悪い&何か問題起きそう)
    - 例えば、 isTestというプロパティについて、 getIsTestを作る。
- アノテーションで任意のgetter、setter名にする(これならまだアリなのかも）
    - https://kotlinlang.org/docs/java-to-kotlin-interop.html#handling-signature-clashes-with-jvmname
    - 例：  `@get:JvmName("isPublished") @set:JvmName("setIsPublished") var published: Boolean = false,`
- そもそもis始まりの名前を使わない。
    - 予期しない動作は防げるかも。でもちゃんとコメントしておかないと後であれこれis始まりがよくない？ってなりそう

## まとめ
is始まりのプロパティ名のgetter、setterは別ルールが適用されるよ。
基本的に問題起きないけど、ライブラリとか(今回はThymelaf)で、このルールに対応できていないものもあるのでそういうところは気を付ける。
【Next.js】middlewareでリダイレクトする際にヘッダーをセットする方法

以下のように記述することでリダイレクトのレスポンスヘッダーに値を追加できます。

```js
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  if (request.nextUrl.pathname === '/') {
    const response = NextResponse.redirect(new URL('/test', request.nextUrl))
    response.headers.set('some-header', 'hello')

    return response
  }
}
```
デザイン参考に便利なサイトまとめ【第一弾】

こんばんは～
チーム開発も中盤に差し掛かり、そろそろデザインを整えたいな～と思っているので、
現時点で使ってみたいサイトをまとめてみました！

2024.3.29追記
第二弾を予想以上に沢山の方が見てくださったので、こちらを第一弾と明記いたしました！

## ロゴ
### Wix Logo Maker

https://ja.wix.com/logo/maker

AIが自分の作りたいロゴの情報からいくつものパターンのロゴを作成してくれます！
色や文字、イラストも編集できて自分好みのロゴができるはず！
無料でロゴのダウンロードが可能です。

## カラー
### 原色大辞典
https://www.colordic.org/

個人的には洋色が好みです！CSSのcolor指定の際にぜひ！

## CSSアニメーション
### Animete.css
https://animate.style/

いろんな動きを指定できます！

### CSS Animo
https://cssanimo.netlify.app/

動きに加えて見た目も変えられます！

## 最後に
最近チーム開発で忙しかったり、自分の用事があったりで忙しいですがなるべく1日1回投稿を続けたいです！今日は他にもHTMLやCSSの入力短縮の略語も学べたので明日以降まとめようと思います。
Photon FusionのRPCのメソッド名の仕様

Photon Fusion SDK v2がUnityのAssetStoreで公開され、早速使ってみよということでRPCのコードを書いていると謎（ではない）Exceptionが発生してしまうようになってしまった。解決するまで意味がわからなかったので、同じ問題に直面した人が同じようにハマらないように記録を残しておきます。

# 対応方法

RPCで呼び出すメソッド名にはprefixかsuffixでRPC（大文字小文字不問）を付ける。
例：RPC_Method とか MethodRpcとか

# エラー内容

以下のような感じで他にも15個（合計18個）のExceptionが表示された。ここの3つ目が重要だった。

```
Fusion.CodeGen.ILWeaverBindings: /(省略)/Assets/Photon/Fusion/CodeGen/Fusion.CodeGen.cs(3522,0): error Exception thrown when weaving Assembly-CSharp
```

```
Fusion.CodeGen.ILWeaverBindings: (0,0): error Fusion.CodeGen.ILWeaverException: Failed to weave behaviour （省略）
```

```
Fusion.CodeGen.ILWeaverBindings: (0,0): error  ---> Fusion.CodeGen.ILWeaverException: System.Void （省略）(System.String): name needs to start or end with the "Rpc" prefix or suffix
```

# その他

- 最初のExceptionで検索すると [Weaver Exception when load the Fusion Application Loop example](https://forum.photonengine.com/discussion/21310/weaver-exception-when-load-the-fusion-application-loop-example) がひっかかり、ここから調査を始めてしまった。Exception全体を眺めてから着手するべきだったなと反省
- Photon Fusionの[チュートリアル](https://doc.photonengine.com/fusion/current/tutorials/host-mode-basics/6-remote-procedure-calls)もやっていたのだが、Hostモードはsuffix、Shareモードはprefixだったため、どっちでも大丈夫ではなく、どちらでなくても大丈夫だと勘違いしてしまった
React Router v5とv6 の違いに混乱した件

# はじめに
僕が受講しているudemyでReact Routerを扱う場面があったのですが、少し情報が古くてv5でした。
でもまぁなんとなく書けるだろうーーと楽観的に捉えていた僕でしたが、5秒も経たないうちにエラーが出ました笑

同じような境遇の方がいましたら、参考までにしてください。

# ルーティングの実装方法
### 単純なページ遷移をしたい場合

- 基本的な設定
```jsx:ルートの設定
<Routes>
    <Route path = "パス" element={<"表示したいコンポーネント名"/>}/>
</Routes>
```
このルートの設定を使って、v5と同様に*Link*コンポーネントを使えば、基本的な画面遷移を実装することが出来ます。
<br>
- ネストする画面遷移
```jsx:ルートの設定
<Routes>
    <Route path="親パスの名前">
        <Route index element={}>
        <Route path="パスの名前(相対的な)" element={}>
        <Route path="パスの名前(相対的な)" element={}>
    </Route>
</Routes>
```
基本的な画面遷移に加えて、さらにネストした画面遷移を実装したい場合、上記のようなコードで可能になります！
indexを使うことで親のパスで表示したいコンポーネントを指定できます。そして同様に*Link*を使用することによってネストされた画面遷移の完成です！

# 終わりに
今回の記事では、React Routerの本当に基礎の基礎の構文だけを載せてみました！僕がそのレベルしか扱えないので笑
今後React Routerを多用する場面やもっと高度なことをする必要が出てきたら再度学びなおそうと思います。Nextjsを使えばルーティングが楽になるということを耳にしたことがあるので、いつか触ってみたいです。

React Routerのことを調べていて思ったこと、

<font color="red">**やはり公式ドキュメントが一番正しい!!!**</font>

英語ばっかだし読む気失せるけど、英語読もうとして挫折するくらい(自分)ならGoogle翻訳使って読んで見ようと思います。一読とはいかなくても、必要な部分だけでも。
エラー処理の基本の理解を深めよう！

# エラー処理
エラー処理は、プログラムのエラー状態に応答し、エラー状態から回復するプロセスのことである！
アプリ操作が失敗してエラーになった場合、コードがそれに応じて応答できるようにすることで、失敗の原因を確認、エラー復旧することが可能になる！

# エラーの表現
エラーは`Error`プロトコルに準拠した型によって表される！

```Swift
enum APIClientError: Error {
    case networkError
}
```
# throw文
エラーを投げるには、`throw文`を使用する！
throw文は、任意のタイミングでエラーを発生させるときに使用する！throw文でエラーを投げるためには、Errorプロトコルに準拠させる必要がる！

```Swift
switch (response as? HTTPURLResponse)?.statusCode {
        case 200:
            let weatherData = try JSONDecoder().decode(WeatherData.self, from: data)
            let description = weatherData.weather[0].main
            let cityName = weatherData.name
            return (description, cityName)
        default:
            throw APIClientError.networkError
        }
```
上記はAPI通信の結果である`response`が`200 OK`じゃなければエラーを投げる処理。

# throwsキーワードを使用した関数によるエラー処理
関数・メソッド・イニシャライザがエラーを投げる可能性があることを示すには、関数の宣言のパラメータの後に`throws`キーワードを記述する。
`throws`でマークされた関数は、スロー関数と呼ばれる。
関数が戻り値の型を指定する戻り矢印(->)の前に`throwsキーワード`を記述する。
そうすると、`Stringのタプル` or `Error`を返す関数になる！

```Swift
func getWeather(latitude: String, longitude: String) async throws -> (String, String) {
        let urlString = "https://api.openweathermap.org/data/2.5/weather?lat=\(latitude)&lon=\(longitude)&appid=\(Constants.apiKey)"
        let url = URL(string: urlString)
        let urlRequest = URLRequest(url: url!)
        let (data, response) = try await URLSession.shared.data(for: urlRequest)
        switch (response as? HTTPURLResponse)?.statusCode {
        case 200:
            let weatherData = try JSONDecoder().decode(WeatherData.self, from: data)
            let description = weatherData.weather[0].main
            let cityName = weatherData.name
            return (description, cityName)
        default:
            throw APIClientError.networkError
        }
    }
```


# do-catch文を使用したエラー処理
`do-catch文`は、次のように`do`を宣言し、正常時に実行したいコードを記述する。`catch`には、エラー時に実行したいコードを記述する。do節の実行中にエラーが発生すると、catch節に実行が移る。
呼び出す側はエラーを返す可能性のあるメソッドを`tryキーワード`を使用し、呼び出す！
```Swift
private func showWeatherView() {
        let (latitude, longitude) = PrefectureLatLon().fetchLatLon(weatherPrefecture: prefecture)
        Task { @MainActor in
            do {
                let (description, cityName) = try await WeatherAPIClient().getWeather(latitude: latitude, longitude: longitude)
                self.weatherLabel.text = description
                self.prefectureLabel.text = cityName
            } catch {
                let alert = AlertMaker().make(didTapRetry: {
                    self.showWeatherView()
                })
                self.present(alert, animated: true, completion: nil)
            }
        }
    }
```
正常にAPI通信が実行できると`do{}`内の処理が実行され、ViewにAPIから取得した天気と地域を表示する！
エラーが発生すると`catch{}`内の処理が実行され、アラートを表示する！

# おまけ: async/awaitについて知りたい方はこちら


https://qiita.com/hinakko/items/1df89b8c4662fcc4bf0e





# 参考文献

https://www.swiftlangjp.com/language-guide/error-handling.html

https://swift.codelly.dev/guide/%E3%82%A8%E3%83%A9%E3%83%BC%E5%87%A6%E7%90%86/#do-catch%E6%96%87
AozoraEpub3公式版の問題点と改造版の問題点

# AozoraEpub3公式版
* そもそもAozoraEpub3-1.1.0b46.zipをダウンロード出来ない
公式サイト以外に自分用途としてアップしている所や中華サイトは見つけることが出来るが、真贋を確認出来ないのでお勧め出来ない
* EPUB3.3準拠のEPUBチェッカーで検証するとエラーが発生する
  * nav.xhtmlに関するエラー
  * 濁点つきフォントに関するエラー

:::note info
エラーが発生したとしてもKindle (第7世代)や Kindle Paperwhite (第7世代)では問題なく読書可能
:::

## 環境がWindowsの場合 (以下の手順時)

https://qiita.com/kokotaro@github/items/4db382eee10997d1f517

* 現状無いように見える

:::note info
公式掲示板に問題発生環境として記載された小説の変換は問題無く変換出来ている。ただKindle端末で全てチェックした訳じゃないので見落としはありそう
:::


## 環境がLinuxの場合 (Ubuntu22.04 LTSのみチェック)
* 挿絵があると変換に失敗する時がある

## 環境がmacOSの場合 (所有してないので公式掲示板の情報)
* 挿絵があると変換に失敗する時がある

## 閲覧時の問題
* 超縦書ビューワーでEPUBファイルを開けない
* BookWalkerのビューワーで濁点フォントが適用されない

:::note warn
そもそもnarou.rbの目的がKindle端末で小説家になろうを読むという目的に見えるので、特定のアプリで正しく表示されないのを問題とするのは違うと思っている。でも直せるなら直したいよね
:::

# AozoraEpub3改造版
## narou.rbへのパッチが必要
* ディレクトリ構造の想定が異なりnarou init時にCSSファイルやフォント情報が反映されない
* 濁点フォントを使用するオプションを有効に指定すると変換時にエラーが発生
* JDK21を使用した場合にエラーが発生する
* 表紙のcssスタイルが反映されない (致命的じゃないので記載するのをためらうレベル)

:::note warn
改造版を使用する場合の修正点のまとめを以下のページで整理した。
:::

https://qiita.com/kokotaro@github/items/506882ae86a9b223c12b

## 良くなること
* 上記の問題を解消出来ると、EPUB3.3準拠のEPUBチェッカーで検証しエラー無しになる
* ビューワーアプリ等での表示差分が無くなる
* Linux、macOS環境で挿絵あると変換に失敗する問題が解消される
ReactでのCSSの使用

## 普通のCSSの使用
#### インライン Style(推奨しない)
下記の条件が必要です。
- HTMLスタイルと同じ、要素のインライン スタイルです
- 文字列ではなく、JS オブジェクトの形式である必要があります
- スタイル名は「fontSize」のようにキャメルケースで表記する

```tsx
<span style={{color: 'green'}}>在庫あり</span>
```
#### classNameの使用
- HTMLクラスと同様にCSSスタイル名をclassNameで設定する
- JSの`class`と重複するため、`className`に名前を変更する
- [clsx](https://www.npmjs.com/package/clsx) または [classnames](https://www.npmjs.com/package/classnames) 条件を使用して判定可能

## CSS-in-js (推奨）
- CSSをJSで記述する（コンポーネントコード内）
- CSS クラス名の重複を心配する必要はない
- CSS-in-js はツールの名前ではなくソリューションです

#### Styled-componentsの使用
ドキュメント
https://styled-components.com/
```tsx
// Button コンポーネント
type ButtonPropsType = {
  primary?: boolean
}
const Button = styled.button<ButtonPropsType>`
  background: transparent;
  border-radius: 3px;
  border: 2px solid palevioletred;
  color: palevioletred;
  margin: 0 1em;
  padding: 0.25em 1em;

  ${(props) =>
    props.primary &&
    css`
      background: palevioletred;
      color: white;
    `}
`

// Containerコンポーネント
const Container = styled.div`
  text-align: center;
`
const Demo: FC = () => {
  return (
    <div>
      <p>styled-components demo</p>
      <Container>
        <Button>Normal Button</Button>
        <Button primary>Primary Button</Button>
      </Container>
    </div>
  )
}
```
初めてのJavaScript:初心者の学び場（Documentメソッド）

今回はJavaScriptのDocumentメソッドです。

Documentオブジェクトは、Webページ全体を表現するためのオブジェクトであり、ブラウザ上でのドキュメントの構造や内容にアクセスするためのメソッドやプロパティを提供します。
##  1\. getElementById(id)
指定されたid属性を持つ要素を取得します。
```diff_javascript:
const element = document.getElementById('myElement');
```

## 2\.getElementsByClassName(className)
指定されたクラス名を持つ要素を含むHTMLCollectionオブジェクトを返します。
```diff_javascript:
const elements = document.getElementsByClassName('myClass');
```

## 3\.getElementsByTagName(tagName)
指定されたタグ名を持つ要素を含むHTMLCollectionオブジェクトを返します。
```diff_javascript:
const elements = document.getElementsByTagName('div');
```

## 4\.querySelector(selector)
指定されたCSSセレクタに一致する最初の要素を返します。
```diff_javascript:
const element = document.querySelector('.myClass');
```

## 5\.querySelectorAll(selector)
指定されたCSSセレクタに一致する全ての要素を含むNodeListオブジェクトを返します。このメソッドは、特定の条件に一致する複数の要素を取得する際に非常に便利です。
```diff_javascript:
const elements = document.querySelectorAll('.myClass');
```

## 6\.createElement(tagName)
指定された要素名の新しいElementオブジェクトを作成します。JavaScriptで動的に要素を生成する際に使われます。
```diff_javascript:
const newElement = document.createElement('div');
```

## 7\.addEventListener(event, listener)
指定されたイベントが発生したときに、指定されたリスナー関数を呼び出します。特定のイベントに対する処理を設定する際に使われます。
```diff_javascript:
element.addEventListener('click', function() {
  console.log('Element clicked');
});
```

## 8\.appendChild(node)
指定されたノードを現在の要素の子要素として追加します。新しい要素をDOMに追加する際によく使われます。
```diff_javascript:
parent element.appendChild(newElement);
```

## 9\.removeChild(node)
指定されたノードを現在の要素から削除します。不要な要素をDOMから削除する際に使われます。
```diff_javascript:
parent element.removeChild(child element);
```

## 10\.getElementById(id), getElementsByClassName(className), getElementsByTagName(tagName)
これらのメソッドは、要素をid、クラス、タグ名によって取得するために使用されます。特にidやクラス名によって要素を特定する必要がある場合によく利用されます。
```diff_javascript:
const elementById = document.getElementById('myElement');
const elementsByClass = document.getElementsByClassName('myClass');
const elementsByTag = document.getElementsByTagName('div');
```
【Golang】GORMでPostgres利用時のCreateをgo-sqlmockで単体テスト

# はじめに
　近年WEBアプリケーションのバックエンドAPIにGolangを採用することが増えている。それに伴いGORMをORマッパーに採用することも少なくないだろう。
　本記事ではデータベースにPostgresを採用時、GORMで実装したInfrastructure層のCreate関数を単体テストする。

# Domain層
　Infrastructure層の単体テストを行うにあたり、本記事で利用するリソースの抜粋を以下に示す。
```golang: domain/user.go
type User struct {
    gorm.Model
    Name  string `gorm:"not null"`
    Email string `gorm:"uniqueIndex;not null"`
}

type UserRepository interface {
    Create(*gorm.DB, *User) error
}
```

# Infrastructure層
 今回単体テストを行うCreate関数を以下に示す。
```golang: infrastructure/persistence/user.go
type userPersistence struct {}

func (up userPersistence) Create(db *gorm.DB, user *domain.User) error {
    return db.Create(user).Error
}
```

# 単体テスト
　本記事の目的である単体テストを行うプログラムを以下に示す。
```golang: infrastructure/persistence/user_test.go
type AnyTime struct{}

func (a AnyTime) Match(v driver.Value) bool {
	_, ok := v.(time.Time)
	return ok
}

func TestCreateUser(t *testing.T) {
    user := &domain.User{
		Name:  "Testing"
        Email: "test@sample.com"
	}

	sqlDB, mock, err := sqlmock.New()
	if err != nil {
		t.Errorf(err.Error())
	}

	db, err := gorm.Open(postgres.New(postgres.Config{Conn: sqlDB}), &gorm.Config{})
	if err != nil {
		t.Errorf(err.Error())
	}

	mock.ExpectBegin()
	mock.ExpectQuery(regexp.QuoteMeta(`INSERT INTO "users"`)).
		WithArgs(AnyTime{}, AnyTime{}, nil, user.Name, user.Email).
		WillReturnRows(sqlmock.NewRows([]string{"id"}).AddRow(1))
	mock.ExpectCommit()

	p := NewUserPersistence()
	if err := p.Create(db, user); err != nil {
		t.Errorf(err.Error())
	}

	if err := mock.ExpectationsWereMet(); err != nil {
		t.Errorf(err.Error())
	}
}
```
　ここで注目したいのが`mock.ExpectQuery`である。go-sqlmockのGitHub内Readmeに、INSERT INTOのテストは`mock.ExpectExec`で行うと記載されている。本来、INSERT, UPDATE, DELETEなどのsqlはExec、selectなどのsqlはQueryで実行される。簡単に説明すると、Execでの実行は戻り値がなく、Queryでの実行は戻り値がある、と考えて問題ない。
　ではなぜINSERTなのにQueryで実装されるのか。これはDBがPostgresの際にGORMが作成するsqlに`RETURNING`が含まれるからである。GORMが作成するsqlを以下に示す。
```sql
INSERT INTO "users" ("created_at","updated_at","deleted_at","name","email") VALUES ($1,$2,$3,$4,$5) RETURNING "id"
```
 RETURNINGはPostgresのみの機能(MySQLにはない)で、実行時に戻り値を設定する。GORMのCreate関数が作成するsqlはIDを返すようになっているため、Execでの実行ではなくQueryでの実行になり、`mock.ExpectQuery`でテストを行う必要がある。これはgo-sqlmockの[issue](https://github.com/DATA-DOG/go-sqlmock/issues/118#issuecomment-614573409)で言及されている。

 # まとめ
 　本記事ではPostgresのDBを利用時GORMで実装したCreate関数を、go-sqlmockで単体テストを行う手法をまとめた。詳しいtestingやgo-sqlmockの記載方法、DataBaseのExecとQueryの違いなどは公式サイトを確認してほしい。
　では、良いエンジニアライフを。
WSL2からJetpack5.1.2をXavierにセットアップ

デュアルブートでUbuntuを起動すれば良いのですが、セットアップが面倒なのと、手持ちのx86_64 PCはストレージを分割するには小さいこともあり、WSL2でJetPackのセットアップを頑張りました。
本来はホストマシンにx86_64のUbuntuを用意していれば何事もなくセットアップが終わるのですが、世の中の多くの方は所有していないらしくNVIDIAのコミュニティでは怨嗟の声が絶えません。

本来のやり方から逸脱して、VMやWSLに入れたUbuntuで`sdkmanager`のフラッシュコマンドを実行する……そのような横着をNVIDIAさんは許してくれないのか、処理中に何回かUSBの接続を切ってエラーになる実装となっています。

## 先人に習う

こちらの方は手動でUSB接続を復帰すれば良いと書いています。
しかしながら…v5.1は早すぎて手動接続は無理ゲーでした。

https://qiita.com/Manyan3/items/91e35d9d976be22c7bb7

記事に書かれているセットアップですが、今回用意したWLSのディストリビューションはUbuntu 20.04なのでqemu-arm問題は起きません。

あまり困ることもなく、先に進んでいくとフラッシュコマンドの実行でUSB接続が切れて先に進めません。
```
sudo ./apply_binaries.sh
sudo ./nvsdkmanager_flash.sh
```

## 人の手で無理ならコードを書き換えたら良いじゃない

どうも「USB接続が切れてから復帰までに手動でUSBを接続しなおすの無理ゲーじゃね？」と暫く悩みましたが、何度か観測していると、どうやら`Rebooting to recovery mode`の場所でUSBが切断されていることが切断音とメッセージのタイミングから予測できました。

`Linux_for_Tegra`フォルダにある、`bootloader/tegraflash_internal.py`にスリープを仕込みます。

```
$ vi bootloader/tegraflash_internal.py

info_print('Rebooting to recovery mode')
time.sleep(10)
```

これで、USBの接続が切れても手動回復する時間の確保に成功しました。
拍手👏

今日もつまらないことに時間を使ってしまった。。orz
Laravel Eloquentのupsertメソッドが便利だった

業務で、foreach文の中で毎回saveを呼んで処理が重くなってしまっていた部分があり、調べてみるとupsertメソッドを使用すると良いと知ったため、備忘録として残します。

# upsertメソッドについて
1つのクエリで、複数のレコードのUpsertを行うことができます。

:::note info
Upsertとは..
更新対象のデータがすでに存在していればupdateを行い、存在していなければinsertを行う。
:::

https://readouble.com/laravel/10.x/ja/eloquent.html

今回の業務では、1つのクエリで更新対象のデータを更新したかったため、updateとして利用しました。

# 使用方法について
例として、Usersテーブルにupsertするケースを挙げます。
また、すでに以下のデータがUsersテーブルに存在するとします。
|id | name | email|
|:-----------:|:------------:|:------------:|
| 1| yamada     | yamada@test.com|
| 2| satou      | satou@test.com|

```php
$users = [
    // update
    ['id' => 1, 'name' => 'yamada', 'email' => 'yamada2@test.com'],
    // update
    ['id' => 2, 'name' => 'satou', 'email' => 'satou2@test.com'],
    // insert
    ['id' => 3, 'name' => 'tanaka', 'email' => 'tanaka@test.com']
];

User::upsert($users, ['id'],['email']);
```

id = 1,2はすでに存在しているためupdateされ、id = 3は存在していないためinsertされます。

引数で渡している値については、

<dl>
  <dt>第1引数</dt>
  <dd>upsertの対象となるデータの値を配列で渡します。</dd>
  <dt>第2引数</dt>
  <dd>レコードのユニークを識別するカラムの配列を渡します。<br>
  （※注意点として、プライマリーキーかユニークキーを選択してください。それ以外だと動きません。）</dd>
  <dt>第3引数</dt>
  <dd>updateする際に更新したいカラムの配列を渡します。こちらは省略可能であり、省略すると全カラムが更新されます。</dd>
</dl>

# タイムスタンプについて
モデルのタイムスタンプが設定されている場合、第3引数に「created_at」「updated_at」を含めなくても、insert時は「created_at」「updated_at」に値が自動で入り、update時は「updated_at」が自動で更新されます。

# 実務で実際にupsertメソッドを使用したときの例
foreach文の中で毎回saveメソッドを呼んでいた部分を、以下のようにupsertメソッドで置き換えを行いました。
````php
$upsertUsers = [];

foreach($TargetUsers as $user){
    $upsertUsers[] = [
        'id' => $user->id,
        'send_mail_count' => 1,
    ];
}

User::upsert($upsertUsers, ['id'],['send_mail_count']);

````

upsertメソッドはすごく便利のため、皆様もぜひ使ってみてください。

# 参考記事
https://re-engines.com/2023/04/11/laravel%E3%81%AE%E4%BE%BF%E5%88%A9%E3%83%A1%E3%82%BD%E3%83%83%E3%83%89upsert/
結局「フルサクセス」っぽい感じ IT用語に「ミニマムサクセス」はなさそうだが、あってもいい感じ２

# はじめに
先日、SLIM（スリム: Smart Lander for Investigating Moon）月面着陸成功をお祝いして、「 [IT用語に「ミニマムサクセス」はなさそうだが、あってもいい感じ](https://qiita.com/mylifewithviolin/items/1e754f04ea40959cba79)」という記事で強引に宇宙開発に触れさせていただきました。

# 「ミニマムサクセス」なのか「フルサクセス」なのか
その後の報道でSLIMは目標地点の55m付近で、逆立ちランディングしていることが明らかになり、太陽電池パネルの向きがいまはあさってなのは、月の自転で太陽の位置が変わるともしかしたら発電するかもということで、発電開始時のサーキュレーション？を避けるためにいったんSLIMをスリープ状態で待機させたところ、太陽が太陽電池パネルに対向するようになった時点で発電開始、結局ミッションの大半は実行できたというように解釈しています。

# 「フルサクセス」っぽい感じ
これは結局、「サクセスクライテリア」に照らし合わせると、「予定していた要求を満たし、計画通りの成果を得ること。」に該当するような気がします。そのような訂正の会見や発表があったかは未確認。

# 「フルサクセス」祈願
今回の快挙ははやぶさ2の帰還成功以来で、昨年のH3ロケット初号機の打ち上げ失敗の暗雲をいっきに払しょくしてくれたように思えます。そして、わたしは次の「フルサクセス」を祈願したい。

次の「フルサクセス」祈願とは、もちろん明日(2024/02/17)のH3ロケット2号機の打ち上げ成功です。
【初心者】言語の理解のプロセス

プログラミングができるようになるということは、言語が習得できているということ。
では、言語を習得できには、言語の理解が必要。
では、理解したといえるまでにはどのようなプロセスが在るのか。

①反復（わからなくても反復）
②単語の暗記（わからなくても暗記）
ーーーーーーーーーー
②から③ってめっちゃ格差あるから、もっと細かい階段つくりたい。
ーーーーーーーーーー
③単語のイメージ（単語の裏にイメージや動きがつく）
ーーーーーーーーーー
③と④の間も格差すごいから細かい階段を作ろう。あとで。
ーーーーーーーーーー
④単語と単語が繋がって文章が読める（概念が受け取れるようになる）
⑤言語が理解できたって感じがしてくる。（一段階これが理解。）
tfsecからTrivyに移行したときの設定

HCLをGitにコミットする前に、pre-commitでtfsecを動かして静的解析を行っていましたが、tfsecの開発が終了？したのでTrivyに移行することにしました。その時の設定内容について記述します。

↓参考記事

https://zenn.dev/acntechjp/articles/9f0e3d4813e36d

# 環境
## ツール
- Azure DevOps
    - Repos(Git)
    - Pipelines
- WSL Ubuntu22.04LST
- trivy

```bash
# WSLにHomebrewを入れているので、インストールはHomebrewで行いました。
brew install trivy
```

- pre-commit

https://pre-commit.com/

- pre-commit-terraform

https://github.com/antonbabenko/pre-commit-terraform

## tfsecを動かしていたタイミング
1. コミットする直前のpre-commit内
1. Azure DevOpsのプルリクエストでマージする直前のPipelines内

## pre-commit
pre-commitを使う場合、プロジェクトのルートに`.pre-commit-config.yaml`を作成していると思うので、tfsecをtrivyに書き換えます。--ignorefileフラグは除外するルールが記述されたファイル、--configフラグはtrivyコマンドのオプションなどが記述されたファイルです。
`trivy.yaml`には.terraform以下を対象外にするようにしています。

https://github.com/antonbabenko/pre-commit-terraform?tab=readme-ov-file#terraform_trivy

```yaml:.pre-commit-config.yaml
- id: terraform_trivy
  args:
    - >
      --args=--ignorefile=__GIT_WORKING_DIR__.trivyignore
      --config=__GIT_WORKING_DIR__trivy.yaml
```

```plaintext:.trivyignore
# パスワード長は社内ルールに準拠しているため除外します。
AVD-AWS-0063
# こめんと
AVD-AWS-0026
```

```yaml:trivy.yaml
scan:
  skip-files:
    - "**/.terraform/**/*"
```

## Azure Pipelines
まず、Azure DevOpsでTrivyエクステンションをインストールします。

https://www.softbanktech.co.jp/special/blog/cloud_blog/2023/0025/

`azure-pipelines.yml`のtfsecだったところをtrivyに置き換えます。

```yaml:azure-pipelines.yml
- task: trivy@1
  displayName: "Trivy"
  inputs:
    path: .
    options: --ignorefile ./.trivyignore --config ./trivy.yaml
```

Trivyエクステンションで使えるパラメータは以下を参照

https://github.com/aquasecurity/trivy-azure-pipelines-task/blob/main/marketplace.md

## インラインルール除外
tfsecと同じ要領です。

```
#trivy:ignore:AVD-AWS-0124
```

以上です。
Next.jsの「Server Components」、「Client Components」の違いを整理する(その①) - 概要理解

## はじめに
Next.jsは、v12まで業務で使用経験はあるが、以降のversionは、ざっくり触っている状態で、なんとなく`app router`を使う程度の知識しか持っていない。
このなんとなくを解消するために、`Server Components`、`Client Components`に関して知識を深めていく。

尚、参考にしたサイトは以下です。

https://zenn.dev/hamo/articles/31133919b987b9

https://dev-harry-next.com/frontend/nextjs-13-app-router-detail

https://blog.stackademic.com/understanding-client-and-server-components-in-next-js-13-6971ac4e920d

## `Client Components`と`Server Components`の違い

### `Client Components`とは

`Webブラウザ`が、JavaScriptの実行、HTML、CSSの組み立てを行い、レンダリングされるコンポーネント。
このレンダリングプロセスは、クライアントサイドレンダリング(CSR)と呼ばれる。

### `Server Components`とは

`サーバ`が、JavaScriptの実行、HTML、CSSの組み立てを行い、レンダリングされるコンポーネント。
このレンダリングプロセスは、サーバーサイドレンダリング(SSR)と呼ばれる。

### アプリケーションへの影響

| 項目 | Client | Server |
| :--: | :--: | :--: |
| バンドルサイズ | 大きくなりがち<br>(圧縮されたHTML、CSS、JavaScript) | 小さめ<br>(組み立てられたHTML) |
| デバイスリソース | 食いがち | 影響が少ない |
| SEO | 検索エンジンがコンテンツのインデックスを効果的に作成しない可能性あり | 検索エンジンが HTML コンテンツをクロールしてインデックスを作成 |
| セキュリティ | 機密情報漏洩リスク | サーバで機密情報を扱うため、安全 |

### コーディングへの影響

| 項目 | Client | Server |
| :--: | :--: | :--: |
| HTMLイベントハンドラ | できる | できない |
| React hooks | 使える | 使えない |
| React class component | 使える | 使えない |
| ブラウザAPI | 使える | 使えない |

## まとめ

`Server Components`を利用することで、アプリケーションに多くのメリットをもたらすことができる。ただし、コーディングを行う上で、いくつかできないことがある。(私自身、`React hooks`はガンガン使っていたので、`Server Components`での実装が正直苦痛...)
どうしても`Client Components`でないとだめだ！という場合を除き、`Server Components`を使う方針でコーディングしていこうと考えている。

## 次回以降

ざっくりと両者の違いを説明した程度のため、`アプリケーションへの影響`、`コーディングへの影響`を基本として、実際に試して確認していこうと思う。
lombokで生成されるはずのメソッドと同名のメソッドを定義するとどうなるか

## lombokで生成されるゲッター、セッターと同名のメソッドを書くと、lombokで生成対象にならない

```java
import lombok.Getter;
import lombok.Setter;

@Setter
@Getter
public class SampleDto {

    private String sampleA;

    public String getSampleA() {
        System.out.println("lombokでない方のゲッター");
        return sampleA;
    }
}
```

```java
public void confirmLombok(){
    SampleDto dto = new SampleDto(){{setSampleA("AAA");}};
    System.out.println(dto.getSampleA());
}
```

```:実行結果
lombokでない方のゲッター
AAA
```
Lombokを使用している場合に、実際に生成されるコードを確認したい場合は、delombokを使う。

```
java -jar lombok.jar delombok -f pretty {delombok対象のディレクトリのパス} -d {出力先のディレクトリのパス}
```

結果を確認すると以下。
```java
public class SampleDto {
    private String sampleA;

    public String getSampleA() {
        System.out.println("lombokでない方のゲッター");
        return sampleA;
    }

    public void setSampleA(final String sampleA) {
        this.sampleA = sampleA;
    }
}

```
lombokでのメソッド生成の対象外になることがわかった。

もちろん、こんな実装をしてはいけません。
（が、過去、遭遇しました。どういうことやねん）
iOS17.2からAVCaptureEventInteractionで音量ボタン撮影が可能に

# 前書き
今まで非公開の通知を利用したり、音量を監視して行っていた音量ボタンでの写真撮影ですが、iOS17.2からついにこのためのAPI「**AVCaptureEventInteraction**」が追加されました！
[AVCaptureEventInteraction](https://developer.apple.com/documentation/avkit/avcaptureeventinteraction)
今の所、日本語で書かれた情報が無かったので備忘録も兼ねて公開します。
始めて技術系の記事を書くので、至らない点もあるかと思いますがよろしくお願いします。
# 実装
実装方法ですが、公式のドキュメントに書いてある通り下記の記述で簡単に実装出来ます。
ただし**AVCapture**の名前がついている通り、このAPIはUIImagePickerControllerのカメラやAVFoundationで制作したカスタムカメラの画面でのみ利用できます。
それ以外の画面ではAVCaptureEventInteractionはイベントを受信しません。
```swift:公式ドキュメントより抜粋
// Create a new capture event interaction with a handler that captures a photo.
let interaction = AVCaptureEventInteraction { [weak self] event in
    // Capture a photo on "press up" of a hardware button.
    if event.phase == .ended {
        self?.camera.capturePhoto()
    }
}
// Add the interaction to the view controller's view.
view.addInteraction(interaction)
eventInteraction = interaction
```
**event.phase** にはキャプチャ イベントの現在のフェーズが格納されます。
| phase |概要 | 
|:-----------:|:------------:|
| began | 音量ボタンを押した時のフェーズ |
| ended | 音量ボタンを離した時のフェーズ |
| cancelled | キャンセルした時のフェーズ |

このphaseにあわせて撮影の処理を記述していきます。例えば、音量ボタンを一度押すと撮影が一回実行されるようにしたい場合は **「ended」** のタイミングで処理を実行したり、連写を実装したい場合は **「began」** のタイミングで連写処理の開始を実装して **「ended」** で連写を終了する、といった感じでしょうか。
一時的にこの処理を止めたい場合は **isEnabled** をfalseに、完全に削除したい場合はviewから**removeInteraction** します。
# 余談
ちなみに、このAPIが実装されたせいかiOS17.2から **_UIApplicationVolumeUpButtonDownNotification** といった非公開の音量ボタン通知は利用できなくなりました。
あんまり居ないかもしれませんが、もしも利用されている場合はiOS17.2以降はAVCaptureEventInteractionで処理するように修正することをオススメします。
# 後書き
iOS17.2以上とは言え、これで非公開のAPIをリジェクトの恐怖に怯えながら利用したり、outputVolumeを監視する必要も無くなりますね…実装も簡単ですし、カメラアプリ制作者にはとても助かるAPIです。
これからカメラアプリ制作する予定で音量ボタンをシャッターボタンにしたい方は、こちらのAPIを利用した方が絶対に良いです。outputVolumeを監視する手法と違って音量も変化しないですし。
Ubuntu22.04にVScodeをインストールし、起動する

<h3>1. VSCodeをインストール</h3> 

VSCodeのインストールは<a href="https://code.visualstudio.com/download">ここ</a>から

Ubuntu22.04にインストールするので拡張子が.debのファイルを選択しました。
任意のフォルダに配置します。

<h3>2. バージョン確認</h3>

このコマンドを実行し、バージョンが表示されたらインストール成功しています。
```
node -v
```

<h3>3. debファイルを展開する</h3>

```
sudo dpkg -i code_1.93.1-1726079302_amd64.deb
```

メッセージが表示されたらyを押下。下の画像は展開に成功したところです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3706432/103290d6-bd6f-8264-3fcc-cdde087a81d1.png)

<h3>4. VSCodeを起動</h3>

```
code
```
と入力すると起動できます♪


<h4>5. ~うまく起動しない場合~ .bashrcにPATHを追加</h3>

```
vi ~/.bashrc

# 最下部に次の行を追加
export PATH=$PATH:/debファイルの展開先フォルダ/visual-studio-code/bin

# 設定を反映
source ~/.bashrc

# もう一度codeを実行

```

【おせわになったサイト】
https://inakademac.com/react-hello-world/
OST ファイルの内容にアクセスするにはどうすればよいですか?

<p>OST ファイルのコンテンツにアクセスする場合。 次に、このページを読んで手順とOST to PST Converterに関する正確な情報を入手し、操作を問題なく完了する必要があります。</p>

<p>Microsoft Outlook は、世界中で最も強力で人気のある電子メール プログラムです。 会話のために電子メールを送受信できます。 メールボックス ファイルは OST および Outlook の通常の PST 形式で保存されます。</p>

<p>OST は、メールボックス データ全体をローカル デバイス上に保持するオフライン ストレージ テーブルです。 これにより、メールボックス データをローカル ディスクに保存できます。 Exchange または IMAP アカウントを Outlook に追加すると、ローカル ディスク上にすぐにセットアップされます。</p>

<p style="text-align:center"><a href="https://www.mailvita.com/dl/osttopst.dmg"><strong>ダウンロード中</strong></a></p>

<h2>OST ファイルのコンテンツにアクセスする理由。</h2>

<ol>
	<li>ユーザーは、あるマシンから別のマシンに転送したい場合があります。</li>
	<li>ユーザーは孤立した OST ファイルを表示できます。</li>
	<li>ユーザーは顧客から OST ファイルを取得し、それを個人の Outlook プロファイルで表示したい場合があります。</li>
</ol>

<h3>OST ファイルの内容に手動でアクセスするにはどうすればよいですか?</h3>

<p>Outlook プロファイルを所有しており、アクティブな Outlook OST ファイルがある場合。 次に、以下に示すように、Outlook のインポート/エクスポート ツールを利用してプロセスを完了できます。</p>

<ol>
	<li>Outlook を開き、左上のメニューにあるファイルに移動します。</li>
	<li>その後、「開いてエクスポート」をタッチし、「インポート/エクスポート」をタッチします。</li>
	<li>リストから「ファイルにエクスポート」を選択し、「次へ」をクリックして開始します。</li>
	<li>その後、Outlook PST ファイルを選択し、「次へ」をクリックして続行します。</li>
	<li>エクスポートするメールボックス データを選択します。</li>
	<li>出力パスを設定し、完了をクリックすると、結果がすぐに得られます。</li>
</ol>

<h3>手動ソリューションの使用の制限</h3>

<ul>
	<li>手続きには時間がかかり、長くなります。</li>
	<li>孤立した、破損した、または大きすぎる OST ファイルは復元できません。</li>
	<li>この方法には、ユーザーの技術的な専門知識が必要です。</li>
</ul>

<h3>自動化されたソリューションを使用して OST ファイルのコンテンツにアクセスするにはどうすればよいですか?</h3>

<p>手動による解決策にはいくつかの危険と制限があります。 したがって、情報を失うことなく正確な出力を保証する優れたプログラミングで構築された <strong>Mailvita <a href="https://www.mailvita.com/ost-to-pst-converter-for-mac/">OSTからPSTへの変換ツール</a></strong> を使用することをお勧めします。</p>

<ul>
	<li>ダウンロードしたウィザードをマシン上で実行します。</li>
	<li>変換したいOSTファイルを選択し、「参照」ボタンをクリックします。</li>
	<li>OST ファイル内のすべての項目をプレビューし、空のフォルダーは無視します。</li>
	<li>変換された PST ファイルを保存するには、保存先を選択し、「参照」ボタンをクリックします。</li>
	<li>「今すぐ生成」ボタンを選択します。</li>
</ul>

<p><img alt="" src="https://www.mailvita.com/img/scr/ost-to-pst/convert-ost-to-pst.webp" /></p>

<h3>自動化ソリューションを使用する利点</h3>

<ul>
	<li>メールボックスのデータは切り替え中も変更されませんでした。 さらに、PST ファイル コンバーターは、元のファイルの変更を防ぐ強力な保護を提供します。</li>
	<li>このウィザードは、すべての企業および専門ユーザーが簡単に使用できます。</li>
	<li>孤立した、破損した、アクセスできない OST ファイルを復元して変換します。</li>
	<li>このユーティリティを使用すると、指定されたメールボックス データの変換が可能になり、無関係なデータがスキップされます。</li>
	<li>すべての Mac および Win オペレーティング システムのバージョンと互換性があります。</li>
	<li>OST は Outlook に簡単にインポートできます。</li>
</ul>

<h3>結論</h3>

<p>この投稿では、OST ファイルのコンテンツにアクセスする方法について説明します。 手動による解決策にはいくつかの制限があります。 そのため、制約なく手順を完了するには、自動化されたソリューションを選択することをお勧めします。</p>
【SwiftUI】TextFieldで数値を扱う

# はじめに
TextFieldで数字を扱いたいときに、数字を文字列に変換して、
使うとき数値に戻すといった面倒なことをしてる人いますよね
私もそれやってました。

iOS15からTextFiledで直接数値を扱えるようになったらしいんです。
気づきませんでした。

# サンプルアプリ
![Simulator Screen Recording - iPhone 15 Pro - 2024-02-16 at 21.53.21.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/61daee68-965a-ca10-1004-1cc681b78174.gif)

# 実装
```swift
import SwiftUI

struct ContentView: View {
    @State var value: Decimal.FormatStyle.FormatInput = 0.0
    @State var int: Int = 0
    @State var double: Double = 0.0
    @State var float: Float = 0.0
    
    var body: some View {
        VStack {
            GroupBox("NSDecimal") {
                Text(value.description)
                
                TextField("", value: $value, format: .number)
                    .textFieldStyle(.roundedBorder)
            }
            
            GroupBox("Int") {
                Text(int.description)
                
                TextField("Int", value: $int, format: .number)
                    .textFieldStyle(.roundedBorder)
            }
            
            GroupBox("Double") {
                Text(double.description)
                
                TextField("Double", value: $double, format: .number)
                    .textFieldStyle(.roundedBorder)
            }
            
            GroupBox("Float") {
                Text(float.description)
                
                TextField("Float", value: $float, format: .number)
                    .textFieldStyle(.roundedBorder)
            }
        }
        // ここでキーボードを数字のみにしている
        .keyboardType(.decimalPad)
        .padding(20)
    }
}
```

# 数字ではないものも入力できる
`.keyboardType(.decimalPad)`の指定をなくせば、数字以外も入力できるようになります。
しかし、@Stateに流れてくる値は数値です。
不要な文字列があるとその前までの、正常な部分までが@Stateに流れてくる仕様っぽいです。
有能すぎますね。

![Simulator Screen Recording - iPhone 15 Pro - 2024-02-16 at 21.58.33.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/38a9c1b6-38f1-bc0b-7266-26609c5fb48d.gif)

# おわり
こんな機能がiOS15で登場してたなんて、、、

# 公式ドキュメント
https://developer.apple.com/documentation/swiftui/textfield/init(_:value:format:prompt:)-6ug7k
Vimを覚える【VIMATE 初級】

# はじめに

単純に使えるとかっこいい、「Vim」を使いたい！

まずは覚え方を考えて、あとは [VIMATE](https://vimate.jp/lessons/vim-01) で手を動かしまくって覚えます。
<br>

覚え方はギリギリまで論理で頑張りつつ、無理なところはごり押します。

今回は「VIMATE初級編」のコマンド

# 覚え方

## 移動系
| コマンド | 機能 | 覚え方 |
| ---- | ---- | ---- |
| `h` `j` `k` `l` | カーソル移動 | タイピングのホームポジション`j`を基準に、<br>左右：`h` `l`<br>上下：`j` `k` |
| `0`  | 行頭（空白文字を含む） | `0`文字目 |
| `^` `$` | 行頭・行末<br>（非空白文字） | 正規表現の行頭`^` / 行末`$` |
| `gg` / `G` | 文書の頭・末<br>（非空白文字） | 「gogo」と「Go」かな・・・ |
| `w` `W` | 次の単語の先頭 | `w` wordの先頭まで移動<br>`W` は空白文字のみ区切りと判定する |
| `e` `E` | 次の単語の末尾 | `e` endまで移動 |
| `b` `B` | 直前の単語の先頭 | `b` back |
| `/` `?` `n` `N` | 検索と移動 | `/` はカーソルより下を検索（暗記）<br>`?` はカーソルより上を検索（`/`の`shift`）<br>`n` next 検索の繰り返し<br>`N` 逆順で繰り返し |
## コピペ・削除系
| コマンド | 機能 | 覚え方 |
| ---- | ---- | ---- |
| `x` `X` | １文字削除 | `x` バツ。消す。<br>`X` カーソルの前の１文字を消す |
| `dd` | 一行削除 | delete delete（削除なので２回）<br>普段なら`ctrl + x`でやるもの。 |
| `yy` | 一行コピー | vimでは「コピー」を`yank`と呼ぶ<br>`yank`：引っ張り出す（バッファに引っ張り出す） |
| `r` | 置換 | replace |
| `p` `P` | ペースト | paste<br>大文字小文字は、いつも通りカーソル前後 |
| `v` `V` | ビジュアルモード<br>（カーソル選択） | visual mode |
| `a` `A` `i` `I` | 挿入 | `i` カーソル前に 「insert（挿入）」<br>`a` カーソル後に「append（追加）」<br>`A` `I` はそれぞれ、「行」単位 |
| `o` `O` | 行を追加し挿入 | open in a new line<br>小文字：下<br>大文字：上 |
| `u` | 操作取り消し | undo |
| `:w` | 保存 | write 書き込む |
| `:help` | ヘルプ | そのまま |
| `:q` | （変更がなければ）<br>ファイルを閉じる |  quit|
| `:wq` | 保存して閉じる | 応用 |
| `:q!` | 変更を破棄して閉じる | `!`は「強制的」 |
## +α メモ

VIMATEでは直接触れないものなど

- `w`操作の対は`b`操作
- 「置換」「挿入」は、コマンド実行後改めて対象の文を入力。
「ペースト」は、`yank`した文を貼り付け
という違いがある。
- `:w ファイル名`で「新しい名前で保存」
- `ctrl + v`で「ビジュアルブロックモード」：矩形の選択範囲
- `g`単体コマンドはない。go = 移動 の意味を持つことも多いが、かならずしもそうではない。
ReactNative + Expoを用いた環境構築

## はじめに
本記事はReactNativeでアプリ開発をしてみたい方に向けた記事となります。

## ReactNativeとは
React Nativeとは、Meta社(旧Facebook)が開発したクロスプラットフォームのアプリ開発用フレームワークです。   
クロスプラットフォームとは、異なるプラットフォーム上で同じ仕様のものを動かすことが出来るプログラムのことです。  
社内でアプリ開発する際に使われているFlutterと同様、React Nativeも、iOSとAndroid端末それぞれのアプリを一つのコードで同時に制作することができます。  
JavaScript用ライブラリ「React」とほぼ同じ原理でネイティブアプリを開発することができるため、Reactが使える人は学習コストが低くすみます。  

## Expoとは
ReactNativeの開発ツールには2種類あり１つはReactNative CLI、そしてもう１つがExpoになります。    
Expoを利用することで、アプリのビルドやリリースに必要な設定が自動化されるため、モバイルアプリ開発の専門的な知識がなくてもアプリを開発できるようになるのが最も大きなメリットであり、特徴です。  
ざっくりとモバイルアプリ開発に必要な細かい設定などを担い、自動化してくれるツールだと思っていただけたら大丈夫です。
# 環境構築
## 前提条件
* Node.jsがインストールされている  
	インストールしていない方は[こちら](https://www.sejuku.net/blog/72545)を参考に

## Expoのインストール
1. 下記のコマンドを実行して、npmを最新化する  
```
sudo npm install -g npm@latest
```

2. expo-cliをインストールする
```
sudo npm install --global expo-cli
```

3. expoがインストールされているか確認
``` 
expo -V
```

## Xcodeのインストール

https://apps.apple.com/jp/app/xcode/id497799835?mt=12

## Android Studioのインストール

https://developer.android.com/studio?hl=ja

# プロジェクトの作成
## 以下コマンドを実行
```
npx create-expo-app my-app
```
(my-appの部分はお好きなプロジェクト名に変更してください)  

## プロジェクトのディレクトリに移動
```
cd my-app
```
## 開発サーバーを起動
```
npx expo start
```

## 参考URL  
https://docs.expo.dev/get-started/create-a-project/

# 最後に
まだまだ自分自身アプリ開発は全然できていない状況なので新たに得た知識などは少しづつ公開できたらなと思っています。  
最後までご覧いただきありがとうございました。
【はじめてのJava Silver】試験概要や申込方法について解説

はじめに
Softbankのテックブログで記事を書いたので紹介します！

![JavaSilverサムネイル.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2980561/33684a88-ca9e-7e64-55f5-3a93abb199fd.png)


本記事では私が2023年5月に取得したJava Silver（Oracle Certified Java Programmer, Silver SE 11 ）の試験概要と申込方法について紹介しました！
特にJava Silverは申込方法が複雑で、資格の認定機関であるOracle・資格情報を管理するCertview・試験を主催しているピアソンVUEといった３つのサイトを経由して申し込むというわかりにくい構図になっているので、丁寧に解説しました！!


### この記事について
- この記事では、Java Silverの試験概要と申込方法を中心に解説しています！
- 申込方法が複雑で困っている方には特におすすめの記事です！

ぜひ読んでみてください！！

https://www.softbank.jp/biz/blog/cloud-technology/articles/202402/java-silver/
最近リリースしたゲームについてまとめる（共同開発）

# はじめに
こんにちは！Thetaです。

去年の4月からプログラミングとUnityを始め、やっとゲームをネットの海にリリース出来たのでここにまとめます。
ゲームを作った背景や処理の説明を少しするぐらいなので、コードについての説明は他の記事で書こうと思っています。



## ８スクエアパズル

https://unityroom.com/games/8squarepuzzle


<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680216/fa17dab3-5ff1-ccde-2736-5900aa7b09ca.png">
<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680216/6df65483-b358-a04d-6be3-fca4f7fd2582.png">

### 説明
オマージュ元である「6ボールパズル」をイメージしていただくのがよいかと思われます。6ボールパズルは6つ同色のボールを繋げて消していくというゲームなのですが、6を8に、ボールをスクエア（四角形）に作り替えた形です。

すなわち同じ色のブロックを上下左右4方向に連結させて、8つ繋がったらブロックが消えて得点が得られるというゲームになります。円状・棒状に連結させると同じ色のブロックが全部消えるので、いかに落ちてくるブロックの落下場所を考えて繋げていくかが最大の肝になります。


### 背景
友人と共同開発したのですが、本来は「6ボールパズル」の完全再現のためのプロジェクトを立ち上げ開発がスタートしました。

私が判定処理や見た目部分の実装を担い、友人が落下処理諸々を実装したのですが、お互い共同開発が初めてで、停滞した時期もありました。

とりあえず共同開発した「６ボールパズル」のクオリティについては次回にでもまとめるとして、

**コードを流用できてリリースしても権利的に大丈夫なように私が作り替えたもの**

が、この8スクエアパズルになります。

かなり難しい仕様になってしまったと思いますが、ランキング機能を搭載すると意外にも多くの方々に遊んでいただき、何度もプレイしてとんでもない点数を獲得している方もいらっしゃいます。うれしいですね～( ´∀｀ )

## NEO NINJA SURVIVER(仮)

https://unityroom.com/games/neoninjasurviver



<img width = "80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680216/a4bf9337-d582-f8ff-f0ba-d7a6743aab25.png">
<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3680216/c5a704a8-359b-4a86-511e-c4febfc67e53.png">

### 説明
「Vampire Surviver」と「dandara」を組み合わせたようなゲームです。壁を飛び回り敵やミサイルから逃げたり、敵を倒して経験値を獲得しパワーアップして4分間生き残ればゴールです。

こちらも８スクエアパズルと同様、友人と共同開発しました。エネミーの追尾やキャラクター・UIのデザインに関しては僕が行い、プレイヤーの挙動をその友人が実装してくれました。

去年の年末（2023年12月）に開催された、Unity1weekというゲームジャムに参加する目的で制作をスタートさせたのですが、これがまぁ終始前途多難って感じで、全然間に合いませんでした。1weekでゲームを作るっていうお題がいかに厳しいかを思い知り、良い経験になりましたね。
※（仮）とついているのは、まだ試作版でスコアランキングやゲームバランス調整などの点で完成度が低いからです。

### 背景

Unity1weekにアップしたい！！！！っていう気持ちのまま見切り発車でプロジェクトが始動。結果的に全然間に合いませんでしたがクリスマスはずっとUnity漬けでした。

友人との齟齬を最低限にする作業を怠ったため、開発現場は終始ピリピリしてたような気がします。1週間という限られた時間でゲームを作ることの難しさとを知りました・・・。

月日は経ち、2月上旬。ローカルでずっと眠り続けていたこのゲームをひとまずは完成させようと、一人で黙々と作業を開始しました。BGMやSEを選定している時間はかなり楽しかったです。

# 感想
理想を言えば共同開発は、開発者だけでなく**進捗状況やタスク管理などを俯瞰して見てくれる役職**が必要だと思いました。仲介役であり、共有事項を明確にしてくれる人がいるだけで停滞の可能性は下がると考えます。

また、特にゲームジャムのような期限を求められるイベントに参加する際は、メンバーのこだわりの中で**捨てられる点、捨てられない点**を決めることが大事だと思います。僕が共同開発時に感じた齟齬も、それらを怠った結果生まれたような気がします。

しかし、これらのような経験をふまえても、共同開発は楽しかったです。まぁ仕事じゃないので、学生気分を存分に味わいながらゲームの構想を語り合ってる時間は一生モノの思い出になりました。今後ゲームジャムがあったとして共同開発するかどうかは未定ですが、ゲームを作ることの楽しさがより一層感じられた良い機会でした。

最後に、ここまで読んでくださった方に感謝します。これからも素敵なゲームエンジニア目指してゲーム作っていくので、ゲーム遊んでいただけたら幸いです。
プロンプトメモ



||プロンプト|
|-|-|
|Posi|1woman, solo, (from front), (((cowboy shot))) , (cute eyes) ,(wearing), white background|
|Posi|(masterpiece, top quality, top quality), (super detailed, absolute resolution), ((16k, high resolution)),<lora:koe_no_katachi_offset:0.7>, <lora:flat2:0.1>,1woman, solo, (from front), (((cowboy shot))) , (cute eyes) ,(wearing), sexy lady, beautiful, smile, wearing white T-shirt, black gaucho pants, black long hair, breast, (big breasts:1)|
|手を後ろ|arms behind back|
|白背景|white background|
|直立|cowboy shot|

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1573902/adf10fb5-d470-f837-ea5d-a203321f7fe5.png)
【Godot, C#】 ノードのインスタンス作成をコード側から行う

# 概要

[Godot](https://godotengine.org/) の C# スクリプトに関する話題です。

C# コードで独自に定義したノードのインスタンスを作成するには ↓ のようにする必要があります。

Godot のバージョン: 4.1.2  
.NET のバージョン: 8.0.2

```cs
PackedScene scene = GD.Load<PackedScene>("res://MyNode.tscn");
MyNode node = scene.Instantiate<MyNode>();

// ↑　は _Ready() まで呼ばれた状態でインスタンスを取得

// 普通に new する方法はうまくいかない
// MyNode node = new MyNode();
```

## 文字列リテラルの引数を消したい

上記の方法の問題点として、文字列リテラルがコードに現れてしまいます。  
文字列リテラルは書き間違いに気づきにくい点、クラス名の変更やファイルの場所の移動などリファクタリングの妨げになる点で避けたいところです。  
これは、コンパイル時に Godot 側が独自に定義したノードに自動で付与する属性 `ScriptPathAttribute` を活用して解決できます。

NodeLoader.cs

```cs
using Godot;
using System.Reflection;

/// <summary>
/// 新しいノードインスタンスを作成するクラス
/// </summary>
/// <typeparam name="TNode"></typeparam>
internal static class NodeLoader<TNode> where TNode : class
{
    private static PackedScene? _scene;
    /// <summary>
    /// 新しいノードのファクトリを取得<br/>
    /// 対象のノード定義ファイル（"*.tscn"）が存在しない場合は例外
    /// </summary>
    /// <exception cref="InvalidOperationException"></exception>
    internal static PackedScene Scene
    {
        get
        {
            if (_scene is null)
            {
                // NOTE:
                // ユーザー定義のノードには、スクリプトファイルのパス属性 ScriptPathAttribute が Godot により自動で付与されます
                // 例）[ScriptPath("res://MyNode.cs")] class MyNode
                // この属性を利用してノード定義ファイルを読み込みます
                var scriptCodePath = typeof(TNode).GetCustomAttribute<ScriptPathAttribute>()?.Path;
                if (scriptCodePath is null)
                    throw new InvalidOperationException($"ノード定義ファイルが見つかりません: {typeof(TNode).Name}");

                _scene = GD.Load<PackedScene>(scriptCodePath.Substring(0, scriptCodePath.Length - 3) + ".tscn");
            }

            return _scene;
        }
    }

    /// <summary>
    /// 新しいノードインスタンスを作成<br/>
    /// 対象のノード定義ファイル（"*.tscn"）が存在しない場合は例外
    /// </summary>
    /// <param name="path"></param>
    /// <returns></returns>
    /// <exception cref="InvalidOperationException"></exception>
    internal static TNode New() => Scene.Instantiate<TNode>();
}
```

</details>

使い方

```cs
partial class MyNode : Node;

MyNode node = NodeLoader<MyNode>.New();
```