OmniAICreator/Qiita-1.07M huggingface dataset:
【通勤ハック】通勤電車で座る戦略をSEがマジメに考える

# 前書き
朝の通勤電車で座りたい！
座れるとちょっと得した気分になる。
皆さんそんな思いはございませんか？
リモートワーク主体で在宅勤務が多くなっている昨今、たまの通勤だからこそ、電車での体力消耗は最低限に抑えたいですよね。

## 電車で座るための提案書
2024年3月、みずほリサーチ&テクノロジーズさんが山手線トレインジャック広告を展開しました。
「電車の中で座りたい」
という身近な欲求に対して、
* 電車が混雑する背景分析
* 乗客へのアンケート調査
* 上記をもとにしたアクションプラン

という、「問題解決プロセスのための提案書」形式で広告を掲出していました。
[電車の中で座るための戦略とアクションプラン](https://www.mizuho-rt.co.jp/company/brand/pdf/kaiketsu.pdf)

## 郊外から都内への通勤ではどうしたら…
提案書は首都圏、特に山手線メインとした内容です。
それでも75%もの人が「できれば座りたい」と回答しています。
郊外から都内へ通勤している方であればより多くの方が「座りたい」と思うのではないでしょうか。
この記事では、郊外から都内に向かう電車で、私が実践し<font color="red">70%</font>くらいの確率で座れていた戦略を紹介します。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/a30721f2-418d-fd0b-822d-b29d84957568.png" width=300>

- - -

# 調査と実践
[基本方針](#基本方針)
[多くの人が降車する駅の便利な車両・ドアを調査](#多くの人が降車する駅の便利な車両ドアを調査)
[乗車する電車の調査](#乗車する電車の調査)
[乗客の様子を調査](#乗客の様子を調査)
[実践時の注意](#実践時の注意)

- - -
## 基本方針
決まった時間に出勤するため、日々同じ時間の電車に乗る人は多いです。
その中で、自分の目的地の前に降りる人を見つけ出し、その人の前の立ち位置を確保することを目指します。

## 多くの人が降車する駅の便利な車両・ドアを調査
郊外から都心へ向かう電車だと、ほとんどの駅で乗り込む人>降りる人となりますが、
別路線への乗り換えができる駅は降りる人が多く、座れる確率が高くなります。
乗換駅など、多くの人が降りる駅で便利な車両・ドアを確認しましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/30ebd895-7499-9883-3050-c3c790980b11.png">

## 乗車する電車の調査
ピーク時間帯を外せれば座れる確率は上がります。
時間をずらせない場合でも、快速などの利便性の高いものvs普通電車の混雑具合も考慮します。
メイン候補と前後2本ずつ、5本程度の候補を決めて、実際に乗ってみましょう。
この時、列の2-3番目くらいに並ぶにはどのくらいの時間までに駅に着く必要があるかもチェックしておくとよいでしょう。

## 乗客の様子を調査
よく見かける人で、途中駅で降りる人・降りない人をチェックします。
なるべく決まった電車に乗っている人を覚えておくと、自分の乗る電車を決める判断基準にもなります。
見分けやすく覚えやすいのは以下のような人たちです。
* 学生
制服で見分けられるようになる
別の時間帯の電車にも対応できる可能性がある
ただし、学生だけに頼りすぎると長期休暇期間・テスト期間に対応できない
人の入れ替わりはあっても長期的な運用が期待できる
* 通勤客（座っている人）
安定した運用が可能
服装や持ち物ではなく、顔を覚えておく必要がある
たまに乗っていない日があるとちょっと心配になる
* 通勤客（乗り込んでくる人）
同じタイミングで乗り込む人やあとから乗り込んで来る人
「あの人、いつも同じような位置に立って、気付いたら座ってるな」と思ったら近くに座っている人をチェック
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/df849576-f3ba-96e3-3ace-c82bd5a10ec6.png"
 width=300>

***
ここまでで降車する人の傾向をつかんだら実践あるのみです！
***

## 実践時の注意
* 決まった時間の電車に乗れるようにする
事前調査を活かせるように、なるべく決まった時間帯の電車に乗れるように頑張りましょう
* ホームで並ぶ際は2番目くらいまで
前に人が多いと、自分の導線がイメージしにくくなります
* ホームに入ってくる電車の窓から車内の様子をチェック
目当ての人が乗っているか、そこまでの導線確認
* 他の乗客の迷惑になる行動はとらない
降りてくる人優先！人を押しのけないetc...
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/1c035e62-288e-8dcc-6971-e9a4cf9967db.png"
 width=300>

***
# 最後に
みずほR&Tの調査では電車で座りたいと考える人は75%にのぼるそうです。
競争率の高い争奪戦ですが、戦略を立てて効果的に機会をモノにしていきたいですね！
ただし、座りたい！の一心で他の乗客に迷惑をかけないように注意しましょう。
また、自分が座れているときでも立っていることがしんどそうな方がいる際には席を譲りましょう。
マナーを守って快適な通勤生活を！
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3799996/6f8b58fb-bceb-c225-4bf1-91944d38488d.png"
 width=300>
Windows11 HomeEditionからUbuntu22.04 LTSにGoogleリモートデスクトップでアクセスする

# ■背景
Windows11 HomeEditionでリモートデスクトップのクライアント機能が使えないことい気づく。代替えになるものを探していたところGoogleリモートデスクトップにいきついた。

## 1 Googleリモートデスクトップをインストール
1-1.リモートデスクトップをダウンロード
以下コマンドでカレントディレクトリにダウンロードされます
```console　
$ wget https:dl.google.com/linux/direct/chrome-remote-desktop_current_amd64.deb
```

1-2.インストール
```console　
$ sudo apt install ./chrome-remote-desktop_current_amd64.deb
```
## 2 Ubuntu側(接続される側)の設定
2-1.remotedesktop.google.come/accessにアクセスし、「SSH経由でセットアップする」を
クリック
![スクリーンショット 2024-09-25 000208.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/d1c730c8-cf5f-cafb-d20d-cb92d3fa9208.png)


2-2.「開始」⇒「次へ」⇒「承認」をクリックし、「Debian Linux」のコードをコピー
![スクリーンショット 2024-09-25 000555.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/01c64567-ee8b-cfb6-2f7e-29446676d718.png)

2-3.コピーしたコマンドをターミナルに貼り付け実行
```console　
$ DISPLAY= /opt/google/chrome-remote-desktop/start-host --code="4/0AQlEd8yEvAIuwm4N7ArXBf9aK29q7jgiOYKtxE2LV5cbgc-m8ayBzTwiGeZcXjrCnvG1-Q" --redirect-url="https://remotedesktop.google.com/_/oauthredirect" --name=$(hostname)
```
2-4 PINコードを聞かれるので6桁以上のPINコードを２回入力しEnter

## 3 Windows側(接続側)の設定
3-1 remotedesktop.google.come/accessにアクセスし、表示されているlinuxPCを選択
![スクリーンショット 2024-09-25 001456.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/17c87fdd-f530-e767-dcba-698babfa895f.png)

3-2 2-4で設定したPINコードを入力しEnter
![スクリーンショット 2024-09-25 001742.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/a75f9c42-f46d-9fe9-bc7f-2f5e3ab270ac.png)

3-3 Ubuntuが表示される
![スクリーンショット 2024-09-25 002433.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3887509/28ce8c4a-ef91-86ee-23f3-2165daf0c98e.png)
とあるお仕事の記録

# はじめに

最近、Qiitaへの投稿ができていませんでした。特に新しい技術を学ぶ機会が少なかったというのが大きいのですが、逆に基礎的な知識が必要になることがあったので、ざっくりまとめてみたいと思います。

# 背景

同じソースコードを使って異なるPCでビルドしたexeが、同じように動くことを説明する必要がありましが、exeにはバイナリレベルで数バイトの差がありました。開発する側の人間からすると、気にするなと言いたいところですが、どこの世界でも外部に対してはそれなりに筋の通った説明が必要になるのです。

なお、今回の基本的な条件は以下の通りです。（細かいところは意図的に濁しています）

* 使用するフレームワークなど
  * QtとVisualStudioは全環境で統一（同じインストーラを使用）
* ビルド環境
  * 異なるWindows環境

:::note warn
今回コンパイラにはVisualStudioを使っていました。おそらくどのコンパイラも、以下のようにバイナリの同一性は保証していないと思いますので、あくまでこの記事の内容は自己責任で参照願います。

[同一ソースコードから生成されるビルド成果物のバイナリ同一性について](https://jpdscore.github.io/blog/vs/identity-of-build-artifacts-from-identical-source/)
:::

# ビルド日時の違い

まずは普通に考えて、exeにはビルド日時が埋でのめ込まれているはずなので、その埋め込まれ方を調べました。現在のWindowsでのexeのフォーマットについては、だいたい次のページでわかります。

[PE形式](https://learn.microsoft.com/ja-jp/windows/win32/debug/pe-format)

このページに従いexeのバイナリを読んだところ、COFFファイルヘッダーのTimeDateStampに埋め込まれているビルド日時の違いで説明できました。

# 想定外の差分

上記のビルド時刻のズレで基本的に問題はなくなったのですが、ある環境だけまったく別の差分が出ていました。その環境でのビルド動作を順に調査したところ、Qtが作成してVisualStudioに渡している中間ソースコードの中に、exeに埋め込む画像のファイル名と何らかの日時が存在し、その環境だけその日時がわずかに違うようでした。

そこで該当のバージョンのQtのソースコードをダウンロードし、問題のソースコードに日時を書き出している部分を読むと、リソースとして埋め込む画像ファイルの作成日時であることと、埋め込まれている形式が分かりました。

そして具体的に埋め込まれたバイナリを形式に従い読んでみたところ、本来のファイルの作成日時が偶数秒に丸められミリ秒がありませんでした。この段階で分かる人には分かると思いますが、この環境にソースコードを持ち込む際、FATフォーマットのUSBメモリを使用していたため、画像ファイルの作成日時が変化していたのが原因でした。

[ファイルのタイムスタンプの設定と取得](https://learn.microsoft.com/ja-jp/windows/win32/fileio/setting-and-getting-the-timestamp-of-a-file)

# 結論

どんな最新技術を使おうとも、結局はOSやコンパイラの制限などは避けられません。新しい技術も必要だけど、昔から経験したことはなんらかの形で役に立つと実感したお仕事でした。
広告プレビューと診断ツールの活用

# 検索広告の表示確認
こんにちは、所属企業で広告運用を担当している鈴木です。

前回は、Google検索広告を検索パートナーとGDNに配信する方法を記事にしました。

ところで、広告運用を行っているみなさんは、自分が配信している検索広告の掲載・表示をどのように確認していますでしょうか？

検索窓にキーワードを入力して、検索結果で確認しているという方も多いかもしれません。

しかし、そのやり方はおすすめできません。
なぜなら、表示回数やクリック数をはじめとする広告実績に影響が出る恐れがあるからです。

ということで今回は、広告実績に影響を及ぼすことなく掲載結果を確認できるGoogle広告のツールについて書いていきたいと思います。

## 「広告プレビューと診断」ツール
自分が配信しているGoogle検索広告の掲載・表示状況を確認したいときに活用できるのが、「広告プレビューと診断」ツールです。

このツールでは、管理画面上から検索語句や地域、言語、デバイス等を設定し、
その条件下での実際の広告掲載・表示状況を確認することが可能となっています。

このツールを活用することで、広告実績に影響が出ないこと以外にも様々なメリットがあります。

たとえば、

- 東京にいながら大阪での掲載・表示状況を確認するなど、配信地域外からでも状況確認が可能
- 広告が表示されていない場合の理由を確認できる
- 様々な広告オプションの表示有無や、表示されない理由を確認できる

といったことが挙げられます。

## ツールの使い方
![スクリーンショット 2024-09-13 113224.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3780649/91b90851-dc4c-b37c-ec02-f95103b031ee.png)

Google広告管理画面にログイン後、左メニュー「ツール」をクリックし、トラブルシューティングから「広告プレビューと診断」を選択します。

上部に検索語句を入力し、住所・言語・デバイス・視聴者を選択すると、検索結果のプレビューが表示されます。

広告が表示されていない場合は、「結果」でその理由を確認することができます。

## まとめ
「広告プレビューと診断」ツールは、自分が配信している検索広告の掲載・表示状況を確認できるだけではなく、
広告が表示されていない理由などを確認し、配信設定の改善につなげることもできる非常に優秀なツールです。

ぜひ活用してみてください。

以上、鈴木でした。
Gemini API ― チャット

# 概要
- [Gemini編 - 総目次](https://qiita.com/search?sort=&q=tag%3AGemini++user%3Ashokkaa)

(日記)前回

https://qiita.com/shokkaa/items/0e257a5e9c069402c80c

の続き。Node.jsで試す。

# 環境
- Ubuntu 24.04
- Node.js v22.4.1

# Project準備 
https://qiita.com/shokkaa/items/6f83b3a107006ccc598b

# generateContent() ―― 一問一答
```ts:src/generateContent.ts
import { GoogleGenerativeAI } from "@google/generative-ai"

async function main() {
    const key = process.env.GOOGLE_API_KEY ?? ""
    const genAI = new GoogleGenerativeAI(key)
    const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" })
    
    async function qa(q: string) {
        const a = await model.generateContent(q)
        console.log(`Q: ${q}`)
        console.log(`A: ${a.response.text()}`)
    }

    await qa("三角、四角、五角形、の次は? 簡潔に")
    await qa("その次は? 簡潔に")
}

main()
```
```sh:Run
export GOOGLE_API_KEY=<your-api-key>
npx -y ts-node src/generateContent.ts 
```

```:結果
Q: 三角、四角、五角形、の次は? 簡潔に
A: 六角形。

Q: その次は? 簡潔に
A: 「その次は」は何の続きについてですか？もう少し詳しく教えてください。
```

# startChat()/sendMessage() ―― 文脈を覚えてほしい

```ts:src/sendMessage.ts
import { GoogleGenerativeAI } from "@google/generative-ai"

async function main() {
    const key = process.env.GOOGLE_API_KEY ?? ""
    const genAI = new GoogleGenerativeAI(key)
    const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash" })
    const chat = model.startChat()

    async function qa(q: string) {
        const a = await chat.sendMessage(q)
        console.log(`Q: ${q}`)
        console.log(`A: ${a.response.text()}`)
        console.log(a.response.usageMetadata)
    }

    await qa("三角、四角、五角形、の次は? 簡潔に")
    await qa("その次は? 簡潔に")
    await qa("その前は? 簡潔に")
}

main()
```
```sh:Run
export GOOGLE_API_KEY=<your-api-key>
npx -y ts-node src/sendMessage.ts 
```

```:結果
Q: 三角、四角、五角形、の次は? 簡潔に
A: 六角形です。
{ promptTokenCount: 16, candidatesTokenCount: 5, totalTokenCount: 21 }
Q: その次は? 簡潔に
A: 七角形です。
{ promptTokenCount: 31, candidatesTokenCount: 5, totalTokenCount: 36 }
Q: その前は? 簡潔に
A: 三角形です。
{ promptTokenCount: 46, candidatesTokenCount: 4, totalTokenCount: 50 }
```

この例のToken合計(平均)
gemini-1.5-flash: 50,48,50 (49.3)
gemini-1.0-pro: 41,41,41 (41)
gemini-1.5-pro: statusText: 'Too Many Requests' (2回/分制限)


# 今回のソースコード

https://github.com/kyoya-p/samples/tree/master/2024/Gemini/GemCode3
中古パソコン買った際の作業リスト


# 20240924_中古パソコン買った際の作業リスト

## 購入後直ぐに
- 写真：全体写真撮っておく。
- 管理：型番、シリアル、購入日、金額をメモしておく。
- 初期化：取り敢えずは初期化して利用開始。
- OS更新：基本は先ずは最新にしておく。

## 情報収集
- 情報収集：HW関係、OS関係。

:::note info
例えば情報収集の例は以下をご確認ください。
:::
https://qiita.com/kubo4ka/items/95c5130a5295817feaba

## OS設定
- 指紋認証：必要なら設定。伴うPINも設定。
- OS設定：不要アプリ削除、不要機能オフ、縦横固定、キーボード設定、表示スケール、powercfg、必要ならジャンクション設定、クイックアクセス不要、taskmgrデフォルトパネル、タスクバー整理、スタートメニュー整理、Users日本語化解除、エクスプローラ＞フォルダの非表示、拡張子表示。
- ディレクトリ構成：linuxライクに、FHSな感じに変更。
- gpedit：コルタナ停止。
- Windowsストア：ターミナル追加、ubuntu追加。
- appwizかPowerShell：WSLを有効化。

## アプリ追加
- chocolaty：choco install -y googlechrome firefox cmder vscode vagrant virtualbox 7zip winmerge wireshark gimp libreoffice-fresh
- キー配置：気になる点あればAHK設定。choco install autohotkey -y

:::note info
chocolateyの説明が必要な場合は以下をご確認ください。
:::

https://qiita.com/kubo4ka/items/96484112f1ed745bf141

## その他
- 発熱対策：気になる点あればサーマルパッド貼り付け。
- 電池劣化：必要なら交換。

:::note info
そもそも中古パソコン買うならどんなこと考えるかは以下をご確認ください。
:::

https://qiita.com/kubo4ka/items/aaab0029cf88c9838dc7

以上
Ubuntuにgooglechromeをインストールする方法

1.ダウンロード
$ wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb

2.インストール
$ sudo apt install ./google-chrome-stable_current_amd64.deb

3.起動する
$ google-chrome

◯例外エラー
22.04ltsで起動時に描画されず真っ白になることがある。下の方法で解決した。
以下のディレクトリ内のファイルを削除し、Ubuntuを再起動します。
 ~/.config/google-chrome/Default/GPUCache
Gemini API - 導入編

# 概要
(日記) [Google Gemini API](https://ai.google.dev/gemini-api)を試してみよう。
[Gemini編 - 総目次](https://qiita.com/search?sort=&q=tag%3AGemini++user%3Ashokkaa)

# 環境
- Ubuntu 24.04
- Kotlin 2.0.0

# 料金
https://ai.google.dev/pricing?hl=ja

# Gemini準備
[Google AI for Developer](https://ai.google.dev/gemini-api/docs/api-key?hl=ja) → Google AI Studio → Get API Key → プロジェクト選択しAPIキーを作成 
※APIキーは非公開。GitHub等にコミットしないよう注意。

[→APIキー参照](https://aistudio.google.com/app/apikey?hl=ja)

```sh:テスト
GOOGLE_API_KEY=<YOUR_API_KEY>
curl -H 'Content-Type: application/json' \
-d '{"contents":[{"parts":[{"text":"説明: AIはどのように動くのか?"}]}]}' \
-X POST \
'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key='"$GOOGLE_API_KEY"
```

```sh:使用可能model列挙
curl https://generativelanguage.googleapis.com/v1beta/models?key=$GOOGLE_API_KEY
```

# URLを直に叩いてみる
カレントディレクトリ以下にあるコード(つまり自身)をレビューし改善するkotlinサンプルコード
```src/main/kotlin/Main.kt
suspend fun main(args: Array<String>): Unit = with(FileSystem.SYSTEM) {
    val key = System.getenv("GOOGLE_API_KEY") ?: throw IllegalArgumentException("Not Found: GOOGLE_API_KEY")
    fun srcs() = listRecursively(".".toPath()).filter { it.name.endsWith(".kt") }.map { read(it) { readUtf8() } }
    val client = HttpClient(CIO) { install(ContentNegotiation) { json(Json { ignoreUnknownKeys = true }) } }
    client.post("https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=$key") {
        contentType(ContentType.Application.Json)
        setBody(ReqGemini(listOf(ReqContent(listOf(ReqPart("コードレビューして: ${srcs().joinToString()}"))))))
    }.body<ResGemini>().also(::println)
}

@Serializable data class ReqGemini(val contents: List<ReqContent>)
@Serializable data class ReqContent(val parts: List<ReqPart>)
@Serializable data class ReqPart(val text: String)
@Serializable data class ResGemini(val candidates: List<ResCandidate>)
@Serializable data class ResCandidate(val content: ResContent)
@Serializable data class ResContent(val parts: List<ResPart>, val role: String)
@Serializable data class ResPart(val text: String)
```
[コード全部](https://github.com/kyoya-p/samples/tree/master/2024/Gemini/GemCode2)


```sh:Run
export GOOGLE_API_KEY=<YOUR_API_KEY>
sh ./gradlew run

ResGemini(candidates=[ResCandidate(content=ResContent(parts=[ResPart(text=コードレビューですね！コードの可読性と保守性を高めるため、いくつかの修正案を提案させていただきます。

**1. 定数の命名:**

{{...中略...}}

これらの変更点によって、コードの可読性と保守性が向上し、将来の変更や拡張が容易になります。)], role=model),

{{...中略...}}

usageMetadata=ResUsageMetadata(promptTokenCount=696, candidatesTokenCount=1235, totalTokenCount=1931))
```

# 参考
#### Geminiモデル別仕様表

https://ai.google.dev/gemini-api/docs/models/gemini?hl=ja

#### Vertex AI API
Gemini APIも共通部分多いと期待

https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/count-tokens?hl=ja

#### Java APIリファレンス-  google-cloud-aiplatform

https://cloud.google.com/java/docs/reference/google-cloud-aiplatform/latest/overview

#### 公式サンプルコード
だいたいPython用しかなくて残念

https://cloud.google.com/docs/samples?hl=ja&text=Gemini
VSCodeで登録したMarkdownスニペットが出てこないときの解決方法

# はじめに

　Visual Studio Code(VSCode)は，ご存知の通り様々な言語に対応したエディタです．もちろん Markdown にも対応しています．
　多くのエディタでは頻繁に使用するコードのパターンを簡単に挿入できるスニペットという機能があり VSCode でも対応しています．しかし，Markdown では他の言語と同様の方法でスニペットを登録しても，編集中の候補として出てきません．
　ここでは，Markdown でスニペットを利用できるようにする方法について書いていきます．

# 解決方法

`settings.json`に以下のコードを挿入します．

```json
  "[markdown]": {
    "editor.quickSuggestions": {
      "comments": "on",
      "strings": "on",
      "other": "on"
    }
  }
```

言語を指定する必要がなければこのようにしても良いです．

```json
"editor.quickSuggestions": {
    "other": true,
    "comments": false,
    "strings": false
}
```

## `settings.json`の開き方がわからない場合

[この記事](https://qiita.com/y-w/items/614843b259c04bb91495)を参考にすると良いです．

## `settings.json`への挿入がわからないとき

[この記事](https://qiita.com/shuntaro_tamura/items/5a92c517a7d95d655505)で json の書き方を把握すると良いです．

または以下を参考に

```json
{
  // いろいろ書いてある
  ほげほげ, // なければ文末にカンマを挿入
  "[markdown]": {
    "editor.quickSuggestions": {
      "comments": "on",
      "strings": "on",
      "other": "on"
    }
  }
}
```

例えばこんな感じ．

```json
{
  "editor.renderWhitespace": "all", // 半角スペースを可視化
  "[markdown]": {
    "editor.quickSuggestions": {
      "comments": "on",
      "strings": "on",
      "other": "on"
    }
  }
}
```

設定が波カッコや角カッコの入れ子の場合もあります．

```json
{
  "[tex]": {
    "editor.suggest.snippetsPreventQuickSuggestions": false,
    "editor.tabSize": 2
  },
  "[markdown]": {
    "editor.quickSuggestions": {
      "comments": "on",
      "strings": "on",
      "other": "on"
    }
  }
}
```
【JavaScript】高齢者の色覚を確認できるツールサイトを作ったわよ

:::note warn
2024/9/26追記

本記事の画像は「20歳から見た」**相対的**な高齢者色覚となっています。
本アプリについて、閲覧者の年齢に基づいた相対画像を出力するように修正しました。
:::

:::note
このサイトのお話をしています: https://konbraphat51.github.io/ElderVisionSimulation/
:::

## はじめに
[User-Friendlyの王、User-Firendlyキング](https://qiita.com/uts1_6/items/11e348ead4bae71571b8)になりたいですよね。

現在卒論で認知症関係のヒューマンコンピューターインタラクションをやっていますが、[なんと老化にともなって視界がどんどん"黄ばんでいく"そう](https://www.tyojyu.or.jp/net/kenkou-tyoju/rouka/koreisha-shikikaku-roka.html)

なので、推奨される色使いなどがあります。[[参考]](https://www.caresapo.jp/kaigo/issue/83dn3a000000hp8q.html)

しかし、定性的にこうしろと言われたところで、じゃあ自分がデザインしたインターフェースが高齢者にとって見やすいか、（若年層にとっては）想像しづらいですよね。

## 作りました
なので、作りました
https://konbraphat51.github.io/ElderVisionSimulation/

レポジトリ: https://github.com/konbraphat51/ElderVisionSimulation?tab=readme-ov-file

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/d909f6f5-1dfb-6293-6d59-488e2a3b6ad1.png)
(サンプル画像は[Wikipedia「自然」](https://ja.wikipedia.org/wiki/%E8%87%AA%E7%84%B6)から)

適当に黄ばませているのではなく、[NHKのリサーチチームの論文](https://www.jstage.jst.go.jp/article/itej/62/7/62_7_1110/_pdf/-char/ja)をもとに実装しています。
ごく簡単にいうと、加齢による水晶体の黄ばみを数式化して、モニターの光が目に当たった際の水晶体の中の光の通りを計算しています。

## 実際どうなの
### 配色サンプル
先ほど引用した「けあさぽ」の配色例を80歳の設定で試してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/52a6fe4b-7952-6ea3-1854-f44512565697.png)
画像引用: [今月の特集　介護環境に色彩を活用しよう 第１回　色が人に与える影響とは？](https://www.caresapo.jp/kaigo/issue/83dn3a000000hp8q.html)

「白黄」は全く識別できないですね。
でも他の配色は（先天性色覚異常と比べて）過剰に神経質になるほど識別困難になるわけでもないという見方もできそうです。

### Qiitaで試そう
60歳で試してみます

ライトテーマ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/438be720-bd0f-6ba1-f13f-a591593aa417.png)

ダークテーマ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/419c559b-3769-b1a7-6a6a-4f162a918818.png)

Qiitaは高齢者フレンドリーな配色をしているとわかりますね。

### Gigazine
白黄のUIデザインをしているサイトで試してみましょう。対象は別になんでもいいですが、真っ先に[Gigazine](https://gigazine.net/)が浮かんできたので、60歳で試してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2602537/4ff3e3bf-1143-9825-7280-07d201134806.png)

白黄UIといっても、文字は黒系統なので、特に利用には問題ありません。しかし、せっかくの「最新ニュース40件」のボックスが見えづらくなっていますね。

## 計算の仕組み
先ほどのNHKの[池田, 成田(2008)の論文](https://www.jstage.jst.go.jp/article/itej/62/7/62_7_1110/_pdf/-char/ja)の数式とデータを使ったとしか言いようがありませんが、さらっとだけ。

それぞれのRGB値について、下記3つの値（「波長」の関数）の積を波長で積分します。（上記論文式(1)）
- n歳の水晶体分光分布特性 →式(4) 
    - 簡単に言うと、目の水晶体の色合い
- 画面の分光分布特性 →式(5)に$\lambda$と$R_0$らを代入
    - 簡単に言うと、画面の色合い
- 目の分光感度特性 →式(2)に、等色関数データを代入
    - 簡単に言うと、色に対する神経の感度

このうち、年齢によって変わるのが一番上、水晶体の色合いの部分です。
[Pokornyらの研究 (1987)](https://www.semanticscholar.org/paper/Aging-of-the-human-lens.-Pokorny-Smith/a253cc944697713ba8dbce30cbddbf7b27d67c7f)によって、年齢とともにどう変化されるのかが数式化されています。（式(3)）
こいつのせいで黄色くなるというわけですね。
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（88/100）

≪問題88≫
かんばん生産管理の利点は何ですか
（２つ選択）
□生産プロセスをマニュアル制御できる。
□リードタイムが短縮できる。
□需要元の出庫が自動転記される。
□生産管理が簡略化される。

≪解答≫
□生産プロセスをマニュアル制御できる。
■リードタイムが短縮できる。
□需要元の出庫が自動転記される。
■生産管理が簡略化される。

≪解説≫  
◆かんばん生産管理は、生産時における物理的な在庫品目に基づいて、生産および品目のフローを制御する手法です。定期的に必要となる品目は、生産時に少量の利用可能な在庫として保持されます。かんばん生産管理では、品目の特定の数量が消費された場合にのみ、品目の補充または生産がトリガされ、この補充は、事前に更新されたマスタデータを使用して生産により直接トリガされます。システム内の入力は、バーコード入力などの最小限の作業に抑えられます。  
◆かんばん生産管理の利点は、次のとおりです。  
（1）かんばん生産管理は、生産管理の簡略化された形式です。可能な限り、補充は生産によって制御されます。  
（2）手動での転記作業は最小限に抑えられます。  
（3）品目は、生産時に直接使用可能となるため、品目の供給を編成する必要がありません。  
（4）生産数量は実際の所要量に対応しています。この自己制御プロセスと、補充が実際に消費されるタイミングに近い時刻で登録されることにより、在庫の削減とリードタイムの短縮が実現します。補充は、品目が実際に必要となったときにのみトリガされ、それ以前には行われません。
マイクラ内で近くの人と喋れるSimple Voice ChatをBungeeCord環境で導入する

# 経緯
マイクラ内で近くの人と喋れるSimple Voice ChatをBungeeCord環境へ導入するのに少し手こずったため導入方法を残します。

# 導入環境
- 自宅鯖
- BungeeCord 1.21.1
- Spigot 1.21.1

# 導入方法
1. BungeeCordサーバーとSpigotサーバーにそれぞれプラグインを導入する
1. BungeeCordサーバーの`voicechat-proxy.properties`の`voice_host`を`xxx.xxx.xxx.xxx:26668`にする。<br />※IPとポートはそれぞれご自身の環境のものをご使用ください。ポートは`port`と同じものです。
1. ポートを開放する<br />※`xxx.xxx.xxx.xxx`はグローバルIP

# 注意点
- spigotのSimple Voice Chatのポートだけに限らずですが必ず使用するポートが被らないようにしてください
- 解放するポートはBungeeCordのポートだけで大丈夫です
- 解放するポートの種類はTCPではなくUDPです

# 参考サイト
- [reddit.com](https://www.reddit.com/r/admincraft/comments/12on4en/comment/jgjhmm1/?utm_source=share&utm_medium=web3x&utm_name=web3xcss&utm_term=1&utm_content=share_button)
- [Simple Voice Chat Wiki](https://modrepo.de/minecraft/voicechat/wiki)
(M5NanoC6)Grove- LEDでPWMで遊ぶ



x 過去ログを見よ

結果


![o_coq454.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/6530a95c-428f-d237-205d-d8f8c8e52b67.jpeg)


プログラム



```c++



//PWM_test1_C6_3


//初期化
void setup() {

  //出力ピンの初期化
  pinMode(1, OUTPUT);

} //setup


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

  //256回繰り返す
  for (int i = 0; i < 256; i++) {

    analogWrite(1, i); //PWM出力

    delay(20); //20ms待つ

  } //for i

} //loop



```
(M5NanoC6)内蔵青LEDでPWMで遊ぶ


x 過去ログを見よ

結果

![o_coq453.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/b6eb971f-4f3f-edb1-688b-44595360a484.jpeg)


プログラム

```c++


//PWM_test1_C6_2


//初期化
void setup() {

  //出力ピンの初期化
  pinMode(7, OUTPUT);

} //setup


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

  //256回繰り返す
  for (int i = 0; i < 256; i++) {

    analogWrite(7, i); //PWM出力

    delay(20); //20ms待つ

  } //for i

} //loop

```
2024/9/24主にITとかセキュリティの記事

〈直言〉サイバー防御、人が生命線　杉浦隆幸氏 日本ハッカー協会代表理事(9/22)
https://www.nikkei.com/article/DGKKZO83618930R20C24A9EA1000/

静岡東海証券の事例に学ぶGoogleフォームの設定ミスと情報漏洩リスク
https://cybersecurity-park.com/3001/

暗号資産取引所BingXにハッキング──オンチェーンデータで4300万ドル超の流出が判明(9/22)
https://www.coindeskjapan.com/252720/

松竹、個人情報２３万人流出か＝委託先へのサイバー攻撃で(9/20)
https://www.risktaisaku.com/articles/-/95499

RDS・Auroraの自動バックアップをAWS Backupに移行するときの勘所(9/21)
https://qiita.com/yuki_ink/items/80ce95ba6655caef5985

米警察、ジェネシス債権者から350億円相当の暗号資産を奪った事件で2人を逮捕(9/22)
https://www.coindeskjapan.com/252596/

インタビュアーから　崩れた「日本語の防壁」(9/22)
https://www.nikkei.com/article/DGKKZO83619120R20C24A9EA1000/

要件定義｜3分で読める非機能要件について(9/22)
https://qiita.com/ho_na/items/a84f9a0db793cb0411db

NewsPicks トピックス 『デジタル政策と未来社会』のまとめ(2024.9.16～2024.9.22）
https://blogs.itmedia.co.jp/business20/2024/09/newspicks_20249162024922.html?ref=rss

インド最高裁のYouTubeページがハッキング、XRPの宣伝動画に(9/22)
https://www.coindeskjapan.com/252643/

来たるべき量子コンピューターの時代に向けて一般人が知っておくべき「ポスト量子暗号」の基礎知識まとめ(9/22)
https://gigazine.net/news/20240922-nist-post-quantum-cryptography-faq/

「マイナでロマンス詐欺防止を」河野太郎デジタル相の呼びかけ、大丈夫？　婚姻、収入情報も業者が把握可能に…(9/22)
https://www.tokyo-np.co.jp/article/355707
child_process.spawnを理解する

# はじめに
Node.jsのコードにおいてchild_processモジュールを使用する機会があり、その中でもspawnを理解したいと思い、こちらの記事を記載しました。

# child_processモジュールとは
Node.jsでサブプロセス（子プロセス）を作成し、メインのNode.jsプロセスから独立してコマンドやプログラムを実行するための機能を提供します。

# child_process.spawn
[こちらの公式ドキュメント](https://nodejs.org/api/child_process.html#child_processspawncommand-args-options)に記載のある通り、child_process.spawnの書き方としては、child_process.spawn(command[, args][, options])というように、実行するコマンド、配列の中に引数、オプションの順番で記載します。

## サンプルコード

```javascript:spawn.js
const { spawn } = require("child_process");
const child = spawn(
  "node",
  [
    "-e",
    `
      process.stdin.on('data', (data) => {
      process.stdout.write(data.toString().toUpperCase());
      });
    `,
  ],
  { stdio: ["pipe", "pipe", "inherit"] }
);

child.stdin.write("Hello, child process!\n");
child.stdout.on("data", (data) => {
  console.log(`Child process output: ${data}`);
});
```

このコードは、Node.js の child_process.spawn() を使用して、別の Node.js プロセスを生成し、親プロセス（メインのスクリプト）からデータを送信して、子プロセス（生成されたプロセス）で処理を行い、その結果を受け取る構成です。

このコードでの具体的な流れ

1.	親プロセスが child.stdin.write() で子プロセスに "Hello, child process!\n" を送ります。
2.	子プロセス内で process.stdin.on('data') が発火し、データを受け取ります。
3.	受け取ったデータを toString().toUpperCase() で大文字に変換し、process.stdout.write() で子プロセスの標準出力に書き込みます。
4.	親プロセスが child.stdout.on('data') で子プロセスの出力を監視し、大文字に変換された結果（"HELLO, CHILD PROCESS!\n"）を console.log() で表示します。


実行されるコマンドは「node」です。引数に「-e」があり、Node.js の -e オプションは、指定された文字列をそのまま実行できる短いスクリプトを指定するものです。

・process.stdin.on('data', (data) => {
process.stdout.write(data.toString().toUpperCase());
});
子プロセス内で、process.stdin.on('data') を使って標準入力からデータを受け取り、そのデータを大文字に変換し、process.stdout.write() で標準出力に書き出します。
process.stdin を使うと、ユーザーがターミナルやコマンドラインからプログラムに入力した内容を受け取れます。

・{ stdio: ["pipe", "pipe", "inherit"] }
spawn 関数の第三引数として stdio オプションが渡されています。これは、子プロセスの標準入力（stdin）、標準出力（stdout）、標準エラー出力（stderr）がどう扱われるかを指定しています。
"pipe": 子プロセスの stdin と stdout を親プロセスと接続します。
"inherit": 子プロセスの stderr は親プロセスの stderr に直接接続されます（親プロセスのコンソールにそのままエラーメッセージが表示される）。

・child.stdin.write("Hello, child process!\n");
child.stdin: これは子プロセスの標準入力ストリームです。write メソッドを使用して、子プロセスにデータを送信しています。ストリームであるという記述は[こちら](https://nodejs.org/api/child_process.html#subprocessstdin)にあります。

・child.stdout:これは、子プロセスの標準出力ストリームを指します。子プロセスが出力するすべてのデータはここに送られます。

### 標準出力（stdout）をinheritに変更した場合
```javascript:spawn.js
const { spawn } = require("child_process");
const child = spawn(
  "node",
  [
    "-e",
    `
      process.stdin.on('data', (data) => {
      process.stdout.write(data.toString().toUpperCase());
      });
    `,
  ],
  // { stdio: ["pipe", "pipe", "inherit"] }
  { stdio: ["pipe", "inherit", "inherit"] }
);

child.stdin.write("Hello, child process!\n");
// child.stdout.on("data", (data) => {
//   console.log(`Child process output: ${data}`);
// });
```

{ stdio: ["pipe", "inherit", "inherit"] }
とした場合は、子プロセスの標準出力は、親プロセスの標準出力に直接接続されます。つまり、子プロセスが標準出力にデータを出力すると、そのまま親プロセスのコンソールに表示されます。そのため、親プロセスでの処理が出来ないため、最後のchild.stdout.on...のコードは削除する必要があります。


# まとめ
Node.jsのchild_processモジュールの挙動を具体的なコードを用いてまとめました。記事に残しておくことで自分が見直す場合にも役立ちますし、他の方の参考にもなれば幸いです。

# Reference

https://nodejs.org/api/child_process.html#child_processspawncommand-args-options
Ciliumが自動作成するGateway API用のServiceTypeをClusterIPに変更したい

# 変更前の状態

こんな感じになっていると思います。`LoadBalancer`タイプのServiceとして作成されます。

```
❯ kubectl -n kube-system get svc
NAME                                       TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGE
cilium-gateway-gateway                     LoadBalancer   10.97.2.250      <pending>     80:31040/TCP                   4m28s
hubble-peer                                ClusterIP      10.99.109.105    <none>        443/TCP                        6m4s
hubble-relay                               ClusterIP      10.100.137.232   <none>        80/TCP                         50m
```

これを`ClusterIP`に変えたいです。

# 設定方法

Helm valueの`gatewayAPI.hostNetwork.enabled`を`true`にしてください。

# 変更後の状態

```
❯ kubectl -n kube-system get svc
NAME                                       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)                        AGE
cilium-gateway-gateway                     ClusterIP   10.96.152.99     <none>        80/TCP                         67s
hubble-peer                                ClusterIP   10.96.52.65      <none>        443/TCP                        71s
hubble-relay                               ClusterIP   10.98.207.91     <none>        80/TCP                         71s
```

できました！

# 参考URL

https://docs.cilium.io/en/v1.16/network/servicemesh/gateway-api/gateway-api/#host-network-mode
TODO リスト用のフォルダ作成

### 1. ターミナル開く

1. まず、MacやLinuxでは「ターミナル」、Windowsでは「コマンドプロンプト」または「PowerShell」を開きます。ターミナルは、コマンドを入力して操作するためのツールで、コードの実行やファイル操作などを行います。

2. 画面に表示されるスクリーンショットのように、アプリケーションフォルダ（Macの場合）やスタートメニュー（Windowsの場合）からターミナルを起動します。

![スクリーンショット 2024-09-24 2.30.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892264/534f78e8-ae02-5bfe-4baa-68b9dc505f96.png)

- 上記の画像は、Macの「ターミナル」を開いた際の画面です。
  
![スクリーンショット 2024-09-24 2.30.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892264/f9f1270b-1fe4-af4b-29b4-f994e9c48add.png)

- WindowsでターミナルやPowerShellを使用する場合の画面例です。

---

### 2. 新規ファイル作成

次に、プロジェクトフォルダを作成して、必要なファイルを準備します。

1. **作業ディレクトリに移動**

   作業を行うフォルダに移動します。以下のコマンドを実行して、`workspace` フォルダに移動します。

   ```bash
   cd workspace
   ```

2. **新しいプロジェクトフォルダを作成**

   新しいプロジェクトを保存するためのフォルダ `todo-app-v-2` を作成します。`mkdir` コマンドでディレクトリを作成します。

   ```bash
   mkdir todo-app-v-2
   ```

3. **HTMLファイルを作成**

   プロジェクトのメインHTMLファイルである `index.html` を作成します。`touch` コマンドで空のファイルを作成できます。

   ```bash
   touch index.html
   ```

4. **JavaScriptファイルを作成**

   `index.js` という名前のJavaScriptファイルを作成し、このファイルにプログラムのロジックを記述します。

   ```bash
   touch index.js
   ```

5. **CSSファイルを作成**

   `index.css` というCSSファイルを作成して、スタイルシートとして利用します。Webページのデザインやレイアウトを指定するために使います。

   ```bash
   touch index.css
   ```

---

### 3. HTMLファイルに基本構造を追加

1. **HTML構造の作成**

   `index.html` ファイルに以下のコードを追加して、TODOリストアプリの基本的なHTML構造を作成します。このコードは、リスト表示の領域と、スタイルシートやJavaScriptファイルのリンクを設定しています。

   ```html
   <!DOCTYPE html>
   <html lang="en">
   <head>
   <meta charset="UTF-8">
   <title>TODO-List</title>
   <link rel="stylesheet" href="index.css"> <!-- CSSファイルをリンク -->
   </head>
   <body>
     <h1>TODO-List-v2</h1> <!-- タイトル部分 -->
     <div id="table"> <!-- タスクリストを表示するための領域 -->
       <h2>Current Tasks</h2>
       <ul class="task_list"></ul> <!-- タスクが表示されるリスト -->
     </div>
   <script src="index.js"></script> <!-- JavaScriptファイルをリンク -->
   </body>
   </html>
   ```

   - **`<h1>`**: メインのタイトルとして「TODO-List-v2」を表示。
   - **`<ul class="task_list">`**: タスクをリスト形式で表示する領域を作成します。タスクの項目はJavaScriptを使って動的に追加します。

---

### 4. CSSファイルにスタイルを追加

次に、`index.css` ファイルに基本的なスタイルを追加して、ページの外観を整えます。

```css
body, html {
    font-family: 'Arial', sans-serif; /* フォントの設定 */
    background-color: #f4f7f6; /* 背景色を淡いグレーに設定 */
    color: #333; /* 文字色を濃いグレーに設定 */
    margin: 0;
    padding: 0;
    display: flex;
    justify-content: center; /* コンテンツを中央に配置 */
    align-items: center; /* 垂直方向でも中央に配置 */
    height: 100vh; /* ページ全体の高さを100%に設定 */
}

h1 {
    text-align: center; /* タイトルを中央に配置 */
    color: #4CAF50; /* タイトルの文字色を緑に設定 */
    margin-bottom: 20px; /* 下にスペースを設定 */
}
```

- **`body, html` のスタイル**:
  - ページ全体をセンタリングし、背景色を淡いグレー（`#f4f7f6`）に、文字色を濃いグレー（`#333`）に設定しています。また、`height: 100vh` でページ全体をフルスクリーンに対応させています。
- **`h1` のスタイル**:
  - タイトル（`TODO-List-v2`）は、緑色（`#4CAF50`）にし、中央揃えにします。また、下に20pxのスペースを設け、見やすくしています。

---

### 5. まとめ

これで、以下の3つのステップが完了しました：
1. ターミナルで新しいプロジェクトフォルダと基本ファイル（HTML、CSS、JavaScript）を作成。
2. `index.html` に、TODOリストアプリの基本的なHTML構造を追加。
3. `index.css` に、アプリの基本スタイルを設定し、見やすくしました。

次のステップとして、`index.js` にタスクの追加や削除などのロジックを記述して、TODOリストの機能を実装します。
Unboundで特定IPアドレスからの問合せのみIPv6アドレスの応答を無効にする

タイトルのとおり、特定のIPアドレスからDNSルックアップが行われた際に、IPv6アドレスの応答を行わない方法（俗に言うAAAA Filterみたいなもの）です。

## なぜ必要だったか

現在、自宅のネットワークは以下のようになっており、IPv6でインターネットへアクセスできないネットワークがあります。

No | 概要 | IPv6到達性
-- | -- | --
1 | フレッツ光（IPoE、IPv4 over IPv6） | あり
2 | フレッツ光（PPPoE）[^1] | なし
3 | マンション備え付けの無料インターネット | なし

[^1]: No.1の接続を行っているルーターでPPPoEパススルーの設定を行い、その配下にPPPoE接続を行うルーターを接続しています。このため、物理的な回線は1本になります。

あまり気にする必要は無かったかもしれませんが、No.2のネットワークにてWebページのIPv6、IPv4両方に対応しているWebページの表示が気持ち遅いように感じられました。
このため、DNSでIPv6アドレスの応答を行わないようにしてみたところ、気持ち早くなったような気がした[^2]ので、IPv6アドレスの応答を行わないDNSサーバを立てることにしました。

[^2]: プラシーボ効果である可能性が否めません・・・

## 動作確認時のバージョン

- OS：Rocky Linux 8.10
- Unbound：1.16.2

※基本的には、上記のバージョン以降で動作するかと思いますが、確実に動くことを保証するのものではありません。

## 設定案

検証を行った際は、それぞれのネットワークに独立したDNSサーバを仮想マシンとして構築していました。
しかし、おうちネットワークという都合上、仮想基盤のリソースは限られているため、どうにかして1つのサーバにまとめられないか、試行錯誤しました。

- 案1：それぞれのネットワークごとに独立したDNSサーバを構築
    - リソース的にあまり採用したくない
    - うまくいかなかったときの最終手段
- 案2：1つの仮想サーバにUnboundのインスタンスを複数立てる
    - 2つ目のインスタンス以降は、Systemdの設定ファイルを自分で作成しないといけない
    - 複数インスタンスを立てることにより、リソース的にも微妙？
    - 何よりスマートじゃない
- 案3：View機能を使用する
    - これが使えないか？

案3で構築できないかという方向で調査を進めましたが、UnboundでIPv6応答を行わない設定をググって見ると、出てくるのは `server:` セクションに `private-address: ::/0` を指定するものばかり。
`view:` セクションには `private-address: ::/0` が使用できないため、「特定のIPアドレス」から問合せのみIPv6アドレスを応答しないという目的を達成できません。

万事休すかと思われましたが、`response-ip:` という設定があることを知り、これを使用することで設定できました。

## 実際の設定

今回の設定に絡む部分だけ抜粋した設定になります。
※設定中のIPアドレスは、例示用のIPアドレスを使用しており、実際のIPアドレスとは異なります。

```
server:
    access-control-view: 192.0.2.0/24 "IPv6 Only"
    access-control-view: 2001:db8::/32 "IPv6 Only"
    access-control-view: 198.51.100.0/24 "IPv4 Only"
view:
    name: "IPv6 Only"
    local-data: "time.apple.com IN A 192.0.2.5"
    local-data: "time.apple.com IN AAAA 2001:db8::1"
view:
    name: "IPv4 Only"
    response-ip: ::/0 redirect
    local-data: "time.apple.com IN A 198.51.100.5"
```

「IPv6 Only」と「IPv4 Only」という2つのViewを作成し、「IPv4 Only」のViewでは、IPv6アドレスを返さないように `response-ip: ::/0 redirect` を設定しています。
`server:` セクションでは、どのIPアドレスからの問合せを、どのViewで処理するかを `access-control-view:` を使用して設定しています。
あとは、iOSデバイス用とかにLAN内のNTPを使用するようにDNSを書き換えたり・・・。まだ他にもAppleデバイスが使用するNTPサーバのFQDNはありますが、ここでは割愛しています。

## 最後に

本当はIPv6がどのネットワークでも使用できるようにして、AAAA Filterを行わずにすむようにしたいのですが、どう頑張ってもIPv6を使用することが出来ないネットワークは出てくるかと思うので、そういった際の一助になれば幸いです[^3]。
また、こういう設定があるよ！というアドバイスも大歓迎です。

[^3]: `private-address: ::/0` を設定するだけで事足りるかもしれませんが。
64パッドを使ってMelodicsのアコースティックドラムコースを遊ぶ

# 前提・動機

- Melodicsはキーボード、パッド、ドラムの練習コースを提供するオンラインサービス(一部無償)
- MelodicsがドラムコースでYamaha FGDP(フィンガードラムパッド)に対応したのを見て64パッドでもできそうだと思ったのでやってみた
  - これまでに64パッド(Launchpad X)を使ってパッドコースを練習している


# 64パッドでFGDP風にMelodicsドラムコースを遊ぶための設定

64パッドとMelodicsの設定
- 64パッドでYamaha FGDP風のカスタムマップを作る
  - 同じ設定でMelodics以外にHalion Sonic(Stereo GM Kit)やModoDrumCS(Studio)、AD2(GMマッピングFairFaxVol1)も叩ける
  - GMマッピングがあってもタムが出ない音源がある
- MelodicsのConnected instrumentsでデバイスを選択して(普通の)スネアを叩けば認識されるはず
  - MelodicsのHit sensitivityで感度を調整できるらしい

カスタムマップの画像
![64pad_fgdp_melodics.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282700/9f589950-a680-109b-4132-a8dfc574e6fd.jpeg)

- 画像の略語
  - HHC=Close HiHat/HHO=Open HiHat/HH P=Pedal HiHat 
  - CC=Crash Cymbal/RC=Ride Cymbal
  - SD=Snare
  - HT=HiTom/MT=MidTom/FT=FloorTom(LowTom)
  - KD=Kick

![melodics_drumkit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282700/8bf51d34-329f-9629-797e-d9ef25b178f0.png)


# Guided PathのThe Hi-Hat Pedalまでやって思ったこと


- 使う指
  - 原則
    - Kick・Pedal HiHatは親指、Snareは人差し指、HiHat(Open/Close)・Crash・Rideは中指
    - タム単体はどれも中指(同時打ちのないタム回しなど)
    - 表拍は利き手、裏拍は逆の手で打つ
  - 同時打ちは自然な手の形・動きになるように考える
    - フロアタムをハイハットのように刻むところはスネア・キックの形が崩れないように小指で打つとか

  - 片手で全部打つこともできるが、パッドコースで十分やってるのでドラムコースの練習ではやらないことにしている
  - 難しいところは動作を分解して整理すると良さそう
    - 平行移動、指先を中心にした回転で手の形をなるべく変えないようにする
    - 指を広げる動きは手の形が変わってミスしがちなので注意する


- Melodicsのドラムコースはスティックで太鼓を叩くアコースティックドラム・エレクトリックドラム用に作られているので、フィンガードラムでの難易度や学習は考慮されていない
  - 序盤でもパッドコース中盤並みに難しいところがある
  - 手の左右や指番号などのサポートがない
    - 表拍と裏拍を決まった手で叩くようにしているが、そうしない方がいい場合もあるはず
      - パラディドル等の左右が大事な課題では題意に沿うよう考えて叩く
    - タム回しの指の左右が雑になりがち

# 雑感

Melodics、フィンガードラム、64パッドどれも楽しいのでおすすめ
Xcode16.0.0で使用出来なくなったPreview機能を動作させる方法

## Xcode16.0.0で使用出来なくなっているPreview機能を動作させる

Xcode16.0.0になってからXcode15.4で動いてたPreview機能が使用出来なくなってしまいました。
iPhone16シリーズを選択すると動かず、iPhoneSE3などでiOSバージョンを17にすると一応動きます。

![iPhoneSE3P.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/e13f02d7-2787-21d5-51a2-305e8d29bf1b.png)

iOSを18.0にすると動かないですが、iOS17であれば動きます。
一応この方法でもどうにか動くが、iPhone16シリーズで動かしたい！と思っていたら、有力なポストを投稿してる方を見つけました。

<br>


![スクリーンショット 2024-09-24 1.25.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/f331a38c-6212-35fb-10ca-04def6aa058d.png)
https://x.com/shtnkgm/status/1834202506999574871

ここにチェック入れるとiPhone16シリーズ、iOS18を選択しても動くようになるので試して下さい。
【Python】VSCodeで関数の引数名を表示する神機能

## 結論

引数が多くて、わかりずらかったコードが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/83b2efed-838f-0865-cce3-0296a6243d52.png)
↓
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/5921752d-ef7c-9e96-2a9c-589bd274fa9e.png)
このように、引数の名前が表示されることでめちゃくちゃわかりやすくなります！

## 設定方法

設定方法は、設定からPython Analysis Inlay Hints: callArgumentNamesをallにするだけ。（画像の一番上の設定です）
なお、この設定は、Pylanceという拡張機能のものです（ただし、Microsoft公式のPythonの拡張機能パックに入っているのでPythonユーザーであれば概ね設定可能だと思います）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/678160/557e4a84-04df-2c0e-0ec7-3b138c9d264e.png)

jsonで設定する場合は以下のようにsettings.jsonに追記してください。

```json:settings.json
{
  "python.analysis.inlayHints.variableTypes": true,
}
```

## その他のTips

ちなみに、こちらはそこそこ有名だと思うので、設定済みの方が多いかと思いますが、画像の他の設定では、戻り値や引数の型を表示することができます。

こちらもjsonの場合は以下

```json:settings.json
{
  "python.analysis.inlayHints.functionReturnTypes": true,
  "python.analysis.inlayHints.variableTypes": true,
}
```

それでは、良いPythonライフを！
C_TS422_2021 SAP Certified Application Associate SAP S/4HANA Production Planning and Manufacturing対策（87/100）

【87日目】
トピック 9：SAPS/4HANAでの簡易製造（4/9）

≪問題87≫
繰返生産におけるライン階層は何を表しますか。
□作業手順に代替順序がある生産ライン
□作業手順に並行順序がある生産ライン
□優先付けされた代替作業区がある生産ライン
□複数の作業区がある生産ライン

≪解答≫
□作業手順に代替順序がある生産ライン
□作業手順に並行順序がある生産ライン
□優先付けされた代替作業区がある生産ライン
■複数の作業区がある生産ライン

≪解説≫
◆繰返生産において、生産ラインは簡易作業区として登録されます。作業区では、生産ラインの利用可能な在庫を定義します。 
◆作業区として登録された生産ラインは、対応する製造バージョンおよび作業手順の1つの作業に割り当てられます。 
◆複数の作業区が割り当てられた生産ラインは、ライン階層として表現することができます。
iOS18新機能アプリアイコンのダークモード、色合い調整用のアイコンを実装する方法

## Xcodeでのアプリアイコンの実装方法

Xcode16から新規作成した場合は最初から表示されています。

![AppearancesP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/d3d67634-e673-8ed5-b1f2-ca951144ae2c.png)

Xcodeの「Assets」→「AppIcon」を開いて下さい。
「Any Appearance」「Dark」「Tlinter」が表示されています。
ここにそれぞれのアイコンを設定して下さい。それぞれをクリックしてファイル選択でも設定できて、またドラック＆ドロップで設定できます。


<br>


### アイコンの種類
「Any Appearance」→従来と同じ通常のアイコン

「Dark」→アイコンをダークモード変更時に使用されるアイコン

「Tlinter」→色合い調整を選択した時に使用されるアイコン
以上のようになります。

![IconType.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/faed674d-adc2-fdbb-2b62-1ece612d49d7.png)

自分で作ってるアプリでの参考例です。

<br>



### iPhoneからの変更方法はこちらです。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/a5125758-4000-5810-a1aa-c9f81ebf8559.png" width="50%">


どのアプリでも良いのでロングタップして、クイックアクション画面を表示させます。
その画面から「ホーム画面を編集」をタップして下さい。

<br>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/cf4a89fa-b33e-08e7-3398-ba4c42023127.png" width="50%">

左上の「編集」ボタンをタップして下さい。

<br>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/a6bb3f0a-c998-53aa-72da-ef650d3e28f3.png" width="50%">

編集画面の「カスタマイズ」をタップして下さい。

<br>

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/c529b9cd-b170-20d0-3c37-24085383c742.png" width="50%">

ここでカスタマイズができるので自分で実装したアプリアイコンが表示されているかを確認して下さい。



#### Xcode16以前のファイルを変更する

![NoneP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1344207/9663fc23-424e-b3ec-8739-cd4f4b8845a8.png)

「App Icon」→「Appearances」→「None」になっているので「Any, Dark, Tinted」に設定を変更して下さい。

<br>

アップデートしただけではアプリアイコンを正常にライト、ダークと切り替えられないケースがあります。
その場合は、iPhoneを再起動して下さい。


<br>

## 通常アプリアイコン変更時の考察記事

https://dev.classmethod.jp/articles/about-dark-mode-app-icons-in-ios18/


<br>

## 関連記事

https://developer.apple.com/jp/design/human-interface-guidelines/app-icons


https://developer.apple.com/jp/design/human-interface-guidelines/dark-mode


https://support.apple.com/ja-jp/guide/iphone/iph385473442/ios


https://qiita.com/gaussbeam/items/617c475bfe1ac9da859a
useStateに関して学んだこと

## 背景
こんにちは。エンジニアのKennieです。
最近フロントエンドの勉強をし始めてuseStateについて学びました。
公式ドキュメントを読みながら勉強していこうと思い、そこでuseStateについて学んだことを書いてみました！


## 1. Reactのstateは非同期で更新される

React のstateの更新は非同期で行われます。つまり、stateを更新するために下記のように `setAge` を呼び出しても、その時点で即座に変更されるわけではありません。実際の更新は、次のレンダーサイクルまで待たなければなりません。



以下の例では、年齢 (`age`) を1ずつ増やすボタンのクリックイベントを扱います。

```jsx
const [age, setAge] = useState(42);

function handleClick() {
  setAge(age + 1); 
  setAge(age + 1); 
  setAge(age + 1); 

  return (
    <div>
      <p>Current age: {age}</p>
      <button onClick={handleClick}>Increase Age</button>
    </div>
  );
}
```
↑こちらのコードの動き
https://codesandbox.io/p/sandbox/react-dev-forked-x58vzm?file=%2Fsrc%2FApp.js%3A5%2C1


このコードでは、ボタンを1回押すと、最終的に `age` は43になります。なぜなら、すべての `setAge(age + 1)` は、最初の `age` の値（42）を基に計算されるからです。これは上記に書いたReactの非同期性によるもので、`setAge` を呼び出しても、再レンダーされるまで `age` の値は更新されないためです。

#### アップデータ関数を使った更新

```jsx

function handleClick() {
  setAge(preveAge => preveAge + 1); // setAge(42 => 43)
  setAge(preveAge => preveAge + 1); // setAge(43 => 44)
  setAge(preveAge => preveAge + 1); // setAge(44 => 45)
}

```
↑こちらのコードの動き
https://codesandbox.io/p/sandbox/react-dev-forked-mg6zxk?file=%2Fsrc%2FApp.js%3A9%2C32

各`setAge`の呼び出しが、最新の`age`の値を基にして次の値を計算するため、ボタンを1回押すと`age`は3回増加し、最終的に+3されます。たとえば、`age`が最初に42であれば、1回のクリックで45になります。このように、アップデータ関数を使用すれば前の値を基に新しい値を計算するため、意図通りの結果が得られます。

## 2. stateの更新におけるオブジェクトと配列

Reactでは、stateにオブジェクトや配列を使用することができますが、**既存のオブジェクトを直接変更すべきではない**とされています。具体的な例を用いて、その理由を説明します。

### 例

こちらは既存のオブジェクトを直接変更している例
```jsx
const [userProfile, setUserProfile] = useState({ username: '', email: '' });
userProfile.username = 'Kennie'; 
```

こちらは置き換えをしている例
```jsx
setUserProfile({
  ...userProfile,
  username: 'Kennie'
});
```

### 解説

1. 既存のオブジェクトを直接変更している場合: Reactではstateにある既存のオブジェクトを直接変更するとReactはその変更を検知できません。結果として、Reactが再レンダリングされたとき、username の値は 'Kennie' ではなく、依然として空の文字列 '' のままです。
2. **新しいオブジェクトの作成**: スプレッド構文（`...userProfile`）を使用することで、元の`userProfile`オブジェクトのプロパティをコピーし、新しいオブジェクトを作成します。この新しいオブジェクトは、元のものとは異なるメモリ領域に保存されるため、参照が変わり、Reactはstateの変更を正しく検知できるようになります。

## 参考リンク
https://react.dev/reference/react/useState

## あとがき
公式ドキュメントにはuseStateの様々な使い方が書かれていて、将来的にここで得た情報は開発をしている際、もしくはバグに出くわした際、役立ってくると感じました。
Microsoft AzureのVMサイズ

# サイズ名の分解

例）Standard_D2as_v5

| 項目 | 説明 |
|:--|:--|
| Standard | 固定値 |
| D | ファミリー |
| 2 | vCPUの数 |
| as | 特徴 |
| v5 | バージョン（物理マシン構成の新しさ） |

- 公式ドキュメント：[Azure virtual machine sizes naming conventions](https://learn.microsoft.com/ja-jp/azure/virtual-machines/vm-naming-conventions)

# 代表的なファミリー

| 値 | 用途 |
|:--|:--|
| D | 汎用（通常はこれ） |
| B | バースト可能な汎用（安価） |
| F | コンピューティング最適化 |
| E | メモリ最適化 |
| L | ストレージ最適化 |
| NC | GPUアクセラレーション |
| NP | FPGA |

:::note info
Bシリーズは負荷がしきい値を下回っている場合にCPUクレジットを蓄積し、クレジットがあればバーストできる
:::

# 代表的な特徴

| 値 | 説明 |
|:--|:--|
| a | AMDプロセッサ（多少安価）[^1] |
| p | ARMプロセッサ |
| s | Premium Storage対応　[^2] |
| d | ローカル一時ディスク有り [^3]|
| m | memory intensive、メモリ多め |
| l | low memory、メモリ少なめ |
| t | tiny memory、メモリ極小 |

[^1]: 無印のプロセッサはIntel
[^2]: Premium Storage対応はPremium SSD以上を使う場合に必要
開発/テスト用途なら安価なStandard SSDで十分
[^3]: ローカル一時ディスクは無くてもOSは動作する
WindowsだとD:ドライブにマップされる
データの永続性は保証されない
ABC372 C - Count ABC Again

## はじめに
9/21開催のABC372のC問題の復習です。
まーたTLEになったので、何が悪かったのか解説見ながら再Tryします。

https://atcoder.jp/contests/abc372/tasks/abc372_c

## 問題文
長さ$N$の文字列$S$が与えられます。
$i$番目のクエリは以下の通りです。

- 整数$X_i$と文字$C_i$が与えられるので、$S$の$X_i$番目の文字を$C_i$に置き換える。その後、$S$に文字列`ABC`が部分文字列として何箇所含まれるか出力する。

### 制約
- $3 \le N \le 2 \times 10^5$
- $1 \le Q \le 2 \times 10^5$
- $S$は英大文字からなる長さ$N$の文字列
- $C_{i}$は英大文字

## 自分の解答
```python:372_C_TLE
n, q = map(int, input().split())
s = list(input())
queries = [input().split() for _ in range(q)]
queries = [(int(x), c) for x, c in queries]

results = []

for x, c in queries:
    s[x-1] = c
    results.append((''.join(s)).count("ABC"))

for result in results:
    print(result)
```

入力値から`[4 B]`のように配列で受け取って、その文字数を置換して、最後に`ABC`の数を`count`するように書きました。

計算量については、

各クエリに対して：
 - 文字の置換: $O(1)$
 - 文字列の結合: $O(N)$
 - "ABC"のカウント: $O(N)$
よって$Q$個のクエリで処理: $O(Q * N)$となる。
ここで$N,Q$と同じ$2\times10^5$と考えるので、
計算量は$O(N^2)$ つまり$O((2 × 10^5)^2)$ となって`TLE`になる。

なるほど、落ち着いて考えると当たり前ですね。

## 解説読んでの理解
- 置換前に`ABC`の数を数える
- 置換文字を含む3文字が置換前`ABC`であれば-1
- 置換後の文字列が`ABC`になれば+1
- これで計算量は$O(N+Q)$

## 回答例
```python:372_C_AC
n, q = map(int,input().split())
s = list(input())

ans = 0
#元の文字列がABCをいくつ含めるか
for i in range(n - 2):
  if s[i] + s[i+1] + s[i+2] == "ABC":
    ans += 1

for i in range(q):
  x,c = input().split()
  x = int(x) - 1

  #文字列置換対象がABCを作るか => 作ればABCが壊れたってことで -1
  for j in range(3):
    if x-j >= 0 and x-j+2 < n:
      if s[x-j] + s[x-j+1] + s[x-j+2] == "ABC":
        ans -= 1

  #文字列置換後、ABCを作るか => 作れば新たにABCが増えたってことで +1
  s[x] = c
  for j in range(3):
    if x-j >= 0 and x-j+2 < n:
      if s[x-j] + s[x-j+1] + s[x-j+2] == "ABC":
        ans += 1

  print(ans)
```
### 結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/296985/85912009-ec34-966b-5f14-20e366110ede.png)

## おわりに
文字列をぐるぐる探すのではなく、はじめに結果を作ってから増減させる。
この辺はまだまだだと痛感しました。
精進します。
ゼロから作るDeep Learning　～3章　ニューラルネットワーク～

自分なりに理解したことを見返せるようにまとめただけ

## ニューラルネットワーク
行列を忘れかけていたので復習。
難しいことは特にしていない。

![IMG_0650.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3892032/cca9ae87-b43f-b3de-57d7-509e7e8806eb.jpeg)


## 手書き文字識別の実装
### 重み関数のshapeからニューラルネットワークの構造を読み解いてみる
ソースコードはこんな感じ

```
import pickle

def get_data():
    # 手書き文字を読み込む
    (x_train, t_train), (x_test, t_test) = load_mnist(normalize=True, flatten=True, one_hot_label=False)
    return x_test, t_test

def init_network():
    # あらかじめ設定された重み関数を呼び出してくる
    with open("sample_weight.pkl", 'rb') as f:
        network = pickle.load(f)
        
    return network

def predict(network, x):
    W1, W2, W3 = network['W1'], network['W2'], network['W3']
    b1, b2, b3 = network['b1'], network['b2'], network['b3']
    
    a1 = np.dot(x, W1) + b1
    z1 = sigmoid(a1)
    a2 = np.dot(z1, W2) + b2
    z2 = sigmoid(a2)
    a3 = np.dot(z2, W3) + b3
    y = softmax(a3)
    
    return y
```

重み関数Wとかは自分で定義せず、元から用意されてるデータを読み込んでいるらしい。
shapeを調べてみると、

ソースコード：
```
x, t = get_data()
print("x.shape: ", x.shape)
print("t.shape: ", t.shape)

network = init_network()
print("w1.shape: ", network['W1'].shape)
print("w2.shape: ", network['W2'].shape)
print("w3.shape: ", network['W3'].shape)
print("b1.shape: ", network['b1'].shape)
print("b2.shape: ", network['b2'].shape)
print("b3.shape: ", network['b3'].shape)
```

結果：
```
x.shape:  (10000, 784)
t.shape:  (10000,)
w1.shape:  (784, 50)
w2.shape:  (50, 100)
w3.shape:  (100, 10)
b1.shape:  (50,)
b2.shape:  (100,)
b3.shape:  (10,)
```

手書き文字のテストデータ（x）が10000個用意されているらしい。
784という数字は、画像サイズが28×28で、これを1次元配列にしたから。

tは正解ラベルだから、xと同じ10000個。

前提として、これは
・隠れ層が2つ
・1つ目の隠れ層のノードが50個
・2つ目の隠れ層のノードが100個
らしい。

つまり、
・W1は784個の入力に対して、それぞれ重みが設定されており、次の50個のノードにつなげるから784×50の行列
・W2は次の50個の入力に対して、さらに次の100個のノードにつなげるから50×100の行列
・W3は最後の100個の入力に対して、10個の出力を持つから、100×10の行列

最後が10個の出力なのは、今回扱っている手書き文字が0～9の10種類の文字だから。
出力結果は、入力がどの文字に相当するかを表す確率になっている。

### 予想してみる
ソースコードはこんな感じ
```
x, t = get_data()
network = init_network()

accuracy_cnt = 0
for i in range(len(x)):
    y = predict(network, x[i])
    # yはどの文字である可能性が高いかを示した確率
    # 最も確率の高い要素のインデックスを取得
    p = np.argmax(y)
    
    # tは正解ラベル。予想結果があっていた場合、cntをプラスする
    if p == t[i]:
        accuracy_cnt += 1
        
print("Accuracy: ", float(accuracy_cnt) / len(x))
```
結果
```
Accuracy:  0.9352
```

## 所感
久々に数学の行列を思い出しながらやっていたのでちょっと飲み込むのに時間がかかった。
機械学習の基礎は過去に一通りやったので、割とすっと入ってきたかな。

普段Java書いているので、久々にPython触ると書きやすいけど型とかすごく不安になる。

あと、紙の書籍ペラペラめくりながらソースコード打つのだるすぎるので、O'REILLYさんは早く電子書籍出してほしい。
IERAE CTF 2024 Write Up


# 目次
- はじめに
- misc
  - OMG
- rev
  - assignment
- crypto
  - derangment
- おわりに


# はじめに
初CTF writte upです．
今回はIERAE CTF 2024に参加しました．
[IERAE CTF 2024](https://ctftime.org/event/1556)

CTFを始めて1年目のぺーぺーなのでwarmupの3問しか解けなかったのですが，解けた問題をまとめました．
順位はソロ参加で224チーム中113位でした．

# misc
## OMG [warmup]
```問題文
Oh my God!!!My browser history has been hijacked!

オーマイガー！！！ブラウザの履歴が乗っ取られてしまった！

Challenge: http://[host]:[port]
```

Challengeのページにアクセスすると，下のようなページが表示されます．
![OMG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638216/e80b85d6-8aa8-702c-2c27-1449e6cc46d9.png)

指示に従ってブラウザのバックボタンを33回押すとflagが表示されます．
詳しい原理は分かりませんが，アクセスした際にブラウザの履歴が33回分のページになっているので，バックボタンを押すことでflagが表示されると思われます．

<details><summary>flag</summary>

IERAE{Tr3ndy_4ds.LOL}

</details>

# rev
## assignment [warmup]
```問題文
Assignment is the root of everything in procedural programs.
```

ここでは調査対象のバイナリファイルが渡されるので，静的解析ツール[Ghidra](https://github.com/NationalSecurityAgency/ghidra)を使って解析します．
解析した結果の中からmain関数の中身を確認すると，flagという配列に整数値が格納されていることが分かります．
配列番号順に直して，ASCIIコードに変換するとflagが表示されます．

![解析結果](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3638216/c8acecdd-9c37-b23a-a2c7-9376e6919c2d.png)

<details><summary>flag</summary>

IERAE{s0me_r4nd0m_str1ng_5a9354c}

</details>

# crypto
## derangment [warmup]
```問題文
I've made a secret magic string, perfectly encrypted!

nc [ip address] [port]
```

サーバ側の処理としては，初期化として小文字アルファベットと数字と記号を15文字重複なく選び，ランダムに並べ替えたものを用意し答えとします．セッションを繋ぐたびに答えは変わることに注意です．ユーザ側はヒントを得ることができます．ヒントは答えをシャッフルしたものが出力されます．ここで，シャッフルする際には答えと同じ位置に文字がこないようにしてあります．ヒントを得られる回数は最大で299回です．ヒントを頼りに答えを求めて，合っているとフラグが出力されます．

解法としては，299回のヒントを使って，文字が出現しなかった位置を特定し，その位置に文字を入れることで答えを求めます．これを手入力で行うとセッションが切れてしまうため，pythonスクリプトを使って自動化します．


```python
from pwn import *
import string
import tqdm  # 進捗状況が見れる

# 接続
io = remote('104.199.135.28', 55555)

# ヒントを取得して、hintsに保存
hints = []
for i in tqdm.tqdm(range(299)):
    io.sendlineafter('> ', '1')
    hints.append(io.recvline().decode().strip().split(' ')[1])

# hints[0][i]が何番目に出てくるのかを調べる
index = [[0 for _ in range(15)] for _ in range(15)]
for i in tqdm.tqdm(range(15)):
    c = hints[0][i]
    for hint in hints:
        for j in range(len(hint)):
            if hint[j] == c:
                index[i][j] = 1
                break

ans = ['' for _ in range(15)]
for i in tqdm.tqdm(range(15)):
    for j in range(15):
        if index[i][j] == 0:
            ans[j] += hints[0][i]
            break

result = ''.join(ans)

if result not in hints and len(result) == 15:
    # 2を入力してを答え入力
    io.sendlineafter('> ', '2')
    io.sendlineafter('> ', result)

    # FLAGを取得
    print(io.recvline().decode())
    print(io.recvline().decode())
else:
    print("not found")

# 接続を切断
io.close()

```

<details><summary>flag</summary>

IERAE{th3r35_n0_5uch_th!ng_45_p3rf3ct_3ncrypt!0n}

</details>

# おわりに
今回はIERAE CTF 2024に参加しました．
24時間ぶっ続けでCTFに取り組んだわけではないので十分な成果が出なかったのですが，そもそもの実力不足なので過去問を解いて解いて解きまくろうと思います．
分野としては，暗号の研究をしているのでcryptoの問題を中心に勉強して無双できる日が来るように頑張ります．
あと，IERAE NIGHTにも参加します．
ホワイトハッカーの方々に直接お話を聞けるので楽しみです．
[IERAE NIGHT](https://ierae.connpass.com/event/324203/)