OmniAICreator/Qiita-1.07M huggingface dataset:
GitHubのリモートリポジトリにpushできない

## はじめに
GitHubのリモートリポジトリにローカルリポジトリを `push` しようとした際にエラーが発生しました。
原因と解決方法を整理しておきます。

## 手順
今回の作業の流れは以下の通りです。

#### ① ローカルでプロジェクトを作成
#### ② GitHubでリモートリポジトリを作成
#### ③ ローカルリポジトリをGitHubのリモートリポジトリに `push`


## エラー内容
③の `git push` 実行時に以下のエラーが発生しました。

```zsh
username@/path/to/your/project % git push -u origin main
To https://github.com/{username}/{new_repo}
 ! [rejected]        main -> main (fetch first)
error: failed to push some refs to 'https://github.com/{username}/{new_repo}'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

```

#### 原因

リモートリポジトリにはすでに何らかのコミットが存在しており、ローカルの main ブランチと同期が取れていなかったために発生しました。

## 解決方法

#### 1. リモートリポジトリの内容をローカルリポジトリへ取り込む

まず、リモートの変更をローカルに反映し、競合（conflict）を解決してから `push` する方法です。
```zsh
git pull origin main --rebase
```

このコマンドを実行すると、リモートの変更をローカルに適用しつつ、ローカルの変更を後ろに並べ直します。
もし競合（conflict）が発生した場合は、手動で修正して `git add .` した後、以下のコマンドを実行してください。

```zsh
git rebase --continue
```

リベースが完了したら、改めて `push` します。

```zsh
git push -u origin main
```

---
#### 2. リモートリポジトリの履歴を強制的に上書く

リモートの main ブランチを完全に上書きしたい場合は、強制 `push` を行います。

:::note warn
この操作を実行すると、リモートの履歴が失われる可能性があります。
:::

今回は、まだリモートリポジトリに `push` していない個人用プロジェクトだったため、この方法を使用しました。

```zsh
git push -u origin main --force
```
## 最後に
久しぶりに git push しようとしたら、意外と忘れていることも多く良い復習になりました。
特に、リモートリポジトリの状態をしっかり確認してから push する習慣をつけたいと思います。

## 参考サイト

https://qiita.com/kaede25/items/1af6b2d729d24a1108cc
unityでアイテムをプカプカ浮遊させる方法

## 参考動画

