OmniAICreator/Qiita-1.07M huggingface dataset:
Railsのserializerを導入した経緯

この記事は東京海洋大学NePPの Advent Calendar 2024の17日目です。

# はじめに

# serializerとは
オブジェクトのデータをフォーマット化して外部に送信するために使われます。
特にWeb API開発では、アプリケーションの内部データをJSONやXMLなどの形式に変換する役割を担います。

# serializerを使うきっかけ
### 問題
インターン先でAPIモードで、Railsを使用していましたが
Railsの通常モードでは、HTMLビューを通じてレスポンスをレンダリングしますが、APIモードではHTMLビューがありません。そして、コントローラーでビューに、ステータスコードとjson形式のデータを返さないといけません。

そのため、レスポンスを返す時にデータをjson形式にする必要があります。
しかし、Railsは基本的にjson形式で変数を扱っていません。

### 解決策
そこで、serializerを使ってみた！



# serializerを導入するメリット
serializerを使うことで、そこで得られるメリットも紹介していこうと思います。
## 1.セキュリティの担保
モデルをそのままレスポンスに使用すると、不要なデータ（例えば、パスワードなど）がクライアントに露出するリスクがあります。
serializerを使うことで、必要なデータのみをレスポンスに含めるよう制御することができます！

### 例

モデルそのものが持つ属性
```
{ id: 1, name: "hashimoto",  password_digest: "123456789" }
```
以下を設定することで、シリアライザーを設定
```
class UserSerializer < BaseSerializer
  attributes :id, :name
end
```
serializerを使ったことによってレスポンスを以下のように制限できる。
```
{ "id": 1, "name": "hashimoto" }
```
## 2.コントローラーの肥大化回避

serializerを使わないと、コントローラでレスポンスデータの整形や加工を直接行う必要があり、コードが肥大化してしまいます。
しかし、serializerを導入することで、レスポンス整形のロジックをコントローラから分離できます。これにより、コントローラがシンプルになり、保守性が向上します。

### 例
serializerを使わない場合のコントローラーの例
```
def show
  user = User.find(params[:id])
  render json: { id: user.id, name: user.name, email: user.email }
end
```

serializerを使った場合のコントローラー

```
def show
  user = User.find(params[:id])
  render json: UserSerializer.new(user)
end
```

## 3.条件付きのレスポンスの柔軟性

シリアライザーの条件付き属性（attribute :name, if: :condition? など）を利用することで、動的なレスポンスを簡単に作ることができます。
または、
```
def include_email?
    @options[:include_email]
end
```
などを使って、エンドポイントごとに、include_emailを使うかどうかの判断をコントローラーに任せたりすることができます。

## 4.再利用性

レスポンス整形ロジックがコントローラやモデルに埋め込まれていると、他のエンドポイントで再利用が難しくなると思います。

しかし、serializerを導入することで、同じモデルを扱う複数のエンドポイントで共通のロジックを再利用できます。
これは、実際に開発していてめっちゃ便利だなと思ってました。他の人が書いたserializerのコードを使いまわせるのは、コード量も減りますし、Railsの基本理念同じことを繰り返さないに少し、沿っていていいなと思いました。
## 5.無駄なデータの送受信
モデルそのものが持つ属性
```
{ id: 1, name: "hashimoto",  password_digest: "123456789" ,email: "hashimoto@gamil.com"......}
```
以下を設定することで、シリアライザーを設定
```
class UserSerializer < BaseSerializer
  attributes :id, :name
end
```
serializerを使ったことによってレスポンスを以下のように制限できる。
```
{ "id": 1, "name": "hashimoto" }
```
必要なデータのみの送受信によってパフォーマンスが上がるのかなとかってに思いましたが、これに関しては、あまり他の記事でも見かけないのでそこまで関係ないのかも。(自分の中での仮説です、、、)
# おわり
セキュリティの担保やコードの可視性などを上げることができるとっても便利なserializerのメリットと自分が導入した経緯をお伝えしてきましたが、この記事が誰かの役に立てれば嬉しいです！
年賀状の画像生成をAmazon BedrockのNova Canvasで挑戦（あけましておめでとうございます）

あけましておめでとうございます！今年もよろしくお願いいたします。

年賀状書きましたか？
Bedrockを使えばまだ間に合いますよ！

## Nova Proで画像生成用のプロンプトを考えさせる

Nova Proで以下のようなプロンプトを投げます。まずは、「年賀状」について知っているか確認します。

```
年賀状って知ってますか？
```

以下のように返答がありました

> はい、年賀状について知っています。
> 
> 年賀状とは、日本で広く行われている新年の挨拶状のことです。年賀状は、友人、家族、同僚、知人などに新年のあいさつを送るために使われます。通常、1月1日から1月7日までの間に届くように投函されます。
> 
> 年賀状には、新年の挨拶の言葉、干支（十二支）に関連するデザインやイラスト、時事ネタや個人的なメッセージなどが書かれます。年賀状を送る習慣は、日本の文化の一部となっており、多くの人々が年末年始に年賀状の交換を楽しんでいます。
> 
> 年賀状の送り方にはいくつかのマナーがあります。例えば、喪中の方には年賀状を送らない代わりに喪中はがきを出し、年賀状を控えることが一般的です。また、年賀状を送る際は、相手の氏名や住所を正確に記入し、適切な時期に投函することが大切です。
> 
> 年賀状は郵便局が発行する専用のはがきを使用することも多く、郵便局では毎年様々なデザインの年賀状切手や年賀はがきを販売しています。

知ってそうなので、引き続きプロンプト生成を依頼します。

```
そうです。2025年の干支はヘビです。 年賀状につかう年賀状のイラストをStable Diffusionで生成したいので、Stable Diffusionに与えるプロンプトを考えてください。

ヘビのイラストを使用してください
ヘビで2025の文字を表すようなデザインにしてください
Happy New Yearの文字を画像の上部に配置してください。
```

> 以下は、指定された要件を満たすStable Diffusionのプロンプトの例です。
> 
> ```
> A vibrant and festive illustration featuring a snake, representing the zodiac sign for the year 2025. The snake is creatively designed to incorporate the number "2025" within its body or surroundings. The image has a joyful and celebratory atmosphere, with bright colors and intricate details. At the top of the image, the text "Happy New Year" is prominently displayed in a stylish and eye-catching font. The overall composition is balanced and harmonious, evoking a sense of warmth and goodwill for the upcoming year.
> ```
> 
> このプロンプトを使用して、Stable Diffusionに年賀状用のイラストを生成することができます。生成された画像は、ヘビをモチーフにし、2025年の文字を表現し、上部に「Happy New Year」の文字を含むデザインになります。

できました！

## Nova Canvasで画像生成する

それでは画像を生成させてみましょう。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/5a03f163-5ef6-835e-1c25-863601e6d6ed.png)

文字の出力がちょっとあやしいのでバリエーション生成機能をつかって何度か再生成させます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/887d25cf-8c72-209f-414f-f926c4f4e860.png)

どうですか😁

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/41574/9d0980f6-d5fa-0ed8-bdd6-4fae3f46eb81.png)

（ちょっと違う気もしますが）


## Nova Reelで動画にする

最後は写真から動画を生成してみましょう。

