OmniAICreator/Qiita-1.07M huggingface dataset:
【Pepper】自動化 ～ログ取得・PKG/APKインストール・Package/Activity名取得～

## 概要
　Pepperに対して毎回手動で行っていた下記３つの作業を自動化しました。
　・ログ取得（Naoqiログ、ADBログ）
　・PKG/APKインストール
　・Package名/Activity名取得
今回作成した自動化ツールはコマンド１つで実行できるため、コマンド入力ミスをなくしたり、作業時間の短縮など業務効率化に寄与します。
 
　また、以下のようなケースで特に力を発揮します。
　・作業に必須なコマンドがまだ覚えられなくて時間がかかってしまう
　・作業対象のPepperやPKG/APKが複数ある
　・コマンド出力内容のどこを見たらいいかわからない

 今回記載する内容は主にPythonで作成した自動化スクリプトですが、PCによって会社からPythonのインストールを禁止されていて使えない場合やインストール方法がわからないといった方でも気にすることなく使えるようにshellスクリプト版も作成しています。

<br>

##### 【目次】
 1. 要件定義
 2. 基本設計
 3. 環境構築
 4. 制作物
 5. 所感


 ## 1. 要件定義
～達成したい目標～
　・作業時間の短縮による業務効率化
 
～現在の課題～
　以下の理由により作業の開始から完了まで時間がかかる
　・コマンド初心者の理解度不足
　・１つの作業に対して複数回コマンドを実行する必要がある
　・１つのコマンド実行完了まで待機する必要がある
　・複数機体に対して実施する場合、機体数分の手間が増える
　・コマンド実行結果の該当箇所を探す必要がある
 
 ～課題解決のために必要なこと～
　〇機能要件
　・１つのコマンドですべての処理が全機体で実行されること
　・成功と失敗の判定を出力する
　・１つのエラーや失敗によって処理が中断されないこと
　・ユーザの求める情報をわかりやすく出力すること

　〇非機能要件
　・スクリプト実行時間が長くならないこと
　・エラー内容や失敗した理由をユーザーに知らせること
　・機体の設定環境に依存せずスクリプトを実行できること
　・入力内容に誤りがある場合は入力をリトライすること


 ## 2. 基本設計
〇共通
　・コマンドの引数が正しいかをスクリプト実行前にチェックすること
　・IPアドレスやネットワーク設定の間違いによるエラーをユーザに通知すること
　・スクリプトの実行状況を逐次ターミナルに出力すること
　・処理が失敗した場合は、どの処理が何の原因で失敗したかをユーザが把握できるようにすること
 
〇ログ取得
　・Naoqiログ/ADBログ（2種類）の取得
　・ADBログ取得用のPKGが存在しない場合は、後続の処理を実行
　・複数機体に対して一括で実行できること
　・機体ごとに複数のログファイルを1つのフォルダにまとめてコピーすること

〇PKG/APKインストール
　・PKGとAPKのどちらもインストールできること
　・ADBコマンドが使用不可に設定されている機体でもAPKをインストールできること
　・ADBコマンドを使用しない方法でのインストールに失敗した場合、開発者モードが有効に設定されていればADBコマンドでリトライすること
　・インストール済みのバージョンを確認し、正確にインストールの成功/失敗判定をすること
　・複数のファイルを一括でインストールできること
　・複数機体に対して一括で実行できること

〇Package/Activity名取得
　・アプリのパッケージ名とアクティビティ名を取得できること
　・ユーザが探しているアプリを一覧で表示すること
　・ダンス/エンタメアプリのみ抽出できること
　・一覧から任意のアプリをユーザが指定できること
　・入力内容が正しくない場合、入力をリトライできること

 ## 3. 環境構築

　・MacOS
　・Python3
　・shell（Python使用不可のPC用）


 ## 4. 制作物

 [python 版]('https://github.com/Hibiki513/Automation_robot/tree/main/AutoCmdExecutor_py')スクリプト

 [shell 版]('https://github.com/Hibiki513/Automation_robot/tree/main/AutoCmdExecutor_shell')スクリプト

 ## 5. 所感

このスクリプトを書き始めた頃は1からPythonで書くという経験がなかったため右も左もわからない状態だったが、Pepperにssh接続する部分でつまづいた。だが、ドキュメントやChatGPTを活用して試行錯誤していくうちにこのスクリプトを書き終える頃には知識を深めることができたと感じている。

この自動化ツールを作成したことで、実際に自分自身の業務効率化にも役立っていると感じている。
今までは、ログ取得やファイルのインストールの最初から最後まで1分以上、長い時は5分ほど時間を取られる作業だったが、ツール実行用のコマンドを叩いた後は別の業務に着手できるため、要件として掲げていた「作業時間の短縮による業務効率化」に貢献できていると考えている。
Jetpack Composeの親子構造とデータフローの基本

Jetpack Composeを効果的に使うためには、Composableの親子構造とデータフローの考え方を理解する必要があります。
この記事では、基本的な考え方と実装方法について解説します！

## 基本的な親子構造とデータフロー

Jetpack Composeでは、UIコンポーネント（Composable）が階層的に組み合わされて構築されます。その際、親から子へデータを一方向に渡し、子Composableで発生したイベントは親にコールバックとして返すのが基本パターンです。

- 親Composable は状態（State）を保持して子にデータを渡す
- 子Composable は受け取ったデータを使ってUIを表示する
- 子で発生したイベントはコールバック関数を通じて親に通知し、親がデータを更新する

データの流れを一方向にすることで、状態管理が明確になり、予測可能な動作を実現できます。

## 実装例

簡単な例で、具体的な流れを見てみましょう。

``` kotlin
@Composable
fun ParentComposable() {
    var message by remember { mutableStateOf("Hello") }

    ChildComposable(
        message = message,
        onMessageChange = { newMessage ->
            message = newMessage
        },
    )
}

@Composable
fun ChildComposable(
    message: String,
    onMessageChange: (String) -> Unit,
) {
    Column {
        Text(text = message)

        TextField(
            value = message,
            onValueChange = onMessageChange,
        )
    )
}
```

## データの一方向フローとState Hoisting

Composeでは、親Composableで状態を管理し、子Composableはその状態を表示するだけに留めるという設計が推奨されています。これをState Hoisting（状態の巻き上げ）と呼びます。

State Hoistingの利点は以下の通りです。
- 状態が一箇所で管理され、デバッグやテストが容易になる
- 子Composableが再利用しやすくなる
- データがどこで変更されたかを把握しやすく、デバッグやメンテナンスが容易になる

## 子から親へイベントを伝えるコールバック

子Composableでユーザーの操作（ボタンタップやテキスト入力など）を受け取った場合、親にそのイベントを通知するには、イベント用のコールバックをパラメータとして渡します。

例）ボタンタップの通知
``` kotlin
@Composable
fun ParentComposable() {
    var count by remember { mutableStateOf(0) }

    ChildButtonComposable(
        onButtonClick = { 
            count += 1 
        },
    )
}

@Composable
fun ChildComposable(onButtonClick: () -> Unit) {
    Button(onClick = onButtonClick) {
        Text("Click me!")
    }
}
```

イベントを親に戻すことで、状態を一箇所に集中管理でき、データフローがシンプルになります。

## まとめ

- 親Composableがデータや状態を保持し、子Composableへ渡す
- 子Composableはイベントを親にコールバックで通知
- 状態はできる限り親で保持する（State Hoisting）

この基本原則を守ることで、明確でメンテナンス性の高いComposeアプリケーションが構築できます！
3.Longest Substring Without Repeating 　解答例・ポイント

# 問題内容
与えられた文字列内で文字が重複しない連続した文字列から最大の長さを返す

# 解答例
```python:sample.py
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        n = len(s)
        maxLength = 0
        charSet = set()
        left = 0

        for right in range(n):
            if s[right] not in charSet:
                charSet.add(s[right])
                maxLength = max(maxLength, right - left + 1)
            else:
                while s[right] in charSet:
                    charSet.remove(s[left])
                    left += 1
                charSet.add(s[right])

        return maxLength    
```

# ポイント
- 既出の文字を集合として保持する
- ループしていく過程で既出文字が現れた際に、集合から特定の既出文字がなくなるまで左端のポインタを動かす
- この処理によって重複していない文字についても集合から削除してしまうが、この問題では連続した文字列の長さについて問われているため大丈夫
新しい技術をサッと俯瞰するプロンプト


新しい技術を学び、俯瞰的な理解を持つことは、現代の技術者にとって非常に重要なスキルです。今回は、新しい技術を深掘りするために役立つプロンプトを紹介します。

## 新しい技術を俯瞰する方法

新しいツールや技術に触れる際、どのように理解を深めるべきか迷うことがあるかと思います。以下に、私が普段から活用している項目と、その理由について解説します。

---

### 📌 俯瞰するための調査ポイント

俯瞰する際に役立つ調査項目を以下に分解しました。それぞれのステップで「どのような情報を集めるか」を明確にしながら、技術の全体像を俯瞰しましょう。

### 1. 基本情報を整理する
- **概要・目的**  
  新しい技術が「何を解決しようとしているのか」を理解します。
- **対象ユーザー**  
  誰のための技術なのかを考えます。

### 2. 提供される機能と技術面を理解する
- 主な機能や特長を洗い出し、その技術的な仕様について深く掘り下げます。

### 3. 開発やコミュニティの状況を確認する
- 開発の活発度やコミュニティの存在感を確認することは、技術の信頼性の指標になります。

### 4. 導入・利用環境の確認
- インストールのしやすさやサポート体制、ドキュメントが整備されているかを調べます。

### 5. ライセンスや利用条件の確認
- 利用や商用使用における許諾条件を把握しましょう。

### 6. 活用実績や事例を調査する
- どのようなユースケースで使われているか、成功事例を確認します。

### 7. 導入時の課題や将来的なリスクを洗い出す
- 導入のハードルや潜在的なリスクを評価することで、計画的に技術を取り入れるための指針とします。

---