![無題の動画 ‐ Clipchampで作成 (1) (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/736e9ad8-ff6d-4882-9670-e125a12bce84.gif)
## コード
```c#
    transform.Rotate(Vector3.up,rotation_speed*Time.deltaTime);//回転
        
    float updown = startposition.y + Mathf.Sin(Time.time * updown_speed) * 0.5f;//上下の動き
        
    transform.position=new Vector3(transform.position.x,updown , transform.position.z);
```

startposition.yはオブジェクトの開始地点のy座標を表している


## Sin関数の動き

例えば、Mathf.Sin(Time.time)を実行したとき**1から-1**の間を繰り返す動きになる



![スクリーンショット 2025-03-02 181503.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3836524/f42e58ac-89b3-4e4a-9aec-f7e082dcf1d6.png)

sin関数を使うことで波のような動きになるので滑らかな動きを再現できる

## sin関数の制御

```c#
Mathf.Sin(Time.time * updown_speed) * 0.5f
```

```updown_speed```は上下の動作速度を表している

0.5fをかけることで可動域を**0.5から-0.5**に可動域を設定できる


## まとめ

アニメーションのように滑らかな動きを作りたいときに使える!
Emacs × Vim = Evil！　人生を豊かにするエディタ環境を構築

Emacsは、Emacs Lispという言語を使って、「自由」を軸にあらゆる想像的活動のための環境して発展してきました。しかし、「ファイルを編集する」という操作に関しては、現代において、vi/Vim が非常に優秀なインターフェースであることも事実です。この2つのエディタは多くのファンを抱え、宗教戦争と言われるほどまで発展しました。長らく、「どちらが良いか」という話を繰り返してきましたが、その中で共和を唱える人が出てきました。それが今回紹介する Evil です。


# Evil とは

Evil という名は、"Extensible VI Layer"からきています。Emacs の自由な環境で、Vim の優秀なインタフェースを提供してみようというものです。

元々、「Emacs上でVi操作したい」という思想は昔からありました。それを元に、色々改修していき、結果的に生まれたのが Evil になります。


# Evilの導入方法

Evilは、MELPA や NonGNU ELPA などからのパッケージで使うことができます。今回は [MELPA](https://melpa.org/#/evil) 上での導入方法を解説します。

まず、M-x コマンドを使って、evil を導入していきます。

```shell
M-x package-install RET evil RET
```

導入ができたら、init.el 上で以下のコードを追加します。

```emacs-lisp:init.el
(use-package evil
:ensure t
:config
(evil-mode t))
```

Emacs を再起動して、ステートに `<N>` と出たら成功です。

https://github.com/KaitoMuraoka/.emacs.d/pull/35


# 操作方法

基本的な操作方法は、Vimと同じです。ステートが<N> の時はVimの Normal モードと同様の動きをします。他にも、

-   <I>: Vim の Insert モードと同様の動き
-   <V>: Vim の Visual モードと同様の動き

をします。また、<E> は Emacs ステートと呼び、Emacs の標準キーバインドで操作することが可能です。

しかし、一部、Emacsの機能を生かせるために、設定でONにする必要がある箇所があります。例えば、C-u はVimではNormalモードで「画面半分上に移動する」という操作を行いますが、Emacsではプレフィックス引数を動作させるキーでもあります。そのため、Emacsの機能を生かすために、デフォルトではOFFになっています。しかし、設定でONにすることができます。以下のように編集することで、C-uをVimと同じ操作にすることができます。

```emacs-lisp:init.el
  (use-package evil
  :ensure t
  :custom 
+  (evil-want-C-u-scroll t)
  :config
  (evil-mode t))
```

https://github.com/KaitoMuraoka/.emacs.d/commit/b3a05afacb74ecd58d03795fba26789645d052bf

他にも、必要な設定はたくさんあるので、以下を参考にすると良いでしょう。

https://evil.readthedocs.io/en/latest/settings.html


## 一部のファイルをEmacsモードにする

私は、プログラミングする際にはVimモードで行いますが、テキストやMarkdownなどの自然言語を扱う場合はEmacsの操作を好みます。絵画では絵筆を、手紙は万年筆を使うようなイメージです。

そのため、ここでは、Markdown, Org-mode, Text-mode の場合は Emacs ステートにする処理について解説します。

init.el 上で、以下のような処理を作成します。

```emacs-lisp: init.el
(dolist (mode '(org-mode markdown-mode text-mode ...))
(add-to-list 'evil-emacs-state-modes mode))
```

`evil-emacs-state-modes` とは、Evil モードが特定のメジャーモードに入った際に、自動的に Emacs ステートに切り替えるための変数です。これにより、指定したモード(今回は、org-mode, markdown-mode, text-modeなど)では、Emacs 標準の操作が可能になります。

## 相対行番号の追加
私は Vim を扱うときに相対行番号をONにして使っています。
相対行番号とは、自身のカーソルを基準とした番号表示のことを指します。これを有効にすると、「相対行番号+j,k」 でカーソルを移動することができ、とても便利です。

Emacs では、

```emacs-lisp:init.el
(setq display-line-numbers-type 'relative)
```

で相対行番号となります。これをEvilで行いたい場合は、`:custom` の上に設定します。

```emacs-lisp:init.el
  (use-package evil
  :ensure t
  :custom 
  (evil-want-C-u-scroll t)
+ (display-line-numbers-type 'relative)
  :config
  (evil-mode t))
```

# 参考文献
https://tarao.hatenablog.com/entry/20130303/evil_intro

https://evil.readthedocs.io/en/latest/index.html
PostProcessBuildを使ってUnityビルドを自動化するときの注意点

# PostProcessBuildとは？
UnityのEditorスクリプト内でのみ使えるアトリビュートで、これを付けたメソッドはビルド終了後に呼び出される。これを使うことで、例えばiOSビルド時のXcodeプロジェクトの設定を自動化できる。この場合別のプラットフォームのビルド時に呼び出されてしまうと困るので、条件付きコンパイル `#if UNITY_IOS`を設定する必要がある。
以下のスクリプトでは生成されるXcodeプロジェクトにGameCenterの設定を行うようにしている。
```csharp:XcodeProjectSetting.cs
#if UNITY_IOS
static class XcodeProjectSetting
{
    [PostProcessBuild(0)]
    public static void OnPostProcessBuild(BuildTarget target, string path)
    {
        var projectPath = PBXProject.GetPBXProjectPath(path)
        var project = new PBXProject();
        project.ReadFromFile(projectPath);
        
        var targetGuid = project.GetUnityMainTargetGuid();
        // GameCenterのCapabilityを追加
        project.AddCapability(targetGuid, PBXCapabilityType.GameCenter);
        
        project.WriteToFile(projectPath);
    }
}
#endif
```
# なにが罠なのか？
UnityのビルドをJenkinsで自動化するために上の `XCodeProjectSetting.cs` と以下のようなビルド用スクリプト `Build.cs` を用意した。
```csharp:Build.cs
static class Build
{
    // iOSビルドを実行
    public static void BuildIOS()
    {
        // ビルドターゲットをiOSに変更
        EditorUserBuildSettings.SwitchActiveBuildTarget(BuildTarget.iOS)

        // 略

        // ビルド実行
        BuildPipeline.BuildPlayer(buildPlayerOptions);
    }
}
```
このメソッドはシェルスクリプトから以下のように呼び出す。
```shell:ios_build.sh
# …
{UNITY_PATH} -quit -batchmode -executeMethod Build.IOSBuild
# …
```
そしてこれをJenkinsから実行するようにすると…生成されたXcodeプロジェクトにGameCenterが設定されていない。つまりPostProcessBuildが実行されていない…？
# 原因
`XcodeProjectSetting.cs` はEditorスクリプトなので、ビルド時にはコンパイルが走らない。よって、Editorスクリプトが最後にコンパイルされたときのビルドターゲットがiOSになっていない限り、条件付きコンパイル `#if UNITY_IOS` 以下が無視されてしまう（コンパイルされない）のが原因。
# 解決法
`EditorUserBuildSettings.SwitchActiveBuildTarget()` でビルドターゲットを切り替えるのではなく、コマンドライン引数からビルドターゲットを指定することで、コマンド実行時、まず最初にEditorスクリプトの再コンパイルが走り期待通りに動作してくれる。
```shell:ios_build.sh
# …
{UNITY_PATH} -quit -batchmode -executeMethod Build.IOSBuild -buildTarget iOS
# …
```
参考になれば幸いです。
Python：pyenvでPythonのバージョン管理

# はじめに
Pythonを使っていて，ライブラリの関係でこのPythonのバージョンを使いたいっていうときはありませんか？
今回はそんな人たちの役に立つように，Pythonのバージョン管理についての記事を書いておきます．

# pyenvとは
複数のPythonのバージョンを管理することができます．

# システムの環境
* OS：Linux
* Pythonのバージョン：3.10

# pyenvのインストール
１. pyenv を使用するための環境構築を行います．
　 以下をコマンドに入力します．

```
sudo apt install build-essential libssl-dev zlib1g-dev \
    libbz2-dev libreadline-dev libsqlite3-dev curl \
    libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev

```


２. pyenv をインストールをします．
 　 gitからクローンします．
```
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```



３. pyenv を高速化します．
 　 以下をコマンドに入力します．
```
cd ~/.pyenv && src/configure && make -C src
```



４. shell の設定を行います.
　  以下をコマンドに入力します．
```
export PYENV_ROOT="$HOME/.pyenv"
command -v pyenv >/dev/null || export PATH="$PYENV_ROOT/bin:$PATH"
eval "$(pyenv init -)
```



５. 変更の反映を行います．
　  デバイスの再起動を行います．
```
sudo reboot
```



６. pyenvがインストールできているか確認を行います．
　  以下をコマンドに入力します．
　  バージョンが返ってきたら pyenv のインストールは完了になります．
```
pyenv --version
```

# Python のインストール
任意のバージョンのPythonをインストールしていきます．
仮想環境を作っているとのちのち便利になるので，まだの方は仮想環境の構築をお勧めします．
以下のサイトを参考にしてみてください．
[Python：venvで仮想環境の作成](https://qiita.com/make_kae/items/e631c1d8ca9ff1d77814)



１. インストールしたい Python のバージョンを確認．
　  まず，pyenv でインストールできる Python のバージョンを確認します．
   　 以下をコマンドに入力します．
```
pyenv install --list
```
　 すると，インストールができる Python のバージョンがすべて表示されます．
   　 自身がインストールしたい Python のバージョンがあるか確認してください．



２. Python のインストール
　 任意のPythonのバージョンをインストールします．
　 今回は python 3.11 とします．
　 以下をコマンドに入力します．
```
pyenv install 3.11
```



３. インストールの確認
　　任意の Python のバージョンがインストールできたか確認します．
　　以下をコマンドに入力します．
```
pyenv versions
```

　　3.11 があれば，インストールできています．

# Python のバージョンの設定
使用したい Python のバージョンを指定します．
今回は Python 3.11 を使用することとします．


1.1　グローバル（全体）で指定するとき
　 以下をコマンドに入力します．

```
pyenv global 3.11
```



1.2. ディレクトリで指定するとき
 　以下をコマンドに入力します．
```
pyenv local 3.11
```



２. Python のバージョンの確認
  　Python のバージョンが変更されているか確認します．
 　以下をコマンドに入力します．
```
pyenv version
```
　 3.11 （任意のバージョ）となれば成功です．


# python のバージョンを削除したいとき
以下のコマンドを入力することで，pyenv にインストールした任意のPythonのバージョンの削除ができます．
今回は，Python 3.11 を削除することとします．

１. pyenv 上にインストールしている Python のバージョンの確認
  　以下をコマンドに入力します．

```
pyenv version
```
   このとき表示されたものがインストールされている Python のバージョンになります．



２. アンインストール
　任意の Python のバージョンをアンインストールします．
 　以下をコマンドに入力します．

```
pyenv uninstall 3.11
```



３. アンインストールの確認
　  任意のPythonがアンインストールされているか確認します．
    以下をコマンドに入力します．
    
```
pyenv versions
```
　 3.11 （任意のバージョ）が表示されなければ成功です．


# 参考
* [【Python】【Linux】pyenvを使用した環境構築](https://qiita.com/Ryo8-k2arl/items/d7220d4f19c76686ef52)
* [Python：venvで仮想環境の作成](https://qiita.com/make_kae/items/e631c1d8ca9ff1d77814)
* [pyenv/pyenv](https://github.com/pyenv/pyenv?tab=readme-ov-file#1-automatic-installer-recommende)
SPAのサイトに chrome 拡張機能で色々やりたい時の tips

# 概要

最近趣味で chrome 拡張機能を作っていましたが、その機能が主に「SPA 製のサイトで、要素を付け足したり、特定の要素の画像を差し替えること」で、特殊なテクニックが必要だったので tips として本記事に残します。

# 背景

ここは読み飛ばしても大丈夫です。

## SPA とは

Single Page Application (シングルページアプリケーション) ですね。近年 Vue.js, React 等で主役になっている方式です。

https://qiita.com/shinkai_/items/79e539b614ac52e48ca4

誤解を恐れずに端的に言えば、「最初のロードを除いて、全体の再読み込みはせずに動的にDOMを書き換えて疑似的にページ遷移させる方式」というものです。

## SPA サイトにおける chrome 拡張機能 (content_scripts)

chrome 拡張機能では、基本的に次のような流れで content_scripts (拡張機能の中で DOM などに触れるスクリプト) が実行されます。

1. ブラウザが読み込まれた URL から、マッチする拡張機能の読み込みをさせる
1. マッチした content_scripts を順次実行していく

即ち、ブラウザがロードされたタイミングでしか呼び出されないということです。
SPAはブラウザがロードされる (= 全体リフレッシュ) ことがないため、工夫しないとページの区別ができません。

# Tips 集

## SPA サイトのローディングを待つ

ここは SPA に限らずですが、近年の動的なサイト全般に利用できるテクニックです。
やることは単純で、「特定の要素が見つかるまで初期化処理を待つ」です。

```typescript:content.ts
function waitUntil(condition: () => boolean, callback: () => void, interval = 1000) {
  let timer: NodeJS.Timeout | undefined = undefined;

  const waiter = () => {
    if (condition() && timer) {
      clearInterval(timer);
      callback();
    }
  };
  timer = setInterval(waiter, interval);
}

waitUntil(
  () => document.querySelector("SomeKeyElement") !== null,
  () => {
    // ロードが終わった後にしたいこと
    main();
  },
  1000
);
```

## SPA サイトでURLの変更を検知したい

汎用的な回答は難しいですが、`MutationObserver`を用いて一定程度実現できます。

参考記事のように、body全体を補足してもいいですが、筆者が対象とするサイトでは title が変化していたので、 title のみ監視することで実現できました。

```typescript
let currentPath = window.location.pathname;

// HACK: SPA の URL 変更を検知するために、title タグの変更を監視する
const title = document.getElementsByTagName("title")[0];
const observer = new MutationObserver(() => {
    if (currentPath === window.location.pathname) return;
    
    currentPath = window.location.pathname;
    
    waitUntil(
      () => document.querySelector("SomeKeyElement") !== null,
      () => {
        // ロードが終わった後にしたいこと
        main();
      },
      1000
    );
observer.observe(title, { childList: true });
```

上記のような方法で、URL の変更を監視できるので、URL 毎に異なる処理を行うこと容易になります。

参考

https://qiita.com/nanasi-1/items/dbaee5d609c2199e861b

https://qiita.com/aki-743/items/f2ede921ae7fdeeed7c0
React × Chakra UI × Supabase で学習記録アプリを作ってみた

# React × Chakra UI × Supabase × TypeScriptで学習記録アプリを作ってみた

## はじめに
今回は、**React × Chakra UI × Supabase × TypeScript** を使って学習記録アプリを開発しました。  

最初は簡単に作れると思っていたのですが、実際には予想以上にハマるポイントが多かったです。  
特に、UIライブラリのバージョン問題やモーダルの状態管理、データの自動更新あたりで苦戦しました。  

## 開発したアプリの概要

### 実装した機能
- 学習内容と学習時間の記録
- 記録の一覧表示（ページネーション付き）
- 記録の編集・削除
- 全角数字の自動変換
- フォームバリデーション


![JISOU_課題3_学習記録アプリ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3851095/1db4cf3d-3c76-4241-b42d-a7c06dccf03e.png)


## 開発技術

| 技術        | バージョン | 説明 |
|------------|-----------|--------------------------------|
| React      | 18.3.1    | コンポーネント単位でUIを構築できるJavaScriptライブラリ。 |
| Chakra UI  | 2.8.2     | カスタマイズ性の高いReact向けUIライブラリ。 |
| Supabase   | 2.46.2    | BaaS（Backend as a Service） |
| TypeScript | 5.6.2     | 型安全を強化し、バグを減らせるJavaScriptの拡張言語。 |
| Vite       | 6.0.1     | 高速な開発環境とビルド機能を備えたフロントエンドツール。 |

## 開発中に直面した課題とその解決策

### ① Chakra UI v3からv2への"逆"移行
開発当初は **Chakra UI v3** がリリースされたタイミングと被ったため、v3を採用しました。  
しかし、以下の問題に直面しました。

- ドキュメントの内容と実際の挙動が違う
- エラーが出てもググっても情報が少ない
- 他のライブラリとの相性が微妙  

バージョンが新しいため解決方法の情報量が足りず、自分の力量では直面した問題を解決することができませんでした。

#### 解決方法
そこで、安定性と情報量を考えて、**Chakra UI v2にダウングレード** しました。

- v2なら公式ドキュメントが充実している
- QiitaやGitHubにもサンプルコードが多い
- 予期せぬエラーに悩む時間を減らせる

結果的に、開発がスムーズになりました。  


---

### ② モーダルとフォームの連携
モーダル内でフォームを扱うときに、状態管理が意外と難しいことに気づきました。  

- モーダルを開いたときに前のデータが残る
- 編集時の初期値を正しくセットできない
- バリデーションエラーの挙動が不安定


#### 解決方法
`useForm` の `reset` と `useEffect` を活用し、モーダルを開くたびにフォームをリセットする仕組みにしました。

```tsx
useEffect(() => {
  if (study && open) {
    reset({
      learn_title: study.learn_title,
      learn_time: study.learn_time,
    });
  }
}, [study, open, reset]);
```

これにより、編集時の初期値設定やバリデーションエラーの問題が解消されました。
状態管理の重要性を改めて実感しました。

---

### ③ Supabaseでの更新日管理
Supabaseを使ってデータを管理していましたが、「更新したら 更新時間：`updated_at` も自動更新されるようにしたい」と思いました。  
これは単に更新日時を記録するためではなく、**「最新のデータをソートして表示したい」** という理由もありました。  

例えば、学習記録を一覧表示するときに、**新しく編集したデータを上位に表示** したかったのですが、`updated_at` が自動更新されないと、どのデータが最近変更されたのか分かりません。  


#### 解決方法
Supabaseの**トリガー機能**を使い、データが更新されたら `updated_at` も自動更新されるようにしました。
```sql
CREATE OR REPLACE FUNCTION update_modified_column()
RETURNS TRIGGER AS $$
BEGIN
  NEW.updated_at = NOW();
  RETURN NEW;
END;
$$ LANGUAGE plpgsql;

CREATE TRIGGER handle_updated_at
BEFORE UPDATE ON study_record
FOR EACH ROW
EXECUTE FUNCTION update_modified_column();
```

このトリガーを設定することで、レコードが更新されるたびに updated_at が自動で更新 されるようになりました。
これにより、フロントエンド側で updated_at を意識しなくても、最新のデータを自動的に上位に表示 できるようになりました。


## 成長したこと & 気づき

#### ①コンポーネント設計を意識できるようになった
以前は「とりあえず動けばいい」という作り方をしていましたが、今回は再利用性を意識して設計できるようになりました。

#### ②状態管理の理解が深まった
「どのコンポーネントがどの状態を持つべきか」を意識できるようになり、無駄なリレンダリングを減らせるようになりました。

#### ③データベース側で処理できるものはDBに任せるべき
Supabaseのトリガーを活用することで、フロントエンド側の実装を減らせることを学びました。

## おわりに

今回のアプリ開発を通して、「実装力」だけでなく「設計力」も鍛えられたと感じています。
特に、状態管理やデータ管理の重要性を改めて実感しました。

今後も試行錯誤しながら開発を続け、より良い設計を学んでいきたいと思います。

# ✅JISOUのメンバー募集中！
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。
日本一のアウトプットコミュニティでキャリアアップしませんか？
興味のある方は、ぜひホームページをのぞいてみてくださ！
▼▼▼

https://projisou.jp
後輩「Dockerってなんですか？」僕「...どっかー？」

ってなったら情けないなと思ったので、Dockerについて改めて調べてみました。


## Dockerとは何か？


> **「アプリを動かすための環境ごとまとめて持ち運べる箱」**

です。

日高屋を例に挙げさせてください

自分は日高屋の肉野菜炒め定食が好きですが
どこの日高屋に行っても同じ味で最高に美味しい肉野菜炒め定食が出てくるのは
どこの店舗でも同じ定食を作れるように共通の道具・材料・レシピがあるからです


Dockerも同じで、どのPCでも同じ環境で開発、動作できるようにするためには
同じライブラリやバージョンのものが必要です。
それらを**全部セットにして箱詰め**して、  
どこでも同じよう動作、開発できるようにするしているイメージです。

つまりDockerは日高屋の店舗です


## Dockerを使う目的

Dockerの目的は下記3点です
- 環境の違いをなくして、どこでも同じようにアプリを動かす
- 簡単に開発・テスト・本番で同じ動作をさせる
- 配布や引っ越しを楽にする


## Dockerを使うメリット

| メリット | 説明 |
|----------|------|
|  環境がそろう | どこで動かしても同じ動作ができる |
|  配布が楽 | 1つの箱を渡すだけでOK |
|  セットアップが簡単 | 難しいインストール作業が不要 |
|  バージョン違い問題が消える | Node.jsやPythonのバージョン差で困らない |
|  テストや本番で再現性が高い | 開発環境と本番環境の違いがなくなる |


## Dockerを使わないと発生する作業

もしDockerを使わなかったら

- **サーバーごとに違う環境設定が必要**
  - Node.jsのバージョンが違くて動かない
  - OSが違くて動かない
  - 必要なソフトが入ってなくて動かない
- **インストール手順書を毎回作る必要がある**
- **動かす場所ごとに動作確認が必要**
- **他の人に渡すときに失敗することが多い**

つまり、Dockerなしだと  
「うちのパソコンでは動くのに…」問題が大量発生します。最悪です。

dockerがないというのは日高屋でいうと
あっちの店舗は豚肉じゃなくて鶏肉使っていて
味は九州の醤油を使っているからちょっと甘いんだよね
みたいなことが起きてしまいます。

ちょっと美味しそうですね。

味はちょっと差があるくらいじゃ大して問題にはならないですが
コードで動いてるものは少しの違いで動かなくなったりしますので
Dockerという存在は非常にありがたいのです


## 実際にどうやって使うのか？

### ① Dockerfileを作る
いわゆる日高屋です

```Dockerfile
FROM node:20.8.0
WORKDIR /usr/src/app
COPY . ./
RUN npm install
RUN npm run build
EXPOSE 8080
CMD ["npm", "run", "start"]
```


### ② Dockerイメージを作る

日高屋にあるマニュアルを見て肉野菜炒め定食を作ります

```bash
docker build -t gcr.io/プロジェクトID/my-app .
```


### ③ イメージをGCPにpushする
お客さんに料理を提供します

```bash
docker push gcr.io/プロジェクトID/my-app
```

これで、8080番ポートでアプリが動き始めます

## まとめ

Dockerを使えば、
 - 環境の差を気にせず  
 - どこでも同じように動かせて  
 - 配布や引っ越しもラク
Nextjsのlayout.tsxと_app.tsxの違い

バージョンによって混同するlayout.tsxと_app.tsxについて書きます
どちら広範(ほぼ全体)のページに適用される使用ですがlayout.tsxはより範囲を絞って適用することができます。

# Nextjsのバージョンごとの違い
13以降App Routerの導入によってlayout.tsxが導入され
より範囲を狭めた適用が可能になりました。

## Next.js12以前:
:::note warn
_app.tsxを使用してアプリケーション全体の設定やレイアウトを管理します。
ルーティングはpagesディレクトリ内のファイルとフォルダで自動的に行われます。
:::

## Next.js13以降（App Router導入）:
:::note warn
appディレクトリを使用し、各ページやセクションごとにlayout.tsxを利用してカスタムレイアウトを設定できます。
:::

_app.tsxも引き続きサポートされていますが、より詳細なレイアウト管理にはlayout.tsxが利用されます。

# layout.tsxを特定範囲だけにするには

:::note info
例えばですが、全体の場合だとappフォルダにlayout.tsxを記載すればいいだけです
もしもaboutページだけに限定したいのであればaboutフォルダの中にlayout.tsxを用意すれば
その範囲だけで適用されます。

```sqlsrc
└── app
    ├── layout.tsx  // 全体レイアウト
    ├── page.tsx  // トップページ
    └── about
        ├── layout.tsx  // Aboutセクションのレイアウト
        └── page.tsx  // Aboutページ

```
Nextjsでコンポーネント(部分テンプレート)作成

今回はコンポーネントの作成について書いていきます
例えばですが各ページでヘッダーを使いまわしたい
部分的に同じだから再度のせるのが手間だと思いませんか
コンポーネントはそれを解決します

# 1,コンポーネントフォルダの作成
今回は仮にヘッダーを作成するとします。
srcより後のフォルダ名(components),ファイル名(Header)は
基本変えても大丈夫ですので、ただ他の人が見てもわかりやすい
ように命名しときましょう。

```sql
src/components/Header.tsx
```

仮にこのような内容で記述します

```typescript
// src/components/Header.tsx
import React from 'react';
import Link from 'next/link';

const Header: React.FC = () => {
  return (
    <header>
      <nav>
        <ul>
          <li>
            <Link href="/"><a>Home</a></Link>
          </li>
          <li>
            <Link href="/about"><a>About</a></Link>
          </li>
          {/* 他のナビゲーションリンクを追加 */}
        </ul>
      </nav>
    </header>
  );
};

export default Header;
```

# 2,ページにheaderコンポーネントを追加します
あとは入れたい場所に<Headerと書けば候補がでてきますので
内容から作成したcomponentsを指定してenterすればimport部分も追加されて
埋め込まれます

```typescript
// src/pages/index.tsx (トップページ)
import React from 'react';
import Header from '../components/Header';

const HomePage: React.FC = () => {
  return (
    <div>
      <Header />
      <h1>Welcome to the Home Page</h1>
      <p>This is the main page of the website.</p>
    </div>
  );
};

export default HomePage;

```

# 3,まとめ
これの応用でサイドバー,フッターも追加できますので
今後のアプリ作成で役立ててください
Nextjsのaタグ、linkタグの使用について

Nextjsでページのリンクに関わるaタグとlinkタグについて
基本的にlinkタグが利用を推奨されています。
そこに関する内容を紹介します

# linkタグのメリット
高速になる、それに尽きます
aタグですとページ全体を読み込み直すので
回線状況が悪いとかなり遅くなりますが
linkタグだと必要な部分だけ変えるので相当早くなります

# 使用方法
下記のように最上部のimportを用意して
リンクを行い部分のタグを変えればOKです
というよりもタグ部分でLinとまで書いて最後にK+Enterで
自動的にimport部分が導入されるので手間が省けます
※他に候補がでるかもしれませんが内容をよく見て選んでください

```typescript
import Link from 'next/link';

const Navigation = () => (
  <nav>
    <ul>
      <li>
        <Link href="/"><a>Home</a></Link>
      </li>
      <li>
        <Link href="/about"><a>About</a></Link>
      </li>
    </ul>
  </nav>
);

export default Navigation;
```
NextjsのApp Router設定の違い


今回の記事ではNextjsの設定にあるApprouterの有無について
違いは色々ありますが、初心者が一番気になる別ページの作成について

# Approuterが無い場合
src/pages/index.tsxがトップページ
src/pages/about.tsxがaboutページになります

```
src
└── pages
    ├── index.tsx  // トップページ
    ├── about.tsx  // Aboutページ
```

# Approuterが有る場合
src/app/page.tsxがトップページ
src/app/about/page.tsxがaboutページになります
基本的にフロントエンドのコードはpage.tsxと同一化して
トップ以外のページはフォルダで分けていく方式になっています。

```
src
└── app
    ├── page.tsx  // トップページ
    └── about
        └── page.tsx  // Aboutページ
```

# まとめ

1,トップページはindex.tsxとpage.tsxと異なる
2,トップ以外のページはアプルーターありだとそのままファイル名に
　無しだとフォルダを作成してその中にpage.tsxを作成する形になる。
Macで Safe Exam Browserを使う

## はじめに
UMTPの試験を受けるため、
自宅でも受けられるSafe Exam Browserを設定しようとしたら
Macの場合、参考資料と若干違っていたので備忘を残します

## 設定手順
UMTPの受験環境設定をベースにしています
https://umtp-japan.org/about_exam/exam_gaiyo/l2

### ① ダウンロード
https://safeexambrowser.org/download_en.html からMac用をダウンロード

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500849/ef22e7d6-826e-4aab-a59b-297c114a3378.png)

### ② 設定
UMTPの受験環境設定では「SEB configration toolを起動する」とあったが、私の場合ダウンロードしても出てこなかった 

- Safe Exam Browserを起動して、 `command + カンマ` で Settingsを開く

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2500849/94bd4b92-ef8b-48da-890b-ca65b992fa0d.png)
（起動中はスクリーンショットが撮れなかったため、画像元：https://safeexambrowser.org/macosx/mac_usermanual_en.html#GeneralPane 実際の画面は若干違いましたが、Start URL欄は同じでした）
- `Paste from saved clipboardstart` を押下してStart URL欄に指定のURLを貼り付ける（事前にコピーしておく）

### 完了！
- 設定画面の右下 `Restart SEB` を押下すると、UMTPのログイン画面が表示される 


## おわりに
試験がんばります:writing_hand:
モノリシックシステムをにマイクロサービスへ移行パターン（Strangler Pattern）

## ストラングラーパターン（Strangler Pattern）とは？
モノリシックシステムを一度にマイクロサービスへ移行するのではなく、段階的に新しいサービスを導入しながら既存システムを徐々に置き換えていく手法です。  
この名称は、締め殺し植物（strangler fig）が既存の木を覆い尽くしながら枯らしていく様子から由来したそうです！

### **ストラングラーパターンの主要な要素**  
1. **APIゲートウェイ（API Gateway）**
   - 既存のモノリシックシステムのエンドポイントを変更せずに、新しいマイクロサービスへトラフィックをルーティングする役割を持ちます。
   - どのリクエストを既存システムと新システムのどちらに送るかを決定します。
   - トラフィックが徐々に新しいサービスへ移行できるよう制御します。

2. **統合グルー（Integration Glue）**
   - 既存システムと新しいマイクロサービス間でデータの同期、変換、メッセージブローカーの管理を行う中間層の役割を果たします。
   - 例えば、既存データベースとマイクロサービスのデータベースが分かれている場合、CDC（Change Data Capture）やイベント駆動アーキテクチャ（Kafka、RabbitMQなど）を活用してデータを同期します。
   - モノリシックサービスとマイクロサービスが共存する間、データの一貫性を保つ上で重要な役割を担います。

## モノリシックシステムを完全に削除する基準
モノリシックシステムを完全に削除できる主要な基準の一つが、**「データ同期率（Data Sync Rate）= 0」** です。  

### **データ同期率とは？**  
- マイクロサービスへ移行した後も、既存のモノリシックシステムと新しいマイクロサービスがデータを共有しなければならない場合があります。  
- そのため、CDCやイベントソーシングなどの手法を用いてデータを同期しますが、  
  **「モノリシックシステムから新システムへのデータ同期がゼロになった」** ということは、既存システムのデータが不要になったことを意味します。  
- つまり、**モノリシックDBからマイクロサービスDBへのデータ移行が完了し、既存システムが一切使用されなくなった状態** です。

### **完全な削除のその他の基準**  
- **トラフィックが100%マイクロサービスへ移行した**  
  - APIゲートウェイを通じて既存システムへのリクエストが完全になくなる。

- **既存システムのすべてのビジネスロジックがマイクロサービスへ移行した**  
  - モノリシックの一部モジュールが残っている場合、完全な移行とは言えない。

- **マイクロサービスが完全に独立している**  
  - データと機能が完全に分離され、モノリシックシステムを停止しても問題が発生しない状態。

## まとめ
**ストラングラーパターンは** 既存システムを段階的にマイクロサービスへ移行する手法であり、APIゲートウェイと統合グルーを活用してトラフィックを制御し、データの一貫性を維持します。

**モノリシックシステムを完全に削除する基準は** データ同期が不要になった（Data Sync Rate = 0）、既存システムへのトラフィックがゼロになった、すべての機能がマイクロサービスへ移行した場合です！
Atcoder 備忘録_2進法_問題B04

# 概要

- 競技プログラミングを始めてみた。
  せっかくなので１テーマごとに解法と学びをアウトプットしてみる。

## 取り組む内容
- 鉄則本[https://atcoder.jp/contests/tessoku-book] に沿って実施する。
- ![鉄則本.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3636949/7525f26c-5077-422b-b6b6-cbfab34ef327.jpeg)
- 言語は Python
- 今回テーマは「2進法」

# 問題文
2 進法表記で表された整数 N が与えられます。
N を 10 進法に変換した値を出力するプログラムを作成してください。

## 制約
N の長さは1 文字以上 8 文字以下N は 0 と 1 からなる
N の先頭の桁は 1 である

## 出力
答えを整数で出力してください。

## 解法
```
N = input()

answer = 0
length = len(N)

for i in range(length):
  if N[i] == "1":
    answer += 2 ** (length- i -1)
    
print(str(answer))

```

# 結果
- AC
- Runtime： 9 ms
- メモリ：8572 KB KB

# 振り返り
## 思想
- 2進数→10進数の変換は　　$\sum_{i=1}^n$ 2 ** i  ( if i桁目=1)

## 学び
- 今回はシンプルだったので特段なし

## 感想
-　2進数を使った探索法あると思うので、そのための基礎を確認できたかなと思います
大学の研究室におけるGithubのすゝめ

本資料はGitHubの基本操作を逆引き形式でまとめたものです。新規作成、更新、削除など、作業ごとに必要なコマンドをすぐに参照できるようにしています。特に個人のプロジェクト管理が多い大学院生向けにまとめています。

## 目次

1. [基本的な操作](#基本的な操作)
   - [新規作成](#新規作成)
   - [更新・同期](#更新同期)
   - [ファイル操作](#ファイル操作)
   - [リポジトリの複製](#リポジトリの複製)
2. [ブランチ操作](#ブランチ操作)
   - [ブランチの作成・チェックアウト](#ブランチの作成チェックアウト)
   - [ブランチ名の変更](#ブランチ名の変更)
   - [ブランチの削除](#ブランチの削除)
3. [マージとコンフリクト解決](#マージとコンフリクト解決)
4. [その他のTips](#その他のtips)
5. [参考リンク](#参考リンク)

---

## 基本的な操作

### 新規作成

- **新しいリポジトリの作成（ローカル）**
  ```bash
  mkdir <プロジェクト名>
  cd <プロジェクト名>
  git init
  ```

- **初回コミット**
  ```bash
  git add -A
  git commit -m "first commit"
  ```

- **空コミットで初期化したい場合**
  ```bash
  git commit --allow-empty -m "first commit"
  ```

- **リモートリポジトリの設定と初期プッシュ**

  ```bash
  git branch -M main
  git remote add origin <YOUR_REPOSITORY_URL>
  git pull origin main --allow-unrelated-histories
  git push -u origin main
  ```

### 更新・同期

- **リモート情報の取得**

  ```bash
  git fetch         # 最新のリモート情報を取得
  git fetch -p      # 不要なリモートブランチ情報の削除（prune）
  ```

- **ブランチ一覧の確認（ローカル・リモート）**

  ```bash
  git branch -a
  ```

### ファイル操作

- **変更したファイルのみをステージング**

  ```bash
  git add -u
  ```

- **未pushのコミットを確認**

  ```bash
  git log <リモート名>/<リモートブランチ名>..<ローカルブランチ名>
  ```

### リポジトリの複製

- **clone（リポジトリの複製）**

  ```bash
  git clone <URL>
  ```

---

## ブランチ操作

### ブランチの作成・チェックアウト

- **新規ブランチの作成**

  ```bash
  git branch <branchname>
  ```

- **既存ブランチへのチェックアウト**

  ```bash
  git checkout <branchname>
  ```

- **ブランチの作成と同時にチェックアウト**

  ```bash
  git checkout -b <branchname>
  ```

- **作成したブランチをリモートへpush**

  ```bash
  git push origin HEAD
  # または
  git push origin <branchname>
  ```

- **リモートのあるブランチを元に新規ローカルブランチを作成**

  ```bash
  git checkout -b <新しいブランチ名> <元にするブランチ名>
  ```

### ブランチ名の変更

- **デフォルトブランチ名（master → main）を変更する場合**

  ```bash
  git branch -m master main
  git push origin main
  # GitHub上でデフォルトブランチを変更後、不要なブランチを削除
  git push origin :master
  ```

### ブランチの削除

- **ローカルブランチの削除**

  ※ 削除する前に、対象ブランチ以外にチェックアウトしておく必要があります。

  ```bash
  git branch         # 現在のブランチを確認
  git checkout <他のブランチ>
  git branch -d <branchname>   # マージ済みなら -d、未マージなら -D を使用
  ```

- **リモートブランチの削除**

  ```bash
  git push origin --delete <branchname>
  ```

- **リモートブランチ一覧の同期（削除時のエラー対策）**

  ```bash
  git fetch -p
  ```

---

## マージとコンフリクト解決

- 他チームの変更を無視して、releaseブランチの内容でmainブランチを上書きするとき

  ```bash
  git checkout release
  git merge -s ours main   # mainの変更を無視してマージ
  git checkout main
  git merge release
  ```

- リモートリポジトリの変更を取り入れて、ローカルブランチの差分のみを更新する場合

  ```bash
  git pull --rebase --autostash
  ```

---

## その他のTips

- **.gitignore更新後のキャッシュクリア**

  一度Git管理下にあるファイルを後から.gitignoreに追加した場合、キャッシュが残っているので以下でクリアします。

  ```bash
  git rm -r --cached .
  ```

- **HEADとは？**

  Gitにおける`HEAD`は、現在チェックアウトされている最新のコミットを指します。詳しくは[こちら](https://qiita.com/ymzkjpx/items/00ff664da60c37458aaa)を参照してください。

---

## 参考文献

1. [Qiita：リモート・ローカルリポジトリ間の同期チェック](https://qiita.com/yuyuchu3333/items/a30387bdd6a0afc1185c)
1. [Qiita：Gitのファーストコミットは空コミットにすべき](https://qiita.com/NorsteinBekkler/items/b2418cd5e14a52189d19)
ChatGPT 4.5(GPT-4.5)について詳細まとめ

## はじめに  
**2025年2月27日**に登場した「GPT-4.5」は、前バージョンのGPT-4からさらに進化したAIモデルになります。
今回はこのリリースされたばかりのGPT-4.5の特徴などについて詳細をまとめてみたいと思います。  

## GPT-4.5とは？  
GPT-4.5は、OpenAIが開発した最新の大規模言語モデル（LLM）であり、**より自然な対話・高精度な情報処理・強化された推論能力**を備えたAIモデルになります。  

## 既存にChatGPTより進化したポイント  
- **処理速度向上**：GPT-4よりも**応答速度が高速化**  
- **知識の拡充**：データ更新頻度が増加し、**最新情報への対応力UP**  
- **推論能力の強化**：より複雑な質問にも対応可能  
- **コード生成の精度向上**：プログラミングサポートがより強力に  
- **マルチモーダル対応の強化**：テキスト＋画像の理解力向上  

##  GPT-4.5の活用方法  
### 1. エンジニア向け活用例  
- **コーディングアシスタント**（エラー修正・コード最適化）  
- **ドキュメント自動生成**（API仕様書の作成など）  
- **バグ解析とデバッグ支援**  

### 2. ライター・コンテンツクリエイター向け  
- **ブログ記事・技術記事の執筆サポート**  
- **キャッチコピーやタイトルの自動生成**  
- **翻訳や要約の精度向上**  

### 3. ビジネス活用  
- **チャットボットの応答品質向上**  
- **データ分析やレポート作成の自動化**  
- **マーケティング戦略の最適化**  

## GPT-4.5を使うには？  
### OpenAIの公式サイトで利用  
- [ChatGPT](https://chat.openai.com/)で直接試せる  
- APIを活用して独自アプリに組み込み可能  

### 他のプラットフォームとの統合  
- Notion AI、GitHub Copilot、Microsoft 365 などに組み込み済み  

## まとめ  
GPT-4.5は、**より高速・高精度・多機能**なAIとして新たに登場しました。
今後も進化が続くと予想され、さまざまな分野での活用が期待されます。 

## さいごに
ChatGPTが目まぐるしいスピードで進化していってますね。
今後のアップデートも楽しみです。
【Xcode】アプリ（プロセス）Kill後の起動をデバッグする方法

## 概要
アプリのプロセスをkillした状態から、様々な方法でAPPを立ち上げる時の挙動をBreakpointを差し込んでデバッグしたい場合がありました。
ただ、Xcodeのデフォルト設定ではアプリをビルドするとすぐにアプリが立ち上がってしまうため、DeepLinkやPush通知からの起動をデバッグできません。
今回はこの解決方法をまとめておきます。

## 方法
![スクリーンショット 2025-03-02 15.18.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577392/63372d0b-42d6-494b-85a2-509f541790d7.png)
まずProject name > Edit Schemeを選択

![スクリーンショット 2025-03-02 15.18.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577392/77eb2da6-1e8d-4dfa-ac81-34f2eb9063e4.png)

続いてRun > Info > Launch を "Wait fot the executable to launched"にします。
これにより、Xcodeはアプリがシステムによって起動されるまでデバッガを待機するようになります。
（= デバッガがアタッチされ、デバッグ可能になってからアプリが起動するようになります）

以上で設定は完了です。

あとは、シミュレータ上でアプリを上にスワイプしてkillしましょう。
そしていつも通りビルドを実行してください。

すると
![スクリーンショット 2025-03-02 16.44.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/577392/16f6633f-400b-4704-8a93-cfba3c462672.png)
このように、デバッガのアタッチを待っている状態になります。
あとはデバッグしたい起動方法でアプリを起動すると、しっかりBreakpointでとまってくれます。

## 使いどころ
#### 1. Deeplink（カスタムURLスキームやユニバーサルリンク）でのアプリ起動のデバッグ
- Deeplinkを開いたときに、`scene(_:openURLContexts:)`（SceneDelegate）や `application(_:open:options:)`（AppDelegate）が正しく動作するかを確認したい場合

#### 2. プッシュ通知でのアプリ起動のデバッグ
- フォアグラウンド / バックグラウンド / kill状態の各パターンで通知をタップしたときの動作を確認する
- userNotificationCenter(_:didReceive:withCompletionHandler:) やdidFinishLaunchingWithOptions 内の処理が期待通り動くかチェックしたい場合

## おわり
モバイルアプリ開発は、バックエンドとか以上にエディタの使いこなしも大切になってきますよね...
今度この記事のAndroid版（Android Studio版）も書こうかな。
laravel ver.11→ver.12へのアップグレード

つい先日、laravelがver.12にアップデートされたので
バージョンアップを自分のプロジェクトでも実施したので手順を備忘録として残します。

ちなみに、公式のガイドはこちらです。
https://laravel.com/docs/12.x/upgrade#upgrade-12.0

## 手順
まずは、composer.jsonを編集し、laravelのverを11から12に書き換えます。
```
"laravel/framework": "^12.0",
```

※自分の場合、React+Inertiaの環境で構築していましたInertiaを使っている場合は
Inertiaのバージョンアップも必要ですので、composer.jsonをver.2に書き換えてください
```
"inertiajs/inertia-laravel": "^2.0",
```
composer.jsonを編集したら、compser updateを実行してください
```
composer update
```


バージョンを確認し、ver.12になっていれば成功です。
```
$php artisan --version
Laravel Framework 12.0.1
```

以上です。
プロジェクト管理ツールredmineをgoogle cloudで組み立てる時のメモ

# 目的と前提
プロジェクト管理ツールのRedmineをGoogle CloudのVMインスタンスを使って組み立てるための自分用のメモです。
次のものはすでに準備しているものとして詳細を省略します。

* インターネットアクセスが可能なVMインスタンス(ubuntu server)
* apacheのインストール

## 主な内容
1) Redmineのインストール
2) メールの設定
3) リマインドメールの設定

### Redmineのインストール
**インストール解説はここ**

https://blog.redmine.jp/articles/6_0/install/ubuntu24/

インストール手順の中でRubyのビルド、gemパッケージのインストールには、マシンパワーをそれなりに要しする。
今回は、かなり時間がかかり、最後にはパワー不足で動作がkillされてしまったので、お金に物を言わせて、インストール時だけマシンパワーを上げた。
*(この時は試しにe2-standardにしてみた。短時間なので、お金はそんなにかからない。)*

configuration.ymlにFQDNを記載する場所があるが、用意したサーバにはDNSを設定しているので、そのDNSを記載。

ない場合は、多分これで確認。
**FQDNの確認方法**
```shell
hostname -f
```

**インストール後、Redmineの初期設定のドキュメントはここ**

https://redmine.jp/tech_note/first-step/admin/


### メールの設定
ちょっと面倒なのはこの手順。google cloudは、VMインスタンスにメールサーバを立てられない(正確にはメールに関する通信設定が果てしなく面倒っぽい)ので、Sendgridを使う。
多分、無料枠内で足りる。
**メール設定に関するドキュメントはここ**

https://cloud.google.com/compute/docs/tutorials/sending-mail/using-sendgrid?hl=ja

ドキュメント内に「ユーザー名、パスワード、ホスト名を含む、SendGrid SMTP アカウントの認証情報を書き留めておきます。」という記載があるが、サービス使用開始までにこれらの設定に出会えず、不明なまま。
でも設定では使わないので、問題なし。

あと、postfixのmain.cfに追記指示のある項目には、デフォルトで記載されているものがある。デフォルトをコメントアウトしなくても問題ない(後ろ記載が優先)が、ログで警告出るので、コメントアウトした。

**メール設定でドキュメントと異なる設定をした部分**
* sasl_passwdマップ作成のところで、.dbファイルを作成する部分は省略した。(エラー解決作業の中で、.dbファイルを作らなくても動くことが分かった)
* 証明書のハンドシェイクがうまくいかず、解決策として、今回は発信専用なので、main.cfのsmtpdに関する設定を全部コメントアウトした。
* 次の内容を指示以外にmain.cfに追記。(本当に必要かどうかはわからないが、エラー解決作業の中で追記し、コメントアウトしなかったもの。)
```
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
smtp_use_tls = yes
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
```

**SendGridの設定**
SendGridでは、送信するメールのfromを認証しなければならない。今回は、Domain Authenticationを使用。
メニューのSetting＞Sender Authenticationをたどり設定。ネームサーバに登録するレコードの指示に従い設定し、認証する手順。

**Redmineのメールのfrom設定**
システム管理者権限でログイン後、管理メニューのメールの項目に、差出元アドレス設定欄があるので、SendGridで認証されているアドレスに合うように設定。

**メールの送信テスト**
Redmineのインストールディレクトリで次のように実行。<USER_ID>はRedmineの登録ユーザID。
```shell
sudo -u www-data RAILS_ENV=production bundle exec rails runner 'Mailer.test_email(User.find_by(login: "<USER_ID>")).deliver_now'
```
で、ログを確認して送信できているかどうか確認。
```shell
sudo tail -n 30 /var/log/syslog
```

### リマインドメールの設定
期限が間近のチケットに関するリマインダメールが便利なので、設定。

**設定方法はここ**

https://redmine.jp/faq/issue/send_reminders/

**crontabの設定に注意**
今回の自動実行は、スーパーユーザではなく、Redmineの実行ユーザであるwww-dataで行うべき。
なので、ドキュメントにあるcrontabの設定ではなく
```shell
sudo -u www-data crontab -e
```
とし、
```
30 6 * * * cd /path/to/redmine &＆ bundle exec rake redmine:send_reminders days=7 RAILS_ENV=production
```
と記載。

**あとはタイムゾーンを確認！**
タイムゾーンが違っていて予想外の時間に動いたので、タイムゾーンの設定変更。
現在の設定確認は`date`や`timedatectl`で。何もしていなければ、世界標準時USTのはず。
まずは、タイムゾーンリスト確認。
```
timedatectl list-timezones
```
Asia/Tokyoがあるはずなので、タイムゾーン変更。
```
sudo timedatectl set-timezone Asia/Tokyo
```
再度確認すると、JSTになっていて、タイムゾーン変更成功。
【ServiceNow】getDisplayBox()の使い方メモ

:::note info
バージョンはVancouverです。
:::
getDisplayBox()を使おうとして引っかかったのでメモ。
### docsの説明を確認
[GlideForm - クライアント](https://www.servicenow.com/docs/ja-JP/bundle/vancouver-api-reference/page/app-store/dev_portal/API_reference/GlideForm/concept/c_GlideFormAPI.html)
>GlideForm - getDisplayBox(文字列 fieldName)
>コア UI のフォームから表示値を取得します。
>注: の Service Portalフォームから表示値を取得するには、 getDisplayValue() メソッドを使用します。

上記に加えてソース例が確認できます。例を参考にPDIで検証します。
### 実際に使ってみる
「説明」を変更したら画面上部にgetDisplayBox()で取得した値を画面上部にアラートを表示させます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/67743eef-2158-430f-a491-57676291661f.png)
1. getDisplayBox()で「日付１」を取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/1b91076e-b774-4a94-b87a-81691cd90eb0.png)
「説明」を変更します。エラーメッセージが表示されうまく取得できませんでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/f5484c70-43a7-4e21-8aaf-d48c7b0f501e.png)
2. getDisplayBox()で「簡単な説明」を取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/194c96f9-46a9-42b7-af86-c472ee0369b5.png)
「説明」を変更します。「簡単な説明」の表示値が取得でき、アラートが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/1cb7a473-fb01-4bd5-bf86-45ab50d9634d.png)
3. getDisplayBox()で「起票者」を取得
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/f94027f7-622c-4b3b-aee9-aaf4eae6d53a.png)
「説明」を変更します。「起票者」の表示値が取得でき、アラートが表示されました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/cd104594-65ea-4fd7-b8f3-9d7f15395958.png)
### getDisplayBox()の使いどころ
動作確認してみたところ、String型とReference型の表示値は取得できましたが、Date/Time型の表示値はgetDisplayBox()で取得しようとするとエラーになりました。
docsにははっきり書かれていませんが、getDisplayBox()は主に参照項目の表示値を取得したいときに使用するためのメソッドのようです。sys_idではなく画面上に表示されている「ユーザー起票者」などの文字列自体を取得したいときに便利です。
Date/Time型は無難にgetValue()で取得するのがよさそうです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/e492b862-4802-4010-8d79-140eef60eed6.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3931295/63782e4f-bfc5-4f7c-a081-414bbcd6fca1.png)
RL78/G23でTAUを使用してLチカ


RL78/G23-128p Fast Prototyping Board(以下FPB)でTAU0を使用したLチカをした際に出た、不具合とその対処法について記録を残します。

## 開発環境
・RL78/G23-128p Fast Prototyping Board
・CS+ for CC V8.12.00

## 不具合事象
下記動画を参考し、CS+で進めました。
https://www.renesas.com/ja/video/smart-configurator-tutorial-create-led-blinking-program-configuring-rl78-timer
TAU0の設定とLED1に対応するピンの設定はこれで完了したと思いましたが、FPBに書き込むと動作せず。
下記の不具合に出会ったので共有します。


### 不具合1：FPBに書き込めず、Lチカが出来ない。
解決方法：下記画面で通信ポートにCOMポートの設定をすることで解決
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088630/473a8b14-afe2-0ad1-af90-153bbff25726.png)


### 不具合2：オンチップ・デバッグで使用する予約領域への書き込みはできません。(address: 0x00000002)(E1203124)
解決方法：スマート・コンフィグレータでオンチップ・デバッグ動作設定をCOMポートに設定し、コードを再生成することで解決。
通常、デバッグのための領域は確保されていない模様
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3088630/79b3af87-4455-c9c7-44af-8bc5995f6aa3.png)

### 不具合：ルネサス公開動画とスマートコンフィグレータで生成されたソースが異なる。
不具合事象の項で紹介した動画では、main関数が下記のように生成されており、私の環境とは異なった。
```
//ルネサス公開動画
int main(void)
{
    EI();
    return 0;
}
```

```
//自環境
void main(void)
{
}
```

今回は割り込みTAU0を使用しているので、EI()を使用し、返り値は不要の為、下記のようなソースとした。
```
void main(void)
{
	R_Config_TAU0_0_Start();
	EI();
	while(1);
}
```

以上。
たかがLチカですが、やはり光った瞬間は嬉しいですね。
SwiftUi 画像 をドラッグして自由に動す方法 場所を保持したままにする

https://qiita.com/yuta317/items/3d400f71dc577cd539c1

先日のこちらでは、手を離したら中央に戻ってしまいましたが、こちらで指を離したところに表示をしている状態に変更する方法です。


# 実装コード
```.swift
struct DraggableImageView: View {
    @State private var currentDrag: CGSize = .zero  // 画像の位置を管理する変数
    @State private var startPosition: CGSize = .zero  // 開始位置を保持

    var body: some View {
        Image(systemName: "star.fill")
            .resizable()
            .frame(width: 50, height: 50)
            .position(x: UIScreen.main.bounds.width / 2 + startPosition.width + currentDrag.width,
                      y: UIScreen.main.bounds.height / 2 + startPosition.height + currentDrag.height)
            .gesture(
                DragGesture()
                    .onChanged { gesture in
                        currentDrag = gesture.translation
                    }
                    .onEnded { _ in
                        startPosition.width += currentDrag.width  // 開始位置を更新
                        startPosition.height += currentDrag.height
                        currentDrag = .zero  // ドラッグ量をリセット
                    }
            )
    }
}
```
`onEnded`でドラッグ位置を保持する事とで場所を保持したままにすることができます！
時間があるときに見たい物理の動画など授業

あくまでも私見です。いいなと思った動画をリンクあげとこうと思います。

# ファイマン自伝
https://www.youtube.com/watch?v=H9fjhQMsDW4&list=PLSBf6QxJAa9GbLlh_q25gATWk_kNrc0ui
第三者からみたファインマン教授の人柄などインタビュー。
御冗談でしょうファインマンで有名ですが私はむしろ
こちらのファインマンさんが本当の人柄のように思います。
https://www.chikumashobo.co.jp/product/9784480096906/


（Lecture 1 of Leonard Susskind's Modern Physics concentrating on General Relativity. Recorded September 22, 2008 at Stanford University.）


Lecture 1 - Leonard Susskindni　
https://www.youtube.com/watch?v=-vS_WIa0vYo&t=3216s


# 弦理論と M 理論・一般相対論
Leonard Susskind の弦理論の授業。南部先生と共にひもの理論を創始した人。元配管工らしいです。
伝説の先生です。
https://www.youtube.com/watch?v=25haxRuZQUk
Einstein's General Theory of Relativityは一般相対論も解説してくれます。
字幕DLで英語の勉強もできる。
https://www.youtube.com/watch?v=hbmf0bB38h0&list=PLPPSIjDe9T-81p1CjN49_Zi_L4-NQorTp

こちらは有名な第二次弦理論の立役者。ウィッテン先生の弦理論
https://www.youtube.com/watch?v=-vS_WIa0vYo&t=1426s



# 大関教授
この先生も面白いです。元駿台講師なので分かりやすいです。量子アニーリングを解説。
https://www.youtube.com/watch?v=MRX13sRRGsE


# 行間物理
物理の本の行間を埋めるプロジェクトです。すばらしいです。発想が
https://techbook-review.jp/intro/

# 量子力学から始めて第二量子化を理解する 
https://www.youtube.com/watch?v=Gl6yVPU12Wc&t=206s
ノートもあるのでワンポイントにはいいかも。

# 電通大の緒方先生の授業。
ぜひ、すべてを聞きたいです。（動画は多い）
解析力学・経路積分まで非常に高度。
https://www.youtube.com/watch?v=Gl6yVPU12Wc
https://www.youtube.com/@YusugeMaerchen

# 量子コンピュータ授業 #1　量子ビットと量子ゲート
慶応大の量子コンピュータの授業。すこし難しい
https://www.youtube.com/watch?v=R2fyLl7KZXM&t=1156s

# アインシュタイン方程式の解き方：回転ブラックホール解
数式がきっちり解説してくれるのがうれしい
https://www.youtube.com/watch?v=vbaQ98imhdw

# おまけ
反〇〇団体にとぼけてイタ電（最近一番おもしろかった）
https://www.youtube.com/watch?v=fCS_yZrsV4g
伝説の教師Leonard Susskindniのジョーク。
なぜ笑ってるのか私の英語力ではわからないです。
だれか解説を。Cancel itとか言ってるのできわどいジョークのようです。
https://www.youtube.com/shorts/pFpsCEjDO7Y
ChatGptによると
"I probably need eraser. Where?"
→ 「消しゴムがたぶん必要です。どこ？」
"It's on the board."
→ 「黒板の上にあるよ。」（普通の返答）
"You aren’t understand me. Will you be my eraser?"
→ 「君は理解していない。君が僕の消しゴムになってくれる？」
→ ここで「eraser（消しゴム）」を「人」に対して使ってしまっている。
"Person to eraser?"
→ 「人が消しゴムに？」
"Yes. I probably need a hooker."
→ ここで「hooker（フッカー/売春婦）」という単語が登場し、意図せず笑いが生まれる。
これでもわからないですｗ
好きな引数を指定してループを回せるeach_with_objectについて

引数に渡したオブジェクトをループ処理の中でアクセスし、レシーバーの要素の数だけループを回す事ができる。

公式では配列を引数に取り、それにpushしていく使い方が紹介されているが、{}をオブジェクトにとって、以下のような使い方も可能
https://docs.ruby-lang.org/ja/latest/method/Enumerable/i/each_with_object.html

```rb
# evens = (1..10).each_with_object([]) {|i, a| a << i*2 } # 配列の場合はこんな感じ
evens = (1..10).each_with_object({}) {|i, h| h[i] = i*2 } # ハッシュの場合はこんな感じでも使える。最後に引数で指定したハッシュオブジェクトを指定する

p evens # {1=>2, 2=>4, 3=>6, 4=>8, 5=>10, 6=>12, 7=>14, 8=>16, 9=>18, 10=>20}
```
【備忘録】numpy.linalg.norm

# 基本的な使い方
- **numpy.linalg.norm(x, ord=None, axis=None, keepdims=False)**
- x:計算したいベクトル or 行列（Numpy配列）
- ord:ノルムの種類を指定するオプション（L１マンハッタン、L2ユークリッド（標準）など）
- axis:デフォルトは全体
ブラウザから操作可能なラジコンを作る【３】



## 【３】サーボモーターを制御

前回、DCモーターをモータードライバー経由でPWMを使用し
加速・減速を行いました。
今回はハンドルの操作に使用する
サーボモーター
DualSenseにはアナログトリガーがあるので
モーターの回転スピードを調整する制御まで進めます。

<br></br>
## 目次
* [【１】Raspberry pi の、GPIOをTypescriptから操作](https://qiita.com/Yasukosan/items/1bf9480c10de7d69c2a4)
* [【２】DCモーターをPWMで速度制御](https://qiita.com/Yasukosan/items/291c76c10be135fd7595)
* [【３】サーボモーターを制御](https://qiita.com/Yasukosan/items/e81c9c9d0159b32e5893)
* [【４】DualSenseをブラウザに接続](https://qiita.com/Yasukosan/items/bf3a085145db84a48823)
* [【５】DualSenseの情報をRaspberryPiに飛ばす](https://qiita.com/Yasukosan/items/400883be94751966221a)
* [【６】DualSenseのチャタリング？問題対応](https://qiita.com/Yasukosan/items/7e52609699b4b71196ca)
* [【７-１】RaspberryPiから低遅延で映像を飛ばす](https://qiita.com/Yasukosan/items/98426f1ba4dea4c9ec5f)
* [【７-２】RaspberryPiから低遅延で映像を飛ばす](https://qiita.com/Yasukosan/items/2246c8a32602ca77ace9)
* [【８】ThreeJSでVRもどきを作成](https://qiita.com/Yasukosan/items/e15e8fd002cf49e3d04d)
* [【９-１】iPhoneの加速度から頭の向きをVRに反映](https://qiita.com/Yasukosan/items/9b4333770baea4110361)
* [【９-２】スマホVRゴーグル向けデザインに変える](https://qiita.com/Yasukosan/items/7f1bb7a9d95cb76f8117)
* [【１０】ラジコン本体の製作](https://qiita.com/Yasukosan/items/0d37c1df5b5d6c02257b)
* 【１１】パワーアップとバッテリー問題の解決
<br></br>
## サーボモーター
サーボを使った工作でおなじみのSG90を使用します。

<img
    src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/147738/ca56f996-09d6-4240-a65c-d1de0b4091f2.jpeg"
    width="320"
/>
RaspberryPiのGPIOに直接つなぐだけで使えるので
注意点も何も無く、挿してコードを動かすだけで使えます。

このサーボの仕様では、初期位置の０度に対して
-９０度～+９０度まで１８０度回転

piggpio経由では、Hz換算で500～2500の範囲に収まるそうで
直感的に分かりにくいこと、この上ないのと
初期位置からマイナス方向に回らないっぽい？

<br></br>
## 試験コード

使い方が根本的に違う、という可能性をハラミつつも
初期位置＝500となっているようなので
ラジコンへの取り付け位置から、手探りで初期位置を調整し

|位置|PWM出力|
|--|--|
|イニシャル|850|
|左|550|
|右|1150|

という割り振りを前提に
試験コードを書いた全容が下記になります。

```javascript
const gpio = require('./gpio.service')

const MotorPorts = {
    HANDLE: 17,
    INITIAL_ANGLE: 850,
}

// PWM信号出力ポート追加
gpio.addPort({port: MotorPorts.HANDLE, mode: 'out'})

await gpio.initGpio()

// 初期位置にサーボを動かす。
gpio.searvoWrite(MotorPorts.HANDLE, MotorPorts.INITIAL_ANGLE)

const angle = [550, 1150]
let p = 0

// 1秒毎に、左・右の角度にサーボを動かす。
while (true) {
    console.log(gpio.searvoWrite(MotorPorts.HANDLE, angle[p]))
    p = (p === 0) ? 1 : 0
    await new Promise((resolve) => setTimeout(resolve, 1000))
}

```
<br></br>
## サーボ駆動試験
試験コードを動かすと、こんな感じでサーボモーターがかくかく動きます。

<iframe width="560" height="315" src="https://www.youtube.com/embed/IFh_bqlX0OQ?si=dDAevVAa2oQpyP-v" 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>


<br></br>
サーボモーターを動かすだけ、の場合こんな感じでかなり簡単に済みます。

誰でも簡単に使えるように
規格化、体系化されたありがたみを感じる部分です。


<br></br>
<br></br>
# UZAYA
Uzayaでは、多分仕事を求めています。
何かの役に立ちそうでしたら、是非お知らせを。
Nextjsの簡単な使い方について

備忘録の一環として記事を書いてみました
これでNodejsのインストールも必要ですが、とりあえず
簡単な立ち上げについて書いてみます。
プロジェクト名はお好みでどうぞ

#インストール

```sql
npx create-next-app プロジェクト名
```

次に詳細設定を行います
```sql
PS C:\Users\user\test> npx create-next-app プロジェクト名
√ Would you like to use TypeScript? ... No/Yes
√ Would you like to use ESLint? ... No/Yes
√ Would you like to use Tailwind CSS? ... No/Yes
√ Would you like to use `src/` directory? ... No/Yes
√ Would you like to use App Router? (recommended) ... No/Yes
√ Would you like to customize the default import alias (@/*)? ... No/Yes
```

最後にcdでプロジェクトそのものに移動して
下記のコードで起動確認を行います

```sql
cd プロジェクト名
npm run dev
```
PHPで「定数」の動作を確認してみた。

# 概要

PHPで「定数」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/php/var/index7.html

# 実装

以下のファイルを作成しました。

```sample.php
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
<?php
define("PAI", 3.14159);

$r = 7;
$menseki = PAI * $r * $r;
print '半径='.$r.'の面積は'.$menseki.'<br />';

$r = 14;
$menseki = PAI * $r * $r;
print '半径='.$r.'の面積は'.$menseki;
?>
</p>

</body>
</html>
```

以下のコマンドを実行しました。

```
$ php sample.php 
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<title>PHPテスト</title>
</head>
<body>

<p>PHPのテストです。</p>

<p>
半径=7の面積は153.93791<br />半径=14の面積は615.75164</p>

</body>
</html>
```

# まとめ

何かの役に立てばと。
【備忘録】numpy.random.randint

# randintの使い方
- np.random.randint(low, high=None, size=Noze, dtype=int)
- lowは生成する乱数の最小値（必須）、highは最大値で省略した場合は0からlowまでで乱数が生成される。sizeは乱数の形状で指定しない場合は単一の整数。２D以上はタプルで指定する。
記憶装置を入力装置として使ってはならない

「このフォルダにファイルが入ったときにアレしたい」的な機能。

結構要求されがちだが、システムとしては個人的に「絶対に避けるべき」レベルの機能なのでその理由をメモしておく。
記憶装置は入力装置ではない。
ファイルシステムはデータの永続化を目的としたものであり、イベント駆動型の処理には向いていない。
そのため、「フォルダにファイルが入ったら何かする」という設計は、信頼性・パフォーマンス・スケーラビリティの面で問題を引き起こしやすい。


**Q. でもそういう機能を搭載した製品あるじゃん。**

**A. あれらも厳密にファイルの変更をリアルタイムに監視できているわけではないのです...（Google DriveやOneDriveのようなサービスはファイルシステムのイベントを監視しつつ、変更をすぐにアップロードするのではなく、一定の間隔でハッシュ比較などを行いながら同期する方式になっている。
つまり、内部的にはバッチ処理とイベント駆動を組み合わせた設計になっており、常に即座に処理されるわけではない。）**

## 想定している機能
「特定のディレクトリに画像ファイルが入ったら処理したい」
や
「特定のディレクトリ配下のテキストファイルをベクトルDBと同期したい」

(主にファイル更新のイベントに関する話で、簡易で厳密でないバッチ処理はアリかも...？)

## 理由まとめ

### 信頼性の無さ
「ファイルの書き込みがいつ終わったか」が書き込み側の都合である。
処理側のプロセスが完了を知る手段が存在ない。
どのタイミングで処理を発火させたら良いかわからず、非効率な処理になる。

### 書き込み方が千差万別
ファイルの書き込みは1度で終わらないことも多い。
例えば、以下のPowerShellでディレクトリを監視した場合、**メモ帳で保存すると1回発火したが、VSCodeだと2回発火した。**
書き込みサイズによると思うが、複数回flushすることは珍しくない。

```powershell
$watchTarget = "./watch_target"

$filter = "*.*"
$includeSubdirectories = $true
$watcher = New-Object System.IO.FileSystemWatcher
$watcher.Path = $watchTarget
$watcher.Filter = $filter
$watcher.IncludeSubdirectories = $includeSubdirectories
$watcher.EnableRaisingEvents = $true

$onChanged = Register-ObjectEvent $watcher "Changed" -Action {
    Write-Host "File changed: $($eventArgs.FullPath)"
}

$onDeleted = Register-ObjectEvent $watcher "Deleted" -Action {
    Write-Host "File deleted: $($eventArgs.FullPath)"
}

while ($true) {
    Start-Sleep -Seconds 1
}

```

### 速度
そもそもストレージの読み書き速度はRAMに比べてとんでもなく遅い。
誇張抜きに1000倍ほど違う。

### ハードウェアの負荷
SSD、HDDは書き込み回数に限度がある。

### 監視プログラムが常駐していない時を考慮するのが大変
OSのファイルシステムなので、監視していないタイミングでユーザーに変更される可能性がある。
その場合
1. とりあえず全部読む
1. 処理時に記録しておいたハッシュと突き合わせて変更があったか調べる

の2ステップが必要になる。
全部読むというのか...？大きくなりうるディレクトリを...？

### スケーラビリティ
分散ストレージではないので、ファイルが大量になるほど処理が遅くなる。
数GBでもレスポンスが悪くなり、実用的ではなくなると思われる。

## 解決策

### APIがあればそれを使う
書き込み側のシステムにAPIがあればそれを使う。
**道具は正しく使おう！**

### オブジェクトストレージを使う
S3, Cloud Storageなど、スケールできるストレージを使用する。

### 入口を制限する
書き込み -> 処理
ではなく
処理 -> 書き込み
にすれば幾らかマシなので、専用のUI、APIを用意する。
家計簿アプリを作る＃４

![スクリーンショット 2025-03-02 151534.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/7d2086d7-a387-4e46-bf44-0647ff8452c4.png)
次に、この部分を削除して、

![スクリーンショット 2025-03-02 151638.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/7e983284-6853-42f1-a9d9-40ac52e62af8.png)
続いて、<Router></Router>を追加し、写真👆のようにインポートします。

![スクリーンショット 2025-03-02 151809.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/60cb8005-ad61-454f-a47c-0eb9ac80ad19.png)
その次に、４行目にBrowserRouter as Routerと書き直します。

![スクリーンショット 2025-03-02 151953.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/5688e58d-d698-43c7-bc0f-ed54459679a3.png)

”Routes”と”Route”も写真のように、付け加え、インポートします。