プロンプトは[ドキュメント](https://docs.aws.amazon.com/nova/latest/userguide/prompting-video-image-prompts.html)に例示があった「dolly forward」を使用しました。

https://x.com/moritalous/status/1874118648341917858

今年もよろしくお願いいたします！
警報以上(地域)・特別警報(全国)の発表を取得し、 TC001 で表示させる

## 基本的には JSON 内の注警報コードをかき集めれば実現できます
新年1本目は [気象庁サイトの注警報情報を取得し、 Ulanzi TC001 で表示させる](https://qiita.com/harycurl/items/9cfa881635a81916dec8) の続編である。
自分の住んでいる市区町村の注警報情報に加え、都道府県レベルの警報・特別警報、全国の特別警報の発表情報を知りたい場合、それぞれ JSON を取得して判定させることができる。

フロー図は両方とも同じ形で、前回の注警報情報取得からアプリ部分を取り除いたものとなる。
![jmawarn_notify1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/9fffbfd9-625a-7762-32a1-9902f2527b2a.png)

違いは http request （地域コード.json / map.json）、状態保存の変数名、 後ろのparser（警報・特別警報で通知 / 特別警報のみ通知）、そして parser A の部分。
両者の parser A を下に記す。

```javascript: parser A（長野県）
var warn_array = msg.payload;
var warns = warn_array.areaTypes[0];
var area_num = Object.keys(warns.areas).length;
var code = [];
var status = [];
var warn = [];

for (var j = 0; j < area_num; j++) {
    var warn_area = warns.areas[j].warnings;
    if (Object.keys(warn_area[0]).length > 1) {
        for (var i = 0; i < warn_area.length; i++) {
            if (warn_area[i].status !== "解除") {
                code.push(warn_area[i].code);
            }
        }
    }
}

if (code.find(value => value.match(/^3/))) {
    warn = "1";
} else if (code.find(value => value.match(/^0/))) {
    warn = "2";
} else if (code.find(value => value.match(/^1/))) {
    warn = "3";
} else if (code.find(value => value.match(/^2/))) {
    warn = "3";
} else {
    warn = "0";
}

msg.payload = warn;
return msg;
```

```javascript: parser A（全国）
var warn_array = msg.payload;
var region_num = Object.keys(warn_array).length;
var code = [];
var status = [];
var warn = [];

for (var k = 0; k < region_num; k++) {
    var area_num = warn_array[k].areaTypes[0].areas.length;
    for (var j = 0; j < area_num; j++) {
        var warn_area = warn_array[k].areaTypes[0].areas[j].warnings;
        if (Object.keys(warn_area[0]).length > 1) {
            for (var i = 0; i < warn_area.length; i++) {
                if (warn_area[i].status !== "解除") {
                    code.push(warn_area[i].code);
                }
            }
        }
    }    
}

if (code.find(value => value.match(/^3/))) {
    warn = "1";
} else if (code.find(value => value.match(/^0/))) {
    warn = "2";
} else if (code.find(value => value.match(/^1/))) {
    warn = "3";
} else if (code.find(value => value.match(/^2/))) {
    warn = "3";
} else {
    warn = "0";
}

msg.payload = warn;
return msg;
```
基本的には地方（全国版のみ）・一次細分地域・注警報でぐるぐる回して code をかき集めるだけである。
全国版は一次細分地域全て（142地域）を集めるので注警報コードが数百個になるが、判定方法は特に変わらない（とはいえ実際に特別警報が発表された時に機能するかはまだ試せていないが）。

動作イメージはこのようになる。
頭にアイコンを表示できるので、発表対象の識別が可能な点も TC001 を使う利点となる。
![jmawarn_notify2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/9af34bd0-1579-6d35-604c-11e44ad9557c.png)
![jmawarn_notify3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3943774/6158207b-c6b8-0224-f9a1-ae69a29b422f.png)

それぞれ実行の度に JSON ファイルを読みに行くため、実行頻度（実用を考えると1分間隔程度で実行させたいが、地域版・全国版はもう少し頻度を減らす）と3本全部走らせるか（全国版は特別警報が出そうなタイミングのみ走らせる）を考慮したい。

毎年のように気象災害で犠牲者が出てしまっているが、今年は災害の少ない、犠牲のない年であることを願いたい。
GitHubでPRがマージされたらIssueを自動的にCloseする方法

# はじめに
GitHubを利用しているとIssueを立ててPR(PullRequest)を作成するという流れがあるかと思います。

その際、PRのマージ後に手動でIssueを閉じるのが面倒くさいなと思ってる方々に向けての記事となります。

:::note alert
注意点
自動クローズ機能は、PRがdefault branch（通常はmainまたはmaster）にマージされた場合にのみ動作します。
:::

### 前提
Issueが存在する
![スクリーンショット 2024-12-31 13.31.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/8ddb38f2-8f08-5577-5409-6156e0d45278.png)

ローカルでブランチを作成してcommit済み
![スクリーンショット 2024-12-31 13.39.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/3282f9d7-c9a7-0fb6-f297-68d74905629a.png)

# 実践

## 1.GitHubにブランチをpushする

![スクリーンショット 2024-12-31 13.42.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/87af8083-e191-1b15-caa5-59719f23fa02.png)

## 2.PRを作成する
![スクリーンショット 2024-12-31 13.43.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/2a83fda1-8503-f8e1-6290-5140bfc712a0.png)

## 3.PRの説明文にキーワードを追加

PRの説明文に以下の形式でキーワードを記載します

```bash
Closed #<Issue番号>
```

実際に書いてみます。

![スクリーンショット 2024-12-31 13.49.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/b48ef2e1-e944-7dbf-03b0-712a8788aef2.png)


close以外にも以下のキーワードも使用出来ます。

- closes
- closed
- fix
- fixes
- fixed
- resolve
- resolves
- resolved

また、複数のIssueをCloseすることも出来ます。

``` bash
Closes #1, #2, #3
```

``` bash
Fixes #1
Fixes #2
Fixes #3
```
## 4.PR作成してマージする

![スクリーンショット 2024-12-31 13.51.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/442b5a7b-643e-940b-46b7-35c0408be39b.png)

## 5.対象のIssueを確認
![スクリーンショット 2024-12-31 13.56.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/474880/8c0596dd-f33c-793c-877b-a8b02b98d41f.png)

PRがマージされた際に自動的にIssueも閉じてます。

# まとめ
デフォルトブランチじゃなくリリース用ブランチ等にPRを出すプロジェクトだと使えないですが、個人開発などには使えるかと思います。

ドキュメント
https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue#linking-a-pull-request-to-an-issue-using-a-keyword
社内で認知を得ることによる仕事への影響について

この記事は [SUPER STUDIO Advent Calendar 2024](https://qiita.com/advent-calendar/2024/super-studio) の22日目の記事になります。

# 概要

社内で自分の名前が売れることの影響について、ある程度一般性のありそうなことについて、自分の考えをまとめたものです。

# 置かれた状況

私はおよそ2年前SUPER STUDIOにジョインしましたが、入社以来サービスのインフラ運用部門に所属しております。当時は職人的なポジションの部署で、運用部門自身やその活動が社内的に広く知られることがありませんでした。

自社のサービスインフラの運用や改善の状況を知ってもらうことは、それを取り扱っていただいている他の部門のメリットにもなるかと思い、関連の近い部門から普段どのようなことをしているか、抱えている問題や取り組んでいる課題などを共有出来るよう、私なりに出来ることをはじめました。

昨年、グループマネージャになったり社内表彰をいただいたりして、社内で自分の名前が知ってもらえるような状況になりました。それを受けて、今年はその認知をどう利用するか、というフェーズに入りました。

# 良かったこと

まず、役職が付いたということも影響してか、いい話も悪い話もひっくるめて何かと声がかかるようになりました。

ビジネスの大事な局面や面白い話というのは、最前線に集まるという傾向があるのはどこの世界も一緒かと思います。常に最前線に立っていることで、今までそれほどクリアに見えていなかった自分の仕事が、どう会社のビジネス戦略に関わってくるのかというあたりもつなげることが出来るようになりました。

まだ関わりのない部署と話すときに、相手が先に自分のことを知ってくれているのは、ある程度便利に働きました。普段関わりのない部門なのに名前を知っている人というのは、だいたいそれほど気をつけて見ていなくても目に止まるような露出をしている人が多く、それだけでもプラスの印象からスタートできるという側面があります。

役職が上がってくると、見る範囲が広くなるので、その中でどれに手を付けるかを自分で選べるようになります。今まで自分の仕事の範囲でなかった領域も、組織変更で自分の関連部署になれば、自分がキャッチアップして手を付けることも出来るようになります。


# 良くなかったこと

メリットの裏の話にはなりますが、わりと何でも自分に話が来るようになります。自分宛てに来た話が多くなってくると、自分だけが抱えてしまう範囲が広くなってくるので、結局自分の時間が制限されることにもなります。それにより、自分がやりたいことをする時間がなくなったりもします。
せっかく出来ることが増えたのに、それに当てる時間はどんどんなくなっていきます。自分がボトルネックになることも多く感じた一年でした。

役職が上がると、単純にやることが増えます。今までやる必要のなかった、同じ部署のメンバーの勤怠の管理や承認業務、他のメンバーの作業の調整などを行う必要が出てきます。
役職が上がるということは、細々とした面倒事をたくさん引き受ける代わりに、自分のできる範囲を広げるという行為だということを、この一年は実感する事になりました。

# 結論

自分の会社でやりたいことがある場合、それが他部署をまたがって成し遂げる必要があるような大きな話であれば、社内で認知されていることは優位に働くことは間違いないです。
逆に、エンジニアとしてサービス開発を長くやっていきたい、色々と面倒なことに巻き込まれず開発に集中したいというような人は、あまり目立たないほうがやりたいことに集中できそうです。

# これから

社内ではある程度必要な人に自分を知っていただけている状況になり、自分が社内で話しに行きやすい状況になりました。

SUPER STUDIOはエンジニア領域では知名度があるとは言えない状況ですので、今後の採用などを見据えて社外向けに色々と情報を発信していければと思っています。

もちろん、日々の活動が社外に発信するに足るような充実した内容になっていることが前提です。
SwiftUI での Drag & Drop

SwiftUI で Drag & Drop を実装するにはいくつか選択肢があります。

この記事は、 【Sansan × YUMEMI】iOSランチタイムLTで発表した内容をまとめたものになります。

https://yumemi.connpass.com/event/333140/

https://www.docswell.com/s/ykws/5YDM9V-2024-11-14-131259

# ガイドライン

iOS アプリ開発の起点としては、ヒューマンインターフェイスガイドラインをまず確認します。

https://developer.apple.com/jp/design/human-interface-guidelines/drag-and-drop

ただ、こちらにリンクされているのは、 UIKit での Drag & Drop の API がリンクされていて、 SwiftUI での Drag & Drop へのリンクがなぜかないです。　要件によっては SwiftUI での Drag & Drop の実現は難しい可能性があるため、その部分は UIKit で実装するのも有力な選択肢の一つになります。

https://developer.apple.com/documentation/uikit/drag-and-drop

SwiftUI 向けの Drag & Drop の公式のドキュメントは以下にあります。

https://developer.apple.com/documentation/swiftui/drag-and-drop

# OS ごとの API

OS ごとに利用可能な API とその特徴を表にまとめました。

| iOS | API | 実装 | ハンドリング |
| -- | -- | -- | -- |
| iOS 16 | draggable/dropDestination |	不要	| できない |
| iOS 14 | onDrag/onDrop | 一部必要 | ドロップはできる |
| iOS 13 | DragGesture | 全て＋スクロールも |	全てできる |


## iOS 16 以上

iOS 16 から Transferable protocol に適合することでアプリ間でのデータのやり取りができるようになります。その延長として、 Drag と Drop が可能な View として SwiftUI 上で表現できるようになっています。

https://developer.apple.com/documentation/coretransferable/transferable

2年前の iOS 16 のリリースに合わせて WWDC2022 で発表されました。

https://developer.apple.com/videos/play/wwdc2022/10062/

draggable/dropDestination を利用することで簡単に Drag & Drop を実現できます。

draggable で Drag 可能な View になります。

https://developer.apple.com/documentation/swiftui/view/draggable(_:)

dropDestionation で Drop 可能な View になります。

https://developer.apple.com/documentation/swiftui/view/dropdestination(for:action:istargeted:)

`isTargeted` で Drop 対象になっていることが検知できます。

ただし、基本的に Drag & Drop 時のハンドリングはできません。 Drag 時の preview をカスタマイズすることはできます。

https://developer.apple.com/documentation/swiftui/view/draggable(_:preview:)

### 制限事項

`LazyVGrid` に付与した `dropDestination` はスクロールすると一度破棄されることがあるので、ドラッグしたままスクロールしてドロップしようとするとできないことがあります。 iOS 17.5 ではドラッグした状態でスクロールして再表示した `LazyVGrid` に `dropDestination` が適用されていないような挙動になります。 iOS 18 では発生しません。また iOS 17.5 でも `LazyVGrid` に換えて `VStack` + `HStack` でレイアウトすれば再表示しても `dropDestination` が適用されていてドラッグ可能になります。

## iOS 14 以上

iOS 14 からは `NSItemProvider` に適合することで onDrag/onDrop で表現できます。

onDrag で Drag 可能な View になります。

https://developer.apple.com/documentation/swiftui/view/ondrag(_:)

ただし preview が使えるのは iOS 15 からです。

https://developer.apple.com/documentation/swiftui/view/ondrag(_:preview:)

onDrop で Drop 可能な View になります。

https://developer.apple.com/documentation/swiftui/view/ondrop(of:istargeted:perform:)

基本的に Drag 時のハンドリングはできません。 Drop 時のハンドリングは `DropDelegate` が用意されています。

https://developer.apple.com/documentation/swiftui/dropdelegate

iOS 16 以上がターゲットでも Drop 時のハンドリングが必要な場合はこちらの API を使います。

## iOS 13 以上

iOS 13 からは DragGesture で表現できます。

https://developer.apple.com/documentation/swiftui/draggesture

基本的に全てハンドリングできます。

Drag & Drop の実装も書く必要があるのと、スクロールイベントが干渉すると実装が難しいです。

# チュートリアル

macOS 向けのチュートリアルですが、 Transferable protocol の実践としては有効な内容になっています。

https://developer.apple.com/tutorials/app-dev-training/supporting-drag-and-drop
【DevPod】devcontainer.jsonのfeatureが読み込まれない場合の対処法

DevPodでワークスペースを作成する際に以下のようなエラーが発生することがあります。

```terminal
devcontainer up: start container: build and extend docker-compose: fetch features: process feature ghcr.io/UserName/devcontainer-features/common-utils:2: could not parse reference: ghcr.io/UserName/devcontainer-features/common-utils:2
```

`devcontainer.json`の`feature`のURLを全て小文字にすることで解消されます。

```json:devcontainer.json
{
  "features": {
    "ghcr.io/username/devcontainer-features/sample:1": {},
  }
}
```
gensparkにAIエージェントが生えた

AIエージェントが流行ってますね。

gensparkにも何か生えたみたいです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/0f50ad68-2bf0-488f-d1d1-574c3b7e9675.png)

※gensparkってなに？

https://qiita.com/Jasmine_teeeeee/items/0207345c03433c07530e

# 使い方

公式

https://www.genspark.ai/spark/ai%E3%82%A8%E3%83%BC%E3%82%B8%E3%82%A7%E3%83%B3%E3%83%88%E3%81%AE%E8%A9%B3%E7%B4%B0/e23e66e6-3617-4ef2-85d2-1804ae13bf60
【Zed】保存時にESLintのエラーを自動修正する方法

`settings.json`に以下の設定を追記すると保存時にESLintのエラーの自動修正できます。

```jsonc:settings.json
{
  "code_actions_on_format": {
    "source.fixAll.eslint": true
  }
}
```

特定の言語でのみ有効化する場合には以下のように記述します。

```jsonc:settings.json
{
  "languages": {
    "JavaScript": {
      "code_actions_on_format": {
        "source.fixAll.eslint": true
      }
    }
  }
}
```
生成AI Feloで作るプレゼン資料

https://corp.qiita.com/releases/2024/11/qiita-bash-202412/

このイベントで登壇してきました。

その際に使用した登壇資料は、Feloで作成しました。

こんな感じ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/c0dd4787-9c50-8e81-c5a8-286d227f7104.png)

無課金勢でもスタイルの変更が可能でした。
またキャンバとの連携でスタンプやシートの編集が簡単に可能だったのでお勧めです。
システム監査技術者試験(AU R6秋)

# 1. はじめに
その年の春に情報処理安全確保支援士試験合格したし、秋に「もう一つ高度資格とるぞ〜」という気持ちでトライしました。
結果としては合格していないので、来年のために振り返り記事になっています。

## 1.1 システム監査技術者試験を選んだわけ

    監査系の資格だったから
    ⇒仕事でシステム監査の現場に参加したり、監査要件を満たすには〜など業務で対応することもあったので、内容がとっつきやすいと思ったから
    論述形式の試験だから
    ⇒他の高度資格よりは回答を作成できると思ったから。あと、下期に受かる可能性がありそうなのがこれしかなかったから
    自分の今のもやもやを晴らせると思ったから
    ⇒日頃の仕事に対してある種のまんねりを感じることがあり、仕事に対して意味を見いだせればいいなと思っていた（モチベ維持）

# 2. 試験概要

IPAの試験情報を確認してもらえればと思います。
https://www.ipa.go.jp/shiken/kubun/sc.html
ざっくり書くと、午前試験はマークシート方式・午後Ⅰ試験は記述方式。
それぞれ6割取れれば合格です。

午後Ⅱ試験に関しては、字数制限ありの論述式で、A判定がでれば合格です

# 3. 勉強方法

教本を１冊購入しました。
https://bookstore.tac-school.co.jp/book/detail/111067/

教本の知識部分は流し読みしつつ、午前問題の過去問と午後問題の解法を身につ蹴るために読みました。

## 3.1. 午前試験対策

午前Ⅰは免除されたので、午前Ⅱのみの受験だったのですが、教本の過去問部分を何周かしました。
実際に試験で出た問題もあったので良かったのですが、もっとやっとけばあと10点は多く取れたと思います。

↓午前I免除については下記参考
https://www.ipa.go.jp/shiken/about/koudo_menjo.html

## 3.2. 午後試験対策

教本の午後問題対策を読みながら、自分なりの対策を立てました。
IPAが公開している過去問はほとんどやっていないです。

・出題分野から自分が得意な分野を見極める
→システム実装の面はやはり弱いので、運用面でのシステム監査に関する問題で点数を確実に取ろうと考えました。
・問題文の構成を把握する
→ひたすら解法のテクニックを叩き込んでました。基本的には問題文から解答を導き出せばよいはずなので、問題の読み解きをミスらないようにはしようと考えてました。
→午後Ⅱはテキストに、まずはタイトルと小項目という構成にしたほうがいいとあったので、参考にしました。

↓イメージ
1.システムのセキュリティ監査について
1.1 システム運用部門にとっての留意点
1.2 ユーザ部門にとっての留意点

# 4. 実際の勉強スケジュール

勉強開始は8月ごろから教本を読み始めていました。
基本は教本を読んで、過去問をやって・・・解法を学んで・・・
試験直前も同じようなサイクルで勉強をしていました。

# 5. モチベーション維持法

・一回では受からないけど手応えは掴みたい
→論述試験だからそんなに簡単には受からないとは思うけど、ここを抑えれば次は受かるぞっていうところを得たかった

夏以降転職活動を続けることに疲れていたこともあり、春ほどのやる気を出せなかったのがよくなかったと反省しました・・・

# 6. おわりに

結果としては、以下の通りです。
午前：60点
午後Ⅰ：70点
午後Ⅱ：C

午後Ⅱに関しては最終問題の制限字数(1,400字以上)に届かないで出してしまったので、Cにはなってしまったのは仕方ないです・・・

# 7.次回への反省
午後Ⅱ対策として、添削講座を申し込んでみようと思いました。書く内容の特訓もですが、久しぶりにあんなに文字数の多い筆記試験をうけたので手が痛くなってしまいました・・・。
【C#】Timers.TimerのStopでイベントが発火してしまう理由と対策

C# でタイマーを使う場合、System.Timers.Timer を使用することがよくあります。しかし、Stop メソッドを呼び出したにもかかわらず、タイミングによってはイベント (Elapsed) が発火してしまう現象に遭遇することがあります。この記事では、その理由と解決方法を解説します。

# なぜStopしてもイベントが発火するのか？
System.Timers.Timer は内部的にスレッドプールを使用して Elapsed イベントを発生させます。
タイマーが停止しても、スレッドプールに既にスケジュールされた Elapsed イベントは実行されます。
何が言いたいかと言うと、タイミングによってはStopしてもイベント発火するようです。かなしみ。

# 発生例
以下のコードでは、Stop を呼び出してもイベントが発火してしまう場合があります。
```ruby:qiita.C#
using System;
using System.Timers;

class Program
{
    private static Timer _timer;

    static void Main()
    {
        _timer = new Timer(1000); // 1秒間隔
        _timer.Elapsed += TimerElapsed;
        _timer.Start();

        Console.WriteLine("Timer started. Press Enter to stop.");
        Console.ReadLine();

        _timer.Stop();
        Console.WriteLine("Timer stopped.");
    }

    private static void TimerElapsed(object sender, ElapsedEventArgs e)
    {
        Console.WriteLine("Timer elapsed.");
    }
}
```
# 対策方法
Elapsed イベントの内部で、タイマーが有効かどうかを確認するフラグを使用します。
```ruby:qiita.C#
private static Timer _timer;
private static bool _isRunning = true;

static void Main()
{
    _timer = new Timer(1000);
    _timer.Elapsed += TimerElapsed;
    _timer.Start();

    Console.WriteLine("Timer started. Press Enter to stop.");
    Console.ReadLine();

    _isRunning = false; // イベントの実行を無効化
    _timer.Stop();
    Console.WriteLine("Timer stopped.");
}

private static void TimerElapsed(object sender, ElapsedEventArgs e)
{
    if (!_isRunning)
    {
        return; // イベントをスキップ
    }

    Console.WriteLine("Timer elapsed.");
}

```
# 結論
System.Timers.Timer を使用する場合、Stop を呼び出してもイベントが発火する可能性があります。確実に防ぎたい場合は、フラグ管理や Dispose の併用や、DispatcherTimer を使用することがいいと思います。なぜなら、UI スレッド上で動作しているため、Stop を呼び出すだけで発火を確実に停止できます。
HTML&CSSでつまづいた部分

この記事は東京海洋大学NePPのAdvent Calendar 2024の22日目です🎄

# はじめに
今回の記事では、私が今までHTML&CSSを学びながら書いてきてややこしいなと感じたことについてまとめていきます。
まだ始めたばかりの方などに参考になればうれしいです:raised_hands:
（私もまだ勉強をしている身なので、間違っている部分などあれば指摘していただけるとありがたいです:bow:）
1. [class属性とid属性の違い](#1-class属性とid属性の違い)
2. [marginとpaddingの違い](#2-marginとpaddingの違い)
3. [ブロック要素とインライン要素とインラインブロック要素の違い](#3-ブロック要素とインライン要素とインラインブロック要素の違い)

# 1. class属性とid属性の違い
1つめはHTMLにおける"class属性とid属性の違い"についてです。

まず大きな違いとして、同じHTMLファイル内で使用できる回数があげられます。同じclass名はページ内で何度も使えますが、同じid名は "ページ内で一度しか" 使うことが出来ません。
次に、CSSで指定した時の適用の優先順位があげられます。CSSでは "idで指定したものが優先" されます。あるタグにclassとidをつけて、そのclass名とid名に対してCSSを設定した時、idが優先されるため実際に適用されるのはid名を指定したCSSのみとなります。

以上のことから、「ページ内で何度も繰り返して表示する部分に対してはclassを使ってCSSで何回も同じコードを書かなくていいようにできる」「ずらしたくはない部分やページ間で同じ表示を使う部分にはidを使う」という違いがあることを確認できます。
気づかずに同じclass名を使ってしまって、思っていたところと違う部分にCSSが適用されてしまうことがたまにあるので気を付けたいです、、

# 2. marginとpaddingの違い
2つめはCSSにおける"marginとpaddingの違い"についてです。

marginとpaddingはどちらも余白を指定できるものです。しかし、"余白を付ける場所が違う" ことに注意しなければいけません。
要素の内側の余白はpadding、その周りにborderがあり、要素の外側（borderの外側）の余白はmarginで指定します。Chromeの「検証」やEdgeの「開発者ツールで調査する」で実際に確認すると分かりやすいですね。（このような概念はボックスモデルというそうなのでもう少し詳しく知りたい方はぜひ調べてみてください）

またメディアクエリを設定する時など、レイアウト崩れ防止のためにbox-sizingをborder-boxを使ってwidthで指定できる要素の幅をborderまで含むようにする場合も注意が必要です。今書いたように、border-boxを指定した時widthに含まれるのは「もともとの要素とpaddingとborder」でmarginは指定していない時と同じく含まれません。

どこの余白を指定しているのかは慣れるまで難しいと思うので何回も確認していくことも大切ですね！

# 3. ブロック要素とインライン要素とインラインブロック要素の違い
3つめはdisplayで指定できる、ブロック要素・インライン要素・インラインブロック要素の違いについてです。
この3つの要素の違いは主に「配置・並び方」「width・heightの設定」「margin・paddingの設定」に現れます。

「配置・並び方」については、ブロック要素のみ縦となり、インライン要素とインラインブロック要素では横になります。
「width・heightの設定」については、インライン要素のみ指定することができず、ブロック要素とインラインブロック要素では指定することができます。
「margin・paddingの設定」については、ブロック要素とインラインブロック要素では縦横左右すべて指定することができ、インライン要素では左右のみ指定することができます。

すごくややこしいですが、この3つの要素を分かっておくと便利なことがあるので私もちゃんと知っておこうと思いました。
例えば、インライン要素であるaタグでリンクを作る時のクリックできる範囲の変え方をはじめて知ったときこの大切さに気付きました。インライン要素のままではテキストの部分のみクリックできるようになっていますが、aタグをブロック要素にすることで大きさが広がりクリックできる範囲を要素全体に広げることができます。HPを作っていくときに大切になってくると思うので忘れないようにしたいです:thumbsup:

# さいごに
今回の記事では、HTML&CSSを学ぶ上で気になった部分についてまとめました。気づいたことなどがあればまた書き足したり、新しく記事にまとめたりしていこうと思います。
「はじめに」でも書いたように、私もまだ勉強中の身なので間違っている部分などは指摘していただけると助かります！
ここまで読んでいただきありがとうございました:relieved:
おざ！あ！願すも今ままいくましおすうとでめけし年しろいてごよ

# あけおめルーレット
十数年生きてきて今更、普通に「あけましておめでとうございます！今年もよろしくお願いします！」なんて言いたく無いですよね。。

そんなあなたに

＼ \ **あけおめルーレット！** / ／

自分だけのあけおめをみんなに送ろう！

![IMG_3627.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730711/327fbdaf-2fe9-b449-efee-493f7b0c3bbe.png)

https://trimscash.github.io/akeome/

https://github.com/trimscash/akeome


## 終
ダラダラしてたら一年が終わりつつあり、今年一つも記事書いてないのに気づいて中身ない記事書いてるわけじゃ無いよ？

reactで書き直したやつ↓

https://trimscash.github.io/akeome-react/

https://github.com/trimscash/akeome-react

ざあうましすてよすおご！ま今まく願でしいもろめ！おとしけい年
アドベントカレンダーの記事を25個書いてみて

2024年12月、Qiitaアドベントカレンダーの完走賞のQiitanのぬいぐるみに惹かれて25個記事を書くことを決めました。
これまであまり記事としてアウトプットはしてこなかったので（アドベントカレンダー始まる前のQiitaの投稿数は2）、たくさんの記事を書く中でいろいろなことを学ぶことができました。
そのことについて少し書いて、25個目の記事としたいと思います。


# 書いた記事一覧
他にもいろいろやることがある中で進めていったので一日一個はできませんでした。
この最後の記事も12/31の23:50とかになってしまいました。
記事が書き終わり次第開いているところにぽんぽん登録していったのでアドベントカレンダーの日付と実際の投稿の順序は全く異なっています。ご了承ください。

1つ情報処理安全確保支援士の記事だけ自分のはてなブログに投稿しました。しかしこれは完走賞の25個にはカウントされていないと思います。

https://qiita.com/shuji4649/items/f62686b81231221fe21c

https://qiita.com/shuji4649/items/e0ff84c6e8c93a1ff5c7

https://qiita.com/shuji4649/items/bb5a30f0cea2839f9439

https://qiita.com/shuji4649/items/770461e8bfc5524b9684

https://qiita.com/shuji4649/items/330307e4d186ca623da4

https://qiita.com/shuji4649/items/1f8db03482e97998c180

https://qiita.com/shuji4649/items/dcf8dd7ae9705be9758e

https://qiita.com/shuji4649/items/3d7fc9a2e0a65cb6c052

https://qiita.com/shuji4649/items/96a9b63a87fc2e752e8c

https://qiita.com/shuji4649/items/d6b33487e02597c5a544

https://qiita.com/shuji4649/items/3cf781f68c1bcc7287c3

https://qiita.com/shuji4649/items/c20def47f64dadfc5ec6

https://qiita.com/shuji4649/items/1f239e8da9de78e0f19f

https://qiita.com/shuji4649/items/d1dfe28047acc5568c06

https://qiita.com/shuji4649/items/c8d36fea225d7da2095d

https://qiita.com/shuji4649/items/3f7220cf27f75b0a576f

https://qiita.com/shuji4649/items/b1ccd9033d0c6cd31421

https://qiita.com/shuji4649/items/350885ead9c40214f304

https://qiita.com/shuji4649/items/12578517ff6778e69411

https://qiita.com/shuji4649/items/27a97164184eb5a448e0

https://qiita.com/shuji4649/items/2b750887a128b43d5124

https://qiita.com/shuji4649/items/3a92129b6a95343ebc9b

https://qiita.com/shuji4649/items/97c04d6bb28ea41e71ba

https://qiita.com/shuji4649/items/19dbf2c1587a0ab71121

https://shuji4649.hatenablog.com/entry/2024/12/29/175855


# 記事を書いてみて

## 思っていたよりも大変
自分でただ理解するだけではなく、記事に文章としてまとめるというのは大変です。
本当にその内容が正しいか確認しないといけない、画像や資料はちゃんと出典が分かるようにしないといけない、プログラムの変数名をわかりやすいものにしたりコメントを丁寧につけないといけない、など考えなければいけないことがたくさんあります。
今まで何気なく読んでいたQiitaの記事もこうやって時間をかけて書いてくださっているんだなということを改めて感じました。
記事を書くのは大変ですが、今までQiitaをはじめとする技術解説記事には数えきれないほどお世話になってきたので、これから少しずつ自分もアウトプットしていけたらなと思います。

## タイピング速くしたい

実は最近あまり文章をタイピングしていないのでは？ということに気づきました。
確かに回路設計ではタイピングの速度は必要ないし、プログラミングでも最近はcopilotの補完を使いまくっているのでそこまで多い量をタイピングしているわけではありません。
しかしこうやって記事を書いている中で、タイピング速度というものが自分の中でとても意識されました。
一般的に見たら速い方だとは思うのですが、これからこうやって文章を書く機会も増えていくと思うのでもっと速く打てるようになりたいなと思いました。

## ネットの記事の信頼性
こうやって自分もネットに記事を公開するようになったのですが、こんなただの高校生でも記事を書いて公開できてしまうということは知っておかないといけないなと思いました。

自分の中では割と理解しているものを中心に記事を書いていて、記事にする際にはしっかり調べなおしているのでそこまで間違った情報が多いわけではないと思うのですが、こうやって誰でも気軽に投稿できるものであるということを意識したうえで読むことは大切な気がします。
そのような点を踏まえても、自分としてはこうやって誰もが自由に知識を共有できるというのは良いことだと思っています。文章にすることで発信者自身の理解が深まり、他の人も新たな知見を得られるとても良い循環だと思います。ただ、一つの記事だけを信用するのではなく、なるべく多くの記事を参考にすることが読む側としては大切だと思いました。

## 日本語難しい
今こうやって文章を書いていてもこの日本語が適切なのかどうかというのは分からないです。
文を分けたほうがいいのか、どこに読点を打つべきか、語順はどれが分かりやすいか、など、意外と適切な文章を書くのって難しい気がします。

特にQiitaのような技術系のものだとたくさんの専門用語や数式が出てくることは珍しくなく、それをわかりやすく伝えるには一定の日本語力が必要だと思いました。

ただ、これはたくさん書いていく中で身に着けていくものだと思うので、これからも継続的にアウトプットを頑張っていきたいと思います。


# 最後に
アドベントカレンダー、大変でしたが楽しかったです！
また来年もやろうと思います！
UnityでDOTSのプロジェクトをWebGLで動作させる事が出来なかった話

# 概要
最新のUnity6でDOTSをWebGLで動作させようと思って色々試したが出来なかったので共有をします。

# 動作環境
Unity6

利用したプロジェクト

https://github.com/Unity-Technologies/EntityComponentSystemSamples/tree/master/PhysicsSamples

# 出来ない原因

* WebGLではSubSceneがロードできない。

unityでwebGLビルドした結果がこれでSubSceneがStreamingAssetsに格納されている構造になっている。
![webGLBuilds.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116884/1baf6b49-5a35-5fa0-cc21-f57300202335.png)

unityroomにアップロードして実行した結果、おそらくsubsceneがロードされなかったというエラーが。
![webGLSubSceneLoadError.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/116884/c89234f2-1d2b-9eba-ac08-7c7783b4b729.png)

WebGLではStreamingAssetsからのロードが出来ないという話があるので、それが原因かも。

公式のdiscussionsを見ると、Unityのバージョンによってload出来たり出来なかったりするので、おそらく公式でまともに対応していない部分だと思われる。

https://discussions.unity.com/t/is-there-a-way-to-load-subscenes-for-entities-on-webgl/1527759/5

# DOTS & WebGLの他に出来ない事

discussionsの投稿内のUnityの中の人によると、WebGLでは以下の事が出来ないようです。
* Burstがシングルスレッドでしか動作しないのでパフォーマンスが出ない。
* Entities Graphicsが動作しない。(WebGPUで動作するので、WebGPUサポートがされれば将来的にいけるかも)

また、これらがいつサポートされるかもまだ決まっていないそうです。

https://discussions.unity.com/t/webgl-and-dots/913496/15
STM32のUART【Arduinoフレームワーク】

ArduinoフレームワークでSTM32のプログラムを書いているときのUARTのやり方について紹介します。

# 方法

以下のように記述するとUARTを使えるようになります。


``` cpp
HardwareSerial uart1(PA10, PA9); //RX=PA10, TX=PA9
```

UARTに対応しているピンのピン番号を引数にしてHardwareSerialクラスのインスタンスを作るとUARTが使えます。
このクラスはArduinoでいう``Serial``と同じなので、あとは``Serial``と同じように使えます。

```sample.cpp
#include <Arduino.h>

HardwareSerial uart1(PA10,PA9);

void setup() {
  uart1.begin(115200);
}

void loop() {
  uart1.println("Hello, World!");
}

```

HardwareSerialのインスタンスを複数宣言すれば、複数のUARTが使えます。
ただし同じ系統のUARTは使えないので、UART〇の〇の数字が異なるものを使用してください。

# 注意点
STM32では、大体一つのUARTに対してTXとRXがそれぞれ複数のピン用意されているのですが、どのTXとRXの組み合わせでも使えるわけではなく、**同じ系統のUARTのTXとRXでも使えない組み合わせがあります**。

これはSTM32全体の問題なのかArduinoフレームワークの問題なのかPlatformIOの問題なのかよくわからないのですが、PlatformIOのArduinoフレームワークで開発しようと考えている人は、基板で実装したりする前にNucleoボード等で確認してみることをおすすめします。

基本的にピンが隣り合っている組み合わせだとうまくいって、そうでない場合はうまくいかないようです。

もし原因や解決策のわかる人がいらっしゃいましたら教えていただきたいです。
リポジトリにコミットされていない .editorconfig を使いたい

## .editorconfig が使いたい

プロジェクト全体の `.editorconfig` が用意されていないが、
ファイル末尾に改行を入れるなど `.editorconfig` を利用したいケースがあります。

メンバーと相談して `.editorconfig` をコミットするのが理想的ですが、
一時的に `.editorconfig` ファイルを用意しコミットしないようにする方法もあります。


## `.editorconfig` の作成

プロジェクトルートに .editorconfig を作成します。以下はサンプル設定です。
詳細は [EditorConfig公式ドキュメント](https://editorconfig.org/) を参照してください。

```プロジェクトルート/.editorconfig
# EditorConfig is awesome: https://editorconfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true

# Matches multiple files with brace expansion notation
# Set default charset
[*.{js,py}]
charset = utf-8

# 4 space indentation
[*.py]
indent_style = space
indent_size = 4

# Tab indentation (no size specified)
[Makefile]
indent_style = tab

# Indentation override for all JS under lib directory
[lib/**.js]
indent_style = space
indent_size = 2

# Matches the exact files either package.json or .travis.yml
[{package.json,.travis.yml}]
indent_style = space
indent_size = 2
```

## `.git/info/exclude` の設定

作成した `.editorconfig` をコミットしないように、自分の環境の `.git/info/exclude` を設定します。
※ リポジトリに `.editorconfig` がコミットされた場合はこれを削除する必要があります

```プロジェクトルート/.git/info/exclude
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

.editorconfig ← 追加
```

## 設定の確認

以下のコマンドを実行し、 `.editorconfig` が表示されなければ設定完了です。
```
$ git status
```
技術を学ぶ上で大切な「言語化」の力：日常の小さなことを言葉にする際に意識すべきポイント

## はじめに

言語化能力とは、頭に浮かんだ考えや、心の中のもやもやした思いを言葉にする力を指します。***この能力が高いと、自分の考えを明確に持ち、それを的確に発言・表現できるようになります。***

:::note warn
***「小さなことだから、自分が分かっていれば十分」と思いがちですが、実はどんな些細なことでも言語化することが非常に重要です。***
:::

頭の中の考えを言葉にして発信したり、相手に分かりやすく伝えることを意識して習慣づけることで、日常のコミュニケーションが大きく変わります。

***そのため、私はどんな小さなことでも言語化することを意識して取り組んでいます。***

## この記事を書こうと思ったきっかけ

仕事に取り組む中で、当初は「***パソコンや技術に集中していれば問題ない***」と考えていました。

***しかし実際には、コミュニケーション能力が非常に重要であることに気づきました。***

特に、難しい技術を相手に伝えるためには、些細なことでも言語化し、言葉として明確にすることが欠かせません。

:::note info
***このスキルは、訓練や日常生活でのちょっとした意識によって鍛えることができます！***
:::

この記事では、自分への備忘録も兼ねて、「***言語化***」の重要性やその鍛え方について、私の考えをまとめていきます。

## 小さなことを言語化する

私の場合、頭の中で思考が止まらず、何を優先すべきか迷う瞬間があります。***そのような漠然とした考えや思考については、まず紙とペンを使って書き出す作業をしています。***

例えば、自宅の検証環境で「こんなことを試してみたい」と思ったときには、手書きでイラストを描いたり、吹き出しアイコンを使って文字を追加したりします。

:::note warn
***また、日常生活の中で感じた些細なことについても、あえて言葉にしてみることで、抽象的なイメージを具体的に表現する練習をしています。***
:::

例えば、味噌汁を作る際には、「***どの具材をどのように切り、どの順番で入れるのか***」を意識的に言語化して料理をするようにしています。

:::note info
***正直なところ、かなり面倒だと感じることもありますが、一つ一つの行動に対して、頭の中で考えたイメージを言葉にする練習を重ねています。***
:::

***言語化には、漠然とした感情や思考を明確にする力があると実感しています。***

## 言語化する上で意識していること

エンジニアの世界では、難しい技術を相手にわかりやすく伝えるという高度なコミュニケーション能力が求められます。

***そのためには、前提知識としてITスキルや技術をある程度理解した上で、それを噛み砕いてわかりやすく伝える工夫が必要です。***

例えば、名前解決の仕組みについて、「***IPアドレスとホスト名を関連付けるサービス***」という漠然としたイメージではなく、

:::note warn
- **どのように関連付けているのか？**
- **名前解決が必要な理由は何なのか？**
:::

といった具体的な疑問を自分に問いかけ、考えるようにしています。

また、頭の中で考えても分からない場合には、インターネットや文献を活用し、理解できる範囲で情報を収集します。

***このように、当たり前だと思っていることでも、自分が理解できていない部分に気づいた瞬間に「なぜ？」と問い続けることで、より深いレベルでの言語化に挑戦しています。***

## まとめ

最後まで読んでいただきありがとうございました！***エンジニアの世界では、コミュニケーション能力や相手に伝えるスキルが想像以上に重要です。***

:::note alert
***複雑なシステムや絡み合った問題を自分の中で整理し、それを相手にわかりやすく伝えることは、決して簡単ではありません。***
:::

しかし、日常の些細な違和感や気づきを言葉にしていくことで、自分の意識や習慣を少しずつ変えることができると改めて実感しました。

## 参考記事

今回の記事を書くにあたり、以下の素晴らしい記事を参考にさせていただきました。***さらに詳しく知りたい方は、ぜひご覧ください。***

https://qiita.com/Sicut_study/items/61f1836df6fcff7abc7a

https://qiita.com/Sicut_study/items/80f5459f8ee7d765b042

https://zenn.dev/keitakn/articles/f3ed13a620d834

https://zenn.dev/seya/articles/8245f7b2faaf4e
2024年の振り返り

2024年の活動について振り返ります。

# アウトプット

- ブログ: 35本
- 登壇(社外): 5回
- 登壇(社内): 10回くらい？
- その他: マルチクラウドデータベース本

ブログは10本くらいセッションレポートで、自身が集中して聞くためにやっていたようなところがあります。
ブログとしてはAWS少なめ、夏から秋にかけてGoogle Cloudが多めに。これは執筆でいろいろと調べたりしている中でSpannerはじめ面白いな、と思ったことから色々と触ったりしてみました。途中でOCIとの連携とかも出てウェイウェイしてましたね。

春先から夏前くらいまでは執筆が紆余曲折したりして余裕がなかったため、登壇とかブログはお休みしてました。

結果的にはやってみた系の軽い内容のものも多かったですが、実際には業務で私自身がクラウドを触る機会はほぼないので、「やってみた」でも触っておかないと頭でっかちになっちゃうので、これは継続していかないとな、とは考えてます。
とはいえ、たまにはちゃんとした内容のものも書ければな～、とは思ってはいます。業務の内容とあんまりリンクさせることもできないので、妄想ユースケース的なものをワイワイやっていけるようなものが良いのかな、と思ってます。登壇もどちらかというとワイガヤできるようなものが良いな、とは思いますけどなかなかオンラインでは難しいしそもそもそれはクローズドな居酒屋でやれれば良いのでは、となっちゃったり笑。
そういう意味では 荻窪．なにか を始めとして幾つかの新しいコミュニティにも参加したりするモチベーションにはなってますね。

社内の登壇はどちらかというと「誰かいませんか？」の時には基本的に応えるような形でやっているような気がします。公然の秘密ですが、社内でもいろいろと登壇してくれる人は大体卒業が早い（）ので、代打は重宝されるのである。。

執筆はオペレーション的な面でかなり苦戦したので、内容はともかくもし次があればもう少しうまく進行したいと思ってます。。共著、編集、レビュワーの皆様には本当に大変お世話になりました、ありがとうございました。

# お仕事

2022年に異動してからメインで実施していたプロジェクトがなんとかリリースして、大きなトラブルなく安定稼働に入ってくれたことはとても嬉しかったです。新システムの評判も良さそうで、まあ今後も別のシステムが残ってたりと色々とありますけど一山超えた感があります。

とはいえ終わる直前に別のプロジェクト支援に突っ込まれて、久々のオンプレで文化の違いというか、そういえばこういったこと（クラウドでは一瞬でできるようなバックアップとか、断面そろえるとか）に多大なる調整と時間を割いてたな、と改めて思ったりしました。

2025年は今までコツコツと仕込んでたのが日の目をみるか、それとも低空飛行が続くか、というところが私的には大きな注目点です。。

# プライベート

昭和30年(祖父の代)くらいから延々と続いてきた我が家のトラブルがこの11月に円満解決しました、時代は回りますね。

# まとめ

アウトプット自体は上述の理由にもありますが自身が手を動かす機会なので継続していきたいとは思いますが、もう少し方向性は絞った方が良いかな、と思ったりはしてます。
例えば、Oracle@AWS はいろいろなユースケースが考えられるので引き続き追っていきたいと思ってますが、一方でAurora DSQLは若干ユースケースを考えるとまだしばらく良いのかな、とか。。
とはいえ業務とのリンクだけではなくて興味ある事は試していく形は継続したいですね。

メインプロジェクトが終わってから本業が基本支援になっているので、そこは少し安定させていきつつコミュニティ活動もやれるようなバランスを目指したいです。
2025年は蛇年、あと干支が一周したらなんと定年です、健康に留意して長く活動できたら、と思います。
来年も引き続きよろしくお願いします。
STM32F446REの回路設計

STM32を表面実装で使いたい！けどどうやって回路設計すればいいの？どんな周辺部品が必要なの？という方向けの記事です。
難しいことを考えずにシンプルに回路設計してみましょう！
この記事では複雑なことは扱わず、とりあえずSTM32マイコンを動かすために最低限必要な回路を作る、というのを目標とします。
# はじめに

今回はSTM32F446REという部品を表面実装するという前提で、STM32に必要な周辺回路を設計します。
STM32F446RE以外のマイコンでも同じように設計できるので、ぜひ参考にしてみてください。


# 何が必要なの？
STM32マイコンの必要なものは主につです。

- マイコン本体
- コンデンサ
- 書き込み回路
- （発振回路）
- （GPIOの配線）

これだけです！

# 設計しよう
それでは始めましょう。今回はKiCADで設計していきます。
以下、μFをuFと表記しています。

## マイコンを置く
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/1daf2ab1-5ff5-a916-9147-9dd369d9a1a2.png)
どん。
# 電源をGNDにつなぐ
VSSとVSSAというピンをGNDにつないでください。
また、VBATと4つのVDDを3.3Vにつないでください。
VDDAはまだおいておいてください。アナログ用の電源なので後でノイズ対策の回路を通して電源につなぎます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/0b5c73f7-0b97-d6d8-1556-72dfa26b34a4.png)



## コンデンサをつける

まずVCAPというピンに4.7uFのコンデンサをつけてGNDに落とします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/1dbf1230-4cfc-c939-89ea-a3c0acb1171b.png)



次に、VDDの部分にコンデンサを付けます。
VBATとVDDに一つずつ100nFのコンデンサを付けます。また、追加で4.7uFのコンデンサを一つずつ付けます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/8195cc98-bf0b-d240-137a-a5394ffe875e.png)

最後にアナログ電源用のVDDAピンに100nFと1uFのコンデンサをつけて、フェライトビーズを通して3.3Vにつなぎます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/5853e038-a1c4-6099-f706-d755e237d8df.png)