## 実際に使えるプロンプト

プロンプト:
```
与えられたキーワードについて次のフォーマットで詳しく教えて下さい。

### 📌 **1. 基本情報**
- **概要・目的**
  - 何をするためのものか？
  - 何の問題を解決するか？
- **対象ユーザー**
  - 誰が使うことを想定しているか？
  - どのような人が関わるべきか？

### 📌 **2. 機能・特徴**
- **主な機能や特長**
  - このソフトウェア・ツールが特に強調している機能は？
  - 他と比較して特徴的な点は？
- **技術スタック**
  - 使われている言語・フレームワーク・ライブラリは？
  - 既存の技術との親和性や相互運用性は？

### 📌 **3. 開発状況**
- **コミュニティの活発度**
  - GitHub上でのスター数、フォーク数、貢献者数は？
  - 最近の更新頻度・安定性は？
- **ロードマップや今後の方針**
  - 将来予定されている機能や開発目標は？
  - 長期的に維持されそうか？

### 📌 **4. 導入・利用**
- **インストール・セットアップ方法**
  - インストールや設定に必要な環境や前提条件は？
  - 簡単に試せるデモやDockerコンテナなどは用意されているか？
- **ドキュメントやサポート体制**
  - わかりやすいドキュメント、チュートリアルは整備されているか？
  - 質問できるフォーラムやチャットはあるか？

### 📌 **5. ライセンス・利用規約**
- **ライセンスの種類**
  - どのようなオープンソースライセンスを採用しているか？（MIT、Apache、GPLなど）
- **商用利用の可否**
  - ビジネスでの利用に制限はあるか？
  - 再配布や改変などに関する注意点は？

### 📌 **6. 活用事例・ユースケース**
- **主な導入事例**
  - すでに採用している企業や団体は？
  - 実際の活用方法・効果は？
- **類似する他のプロジェクトとの比較**
  - 類似する既存ソフトウェアと比較した際の利点・欠点は？

### 📌 **7. 課題・リスク**
- **現在の課題や制限事項**
  - 既知の問題やバグは？
  - 性能・セキュリティ面の懸念は？
- **将来的なリスク**
  - 開発が停滞・中止した場合の影響は？
  - 依存ライブラリの更新停止などの影響は？
```

---

## おわりに

新しい技術について理解を進める際のエントリーポイントとして、このプロンプトを活用してみてください。

情報を整理するだけでなく、具体的な導入や将来計画を俯瞰できるようになります。特に技術選定やプロジェクト計画の初期段階で効果を発揮するはずです。

このプロンプトをGPTsにしておくと、さらに便利になると思います！Enjoy!!
家計簿アプリを作る＃８

![スクリーンショット 2025-03-06 093428.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/970f5492-3a97-4618-8d31-8f18e581f574.png)
続いて、AppLayoutファイルを作っていきます。

![スクリーンショット 2025-03-06 093554.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/2524417e-9c5a-4468-9708-a77e1e2a7609.png)
AppLayoutの子、HomeコンポーネントのPathは、indexに書き換えられます。そうすることによって、AppLayoutコンポーネントが呼ばれたときに、Homeコンポーネントが呼ばれます。

![スクリーンショット 2025-03-06 093842.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/02985441-04ed-407e-b2d2-bb89d2aac8f4.png)
componentsファルダの中に、layoutフォルダ、その中に、AppLayout.tsxファイルを作成していきます。

![スクリーンショット 2025-03-06 094034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4012588/0333f8c8-e5b0-4abb-94d0-76b3dcbe4b64.png)
そして、ひな形を作成します。
【Python】毎週勉強するシリーズ ～リスト関数～

# 概要
AI が流行ってる昨今 Python は必須級のスキルになってきてます。
時代に取り残されないようにコツコツと Python を勉強しようと思います！
三日坊主にならないように Qita でアウトプットしながら進めます💪