これで電源周りは終わりです。

## 書き込み回路

書き込みはUART書き込みが楽です。
BOOT0ピンをHIGHにすることでUART1かUART3からプログラムを書き込めるようになります。今回はUART1を使います。
UART1はRXがPA10、TXがPA9です。

これをPCとつなげます。別でUSB-シリアル変換を使うのであればUARTのままピンソケットなどで出せばよいですし、基板にUSBコネクタを実装するのであればUSB-シリアル変換回路も作りましょう。

以下はCH340Eを使った例です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/e02a35a5-7b41-2565-b7ab-811b8277d9f1.png)


そして、BOOT0の切り替えのためのスライドスイッチとリセットのためのタクトスイッチをつけます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/a862bf5e-4011-51e1-3459-30e7ca634035.png)


これで完成です！！

## 発振回路
水晶発振器を用意して外部発振回路をつけても良いのですが、基本的には内部にある発振回路で十分なため、初心者の方は特に気にしなくてよいと思います。
## この後
入出力のピン割り当てを決めるときにはSTM32CubeIDEを使うと便利です。
どのピンでどんな機能（UART、I2C、ADCなど）が使えるのかがすぐわかり、その条件の下で割り当てを考えられます。

回路設計が終わって基板設計をする際には、電源ピンにつけたコンデンサはできるだけそのピンの近くに配置するということだけ気を付けてください。ノイズがマイコンに入らないようにするためのコンデンサなので近くに置かないと意味がないです。


# 最後に
STM32はなんだか難しそうなイメージがありますが、ただ動く回路を作るだけなら意外と難しくなさそうですよね。ぜひやってみてください。

より詳しいことを知りたい人は以下の資料が参考になると思います。

https://www.stmcu.jp/design/document/application_note/51505/
VSCodeに生えたGitHub Copilotの困りごと

# はじめに

VSCodeに生えたGitHub Copilotでたくさん遊んでいます。
たのしい！

ただ、ちょっとの困りごとがありますので、こちらにしたためて、改善アップデートがかかったら更新したり、
ご指摘いただいたら更新したりしたいと思います。

# 困りごと

## Copilot Editsで追加したフォルダが削除されない（破棄を選択した場合）

例えば、以下のようにNext.jsのプロジェクト内に、ページを追加してほしかった際、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/8315a38a-0dab-2195-1f7f-da201c8607b3.png)

追加したディレクトリが間違っていたので、「破棄」を選択しました。
追加された間違ったファイルは削除されましたが、フォルダが残ってしまいます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/0dc30f5c-d279-d047-9950-9ee10beb7ec0.png)

目検でCopilotが追加したディレクトリを確認しながら削除するのが、少しストレスです。

## Copilot Editsに表示中のファイルを追加したいのに、できる時とできないときがある