# 今日やること
[とほほのPython入門 - リスト・タプル・辞書](https://www.tohoho-web.com/python/list.html) のリスト関数(map(), filter(), reduce())を理解する。

# map()
`map()` はリストの各要素に対して処理を行い、行った結果を返します。
下記の例では各要素を2倍にする処理を行います。

```py
a = [1, 2, 3]

def double(x): return x * 2

print(list(map(double, a)))                  #=> [2, 4, 6] : 関数方式
print(list(map(lambda x: x * 2, a)))         #=> [2, 4, 6] : lambda方式
print([x * 2 for x in a])                    #=> [2, 4, 6] : 内包表記(後述)
```

`list()` はリスト型に型変換するための標準関数です。
なんで変換してるのかなぁと思って調べたら、`map()` は mapオブジェクトを返却するようです。
JavaScript の `map()` みたいにリストを返却するのかなって思ってましたが、Python は違うようですね。

# filter()
`filter()` はリストの各要素に対して処理を行い、処理結果が真となる要素のみを取り出します。
下記の例では各要素から奇数のみを取り出します。

```py
a = [1, 2, 3]

def isodd(x): return x % 2
print(list(filter(isodd, a)))              #=> [1, 3] : 関数方式
print(list(filter(lambda x: x % 2, a)))    #=> [1, 3] : lambda方式
print([x for x in a if x % 2])             #=> [1, 3] : 内包表記(後述)
```

# reduce() 
`reduce()` はリストの最初の2要素を引数に処理を呼び出し、結果と次の要素を引数に処理の呼び出しを繰り返し、単一の結果を返します。
下記の例では、各要素の合計を計算しています。

```py
from functools import reduce

a = [1, 2, 3, 4, 5]

def add(x, y): return x + y
print(reduce(add, a))                  #=> 15 : 関数方式
print(reduce(lambda x, y: x + y, a))   #=> 15 : lambda方式
```

# 感想
今日はリスト関数をやってみました！

今回も見ていただきありがとうございました。
また次回お会いしましょう！！

# 次回やること
[とほほのPython入門 - リスト・タプル・辞書](https://www.tohoho-web.com/python/list.html) のリストの内包表記を理解する。
統計検定1級　2021　統計数理　問4　解説

![img20250304_09195238.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/71398fe7-3073-4c80-831e-ca51aa9b730f.jpeg)
![img20250304_09205636.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/89306e7f-027e-46fc-98c0-c9b3a6900df1.jpeg)
![img20250304_09213612.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3576811/c1164ca3-c485-47a5-8287-d05c943f6d12.jpeg)
【PC時短スキル】ムダな操作をしたくない！マウスホイール活用

# はじめに
ノベルワークスの[つつみん](https://x.com/tsutsumin_38)です！
最近身につけた時短スキルを備忘録として記録しておきたいと思います！
# こんな人にみてほしい
- windows使用していて、ブラウザで必要なタブを一気に開きたい
- マウスを使用している方
- 繰り返し作業が嫌いな方
- かっこよくスマートにタブを操作したい方
# 背景
毎朝、始業時にchromeで必要なタブをひとつずつ開いていたけど、なんだかめんどくさいし、繰り返し作業になっていると感じた。
一日の中で、タブに関する作業が結構多いと思ってスマートに操作したいと思った。

## タブの操作にマウスのホイールクリックが便利
### ウオーミングアップ　新しいタブでリンクを開くことができる！
Google 検索で、気になるリンクをポチポチと**ホイールクリック**しておくと、新しいタブで表示させておくことができる！

<img width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957410/7f5ae003-5cc7-4856-9751-033f0e7ee224.png">

![2025-03-06_00h18_32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957410/62b70e30-c037-427a-b189-6fa5efbaad6c.png)

![2025-03-06_00h22_39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957410/243fcb83-9d2b-41c3-ae7f-af89223ce380.png)

:::note info
Google 検索をしたときに、気になるリンクをすべて先に開いておいて、後で順番にまとめて内容を確認するという調べ方に使える！！
:::
ちなみに開いたタブの上でホイールクリックすると、タブを閉じることもできます～！

便利～～:clap:

### 本題　ブックマークバーのフォルダからまとめて表示できる！
**ブックマークバーのフォルダ**と、**ホイールクリック**を使うと、
![2025-03-06_00h30_26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957410/6cbeab18-377f-4add-a21f-cad1f709b2d1.png)

![2025-03-06_00h31_17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3957410/8caa35ba-2de1-4d0e-ba3f-8fdb40c42a64.png)

フォルダに入れたサイトが一気に開く～～～！！いちいちポチポチしなくてワンクリック！
（ブックマークをひとつのフォルダにまとめておく必要はあるけど）

これで毎朝の作業が時短になった！！

便利～～～:clap::clap:

# おわりに
他の人のPC操作をまじまじと見たり、学ぶ機会はないけど、画面共有とかで、あの人の操作スマートだなと思うことはある。私はいつも「ちょっと待ってくださいねー、あれ？？」とか言ってるので、改善していきたい。マウスのホイールはスクロールする時にしか使用してなかったけど、これから活用していきたいです！
ムダな操作を減らすようなちょっとしたスキルを身につけてスマートな操作をしたいと思います！！！
初心者向けJIS X 8341-3ガイド｜アクセシビリティ対応サイト制作の流れ

アクセシビリティ対応のサイト制作は、全てのユーザーにとって使いやすいウェブ環境を実現するための重要な取り組みです。本記事では、JIS X 8341-3の基本概念から実装例、制作プロセスまで、現役エンジニアとしての視点から具体的に解説していきます。  

## はじめに  
JIS X 8341-3は、障害の有無や年齢に関わらず誰もがウェブコンテンツを利用できるように定められた日本産業規格です。
ここでは、技術ポイントやチェックリスト、コード例を交えて、プログラマーやエンジニア初心者にも分かりやすく解説します。  

## JIS X 8341-3 の概要  
- **定義**:  
  JIS X 8341-3は「高齢者・障害者等配慮設計指針」の第3部であり、ウェブアクセシビリティの達成基準を「知覚可能」「操作可能」「理解可能」「堅牢」という4原則に基づいて定めています。  

![スクリーンショット 2025-03-06 8.39.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637864/f6024785-0f2c-4c62-b01b-9c82c1b1e936.png)


- **適合レベル**:  
  適合レベルはA、AA、AAAの3段階があり、一般的にはAA以上の適合を目標とすることが望まれます。  

- **ポイント**:  
  実装の際には、画像のalt属性設定、キーボード操作のサポート、コントラスト比のチェック、そして適切な文書構造の確保などが求められます。  

## サイト制作のプロセス  
アクセシブルなサイト制作は、以下のフローに沿って進めると効果的です。  

```
+--------------+      +------------+      +-------------+
| 企画・設計   | ---> |  実装・検証  | ---> |  リリース   |
+--------------+      +------------+      +-------------+
```

- **企画・設計** 🚀  
  - 制作の目的や対象ユーザー、コンテンツの範囲を明確にします。  
  - アクセシビリティ向上のためのチェックリストを作成し、必要な技術要求を整理します[8]。  

- **実装・検証** 🔍  
  - 設計に沿って、セマンティックなHTMLやCSS、ARIA属性などを活用して実装します[1]。  
  - 自動チェックツールや手動テストでアクセシビリティレベルの確認を行います[4]。  

- **リリース** 🎯  
  - 全体の検証が完了したら、定期的な運用や改善サイクルを回し、常に最新の基準に沿ったサイトを保守します。  

## 実装の具体例  
具体的なコード例を見てみましょう。以下は、シンプルながらもJIS X 8341-3のポイントを押さえたHTMLテンプレートです。  

```html



  
  アクセシブルなサイト例
  
    /* シンプルなスタイル */
    body { font-family: Arial, sans-serif; line-height: 1.6; background-color: #fff; color: #333; }
    .nav { background-color: #f8f8f8; padding: 10px; }
    a { color: #005a9c; text-decoration: none; }
    a:focus { outline: 2px solid #ffbf47; } /* キーボード操作時のフォーカス表示 */
  


  
    
  
  
    
      ホーム
      会社概要
      お問い合わせ
    
  
  
    アクセシブルなウェブサイトの作り方
    このサイトは、JIS X 8341-3 のガイドラインに基づき制作されています。画像やリンク、ナビゲーションに関する各要素を最適化することで、誰もが快適に利用できる設計を実現しています。
  
  
    &copy; 2025 企業名
  


```

このサンプルでは、以下の点に注意しています:  
- **alt属性の設定**: 画像には必ず内容を説明するテキストを設定  
- **キーボードフォーカスの明確化**: フォーカス時に視覚的な変化を実装  
- **セマンティックなマークアップ**: header、nav、main、footerの各要素で構造を明確化 

## アクセシビリティチェックのポイント  
実装後は以下の項目を重点的にチェックしてください。  

- **画像のalt属性**  
  → 画像情報がテキストとして伝わるかを確認  
- **キーボード操作**  
  → 全ての操作がキーボードだけで可能かを検証  
- **色のコントラスト**  
  → 文字と背景の色の比率を十分に確保する（通常は4.5:1以上）  
- **文書構造**  
  → 見出しやリスト、ナビゲーションが正しくマークアップされているか  
- **ARIA属性の活用**  
  → 補助技術での利用を想定し、必要な場合は適切なroleやラベルを設定[1]  

## ツールの活用  
最近では、アクセシビリティチェックを自動化するツールも充実しており、たとえば以下のようなツールが活用できます。  

- **PowerCMS 8341**: CMS上でJIS X 8341-3準拠のチェックや自動修正を支援するプラグインです。  
- **ブラウザ拡張機能**: ChromeやFirefoxのアクセシビリティ検査ツールを使うと、リアルタイムで問題点が検出できます[3]。  

詳細なチェックリストや検証方法については、関連するガイドラインや技術要求書を参照してください。  

## まとめ  
本記事では、JIS X 8341-3に基づいたウェブサイト制作のプロセスと実装の具体例を解説しました。アクセシビリティ対応は、ユーザー体験の向上に直結する重要な要素です。計画段階から実装、テスト、運用まで一貫して取り組むことで、全てのユーザーに優しいウェブサイトを構築できます👍

アクセシブルなサイト制作への取り組みで、あなたのプロジェクトにもさらなる価値が加わることを期待しています🚀

---

### 最後に：業務委託のご相談を承ります

私は、業務委託エンジニアとしてWEB制作やシステム開発を請け負っています。最新技術を活用し、レスポンシブなWebサイトやインタラクティブなアプリケーション、API連携など、幅広いニーズに対応可能です。

「課題解決に向けた即戦力が欲しい」「高品質なWeb制作を依頼したい」という方は、ぜひお気軽にご相談ください。一緒にビジネスの成長を目指しましょう！

👉 [ポートフォリオ](https://yushiyamamoto.vercel.app/)

🌳 [らくらくサイト](https://rakuraku-site.prodouga.com/)
OMCB036D(983,組合せ)

https://onlinemathcontest.com/contests/omcb036/tasks/9657

この記事では、解を導いた方法(考え方)は示していますが、証明はできていません。

ひとまず$100$以下の素数を大きい順に$10$個取ります。
$S=97+89+83+79+73+71+67+61+59+53=732$
$S$で使っている素数の集合を$P$とします。
この時点で$P$は$S$と同じです。
$P=\lbrace97,89,83,79,73,71,67,61,59,53\rbrace$

$53$を$100$に置き換えます。
$S=100+97+89+83+79+73+71+67+61+59=779$
$P=\lbrace97,89,83,79,73,71,67,61,59,5,2\rbrace$

$59$を$99$に置き換えます。
$S=100+99+97+89+83+79+73+71+67+61=819$
$P=\lbrace97,89,83,79,73,71,67,61,11,5,3,2\rbrace$

$98,96,95,94,93,92$は$100,99$と素ではないです。

$61$を$91$に置き換えます。
$S=100+99+97+91+89+83+79+73+71+67=849$
$P=\lbrace97,89,83,79,73,71,67,13,11,7,5,3,2\rbrace$

これ以上は大きい数を置き換えられなくなったので、今、置き換えた数を別の数にすることで、更に置き換えができないか考えてみます。
$2,3,5,7$は、それぞれ$50,33,20,14$以下の数とかけても$100$以下になります。
$100$は素数$2,5$の組み合わせなので、$2,5$をそれぞれ別の数と組み合わせて、$100+67$より大きくなる$2^☆×○$と$5^{□}×△$がないか探します。

$2×47,5×19$とすることで、それぞれ$94,95$が得られ、$94+95>100+67$になります。
ここでは$2,5$とかけても$100$以下になる素数を探して割り当てました。

$S=99+97+95+94+91+89+83+79+73+71=871$
$P=\lbrace97,89,83,79,73,71,47,19,13,11,7,5,3,2\rbrace$

これ以上は大きくならなそうです。
久しぶりにWindowsへSQL*Plusをインストールしようとしたら罠にハマった話

# はじめに
Oracle Databaseに接続するCLIベースのクライアントは最近専らSQLclを使用していたのですが、諸般の事情によりSQL*Plusをインストールする必要になりました。
インストール作業はOracle Database 12cの頃以来だったのですが、当時と手順はさして変わらないだろうと思って臨んだら、思わぬ罠にハマってしまいましたので、備忘録として残します。

# クライアント端末の環境

Windows 11 Pro 22H2

# 誤った手順

https://edelivery.oracle.com/osdc/faces/SoftwareDelivery

1. 上記「Oracle Software Delivery Cloud」で「Oracle Database Client 23」と検索し、「Oracle Database Client 23.5.0.0.0」を選択、ダウンロード実行
※要Oracleアカウント
1. 前項でダウンロードしたexeファイル（ダウンロードマネージャ）を実行し、S/Wのzipファイルをローカルにダウンロードする
1. 前項でダウンロードしたzipファイルを解凍する
1. 解凍したファイルを開き、フォルダ内の「setup.exe」を実行する
1. Oracleホームのユーザー選択画面で「Windows組み込みアカウントの使用」（デフォルト）を選択し「次へ」ボタンをクリック
**この時点で不穏な臭いを感じる**
🤔Oracleホーム...？JAVA_HOMEはよくいじる環境変数だけど、ORACLE_HOMEなんて環境変数触ったことないぞ...？
1. Oracleベースのフォルダに適当なパスを設定し、「次へ」をクリック
1. 「選択したOracleホームはOracleベースの外部に設定されています。」と怒られる。いったん無視して「はい」ボタンをクリックして続行
**ハマった罠。警告を無視してはいけない**
1. サマリー画面が表示される。「インストールボタン」をクリック
1. 「Oracle Clientのインストールが成功しました。」と表示されるので、インストーラを閉じる
1. コマンドプロンプトを起動し`sqlplus -v`でパスが通っていることを確認
1. 前項「6.」でインストールしたフォルダを起点にtnsnames.oraを格納するadminフォルダを探すが、見つからない
**罠の終点**

上記サイトでダウンロードできるクライアントは、 **Oracle Databaseがインストールされた端末向けの** インストーラでした。
そもそも、最初のステップから全く違いました。

# 正しい手順

https://www.oracle.com/jp/database/technologies/instant-client/downloads.html

1. 上記URLから「 Instant Client for Microsoft Windows (x64)」のリンクをクリック
1. Basicパッケージ「instantclient-**basic**-windows.x64-**バージョン**dbru.zip」のリンクをクリックしてダウンロード
1. SQL*Plus パッケージ「instantclient-**sqlplus**-windows.x64-**バージョン**dbru.zip」のリンクをクリックしてダウンロード
1. 「instantclient-**basic**-windows.x64- __バージョン__ dbru.zip」を任意のフォルダで解凍し、フォルダ名を「client」にリネーム
※フォルダのリネームは省略してもOKです。ここでは以降の説明を簡易にすることを目的としてリネームしています。
1. 「instantclient-**sqlplus**-windows.x64-**バージョン**dbru.zip」を解凍
1. 前項で解凍したフォルダ内の下記ファイルをすべてコピー or 切り取り
    * glogin.sql
    * Orasqlplusic.dll
    * sqlplus.exe
    * sqlplus.sym
1. 「client\instantclient_**バージョン番号**」フォルダへ前項でコピーしたファイルをペースト
1. 「client\instantclient_**バージョン番号**\network\admin」フォルダ内にtnsnames.oraを作成・格納
1. 「client\instantclient_**バージョン番号**」を環境変数`PATH`に追加

あとは以下のようにコマプロから起動するだけです。
```plaintext:cmd
sqlplus scott/tiger@dbname

SQL*Plus: Release 21.0.0.0.0 - Production on aaa mon d hh:mi:ss yyyy Version 21.9.0.0.0

Copyright (c) 1982, 2022, Oracle.  All rights reserved.

Last Successful login time: aaa mon dd yyyy hh:mi:ss +09:00

Connected to:
Oracle Database xxx Release xx.x.x.x.x - Production Version x.x.0.0.0

SQL>
```

# まとめ

バイナリをダウンロードして解凍するだけになったので、レジストリの汚染を気にせずとも良くなった点と、やたらめったらサイズの大きいファイルをダウンロードする必要も無くなったので、作業の流れさえ覚えてしまえば現行手順も悪くないと感じました。
ただ、SQL*Loaderを使う必要がないのであれば、SQLclで事足りてしまうんだよなぁ...
NEC TK-80 と HSP製プログラム（ 日本国産の 端末 OS プログラム言語 応援 ）

## 追記：　ワンボードマイコン関連ニュース

https://x.com/toshitada1973/status/1934979615182975351

https://x.com/hortense667/status/1924984554517103000

https://x.com/Dream_Library_/status/1925899413173469559

https://x.com/pc_watch/status/1912253119205183863

## NECのTK-80 と HSP

きょうネット上でこのような記事を見かけました。

https://x.com/pc_watch/status/1896308002875150583

日本国産プログラミング言語に『 HSP 』というものがあります。

https://ja.wikipedia.org/wiki/Hot_Soup_Processor

この HSP（HSP3）で作られた「TK-80をエミュレーションするプログラム」や「TK-80のシミュレータ」があるので紹介したいと思いました。
　
　
**『 あまのじゃくんVer1.0 』**  TK-80シミュレータ用の逆アセンブラ
**『 .tk8ファイルの16進表示 』** TK-80シミュレータのプログラム（バイナリ）16進表示

JH7UBC さんのサイト

http://jh7ubc.web.fc2.com/hsp/hsp.html

***
 
**『 Gocaine TK-80 Z80 』**

https://dev.onionsoft.net/seed/info.ax?id=2437

開発者の hirokirepo さん は
**CP/Mエミュレーター**
**Z80エミュレーターモジュール**
**Z80逆アセンブラー**
**8080 to z80アセンブリコンバーター**
さまざまなプログラムを HSP3で開発しています。

https://dev.onionsoft.net/seed/info.ax?user=868

2025年4月7日 追記：
hirokirepo さん は
**PC-8001/PC-8801エミュレータ**
**AArch64のWineでx86(i386) ABIのアプリを動かすエミュレータ**
も開発されています
**GitHub 開発者ページ　hiroki-repo**
https://github.com/hiroki-repo
　

## HSPプログラミングは 電子工作にもつかえます

HSPは
USB-IO
Arduino
Raspberry Pi
GPIO
とつなげて電子工作を制御することもできます
↓ HSP電子工作のリンク

https://junji.jp/net/hsp3/#電子工作プログラミング

## ワンボードマイコン 関連記事
　NEC　SHARP　富士通　日立　

https://x.com/avwatch/status/1675667513261301761

https://x.com/oec_Nibbleslab/status/1900727066234159187

https://x.com/pc_watch/status/1901381559254655232

https://x.com/pc_watch/status/1898844362601373870

https://x.com/pc_watch/status/1903918116436156599

参考：大阪市立科学館 ワンボードマイコンとは？

https://www.sci-museum.jp/wp-content/themes/scimuseum2021/pdf/study/universe/2021/06/202106_20.pdf

https://x.com/Dream_Library_/status/1893107450540368100

---


私（ すずきじゅんじ ）は普段から「 日本国産の 端末 OS プログラム言語 」を応援する活動をしていて、先日書いた記事もたくさんのひとが見てくださいました。（読んでくださってありがとうございます。）

きょうこの TK-80 の記事を読んだのもなにかの縁だと思い、点と点をむすんで紹介する記事を書いてみた次第です。

https://qiita.com/Junji_Suzuki_JBOYSOFT/items/a87101f83ddc607fe7d5

## 日本国産の 端末　OS　言語　応援ページ

https://junji.jp/net/hsp3/msx-japan/

1970年代から1990年ごろまでは、日本国内のパソコンはほぼすべて日本国産製品でした。
いまの若い人たちはそのことを知らないだけでなく、「そのことを信じられない」「想像できない」という言葉もきいたりします。

日本には、自分たちの力で価値ある高度な製品を生み出す、つくりだす技術と力があったし、それがいまなおある、と私は思います。
足りないものがあるとすれば、それは「気持ち」「心持ち」ではないかと、私は考えています。
SQLite3でデータベースを作成するPythonコード

SQLite3でデータベースを作成するPythonコード
 
import sqlite3

# データベースファイル名
dbname = 'mydatabase.db'

# データベースに接続 (ファイルが存在しない場合は新規作成)
conn = sqlite3.connect(dbname)

# カーソルオブジェクトを作成
cur = conn.cursor()

# テーブルを作成 (既に存在する場合は何もしない)
cur.execute('''
    CREATE TABLE IF NOT EXISTS users (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        name TEXT NOT NULL,
        age INTEGER,
        email TEXT UNIQUE
    )
''')

# 変更をコミット (データベースに反映)
conn.commit()

# 接続を閉じる
conn.close()

print(f'{dbname} データベースと users テーブルが作成されました。')


データベースの中に、テーブルは複数存在できる。

データベースを作って、
カーソルオブジェクトをつくる。

cur.execute(...): SQL文を実行します。

CREATE TABLE IF NOT EXISTS users: users テーブルを作成します。既に存在する場合は何もしません。
id INTEGER PRIMARY KEY AUTOINCREMENT: id 列を整数型、主キー、自動増加に設定します。
name TEXT NOT NULL: name 列をテキスト型、必須項目に設定します。

age INTEGER: age 列を整数型に設定します。

email TEXT UNIQUE: email 列をテキスト型、一意制約に設定します。

conn.commit(): 変更をデータベースに反映します。

conn.close(): データベース接続を閉じます。

print(...): データベースとテーブルが作成されたことを出力します
M5StampS3、スタックチャンで文字列を表示して遊ぶ。



注意、いろいろ
----

- 過去ログを見よ!!!
- 3.1.3
- 「絶滅メディア博物」「スタックチャンフェス」



結果
---


![image_original (53).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/023ad7ab-2536-4eff-bc97-891daf9b34af.jpeg)


プログラム
----


```c++


//balloon_1_M5StampS3_1


//インクルド
#include <M5UnitGLASS2.h>
#include <M5Unified.h>
#include <Avatar.h>


//定義
using namespace m5avatar; //ネームスペース

Avatar avatar; //アバターの実体の定義
const char* lyrics[] = {"やん坊","まん坊","天気予報"};//ポインター配列
const int lyricsSize = sizeof(lyrics) / sizeof(char*);//配列の個数
int lyricsIdx = 0;//カウンター


//初期化
void setup(){

  auto cfg=M5.config();
  cfg.unit_glass2.pin_sda=13;
  cfg.unit_glass2.pin_scl=15;
  M5.begin(cfg);//M5の初期化

  avatar.setScale(.45);
  avatar.setPosition(-88-17,-96);
  avatar.init();//アバターの初期化 (アバターは、バックグランドで動く)

  //avatar.setSpeechFont(&fonts::lgfxJapanGothic_12);//日本語フォント
  avatar.setSpeechFont(&fonts::lgfxJapanGothicP_16);//日本語フォント

}//setup


//メインループ
void loop(){

  //M5.update(); 
  //if (M5.BtnA.wasPressed()){//ボタンが押された場合

    //lyricsIdx++は、後で1プラスする
    //余りを求める処理は、0から文字列のポインター配列サイズぶん繰り返す
    //「l」に文字列のポインターが入る
    const char* l = lyrics[lyricsIdx++ % lyricsSize];

    avatar.setSpeechText(l); //テキストの表示

    avatar.setExpression(Expression::Happy); //表情を変える

    avatar.setMouthOpenRatio(0.7); //口を動かす

    delay(200);//0.2秒待つ

    avatar.setMouthOpenRatio(0); //口を閉じる

  //}//if

  delay(3000);//3秒待つ

}//loop



```

・

・

・

おまけ(元のサンプル)
----

```c++

#include <M5Unified.h>
#include <Avatar.h>

using namespace m5avatar;

Avatar avatar;
const char* lyrics[] = {"Hey,",     "diddle,",     "diddle,",        "The cat",
                         "and",      "the fiddle,", "The cow",        "jumped",
                         "over",     "the moon.",   "The little dog", "laughed",
                         "to",       "see",         "such sport,",    "And",
                         "the dish", "ran away",    "with the spoon."};
const int lyricsSize = sizeof(lyrics) / sizeof(char*);
int lyricsIdx = 0;

void setup()
{
  M5.begin();
  avatar.init();
}

void loop()
{
  M5.update();
  if (M5.BtnA.wasPressed())
  {
    const char* l = lyrics[lyricsIdx++ % lyricsSize];
    avatar.setSpeechText(l);
    avatar.setMouthOpenRatio(0.7);
    delay(200);
    avatar.setMouthOpenRatio(0);
  }
}


```
.NET、ASP.NETの違いに関する備忘録【2025.3】

## .NETとは
　Microsoft社が開発・提供する「さまざまな種類のアプリケーションを開発するためのクロスプラットフォーム」である。C#を中心とした複数の言語で記述されたプログラムを実行できる。
　広義には、.NETで使用される言語や関連する概念、過去に存在した.NET Frameworkや.NET Coreといった概念をひっくるめて.NETと呼んだりしている。
 
### .NETでビルドできるアプリの種類
 - Web
 - モバイル（iOS, Android）
 - デスクトップ
 - 人工知能
 - クラウド
 - マイクロサービス
 - ゲーム
 - IoT

## ASP.NETとは
　.NETを使用したオープンソースのwebフレームワーク。ASPはActive Server Pagesの略で、動的なwebページを作成することができる。

## ASP.NET Coreとは
　macOS、Linux、および Windows 上で実行される ASP.NET のオープンソースバージョン。以前の Windows 専用バージョンの ASP.NET を再設計したもの。
 ASP.NET Core より前に存在していた Windows のみのバージョンの ASP.NET は、通常、単に ASP.NET と呼ばれる。

### ASP.NET Core Blazorとは
　C#のみでweb UIを開発することができるフレームワーク。フロントエンドからバックエンドまでC#のみで開発することができる。

### ASP.NET Core Razor Pagesとは
　 ページ指向のwebアプリケーションフレームワーク。ページ指向とは、ひとつのページにひとつのソースファイルが対応し、フォルダの構造がそのままサイトの構造になっているもの。MVVMパターンに準拠しているとも言われる。

#### MVVMパターンとは
  データ処理を扱うモデル（Model：M）とUIを担うビュー（View：V）の間にビューモデル（ViewModel：VM）が介在している。ビューとビューモデルの間は双方向のデータバインド（表示上の項目とデータ上の項目を結び付けること）という仕組みで、相互にデータの反映を行うようになっている。

### ASP.NET Core MVCとは
　MVCパターンに基づいたwebアプリケーションフレームワーク。ASP.NET Core と共に使用するために最適化された、ライトウェイトかつオープン ソースのテストしやすいプレゼンテーション フレームワーク。

 #### MVCパターンとは
 アプリケーションの構成要素をモデル（Model：M）、ビュー（View：V）、コントローラ（Controller：C）に分割し、それぞれが独立して協調しながら動作する。モデルはデータ処理、ビューはUIの構築、コントローラは要求の振り分けを行う。
Jestを実行すると`An update to Page inside a test was not wrapped in act(...).`のWarningが出た

# はじめに
Jestでテスト実行したところ、`An update to Page inside a test was not wrapped in act(...).`のWarningが出ました。
原因は書いてある通り、**Reactのステート更新時には`act`でラップをする必要がある**ようです。

```
    An update to Page inside a test was not wrapped in act(...).
    
    When testing, code that causes React state updates should be wrapped into act(...):
    
    act(() => {
      /* fire events that update state */
    });
    /* assert on the output */
    
    This ensures that you're testing the behavior the user would see in the browser. Learn more at https://react.dev/link/wrap-tests-with-act
```
# actとは
公式ドキュメントには下記の説明がありました。
>`act`は、アサーションを行う前に保留中の React の更新を適用するために用いるテストヘルパです。

https://ja.react.dev/reference/react/act

超ざっくりですが、**`act`でラップした処理が実DOMに反映されるまでは、次の処理の実行を待ってくれる**といった認識です。

**`act`は以下のような場合に使用します。**

・Reactの状態更新（useStateやuseReducer）が発生する操作をテストする時
・コンポーネントの初期レンダリング時（特に非同期処理がある場合）
・useEffectの実行時
・イベントハンドラの実行時
・APIコールなどの非同期処理

**注意点としては下記です。**

・公式では`act` を`await`および`async`関数と一緒に使用することを推奨している
・ステートが非同期で更新されるケースは`act`では対応できない
・React Testing Library を使えば`act`は不要

# おわりに
普段はReact Testing Libraryを使っていたので、今回このようなWarningに初めて遭遇しました。いちいち`act`を使っているとコードの記述量が増えてしまった印象があるので、React Testing Libraryのありがたみに気づきました。

# 参考
actの挙動について図とともに詳しく解説されています。

https://oisham.hatenablog.com/entry/2024/01/18/150850
AWS IoTルールのSQLでMQTTのJSONプロパティ名が特殊な場合の参照方法

# はじめに

AWS IoT Coreのルールで使うSQLにおいて、MQTTのJSONプロパティ名（フィールド名）が特殊な場合の参照方法を紹介する。

# 動作環境
* AWS IoT SQLルールエンジン
  * バージョン：2016-03-23 

# 方法

以下のような特殊な要素を含むJSONプロパティ名を参照する場合は、[get関数](https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html#iot-sql-function-get)を使う。
 * ```.```（ドット）
 * ```-```（ハイフン）
 * 数字

## 例

```json:特殊なJSONプロパティを含むMQTTの例（トピック名：my/topic/）
{
   "serial.no": "00001",
   "item1" : {
     "0": {
       "my-key": "myValue"     
     }
   }
}
```

上記のMQTTトピックから、```serial.no```と```my-key```を抽出するSQLは以下となる。

```sql:AWS IoT SQL
SELECT
  get(*, 'serial.no') AS serial_no
  get(get(get(*, 'item1'), '0'), 'my-key') AS my_key

FROM 'my/topic'
```

結果
```json
{
   "serial_no": "00001",
   "my_key": "myValue"
}
```

# まとめ

AWS IoT Coreのルールで使うSQLにおいて、MQTTのJSONプロパティ名（フィールド名）が特殊な場合の参照方法を紹介した。通常のSQLと参照方法が異なりget関数を使うことで参照できた。気づけないと、結構はまってしまうのでどなたかのお役に立ててればと思う。

# 参考

https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-json.html

https://docs.aws.amazon.com/ja_jp/iot/latest/developerguide/iot-sql-functions.html#iot-sql-function-get

https://dev.classmethod.jp/articles/iot-core-rule-use-get-method/

https://stackoverflow.com/questions/76665000/iot-rules-select-property-with-name-0

https://stackoverflow.com/questions/74443684/writing-the-correct-sql-statement-in-aws-iot-rule
webhookに関する備忘録

## webhookとは何か？
Webhook（ウェブフック）とは、特定のイベントが発生した際に、アプリケーション間でデータを自動的に送信する仕組みです。HTTP プロトコルを使用して実装され、リアルタイムで通知を受け取る必要性があるアプリケーションやサービスに適しています。﻿
　→サーバ側から通知が自動的に届くような仕組み

### webhookの仕組み
1. 送信元のサービスでデータの追加などの「きっかけ」が発生する
1. 「きっかけ」により、指定した「宛先（URL）」へのHTTP通信が発生する
1. 指定した「宛先」へデータを送信できる

### webhookの活用例
- GitHub のプロジェクト状況や PR のリクエスト通知を Slack などのコミュニケーションアプリで受信する。﻿
- ToDoアプリにレコードを追加したときに、メールやチャットで通知を受け取る。﻿
- 投稿管理アプリのレコードのステータスが「承認」になったとき、レコードの内容を SNS に投稿する。﻿

### webhookの注意点
- 悪意を持ったユーザーが不正なリクエストを送ることで、誤った情報を受け取ったり、悪意のある操作が行われる可能性がある
- ユーザーからのリクエストが暗号化や認証の手段で保護されていない場合、個人情報が漏洩するリスクもある

### APIとの相違
|| webhook | API |
|----| ---- | ---- |
|通信方式|プル型|プッシュ型|
|通信コスト|低|高|
|トリガ|自動的|能動的|
|方向|一方向|双方向|
|事前設定|通知先を設定|なし|
|セキュリティ|認証機能なし|認証機能あり|

以上
競プロ日記#25/03/05

# AtCoder
## 三井住友信託銀行プログラミングコンテスト2019:[B-Tax Rate](https://atcoder.jp/contests/sumitrust2019/tasks/sumitb2019_b)
- 公式解説によると以下の2つの解法があるらしい。
1つ目の全探索は考えもしなかった。

1. 解法 1 - 「全探索で答えを見つける」
2. 解法 2 - 「計算で答えを決め打ちする」

- 解法2の方に近いものを考えたが、例えばNが1001の場合
```
int X;
X = N / 1.08;
```
でXを求めても切り捨てられるために926となる（答えは927）
切り捨てるという性質を考慮して+1することも考えたが割り切れる場合に困る（ガウス記号的な概念が欲しい）
無理やり実装できないこともなかったが、正攻法的なしっくりした解法が思いつかなった。
→結局正攻法のようなものはないわけで、以下の解説の様に決め打ちした値前後で正解を探す方法がよさそう。

>アップルパイの税抜き価格を X とすると、税込み価格は X × 1.08 を整数で切り捨てた値です。これが N
円になるためには、N ≤ X × 1.08 < N + 1 が条件となります。
ここで、条件の値を全部 1.08 で割ってみると、 N
1.08 ≤ X < N+1
1.08 となります。ですので、 N
1.08 以上 N+1
1.08
未満に整数があるならこれが税抜き価格となり、なければ税抜き価格としてありうるものがない、ということ
が分かります。
例えば、N = 1001 の場合、926.851851… ≤ X < 927.777777… となるので、税抜き価格が 927 円である
ことが分かります。税抜き価格を 「 N
1.08 を整数に切り上げた値」 と決め打ちして、税込み価格が N に一致す
るかどうかを判定する、というような実装もできます。

# アルゴ式-[1 円玉と 5 円玉](https://algo-method.com/tasks/359)
- 以下の様に1円玉の枚数を求める時にN（円）から5円玉の枚数 * 5で5円玉で払った金額を引いてたが解説によると
> 1 円玉で、N % 5 枚支払う（N % 5）

```
int N;
cin >> N;

int count5, count1;
int ans = 0;

count5 = N / 5;
count1 = N - count5 * 5;

ans = count1 + count5;
```
# アルゴ式-[コインの問題](https://algo-method.com/tasks/360)
- ここに残せないくらいしょうもない実装になってしまった。
if文を列挙するというとても賢くないやり方。解説ではコインが4枚のため4回ループのfor文で、コインの枚数制限がない場合の枚数を最初に出して、それを実在する枚数とmin関数で比較する方法を取ってた。とても賢い。
for文で回してるが残り金額Xが0になった場合もaddが0になるのでその後のmin関数できちんと弾ける
```
for (int i = 0; i < 4; ++i) {
    // コインの枚数制限 (A[i] 枚) がないときの枚数
    int add = X / coins[i];
    
    // 枚数制限を考慮してコインの使用枚数を求める
    add = min(add, A[i]);
    res += add;
    
    // 残り金額を求める
    X -= coins[i] * add;
}
```
リアルタイム同期できる掲示板NEARにお絵かき機能を追加しました！

こんにちは。

個人開発でWebアプリなどを作っているものです。

この度、開発中のリアルタイムに書き込み中のメッセージが表示される掲示板「NEAR」にお絵かき機能を追加しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4015962/9d142e00-bfd5-4fa0-ae92-3e0c5afe4317.png)

NEARはこちら

https://near-production.up.railway.app/

今回は、お絵かき機能（ホワイトボード機能）を追加した理由と開発の舞台裏を、ソースコードとともにご紹介します。リアルタイム掲示板の「NEAR」に、ただ文字を書き込むだけでなく、思いついたアイデアをササッとイラストで共有できる――そんなワクワクする機能をつけたい！という思いから、このお絵かき機能を開発しました。

## なぜお絵かき機能を追加しようと思ったのか
テキストベースのコミュニケーションは便利ですが、時に図やイラストを使った方が手っ取り早いときがあります。たとえば「細かいニュアンスをパッと絵で伝えたい！」とか、「ゆるキャラのラフをスケッチして見せたい！」なんて場面です。

そんなときに、いちいち外部ツールで絵を描いてアップロードするのは面倒。そこで、掲示板自体にホワイトボードを用意してしまおう！というわけです。

## 実装の流れ
#### 1. Canvasエレメントの配置
まずはHTMLに canvas タグを用意して、JavaScriptで描画できるようにします。

#### 2. リアルタイムで送信
描画中にもイベントが走るたびにホワイトボードの内容（Base64形式の画像データ）をサーバーに送信し、他のユーザーがどんな絵を描いているのかをリアルタイムに見られるようにしました。（負荷がすごそうｗ）

#### 3. ホワイトボードの表示/非表示の切り替え
通常のテキスト・チャットと同時に使うために、ボタン一つでホワイトボードを表示/非表示にできるようにし、使い勝手の良いUIを目指しました。

### ソースコードの一部
以下に、ホワイトボードをセットアップする箇所のコードを少しだけご紹介します。
```index.htmlの一部 (.js
function setupWhiteboard() {
  const categoryCanvas = document.getElementById('categoryWhiteboardCanvas');
  const threadCanvas = document.getElementById('threadWhiteboardCanvas');
  const categoryControls = document.getElementById('categoryWhiteboardControls');
  const threadControls = document.getElementById('threadWhiteboardControls');
  const categoryButton = document.getElementById('categoryWhiteboardButton');
  const threadButton = document.getElementById('threadWhiteboardButton');
  const categoryMessageInput = document.getElementById('messageInput');
  const threadMessageInput = document.getElementById('threadMessageInput');

  // 要素が存在しない場合は早期リターン（エラーを防ぐため）
  if (!categoryCanvas || !threadCanvas || !categoryControls || !threadControls ||
      !categoryButton || !threadButton || !categoryMessageInput || !threadMessageInput) {
    console.error('Some whiteboard elements are missing');
    return;
  }

  // 初期状態で非表示に
  categoryCanvas.style.display = 'none';
  threadCanvas.style.display = 'none';
  categoryControls.style.display = 'none';
  threadControls.style.display = 'none';

  // カテゴリビューとスレッドビューのホワイトボードを初期化
  setupWhiteboardInstance('category');
  setupWhiteboardInstance('thread');

  // カラーピッカーとブラシサイズの変更イベントをセット
  const categoryColorPicker = document.getElementById('categoryColorPicker');
  if (categoryColorPicker) {
    categoryColorPicker.addEventListener('change', (e) => {
      const ctx = categoryCanvas.getContext('2d');
      ctx.strokeStyle = e.target.value;
    });
  }
  // ... (残りも同様にthreadCanvasに対して設定)
}
```
この関数が「ホワイトボードをセットアップする」作業の中心部分です。使用するHTML要素が正しく存在するかどうかをチェックしたうえで、初期状態を非表示にし、色やブラシサイズを管理するためのイベントリスナーをセットアップしています。

## 実際の使い心地
ホワイトボードボタンを押すと、テキスト入力欄の上にキャンバスが表示され、マウスでお絵かきが可能になります。突然思いついたアイデアをサラッと描いて共有するのはもちろん、ちょっとした図やマインドマップをかんたんに共有できるのが便利かな？
スレッド内での話題に、「この部分ってどういうこと？」なんて話になると、ぱっと図解して見せられます！

## まとめ
リアルタイム掲示板にお絵かき機能を足すだけで、コミュニケーションの幅が一気に広がります。テキストオンリーではカバーしきれない情報を共有したり、リアルタイムで相手に表示されるので、どんな絵ができるかな？という楽しみ方など、自由に使ってください。

ちなみに開発中によく出たエラーは要素が未定義のまま呼ばれることが多かったことです。

今後はスタンプ機能や、描画のアニメーション再生機能なども追加して、もっと楽しく気軽に使えるサービスにしていきたいと思っています！

それでは＾＾
SaaS=Webアプリではない！？SaaSとWebアプリの決定的な違いを徹底解説

## SaaSとは
SaaSとはSoftware as a Serviceのことで、インターネット上でインフラ、OSに加えてアプリケーションまで提供するサービスのことを指します。
具体例としてはSNS、メールなどが挙げられます。

## Webアプリとは
Webアプリとはブラウザ上で動くアプリ全体のことを指します。
Web版のインスタグラムやWord、オンライン電卓などがこれに該当します。

## SaaSとWebアプリの違い
上の説明を見ると、SaaS=Webアプリではないかと思ってしまいますよね。
私はそう思いました。でもそうではないのです。
まずWebアプリはブラウザ上で動くアプリ全体のことを指します。
一方、SaaSはWebアプリの中でも、サブスクや有料プランなどで料金をいただいて運用するものを指します。
つまり無料のオンライン電卓はWebアプリではあるが、SaaSではないということになります。料金をいただいていないからですね。
以上よりWebアプリ=SaaSではないことが理解できたかなと思います。

### まとめ
WebアプリとSaaSの違いがわかりましたでしょうか？
同じだと思っていたためかなり目から鱗でした。
ぜひこの違いを覚えて帰っていただけたらと思いm
php sedコマンド

ファイルEUC-JPをUTF-8
sedコマンドとは
sedとはStream EDitorの略で、入力されたテキストデータを1行ずつ読み込んで指定した処理を適用して出力を行います。主に文字列の置換や抽出に用いられます。

```
<?php
$dir = "./templates";
 
// 既知のディレクトリをオープンし、その内容を読み込みます。
if (is_dir($dir)) {
    if ($dh = opendir($dir)) {
        while (($file = readdir($dh)) !== false) {
	  if(strpos($file, 'tpl')){
	  //if($file=='addlist.php'){
            echo "filename: $file : filetype: " . filetype($dir . $file) . "\n";
		exec ('sed -i -e \'s/EUC-JP/UTF-8/g\' ./templates/'.$file);
	  }
        }
        closedir($dh);
    }
}
?>
```
http://www.sns.ne.jp/support.php?entryid=20220227035131
VSCodeでArduino開発をしたいけど、手法が2つあってどっちを使ったらいいか分からない人への記事

# この記事を読むと…
- VSCodeでArduino開発をする2つの手法があることを知る
- PlatformIOとVSCode-Arduinoの違いとそれぞれの特徴が分かる

# 混乱の Arduino + VSCode 開発
みなさん、地球に生まれた人類なら一度は思ったことがあるでしょう。
「VSCodeでArduino開発をしたい！！！！！！！！」

インターネットで「Arduino VSCode」と調べると、大きく分けて2つの手法がヒットします。1つ目は **VSCode-Arduino拡張機能** を使う方法、2つ目は **PlatformIO** (こちらも拡張機能)を使う方法です。

今回は、これら2つの違いと特徴を説明します。

# リンク
**VSCode-Arduino**

https://marketplace.visualstudio.com/items?itemName=vscode-arduino.vscode-arduino-community

**PlatformIO IDE**

https://platformio.org/platformio-ide

# VSCode-Arduino vs PlatformIO
|項目|VSCode-Arduino|PlatformIO|
|:--:|:--:|:--:|
|形態|VSCode拡張機能|VSCode拡張機能|
|パブリッシャー|コミュニティ(かつてはMicrosoftだったが、現在はサポートが終了)|PlatformIO|
|ベース技術|Arduino CLI|PlatformIO Core|
|コード補完やエラー表示|△|〇|
|ボードへの書き込み|〇|〇|
|ArduinoIDEとの互換性|〇|✕|
|機能の豊富さ|△|〇|

### VSCode-Arduino
VSCode-Arduinoとは、 **Arduino IDEの各機能をVSCodeから使えるようにする拡張機能** です。

:::note
VSCode-Arduino拡張機能は、Arduino CLIというツールをVSCodeから使えるようにしています。Arduino CLIとは、Arduino IDEの各機能(コンパイル、書き込み、ライブラリ管理、ボードマネージャの管理…)をコンソール上から行えるツールです。

Arduino CLIを使って、Arduino IDEの機能をVSCode上から触れるようにしてあるわけです。
:::

ここでポイントなのは、 **プロジェクトの構造やツールチェインは、Arduino IDEと同じ** ということです。従って、VSCode-ArduinoはArduino IDEと互換性があります。

### PlatformIO IDE
PlatformIOは、オリジナルのツールチェインを使ってコンパイル、ビルド、Arduinoに書き込みを行います。
そのため、PlatformIOでは、 **プロジェクトの構造もツールチェインもArduino IDEと全く違います** 。従って、PlatformIOはArduino IDEと互換性はありません。

**Arduino IDEと並行する位置に存在するIDE** と考えてもらえると分かりやすいです。

# 具体的に何が違うの？
VSCode-ArduinoとPlatformIOではどんな差異があるのか、具体例の一部を紹介します。

### プロジェクトの構造
#### VSCode-Arduino
```
MyProject/
├── MyProject.ino
└── MyFunctions.ino  # ファイル分割する場合
```
#### PlatformIO IDE
```
MyProject/
├── .pio/
│   └── # 依存環境のソースなど
├── src/
│   └── main.cpp
└── platformio.ini  # 設定ファイル (依存環境などもここに記述)
```

### 文法
| 項目 | VSCode-Arduino | PlatformIO |
|:-:|:-:|:-:|
| #include \<Arduino.h\> | 不要 | 必要 |
| プロトタイプ宣言 | 不要 | 必要 |
| ヘッダファイル | 不要 | 必要 |
| 拡張子 | .ino | .cpp, .hpp, .c, .h, ... |
| std::vectorなどSTL機能 | ほぼ ✕ | ◯ |
| 例外処理 (try-catch) | ✕ | ◯ |

### ライブラリのソースの場所
#### VSCode-Arduino
バラバラ (Arduino IDEと一緒) です。
(Windowsだったら、 `..\Documents\Arduino\libraries\` や `..\AppData\Local\Arduino15\` など)

#### PlatformIO
プロジェクト内の、 `.pio\libdeps\` にまとまってる。
しかも依存環境の情報も設定ファイル (`platformio.ini`) に書き込まれる…！！

# 言語支援機能について
VSCode-ArduinoもPlatformIOも、あくまで **主機能はコンパイル、ビルド、書き込み** などになっています。(PlatformIOはプロジェクト管理などもできて高機能ですが)
従って、いずれを使う場合も、補完機能や静的解析(エラーの表示)などの言語支援機能は、Microsoftの公開している **C/C++** という別の拡張機能を使うことになります。

### PlatformIO IDEでは
PlatformIOでは、C/C++拡張機能はPlatformIOのインストール時に自動的にインストールされます。セットアップも完璧に行ってくれるので、**基本的にLSPがよわよわで困ることはありません**。補完や静的解析はバッチリ動作します。

### VSCode-Arduinoでは
VSCode-Arduinoは、あくまでArduino IDEの機能をVSCodeから使えるようにしたものに過ぎないので、C/C++のセットアップなどは行ってくれません。そのため、これは自分で行うことになります。

しかし、Arduino IDEはライブラリやフレームワークなど依存環境をPC中にバラバラに保存しています。従って、C/C++拡張機能をインストールしても、**かなり複雑な設定をしないと補完機能や静的解析はまともに動きません**。

# 結論
初学者の人 → **Arduino IDE** 
オススメ → **PlatformIO**
Arduino IDEとの互換性をどうしても保ちたい人 → **VSCode-Arduino**

# ちなみに
ESP32にはESP-IDFというのがあったり、他にも色々あったりしますが、使ったことがないので触れません。
仮想現実(VR)を作ることを仮想化と言う？いえ、クラウドでは違うんです。クラウドにおける仮想化を分かりやすく解説。

# 仮想化とは
コンピュータを動かすのに必要なOS、ハードディスク、メモリなどの部品をソフトウェアで置き換える技術のことを指します。
仮想化が用いられている具体例としては仮想サーバーが挙げられます。
仮想化技術を用いると、物理サーバー(実際に存在している実体としてのサーバー)上に複数のサーバーを仮想的に作成することができます。
サーバーを作成するときに必要な部品を仮想的に作成して仮想サーバーを作成しているということになります。

# 仮想化のメリット(仮想サーバーを想定)
まず仮想サーバーはメモリやストレージを容易に増減することができます。そのため必要になったら増やす、いらなくなったら減らすということができます。
また、仮想サーバーは複製や消去も容易です。
これが物理サーバーだったらどうなるでしょうか？
物理サーバーを1台増やす際、部品だけでもかなり高額でコストが非常に高くなってしまいます。また、不要になった時に処分するコストもかかるため非常にお金がかかります。
一方仮想サーバーだとコストをかけずに増減できるということです。

# まとめ
コンピュータの部品をソフトウェアで仮想的に作成することを仮想化技術という。これだけでも覚えていってください！
仮想化技術はかなり便利なのでぜひ実際に仮想サーバーに触れてみてください。
CircuitPythonで2Dコード リーダー SR-2000の模擬をしようとしてハマった話

# 要点
CircuitPython のコンソール入力を利用する際には **制御コードには気をつけろ！**　という話です。

# 背景

[KEENCE社製2Dコード リーダー SR-2000 ](https://www.keyence.co.jp/products/barcode/barcode-readers/sr-2000/)からシリアルポート接続を利用してバーコードデータを読み取るアプリを作成していました。

SR-2000をどこの環境で使えるわけでもないので、ラズピコ＋CircuitPythonを利用してダミー環境を用意することにしました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/8dd8f80e-af1d-4f5e-8c7c-c4f22973620e.png)

# 模擬したかったこと
2Dコード リーダー SR-2000のバーコード読み取り用ライトをONするには`LON`とう文字を送ります。OFFする場合には`LOFF`を送ります。
ここで文字のコマンドの前後にSTXとETXを付ける必要があります。
* STX:バイナリで0x02
* ETX:バイナリで0x03

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204268/82c1c4ba-f44b-4409-b3d6-50dc5fdbbf48.png)

```cs
private const string COMMAND_LON = "\x02LON\x03\r\n";   // <STX>LON<ETX>
private const string COMMAND_LOFF = "\x02LOFF\x03\r\n";   // <STX>LON<ETX>
```
このSrtingをシリアルポートで送信してON/OFFできていることを確認しまして、ではこれをラズピコで模擬しようとしました。

# CircuitPythonのコード

CircuitPythonの動作確認でTeratermによる手入力も行っていた為、制御文字を含む完全なチェックは不要とし、受信文字の中に`LON` と`LOFF`が含まれていることをもってLEDのON/OFFをして、バーコードリーダーのライトを模擬しました。

```python
def receive_task():
    if supervisor.runtime.serial_bytes_available:
        msg=input()
        print(msg)
        if "LON" in msg:
            LED_PIN.value = 1
        if "LOFF" in msg:
            LED_PIN.value = 0
```
上記のコードで、Teratermから`LON` `LOFF`を送って、まずは動作OK！
しかし、C#から制御文字を含むデータを送信するとうんともすんともで・・・
「改行コードを送ってないからか？？」とも色々悩みましたが、改行コードが原因ではありませんでした。

# 制御文字送信でCircuitPythonが反応しなくなった理由

何気に送ってしまっていたETXという制御コードですが`Ctrl+C`を押したのと同じ効果があります。

Hex|値|ctrl|説明
------|------|------|------
0x00|NUL|Ctrl+@|NULl（ヌル）
0x01|SOH|Ctrl+A|Start Of Heading（ヘッダ開始）
0x02|STX|Ctrl+B|Start of TeXt（テキスト開始）
0x03|ETX|Ctrl+C|End of TeXt（テキスト終了）
0x04|EOT|Ctrl+D|End Of Transmission（転送終了）
0x05|ENQ|Ctrl+E|ENQuiry（問合せ）

CircuitPythonにおいてはコンソール操作で以下のアクションが定義されています。
* `Ctrl+C` スクリプトの停止
* `Ctrl+D` スクリプトの再始動

つまり、送った制御コードでスクリプトが停止してしまい、先に進まなかったというオチでした。（T T）
drogon に hypodermic を組み込み（C++でDependency Injection）

## はじめに
drogon はC++によるフルスタックのWebフレームワークです。
サンプルコードはわかりやすさ優先と思われますが，コントローラ内で色々やっています。

この記事は，Java の Spring と同じように，DIコンテナで疎結合にしたい... と思ってそのやり方を調べたメモです。
DIコンテナとしてこの記事では hypodermic を使いますが，他のライブラリでも同じようにできるはずです。

## 方針
drogon のプラグインとして，hypodermic を保持するものを作ります。
これだけだと，コントローラ（HttpControllerなど）にインジェクションができないので，コントローラ生成をテンプレート特殊化でフックし，hypodermic でインスタンスを作るようにします。

## hypodermic を使うプラグイン
こんなコードを書きます。
```C++
class HypodermicPlugin : public drogon::Plugin<HypodermicPlugin>
{
    std::shared_ptr<Hypodermic::Container> m_container;
  
public:
    // drogon から呼び出されるプラグイン初期化関数
    void initAndStart(const Json::Value &config) override
    {
        // DIコンテナのbuilderに対象のクラスとインスタンスを登録
        Hypodermic::ContainerBuilder builder;

        // TODO: ここでbuilderにクラスを登録
        
        // DIコンテナ構築
        m_container = builder.build();
    }

    // drogon から呼び出されるプラグイン終了関数
    void shutdown() override
    {
        m_container = nullptr;
    }

    // コンテナへのアクセッサ
    std::shared_ptr<Hypodermic::Container> getContainer()
    { 
      return m_container;
    }
};
```

main関数など初期化時にこのプラグインを登録します。
```C++
void main()
{
    auto &instance = drogon::app();
    instance.addPlugin("HypodermicPlugin", Json::Value::Members{}, Json::Value{});

    // 以後，待ち受けポートの設定や instance.run() 呼び出し
    // ...
}
```

これで，HttpController継承クラスでこんな処理が書けます。
SomeClassはhypodermicに登録したタイプです。
```C++
auto plugin = drogon::app().getSharedPlugin<HypodermicPlugin>();
auto container = plugin->getContainer();
auto instance = container->resolve<SomeType>();
```

## コントローラ生成処理のフック
上記コードで，コントローラ内で色々なクラス（例えばdrogon::orm::DbClient）をhypodermic から取得できます。

ただ，コントローラそのものはdrogonが生成しているので，コントローラに依存性を注入することができません。
コントローラ生成は，drogonのクラスマップにコントローラが登録される時，ファクトリ関数オブジェクトを同時に登録することで行われています。
具体的な処理は， drogon::DrObject<T>::DrAllocator::registerClass<U>() メソッドです。

以下のようなコードを書くと，テンプレート特殊化でこれを上書きし， hypodermic を使ってコントローラを生成することができます。
SomeClassはhypodermicに登録したコントローラクラスです。
```C++
namespace drogon {
    // DIコンテナを使ってUserControllerを構築するように drogon を設定（テンプレート特殊化）
    template <>
    template <>
    inline void DrObject<SomeClass>::DrAllocator::registerClass<SomeClass>()
    {
        DrClassMap::registerClass(
            className(),
            []() -> DrObjectBase * { return nullptr; },  // 生成処理（生ポインタ返却）
            []() -> std::shared_ptr<DrObjectBase> {    // 生成処理（スマートポインタ返却）
                auto plugin = drogon::app().getSharedPlugin<HypodermicPlugin>();
                auto container = plugin->getContainer();
                return container->resolve<SomeClass>();
            });
    }
}
```
生ポインタを取得する関数オブジェクトは（コントローラ生成では）使われてないようなので，手抜きしています。

## おわりに
これで，hypodermic のコンストラクタインジェクションをコントローラにも使えるようになります。

Javaのようにアノテーションを書けばDIできるとはならないですが，C++でもDI導入によりクラス間を疎結合にできるのが分かってよかったです。
react-routerでLinkが作用しない症状について

# はじめに
Router.jsxに記述しているRoute TopコンポーネントをRoute DefaultLayoutコンポーネントで囲うと、リンクの画面が遷移しない症状が発生しました。
DefaultLayoutコンポーネントの記述に問題がありそうでした。

# バージョン
react-router: 7.2.0
<br>

このように記述していました。
```.Router.jsx
import { BrowserRouter, Route, Routes } from "react-router";
import { Top } from "../components/pages/Top";
import { Users } from "../components/pages/Users";
import { DefaultLayout } from "../components/templates/DefaultLayout";
import { HeaderOnly } from "../components/templates/HeaderOnly";

export const Router = () => {
  return (
    <BrowserRouter>
      <Routes>
        <Route element={<DefaultLayout />}> // ← これで囲うとリンクが作用しませんでした。
          <Route path="/" element={<Top />} />
        </Route>

        <Route element={<HeaderOnly />}>
          <Route path="/users" element={<Users />} />
        </Route>
      </Routes>
    </BrowserRouter>
  );
};
```


```DefaultLayout.jsx
import { Footer } from "../atoms/layout/Footer";
import { Header } from "../atoms/layout/Header";

export const DefaultLayout = (props) => {
  const { children } = props;

  return (
    <>
      <Header />
      {children}
      <Footer />
    </>
  );
};
```

```Header.jsx
import styled from "styled-components";
import { Link } from "react-router";

export const Header = () => {
  return (
    <SHeader>
      <SLink to="/">HOME</SLink>
      <SLink to="/users">USERS</SLink>
    </SHeader>
  );
};

const SHeader = styled.header`
  background-color: #11999e;
  color: #fff;
  text-align: center;
  padding: 8px 0;
`;

const SLink = styled(Link)`
  margin: 0 8px;
`;
```

# 解決方法
propsではなく、Outletを使用する

```.DefaultLayout.jsx
import { Outlet } from "react-router";
import { Footer } from "../atoms/layout/Footer";
import { Header } from "../atoms/layout/Header";

export const DefaultLayout = () => {
  return (
    <>
      <Header />
      <Outlet /> // ← こちらを修正
      <Footer />
    </>
  );
};

```
# 参考
https://react-router-docs-ja.techtalk.jp/start/library/routing

https://zenn.dev/immedio/articles/1dedd5c1b9ee82

# おわりに
ドキュメントや他の方の記事が大変参考になりました。

<br>

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707255/8bfacf61-7d8d-6d27-cb07-98d1f8f27fcd.png"  width=100%>](https://projisou.jp)
ts-rsで型安全なパスパラメータを実装する：テンプレートリテラル型の活用

# ts-rsでTypeScriptのテンプレートリテラル型を活用したタイプセーフなパスパラメータの実装

## はじめに

TauriアプリケーションでAxumをバックエンドとして使用する際、フロントエンドからのリクエストパスの型安全性を確保することは重要です。特に、Axumのルーターで受け付けるパスパラメータとフロントエンドのTypeScriptコードの間で型の整合性を保つことで、実行時エラーを防ぐことができます。

本記事では、ts-rsを使用してTypeScriptのテンプレートリテラル型を活用し、以下のような利点を持つパスパラメータの実装方法を紹介します：

- Axumルーターで受け付けるパスパターンをTypeScript側で型として表現
- コンパイル時の型チェックによる早期エラー検出
- フロントエンド・バックエンド間での型の一貫性確保

例えば、以下のようなAxumのルート定義があるとき：

```rust
let app = Router::new()
    .route("/page/:id", get(handler))
    .route("/api/v1/:resource", post(api_handler));
```

この記事で紹介する実装方法により、フロントエンド側で以下のような型チェックを実現できます：

```typescript
// コンパイル時に型チェックが効く
const { path }: Page = { path: "page/123" };  // OK
const { path }: Page = { path: "page/hoge" };  // コンパイルエラー
const { path }: Page = { path: "invalid/123" };  // コンパイルエラー
```

## 環境

```toml
[dependencies]
ts-rs = "10.1.0"
serde = { version = "1.0", features = ["derive"] }
```

## 実装方法

### 1. Rust側の型定義

```rust
use ts_rs::TS;
use serde::{Serialize, Deserialize};

#[derive(TS, Serialize, Deserialize)]
#[ts(export, export_to = "page.ts")]
pub struct Page {
    #[ts(type = "`page/${number}`")] // テンプレートリテラル型の定義
    pub path: String,
}
```

### 2. 生成されるTypeScript型定義

```typescript
export type Page = { path: `page/${number}`, };
```

### 3. 使用例

```typescript
// 正常なケース
const { path }: Page = { path: "page/6" };  // OK

// コンパイルエラーとなるケース
const { path1 }: Page = { path: "page/hoge" };  // Error: Type 'string' is not assignable to type '`page/${number}`'
const { path2 }: Page = { path: "invalid/6" };  // Error: Type 'string' is not assignable to type '`page/${number}`'
```

## 詳細な説明

### テンプレートリテラル型とは

TypeScriptのテンプレートリテラル型は、文字列の形式を型レベルで制約することができる機能です。この機能を使うことで、以下のような利点があります：

- コンパイル時の型チェック
- IDEによる入力補完
- 実行時エラーの防止

### ts-rsでの実装のポイント

1. **属性の設定**
   ```rust
   #[ts(export, export_to = "page.ts")]
   ```
   - `export`: TypeScript型定義を生成
   - `export_to`: 出力先ファイルを指定

2. **型定義のカスタマイズ**
   ```rust
   #[ts(type = "`page/${number}`")]
   ```
   - テンプレートリテラル型を直接指定
   - TypeScriptの型システムを活用

### 活用例

```rust
// 複数のパスパラメータパターン
#[derive(TS, Serialize, Deserialize)]
#[ts(export)]
pub struct ApiPath {
    #[ts(type = "`api/v${number}/${string}`")]
    pub path: String,
}

// オプショナルパラメータ
#[derive(TS, Serialize, Deserialize)]
#[ts(export)]
pub struct UserPath {
    #[ts(type = "`users/${number}/${string?}`")]
    pub path: String,
}
```

## 注意点

1. **シリアライズ/デシリアライズ**
   - Rust側では通常の`String`として扱われる
   - TypeScript側でのみ型制約が適用される

2. **型の制約**
   - コンパイル時の型チェックのみ
   - 実行時のバリデーションは別途必要

## まとめ

ts-rsとTypeScriptのテンプレートリテラル型を組み合わせることで、以下が実現できます：

- 型安全なパスパラメータの実装
- コンパイル時の型チェック
- 開発時の補完サポート

これにより、RustとTypeScript間のより安全なインターフェース設計が可能になります。

## 参考リンク

- [ts-rs Documentation](https://docs.rs/ts-rs)
- [TypeScript Template Literal Types](https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html)
- [Rust serde](https://serde.rs/)
クラウド vs オンプレミス、知らないと後悔する決定的な違い

# クラウドとは
クラウドとは、いつでもどこでもインターネット回線を介してアクセス出来る環境のことを指します。
１つ具体例を挙げるとspotifyなどの音楽サービスがあります。
私たちはスマホやパソコンからインターネットを通してspotifyにアクセスし、音楽を聞きますよね！
もしspotifyがクラウド上で動いていない場合、私たちは自分の端末に保存したデータしか使えないため、音楽を聞くことができません。
spotifyがクラウド上で動いているゆえ、クラウド上のデータ（音楽データ）にアクセスでき、自分の端末に音楽をダウンロードすることなく音楽を聞くことが出来るというわけです。

# オンプレミスとは
オンプレミスとは、自社でサーバーなどを用意することを指します。
オンプレミスのメリットとしては自社で自由に設計が出来ることがあげられますが、その一方で優れた技術を持つ技術者が必要になってきます。
一方サーバーをレンタルして用意する場合もありますよね。
特にネットワークでアクセスできるクラウド上にあるインフラ（サーバーなど）を利用することをクラウドコンピューティングといいます。

# まとめ
オンプレミスは自社でサーバーを用意すること、クラウドはインターネットで接続できるクラウド上のサーバー（インフラ）を借りて利用することです。
この決定的な違いだけでも覚えてもらえると嬉しいです。