画僧の場所から表示中のファイルを追加できるときもあれば、できないときがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/3019361e-31fa-e52c-ff97-c9131ea3a101.png)

発生条件は体感ですが、以下で多発しています。（多発というのはできる時もある）

・新規チャットを開き直した時
・追加したファイルを削除して、再度選択した場合

## 右クリックで実行した@workspace /explain　にはプロンプトを設定できない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/b500f517-4178-f73c-57fc-20cbc25163bb.png)

細かい話ですが、右クリックで説明コマンドを実行すると、
全体の説明になってしまいます。
無課金勢には、１依頼１依頼が貴重な依頼になるので、もう少し慎重に実行してほしいです。

## 右クリックの選択肢が日本語じゃない場合がある

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3778585/cad0170b-7be5-953c-ca3b-17a610ba8d70.png)

ファイルの中に日本語があるとたまに日本語で表示できたりするんですが、
ほぼ英語になってしまいます。
これはどうしたら日本語になるのでしょうか。。
業務でよく使うGitコマンドまとめ

必ず使う以下のコマンド以外で、業務上個人的によく使うコマンドやオプションをまとめます。
こちらのコマンドの基本的な使い方は調べると色んな方が書いていると思うのでそちらをご覧ください。

- git clone
- git add
- git commit
- git push
- git pull

## ローカルのremoteブランチ状態を最新にする

かなりたくさんの人がいるプロジェクトだと頻繁にブランチが作成・削除されるので、よくこのオプションをつけています。

```bash
$ git fetch --prune
```

以下設定で自動付与も可能。

```bash
$ git config --global fetch.prune true
```

## ローカルの変更内容を一時退避

```bash
$ git stash
```

## 一時退避したリストを見る

```bash
$ git stash list
```

## 一時退避した内容を確認する

```bash
$ git stash show stash@{x} -p
$ git stash show -p # リストの一番上を確認する場合
```

※GUI使ったら楽に内容確認できます。

## 一時退避した内容を取り出す

```bash
$ git stash pop stash@{x}
$ git stash pop # リストの一番上を取り出す場合
```

## ローカルブランチの切ったベースを最新にする

:::note alert
一度push済みのブランチにはやらないでください。
:::

```bash
$ git rebase -i origin/xxxxx
```

コンフリクトが起きたら適宜解消して以下コマンドを打つ。

```bash
$ git rebase --continue
```

やっぱやめたくなったら

```bash
$ git rebase --abort
```

## 一つ前のコミットをローカルに残しつつ無かったことにする

:::note alert
一度push済みのブランチにはやらないでください。
:::

ブランチを移動しまくるためにローカルで一度仮的な感じにコミットをして、その後正しい内容のみでコミットし直す時によくやります。

```bash
$ git reset --soft ^HEAD
```

これでログからは消え、変更内容が全てstaging状態になります。

ここからさらにコードの変更するなりしてreset/restore、add、commitしてください。

## 部分的に作業を元に戻す

※GUI使ったら楽ではあります。

部分だけaddして、残した分を全て戻します。

```bash
$ git add -p .
$ git restore . または git checkout .
```

### （おまけ）部分的にstagingに追加する

これもGUI使えばいい話ですが、通常のコミットも作業内容確認と作業用の不要なコードをコミットしないために`git add -p`で内容を確認しつつstagingしてます。

がっつとまとまってしまう場合は`s`で分割してます。

よく使うのは、`y`, `n`, `q`, `s`, `g`です。

```bash
y - この変更部分（hunk）をステージングする
n - この変更部分をステージングしない
q - 終了する。この変更部分および残りの変更部分をステージングしない
a - この変更部分およびファイル内のそれ以降の変更部分をすべてステージングする
d - この変更部分およびそれ以降の変更部分をすべてステージングしない
j - この変更部分を保留にして、次の保留中の変更部分に進む
J - この変更部分を保留にして、次の変更部分に進む
g - 移動する変更部分を選択する
/ - 指定した正規表現に一致する変更部分を検索する
e - 現在の変更部分を手動で編集する
? - ヘルプを表示する
```

## 直前にいたブランチに移動

```bash
$ git switch - または git checkout -
```

## ブランチ名を変える

```bash
$ git branch -m 変更後のブランチ名 # 今いるブランチの場合
$ git branch -m 現在のブランチ名 変更後のブランチ名
```

## 直接コミットしないブランチをローカルで最新化する

mainやdevelopは直接コミットが禁止されていることが多いですが、ローカルに落としていると思います。

変更内容が多すぎたり、git pullしてもうまくいかない時、ローカルから該当ブランチを一度消して最新に切り替えます。

```bash
$ git branch -D develop
$ git fetch
$ git checkout develop
```

## まとめ

使用タイミングに注意すべきコマンドもありますが、ポイントを押さえておけば通常の作業で便利なコマンドもたくさんあります。

たまに不安になって自分もやりますが、動作がイマイチ分からないものは壊してもいいリポジトリを作って挙動を試した上で使ってください。
会議文字起こしAIの活用とそのメリット

現代のビジネス環境では、会議の効率性が重要視されています。特に、リモートワークの普及に伴い、多くの会議がオンラインで行われるようになり、会議内容を正確に記録することが求められています。ここで登場するのが「会議文字起こしAI」です。この技術は、会議中の発言を自動的にテキストに変換し、手動でメモを取る手間を大幅に削減します。

### 会議文字起こしAIとは？
会議文字起こしAIは、人工知能（AI）を活用して、音声データをリアルタイムでテキストに変換するツールです。この技術を活用することで、会議中に話された内容を漏れなく記録でき、後で必要な情報を簡単に検索・確認することができます。また、議事録を作成する際にも、大きな負担を軽減することができます。

### 会議文字起こしAIの利点
1. **時間の節約**
従来の手動による議事録作成は、多くの時間と労力を要しましたが、文字起こしAIを活用することで、瞬時に音声をテキスト化できます。これにより、会議後の作業時間を大幅に削減できます。

2. **正確な記録**
人間によるメモは、時には曖昧だったり、重要な内容を見逃したりすることがあります。しかし、AIによる文字起こしは、会議中の発言を漏れなく記録するため、発言の取り違いや抜け漏れの心配がありません。

3. **容易な検索**
テキスト化された会議内容は、後からキーワードで簡単に検索でき、必要な情報をすぐに見つけることができます。これは、特に長時間にわたる会議や複数のトピックが扱われた場合に非常に便利です。

###  Soro.jp：効率的な会議文字起こしAIツール
会議文字起こしAIを活用するためには、優れたツールが必要です。その一例がSoro.jpです。このツールは、会議中の音声を高精度にテキスト化し、会議後の議事録作成を大幅に効率化します。特に、使いやすいインターフェースと高度なAI技術を兼ね備えており、どのような規模の会議でも効果的に利用できます。
さらに、[Soro.jp]((https://soro.jp)) は日本語に特化した文字起こし機能を提供しているため、国内のビジネスシーンにおいて非常に有用です。

### まとめ
会議文字起こしAIは、現代のビジネス環境において欠かせないツールとなりつつあります。手動でのメモ取りや議事録作成の負担を軽減し、会議後の生産性を向上させるために、文字起こしAIの導入は今後ますます広がるでしょう。特に、Soro.jpのような先進的なツールを活用すれば、会議の効率がさらに向上すること間違いありません。ぜひ、この機会にSoro.jpを試してみてはいかがでしょうか。
Azure OpenAIをDify（v0.14.2）にセットアップするメモ

備忘録的にDifyとAzure OpenAIの連携メモです。

## ローカルでDifyを試すまで

MacにDockerを入れてdocker-composeで起動

https://note.com/south373/n/n9664d5b5141c

こちらのリポジトリからcloneしてくる

https://github.com/langgenius/dify

dockerフォルダがあるのでその中で`docker compose up -d`

```
$ cd docker
$ docker compose up -d
```

http://localhost/installにアクセスするとログイン画面に

> ![スクリーンショット 2024-12-31 22.40.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/10504b23-617a-2c43-31db-54653ca8eea3.png)

これでローカル起動はOK

## Azure OpenAIでモデル準備

Azureのポータルで作成

> ![](https://i.gyazo.com/13c00cddfc3118d4899509a78f5d444c.png)

- モデルを作成してデプロイ gpt-4o-miniを指定してみました。

> ![スクリーンショット 2024-12-31 22.43.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/3d8e6555-4ea6-6d98-915e-2935741f753e.png)

`APIキー` と`エンドポイントURL` が表示されるのでそれを控えておく

## Dify側で設定

Difyの画面から、設定 -> モデルプロバイダーからモデルを追加。

`Azure OpenAI Service`を見つけて追加します。

> ![スクリーンショット 2024-12-31 22.23.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/1a690df9-6aa1-6689-3594-fff41008a53f.png)

API VersionはデプロイしたときのURLに書いてあります。`?api-version=2024-08-01-preview`などがURLについてます。

> ![スクリーンショット 2024-12-31 22.48.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/a5dc8d70-89e0-8291-257b-f5d8b6331945.png)

無事に追加できるとモデル一覧に表示されます。

> ![スクリーンショット 2024-12-31 22.19.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/b837a5ef-a687-d774-ea03-9c0fb2875d17.png)

## Difyのワークフローで使う

追加が無事にできるとワークフローではLLMモジュールで利用できます。

> 他に設定していたllama3以外に今回設定したgpt-4o-miniの表示が出た
> ![スクリーンショット 2024-12-31 22.24.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/189e9c7f-eb72-a841-0414-c40031b21cd6.png)


あとは通常Difyを使う感じでLLMモジュールとして利用できます。

> ![スクリーンショット 2024-12-31 22.25.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/80a48e80-36ac-8db7-10f3-7c64b97813db.png)


## まとめ

ローカルDifyとAzure OpenAIを接続できました。Azureのクレジット+ローカルDifyでやる人には良さそう。



## 蛇足

ちなみにAzure AI StudioのモデルプロバイダーではAPIキーとエンドポイントなど入れてもエラーがでたので何かがちがうっぽい...?

> ![](https://i.gyazo.com/cc898328cf391f800eb9c90ff85b09a1.png)

関係ないけどAzure Web AppsのコンテナデプロイでDify使いたいけど上手くいかない...

この辺試した方いたら教えてくれるとうれしいです。
iOSアプリでHTML・JavaScriptの実行が必要なときに、リファラーを設定する方法

# システム内容(ざっくり)
とあるiOSアプリを作っているのだが、新たに実装の必要のある機能で必須として使う必要のあるライブラリがHTML・JavaScriptが前提なものになっていて、しかしiOSアプリなのでWKWebViewを用いて裏側でHTML・JavaScriptを実行するような処理を作った。

そのライブラリのメソッドを呼ぶことでAPIを呼ぶような処理になっているが、エラーとなった。それは、リファラーが空であることが原因だった。

# 原因
iosアプリとしてではなくブラウザ向けのシステムとしてchromeなどの通常のブラウザで実行したら、当然デフォルトでリファラーは入っているが、iOSアプリの内部ブラウザからアクセスした場合はリファラーが入っていないようだった。

WKWebViewを使っている場合、HTMLがローカルにあるとリファラーが空になる。これは、リファラーは通常リクエスト元のURLを示すため、ローカルファイルの場合はリファラーが設定されない

# 解決策
baseURLを指定するだけでよかった。

```swift:anime-suko.swift
var webView: WKWebView!

self.webView.loadHTMLString(htmlString, baseURL: URL(string: Configuration.shared.apiUrl))
```

baseURLを指定すると、WKWebViewはそのURLを基準としてHTMLコンテンツを読み込みます。Refererヘッダーは、リクエストがどのページから来たのかを示すもので、サーバー側でリクエストの出所を確認するために使われます。これを指定したらなんとかサーバー側でリファラーが入るようにできた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/179803/c95ba997-3fd9-3ee3-a61e-1236a5a685d1.png)
カラーセンサS9706を使ってみる

S9706というカラーセンサをArduinoで使ってみます。

# S9706とは
浜松ホトニクス製のカラーセンサです。
12bitでRGBの値が読めます。
秋月電子のリンク

https://akizukidenshi.com/catalog/g/g102493/

浜松ホトニクスのリンク

https://www.hamamatsu.com/jp/ja/product/optical-sensors/photo-ic/color-sensor/rgb-color-sensor/S9706.html

# 配線

S9706はI2Cなどではないため普通のデジタル入出力ピンで使えます。

S9706のピン配置は以下のようになっています。（[データシート](https://akizukidenshi.com/goodsaffix/S9706.pdf)より）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/3426dccd-ef64-6719-d66b-3f14c17d8d39.png)

1,4,5,6をデジタルピンに、2を5Vまたは3.3Vに、3をGNDに接続してください。

表面実装部品ですが、1.27mmのSOP変換基板などを使えばブレッドボード上で使えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3124670/2ce872d0-f1a8-8346-f2bb-639352bb20a8.png)


S9706の上下に気を付けてください。二本線のようなものが見える方が上です。


# プログラム

以下のようなプログラムを書きます。

データの読み取りの仕組みについては[データシート](https://akizukidenshi.com/goodsaffix/S9706.pdf)の「タイミングチャート」というところをご確認ください。


```S9706.ino
#define RANGE 2
#define GATE  3 
#define CK   4 
#define DOUT 5 

int red, green, blue; // RGB値を格納する変数

int tg = 50; // 積分時間

void setup() {
  pinMode(RANGE, OUTPUT);
  pinMode(GATE, OUTPUT);
  pinMode(CK, OUTPUT);
  pinMode(DOUT, INPUT);
  Serial.begin(9600);
}

void loop() {
  digitalWrite(GATE, LOW);
  digitalWrite(CK, LOW);
  delayMicroseconds(2000);

  // 感度設定
  digitalWrite(RANGE, HIGH);

  // 光量の積算を開始
  digitalWrite(GATE, HIGH);
  
  delay(tg + 1); // 積分時間だけ待つ

  // 光量の積算を終了
  digitalWrite(GATE, LOW);
  delayMicroseconds(4); 

  // 測光データを取得
  red = readColor();
  green = readColor();
  blue = readColor();


  digitalWrite(GATE, HIGH);


  Serial.print(red);
  Serial.print(" ");
  Serial.print(green);
  Serial.print(" ");
  Serial.println(blue);


}

// 12ビットのデータを読み取る
int readColor() {
  int result = 0;
  for (int i = 0; i < 12; i++) {
    digitalWrite(CK, HIGH);
    delayMicroseconds(1);
    result |= (digitalRead(DOUT) << i);
    digitalWrite(CK, LOW);
    delayMicroseconds(1);
  }
  delayMicroseconds(3);
  return result;
}
```

これでRGB値を取得することができました！

適切な積分時間・感度を探してみてください！
Windows 環境でキー操作時の挙動がおかしいキーボードをうまく使う

# 経緯
日常使用しているキーボードが故障したため、急場をしのぐために物置からキーボードを拾って使うことにしました。ところが…。

# どこがおかしかったのか
LShift, RShift, Numpad0 の挙動がおかしい或いは機能しない。  
  
# どういったキーボードか
* HMB-35957-U22
* いわゆる英語配列キーボード
* XT, AT 両対応
* AT 対応動作に設定し、PC の PS/2ポート へ接続し使用
  
# おかしいキーのスキャンコードを調べる
私は DirectX 8.1 SDK に入っていた Keyboard.exe(DirectInput Keyboard Sample) を利用したのですが、[Keymill](https://www.vector.co.jp/soft/winnt/util/se489724.html) でもよいようです。  
  
スキャンコードは次のようでした。
```
LShift: 56H
RShift: 73H
Numpad0: 7cH
```

# *.reg ファイルを作成し、レジストリに書き込む
次の資料が役立つはずです。  
* [Configuration of keyboard and mouse class drivers: Scan code mapper for keyboards](https://learn.microsoft.com/en-us/previous-versions/windows/hardware/hid/keyboard-and-mouse-class-drivers#scan-code-mapper-for-keyboards)  
* [scancode.doc](https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/scancode.doc)  
* [translate.pdf](https://download.microsoft.com/download/1/6/1/161ba512-40e2-4cc9-843a-923143f3456c/translate.pdf)  

詳しいことは google.com で Scancode Map site:qiita.com などを検索すれば色々と出てくるので、それをご覧になればよいでしょう。  
  
次のような *.reg ファイルを作ればよいようです。
```
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Control\Keyboard Layout]
"Scancode Map"=hex:\
  00,00,00,00,\         ; バージョン
  00,00,00,00,\         ; フラグ
  04,00,00,00,\         ; NULL終端含むエントリ数
  2a,00,56,00,\         ; 01 LShiftの修正(56H -> 2aH)
  36,00,73,00,\         ; 02 RShiftの修正(73H -> 36H)
  52,00,7c,00,\         ; 03 Numpad0の修正(7cH -> 52H)
  00,00,00,00           ; 04 NULL終端
```