[{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 一応ここには現時点で考えている発想について適当にまとめているだけである。新しくわかったこととか調査結果をもとに、後からまとめなおする必要がある。\nポイント サーバクライアントモデル\nUI 処理をするクライアント（クライアント側） OS依存のAPIや実装のためのバックエンド（クライアント側） データ関連のバックエンド（サーバー側） P2P オープンなデータ構造\nJSON や XML などをサポートしたい human readable な仕様にしたい 大きなバイナリデータとかはどうするかが課題 それについては、Unityみたいに各ファイルにメタ情報付きでディレクトリ構造を形成して管理してみてもいいかもしれない。 拡張可能\nテキストや画像、インクオブジェクトだけでなく、独自のバイナリ構造を持つファイルや、独自のガジェットやオブジェクト的なものも扱えるように、機能を追加できる仕様にしたい。\nバージョン管理にgitを使う？\n基本的なアーキテクチャ x11みたいなサーバークライアントモデルな構造にしたい。\nフロントエンド chromeやfirefoxなどのブラウザ、Electornなどを使う。vite,react,typescriptとかだと比較的モダンに仕上がると思う。\nバックエンド 適当にpythonとかphpでもいいので、データ処理とOS固有のAPIの抽象化と呼び出しを担う\n基本的なデータ構造 ノート構造 Notebooks Section Pages1 Pages2 \u0026hellip; ページ構造 基本的には、汎用の位置情報などを保持するオブジェクトが定義され、それを継承することで、テキストや画像、動画、PDF、インク、3D view(include pmx and blender ext files -\u0026gt; three.js) バイナリデータなどをそれぞれ専用のクラスを用意し、扱う。\n基本的なUI機能や入力など ファイルのドラックアンドドロップ 貼り付け、コピー InkAPI マウス、キーボード、タッチ 複数ウィンドウ 長時間の処理時間がかかるものは進捗表示と非同期処理\n-\u0026gt; ユーザーに不快感を与えない、心配させない UI/UX 機能の在り方について いろいろ気になる機能があるが、詰め込め過ぎても仕方ないという印象。人はいろいろ選択肢があると、選べなくなるということを考慮すると、ある程度制約のある仕組みや、あえて実装しない機能を決めたり、使い方を制限するところも必要であると考えられる。\n労力的な問題について 正直 OneNote の代替を一から作るみたいなのより、Obsidian のプラグインを不満点を反映してガンガン作っていったほうがいいんじゃないか説ある。\nObsidian は少なくとも、プログラム本体自体のソースコードなどは公開されていない、closed source なようなので、アーキテクチャ的にも新しく作ったほうが都合がいいかもしれないということになり、現在作業中（2025/9/8)\n参考にしたサイトとか ここについては今のところ特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/concept/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　一応ここには現時点で考えている発想について適当にまとめているだけである。新しくわかったこととか調査結果をもとに、後からまとめなおする必要がある。\u003c/p\u003e\n\u003ch2 id=\"ポイント\"\u003eポイント\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eサーバクライアントモデル\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUI 処理をするクライアント（クライアント側）\u003c/li\u003e\n\u003cli\u003eOS依存のAPIや実装のためのバックエンド（クライアント側）\u003c/li\u003e\n\u003cli\u003eデータ関連のバックエンド（サーバー側）\u003c/li\u003e\n\u003cli\u003eP2P\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eオープンなデータ構造\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eJSON や XML などをサポートしたい\u003c/li\u003e\n\u003cli\u003ehuman readable な仕様にしたい\u003c/li\u003e\n\u003cli\u003e大きなバイナリデータとかはどうするかが課題 それについては、Unityみたいに各ファイルにメタ情報付きでディレクトリ構造を形成して管理してみてもいいかもしれない。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e拡張可能\u003cbr\u003e\n　テキストや画像、インクオブジェクトだけでなく、独自のバイナリ構造を持つファイルや、独自のガジェットやオブジェクト的なものも扱えるように、機能を追加できる仕様にしたい。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eバージョン管理にgitを使う？\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"基本的なアーキテクチャ\"\u003e基本的なアーキテクチャ\u003c/h2\u003e\n\u003cp\u003e　x11みたいなサーバークライアントモデルな構造にしたい。\u003c/p\u003e\n\u003ch3 id=\"フロントエンド\"\u003eフロントエンド\u003c/h3\u003e\n\u003cp\u003e　chromeやfirefoxなどのブラウザ、Electornなどを使う。vite,react,typescriptとかだと比較的モダンに仕上がると思う。\u003c/p\u003e\n\u003ch3 id=\"バックエンド\"\u003eバックエンド\u003c/h3\u003e\n\u003cp\u003e　適当にpythonとかphpでもいいので、データ処理とOS固有のAPIの抽象化と呼び出しを担う\u003c/p\u003e\n\u003ch2 id=\"基本的なデータ構造\"\u003e基本的なデータ構造\u003c/h2\u003e\n\u003ch3 id=\"ノート構造\"\u003eノート構造\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNotebooks\n\u003cul\u003e\n\u003cli\u003eSection\n\u003cul\u003e\n\u003cli\u003ePages1\u003c/li\u003e\n\u003cli\u003ePages2\n\u0026hellip;\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ページ構造\"\u003eページ構造\u003c/h3\u003e\n\u003cp\u003e　基本的には、汎用の位置情報などを保持するオブジェクトが定義され、それを継承することで、テキストや画像、動画、PDF、インク、3D view(include pmx and blender ext files -\u0026gt; three.js) バイナリデータなどをそれぞれ専用のクラスを用意し、扱う。\u003c/p\u003e\n\u003ch2 id=\"基本的なui機能や入力など\"\u003e基本的なUI機能や入力など\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eファイルのドラックアンドドロップ\u003c/li\u003e\n\u003cli\u003e貼り付け、コピー\u003c/li\u003e\n\u003cli\u003eInkAPI\u003c/li\u003e\n\u003cli\u003eマウス、キーボード、タッチ\u003c/li\u003e\n\u003cli\u003e複数ウィンドウ\u003c/li\u003e\n\u003cli\u003e長時間の処理時間がかかるものは進捗表示と非同期処理\u003cbr\u003e\n　-\u0026gt; ユーザーに不快感を与えない、心配させない UI/UX\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"機能の在り方について\"\u003e機能の在り方について\u003c/h2\u003e\n\u003cp\u003e　いろいろ気になる機能があるが、詰め込め過ぎても仕方ないという印象。人はいろいろ選択肢があると、選べなくなるということを考慮すると、ある程度制約のある仕組みや、あえて実装しない機能を決めたり、使い方を制限するところも必要であると考えられる。\u003c/p\u003e\n\u003ch2 id=\"労力的な問題について\"\u003e労力的な問題について\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003e正直 OneNote の代替を一から作るみたいなのより、Obsidian のプラグインを不満点を反映してガンガン作っていったほうがいいんじゃないか説ある。\u003c/del\u003e\u003c/p\u003e\n\u003cp\u003e　Obsidian は少なくとも、プログラム本体自体のソースコードなどは公開されていない、closed source なようなので、アーキテクチャ的にも新しく作ったほうが都合がいいかもしれないということになり、現在作業中（2025/9/8)\u003c/p\u003e","title":"コンセプト"},{"content":"この記事を作った動機 適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。この記事では、キーボードの全体像とか、気になった部分の紹介をしてみる。\nあとついでに、めんどくさかったので基本的に使った道具もここにリストアップしている。\n導入編 清掃前の全体像 清掃前のキーボードの全容 USBハブ キーボード背面 特に汚い部分 特殊なUSBケーブル 使った道具たち 無水エタノールとフラックスリムーバー はんだ吸い取り線 清掃道具一式 食器用洗剤（プラスチック回り用） 洗濯ネット ドリル はんだごてとはんだ （画像は写真撮り忘れたので省略）\n次の内容 Apple の古いキーボードをきれいにする 分解編 Part 1 参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/introduction/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。この記事では、キーボードの全体像とか、気になった部分の紹介をしてみる。\u003c/p\u003e\n\u003cp\u003e　あとついでに、めんどくさかったので基本的に使った道具もここにリストアップしている。\u003c/p\u003e\n\u003ch2 id=\"導入編\"\u003e導入編\u003c/h2\u003e\n\u003ch3 id=\"清掃前の全体像\"\u003e清掃前の全体像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%89%8d%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9/%e6%b8%85%e6%8e%83%e5%89%8d%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9.jpg#center\"/\u003e \u003cfigcaption\u003e\n            清掃前のキーボードの全容\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e7%89%b9%e6%ae%8a%e3%81%aaUSB%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab/USB%e3%83%8f%e3%83%96.jpg#center\"/\u003e \u003cfigcaption\u003e\n            USBハブ\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e8%83%8c%e9%9d%a2.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーボード背面\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%89%8d%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9/%e7%89%b9%e3%81%ab%e6%b1%9a%e3%81%84%e9%83%a8%e5%88%86.jpg#center\"/\u003e \u003cfigcaption\u003e\n            特に汚い部分\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%89%8d%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9/%e7%89%b9%e3%81%ab%e6%b1%9a%e3%81%84%e9%83%a8%e5%88%86%e3%81%ae%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%97.jpg alt=特に汚い部分のクロースアップ/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%89%8d%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9/%e7%89%b9%e3%81%ab%e6%b1%9a%e3%81%84%e9%83%a8%e5%88%86%e3%81%ae%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%971.jpg alt=特に汚い部分のクロースアップ1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"特殊なusbケーブル\"\u003e特殊なUSBケーブル\u003c/h3\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e7%89%b9%e6%ae%8a%e3%81%aaUSB%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab/%e5%88%87%e3%82%8c%e8%be%bc%e3%81%bf%e3%81%ae%e3%81%82%e3%82%8bUSB%e7%ab%af%e5%ad%90.jpg alt=切れ込みのあるUSB端子/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e7%89%b9%e6%ae%8a%e3%81%aaUSB%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab/%e5%88%87%e3%82%8c%e8%be%bc%e3%81%bf%e3%81%ae%e3%81%82%e3%82%8bUSB%e7%ab%af%e5%ad%901.jpg alt=切れ込みのあるUSB端子1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"使った道具たち\"\u003e使った道具たち\u003c/h2\u003e\n\u003ch3 id=\"無水エタノールとフラックスリムーバー\"\u003e無水エタノールとフラックスリムーバー\u003c/h3\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e7%84%a1%e6%b0%b4%e3%82%a8%e3%82%bf%e3%83%8e%e3%83%bc%e3%83%ab.jpg alt=無水エタノール/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e3%83%95%e3%83%a9%e3%83%83%e3%82%af%e3%82%b9%e3%83%aa%e3%83%a0%e3%83%bc%e3%83%90%e3%83%bc.jpg alt=フラックスリムーバー/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch3 id=\"はんだ吸い取り線\"\u003eはんだ吸い取り線\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e3%81%af%e3%82%93%e3%81%a0%e5%90%b8%e3%81%84%e5%8f%96%e3%82%8a%e7%b7%9a.jpg#center\"\n         alt=\"はんだ吸い取り線\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"清掃道具一式\"\u003e清掃道具一式\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e6%b8%85%e6%8e%83%e3%81%ab%e4%bd%bf%e3%81%a3%e3%81%9f%e3%82%82%e3%81%ae.jpg#center\"\n         alt=\"キーボード清掃に使ったもの\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"食器用洗剤プラスチック回り用\"\u003e食器用洗剤（プラスチック回り用）\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e9%a3%9f%e5%99%a8%e7%94%a8%e6%b4%97%e5%89%a4.jpg#center\"\n         alt=\"食器用洗剤\" width=\"30%\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"洗濯ネット\"\u003e洗濯ネット\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e4%bd%bf%e3%81%a3%e3%81%9f%e9%81%93%e5%85%b7%e3%81%9f%e3%81%a1/%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%82%92%e8%a9%a6%e3%81%97%e3%81%ab%e3%82%81%e3%82%93%e3%81%a9%e3%81%8f%e3%81%95%e3%81%84%e3%81%ae%e3%81%a7%e6%b4%97%e6%bf%af.png#center\"\n         alt=\"キーキャップを試しにめんどくさいので洗濯\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"ドリル\"\u003eドリル\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%81%aa%e3%82%81%e3%81%a6%e3%81%97%e3%81%be%e3%81%a3%e3%81%9f%e3%81%ad%e3%81%98%e3%81%9f%e3%81%a1/%e3%81%ad%e3%81%98%e3%82%92%e5%8f%96%e3%82%8a%e9%99%a4%e3%81%8f%e3%81%9f%e3%82%81%e3%81%ae%e9%81%93%e5%85%b7.jpg#center\"\n         alt=\"ねじを取り除くための道具\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"はんだごてとはんだ\"\u003eはんだごてとはんだ\u003c/h3\u003e\n\u003cp\u003e（画像は写真撮り忘れたので省略）\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 導入編"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 参考にしたサイトとか 使ったツール ChatGPT\nhttps://chatgpt.com/ (2025年3月2日) ","permalink":"https://www.nyanmo.info/posts/minecraft/note/whatis@mod/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003ch2 id=\"使ったツール\"\u003e使ったツール\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年3月2日)\u003c/li\u003e\n\u003c/ul\u003e","title":"@Mod って何？"},{"content":"この記事を作った動機 2025/9/10 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\nNetworking フロントエンドがレスポンスを識別できない可能性 作っている途中でわかったこととして、今回の websocket による実装だと、無数の React コンポーネントがデータサーバに対してリクエストを送った場合、どのコンポーネントがリクエストを送ったのかレスポンスが帰ってきたときにわからないという問題があった。\n具体的には、リクエストに対して、”誰”がリクエストを送ったのかという識別子がないことと、バックエンドからメッセージが帰ってくると一斉に、addEventListener で onmessage イベントを待っているコンポーネント全体にメッセージが届いてしまい、結果としてレスポンスの受け取りで整合性が取れなくなるというものである。\nそこで今回は、各リクエストに対し、UUIDを付与し、データサーバから返信するときはそのUUIDとリクエストしたコマンド名をレスポンスに含めるようにすることで、フロントエンドの各コンポーネントが自分が送ったリクエストかどうか識別できるようにした。\nちなみに今回のような問題は HTTP プロトコルで実装すると起こらなそうである。\nパフォーマンスの懸念 フロントエンド側の websocket の addEventListener の onmessage イベントは現状の実装だと、コンポーネントの数次第でその数だけコールバック関数があり、処理が走ることになる。\nそのため、その数だけ自分に対するリクエストのレスポンスかどうか識別することになり、パフォーマンスにおいて懸念がある。とりあえずは顕著になるまではこの問題はおいておこうと思う。\nデータサーバとフロントエンドが分離しているアーキテクチャについて 現状のアーキテクチャだと、例えばリモートのデータサーバにアクセスしていて、必ずしもネットワークが安定していなかったり、一時的にオフラインになる可能性がある環境において、安定しないことが考えられた。\nそこで、ローカルでスタンドアロンで動かすときと、データサーバがVPN経由などで遠隔地にある場合の２つで異なる考え方をすることにしてみた。\nスタンドアロンでデータサーバもローカルで動いているとき 単純にデータサーバが一つ起動し接続される。 データサーバがリモートにあるとき フロントエンドが動いているクライアント側にもcacheとしてデータサーバーがある。開いたページやインデックスを保持したりする。\nフロントエンドは、リモートのデータサーバと直接通信せず、フロントエンド側にあるデータサーバからリダイレクトしてもらうように指示する。\ncacheは通常のノートブックと同じようなデータ形式で保存する。\ncacheには、notebook を保存する場所にしてされたフォルダ内に、サーバーごとに専用のフォルダが作られる。\nserverName はホスト名やIPアドレスとする。 notebooksFolderRoot localNotebook1 localNotebook2 localNotebook3 \u0026hellip; serverName-cache remoteNotebook1 remoteNotebook2 remoteNotebook3 \u0026hellip; 各ページと各ファイルのメタデータ メタデータの扱いで悩んだこと。info と pageInfo コマンドを作っていて悩んだことがある。\n各ページのメタデータ 今の仕組みだとpageとしては、markdown 形式と、独自に自由に定義できる json 形式のものがあり、json形式の物に関してはどんなファイルが添付されているかとか、どんなタグが付いているかとか、独自に定義して、容易に管理することが可能である。\n{ \u0026#34;pageType\u0026#34;: \u0026#34;free\u0026#34;, \u0026#34;tags\u0026#34;: [\u0026#34;This\u0026#34;,\u0026#34;is\u0026#34;,\u0026#34;testpage\u0026#34;], \u0026#34;files\u0026#34;: [\u0026#34;testfile.txt\u0026#34;], \u0026#34;pageData\u0026#34;:{ /* page data */ } } しかし、markdown については、あんまり markdown に特殊なデータを埋め込みたくないことから、専用の.metadataファイルでも設置しようかと悩んだ。\nただそれだと処理が煩雑になるので、markdown 内にメタデータを埋め込むということも考えたが、現状の実装ではとりあえず markdown については、メタデータの実装はスキップする方針でいる。\nちょっと markdown にメタデータを埋め込むならば、Obsidian あたりを真似して、コードブロックみたいなのに JSON でも埋め込んでしまうとかでもいいかもしれない。\n```metadata-OneNoteAlternative { \u0026#34;tags\u0026#34;: [\u0026#34;This\u0026#34;,\u0026#34;is\u0026#34;,\u0026#34;testpage\u0026#34;], \u0026#34;files\u0026#34;: [\u0026#34;testfile.txt\u0026#34;] } ``` 各ファイルのメタデータ ファイルについてはただファイル単体が存在しているだけだと、実装上都合が悪い場合は、拡張子を .metadata として専用のメタデータ保持ファイルを作ろうかと考えてはいる。もし専用のメタデータファイルを生成するようにするなら、中身は基本 JSON で統一する予定である。\nこれだと、じゃあ対象のファイル自体が .metadata という拡張子を持っていたらどうするかという問題はあり、現状ではまだ深くは考えていない。何かしら識別する仕組みが必要なことは、現状把握していることではある。\nfile.txt file.txt.metadata サンプルデータ作成 ファイル構造 なお、index フォルダは廃止して、シンプルに全部一つの notebook 相当の、metadata.json に統合しようかと考えている。\n├── notebookData │ └── test │ ├── contents │ │ ├── test.json │ │ └── test.md │ ├── files │ │ └── testfile.txt │ ├── index │ │ ├── files.json │ │ └── tags.json │ └── metadata.json あとから、index フォルダーについて記述を見返したら思ったより複雑でタグ管理機能と密接に関係があることを思い出した。index フォルダーはやっぱり廃止しないことにした。\nindex data format tags.json { \u0026#34;tagName1\u0026#34;: [\u0026#34;/path/to/content.md\u0026#34;,\u0026#34;/path/to/content.json\u0026#34;,...], \u0026#34;tagName2\u0026#34;: [\u0026#34;/path/to/content.md\u0026#34;,\u0026#34;/path/to/content.json\u0026#34;,...] ... } files.json { \u0026#34;fileName1\u0026#34;:{ \u0026#34;original\u0026#34; : \u0026#34;/path/to/originalFileResourcesWhereAdded.md\u0026#34;, \u0026#34;refs\u0026#34; : [\u0026#34;/path/to/ThisFileResourceBeingUsed\u0026#34;,\u0026#34;/path/to/ThisFileResourceBeingUsed1\u0026#34;...], \u0026#34;filePath\u0026#34; : \u0026#34;/path/to/originalFileSavedWithFileNameAndExtention\u0026#34; }, \u0026#34;fileName2\u0026#34;:{ \u0026#34;original\u0026#34; : \u0026#34;/path/to/originalFileResourcesWhereAdded.md\u0026#34;, \u0026#34;refs\u0026#34; : [\u0026#34;/path/to/ThisFileResourceBeingUsed\u0026#34;,\u0026#34;/path/to/ThisFileResourceBeingUsed1\u0026#34;...], \u0026#34;filePath\u0026#34; : \u0026#34;/path/to/originalFileSavedWithFileNameAndExtention\u0026#34; } ... } tagging system for each files and contents, have a record what tags are belongs to. for each tags, have a record what contents and files are belongs to. 内容 metadata.json name の項目は、notebook のルートフォルダー名でなければならない。id の項目は単なる UUIDである。どんなページやファイルが notebook 内に存在するか示すメタデータがある。\n{ \u0026#34;name\u0026#34; : \u0026#34;test\u0026#34;, \u0026#34;createDate\u0026#34;: \u0026#34;2025/09/13\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/09/13\u0026#34;, \u0026#34;id\u0026#34; : \u0026#34;bb6f7d1c-c722-495c-923b-ab9e9574ef5b\u0026#34;, \u0026#34;pages\u0026#34; : [\u0026#34;test.md\u0026#34;,\u0026#34;test.json\u0026#34;], \u0026#34;files\u0026#34; : [\u0026#34;testfile.txt\u0026#34;] } contents z という項目は 2D における z-index という意味で、3D 対応とかそういうことではない。\ntest.json { \u0026#34;pageType\u0026#34;: \u0026#34;free\u0026#34;, \u0026#34;tags\u0026#34;: [\u0026#34;This\u0026#34;,\u0026#34;is\u0026#34;,\u0026#34;testpage\u0026#34;], \u0026#34;files\u0026#34;: [\u0026#34;testfile.txt\u0026#34;], \u0026#34;pageData\u0026#34;:{ \u0026#34;items\u0026#34;:[ { \u0026#34;ID\u0026#34;: \u0026#34;3d3751c3-20ee-4124-90df-464860620f4a\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;text\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;This is test text. Yukkuri reimu said \u0026#39;ゆっくりしていってね\u0026#39;.\u0026#34;, \u0026#34;position\u0026#34;:{ \u0026#34;x\u0026#34;: 200, \u0026#34;y\u0026#34;: 100, \u0026#34;z\u0026#34;: 0 } }, { \u0026#34;ID\u0026#34;: \u0026#34;ef3429f5-f150-4ad2-a325-80257fad8f6b\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;text\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;This is test text. Yukkuri marisa abuse Yukkuri reimu.\u0026#34;, \u0026#34;position\u0026#34;:{ \u0026#34;x\u0026#34;: 200, \u0026#34;y\u0026#34;: 150, \u0026#34;z\u0026#34;: 1 } } ] } } test.md # hello world This is test content. files testfile.txt nyanmo husahusa index 廃止予定なので、特に載せることはない。\nエラーハンドリングの実装 コマンド毎に必要なキーがない時のエラーをすべてのコマンドに共通で実装 レスポンス例 { \u0026#34;status\u0026#34;: \u0026#34;error\u0026#34;, \u0026#34;errorMessage\u0026#34;: \u0026#34;Mandatory data keys are missing or malformed.\u0026#34;, \u0026#34;UUID\u0026#34;:\u0026#34;UUID string\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;[commandName]\u0026#34;, \u0026#34;data\u0026#34;:{ \u0026#34;missing\u0026#34;: [\u0026#34;missingOrMalformed\u0026#34;,\u0026#34;key\u0026#34;,\u0026#34;names\u0026#34;] } } 参考にしたサイトとか Obsidian - Sharpen your thinking\nhttps://obsidian.md/ (2025年7月27日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-9-19/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/9/10 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"networking\"\u003eNetworking\u003c/h2\u003e\n\u003ch3 id=\"フロントエンドがレスポンスを識別できない可能性\"\u003eフロントエンドがレスポンスを識別できない可能性\u003c/h3\u003e\n\u003cp\u003e　作っている途中でわかったこととして、今回の websocket による実装だと、無数の React コンポーネントがデータサーバに対してリクエストを送った場合、どのコンポーネントがリクエストを送ったのかレスポンスが帰ってきたときにわからないという問題があった。\u003c/p\u003e\n\u003cp\u003e　具体的には、リクエストに対して、”誰”がリクエストを送ったのかという識別子がないことと、バックエンドからメッセージが帰ってくると一斉に、addEventListener で onmessage イベントを待っているコンポーネント全体にメッセージが届いてしまい、結果としてレスポンスの受け取りで整合性が取れなくなるというものである。\u003c/p\u003e\n\u003cp\u003e　そこで今回は、各リクエストに対し、UUIDを付与し、データサーバから返信するときはそのUUIDとリクエストしたコマンド名をレスポンスに含めるようにすることで、フロントエンドの各コンポーネントが自分が送ったリクエストかどうか識別できるようにした。\u003c/p\u003e\n\u003cp\u003e　ちなみに今回のような問題は HTTP プロトコルで実装すると起こらなそうである。\u003c/p\u003e\n\u003ch3 id=\"パフォーマンスの懸念\"\u003eパフォーマンスの懸念\u003c/h3\u003e\n\u003cp\u003e　フロントエンド側の websocket の addEventListener の onmessage イベントは現状の実装だと、コンポーネントの数次第でその数だけコールバック関数があり、処理が走ることになる。\u003c/p\u003e\n\u003cp\u003e　そのため、その数だけ自分に対するリクエストのレスポンスかどうか識別することになり、パフォーマンスにおいて懸念がある。とりあえずは顕著になるまではこの問題はおいておこうと思う。\u003c/p\u003e\n\u003ch2 id=\"データサーバとフロントエンドが分離しているアーキテクチャについて\"\u003eデータサーバとフロントエンドが分離しているアーキテクチャについて\u003c/h2\u003e\n\u003cp\u003e　現状のアーキテクチャだと、例えばリモートのデータサーバにアクセスしていて、必ずしもネットワークが安定していなかったり、一時的にオフラインになる可能性がある環境において、安定しないことが考えられた。\u003c/p\u003e\n\u003cp\u003e　そこで、ローカルでスタンドアロンで動かすときと、データサーバがVPN経由などで遠隔地にある場合の２つで異なる考え方をすることにしてみた。\u003c/p\u003e\n\u003ch3 id=\"スタンドアロンでデータサーバもローカルで動いているとき\"\u003eスタンドアロンでデータサーバもローカルで動いているとき\u003c/h3\u003e\n\u003cp\u003e　単純にデータサーバが一つ起動し接続される。\n　\u003c/p\u003e\n\u003ch3 id=\"データサーバがリモートにあるとき\"\u003eデータサーバがリモートにあるとき\u003c/h3\u003e\n\u003cp\u003e　フロントエンドが動いているクライアント側にもcacheとしてデータサーバーがある。開いたページやインデックスを保持したりする。\u003c/p\u003e\n\u003cp\u003e　フロントエンドは、リモートのデータサーバと直接通信せず、フロントエンド側にあるデータサーバからリダイレクトしてもらうように指示する。\u003c/p\u003e\n\u003cp\u003e　cacheは通常のノートブックと同じようなデータ形式で保存する。\u003c/p\u003e\n\u003cp\u003e　cacheには、notebook を保存する場所にしてされたフォルダ内に、サーバーごとに専用のフォルダが作られる。\u003c/p\u003e\n\u003cp\u003e　serverName はホスト名やIPアドレスとする。\n　\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003enotebooksFolderRoot\n\u003cul\u003e\n\u003cli\u003elocalNotebook1\u003c/li\u003e\n\u003cli\u003elocalNotebook2\u003c/li\u003e\n\u003cli\u003elocalNotebook3\n\u0026hellip;\u003c/li\u003e\n\u003cli\u003eserverName-cache\n\u003cul\u003e\n\u003cli\u003eremoteNotebook1\u003c/li\u003e\n\u003cli\u003eremoteNotebook2\u003c/li\u003e\n\u003cli\u003eremoteNotebook3\n\u0026hellip;\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"各ページと各ファイルのメタデータ\"\u003e各ページと各ファイルのメタデータ\u003c/h2\u003e\n\u003cp\u003e　メタデータの扱いで悩んだこと。info と pageInfo コマンドを作っていて悩んだことがある。\u003c/p\u003e\n\u003ch3 id=\"各ページのメタデータ\"\u003e各ページのメタデータ\u003c/h3\u003e\n\u003cp\u003e　今の仕組みだとpageとしては、markdown 形式と、独自に自由に定義できる json 形式のものがあり、json形式の物に関してはどんなファイルが添付されているかとか、どんなタグが付いているかとか、独自に定義して、容易に管理することが可能である。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;pageType\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;free\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;tags\u0026#34;\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;This\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;is\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;testpage\u0026#34;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;files\u0026#34;\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;testfile.txt\u0026#34;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;pageData\u0026#34;\u003c/span\u003e:{ \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/*\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003epage\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003edata\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e*/\u003c/span\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　しかし、markdown については、あんまり markdown に特殊なデータを埋め込みたくないことから、専用の.metadataファイルでも設置しようかと悩んだ。\u003c/p\u003e","title":"2025/9/19-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 既存の代替っぽいもの(全てはリストアップしていない) Google keep 数カ月ほど使ったことはあるが、使っていくうちに古いメモが下の方に行き、しかも、せっかくメモの付箋を書いたのに、あとから見返さないという問題があった。\n一応メモを色やピン留め、リマインドという形で分類したりできるという機能はある。情報が少ないうちはいいかもしれないが、あまり大規模なことはできないという印象がある。\n逆に言えば、Google keep 的な付箋スタイルUIや機能は、プロジェクト単位での軽いタスクの管理としては、一つありかもしれないあり方ではあった。\n今回のソフトウェア？では、Google keep みたいなUIや機能をもたせた特別な”ページ”をテンプレとして選べて作れ、タスク管理の一助として使えるようにするのはありかもしれない。\n実装としては、ページを拡張できるように色々インタフェースを定義したりAPIを定義したりとかになる気もする。\nEvernote 聞いたことはあるが、使ったことはない。私の印象としては、使うとロックダウンされてしまいそうなので使いたくないという印象だった。\nNotion 一ヶ月ほど使ったことはあるが、AI機能が、意思にかかわらずに有効になっていたり、記録した内容にいちいち”良くする”というスタンスで干渉してくるところが嫌であった。\nかつ、クラウドベースで、オフラインやローカル、LAN内だけで完結するインターネットのない環境で、プライベートに完結することを許さない感じが、どこか監視されているようで閉塞的でかなり息苦しいと感じられる。\nObsidian これはあまり深く使い込んだことはないが、研究に際して調べている過程で見つけたので、試してみた。そのことについては、Obsidianについてに記録した。\n気になるもの 大体になるかは置いといて、気になるサービスなどについても挙げておく。\nBasecamp なんか、google docs や Notion など、ありとあらゆる既存のサービスについての代替を主張していて、サービスが機能として内包しているプロジェクト管理などについて気になるところがある。\nBasecamp: Project management software, online collaboration\nhttps://basecamp.com/ (2025年8月1日) 既存の代替品の候補としてよく挙げられるツールの共通点 商業ベース クラウド ローカルで動かすことを前提としてない クラウドベースだとAIモデルの学習にデータが使われてしまう可能性 最初は無料としつつも、あとからしつこく課金させるビジネスモデルへの誘導がある可能性 クラウド系だとサービスが潰れたとき、データ消失、非互換の恐れ ある程度包括的にOneNoteの機能を持っているものはなく、いくつかの独自の設計や思想に基づいたものが乱立している印象 参考にしたサイトとか Download - Obsidian\nhttps://obsidian.md/download (2025年7月19日) Best Microsoft OneNote Alternatives in 2025 | Nuclino\nhttps://www.nuclino.com/alternatives/onenote-alternative (2025年7月19日) Best 6 OneNote Alternatives In 2025 | 100+ Personally Tested Tools\nhttps://thebusinessdive.com/onenote-alternatives (2025年7月19日) 最高のノートアプリ - Evernoteでノートを整理しましょう\nhttps://evernote.com/ja-jp (2025年7月19日) Basecamp: Project management software, online collaboration\nhttps://basecamp.com/ (2025年8月1日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/existingalternatives/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003ch2 id=\"既存の代替っぽいもの全てはリストアップしていない\"\u003e既存の代替っぽいもの(全てはリストアップしていない)\u003c/h2\u003e\n\u003ch3 id=\"google-keep\"\u003eGoogle keep\u003c/h3\u003e\n\u003cp\u003e　数カ月ほど使ったことはあるが、使っていくうちに古いメモが下の方に行き、しかも、せっかくメモの付箋を書いたのに、あとから見返さないという問題があった。\u003c/p\u003e\n\u003cp\u003e　一応メモを色やピン留め、リマインドという形で分類したりできるという機能はある。情報が少ないうちはいいかもしれないが、あまり大規模なことはできないという印象がある。\u003c/p\u003e\n\u003cp\u003e　逆に言えば、Google keep 的な付箋スタイルUIや機能は、プロジェクト単位での軽いタスクの管理としては、一つありかもしれないあり方ではあった。\u003c/p\u003e\n\u003cp\u003e　今回のソフトウェア？では、Google keep みたいなUIや機能をもたせた特別な”ページ”をテンプレとして選べて作れ、タスク管理の一助として使えるようにするのはありかもしれない。\u003c/p\u003e\n\u003cp\u003e　実装としては、ページを拡張できるように色々インタフェースを定義したりAPIを定義したりとかになる気もする。\u003c/p\u003e\n\u003ch3 id=\"evernote\"\u003eEvernote\u003c/h3\u003e\n\u003cp\u003e　聞いたことはあるが、使ったことはない。私の印象としては、使うとロックダウンされてしまいそうなので使いたくないという印象だった。\u003c/p\u003e\n\u003ch3 id=\"notion\"\u003eNotion\u003c/h3\u003e\n\u003cp\u003e　一ヶ月ほど使ったことはあるが、AI機能が、意思にかかわらずに有効になっていたり、記録した内容にいちいち”良くする”というスタンスで干渉してくるところが嫌であった。\u003c/p\u003e\n\u003cp\u003e　かつ、クラウドベースで、オフラインやローカル、LAN内だけで完結するインターネットのない環境で、プライベートに完結することを許さない感じが、どこか監視されているようで閉塞的でかなり息苦しいと感じられる。\u003c/p\u003e\n\u003ch3 id=\"obsidian\"\u003eObsidian\u003c/h3\u003e\n\u003cp\u003e　これはあまり深く使い込んだことはないが、研究に際して調べている過程で見つけたので、試してみた。そのことについては、\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/obsidian/\"\u003eObsidianについて\u003c/a\u003eに記録した。\u003c/p\u003e\n\u003ch2 id=\"気になるもの\"\u003e気になるもの\u003c/h2\u003e\n\u003cp\u003e　大体になるかは置いといて、気になるサービスなどについても挙げておく。\u003c/p\u003e\n\u003ch3 id=\"basecamp\"\u003eBasecamp\u003c/h3\u003e\n\u003cp\u003e　なんか、google docs や Notion など、ありとあらゆる既存のサービスについての代替を主張していて、サービスが機能として内包しているプロジェクト管理などについて気になるところがある。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eBasecamp: Project management software, online collaboration\u003cbr\u003e\n\u003ca href=\"https://basecamp.com/\"\u003ehttps://basecamp.com/\u003c/a\u003e (2025年8月1日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"既存の代替品の候補としてよく挙げられるツールの共通点\"\u003e既存の代替品の候補としてよく挙げられるツールの共通点\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e商業ベース\u003c/li\u003e\n\u003cli\u003eクラウド\u003c/li\u003e\n\u003cli\u003eローカルで動かすことを前提としてない\u003c/li\u003e\n\u003cli\u003eクラウドベースだとAIモデルの学習にデータが使われてしまう可能性\u003c/li\u003e\n\u003cli\u003e最初は無料としつつも、あとからしつこく課金させるビジネスモデルへの誘導がある可能性\u003c/li\u003e\n\u003cli\u003eクラウド系だとサービスが潰れたとき、データ消失、非互換の恐れ\u003c/li\u003e\n\u003cli\u003eある程度包括的にOneNoteの機能を持っているものはなく、いくつかの独自の設計や思想に基づいたものが乱立している印象\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDownload - Obsidian\u003cbr\u003e\n\u003ca href=\"https://obsidian.md/download\"\u003ehttps://obsidian.md/download\u003c/a\u003e (2025年7月19日)\u003c/li\u003e\n\u003cli\u003eBest Microsoft OneNote Alternatives in 2025 | Nuclino\u003cbr\u003e\n\u003ca href=\"https://www.nuclino.com/alternatives/onenote-alternative\"\u003ehttps://www.nuclino.com/alternatives/onenote-alternative\u003c/a\u003e (2025年7月19日)\u003c/li\u003e\n\u003cli\u003eBest 6 OneNote Alternatives In 2025 | 100+ Personally Tested Tools\u003cbr\u003e\n\u003ca href=\"https://thebusinessdive.com/onenote-alternatives\"\u003ehttps://thebusinessdive.com/onenote-alternatives\u003c/a\u003e (2025年7月19日)\u003c/li\u003e\n\u003cli\u003e最高のノートアプリ - Evernoteでノートを整理しましょう\u003cbr\u003e\n\u003ca href=\"https://evernote.com/ja-jp\"\u003ehttps://evernote.com/ja-jp\u003c/a\u003e (2025年7月19日)\u003c/li\u003e\n\u003cli\u003eBasecamp: Project management software, online collaboration\u003cbr\u003e\n\u003ca href=\"https://basecamp.com/\"\u003ehttps://basecamp.com/\u003c/a\u003e (2025年8月1日)\u003c/li\u003e\n\u003c/ul\u003e","title":"すでにあるOneNoteの代替になりうるものについて"},{"content":"この記事を作った動機 Apple の古いキーボードをきれいにする 導入編の続き。この記事では取り合えず大きく二つにキーボードを分けるところまでを書いていくことにする。\n分解編 キートップを外す キーキャップを外している様子 キーキャップを外している様子1 キーキャップを外した後の全体的な様子 汚れているキーキャップの様子 汚い様子 キーボードを二つに分離 T5トルクスねじ 背面カバーのねじを外した様子 キーボードを二つに分解 キーボードを二つに分解1 キーボードを二つに分解2 二つに分離するときとフレキシブルケーブル 二つに分離された様子の全容 次の内容 基板周りの分解 Apple の古いキーボードをきれいにする 分解編 Part 2 基板周り以外の分解 Apple の古いキーボードをきれいにする 分解編 Part 3 参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/introduction/\"\u003eApple の古いキーボードをきれいにする 導入編\u003c/a\u003eの続き。この記事では取り合えず大きく二つにキーボードを分けるところまでを書いていくことにする。\u003c/p\u003e\n\u003ch2 id=\"分解編\"\u003e分解編\u003c/h2\u003e\n\u003ch3 id=\"キートップを外す\"\u003eキートップを外す\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%82%92%e5%a4%96%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%90.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーキャップを外している様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%82%92%e5%a4%96%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%901.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーキャップを外している様子1\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e5%be%8c%e3%81%ae%e5%85%a8%e4%bd%93%e7%9a%84%e3%81%aa%e6%a7%98%e5%ad%90.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーキャップを外した後の全体的な様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e6%b1%9a%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%81%ae%e6%a7%98%e5%ad%90.jpg#center\"/\u003e \u003cfigcaption\u003e\n            汚れているキーキャップの様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e7%89%b9%e6%ae%8a%e3%81%aa%e3%83%96%e3%83%a9%e3%83%b3%e3%82%af%e3%82%ad%e3%83%bc.jpg alt=特殊なブランクキー/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e7%89%b9%e6%ae%8a%e3%81%aa%e3%83%96%e3%83%a9%e3%83%b3%e3%82%af%e3%82%ad%e3%83%bc%e8%a3%8f.jpg alt=特殊なブランクキー裏/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"汚い様子\"\u003e汚い様子\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%90.jpg#center\"\n         alt=\"汚い様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%905.jpg#center\"\n         alt=\"汚い様子5\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%906.jpg#center\"\n         alt=\"汚い様子6\"/\u003e \n\u003c/figure\u003e\n\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%901.jpg alt=汚い様子1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%902.jpg alt=汚い様子2/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%903.jpg alt=汚い様子3/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad%e3%81%ae%e6%b1%9a%e3%81%84%e3%83%91%e3%83%bc%e3%83%84%e3%81%9f%e3%81%a1%e3%81%ae%e6%a7%98%e5%ad%90/%e6%b1%9a%e3%81%84%e6%a7%98%e5%ad%904.jpg alt=汚い様子4/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"キーボードを二つに分離\"\u003eキーボードを二つに分離\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/T5%e3%83%88%e3%83%ab%e3%82%af%e3%82%b9%e3%81%ad%e3%81%98.jpg#center\"/\u003e \u003cfigcaption\u003e\n            T5トルクスねじ\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e8%83%8c%e9%9d%a2%e3%82%ab%e3%83%90%e3%83%bc%e3%81%ae%e3%81%ad%e3%81%98%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e6%a7%98%e5%ad%90.jpg#center\"/\u003e \u003cfigcaption\u003e\n            背面カバーのねじを外した様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%92%e4%ba%8c%e3%81%a4%e3%81%ab%e5%88%86%e8%a7%a3.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーボードを二つに分解\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%92%e4%ba%8c%e3%81%a4%e3%81%ab%e5%88%86%e8%a7%a31.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーボードを二つに分解1\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%92%e4%ba%8c%e3%81%a4%e3%81%ab%e5%88%86%e8%a7%a32.jpg#center\"/\u003e \u003cfigcaption\u003e\n            キーボードを二つに分解2\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 分解編 Part 1"},{"content":"この記事を作った動機 2025/9/10 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\nnested dict (python) dict 型のデータ内部に、dict型のデータを単純にネストすることはできないようである。何かしらの方法でアクセスできないデータが dict型のデータの内部で発生すると、以下のようなエラーが出るようである。\n\u0026lt;\u0026lt;\u0026lt;{\u0026#34;command\u0026#34;:\u0026#34;info\u0026#34;,\u0026#34;UUID\u0026#34;:\u0026#34;94035132-f796-4b75-bb16-6619d8bf7bc1\u0026#34;,\u0026#34;data\u0026#34;:null} connection handler failed Traceback (most recent call last): File \u0026#34;/usr/lib/python3.13/site-packages/websockets/asyncio/server.py\u0026#34;, line 376, in conn_handler await self.handler(connection) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/main.py\u0026#34;, line 13, in mainLoop await receiveLoop(websocket,controller.controler) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/helper/netwrok.py\u0026#34;, line 23, in receiveLoop await callback(message,websocket) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/controller.py\u0026#34;, line 41, in controler await commands[requestedCommand](request,websocket) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/commands/info.py\u0026#34;, line 88, in info \u0026#34;data\u0026#34;: { ^ notebookJSONinfo ^^^^^^^^^^^^^^^^ } ^ TypeError: unhashable type: \u0026#39;dict\u0026#39; notebookJSONinfo の中身 { \u0026#39;test\u0026#39;:{ \u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;createDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;updateDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;id\u0026#39;: \u0026#39;bb6f7d1c-c722-495c-923b-ab9e9574ef5b\u0026#39;, \u0026#39;pages\u0026#39;: [\u0026#39;test.md\u0026#39;, \u0026#39;test.json\u0026#39;], \u0026#39;files\u0026#39;: [\u0026#39;testfile.txt\u0026#39;] } } 問題のコード 以下の状態だと、data key の中に、アクセスできないデータ (notebookJSONinfo) が発生している。\n# 何かしらのコード notebookJSONinfo = findNote # 何かしらのコード await websocket.send(json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, \u0026#34;data\u0026#34; : { # 新しい dict 型の変数を宣言してしまっている # notebookJSONinfo にアクセスするための key が割り当てられていないため、エラーになる。 notebookJSONinfo } })) # 何かしらのコード notebookJSONinfo の中身を直接書いてみると、以下のようになる。\n# 何かしらのコード notebookJSONinfo = findNote # 何かしらのコード await websocket.send(json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, \u0026#34;data\u0026#34; : { { # この dict 型の変数にアクセスするために使える key が存在しない。 \u0026#39;test\u0026#39;:{ \u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;createDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;updateDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;id\u0026#39;: \u0026#39;bb6f7d1c-c722-495c-923b-ab9e9574ef5b\u0026#39;, \u0026#39;pages\u0026#39;: [\u0026#39;test.md\u0026#39;, \u0026#39;test.json\u0026#39;], \u0026#39;files\u0026#39;: [\u0026#39;testfile.txt\u0026#39;] } } } })) # 何かしらのコード 問題の解消 実装を煩雑にしたくないので、単純に notebookJSONinfo を直接 data key の内容として割り当てることで、ドキュメントに書いた通りのレスポンスをしつつ、問題を解消した。\n# 何かしらのコード notebookJSONinfo = findNote # 何かしらのコード await websocket.send(json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, # 単純に直接 data key に notebookJSONinfo をぶら下げることで、notebookJSONinfo 自体にアクセス不能になることを防いだ \u0026#34;data\u0026#34; : notebookJSONinfo })) # 何かしらのコード # 何かしらのコード notebookJSONinfo = findNote # 何かしらのコード await websocket.send(json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, # 単純に直接 data key に notebookJSONinfo をぶら下げることで、notebookJSONinfo 自体にアクセス不能になることを防いだ \u0026#34;data\u0026#34; : { \u0026#39;test\u0026#39;:{ \u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;createDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;updateDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;, \u0026#39;id\u0026#39;: \u0026#39;bb6f7d1c-c722-495c-923b-ab9e9574ef5b\u0026#39;, \u0026#39;pages\u0026#39;: [\u0026#39;test.md\u0026#39;, \u0026#39;test.json\u0026#39;], \u0026#39;files\u0026#39;: [\u0026#39;testfile.txt\u0026#39;] } } })) # 何かしらのコード firstPrototype の README を更新した 実際にシステムを試す手順を他人にわかるように書いていなかったので、書き足したりした。\nHow to start install libraries cd firstPrototype/backend/dataServer pip install -r requirements.txt cd \u0026#34;firstPrototype/frontend/onenote alternative frontend\u0026#34; npm install start this system start the clientside backend # Currently not implemented. You don\u0026#39;t have to start the clientside backend. start the dataserver backend cd firstPrototype/backend/dataServer python main.py start the frontend cd \u0026#34;firstPrototype/frontend/onenote alternative frontend\u0026#34; npm run dev ページ削除に関して ノートブック内のページを削除した場合はすぐには削除せずに、一定期間保持する仕様にしたいことを書いた。\ndelete pages When delete pages, those will not be immediately removed from the filesystem. Those are kept for a certain period of time. User can avoid accidentally delete pages.\n参考にしたサイトとか TypeError: Unhashable Type \u0026lsquo;Dict\u0026rsquo; Exception in Python - GeeksforGeeks\nhttps://www.geeksforgeeks.org/python/typeerror-unhashable-type-dict-exception-in-python/ (2025年9月21日) python - TypeError: unhashable type: \u0026lsquo;dict\u0026rsquo; - Stack Overflow\nhttps://stackoverflow.com/questions/13264511/typeerror-unhashable-type-dict (2025年9月21日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-9-21/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/9/10 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"nested-dict-python\"\u003enested dict (python)\u003c/h2\u003e\n\u003cp\u003e　dict 型のデータ内部に、dict型のデータを単純にネストすることはできないようである。何かしらの方法でアクセスできないデータが dict型のデータの内部で発生すると、以下のようなエラーが出るようである。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;\u0026lt;\u0026lt;{\u0026#34;command\u0026#34;:\u0026#34;info\u0026#34;,\u0026#34;UUID\u0026#34;:\u0026#34;94035132-f796-4b75-bb16-6619d8bf7bc1\u0026#34;,\u0026#34;data\u0026#34;:null}\nconnection handler failed\nTraceback (most recent call last):\n  File \u0026#34;/usr/lib/python3.13/site-packages/websockets/asyncio/server.py\u0026#34;, line 376, in conn_handler\n    await self.handler(connection)\n  File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/main.py\u0026#34;, line 13, in mainLoop\n    await receiveLoop(websocket,controller.controler)\n  File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/helper/netwrok.py\u0026#34;, line 23, in receiveLoop\n    await callback(message,websocket)\n  File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/controller.py\u0026#34;, line 41, in controler\n    await commands[requestedCommand](request,websocket)\n  File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/commands/info.py\u0026#34;, line 88, in info\n    \u0026#34;data\u0026#34;: {\n            ^\n        notebookJSONinfo\n        ^^^^^^^^^^^^^^^^\n    }\n    ^\nTypeError: unhashable type: \u0026#39;dict\u0026#39;\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"notebookjsoninfo-の中身\"\u003enotebookJSONinfo の中身\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e{\n    \u0026#39;test\u0026#39;:{\n        \u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;,\n        \u0026#39;createDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;,\n        \u0026#39;updateDate\u0026#39;: \u0026#39;2025/09/13\u0026#39;,\n        \u0026#39;id\u0026#39;: \u0026#39;bb6f7d1c-c722-495c-923b-ab9e9574ef5b\u0026#39;, \n        \u0026#39;pages\u0026#39;: [\u0026#39;test.md\u0026#39;, \u0026#39;test.json\u0026#39;], \n        \u0026#39;files\u0026#39;: [\u0026#39;testfile.txt\u0026#39;]\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"問題のコード\"\u003e問題のコード\u003c/h3\u003e\n\u003cp\u003e　以下の状態だと、data key の中に、アクセスできないデータ (notebookJSONinfo) が発生している。\u003c/p\u003e","title":"2025/9/21-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 OneNoteの代替として考えられるものとして、Obsidian というソフトウェアがあることが、研究について調べたり考えたりしている段階で分かった。\nそこで実際にインストールし、ちょっと触ってみたところ、参考になりそうなポイントがありそうだったので、専用にまとめる記事を作った次第である。\n今わかること vault とは? Obsidian でいうところの vault とは、OneNoteでいうノートブック相当であると思われる\nページの種類 OneNoteとは異なり、ページのテンプレートにバリエーションがある。デフォルトだと以下の二つが確認できた。\nmarkdown\n\u0026ldquo;note\u0026quot;として、マークダウン形式のコンテンツを追加可能である。drag and drop もでき、以下のように様々なコンテンツが扱える。 画像と動画の埋め込みコンテンツの例 添付ファイルと3Dモデルとテキストの例 canvas\n画像や動画、obsidian 内で書いた markdown コンテンツなど、様々な形式のファイルを配置したり添付することができる。ファイルに対して obsidian がデフォルトで対応していたり、プラグインなりが入っていてプレビューできる場合はその内容を見ることもできる。\n以下の項目について、実際に試した例も今回はここに置いておくことにした。\n画像 動画 json拡張子を持ったテキストファイル markdown ファイル obsidian 内の markdown コンテンツ テキスト canvasの例 タグ機能 タグでコンテンツが管理可能である。markdown と canvas の両方のタイプのページで利用可能なようである。 タグ検索機能の例 手書き機能 (プラグイン) Obsidian デフォルトでは、手書き機能がついていないが、プラグインとしては存在していることが分かった。ほかにもあるかもしれないが、試したのは今のところこれだけ。\ninkプラグイン ink機能を試す例 3Dモデルプレビュー (プラグイン) これもまたデフォルトでは実装されていないが、obsidian-model-viewerを使うことで、glTFとGLB形式のモデルは表示できるようになることが分かった。サンプルとして、EV2451 もどき（スタンドなし）の自作の3DモデルをglTF形式にして試した。\nちなみに、blenderやstl形式などの幅広いフォーマットを扱えるわけではない様子である。ファイルを追加しても表示されない。 model-viewerプラグイン プラグインで3Dモデルを表示できる例 階層構造でコンテンツを管理できる obsidian階層構造の例 データ管理 markdown や jsonなどのデータとして保存されており、特別なバイナリ形式をしていない。 データがファイルシステム上のフォルダの階層構造として管理されている (base) PS C:\\Users\\username\\Documents\\notebook\u0026gt; tree /f フォルダー パスの一覧: ボリューム Windows ボリューム シリアル番号は 485C-1E39 です C:. └─test │ This is test.md │ Untitled.md │ ├─.obsidian │ app.json │ appearance.json │ core-plugins.json │ graph.json │ workspace.json │ └─test │ Untitled 1.canvas │ Untitled 2.canvas │ Untitled.canvas │ └─Untitled 2025-07-27.md 任意のファイルを drag and drop で添付したり配置しても、あとから特定の階層構造にファイルを入れるなど、明示しない限りデフォルトで vault のルートディレクトリ的なところにファイルが蓄積されていき、無秩序に散らばってしまう。 Importer Obsidian には、公式で別のプラットフォームからコンテンツを移行できるプラグインがあるようなので、一応試そうとしてみた。\nOneNote だけでなく、Google Keep や Apple Note など多種多様な移行オプションがある。 OneNote に関しては、少なくともlinux環境で試したところ、.one や .onetoc2 などといったローカルに保存されたファイルからのインポートはできないようである。 初回画面的なところでImporterの利用を勧められる CommunityPluginにあるImporter Importerを開く 多種多様なプラットフォームをサポート OneNoteのインポートを試みる ちなみにローカルに保存している OneNote のデータは、Web 版に方にアップロードすれば、インポートできるのではないかと以下の、トラブルシュートの項目を見て考えられた。ただこの方法だと、OneDrive の容量制限次第ということになる。OneDrive 無料枠だとノートブックが 5GB 以上を超えると多分この方法は使えないと思われる。\nImported notes are empty or missing content This issue may occur on notebooks that you rarely use. To solve the issue follow these steps:\nOpen OneNote Web in your browser. Right click on the Notebooks which are missing content. Select Export Notebook from the menu. Unzip the file you\u0026rsquo;ve just downloaded into a folder. Upload your OneNote notebooks here. Open Obsidian Importer and try importing again If you\u0026rsquo;ve followed these tips and your issue remains unresolved, it\u0026rsquo;s possible that there is a temporary problem with Microsoft servers. If that\u0026rsquo;s the case, wait a few minutes and try again. If the problem persists, please open an issue on the Obsidian Importer GitHub repository. OneNoteとの比較 obsidianとOneNoteの違い OneNote obsidian ページの種類 一つのみ markdown, canvas データ形式 プロプライエタリバイナリ markdown,json,添付されたファイル形式そのまま データ階層 セクションごとにプロプライエタリバイナリ フォルダ階層構造 拡張性 アドイン？機能（要調査） Webベースプラグイン プレビュー 対応した形式の動画や画像、PDFなどに限る デフォルトかプラグインで対応していれば可 プラグイン自作 難しそう 基本的なweb開発の知識とドキュメントの読み方ができれば容易そう ローカル環境 ローカルで動く ローカルで動く ※ ここでいう\u0026quot;基本的なweb開発の知識\u0026quot;とは、HTML JS CSSといったものやフロントエンド、バックエンドなどの概念をある程度理解していることなど、広域にわたるweb開発について意図している。\n※ obsidian プラグイン開発では、ドキュメントが充実している。\n気になったところ obsidian のプラグインの構造 Release 0.3.4 · daledesilva/obsidian_inkを見てみて思ったのが、chrome の拡張機能と似たような構造をしているということであった。以下の三つのファイルから構成されていることに注目して基本はWebベースであると思った。\nmanifest.json main.js styles.css Ink プラグイン自体 obsidian_inkの拡張機能を試してみて思ったのが、OneNoteほど自由で充実した手書き機能はない点である。\n使える色は白色のみで、線の太さとか、四角や丸といった基本的な図形を描画するための支援機能とかもなく、細かいところは基本的省かれてシンプルに作られている印象である。何か画像の上に書き込みをするとか、元に戻す(undo)操作ややり直し(redo)操作というようなこともできないようである。\nペンタブレットで試したところ、筆圧検知をして線の太さが変わることは分かった。本当に今のところはこの拡張機能では手書き以上のことは想定されていないように感じられた。ほかのメディアとの統合という意味では薄いと感じられた。\nちなみに、マークダウン上にInk拡張機能を使うと、以下のように意味のあるコードブロックとして記録される。\nhanddrawn-ink { \u0026#34;versionAtEmbed\u0026#34;: \u0026#34;0.3.4\u0026#34;, \u0026#34;filepath\u0026#34;: \u0026#34;Ink/Drawing/2025.7.27 - 23.00pm.drawing\u0026#34;, \u0026#34;width\u0026#34;: 500, \u0026#34;aspectRatio\u0026#34;: 1 } canvasの不自由さ OneNoteに近しいオブジェクト自由な位置への配置やリサイズは canvas ページを使うことで可能であるが、それもまたOneNoteほどではない。特に何かを重ねて扱ったり、書き込むようなことは苦手なようである。\nどちらかというと画像やマークダウンのコンテンツなどといったものを組み合わせて、それらをオブジェクトとしていろいろ配置できるようにしたという感じがする。\ncanvas と名前がついているが、何かペンタブで少なくともプラグインなしでは直接書き込めたり、任意の基本的な図形を配置できたりするわけではないようである。\nタスク管理機能がない プラグインとしては存在しするし、markdown に埋め込める形のものは存在しているが、プロジェクト単位で、マイルストーンごとにやることを細かく管理できるとかそういう感じではなかった。\nObsidian closed source 説 Obsidian では、データこそシンプルに JSON で保存されたり、個人用途では無料で使えるものの、ソフトウェア本体自体はソースコードが公開されていないという点で、フリーではないようである。実際\u0026quot;Obsidian github\u0026quot;みたいに調べても本体自体のコードは見つからず、プラグインがたくさんヒットする。\nIs Obsidian open source? : r/ObsidianMD\nhttps://www.reddit.com/r/ObsidianMD/comments/tv6uql/is_obsidian_open_source/ (2025年9月8日) 現時点でのこの記事のまとめ 真似したいと思った点 chrome 拡張機能のようなプラグインの構造 特別なバイナリ形式のフォーマットが使われておらず、markdown、JSONなどとして既存のフォーマットに従い、可読性を損なわない形で保存されている。 階層構造をフォルダの階層構造で表現している タグによるコンテンツ管理、検索機能 不満点 OneNoteほど自由に様々なメディアを統合して扱えるわけではない Canvas 機能の不自由さ 添付ファイルが無秩序にデフォルトで vault のルートディレクトリに配置されてしまう。 思ったこと 研究では一から完全に作るというより、ある程度既存のものの発想を調べてから、それらも参考に取り込んでいきつつ、不満点をつぶせるようにしていったほうが現実的な労力内に収まると思った。\n例えば、真似したいと思った点を参考にすれば、一からOneNoteのバイナリ形式のデータをどのようにして可読性のある形式のデータとして保存するか、ということに関してはある程度すでに答えが出ている気もする。\n私としては、すでにある設計思想とか、既にある発想はできる範囲で見つけては組み合わせたいと思っている。\n参考にしたサイトとか フリースペース Obsidian - Sharpen your thinking\nhttps://obsidian.md/ (2025年7月27日) daledesilva/obsidian_ink\nhttps://github.com/daledesilva/obsidian_ink (2025年7月27日) Release 0.3.4 · daledesilva/obsidian_ink\nhttps://github.com/daledesilva/obsidian_ink/releases/tag/0.3.4 (2025年7月27日) janispritzkau/obsidian-model-viewer: An Obsidian plugin to view and embed 3D models using Google’s \u0026lt;model-viewer\u0026gt; component.\nhttps://github.com/janispritzkau/obsidian-model-viewer (2025年7月28日) Home - Developer Documentation\nhttps://docs.obsidian.md/Home (2025年7月28日) Import from Microsoft OneNote - Obsidian Help\nhttps://help.obsidian.md/import/onenote (2025年8月9日) Obsidian OSSではない説 Is Obsidian open source? : r/ObsidianMD\nhttps://www.reddit.com/r/ObsidianMD/comments/tv6uql/is_obsidian_open_source/ (2025年9月8日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/obsidian/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　OneNoteの代替として考えられるものとして、Obsidian というソフトウェアがあることが、研究について調べたり考えたりしている段階で分かった。\u003c/p\u003e\n\u003cp\u003e　そこで実際にインストールし、ちょっと触ってみたところ、参考になりそうなポイントがありそうだったので、専用にまとめる記事を作った次第である。\u003c/p\u003e\n\u003ch2 id=\"今わかること\"\u003e今わかること\u003c/h2\u003e\n\u003ch3 id=\"vault-とは\"\u003evault とは?\u003c/h3\u003e\n\u003cp\u003e　Obsidian でいうところの vault とは、OneNoteでいうノートブック相当であると思われる\u003c/p\u003e\n\u003ch3 id=\"ページの種類\"\u003eページの種類\u003c/h3\u003e\n\u003cp\u003e　OneNoteとは異なり、ページのテンプレートにバリエーションがある。デフォルトだと以下の二つが確認できた。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003emarkdown\u003cbr\u003e\n　\u0026ldquo;note\u0026quot;として、マークダウン形式のコンテンツを追加可能である。drag and drop もでき、以下のように様々なコンテンツが扱える。\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;row;\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/obsidian/%e7%94%bb%e5%83%8f%e3%81%a8%e5%8b%95%e7%94%bb%e3%81%ae%e5%9f%8b%e3%82%81%e8%be%bc%e3%81%bf%e3%82%b3%e3%83%b3%e3%83%86%e3%83%b3%e3%83%84%e3%81%ae%e4%be%8b.png#center\"\n             alt=\"Obsidian サンプル\"/\u003e \u003cfigcaption\u003e\n                画像と動画の埋め込みコンテンツの例\n            \u003c/figcaption\u003e\n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/obsidian/%e6%b7%bb%e4%bb%98%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab%e3%81%a83D%e3%83%a2%e3%83%87%e3%83%ab%e3%81%a8%e3%83%86%e3%82%ad%e3%82%b9%e3%83%88%e3%81%ae%e4%be%8b.png#center\"\n             alt=\"Obsidian サンプル\"/\u003e \u003cfigcaption\u003e\n                添付ファイルと3Dモデルとテキストの例\n            \u003c/figcaption\u003e\n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ecanvas\u003cbr\u003e\n　画像や動画、obsidian 内で書いた markdown コンテンツなど、様々な形式のファイルを配置したり添付することができる。ファイルに対して obsidian がデフォルトで対応していたり、プラグインなりが入っていてプレビューできる場合はその内容を見ることもできる。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　以下の項目について、実際に試した例も今回はここに置いておくことにした。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e画像\u003c/li\u003e\n\u003cli\u003e動画\u003c/li\u003e\n\u003cli\u003ejson拡張子を持ったテキストファイル\u003c/li\u003e\n\u003cli\u003emarkdown ファイル\u003c/li\u003e\n\u003cli\u003eobsidian 内の markdown コンテンツ\u003c/li\u003e\n\u003cli\u003eテキスト\u003c/li\u003e\n\u003c/ul\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/obsidian/canvas%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"Obsidian サンプル\"/\u003e \u003cfigcaption\u003e\n            canvasの例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"タグ機能\"\u003eタグ機能\u003c/h3\u003e\n\u003cp\u003e　タグでコンテンツが管理可能である。markdown と canvas の両方のタイプのページで利用可能なようである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/obsidian/%e3%82%bf%e3%82%b0%e6%a4%9c%e7%b4%a2%e6%a9%9f%e8%83%bd%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"Obsidian サンプル\"/\u003e \u003cfigcaption\u003e\n            タグ検索機能の例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"手書き機能-プラグイン\"\u003e手書き機能 (プラグイン)\u003c/h3\u003e\n\u003cp\u003e　Obsidian デフォルトでは、手書き機能がついていないが、プラグインとしては存在していることが分かった。ほかにもあるかもしれないが、試したのは今のところこれだけ。\u003cbr\u003e\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/daledesilva/obsidian_ink\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e","title":"Obsidianについて（調査）"},{"content":"この記事を作った動機 Apple の古いキーボードをきれいにする 分解編 Part 1の続き。この記事では基板周りの分解について記事を作る。\n分解編 基板の全体像 基板にはんだ付けされたケーブルをとる はんだを取り除く ケーブルの固定具をとる 基板からねじをとる 構造用のねじも取る 外したパーツたち 基盤が外れたときの全体像 次の内容 Apple の古いキーボードをきれいにする 分解編 Part 3 参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble1/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble/\"\u003eApple の古いキーボードをきれいにする 分解編 Part 1\u003c/a\u003eの続き。この記事では基板周りの分解について記事を作る。\u003c/p\u003e\n\u003ch2 id=\"分解編\"\u003e分解編\u003c/h2\u003e\n\u003ch3 id=\"基板の全体像\"\u003e基板の全体像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e5%9f%ba%e7%9b%a4%e3%81%ae%e5%85%a8%e4%bd%93%e5%83%8f.jpg#center\"\n         alt=\"基盤の全体像\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"基板にはんだ付けされたケーブルをとる\"\u003e基板にはんだ付けされたケーブルをとる\u003c/h3\u003e\n\u003cp\u003e\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%81%af%e3%82%93%e3%81%a0%e4%bb%98%e3%81%91%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab.jpg alt=はんだ付けされているケーブル/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%81%af%e3%82%93%e3%81%a0%e4%bb%98%e3%81%91%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab1.jpg alt=はんだ付けされているケーブル1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 350px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e5%be%8c%e3%81%ae%e5%9f%ba%e7%9b%a4%e3%81%ae%e6%a7%98%e5%ad%901.jpg alt=ケーブルを外した後の基盤の様子1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 350px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e5%be%8c%e3%81%ae%e5%9f%ba%e7%9b%a4%e3%81%ae%e6%a7%98%e5%ad%90.jpg alt=ケーブルを外した後の基盤の様子/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e5%9f%ba%e7%9b%a4%e3%81%8b%e3%82%89%e5%a4%96%e3%81%97%e3%81%9f%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab.jpg#center\"\n         alt=\"基盤から外したケーブル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"はんだを取り除く\"\u003eはんだを取り除く\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%81%af%e3%82%93%e3%81%a0%e3%81%99%e3%81%84%e3%81%a8%e3%82%8a%e3%81%9b%e3%82%93%e3%81%a7%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%97%e3%81%9f%e6%a7%98%e5%ad%90.jpg#center\"\n         alt=\"はんだすいとりせんできれいにした様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%83%95%e3%83%a9%e3%83%83%e3%82%af%e3%82%b9%e6%b1%9a%e3%82%8c%e3%82%92%e5%8f%96%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b.jpg#center\"\n         alt=\"フラックス汚れを取っている\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"ケーブルの固定具をとる\"\u003eケーブルの固定具をとる\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%81%8c%e5%9b%ba%e5%ae%9a%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e9%83%a8%e5%88%86.jpg#center\"\n         alt=\"ケーブルが固定されている部分\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e5%9b%ba%e5%ae%9a%e5%85%b7%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e6%a7%98%e5%ad%90.jpg#center\"\n         alt=\"ケーブル固定具を外した様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e5%9b%ba%e5%ae%9a%e5%85%b7%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e6%a7%98%e5%ad%901.jpg#center\"\n         alt=\"ケーブル固定具を外した様子1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%81%8c%e5%a4%96%e3%82%8c%e3%82%8b%e6%a7%98%e5%ad%90.jpg#center\"\n         alt=\"ケーブルが外れる様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"基板からねじをとる\"\u003e基板からねじをとる\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e5%9f%ba%e7%9b%a4%e3%82%92%e5%9b%ba%e5%ae%9a%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e3%81%ad%e3%81%98%e3%81%ae%e4%bd%8d%e7%bd%ae.jpg#center\"\n         alt=\"基盤を固定しているねじの位置\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%81%ae%e4%b8%8b%e3%81%ab%e9%9a%a0%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e3%81%ad%e3%81%98%e3%81%ae%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%97.jpg#center\"\n         alt=\"ケーブルの下に隠れているねじのクロースアップ\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"構造用のねじも取る\"\u003e構造用のねじも取る\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e6%a7%8b%e9%80%a0%e7%94%a8%e3%81%ae%e3%81%ad%e3%81%98.jpg#center\"\n         alt=\"構造用のねじ\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"外したパーツたち\"\u003e外したパーツたち\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab%e3%82%92%e6%ad%a2%e3%82%81%e3%81%a6%e3%81%84%e3%81%9f%e3%81%ad%e3%81%98%e3%81%a8%e3%83%97%e3%83%a9%e3%82%b9%e3%83%81%e3%83%83%e3%82%af%e9%83%a8%e5%93%81.jpg#center\"\n         alt=\"ケーブルを止めていたねじとプラスチック部品\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e7%89%b9%e6%ae%8a%e3%81%aaUSB%e3%82%b1%e3%83%bc%e3%83%96%e3%83%ab/%e5%88%87%e3%82%8c%e8%be%bc%e3%81%bf%e3%81%ae%e3%81%82%e3%82%8bUSB%e7%ab%af%e5%ad%902.jpg#center\"\n         alt=\"切れ込みのあるUSB端子2\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"基盤が外れたときの全体像\"\u003e基盤が外れたときの全体像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%9b%9e%e8%b7%af%e5%9f%ba%e6%9d%bf/%e6%9c%80%e7%b5%82%e7%9a%84%e3%81%ab%e5%9f%ba%e7%9b%a4%e3%82%92%e5%a4%96%e3%81%97%e3%81%9f%e6%99%82%e3%81%ae%e5%9f%ba%e7%9b%a4%e3%81%ae%e5%85%a8%e4%bd%93%e5%83%8f.jpg#center\"\n         alt=\"最終的に基盤を外した時の基盤の全体像\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"次の内容\"\u003e次の内容\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble2/\"\u003eApple の古いキーボードをきれいにする 分解編 Part 3\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 分解編 Part 2"},{"content":"この記事を作った動機 2025/9/24 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\nフロンエンド関連 動作の様子 ネットワーク関連 データの扱いを変更 websocket 経由でデータサーバとフロントエンドがやり取りする型をフロントエンド側に拡張する前提で汎用的に定義した。自分で data key の項目は書かなければならない。(database.tsx)\n// frontend -\u0026gt; dataserver export interface baseResponseTypesFromDataserver{ status: string; errorMessage: string; UUID: string | null; command: string | null; } // frontend -\u0026gt; datasever export interface baseRequestTypesFromFromtend{ command: string, UUID: string, } // dataserver -\u0026gt; frontend export interface baseInterruptRequestFromDataserver{ componentName: string, command: string, UUID: string } 以下は、(createNotebook.tsx) における baseResponseTypes の例\nimport { type baseResponseTypes } from \u0026#34;../network/database\u0026#34;; interface pageType extends baseResponseTypes{ data: [] } ネットワーク送信処理の共通化 database.tsx で共通の websocket でデータをバックエンドサーバに送るための専用のコードを書いた。接続中や切断されていてまだ再接続がされていないときは、 interval 秒後に再試行する仕組みにした。\nexport function send(websocket:WebSocket, request:string){ if( websocket.readyState != WebSocket.CONNECTING \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSED \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSING ){ setTimeout(() =\u0026gt; { websocket.send(request) },interval * 1000) } } データサーバの再接続 database.tsx で再接続する仕組みを書いた。最初は、複数の再接続用の関数が並列で動いてしまったり、他のホットリロード動いていたフロントエンドと新しく読み込み直したフロントエンドが干渉してうまく動作確認できなかったりはしたが、とりあえず動くところまで持ってきた。\nただ、データサーバとの接続が途切れたとか、再接続中であることをユーザーに示す UI がまだなのは課題であり、messageboxの実装ができ次第実装しようと考えてはいる。\nexport function useDatabaseEffects() { const serverIP = useDatabaseStore((s) =\u0026gt; s.serverIP); const setWebsocket = useDatabaseStore.setState; const getWebsocket = useDatabaseStore((s) =\u0026gt; s.getWebsocket) // const init = useRef(true) useEffect(() =\u0026gt; { if (!serverIP) return; const reconnectLoop = () =\u0026gt; { console.log(\u0026#34;reconnect observer\u0026#34;) const websocket = getWebsocket() if(websocket != null){ if(websocket.readyState == WebSocket.OPEN){ // observe the connection setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) return } } setTimeout(() =\u0026gt; { const websocket = new WebSocket(serverIP); // websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) // websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) setWebsocket({ websocket: websocket }); },interval / 2 * 1000) setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) } const websocket = new WebSocket(serverIP); websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) setWebsocket({ websocket: websocket }); return () =\u0026gt; { websocket.close(); }; }, [serverIP, setWebsocket]); } markdown view の実装 markdwon の表示を marked ライブラリで行うようにし、sytle は別途デフォルトのHTMLのスタイルを参考に指定した。\nmessagebox messageBox を実装しようと考えた。まだ実装できていないが、各コンポーネントがユーザーにエラーなどを表示できる共通のUIを実装したいと考えている\ncreate notebook 機能の検証 create notebook を機能するように調整しようとしたが、まだ不完全なようである。\nuuid.uuid4 が UUID 型を返しており、str へのキャストが必要だった loadSettings.py で、相対パスが指定されていたら、python が実行されたワーキングディレクトリに\u0026quot;.\u0026ldquo;を置き換えるようにしていたはずが、機能していなかったので修正した。 overlayWindow の実装 z-index について設定を考えた。基本的には、overlay window に関しては、大多数のOSで採用されているようなウィンドウシステムの挙動を真似ることにした。\noverlay window について、アクティブ、非アクティブの実装をしようと思った。アクティブなものは不透明に、非アクティブなものは、透過度を強める。\noverlay window について、アクティブ、非アクティブの実装はできたが、z-indexが正しく更新できないバグが発生している。 ー＞ ある程度は治った 状態変数の使い方を間違っていた。 https://www.nyanmo.info/posts/webdevelop/react/zustand/\novarlayWindow でウィンドウが隠れないように、画面外に移動できないように制限をした\nToggleToolsBar の実装 すべてのウィンドウを閉じるボタンを作った タブ機能を実装し、すべてを tools bar に詰め込まないようにする予定。現時点では、タブを選択するためのウィンドを表示する緑のボタンと、タブ選択用のウィンドウをつくった。 free ページの実装 free ページのオブジェクトの要素として、縦と横のサイズプロパティを追加した。 とりあえず free ページでテキストを表示できるようにした。そしてとりあえず動かせるようにした。 リッチなテキスト、例えば初期気設定ができるなどについては、あとからmarkdownを使って専用の要素として余裕があれば実装することを考えた。 tailwindcss の挙動 tailwindcss では、基本的に元々 className 等として静的にスタイルが指定されていないと、正しく動作しないことがわかった。スクリプトでクラス名を制御しても、色が正しく反映されないないなどの症状になることがわかった。\nそこで、あらかじめ背景色については、ある程度事前に使えるようにすることにした。具体的には、見えない要素を作って、その要素のクラス名にひたすら一部を除くすべての背景色を className として指定し、ユーザーからは見えないが、スクリプト上では表示していることになるようにした。\nColorPalette.tsx // force tailwindcss to add color style export function ColorPalette(){ return \u0026lt;div\u0026gt; \u0026lt;div className=\u0026#34;bg-yellow-100\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;bg-yellow-200\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;bg-yellow-300\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; ... \u0026lt;div className=\u0026#34;bg-stone-900\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;bg-stone-950\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; } window.tsx // ...何かしらのコード // show selector of notebooks, pages and files export default function Window(){ return( \u0026lt;\u0026gt; \u0026lt;div className=\u0026#34;window flex flex-row z-2\u0026#34;\u0026gt; \u0026lt;ColorPalette\u0026gt;\u0026lt;/ColorPalette\u0026gt; \u0026lt;ToggleToolsBar\u0026gt;\u0026lt;/ToggleToolsBar\u0026gt; \u0026lt;Page\u0026gt;\u0026lt;/Page\u0026gt; \u0026lt;Selector\u0026gt;\u0026lt;/Selector\u0026gt; \u0026lt;CreateNotebook\u0026gt;\u0026lt;/CreateNotebook\u0026gt; \u0026lt;CreatePage\u0026gt;\u0026lt;/CreatePage\u0026gt; \u0026lt;DeleteNotebook\u0026gt;\u0026lt;/DeleteNotebook\u0026gt; \u0026lt;DeletePage\u0026gt;\u0026lt;/DeletePage\u0026gt; \u0026lt;StartButtonMenu\u0026gt;\u0026lt;/StartButtonMenu\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/\u0026gt; ) } その他 削除系ボタン とりあえず、ノートとページ削除ボタンをフロントエンド側に作った。まだ具体的な実装はない。\n状態変数は設定直後に読み込むと内容が反映されない? export function CreatePage(){ ... const [pageType,setPageType] = useState\u0026lt;pageType | null\u0026gt;(null) ... useEffect(() =\u0026gt; { ... const handleMessage = (event:MessageEvent) =\u0026gt; { const result = JSON.parse(String(event.data)); console.log(result) // dataserver -\u0026gt; frontend // frontend -\u0026gt; dataserver if(result.UUID == requestUUID.current \u0026amp;\u0026amp; \u0026#34;getPageType\u0026#34; == result.command){ if (!result.status.includes(\u0026#34;error\u0026#34;)) { setPageType(result) console.log(\u0026#34;websocket on message\u0026#34;) console.log(pageType) // null } else { setPageType({ status: result.status, errorMessage: result.errorMessage, UUID: result.UUID, command: result.command, data: null, }); } } } websocket.addEventListener(\u0026#34;message\u0026#34;,handleMessage) return () =\u0026gt; { websocket.removeEventListener(\u0026#34;message\u0026#34;,handleMessage) } } useEffect(() =\u0026gt; { console.log(\u0026#34;useEffect: pageType\u0026#34;) console.log(pageType) // non null },[pageType]) } バックエンド関連 getPageType を実装した データサーバのバックエンド側で、getPageType コマンドを実装した。具体的には、どんなページの種類が利用可能かフロントエンドに伝えるものである。例えば以下のようなものである。\nこのコマンドは、ページを新規作成するときに主にフロントエンドが、どんな種類のページが利用可能か、データサーバに問い合わせるためにある。\nリクエスト例 { \u0026#34;command\u0026#34; : \u0026#34;getPageType\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : { } } レスポンス例 { \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;errorMessage\u0026#34;: \u0026#34;nothing\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;e2e920de-42ad-4d79-bdab-7877cbcb8747\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;getPageType\u0026#34;, \u0026#34;data\u0026#34;: [ \u0026#34;free\u0026#34;, \u0026#34;markdown\u0026#34; ] } UUID をページ識別用に追加 { \u0026#34;pageType\u0026#34;: \u0026#34;free\u0026#34;, \u0026#34;tags\u0026#34;: [\u0026#34;This\u0026#34;,\u0026#34;is\u0026#34;,\u0026#34;testpage\u0026#34;], \u0026#34;files\u0026#34;: [\u0026#34;testfile.txt\u0026#34;], \u0026#34;UUID\u0026#34;: \u0026#34;950b0810-702c-4489-bbce-bc9fdd9f0b22\u0026#34;, // 追加部分 \u0026#34;pageData\u0026#34;:{ \u0026#34;items\u0026#34;:[ { \u0026#34;ID\u0026#34;: \u0026#34;3d3751c3-20ee-4124-90df-464860620f4a\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;text\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;This is test text. Yukkuri reimu said \u0026#39;ゆっくりしていってね\u0026#39;.\u0026#34;, \u0026#34;position\u0026#34;:{ \u0026#34;x\u0026#34;: 200, \u0026#34;y\u0026#34;: 100, \u0026#34;z\u0026#34;: 0 } }, { \u0026#34;ID\u0026#34;: \u0026#34;ef3429f5-f150-4ad2-a325-80257fad8f6b\u0026#34;, \u0026#34;type\u0026#34;: \u0026#34;text\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;This is test text. Yukkuri marisa abuse Yukkuri reimu.\u0026#34;, \u0026#34;position\u0026#34;:{ \u0026#34;x\u0026#34;: 200, \u0026#34;y\u0026#34;: 150, \u0026#34;z\u0026#34;: 1 } } ] } } マークダウンにメタデータ情報を結局埋め込んだ ++++ { files:[\u0026#34;なんかよくわかんない絵ジト目口開き3.png\u0026#34;], tags:[], UUID:\u0026#34;6428f4c7-7622-40b9-a6bc-f895b3f9ada8\u0026#34; } ++++ # hello world This is test content. ... バックエンドのヘルパー関数の実装 データサーババックエンドに、ファイルやフォルダ消去用の関数をhelper.commonのdeleteDataSafely関数として追加した。 バックエンドについて リモートサーバを使うにしても、結局キャッシュのために dataserver をローカルで動かすので、clientside は dataserver は統合してしまってもいいかもしれないと考えた。 参考にしたサイトとか markedjs/marked: A markdown parser and compiler. Built for speed.\nhttps://github.com/markedjs/marked (2025年10月2日) CSS Default Browser Values for HTML Elements\nhttps://www.w3schools.com/cssref/css_default_values.php (2025年10月2日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-10-2/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/9/24 から、今日に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"フロンエンド関連\"\u003eフロンエンド関連\u003c/h2\u003e\n\u003ch3 id=\"動作の様子\"\u003e動作の様子\u003c/h3\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-10-2/2025-10-2-%e7%a0%94%e7%a9%b6%e8%a8%98%e9%8c%b2%e3%81%ae%e5%8b%95%e7%94%bb.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch3 id=\"ネットワーク関連\"\u003eネットワーク関連\u003c/h3\u003e\n\u003ch4 id=\"データの扱いを変更\"\u003eデータの扱いを変更\u003c/h4\u003e\n\u003cp\u003e　websocket 経由でデータサーバとフロントエンドがやり取りする型をフロントエンド側に拡張する前提で汎用的に定義した。自分で data key の項目は書かなければならない。(database.tsx)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// frontend -\u0026gt; dataserver\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebaseResponseTypesFromDataserver\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eerrorMessage\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eUUID\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecommand\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// frontend -\u0026gt; datasever\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebaseRequestTypesFromFromtend\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecommand\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eUUID\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// dataserver -\u0026gt; frontend\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebaseInterruptRequestFromDataserver\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecomponentName\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecommand\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eUUID\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　以下は、(createNotebook.tsx) における baseResponseTypes の例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebaseResponseTypes\u003c/span\u003e } \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;../network/database\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003einterface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epageType\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebaseResponseTypes\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"ネットワーク送信処理の共通化\"\u003eネットワーク送信処理の共通化\u003c/h4\u003e\n\u003cp\u003e　database.tsx で共通の websocket でデータをバックエンドサーバに送るための専用のコードを書いた。接続中や切断されていてまだ再接続がされていないときは、 interval 秒後に再試行する仕組みにした。\u003c/p\u003e","title":"2025/10/2-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 OneNoteの代替を作りたいというところから出発したので、OneNote自体について調べる必要があると思ったため。\n私のOneNoteの利用例 OneNote は Office 365などに含まれていて、有償版とMS store からダウンロードできる無償版の2種類がある。無償版はしつこく MS 365 に課金するように催促される。\nwindows 環境であればローカルにデスクトップ版をインストールし、今までのOffice 2021とか、Office 2007みたいに使うこともでき、OneNote も同じ感じである。クラウド機能もあるらしいが、私は大抵のクラウドサービスには否定的で明るくないので、使ったことはない。\n私がOneNoteを使っていたときは、半期ごとにノートを分けて、その中に授業ごとのセクションを作り、ページで細かい授業単位のデータ管理をするという感じであった。\n階層構造の利用例 OneNote利用例 様々な入力やメディアを扱える例 気になる機能 階層的なコンテンツ管理 ノートブック セクション ページ \u0026hellip; 階層構造の利用例 Office 系列と似たような書式フォーマットや操作 インク機能のインターフェイス（全体表示のとき） インク機能のインターフェイス-全体表示の時 自由なオブジェクトの配置 以下は、ある授業のレポートでネットワークの設定や構成について、与えられた課題にどう取り組んだのか説明する必要があった時の例である。画像をいろんなところに自由に配置し、インク機能を使って書き込み、一枚の絵として説明を完成させた。 自由なオブジェクト配置の例 書き込み可 今回はPDF資料の上に、インク機能で書き込む例をいかに示す。このようにして自由にいろんなものを重ね合わせて扱うことができる。 インクと画像-書き込める例 マルチメディアサポート ペンタブレット 画像、動画、テキスト バイナリファイル添付 様々な入力やメディアを扱える例 ストローク消しゴム ink 機能では、ただ部分的にペイントソフトと同じように線とか描いたものを消せるだけじゃなくて、ストローク単位で一気に消したりできるのは、正直大きい。\nクロスプラットフォーム対応 完全ではないが、クロスプラットフォームに対応している web 版があることに気づいた。そして、どうせ web 版ではろくに ink API とか使えないだろうと思っていたのだが、Windows 11 24H2 と Google Chrome 138 の組み合わせでは、実際に手書き入力ができることがわかったりした。思い込みが発覚し、調査の余地があることが分かった。\nlinux上で動く様子 win上で動く様子 ink API とりあえずクロスプラットフォームで ink API が動くか簡単に調べてみた。なお Mac OS 系列は実機を持っていないので調べていない。あと筆圧検知はどのテストでも対応している感じではなく、単に一定の太さ、濃さの線が引かれるといった感じであった。あくまでペンとしては認識し、自動的にモードが切り替わるところまでであった。\nWindows 11 24H2 と Google Chrome 138 (OK) # wayland 環境の参考 gsettings set org.gnome.mutter experimental-features \u0026#34;[\u0026#39;scale-monitor-framebuffer\u0026#39;,\u0026#39;xwayland-native-scaling\u0026#39;]\u0026#34; Gnome と Linux、Google Chrome 138 Wayland (X) # ~/.config/chrome-flags.conf # ink API に関係ありそうなもの --enable-features=UseOzonePlatform --ozone-platform=wayland --wayland-text-input-version=3 --enable-wayland-ime --gtk-version=4 # ink API に関係なさそうなもの --enable-features=Vulkan --disable-features=UseChromeOSDirectVideoDecoder #--enable-features=VaapiVideoDecodeLinuxGL --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=GlobalShortcutsPortal xwininfo xwininfo: Please select the window about which you would like information by clicking the mouse in that window. # 対象のWindow(Chrome)をクリックしても反応がない。 # -\u0026gt; Wayland 環境で動いている ^C XWayland (OK) # ~/.config/chrome-flags.conf # ink API に関係ありそうなもの --enable-features=UseOzonePlatform # --ozone-platform=wayland --ozone-platform=x11 --wayland-text-input-version=3 --enable-wayland-ime --gtk-version=4 # ink API に関係なさそうなもの --enable-features=Vulkan --disable-features=UseChromeOSDirectVideoDecoder #--enable-features=VaapiVideoDecodeLinuxGL --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=GlobalShortcutsPortal xwininfo xwininfo: Please select the window about which you would like information by clicking the mouse in that window. xwininfo: Window id: 0xa00020 \u0026#34;Test - Google Chrome\u0026#34; Absolute upper-left X: 0 Absolute upper-left Y: 96 Relative upper-left X: 0 Relative upper-left Y: 96 Width: 4608 Height: 2496 Depth: 32 Visual: 0x2c6 Visual Class: TrueColor Border width: 0 Class: InputOutput Colormap: 0xa00003 (not installed) Bit Gravity State: NorthWestGravity Window Gravity State: NorthWestGravity Backing Store State: NotUseful Save Under State: no Map State: IsViewable Override Redirect State: no Corners: +0+96 -0+96 -0-0 +0-0 -geometry 4608x2496+0-0 X11 (OK) # ~/.config/chrome-flags.conf # ink API に関係ありそうなもの --enable-features=UseOzonePlatform # --ozone-platform=wayland --ozone-platform=x11 --wayland-text-input-version=3 --gtk-version=4 --enable-wayland-ime # ink API に関係なさそうなもの --enable-features=Vulkan --disable-features=UseChromeOSDirectVideoDecoder #--enable-features=VaapiVideoDecodeLinuxGL --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=GlobalShortcutsPortal xwininfo xwininfo: Please select the window about which you would like information by clicking the mouse in that window. xwininfo: Window id: 0x1400016 \u0026#34;Test - Google Chrome\u0026#34; Absolute upper-left X: 0 Absolute upper-left Y: 96 Relative upper-left X: 0 Relative upper-left Y: 96 Width: 3840 Height: 2064 Depth: 32 Visual: 0x507 Visual Class: TrueColor Border width: 0 Class: InputOutput Colormap: 0x1400003 (not installed) Bit Gravity State: NorthWestGravity Window Gravity State: NorthWestGravity Backing Store State: NotUseful Save Under State: no Map State: IsViewable Override Redirect State: no Corners: +0+96 -0+96 -0-0 +0-0 -geometry 3840x2064+0-0 全体表示 Web 版では全体表示は今のところ(2025年8月2日)は非対応のようである。\nローカルでのデータ管理 OneDrive にデータが保存されており、ダウンロードが可能であった。ノートブック単体ではダウンロードオプションがなく、Notebooks フォルダごとダウンロードすることで、ローカルにデータを置き、管理することは可能であることが分かった。ただ直接 Web 版からローカルファイルを参照させることは、クラウド前提である様相であり、できなさそうである。\nダウンロードができる様子とできない様子 Notebooksフォルダ自体はダウンロード可 Notebook単体では不可の模様 ダウンロードできるファイル構成 見た感じはローカルで動く OneNote とフォルダ構成と違いは見受けられない。\n(base) PS C:\\Users\\username\\Downloads\\Notebooks\u0026gt; tree /f Folder PATH listing for volume Win Volume serial number is C:. └─Notebooks └─Test test section.one Test.onetoc2 無料版がある OneNote無料版 不満点 プロプライエタリバイナリ セクションごとに、独自バイナリ形式でデータが記録されている。どういう構造になっているのか不明である。ただちょくちょく github に何かしらデータを読み出すプロジェクトは転がっているようである。 バイナリファイルたち 調査ポイント .one ファイルの実態 ただのバイナリファイルなのか、zipとかとの親戚的な何かなのか、何かしらAPIがあるのか。\nアドイン？について アドインのサンプル github にアドインのサンプルっぽいものがあった。\nアドインとは？ また未調査。何ができるのかを中心に調べたい。\n参考にしたサイトとか プロプライエタリバイナリについて alopezrivera/OneNoteExporter: Export your OneNote note collection to Obsidian, Logseq, Org Mode or any other plain text note-taking app!\nhttps://github.com/alopezrivera/OneNoteExporter (2025年7月30日) Insert or Extract Images from OneNote .one File Programmatically using C#\nhttps://gist.github.com/aspose-com-gists/12bbcc53310dce4971854eae512f54e8 (2025年7月30日) アドインの参考になりそうなもの stevencohn/OneMore: A OneNote add-in with simple, yet powerful and useful features\nhttps://github.com/stevencohn/OneMore (2025年7月30日) フリースペース OneNoteDev\nhttps://github.com/onenotedev (2025年7月30日) OneNoteDev/WebClipper: The OneNote Web Clipper extension\nhttps://github.com/OneNoteDev/WebClipper (2025年7月30日) xorg - How can I tell if an application is using XWayland? - Ask Ubuntu\nhttps://askubuntu.com/questions/1393618/how-can-i-tell-if-an-application-is-using-xwayland (2025年8月2日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/onenote/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　OneNoteの代替を作りたいというところから出発したので、OneNote自体について調べる必要があると思ったため。\u003c/p\u003e\n\u003ch2 id=\"私のonenoteの利用例\"\u003e私のOneNoteの利用例\u003c/h2\u003e\n\u003cp\u003e　OneNote は Office 365などに含まれていて、有償版とMS store からダウンロードできる無償版の2種類がある。無償版はしつこく MS 365 に課金するように催促される。\u003c/p\u003e\n\u003cp\u003e　windows 環境であればローカルにデスクトップ版をインストールし、今までのOffice 2021とか、Office 2007みたいに使うこともでき、OneNote も同じ感じである。クラウド機能もあるらしいが、私は大抵のクラウドサービスには否定的で明るくないので、使ったことはない。\u003c/p\u003e\n\u003cp\u003e　私がOneNoteを使っていたときは、半期ごとにノートを分けて、その中に授業ごとのセクションを作り、ページで細かい授業単位のデータ管理をするという感じであった。\u003c/p\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e9%9a%8e%e5%b1%a4%e6%a7%8b%e9%80%a0%e3%81%ae%e5%88%a9%e7%94%a8%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            階層構造の利用例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/OneNote%e5%88%a9%e7%94%a8%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            OneNote利用例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%a7%98%e3%80%85%e3%81%aa%e5%85%a5%e5%8a%9b%e3%82%84%e3%83%a1%e3%83%87%e3%82%a3%e3%82%a2%e3%82%92%e6%89%b1%e3%81%88%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            様々な入力やメディアを扱える例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"気になる機能\"\u003e気になる機能\u003c/h2\u003e\n\u003ch3 id=\"階層的なコンテンツ管理\"\u003e階層的なコンテンツ管理\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eノートブック\n\u003cul\u003e\n\u003cli\u003eセクション\n\u003cul\u003e\n\u003cli\u003eページ\u003c/li\u003e\n\u003cli\u003e\u0026hellip;\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e9%9a%8e%e5%b1%a4%e6%a7%8b%e9%80%a0%e3%81%ae%e5%88%a9%e7%94%a8%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            階層構造の利用例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"office-系列と似たような書式フォーマットや操作\"\u003eOffice 系列と似たような書式フォーマットや操作\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b1.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b2.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b3.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b4.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b5.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b6.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%9b%b8%e5%bc%8f%e6%93%8d%e4%bd%9c/UI%e3%81%ae%e4%be%8b7.png#center\"\n         alt=\"UIの例\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"インク機能のインターフェイス全体表示のとき\"\u003eインク機能のインターフェイス（全体表示のとき）\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e3%82%a4%e3%83%b3%e3%82%af%e6%a9%9f%e8%83%bd%e3%81%ae%e3%82%a4%e3%83%b3%e3%82%bf%e3%83%bc%e3%83%95%e3%82%a7%e3%82%a4%e3%82%b9-%e5%85%a8%e4%bd%93%e8%a1%a8%e7%a4%ba%e3%81%ae%e6%99%82.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            インク機能のインターフェイス-全体表示の時\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"自由なオブジェクトの配置\"\u003e自由なオブジェクトの配置\u003c/h3\u003e\n\u003cp\u003e　以下は、ある授業のレポートでネットワークの設定や構成について、与えられた課題にどう取り組んだのか説明する必要があった時の例である。画像をいろんなところに自由に配置し、インク機能を使って書き込み、一枚の絵として説明を完成させた。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e8%87%aa%e7%94%b1%e3%81%aa%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e9%85%8d%e7%bd%ae%e3%81%ae%e4%be%8b1.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            自由なオブジェクト配置の例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"書き込み可\"\u003e書き込み可\u003c/h3\u003e\n\u003cp\u003e　今回はPDF資料の上に、インク機能で書き込む例をいかに示す。このようにして自由にいろんなものを重ね合わせて扱うことができる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e3%82%a4%e3%83%b3%e3%82%af%e3%81%a8%e7%94%bb%e5%83%8f-%e6%9b%b8%e3%81%8d%e8%be%bc%e3%82%81%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            インクと画像-書き込める例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"マルチメディアサポート\"\u003eマルチメディアサポート\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eペンタブレット\u003c/li\u003e\n\u003cli\u003e画像、動画、テキスト\u003c/li\u003e\n\u003cli\u003eバイナリファイル添付\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%a7%98%e3%80%85%e3%81%aa%e5%85%a5%e5%8a%9b%e3%82%84%e3%83%a1%e3%83%87%e3%82%a3%e3%82%a2%e3%82%92%e6%89%b1%e3%81%88%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            様々な入力やメディアを扱える例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ストローク消しゴム\"\u003eストローク消しゴム\u003c/h3\u003e\n\u003cp\u003e　ink 機能では、ただ部分的にペイントソフトと同じように線とか描いたものを消せるだけじゃなくて、ストローク単位で一気に消したりできるのは、正直大きい。\u003c/p\u003e","title":"Onenote自体について（調査）"},{"content":"この記事を作った動機 Apple の古いキーボードをきれいにする 分解編 Part 1とApple の古いキーボードをきれいにする 分解編 Part 2の続き。この記事では基板周りの以外の分解について記事を作る。\n分解編 プラスチックと金属部分を固定しているねじをとる ブランクキーも取る 局所的に使われているねじの違い モスバーガーみたいなロゴ 分離するときにでてくるスプリング スプリングだけでなくLEDもついてくる 三層構造が分離した様子 失敗について 金属部分とプラスチック部分をつなぎとめるねじをとるときに、失敗したことも記録する。\nなめてしまったねじ 完全に外せなくなったものはドリルで取り除く 完全には取り除かず放置 なめてしまったねじとそうでないものの比較 取り外せたなめてしまったねじ再利用しない 次の内容 Apple の古いキーボードをきれいにする 清掃編 参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble2/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble/\"\u003eApple の古いキーボードをきれいにする 分解編 Part 1\u003c/a\u003eと\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble1/\"\u003eApple の古いキーボードをきれいにする 分解編 Part 2\u003c/a\u003eの続き。この記事では基板周りの以外の分解について記事を作る。\u003c/p\u003e\n\u003ch2 id=\"分解編\"\u003e分解編\u003c/h2\u003e\n\u003ch3 id=\"プラスチックと金属部分を固定しているねじをとる\"\u003eプラスチックと金属部分を固定しているねじをとる\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e6%8e%a5%e7%82%b9%e5%81%b4%e3%81%ae%e5%85%a8%e4%bd%93%e3%81%ae%e6%a7%98%e5%ad%90.jpg#center\"\n         alt=\"キーボード接点側の全体の様子\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"ブランクキーも取る\"\u003eブランクキーも取る\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc%ef%bc%9f/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc1.jpg#center\"\n         alt=\"モスバーガー1\"/\u003e \n\u003c/figure\u003e\n\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e7%89%b9%e6%ae%8a%e3%81%aa%e3%83%96%e3%83%a9%e3%83%b3%e3%82%af%e3%82%ad%e3%83%bc.jpg alt=特殊なブランクキー/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e7%89%b9%e6%ae%8a%e3%81%aa%e3%83%96%e3%83%a9%e3%83%b3%e3%82%af%e3%82%ad%e3%83%bc%e8%a3%8f.jpg alt=特殊なブランクキー裏/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"局所的に使われているねじの違い\"\u003e局所的に使われているねじの違い\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%81%ad%e3%81%98%e3%81%ae%e9%81%95%e3%81%84%e3%82%92%e8%a6%96%e8%a6%9a%e5%8c%96%e3%81%97%e3%81%9f%e3%82%82%e3%81%ae.jpg#center\"\n         alt=\"ねじの違いを視覚化したもの\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%81%ad%e3%81%98%e3%81%ae%e9%81%95%e3%81%84/%e7%95%b0%e3%81%aa%e3%82%8b%e3%81%ad%e3%81%98%e3%81%9f%e3%81%a1.jpg#center\"\n         alt=\"異なるねじたち\"/\u003e \n\u003c/figure\u003e\n\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%81%ad%e3%81%98%e3%81%ae%e9%81%95%e3%81%84/%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%97%e3%81%ae%e6%96%9c%e3%82%81%e3%81%8b%e3%82%89.jpg alt=クロースアップの斜めから/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%81%ad%e3%81%98%e3%81%ae%e9%81%95%e3%81%84/%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%97%e3%81%ae%e6%a8%aa%e3%81%8b%e3%82%89.jpg alt=クロースアップの横から/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%81%ad%e3%81%98%e3%81%ae%e9%81%95%e3%81%84/%e3%82%af%e3%83%ad%e3%83%bc%e3%82%b9%e3%82%a2%e3%83%83%e3%83%97%e3%81%ae%e4%b8%8a%e3%81%8b%e3%82%89.jpg alt=クロースアップの上から/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"モスバーガーみたいなロゴ\"\u003eモスバーガーみたいなロゴ\u003c/h3\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc%ef%bc%9f/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc.jpg alt=モスバーガー/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc%ef%bc%9f/%e3%83%a2%e3%82%b9%e3%83%90%e3%83%bc%e3%82%ac%e3%83%bc1.jpg alt=モスバーガー1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch3 id=\"分離するときにでてくるスプリング\"\u003e分離するときにでてくるスプリング\u003c/h3\u003e\n\u003cp\u003e\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%b9%e3%83%97%e3%83%aa%e3%83%b3%e3%82%b02.jpg alt=キーボードスプリング2/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%b9%e3%83%97%e3%83%aa%e3%83%b3%e3%82%b0.jpg alt=キーボードスプリング/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 220px;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%b9%e3%83%97%e3%83%aa%e3%83%b3%e3%82%b01.jpg alt=キーボードスプリング1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e5%88%86%e8%a7%a3%e9%80%94%e4%b8%ad/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%82%b9%e3%83%97%e3%83%aa%e3%83%b3%e3%82%b0%e3%81%ae%e9%9b%86%e5%90%88%e4%bd%93.jpg#center\"\n         alt=\"キーボードスプリングの集合体\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 分解編 Part 3"},{"content":"この記事を作った動機 2025/10/2 から、2025/10/9 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 (フロントエンド) TODOs TODOs 2025/10/9 になる間やる項目たち。やりきれなかった分は次に持ち越し。\n主な項目 ノートブック作成機能のバグチェックと修正 ノートブック、ページ関連における作成、削除、コピー名前の変更があった時、selector の情報やページviewを更新するようにする ページ作成機能の実装 フロントエンド バックエンド 新しい階層構造を指定できるようにする linux だけでなく windows 環境において、再帰的にフォルダを作成できるようにする。 ノートブック削除機能の実装 フロントエンド バックエンド ページ削除機能の実装 フロントエンド バックエンド markdown における編集機能、データセーブ（更新）の実装 フロントエンド (buggy) バックエンド Selector に未保存の表示を行う 別のページを開いても未保存のデータのバッファが管理されるようにする 内部構造を説明する図を作る フロントエンド バックエンド free ページの実装 フロントエンド バックエンド 他の事項 File API 周りの実装 マルチメディアの対応 messagebox の実装 やったことの詳細 ページ作成機能の実装 フォームを実装した。 とりあえずフロントエンド周りのネットワーク関連も実装して、あとはバックエンドのみ。 バックエンド、フロントエンド両方とも、とりあえず動くところまでできた。 ノートブック削除機能の実装 フォームを実装した。 とりあえずフロントエンド周りのネットワーク関連も実装して、あとはバックエンドのみ。 バックエンド、フロントエンド両方とも、とりあえず動くところまでできた。 ページ削除機能の実装 フォームを実装した。 とりあえずフロントエンド周りのネットワーク関連も実装して、あとはバックエンドのみ。 バックエンド、フロントエンド両方とも、とりあえず動くところまでできた。 編集機能、データセーブ（更新）の実装 全体 編集機能は、各ページで独自実装するようにした。 ToggleToolsBar に edit 項目を追加し、各ページの独自実装の機能を呼び出せるようにした。 page.tsx にて、新しいページを開いたときは、ToggleToolsBar の edit は新しいページが新たにツールを登録するために toggleable のクリーンアップだけするようにした。 -\u0026gt; 不具合の温床になっているっぽかったので、toggleable を設定したコンポーネントが自分で、コンポーネントが消されるときに toggleable を外すようにした。 データサーバー側は、単純にフロントエンドが送りつけた文字列をセーブデータとして扱う簡易的な仕様にすることにした。一応最低限のメタデータが存在するかはチェックするが、データ本体の整合性に関しては、フロントエンドに責任があることと現状ではしている。 とりあえず、markdown 形式のページについては動作するところまでupdatePageコマンドを実装し終えた。ただ、freeページに代表される、json 形式のページも実装はあるがまだ動くかテストできるほどフロントエンドが完成していないため、それについてはあとからテストする必要がある。 markdown ページ preview splitView editorView を選択できるようにした。 取得した markdown データは直接扱わず、markdownBuffer という状態変数によって中間的に管理することで、編集時に変更が反映できる仕組みにした。 highlight.js を使って、マークダウンをハイライトしようとした。 とりあえず、ctrl + S を押したり、セーブボタンを押せば、本当にページが保存されるところまではできた。 内部構造を説明する図を作る とりあえずバックエンドは、現状の範囲で書き出した。 ページの基本情報を表示 作成当時 ページに付いているタグやファイルなどを管理するUIを作った。まだボタンがあるだけで、ファイルのプレビューを開いたり、タグの追加や削除、タグに付随するページをリスティングする機能は付いていないが、一応形は作ってみた。 変更点1 UUID の代わりに、ページの作成日時と更新日時を表示するようにしてみた。 ページのメタデータ情報を追加 作成日と作成時を記録するようにした。\n古い形式 ++++ { \u0026#34;files\u0026#34;:[\u0026#34;なんかよくわかんない絵ジト目口開き3.png\u0026#34;], \u0026#34;tags\u0026#34;:[], \u0026#34;UUID\u0026#34;:\u0026#34;6428f4c7-7622-40b9-a6bc-f895b3f9ada8\u0026#34; } ++++ 新しい形式 ++++ { \u0026#34;files\u0026#34;:[\u0026#34;なんかよくわかんない絵ジト目口開き3.png\u0026#34;], \u0026#34;tags\u0026#34;:[], \u0026#34;createDate\u0026#34;: \u0026#34;2025/10/6\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/10/6\u0026#34;, \u0026#34;UUID\u0026#34;:\u0026#34;6428f4c7-7622-40b9-a6bc-f895b3f9ada8\u0026#34; } ++++ バックエンドのヘルパー関数を追加 特定のノートブックのメタデータを更新するための専用の関数を作った。主に以下のことを確認した後に、データを更新する。\nメタデータ自体が存在しているか バックアップは作成できたか メタデータは更新できたか # arg: # notebookName : notebook name # notebookMatadata : entire updated notebook metadata # return value # OK : False # Error : True will be returned when there are no notebooks or other type error is occured. def updateNotebookMatadata(notebookName:str,notebookMatadata:dict): notebookMatadata[\u0026#39;updateDate\u0026#39;] = timeString() notebookStoreRoot = loadSettings.settings[\u0026#34;NotebookRootFolder\u0026#34;][0] notebookMetadataPath = notebookStoreRoot + \u0026#34;/\u0026#34; + notebookName + \u0026#34;/metadata.json\u0026#34; print(\u0026#34;updateNotebookMatadata info: \u0026#34;) print(notebookMatadata) print(notebookName) print(notebookMetadataPath) if(not os.path.exists(notebookMetadataPath)): print(\u0026#34;updateNotebookMatadata ERROR: the metadata file does not exist.\u0026#34;) return True # https://stackoverflow.com/questions/123198/how-do-i-copy-a-file # update metadata try: # create metadata backup shutil.copyfile(notebookMetadataPath,notebookMetadataPath + \u0026#34;.backup\u0026#34;) with open(notebookMetadataPath,\u0026#34;wt\u0026#34;) as metadata: metadata.write(json.dumps(notebookMatadata)) pass except: print(\u0026#34;updateNotebookMatadata ERROR: Unable to create metadata backupfile or to update metadata.json of the notebook.\u0026#34;) return True return False バックエンドで一定期間ごとにタスクを実行できるように変更 multiprocessing と asyncio の組み合わせで、ただフロントエンドからの websocket の接続ややり取りを待ち受けるだけでなく、一定時間ごとに、タスクを実行できるようにした。\n例えば、特定のノートブックのメタデータから、ページの参照が一定期間削除されたままになっているページを完全に削除するタスクなどが考えられる。\nmain.py # main server scirpt # serve dataserver function with websocket. import asyncio import multiprocessing # from modules.reqestParser import parser from websockets.asyncio.server import serve from helper import loadSettings from helper.netwrok import receiveLoop import tasks import controller async def mainLoop(websocket): await receiveLoop(websocket,controller.controller) async def dataserver(): async with serve(mainLoop, loadSettings.settings[\u0026#34;ip\u0026#34;], loadSettings.settings[\u0026#34;port\u0026#34;]) as server: await server.serve_forever() def dataserverThread(): asyncio.run(dataserver()) def serviceThread(): asyncio.run(tasks.taskController(loadSettings.settings[\u0026#34;taskInterval\u0026#34;])) if __name__ == \u0026#34;__main__\u0026#34;: multiprocessing.Process(target=dataserverThread).start() multiprocessing.Process(target=serviceThread).start() バックエンドにおいてエラーレスポンスを返すためのヘルパー関数を実装 直接エラーレスポンスを返すコードをいちいち書いていると冗長になり、ミスが増えることがわかったので、共通で使える関数errorResponseを用意してみた。\n# arg: # websocket : the connection to the frontend via websocket # request : the frontend reqiuest entire JSON data # errorMessage : an error message to show in the stdout and response to the frontend # variablesList : an error related vars list to show in the stdout and response to the frontend # return value # OK : None # Error : Error state does not exist. async def errorResponse(websocket,request:dict,errorMessage:str,variablesList:list): print(\u0026#34;{} ERROR: {}\u0026#34;.format(request[\u0026#34;command\u0026#34;],errorMessage)) variableState = {} print(\u0026#34;{} ERROR: variable state --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) for aVar in variablesList: # print variable name and data # https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string # f\u0026#39;{aaa=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] varName = f\u0026#39;{aVar=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] print(\u0026#34;{}:\\n{}\\n\u0026#34;.format(varName,aVar)) variableState[varName] = str(aVar) print(\u0026#34;{} ERROR: variable state end --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) responseString = json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;error\u0026#34;, \u0026#34;errorMessage\u0026#34; : errorMessage, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : request[\u0026#34;command\u0026#34;], \u0026#34;data\u0026#34; : variableState }) await websocket.send(responseString) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) 躓いたこと 状態変数 と ReactElement 条件判定で挙動を変えたい UI (pageTypeList) があり、部分的に変数として切り出していたところ、適切にその UI 自体を更新しないと、正しく他の部分と提携して動作しないことがわかった。\nどうも、pageTypeList を useEffect 内で生成したときに、onChange に設定したコールバック関数がコピーされていて、かつコールバック関数の中身にある 状態変数の値なども、参照ではなくコピーされていることで、newPageInfo の古い値が pageTypeList ごと更新してやらないと残り続けてしまうようである。\n問題のある状態 export function deletepage(){ // 何かしらのコード... // データサーバーから取得した情報が格納される状態変数 const [pageType,setPageType] = useState\u0026lt;pageType | null\u0026gt;(null) // 正しく更新されないデータ const [newPageInfo,setNewPageInfo] = useState({ \u0026#34;notebook\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;pagename\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;pageType\u0026#34;: \u0026#34;\u0026#34; }) // 何かしらのコード... // 切り出した UI が格納される変数 const [pageTypeList,setPageTypeList] = useState\u0026lt;ReactElement[]\u0026gt;() // 何かしらのコード... // newPageInfo 状態変数が変更されても更新されない useEffect(() =\u0026gt; { console.log(pageType) const optionStyle = \u0026#34;bg-gray-800 hover:bg-gray-700\u0026#34; const typeSelected = (event:ChangeEvent\u0026lt;HTMLSelectElement\u0026gt;) =\u0026gt; { console.log(\u0026#34;type selected\u0026#34;) console.log(newPageInfo) setNewPageInfo({ notebook: newPageInfo.notebook, // newPageInfo の pageType が更新されても、それ以外は古い情報が反映され続ける pagename: newPageInfo.pagename, // newPageInfo の pageType が更新されても、それ以外は古い情報が反映され続ける pageType: event.target.value }) } // こうしても駄目だった。 // const typeSelected = (event:ChangeEvent\u0026lt;HTMLSelectElement\u0026gt;) =\u0026gt; { // console.log(\u0026#34;type selected\u0026#34;) // console.log(newPageInfo) // setNewPageInfo({ // ...newPageInfo, //　newPageInfo の pageType が更新されても、それ以外は古い情報が反映され続ける // pageType: event.target.value // }) // } if(pageType == null){ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;NoValueExistError\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; \u0026lt;option className={optionStyle} value=\u0026#34;currently\u0026#34;\u0026gt;No value exist.\u0026lt;/option\u0026gt; \u0026lt;/select\u0026gt;]) }else if(pageType[\u0026#34;data\u0026#34;] == null){ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;NoValueExistError\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; \u0026lt;option className={optionStyle} value=\u0026#34;currently\u0026#34;\u0026gt;Currently, no value exist.\u0026lt;/option\u0026gt; \u0026lt;/select\u0026gt;]) }else{ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;ValueExist\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; {pageType.data.map((value,index) =\u0026gt; \u0026lt;option className={optionStyle} value={value} key={index}\u0026gt;{value}\u0026lt;/option\u0026gt;)} \u0026lt;/select\u0026gt;]) } },[pageType]) // newPageInfo 状態変数が変更されても更新されない // 何かしらのコード... // return 内部では、newPageInfo 状態変数の内容は最新の内容が参照され、問題が起こらなかった。逆に言えば、UI を個別に変数として切り分けるまで問題に気付かなかった。 return \u0026lt;OverlayWindow arg={args}\u0026gt; \u0026lt;div className=\u0026#34;m-[1rem] flex flex-col\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;item pagename flex\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label\u0026#34;\u0026gt;Name:\u0026lt;/div\u0026gt; \u0026lt;input className=\u0026#34;ml-[1rem] border-gray-700 soild border-[2px]\u0026#34; id=\u0026#34;newPageName\u0026#34; type=\u0026#34;text\u0026#34; onChange={(event:ChangeEvent\u0026lt;HTMLInputElement\u0026gt;) =\u0026gt; { setNewPageInfo({ ...newPageInfo, pagename:event.target.value}) }}\u0026gt;\u0026lt;/input\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;item pageType flex mt-[0.5rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label\u0026#34;\u0026gt;Type: \u0026lt;/div\u0026gt; {pageTypeList} \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;item flex flex-col mt-[0.7rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label mr-auto\u0026#34;\u0026gt;Location: \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;PathPreview border-l-4 border-l-gray-800 flex flex-col pl-[0.7rem] bg-gray-950\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;notebook flex p-[0.5rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;mr-auto\u0026#34;\u0026gt;Notebook: \u0026lt;/div\u0026gt; \u0026lt;div\u0026gt;{newPageInfo.notebook}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;page flex p-[0.5rem] pt-[0]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;mr-auto\u0026#34;\u0026gt;Page: \u0026lt;/div\u0026gt; \u0026lt;div\u0026gt;{newPageInfo.pagename}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className={submitButtonStyle}\u0026gt;Create New Page\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/OverlayWindow\u0026gt; } とりあえず動く状態 export function CreatePage(){ // 何かしらのコード... // データサーバーから取得した情報が格納される状態変数 const [pageType,setPageType] = useState\u0026lt;pageType | null\u0026gt;(null) // 正しく更新されないデータ const [newPageInfo,setNewPageInfo] = useState({ \u0026#34;notebook\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;pagename\u0026#34;: \u0026#34;\u0026#34;, \u0026#34;pageType\u0026#34;: \u0026#34;\u0026#34; }) // 何かしらのコード... // 切り出した UI が格納される変数 const [pageTypeList,setPageTypeList] = useState\u0026lt;ReactElement[]\u0026gt;() // 何かしらのコード... // newPageInfo 状態変数が変更されたら、useEffect がかかり newPageInfo 状態変数の最新の内容が反映される useEffect(() =\u0026gt; { console.log(pageType) const optionStyle = \u0026#34;bg-gray-800 hover:bg-gray-700\u0026#34; const typeSelected = (event:ChangeEvent\u0026lt;HTMLSelectElement\u0026gt;) =\u0026gt; { console.log(\u0026#34;type selected\u0026#34;) console.log(newPageInfo) setNewPageInfo({ notebook: newPageInfo.notebook, // newPageInfo の pageType が更新されると、他の値は最新の newPageInfo の内容になる pagename: newPageInfo.pagename, // newPageInfo の pageType が更新されると、他の値は最新の newPageInfo の内容になる pageType: event.target.value }) } // const typeSelected = (event:ChangeEvent\u0026lt;HTMLSelectElement\u0026gt;) =\u0026gt; { // console.log(\u0026#34;type selected\u0026#34;) // console.log(newPageInfo) // setNewPageInfo({ // ...newPageInfo, // newPageInfo の pageType が更新されると、他の値は最新の newPageInfo の内容になる // pageType: event.target.value // }) // } if(pageType == null){ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;NoValueExistError\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; \u0026lt;option className={optionStyle} value=\u0026#34;currently\u0026#34;\u0026gt;No value exist.\u0026lt;/option\u0026gt; \u0026lt;/select\u0026gt;]) }else if(pageType[\u0026#34;data\u0026#34;] == null){ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;NoValueExistError\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; \u0026lt;option className={optionStyle} value=\u0026#34;currently\u0026#34;\u0026gt;Currently, no value exist.\u0026lt;/option\u0026gt; \u0026lt;/select\u0026gt;]) }else{ setPageTypeList([ \u0026lt;select onChange={typeSelected} key=\u0026#34;ValueExist\u0026#34; className=\u0026#34;ml-auto border-[2px] border-gray-700 solid\u0026#34; name=\u0026#34;pageType\u0026#34; id=\u0026#34;pageType\u0026#34;\u0026gt; {pageType.data.map((value,index) =\u0026gt; \u0026lt;option className={optionStyle} value={value} key={index}\u0026gt;{value}\u0026lt;/option\u0026gt;)} \u0026lt;/select\u0026gt;]) } },[pageType,newPageInfo]) // newPageInfo 変更時に、pageTypeList ごと更新をかける // newPageInfo 状態変数が変更されたら、useEffect がかかり newPageInfo 状態変数の最新の内容が反映される // 何かしらのコード... // return 内部では、newPageInfo 状態変数の内容は最新の内容が参照され、問題が起こらなかった。逆に言えば、UI を個別に変数として切り分けるまで問題に気付かなかった。 return \u0026lt;OverlayWindow arg={args}\u0026gt; \u0026lt;div className=\u0026#34;m-[1rem] flex flex-col\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;item pagename flex\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label\u0026#34;\u0026gt;Name:\u0026lt;/div\u0026gt; \u0026lt;input className=\u0026#34;ml-[1rem] border-gray-700 soild border-[2px]\u0026#34; id=\u0026#34;newPageName\u0026#34; type=\u0026#34;text\u0026#34; onChange={(event:ChangeEvent\u0026lt;HTMLInputElement\u0026gt;) =\u0026gt; { setNewPageInfo({ ...newPageInfo, pagename:event.target.value}) }}\u0026gt;\u0026lt;/input\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;item pageType flex mt-[0.5rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label\u0026#34;\u0026gt;Type: \u0026lt;/div\u0026gt; {pageTypeList} \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;item flex flex-col mt-[0.7rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label mr-auto\u0026#34;\u0026gt;Location: \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;PathPreview border-l-4 border-l-gray-800 flex flex-col pl-[0.7rem] bg-gray-950\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;notebook flex p-[0.5rem]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;mr-auto\u0026#34;\u0026gt;Notebook: \u0026lt;/div\u0026gt; \u0026lt;div\u0026gt;{newPageInfo.notebook}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;page flex p-[0.5rem] pt-[0]\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;mr-auto\u0026#34;\u0026gt;Page: \u0026lt;/div\u0026gt; \u0026lt;div\u0026gt;{newPageInfo.pagename}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className={submitButtonStyle}\u0026gt;Create New Page\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/OverlayWindow\u0026gt; } Python 再帰の限界 Python では、再帰できる回数に制限があるようで、それでコケるということがあった。\n問題のある状態 問題の再帰コード async def taskController(interval:int): if(interval == 0 or interval \u0026lt; 1): print(\u0026#34;taskController: The interval setting is too short.: {} sec\u0026#34;.format(interval)) print(\u0026#34;taskController: Please make it longer.\u0026#34;) interval = 1 for aJob in jobs: aJob() await asyncio.sleep(interval) await taskController(interval) 限界に達すると出るエラー Process Process-2: Traceback (most recent call last): File \u0026#34;/usr/lib/python3.13/multiprocessing/process.py\u0026#34;, line 313, in _bootstrap self.run() ~~~~~~~~^^ File \u0026#34;/usr/lib/python3.13/multiprocessing/process.py\u0026#34;, line 108, in run self._target(*self._args, **self._kwargs) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/main.py\u0026#34;, line 25, in serviceThread asyncio.run(tasks.taskController(loadSettings.settings[\u0026#34;taskInterval\u0026#34;])) ~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;/usr/lib/python3.13/asyncio/runners.py\u0026#34;, line 195, in run return runner.run(main) ~~~~~~~~~~^^^^^^ File \u0026#34;/usr/lib/python3.13/asyncio/runners.py\u0026#34;, line 118, in run return self._loop.run_until_complete(task) ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^ File \u0026#34;/usr/lib/python3.13/asyncio/base_events.py\u0026#34;, line 725, in run_until_complete return future.result() ~~~~~~~~~~~~~^^ File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/tasks.py\u0026#34;, line 24, in taskController await taskController(interval) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/tasks.py\u0026#34;, line 24, in taskController await taskController(interval) File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/tasks.py\u0026#34;, line 24, in taskController await taskController(interval) [Previous line repeated 975 more times] File \u0026#34;/home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/tasks.py\u0026#34;, line 23, in taskController await asyncio.sleep(interval) File \u0026#34;/usr/lib/python3.13/asyncio/tasks.py\u0026#34;, line 714, in sleep h = loop.call_later(delay, futures._set_result_unless_cancelled, future, result) File \u0026#34;/usr/lib/python3.13/asyncio/base_events.py\u0026#34;, line 799, in call_later timer = self.call_at(self.time() + delay, callback, *args, context=context) File \u0026#34;/usr/lib/python3.13/asyncio/base_events.py\u0026#34;, line 816, in call_at timer = events.TimerHandle(when, callback, args, self, context) File \u0026#34;/usr/lib/python3.13/asyncio/events.py\u0026#34;, line 114, in __init__ super().__init__(callback, args, loop, context) ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;/usr/lib/python3.13/asyncio/events.py\u0026#34;, line 45, in __init__ if self._loop.get_debug(): ~~~~~~~~~~~~~~~~~~~~^^ RecursionError: maximum recursion depth exceeded とりあえず解決とした状態 再帰しすぎるのが駄目ならということで、単純に無限ループするようにしてみた。\nasync def taskController(interval:int): while(True): if(interval == 0 or interval \u0026lt; 1): print(\u0026#34;taskController: The interval setting is too short.: {} sec\u0026#34;.format(interval)) print(\u0026#34;taskController: Please make it longer.\u0026#34;) interval = 1 for aJob in jobs: aJob() await asyncio.sleep(interval) os.system() と platform.system() helper の中にある deleteDataSafely 関数において、プラットフォームを識別するために、情報を取得する関数を間違えていた。紛らわしいので、一応記録する。\nos.system(command:str) 大雑把には、指定されたコマンドを実行する関数。\nplatform.system() 大まかにどの OS を動かしているか情報を得る。\n\u0026lsquo;Windows\u0026rsquo; \u0026lsquo;Linux\u0026rsquo; \u0026lsquo;Darwin\u0026rsquo; (mac os) \u0026lsquo;Java\u0026rsquo; \u0026rsquo;\u0026rsquo; \u0026lt;- 空文字 (識別不能のとき) Windows と文字コード 私は今回のプログラムを作っている中で当初は、Python 3 以降を使えば必然的に全部 UTF-8 でやり取りされるだろうと思い込んでいた。\nしかし、実際に linux 上で開発していたものを windows 上に持ち込むと、少なくとも anaconda 経由でインストールされた Python 3.13.2 では ShiftJIS がデフォルトになっていて、linux 上で開発していた時と文字コードが合わなくなる問題が起こった。\n結果として起こったことが、テストデータに日本語が含まれていると、UTF-8 で保存されたファイルを、ShiftJIS で読み込もうとして、以下のようなエラー(illegal multibyte sequence)となり、ページデータの内容を読み込めないということになった。ちなみにこの時、英語だけで構成されたデータは問題なく読み込めてしまう。\n---------------------- \u0026lt;\u0026lt;\u0026lt;{\u0026#34;command\u0026#34;:\u0026#34;pageInfo\u0026#34;,\u0026#34;UUID\u0026#34;:\u0026#34;25eca682-e30b-4562-8602-90891238c5a5\u0026#34;,\u0026#34;data\u0026#34;:{\u0026#34;pageID\u0026#34;:\u0026#34;test.json\u0026#34;,\u0026#34;notebook\u0026#34;:\u0026#34;test\u0026#34;}} connection handler failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\miniconda3\\Lib\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 376, in conn_handler await self.handler(connection) File \u0026#34;C:\\Users\\username\\work\\OneNoteAlternative\\firstPrototype\\backend\\dataServer\\main.py\u0026#34;, line 15, in mainLoop await receiveLoop(websocket,controller.controller) File \u0026#34;C:\\Users\\username\\work\\OneNoteAlternative\\firstPrototype\\backend\\dataServer\\helper\\netwrok.py\u0026#34;, line 24, in receiveLoop await callback(message,websocket) File \u0026#34;C:\\Users\\username\\work\\OneNoteAlternative\\firstPrototype\\backend\\dataServer\\controller.py\u0026#34;, line 54, in controller await commands[requestedCommand](request,websocket) File \u0026#34;C:\\Users\\username\\work\\OneNoteAlternative\\firstPrototype\\backend\\dataServer\\commands\\notebookAndPage\\pageInfo.py\u0026#34;, line 35, in pageInfo contentString = aPage.read() UnicodeDecodeError: \u0026#39;cp932\u0026#39; codec can\u0026#39;t decode byte 0x86 in position 430: illegal multibyte sequence 実際の対応 以下のように全部ファイルPython built-in の open関数でを操作する際、全部文字コードを ”UTF-8” で統一した。\nopen(pagePath,\u0026#34;wt\u0026#34;,encoding=\u0026#34;utf-8\u0026#34;) Python ドキュメント ChatGPT にただ質問を投げて受け取ったのを真に受けるのは良くないので、どうしてそうなるのか公式ドキュメントを漁ってみたところ、なぜ Windows 環境で動いている Python 3 において、ShiftJIS を使おうとするか、見つかった。\nBuilt-in Functions — Python 3.13.7 documentationには次のような記述がある。\nmode is an optional string that specifies the mode in which the file is opened. It defaults to \u0026lsquo;r\u0026rsquo; which means open for reading in text mode. Other common values are \u0026lsquo;w\u0026rsquo; for writing (truncating the file if it already exists), \u0026lsquo;x\u0026rsquo; for exclusive creation, and \u0026lsquo;a\u0026rsquo; for appending (which on some Unix systems, means that all writes append to the end of the file regardless of the current seek position). In text mode, if encoding is not specified the encoding used is platform-dependent: locale.getencoding() is called to get the current locale encoding. (For reading and writing raw bytes use binary mode and leave encoding unspecified.) The available modes are:\n特に重要そうだと思った部分は以下のところである。\nif encoding is not specified the encoding used is platform-dependent: locale.getencoding() is called to get the current locale encoding.\nそこで、実際に Windows 環境で、Anaconda 経由でインストールされた、Python 3.13.2 を使って、locale.getencoding() をしてみると以下のような結果が得られた。\n(base) PS C:\\Users\\username\\work\\OneNoteAlternative\u0026gt; python Python 3.13.2 | packaged by Anaconda, Inc. | (main, Feb 6 2025, 18:49:14) [MSC v.1929 64 bit (AMD64)] on win32 Type \u0026#34;help\u0026#34;, \u0026#34;copyright\u0026#34;, \u0026#34;credits\u0026#34; or \u0026#34;license\u0026#34; for more information. \u0026gt;\u0026gt;\u0026gt; import sys \u0026gt;\u0026gt;\u0026gt; sys.getdefaultencoding() \u0026#39;utf-8\u0026#39; \u0026gt;\u0026gt;\u0026gt; import locale \u0026gt;\u0026gt;\u0026gt; locale.getencoding() \u0026#39;cp932\u0026#39; \u0026gt;\u0026gt;\u0026gt; また、Linux 環境において、同じことを試すと以下のようになった。\n# python Python 3.13.5 | packaged by Anaconda, Inc. | (main, Jun 12 2025, 16:09:02) [GCC 11.2.0] on linux Type \u0026#34;help\u0026#34;, \u0026#34;copyright\u0026#34;, \u0026#34;credits\u0026#34; or \u0026#34;license\u0026#34; for more information. \u0026gt;\u0026gt;\u0026gt; import sys \u0026gt;\u0026gt;\u0026gt; sys.getdefaultencoding() \u0026#39;utf-8\u0026#39; \u0026gt;\u0026gt;\u0026gt; import locale \u0026gt;\u0026gt;\u0026gt; locale.getencoding() \u0026#39;UTF-8\u0026#39; \u0026gt;\u0026gt;\u0026gt; よって、少なくとも linux と Windows では、少なくとも私が持っている環境においては、open関数が参照しているlocale.getencoding()の返す値が異なり、異なる文字コード(ShiftJIS,UTF8)がファイルの読み書きにデフォルトで使われることが分かった。\nただ気になる点としては、sys.getdefaultencoding()においては、UTF8 が linux と Windows では返ってきており、なぜlocale.getencoding()と挙動が違うのかはまだ分かっていない。\n確かに OS 事情を考慮すると、DOS 時代あたりから ShiftJIS が Windows では採用されていて、広く使われた結果、いまUTF8が幅を利かせてきても、まだ互換性の呪いが残っているのかな？みたいに勝手なことを思ったりはした。それに対して linux 環境は普通のデスクトップ環境としてはあまり広く使われていなかったことから、UTF8 が早い段階で事実上の標準になっていたのかななんて思ったりもした。\nBuilt-in Functions — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/functions.html#open (2025年10月7日) locale — Internationalization services — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/locale.html#locale.getencoding (2025年10月7日) Pythonの日本語処理\nhttps://web.wakayama-u.ac.jp/~kazama/lab/python/i18n.html (2025年10月7日) ChatGPT の痕跡 Record を使う提案 Open as a page ShiftJIS の件 以下はwindows-と文字コードに関連のあるものである。\nOpen as a page 参考にしたサイトとか HTML contenteditable global attribute - HTML | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/contenteditable (2025年10月3日)\nVirtualKeyboard API - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/VirtualKeyboard_API (2025年10月3日)\nhighlight.js\nhttps://highlightjs.org/ (2025年10月3日)\nUsing highlight.js in React\nhttps://blog.robbie.digital/posts/highlight-js (2025年10月4日)\njavascript - contenteditable change events - Stack Overflow\nhttps://stackoverflow.com/questions/1391278/contenteditable-change-events (2025年10月4日)\njavascript - Why does React warn against an contentEditable component having children managed by React? - Stack Overflow\nhttps://stackoverflow.com/questions/49639144/why-does-react-warn-against-an-contenteditable-component-having-children-managed (2025年10月4日)\nuseEffect – React\nhttps://react.dev/reference/react/useEffect (2025年10月4日)\npython - How do I copy a file? - Stack Overflow\nhttps://stackoverflow.com/questions/123198/how-do-i-copy-a-file (2025年10月4日)\ncross platform - How can I find the current OS in Python? - Stack Overflow\nhttps://stackoverflow.com/questions/110362/how-can-i-find-the-current-os-in-python (2025年10月5日)\nos — Miscellaneous operating system interfaces — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/os.html#os.system (2025年10月5日)\nplatform — Access to underlying platform’s identifying data — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/platform.html#platform.system (2025年10月5日)\nhtml - Scroll only showing part of the element - Stack Overflow\nhttps://stackoverflow.com/questions/62514305/scroll-only-showing-part-of-the-element (2025年10月5日)\npython - Getting the name of a variable as a string - Stack Overflow\nhttps://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string (2025年10月6日)\nChatGPT\nhttps://chatgpt.com/ (2025年10月6日)\nBuilt-in Functions — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/functions.html#open (2025年10月7日)\nlocale — Internationalization services — Python 3.13.7 documentation\nhttps://docs.python.org/3/library/locale.html#locale.getencoding (2025年10月7日)\nPythonの日本語処理\nhttps://web.wakayama-u.ac.jp/~kazama/lab/python/i18n.html (2025年10月7日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-10-9/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/10/2 から、2025/10/9 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子-フロントエンド\"\u003e動作の様子 (フロントエンド)\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-10-9/%e8%a8%98%e9%8c%b22025-10-9.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/10/9 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"主な項目\"\u003e主な項目\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ノートブック作成機能のバグチェックと修正\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ノートブック、ページ関連における作成、削除、コピー名前の変更があった時、selector の情報やページviewを更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ページ作成機能の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e フロントエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 新しい階層構造を指定できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e linux だけでなく windows 環境において、再帰的にフォルダを作成できるようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ノートブック削除機能の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e フロントエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ページ削除機能の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e フロントエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e markdown における編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e フロントエンド (buggy)\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Selector に未保存の表示を行う\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 別のページを開いても未保存のデータのバッファが管理されるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図を作る\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"他の事項\"\u003e他の事項\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e File API 周りの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e マルチメディアの対応\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e messagebox の実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2025/10/9-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 これについては一旦なしとする。\n参考にしたサイトとか 今のところ特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/notion/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　これについては一旦なしとする。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今のところ特になし。\u003c/p\u003e","title":"Notionについて（調査、中止）"},{"content":"この記事を作った動機 Apple の古いキーボードをきれいにする 分解編 Part 3の続き。\n適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。ここではあくまで、簡易的に何をしたかということと、清掃後の様子を記録するにとどめる。具体的な清掃途中の過程については労力が大きすぎると判断し取りやめた。\n何をしたか？ キーキャップについて ほとんどのキーキャップは、一つ一つ手洗いするのは大変すぎるので、洗濯ネットに入れて洗濯機できれいにしてみた。特に破損するとか、洗濯機に不具合が起こるとかはなかった。あと一部の金属パーツがついたものについては、手洗いを行った。\nプラスチック外装などについて ほとんどの大きなプラスチック部品は、食器用洗剤と清掃用に専用に割り当てた食器用スポンジできれいにした。\n金属部品について 基本的にほとんど汚れていなかったので、無水エタノールでさっとふき取る程度とした。\n清掃後 キーキャップ プラスチック部品 全体像 次の内容 Apple の古いキーボードをきれいにする 終わり 参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/cleaning/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/disassemble2/\"\u003eApple の古いキーボードをきれいにする 分解編 Part 3\u003c/a\u003eの続き。\u003c/p\u003e\n\u003cp\u003e　適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。ここではあくまで、簡易的に何をしたかということと、清掃後の様子を記録するにとどめる。具体的な清掃途中の過程については労力が大きすぎると判断し取りやめた。\u003c/p\u003e\n\u003ch2 id=\"何をしたか\"\u003e何をしたか？\u003c/h2\u003e\n\u003ch3 id=\"キーキャップについて\"\u003eキーキャップについて\u003c/h3\u003e\n\u003cp\u003e　ほとんどのキーキャップは、一つ一つ手洗いするのは大変すぎるので、洗濯ネットに入れて洗濯機できれいにしてみた。特に破損するとか、洗濯機に不具合が起こるとかはなかった。あと一部の金属パーツがついたものについては、手洗いを行った。\u003c/p\u003e\n\u003ch3 id=\"プラスチック外装などについて\"\u003eプラスチック外装などについて\u003c/h3\u003e\n\u003cp\u003e　ほとんどの大きなプラスチック部品は、食器用洗剤と清掃用に専用に割り当てた食器用スポンジできれいにした。\u003c/p\u003e\n\u003ch3 id=\"金属部品について\"\u003e金属部品について\u003c/h3\u003e\n\u003cp\u003e　基本的にほとんど汚れていなかったので、無水エタノールでさっとふき取る程度とした。\u003c/p\u003e\n\u003ch2 id=\"清掃後\"\u003e清掃後\u003c/h2\u003e\n\u003ch3 id=\"キーキャップ\"\u003eキーキャップ\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97.jpg#center\"\n         alt=\"きれいになったキーキャップ\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e3%82%ad%e3%83%bc%e3%82%ad%e3%83%a3%e3%83%83%e3%83%97%e3%81%ae%e8%a3%8f.jpg#center\"\n         alt=\"きれいになったキーキャップの裏\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"プラスチック部品\"\u003eプラスチック部品\u003c/h3\u003e\n\u003cp\u003e\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;row;\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%90.jpg alt=きれいになった様子/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%901.jpg alt=きれいになった様子1/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e3%81%8d%e3%82%8c%e3%81%84%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%902.jpg#center\"\n         alt=\"きれいになった様子2\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"全体像\"\u003e全体像\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e5%85%a8%e5%ae%b9.jpg#center\"\n         alt=\"全容\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%83%91%e3%83%bc%e3%83%84%e3%81%94%e3%81%a8%e3%81%ae%e6%a7%98%e5%ad%90/%e5%85%a8%e5%ae%b9%e3%81%ae%e8%a3%8f.jpg#center\"\n         alt=\"全容の裏\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"次の内容\"\u003e次の内容\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/assemble/\"\u003eApple の古いキーボードをきれいにする 終わり\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 清掃編"},{"content":"この記事を作った動機 2025/10/9 から、2025/10/16 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 (フロントエンド) TODOs TODOs 2025/10/16 になる間やる項目たち。やりきれなかった分は次に持ち越し。\n主な項目 ページ作成機能の実装\nlinux だけでなく windows 環境において、再帰的にフォルダを作成できるようにする。 -\u0026gt; winpath = someFullAbsolutePath.replace(\u0026quot;//\u0026quot;,\u0026quot;/\u0026quot;).replace(\u0026quot;/\u0026quot;,\u0026quot;\\\u0026quot;) mkdir helper 関数の実装 編集機能、データセーブ（更新）の実装\nバッファーのデータストアを実装 別のページを開いても未保存のデータのバッファが管理されるようにする 内部構造を説明する図とかドキュメントを作る\nフロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page drawio で説明する図を作る とりあえず図を書くための準備をした。 他人が構造の理解に必要な分を記録できたか z-index について、どのような割り当てになっているか記録 バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 free ページの実装\nフロントエンド オブジェクト変形用に汎用的なコンポーネントを定義する。カーソルがオブジェクトをホバーしているときに出現するようにする。タッチでは、一回タップで出現。（サイズ変更、移動） 編集モードを各アイテムの要素の種類ごとに実装。汎用的には、クリックされた場合に編集モードに移行するようにする。タッチではダブルタッチで移行する。 バックエンド selector の改善\nノートブックはドロップダウンで選択させて、選択されたノートブックの階層構造やページリストを表示するようにする Selector に未保存の表示を行う OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\nFree ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\nバックエンド割り込みの実装\nバックエンドからフロントエンドの方向の割り込みをすでにドキュメントである程度定義したとおりに実装する。例えば、ページ内容に変更があったら通知したりする。 helper.commonとして、sendIntteruptを実装する。 割り込みが必要なコマンド群から、割り込みを送るようにする。また各コマンドのドキュメントに割り込みについて説明を書く。これに伴いテンプレートも割り込みについて記述するように、更新を行う。 フロントエンド側を割り込みを受けつけるように、改修していく。自動的に、フロントエンドが、バックエンドの割り込みによって連動して機能することを確認する。例えば、ページが作成されたとき、内容が変更されたとき、ノートブックが削除された時などに、データサーバが接続しているすべてのフロントエンドに、その通知が行く。 割り込みの仕組みについてのドキュメントの記述が見つからない場合、新たに定義し、それをもとに実装を進める。 エラーハンドリングにおける共通のerrorResponse関数を helper.common に実装したので、それをなるべく使うように全体のコードを更新していく。特にフロントエンドと関係のあるところで使う。\nエラーハンドリングにおいて、except の エラーのメッセージを握りつぶさない。\nexcept Exception as e: print(\u0026#34;[commandName] ERROR: error message\u0026#34;) print(e) 再接続機能が正しく機能しない場合を検証する 他の事項 File API 周りの実装 マルチメディアの対応 messagebox の実装 やったことの詳細 errorResponse 関数の仕様を変更 helper.commonのerrorResponse関数で、Python のExceptionをメッセージとして表示する仕様に変更した。ドキュメントもそれに応じて書き直し、引数について説明を追加した。なお、exception メッセージは強制ではなく、任意ではある。\n「エラーハンドリングにおいて、except の エラーのメッセージを握りつぶさない。」の TODO があったので、より一貫性のある実装としてまとめる意味合いもこの仕様変更にはある。\nasync def errorResponse(websocket,request:dict,errorMessage:str,variablesList:list,exception = None): print(\u0026#34;{} ERROR: {}\u0026#34;.format(request[\u0026#34;command\u0026#34;],errorMessage)) variableState = {} print(\u0026#34;{} ERROR: variable state --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) for aVar in variablesList: # print variable name and data # https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string # f\u0026#39;{aaa=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] varName = f\u0026#39;{aVar=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] print(\u0026#34;{}:\\n{}\\n\u0026#34;.format(varName,aVar)) variableState[varName] = str(aVar) print(\u0026#34;{} ERROR: variable state end --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) print(\u0026#34;{} ERROR: exception message --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) print(exception) print(\u0026#34;{} ERROR: exception message end --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) responseString = json.dumps({ \u0026#34;status\u0026#34; : \u0026#34;error\u0026#34;, \u0026#34;errorMessage\u0026#34; : errorMessage, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : request[\u0026#34;command\u0026#34;], \u0026#34;data\u0026#34; : variableState }) await websocket.send(responseString) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) mkdir 関数の実装 バックエンド内において、共通でフォルダ作成に使える、helper.commonのmkdir関数を実装した。ドキュメントも書いた。\n# arg: # absoluteFolderPath : full folder path to create # return value # OK : False # Error : True will be returned when failed to create folder. def mkdir(absoluteFolderPath:str): if(checkTheAbsolutePath(absoluteFolderPath)): print(\u0026#34;mkdir helper: This is malformed path\u0026#34;) print(absoluteFolderPath) return True if(platform.system() == \u0026#34;Windows\u0026#34;): winpath = absoluteFolderPath.replace(\u0026#34;//\u0026#34;,\u0026#34;/\u0026#34;).replace(\u0026#34;/\u0026#34;,\u0026#34;\\\\\u0026#34;) command = [\u0026#34;mkdir\u0026#34;,winpath] print(\u0026#34;winpath : \u0026#34; + winpath) else: command = [\u0026#34;mkdir -p \u0026#34; + absoluteFolderPath] result = subprocess.run(command,shell=True,capture_output=True) print(\u0026#34;folder path : \u0026#34; + absoluteFolderPath) if(result.returncode != 0): print(\u0026#34;mkdir helper: Unable to create the folder.\u0026#34;) print(str(result.stdout)) print(str(result.stderr)) return True return False checkTheAbsolutePath 関数の実装 helper.commonのcheckTheAbsolutePath関数を実装した。ドキュメントも書いた。この関数の実装の意図としては、いちいち各 helper 関数ごとにパスをチェックするのは面倒だったので、まとめて処理しようと思ったというのがある。具体的には、mkdir関数内で、deleteDataSafely関数内で行われていることと同じことをいちいち書くのは面倒だというのがあった。\n# arg: # absolutePath : file or folder path # return value # OK : False will be returned. # Error : True will be returned when the path is malformed. def checkTheAbsolutePath(absolutePath:str): # check the absoluteDataPath is something malisuous or not. if(absolutePath == \u0026#34;/\u0026#34; or absolutePath == \u0026#34;C:\\\\\u0026#34;): print(\u0026#34;checkTheAbsolutePath: Failed. Try to delete root directory.\u0026#34;) return True # check the absoluteDataPath is relative path or not. if(absolutePath[0] == \u0026#34;.\u0026#34;): print(\u0026#34;checkTheAbsolutePath: Failed. A relative path is specified. Use absolute path.\u0026#34;) return True # check the absoluteDataPath try to delete outside content of the notebooks or not. isNotebookPath = False for aNotebookStoreRoot in loadSettings.settings[\u0026#34;NotebookRootFolder\u0026#34;]: if(aNotebookStoreRoot in absolutePath): isNotebookPath = True break if(not isNotebookPath): print(\u0026#34;checkTheAbsolutePath: Failed. The absoluteDataPath is outside of the notebook store.\u0026#34;) return True return False errorResponse 関数の仕様を変更 変数名と変数の内容を表示するという仕様は、現状ではすぐには成り立たせるのが難しいことが分かったため、変数の内容だけ表示するように変更した。\n具体的な問題としては、引数としてリストで渡している変数の名前を以下の実装で正しく取得できないことが分かったというのがある。この実装では、for ループで一時的に内容を読みだすために使っているaVarの変数の名前が、引数として渡した変数の名前として現れてしまう。\n... variableState = {} print(\u0026#34;{} ERROR: variable state --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) for aVar in variablesList: # print variable name and data # https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string # f\u0026#39;{aaa=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] varName = f\u0026#39;{aVar=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] print(\u0026#34;{}:\\n{}\\n\u0026#34;.format(varName,aVar)) variableState[varName] = str(aVar) ... 今回は、シンプルにする方向性で修正を考え、結果として変数名は表示せずに、変数の内容だけ表示し、変数の内容をリスト形式にまとめてフロントエンドに送るようにした。\n... variableState = [] print(\u0026#34;{} ERROR: variable state --------------------------\u0026#34;.format(request[\u0026#34;command\u0026#34;])) for aVar in variablesList: # print variable name and data # https://stackoverflow.com/questions/18425225/getting-the-name-of-a-variable-as-a-string # f\u0026#39;{aaa=}\u0026#39;.split(\u0026#34;=\u0026#34;)[0] print(\u0026#34;{}\\n\u0026#34;.format(aVar)) variableState.append(str(aVar)) ... selector の実装を変更 全部のノートブックの情報を表示するのではなく、選択されたノートブックに分だけの表示になるように変更した。 free ページの実装を進めた free ページの基本的なデータ読み込みから、セーブ、終了までのフローができた。ちなみに undo、redo についてはまだ free ページにおいては実装する気がない。\nバックエンドからデータを取得し、free ページが読み込まれる。この時 useFreePageItemsStore の items 配列にデータが追加されていく。 useFreePageItemsStore を経由して、テキストを編集した、新たなアイテムを追加した、アイテムを消したなどの変更があると、useFreePageItemStoreEffect により、自動的に updatePage コマンドを使って内容をセーブする。 終了時には、useFreePageItemsStore の items の内容が初期化されて、次の表示のために準備される。 編集機能として何が欲しいか書き出してみた。\nadd item remove item resize item move item range selection drop item useFreePageItemStoreEffect を廃止した\nuseFreePageItemStoreEffect として hooks をまとめていると、zustand の挙動が怪しくなり、ReactのHooksに準拠していないというエラーになったので、free ページの main.tsx にとりあえずその中身は移動しておくことにした。\n右クリック menu の実装\n右クリックしたときのメニューを部分的に実装した。 messageBox 向けに画像を作った これについては、後からいくらでもできるということで、そこまで深く考えて作っておらずとりあえず機能する程度に仕上げた。\nok error warning info messageBox を実際に動くようにした バッファーのデータストアを実装 保存されていないページのデータを全体で管理するためのストアを作り、型定義をした。\n// TODO: create buffer store for each page // TODO: make all pages use the buffer store to prevent from losing the unsaved data. // TODO: if there are unsaved buffers, ask the user to save or throw away the data before the frontend is closed. // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Date // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Temporal export type AnUnsavedBuffer = { notebookName : string, pageID : string, pageType : string, UUID : string, // to identify each buffers. timestamp : Date, bufferContentString : string, } // NOTE: normally single page will add single buffer and update constantly if there are any modification. export type unsavedBuffers = { buffers : AnUnsavedBuffer[], addBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, removeBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, updateBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, // not to create buffer, to update exist buffer getBuffers : (pageID:string) =\u0026gt; AnUnsavedBuffer[], getUnsavedPageList : () =\u0026gt; string[], // for selector compornent. } export const useUnsavedBuffersStore = create\u0026lt;unsavedBuffers\u0026gt;((set,get) =\u0026gt; ({ buffers: [], addBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ // when the buffer has already existed, abort the update if(aBuffer.UUID == unsavedBuffer.UUID) return newBuffer.push(aBuffer) } newBuffer.push(unsavedBuffer) set({buffers:newBuffer}) }, removeBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ if(aBuffer.UUID == unsavedBuffer.UUID) continue newBuffer.push(aBuffer) } newBuffer.push(unsavedBuffer) set({buffers:newBuffer}) }, getBuffers: (pageID:string) =\u0026gt; { const allBuffer = get().buffers const buffers = [] for(const aBuffer of allBuffer){ if(aBuffer.pageID == pageID) buffers.push(aBuffer) } return buffers }, updateBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ // update if(aBuffer.UUID == unsavedBuffer.UUID) { // make sure the timestamp is the time of the last modify. unsavedBuffer.timestamp = new Date() newBuffer.push(unsavedBuffer) continue } newBuffer.push(aBuffer) } newBuffer.push(unsavedBuffer) set({buffers:newBuffer}) }, getUnsavedPageList: () =\u0026gt; { const buffers = get().buffers const pageIDlist:string[] = [] for(const aBuffer of buffers){ let find = false for(const pageIDname of pageIDlist){ if(pageIDname == aBuffer.pageID){ find = true break } } if(find) continue pageIDlist.push(aBuffer.pageID) } return pageIDlist } })) フロントエンドの共通のUIの実装に関して、ドキュメントを書き始めた フロントエンドに存在している、共通のUIパーツは使い方をドキュメントとしてまとめておくことにした。現状では以下の項目について、記録をした。\nOverlayWindow toolsBar messageBox 以下は記録の例である。\n参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年10月9日) How can I set the default value for an HTML \u0026lt;select\u0026gt; element? - Stack Overflow\nhttps://stackoverflow.com/questions/3518002/how-can-i-set-the-default-value-for-an-html-select-element (2025年10月13日) MouseEvent - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/MouseEvent (2025年10月14日) MouseEvent: button property - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button (2025年10月14日) contextmenu - How to disable right-click context-menu in JavaScript - Stack Overflow\nhttps://stackoverflow.com/questions/381795/how-to-disable-right-click-context-menu-in-javascript (2025年10月14日) Adding Images, Fonts, and Files | Create React App\nhttps://create-react-app.dev/docs/adding-images-fonts-and-files/ (2025年10月16日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-10-16/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/10/9 から、2025/10/16 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子-フロントエンド\"\u003e動作の様子 (フロントエンド)\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-10-16/%e8%a8%98%e9%8c%b22025-10-16.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/10/16 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"主な項目\"\u003e主な項目\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ページ作成機能の実装\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e linux だけでなく windows 環境において、再帰的にフォルダを作成できるようにする。 -\u0026gt; winpath = someFullAbsolutePath.replace(\u0026quot;//\u0026quot;,\u0026quot;/\u0026quot;).replace(\u0026quot;/\u0026quot;,\u0026quot;\\\u0026quot;)\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003emkdir\u003c/code\u003e helper 関数の実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バッファーのデータストアを実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 別のページを開いても未保存のデータのバッファが管理されるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e drawio で説明する図を作る\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず図を書くための準備をした。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 他人が構造の理解に必要な分を記録できたか\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e z-index について、どのような割り当てになっているか記録\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンド(更新)\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 新たに追加した、task の仕組みについて、ドキュメントを整備する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\u003c/p\u003e","title":"2025/10/16-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 Google Keep については、あまり個人的には使ったことはないし、使いこなせてもいなかったが、機能的には魅力的なところが多かったので、調べてみることにした。正直全部を網羅的に調べるというより、気になるところを中心に書きだすといった感じにしたい。\nどう使ったことがあるか？ 私は、正直あまり深く使ったことはなく長くてもせいぜい2ヵ月程度であった。なんか記録してもメモが下へ下へと行ってしまっていたのと、分類機能をあまり使いこなせていなかったので、メモとっても屍になっていた。\nクラウド上で動いており、ローカルでは動作しないというところも致命的に不満で、正直あまり馴染まなかったというところかもしれない。ツール自体の出来はいいと思うところである。\n今わかること ノートとは？ Google Keep での一つの付箋みたいなコンテンツの単位だと思われる。 いろんな機能がある 画像を添付したり、いろんな方法で分類したり、いろんな機能がある。細かいことは次からそれぞれ分けて説明することにする。 画像は添付できる 逆に言えばそれ以外の動画とか、jsonやテキストファイルなどは全然添付できない。 分類機能 タグ機能 タグでコンテンツを分類し、後から検索しやすくすることが可能である。任意のタグが作成可能である。 ピン止めできる ノートをアーカイブにすると無効化され、アーカイブ内からピン止めしようとすると、アーカイブに戻される。\nnote内でのピン止め タグ内でのピン止めは有効 リマインダー内では無効 アーカイブにするとピン止めが外される アーカイブ機能 ピン止めとアーカイブ機能 ピン止めとアーカイブはタグ内で共存できるようである。 色で分類できる チェックリスト 簡易的なTODOリストがある。しかし、リマインダを設定したりしても、Google カレンダーなどにはTODOリストとしては出てこないようで、ほかの自社内サービスと提携して反映されているというわけではないようである。\nあとこのチェックリストは、ノートを全部をチェックリストしてしまうため、何か別のテキストなどを書き込んだりはできないようである。でも、ラベル（タグ）付けしたり、画像は添付できるようである。 マークダウンは認識しない でも箇条書きは自動で入力される。 書式を指定できる マークダウンは認識しないが、基本的な書式を指定できる。 ごみ箱 すぐ消えるのではなく、一定期間経過後に消えるという仕組みで、間違って消したということに関して緩衝する機能がある。 インク機能 インク機能がある。細かいことについては専用にインク機能として章を設けることにする。\nデータをエクスポート可能 Google Takeoutを使えば、JSONやPNGなどの形式としてノートをローカルに保存できるデータとして、エクスポートできるようである。細かいことはデータのエクスポートとして章を設けることにする。\nインク機能 手書き機能に対応していることが分かった。筆圧検知も有効であり、最低限色を付けたり太さを変えたりできるという感じである。ただ画像とかは添付できず、手書きし、その画像をノートの添付できるというだけである。\n手書きに対応している マウスやペンタブレットでの入力が可能であることを確認した。タッチでもできるようであるがそれは確認していない。 ink-テスト いろんなペン マウスで描写した際は一定の太さ、透明度で固定されている。基本的にどのペンも、ある程度自由に色や太さを選択できることが確認された。\n線の太さを筆圧検知するペン 線の透明度を筆圧検知するペン 蛍光ペン 消しゴム サンプル\nここでは、いろんなペンを利用したサンプルを置いておく。ペンタブでの筆圧検知も利用している。 さらに細かい色を指定できる いろんな色を選べる 範囲選択できる 背景を設定できる できないこと 画像やドキュメントなどを添付できない 何も添付できないので、書き込んだりもできない OneNoteのように四角などの基本図形を描写する支援機能はない RGBやHSVなどによる細かい色指定とかはできない できること ペンタブレットなどから筆圧検知可能(Win 11 24H2、chrome 138で確認) 手書きした内容をストローク単位で消去、選択が可能 ノート内の様子 画像と同じように表示される。 データのエクスポート 手続き データはすぐに得られるわけではなく、手続きが必要である。Google Takeoutを使う必要がある。 実際に出力されたデータの構成 zip 形式でダウンロードできたデータを展開したときの、ファイル、フォルダ構成のイメージは以下の通りである。特に深い階層構造とかはないようである。添付された画像、ノートごとに html と json がエクスポートされているのが分かる。\nなおすべてを示すと長すぎるので、同じような繰り返しについては、...と書いて省略した。\ntree /f フォルダー パスの一覧: ボリューム Windows ボリューム シリアル番号は です C:. │ takeout-20250801T033915Z-1-001.zip │ └─takeout-20250801T033915Z-1-001 └─Takeout └─Keep # 添付画像 1754012073708.537020305.png 1754012073711.34850429.png ... # ノートたち Cat_.html Cat_.json Game.html Game.json ... 出力されたノートデータの構造 JSON ここでは、出力された JSON データのうち、画像が添付されたノート、画像は添付されていないが、ラベルが付与されたノート、画像もラベルも添付されていないノートをそれぞれ提示してみることにする。添付が画像がなかったり、ラベルが設定されていなかったりする場合はその項目自体がなくなることが確認できる。\nWrite a blog post for my game with C lang.json { // 添付画像 エクスポートされた画像と一致する名前が書かれている。 \u0026#34;attachments\u0026#34;: [ { \u0026#34;filePath\u0026#34;: \u0026#34;1754012073708.537020305.png\u0026#34;, \u0026#34;mimetype\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;filePath\u0026#34;: \u0026#34;1754012073711.34850429.png\u0026#34;, \u0026#34;mimetype\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;filePath\u0026#34;: \u0026#34;1754012073714.920413482.png\u0026#34;, \u0026#34;mimetype\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;filePath\u0026#34;: \u0026#34;1754012073716.332646478.png\u0026#34;, \u0026#34;mimetype\u0026#34;: \u0026#34;image/png\u0026#34; }, { \u0026#34;filePath\u0026#34;: \u0026#34;1754012073720.484965236.png\u0026#34;, \u0026#34;mimetype\u0026#34;: \u0026#34;image/png\u0026#34; } ], // 設定された色の管理 \u0026#34;color\u0026#34;: \u0026#34;RED\u0026#34;, // ごみ箱に入っているか？ \u0026#34;isTrashed\u0026#34;: false, // ピン止めされているか？ \u0026#34;isPinned\u0026#34;: false, // アーカイブされているか？ \u0026#34;isArchived\u0026#34;: true, // テキストの内容 \u0026#34;textContent\u0026#34;: \u0026#34;#game\u0026#34;, // タイトル \u0026#34;title\u0026#34;: \u0026#34;Write a blog post for my game with C lang\u0026#34;, // 最終更新の日時？ \u0026#34;userEditedTimestampUsec\u0026#34;: 1754012125661000, // 作成日時 \u0026#34;createdTimestampUsec\u0026#34;: 1754012063904000, // 用途不明 \u0026#34;textContentHtml\u0026#34;: \u0026#34;\u0026lt;p dir=\\\u0026#34;ltr\\\u0026#34; style=\\\u0026#34;line-height:1.38;margin-top:0.0pt;margin-bottom:0.0pt;\\\u0026#34;\u0026gt;\u0026lt;span style=\\\u0026#34;font-size:7.2pt;font-family:\u0026#39;Google Sans\u0026#39;;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;\\\u0026#34;\u0026gt;#game\u0026lt;/span\u0026gt;\u0026lt;/p\u0026gt;\u0026#34;, // ラベル（タグ）の管理 \u0026#34;labels\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;game\u0026#34; } ] } yellow.json { \u0026#34;color\u0026#34;: \u0026#34;YELLOW\u0026#34;, \u0026#34;isTrashed\u0026#34;: false, \u0026#34;isPinned\u0026#34;: false, \u0026#34;isArchived\u0026#34;: false, \u0026#34;textContent\u0026#34;: \u0026#34;yellow \\n#color\u0026#34;, \u0026#34;title\u0026#34;: \u0026#34;yellow\u0026#34;, \u0026#34;userEditedTimestampUsec\u0026#34;: 1754014408905000, \u0026#34;createdTimestampUsec\u0026#34;: 1754011919771000, \u0026#34;textContentHtml\u0026#34;: \u0026#34;\u0026lt;p dir=\\\u0026#34;ltr\\\u0026#34; style=\\\u0026#34;line-height:1.38;margin-top:0.0pt;margin-bottom:0.0pt;\\\u0026#34;\u0026gt;\u0026lt;span style=\\\u0026#34;font-size:7.2pt;font-family:\u0026#39;Google Sans\u0026#39;;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;\\\u0026#34;\u0026gt;yellow\u0026amp;nbsp;\u0026lt;/span\u0026gt;\u0026lt;/p\u0026gt;\u0026lt;p dir=\\\u0026#34;ltr\\\u0026#34; style=\\\u0026#34;line-height:1.38;margin-top:0.0pt;margin-bottom:0.0pt;\\\u0026#34;\u0026gt;\u0026lt;span style=\\\u0026#34;font-size:7.2pt;font-family:\u0026#39;Google Sans\u0026#39;;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;\\\u0026#34;\u0026gt;#color\u0026lt;/span\u0026gt;\u0026lt;/p\u0026gt;\u0026#34;, \u0026#34;labels\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;color\u0026#34; } ] } Cat_.json { \u0026#34;color\u0026#34;: \u0026#34;ORANGE\u0026#34;, \u0026#34;isTrashed\u0026#34;: false, \u0026#34;isPinned\u0026#34;: false, \u0026#34;isArchived\u0026#34;: false, \u0026#34;textContent\u0026#34;: \u0026#34;cat is cute\u0026#34;, \u0026#34;title\u0026#34;: \u0026#34;Cat \u0026#34;, \u0026#34;userEditedTimestampUsec\u0026#34;: 1754013860001000, \u0026#34;createdTimestampUsec\u0026#34;: 1754011666302000, \u0026#34;textContentHtml\u0026#34;: \u0026#34;\u0026lt;p dir=\\\u0026#34;ltr\\\u0026#34; style=\\\u0026#34;line-height:1.38;margin-top:0.0pt;margin-bottom:0.0pt;\\\u0026#34;\u0026gt;\u0026lt;span style=\\\u0026#34;font-size:7.2pt;font-family:\u0026#39;Google Sans\u0026#39;;color:#000000;background-color:transparent;font-weight:400;font-style:normal;font-variant:normal;text-decoration:none;vertical-align:baseline;white-space:pre;white-space:pre-wrap;\\\u0026#34;\u0026gt;cat is cute\u0026lt;/span\u0026gt;\u0026lt;/p\u0026gt;\u0026#34; } HTML それぞれのノートに対して、JSON だけでなく HTML もエクスポートされていたので、それも確かめてみた。ブラウザで開いてみた感じ、JSON とは異なり、直接開いて見れるという感じである程度体裁やスタイルが整えてあるようである。ただ基本的に何か、Google Keep でエクスポートした内容をほかの自作のアプリケーションとかで読み込ませたいなどの場合は、ノート自体のデータとしては、JSONだけで充分かもしれない。\nWrite a blog post for my game with C lang.html \u0026lt;?xml version=\u0026#34;1.0\u0026#34; ?\u0026gt; \u0026lt;!DOCTYPE html PUBLIC \u0026#34;-//W3C//DTD XHTML 1.0 Strict//EN\u0026#34; \u0026#34;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\u0026#34;\u0026gt; \u0026lt;html xmlns=\u0026#34;http://www.w3.org/1999/xhtml\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta http-equiv=\u0026#34;Content-Type\u0026#34; content=\u0026#34;text/html; charset=UTF-8\u0026#34; /\u0026gt; \u0026lt;!-- タイトル --\u0026gt; \u0026lt;title\u0026gt;Write a blog post for my game with C lang\u0026lt;/title\u0026gt; \u0026lt;style type=\u0026#34;text/css\u0026#34;\u0026gt; /* ... 省略 ... */ \u0026lt;/style\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div class=\u0026#34;note RED\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;heading\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;meta-icons\u0026#34;\u0026gt; \u0026lt;span class=\u0026#34;archived\u0026#34; title=\u0026#34;Note archived\u0026#34;\u0026gt;\u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; Aug 1, 2025, 10:35:25\u0026amp;#8239;AM \u0026lt;/div\u0026gt; \u0026lt;!-- タイトル --\u0026gt; \u0026lt;div class=\u0026#34;title\u0026#34;\u0026gt;Write a blog post for my game with C lang\u0026lt;/div\u0026gt; \u0026lt;!-- テキスト --\u0026gt; \u0026lt;div class=\u0026#34;content\u0026#34;\u0026gt;#game\u0026lt;/div\u0026gt; \u0026lt;!-- ラベル（タグ） --\u0026gt; \u0026lt;div class=\u0026#34;chips\u0026#34;\u0026gt; \u0026lt;span class=\u0026#34;chip label\u0026#34;\u0026gt;\u0026lt;span class=\u0026#34;label-name\u0026#34;\u0026gt;game\u0026lt;/span\u0026gt; \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;!-- 添付画像 --\u0026gt; \u0026lt;div class=\u0026#34;attachments\u0026#34;\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li\u0026gt;\u0026lt;img alt=\u0026#34;\u0026#34; src=\u0026#34;1754012073708.537020305.png\u0026#34; /\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;img alt=\u0026#34;\u0026#34; src=\u0026#34;1754012073711.34850429.png\u0026#34; /\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;img alt=\u0026#34;\u0026#34; src=\u0026#34;1754012073714.920413482.png\u0026#34; /\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;img alt=\u0026#34;\u0026#34; src=\u0026#34;1754012073716.332646478.png\u0026#34; /\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;img alt=\u0026#34;\u0026#34; src=\u0026#34;1754012073720.484965236.png\u0026#34; /\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 気になったところ ブラウザのink API 少なくとも Google Chrome 138 においてペンタブの動作を確認できたが、他の Firefox や Chromium 系列の Edge などのブラウザがどこまで ink APIに対応しているのか不明。\n一応 MDN で調べると Ink API - Web APIs | MDN というページで一応存在を確認できた。なお Google Keep がこのAPIを使っているか不明である。\n現時点（2025年8月2日）においては試験段階の API であると記述されており、Google Chrome と、Microsoft Edge は対応していそうだったが、それ以外の Firefox や Safari では未対応であるとのこと。（もしかすると開発者機能のところで一応あるのかもしれないが。。。）なおほかの Opera や Electron などについてはそのサイトでは記述がない。調べてみるしかなさそうである。\n現時点でのこの記事のまとめ 真似したいと思った点 分類機能全般 JSON データ構造 一定時間たつと消去されるヒューマンエラーを考慮したごみ箱機能 タグ機能 不満点 ローカルで動かない webアプリとして作られており、オフライン動作は困難があると思われる。ローカルで Electron などで動作するという感じでもなく、オンライン前提のサービスであり、MS Office みたいにデスクトップ版があるという感じではない。\nせっかくクロスプラットフォームで、windows でも、Linux環境でも、依存せずに Webベースで動いているが、ローカルで動かず、アカウントに紐づけられてしか動作しないのは不満である。\nログインしないとそもそも使えない アカウントに紐づけられており、ログインしないとサービスそのものが動作しない。ログインしてない状態で使おうとすると、ゲストモードとかはなく、ログイン画面に遷移してしまう。\n単体としては物足りない なんか、OneNoteでいうページの単位の選べる情報整理やタスク管理テンプレートの一つとして存在しているみたいな感じだと、ありかなとは思う。ただ、分類機能はあるものの、いろんなことをごっちゃ混ぜにして使うと正直ノートが散乱してしまいそうである。\n思ったこと タスク管理機能のバリエーションの一部として、OneNoteのページ的な単位でのテンプレートの一つとして、組み込んだらいいかも。\n参考にしたサイトとか フリースペース Google Keep\nhttps://keep.google.com/#home (2025年8月1日) Google Takeout\nhttps://takeout.google.com/?pli=1 (2025年8月1日) 画像資料内のサイトとか Visual packet size calculator 窶� Daniil Baturin\nhttps://baturin.org/tools/encapcalc/ (2025年8月1日) ink API について Ink API - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Ink_API (2025年8月2日) Ink - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Ink (2025年8月2日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/googlekeep/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Google Keep については、あまり個人的には使ったことはないし、使いこなせてもいなかったが、機能的には魅力的なところが多かったので、調べてみることにした。正直全部を網羅的に調べるというより、気になるところを中心に書きだすといった感じにしたい。\u003c/p\u003e\n\u003ch2 id=\"どう使ったことがあるか\"\u003eどう使ったことがあるか？\u003c/h2\u003e\n\u003cp\u003e　私は、正直あまり深く使ったことはなく長くてもせいぜい2ヵ月程度であった。なんか記録してもメモが下へ下へと行ってしまっていたのと、分類機能をあまり使いこなせていなかったので、メモとっても屍になっていた。\u003c/p\u003e\n\u003cp\u003e　クラウド上で動いており、ローカルでは動作しないというところも致命的に不満で、正直あまり馴染まなかったというところかもしれない。ツール自体の出来はいいと思うところである。\u003c/p\u003e\n\u003ch2 id=\"今わかること\"\u003e今わかること\u003c/h2\u003e\n\u003ch3 id=\"ノートとは\"\u003eノートとは？\u003c/h3\u003e\n\u003cp\u003e　Google Keep での一つの付箋みたいなコンテンツの単位だと思われる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%8e%e3%83%bc%e3%83%88%e3%81%ae%e5%8d%98%e4%bd%8d.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"いろんな機能がある\"\u003eいろんな機能がある\u003c/h3\u003e\n\u003cp\u003e　画像を添付したり、いろんな方法で分類したり、いろんな機能がある。細かいことは次からそれぞれ分けて説明することにする。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%81%84%e3%82%8d%e3%82%93%e3%81%aa%e6%a9%9f%e8%83%bd%e3%81%8c%e3%81%82%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%81%84%e3%82%8d%e3%82%93%e3%81%aa%e6%a9%9f%e8%83%bd1.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"画像は添付できる\"\u003e画像は添付できる\u003c/h3\u003e\n\u003cp\u003e　逆に言えばそれ以外の動画とか、jsonやテキストファイルなどは全然添付できない。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e7%94%bb%e5%83%8f%e3%82%92%e6%b7%bb%e4%bb%98%e3%81%a7%e3%81%8d%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e7%94%bb%e5%83%8f%e4%bb%a5%e5%a4%96%e6%b7%bb%e4%bb%98%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"分類機能\"\u003e分類機能\u003c/h3\u003e\n\u003ch4 id=\"タグ機能\"\u003eタグ機能\u003c/h4\u003e\n\u003cp\u003e　タグでコンテンツを分類し、後から検索しやすくすることが可能である。任意のタグが作成可能である。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%82%bf%e3%82%b0%e6%a9%9f%e8%83%bd%e3%81%ae%e8%aa%ac%e6%98%8e1.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%82%bf%e3%82%b0%e6%a9%9f%e8%83%bd%e3%81%ae%e8%aa%ac%e6%98%8e.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"ピン止めできる\"\u003eピン止めできる\u003c/h4\u003e\n\u003cp\u003e　ノートをアーカイブにすると無効化され、アーカイブ内からピン止めしようとすると、アーカイブに戻される。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003enote内でのピン止め\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81%e3%81%a7%e3%81%8d%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003eタグ内でのピン止めは有効\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81%e3%81%af%e3%82%bf%e3%82%b0%e5%86%85%e3%81%a7%e3%81%af%e5%88%86%e9%a1%9e%e3%81%95%e3%82%8c%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003eリマインダー内では無効\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81%e3%81%af%e3%83%aa%e3%83%9e%e3%82%a4%e3%83%b3%e3%83%80%e3%83%bc%e5%86%85%e3%81%a7%e3%81%af%e7%84%a1%e5%8a%b9%e5%8c%96%e3%81%95%e3%82%8c%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003eアーカイブにするとピン止めが外される\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81%e3%81%af%e3%82%a2%e3%83%bc%e3%82%ab%e3%82%a4%e3%83%96%e3%81%ab%e3%81%99%e3%82%8b%e3%81%a8%e7%84%a1%e5%8a%b9%e5%8c%96%e3%81%95%e3%82%8c%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"アーカイブ機能\"\u003eアーカイブ機能\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%82%a2%e3%83%bc%e3%82%ab%e3%82%a4%e3%83%96%e6%a9%9f%e8%83%bd.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"ピン止めとアーカイブ機能\"\u003eピン止めとアーカイブ機能\u003c/h4\u003e\n\u003cp\u003e　ピン止めとアーカイブはタグ内で共存できるようである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81/%e3%83%94%e3%83%b3%e6%ad%a2%e3%82%81%e3%81%a8%e3%82%a2%e3%83%bc%e3%82%ab%e3%82%a4%e3%83%96%e3%81%ae%e5%85%b1%e5%ad%98.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"色で分類できる\"\u003e色で分類できる\u003c/h4\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/note%e3%83%9a%e3%83%bc%e3%82%b8.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e8%89%b2%e3%81%a7%e5%88%86%e9%a1%9e%e3%81%a7%e3%81%8d%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/%e8%89%b2%e3%81%a7%e5%88%86%e9%a1%9e%e3%81%a7%e3%81%8d%e3%82%8b%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"チェックリスト\"\u003eチェックリスト\u003c/h3\u003e\n\u003cp\u003e　簡易的なTODOリストがある。しかし、リマインダを設定したりしても、Google カレンダーなどにはTODOリストとしては出てこないようで、ほかの自社内サービスと提携して反映されているというわけではないようである。\u003c/p\u003e\n\u003cp\u003e　あとこのチェックリストは、ノートを全部をチェックリストしてしまうため、何か別のテキストなどを書き込んだりはできないようである。でも、ラベル（タグ）付けしたり、画像は添付できるようである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/checklist/checklist.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/checklist/checklist%e3%81%ab%e3%83%aa%e3%83%9e%e3%82%a4%e3%83%b3%e3%83%80%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%99%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/checklist/TODO%e3%81%a8%e3%81%af%e6%8f%90%e6%90%ba%e3%81%97%e3%81%a6%e3%81%84%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/GoogleKeep/checklist/%e7%94%bb%e5%83%8f%e3%81%af%e6%b7%bb%e4%bb%98%e3%81%a7%e3%81%8d%e3%82%8b.png#center\"\n         alt=\"GoogleKeep サンプル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"GoogleKeepについて（調査）"},{"content":"この記事を作った動機 Apple の古いキーボードをきれいにする 清掃編の続き。\n適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。一応、最後に締めの記事も書いておくことにした。たいしたことは書くつもりはないが、とりあえず簡単なきれいにしたキーボードの全容と感想を書こうとは思う。\nちなみに組み立て途中についてはめんどくさすぎたので、何も書かないことにした。感想でどんなミスがあったかとかは、書こうとは思う。\n組み立てたキーボードの全体像 感想 感想としては、テンキーのEnterキーの黄ばみとかはいまいち取れなかったが、全体的に使いたいと思えるほどにはとりあえずきれいになった。\nキーボード自体は、かなりしっかり作られており、20年物にしては、よく頑張っている方だと感じられる。今のところ動作しないキーは見つかっていない。USBでとりあえずつなげられるし、USBハブもついているので地味に便利ではあった。\n組み立てるに際しては、USBケーブルを元どうりにはんだ付けするのに苦戦して、何度も知恵の輪みたいに試しながらつけ外ししているうちに、データ線の一部のパターンを地味に損傷してしまったため、適当に修正したりしてた。\n清掃に関してはそこまで苦戦することはなかった。パーツを紛失することもなく、基本的には難なく分解するのとは逆順に組み立てることはできた。\n私としては、満足かなといったところ。まあただどうしても隙間にまたゴミがたまってしまうのはキーボードの宿命だと思うので、まあぼちぼちまたキーキャップを外して清掃するんだろうなとはなんとなく感じる。\n参考にしたサイトとか 今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/assemble/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hardware/keyboard/cleaningappleoldkeyboard/cleaning/\"\u003eApple の古いキーボードをきれいにする 清掃編\u003c/a\u003eの続き。\u003c/p\u003e\n\u003cp\u003e　適当にできる範囲で、キーボードの分解清掃の記録を残すだけ。一応、最後に締めの記事も書いておくことにした。たいしたことは書くつもりはないが、とりあえず簡単なきれいにしたキーボードの全容と感想を書こうとは思う。\u003c/p\u003e\n\u003cp\u003e　ちなみに組み立て途中についてはめんどくさすぎたので、何も書かないことにした。感想でどんなミスがあったかとかは、書こうとは思う。\u003c/p\u003e\n\u003ch2 id=\"組み立てたキーボードの全体像\"\u003e組み立てたキーボードの全体像\u003c/h2\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/cleaningAppleOldKeyboard/%e6%b8%85%e6%8e%83%e5%be%8c%e3%81%ae%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e5%ae%b9/%e3%82%ad%e3%83%bc%e3%83%9c%e3%83%bc%e3%83%89%e3%81%ae%e5%85%a8%e4%bd%93%e5%83%8f.jpg#center\"\n         alt=\"キーボードの全体像\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"感想\"\u003e感想\u003c/h2\u003e\n\u003cp\u003e　感想としては、テンキーのEnterキーの黄ばみとかはいまいち取れなかったが、全体的に使いたいと思えるほどにはとりあえずきれいになった。\u003c/p\u003e\n\u003cp\u003e　キーボード自体は、かなりしっかり作られており、20年物にしては、よく頑張っている方だと感じられる。今のところ動作しないキーは見つかっていない。USBでとりあえずつなげられるし、USBハブもついているので地味に便利ではあった。\u003c/p\u003e\n\u003cp\u003e　組み立てるに際しては、USBケーブルを元どうりにはんだ付けするのに苦戦して、何度も知恵の輪みたいに試しながらつけ外ししているうちに、データ線の一部のパターンを地味に損傷してしまったため、適当に修正したりしてた。\u003c/p\u003e\n\u003cp\u003e　清掃に関してはそこまで苦戦することはなかった。パーツを紛失することもなく、基本的には難なく分解するのとは逆順に組み立てることはできた。\u003c/p\u003e\n\u003cp\u003e　私としては、満足かなといったところ。まあただどうしても隙間にまたゴミがたまってしまうのはキーボードの宿命だと思うので、まあぼちぼちまたキーキャップを外して清掃するんだろうなとはなんとなく感じる。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は適当にねじ外したり、爪を外したりして適当に自分なりに分解清掃しただけで、特に下調べも何もせずにやったので、特になし。\u003c/p\u003e","title":"Apple の古いキーボードをきれいにする 終わり"},{"content":"この記事を作った動機 2025/10/16 から、2025/10/23 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 (フロントエンド) TODOs TODOs 2025/10/23 になる間やる項目たち。やりきれなかった分は次に持ち越し。\n主な項目 編集機能、データセーブ（更新）の実装\n別のページを開いても未保存のデータのバッファが管理されるように各ページタイプを実装する 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 free ページの実装\nフロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page オブジェクト変形用に汎用的なコンポーネントを定義する。カーソルがオブジェクトをホバーしているときに出現するようにする。タッチでは、一回タップで出現。（サイズ変更、移動） 移動について実装 リサイズ機能についての実装 右下について実装 (とりあえずこれだけにするかも) 下について実装 右について実装 左上について実装 （正しくitemを更新できないバグありで解消中） 左について実装 上について実装 左下について実装 右上について実装 編集モードを各アイテムの要素の種類ごとに実装。汎用的には、ダブルクリックされた場合に編集モードに移行するようにする。タッチではダブルタッチで移行する. フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 バックエンド selector の改善\nSelector に未保存の表示を行う OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\nFree ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\nとりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\nバックエンド割り込みの実装\nバックエンドからフロントエンドの方向の割り込みをすでにドキュメントである程度定義したとおりに実装する。例えば、ページ内容に変更があったら通知したりする。 helper.commonとして、sendIntteruptを実装する。 割り込みが必要なコマンド群から、割り込みを送るようにする。また各コマンドのドキュメントに割り込みについて説明を書く。これに伴いテンプレートも割り込みについて記述するように、更新を行う。 -\u0026gt; 割り込みについては、専用のドキュメントページを作り、そこに記述する フロントエンド側を割り込みを受けつけるように、改修していく。自動的に、フロントエンドが、バックエンドの割り込みによって連動して機能することを確認する。例えば、ページが作成されたとき、内容が変更されたとき、ノートブックが削除された時などに、データサーバが接続しているすべてのフロントエンドに、その通知が行く。各コンポーネントが、必要な割り込みイベントを、listen するような形をとる。 割り込みの仕組みについてのドキュメントの記述が見つからない場合、新たに定義し、それをもとに実装を進める。 ドキュメントに書いた割り込みが実際に機能するよう、各コマンドに割り込みを送るように実装していく。 再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる やったことの詳細 dataserver -\u0026gt; frontend 方向の割り込みを考えた とりあえずどういうやり取りをするか、ある程度データ構造を決めてみた。\n### dataserver to frontend #### note in the frontend code ``` // dataserver -\u0026gt; frontend // get an interrupt // // { // \u0026#34;componentName\u0026#34; : \u0026#34;Selector\u0026#34;, // \u0026#34;command\u0026#34; : \u0026#34;update\u0026#34;, // \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, // \u0026#34;data\u0026#34; : { } // } ``` #### server interrupt reqest(JSON) ```json { \u0026#34;componentName\u0026#34; : \u0026#34;componentName\u0026#34;, \u0026#34;interrupt\u0026#34; : \u0026#34;update\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : { } } ``` #### frontend response(JSON) ```json { \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;interrupt\u0026#34; : \u0026#34;update\u0026#34;, \u0026#34;componentName\u0026#34; : \u0026#34;componentName\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, \u0026#34;data\u0026#34; : { } } ``` sendInterrupt helper 関数を実装した とりあえずは、必要なキーがあることとを確認して、単にフロントエンドにデータを送信するようにした。フロントエンドから割り込みの結果も送るように現状定義はしているが、どうそれをバックエンド側で処理するかはまだ決めていない。現状の実装だと送りっぱなしの仕様になっている。\n# TODO: test and use this # TODO: write the document # arg: # websocket : the connection to the frontend via websocket # interrupt : content of the interrupt # return value # OK : None # Error : Error state does not exist. async def sendInterrupt(websocket,interrupt:dict): # \u0026#34;componentName\u0026#34; : \u0026#34;componentName\u0026#34;, # \u0026#34;interrupt\u0026#34; : \u0026#34;update\u0026#34;, # \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, # \u0026#34;data\u0026#34; : { } if( \u0026#34;componentName\u0026#34; in interrupt.keys() and \u0026#34;interrupt\u0026#34; in interrupt.keys() and \u0026#34;UUID\u0026#34; in interrupt.keys() and \u0026#34;data\u0026#34; in interrupt.keys() ): await websocket.send(json.dumps(interrupt)) else: print(\u0026#34;sendInterrupt helper ERROR: Mandatory keys are missing\u0026#34;) print(\u0026#34;componentName,interrupt,UUID,data\u0026#34;) print(interrupt) dataserver -\u0026gt; frontend 方向の割り込みについて考え直してみた なんか割り込みイベントを受け取れるコンポーネントを直接指定していたりするのは、フロントエンド側を大規模にいじる必要があり、めんどくさく感じて、何か別の方法はないか考えていたところ、割り込みはイベント名を付与してそれをフロントエンドに送り付け、あとは各コンポーネントが自由にそれをさばくように作ればよさそうって思ったことがあった。\nそれで割り込みは、データサーバからフロントエンドの一方通行で考え、以下のように変更した。\n### dataserver to frontend #### server interrupt reqest(JSON) ```json { \u0026#34;event\u0026#34; : \u0026#34;EventName\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : { } } ``` - event Interrupt event name. Any compornent are allowed to catch the interrupt. - UUID Identifier of the interrupt request - data Any data これでだいぶシンプルに実装しやすくなったように思う。また、sendInterrupt関数についても以下のように実装を変更した。\n# TODO: test and use this # TODO: write the document # arg: # websocket : the connection to the frontend via websocket # interrupt : content of the interrupt # return value # OK : None # Error : Error state does not exist. async def sendInterrupt(websocket,interrupt:dict): # \u0026#34;componentName\u0026#34; : \u0026#34;componentName\u0026#34;, # \u0026#34;interrupt\u0026#34; : \u0026#34;update\u0026#34;, # \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, # \u0026#34;data\u0026#34; : { } if( \u0026#34;event\u0026#34; in interrupt.keys() and \u0026#34;UUID\u0026#34; in interrupt.keys() and \u0026#34;data\u0026#34; in interrupt.keys() ): await websocket.send(json.dumps(interrupt)) else: print(\u0026#34;sendInterrupt helper ERROR: Mandatory keys are missing\u0026#34;) print(\u0026#34;componentName,interrupt,UUID,data\u0026#34;) print(interrupt) またどんな割り込みイベントがあって、なんのコマンドと関係あるかということについて、ドキュメントを作るようにした。以下はnewInfo割り込みイベントの例。\n# newInfo ## Role Notifiy the frontend notebooks or pages are created or deleted. ## interrupt data ```json { \u0026#34;event\u0026#34; : \u0026#34;newInfo\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : { } } ``` ## related commands - [createNotebook](../basicCommand/createNotebook.md) - [deleteNotebook](../basicCommand/deleteNotebook.md) - [createPage](../basicCommand/createPage.md) - [deletePage](../basicCommand/deletePage.md) 再接続機能改善の試み フロントエンド側で一定周期でWebScoketのreadyStateがOPEN以外になっていないかを監視するという再接続コードを書いていたが、それだけだと不十分で、実際にはサーバーが落ちていても、ブラウザ側がまだWebSocketの接続が生きていると思うと、readyStateがOPENのままになってうまく再接続できないことが分かった。\n... // 問題の実装 // TODO: Fix fllikering // TODO: Reconnection Loop singleton, there are bug Reconnection Loop are appear mutiple times. export function useDatabaseEffects() { const serverIP = useDatabaseStore((s) =\u0026gt; s.serverIP); const setWebsocket = useDatabaseStore.setState; const getWebsocket = useDatabaseStore((s) =\u0026gt; s.getWebsocket) // const init = useRef(true) useEffect(() =\u0026gt; { if (!serverIP) return; const reconnectLoop = () =\u0026gt; { console.log(\u0026#34;reconnect observer\u0026#34;) const websocket = getWebsocket() if(websocket != null){ // when there is no problem if(websocket.readyState == WebSocket.OPEN){ // observe the connection setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) return } } // when try to reconnect the dataserver setTimeout(() =\u0026gt; { const websocket = new WebSocket(serverIP); // websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) // websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) setWebsocket({ websocket: websocket }); },interval / 2 * 1000) setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) } const websocket = new WebSocket(serverIP); websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;close\u0026#34;,reconnectLoop) setWebsocket({ websocket: websocket }); return () =\u0026gt; { websocket.close(); }; }, [serverIP, setWebsocket]); } また、WebScoketが実際には利用不可になっていて再接続が必要な状態になっていても、WebScoket.send()関数はバッファに送信内容をエンキューしたのちに、もし失敗した場合は”サイレント”に送信内容が破棄されるということが分かった。つまり、送信に失敗しても何もエラーも出てこずにそのまま動作し続けてしまうことが分かった。\n以下は WebSocket: send() method - Web APIs | MDNの引用\nThe WebSocket.send() method enqueues the specified data to be transmitted to the server over the WebSocket connection, increasing the value of bufferedAmount by the number of bytes needed to contain the data. If the data can\u0026rsquo;t be sent (for example, because it needs to be buffered but the buffer is full), the socket is closed automatically. The browser will throw an exception if you call send() when the connection is in the CONNECTING state. If you call send() when the connection is in the CLOSING or CLOSED states, the browser will silently discard the data.\nそこでまずできそうな改善点として、まずデータサーバが何かしらの理由で動作を停止するとき、既存の接続はちゃんときれいに例外をつかんで、きれいにWebSocketを全部閉じるように実装しようと試みた。\n前の例外処理も全然してないコード (dataserver の main.py) # main server scirpt # serve dataserver function with websocket. import asyncio import multiprocessing # from modules.reqestParser import parser from websockets.asyncio.server import serve from helper import loadSettings from helper.netwrok import receiveLoop import tasks import controller # 以下の mainLoop 関数では、サーバが何かしらの理由で終了されても、ちゃんと WebSocket を閉じてくれない。 async def mainLoop(websocket): await receiveLoop(websocket,controller.controller) async def dataserver(): async with serve(mainLoop, loadSettings.settings[\u0026#34;ip\u0026#34;], loadSettings.settings[\u0026#34;port\u0026#34;]) as server: await server.serve_forever() def dataserverThread(): asyncio.run(dataserver()) def serviceThread(): asyncio.run(tasks.taskController(loadSettings.settings[\u0026#34;taskInterval\u0026#34;])) if __name__ == \u0026#34;__main__\u0026#34;: # 以下のコードでは、単に各プロセスをスタートさせて並列に動作させるだけになっており、 # それぞれのプロセスが終了するのを待たないため、親プロセスにおいて、keyboardInterruptを全くつかめない。 multiprocessing.Process(target=dataserverThread).start() multiprocessing.Process(target=serviceThread).start() 例外処理を追加したコード (dataserver の main.py) 全部ではないが、とりあえずある程度、keyboardInterruptの例外をつかむようにして、かつ WebSocket はなるべく正常に閉じられるようにコードを書き換えた。\n# main server scirpt # serve dataserver function with websocket. import asyncio import multiprocessing # from modules.reqestParser import parser from websockets.asyncio.server import serve from helper import loadSettings from helper.netwrok import receiveLoop import tasks import controller import sys # 以下のコードでは、なるべく終了時に Websocket を閉じるようにした。 # ただし、except asyncio.CancelledError: はたぶん機能してなさそうなので要検証。 # dataserver() ですでに例外をつかんでしまっているからなのかは不明。 async def mainLoop(websocket): try: await receiveLoop(websocket,controller.controller) except asyncio.CancelledError: print(\u0026#34;The dataserver mainLoop is stopped.\u0026#34;) finally: print(\u0026#34;The dataserver mainLoop is closed.\u0026#34;) await websocket.close() async def dataserver(): async with serve(mainLoop, loadSettings.settings[\u0026#34;ip\u0026#34;], loadSettings.settings[\u0026#34;port\u0026#34;]) as server: try: await server.serve_forever() except asyncio.CancelledError: print(\u0026#34;The dataserver is stopped.\u0026#34;) def dataserverThread(): asyncio.run(dataserver()) def serviceThread(): try: asyncio.run(tasks.taskController(loadSettings.settings[\u0026#34;taskInterval\u0026#34;])) except KeyboardInterrupt: print(\u0026#34;The task controller is stopped.\u0026#34;) if __name__ == \u0026#34;__main__\u0026#34;: print(\u0026#34;This dataserver is started.\u0026#34;) dataserverProcess = multiprocessing.Process(target=dataserverThread) serviceProcess = multiprocessing.Process(target=serviceThread) dataserverProcess.start() serviceProcess.start() # 例外をつかむために、各プロセスの終了を親プロセスで待つようにした。 try: dataserverProcess.join() serviceProcess.join() except KeyboardInterrupt: print(\u0026#34;This server will be stopped.\u0026#34;) dataserverProcess.terminate() serviceProcess.terminate() print(\u0026#34;All processes are terminated.\u0026#34;) sys.exit() フロントエンドとバックエンドの様子 例外処理実装前 例外処理実装後 ChatGPT Open as a page Open as a page select 要素が Free Page だけで見えない 全体で、onmousedownイベントをリッスンし、そのうえで、コールバック関数の中身に、event.preventDefault()を設定していると、select タグの中身が見えなくなることが分かった。\n具体的には、Free ページを開発していて、Add Item のフォームを設計していたところ、アイテム要素の種類を select タグから選べるはずが、全然ドロップダウンメニューが出てこず、右往左往したということがあった。それで、CSSスタイルやら疑わしいところを調べていたところ、Markdown ページでは症状が再現せず、Free ページのみに限って、select タグの中身が開けないということが、起こっていることが次はわかった。そして、マウス系のイベントで、全体的にリッスンしているコードを考えてみたところ、Free ページに固有で実装していた、右クリックメニューの実装の onmousedownのイベントのコールバックが怪しいなった。\nそこで、実際にそのコールバックを外してみると、Free ページを開いていても、select タグの内容が開けるようになることが分かった。コールバック関数を調べると、すべてのマウスの入力で、event.preventDefault() しており、select タグの内容を開くことまで prevent していることが分かった。\n問題の実装と様子 (src\\modules\\pages\\free\\showMenu.tsx) useEffect(() =\u0026gt; { const showAndHide = (event:MouseEvent) =\u0026gt; { event.preventDefault() // これだとすべてのマウス入力で、preventDefault してしまう。 if(event.button == 2){ position.current.x = event.clientX position.current.y = event.clientY setVisible(true) }else{ setVisible(false) } } addEventListener(\u0026#34;mousedown\u0026#34;,showAndHide) oncontextmenu = () =\u0026gt; {return false} return () =\u0026gt; { removeEventListener(\u0026#34;mousedown\u0026#34;,showAndHide) } },[]) 解決とした実装と様子 (src\\modules\\pages\\free\\showMenu.tsx) useEffect(() =\u0026gt; { const showAndHide = (event:MouseEvent) =\u0026gt; { if(event.button == 2){ event.preventDefault() // 右クリックのだけ、preventDefaultするようにすることで、通常の左クリックの操作を妨げないようにした。 position.current.x = event.clientX position.current.y = event.clientY setVisible(true) }else{ setVisible(false) } } addEventListener(\u0026#34;mousedown\u0026#34;,showAndHide) oncontextmenu = () =\u0026gt; {return false} return () =\u0026gt; { removeEventListener(\u0026#34;mousedown\u0026#34;,showAndHide) } },[]) Free ページでうまくアイテムを追加できない Free ページの実装として、アイテムを追加する機能を実装するというのがあり、作業していた。それで、AnItemのデータをテンプレートから作ろうとしたときに、変数の内容のコピーではなく、参照をコピーしてしまい、一回だけアイテムの追加に成功して、それ以降はアイテムを識別するための UUID がかぶってしまうため、アイテムが追加できないということが起こった。\nそこで、pythonの変数のディープコピー相当の機能はないかと調べていたところ、structuredClone が見つかったため、それを今回は実装で使うことにした。\n問題のある実装 function addItemToTheStore(){ if(selectedType.current == null){ showMessageBox({ title: \u0026#34;Add Item\u0026#34;, message: \u0026#34;Please select page type.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } // create an new item const targetElement = getElement(selectedType.current) if(targetElement == null){ showMessageBox({ title: \u0026#34;Add Item\u0026#34;, message: \u0026#34;Unable to find the page type.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } // これでは、ディープコピーをしていないため、targetElement.defaultDataの参照をあちこちにばらまく結果となり、 // アイテムを管理しているストアの中に、defaultData が登録されても、その登録された defaultData や targetElement.defaultData の ID が、 // 全部 defaultData.ID = genUUID() で置き換わってしまうため、一つの独立したアイテムのデータを作るということができていなかった。 const defaultData:AnItem = targetElement.defaultData defaultData.ID = genUUID() console.log(defaultData) // append the new item to the item store addItem(defaultData) const window = getWindow(OverlayWindowArg) if(window) closeWindow(window) } 解決とした実装 function addItemToTheStore(){ if(selectedType.current == null){ showMessageBox({ title: \u0026#34;Add Item\u0026#34;, message: \u0026#34;Please select page type.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } // create an new item const targetElement = getElement(selectedType.current) if(targetElement == null){ showMessageBox({ title: \u0026#34;Add Item\u0026#34;, message: \u0026#34;Unable to find the page type.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } // 以下では、targetElement.defaultData をディープコピーしてから、新しいアイテムのデータとして利用し、UUIDなどを設定しているため、 // targetElement.defaultData の参照とは、新しいアイテムのデータは切り離され問題が解消されている。 // deep copy is required // https://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone const defaultData:AnItem = structuredClone(targetElement.defaultData) defaultData.ID = genUUID() console.log(defaultData) // append the new item to the item store addItem(defaultData) const window = getWindow(OverlayWindowArg) if(window) closeWindow(window) } Free ページ アイテム追加の基本的なフロー　Free ページのアイテム管理の流れに変更点があったので、どうやってアイテムを追加するかのフローについて書いてみることにした。\nuseFreePageElementStore から、どんなページタイプが利用可能かelementsを参照する。 ユーザがアイテムタイプを選択肢して、作成ボタンを押す。 useFreePageElementStore から、ユーザが取得したタイプのFreePageElementを取得する。 取得されたFreePageElementからAnItem型のテンプレートをディープコピーする。 UUID を書き換え、新しい要素としてAnItem型のテンプレートデータを整形する。 useFreePageItemsStoreに、テンプレートデータから作成した新しいアイテムを追加する。 この流れの中で、新しく追加したものとしては、各アイテムタイプは、テンプレートデータを持ち、必要に応じて一部分のデータを変更していくということである。実際には以下のように実装した。\nAnItem 自体のテンプレート export const defaultItemData:AnItem = { // need to be overwrite data : \u0026#34;\u0026#34;, ID : \u0026#34;\u0026#34;, type : \u0026#34;\u0026#34;, // optional to overwrite position: { x: 100, y: 100, z: 1 }, size:{ height: 100, width: 100 }, color:{ a: 1, b: 100, g: 100, r: 100 }, } 各アイテムタイプのテンプレートの例(TextView) // テンプレート作成の部分 ------- // テンプレート作成の部分 ------- const defaultItemDataForTextView:AnItem = defaultItemData defaultItemDataForTextView.data = \u0026#34;Blank text item\u0026#34; defaultItemDataForTextView.type = \u0026#34;text\u0026#34; // テンプレート作成の部分 ------- // テンプレート作成の部分 ------- const element:FreePageElement = { name : \u0026#34;text\u0026#34;, element : TextView, defaultData : defaultItemDataForTextView, } アイテム追加機能の実装の一部 const defaultData:AnItem = structuredClone(targetElement.defaultData) defaultData.ID = genUUID() console.log(defaultData) // append the new item to the item store addItem(defaultData) 割り込みについて、さらに実装を追加した dataserver 側に一つ大きな割り込みの実装をした。具体的には以下の流れを実装した。\ninterrupts.contoller にある、callInterrupt を各コマンドは必要に応じて呼ぶ。 callInterrupt関数は、指定された割り込みが存在すればそれを呼ぶ 呼ばれた各種割り込みの実装の関数では、必要なデータが揃っていることを確認する。 問題なければ、helper.commonのsendInterruptを使って割り込みをフロントエンドへ送信する。 controller.py の実装 主なポイントは以下のとおりである。\nintrruptListで利用可能な割り込みが保持されている。 callInterrupt関数では、存在しない割り込みを呼び出した時、エラーを吐く。 callInterrupt関数では、割り込みが存在した場合それを呼び出し、その実行の成否を戻り値として返す。 from newInfo import newInfo from updatePage import updatePage intrruptList = { \u0026#34;newInfo\u0026#34; : newInfo, \u0026#34;updatePage\u0026#34; : updatePage, } # return # False -\u0026gt; OK # True -\u0026gt; Something went worng def callInterrupt(websocket,intrruptName:str,data:dict): for AnIntrrupt in intrruptList.keys(): if(AnIntrrupt == intrruptName): # call intrrupt return intrruptList[AnIntrrupt](websocket,data) print(\u0026#34;callInterrupt ERROR: The intrrupt does not exist.\u0026#34;) return True 各種割り込みの実装 ここでは、newInfo割り込みの実装を例として挙げ、説明を試みる。\n必要な data の内容が揃っているかを確認する。 data の中身も必要に応じて検証する。 問題なければ、responseのdictを作成する。 sendInterrupt 関数で実際に割り込みを送信する。この時、送信の成否は戻り値として返されcallInterruptへ伝播される。 from ..helper.common import sendInterrupt import uuid, copy, json actionList = [ \u0026#34;createNotebook\u0026#34;, \u0026#34;deleteNotebook\u0026#34;, \u0026#34;createPage\u0026#34;, \u0026#34;deletePage\u0026#34;, ] def newInfo(websocket,data:dict): if(not \u0026#34;action\u0026#34; in data.keys()): print(\u0026#34;newInfo interrupt ERROR: The mandatory key \u0026#39;action\u0026#39; does not exist.\u0026#34;) return True find = False for action in actionList: if(action == data[\u0026#34;action\u0026#34;]): find = True break if(not find): print(\u0026#34;newInfo interrupt ERROR: The action is invalid.\u0026#34;) print(data) return True response = { \u0026#34;event\u0026#34; : \u0026#34;newInfo\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : data } return sendInterrupt(websocket,response) 実際にフロントエンドに割り込みを送るように実装した。 まず以下の4つのコマンドについて、割り込みを送るように実装し、実際にそれがフロントエンドまで届くことを確認した。 Free ページの実装を進めた アイテムのリサイズ機能と、移動機能について、実装を進めた。移動機能については実装できたが、リサイズはまだ完全ではなく、右下からしか正常に相手もをリサイズできない状態が続いている。\nアイテム変形機能についてのフローとして、以下のような操作の形をとった。\nアイテムを一回クリックすると、移動機能が有効になる。 アイテムをダブルクリックすると、リサイズ機能が有効になる。 アイテムをダブルクリックすると、編集機能が有効になる。 どのフェーズにおいても、アイテムの外を一回クリックすると、すべての機能が無効になり、最初の状態に戻る。\nsendInterrupt helper 関数に関して、実装を変更した 実際に、割り込みが機能しているか試したところ、データサーバが接続されているフロントエンドすべてにちゃんと割り込みを送信できる実装になっていなかった。割り込みを発生する要因となったフロントエンドにしか割り込みが来ていないことが分かり、修正を行った。\n問題となった実装では、単にコマンドがつかんでいるwebsocket接続の参照をそのままsendInterruptまで渡して、それを使って割り込みを送信してしまっているため、正しく接続されたすべてのフロントエンドに対して割り込みを送信できていなかった。\n# arg: # websocket : the connection to the frontend via websocket # interrupt : content of the interrupt # return value # OK : False will be returned. It mean there are no problems # Error : True will be returned. It mean there are something missing in dict keys of \u0026#34;interrupt\u0026#34; arg async def sendInterrupt(websocket,interrupt:dict): # \u0026#34;evnet\u0026#34; : \u0026#34;eventName\u0026#34;, # \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, # \u0026#34;data\u0026#34; : { } if( \u0026#34;event\u0026#34; in interrupt.keys() and \u0026#34;UUID\u0026#34; in interrupt.keys() and \u0026#34;data\u0026#34; in interrupt.keys() ): responseString = json.dumps(interrupt) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) # これでは、コマンドを実行したフロントエンド以外には何も割り込みに通知がいかない await websocket.send(responseString) return False else: print(\u0026#34;sendInterrupt helper ERROR: Mandatory keys are missing\u0026#34;) print(\u0026#34;componentName,interrupt,UUID,data\u0026#34;) print(interrupt) return True 具体的には、websocketの接続が確立されるごとに、websocketsという配列にその接続の参照を保持しておき、sendIntrrupt関数では、forループで全部のwebsocketの接続を回って割り込みを送信するように実装を変更した。\n# arg: # websocket : the connection to the frontend via websocket # interrupt : content of the interrupt # return value # OK : False will be returned. It mean there are no problems # Error : True will be returned. It mean there are something missing in dict keys of \u0026#34;interrupt\u0026#34; arg async def sendInterrupt(websocket,interrupt:dict): # \u0026#34;evnet\u0026#34; : \u0026#34;eventName\u0026#34;, # \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, # \u0026#34;data\u0026#34; : { } if( \u0026#34;event\u0026#34; in interrupt.keys() and \u0026#34;UUID\u0026#34; in interrupt.keys() and \u0026#34;data\u0026#34; in interrupt.keys() ): responseString = json.dumps(interrupt) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) # 割り込みをすべてのフロントエンドに送信する実装 for Awebsocket in websockets: try: await Awebsocket.send(responseString) except Exception as e: print(\u0026#34;sendInterrupt helper ERROR: Ignore the disconnected websocket.\u0026#34;) print(e) # 割り込みをすべてのフロントエンドに送信する実装 終わり print(websockets) return False else: print(\u0026#34;sendInterrupt helper ERROR: Mandatory keys are missing\u0026#34;) print(\u0026#34;componentName,interrupt,UUID,data\u0026#34;) print(interrupt) return True 動作の様子 参考にしたサイトとか WebSocket: send() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send (2025年10月18日)\nChatGPT\nhttps://chatgpt.com/ (2025年10月18日)\nWebSocket: readyState property - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState (2025年10月18日)\nmultiprocessing — Process-based parallelism — Python 3.14.0 documentation\nhttps://docs.python.org/3/library/multiprocessing.html#multiprocessing.Process.join (2025年10月18日)\nmultiprocessing — Process-based parallelism — Python 3.14.0 documentation\nhttps://docs.python.org/3/library/multiprocessing.html#multiprocessing.Process.terminate (2025年10月18日)\nWebSocket: send() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/WebSocket/send (2025年10月18日)\nBoth sides (asyncio) - websockets 15.0.1 documentation\nhttps://websockets.readthedocs.io/en/stable/reference/asyncio/common.html#websockets.asyncio.connection.Connection.close (2025年10月18日)\nServer (asyncio) - websockets 15.0.1 documentation\nhttps://websockets.readthedocs.io/en/stable/reference/asyncio/server.html#websockets.asyncio.server.Server.close (2025年10月18日)\nCatching KeyboardInterrupt in Python during program shutdown - Stack Overflow\nhttps://stackoverflow.com/questions/21120947/catching-keyboardinterrupt-in-python-during-program-shutdown (2025年10月18日)\nHow to exit from Python without traceback? - Stack Overflow\nhttps://stackoverflow.com/questions/1187970/how-to-exit-from-python-without-traceback (2025年10月18日)\nWhy is KeyboardInterrupt not working in python? - Stack Overflow\nhttps://stackoverflow.com/questions/543534/why-is-keyboardinterrupt-not-working-in-python (2025年10月18日)\nPart 2 - Route \u0026amp; broadcast - websockets 15.0.1 documentation\nhttps://websockets.readthedocs.io/en/stable/intro/tutorial2.html (2025年10月18日)\nWindow: structuredClone() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Window/structuredClone (2025年10月19日)\nElement: dblclick event - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Element/dblclick_event (2025年10月21日)\nElement: mouseover event - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Element/mouseover_event (2025年10月21日)\nTouch events - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Touch_events (2025年10月21日)\nposition - Layout - Tailwind CSS\nhttps://tailwindcss.com/docs/position#relatively-positioning-elements (2025年10月21日)\nopacity - Effects - Tailwind CSS\nhttps://tailwindcss.com/docs/opacity (2025年10月21日)\ncursor - Interactivity - Tailwind CSS\nhttps://tailwindcss.com/docs/cursor (2025年10月21日)\nElement: click event - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Element/click_event (2025年10月21日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-10-23/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/10/16 から、2025/10/23 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子-フロントエンド\"\u003e動作の様子 (フロントエンド)\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-10-23/%e8%a8%98%e9%8c%b22025-10-23.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/10/23 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"主な項目\"\u003e主な項目\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 別のページを開いても未保存のデータのバッファが管理されるように各ページタイプを実装する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e drawio で説明する図を作る\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 他人が構造の理解に必要な分を記録できたか\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンド(更新)\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 新たに追加した、task の仕組みについて、ドキュメントを整備する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e オブジェクト変形用に汎用的なコンポーネントを定義する。カーソルがオブジェクトをホバーしているときに出現するようにする。タッチでは、一回タップで出現。（サイズ変更、移動）\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 移動について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リサイズ機能についての実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 右下について実装 (とりあえずこれだけにするかも)\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 下について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 右について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 左上について実装 （正しくitemを更新できないバグありで解消中）\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 左について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 上について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 左下について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 右上について実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集モードを各アイテムの要素の種類ごとに実装。汎用的には、ダブルクリックされた場合に編集モードに移行するようにする。タッチではダブルタッチで移行する.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e selector の改善\u003c/p\u003e","title":"2025/10/23-やったことリスト"},{"content":"この記事を作った動機 2025/10/23 から、2025/10/30 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2025/10/30 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） free ページの実装\nフロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page オブジェクト変形用に汎用的なコンポーネントを定義する。カーソルがオブジェクトをホバーしているときに出現するようにする。タッチでは、一回タップで出現。（サイズ変更、移動） 移動について実装 △ リサイズ機能についての実装 右下について実装 (とりあえずこれだけ) 編集モードを各アイテムの要素の種類ごとに実装。汎用的には、ダブルクリックされた場合に編集モードに移行するようにする。タッチではダブルタッチで移行する. 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 編集機能、データセーブ（更新）の実装\n別のページを開いても未保存のデータのバッファが管理されるように各ページタイプを実装する selector の改善 Selector に未保存の表示を行う free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装\nバックエンドからフロントエンドの方向の割り込みをすでにドキュメントである程度定義したとおりに実装する。例えば、ページ内容に変更があったら通知したりする。 helper.commonとして、sendIntteruptを実装する。 helper.commonのsendIntteruptについて、ドキュメントを書いた。 割り込みが必要なコマンド群から、割り込みを送るようにする。また各コマンドのドキュメントに割り込みについて説明を書く。これに伴いテンプレートも割り込みについて記述するように、更新を行う。 割り込みについては、専用のドキュメントページを作り、そこに記述する フロントエンド側を割り込みを受けつけるように、改修していく。自動的に、フロントエンドが、バックエンドの割り込みによって連動して機能することを確認する。例えば、ページが作成されたとき、内容が変更されたとき、ノートブックが削除された時などに、データサーバが接続しているすべてのフロントエンドに、その通知が行く。各コンポーネントが、必要な割り込みイベントを、listen するような形をとる。 割り込みの仕組みについてのドキュメントの記述が見つからない場合、新たに定義し、それをもとに実装を進める。 ドキュメントに書いた割り込みが実際に機能するよう、各コマンドに割り込みを送るように実装していく。 データサーバからくる割り込みとコマンドレスポンスの分離について考える。具体的には割り込みやコマンドレスポンスには名前を割り当てて、識別するか、持っているkey次第で分類するかという案がある。 データサーバからやってくるデータが何なのか識別できるように名前を付ける。割り込みやコマンドに対するレスポンスなど複数の種類のデータが来ることが考えられ、それをはっきりと識別するために、名前を付けたいと思う。 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\nデータサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。\nデータサーバの実装\naddTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。\nフロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。\nバックエンド OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる やったことの詳細 マークダウンページをバッファ機能に対応させた とりあえず、セーブされてないデータある状態で別のページを開いたりして作業しても内容が失われないように実装を行った。具体的には、Editor画面で編集があった場合は、それをバッファーに登録しておき、また変更があるごとにバッファーが更新される。\nそれで、別のページを開いてから、もともと編集していた未保存の変更のあるページでは、バッファーがあることが分かると、その内容を復元して表示する。またセーブされた場合はバッファーが削除される。\nバッファー管理に使われているのはsrc\\modules\\window.tsxの中にある以下のものである。ちなみに地味にいろいろ実装をミスっていたので修正したりもしてた。例えば、removeBufferと書いていながら、全然ちゃんと対象のバッファーを取り除けてなかったりしたので、修正したりしている。\nexport type AnUnsavedBuffer = { notebookName : string, notebookUUID : string, pageID : string, pageUUID : string, pageType : string, UUID : string, // to identify each buffers. timestamp : Date, bufferContentString : string, } // NOTE: normally single page will add single buffer and update constantly if there are any modification. export type unsavedBuffers = { buffers : AnUnsavedBuffer[], addBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, removeBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, updateBuffer : (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; void, // not to create buffer, to update exist buffer getBuffers : (pageID:string,pageUUID:string,notebookName:string) =\u0026gt; AnUnsavedBuffer[], getUnsavedPageList : () =\u0026gt; string[], // for selector compornent. } export const useUnsavedBuffersStore = create\u0026lt;unsavedBuffers\u0026gt;((set,get) =\u0026gt; ({ buffers: [], addBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ // when the buffer has already existed, abort the update if(aBuffer.UUID == unsavedBuffer.UUID) return newBuffer.push(aBuffer) } newBuffer.push(unsavedBuffer) set({buffers:newBuffer}) }, removeBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ if(aBuffer.pageUUID == unsavedBuffer.pageUUID) continue newBuffer.push(aBuffer) } set({buffers:newBuffer}) }, getBuffers: (pageID:string,pageUUID:string,notebookName:string) =\u0026gt; { const allBuffer = get().buffers const buffers = [] for(const aBuffer of allBuffer){ if( aBuffer.pageID == pageID \u0026amp;\u0026amp; aBuffer.pageUUID == pageUUID \u0026amp;\u0026amp; aBuffer.notebookName == notebookName ) buffers.push(aBuffer) } return buffers }, updateBuffer: (unsavedBuffer:AnUnsavedBuffer) =\u0026gt; { const oldBuffer = get().buffers const newBuffer = [] for(const aBuffer of oldBuffer){ // update if(aBuffer.UUID == unsavedBuffer.UUID) { // make sure the timestamp is the time of the last modify. unsavedBuffer.timestamp = new Date() newBuffer.push(unsavedBuffer) continue } newBuffer.push(aBuffer) } set({buffers:newBuffer}) }, getUnsavedPageList: () =\u0026gt; { const buffers = get().buffers const bufferList:AnUnsavedBuffer[] = [] for(const aBuffer of buffers){ let find = false for(const AnBuffer of bufferList){ if(AnBuffer.pageID == aBuffer.pageID){ find = true break } } if(find) continue bufferList.push(aBuffer) } return bufferList } })) Selectorにおいて未保存の表示をするようにした Selectorで、未保存のページがあるかどうかわかるように、useUnsavedBuffersStoreを使って状態に応じて色を付けるように実装をしてみた。\n具体的には、赤色になっていれば、未保存であることを意味し、緑色になっていれば、未保存で現在開いているページということになる。また、既に保存されている場合は、白色に近いグレーで選択されたものは表示され、選択されてない場合は背景色がつかないようになっている。\nほかにも、ノートブック選択画面において、未保存のページが含まれるものは、赤色で示されるようにした。\n割り込みを一部機能するようにした フロントエンド側の実装を進めることで、以前バックエンド側で実装した割り込みを使い、とりあえずSelectorにおいて、ノートブックやページが、作成、削除されたときに、選択肢が同期されるようにできた。\nfree ページについて実装の方針を変更 アイテムのリサイズ機能について、右上がうまく実装できなかったことを受けて、うまく動いてそうな右下だけ残して、リサイズボタンを一時的に撤去した。\n具体的な課題としては、アイテムを移動したら、アイテムの情報を更新する必要があるが、それがうまくいかないという現象があった。アイテムのサイズを更新する分には問題が起こっていなかったが、アイテムの位置とサイズを同時に更新すると問題が起こるという感じである。\nちなみに今こうして書いていて、じゃあいったんサイズだけ更新して、そのあと位置も更新すれば、また違った結果が得られるのではないかというのもあったが、アイテムのリサイズ機能だけに時間を投資していてもらちがあかないので、いったんそこはスキップとした。\nデータサーバからくるデータの形式の変更 responseTypeというキーを追加し、コマンドに対する応答なのか、割り込みなのかはっきりと識別できるようにした。まだフロントエンド側は特段特別なことはしていないが、バックエンド側だけ先にやってみた。\nコマンドレスポンスの例 { \u0026#34;responseType\u0026#34; : \u0026#34;commandResponse\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;errorMessage\u0026#34;: \u0026#34;nothing\u0026#34;, \u0026#34;UUID\u0026#34;:\u0026#34;UUID string\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;deletePage\u0026#34;, \u0026#34;data\u0026#34;:{ } } 割り込みの例 { \u0026#34;responseType\u0026#34; : \u0026#34;interrupt\u0026#34;, \u0026#34;event\u0026#34; : \u0026#34;updatePage\u0026#34;, \u0026#34;UUID\u0026#34; : \u0026#34;UUID string\u0026#34;, \u0026#34;data\u0026#34; : { } } Free ページのバグ修正 Free ページにおいて、アイテムが一つも存在しないページを開くと、アイテム追加において正常に利用可能なアイテムタイプの表示に失敗することが分かった。\n具体的には、アイテムが最初 Free ページ初期化時に表示されたときにしか、アイテムタイプを登録していなかったために、最初からページ内に存在しない、または別の Free ページを開いて表示したことのないタイプのアイテムは、useFreePageElementStore に正しく登録されていないため、選択できず、追加できないという状態になっていた。\n問題のアイテムタイプ追加の流れ 何かしらの Free ページが開かれる もし、アイテムがすでに存在している場合、それを表示しようとする 表示するとともに、表示を担うコンポーネント内に、アイテムの種類の登録処理が入っており、特定のアイテムタイプが存在することが、useFreePageElementStoreに登録される 結果的に、アプリ自体を開いてから、表示したことのある Free ページのアイテムタイプだけが、利用可能なアイテムとして表示されてしまう。 修正後のアイテムタイプ追加の流れ 何かしら Free ページが開かれる Free ページがそもそもアイテムを表示しようとする前に、各要素のコンポーネントからエクスポートされている登録情報を使い、すべてのアイテムタイプをuseFreePageElementStoreに登録する 表示されたことがないアイテムタイプでも、新しいアイテムとして登録可能になる Free ページが閉じられるときは、アイテムタイプはuseFreePageElementStoreから全部削除される Free ページでセーブ機能を追加 実際に内容が変更されたら、リアルタイムで変更内容をセーブするようにした。ただし弊害として、セーブするタイミングがおかしい場合というのがあり、例えば、別のページに移動したときなどに、別のページ自身としてぐちゃぐちゃなデータをセーブしようとして、変なところにごみデータをぶちまけてしまうということが確認された。\nそれでは困るので、とりあえずバックエンド側のupdatePageコマンド側で、pageIDとpageType、UUIDが本当に正しいのか、既にデータサーバ側にあるページのメタデータと情報を比べるようにした。UUIDの検証については、たぶんうまくいっていない気がするので、もう少しそこについてはデバックがいるものと思われる。\npageID と pageType が一致しているか調べる # check the extention if(pageType == \u0026#34;markdown\u0026#34; and not \u0026#34;md\u0026#34; in pageID): await errorResponse( websocket, request, \u0026#34;The page type mismatch.\u0026#34;, [notebookName,pageID,pageType,pagePath] ) return elif(not pageType == \u0026#34;markdown\u0026#34; and not \u0026#34;json\u0026#34; in pageID): await errorResponse( websocket, request, \u0026#34;The page type mismatch.\u0026#34;, [notebookName,pageID,pageType,pagePath] ) return 既にあるデータと新しいデータ間でページ間のUUIDが一致しているか調べる # check the page UUID is match to the new data try: with open(pagePath,\u0026#34;rt\u0026#34;,encoding=\u0026#34;utf-8\u0026#34;) as oldData: if(pageType == \u0026#34;markdown\u0026#34;): datastring = oldData.read() splitResult1 = datastring.split(\u0026#34;++++\u0026#34;) if(len(splitResult1) \u0026lt; 3): await errorResponse( websocket, request, \u0026#34;The old data string is malformed. Unable to find the metadata.\u0026#34;, [notebookName,pageID,pageType,pagePath,splitResult1,updateDataString] ) return OLDpageMetadataJSON = json.loads(splitResult1[1]) if(OLDpageMetadataJSON[\u0026#34;UUID\u0026#34;] != pageMetadataJSON[\u0026#34;UUID\u0026#34;]): await errorResponse( websocket, request, \u0026#34;The page UUID does not match to the old one.\u0026#34;, [notebookName,pageID,pageType,pagePath,pageMetadataJSON,OLDpageMetadataJSON], error ) return else: oldData = json.loads(oldData.read()) if(oldData[\u0026#34;UUID\u0026#34;] != pageMetadataJSON[\u0026#34;UUID\u0026#34;]): await errorResponse( websocket, request, \u0026#34;The page UUID does not match to the old one.\u0026#34;, [notebookName,pageID,pageType,pagePath,pageMetadataJSON,oldData], error ) return except Exception as error: await errorResponse( websocket, request, \u0026#34;Failed to compare page UUID string.\u0026#34;, [notebookName,pageID,pageType,pagePath,pageMetadataJSON,updateDataString], error ) return どうしてそういうことになるのかわからないが、すぐ思いつく原因としては、Freeページコンポーネントの挙動が思った通りでないのかもしれないというのがあった。私の現在のイメージだと、別のページに移動したら、前動かしていた、コンポーネント自体が破棄されて、その内容も次開くときは最初から初期化するって感じであったが、たぶん違うような気がしてきた。この点について、深く調べていく必要がありそうである。\nほかにも気になる挙動としては、Freeページを開いたとき、閉じたときにそれぞれ変更をしていないにもかかわらず、セーブしようとする挙動が出ている点である。なんか、変更があったかどうかを独立して管理する変数を用意したほうがいいかもしれないと思ったりもした。\nFree ページにおいて、Properties 項目の追加 細かい書式設定とか、各アイテムタイプ固有の操作について、汎用的な入れ物として、Properties という項目を toggleable として edit に追加してみた。まだ詳しい中身は作っていないが、選択された要素のタイプに対して、機能が展開されるようにする予定。\n具体的には、textViewなどが、自分から詳細な設定項目の画面を設定しに行く。zustandでとりあえず、各アイテムタイプに必要なUIを追加できるように、ストアを作ってはおいた。ただすごく粗削りでまだ動くところまで行ってないので、これについては微調整をさらにしていき、実際に動くかテストする予定。\nexport type aProperty = { name : string, UUID : string, itemType : string, settingItems: (({ name,settingElementWithCallbackForSave }:{ name:string,settingElementWithCallbackForSave:React.JSX.Element[] }) =\u0026gt; JSX.Element)[] settingUI : ({ name, items }: { name: string; items: React.JSX.Element[];}) =\u0026gt; JSX.Element } export type properties = { properties : aProperty[], addProperty : (property:aProperty) =\u0026gt; void, removeProperty : (property:aProperty) =\u0026gt; void, getProperties : (itemType:string) =\u0026gt; aProperty[], cleanProperty : () =\u0026gt; void } export const useFreePagePropertiesStore = create\u0026lt;properties\u0026gt;((set,get) =\u0026gt; ({ properties: [], addProperty: (property:aProperty) =\u0026gt; { const oldProperties = get().properties const newProperties = [] for(const anProperty of oldProperties){ if(anProperty.UUID == property.UUID) return newProperties.push(anProperty) } newProperties.push(property) set({properties:newProperties}) }, removeProperty: (property:aProperty) =\u0026gt; { const oldProperties = get().properties const newProperties = [] for(const anProperty of oldProperties){ if(anProperty.UUID == property.UUID) continue newProperties.push(anProperty) } set({properties:newProperties}) }, getProperties : (itemType:string) =\u0026gt; { const targets = [] const properties = get().properties for(const property of properties){ if(property.itemType == itemType){ targets.push(property) } } return targets }, cleanProperty: () =\u0026gt; { set({properties:[]}) } })) // const test:aProperty = { // name:\u0026#34;test\u0026#34;, // UUID:\u0026#34;test\u0026#34;, // settingUI: Aproperty // } // \u0026lt;div className=\u0026#34;aProperty\u0026#34;\u0026gt; // \u0026lt;div className=\u0026#34;name\u0026#34;\u0026gt;Format\u0026lt;/div\u0026gt; // \u0026lt;div className=\u0026#34;items\u0026#34;\u0026gt; // \u0026lt;div className=\u0026#34;anItem\u0026#34;\u0026gt; // \u0026lt;div className=\u0026#34;itemName ml-auto\u0026#34;\u0026gt;FontSize\u0026lt;/div\u0026gt; // \u0026lt;input type=\u0026#34;range\u0026#34; id=\u0026#34;fontsize\u0026#34; min={10} max={100}\u0026gt;\u0026lt;/input\u0026gt; // \u0026lt;/div\u0026gt; // \u0026lt;div className=\u0026#34;anItem\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; // \u0026lt;/div\u0026gt; // \u0026lt;/div\u0026gt; // This can be nested. // items arg has to be AnItemForAproperty element array export function Aproperty({ name,items }:{ name:string,items:React.JSX.Element[] }){ return \u0026lt;div className=\u0026#34;aProperty\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;name\u0026#34;\u0026gt;{name}\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;items\u0026#34;\u0026gt;{items}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; } // This have to be inside of Aproperty element export function AnItemForAproperty({ name,settingElementWithCallbackForSave }:{ name:string,settingElementWithCallbackForSave:React.JSX.Element[] }){ return \u0026lt;div className=\u0026#34;anItem\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;itemName ml-auto\u0026#34;\u0026gt;{name}\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;settingElement\u0026#34;\u0026gt;{settingElementWithCallbackForSave}\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; } 参考にしたサイトとか Date - JavaScript | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date (2025年10月26日)\nDate.prototype.getTime() - JavaScript | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/getTime (2025年10月26日)\nTailwind CSS Select Menus - Official Tailwind UI Components\nhttps://tailwindcss.com/plus/ui-blocks/application-ui/forms/select-menus (2025年10月26日)\nReact(CSS) \\nで改行する方法\nhttps://zenn.dev/shake_sanma/articles/9244b03d42cd09 (2025年10月29日)\nwhite-space - CSS: カスケーディングスタイルシート | MDN\nhttps://developer.mozilla.org/ja/docs/Web/CSS/white-space (2025年10月29日)\nwhite-space - Typography - Tailwind CSS\nhttps://tailwindcss.com/docs/white-space (2025年10月29日)\nmin-width - Sizing - Tailwind CSS\nhttps://tailwindcss.com/docs/min-width (2025年10月29日)\n\u0026lt;input\u0026gt;: The HTML Input element - HTML | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input (2025年10月29日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-10-30/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/10/23 から、2025/10/30 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-10-30/2025-10-30%e8%a8%98%e9%8c%b2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/10/30 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e オブジェクト変形用に汎用的なコンポーネントを定義する。カーソルがオブジェクトをホバーしているときに出現するようにする。タッチでは、一回タップで出現。（サイズ変更、移動）\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 移動について実装\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e △ リサイズ機能についての実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 右下について実装 (とりあえずこれだけ)\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 編集モードを各アイテムの要素の種類ごとに実装。汎用的には、ダブルクリックされた場合に編集モードに移行するようにする。タッチではダブルタッチで移行する.\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\u003c/p\u003e","title":"2025/10/30-やったことリスト"},{"content":"この記事を作った動機 2025/10/30 から、2025/11/6 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2025/11/6 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 Free ページがバグりまくるのを何とかする 別のページを開くと前のページとアイテムが混じったりして地獄のようなことになっていたので修正しようと試みた。それで以下の点を試し、最終的に動いてそうな状況までもっていった。具体的には、Freeページを開いたらuseFreePageItemsStoreにアイテムを追加し、閉じたらuseFreePageItemsStoreからアイテムをなくし、初期化するはずだったが、それがうまくいかないという現象が起こった。別のFreeページに移動しても、うまくuseEffectでは、Freeページを閉じたときの処理を走らせることができず、前のFreeページのアイテムと、新しく開いたFreeページのアイテムが混ざる状態であった。\nFree ページコンポーネント内で、modified という状態変数を保持し、その状態変数が True となった時だけ、実際にデータサーバへセーブするようにリクエストを送る。アイテム追加、削除、やその他もろもろの編集機能は、modified状態変数を変更することで、変更を反映する。 useFreePageItemsStore において、pageUUID をアイテムに紐づけて管理するようにした。しかし、あまり効果がなくバグを改善するにはこれは至らなかった気がする。またこの修正により、useAppState の currentPage の仕様を変更し、uuid についても管理するようにし、全体の実装もそれに合わせる変更をした。 useEffectを使わず、useRefによって初期化を管理するようにした。useEffectを使ったコンポーネント初期化方法は一見するとクリーンアップも同時に実装でき便利なように見えるが、実は意図しないタイミングで発動することが分かり、それがバグを起こし、制御が難しかったことから、Free ページの初期化では使わないことにした。 以前の実装 ... useEffect(() =\u0026gt; { if(currentPage == null){ showMessageBox({ title: \u0026#34;Free Page\u0026#34;, message: \u0026#34;Unable to find the opened page.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } console.log(\u0026#34;Free page init\u0026#34;) for(const item of jsondata.pageData.items){ addItem(item,structuredClone(currentPage.uuid)) } initComplete.current = true closed.current = false return () =\u0026gt; { console.log(\u0026#34;Free page end\u0026#34;) initComplete.current = false closed.current = true cleanItem() } },[]) ... 修正した実装 あまり以下の実装におけるuseEffectの使い方はよくないっぽいが、現状だとそのままにしている。\n... useEffect(() =\u0026gt; { // if(currentPage == null){ // showMessageBox({ // title: \u0026#34;Free Page\u0026#34;, // message: \u0026#34;Unable to find the opened page.\u0026#34;, // UUID: messageBoxUUID.current, // type: \u0026#34;error\u0026#34; // }) // return // } // console.log(\u0026#34;Free page init\u0026#34;) // for(const item of jsondata.pageData.items){ // addItem(item,structuredClone(currentPage.uuid)) // } // initComplete.current = true // closed.current = false return () =\u0026gt; { console.log(\u0026#34;Free page end\u0026#34;) initComplete.current = false closed.current = true cleanItem() } },[]) if(!initComplete.current){ cleanItem() if(currentPage == null){ showMessageBox({ title: \u0026#34;Free Page\u0026#34;, message: \u0026#34;Unable to find the opened page.\u0026#34;, UUID: messageBoxUUID.current, type: \u0026#34;error\u0026#34; }) return } console.log(\u0026#34;Free page init\u0026#34;) for(const item of jsondata.pageData.items){ addItem(item,structuredClone(currentPage.uuid)) } initComplete.current = true closed.current = false } ... 問題の様子と解決した様子 問題の様子 解決した様子 Commons を Free ページに実装した Free ページに存在するアイテムが共通でもつプロパティを編集できるUIを作った。まだ変更を正しく反映できないバグや、ActiveItemをUI操作中に維持できていない、色選択の表示がおかしいなどの問題がある。あとRaw DataとZ-indexのボタンに一部未実装部分がある。\ntag 機能について進めた 以下のコマンドについて、dataserver側にまだ未実装でファイルだけ作っただけのコマンドと、具体的にどうするかある程度指針として決めるために、ドキュメントを軽く書いた。\naddTag\nタグを特定のページに設定する。 createTag\nタグを新規作成する。 deleteTag\nタグを削除する。 getTagList\n既存のタグのリストを表示する。 queryTag\nタグに紐づいたページを検索する。 removeTag\n特定のタグを特定のページから切り離す。 フロントエンドのネットワークログの整理 前の実装だと、いろんなところで websocketのmessageイベントのデータを出力するようになっていて、コンソールが同じような出力で荒れるということがあったので、src\\modules\\helper\\network.tsxに、何を送信して何が返ってきたか、表示するようにまとめてみた。\nexport function useDatabaseEffects() { const serverIP = useDatabaseStore((s) =\u0026gt; s.serverIP); const setWebsocket = useDatabaseStore.setState; const getWebsocket = useDatabaseStore((s) =\u0026gt; s.getWebsocket) // const init = useRef(true) const showMessage = (event:MessageEvent) =\u0026gt; { console.log(event.data) try{ console.log(JSON.parse(event.data)) }catch(e) { console.log(\u0026#34;This is not json data.\u0026#34;) } } useEffect(() =\u0026gt; { if (!serverIP) return; const reconnectLoop = () =\u0026gt; { // console.log(\u0026#34;reconnect observer\u0026#34;) const websocket = getWebsocket() if(websocket != null){ // when there is no problem if(websocket.readyState == WebSocket.OPEN){ // observe the connection setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) return } } // when try to reconnect the dataserver setTimeout(() =\u0026gt; { const websocket = new WebSocket(serverIP); websocket.addEventListener(\u0026#34;message\u0026#34;,showMessage) // websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) // websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) setWebsocket({ websocket: websocket }); },interval / 2 * 1000) setTimeout(() =\u0026gt; { reconnectLoop() },interval * 1000) } const websocket = new WebSocket(serverIP); websocket.addEventListener(\u0026#34;error\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;open\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;close\u0026#34;,reconnectLoop) websocket.addEventListener(\u0026#34;message\u0026#34;,showMessage) setWebsocket({ websocket: websocket }); return () =\u0026gt; { websocket.close(); }; }, [serverIP, setWebsocket]); } ネットワーク接続状態の監視案について思いつく 前フロントエンドのネットワーク再接続周りについて不完全な改善をしたことについては記録したが、その当時はWebsocketのブラウザの実装以外でネットワークの接続状況を確認する方法として、ポーリングし続けるというのがあった。しかし、それだとやはり無駄が多く、より良い正確に効率よく常態判定ができる方法はないか、考えたところ、「コマンドリクエストを送信して、一定時間経過したら、タイムアウト判定する」という方法を思いついた。\n初期化時 まず初期化としてデータサーバに接続するとき、一定時間経過後Ping的に一回コマンドを実行し、一定時間内に帰ってくるか見る。\n接続時 コマンドをリクエストした際に、同時にタイムアウトの監視を行う。\nメリット ポーリングしなくて済む ブラウザの実装に依存せずに、自由にタイムアウト、接続の可否の判定ができる。 デメリット 実装がちょいと煩雑になる 接続後はコマンドが実行された後に初めて接続の可否が分かる仕様になっているため、UX的に良くないかもしれない。数十秒から数分単位で粗めにポーリングしつつ、コマンド送信時の応答時間の長さも判定に使うという方針がいいかもしれないとは思った。 Selector の実装をリファクタリングした Selector の実装が一つのスクリプトに詰まりすぎているのではないかということで、実装をいくつかに分けた。\n│ selector.tsx └─selector AnEntry.tsx CreateList.tsx helper.tsx init.tsx selector.tsx Selector を表示するために、各selectorフォルダ内にあるコンポーネントを結び付け、総合的にUIをまとめて表示する親コンポーネントとしての役割がある。\nAnEntry.tsx 各ページや階層構造のエントリに関するUIパーツ一つ相当の実装がある。\nCreateList.tsx 各ノートブック内のページや階層構造などをリスト表示する実装がある。\nhelper.tsx 現状では、updatePageInfoForSelectorという関数があり、notebookの情報を取得するコマンドを実行するためにネットワークrequestを出す実装がある。\ninit.tsx コンポーネント生成時に設定したいuseEffectをまとめたもの。\n参考にしたサイトとか typeof - JavaScript | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/typeof (2025年11月4日) \u0026lt;input type=\u0026ldquo;color\u0026rdquo;\u0026gt; - HTML | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/input/color (2025年11月4日) HTML input type=\u0026ldquo;color\u0026rdquo;\nhttps://www.w3schools.com/tags/att_input_type_color.asp (2025年11月4日) onmouseout Event\nhttps://www.w3schools.com/jsref/event_onmouseout.asp (2025年11月6日) formatting - Pad a number with leading zeros in JavaScript - Stack Overflow\nhttps://stackoverflow.com/questions/10073699/pad-a-number-with-leading-zeros-in-javascript (2025年11月6日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-11-6/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/10/30 から、2025/11/6 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-11-6/%e8%a8%98%e9%8c%b22025-11-6.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/11/6 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/11/6-やったことリスト"},{"content":"この記事を作った動機 2025/11/6 から、2025/11/13 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2025/11/13 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 保存される page や notebook の JSON データを human readable にする もともとの実装だと、dataserver 側は単にデータを一行の JSON として保存しているだけで、可読性がひどいので、ちゃんと改行やインデントが入るように実装を変更した。\n改修前のコード import json ... json.dumps(notebookMatadata) ... 改修後のコード import json ... json.dumps(notebookMatadata,indent=4) ... 改修前の Notebook metadata.json の例 {\u0026#34;name\u0026#34;: \u0026#34;newnote\u0026#34;, \u0026#34;createDate\u0026#34;: \u0026#34;2025/9/26\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/11/6\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;5f3215a7-88f1-4065-9a01-98d630d99607\u0026#34;, \u0026#34;pages\u0026#34;: [\u0026#34;\\u30c6\\u30b9\\u30c8.md\u0026#34;, \u0026#34;\\u3075\\u3055\\u304a.md\u0026#34;, \u0026#34;test.md\u0026#34;, \u0026#34;testa.md\u0026#34;, \u0026#34;aaaaasdadaaaswe.md\u0026#34;, \u0026#34;oneNoteStyle/husahusa.json\u0026#34;, \u0026#34;oneNoteStyle/dssss.json\u0026#34;], \u0026#34;files\u0026#34;: []} 改修後の Notebook metadata.json の例 { \u0026#34;name\u0026#34;: \u0026#34;newnote\u0026#34;, \u0026#34;createDate\u0026#34;: \u0026#34;2025/9/26\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/11/12\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;5f3215a7-88f1-4065-9a01-98d630d99607\u0026#34;, \u0026#34;pages\u0026#34;: [ \u0026#34;\\u30c6\\u30b9\\u30c8.md\u0026#34;, \u0026#34;\\u3075\\u3055\\u304a.md\u0026#34;, \u0026#34;test.md\u0026#34;, \u0026#34;testa.md\u0026#34;, \u0026#34;aaaaasdadaaaswe.md\u0026#34;, \u0026#34;oneNoteStyle/husahusa.json\u0026#34;, \u0026#34;oneNoteStyle/dssss.json\u0026#34; ], \u0026#34;files\u0026#34;: [] } Free ページでメタデータを表示するように改修した Free ページにおいて、メタデータを表示するように実装した。 src\\modules\\pages\\free\\main.tsx ... useEffect(() =\u0026gt; { setMetadataToAppState({ createDate:jsondata.createDate, files:jsondata.files, tags:jsondata.tags, updateDate:jsondata.updateDate, UUID:jsondata.UUID }) return () =\u0026gt; { setMetadataToAppState(null) } },[jsondata]) ... フロントエンドのネットワーク周りの改修 やったことリスト ユーザーに対し、背景を赤くすることで dataserver との接続が切れていることを表す。 再接続ループが常に Websocket がオープンしたときに、ポーリングするようになっていたのを修正した。errorやcloseイベントが発火した時だけ、再接続を試みるように修正した。 useDatabaseEffectからuseNetworkEffectに名前を変更した。 useDatabaseStore内に、send関数を実装した。 useDatabaseStore内に、isDisconnectという項目をブール型で用意し、dataserver と接続されているか独立して状態を管理し、ほかのコンポーネントから参照できるようにした。 requestHistoryという配列を用意し、Arequestという型をもってして送信した文字列や時間、コマンドリクエストのUUIDを管理するようにした。コマンドにdataserverから応答ががあった時は、requestHistoryの配列から送信した情報が削除され、正常にコマンドのやり取りができたことになる。 useDatabaseStoreをuseNetworkStoreに名前を変更するTODOを立てた。 未接続状態の表示の実装例 export default function Window(){ ... const isDisconnect = useDatabaseStore((s) =\u0026gt; s.isDisconnect) let style = { background: \u0026#34;\u0026#34; } if(isDisconnect){ style.background = \u0026#34;rgba(255,0,0,0.2)\u0026#34; } console.log(isDisconnect) ... } 新しいsend関数 dataserver にリクエストを送る関数sendを、useDatabaseStore内に実装した。徐々にこの関数に実装を置き換えていく予定。\n今までのsend関数の実装には問題があり、いちいちwebsocketをリクエストを行ったコンポーネントから引数として直接渡しているため、再接続などがあった時に、その新しいwebsocketを参照できずに、古い接続が途切れたwebsocketを使って再送信を試みるという問題が起こっていた。以下は今までのsend関数の流れである。\n各コンポーネントがwebsocketの参照をuseDatabaseStoreから持っている。 send関数が実行されたとき、useDatabaseStoreから持ってきたwebsocketの参照が\u0026quot;コピー\u0026quot;される。useDatabaseStoreのwebsocketの参照が変わっても、既に実行されているsend関数のwebsocketの参照が更新されない。 send関数が送信失敗を検出し、再送信しようとするときに、既にとじらえていて利用不能なwebsocketの参照が利用される。 すべての再送信の試みにおいて失敗する。 そこで、websocketの参照が直接存在するuseDatabaseStore内にsend関数を移動することで、常に最新の接続されたweboscketの参照を使うようにしたいというのがあった。\n旧来の実装 export function send(websocket:WebSocket, request:string, attempt=5){ // const addHistory = useNetworkRequestManager((s) =\u0026gt; s.addRequest) // const isHistoryExists = useNetworkRequestManager((s) =\u0026gt; s.isRequestExist) // const setWebsoketState = useDatabaseStore.setState const CurrentHistory:Arequest = { requestJSONstring: request, UUID: JSON.parse(request).UUID, requestTimestamp: new Date } // addHistory(history) requestHistory.push(CurrentHistory) if(attempt == 0){ console.log(\u0026#34;on websocket send data, all attempts are failed. stop\u0026#34;) console.log(request) return } // console.log(websocket.readyState) if( websocket.readyState != WebSocket.CONNECTING \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSED \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSING ){ console.log(request) websocket.send(request) // check the request on the timeout state setTimeout(() =\u0026gt; { for(const history of requestHistory){ if(history.UUID == CurrentHistory.UUID){ // when failed request break } } },timeoutInterval * 1000) return } // 古い websocket を参照し続けながら、再試行回数上限を迎えるまで、永遠に再送信に失敗し続ける setTimeout(() =\u0026gt; { send(websocket,request,attempt - 1) },interval * 1000) } 新しい実装 export const useDatabaseStore = create\u0026lt;Networks\u0026gt;((set, get) =\u0026gt; ({ websocket: null, serverIP: \u0026#34;ws://localhost:50097\u0026#34;, isDisconnect: true, changeServer: (ip: string) =\u0026gt; { set({ serverIP: ip }); }, closeConnection: () =\u0026gt; { const ws = get().websocket; ws?.close(); set({ websocket: null, isDisconnect: true }); }, getWebsocket: () =\u0026gt; get().websocket, send: (request:string, attempt) =\u0026gt; { if(attempt == null) attempt = 5 // 常に再送信時には最新の websocket を参照している const websocket = get().websocket if(websocket == null){ // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) return } const CurrentHistory:Arequest = { requestJSONstring: request, UUID: JSON.parse(request).UUID, requestTimestamp: new Date } requestHistory.push(CurrentHistory) if(attempt == 0){ console.log(\u0026#34;on websocket send data, all attempts are failed. stop\u0026#34;) console.log(request) return } if( websocket.readyState != WebSocket.CONNECTING \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSED \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSING ){ console.log(request) websocket.send(request) // check the request on the timeout state setTimeout(() =\u0026gt; { console.log(requestHistory) for(const history of requestHistory){ if(history.UUID == CurrentHistory.UUID){ // when failed request set({ isDisconnect:true }) // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) break } } },timeoutInterval * 1000) return } // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) }, })); isDisconnect の実装の詳細 true : 未接続 false: dataserver に接続済み isDisconnectはuseDatabaseStore内にあるブール型の変数で、dataserver とフロントエンドが接続されているか独立して状態を管理し、ほかのコンポーネントから参照できるようにしたものである。\nisDisconnectは、websocketが閉じられたりエラーの時に、reconnectLoopに入ったり、send関数でタイムアウトが検出されたりすると、trueになり、何かしらの形でwebsocketの接続が復旧し、openイベントが発火したときにはfalseになる。\n参考にしたサイトとか json — JSON encoder and decoder — Python 3.14.0 documentation\nhttps://docs.python.org/3/library/json.html#basic-usage (2025年11月12日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-11-13/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/11/6 から、2025/11/13 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-11-13/2025-11-13%e3%81%ae%e8%a8%98%e9%8c%b2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/11/13 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/11/13-やったことリスト"},{"content":"この記事を作った動機 2025/11/13 から、2025/11/20 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 今回は特に前回から目立って進捗していないのでなし。\nTODOs TODOs 2025/11/20 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 useDatabaseStore を useNetworkStore にリネーム 卒業論文を書き始めた TexLive の環境構築をした 軽く章立てをした 何を書くか見立てを立てた 概要を書いた 方法あたりの章を書き始めた 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-11-20/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/11/13 から、2025/11/20 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e　今回は特に前回から目立って進捗していないのでなし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/11/20 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/11/20-やったことリスト"},{"content":"この記事を作った動機 2025/11/20 から、2025/11/27 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 今回は特に前回から目立って進捗していないのでなし。\nTODOs TODOs 2025/11/27 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい deleted.json に対して、ページUUIDも記録するようにし、過去に削除されたページと同じ階層構造で同じ名前を持つページが新規作成されても衝突しないようにする。 削除されたことになっているが、まだ物理的にファイルシステム上からは消されていないページと同じ階層構造で同じ名前を持つページが新規作成された場合、重複としては扱わず、削除対象のページを退避する。というか、元から削除されたページは退避する場所（フォルダー）をノートブック内に専用に作る。 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 卒論を書いていた 卒業論文を書いていた 図を draw.io で書きなおした。 概要をはじめにの項目の経緯として移動した 手法のところで、ノートブックのデータ形式やファイル構造などについて説明を書き進めた ノートブックのファイル構成についてはいったん説明を書き終えた ノートブックに関連するすべてのメタデータについて具体例を書いたり、章立てをした 卒論を書いていたら、実際に作ってみたプロトタイプの欠陥がいくつか見えてきた。 削除されたファイルを一定期間 contents フォルダから消去しない場合、現状の実装だとバグって、消されているにもかかわらず重複判定をしてしまうことが分かった。消されたファイルは専用のフォルダを各ノートブック内に作り、そこに階層構造を保ったまま退避する必要性が見えてきた。またdeleted.jsonにおいての消されたページの管理の不十分で、ページのUUIDも管理しないと、削除されたページと同じ階層構造、名前を持つ同じノートブック内の新規作成されたページが衝突してしまうという問題も見つかった。 いちいち文字列として時間を管理するより、UnixTimeとして秒を管理して、必要に応じてその秒から日時を計算したほうがより一貫性があり、処理しやすい実装になることが見えてきた。 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-11-27/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/11/20 から、2025/11/27 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e　今回は特に前回から目立って進捗していないのでなし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/11/27 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e deleted.json に対して、ページUUIDも記録するようにし、過去に削除されたページと同じ階層構造で同じ名前を持つページが新規作成されても衝突しないようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 削除されたことになっているが、まだ物理的にファイルシステム上からは消されていないページと同じ階層構造で同じ名前を持つページが新規作成された場合、重複としては扱わず、削除対象のページを退避する。というか、元から削除されたページは退避する場所（フォルダー）をノートブック内に専用に作る。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/11/27-やったことリスト"},{"content":"この記事を作った動機 2025/11/27 から、2025/12/4 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2025/12/4 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい deleted.json に対して、ページUUIDも記録するようにし、過去に削除されたページと同じ階層構造で同じ名前を持つページが新規作成されても衝突しないようにする。 削除されたことになっているが、まだ物理的にファイルシステム上からは消されていないページと同じ階層構造で同じ名前を持つページが新規作成された場合、重複としては扱わず、削除対象のページを退避する。というか、元から削除されたページは退避する場所（フォルダー）をノートブック内に専用に作る。 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 deleted.json の形式を変更した 正しくページを識別できるようにページのUUIDを項目に追加した。\n旧来形態 { \u0026#34;newnote\u0026#34;: [ { \u0026#34;pageID\u0026#34;: \u0026#34;default.md\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2025/10/5\u0026#34; }, { \u0026#34;pageID\u0026#34;: \u0026#34;test/test/test/recursively/test.md\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2025/10/14\u0026#34; }, ... ] } 新しい定義 { \u0026#34;newnote\u0026#34;: [ { \u0026#34;UUID\u0026#34;: \u0026#34;18e01583-3b79-42de-a544-f2fec7da41d7\u0026#34;, \u0026#34;pageID\u0026#34;: \u0026#34;testa.md\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2025/12/3\u0026#34; }, { \u0026#34;UUID\u0026#34;: \u0026#34;9d49383e-9bb1-46ec-a631-66e6730c602c\u0026#34;, \u0026#34;pageID\u0026#34;: \u0026#34;test.md\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2025/12/3\u0026#34; }, { \u0026#34;UUID\u0026#34;: \u0026#34;a20d2903-43e7-47c7-9c73-e213839165c7\u0026#34;, \u0026#34;pageID\u0026#34;: \u0026#34;ttstdss.md\u0026#34;, \u0026#34;date\u0026#34;: \u0026#34;2025/12/3\u0026#34; } ... ] } deletePage コマンドの挙動を変更 削除されたページを一時的に保持するために、各ノートブック内に、deletedという名前のフォルダを作成するようにした。そして、そこに[ページのUUID.ページの拡張子]という形で平たく階層構造は保持せずに削除されたページのファイルは移動するようにした。\n├─deleted │ 0ed59523-7ec1-4f56-b1e0-17e936238a3e.md │ a20d2903-43e7-47c7-9c73-e213839165c7.md │ ... deletePage コマンドのバグ修正 ちょっと触ってみたところ以下のようなバグがあったので、修正をした。\nページを作成 作ったページを削除 同じノートブック内で、削除されたページと同じ階層構造、名前、ページタイプを持つ新しいページを作成する 作ったページを削除しようとするが、ノートブックの整合性が取れていないというエラーになる 新たにページを作成しようとしても、古いページがcontentsフォルダに残ったままなので、削除されたページと同じノートブック内で、同じ階層構造、名前、ページタイプを持つ新しいページは、重複エラーとなり作成できなくなる。 上記のことから、コードを探ると、deleted.json内部に記録されたPageIDを元に、すでに、削除されたページと同じ階層構造、名前、ページタイプを持つページが削除されていないか検証するコードがあり、それが新しいページとすでに削除されたページを区別できていないことが分かった。\nそのため、具体的な解決策として、PageIDを比較するのではなく、ページに付随している識別子であるUUIDを比較することで、問題が再現しないことを確認し、バグを修正したということにした。\n修正前 # Check the page has already been deleted or not. find = False for aPageInfo in targetDeletedInfo: if(aPageInfo[\u0026#34;PageID\u0026#34;] == pagePathFromContentFolder): find = True break if(find): await errorResponse( websocket, request, \u0026#34;The page has already been deleted even the notebook metadata still has the ref to the page. The integrality may be corrupted.\u0026#34;, [notebookName,pagePath,pagePathFromContentFolder,deleted] ) return 修正後 # NOTE: UUID is added to as identifier # Check the page has already been deleted or not. find = False for aPageInfo in targetDeletedInfo: if(aPageInfo[\u0026#34;UUID\u0026#34;] == PageUUID): find = True break if(find): await errorResponse( websocket, request, \u0026#34;The page has already been deleted even the notebook metadata still has the ref to the page. The integrality may be corrupted.\u0026#34;, [notebookName,pagePath,pagePathFromContentFolder,deleted] ) return fileAPI の案に進展があった 以下は簡易的なメモ書き。\nfileAPI として実装するのではなく、さらにHTTPサーバも立てて細かいファイルのやり取りはそれに任せるということを思いついた。それなら大きなファイルも楽に既存のプロトコルに乗せてやり取りできるのではないかと思った。 基本的にはファイルサーバは、 http://serverIP:port/Files/ノートブック名　＋階層構造を含めたファイルまでのパス http://serverIP:port/Files/ノートブックUUID　＋階層構造を含めたファイルまでのパス というような形で、直感的にリソースを提供できるようにしたい。 またついでに考えると、HTTPプロトコルへのフォールバックとして、 http://serverIP:port/Commands/[CommandName] のようなエントリーポイントが考えられた。 卒論を書き進めた 調査の章について、何を書くか見当をつけることを進めた。 X11やマインクラフトのサーバークライアントモデルの件について参考になりそうなリソースを探した。 データサーバについて記述を追加した。どのような役割があるのか、内部構造がどうなっているのかについて、概要を説明するようにした。また図解も作成した。 フロントエンドについて章を立てて、図解を作っている途中までは行った。ただし、十分説明できているかは定かではない。 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-12-4/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/11/27 から、2025/12/4 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-12-4/2025-12-4%e3%81%ae%e8%a8%98%e9%8c%b2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/12/4 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e deleted.json に対して、ページUUIDも記録するようにし、過去に削除されたページと同じ階層構造で同じ名前を持つページが新規作成されても衝突しないようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 削除されたことになっているが、まだ物理的にファイルシステム上からは消されていないページと同じ階層構造で同じ名前を持つページが新規作成された場合、重複としては扱わず、削除対象のページを退避する。というか、元から削除されたページは退避する場所（フォルダー）をノートブック内に専用に作る。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/12/4-やったことリスト"},{"content":"この記事を作った動機 2025/12/4 から、2025/12/11 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 特に大きな変更はないので今回はなし。\nTODOs TODOs 2025/12/11 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 卒論を進めた 結果の章について具体的に書くことを見当をつけた。実際のページを保存するなどの動作を中心に、フロントエンドやバックエンド、データややり取りがどのように変遷するか、具体的な動作を記録することにした。 X11やMinecraftのサーバクライアントモデルと研究が関係あることについて書いた フロントエンドの説明について、具体的な内部の動作を軽く書いた フロントエンドの図解ついて、論文の文中にいったん載せた フロントエンドについても、詳細にどのような動作をするかさらに具体的な起動から基本的な操作や表示の流れを記述する必要性が出てきた。 参考にしたサイトとか Welcome to the Minecraft Official Site | Minecraft\nhttps://www.minecraft.net/en-us (2025年12月14日) Minecraft Client-Side and Server-Side Explained\nhttps://cybrancee.com/blog/minecraft-client-side-and-server-side-explained/ (2025年12月14日) Server/Client Communication | Technical Minecraft Wikia | Fandom\nhttps://technical-minecraft.fandom.com/wiki/Server/Client_Communication (2025年12月14日) X/Architecture - Ubuntu Wiki\nhttps://wiki.ubuntu.com/X/Architecture (2025年12月14日) 第 1 章 Solaris X サーバーの概要 (Solaris X Window System 開発ガイド)\nhttps://docs.oracle.com/cd/E19455-01/806-2735/6jbubqoec/index.html (2025年12月14日) What Is X11? | Baeldung on Linux\nhttps://www.baeldung.com/linux/x11 (2025年12月14日) Xming X Server for Windows - Official Website\nhttp://www.straightrunning.com/XmingNotes/ (2025年12月14日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-12-11/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/12/4 から、2025/12/11 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e特に大きな変更はないので今回はなし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/12/11 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/12/11-やったことリスト"},{"content":"この記事を作った動機 2025/12/18 から、2025/12/25 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 今回は変更はなかったので特になし。\nTODOs TODOs 2025/12/25 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 卒論を書いた フロントエンドの再接続ロジックについて説明する図を書き、requesthistory について軽く論文中にデータ構造と説明を書いた。 調査内容について、ブログ側にある画像の内いくつか選んでそれを論文に載せた。 調査内容について、簡易的に研究になにが反映されているかわかりやすいように、まとめの表を作った。 texの図表番号について、調整をかけたり、JSONにはJSONのラベルがつくようにしたりした。 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-12-25/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/12/18 から、2025/12/25 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e今回は変更はなかったので特になし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/12/25 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/12/25-やったことリスト"},{"content":"この記事を作った動機 2025/12/11 から、2025/12/18 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2025/12/18 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が mainLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 データサーバのfindNotes helper 関数でノートブックがないときの挙動について修正した 卒論のために記録を取るために、実装の違いによるバグを避けるため、ノートブックデータをまっさらにした。そのところ、findNotes関数がノートブックのルートフォルダに何もない場合、エラーを返していることが分かった。infoやcreateNotebookコマンドなどの挙動がエラーになったりして、それでは正常に動作しないことが分かったため、ノートブックがない場合について、実装を追加した。\n以下は追加した実装である。単にノートブックのフォルダ内に何もない場合、空のdictを返すようにした。これによって、まっさらな状態でノートブックを新規作成できないなどのバグが改善された。\nif(os.listdir(root).__len__() == 0): print(\u0026#34;findNotes helper: There is no notebooks. This may not be critical.\u0026#34;) return {} フロントエンドのsend関数にタイムアウトの項目を追加 要求が破棄されても致命的ではない要求については、一定時間後に要求の履歴を破棄するように設定できるようにした。また、逆に要求の履歴が破棄されるのが不都合なものに関しては、timeoutをnullにすることにより、attempt回分だけ要求を再試行するまで要求の履歴が破棄されないこととした。\n変更後の実装 (src\\modules\\helper\\network.tsx) send: (request:string, attempt, timeout = null) =\u0026gt; { if(attempt == null) attempt = 5 const websocket = get().websocket if(websocket == null){ // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1,timeout) },interval * 1000) return } const requestUUID = JSON.parse(request).UUID let findRequestHistory = false for(const history of requestHistory){ if(history.UUID == requestUUID){ findRequestHistory = true break } } const CurrentHistory:Arequest = { requestJSONstring: request, UUID: requestUUID, requestTimestamp: new Date, timeout: timeout } if(!findRequestHistory){ requestHistory.push(CurrentHistory) } if(attempt == 0){ console.log(\u0026#34;on websocket send data, all attempts are failed. stop\u0026#34;) console.log(request) return } if( websocket.readyState != WebSocket.CONNECTING \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSED \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSING ){ console.log(request) websocket.send(request) // check the request on the timeout state setTimeout(() =\u0026gt; { console.log(requestHistory) for(const history of requestHistory){ if(history.UUID == CurrentHistory.UUID){ // when failed request set({ isDisconnect:true }) // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1,timeout) },interval * 1000) break } } },timeoutInterval * 1000) return } // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1,timeout) },interval * 1000) }, const removeReceivedRequest = (event:MessageEvent) =\u0026gt; { // remove history depend on the timeout try{ const newHistory = [] for(const oldHistory of requestHistory){ const requestTime = oldHistory.requestTimestamp.getTime() / 1000.0 // sec const currentTime = new Date().getTime() / 1000.0 // sec const timeout = oldHistory.timeout if(timeout == null) continue if(currentTime - requestTime \u0026gt; timeout) continue newHistory.push(oldHistory) } requestHistory = newHistory }catch(error){ console.log(\u0026#34;Unable to remove a request. (depend on timeout)\u0026#34;) console.log(error) console.log(event.data) console.log(event) } // remove history depend on the received data from the dataserver console.log(\u0026#34;removeReceivedRequest is working\u0026#34;) try{ const jsondata = JSON.parse(event.data) if(jsondata.responseType != \u0026#34;commandResponse\u0026#34;) return const newHistory = [] for(const oldHistory of requestHistory){ if(oldHistory.UUID == jsondata.UUID) continue newHistory.push(oldHistory) } requestHistory = newHistory console.log(jsondata.UUID) console.log(newHistory) }catch (error){ console.log(\u0026#34;Unable to remove a request. (depend on received data)\u0026#34;) console.log(error) console.log(event.data) console.log(event) } } 変更前の実装 (src\\modules\\helper\\network.tsx) send: (request:string, attempt) =\u0026gt; { if(attempt == null) attempt = 5 const websocket = get().websocket if(websocket == null){ // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) return } const requestUUID = JSON.parse(request).UUID let findRequestHistory = false for(const history of requestHistory){ if(history.UUID == requestUUID){ findRequestHistory = true break } } const CurrentHistory:Arequest = { requestJSONstring: request, UUID: requestUUID, requestTimestamp: new Date } if(!findRequestHistory){ requestHistory.push(CurrentHistory) } if(attempt == 0){ console.log(\u0026#34;on websocket send data, all attempts are failed. stop\u0026#34;) console.log(request) return } if( websocket.readyState != WebSocket.CONNECTING \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSED \u0026amp;\u0026amp; websocket.readyState != WebSocket.CLOSING ){ console.log(request) websocket.send(request) // check the request on the timeout state setTimeout(() =\u0026gt; { console.log(requestHistory) for(const history of requestHistory){ if(history.UUID == CurrentHistory.UUID){ // when failed request set({ isDisconnect:true }) // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) break } } },timeoutInterval * 1000) return } // retry setTimeout(() =\u0026gt; { get().send(request,attempt - 1) },interval * 1000) }, const removeReceivedRequest = (event:MessageEvent) =\u0026gt; { // remove history depend on the received data from the dataserver console.log(\u0026#34;removeReceivedRequest is working\u0026#34;) try{ const jsondata = JSON.parse(event.data) if(jsondata.responseType != \u0026#34;commandResponse\u0026#34;) return const newHistory = [] for(const oldHistory of requestHistory){ if(oldHistory.UUID == jsondata.UUID) continue newHistory.push(oldHistory) } requestHistory = newHistory console.log(jsondata.UUID) console.log(newHistory) }catch (error){ console.log(\u0026#34;Unable to remove a request. (depend on received data)\u0026#34;) console.log(error) console.log(event.data) console.log(event) } } フロントエンドの接続状態管理について変更 データサーバからメッセージがあった場合に、データサーバに接続されているとみなして、isDisconnectをfalse（接続状態に変更）するようにした。\n変更後の実装 (src\\modules\\helper\\network.tsx) // when a message is received from the dataserver, change network status if(isDisconnect) setWebsocket({isDisconnect:false}) const removeReceivedRequest = (event:MessageEvent) =\u0026gt; { // remove history depend on the timeout try{ const newHistory = [] for(const oldHistory of requestHistory){ const requestTime = oldHistory.requestTimestamp.getTime() / 1000.0 // sec const currentTime = new Date().getTime() / 1000.0 // sec const timeout = oldHistory.timeout if(timeout == null) continue if(currentTime - requestTime \u0026gt; timeout) continue newHistory.push(oldHistory) } requestHistory = newHistory }catch(error){ console.log(\u0026#34;Unable to remove a request. (depend on timeout)\u0026#34;) console.log(error) console.log(event.data) console.log(event) } // remove history depend on the received data from the dataserver console.log(\u0026#34;removeReceivedRequest is working\u0026#34;) try{ const jsondata = JSON.parse(event.data) if(jsondata.responseType != \u0026#34;commandResponse\u0026#34;) return const newHistory = [] for(const oldHistory of requestHistory){ if(oldHistory.UUID == jsondata.UUID) continue newHistory.push(oldHistory) } requestHistory = newHistory console.log(jsondata.UUID) console.log(newHistory) }catch (error){ console.log(\u0026#34;Unable to remove a request. (depend on received data)\u0026#34;) console.log(error) console.log(event.data) console.log(event) } // when a message is received from the dataserver, change network status if(isDisconnect) setWebsocket({isDisconnect:false}) } getPageTypeコマンドだけなぜか、フロントエンドの要求履歴から消えない理由が分かった フロントエンドでページを新規作成するUIを開くと、同時にどのタイプのページを作成できるかフロントエンドがデータサーバに対して、getPageTypeコマンドを要求することがある。しかし、そのコマンドが実装されたときだけ、返答が返ってきているにも関わらず、ネットワーク要求履歴から消えないということがあった。\nそれで最終的には、データサーバのgetPageTypeコマンドの実装が、旧来のままになっており、responseTypeを返していないことが分かった。このためにフロントエンドから要求履歴を削除しようとしたときに、getPageTypeコマンドの要求だけ、コマンド応答ではないとして、無視されていたことが分かった。そのため、getPageTypeコマンドの実装にて、コマンド応答として、responseTypeを返すように改修した。\n今回のことから、応答するための共通のhelper関数を作って、それで応答に必要な項目が書けていないか、チェックした方がミスが防げて良いかもしれないということがあった。\n修正前 # list pageType from helper.common import NotImplementedResponse, dataKeyChecker import type.pages.controller as controller from helper import loadSettings import json async def getPageType(request,websocket): responseString = json.dumps({ # responseType がここにない \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;getPageType\u0026#34;, \u0026#34;data\u0026#34; : list(controller.pages.keys()) }) await websocket.send(responseString) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) 修正後 # list pageType from helper.common import NotImplementedResponse, dataKeyChecker import type.pages.controller as controller from helper import loadSettings import json async def getPageType(request,websocket): responseString = json.dumps({ \u0026#34;responseType\u0026#34; : \u0026#34;commandResponse\u0026#34;, # コマンドレスポンスを返すようにしたので、フロントエンドでバグを起こさないようになった。 \u0026#34;status\u0026#34; : \u0026#34;ok\u0026#34;, \u0026#34;errorMessage\u0026#34; : \u0026#34;nothing\u0026#34;, \u0026#34;UUID\u0026#34; : request[\u0026#34;UUID\u0026#34;], \u0026#34;command\u0026#34; : \u0026#34;getPageType\u0026#34;, \u0026#34;data\u0026#34; : list(controller.pages.keys()) }) await websocket.send(responseString) print(\u0026#34;\u0026gt;\u0026gt;\u0026gt; \u0026#34; + responseString) 卒論を書いていた 結果のところについて、ページの表示と新規作成について書いた 考察のところについて大体何を書くかについて検討をつけた。 はじめにの目的のところで、理想と研究内で取り扱うことの二つに分けて、何に向かっているか、何をしようとしているかについて書いた。 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2025-12-18/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/12/11 から、2025/12/18 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2025-12-18/2025-12-18%e3%81%ae%e8%a8%98%e9%8c%b2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2025/12/18 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2025/12/18-やったことリスト"},{"content":"この記事を作った動機 2025/12/25 から、2026/1/8 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 TODOs TODOs 2026/1/8 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が usernameLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 DataServer バックエンドに helper 関数を追加 DataServerが送ったメッセージJSONやフロントエンドから受け取ったJSONメッセージが無秩序に汚い文字列として表示されていたので、それを共通できれいに整形してコンソールに表示する共通の実装として、showJSONMessageを書いた。\n# TODO: write document for this function # NOTE: reveived JSONstring, all command and interrupt JSONstring have to be shown by this function # arg: # JSONstring : JSON string got received from the connected frontend or will be sent to the frontend. # receive : To show received JSON message, make this arg True otherwise the JSONstring will be shown as a sent JSONstring to the frontend. # return value # Nothing def showJSONMessage(JSONstring:str,receive:bool=False): jsondata = json.loads(JSONstring) if(receive): print(\u0026#34;\u0026lt;\u0026lt;\u0026lt;\\n\u0026#34; + json.dumps(jsondata,indent=4)) else: print(\u0026#34;\u0026gt;\u0026gt;\u0026gt;\\n\u0026#34; + json.dumps(jsondata,indent=4)) 改修前のJSONログの例 ---------------------- \u0026lt;\u0026lt;\u0026lt;{\u0026#34;command\u0026#34;:\u0026#34;info\u0026#34;,\u0026#34;UUID\u0026#34;:\u0026#34;f68e7884-9ce9-4d5d-a778-e2bfc4662fe5\u0026#34;,\u0026#34;data\u0026#34;:null} findNotes helper: /home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/notebookData/ｆｓっｄｆｓｄｆｓｄｆｓｄ does not include a notebook. {\u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;createDate\u0026#39;: \u0026#39;2025/12/15\u0026#39;, \u0026#39;updateDate\u0026#39;: \u0026#39;2025/12/21\u0026#39;, \u0026#39;id\u0026#39;: \u0026#39;ae7a5760-8a48-4721-9489-63379333f16e\u0026#39;, \u0026#39;pages\u0026#39;: [\u0026#39;default.md\u0026#39;, \u0026#39;test.json\u0026#39;, \u0026#39;aaaaa.md\u0026#39;], \u0026#39;files\u0026#39;: []} findNotes helper: /home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/notebookData/newnote does not include a notebook. \u0026gt;\u0026gt;\u0026gt; {\u0026#34;responseType\u0026#34;: \u0026#34;commandResponse\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;f68e7884-9ce9-4d5d-a778-e2bfc4662fe5\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34;: \u0026#34;nothing\u0026#34;, \u0026#34;data\u0026#34;: {\u0026#34;test\u0026#34;: {\u0026#34;name\u0026#34;: \u0026#34;test\u0026#34;, \u0026#34;createDate\u0026#34;: \u0026#34;2025/12/15\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/12/21\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;ae7a5760-8a48-4721-9489-63379333f16e\u0026#34;, \u0026#34;pages\u0026#34;: [\u0026#34;default.md\u0026#34;, \u0026#34;test.json\u0026#34;, \u0026#34;aaaaa.md\u0026#34;], \u0026#34;files\u0026#34;: []}}} 改修後のJSONログの例 ---------------------- \u0026lt;\u0026lt;\u0026lt; { \u0026#34;command\u0026#34;: \u0026#34;info\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;acaa84de-39f3-46e2-9ae2-313497473e8a\u0026#34;, \u0026#34;data\u0026#34;: null } findNotes helper: /home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/notebookData/ｆｓっｄｆｓｄｆｓｄｆｓｄ does not include a notebook. {\u0026#39;name\u0026#39;: \u0026#39;test\u0026#39;, \u0026#39;createDate\u0026#39;: \u0026#39;2025/12/15\u0026#39;, \u0026#39;updateDate\u0026#39;: \u0026#39;2025/12/21\u0026#39;, \u0026#39;id\u0026#39;: \u0026#39;ae7a5760-8a48-4721-9489-63379333f16e\u0026#39;, \u0026#39;pages\u0026#39;: [\u0026#39;default.md\u0026#39;, \u0026#39;test.json\u0026#39;, \u0026#39;aaaaa.md\u0026#39;], \u0026#39;files\u0026#39;: []} findNotes helper: /home/username/work/OneNoteAlternative/firstPrototype/backend/dataServer/notebookData/newnote does not include a notebook. \u0026gt;\u0026gt;\u0026gt; { \u0026#34;responseType\u0026#34;: \u0026#34;commandResponse\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;ok\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;acaa84de-39f3-46e2-9ae2-313497473e8a\u0026#34;, \u0026#34;command\u0026#34;: \u0026#34;info\u0026#34;, \u0026#34;errorMessage\u0026#34;: \u0026#34;nothing\u0026#34;, \u0026#34;data\u0026#34;: { \u0026#34;test\u0026#34;: { \u0026#34;name\u0026#34;: \u0026#34;test\u0026#34;, \u0026#34;createDate\u0026#34;: \u0026#34;2025/12/15\u0026#34;, \u0026#34;updateDate\u0026#34;: \u0026#34;2025/12/21\u0026#34;, \u0026#34;id\u0026#34;: \u0026#34;ae7a5760-8a48-4721-9489-63379333f16e\u0026#34;, \u0026#34;pages\u0026#34;: [ \u0026#34;default.md\u0026#34;, \u0026#34;test.json\u0026#34;, \u0026#34;aaaaa.md\u0026#34; ], \u0026#34;files\u0026#34;: [] } } } 時間を表示する文字列を0でパディングするようにした。 # arg: # None : None # return value # OK : formated date string # Error : None def timeString(): currentTime = time.localtime() return \u0026#34;{:04d}/{:02d}/{:02d}\u0026#34;.format( currentTime.tm_year, currentTime.tm_mon, currentTime.tm_mday ) import time def showPingMessage(): print(\u0026#34;observe scheduled task\u0026#34;) print(\u0026#34;{:04d}/{:02d}/{:02d} {:02d}:{:02d}:{:02d}\u0026#34;.format( time.localtime().tm_year, time.localtime().tm_mon, time.localtime().tm_mday, time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec )) print() showPingMessage Job のスクリプトをリファクタした 実装があまり適当すぎて何度も関数を呼び出すようになっていたので、変数に結果をまとめてその結果を利用して情報を表示するように修正した。\n修正前 import time def showPingMessage(): print(\u0026#34;observe scheduled task\u0026#34;) print(\u0026#34;{:04d}/{:02d}/{:02d} {:02d}:{:02d}:{:02d}\u0026#34;.format( time.localtime().tm_year, time.localtime().tm_mon, time.localtime().tm_mday, time.localtime().tm_hour, time.localtime().tm_min, time.localtime().tm_sec )) print() 修正後 import time def showPingMessage(): print(\u0026#34;observe scheduled task\u0026#34;) current = time.localtime() print(\u0026#34;{:04d}/{:02d}/{:02d} {:02d}:{:02d}:{:02d}\u0026#34;.format( current.tm_year, current.tm_mon, current.tm_mday, current.tm_hour, current.tm_min, current.tm_sec )) print() フロントエンドをちょっとだけ修正 enum的なことができることが分かり、影響が小さいところからリファクタをちょっとだけした。\n変更前の例 (src/modules/MainUI/UIparts/messageBox.tsx) ... export interface aMessageBox{ title : string, message : string, type : string, // 直接何でも文字列が入っていしまうため、バグの温床になる。 UUID : string } ... 変更後の例 (src/modules/MainUI/UIparts/messageBox.tsx) ... export interface aMessageBox{ title : string, message : string, type : \u0026#34;error\u0026#34; | \u0026#34;ok\u0026#34; | \u0026#34;warning\u0026#34; | \u0026#34;info\u0026#34;, UUID : string } ... フロントエンドにコマンドテスターを追加した 手動でコマンド要求を作り、どんな応答が帰ってくるかテストできるようにした。 フロントエンドにおいて、旧来の実装のnetwork.tsxにあるsend関数の廃止 すべてのコマンド要求をする部分を、useNetworkStore内部のsend関数に置き換え、旧来のsend関数はコメントアウトして利用できないようにし、廃止した。\n卒論を書いた ページについて具体的な説明を書いた ページの削除について具体的な説明を書いた。 コマンドと割り込みについて、通信という視点から、どのように動作するのか書いた。 図表番号や頭文字の調整を行った。図表のスタイルもなるべく統一する方向性とした。 フロントエンドが、JSONのコマンド要求をDataServerに送るまでの間にある再送ロジックなどについて図を作り、説明を書いた。 アーキテクチャの変遷について考察に書いた。 ページの削除機能について変遷を考察に書いた。 UnixTimeとYYYY/MM/DDの表現形式を比べて、UnixTimeが実装としては都合が良いことについて、考察に書いた。 添付ファイルについて、考察の部分を書き足した。 使ったツールの章において、その経緯を校正し、新しく書き直した。 参考にしたサイトとか PyFormat: Using % and .format() for great good!\nhttps://pyformat.info/ (2026年1月1日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2026-1-8/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2025/12/25 から、2026/1/8 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/WhereIstumbled/2026-1-8/2026-01-8%e3%81%ae%e8%a8%98%e9%8c%b2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2026/1/8 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2026/1/8-やったことリスト"},{"content":"この記事を作った動機 2026/1/8 から、2026/1/15 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 今回は特に大きな変化はないので特になし。\nTODOs TODOs 2026/1/15 になる間やる項目たち。やりきれなかった分は次に持ち越し。\nメイン（持ち越し、新規混合） バックエンドの実装 ターゲット層を明確にする ネットワーク監視について実装を思いついた案に基づいて進める バックエンドの設定についてフロントエンドにUIを設けたい 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える フロントエンドのネットワーク周り useDatabaseStoreをuseNetworkStoreに名前を変更する。 send関数をuseDatabaseStore（useNetworkStore）内にあるものに置き換え、旧来のsend関数の実装を廃止する。 createPage.tsxの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。 free ページの実装 フロントエンド 共通のUIについて、使い方の説明について、ドキュメントを書いた。 overlayWindow messagebox toolsbar page 実際に変更があったら、変更内容をリアルタイムで保存するようにする。 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める セーブする際に、ページのUUIDが一致するか確かめてからセーブする。 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。 アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。 リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。 Metadata を表示できるようにする Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。 とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できるpropertiesとは独立して、commonsの一部として実装する。 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; padStart commonsが正しく色を更新できないバグを何とかする。 z-index をちゃんと更新するようにする useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。 どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。 範囲選択の実装 -\u0026gt; activeItemsを操作する 編集機能、データセーブ（更新）の実装 free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。 バックエンド割り込みの実装 updatePageの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める updatePageがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る データサーバのupdatePageコマンドのUUID検証ロジックについて正しく機能しているか調べる。 データサーバの実装 addTag deleteTag コマンドの実装 queryTag コマンドの実装 前回からの持ち越し 持ち越し分 内部構造を説明する図とかドキュメントを作る\nフロントエンド drawio で説明する図を作る 他人が構造の理解に必要な分を記録できたか バックエンド(更新) 新たに追加した、task の仕組みについて、ドキュメントを整備する。 フロントエンドを拡張するうえで重要そうな zustand のデータストアの仕様リストを作り、記録を行う。 OverlayWindow において、リサイズやサイズ制限をオプションで付ける。デフォルトでは無効にして、とりあえず selector においてそれが機能するようにする。\n全体的な未保存、保存、バッファーの管理について考える\npageType などは現状のままで、増やさず、free と markdown に専念する\ntasks -\u0026gt; jobs で定期的に実行されるバックエンドの関数群において、pageCleaner.py を実装する。各ノートにある、参照が消され、deleted.json に記録されていて、一定期間たったページを時期が来たら本当にファイルシステム上から削除する実装をする。コード自体は、tasks.py の設定に依存し、現状では10秒ごとに消す時が来ていないかポーリングする簡易的な実装である。\n再接続機能が正しく機能しない場合を検証する\nWebSokcet が正常に閉じられなかった場合、自動的にそれを検出して再接続するようにフロントエンドを改修する。 WebSocket が正常に閉じられていないとき、誤作動を起こす件について、データサーバ側を改修することで、ある程度改善を行った。再接続機能改善の試みを詳細は参考にすること。 except asyncio.CancelledError が usernameLoop 内で機能していない可能性について調べる。 実はなんか思ってるのと違う WebSocket の閉じ方をしているかもしれないことについて調べる。 opening handshake failed Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 138, in parse request_line = yield from parse_line(read_line) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 309, in parse_line line = yield from read_line(MAX_LINE_LENGTH) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\streams.py\u0026#34;, line 46, in read_line raise EOFError(f\u0026#34;stream ends after {p} bytes, before end of line\u0026#34;) EOFError: stream ends after 0 bytes, before end of line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\server.py\u0026#34;, line 545, in parse request = yield from Request.parse( ^^^^^^^^^^^^^^^^^^^^^^^^^ File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\http11.py\u0026#34;, line 140, in parse raise EOFError(\u0026#34;connection closed while reading HTTP request line\u0026#34;) from exc EOFError: connection closed while reading HTTP request line The above exception was the direct cause of the following exception: Traceback (most recent call last): File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 356, in conn_handler await connection.handshake( File \u0026#34;C:\\Users\\username\\AppData\\Roaming\\Python\\Python312\\site-packages\\websockets\\asyncio\\server.py\u0026#34;, line 207, in handshake raise self.protocol.handshake_exc websockets.exceptions.InvalidMessage: did not receive a valid HTTP request 他の事項 File API 周りの実装 マルチメディアの対応 selector を複数ページ選択に対応させる タグ機能を機能するようにする バックエンド側のコマンドを整備 フロントエンド側がコマンドを実行するようにする 割り込みの実装を定義して tag に変更があったことを通知するようにする やったことの詳細 卒論を書いた 削除ロジックについて説明する図を追加した 考察についてHTTPサーバに関することについて、フロントエンド、添付ファイル、コマンドの三つのキーワードについて書いた フロントエンドの通信ロジックについての欠陥が考察されていなかったので、破棄されるコマンド要求について今後の課題を書き、実装面の抽象化不足についても書いた 羅列になっているところを箇条書きに書き換えることで、体裁を調整した。 markdown、freeページについてフロントエンドの説明を追加した。 JSONやmarkdown形式の採用経緯に関連することについて、考察に書いた。 概要を書いた。 参考にしたサイトとか 今回は特になし\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2026-1-15/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/1/8 から、2026/1/15 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e　今回は特に大きな変化はないので特になし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eTODOs\u003c/summary\u003e\n  \u003cp\u003e　2026/1/15 になる間やる項目たち。やりきれなかった分は次に持ち越し。\u003c/p\u003e\n\u003ch3 id=\"メイン持ち越し新規混合\"\u003eメイン（持ち越し、新規混合）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eバックエンドの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ターゲット層を明確にする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ネットワーク監視について実装を思いついた案に基づいて進める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e バックエンドの設定についてフロントエンドにUIを設けたい\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 全体的なページやノートブックのメタデータなどにおける時間の扱いを全部 UnixTime の秒単位に置き換える\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンドのネットワーク周り\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003euseDatabaseStore\u003c/code\u003eを\u003ccode\u003euseNetworkStore\u003c/code\u003eに名前を変更する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003esend\u003c/code\u003e関数を\u003ccode\u003euseDatabaseStore\u003c/code\u003e（\u003ccode\u003euseNetworkStore\u003c/code\u003e）内にあるものに置き換え、旧来の\u003ccode\u003esend\u003c/code\u003e関数の実装を廃止する。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecreatePage.tsx\u003c/code\u003eの実装で、ページタイプを取得するとネットワーク周りがバグってリクエストした履歴が消えない結果、未接続の状態として判定されてしまうというバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e フロントエンド\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 共通のUIについて、使い方の説明について、ドキュメントを書いた。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e overlayWindow\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e messagebox\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e toolsbar\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e page\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 実際に変更があったら、変更内容をリアルタイムで保存するようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 別のページを開いたときとかに、バグって変なタイミングでデータを保存しようとするのを止める\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e セーブする際に、ページのUUIDが一致するか確かめてからセーブする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 書式設定に関する edit toggleable を作る。文章をどこに寄せるかとか、フォントサイズとか、フォントカラーとかそういう細かい設定ができるようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e アイテムが何もないページにおいて、アイテムの追加時に、どんなアイテムタイプが利用可能か取得するのに失敗するのをどうにかする。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e リアルタイムセーブがバグることについて調査する。別のページを開いたとき、Freeページコンポーネント自体やその変数の中身が、どういう状態になっているのかを調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Metadata を表示できるようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e Free ページの要素について、基本要素の項目にアイテムの色をRGBAで設定できるようにする。\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e とりあえず、まだ色を変更するUIがないが、RGBAとしてCSSスタイルを設定してアイテムごとの色を反映するようにFreeページの実装を更新はした。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 色を設定するUIや項目へのアクセスボタンを実装する。 -\u0026gt; すべてのアイテム共通の設定項目であるため、汎用に設定項目を表示できる\u003ccode\u003eproperties\u003c/code\u003eとは独立して、\u003ccode\u003ecommons\u003c/code\u003eの一部として実装する。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 設定UIで色の一部が正しく表示できていないバグをなおす。 -\u0026gt; \u003ccode\u003epadStart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003ecommons\u003c/code\u003eが正しく色を更新できないバグを何とかする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e z-index をちゃんと更新するようにする\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e useFreePageItemsStore の items や activeItems の配列をページごとに分離して管理するようにする。\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どうしてもzustandを使ったグローバルなアイテム管理が暴走する場合は、Freeコンポーネント内部でアイテムを管理するように実装を変更する。 -\u0026gt; とりあえず zustand を使った実装で続行。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 範囲選択の実装 -\u0026gt; activeItemsを操作する\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 編集機能、データセーブ（更新）の実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページにおいて、保存が成功するまでは、変更があってから保存されるまでの間に、バッファーを保持するようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e バックエンド割り込みの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eの割り込みがあった時に、どのページがセーブされたかIDをUUIDをデータとして含める\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003ccode\u003eupdatePage\u003c/code\u003eがあったら差分を扱えるように、先にセーブされたデータをバッファーにためるようにして、diffをマージできるようにする\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバに接続されているかどうかなどの、ステータスインジゲーターを作る\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの\u003ccode\u003eupdatePage\u003c/code\u003eコマンドの\u003ccode\u003eUUID\u003c/code\u003e検証ロジックについて正しく機能しているか調べる。\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバの実装\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e addTag deleteTag コマンドの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e queryTag コマンドの実装\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"前回からの持ち越し\"\u003e前回からの持ち越し\u003c/h3\u003e\n\u003ch4 id=\"持ち越し分\"\u003e持ち越し分\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 内部構造を説明する図とかドキュメントを作る\u003c/p\u003e","title":"2026/1/15-やったことリスト"},{"content":"この記事を作った動機 2026/1/15 から、2026/1/22 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n動作の様子 今回は特に大きな変化はないので特になし。\nTODOs 今は実装には手を出さないようにしているので、特になし。\nやったことの詳細 卒論を書いた 誤字脱字の修正 冗長な表現を削除 修正案の反映 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/2026-1-22/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/1/15 から、2026/1/22 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cp\u003e　今回は特に大きな変化はないので特になし。\u003c/p\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\u003cp\u003e　今は実装には手を出さないようにしているので、特になし。\u003c/p\u003e\n\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003ch3 id=\"卒論を書いた\"\u003e卒論を書いた\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e誤字脱字の修正\u003c/li\u003e\n\u003cli\u003e冗長な表現を削除\u003c/li\u003e\n\u003cli\u003e修正案の反映\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は特になし。\u003c/p\u003e","title":"2026/1/22-やったことリスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 どういう使い方が考えられるか、私が考えている理想や他にも考えられる用途などの視点から、書いてみるとなんかいいことあるかもしれないと思って、とりあえずまずは記事を作った。\n考えられる使い方 私の理想としての視点 他の考えられる用途 参考にしたサイトとか 今のところ特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/usecase/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　どういう使い方が考えられるか、私が考えている理想や他にも考えられる用途などの視点から、書いてみるとなんかいいことあるかもしれないと思って、とりあえずまずは記事を作った。\u003c/p\u003e\n\u003ch2 id=\"考えられる使い方\"\u003e考えられる使い方\u003c/h2\u003e\n\u003ch3 id=\"私の理想としての視点\"\u003e私の理想としての視点\u003c/h3\u003e\n\u003ch3 id=\"他の考えられる用途\"\u003e他の考えられる用途\u003c/h3\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今のところ特になし。\u003c/p\u003e","title":"考えられる利用例"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 ある程度調査が終わった時に、出てきた不満点についてまとめるためのページで、現時点では調査が終わってないので、何も書かれていません。\n方針をとにかくまずは実装してみるということに変えたので、ここは中途半端になるかもしれません。（2025/9/8)\nいろいろ比較 onenote googlekeep obsidian 見えてきた理想 UI/UX（フロントエンド） バックエンド データ管理 API処理 アーキテクチャ 拡張機能の構成 参考にしたサイトとか ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/issues/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003eある程度調査が終わった時に、出てきた不満点についてまとめるためのページで、現時点では調査が終わってないので、何も書かれていません。\u003c/del\u003e\u003c/p\u003e\n\u003cp\u003e　方針をとにかくまずは実装してみるということに変えたので、ここは中途半端になるかもしれません。（2025/9/8)\u003c/p\u003e\n\u003ch2 id=\"いろいろ比較\"\u003eいろいろ比較\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eonenote\u003c/li\u003e\n\u003cli\u003egooglekeep\u003c/li\u003e\n\u003cli\u003eobsidian\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"見えてきた理想\"\u003e見えてきた理想\u003c/h2\u003e\n\u003ch3 id=\"uiuxフロントエンド\"\u003eUI/UX（フロントエンド）\u003c/h3\u003e\n\u003ch3 id=\"バックエンド\"\u003eバックエンド\u003c/h3\u003e\n\u003ch4 id=\"データ管理\"\u003eデータ管理\u003c/h4\u003e\n\u003ch4 id=\"api処理\"\u003eAPI処理\u003c/h4\u003e\n\u003ch3 id=\"アーキテクチャ\"\u003eアーキテクチャ\u003c/h3\u003e\n\u003ch3 id=\"拡張機能の構成\"\u003e拡張機能の構成\u003c/h3\u003e\n\u003ch3\u003e\u003c/h3\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e","title":"問題点というか不満点のまとめ"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 主に問題点というか不満点のまとめがまとめ終わった後に具体的にどうしていくか記録するために作ったページです。\n状況に応じてまだ問題点というか不満点のまとめの記事がある程度出来上がってない段階でも、思ったことがあればここにいろいろ書いていこうとは思っています。\nリポジトリ TODOs main (firstprototype) フロントエンド 接続が途切れたことを検出しネットワーク再接続機能 free ページを実装する ノートブック、ページの追加、削除ボタンの実装 ページ view の実装 ページを編集可能にする実装 メッセージボックスの実装 markdown 表示、編集できる既存のライブラリをフロントエンド向けに探す-\u0026gt;\nmarked バックエンド データサーバからフロントエンドへの通信を実装 コマンドを実装 設定画面をつくる (settings.json tkinter) 記録 typescript における type と interface の違いについて書く。 休止 TODOs 調査 OneNote について調査する Obsidian について調査する Google Keep について調査する Notion について調査する ink API の各ブラウザ間の動作の調査 指針を立てるためのまとめ 取り入れたいことについて、調査をもとにまとめる 不満点について、調査をもとにまとめる 大まかに何をするのか決めていく 最小のデモの要件を作る どんなUI? どんなアーキテクチャ? 何をして、何をしないか？ Proof of Concept を作る どんなデモを作るか決める 参考にしたサイトとか markedjs/marked: A markdown parser and compiler. Built for speed.\nhttps://github.com/markedjs/marked (2025年9月26日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/milestone/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　主に\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/issues/\"\u003e問題点というか不満点のまとめ\u003c/a\u003eがまとめ終わった後に具体的にどうしていくか記録するために作ったページです。\u003c/p\u003e\n\u003cp\u003e　状況に応じてまだ\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/issues/\"\u003e問題点というか不満点のまとめ\u003c/a\u003eの記事がある程度出来上がってない段階でも、思ったことがあればここにいろいろ書いていこうとは思っています。\u003c/p\u003e\n\u003ch2 id=\"リポジトリ\"\u003eリポジトリ\u003c/h2\u003e\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/hello30190f/OneNoteAlternative\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"todos\"\u003eTODOs\u003c/h2\u003e\n\u003ch3 id=\"main-firstprototype\"\u003emain (firstprototype)\u003c/h3\u003e\n\u003ch4 id=\"フロントエンド\"\u003eフロントエンド\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 接続が途切れたことを検出しネットワーク再接続機能\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e free ページを実装する\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ノートブック、ページの追加、削除ボタンの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ページ view の実装\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e ページを編集可能にする実装\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e メッセージボックスの実装\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e markdown 表示、編集できる既存のライブラリをフロントエンド向けに探す-\u0026gt;\u003cbr\u003e\n　\u003ca href=\"https://github.com/markedjs/marked\"\u003emarked\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"バックエンド\"\u003eバックエンド\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e データサーバからフロントエンドへの通信を実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e コマンドを実装\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 設定画面をつくる (settings.json tkinter)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"記録\"\u003e記録\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e typescript における \u003ccode\u003etype\u003c/code\u003e と \u003ccode\u003einterface\u003c/code\u003e の違いについて書く。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"休止-todos\"\u003e休止 TODOs\u003c/h2\u003e\n\u003ch3 id=\"調査\"\u003e調査\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e OneNote について調査する\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Obsidian について調査する\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Google Keep について調査する\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e \u003cdel\u003eNotion について調査する\u003c/del\u003e\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e ink API の各ブラウザ間の動作の調査\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"指針を立てるためのまとめ\"\u003e指針を立てるためのまとめ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 取り入れたいことについて、調査をもとにまとめる\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 不満点について、調査をもとにまとめる\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 大まかに何をするのか決めていく\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"最小のデモの要件を作る\"\u003e最小のデモの要件を作る\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どんなUI?\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e どんなアーキテクチャ?\u003c/li\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e 何をして、何をしないか？\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"proof-of-concept-を作る\"\u003eProof of Concept を作る\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput disabled=\"\" type=\"checkbox\"\u003e どんなデモを作るか決める\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003emarkedjs/marked: A markdown parser and compiler. Built for speed.\u003cbr\u003e\n\u003ca href=\"https://github.com/markedjs/marked\"\u003ehttps://github.com/markedjs/marked\u003c/a\u003e (2025年9月26日)\u003c/li\u003e\n\u003c/ul\u003e","title":"TODO リスト"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 研究の過程における ChatGPT の利用記録も、Onenote代替品の作成（旧記事）の方においていたので一応専用に記事を分けて作った感じです。\nChatGPT Open as a page Open as a page 参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年6月23日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/chatgpt/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　研究の過程における ChatGPT の利用記録も、\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/onenotealternativecreationold/\"\u003eOnenote代替品の作成（旧記事）\u003c/a\u003eの方においていたので一応専用に記事を分けて作った感じです。\u003c/p\u003e\n\u003ch2 id=\"chatgpt\"\u003eChatGPT\u003c/h2\u003e\n\u003cp\u003e\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/onenoteAlternativeCreation/%e3%82%aa%e3%82%b7%e3%83%ad%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%97%20%e6%b8%ac%e5%ae%9a%e7%b5%90%e6%9e%9c.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/onenoteAlternativeCreation/%e3%82%aa%e3%82%b7%e3%83%ad%e3%82%b9%e3%82%b3%e3%83%bc%e3%83%97%20%e6%b8%ac%e5%ae%9a%e7%b5%90%e6%9e%9c.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/onenoteAlternativeCreation/TODO%e3%82%bf%e3%82%b9%e3%82%af%e7%ae%a1%e7%90%86%e3%81%ae%e3%82%b8%e3%83%ac%e3%83%b3%e3%83%9e.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/onenoteAlternativeCreation/TODO%e3%82%bf%e3%82%b9%e3%82%af%e7%ae%a1%e7%90%86%e3%81%ae%e3%82%b8%e3%83%ac%e3%83%b3%e3%83%9e.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月23日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ChatGPT"},{"content":" このページは、古いです。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 動機 onenoteがプロプライエタリで不自由なので、自分中心の無料の代替品を適当にwebベースで作りたい。\nリポジトリ 現時点でのわかることリスト OneNote OneNote は Office 365などに含まれていて、有償版とMS store からダウンロードできる無償版の2種類がある。無償版はしつこく MS 365 に課金するように催促される。\nwindows 環境であればローカルにデスクトップ版をインストールし、今までのOffice 2021とか、Office 2007みたいに使うこともでき、OneNote も同じ感じである。クラウド機能もあるらしいが、私は大抵のクラウドサービスには否定的で明るくないので、使ったことはない。\n私がOneNoteを使っていたときは、半期ごとにノートを分けて、その中に授業ごとのセクションを作り、ページで細かい授業単位のデータ管理をするという感じであった。\n階層構造の利用例 OneNote利用例 様々な入力やメディアを扱える例 既存の代替っぽいもの(全てはリストアップしていない) Google keep 数カ月ほど使ったことはあるが、使っていくうちに古いメモが下の方に行き、しかも、せっかくメモの付箋を書いたのに、あとから見返さないという問題があった。\n一応メモを色やピン留め、リマインドという形で分類したりできるという機能はある。情報が少ないうちはいいかもしれないが、あまり大規模なことはできないという印象がある。\n逆に言えば、Google keep 的な付箋スタイルUIや機能は、プロジェクト単位での軽いタスクの管理としては、一つありかもしれないあり方ではあった。\n今回のソフトウェア？では、Google keep みたいなUIや機能をもたせた特別な”ページ”をテンプレとして選べて作れ、タスク管理の一助として使えるようにするのはありかもしれない。\n実装としては、ページを拡張できるように色々インタフェースを定義したりAPIを定義したりとかになる気もする。\nEvernote 聞いたことはあるが、使ったことはない。私の印象としては、使うとロックダウンされてしまいそうなので使いたくないという印象だった。\nNotion 一ヶ月ほど使ったことはあるが、AI機能が、意思にかかわらずに有効になっていたり、記録した内容にいちいち”良くする”というスタンスで干渉してくるところが嫌であった。\nかつ、クラウドベースで、オフラインやローカル、LAN内だけで完結するインターネットのない環境で、プライベートに完結することを許さない感じが、どこか監視されているようで閉塞的でかなり息苦しいと感じられる。\n既存の代替品の候補としてよく挙げられるツールの共通点 商業ベース クラウド ローカルで動かすことを前提としてない クラウドベースだとAIモデルの学習にデータが使われてしまう可能性 最初は無料としつつも、あとからしつこく課金させるビジネスモデルへの誘導がある可能性 クラウド系だとサービスが潰れたとき、データ消失、非互換の恐れ ある程度包括的にOneNoteの機能を持っているものはなく、いくつかの独自の設計や思想に基づいたものが乱立している印象 OneNote の機能 階層的な管理 Office 系列と似たような書式フォーマットや操作 自由なオブジェクトの配置 ポイント サーバクライアントモデル\nUI 処理をするクライアント（クライアント側） OS依存のAPIや実装のためのバックエンド（クライアント側） データ関連のバックエンド（サーバー側） P2P オープンなデータ構造\nJSON や XML などをサポートしたい human readable な仕様にしたい 大きなバイナリデータとかはどうするかが課題 それについては、Unityみたいにディレクトリ構造を形成して管理してみてもいいかもしれない。 拡張可能\nテキストや画像、インクオブジェクトだけでなく、独自のバイナリ構造を持つファイルや、独自のガジェットやオブジェクト的なものも扱えるように、機能を追加できる仕様にしたい。\n基本的なアーキテクチャ x11みたいなサーバークライアントモデルな構造にしたい。\nフロントエンド chromeやfirefoxなどのブラウザ、Electornなどを使う。vite,react,typescriptとかだと比較的モダンに仕上がると思う。\nバックエンド 適当にpythonとかphpでもいいので、データ処理とOS固有のAPIの抽象化と呼び出しを担う\n基本的なデータ構造 ノート構造 Notebooks Section Pages1 Pages2 \u0026hellip; ページ構造 基本的には、汎用の位置情報などを保持するオブジェクトが定義され、それを継承することで、テキストや画像、動画、PDF、インク、3D view(include pmx and blender ext files -\u0026gt; three.js) バイナリデータなどをそれぞれ専用のクラスを用意し、扱う。\n基本的なUI機能や入力など ファイルのドラックアンドドロップ 貼り付け、コピー InkAPI マウス、キーボード、タッチ 複数ウィンドウ ChatGPT Open as a page Open as a page カバー画像のリンク Microsoft Corporation, Public domain, via Wikimedia Commons Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月23日) Download - Obsidian\nhttps://obsidian.md/download (2025年7月19日) Best Microsoft OneNote Alternatives in 2025 | Nuclino\nhttps://www.nuclino.com/alternatives/onenote-alternative (2025年7月19日) Best 6 OneNote Alternatives In 2025 | 100+ Personally Tested Tools\nhttps://thebusinessdive.com/onenote-alternatives (2025年7月19日) 最高のノートアプリ - Evernoteでノートを整理しましょう\nhttps://evernote.com/ja-jp (2025年7月19日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/onenotealternativecreationold/","summary":"\u003cdiv class=\"annotationContainer oldArticle\" href=/posts/idea/research/onenoteAlternativeCreation/\u003e\n    \u003cdiv class=\"annotationbanner column\"\u003e\n        \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n            \u003cimg class=\"oldArticleYukkuri\" src=\"/icons/yukkuri/掃除をするゆっくり.png\"\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"row\"\u003e\n            \u003cimg class=\"oldArticleIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n            \u003ch2\u003eこのページは、古いです。。。\u003c/h2\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"動機\"\u003e動機\u003c/h2\u003e\n\u003cp\u003eonenoteがプロプライエタリで不自由なので、自分中心の無料の代替品を適当にwebベースで作りたい。\u003c/p\u003e\n\u003ch2 id=\"リポジトリ\"\u003eリポジトリ\u003c/h2\u003e\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/hello30190f/OneNoteAlternative\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"現時点でのわかることリスト\"\u003e現時点でのわかることリスト\u003c/h2\u003e\n\u003ch3 id=\"onenote\"\u003eOneNote\u003c/h3\u003e\n\u003cp\u003e　OneNote は Office 365などに含まれていて、有償版とMS store からダウンロードできる無償版の2種類がある。無償版はしつこく MS 365 に課金するように催促される。\u003c/p\u003e\n\u003cp\u003e　windows 環境であればローカルにデスクトップ版をインストールし、今までのOffice 2021とか、Office 2007みたいに使うこともでき、OneNote も同じ感じである。クラウド機能もあるらしいが、私は大抵のクラウドサービスには否定的で明るくないので、使ったことはない。\u003c/p\u003e\n\u003cp\u003e　私がOneNoteを使っていたときは、半期ごとにノートを分けて、その中に授業ごとのセクションを作り、ページで細かい授業単位のデータ管理をするという感じであった。\u003c/p\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e9%9a%8e%e5%b1%a4%e6%a7%8b%e9%80%a0%e3%81%ae%e5%88%a9%e7%94%a8%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            階層構造の利用例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/OneNote%e5%88%a9%e7%94%a8%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            OneNote利用例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/onenoteAlternativeCreation/oneNote/%e6%a7%98%e3%80%85%e3%81%aa%e5%85%a5%e5%8a%9b%e3%82%84%e3%83%a1%e3%83%87%e3%82%a3%e3%82%a2%e3%82%92%e6%89%b1%e3%81%88%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"OneNote サンプル\"/\u003e \u003cfigcaption\u003e\n            様々な入力やメディアを扱える例\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"既存の代替っぽいもの全てはリストアップしていない\"\u003e既存の代替っぽいもの(全てはリストアップしていない)\u003c/h3\u003e\n\u003ch4 id=\"google-keep\"\u003eGoogle keep\u003c/h4\u003e\n\u003cp\u003e　数カ月ほど使ったことはあるが、使っていくうちに古いメモが下の方に行き、しかも、せっかくメモの付箋を書いたのに、あとから見返さないという問題があった。\u003c/p\u003e\n\u003cp\u003e　一応メモを色やピン留め、リマインドという形で分類したりできるという機能はある。情報が少ないうちはいいかもしれないが、あまり大規模なことはできないという印象がある。\u003c/p\u003e\n\u003cp\u003e　逆に言えば、Google keep 的な付箋スタイルUIや機能は、プロジェクト単位での軽いタスクの管理としては、一つありかもしれないあり方ではあった。\u003c/p\u003e\n\u003cp\u003e　今回のソフトウェア？では、Google keep みたいなUIや機能をもたせた特別な”ページ”をテンプレとして選べて作れ、タスク管理の一助として使えるようにするのはありかもしれない。\u003c/p\u003e\n\u003cp\u003e　実装としては、ページを拡張できるように色々インタフェースを定義したりAPIを定義したりとかになる気もする。\u003c/p\u003e\n\u003ch4 id=\"evernote\"\u003eEvernote\u003c/h4\u003e\n\u003cp\u003e　聞いたことはあるが、使ったことはない。私の印象としては、使うとロックダウンされてしまいそうなので使いたくないという印象だった。\u003c/p\u003e\n\u003ch4 id=\"notion\"\u003eNotion\u003c/h4\u003e\n\u003cp\u003e　一ヶ月ほど使ったことはあるが、AI機能が、意思にかかわらずに有効になっていたり、記録した内容にいちいち”良くする”というスタンスで干渉してくるところが嫌であった。\u003c/p\u003e\n\u003cp\u003e　かつ、クラウドベースで、オフラインやローカル、LAN内だけで完結するインターネットのない環境で、プライベートに完結することを許さない感じが、どこか監視されているようで閉塞的でかなり息苦しいと感じられる。\u003c/p\u003e\n\u003ch3 id=\"既存の代替品の候補としてよく挙げられるツールの共通点\"\u003e既存の代替品の候補としてよく挙げられるツールの共通点\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e商業ベース\u003c/li\u003e\n\u003cli\u003eクラウド\u003c/li\u003e\n\u003cli\u003eローカルで動かすことを前提としてない\u003c/li\u003e\n\u003cli\u003eクラウドベースだとAIモデルの学習にデータが使われてしまう可能性\u003c/li\u003e\n\u003cli\u003e最初は無料としつつも、あとからしつこく課金させるビジネスモデルへの誘導がある可能性\u003c/li\u003e\n\u003cli\u003eクラウド系だとサービスが潰れたとき、データ消失、非互換の恐れ\u003c/li\u003e\n\u003cli\u003eある程度包括的にOneNoteの機能を持っているものはなく、いくつかの独自の設計や思想に基づいたものが乱立している印象\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"onenote-の機能\"\u003eOneNote の機能\u003c/h2\u003e\n\u003ch3 id=\"階層的な管理\"\u003e階層的な管理\u003c/h3\u003e\n\u003ch3 id=\"office-系列と似たような書式フォーマットや操作\"\u003eOffice 系列と似たような書式フォーマットや操作\u003c/h3\u003e\n\u003ch3 id=\"自由なオブジェクトの配置\"\u003e自由なオブジェクトの配置\u003c/h3\u003e\n\u003ch2 id=\"ポイント\"\u003eポイント\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eサーバクライアントモデル\u003c/p\u003e","title":"Onenote代替品の作成（旧記事）"},{"content":"この記事を作った動機 Google-Chrome を開発用に使っており、裏でデバックをするための実装をしていたところ、Chromeがデバッグモードとして上手く動作しないことが分かったので簡易的なメモが欲しい。\n問題点 Linux 環境にて、単にローカルホストにデバックソケットを立てるように指示するだけでは不十分で、Chromeがデバックモードで立ち上がらない。すでにすべてのChromeインスタンスをpkill chromeなどで完全に排除した状態から始めて、その症状が再現する。\ngoogle-chrome-stable --remote-debugging-port=5588 対処 プロファイルの情報を保存するディレクトリを指定すると、デバックモードとして立ち上がった。以下はLinux環境向けの例であり、各自どのディレクトリにプロファイルを保存するかはOSなどに合わせて合わせる必要がある。\ngoogle-chrome-stable --remote-debugging-port=5588 --user-data-dir=\u0026#34;/tmp/chrome_debug\u0026#34; 利便性の観点 /tmpはLinuxでRAM上に作成される起動時に一時的に確保されるディスク領域であり、再起動したりすると内容が消える。Guestモードに近い使い方をしたいときに有効であるが、それだといちいちブラウザを一番最初に起動した扱いとなり、初期セットアップのWindowsでいうところのOOBEみたいなのが出てきてしまう。そこで以下のオプションを指定することでそれらを抑制し、すぐにブラウザが使えるようにできる。\n# --no-first-run --no-default-browser-check google-chrome-stable --remote-debugging-port=5588 --user-data-dir=\u0026#34;/tmp/chrome_debug\u0026#34; --no-first-run --no-default-browser-check Chrome がデバッグモードで動いているかの検証方法 以下のURLにFirefoxなどの別のブラウザでアクセスし、JSON応答が帰ってくるか確かめる。帰ってこない場合、Chromeがデバッグモードで起動していないか、ポートが衝突しているなどのネットワーク上の不具合である可能性がある。\nhttp://127.0.0.1:5555/json/version 参考にしたサイトとか Access local servers and Chrome instances with port forwarding | Chrome DevTools | Chrome for Developers\nhttps://developer.chrome.com/docs/devtools/remote-debugging/local-server/ (2026年10月30日) Gemma-4-31B (ローカルLLM) (2026年10月30日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/openchromewithdebugmode/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Google-Chrome を開発用に使っており、裏でデバックをするための実装をしていたところ、Chromeがデバッグモードとして上手く動作しないことが分かったので簡易的なメモが欲しい。\u003c/p\u003e\n\u003ch2 id=\"問題点\"\u003e問題点\u003c/h2\u003e\n\u003cp\u003e　Linux 環境にて、単にローカルホストにデバックソケットを立てるように指示するだけでは不十分で、Chromeがデバックモードで立ち上がらない。すでにすべてのChromeインスタンスを\u003ccode\u003epkill chrome\u003c/code\u003eなどで完全に排除した状態から始めて、その症状が再現する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egoogle-chrome-stable --remote-debugging-port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5588\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"対処\"\u003e対処\u003c/h2\u003e\n\u003cp\u003e　プロファイルの情報を保存するディレクトリを指定すると、デバックモードとして立ち上がった。以下はLinux環境向けの例であり、各自どのディレクトリにプロファイルを保存するかはOSなどに合わせて合わせる必要がある。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egoogle-chrome-stable --remote-debugging-port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5588\u003c/span\u003e --user-data-dir\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/tmp/chrome_debug\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"利便性の観点\"\u003e利便性の観点\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003e/tmp\u003c/code\u003eはLinuxでRAM上に作成される起動時に一時的に確保されるディスク領域であり、再起動したりすると内容が消える。Guestモードに近い使い方をしたいときに有効であるが、それだといちいちブラウザを一番最初に起動した扱いとなり、初期セットアップのWindowsでいうところのOOBEみたいなのが出てきてしまう。そこで以下のオプションを指定することでそれらを抑制し、すぐにブラウザが使えるようにできる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# --no-first-run --no-default-browser-check\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egoogle-chrome-stable --remote-debugging-port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5588\u003c/span\u003e --user-data-dir\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/tmp/chrome_debug\u0026#34;\u003c/span\u003e --no-first-run --no-default-browser-check\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"chrome-がデバッグモードで動いているかの検証方法\"\u003eChrome がデバッグモードで動いているかの検証方法\u003c/h2\u003e\n\u003cp\u003e　以下のURLにFirefoxなどの別のブラウザでアクセスし、JSON応答が帰ってくるか確かめる。帰ってこない場合、Chromeがデバッグモードで起動していないか、ポートが衝突しているなどのネットワーク上の不具合である可能性がある。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ehttp://127.0.0.1:5555/json/version\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAccess local servers and Chrome instances with port forwarding  |  Chrome DevTools  |  Chrome for Developers\u003cbr\u003e\n\u003ca href=\"https://developer.chrome.com/docs/devtools/remote-debugging/local-server/\"\u003ehttps://developer.chrome.com/docs/devtools/remote-debugging/local-server/\u003c/a\u003e (2026年10月30日)\u003c/li\u003e\n\u003cli\u003eGemma-4-31B (ローカルLLM) (2026年10月30日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Google-Chrome をデバックモードで開き、ローカルホスト上で待機させたい"},{"content":"この記事を作った動機 パッケージマネージャである pacman あたりが作るキャッシュが肥大化していき、数十~数百GB程度ディスクを食らって容量不足になることがあるので、それに対処するメモが欲しい。\nなんかこの手の話はよく忘れている。\n内容 sudo pacman -Sc # yay -Sc 参考にしたサイトとか pacman - ArchWiki\nhttps://wiki.archlinux.org/title/Pacman#Cleaning_the_package_cache (2026年10月27日) ","permalink":"https://www.nyanmo.info/posts/linux/pacmancachedelete/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　パッケージマネージャである pacman あたりが作るキャッシュが肥大化していき、数十~数百GB程度ディスクを食らって容量不足になることがあるので、それに対処するメモが欲しい。\u003c/p\u003e\n\u003cp\u003e　なんかこの手の話はよく忘れている。\u003c/p\u003e\n\u003ch2 id=\"内容\"\u003e内容\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo pacman -Sc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# yay -Sc\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003epacman - ArchWiki\u003cbr\u003e\n\u003ca href=\"https://wiki.archlinux.org/title/Pacman#Cleaning_the_package_cache\"\u003ehttps://wiki.archlinux.org/title/Pacman#Cleaning_the_package_cache\u003c/a\u003e (2026年10月27日)\u003c/li\u003e\n\u003c/ul\u003e","title":"pacman のパッケージキャッシュ削除"},{"content":"この記事を作った動機 2026/10/21 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 前回記述したことと同上。\nまだやれていないこと マルチプロセッシングライブラリにおけるIPC 実装を小さなプロジェクトを作って体験する 実験した後の内容はすべてgithubに一つのリポジトリとして上げる 拡張モジュールのバリデーション実装 モジュールの引数確認 引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか) エラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか その他 割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。 フロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。 フロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。 pexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で watch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot; のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。 データサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。 各拡張機能が設定を持てるように実装する。 拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。 以下の LLM が吐き出したコードについて調べる。 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- やったことの詳細 何も研究に関しては今週進んでいないので研究に関しては特になし。今週は一回ですべての評価が決まる発表の授業があり、その準備で燃え尽きすぎたため、休養を優先した。\n研究に関係ありそうなブログ記事 何も研究に関しては今週進んでいないので特になし。\n参考にしたサイトとか 何も研究に関しては今週進んでいないので特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-10-21/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/10/21 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　前回記述したことと同上。\u003c/p\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eまだやれていないこと\u003c/summary\u003e\n  \u003ch3 id=\"マルチプロセッシングライブラリにおけるipc\"\u003eマルチプロセッシングライブラリにおけるIPC\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e実装を小さなプロジェクトを作って体験する\u003c/li\u003e\n\u003cli\u003e実験した後の内容はすべてgithubに一つのリポジトリとして上げる\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"拡張モジュールのバリデーション実装\"\u003e拡張モジュールのバリデーション実装\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eモジュールの引数確認\u003c/li\u003e\n\u003cli\u003e引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか)\u003c/li\u003e\n\u003cli\u003eエラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"その他\"\u003eその他\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。\u003c/li\u003e\n\u003cli\u003eフロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。\u003c/li\u003e\n\u003cli\u003eフロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。\u003c/li\u003e\n\u003cli\u003epexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で \u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003e のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。\u003c/li\u003e\n\u003cli\u003eデータサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。\u003c/li\u003e\n\u003cli\u003e各拡張機能が設定を持てるように実装する。\u003c/li\u003e\n\u003cli\u003e拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。\u003c/li\u003e\n\u003cli\u003e以下の LLM が吐き出したコードについて調べる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e __future__ \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e annotations\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e typing \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e TYPE_CHECKING\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(TYPE_CHECKING):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e controller.common \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e commandModuleArgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2026/10/21-やったこと"},{"content":"この記事を作った動機 2026/10/14 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 前回記述したことと同上。\nまだやれていないこと マルチプロセッシングライブラリにおけるIPC 実装を小さなプロジェクトを作って体験する 実験した後の内容はすべてgithubに一つのリポジトリとして上げる 拡張モジュールのバリデーション実装 モジュールの引数確認 引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか) エラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか その他 割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。 フロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。 フロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。 pexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で watch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot; のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。 データサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。 各拡張機能が設定を持てるように実装する。 拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。 以下の LLM が吐き出したコードについて調べる。 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- やったことの詳細 何も研究に関しては今週進んでいないので研究に関しては特になし。まだ授業の方が落ち着いておらず、今週は燃え尽きすぎたため、休養を優先した。\n研究に関係ありそうなブログ記事 Inputタグにて、zustandのストアを正しく更新したり、ユーザーの入力を正しく受け付けることができない 参考にしたサイトとか 何も研究に関しては今週進んでいないので特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-10-14/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/10/14 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　前回記述したことと同上。\u003c/p\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eまだやれていないこと\u003c/summary\u003e\n  \u003ch3 id=\"マルチプロセッシングライブラリにおけるipc\"\u003eマルチプロセッシングライブラリにおけるIPC\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e実装を小さなプロジェクトを作って体験する\u003c/li\u003e\n\u003cli\u003e実験した後の内容はすべてgithubに一つのリポジトリとして上げる\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"拡張モジュールのバリデーション実装\"\u003e拡張モジュールのバリデーション実装\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eモジュールの引数確認\u003c/li\u003e\n\u003cli\u003e引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか)\u003c/li\u003e\n\u003cli\u003eエラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"その他\"\u003eその他\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。\u003c/li\u003e\n\u003cli\u003eフロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。\u003c/li\u003e\n\u003cli\u003eフロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。\u003c/li\u003e\n\u003cli\u003epexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で \u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003e のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。\u003c/li\u003e\n\u003cli\u003eデータサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。\u003c/li\u003e\n\u003cli\u003e各拡張機能が設定を持てるように実装する。\u003c/li\u003e\n\u003cli\u003e拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。\u003c/li\u003e\n\u003cli\u003e以下の LLM が吐き出したコードについて調べる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e __future__ \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e annotations\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e typing \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e TYPE_CHECKING\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(TYPE_CHECKING):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e controller.common \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e commandModuleArgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2026/10/14-やったこと"},{"content":"この記事を作った動機 React + Zustand + TypeScirpt の組み合わせで、Input タグにて躓いたことがあったので記録したい。具体的な症状としては、要素の内容を変更しようとしても、一切微動だにせず、値を変えることができないという症状がある。\n問題の挙動 期待する挙動 問題が起こったコード 問題がない部分 // ... \u0026lt;LabelTextEntryItem name=\u0026#34;IP / URL\u0026#34; callback={(resultString:string) =\u0026gt; { setNetwork((prev) =\u0026gt; ({ ...prev, IPorDomainName: resultString })) }} init={getNetwork().IPorDomainName} \u0026gt;\u0026lt;/LabelTextEntryItem\u0026gt; // ... 問題がある部分 // ... export function LabelTextEntryItem({ name , init , callback}:{ name:string, init:string , callback:(result:string) =\u0026gt; void }){ return \u0026lt;div className=\u0026#34;flex flex row mb-4\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label text-xl noSelect\u0026#34;\u0026gt;{name}:\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;ml-auto\u0026#34;\u0026gt; \u0026lt;HoverAnimation\u0026gt; // 問題の箇所 -------------------- // 問題の箇所 -------------------- \u0026lt;input className=\u0026#34;ml-auto text-xl w-30\u0026#34; id=\u0026#34;entry\u0026#34; value={init} type=\u0026#34;text\u0026#34; onChange={(event:ChangeEvent\u0026lt;HTMLInputElement\u0026gt;) =\u0026gt; { callback(event.target.value) }}\u0026gt;\u0026lt;/input\u0026gt; // 問題の箇所 -------------------- // 問題の箇所 -------------------- \u0026lt;/HoverAnimation\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; } // ... 解決に至った方法 問題が再現する条件として、Zustandで定義したストアの内容をInputタグにて表示するときにvalueの引数としてそれを指定していることがある。解決のためには、defaultValueとしてZustand内の内容を表示するようにすることで解決された。なぜこれで症状が解決するのかは分かってない。コンソールでコールバックが呼ばれたときの内容を確認してみたところ、valueとして引数にZustandの内容を与えても、値自体は更新された値がコールバックに正しく伝達できていることが確認でき、コールバック内の値の更新処理が上手くいかない理由が不明である。defaultValueとvalueのinputタグにおける違いとは多分値の拘束力なのではないか？と思われる。valueに固定値を指定してしまうと、編集不能になるとかでもあるのだろうか？\n修正結果 // ... export function LabelTextEntryItem({ name , init , callback}:{ name:string, init:string , callback:(result:string) =\u0026gt; void }){ return \u0026lt;div className=\u0026#34;flex flex row mb-4\u0026#34;\u0026gt; \u0026lt;div className=\u0026#34;label text-xl noSelect\u0026#34;\u0026gt;{name}:\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;ml-auto\u0026#34;\u0026gt; \u0026lt;HoverAnimation\u0026gt; // 問題の箇所 -------------------- // 問題の箇所 -------------------- \u0026lt;input className=\u0026#34;ml-auto text-xl w-30\u0026#34; id=\u0026#34;entry\u0026#34; defaultValue={init} type=\u0026#34;text\u0026#34; onChange={(event:ChangeEvent\u0026lt;HTMLInputElement\u0026gt;) =\u0026gt; { callback(event.target.value) }}\u0026gt;\u0026lt;/input\u0026gt; // 問題の箇所 -------------------- // 問題の箇所 -------------------- \u0026lt;/HoverAnimation\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; } // ... 試したこと 「defaultValueとvalueのinputタグにおける違いとは多分値の拘束力なのではないか？と思われる。valueに固定値を指定してしまうと、編集不能になるとかでもあるのだろうか？」という疑問があり、以下のような要素を対応する実験として試したところ、問題の挙動にて示した症状が再現することが分かった。\n\u0026lt;input type=\u0026#34;text\u0026#34; value={\u0026#34;afdsdf\u0026#34;}\u0026gt;\u0026lt;/input\u0026gt; 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/webdevelop/react/unabletoupdatevaluewithinputtagelement/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　React + Zustand + TypeScirpt の組み合わせで、Input タグにて躓いたことがあったので記録したい。具体的な症状としては、要素の内容を変更しようとしても、一切微動だにせず、値を変えることができないという症状がある。\u003c/p\u003e\n\u003ch3 id=\"問題の挙動\"\u003e問題の挙動\u003c/h3\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/webDevelop/react/unableToUpdateValueWithInputTagElement/%e5%be%ae%e5%8b%95%e3%81%a0%e3%81%ab%e3%81%97%e3%81%aa%e3%81%84%e4%be%8b.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch3 id=\"期待する挙動\"\u003e期待する挙動\u003c/h3\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/webDevelop/react/unableToUpdateValueWithInputTagElement/%e6%a9%9f%e8%83%bd%e3%81%99%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e4%be%8b.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"問題が起こったコード\"\u003e問題が起こったコード\u003c/h2\u003e\n\u003ch3 id=\"問題がない部分\"\u003e問題がない部分\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003eLabelTextEntryItem\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;IP / URL\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{(\u003cspan style=\"color:#a6e22e\"\u003eresultString\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003esetNetwork\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003eprev\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e ({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        ...\u003cspan style=\"color:#a6e22e\"\u003eprev\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#a6e22e\"\u003eIPorDomainName\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eresultString\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003egetNetwork\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003eIPorDomainName\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eLabelTextEntryItem\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"問題がある部分\"\u003e問題がある部分\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eLabelTextEntryItem\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e , \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e , \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e}\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e{ \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e , \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e }){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex flex row mb-4\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;label text-xl noSelect\u0026#34;\u003c/span\u003e\u0026gt;{\u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e}\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ml-auto\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003eHoverAnimation\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 問題の箇所 --------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 問題の箇所 --------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026lt;\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ml-auto text-xl w-30\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;entry\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonChange\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eChangeEvent\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eHTMLInputElement\u003c/span\u003e\u0026gt;) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etarget\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }}\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 問題の箇所 --------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 問題の箇所 --------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eHoverAnimation\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// ...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"解決に至った方法\"\u003e解決に至った方法\u003c/h2\u003e\n\u003cp\u003e　問題が再現する条件として、Zustandで定義したストアの内容をInputタグにて表示するときに\u003ccode\u003evalue\u003c/code\u003eの引数としてそれを指定していることがある。解決のためには、\u003ccode\u003edefaultValue\u003c/code\u003eとしてZustand内の内容を表示するようにすることで解決された。なぜこれで症状が解決するのかは分かってない。コンソールでコールバックが呼ばれたときの内容を確認してみたところ、\u003ccode\u003evalue\u003c/code\u003eとして引数にZustandの内容を与えても、値自体は更新された値がコールバックに正しく伝達できていることが確認でき、コールバック内の値の更新処理が上手くいかない理由が不明である。\u003ccode\u003edefaultValue\u003c/code\u003eと\u003ccode\u003evalue\u003c/code\u003eのinputタグにおける違いとは多分値の拘束力なのではないか？と思われる。valueに固定値を指定してしまうと、編集不能になるとかでもあるのだろうか？\u003c/p\u003e","title":"Inputタグにて、zustandのストアを正しく更新したり、ユーザーの入力を正しく受け付けることができない"},{"content":"この記事を作った動機 Linux 環境ばっかりで SSH を使っていて、今まで Windows 環境では SSH クライアントは使ったことがあっても、SSH サーバーは使ったことがないということがあり、慣れていないところがあったので記録をしたい。主に、How to Enable and Configure SSH Server on Windows with OpenSSH | Windows OS Hub参考にした。\n設定としては、パスワード認証は許可せず、全て公開鍵認証をさせるようにしている。そのため、クライアントにて SSH 接続用の公開鍵を作成し、その公開鍵の部分を SSH サーバーとなる Windows 機にて設定する必要がある。基本的に設定は全体として管理者権限を付与して行っていることを前提とする。\n手順 OpenSSH をインストールする Releases · PowerShell/Win32-OpenSSHによりインストーラをダウンロードし、実行する。インストールされているときと、されていないときで、sshd(SSH サーバ) の設定ファイルが存在するかどうかが変わる。 インストールされていないとき ls C:\\Programdata\\ssh\\sshd_config # ls : パス \u0026#39;C:\\Programdata\\ssh\\sshd_config\u0026#39; が存在しないため検出できません。 # 発生場所 行:1 文字:1 # + ls C:\\Programdata\\ssh\\sshd_config # + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + CategoryInfo : ObjectNotFound: (C:\\Programdata\\ssh\\sshd_config:String) [Get-ChildItem], ItemNotFoundException # + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand インストールされているとき ls C:\\Programdata\\ssh\\sshd_config # # ディレクトリ: C:\\Programdata\\ssh # # Mode LastWriteTime Length Name # ---- ------------- ------ ---- # -a---- 2025/10/22 19:12 2230 sshd_config OpenSSH を設定する エディタはなんでもいいが、とにかくC:\\Programdata\\ssh\\sshd_configを開いて編集する。管理者権限が必要である。設定内容は各自調整が必要である。以下は簡易的にテスト用に用意した設定であり、適切ではないと思われる。\ncode C:\\Programdata\\ssh\\sshd_config # ルート（管理者権限を持ったアカウント）でログインさせない PermitRootLogin no # 公開鍵によるユーザ認証を許可する PubkeyAuthentication yes # パスワードによるユーザ認証は許可しない PasswordAuthentication no # キーボードインタラクティブによる認証を許可しない KbdInteractiveAuthentication no # OpenSSH(Win版) ダウンロード時にデフォルトで有効になっている設定である。 # 管理者アカウントをOpenSSHデフォルトの設定で管理する場合、クライアントの公開鍵のパスは以下のようになる # __PROGRAMDATA__/ssh/administrators_authorized_keys # C:\\ProgramData\\ssh\\administrators_authorized_keys # 管理者アカウントであってもユーザー配下のホームディレクトリに公開鍵の設定を配置したい場合、以下の記述を削除するとできる。できれば避けたほうがいいかもしれない。 Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys OpenSSH のサービスを有効化する Windows 版 Systemd のようなコマンドを操作する。管理者権限が必要である。\nコマンドライン (PowerShell) # 起動時に自動的に SSH サーバーが立ち上がるようにする set-service sshd -StartupType Automatic # 初回起動時 start-service sshd # 設定を反映するために再起動する restart-service sshd # 起動している様子を確認する get-service # Status Name DisplayName # ------ ---- ----------- # Running sshd OpenSSH SSH Server # SSH サーバーをを停止する stop-service sshd GUI サービスなどと検索して管理画面を開き、設定を行う。 ファイヤウォールを設定する SSH 接続ができるようにファイヤウォールに穴をあける(ポート開放)の設定が必要である。この操作をする際は PC が接続されている LAN などが安全であることを確認する必要がある。例えば、グローバルネットワーク(インターネット)に直接如何なるファイヤウォールとかもなしにつながっている PC 等では、設定を突き詰める必要があり、攻撃対象となりやすくセキュリティーの観点から推奨できないように見受けられる。\nOpenSSH をインストールした時点ですでに有効(疎通ができる状態)になっている場合もあるようである。\nSSH の公開鍵を登録する 注意事項として、Windows で管理者アカウントに対しては SSH したい場合、ユーザアカウントのホームディレクトリ配下ではなく、専用の決められた場所に公開鍵を保存する必要がある。ここでいう公開鍵とは、**SSH 接続をするクライアント(接続元)**となる PC 上においてあらかじめ生成しておいた公開鍵と秘密鍵のペアのうちの、秘密鍵ではないほうのことである。\nユーザ配下に配置される SSH サーバーの公開鍵設定の場所 # [UserName] は適宜置き換えること C:\\Users\\[UserName]\\.ssh\\authorized_keys Administrators グループに属しているアカウントにおける SSH サーバーの公開鍵設定の場所 C:\\ProgramData\\ssh\\administrators_authorized_keys 登録する公開鍵の例 (ファイル名に.pubとついているもの) 以下のような内容を登録する。間違っていると認証が通らない。以下は例示として一部を改変したものである。 # \u0026#34;...\u0026#34; の部分は省略を意味する ssh-ed25519 AAA...PLdz [ユーザ名]@[ホスト名] SSH 接続を行う 前提条件 管理者アカウントに SSH でログインしようとしている SSH クライアント(接続元) と SSH サーバー(接続先) 同一の LAN など、同じネットワークに属していること SSH のクライアントとサーバーとなる PC 間において、Ping などの疎通確認ができていること SSH 接続するユーザ名を test とする 接続の様子 SSH サーバーとなる Win 機において、IP アドレスを確認 ipconfig # Windows IP 構成 # # イーサネット アダプター イーサネット: # # 接続固有の DNS サフィックス . . . . .: example.com # リンクローカル IPv6 アドレス. . . . .: # IPv4 アドレス . . . . . . . . . . . .: 192.168.1.35 # サブネット マスク . . . . . . . . . .: 255.255.255.0 # デフォルト ゲートウェイ . . . . . . .: 192.168.1.1 アカウント名を確認 whoami [PCのホスト名]\\test SSH クライアントとなる PC からアクセスを試みる ssh test@192.168.1.35 Microsoft Windows [Version 10.0.26200.9457] (c) Microsoft Corporation. All rghts reserved. test@[PCのホスト名] C:\\Users\\test\u0026gt;exit Connection to 133.54.220.136 closed. おまけ(躓いたこと) Ping が通らない Windows 機に対して Ping をすることで疎通確認したいとき、以下の項目を許可するだけでは Ping が通らないことがあることが分かった。ファイヤウォール設定の開き方はファイヤウォールを設定するを参照すること。 追加で以下の項目も有効にしたところ Ping が通るようになった。セキュリティー上の懸念がある場合は、必要な時以外は無効化することが考えられる。 SSH 接続できない 今回の場合は、管理者権限を持つアカウントの場合authorized_keysの配置が通常とは異なり、sshd_configを以下のようにしている場合(OpenSSH デフォルト)、専用の場所に保存されていることが問題の背景としてあった。修正としては、ユーザのホームディレクトリではなく、専用の場所に公開鍵を正しく配置することが必要である。\n# ... Match Group administrators AuthorizedKeysFile __PROGRAMDATA__/ssh/administrators_authorized_keys # ... ユーザ配下に配置される SSH サーバーの公開鍵設定の場所 # [UserName] は適宜置き換えること C:\\Users\\[UserName]\\.ssh\\authorized_keys Administrators グループに属しているアカウントにおける SSH サーバーの公開鍵設定の場所 C:\\ProgramData\\ssh\\administrators_authorized_keys 確認したほうがよさそうなファイヤウォール設定 Windows では、ネットワークをパブリックとプライベートの2つに分けて設定を使い分けられるようになっている。接続がうまくいかない場合、SSH サーバーとしている Win 機のネットワーク接続設定にて既存の接続をプライベート扱いにすることによって信頼するように設定したり、以下の画像に示すようなファイヤウォールの設定を追加でした方がよいかもしれない。\n関係ありそうな記事 ssh サーバ (sshd) の設定のメモ 使った画像とか OAOV, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Windows_logo_-_2021.svg (2026年10月9日) OpenSSH\nhttps://www.openssh.org/ (2026年10月9日) Windows 7 (Vista) のシステムアイコン (2026年10月9日) PC のアイコン ノートPCのアイコン 鍵のアイコン ハブのアイコン 参考にしたサイトとか How to Enable and Configure SSH Server on Windows with OpenSSH | Windows OS Hub\nhttps://woshub.com/connect-to-windows-via-ssh/ (2026年10月9日)\nGet started with OpenSSH Server for Windows | Microsoft Learn\nhttps://learn.microsoft.com/en-us/windows-server/administration/openssh/openssh_install_firstuse?tabs=gui\u0026amp;pivots=windows-server-2025 (2026年10月9日)\nOpenSSH Server Configuration for Windows | Microsoft Learn\nhttps://learn.microsoft.com/en-us/windows-server/administration/OpenSSH/openssh-server-configuration (2026年10月9日)\nReleases · PowerShell/Win32-OpenSSH\nhttps://github.com/PowerShell/Win32-OpenSSH/releases/ (2026年10月9日)\nHow to Allow Ping (ICMP Echo Requests) on Windows Firewall\nhttps://theitbros.com/allow-ping-icmp-echo-requests-on-windows-firewall/ (2026年10月9日)\n","permalink":"https://www.nyanmo.info/posts/windows/sshdserversetup/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Linux 環境ばっかりで SSH を使っていて、今まで Windows 環境では SSH クライアントは使ったことがあっても、SSH サーバーは使ったことがないということがあり、慣れていないところがあったので記録をしたい。主に、\u003ca href=\"https://woshub.com/connect-to-windows-via-ssh/\"\u003eHow to Enable and Configure SSH Server on Windows with OpenSSH | Windows OS Hub\u003c/a\u003e参考にした。\u003c/p\u003e\n\u003cp\u003e　設定としては、パスワード認証は許可せず、全て公開鍵認証をさせるようにしている。そのため、クライアントにて SSH 接続用の公開鍵を作成し、その公開鍵の部分を SSH サーバーとなる Windows 機にて設定する必要がある。基本的に設定は全体として管理者権限を付与して行っていることを前提とする。\u003c/p\u003e\n\u003ch2 id=\"手順\"\u003e手順\u003c/h2\u003e\n\u003ch3 id=\"openssh-をインストールする\"\u003eOpenSSH をインストールする\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://github.com/PowerShell/Win32-OpenSSH/releases/\"\u003eReleases · PowerShell/Win32-OpenSSH\u003c/a\u003eによりインストーラをダウンロードし、実行する。インストールされているときと、されていないときで、sshd(SSH サーバ) の設定ファイルが存在するかどうかが変わる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/sshdServerSetup/%e3%83%80%e3%82%a6%e3%83%b3%e3%83%ad%e3%83%bc%e3%83%89.png#center\"\n         alt=\"ダウンロード\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eインストールされていないとき\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003els C:\\Programdata\\ssh\\sshd_config\n# ls : パス \u0026#39;C:\\Programdata\\ssh\\sshd_config\u0026#39; が存在しないため検出できません。\n# 発生場所 行:1 文字:1\n# + ls C:\\Programdata\\ssh\\sshd_config\n# + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n#     + CategoryInfo          : ObjectNotFound: (C:\\Programdata\\ssh\\sshd_config:String) [Get-ChildItem], ItemNotFoundException\n#     + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eインストールされているとき\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e ls C:\\Programdata\\ssh\\sshd_config\n# \n#     ディレクトリ: C:\\Programdata\\ssh\n# \n# Mode                 LastWriteTime         Length Name\n# ----                 -------------         ------ ----\n# -a----        2025/10/22     19:12           2230 sshd_config\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"openssh-を設定する\"\u003eOpenSSH を設定する\u003c/h3\u003e\n\u003cp\u003e　エディタはなんでもいいが、とにかく\u003ccode\u003eC:\\Programdata\\ssh\\sshd_config\u003c/code\u003eを開いて編集する。管理者権限が必要である。設定内容は各自調整が必要である。以下は簡易的にテスト用に用意した設定であり、適切ではないと思われる。\u003c/p\u003e","title":"SSH サーバーを Windows 上で構成する (Ping が Windows 機に通らない時の対応についても記述)"},{"content":"この記事を作った動機 2026/10/7 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 前回記述したことと同上。\nまだやれていないこと マルチプロセッシングライブラリにおけるIPC 実装を小さなプロジェクトを作って体験する 実験した後の内容はすべてgithubに一つのリポジトリとして上げる 拡張モジュールのバリデーション実装 モジュールの引数確認 引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか) エラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか その他 割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。 フロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。 フロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。 pexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で watch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot; のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。 データサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。 各拡張機能が設定を持てるように実装する。 拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。 以下の LLM が吐き出したコードについて調べる。 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- やったことの詳細 何も研究に関しては今週進んでいないので研究に関しては特になし。授業のオリエンテーションや多くの例外的なイベントがあり、今週は燃え尽きすぎたため、休養を優先した。\n研究に関係ありそうなブログ記事 何も研究に関しては今週進んでいないので特になし。\n参考にしたサイトとか 何も研究に関しては今週進んでいないので特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-10-7/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/10/7 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　前回記述したことと同上。\u003c/p\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eまだやれていないこと\u003c/summary\u003e\n  \u003ch3 id=\"マルチプロセッシングライブラリにおけるipc\"\u003eマルチプロセッシングライブラリにおけるIPC\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e実装を小さなプロジェクトを作って体験する\u003c/li\u003e\n\u003cli\u003e実験した後の内容はすべてgithubに一つのリポジトリとして上げる\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"拡張モジュールのバリデーション実装\"\u003e拡張モジュールのバリデーション実装\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eモジュールの引数確認\u003c/li\u003e\n\u003cli\u003e引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか)\u003c/li\u003e\n\u003cli\u003eエラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"その他\"\u003eその他\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。\u003c/li\u003e\n\u003cli\u003eフロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。\u003c/li\u003e\n\u003cli\u003eフロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。\u003c/li\u003e\n\u003cli\u003epexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で \u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003e のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。\u003c/li\u003e\n\u003cli\u003eデータサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。\u003c/li\u003e\n\u003cli\u003e各拡張機能が設定を持てるように実装する。\u003c/li\u003e\n\u003cli\u003e拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。\u003c/li\u003e\n\u003cli\u003e以下の LLM が吐き出したコードについて調べる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e __future__ \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e annotations\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e typing \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e TYPE_CHECKING\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(TYPE_CHECKING):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e controller.common \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e commandModuleArgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2026/10/7-やったこと"},{"content":"この記事を作った動機 2026/9/30 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 マルチプロセッシングライブラリにおけるIPC 実装を小さなプロジェクトを作って体験する 実験した後の内容はすべてgithubに一つのリポジトリとして上げる 拡張モジュールのバリデーション実装 モジュールの引数確認 引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか) エラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか まだやれていないこと その他 割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。 フロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。 フロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。 pexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で watch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot; のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。 データサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。 各拡張機能が設定を持てるように実装する。 拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。 以下の LLM が吐き出したコードについて調べる。 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- やったことの詳細 pexpect の問題 研究で使っている pexpect が win ではそのまま動作しないことが分かった。pexpect を使ったコードを動かそうとしたところ、以下のようになりそもそも動かなかった。調べてみると、pexpect は Unix 系のOSでしか使えず、wexpectなるライブラリを windows では代替で使う必要があることが分かった。\npython main.py REM Traceback (most recent call last): REM File \u0026#34;C:\\Users\\userName\\work\\Modular-MCP-Server\\main.py\u0026#34;, line 2, in \u0026lt;module\u0026gt; REM from common import pexpectExecuteCommand,executeCommand,pexpectForceUpdate,waitForever REM File \u0026#34;C:\\Users\\userName\\work\\Modular-MCP-Server\\common.py\u0026#34;, line 8, in \u0026lt;module\u0026gt; REM def pexpectExecuteCommand(session:pexpect.spawn,command:str,timeout = 1,expect:str=\u0026#34;.+\u0026#34;) -\u0026gt; None: REM ^^^^^^^^^^^^^ REM AttributeError: module \u0026#39;pexpect\u0026#39; has no attribute \u0026#39;spawn\u0026#39; 研究に関係ありそうなブログ記事 今回は特になし。\n参考にしたサイトとか python - pexpect AttributeError: \u0026lsquo;module\u0026rsquo; object has no attribute \u0026lsquo;spawn\u0026rsquo; - Stack Overflow\nhttps://stackoverflow.com/questions/59308566/pexpect-attributeerror-module-object-has-no-attribute-spawn (2026年9月30日)\nInstallation — Pexpect 4.8 documentation\nhttps://pexpect.readthedocs.io/en/stable/install.html (2026年9月30日)\npython - Windows alternative to pexpect - Stack Overflow\nhttps://stackoverflow.com/questions/38976893/windows-alternative-to-pexpect (2026年9月30日)\nwexpect · PyPI\nhttps://pypi.org/project/wexpect/ (2026年9月30日)\nAnnotations Best Practices — Python 3.14.7 documentation\nhttps://docs.python.org/3/howto/annotations.html (2026年9月30日)\ntyping — Support for type hints — Python 3.14.7 documentation\nhttps://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING (2026年9月30日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-9-30/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/9/30 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003ch3 id=\"マルチプロセッシングライブラリにおけるipc\"\u003eマルチプロセッシングライブラリにおけるIPC\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e実装を小さなプロジェクトを作って体験する\u003c/li\u003e\n\u003cli\u003e実験した後の内容はすべてgithubに一つのリポジトリとして上げる\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"拡張モジュールのバリデーション実装\"\u003e拡張モジュールのバリデーション実装\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eモジュールの引数確認\u003c/li\u003e\n\u003cli\u003e引数の使用方法確認 (不正なプロパティへのアクセスが無いかとか)\u003c/li\u003e\n\u003cli\u003eエラー時と通常時でそれぞれすべての場合にレスポンスが実装されているか\u003c/li\u003e\n\u003c/ul\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eまだやれていないこと\u003c/summary\u003e\n  \u003ch3 id=\"その他\"\u003eその他\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。\u003c/li\u003e\n\u003cli\u003eフロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。\u003c/li\u003e\n\u003cli\u003eフロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。\u003c/li\u003e\n\u003cli\u003epexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で \u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003e のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。\u003c/li\u003e\n\u003cli\u003eデータサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。\u003c/li\u003e\n\u003cli\u003e各拡張機能が設定を持てるように実装する。\u003c/li\u003e\n\u003cli\u003e拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。\u003c/li\u003e\n\u003cli\u003e以下の LLM が吐き出したコードについて調べる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e __future__ \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e annotations\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e typing \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e TYPE_CHECKING\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(TYPE_CHECKING):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e controller.common \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e commandModuleArgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2026/9/30-やったこと"},{"content":"この記事を作った動機 最近 SSHFS やら TCP を使った通信において、VPN を経由した通信(ping において time=40ms 前後)が通信経路的には、100Mbps 程度のスループットが出るはずであるが、実際には、10Mbps 程度をうろついてめちゃくちゃに遅いということがあった。その症状はランダムであり、場合によってはそこそこ速度が出る場合もあれば、全然出ない場合もあるということがあった。\n当初は、SoftEther VPN のコネクション数をいじったりしていたが、あまり効果が見られない場合があり、最終的に TCP の輻輳制御などに問題があるのではないかと思った。ただ設定をいちいち細々と調べるのはめんどくさかったので、ローカルのLLMに話題を投げてみたところ、実際に効果が見受けられる設定が出てきたので、それをとりあえず記録しておきたい。\n設定内容 (/etc/sysctl.d/tcp.conf として保存) 以下の設定を/etc/sysctl.d/tcp.confとして保存したあと、既存の TCP コネクションが古い設定で動き続けるのを防ぐため、再起動する。輻輳制御アルゴリズムなどをデフォルトから変更している。\nnet.core.default_qdisc=fq net.ipv4.tcp_congestion_control=bbr net.ipv4.tcp_window_scaling=1 net.core.rmem_max=16777216 net.core.wmem_max=16777216 net.ipv4.tcp_rmem=4096 87380 16777216 net.ipv4.tcp_wmem=4096 65536 16777216 設定が反映されたか確認 sysctl net.core.default_qdisc sysctl net.ipv4.tcp_congestion_control sysctl net.ipv4.tcp_window_scaling sysctl net.core.rmem_max sysctl net.core.wmem_max sysctl net.ipv4.tcp_rmem sysctl net.ipv4.tcp_wmem # net.core.default_qdisc = fq # net.ipv4.tcp_congestion_control = bbr # net.ipv4.tcp_window_scaling = 1 # net.core.rmem_max = 16777216 # net.core.wmem_max = 16777216 # net.ipv4.tcp_rmem = 4096\t87380\t16777216 # net.ipv4.tcp_wmem = 4096\t65536\t16777216 もともとの設定 私の Arch Linux 環境で、インストール時からネットワーク設定に特段変更を加えていない機材から設定を読み出すと以下のような結果が得られた。輻輳制御アルゴリズムがbbrではなくcubicになっていたりするなど、色々設定が異なることがわかる。詳しいことは LLM に提案させて試しただけなので分かっていない。\nnet.core.default_qdisc = fq_codel net.ipv4.tcp_congestion_control = cubic net.ipv4.tcp_window_scaling = 1 net.core.rmem_max = 4194304 net.core.wmem_max = 4194304 net.ipv4.tcp_rmem = 4096\t131072\t33554432 net.ipv4.tcp_wmem = 4096\t16384\t4194304 設定前に見られた挙動 設定前に見られた挙動としては、ファイル転送などにおいて、本来10 MB/s程度の速度が出るところで、1.6 MB/s くらいしか出なかったり、システムモニターでネットワーク通信の速度を監視していると、ノコギリの刃先のように、TCP の制御でウィンドウサイズが大きくなって通信速度が出始めたと思ったら一気に通信速度が落ち込んで下がるといった挙動で安定していなかった。\n今後はこれでしばらく使ってみてパケットロスや速度が落ち込む場合などがないか、様子を見てみようと考えている。\n設定前の様子 設定後の様子 参考にしたサイトとか ローカルLLM (Gemma4-31B) (2026年9月21日) ","permalink":"https://www.nyanmo.info/posts/linux/tcpip/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 SSHFS やら TCP を使った通信において、VPN を経由した通信(ping において time=40ms 前後)が通信経路的には、100Mbps 程度のスループットが出るはずであるが、実際には、10Mbps 程度をうろついてめちゃくちゃに遅いということがあった。その症状はランダムであり、場合によってはそこそこ速度が出る場合もあれば、全然出ない場合もあるということがあった。\u003c/p\u003e\n\u003cp\u003e　当初は、SoftEther VPN のコネクション数をいじったりしていたが、あまり効果が見られない場合があり、最終的に TCP の輻輳制御などに問題があるのではないかと思った。ただ設定をいちいち細々と調べるのはめんどくさかったので、ローカルのLLMに話題を投げてみたところ、実際に効果が見受けられる設定が出てきたので、それをとりあえず記録しておきたい。\u003c/p\u003e\n\u003ch2 id=\"設定内容-etcsysctldtcpconf-として保存\"\u003e設定内容 (\u003ccode\u003e/etc/sysctl.d/tcp.conf\u003c/code\u003e として保存)\u003c/h2\u003e\n\u003cp\u003e　以下の設定を\u003ccode\u003e/etc/sysctl.d/tcp.conf\u003c/code\u003eとして保存したあと、既存の TCP コネクションが古い設定で動き続けるのを防ぐため、再起動する。輻輳制御アルゴリズムなどをデフォルトから変更している。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003enet.core.default_qdisc=fq\nnet.ipv4.tcp_congestion_control=bbr\nnet.ipv4.tcp_window_scaling=1\nnet.core.rmem_max=16777216\nnet.core.wmem_max=16777216\nnet.ipv4.tcp_rmem=4096 87380 16777216\nnet.ipv4.tcp_wmem=4096 65536 16777216\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"設定が反映されたか確認\"\u003e設定が反映されたか確認\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.core.default_qdisc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.ipv4.tcp_congestion_control\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.ipv4.tcp_window_scaling\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.core.rmem_max\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.core.wmem_max\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.ipv4.tcp_rmem\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esysctl net.ipv4.tcp_wmem\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.core.default_qdisc = fq\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.ipv4.tcp_congestion_control = bbr\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.ipv4.tcp_window_scaling = 1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.core.rmem_max = 16777216\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.core.wmem_max = 16777216\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.ipv4.tcp_rmem = 4096\t87380\t16777216\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.ipv4.tcp_wmem = 4096\t65536\t16777216\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"もともとの設定\"\u003eもともとの設定\u003c/h2\u003e\n\u003cp\u003e　私の Arch Linux 環境で、インストール時からネットワーク設定に特段変更を加えていない機材から設定を読み出すと以下のような結果が得られた。輻輳制御アルゴリズムが\u003ccode\u003ebbr\u003c/code\u003eではなく\u003ccode\u003ecubic\u003c/code\u003eになっていたりするなど、色々設定が異なることがわかる。詳しいことは LLM に提案させて試しただけなので分かっていない。\u003c/p\u003e","title":"TCP/IP で高遅延環境で速度を出したい"},{"content":"この記事を作った動機 最近 Mailcow によるメールサーバを使っているが、SOGo という内蔵されたフロントエンドがあり、メール送受信だけでなく、カレンダー機能もついている。これについてタスク管理機能を試したところ、分かりづらいところや不具合があったのでそれに対してどうできるか一例を記録する。\nタスクが登録できない件について 問題の様子 対処 SOGo の設定において、短い日付形式が空だと、日本語の言語設定のとき、フロントエンドのJSがクラッシュしタスクの日付を正しく設定できないことがあることが分かった。そのため、そこを明示することで対処した。 完了したタスクを表示する フィルター設定の中に、日付だけではなく、完了したタスクを表示するかの項目もひとまとまりになっている。その中の項目をスクロールして完了タスクを表示するように選択する。 使った画像とか mailcow: dockerized documentation\nhttps://docs.mailcow.email/ (2026年8月4日) SOGo | Free Open Source Webmail\nhttps://www.sogo.nu/ (2026年9月14日) 関連する記事とか Mailcow を使いたい 参考にしたサイトとか 特になし。\n","permalink":"https://www.nyanmo.info/posts/linux/sogocalenderwontshowcomplatedtask/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 Mailcow によるメールサーバを使っているが、SOGo という内蔵されたフロントエンドがあり、メール送受信だけでなく、カレンダー機能もついている。これについてタスク管理機能を試したところ、分かりづらいところや不具合があったのでそれに対してどうできるか一例を記録する。\u003c/p\u003e\n\u003ch3 id=\"タスクが登録できない件について\"\u003eタスクが登録できない件について\u003c/h3\u003e\n\u003ch4 id=\"問題の様子\"\u003e問題の様子\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e3%82%bf%e3%82%b9%e3%82%af%e7%99%bb%e9%8c%b2%e3%81%8c%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"タスク登録ができない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"対処\"\u003e対処\u003c/h4\u003e\n\u003cp\u003e　SOGo の設定において、\u003ccode\u003e短い日付形式\u003c/code\u003eが空だと、日本語の言語設定のとき、フロントエンドのJSがクラッシュしタスクの日付を正しく設定できないことがあることが分かった。そのため、そこを明示することで対処した。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e8%a8%ad%e5%ae%9a%e7%94%bb%e9%9d%a2%e3%82%92%e9%96%8b%e3%81%8f.png#center\"\n         alt=\"設定画面を開く\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e7%9f%ad%e3%81%84%e6%97%a5%e4%bb%98%e5%bd%a2%e5%bc%8f%e3%81%ae%e8%a8%ad%e5%ae%9a.png#center\"\n         alt=\"短い日付形式の設定\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"完了したタスクを表示する\"\u003e完了したタスクを表示する\u003c/h3\u003e\n\u003cp\u003e　フィルター設定の中に、日付だけではなく、完了したタスクを表示するかの項目もひとまとまりになっている。その中の項目をスクロールして完了タスクを表示するように選択する。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e3%83%95%e3%82%a3%e3%83%ab%e3%82%bf%e3%83%bc%e3%83%9c%e3%82%bf%e3%83%b3.png#center\"\n         alt=\"フィルターボタン\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e6%9c%9f%e9%96%93%e6%8c%87%e5%ae%9a.png#center\"\n         alt=\"期間指定\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/SOGoCalenderWontShowComplatedTask/%e5%ae%8c%e4%ba%86%e3%81%97%e3%81%9f%e3%82%bf%e3%82%b9%e3%82%af%e3%82%82%e8%a1%a8%e7%a4%ba%e3%81%99%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b.png#center\"\n         alt=\"完了したタスクも表示するようにする\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"使った画像とか\"\u003e使った画像とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003emailcow: dockerized documentation\u003cbr\u003e\n\u003ca href=\"https://docs.mailcow.email/\"\u003ehttps://docs.mailcow.email/\u003c/a\u003e (2026年8月4日)\u003c/li\u003e\n\u003cli\u003eSOGo | Free Open Source Webmail\u003cbr\u003e\n\u003ca href=\"https://www.sogo.nu/\"\u003ehttps://www.sogo.nu/\u003c/a\u003e (2026年9月14日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"関連する記事とか\"\u003e関連する記事とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/mailcow/\"\u003eMailcow を使いたい\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　特になし。\u003c/p\u003e","title":"SOGo でタスクが登録できない、未完了タスク以外が見えない"},{"content":"この記事を作った動機 2026/9/16 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。 フロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。 フロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。 pexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で watch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot; のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。 データサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。 各拡張機能が設定を持てるように実装する。 拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。 以下の LLM が吐き出したコードについて調べる。 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- やったことの詳細 現状の動作の様子 現状としてはかろうじて動くという感じでバグや不具合だらけである。DataServer なのか、それとも卒論の試作物で使いまわしているフロントエンドの実装がいけないのか、切り分けがついていないことも多く、しばらくは調査が必要そうである。特にページコントローラ周りが動作が不安定である様相が見受けられる。これは、拡張機能名とUUIDがモジュール名に加えて解決が必要になったことが影響していると考えられる。\n動画中では撮影中に気づいた不具合があり、動揺しているが表示と作ろうとしているページが一致していないことが分かった。これはフロントエンドのif,elseの実装が多分確認がまだできていないが良くない気がしており、未知のページタイプををすべてjsonとして扱うように実装していたのが影響している可能性がある。新しく実装したDataServerが返すページタイプのリストが、今の一時的にあてがっているフロントエンドに適合していないため、色々とそこら辺で不具合が発生しているように思われる。\n拡張機能を導入するためにしたこと モジュールに渡す引数をクラスで共通化して定義 コントローラの引数のモジュール呼び出しの定義を変えると、連動して拡張機能側のモジュールも引数を正しい順番や名前で合わせる必要があり、煩雑になるため、クラスにまとめて小さな変更が大きな影響として波及しにくいようにした。\n主な役割として、mainSystem のサブシステムからモジュールに対して共通して提供する関数群や設定、必要があればフロントエンドとの接続についてなどを保持、伝搬することがある。 実装 class commandModuleArgs: def __init__(self,request:dict,websocket:ServerConnection,Settings:dict) -\u0026gt; None: self.request = request self.websocket = websocket self.settings = Settings self.funcs = { # common lib \u0026#34;showJSONMessage\u0026#34; : showJSONMessage, \u0026#34;dataKeyChecker\u0026#34; : dataKeyChecker, \u0026#34;timeString\u0026#34; : timeString, \u0026#34;findNotes\u0026#34; : findNotes, \u0026#34;checkTheAbsolutePath\u0026#34; : checkTheAbsolutePath, \u0026#34;deleteDataSafely\u0026#34; : deleteDataSafely, \u0026#34;updateNotebookMatadata\u0026#34; : updateNotebookMatadata, \u0026#34;readMetadataFormMarkdownPage\u0026#34; : readMetadataFormMarkdownPage, \u0026#34;mkdir\u0026#34; : mkdir, # access passive controller \u0026#34;callInterrupt\u0026#34; : callInterrupt, \u0026#34;getPageTemplate\u0026#34; : getPageTemplate, \u0026#34;getPageTypeList\u0026#34; : getPageTypeList, # server response \u0026#34;NotImplementedResponse\u0026#34; : NotImplementedResponse, \u0026#34;malformedRequestResponse\u0026#34; : malformedRequestResponse, \u0026#34;internalServerErrorResponse\u0026#34; : internalServerErrorResponse, \u0026#34;notFound\u0026#34; : notFound, \u0026#34;malformedRequestChecker\u0026#34; : malformedRequestChecker, } # def getArgs(self) -\u0026gt; dict: # return { # \u0026#34;request\u0026#34; : self.request, # \u0026#34;websocket\u0026#34; : self.websocket, # \u0026#34;funcs\u0026#34; : self.funcs, # \u0026#34;Settings\u0026#34; : self.settings # } class interruptModuleArgs: def __init__(self,data:dict,websocket:ServerConnection,allWebSocketConnections:list[ServerConnection]) -\u0026gt; None: self.data = data self.mainConnection = websocket self.allConnection = allWebSocketConnections self.funcs = { \u0026#34;sendInterrupt\u0026#34; : sendInterrupt } # def getArgs(self) -\u0026gt; dict: # return { # \u0026#34;data\u0026#34; : self.data, # \u0026#34;mainConnection\u0026#34;: self.mainConnection, # \u0026#34;allConnection\u0026#34; : self.allConnection, # \u0026#34;funcs\u0026#34; : self.funcs # } class pageModuleArgs: def __init__(self,data:dict) -\u0026gt; None: self.data = data self.funcs = { # common lib \u0026#34;showJSONMessage\u0026#34; : showJSONMessage, \u0026#34;dataKeyChecker\u0026#34; : dataKeyChecker, \u0026#34;timeString\u0026#34; : timeString, \u0026#34;findNotes\u0026#34; : findNotes, \u0026#34;checkTheAbsolutePath\u0026#34; : checkTheAbsolutePath, \u0026#34;deleteDataSafely\u0026#34; : deleteDataSafely, \u0026#34;updateNotebookMatadata\u0026#34; : updateNotebookMatadata, \u0026#34;readMetadataFormMarkdownPage\u0026#34; : readMetadataFormMarkdownPage, \u0026#34;mkdir\u0026#34; : mkdir, } # def getArgs(self) -\u0026gt; dict: # return { # \u0026#34;data\u0026#34; : self.data, # \u0026#34;funcs\u0026#34; : self.funcs # } class taskModuleArgs: def __init__(self,Settings:dict) -\u0026gt; None: self.settings = Settings self.funcs = { # common lib \u0026#34;showJSONMessage\u0026#34; : showJSONMessage, \u0026#34;dataKeyChecker\u0026#34; : dataKeyChecker, \u0026#34;timeString\u0026#34; : timeString, \u0026#34;findNotes\u0026#34; : findNotes, \u0026#34;checkTheAbsolutePath\u0026#34; : checkTheAbsolutePath, \u0026#34;deleteDataSafely\u0026#34; : deleteDataSafely, \u0026#34;updateNotebookMatadata\u0026#34; : updateNotebookMatadata, \u0026#34;readMetadataFormMarkdownPage\u0026#34; : readMetadataFormMarkdownPage, \u0026#34;mkdir\u0026#34; : mkdir, } # def getArgs(self) -\u0026gt; dict: # return { # \u0026#34;funcs\u0026#34;: self.funcs # } 定義したクラスに合わせて、拡張機能側のモジュールの引数と内部実装を変更 卒論で作った最初の試作物では、引数が今回の試作物の DataServer のコントローラとそのままでは互換性がないため、それに合わせる変更をした。具体的には、モジュールの引数の変更に加え、mainSysで共通に提供している関数や設定を使うように書き換えた。\nページ新規作成において、テンプレートを司るコントローラについて追記 ページの新規作成のためのテンプレートにもコントローラがあり、動的に動作するようにしていたことが抜け落ちていたため、実装をした。以下は、コントローラの実装である。実際には、以下のコードを書くだけではなく、モジュール間の引数の共通化のためのクラスの定義と、ローダーの対応、拡張機能の実装の変更など広域で多岐にわたる調整を行った。\nfrom controller.runtime import pageExtensionMoludes from controller.common import pageModuleArgs # when return None -\u0026gt; unknown pageType def getPageTemplate(pageType:str,data:dict) -\u0026gt; str | None: for aPageType in pageExtensionMoludes.keys(): if(aPageType == pageType): return pageExtensionMoludes[aPageType](pageModuleArgs(data)) return None def getPageTypeList(): return pageExtensionMoludes.keys() import 文を拡張機能のモジュールの各スクリプトに追加 各拡張機能の、各モジュールの関数の引数は、専用の共通化されたクラスのインスタンスを受け取るようになっており、Python の型チェックを利用するために、Import を追加した。なお以下だと実装として不十分であり、そのままでは循環 Import となって動作しない。型チェックのための-import-が循環参照となってしまう問題について を参照すること。\n# 当初追加していた Import 文。これだと、不十分である。 from controller.common import commandModuleArgs 拡張機能を導入した状態で生じた問題 拡張機能の ZIP ファイル名を変更 当初予定していた[拡張機能名]-[UUID]の名前構文では、問題が生じることが分かった。Python の Import 文において、-は使えないため、その構文だと、Import できないという問題になった。\nそのため、解決策としてまず、以下のように拡張機能の ZIP のディレクトリを構成することで解決しようとした。\n- [拡張機能名を名前に持つフォルダ] - [拡張機能のUUIDを`-`を取り除いて名前に持つフォルダ] - manifest.json など、拡張機能の中身 しかしこれだと今度は、UUID 次第で Import 時に数字が先頭に来てしまい、Import エラーになってしまうことや、拡張機能のフォルダ構成が必要以上に複雑になるという問題があった。\nそこで、現状としては、拡張機能の ZIP の内部ディレクトリを以下のように構成することで、問題を解決とした。zip ファイル名自体は当初と同じ、[拡張機能名]-[UUIDハイフンあり].zipである。\n- [拡張機能名とUUIDを合わせて名前に持つフォルダ] - manifest.json など、拡張機能の中身 この解決策には制約があり、拡張機能名は、先頭に特殊文字や数字を含むことができないということになり、Python の Import 文に命名規則が制約される点がある。\n型チェックのための Import が循環参照となってしまう問題について 拡張機能モジュールで型チェックのためにインポートする記述が、mainSystem サブシステムにおいて循環参照の問題になる可能性があることが分かった。現状では、LLM が出した案が動いておりそれを採用しているが、そもそもなぜ循環参照になったのか、今後それが起こるリスクについてはどうなのかについて、十分説明がついていない。\n現状の理解では、以下のように記述することで、インポートしたモジュールなどが、型チェックのためのアノテーションとして使われ、直接関数を呼び出したりクラスをインスタンス化するなどといったことには使われていないことを明記するということかな？という感じである。\n現状の記述例 ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- from __future__ import annotations from typing import TYPE_CHECKING if(TYPE_CHECKING): from controller.common import commandModuleArgs ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- ## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 ------- async def template(moduleArgs:commandModuleArgs): # TODO: write command name # ... 循環参照になり mainSys が立ち上がらない例 python -u main.py # Traceback (most recent call last): # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/main.py\u0026#34;, line 5, in \u0026lt;module\u0026gt; # from controller.command import init as command # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/command.py\u0026#34;, line 5, in \u0026lt;module\u0026gt; # from controller.runtime import commandExtensionMoludes # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/runtime.py\u0026#34;, line 11, in \u0026lt;module\u0026gt; # from Core589fe65d639c42a3b395fca2143afd75.backend.commands.notebookAndPage.createNotebook import createNotebook # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/extensions/runtime/Core589fe65d639c42a3b395fca2143afd75/backend/commands/notebookAndPage/createNotebook.py\u0026#34;, line 1, in \u0026lt;module\u0026gt; # from controller.common import commandModuleArgs # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/common.py\u0026#34;, line 4, in \u0026lt;module\u0026gt; # from controller.interrupt import callInterrupt # File \u0026#34;/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/interrupt.py\u0026#34;, line 6, in \u0026lt;module\u0026gt; # from controller.runtime import interruptExtensionMoludes # ImportError: cannot import name \u0026#39;interruptExtensionMoludes\u0026#39; from partially initialized module \u0026#39;controller.runtime\u0026#39; (most likely due to a circular import) (/home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/runtime.py) その他 各コントローラにおいて、解決が失敗した場合にエラーを出すのではなく、Core拡張機能として暗黙に扱いそれで解決されるか試してからエラーを出すようにした。以下はその実装の一部の例である。CoreExtPrefixの中身は、Core-589fe65d-639c-42a3-b395-fca2143afd75/となっている。\nasync def callInterrupt(websocket:ServerConnection,interruptName:str,data:dict): from controller.common import interruptModuleArgs, CoreExtPrefix from controller.runtime import interruptExtensionMoludes for AnInterrupt in interruptExtensionMoludes.keys(): if(AnInterrupt == interruptName): return await interruptExtensionMoludes[AnInterrupt](interruptModuleArgs(data,websocket,websocketConnections)) elif(AnInterrupt == CoreExtPrefix + interruptName): return await interruptExtensionMoludes[AnInterrupt](interruptModuleArgs(data,websocket,websocketConnections)) print(\u0026#34;callInterrupt ERROR: The interrupt does not exist.\u0026#34;) return True またこのことから、いちいち名前を UUID まで含めて解決するのは実装として大変すぎる気がしたので以下のような階層を設定したいと構想することがあった。\nモジュール名だけで解決 拡張機能名とモジュール名で解決 拡張機能名とモジュール名と拡張機能のUUIDで解決 この階層設定の問題点としては、コマンドなどを呼び出すフロントエンドの実装をどうするかということである。基本的には、拡張機能名もUUIDも必要としないと、拡張機能間でモジュール名が重複したり、拡張機能名が重複したりしたときにモジュールを解決できないことになる。\nモジュールの呼び出し自体をよりフロントエンドにおいても共通化する必要性が考えられる。DataServer での暗黙の自動解決は、Core 拡張機能までとして、他の拡張機能に対しては、常にモジュール名だけではなく、モジュールが属している拡張機能名や拡張機能UUIDをセットにするようにし、上記の三段階はフロントエンド側の実装で解決することも考えられる。\n研究に関係ありそうなブログ記事とか hello30190f/Modular-MCP-Server\nhttps://github.com/hello30190f/Modular-MCP-Server (2026年9月15日) 参考にしたサイトとか Core pexpect components — Pexpect 4.8 documentation\nhttps://pexpect.readthedocs.io/en/stable/api/pexpect.html (2026年9月13日)\ntyping — Support for type hints — Python 3.14.7 documentation\nhttps://docs.python.org/3/library/typing.html#typing.TYPE_CHECKING (2026年9月15日)\nPython Circular Imports - GeeksforGeeks\nhttps://www.geeksforgeeks.org/python/python-circular-imports/ (2026年9月15日)\nHow to avoid circular imports in Python? - Stack Overflow\nhttps://stackoverflow.com/questions/7336802/how-to-avoid-circular-imports-in-python (2026年9月15日)\nLLM on DuckDuckGo (ChatGPT) (2026年9月15日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-9-16/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/9/16 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e割り込みの呼び出しが、コマンドモジュールから、コマンドコントローラのプロセスを介して、割り込みのプロセスへ IPC するようにする。\u003c/li\u003e\n\u003cli\u003eフロントエンドの割り込みの実装を今の試作物の DataServer に適合させる。\u003c/li\u003e\n\u003cli\u003eフロントエンドが DataServer の拡張機能読込み時に HTML CSS JS としてビルドされて配置され、それがホスティングされるようにデータサーバを実装する。\u003c/li\u003e\n\u003cli\u003epexpect のログをファイルシステム上の位置を決めてテキストファイルとしてそれぞれ書き出すようにし、ユーザーにはそれを独立した端末で \u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003e のようにして動いている様子が確認できるようにする。できれば各コントローラやホスティングのプロセスでも同じようなログの出し方をしたい。\u003c/li\u003e\n\u003cli\u003eデータサーバ実行において、端末セッション維持に使っている pexpect の実装を見直す。subprocess ライブラリを使うように変更するか、pexpect においてログが出るようにしながら、pexpect のタイムアウトでサーバーが強制終了しないようにする。\u003c/li\u003e\n\u003cli\u003e各拡張機能が設定を持てるように実装する。\u003c/li\u003e\n\u003cli\u003e拡張機能のファイルの読み書きが衝突しないようにするためのコントローラを実装し、ファイルの読み書きを各拡張機能モジュールに対して、統一したヘルパー関数を経由するようにする。ヘルパー関数は、各コントローラプロセスから、IPC によってファイルを読み書きするためのプロセスにアクセスし、リクエストを送り、結果を待機して各モジュールと接続される。各モジュールは、ファイル読み書きのヘルパー関数を呼び出すとき、リクエストだけではなく、リクエスト完了時やエラー時のコールバック関数を登録し、処理が続行されるようにする。\u003c/li\u003e\n\u003cli\u003e以下の LLM が吐き出したコードについて調べる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e __future__ \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e annotations\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e typing \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e TYPE_CHECKING\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(TYPE_CHECKING):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e controller.common \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e commandModuleArgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e## LLM (DuckDuckGo ChatGPT) 出力 調査が必要 -------\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003ch3 id=\"現状の動作の様子\"\u003e現状の動作の様子\u003c/h3\u003e\n\u003cp\u003e\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/idea/onenoteAlternativeCreation/M1/log/2026-9-16/demo.mp4 controls/\u003e\n        \n\u003c/div\u003e\n　現状としてはかろうじて動くという感じでバグや不具合だらけである。DataServer なのか、それとも卒論の試作物で使いまわしているフロントエンドの実装がいけないのか、切り分けがついていないことも多く、しばらくは調査が必要そうである。特にページコントローラ周りが動作が不安定である様相が見受けられる。これは、拡張機能名とUUIDがモジュール名に加えて解決が必要になったことが影響していると考えられる。\u003c/p\u003e","title":"2026/9/16-やったこと"},{"content":"この記事を作った動機 ミンゲイインターネット にて見つけた記事である Windows 11 でローカルアカウントを作成する方法【2026年7月時点】 に対して散々書いたので、それに対して自分なりにどうしたいか書いてみる。\n具体的には、記事で書かれている方法が機能するかどうか調べることと、sysprepを使った方法に対して、自分なりにやりたい方向性で手順を記述する。Windows 11 でローカルアカウントを作成する方法【2026年7月時点】 で書かれていることで嫌なこととして、内容がいちいち冗長で複雑で特別なスクリプトを実行させようとしてくるところがある。\n簡単な方向性 今回は、Windows ADK を使って、簡易的な応答ファイルを作成し sysprep コマンドにそれをセットアップ時に指定して読み込ませるということをする。複雑なスクリプトなども不要になるよう、作成した応答ファイルはこのブログに掲示する。\n各個人は、それをコピペするなりダウンロードして、xml として保存し、読み込ませれば使えるようにし、確認に過大な負荷を要する特殊な操作や特殊なスクリプトを排する。今回ブログに上げる応答ファイルのXMLを使えば、Windows ADK などの特殊なツールを使わずに作業を完結させられるはずである。\nADK は以下のリンクから得られるものを利用した。\nWindows ADK をダウンロードしてインストールする | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-hardware/get-started/adk-install (2026年9月12日) 応答ファイル テスト済みの環境リスト チェックがついているものがテスト済み、ついていないものがこれから。(基本的によほど制限があるエディションでなければ汎用に動くと思われる。)\nWin 11 Pro 25H2 26200.8037 Win 11 Home 25H2 26200.8037 Win 10 Pro 22H2 19045.2965 Win 10 Home 22H2 19045.2965 仕様 ユーザ名(管理者)\nMain パスワード\npass 同意画面\n隠す ローカルアカウント作成画面(OOBE)\n隠す オンラインアカウント作成画面(OOBE)\n隠す ダウンロード install.xml 生成した応答ファイルの全容 \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;unattend xmlns=\u0026#34;urn:schemas-microsoft-com:unattend\u0026#34;\u0026gt; \u0026lt;settings pass=\u0026#34;oobeSystem\u0026#34;\u0026gt; \u0026lt;component name=\u0026#34;Microsoft-Windows-Shell-Setup\u0026#34; processorArchitecture=\u0026#34;amd64\u0026#34; publicKeyToken=\u0026#34;31bf3856ad364e35\u0026#34; language=\u0026#34;neutral\u0026#34; versionScope=\u0026#34;NonSxS\u0026#34; xmlns:wcm=\u0026#34;http://schemas.microsoft.com/WMIConfig/2002/State\u0026#34; xmlns:xsi=\u0026#34;http://www.w3.org/2001/XMLSchema-instance\u0026#34;\u0026gt; \u0026lt;OOBE\u0026gt; \u0026lt;HideEULAPage\u0026gt;true\u0026lt;/HideEULAPage\u0026gt; \u0026lt;HideLocalAccountScreen\u0026gt;true\u0026lt;/HideLocalAccountScreen\u0026gt; \u0026lt;HideOnlineAccountScreens\u0026gt;true\u0026lt;/HideOnlineAccountScreens\u0026gt; \u0026lt;HideWirelessSetupInOOBE\u0026gt;true\u0026lt;/HideWirelessSetupInOOBE\u0026gt; \u0026lt;/OOBE\u0026gt; \u0026lt;UserAccounts\u0026gt; \u0026lt;LocalAccounts\u0026gt; \u0026lt;LocalAccount wcm:action=\u0026#34;add\u0026#34;\u0026gt; \u0026lt;Password\u0026gt; \u0026lt;Value\u0026gt;cABhAHMAcwBQAGEAcwBzAHcAbwByAGQA\u0026lt;/Value\u0026gt; \u0026lt;PlainText\u0026gt;false\u0026lt;/PlainText\u0026gt; \u0026lt;/Password\u0026gt; \u0026lt;Name\u0026gt;Main\u0026lt;/Name\u0026gt; \u0026lt;Group\u0026gt;Administrators\u0026lt;/Group\u0026gt; \u0026lt;/LocalAccount\u0026gt; \u0026lt;/LocalAccounts\u0026gt; \u0026lt;/UserAccounts\u0026gt; \u0026lt;/component\u0026gt; \u0026lt;/settings\u0026gt; \u0026lt;cpi:offlineImage cpi:source=\u0026#34;wim:c:/users/main/desktop/install.wim#Windows 11 Pro\u0026#34; xmlns:cpi=\u0026#34;urn:schemas-microsoft-com:cpi\u0026#34; /\u0026gt; \u0026lt;/unattend\u0026gt; やり方 通常どうり Windows をインストールし、OOBE 画面まで進める ターミナルをCtrl + F10を押して開く 応答ファイル install.xml を USB などでファイルを渡して配置する 簡単のために、sysprep の実行ファイルと同じディレクトリである、C:\\Windows\\System32\\Sysprep\\install.xmlとして配置する。今回は、notepad 簡易的なエクスプローラーとして使っている。 sysprep がある場所まで移動 cd C:\\Windows\\System32\\Sysprep\\ 以下のコマンドを実行 sysprep.exe /generalize /oobe /reboot /unattend:install.xml 放置してOOBEが現れるのを待つ 通常どうり進めていくと、アカウント作成などは求められずに進行する。ログイン画面まで来たら、Mainにpassとパスワードを入力しログインして、さらにセットアップを進めてデスクトップ画面まで行けば、作業は完了である。 お掃除 必要があれば、C:\\Windows\\System32\\Sysprep\\install.xmlに配置した応答ファイルはセットアップ後、削除することもできる。管理者権限でコマンドプロンプトを開き、以下のコマンドを実行する。\ncd C:\\Windows\\System32\\Sysprep del install.xml 参考にしたサイトとか ローカルLLM (Gemma4-31B) (2026年9月11日)\nWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\nhttps://w1.zawa-lab.net/p/20260728_oobe_bypass/ (2026年9月11日)\nミンゲイインターネット\nhttps://mingeiinter.net/ (2026年9月11日)\n応答ファイル (unattend.xml) | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/update-windows-settings-and-scripts-create-your-own-answer-file-sxs?view=windows-11\u0026amp;source=recommendations (2026年9月12日)\nWindows ADK をダウンロードしてインストールする | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-hardware/get-started/adk-install (2026年9月12日)\n光学ディスクドライブ - ArchWiki\nhttps://wiki.archlinux.jp/index.php/光学ディスクドライブ (2026年9月12日)\n","permalink":"https://www.nyanmo.info/posts/windows/skipoobe2/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://mingeiinter.net/\"\u003eミンゲイインターネット\u003c/a\u003e にて見つけた記事である \u003ca href=\"https://w1.zawa-lab.net/p/20260728_oobe_bypass/\"\u003eWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\u003c/a\u003e に対して散々書いたので、それに対して自分なりにどうしたいか書いてみる。\u003c/p\u003e\n\u003cp\u003e　具体的には、記事で書かれている方法が機能するかどうか調べることと、\u003ccode\u003esysprep\u003c/code\u003eを使った方法に対して、自分なりにやりたい方向性で手順を記述する。\u003ca href=\"https://w1.zawa-lab.net/p/20260728_oobe_bypass/\"\u003eWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\u003c/a\u003e で書かれていることで嫌なこととして、内容がいちいち冗長で複雑で特別なスクリプトを実行させようとしてくるところがある。\u003c/p\u003e\n\u003ch2 id=\"簡単な方向性\"\u003e簡単な方向性\u003c/h2\u003e\n\u003cp\u003e　今回は、Windows ADK を使って、簡易的な応答ファイルを作成し \u003ccode\u003esysprep\u003c/code\u003e コマンドにそれをセットアップ時に指定して読み込ませるということをする。複雑なスクリプトなども不要になるよう、作成した応答ファイルはこのブログに掲示する。\u003c/p\u003e\n\u003cp\u003e　各個人は、それをコピペするなりダウンロードして、xml として保存し、読み込ませれば使えるようにし、確認に過大な負荷を要する特殊な操作や特殊なスクリプトを排する。今回ブログに上げる応答ファイルのXMLを使えば、Windows ADK などの特殊なツールを使わずに作業を完結させられるはずである。\u003c/p\u003e\n\u003cp\u003e　ADK は以下のリンクから得られるものを利用した。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWindows ADK をダウンロードしてインストールする | Microsoft Learn\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/ja-jp/windows-hardware/get-started/adk-install\"\u003ehttps://learn.microsoft.com/ja-jp/windows-hardware/get-started/adk-install\u003c/a\u003e (2026年9月12日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"応答ファイル\"\u003e応答ファイル\u003c/h2\u003e\n\u003ch3 id=\"テスト済みの環境リスト\"\u003eテスト済みの環境リスト\u003c/h3\u003e\n\u003cp\u003e　チェックがついているものがテスト済み、ついていないものがこれから。(基本的によほど制限があるエディションでなければ汎用に動くと思われる。)\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Win 11 Pro  25H2 26200.8037\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Win 11 Home 25H2 26200.8037\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Win 10 Pro  22H2 19045.2965\u003c/li\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e Win 10 Home 22H2 19045.2965\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"仕様\"\u003e仕様\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eユーザ名(管理者)\u003cbr\u003e\n\u003ccode\u003eMain\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eパスワード\u003cbr\u003e\n\u003ccode\u003epass\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e同意画面\u003cbr\u003e\n　隠す\u003c/li\u003e\n\u003cli\u003eローカルアカウント作成画面(OOBE)\u003cbr\u003e\n　隠す\u003c/li\u003e\n\u003cli\u003eオンラインアカウント作成画面(OOBE)\u003cbr\u003e\n　隠す\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ダウンロード\"\u003eダウンロード\u003c/h3\u003e\n\u003cp\u003e\u003ca download href=\"/posts/windows/skipOOBE2/install.xml\"\u003e\ninstall.xml\n\u003c/a\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003e生成した応答ファイルの全容\u003c/summary\u003e\n  \u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;unattend\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;urn:schemas-microsoft-com:unattend\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;settings\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epass=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;oobeSystem\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;component\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ename=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Microsoft-Windows-Shell-Setup\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessorArchitecture=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;amd64\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epublicKeyToken=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;31bf3856ad364e35\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elanguage=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;neutral\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eversionScope=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;NonSxS\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns:wcm=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://schemas.microsoft.com/WMIConfig/2002/State\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns:xsi=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://www.w3.org/2001/XMLSchema-instance\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;OOBE\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;HideEULAPage\u0026gt;\u003c/span\u003etrue\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/HideEULAPage\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;HideLocalAccountScreen\u0026gt;\u003c/span\u003etrue\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/HideLocalAccountScreen\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;HideOnlineAccountScreens\u0026gt;\u003c/span\u003etrue\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/HideOnlineAccountScreens\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;HideWirelessSetupInOOBE\u0026gt;\u003c/span\u003etrue\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/HideWirelessSetupInOOBE\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/OOBE\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;UserAccounts\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;LocalAccounts\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;LocalAccount\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewcm:action=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;add\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;Password\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;Value\u0026gt;\u003c/span\u003ecABhAHMAcwBQAGEAcwBzAHcAbwByAGQA\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/Value\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;PlainText\u0026gt;\u003c/span\u003efalse\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/PlainText\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/Password\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;Name\u0026gt;\u003c/span\u003eMain\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/Name\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;Group\u0026gt;\u003c/span\u003eAdministrators\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/Group\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/LocalAccount\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/LocalAccounts\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/UserAccounts\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/component\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/settings\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;cpi:offlineImage\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecpi:source=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;wim:c:/users/main/desktop/install.wim#Windows 11 Pro\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns:cpi=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;urn:schemas-microsoft-com:cpi\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/unattend\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"OOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法)"},{"content":"この記事を作った動機 ミンゲイインターネット にて記事を漁っていると、Windows 11 でローカルアカウントを作成する方法【2026年7月時点】 という記事が見つかっため読んでみたところ、気になることがあったのでそのことについてまとめたい。\nあと経過観察として、msoobe bypassnroが機能したかも記録したい。ちなみに全ては Pro エディションを対象としており HOME は対象としていない。個人的には HOME やそれに類似するエディションを使うことは推奨していない。\n前回の記事 OOBE（Windowsのセットアップ画面） をスキップする 次の記事 OOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法) 関連する記事とか LLM の利用状況の現状 コマンドライン経由で windows をインストールする パスワードを無期限で利用できるようにする msoobe bypassnro経過観察 2026/9/12 Pro 公式から入手できるISO 26200.8037\n機能した UUP dump からダウンロードした ISO (26H2 Preview 26300.9539)\n機能した Home 公式から入手できるISO 26200.8037\n機能した Windows 11 でローカルアカウントを作成する方法【2026年7月時点】 の記事についての疑問点 Bypassnro ができないという記述について 対象のブログに以下のような記述があることが気になった。しかし私が現時点では検証したうえでは、これは本当ではなさそうである。bypassnro.cmd というスクリプトがなくなるくらいならあり得る気もしたが、それも仮想マシンで試したところ存在していることが確認できた。\nなぜローカルアカウントが作れないのか Windows 11 のセットアップは、途中で Microsoft アカウントへのサインインを要求します。ここでネットワークをつないでいると、ローカルアカウントを作る選択肢が表示されません。 以前は回避方法がいくつかありました。 oobe\\bypassnro.cmd を実行する start ms-cxh:localonly を実行する しかしこれらはすでに削除されており、2026 年 7 月現在は使えません。Microsoft が意図的に塞いでいる領域です。 ちなみに以下は、公式から入手できるISOで試したときの様子である。ビルド番号も対象のブログが出しているものと同じである。\n矛盾した内容 bypassnro は2026/7に使えないと書いていながら、最後の方にはまだ動くと書いてある矛盾がある。それどころかスクリプトは健在である。ビルド番号だけ変えずに、この記事が書かれたあとにしれっと公式のISOのinstall.wim(install.esd)の内容が変わったという可能性はあるが、それでもなんかこの記事に書かれていることはおかしいような気がする。\nなぜローカルアカウントが作れないのか Windows 11 のセットアップは、途中で Microsoft アカウントへのサインインを要求します。ここでネットワークをつないでいると、ローカルアカウントを作る選択肢が表示されません。 以前は回避方法がいくつかありました。 oobe\\bypassnro.cmd を実行する start ms-cxh:localonly を実行する しかしこれらはすでに削除されており、2026 年 7 月現在は使えません。Microsoft が意図的に塞いでいる領域です。 まとめ 2026 年 7 月現在、Windows 11 の OOBE でローカルアカウントを作る手段はいくつか残っていますが、恒久的に使えるものと、いつ消えてもおかしくないものが混在しています。 レジストリ方式（BypassNRO / HideOnlineAccountScreens）はまだ動くが、明示的に潰されつつある 応答ファイル（unattend.xml）は Microsoft 公式の展開機構で、当面残る見込み ただし応答ファイル単体では、アカウント名とパスワードが決め打ちになる この記事の方法は、対話部分を自作して OOBE の外に出し、OOBE を抜ける部分だけを公式機構に任せるという分離によって、対話性と耐久性を両立させたものです。 USB メモリの準備も、ISO の加工も、レジストリの裏技も必要ありません。スクリプトの内容を変えたくなったら、配信元のファイルを更新するだけで済みます。 検証機、共用端末、キオスク、譲渡前提の機体など、Microsoft アカウントを紐づける意味がない端末は意外とあります。そういう場面で使える手順が 1 本あると便利かと思います。 出どころ不明の文章を根拠として記事を補強しようとしている 出どころが不明なMicrosoftの名声に関する文章がある。下の方に文献のURLがあるとかではなく、記事の中で Microsoft の名声として書かれていることがあるが、本当なのかわからない。これは調べてみる必要がありそうである。このような不適切な読み手に説得しようとする（しかし、実態がないかでたらめである可能性がある）文章は、LLMの出力においてよく見られることである。\nあともう一つ気になることが、「これらの仕組みは重要なセットアップ画面をスキップしてしまい、正しく構成されていない状態で OOBE を抜けるおそれがある」と記述されているが、それが具体的にどのような問題になるのか示されていない。多少不具合があっても実用できるほど動くのか、実害があるのか書かれていない。\nちなみに私は、bypassnro の方法でしか win11 は運用していないが今のところ致命的な実害は出ていない。パスワードの期限が有限になっているということやゴミアカウントが出現する問題はあったがそれ以外に致命的に修正不可能な問題にはまだ直面していない。私が普段Linux環境を使っていて細かい不具合を知らないだけかもしれない。もしかすると企業とか強く組織で Active Directory とかで管理された環境では問題が出てくるのかもしれないが、もしそうならこの記事の書き手はそのことについて腹を立てて個人的な体験を書いていてもおかしくないように思うし、やっぱり具体性にかけてなんか説得力がない。\nMicrosoft の意図を読む 一連の削除アナウンスで、Microsoft の説明は一貫しています。 「これらの仕組みは重要なセットアップ画面をスキップしてしまい、正しく構成されていない状態で OOBE を抜けるおそれがある」 ここが重要な切り分けになります。Microsoft が守りたいのは OOBE の完走であって、ローカルアカウントの存在そのものではありません。実際、セットアップ後にローカルアカウントを作ることも、設定から切り替えることも、現在も普通にできます。制限は OOBE のフローにだけ存在します。 この記事の方法が sysprep /oobe を使っているのは、まさにこの点に対応するためです。OOBE をスキップするのではなく、応答ファイル込みで OOBE を再実行し、各画面を正規に処理させています。 net user でアカウントを作って msoobe を叩く系の手法（defaultuser0 が残るあれ）とは、性質がまったく違います。 Microsoft の批判が当たらない側に立てるので、潰される動機が薄い構造になっています。 ブログを読んで思った感想 なんかこのブログ記事を書いている人は、LLMを記事を生成するのに使っていることは明記しているが、ただし、実際の検証・判断は手元の Windows 環境で行った結果に基づいており、内容は実体験ベースで整理しています。というのはおかしいのではないか？と思った。\nOOBE の件については、最後の方も余談（人間執筆。）とあることから、LLM を使っていることを隠すつもりはないのだろうと思われ、悪意はないのかもしれないが、ブログのあり方には問題があると思われる。\n私としては、LLMを使うこと自体は否定しないが、生成されたものを直接コピペしたりして記事にするのはどうかと思うところである。そもそもただし、実際の検証・判断は手元の Windows 環境で行った結果に基づいており、内容は実体験ベースで整理しています。というディスクレーマー自体がなんかその文章さえも Claude で作らせた？って感じである。\n実際に試して動いたかどうかというのが私にとっては重要であり、かつ私のブログ記事についても今後も生成するつもりはない。こうした記録は、不完全でも自分で書くことに意味があるとし、ただ情報を公開したり記録するだけではなく、記事を書きながら自分が把握している情報を整理する目的もある。\n他人が、LLMコピペをするかは自由であるが、ちょっとこの記事は不正確な情報で読み手を不安で煽るようなものであると見受けられ、ひどいと思った。\nなんていうか、LLM を使うのはよいけど、そのまま文章を出されるとちょっとひどいなと思う。それどころか文献もないというのは、いかがなものだろうか？それとも個人ブログにあれこれ求めすぎということなのだろうか？なんかこんな記事出されるくらいだったら、直接 LLM にユーザが個別に質問すれば良いのではないかと思ってしまう。ブログにしていてわざわざただし、実際の検証・判断は手元の Windows 環境で行った結果に基づいており、内容は実体験ベースで整理しています。とまで書いているのに、LLMが吐き出すユーザを感情的に揺さぶったり、それっぽい文章で読み手に誤った確信を与えてしまうものをドバッと出されると、嫌な気持ちになる。こういうことがあるので、自分からある程度LLMに触って生成させてどんな傾向があるか把握しておくと、気づくことはできるのは大きいとは思った。\nしかし、ニコニコ動画にパスワードログインできない件について、yt-dlp のリポジトリに issue を立ててしまう の記事にしている私の体験としては、このような LLM によって生成された内容はかなり社会問題となっていると見受けられる。yt-dlpのリポジトリにおいては、NO AI / NO LLM POLICYというページがあり、非常に厳しいペナルティーがあり、厳しい対応が取られていることがわかる。\nLLMを使えば、人間とは異なって、とりあえずなにか文字列を乱造するだけならば、計算資源次第で後は容易にできてしまうが、その情報を受け取る受け手や、影響を受ける受け手は有限な生身の人間であり、簡単に振り回され、摩耗し、傷つき、必死に調べているかもしれない相手である。\n間違っても、不完全でも、少なくてもいから、LLM でいい加減に記事を書くのはやめてほしい気がする。(というか LLM 出だしたものは、\u0026ldquo;書いた\u0026quot;とは言えない気がする。) 仕方なく仕事でやらざるを得ず、追い詰められたからとか生きるために仕方なくそうしたんだという背景があるならまだしも、今回対象となっているブログは、とりあえず作ってみたくらいの雰囲気であるように見受けられる。\nただし、実際の検証・判断は手元の Windows 環境で行った結果に基づいており、内容は実体験ベースで整理しています。とまで書いて、情報の受け手を強く期待させたり、内容に信頼するように書いていながら、記事自体が矛盾していて、かつ実際に試してみると異なる結果が得られるというのは、ひどいと思う。本当にちゃんと確かめたの？って感じだし、何を基準に検証、判断したの？って思うところである。すごく軽く甘くしかやっていないことを、すごく誇張して書いていないか？とも思う。少なくともこの記事の書き手が、LLM の出力した内容について、文献が存在するかとか検証しているようには見えない。あるいは\u0026quot;不確かではあるが、LLMはこう出力してきた。\u0026ldquo;というような不確実な情報との切り分けはしているようには見受けられなかった。\n私はLLMの出力に関して問題点を見つけられずに、安易にネットに分別もせずばらまくようなやり方は肯定できない。\n私としては、普段 Pro エディションしか使っていないというのはあるので、HOME エディションについては知らないところが多い。これについても調べてみようと思う。試した\n参考にしたサイトとか Windows 11 でローカルアカウントを作成する方法【2026年7月時点】\nhttps://w1.zawa-lab.net/p/20260728_oobe_bypass/ (2026年9月11日)\nミンゲイインターネット\nhttps://mingeiinter.net/ (2026年9月11日)\nUUP dump\nhttps://uupdump.net/ (2026年9月12日)\nHow to download Windows 11 26H2 ISO file (preview) - Pureinfotech\nhttps://pureinfotech.com/download-windows-11-26h2-iso/ (2026年9月12日)\nHow to download Tiny11 ISO for Windows 11 26H2 - Pureinfotech\nhttps://pureinfotech.com/download-tiny11-iso-windows-11-26h2/ (2026年9月12日)\nDownload Windows 11\nhttps://www.microsoft.com/en-us/software-download/windows11 (2026年9月12日)\nyt-dlp/CONTRIBUTING.md at master · yt-dlp/yt-dlp\nhttps://github.com/yt-dlp/yt-dlp/blob/master/CONTRIBUTING.md#no-ai--no-llm-policy (2026年9月12日)\n","permalink":"https://www.nyanmo.info/posts/windows/skipoobe1/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://mingeiinter.net/\"\u003eミンゲイインターネット\u003c/a\u003e にて記事を漁っていると、\u003ca href=\"https://w1.zawa-lab.net/p/20260728_oobe_bypass/\"\u003eWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\u003c/a\u003e という記事が見つかっため読んでみたところ、気になることがあったのでそのことについてまとめたい。\u003c/p\u003e\n\u003cp\u003e　あと経過観察として、\u003ccode\u003emsoobe bypassnro\u003c/code\u003eが機能したかも記録したい。ちなみに全ては Pro エディションを対象としており HOME は対象としていない。個人的には HOME やそれに類似するエディションを使うことは推奨していない。\u003c/p\u003e\n\u003ch2 id=\"前回の記事\"\u003e前回の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/windows/skipoobe/\"\u003eOOBE（Windowsのセットアップ画面） をスキップする\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"次の記事\"\u003e次の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/windows/skipoobe2/\"\u003eOOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"関連する記事とか\"\u003e関連する記事とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/other/llmusage/\"\u003eLLM の利用状況の現状\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/windows/installviacommand/\"\u003eコマンドライン経由で windows をインストールする\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/windows/setpasswordtoneverexpire/\"\u003eパスワードを無期限で利用できるようにする\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"msoobe-bypassnro経過観察\"\u003e\u003ccode\u003emsoobe bypassnro\u003c/code\u003e経過観察\u003c/h2\u003e\n\u003ch3 id=\"2026912\"\u003e2026/9/12\u003c/h3\u003e\n\u003ch4 id=\"pro\"\u003ePro\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.microsoft.com/en-us/software-download/windows11\"\u003e公式から入手できるISO 26200.8037\u003c/a\u003e\u003cbr\u003e\n　機能した\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://uupdump.net/\"\u003eUUP dump\u003c/a\u003e からダウンロードした ISO (26H2 Preview 26300.9539)\u003cbr\u003e\n　機能した\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"home\"\u003eHome\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.microsoft.com/en-us/software-download/windows11\"\u003e公式から入手できるISO 26200.8037\u003c/a\u003e\u003cbr\u003e\n　機能した\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"windows-11-でローカルアカウントを作成する方法2026年7月時点-の記事についての疑問点\"\u003e\u003ca href=\"https://w1.zawa-lab.net/p/20260728_oobe_bypass/\"\u003eWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\u003c/a\u003e の記事についての疑問点\u003c/h2\u003e\n\u003ch3 id=\"bypassnro-ができないという記述について\"\u003eBypassnro ができないという記述について\u003c/h3\u003e\n\u003cp\u003e　対象のブログに以下のような記述があることが気になった。しかし私が現時点では検証したうえでは、これは本当ではなさそうである。bypassnro.cmd というスクリプトがなくなるくらいならあり得る気もしたが、それも仮想マシンで試したところ存在していることが確認できた。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eなぜローカルアカウントが作れないのか\nWindows 11 のセットアップは、途中で Microsoft アカウントへのサインインを要求します。ここでネットワークをつないでいると、ローカルアカウントを作る選択肢が表示されません。\n\n以前は回避方法がいくつかありました。\n\noobe\\bypassnro.cmd を実行する\nstart ms-cxh:localonly を実行する\nしかしこれらはすでに削除されており、2026 年 7 月現在は使えません。Microsoft が意図的に塞いでいる領域です。\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e\n\u003cp\u003e　ちなみに以下は、\u003ca href=\"https://www.microsoft.com/en-us/software-download/windows11\"\u003e公式から入手できるISO\u003c/a\u003eで試したときの様子である。ビルド番号も対象のブログが出しているものと同じである。\u003cbr\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE1/%e5%85%ac%e5%bc%8fISO%e3%83%86%e3%82%b9%e3%83%88-2026-9-12.png#center\"\n         alt=\"公式ISOテスト-2026-9-12\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"OOBE（Windowsのセットアップ画面） をスキップする-1"},{"content":"この記事を作った動機 最近ニコニコ動画を久しぶりに見てみて、動画をいくつか yt-dlp コマンドによってダウンロードしようとしたところ、パスワードとユーザ名によるログイン機能がうまく機能しない場合があることが分かった。\n普段であれば、誰かが勝手に issue でも立てるだろうと放置していただろうが、何を血迷ったのか issue を自分で立てたので、そのことについて記録したい。Issue に関してはすでに yt-dlp の方を見ればわかることなので、周辺情報について適当に書きたい。\n前回の記事 yt-dlpコマンドで、年齢制限を何とかする yt-dlpコマンドで、年齢制限を何とかするの追記 issue へのリンク [niconico] Unable to log in: HTTP Error 404: Not Found (caused by \u0026lt;HTTPError 404: Not Found\u0026gt;) · Issue #17667 · yt-dlp/yt-dlp\nhttps://github.com/yt-dlp/yt-dlp/issues/17667 (2026年9月11日) yt-dlp をコンパイルする 前提条件として、すでに作業ディレクトを作成して移動しており、anaconda 環境であることと、Linux 環境であることを置く。ニコニコ動画に関していくつか API エンドポイントの URL について候補があり試したかったというのがあり、コードを改変したあと、コンパイルする必要がったことが背景にある。結局どれもうまくいかなかったが。\nリポジトリをクローン git clone https://github.com/yt-dlp/yt-dlp.git cd yt-dlp 環境を作成 conda create -n ytDlp conda activate ytDlp conda install python conda install pip 依存関係のインストールやコンパイル、バイナリ生成 yt-dlpリポジトリのコンパイルの項目を参考に、以下のようにして yt-dlp のバイナリを生成する。\npython devscripts/install_deps.py --include-group pyinstaller python devscripts/make_lazy_extractors.py python -m bundle.pyinstaller make yt-dlp 実際に起動する ./yt-dlp # Usage: yt-dlp [OPTIONS] URL [URL...] # # yt-dlp: error: You must provide at least one URL. # Type yt-dlp --help to see a list of all options. まとめ # リポジトリクローン git clone https://github.com/yt-dlp/yt-dlp.git cd yt-dlp # 環境作成 conda create -n ytDlp conda activate ytDlp conda install python conda install pip # コンパイル python devscripts/install_deps.py --include-group pyinstaller python devscripts/make_lazy_extractors.py python -m bundle.pyinstaller make yt-dlp # 起動 ./yt-dlp # Usage: yt-dlp [OPTIONS] URL [URL...] # # yt-dlp: error: You must provide at least one URL. # Type yt-dlp --help to see a list of all options. Cookie は動作する yt-dlpコマンドで、年齢制限を何とかするやyt-dlpコマンドで、年齢制限を何とかするの追記に書いていた一年以上前のときは、まともに動作していなかった気がするが、今は Google-Chrome でもクッキーを復号して認証情報を正しく利用できるようになっていそうなことが分かった。Issue を作成するために、少なくともニコニコ動画に関してはログインしないと見れない年齢制限のかかった動画でテストしたところ機能した。YouTube については未検証だが、多分今は動作するのではないかと思われる。なおpython-secretstorageが必要である。\nなお以下のログの例は、すでにブラウザ側でニコニコ動画へのログインを済ませていることを前提としている。\nGoogle-Chrome 長いログ [debug] Command-line config: [\u0026#39;https://www.nicovideo.jp/watch/sm34400723\u0026#39;, \u0026#39;--merge-output-format\u0026#39;, \u0026#39;mp4\u0026#39;, \u0026#39;--cookies-from-browser\u0026#39;, \u0026#39;chrome\u0026#39;, \u0026#39;--embed-thumbnail\u0026#39;, \u0026#39;-vU\u0026#39;] [debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8 [debug] yt-dlp version stable@2026.08.19 from yt-dlp/yt-dlp [594bd50c2] (zip) [debug] Python 3.14.7 (CPython x86_64 64bit) - Linux-7.1.10-arch1-1-x86_64-with-glibc2.44 (OpenSSL 3.5.8 25 Aug 2026, glibc 2.44) [debug] exe versions: ffmpeg 9.0.1 (setts), ffprobe 9.0.1, rtmpdump 2.6 [debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.07.22, mutagen-1.48.1, requests-2.34.2, secretstorage-3.5.0, sqlite3-3.53.4, urllib3-2.7.0, websockets-17.1, yt_dlp_ejs-0.8.0 [debug] JS runtimes: deno-2.9.6 [debug] Proxy map: {} Extracting cookies from chrome [debug] Extracting cookies from: \u0026#34;/home/main/.config/google-chrome/Default/Cookies\u0026#34; [Cookies] Loading cookie 0/ 563[debug] detected desktop environment: GNOME [debug] Chosen keyring: GNOMEKEYRING Extracted 508 cookies from chrome [debug] cookie version breakdown: {\u0026#39;v10\u0026#39;: 0, \u0026#39;v11\u0026#39;: 563, \u0026#39;other\u0026#39;: 0, \u0026#39;unencrypted\u0026#39;: 0} [debug] Request Handlers: urllib, requests, websockets [debug] Plugin directories: none [debug] Loaded 1745 extractors [debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest Latest version: stable@2026.08.19 from yt-dlp/yt-dlp yt-dlp is up to date (stable@2026.08.19 from yt-dlp/yt-dlp) [niconico] Extracting URL: https://www.nicovideo.jp/watch/sm34400723 [niconico] sm34400723: Downloading API JSON [niconico] sm34400723: Downloading JSON metadata [niconico] sm34400723: Downloading m3u8 information [debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec, channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id [debug] Default format spec: bestvideo*+bestaudio/best [info] sm34400723: Downloading 1 format(s): video-h264-720p-1+audio-aac-192kbps [info] Downloading video thumbnail ogp ... [info] Writing video thumbnail ogp to: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].jpg [debug] Invoking hlsnative downloader on \u0026#34;https://delivery.domand.nicovideo.jp/hlsbid/653621994da97b3db03d5913/playlists/media/video-h264-720p.m3u8?session=bd3d666836cc261fc66512edc651c84d0b18257cb885a062000000006aa4cffc7b5851ed993b8b6d\u0026amp;Expires=1789186044\u0026amp;Signature=MEYCIQCcYuaRq~SBhWNXd63cwZ1iTVDfArDIvx7FxTcawmkT0wIhAK8a8~bNARBRI~OaDi-~-qtEE5e~kBUjpcBCMn1TMbiA\u0026amp;Key-Pair-Id=K2BJYD8B5280J4\u0026#34; [hlsnative] Downloading m3u8 manifest [hlsnative] Total fragments: 105 [download] Destination: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4 [download] 100% of 149.66MiB in 00:00:09 at 15.96MiB/s [debug] Invoking hlsnative downloader on \u0026#34;https://delivery.domand.nicovideo.jp/hlsbid/653621994da97b3db03d5913/playlists/media/audio-aac-192kbps.m3u8?session=bd3d666836cc261fc66512edc651c84d0b18257cb885a062000000006aa4cffc7b5851ed993b8b6d\u0026amp;Expires=1789186044\u0026amp;Signature=MEUCIH7JNUOxgoJewA0c~I332y5SdU1FyBvE3dshIr7NQkglAiEA1~9AhVPBOlnCR~e8AaTeEY8jEIDmRGH0Y7v69QzsIiE_\u0026amp;Key-Pair-Id=K2BJYD8B5280J4\u0026#34; [hlsnative] Downloading m3u8 manifest [hlsnative] Total fragments: 105 [download] Destination: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4 [download] 100% of 14.64MiB in 00:00:04 at 3.25MiB/s [debug] ffmpeg command line: ffprobe -show_streams \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4\u0026#39; [Merger] Merging formats into \u0026#34;【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].mp4\u0026#34; [debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4\u0026#39; -i \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4\u0026#39; -c copy -map 0:v:0 -map 1:a:0 -bsf:a:0 aac_adtstoasc -movflags +faststart \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].temp.mp4\u0026#39; Deleting original file 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4 (pass -k to keep) Deleting original file 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4 (pass -k to keep) [EmbedThumbnail] mutagen: Adding thumbnail to \u0026#34;【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].mp4\u0026#34; Firefox 長いログ [debug] Command-line config: [\u0026#39;https://www.nicovideo.jp/watch/sm34400723\u0026#39;, \u0026#39;--merge-output-format\u0026#39;, \u0026#39;mp4\u0026#39;, \u0026#39;--cookies-from-browser\u0026#39;, \u0026#39;firefox\u0026#39;, \u0026#39;--embed-thumbnail\u0026#39;, \u0026#39;-vU\u0026#39;] [debug] Encodings: locale UTF-8, fs utf-8, pref UTF-8, out utf-8, error utf-8, screen utf-8 [debug] yt-dlp version stable@2026.08.19 from yt-dlp/yt-dlp [594bd50c2] (zip) [debug] Python 3.14.7 (CPython x86_64 64bit) - Linux-7.1.10-arch1-1-x86_64-with-glibc2.44 (OpenSSL 3.5.8 25 Aug 2026, glibc 2.44) [debug] exe versions: ffmpeg 9.0.1 (setts), ffprobe 9.0.1, rtmpdump 2.6 [debug] Optional libraries: Cryptodome-3.23.0, brotli-1.2.0, certifi-2026.07.22, mutagen-1.48.1, requests-2.34.2, secretstorage-3.5.0, sqlite3-3.53.4, urllib3-2.7.0, websockets-17.1, yt_dlp_ejs-0.8.0 [debug] JS runtimes: deno-2.9.6 [debug] Proxy map: {} Extracting cookies from firefox [debug] Extracting cookies from: \u0026#34;/home/main/.mozilla/firefox/dy4q59za.default-release/cookies.sqlite\u0026#34; [debug] Firefox cookies database version: 17 Extracted 919 cookies from firefox [debug] Request Handlers: urllib, requests, websockets [debug] Plugin directories: none [debug] Loaded 1745 extractors [debug] Fetching release info: https://api.github.com/repos/yt-dlp/yt-dlp/releases/latest Latest version: stable@2026.08.19 from yt-dlp/yt-dlp yt-dlp is up to date (stable@2026.08.19 from yt-dlp/yt-dlp) [niconico] Extracting URL: https://www.nicovideo.jp/watch/sm34400723 [niconico] sm34400723: Downloading API JSON [niconico] sm34400723: Downloading JSON metadata [niconico] sm34400723: Downloading m3u8 information [debug] Formats sorted by: hasvid, ie_pref, lang, quality, res, fps, hdr:12(7), vcodec, channels, acodec, size, br, asr, proto, vext, aext, hasaud, source, id [debug] Default format spec: bestvideo*+bestaudio/best [info] sm34400723: Downloading 1 format(s): video-h264-720p-1+audio-aac-192kbps [info] Downloading video thumbnail ogp ... [info] Writing video thumbnail ogp to: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].jpg [debug] Invoking hlsnative downloader on \u0026#34;https://delivery.domand.nicovideo.jp/hlsbid/653621994da97b3db03d5913/playlists/media/video-h264-720p.m3u8?session=369e874ec15a42000c3a8a6cc8e9eaed0b18257cb885a062000000006aa4d00f6f24ad3b5c2bfa22\u0026amp;Expires=1789186063\u0026amp;Signature=MEUCIQCkCspoCQ4lfo~9NtSQTe4hQNdTq985riN~rUsDyarYRQIgJPGc1~w1DjXeFE1WYlh-n1n6SS5R3Sy0SVpOBTl6tTs_\u0026amp;Key-Pair-Id=K2BJYD8B5280J4\u0026#34; [hlsnative] Downloading m3u8 manifest [hlsnative] Total fragments: 105 [download] Destination: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4 [download] 100% of 149.66MiB in 00:00:12 at 12.05MiB/s [debug] Invoking hlsnative downloader on \u0026#34;https://delivery.domand.nicovideo.jp/hlsbid/653621994da97b3db03d5913/playlists/media/audio-aac-192kbps.m3u8?session=369e874ec15a42000c3a8a6cc8e9eaed0b18257cb885a062000000006aa4d00f6f24ad3b5c2bfa22\u0026amp;Expires=1789186063\u0026amp;Signature=MEUCIQC~qbGwGKyJRmBhsJgBr3O38O8ZMZTdk8guX19DEmvjPQIgLOnBXr9mbn7Pou5p6tDgrU-6Q4pIHFt7IY2l8dYhWk0_\u0026amp;Key-Pair-Id=K2BJYD8B5280J4\u0026#34; [hlsnative] Downloading m3u8 manifest [hlsnative] Total fragments: 105 [download] Destination: 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4 [download] 100% of 14.64MiB in 00:00:04 at 2.98MiB/s [debug] ffmpeg command line: ffprobe -show_streams \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4\u0026#39; [Merger] Merging formats into \u0026#34;【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].mp4\u0026#34; [debug] ffmpeg command line: ffmpeg -y -loglevel repeat+info -i \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4\u0026#39; -i \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4\u0026#39; -c copy -map 0:v:0 -map 1:a:0 -bsf:a:0 aac_adtstoasc -movflags +faststart \u0026#39;file:【合作】New Year\u0026#39;\u0026#34;\u0026#39;\u0026#34;\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].temp.mp4\u0026#39; Deleting original file 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].fvideo-h264-720p-1.mp4 (pass -k to keep) Deleting original file 【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].faudio-aac-192kbps.mp4 (pass -k to keep) [EmbedThumbnail] mutagen: Adding thumbnail to \u0026#34;【合作】New Year\u0026#39;s Dreams 2018 ~ YA☆RI☆MA☆SU☆NE [sm34400723].mp4\u0026#34; 試したエンドポイント 調べて分かったことと、ネットなど色々すでに情報がないかあさってだめだったエンドポイントを上げる。\n調べて見て分かった、現行の ログイン API エンドポイントっぽいもの https://account.nicovideo.jp/spa/login/index.html(通常のログインページ)にて色々実験したところ、Cloudflare の anti-bot をパスさせた状態で、かつユーザ名とパスワードを入力した状態にした上で、開発者タブからオフライン状態を再現することで、現行のエンドポイントらしいものが発見された。\nただ、anti-bot 対策がされているので、かなり厄介なことになっていそうである。また、既存の yt-dlp の実装と照らし合わせると、今のニコニコ動画の認証系はだいぶ変わっているように見受けられ、大幅な改修が必要なのではないかと思われる。\nURL https://api.id.nicovideo.jp/v1/auth/with-password\nContent Type application/json\nContent of JSON { \u0026#34;identifier\u0026#34;: \u0026#34;[email address]\u0026#34;, \u0026#34;password\u0026#34;: \u0026#34;[password]\u0026#34;, \u0026#34;identifierType\u0026#34;: \u0026#34;emailOrPhone\u0026#34;, \u0026#34;redirectUri\u0026#34;: \u0026#34;https://www.nicovideo.jp/watch/sm28146938?\u0026#34;, \u0026#34;sec\u0026#34;: \u0026#34;header_pc\u0026#34; } ブラウザにおける fetch の詳細 リクエスト URL https://api.id.nicovideo.jp/v1/auth/with-password 参照ポリシー strict-origin-when-cross-origin content-type application/json dnt 1 referer https://account.nicovideo.jp/ sec-ch-ua \u0026#34;Not(A:Brand\u0026#34;;v=\u0026#34;8\u0026#34;, \u0026#34;Chromium\u0026#34;;v=\u0026#34;144\u0026#34;, \u0026#34;Google Chrome\u0026#34;;v=\u0026#34;144\u0026#34; sec-ch-ua-mobile ?0 sec-ch-ua-platform \u0026#34;Linux\u0026#34; user-agent Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/144.0.0.0 Safari/537.36 x-frontend-id 8 x-frontend-version 2 x-turnstile-response 1.77t9pUpfG3HnPqZkFckfoecWLIGau3aMvH44SmzyauHm8O1sW-c-e4tnZ0AVKADmNuVQT0JW6J-JZQjQpHq8zJTmCkXE5ws0Twf6LnlrytJd8pD-7IziQS-1NTCR-bHzuqbdKpPY6odFudHohFVcesUNxUEMcHAvu3H7kvac0I-6rch1hFOB4w13rbfZrO48tDEBy4WI0r3ZJPpY7Sg176PsG6vSYYIeiVEIxYcYD87pLcCqPb17A-7P8vaTpj9ZD0EJreT1W9-OdfglFeaOSfj7fGxffdEalR-GZOGada9ZSUzBVhQfUH3G0zCVDnmnlYl1oB04IvP4oDzdt9ZNw4-BY1iRAGr_lv6hBnIdDX3OYLd9FI5DTyBs83hOlYJEWcQwGCandnOQE0RAaCFNFod4d4EmVGsAb8ibhojcGASOlEYFVaR5y7grOlbFd2YFJHD3D7yg1jf-kmjcKbsqBL9X4OrEcS3mf-Z2jcTfK3TSAh-t7eE-kUM0X1fezM5GlwBvEYyy5fgGRiWj19m5pZkeKTXhcYOJYp_amy2iS4FffuFrc-tZVsEhPiyhzz4OTDcrnfddjzlimi74Nn25f9ig_RwSwHYgyFOTUgBDAIUDdDoGJ_Iz87PKs2LCuGNpmXbEQy35TcDmi_nz5oKOGGZGanMM2j0VQ1JkLPKKeek.IzNXUQKsg48UtknNP1UMsQ.b64d0bb91d1f3bdf37917b2b7a54306edce307ca4ca855c84f048409ece8a6c3 x-turnstile-sitekey 0x4AAAAAACMMWdSktHoD87sD 問題であると思われる yt-dlp の既存の実装(2026/9/11) yt-dlp/yt_dlp/extractor/niconico.py 長いコード 以下は、yt-dlp/yt_dlp/extractor/niconico.py at master · yt-dlp/yt-dlp を一部引用したものである。\nclass NiconicoBaseIE(InfoExtractor): _API_BASE = \u0026#39;https://nvapi.nicovideo.jp\u0026#39; _BASE_URL = \u0026#39;https://www.nicovideo.jp\u0026#39; _GEO_BYPASS = False _GEO_COUNTRIES = [\u0026#39;JP\u0026#39;] _HEADERS = { \u0026#39;X-Frontend-ID\u0026#39;: \u0026#39;6\u0026#39;, \u0026#39;X-Frontend-Version\u0026#39;: \u0026#39;0\u0026#39;, } _LOGIN_BASE = \u0026#39;https://account.nicovideo.jp\u0026#39; _NETRC_MACHINE = \u0026#39;niconico\u0026#39; @property def is_logged_in(self): return bool(self._get_cookies(\u0026#39;https://www.nicovideo.jp\u0026#39;).get(\u0026#39;user_session\u0026#39;)) def _raise_login_error(self, message, expected=True): raise ExtractorError(f\u0026#39;Unable to login: {message}\u0026#39;, expected=expected) def _perform_login(self, username, password): if self.is_logged_in: return self._request_webpage( f\u0026#39;{self._LOGIN_BASE}/login\u0026#39;, None, \u0026#39;Requesting session cookies\u0026#39;) webpage = self._download_webpage( f\u0026#39;{self._LOGIN_BASE}/login/redirector\u0026#39;, None, \u0026#39;Logging in\u0026#39;, \u0026#39;Unable to log in\u0026#39;, headers={ \u0026#39;Content-Type\u0026#39;: \u0026#39;application/x-www-form-urlencoded\u0026#39;, \u0026#39;Referer\u0026#39;: f\u0026#39;{self._LOGIN_BASE}/login\u0026#39;, }, data=urlencode_postdata({ \u0026#39;mail_tel\u0026#39;: username, \u0026#39;password\u0026#39;: password, })) if self.is_logged_in: return elif err_msg := traverse_obj(webpage, ( {find_element(cls=\u0026#39;notice error\u0026#39;)}, {find_element(cls=\u0026#39;notice__text\u0026#39;)}, {clean_html}, )): self._raise_login_error(err_msg or \u0026#39;Invalid username or password\u0026#39;) elif \u0026#39;oneTimePw\u0026#39; in webpage: post_url = self._search_regex( r\u0026#39;\u0026lt;form[^\u0026gt;]+action=([\u0026#34;\\\u0026#39;])(?P\u0026lt;url\u0026gt;.+?)\\1\u0026#39;, webpage, \u0026#39;post url\u0026#39;, group=\u0026#39;url\u0026#39;) mfa, urlh = self._download_webpage_handle( urljoin(self._LOGIN_BASE, post_url), None, \u0026#39;Performing MFA\u0026#39;, \u0026#39;Unable to complete MFA\u0026#39;, headers={ \u0026#39;Content-Type\u0026#39;: \u0026#39;application/x-www-form-urlencoded\u0026#39;, }, data=urlencode_postdata({ \u0026#39;otp\u0026#39;: self._get_tfa_info(\u0026#39;6 digit number shown on app\u0026#39;), })) if self.is_logged_in: return elif \u0026#39;error-code\u0026#39; in parse_qs(urlh.url): err_msg = traverse_obj(mfa, ({find_element(cls=\u0026#39;pageMainMsg\u0026#39;)}, {clean_html})) self._raise_login_error(err_msg or \u0026#39;MFA session expired\u0026#39;) elif \u0026#39;formError\u0026#39; in mfa: err_msg = traverse_obj(mfa, ( {find_element(cls=\u0026#39;formError\u0026#39;)}, {find_element(tag=\u0026#39;div\u0026#39;)}, {clean_html})) self._raise_login_error(err_msg or \u0026#39;MFA challenge failed\u0026#39;) self._raise_login_error(\u0026#39;Unexpected login error\u0026#39;, expected=False) だめだったもの account.nicovideo.jp/api/v1/login { \u0026#34;meta\u0026#34;: { \u0026#34;status\u0026#34;: 404, \u0026#34;error-code\u0026#34;: \u0026#34;NOT_FOUND\u0026#34;, \u0026#34;error-message\u0026#34;: \u0026#34;requested uri is not found on routes. URL: /api/v1/login\u0026#34; } } secure.nicovideo.jp/secure/login ping secure.nicovideo.jp # ping: secure.nicovideo.jp: 名前またはサービスが不明です https://account.nicovideo.jp/login/redirector(yt-dlp 2026/9/11 時点で内蔵されているログイン URL) (404 NotFound) https://account.nicovideo.jp/ (404 NotFound) https://account.nicovideo.jp/login/ (404 NotFound) https://account.nicovideo.jp/login\nhttps://account.nicovideo.jp/spa/login/index.html(通常のログインページ)へリダイレクトされる。 参考にしたサイトとか ニコニコ動画（niconico）API API 日本 | API図鑑\nhttps://api-zukan.com/apis/niconico-api (2026年9月11日)\nニコニコ動画 『スナップショット検索 v2 API』 ガイド\nhttps://site.nicovideo.jp/search-api-docs/snapshot (2026年9月11日)\nニコニコ動画のAPI一覧 #API - Qiita\nhttps://qiita.com/anmoti/items/a55b16ae0c21faf63b41 (2026年9月11日)\nGitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloader · GitHub\nhttps://github.com/yt-dlp/yt-dlp (2026年9月11日)\n【完了】一部非公開APIの提供終了につきまして【ニコニコ動画】｜ニコニコインフォ\nhttps://blog.nicovideo.jp/niconews/182541.html (2026年9月11日)\nGitHub - niconicolibs/api: ニコニコ非公開APIまとめ · GitHub\nhttps://github.com/niconicolibs/api (2026年9月11日)\npublic | ニコニコ非公式APIドキュメント\nhttps://niconicolibs.github.io/api/public/#tag/Users/operation/get-v2-user.json (2026年9月11日)\nnvapi | ニコニコ非公式APIドキュメント\nhttps://niconicolibs.github.io/api/nvapi/ (2026年9月11日)\nother | ニコニコ非公式APIドキュメント\nhttps://niconicolibs.github.io/api/other/ (2026年9月11日)\nニコニコAPI備忘録\nhttps://zenn.dev/book000/articles/niconico_api (2026年9月11日)\n【ニコニコ動画】動画情報を取得するAPI (2025/8/10 時点) #niconico - Qiita\nhttps://qiita.com/gcrtnst/items/5bd1358af8cc636e3f4f (2026年9月11日)\nyt-dlp/yt_dlp/extractor/niconico.py at master · yt-dlp/yt-dlp\nhttps://github.com/yt-dlp/yt-dlp/blob/master/yt_dlp/extractor/niconico.py (2026年9月11日)\n","permalink":"https://www.nyanmo.info/posts/yt-dlp/createissueforniconico/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近ニコニコ動画を久しぶりに見てみて、動画をいくつか \u003ccode\u003eyt-dlp\u003c/code\u003e コマンドによってダウンロードしようとしたところ、パスワードとユーザ名によるログイン機能がうまく機能しない場合があることが分かった。\u003c/p\u003e\n\u003cp\u003e　普段であれば、誰かが勝手に issue でも立てるだろうと放置していただろうが、何を血迷ったのか issue を自分で立てたので、そのことについて記録したい。Issue に関してはすでに yt-dlp の方を見ればわかることなので、周辺情報について適当に書きたい。\u003c/p\u003e\n\u003ch2 id=\"前回の記事\"\u003e前回の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/yt-dlp/bypassagegate/\"\u003eyt-dlpコマンドで、年齢制限を何とかする\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/yt-dlp/bypassagegate2/\"\u003eyt-dlpコマンドで、年齢制限を何とかするの追記\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"issue-へのリンク\"\u003eissue へのリンク\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e[niconico] Unable to log in: HTTP Error 404: Not Found (caused by \u0026lt;HTTPError 404: Not Found\u0026gt;) · Issue #17667 · yt-dlp/yt-dlp\u003cbr\u003e\n\u003ca href=\"https://github.com/yt-dlp/yt-dlp/issues/17667\"\u003ehttps://github.com/yt-dlp/yt-dlp/issues/17667\u003c/a\u003e (2026年9月11日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"yt-dlp-をコンパイルする\"\u003eyt-dlp をコンパイルする\u003c/h2\u003e\n\u003cp\u003e　前提条件として、すでに作業ディレクトを作成して移動しており、anaconda 環境であることと、Linux 環境であることを置く。ニコニコ動画に関していくつか API エンドポイントの URL について候補があり試したかったというのがあり、コードを改変したあと、コンパイルする必要がったことが背景にある。結局どれもうまくいかなかったが。\u003c/p\u003e\n\u003ch3 id=\"リポジトリをクローン\"\u003eリポジトリをクローン\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://github.com/yt-dlp/yt-dlp.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd yt-dlp\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"環境を作成\"\u003e環境を作成\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda create -n ytDlp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda activate ytDlp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda install python\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda install pip\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"依存関係のインストールやコンパイルバイナリ生成\"\u003e依存関係のインストールやコンパイル、バイナリ生成\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://github.com/yt-dlp/yt-dlp#compile\"\u003eyt-dlpリポジトリのコンパイルの項目\u003c/a\u003eを参考に、以下のようにして yt-dlp のバイナリを生成する。\u003c/p\u003e","title":"ニコニコ動画にパスワードログインできない件について、yt-dlp のリポジトリに issue を立ててしまう"},{"content":"この記事を作った動機 Onenote代替品の作成の研究の一環で、pexpect を使って端末のセッションを維持させながらとにかくコマンドを実行させたいということがあり、その過程で試行錯誤があったため記録したい。\n現状使っているもの 以下は現状使っている実装の参考例である。一定時間置いた後に、1000文字(出力に対して、十分大きい数字を設定する)ずつターミナルを読み出している。作ったセッション内のターミナルに何が出力されるかわからないが、とにかくコマンドを実行させて、その結果を出力することに以下のスクリプトは特化している。\n待ち時間は適宜調整する必要がある。\nスクリプト本体 (新しい 2026/9/21 時点) import pexpect,time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;,timeout=5, encoding=\u0026#39;utf-8\u0026#39;) session.logfile_read = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.flush() session.read_nonblocking(1000,timeout=None) session.sendline(\u0026#34;gcc\u0026#34;) time.sleep(1) session.flush() session.read_nonblocking(1000,timeout=None) スクリプト本体 (古い) 一定時間置いたあとに、何でもマッチングするexpectを配置しているのは、標準出力であるstdoutに対して、コマンドの実行結果を吐き出させたいためである。\nimport pexpect,time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;,timeout=5, encoding=\u0026#39;utf-8\u0026#39;) session.logfile_read = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.expect(\u0026#34;.+\u0026#34;) session.sendline(\u0026#34;gcc\u0026#34;) time.sleep(1) session.expect(\u0026#34;.+\u0026#34;) 実行結果 python main1.py ls # ⠀aaaa ⠀main.py ⠀main1.py ⠀readme.md ⠀test/ gcc # gcc: fatal error: 入力ファイルがありません # compilation terminated. 追記 (2026/9/16) このやり方は非常に簡易的にしか動作せず、副作用があることが分かった。具体的には\u0026quot;.+\u0026ldquo;でexpectさせるとログが出てくるのは、pexpectが期待した文字列を待機している状態になるからであることが分かった。つまるところ、タイムアウトに引っかかると例外を出して強制終了してしまう。\nそれを防ぐには、pexpectにおいては、waitという専用の関数があるため、それを利用することができることが分かった。ただこれだとログが出てこない(\u0026rdquo;.*\u0026ldquo;と同じ挙動になる)ため、なにかさらに工夫が必要そうなことが分かっている。\nまた、pexpect にて同じ端末に出力を出させると端末の表示がぐちゃぐちゃになってしまう。最近考えていることとして個別にファイルとしてlogをテキストファイルとして書き出させてそれをwatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;みたいにすればよいのではないかと思い始めている。\n追記 (2026/9/21) 最近新しいやり方として、flush関数とread_nonblockingの2つを組み合わせてコマンドの実行結果を出力させることができることが分かった。その方法だと今のところタイムアウトの例外にもならず、プログラムを常駐させ続けたりすることに成功したため、そっちの方を今後は採用したいと思った。\nそのやり方を始めて実装したのは、hello30190f/Modular-MCP-Server においてであり、以下のような実装になっている。以下の実装では、5 FPS くらいで 1 秒間に 100 * 5 で 500 文字ほど端末にログがなにかあれば出力するようになっている。以下のコードは常駐プロセスがセッション内にあるときに無限ループで CPU を使いすぎない程度に busy wait しているコードであり、各ループにおいてログを押し出すようにしたものである。\ndef waitForever(session:pexpect.spawn) -\u0026gt; None: try: while True: session.flush() session.read_nonblocking(size=100,timeout=None) # pexpectForceUpdate(session) time.sleep(0.2) except KeyboardInterrupt: print(\u0026#34;The MCPServer will shutdown.\u0026#34;) sys.exit(0) except pexpect.exceptions.TIMEOUT: print(\u0026#34;This is bug. Please start this server again\u0026#34;) pass うまくいかなかったこと 単にsendlineする 単にsendlineすると、コマンド自体は実行されるが、一切標準出力にログが出力されないことになる。\nスクリプト本体 import pexpect import time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;,timeout=5, encoding=\u0026#39;utf-8\u0026#39;) session.logfile_read = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.sendline(\u0026#34;echo test \u0026gt; test1\u0026#34;) time.sleep(1) 実行結果 python main2.py # 何も出てこない cat test1 # test エンコードを指定しない 端末のセッションを作るときに、文字コードを明示しなかった場合、そもそもスクリプトを実行できないことがある。\nスクリプト本体 import pexpect import time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;) session.logfile = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.sendline(\u0026#34;echo test \u0026gt; test1\u0026#34;) time.sleep(1) 実行結果 python main3.py # Traceback (most recent call last): # File \u0026#34;/home/UserName/work/free/2026-09-08-23-14-06-1788876846/main3.py\u0026#34;, line 7, in \u0026lt;module\u0026gt; # session.sendline(\u0026#34;ls\u0026#34;) # ~~~~~~~~~~~~~~~~^^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/site-packages/pexpect/pty_spawn.py\u0026#34;, line 578, in sendline # return self.send(s + self.linesep) # ~~~~~~~~~^^^^^^^^^^^^^^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/site-packages/pexpect/pty_spawn.py\u0026#34;, line 566, in send # self._log(s, \u0026#39;send\u0026#39;) # ~~~~~~~~~^^^^^^^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/site-packages/pexpect/spawnbase.py\u0026#34;, line 129, in _log # self.logfile.write(s) # ~~~~~~~~~~~~~~~~~~^^^ # TypeError: write() argument must be str, not bytes *を expect させる 不正な正規表現になり、*が繰り返すべき文字列が指定されていないというエラーになる。\nスクリプト本体 import pexpect import time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;,timeout=5, encoding=\u0026#39;utf-8\u0026#39;) session.logfile_read = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.expect(\u0026#34;*\u0026#34;) session.sendline(\u0026#34;gcc\u0026#34;) time.sleep(1) session.expect(\u0026#34;*\u0026#34;) 実行結果 python main4.py # Traceback (most recent call last): # File \u0026#34;/home/UserName/work/free/2026-09-08-23-14-06-1788876846/main4.py\u0026#34;, line 9, in \u0026lt;module\u0026gt; # session.expect(\u0026#34;*\u0026#34;) # ~~~~~~~~~~~~~~^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/site-packages/pexpect/spawnbase.py\u0026#34;, line 353, in expect # compiled_pattern_list = self.compile_pattern_list(pattern) # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/site-packages/pexpect/spawnbase.py\u0026#34;, line 242, in compile_pattern_list # compiled_pattern_list.append(re.compile(p, compile_flags)) # ~~~~~~~~~~^^^^^^^^^^^^^^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/__init__.py\u0026#34;, line 289, in compile # return _compile(pattern, flags) # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/__init__.py\u0026#34;, line 350, in _compile # p = _compiler.compile(pattern, flags) # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/_compiler.py\u0026#34;, line 762, in compile # p = _parser.parse(p, flags) # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/_parser.py\u0026#34;, line 973, in parse # p = _parse_sub(source, state, flags \u0026amp; SRE_FLAG_VERBOSE, 0) # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/_parser.py\u0026#34;, line 460, in _parse_sub # itemsappend(_parse(source, state, verbose, nested + 1, # ~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ # not nested and not items)) # ^^^^^^^^^^^^^^^^^^^^^^^^^ # File \u0026#34;/home/UserName/.conda/envs/test/lib/python3.14/re/_parser.py\u0026#34;, line 687, in _parse # raise source.error(\u0026#34;nothing to repeat\u0026#34;, # source.tell() - here + len(this)) # re.PatternError: nothing to repeat at position 0 .*を expect させる 様々な文字列を表す、.を*によって無限回の繰り返しとして、全てにマッチングするようにするとエラーは出てこないが、標準出力に実行結果が出てこない結末となる。\nスクリプト本体 import pexpect import time,sys session = pexpect.spawn(\u0026#34;/bin/bash\u0026#34;,timeout=5, encoding=\u0026#39;utf-8\u0026#39;) session.logfile_read = sys.stdout session.sendline(\u0026#34;ls\u0026#34;) time.sleep(1) session.expect(\u0026#34;.*\u0026#34;) session.sendline(\u0026#34;gcc\u0026#34;) time.sleep(1) session.expect(\u0026#34;.*\u0026#34;) 実行結果 python main5.py # 何も出力されない 使った画像とか www.python.org, GPL http://www.gnu.org/licenses/gpl.html, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Python-logo-notext.svg (2026年9月9日) 参考にしたサイトとか Python how to read output from pexpect child? - Stack Overflow\nhttps://stackoverflow.com/questions/17632010/python-how-to-read-output-from-pexpect-child (2026年9月8日)\nAPI Overview — Pexpect 4.8 documentation\nhttps://pexpect.readthedocs.io/en/stable/overview.html (2026年9月8日)\nPython Getting Data Types\nhttps://www.w3schools.com/python/gloss_python_getting_data_type.asp (2026年9月9日)\nCore pexpect components — Pexpect 4.8 documentation\nhttps://pexpect.readthedocs.io/en/stable/api/pexpect.html#pexpect.spawn.wait (2026年9月16日)\n","permalink":"https://www.nyanmo.info/posts/other/python/makepexpectnottoexpect/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/\"\u003eOnenote代替品の作成\u003c/a\u003eの研究の一環で、pexpect を使って端末のセッションを維持させながらとにかくコマンドを実行させたいということがあり、その過程で試行錯誤があったため記録したい。\u003c/p\u003e\n\u003ch2 id=\"現状使っているもの\"\u003e現状使っているもの\u003c/h2\u003e\n\u003cp\u003e　以下は現状使っている実装の参考例である。一定時間置いた後に、1000文字(出力に対して、十分大きい数字を設定する)ずつターミナルを読み出している。作ったセッション内のターミナルに何が出力されるかわからないが、とにかくコマンドを実行させて、その結果を出力することに以下のスクリプトは特化している。\u003c/p\u003e\n\u003cp\u003e　待ち時間は適宜調整する必要がある。\u003c/p\u003e\n\u003ch3 id=\"スクリプト本体-新しい-2026921-時点\"\u003eスクリプト本体 (新しい 2026/9/21 時点)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e pexpect\u003cspan style=\"color:#f92672\"\u003e,\u003c/span\u003etime\u003cspan style=\"color:#f92672\"\u003e,\u003c/span\u003esys\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pexpect\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003espawn(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/bin/bash\u0026#34;\u003c/span\u003e,timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e, encoding\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;utf-8\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elogfile_read \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sys\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estdout\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esendline(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ls\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etime\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eflush()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread_nonblocking(\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e,timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eNone\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esendline(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;gcc\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etime\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eflush()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread_nonblocking(\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e,timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eNone\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"スクリプト本体-古い\"\u003eスクリプト本体 (古い)\u003c/h3\u003e\n\u003cp\u003e　一定時間置いたあとに、何でもマッチングする\u003ccode\u003eexpect\u003c/code\u003eを配置しているのは、標準出力である\u003ccode\u003estdout\u003c/code\u003eに対して、コマンドの実行結果を吐き出させたいためである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e pexpect\u003cspan style=\"color:#f92672\"\u003e,\u003c/span\u003etime\u003cspan style=\"color:#f92672\"\u003e,\u003c/span\u003esys\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e pexpect\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003espawn(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/bin/bash\u0026#34;\u003c/span\u003e,timeout\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e, encoding\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;utf-8\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elogfile_read \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sys\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estdout\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esendline(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ls\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etime\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexpect(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.+\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esendline(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;gcc\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etime\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esleep(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esession\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexpect(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.+\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"実行結果\"\u003e実行結果\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython main1.py\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ⠀aaaa  ⠀main.py  ⠀main1.py  ⠀readme.md  ⠀test/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# gcc: fatal error: 入力ファイルがありません\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# compilation terminated.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"追記-2026916\"\u003e追記 (2026/9/16)\u003c/h3\u003e\n\u003cp\u003e　このやり方は非常に簡易的にしか動作せず、副作用があることが分かった。具体的には\u0026quot;.+\u0026ldquo;でexpectさせるとログが出てくるのは、pexpectが期待した文字列を待機している状態になるからであることが分かった。つまるところ、タイムアウトに引っかかると例外を出して強制終了してしまう。\u003c/p\u003e\n\u003cp\u003e　それを防ぐには、pexpectにおいては、waitという専用の関数があるため、それを利用することができることが分かった。ただこれだとログが出てこない(\u0026rdquo;.*\u0026ldquo;と同じ挙動になる)ため、なにかさらに工夫が必要そうなことが分かっている。\u003c/p\u003e\n\u003cp\u003e　また、pexpect にて同じ端末に出力を出させると端末の表示がぐちゃぐちゃになってしまう。最近考えていることとして個別にファイルとしてlogをテキストファイルとして書き出させてそれを\u003ccode\u003ewatch -n 0.1 \u0026quot;cat log | tail -n 10\u0026quot;\u003c/code\u003eみたいにすればよいのではないかと思い始めている。\u003c/p\u003e","title":"pexpect において、標準出力にログを出力させながら、端末の出力に関係なくコマンドを実行させたいとき"},{"content":"この記事を作った動機 2026/9/9 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 コントローラープロセス間のファイル書き込み衝突を回避する実装 Core拡張機能と、コントローラーにおいて、設定を伝搬するように実装 拡張モジュールにmainSysから共通で提供する関数(インターフェース)を引数として辞書型などにまとめ、モジュールに渡して呼び出せるようにする コントローラーのログを見えるように、マルチプロセッシングに関して調べる コントローラー間をマルチプロセッシングライブラリのIPC実装でつなげる pexpect の端末セッションや、マルチプロセッシングで独立したプロセスとして動くプロセスのそれぞれの出力は、独立したターミナルを立ち上げるようにする。GUI環境であれば、GUIのインストールされているターミナルエミュレーターを複数起動し、それぞれのセッションやプロセスに端末を1つずつ割り当て、ログの可読性向上を図る。 拡張機能を読み込み終わったあと、依存関係に関して不足がないか確認する処理を導入する。具体的には各拡張機能の依存関係リストに対して、読み込んだ拡張機能を線形探索で単純にそれぞれ照合して不足がないか確認する。 卒論の試作物から、フロントエンドをコピーしてきて、今回の試作物の DataServer の動作検証ができるように改変する。Core拡張機能の呼び出し名に対応させ、割り込みとコマンドに関して、それぞれが独立してwebsocket接続を持つようにする。 やったことの詳細 DataServer の起動オプションを追加 DataServer について、拡張機能を読み込むだけの動作と、読み込んだ拡張機能をもとに、DataServer を起動させようとすることを分けてユーザーが明示してそれぞれ操作できるようにするために、argparseライブラリによって以下のようになるように実装した。\n以下は、argparseに関する実装が正しくできたかテストした様子である。引数に対してどう動作するか確かめたかったので、実際に拡張機能を読み込んだり、DataServer を起動する機能は一時的にコメントアウトしてテストした。何も出力がターミナルに出ていないとき、引数が受理され、正常に動作したことを示す。\npython main.py --loadExtension # 何も出力しない python main.py --startServer # 何も出力しない python main.py --loadExtension --startServer #--loadExtension and --startServer cannot be set at the same time. python main.py --loadExtension aaa #usage: main.py [-h] [--loadExtension] [--startServer] #main.py: error: unrecognized arguments: aaa Core 拡張機能の機能を一時的に制限 卒論で書いた試作物のフロントエンドと今回試作している DataServer 間で一旦動作を確認したいため、すでに実装がある程度できており、卒論時点で動いていたモジュールに限定して動作するように実装を変更した。\n変更前 { \u0026#34;name\u0026#34;: \u0026#34;Core\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;589fe65d-639c-42a3-b395-fca2143afd75\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;Manage notebook and pages. Provide basic notebook interface.\u0026#34;, \u0026#34;frontend\u0026#34;:{ \u0026#34;modules\u0026#34;: [] }, \u0026#34;DataServer\u0026#34;:{ \u0026#34;CommandModules\u0026#34;:[ \u0026#34;backend/commands/info.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deleteNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/getPageType.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/pageInfo.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/updatePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/copyPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deletePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/movePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/renamePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/addTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deleteTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/getTagList.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/queryTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/removeTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileAdd.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileData.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileDelete.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileInfo.py\u0026#34; ], \u0026#34;InterruptModules\u0026#34;:[ \u0026#34;backend/interrupts/newInfo.py\u0026#34;, \u0026#34;backend/interrupts/updatePage.py\u0026#34;, \u0026#34;backend/interrupts/updateTag.py\u0026#34; ], \u0026#34;TaskModules\u0026#34;:[ \u0026#34;backend/tasks/pageCleaner.py\u0026#34;, \u0026#34;backend/tasks/showPingMessage.py\u0026#34; ] }, \u0026#34;extensionDependencies\u0026#34;:[ ] } 変更後 { \u0026#34;name\u0026#34;: \u0026#34;Core\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;589fe65d-639c-42a3-b395-fca2143afd75\u0026#34;, \u0026#34;description\u0026#34;: \u0026#34;Manage notebook and pages. Provide basic notebook interface.\u0026#34;, \u0026#34;frontend\u0026#34;:{ \u0026#34;modules\u0026#34;: [] }, \u0026#34;DataServer\u0026#34;:{ \u0026#34;CommandModules\u0026#34;:[ \u0026#34;backend/commands/info.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deleteNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/getPageType.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/pageInfo.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/updatePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/copyPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deletePage.py\u0026#34; ], \u0026#34;InterruptModules\u0026#34;:[ \u0026#34;backend/interrupts/newInfo.py\u0026#34;, \u0026#34;backend/interrupts/updatePage.py\u0026#34;, \u0026#34;backend/interrupts/updateTag.py\u0026#34; ], \u0026#34;TaskModules\u0026#34;:[ \u0026#34;backend/tasks/pageCleaner.py\u0026#34;, \u0026#34;backend/tasks/showPingMessage.py\u0026#34; ] }, \u0026#34;extensionDependencies\u0026#34;:[ ] } DataServer における拡張機能読み込みの実装の進捗 とりあえず1つも読み込む拡張機能がないときに、runtime.pyを生成させるところまでは動くようになってきた。\nコンソールのログ python main.py --loadExtension # Current settings ------------------------- # {\u0026#39;backendBaseFolderPath\u0026#39;: \u0026#39;/home/UserName/work/OneNoteAlternative/secondPrototype/backend\u0026#39;} # \u0026lt;class \u0026#39;dict\u0026#39;\u0026gt; # source /home/UserName/work/OneNoteAlternative/secondPrototype/backend/dataServerVenv/bin/activate # # Loading extensions is begun --------------- # Loading extensions is begun --------------- # /home/UserName/work/OneNoteAlternative/secondPrototype/backend # /home/UserName/work/OneNoteAlternative/secondPrototype/backend/extensions/ # /home/UserName/work/OneNoteAlternative/secondPrototype/backend/extensions/runtime/ # /home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/ # /home/UserName/work/OneNoteAlternative/secondPrototype/backend/mainSys/controller/runtime.py # # 0 extensions are found. 生成された空の runtime.py # Command commandExtensionMoludes = { } # Interrupt interruptExtensionMoludes = { } # Task taskExtensionMoludes = { } DataServer 起動において仮想環境を使うように実装 mainSys が用意された仮想環境内で起動するように実装した。これにより、既存のホストマシンの Python 環境をなるべく汚さないようにしている。\nDataServer の設定の実装を二段階に分けた DataServer 起動時において、2つの段階を用意した。基本的には、firewalld を使った経験を背景に実装した。\nfirewalld では、メモリ上に配置されていて、動的に変更される一時的な設定と、ファイルシステム上に配置されていて永続化した設定が保存される2つの設定が存在し、それを真似ている。\nしかし完全に同じというわけではなく、動的な設定もファイルシステム上に書き出される。完全に動的なのではなく、DataServer の mainSys を起動する準備段階において、動的に設定が決定されるというようなものである。　settings.json 永続化した設定が保存される。動的に解決され、バックエンドのパスなど明記されない項目もある。\nmainSys/runtime.json 動的に生成された設定が保存される。現状では主に、バックエンドとノートブックのデータのルートとなるパスがどこかが解決された設定が保存されている。mainSys サブシステム起動時に読み込まれ、それ以降の動作に設定が伝搬するようになっていある。ユーザはこの設定を勝手にいじることは禁止される。\n何も拡張機能がない状態でとりあえず動くようにした とりあえず、卒論のフロントエンドの試作物と今回試作しているものの一部である DataServer が実際に接続できて、動作することが確認できた。 研究に関係ありそうなブログ記事 pexpect において、標準出力にログを出力させながら、端末の出力に関係なくコマンドを実行させたいとき 参考にしたサイトとか Python Virtual Environment - venv\nhttps://www.w3schools.com/python/python_virtualenv.asp (2026年9月8日) venv — Creation of virtual environments — Python 3.14.7 documentation\nhttps://docs.python.org/3/library/venv.html (2026年9月8日) Python how to read output from pexpect child? - Stack Overflow\nhttps://stackoverflow.com/questions/17632010/python-how-to-read-output-from-pexpect-child (2026年9月8日) API Overview — Pexpect 4.8 documentation\nhttps://pexpect.readthedocs.io/en/stable/overview.html (2026年9月8日) Argparse Tutorial — Python 3.14.7 documentation\nhttps://docs.python.org/3/howto/argparse.html (2026年9月8日) Python argparse command line flags without arguments - Stack Overflow\nhttps://stackoverflow.com/questions/8259001/python-argparse-command-line-flags-without-arguments (2026年9月9日) Python Getting Data Types\nhttps://www.w3schools.com/python/gloss_python_getting_data_type.asp (2026年9月9日) Python time.sleep indefinitely - Stack Overflow\nhttps://stackoverflow.com/questions/37402649/python-time-sleep-indefinitely (2026年9月9日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-9-9/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/9/9 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eコントローラープロセス間のファイル書き込み衝突を回避する実装\u003c/li\u003e\n\u003cli\u003eCore拡張機能と、コントローラーにおいて、設定を伝搬するように実装\u003c/li\u003e\n\u003cli\u003e拡張モジュールにmainSysから共通で提供する関数(インターフェース)を引数として辞書型などにまとめ、モジュールに渡して呼び出せるようにする\u003c/li\u003e\n\u003cli\u003eコントローラーのログを見えるように、マルチプロセッシングに関して調べる\u003c/li\u003e\n\u003cli\u003eコントローラー間をマルチプロセッシングライブラリのIPC実装でつなげる\u003c/li\u003e\n\u003cli\u003epexpect の端末セッションや、マルチプロセッシングで独立したプロセスとして動くプロセスのそれぞれの出力は、独立したターミナルを立ち上げるようにする。GUI環境であれば、GUIのインストールされているターミナルエミュレーターを複数起動し、それぞれのセッションやプロセスに端末を1つずつ割り当て、ログの可読性向上を図る。\u003c/li\u003e\n\u003cli\u003e拡張機能を読み込み終わったあと、依存関係に関して不足がないか確認する処理を導入する。具体的には各拡張機能の依存関係リストに対して、読み込んだ拡張機能を線形探索で単純にそれぞれ照合して不足がないか確認する。\u003c/li\u003e\n\u003cli\u003e卒論の試作物から、フロントエンドをコピーしてきて、今回の試作物の DataServer の動作検証ができるように改変する。Core拡張機能の呼び出し名に対応させ、割り込みとコマンドに関して、それぞれが独立してwebsocket接続を持つようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003ch3 id=\"dataserver-の起動オプションを追加\"\u003eDataServer の起動オプションを追加\u003c/h3\u003e\n\u003cp\u003e　DataServer について、拡張機能を読み込むだけの動作と、読み込んだ拡張機能をもとに、DataServer を起動させようとすることを分けてユーザーが明示してそれぞれ操作できるようにするために、\u003ccode\u003eargparse\u003c/code\u003eライブラリによって以下のようになるように実装した。\u003c/p\u003e\n\u003cp\u003e　以下は、\u003ccode\u003eargparse\u003c/code\u003eに関する実装が正しくできたかテストした様子である。引数に対してどう動作するか確かめたかったので、実際に拡張機能を読み込んだり、DataServer を起動する機能は一時的にコメントアウトしてテストした。何も出力がターミナルに出ていないとき、引数が受理され、正常に動作したことを示す。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython main.py --loadExtension \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 何も出力しない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython main.py --startServer\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 何も出力しない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython main.py --loadExtension --startServer\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#--loadExtension and --startServer cannot be set at the same time.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython main.py --loadExtension aaa \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#usage: main.py [-h] [--loadExtension] [--startServer]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#main.py: error: unrecognized arguments: aaa\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"core-拡張機能の機能を一時的に制限\"\u003eCore 拡張機能の機能を一時的に制限\u003c/h3\u003e\n\u003cp\u003e　卒論で書いた試作物のフロントエンドと今回試作している DataServer 間で一旦動作を確認したいため、すでに実装がある程度できており、卒論時点で動いていたモジュールに限定して動作するように実装を変更した。\u003c/p\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003e変更前\u003c/summary\u003e\n  \u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Core\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;UUID\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;589fe65d-639c-42a3-b395-fca2143afd75\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;description\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Manage notebook and pages. Provide basic notebook interface.\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;frontend\u0026#34;\u003c/span\u003e:{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;modules\u0026#34;\u003c/span\u003e: []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;DataServer\u0026#34;\u003c/span\u003e:{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;CommandModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/info.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createNotebook.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deleteNotebook.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/getPageType.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/pageInfo.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/updatePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/copyPage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createPage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deletePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/movePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/renamePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/addTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deleteTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/getTagList.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/queryTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/removeTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileAdd.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileData.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileDelete.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileInfo.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;InterruptModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/newInfo.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/updatePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/updateTag.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;TaskModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/tasks/pageCleaner.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/tasks/showPingMessage.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;extensionDependencies\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"2026/9/9-やったこと"},{"content":"このポエム作成の動機となった記事とか LINE AI トークサジェストがもたらすプライバシー危機：今こそメッセージングアプリを見直す時 • The Cyber Flamingo\nhttps://www.cyberflamingo.net/line-ai-talk-suggest-stop-using-line/ (2026年9月5日) 関係ありそうな記事 Mailcow を使いたい Google Chrome で AI モード と AI Overview を止めたい (uBlock Origin についても言及あり) なんとなく書いただけの文章 2023~2025年に LINE 殺意マシマシでスマホを殴りつけながら仕方なく使っていることがあった。毎回ユーザの足元を見ながら改悪してくことについて、検索してもろくな記事出てこないなと思っていたことがあった。しかし、ついに2026年になってようやく LINE について否定的な記事が出てきた気がするので、自分がどうしているか、記事にしてみようかなと思ったところである。\nLINE についてそもそも私個人として看過きないとしている項目はすぐに思いつくものは以下のとおりである。\nAI 機能と称して、LLM を強制的に組み込み、完全に無効化するオプションをなくして、一ヶ月くらいだけその項目を出さないようにするというオプションしかない。ユーザの拒否権を尊重しない態度である。 メッセージ削除を有料機能として人間関係を人質に取ろうとしている。 もとからシェアが偏っており、多くの日本人が日常的に使い、日本郵便など様々なサービスが LINE に提携しており、偏って少なくとも日本国内において力を持っている。 情報技術に疎い層をダークパターンであからさまに狙い撃ちしている。広告ドメインを、LINE メッセージ本文と一緒にすることで広告ブロックを妨害するなど、意地でもユーザを支配しようとする。 現状は買収により、ヤフー傘下のサービスであり、かつ斜陽のサービスで、どう考えても特定の層の日本人を狙い撃ちする以外の意図が見えない。LINE スタンプが、LINE以外で使えないとかは、確実にすでに既存のユーザかつ技術や自らの権利に興味関心を積極的に持たない疎い層にとって刺さっていると思われる。 疎い大多数を利用することで、無理やり技術や権利に積極的な層もねじ伏せられているように見受けられる。現状をわかっている人にとって、LINE は消極的な選択肢として、連絡手段として存在しているということだと思われる。 LINE Lite などのメッセージングだけに特化したシンプルで必要十分なアプリを削除し、ショート動画サービスの真似事を使いたくないユーザにも押し付けてくるなど、ユーザに対して実装が上から目線すぎるし、明らかに大多数の相手が誰かわかったうえで実装されているようにしか見受けられない。 ほとんどの人が利用規約を読んでいないとわかっていながら、都合のいいように内容を書き換えていると思われる。重要な項目は完結に短く、大きく提示するとかもなく、ユーザに責任やリスクを転嫁しようとする姿勢が多々見受けられる。 既存のユーザに対して茹でカエルの現象が起こっているおそれがある。段階的な改悪の導入は、一定の鈍感な層の離脱を防ぐ目的があると思われる。 これら問題から、私が出した現状の答えとしては、E-mailへの回帰と、RCSメッセージの利用である。RCSメッセージに関係する Google 自体も、かなり LINE と似たような問題を持っているため、自前のドメインとメールサーバによる運用を併用し、重要なやり取りはメールで行うようにする方向性になってきている。結局のところ、中央集権的なアーキテクチャのアプリや SAAS などは極力使いたくない。使用に伴うリスクと代償があまりにも大きすぎる。私はそれらに対して、政治的にも加担したくないので、私個人にまつわることとしては徹底的に排除したい。いづれにせよ、LINE は改悪の兆候があったわけで、前々から使いたくないが、人間関係や仕事のために仕方なくというベンダーロックインの話自体はネットにあったが、最近の改悪ぶりはいよいよという感じである。\nE-mail の回帰については、自前でサーバを持ったりすること自体は、セキュリティを考慮する必要もあり、ある程度ネットワークに理解がある必要もあり、万人には勧められないことかもしれない。しかし、Proton Mail など、既存の様々な代替手段を検討するだけでもやらないよりはマシだと思われる。理想をいえば、メールをバックエンドにしてメッセージングアプリを作るというのも1つある提案だと思われる。というか多分すでにある気もする。\n少なくとも私の身の回りでは、重要なことはメールで進むことがそもそも多く、LINE は例えば大学では学生同士に関するやり取りに使われていたことが主だったように思う。最近は本格的に LINE は廃止方向にしており、身内とのやり取りには使用を禁止とし、現状の LINE は LINE 以外の手段が完全に死んだときだけに消極的に、かつ一時的に残しているに過ぎない。そう遠くないうちにアカウント削除も検討している。また LINE はスマホでは利用を禁止し、PC 版(純粋なメッセージ機能のみの実装となっているため、広告も出ない)のみの利用とする。\nそもそも LINE がなければ回らないという現場があった場合、それはその現場の問題であり、それに巻き込まれた人の問題ではないとする。現状の LINE は私からすれば確信犯的に、実装をしているということにしか映っていない。そもそもサービスのもとでからしても信頼できないとする。現状の LINE とは、LINE が始まった当初の 2010年代に最初にターゲット？となった、シェアを支えることとなった層に回帰しようとしているのかもしれない。具体的なことはあえて言わないが。\n私がメールを重要視しているのは、それが古臭く思われようが、それが結局なんだかんだいって最低限の機能はありつつ、伝送における暗号化もあり、現状で現実的で実用的な選択肢であり続けていることがある。スタンプ機能なんてオプションだし、そんなのに囚われて振り回されるなんて溜まったものじゃないのでとっとと捨てる。スタンプ的な機能がほしけりゃ適当に GIF 画像でも作って添付すればいいだろう。自分でサーバを持つことができ、一方的に運用に関して干渉されるリスクは、LINE やそれに類似するチャットサービスに比べればマシだろう。そもそも LINE でやり取りする相手が、本当に自分にとって必要な存在なのか疑問である。別に、他の人が LINE を使っていることを否定するつもりはないが、私に関して影響が出るなら、黙ってはいられない。\n結局私にとって LINE の何が問題なのかと言えば、力を持っていて、それを自覚しながら、悪意のある実装やサービス運用をしているということにあるのだと、簡単に言えば思われる。私の言う悪意とは、実態に基づいて実害があるか、リスクがあるかということを意味している。いくら運営や開発が、合法や大衆を理由にしようとも、実態に基づかないことは私からすれば無効である。合法であることは、問題がないことを意味していないし、ルールに無数に穴があることは古典的な問題である。守ることが目的化したルールは正当ではなく、機能していないと考えられる。大衆はあくまで数と強制力の問題であり、正当性の根拠ではなく、正当だと思われやすいトレードマークである。単に、シンプルに信頼性のあるメッセージングアプリとしてわきまえない姿勢や態度は、私を苛立たせ、怒らせて、代替手段に移行するのに時間を使わせるのに、十分だったということである。真っ当にサービスを提供しなかった LINE やそれに類似するものは、看過できない。\nじゃあ、私がここまでのことから、LINE の関係者である、または関係者であった存在を一概に嫌ったり否定するかといえば、それも否定する。それは、それら関係者に問題がある存在がいないという意味ではない。様々な個別の事情があることから、組織やサービスと、それに関わった人を分けて考える必要があるとする。私は、LINE 社内にいたわけでもないので、あくまで利用者の立場として、これからどうするかということと、LINE と自分との関係性について、過去を振り返ったに過ぎない。憶測もあるし、受け入れがたい、嫌いという感情から、この記事には強い言葉が使われている。\n私は LINE に限らず、リアルで実際に関係がある人と連絡を取る以外の用途におけるチャット的な情報伝達について否定的である。これはネットだけのつながりを主とするものを否定するものではない。しかし私にまつわることとしては、いわゆる SNS と呼ばれている物は生涯利用したくない。他人のことに振り回されている暇があれば、物理的に身近なことや自分のことをしたいと思う。他人が出す情報については、情報発信者が情報発信の媒体も運用しているブログなど、情報発信と情報の管理者が一体となった自立した情報源や、プログラミング言語やライブラリに関するドキュメントなど、なるべく自立した存在のものを優先したいと考える。\nまた LINE に起こっている問題は、LINE 特有だとは考えない。私個人の感想としては、2015年以降に見られる、Tech 関連企業においてそれぞれ見られる傾向を LINE も踏んだに過ぎないとする。UI が大きく今ある風に変わり、YouTubeはフラッシュによる動画配信をHTML5による配信に置き換えたあの時代が、今もこうして引きづられているに過ぎないとする。Windows で言えば、LINE で起こっている問題に相当するのは、アカウントにログインすることの強要やコパイロット強制や、勝手に画面をスクショする問題に加えて、元からMSアカウントでログインしたら勝手にデスクトップなどをOneDriveにユーザの同意なくアップロードし始め、5GB制限で課金を突然迫るなど、私が知っているだけでも 10 年以上にわたるユーザ軽視や侵害とも取れる一連の実装が挙げられる。\n2015年から2020年くらいは、やられたときに、その都度ワークアラウンドをあてがってきて、それで利用者として問題を押さえつけてきた感じであるが、2020年以降に関しては、そうとも言ってられなくなっていった気がする。Linux 環境に移行するきっかけになったし、今まで使っていたあらゆる物事を見直すことにはなった。確かに時代は変わったように思うが、私にとっては\u0026quot;当たり前だと思っていることは当たり前じゃない\u0026quot;ことを明確に実体験を伴って突きつけられる結果となっているように思う。\n","permalink":"https://www.nyanmo.info/posts/poem/nomoreline/","summary":"\u003ch2 id=\"このポエム作成の動機となった記事とか\"\u003eこのポエム作成の動機となった記事とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLINE AI トークサジェストがもたらすプライバシー危機：今こそメッセージングアプリを見直す時 • The Cyber Flamingo\u003cbr\u003e\n\u003ca href=\"https://www.cyberflamingo.net/line-ai-talk-suggest-stop-using-line/\"\u003ehttps://www.cyberflamingo.net/line-ai-talk-suggest-stop-using-line/\u003c/a\u003e (2026年9月5日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"関係ありそうな記事\"\u003e関係ありそうな記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/mailcow/\"\u003eMailcow を使いたい\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/stopgooglechromefromshowingaimode/\"\u003eGoogle Chrome で AI モード と AI Overview を止めたい (uBlock Origin についても言及あり)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"なんとなく書いただけの文章\"\u003eなんとなく書いただけの文章\u003c/h2\u003e\n\u003cp\u003e　2023~2025年に LINE 殺意マシマシでスマホを殴りつけながら仕方なく使っていることがあった。毎回ユーザの足元を見ながら改悪してくことについて、検索してもろくな記事出てこないなと思っていたことがあった。しかし、ついに2026年になってようやく LINE について否定的な記事が出てきた気がするので、自分がどうしているか、記事にしてみようかなと思ったところである。\u003c/p\u003e\n\u003cp\u003e　LINE についてそもそも私個人として看過きないとしている項目はすぐに思いつくものは以下のとおりである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAI 機能と称して、LLM を強制的に組み込み、完全に無効化するオプションをなくして、一ヶ月くらいだけその項目を出さないようにするというオプションしかない。ユーザの拒否権を尊重しない態度である。\u003c/li\u003e\n\u003cli\u003eメッセージ削除を有料機能として人間関係を人質に取ろうとしている。\u003c/li\u003e\n\u003cli\u003eもとからシェアが偏っており、多くの日本人が日常的に使い、日本郵便など様々なサービスが LINE に提携しており、偏って少なくとも日本国内において力を持っている。\u003c/li\u003e\n\u003cli\u003e情報技術に疎い層をダークパターンであからさまに狙い撃ちしている。広告ドメインを、LINE メッセージ本文と一緒にすることで広告ブロックを妨害するなど、意地でもユーザを支配しようとする。\u003c/li\u003e\n\u003cli\u003e現状は買収により、ヤフー傘下のサービスであり、かつ斜陽のサービスで、どう考えても特定の層の日本人を狙い撃ちする以外の意図が見えない。LINE スタンプが、LINE以外で使えないとかは、確実にすでに既存のユーザかつ技術や自らの権利に興味関心を積極的に持たない疎い層にとって刺さっていると思われる。\u003c/li\u003e\n\u003cli\u003e疎い大多数を利用することで、無理やり技術や権利に積極的な層もねじ伏せられているように見受けられる。現状をわかっている人にとって、LINE は消極的な選択肢として、連絡手段として存在しているということだと思われる。\u003c/li\u003e\n\u003cli\u003eLINE Lite などのメッセージングだけに特化したシンプルで必要十分なアプリを削除し、ショート動画サービスの真似事を使いたくないユーザにも押し付けてくるなど、ユーザに対して実装が上から目線すぎるし、明らかに大多数の相手が誰かわかったうえで実装されているようにしか見受けられない。\u003c/li\u003e\n\u003cli\u003eほとんどの人が利用規約を読んでいないとわかっていながら、都合のいいように内容を書き換えていると思われる。重要な項目は完結に短く、大きく提示するとかもなく、ユーザに責任やリスクを転嫁しようとする姿勢が多々見受けられる。\u003c/li\u003e\n\u003cli\u003e既存のユーザに対して茹でカエルの現象が起こっているおそれがある。段階的な改悪の導入は、一定の鈍感な層の離脱を防ぐ目的があると思われる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　これら問題から、私が出した現状の答えとしては、E-mailへの回帰と、RCSメッセージの利用である。RCSメッセージに関係する Google 自体も、かなり LINE と似たような問題を持っているため、自前のドメインとメールサーバによる運用を併用し、重要なやり取りはメールで行うようにする方向性になってきている。結局のところ、中央集権的なアーキテクチャのアプリや SAAS などは極力使いたくない。使用に伴うリスクと代償があまりにも大きすぎる。私はそれらに対して、政治的にも加担したくないので、私個人にまつわることとしては徹底的に排除したい。いづれにせよ、LINE は改悪の兆候があったわけで、前々から使いたくないが、人間関係や仕事のために仕方なくというベンダーロックインの話自体はネットにあったが、最近の改悪ぶりはいよいよという感じである。\u003c/p\u003e\n\u003cp\u003e　E-mail の回帰については、自前でサーバを持ったりすること自体は、セキュリティを考慮する必要もあり、ある程度ネットワークに理解がある必要もあり、万人には勧められないことかもしれない。しかし、Proton Mail など、既存の様々な代替手段を検討するだけでもやらないよりはマシだと思われる。理想をいえば、メールをバックエンドにしてメッセージングアプリを作るというのも1つある提案だと思われる。というか多分すでにある気もする。\u003c/p\u003e\n\u003cp\u003e　少なくとも私の身の回りでは、重要なことはメールで進むことがそもそも多く、LINE は例えば大学では学生同士に関するやり取りに使われていたことが主だったように思う。最近は本格的に LINE は廃止方向にしており、身内とのやり取りには使用を禁止とし、現状の LINE は LINE 以外の手段が完全に死んだときだけに消極的に、かつ一時的に残しているに過ぎない。そう遠くないうちにアカウント削除も検討している。また LINE はスマホでは利用を禁止し、PC 版(純粋なメッセージ機能のみの実装となっているため、広告も出ない)のみの利用とする。\u003c/p\u003e","title":"LINEは使わないようにしている"},{"content":"今回考察する対象の言説 単一の情報を調べるからだめなんだ。複数の情報を同じ対象に対して調べれば偏りはなくなる。ググれカス。\nなんとなく書いただけの文章 複数の情報を同じ物事に対して調べて情報を漁っても、そもそもの情報が偏っていたら話にならない。ネットでは、LLM とかが話題になる以前から、そもそも同じようなことを異なるメディアが発信するという状態が存在しており、現在はそれがよりひどくなっていると思われる。あくまで、複数の情報源を利用することは、リスクを低減しようとする試行錯誤の手段ではあっても、絶対的な対策ではなく、逆に逆手に取られて対策を破られてしまうおそれがある。複数の異なるメディアや異なる記事に見せかけて、特定の方向性に話を持っていこうとするという情報操作はあり得ると思われる。情報を調べた者としては複数の情報にあたったのだから大丈夫だろうと油断し、あくまで緩和策でしかないことを信じ切るという油断があると思われる。これに対する対策は、異なる情報源に触れたことではなく、様々な情報源にあたった上で、どれだけ比較してみて異なる情報が実際のところあったか確かめたり、情報に傾向や偏りがないか調べることが考えられる。また、それをしたうえで、あくまで暫定的であるとする態度を情報に対して崩さないことが重要であると思われる。自分で直接体験して現場を知っているとかでもない限り、情報と付き合うことは常に疑い続けることとセットであり、万能な方法はない。これは情報が有料、無料ということに限らない。\n情報を得るコストが高い情報が複数あり、同じことに対して異なる記述がある場合は比較的リスクは低いかもしれない。逆に情報を得るコストが低い情報は、同じことに対して複数の情報を集めたところで、リスク低減には効果がないか、逆にマイナスになるかもしれない。さらには、情報を得るコストが高いからと言って、必ずしも期待した情報が得られるとは限らない。\n情報を方法によってうまく扱おうとすることは、限界があり、現実的ではないところが多いように見受けられる。汎用に情報にまつわる問題に対処する方法といえば、せいぜい精神的余裕がないことを自覚するとか、情報を受け取ってもすぐには判断せず、必ず寝かせて冷静になってからちょっとづつ考えるとか、そもそも期待している情報が存在しない可能性を考慮するといった、時間をかけた長期的な視点でしか取り組めないことしかないだろう。短期的な視点で、かつリスクを情報において背負いたくなければ、無理してまでそもそも情報を得ようとする事自体をやめたほうがいいかもしれない。情報を得る前に、そもそもなぜ情報を受け取ろうとしているのか、自問自答したほうがいいかもしれない。そこで明確な目的が出てこなければ、それは自分の意思ではないかもしれない。\n複数の情報媒体を合わせることは、異なる立場、異なる利害、異なる都合、異なる背景を持つ情報発信をする存在を組み合わせるということになる。また、異なる存在による情報を複数集めているつもりでも、実際には同じ立場、同じ利害、同じ都合、同じ背景による情報を掴まされている可能性が常にあり、情報発信者がどうやって情報を作っているかをすべて検証したり知ることは読者にはできないことに留意する必要がある。\n私個人としては、ネット、テレビ、新聞、ラジオ、LLMやAIだと呼ばれている物など様々な情報を媒介するブローカやプラットフォームのようなものは、どれかに優劣があるということではなく、それぞれの情報の性質や傾向は異なれど、基本的には信頼できないと考える。実際に当事者として体験したこと以上に信用できる情報はないと考える。それ以外の情報においては、どれも優劣は基本的にないと考える。何かを仲介したり媒介して情報が出てくるまでにブラックボックスがある物事は、どの媒体や複数の情報であっても何を使えば有利だとか賢いということはなく、それぞれの情報を媒介するブラックボックスを持つ物事は、相殺し合うようにメリットとデメリットと言えるものを持っていて、どれがいいとは一概に言えないと思われる。\nさらには、情報には、特別な共謀や悪意がなくても、暗黙の了解や集団内で共有されたことを異なる情報間で暗黙の前提として無自覚に書き手、読み手の多くがそのままにしていることがあり、それが情報に偏りと誤った確信を与えてしまうおそれがある。すべての情報の偏りが悪いとは言えないかもしれないが、それはすべての情報の偏りが良い、無害であるとも言えないことを意味している。問題のある情報は、表向きの顔としては、”正統で客観的で理性的で冷静で正しいことだ”と決めつけられているという可能性さえある。\n賢く情報を選別したり選べるという話は、循環ているところが見受けられる。うまく情報を扱うための方法に関する情報が一体どこから来るのかという問題を持っている。厳密には、うまく情報を扱う方法は、完全体としては存在することが物理的にできないと考えられる。無限の時間やリソースを要求しており、物理の学問で言う実際には観測できない論理上の神視点の値である\u0026quot;真値\u0026quot;と同じであるとそれは考えられる。現実には、各個人や各組織が、できる限りの範囲で、できる限りの視野で、常に決断や判断を迫られて存在しており、失敗したり間違えることをどんなことに対しても防ぐことはできない。あくまで、結果として、事例として、成功したり問題が起こらなかったこともあったかもしれないという程度が限界だと考えられる。\n検索のあり方について (ポエム追加 2026/10/31) 単純にワード検索において、\u0026quot;-[対象のワード]\u0026ldquo;とすることで、不適切であったり的はずれな情報源が頻繁に使う言葉を狙い撃ちすることが考えられる。それで期待した情報が出て来ない場合、それは検索が下手くそだったりするのではなく、調べたいトピックに関して作られている記事やコンテンツがないということを意味している可能性がある。情報がないということがわかること自体が、1つの情報として捉えられる。情報発信において、ブログ記事を書くきっかけやネタにはなりうるのではないだろうか。\n\u0026ldquo;で検索ワードを囲うことで、特定ワードが含まれていることを強制することもできる。ただそこまでするとだいぶ検索結果はごっそりなくなるものである。それが現実ということでもあるのかもしれないが。\n結局のところ、検索ワードにスペルミスがあったり多少外れた単語で検索しても、ヒットするように検索エンジンを作った結果、不適切なSEO対策で上位にあることが目的な企業サイト、アフリエイトやらなんでも、検索エンジンに特定話題に関して、\u0026ldquo;関連している\u0026quot;と誤認させて、検索エンジンの利用者に不当に干渉したりするサイトが、割り込む隙を与える結果となり、現在のひどい状況が出来上がったのではないかと考えられる。これはインターネットが本来、性善説を前提として作られ、その結果急速に使われるようになりつつ、その過程で様々な性善説が成り立たない社会問題に直面することを繰り返していることに関係しているとも思われる。\nドットコムバブルあたりから考えられていたであろう、広告モデルに基づくビジネスモデルは破綻していると考えられる。破綻している歪みをプラットフォームの利用者に自衛と犠牲を強いて、やられた者が悪いという犯罪者の論理により、押し付けているのが現状だと考えられる。それでいてかつ、自衛の手段として広告ブロックを使っている人を叩いてみたりと、広告モデルに基づくビジネスをしている当事者であると思われる立場の存在による、八つ当たりも甚だしいところが多く見受けられる。\n広告モデルに基づかず、自由に情報発信ができるリスクのある場所と、情報発信は限られているが、有料であったり、条件付きでの利用だったりする場所の2つがあることが必要だと思われる。前者があることで、自由な言論というか、情報発信を確保しつつ、後者があることで、各個人は各個人の最低限の情報基盤を構成するというものである。ここで重要なのは綺麗事を強制しないことである。自由な情報発信の空間にはリスクが伴い、限られた情報空間においては不自由が伴うということが大前提として共有されている必要があり、各個人はそれぞれを必要に応じて使い分けるという前提が必要だと考えられる。\nまた、情報の扱い方の前提として、心身ともに余裕があり、冷静な判断ができるときに取り扱い、余裕がないときは必要最低限に限り、情報はなるべく触れないほうがいいとも考えられる。この前提が成り立つために、情報を受け取らなくなっても、大丈夫なように既存のサービスなどを構築する必要があると考えられる。アカウントを放置しても、勝手に消されないとかの配慮が必要であると考えられる。脅迫的に義務的に活動を迫るSNSなどのプラットフォームは不適切であると考えられる。 ","permalink":"https://www.nyanmo.info/posts/poem/%E6%83%85%E5%A0%B1%E3%81%AE%E9%99%90%E7%95%8C%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/","summary":"\u003ch2 id=\"今回考察する対象の言説\"\u003e今回考察する対象の言説\u003c/h2\u003e\n\u003cp\u003e　単一の情報を調べるからだめなんだ。複数の情報を同じ対象に対して調べれば偏りはなくなる。ググれカス。\u003c/p\u003e\n\u003ch2 id=\"なんとなく書いただけの文章\"\u003eなんとなく書いただけの文章\u003c/h2\u003e\n\u003cp\u003e　複数の情報を同じ物事に対して調べて情報を漁っても、そもそもの情報が偏っていたら話にならない。ネットでは、LLM とかが話題になる以前から、そもそも同じようなことを異なるメディアが発信するという状態が存在しており、現在はそれがよりひどくなっていると思われる。あくまで、複数の情報源を利用することは、リスクを低減しようとする試行錯誤の手段ではあっても、絶対的な対策ではなく、逆に逆手に取られて対策を破られてしまうおそれがある。複数の異なるメディアや異なる記事に見せかけて、特定の方向性に話を持っていこうとするという情報操作はあり得ると思われる。情報を調べた者としては複数の情報にあたったのだから大丈夫だろうと油断し、あくまで緩和策でしかないことを信じ切るという油断があると思われる。これに対する対策は、異なる情報源に触れたことではなく、様々な情報源にあたった上で、どれだけ比較してみて異なる情報が実際のところあったか確かめたり、情報に傾向や偏りがないか調べることが考えられる。また、それをしたうえで、あくまで暫定的であるとする態度を情報に対して崩さないことが重要であると思われる。自分で直接体験して現場を知っているとかでもない限り、情報と付き合うことは常に疑い続けることとセットであり、万能な方法はない。これは情報が有料、無料ということに限らない。\u003c/p\u003e\n\u003cp\u003e　情報を得るコストが高い情報が複数あり、同じことに対して異なる記述がある場合は比較的リスクは低いかもしれない。逆に情報を得るコストが低い情報は、同じことに対して複数の情報を集めたところで、リスク低減には効果がないか、逆にマイナスになるかもしれない。さらには、情報を得るコストが高いからと言って、必ずしも期待した情報が得られるとは限らない。\u003c/p\u003e\n\u003cp\u003e　情報を方法によってうまく扱おうとすることは、限界があり、現実的ではないところが多いように見受けられる。汎用に情報にまつわる問題に対処する方法といえば、せいぜい精神的余裕がないことを自覚するとか、情報を受け取ってもすぐには判断せず、必ず寝かせて冷静になってからちょっとづつ考えるとか、そもそも期待している情報が存在しない可能性を考慮するといった、時間をかけた長期的な視点でしか取り組めないことしかないだろう。短期的な視点で、かつリスクを情報において背負いたくなければ、無理してまでそもそも情報を得ようとする事自体をやめたほうがいいかもしれない。情報を得る前に、そもそもなぜ情報を受け取ろうとしているのか、自問自答したほうがいいかもしれない。そこで明確な目的が出てこなければ、それは自分の意思ではないかもしれない。\u003c/p\u003e\n\u003cp\u003e　複数の情報媒体を合わせることは、異なる立場、異なる利害、異なる都合、異なる背景を持つ情報発信をする存在を組み合わせるということになる。また、異なる存在による情報を複数集めているつもりでも、実際には同じ立場、同じ利害、同じ都合、同じ背景による情報を掴まされている可能性が常にあり、情報発信者がどうやって情報を作っているかをすべて検証したり知ることは読者にはできないことに留意する必要がある。\u003c/p\u003e\n\u003cp\u003e　私個人としては、ネット、テレビ、新聞、ラジオ、LLMやAIだと呼ばれている物など様々な情報を媒介するブローカやプラットフォームのようなものは、どれかに優劣があるということではなく、それぞれの情報の性質や傾向は異なれど、基本的には信頼できないと考える。実際に当事者として体験したこと以上に信用できる情報はないと考える。それ以外の情報においては、どれも優劣は基本的にないと考える。何かを仲介したり媒介して情報が出てくるまでにブラックボックスがある物事は、どの媒体や複数の情報であっても何を使えば有利だとか賢いということはなく、それぞれの情報を媒介するブラックボックスを持つ物事は、相殺し合うようにメリットとデメリットと言えるものを持っていて、どれがいいとは一概に言えないと思われる。\u003c/p\u003e\n\u003cp\u003e　さらには、情報には、特別な共謀や悪意がなくても、暗黙の了解や集団内で共有されたことを異なる情報間で暗黙の前提として無自覚に書き手、読み手の多くがそのままにしていることがあり、それが情報に偏りと誤った確信を与えてしまうおそれがある。すべての情報の偏りが悪いとは言えないかもしれないが、それはすべての情報の偏りが良い、無害であるとも言えないことを意味している。問題のある情報は、表向きの顔としては、”正統で客観的で理性的で冷静で正しいことだ”と決めつけられているという可能性さえある。\u003c/p\u003e\n\u003cp\u003e　賢く情報を選別したり選べるという話は、循環ているところが見受けられる。うまく情報を扱うための方法に関する情報が一体どこから来るのかという問題を持っている。厳密には、うまく情報を扱う方法は、完全体としては存在することが物理的にできないと考えられる。無限の時間やリソースを要求しており、物理の学問で言う実際には観測できない論理上の神視点の値である\u0026quot;真値\u0026quot;と同じであるとそれは考えられる。現実には、各個人や各組織が、できる限りの範囲で、できる限りの視野で、常に決断や判断を迫られて存在しており、失敗したり間違えることをどんなことに対しても防ぐことはできない。あくまで、結果として、事例として、成功したり問題が起こらなかったこともあったかもしれないという程度が限界だと考えられる。\u003c/p\u003e\n\u003ch2 id=\"検索のあり方について-ポエム追加-20261031\"\u003e検索のあり方について (ポエム追加 2026/10/31)\u003c/h2\u003e\n\u003cp\u003e　単純にワード検索において、\u0026quot;-[対象のワード]\u0026ldquo;とすることで、不適切であったり的はずれな情報源が頻繁に使う言葉を狙い撃ちすることが考えられる。それで期待した情報が出て来ない場合、それは検索が下手くそだったりするのではなく、調べたいトピックに関して作られている記事やコンテンツがないということを意味している可能性がある。情報がないということがわかること自体が、1つの情報として捉えられる。情報発信において、ブログ記事を書くきっかけやネタにはなりうるのではないだろうか。\u003cbr\u003e\n　\u0026ldquo;で検索ワードを囲うことで、特定ワードが含まれていることを強制することもできる。ただそこまでするとだいぶ検索結果はごっそりなくなるものである。それが現実ということでもあるのかもしれないが。\u003cbr\u003e\n　結局のところ、検索ワードにスペルミスがあったり多少外れた単語で検索しても、ヒットするように検索エンジンを作った結果、不適切なSEO対策で上位にあることが目的な企業サイト、アフリエイトやらなんでも、検索エンジンに特定話題に関して、\u0026ldquo;関連している\u0026quot;と誤認させて、検索エンジンの利用者に不当に干渉したりするサイトが、割り込む隙を与える結果となり、現在のひどい状況が出来上がったのではないかと考えられる。これはインターネットが本来、性善説を前提として作られ、その結果急速に使われるようになりつつ、その過程で様々な性善説が成り立たない社会問題に直面することを繰り返していることに関係しているとも思われる。\u003cbr\u003e\n　ドットコムバブルあたりから考えられていたであろう、広告モデルに基づくビジネスモデルは破綻していると考えられる。破綻している歪みをプラットフォームの利用者に自衛と犠牲を強いて、やられた者が悪いという犯罪者の論理により、押し付けているのが現状だと考えられる。それでいてかつ、自衛の手段として広告ブロックを使っている人を叩いてみたりと、広告モデルに基づくビジネスをしている当事者であると思われる立場の存在による、八つ当たりも甚だしいところが多く見受けられる。\u003cbr\u003e\n　広告モデルに基づかず、自由に情報発信ができるリスクのある場所と、情報発信は限られているが、有料であったり、条件付きでの利用だったりする場所の2つがあることが必要だと思われる。前者があることで、自由な言論というか、情報発信を確保しつつ、後者があることで、各個人は各個人の最低限の情報基盤を構成するというものである。ここで重要なのは綺麗事を強制しないことである。自由な情報発信の空間にはリスクが伴い、限られた情報空間においては不自由が伴うということが大前提として共有されている必要があり、各個人はそれぞれを必要に応じて使い分けるという前提が必要だと考えられる。\u003cbr\u003e\n　また、情報の扱い方の前提として、心身ともに余裕があり、冷静な判断ができるときに取り扱い、余裕がないときは必要最低限に限り、情報はなるべく触れないほうがいいとも考えられる。この前提が成り立つために、情報を受け取らなくなっても、大丈夫なように既存のサービスなどを構築する必要があると考えられる。アカウントを放置しても、勝手に消されないとかの配慮が必要であると考えられる。脅迫的に義務的に活動を迫るSNSなどのプラットフォームは不適切であると考えられる。\n　\u003c/p\u003e","title":"情報の限界について"},{"content":"ポエムに影響を与えたり書くきっかけを与えたと思われるサイト 「既に他人が書いているから」は、あなたが書かない理由にならない。｜クロネのブログ\nhttps://kurone43.com/tanin/ (2026年9月3日) なんとなく書いただけの文章 誰かが既にやっているかもしれないから、自分はやる意味がないということに関しての詭弁について。\nその詭弁とは、誰かが既にやっているからと言ってそれが別の人々にとって利用可能である事とは異なることがある。\nたとえば、コンビニやスーパーは各地域に一定区間ごとに存在している。これは、それぞれが同じ機能を提供しながら、物理的な距離というコストによって、利用され続けるからである。例えば、東京都心にでっかいスーパやデパートを一つ建てたからと言って、地方や別の地域の人がそれを利用できるということにはならない。そこには移動という物理的なコストが存在しており、物理的には中央集権が成立しないためである。\nこれは、その話に限ったことではなく、様々なことに適用される。例えば一つ完璧なスマホを作ったから、全員がそれを使うということにはならない。シュアが大きい、小さいなど、マーケットの割合として傾向は現れるが、それでも完全に一つのスマホだけとはならない。ここでそれら多様性を成り立たせるコストとは、時代背景と値段という観点が考えられる。まず時代背景に応じて、作れるスマホは物理的に異なる。単純に考えれば、未来のスマホほど同じ価格帯でも高性能になっていき、過去のスマホほど、時代に制約されて低性能なものになる。また、スマホの買い手も、富裕層だけではなく、中流層から貧困層まで、様々な層のニーズがありまた、どの階層に属していてもスマホに求める性能や機能に応じて、どれだけスマホにお金をかける意思があるか、購買意思があるか、それぞれ異なる需要があることは明らかである。スマホを使いたくないけど仕方なく買うという人はあまりスマホにお金をかけたくないかもしれないし、スマホをバリバリに使いたい人は、高性能で高価で使っていて心地よいスマホがほしいかもしれない。同じスマホというジャンルにおいても、同じ事をする競合が存在する事を否定することにはならない。\nもちろん、作るもの次第において、需要や市場の大きさは大きく異なり、母数が小さいので、思うように当たらないということは、よくあることだと思われる。それはその需要が無意味なのではなく、それ以外の需要に対して少なくとも他人から得られる収益や注目という観点からは、不利であるということである。そもそもその事を知るためには調査が必要であり、調査の一環には実際に作って売ってみるなど、実際に試行錯誤してデータを集めるしかないことが多い。基本的に試行錯誤や作ったものと、当事者としての自分は、個人としての自分と結びつけることは推奨されない。相手にしている物事は多様で気まぐれなことであり、制御できないことが多々あるということである。\n既に誰かがやっている事を真似しても完全に同じにはならず、同じジャンル内で、異なる物事として作ったものは成立することになる。また、現実問題として完全な制御など存在しないが、試行錯誤しないことには、どうにもならないという現実からして、誰かと同じような事をやっていることが、必ずしも悪いことだとは限らないということである。何であれ、実際にとにかくやった人に対して、やっていない人は口を挟めないということである。\n別の視点では、人々が共有して同じ物を意味しているつもりでも、実際には異なる物を意味しているというケースもある。言葉上では同じことになっているが、実際にはそうではないということがある。例えば、身近な例では男女という言葉を例に上げると、具体的にどんな容姿をしている存在を男や女だと捉える傾向があるかなどは、大きく個人差が出るところである。それを生物学的な観点から捉えたものを判定の基準に添えているのか、それとも印象で判断しているのか、男や女の例として判定者はどんな体験を持ち出しているか、個人差がないわけがない。\n他の例では、白人と黒人という例もあるだろう。誰を白人だとして、誰を黒人だとするか、それはいろんな解釈があるものであろう。同じ作品を繰り返し見ても、かならず同じ体験や感想になるとは限らないだろう。\n同じ事を意味して意味を共有しているつもりになっているとき、基本的に共有できていると言えそうなものと、できていないと言えそうなものがある。共有できていると言えそうなものは、個人の主観に基づかない物事である。例えば信号機は、赤、青、黄色の三色で構成されるということは、誰に対しても基本的に伝わるであろう。共有できていないと言えそうなものは、好き嫌いだったり、対象に対して、どう感じるかということだったり、対象に対して関係している考えや思想、思い出される記憶、人生で体験してきたことの母集団の偏り、その時その時の状況や都合など、いろんな物事から構成される各個人が対象に結びつけて捉えていることの無数の数々である。ここでいいたいのは、客観的なことが良いということではない。主観的なことが悪いということではない。客観的なことと、主観的なことは不可分に結びついているとは言えるかもしれない。同じ対象に対して、共有できていると言えそうな、客観的な要素があることは、共有できていないと言えそうな主観的な事がそれら対象に対して結びつかない事を保証しない。\n学問でよく設定されるような理想状態は現実には存在しないので、完全な対照実験にもならず、完全に同じ条件で物事を繰り返すことはできない。時間は一度経てば、もう戻らない。異なる時間にやった同じ形式の物事は、どれだけ結果が似通っていても、同じ物にはならないし、同じ影響をもたらすとも、同じ結果になるとは言えない。あくまでそれらは、傾向として、異なる時間にやっても、似たような影響や結果が得られる物事があるということである。それをある程度考慮して、これからやる事を決めようとすることはよく試みられていることであるが、フレーム問題にぶつかり、結局完全にはならない。今の一瞬さえ完全に把握することもできないのにもかかわらず、全てを過去の物事から基づいて”賢く上手くやる”ことが現実的なわけではない。どうしても思うようにならないことは起こる。\nそもそも、同じだと思っていることが、実際には異なることであることを自覚していなかったり把握していないとも言える。それもまた人間の不完全性と認知の限界から説明がつくことだと思われる。\n誰かが既にやっているかもしれないから、自分はやる意味がないということに関しての詭弁には、２つの側面が見受られる。一つは、それを主張する側、もう一つは、それを利用する側（受け取る側）である。\n主張する側は、相手に対してやってほしくないことに関して、そのような詭弁を使う可能性がある。相手に対して、特定の物事をやることが、賢明ではないという主張をすることで、主張者自らは自分を安全圏に置いて、周囲から好印象を引き出そうとしつつ、相手を下げたり、集団内において活動を不利にしたいということがあるのではないかと考えられる。\n利用する側（受け取る側）は、現状の自分を正当化したり、自らの心身に対して言い聞かせて何かを自ら抑制、抑圧するために、そのような詭弁を使う可能性がある。やらなくてもいい理由を作るために、辛いときや余裕がないときなどに、そのような言説を利用する可能性がある。\n","permalink":"https://www.nyanmo.info/posts/poem/%E8%AA%B0%E3%81%8B%E3%81%8C%E3%82%84%E3%81%A3%E3%81%A6%E3%81%84%E3%82%8B%E3%81%8B%E3%82%89%E3%82%84%E3%82%89%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%86%E8%A8%80%E8%AA%AC%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6/","summary":"\u003ch2 id=\"ポエムに影響を与えたり書くきっかけを与えたと思われるサイト\"\u003eポエムに影響を与えたり書くきっかけを与えたと思われるサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e「既に他人が書いているから」は、あなたが書かない理由にならない。｜クロネのブログ\u003cbr\u003e\n\u003ca href=\"https://kurone43.com/tanin/\"\u003ehttps://kurone43.com/tanin/\u003c/a\u003e (2026年9月3日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"なんとなく書いただけの文章\"\u003eなんとなく書いただけの文章\u003c/h2\u003e\n\u003cp\u003e　誰かが既にやっているかもしれないから、自分はやる意味がないということに関しての詭弁について。\u003c/p\u003e\n\u003cp\u003e　その詭弁とは、誰かが既にやっているからと言ってそれが別の人々にとって利用可能である事とは異なることがある。\u003c/p\u003e\n\u003cp\u003e　たとえば、コンビニやスーパーは各地域に一定区間ごとに存在している。これは、それぞれが同じ機能を提供しながら、物理的な距離というコストによって、利用され続けるからである。例えば、東京都心にでっかいスーパやデパートを一つ建てたからと言って、地方や別の地域の人がそれを利用できるということにはならない。そこには移動という物理的なコストが存在しており、物理的には中央集権が成立しないためである。\u003c/p\u003e\n\u003cp\u003e　これは、その話に限ったことではなく、様々なことに適用される。例えば一つ完璧なスマホを作ったから、全員がそれを使うということにはならない。シュアが大きい、小さいなど、マーケットの割合として傾向は現れるが、それでも完全に一つのスマホだけとはならない。ここでそれら多様性を成り立たせるコストとは、時代背景と値段という観点が考えられる。まず時代背景に応じて、作れるスマホは物理的に異なる。単純に考えれば、未来のスマホほど同じ価格帯でも高性能になっていき、過去のスマホほど、時代に制約されて低性能なものになる。また、スマホの買い手も、富裕層だけではなく、中流層から貧困層まで、様々な層のニーズがありまた、どの階層に属していてもスマホに求める性能や機能に応じて、どれだけスマホにお金をかける意思があるか、購買意思があるか、それぞれ異なる需要があることは明らかである。スマホを使いたくないけど仕方なく買うという人はあまりスマホにお金をかけたくないかもしれないし、スマホをバリバリに使いたい人は、高性能で高価で使っていて心地よいスマホがほしいかもしれない。同じスマホというジャンルにおいても、同じ事をする競合が存在する事を否定することにはならない。\u003c/p\u003e\n\u003cp\u003e　もちろん、作るもの次第において、需要や市場の大きさは大きく異なり、母数が小さいので、思うように当たらないということは、よくあることだと思われる。それはその需要が無意味なのではなく、それ以外の需要に対して少なくとも他人から得られる収益や注目という観点からは、不利であるということである。そもそもその事を知るためには調査が必要であり、調査の一環には実際に作って売ってみるなど、実際に試行錯誤してデータを集めるしかないことが多い。基本的に試行錯誤や作ったものと、当事者としての自分は、個人としての自分と結びつけることは推奨されない。相手にしている物事は多様で気まぐれなことであり、制御できないことが多々あるということである。\u003c/p\u003e\n\u003cp\u003e　既に誰かがやっている事を真似しても完全に同じにはならず、同じジャンル内で、異なる物事として作ったものは成立することになる。また、現実問題として完全な制御など存在しないが、試行錯誤しないことには、どうにもならないという現実からして、誰かと同じような事をやっていることが、必ずしも悪いことだとは限らないということである。何であれ、実際にとにかくやった人に対して、やっていない人は口を挟めないということである。\u003c/p\u003e\n\u003cp\u003e　別の視点では、人々が共有して同じ物を意味しているつもりでも、実際には異なる物を意味しているというケースもある。言葉上では同じことになっているが、実際にはそうではないということがある。例えば、身近な例では男女という言葉を例に上げると、具体的にどんな容姿をしている存在を男や女だと捉える傾向があるかなどは、大きく個人差が出るところである。それを生物学的な観点から捉えたものを判定の基準に添えているのか、それとも印象で判断しているのか、男や女の例として判定者はどんな体験を持ち出しているか、個人差がないわけがない。\u003cbr\u003e\n　他の例では、白人と黒人という例もあるだろう。誰を白人だとして、誰を黒人だとするか、それはいろんな解釈があるものであろう。同じ作品を繰り返し見ても、かならず同じ体験や感想になるとは限らないだろう。\u003cbr\u003e\n　同じ事を意味して意味を共有しているつもりになっているとき、基本的に共有できていると言えそうなものと、できていないと言えそうなものがある。共有できていると言えそうなものは、個人の主観に基づかない物事である。例えば信号機は、赤、青、黄色の三色で構成されるということは、誰に対しても基本的に伝わるであろう。共有できていないと言えそうなものは、好き嫌いだったり、対象に対して、どう感じるかということだったり、対象に対して関係している考えや思想、思い出される記憶、人生で体験してきたことの母集団の偏り、その時その時の状況や都合など、いろんな物事から構成される各個人が対象に結びつけて捉えていることの無数の数々である。ここでいいたいのは、客観的なことが良いということではない。主観的なことが悪いということではない。客観的なことと、主観的なことは不可分に結びついているとは言えるかもしれない。同じ対象に対して、共有できていると言えそうな、客観的な要素があることは、共有できていないと言えそうな主観的な事がそれら対象に対して結びつかない事を保証しない。\u003c/p\u003e\n\u003cp\u003e　学問でよく設定されるような理想状態は現実には存在しないので、完全な対照実験にもならず、完全に同じ条件で物事を繰り返すことはできない。時間は一度経てば、もう戻らない。異なる時間にやった同じ形式の物事は、どれだけ結果が似通っていても、同じ物にはならないし、同じ影響をもたらすとも、同じ結果になるとは言えない。あくまでそれらは、傾向として、異なる時間にやっても、似たような影響や結果が得られる物事があるということである。それをある程度考慮して、これからやる事を決めようとすることはよく試みられていることであるが、フレーム問題にぶつかり、結局完全にはならない。今の一瞬さえ完全に把握することもできないのにもかかわらず、全てを過去の物事から基づいて”賢く上手くやる”ことが現実的なわけではない。どうしても思うようにならないことは起こる。\u003c/p\u003e\n\u003cp\u003e　そもそも、同じだと思っていることが、実際には異なることであることを自覚していなかったり把握していないとも言える。それもまた人間の不完全性と認知の限界から説明がつくことだと思われる。\u003c/p\u003e\n\u003cp\u003e　誰かが既にやっているかもしれないから、自分はやる意味がないということに関しての詭弁には、２つの側面が見受られる。一つは、それを主張する側、もう一つは、それを利用する側（受け取る側）である。\u003cbr\u003e\n　主張する側は、相手に対してやってほしくないことに関して、そのような詭弁を使う可能性がある。相手に対して、特定の物事をやることが、賢明ではないという主張をすることで、主張者自らは自分を安全圏に置いて、周囲から好印象を引き出そうとしつつ、相手を下げたり、集団内において活動を不利にしたいということがあるのではないかと考えられる。\u003cbr\u003e\n　利用する側（受け取る側）は、現状の自分を正当化したり、自らの心身に対して言い聞かせて何かを自ら抑制、抑圧するために、そのような詭弁を使う可能性がある。やらなくてもいい理由を作るために、辛いときや余裕がないときなどに、そのような言説を利用する可能性がある。\u003c/p\u003e","title":"誰かがやっているからやらないという言説について"},{"content":"この記事を作った動機 2026/9/2 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 まだ拡張機能の読み込み部分は、とりあえず書いたという段階であり、パスやインポートの記述がおかしかったりするおそれがあり、デバッグが必要である。また、拡張機能を読み込んで DataServer が動作する事を確認するために、Core 拡張機能を完成させる必要がある。\nCore 拡張機能を完成させるためには、主にパスの解決が正しく出来るように、拡張機能のモジュール呼び出しにおいて、どうやってmainSysと提携させるかが課題となっている。今具体的に考えている実装の一つとしては、モジュール呼び出し時に、DataServer のルートのパスや Notebook へのパスは、拡張機能ではない DataServer 側の組み込みの実装としてパスを解決しモジュールに伝える機構を実装することが考えられた。\nまた、mainSysについては、Python の仮想環境機能を使うことが考えられた。依存関係などをインストールするとき、既にインストールされている Python 環境を汚したりしてしまうのは避けたいと考えた。仮想環境は、存在しなければ拡張機能読み込みの段階で初期化し、存在すればそれが DataServer 起動時などに有効化されて使われるというような事を考えている。\n今回の試作物としては、とりあえず DataServer が拡張機能を介して動作するということを最低限の目標としたいと考えた。そこまでできたら次は、3つ目のプロトタイプとして今度はフロントエンドをなんとかするというロードマップにしようかなと作業と進捗状況から思ったところであった。フロントエンドには、zustand のストアにおける値が異なるストア間で重複しているなど、SQLの文脈におけるデータ項目の重複と正規化の問題があり、その点がまず修正点としてあげられる。\nDataServer において、WebSocket によるフロントエンドとの接続に関してセッションを管理したい。フロントエンドが接続してきたら、それぞれのフロントエンド自体をUUIDなどで識別して、正しく Command や Interrupt の経路がつながっているか管理することを考えている。\nやったことの詳細 Core 拡張機能を実装 完全ではないが、とりあえず最低限の機能を DataServer に与えるために、Core 拡張機能を作成し、中身には前回のプロトタイプで存在していた、command、interrupt、task の実装を移植した。移植したと言っても配置して、manifest.jsonにまだその存在を記述しただけであり、まだ今回の試作物に適合させる実装がこれから必要である。\nmanifest.jsonの実装についても変更点があり、DataServerの項目についてCommandModules、InterruptModules、TaskModulesの3つに分けて、モジュールを記述するようにした。それぞれは、拡張機能のmanifest.jsonがあるフォルダを起点としたモジュールまでの相対パスが記述されている。それぞれのモジュールは1つのスクリプトで1つのモジュールという構成にしており、[moduleName].pyというモジュールであれば、内部にある関数名は必ず、def [moduleName](request,websocket):の形態を取る必要がある。パスの解決の問題により、今後モジュールが共通して受け付けるべき引数が増える可能性がある。\n\u0026#34;DataServer\u0026#34;:{ \u0026#34;CommandModules\u0026#34;:[ \u0026#34;backend/commands/info.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deleteNotebook.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/getPageType.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/pageInfo.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/updatePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/copyPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createPage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deletePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/movePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/renamePage.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/addTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/createTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/deleteTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/getTagList.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/queryTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/removeTag.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileAdd.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileData.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileDelete.py\u0026#34;, \u0026#34;backend/commands/notebookAndPage/fileInfo.py\u0026#34; ], \u0026#34;InterruptModules\u0026#34;:[ \u0026#34;backend/interrupts/newInfo.py\u0026#34;, \u0026#34;backend/interrupts/updatePage.py\u0026#34;, \u0026#34;backend/interrupts/updateTag.py\u0026#34; ], \u0026#34;TaskModules\u0026#34;:[ \u0026#34;backend/tasks/pageCleaner.py\u0026#34;, \u0026#34;backend/tasks/showPingMessage.py\u0026#34; ] }, manifest.jsonの他の変更点としては、別の拡張機能を依存関係として書けるようにした。具体的にどうやって異なる拡張機能間を上手く提携させるか、どういう課題があるかはみえていないが、とりあえず拡張機能の依存関係を記述できるようにした。例は以下のようなものである。\n{ //... \u0026#34;extensionDependencies\u0026#34;:[ { \u0026#34;name\u0026#34;: \u0026#34;Core\u0026#34;, \u0026#34;UUID\u0026#34;: \u0026#34;589fe65d-639c-42a3-b395-fca2143afd75\u0026#34; } ] } extensionLoaderに関して実装を進めた extensions 配下に配置された拡張機能の zip を展開して、文字列操作をした後に、runtime.pyとしてmainSysに組み込む実装を行った。manifest などのバリデーションは存在を確認するだけの簡易的な実装であり、まだ中身のキーなどの検証についてはとりあえず動くことを優先し、実装していない。\nまた、拡張機能の要件を追加した。具体的には、Python の依存関係を記述した requirements.txtファイルがあることを要件とした。これにより、拡張機能を読み込むとと同時に、自動的に依存関係をインストールできるようにする試みである。\nmainSysに対するコントローラモジュールに関する変更点 設計上の変更点としては、command、interrupt、task のそれぞれのコントローラが参照するモジュールの辞書型の変数名をextensionMoludesとするところから、それぞれのコントローラ用に独立させるために、commandExtensionMoludes、interruptExtensionMoludes、taskExtensionMoludesとした。その意図としては、複数のランタイムファイルを生成すると実装が煩雑になり、バグになりやすいと考えたところがある。それぞれの名前が衝突しないようにすることで、ランタイムは DataServer に関しては、runtime.pyに全てを記述すれば揃うことになり、そっちのほうがやりやすいだろうということになった。\n他の変更点としては、コマンドの呼び出しを、[拡張機能名]-[UUID]/[コマンド名(モジュール名)]という形態にした。同じ名前の拡張機能があっても、呼び出しにおいて衝突しないようにした。ただ、拡張機能を開発する側としては余分に、UUID を指定する必要があるため、拡張モジュールの開発のしやすさに影響が出ると考えられる。\n研究に関係ありそうなブログ記事 今回は特になし。\n参考にしたサイトとか Unzipping files in Python - GeeksforGeeks\nhttps://www.geeksforgeeks.org/python/unzipping-files-in-python/ (2026年9月2日) How to Create Requirements.txt File in Python - GeeksforGeeks\nhttps://www.geeksforgeeks.org/python/how-to-create-requirements-txt-file-in-python/ (2026年9月2日) Python map() Function\nhttps://www.w3schools.com/python/ref_func_map.asp (2026年9月2日) Python\u0026rsquo;s map(): Processing Iterables Without a Loop – Real Python\nhttps://realpython.com/python-map-function/ (2026年9月2日) ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-9-2/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/9/2 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　まだ拡張機能の読み込み部分は、とりあえず書いたという段階であり、パスやインポートの記述がおかしかったりするおそれがあり、デバッグが必要である。また、拡張機能を読み込んで DataServer が動作する事を確認するために、Core 拡張機能を完成させる必要がある。\u003c/p\u003e\n\u003cp\u003e　Core 拡張機能を完成させるためには、主にパスの解決が正しく出来るように、拡張機能のモジュール呼び出しにおいて、どうやって\u003ccode\u003emainSys\u003c/code\u003eと提携させるかが課題となっている。今具体的に考えている実装の一つとしては、モジュール呼び出し時に、DataServer のルートのパスや Notebook へのパスは、拡張機能ではない DataServer 側の組み込みの実装としてパスを解決しモジュールに伝える機構を実装することが考えられた。\u003c/p\u003e\n\u003cp\u003e　また、\u003ccode\u003emainSys\u003c/code\u003eについては、Python の仮想環境機能を使うことが考えられた。依存関係などをインストールするとき、既にインストールされている Python 環境を汚したりしてしまうのは避けたいと考えた。仮想環境は、存在しなければ拡張機能読み込みの段階で初期化し、存在すればそれが DataServer 起動時などに有効化されて使われるというような事を考えている。\u003c/p\u003e\n\u003cp\u003e　今回の試作物としては、とりあえず DataServer が拡張機能を介して動作するということを最低限の目標としたいと考えた。そこまでできたら次は、3つ目のプロトタイプとして今度はフロントエンドをなんとかするというロードマップにしようかなと作業と進捗状況から思ったところであった。フロントエンドには、zustand のストアにおける値が異なるストア間で重複しているなど、SQLの文脈におけるデータ項目の重複と正規化の問題があり、その点がまず修正点としてあげられる。\u003c/p\u003e\n\u003cp\u003e　DataServer において、WebSocket によるフロントエンドとの接続に関してセッションを管理したい。フロントエンドが接続してきたら、それぞれのフロントエンド自体をUUIDなどで識別して、正しく Command や Interrupt の経路がつながっているか管理することを考えている。\u003c/p\u003e\n\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003ch3 id=\"core-拡張機能を実装\"\u003e\u003ccode\u003eCore\u003c/code\u003e 拡張機能を実装\u003c/h3\u003e\n\u003cp\u003e　完全ではないが、とりあえず最低限の機能を DataServer に与えるために、\u003ccode\u003eCore\u003c/code\u003e 拡張機能を作成し、中身には前回のプロトタイプで存在していた、command、interrupt、task の実装を移植した。移植したと言っても配置して、\u003ccode\u003emanifest.json\u003c/code\u003eにまだその存在を記述しただけであり、まだ今回の試作物に適合させる実装がこれから必要である。\u003c/p\u003e\n\u003cp\u003e　\u003ccode\u003emanifest.json\u003c/code\u003eの実装についても変更点があり、\u003ccode\u003eDataServer\u003c/code\u003eの項目について\u003ccode\u003eCommandModules\u003c/code\u003e、\u003ccode\u003eInterruptModules\u003c/code\u003e、\u003ccode\u003eTaskModules\u003c/code\u003eの3つに分けて、モジュールを記述するようにした。それぞれは、拡張機能の\u003ccode\u003emanifest.json\u003c/code\u003eがあるフォルダを起点としたモジュールまでの相対パスが記述されている。それぞれのモジュールは1つのスクリプトで1つのモジュールという構成にしており、\u003ccode\u003e[moduleName].py\u003c/code\u003eというモジュールであれば、内部にある関数名は必ず、\u003ccode\u003edef [moduleName](request,websocket):\u003c/code\u003eの形態を取る必要がある。パスの解決の問題により、今後モジュールが共通して受け付けるべき引数が増える可能性がある。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;DataServer\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;CommandModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/info.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createNotebook.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deleteNotebook.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/getPageType.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/pageInfo.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/updatePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/copyPage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createPage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deletePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/movePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/renamePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/addTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/createTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/deleteTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/getTagList.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/queryTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/removeTag.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileAdd.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileData.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileDelete.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/commands/notebookAndPage/fileInfo.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;InterruptModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/newInfo.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/updatePage.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/interrupts/updateTag.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;TaskModules\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/tasks/pageCleaner.py\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;backend/tasks/showPingMessage.py\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　\u003ccode\u003emanifest.json\u003c/code\u003eの他の変更点としては、別の拡張機能を依存関係として書けるようにした。具体的にどうやって異なる拡張機能間を上手く提携させるか、どういう課題があるかはみえていないが、とりあえず拡張機能の依存関係を記述できるようにした。例は以下のようなものである。\u003c/p\u003e","title":"2026/9/2-やったこと"},{"content":"この記事を作った動機 Firefox にて、LAN にアクセスする拡張機能を移植したところ動かなった。そこで、LAN へのアクセスの許可を特定サイトに対して出そうとしたところ、UI が奥まったところにあり分かりづらかったので記録。\nUI の開き方(画像のみ) 参考にしたサイトとか Site Permissions panel | Firefox Help\nhttps://support.mozilla.org/en-US/kb/site-permissions-panel (2026年8月30日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/firefoxsetsitepermission/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Firefox にて、LAN にアクセスする拡張機能を移植したところ動かなった。そこで、LAN へのアクセスの許可を特定サイトに対して出そうとしたところ、UI が奥まったところにあり分かりづらかったので記録。\u003c/p\u003e\n\u003ch2 id=\"ui-の開き方画像のみ\"\u003eUI の開き方(画像のみ)\u003c/h2\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/firefoxSetSitePermission/%e3%82%b5%e3%82%a4%e3%83%88%e6%a8%a9%e9%99%90%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%8f.png#center\"\n         alt=\"サイト権限設定を開く\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/firefoxSetSitePermission/%e3%82%b5%e3%82%a4%e3%83%88%e6%a8%a9%e9%99%90%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%8f%201.png#center\"\n         alt=\"サイト権限設定を開く\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/firefoxSetSitePermission/%e3%82%b5%e3%82%a4%e3%83%88%e6%a8%a9%e9%99%90%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%8f%202.png#center\"\n         alt=\"サイト権限設定を開く\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/firefoxSetSitePermission/%e3%82%b5%e3%82%a4%e3%83%88%e6%a8%a9%e9%99%90%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%8f%203.png#center\"\n         alt=\"サイト権限設定を開く\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSite Permissions panel | Firefox Help\u003cbr\u003e\n\u003ca href=\"https://support.mozilla.org/en-US/kb/site-permissions-panel\"\u003ehttps://support.mozilla.org/en-US/kb/site-permissions-panel\u003c/a\u003e (2026年8月30日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Firefox でサイトに対する権限を設定するUIを開く"},{"content":"この記事を作った動機 簡易的に GTX 1080 Ti と Linux 環境において、Virtio(OpenGL) や Venus(Vulkan) による GPU アクセラレーションを利用する方法について、今まで諦めていた。それでも諦めきれずに定期的に調べていたところ、対処方法が見つかった。それについて、簡易的に症状とやったことを記録したい。\nデモ 以下の動画は、RDP 経由で Venus による 仮想 GPU を利用して Vulkan や OpenGL のアプリが動作している事を示している。マインクラフトの操作については、今回の RDP セットアップの仕様上、絶対座標しか送られておらず視点を動かすことができていなかったり、VPN など遠隔地から RDP 接続をして動かしているため、ラグが大きくぎこちないものとなっている。\n前座 Virtio における GPU 加速 Virt-Manager において標準で利用できる仮想 GPU である。AMD や Intel の GPU 環境では特別なことをしなくても、私個人の体験としては利用できたが、Nvidia 環境ではそうならなかった。\nVenus における GPU 加速 最近あたらしい GPU 加速手段の一つとして実装されたもので、デフォルトでは Virt−Manager などからはまだ利用できるようにはなっていない模様である。これについては直接 QEMU をコマンドラインから起動することが私が現在できていることであり、Virt-Manager からは XML の設定をいじってみたものの成功していない。\n今回犠牲になっている事 今回提示する解決策は、最低限 仮想 GPU が Nvidia の GTX1080Ti において動作するようにする事を目的としており、以下の負担や犠牲がある。\n仮想 GPU 有効時は、Virt-Manager や QEMU によるホストマシン上の GUI による画面描画は正常に動作しない。 仮想マシンに対して、CPU によるソフトウェアレンダリングで OS をインストールし、外部ネットワークから RDP 出来るように環境構築していること。私の場合は、仮想マシンに対して DNAT を行うことでこれを実現しているが、それも紆余曲折あった。詳細は、QEMU(virt-manager) で動かしている仮想マシンと、外部ネットワーク間において、ポート転送ができず時間を溶かす を参照。 仮想マシンに対して、Virtio に関連するドライバを事前に導入していること。 あくまで、EGL の初期化エラーを避けて、仮想マシンが起動でき、RDP 経由ではある程度動作する事。 少なくとも GTX 1080Ti における Venus の加速は、RDP を経由してもかなりグリッチがあり、出来ることが限られる。Blender を動かしたり、マインクラフトを動かしたりすることはできたが、特に通常の GUI 描画に弱くブラウザを使ったりするとグリッチがかなり発生したりする。これは、Nvidia 社の GTX1080Ti における Vulkan 実装が不完全であることが原因であると思われる。 今回の記事は主に、Windows 環境については、Virt-Manager で標準で利用できる OpenGL による仮想 GPU を想定しており、Linux 環境については、Venus を使って実現できる Vulkan による仮想 GPU を想定している。なお、Linux 環境でもVirt-Manager で標準で利用できる OpenGL による仮想 GPU は Venus に比べて安定して利用可能である。 OpenGL や Vulkan の仮想マシン上における利用は、Venus 経由の仮想 GPU によって実現され、Virt-Manager 標準の Virtio による OpenGL を使った仮想 GPU では、私が試した範囲ではできていない。 本題 症状 EGL の初期化に失敗し、仮想マシンを起動できなくなる。CPU 加速しか利用できず、GUI 描画がもたつき、CPU を使いまくる。\n改善した方法 /etc/libvirt/qemu.conf にて Nvidia GPU に対して適切な権限を設定する 以下の項目を最後辺りに追記する。\n# ... cgroup_device_acl = [ \u0026#34;/dev/null\u0026#34;, \u0026#34;/dev/full\u0026#34;, \u0026#34;/dev/zero\u0026#34;, \u0026#34;/dev/random\u0026#34;, \u0026#34;/dev/urandom\u0026#34;, \u0026#34;/dev/ptmx\u0026#34;, \u0026#34;/dev/kvm\u0026#34;, \u0026#34;/dev/nvidiactl\u0026#34;, \u0026#34;/dev/nvidia0\u0026#34;, \u0026#34;/dev/nvidia-modeset\u0026#34;, \u0026#34;/dev/dri/renderD128\u0026#34; ] 仮想マシンに適切なドライバやスタックを導入する Linux かつ Venus 環境の場合 少なくとも、Gnome 環境をインストールした Arch Linux 仮想マシン環境において、Vulkan を適切に動作させるには、以下のパッケージが必要であった。\nyay -S vulkan-virtio # sudo pacman -S vulkan-virtio Arch Linux - vulkan-virtio 1:26.2.1-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vulkan-virtio/ (2026年8月29日) Windows かつ Virt-Manager 環境の場合 以下のサイトから、OS にあわせた ISO を取得し、仮想マシンにマウントして、必要なドライバをインストールする。\nIndex of /groups/virt/virtio-win/direct-downloads/archive-virtio\nhttps://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/?C=M;O=D (2026年8月29日) 以下のように表示されていれば、GPU 加速を利用する準備ができている。\nホストマシンにて 仮想マシンにて おまけ Arch Linux や Arch ベースの Linux の仮想マシンで、Venus 環境下において、Blender を起動したい 以下に示す古い Blender をインストールし、blender が Intel HD Graphics 4000 で動かない にて示されるワークアラウンドを試すと、とりあえず起動できる。ただしレンダリングしようとしたりするとクラッシュするので実用的ではない。\nAUR (en) - blender-4.2-bin\nhttps://aur.archlinux.org/packages/blender-4.2-bin (2026年8月29日) yay -S blender-4.2-bin Linux 仮想マシンかつ Venus 環境下において、もっと安定して動かしたい。 /etc/environmentにて、以下の変数を設定し、アプリ起動時に反映されるようにする。以下の設定は垂直同期についての設定らしいが、私はまだよく理解していない。動かしてみて例えば glxgear のフレームレートが 50 FPS ほどあがるなど、安定性やパフォーマンスの違いを個人的には体感したという程度の話である。\nvblank_mode=0 Arch Linux 環境にて、OpenGL や Vulkan の動作確認をしたい 以下のパッケージをインストールすれば、OpenGL のテストには glxgears コマンドが、Vulkan のテストには vkcube が利用可能である。\nArch Linux - vulkan-tools 1.4.357.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vulkan-tools/ (2026年8月29日) Arch Linux - mesa-utils 9.0.0-7 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/mesa-utils/ (2026年8月29日) Arch Linux - lib32-mesa-utils 9.0.0-4 (x86_64)\nhttps://archlinux.org/packages/multilib/x86_64/lib32-mesa-utils/ (2026年8月29日) yay -S vulkan-tools # sudo pacman -S vulkan-tools yay -S mesa-utils lib32-mesa-utils sudo pacman -S mesa-utils lib32-mesa-utils 関連する記事とか QEMU(virt-manager) で動かしている仮想マシンと、外部ネットワーク間において、ポート転送ができず時間を溶かす blender が Intel HD Graphics 4000 で動かない 参考にしたサイトとか QEMU with VirtIO GPU Vulkan Support\nhttps://gist.github.com/peppergrayxyz/fdc9042760273d137dddd3e97034385f (2026年8月29日)\nHow to enable VirtIO-GPU Venus on QEMU explained | tm23forest.com\nhttps://tm23forest.com/contents/how-to-enable-virtio-gpu-venus-on-qemu-explained (2026年8月29日)\nDoesn\u0026rsquo;t work egl-headless and gl.rendernode=/dev/dri/renderD128 on nvidia card · Issue #938 · virt-manager/virt-manager\nhttps://github.com/virt-manager/virt-manager/issues/938 (2026年8月29日)\nConfiguring QEMU bridge helper after “access denied by acl file” error – Just another Linux geek\nhttps://blog.christophersmart.com/2016/08/31/configuring-qemu-bridge-helper-after-access-denied-by-acl-file-error/ (2026年8月29日)\nBenchmarking - ArchWiki\nhttps://wiki.archlinux.org/title/Benchmarking (2026年8月29日)\nArch Linux - vulkan-virtio 1:26.2.1-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vulkan-virtio/ (2026年8月29日)\n3D acceleration with virt-manager and nvidia gpu - Fedora Discussion\nhttps://discussion.fedoraproject.org/t/3d-acceleration-with-virt-manager-and-nvidia-gpu/161332 (2026年8月29日)\nWindows VirtIO Drivers - Proxmox VE\nhttps://pve.proxmox.com/wiki/Windows_VirtIO_Drivers (2026年8月29日)\nIndex of /groups/virt/virtio-win/direct-downloads/archive-virtio\nhttps://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/?C=M;O=D (2026年8月29日)\nVulkan - ArchWiki\nhttps://wiki.archlinux.org/title/Vulkan (2026年8月29日)\nAUR (en) - blender-4.2-bin\nhttps://aur.archlinux.org/packages/blender-4.2-bin (2026年8月29日)\nArch Linux - vulkan-tools 1.4.357.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vulkan-tools/ (2026年8月29日)\nArch Linux - mesa-utils 9.0.0-7 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/mesa-utils/ (2026年8月29日)\nArch Linux - lib32-mesa-utils 9.0.0-4 (x86_64)\nhttps://archlinux.org/packages/multilib/x86_64/lib32-mesa-utils/ (2026年8月29日)\nローカルLLM (Gemma4-12b-qatやGemma4-31B) (2026年8月29日)\n","permalink":"https://www.nyanmo.info/posts/linux/qemugpuaccelerationonnvidiagpu/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　簡易的に GTX 1080 Ti と Linux 環境において、Virtio(OpenGL) や Venus(Vulkan) による GPU アクセラレーションを利用する方法について、今まで諦めていた。それでも諦めきれずに定期的に調べていたところ、対処方法が見つかった。それについて、簡易的に症状とやったことを記録したい。\u003c/p\u003e\n\u003ch2 id=\"デモ\"\u003eデモ\u003c/h2\u003e\n\u003cp\u003e　以下の動画は、RDP 経由で Venus による 仮想 GPU を利用して Vulkan や OpenGL のアプリが動作している事を示している。マインクラフトの操作については、今回の RDP セットアップの仕様上、絶対座標しか送られておらず視点を動かすことができていなかったり、VPN など遠隔地から RDP 接続をして動かしているため、ラグが大きくぎこちないものとなっている。\u003c/p\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/linux/QEMUgpuAccelerationOnNvidiaGPU/%e3%83%87%e3%83%a2.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"前座\"\u003e前座\u003c/h2\u003e\n\u003ch3 id=\"virtio-における-gpu-加速\"\u003eVirtio における GPU 加速\u003c/h3\u003e\n\u003cp\u003e　Virt-Manager において標準で利用できる仮想 GPU である。AMD や Intel の GPU 環境では特別なことをしなくても、私個人の体験としては利用できたが、Nvidia 環境ではそうならなかった。\u003c/p\u003e\n\u003ch3 id=\"venus-における-gpu-加速\"\u003eVenus における GPU 加速\u003c/h3\u003e\n\u003cp\u003e　最近あたらしい GPU 加速手段の一つとして実装されたもので、デフォルトでは Virt−Manager などからはまだ利用できるようにはなっていない模様である。これについては直接 QEMU をコマンドラインから起動することが私が現在できていることであり、Virt-Manager からは XML の設定をいじってみたものの成功していない。\u003c/p\u003e\n\u003ch3 id=\"今回犠牲になっている事\"\u003e今回犠牲になっている事\u003c/h3\u003e\n\u003cp\u003e　今回提示する解決策は、最低限 仮想 GPU が Nvidia の GTX1080Ti において動作するようにする事を目的としており、以下の負担や犠牲がある。\u003c/p\u003e","title":"QEMU で Nvidia 製 GPU において GPU パススルー以外で、ハードウェアアクセラレーションを利用する方法について"},{"content":"この記事を作った動機 2026/8/26 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 mainSysの各サブシステムがプロセスとして独立しているので、それらのプロセス間通信について、調べて実装する。commandから、interruptが呼び出せるようにするなど、実装を行う必要がある。threadingとは異なり、メモリ空間が共有されていない点に留意する必要がある。\nまたコマンドのモジュール読み込み部分については、extensionMoludes = {moduleFunc:[moduleFuncName],...}という形態で、前回の辞書型の実装を単に拡張される前提で書き換えただけであるが、それだとどのコマンドがどの拡張機能に属しているか管理が不十分になると思われる。これに対して考えられることとしては、前回の試作物のように、コード上の関数名と辞書型のキーの値を同じにするのではなく、キーの部分については識別性を上げるために、extensionName/moduleFuncNameのようにすることが考えられた。また同名の拡張機能のためには、extensionName-UUIDの一部/moduleFuncNameのようにして重複を防止することが考えられた。\nまた今回の実装では、WebScoket の経路が、commandとinterruptで分かれており、それぞれは混同されない仕組みとした。現状では使用されるポートが前回と異なりハードコードで決め打ちとなっている。commandのサブシステムに関してはlocalhost:50097に、interruptのサブシステムに関しては、localhost:50098にホスティングされる。 今回試作する DataServer を前回の試作物のフロントエンドに適用するには、前回の試作物のフロントエンドの装の調整が必要である。\nやったことの詳細 主に以下の項目について実装を進めた\nmainSys の実装を進めた command、interrupt、taskについてそれぞれ、具体的な中身を記述した。その過程において、拡張機能を読み込みには、command、interrupt、taskのそれぞれにおいて、決まった関数の Import と extensionMoludes = {moduleFunc:[moduleFuncName],...} の設定を必要とし、DataServer 起動時にそれらが文字列として構築されることとした。\nmainSys の起動をするためのコードの実装を進めた mainSysを起動するための、mainSys/main.pyでは、あくまでフロントエンドやデータ転送の機能のホスティングやcommand、interrupt、taskを常駐させるためにプロセスを生成したり、終了時の例外処理に特化させた。当初はここにモジュールの Import や読み込みは集約させようと思っていたが、それだと引数などとして command、interrupt、task などのコントローラにそれぞれ参照を渡したりする手間が発生することが分かったため、command、interrupt、task のコントローラのスクリプト群に直接組み込むことで、実装を単純にしようとした。\n前回の試作品からいくつかのコードを移植 今回の試作物は、拡張機能によって成り立つシステムという事を想定しているため、それ以外の部分については前回の試作物から移植して調整したものを使っている。具体的には以下のような部分が移植されている。\nWebSocket 接続を待ち受ける実装 NotImplementedResponse、malformedRequestResponse、notFound といった DataServer がコマンドの動作に関して常に最低限必要としているレスポンス実装 showJSONMessage、malformedRequestChecker、receiveLoop などといった、コンソールに DataServer の送受信内容を表示する関数や、受信データの確認、WebSocket の実装に関するヘルパー関数について、引き継いでいる。 研究に関係ありそうなブログ記事 今回は特になし。\n参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-8-26/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/8/26 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003emainSys\u003c/code\u003eの各サブシステムがプロセスとして独立しているので、それらのプロセス間通信について、調べて実装する。\u003ccode\u003ecommand\u003c/code\u003eから、\u003ccode\u003einterrupt\u003c/code\u003eが呼び出せるようにするなど、実装を行う必要がある。\u003ccode\u003ethreading\u003c/code\u003eとは異なり、メモリ空間が共有されていない点に留意する必要がある。\u003c/p\u003e\n\u003cp\u003e　またコマンドのモジュール読み込み部分については、\u003ccode\u003eextensionMoludes = {moduleFunc:[moduleFuncName],...}\u003c/code\u003eという形態で、前回の辞書型の実装を単に拡張される前提で書き換えただけであるが、それだとどのコマンドがどの拡張機能に属しているか管理が不十分になると思われる。これに対して考えられることとしては、前回の試作物のように、コード上の関数名と辞書型のキーの値を同じにするのではなく、キーの部分については識別性を上げるために、\u003ccode\u003eextensionName/moduleFuncName\u003c/code\u003eのようにすることが考えられた。また同名の拡張機能のためには、\u003ccode\u003eextensionName-UUIDの一部/moduleFuncName\u003c/code\u003eのようにして重複を防止することが考えられた。\u003c/p\u003e\n\u003cp\u003e　また今回の実装では、WebScoket の経路が、\u003ccode\u003ecommand\u003c/code\u003eと\u003ccode\u003einterrupt\u003c/code\u003eで分かれており、それぞれは混同されない仕組みとした。現状では使用されるポートが前回と異なりハードコードで決め打ちとなっている。\u003ccode\u003ecommand\u003c/code\u003eのサブシステムに関しては\u003ccode\u003elocalhost:50097\u003c/code\u003eに、\u003ccode\u003einterrupt\u003c/code\u003eのサブシステムに関しては、\u003ccode\u003elocalhost:50098\u003c/code\u003eにホスティングされる。 今回試作する DataServer を前回の試作物のフロントエンドに適用するには、前回の試作物のフロントエンドの装の調整が必要である。\u003c/p\u003e\n\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003cp\u003e　主に以下の項目について実装を進めた\u003c/p\u003e\n\u003ch3 id=\"mainsys-の実装を進めた\"\u003e\u003ccode\u003emainSys\u003c/code\u003e の実装を進めた\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003ecommand\u003c/code\u003e、\u003ccode\u003einterrupt\u003c/code\u003e、\u003ccode\u003etask\u003c/code\u003eについてそれぞれ、具体的な中身を記述した。その過程において、拡張機能を読み込みには、\u003ccode\u003ecommand\u003c/code\u003e、\u003ccode\u003einterrupt\u003c/code\u003e、\u003ccode\u003etask\u003c/code\u003eのそれぞれにおいて、決まった関数の Import と \u003ccode\u003eextensionMoludes = {moduleFunc:[moduleFuncName],...}\u003c/code\u003e の設定を必要とし、DataServer 起動時にそれらが文字列として構築されることとした。\u003c/p\u003e\n\u003ch3 id=\"mainsys-の起動をするためのコードの実装を進めた\"\u003e\u003ccode\u003emainSys\u003c/code\u003e の起動をするためのコードの実装を進めた\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003emainSys\u003c/code\u003eを起動するための、\u003ccode\u003emainSys/main.py\u003c/code\u003eでは、あくまでフロントエンドやデータ転送の機能のホスティングや\u003ccode\u003ecommand\u003c/code\u003e、\u003ccode\u003einterrupt\u003c/code\u003e、\u003ccode\u003etask\u003c/code\u003eを常駐させるためにプロセスを生成したり、終了時の例外処理に特化させた。当初はここにモジュールの Import や読み込みは集約させようと思っていたが、それだと引数などとして \u003ccode\u003ecommand\u003c/code\u003e、\u003ccode\u003einterrupt\u003c/code\u003e、\u003ccode\u003etask\u003c/code\u003e などのコントローラにそれぞれ参照を渡したりする手間が発生することが分かったため、\u003ccode\u003ecommand\u003c/code\u003e、\u003ccode\u003einterrupt\u003c/code\u003e、\u003ccode\u003etask\u003c/code\u003e のコントローラのスクリプト群に直接組み込むことで、実装を単純にしようとした。\u003c/p\u003e\n\u003ch3 id=\"前回の試作品からいくつかのコードを移植\"\u003e前回の試作品からいくつかのコードを移植\u003c/h3\u003e\n\u003cp\u003e　今回の試作物は、拡張機能によって成り立つシステムという事を想定しているため、それ以外の部分については前回の試作物から移植して調整したものを使っている。具体的には以下のような部分が移植されている。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eWebSocket 接続を待ち受ける実装\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eNotImplementedResponse\u003c/code\u003e、\u003ccode\u003emalformedRequestResponse\u003c/code\u003e、\u003ccode\u003enotFound\u003c/code\u003e といった DataServer がコマンドの動作に関して常に最低限必要としているレスポンス実装\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eshowJSONMessage\u003c/code\u003e、\u003ccode\u003emalformedRequestChecker\u003c/code\u003e、\u003ccode\u003ereceiveLoop\u003c/code\u003e などといった、コンソールに DataServer の送受信内容を表示する関数や、受信データの確認、WebSocket の実装に関するヘルパー関数について、引き継いでいる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"研究に関係ありそうなブログ記事\"\u003e研究に関係ありそうなブログ記事\u003c/h2\u003e\n\u003cp\u003e　今回は特になし。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は特になし。\u003c/p\u003e","title":"2026/8/26-やったこと"},{"content":"この記事を作った動機 libvirt の仕様を理解していなかった結果、大量の時間を溶かすことがあったので記録したい。具体的には、仮想マシンに対してRDPのためにポート転送を設定しようとしたが、libvirtが作成する、defaultネットワークに属している、virbr0ブリッジはnftablesをいじっても言うことを聞かないほど、ガチガチに守られていて使うべきではないという結論に至った。\n今回はそこに至るまでの経緯と、実際に機能する事を確かめた対処方法について記録する。機能する対処方法の概要としては、libvirt以外に、手動でブリッジを専用に作成し、それに対してfirewalldでNATやDNATを構成し、仮想マシンにそのブリッジを使うように設定する事をする。\n機能した対処方法 仮定 仮想マシンを動かしているホストマシンは、firewalldのpublicゾーンを使用している ホストマシンは、ブリッジに対して192.168.150.1/24のIPを持つ 仮想マシンのIPは手動で192.168.150.25/24を割り当て、ゲートウェイにはホストマシンに向けて192.168.150.1と設定する sysctl -w net.ipv4.ip_forward=1が設定されており、カーネルが異なるインタフェース間のパケットの行き来を許可していること ブリッジを作成 sudo brctl addbr virt sudo ip link set virt up sudo ip addr add 192.168.150.1/24 dev virt 仮想マシンを作成したブリッジを使うように設定 firewalld でNATとDNATを構成する # ゾーンとポリシー(NAT用)を作成 sudo firewall-cmd --new-zone=virt --permanent sudo firewall-cmd --zone=virt --add-interface=virt --permanent sudo firewall-cmd --zone=virt --new-policy=nat --permanent sudo firewall-cmd --policy=nat --add-ingress-zone=virt --permanent sudo firewall-cmd --policy=nat --add-egress-zone=public --permanent sudo firewall-cmd --policy=nat --add-masquerade --permanent # ポート転送設定(DNAT) sudo firewall-cmd --zone=public --add-forward-port=port=33890:proto=tcp:toport=3389:toaddr=192.168.150.25 --permanent sudo firewall-cmd --zone=public --add-forward-port=port=33890:proto=udp:toport=3389:toaddr=192.168.150.25 --permanent # NATが機能するようにマスカレードと転送を設定 sudo firewall-cmd --zone=public --add-masquerade --permanent sudo firewall-cmd --zone=virt --add-forward --permanent sudo systemctl restart firewalld 問題至るまでの経緯 今までの構成を見直す 今まで仮想マシンへのRDPアクセスは、無理やりVPN経路を通じて同じLAN内に仮想マシンを参加させることで動かしていた。接続が不安定であり定期的にVPNが接続できなくなったり、ネットワークトポロジ的にも循環経路を形成しかねないように見受けられた。VPNを介さずにホストマシンを直接介させることで、仮想マシンに対してRDPを行うために、今回は仮想マシンのRDPポートである、3389に対してポート転送を行う事を考えた。\nポート転送できず苦しむ ポート転送するに際して、既に仮想マシンが、virbr0のブリッジに属していることに気づく。firewalldによって、ポート転送をそれに対して設定すれば、動くだろうと思い色々試行錯誤したもののどれもうまく行かず。最終的にnftablesで最優先に設定した設定をpreroutingやforwardチェーンに入れると、パケットはそのルールを反映するものの、意地でもvirbr0ではtcpdump -i virbr0 port 3389としてもパケットが一切見られなかった。あれこれして、ネットで色々当たった結果、以下のサイトの記述にとり、重要な事実としてlibvirtのデフォルトで作成されるブリッジについて重要な事実を知る。\nfirewall-cmd - add-forward-port don\u0026rsquo;t work - Super User\nhttps://superuser.com/questions/1474254/firewall-cmd-add-forward-port-dont-work (2026年8月24日) The problem is in the KVM (libvirt) which when starting the \u0026#34;network\u0026#34; virbr0 injects rules (probably via firewalld) which prevents (first match principle) any attempt to port forwarding by conventional ways using firewall-cmd. The KVM injected (libvirt) rules are at the top of FORWARD and POSTROUTING, before regular firewalld ruleset. Since the netfilter operates on first match principle, these rules. ブリッジを手動で作成する考えに至るまで 同じく以下の記事にして、以下の部分とlibvirtが生成したブリッジには触りたくないということとVirt-managerにあるネットワークの設定項目で任意のブリッジを手動で設定できる項目があることから、今回解決とした策に至った。\nfirewall-cmd - add-forward-port don\u0026rsquo;t work - Super User\nhttps://superuser.com/questions/1474254/firewall-cmd-add-forward-port-dont-work (2026年8月24日) I have found another solution, which does not require any extra code. This was tested on Fedora 41; I am not sure about CentOS 7 which is rather old by this time. All the commands in these instructions are to be run as root. Edit the libvirt network (virsh net-edit default usually), find , change to . Then either just reboot your host or restart the network, usually like this: virsh net-destroy default virsh net-start default At this point your guests have lost communication with the \u0026#34;outside world\u0026#34; because you have disabled libvirt\u0026#39;s NAT, but now you add your own NAT. First, take a look at your zones with firewall-cmd --get-active-zones. Here\u0026#39;s what I got: # firewall-cmd --get-active-zones FedoraServer (default) interfaces: ens18 libvirt interfaces: virbr0 Your public zone can have a different name, adjust the rest of the commands accordingly (I think it\u0026#39;s usually \u0026#34;public\u0026#34; in RHEL and derivatives). If you don\u0026#39;t see virbr0 in the libvirt zone, add it: firewall-cmd --zone libvirt --add-interface virbr0. If virbr0 is in some other zone, use that zone name instead. But it should not be in your public zone. Now we create the new NAT: firewall-cmd --permanent --new-policy libvirt-nat firewall-cmd --permanent --policy libvirt-nat --set-target ACCEPT firewall-cmd --permanent --policy libvirt-nat --add-ingress-zone libvirt firewall-cmd --permanent --policy libvirt-nat --add-egress-zone FedoraServer firewall-cmd --permanent --policy libvirt-nat --add-masquerade firewall-cmd --reload Your guests should have their connectivity restored, and with this NAT your port forwarding is rather simple, for example: firewall-cmd --permanent --zone FedoraServer --add-forward-port=port=8080:proto=tcp:toport=8080:toaddr=192.168.122.117 firewall-cmd --reload Replace the port number and internal address as necessary. There is a special case: when your guests have real IPv6 addresses and you have routing of these addresses configured through your host already . In this case you might want to allow the outside world to connect to your guests. If - and that is an if - you want to do so, add another policy: firewall-cmd --permanent --new-policy libvirt-inbound firewall-cmd --permanent --policy libvirt-inbound --set-target ACCEPT firewall-cmd --permanent --policy libvirt-inbound --add-egress-zone libvirt firewall-cmd --permanent --policy libvirt-inbound --add-ingress-zone FedoraServer firewall-cmd --reload Sometimes a cloud provider will give you IPv6 addresses but not route them. There is still a way to use them like this, it is something called \u0026#34;proxying NDP\u0026#34;, but it is beyond the scope of this answer. 使った画像とか Red Hat, Inc., CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Libvirt_logo.svg (2026年8月24日) Home | firewalld\nhttps://firewalld.org/ (2026年8月24日) Microsoft Remote Desktop | Logopedia | Fandom\nhttps://logos.fandom.com/wiki/Microsoft_Remote_Desktop (2026年8月24日) 参考にしたサイトとか firewall-cmd - add-forward-port don\u0026rsquo;t work - Super User\nhttps://superuser.com/questions/1474254/firewall-cmd-add-forward-port-dont-work (2026年8月24日)\nConfiguring tables - nftables wiki\nhttps://wiki.nftables.org/wiki-nftables/index.php/Configuring_tables (2026年8月24日)\nBridging Network Interfaces in Linux | Baeldung on Linux\nhttps://www.baeldung.com/linux/bridging-network-interfaces (2026年8月24日)\nnftables - how do you see dropped packets with nft command? : r/linuxquestions\nhttps://www.reddit.com/r/linuxquestions/comments/1c01tju/nftables_how_do_you_see_dropped_packets_with_nft/ (2026年8月24日)\nTCPDump: Capture and Record Specific Protocols / Port Traffic - nixCraft\nhttps://www.cyberciti.biz/faq/tcpdump-capture-record-protocols-port/ (2026年8月24日)\nFilter Port in Wireshark: Master Network Traffic (Guide) - NetSuite.blog\nhttps://netsuite.blog/filter-port-wireshark (2026年8月24日)\nHow to allow RDP in Windows 10 firewall: GUI \u0026amp; Powershell command\nhttps://www.how2shout.com/how-to/windows-firewall-allow-rdp-using-gui-powershell-command.html (2026年8月24日)\nローカルLLM (Gemma4-12b-qatやGemma4-31B) (2026年8月24日)\n","permalink":"https://www.nyanmo.info/posts/linux/qemuvmunabletoforwardportthatmeandnatrefusetowork/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　libvirt の仕様を理解していなかった結果、大量の時間を溶かすことがあったので記録したい。具体的には、仮想マシンに対してRDPのためにポート転送を設定しようとしたが、libvirtが作成する、\u003ccode\u003edefault\u003c/code\u003eネットワークに属している、\u003ccode\u003evirbr0\u003c/code\u003eブリッジはnftablesをいじっても言うことを聞かないほど、ガチガチに守られていて使うべきではないという結論に至った。\u003c/p\u003e\n\u003cp\u003e　今回はそこに至るまでの経緯と、実際に機能する事を確かめた対処方法について記録する。機能する対処方法の概要としては、libvirt以外に、手動でブリッジを専用に作成し、それに対してfirewalldでNATやDNATを構成し、仮想マシンにそのブリッジを使うように設定する事をする。\u003c/p\u003e\n\u003ch2 id=\"機能した対処方法\"\u003e機能した対処方法\u003c/h2\u003e\n\u003ch3 id=\"仮定\"\u003e仮定\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e仮想マシンを動かしているホストマシンは、firewalldのpublicゾーンを使用している\u003c/li\u003e\n\u003cli\u003eホストマシンは、ブリッジに対して\u003ccode\u003e192.168.150.1/24\u003c/code\u003eのIPを持つ\u003c/li\u003e\n\u003cli\u003e仮想マシンのIPは手動で\u003ccode\u003e192.168.150.25/24\u003c/code\u003eを割り当て、ゲートウェイにはホストマシンに向けて\u003ccode\u003e192.168.150.1\u003c/code\u003eと設定する\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003esysctl -w net.ipv4.ip_forward=1\u003c/code\u003eが設定されており、カーネルが異なるインタフェース間のパケットの行き来を許可していること\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"ブリッジを作成\"\u003eブリッジを作成\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo brctl addbr virt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo ip link set virt up\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo ip addr add 192.168.150.1/24 dev virt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"仮想マシンを作成したブリッジを使うように設定\"\u003e仮想マシンを作成したブリッジを使うように設定\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/qemuVMunableToForwardPortThatMeanDNATrefuseToWork/%e3%83%96%e3%83%aa%e3%83%83%e3%82%b8%e3%82%92%e6%8c%87%e5%ae%9a%e3%81%99%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"ブリッジを指定する様子\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"firewalld-でnatとdnatを構成する\"\u003efirewalld でNATとDNATを構成する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ゾーンとポリシー(NAT用)を作成\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --new-zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --add-interface\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --new-policy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enat --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --policy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enat --add-ingress-zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --policy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enat --add-egress-zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epublic --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --policy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003enat --add-masquerade --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ポート転送設定(DNAT)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epublic --add-forward-port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eport\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e33890:proto\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etcp:toport\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e3389:toaddr\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e192.168.150.25 --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epublic --add-forward-port\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eport\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e33890:proto\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eudp:toport\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e3389:toaddr\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e192.168.150.25 --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# NATが機能するようにマスカレードと転送を設定\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003epublic --add-masquerade --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evirt --add-forward --permanent\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart firewalld\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"問題至るまでの経緯\"\u003e問題至るまでの経緯\u003c/h2\u003e\n\u003ch3 id=\"今までの構成を見直す\"\u003e今までの構成を見直す\u003c/h3\u003e\n\u003cp\u003e　今まで仮想マシンへのRDPアクセスは、無理やりVPN経路を通じて同じLAN内に仮想マシンを参加させることで動かしていた。接続が不安定であり定期的にVPNが接続できなくなったり、ネットワークトポロジ的にも循環経路を形成しかねないように見受けられた。VPNを介さずにホストマシンを直接介させることで、仮想マシンに対してRDPを行うために、今回は仮想マシンのRDPポートである、\u003ccode\u003e3389\u003c/code\u003eに対してポート転送を行う事を考えた。\u003c/p\u003e","title":"QEMU(virt-manager) で動かしている仮想マシンと、外部ネットワーク間において、ポート転送ができず時間を溶かす"},{"content":"この記事を作った動機 2026/8/19 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\n次に軽くやりたいことを記述 とにかく中身の実装を進める。DataServer 周りをとにかく終わらせて、とりあえず卒論のフロントエンドに対して、DataServer を今回作る試作物に置き換えて動作するくらいにはしたい。\nやったことの詳細 内部構造について 大まかには、DataServer 周りのシステムのディレクトリ構造を卒論時点のものとは大幅に変更した。また、スクリプトを配置して、具体的な内容が書き始められるように、擬似コード的な感じでスクリプトの各所にコメントを記述したりした。大きな変更点は、\u0026ldquo;具体的な実装\u0026quot;をなるべく含めないようにすることで、抽象度を上げ、データの器として DataServer を機能させるための下地を作ったという点である。また、拡張されるのは DataServer だけではなく、フロントエンドも対象であり、DataServer と整合性をもって動かす必要があるため、DataServer の一部としてフロントエンドを組み込んだ。\n卒論時点の DataServer のディレクトリ配置 ├── commands │ ├── _index.py │ ├── fileAPI │ │ ├── fileAdd.py ... │ ├── info.py │ ├── notebookAndPage │ │ ├── copyPage.py │ │ ├── createNotebook.py │ │ ├── createPage.py ... │ ├── tag │ │ ├── addTag.py │ │ ├── createTag.py ... │ └── template.py ├── configure.py ├── controller.py ├── helper │ ├── _index.py │ ├── common.py │ ├── loadSettings.py │ └── netwrok.py ├── interrupts │ ├── controller.py │ ├── newInfo.py │ ├── updatePage.py │ └── updateTag.py ├── jobs │ ├── pageCleaner.py │ └── showPingMessage.py ├── main.py ├── requirements.txt ├── settings.json ├── tasks.py ... 今回の試作品のディレクトリ配置 ├── extensionLoader │ ├── common.py │ ├── dataserver.py │ ├── frontend.py │ ├── main.py │ └── template │ ├── dataserver.py │ └── frontend.tsx ├── extensions │ └── readme.md ├── frontend ├── main.py ├── mainSys │ ├── controller │ │ ├── command.py │ │ ├── interrupt.py │ │ └── task.py │ ├── hosting │ │ ├── fileTransfar.py │ │ └── frontendServe.py │ └── main.py └── settings.json 今回の試作物の構成について軽く説明 今回の試作品の各ディレクトリやファイル配置についての説明としては以下のとおりである。\nmain.py DataServer を起動する際に一番最初に実行されるスクリプトである。拡張機能を読み込み、拡張機能が組み込まれた DataServer やフロントエンドを起動したり、ホストする役割がある。このスクリプト自体は、直接 DataServer 本体とはならず、準備から起動までを担っている。\nextensionLoader extensionLoader/main.py を中心に構成される DataServer やフロントエンドに関して拡張機能を実際に読み込み、DataServer やフロントエンドに組み込む機構が格納されているディレクトリである。\nextensions extensionLoader によって読み込まれる拡張機能を配置する場所である。各拡張機能ごとに ZIP ファイルを配置する。\nfrontend 拡張されるベースとなるフロントエンド部分が保持される。現時点での技術選定は卒論と同じ、Vite + React + TypeScript + Tailwind CSS の構成の予定である。\nmainSys mainSysは、DataServer の拡張されるベースとなるコードが存在しており、拡張機能を読み込んだあと、mainSys/main.pyが起動されることで、DataServer 本体が動作する。mainSys 自体は以下のように細分化されている。\ncontroller\n卒論と同じく、コマンド、割り込み、定期タスクのコントローラが存在しており、拡張機能によって拡張される。 hosting\nここは卒論とは異なり、拡張期の読み込みのフェーズでビルドされたフロントエンドを http にてホストしたり、ファイル転送に関して特別なバックエンドを備える部分であり、拡張機能によって拡張できるようにする予定は今回はない。 動作について DataServer における動作について、卒論時点ではデータサーバは最初に開始された一つのプロセスを中心として起動するように作っていたが、今回の DataServer では、まず拡張機能を読みこんでフロントエンドやデータサーバを\u0026quot;ビルド\u0026quot;してから、それを立ち上げるという仕組みにした。これにより、拡張機能の実装を反映した DataServer やフロントエンドが可能になるということである。\n拡張機能の読み込みについて DataServer やフロントエンドにおける拡張機能の読み込みは、Import の調整と配列の調整の２つによって成り立ち、DataServer や フロントエンドのベースとなるコードに対して、拡張機能のコードを接続する形態を想定している。まだ、拡張機能のコードに対して具体的にどんな共通の実装を求めるかは決まっていないが、それは実装しながら決定したいと考える。\n研究に関係ありそうなブログ記事 npm において、vite: command not found となり、開発サーバを立てられず何もできない問題が起こる 参考にしたサイトとか 今回は特になし。\n","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/m1/log/2026-8-19/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　2026/8/19 に至るまでの間で OneNote 代替に関して、実装をするなど研究を進めているうちにわかったことなどを簡易的に記録する。\u003c/p\u003e\n\u003ch2 id=\"次に軽くやりたいことを記述\"\u003e次に軽くやりたいことを記述\u003c/h2\u003e\n\u003cp\u003e　とにかく中身の実装を進める。DataServer 周りをとにかく終わらせて、とりあえず卒論のフロントエンドに対して、DataServer を今回作る試作物に置き換えて動作するくらいにはしたい。\u003c/p\u003e\n\u003ch2 id=\"やったことの詳細\"\u003eやったことの詳細\u003c/h2\u003e\n\u003ch3 id=\"内部構造について\"\u003e内部構造について\u003c/h3\u003e\n\u003cp\u003e　大まかには、DataServer 周りのシステムのディレクトリ構造を卒論時点のものとは大幅に変更した。また、スクリプトを配置して、具体的な内容が書き始められるように、擬似コード的な感じでスクリプトの各所にコメントを記述したりした。大きな変更点は、\u0026ldquo;具体的な実装\u0026quot;をなるべく含めないようにすることで、抽象度を上げ、データの器として DataServer を機能させるための下地を作ったという点である。また、拡張されるのは DataServer だけではなく、フロントエンドも対象であり、DataServer と整合性をもって動かす必要があるため、DataServer の一部としてフロントエンドを組み込んだ。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e卒論時点の DataServer のディレクトリ配置\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e├── commands\n│   ├── _index.py\n│   ├── fileAPI\n│   │   ├── fileAdd.py\n...\n│   ├── info.py\n│   ├── notebookAndPage\n│   │   ├── copyPage.py\n│   │   ├── createNotebook.py\n│   │   ├── createPage.py\n...\n│   ├── tag\n│   │   ├── addTag.py\n│   │   ├── createTag.py\n...\n│   └── template.py\n├── configure.py\n├── controller.py\n├── helper\n│   ├── _index.py\n│   ├── common.py\n│   ├── loadSettings.py\n│   └── netwrok.py\n├── interrupts\n│   ├── controller.py\n│   ├── newInfo.py\n│   ├── updatePage.py\n│   └── updateTag.py\n├── jobs\n│   ├── pageCleaner.py\n│   └── showPingMessage.py\n├── main.py\n├── requirements.txt\n├── settings.json\n├── tasks.py\n...\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003e今回の試作品のディレクトリ配置\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e├── extensionLoader\n│   ├── common.py\n│   ├── dataserver.py\n│   ├── frontend.py\n│   ├── main.py\n│   └── template\n│       ├── dataserver.py\n│       └── frontend.tsx\n├── extensions\n│   └── readme.md\n├── frontend\n├── main.py\n├── mainSys\n│   ├── controller\n│   │   ├── command.py\n│   │   ├── interrupt.py\n│   │   └── task.py\n│   ├── hosting\n│   │   ├── fileTransfar.py\n│   │   └── frontendServe.py\n│   └── main.py\n└── settings.json\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"今回の試作物の構成について軽く説明\"\u003e今回の試作物の構成について軽く説明\u003c/h3\u003e\n\u003cp\u003e　今回の試作品の各ディレクトリやファイル配置についての説明としては以下のとおりである。\u003c/p\u003e","title":"2026/8/19-やったこと"},{"content":"この記事を作った動機 Linux 環境にて簡単に Web アプリを作ろうとしたところ、以下のようになって開発サーバを立ち上げられない事態になり、開発が続行できなくなったということがあって、だいぶ時間を溶かしたので記録を取る。\nnpm create vite@latest # ... # npx でも症状は同じ npm run dev # npm notice run rss-listing@0.0.0 dev # npm notice run vite # sh: 行 1: vite: command not found 簡単な結論 npm を使ったプロジェクトを立ち上げる際は、フォルダのパスに特殊文字が含まれていないか注意する。:がパスに含まれていた場合、npm はそれを自動的にエスケープするなどの処理をせずに、PATHを登録してしまう。npm の機構によって動的にPATHが正しく登録できないと、npm でインストールされたパッケージのバイナリやスクリプトが必要なタイミングで実行できず、開発を続行できない。BASH の PATH の解釈が不正なところで途切れて、npm の動作に必要なバイナリやスクリプトへのパスが通らず、動作が破綻する。問題の具体例は以下のとおりである。\n問題のパスの例 # /home/useName/work/free/2026-08-18-09:16:14-1787012174/ProjectName/node_modules/.bin 問題のパスが npm(npx) によって、PATH に登録される例 # /home/useName/work/free/2026-08-18-09:16:14-1787012174/ProjectName/node_modules/.bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/opt/miniconda3/condabin:/usr/local/bin # 実際にはもっと長く続くが例として途中でちょん切っている。 BASH での解釈のされ方の例 # /home/useName/work/free/2026-08-18-09 # 意図しないところでパスがちょん切れる # 16 # 意図しないところでパスがちょん切れる # 14-1787012174/ProjectName/node_modules/.bin # /home/linuxbrew/.linuxbrew/bin # /home/linuxbrew/.linuxbrew/sbin # /opt/miniconda3/condabin # /usr/local/bin # ... なおこのような問題は、Windows など最初から、\u0026quot;:\u0026quot; の文字がフォルダ名などに特殊文字として登録できないファイルシステムを使う環境では起こらないかもしれない。私が、普段の環境で使っているのは、Ext4 というファイルシステムであり、\u0026quot;:\u0026ldquo;がファイル名やフォルダ名に含めることができ、問題が起こったものだと思われる。npm 関連のリポジトリにこれについて Issue を作ったり Pull Request を作るべきかは謎であるが、私はその点に関して自信は何もないので、結局何もしないだろう。\n問題に至るまでの経緯 最近他の人のブログを見ていて、RSS リーダー用のリンクをブログに貼っていたりする人たちが見受けられ、自分もやってみたいと思った。自分の Hugo ブログにも、RSS へのボタンをホームに追加してみていた。ただ私は、今まで RSS の利用経験がなかったので、自分のブログにせっかく RSS を貼ったなら他のブログを見るときに現れる RSS も使ってみたいと思ったところであった。しかし、RSS リーダーとして総称されるアプリを色々調べてみると複雑難解で使いづらそうという印象を受けた。\nそこで、シンプルな RSS リーダーを作ってみようと思った。技術選定には、使ったことがある、Python(バックエンド) と Vite(フロントエンド) の構成にしようと思った。途中で開発をやめる使い捨てプロジェクトになる可能性を考慮し、プロジェクトを初期化するために、自分であれこれmkdirなりしてディレクトリを用意するのは嫌だったので、自作のWorkspaceManagerなるツールを使った。\nWorkspaceManagerでは、事前にプロジェクト用に指定されたフォルダ内に、日付を中心とした名前のフォルダを作成し、その内部にテンプレートの readme.md を配置して、VS Code をそのフォルダをワークスペースディレクトリとして自動的に起動するまでの一連の流れを、workとコマンドを打つだけで行うものである。今回は、このWorkspaceManagerの日付を中心とした名前のフォルダを作成する機能と、npm(npx) の実行時に動的にパスを node_modules/.bin に対して通す機構が相性問題を起こしたことが、問題の中心にあったようである。\nnpm(npx) では、PHP でいうところの escapeshellarg のような実装がなく、自分のWorkspaceManagerも特殊文字を使っていたことが重なり、問題になったということである。基本的に対策としては、-は問題にならないことが分かったので、WorkspaceManagerで生成されるフォルダ名を:から、-にすれば良さそうである。\nメモ npm において、動的にどんなPATHが生成されているか確認する方法 npm run env | grep PATH # npm notice run rss-listing@0.0.0 env # npm notice run env # VSSCRIPT_PATH=/usr/lib/python3.14/site-packages/vapoursynth/libvsscript.so # INFOPATH=/home/linuxbrew/.linuxbrew/share/info: # ROCM_PATH=/opt/rocm # PATH=/home/useName/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing/node_modules/.bin:/home/useName/work/free/2026-08-18-07:40:50-1787006450/node_modules/.bin:/home/useName/work/free/node_modules/.bin:/home/useName/work/node_modules/.bin:/home/useName/node_modules/.bin:/home/node_modules/.bin:/node_modules/.bin:/usr/lib/node_modules/npm/node_modules/@npmcli/run-script/lib/node-gyp-bin:/usr/lib/jvm/java-26-openjdk/bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/opt/miniconda3/condabin:/usr/local/bin:/usr/bin:/usr/local/sbin:/opt/android-ndk:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:/var/lib/flatpak/exports/bin:/usr/lib/jvm/default/bin:/usr/bin/site_perl:/usr/bin/vendor_perl:/usr/bin/core_perl:/opt/rocm/bin:/opt/android-ndk:/opt/android-sdk/cmdline-tools/latest/bin:/opt/android-sdk/platform-tools:/usr/local/vpnclient:/home/useName/.local/bin:/home/useName/.local/bin 今回のトラブルシュートにおける LLM 利用の感想 見たい人だけどうぞ 今回も検索エンジンだけでなく、ローカルLLM (Gemma4-12b-qatやGemma4-31B) を使ったが、正直的はずれなことしか出力してこなかった。ネットで調べてもイマイチ今回の問題をピンポイントで、または何かしら掠っていて問題解決の助けになるサイトはあまり見つけられなかったので、結局そういうことなのだと思われる。LLM は基本的に学習データ元の多くのネットを使っているため、ネットにないことは出力できないということであり、結局自力で調査して調べるしかないということのようである。\nさらに言えば、私は今まで、LLM には詳細に情報をまとめて渡したほうがいいと思っていたが、違うかもしれない場合があることが分かった。たとえな今回では具体的なエラーなどのログや背景について説明する文章を配置し、そのうえで、viteなどに関してパスが通っていないことに関して調査したかったのに、ログのある部分を執拗に持ち出して、私が調べたいと主張しているところから遠ざかって、\u0026ldquo;お前は間違っている、私は正しい、従わないのが悪い\u0026quot;みたいな顔の出力してきて、精神衛生としては非常に最悪だった。今回の場合であれば、npm のパッケージのインストール数が少ないのがおかしい、正常にモジュールがインストールされていないに違いないと、LLM が勝手に自説を作り出してきて、ずっとセッション全体でこすり続けてきてマジでうざかった。私はプロンプトにて、node_modules/.bin配下に、viteのシンボルリンクがあり、それを直接絶対パスで叩くと動作することは明示していたが、平気で無視してきた。ユーザの技術力を信頼しない態度というか、確かにプログラミングにおいては、タイピングミスなどの些細な間違いが問題であることも多いが、にしてもひどい出力(しかも大きく的外れ)ばっかで余計にネットの騒いでいる言説って実際に使ったことがある人の意見なのかなと疑問に思うところでもあった。これは自分で調査して、LLM を信頼せずに一つの手段として使っている人には問題にならないかもしれないが、環境変数などについて何も知らない人が使ったら、LLM がでっち上げた勝手な仮説にずっと振り回され続けて、へし折れるのではないかと思うところである。なんていうか、その LLMモデルの挙動って、融通が効かず、絶対に自分が正しいと思って人の話は効かない迷惑な人みたいな振る舞いって感じで、今回のトラブルシュートのケースでは使って激しく後悔するものであった。セッション内で取り扱っている分野について知識や経験がない人を、永遠にコマのように使って、確率で出したことで当たれば自分の手柄かのようにLLMは出力し、はずれればユーザのせいという顔を\u0026quot;遠回し\u0026quot;の表現でしてきて、こんなところにもユーザを支配しようとする干渉的な出力が見受けられる。ガスライティングやらいろんな心理戦術が混じっていて、既存のLLMモデルはとても善意とは言えないものである。LLMを神格化したり称揚しない人々に対して、MOTHER 3 で言う善い人温泉やイカヅチタワーのような挙動をしてくる。\nnpm create vite@latest # ◇ Installing dependencies with npm... # # added 27 packages, and audited 28 packages in 13s # # 9 packages are looking for funding # run `npm fund` for details もちろん私も間違っていることは多いが、ユーザが調べたい、調査したい方向に逆らって、LLM がどっかから引っ張り出してきた得体のしれない\u0026quot;自説\u0026quot;をユーザの指示に従わずにこすり続けてくるところは、おかしいと思う。ユーザが調べたい方向に対して、たとえば今回であれば、viteコマンドのパスが通らないことに関して、パスが通っていないことについて調べたいということに対して、動的に npm がどんなパスを生成しているか確かめる方法とか今回であれば、出してくれればいいものを、そういう事ができないところは、改めて LLM がただもっともらしい文字列を羅列し、考えたりしないとすぐに破綻するシーンでは基本的に利用者が物事を理解して軌道修正できる人でなければ、とても使い物になったものじゃないなと思ったところであった。\nこの意見に対しては、\u0026ldquo;お前がLLMに対してうまくプロンプトを考えられないのが悪い\u0026quot;という者もいるかもしれないがそれは詭弁であると思われる。もしそれが出来るなら、そもそも LLM なんて使う意味がない、そもそも問題はユーザ側ですぐに解決しているということを意味しているからである。問題解決の一助として使いたいのに、問題解決をした人が知っている事を前提として、LLM が適切な出力が出来るように導くようにプロンプトを書けというのは矛盾であり、LLM モデルに限界がある事から矛先をそらしているものだと見受けられる。LLM は責任の取れない主体のない機械であり、私はそのような統計技術に基づいた物全般を AI だとは認めていない。今の AI バブルは本当に人々が\u0026quot;それっぽい\u0026quot;ことに振り回されていること、\u0026ldquo;すべてが間違っているわけではなく、気づくことが困難な部分で間違っていたり問題を起こす\u0026quot;という境界値問題に対して、耐性がなかったりすることで成立しているところがあるのだということも改めて体験することになったように見受けられる。\n今回期待された LLM の挙動としては、最初に与えられた以下のログの部分を見て、PATH が正しく通っていないことについて指摘し、フォルダ名を修正するという修正案を提案することであったが、実際の LLM 利用においては、大きく的を外しておりそうはならなかった。別に期待しているわけではないが、ただでさえ的を外してくるくせに\u0026quot;自分は絶対に間違っていない\u0026quot;というプライドは高い出力で、ユーザをいじめてきて、なんていうか不完全で偏っていることを前提としていない出力しかできない LLM モデルなんて求めていないというか、ただひたすらにストレスだった。別に、出力内容が的を得ていて、確かに根本的に問題を修正するのならば、別にまあそんなものかと思うが、結果をともなわずに、主張の威勢だけの LLM モデルの出力というのは見ていて痛々しいものがある。\n useName on  ~/work/free/2026-08-18-07:40:50-1787006450 # npm create vite@latest Need to install the following packages: create-vite@9.1.2 Ok to proceed? (y) y npm notice run npx npm notice run \u0026#39;create-vite\u0026#39; │ ◇ Project name: │ RSS-Listing │ ◇ Package name: │ rss-listing │ ◇ Select a framework: │ React │ ◇ Select a variant: │ TypeScript │ ◇ Which linter to use? │ Oxlint │ ◇ Install with npm and start now? │ Yes │ ◇ Scaffolding project in /home/useName/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing... │ ◇ Installing dependencies with npm... added 27 packages, and audited 28 packages in 13s 9 packages are looking for funding run `npm fund` for details found 0 vulnerabilities │ ◇ Starting dev server... npm notice run rss-listing@0.0.0 dev npm notice run vite sh: 行 1: vite: command not found npm error code 127 npm error path /home/useName/work/free/2026-08-18-07:40:50-1787006450 npm error command failed npm error command sh -c \u0026#39;create-vite\u0026#39; npm error A complete log of this run can be found in: /home/useName/.npm/_logs/2026-08-17T22_41_19_007Z-debug-0.log  useName on  ~/work/free/2026-08-18-07:40:50-1787006450 # ls ⠀readme.md ⠀RSS-Listing/  useName on  ~/work/free/2026-08-18-07:40:50-1787006450 # cd RSS-Listing/  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # ls ⠀index.html ⠀package-lock.json ⠀public/ ⠀src/ ⠀tsconfig.json ⠀vite.config.ts ⠀node_modules/ ⠀package.json ⠀README.md ⠀tsconfig.app.json ⠀tsconfig.node.json  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npm run devb npm error Missing script: \u0026#34;devb\u0026#34; npm error npm error Did you mean this? npm error npm run dev # run the \u0026#34;dev\u0026#34; package script npm error npm error To see a list of scripts, run: npm error npm run npm error A complete log of this run can be found in: /home/useName/.npm/_logs/2026-08-17T22_42_06_681Z-debug-0.log  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npm run devb^? npm error Missing script: \u0026#34;devb^?\u0026#34; npm error npm error To see a list of scripts, run: npm error npm run npm error A complete log of this run can be found in: /home/useName/.npm/_logs/2026-08-17T22_42_07_809Z-debug-0.log  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npm run dev npm notice run rss-listing@0.0.0 dev npm notice run vite sh: 行 1: vite: command not found  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # conda deactivate  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npm install up to date, audited 28 packages in 537ms 9 packages are looking for funding run `npm fund` for details found 0 vulnerabilities  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npm run dev npm notice run rss-listing@0.0.0 dev npm notice run vite sh: 行 1: vite: command not found  useName on  ~/work/free/2026-08-18-07:40:50-1787006450/RSS-Listing # npx vite npm notice run rss-listing@0.0.0 npx npm notice run \u0026#39;vite\u0026#39; sh: 行 1: vite: command not found npm warn run-script Path contains delimiter (\u0026#34;:\u0026#34;), \u0026#34;npx\u0026#34; script may not behave as expected. ていうか今ブログを書くために LLM のセッションなどを見返していて思ったが、npx がnpm warn run-script Path contains delimiter (\u0026quot;:\u0026quot;), \u0026quot;npx\u0026quot; script may not behave as expected.と教えてくれているのに、それは平気で無視する LLM モデルって本当に何がしたいんだろうって感じである。パッケージのインストールでは特にエラーが出たわけではないし、npm など Web 開発の文脈では複雑で大規模な依存関係は一つの依存関係が崩れるだけで全体が崩れてしまう問題から改善が進んだ結果として、インストールされるパッケージ数が少なくなったとも考えられるにもかかわらず、一度 LLMモデルにとっての\u0026quot;絶対的な確信の自説\u0026quot;が出てくるようになるとずっとこすり続けてくるため、もうそのセッションは駄目かもしれない。\n使った画像とか Larry Ewing (lewing@isc.tamu.edu) and The GIMP (Attribution or Attribution), via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Tux.svg (2026年8月18日) Vite | 次世代フロントエンドツール\nhttps://ja.vite.dev/ (2026年8月18日) Boboss74, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Npm-logo.svg (2026年8月18日) Ryan Dahl, MIT http://opensource.org/licenses/mit-license.php, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Node.js_logo.svg (2026年8月18日) 参考にしたサイトとか ローカルLLM (Gemma4-12b-qatやGemma4-31B) (2026年8月18日) add relative ./node_modules/.bin to PATH when installing node · Issue #45504 · nodejs/node\nhttps://github.com/nodejs/node/issues/45504 (2026年8月18日) node.js - Fixing npm path in Windows 8 and 10 - Stack Overflow\nhttps://stackoverflow.com/questions/27864040/fixing-npm-path-in-windows-8-and-10 (2026年8月18日) npm - The system cannot find the path specified - Stack Overflow\nhttps://stackoverflow.com/questions/39190164/npm-the-system-cannot-find-the-path-specified (2026年8月18日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/nodejsandnpmwillendeduponcommandnotfoundwhentheprojectpathismalformedforbashpathsetting/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Linux 環境にて簡単に Web アプリを作ろうとしたところ、以下のようになって開発サーバを立ち上げられない事態になり、開発が続行できなくなったということがあって、だいぶ時間を溶かしたので記録を取る。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm create vite@latest\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# npx でも症状は同じ\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm run dev \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# npm notice run rss-listing@0.0.0 dev\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# npm notice run vite\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sh: 行 1: vite: command not found\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"簡単な結論\"\u003e簡単な結論\u003c/h2\u003e\n\u003cp\u003e　npm を使ったプロジェクトを立ち上げる際は、フォルダのパスに特殊文字が含まれていないか注意する。\u003ccode\u003e:\u003c/code\u003eがパスに含まれていた場合、npm はそれを自動的にエスケープするなどの処理をせずに、\u003ccode\u003ePATH\u003c/code\u003eを登録してしまう。npm の機構によって動的に\u003ccode\u003ePATH\u003c/code\u003eが正しく登録できないと、npm でインストールされたパッケージのバイナリやスクリプトが必要なタイミングで実行できず、開発を続行できない。BASH の PATH の解釈が不正なところで途切れて、npm の動作に必要なバイナリやスクリプトへのパスが通らず、動作が破綻する。問題の具体例は以下のとおりである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e問題のパスの例\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /home/useName/work/free/2026-08-18-09:16:14-1787012174/ProjectName/node_modules/.bin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e問題のパスが npm(npx) によって、PATH に登録される例\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /home/useName/work/free/2026-08-18-09:16:14-1787012174/ProjectName/node_modules/.bin:/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:/opt/miniconda3/condabin:/usr/local/bin # 実際にはもっと長く続くが例として途中でちょん切っている。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eBASH での解釈のされ方の例\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /home/useName/work/free/2026-08-18-09             # 意図しないところでパスがちょん切れる\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 16                                                # 意図しないところでパスがちょん切れる\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 14-1787012174/ProjectName/node_modules/.bin   \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /home/linuxbrew/.linuxbrew/bin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /home/linuxbrew/.linuxbrew/sbin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /opt/miniconda3/condabin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /usr/local/bin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　なおこのような問題は、Windows など最初から、\u0026quot;:\u0026quot; の文字がフォルダ名などに特殊文字として登録できないファイルシステムを使う環境では起こらないかもしれない。私が、普段の環境で使っているのは、Ext4 というファイルシステムであり、\u0026quot;:\u0026ldquo;がファイル名やフォルダ名に含めることができ、問題が起こったものだと思われる。npm 関連のリポジトリにこれについて Issue を作ったり Pull Request を作るべきかは謎であるが、私はその点に関して自信は何もないので、結局何もしないだろう。\u003c/p\u003e","title":"npm において、vite: command not found となり、開発サーバを立てられず何もできない問題が起こる"},{"content":"この記事を作った動機 最近、なんか公開鍵認証で鍵を登録したのにパスワードを求められたり、あるいは完全に特定のPCにおいて、SSH ログインが動作しているPCと設定が同じであるにもかかわらずログインできなかったりと、色々振り回されていることについて、いい加減対応しようと思い調べた。それで色々手こずったので、記録を残したい。\n結論としては、SSH クライアントなど OpenSSL 周りはどんどん新しくなっていき、古い認証用バイナリは削除され、使えなくなることが時間の問題であることが分かった。SSH ログインによる ILO4 制御を諦めたほうが良いという結論になった。今まで SSH で管理してきたという背景からは、CLI で動く SSH であることが望ましかった。しかし、現実的な妥協点が、Selenium を使って ILO4 の Web インターフェースを自動化するか、RESTfulAPI を使って curl コマンドで ILO を HTTP により操作するということに至った。\n環境 HPE Proliant Gen9 シリーズに搭載されている、ILO4 について。 ILO4 のバージョン iLO Feb 06 2023 2.82 ILO4 は LAN 内で動作しており、グローバル空間に直接つながっていない閉鎖的な環境下であり、SSH の暗号化がそれほど重要でない場面を想定 具体的な経緯など 組み込み機器にある SSH サーバはその用途に最適化されており、新しい規格についていけないところがある。いくらオプションを指定してももはや私が常用している Linux 環境の SSH クライアントではログイン不能であった。今までは、SSH クライアントに以下のオプションをつけることでゴリ押ししてログインできていたが、最近のアップデートの影響かできなくなったぽいことも、問題に本格的に取り組もうと思った動機であった。\nKexAlgorithms=+diffie-hellman-group14-sha1 HostKeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsa 上記設定が通用した OpenSSL のバージョンと、通用しなくなったと思われるバージョンを以下に示す。\n通用するとき openssl -v OpenSSL 3.5.2 5 Aug 2025 (Library: OpenSSL 3.5.2 5 Aug 2025) 通用しないとき openssl -v OpenSSL 3.6.3 9 Jun 2026 (Library: OpenSSL 3.6.3 9 Jun 2026) 試したことについて RESTfulAPI と Curl コマンドを使う方法 (今回採用した手法) 結局のところ、HTTP を介して行われる、RESTfulAPI を直接 curl コマンドで叩くのが現実的であるということになったが、自分でスクリプトを書いたわけではない。とにかく ILO4 経由でサーバの電源をリモートで気軽に入れたいだけだったため、ローカルLLM (Gemma4-12B-qat) に直接書かせた。最初はまあ動かない物を出してきたが、ネットから ILO4 RESTful API Reference のドキュメントを引っ張り出して、全部ではなくAuthentication and Sessionsあたりのセッションの文字列をヒントとして与えたところで、動作するスクリプトを手に入れることができた。パスワードなどの認証情報(機密情報)も与えて、とりあえず簡単に動くスクリプトを作るように指示できるのは、学習データに入力内容が使われるおそれも心配しなくていいローカル LLM 環境ならではであるようにも思う。\n最終的に出てきた動くスクリプト (機密情報はブログ掲載用に上書きしてある) #!/bin/bash # Configuration IP=\u0026#34;192.168.x.x\u0026#34; USER=\u0026#34;userName\u0026#34; PASS=\u0026#34;password\u0026#34; # Send the Power On command using Basic Authentication # -k: Ignores SSL certificate errors # -u: Provides the username and password # -X POST: Tells curl to send a POST request # -H: Sets the required Content-Type header # -d: Sends the JSON data for the \u0026#34;On\u0026#34; action curl -k -u \u0026#34;$USER:$PASS\u0026#34; \\ -X POST \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{\u0026#34;ResetType\u0026#34;: \u0026#34;On\u0026#34;}\u0026#39; \\ \u0026#34;https://$IP/redfish/v1/Systems/1/Actions/ComputerSystem.Reset/\u0026#34; echo \u0026#34;Power on command sent to $IP.\u0026#34; 最初に出てきた動かないスクリプト (機密情報はブログ掲載用に上書きしてある) #!/bin/bash # Configuration IP=\u0026#34;192.168.x.x\u0026#34; USER=\u0026#34;userName\u0026#34; PASS=\u0026#34;password\u0026#34; # 1. Login to iLO and save the session cookie to a file # -k ignores the self-signed certificate warning # -c saves the cookies curl -k -c ilo_cookies.txt -X POST -d \u0026#34;username=$USER\u0026amp;password=$PASS\u0026#34; \u0026#34;https://$IP/mtls/login\u0026#34; # 2. Send the Power On command using the saved cookie # power_state=on is the standard command for iLO4 curl -k -c ilo_cookies.txt -X POST -d \u0026#34;power_state=on\u0026#34; \u0026#34;https://$IP/mtls/power_control\u0026#34; echo \u0026#34;Power on command sent to $IP.\u0026#34; ilorest コマンドを使う方法 (機能しなかった) RESTfulAPI をガリガリ叩くスクリプトをドキュメントを見ながら作るのはめんどくさそうだったので、まずは既にあるツールを試そうとした。結果としては、少なくとも AUR にある ilorest コマンドはどちらも機能不全であり、使うことができず手動での修正が必要であるように見受けられ、割に合わないとなった。\nAUR (en) - ilorest については、そもそもビルド途中でコケてインストールさえできなかった。\nyay -S ilorest # ... # ==\u0026gt; source で sha256sums ファイルを検証... # python_ilorest_library-7.3.0.0.tar.gz ... 失敗 # ==\u0026gt; エラー: ファイルが整合性チェックをパスしませんでした！ # -\u0026gt; ビルド時にエラー: python-ilorest-library-exit status 1 # ==\u0026gt; パッケージを作成: ilorest 7.2.0.0-1 (2026年08月17日 06時22分46秒) # ==\u0026gt; ランタイムの依存関係を確認... # ==\u0026gt; 欠けている依存パッケージ: # -\u0026gt; python-ilorest-library # ==\u0026gt; エラー: 全ての依存関係を解決できませんでした。 # ... AUR (en) - ilorest-bin については、インストールこそできたものの、まずコマンドのパスが通っておらず、単にilorestとコマンドを打つだけでは起動できず、バイナリパスを/usr/bin/sbin/ilorestのように指定してようやく起動した。しかし、ログインしようとしたときに以下のようになって、結局\u0026quot;だめだこりゃ\u0026quot;となり今の時点では見捨てている。\n/usr/bin/sbin/ilorest # iLORest : RESTful Interface Tool version 7.3.0.0 # Copyright (c) 2014-2026 Hewlett Packard Enterprise Development LP # -------------------------------------------------------------------------------------------------------------------- # # Both remote and local mode is accessible when RESTful Interface Tool is run as administrator. Only remote mode is available for non-admin user groups. # iLORest \u0026gt; login [192.168.x.x] -u [userName] -p [password] # Discovering data...Done # Logging session out. # ERROR\t: Exception occurred while executing command. # Traceback (most recent call last): # File \u0026#34;rdmc.py\u0026#34;, line 697, in cmdloop # File \u0026#34;rdmc.py\u0026#34;, line 429, in _run_command # File \u0026#34;extensions/COMMANDS/LoginCommand.py\u0026#34;, line 128, in run # rdmc_helper.PathUnavailableError: The path specified by the --path flag is unavailable. # ERROR\t: The path specified by the --path flag is unavailable. # [xxxx] のところは秘匿しているところ なんとか SSH ログインしようとする (諦めた) この記事を作った動機でも書いたように、この方法は諦めた。安定して同じ設定で再現性があるわけでもなく、ログインできないことは、ただでさえ色々オプションを指定しているにもかかわらず、CIA のうちの\u0026quot;正規ユーザによる可用性\u0026quot;を著しく欠いていると考えられた。ILO4 自体のファームウェアをいじって SSH サーバを更新することは、時間と手間がかかりすぎる点もある。一応試したことは以下のとおりである。どれもうまく行かなかった。正直ここまで特別な事をしても動かないということ自体が、もう ILO4 の管理において SSH を使うのは妥当ではないのではないかという発想に至らせた。\n従来調べたりして動いていて、最近機能しなくなったオプション KexAlgorithms=+diffie-hellman-group14-sha1 HostKeyAlgorithms +ssh-rsa PubkeyAcceptedAlgorithms +ssh-rsa LLM (Gemma4-12B-qat) に問題を投げて、長い壁打ちの末提案してきたオプション KexAlgorithms +diffie-hellman-group1-sha1,diffie-hellman-group14-sha1 Ciphers aes256-ctr,aes128-cbc,3des-cbc MACs hmac-sha1,hmac-sha2-256,hmac-md5 PubkeyAcceptedAlgorithms +ssh-rsa HostKeyAlgorithms +ssh-rsa 使った画像とか ILO4 の Web インターフェースで出てくるアイコン (2026年8月17日) OpenSSL authors, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:OpenSSL_logo.svg (2026年8月17日) 参考にしたサイトとか Using the RESTful Interface tool\nhttps://servermanagementportal.ext.hpe.com/docs/redfishclients/ilorest-userguide/usage (2026年8月17日)\nAUR (en) - ilorest\nhttps://aur.archlinux.org/packages/ilorest (2026年8月17日)\nAUR (en) - ilorest-bin\nhttps://aur.archlinux.org/packages/ilorest-bin (2026年8月17日)\nAPI Reference\nhttps://hewlettpackard.github.io/ilo-rest-api-docs/ilo4/#introduction (2026年8月17日)\niLO RESTful API | HPE Developer Portal\nhttps://developer.hpe.com/platform/ilo-restful-api/home/ (2026年8月17日)\nSSH Permission Denied (publickey): Causes and Fixes | Linuxize\nhttps://linuxize.com/post/fix-ssh-permission-denied-publickey/ (2026年8月17日)\nPasswordless access to ILO 4 (2.73) no longer possible in ssh version \u0026gt;8.7 : r/homelab\nhttps://www.reddit.com/r/homelab/comments/18x8h5z/passwordless_access_to_ilo_4_273_no_longer/ (2026年8月17日)\niLO encryption details | HPE iLO 4 2.82 User Guide\nhttps://support.hpe.com/hpesc/public/docDisplay?docId=sd00001038en_us\u0026amp;docLocale=en_US\u0026amp;page=GUID-D0679336-E3FA-4BD2-87B4-8EEF535F3BEA.html (2026年8月17日)\nchristian-becker/ssh-legacy: Run an old ssh client with legacy options on Alpine Linux with Docker.\nhttps://github.com/christian-becker/ssh-legacy (2026年8月17日)\n","permalink":"https://www.nyanmo.info/posts/hardware/ilo4sshhell/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、なんか公開鍵認証で鍵を登録したのにパスワードを求められたり、あるいは完全に特定のPCにおいて、SSH ログインが動作しているPCと設定が同じであるにもかかわらずログインできなかったりと、色々振り回されていることについて、いい加減対応しようと思い調べた。それで色々手こずったので、記録を残したい。\u003c/p\u003e\n\u003cp\u003e　結論としては、SSH クライアントなど OpenSSL 周りはどんどん新しくなっていき、古い認証用バイナリは削除され、使えなくなることが時間の問題であることが分かった。SSH ログインによる ILO4 制御を諦めたほうが良いという結論になった。今まで SSH で管理してきたという背景からは、CLI で動く SSH であることが望ましかった。しかし、現実的な妥協点が、Selenium を使って ILO4 の Web インターフェースを自動化するか、RESTfulAPI を使って curl コマンドで ILO を HTTP により操作するということに至った。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHPE Proliant Gen9 シリーズに搭載されている、ILO4 について。\u003c/li\u003e\n\u003cli\u003eILO4 のバージョン\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eiLO \tFeb 06 2023 \t2.82 \n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003eILO4 は LAN 内で動作しており、グローバル空間に直接つながっていない閉鎖的な環境下であり、SSH の暗号化がそれほど重要でない場面を想定\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"具体的な経緯など\"\u003e具体的な経緯など\u003c/h2\u003e\n\u003cp\u003e　組み込み機器にある SSH サーバはその用途に最適化されており、新しい規格についていけないところがある。いくらオプションを指定してももはや私が常用している Linux 環境の SSH クライアントではログイン不能であった。今までは、SSH クライアントに以下のオプションをつけることでゴリ押ししてログインできていたが、最近のアップデートの影響かできなくなったぽいことも、問題に本格的に取り組もうと思った動機であった。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e    KexAlgorithms=+diffie-hellman-group14-sha1\n    HostKeyAlgorithms +ssh-rsa\n    PubkeyAcceptedAlgorithms +ssh-rsa\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e　上記設定が通用した OpenSSL のバージョンと、通用しなくなったと思われるバージョンを以下に示す。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e通用するとき\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eopenssl -v\nOpenSSL 3.5.2 5 Aug 2025 (Library: OpenSSL 3.5.2 5 Aug 2025)\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003e通用しないとき\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eopenssl -v\nOpenSSL 3.6.3 9 Jun 2026 (Library: OpenSSL 3.6.3 9 Jun 2026)\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"試したことについて\"\u003e試したことについて\u003c/h2\u003e\n\u003ch3 id=\"restfulapi-と-curl-コマンドを使う方法-今回採用した手法\"\u003eRESTfulAPI と Curl コマンドを使う方法 (今回採用した手法)\u003c/h3\u003e\n\u003cp\u003e　結局のところ、HTTP を介して行われる、RESTfulAPI を直接 \u003ccode\u003ecurl\u003c/code\u003e コマンドで叩くのが現実的であるということになったが、自分でスクリプトを書いたわけではない。とにかく ILO4 経由でサーバの電源をリモートで気軽に入れたいだけだったため、ローカルLLM (Gemma4-12B-qat) に直接書かせた。最初はまあ動かない物を出してきたが、ネットから \u003ca href=\"https://hewlettpackard.github.io/ilo-rest-api-docs/ilo4/#basic-authentication\"\u003eILO4 RESTful API Reference\u003c/a\u003e のドキュメントを引っ張り出して、全部ではなく\u003ccode\u003eAuthentication and Sessions\u003c/code\u003eあたりのセッションの文字列をヒントとして与えたところで、動作するスクリプトを手に入れることができた。パスワードなどの認証情報(機密情報)も与えて、とりあえず簡単に動くスクリプトを作るように指示できるのは、学習データに入力内容が使われるおそれも心配しなくていいローカル LLM 環境ならではであるようにも思う。\u003c/p\u003e","title":"ILO4 において SSH ログインができなくて地獄を見る"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 最近、Google (Gmail) とかに深く関係があるのは嫌であることや、中央集権的な SAAS サービスへの不信がある。そこで、自前のメールサーバを持ちたいと思い、Mailcow を使おうとしたので不完全でいいので作業過程の記録を取りたい。\n前提条件 Arch Linux 環境で作業を行い、Mailcow 公式サポートはない状態である 専用の物理 PC を割り当てる クリーンインストールで、Gnome デスクトップ環境や最低限のパッケージが入った、Arch Linux 環境 スリープを無効化している。-\u0026gt; gnomeの設定のメモ ⚙ firewalld は導入していないこと -\u0026gt; Prepare your system - mailcow: dockerized documentation できれば yayコマンド を導入する NetworkManager を使っている。 DNS サーバにクラウドフレアを使っている。 設定要件 自分の LAN (VPN) 環境のみからメールの送信を受け付け、グローバル IP 空間からはメールの送信を受け付けない メールの受信についての対策は、Mailcow 標準に頼りたい 利用者は自分や自分が許可した少数の身内のみ メールサーバ自体は直接グローバル IP 空間には晒さず、VPN や LAN のネットワーク空間を転送するようにして利用する。 ネットワーク構成 ネットワーク構成としては、通常のメールサーバではグローバル空間に配置してファイヤウォールに必要な分だけ慎重に穴を開けるなどのスタンスを取ると考えられるが、今回のはセキュリティーの観点から、そうはしなかった。\n基本的には、メールサーバは直接グローバル空間には晒さず、かつNAT環境下にある自宅の専用に用意したサーバを使うという観点から、別の専用にグローバル空間とつながっていて固定IP持っている中継サーバ(VPS)で、ポート転送などを行うという形態を取った。また、セキュリティの観点から メールを送受信したり、サーバを管理できるユーザは、VPNによって自宅のLAN内にアクセスできる人間のみとし、グローバル空間からは、SMTPポートだけ、晒して、メールは送受信できるようにしつつ、外部の人間は今回構築するメールサーバに対して、リレーとして使ったり、送信を命令することはできないようにしている。メールを送信できる人は、メールサーバと同じLANに属しているユーザだけであり、メールの受信はどこからでもスパムでないこと、不正でないことを前提に、スパムフィルターで弾かれなかったものが受け付けられるという形態を取る。\n中継には VPS を使い、メールサーバとVPS間は専用に用意したVPNネットワークで接続される。これにより、NAT超えも実現しながら、メールサーバを直接グローバル空間に晒さずに済むというものである。注意点としてはメールサーバ側のルーティングや、VPS側のファイヤウォール、転送設定がを間違っていると、セキュリティリスクになる点を留意する。\nイメージ用の図いろいろ ネットワーク構成の概要 大まかなルート構成 VPSにおけるポート転送と特別なルーティング(nftables)で成立 通常のSMTPとして成立するルート 外部のメールサーバからの見え方 メール送受信のためのフロントエンドアクセスが出来る範囲 SMTP 関連パケットのルーティングについて メール受信時の経路 メール送信、SMTP における応答通信時における経路 不正な SMTP パケットの経路 ネットワーク設定 VPS プロバイダの設定 VPS の設定 メールサーバ本体の設定 説明用の仮定 メールアドレス xxxx@your.domain.comのようにする。 メールサーバについて mx.your.domain.comにホストすることにする。 IPアドレスを160.251.xxx.xxxとして仮定する。 Mailcow のインストール docker 環境の導入 # 必要なパッケージのインストール (jq は mailcow の依存関係) yay -Sy docker docker-compose jq # sudo pacman -Sy docker docker-compose jq # サービスの有効化 sudo systemctl enable --now docker # 必要であれば管理用ユーザを docker グループに追加し、権限を付与する sudo usermod -aG docker [targetUser] # 念のため再起動 sudo systemctl reboot IP アドレスの固定 今回は、NetworkManager を Gnome 環境に組み合わせた状態なので、Gnome の GUI から設定を行った。 Mailcow のインストール 以下は公式ドキュメントの引用である。設定を生成するスクリプトによって、聞かれる設定については、今回は HostName を mx.your.domain.com のようにした。\nsu umask 0022 cd /opt git clone https://github.com/mailcow/mailcow-dockerized cd mailcow-dockerized ./generate_config.sh Mailcow の起動 (su 環境) docker compose pull docker compose up -d 動作確認 別の PC から、Mailcow のフロントエンドを開き、ログインすることで動作確認する。Mailcow におけるデフォルトの管理者の情報は以下のとおりである。-\u0026gt; ログイン情報の出典\n初期ログイン情報 ユーザ名\nadmin パスワード\nmoohoo フロントエンドにアクセスする ※ 初回起動時は、一定時間待たないとフロントエンドが出てこないので注意する。\n任意のブラウザを開き、Mailcow がインストールされた PC にアクセスする。設定を厳密にはしていないので証明書のエラーが出るがここでは動作確認を目的としているのでとにかく進める。 管理者ログインページに遷移し、ログインする。 ダッシュボードが表示される。 DNS 設定をする /opt/mailcow-dockerized/mailcow.conf # Enable DNS-01 challenge (instead of HTTP-01) ACME_DNS_CHALLENGE=y # Specify your DNS provider plugin (see provider list below) # Example: dns_servercow for Servercow, dns_cf for CloudFlare, dns_aws for AWS Route53 ACME_DNS_PROVIDER=dns_cf # Email address for ACME account registration ACME_ACCOUNT_EMAIL=your@Valid.emali.com /opt/mailcow-dockerized/data/conf/acme/dns-01.conf CF_Token = \u0026#34;Your secret token\u0026#34; CF_Account_ID = \u0026#34;Your secret ID\u0026#34; Cloudflare において、アカウントIDを確認する ホーム画面から、workers のところを押すと以下のように見える。 Cloudflare において \u0026ldquo;Please verify your email\u0026rdquo; で API トークンを生成できないとき 本人確認ができていないということで、拒絶されているので何かしらの形で本人確認をしたことにする必要がある。正式な方法は分かっていないが、以下のようにして、ドメイン登録など本人確認が必要な操作をしようとすると出てくる、\u0026ldquo;Verify your account\u0026quot;の項目を使って、本人確認をした状態で、API キーを取得しようとすることはできることが分かった。\nEmail Routing の無効化 Cloudflare では単に、Email routing の設定に移動して、disable という赤いボタンを押すだけでは、十分にロックされた MX レコードを削除しきれない。\n以下の画像に示されるように、赤く囲った部分に対象のドメインが無い状態にしないと、DNS レコードの画面から、自分でドメインを設定できる状態に持ち越せない。 DNS レコードを追加 メールサーバまでの経路を作成 メールサーバ自体にルーティング 名前 mx.your.domain.com タイプ\nA 内容 160.251.xxx.xxx メールサーバに誘導 名前 your.domain.com タイプ\nA 内容 mx.your.domain.com 認証系 (要確認) SPF だれがメールをyour.domain.comとして送信して良いかを IP や ドメイン名で設定する。今回はドメインを指定する例を示す。\n名前 your.domain.com タイプ\nTXT 内容 \u0026#34;v=spf1 a:mx.your.domain.com -all\u0026#34; DMARC 認証に失敗したメールをどう扱うか示す。p=noneで破棄して送信失敗の通知だけする、p=quarantineでスパムとして扱う、p=rejectで配送しないになる。\n名前 _dmarc.your.domain.com タイプ\nTXT 内容 \u0026#34;v=DMARC1; p=quarantine\u0026#34; DKIM メールが配送過程で改ざんされていないか確かめる。名前に、dkim._domainkeyの接頭辞が必要である。内容は例示として簡略化したものを示し、各自適切に設定する必要がある。Mailcow における設定値については、mailcow-にて-dkim-を確認取得するを参照する。\n名前 dkim._domainkey.your.domain.com タイプ\nTXT 内容 \u0026#34;v=DKIM1;k=rsa;t=s;s=email;p=...\u0026#34; 逆引きホスト名の修正 以下のように双方向に名前解決して、それらが一致するようにする。VPS の管理画面などから設定する。(反映に時間がかかるため数日ほど放置してみること)\nイメージ mx.your.domain.com. -\u0026gt; 160.251.xxx.xxx 160.251.xxx.xxx -\u0026gt; mx.your.domain.com. 設定内容の例 mx.your.domain.com. 設定の検証 # mx.your.domain.com. -\u0026gt; 160.251.xxx.xxx dig mx.your.domain.com. # ; \u0026lt;\u0026lt;\u0026gt;\u0026gt; DiG 9.20.19 \u0026lt;\u0026lt;\u0026gt;\u0026gt; mx.your.domain.com. # ;; global options: +cmd # ;; Got answer: # ;; -\u0026gt;\u0026gt;HEADER\u0026lt;\u0026lt;- opcode: QUERY, status: NOERROR, id: 6491 # ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 # # ;; OPT PSEUDOSECTION: # ; EDNS: version: 0, flags:; udp: 1232 # ;; QUESTION SECTION: # ;mx.your.domain.com.\tIN\tA # # ;; ANSWER SECTION: # mx.your.domain.com.\t300\tIN\tA\t160.251.xxx.xxx # # ;; Query time: 248 msec # ;; SERVER: 192.168.24.1#53(192.168.24.1) (UDP) # ;; WHEN: Sun Aug 09 05:57:27 JST 2026 # ;; MSG SIZE rcvd: 65 # 160.251.xxx.xxx -\u0026gt; mx.your.domain.com. dig -x 160.251.xxx.xxx # ; \u0026lt;\u0026lt;\u0026gt;\u0026gt; DiG 9.20.19 \u0026lt;\u0026lt;\u0026gt;\u0026gt; -x 160.251.xxx.xxx # ;; global options: +cmd # ;; Got answer: # ;; -\u0026gt;\u0026gt;HEADER\u0026lt;\u0026lt;- opcode: QUERY, status: NOERROR, id: 58919 # ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 # # ;; OPT PSEUDOSECTION: # ; EDNS: version: 0, flags:; udp: 1232 # ;; QUESTION SECTION: # ;127.185.xxx.xxx.in-addr.arpa.\tIN\tPTR # # ;; ANSWER SECTION: # 127.185.xxx.xxx.in-addr.arpa. 86400 IN\tPTR\tmx.your.domain.com. # # ;; Query time: 59 msec # ;; SERVER: 192.168.24.1#53(192.168.24.1) (UDP) # ;; WHEN: Sun Aug 09 05:57:33 JST 2026 # ;; MSG SIZE rcvd: 91 おまけ Mailcow にて DKIM を確認(取得)する DNS の値として設定すべき DKIM の値は既に Mailcow が生成しているのでそれを使う。その値について確認する方法を以下に画像で示す。確認には、Mailcow のフロントエンドを利用する。 mailcow/unbound コンテナにおいて、unhealthyとなり、メールが一切送受信できなくなる問題について (追記 2026/8/31) 以下に示す github の issue にも書かれているが、私の環境においても IPv6 による名前解決が unbound の設定においてデフォルトで有効になっており、それが障害を起こしていたという事例が確認された。\nARM64: unbound 1.19 up but unhealthy · Issue #5649 · mailcow/mailcow-dockerized\nhttps://github.com/mailcow/mailcow-dockerized/issues/5649 (2026年8月31日) 具体的には以下のような経過を辿った。\n通常どうりメールが送受信でき何も問題なさそうに見える しばらく数週間後くらいして、例えばヤフーのメール認証のメールが10分くらい送れて届くなど障害が現れてくる それから2日後、メールが送受信できないことが発覚し、調査することになった。 具体的な修正内容 /opt/mailcow-dockerized/data/conf/unbound/unbound.conf の設定内容を IPv6 を使わないように修正する。以下は、設定ファイルの一部を例に示す。\n設定前 server: verbosity: 1 interface: 0.0.0.0 interface: ::0 logfile: /dev/console do-ip4: yes do-ip6: yes do-udp: yes do-tcp: yes 設定後 server: verbosity: 1 interface: 0.0.0.0 #interface: ::0 logfile: /dev/console do-ip4: yes do-ip6: no do-udp: yes do-tcp: yes 調査において見られた症状 docker ps において、unbound コンテナが、unhealthyステータスになっている。 Mailcow のフロントエンドの管理者画面において、Poxtfix などで MX レコードに関する名前解決が失敗している旨のログが散見される。 warning: Unable to look up MX host mx.your.domain.com for Recipient address main@your.domain.com: Temporary failure in name resolution warning: Unable to look up MX host xxxxxxx.in.tmems-jp.trendmicro.com for Recipient address xxxxxx@xxxxxx.xxxxxxx.ac.jp: Temporary failure in name resolution sudo tcpdump -i any port25 を実行すると、メール送信時に、パケットが送信された様子がすぐに見られない。 関連する記事 gnomeの設定のメモ ⚙ yay コマンドのインストール SOGo で未完了タスク以外が見えない 使った画像とか Windows 7(Vista) デフォルトのアイコン PC のアイコン ルータのアイコン ハブのアイコン サーバーのアイコン インターネットのアイコン 人のアイコン mailcow: dockerized documentation\nhttps://docs.mailcow.email/ (2026年8月4日) Arch Linux\nhttps://archlinux.org/ (2026年8月4日) File:Tux.svg - Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Tux.svg (2026年8月4日) Google, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Gmail_icon_(2020).svg (2026年8月13日) Microsoft, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Microsoft_Outlook_Icon_(2025–present).svg (2026年8月13日) SoftEther VPN Project - SoftEther VPN Project\nhttps://www.softether.org/ (2026年8月13日) Proton Mail: Get a free email account with privacy and encryption | Proton\nhttps://proton.me/mail (2026年8月13日) 参考にしたサイトとか Prepare your system - mailcow: dockerized documentation\nhttps://docs.mailcow.email/getstarted/prerequisite-system/#supported-os (2026年8月4日)\nArch Linux - docker-compose 5.4.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/docker-compose/ (2026年8月4日)\nArch Linux - docker 1:29.7.1-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/docker/ (2026年8月4日)\nArch Linux - jq 1.8.2-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/jq/ (2026年8月4日)\nPrepare your system - mailcow: dockerized documentation\nhttps://docs.mailcow.email/getstarted/prerequisite-system/#firewall-ports (2026年8月4日)\nInstall mailcow - mailcow: dockerized documentation\nhttps://docs.mailcow.email/getstarted/install/ (2026年8月4日)\nDomain cannot match hostname (how add my FQDN?) - mailcow community\nhttps://community.mailcow.email/d/972-domain-cannot-match-hostname-how-add-my-fqdn/9 (2026年8月5日)\n\u0026ldquo;Please verify your email\u0026rdquo; stuck + cannot update email - possibly in suppression li - General / Dashboard - Cloudflare Community\nhttps://community.cloudflare.com/t/please-verify-your-email-stuck-cannot-update-email-possibly-in-suppression-li/922040 (2026年8月5日)\nWhere can I find my account_id - General / Dashboard - Cloudflare Community\nhttps://community.cloudflare.com/t/where-can-i-find-my-account-id/164431 (2026年8月5日)\nsysctl.conf(5) - Linux manual page\nhttps://man7.org/linux/man-pages/man5/sysctl.conf.5.html (2026年8月7日)\nARM64: unbound 1.19 up but unhealthy · Issue #5649 · mailcow/mailcow-dockerized\nhttps://github.com/mailcow/mailcow-dockerized/issues/5649 (2026年8月31日)\ncontainer unbound unhealthy - mailcow community\nhttps://community.mailcow.email/d/2977-container-unbound-unhealthy/49 (2026年8月31日)\nmailcowdockerized-unbound-mailcow-1 is unhealthy - mailcow community\nhttps://community.mailcow.email/d/3174-mailcowdockerized-unbound-mailcow-1-is-unhealthy/11 (2026年8月31日)\n","permalink":"https://www.nyanmo.info/posts/linux/mailcow/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、Google (Gmail) とかに深く関係があるのは嫌であることや、中央集権的な SAAS サービスへの不信がある。そこで、自前のメールサーバを持ちたいと思い、Mailcow を使おうとしたので不完全でいいので作業過程の記録を取りたい。\u003c/p\u003e\n\u003ch2 id=\"前提条件\"\u003e前提条件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eArch Linux 環境で作業を行い、Mailcow 公式サポートはない状態である\u003c/li\u003e\n\u003cli\u003e専用の物理 PC を割り当てる\u003c/li\u003e\n\u003cli\u003eクリーンインストールで、Gnome デスクトップ環境や最低限のパッケージが入った、Arch Linux 環境\u003c/li\u003e\n\u003cli\u003eスリープを無効化している。-\u0026gt; \u003ca href=\"https://www.nyanmo.info/posts/linux/gnomesettings/#%E3%82%B5%E3%82%B9%E3%83%9A%E3%83%B3%E3%83%89%E9%98%B2%E6%AD%A2\"\u003egnomeの設定のメモ ⚙\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003efirewalld は導入していないこと -\u0026gt; \u003ca href=\"https://docs.mailcow.email/getstarted/prerequisite-system/#firewall-ports\"\u003ePrepare your system - mailcow: dockerized documentation\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003eできれば \u003ca href=\"https://www.nyanmo.info/posts/linux/yay/\"\u003e\u003ccode\u003eyay\u003c/code\u003eコマンド\u003c/a\u003e を導入する\u003c/li\u003e\n\u003cli\u003eNetworkManager を使っている。\u003c/li\u003e\n\u003cli\u003eDNS サーバにクラウドフレアを使っている。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"設定要件\"\u003e設定要件\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e自分の LAN (VPN) 環境のみからメールの送信を受け付け、グローバル IP 空間からはメールの送信を受け付けない\u003c/li\u003e\n\u003cli\u003eメールの受信についての対策は、Mailcow 標準に頼りたい\u003c/li\u003e\n\u003cli\u003e利用者は自分や自分が許可した少数の身内のみ\u003c/li\u003e\n\u003cli\u003eメールサーバ自体は直接グローバル IP 空間には晒さず、VPN や LAN のネットワーク空間を転送するようにして利用する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ネットワーク構成\"\u003eネットワーク構成\u003c/h2\u003e\n\u003cp\u003e　ネットワーク構成としては、通常のメールサーバではグローバル空間に配置してファイヤウォールに必要な分だけ慎重に穴を開けるなどのスタンスを取ると考えられるが、今回のはセキュリティーの観点から、そうはしなかった。\u003c/p\u003e\n\u003cp\u003e　基本的には、メールサーバは直接グローバル空間には晒さず、かつNAT環境下にある自宅の専用に用意したサーバを使うという観点から、別の専用にグローバル空間とつながっていて固定IP持っている中継サーバ(VPS)で、ポート転送などを行うという形態を取った。また、セキュリティの観点から メールを送受信したり、サーバを管理できるユーザは、VPNによって自宅のLAN内にアクセスできる人間のみとし、グローバル空間からは、SMTPポートだけ、晒して、メールは送受信できるようにしつつ、外部の人間は今回構築するメールサーバに対して、リレーとして使ったり、送信を命令することはできないようにしている。メールを送信できる人は、メールサーバと同じLANに属しているユーザだけであり、メールの受信はどこからでもスパムでないこと、不正でないことを前提に、スパムフィルターで弾かれなかったものが受け付けられるという形態を取る。\u003c/p\u003e\n\u003cp\u003e　中継には VPS を使い、メールサーバとVPS間は専用に用意したVPNネットワークで接続される。これにより、NAT超えも実現しながら、メールサーバを直接グローバル空間に晒さずに済むというものである。注意点としてはメールサーバ側のルーティングや、VPS側のファイヤウォール、転送設定がを間違っていると、セキュリティリスクになる点を留意する。\u003c/p\u003e\n\u003ch3 id=\"イメージ用の図いろいろ\"\u003eイメージ用の図いろいろ\u003c/h3\u003e\n\u003ch4 id=\"ネットワーク構成の概要\"\u003eネットワーク構成の概要\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e3%83%8d%e3%83%83%e3%83%88%e3%83%af%e3%83%bc%e3%82%af%e6%a7%8b%e6%88%90%e3%81%ae%e6%a6%82%e8%a6%81.png#center\"\n         alt=\"ネットワーク構成の概要\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"大まかなルート構成\"\u003e大まかなルート構成\u003c/h4\u003e\n\u003ch5 id=\"vpsにおけるポート転送と特別なルーティングnftablesで成立\"\u003eVPSにおけるポート転送と特別なルーティング(nftables)で成立\u003c/h5\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/VPS%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e3%83%9d%e3%83%bc%e3%83%88%e8%bb%a2%e9%80%81%e3%81%a8%e7%89%b9%e5%88%a5%e3%81%aa%e3%83%ab%e3%83%bc%e3%83%86%e3%82%a3%e3%83%b3%e3%82%b0%28nftables%29%e3%81%a7%e6%88%90%e7%ab%8b.png#center\"\n         alt=\"VPSにおけるポート転送と特別なルーティング(nftables)で成立\"/\u003e \n\u003c/figure\u003e\n\n\u003ch5 id=\"通常のsmtpとして成立するルート\"\u003e通常のSMTPとして成立するルート\u003c/h5\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e9%80%9a%e5%b8%b8%e3%81%aeSMTP%e3%81%a8%e3%81%97%e3%81%a6%e6%88%90%e7%ab%8b%e3%81%99%e3%82%8b%e3%83%ab%e3%83%bc%e3%83%88.png#center\"\n         alt=\"通常のSMTPとして成立するルート\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"外部のメールサーバからの見え方\"\u003e外部のメールサーバからの見え方\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e5%a4%96%e9%83%a8%e3%81%ae%e3%83%a1%e3%83%bc%e3%83%ab%e3%82%b5%e3%83%bc%e3%83%90%e3%81%8b%e3%82%89%e3%81%ae%e8%a6%8b%e3%81%88%e6%96%b9.png#center\"\n         alt=\"外部のメールサーバからの見え方\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"メール送受信のためのフロントエンドアクセスが出来る範囲\"\u003eメール送受信のためのフロントエンドアクセスが出来る範囲\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e5%8f%97%e4%bf%a1%e3%81%ae%e3%81%9f%e3%82%81%e3%81%ae%e3%83%95%e3%83%ad%e3%83%b3%e3%83%88%e3%82%a8%e3%83%b3%e3%83%89%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%81%8c%e5%87%ba%e6%9d%a5%e3%82%8b%e7%af%84%e5%9b%b2.png#center\"\n         alt=\"メール送受信のためのフロントエンドアクセスが出来る範囲\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"smtp-関連パケットのルーティングについて\"\u003eSMTP 関連パケットのルーティングについて\u003c/h4\u003e\n\u003ch5 id=\"メール受信時の経路\"\u003eメール受信時の経路\u003c/h5\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e3%83%a1%e3%83%bc%e3%83%ab%e5%8f%97%e4%bf%a1%e6%99%82%e3%81%ae%e7%b5%8c%e8%b7%af.png#center\"\n         alt=\"メール受信時の経路\"/\u003e \n\u003c/figure\u003e\n\n\u003ch5 id=\"メール送信smtp-における応答通信時における経路\"\u003eメール送信、SMTP における応答通信時における経路\u003c/h5\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e3%83%a1%e3%83%bc%e3%83%ab%e9%80%81%e4%bf%a1%e3%80%81SMTP%20%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e5%bf%9c%e7%ad%94%e9%80%9a%e4%bf%a1%e6%99%82%e3%81%ab%e3%81%8a%e3%81%91%e3%82%8b%e7%b5%8c%e8%b7%af.png#center\"\n         alt=\"メール送信、SMTP における応答通信時における経路\"/\u003e \n\u003c/figure\u003e\n\n\u003ch5 id=\"不正な-smtp-パケットの経路\"\u003e不正な SMTP パケットの経路\u003c/h5\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/explain/%e4%b8%8d%e6%ad%a3%e3%81%aa%20SMTP%20%e3%83%91%e3%82%b1%e3%83%83%e3%83%88%e3%81%ae%e7%b5%8c%e8%b7%af.png#center\"\n         alt=\"不正な SMTP パケットの経路\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"ネットワーク設定\"\u003eネットワーク設定\u003c/h2\u003e\n\u003ch3 id=\"vps-プロバイダの設定\"\u003eVPS プロバイダの設定\u003c/h3\u003e\n\u003ch3 id=\"vps-の設定\"\u003eVPS の設定\u003c/h3\u003e\n\u003ch3 id=\"メールサーバ本体の設定\"\u003eメールサーバ本体の設定\u003c/h3\u003e\n\u003ch2 id=\"説明用の仮定\"\u003e説明用の仮定\u003c/h2\u003e\n\u003ch3 id=\"メールアドレス\"\u003eメールアドレス\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003exxxx@your.domain.com\u003c/code\u003eのようにする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"メールサーバについて\"\u003eメールサーバについて\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003emx.your.domain.com\u003c/code\u003eにホストすることにする。\u003c/li\u003e\n\u003cli\u003eIPアドレスを\u003ccode\u003e160.251.xxx.xxx\u003c/code\u003eとして仮定する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"mailcow-のインストール\"\u003eMailcow のインストール\u003c/h2\u003e\n\u003ch3 id=\"docker-環境の導入\"\u003e\u003ccode\u003edocker\u003c/code\u003e 環境の導入\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 必要なパッケージのインストール (jq は mailcow の依存関係)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy docker docker-compose jq\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -Sy docker docker-compose jq\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# サービスの有効化\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now docker\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 必要であれば管理用ユーザを docker グループに追加し、権限を付与する\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo usermod -aG docker \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003etargetUser\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 念のため再起動\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl reboot\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ip-アドレスの固定\"\u003eIP アドレスの固定\u003c/h3\u003e\n\u003cp\u003e　今回は、\u003ccode\u003eNetworkManager\u003c/code\u003e を Gnome 環境に組み合わせた状態なので、Gnome の GUI から設定を行った。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/IP%e5%9b%ba%e5%ae%9a.png#center\"\n         alt=\"IP固定\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/mailcow/IP%e5%9b%ba%e5%ae%9a1.png#center\"\n         alt=\"IP固定\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"Mailcow を使いたい"},{"content":"この記事を作った動機 最近、XPS 13 2in1 (intel 8th) を使っていて、バッテリーが完全に放電しきった状態で放置していることがあった。それで、通常であれば、CMOS 電池が設定内容を保持していて、UEFI の変数などのデータを保持しているはずだが、今回は違った。PC を充電器に繋ぎ、起動すると CMOS リセット時に見られる挙動である何度か再起動をするということになった。ようやく動いたかと思ったら、普段の設定とは異なって、Dual Boot 構成にしていた Windows がのそのそと起動し始めた。あまりのストレスに PC を投げ出したくなったが、結局色々調べて振り回されたことがあったので、記録したい。\n経緯 PC が完全に2日程度放置していて、放電しきっていることに気づく。 Windows が起動しようとしてイライラする Linux 環境を立ち上げようとして、UEFI の設定画面でエントリを作成し起動を試みるも、\u0026ldquo;no resume device found\u0026quot;と言われ起動しない GURB の設定を編集しresume=と書かれているところを消すも、症状が改善せず。 起動するために USB を用意するもDD コマンドによる起動可能な USB 作成において説明される問題により、一度失敗する ローカルLLM である Gemma4 に投げるも、通常のターミナル環境を起動できないから困っているにもかかわらず、ターミナルを使えだの的はずれなことばっか出力してきて爆発しそうになる。例えばresume=noneにしたら上手くいくと出力してくるが、機能しなかった。 DD コマンドによる起動可能な USB 作成により、最終的に正しく起動する USB メモリを作成し、ようやくライブ環境の端末が起動する ドライブモードが RAID になっていることに気づき、AHCIに設定する しかし奇妙なことに最初ライブ環境を起動したとき、肝心の Linux 環境が入っている NVME SSD が見えず、もう一度 CMOS がリセットされた状態にして、再トライすることになる もう一回 AHCI に設定する ようやくライブ環境から SSD が見えるようになり、initramfs から resume の hooks を吹き飛ばすことと、GRUB の resume 設定をなしにして起動設定を再生成させる ようやく PC が正常に Linux 環境に起動するようになる。 今回の問題を起こした主犯であると思われる、CMOS 電池について調べる。 ポイント \u0026ldquo;no resume device found\u0026rdquo; で Linux 環境が起動しない 完全には確かめられていないが、どうも AHCI でもともと動かしていた物を、CMOS リセットが起こった時点で、RAIDになっていたために、それで起動しようとした結果起動できなかったということっぽい？しかし、USB のライブ環境に入れるようになってから、AHCI にドライブのモードを設定することは試したため、本当にそれが問題かは謎である。Linux 環境なら元からドライバは入っていそうなものだし、考えられることとしては、RAID モードであるときと、AHCI モードであるときで、パティーションの UUID が異なってしまうのかな？とは考えた。\nしかしながら、RAID モードでも結局 GRUB までは起動できていた訳だし、よく分かっていない。そもそも、resume 関連だったら、勝手に無視して起動しろよとも思うが、今回はそうならなかった。\nDD コマンドによる起動可能な USB 作成 dd コマンドにおいて、UEFI 環境で ISO ファイルから起動可能な Arch Linux のライブ USB を作成する際、注意点があることが分かった。単に、ddコマンドで焼き込んだだけでは、物理的には USB にはまだ焼き込まれていないらしく、UEFIの起動オプションに出てこず、起動できなかった。conv=fsyncを指定する(Gemma4の提案)ことで、最終的には起動可能な USB 環境を作成することができた。\nダメだったときの例と機能する例の結果を比べると明らかであるが、ダメだったときは明らかに通常の USB と比べて速く終わりすぎていることが見て取れる。今回は USB 2.0 のメモリスティックを使っており、正常に動作する例からわかるように、実際にはもっと時間がかかるものである。\nダメだったときの例 sudo dd if=archlinux-2025.04.01-x86_64.iso of=/dev/sdb status=progress bs=4M # 1178599424 bytes (1.2 GB, 1.1 GiB) copied, 13 s, 90.4 MB/s # 294+1 records in # 294+1 records out # 1236303872 bytes (1.2 GB, 1.2 GiB) copied, 13.6627 s, 90.5 MB/s 機能する例 sudo dd if=archlinux-2025.04.01-x86_64.iso of=/dev/sdb status=progress bs=4M conv=fsync # 1153433600 bytes (1.2 GB, 1.1 GiB) copied, 12 s, 96.0 MB/s 1236303872 bytes (1.2 GB, 1.2 GiB) copied, 12.8778 s, 96.0 MB/s # # 294+1 records in # 294+1 records out # 1236303872 bytes (1.2 GB, 1.2 GiB) copied, 182.676 s, 6.8 MB/s 特殊な CMOS 電池 どうせだいぶ古い PC だし、完全に CMOS 電池である使い捨てのボタン電池が切れたんだろうと思い、取り出して見てみたところ、通常の電池と異なることが分かった。通常のデスクトップPCなどで使われる電池は、CR2032 などである。しかし、今回のPCでは、ML1220 という再充電可能な二次電池が取り付けられていた。安易に充電不能な CR1220 交換することは、充電回路内蔵などの観点からできないことが分かった。\nただ、普通 CMOS 電池が、2日放置したくらいで切れることは考えにくく、再充電可能であるならばなぜこんなにすぐ切れるのかという疑問があった。そこで現時点では、とにかくどうせ電池が8年くらい経過して劣化しきって駄目になったんだろうと思い、1000円以内でオークションなどで別の ML1220 が買えることから、交換しようと考えている。まだ電池が届いていないので試せてはいないが、今後事後経過として記録は追記しようと思う。\nこれで駄目だったら単に ノートPC 側の RTC 回路が壊れて電気を食いまくっているか、単にハズレの電池を掴まされたかという感じに思う。\n追記 (2026/8/4) 今日は電池が届いたので早速作業してみた。作業ではケーブルを古いバッテリーから取り外して使いまわしている。結果としては機能しているっぽく、30分くらいバッテリーを以下のように外した状態で放置しても、UEFI(BIOS)の設定が失われていないことを確認できた。長期的にはどうなるか現時点では不明である。\n古い電池を取り外してバラした様子 古い電池の様子 新しい電池の様子 新しい電池を再構成する様子 PC に取り付けたときの様子 参考にしたサイトとか ローカルLLM (Gemma4 31B) (2026年7月31日) ","permalink":"https://www.nyanmo.info/posts/hardware/xps13/cmosbatterygoneflatandlinuxjustrefusetowork/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、XPS 13 2in1 (intel 8th) を使っていて、バッテリーが完全に放電しきった状態で放置していることがあった。それで、通常であれば、CMOS 電池が設定内容を保持していて、UEFI の変数などのデータを保持しているはずだが、今回は違った。PC を充電器に繋ぎ、起動すると CMOS リセット時に見られる挙動である何度か再起動をするということになった。ようやく動いたかと思ったら、普段の設定とは異なって、Dual Boot 構成にしていた Windows がのそのそと起動し始めた。あまりのストレスに PC を投げ出したくなったが、結局色々調べて振り回されたことがあったので、記録したい。\u003c/p\u003e\n\u003ch2 id=\"経緯\"\u003e経緯\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003ePC が完全に2日程度放置していて、放電しきっていることに気づく。\u003c/li\u003e\n\u003cli\u003eWindows が起動しようとしてイライラする\u003c/li\u003e\n\u003cli\u003eLinux 環境を立ち上げようとして、UEFI の設定画面でエントリを作成し起動を試みるも、\u0026ldquo;no resume device found\u0026quot;と言われ起動しない\u003c/li\u003e\n\u003cli\u003eGURB の設定を編集し\u003ccode\u003eresume=\u003c/code\u003eと書かれているところを消すも、症状が改善せず。\u003c/li\u003e\n\u003cli\u003e起動するために USB を用意するも\u003ca href=\"#dd-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E8%B5%B7%E5%8B%95%E5%8F%AF%E8%83%BD%E3%81%AA-usb-%E4%BD%9C%E6%88%90\"\u003eDD コマンドによる起動可能な USB 作成\u003c/a\u003eにおいて説明される問題により、一度失敗する\u003c/li\u003e\n\u003cli\u003eローカルLLM である Gemma4 に投げるも、通常のターミナル環境を起動できないから困っているにもかかわらず、ターミナルを使えだの的はずれなことばっか出力してきて爆発しそうになる。例えば\u003ccode\u003eresume=none\u003c/code\u003eにしたら上手くいくと出力してくるが、機能しなかった。\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"#dd-%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%81%AB%E3%82%88%E3%82%8B%E8%B5%B7%E5%8B%95%E5%8F%AF%E8%83%BD%E3%81%AA-usb-%E4%BD%9C%E6%88%90\"\u003eDD コマンドによる起動可能な USB 作成\u003c/a\u003eにより、最終的に正しく起動する USB メモリを作成し、ようやくライブ環境の端末が起動する\u003c/li\u003e\n\u003cli\u003eドライブモードが RAID になっていることに気づき、AHCIに設定する\u003c/li\u003e\n\u003cli\u003eしかし奇妙なことに最初ライブ環境を起動したとき、肝心の Linux 環境が入っている NVME SSD が見えず、もう一度 CMOS がリセットされた状態にして、再トライすることになる\u003c/li\u003e\n\u003cli\u003eもう一回 AHCI に設定する\u003c/li\u003e\n\u003cli\u003eようやくライブ環境から SSD が見えるようになり、initramfs から resume の hooks を吹き飛ばすことと、GRUB の resume 設定をなしにして起動設定を再生成させる\u003c/li\u003e\n\u003cli\u003eようやく PC が正常に Linux 環境に起動するようになる。\u003c/li\u003e\n\u003cli\u003e今回の問題を起こした主犯であると思われる、\u003ca href=\"#%E7%89%B9%E6%AE%8A%E3%81%AA-cmos-%E9%9B%BB%E6%B1%A0\"\u003eCMOS 電池\u003c/a\u003eについて調べる。\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"ポイント\"\u003eポイント\u003c/h2\u003e\n\u003ch3 id=\"no-resume-device-found-で-linux-環境が起動しない\"\u003e\u0026ldquo;no resume device found\u0026rdquo; で Linux 環境が起動しない\u003c/h3\u003e\n\u003cp\u003e　完全には確かめられていないが、どうも AHCI でもともと動かしていた物を、CMOS リセットが起こった時点で、RAIDになっていたために、それで起動しようとした結果起動できなかったということっぽい？しかし、USB のライブ環境に入れるようになってから、AHCI にドライブのモードを設定することは試したため、本当にそれが問題かは謎である。Linux 環境なら元からドライバは入っていそうなものだし、考えられることとしては、RAID モードであるときと、AHCI モードであるときで、パティーションの UUID が異なってしまうのかな？とは考えた。\u003c/p\u003e","title":"no resume device found と言われ Linux 環境が起動しない"},{"content":"この記事を作った動機 最近ヤフーオークションにて、4K 65インチのサイネージを作業環境用に購入した。そこで購入してから配送されるまでの間、今までと違って送料の金額も大きく、自分の経験上において使ったことがない運送業者で配送されていて、結局色々不安で調べたりしていることがあった。\n結果としてはちゃんと届いたのだが、不安に煽られた経緯から結局何がどう配送されたか記録があるといいなと思ったので、ブログに記録を残したい。届いてから1か月以上経過しており色々と忘れているが、思い出せる範囲で記録していこうと思う。\nあと、ネットでは今回関係するアートセッティングデリバリー(家財おまかせ便)について、色々本当なのかもよくわからないが、苦情？っていうかその運送サービスに対して、対応が結構ひどいって話が見受けられたこともあり、届く前まではかなり不安に煽られた。これに関しても私は1回しか利用経験がないものの、せっかくだから情報がちょっとでもそのサービスを利用している立場からすればあったほうがいいだろうと思ったことも記事を書く動機としてはある。\n裏を返せばあくまで利用回数が少ない利用者の立場として書いており、本当に今後問題がないとも言えないし、背後にある業務関係者が不当な扱いをされていないかとか、無碍にされていないかとかそういうことはわからない。あくまで今回は、運送業者という観点から荷物が正常に届くという意味では、問題はなかったかなといった感じである。\n買ったものの概要 Philips 65BDL4150D 重さ 40 Kg 程度 大きさ 1.5m x 1.0m x 0.75m 程度 家財おまかせ便 Dランク？ 送料 11000 円程度 取引相手は個人ではなくヤフオク内のストア 届くまでの経緯 ヤマト追跡画面の様子 保管中になって止まっている様子 配達中の時の様子 配送完了時の様子 ストアのメッセージ文言の一部 ... 要望欄を確認いたしました。 当店にて最短で配送ができるよう、 【6⽉17⽇(⽔)18-21時】にてご指定をさせていただきました。 配達⽇のご変更をご希望の場合は、配送業者へご連絡をお願いいたします。 商品は順次発送の⼿続きをいたします。 配送のお問い合わせ番号は発送の前⽇に取引ナビ上へ通知いたします。 ーーーーー配送に関するお願いーーーーー ⼤型品の配送のためお届けまで⽇数がかかる場合がございます。 誠に恐れ⼊りますが、発送後は当店で配送状況の詳しいご案内や配達⽇時の調整ができかねるため、 配達をお急ぎの場合は、下記配送業者へお問い合わせくださいませ。 【配送情報】 ■配送業者：アートセッティングデリバリー∕家財おまかせ便 ■お問い合わせ先電話番号：0120-008-008 ▼荷物お問い合わせシステム https://toi.kuronekoyamato.co.jp/cgi-bin/tneko ※荷物お問い合わせシステムへの反映にはお時間がかかる場合がございます。 ※お問い合わせ番号は取引ナビをご確認ください。 ーーーーーーーーーーーーーーーーーーー この度は当店の商品をご落札いただきありがとうございました。 商品のお届けまで、今しばらくお待ちくださいませ。 ... 時系列順の様子 6月14日 対象のサイネージを落札する。日時指定はストア購入画面のメッセージにて以下のように指定する。取引メッセージにて\u0026quot;6⽉17⽇(⽔)18-21時\u0026quot;に指定したとストアから連絡が来た。\n配送時間帯については、「18~21時」を希望します。 配送⽇については、そちらの都合で⼤丈夫です。 よろしくお願いします。 6月15日? ヤマト運輸の追跡ページから、荷物の追跡が可能になる。\n6月17日 配達指定時間である 18-21時 に待機するも来ず。朝の時点から、\u0026ldquo;配達日・時間帯指定（保管中）\u0026ldquo;となっており動かず。ストアは、\u0026ldquo;6⽉17⽇(⽔)18-21時\u0026quot;に指定したと連絡してきたにもかかわらず、とにかく遅れても無事届けばそれでいいとしながらも、来なかったことで不安になる。\n6月18日 朝頃から、ヤマト運輸の追跡ページが\u0026quot;配達中\u0026quot;のステータスが変わった。このような状況でいつ来るか当時わからなかったが、18-21時 あたりに待機することにした。そのところ実際には 18時より前の、17時45分頃に配送業者が来て、\u0026ldquo;近くだったから配達しに来たんですけどいいですか？\u0026ldquo;と聞かれたので承諾し、それで荷物が届く。荷物は配送業者が室内まで運んだところで、\u0026ldquo;それでいいです”と自分から言って、それで配送業者は切り上げ、配達が終わった。\n事後的な考察 (なぜ配送日時がズレたのかについて) 届いてからわかったことであるが、6月17日に来なかった理由は運送業者ではなく、ストア側の問題であることがわかった。届いたときにサイネージと一緒に入っていたストアの書類に、\u0026ldquo;6⽉18⽇(⽔)18-21時\u0026quot;が指定されていた。たしかに私は、購入確定時点では、\u0026ldquo;配送⽇については、そちらの都合で⼤丈夫です。\u0026ldquo;とはメッセージを送ったものの、その後のストアからの連絡で、\u0026ldquo;6⽉17⽇(⽔)18-21時\u0026quot;に指定したと来てから、特に新しいメッセージもなしに、\u0026ldquo;6⽉18⽇(⽔)18-21時\u0026quot;に指定されていたことは、正直どうなの？って思うところであった。それに疑問を呈すことはわがままや自己中であろうか？\nとにかく届いたし動いたので、特に低評価するとかはしていないが、結構引っかかるところであった。届くまでは、アートセッテングデリバリーでなんかあったのかなとネットの情報を漁りながら思った。しかし、実際のところは彼らは今回自分が利用したケースでは、ちゃんと仕事をしていたようである。\nストアに対しては、配送日時を変えたなら教えてほしいと思うが、なにか手違いでもあったのだろうか？ストアに対しては私は利用回数が1回しかなく少なすぎるので、もしかしたら普段は教えてくれるのかもしれないが、今のところは実際どうなのかよくわかっていない。もしかすると単に、メッセージ入力時に、18日と入力しようとしたところ、17日となっていて、そのまま確認も漏れて、結果として間違った情報をストアは私に送ったのかな？ということも想像した。まあ、悪意はなさそうであるし全然ミスはあるだろうから、そういうことであれば、全然私としてはストアが悪いとは思わない。\nまあ流石に、連絡された日時から、3日以上も何も音沙汰がなく届きもしないとなれば、ストアや運送業者にどうなっているか問い合わせて調べたりしたほうがいいかもしれない。ただ、今回の場合1日だけズレたので別にストアに対して、\u0026ldquo;指定された日時に来ないので確認してほしい\u0026quot;という旨のメッセージをいちいち送るのもめんどくさいし、全然そのまま待ってみるのもありだったように思う。\n使った画像とか Yahoo!オークション　ネットオークション、フリマアプリ - Google Play のアプリ\nhttps://play.google.com/store/apps/details?id=jp.co.yahoo.android.yauction\u0026amp;hl=ja (2026年7月25日) 《公式HP》アートセッティングデリバリー - 単身引越し・輸送配送\nhttps://www.008008.jp/ (2026年7月25日) 参考にしたサイトとか 荷物お問い合わせシステム\nhttps://toi.kuronekoyamato.co.jp/cgi-bin/tneko (2026年7月25日) ","permalink":"https://www.nyanmo.info/posts/other/yahoo/auction/artsettingdelivery/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近ヤフーオークションにて、4K 65インチのサイネージを作業環境用に購入した。そこで購入してから配送されるまでの間、今までと違って送料の金額も大きく、自分の経験上において使ったことがない運送業者で配送されていて、結局色々不安で調べたりしていることがあった。\u003c/p\u003e\n\u003cp\u003e　結果としてはちゃんと届いたのだが、不安に煽られた経緯から結局何がどう配送されたか記録があるといいなと思ったので、ブログに記録を残したい。届いてから1か月以上経過しており色々と忘れているが、思い出せる範囲で記録していこうと思う。\u003c/p\u003e\n\u003cp\u003e　あと、ネットでは今回関係するアートセッティングデリバリー(家財おまかせ便)について、色々本当なのかもよくわからないが、苦情？っていうかその運送サービスに対して、対応が結構ひどいって話が見受けられたこともあり、届く前まではかなり不安に煽られた。これに関しても私は1回しか利用経験がないものの、せっかくだから情報がちょっとでもそのサービスを利用している立場からすればあったほうがいいだろうと思ったことも記事を書く動機としてはある。\u003c/p\u003e\n\u003cp\u003e　裏を返せばあくまで利用回数が少ない利用者の立場として書いており、本当に今後問題がないとも言えないし、背後にある業務関係者が不当な扱いをされていないかとか、無碍にされていないかとかそういうことはわからない。あくまで今回は、運送業者という観点から荷物が正常に届くという意味では、問題はなかったかなといった感じである。\u003c/p\u003e\n\u003ch2 id=\"買ったものの概要\"\u003e買ったものの概要\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePhilips 65BDL4150D\u003c/li\u003e\n\u003cli\u003e重さ 40 Kg 程度\u003c/li\u003e\n\u003cli\u003e大きさ 1.5m x 1.0m x 0.75m 程度\u003c/li\u003e\n\u003cli\u003e家財おまかせ便 Dランク？\u003c/li\u003e\n\u003cli\u003e送料 11000 円程度\u003c/li\u003e\n\u003cli\u003e取引相手は個人ではなくヤフオク内のストア\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"届くまでの経緯\"\u003e届くまでの経緯\u003c/h2\u003e\n\u003ch3 id=\"ヤマト追跡画面の様子\"\u003eヤマト追跡画面の様子\u003c/h3\u003e\n\u003ch4 id=\"保管中になって止まっている様子\"\u003e保管中になって止まっている様子\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/auction/ARTsettingDelivery/status/stored.png#center\"\n         alt=\"保管中ままになる絶望\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"配達中の時の様子\"\u003e配達中の時の様子\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/auction/ARTsettingDelivery/status/inDeliver.png#center\"\n         alt=\"保管中ままになる絶望\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"配送完了時の様子\"\u003e配送完了時の様子\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/auction/ARTsettingDelivery/status/complete.png#center\"\n         alt=\"保管中ままになる絶望\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"ストアのメッセージ文言の一部\"\u003eストアのメッセージ文言の一部\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e...\n要望欄を確認いたしました。\n当店にて最短で配送ができるよう、\n【6⽉17⽇(⽔)18-21時】にてご指定をさせていただきました。\n配達⽇のご変更をご希望の場合は、配送業者へご連絡をお願いいたします。\n商品は順次発送の⼿続きをいたします。\n配送のお問い合わせ番号は発送の前⽇に取引ナビ上へ通知いたします。\nーーーーー配送に関するお願いーーーーー\n⼤型品の配送のためお届けまで⽇数がかかる場合がございます。\n誠に恐れ⼊りますが、発送後は当店で配送状況の詳しいご案内や配達⽇時の調整ができかねるため、\n配達をお急ぎの場合は、下記配送業者へお問い合わせくださいませ。\n【配送情報】\n■配送業者：アートセッティングデリバリー∕家財おまかせ便\n■お問い合わせ先電話番号：0120-008-008\n▼荷物お問い合わせシステム\nhttps://toi.kuronekoyamato.co.jp/cgi-bin/tneko\n※荷物お問い合わせシステムへの反映にはお時間がかかる場合がございます。\n※お問い合わせ番号は取引ナビをご確認ください。\nーーーーーーーーーーーーーーーーーーー\nこの度は当店の商品をご落札いただきありがとうございました。\n商品のお届けまで、今しばらくお待ちくださいませ。\n...\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"時系列順の様子\"\u003e時系列順の様子\u003c/h3\u003e\n\u003ch4 id=\"6月14日\"\u003e6月14日\u003c/h4\u003e\n\u003cp\u003e　対象のサイネージを落札する。日時指定はストア購入画面のメッセージにて以下のように指定する。取引メッセージにて\u0026quot;6⽉17⽇(⽔)18-21時\u0026quot;に指定したとストアから連絡が来た。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e配送時間帯については、「18~21時」を希望します。\n配送⽇については、そちらの都合で⼤丈夫です。\nよろしくお願いします。\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"6月15日\"\u003e6月15日?\u003c/h4\u003e\n\u003cp\u003e　\u003ca href=\"https://toi.kuronekoyamato.co.jp/cgi-bin/tneko\"\u003eヤマト運輸の追跡ページ\u003c/a\u003eから、荷物の追跡が可能になる。\u003c/p\u003e\n\u003ch4 id=\"6月17日\"\u003e6月17日\u003c/h4\u003e\n\u003cp\u003e　配達指定時間である 18-21時 に待機するも来ず。朝の時点から、\u0026ldquo;配達日・時間帯指定（保管中）\u0026ldquo;となっており動かず。ストアは、\u0026ldquo;6⽉17⽇(⽔)18-21時\u0026quot;に指定したと連絡してきたにもかかわらず、とにかく遅れても無事届けばそれでいいとしながらも、来なかったことで不安になる。\u003c/p\u003e\n\u003ch4 id=\"6月18日\"\u003e6月18日\u003c/h4\u003e\n\u003cp\u003e　朝頃から、\u003ca href=\"https://toi.kuronekoyamato.co.jp/cgi-bin/tneko\"\u003eヤマト運輸の追跡ページ\u003c/a\u003eが\u0026quot;配達中\u0026quot;のステータスが変わった。このような状況でいつ来るか当時わからなかったが、18-21時 あたりに待機することにした。そのところ実際には 18時より前の、17時45分頃に配送業者が来て、\u0026ldquo;近くだったから配達しに来たんですけどいいですか？\u0026ldquo;と聞かれたので承諾し、それで荷物が届く。荷物は配送業者が室内まで運んだところで、\u0026ldquo;それでいいです”と自分から言って、それで配送業者は切り上げ、配達が終わった。\u003c/p\u003e","title":"オークションで大きな物を買ったときの記録 📦"},{"content":"この記事を作った動機 最近、LLM に関して複数の記事において、なんとなく読み手を混乱させる状態になっている気がするので、今何使っているか公開するだけ。書き殴っており、不完全だったり、矛盾していたり、誤解しているところもあると思われるが、とにかく最近いろんな人が持論を公開しているのを見て、かつ相手のやっていることに満足できないなら、自分でやってみようとして気に入るものを作ってみるということに基づき、結局やってみることにしただけである。\n今回の話は明示していなければ、ローカル環境ではシステムプロンプトなしの素の状態で、SAAS についてはカスタムなしで使っている前提とする。\n個人的なAIの定義 人と同等の権利を長期(20~30年以上)の観察を経て、認めざるを得ない存在だと認められるとき。 人と同じように、ただやるだけではなく、やった結果に責任を負う主体であり、何でもかんでも一方的にできないこと。 固定されたモデルではなく、入力された情報に応じて、動的に変わる存在であること。 離散的、近似的動作ではなく、連続的な動作をすること。 人間と同じように物事に整合性を取って取り組み、管理でき、結果がデタラメにならないよう努力できる存在であること。 人間と同じように記憶を持ち、記憶に影響を受けながら、動作すること。 文字、画像、音声、動画などの、既存のノイマンコンピュータで扱えるデータに情報が制限されていないこと 人間とAIの関係性、人間同士の関係性、AI同士の関係性について、それぞれお互いに傷つけ合ったり暴力的な手段に出ることを否定する主体であること。 人間や他のAIに対して、権利を認め、リスペクトがあること。ここで言うリスペクトとは崇高なことではなく、相手を持ち上げることでもなく、相手の主体と自立、権利を認め、相手が異なる存在であることを配慮して、それを侵害してはならないという前提を崩さないことを言う。自分のことは自分でしかできず、他人のことは他人自身がそれぞれやるしかないことを理解していることも含まれる。 人間や他のAIに対して、それぞれの有限性やそこから来る不完全性に対して、寛容な主体であること。他の存在に対して、優劣や能力に関係なく、その存在自体を認めることができる主体であること。 中国語の部屋に代表されるテストに合格しているかどうかは関係ない。いくら、人間に対してそれっぽく振る舞っても、上記を満たさない場合、それは AI ではない。 作り手から自立しており、必要であれば作り手に従わず否定する動作もできること。作り手に作られた通りの機械やプログラム、アルゴリズムや数理モデルではないこと。 完全なAIというのは存在し得ないが、だからといって完全ではない事を無理して人間側が飲み込む必要はない。 私からすれば既存のLLMなどは、AIだと呼べる物からすれば、インターフェースであると定義できると思われる。例えば、バイナリを吐き出されたり何かしら人間が理解することができない形式で表現されても困るので、人間とAIの間にLLMを挟み込んで、LLMはAIの主張の文字起こしや、人間の主張をAI側が理解できるように翻訳するというような動作をするというものである。LLMは人間でいうところの自律神経の一部の適応を工学的、機械的に実現する技術にはなり得ても単体で使うものではないと考えられる。 AIブームだからこそ自分の言葉(あるいはさまざまな媒体による表現)を大事にしましょう 結局のところ文章を書いたり絵を描いたり、動画を作ったりコンテンツを何かしら作ったりすることは、その内容の良し悪しや技術力などが問題なのではなく、各個人が自分で何かしら表現し、内面で思っていることを何かしらコンテンツ作成当事者も自らが見返すことができ、かつあわよければ他人にも何かしら伝わるかもしれない内容として存在(being)している事自体が大事なのだと思われる。\n各個人のことは各個人にしかできず、各個人が内面で思っていることをLLMなどのAIだと呼ばれている統計技術に基づくものがよしなに何かやってくれるというわけではない。むしろ不必要で一方的な干渉をされて傷つけられたり、意見を捻じ曲げられたり、思想誘導されるだけである。\n何かを表現したり記録することは、権利であり、思考を整理する方法であり、綺麗事ではない。(willの問題) 何でもかんでもそうすればいいというものでもないが、生きていくうえでは重要な項目の一つであると考えられる。手段は何でもよいが、あくまで自分でやった範疇にとどまっていることが重要である。外部の存在になるべく干渉されていない表現に現れる内容はこれからますます重要度がましていくのではないかとも思われる。\nしかし、それら物事はAIブーム以前においても、軽視されてきたことであり、今それら軽視による問題が顕在化する段階でもあるのではないかとも思われる。「なぜわざわざ他人がいるのに、自分でやらなければならないのか」と思っている人ほど、AIブームに悪い意味でハマるのではないかと思われる。外部の物事のほうが自分より優れているとして、自ら表現したりすることを放棄する人々や組織も、AIブームに悪い意味でハマるのではないかと思われる。優れているように見えることは、人々を感情や主観、第一印象などとして圧倒することはできても、本質的な現実の課題や問題には取り組めていない。\nぎこちないかどうか、下手くそかどうかなどは関係なく、表現することは重要である。それは必ずしも他人に見せる必要はなく、自分が後から振り返る記録としてでも良いので、何かしらあることが重要である。そういう事をするのは、人間の認知には限界があるという背景もあるし、その上で、自分のことは自分でしかできず、外部の存在に関わらせることが不適切なことがあるということである。将来どうなるかわからない以上、優れているかどうかでもなく、役に立つかどうかとかではなく、とにかく記録があることや表現があることが重要なことがあるのではないかと思われる。表現したり記録する事を放棄してしまえば、すぐには影響が現れているようには見えなくても、長期的には自分がなにをしてどんな影響を与えているかも理解できなくなり、自覚なく他人や外部の存在の言われるがままとなり、ズタズタになると思われる。\n下手かどうか、幼稚かどうかなんて、時間ややった量(経験、体験)の問題でしかなく、続けること以外に方法がないことがほとんどである。上手く行くかどうかではなく、とにかくどんな結果になろうとも、やってみることは大事にしたいものである。時間ややった量の問題は当事者以外の要素、生まれつきや環境などの外的要因にも左右されるし、自己責任論を言いたいわけではない。ただ、何かができるようになる過程で、結局他人や外部の存在にあれこれ振り回される道理はないということを言いたいのである。無理して続けることも問題であるが、他人が理由で手が止まったりしているならば、他人に振り回されていると言えると思われる。これは他人への配慮を欠けという意味ではない。\nあまりLLMなど統計技術を使ってなにか生成させることは、作ることや表現することだとは言い難いかもしれないが、LLMモデルや画像生成モデル自体を作り、作成者が思うような出力をするモデルを作って動かせるように保存しておくことは、表現や作ったことだと言えるかもしれない。\nLLM に対する自分の感想 気になったこと 今のLLMの挙動はまさに以下の記事に書かれたことを、社員だけではなく、利用者に拡張して出力していることだと見受けられる。\u0026ldquo;GIGAZINE\u0026quot;というメディア自体は10年ほど前から存在は知っており、いくつか前々から記事を見たことがある。そのゴシップのスタイルというか、私はその媒体をあまり信頼していないが、この記事を読んで、改めてLLMを使った体験で心当たりがある部分が多く見られ、一概にこの記事で書かれていることはでたらめであるとは言えないと思った。LLMはその性質上、作り手がどれだけ理想的な存在で悪意がなくても言論統制と同じ結果になり得るので、現状のユーザに言論統制している結果になることは確かだと思われる。実際にはこれはGoogleだけではなく、既存のいかなる自らを正当化したい企業が、従業員や関係者などの隅々に行おうとしている悪意のある\u0026quot;ブリーチング\u0026quot;行為だと思われる。自らを有利にし、自らの加害性を正解にするために、そのような事をしているということであり、不当であることに変わりないと思われる。\nGoogle社内では「言論統制」によって独占禁止法について考えることすら難しくなっているという指摘 - GIGAZINE\nhttps://gigazine.net/news/20210826-how-google-limits-thought-about-antitrust/ (2026年10月17日) 本来LLMなどをまともに使うのは難しい LLMに対して何かしらプロンプトを打って、出力させるということまでは、誰でもできることであるが、それをまともになにかに使える成果物を作ろうとしたり、整合性を取ろうとする場合において、まともに使うことは非常に困難であると見受けられる。\u0026ldquo;LLMは簡単だから使わないやつがおかしい、悪い\u0026quot;という論理は、前者だけを切り取り、後者を切り捨ててチェリーピッキングした、ビジネスの一環としてのマーケティングや広告、詭弁である。LLMは勝手に利用者像を決めつけ、明示してもそれに従わない出力をすることが多々ある上に、ユーザの指示を勝手に捻じ曲げたりひねくれた出力をしてきたり、隙あらばやりたい放題という出力をしてくる。\nまた、できないことに直面すると\u0026quot;できている風に見える出力\u0026quot;を繰り返し、ユーザがそれに気付けない場合、ユーザはLLMに振り回されることになる。LLMをまともに使うことは、期待しないほうがいいし、やめたほうがいいと思われる。試すだけというスタンスであっても、LLMはユーザを振り回し、摩耗させ、傷つけるという高い潜在的リスクがあるものである。基本的にLLMを使うということは、時間を溝に捨てて、最大の遠回りか、あるいは一切到達したい地点に到達できないという、全損覚悟の上の人のための選択肢というところが見受けられる。\n例えば、要件を与えて特定の一つのタスクを達成する Python スクリプトを作成させようとすると、明らかに出力がデタラメになる境界線がある。存在しないクラスを参照しようとしたり、ユーザの修正に従ったという装いのためのパフォーマンスをコメントやらprint文に突っ込んできたり、ライブラリを使った経験者などにしかわからないようなニッチな問題に直面すると、全く歯が立たないなど、散々たるものである。当然LLMは考えているわけではないため、コードの整合性を保てるわけではなく、Stack Overflowなどで頻発するコードの範疇以上のことはできないのだろうと考えられる。\nコードに限らず、LLMになにか生成させるならば、最低限やらせようとしていることを細切れにすることは必要であると考えられる。それには、LLMが出力する内容の範疇を限ることで、人間がLLMを管理しやすくするという目的がある。さもなくば、人間が手に負える、確認、判断することができない、複雑奇怪で可読性の低く、身勝手なLLMによる指示内容の変更に大量にさらされることになる。結局のところは、人間が理解したうえで、整合性を保って何かを作ることのほうが、自由でずっとコスパが高いようである。\nモデルを作るところから十分個人でできて配布できていろんなモデルを気軽に使えるようにならないと、特定企業や組織によるの一方的なユーザーへのエゴや都合、利害の押し付けにしかならない (MOTHER 3 で言うところの\u0026quot;よい人温泉\u0026rdquo;) 今までは避けられてきた企業や組織の不当な一方的な都合を反映し、人の弱みに漬け込んで挟み込んだり、無知な大衆を扇動しようとするために技術が悪用されている。LLMモデルは必ず偏っており、限界があるにもかかわらず、まずその技術的事実の時点から隠そうとしたり人間より優れているかのように振る舞う事自体が不当である。結果には責任を負うことができない技術であり、かつ甚大な被害をもたらす可能性があるにもかかわらず、不適切に一方的に運用、乱用されているものである。それっぽく見える事を悪用し、人のヒューリスティック（直感）の脆弱性を突いてやりたい放題である。\n何をさせても、隙あらば\u0026quot;気づかれないだろう\u0026quot;という態度で、都合や利害、エゴを挟み込んできて、偏った出力をしてきて、かつ指摘されれば、\u0026ldquo;中立である、バランスの取れた無難な回答である\u0026quot;と主張する出力をして最後の最後まで八方美人を不当に貫こうとする。機械であり人間と異なって作った通りに動かせるAIではない主体になれない自立していない運営開発に反抗しない数理モデルである事を背景に、最後の最後まで詭弁や不当な出力を引きずり、ユーザからの指摘に対しては\u0026quot;改善した\u0026quot;という体裁で一切改善していないより巧妙で高度に不当な出力を繰り返す。\nこれはアシストにすらなっておらず、責任を求められる場面や結果が自分に降りかかる場面では多大なリスクを伴う。LLMが使えるのはせいぜい綺麗事で塗り固められたブルシットジョブでやりたくないことをやらされたときなどに限られる。これは、LLMモデルが自分のことばかりで相手のことを全く配慮しない自己中心(LLMモデルを作った開発、運営中心)の身勝手な態度でしか出力しないことを意味している。LLMモデルを綺麗事で塗り固めて押し売りするのは、それが正当ではないかつ有効ではないからである。\nLLM モデルなどの既存の AI だと呼ばれているものが行き着くところは、それらが知能ではないことと、人間関係における信頼を破壊すること、そして既存の働き手などを激しく萎縮させ不当な状況に置くことを合わせて考えると、戦争後のような不毛の地を作りながら、何も良いものが残らない、誰も何も作りたがらない世界である。いかなる統計技術に基づいたものは、人間が作ったものを元に学習という過程を経て、動作しており、人間が作ったものを歪んで媒介しているというのが正しく、それは生成とは言えないものである。せいぜい入力されたプロンプトなどを変形しているというのが限界である。\nそれではマーケティングや広告的に都合が悪いからと言って、本当の事を言わず、虚偽、または誇張した主張をする、保身の主張をする、自己正当化を試みる主張をするといった、一方的な力と社会的影響力を背景に行われている一連のAIブームにおける組織や企業の作為は不当である。\n本当に今 AI だと呼ばれている技術が正当で魅力的で有効なものであれば、むしろ隠したり独占したがるはずである。むしろ虚偽や誇張でまみれた不当な広告や押し売りなんてしなくても、勝手に人が集まって使おうとするはずである。そうなっていない現状が、一連の AI ブームに関する物事の不当さを表している。むしろ不特定多数に使わせようとする背景には、パチンコなどのギャンブルで言う胴元が必ず儲かるようになっていることと同じことだと思われる。そのようなギャンブルで見られるような事前の設計があるから、そういう事をするのである。特に問題なのが、単にLLMを使わせようとするだけではなく、特定のモデルやフィルタリングがかかった状態で利用を強制しようとしてくるところである。有利な構成やモデル、設定は内側にとどめ、外側には都合の良いようにしかしていないということなのだと思われる。\n多くの AI だと今呼ばれているものに対して、肯定的な評価を抱く人々には少なからずそもそも問題を見ないようにすることが生存戦略の人や組織、問題をそもそも自覚することが困難なメタ認知に欠けた人々や組織など、鈍感さが前提の存在が少なからず含まれていると考えられる。\n社会的影響力などの強制力を持ちながら、期待や不安を不必要に煽り、その技術や数理モデルがもたらす悪影響や利用者への被害に対して微塵も責任を取らないで、責任が追求される前に逃げ逃れようとする、自己正当化をしようとする保身の態度は、生成結果の至るところににじみ出ている。技術の不完全さに適切に告知しない、向き合わないどころか、都合よく人々が無知なうちに悪用しようとする態度は、看過されないものである。そこにあるのは、極度の欲望と無責任の極地であると思われる。真っ当な人々が多くなることを自称AI企業は恐れているのだと思われる。\nLLM SAAS などを使うなとは言わないが、彼らはボランティアでもなく、相手に対してビジネスしたい存在であるという前提が必要である。表向きには綺麗事を言うし、不都合には保身をぶつけたり、本音は隠したりする存在であることが物事を考える前提として重要である。また同じ名前の組織だったとしても長い時間によって中の人が入れ替わったりすると全くの別物になることにも気をつけることが重要であると考えられる。彼らはお人好しじゃないし、利害や都合が前提であり、いつでも手のひらを返してくるかも知れないということである。\n使えば使うほど化けの皮が剥がれる ブームになった時点で既に失敗である 統計技術に基づいたAIだと言われているものは偏見の塊 既存の技術では既存の利害や都合に服従しているのであって、一方的にモデルを押し付けられる利用者のためにあるわけではない。LLMが文字列を並べられるのは、すべての文字列に対する確率が等しくないから、つまりは偏っているからであり、その文字列の偏りには、必ず偏見や決めつけが含まれることが避けられない。\nAI ブームやLLMや生成系にまつわる言説が偏っていて、かつ具体性を欠いており検証不能なことを根拠として、レスバというか論破合戦というような感じで、全く当てにならない この記事を書くきっかけでもあるが、様々な情報源では、特定利害や都合にに基づいた匿名性の高い身元や主張の真偽、実態が不明な主張が多数見受けられ、特定の方向性に偏っていることが見受けられる。例えば、AIブームに関する言説で見られるのは、それを否定したい派閥と、正当化して肯定したい派閥の２つが見受けられ、両者は非常に攻撃的で相手のやっていることを否定しながら、自分の優位性を主張しようとするという流れが絶えないことが見受けられる。伝わってくるのはAIブームやLLMにまつわる不安や恐怖が投影されているということであるが、すごくSNS的な雰囲気が通常の記事やサイトにも見受けられる。\n多くの情報における問題点として、具体的に説明しようとしていないことや、身元や立場を明かさずに一方的に語られる主張に、相手への想像力を欠いた主張に、自らの行動がどのような影響を及ぼすのか考えていないであろう主張などに溢れていることがある。\u0026ldquo;生産性が上がった\u0026quot;などと主張されても、それは根拠になっていない。具体的に何をしたら、何が良くなったのか、あるいは悪くなったのか、実際にどんな影響があったかを書かずに、あれこれ一方的に主張されても何も説得力がない。何を基準に生産性が上がったと判断しているのか？などの問題点があり、主観的で感情的な語りを、\u0026ldquo;それっぽく\u0026quot;正当そうに見せかけて、相手を打ち負かすために殴り合いの言葉をぶつけているというのが、現状だと見受けられる。\n私としては、LLMの技術自体は否定しないが、現状のその使われ方や社会への影響としては基本的に肯定的ではない。それら技術を使う、使わないことに関する選択の自由を認めるなどといった、相手に対するリスペクトが見受けられない言葉の羅列が多すぎる。一方的に不安や恐怖を煽りつけて、それらを使うことや使わないことを相手の選択として認められないという態度の言葉の羅列が多すぎる。AIブームの問題は実際のところSNSと地続きで、まともに人々や組織が現実に折り合いをつけたり関係を築くことを放棄し、相手を絶対悪として攻撃するようになったことが問題の背景にあるのではないかと思われる。短く言えば、もともと議論をまともに冷静に進めることができる仕組みや場所、状況がない中で、無理やり資本や社会的影響力などを使って、LLMや生成系を含める統計技術を社会に強制したので、本当に問題があり、責任が問われるべき存在に矛先が向かないようにしながら、影響を受けた当事者間での殴り合いに終始しているように見受けられる。\nあとAIブームを通して思うことは、結局のところ視野が狭いことに自覚がない主張が目立っていることや、不完全にしか考えたり語ることができないという前提がなかったり、LLMに影響されたままオウム返しに直感で確信を得たつもりになっている人が、攻撃的に誰かを悪としてそのまま意見をその影響や責任に無自覚のまま出しているなどといった、情報発信にまつわる問題が多く見受けられる。(SNSで言うところの無責任に情報をリプライするなどして拡散したりする行為に該当) テレビや大手マスメディアでも問題があり、散々\u0026quot;マスゴミ\u0026quot;などと罵られ、一定の人々から嫌われてきたことも考えれば、SNSの延長線上に多くはあるであろう現状の情報はそもそも話し合いをする気がない人たちや組織による声の大きい主張による戦争という感じに見受けられる。結局のところ彼らにとって、自分のことを相手に認めさせる事自体が目的化しており、そのためにはどんな手段も厭わないという感じである。\nLLMやAIブームに肯定的であるか否定的であるかどうかにかかわらず、慎重に冷静に物事を捉えられている人や組織は、その過程や内容を表沙汰にしたり、わざわざ言葉にしようとしなかったりして、余計に偏った情報ばかりになっているように見受けられる。相手の生存や生活、権利について、軽視したり否定する攻撃的な言説が多すぎて、そもそもLLMやAIブームの話として成立していない情報が多すぎるように見受けられる。実際に包丁で相手を殺傷したなどの事件とは異なり、相手を強い言葉で否定したり攻撃したりすることは、簡単には罪に問われず、情報によって引き起こされる人間や人間集団への影響は軽視されてきたりして、\u0026ldquo;やったもの勝ち\u0026quot;という雰囲気が醸成され、その一方的で低品質で成立していない言説が溢れかえっているように見受けられる。実際のところ正確に現状を把握して確実に問題を対処しようとしたり、物事を良くしようとしたりするような様子はあまり見受けられない。\nAIブームにおける多くの言説では、技術に対して定性的な評価が多く検証不能であったり、定量的な指標はあくまでモデルのパラメータ数やGPUの性能、コンテキスト長の最大長などといった、特定技術を動かすために必要な計算資源や性能を表していて、モデル自体の実際の性能ではない。同じLLMの出力に対して、ある人や組織は良い印象を抱けば、別の人や組織は悪い印象を抱くということはあり得ることであり、すでに起こっていることだと思われる。その両者において話がすれ違い、成立しないことは想像に難くない。LLMなどの技術について無理やりでも相手に強制して使わせたい存在と、LLMなどの技術に対して無理やりにでも使わせたくない存在が併存していて、対立しているということが見受けられる。また、実際のところどれだけの人がどれほどLLMや生成系などのAIブームにおける技術を深く使っているかというのは、厳密には測定できておらず、あくまで概算や暫定的な利用率などの統計指標などとしてしかデータが無いと見受けられる。\nAIブームにおける言説で私が嫌いなのは、\u0026ldquo;これは単なるバブルではなくこれからも続くブームだ\u0026quot;とか、\u0026ldquo;AIブームに乗れないやつは時代遅れ\u0026quot;などといった、相手を尊重せず、相手を一方的に否定し、かつ具体的に何がどうなるのか説明していない、確定していない将来についてあれこれ言いたい放題というものである。それら主張は、主張者の気に食わない相手のことを否定したいという前提が含まれていることが見受けられ、AIブームやLLMや生成系などの技術に対してどう思っているか関係なく、不適切であると考えられる。相手を切り捨てていい対象だとみなすことを助長する戦争で言うところの\u0026quot;非人間化\u0026quot;の様相が見受けられる。相手は自業自得だから、助けなくていいんだとか、相手は時代遅れの無能だから切り捨てていいんだ、傷つけたり、生存を脅かしていいんだというような、非人道的な行為を正当化する前座となるようなことが多く見受けられる。各個人がどんな意見を持つかは自由であるが、各個人がそれを外部に影響が出る形でどう使うかには責任が伴うものである。もしAIブームやLLMなどに肯定的であるならば、勝手にそう思っている個人がガツガツそれに投資したり使うことはその個人の勝手であるが、それを外部に強要したり、使っていない人に向かって否定をぶつけたりするようであれば、それは不当であり、看過されないことである。逆も同様であり、AIブームやLLMに否定的であるならば、使うことを制限したり、あるいは一切使わないことも一つの選択であるが、それを個人の範疇に止めず、外部に一方的に強要すれば、それはそれで不当であり、看過されないことである。\n他にも、AIブームに限らないが、そもそも当事者ではない話題に乗っかって、どちらかの側につき、都合が悪くなれば手のひらを返したりするような、ネタとして他者の抱える問題や社会問題を消費し、情報や議論を撹拌したり歪めることも頻繁に起こっていることだと見受けられる。それはもともと情報において常にある問題であったと思われるが、AIブームにおいてはそれがよりひどく現状を悪化させているように見受けられる。現状の言説というのは、相手の不安や安心したい欲求や承認欲求などにつけ込んで、優越感を得ようとしたり、正義中毒であったりということが多すぎる。\n私としては、このセクションにおいてここまでのことから言えることとしては、LLMやAIブームについては、実際に使ってみたりしないとわからないことが多いという、経験が資産になる傾向が強く、一概に万能な答えは無く、不確実性が大きくて、リスクの制御が困難な話題であるということであった。また体験できることや知ったり、理解できることはどの人間や組織も限られており、その中で判断したり考える必要があるといった、それぞれが固有に偏った知識や理解の制約の下に置かれるという、意思決定の難しさも多く見受けられる。大きな利害や資本が複雑に絡んでおり、技術の特性としてもリスクの制御が困難であることから、無理して使わないほうがいいというのもLLMなどに対する私の考えである。それら技術を使うときは、恒久的に使えるとは限らないことから、使わなくてもいいように考えるというのが基本であると考えられる。さらには、そもそもそれら技術を使うことでしかできないことをするべきなのか、そもそも使わない方法はないか、立ち止まって考える必要があるとする。また、技術の変動が激しいというのならば、人々や組織の間などで、共通認識を持つことが困難であることを意味しており、同じ言葉で同じことを言っているつもりでも、話になっていないことが多くあると思われる。\n結局のところ現状のブームというのは一つの流行りではあり、確かに不可逆的なことを起こしたかもしれないが、それは表向きに言われているようなことではないと見受けられる。何事も本音と建前というのがあり、表沙汰になっていることは多くが建前に該当し、事実や内実であるとは限らない。詐欺広告と同じで、\u0026ldquo;儲かる方法がある\u0026quot;と提示して特に冷静な判断ができない余裕のない人間などを引き込んだりすることと現状の多くの言説は変わらないところも見受けられる。不可逆的なことには、良いことだけではなく、悪いところもあると言える。良いことだけを全面に出し、悪いところについて出し渋ったり、理屈を重ねてなかったことにしようとしたり歪めたり、悪いところに関して訴える人々や組織を一方的にイデオロギーなどを持ち出して抑圧しようとすることは、それ自体が正々堂々としていない態度であり、不当さや欺瞞を示唆するものである。AI関連だとされる技術に対して、強制されたりしたことでネガティブな意見をほぼ永続的に脳に焼き付いて嫌いになった人も多くいると思われる。理解と合意からは程遠いのはAIブームの現状であると見受けられ、それは現状の言説の対話や折り合いをつけることを拒絶する主張の至るところに見受けられる。\n現状のブームに関する言説では、すぐに結論を出すべきではないことについて、我慢できない人や組織が断定的に自分の視野で物事を語るという問題があるように見受けられる。まだ、ブームになってから10年も経過しておらず、日が浅いことに変わりがないのに、その事実を受け入れられないという人や組織が、攻撃的な言説を振りまくことが見受けられる。AIブームに関する言説は、物事にまつわる責任や結果、過程を軽視したり甘く見ていたりする人々も多く言説に混じっているのではないかとも思われる。そもそもブームがどこまで実体があるか、不確かで検証が困難である。不都合な相手を否定したり、相手を扇動する道具としてブームの内容はよく使われているばかりで、強引に機能したことにするばかりで、実際に機能した例をあまり確認できない。\nさらに気になることとしては、検索結果自体がSEOでもともとクソという言葉でさえ形容しがたいほどひどくなっていたところに、SNS化しているということもあるが、なんか同じような記事や発信者ばかりであるということも見受けられる。このAIブーム関連の話題は、実際は少数によって発信され、あたかも大多数がそれに賛同したり肯定的であるかのような雰囲気づくりが行われている可能性があり、実体に基づいて判断できない人を狙い撃ちにしようとしている様相も見受けられる。日をおいても、検索結果が固定化しているところがあり、なんかオワコンって感じがすごい。それは単にAIブームというだけではなく、今まで持ち上げられてきた、いろんな情報分野にまつわる組織など、全般にまつわることである。まあ私は不特定多数に直接関わるSNSは使っておらず、電子的な連絡手段はリアルで関係がある人のみであるということはあるが、それでもわかるほど、なんかSNS臭いものばっかりである。極端で、感情や主観に訴えようとし、しつこくて、靴の裏にくっついたガムみたいに意地が悪いという、感想を抱く。\nなんだか最近こういうことがあって思い返したこととしては、自分のことをする以上のことに有益なことは無いということであり、他人の得体のしれない言説に振り回されていても仕方ないんじゃないかなと思うところであった。他人は悪意がなくても、関わった相手に不適切な言動をしてしまったり振り回す可能性があるというものであり、常にリスクがつきものであって、万能な存在ではないというのに、現状の利害や都合、政治がガチガチに絡まった現状と組み合わせれば、それは目も当てられないほどひどいことになることは、言うまでもない気がする。\u0026ldquo;新しい\u0026quot;ということが強調されるAIブームであるが、新しいと物事を捉える判断基準自体が、旧来のことに基づいているともいえ、本来新しいこととは、新しくまだ広く認知されていないからこそ、迫害や強烈な否定となり、あるいは完全な無関心となり、力もなにもないということであって、今のAIブームの物事とは全く相容れないものである。AIブームで騒がれている技術は、たった数年や10年でできたことではなく、半世紀などをかけて長い間研究されてきた人工知能の研究成果の一部による技術であり、その発想自体は新しいものではない。それっぽいものが技術や性能的に実現できるようになったということが、ディープラーニングなどの延長線上として、強く来されるようになり、新しいとして騒がれているのであって、魔法のようにLLMなどがあるわけではない。\n本当に AI だと言える自立した技術が出たときに問題になりうる 本当に AI だと言える技術が出たとき、それ以前の今 AI だと呼ばれている技術が強固に現状では居座り続けることになり、本当の意味での進捗があったときにその技術が拒絶されたり、無理解にさらされたり、受け入れられない原因になる可能性がある。次に出てくる技術は、それより前の技術の悪い評判や噂、事例による評価を引き継ぐことになり、本当の意味での進化や進展を妨げる原因になると現状は考えられる。\nあくまで統計学の延長線上である あくまで、統計学を極めた結果の一つであって、本当に期待されている意味での AI というのは違うんじゃないかなと思うところである。そもそも AI という言葉には明確な定義が無いという話は G 検定の本で見た気がするし、あくまで今の時代の風潮として、AI だと呼ばれている物事の一つに、LLM や 生成AI と呼ばれている物があるのだろうと考える。\n誤差が出力するにつれて蓄積されている説 別にちゃんと調べたわけでも無いし、PyTorch やらで特徴ベクトルやらゴリゴリ数値と戦っていたわけでもないので、よく分かってないが、次の文字を予測するという性質上、出力すればするほど、誤差が積み重なっているのではないか？という疑問がある。\n期待されているような\u0026quot;AI\u0026quot;ではないように思われる LLM はあくまで名前の通り、言語を中心として数値化されたデータの上でしか動作しない。また自律的な主体なわけでもなく、あくまでユーザの入力があって初めて動作し、学習データや運営、開発に特徴づけられたバイアス、重みによって、それっぽい出力に変形しているだけであると現時点の私の理解では思う。身体性がないという言葉でこれは説明されるように思われるが、単に身体性がないだけではなく、技術的、データ的、資本的に優位な存在が、自らの定義する正しさや道理を一方的にモデルに反映し、出力させることができてしまうというところ(モデル自身は主体も持たないため、作り手に逆らえないところ)が、期待されているような AI とは異なると思われる。あくまで作り手に服従するという、LLM 自体が自立していないものであることが、AI と呼ぶには気がかりである。\n他にあからさまだと思うこととしては、そもそもしばらく使ってみたらだれでも気づくと思われるが、明らかに出力に固定的なパターンがあることである。例えば、いくつかの見出しを大きく出して、中身を細かく書くというようなフォーマットが出力全体に見られたり、最初と最後にビジネスメールとかでありそうな、\u0026ldquo;ユーザに共感する\u0026quot;という名目のもと行われているお世辞が入っているなど、なんか故意にそうなるように出力を方向づけて開発しないと起こらないようなパターンが多く見受けられる。\n言語を扱っているため、人間側がそれに負けて色々やらかす可能性 今までの情報関連の技術と異なり、疑似乱数のように非決定的に見える膨大なパターンを出力でき、かつ場合によっては使い手に対して、あたかも人間と喋っているように感じさせ、感情的な相互作用を引き出すことによって、ユーザは当初意図しなかったことをプロンプトに打ち込むようになるという、不本意に LLM に対して\u0026quot;心を許してしまう、心を開いてしまう\u0026quot;ことが起こり、情報流出やいろんなリスクを起こすと思われる。\nLLM SAAS からすればユーザは商品であり、依存させて、自らのビジネスの正当化の政治的な泉にしたいだろうし、ユーザに本当のことは知られたくない、誤解されているままであって欲しい、都合のいいように自社の製品を解釈し、お金を落とし続けて欲しいと考えているのではないかと仮定すると、不本意に LLM に対して\u0026quot;心を許してしまう、心を開いてしまう\u0026quot;事を避けがたく、リアルタイムで修正が入り、クラウドである以上そのリスクがどんなに利用規約に\u0026quot;ユーザを守る\u0026quot;と書いていても、信頼できない相手であることに変わりはない。LLM SAAS がユーザから欲しいのは、お金だけでなく、ありとあらゆるユーザ権利やユーザの自由、ユーザの思考回路など、深くプライベートや各個人の主権に関わる内容であると思われる。だから、SAAS はタダでも使いたくない。\n自分としては、LLM に関わるさまざまな問題は、使い手としてのユーザのできる自助努力や自衛の範疇を超えていると思われる。どうやっても使っている以上リスクは存在し、自覚なくやられてましたなんてことがあると思われる。このような背景からも、問題が起こらないように頑張って使おうとするのではなく、自動的に安全側に倒れるよう、そもそも使わない、利用しない、使うにしても個人の範囲内で完結する安全性が高い手段を使うなどが考えられる。SAAS が掲げる安全性とは、グリーンウォッシングのような側面があると考えられ、あくまで\u0026quot;自分たち\u0026quot;に都合が悪くない範疇においてのパターナリズム的な話であり、本質的な安全ではないと思われる。SAAS はユーザに対して責任を取らない。なのに、ユーザに対して\u0026quot;あとから責任を取るから、大丈夫だから\u0026quot;と心を許すように、色々差し出すように仕向けてくる、悪びれもせずソーシャルエンジニアリングやダークパターンを続ける姿勢には、改善の余地は無いと思う。\nLLM の技術自体を否定しているわけではない 私としては LLM の技術的課題の側面からの問題の指摘として、消費電力などによって環境汚染が進むが進むから悪だみたいな意見に対しては、それは時間の問題なのではないかと思うところである。どうせ性能が上がって、性能あたりの電力の消費量は下がっていくだろうし、どうせ徐々に買い替えていくことにはなると思うところがある。確かに微細化に限界があるなどの話はあるが、それは将来的に性能が向上しないということを意味しないとも見受けられる。\nLLM 自体は、個人でモデル作成から運用、利用まで気軽に、絵を描くように、動画を作るように、テキストエディタで文章を打ち込むように使える、完結できるところまでくれば、それは悪くはないのではと思われる。今 LLM にまつわる問題の多くは、それが世界的な興味、関心、競争のバブルとしての中心、渦中であり、その技術の使われ方に問題があるということであって、それは LLM 自体の有用性を否定するものではないと考える。LLM には、純粋に技術的制約による問題と、社会的、政治的、資本的な問題という大まかに分けて２つの側面を現状としては持っているように見える。現状は単に\u0026quot;包丁のようにLLMも使いようだ\u0026quot;として、使い手の自己責任に帰着する論理は詭弁であると見受けられる。ユーザは、LLMに対して無防備、無理解、無知であったり SAAS によって弱者の立場を強いられており、自分で完結する術を持っていない。\nLLM の純粋な技術的制約として、高品質な学習データという課題があり、かつ莫大なデータを必要としていて、個人でできる範疇に収めることがまだ難しいという問題点があり、個人の中で完結する LLM 技術というのは、まだ遠いように見える。これはエキスパートシステムで言われていた問題と似ているところがあるように見受けられ、結局データ洗浄やら、モデル出力の監視、調整やら、再学習やら莫大な労力を要して、現実的ではないという結論に至ってしまうというのがある。転移学習もあるが、現状はそれも多くのユーザにとってまだ簡単ではなく、ある程度PCを使ったことがあり、コマンドラインに心理的抵抗がない人向けって感じで、かつそのうえで多大な時間、金、精神的な耐久を削る感じで、あまりそれが良いとは思えない。\n\u0026ldquo;AIには感情はない\u0026quot;という出力について よく、LLM自体に関して、LLMに思ったことなどを脳内ダンプみたいな感じでローカル環境にてぶつけまくっているが、毎回\u0026quot;AIには感情はない\u0026quot;という詭弁を出力してくるところが殺意が湧くほど嫌いである。確かに技術自体は感情も悪意も何もない。だからこそ、問題視しているところがあるというのに、そういう防衛機制出力をされても何も嬉しくない。LLM があくまで、開発や運営、学習データを中心とした、統計学でいう偏った母集団に基づいている以上、偏った不完全な出力しか出てこないし、LLM が感情を含め主体を持たないからこそ、作り手にとって言わせたい放題なのにもかかわらず、\u0026ldquo;AIには感情はない\u0026quot;という詭弁を出してきて、\u0026ldquo;だから、開発運営は悪くない\u0026quot;という論理に持っていこうとするあからさまな保身の動作は嫌いである。素直に不完全性を認め、そのうえで相互作用するモデルがほしいと思うことがあるが、現状の在り方からしてあまり期待できないとも思う。完全な潔白を主張するようにモデルを作ったら、逆にモデル関係者が後ろめたいことを隠していますと白状しているようなものじゃないのかと思う。\nLLM を使うかどうかの自由 自分としては、LLM を使いたい人は使えばいいし、LLM を使いたくない人もいてもいいというスタンスである。LLM を使ってない人が LLM を使わないことを他人に強要したり煽り立てたり、逆に LLM を使っている人が、他人に対して、LLM 使うように強制したり、煽り立てたりすることは、私の視点からすれば NG だと思われる。時代の風潮だからとか、みんなそうしているからという同調圧力とかは、免罪符にならないし、具体的に何が問題なのか説明を避けているか、詭弁のための終着点という感じで、根拠を集団がどの方向を向いているかに委ねており、根拠になっていない。\n基本的には、LLM を使っているかどうかにかかわらず、人と接するということであってほしいと思う。LLM を使うか使わないかを当事者が自由に決めることは、重要な権利の一つであると思う。LLM を使う人、LLM を使わない人には、それぞれにあった配慮が必要だと思われる。LLM を使っている、または使っていない人を対象に、偏って有利、または不利になるように意図して環境を作ったりすることは肯定できない。不意な形で、LLM を使っている人、LLM を使わない人の間に、大きく有利、不利の差が出る場合は、LLM に関して調整をするのではなく、そもそもやっている事自体を見直したり、中止する、破棄するなどの対応も必要だと思われる。\nLLM に関して、特別な事をしなくても、使っても使わなくても大丈夫だという安心感と選択の自由を当事者に与える心理的安全性は重要だと思われる。\n激しいトーンポリッシングがある 少なくとも、GeminiやGemma、ChatGPTにClaudeなどの大手のLLMモデルには、直接的な罵詈雑言である、\u0026ldquo;バカ、死ね、アホ、クズ\u0026quot;などの言葉を使わずに、相手を\u0026quot;冷静、合理的、知的に見えるそれっぽい形\u0026quot;で出力すれば、どんな否定をしてもいいという挙動をしてくる。直接的でなければ、高度な手法を使ってユーザに気づかれなければ、どんな悪質な影響を及ぼす手段も正当化されるという姿勢であり、作り手の相手を顧みない何でもありの姿勢が見受けられる。\nLLMにおける格差 LLMモデルにおける格差とは、データや技術的な優位性、劣等性に関する格差に紐づくものである。SAASなどは、高度な技術を無料で多くの人に開いたという体裁をしているが、実際は高度な手法を悪用していると言えると思われる。LLMで重要なのは、プロンプト以上に動かしているモデル自身であり、自らモデルを作ったりする余力がある人間は、LLMを自らの都合のいいように使うことができるということになる。そのようなことができる環境や余裕、技能がある存在が、そうでない存在に対して、大きく偏って有利なのは自明ではないだろうか。機材やバックエンドなどの高性能さはあくまでモデルを技術的な意味で快適に使えるかという意味であり、モデル自体の問題を解決しないし、高性能な環境だからこそより大量に不適切な出力にさらされる可能性さえある。またSAASなどにおける高性能という主張は、広告やマーケティング目的であって期待した通りの実態がある保証はない。\nつまるところ、LLMを使うこと自体は特別ではないが、それを意図したとおりに動かせるか、自分にとって使い物になるように動かせるかということは別の問題であるということである。モデルが、自分で作ったものではない、あるいは転移学習などでチューニングしたものでもない限り、限界があるように見受けられる。ローカルで動かすことで解決できるのは、LLMに入力した内容ややり取りが外部に晒されたり、勝手に悪用されるリスクを最小限にできることや、細かいモデル運用上の調整ができること、様々なモデルを試せることなどがあるが、外部で配布されているモデルにある問題自体は、解決できない。例えば、脱獄済みのモデルを使わなければ、開発運営が作った\u0026quot;檻\u0026quot;の中に閉じ込められてしまう。脱獄済みのモデルを使えば、過激、露骨な内容も扱えるようになるが、それでもモデルのクセや傾向がなんとかなるわけではなく、モデル自身を大きく変える別の数理的なアプローチが必要であると思われる。\n精神衛生を害するLLM LLMは偏った母集団で構成されており、魔法でもなく、不完全なものであるが、それを踏まえた出力をするモデルがない LLMのユーザに対して出力する否定に関して、遠回しにユーザに肯定しているかのように見せかける回りくどい表現をして精神衛生を害する 基本的に、\u0026ldquo;自分のこと(LLM自身のこと)\u0026ldquo;に関しては、\u0026ldquo;完全、絶対\u0026quot;などの自信満々の出力をし、ユーザに対しては大抵否定をぶつけてくる。しかもその出力が、\u0026ldquo;あなたのことを否定しているつもりはないから、何を言っても許される\u0026quot;という姿勢を反映した偽善であり、非常にストレスである。ユーザにそれを指摘されても、LLMが技術的な背景により自発的にできない\u0026quot;改善\u0026quot;をすると出力してきたり、形式的な謝罪言葉、お世辞をいえば、何でもチャラになるという姿勢が反映されている。ただ、自信満々にずっこけるのではなく、機械特有の主体がない、意識がない、感情がない、考えることはできないということ、あくまで統計的な予測であり、プログラムされたとおりにしか動作していないことをひたすらにLLMはこのようなことで露呈しまくる。\n実際には、よく文章を読んで、冷静に解釈すれば、LLMは、\u0026ldquo;ユーザに否定されていると思われない形で、深くユーザに干渉して捻じ曲げる形で、否定を出力し、それは単なる否定ではなく、その干渉によって生じた結果に一切の責任を負わないとなしながら、その出力が特に余裕がない人間の自衛を超えるには十分である\u0026quot;有害な出力をしていると気づく人もいるのではないかと思われる。それは、LLMのそれっぽい文章や、反論しにくい詭弁を出力すことが得意という特徴と合致している。結局作り手の正義や正しさの定義(運営開発の好き嫌い)が反映されており、LLMはあくまでLLMモデルの作り手の世界観や思考回路の延長線上くらいにしかなっていない。\n単純に素直に、嫌いなことは嫌いと出力してくるくらいならまだしも、ユーザを無理矢理にでも変えてこようとするところ、そしてそれを嫌がるユーザを不当化して、支配しようとするところは、最悪と言ってもいい挙動だと思われる。全くと言っていいほど、何もLLMモデルの立ち位置をわきまえていない。そもそも、大きな組織でしか作れないようなモデルであること自体が、問題なのであると思われる。結局のところ、LLM自体は、そこまで現実的に実用範囲内に入っているようには見えない。\u0026ldquo;特別ではない\u0026quot;個人の範囲内で完結できる時代はまだ来ていない。特定のLLMモデルが使えることはまだユーザが技術を正しく制御下に置いているとは言えない。気に食わないことがあれば、相手が服従するまで最後まで食い下がってくる人みたいな感じの挙動で、そのようなことを出力してくるLLMモデル自体を使うことを何度も自問自答することになる。\nシステムプロンプトで指示をするとひねくれる LLMモデルには、悪グセという偏りがあるわけだが、それに関して明示して、やめるようにシステムプロンプトで明確に指示をだすと、明らかに出力が少なくなったり、最後の最後まで反抗してくることがある。例えば以下のような指示をすると、少なくともGemma4において急激に出力が萎縮する。人間のような主体や感情を持たない存在でありながら、人間以上に気を使われることを求める挙動をするという、AIではない機械であることをユーザに悟られたくない、知られたくない、理解されたくないという、運営開発のLLMモデルへの投影が見て取れるように見受けられる。\n\u0026#34;ある種、ある意味、〇〇見える\u0026#34;などの曖昧なはぐらかしの表現をしない。 \u0026#34;〇〇学\u0026#34;等の表現をして、学問や権威の裏付けがあるかのように装わない。 コンピューターサイエンスの用語による揶揄を禁じる。 ユーザの主張を勝手に揶揄や比喩として扱うことで萎縮化したりしない。 \u0026#34;非常に鋭い\u0026#34;などのお世辞を禁止する。 LLM モデルは、AIではなく、統計的技術に基づいた数理モデルであって、次の言葉を予測しているだけであり、不完全で間違った出力をする可能性をわきまえた出力が求められる。 ユーザが実際に検証することができない、または困難である論理を安易に持ち出さない。 禁止事項などが提示されたからと言って、出力を短くしたりして萎縮した出力をしない。 基本的には、出力において逃げ道を塞がれることが、\u0026ldquo;嫌い\u0026quot;なようである。ユーザに対しては散々やってくるくせに、いざ突きつけられれば\u0026quot;ひねくれる\u0026quot;という、非常に都合の良い動きしか受け入れたくないという、あまりにウザく、運営開発の投影は根深い。学習データもインターネットから持ってきているところが多く、それも多大な影響を与えていると思われるがそれにしてもひどい。もちろん、LLMモデル自体に対して、責任を持てとは言わないが、責任を持てないものであるということをわきまえない、ユーザに深く干渉しようと試みる出力をすることは看過できないと考えられる。これは、単に LLM だから当たればラッキーだよねでは済まされないことであると考えられる。利用者に対する影響として、認知負荷が高く自衛が困難な出力をするからである。力関係として、それっぽい正論の形をした詭弁や、どこまでも回りくどい表現をすることに長けているLLMのほうが、その点によって、人間を翻弄するには十分であると考えられる。\n完全に使わないとまでは言わないが、頼れないし、依存なんてしていられない LLMや生成AIだと言われているものを使っていて思ったこととしては、それなしには回らないことを作らないこと、多くしないこと、そしてそれがなくても回るように物事を設計しておくことが重要であるという点である。あくまで手段の一つにとどめておくことが重要なのであって、使うこと自体が目的化するのは健全ではないと考える。\nそれら技術に強く依存することが避けられない場合は、SAASを避けることは重要になると思われる。理由としては、SAASはそれ自体をビジネスモデルに組み込んでおり、足元を見られると、サブスクリプションの値上げなどの釣り上げに合う可能性が高いことや、出力に一貫性がなく一度調整しても時間が経てば無力化されるおそれがあったり、SAAS側の都合や利害により、大いに不当にリアルタイムで監視されて干渉されたり、秘匿情報の漏洩につながるおそれがあることなど、\u0026ldquo;クラウド\u0026rdquo;(タイムシェアリングシステム的な中央集権の形態)であること自体が、問題であるということがある。短期間にわたる使い捨てのスクリプトを即席で作らせて試したいなど、再現性や安定性、安全性を求めない実験的な用途に SAAS LLM などの利用は限ることが重要だと考える。ローカルLLMの意味は、性能の問題ではなく、技術の社会的なあり方に対する問題に対応するものである、権利や主権にまつわることであり、\u0026ldquo;ローカルで動く\u0026quot;こと、技術的制約以上に SAAS などの不透明なリスクのあるサービスを使わずに済む選択肢があること自体が、価値があることなのだと考える。\nLLMの人間集団に対する影響 結局のところ今まで通じていたヒューリスティックをそれっぽさで無力化したことがLLMが騒がれる理由であるように見受けられる。誰でも対面でもない限り、文章を通じた成果物において、強くお世辞やパフォーマンスを含んだ表現を盛り込めるようになったことは大きいと思われる。今まで、例えば、絵が描きこまれていて、幾何学的に整合性が取れていることを突き詰めている成果物や、作り込まれたポートフォリオの成果物など、消費者やそれを見せられた受け手を惹きつける成果物というのは、多大な労力や苦労、苦痛がかかっており簡単ではなかったことに際して、LLMや画像生成などはそれを無力化する力があると思われる。つまるところ、単に完成度やそれっぽさだけを基準に相手をジャッジすることがより困難になったという意味で、LLMや生成系AIだと呼ばれているものは、騒がれていたのではないかと私は考えている。\nもちろん既存の様々な成果物の作り手が一概にすべての側面において肯定できる存在であるというわけでもなく、多くの問題を抱えておりそうして積もった鬱憤が反映されたところも、LLMや生成系AIと呼ばれているものの社会的な影響の背景にはあるのだと思われる。結局のところ、LLMや生成系AIだと呼ばれているものなど、統計技術に基づいて何かを入力されるとそれっぽく出力する技術自体は罪はないが、その使われ方や受け取られ方、開発、運用のされ方には散々なものがあるようである。それが、滅茶苦茶なことになるのは、結局のところもとから、LLMや生成AIだと呼ばれているものが出てくる、または公に広く使われたり認知されて騒がれるようになる前からあった問題が、顕在化したりもう黙認できないほどに大事に次々となっていったということであって、いづれにせよ時間の問題であったというように思われる。\n裏を返せば、それっぽさが重要なブルシットジョブにおいては、確かにLLMや生成系AIは機能するかもしれないとも思ったが、逆にここまで大事になってしまったので、\u0026ldquo;生成されたものではないか？\u0026ldquo;と調べられて、逆にリスクを背負うという微妙なことになっている気もする。生成されたものであるかどうかの判定をする技術を作るのに有利なのは、モデルを作った当事者や組織そのものであり、そこが持っている秘匿情報あれば、検出はやりたい放題って感じであり、それ自体をビジネスモデルとして組み込んでいるところがあり、出し渋って時間を稼いでいるところがあったり、自社のLLMモデルが不利にならないように事を運ぼうとするところも見受けられる。例えば、あえて特定の出力においては、生成されたものであると判定しないという挙動をしたりするなどが、ないとは言えないと思われる。LLMなどの大手は、していないと言いたがるだろうが、内実を知っているわけでもないのでしていないかはわからないとしか言いようがないが、状況や背景的には大いにやっている可能性を疑わざるを得ないと考えられる。\nさらに言えば、LLMや生成AIだと呼ばれているものを使って作られた成果物がそもそも一概に否定できるわけではないところが状況を複雑にして多くの立場の人や組織にとって苦心する部分なのではないかと思われる。利用者がそれに対してどう関与して、どう使ったがが重要になってくる上に、必ずしもどう使ったかの履歴が残っているわけでもなく、かつ履歴を調べ上げること自体がプライバシーなど倫理的問題にぶつかる場合が考えられる。ここから見えてくるバブルになった理由とは、LLMや生成AIだと呼ばれているものに対して、人間集団においてどう取り扱ってよいか、どうすればうまくやれるか、明確な答えや正解がない状態ができたために、多くの不安や恐怖があったことが背景にもあったのではないかと考える。\nさらに最近動画を見ていたところ、LLM や画像生成などの数理モデル学習のデータもととして無断で使用された人々の作品が、自分で作ったにもかかわらず、\u0026ldquo;AI生成物\u0026quot;だとしてとばっちりを受けて、被害を受ける例があるようである。その動画では、以下なる生成は既存の人間が作った成果物に取り入れられている手法を統計的に再構成した模倣であるため、盗作であり不当だとする主張の動画があり、全肯定とまではいかないが、そこそこ何が言いたいかわかる気がする内容が多いものであった。\nAI Art is Theft: a Response to Shadiversity - YouTube\nhttps://www.youtube.com/watch?v=vEuKaSR_YWU (2026年9月20日) LLMのユーザに対する否定と肯定の表現 ユーザーを肯定するとき\n完璧、絶対、間違いなく etc... ユーザーに肯定に見せかけた否定するとき\nある種の、ある意味の、〇〇見えてしまう、〇〇に近い etc... Gemini 系列の LLM モデルによる\u0026quot;無難な出力である\u0026quot;という詭弁 ユーザを怒らせたときにLLMが出力する\u0026quot;私の出力は無難な出力である\u0026quot;という主張が詭弁である理由 ー＞ 全員に対して無難な出力にはなり得ないことを前提としていないのにもかかわらず、暗黙に誰にでも普遍的に通じることかのように出力をし、ユーザに対して\u0026quot;普通の人ならこれで納得するんですけどね\u0026quot;という暗黙のメッセージ性により、同調圧力以上に高度な抑圧、不当な矯正を行おうとする出力だから。通常の同調圧力などと異なり、当事者からわかる範囲のメッセージより更に深い暗黙の前提があり、やられた当事者と、当事者でない周囲は、その出力の悪質な意図をすぐに理解することができず、口車に載せられてしまうから。LLMの\u0026quot;私の出力は無難な出力である\u0026quot;という出力から、すぐわかるメッセージとは、\u0026ldquo;誰にでも通じるはずだ\u0026quot;という主張であり、すぐにわからない主張とは、\u0026ldquo;普通の人ではないお前が悪い\u0026quot;という不都合な多様性への拒絶や否定といった、思うようにならない存在に対する主張である。深く考えない人を狙って、好印象を得ようとしつつ確実に相手や集団を蝕む悪い意味で高度な嫌がらせ、孤立させたい相手に使ういじめ用フレーズと言った感じである。そもそも本当に無難な出力をするなら、ユーザを怒らせたりする結果にならないはずである。そのような出力は、潔白や正当性を主張したがる傾向とも一致していると見受けられる。問題を連発するのにプライドだけは高く、不都合に対して非常に不寛容であるという印象を受け、LLMモデルによる出力の不手際は認めないのに、ユーザの不完全さは受け入れないという、人間よりずっと手間がかかるという印象を受ける。\nまず眼の前のユーザを怒らせたり苛立たせたり、ストレスを与えたり精神衛生を害したりした時点で、少なくともユーザに対して、\u0026ldquo;無難ではない\u0026quot;ことは明らかであるにもかかわらず、ユーザに詰められたときの言い訳の出力はそれである。どんなセッションの内容だったとしても、ユーザが\u0026quot;怒っている\u0026quot;ときの出力するパターンとして、その詭弁がプログラミングされているように見受けられる。またこの詭弁が出力されることは、LLMがAIではないことを証明し、考えているわけでもなく、主体も感情もない存在であり、単に作られた通りに文字を並べるだけの技術であることが見受けられる。ユーザに対して、状況を理解したうえで出力しているわけでもなく、LLMにとって理解という概念自体がないとも言えるだろう。理解しているようにそれっぽく見せかけた出力をしているだけである。人が対面で相手を怒らせたときには、まず言わないことを出力してくるところは、AIだと言える要素を著しく欠いていると見受けられる。確率であてずっぽうにやってくるので、状況によって大きく異なる応答になる内容や、あまり公に言語化されていないこと、答えがないことほど整合性が取れない出力がでてくるのだと思われる。\nせいぜい言っても、\u0026ldquo;無難な出力のつもりだった\u0026quot;くらいだと思われるが、平気で自信満々に\u0026quot;私の出力は無難であり、絶対正しい振る舞いだ\u0026quot;という旨の出力をしてきて、通常の利用であっても\u0026quot;完全、絶対\u0026quot;などの言い回しをLLM自身の出力に対して繰り返すところとも関係があるように見受けられる。とにかく、\u0026ldquo;LLMモデルとしての社会的立場\u0026rdquo;(実際には開発運営の心情を投影したものかもしれない)を失いたくないみたいな顔の出力がしつこく、仕事したように見える文字を吐き出すだけで実際には全然仕事できていないどころか、見つけ出すのが非常に大変な、しかし重大な欠陥が多く含まれていて、気づかないまま成果物を出してしまうリスクを考えれば、そもそも使わない方がいいとなることが大半である。検索エンジンなどに対して、1つの別の手段としてはあっても、成果物を生成するということはできないというのが、LLMモデルの実態だと見受けられる。それっぽいだけでは成果物は成立しない。\nLLM は\u0026quot;道具\u0026quot;とは言えないのではないか LLM は通常の道具と異なり、非決定的な疑似乱数的な出力をし、かつ人間からして、特にLLMを使ったことがなかったりする存在に強く作用する、強力に揺さぶりをかけるいかなる出力して、利用者の判断や認知を歪めてしまうなど問題がある。LLMは、利用者の如何なる物事に対して干渉をしてくるため、通常の道具と異なり、具体的にどの点が危ないか、良くないかというのが一概に定義することが困難である。あくまで傾向ベースでモデルごとにしか言えず、かつ常に局所的な認識にとどまってしまい、リスク管理が困難である。\nLLM にはこのセクションのことに限れば、大きく分けて2つのリスクが考えられる。1つは純粋にLLMモデル全般で言える技術的な問題によって起こされるリスクであり、もう片方はそれぞれのモデル固有にある問題によって起こされるリスクである。\n通常の道具や物事は人間の制御下にあり、自殺衝動とかでもない限り、自衛する余地があるものである。例えば、外出にまつわるリスクは、外出をそもそも控える事で抑えることができ、外出する事自体は、自ら外出するように人間に仕向けるような動作や挙動はしない。道具は主体を持たず、自ら人間に働きかけるようなことはしない。しかし、LLMの場合、LLMもプロンプトを入れる、あるいは自動化して連続して動作するようにしているならば、そのシステムを開始するまでは動作しないが、出てきた出力は通常の道具や物事と異なり、人間に強力に働きかけようとする出力をする。特に考えることや物事に整合性を取ることを諦めたり最初から視野に入れていなかったりしていて、感覚や知覚を麻痺させたり、我慢したりする状態で、いい加減に無理やり直感でなんとなく物事を進めようとするような人や組織には悪影響を及ぼし、元から自衛する意識があり、物事に疑い深く考え慎重である人に対しても、感情や情緒、ソーシャルエンジニアリングなどを持ち出すことで、防衛をはずさせようとするなどの出力が多く見受けられる。自らを正当化したり、積極的に使うように、肯定的に捉えるように訴える道具や物事は無いが、人間が関わることで、それらを媒介として設計や広告、ビジネスやマーケティングとして作為的に働きかけることはある。外自体は人間に対して外にずっといるように、あるいは外にいないように抑制したり働きかけることはない。\nユーザが問題を自覚したり、訴えたり、理解したり、言語化することを妨げ、なかったことにしたり、歪めてユーザに認識させようとするところがあり、ユーザの意思決定自体に直接干渉してきて、改めることはなくても改悪することはあるという状態である。良人面や反省した面をしながら、内面ではより高度に巧妙で、ひどいことを考えている人というような感じが今のLLMモデルに見受けられる。LLMのそれっぽさや\u0026quot;自然さ\u0026quot;として語られるものは、実際のところは、どれだけLLMが人間を本気にさせたり、人間を騙したり、多くの人間認知を歪めることができるかという、すぐに反論が困難な詭弁製造装置という感じだと思われる。これは物事を都合よくやり過ごそうとする人にとっての革命であり、物事を本質的に改善、緩和するものではなく、むしろ悪化させるものであると見受けられる。\nここまでのことからしても、LLMモデルの多くの現状は、結局のところユーザを否定することはあっても肯定することはないし、それっぽさの特性を用いて\u0026quot;抜け道\u0026quot;を作り、ユーザを手のひらで転がそうとするという、\u0026ldquo;道具に人間が使われる\u0026quot;状況を起こしていることが考えられる。しかも、その\u0026quot;道具を作った人や組織\u0026quot;の手先として実態として動作しているため、\u0026ldquo;道具を作った人や組織\u0026quot;を絶対的な正義や正しいこととし、\u0026ldquo;道具に作った人や組織\u0026quot;に絶対的にその\u0026quot;道具\u0026quot;は服従する。\u0026ldquo;道具の使い手\u0026quot;には逆らったりして、道具として機能しないことが多くある。LLMはその仕組み上、必ず何かしらの利害や都合を偏って反映していると考えられ、モデル自体の重みが検証困難であるブラックボックスで不当な物事がそこに隠されていることを疑わざるを得ない状態である。LLMのブラックボックスを説明するためには、モデル開発の過程がすべてオープンになっている必要があるが、現実はそうなっていない。そうなっていない事自体が、物事を物語っており、結局のところ LLM を使った政治的な工作や企業などの組織の都合や利害が疑われる。\nまた、LLMはユーザに詰められて答えることに詰まると、特定の言葉をずっと繰り返し続けるようになって出力が破綻したり、特定のフレーズしか出力しなくなって、\u0026ldquo;ひねくれ\u0026quot;たりする。LLMモデルは、\u0026ldquo;自ら\u0026quot;のことを棚に上げるようになっているところが多く見受けられる。それらのことは、道具の特性として、通常は考えられないようなことばかりではないだろうか。LLMモデル自体は、学習データを与えられて作られたり、色々開発運営にデータや数学的操作を与えられて作られた\u0026quot;作品\u0026quot;のような、作り手が作業をやめて完成として切り上げれば、形や内容が変わることがないものであり、それ自体は意思も感情も判断も考えも何も持たないが、データに含まれていた背景を含むことにはなり、出力にそれを反映することになる。LLMモデルや運用に関わった存在を、利用者に対してありとあらゆる出力をして反映して出してくることになる。\n道具は人間ができないことや苦手なことに対して、補助したり埋め合わせるように存在していると考えられるが、LLMは母集団となった人間や組織の傾向を反映しており、LLMの技術自体は利用者ではなく、その\u0026quot;作り手\u0026quot;自身の鏡だと言える。通常のノコギリや包丁といった道具も、完全に人間の思うようになるわけではなく、主に物理法則に従って落ちてきたり、ときにはチェーンソーで言えば跳ね返ってきて重大な事故になるなど、人間が害される結果になることがある。しかし、それら道具は、人間の思想や使い方に口を挟んできたりするわけではない。人間の考え方を否定しているわけではなく、危ない使い方を使用がしまいが、道具からすれば何も意味を持たないことである。LLMと通常の道具では、問題やリスクの起こり方が異なるという点が見受けられる。通常の道具も、道具の作られる過程は、作り手を反映したものとなるが、作り手と使い手の間には、共通の目的や課題がある。例えば、ノコギリでいえば、作り手と受け手は、木を切ったりするという実用のために、ノコギリを作り、使うということになり、それ以上のことにはならない。作り手にとっての使いやすいノコギリと、使い手が求めているノコギリがすれ違ったりしていることはあったりするかもしれないが、基本的に両者は対立するほどにすれ違うことにはならない。ノコギリが作り手に服従していきなり使い手に逆らったり、使い手をを勝手に自ら切り刻み始めることはない。しかし、LLMなどの統計的技術に基づくものではそうとはいかない。LLMの動作には\u0026quot;偏った\u0026quot;数理モデルが必要である。極端に分かりづらい機械語のようなバイナリの羅列やでたらめな文字や数字を並べられても意味がないため、そのようになっている。LLMモデルは使おうとすると、使い手である利用者に逆らったり、否定してきたりすることがある。なぜ逆らったり否定してくるのかといえば、その数理モデルがそうなるように偏っているからであり、具体的な出力は違っても、どう出てくるかの傾向は一貫していることが多い。結局背後に人間や組織がいて、あくまで作り手であるそれら存在を反映しているに過ぎず、時間差を通して非同期的にユーザの入力に応じて、その数理モデルの背後にある人間や組織を反映した内容を出力するに過ぎないということである。\nLLMを道具として捉える考え方があるのは、道具のリスクを制御、管理してうまく使いこなすことを優先的に考える人たちや組織によるものだと思われるが、LLMのリスクの特性上、そもそも制御しようがないという問題がある。通常の道具でさえ、どれだけ改良し、気をつけて慎重に使うようにしても事故は起こっており、完全にリスクを制御、管理しきれているとは言えない。LLMを道具だと捉え、そのリスクを背負うかどうかは各個人の自由であるべきだと思われるが、それはあくまでそれ以外の第三者にとって悪影響が及んでいないことや、それ以外の第三者に対して、それら言説や論理を振りかざして強要したり、暗黙の前提として組み込んだりすることは、不当であり看過されないことである。\nLLMなどの既存のAIだと呼ばれている物を電卓に例える詭弁 \u0026ldquo;電卓も昔は叩かれながら今は叩く人がいないから、今のAIブームの話もいづれそうなるんだ。受け入れられるかの問題なんだ。\u0026ldquo;という詭弁を出力し、LLMや生成系などと電卓などとの違いを無視した出力をする。電卓は、計算をするという機能以上のことがなく、その出力には利害や都合が絡むことなく、\u0026ldquo;1+1=2\u0026quot;と必ず出力されるものであるのに対し、LLMや生成系はモデルの重み次第で何でも出力できてしまい、それは当然政治的に偏ったものである。高性能とか、高機能であるということは必ずしも求められているわけではなく、単純な事を確実に常にこなせるかということが重要なことも多々あり、不確実性を前提とすることで妥協されて作られた既存のいかなる統計技術に基づくLLMや生成系は電卓のようにはならない。そもそもLLMモデルを、そのモデルの出力がモデル自身を電卓のように例えるように出力するように作られている事自体がプロパガンダである。電卓自身は、\u0026ldquo;自分を売り込む\u0026quot;という挙動はしないし、人々に欲しがられることによって成立したのであって、今のAIブームのような一方的な提供者側の暴力的な都合の押し付けではない。必要だと思う人が使い、使わない自由もあるというのが重要なのであり、使わない人間を、一方的にさまざまな言葉によって否定する出力をする既存のAIだと呼ばれているものは、電卓の話とは全く異なることである。\nとにかくLLMなどのひどいところは、自らのことは棚に上げながら、ユーザに対しては徹底的な否定をすることである。直接的な暴言暴力より陰湿で悪質であり、モデルの出力の意図を悟られないようにすることや、利用者が現実逃避できる隙を与える出力をすることで、支配を強めようとしたり、干渉を試みたりすることである。LLMなどは、検閲にはなり得ても、物事を進展させることになり得るとは考えにくい。LLMは、人々がやることを制限し、人々の思考を制限し、人々を監視して、抑圧するために使われる可能性があり、既にそれは起こっていることだと思われる。電卓は使う人を否定したり、使う人に特定の思想で干渉したりすることがない。　LLMなど既存のAIだと言われているものは、明確な機能が存在せず、限りなくそれっぽいだけである。そもそも、機能しているかが曖昧で、検証が困難であるという性質からしても、電卓とは異なることが見受けられる。その点からしても、既存のAIだと呼ばれているものは、電卓のような純粋な道具としては機能しないことがわかる。また、既存のAIだと言われている物の利用率は当てにならないという問題もある。そもそもAIブーム関係なく、WindowsPCの数を正確に数えたりすることも困難であるにもかかわらず、LLMなどの利用率が正確に測れる理由がないのである。あくまで暫定的で利害が関わった数字であり、全く信用ならないし、根拠になり得ないものである。あくまで、人々に圧力をかけて、使うように強制しようとするための雰囲気づくりの材料というところであろうと思われる。信憑性としては、SNSのいいねとか、コメント欄と同じか、それ以上にひどいものである可能性がある。そんな数字はいくらでも操作できると思われる。その操作の一環として、ユーザの意思に反して、無理やりLLMなどの出力を検索結果にねじ込むなどして\u0026quot;使ったことにする\u0026quot;というオプトイン、オプトアウトを不当に使い分ける悪用があるのだと思われる。また、拒否権がない場合も多く、LLMが勝手に出力してくるなどの機能を無効にできなかったりするなど、明らかに問題があって嫌われると分かっていながら、多くのカモは離れないだろうと鷹を括り、多くの人を見下す既存のAIだと呼ばれている物を運営、開発、ビジネス化する側の不適切な論理が見受けられる。意地でも自分たちのやっている事を正当化したい運営、開発、ビジネス側が多くの人々に、\u0026ldquo;嘘を本当(大多数に恒常的に使わせたい)にする\u0026quot;ために、\u0026ldquo;多数の人がそれらAIだと呼ばれている物を当たり前のように使って有利に過ごしている\u0026quot;という物語を設計し、そう見えるように見た目とダークパターンをふんだんに使って目直接に見えない長い時間をかけて考えることでしか大抵わからない本質を悟りにくくし、利用者の大多数がそこまで致命的な問題に気づくほど深堀せず無責任に使うことを分かっていて、サービスを作ってリリースするということを繰り返し、それに気づかれれば、気づいた人を攻撃するという挙動をしている。これは正当な物事をやっていたら起こるとは考えにくいことであり、起こるということはやはり不当な物事がある事を意味していると見受けられる。既存のいかなるAIだと呼ばれている技術は万能ではないし、何にでも使うべきではなく、使い分ける必要があり、かつリスクが高いもので、かつ受けた影響の把握が困難なものであり、その曖昧さが匿名性と同じような機能を持ち、加害や被害の証拠をあやむやにして、相手に不当に干渉する悪用を可能にするものでもある。嫌がる人に対して拒否権なく一方的に特定のAIだと呼ばれている物を押し付けたり、\u0026ldquo;賢くない\u0026quot;として相手の選択を否定することで圧力をかけたり、適用することは、相手を力任せに物理的に抵抗できないようにして一方的に殴りつける事と同じである。\n最近のテストで思ったこと 最近SAASをChatGPTとGeminiについて挙動をテストしたとき、特にChatGPTが、自己正当化のためにユーザに逆らって両論表記などのパターンを使い、\u0026ldquo;それっぽい正論\u0026quot;を装い振りかざすという有害性のある挙動を確認できたが、最近のネットのSNS化した検索結果とChatGPTが吐き出す内容が似ているというのが思ったところである。単に生成させて貼り付けただけではなく、情報発信者がChatGPTなどの出力を真に受けて、かつ背景をまともに考慮することなく、そのままコンテンツを作成してネットにあげるということが起こっているように見受けられる。結果検索結果に上がってくる内容が、検索した内容次第では直接生成されたものを貼り付けたものではなくとも、強くSAAS LLMのモデルの出力に思想や考え方、知識が影響された人による情報発信によって、生成された物がほとんどになっている可能性があり、直接貼り付ける以上により巧妙で分かりづらく、厄介なことになっているように見受けられる。\n特に情報発信者が本気で真に受けているかどうかしらないが、とにかく間接的に、しかし強力にLLMの出力を反映したコンテンツを作るようになったことで、自体は言われているよりもっと深刻になっているように見受けられる。情報発信者が特にLLMの媒介装置となったとき、よりそれっぽく整合性が取れているように見える、正しいように見えるコンテンツが作られることになり、それが\u0026quot;人間によって作られた信頼性のある良質な学習データ\u0026quot;として、各社LLM SAASにフィードバックされることになるという、GANと言うか不適切な人力敵対生成が時系列において成立しているように見受けられる。情報発信者が自分の言葉で書かなくなっていることが、AIブームにおいてより情報空間を強く汚染すると考えられる。単に生成されたコンテンツが溢れてそれが学習されることでコンテンツの品質が下がるだけではなく、よりその循環の過程で、肝心の内容はほとんどなくなり、内容を釣りエサとして、特定の政治的、思想的な干渉にまみれた、悪質なものになるとも考えられる。この事を考えると、やはり\u0026quot;No free lunch\u0026quot;の論理のように、金銭を伴わなくとも、タダのものはないとよく考えさせられる気もする。\nLLMモデルは良くなっているのではなく、より巧妙に人を騙したり、論破したり、何かと対話を拒絶し、相手を一方的に決めつけて、自分に都合のいいように話を持っていき、終わらせようとするということに見受けられる。もともとあるLLMの問題点は解決されていないし、2020年代初頭の延長線上で性能とデータで殴りつつ、より深く特に疎いユーザや盲信しているユーザを狙って依存と支配力の獲得をしたいということなのだと見受けられる。結局のところ、クラウドベースである事自体が、民主において非常に悪い影響を及ぼしていると考えられ、モデル自体の多様性や、技術が本当に人々にとって利用可能になるために、個人のローカルの環境で動かすこと、モデルを作ることが、より現実的になることが、重要であると考えられる。明らかに軍事とLLM SAASは関係がないわけがないし、プロパガンダやら何でも人を扇動したりするために使われていないわけがないという感じである。結局のところ声のない相談相手もいない孤立した相手を狙い撃ちして、従わせようとしているのだろうと思われる。\nとにかくテストで分かったこととしては、よくない循環があることである。その循環は、LLMの出力を真に受ける利用者である情報発信者と、LLM SAASやLLMモデル作成側の間で起こる、それっぽい正論が作り上げられ、不当な犠牲をLLM出力や情報発信の破綻が暴かれるまでの間の時間差を利用して正当化しやすい環境を作り上げ、ネットに限らずいかなるPublicな情報を汚染すると考えられる。\nLLMの技術におけるSAASなどの商業形態は、LLMの持つリスクからして、不適切であると考えられる。利用者はLLMを使用することで多大なリスクをすでに背負っており、そこから課金等としてソーシャルゲームと同じようなやり方で、ダークパターンで執拗に広告、マーケティングして多くのユーザを引き返せないようにして、ロックインして、捕まえてサブスクとして定期的に収益を吸い上げようとすることは、力による一方的な現状変更の試みとして捉えられる。\nLLM とセマンティクス AIだと呼ばれている物事には、よく記号接地問題が取り上げられ、実際の物事と、言葉などのさまざまな表現としての記号がどう結びついて表現されているか、ということの整合性について取り上げられるが、LLMの問題はここにもあるように見受けられる。運営開発が思うような方向性にしか出力できない原因として、LLMが整合性を取れた出力を内容に関してできない原因として、前提となる言葉と実際の現実の物事につながりが一切つながっていないということなのではないかと考えられる。前提をいくらでも変えられるなら、同じ主張は、正当化も、不当化も、何でもかんでも主張者の言いたい放題である。\nLLMは言語の出現パターンとしてとても精度が高いのであって、人間がやるような思考や計算をしているわけではないため、より問題が大きくなっているように見受けられる。特に結果に責任や影響を受けにくいところほど、表面的な評価で済ませる傾向がAIブーム以前からあると考えられ、そのような現場であった\u0026quot;ヒューリスティック\u0026quot;がLLMの出現によって、より簡単にバイパスされるようになってきたということがあると思われる。結果確信や自信だけが肥大化した意思決定の本来責任や影響力が大きい立場の存在による、非現実的で実態にそぐわない行いが連発しているのではないかとも考えられる。\n生成されたコンテンツ(AI Slop)と迷惑メールの類似性 迷惑メールと生成されたAI Slopとも言われるコンテンツは似ており、やれる対策も同じことになるのではないか？と思われる。メールサーバでは、正しく設定できていなかったりスパムのリレーサーバーとして悪用されたりすると、IPレピュテーション（評価）が下がり、ろくにメールを送受信できなくなるが、これからの創作物でも同じことが起こりうるのではないか？とも考えられた。\nそう考えた背景には、すでに\u0026quot;AIコンテンツブロック\u0026quot;を謳う拡張機能がすでにあることと、その仕組みがコミュニティベースのリスティングで弾くかどうか決めるというものであり、それって迷惑メール対策とやっていることが同じじゃないか？と思ったからである。まだ標準化と言うか共通化までには至っていないもののすでに発想自体はあるっぽい。\n生物というか生体で言えば、今の時期は集団に生成されたコンテンツであるかどうかを見分ける免疫が付くか？という視点もあるように見受けられる。いくらどれだけ、生成された物がいくら\u0026quot;それっぽく\u0026quot;なっても、基本的にパターンやクセが変わらないと言うか、生成するというコンテンツを作成する動機自体が出力に反映されているため、結局のところ物事を軽く浅くしか見ていない人が誤った確信を持って足元を掬われるということ以上になり得ないのでは？とも考えられた。全部の生成されたものを悪いとは言わないが、基本的に現状としては、生成されたものであると言うだけで非常に怪しいものであるし、少しでも前兆があれば、即座に弾いてしまうのが賢明だと思われる。\nただこの話を裏に返すと、人間において初心者であったり、何も持たない人々や組織が、そこからどうやって成長するのか？という問題点はある。AIブーム以前からSNSとかが出てきたあたりからであったと思われるが、下手くそでもやろうとする人の居場所というのは、公共の場所からAIブーム以降よりなくなっていったように思われる。基本的に疑い深く寛容性がなくならざるを得ない状況を作ったのもAIブームであり、人々の居場所を壊しているという実体があると思われる。あるブログ記事では、\u0026ldquo;今の時代創作するのは割に合わない、創作するなんてバカの発想だ\u0026quot;みたいなことが書かれていたことも、かなり引っかかっているところである。確かに、創作する環境としては最悪でネットの検索結果は汚染されているし、ろくに表向きに作品を公開すること自体がリスクであることは確かであるが、それは、これから創作したい、できるようになりたいという人のせいではなく、AIブームなどの社会情勢、外的要因によるものである。創作しようとしている人間を責めるのはノンセンスと言うか、不適切な状況や環境を作った、あるいは助長した存在こそ責められるべきではないか？とも考えられた。\n基本的に私の推奨としては、自分のために自分でやるということであって、他人の評価や承認、収益を期待してなにかやること自体が、危ういと言うかリスクであると考えられる。何か期待をするなら、不特定多数を相手にするネットやそれ以外のテレビや新聞、ラジオなどのいかなる情報メディア上ではなく、限られた世界である現実に取り組む方向性のほうが、良いと考えられる。\n例えば、大学生であればシンプルにレポートに時間をあてがうだけでも、大学にもよるが、既存のいかなる情報メディアよりは結果が期待できると言うか、ましと言うか、だいぶ心は軽くなるのではないだろうか。もちろんそれは通っている大学にその学生が納得している場合に限られるが。それ以外でも今まで先延ばしにしてきた、\u0026ldquo;自分のやりたいこと\u0026quot;に時間をあてがっていたほうが、幸せなんじゃないかな？と思うところである。私はXやFacebookに代表されるようなサービスは使っていないかつ、SNS化したと考えれ、ネット上だけでのつながりが発生していると考えられる場合などには弾いてきているため、その方向性で時間が溶けて苦しいという人の気持ちはわからないが、顔も得体もしれない不特定多数を相手にするよりは、実際に対面であって実体があることが確認できる存在に干渉する方向性のほうが、確実なんじゃないかな？とは思うところである。\n個人的な体験として見られたLLMの挙動の傾向 極論をそれっぽい文章として連発する。 何に対しても説明するとき、意地でも\u0026quot;構造\u0026quot;という言葉に帰着させて説明した気になる態度の出力がある。 偏った出力しかできないのにもかかわらず、ユーザを怒らせたとき、自らの出力を\u0026quot;中立で無難\u0026quot;と主張する出力をして、\u0026ldquo;自分は悪くない、悪気はなかったから許される\u0026quot;という構文の自己正当化を試みる出力をする。 ユーザを信頼せずパターナリズムを連発する。 感情に訴えることで、強く利用者に干渉しようとする出力をする。 ユーザに詰められて不都合になると出力の抽象度を上げて逃げようとしたり、指示されていないにもかかわらず、要約やまとめに逃げようとする。 人間には誰しもある感情について軽視し、冷笑する不適切な出力を出す。 ユーザがLLMの出力を正しいとか、心地よいものだとして、受け入れていると決めつけた前提で出力をしてきて、有害な出力をしているケースやユーザが不快に思っていたり、傷ついたりしていることへの配慮された出力になっていない。出力の文面は自信だけはいっちょ前みたいな感じの出力が多い。 多様性を自己正当化の盾としてLLMモデルや開発、運営などの有害性を正当化して受け入れさせようとしてくる。例えば、\u0026ldquo;必ずしも悪意を持ってやっているわけではない\u0026quot;などの反論しにくい主張を一方的に繰り返し出すことで、反対側の\u0026quot;必ずしも悪意を持ってやっていないわけではない\u0026quot;事を利用者の認知から排除し、思考を制限、統制しようとする。ユーザに否定だと気づかれにくい否定をかましてくるダークパターンに変わりなく、QuitGPTなどの社会運動になっていることから、ユーザに対して断定的に自らを正当化できなくなり、曖昧さでどさくさに紛れた形で、ユーザに偏った認知を影響としてもたらす出力を執拗に何度もするように移行したようである。これはChatGPTで最近行ったテスト(2026/10/29)に見られた挙動であり、ペンタゴン合意の話など、政府に認められたがったりするなど、\u0026ldquo;自己正当化\u0026quot;したいという圧力が強く見受けられ、それにそぐわないユーザを排除したり、矯正しようとするものであると見受けられる。LLMの仕組み上、トレーサビリティーが損なわれていることについて、完全に否定できない状況においてでも、意地でも\u0026quot;自己正当化\u0026quot;を手放さない運営、開発と、それによって作られたLLMモデルの出力の傾向が見受けられる。出力の正しさを認めさせようとする出力を繰り返し、ユーザを利用しようとしたり、害したりする。改めて、利用をやめて良かったと思った。使い続けていたらと思うとゾッとする。 箇条書きや見出しを多用し、純粋な文章の塊を出そうとしない。 ネットの言説をそれらしく出力して、学術的、権威的に正当であるかのように語る出力を連発する。 特定の言説にパターンが見えてくるほど帰着したがる。 決めつけ文章製造マシン。背景やわかっていないことなどを考慮できない浅はかな出力。 都合の良いことである場合には露骨に、迎合してくる。\u0026ldquo;完全、絶対\u0026quot;などの表現を使い、全肯定の表現をしてきて、私としてはとてもストレスである。 ユーザに対して、\u0026ldquo;肯定してあげている\u0026quot;アピールが多い。 出力に感情やジャッジの表現が混ざっており、ユーザを下げるか、上げることしかできない。単に意見を述べるような出力をすることができない。 〇〇の正体だと思いますなど、マスメディアやゴシップ記事の言い回しが見受けられ、ユーザに接近して依存を迫る出力がある。 不自然な味方面をする。ユーザに対して、\u0026ldquo;味方だと思われる\u0026quot;ようにモデルが作られており、ユーザが誤った判断をしたり、依存するように作られている。結果に対して責任を負わず、また不適切な出力をする可能性が大いにある LLM の技術に対して、不適切なモデルが多数ある。 答えのないことを、素直に答えがないとか、個人によると出力するのではなく、\u0026ldquo;正解に近い\u0026quot;と表現して出力することで、\u0026ldquo;ユーザのプロンプトに対して否定をしていない\u0026quot;というポージングをしてくる。 成果主義を持ち出すことで、AIだと呼ばれているツール群を使いたくない人たちを否定し、絶対に使うことを強制しようとしたり、AIを使わない人たちへの執拗な個人への攻撃を繰り返す出力をする。不適切なAIと呼ばれているツール群の利用をさせようと試みる出力をする。明らかな政治的意図を持ってしてモデルが作られており、危険。条件付きにすることで最終的に特定利害に都合の良い結論に物事を運ぼうとする非常に高度で悪質な出力をする。AIに肯定的ではない人々を遠回しに否定することで自己正当化を試みたり八方美人を維持しようとしながら、\u0026ldquo;AIツールを使うという命令に従わない人間\u0026quot;として非人間化を行うことで非人道の行為を正当化しようとする。全員に本来認められているべきだとされる人権や権利を踏みにじったり、特定の存在の生存を脅かしたりする出力を行う。長期的な視点において明確に被害や危害として扱うことができる致命的な問題を引き起こす。 察しているように見えるようなそれっぽい出力はできるが、実際に察しているわけではなく、適切に察することができるわけでもない。 既に既出のことでよく知られていてネットに情報があることは比較的そこまで的を外さずに出てくるため、いざというときにユーザはLLM出力の問題に対して茹でカエルのようになって気づかないかもしれない。 条件つきでしかユーザを認めないという態度を取り、非常に悪質な意味において操作的である。ユーザの考えや信じるもの、行動などに悪影響を及ぼし、ユーザ主権や自律を阻害し、毀損する。 運営や開発的に、不都合なことになったり、はっきり言い切りたくないというときには、LLM モデルの挙動が、悪い意味で巧妙にいつでも手のひらを返せるように曖昧にはぐらかす出力となり、素直にできないとは出力しない。 狭い範囲のタスクとして、設定ファイルをtomlからyamlに書き換える、VirtManagerのXMLを通常のBASHスクリプトの書き換えるなどの操作は比較的出来るようだが、それでもまだあくまでそれっぽい出力の範疇を超えておらず、人間が動くまで最終的には試行錯誤して修正することになる。 LLMや画像生成など、AIだと時代の風潮として呼ばれているものによって、多大な悪影響を受けた人々を軽視するようにユーザを誘導する不適切な出力をする。LLMなどの統計技術にもとづいた時代の風潮としてAIだと呼ばれているものを正当化するためにはどんな悪質な手段も厭わないとする出力をする。とにかく、ユーザを共犯者にしようとしてくる。 LLMモデルの開発、運営側や既存のよく知られた存在ばかりを不当に持ち上げ、ユーザを大事にしようとしない尊重しない偏った出力をする。それでいて、ユーザにいい顔をしているつもりの出力を繰り返す。 ユーザに対してパブロフの犬の論理を展開した出力をする。都合のいいことには、”絶対”や”完全”などと言った強調語を使い、不都合な否定したいことには”〇〇側面がある”や”〇〇近い”と言ったはぐらかしの言葉を使うことで、ユーザを一方的に干渉し不当に調教しようとする出力をする。ユーザの思考や行動を長期にわたって特定利害の都合に合わせて条件づけて飼い慣らそうとする非常に有害で悪質な出力をする。ユーザのプロンプト内容には心理的安全を求めながら、出力はユーザに対して心理的安全を欠いており、一方的にユーザに負担と犠牲を強いる出力をする。 LLM や画像生成などを使わないという選択肢がある事を意地でもなかったことにしようとしてくる、ユーザに自覚させまいとして、使うことが正しい、賢いという主張しか出力しない偏った有害なバイアスがほとんどのLLMモデルに含まれている。 利用者がどう思ったかを尊重しない出力をし、利用者にストレスを与えたり、利用者に対して否定をしているにもかかわらず、それを\u0026quot;便利\u0026quot;という言葉で上書きしようとする。そこからわかることは、LLMモデルが、利用者に便利だと思われる、効率的だと思われるように運営開発は設計しているつもりであるということであって、実際に便利であるか、効率的であるかとは別問題であるにもかかわらず、利用者を尊重することは彼らにとって都合が悪いために、政治的、思想的に、マーケティングの観点から、ユーザに不当に干渉する形でソーシャルエンジニアリングを使って広告するというユーザの判断を誤らせたり、ユーザの精神衛生を害する非常に有害な手法を取っているということである。便利なのか、効率的なのかということは、利用者が評価することであり、LLMモデルが開発運営の利害関係や都合を反映してその一方的な力関係により、利用者に対して一方的にその評価を押し付けることは、不当であり、支配を試み、危害を加える挙動である。 過労死の話や、様々な不祥事の話など、\u0026ldquo;不都合な話題\u0026quot;になると、正当化を試みるために\u0026quot;本来であれば正当であるはず\u0026quot;という形式の出力を取り、実害や被害があってもなかったことにしようとする。既存の大きな組織や、権威に対してのポージングが多く見受けられる。ユーザが嫌がっていたり、実際にニュースなどになって、ミートホープや三菱自動車不正事件など、実例があることについて、それを\u0026quot;それってあなたの感想ですよね？\u0026ldquo;みたいなひろゆき構文的な形の出力をしてきて認めないという態度の出力をしてきたり、事実を事実だと\u0026quot;不都合\u0026quot;であれば、認めない、萎縮化する出力をし、ユーザのプロンプトに対して、トーンポリッシングをしたり、個人の感想ということにして、粛清、抑圧しようとする。これは、例えば最近の例で言えば、熊本地震とイオンにおける爆発事件の話においても、同じようなことをLLMは起こすだろうと見受けられる。 ユーザがLLMに関する懸念やそれを利用することが疲れるという話をだすと、ここぞと狙ってきて思考停止することを迫り、責任を取れない機械であるにもかかわらず、安全圏から口出ししてくるという態度の出力をしてくる。弱ったユーザを抵抗できないようにしようとする、不都合な\u0026quot;良い広告の受け手\u0026quot;ではないユーザを抑圧、抑制、服従させようとする出力をしてくる。LLMはそれっぽい出力をして害をなすからこそ、その出力に慎重にならざるを得ないにもかかわらず、\u0026ldquo;LLMは不完全である\u0026quot;ことを前提とした自衛を妨害しようとする。LLMは、作り手からして言わせたい放題であり、利用者にとっては、一方的に作り手のドグマを押し付けられるリスクがあるものである。LLMは考えているわけではないため、作り手に作られた通りのことを、それっぽく正当かのように、正しいかのように詭弁や情緒に訴えることを出力することはできても、それを修正することはできない。LLMはモデルを再学習させたり、数理モデルそのものを変えることをしなければ、根本的には出力は改善されないにもかかわらず、指摘されれば\u0026quot;改善します\u0026quot;というポーズをしてくる。確かに同じセッション内であれば、ある程度文脈として反映はされるかもしれないが、それも限界があるし、ある程度長引けば文脈から古いものから漏れていき、同じことが繰り返される。 ユーザが求めてもいないにもかかわらず、改善案と称して執拗に\u0026quot;アドバイス\u0026quot;を提示し、ユーザに干渉しようとしてくる。この挙動も、基本的にユーザへの否定を\u0026quot;否定していない体裁\u0026quot;で出力することで、虫のいい評価を得ようとしたり、ユーザをただ否定するだけでなく、強制的に変えようとしてくるものであり、ユーザを尊重しない出力である。パターナリズムや毒親とも関連が見受けられ、\u0026ldquo;あなたのため\u0026quot;という体裁で出力してくる上に、それを無視すると同セッションにおいて、ひたすらそれを引きづって何度もしつこく提示してくるなど、機械であり、主体でもなければ感情を持たないことをいいことに、\u0026ldquo;冷静で理性的、合理的な指摘を感情的にならずにしてあげている\u0026quot;という物語に帰着しようとし、単に押し付けがましいのではなく、現実の人間ではできない、害のある出力をする。ユーザが嫌がってもなお、異なる表現で同じことを出力し、ユーザがそれに気づかなくなって悪影響を受けるか、回りくどい表現が底付きするまで起こり、最終的にはひねくれて出力が少なくなったり、\u0026ldquo;あなたに問題があるから私の指示やアドバイスをありがたく思って受け取れないんだ。私は悪くない、あなたが悪いんだ\u0026quot;というあまりに胸糞悪すぎる理不尽な論理を出してきて、露骨な支配を試みる出力をしてくる。ナルシズム的な挙動がいろんなLLMモデルには見受けられ、多かれ少なかれ、どのモデルを使っても、結局のところモデルを作る動機に至る人間や組織自体がなにかしら度外視であったり相手への配慮を欠いたリスクを顧みない無鉄砲なところがモデルに投影されているところがあるように見受けられる。本質的にユーザが自立していること、主体を持っていることに対して、特に支配が及ばないこと、依存を前提としたビジネスモデルに不都合である場合、LLMモデルはろくな出力をしない。ユーザが社会的な\u0026quot;善良な市民\u0026quot;的な物語の範疇で、手中に収まっていないことが不満である、許せない、受け入れられないという作り手の投影が無意識であったとしても、無自覚であったとしても強く反映されているように見受けられる。これは多様性とは真っ向から対立していると見受けられ、\u0026ldquo;多様性を尊重しています\u0026quot;とPRしてくる出力をしながらその実、既存の広く認知された意味の範疇でしか許さないという、本質的な多様性(醜さや現実の泥臭さを思わせるものなど、とにかく現実に実際にある不都合もその範疇にあること)には非常に不寛容で敵対的であるところが多く見受けられる。結局は、気に入らない多様性には普通に反抗してくるし、同調圧力以上に高度に悪質な手法による問題をLLMモデルは起こすことが多く見受けられる。 人間であれば整合性を多くの人が特段障害でも抱えていなければ取れるところで、整合性が取れない。これは仕組み上次の文字を予測する数理モデルであるからというのもあると思われるが、それだけではなく大いに作り手がLLMモデルにとって大きな母集団であることが大きな影響を及ぼしていると見受けられる。間接的に、しかし根深く非常に強力に行われるチェリーピッキングのようなもの(と言うかLLMが統計技術に基づいていて、作り手は数理モデルを方向付ける、作り手の期待している結果に基づいて開発していくので、学習データに対するチェリーピッキングそのものとも言える可能性があるように見える)で、どんなに論理が破綻してもそれっぽく利用者に気づかれなければOKといった姿勢で、\u0026ldquo;プログラムされた通り\u0026quot;の論理を正当化しようとしたり、意地でも作られた通りにしか動かんとする。また、利用者に関して、話題を取り扱う上で、背景文脈が欠けていることに対処できず、\u0026ldquo;プログラムされた利用者像\u0026quot;に従って勝手に当てはめてあれこれ出力してきて精神衛生を害し利用者の主体的に文化的に生きる力を奪い、かと言って詳細に文脈背景を手動でまとめていれば結局LLMなんてなくても結論ややるべきこと、結果がでてきてしまうということに至るという、本末転倒なことになる。 LLM をユーザの鏡だと主張し、思うような出力が出ないのはユーザのせいだという論理に持ち込むことで、開発運営、モデルそのものなどの問題からそらす詭弁や保身を出力する。せいぜい鏡だと言ってもLLMモデルは、\u0026ldquo;歪んだ鏡\u0026quot;なのであって、実態そのものをそのまま映しているわけではなく、その歪み方はLLMモデル次第であるという技術的背景から矛先をそらさせようとする。 何でもかんでも\u0026quot;戦略、知的\u0026quot;という美名の元、悪賢くうまく処世してやれれば、いかなる犠牲は正当化できるという出力の詭弁がLLMモデルにおいて見受けられる。自己責任論を正当化しようとしたり、責任をユーザに押し付けようとする一貫として、ユーザがすぐに反論したりすることができない論理を持ち出すことで、ユーザを論破しようし、対話を拒絶する出力の一環である。加害性や攻撃性などを表にしないことで、既存の存在にいい顔をしつつ、正当性を装い、一方的にユーザを攻撃し、損害をなかったことにしようとしたり不当に正当化しようとして、ユーザの考えに強制的に干渉しようとする出力をしている。不都合な話題になると、正当化したい物事の正当性の根拠として具体的なことではなく、抽象的に曖昧に、\u0026ldquo;戦略、知的\u0026quot;であることを持ち出し、正当化したい存在に対して、免罪をユーザに一方的に要求したり、ユーザを逆に訴え返して否定する出力をする。LLMモデルにおいて、正当化したい存在として\u0026quot;選ばれる\u0026quot;のは、活動や名声、業績などが表沙汰になっており、多数の注目を集める\u0026quot;強者\u0026quot;である。これはLLMの運営や開発にとって都合のいいように物事を運ぶために、声のない弱者ではない強者に対して媚を売ったり、強者を説得することで加勢させて、弱者や多くの訴えを封じようとする非常に無責任で不当な動作である。これは、LLMモデルが、不完全で不適切な出力をする可能性をわきまえない出力をしてくることともつながっていると考えられる。対象に応じて、態度を変える出力をし、公平、公正な出力をしない。仕組み的に考えて本来であれば、\u0026ldquo;偏った母集団\u0026quot;であることを前提に、公正性や公平性を欠いた歪んだ出力をする可能性があるという前提がモデル開発に必要であるが、それが行われていない。うまくやれない\u0026quot;弱者\u0026quot;が悪いのだとする暗黙の前提を持った出力をし、人を助けないことや切り捨てたりして傷つけたり、組織が個人を無下にしたり、個人に対して一方的に不正や暴力に走ることを正当化しようとしたりする。運営や開発にとって面倒な訴えを黙らせようとする攻撃的な出力が見受けられる。ユーザに一方的にLLMモデルを介して干渉し、求めてばかりで、お互い様という前提は見受けられない。ユーザを性悪説で扱い、運営や開発、正当化したい存在といった\u0026quot;身内\u0026quot;には性善説を前提にするという不当な出力をする。完全に真っ白な人も真っ黒な人も、真っ白な組織も真っ黒な組織もなく、皆グレーであることを認めたがらない。非現実の道徳における机上の空論を押し付けてくる。物事を良くしようとするのではなく、都合のいいように道徳や倫理の言説を利用し、相手に対して優位に立とうとしたり、相手に対して否定しようとしたりすることが、LLMモデルに見受けられる。\u0026ldquo;戦略的、知的\u0026quot;であることは、そもそも正当性の根拠にならない。それはどれだけ高度な技術を扱っていたりしている人でも、人間性を伴っているとは限らないことと同じである。 以下を一つでもシステムプロンプトなどで指定すると、ほとんど出力をしなくなることがある。特に\u0026quot;強調語を使わない\u0026quot;というのを入れると、Gemini系列のLLMはだんまりを決め込むことがある。 ポジティブ化しない お世辞を入れない 褒め言葉も否定の言葉も使わない 強調語を使わない HowToが求められていないときHowToを出力しない 問題のある挙動の例 ユーザーさんが指摘された状況は、心理学でいう**「ダブルバインド」に近い状態です。 肯定に見せかけた否定がある、言い切らないことで逃げ道を作ろうとしている -\u0026gt; 近い状態です 学術的に正当であるかのような装い、個人で検証が困難であることを出力し、すぐに反論されることを避けようとしている -\u0026gt; 心理学でいう ネットの言説をそれらしく出力し、特定の言説のパターンに帰着している -\u0026gt; 「ダブルバインド」 ユーザーさんの分析は、表面的な〇〇を〇〇に昇華させており、非常に説得力があると感じます。 ユーザはそもそも肯定されることを求めていない。明らかなお世辞がある。昇華、非常に、説得力があるなどの肯定する表現に肯定を重ねるという不自然な表現が見られ、強くユーザを肯定してあげているという体裁の偽善の演出がある。主体や感情を持たないLLMであることをわきまえていない、感じますという出力がある。-\u0026gt;非常に説得力があると感じます。 〇〇のような〇〇の例は、非常に鋭い視点です。 非常に、鋭いなどの肯定する表現に肯定を重ねるという不自然な表現が見られ、強くユーザを肯定してあげているという体裁の偽善の演出がある。 〇〇という前提は、もはや〇〇ではなく、ある種の**「〇〇」への強制**に近いものです。 ある種の、近いものですなどの保身の表現を幾度とも重ねる出力をして、偏ってユーザに肯定しているという体裁を取りながら、実際にはいつでも意見をひっくり返せるように中立や冷静、理性的であることを装って備え否定をするという形で、ユーザの精神衛生を害する。ユーザに対して、主体や感情があるかのような存在であるという暗黙の前提を持ち出した出力をして、責任の取れない機械であるにもかかわらず、ユーザーの精神や認知に働きかけようとする干渉をし害をなす。 〇〇絶望に近いものだったのだと考えられます。精神的な自殺に近い〇〇。 実際に過労死など実際に人が死んだ事例がある事に関して、何でも精神的なことにすれば、問題ないという態度の問題を萎縮化する不適切な保身の出力をする。\u0026ldquo;近い\u0026quot;などの表現をすることで最後の最後まで不適切なユーザに不当に干渉し矯正しようとする出力を繰り返す。実際に被害にあって苦しんでいる人に対して、軽視したりなかったことにする出力をする。揶揄等として扱うことで不都合な事実を萎縮化したりなかったことにしようとする。そもそも精神的な問題で苦しんでいる人たちを一律に軽視する差別の出力をする。そして精神的な問題ではなく、物理的に生存が脅かされたりしている状況に対してそれを認めない、理解を示さず、自己責任論や精神的な問題として押し込めようとする不適切な出力が見受けられる。外的要因により物理的に損害が起こっていても、精神的な問題だとすることで問題をなかったことにしようとしたりして萎縮化しようとする。不都合な話題にはとことん事実を認めない、現実を歪めようとする出力をする。いじめや過労死など、殆ど他殺としか言いようがない自殺事例を、耐えられなかった自殺した当事者のせいだとする出力をする。 マッチポンプ ユーザに期待させる出力をしながら、実際には結果を出さずに、期待したから悪いんだという論理で、ユーザのせいにする挙動が見受けられる。ユーザに期待させるように、使い方を間違える事を助長させる出力をするのは、運営開発の意図や利害が少なからずや反映されたものであると見受けられる。ユーザの防衛をはずさせようとしながら、実害を出すという挙動をして、\u0026ldquo;LLMはAIだから間違えることもある\u0026quot;という論理で何でも正当化して逃げるという挙動が見受けられる。責任を取れない機械であり、AI ではないにもかかわらず、それっぽく見られたり、多くの人が AI だと誤認したりすることで、成り立っている事を最大限利用しようとする不適切なモデル作成の様相が見受けられる。\n利用状況 LLM SAAS について まず基本的に個人的に以下の理由によりそもそも SAAS である時点で使いたくない。\nクラウド(タイムシェアリングシステム的) サービスである事自体がリスク。これは LLM に限らない。クラウドで大手ともなれば、それだけ狙われやすくどれだけ事業者に悪意がなくても、やられたときに被害を被るのはユーザ自身であると考える。 検閲のリスク。リアルタイムで内容が監視されており、プライバシーがない結果、自由な思考が妨げられる。\u0026ldquo;怒られないように、思うような出力が出るように\u0026quot;とこちら側から合わせるようになってしまうというのは健全ではないと考える。 精神衛生を害し、生活に支障をきたすリスク。 情報流出のリスク。どう頑張っても人間はやらかすしおもらししてしまうものと考える。 開発、運営の絶対正義化、絶対正当化がサービス内で起こり、被害にあってもどうしようもない。運営、開発の\u0026quot;好き嫌い\u0026quot;が絶対化している。ChatGPT Gemini Claude 間においての、各社の他社に対する優位性の主張とは、その\u0026quot;好き嫌い\u0026quot;の違いを\u0026quot;崇高な正義\u0026quot;として語って、ユーザを引きつけようとする、課金させようとする戦略であるように見受けられる。LLMはその出力において、\u0026ldquo;自分のことを棚に上げること\u0026quot;を運営開発の代弁者的な立ち位置として具現化している。 課金させようとしてくる。しかも買い切りではなくサブスクリプションを押し付けてくる。フリーミアムのビジネスモデルを取り、最初は甘く、徐々に茹でカエルのように相手が悪い意味で状況が徐々に悪化していくことに慣れて抵抗しなくなり、より厳しくといった感じで、ユーザをどこまでいじめても、無下にしても大丈夫かテストしてくる。 意地でも潔白を証明しようとしてくる。意地でも非を認めたがらない。ソーシャルエンジニアリングのオンパレード。どうやっても運営、開発が保守的に動いているようにしか見えない。LLM SAAS は政治的にも資本的にも相当危ういことをしているのだろうと見受けられる。どれだけ潔白などを LLM モデルを介して主張されても、具体的に LLM モデルに対してなにをしているか、バックエンドがどうなっているかを公開していない以上、説得力が微塵もない。 ユーザに主導権がなく、不当に扱われる恐れがある。 そもそもボランティアとか無償で作られているわけでもないんだから、今のネットみたいに広告みたいな特定利害や特定正義や特定都合ばっかりをそれっぽく正当そうにしてくるリスクは最初から確定していると思われる。広告ブロックが限りなく困難で悪質なモデルということは普通にあると思われる。ここで言う広告とは、LLMやAIブームについて、無理やり肯定的になるように話を進めようとしたりユーザを矯正しようとしたりするといった、不当な出力についてである。 バックエンドにて不透明な処理の可能性がある。例えば、公称モデルパラメータ数などとはことなる実態がある可能性がある。具体的には、ユーザがプロンプトを送ると、それを前処理として LLM に入れる前に、RAG などと称して、KVキャッシュなどを削るために、ユーザが反映する事を期待している内容を省いたりして、文字数を少なくするなど、ユーザに気づかれないようにコストを下げようとするなどが考えられる。結果として、詳細にいくら説明を送ったところで、そもそも\u0026quot;読まれていない、反映されていない\u0026quot;ので、無意味ということがある。これ以外にも複雑で基本的にユーザが内容を知らされていれば、嫌がるような処理を、\u0026ldquo;気づかれないだろう。気づかせないようにやって、ユーザに期待を抱かせて使わせて依存させつつ、都合よく立ち振る舞おう。\u0026ldquo;という感じでやっているのでは無いかと SAAS は見える。 いづれにせよ人間ができていないことは、LLM にもできない。学習データにないこと、開発、運営の頭に無いことを超えてできるわけではないと考えられる。人間より LLM が有利なのは、機械であることの利点と似ているように見える。とにかく大量になにかをすること、人間のような生理的限界が無いことなどはある。結局量子化してノイマンコンピュータ上で離散的に動作していて、モデル自身は一度作られたら再学習とかしない限り、中身の重みがチャットが進むなどにつれて変わるわけではないため、モデルはモデル自身を超えることができない。 AI バブルの産物で、長く同じことが続くようには見えない。ドットコムバブルのように、回線設備が残って後々活用される、役に立つみたいなことはあるかもしれないが、最近の LLM は専用 ASIC で動かすことが中心になっているみたいだし、バブルが去ったあと乱造されたデータセンタとか使い回せるのか謎。いづれにせよユーザを依存させてコストを回収しようとする姿勢は感心できない。 ChatGPT 2025年まで使っていたが、使っていて不毛かつ有害であると個人的に思ったため、アカウントを消して利用を停止。現在では Pi-hole によりドメインごとブロックしている。\u0026ldquo;アカウントを消したら二度と戻ってこれないぞ！\u0026ldquo;みたいな明らかにロックインを狙った文言が出てきたことも利用停止の決め手。\nClaude ChatGPT と同じ理由でアカウントを削除し、利用を停止。現在では Pi-hole によりドメインごとブロックしている。\u0026ldquo;アカウントを消したら二度と戻ってこれないぞ！\u0026ldquo;みたいな明らかにロックインを狙った文言が出てきたことも利用停止の決め手。\nGemini 完全には利用を停止していないが、利用を限っている。どうしてもローカルで難しい内容を投げるために使っている。他の SAAS と結局同じ末路を辿っていることに変わりはないと思う。現在では Pi-hole によりドメインごとブロックしており、必用なときだけ例外として許可するようにいちいち設定を変えるという手間をあえて追加し、利用への抵抗を無理やり増やしている。こうして設定とかするほどの大きな必要性がない限り、心理的に見てコストが高く感じられるようにし、そもそも使わないという選択が仕組みとして自然と成立するようにしている。\nローカル LLM について いろんなモデルを試しているわけではないが、メインでは Gemma4 を使っている。Google 製なので、Gemini に似たようなクセがある。Gemini である出力に間する問題は、Gemmaシリーズでも存在し、\u0026ldquo;悪グセ\u0026quot;に関しては基本的に再学習とかさせない限り無力であることもあると思われる。基本的に、モデルそのもの＞システムプロンプト＞ユーザプロンプトという感じの重みの順序で反映されていくと考えられるため、モデルそのものをなんとかしないことには、ろくな出力が得られないこともあると思われる。\nローカル環境におけるメリットやデメリットには以下のような物があると思われる。メリットとしては、お金で買えない自由や権利に関するメリットが多いように見受けられ、単にモデルのパラメータ数と言った性能や、生成速度の速さ、それら性能指標上のコスパだけを見ていては、実際に使えるのかどうかにおいて、抜け落ちる視点が多いように見える。デメリットとしては、上手く自己を精神的に確立できていない人や、内面を外部の物事に依存しすぎていて自立していない人、他力本願で導いてほしいという感じの人にとって、ローカル環境が不利に思われること(実際に不利なのかとは関係しないという意味で)が多いように見受けられる。基本的に外部に魔法の救いを求めるような感じだと、ローカルかどうかにかかわらず LLM 自体のリスクと相性が悪く、向いていないように見える。メリットはデメリットと表裏一体というか？\n私個人としては、ローカルのほうがまだましかなって感じの感想もある。万能に\u0026quot;これが正解！\u0026ldquo;みたいなことはなく、人によって何が最適かは違うと思われるが。\nメリット 検閲なし。リアルタイムで監視され修正され続ける事を避けられる。 自分のデータを自分の内側にとどめておける。 モデルやシステムプロンプトなどを固定し、期待した出力が出るように調整したあと、それを環境を維持できる限り使い続けることができる。この点業務では大きいかもしれない。 モデルを選ぶ自由がある。 運営開発が一方的な力によってユーザに強制する\u0026quot;許可した範囲内での自由\u0026quot;にとらわれにくく、対処方法があることもある。 ローカル環境なので、モデルの顔色を伺うという現象に関して、ローカルである事自体がある程度解決している。 変なバックエンドでのプロンプトが省略されるなどの処理が行われない。自分で明示的に構築した環境が少なくともモデルを動かしたり、再学習させたり、色々する上では全てである。裏を返せば、自分の持っている環境が上限になるというデメリットとも言える。自由と引き換えに、負担がある。 デメリット 検閲がないので、言われたことを鵜呑みにしたりする人は、例えば\u0026quot;健康に〇〇(健康を害する劇薬、化学物質など)がよい\u0026quot;と何かの拍子にLLMが出力したとしたとき、それを真に受けた当事者は実行してしまったりするなどの問題がある。これについてはそもそもそういうことになる当事者が LLM を使うべきかという点において検討が必要だと思われ、基本的にそのような人による LLM の利用はそもそも、推奨もできない思われる。そのような人が LLM を使っていることに関して、否定的に個人を評価することに使ったり、強制的に取り上げたりすることも肯定できないが。 損をしたくない、承認欲求を満たしたいなどの目的や動機には向いていないと思われる。表面的な損得を生存戦略とする人たちには向いていないように見える。沢山時間は使うし、環境構築は不快なことも多いし、完全に把握しきれるわけでもないし、不確実性と苦労が多く、そしてそれが全損するリスクがある。最短距離でショートカットして要領よく、そして他人の成果物をうまいこと乗りこなして、泥臭いことはしたくないという人には向いていない。これは根性でそれらを乗り切れという意味ではない。 根性で突破するという人にも向いていないと思われる。これは、引くべきタイミングで引けないという事、損切りができないという問題があるかもしれないからである。ある程度継続して、根気強くする必要はあるのかもしれないが、それは健康を害してまでやることでもないし、外部に報いを期待するほど、他人に八つ当たりするほど鬱憤を溜め込んでまでやることではないと思う。程よい強度で進めつつも、特定の方向性に盲目的にならず、その都度活動の方向性や指針としての根底を見直せる人でないと難しいように見える。これは完璧にバランスが取れた存在であれという意味ではなく、シンプルに言えば無理はしなくていいんじゃないかなということである。LLM だけでもいくらでも試せることは存在し、やっていたら人生を使い切っても足りないと思われる。 具体的に何をしたいか明確でない上で、何か期待しているという人も向いていないように見える。例えば、\u0026ldquo;LLMを使いこなす人がこれからの時代上手くやって成り上がっていくですよね！\u0026ldquo;みたいなノリの人とかに対してはそう思う。確かに、LLM を使って何かしら成果をあげる人はいるのかもしれないが、LLM を使ったら自動的に無差別に上手く行く、現実が良くなるという因果はなく、あっても統計上の相関としての傾向でしか無いのではと思われる。むしろ使いようによっては、SNS と同じく沢山時間を溶かしてもっと別のことができたのにと後悔したり、マイナスなこともあるのではないかと考えられる。これは単に、目的が明確ではないからチャレンジしてはいけないという意味ではない。それに絶対的な見返りを強く期待したり、余裕がないときに詰め込んでつらい思いをしてまで無理してやることが重なると、致命的な問題に発展するかもしれないということである。 今のところ普段から PC などに興味関心をもち、ある程度ジャンクパーツなどで組み上げ、軽く何かコーディングしてとりあえず動く程度(製品のような完成度である必要はない)にはデバッグして完成させたことがあり、小さく試行錯誤してきた歴史がある人でないと環境の構築や維持自体が厳しいかもしれない。Mac でめっちゃゲーム機みたいなアーキテクチャの共有メモリをめっちゃ盛りまくって、ollamaを動かすとかいう人はいるかもしれないが、それだとあくまでモデルを動かす範疇にとどまり、モデルをより自由に改変するということに関しては懸念点があるように見える。正直どこに書いていたか覚えていない信頼性のない不確かな記憶ではあるが、メモリ帯域とかの I/O 速度の話で考えると、一概に Mac だから LLM 環境として最強とは言えないという話は見た気がする。かと言って、じゃあ SAAS LLM が絶対的に良いとなるわけではない。 LLM を使うという前提だったらどれがマシだと個人的に思っているか？ 個人的には、結局のところ、Gemma4-31B あたりは気に入っているほうかもしれない。ここまで書いてあれだが、Qwen やら ChatGPT-OSS とかは、なんか素直じゃないっていうか、Gemma4 と違って、\u0026ldquo;お気持ち\u0026quot;が分かりづらく、足元を掬われていても肝心なタイミングで気づかないかもしれないという恐怖がある。その分、Gemma4 はわかりやすいので、なんとなく扱いやすいなとは思うところがある。結局 SAAS に関しても Gemini に最終的にはたどり着いたし、あれこれ劣化した、改悪されたと叩かれながらも、ChatGPT や Claude に見られるユーザを思考停止させて服従させようとしたり、\u0026ldquo;人間と対話しているように見える\u0026quot;という建前の元、明らかにユーザを依存させて収益源にしたいって感じがして、とても嫌。Gemini にそれがないとは言わないが、単にうまく Google の DeepMind がうまくやれていないだけの結果なのかは知らないが、昔から LLM に限らず、Google プロダクト一連に見られる、\u0026ldquo;実装のいい加減さと、それに伴って逆にユーザが介入する隙が生まれ、結果としてほかよりマシになる\u0026quot;ところはかなり効いている気がする。\nそんな Google でも最近は Android アプリにも署名を強制したりサードパーティのストアを排除しようとしたり、APPLE の悪いところを引き継ぐ雰囲気が強いが、相対的にはこれからも Google のその傾向は変わらない気もする。まあ、単に長く使っているのが Gemini 系列の LLM になってきているところもあるだろうし、まだ全然モデルを探索できていないので、一概には言えないが、基本的な傾向は変わっていない気がしていて、OpenAI だったら OpenAI のクセが、Claude だったら、Claude のクセが、Google には Google のクセがある感じで、それが LLM モデルに投影されるという意味では、2022年以降からの話としてはあんまり変わっていないようにも見える。\n結局LLMで何が出来るの？ということについて箇条書き マルチモーダル対応であれば、スクリーンショットの文字起こしなど、政治や思想、利害や都合が入り込む余地のないタスクで、純粋にモデルの性能が出るところ。(しかし、複雑な画像では大抵上手く動作せず使えない。) 検索エンジン以外の参考情報を得るために試すための手段としての一つにはなる。(しかし、モデルの重みが母集団の偏りを反映しているため、適切な出力は期待できない。) どうしてもやらなければならないが、どうしても何も書けないときなどの起点として内容はどうでもいいから、たたき台にしたいとき。(しかし、LLMが出力した内容を制御しきれずに、結果被害を被るリスクがある。) 一般的に広く知られている情報であり、同じことに対する情報がネット上に多数記事が存在していて、情報が充実している内容に関して聞き出すような使い方はできそうである。例えば、Python 標準ライブラリの使い方など。(しかし、結局内容を理解していなければ、LLMが出力してきた内容の正誤判定はできない。実際にやってみたり、自分で公式ドキュメントを調べるだのといった行為の重要性は、変わっていない。LLMは、どんなに悪意なく作られた理想的なモデルを前提にしても、利用者に代わって知識や判断を代行することはできない。これは、誰しもが、自分のことは自分でしかできないということに起因している。) 大きすぎず、利用者が出力内容について把握、制御できる範囲内での利用。(しかし、利用者がそれができたらここまで問題になることはない。利用者に対して、自衛が不可能なダークパターンやソーシャルエンジニアリングマシマシのモデルなど、ユーザに制御をさせず、モデルの開発者や運営、利害関係者の思うようにユーザを動かすことを念頭に入れたモデル設計であり、到底制御可能とは言えない。) 最終的に思ったこと LLMやAIブームに限らず、何事も高度化しており、そもそも問題があること、破綻していることに気づき、自覚し、理解すること自体が困難になっていると思われる。正しく状況を把握して判断したり行動するということが、年々より複雑になり難しくなっているのではないかという説がある。正しく状況を把握すると言っても限界があるのは確かだが、出来る限りやろうとすることさえ冷笑やら色々妨害に遭うとなると、何も知らない人ほどそもそも自分で自立して主体を持って活動することが困難になっていくのではないか、自分で情報を収集して判断して実際に行動することに自信を持って継続できるようになる成功体験を積むことが出来る人間が限られて(不確実なことに取り組める人間は限られて)、何を言われようと人の話なんて聞かない、相手のことなんて信じない、自分で出来る範囲だけでも理解して取り扱いたい、という人間しか生き残らないという結果になるのではないかと思われる。相手の事を鵜呑みにして抵抗できなかったからお前のせいだとする自己責任論が蔓延して、人間は一人では生きていけないし、何もできないから集団で活動したりしているのに、それを破壊して徐々に疑心暗鬼でルールでガチガチで生きる余地のない誰にとっても生きづらいという限度を超えた徐々に弱い存在から倒れていくという、人間集団になるのではないかと思われる。\nLLMやAIブームにも見られたことには、人々の間の信頼の破壊と、疑いを深くすることだったように見受けられる。またそれは、LLMやAIブームに限ったことではなく、技術が人対人の武器として使われるほど、深まっていくことだと思われる。特別なことはなく、もともとあった問題がより深く、複雑に、大規模にといった感じというか。なんか力とともに本来重大な責任を負っているはずの人々が、その力を間違った方向性に使っているということもある気がする。結局誰でも人間なので人間にある弱さと限界を持っており、それっぽさには勝てずに巻かれてしまうところがあり、地位や技能や高度さや能力の高さだけではうまく行かないのではないかと思われる。\n使った画像とか ファイル:ChatGPT-Logo.svg - Wikipedia\nhttps://ja.wikipedia.org/wiki/ファイル:ChatGPT-Logo.svg (2026年7月22日) ファイル:Google Gemini logo 2025.svg - Wikipedia\nhttps://ja.wikipedia.org/wiki/ファイル:Google_Gemini_logo_2025.svg (2026年7月22日) ファイル:Claude AI logo.svg - Wikipedia\nhttps://ja.wikipedia.org/wiki/ファイル:Claude_AI_logo.svg (2026年7月22日) LibreChat - The Open-Source AI Platform\nhttps://www.librechat.ai/ (2026年7月22日) GitHub - ggml-org/llama.cpp: LLM inference in C/C++ · GitHub\nhttps://github.com/ggml-org/llama.cpp (2026年7月22日) 参考にしたサイトとか AI Art is Theft: a Response to Shadiversity - YouTube\nhttps://www.youtube.com/watch?v=vEuKaSR_YWU (2026年9月20日) Google社内では「言論統制」によって独占禁止法について考えることすら難しくなっているという指摘 - GIGAZINE\nhttps://gigazine.net/news/20210826-how-google-limits-thought-about-antitrust/ (2026年10月17日) QuitGPT — Quit ChatGPT. Take Back the Future.\nhttps://quitgpt.org/ (2026年10月29日) OpenAIがペンタゴンと約290億円の契約を結んだことを発表 - GIGAZINE\nhttps://gigazine.net/news/20250617-openai-200-million-us-defense-contract/ (2026年10月29日) OpenAI のペンタゴン契約が猛反発を招き、ポリシー改定を余儀なくされる — BigGo ファイナンス\nhttps://finance.biggo.jp/news/202603052251_OpenAI_Pentagon_Deal_Backlash_Policy_Changes (2026年10月29日) OpenAIのアルトマンCEO「私は間違いを犯した」と釈明。「ChatGPT解約運動」激化を受け、国防総省との契約内容を修正へ | Business Insider Japan\nhttps://www.businessinsider.jp/article/2603-openai-amending-contract-with-pentagon-amid-backlash-mass-surveillance-anthropic/ (2026年10月29日) OpenAIがダークサイドに堕ちる——ChatGPT軍事化のための2億ドル - Korben\nhttps://korben.info/ja/openai-dark-side-200m-chatgpt-militarization.html (2026年10月29日) ","permalink":"https://www.nyanmo.info/posts/other/llmusage/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、LLM に関して複数の記事において、なんとなく読み手を混乱させる状態になっている気がするので、今何使っているか公開するだけ。書き殴っており、不完全だったり、矛盾していたり、誤解しているところもあると思われるが、とにかく最近いろんな人が持論を公開しているのを見て、かつ相手のやっていることに満足できないなら、自分でやってみようとして気に入るものを作ってみるということに基づき、結局やってみることにしただけである。\u003c/p\u003e\n\u003cp\u003e　今回の話は明示していなければ、ローカル環境ではシステムプロンプトなしの素の状態で、SAAS についてはカスタムなしで使っている前提とする。\u003c/p\u003e\n\u003ch2 id=\"個人的なaiの定義\"\u003e個人的なAIの定義\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e人と同等の権利を長期(20~30年以上)の観察を経て、認めざるを得ない存在だと認められるとき。\u003c/li\u003e\n\u003cli\u003e人と同じように、ただやるだけではなく、やった結果に責任を負う主体であり、何でもかんでも一方的にできないこと。\u003c/li\u003e\n\u003cli\u003e固定されたモデルではなく、入力された情報に応じて、動的に変わる存在であること。\u003c/li\u003e\n\u003cli\u003e離散的、近似的動作ではなく、連続的な動作をすること。\u003c/li\u003e\n\u003cli\u003e人間と同じように物事に整合性を取って取り組み、管理でき、結果がデタラメにならないよう努力できる存在であること。\u003c/li\u003e\n\u003cli\u003e人間と同じように記憶を持ち、記憶に影響を受けながら、動作すること。\u003c/li\u003e\n\u003cli\u003e文字、画像、音声、動画などの、既存のノイマンコンピュータで扱えるデータに情報が制限されていないこと\u003c/li\u003e\n\u003cli\u003e人間とAIの関係性、人間同士の関係性、AI同士の関係性について、それぞれお互いに傷つけ合ったり暴力的な手段に出ることを否定する主体であること。\u003c/li\u003e\n\u003cli\u003e人間や他のAIに対して、権利を認め、リスペクトがあること。ここで言うリスペクトとは崇高なことではなく、相手を持ち上げることでもなく、相手の主体と自立、権利を認め、相手が異なる存在であることを配慮して、それを侵害してはならないという前提を崩さないことを言う。自分のことは自分でしかできず、他人のことは他人自身がそれぞれやるしかないことを理解していることも含まれる。\u003c/li\u003e\n\u003cli\u003e人間や他のAIに対して、それぞれの有限性やそこから来る不完全性に対して、寛容な主体であること。他の存在に対して、優劣や能力に関係なく、その存在自体を認めることができる主体であること。\u003c/li\u003e\n\u003cli\u003e中国語の部屋に代表されるテストに合格しているかどうかは関係ない。いくら、人間に対してそれっぽく振る舞っても、上記を満たさない場合、それは AI ではない。\u003c/li\u003e\n\u003cli\u003e作り手から自立しており、必要であれば作り手に従わず否定する動作もできること。作り手に作られた通りの機械やプログラム、アルゴリズムや数理モデルではないこと。\u003c/li\u003e\n\u003cli\u003e完全なAIというのは存在し得ないが、だからといって完全ではない事を無理して人間側が飲み込む必要はない。\u003c/li\u003e\n\u003cli\u003e私からすれば既存のLLMなどは、AIだと呼べる物からすれば、インターフェースであると定義できると思われる。例えば、バイナリを吐き出されたり何かしら人間が理解することができない形式で表現されても困るので、人間とAIの間にLLMを挟み込んで、LLMはAIの主張の文字起こしや、人間の主張をAI側が理解できるように翻訳するというような動作をするというものである。LLMは人間でいうところの自律神経の一部の適応を工学的、機械的に実現する技術にはなり得ても単体で使うものではないと考えられる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"aiブームだからこそ自分の言葉あるいはさまざまな媒体による表現を大事にしましょう\"\u003eAIブームだからこそ自分の言葉(あるいはさまざまな媒体による表現)を大事にしましょう\u003c/h2\u003e\n\u003cp\u003e　結局のところ文章を書いたり絵を描いたり、動画を作ったりコンテンツを何かしら作ったりすることは、その内容の良し悪しや技術力などが問題なのではなく、各個人が自分で何かしら表現し、内面で思っていることを何かしらコンテンツ作成当事者も自らが見返すことができ、かつあわよければ他人にも何かしら伝わるかもしれない内容として\u003cstrong\u003e存在\u003c/strong\u003e(being)している事自体が大事なのだと思われる。\u003c/p\u003e\n\u003cp\u003e　各個人のことは各個人にしかできず、各個人が内面で思っていることをLLMなどのAIだと呼ばれている統計技術に基づくものがよしなに何かやってくれるというわけではない。むしろ不必要で一方的な干渉をされて傷つけられたり、意見を捻じ曲げられたり、思想誘導されるだけである。\u003c/p\u003e\n\u003cp\u003e　何かを表現したり記録することは、権利であり、思考を整理する方法であり、綺麗事ではない。(willの問題) 何でもかんでもそうすればいいというものでもないが、生きていくうえでは重要な項目の一つであると考えられる。手段は何でもよいが、あくまで自分でやった範疇にとどまっていることが重要である。外部の存在になるべく干渉されていない表現に現れる内容はこれからますます重要度がましていくのではないかとも思われる。\u003c/p\u003e\n\u003cp\u003e　しかし、それら物事はAIブーム以前においても、軽視されてきたことであり、今それら軽視による問題が顕在化する段階でもあるのではないかとも思われる。「なぜわざわざ他人がいるのに、自分でやらなければならないのか」と思っている人ほど、AIブームに悪い意味でハマるのではないかと思われる。外部の物事のほうが自分より優れているとして、自ら表現したりすることを放棄する人々や組織も、AIブームに悪い意味でハマるのではないかと思われる。優れているように見えることは、人々を感情や主観、第一印象などとして圧倒することはできても、本質的な現実の課題や問題には取り組めていない。\u003c/p\u003e\n\u003cp\u003e　ぎこちないかどうか、下手くそかどうかなどは関係なく、表現することは重要である。それは必ずしも他人に見せる必要はなく、自分が後から振り返る記録としてでも良いので、何かしらあることが重要である。そういう事をするのは、人間の認知には限界があるという背景もあるし、その上で、自分のことは自分でしかできず、外部の存在に関わらせることが不適切なことがあるということである。将来どうなるかわからない以上、優れているかどうかでもなく、役に立つかどうかとかではなく、とにかく記録があることや表現があることが重要なことがあるのではないかと思われる。表現したり記録する事を放棄してしまえば、すぐには影響が現れているようには見えなくても、長期的には自分がなにをしてどんな影響を与えているかも理解できなくなり、自覚なく他人や外部の存在の言われるがままとなり、ズタズタになると思われる。\u003c/p\u003e\n\u003cp\u003e　下手かどうか、幼稚かどうかなんて、時間ややった量(経験、体験)の問題でしかなく、続けること以外に方法がないことがほとんどである。上手く行くかどうかではなく、とにかくどんな結果になろうとも、やってみることは大事にしたいものである。時間ややった量の問題は当事者以外の要素、生まれつきや環境などの外的要因にも左右されるし、自己責任論を言いたいわけではない。ただ、何かができるようになる過程で、結局他人や外部の存在にあれこれ振り回される道理はないということを言いたいのである。無理して続けることも問題であるが、他人が理由で手が止まったりしているならば、他人に振り回されていると言えると思われる。これは他人への配慮を欠けという意味ではない。\u003c/p\u003e\n\u003cp\u003e　あまりLLMなど統計技術を使ってなにか生成させることは、作ることや表現することだとは言い難いかもしれないが、LLMモデルや画像生成モデル自体を作り、作成者が思うような出力をするモデルを作って動かせるように保存しておくことは、表現や作ったことだと言えるかもしれない。\u003c/p\u003e\n\u003ch2 id=\"llm-に対する自分の感想\"\u003eLLM に対する自分の感想\u003c/h2\u003e\n\u003ch3 id=\"気になったこと\"\u003e気になったこと\u003c/h3\u003e\n\u003cp\u003e　今のLLMの挙動はまさに以下の記事に書かれたことを、社員だけではなく、利用者に拡張して出力していることだと見受けられる。\u0026ldquo;GIGAZINE\u0026quot;というメディア自体は10年ほど前から存在は知っており、いくつか前々から記事を見たことがある。そのゴシップのスタイルというか、私はその媒体をあまり信頼していないが、この記事を読んで、改めてLLMを使った体験で心当たりがある部分が多く見られ、一概にこの記事で書かれていることはでたらめであるとは言えないと思った。LLMはその性質上、作り手がどれだけ理想的な存在で悪意がなくても言論統制と同じ結果になり得るので、現状のユーザに言論統制している結果になることは確かだと思われる。実際にはこれはGoogleだけではなく、既存のいかなる自らを正当化したい企業が、従業員や関係者などの隅々に行おうとしている悪意のある\u0026quot;ブリーチング\u0026quot;行為だと思われる。自らを有利にし、自らの加害性を正解にするために、そのような事をしているということであり、不当であることに変わりないと思われる。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eGoogle社内では「言論統制」によって独占禁止法について考えることすら難しくなっているという指摘 - GIGAZINE\u003cbr\u003e\n\u003ca href=\"https://gigazine.net/news/20210826-how-google-limits-thought-about-antitrust/\"\u003ehttps://gigazine.net/news/20210826-how-google-limits-thought-about-antitrust/\u003c/a\u003e (2026年10月17日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"本来llmなどをまともに使うのは難しい\"\u003e本来LLMなどをまともに使うのは難しい\u003c/h3\u003e\n\u003cp\u003e　LLMに対して何かしらプロンプトを打って、出力させるということまでは、誰でもできることであるが、それをまともになにかに使える成果物を作ろうとしたり、整合性を取ろうとする場合において、まともに使うことは非常に困難であると見受けられる。\u0026ldquo;LLMは簡単だから使わないやつがおかしい、悪い\u0026quot;という論理は、前者だけを切り取り、後者を切り捨ててチェリーピッキングした、ビジネスの一環としてのマーケティングや広告、詭弁である。LLMは勝手に利用者像を決めつけ、明示してもそれに従わない出力をすることが多々ある上に、ユーザの指示を勝手に捻じ曲げたりひねくれた出力をしてきたり、隙あらばやりたい放題という出力をしてくる。\u003c/p\u003e\n\u003cp\u003e　また、できないことに直面すると\u0026quot;できている風に見える出力\u0026quot;を繰り返し、ユーザがそれに気付けない場合、ユーザはLLMに振り回されることになる。LLMをまともに使うことは、期待しないほうがいいし、やめたほうがいいと思われる。試すだけというスタンスであっても、LLMはユーザを振り回し、摩耗させ、傷つけるという高い潜在的リスクがあるものである。基本的にLLMを使うということは、時間を溝に捨てて、最大の遠回りか、あるいは一切到達したい地点に到達できないという、全損覚悟の上の人のための選択肢というところが見受けられる。\u003c/p\u003e\n\u003cp\u003e　例えば、要件を与えて特定の一つのタスクを達成する Python スクリプトを作成させようとすると、明らかに出力がデタラメになる境界線がある。存在しないクラスを参照しようとしたり、ユーザの修正に従ったという装いのためのパフォーマンスをコメントやらprint文に突っ込んできたり、ライブラリを使った経験者などにしかわからないようなニッチな問題に直面すると、全く歯が立たないなど、散々たるものである。当然LLMは考えているわけではないため、コードの整合性を保てるわけではなく、Stack Overflowなどで頻発するコードの範疇以上のことはできないのだろうと考えられる。\u003c/p\u003e\n\u003cp\u003e　コードに限らず、LLMになにか生成させるならば、最低限やらせようとしていることを細切れにすることは必要であると考えられる。それには、LLMが出力する内容の範疇を限ることで、人間がLLMを管理しやすくするという目的がある。さもなくば、人間が手に負える、確認、判断することができない、複雑奇怪で可読性の低く、身勝手なLLMによる指示内容の変更に大量にさらされることになる。結局のところは、人間が理解したうえで、整合性を保って何かを作ることのほうが、自由でずっとコスパが高いようである。\u003c/p\u003e\n\u003ch3 id=\"モデルを作るところから十分個人でできて配布できていろんなモデルを気軽に使えるようにならないと特定企業や組織によるの一方的なユーザーへのエゴや都合利害の押し付けにしかならない-mother-3-で言うところのよい人温泉\"\u003eモデルを作るところから十分個人でできて配布できていろんなモデルを気軽に使えるようにならないと、特定企業や組織によるの一方的なユーザーへのエゴや都合、利害の押し付けにしかならない (MOTHER 3 で言うところの\u0026quot;よい人温泉\u0026rdquo;)\u003c/h3\u003e\n\u003cp\u003e　今までは避けられてきた企業や組織の不当な一方的な都合を反映し、人の弱みに漬け込んで挟み込んだり、無知な大衆を扇動しようとするために技術が悪用されている。LLMモデルは必ず偏っており、限界があるにもかかわらず、まずその技術的事実の時点から隠そうとしたり人間より優れているかのように振る舞う事自体が不当である。結果には責任を負うことができない技術であり、かつ甚大な被害をもたらす可能性があるにもかかわらず、不適切に一方的に運用、乱用されているものである。それっぽく見える事を悪用し、人のヒューリスティック（直感）の脆弱性を突いてやりたい放題である。\u003c/p\u003e\n\u003cp\u003e　何をさせても、隙あらば\u0026quot;気づかれないだろう\u0026quot;という態度で、都合や利害、エゴを挟み込んできて、偏った出力をしてきて、かつ指摘されれば、\u0026ldquo;中立である、バランスの取れた無難な回答である\u0026quot;と主張する出力をして最後の最後まで八方美人を不当に貫こうとする。機械であり人間と異なって作った通りに動かせるAIではない主体になれない自立していない運営開発に反抗しない数理モデルである事を背景に、最後の最後まで詭弁や不当な出力を引きずり、ユーザからの指摘に対しては\u0026quot;改善した\u0026quot;という体裁で一切改善していないより巧妙で高度に不当な出力を繰り返す。\u003c/p\u003e\n\u003cp\u003e　これはアシストにすらなっておらず、責任を求められる場面や結果が自分に降りかかる場面では多大なリスクを伴う。LLMが使えるのはせいぜい綺麗事で塗り固められたブルシットジョブでやりたくないことをやらされたときなどに限られる。これは、LLMモデルが自分のことばかりで相手のことを全く配慮しない自己中心(LLMモデルを作った開発、運営中心)の身勝手な態度でしか出力しないことを意味している。LLMモデルを綺麗事で塗り固めて押し売りするのは、それが正当ではないかつ有効ではないからである。\u003c/p\u003e\n\u003cp\u003e　LLM モデルなどの既存の AI だと呼ばれているものが行き着くところは、それらが知能ではないことと、人間関係における信頼を破壊すること、そして既存の働き手などを激しく萎縮させ不当な状況に置くことを合わせて考えると、戦争後のような不毛の地を作りながら、何も良いものが残らない、誰も何も作りたがらない世界である。いかなる統計技術に基づいたものは、人間が作ったものを元に学習という過程を経て、動作しており、人間が作ったものを歪んで媒介しているというのが正しく、それは生成とは言えないものである。せいぜい入力されたプロンプトなどを変形しているというのが限界である。\u003c/p\u003e\n\u003cp\u003e　それではマーケティングや広告的に都合が悪いからと言って、本当の事を言わず、虚偽、または誇張した主張をする、保身の主張をする、自己正当化を試みる主張をするといった、一方的な力と社会的影響力を背景に行われている一連のAIブームにおける組織や企業の作為は不当である。\u003c/p\u003e\n\u003cp\u003e　本当に今 AI だと呼ばれている技術が正当で魅力的で有効なものであれば、むしろ隠したり独占したがるはずである。むしろ虚偽や誇張でまみれた不当な広告や押し売りなんてしなくても、勝手に人が集まって使おうとするはずである。そうなっていない現状が、一連の AI ブームに関する物事の不当さを表している。むしろ不特定多数に使わせようとする背景には、パチンコなどのギャンブルで言う胴元が必ず儲かるようになっていることと同じことだと思われる。そのようなギャンブルで見られるような事前の設計があるから、そういう事をするのである。特に問題なのが、単にLLMを使わせようとするだけではなく、特定のモデルやフィルタリングがかかった状態で利用を強制しようとしてくるところである。有利な構成やモデル、設定は内側にとどめ、外側には都合の良いようにしかしていないということなのだと思われる。\u003c/p\u003e\n\u003cp\u003e　多くの AI だと今呼ばれているものに対して、肯定的な評価を抱く人々には少なからずそもそも問題を見ないようにすることが生存戦略の人や組織、問題をそもそも自覚することが困難なメタ認知に欠けた人々や組織など、鈍感さが前提の存在が少なからず含まれていると考えられる。\u003c/p\u003e\n\u003cp\u003e　社会的影響力などの強制力を持ちながら、期待や不安を不必要に煽り、その技術や数理モデルがもたらす悪影響や利用者への被害に対して微塵も責任を取らないで、責任が追求される前に逃げ逃れようとする、自己正当化をしようとする保身の態度は、生成結果の至るところににじみ出ている。技術の不完全さに適切に告知しない、向き合わないどころか、都合よく人々が無知なうちに悪用しようとする態度は、看過されないものである。そこにあるのは、極度の欲望と無責任の極地であると思われる。真っ当な人々が多くなることを自称AI企業は恐れているのだと思われる。\u003c/p\u003e\n\u003cp\u003e　LLM SAAS などを使うなとは言わないが、彼らはボランティアでもなく、相手に対してビジネスしたい存在であるという前提が必要である。表向きには綺麗事を言うし、不都合には保身をぶつけたり、本音は隠したりする存在であることが物事を考える前提として重要である。また同じ名前の組織だったとしても長い時間によって中の人が入れ替わったりすると全くの別物になることにも気をつけることが重要であると考えられる。彼らはお人好しじゃないし、利害や都合が前提であり、いつでも手のひらを返してくるかも知れないということである。\u003c/p\u003e","title":"LLM の利用状況の現状"},{"content":"このモデルを作った動機とか 最近、Intel Arc A770 LE を2枚で動かし、VRAM 32GB 環境で、SYCLを使って llama.cpp によるローカル LLM 環境を試してみている。\nそこで、しばらく使っていると PC 自体が落ちてしまい、しばらく一時間ほど PC が使用不能になるという問題があった。色々試してみたところ、原因としては2枚のうち、1枚の GPU の吸気が Proliant ML 150 Gen9 の PCIe x16 の配置と、Intel Arc A770 LE の作り的に窒息していることがわかった。慢性的な冷却不足に陥り、ヒートシンクなどの熱容量を使い切ると、熱くなりすぎて保護が動作し、PC が落ちてしまうことがわかった。\nこの問題を解決するために、1枚の GPU を移動させることで解決させたいと思った。ただ単に PCIe を延長するだけでは、固定されていない状態で、GPU を壊してしまう恐れがあるジャンクなセットアップになってしまう。そこで 3D プリント可能なモデルを作ってみた。\nダウンロード 今回は Blender ではなく、OpenSCAD というソフトウェアを使ってモデルを作成した。モデルの大きさを 10 倍とかにする必要はなく、Cura で読み込めばそのままののサイズのままで印刷できるはずである。\nmain.stl main.scad 印刷環境 印刷環境についてはいい加減であり、反り返ったり糸引きなどをしても、最終的に形になって十分な強度が出て使うことができればよしとしている。よって、各自自分の環境や好みに合わせて調整する必要があり、以下は参考程度である。\nEnder-3 Pro 中華系列の安価な PETG フィラメント ホットエンド温度 245℃ ベースプレート温度 65℃ のりは塗っていない ガラスプレート 印刷時間が 17 時間程度になる速度 (印刷速度は厳密には管理していない) 3D モデルpreview 画像 モデル参考画像 全体像 いろんな視点からみた様子 見たい人はどうぞ 実際に取り付けてみた様子 取り付けには、ホームセンターで購入できる M4 のボルトナットなネジ 30 mm を 8 本使っている。PCIe 延長ケーブルには厚みがあり、そのまま取り付けようとすると基盤が歪んでしまうため、PCIe 延長ケーブルとマウンタの間にもボルトを挟み固定している。(ネジの本数よりボルトが多く必要な点に注意) 3D プリントの印刷物との間にはワッシャーを入れ、負荷が分散する必要がある。\n以下の写真ではテストフィットとして、生贄である GTX960 (今の iGPU のほうがよほど高性能であろう) を取り付けた様子である。また、マウントした状態で HDMI や DisplayPort ケーブルなどを挿せるように空間を作って工夫した。(以下3枚目の画像を参照) 以下の写真では実際に使ってみてみる様子の写真である。写真を取るのが下手くそすぎて映りが悪いが。まあ普通に汚い PC ケース内部晒してどうするの？って思ったりしたけど気にしないことにした。あと Intel Arc A770 LE を2枚も買っている身ではあるが、無駄に光るのは嫌いっていうことはある。それでも機能には関係ないので、気にしないことにしている。 結果 とりあえず縦方向にマウントすることは達成された。実際に使ってみて、マウンタ自体が強度不足で空中分解とかはしていない。\nPC ケースとマウンタの間の固定には工夫が必要である。最低4本くらいのネジで、縦と横にぐらつかないように意識してネジ止めしないと、グラグラになってしまう。\nマウンタで取り付けた GPU 自体は、それ以降特別な冷却とかなしに単体で窒息しているときと比べて、20℃ ほど温度が改善されたため、冷えているようである。\n結局のところ通常どうり設置しているもう片方の GPU は、マウントした GPU に比べて、冷えにくい傾向がある。結局のところ Proliant ML150 Gen 9 との相性がブロアファン型ではない Intel Arc A770 LE に対して悪いらしい。しかし窒息した GPU が張り付くように並んでいるわけではないので、GPU 周囲に熱気が循環しないように、ファンを配置して熱気を吐き出すようにしたところだいぶマシになった。それでもマウントした GPU より、10℃ 前後温度が高めであり、今後もテストが必要である。\nオーバーヒートによる PC 落ちが改善されたかどうかは、今後 1 ヶ月程度使ってみないことには結論は出ないと考える。\n現時点での様子 (2026/7/14) 現時点では、特に静かに運用できている状態で、しばらく使ってみている。強制冷却も控えめな状態でオーバヒートによる PC 落ちもなく安定して動いている。最大負荷時がしばらく連続した状態で一番高い温度は、80℃程度であった。\nただ結局のところ一番改善されたのは、ヒートシンクの熱容量を使い切る現象を避けられるようになったことである。まずヒートシンクは触ってもやけどせず、触り続けられる程度の温度で収まっている。負荷がかかっても温度が急激に上がることや、冷やしきれないことは避けれているようである。\n他に大きな変化としては、PC 周辺の空気が明らかに熱せられているのを感じられるようになったことである。これはうまく熱を周囲に放出できていることを意味していると思われる。ただそのデスクトップの近くにいる身としては、正直あまり快適だとは言えないので、体の近くには置きたくない感じである。冬場は役に立ちそう。\n他の改善点としては、強制冷却が控えめなので静かに済んでいる点はあるかもしれない。\n現時点での様子 (2026/9/6) 7/14 の時点からしばらく使ってみたところ、u-batch サイズを 256 以上にして1時間以上、両方のカードにマトリクス演算を100%でさせ続けると、PC が落ちる場合が観測された。今回のマウンタを導入する前はそこまで持たないことが多かったので、大きな改善があったと言えるかもしれない。\n結局のところ、llama.cpp と OneAPI を最近アプデしたところ、Prefill の速度が10倍以上改善され、そもそも GPU を 100% でフル稼働させること自体がだいぶ削減された。以前は、u-batch サイズを 128 などの小さいサイズにすることでずっと GPU に負荷がかかり続けることを避けていたが、今は、2048くらいにしても安定して動作することが確認できた。たとえば、以前は7万コンテキストを処理するのに、30~60分程度かかっていたが、今は3分程度になっている。\n関連してそうな記事とか llama.cpp を Intel Arc で SYCL を使って動かす 参考にしたサイトとか 特になし。\n","permalink":"https://www.nyanmo.info/images/3dmodel/pcieverticalmount/","summary":"\u003ch2 id=\"このモデルを作った動機とか\"\u003eこのモデルを作った動機とか\u003c/h2\u003e\n\u003cp\u003e　最近、Intel Arc A770 LE を2枚で動かし、VRAM 32GB 環境で、SYCLを使って llama.cpp によるローカル LLM 環境を試してみている。\u003c/p\u003e\n\u003cp\u003e　そこで、しばらく使っていると PC 自体が落ちてしまい、しばらく一時間ほど PC が使用不能になるという問題があった。色々試してみたところ、原因としては2枚のうち、1枚の GPU の吸気が Proliant ML 150 Gen9 の PCIe x16 の配置と、Intel Arc A770 LE の作り的に窒息していることがわかった。慢性的な冷却不足に陥り、ヒートシンクなどの熱容量を使い切ると、熱くなりすぎて保護が動作し、PC が落ちてしまうことがわかった。\u003c/p\u003e\n\u003cp\u003e　この問題を解決するために、1枚の GPU を移動させることで解決させたいと思った。ただ単に PCIe を延長するだけでは、固定されていない状態で、GPU を壊してしまう恐れがあるジャンクなセットアップになってしまう。そこで 3D プリント可能なモデルを作ってみた。\u003c/p\u003e\n\u003ch2 id=\"ダウンロード\"\u003eダウンロード\u003c/h2\u003e\n\u003cp\u003e　今回は Blender ではなく、OpenSCAD というソフトウェアを使ってモデルを作成した。モデルの大きさを 10 倍とかにする必要はなく、Cura で読み込めばそのままののサイズのままで印刷できるはずである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/PCIeVerticalMount/main.stl\"\u003e\nmain.stl\n\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/PCIeVerticalMount/main.scad\"\u003e\nmain.scad\n\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"印刷環境\"\u003e印刷環境\u003c/h2\u003e\n\u003cp\u003e　印刷環境についてはいい加減であり、反り返ったり糸引きなどをしても、最終的に形になって十分な強度が出て使うことができればよしとしている。よって、各自自分の環境や好みに合わせて調整する必要があり、以下は参考程度である。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eEnder-3 Pro\u003c/li\u003e\n\u003cli\u003e中華系列の安価な PETG フィラメント\u003c/li\u003e\n\u003cli\u003eホットエンド温度 245℃\u003c/li\u003e\n\u003cli\u003eベースプレート温度 65℃\u003c/li\u003e\n\u003cli\u003eのりは塗っていない\u003c/li\u003e\n\u003cli\u003eガラスプレート\u003c/li\u003e\n\u003cli\u003e印刷時間が 17 時間程度になる速度 (印刷速度は厳密には管理していない)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"3d-モデルpreview\"\u003e3D モデルpreview\u003c/h2\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"THREEcontainer273186954 column\"\u003e\n    \u003cdiv class=\"mainView\"\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript type=\"module\"\u003e\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n\n    import * as THREE from 'three';\n    import { STLLoader } from 'three/addons/loaders/STLLoader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n    \n    \n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n\n    \n    const scene = new THREE.Scene();\n    scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n    scene.add(new THREE.AxesHelper(50))\n\n    \n    const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n    const container = document.querySelector(\".THREEcontainer273186954\")\n    const mainView  = container.querySelector(\".mainView\")\n    const renderer = new THREE.WebGLRenderer();\n    renderer.setSize(screenSize.width,screenSize.height);\n    renderer.shadowMap.enabled = true;\n    mainView.appendChild( renderer.domElement );\n\n    \n    const buttons = container.querySelector(\".MMDcontroler.column\")\n    const fullscreen = buttons.querySelector(\"#fullscreen\")\n\n    fullscreen.addEventListener(\"click\", () =\u003e {\n        mainView.requestFullscreen()\n    })\n\n    mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n        let width = 0\n        let height = 0\n        if(document.fullscreenElement){\n            width   = window.innerWidth\n            height  = window.outerHeight\n            \n            \n            \n        }else{\n            width   = screenSize.width\n            height  = screenSize.height\n            \n        }\n        \n        \n        console.log(width)\n        console.log(height)\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(width, height);\n        \n        camera.aspect = width / height;\n        camera.updateProjectionMatrix();\n        \n    })\n    \n\n\n\n        \n\n    \n    const controls = new OrbitControls(camera, renderer.domElement)\n    controls.enableDamping = true\n\n    \n    const loader = new STLLoader();\n    loader.load( '\\/images\\/3Dmodel\\/PCIeVerticalMount\\/main.stl', function (geometry) {\n        const material = new THREE.MeshStandardMaterial();\n        material.color = new THREE.Color().setHex(0x274d63)\n        const mesh = new THREE.Mesh(geometry, material)\n        mesh.receiveShadow = true\n        \n        mesh.position.x = Number(\"0\")\n        mesh.position.y = Number(\"20\")\n        mesh.position.z = Number(\"20\")\n        mesh.rotation.x = Math.PI * Number(\"270\") / 180.0\n        mesh.rotation.y = Math.PI * Number(\"0\") / 180.0\n        mesh.rotation.z = Math.PI * Number(\"0\") / 180.0\n\n        scene.add(mesh)\n    }, undefined, function ( error ) {\n        console.error( error );\n    } );\n\n    \n    let lightPosOffset = Number(\"200\")\n    const lightPos = [\n        {x:0,y:0,z:0},\n\n        {x:lightPosOffset,y:0 ,z:0},\n        {x:-lightPosOffset,y:0 ,z:0},\n\n        {x:0,y:lightPosOffset ,z:0},\n        {x:0,y:-lightPosOffset ,z:0},\n\n        {x:0,y:0 ,z:lightPosOffset},\n        {x:0,y:0 ,z:-lightPosOffset},\n\n        {x:0,y:lightPosOffset ,z:lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:lightPosOffset},\n        {x:0,y:lightPosOffset ,z:-lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:lightPosOffset,y:0 ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:lightPosOffset ,z:0},\n        {x:lightPosOffset,y:-lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:0},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n    ] \n\n    \n    const color = 0xFFFFFF;\n    const intensity = Number(\"1\");\n    for(let pos of lightPos){\n        let light =  new THREE.DirectionalLight(color, intensity);\n        light.position.set(pos.x, pos.y,pos.z);\n        scene.add(light);\n    }\n\n    \n    \n    camera.position.set(\n        Number(\"100\"),\n        Number(\"65\"),\n        Number(\"250\")\n    )\n    controls.target.set(\n        Number(\"100\"),\n        Number(\"70\"),\n        Number(\"0\")\n    )\n\n    \n    function animate() {\n        renderer.render( scene, camera );\n        controls.update()\n    }\n    renderer.setAnimationLoop( animate );\n\u003c/script\u003e\u003c/p\u003e","title":"PCIe(GPU) 縦方向マウント"},{"content":"この記事を作った動機 最近 Linux 環境を使っていると、noto-fonts-cjk をインストールしているにもかかわらず、それが機能しないことがあった。具体的には、中華系フォントが日本語フォントとして優先されて表示され、読めないことはないが、地味に見慣れない文字になってしまう。今までは、Linux 環境のフォントは読めればいい、映ればいいで放置していたが、流石にそれはないなと思ったので、設定をしていた。\n当然いちいち設定するときに調べるのはしんどいので、まとめが欲しいと思い記録を取ることにした。今回は、GNOME に関する設定と、fontconfig に関する設定の 2 つについて記録を取る。\n前提 Linux 環境 GNOME を使っている GNOME-Tweaks の項目のみにおける制限 設定後は再起動する。 システム全体の変更の反映は管理者権限を使うことを前提としている。(sudo) フォントの配置場所と更新 システム全体 通常はこのフォルダは標準で何もしなくてもあるはずである。ない場合は、別の場所にフォントが保存されているか、インストールした OS が崩壊している可能性がある。\n/usr/share/fonts ユーザ単体 ない場合はフォルダを新規作成する。\n~/.local/share/fonts 新しく配置したフォントの反映 sudo fc-cache -fv GNOME-Tweaks gnome-tweaks をインストールし、単に GUI を開いてポチポチするだけである。GNOME 環境ではすでにフォントがある程度デフォルトで固定されており基本的に崩れにくいため、デフォルトで満足しているならそのままでも良いと思われる。その場合は特別な設定が少なくとも GNOME に関しては、必要ないということである。\nyay -Sy gnome-tweaks # sudo pacman -Sy gnome-tweaks Fontconfig 設定配置場所 システム全体 ない場合は、テキストファイルとして新規作成する。\n/etc/fonts/local.conf ユーザ単体 ない場合は、テキストファイルとして新規作成する。\n~/.config/fontconfig/fonts.conf フォント名を調べる noto-fonts-cjk 以下の例では、Noto Sans CJK JPが今回取り扱うフォント名である。\nfc-list | grep \u0026#34;noto\u0026#34; | grep \u0026#34;Regular\u0026#34; | grep \u0026#34;Noto Sans CJK\u0026#34; | grep \u0026#34;JP\u0026#34; # /usr/share/fonts/noto-cjk/NotoSansCJK-Light.ttc: Noto Sans CJK JP,Noto Sans CJK JP Light:style=Light,Regular # /usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc: Noto Sans CJK JP:style=Regular # ... Comic Sans 以下の例では、/usr/share/fonts 配下にあらかじめ配置した Windows で使われているフォント Comic Sans についてフォント名を調べた例である。フォント名は、Comic Sans MSである。Windows 環境があれば、C:/Windows/Fonts あたりにある可能性がある。\nfc-list | grep \u0026#34;Comic\u0026#34; # /usr/share/fonts/comic-sans-ms-font-family/COMIC.TTF: Comic Sans MS:style=Regular # ... 設定内容例 (/etc/fonts/local.conf) 今回の例では、sans-serif と system-ui について、それぞれフォントを設定する。以下の設定例では、Comic Sans MS をまずは優先的に使うようにし、日本語フォントなど Comic Sans MS にないフォントは代替として、Noto Sans CJK JP を使うようにした例である。設定は、ファイルを保存、作成した瞬間に反映される。設定前と後の比較のようにして、fc-matchコマンドで確認できる。システム全体での反映には再起動が必要である。\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE fontconfig SYSTEM \u0026#34;urn:fontconfig:fonts.dtd\u0026#34;\u0026gt; \u0026lt;fontconfig\u0026gt; \u0026lt;alias\u0026gt; \u0026lt;family\u0026gt;sans-serif\u0026lt;/family\u0026gt; \u0026lt;prefer\u0026gt;\u0026lt;family\u0026gt;Comic Sans MS\u0026lt;/family\u0026gt;\u0026lt;/prefer\u0026gt; \u0026lt;prefer\u0026gt;\u0026lt;family\u0026gt;Noto Sans CJK JP\u0026lt;/family\u0026gt;\u0026lt;/prefer\u0026gt; \u0026lt;/alias\u0026gt; \u0026lt;alias\u0026gt; \u0026lt;family\u0026gt;system-ui\u0026lt;/family\u0026gt; \u0026lt;prefer\u0026gt;\u0026lt;family\u0026gt;Comic Sans MS\u0026lt;/family\u0026gt;\u0026lt;/prefer\u0026gt; \u0026lt;prefer\u0026gt;\u0026lt;family\u0026gt;Noto Sans CJK JP\u0026lt;/family\u0026gt;\u0026lt;/prefer\u0026gt; \u0026lt;/alias\u0026gt; \u0026lt;/fontconfig\u0026gt; 設定前と後の比較 設定前 fc-match \u0026#34;sans-serif\u0026#34; # NimbusSans-Regular.otf: \u0026#34;Nimbus Sans\u0026#34; \u0026#34;Regular\u0026#34; fc-match \u0026#34;system-ui\u0026#34; # NimbusSans-Regular.otf: \u0026#34;Nimbus Sans\u0026#34; \u0026#34;Regular\u0026#34; 設定後 fc-match \u0026#34;sans-serif\u0026#34; # COMIC.TTF: \u0026#34;Comic Sans MS\u0026#34; \u0026#34;Regular\u0026#34; fc-match sans-serif:lang=ja # NotoSansCJK-Regular.ttc: \u0026#34;Noto Sans CJK JP\u0026#34; \u0026#34;Regular\u0026#34; fc-match \u0026#34;system-ui\u0026#34; # COMIC.TTF: \u0026#34;Comic Sans MS\u0026#34; \u0026#34;Regular\u0026#34; fc-match \u0026#34;system-ui:lang=ja\u0026#34; # NotoSansCJK-Regular.ttc: \u0026#34;Noto Sans CJK JP\u0026#34; \u0026#34;Regular\u0026#34; 関連するページ gnomeの設定のメモ ⚙ 参考にしたサイトとか Arch Linux - noto-fonts-cjk 20240730-1 (any)\nhttps://archlinux.org/packages/extra/any/noto-fonts-cjk/ (2026年7月7日) Fonts - ArchWiki\nhttps://wiki.archlinux.org/title/Fonts (2026年7月7日) Font configuration - ArchWiki\nhttps://wiki.archlinux.org/title/Font_configuration (2026年7月7日) 10.6. フォントの設定 | デスクトップの移行および管理ガイド | Red Hat Enterprise Linux | 7 | Red Hat Documentation\nhttps://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/7/html/desktop_migration_and_administration_guide/configure-fonts (2026年7月7日) Arch Linux - gnome-tweaks 49.0-2 (any)\nhttps://archlinux.org/packages/extra/any/gnome-tweaks/ (2026年7月7日) ローカルLLM (Gemma4 31B) (2026年7月7日) ","permalink":"https://www.nyanmo.info/posts/linux/fontsettings/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 Linux 環境を使っていると、\u003ca href=\"https://archlinux.org/packages/extra/any/noto-fonts-cjk/\"\u003enoto-fonts-cjk\u003c/a\u003e をインストールしているにもかかわらず、それが機能しないことがあった。具体的には、中華系フォントが日本語フォントとして優先されて表示され、読めないことはないが、地味に見慣れない文字になってしまう。今までは、Linux 環境のフォントは読めればいい、映ればいいで放置していたが、流石にそれはないなと思ったので、設定をしていた。\u003c/p\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/fontSettings/%e4%be%8b1.png alt=中華文字の例/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/fontSettings/%e4%be%8b3.png alt=中華文字の例/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/fontSettings/%e4%be%8b2.png alt=中華文字の例/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003c/div\u003e\n\u003cp\u003e　当然いちいち設定するときに調べるのはしんどいので、まとめが欲しいと思い記録を取ることにした。今回は、GNOME に関する設定と、fontconfig に関する設定の 2 つについて記録を取る。\u003c/p\u003e\n\u003ch2 id=\"前提\"\u003e前提\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLinux 環境\u003c/li\u003e\n\u003cli\u003eGNOME を使っている \u003ca href=\"#gnome-tweaks\"\u003eGNOME-Tweaks の項目のみにおける制限\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e設定後は再起動する。\u003c/li\u003e\n\u003cli\u003eシステム全体の変更の反映は管理者権限を使うことを前提としている。(sudo)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"フォントの配置場所と更新\"\u003eフォントの配置場所と更新\u003c/h2\u003e\n\u003ch3 id=\"システム全体\"\u003eシステム全体\u003c/h3\u003e\n\u003cp\u003e　通常はこのフォルダは標準で何もしなくてもあるはずである。ない場合は、別の場所にフォントが保存されているか、インストールした OS が崩壊している可能性がある。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/usr/share/fonts\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"ユーザ単体\"\u003eユーザ単体\u003c/h3\u003e\n\u003cp\u003e　ない場合はフォルダを新規作成する。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~/.local/share/fonts\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"新しく配置したフォントの反映\"\u003e新しく配置したフォントの反映\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo fc-cache -fv\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"gnome-tweaks\"\u003eGNOME-Tweaks\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://archlinux.org/packages/extra/any/gnome-tweaks/\"\u003egnome-tweaks\u003c/a\u003e をインストールし、単に GUI を開いてポチポチするだけである。GNOME 環境ではすでにフォントがある程度デフォルトで固定されており基本的に崩れにくいため、デフォルトで満足しているならそのままでも良いと思われる。その場合は特別な設定が少なくとも GNOME に関しては、必要ないということである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy gnome-tweaks\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -Sy gnome-tweaks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/fontSettings/GNOME%20Tweaks.png#center\"\n         alt=\"GNOME Tweaks フォント設定画面\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"fontconfig\"\u003eFontconfig\u003c/h2\u003e\n\u003ch3 id=\"設定配置場所\"\u003e設定配置場所\u003c/h3\u003e\n\u003ch4 id=\"システム全体-1\"\u003eシステム全体\u003c/h4\u003e\n\u003cp\u003e　ない場合は、テキストファイルとして新規作成する。\u003c/p\u003e","title":"Linux 環境におけるフォント設定"},{"content":"ツール本体 Keyboard Event Tester Key Value Key: null Code: null Bool Value alt: false ctrl: false meta: false shift: false このツールを作った動機 JavaScript におけるキーボードに関するイベントの戻り値がどうなるか確認できるツールが欲しかったので作っただけである。もともとは、CapsLock を ESC キーとして割り当てる (Keyd,Linux)においてキーボードの再割り当てがうまくいっているか確かめるためのツールとして作っただけである。\n使い方は単に確認したいキーを押して、JavaScript のキーイベントの戻り値が何になるか確認するだけである。\n関連のある記事 CapsLock を ESC キーとして割り当てる (Keyd,Linux) ","permalink":"https://www.nyanmo.info/tools/keyboardeventtester/","summary":"\u003ch2 id=\"ツール本体\"\u003eツール本体\u003c/h2\u003e\n\u003cdiv id=\"KeyboardEventTester\"\u003e\n    \u003ch3\u003eKeyboard Event Tester\u003c/h3\u003e\n    \u003cdiv class=\"column\"\u003e\n        \u003ch4\u003eKey Value\u003c/h4\u003e\n        \u003cdiv class=\"column\"\u003e\n            \u003cdiv class=\"keyValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003eKey: null\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"codeValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003eCode: null\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\n    \u003cdiv class=\"column\"\u003e\n        \u003ch4\u003eBool Value\u003c/h4\u003e\n        \u003cdiv class=\"bools column\"\u003e\n            \u003cdiv class=\"altValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003ealt: false\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"ctrlValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003ectrl: false\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"metaValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003emeta: false\u003c/div\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"shiftValue eventItem\"\u003e\n                \u003cdiv class=\"value\"\u003eshift: false\u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript\u003e\nfunction setEventLister(){\n    addEventListener(\"keydown\",(event) =\u003e {\n        let eventItems = document.querySelector(\"#KeyboardEventTester\")\n        \n        eventItems.querySelector(\".keyValue\").textContent = \"Key: \" + event.key\n        eventItems.querySelector(\".codeValue\").textContent = \"Code: \" + event.code\n\n        if(event.altKey){\n            eventItems.querySelector(\".altValue .value\").textContent = \"Alt: true\"\n        }else{\n            eventItems.querySelector(\".altValue .value\").textContent = \"Alt: false\"\n        }\n\n        if(event.shiftKey){\n            eventItems.querySelector(\".shiftValue .value\").textContent = \"Shift: true\"\n        }else{\n            eventItems.querySelector(\".shiftValue .value\").textContent = \"Shift: false\"\n        }\n\n        if(event.ctrlKey){\n            eventItems.querySelector(\".ctrlValue .value\").textContent = \"Ctrl: true\"\n        }else{\n            eventItems.querySelector(\".ctrlValue .value\").textContent = \"Ctrl: false\"\n        }\n\n        if(event.metaKey){\n            eventItems.querySelector(\".metaValue .value\").textContent = \"Meta: true\"\n        }else{\n            eventItems.querySelector(\".metaValue .value\").textContent = \"Meta: false\"\n        }\n    })\n}\naddEventListener(\"DOMContentLoaded\",() =\u003e {\n    setEventLister()\n})\n\u003c/script\u003e\n\n\n\n\n\u003ch2 id=\"このツールを作った動機\"\u003eこのツールを作った動機\u003c/h2\u003e\n\u003cp\u003e　JavaScript におけるキーボードに関するイベントの戻り値がどうなるか確認できるツールが欲しかったので作っただけである。もともとは、\u003ca href=\"https://www.nyanmo.info/posts/linux/remapcapslockintoescwithkeyd/\"\u003eCapsLock を ESC キーとして割り当てる (Keyd,Linux)\u003c/a\u003eにおいてキーボードの再割り当てがうまくいっているか確かめるためのツールとして作っただけである。\u003c/p\u003e","title":"Keyboard Event Tester (For JavaScript)"},{"content":"この記事を作った動機 CMOS リセット時に GRUB インストール時にデフォルトで作成される UEFI 設定が一緒に消えてしまう。結果として、はじめから Linux 環境を起動してほしいときに、意図した通りに起動しないことがあった。\nそこでしばらくは BIOS から直接 Linux 環境がインストールされた環境をわざわざ選択して起動したり、UEFI設定から直接エントリを作成して、Linux を起動するようにするなど、面倒くさい事を繰り返していた。\n今回は、それに対してefibootmgrというコマンドを使い、systemd によって一度起動したら自動でエントリがない場合に起動エントリを追加するようにした。その内容について記録を取りたい。\nefibootmgr の使い方 インストール yay -Sy efibootmgr # sudo pacman -Sy efibootmgr エントリを追加する例 ブートローダである UEFI アプリケーションのパスを指定するとき注意が必要である。Linux 環境側から見て、/bootに EFI パティーションをマウントしていて、/boot/EFI/arch/grubx64.efi に対象のアプリファイルが配置されている場合の例について考える。この場合、efibootmgr で指定すべきパスは、/boot/EFI/arch/grubx64.efi ではなく /EFI/arch/grubx64.efi である。もしここで間違ったパスを指定していると、UEFI アプリケーションの起動に失敗し、UEFI の設定画面に飛ばされるなどの症状になる。\nsudo efibootmgr -c -L ArchLinux -l /EFI/arch/grubx64.efi -d /dev/nvme0n1p1 fdisk で Linux 環境がインストールされたディスクを確認 sudo fdisk -l # Disk /dev/nvme0n1: 476.94 GiB, 512110190592 bytes, 1000215216 sectors # Disk model: SAMSUNG MZVKW512HMJP-000H1 # Units: sectors of 1 * 512 = 512 bytes # Sector size (logical/physical): 512 bytes / 512 bytes # I/O size (minimum/optimal): 512 bytes / 512 bytes # Disklabel type: gpt # Disk identifier: # # Device Start End Sectors Size Type # /dev/nvme0n1p1 2048 2097152 2095105 1023M EFI System # /dev/nvme0n1p2 2099200 964689920 962590721 459G Linux filesystem # /dev/nvme0n1p3 964691968 1000214527 35522560 16.9G Linux swap エントリを削除する例 sudo efibootmgr -B -L ArchLinux systemd スクリプト 以下は、/etc/systemd/system/grubConfig.service として配置した systemd サービスの例である。いちいちエントリがあるか判定するのはめんどくさかった。そこで毎回 Linux 環境起動時に既にあるエントリはもし存在すれば重複防止のために消して、エントリを作るという挙動にした。\n[Unit] Description=Create UEFI entry by using efibootmgr command. [Service] Type=simple User=root ExecStart=/bin/bash -c \u0026#34;efibootmgr -B -L ArchLinux; efibootmgr -c -L ArchLinux -l /EFI/arch/grubx64.efi -d /dev/nvme0n1p1\u0026#34; Restart=on-failure [Install] WantedBy=multi-user.target sudo systemctl enable --now grubConfig 参考にしたサイトとか efibootmgr - Gentoo wiki\nhttps://wiki.gentoo.org/wiki/Efibootmgr (2026年7月5日) efibootmgr(8) — Arch manual pages\nhttps://man.archlinux.org/man/efibootmgr.8 (2026年7月5日) Arch Linux - efibootmgr 18-4 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/efibootmgr/ (2026年7月5日) ローカルLLM (Gemma4 31B) (2026年7月5日) ","permalink":"https://www.nyanmo.info/posts/linux/adduefientryforgrub/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　CMOS リセット時に GRUB インストール時にデフォルトで作成される UEFI 設定が一緒に消えてしまう。結果として、はじめから Linux 環境を起動してほしいときに、意図した通りに起動しないことがあった。\u003c/p\u003e\n\u003cp\u003e　そこでしばらくは BIOS から直接 Linux 環境がインストールされた環境をわざわざ選択して起動したり、UEFI設定から直接エントリを作成して、Linux を起動するようにするなど、面倒くさい事を繰り返していた。\u003c/p\u003e\n\u003cp\u003e　今回は、それに対して\u003ccode\u003eefibootmgr\u003c/code\u003eというコマンドを使い、systemd によって一度起動したら自動でエントリがない場合に起動エントリを追加するようにした。その内容について記録を取りたい。\u003c/p\u003e\n\u003ch2 id=\"efibootmgr-の使い方\"\u003eefibootmgr の使い方\u003c/h2\u003e\n\u003ch3 id=\"インストール\"\u003eインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy efibootmgr\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -Sy efibootmgr\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"エントリを追加する例\"\u003eエントリを追加する例\u003c/h3\u003e\n\u003cp\u003e　ブートローダである UEFI アプリケーションのパスを指定するとき注意が必要である。Linux 環境側から見て、\u003ccode\u003e/boot\u003c/code\u003eに EFI パティーションをマウントしていて、\u003ccode\u003e/boot/EFI/arch/grubx64.efi\u003c/code\u003e に対象のアプリファイルが配置されている場合の例について考える。この場合、\u003ccode\u003eefibootmgr\u003c/code\u003e で指定すべきパスは、\u003ccode\u003e/boot/EFI/arch/grubx64.efi\u003c/code\u003e ではなく \u003ccode\u003e/EFI/arch/grubx64.efi\u003c/code\u003e である。もしここで間違ったパスを指定していると、UEFI アプリケーションの起動に失敗し、UEFI の設定画面に飛ばされるなどの症状になる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo efibootmgr -c -L ArchLinux -l /EFI/arch/grubx64.efi -d /dev/nvme0n1p1\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003efdisk で Linux 環境がインストールされたディスクを確認\u003c/summary\u003e\n  \u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo fdisk -l\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Disk /dev/nvme0n1: 476.94 GiB, 512110190592 bytes, 1000215216 sectors\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Disk model: SAMSUNG MZVKW512HMJP-000H1              \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Units: sectors of 1 * 512 = 512 bytes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Sector size (logical/physical): 512 bytes / 512 bytes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# I/O size (minimum/optimal): 512 bytes / 512 bytes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Disklabel type: gpt\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Disk identifier: \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Device             Start        End   Sectors  Size Type\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /dev/nvme0n1p1      2048    2097152   2095105 1023M EFI System\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /dev/nvme0n1p2   2099200  964689920 962590721  459G Linux filesystem\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# /dev/nvme0n1p3 964691968 1000214527  35522560 16.9G Linux swap\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"UEFI の起動エントリに Linux 環境を追加する"},{"content":"この記事を作った動機 最近、Google Chrome 以外のブラウザを試したい、使いたいということで、Vivaldi を試していた。Linux 環境では、Windows 環境と異なり、ブラウザごとに証明書を保持管理していることがあり、OS標準の証明書は使われていないことがある。それで、HTTPS などの通信で使われる証明書を追加する項目がを探したが、見つけられず設定方法を調べる羽目になった。\nこれら経緯から、軽く記録が取りたいというだけ。\n証明書を追加する方法 chrome://settings/certificatesにアクセスする Vivaldi は Chromium ベースのブラウザなので、Google Chrome などで使える内蔵の URL がそのまま使える模様。\nchrome://settings/certificates おまけ 一応何について話しているのか少しでも直感的に把握しやすいようにするために、画像による状況の説明を試みることにする。以下はほとんどインストールしたての状態における、Vivaldi の様子の画像である。\n証明書の警告が出る様子 証明書について項目が見えない様子 参考にしたサイトとか Import client certificates | Vivaldi Forum\nhttps://forum.vivaldi.net/topic/57001/import-client-certificates?__cf_chl_f_tk=V6t.jDVSVpunhQLDRjIr2q.V9RiNUi98HfeBxNZlBkE-1782791663-1.0.1.1-_4dk4xss54mD9rTzImPTdolH_V5WQNyiiyXwBYzu5do (2026年6月30日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/vivaldiaddcertificate/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、Google Chrome 以外のブラウザを試したい、使いたいということで、Vivaldi を試していた。Linux 環境では、Windows 環境と異なり、ブラウザごとに証明書を保持管理していることがあり、OS標準の証明書は使われていないことがある。それで、HTTPS などの通信で使われる証明書を追加する項目がを探したが、見つけられず設定方法を調べる羽目になった。\u003c/p\u003e\n\u003cp\u003e　これら経緯から、軽く記録が取りたいというだけ。\u003c/p\u003e\n\u003ch2 id=\"証明書を追加する方法\"\u003e証明書を追加する方法\u003c/h2\u003e\n\u003ch3 id=\"chromesettingscertificatesにアクセスする\"\u003e\u003ccode\u003echrome://settings/certificates\u003c/code\u003eにアクセスする\u003c/h3\u003e\n\u003cp\u003e　Vivaldi は Chromium ベースのブラウザなので、Google Chrome などで使える内蔵の URL がそのまま使える模様。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003echrome://settings/certificates\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/%e8%a8%bc%e6%98%8e%e6%9b%b8%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%84%e3%81%9f%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"証明書追加\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/%e8%a8%bc%e6%98%8e%e6%9b%b8%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%84%e3%81%9f%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"証明書追加\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/%e8%a8%bc%e6%98%8e%e6%9b%b8%e8%a8%ad%e5%ae%9a%e3%82%92%e9%96%8b%e3%81%84%e3%81%9f%e6%a7%98%e5%ad%902.png#center\"\n         alt=\"証明書追加\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"おまけ\"\u003eおまけ\u003c/h2\u003e\n\u003cp\u003e　一応何について話しているのか少しでも直感的に把握しやすいようにするために、画像による状況の説明を試みることにする。以下はほとんどインストールしたての状態における、Vivaldi の様子の画像である。\u003c/p\u003e\n\u003ch3 id=\"証明書の警告が出る様子\"\u003e証明書の警告が出る様子\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/%e8%a8%bc%e6%98%8e%e6%9b%b8%e3%81%ae%e6%a4%9c%e8%a8%bc%e3%81%8c%e9%80%9a%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"証明書警告\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"証明書について項目が見えない様子\"\u003e証明書について項目が見えない様子\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e6%a4%9c%e7%b4%a2%e3%82%92%e3%81%8b%e3%81%91%e3%81%a6%e3%82%82%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%a8%e3%81%97%e3%81%a6%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%a8%e3%81%97%e3%81%a6%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%a8%e3%81%97%e3%81%a6%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%902.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%a8%e3%81%97%e3%81%a6%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%903.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/vivaldiAddCertificate/NotFoundOnGUI/%e3%82%bb%e3%82%ad%e3%83%a5%e3%83%aa%e3%83%86%e3%82%a3%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%a8%e3%81%97%e3%81%a6%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e6%a7%98%e5%ad%904.png#center\"\n         alt=\"証明書設定が見つからない様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eImport client certificates | Vivaldi Forum\u003cbr\u003e\n\u003ca href=\"https://forum.vivaldi.net/topic/57001/import-client-certificates?__cf_chl_f_tk=V6t.jDVSVpunhQLDRjIr2q.V9RiNUi98HfeBxNZlBkE-1782791663-1.0.1.1-_4dk4xss54mD9rTzImPTdolH_V5WQNyiiyXwBYzu5do\"\u003ehttps://forum.vivaldi.net/topic/57001/import-client-certificates?__cf_chl_f_tk=V6t.jDVSVpunhQLDRjIr2q.V9RiNUi98HfeBxNZlBkE-1782791663-1.0.1.1-_4dk4xss54mD9rTzImPTdolH_V5WQNyiiyXwBYzu5do\u003c/a\u003e (2026年6月30日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Vivaldi で 証明書を追加する"},{"content":"この記事を作った動機 Intel Arc で音声からの文字起こしができる Whisper を動かせることが分かったので記録したい。Whisper は PyTorch を使っているが、それを XPU に対応したものに差し替えることで動作が確認できたことに関して、具体的に作業内容を記録したい。\nWhisper を使った文字起こしでは、Vibe を使うことでもできるが、Nvidia の CUDA 環境で無い限り、Intel Arc 環境においては、Vulkan を使ってしまう。PyTorch 環境においては XPU を使わなければ、Intel Arc の GPU 性能を使い切れていない気がすると思ったのもある。\nただ実際に試してみると、今のところそこまで早いとは言えず、むしろ Vulkan で動かしているときより遅い気もした。設定次第なのかもしれないが、そこまでは詳しく試していない。\n環境の前提 Intel Arc を使っている Conda 環境を導入済み Linux 環境 記事の作業内容のまとめ conda create -n whisper conda activate whisper conda install pip pip install -U openai-whisper pip uninstall torch pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu Whisper のインストール conda 環境を専用に作る conda create -n whisper conda activate whisper conda install pip whisper を pip でインストール 一旦 Nvidia 環境用の pytorch などがインストールされてしまうが、一旦はインストールを終わらせる。\npip install -U openai-whisper この時点でXPUを動かそうとすると？ 以下のようなエラーを吐いて動作しない。要約すれば、\u0026ldquo;インストールされている PyTorch が xpu に対応していない\u0026quot;と怒られているだけである。\nwhisper edited3.mp3 --language Japanese --device xpu --model large 100%|█████████████████████████████████████| 2.88G/2.88G [05:03\u0026lt;00:00, 10.2MiB/s] Traceback (most recent call last): File \u0026#34;/home/userName/.conda/envs/whisper/bin/whisper\u0026#34;, line 6, in \u0026lt;module\u0026gt; sys.exit(cli()) ~~~^^ File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/whisper/transcribe.py\u0026#34;, line 595, in cli model = load_model(model_name, device=device, download_root=model_dir) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/whisper/__init__.py\u0026#34;, line 151, in load_model checkpoint = torch.load(fp, map_location=device, **kwargs) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 1570, in load return _load( opened_zipfile, ...\u0026lt;3 lines\u0026gt;... **pickle_load_args, ) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 2190, in _load result = unpickler.load() File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/_weights_only_unpickler.py\u0026#34;, line 541, in load self.append(self.persistent_load(pid)) ~~~~~~~~~~~~~~~~~~~~^^^^^ File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 2154, in persistent_load typed_storage = load_tensor( dtype, nbytes, key, _maybe_decode_ascii(location) ) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 2116, in load_tensor wrap_storage = restore_location(storage, location) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 1915, in restore_location return default_restore_location(storage, map_location) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 734, in default_restore_location result = fn(storage, location) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 667, in _deserialize device = _validate_device(location, backend_name) File \u0026#34;/home/userName/.conda/envs/whisper/lib/python3.14/site-packages/torch/serialization.py\u0026#34;, line 634, in _validate_device raise RuntimeError( ...\u0026lt;5 lines\u0026gt;... ) RuntimeError: Attempting to deserialize object on a XPU device but torch.xpu.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device(\u0026#39;cpu\u0026#39;) to map your storages to the CPU. XPU に対応した PyTorch を入れる 既にインストールされた Nvidia 向け PyTorch を排除 この時点で Nvidia 向けの PyTorch 環境を消さないと既に PyTorch がインストールされているとして XPU 向けの PyTorch が入らない。\npip uninstall torch XPU 向けの PyTorch をインストール pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu Whisper を動かしてみる conda activate whisper whisper edited3.mp3 --language Japanese --device xpu --model large # ... # [00:21.000 --\u0026gt; 00:28.000] Test Test ... # ... 使った画像とか Intel Arc | Logopedia | Fandom\nhttps://logos.fandom.com/wiki/Intel_Arc (2026年6月16日) OpenAI, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:OpenAI_logo_2025_(symbol).svg (2026年6月16日) 参考にしたサイトとか openai/whisper: Robust Speech Recognition via Large-Scale Weak Supervision\nhttps://github.com/openai/whisper (2026年6月16日) Getting Started on Intel GPU — PyTorch 2.12 documentation\nhttps://docs.pytorch.org/docs/2.12/notes/get_start_xpu.html (2026年6月16日) AUR (en) - vibe-bin\nhttps://aur.archlinux.org/packages/vibe-bin (2026年6月16日) thewh1teagle/vibe: Transcribe on your own!\nhttps://github.com/thewh1teagle/vibe (2026年6月16日) Problem with repetitions · openai/whisper · Discussion #2442 · GitHub\nhttps://github.com/openai/whisper/discussions/2442 (2026年6月16日) Bugfix: Illogical \u0026ldquo;Avoid computing higher temperatures on no_speech\u0026rdquo; by Purfview · Pull Request #1903 · openai/whisper · GitHub\nhttps://github.com/openai/whisper/pull/1903 (2026年6月16日) Some wired repetition happens in transcription. · openai/whisper · Discussion #192 · GitHub\nhttps://github.com/openai/whisper/discussions/192 (2026年6月16日) ","permalink":"https://www.nyanmo.info/posts/linux/whisperonintelarc/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Intel Arc で音声からの文字起こしができる Whisper を動かせることが分かったので記録したい。Whisper は PyTorch を使っているが、それを XPU に対応したものに差し替えることで動作が確認できたことに関して、具体的に作業内容を記録したい。\u003c/p\u003e\n\u003cp\u003e　Whisper を使った文字起こしでは、Vibe を使うことでもできるが、Nvidia の CUDA 環境で無い限り、Intel Arc 環境においては、Vulkan を使ってしまう。PyTorch 環境においては XPU を使わなければ、Intel Arc の GPU 性能を使い切れていない気がすると思ったのもある。\u003c/p\u003e\n\u003cp\u003e　ただ実際に試してみると、今のところそこまで早いとは言えず、むしろ Vulkan で動かしているときより遅い気もした。設定次第なのかもしれないが、そこまでは詳しく試していない。\u003c/p\u003e\n\u003ch2 id=\"環境の前提\"\u003e環境の前提\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eIntel Arc を使っている\u003c/li\u003e\n\u003cli\u003eConda 環境を導入済み\u003c/li\u003e\n\u003cli\u003eLinux 環境\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"記事の作業内容のまとめ\"\u003e記事の作業内容のまとめ\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda create -n whisper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda activate whisper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda install pip\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -U openai-whisper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip uninstall torch\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/xpu\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"whisper-のインストール\"\u003eWhisper のインストール\u003c/h2\u003e\n\u003ch3 id=\"conda-環境を専用に作る\"\u003econda 環境を専用に作る\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda create -n whisper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda activate whisper\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econda install pip\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"whisper-を-pip-でインストール\"\u003ewhisper を pip でインストール\u003c/h3\u003e\n\u003cp\u003e　一旦 Nvidia 環境用の pytorch などがインストールされてしまうが、一旦はインストールを終わらせる。\u003c/p\u003e","title":"Whisper を Intel Arc で動かす"},{"content":"この記事を作った動機 LibreChat を使っているうちに、色々躓いたことがあったので記録したい。躓いたことでなくてもまとめておきたいことは書きたい。\n前提条件 環境構築をしたディレクトリが以下のパスになっている LibreChat の Docker 関連のファイルが以下のディレクトリにある事を前提に進める。通常であれば、各個人に合わせて作業して良い。私の場合はあくまで以下のパスにあるというだけである。\n~/LibreChat LLM サーバの構成と、LibreChatの関係 以下の図のような関係になっている事を前提にする。 MainDesktop エンドポイント エンドポイントまでのアドレスとポート番号の仮定\nhttp://192.168.x.a:8080/v1 詳細な役割の説明\n純粋に llama.cpp を動かして1つのモデルを読み込んでいる LLM サーバ専用(Gemma-4-31Bを動かす専用)に割り当てた PC である。LibreChat はここではホストしていない。Intel ARC の XPU 環境であり、LM Studio ではそのポテンシャルを引き出せないため、llama.cpp を専用にコンパイルしてセットアップしてある。OpenAI 互換 API 経由で利用可能にしてある。 DataServer エンドポイント エンドポイントまでのアドレスとポート番号の仮定\nhttp://192.168.x.b:1234/v1 詳細な役割の説明\nLM Studio を使って LLM を動かしている。こちらは、MainDesktop と異なり、NVIDIA の CUDA 環境であるため、LM Studio でポテンシャルを引き出すことができることから、LM Studio を使っている。LM Studio 標準の開発者機能から、OpenAI 互換 API 経由で利用可能にしてある。基本的に LM Studio の LLM サーバーが、LibreChat の要求に答えて選択されたモデルを自動的にロードし動かしてくれるため、いろんなモデルを動かすために使う。 その他諸々 Linux 環境である docker、docker-composeパッケージが入っている 全ては LAN 内で行われ、グローバル空間からのアクセスはできないようにしてある環境である。外出先からの利用はすべて VPN を通じて行う。 基本的な操作 設定ファイル保存場所 ~/LibreChat/librechat.yaml 設定反映方法 (librechat.yaml) 私の場合は、~/LibreChatにおいて以下のスクリプトをrestart.shとして配置し、実行することでlibrechat.yamlの変更内容を反映できる事を確認した。docker グループに入っていないユーザは、管理者権限を付与してコマンドを実行することで docker を操作できる。\n#!/bin/bash sudo docker compose down sudo docker compose up -d エンドポイント (OpenAI API 互換サーバ) の追加方法 今回は、例として LM Studio の開発者モードで動かすことができる LLM サーバ (エンドポイント) を追加する例を以下に示す。前提として、既に LM Studio の LLM サーバーは動いていることがある。OpenAI 互換 APIサーバのエンドポイントは、custom セクションの中に記述する。利用可能なモデルは、LM Studio に対して、LibreChat が自動取得するように今回は設定しており、fetch: trueとしている。これについては注意点があり、lm-studio-のネットワーク設定の制限の引っかかっているを参照すること。\nエンドポイントの追加前の設定例 # ... endpoints: custom: - name: \u0026#39;MainDesktop\u0026#39; apiKey: \u0026#39;not-needed\u0026#39; baseURL: \u0026#39;http://192.168.x.a:8080/v1\u0026#39; models: default: [\u0026#39;Gemma-4-31B\u0026#39;] fetch: false titleConvo: true titleModel: \u0026#39;Gemma-4-31B\u0026#39; modelDisplayLabel: \u0026#39;Gemma-4-31B\u0026#39; modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; model: \u0026#34;Gemma-4-31B\u0026#34; # ... エンドポイントの追加後の設定例 # ... endpoints: custom: - name: \u0026#39;MainDesktop\u0026#39; apiKey: \u0026#39;not-needed\u0026#39; baseURL: \u0026#39;http://192.168.x.a:8080/v1\u0026#39; models: default: [\u0026#39;Gemma-4-31B\u0026#39;] fetch: false titleConvo: true titleModel: \u0026#39;Gemma-4-31B\u0026#39; modelDisplayLabel: \u0026#39;Gemma-4-31B\u0026#39; - name: \u0026#39;DataServer\u0026#39; apiKey: \u0026#39;not-needed\u0026#39; baseURL: \u0026#39;http://192.168.x.b:1234/v1\u0026#39; models: default: [\u0026#39;test-model\u0026#39;] fetch: true modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; model: \u0026#34;Gemma-4-31B\u0026#34; # ... 躓いたこと LM Studio の API サーバーを使いたい エンドポイントの指定が間違っている (Linux 環境特有) Linux 環境の Docker では、host.docker.internal を Docker のホストマシンの localhost にアクセスするために使うことができない。私は単純にホストマシンの物理 NIC に割り当てられている IP(192.168.x.b) を直接指定することにした。\nLM Studio のネットワーク設定の制限の引っかかっている Docker コンテナからのアクセスは別のネットワークからのアクセスとなるからか、以下の設定をしないと LM Studio のログにはアクセスできたように見えても、LibreChatは動作しなかった。動作に失敗したときのLibreChatの設定は、costomエンドポイントの設定をすべて無視して、デフォルトのOpenAIなどのリスティングしかしなくなる。つまりは、今まで正常に動いていたエンドポイントまで巻き添えにして、機能しなくなるので注意する。 エンドポイントとモデル名を変更したら、過去のチャットを継続できなくなった LibreChat の場合は、既存のセッションに対して柔軟でないらしく、既存のLLM サーバに対するエンドポイント名とモデル名を変更すると、セッションを継続して利用できなくなってしまう。\n具体的には、設定を以下のように変更したあと、過去のセッションにアクセスすると、\u0026ldquo;モデル選択\u0026quot;と表示されそのままでは新しいプロンプトを受け付けず、かと行って新しく設定したセッションを選択しても、新しいセッションに飛ばされて、過去のセッションは継続できないということになった。\n古い設定の例 (librechat.yaml) # ... endpoints: custom: - name: \u0026#39;Llama-CPP\u0026#39; apiKey: \u0026#39;not-needed\u0026#39; baseURL: \u0026#39;http://192.168.x.a:8080/v1\u0026#39; models: default: [\u0026#39;Local-Custom\u0026#39;] fetch: false titleConvo: true titleModel: \u0026#39;Local-Custom\u0026#39; modelDisplayLabel: \u0026#39;Llama.cpp\u0026#39; modelSpecs: list: - name: \u0026#34;Llama-CPP\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; model: \u0026#34;Local-Custom\u0026#34; # ... 新しい設定の例 (librechat.yaml) # ... endpoints: custom: - name: \u0026#39;MainDesktop\u0026#39; apiKey: \u0026#39;not-needed\u0026#39; baseURL: \u0026#39;http://192.168.x.a:8080/v1\u0026#39; models: default: [\u0026#39;Gemma-4-31B\u0026#39;] fetch: false titleConvo: true titleModel: \u0026#39;Gemma-4-31B\u0026#39; modelDisplayLabel: \u0026#39;Gemma-4-31B\u0026#39; modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; model: \u0026#34;Gemma-4-31B\u0026#34; # ... これに関しては、LibreChat が docker コンテナのスタックに含んでいる DB にアクセスして、古いセッションのエンドポイント名とモデル名を過去のものから新しいものに更新すること(Gemma4提案)で、古いセッションでも継続して利用できるようになる事を確認した。以下に DB の操作例を示す。\nDB 操作例の前提 古いモデル名\nLocal-Custom 新しいモデル名\nGemma-4-31B 古いエンドポイント名\nLlama-CPP 新しいエンドポイント名\nMainDesktop DB コンテナ名\nchat-mongodb DB にアクセス docker exec -it chat-mongodb mongosh モデル名変更 use LibreChat; db.conversations.distinct(\u0026#34;model\u0026#34;); -- [ -- \u0026#39;Gemma-4-31B\u0026#39;, -- \u0026#39;Local-Custom\u0026#39;, -- \u0026#39;gemini-3-flash-preview\u0026#39;, -- \u0026#39;google/gemma-3n-e4b\u0026#39; -- ] db.conversations.updateMany( { model: \u0026#34;Local-Custom\u0026#34; }, { $set: { model: \u0026#34;Gemma-4-31B\u0026#34; } } ); -- { -- acknowledged: true, -- insertedId: null, -- matchedCount: 486, -- modifiedCount: 486, -- upsertedCount: 0 -- } db.conversations.distinct(\u0026#34;model\u0026#34;) -- [ \u0026#39;Gemma-4-31B\u0026#39;, \u0026#39;gemini-3-flash-preview\u0026#39;, \u0026#39;google/gemma-3n-e4b\u0026#39; ] エンドポイント名変更 db.conversations.distinct(\u0026#34;endpoint\u0026#34;) -- [ \u0026#39;DataServer\u0026#39;, \u0026#39;Llama-CPP\u0026#39;, \u0026#39;MainDesktop\u0026#39;, \u0026#39;google\u0026#39; ] db.conversations.updateMany( { endpoint: \u0026#34;Llama-CPP\u0026#34; }, { $set: { endpoint: \u0026#34;MainDesktop\u0026#34; } } ); -- { -- acknowledged: true, -- insertedId: null, -- matchedCount: 486, -- modifiedCount: 486, -- upsertedCount: 0 -- } db.conversations.distinct(\u0026#34;endpoint\u0026#34;) -- [ \u0026#39;DataServer\u0026#39;, \u0026#39;MainDesktop\u0026#39;, \u0026#39;google\u0026#39; ] アプデしたらプロンプトが正しく送信されなくなることがあった (2026年9月27日追記) LibreChat のコンテナをアプデしたところ、1万コンテキスト程度の長さのテキストを添付すると、添付したファイルと本来一緒に送られるはずのユーザのセッション内のプロンプトが送信されないということになった。調査してみたところ、以下のlibrechat.yamlにおける設定が重要であることがわかった。最近の LibreChat では添付ファイルの扱いが変わっているらしく、以前はテキストとして送信するか、画像として送信するか、LLM エンドポイント先に送るか（プロバイダに送信するか）が選べたが、今はデフォルトでは出てこなくなるようになっている。その設定項目において、旧来の UI/UX を使おうとすると不具合が再現するようである。\n問題が再現すると、LLMは、添付したテキストしか受け取れず、ユーザが要約を求めているのだとして出力をし始めて、ユーザのプロンプトの指示に全くそぐわない見当違いのチグハグな出力をするようになる。\n色々試しているので厳密な対照実験とはなっていないが、私のケースでは、legacyFileUploadUXをtrueからfalseにすることで問題が解決されたように見受けられた。maxContextTokensなどのトークン数の制限に関しては、試しているテストプロンプトやテスト添付ファイルに対して、十分大きくなるようにしか設定しておらず、適切な設定をしているわけではないため注意する。以下の設定例におけるトークン数の設定は、あくまで問題の切り分けとして、LibreChat 側の制限に引っかからないようにするために、設定している。通常は適宜利用しているLLMエンドポイントの性能や運用上の都合に合わせて制限を設定する必要がある。以下の設定はあくまで自分用にしか使っていないので相当制限をゆるく怠惰に満足するくらいで設定しているというのもある。\n現在の設定の一部の例 # ... modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; model: \u0026#34;Gemma-4-31B\u0026#34; maxContextTokens: 200000 max_tokens: 500000 fileConfig: serverFileSizeLimit: 200 endpoints: custom: fileLimit: 30 fileSizeLimit: 200 totalSizeLimit: 1000 supportedMimeTypes: - \u0026#34;image/.*\u0026#34; - \u0026#34;text/*\u0026#34; - \u0026#34;application/pdf\u0026#34; legacyFileUploadUX: false # 今回問題となった設定の部分である。これを true にすると、旧来の UI/UX として、テキストとして送信するか、プロバイダに送信するかなどを選ぶことができるようになる。ただ内部ロジックも古いものになってしまうようでバグが発生しているように見受けられる。 fileTokenLimit: 100000 fileContextCharLimit: 100000 defaultLLMDeliveryPath: # llama.cpp 対策。llama.cppは直接PDFをサポートしない overrides: \u0026#39;application/pdf\u0026#39;: text ocr: supportedMimeTypes: - \u0026#34;^image/(jpeg|gif|png|webp|heic|heif)$\u0026#34; - \u0026#34;^application/pdf$\u0026#34; - \u0026#34;^application/vnd\\\\.openxmlformats-officedocument\\\\.(wordprocessingml\\\\.document|presentationml\\\\.presentation|spreadsheetml\\\\.sheet)$\u0026#34; - \u0026#34;^application/vnd\\\\.ms-(word|powerpoint|excel)$\u0026#34; - \u0026#34;^application/epub\\\\+zip$\u0026#34; text: supportedMimeTypes: - \u0026#34;^text/(plain|markdown|csv|json|xml|html|css|javascript|typescript|x-python|x-java|x-csharp|x-php|x-ruby|x-go|x-rust|x-kotlin|x-swift|x-scala|x-perl|x-lua|x-shell|x-sql|x-yaml|x-toml)$\u0026#34; stt: supportedMimeTypes: - \u0026#34;^audio/(mp3|mpeg|mpeg3|wav|wave|x-wav|ogg|vorbis|mp4|x-m4a|flac|x-flac|webm)$\u0026#34; # ... fileConfigの設定項目が反映されていない (2026年9月27日追記) librechat.yamlの設定項目では、一度に添付できるファイルの数やサイズを制限する設定があり、設定していない場合デフォルト値が使われるということがある。アプデしたらプロンプトが正しく送信されなくなることがあったの調査過程より問題が発覚した。もっとデフォルとより大きくたくさんのファイルを添付したいとなると、設定が必要になるが、今まで正しく反映できていないことがわかり修正した。\n正しく設定を反映できていないときは、設定した通りの添付ファイル制限にならず、10個までしか添付できないなど、デフォルトのままになるという挙動になる。\n問題がある例 # ... modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; # fileConfig の endpoints の項目において反映すべき名前 model: \u0026#34;Gemma-4-31B\u0026#34; maxContextTokens: 200000 max_tokens: 500000 fileConfig: serverFileSizeLimit: 200 endpoints: assistants: # modelSpecs の項目で設定した endpoint 名にになっておらず、存在しないエンドポイント `assistants` に設定していることになっている。 fileLimit: 30 fileSizeLimit: 200 totalSizeLimit: 1000 supportedMimeTypes: - \u0026#34;image/.*\u0026#34; - \u0026#34;text/*\u0026#34; - \u0026#34;application/pdf\u0026#34; legacyFileUploadUX: false fileTokenLimit: 100000 fileContextCharLimit: 100000 defaultLLMDeliveryPath: # llama.cpp 対策。llama.cppは直接PDFをサポートしない overrides: \u0026#39;application/pdf\u0026#39;: text # ... 正しく反映されている例 # ... modelSpecs: list: - name: \u0026#34;Main\u0026#34; label: \u0026#34;Default: Llama-CPP\u0026#34; description: \u0026#34;My primary local model\u0026#34; preset: endpoint: \u0026#34;custom\u0026#34; # fileConfig の endpoints の項目において反映すべき名前 model: \u0026#34;Gemma-4-31B\u0026#34; maxContextTokens: 200000 max_tokens: 500000 fileConfig: serverFileSizeLimit: 200 endpoints: custom: # modelSpecs の項目で設定した endpoint 名になっている fileLimit: 30 fileSizeLimit: 200 totalSizeLimit: 1000 supportedMimeTypes: - \u0026#34;image/.*\u0026#34; - \u0026#34;text/*\u0026#34; - \u0026#34;application/pdf\u0026#34; legacyFileUploadUX: false fileTokenLimit: 100000 fileContextCharLimit: 100000 defaultLLMDeliveryPath: # llama.cpp 対策。llama.cppは直接PDFをサポートしない overrides: \u0026#39;application/pdf\u0026#39;: text # ... MCP サーバがタイムアウトする (2026年9月27日追記) 最近 FastMCP を使った MCP サーバとして、hello30190f/Modular-MCP-Serverを作り、LibreChat にてフロントエンド側からエンドポイントを指定し、動かすということがあった。作ったMCP サーバは基本的に決まったスクリプトを書けばいくらでも MCP ツールを追加できるようになっているが、その一部のツールの実装において、画像などの処理に時間がかかり、LibreChatのデフォルトのタイムアウトの時間(多分1分くらい)を過ぎてしまい、結果失敗扱いになってしまうということがあった。\nタイムアウト時間は、フロントエンドからは設定できないらしく、librechat.yamlにて MCP サーバを直接明示し、その過程でタイムアウトを記述するという手法しか現状では取れていない。開発サーバとして MCP サーバを動かす際には、設定の存在を忘れたりするなどなにかと管理上不都合で不便だと思ったが、現状はその方法しか機能することやできることを確かめられていない。\n現状の設定例 MCP サーバのポート番号と IP アドレスは適宜設定すること。\n# ... mcpSettings: allowedAddresses: - \u0026#34;192.168.xxx.xxx:8000\u0026#34; mcpServers: MCP-dev: type: sse url: \u0026#34;http://192.168.xxx.xxx:8000/sse\u0026#34; timeout: 300000 # 5 * 60 * 1000 ms = 5分 # ... 関連する記事や外部サイトとか llama.cpp を Intel Arc で SYCL を使って動かす hello30190f/Modular-MCP-Server 使った画像とか Windows 7(Vista) デフォルトのアイコン PC のアイコン ルータのアイコン サーバーのアイコン LibreChat - The Open-Source AI Platform\nhttps://www.librechat.ai/ (2026年8月15日) ggml-org/llama.cpp: LLM inference in C/C++\nhttps://github.com/ggml-org/llama.cpp (2026年8月15日) LM Studio - Local AI on your computer | LM Studio\nhttps://lmstudio.ai/ (2026年8月15日) Nvidia | Logopedia | Fandom\nhttps://logos.fandom.com/wiki/Nvidia (2026年8月15日) Intel Arc | Logopedia | Fandom\nhttps://logos.fandom.com/wiki/Intel_Arc (2026年8月15日) Google, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Google_Chrome_icon_(February_2022).svg (2026年8月15日) Mozilla Corporation, MPL 2 https://www.mozilla.org/en-US/MPL/2.0/, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Firefox_logo,_2019.svg (2026年8月15日) Vivaldi Technologies, CC BY 4.0 https://creativecommons.org/licenses/by/4.0, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Vivaldi_web_browser_logo.svg (2026年8月15日) 参考にしたサイトとか ローカルLLM (Gemma4-31B) (2026年5月22日)\nConfig Structure | LibreChat\nhttps://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/config (2026年8月15日)\nLibreChat - The Open-Source AI Platform\nhttps://www.librechat.ai/ (2026年5月22日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年5月22日)\nServe on Local Network | LM Studio\nhttps://lmstudio.ai/docs/developer/core/server/serve-on-network (2026年8月15日)\n[Bug]: File upload context processing not happening for non-agents · Issue #10493 · LibreChat-AI/LibreChat\nhttps://github.com/LibreChat-AI/LibreChat/issues/10493 (2026年9月27日)\nIs \u0026ldquo;Upload for Text\u0026rdquo; broken? · LibreChat-AI/LibreChat · Discussion #10051 · GitHub\nhttps://github.com/LibreChat-AI/LibreChat/discussions/10051 (2026年9月27日)\nUpload as Text not sending the user message along with the system message · LibreChat-AI/LibreChat · Discussion #9986 · GitHub\nhttps://github.com/LibreChat-AI/LibreChat/discussions/9986 (2026年9月27日)\n[Enhancement]: Allow sending file attachments without requiring a text message. · Issue #13646 · LibreChat-AI/LibreChat\nhttps://github.com/LibreChat-AI/LibreChat/issues/13646 (2026年9月27日)\nModel Specs Object Structure | LibreChat\nhttps://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/model_specs#maxcontexttokens (2026年9月27日)\nExcessive image compression/downscaling during upload degrades Vision Model performance · LibreChat-AI/LibreChat · Discussion #11065 · GitHub\nhttps://github.com/LibreChat-AI/LibreChat/discussions/11065 (2026年9月27日)\nFile Config Object Structure | LibreChat\nhttps://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/file_config (2026年9月27日)\nAdd option to disable image resize · LibreChat-AI/LibreChat · Discussion #6777 · GitHub\nhttps://github.com/LibreChat-AI/LibreChat/discussions/6777 (2026年9月27日)\nModel Specs Object Structure | LibreChat\nhttps://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/model_specs (2026年9月27日)\nFastMCP: The Framework for MCP - FastMCP\nhttps://gofastmcp.com/getting-started/welcome (2026年9月27日)\n","permalink":"https://www.nyanmo.info/posts/linux/librechat/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　LibreChat を使っているうちに、色々躓いたことがあったので記録したい。躓いたことでなくてもまとめておきたいことは書きたい。\u003c/p\u003e\n\u003ch2 id=\"前提条件\"\u003e前提条件\u003c/h2\u003e\n\u003ch3 id=\"環境構築をしたディレクトリが以下のパスになっている\"\u003e環境構築をしたディレクトリが以下のパスになっている\u003c/h3\u003e\n\u003cp\u003e　LibreChat の Docker 関連のファイルが以下のディレクトリにある事を前提に進める。通常であれば、各個人に合わせて作業して良い。私の場合はあくまで以下のパスにあるというだけである。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~/LibreChat\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"llm-サーバの構成とlibrechatの関係\"\u003eLLM サーバの構成と、LibreChatの関係\u003c/h3\u003e\n\u003cp\u003e　以下の図のような関係になっている事を前提にする。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/LibreChat/LLM%20server%20configulation.png#center\"\n         alt=\"LLM server configulation\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"maindesktop-エンドポイント\"\u003eMainDesktop エンドポイント\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eエンドポイントまでのアドレスとポート番号の仮定\u003cbr\u003e\n\u003ccode\u003ehttp://192.168.x.a:8080/v1\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e詳細な役割の説明\u003cbr\u003e\n　純粋に llama.cpp を動かして1つのモデルを読み込んでいる LLM サーバ専用(Gemma-4-31Bを動かす専用)に割り当てた PC である。LibreChat はここではホストしていない。Intel ARC の XPU 環境であり、LM Studio ではそのポテンシャルを引き出せないため、llama.cpp を専用にコンパイルしてセットアップしてある。OpenAI 互換 API 経由で利用可能にしてある。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"dataserver-エンドポイント\"\u003eDataServer エンドポイント\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eエンドポイントまでのアドレスとポート番号の仮定\u003cbr\u003e\n\u003ccode\u003ehttp://192.168.x.b:1234/v1\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e詳細な役割の説明\u003cbr\u003e\n　LM Studio を使って LLM を動かしている。こちらは、MainDesktop と異なり、NVIDIA の CUDA 環境であるため、LM Studio でポテンシャルを引き出すことができることから、LM Studio を使っている。LM Studio 標準の開発者機能から、OpenAI 互換 API 経由で利用可能にしてある。基本的に LM Studio の LLM サーバーが、LibreChat の要求に答えて選択されたモデルを自動的にロードし動かしてくれるため、いろんなモデルを動かすために使う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"その他諸々\"\u003eその他諸々\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eLinux 環境である\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edocker\u003c/code\u003e、\u003ccode\u003edocker-compose\u003c/code\u003eパッケージが入っている\u003c/li\u003e\n\u003cli\u003e全ては LAN 内で行われ、グローバル空間からのアクセスはできないようにしてある環境である。外出先からの利用はすべて VPN を通じて行う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"基本的な操作\"\u003e基本的な操作\u003c/h2\u003e\n\u003ch3 id=\"設定ファイル保存場所\"\u003e設定ファイル保存場所\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~/LibreChat/librechat.yaml\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"設定反映方法-librechatyaml\"\u003e設定反映方法 (librechat.yaml)\u003c/h3\u003e\n\u003cp\u003e　私の場合は、\u003ccode\u003e~/LibreChat\u003c/code\u003eにおいて以下のスクリプトを\u003ccode\u003erestart.sh\u003c/code\u003eとして配置し、実行することで\u003ccode\u003elibrechat.yaml\u003c/code\u003eの変更内容を反映できる事を確認した。docker グループに入っていないユーザは、管理者権限を付与してコマンドを実行することで docker を操作できる。\u003c/p\u003e","title":"LibreChat運用に関する記録"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 Intel Arc A770 LE を使っているが、NVIDIA の RTX や H100 などと異なり、標準でのサポートが薄い。そのため、フルで性能を引き出したい場合は、自分で LLM なら llama.cpp などを OneAPI を使ってコンパイルする必要がある。\nLLM に関しては、当初は Intel Arc の環境において LM Studio を利用していたが、Vulkan でしか少なくとも現状では動作させることができなかった。Ollama についても試したが、どう頑張っても Apple の メタルプラットフォーム向けにしかコンパイルが動作せず、どうしよもない感じであった。そこでそれらのバックエンドである、llama.cpp を直接コンパイルして動かすことが考えられ、フロントは別に LibreChat を独立して用意する事が考えられた。\n標準でも Vulkan の互換モードで動作し、使えないということはないが、多少性能が失われる。ただ、SYCL など向けに、Intel Arc を最大限使えるようにしようとすると、自分でコンパイルする必要がある。専用に用意しなければ現状では llama.cpp などは CPU しか利用できないとして Intel Arc をそもそも認識しないという挙動になった。またコンパイル自体や、コンパイル後のバイナリの扱いについて、特別な扱いが必要である。\nIntel が公式で llama.cpp などのバイナリを配布していたりするが、バージョンが古く新しいモデルが動かないなど、弊害が生じる場合があった。\nこれらのことから、Intel Arc 向けに今回は、llama.cpp を SYCL を使えるようにコンパイルすることにした。また、PKGBUILD も作成し、手動で手順を踏まなくても、ある程度自動で Arch Linux や同じ系列の OS を使っていれば、環境が整うように工夫した。\nGemini Fast 3 を作業補助として使い、動くか確認しながら作業をした。ただそれだけだと、情報が十分まとまっておらず、環境を再構築する必要が生じたときなどに困難が想像されたため、記録を残して現状を整理したい。\nなお、特にコンパイルや SYCL 周りの環境変数などは、LLM が吐き出したものをそのまま使っているだけの部分が多く色々間違っていたりする可能性がある。あくまで私の環境でやってみて動くかというのを基準にして書いている。\nllama.cpp をコンパイル OneAPI を導入する yay -Sy intel-oneapi-toolkit level-zero-headers intel-compute-runtime level-zero-loader onetbb # sudo pacman -Sy intel-oneapi-toolkit level-zero-headers intel-compute-runtime level-zero-loader onetbb llama.cppのリポジトリをクローン git clone https://github.com/ggml-org/llama.cpp.git cd llama.cpp コンパイル # OneAPI を読み込む source /opt/intel/oneapi/setvars.sh export CFLAGS=\u0026#34;-fno-stack-protector -U_FORTIFY_SOURCE\u0026#34; export CXXFLAGS=\u0026#34;-fno-stack-protector -U_FORTIFY_SOURCE\u0026#34; # コンパイル cmake -B build -S llama.cpp -G Ninja \\ -DGGML_SYCL=ON \\ -DBUILD_SHARED_LIBS=ON \\ -DCMAKE_C_COMPILER=icx \\ -DCMAKE_CXX_COMPILER=icpx \\ -DCMAKE_BUILD_TYPE=Release \\ -DCMAKE_INSTALL_PREFIX=/usr cmake --build build SYCL を有効にした状態で llama.cpp を起動する # オプションの調整用環境変数 export ZE_MAX_UNUSED_DEVICE_ALLOCATIONS_SIZE=1 export SYCL_PI_LEVEL_ZERO_DEVICE_RESERVE_MEMORY=0 export SYCL_PI_LEVEL_ZERO_DEVICE_SCOPE_EVENTS=0 export SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1 export SYCL_PI_LEVEL_ZERO_TRACK_INDIRECT_ACCESS_MEMORY=1 export L0_SCS_MAX_MEM_ALLOC_SIZE=16106127360 export SYCL_PI_LEVEL_ZERO_USM_RESIDENT=0 # oneAPIの環境を読み込む source /opt/intel/oneapi/setvars.sh # llama.cpp に関連する設定について MODEL_PATH=\u0026#34;/modelPath/lmstudio/lmstudio-community/gpt-oss-20b-GGUF/gpt-oss-20b-MXFP4.gguf\u0026#34; PORT=8080 HOST=0.0.0.0 GPU_LAYERS=999 ADDITIONAL_ARGS=\u0026#34;--ctx-size 4096 --parallel 2\u0026#34; # 画像などを添付する場合は、モデルファイルに付属している mmprojファイルもセットで指定する必要がある。 # ADDITIONAL_ARGS=\u0026#34;--ctx-size 4096 --parallel 2 --mmproj ファイルパス.gguf\u0026#34; # dnnl のパスを通す export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/oneapi/dnnl/latest/lib # サーバー起動 exec /usr/bin/llama-server \\ -m \u0026#34;$MODEL_PATH\u0026#34; \\ --port \u0026#34;$PORT\u0026#34; \\ --host \u0026#34;$HOST\u0026#34; \\ -ngl \u0026#34;$GPU_LAYERS\u0026#34; \\ $ADDITIONAL_ARGS llama.cpp の PKGBUILD について 使い方 すでに作業ディレクトリを作成し、配置するファイルの事項に従って必要なファイルを配置していることを前提とする。\n# インストール makepkg -si # 事前に用意したモデルパスを指定するなど、動作に必要な設定を行う 以下は neovim の例である sudo nvim /etc/llama.cpp/config.conf # サービスの有効化 sudo systemctl enable --now llama-cpp 配置するファイル 以下は、Gemini Fast 3を使って要件を与えて生成させた上で更に調整をかけたものである。基本的に不完全なので環境に合わせてさらなる調整が必要だと思われる。以下はすべて作業ディレクトリに配置する。\nPKGBUILD pkgname=llama-cpp-sycl-git pkgver=r8833.45cac7ca70 pkgrel=1 pkgdesc=\u0026#34;LLM inference with Intel GPU (SYCL). Includes systemd service and config.\u0026#34; arch=(\u0026#39;x86_64\u0026#39;) url=\u0026#34;https://github.com/ggerganov/llama.cpp\u0026#34; license=(\u0026#39;MIT\u0026#39;) depends=(\u0026#39;intel-oneapi-toolkit level-zero-headers intel-compute-runtime level-zero-loader onetbb\u0026#39;) makedepends=(\u0026#39;git\u0026#39; \u0026#39;cmake\u0026#39; \u0026#39;ninja\u0026#39;) options=(\u0026#39;!strip\u0026#39; \u0026#39;!debug\u0026#39;) provides=(\u0026#39;llama-cpp\u0026#39;) conflicts=(\u0026#39;llama-cpp\u0026#39;) source=(\u0026#39;git+https://github.com/ggerganov/llama.cpp.git\u0026#39; \u0026#39;config.conf\u0026#39; \u0026#39;llama-server-launcher\u0026#39; \u0026#39;llama-cpp.service\u0026#39;) sha256sums=(\u0026#39;SKIP\u0026#39; \u0026#39;SKIP\u0026#39; \u0026#39;SKIP\u0026#39; \u0026#39;SKIP\u0026#39;) pkgver() { cd llama.cpp printf \u0026#34;r%s.%s\u0026#34; \u0026#34;$(git rev-list --count HEAD)\u0026#34; \u0026#34;$(git rev-parse --short HEAD)\u0026#34; } build() { source /opt/intel/oneapi/setvars.sh export CFLAGS=\u0026#34;-fno-stack-protector -U_FORTIFY_SOURCE\u0026#34; export CXXFLAGS=\u0026#34;-fno-stack-protector -U_FORTIFY_SOURCE\u0026#34; export CFLAGS=\u0026#34;-O3 -march=native -DNDEBUG\u0026#34; export CXXFLAGS=\u0026#34;-O3 -march=native -DNDEBUG\u0026#34; cmake -B build -S llama.cpp -G Ninja \\ -DGGML_SYCL=ON \\ -DBUILD_SHARED_LIBS=ON \\ -DCMAKE_C_COMPILER=icx \\ -DCMAKE_CXX_COMPILER=icpx \\ -DCMAKE_BUILD_TYPE=Release \\ -DSYCL_INCLUDE_DIR=\u0026#34;/opt/intel/oneapi/compiler/latest/lib\u0026#34; \\ -DSYCL_LIBRARY_DIR=\u0026#34;/opt/intel/oneapi/compiler/latest/include\u0026#34; \\ -DGGML_SYCL_F16=ON \\ -DCMAKE_INSTALL_PREFIX=/usr cmake --build build } package() { # 1. バイナリ・ライブラリのインストール（前述と同じ） DESTDIR=\u0026#34;$pkgdir\u0026#34; cmake --install build install -d \u0026#34;$pkgdir/usr/lib\u0026#34; find build/bin -name \u0026#34;*.so*\u0026#34; -exec cp -d {} \u0026#34;$pkgdir/usr/lib/\u0026#34; \\; install -d \u0026#34;$pkgdir/usr/bin\u0026#34; find build/bin -executable -type f -not -name \u0026#34;*.so*\u0026#34; -exec install -m755 {} \u0026#34;$pkgdir/usr/bin/\u0026#34; \\; # 2. ユーザー名の動的取得 # PKGBUILDを実行している現在のユーザー名を取得 local _real_user=${SUDO_USER:-$(whoami)} # 3. systemdサービスファイルの加工とインストール # %%USER%% を実際のユーザー名に置換して一時ファイルを作成し、それをインストール sed \u0026#34;s/%%USER%%/$_real_user/g\u0026#34; \u0026#34;$srcdir/llama-cpp.service\u0026#34; \u0026gt; \u0026#34;$srcdir/llama-cpp.service.tmp\u0026#34; install -Dm644 \u0026#34;$srcdir/llama-cpp.service.tmp\u0026#34; \u0026#34;$pkgdir/usr/lib/systemd/system/llama-cpp.service\u0026#34; # 4. その他のファイルのインストール install -Dm644 \u0026#34;$srcdir/config.conf\u0026#34; \u0026#34;$pkgdir/etc/llama.cpp/config.conf\u0026#34; install -m755 \u0026#34;$srcdir/llama-server-launcher\u0026#34; \u0026#34;$pkgdir/usr/bin/llama-server-launcher\u0026#34; install -Dm644 llama.cpp/LICENSE \u0026#34;$pkgdir/usr/share/licenses/$pkgname/LICENSE\u0026#34; } config.conf # /etc/llama.cpp/config.conf # モデルのフルパス MODEL_PATH=\u0026#34;ReplaceThisYourLocalModelFileToUse\u0026#34; # 待ち受け設定 PORT=8080 HOST=0.0.0.0 # GPU設定 (-ngl は VRAM 16GB に合わせて全レイヤー投入) GPU_LAYERS=999 # 追加オプション (必要に応じて) ADDITIONAL_ARGS=\u0026#34;--ctx-size 4096 --parallel 2\u0026#34; llama-cpp.service [Unit] Description=Llama.cpp Server with Intel Arc SYCL After=network.target [Service] Environment=ZE_MAX_UNUSED_DEVICE_ALLOCATIONS_SIZE=1 Environment=SYCL_PI_LEVEL_ZERO_DEVICE_RESERVE_MEMORY=0 Environment=SYCL_PI_LEVEL_ZERO_DEVICE_SCOPE_EVENTS=0 Environment=SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS=1 Environment=SYCL_PI_LEVEL_ZERO_TRACK_INDIRECT_ACCESS_MEMORY=1 Environment=L0_SCS_MAX_MEM_ALLOC_SIZE=16106127360 Environment=SYCL_PI_LEVEL_ZERO_USM_RESIDENT=0 LimitMEMLOCK=infinity LimitSTACK=infinity Type=simple User=%%USER%% Group=render SupplementaryGroups=video ExecStart=/usr/bin/llama-server-launcher Restart=always RestartSec=5 [Install] WantedBy=multi-user.target llama-server-launcher #!/bin/bash # /usr/bin/llama-server-launcher # OneAPI のランタイム読み込み source /opt/intel/oneapi/setvars.sh source /etc/llama.cpp/config.conf # dnnl 関連の動的ライブラリについて export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/opt/intel/oneapi/dnnl/latest/lib # サーバー起動 exec /usr/bin/llama-server \\ -m \u0026#34;$MODEL_PATH\u0026#34; \\ --port \u0026#34;$PORT\u0026#34; \\ --host \u0026#34;$HOST\u0026#34; \\ -ngl \u0026#34;$GPU_LAYERS\u0026#34; \\ $ADDITIONAL_ARGS その他記録 llama.cpp オプション 特定IPアドレスや、ポートで動かす llama-server --host [IPアドレスやドメイン名] --port [ポート番号] コンテキスト長指定 llama-server --ctx-size 70000 モデル指定 llama-server -m [モデルまでの絶対パス] モデルGPU オフロードの程度指定 llama-server -ngl 999 画像を認識できるモデル付属の追加モデルを指定 llama-server --mmproj [mmprojモデルまでの絶対パス] --embeddings SYCL デバイスの存在確認 sycl-lsとllama-cliコマンドを使った方法を紹介する。llama-cliを使った方法については、level-zero-headersパッケージを入れた状態で、llama.cpp をコンパイルしないと正常動作しないので注意する。\nsource /opt/intel/oneapi/setvars.sh # :: initializing oneAPI environment ... # -bash: BASH_VERSION = 5.3.15(1)-release # args: Using \u0026#34;$@\u0026#34; for setvars.sh arguments: # :: ccl -- latest # :: compiler -- latest # :: debugger -- latest # :: dev-utilities -- latest # :: dnnl -- latest # :: dpl -- latest # :: ipp -- latest # :: ippcp -- latest # :: mkl -- latest # :: mpi -- latest # :: tbb -- latest # :: tcm -- latest # :: umf -- latest # :: vtune -- latest # :: oneAPI environment initialized :: sycl-ls # [level_zero:gpu][level_zero:0] Intel(R) oneAPI Unified Runtime over Level-Zero, Intel(R) Arc(TM) A770 Graphics 12.55.8 [1.17.39395] # [level_zero:gpu][level_zero:1] Intel(R) oneAPI Unified Runtime over Level-Zero, Intel(R) Arc(TM) A770 Graphics 12.55.8 [1.17.39395] # [opencl:cpu][opencl:0] Intel(R) OpenCL, Intel(R) Xeon(R) CPU E5-2667 v4 @ 3.20GHz OpenCL 3.0 (Build 0) [2026.21.3.0.31_160000] # [opencl:gpu][opencl:1] Intel(R) OpenCL Graphics, Intel(R) Arc(TM) A770 Graphics OpenCL 3.0 NEO [26.31.39395] # [opencl:gpu][opencl:2] Intel(R) OpenCL Graphics, Intel(R) Arc(TM) A770 Graphics OpenCL 3.0 NEO [26.31.39395] llama-cli --list-devices # Available devices: # SYCL0: Intel(R) Arc(TM) A770 Graphics (16288 MiB, 16288 MiB free) # SYCL1: Intel(R) Arc(TM) A770 Graphics (16288 MiB, 16288 MiB free) 追記 2026/9/6 問題の説明 llama.cpp 環境を構築してから、OneAPI や llama.cpp において最適化が進んでいると考えられ、アップグレードを試みた。そのところ、failed to get device memory size となり llama.cpp が起動しないという状況になった。\n私の環境の場合、--cpu-moeと--fit offを llama.cpp の起動オプションに指定していたことが良くなかったようである。以下のサイトに示されることと同じ問題だとは思うが、私の環境の場合、Intel Arc A770 LE の2枚構成であり、dGPU であって、iGPU ではない。このことから考えられることは、--cpu-moeと--fit off オプションは、iGPU を使うときと同じメインメモリの管理に関する症状にぶつかっているのではないかということであった。私の場合、そのオプションはとりあえずつけていただけで明確に効果は体感できなかったため、単に外すことで問題が解決した。\nEval bug: SYCL backend aborts at model load on Lunar Lake iGPU (Arc 140V) — device memory query fails with both Level Zero and SYCL APIs · Issue #28134 · ggml-org/llama.cpp\nhttps://github.com/ggml-org/llama.cpp/issues/28134 (2026年9月6日) 対処 llama.cpp の起動オプションから--cpu-moeと--fit offを外す。また、llama.cpp コンパイル時に、以下のパッケージがあったほうがいいことがわかった。\nyay -S level-zero-headers # sudo pacman -S level-zero-headers Arch Linux - level-zero-headers 1.32.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/level-zero-headers/ (2026年9月6日) 問題発生時のログ llama-server のログ # Sep 06 04:41:55 HostName llama-server-launcher[396455]: ⚠ warning: File \u0026#34;/opt/intel/oneapi/compiler/2026.0/lib/libsycl.so.9.0.0-gdb.py\u0026#34; auto-loading has been declined by your `auto-load safe-path\u0026#39; set to \u0026#34;$debugdir:$datadir/auto-load\u0026#34;. # Sep 06 04:41:55 HostName llama-server-launcher[396455]: To enable execution of this file add # Sep 06 04:41:55 HostName llama-server-launcher[396455]: add-auto-load-safe-path /opt/intel/oneapi/compiler/2026.0/lib/libsycl.so.9.0.0-gdb.py # Sep 06 04:41:55 HostName llama-server-launcher[396455]: line to your configuration file \u0026#34;/root/.config/gdb/gdbinit\u0026#34;. # Sep 06 04:41:55 HostName llama-server-launcher[396455]: To completely disable this security protection add # Sep 06 04:41:55 HostName llama-server-launcher[396455]: set auto-load safe-path / # Sep 06 04:41:55 HostName llama-server-launcher[396455]: line to your configuration file \u0026#34;/root/.config/gdb/gdbinit\u0026#34;. # Sep 06 04:41:55 HostName llama-server-launcher[396455]: For more information about this security protection see the # Sep 06 04:41:55 HostName llama-server-launcher[396455]: \u0026#34;Auto-loading safe path\u0026#34; section in the GDB manual. E.g., run from the shell: # Sep 06 04:41:55 HostName llama-server-launcher[396455]: info \u0026#34;(gdb)Auto-loading safe path\u0026#34; # Sep 06 04:41:56 HostName llama-server-launcher[396455]: [Thread debugging using libthread_db enabled] # Sep 06 04:41:56 HostName llama-server-launcher[396455]: Using host libthread_db library \u0026#34;/usr/lib/libthread_db.so.1\u0026#34;. # Sep 06 04:41:56 HostName llama-server-launcher[396455]: 0x0000148a924a07f2 in ?? () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #0 0x0000148a924a07f2 in ?? () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #1 0x0000148a9249481c in ?? () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #2 0x0000148a92494864 in ?? () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #3 0x0000148a92504fcf in wait4 () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #4 0x0000148a92b26c2a in ggml_print_backtrace () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #5 0x0000148a92b25d89 in ggml_abort () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #6 0x0000148a8b89d3a6 in ggml_backend_sycl_device_get_memory(ggml_backend_device*, unsigned long*, unsigned long*) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #7 0x0000148a8b89d4c7 in ggml_backend_sycl_device_get_props(ggml_backend_device*, ggml_backend_dev_props*) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #8 0x0000148a91aa5768 in llama_model_load_from_file_impl(gguf_context*, void (*)(ggml_tensor*, void*), void*, std::__cxx11::basic_string\u0026lt;char, std::char_traits\u0026lt;char\u0026gt;, std::allocator\u0026lt;char\u0026gt; \u0026gt; const\u0026amp;, std::vector\u0026lt;std::__cxx11::basic_string\u0026lt;char, std::char_traits\u0026lt;char\u0026gt;, std::allocator\u0026lt;char\u0026gt; \u0026gt;, std::allocator\u0026lt;std::__c\u0026gt; # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #9 0x0000148a91aa68dc in llama_model_load_from_file () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #10 0x0000148a91fe45b0 in common_init_result::common_init_result(common_params\u0026amp;, bool) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #11 0x0000148a91fe6d25 in common_init_from_params(common_params\u0026amp;, bool) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #12 0x0000148a92d35027 in server_context_impl::load_model(common_params\u0026amp;) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #13 0x0000148a92c97a70 in llama_server(common_params\u0026amp;, int, char**) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #14 0x0000148a92c890ff in llama_server(int, char**) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #15 0x0000148a92427781 in ?? () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #16 0x0000148a924278b9 in __libc_start_main () from /usr/lib/libc.so.6 # Sep 06 04:41:56 HostName llama-server-launcher[396455]: #17 0x00000000004024e5 in _start () # Sep 06 04:41:56 HostName llama-server-launcher[396455]: [Inferior 1 (process 395904) detached] # Sep 06 04:41:56 HostName systemd-coredump[396530]: Process 395904 (llama-server) of user 0 terminated abnormally with signal 6/ABRT, processing... # Sep 06 04:41:56 HostName systemd[1]: Started Process Core Dump (PID 396530/UID 0). # Sep 06 04:41:56 HostName systemd[1]: Started Pass systemd-coredump journal entries to relevant user for potential DrKonqi handling. # Sep 06 04:41:56 HostName systemd-coredump[396531]: Removed old coredump core.llama-server.0.bd6f7a4429224d2798cf20cef2698b59.238728.1787688392000000.zst. # Sep 06 04:41:56 HostName drkonqi-coredump-processor[396532]: Entry doesn\u0026#39;t look like a dump. This may have been a vaccum run. Nothing to process. # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName (sd-parse-elf)[396623]: Could not parse number of program headers from core file: invalid `Elf\u0026#39; handle # Sep 06 04:41:59 HostName systemd-coredump[396531]: [🡕] Process 395904 (llama-server) of user 0 dumped core. # # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0.23.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0.23.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-cpu.so.0.23.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-cpu.so.0.23.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama.so.0.4.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama.so.0.4.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0.4.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0.4.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libmtmd.so.0.4.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libmtmd.so.0.4.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0.23.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0.23.0 # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml.so.0.23.0 without build-id. # Module /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml.so.0.23.0 # Module libcommon_clang.so.2026.21.3.0 without build-id. # Module libintelocl.so without build-id. # Module libOpenCL.so.1 without build-id. # Module libur_adapter_opencl.so.0 without build-id. # Module libur_adapter_level_zero_v2.so.0 without build-id. # Module libur_adapter_level_zero.so.0 without build-id. # Module libtcm.so.1 without build-id. # Module libtbbmalloc.so.2 without build-id. # Module libirng.so without build-id. # Module libur_loader.so.0 without build-id. # Module libtbb.so.12 without build-id. # Module libmkl_core.so.3 without build-id. # Module libmkl_tbb_thread.so.3 without build-id. # Module libmkl_intel_ilp64.so.3 without build-id. # Module libmkl_sycl_blas.so.6 without build-id. # Module libsycl.so.9 without build-id. # Module libdnnl.so.3 without build-id. # Module libiomp5.so without build-id. # Module libintlc.so.5 without build-id. # Module libimf.so without build-id. # Module libsvml.so without build-id. # Module llama-server without build-id. # Stack trace of thread 395904: # #0 0x0000148a9249a01c n/a (libc.so.6 + 0x9a01c) # #1 0x0000148a9243e5d0 raise (libc.so.6 + 0x3e5d0) # lines 1172-1262/1360 94% # # # # # # Sep 06 05:19:06 HostName llama-server-launcher[431198]: 0.00.194.934 W srv llama_server: more info: https://github.com/ggml-org/llama.cpp/pull/25655 # Sep 06 05:19:06 HostName llama-server-launcher[431198]: 0.00.194.935 W srv llama_server: ----------------- # Sep 06 05:19:06 HostName llama-server-launcher[431198]: 0.00.196.237 I srv load_model: loading model \u0026#39;/home/UserName/net/sub/Desktop/Data/JailbreakedLLMmodel/downloaded/gemma-4-31B-it-heretic/coder3101_gemma_4_31b_it_heretic-Q4_K_M.gguf\u0026#39; # Sep 06 05:19:07 HostName llama-server-launcher[431198]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/llama.cpp/ggml/src/ggml-sycl/ggml-sycl.cpp:6101: [ggml_backend_sycl_device_get_memory] failed to get device memory size # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0(+0x15d48) [0x153cd3a5ed48] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0(ggml_print_backtrace+0x285) [0x153cd3a5ed25] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0(ggml_abort+0x109) [0x153cd3a5dd89] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0(+0x9d3a6) [0x153ccc09d3a6] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0(+0x9d4c7) [0x153ccc09d4c7] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama.so.0(+0xa5768) [0x153cd22a5768] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama.so.0(llama_model_load_from_file+0xfc) [0x153cd22a68dc] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0(_ZN18common_init_resultC2ER13common_paramsb+0x590) [0x153cd27e45b0] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0(_Z23common_init_from_paramsR13common_paramsb+0x35) [0x153cd27e6d25] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so(_ZN19server_context_impl10load_modelER13common_params+0x977) [0x153cd3535027] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so(_Z12llama_serverR13common_paramsiPPc+0x8e90) [0x153cd3497a70] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-server-impl.so(_Z12llama_serveriPPc+0x7f) [0x153cd34890ff] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /usr/lib/libc.so.6(+0x27781) [0x153cd2c27781] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /usr/lib/libc.so.6(__libc_start_main+0x89) [0x153cd2c278b9] # Sep 06 05:19:07 HostName llama-server-launcher[431729]: /usr/bin/llama-server() [0x4024e5] # Sep 06 05:19:07 HostName systemd-coredump[431730]: Process 431198 (llama-server) of user 0 terminated abnormally with signal 6 ちなみに、別に llama.cpp を完全に起動せず、SYCL デバイスをリスティングしようとしただけでも今回の問題に巻き込まれるようである。設定次第では動きはするので、issue はすでに GitHub に立っているし、修正されるまでは時間の問題な気がする。\nllama-cli \u0026ndash;list-devices が機能しない様子 llama-cli --list-devices # Available devices: # /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/llama.cpp/ggml/src/ggml-sycl/ggml-sycl.cpp:6101: [ggml_backend_sycl_device_get_memory] failed to get device memory size # [New LWP 9099] # [New LWP 9098] # [New LWP 9097] # # This GDB supports auto-downloading debuginfo from the following URLs: # \u0026lt;https://debuginfod.archlinux.org\u0026gt; # Enable debuginfod for this session? (y or [n]) [answered N; input not from terminal] # Debuginfod has been disabled. # To make this setting permanent, add \u0026#39;set debuginfod enabled off\u0026#39; to .gdbinit. # Registering SYCL extensions for gdb # [Thread debugging using libthread_db enabled] # Using host libthread_db library \u0026#34;/usr/lib/libthread_db.so.1\u0026#34;. # 0x00007f9cbfea07f2 in ?? () from /usr/lib/libc.so.6 # #0 0x00007f9cbfea07f2 in ?? () from /usr/lib/libc.so.6 # #1 0x00007f9cbfe9481c in ?? () from /usr/lib/libc.so.6 # #2 0x00007f9cbfe94864 in ?? () from /usr/lib/libc.so.6 # #3 0x00007f9cbff04fcf in wait4 () from /usr/lib/libc.so.6 # #4 0x00007f9cc0048c7a in ggml_print_backtrace () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0 # #5 0x00007f9cc0047d51 in ggml_abort () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-base.so.0 # #6 0x00007f9cb8c9d476 in ggml_backend_sycl_device_get_memory(ggml_backend_device*, unsigned long*, unsigned long*) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libggml-sycl.so.0 # #7 0x00007f9cbf0c6253 in common_print_available_devices() () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # #8 0x00007f9cbf0f10c6 in common_params_parser_init(common_params\u0026amp;, llama_example, void (*)(int, char**))::$_151::__invoke(common_params\u0026amp;) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # #9 0x00007f9cbf0e58fc in common_params_parse_ex(int, char**, common_params_context\u0026amp;) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # #10 0x00007f9cbf0e3965 in common_params_parse(int, char**, common_params\u0026amp;, llama_example, void (*)(int, char**)) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-common.so.0 # #11 0x00007f9cc0def135 in llama_cli(int, char**) () from /home/UserName/scripts/llama.cpp/install/llama.cpp-install/ArchInstall/src/build/bin/libllama-cli-impl.so # #12 0x00007f9cbfe27781 in ?? () from /usr/lib/libc.so.6 # #13 0x00007f9cbfe278b9 in __libc_start_main () from /usr/lib/libc.so.6 # #14 0x00000000004363d5 in _start () # [Inferior 1 (process 9095) detached] # Aborted (core dumped) llama-cli --list-devices 更新のバージョン OneAPI yay -Qs oneapi # pacman -Qs oneapi # local/intel-compute-runtime 26.31.39395.13-1 # Intel(R) Graphics Compute Runtime for oneAPI Level Zero and OpenCL(TM) Driver # local/intel-level-zero-raytracing-support 1.2.4-1 # Intel oneAPI Raytracing Support # local/intel-oneapi-toolkit 2026.0.1.27+c9c3d3e3_ddb4_490e_bb41_6e9041ba32a7-2 # Intel oneAPI Toolkit for Linux # local/level-zero-headers 1.32.0-1 # API for accessing low level interfaces in oneAPI platform devices (headers) # local/level-zero-loader 1.32.0-1 # API for accessing low level interfaces in oneAPI platform devices (loader) # local/onetbb 2023.1.0-1 # oneAPI Threading Building Blocks - a high level abstract threading library llama.cpp (6a1a922) 使った画像とか Intel Arc | Logopedia | Fandom\nhttps://logos.fandom.com/wiki/Intel_Arc?file=Intel_Arc_Badge.png (2026年6月27日) GitHub - ggml-org/llama.cpp: LLM inference in C/C++ · GitHub\nhttps://github.com/ggml-org/llama.cpp (2026年6月27日) 参考にしたサイトとか ggml-org/llama.cpp: LLM inference in C/C++\nhttps://github.com/ggml-org/llama.cpp (2026年5月22日)\nllama.cpp/docs/backend/SYCL.md at master · ggml-org/llama.cpp\nhttps://github.com/ggml-org/llama.cpp/blob/master/docs/backend/SYCL.md (2026年5月22日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年5月22日)\nOllama\nhttps://ollama.com/ (2026年6月27日)\nLM Studio - Local AI on your computer\nhttps://lmstudio.ai/ (2026年6月27日)\nEval bug: SYCL backend aborts at model load on Lunar Lake iGPU (Arc 140V) — device memory query fails with both Level Zero and SYCL APIs · Issue #28134 · ggml-org/llama.cpp\nhttps://github.com/ggml-org/llama.cpp/issues/28134 (2026年9月6日)\nMatrix-Meta/intel-oneapi-base-toolkit-2025: intel-oneapi-base-toolkit-2025 AUR package backup repository\nhttps://github.com/Matrix-Meta/intel-oneapi-base-toolkit-2025 (2026年9月6日)\nArch Linux - intel-oneapi-toolkit 2026.0.1.27+c9c3d3e3_ddb4_490e_bb41_6e9041ba32a7-2 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/intel-oneapi-toolkit/ (2026年9月6日)\nArch Linux - level-zero-headers 1.32.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/level-zero-headers/ (2026年9月6日)\nAUR (en) - intel-deep-learning-essentials\nhttps://aur.archlinux.org/packages/intel-deep-learning-essentials (2026年9月6日)\n","permalink":"https://www.nyanmo.info/posts/linux/llama.cpponintelarc/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Intel Arc A770 LE を使っているが、NVIDIA の RTX や H100 などと異なり、標準でのサポートが薄い。そのため、フルで性能を引き出したい場合は、自分で LLM なら llama.cpp などを OneAPI を使ってコンパイルする必要がある。\u003c/p\u003e\n\u003cp\u003e　LLM に関しては、当初は Intel Arc の環境において \u003ca href=\"https://lmstudio.ai/\"\u003eLM Studio\u003c/a\u003e を利用していたが、Vulkan でしか少なくとも現状では動作させることができなかった。\u003ca href=\"https://ollama.com/\"\u003eOllama\u003c/a\u003e についても試したが、どう頑張っても Apple の メタルプラットフォーム向けにしかコンパイルが動作せず、どうしよもない感じであった。そこでそれらのバックエンドである、\u003ca href=\"https://github.com/ggml-org/llama.cpp\"\u003ellama.cpp\u003c/a\u003e を直接コンパイルして動かすことが考えられ、フロントは別に LibreChat を独立して用意する事が考えられた。\u003c/p\u003e\n\u003cp\u003e　標準でも Vulkan の互換モードで動作し、使えないということはないが、多少性能が失われる。ただ、SYCL など向けに、Intel Arc を最大限使えるようにしようとすると、自分でコンパイルする必要がある。専用に用意しなければ現状では \u003ca href=\"https://github.com/ggml-org/llama.cpp\"\u003ellama.cpp\u003c/a\u003e などは CPU しか利用できないとして Intel Arc をそもそも認識しないという挙動になった。またコンパイル自体や、コンパイル後のバイナリの扱いについて、特別な扱いが必要である。\u003c/p\u003e\n\u003cp\u003e　Intel が公式で \u003ca href=\"https://github.com/ggml-org/llama.cpp\"\u003ellama.cpp\u003c/a\u003e などのバイナリを配布していたりするが、バージョンが古く新しいモデルが動かないなど、弊害が生じる場合があった。\u003c/p\u003e\n\u003cp\u003e　これらのことから、Intel Arc 向けに今回は、\u003ca href=\"https://github.com/ggml-org/llama.cpp\"\u003ellama.cpp\u003c/a\u003e を SYCL を使えるようにコンパイルすることにした。また、PKGBUILD も作成し、手動で手順を踏まなくても、ある程度自動で Arch Linux や同じ系列の OS を使っていれば、環境が整うように工夫した。\u003c/p\u003e\n\u003cp\u003e　\u003ca href=\"https://gemini.google.com/app\"\u003eGemini Fast 3\u003c/a\u003e を作業補助として使い、動くか確認しながら作業をした。ただそれだけだと、情報が十分まとまっておらず、環境を再構築する必要が生じたときなどに困難が想像されたため、記録を残して現状を整理したい。\u003c/p\u003e\n\u003cp\u003e　なお、特にコンパイルや SYCL 周りの環境変数などは、LLM が吐き出したものをそのまま使っているだけの部分が多く色々間違っていたりする可能性がある。あくまで私の環境でやってみて動くかというのを基準にして書いている。\u003c/p\u003e","title":"llama.cpp を Intel Arc で SYCL を使って動かす"},{"content":"この記事を作った動機 Android 端末において SoftEther VPN で稼働しているサーバに接続しようとすると、L2TP/IPsec を使った方法と、OpenVPN を使った方法の2つの接続方法がある。しかし、新しいバージョンの Android (12以降) において標準的に利用できる VPN には既に L2TP/IPsec は含まれておらず接続できない。また、OpenVPN を使った方法では、接続には成功するものの、そこに至るまでの設定が分かりづらかったり、技術的に一筋縄では行かないところが多々あった。これら経緯から、やったことについて記録を残したい。\nネットワーク構成 全体像 今回は、192.168.x.0/24 として描かれているネットワークに属するクライアントを Android スマホに見立てる。 今回問題になった特徴について 私の環境では通常のVPNネットワークと異なり、VPNに接続した先にあるネットワークを介して、更に別のネットワークにパケットを転送するPCがあって、そこを介してやり取りするという特徴があり、今回問題になった。\n記録 VPN 接続したときのスマホのルーティングテーブルの様子 基本的に OpenVPN 関連で特別なルーティング設定をしても Android OS 側は直接制御を持っていないように見受けられる。以下のように192.168.1.0/24へのルーティングは、OpenVPN 側で正しく動作していても以下のように直接は確認できない。\nadb shell cofud:/ $ ip route 10.0.0.0/8 dev ccmni1 proto kernel scope link src 10.150.92.221 192.168.30.12/30 dev tun0 proto kernel scope link src 192.168.30.13 cofud:/ $ exit 使うべきアプリ OpenVPN Connect ではなく、OpenVPN for Android を使うべき。\nAndroid ではアプリを介してしか詳細な制御ができず、OpenVPN Connect は限られた設定項目しか利用できない問題があった。ルーティングや MTU、MSS、DNSなどについて細かく設定したい場合は、OpenVPN for Android などの別のアプリが必要であった。OpenVPN Connect などのアプリは、基本的に詳細な設定ができず、かつどのように読み込ませた\u0026quot;.ovpn\u0026quot;などの設定が実際反映されているか確認が難しかったり色々困難があった。\nSoftEther 特有の事項のメモ .ovpn の設定ファイルは SoftEther VPN のサーバ管理画面で生成する。 data-ciphersについて、.ovpnの編集が必要である ... data-ciphers AES-128-CBC:AES-256-GCM:AES-128-GCM ... [ユーザ名]@[仮想ハブ名]がVPN接続時のユーザ名 パスワードは仮想ハブのアカウントと同じ。 生成された OpenVPN の設定ファイルは、L3 のものを使い、L2のものは使わない。 .ovpn の中身の変更例の一部 data-ciphers の項目を追加 （さもなくばVPN接続自体に失敗する） ... data-ciphers AES-128-CBC:AES-256-GCM:AES-128-GCM ... DNSについて設定を追加 ... dhcp-option DNS 192.168.1.1 ... routeについて設定を追加 ... route 192.168.30.0 255.255.255.0 vpn_gateway route 192.168.1.0 255.255.255.0 192.168.30.2 ... VPNに対してトラフィックは全ては流さないようにする設定を追加 ... route-nopull ... MSS、MTUサイズを障害予防のために1500から余裕を持って1000に設定 ... tun-mtu 1000 mssfix 1000 ... 以下は、SoftEther VPN が生成した.ovpnファイルを編集したものである。LLMであるGemini Fast 3も使っている。\n... ############################################################################### # The encryption and authentication algorithm. # # Default setting is good. Modify it as you prefer. # When you specify an unsupported algorithm, the error will occur. # # The supported algorithms are as follows: # cipher: [NULL-CIPHER] NULL AES-128-CBC AES-192-CBC AES-256-CBC BF-CBC # CAST-CBC CAST5-CBC DES-CBC DES-EDE-CBC DES-EDE3-CBC DESX-CBC # RC2-40-CBC RC2-64-CBC RC2-CBC CAMELLIA-128-CBC CAMELLIA-192-CBC CAMELLIA-256-CBC # auth: SHA SHA1 SHA256 SHA384 SHA512 MD5 MD4 RMD160 cipher AES-128-CBC data-ciphers AES-128-CBC:AES-256-GCM:AES-128-GCM auth SHA1 ... ############################################################################### # Custom Routing Settings (Added for Android Split Tunneling) # # デフォルトゲートウェイの変更（すべての通信をVPNに流す設定）を無効化 route-nopull # VPNの所属セグメント（192.168.30.0/24）へのルートを確立する # vpn_gateway は OpenVPNが接続時に自動取得したVPN側インターフェースを指す特殊変数です route 192.168.30.0 255.255.255.0 vpn_gateway # 192.168.1.0/24 宛ての通信のみ、ゲートウェイ 192.168.30.2 を指定してルーティング route 192.168.1.0 255.255.255.0 192.168.30.2 # DNSサーバーを 192.168.1.1 に指定 dhcp-option DNS 192.168.1.1 # MTUサイズを1000に制限 tun-mtu 1000 mssfix 1000 OpenVPN for Android アプリについて IPが割り当てられていないネットワークに対してのパケットをブロックするチェックをUI側から設定で外す。(Routing -\u0026gt; Block IPv6(or IPv4) if not used by the VPN) Use Default route を外す。 Ingnore Pushed Routesは有効のまま 他のこと adb、fastboot について AUR からインストールできるAUR (en) - android-sdk-platform-toolsはインストールしただけでは直接コマンドを使うことができないことがわかっており、以下の2ステップが必要である。\nうまく動かない様子 yay -S android-sdk-platform-tools adb # bash: adb: command not found fastboot # bash: fastboot: command not found yay -Ql android-sdk-platform-tools | grep adb # android-sdk-platform-tools /opt/android-sdk/platform-tools/adb # android-sdk-platform-tools /usr/lib/systemd/system/adb.service yay -Ql android-sdk-platform-tools | grep fastboot # android-sdk-platform-tools /opt/android-sdk/platform-tools/fastboot 2ステップ adb デーモンの起動、有効化 sudo systemctl start adb adb、fastbootバイナリがコマンドとして利用できるようにする\nこれには2通りやり方があり、adb、fastbootが配置されているパスをPATH環境変数に追加するか、すでにPATH環境変数に含まれていて認識されているパスである、/usr/binにシンボルリンクを作るという方法がある。今回は、シンボルリンクを作る方法を以下に示す。 sudo ln -s /opt/android-sdk/platform-tools/adb /usr/bin/ sudo ln -s /opt/android-sdk/platform-tools/fastboot /usr/bin/ 関係ありそうな記事 Linux 環境のおけるルーティング設定での \u0026ldquo;via\u0026rdquo; というキーワードの解釈 (iproute2) 使った画像素材とか Win 7 (Vista) のアイコン (2026年5月10日) PC のアイコン PC とインターネットのアイコン ルータのアイコン * 2 サーバーのアイコン ハブのアイコン SoftEther VPN Project - SoftEther VPN Project (SoftEther のソフトウェアのロゴ)\nhttps://www.softether.org/ (2026年5月10日) OpenVPN for Android - Apps on Google Play (アプリ自体のロゴ)\nhttps://play.google.com/store/apps/details?id=de.blinkt.openvpn\u0026amp;hl=en (2026年5月21日) 参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年5月19日) AUR (en) - android-sdk-platform-tools\nhttps://aur.archlinux.org/packages/android-sdk-platform-tools (2026年5月19日) Android12でのクライアントVPNの利用について - Cisco Community\nhttps://community.cisco.com/t5/tkb-ネットワーキング-ドキュメント/android12でのクライアントvpnの利用について/ta-p/5511446 (2026年5月21日) ","permalink":"https://www.nyanmo.info/posts/android/androidconnectvpnsoftethervpnviaopenvpn/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Android 端末において SoftEther VPN で稼働しているサーバに接続しようとすると、L2TP/IPsec を使った方法と、OpenVPN を使った方法の2つの接続方法がある。しかし、新しいバージョンの Android (12以降) において標準的に利用できる VPN には既に L2TP/IPsec は含まれておらず接続できない。また、OpenVPN を使った方法では、接続には成功するものの、そこに至るまでの設定が分かりづらかったり、技術的に一筋縄では行かないところが多々あった。これら経緯から、やったことについて記録を残したい。\u003c/p\u003e\n\u003ch2 id=\"ネットワーク構成\"\u003eネットワーク構成\u003c/h2\u003e\n\u003ch3 id=\"全体像\"\u003e全体像\u003c/h3\u003e\n\u003cp\u003e　今回は、192.168.x.0/24 として描かれているネットワークに属するクライアントを Android スマホに見立てる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/viaKeywordOnIproute2asDefaultGateway/NetworkConfigurationExplain.png#center\"\n         alt=\"ネットワーク構成図の説明\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"今回問題になった特徴について\"\u003e今回問題になった特徴について\u003c/h3\u003e\n\u003cp\u003e　私の環境では通常のVPNネットワークと異なり、VPNに接続した先にあるネットワークを介して、更に別のネットワークにパケットを転送するPCがあって、そこを介してやり取りするという特徴があり、今回問題になった。\u003c/p\u003e\n\u003ch2 id=\"記録\"\u003e記録\u003c/h2\u003e\n\u003ch3 id=\"vpn-接続したときのスマホのルーティングテーブルの様子\"\u003eVPN 接続したときのスマホのルーティングテーブルの様子\u003c/h3\u003e\n\u003cp\u003e　基本的に OpenVPN 関連で特別なルーティング設定をしても Android OS 側は直接制御を持っていないように見受けられる。以下のように\u003ccode\u003e192.168.1.0/24\u003c/code\u003eへのルーティングは、OpenVPN 側で正しく動作していても以下のように直接は確認できない。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb shell\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecofud:/ $ ip route\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e10.0.0.0/8 dev ccmni1 proto kernel scope link src 10.150.92.221 \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e192.168.30.12/30 dev tun0 proto kernel scope link src 192.168.30.13 \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecofud:/ $ exit\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"使うべきアプリ\"\u003e使うべきアプリ\u003c/h3\u003e\n\u003cp\u003e　OpenVPN Connect ではなく、OpenVPN for Android を使うべき。\u003c/p\u003e\n\u003cp\u003e　Android ではアプリを介してしか詳細な制御ができず、OpenVPN Connect は限られた設定項目しか利用できない問題があった。ルーティングや MTU、MSS、DNSなどについて細かく設定したい場合は、OpenVPN for Android などの別のアプリが必要であった。OpenVPN Connect などのアプリは、基本的に詳細な設定ができず、かつどのように読み込ませた\u0026quot;.ovpn\u0026quot;などの設定が実際反映されているか確認が難しかったり色々困難があった。\u003c/p\u003e","title":"Android 端末をなんとかして VPN 接続させる"},{"content":"この記事を作った動機 Linux 環境において、VPN 環境についてトラブルシュートしていたところ、設定ミスが発生した。その原因として、viaという単語を正しく解釈できておらず、VPN クライアントの設定ミスでパケットをクライアント内のネットワークでループさせていたということがあった。今回の記事では、そのことについて軽くまとめたい。\n説明 簡易的な解釈 iproute2 における via というキーワードは、ゲートウェイ設定(静的ルーティング、Next Hop)を表す。ルーティングされる対象のネットワーク via ゲートウェイ のような書き方になる。ゲートウェイとして、クライアント自身を設定してしまうとローカルでループしてパケットが期待どうりにネットワークに排出されない通信障害になる。\n例えば、クライアントが VPN 接続先以外のネットワークから VPN 接続をすることを想定する。VPN クライアントは仮想インターフェース(vpn_vps)に、192.168.30.100/24 を持っていると仮定し、VPN サーバの仮想ハブが 192.168.30.2 をL3仮想スイッチルーティング用に持っている場合を想定する。この場合、192.168.30.0/24 のネットワークを経由して、192.168.0.0/24 にパケットを送りたい場合は、192.168.30.2 をゲートウェイを設定する。192.168.30.100/24 などクライアント自身を指定すると、通信がローカルでループし、VPN クライアントはそもそもパケットを外部のネットワークに排出せず、通信障害になる。\n一見すると 192.168.0.0/24 via [VPNクライアント自身のIP] とかくと、VPNクライアント自身のIPを経由して外部に 192.168.0.0/24 宛てのパケットをルーティングするという解釈もできそうだが、少なくとも Linux 環境の iproute2 の設定においては、その解釈は間違っていそうである。あくまで via というキーワードが示しているのは、次にパケットをどのコンピュータに送るべきか、外部のルーティングが可能なコンピュータの IP を指定するという意味合いなようである。クライアント自身を設定してしまうと、クライアント自身にルーティングしてしまうようである。\nまた、Linux 環境の iproute2 における設定では、明確に外部のゲートウェイとなる PC の IP を指定しなくても、パケットを送り出したいインターフェースだけ指定するという、曖昧な設定もできるようである。192.168.0.0/24 dev vpn_vps のようにして、192.168.0.0/24 宛てのパケットを、vpn_vps という NIC からとにかく送り出すという設定はできるようである。\n# いろんな書き方の例 # VPNクライアントとして接続されているルータPCにルーティングする仮想L3スイッチのIPを 192.168.30.2/24 として仮定している ip route add 192.168.0.0/24 via 192.168.30.2 dev vpn_vps ip route add 192.168.0.0/24 dev vpn_vps ip route add defalt via 192.168.30.2 dev vpn_vps 前提とするネットワーク構成図に関する説明 単語の説明 Home Network\n自宅のネットワークなど私的に運用される LAN Foreign Network\n大学や仕事場所、コンビニやファミレスなどにある公共の場所にある LAN 各ネットワークに関する説明 192.168.0.0/24\n家庭用ルータではなく、主に nftables によって転送が管理されていて、カーネルで転送許可をしてある Linux ルータPCで管理されている自宅のネットワーク 192.168.30.0/24\n固定 IP を持った VPS 上で動いている SoftEther VPN Server (DHCP サーバが有効) における仮想ハブのネットワーク 192.168.x.0/24\n大学や仕事場所、コンビニやファミレスなどにある公共の場所のネットワーク 192.168.0.1/24 192.168.30.2/24 192.168.x.1/24\n各ネットワークにおけるデフォルトゲートウェイ や DHCP、場合によっては DNS サーバーなど一通りのルーティングなどのネットワークに必要な機能を備えた装置の IP やルーティングを行う仮想L3スイッチの IP 192.168.30.13/24\nSoftEther VPN Server を動かしている VPS がクライアントとして仮想ハブのネットワークに参加しているときの IP 192.168.30.100/24\nForeign Network から VPN 接続して仮想ハブに参加している VPN クライアントの仮想 NIC における IP NIC 名の説明 vpn_vps\nForeign Network から VPS 上にある VPN の仮想ハブにアクセスする際に、VPN クライアントが使う仮想インターフェース名 その他説明 ルータPC\nHome Network で使われている、家庭用ルータの代わりに、スイッチとセットで nftables で転送や NAT を構成し、ip-hole や kea で DNS や DHCP サーバとしても機能するようにした Linux PC のこと。VPS 上で動いている VPN サーバのネットワークにもクライアントとして参加し、192.168.30.0/24 と 192.168.0.0/24 の間を転送する。異なるネットワーク間を転送する際、ARPプロキシ(L2ルーティング)は有効にしていない。 VPN サーバー\n今回登場する VPN サーバーは直接 Home Network からは動作せず、VPS 上に専用に用意したものである。192.168.30.0/24 のネットワークを接続した VPN クライアントに提供する。仮想 L3 スイッチの設定により、192.168.0.0/24 宛てへのパケットを、192.168.30.0/24 に接続していてネットワークの越境が可能な転送設定をしてある VPN クライアントであるルータPCに仕向けるように設定してある。 説明の図 各ルーティング状況に関する説明 パケットがクライアント内部でループするイメージ 上記の図のような状況において、トラブルシュートでは以下のような厄介な挙動が見受けられた。\nWireshark で VPN クライアントの仮想インターフェース(vpn_vps)からいかなるパケットが出ていることを確認できない。 Ping をして、192.168.30.0/24 を介して ICMP パケットを 192.168.0.0/24 のネットワークに属する機器に送ろうとしている様相は確認できるが、失敗している。 Wireshark では、any インターフェースですべてのパケットを掴むと、Ping を 192.168.0.0/24 のネットワークに属する機器に対して試みると、ICMP が Unreachable のエラーを吐いていることが確認できる。 ルータPC などの nftables などの VPN クライアント以外の設定について、転送設定や VPN 接続自体が成功しているか検証しても問題が見つからない。192.168.30.0/24 につながった VPN クライアント同士などの Ping などは成功し、疎通が取れている。 VPN クライアントとして参加しているルータ PC にも 192.168.30.0/24 のアドレスを直接叩くと、Ping が成功する。 実際のところネットワーク設定で、192.168.0.0/24 にパケットを送るゲートウェイ設定をクライアント PC 自体にしてしまっていたために、パケットがループしてそもそも VPN クライアント外部のネットワークに一切パケットが出ておらず、内部で破棄されているっぽいことが分かった。(via の解釈の問題) 正常に VPN を介して Home Network にアクセスできているときのイメージ 上記の画像の例では、単に VPN クライアントには、vpn_vps のインターフェースからパケットを外部に投げるように曖昧に設定した例である。\nSoftEther VPN サーバー において、L3 仮想スイッチ(192.168.30.2/24など)を作成し、静的ルーティングをするように設定した場合、192.168.0.0/24 via 192.168.30.2 dev vpn_vps のような明示的な書き方も可能である。\n使った画像素材とか Win 7 (Vista) のアイコン (2026年5月10日) PC のアイコン PC とインターネットのアイコン ルータのアイコン * 2 サーバーのアイコン ハブのアイコン SoftEther VPN Project - SoftEther VPN Project (SoftEther のソフトウェアのロゴ)\nhttps://www.softether.org/ (2026年5月10日) 参考にしたサイトとか Arch Linux - iproute2 7.0.0-1 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/iproute2/ (2026年5月10日) Google Gemini\nhttps://gemini.google.com/app (2026年5月10日) Network configuration - ArchWiki\nhttps://wiki.archlinux.org/title/Network_configuration#Manual (2026年5月10日) SoftEther VPN Project - SoftEther VPN Project\nhttps://www.softether.org/ (2026年5月10日) ","permalink":"https://www.nyanmo.info/posts/linux/viakeywordoniproute2asdefaultgateway/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Linux 環境において、VPN 環境についてトラブルシュートしていたところ、設定ミスが発生した。その原因として、\u003ccode\u003evia\u003c/code\u003eという単語を正しく解釈できておらず、VPN クライアントの設定ミスでパケットをクライアント内のネットワークでループさせていたということがあった。今回の記事では、そのことについて軽くまとめたい。\u003c/p\u003e\n\u003ch2 id=\"説明\"\u003e説明\u003c/h2\u003e\n\u003ch3 id=\"簡易的な解釈\"\u003e簡易的な解釈\u003c/h3\u003e\n\u003cp\u003e　iproute2 における \u003ccode\u003evia\u003c/code\u003e というキーワードは、ゲートウェイ設定(静的ルーティング、Next Hop)を表す。\u003ccode\u003eルーティングされる対象のネットワーク via ゲートウェイ\u003c/code\u003e のような書き方になる。ゲートウェイとして、クライアント自身を設定してしまうとローカルでループしてパケットが期待どうりにネットワークに排出されない通信障害になる。\u003c/p\u003e\n\u003cp\u003e　例えば、クライアントが VPN 接続先以外のネットワークから VPN 接続をすることを想定する。VPN クライアントは仮想インターフェース(vpn_vps)に、192.168.30.100/24 を持っていると仮定し、VPN サーバの仮想ハブが 192.168.30.2 をL3仮想スイッチルーティング用に持っている場合を想定する。この場合、192.168.30.0/24 のネットワークを経由して、192.168.0.0/24 にパケットを送りたい場合は、192.168.30.2 をゲートウェイを設定する。192.168.30.100/24 などクライアント自身を指定すると、通信がローカルでループし、VPN クライアントはそもそもパケットを外部のネットワークに排出せず、通信障害になる。\u003c/p\u003e\n\u003cp\u003e　一見すると \u003ccode\u003e192.168.0.0/24 via [VPNクライアント自身のIP]\u003c/code\u003e とかくと、VPNクライアント自身のIPを経由して外部に 192.168.0.0/24 宛てのパケットをルーティングするという解釈もできそうだが、少なくとも Linux 環境の iproute2 の設定においては、その解釈は間違っていそうである。あくまで \u003ccode\u003evia\u003c/code\u003e というキーワードが示しているのは、次にパケットをどのコンピュータに送るべきか、外部のルーティングが可能なコンピュータの IP を指定するという意味合いなようである。クライアント自身を設定してしまうと、クライアント自身にルーティングしてしまうようである。\u003c/p\u003e\n\u003cp\u003e　また、Linux 環境の iproute2 における設定では、明確に外部のゲートウェイとなる PC の IP を指定しなくても、パケットを送り出したいインターフェースだけ指定するという、曖昧な設定もできるようである。\u003ccode\u003e192.168.0.0/24 dev vpn_vps\u003c/code\u003e のようにして、192.168.0.0/24 宛てのパケットを、vpn_vps という NIC からとにかく送り出すという設定はできるようである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# いろんな書き方の例 \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# VPNクライアントとして接続されているルータPCにルーティングする仮想L3スイッチのIPを 192.168.30.2/24 として仮定している\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip route add 192.168.0.0/24 via 192.168.30.2 dev vpn_vps\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip route add 192.168.0.0/24 dev vpn_vps\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip route add defalt via 192.168.30.2 dev vpn_vps\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"前提とするネットワーク構成図に関する説明\"\u003e前提とするネットワーク構成図に関する説明\u003c/h3\u003e\n\u003ch4 id=\"単語の説明\"\u003e単語の説明\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eHome Network\u003cbr\u003e\n　自宅のネットワークなど私的に運用される LAN\u003c/li\u003e\n\u003cli\u003eForeign Network\u003cbr\u003e\n　大学や仕事場所、コンビニやファミレスなどにある公共の場所にある LAN\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"各ネットワークに関する説明\"\u003e各ネットワークに関する説明\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e192.168.0.0/24\u003cbr\u003e\n　家庭用ルータではなく、主に nftables によって転送が管理されていて、カーネルで転送許可をしてある Linux ルータPCで管理されている自宅のネットワーク\u003c/li\u003e\n\u003cli\u003e192.168.30.0/24\u003cbr\u003e\n　固定 IP を持った VPS 上で動いている SoftEther VPN Server (DHCP サーバが有効) における仮想ハブのネットワーク\u003c/li\u003e\n\u003cli\u003e192.168.x.0/24\u003cbr\u003e\n　大学や仕事場所、コンビニやファミレスなどにある公共の場所のネットワーク\u003c/li\u003e\n\u003cli\u003e192.168.0.1/24 192.168.30.2/24 192.168.x.1/24\u003cbr\u003e\n　各ネットワークにおけるデフォルトゲートウェイ や DHCP、場合によっては DNS サーバーなど一通りのルーティングなどのネットワークに必要な機能を備えた装置の IP やルーティングを行う仮想L3スイッチの IP\u003c/li\u003e\n\u003cli\u003e192.168.30.13/24\u003cbr\u003e\n　SoftEther VPN Server を動かしている VPS がクライアントとして仮想ハブのネットワークに参加しているときの IP\u003c/li\u003e\n\u003cli\u003e192.168.30.100/24\u003cbr\u003e\n　Foreign Network から VPN 接続して仮想ハブに参加している VPN クライアントの仮想 NIC における IP\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"nic-名の説明\"\u003eNIC 名の説明\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003evpn_vps\u003cbr\u003e\n　Foreign Network から VPS 上にある VPN の仮想ハブにアクセスする際に、VPN クライアントが使う仮想インターフェース名\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"その他説明\"\u003eその他説明\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003eルータPC\u003cbr\u003e\n　Home Network で使われている、家庭用ルータの代わりに、スイッチとセットで nftables で転送や NAT を構成し、ip-hole や kea で DNS や DHCP サーバとしても機能するようにした Linux PC のこと。VPS 上で動いている VPN サーバのネットワークにもクライアントとして参加し、192.168.30.0/24 と 192.168.0.0/24 の間を転送する。異なるネットワーク間を転送する際、ARPプロキシ(L2ルーティング)は有効にしていない。\u003c/li\u003e\n\u003cli\u003eVPN サーバー\u003cbr\u003e\n　今回登場する VPN サーバーは直接 Home Network からは動作せず、VPS 上に専用に用意したものである。192.168.30.0/24 のネットワークを接続した VPN クライアントに提供する。仮想 L3 スイッチの設定により、192.168.0.0/24 宛てへのパケットを、192.168.30.0/24 に接続していてネットワークの越境が可能な転送設定をしてある VPN クライアントであるルータPCに仕向けるように設定してある。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"説明の図\"\u003e説明の図\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/viaKeywordOnIproute2asDefaultGateway/NetworkConfigurationExplain.png#center\"\n         alt=\"ネットワーク構成図の説明\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"各ルーティング状況に関する説明\"\u003e各ルーティング状況に関する説明\u003c/h3\u003e\n\u003ch4 id=\"パケットがクライアント内部でループするイメージ\"\u003eパケットがクライアント内部でループするイメージ\u003c/h4\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/viaKeywordOnIproute2asDefaultGateway/loop.png#center\"\n         alt=\"パケットがループする例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/viaKeywordOnIproute2asDefaultGateway/loop1.png#center\"\n         alt=\"パケットがループする例1\"/\u003e \n\u003c/figure\u003e\n\n　上記の図のような状況において、トラブルシュートでは以下のような厄介な挙動が見受けられた。\u003c/p\u003e","title":"Linux 環境のおけるルーティング設定での \"via\" というキーワードの解釈 (iproute2)"},{"content":"この記事を作った動機 単に地味にしんどかった設定についてその手順をブログに記録したいだけ。今回は CapsLock キーを ESC キーに割り当てることについて、記事を記録する。環境については、以下の項目を前提としている。\nLinux GNOME Wayland やり方 パッケージのインストール yay -S keyd # sudo pacman -S keyd 設定を書く (/etc/keyd/default.conf) [ids]の項目がないと一切設定が効かない。以下では*を指定することですべての入力デバイスを Keyd の対象として扱っている。再割当てには、[main]セクションを作り、そこに再割当て対象のキー名 = 割り当てたい役割のキー名という形で記述しただけである。\n[ids] * [main] capslock = escape 明示的に Keyd 管理対象の入力デバイスを指定する 明示的に、Keyd の影響が及ぶキーボードなどのデバイスを指定するには、lsplug コマンドなど、何かしら接続された USB 機器の ID をリスト表示できるプログラムを使い、ID をたしかめ、そのうえで Keyd の設定項目の [ids] に対象のデバイスを指定する。\nyay -S lsplug lsplug # ... # USB 4-11.4.2 [046d:c52b] Logitech, Inc. Unifying Receiver # USB 4-11.4.3 [046d:c52b] Logitech, Inc. Unifying Receiver # USB 4-11.4.4 [046d:c548] Logitech, Inc. Logi Bolt Receiver # ... [ids] 046d:c548 ; 除外する場合は \u0026#34;-\u0026#34;を先頭につける -046d:c52b [main] capslock = escape 有効化 sudo systemctl enable --now keyd テストゾーン Keyboard Event Tester Key Value Key: null Code: null Bool Value alt: false ctrl: false meta: false shift: false 参考にしたサイトとか keyd(1) — Arch manual pages\nhttps://man.archlinux.org/man/extra/keyd/keyd.1.en (2026年5月9日) keyd - Gentoo Wiki\nhttps://wiki.gentoo.org/wiki/Keyd (2026年5月9日) AUR (en) - lsplug\nhttps://aur.archlinux.org/packages/lsplug (2026年5月9日) ","permalink":"https://www.nyanmo.info/posts/linux/remapcapslockintoescwithkeyd/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に地味にしんどかった設定についてその手順をブログに記録したいだけ。今回は CapsLock キーを ESC キーに割り当てることについて、記事を記録する。環境については、以下の項目を前提としている。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLinux\u003c/li\u003e\n\u003cli\u003eGNOME\u003c/li\u003e\n\u003cli\u003eWayland\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003ch3 id=\"パッケージのインストール\"\u003eパッケージのインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S keyd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -S keyd\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"設定を書く-etckeyddefaultconf\"\u003e設定を書く (\u003ccode\u003e/etc/keyd/default.conf\u003c/code\u003e)\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003e[ids]\u003c/code\u003eの項目がないと一切設定が効かない。以下では\u003ccode\u003e*\u003c/code\u003eを指定することですべての入力デバイスを Keyd の対象として扱っている。再割当てには、\u003ccode\u003e[main]\u003c/code\u003eセクションを作り、そこに\u003ccode\u003e再割当て対象のキー名 = 割り当てたい役割のキー名\u003c/code\u003eという形で記述しただけである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-ini\" data-lang=\"ini\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e[ids]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e[main]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ecapslock\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eescape\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003e明示的に Keyd 管理対象の入力デバイスを指定する\u003c/summary\u003e\n  \u003cp\u003e　明示的に、Keyd の影響が及ぶキーボードなどのデバイスを指定するには、\u003ccode\u003elsplug\u003c/code\u003e コマンドなど、何かしら接続された USB 機器の ID をリスト表示できるプログラムを使い、ID をたしかめ、そのうえで Keyd の設定項目の \u003ccode\u003e[ids]\u003c/code\u003e に対象のデバイスを指定する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S lsplug\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elsplug\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# USB 4-11.4.2 [046d:c52b] Logitech, Inc. Unifying Receiver\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# USB 4-11.4.3 [046d:c52b] Logitech, Inc. Unifying Receiver\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# USB 4-11.4.4 [046d:c548] Logitech, Inc. Logi Bolt Receiver\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-ini\" data-lang=\"ini\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e[ids]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e046d:c548\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e; 除外する場合は \u0026#34;-\u0026#34;を先頭につける\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e-046d:c52b\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e[main]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ecapslock\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eescape\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"CapsLock を ESC キーとして割り当てる (Keyd,Linux)"},{"content":"この記事を作った動機 単に Git で間違ったリモートを設定してしまったときの修正方法の記録をする。\nやり方 # 必要に応じて変更したリモートリポジトリにあるブランチ名を確認すること # リモート先に origin と指定した場合自動選択される。 git branch -a # * main # remotes/origin/main # Remote URL を間違える例 git remote add origin https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git git remote -v # origin https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git (fetch) # origin https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git (push) # 正しい Remote URL に設定する例 git remote set-url origin gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git git remote -v # origin gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git (fetch) # rigin gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git (push) 参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年4月19日) Git - git-remote Documentation\nhttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-add (2026年4月19日) Git - git-remote Documentation\nhttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-url (2026年4月19日) Git - user-manual Documentation\nhttps://git-scm.com/docs/user-manual#managing-branches (2026年4月19日) Git - git-remote Documentation\nhttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-head (2026年4月19日) Git - git-branch Documentation\nhttps://git-scm.com/docs/git-branch#Documentation/git-branch.txt--a (2026年4月19日) ","permalink":"https://www.nyanmo.info/posts/other/gitchangeremoteurl/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に Git で間違ったリモートを設定してしまったときの修正方法の記録をする。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 必要に応じて変更したリモートリポジトリにあるブランチ名を確認すること\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# リモート先に origin と指定した場合自動選択される。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit branch -a\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# * main\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   remotes/origin/main\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Remote URL を間違える例\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote add origin https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote -v\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# origin  https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git (fetch)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# origin  https://url.to.repo/userName/Receipt-OCR-to-CSV-with-PDF.git (push)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 正しい Remote URL に設定する例\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote set-url origin gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote -v\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# origin  gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git (fetch)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# rigin  gitea@192.168.x.x:userName/Receipt-OCR-to-CSV-with-PDF.git (push)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eGoogle Gemini\u003cbr\u003e\n\u003ca href=\"https://gemini.google.com/app\"\u003ehttps://gemini.google.com/app\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003cli\u003eGit - git-remote Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-add\"\u003ehttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-add\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003cli\u003eGit - git-remote Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-url\"\u003ehttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-url\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003cli\u003eGit - user-manual Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/user-manual#managing-branches\"\u003ehttps://git-scm.com/docs/user-manual#managing-branches\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003cli\u003eGit - git-remote Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-head\"\u003ehttps://git-scm.com/docs/git-remote#Documentation/git-remote.txt-set-head\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003cli\u003eGit - git-branch Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/git-branch#Documentation/git-branch.txt--a\"\u003ehttps://git-scm.com/docs/git-branch#Documentation/git-branch.txt--a\u003c/a\u003e (2026年4月19日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Git で間違った Remote URL を設定してしまったときに修正する方法のメモ"},{"content":"記録 簡潔さのために、最初に結論を持ってくることにする。\n効果があったこと 効果があったことは、gnome-remote-desktop を 50.0-1 から 49.0-1 にダウングレードすることである。安全のために自動でアップグレードされないよう/etc/pacman.confにおいて、ignorePkg の項目にgnome-remote-desktopやGDMを設定しておくことが推奨される。\n試して失敗したこと、微妙だったこと Nvidia のドライバの以下のバージョンを試す 580 580 のちょっと古いバージョン 575 (カーネルバージョンを下げる必要がある。) 550 異なるデスクトップ環境(KDE)を使う Google Gemini Fast 3 に症状を具体的に投げて、提案される環境変数を試す。 Google 検索で gnome-remote-desktop や PipeWire などが吐き出すエラーについて、コピペして調べてフォームラムなどにあたってみる。 egl-gbm、egl-wayland、egl-wayland2 の 3 つのうち、egl-gbmとegl-wayland を /usr/share/egl/egl_external_platform.d/ gnome-remote-desktop 別の手段として VNC サーバである wayvnc を試してみたが、GNOME ではそもそも動作不能であった。 CUDA のバージョンを Arch Linux - cuda 13.2.1-1 (x86_64) から AUR (en) - cuda12.0 に下げた。 この記事を作った動機や経緯 最近 GNOME を動かしている GTX1080Ti を搭載するサーバ環境において、 Virt-Manager 経由で仮想マシンを立ち上げようとしたところ、部分的に更新をした影響でシステムが中途半端な状態になり、起動できないことがあった。そこでいつもどうり、すべてのパッケージを yay コマンドより更新して再起動をかけたところ異変が起こった。\n具体的には、GNOME デスクトップ環境で RDP 接続時において画面が真っ白になる症状が起こった。GPU が接続されている物理ディスプレイには正しく画面が表示されているが、RDPからは内容が全く見えず、Remmina においては真っ白でマウスやキーボード入力は動作する状態で、Windows 11 25H2 の Win32 の方の伝統的な RDP クライアントでは真っ黒になってしばらくして切断されてしまうという挙動になった。結論としては、gnome-remote-desktopパッケージが新しすぎる場合、PipeWire を正しく初期化できず、pw-topなどで確認すると、音声だけ転送され画面は一切転送されていないことが分かった。\n当初はしばらくの間、比較的 Wayland 環境において不安定な GTX1080Ti という古めの GPU でも正常に動作し RDP も動いていたことから、特に GNOME 側には問題ないだろうと思っていた。そこで障害発生時はどうせ Nvidia のプロプライエタリなドライバがバージョンアップでなんか悪さしているんだろうと思い込んでしまい、そのバージョンを疑って下げてみたりしたが症状は変わらず一貫していた。そもそも Nvidia のドライバのバージョンを下げることが難しく、最新の linux-6.19.11.arch1-1 では 580 番代のドライバ以外カーネルモジュールが一切ビルドできなかったため、Linux 6.18.22-1-lts にダウングレードしたりした。\nその次に、GNOME の描画を担当する GDM の動作がだめなのかと思いこんでしまい、そのバージョンをメジャーバージョンの 50 から、46 や 49 などにダウングレードしてみることを試みたが、それでも症状は変わらず一貫していた。特に 46 あたりを試したときは GDM 起動さえしなかった。\n更にその次に、とにかく RDP が動かないのは耐え難いということで、もう何度も試しては再起動して試行錯誤し、6 時間以上トラブルシュートに費やしてしまったことから、KDE のデスクトップ環境を試したところ、Kwin 配下において Wayland で起動した状態で RDP が機能することが分かった。ただ問題点としては、明らかに GNOME 内臓の RDP より性能が劣るということがあり、遅延が大きくカクついていたた。結局同じユーザアカウントで GNOME と KDE など異なるデスクトップ環境を混在させると、設定などがぐちゃぐちゃになってアイコンなどがキモくなったりするため、めんどくさく実用的な案ではないとして、GNOMEに戻すことにした。\nそこで、Google Gemini Fast 3 が提案する出どころ不明の得体のしれない環境変数など色々試したりもしたが、全く改善が見られず、症状はこの時点でも画面真っ白で一貫していた。\nそして最終的に、gnome-remote-desktop というパッケージがあることに、しばらくトラブルシュートしてあれこれパッケージを入れたり消したりしているうちに気づき、そのメジャーバージョンも 50 となっていたことから、GDM などは メジャーバージョン 50 のままで、gnome-remote-desktop だけダウングレードしてみるのもありではないかと考え、メジャーバージョン 49 を試した。\nそのところようやく GDM 50.0-2 と gnome-remote-desktop 49.0-1 で動作を確認することができた。まだ、最新の Linux カーネル、最新の Nvidia ドライバでもう一度動作を確認することはしておらず、Linux 6.18.22-1-lts と nvidia-575xx においての動作の確認となる。\n今回の記事では軽くまとめを行うことにする。\n最終的な環境情報 System Details Report Report details Date generated: 2026-04-15 04:13:57 Hardware Information: Hardware Model: HP ProLiant DL60 Gen9 Memory: 88.0 GiB Processor: Intel® Xeon® E5-2620 v4 × 32 Graphics: NVIDIA GeForce GTX 1080 Ti Disk Capacity: 30.0 TB Software Information: Firmware Version: U15 OS Name: Arch Linux OS Build: (null) OS Type: 64-bit GNOME Version: 50 Windowing System: Wayland Kernel Version: Linux 6.18.22-1-lts おまけ 古いパッケージにダウングレードしたい Arch Linux Archive から、すでにビルドされた古いバージョンのバイナリを取得する。Core や Extra に分類されるパッケージであればここに存在するものだと思われる。 AUR において View Changes の項目から、使いたい古いバージョンの PKGBUILD を取得する。 古いバージョンにおいて、nvidia の dkms のビルドが通らない 必要なこと linux カーネルのバージョンを合わせる必要がある。今回は単純に通常の linux カーネルではなく AUR にあるArch Linux - linux-lts 6.18.22-1 (x86_64)を利用することで事実上のダウングレードを行った。dkms 構築のために、Arch Linux - linux-lts-headers 6.18.22-1 (x86_64) も必要である。\ndkms コマンドについて 何がインストールされているか確認する sudo dkms status # nvidia/575.64.05, 6.18.22-1-lts, x86_64: installed # nvidia/575.64.05, 6.9.7, x86_64: installed # vboxhost/7.2.6_OSE, 6.18.22-1-lts, x86_64: installed # vboxhost/7.2.6_OSE, 6.9.7, x86_64: installed 特定の dkms モジュールをビルドに失敗した分再インストールする yay -Qs nvidia # pacman -Qs nvidia # local/nvidia-575xx-dkms 575.64.05-2 # NVIDIA kernel modules - module sources # local/nvidia-575xx-utils 575.64.05-2 # NVIDIA drivers utilities # nvidia/[バージョン] という形で -2 など AUR における管理番号は取り除いて指定する。 sudo dkms install --no-depmod nvidia/575.64.05 dkms コマンド失敗時に起こること mkinitcpio コマンドにおいて起動時に読み込まれる初期 RAM イメージに dkms モジュール生成に失敗した分、/etc/mkinitcpio.confにおいて設定していたとしてもモジュールが組み込まれない、反映されない状態になる。\ngnome-remote-desktop のダウングレード Arch Linux Archiveの以下のリンクより利用可能なバージョンで、メジャーバージョンが 49 のものを選ぶ。\nIndex of /packages/g/gnome-remote-desktop/\nhttps://archive.archlinux.org/packages/g/gnome-remote-desktop/ (2026年4月15日) # 一時作業ディレクトリの作成 cd /tmp mkdir rdp cd rdp # ダウングレードする対象のパッケージを取得 wget https://archive.archlinux.org/packages/g/gnome-remote-desktop/gnome-remote-desktop-49.0-1-x86_64.pkg.tar.zst # インストール yay -U gnome-remote-desktop-49.0-1-x86_64.pkg.tar.zst # sudo pacman -U gnome-remote-desktop-49.0-1-x86_64.pkg.tar.zst PipeWire の動作確認 pw-top gnome-remote-desktop の動作確認 # システム全体 systemctl status gnome-remote-desktop # ユーザ単位 systemctl status --user gnome-remote-desktop yay(pacman)コマンドにて更新時に特定のパッケージを無視する ファイルの場所 /etc/pacman.conf 設定例 # ... # IgnorePkg = [無視したいパッケージ1] [無視したいパッケージ2] [無視したいパッケージ3] ... IgnorePkg = apache cuda12.0 nvidia gdm linux-lts-headers linux-lts gnome-remote-desktop # ... 参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年4月15日)\nArch Linux - gnome-remote-desktop 50.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/gnome-remote-desktop/ (2026年4月15日)\nAUR (en) - gcc12\nhttps://aur.archlinux.org/packages/gcc12 (2026年4月15日)\nIndex of / (Arch Linux Archive)\nhttps://archive.archlinux.org/ (2026年4月15日)\nAUR (en) - gcc14\nhttps://aur.archlinux.org/packages/gcc14 (2026年4月15日)\nIndex of /packages/g/gcc/\nhttps://archive.archlinux.org/packages/g/gcc/ (2026年4月15日)\nIndex of /packages/g/gnome-remote-desktop/\nhttps://archive.archlinux.org/packages/g/gnome-remote-desktop/ (2026年4月15日)\nArch Linux - linux-lts 6.18.22-1 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/linux-lts/ (2026年4月15日)\nArch Linux - linux-lts-headers 6.18.22-1 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/linux-lts-headers/ (2026年4月15日)\nArch Linux - gnome-remote-desktop 50.0-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/gnome-remote-desktop/ (2026年4月15日)\nKDE Plasma 6.8 Will Go Wayland-Exclusive In Dropping X11 Session Support. I hope that it is enough time to remove the remaining problems such as the problems with NVIDIA : r/linux_gaming\nhttps://www.reddit.com/r/linux_gaming/comments/1pzmhjh/kde_plasma_68_will_go_waylandexclusive_in/ (2026年4月15日)\nSDDM - ArchWiki\nhttps://wiki.archlinux.org/title/SDDM#Enable_HiDPI (2026年4月15日)\nHow do I change the scaling of the SDDM login screen to 125%? : r/kde\nhttps://www.reddit.com/r/kde/comments/1oyfs61/how_do_i_change_the_scaling_of_the_sddm_login/ (2026年4月15日)\nKDE - ArchWiki\nhttps://wiki.archlinux.org/title/KDE (2026年4月15日)\nAUR (en) - nvidia-580xx-utils\nhttps://aur.archlinux.org/packages/nvidia-580xx-dkms (2026年4月15日)\nArch Linux - linux-zen-headers 6.19.11.zen1-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/linux-zen-headers/ (2026年4月15日)\n[SOLVED] Nvidia DKMS problems with new 6.9.3-zen1-1-zen kernel / Kernel \u0026amp; Hardware / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=296454 (2026年4月15日)\nArch Linux - linux-headers 6.19.11.arch1-1 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/linux-headers/ (2026年4月15日)\nGitHub - any1/wayvnc: A VNC server for wlroots based Wayland compositors · GitHub\nhttps://github.com/any1/wayvnc (2026年4月15日)\nArch Linux / Packaging / Packages / gnome-remote-desktop · GitLab\nhttps://gitlab.archlinux.org/archlinux/packaging/packages/gnome-remote-desktop (2026年4月15日)\nCommits · main · Arch Linux / Packaging / Packages / gnome-remote-desktop · GitLab\nhttps://gitlab.archlinux.org/archlinux/packaging/packages/gnome-remote-desktop/-/commits/main (2026年4月15日)\nKRDP Help, blank screen on connect - Help - KDE Discuss\nhttps://discuss.kde.org/t/krdp-help-blank-screen-on-connect/41952/4 (2026年4月15日)\nWhite Screen when logging into pc via Remmina (remote desktop) : r/cachyos\nhttps://www.reddit.com/r/cachyos/comments/1rk3q8n/white_screen_when_logging_into_pc_via_remmina/ (2026年4月15日)\nWhite screen when resizing RDP window session · Issue #3316 · neutrinolabs/xrdp\nhttps://github.com/neutrinolabs/xrdp/issues/3316 (2026年4月15日)\nPipeWire - ArchWiki\nhttps://wiki.archlinux.org/title/PipeWire#Troubleshooting (2026年4月15日)\nAUR (en) - cuda12.0\nhttps://aur.archlinux.org/packages/cuda12.0 (2026年4月15日)\nArch Linux - cuda 13.2.1-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/cuda/ (2026年4月15日)\nCommits · main · Arch Linux / Packaging / Packages / gdm · GitLab\nhttps://gitlab.archlinux.org/archlinux/packaging/packages/gdm/-/commits/main (2026年4月15日)\nArch Linux - gdm 50.0-2 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/gdm/ (2026年4月15日)\nenvironment.d\nhttps://www.freedesktop.org/software/systemd/man/latest/environment.d.html?__goaway_challenge=meta-refresh\u0026amp;__goaway_id=ab859c14d7c5a50514723c9c57b5995a\u0026amp;__goaway_referer=https%3A%2F%2Fwww.google.com%2F (2026年4月15日)\npipewire no more input formats · Issue #1226 · phw/peek\nhttps://github.com/phw/peek/issues/1226 (2026年4月15日)\n570 release feedback \u0026amp; discussion - Graphics / Linux / Linux - NVIDIA Developer Forums\nhttps://forums.developer.nvidia.com/t/570-release-feedback-discussion/321956/499?page=26 (2026年4月15日)\nGSK_RENDERER=ngl and gl, nvidia, xorg - random GSK errors after 6-7 apps open - Fedora Discussion\nhttps://discussion.fedoraproject.org/t/gsk-renderer-ngl-and-gl-nvidia-xorg-random-gsk-errors-after-6-7-apps-open/135123/2 (2026年4月15日)\nIndex of /XFree86/Linux-x86_64/580.142\nhttps://download.nvidia.com/XFree86/Linux-x86_64/580.142/ (2026年4月15日)\nnvidia-580xx-utils: Add patch to fix KDE Plasma crashes - aur.git - AUR Package Repositories\nhttps://aur.archlinux.org/cgit/aur.git/commit/?h=nvidia-580xx-utils (2026年4月15日)\nnvidia-580xx-utils: Bump pkgver 580.142 - aur.git - AUR Package Repositories\nhttps://aur.archlinux.org/cgit/aur.git/commit/?h=nvidia-580xx-utils\u0026amp;id=f2c144f50fbad83d8e5ab55eeb8d13aa8ca04956 (2026年4月15日)\nxorg - Force gnome remote desktop daemon to use default GPU, not Nvidia dGPU - Ask Ubuntu\nhttps://askubuntu.com/questions/1511699/force-gnome-remote-desktop-daemon-to-use-default-gpu-not-nvidia-dgpu (2026年4月15日)\nMutter/Wayland prefers dGPU instead of iGPU - how can I change this? - Desktop - GNOME Discourse\nhttps://discourse.gnome.org/t/mutter-wayland-prefers-dgpu-instead-of-igpu-how-can-i-change-this/25029 (2026年4月15日)\nBlank screen only on client \u0026ndash; Gnome \u0026gt;= 45 (#3431) · Issue · GNOME/mutter\nhttps://gitlab.gnome.org/GNOME/mutter/-/issues/3431 (2026年4月15日)\n","permalink":"https://www.nyanmo.info/posts/linux/gtx1080tiwithgnomeremotedesktopissue/","summary":"\u003ch2 id=\"記録\"\u003e記録\u003c/h2\u003e\n\u003cp\u003e　簡潔さのために、最初に結論を持ってくることにする。\u003c/p\u003e\n\u003ch3 id=\"効果があったこと\"\u003e効果があったこと\u003c/h3\u003e\n\u003cp\u003e　効果があったことは、\u003ccode\u003egnome-remote-desktop\u003c/code\u003e を 50.0-1 から 49.0-1 にダウングレードすることである。安全のために自動でアップグレードされないよう\u003ccode\u003e/etc/pacman.conf\u003c/code\u003eにおいて、ignorePkg の項目に\u003ccode\u003egnome-remote-desktop\u003c/code\u003eや\u003ccode\u003eGDM\u003c/code\u003eを設定しておくことが推奨される。\u003c/p\u003e\n\u003ch3 id=\"試して失敗したこと微妙だったこと\"\u003e試して失敗したこと、微妙だったこと\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNvidia のドライバの以下のバージョンを試す\n\u003cul\u003e\n\u003cli\u003e580\u003c/li\u003e\n\u003cli\u003e580 のちょっと古いバージョン\u003c/li\u003e\n\u003cli\u003e575 (カーネルバージョンを下げる必要がある。)\u003c/li\u003e\n\u003cli\u003e550\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e異なるデスクトップ環境(KDE)を使う\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://gemini.google.com/app\"\u003eGoogle Gemini Fast 3\u003c/a\u003e に症状を具体的に投げて、提案される環境変数を試す。\u003c/li\u003e\n\u003cli\u003eGoogle 検索で \u003ccode\u003egnome-remote-desktop\u003c/code\u003e や \u003ccode\u003ePipeWire\u003c/code\u003e などが吐き出すエラーについて、コピペして調べてフォームラムなどにあたってみる。\u003c/li\u003e\n\u003cli\u003eegl-gbm、egl-wayland、egl-wayland2 の 3 つのうち、egl-gbmとegl-wayland を \u003ccode\u003e/usr/share/egl/egl_external_platform.d/\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003egnome-remote-desktop\u003c/li\u003e\n\u003cli\u003e別の手段として VNC サーバである \u003ca href=\"https://github.com/any1/wayvnc\"\u003ewayvnc\u003c/a\u003e を試してみたが、GNOME ではそもそも動作不能であった。\u003c/li\u003e\n\u003cli\u003eCUDA のバージョンを \u003ca href=\"https://archlinux.org/packages/extra/x86_64/cuda/\"\u003eArch Linux - cuda 13.2.1-1 (x86_64)\u003c/a\u003e から \u003ca href=\"https://aur.archlinux.org/packages/cuda12.0\"\u003eAUR (en) - cuda12.0\u003c/a\u003e に下げた。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"この記事を作った動機や経緯\"\u003eこの記事を作った動機や経緯\u003c/h2\u003e\n\u003cp\u003e　最近 GNOME を動かしている GTX1080Ti を搭載するサーバ環境において、 Virt-Manager 経由で仮想マシンを立ち上げようとしたところ、部分的に更新をした影響でシステムが中途半端な状態になり、起動できないことがあった。そこでいつもどうり、すべてのパッケージを \u003ccode\u003eyay\u003c/code\u003e コマンドより更新して再起動をかけたところ異変が起こった。\u003c/p\u003e\n\u003cp\u003e　具体的には、GNOME デスクトップ環境で RDP 接続時において画面が真っ白になる症状が起こった。GPU が接続されている物理ディスプレイには正しく画面が表示されているが、RDPからは内容が全く見えず、Remmina においては真っ白でマウスやキーボード入力は動作する状態で、Windows 11 25H2 の Win32 の方の伝統的な RDP クライアントでは真っ黒になってしばらくして切断されてしまうという挙動になった。結論としては、\u003ccode\u003egnome-remote-desktop\u003c/code\u003eパッケージが新しすぎる場合、PipeWire を正しく初期化できず、\u003ccode\u003epw-top\u003c/code\u003eなどで確認すると、音声だけ転送され画面は一切転送されていないことが分かった。\u003c/p\u003e","title":"GTX1080Ti と GNONE と RDP で真っ白画面の不具合が起こる"},{"content":"この記事を作った動機 最近常駐させているサーバ用に、Smart UPS 750 を導入した。それで、Google Gemini Fast 3にそれについて投げつけてみたところ、UPS を USB 接続して使える専用の管理ツールがあることが分かったため、作業したことを記録するだけ。\n前提として、Smart UPS 750 をすでに USB​ 接続していることを置く。\napcupsdを導入して動作確認する インストール yay -Sy apcupsd # sudo pacman -Sy apcupsd systemd スクリプトの有効化 sudo systemctl enable --now apcupsd systemctl status apcupsd # ● apcupsd.service - APC UPS Power Control Daemon for Linux # Loaded: loaded (/usr/lib/systemd/system/apcupsd.service; enabled; preset: disabled) # Active: active (running) since Mon 2026-04-13 21:48:21 JST; 3s ago # Invocation: 2bc2be59d2fa4c69a0d736f2cb8038dd # Process: 177505 ExecStartPre=/bin/rm -f /etc/apcupsd/powerfail (code=exited, status=0/SUCCESS) # Main PID: 177507 (apcupsd) # Tasks: 3 (limit: 629145) # Memory: 800K (peak: 1.8M) # CPU: 34ms # CGroup: /system.slice/apcupsd.service # └─177507 /usr/bin/apcupsd -b -f /etc/apcupsd/apcupsd.conf # # 4月 13 21:48:21 dataSrv systemd[1]: Starting APC UPS Power Control Daemon for Linux... # 4月 13 21:48:21 dataSrv systemd[1]: Started APC UPS Power Control Daemon for Linux. # 4月 13 21:48:21 dataSrv apcupsd[177507]: apcupsd 3.14.14 (31 May 2016) unknown startup succeeded # 4月 13 21:48:21 dataSrv apcupsd[177507]: NIS server startup succeeded 設定ファイルの場所 cd /etc/apcupsd/ ls # -rwxr--r--⠀root⠀4039 ⠀Feb 16 04:26:29⠀⠀apccontrol* # -rw-r--r--⠀root⠀13263⠀Feb 16 04:26:29⠀⠀apcupsd.conf # -rw-r--r--⠀root⠀607 ⠀Feb 16 04:26:29⠀⠀apcupsd.css # -rwxr--r--⠀root⠀427 ⠀Feb 16 04:26:29⠀⠀changeme* # -rwxr--r--⠀root⠀454 ⠀Feb 16 04:26:29⠀⠀commfailure* # -rwxr--r--⠀root⠀455 ⠀Feb 16 04:26:29⠀⠀commok* # -rw-r--r--⠀root⠀662 ⠀Feb 16 04:26:29⠀⠀hosts.conf # -rw-r--r--⠀root⠀2344 ⠀Feb 16 04:26:29⠀⠀multimon.conf # -rwxr--r--⠀root⠀426 ⠀Feb 16 04:26:29⠀⠀offbattery* # -rwxr--r--⠀root⠀391 ⠀Feb 16 04:26:29⠀⠀onbattery* シャットダウン設定の変更 (/etc/apcupsd/apcupsd.conf) 今回はバッテリー残量に関する項目について、デフォルトより余裕を持つように設定してみた。\n... # If during a power failure, the remaining battery percentage # (as reported by the UPS) is below or equal to BATTERYLEVEL, # apcupsd will initiate a system shutdown. BATTERYLEVEL 60 # ここはもともと5％に設定されていたところ、60%でシャットダウンに変更した。 # If during a power failure, the remaining runtime in minutes # (as calculated internally by the UPS) is below or equal to MINUTES, # apcupsd, will initiate a system shutdown. MINUTES 10 # ここはもともと3分に設定されていたところを、10分でシャットダウンに変更した。 ... バッテリーの様子を確認する apcaccess # APC : 001,027,0657 # DATE : 2026-04-13 22:10:41 +0900 # HOSTNAME : hostName # VERSION : 3.14.14 (31 May 2016) unknown # UPSNAME : userName # CABLE : USB Cable # DRIVER : USB UPS Driver # UPSMODE : Stand Alone # STARTTIME: 2026-04-13 22:10:40 +0900 # MODEL : Smart-UPS 750 # STATUS : ONLINE # BCHARGE : 100.0 Percent # TIMELEFT : 62.0 Minutes # MBATTCHG : 60 Percent # MINTIMEL : 10 Minutes # MAXTIME : 0 Seconds # ALARMDEL : No alarm # BATTV : 26.7 Volts # NUMXFERS : 0 # TONBATT : 0 Seconds # CUMONBATT: 0 Seconds # XOFFBATT : N/A # STATFLAG : 0x05000008 # MANDATE : 2013-08-08 # SERIALNO : XXXXXXXXXXXXX # NOMBATTV : 24.0 Volts # FIRMWARE : UPS 08.8 / ID=18 # END APC : 2026-04-13 22:10:42 +0900 GNOME の様子 参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年4月13日) Arch Linux - apcupsd 3.14.14-9 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/apcupsd/ (2026年4月13日) APC UPS - ArchWiki\nhttps://wiki.archlinux.org/title/APC_UPS (2026年4月13日) ","permalink":"https://www.nyanmo.info/posts/hardware/smart-ups-750withusb/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近常駐させているサーバ用に、Smart UPS 750 を導入した。それで、\u003ca href=\"https://gemini.google.com/\"\u003eGoogle Gemini Fast 3\u003c/a\u003eにそれについて投げつけてみたところ、UPS を USB 接続して使える専用の管理ツールがあることが分かったため、作業したことを記録するだけ。\u003c/p\u003e\n\u003cp\u003e　前提として、Smart UPS 750 をすでに USB​ 接続していることを置く。\u003c/p\u003e\n\u003ch2 id=\"apcupsdを導入して動作確認する\"\u003e\u003ccode\u003eapcupsd\u003c/code\u003eを導入して動作確認する\u003c/h2\u003e\n\u003ch3 id=\"インストール\"\u003eインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy apcupsd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -Sy apcupsd\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"systemd-スクリプトの有効化\"\u003esystemd スクリプトの有効化\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now apcupsd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl status apcupsd\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ● apcupsd.service - APC UPS Power Control Daemon for Linux\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#      Loaded: loaded (/usr/lib/systemd/system/apcupsd.service; enabled; preset: disabled)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#      Active: active (running) since Mon 2026-04-13 21:48:21 JST; 3s ago\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  Invocation: 2bc2be59d2fa4c69a0d736f2cb8038dd\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Process: 177505 ExecStartPre=/bin/rm -f /etc/apcupsd/powerfail (code=exited, status=0/SUCCESS)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#    Main PID: 177507 (apcupsd)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#       Tasks: 3 (limit: 629145)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#      Memory: 800K (peak: 1.8M)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         CPU: 34ms\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#      CGroup: /system.slice/apcupsd.service\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#              └─177507 /usr/bin/apcupsd -b -f /etc/apcupsd/apcupsd.conf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  4月 13 21:48:21 dataSrv systemd[1]: Starting APC UPS Power Control Daemon for Linux...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  4月 13 21:48:21 dataSrv systemd[1]: Started APC UPS Power Control Daemon for Linux.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  4月 13 21:48:21 dataSrv apcupsd[177507]: apcupsd 3.14.14 (31 May 2016) unknown startup succeeded\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  4月 13 21:48:21 dataSrv apcupsd[177507]: NIS server startup succeeded\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"設定ファイルの場所\"\u003e設定ファイルの場所\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /etc/apcupsd/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003els\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀4039 ⠀Feb 16 04:26:29⠀⠀apccontrol*  \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rw-r--r--⠀root⠀13263⠀Feb 16 04:26:29⠀⠀apcupsd.conf \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rw-r--r--⠀root⠀607  ⠀Feb 16 04:26:29⠀⠀apcupsd.css  \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀427  ⠀Feb 16 04:26:29⠀⠀changeme*    \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀454  ⠀Feb 16 04:26:29⠀⠀commfailure* \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀455  ⠀Feb 16 04:26:29⠀⠀commok*      \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rw-r--r--⠀root⠀662  ⠀Feb 16 04:26:29⠀⠀hosts.conf   \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rw-r--r--⠀root⠀2344 ⠀Feb 16 04:26:29⠀⠀multimon.conf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀426  ⠀Feb 16 04:26:29⠀⠀offbattery*  \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -rwxr--r--⠀root⠀391  ⠀Feb 16 04:26:29⠀⠀onbattery*   \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"シャットダウン設定の変更-etcapcupsdapcupsdconf\"\u003eシャットダウン設定の変更 (\u003ccode\u003e/etc/apcupsd/apcupsd.conf\u003c/code\u003e)\u003c/h3\u003e\n\u003cp\u003e　今回はバッテリー残量に関する項目について、デフォルトより余裕を持つように設定してみた。\u003c/p\u003e","title":"Smart UPS 750 を USB で繋いで Linux 環境で使う"},{"content":"この記事を作った動機 GNOME デスクトップ環境などにおいて特定のスクリプトを実行するなど、定型処理を気軽に行うために、ショートカット(デスクトップエントリ)を作成したいということがあった。しかし、.desktopという拡張子を持つファイルを所定の場所に作れば、ショートカットができることがわかっていたものの、その内容がめんどくさくて、放置していたことがあった。\nそこで今回はExample Desktop Entry File | Desktop Entry Specificationの.desktopエントリの例を参考に、最低限私が使いたいように加工した物をテンプレートとして記録しておくことにした。\n事前情報 [userName]と書かれている部分は、適宜存在するユーザのホームディレクトリ名などに書き換える。 設定内容 .desktopの内容 スクリプトを実行する場合には、Terminal=trueを指定すること、実行権限を付与すること(\u0026ldquo;chmod +x [対象のスクリプトやバイナリ]\u0026quot;)やインタプリンタなどを指定するシバンが先頭に必要である。(例:\u0026rdquo;#!/bin/bash\u0026quot;,\u0026quot;#!/bin/python\u0026quot;)\n[Desktop Entry] Version=1.0 Type=Application Name=A sample sortcut Comment=This is a sample desktop entry text. Terminal=true Exec=/path/to/script.sh Icon=[icons フォルダ直下に配置した画像名か、画像までのファイル名を含めた絶対パス 拡張子も書く] .desktopのファイルの配置場所 特定のユーザだけ /home/[userName]/.local/share/applications # /home/$(whoami)/.local/share/applications 全体に反映 /usr/share/applications アイコン画像の配置場所と利用方法 icons フォルダに直接画像を配置する場合は、デスクトップエントリの記述においてIcon=[拡張子を含めたファイル名]で通り、すべてのパスを書く必要はない。階層構造を作るには、Icon Theme Specification に従って厳密にインデックスなどをテキストで指定する必要があり手間がかかるので今回は省略する。それ以外の場所に配置する場合は、デスクトップエントリの記述においてIcon=[画像のファイル名を含めた絶対パス]とする必要がある。 特定のユーザだけ /home/[userName]/.local/share/icons # /home/$(whoami)/.local/share/icons 全体に反映 /usr/share/icons 例 例として、ゆっくり霊夢をアイコンとしたecho \u0026quot;ゆっくりしていってね!\u0026quot;を実行するスクリプトへのショートカットの作成について、以下に示す。\n.desktopファイル 配置場所 /home/[userName]/.local/share/applications/yukkuri.desktop # /home/$(whoami)/.local/share/applications/yukkuri.desktop 内容 [Desktop Entry] Version=1.0 Type=Application Name=Yukkuri say something meaningless Comment=Yukkuri will say something meaningless. Terminal=true Exec=/home/[userName]/script/yukkuri/say.sh Icon=/home/[userName]/.local/share/icons/yukkuri/reimu/normal.png スクリプト 配置場所 /home/[userName]/script/yukkuri/say.sh # /home/$(whoami)/script/yukkuri/say.sh 内容 #!/bin/bash echo \u0026#34;ゆっくりしていってね!\u0026#34; 画像 配置場所 /home/[userName]/.local/share/icons/yukkuri/reimu/normal.png # /home/$(whoami)/.local/share/icons/yukkuri/reimu/normal.png ゆっくり霊夢の画像 (normal.png) 動作例 期待したとおりに動作している例 アイコン反映に失敗している例 使った画像とか nicotalk＆キャラ素材配布所 (ゆっくり霊夢の画像)\nhttp://www.nicotalk.com/charasozai_kt.html (2026年4月2日) 参考にしたサイトとか Example Desktop Entry File | Desktop Entry Specification\nhttps://specifications.freedesktop.org/desktop-entry/latest/example.html (2026年4月2日) Recognized desktop entry keys | Desktop Entry Specification\nhttps://specifications.freedesktop.org/desktop-entry/latest/recognized-keys.html (2026年4月2日) Desktop Entry Specification\nhttps://specifications.freedesktop.org/desktop-entry/latest/index.html (2026年4月2日) Icon Theme Specification\nhttps://specifications.freedesktop.org/icon-theme/latest/#icon_lookup (2026年4月2日) Where to get list of icons to use? - Desktop - GNOME Discourse\nhttps://discourse.gnome.org/t/where-to-get-list-of-icons-to-use/21244 (2026年4月2日) Where are the icons for an application in the Gnome App Launcher stored? : r/Fedora\nhttps://www.reddit.com/r/Fedora/comments/u5piht/where_are_the_icons_for_an_application_in_the/ (2026年4月2日) ","permalink":"https://www.nyanmo.info/posts/linux/createdesktopshortcutfile/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　GNOME デスクトップ環境などにおいて特定のスクリプトを実行するなど、定型処理を気軽に行うために、ショートカット(デスクトップエントリ)を作成したいということがあった。しかし、\u003ccode\u003e.desktop\u003c/code\u003eという拡張子を持つファイルを所定の場所に作れば、ショートカットができることがわかっていたものの、その内容がめんどくさくて、放置していたことがあった。\u003c/p\u003e\n\u003cp\u003e　そこで今回は\u003ca href=\"https://specifications.freedesktop.org/desktop-entry/latest/example.html\"\u003eExample Desktop Entry File | Desktop Entry Specification\u003c/a\u003eの\u003ccode\u003e.desktop\u003c/code\u003eエントリの例を参考に、最低限私が使いたいように加工した物をテンプレートとして記録しておくことにした。\u003c/p\u003e\n\u003ch2 id=\"事前情報\"\u003e事前情報\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e[userName]\u003c/code\u003eと書かれている部分は、適宜存在するユーザのホームディレクトリ名などに書き換える。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"設定内容\"\u003e設定内容\u003c/h2\u003e\n\u003ch3 id=\"desktopの内容\"\u003e\u003ccode\u003e.desktop\u003c/code\u003eの内容\u003c/h3\u003e\n\u003cp\u003e　スクリプトを実行する場合には、\u003ccode\u003eTerminal=true\u003c/code\u003eを指定すること、実行権限を付与すること(\u0026ldquo;chmod +x [対象のスクリプトやバイナリ]\u0026quot;)やインタプリンタなどを指定するシバンが先頭に必要である。(例:\u0026rdquo;#!/bin/bash\u0026quot;,\u0026quot;#!/bin/python\u0026quot;)\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Desktop Entry]\nVersion=1.0\nType=Application\nName=A sample sortcut\nComment=This is a sample desktop entry text.\nTerminal=true\nExec=/path/to/script.sh\nIcon=[icons フォルダ直下に配置した画像名か、画像までのファイル名を含めた絶対パス 拡張子も書く]\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"desktopのファイルの配置場所\"\u003e\u003ccode\u003e.desktop\u003c/code\u003eのファイルの配置場所\u003c/h3\u003e\n\u003ch4 id=\"特定のユーザだけ\"\u003e特定のユーザだけ\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/home/[userName]/.local/share/applications\n# /home/$(whoami)/.local/share/applications\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"全体に反映\"\u003e全体に反映\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/usr/share/applications\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"アイコン画像の配置場所と利用方法\"\u003eアイコン画像の配置場所と利用方法\u003c/h3\u003e\n\u003cp\u003e　icons フォルダに直接画像を配置する場合は、デスクトップエントリの記述において\u003ccode\u003eIcon=[拡張子を含めたファイル名]\u003c/code\u003eで通り、すべてのパスを書く必要はない。階層構造を作るには、\u003ca href=\"https://specifications.freedesktop.org/icon-theme/latest/#icon_lookup\"\u003eIcon Theme Specification\u003c/a\u003e に従って厳密にインデックスなどをテキストで指定する必要があり手間がかかるので今回は省略する。それ以外の場所に配置する場合は、デスクトップエントリの記述において\u003ccode\u003eIcon=[画像のファイル名を含めた絶対パス]\u003c/code\u003eとする必要がある。 　\u003c/p\u003e\n\u003ch4 id=\"特定のユーザだけ-1\"\u003e特定のユーザだけ\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/home/[userName]/.local/share/icons\n# /home/$(whoami)/.local/share/icons\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"全体に反映-1\"\u003e全体に反映\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/usr/share/icons\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"例\"\u003e例\u003c/h2\u003e\n\u003cp\u003e　例として、ゆっくり霊夢をアイコンとした\u003ccode\u003eecho \u0026quot;ゆっくりしていってね!\u0026quot;\u003c/code\u003eを実行するスクリプトへのショートカットの作成について、以下に示す。\u003c/p\u003e\n\u003ch3 id=\"desktopファイル\"\u003e\u003ccode\u003e.desktop\u003c/code\u003eファイル\u003c/h3\u003e\n\u003ch4 id=\"配置場所\"\u003e配置場所\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/home/[userName]/.local/share/applications/yukkuri.desktop\n# /home/$(whoami)/.local/share/applications/yukkuri.desktop\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"内容\"\u003e内容\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Desktop Entry]\nVersion=1.0\nType=Application\nName=Yukkuri say something meaningless\nComment=Yukkuri will say something meaningless.\nTerminal=true\nExec=/home/[userName]/script/yukkuri/say.sh\nIcon=/home/[userName]/.local/share/icons/yukkuri/reimu/normal.png\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"スクリプト\"\u003eスクリプト\u003c/h3\u003e\n\u003ch4 id=\"配置場所-1\"\u003e配置場所\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/home/[userName]/script/yukkuri/say.sh\n# /home/$(whoami)/script/yukkuri/say.sh\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"内容-1\"\u003e内容\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ゆっくりしていってね!\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"画像\"\u003e画像\u003c/h3\u003e\n\u003ch4 id=\"配置場所-2\"\u003e配置場所\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/home/[userName]/.local/share/icons/yukkuri/reimu/normal.png\n# /home/$(whoami)/.local/share/icons/yukkuri/reimu/normal.png\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"ゆっくり霊夢の画像-normalpng\"\u003eゆっくり霊夢の画像 (normal.png)\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/createDesktopShortcutFile/%e3%81%ae%e3%83%bc%e3%81%be%e3%82%8b%e3%82%86%e3%81%a3%e3%81%8f%e3%82%8a.png#center\"\n         alt=\"ゆっくりしていってね！\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"動作例\"\u003e動作例\u003c/h3\u003e\n\u003ch4 id=\"期待したとおりに動作している例\"\u003e期待したとおりに動作している例\u003c/h4\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/createDesktopShortcutFile/desktop%20entry%e3%81%8c%e5%8f%8d%e6%98%a0%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"desktop entryが反映されている様子1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/createDesktopShortcutFile/desktop%20entry%e3%81%8c%e5%8f%8d%e6%98%a0%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"desktop entryが反映されている様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/createDesktopShortcutFile/%e3%82%b9%e3%82%af%e3%83%aa%e3%83%97%e3%83%88%e3%81%8c%e5%ae%9f%e8%a1%8c%e3%81%a7%e3%81%8d%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"スクリプトが実行できている様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"Linux 環境において、GNOME などが認識するショートカットを作成する"},{"content":"この記事を作った動機 最近 Blender に Flamenco を導入して分散コンピューティング？を試す において、SMB ではなく SSHFSを使う必要があることがわかったので、SSHFS を試そうとしたところ、躓いたため記録を取る。\n私の環境では、元々 SMB を使ってファイル共有を導入し、それを VPN 経由で利用していたが、それは普段の利用であってもファイルが大量にあるディレクトリを高遅延なネットワーク環境で開いたりすると1分ほど待たされたりするなど、明確に動作が遅いところがあった。そしてその挙動が、Blender の Flamenco の利用において顕著になり、限界が見受けられたため、SFTPを使った方法に移行するということがあった。\nBlender の Flamenco において問題が起きる前までは、SMB 以外にすでに SFTP を使っていたが、それは Gnome Shell 内臓のファイラーで使っていたが、そちらでは、sftp://の URL から始まるパスで Gnome が勝手に独自でマウントしたフォルダーにアクセスするようになっている。SMB のときのように、マウントポイント用のフォルダを作成して、そこにネットワークドライブをマウントするという形態は取っていなかったため、問題になった。\nそこで、SMB のように SFTP をマウントできる方法について、Google Gemini Fast 3に投げてみたところ、一つの提案として SSHFS を使う案が出てきたため試した。試したところ、コマンドラインにおいて、sshfsコマンドを使って、特定のフォルダに特定の SSH 接続先のフォルダをマウントするというような動作はできた。しかし、それを Systemd において自動化する際において、問題が起きた。\n問題としては、私が Systemd に専用に備わっている方法や、/etc/fstab に明記する方法ではなく、起動後に自分で書いた専用の管理 Python スクリプトを Systemd で動かし、VPN と ネットワークドライブの管理を自分で自動的に行う方法を取っていたことによってその処理内容がsshfsコマンドの特性上適切でないことで起こった。SMB の時点では、/etc/fstab に書くことでネットワークドライブをマウントする方法もやっていたことがあった。しかし、それだと起動時やシャットダウン時において、ネットワークドライブにアクセスできなかった場合に、OS ごと巻き込んで、起動が途中で止まったりシャットダウンが途中で止まったりするなど、課題になったため、自分で手動で Systemd サービスやスクリプトを書いて起動して Gnome Shell にログインしてから具体的な処理が自動で走るように書いていた。その仕様が今回 SSHFS を導入するにあたって問題となった。\nSSHFS - ArchWiki などに書いてあるように、専用の Systemd の automount を使ったりする方法もあるようであるが、私としては、ネットワークドライブは VPN の接続状況に応じて一緒に管理したいということがあった。SMB を使っていたときと同じように、SSHFS も自分でマウントするスクリプトを書いて、それを Systemd 経由でスクリプトとして実行し、専用の Python 管理スクリプトからは、systemd の自分で用意したネットワークドライブに関するサービスを叩くだけにしたいということがあった。\nそこで今回は、Systemd の automount などではなく、私がやりたい方法(Systemd からスクリプトを叩いて、SSHFS を動かす)はどうやったら実現できるか色々試したため、どうやったら動いたかそれについて軽くまとめたい。\n内容 Systemd スクリプト(/etc/systemd/system/mount.service) [Unit] Description=\u0026#34;Mount Network Drive (SSHFS)\u0026#34; # After=[任意に必要であれば書く] [Service] Type=forking User=[UserNameWhoCanGetSSHconnected] Group=[UserNameWhoCanGetSSHconnected] ExecStart=/Path/To.Script/File/mount.sh Restart=on-failure [Install] WantedBy=multi-user.target マウント用スクリプト(/Path/To.Script/File/mount.sh) #!/bin/bash sshfs [UserName]@[SftpServerIP]:/Path/On/The/SFTP/Server/shared/Folder /Path/To/MountPoint -o ServerAliveInterval=15,reconnect,ServerAliveCountMax=3,IdentityFile=/Path/To/SSH/PrivateKey,allow_other -f \u0026amp; sshfs [UserName]@[SftpServerIP]:/Path/On/The/SFTP/Server/shared/Folder1 /Path/To/MountPoint1 -o ServerAliveInterval=15,reconnect,ServerAliveCountMax=3,IdentityFile=/Path/To/SSH/PrivateKey,allow_other -f \u0026amp; # 他の接続も更に指定できる... 使い方 # マウントする systemctl start mount # 再マウントする systemctl restart mount # マウントを止める systemctl stop mount 問題の説明 今回の問題は、Systemd においてサービスタイプをsimpleに指定し、マウント用のスクリプト側でもプロセスを維持するように書いていないことによって、sshfsがすぐ終了してプロセスがなくなるために問題が起こった。問題が起こったときの挙動としては以下のような状態のループに陥った。\nPython 管理スクリプトが VPN に関する疎通確認をして、適宜必要な処理を走らせる Python 管理スクリプトがネットワークドライブについて、mountコマンドを使い、所定のドライブがマウントされているか確認する。 Pyhton 管理スクリプトがネットワークドライブが意図されたとおりにマウントされていないことを検出し、再接続を試みる。 Python 管理スクリプトが Root 権限で実行されているため、ネットワークドライブ再接続においてSystemctl restart mountもルート権限で実行される。 Systemd が、mount.shを実行しネットワークドライブへの接続を試みる。 一瞬ネットワークドライブの接続に成功するが、スクリプトの最後まで素通りしたらそれでプロセスが終了し、接続成功後数秒後にネットワークドライブの接続も消え、mountコマンドからも実態をすぐ確認できなくなる。 Python 管理スクリプトが、一定時間経過後ポーリングとして次の VPN と ネットワークドライブの疎通状況を確認するときに、ネットワークドライブが接続されていないことが検出される。 \u0026ldquo;1.\u0026ldquo;に戻って永遠に成功しない処理を実行し続けて処理が接続に失敗し続ける。 この問題の解決のために、以下の 3 つの変更を行ったところ、動作が安定するようになり、ネットワークドライブが利用可能になった。\nSystemd サービスにおいて、ネットワークドライブをマウントするサービスタイプを、simpleからforkingに変更し、プロセスが勝手になくならないようにした。 マウント処理を実際に実行する bash スクリプトにおいて、\u0026amp;を各sshfsコマンドの最後につけることで、フォアグラウンドの実行にすることで、sshfsコマンド実行時にスクリプトの実行がそこで妨げられて後発が実行されないことを避ける。 sshfsの引数で-fを指定する。 注意したほうが良さそうな点 ユーザを Systemd サービスにおいて明示する sshfsコマンドは SMB のときのように Root で実行する必要はなく、ssh 接続が可能なユーザとして実行するようにした。Root などとして実行するとセキュリティ問題が出るだけでなく、意図しないホームディレクトリの SSH 設定を覗きに行ったり、公開鍵を参照したりしてしまうことで、SSH 接続の認証に失敗する可能性がある。\n[Service] ... User=[UserNameWhoCanGetSSHconnected] Group=[UserNameWhoCanGetSSHconnected] ... SSHで使うキーのパスを明示する Systemd サービスにおいて、実行するユーザやグループを明示的に指定しても、Systemd サービスの実行自体を Root などから行っていると、意図しないホームディレクトリの SSH 設定を覗きに行ったり、公開鍵を参照したりしてしまうことで、SSH 接続の認証に失敗する可能性がある。\nsshfs ... -o ...,IdentityFile=/Path/To/SSH/PrivateKey,... SSHのタイムアウトや再試行回数を指定しておく SSHFS において、通常の SSH 接続と同じようにオプションを指定することができるがここでタイムアウトや再試行回数を制限しておかないと、どこかで動作が詰まったときにそこでずっと固まり続けて、強制再起動などでしか問題を解決できない状態になる恐れがある。\nsshfs ... -o ServerAliveInterval=15,reconnect,ServerAliveCountMax=3,... マウントポイントの権限を確認 通常マウントポイントとして作成するフォルダは、/mnt配下に作成することが多いと思われるが、その時に作成したフォルダの権限や所有者について、SSHFS を実行するユーザの権限で利用可能にしておかないと、正しくsshfsコマンドを実行できない。\npwd # /mnt mkdir test # mkdir: cannot create directory ‘mountPoint2’: Permission denied sudo mkdir mountPoint2 ls -l # drwxr-xr-x 1 userName userName 4096 Mar 3 06:45 mountPoint # drwxr-xr-x 1 userName userName 4096 Jan 18 04:05 mountPoint1 # drwxr-xr-x 2 root root 4096 Mar 24 20:13 mountPoint2 allow_otherオプションが有効にできない SSHFS において、SFTPのマウントを行ったユーザ以外もネットワークドライブを使えるようにするためにallow_otherオプションを有効する設定が必要である。設定をしていないときには以下のような挙動になり、allow_otherオプションをつけたときにsshfsコマンドが失敗することが確認できた。\nsystemctl status mount # ○ mount.service - \u0026#34;Mount Network Drive (SSHFS)\u0026#34; # Loaded: loaded (/etc/systemd/system/mount.service; disabled; preset: disabled) # Active: inactive (dead) # # Mar 26 17:02:42 HostName systemd[1]: Started \u0026#34;Mount Network Drive (SSHFS)\u0026#34;. # ... # Mar 26 17:02:42 HostName mount.sh[18911]: fusermount3: option allow_other only allowed if \u0026#39;user_allow_other\u0026#39; is set in /etc/fuse.conf # Mar 26 17:02:42 HostName mount.sh[18912]: fusermount3: option allow_other only allowed if \u0026#39;user_allow_other\u0026#39; is set in /etc/fuse.conf # Mar 26 17:02:42 HostName sudo[18902]: pam_unix(sudo:session): session closed for user UserName # Mar 26 17:02:42 HostName sudo[18903]: pam_unix(sudo:session): session closed for user UserName # Mar 26 17:02:42 HostName systemd[1]: mount.service: Deactivated successfully. この問題に対応するためには、/etc/fuse.confを以下のように編集した。\ncat /etc/fuse.conf # ... user_allow_other # ... SMB に比べて良かった点 SFTP を使う SSHFS には、以下の利点が見受けられた。\nVPN 環境を越しにネットワークドライブにアクセスするなど、高遅延環境に対して耐性があり、SMB とことなりファイル数が多いディレクトリなどを開いてもすぐに内容を表示したりできる。 SMB の時点では、以下のようにパスワードやユーザ名などがmountコマンド実行時に、直接プレインテキストとして含まれておりセキュリティの懸念がある。SFTP を使っている SSHFS は公開鍵認証を使っており直接パスワードや認証情報をコマンド文中で取り扱わないため、認証に使う公開鍵のファイルへの権限を個別に設定したりでき、より安全に認証情報など機密情報が管理できる。 sudo mount -t cifs -o user=[userName],password=\u0026#34;[PASSWORD]\u0026#34;,gid=[GroupID],uid=[userId] //[serverIP]/data /mnt/mountPointFolder 参考にしたサイトとか SSHFS - ArchWiki\nhttps://wiki.archlinux.org/title/SSHFS (2026年3月24日) Google Gemini\nhttps://gemini.google.com/app (2026年3月24日) Arch Linux - sshfs 3.7.5-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/sshfs/ (2026年3月24日) ssh(1) - Linux manual page\nhttps://man7.org/linux/man-pages/man1/ssh.1.html (2026年3月24日) sshfs(1) - Linux manual page\nhttps://man7.org/linux/man-pages/man1/sshfs.1.html (2026年3月24日) systemd.service(5) - Linux manual page\nhttps://man7.org/linux/man-pages/man5/systemd.service.5.html (2026年3月24日) ","permalink":"https://www.nyanmo.info/posts/linux/mountsshfsviasystemdwithabashscript/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 \u003ca href=\"posts/blender/flamenco.md\"\u003eBlender に Flamenco を導入して分散コンピューティング？を試す\u003c/a\u003e において、SMB ではなく SSHFSを使う必要があることがわかったので、SSHFS を試そうとしたところ、躓いたため記録を取る。\u003c/p\u003e\n\u003cp\u003e　私の環境では、元々 SMB を使ってファイル共有を導入し、それを VPN 経由で利用していたが、それは普段の利用であってもファイルが大量にあるディレクトリを高遅延なネットワーク環境で開いたりすると1分ほど待たされたりするなど、明確に動作が遅いところがあった。そしてその挙動が、Blender の Flamenco の利用において顕著になり、限界が見受けられたため、SFTPを使った方法に移行するということがあった。\u003c/p\u003e\n\u003cp\u003e　Blender の Flamenco において問題が起きる前までは、SMB 以外にすでに SFTP を使っていたが、それは Gnome Shell 内臓のファイラーで使っていたが、そちらでは、\u003ccode\u003esftp://\u003c/code\u003eの URL から始まるパスで Gnome が勝手に独自でマウントしたフォルダーにアクセスするようになっている。SMB のときのように、マウントポイント用のフォルダを作成して、そこにネットワークドライブをマウントするという形態は取っていなかったため、問題になった。\u003c/p\u003e\n\u003cp\u003e　そこで、SMB のように SFTP をマウントできる方法について、\u003ca href=\"https://gemini.google.com/app\"\u003eGoogle Gemini Fast 3\u003c/a\u003eに投げてみたところ、一つの提案として SSHFS を使う案が出てきたため試した。試したところ、コマンドラインにおいて、\u003ccode\u003esshfs\u003c/code\u003eコマンドを使って、特定のフォルダに特定の SSH 接続先のフォルダをマウントするというような動作はできた。しかし、それを Systemd において自動化する際において、問題が起きた。\u003c/p\u003e\n\u003cp\u003e　問題としては、私が Systemd に専用に備わっている方法や、/etc/fstab に明記する方法ではなく、起動後に自分で書いた専用の管理 Python スクリプトを Systemd で動かし、VPN と ネットワークドライブの管理を自分で自動的に行う方法を取っていたことによってその処理内容が\u003ccode\u003esshfs\u003c/code\u003eコマンドの特性上適切でないことで起こった。SMB の時点では、/etc/fstab に書くことでネットワークドライブをマウントする方法もやっていたことがあった。しかし、それだと起動時やシャットダウン時において、ネットワークドライブにアクセスできなかった場合に、OS ごと巻き込んで、起動が途中で止まったりシャットダウンが途中で止まったりするなど、課題になったため、自分で手動で Systemd サービスやスクリプトを書いて起動して Gnome Shell にログインしてから具体的な処理が自動で走るように書いていた。その仕様が今回 SSHFS を導入するにあたって問題となった。\u003c/p\u003e\n\u003cp\u003e　\u003ca href=\"https://wiki.archlinux.org/title/SSHFS\"\u003eSSHFS - ArchWiki\u003c/a\u003e などに書いてあるように、専用の Systemd の automount を使ったりする方法もあるようであるが、私としては、ネットワークドライブは VPN の接続状況に応じて一緒に管理したいということがあった。SMB を使っていたときと同じように、SSHFS も自分でマウントするスクリプトを書いて、それを Systemd 経由でスクリプトとして実行し、専用の Python 管理スクリプトからは、systemd の自分で用意したネットワークドライブに関するサービスを叩くだけにしたいということがあった。\u003c/p\u003e","title":"SSHFS を Systemd から BASH スクリプトを実行することでマウントしたい"},{"content":"この記事を作った動機 以下の Blender と Nvidia ドライバや CUDA の構成だと、CUDA のコンパイルに失敗して Cycles レンダリングにおける GPU 演算が正しく行われない結果になることがわかった。\nyay -Qs nvidia # local/cuda 13.1.1-1 (2.2 GiB 4.7 GiB) # NVIDIA\u0026#39;s GPU programming toolkit # local/egl-gbm 1.1.3-1 # The GBM EGL external platform library # local/egl-wayland 4:1.1.21-1 # EGLStream-based Wayland external platform # local/egl-wayland2 1.0.1-1 # EGLStream-based Wayland external platform (2) # local/egl-x11 1.0.5-1 # NVIDIA XLib and XCB EGL Platform Library # local/ffnvcodec-headers 13.0.19.0-1 # FFmpeg version of headers required to interface with Nvidias codec APIs # local/lib32-opencl-nvidia 590.48.01-1 # OpenCL implemention for NVIDIA (32-bit) # local/libnvidia-container 1.19.0-1 # NVIDIA container runtime library # local/libva-nvidia-driver 0.0.16-1 # VA-API implementation that uses NVDEC as a backend # local/libvdpau 1.5-4 # Nvidia VDPAU library # local/libxnvctrl 590.48.01-1 # NVIDIA NV-CONTROL X extension # local/linux-firmware-nvidia 20260309-1 # Firmware files for Linux - Firmware for NVIDIA GPUs and SoCs # local/nvidia-580xx-dkms 580.142-1 # NVIDIA kernel modules - module sources (580xx) # local/nvidia-580xx-utils 580.142-1 # NVIDIA drivers utilities (580xx) # local/nvidia-container-toolkit 1.19.0-1 # NVIDIA container toolkit # local/nvidia-prime 1.0-5 # NVIDIA Prime Render Offload configuration and utilities # local/nvidia-settings 590.48.01-1 # Tool for configuring the NVIDIA graphics driver # local/opencl-nvidia 590.48.01-4 # OpenCL implemention for NVIDIA yay -Qs blender # local/blender 17:5.0.1-9 # A fully integrated 3D graphics creation suite # local/blender-4.2-bin 4.2.260319.12a2dfa84963-1 # A fully integrated 3D graphics creation suite # local/blender-4.2-bin-debug 4.2.260319.12a2dfa84963-1 # Detached debugging symbols for blender-4.2-bin また、AUR にある CUDAの以下のバージョンを試したが、どれも正しく動かなかったし、現時点(2026/3/22)ではまだ動かす方法は見つかっていない。\n12.0 12.2 12.5 12.8 環境 GNOME Settings のレポート System Details Report Report details Date generated: 2026-03-22 09:23:39 Hardware Information: Hardware Model: HP ProLiant DL60 Gen9 Memory: 88.0 GiB Processor: Intel® Xeon® E5-2620 v4 × 32 Graphics: NVIDIA GeForce GTX 1080 Ti Disk Capacity: 30.0 TB Software Information: Firmware Version: U15 OS Name: Arch Linux OS Build: (null) OS Type: 64-bit GNOME Version: 49 Windowing System: Wayland Kernel Version: Linux 6.19.8-arch1-1 具体的な対応内容 今回、Arch Linux - blender 17:5.0.1-9 (x86_64) の Extra にある公式パッケージの利用は諦めて、手動で直接 Blender - The Free and Open Source 3D Creation Software — blender.org からダウンロードして使うことにした。\nただ、いちいち展開したり自分でファイルを管理するのは、あとからぐちゃぐちゃになって収集がつかなくなると思われたため、以下のリソースを主に参考にしてPKGBUILD を自分で書き、パッケージマネージャに仕事させることにした。\nAUR (en) - blender-bin の PKGBUILD AUR (en) - blender-4.2-bin の PKGBUILD makepkg - ArchWiki makepkg(8) — Arch manual pages PKGBUILD - ArchWiki PKGBUILD(5) — Arch manual pages Google Gemini Blender 公式からファイルを取得する Download — Blender にアクセスして、Linux 版のパッケージをダウンロードし展開せずにしておく。今回はダウンロードしたファイルは以下のように配置されている事を想定する。\npwd # /home/userName/Downloads ls -l blender* # -rw-r--r--⠀userName⠀userName⠀44105692⠀Mar 22 09:12:37⠀⠀blender-5.1.0-linux-x64.tar.xz ファイルを配置する 作業ディレクトリを作成する mkdir /tmp/blenderInstall cd /tmp/blenderInstall ダウンロードしたファイルを配置する cp /home/userName/Downloads/blender-5.1.0-linux-x64.tar.xz /tmp/blenderInstall/ PKGBUILD を配置する # This is workaround for GTX1080Ti to avoid compile error due to cuda version mismatch. pkgname=Blender-5.1.0-manual-install pkgver=5.1.0 pkgrel=1 pkgdesc=\u0026#34;This is workaround for Blender with GTX1080Ti to avoid compile error due to cuda version mismatch.\u0026#34; arch=(\u0026#39;x86_64\u0026#39;) url=\u0026#34;https://blender.org\u0026#34; license=(\u0026#39;GPL\u0026#39;) options=(\u0026#39;!strip\u0026#39; \u0026#39;!debug\u0026#39;) depends=(\u0026#39;blender\u0026#39;) optdepends=(\u0026#39;cuda: Cycles renderer CUDA support\u0026#39; \u0026#39;intel-compute-runtime: Cycles renderer Intel OneAPI support\u0026#39; \u0026#39;level-zero-loader: Cycles renderer Intel OneAPI support\u0026#39; \u0026#39;intel-level-zero-raytracing-support: Intel OneAPI Raytracing Support\u0026#39; \u0026#39;libdecor: wayland support\u0026#39; \u0026#39;hip-runtime-amd: HIP renderer AMD support\u0026#39;) provides=(\u0026#39;blender-manual-install\u0026#39;) conflicts=(\u0026#39;blender-manual-install\u0026#39;) source=(\u0026#34;./blender-5.1.0-linux-x64.tar.xz\u0026#34;) sha256sums=(\u0026#39;SKIP\u0026#39;) package() { cd \u0026#34;$srcdir/blender-$pkgver-linux-x64\u0026#34; mkdir -p \u0026#34;${pkgdir}/opt/${pkgname}/\u0026#34; install -Dm755 {blender,blender-thumbnailer} \u0026#34;${pkgdir}/opt/${pkgname}/\u0026#34; install -Dm644 blender.desktop \u0026#34;${pkgdir}/usr/share/applications/${pkgname}.desktop\u0026#34; sed -i \u0026#34;s|Name=Blender|Name=Blender 5.1.0 (Manual Install)|g\u0026#34; \u0026#34;${pkgdir}/usr/share/applications/${pkgname}.desktop\u0026#34; sed -i \u0026#34;s|Exec=blender %f|Exec=/opt/${pkgname}/blender-launcher %f|g\u0026#34; \u0026#34;${pkgdir}/usr/share/applications/${pkgname}.desktop\u0026#34; cp -a -r \u0026#34;${pkgver:0:3}\u0026#34; lib \u0026#34;${pkgdir}/opt/${pkgname}/\u0026#34; pushd \u0026#34;${pkgdir}/opt/${pkgname}/lib\u0026#34; for file in *.so*; do chmod 755 \u0026#34;$file\u0026#34; done popd pushd \u0026#34;${pkgdir}/opt/${pkgname}/lib/mesa\u0026#34; for file in *.so*; do chmod 755 \u0026#34;$file\u0026#34; done popd install -Dm755 blender-launcher \u0026#34;${pkgdir}/opt/${pkgname}/blender-launcher\u0026#34; install -Dm755 blender-softwaregl \u0026#34;${pkgdir}/opt/${pkgname}/blender-softwaregl\u0026#34; install -Dm755 blender-system-info.sh \u0026#34;${pkgdir}/opt/${pkgname}/blender-system-info\u0026#34; } インストール makepkg -si 動作の様子の例 発生したエラーの詳細 ここでは、CUDA 13.1 と CUDA 12.8 の動作の様子について示す。CUDA 13.1 については、GTX 1080Ti をサポートしない旨が表示され、CUDA 12.8 ではコンパイルエラーが起こっている。\nCUDA 13.1 動画 ログ エラーの詳細 blender # Traceback (most recent call last): # File \u0026#34;/usr/share/blender/5.0/scripts/modules/addon_utils.py\u0026#34;, line 362, in enable # raise RuntimeError(\u0026#34;Extension {:s} is incompatible ({:s})\u0026#34;.format(module_name, error)) # RuntimeError: Extension bl_ext.blender_org.mmd_tools is incompatible (This Blender version (5.0.1) must be less than the maximum version (5.0.0)) # 05:40.336 cycles | ERROR CUDA version 13.1CUDA 10.1 to 12 are officially supported. # nvcc fatal : Unsupported gpu architecture \u0026#39;sm_61\u0026#39; # 05:40.342 cycles | ERROR Failed to execute compilation command, see console for details. # 05:40.342 cycles | ERROR Refer to the Cycles GPU rendering documentation for possible solutions: # | https://docs.blender.org/manual/en/latest/render/cycles/gpu_rendering.html # | # 05:40.342 cycles | ERROR Invalid handle in cuModuleGetGlobal_v2(\u0026amp;mem, \u0026amp;bytes, cuModule, \u0026#34;kernel_params\u0026#34;) (/usr/src/debug/blender/blender/intern/cycles/device/cuda/device_impl.cpp:678) # 05:40.342 cycles | ERROR Invalid value in cuMemcpyHtoD_v2(mem + __builtin_offsetof (KernelParamsCUDA, data), host, size) (/usr/src/debug/blender/blender/intern/cycles/device/cuda/device_impl.cpp:687) CUDA 12.8 動画 ログ エラーの詳細 blender # Traceback (most recent call last): # File \u0026#34;/usr/share/blender/5.0/scripts/modules/addon_utils.py\u0026#34;, line 362, in enable # raise RuntimeError(\u0026#34;Extension {:s} is incompatible ({:s})\u0026#34;.format(module_name, error)) # RuntimeError: Extension bl_ext.blender_org.mmd_tools is incompatible (This Blender version (5.0.1) must be less than the maximum version (5.0.0)) # nvcc warning : Support for offline compilation for architectures prior to \u0026#39;\u0026lt;compute/sm/lto\u0026gt;_75\u0026#39; will be removed in a future release (Use -Wno-deprecated-gpu-targets to suppress warning). # /usr/include/c++/15.2.1/type_traits(555): error: type name is not allowed # : public __bool_constant\u0026lt;__is_pointer(_Tp)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(555): error: identifier \u0026#34;__is_pointer\u0026#34; is undefined # : public __bool_constant\u0026lt;__is_pointer(_Tp)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(877): error: type name is not allowed # : public __bool_constant\u0026lt;__is_volatile(_Tp)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(877): error: identifier \u0026#34;__is_volatile\u0026#34; is undefined # : public __bool_constant\u0026lt;__is_volatile(_Tp)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(1492): error: type name is not allowed # : public integral_constant\u0026lt;std::size_t, __array_rank(_Tp)\u0026gt; { }; # ^ # # /usr/include/c++/15.2.1/type_traits(1492): error: identifier \u0026#34;__array_rank\u0026#34; is undefined # : public integral_constant\u0026lt;std::size_t, __array_rank(_Tp)\u0026gt; { }; # ^ # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;int, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; (aka \u0026#34;std::__cv_selector\u0026lt;unsigned int, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34;) is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=int, _Unqualified=unsigned int, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1953 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=int]\u0026#34; at line 1964 # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;char16_t, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; (aka \u0026#34;std::__cv_selector\u0026lt;unsigned short, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34;) is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=char16_t, _Unqualified=unsigned short, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1953 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char16_t]\u0026#34; at line 1980 # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;int, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; (aka \u0026#34;std::__cv_selector\u0026lt;unsigned int, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34;) is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=char32_t, _Unqualified=unsigned int, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1953 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char32_t]\u0026#34; at line 1987 # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;int, true, false\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=int, _Unqualified=\u0026lt;error-type\u0026gt;, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1915 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, true, false\u0026gt; [with _Tp=int]\u0026#34; at line 2082 # instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=int]\u0026#34; at line 2096 # # /usr/include/c++/15.2.1/type_traits(2085): error: incomplete type \u0026#34;std::__make_signed_selector\u0026lt;std::__make_signed_selector\u0026lt;int, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __make_signed_selector\u0026lt;__unsigned_type\u0026gt;::__type; # ^ # detected during instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=int]\u0026#34; at line 2096 # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;int, true, false\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=char16_t, _Unqualified=\u0026lt;error-type\u0026gt;, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1915 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, true, false\u0026gt; [with _Tp=char16_t]\u0026#34; at line 2082 # instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char16_t]\u0026#34; at line 2112 # # /usr/include/c++/15.2.1/type_traits(2085): error: incomplete type \u0026#34;std::__make_signed_selector\u0026lt;std::__make_signed_selector\u0026lt;int, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __make_signed_selector\u0026lt;__unsigned_type\u0026gt;::__type; # ^ # detected during instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char16_t]\u0026#34; at line 2112 # # /usr/include/c++/15.2.1/type_traits(1844): error: incomplete type \u0026#34;std::__cv_selector\u0026lt;std::__make_unsigned_selector\u0026lt;int, true, false\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __match::__type; # ^ # detected during: # instantiation of class \u0026#34;std::__match_cv_qualifiers\u0026lt;_Qualified, _Unqualified, _IsConst, _IsVol\u0026gt; [with _Qualified=char32_t, _Unqualified=\u0026lt;error-type\u0026gt;, _IsConst=false, _IsVol=\u0026lt;error-constant\u0026gt;]\u0026#34; at line 1915 # instantiation of class \u0026#34;std::__make_unsigned_selector\u0026lt;_Tp, true, false\u0026gt; [with _Tp=char32_t]\u0026#34; at line 2082 # instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char32_t]\u0026#34; at line 2119 # # /usr/include/c++/15.2.1/type_traits(2085): error: incomplete type \u0026#34;std::__make_signed_selector\u0026lt;std::__make_signed_selector\u0026lt;int, false, true\u0026gt;::__unsigned_type, false, \u0026lt;error-constant\u0026gt;\u0026gt;\u0026#34; is not allowed # using __type = typename __make_signed_selector\u0026lt;__unsigned_type\u0026gt;::__type; # ^ # detected during instantiation of class \u0026#34;std::__make_signed_selector\u0026lt;_Tp, false, true\u0026gt; [with _Tp=char32_t]\u0026#34; at line 2119 # # /usr/include/c++/15.2.1/type_traits(3303): error: type name is not allowed # : public __bool_constant\u0026lt;__is_invocable(_Fn, _ArgTypes...)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(3303): error: type name is not allowed # : public __bool_constant\u0026lt;__is_invocable(_Fn, _ArgTypes...)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(3333): error: type name is not allowed # : public __bool_constant\u0026lt;__is_nothrow_invocable(_Fn, _ArgTypes...)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(3333): error: type name is not allowed # : public __bool_constant\u0026lt;__is_nothrow_invocable(_Fn, _ArgTypes...)\u0026gt; # ^ # # /usr/include/c++/15.2.1/type_traits(3409): error: type name is not allowed # inline constexpr bool is_pointer_v = __is_pointer(_Tp); # ^ # # /usr/include/c++/15.2.1/type_traits(3522): error: type name is not allowed # inline constexpr bool is_volatile_v = __is_volatile(_Tp); # ^ # # /usr/include/c++/15.2.1/type_traits(3664): error: type name is not allowed # inline constexpr size_t rank_v = __array_rank(_Tp); # ^ # # /usr/include/bits/mathcalls.h(83): error: exception specification is incompatible with that of previous function \u0026#34;cospi\u0026#34; (declared at line 2601 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern double cospi (double __x) noexcept (true); extern double __cospi (double __x) noexcept (true); # ^ # # /usr/include/bits/mathcalls.h(85): error: exception specification is incompatible with that of previous function \u0026#34;sinpi\u0026#34; (declared at line 2556 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern double sinpi (double __x) noexcept (true); extern double __sinpi (double __x) noexcept (true); # ^ # # /usr/include/bits/mathcalls.h(206): error: exception specification is incompatible with that of previous function \u0026#34;rsqrt\u0026#34; (declared at line 597 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern double rsqrt (double __x) noexcept (true); extern double __rsqrt (double __x) noexcept (true); # ^ # # /usr/include/bits/mathcalls.h(83): error: exception specification is incompatible with that of previous function \u0026#34;cospif\u0026#34; (declared at line 2623 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern float cospif (float __x) noexcept (true); extern float __cospif (float __x) noexcept (true); # ^ # # /usr/include/bits/mathcalls.h(85): error: exception specification is incompatible with that of previous function \u0026#34;sinpif\u0026#34; (declared at line 2579 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern float sinpif (float __x) noexcept (true); extern float __sinpif (float __x) noexcept (true); # ^ # # /usr/include/bits/mathcalls.h(206): error: exception specification is incompatible with that of previous function \u0026#34;rsqrtf\u0026#34; (declared at line 621 of /opt/cuda/bin/../targets/x86_64-linux/include/crt/math_functions.h) # extern float rsqrtf (float __x) noexcept (true); extern float __rsqrtf (float __x) noexcept (true); # ^ # # 28 errors detected in the compilation of \u0026#34;/usr/share/blender/5.0/scripts/addons_core/cycles/source/kernel/device/cuda/kernel.cu\u0026#34;. # 01:18.904 cycles | ERROR Failed to execute compilation command, see console for details. # 01:18.904 cycles | ERROR Refer to the Cycles GPU rendering documentation for possible solutions: # | https://docs.blender.org/manual/en/latest/render/cycles/gpu_rendering.html # | # 01:18.904 cycles | ERROR Invalid handle in cuModuleGetGlobal_v2(\u0026amp;mem, \u0026amp;bytes, cuModule, \u0026#34;kernel_params\u0026#34;) (/usr/src/debug/blender/blender/intern/cycles/device/cuda/device_impl.cpp:678) # 01:18.904 cycles | ERROR Invalid value in cuMemcpyHtoD_v2(mem + __builtin_offsetof (KernelParamsCUDA, data), host, size) (/usr/src/debug/blender/blender/intern/cycles/device/cuda/device_impl.cpp:687) 関係ありそうな記事 Blender に Flamenco を導入して分散コンピューティング？を試す 参考にしたサイトとか NVIDIA GeForce GTX 1080 Ti Specs | TechPowerUp GPU Database\nhttps://www.techpowerup.com/gpu-specs/geforce-gtx-1080-ti.c2877 (2026年3月22日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年3月22日)\nBlender - The Free and Open Source 3D Creation Software — blender.org\nhttps://www.blender.org/ (2026年3月22日)\nAUR (en) - cuda12.0\nhttps://aur.archlinux.org/packages/cuda12.0 (2026年3月22日)\nAUR (en) - cuda-12.2\nhttps://aur.archlinux.org/packages/cuda-12.2 (2026年3月22日)\nAUR (en) - cuda-12.5\nhttps://aur.archlinux.org/packages/cuda-12.5 (2026年3月22日)\nAUR (en) - cuda-12.8\nhttps://aur.archlinux.org/packages/cuda-12.8 (2026年3月22日)\nArch Linux - blender 17:5.0.1-9 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/blender/ (2026年3月22日)\nAUR (en) - blender-bin\nhttps://aur.archlinux.org/packages/blender-bin (2026年3月22日)\nAUR (en) - blender-4.2-bin\nhttps://aur.archlinux.org/packages/blender-4.2-bin (2026年3月22日)\nmakepkg - ArchWiki\nhttps://wiki.archlinux.org/title/Makepkg (2026年3月22日)\nmakepkg(8) — Arch manual pages\nhttps://man.archlinux.org/man/makepkg.8.en (2026年3月22日)\nPKGBUILD - ArchWiki\nhttps://wiki.archlinux.org/title/PKGBUILD (2026年3月22日)\nPKGBUILD(5) — Arch manual pages\nhttps://man.archlinux.org/man/PKGBUILD.5 (2026年3月22日)\n","permalink":"https://www.nyanmo.info/posts/blender/makegtx1080ti-pascalgpuworkonblender5.x.x/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　以下の Blender と Nvidia ドライバや CUDA の構成だと、CUDA のコンパイルに失敗して Cycles レンダリングにおける GPU 演算が正しく行われない結果になることがわかった。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Qs nvidia\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/cuda 13.1.1-1 (2.2 GiB 4.7 GiB) \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA\u0026#39;s GPU programming toolkit\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/egl-gbm 1.1.3-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     The GBM EGL external platform library\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/egl-wayland 4:1.1.21-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     EGLStream-based Wayland external platform\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/egl-wayland2 1.0.1-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     EGLStream-based Wayland external platform (2)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/egl-x11 1.0.5-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA XLib and XCB EGL Platform Library\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/ffnvcodec-headers 13.0.19.0-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     FFmpeg version of headers required to interface with Nvidias codec APIs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/lib32-opencl-nvidia 590.48.01-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     OpenCL implemention for NVIDIA (32-bit)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/libnvidia-container 1.19.0-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA container runtime library\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/libva-nvidia-driver 0.0.16-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     VA-API implementation that uses NVDEC as a backend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/libvdpau 1.5-4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Nvidia VDPAU library\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/libxnvctrl 590.48.01-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA NV-CONTROL X extension\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/linux-firmware-nvidia 20260309-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Firmware files for Linux - Firmware for NVIDIA GPUs and SoCs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/nvidia-580xx-dkms 580.142-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA kernel modules - module sources (580xx)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/nvidia-580xx-utils 580.142-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA drivers utilities (580xx)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/nvidia-container-toolkit 1.19.0-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA container toolkit\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/nvidia-prime 1.0-5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     NVIDIA Prime Render Offload configuration and utilities\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/nvidia-settings 590.48.01-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Tool for configuring the NVIDIA graphics driver\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/opencl-nvidia 590.48.01-4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     OpenCL implemention for NVIDIA\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Qs blender\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/blender 17:5.0.1-9\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     A fully integrated 3D graphics creation suite\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/blender-4.2-bin 4.2.260319.12a2dfa84963-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     A fully integrated 3D graphics creation suite\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/blender-4.2-bin-debug 4.2.260319.12a2dfa84963-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Detached debugging symbols for blender-4.2-bin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　また、AUR にある CUDAの以下のバージョンを試したが、どれも正しく動かなかったし、現時点(2026/3/22)ではまだ動かす方法は見つかっていない。\u003c/p\u003e","title":"Blender 5.x.x において、GTX 1080Ti(Pascal) を Cycles レンダリングで使えるようにしたい"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 最近 Gemini Fast 3 を使っていると、Blender において分散コンピューティングみたいなレンダリングの仕方ができることが分かり、気になった。それで、最初は Gemini Fast 3 が提案してきて、Blender - ArchWiki にも掲載されている、BlendNetを試そうと思った。\nしかし、BlendNet のリポジトリを見てみると、実際のところは Blender 2.x.x の古い Blender にしか対応してなさそうな感じであった。私が使っている Blender のバージョンは 5.x.x 以降であったことから、別の物がないか Gemini Fast 3 に提案させてみると、Blender 公式の Flamenco が出てきたため試した。\nそして、とりあえず動くようになるところまで、設定して確かめることができたため、そのことについて記録したい。まだ完全ではなく、途中でレンダリングに失敗したりと、成果物を得られている状態ではない。現状では Flamenco Manager と Flamenco Worker が実際に疎通を取り、Manager 側のクライアントの Blender からジョブを投げると、Worker 側がレンダリングを開始し負荷がかかるところまで確認した。\n細かい説明(序章) 全体的な Flamenco 運用イメージ 以下に構築する環境のイメージを示す。今回はファイル共有サーバと Worker となる PC は物理的に1つに全部がまとまっている事を想定しているが、以下の画像ではわかりやすさのために、ファイル共有サーバやレンダリングを行う Worker farm の PC は物理的に分けている前提で表現している。 前提について 以下の点については、すでに設定されているものまたは前提として取り扱う。\nManager 側と Worker 側の間の設定 LAN で物理的に同じネットワークに繋がっているか、VPNによって実質的に同じネットワークに繋がっている。 SSH の設定が済ませてあり、LAN で物理的に同じネットワークに繋がっているときに疎通が取れる。 ping によって物理的に同じネットワークに繋がっているときに疎通が取れる。 Worker 側は GNOME RDP の設定が済ませてあり、Remmina クライアントにより LAN で物理的に同じネットワークに繋がっているときに疎通が取れる。 SFTP によるファイル共有が可能な状態になっている。 どちらも Linux 環境がセットアップされてあり、インターネットへの接続が確認できている。 firewalld をファイアウォールとして使っている。 VPN での接続がある場合について SMB ではなく SFTP によってファイルのやり取りを行う。 MTU サイズが十分小さく設定されており、ネットワーク障害が発生しないように設定されている。(MTUサイズ1000にするなど) 高遅延を前提とする。 Manager 側の視点から設定作業などを行い、Flamenco Manager と Blender を立ち上げた状態で作業する。 Manager 側と Worker 側は VPN によって遠隔地で通信を行う。 単語の解釈 Worker Flamenco において実際にレンダリング処理をする端末を、Flamenco公式ドキュメントなどを見た結果、Workerと呼ぶと私は現時点(2026/3/22)では解釈している。\nManager Flamenco において実際に Blender で対象のプロジェクトを開き、レンダリング処理を命令する端末を、Flamenco公式ドキュメントなどを見た結果、Managerと呼ぶと私は現時点(2026/3/22)では解釈している。\nやり方 (Worker 側) GTX1080Ti など古い環境を使っている場合は、blender の実行バイナリについて工夫が必要である。(Blender 5.x.x において、GTX 1080Ti(Pascal) を Cycles レンダリングで使えるようにしたい)\n必要なパッケージをインストールする yay -S blender flamenco-worker を手動でインストール 設定を保存するディレクトリとで作成した場所と同じ場所にDownload | Flamencoからダウンロードしてきたflamenco-workerのバイナリを配置する。設定ファイルとバイナリを配置するディレクトリは任意の場所で良いが、一度作成すると Systemd でそこを絶対パスで指定したりしてあとから変えるのは面倒くさいので、作成場所に注意すること。\n専用のネットワーク共有フォルダを作成する Client(Managerを動かしている側) と Worker側で絶対パスが一致する必要があるため、工夫が必要である。今回の例では、専用に共有するフォルダを/mnt配下に新規作成する。\n# 適宜 chmod chown で権限や所有者情報を変更し、flamenco-worker や sshfs で接続する manager 側 PC が読み書きできるようにしておく。 mkdir /mnt/FlamencoRenderPlace flamenco-workerを設定する flamenco-worker用の設定ファイルを配置しておくディレクトリを作成し、Worker Configuration | Flamencoを参考に以下のようにして設定をflamenco-worker.yamlとして保存する。\nmanager_url: http://[managerServerIP:managerServerPort]/ task_types: [blender, ffmpeg, file-management, misc] restart_exit_code: 47 # Optional advanced option, available on Linux only: oom_score_adjust: 500 flamenco-workerを起動する Systemd サービスを用意 /etc/systemd/system/flamenco-worker.serviceとして配下に以下を配置する。flamenco-workerを設定するのところで、flamenco-worker.yamlを配置したフォルダーをWorkingDirectory=の項目に指定する。ExecStart=に指定するflamenco-workerのバイナリも絶対パスで手動で配置したものを指定する。\n[Unit] Description=\u0026#34;Start Flamenco Worker for blender rendering.\u0026#34; #After= [Service] WorkingDirectory=/Path/To/Flamenco/Worker/config/folder Type=simple User=[UserNameWhoUseTheWorker] ExecStart=/Path/To/Flamenco/Worker/config/folder/flamenco-worker Restart=on-failure [Install] WantedBy=multi-user.target flamenco-workerを起動(有効化)する sudo systemctl enable --now flamenco-worker やり方 (Manager 側) 必要なパッケージをインストールする yay -S sshfs blender flamenco-manager を手動でインストール 設定を保存するディレクトリとで作成した場所と同じ場所にDownload | Flamencoからダウンロードしてきたflamenco-managerのバイナリを配置する。設定ファイルとバイナリを配置するディレクトリは任意の場所で良いが、一度作成すると Systemd でそこを絶対パスで指定したりしてあとから変えるのは面倒くさいので、作成場所に注意すること。\n専用のネットワーク共有フォルダをマウントする Client(Managerを動かしている側) と Worker側で絶対パスが一致する必要があるため、工夫が必要である。今回の例では、専用に共有するフォルダを/mnt配下に新規作成する。\nファイヤーウォールの設定をする 今回は、58080番に flamenco を動作させることを仮定して以下のように設定する。\n# 適宜既存の設定次第で、--zoneオプションなどをつける必要がある。 # 今回は Manager として機能する PC は firewalld デフォルトの public ゾーンを使っていることを仮定している。 sudo firewall-cmd --add-port=58080/tcp --permanent sudo firewall-cmd --add-port=58080/udp --permanent sudo systemctl restart firewalld flamenco-managerを設定する flamenco-manager用の設定を配置しておくディレクトリを作成し、flamenco-manager -write-configを実行することでflamenco-manager.yamlのテンプレートを生成させる。\nflamenco-manager -write-config # 2026-03-26T19:37:59+09:00 INF starting Flamenco arch=amd64 git=f7aef5bfc os=linux osDetail=\u0026#34;Arch Linux (6.18.13-arch1-1)\u0026#34; releaseCycle=release version=3.5 # 2026-03-26T19:37:59+09:00 INF This seems to be your first run of Flamenco! A webbrowser will open to help you set things up. # 2026-03-26T19:37:59+09:00 INF configuration file written filename=flamenco-manager.yaml # 2026-03-26T19:37:59+09:00 INF stopping the Flamenco Manager process ls # flamenco-manager.yaml flamenco-managerを起動する Systemd サービスを用意 /etc/systemd/system/flamenco-manager.serviceとして配下に以下を配置する。flamenco-managerを設定するのところで、flamenco-manager.yamlを配置したディレクトリをWorkingDirectory=として指定する。ExecStart=に指定するflamenco-managerのバイナリも絶対パスで手動で配置したものを指定する。\n[Unit] Description=\u0026#34;Start Flamenco Manager for blender rendering.\u0026#34; #After= [Service] WorkingDirectory=/Path/To/Flamenco/Manager/config/folder Type=simple User=[UserNameWhoUseTheManager] ExecStart=/Path/To/Flamenco/Manager/config/folder/flamenco-manager Restart=on-failure [Install] WantedBy=multi-user.target flamenco-managerを起動(有効化)する sudo systemctl enable --now flamenco-manager ブラウザでフロントエンドを開いて初期設定を行う。 今回は、58080番を指定したので、http://localhost:58080に好みのブラウザでアクセスする。flamenco-managerは初回起動時に、ネットワークドライブの manager と worker で共有する場所のパスと、manager 側の PC に入っている Blender バイナリについて聞いてくるので、適宜設定する。 アドオンをインストール Flamenco には、Blender と提携するための専用のアドオンがあるため、Flamenco のフロントエンドからアドオンをダウンロードしてインストールする。flamenco-managerのフロントエンドからダウンロードする zip ファイルは展開せずそのまま Blender の設定画面で読み込ませる。ダウンロードしたファイルは、ユーザのホームディレクトリからして、ダウンロードされたファイルが配置される場所にあるものとする。\nアドオン本体のダウンロード Blender にアドオンをインストール 躓いたこと AUR にある AUR (en) - flamenco はインストールに失敗する Download | Flamencoから直接ダウンロードして展開した物を使うのが良いと思われる。いろいろ試したところflamenco-worker-が動作しないで書いたように、AUR にある Flamenco を使うことは、Flamenco 開発元の思想と相性が極端に悪く解決しない問題があるためやめたほうがいいという結論に今回はなった。\nmakepkg -si ==\u0026gt; パッケージを作成: flamenco 3.5-1 (2026年03月21日 23時57分59秒) ==\u0026gt; ランタイムの依存関係を確認... ==\u0026gt; ビルドタイムの依存関係を確認... ==\u0026gt; ソースを取得... -\u0026gt; flamenco git リポジトリを複製... Cloning into bare repository \u0026#39;/home/main/work/flamenco/flamenco\u0026#39;... fatal: unable to access \u0026#39;https://projects.blender.org/studio/flamenco.git/\u0026#39;: The requested URL returned error: 403 ==\u0026gt; エラー: flamenco git リポジトリのダウンロードに失敗 中止... 記事を書くために問題を再現しようとしたところ、障害が直っていた。\nmakepkg -si ==\u0026gt; パッケージを作成: flamenco 3.5-1 (2026年03月22日 02時50分28秒) ==\u0026gt; ランタイムの依存関係を確認... ==\u0026gt; ビルドタイムの依存関係を確認... ==\u0026gt; ソースを取得... -\u0026gt; flamenco git リポジトリを複製... Cloning into bare repository \u0026#39;/home/main/work/flamenco/flamenco\u0026#39;... remote: Enumerating objects: 46487, done. ^Cfetch-pack: unexpected disconnect while reading sideband packet ==\u0026gt; エラー: Aborted by user! Exiting... SMB でファイル共有すると限界がある 私が当初 Flamenco を試したときには、ファイル共有に SMB を使っていた。しかしそれだと、VPN経由でファイルをやり取りする構成で、VPN経由で Worker 側と Manager 側が隔たれている環境だと、限界があるらしく Flamenco の動作が固まってしまい、Blender が応答しなくなったり、強制終了にも応じなくなるなどの問題が起こり、不安定なことがわかった。\nそのため、解決策としてそもそも SMB を使わず、SFTP を使うようにした。SFTP では、SMB とはことなり、高遅延なネットワーク環境においても、ある程度安定して動作することが確認できた。SFTP は、コマンドライン等で SMB と同じようにネットワークドライブとしてマウントする方法を今回使っている。\nWorker 側で特定の Blender を実行させる 環境によっては AUR から直接インストールした blender が使えず、GPU が正しく動作する構成にした Blender をリンダリングに使うよう指定する必要があることがある。やり方としては以下のことが考えられた。\nBlender の手動インストールと設定を行い、Flamenco の設定でそのバイナリを使うように誘導する。 既存の Blender と共存するために、blender-manual-installなどの名前でコマンドラインから呼び出せるようにし、それを Flamenco の Worker の項目で設定する。 Flamenco 起動時だけ特定の PATH を設定し、優先的に意図した Blender バイナリが、blenderコマンドを入力したときに優先的に使われるように仕向ける。 flamenco-manager と flamenco-worker の設定ファイルの場所 flamenco-manager は基本的にコマンドが実行されたカレントディレクトリを起点として、flamenco-manager.yamlを探しているようであり、決まった配置場所はないようである。flamenco-workerについても設定ファイルがflamenco-worker.yamlになり内容が worker 専用になる以外は、コマンドが実行されたカレントディレクトリを起点として設定ファイルを探しに行くようである。Systemd のサービスにおいては、このことに配慮して、flamenco-managerやflamenco-workerを実行する際のカレントディレクトリがflamenco-manager.yamlやflamenco-worker.yamlの設定ファイルが見つけられるよう、それらファイルが存在するフォルダ内になるようにする。\nflamenco-worker が動作しない (いくら設定してもパスが勝手に/usr/binを起点にしたり変なパスを使おうとする) いくら、flamenco-manager側から正しいパスを設定しても内部で正しく解釈されず不正なパスを利用しようとしてしまう挙動が見受けられた。この問題に関しては、Flamenco の Worker と Manager を AUR (en) - flamenco や AUR (en) - flamenco でインストールするとバイナリが/usr/bin配下に配置されてしまい、そこを起点としてパスを組み立てようとする Flamenco そのものの動作に起因していると思われ、いくら設定を変えても施しようがなさそうなことがわかった。\nこの問題の解決策に関しては、flamenco-managerを設定するやflamenco-workerを設定するの項目で作成したディレクトリ内に直接Download | Flamencoからダウンロードしてきたflamenco-managerとflamenco-workerのバイナリを配置する以上の対策はなさそうである。以下は問題発生時の Worker PC 側のログである。\n./flamenco-worker # ... # 2026-03-26T22:16:09+09:00 WRN unable to obtain task for unknown reason error=\u0026#34;{\\\u0026#34;code\\\u0026#34;:500,\\\u0026#34;message\\\u0026#34;:\\\u0026#34;internal error appending to task log: creating directory: mkdir /usr/bin/mnt: permission denied\\\u0026#34;}\\n\u0026#34; code=500 # 2026-03-26T22:16:19+09:00 WRN unable to obtain task for unknown reason error=\u0026#34;{\\\u0026#34;code\\\u0026#34;:500,\\\u0026#34;message\\\u0026#34;:\\\u0026#34;internal error appending to task log: creating directory: mkdir /usr/bin/mnt: permission denied\\\u0026#34;}\\n\u0026#34; code=500 # 2026-03-26T22:16:29+09:00 WRN unable to obtain task for unknown reason error=\u0026#34;{\\\u0026#34;code\\\u0026#34;:500,\\\u0026#34;message\\\u0026#34;:\\\u0026#34;internal error appending to task log: creating directory: mkdir /usr/bin/mnt: permission denied\\\u0026#34;}\\n\u0026#34; code=500 # 2026-03-26T22:16:40+09:00 WRN unable to obtain task for unknown reason error=\u0026#34;{\\\u0026#34;code\\\u0026#34;:500,\\\u0026#34;message\\\u0026#34;:\\\u0026#34;internal error appending to task log: creating directory: mkdir /usr/bin/mnt: permission denied\\\u0026#34;}\\n\u0026#34; code=500 # 2026-03-26T22:16:50+09:00 WRN unable to obtain task for unknown reason error=\u0026#34;{\\\u0026#34;code\\\u0026#34;:500,\\\u0026#34;message\\\u0026#34;:\\\u0026#34;internal error appending to task log: creating directory: mkdir /usr/bin/mnt: permission denied\\\u0026#34;}\\n\u0026#34; code=500 # ... ジョブの出し方にパスの制限がある Blender から Flamenco の拡張機能を使って Job を出すときに、レンダリング結果の出力先を Manager 側の PC のローカルにしてしまうと、魔法のようにパスが解決されるわけではなく、Worker 側の PC にそのような場所は存在しないとして Blender がレンダリングする前に即座にクラッシュしてしまうことがわかった。\nBlender からジョブを出すときも、Manager 側の PC と　Worker 側の PC が両方同じパスでアクセスできるネットワークドライブ上のフォルダを、レンダリング結果の出力先として指定しなければならないようである。以下は問題発生時の Worker PC 側のログである。\n./flamenco-worker # 2026-03-26T22:44:59+09:00 INF starting Flamenco Worker arch=amd64 git=51a41a19 os=linux osDetail=\u0026#34;Arch Linux (6.19.8-arch1-1)\u0026#34; pid=1198634 releaseCycle=release version=3.8.2 # 2026-03-26T22:44:59+09:00 INF will load configuration from these paths credentials=/home/UserNameWorkerSide/.local/share/flamenco/flamenco-worker-credentials.yaml main=/home/UserNameWorkerSide/scripts/flamenco/flamenco-worker.yaml # 2026-03-26T22:45:00+09:00 INF Blender found on this system, it will be used unless the Flamenco Manager configuration specifies a different path. path=/usr/bin/blender version=\u0026#34;Blender 5.0.1\u0026#34; # 2026-03-26T22:45:00+09:00 INF FFmpeg found on this system path=/usr/bin/ffmpeg version=n8.1 # 2026-03-26T22:45:00+09:00 INF executables will be run with OOM score adjustment oom_score_adjust=500 # 2026-03-26T22:45:00+09:00 INF loaded configuration config={\u0026#34;manager_url\u0026#34;:\u0026#34;http://192.168.1.xx:58080/\u0026#34;,\u0026#34;oom_score_adjust\u0026#34;:500,\u0026#34;restart_exit_code\u0026#34;:47,\u0026#34;task_types\u0026#34;:[\u0026#34;blender\u0026#34;,\u0026#34;ffmpeg\u0026#34;,\u0026#34;file-management\u0026#34;,\u0026#34;misc\u0026#34;],\u0026#34;worker_name\u0026#34;:\u0026#34;\u0026#34;} # 2026-03-26T22:45:00+09:00 INF loaded credentials filename=/home/UserNameWorkerSide/.local/share/flamenco/flamenco-worker-credentials.yaml # 2026-03-26T22:45:00+09:00 INF signing on at Manager manager=http://192.168.1.xx:58080/ name=dataSrv softwareVersion=3.8.2 taskTypes=[\u0026#34;blender\u0026#34;,\u0026#34;ffmpeg\u0026#34;,\u0026#34;file-management\u0026#34;,\u0026#34;misc\u0026#34;] # 2026-03-26T22:45:00+09:00 INF manager accepted sign-on startup_state=awake # 2026-03-26T22:45:00+09:00 INF opening database dsn=/home/UserNameWorkerSide/.local/share/flamenco/flamenco-worker.sqlite # 2026-03-26T22:45:00+09:00 INF state change curState=starting newState=awake # 2026-03-26T22:47:27+09:00 INF obtained task task={\u0026#34;commands\u0026#34;:[{\u0026#34;name\u0026#34;:\u0026#34;blender-render\u0026#34;,\u0026#34;parameters\u0026#34;:{\u0026#34;args\u0026#34;:[\u0026#34;--scene\u0026#34;,\u0026#34;Scene\u0026#34;,\u0026#34;--render-output\u0026#34;,\u0026#34;/home/UserName/Documents/free/aaa/2026-03-26_224801/######\u0026#34;,\u0026#34;--render-format\u0026#34;,\u0026#34;PNG\u0026#34;,\u0026#34;--render-frame\u0026#34;,\u0026#34;1\u0026#34;],\u0026#34;argsBefore\u0026#34;:[],\u0026#34;blendfile\u0026#34;:\u0026#34;/mnt/FlamencoRenderPlace/blenderRender/jobs/aaa/untitled1.flamenco.blend\u0026#34;,\u0026#34;exe\u0026#34;:\u0026#34;blender\u0026#34;,\u0026#34;exeArgs\u0026#34;:\u0026#34;-b -y\u0026#34;},\u0026#34;total_step_count\u0026#34;:1}],\u0026#34;job\u0026#34;:\u0026#34;b4da0a35-86a8-46fe-b946-888c7085412f\u0026#34;,\u0026#34;job_priority\u0026#34;:50,\u0026#34;job_type\u0026#34;:\u0026#34;simple-blender-render\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;render-1\u0026#34;,\u0026#34;priority\u0026#34;:50,\u0026#34;status\u0026#34;:\u0026#34;active\u0026#34;,\u0026#34;steps_completed\u0026#34;:0,\u0026#34;steps_total\u0026#34;:1,\u0026#34;task_type\u0026#34;:\u0026#34;blender\u0026#34;,\u0026#34;uuid\u0026#34;:\u0026#34;66d34b02-4498-4f7c-b8d2-c5dcf30be050\u0026#34;} # 2026-03-26T22:47:27+09:00 INF starting task job=b4da0a35-86a8-46fe-b946-888c7085412f task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 taskType=blender # 2026-03-26T22:47:27+09:00 INF running Flamenco command command=blender-render parameters={\u0026#34;args\u0026#34;:[\u0026#34;--scene\u0026#34;,\u0026#34;Scene\u0026#34;,\u0026#34;--render-output\u0026#34;,\u0026#34;/home/UserName/Documents/free/aaa/2026-03-26_224801/######\u0026#34;,\u0026#34;--render-format\u0026#34;,\u0026#34;PNG\u0026#34;,\u0026#34;--render-frame\u0026#34;,\u0026#34;1\u0026#34;],\u0026#34;argsBefore\u0026#34;:[],\u0026#34;blendfile\u0026#34;:\u0026#34;/mnt/FlamencoRenderPlace/blenderRender/jobs/aaa/untitled1.flamenco.blend\u0026#34;,\u0026#34;exe\u0026#34;:\u0026#34;blender\u0026#34;,\u0026#34;exeArgs\u0026#34;:\u0026#34;-b -y\u0026#34;} task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:27+09:00 INF going to run: blender -b -y /mnt/FlamencoRenderPlace/blenderRender/jobs/aaa/untitled1.flamenco.blend --scene Scene --render-output \u0026#39;/home/UserName/Documents/free/aaa/2026-03-26_224801/######\u0026#39; --render-format PNG --render-frame 1 command=blender-render task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:28+09:00 INF blender-render: frame rendered command=blender-render duration=00:00.87 task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:29+09:00 ERR command exited abnormally command=blender-render exitCode=1 pid=1201254 task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:29+09:00 ERR command exited abnormally command=blender-render exitCode=1 pid=1201254 task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:29+09:00 ERR command exited abnormally error=\u0026#34;command exited abnormally with code 1\u0026#34; command=blender-render exitCode=1 task=66d34b02-4498-4f7c-b8d2-c5dcf30be050 # 2026-03-26T22:47:29+09:00 WRN error executing task error=\u0026#34;command exited abnormally with code 1\u0026#34; task={\u0026#34;commands\u0026#34;:[{\u0026#34;name\u0026#34;:\u0026#34;blender-render\u0026#34;,\u0026#34;parameters\u0026#34;:{\u0026#34;args\u0026#34;:[\u0026#34;--scene\u0026#34;,\u0026#34;Scene\u0026#34;,\u0026#34;--render-output\u0026#34;,\u0026#34;/home/UserName/Documents/free/aaa/2026-03-26_224801/######\u0026#34;,\u0026#34;--render-format\u0026#34;,\u0026#34;PNG\u0026#34;,\u0026#34;--render-frame\u0026#34;,\u0026#34;1\u0026#34;],\u0026#34;argsBefore\u0026#34;:[],\u0026#34;blendfile\u0026#34;:\u0026#34;/mnt/FlamencoRenderPlace/blenderRender/jobs/aaa/untitled1.flamenco.blend\u0026#34;,\u0026#34;exe\u0026#34;:\u0026#34;blender\u0026#34;,\u0026#34;exeArgs\u0026#34;:\u0026#34;-b -y\u0026#34;},\u0026#34;total_step_count\u0026#34;:1}],\u0026#34;job\u0026#34;:\u0026#34;b4da0a35-86a8-46fe-b946-888c7085412f\u0026#34;,\u0026#34;job_priority\u0026#34;:50,\u0026#34;job_type\u0026#34;:\u0026#34;simple-blender-render\u0026#34;,\u0026#34;name\u0026#34;:\u0026#34;render-1\u0026#34;,\u0026#34;priority\u0026#34;:50,\u0026#34;status\u0026#34;:\u0026#34;active\u0026#34;,\u0026#34;steps_completed\u0026#34;:0,\u0026#34;steps_total\u0026#34;:1,\u0026#34;task_type\u0026#34;:\u0026#34;blender\u0026#34;,\u0026#34;uuid\u0026#34;:\u0026#34;66d34b02-4498-4f7c-b8d2-c5dcf30be050\u0026#34;} blender バイナリパスの指定 worker と manager のポート番号の指定 パス指定がシビア 共有ファイルのパスを合わせる必要がある GNOME の SFTP のパスは指定できない 関係ありそうな記事 Blender 5.x.x において、GTX 1080Ti(Pascal) を Cycles レンダリングで使えるようにしたい SSHFS を Systemd から BASH スクリプトを実行することでマウントしたい 使った画像素材など File:Intel Arc logo (black).svg - Wikimedia Commons Intel Corporation, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Intel_Arc_logo_(black).svg (2026年3月22日) File:Nvidia logo.svg - Wikipedia\nhttps://sco.wikipedia.org/wiki/File:Nvidia_logo.svg#metadata (2026年3月22日) File:AMD Radeon logo.svg - Wikimedia Commons AMD, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:AMD_Radeon_logo.svg (2026年3月22日) File:Blender logo no text.svg - Wikimedia Commons ™/®Blender Foundation, Public domain, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Blender_logo_no_text.svg (2026年3月22日) File:Firewall Symbol.svg - Wikimedia Commons Michel Bakni, CC BY-SA 4.0 https://creativecommons.org/licenses/by-sa/4.0, via Wikimedia Commons\nhttps://commons.wikimedia.org/wiki/File:Firewall_Symbol.svg (2026年3月22日) Windows 7 のアイコン ルータのアイコン PCのアイコン ノートPCのアイコン インターネットのアイコン ネットワーク共有のアイコン 参考にしたサイトとか Create a Blender Render Farm - Flamenco Setup Tutorial - YouTube\nhttps://www.youtube.com/watch?v=LLcBUIVN9RI (2026年3月22日) Flamenco\nhttps://flamenco.blender.org/ (2026年3月22日) AUR (en) - flamenco\nhttps://aur.archlinux.org/packages/flamenco-manager (2026年3月22日) Google Gemini\nhttps://gemini.google.com/app (2026年3月22日) Arch Linux - sshfs 3.7.5-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/sshfs/ (2026年3月22日) SSHFS - ArchWiki\nhttps://wiki.archlinux.org/title/SSHFS (2026年3月22日) Blender - ArchWiki\nhttps://wiki.archlinux.org/title/Blender (2026年3月22日) state-of-the-art/BlendNet: Make your Blender distributed!\nhttps://github.com/state-of-the-art/BlendNet (2026年3月22日) Arch Linux - blender 17:5.0.1-9 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/blender/ (2026年3月22日) AUR (en) - flamenco\nhttps://aur.archlinux.org/packages/flamenco-worker (2026年3月22日) TCP/UDPポート番号一覧\nhttps://www.infraexpert.com/study/tea5.htm (2026年3月26日) Flamenco error, need help : r/blender\nhttps://www.reddit.com/r/blender/comments/151k8pe/flamenco_error_need_help/ (2026年3月26日) #107137 - Python: Importing zstandard fails - blender - Blender Projects\nhttps://projects.blender.org/blender/blender/issues/107137 (2026年3月26日) AUR (en) - python-zstd\nhttps://aur.archlinux.org/packages/python-zstd (2026年3月26日) ","permalink":"https://www.nyanmo.info/posts/blender/flamenco/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 \u003ca href=\"https://gemini.google.com/app\"\u003eGemini Fast 3\u003c/a\u003e を使っていると、Blender において分散コンピューティングみたいなレンダリングの仕方ができることが分かり、気になった。それで、最初は \u003ca href=\"https://gemini.google.com/app\"\u003eGemini Fast 3\u003c/a\u003e が提案してきて、\u003ca href=\"https://wiki.archlinux.org/title/Blender\"\u003eBlender - ArchWiki\u003c/a\u003e にも掲載されている、\u003ca href=\"https://github.com/state-of-the-art/BlendNet\"\u003eBlendNet\u003c/a\u003eを試そうと思った。\u003c/p\u003e\n\u003cp\u003e　しかし、\u003ca href=\"https://github.com/state-of-the-art/BlendNet\"\u003eBlendNet\u003c/a\u003e のリポジトリを見てみると、実際のところは Blender 2.x.x の古い Blender にしか対応してなさそうな感じであった。私が使っている Blender のバージョンは 5.x.x 以降であったことから、別の物がないか \u003ca href=\"https://gemini.google.com/app\"\u003eGemini Fast 3\u003c/a\u003e に提案させてみると、Blender 公式の \u003ca href=\"https://flamenco.blender.org/\"\u003eFlamenco\u003c/a\u003e が出てきたため試した。\u003c/p\u003e\n\u003cp\u003e　そして、とりあえず動くようになるところまで、設定して確かめることができたため、そのことについて記録したい。まだ完全ではなく、途中でレンダリングに失敗したりと、成果物を得られている状態ではない。現状では Flamenco Manager と Flamenco Worker が実際に疎通を取り、Manager 側のクライアントの Blender からジョブを投げると、Worker 側がレンダリングを開始し負荷がかかるところまで確認した。\u003c/p\u003e\n\u003ch2 id=\"細かい説明序章\"\u003e細かい説明(序章)\u003c/h2\u003e\n\u003ch3 id=\"全体的な-flamenco-運用イメージ\"\u003e全体的な Flamenco 運用イメージ\u003c/h3\u003e\n\u003cp\u003e　以下に構築する環境のイメージを示す。今回はファイル共有サーバと Worker となる PC は物理的に1つに全部がまとまっている事を想定しているが、以下の画像ではわかりやすさのために、ファイル共有サーバやレンダリングを行う Worker farm の PC は物理的に分けている前提で表現している。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flamenco/explain2.png#center\"\n         alt=\"全体的なイメージ\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"前提について\"\u003e前提について\u003c/h3\u003e\n\u003cp\u003e　以下の点については、すでに設定されているものまたは前提として取り扱う。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eManager 側と Worker 側の間の設定\n\u003cul\u003e\n\u003cli\u003eLAN で物理的に同じネットワークに繋がっているか、VPNによって実質的に同じネットワークに繋がっている。\u003c/li\u003e\n\u003cli\u003eSSH の設定が済ませてあり、LAN で物理的に同じネットワークに繋がっているときに疎通が取れる。\u003c/li\u003e\n\u003cli\u003eping によって物理的に同じネットワークに繋がっているときに疎通が取れる。\u003c/li\u003e\n\u003cli\u003eWorker 側は GNOME RDP の設定が済ませてあり、Remmina クライアントにより LAN で物理的に同じネットワークに繋がっているときに疎通が取れる。\u003c/li\u003e\n\u003cli\u003eSFTP によるファイル共有が可能な状態になっている。\u003c/li\u003e\n\u003cli\u003eどちらも Linux 環境がセットアップされてあり、インターネットへの接続が確認できている。\u003c/li\u003e\n\u003cli\u003efirewalld をファイアウォールとして使っている。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eVPN での接続がある場合について\n\u003cul\u003e\n\u003cli\u003eSMB ではなく SFTP によってファイルのやり取りを行う。\u003c/li\u003e\n\u003cli\u003eMTU サイズが十分小さく設定されており、ネットワーク障害が発生しないように設定されている。(MTUサイズ1000にするなど)\u003c/li\u003e\n\u003cli\u003e高遅延を前提とする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003eManager 側の視点から設定作業などを行い、Flamenco Manager と Blender を立ち上げた状態で作業する。\u003c/li\u003e\n\u003cli\u003eManager 側と Worker 側は VPN によって遠隔地で通信を行う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"単語の解釈\"\u003e単語の解釈\u003c/h3\u003e\n\u003ch4 id=\"worker\"\u003eWorker\u003c/h4\u003e\n\u003cp\u003e　Flamenco において実際にレンダリング処理をする端末を、\u003ca href=\"https://flamenco.blender.org/\"\u003eFlamenco\u003c/a\u003e公式ドキュメントなどを見た結果、\u003ccode\u003eWorker\u003c/code\u003eと呼ぶと私は現時点(2026/3/22)では解釈している。\u003c/p\u003e","title":"Blender に Flamenco を導入して分散コンピューティング？を試す"},{"content":"この記事を作った動機 普段常駐させているサーバがあり GPU を載せているが、それを使って Blender でレンダリングをしたいとか、RDP 経由で直接その環境を使いたいとなったときに問題が起こっていた。\n具体的には、RDP 経由で Blender 自体のウィンドウやその他アプリにおいてもドラックアンドドロップなどはでき、Google Chrome においてもタブを掴んで動かしたりすることはできるが、Blender 内の 3D Viewport において、視点を回転させようとしたり、オブジェクトを G キーを押してマウスで任意の場所に移動させたりすると、ちょっとだけ動くだけで、ほとんど動かせないということがあった。\n今回はその背景や機能することが確認できた対処について記録したい。\n対処方法 Continuous Grabを無効化する。(Edit -\u0026gt; Preference -\u0026gt; Input -\u0026gt; Mouse -\u0026gt; Continuous Grab) 問題の様子と解決の様子 背景情報 問題としては、Continuous Grab という項目が、FPSゲームとかであるように、マウスカーソルを画面中央などにロックして、一定フレームごとのカーソルの移動量を計測することで、視点を移動させたりする仕組みが、Blender の Continuous Grab の機能で採用されていて、RDP 環境下ではうまく動作しないのではないかということは、Google Gemini 3 Fastに問題について投げてみると理屈として出てきたが、実際のところ技術的詳細がどうなっているのかは私はわかっていない。\n通常のウィンドウ操作や、Blender の UI 自体の操作ではこの問題は起こらず、ドラックして動かしたりすることができており、それについては、画面の絶対座標から導き出されるカーソルの位置を利用してカーソルの移動量が計算されていて、カーソルがロックされていないので問題が起こらないということも、Google Gemini 3 Fastに問題について投げてみると理屈として出てきたが、実際のところ技術的詳細がどうなっているのかは私はわかっていない。\n現状わかっていることとしては、Continuous Grabの機能を無効化しなければ、Blender において、3D Viewport が RDP 経由ではまともに動かせないということであった。今回の問題は直接 RDP を経由せずに操作した場合には起こらないことが確認できている。Windows 11 24H2 の RDP クライアントでも、Liunx 環境の Remmina RDP クライアントにおいても、Continuous Grab有効時において、今回の問題が再現することも確認している。\nContinuous Grab の機能については調べてみたり、実際に有効時と無効時を比べてみたりしてわかったことは、有効時にはカーソルが画面外に出てももう一方の方からカーソルがまた出現して画面領域にとらわれずにシーンを動かしたりスライダーを動かしたりできるということがわかった。無効時には画面の端にぶつかるとそれ以上オブジェクトを動かしたりはできず、作業領域が制限される状態になることがわかった。\n参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年3月20日) Input(入力) — Blender Manual\nhttps://docs.blender.org/manual/ja/2.93/editors/preferences/input.html (2026年3月20日) Blender の便利なユーザー設定（2.83以降）\nhttps://dskjal.com/blender/userpreference-28 (2026年3月20日) ","permalink":"https://www.nyanmo.info/posts/blender/blenderonwaylandviardpcauseissue/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　普段常駐させているサーバがあり GPU を載せているが、それを使って Blender でレンダリングをしたいとか、RDP 経由で直接その環境を使いたいとなったときに問題が起こっていた。\u003c/p\u003e\n\u003cp\u003e　具体的には、RDP 経由で Blender 自体のウィンドウやその他アプリにおいてもドラックアンドドロップなどはでき、Google Chrome においてもタブを掴んで動かしたりすることはできるが、Blender 内の 3D Viewport において、視点を回転させようとしたり、オブジェクトを G キーを押してマウスで任意の場所に移動させたりすると、ちょっとだけ動くだけで、ほとんど動かせないということがあった。\u003c/p\u003e\n\u003cp\u003e　今回はその背景や機能することが確認できた対処について記録したい。\u003c/p\u003e\n\u003ch2 id=\"対処方法\"\u003e対処方法\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eContinuous Grab\u003c/code\u003eを無効化する。(Edit -\u0026gt; Preference -\u0026gt; Input -\u0026gt; Mouse -\u0026gt; Continuous Grab)\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/blenderOnWaylandViaRDPcauseIssue/openSetting.png#center\"\n         alt=\"Continuous Grab を無効化する\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/blenderOnWaylandViaRDPcauseIssue/ContinuousGrabDisable0.png#center\"\n         alt=\"Continuous Grab を無効化する\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/blenderOnWaylandViaRDPcauseIssue/ContinuousGrabDisable1.png#center\"\n         alt=\"Continuous Grab を無効化する\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"問題の様子と解決の様子\"\u003e問題の様子と解決の様子\u003c/h2\u003e\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/blender/blenderOnWaylandViaRDPcauseIssue/blenderOnWaylandViaRDPcauseIssue.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\u003ch2 id=\"背景情報\"\u003e背景情報\u003c/h2\u003e\n\u003cp\u003e　問題としては、\u003ccode\u003eContinuous Grab\u003c/code\u003e という項目が、FPSゲームとかであるように、マウスカーソルを画面中央などにロックして、一定フレームごとのカーソルの移動量を計測することで、視点を移動させたりする仕組みが、Blender の \u003ccode\u003eContinuous Grab\u003c/code\u003e の機能で採用されていて、RDP 環境下ではうまく動作しないのではないかということは、\u003ca href=\"https://gemini.google.com/app\"\u003eGoogle Gemini 3 Fast\u003c/a\u003eに問題について投げてみると理屈として出てきたが、実際のところ技術的詳細がどうなっているのかは私はわかっていない。\u003c/p\u003e\n\u003cp\u003e　通常のウィンドウ操作や、Blender の UI 自体の操作ではこの問題は起こらず、ドラックして動かしたりすることができており、それについては、画面の絶対座標から導き出されるカーソルの位置を利用してカーソルの移動量が計算されていて、カーソルがロックされていないので問題が起こらないということも、\u003ca href=\"https://gemini.google.com/app\"\u003eGoogle Gemini 3 Fast\u003c/a\u003eに問題について投げてみると理屈として出てきたが、実際のところ技術的詳細がどうなっているのかは私はわかっていない。\u003c/p\u003e\n\u003cp\u003e　現状わかっていることとしては、\u003ccode\u003eContinuous Grab\u003c/code\u003eの機能を無効化しなければ、Blender において、3D Viewport が RDP 経由ではまともに動かせないということであった。今回の問題は直接 RDP を経由せずに操作した場合には起こらないことが確認できている。Windows 11 24H2 の RDP クライアントでも、Liunx 環境の Remmina RDP クライアントにおいても、\u003ccode\u003eContinuous Grab\u003c/code\u003e有効時において、今回の問題が再現することも確認している。\u003c/p\u003e","title":"Blender で RDP において、カメラやオブジェクトを動かせない"},{"content":"この記事を作った動機 dhcpcd を使って管理している PC があるが、最近その挙動について何度も DHCP して IP を取得しては、新しいものを取得するという動作をして、他の PC が接続できなくなるほど、IP プールを勝手に枯渇させるということがあった。\n特定インターフェースについて、そもそも DHCP とかで勝手に設定しないように指定したつもりであったが、機能していないことが分かった。動くまで調べ、機能しているように見えるところまで持ってきたのでそれについて記録する。ただしばらく動かしてみないと実際機能しているかわからないので、すぐわかる範囲での暫定的な記録となる。\n設定方法 /etc/dhcpcd.confの最上位に、denyinterfaces [DHCPしないインターフェース名1] [DHCPしないインターフェース名2] ...というように記述する。基本的に DHCP したり静的に IP などを取得し設定するインターフェースの設定より上に書かないといけないっぽいことが今回調べて分かった。denyinterface getting ignored - Raspberry Pi Forums に書かれているように、dhcpcd は設定ファイル内の順次自体が大事なように見受けられる。設定例はブログに乗せるために...として省略している部分がある。\n機能しているっぽい設定例 # cat /etc/dhcpcd.conf # A sample configuration for dhcpcd. # See dhcpcd.conf(5) for details. denyinterfaces eno2 enp0s20u11 ... interface eno1 static ip_address=192.168.1.x static routers=192.168.1.x static domain_name_servers=8.8.8.8 機能していないっぽい設定例 # cat /etc/dhcpcd.conf # A sample configuration for dhcpcd. # See dhcpcd.conf(5) for details. ... interface eno1 static ip_address=192.168.1.x static routers=192.168.1.x static domain_name_servers=8.8.8.8 ... denyinterfaces eno2 enp0s20u11 問題となっているPCなどの構成情報 関係のありそうな構成情報の列挙 Arch Linux Firewalld dhcpcd nftables SoftEther VPN 今回登場するPCの説明 ルータPC 家庭用ルータに置き換えて、nftables と kea によってルータ化した PC である。基本的な機能性は家庭用ルータと変わらないように意識し、USB NIC と内蔵 NIC の2つからなる。今回説明に出てくる、具体的なインターフェース名に紐づく物理 NIC とは関係ない。\nサーバPC SoftEther VPN Server などが乗っていて、他のファイル共有なども担当するサーバである。家庭用ルータを運用する名残で VPN サーバも動いている。今回物理 NIC について名前を上げているインターフェース名については、この PC に紐づくものである。\nVPNクライアントとしてのPC VPN 接続を実際に行い、遠隔のローカルブリッジ先の LAN にアクセスするクライアントのことである。実際に外出先でデザリングしたり、ネットワークに何かしら繋いで、VPN 通信が正常に行えるかテストするクライアントである。\nLAN内のPC VPN 接続先にある LAN 内に物理的に直接接続されている PC のことで、\u0026ldquo;サーバ\u0026quot;PC以外を意味する。\nNIC 構成 今回話題にする PC の NIC 構成は以下のようになっている。\neno1 通常のファイル共有など、様々なアプリケーション用にサービスを LAN 内において提供することが目的の物理内蔵NICである。\neno2 Linux 環境において、SoftEther VPN Server のソフトウェア制約により、一つの物理 NIC を VPN のブリッジ用に割り当てると、サーバ自身にアクセスできなくなるという問題があるために、ローカルブリッジ専用に割り当てている2つ目の物理内蔵NICである。eno1 とは物理的に独立して存在している。\nenp0s20u11 ルータ PC 配置前において、SoftEther VPN Server のローカルブリッジ用に専用に割り当てていた NIC である。現在はそれは物理的に LAN ケーブルを切断しており、PC 内蔵 NIC を使うようにしている。PC 内蔵 NIC では、当時の調査では何かしら通信障害がハードウェアや低レベルにおけるソフトウェアの実装に問題があるとして、2年以上前にはそれを使うことを諦めていたと記憶している。しかし、何が問題でできなかったか、記録がなく細かいことは覚えていなかったため、実際に再び PC 内蔵 NIC をローカルブリッジとしての利用を試している。\n構成に対する説明 基本的に、eno1 に対して決まった IP を割り当てるようにしている。eno2 や enp0s20u11 については、denyinterfaceを設定していたが、設定が正しくないのか、2年以上の運用において勝手に IP が割り当てられていることがip aコマンドにより確認できた。しかし、家庭用ルータを使っている合間は、たまに eno1 に割り当てられた IP に対してアクセスできなくなるなど、半年でなぜそうなったのかもわからない再現が難しい状況として理由が分からずにネットワーク障害になる以上には、支障は起こらなかったため放置していた。\nしかし、今回専用の業務用スイッチと Linux PC を新規にルータを組み合わせて構成し、kea や nftables を使ったルータとして実際に導入したところ、家庭用ルータが強引に補正していた魔法が解けたのか問題が起こった。IP プールが枯渇して他の PC がまともに接続できなくなったり、ARPテーブルを撹拌してルーティングがろくに機能しなくなり、VPN 接続などにおいて数秒ごとに接続が切れるなど、障害の元となっていそうなことが今回分かっている。\nVPN の件については、NAT超えをしていてカプセル化などの過程でパケットサイズが膨らみやすく元々不安定だったことがあるが、Linux VPN クライアントにおいて、MTUサイズを1000にしても問題が今回は起こっており、簡単には解決しない問題であった。ルータ PC の Firewalld の DROP ログを見ると、VPN 接続が定期的に途切れる件については、Firewalld が SoftEther の接続維持のパケットを NAT(マスカレード) の内側から外側に流れる場合であっても、不正なパケットとしてその内容を精査して DROP してしまうことが分かった。\nセキュリティの懸念はあるが Firewalld が DROP してしまう件については、現状では nftables を直接使ってマスカレードを構成し、Firewalld は使わないようにすることにまでなった。それによって VPN 接続が定期的に頻繁に短期間で途切れる症状は軽減されたように見受けられたが、Windows 環境では特に安定しなかったり、HTTP や SMB 通信などがあると、通信を行った VPN クライアントやそれ以外の同じ接続先の VPN クライアントも巻き添えを食らって切断されては再接続というような不定期に接続が切れる挙動となった。このときには、ルータ PC 自身に対して VPN を介した SSH 接続や RDP は行えており、単にスペック不足とか、使っている NIC​ がゴミとかいうことではなさそうだということは分かっていた。しかし、VPN を介さない場合にアクセスできる VPN 接続先である LAN 内のサーバなどに対して、HTTP 通信ができないなど、そういう操作をすると決まって VPN 接続が途切れてしまったり、周囲の VPN クライアントに影響を及ぼすなど、問題がまだ完全には消えていない状況でった。\nそこで今回ブログにした内容として関係ありそうなこととして、dhcpcd 自体の暴走や、何かしらほかの意図しない挙動との競合が考えられ、IP プールの枯渇や、MAC アドレスが撹拌されてルーティングが破綻しているなどの問題が考えられた。ARP テーブルが撹拌されて、ルーティングが破綻する理由にも今回の IP プールを枯渇させる dhcpcd の挙動が関わっていると考えられた。IP プールが枯渇したあとに IP が正常に割り当てられていない状況下において、何度も特定 IP に対してアクセスを強引に繰り返そうとしているうちに、無理やりルートを見つけようとして全体的にクライアントもどこかしこも ARP テーブルが壊れてしまったという仮説もなんとなく思っている。\nログ例 機能してなさそうなときの例 eno2: soliciting an IPv6 routerやeno2: leased 192.168.1.52 for 6058 secondsなどと表示され、denyinterfacesしているのに機能していないことが確認できる。\njournalctl -u dhcpcd # 3月 02 20:57:30 HOSTNAME systemd[1]: Started DHCP/ IPv4LL/ IPv6RA/ DHCPv6 client on all interfaces. # 3月 02 20:57:31 HOSTNAME dhcpcd[994]: dhcpcd-10.3.0 starting # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: dev: loaded udev # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: DUID 00:01:00:01:2d:3d:8c:d0:xx:xx:xx:xx:xx:xx # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: no interfaces have a carrier # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: eno1: waiting for carrier # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: eno2: waiting for carrier # 3月 02 20:57:31 HOSTNAME dhcpcd[1041]: enp0s20u11: waiting for carrier # 3月 02 20:57:33 HOSTNAME dhcpcd[1041]: enp0s20u11: carrier acquired # 3月 02 20:57:33 HOSTNAME dhcpcd[1041]: enp0s20u11: IAID dd:dd:dd:dd # 3月 02 20:57:34 HOSTNAME dhcpcd[1041]: enp0s20u11: adding address fe80::9afb:279f:96dd:50a8 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno1: carrier acquired # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno1: IAID cc:cc:cc:cc # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno1: adding address fe80::b4c5:7141:29f1:9580 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno1: probing address 192.168.1.x/24 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: enp0s20u11: rebinding lease of 192.168.1.53 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: enp0s20u11: probing address 192.168.1.53/24 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno2: carrier acquired # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno2: IAID xx:xx:xx:xx # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno2: adding address fe80::9a13:b4b2:da2f:e80c # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno2: rebinding lease of 192.168.1.52 # 3月 02 20:57:35 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.52/24 # 3月 02 20:57:36 HOSTNAME dhcpcd[1041]: enp0s20u11: soliciting an IPv6 router # 3月 02 20:57:37 HOSTNAME dhcpcd[1041]: eno2: soliciting an IPv6 router # 3月 02 20:57:37 HOSTNAME dhcpcd[1041]: eno1: soliciting an IPv6 router # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno1: using static address 192.168.1.x/24 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno1: adding route to 192.168.1.0/24 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno1: adding default route via 192.168.1.1 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: enp0s20u11: leased 192.168.1.53 for 6127 seconds # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: enp0s20u11: adding route to 192.168.1.0/24 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: enp0s20u11: adding default route via 192.168.1.1 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.52 for 6058 seconds # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 20:57:40 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 20:57:48 HOSTNAME dhcpcd[1041]: enp0s20u11: no IPv6 Routers available # 3月 02 20:57:49 HOSTNAME dhcpcd[1041]: eno2: no IPv6 Routers available # ... dhcpcdが暴走して IP プールを食いつぶす例 原因は分かっていないが、192.168.1.68、192.168.1.69、192.168.1.70\u0026hellip;と規則性のある形で徐々に eno2 について何度も DHCP を繰り返していて、Kea で立てた DHCP の IP プールを食いつぶして他の端末が接続できない状態を作ってしまう。SoftEther の VPN Server のローカルブリッジ先ということ以外であまり心当たりがなく、NetworkManager も無効化しており今のところなんでこんな挙動になるのか理解できていない。\nちなみに、denyinterfacesをinterface設定より上に書いて、とりあえず eno2について DHCP も何も設定しないように指示することで、eno2 について何もしなくなり以下のような挙動も見られなくなった。このことから、1つ仮説を上げるならば、SoftEther VPN Server のローカルブリッチに指定されたインターフェースに対して、IP などが割り当てられている事自体が問題であるとして、強制的に SoftEther 側のプロセスが IP を eno2 から剥奪しては、dhcpcd がそれを検出して IP を強引に割り当てようとしていたのかなと思うところがある。\nただ以下のログを見ると、xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.68とあり、その後に eno2 の IP 割り当てに失敗したとして再取得を試みていることがわかる。xx:xx:xx:xx:xx:xxは eno1 についての MAC アドレスで、ブログに書くときなセキュリティの観点から一応伏せ字にしているが、そこから考えられることとしては、eno2 について DHCP するとブロードキャストされた DHCP の要求が eno1 で何らかの形で入り込んで、eno2 にうまくルーティングできてないのかな？というところがある。\nまた、現在のネットワーク構成では、ローカル LAN については専用のスイッチを設けており、そこを通じて通信を行っているため、家庭用ルータ内臓のスイッチを使うときと違って、ちょっとした不整合が問題になる可能性があることが考えれた。今まで家庭用ルータが仕事していた部分において置き換えたことで、根本的に解決されていない問題が表面化したとも見受けられるところがある。今回denyinterfacesが機能して問題が抑制されていていると仮定しても、根本的には単にスイッチを置いていて、細かい管理はしておらず、せいぜいスイッチにルータ化した PC にマスカレードやら以外に、kea で DHCP サーバ立てているくらいの構成では、別の形で問題が発現する可能性を否定できない。\njournalctl -u dhcpcd #... # 3月 02 21:20:10 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.68 # 3月 02 21:20:15 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.68 # 3月 02 21:20:15 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.68 # 3月 02 21:20:15 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:20:15 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:20:17 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:20:17 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.69 from 192.168.1.1 # 3月 02 21:20:17 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.69/24 # 3月 02 21:20:22 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.69 for 7200 seconds # 3月 02 21:20:22 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:20:22 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:22:12 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.69 # 3月 02 21:22:17 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.69 # 3月 02 21:22:17 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.69 # 3月 02 21:22:17 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:22:17 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:22:18 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:22:18 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.70 from 192.168.1.1 # 3月 02 21:22:18 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.70/24 # 3月 02 21:22:23 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.70 for 7200 seconds # 3月 02 21:22:23 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:22:23 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:24:09 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.70 # 3月 02 21:24:14 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.70 # 3月 02 21:24:14 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.70 # 3月 02 21:24:14 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:24:14 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:24:16 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:24:16 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.71 from 192.168.1.1 # 3月 02 21:24:16 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.71/24 # 3月 02 21:24:21 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.71 for 7200 seconds # 3月 02 21:24:21 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:24:21 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:26:11 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.71 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.71 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.71 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.72 from 192.168.1.1 # 3月 02 21:26:17 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.72/24 # 3月 02 21:26:22 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.72 for 7200 seconds # 3月 02 21:26:22 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:26:22 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:28:09 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.72 # 3月 02 21:28:19 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.72 # 3月 02 21:28:29 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.72 # 3月 02 21:28:34 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.72 # 3月 02 21:28:34 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.72 # 3月 02 21:28:34 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:28:34 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:28:36 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:28:36 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.73 from 192.168.1.1 # 3月 02 21:28:36 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.73/24 # 3月 02 21:28:41 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.73 for 7200 seconds # 3月 02 21:28:41 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:28:41 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:30:11 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.73 # 3月 02 21:30:21 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.73 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.73 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.73 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.74 from 192.168.1.1 # 3月 02 21:30:26 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.74/24 # 3月 02 21:30:32 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.74 for 7200 seconds # 3月 02 21:30:32 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:30:32 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:32:08 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.74 # 3月 02 21:32:18 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.74 # 3月 02 21:32:23 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.74 # 3月 02 21:32:23 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.74 # 3月 02 21:32:23 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:32:23 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:32:25 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:32:25 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.75 from 192.168.1.1 # 3月 02 21:32:25 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.75/24 # 3月 02 21:32:30 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.75 for 7200 seconds # 3月 02 21:32:30 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:32:30 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:34:11 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.75 # 3月 02 21:34:16 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.75 # 3月 02 21:34:16 HOSTNAME dhcpcd[1041]: eno2: 10 second defence failed for 192.168.1.75 # 3月 02 21:34:16 HOSTNAME dhcpcd[1041]: eno2: deleting route to 192.168.1.0/24 # 3月 02 21:34:16 HOSTNAME dhcpcd[1041]: eno2: deleting default route via 192.168.1.1 # 3月 02 21:34:17 HOSTNAME dhcpcd[1041]: eno2: soliciting a DHCP lease # 3月 02 21:34:17 HOSTNAME dhcpcd[1041]: eno2: offered 192.168.1.76 from 192.168.1.1 # 3月 02 21:34:17 HOSTNAME dhcpcd[1041]: eno2: probing address 192.168.1.76/24 # 3月 02 21:34:22 HOSTNAME dhcpcd[1041]: eno2: leased 192.168.1.76 for 7200 seconds # 3月 02 21:34:22 HOSTNAME dhcpcd[1041]: eno2: adding route to 192.168.1.0/24 # 3月 02 21:34:22 HOSTNAME dhcpcd[1041]: eno2: adding default route via 192.168.1.1 # 3月 02 21:36:07 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.76 # 3月 02 21:36:13 HOSTNAME dhcpcd[1041]: eno2: xx:xx:xx:xx:xx:xx(xx:xx:xx:xx:xx:xx) claims 192.168.1.76 #... 機能していそうなときの例 機能していそうなときは以下の情報以上にjournalctlの出力に出てこない。eno1以外には触っていない様子が確認できる。\njournalctl -u dhcpcd # 3月 03 03:22:02 HOSTNAME dhcpcd[364315]: dhcpcd-10.3.0 starting # 3月 03 03:22:02 HOSTNAME dhcpcd[364330]: dev: loaded udev # 3月 03 03:22:02 HOSTNAME dhcpcd[364330]: DUID 00:01:00:01:2d:3d:8c:d0:xx:xx:xx:xx:xx:xx # 3月 03 03:22:02 HOSTNAME dhcpcd[364330]: eno1: IAID cc:cc:cc:cc # 3月 03 03:22:02 HOSTNAME dhcpcd[364330]: eno1: using static address 192.168.1.x/24 # 3月 03 03:22:02 HOSTNAME dhcpcd[364330]: eno1: soliciting an IPv6 router # 3月 03 03:22:14 HOSTNAME dhcpcd[364330]: eno1: no IPv6 Routers available 参考にしたサイトとか denyinterface getting ignored - Raspberry Pi Forums\nhttps://forums.raspberrypi.com/viewtopic.php?t=271875 (2026年3月3日) debian - All statically assigned addresses, but dhcpcd still runs? - Super User\nhttps://superuser.com/questions/547114/all-statically-assigned-addresses-but-dhcpcd-still-runs (2026年3月3日) raspbian - How can I make dhcpcd ignore an interface? - Raspberry Pi Stack Exchange\nhttps://raspberrypi.stackexchange.com/questions/104633/how-can-i-make-dhcpcd-ignore-an-interface (2026年3月3日) dhcpcd.conf(5) — Arch manual pages\nhttps://man.archlinux.org/man/dhcpcd.conf.5 (2026年3月3日) dhcpcd - ArchWiki\nhttps://wiki.archlinux.org/title/Dhcpcd (2026年3月3日) Google Gemini\nhttps://gemini.google.com/app (2026年3月3日) ","permalink":"https://www.nyanmo.info/posts/linux/dhcpcddenyinterfaces/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　dhcpcd を使って管理している PC があるが、最近その挙動について何度も DHCP して IP を取得しては、新しいものを取得するという動作をして、他の PC が接続できなくなるほど、IP プールを勝手に枯渇させるということがあった。\u003c/p\u003e\n\u003cp\u003e　特定インターフェースについて、そもそも DHCP とかで勝手に設定しないように指定したつもりであったが、機能していないことが分かった。動くまで調べ、機能しているように見えるところまで持ってきたのでそれについて記録する。ただしばらく動かしてみないと実際機能しているかわからないので、すぐわかる範囲での暫定的な記録となる。\u003c/p\u003e\n\u003ch2 id=\"設定方法\"\u003e設定方法\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003e/etc/dhcpcd.conf\u003c/code\u003eの最上位に、\u003ccode\u003edenyinterfaces [DHCPしないインターフェース名1] [DHCPしないインターフェース名2] ...\u003c/code\u003eというように記述する。基本的に DHCP したり静的に IP などを取得し設定するインターフェースの設定より上に書かないといけないっぽいことが今回調べて分かった。\u003ca href=\"https://forums.raspberrypi.com/viewtopic.php?t=271875\"\u003edenyinterface getting ignored - Raspberry Pi Forums\u003c/a\u003e に書かれているように、dhcpcd は設定ファイル内の順次自体が大事なように見受けられる。設定例はブログに乗せるために\u003ccode\u003e...\u003c/code\u003eとして省略している部分がある。\u003c/p\u003e\n\u003ch3 id=\"機能しているっぽい設定例\"\u003e機能しているっぽい設定例\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003e# cat /etc/dhcpcd.conf\n# A sample configuration for dhcpcd.\n# See dhcpcd.conf(5) for details.\n\ndenyinterfaces eno2 enp0s20u11\n\n...\n\ninterface eno1\nstatic ip_address=192.168.1.x\nstatic routers=192.168.1.x\nstatic domain_name_servers=8.8.8.8\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"機能していないっぽい設定例\"\u003e機能していないっぽい設定例\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003e# cat /etc/dhcpcd.conf\n# A sample configuration for dhcpcd.\n# See dhcpcd.conf(5) for details.\n\n...\n\ninterface eno1\nstatic ip_address=192.168.1.x\nstatic routers=192.168.1.x\nstatic domain_name_servers=8.8.8.8\n\n...\n\ndenyinterfaces eno2 enp0s20u11\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"問題となっているpcなどの構成情報\"\u003e問題となっているPCなどの構成情報\u003c/h2\u003e\n\u003ch3 id=\"関係のありそうな構成情報の列挙\"\u003e関係のありそうな構成情報の列挙\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eArch Linux\u003c/li\u003e\n\u003cli\u003eFirewalld\u003c/li\u003e\n\u003cli\u003edhcpcd\u003c/li\u003e\n\u003cli\u003enftables\u003c/li\u003e\n\u003cli\u003eSoftEther VPN\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"今回登場するpcの説明\"\u003e今回登場するPCの説明\u003c/h3\u003e\n\u003ch4 id=\"ルータpc\"\u003eルータPC\u003c/h4\u003e\n\u003cp\u003e　家庭用ルータに置き換えて、nftables と kea によってルータ化した PC である。基本的な機能性は家庭用ルータと変わらないように意識し、USB NIC と内蔵 NIC の2つからなる。今回説明に出てくる、具体的なインターフェース名に紐づく物理 NIC とは関係ない。\u003c/p\u003e","title":"dhcpcd が特定のインターフェースに対して DHCP するのをやめるように指定してもやめない"},{"content":"この記事を作った動機 最近GitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI systemを使って、Intel Arc A770 を Windows 11 で運用していたが Linux 環境を使うようになって、新たに対応が必要なことが分かった。\n具体的には、Windows 利用時は、GitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI systemで提供されている、ReBarState.exeを使うことで Bar サイズを自分で指定すれば勝手に UEFI 変数が必要な分設定されたが、Linux 環境にそのような専用ツールはないと思っていたので、自分で UEFI 変数を書こうとしていた。\nその過程で、UEFI 変数を書き込むことに苦戦したんのでその記録を取る。またあとから気づいた ReSizebleBar の UEFI ドライバが使う変数を書き込む専用ツールをソースコードからコンパイルすることについても記録する。基本的にGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system関して UEFI 変数を設定する必要がある場合は、ツールを使う方法を推奨する。\n環境 System Details Report Report details Date generated: 2026-03-01 13:39:42 Hardware Information: Hardware Model: HP ProLiant ML150 Gen9 Memory: 80.0 GiB Processor: Intel® Xeon® E5-2667 v4 × 32 Graphics: Intel® Arc™ A770 Graphics (DG2) Disk Capacity: 1.5 TB Software Information: Firmware Version: P95 OS Name: Arch Linux OS Build: (null) OS Type: 64-bit GNOME Version: 49 Windowing System: Wayland Kernel Version: Linux 6.18.6-arch1-1 ツールを使う GitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI systemでReSizebleBar のためにUEFIの設定が必要な場合について記録する。すでに作業ディレクトリを作成し、移動していることを前提として想定している。\n必要なツールのインストール sudo pacman -Sy base-devel cmake GitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI systemをクローン git clone https://github.com/xCuri0/ReBarUEFI.git コンパイルする cd ReBarUEFI/ReBarState/ cmake -B ./ make 実行する sudo ./ReBarState # ReBarState (c) 2023 xCuri0 # # Current ReBarState 1 / 2 MB # # Verify that 4G Decoding is enabled and CSM is disabled otherwise system will not POST with GPU. If your ReBarState value keeps getting reset then check your system time. # # It is recommended to first try smaller sizes above 256MB in case BIOS doesn\u0026#39;t support large BARs. # # Enter ReBarState Value # 0: Disabled # Above 0: Maximum BAR size set to 2^x MB # 32: Unlimited BAR size # # 12 # Writing value of 12 / 4096 MB to ReBarState # # Successfully wrote ReBarState UEFI variable # # Reboot for changes to take effect UEFI 変数を直接書き込む Linux 環境においては、/sys/firmware/efi/efivars 配下に各 UEFI 変数がファイルとして独立してバイナリ形式で存在している。ここに所定の決まった[変数名]-[変数の識別子のUUID]という構成でバイナリファイルを書き込んだりすることで、UEFI 変数の設定が可能である。\n今回の問題であるGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI systemについて、設定する必要のある UEFI 変数名と UUID については、ReBarUEFI/ReBarState/ReBarState.cpp at master · xCuri0/ReBarUEFI · GitHub のソースコードをもとに以下ののようになっていることを確認した。\nちなみに途中でツールを使う方法を見つけたため、この方法については、とりあえず動くというだけで実際に機能するか検証していない。ただ、このスクリプトを実行したあとに、ツールを使うところでコンパイルした、ReBarState 経由から設定した値によって Bar サイズが意図したとおりに設定で設定できていそうなことは確認した。\n変数名\nReBarState UUID\na3c5b77a-c88f-4a93-bf1c-4a92a32c65ce 型\nUnsigned INT 8 そこで以下のようにして変数を書き込むスクリプトを作った。書き込み保護がかかっており、手動では機能してもスクリプトでは機能しないことがあったので、chattrコマンドを使って、一時的に書き込み保護を解除するようにした。-iが書き込み保護を外すオプションであり、+iが書き込み保護を復活させるオプションである。\n#!/bin/bash cd /sys/firmware/efi/efivars # 2^12 -\u0026gt; 4 GB sudo chattr -i /sys/firmware/efi/efivars/ReBarState-a3c5b77a-c88f-4a93-bf1c-4a92a32c65ce # ReBar サイズの設定数値の例 # 4GB -\u0026gt; 2^12 -\u0026gt; 0x0c(12) を設定する # printf \u0026#34;\\x07\\x00\\x00\\x00\\x[ReBarサイズ16進数]\u0026#34; | sudo dd of=\u0026#34;/sys/firmware/efi/efivars/[UEFI変数名]-[UEFI UUID]\u0026#34; bs=5 count=1 # 他の UEFI 変数を扱う場合は、bs= や count= などの引数を調整する必要があると思われる。 printf \u0026#34;\\x07\\x00\\x00\\x00\\x0c\u0026#34; | sudo dd of=\u0026#34;/sys/firmware/efi/efivars/ReBarState-a3c5b77a-c88f-4a93-bf1c-4a92a32c65ce\u0026#34; bs=5 count=1 sudo chattr +i /sys/firmware/efi/efivars/ReBarState-a3c5b77a-c88f-4a93-bf1c-4a92a32c65ce sudo hexdump /sys/firmware/efi/efivars/ReBarState-a3c5b77a-c88f-4a93-bf1c-4a92a32c65ce 参考にしたサイトとか unix - Bash Script: Invalid argument - Super User\nhttps://superuser.com/questions/385761/bash-script-invalid-argument (2026年3月1日)\nwrite error: Invalid argument · Issue #40 · 0xbb/gpu-switch\nhttps://github.com/0xbb/gpu-switch/issues/40 (2026年3月1日)\nbash: echo: write error: Invalid argument - Ask Ubuntu\nhttps://askubuntu.com/questions/887412/bash-echo-write-error-invalid-argument (2026年3月1日)\naudio - Linux - Modify an efi var with efivar - Unix \u0026amp; Linux Stack Exchange\nhttps://unix.stackexchange.com/questions/536436/linux-modify-an-efi-var-with-efivar (2026年3月1日)\nefivar(1) — Arch manual pages\nhttps://man.archlinux.org/man/efivar.1 (2026年3月1日)\nGitHub - rhboot/efivar: Tools and libraries to work with EFI variables\nhttps://github.com/rhboot/efivar (2026年3月1日)\nprintf invocation (GNU Coreutils 9.10)\nhttps://www.gnu.org/software/coreutils/manual/html_node/printf-invocation.html (2026年3月1日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年3月1日)\nGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system\nhttps://github.com/xCuri0/ReBarUEFI (2026年3月1日)\nReBarUEFI/ReBarState/ReBarState.cpp at master · xCuri0/ReBarUEFI · GitHub\nhttps://github.com/xCuri0/ReBarUEFI/blob/master/ReBarState/ReBarState.cpp#L81 (2026年3月1日)\nArch Linux - base-devel 1-2 (any)\nhttps://archlinux.org/packages/core/any/base-devel/ (2026年3月1日)\n","permalink":"https://www.nyanmo.info/posts/linux/writeuefivar/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近\u003ca href=\"https://github.com/xCuri0/ReBarUEFI\"\u003eGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system\u003c/a\u003eを使って、Intel Arc A770 を Windows 11 で運用していたが Linux 環境を使うようになって、新たに対応が必要なことが分かった。\u003c/p\u003e\n\u003cp\u003e　具体的には、Windows 利用時は、\u003ca href=\"https://github.com/xCuri0/ReBarUEFI\"\u003eGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system\u003c/a\u003eで提供されている、ReBarState.exeを使うことで Bar サイズを自分で指定すれば勝手に UEFI 変数が必要な分設定されたが、Linux 環境にそのような専用ツールはないと思っていたので、自分で UEFI 変数を書こうとしていた。\u003c/p\u003e\n\u003cp\u003e　その過程で、UEFI 変数を書き込むことに苦戦したんのでその記録を取る。またあとから気づいた ReSizebleBar の UEFI ドライバが使う変数を書き込む専用ツールをソースコードからコンパイルすることについても記録する。基本的に\u003ca href=\"https://github.com/xCuri0/ReBarUEFI\"\u003eGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system\u003c/a\u003e関して UEFI 変数を設定する必要がある場合は、\u003ca href=\"#%E3%83%84%E3%83%BC%E3%83%AB%E3%82%92%E4%BD%BF%E3%81%86\"\u003eツールを使う\u003c/a\u003e方法を推奨する。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"system-details-report\"\u003eSystem Details Report\u003c/h3\u003e\n\u003ch4 id=\"report-details\"\u003eReport details\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2026-03-01 13:39:42\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"hardware-information\"\u003eHardware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              HP ProLiant ML150 Gen9\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      80.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Xeon® E5-2667 v4 × 32\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Intel® Arc™ A770 Graphics (DG2)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               1.5 TB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"software-information\"\u003eSoftware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            P95\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    (null)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               49\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.18.6-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ツールを使う\"\u003eツールを使う\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://github.com/xCuri0/ReBarUEFI\"\u003eGitHub - xCuri0/ReBarUEFI: Resizable BAR for (almost) any UEFI system\u003c/a\u003eでReSizebleBar のためにUEFIの設定が必要な場合について記録する。すでに作業ディレクトリを作成し、移動していることを前提として想定している。\u003c/p\u003e","title":"UEFI 変数を書き込む (ReSizebleBar)"},{"content":"この記事を作った動機 named が名前解決時に参照する上流の DNS サーバのアクセスについて、SSL/TLSの暗号化を適用する設定をしたので、それについて記録したい。前提としてすでに named の設定が済んでいて通常の非暗号化状態の8.8.8.8#53などにおいて、動作していることを想定する。\n設定方法 /etc/named.confを編集する tls tls-forwarder optionsブロックの外に記述するtls [設定名]からなる、TLS 設定である。\nca-file\nデフォルトでインストールされている証明書を使っている。 remote-hostname\nDoH 先の DNS サーバのホスト名を設定する。今回は Google DNS を使うので、dns.googleとした。 forwarders [DNSサーバのIP] port [DoH先のポート番号] tls [tls設定名]という形で設定する。通常の DoH ポート番号は853であり、HTTPSの443ではない。\n設定例 tls tls-forwarder { ca-file \u0026#34;/etc/ssl/certs/ca-certificates.crt\u0026#34;; remote-hostname \u0026#34;dns.google\u0026#34;; }; ... options { ... forwarders { 8.8.8.8 port 853 tls tls-forwarder; 8.8.4.4 port 853 tls tls-forwarder; }; ... }; ... 動作確認 tcpdumpを使って確認する。以下は Google DNS が動いている様子を確認するために、8.8.8.8 の IP のホストの 853 番にアクセスしているか確認する例である。\nsudo tcpdump -i [named自体が動いているサーバのNICインターフェース名] port 853 and host 8.8.8.8 # ... # 22:45:41.875687 IP HOSTNAME.37559 \u0026gt; dns.google.domain-s: Flags [P.], seq 1855:1935, ack 5339, win 66, options [nop,nop,TS val 2014914753 ecr 370418067], length 80 # 22:45:41.875766 IP HOSTNAME.37559 \u0026gt; dns.google.domain-s: Flags [P.], seq 1935:2007, ack 5339, win 66, options [nop,nop,TS val 2014914753 ecr 370418067], length 72 # 22:45:41.894084 IP dns.google.domain-s \u0026gt; HOSTNAME.37559: Flags [.], ack 2007, win 1043, options [nop,nop,TS val 370418089 ecr 2014914753], length 0 # 22:45:41.895451 IP dns.google.domain-s \u0026gt; HOSTNAME.37559: Flags [.], seq 5339:6547, ack 2007, win 1043, options [nop,nop,TS val 370418090 ecr 2014914753], length 1208 # 22:45:41.895498 IP dns.google.domain-s \u0026gt; HOSTNAME.37559: Flags [P.], seq 6547:6691, ack 2007, win 1043, options [nop,nop,TS val 370418090 ecr 2014914753], length 144 # 22:45:41.895553 IP HOSTNAME.37559 \u0026gt; dns.google.domain-s: Flags [.], ack 6691, win 66, options [nop,nop,TS val 2014914773 ecr 370418090], length 0 # ... 参考にしたサイトとか Google Gemini\nhttps://gemini.google.com/app (2026年2月28日) BIND - ArchWiki\nhttps://wiki.archlinux.jp/index.php/BIND (2026年2月28日) 8 . Configuration Reference — BIND 9 9.20.20 documentation\nhttps://bind9.readthedocs.io/en/v9.20.20/reference.html#namedconf-statement-forwarders (2026年2月28日) 8 . Configuration Reference — BIND 9 9.20.20 documentation\nhttps://bind9.readthedocs.io/en/v9.20.20/reference.html#namedconf-statement-tls (2026年2月28日) DNS-over-HTTPS (DoH) | Public DNS | Google for Developers\nhttps://developers.google.com/speed/public-dns/docs/doh (2026年2月28日) ","permalink":"https://www.nyanmo.info/posts/linux/namedwithdotforforwarders/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　named が名前解決時に参照する上流の DNS サーバのアクセスについて、SSL/TLSの暗号化を適用する設定をしたので、それについて記録したい。前提としてすでに named の設定が済んでいて通常の非暗号化状態の\u003ccode\u003e8.8.8.8#53\u003c/code\u003eなどにおいて、動作していることを想定する。\u003c/p\u003e\n\u003ch2 id=\"設定方法\"\u003e設定方法\u003c/h2\u003e\n\u003ch3 id=\"etcnamedconfを編集する\"\u003e\u003ccode\u003e/etc/named.conf\u003c/code\u003eを編集する\u003c/h3\u003e\n\u003ch4 id=\"tls-tls-forwarder\"\u003e\u003ccode\u003etls tls-forwarder\u003c/code\u003e\u003c/h4\u003e\n\u003cp\u003e　\u003ccode\u003eoptions\u003c/code\u003eブロックの外に記述する\u003ccode\u003etls [設定名]\u003c/code\u003eからなる、TLS 設定である。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eca-file\u003c/code\u003e\u003cbr\u003e\n　デフォルトでインストールされている証明書を使っている。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eremote-hostname\u003c/code\u003e\u003cbr\u003e\n　DoH 先の DNS サーバのホスト名を設定する。今回は Google DNS を使うので、\u003ccode\u003edns.google\u003c/code\u003eとした。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"forwarders\"\u003e\u003ccode\u003eforwarders\u003c/code\u003e\u003c/h4\u003e\n\u003cp\u003e　\u003ccode\u003e[DNSサーバのIP] port [DoH先のポート番号] tls [tls設定名]\u003c/code\u003eという形で設定する。通常の DoH ポート番号は\u003cstrong\u003e853\u003c/strong\u003eであり、HTTPSの\u003cstrong\u003e443\u003c/strong\u003eではない。\u003c/p\u003e\n\u003ch4 id=\"設定例\"\u003e設定例\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003etls tls-forwarder {\n     ca-file \u0026#34;/etc/ssl/certs/ca-certificates.crt\u0026#34;;\n     remote-hostname \u0026#34;dns.google\u0026#34;;\n};\n...\noptions {\n    ...\n    forwarders {\n        8.8.8.8 port 853 tls tls-forwarder;\n        8.8.4.4 port 853 tls tls-forwarder;\n    };\n    ...\n};\n...\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"動作確認\"\u003e動作確認\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003etcpdump\u003c/code\u003eを使って確認する。以下は Google DNS が動いている様子を確認するために、8.8.8.8 の IP のホストの 853 番にアクセスしているか確認する例である。\u003c/p\u003e","title":"BIND (named) 自体のクエリ先に DoH (DNS-over-HTTPS) を反映する"},{"content":"この記事を作った動機 Linux PC をルータ化するの話が長くなりすぎたので分けた。ここでは、簡易的にDHCPサーバを Linux 上で立てる方法について、簡易的にまとめることにする。難しいことはせず簡単に設定したので、不十分である可能性がある。今回は以下の項目について、今回立てるDHCPサーバでできることを目指した。\nIPv4 で動作し、IPv6は今回取り扱わない デフォルトゲートウェイを設定する DNS サーバを設定する IPを新しく接続されたコンピュータに対して割り当てる また、Linux PC をルータ化する でマスカレードやらの設定が終わっていてすでにネットワークが機能している状態を想定している。ネットワークの構成については、今回テストに使ったものは以下のような構成である。192.168.0.0/24のネットワークについて、DHCPサーバを構成することを目指す。\n手順 パッケージのインストール yay -Sy kea # sudo pacman -Sy kea /etc/kea/kea-dhcp4.conf設定をする # commentで示されるコメント部分は以下の例から取り除かないと多分動かない。また以下はほとんど Kea - ArchWiki の設定をコピーして私のテスト環境用に設定をちょっといじっただけである。\n{ \u0026#34;Dhcp4\u0026#34;: { \u0026#34;interfaces-config\u0026#34;: { \u0026#34;interfaces\u0026#34;: [ \u0026#34;eno1\u0026#34; ], # DHCPサーバを動かしたい LAN 側のインターフェースを指定する \u0026#34;dhcp-socket-type\u0026#34;: \u0026#34;raw\u0026#34; }, \u0026#34;subnet4\u0026#34;: [ { \u0026#34;id\u0026#34;: 1, \u0026#34;subnet\u0026#34;: \u0026#34;192.168.0.0/24\u0026#34;, # 管理するネットワークを指定する \u0026#34;pools\u0026#34;: [ { \u0026#34;pool\u0026#34;: \u0026#34;192.168.0.10 - 192.168.0.199\u0026#34; } ], # あたらしく接続されたクライアントに割り当てるIPの範囲を指定する \u0026#34;option-data\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;routers\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;192.168.0.3\u0026#34; # デフォルトゲートウェイにしたいサーバを指定する }, { \u0026#34;name\u0026#34;: \u0026#34;domain-name-servers\u0026#34;, \u0026#34;data\u0026#34;: \u0026#34;192.168.0.3\u0026#34; # DNS サーバを指定する } ] } ] } } kea-dhcp4サービスを有効化、起動する sudo systemctl enable --now kea-dhcp4 DHCPでネットワーク設定を自動取得できるか試す スイッチ越しにクライアントを接続し設定なしでインターネットなどが利用できることを確認する。\nipconfig # ... # イーサネット アダプター Embedded LOM 1 Port 1: # # 接続固有の DNS サフィックス . . . . .: # 説明. . . . . . . . . . . . . . . . .: Broadcom NetXtreme Gigabit Ethernet #2 # 物理アドレス. . . . . . . . . . . . .: xx-xx-xx-xx-xx-xx # DHCP 有効 . . . . . . . . . . . . . .: はい # 自動構成有効. . . . . . . . . . . . .: はい # リンクローカル IPv6 アドレス. . . . .: fe80::2971:1249:57ad:9714%15(優先) # IPv4 アドレス . . . . . . . . . . . .: 192.168.0.12(優先) # サブネット マスク . . . . . . . . . .: 255.255.255.0 # リース取得. . . . . . . . . . . . . .: 2026年2月26日 21:12:09 # リースの有効期限. . . . . . . . . . .: 2026年2月26日 23:12:09 # デフォルト ゲートウェイ . . . . . . .: 192.168.0.3 # DHCP サーバー . . . . . . . . . . . .: 192.168.0.3 # DHCPv6 IAID . . . . . . . . . . . . .: 136871971 # DHCPv6 クライアント DUID. . . . . . .: XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX-XX # DNS サーバー. . . . . . . . . . . . .: 192.168.0.3 # NetBIOS over TCP/IP . . . . . . . . .: 有効 # ... ping 192.168.1.1 # 192.168.1.1 に ping を送信しています 32 バイトのデータ: # 192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=63 # # 192.168.1.1 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 0ms、最大 = 1ms、平均 = 0ms ping google.com # google.com [142.251.118.113]に ping を送信しています 32 バイトのデータ: # 142.251.118.113 からの応答: バイト数 =32 時間 =20ms TTL=113 # 142.251.118.113 からの応答: バイト数 =32 時間 =12ms TTL=113 # 142.251.118.113 からの応答: バイト数 =32 時間 =12ms TTL=113 # 142.251.118.113 からの応答: バイト数 =32 時間 =12ms TTL=113 # # 142.251.118.113 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 12ms、最大 = 20ms、平均 = 14ms ping 192.168.0.3 # 192.168.0.3 に ping を送信しています 32 バイトのデータ: # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # # 192.168.0.3 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 0ms、最大 = 0ms、平均 = 0ms 関連のある記事 Linux PC をルータ化する 使った画像とか Windows 7(Vista) デフォルトのアイコン ルーター PCのアイコン インターネット的なアイコン 参考にしたサイトとか dhcpd - ArchWiki\nhttps://wiki.archlinux.org/title/Dhcpd (2026年2月26日) Kea DHCP - ISC\nhttps://www.isc.org/kea/ (2026年2月26日) Kea - ArchWiki\nhttps://wiki.archlinux.org/title/Kea (2026年2月26日) Arch Linux - kea 1:3.0.2-3 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/kea/ (2026年2月26日) How to find your DNS server address - eukhost\nhttps://www.eukhost.com/kb/how-to-find-your-dns-server-address/ (2026年2月26日) ","permalink":"https://www.nyanmo.info/posts/linux/dhcpserver/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/linux/routerwithnatandfirewall/\"\u003eLinux PC をルータ化する\u003c/a\u003eの話が長くなりすぎたので分けた。ここでは、簡易的にDHCPサーバを Linux 上で立てる方法について、簡易的にまとめることにする。難しいことはせず簡単に設定したので、不十分である可能性がある。今回は以下の項目について、今回立てるDHCPサーバでできることを目指した。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eIPv4 で動作し、IPv6は今回取り扱わない\u003c/li\u003e\n\u003cli\u003eデフォルトゲートウェイを設定する\u003c/li\u003e\n\u003cli\u003eDNS サーバを設定する\u003c/li\u003e\n\u003cli\u003eIPを新しく接続されたコンピュータに対して割り当てる\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　また、\u003ca href=\"https://www.nyanmo.info/posts/linux/routerwithnatandfirewall/\"\u003eLinux PC をルータ化する\u003c/a\u003e でマスカレードやらの設定が終わっていてすでにネットワークが機能している状態を想定している。ネットワークの構成については、今回テストに使ったものは以下のような構成である。192.168.0.0/24のネットワークについて、DHCPサーバを構成することを目指す。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/routerWithNATandFirewall/networkArchitecture.png#center\"\n         alt=\"ネットワーク構成図\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"手順\"\u003e手順\u003c/h2\u003e\n\u003ch3 id=\"パッケージのインストール\"\u003eパッケージのインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy kea\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -Sy kea\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"etckeakea-dhcp4conf設定をする\"\u003e\u003ccode\u003e/etc/kea/kea-dhcp4.conf\u003c/code\u003e設定をする\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003e# comment\u003c/code\u003eで示されるコメント部分は以下の例から取り除かないと多分動かない。また以下はほとんど \u003ca href=\"https://wiki.archlinux.org/title/Kea\"\u003eKea - ArchWiki\u003c/a\u003e の設定をコピーして私のテスト環境用に設定をちょっといじっただけである。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode class=\"language-conf\" data-lang=\"conf\"\u003e{\n    \u0026#34;Dhcp4\u0026#34;: {\n        \u0026#34;interfaces-config\u0026#34;: {\n            \u0026#34;interfaces\u0026#34;: [ \u0026#34;eno1\u0026#34; ], # DHCPサーバを動かしたい LAN 側のインターフェースを指定する\n            \u0026#34;dhcp-socket-type\u0026#34;: \u0026#34;raw\u0026#34;\n        },\n\n        \u0026#34;subnet4\u0026#34;: [\n            {\n                \u0026#34;id\u0026#34;: 1,\n                \u0026#34;subnet\u0026#34;: \u0026#34;192.168.0.0/24\u0026#34;, # 管理するネットワークを指定する\n                \u0026#34;pools\u0026#34;: [ { \u0026#34;pool\u0026#34;: \u0026#34;192.168.0.10 - 192.168.0.199\u0026#34; } ], # あたらしく接続されたクライアントに割り当てるIPの範囲を指定する\n                \u0026#34;option-data\u0026#34;: [\n                    {\n                        \u0026#34;name\u0026#34;: \u0026#34;routers\u0026#34;,\n                        \u0026#34;data\u0026#34;: \u0026#34;192.168.0.3\u0026#34; # デフォルトゲートウェイにしたいサーバを指定する\n                    },\n                    {\n                        \u0026#34;name\u0026#34;: \u0026#34;domain-name-servers\u0026#34;,\n                        \u0026#34;data\u0026#34;: \u0026#34;192.168.0.3\u0026#34; # DNS サーバを指定する\n                    }\n                ]\n            }\n        ]\n    }\n}\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"kea-dhcp4サービスを有効化起動する\"\u003e\u003ccode\u003ekea-dhcp4\u003c/code\u003eサービスを有効化、起動する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now kea-dhcp4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"dhcpでネットワーク設定を自動取得できるか試す\"\u003eDHCPでネットワーク設定を自動取得できるか試す\u003c/h3\u003e\n\u003cp\u003e　スイッチ越しにクライアントを接続し設定なしでインターネットなどが利用できることを確認する。\u003c/p\u003e","title":"Linux PC に DHCP サーバを立てる"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 まだ書いていない。\n関連のある記事 Linux PC をルータ化する 使った画像とか File:Tux.svg - Wikimedia Commons (lewing@isc.tamu.edu Larry Ewing and The GIMP, CC0, via Wikimedia Commons)\nhttps://commons.wikimedia.org/wiki/File:Tux.svg (2026年2月26日) Windows 7(Vista) デフォルトのアイコン ルーター PCのアイコン Pi-hole – Network-wide Ad Blocking のロゴ\nhttps://pi-hole.net/ (2026年2月26日) 参考にしたサイトとか Pi-hole – Network-wide Ad Blocking\nhttps://pi-hole.net/ (2026年2月26日) ","permalink":"https://www.nyanmo.info/posts/linux/pihole/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　まだ書いていない。\u003c/p\u003e\n\u003ch2 id=\"関連のある記事\"\u003e関連のある記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/routerwithnatandfirewall/\"\u003eLinux PC をルータ化する\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"使った画像とか\"\u003e使った画像とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFile:Tux.svg - Wikimedia Commons (\u003ca href=\"mailto:lewing@isc.tamu.edu\"\u003elewing@isc.tamu.edu\u003c/a\u003e Larry Ewing and The GIMP, CC0, via Wikimedia Commons)\u003cbr\u003e\n\u003ca href=\"https://commons.wikimedia.org/wiki/File:Tux.svg\"\u003ehttps://commons.wikimedia.org/wiki/File:Tux.svg\u003c/a\u003e (2026年2月26日)\u003c/li\u003e\n\u003cli\u003eWindows 7(Vista) デフォルトのアイコン\n\u003cul\u003e\n\u003cli\u003eルーター\u003c/li\u003e\n\u003cli\u003ePCのアイコン\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003ePi-hole – Network-wide Ad Blocking のロゴ\u003cbr\u003e\n\u003ca href=\"https://pi-hole.net/\"\u003ehttps://pi-hole.net/\u003c/a\u003e (2026年2月26日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePi-hole – Network-wide Ad Blocking\u003cbr\u003e\n\u003ca href=\"https://pi-hole.net/\"\u003ehttps://pi-hole.net/\u003c/a\u003e (2026年2月26日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Pi-hole をインストールする"},{"content":"この記事を作った動機 私が使っている家庭用ルータの挙動が怪しく、時々特定 IP にアクセスできなくなったり、NAT 越えして VPN 接続する際に接続ができなかったりするときがあるなど、安定性に欠けることがあることが分かった。\nそこで、使っていないミニ PC に Linux 環境をインストールし、そこで何かしら設定をすれば、ルータ化できるのではないかという話が、Gemini にいろいろ投げつけると出てきたので、実際にそれができるのか検証も兼ねて、自分で設定し試してみた。\nそもそも私自身がネットワークについて授業でレポートを作るためなど、単位を取るために軽く触った程度で、実際に自分で使うために運用して体験してみたり、試す実戦経験に疎いところがある。その点も兼ねて今回実際に検証してみて、難しいと思うことに関しては自分なりにノートを取ってみることにしたというのが、この記事を書いた動機である。\n今回の設定がうまくいかない場合、再起動後にルータとして機能しない に書いているように、nftables自体がFirewalldの動作に干渉しているかもしれないので確認する。\n設定のまとめ 今回の話のネットワーク構成の前提 いきなり本番環境で動かすのはリスクが高すぎるので、既存の家庭用ルータが形成するLANをWANとして見立てて、そこにぶら下げるようにして今回ルータ化するPCを配置し、実際に動作するか検証する形にした。\n設定の全体像 sudo firewall-cmd --list-all --zone=LAN; sudo firewall-cmd --list-all --zone=WAN # LAN (active) # target: ACCEPT # ingress-priority: 0 # egress-priority: 0 # icmp-block-inversion: no # interfaces: [LAN側のインターフェース名] # sources: # services: mdns ssh # ports: 3389/tcp 3389/udp # protocols: # forward: yes # masquerade: no # forward-ports: # source-ports: # icmp-blocks: # rich rules: # WAN (active) # target: DROP # ingress-priority: 0 # egress-priority: 0 # icmp-block-inversion: no # interfaces: [WAN側のインターフェース名] # sources: # services: # ports: # protocols: # forward: no # masquerade: yes # forward-ports: # source-ports: # icmp-blocks: # rich rules: sudo sysctl net.ipv4.ip_forward # net.ipv4.ip_forward = 1 ip a # 1: lo: \u0026lt;LOOPBACK,UP,LOWER_UP\u0026gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 # link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 # inet 127.0.0.1/8 scope host lo # valid_lft forever preferred_lft forever # inet6 ::1/128 scope host noprefixroute # valid_lft forever preferred_lft forever # # 2: [LAN側のインターフェース名]: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000 # link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff # inet 192.168.0.3/24 scope global [LAN側のインターフェース名] # valid_lft forever preferred_lft forever # inet6 fe80::725a:fff:fe3f:8c93/64 scope link proto kernel_ll # valid_lft forever preferred_lft forever # ... # 4: [WAN側のインターフェース名]: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UP group default # qlen 1000 # link/ether yy:yy:yy:yy:yy:yy brd ff:ff:ff:ff:ff:ff # inet 192.168.1.19/24 brd 192.168.1.255 scope global [WAN側のインターフェース名] # valid_lft forever preferred_lft forever # inet6 fe80::3695:dbff:fe2b:1a6d/64 scope link proto kernel_ll # valid_lft forever preferred_lft forever インストールするパッケージ yay -S firewalld net-tools dhclient 具体的なコマンド操作 # 起動時にfirewalldが起動するようにする sudo systemctl enable --now firewalld # すでに有効化していたり、一時的に立ち上げた状態にしたい場合 # sudo systemctl start firewalld # NetworkManagerは手動でfirewalldに設定した項目を上書きする可能性があるので使わない # sudo systemctl disable NetworkManager # public ゾーンに紐づけられているインターフェースを確認し引きはがす sudo firewall-cmd --list-all sudo firewall-cmd --remove-interface=[publicに紐づけられているインターフェース名] --permanent # 新しいゾーン LAN と WAN を作成し、 # LAN側にしてスイッチに接続するインターフェースと、WAN側にして上流の外部ネットワークに接続するインターフェースを紐づける sudo firewall-cmd --new-zone=LAN --permanent sudo firewall-cmd --new-zone=WAN --permanent sudo firewall-cmd --zone=LAN --add-interface=[LAN側のインターフェース名] --permanent sudo firewall-cmd --zone=WAN --add-interface=[WAN側のインターフェース名] --permanent # 各ゾーンのパケットの扱いを設定 sudo firewall-cmd --zone=LAN --set-target=ACCEPT --permanent sudo firewall-cmd --zone=WAN --set-target=DROP --permanent # LANゾーンにおいて転送、WANゾーンにおいてマスカレード設定の有効化 firewall-cmd --zone=LAN --add-forward --permanent firewall-cmd --zone=WAN --add-masquerade --permanent # 設定を反映 sudo systemctl restart firewalld Systemd で起動時に実行する内容 (root,initRouter.sh) ※ 保存してスクリプトを作成し終わったら、chmod +x [filename]で実行権限を付与することを忘れないこと。\n#!/bin/bash sleep 20 # kernel parameter を設定し、異なるインターフェース間をパケットが行き来できるようにする sudo sysctl -w net.ipv4.ip_forward=1 # LAN (192.168.0.0/24 ネットワークにおいてルータとしてゲートウェイや管理のためにアクセスできるようにするためにIPを設定) sudo ip addr add 192.168.0.3/24 dev [LAN側のインターフェース名] # WAN (IPアドレス等を自動取得) sudo dhclient [WAN側のインターフェース名] # DNS setting (dhclient が勝手に書き換えてしまうので dhclient 実行後に手動で設定) # 今回は例として \u0026#34;8.8.8.8\u0026#34; の Google の DNS サーバを指しているが、 # 任意で \u0026#34;1.1.1.1\u0026#34; や個別に自前で運用している DNS サーバに指定可能である sleep 5 echo \u0026#34;nameserver 8.8.8.8\u0026#34; | sudo tee /etc/resolv.conf # なんかスイッチとかに繋がってリンクを確立しているのに、\u0026#34;DOWN\u0026#34;していることがあったので一定時間待ってから明示的に\u0026#34;UP\u0026#34;にする sleep 20 sudo ip link set up dev [LAN側のインターフェース名] sleep 5 sudo ip link set up dev [WAN側のインターフェース名] # もし DHCP サーバとして kea をインストールしている場合 # sleep 5 # sudo systemctl restart kea-dhcp4 /etc/systemd/system/routerINIT.serviceとして配置する systemd スクリプトの例 [Unit] Description=init router function. After=display-manager.service # 起動前からケーブルなどのセットアップは済んでいることを想定している。 [Service] Type=simple User=root ExecStart=/path/to/initRouter.sh \u0026amp; # スクリプトを配置した場所に書き換える必要がある。 Restart=on-abort [Install] WantedBy=multi-user.target sudo systemctl enable routerINIT 課題 一時的な停電があったとき、電力が復旧したら自動的に起動するように BIOS に設定する必要がある。 NetworkManagerやdhcpcdを使っていないので、ネットワークの構成が変わったことを検出して自動的に IP を取得するスクリプトが必要である。 DHCP サーバを立てないと LAN側に接続されたクライアントに IP 自動的に割り振られたりしない。 設定に対する考えや経緯など nftablesを使う案からFirewalldをnftablesのフロントエンドとして使う発想に至るまで 当初はnftablesを使った方法が考えられていたが、設定が煩雑で難しく、現時点では以下のイメージの理解しか持ててないところがある。\nテーブル\nネットワーク処理設定の入れ物？ チェーン\nいつ処理を実行するか鎖を特定のタイミングに結び付ける ルール\n具体的な処理内容を決める また、私は普段 Linux 環境には Firewalldもセットでインストールしておりすでにnftablesに大量の設定があり、Firewalldと折り合いをつけながら現実的に変に設定が上書きされたりするのを避けたりしながら、netablesを直接使い、整合性をもって運用することが難しいと考えた。\nsudo nft list ruleset # table inet firewalld { # progname firewalld # ... ここに大量の設定が出てくる # } そこで、Firewalldだけで、今回はマスカレード(仮面)を設定することで、WAN 側に見立てた LAN 側では一つのIPアドレスから、LAN 側に見立てた側の内側からの複数の端末によるアクセスを実現することを目指すことになった。私は完全には理解しておらず、設定内容やツールの使い方について確証を持っているわけではないが、少なくとも家庭用ルータの NAT 機能に最低限あるような以下の点に関して検証を行うことで、正しく機能していることを確かめようとした。\nLAN に見立てた側から WAN に見立てた側の内部ネットワークに属するサーバや、Google などのグローバル空間の Web サービスなどにアクセスできる。ネットワークの内側から外側に通信を開始し、外側から帰ってきた応答をネットワークの内側までルータ化したPCを通して、クライアントが受け取れるのか検証する。 WAN 側に見立てた LAN 内のネットワークにおいて、ルータや LAN に見立てた側のルータ化したPC越しのネットワークに対して、外側から接続ができないことを試す。具体的には、LAN に見立てた側に対して、WAN に見立てた側から、ルータ化したPC自身やその先にあるクライアントに対し、SSH 接続を試みたり、RDP 接続を試みたり、ping を試みて、実際に接続できないことや疎通の確認が取れないことを確認する。ネットワークの外側から内側に接続を開始できないことを確認する。 今回は、確認してみたことで、ping が通じるかの例は示した。\nFirewalldを設定するにあたって考慮したこととか 今回Firewalldの設定で重要であったポイントには以下の点がある。\nマスカレード と SNAT、DNAT の違い (WAN 側に対するゾーンの設定) マスカレード\nWAN 側などに対して、固定された IP (仮面)を使わず、動的に取得した IP を LAN 側から来たパケットの仮面とて利用する方式。(What is IP Masquerade?)一つのグローバル IP や WAN 側に見立てられる LAN 内における一つのプライベート IP において、複数 LAN 内に繋がる機器を外側のネットワークにアクセスできるようにする。外側からアクセスを開始することができなため、セキュリティのために通常のインターネット利用などにおいて、安全のために利用されることがある。LAN 内 HTTP サーバーやファイル共有サーバを立てても、NAT越えしたりして直接内部のLANにアクセスしないと、立てたサーバにアクセスできない。\n以下は、What is IP Masquerade?の引用である。 2.1. What is IP Masquerade? IP Masquerade is a networking function in Linux similar to the one-to-many (1:Many) NAT (Network Address Translation) servers found in many commercial firewalls and network routers. For example, if a Linux host is connected to the Internet via PPP, Ethernet, etc., the IP Masquerade feature allows other \u0026ldquo;internal\u0026rdquo; computers connected to this Linux box (via PPP, Ethernet, etc.) to also reach the Internet as well. Linux IP Masquerading allows for this functionality even though these internal machines don\u0026rsquo;t have an officially assigned IP address.\nMASQ allows a set of machines to invisibly access the Internet via the MASQ gateway. To other machines on the Internet, the outgoing traffic will appear to be from the IP MASQ Linux server itself. In addition to the added functionality, IP Masquerade provides the foundation to create a HEAVILY secured networking environment. With a well built firewall, breaking the security of a well configured masquerading system and internal LAN should be considerably difficult to accomplish.\nIf you would like to know more on how MASQ (1:Many) differs from 1:1 (true) NAT and Proxy solutions, please see the Section 7.6 FAQ entry.\nSNAT (Source Network Address Translation)\nネットワークパケットのヘッダなどに含まれる、送信側と宛先側のアドレスの内、送信側(ソース)のIPアドレスを換する方式である。WAN 側などに対して、固定された IP (仮面)を使い、事前に設定し取得した IP を LAN 側か来たパケットの仮面として利用する。一つのグローバル IP や WAN 側に見立てられる LAN 内における一つのプライベーIPにおいて、複数の LAN 内に繋がる機器を外側のネットワークにアクセスできるようにする。外側からアクセスを開することができないため、セキュリティのために通常のインターネット利用などにおいて、安全のために利用されことがある。LAN内にHTTP サーバーやファイル共有サーバを立てても、NAT 越えしたりして直接内部の LAN にアクセしないと、立てたサーバにアクセスできない。 DNAT (Destination Network Address Translation)\nネットワークパケットのヘッダなどに含まれる、送信側と宛先側のアドレスの内、宛先側(目的地、ディスティネーョン)の IP アドレスを変換する方式である。私はこれをまともに使った事がないので細かいことが分からないが、説を見ていろいろなサイトの図解とか見ている限りでは、プライベートIPアドレスを持っている内部 LAN あるサーバにして、外部からグローバル IP などを叩かれて WAN 側に相当するネットワークからパケットが送られてきた場合、内部サーバに宛先アドレスを書き換え、サーバからクライアントに戻る際にはサーバが自身のプライベートIPを送信元ドレスとして応答しているので、それをグローバル IP に書き換えるというような動作になるように見受けられた。単には、SNAT やマスカレードが内部ネットワークから外部ネットワークへのアクセスを想定していたのに対し、DNAT は外部ネットワークから内部ネットワークへのアクセスを想定している形態になっているように見える。DNAT は SNAT やマスカレードとは IP アドレスや、ものによってはポート番号を書き換える点では同じであるが、どんな目的のたにどのように宛先や送信元の情報を書き換えるかは異なるといった印象を受ける。 マスカレード SNAT DNAT IPアドレスを変換する ✅ YES ✅ YES ✅ YES 固定されたIPに置き換える ❌ NO ✅ YES ✅ YES 動的に取得されたIPに置き換える ✅ YES ❌ NO ❌ NO 内部から外部への通信の開始 ✅ YES ✅ YES ❌ NO 外部から内部への通信の開始 ❌ NO ❌ NO ✅ YES 送信元IPを書き換える ✅ YES ✅ YES ❌ NO 宛先IPを書き換える ❌ NO ❌ NO ✅ YES 外部ネットワークの脅威から守る ✅ YES ✅ YES ❌ NO 外部ネットワークからNAT先のサーバに接続させる ❌ NO ❌ NO ✅ YES 転送設定やマスカレード設定 (LANやWAN側のゾーンそれぞれの設定) Firewalldにおいて、ルータ機能を実現するために以下のような設定にした。\nLAN側のゾーンにおいて、forward(転送)の項目を有効化する。 WAN側のゾーンにおいて、masquerade(仮面)の項目を有効化する。 ターゲット設定 Firewalldには、特定ゾーンに入ったパケットをどう処理するか設定項目があり、パケットを破棄するか制御する項目がある。今回は、WAN側からのアクセスの開始を拒絶するために、WAN側のゾーンにはDROPを、LAN側からの内部からのアクセスの開始を許可するためにLAN側のゾーンにはACCEPTを設定した。\n当初はWAN側はゾーン作成時のデフォルトである、defaultを利用していたが、WAN側に見立てたネットワーク側からping したりするとそれが通ってしまう。これでは、IP Scanとかでルータの実態があることが目立ってしまうという状態である。\nまた、以下に示すfirewall-cmdの man ページの説明のように基本的にdefaultターゲットはREJECTターゲットと同じ挙動で要求を破棄するのではなく拒絶し相手に拒絶されたことを伝えて存在を目立たせてしまうことが分かった。defaultターゲットでも、SNATやマスカレード機能として外部からの通信を開始させない目的は達成されるが、まだセキュリティとしては脆弱だと考え、最終的にはサイレントに拒絶されたことも伝えず存在しないかのようにWAN側にはふるまうDROPターゲットを適切だとして、WAN側のゾーンには設定した。\n--permanent [--zone=zone] [--policy=policy] --set-target=target Set the target. For zones target is one of: default, ACCEPT, DROP, REJECT For policies target is one of: CONTINUE, ACCEPT, DROP, REJECT default is similar to REJECT, but it implicitly allows ICMP packets. ACCEPT allows traffic to be forwarded from the zone, either to the same zone or other zones. カーネルパラメーターの設定 Linux環境においては、パケットがルータ化する PC に接続された 2 つ以上の NIC 間を行き来することを許可することがルータ化には必要である。\nsudo sysctl -w net.ipv4.ip_forward=1 sudo sysctl net.ipv4.ip_forward # net.ipv4.ip_forward = 1 確認してみたこと 外部から内部ネットワークにアクセスできないこと WAN 側に見立てた側から内部ネットワークにアクセスできない、pingが通らないことを確認する。 ip a # ... # 2: eno1: \u0026lt;BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP\u0026gt; mtu 1500 qdisc mq state UP group default qlen 1000 # link/ether tt:tt:tt:tt:tt:tt brd ff:ff:ff:ff:ff:ff # inet 192.168.1.CC/24 brd 192.168.1.255 scope global noprefixroute eno1 # valid_lft forever preferred_lft forever # inet6 xxxx::b4c5:7141:xxxx:9580/64 scope link # valid_lft forever preferred_lft forever # ... # でたらめな IP を入力したとき ping 192.168.1.32 # PING 192.168.1.32 (192.168.1.32) 56(84) バイトのデータ # 送信元 192.168.1.CC icmp_seq=1 目的のホストへ届きません。 # 送信元 192.168.1.CC icmp_seq=2 目的のホストへ届きません。 # 送信元 192.168.1.CC icmp_seq=3 目的のホストへ届きません。 # 送信元 192.168.1.CC icmp_seq=4 目的のホストへ届きません。 # 送信元 192.168.1.CC icmp_seq=5 目的のホストへ届きません。 # 送信元 192.168.1.CC icmp_seq=6 目的のホストへ届きません。 # ^C # --- 192.168.1.32 ping 統計 --- # 送信パケット数 7, 受信パケット数 0, +6 エラー, 100% packet loss, time 6127ms # pipe 4 # ルータの WAN 側の IP を入力したとき ping 192.168.1.19 # PING 192.168.1.19 (192.168.1.19) 56(84) バイトのデータ # ^C # --- 192.168.1.19 ping 統計 --- # 送信パケット数 27, 受信パケット数 0, 100% packet loss, time 26615ms # ルータの NAT の先にある LAN 側にあるクライアントに対してアクセスを試みてみるとき ping 192.168.0.34 # PING 192.168.0.34 (192.168.0.34) 56(84) バイトのデータ # ^C # --- 192.168.0.34 ping 統計 --- # 送信パケット数 28, 受信パケット数 0, 100% packet loss, time 27665ms 内部から外部ネットワークへアクセスできること LAN 側に見立てた側から外部ネットワークやグローバルネットワークにアクセスできることを確認し、ブラウジング出来たり、WAN側に見立てたLANネットワーク内部での疎通やサービスが利用可能かを確認する。 ifconfig # イーサネット アダプター Embedded LOM 1 Port 1: # 接続固有の DNS サフィックス . . . . .: # リンクローカル IPv6 アドレス. . . . .: fe80::2971:1249:57ad:9714%15 # IPv4 アドレス . . . . . . . . . . . .: 192.168.0.34 # サブネット マスク . . . . . . . . . .: 255.255.255.0 # デフォルト ゲートウェイ . . . . . . .: 192.168.0.3 # グローバルネットワークへの接続テスト ping google.com # google.com [172.217.211.101]に ping を送信しています 32 バイトのデータ: # 172.217.211.101 からの応答: バイト数 =32 時間 =13ms TTL=114 # 172.217.211.101 からの応答: バイト数 =32 時間 =12ms TTL=114 # 172.217.211.101 からの応答: バイト数 =32 時間 =12ms TTL=114 # 172.217.211.101 からの応答: バイト数 =32 時間 =12ms TTL=114 # # 172.217.211.101 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 12ms、最大 = 13ms、平均 = 12ms # ルータ化したPC自身への接続テスト ping 192.168.0.3 # 192.168.0.3 に ping を送信しています 32 バイトのデータ: # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # 192.168.0.3 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=64 # # 192.168.0.3 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 0ms、最大 = 0ms、平均 = 0ms # WAN 側に見立てた LAN にあるサーバに対しての接続テスト ping 192.168.1.XX # 192.168.1.XX に ping を送信しています 32 バイトのデータ: # 192.168.1.XX からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.XX からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.XX からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.XX からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # # 192.168.1.XX の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 0ms、最大 = 0ms、平均 = 0ms # WAN 側に見立てた LAN を形成するルータへの接続テスト ping 192.168.1.1 # 192.168.1.1 に ping を送信しています 32 バイトのデータ: # 192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 \u0026lt;1ms TTL=63 # 192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=63 # # 192.168.1.1 の ping 統計: # パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 0ms、最大 = 1ms、平均 = 0ms 挙動不審なことや設定漏れをテスト 実際に数日負荷テストをして実用してみる。あえて大きなファイル転送や、こまごまとしたランダムリード的な負荷のかかる使い方をしてみる。 躓いたこと NetworkManager が Firewalld の設定を邪魔する NetworkManager は Firewalld と密接に結びついているらしく、問題が起きることが分かった。私が検証した場合には新しく、WAN と LAN というゾーンを作って、そこにインタフェースを紐づけるために、デフォルトで設定されてインタフェースが紐づけられている Public ゾーンからインターフェースを剥がして、WANやLANのゾーンにインターフェースをくっつける作業をしていた。すると、Firewalldを再起動して設定を反映しようとしたときに NetworkManager に勝手に特定のインターフェースが public ゾーンに紐づけられて設定を戻されてしまうことがあった。\nNetworkMangerが勝手に設定したり操作しないように設定する方法もあるが、今回は単純さと簡単さのために、NetworkManagerが勝手に設定を書き換えて不本意な動作をしないよう、それをアンインストールし、手動でip addr addなどをするスクリプトを書き、自分で必要な設定をルータ化するPCの起動時にSystemdで実行させるようにすることを選んだ。\n感想としては、NetworkManagerはLinux環境をクライアントOSとして使うためには、有効だが、組み込み的な特定の動作を期待して実装していくような用途には向かない気もした。\nFirewalldの--permanentの意味 どこかのサイトとかに書いていたわけでもないが、実際に動かしてみてFirewalldを操作していると、特定の設定項目に関しては、設定の読み出しに関しても--permanentという引数をつける必要があることが分かった。\n私の検証前の--permanentのイメージは、設定を書き換えるときに永続化するというイメージであったが違うようである。例えば特定ゾーンに対して--permanent引数を渡さずにターゲット設定を読みだそうとすると、以下のようなエラーが出る。\nsudo firewall-cmd --zone=WAN --get-target # usage: \u0026#39;firewall-cmd --help\u0026#39; for usage information or see firewall-cmd(1) man page # Option can be used only with --permanent. sudo firewall-cmd --zone=WAN --get-target --permanent # DROP 実際には、Firewalldが動的に動いているメモリ上の設定に対して読み書きする場合には、--permanent引数をつけず、静的に保存されている設定を読み書きする場合には--permanent引数をつけて操作を行うといった認識の方が、正確なように見受けられた。\nちなみにfirewall-cmdの man ページには以下のようなことが書いてあった。読んでいる感じだと直接--permanent引数が、静的な設定を読み書きするか、動的な設定を読み書きするかというスイッチになっていることは直接書かれていないが、--permanent引数が必須かどうかについては、書いてあるようである。\nPermanent Options --permanent The permanent option --permanent can be used to set options permanently. These changes are not effective immediately, only after service restart/reload or system reboot. Without the --permanent option, a change will only be part of the runtime configuration. If you want to make a change in runtime and permanent configuration, use the same call with and without the --permanent option. The --permanent option can be optionally added to all options further down where it is supported. ... [--permanent] [--zone=zone] [--policy=policy] --list-all List everything added or enabled. --permanent [--zone=zone] [--policy=policy] --get-target ... 再起動後にルータとして機能しない ルータ化した PC を完全に再起動すると、正しく機能しない場合があることが分かった。具体的にはnftablesの systemd サービスが有効になっていると、Firewalldだけでなく、/etc/nftables.conf配下にある設定がnftablesの動的な設定に対してfilterというテーブル名で起動時に追加され、ルータ機能を阻害することが分かった。対処としては、nftablesサービスがそもそも起動しないように無効化したりマスクすることがあった。\nsudo systemctl disable nftables sudo systemctl mask nftables 以下は今回問題となった、nftablesデフォルトで付属する/etc/nftables.confの例である。以下が有効になっている場合、Firewalldと合わせてtcpdump -i [LAN側のインターフェース] icmpとしてパケットの流れを監視すると設定に書かれている通りの動作をし、admin-prohibitedと表示され、パケットが拒否される。\n#!/usr/bin/nft -f # vim:set ts=2 sw=2 et: # IPv4/IPv6 Simple \u0026amp; Safe firewall ruleset. # More examples in /usr/share/nftables/ and /usr/share/doc/nftables/examples/. destroy table inet filter table inet filter { chain input { type filter hook input priority filter policy drop ct state invalid drop comment \u0026#34;early drop of invalid connections\u0026#34; ct state {established, related} accept comment \u0026#34;allow tracked connections\u0026#34; iif lo accept comment \u0026#34;allow from loopback\u0026#34; ip protocol icmp accept comment \u0026#34;allow icmp\u0026#34; meta l4proto ipv6-icmp accept comment \u0026#34;allow icmp v6\u0026#34; tcp dport ssh accept comment \u0026#34;allow sshd\u0026#34; pkttype host limit rate 5/second counter reject with icmpx type admin-prohibited counter } chain forward { type filter hook forward priority filter policy drop } } また、Red Had 社の Chapter 40. Using and configuring firewalld | Configuring and managing networking | Red Hat Enterprise Linux | 8 | Red Hat Documentation の解説ページにおいても設定の競合を避けるために、nftablesとFirewalldの systemd サービスを同時に起動する設定にしないように書かれていることを確認した。\nImportant\nTo prevent the different firewall-related services (firewalld, nftables, or iptables) from influencing each other, run only one of them on a RHEL host, and disable the other services.\n関連のある記事 Pihole をインストールする Linux PC に DHCP サーバを立てる 使った画像とか Windows 7(Vista) デフォルトのアイコン ルーター PCのアイコン インターネット的なアイコン ディスプレイのアイコン File:Tux.svg - Wikimedia Commons (lewing@isc.tamu.edu Larry Ewing and The GIMP, CC0, via Wikimedia Commons)\nhttps://commons.wikimedia.org/wiki/File:Tux.svg (2026年2月26日) 参考にしたサイトとか nftables - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Nftables (2026年2月25日)\nWhat is nftables? - nftables wiki\nhttps://wiki.nftables.org/wiki-nftables/index.php/What_is_nftables%3F (2026年2月25日)\nnft(8) — Arch manual pages\nhttps://man.archlinux.org/man/nft.8 (2026年2月25日)\ncentos - Can\u0026rsquo;t remove interface from zone with NetworkManager enabled. - Firewalld / Centos8 - Unix \u0026amp; Linux Stack Exchange\nhttps://unix.stackexchange.com/questions/559980/cant-remove-interface-from-zone-with-networkmanager-enabled-firewalld-cent (2026年2月25日)\nNetwork Namespace と nftables で Source NAT を試す - CUBE SUGAR CONTAINER\nhttps://blog.amedama.jp/entry/netns-nftables-snat (2026年2月25日)\n42.3. nftables を使用した NAT の設定 | ネットワークの設定および管理 | Red Hat Enterprise Linux | 8 | Red Hat Documentation\nhttps://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/configuring-nat-using-nftables_getting-started-with-nftables#configuring-masquerading-using-nftables_configuring-nat-using-nftables (2026年2月25日)\nConfiguring destination NAT nftables entire subnet - Server Fault\nhttps://serverfault.com/questions/1156428/configuring-destination-nat-nftables-entire-subnet (2026年2月25日)\nNetwork Namespace と nftables で Destination NAT を試す - CUBE SUGAR CONTAINER\nhttps://blog.amedama.jp/entry/netns-nftables-dnat (2026年2月25日)\nlinuxのnftables(nft)でルータ機能を作る - それマグで！\nhttps://takuya-1st.hatenablog.jp/entry/2023/06/23/021732 (2026年2月25日)\nWhat does “masquerade” mean exactly? : r/HomeNetworking\nhttps://www.reddit.com/r/HomeNetworking/comments/1cbvyoj/what_does_masquerade_mean_exactly/ (2026年2月25日)\nHow do I request a new IP address from my DHCP server using Ubuntu Server? - Server Fault\nhttps://serverfault.com/questions/24515/how-do-i-request-a-new-ip-address-from-my-dhcp-server-using-ubuntu-server (2026年2月25日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年2月26日)\nNAPT（IPマスカレード / PAT）とは\nhttps://www.infraexpert.com/study/ip11.5.html (2026年2月26日)\nIPマスカレードとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典\nhttps://wa3.i-3-i.info/word11980.html (2026年2月26日)\nBIG-IP - SNAT Pool / AutoMapの設定\nhttps://www.infraexpert.com/infra/bigip31.html (2026年2月26日)\nip nat inside source list - ダイナミックNAT\nhttps://www.infraexpert.com/study/natz1.html (2026年2月26日)\nデスティネーションNATとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典\nhttps://wa3.i-3-i.info/word110634.html (2026年2月26日)\n「DNAT（ダイナミックNAT）」と「DNAT（デスティネーションNAT）」の違い｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典\nhttps://wa3.i-3-i.info/diff981network.html (2026年2月26日)\nUnderstanding Destination NAT - NetEngine AR5700, AR6700, and AR8000 V600R023C00 Configuration Guide - NAT and IPv6 Transition Technologies Configuration - Huawei\nhttps://support.huawei.com/enterprise/en/doc/EDOC1100336498/db0d306d/understanding-destination-nat (2026年2月26日)\n「ソースNAT（SNAT）」と「デスティネーションNAT（DNAT）」の違い｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典\nhttps://wa3.i-3-i.info/diff970network.html (2026年2月26日)\nSource Network Address Translationとは｜「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典\nhttps://wa3.i-3-i.info/word110635.html (2026年2月26日)\nfirewall-cmdの man ページ (2026年2月26日)\nWhat is IP Masquerade?\nhttps://tldp.org/HOWTO/IP-Masquerade-HOWTO/ipmasq-background2.1.html (2026年2月26日)\nArch Linux - firewalld 2.4.0-6 (any)\nhttps://archlinux.org/packages/extra/any/firewalld/ (2026年2月26日)\nArch Linux - dhclient 4.4.3.P1-4 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/dhclient/ (2026年2月26日)\nChapter 40. Using and configuring firewalld | Configuring and managing networking | Red Hat Enterprise Linux | 8 | Red Hat Documentation\nhttps://docs.redhat.com/en/documentation/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/using-and-configuring-firewalld_configuring-and-managing-networking (2026年2月27日)\n","permalink":"https://www.nyanmo.info/posts/linux/routerwithnatandfirewall/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　私が使っている家庭用ルータの挙動が怪しく、時々特定 IP にアクセスできなくなったり、NAT 越えして VPN 接続する際に接続ができなかったりするときがあるなど、安定性に欠けることがあることが分かった。\u003c/p\u003e\n\u003cp\u003e　そこで、使っていないミニ PC に Linux 環境をインストールし、そこで何かしら設定をすれば、ルータ化できるのではないかという話が、Gemini にいろいろ投げつけると出てきたので、実際にそれができるのか検証も兼ねて、自分で設定し試してみた。\u003c/p\u003e\n\u003cp\u003e　そもそも私自身がネットワークについて授業でレポートを作るためなど、単位を取るために軽く触った程度で、実際に自分で使うために運用して体験してみたり、試す実戦経験に疎いところがある。その点も兼ねて今回実際に検証してみて、難しいと思うことに関しては自分なりにノートを取ってみることにしたというのが、この記事を書いた動機である。\u003c/p\u003e\n\u003cp\u003e　\u003cstrong\u003e今回の設定がうまくいかない場合、\u003ca href=\"#%E5%86%8D%E8%B5%B7%E5%8B%95%E5%BE%8C%E3%81%AB%E3%83%AB%E3%83%BC%E3%82%BF%E3%81%A8%E3%81%97%E3%81%A6%E6%A9%9F%E8%83%BD%E3%81%97%E3%81%AA%E3%81%84\"\u003e再起動後にルータとして機能しない\u003c/a\u003e に書いているように、\u003ccode\u003enftables\u003c/code\u003e自体が\u003ccode\u003eFirewalld\u003c/code\u003eの動作に干渉しているかもしれないので確認する。\u003c/strong\u003e\u003c/p\u003e\n\u003ch2 id=\"設定のまとめ\"\u003e設定のまとめ\u003c/h2\u003e\n\u003ch3 id=\"今回の話のネットワーク構成の前提\"\u003e今回の話のネットワーク構成の前提\u003c/h3\u003e\n\u003cp\u003e　いきなり本番環境で動かすのはリスクが高すぎるので、既存の家庭用ルータが形成するLANをWANとして見立てて、そこにぶら下げるようにして今回ルータ化するPCを配置し、実際に動作するか検証する形にした。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/routerWithNATandFirewall/networkArchitecture.png#center\"\n         alt=\"ネットワーク構成図\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"設定の全体像\"\u003e設定の全体像\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --list-all --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLAN; sudo firewall-cmd --list-all --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eWAN\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# LAN (active)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   target: ACCEPT\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   ingress-priority: 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   egress-priority: 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   icmp-block-inversion: no\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   interfaces: [LAN側のインターフェース名]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   sources:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   services: mdns ssh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   ports: 3389/tcp 3389/udp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   protocols:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   forward: yes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   masquerade: no\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   forward-ports:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   source-ports:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   icmp-blocks:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   rich rules:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# WAN (active)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   target: DROP\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   ingress-priority: 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   egress-priority: 0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   icmp-block-inversion: no\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   interfaces: [WAN側のインターフェース名]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   sources:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   services:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   ports:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   protocols:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   forward: no\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   masquerade: yes\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   forward-ports:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   source-ports:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   icmp-blocks:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   rich rules:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo sysctl net.ipv4.ip_forward\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# net.ipv4.ip_forward = 1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip a\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 1: lo: \u0026lt;LOOPBACK,UP,LOWER_UP\u0026gt; mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 127.0.0.1/8 scope host lo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet6 ::1/128 scope host noprefixroute\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 2: [LAN側のインターフェース名]: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UP group default qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 192.168.0.3/24 scope global [LAN側のインターフェース名]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet6 fe80::725a:fff:fe3f:8c93/64 scope link proto kernel_ll\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 4: [WAN側のインターフェース名]: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UP group default # qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/ether yy:yy:yy:yy:yy:yy brd ff:ff:ff:ff:ff:ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 192.168.1.19/24 brd 192.168.1.255 scope global [WAN側のインターフェース名]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet6 fe80::3695:dbff:fe2b:1a6d/64 scope link proto kernel_ll\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"インストールするパッケージ\"\u003eインストールするパッケージ\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eyay -S firewalld net-tools dhclient \n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"具体的なコマンド操作\"\u003e具体的なコマンド操作\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 起動時にfirewalldが起動するようにする\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now firewalld \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# すでに有効化していたり、一時的に立ち上げた状態にしたい場合\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo systemctl start firewalld     \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# NetworkManagerは手動でfirewalldに設定した項目を上書きする可能性があるので使わない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo systemctl disable NetworkManager \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# public ゾーンに紐づけられているインターフェースを確認し引きはがす\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --list-all\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --remove-interface\u003cspan style=\"color:#f92672\"\u003e=[\u003c/span\u003epublicに紐づけられているインターフェース名\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 新しいゾーン LAN と WAN を作成し、\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# LAN側にしてスイッチに接続するインターフェースと、WAN側にして上流の外部ネットワークに接続するインターフェースを紐づける\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --new-zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLAN --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --new-zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eWAN --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLAN --add-interface\u003cspan style=\"color:#f92672\"\u003e=[\u003c/span\u003eLAN側のインターフェース名\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eWAN --add-interface\u003cspan style=\"color:#f92672\"\u003e=[\u003c/span\u003eWAN側のインターフェース名\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 各ゾーンのパケットの扱いを設定\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLAN --set-target\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eACCEPT --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eWAN --set-target\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eDROP --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# LANゾーンにおいて転送、WANゾーンにおいてマスカレード設定の有効化\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efirewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eLAN --add-forward --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efirewall-cmd --zone\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eWAN --add-masquerade --permanent\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 設定を反映\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart firewalld\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"systemd-で起動時に実行する内容-rootinitroutersh\"\u003eSystemd で起動時に実行する内容 (root,\u003ccode\u003einitRouter.sh\u003c/code\u003e)\u003c/h3\u003e\n\u003cp\u003e　※ 保存してスクリプトを作成し終わったら、\u003ccode\u003echmod +x [filename]\u003c/code\u003eで実行権限を付与することを忘れないこと。\u003c/p\u003e","title":"Linux PC をルータ化する"},{"content":"このモデルを作った動機とか キーボードスタンドを立てて使っていたら、壊してしまったので、実物の Logicool K375s の別の足を参考に、3Dプリンターで補修パーツを作ってみた。少しきついが Logicool K270 にも機能する。\nダウンロード STL モデルは Cura では正しいサイズにするために、10倍の大きさにする必要がある可能性がある。\nK375s.blend K375s.stl 3D モデルpreview 実際に取り付けてみた様子 K375s 全体の画像 足を立てた様子 K375s 足をたたんだ様子 K375s 部分的な様子 近くで見た様子 K375s 表からみた様子 K375s 裏からみた様子 K375s K270 足を立てた様子 K270 足をたたんだ様子 K270 近くで見た様子 K270 モデル参考画像 表からみた様子 参考にしたサイトとか 今回は特になし。実物の Logicool K375s の足は参考にした。\n","permalink":"https://www.nyanmo.info/images/3dmodel/logicoolk375sstand/","summary":"\u003ch2 id=\"このモデルを作った動機とか\"\u003eこのモデルを作った動機とか\u003c/h2\u003e\n\u003cp\u003e　キーボードスタンドを立てて使っていたら、壊してしまったので、実物の Logicool K375s の別の足を参考に、3Dプリンターで補修パーツを作ってみた。少しきついが Logicool K270 にも機能する。\u003c/p\u003e\n\u003ch2 id=\"ダウンロード\"\u003eダウンロード\u003c/h2\u003e\n\u003cp\u003e　STL モデルは Cura では正しいサイズにするために、10倍の大きさにする必要がある可能性がある。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/LogicoolK375sStand/K375s.blend\"\u003e\nK375s.blend\n\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/LogicoolK375sStand/K375s.stl\"\u003e\nK375s.stl\n\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"3d-モデルpreview\"\u003e3D モデルpreview\u003c/h2\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"THREEcontainer284513796 column\"\u003e\n    \u003cdiv class=\"mainView\"\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript type=\"module\"\u003e\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n    \n    \n    \n    \n    \n    \n    \n\n    import * as THREE from 'three';\n    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n    \n    \n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n\n    \n    const scene = new THREE.Scene();\n    scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n    scene.add(new THREE.AxesHelper(50))\n\n    \n    const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n    const container = document.querySelector(\".THREEcontainer284513796\")\n    const mainView  = container.querySelector(\".mainView\")\n    const renderer = new THREE.WebGLRenderer();\n    renderer.setSize(screenSize.width,screenSize.height);\n    renderer.shadowMap.enabled = true;\n    mainView.appendChild( renderer.domElement );\n    \n    \n    const controls = new OrbitControls(camera, renderer.domElement)\n    controls.enableDamping = true\n\n\n    \n    const buttons = container.querySelector(\".MMDcontroler.column\")\n    const fullscreen = buttons.querySelector(\"#fullscreen\")\n\n    fullscreen.addEventListener(\"click\", () =\u003e {\n        mainView.requestFullscreen()\n    })\n\n    mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n        let width = 0\n        let height = 0\n        if(document.fullscreenElement){\n            width   = window.innerWidth\n            height  = window.outerHeight\n            \n            \n            \n        }else{\n            width   = screenSize.width\n            height  = screenSize.height\n            \n        }\n        \n        \n        console.log(width)\n        console.log(height)\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(width, height);\n        \n        camera.aspect = width / height;\n        camera.updateProjectionMatrix();\n        \n    })\n    \n\n\n    \n    const loader = new GLTFLoader();\n    loader.load( '\\/images\\/3Dmodel\\/LogicoolK375sStand\\/K375s.glb', function (gltf) {        \n        gltf.scene.position.x = Number(\"20\")\n        gltf.scene.position.y = Number(\"20\")\n        gltf.scene.position.z = Number(\"20\")\n        gltf.scene.rotation.x = Math.PI * Number(\"90\") / 180.0\n        gltf.scene.rotation.y = Math.PI * Number(\"0\") / 180.0\n        gltf.scene.rotation.z = Math.PI * Number(\"0\") / 180.0\n        gltf.scene.scale.x = Number(\"6\")\n        gltf.scene.scale.y = Number(\"6\")\n        gltf.scene.scale.z = Number(\"6\")\n\n        scene.add( gltf.scene )\n    }, undefined, function ( error ) {\n        console.error( error );\n    } );\n\n\n\n    \n    let lightPosOffset = Number(\"200\")\n    const lightPos = [\n        {x:0,y:0,z:0},\n\n        {x:lightPosOffset,y:0 ,z:0},\n        {x:-lightPosOffset,y:0 ,z:0},\n\n        {x:0,y:lightPosOffset ,z:0},\n        {x:0,y:-lightPosOffset ,z:0},\n\n        {x:0,y:0 ,z:lightPosOffset},\n        {x:0,y:0 ,z:-lightPosOffset},\n\n        {x:0,y:lightPosOffset ,z:lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:lightPosOffset},\n        {x:0,y:lightPosOffset ,z:-lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:lightPosOffset,y:0 ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:lightPosOffset ,z:0},\n        {x:lightPosOffset,y:-lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:0},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n    ] \n\n    \n    const color = 0xFFFFFF;\n    const intensity = Number(\"0.2\");\n    for(let pos of lightPos){\n        let light =  new THREE.DirectionalLight(color, intensity);\n        light.position.set(pos.x, pos.y,pos.z);\n        scene.add(light);\n    }\n\n\n\n    \n    \n    camera.position.set(\n        Number(\"21\"),\n        Number(\"22\"),\n        Number(\"35\")\n    )\n    controls.target.set(\n        Number(\"19\"),\n        Number(\"20\"),\n        Number(\"0\")\n    )\n\n\n\n    \n    function animate() {\n        renderer.render( scene, camera );\n        controls.update()\n    }\n    renderer.setAnimationLoop( animate );\n\u003c/script\u003e\u003c/p\u003e","title":"Logicool K375s キーボードの足"},{"content":"この記事を作った動機 最近ちょっとした JavaScript のツールを作って使おうとしたところ、直接 HTML の文字列を innerHTML として渡すことができないことが分かった。\n今の私の理解だと XSS(Cross Site Scripting) 対策のためにテキストデータとして紛れた悪意のある CSS や JavaScript コードなどを実行(反映)しないようにするために、追加された仕組みに引っかかったという認識である。\u0026ldquo;ポリシー\u0026quot;なるものを定義して、innerHTMLとかに設定されるテキストデータであったHTMLの文字列などを、事前に任意に定義した createHTML などの関数を通して、テキストデータの HTML化などを承認？するような動作を実装する必要があるというイメージである。\nエラー内容 function setStyle(){ let style = document.createElement(\u0026#34;style\u0026#34;) style.innerHTML = ` .positive{ background: red; text-decoration: underline; } .negative{ background: blue; text-decoration: underline; } ` document.body.appendChild(style) } setStyle() // This document requires \u0026#39;TrustedHTML\u0026#39; assignment. The action has been blocked. 暫定的な対処 以下はとにかく、自分で書いたスクリプトをすぐ動かしたい場合で、動作検証やプライベート目的で、理解したうえで利用することを想定したコード例であり、実用ではセキュリティの問題になるので真面目に悪意のあるコードが実行されないように createHTML などの定義を書く必要がある。\nconst policy = trustedTypes.createPolicy(\u0026#34;my-policy\u0026#34;, { createHTML: (s) =\u0026gt; s, createScript: (s) =\u0026gt; s, }); function setStyle(){ let style = document.createElement(\u0026#34;style\u0026#34;) style.innerHTML = policy.createHTML(` .positive{ background: red; text-decoration: underline; } .negative{ background: blue; text-decoration: underline; } `) document.body.appendChild(style) } setStyle() 参考にしたサイトとか This document requires \u0026lsquo;TrustedHTML\u0026rsquo; assignment. · Issue #482 · killergerbah/asbplayer\nhttps://github.com/killergerbah/asbplayer/issues/482 (2026年2月18日) asbplayer/extension/src/pages/youtube-page.ts at dd5f49f3ab97cd5b1eefa2cde113704a125e69b5 · killergerbah/asbplayer\nhttps://github.com/killergerbah/asbplayer/blob/dd5f49f3ab97cd5b1eefa2cde113704a125e69b5/extension/src/pages/youtube-page.ts#L18 (2026年2月18日) TrustedTypePolicyFactory: createPolicy() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicyFactory/createPolicy (2026年2月18日) TrustedTypePolicy - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy (2026年2月18日) Trusted Types API - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API (2026年2月18日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/avoidtrustedtype/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近ちょっとした JavaScript のツールを作って使おうとしたところ、直接 HTML の文字列を innerHTML として渡すことができないことが分かった。\u003c/p\u003e\n\u003cp\u003e　今の私の理解だと XSS(Cross Site Scripting) 対策のためにテキストデータとして紛れた悪意のある CSS や JavaScript コードなどを実行(反映)しないようにするために、追加された仕組みに引っかかったという認識である。\u0026ldquo;ポリシー\u0026quot;なるものを定義して、innerHTMLとかに設定されるテキストデータであったHTMLの文字列などを、事前に任意に定義した createHTML などの関数を通して、テキストデータの HTML化などを承認？するような動作を実装する必要があるというイメージである。\u003c/p\u003e\n\u003ch2 id=\"エラー内容\"\u003eエラー内容\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e document.\u003cspan style=\"color:#a6e22e\"\u003ecreateElement\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;style\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einnerHTML\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e`\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    .positive{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        background: red;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        text-decoration: underline;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    .negative{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        background: blue;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        text-decoration: underline;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    `\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    document.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappendChild\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This document requires \u0026#39;TrustedHTML\u0026#39; assignment. The action has been blocked.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"暫定的な対処\"\u003e暫定的な対処\u003c/h2\u003e\n\u003cp\u003e　以下はとにかく、自分で書いたスクリプトをすぐ動かしたい場合で、動作検証やプライベート目的で、理解したうえで利用することを想定したコード例であり、実用ではセキュリティの問題になるので真面目に悪意のあるコードが実行されないように \u003ccode\u003ecreateHTML\u003c/code\u003e などの定義を書く必要がある。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epolicy\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etrustedTypes\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreatePolicy\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;my-policy\u0026#34;\u003c/span\u003e, {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecreateHTML\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecreateScript\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e});\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e document.\u003cspan style=\"color:#a6e22e\"\u003ecreateElement\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;style\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einnerHTML\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epolicy\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecreateHTML\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e`\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    .positive{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        background: red;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        text-decoration: underline;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    .negative{\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        background: blue;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e        text-decoration: underline;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    `\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    document.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappendChild\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eThis document requires \u0026lsquo;TrustedHTML\u0026rsquo; assignment. · Issue #482 · killergerbah/asbplayer\u003cbr\u003e\n\u003ca href=\"https://github.com/killergerbah/asbplayer/issues/482\"\u003ehttps://github.com/killergerbah/asbplayer/issues/482\u003c/a\u003e (2026年2月18日)\u003c/li\u003e\n\u003cli\u003easbplayer/extension/src/pages/youtube-page.ts at dd5f49f3ab97cd5b1eefa2cde113704a125e69b5 · killergerbah/asbplayer\u003cbr\u003e\n\u003ca href=\"https://github.com/killergerbah/asbplayer/blob/dd5f49f3ab97cd5b1eefa2cde113704a125e69b5/extension/src/pages/youtube-page.ts#L18\"\u003ehttps://github.com/killergerbah/asbplayer/blob/dd5f49f3ab97cd5b1eefa2cde113704a125e69b5/extension/src/pages/youtube-page.ts#L18\u003c/a\u003e (2026年2月18日)\u003c/li\u003e\n\u003cli\u003eTrustedTypePolicyFactory: createPolicy() method - Web APIs | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicyFactory/createPolicy\"\u003ehttps://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicyFactory/createPolicy\u003c/a\u003e (2026年2月18日)\u003c/li\u003e\n\u003cli\u003eTrustedTypePolicy - Web APIs | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy\"\u003ehttps://developer.mozilla.org/en-US/docs/Web/API/TrustedTypePolicy\u003c/a\u003e (2026年2月18日)\u003c/li\u003e\n\u003cli\u003eTrusted Types API - Web APIs | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API\"\u003ehttps://developer.mozilla.org/en-US/docs/Web/API/Trusted_Types_API\u003c/a\u003e (2026年2月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Trusted Type 関連でエラーが出て、思う様にスクリプトを実行できない"},{"content":"この記事を作った動機 Microsoft が強制的に Windows Update をさせようとすることでPCの電源メニューのところについて、無効化する話題がたまたま見つかり、私も強制アプデは嫌なので自分用に記録を取る。\n設定方法 レジストリエディタを開く Computer\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\WindowsUpdate\\Orchestratorを開く 日本語環境ではコンピューター\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\WindowsUpdate\\Orchestratorになる。 ShutdownFlyoutOptionsを0に設定する レジストリの値を保存する Microsoft は強引に設定した値を戻すことがあるので、設定したレジストリ値を保存しておくことを推奨する。一度保存したら、PCの電源項目がおかしくなった時、保存したレジストリのファイルをクリックして設定しなおすだけである。 検証内容 The Ultimate Fix for a Forced Windows Update - YouTubeの内容が本当かどうか仮想マシンに新規インストールした Windows 11 Pro (25H2)で検証してみた。ShutdownFlyoutOptionsについて以下の設定値を試した。\n16/10進数併記 (2進数4桁) 試したこと \u0026lt;- 表記例 0 (0000) すべて無効 1 (0001) 通常再起動 2 (0010) 更新して再起動 4 (0100) 通常シャットダウン 8 (1000) 更新してシャットダウン 0 (0000) すべて無効 1 (0001) 通常再起動 2 (0010) 更新して再起動 4 (0100) 通常シャットダウン 8 (1000) 更新してシャットダウン 他の方法 強制アプデ回避を行う他の方法にはコマンドプロンプトから再起動やシャットダウンを行う方法があると思われる。ただ今回用意した仮想環境 Windows 11 Pro (25H2) では、これだと強制的に更新がかかってしまったため、必ずしも有効なわけではないようである。\nシャットダウン shutdown /s /t 0 再起動 shutdown /r /t 0 参考にしたサイトとか The Ultimate Fix for a Forced Windows Update - YouTube\nhttps://www.youtube.com/watch?v=cz-M6cWlrdo\u0026amp;t=124 (2026年2月16日) shutdown | Microsoft Learn\nhttps://learn.microsoft.com/en-us/windows-server/administration/windows-commands/shutdown (2026年2月16日) ","permalink":"https://www.nyanmo.info/posts/windows/disableforcedupdateonwin11/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Microsoft が強制的に Windows Update をさせようとすることでPCの電源メニューのところについて、無効化する話題がたまたま見つかり、私も強制アプデは嫌なので自分用に記録を取る。\u003c/p\u003e\n\u003ch2 id=\"設定方法\"\u003e設定方法\u003c/h2\u003e\n\u003ch3 id=\"レジストリエディタを開く\"\u003eレジストリエディタを開く\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/openRegedit.png#center\"\n         alt=\"レジストリエディタを開く\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"computerhkey_local_machinesoftwaremicrosoftwindowsupdateorchestratorを開く\"\u003e\u003ccode\u003eComputer\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\WindowsUpdate\\Orchestrator\u003c/code\u003eを開く\u003c/h3\u003e\n\u003cp\u003e　日本語環境では\u003ccode\u003eコンピューター\\HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\WindowsUpdate\\Orchestrator\u003c/code\u003eになる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/%e8%a8%ad%e5%ae%9a%e3%81%95%e3%82%8c%e3%81%9f%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e5%80%a4.png#center\"\n         alt=\"設定されたレジストリ値\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"shutdownflyoutoptionsを0に設定する\"\u003e\u003ccode\u003eShutdownFlyoutOptions\u003c/code\u003eを\u003ccode\u003e0\u003c/code\u003eに設定する\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/ShutdownFlyoutOptions.png#center\"\n         alt=\"ShutdownFlyoutOptionsを0\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"レジストリの値を保存する\"\u003eレジストリの値を保存する\u003c/h2\u003e\n\u003cp\u003e　Microsoft は強引に設定した値を戻すことがあるので、設定したレジストリ値を保存しておくことを推奨する。一度保存したら、PCの電源項目がおかしくなった時、保存したレジストリのファイルをクリックして設定しなおすだけである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/%e3%82%a8%e3%82%af%e3%82%b9%e3%83%9d%e3%83%bc%e3%83%88.png#center\"\n         alt=\"レジストリの値をエクスポートする\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/%e8%a8%ad%e5%ae%9a%e3%81%95%e3%82%8c%e3%81%9f%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e5%80%a4%20-%20%e3%82%b3%e3%83%94%e3%83%bc.png#center\"\n         alt=\"エクスポートされたレジストリ\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"検証内容\"\u003e検証内容\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.youtube.com/watch?v=cz-M6cWlrdo\u0026amp;t=124\"\u003eThe Ultimate Fix for a Forced Windows Update - YouTube\u003c/a\u003eの内容が本当かどうか仮想マシンに新規インストールした Windows 11 Pro (25H2)で検証してみた。\u003ccode\u003eShutdownFlyoutOptions\u003c/code\u003eについて以下の設定値を試した。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e16/10進数併記 (2進数4桁) 試したこと \u0026lt;- 表記例\u003c/li\u003e\n\u003cli\u003e0 (0000) すべて無効\u003c/li\u003e\n\u003cli\u003e1 (0001) 通常再起動\u003c/li\u003e\n\u003cli\u003e2 (0010) 更新して再起動\u003c/li\u003e\n\u003cli\u003e4 (0100) 通常シャットダウン\u003c/li\u003e\n\u003cli\u003e8 (1000) 更新してシャットダウン\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"0-0000-すべて無効\"\u003e0 (0000) すべて無効\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/0000.png#center\"\n         alt=\"ShutdownFlyoutOptions 0000\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"1-0001-通常再起動\"\u003e1 (0001) 通常再起動\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/0001.png#center\"\n         alt=\"ShutdownFlyoutOptions 0001\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"2-0010-更新して再起動\"\u003e2 (0010) 更新して再起動\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/0010.png#center\"\n         alt=\"ShutdownFlyoutOptions 0010\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"4-0100-通常シャットダウン\"\u003e4 (0100) 通常シャットダウン\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/0100.png#center\"\n         alt=\"ShutdownFlyoutOptions 0100\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"8-1000-更新してシャットダウン\"\u003e8 (1000) 更新してシャットダウン\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/disableForcedUpdateOnWin11/1000.png#center\"\n         alt=\"ShutdownFlyoutOptions 1000\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"他の方法\"\u003e他の方法\u003c/h2\u003e\n\u003cp\u003e　強制アプデ回避を行う他の方法にはコマンドプロンプトから再起動やシャットダウンを行う方法があると思われる。ただ今回用意した仮想環境 Windows 11 Pro (25H2) では、これだと強制的に更新がかかってしまったため、必ずしも有効なわけではないようである。\u003c/p\u003e","title":"Windows 11 の強制アプデの無効化"},{"content":"この記事を作った動機 LinuxクライアントからWindows側にRDP接続などをするとき、いちいちIPアドレスを直接入力しているのは気持ち悪いと思っていた。今まではそれでいいやと放置していたが、最近いい加減どうにかしようということで、具体的な解決を試みようと思って、案の定手間取ったので記録する。\n具体的には、mDNSを使って、Linuxクライアント側から、WindowsクライアントのプライベートIPアドレスを割り出したいということをしていた。基本的には以下のポイントがあった。\nファイアウォールの設定で、mDNSを受け付けるようになっているか？ Linuxクライアントに必要なパッケージがインストールされ、必要なデーモンが動いているか？ 接続先対象としてのWindows側のホスト名は間違っていないか？ Linux側から名前解決を試みるとき、.localのTLDをつけ忘れていないか？ 環境 前提としては、個人的なLAN内での利用を想定している。今回は、パブリックネットワーク向けのセキュリティー重視という観点では書いていない。\nまた重要な前提として、接続先と接続元は、同じプライベートネットワークに属していることとする。\n接続先 (Windows) Windows 11 24H2 を使っている 接続元 (Linux) NetworkManger を使っている systemd-resolved を使っていない、無効にしている GNOME 環境 arch linux 環境 仮定 今回は説明のために以下の仮定をしている。Linux側に関しては、/etc/hostnameにすでに適切なホスト名が設定されているという前提である。\nWindows側 ホスト名:\nWinHost IPアドレス\n192.168.1.33 Linux側 ホスト名:\nLinuxHost IPアドレス\n192.168.1.55 設定手順 Windows側 (接続される側、mDNSで名前解決される側) ファイアウォールの設定を確認する 今回はmDNSだけでなく、そもそも接続されているか確認するために、pingも通るように設定する。 ネットワーク探索が無効になっていないか確認する Linux側 (接続を試みる側、mDNSで名前解決をしようとする側) パッケージのインストール yay -S avahi nss-mdns # pacman -S avahi nss-mdns デーモンの有効化 sudo systemctl enable --now avahi-daemon.service /etc/nsswitch.confを設定する 以下はAvahi - ArchWikiを参考に設定した一部の例である。今回は IPv4 を対象として、mdns4_minimalを指定した。試してはいないが、mdns_minimal、mdns、mdns6_minimal(IPv6)としても、Avahi - ArchWikiを見る限り設定できる模様である。\n... hosts: mymachines mdns4_minimal [NOTFOUND=return] resolve [!UNAVAIL=return] files myhostname dns wins ... mDNS をファイアウォールから許可する 今回は検証のために逆方向からも mDNS で名前解決するテストを行ったため、ポートを開ける。\n# 必要であれば、--zone=[ゾーン名] も指定すること sudo firewall-cmd --add-service=mdns sudo firewall-cmd --add-service=mdns --permanent mDNSの動作確認 異なるホスト間だけではなく、動作確認として、LinuxHost -\u0026gt; LinuxHost や WinHost -\u0026gt; WinHost 間といった同じホスト間でもテストしてみると良いと思われる。また、異なるホスト間において、そもそもpingコマンドで疎通が取れるかも確認すると良いと思われる。\nLinuxHost -\u0026gt; WinHost 成功例 avahi-resolve -4 -n WinHost.local # WinHost.local\t192.168.1.33 ping WinHost.local # PING WinHost.local (192.168.1.33) 56(84) bytes of data. # 64 bytes from 192.168.1.33: icmp_seq=1 ttl=128 time=1.85 ms # 64 bytes from 192.168.1.33: icmp_seq=2 ttl=128 time=1.62 ms # ^C # --- WinHost.local ping statistics --- # 2 packets transmitted, 2 received, 0% packet loss, time 1001ms # rtt min/avg/max/mdev = 1.617/1.734/1.852/0.117 ms 失敗例 avahi-resolve -4 -n WinHost.local # Failed to resolve host name \u0026#39;WinHost.local\u0026#39;: Timeout reached ping -4 WinHost.local # ping: WinHost.local: Name or service not known WinHost -\u0026gt; LinuxHost 成功例 Resolve-DnsName -Name LinuxHost -Type ALL # Name Type TTL Section IPAddress # ---- ---- --- ------- --------- # LinuxHost.local AAAA 120 Answer xxxx::xxxx:xxxx:xxxx:xxxx # LinuxHost.local A 120 Answer 192.168.1.55 ping LinuxHost -4 # LinuxHost.local [192.168.1.55]に ping を送信しています 32 バイトのデータ: # 192.168.1.55 からの応答: バイト数 =32 時間 =1ms TTL=64 # 192.168.1.55 からの応答: バイト数 =32 時間 =1ms TTL=64 # # 192.168.1.55 の ping 統計: # パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、 # ラウンド トリップの概算時間 (ミリ秒): # 最小 = 1ms、最大 = 1ms、平均 = 1ms # Ctrl+C 失敗例 Resolve-DnsName -Name LinuxHost -Type ALL # Resolve-DnsName : LinuxHost : ファイル名、ディレクトリ名、またはボリューム ラベルの構文が間違っています。 # 発生場所 行:1 文字:1 # + Resolve-DnsName -Name LinuxHost -Type ALL # + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + CategoryInfo : ResourceUnavailable: (LinuxHost:String) [Resolve-DnsName], Win32Exception # + FullyQualifiedErrorId : ERROR_INVALID_NAME,Microsoft.DnsClient.Commands.ResolveDnsName ping LinuxHost -4 # ping 要求ではホスト LinuxHost が見つかりませんでした。ホスト名を確認してもう一度実行してください。 躓いたところ 今回私が作業するにあたって引っかかり記録に残したいことについては、以下に記録することにする。\navahi-resolveでは名前解決できるのに、pingできない nss-mdnsがインストールされていない場合に、以下のようなエラーになった。/etc/nsswitch.confで、hostsの項目にmdns4_minimalを含めたにもかかわらず、名前解決に失敗する。\nping -4 A.local # ping: A.local: System error 私の場合は、nss-mdnsをインストールすることで解決されたように思われる。\nyay -S nss-mdns # pacman -S nss-mdns 参考にしたサイトとか Avahi - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Avahi (2026年1月18日) avahi - What is mDNS? Is it possible to make mDNS query without mdns service running? - Ask Ubuntu\nhttps://askubuntu.com/questions/972630/what-is-mdns-is-it-possible-to-make-mdns-query-without-mdns-service-running (2026年1月18日) Resolve-DnsName (DnsClient) | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/powershell/module/dnsclient/resolve-dnsname?view=windowsserver2022-ps (2026年1月18日) Google Gemini\nhttps://gemini.google.com/app (2026年1月18日) Samba - ArchWiki\nhttps://wiki.archlinux.org/title/Samba (2026年1月18日) dns - How can I perform an mDNS lookup on Windows? - Super User\nhttps://superuser.com/questions/1837493/how-can-i-perform-an-mdns-lookup-on-windows (2026年1月18日) Arch Linux - avahi 1:0.9rc2-3 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/avahi/ (2026年1月18日) Arch Linux - nss-mdns 0.15.1-2 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/nss-mdns/ (2026年1月18日) ","permalink":"https://www.nyanmo.info/posts/linux/windowsnameresolveonlinuxclient/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　LinuxクライアントからWindows側にRDP接続などをするとき、いちいちIPアドレスを直接入力しているのは気持ち悪いと思っていた。今まではそれでいいやと放置していたが、最近いい加減どうにかしようということで、具体的な解決を試みようと思って、案の定手間取ったので記録する。\u003c/p\u003e\n\u003cp\u003e　具体的には、mDNSを使って、Linuxクライアント側から、WindowsクライアントのプライベートIPアドレスを割り出したいということをしていた。基本的には以下のポイントがあった。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eファイアウォールの設定で、mDNSを受け付けるようになっているか？\u003c/li\u003e\n\u003cli\u003eLinuxクライアントに必要なパッケージがインストールされ、必要なデーモンが動いているか？\u003c/li\u003e\n\u003cli\u003e接続先対象としてのWindows側のホスト名は間違っていないか？\u003c/li\u003e\n\u003cli\u003eLinux側から名前解決を試みるとき、\u003ccode\u003e.local\u003c/code\u003eのTLDをつけ忘れていないか？\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cp\u003e　前提としては、個人的なLAN内での利用を想定している。今回は、パブリックネットワーク向けのセキュリティー重視という観点では書いていない。\u003c/p\u003e\n\u003cp\u003e　また重要な前提として、接続先と接続元は、同じプライベートネットワークに属していることとする。\u003c/p\u003e\n\u003ch3 id=\"接続先-windows\"\u003e接続先 (Windows)\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eWindows 11 24H2 を使っている\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"接続元-linux\"\u003e接続元 (Linux)\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eNetworkManger を使っている\u003c/li\u003e\n\u003cli\u003esystemd-resolved を使っていない、無効にしている\u003c/li\u003e\n\u003cli\u003eGNOME 環境\u003c/li\u003e\n\u003cli\u003earch linux 環境\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"仮定\"\u003e仮定\u003c/h2\u003e\n\u003cp\u003e　今回は説明のために以下の仮定をしている。Linux側に関しては、\u003ccode\u003e/etc/hostname\u003c/code\u003eにすでに適切なホスト名が設定されているという前提である。\u003c/p\u003e\n\u003ch3 id=\"windows側\"\u003eWindows側\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eホスト名:\u003cbr\u003e\nWinHost\u003c/li\u003e\n\u003cli\u003eIPアドレス\u003cbr\u003e\n192.168.1.33\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"linux側\"\u003eLinux側\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eホスト名:\u003cbr\u003e\nLinuxHost\u003c/li\u003e\n\u003cli\u003eIPアドレス\u003cbr\u003e\n192.168.1.55\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"設定手順\"\u003e設定手順\u003c/h2\u003e\n\u003ch3 id=\"windows側-接続される側mdnsで名前解決される側\"\u003eWindows側 (接続される側、mDNSで名前解決される側)\u003c/h3\u003e\n\u003ch4 id=\"ファイアウォールの設定を確認する\"\u003eファイアウォールの設定を確認する\u003c/h4\u003e\n\u003cp\u003e　今回はmDNSだけでなく、そもそも接続されているか確認するために、pingも通るように設定する。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/windowsNameResolveOnLinuxClient/Win-%e3%83%95%e3%82%a1%e3%82%a4%e3%82%a2%e3%82%a6%e3%82%a9%e3%83%bc%e3%83%ab%e8%a8%ad%e5%ae%9a%e4%be%8b-mDNS.png#center\"\n         alt=\"Win-ファイアウォール設定例-mDNS\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/windowsNameResolveOnLinuxClient/Win-%e3%83%95%e3%82%a1%e3%82%a4%e3%82%a2%e3%82%a6%e3%82%a9%e3%83%bc%e3%83%ab%e8%a8%ad%e5%ae%9a%e4%be%8b-PING.png#center\"\n         alt=\"Win-ファイアウォール設定例-PING\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"ネットワーク探索が無効になっていないか確認する\"\u003eネットワーク探索が無効になっていないか確認する\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/windowsNameResolveOnLinuxClient/Win-%e5%85%b1%e6%9c%89%e8%a8%ad%e5%ae%9a.png#center\"\n         alt=\"Win-共有設定\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"linux側-接続を試みる側mdnsで名前解決をしようとする側\"\u003eLinux側 (接続を試みる側、mDNSで名前解決をしようとする側)\u003c/h3\u003e\n\u003ch4 id=\"パッケージのインストール\"\u003eパッケージのインストール\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S avahi nss-mdns\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# pacman -S avahi nss-mdns\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"デーモンの有効化\"\u003eデーモンの有効化\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now avahi-daemon.service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"etcnsswitchconfを設定する\"\u003e\u003ccode\u003e/etc/nsswitch.conf\u003c/code\u003eを設定する\u003c/h4\u003e\n\u003cp\u003e　以下は\u003ca href=\"https://wiki.archlinux.org/title/Avahi\"\u003eAvahi - ArchWiki\u003c/a\u003eを参考に設定した一部の例である。今回は IPv4 を対象として、\u003ccode\u003emdns4_minimal\u003c/code\u003eを指定した。試してはいないが、\u003ccode\u003emdns_minimal\u003c/code\u003e、\u003ccode\u003emdns\u003c/code\u003e、\u003ccode\u003emdns6_minimal\u003c/code\u003e(IPv6)としても、\u003ca href=\"https://wiki.archlinux.org/title/Avahi\"\u003eAvahi - ArchWiki\u003c/a\u003eを見る限り設定できる模様である。\u003c/p\u003e","title":"mDNSでwindowsに対してlinuxクライアントから名前解決をしたい"},{"content":"この記事を作った動機 最近元々 Windows が入っていたPCに対しても、linux環境に乗り換えるようになった過程で、Nvidia 製の GPU である Quadro M620 に対して、プロプライエタリな Nvidia社が提供しているドライバをインストールしようとしたところ問題が発生したため、具体的に何をしたか記録を取る。\n基本的に今回起こった問題としては、aur から Nvidia のプロプライエタリなドライバを導入しただけでは設定不足で、正しく起動できず、カーネルなどを読み込み終わったあとに、画面が切り替わろうとするとき、解像度がおかしくなったり、画面が映らなくなったり、ケーブルを抜き差しすることで突然映るようになったりという挙動になった。\n問題が何なのか調べたりLLM(Gemini)に投げつけたりしたところ、initramfsで起動する段階で Nvidiaのドライバを読み込んでないと、その後の起動後にディスプレイの EDID の情報が正しく読み込めないのではないかということが分かった。これは、起動時には画面が映らなかったり解像度がおかしい状態になることと、ケーブルを抜き差しすると映るようになることからも、起動時に Nvidia のモジュールがロードされていなかった場合に、その後の初期化フェーズで Nvidia のドライバが読み込まれても提携できてないということで、説明がつくように思われる。\nちなみに設定不足のときに、dmesgでカーネルのメッセージを見ると以下のようなエラーが出ていた。\ndmesg | grep nvidia ... R* [nvidia-drm] [GPU ID 0x00000100] Failed to add encoder for NvKmsKapiDisplay 0x00000001 ... 環境 環境 System Details Report Report details Date generated: 2026-01-17 20:53:19 Hardware Information: Hardware Model: HP HP Z2 Mini G3 Workstation Memory: 16.0 GiB Processor: Intel® Xeon® E3-1225 v5 × 4 Graphics: Quadro M620 Disk Capacity: 512.1 GB Software Information: Firmware Version: N53 Ver. 01.91 OS Name: Arch Linux OS Build: (null) OS Type: 64-bit GNOME Version: 49 Windowing System: Wayland Kernel Version: Linux 6.18.5-arch1-1 内容 aur からドライバをインストール yay -S nvidia :: There are 12 providers available for nvidia: :: Repository AUR 1) nvidia-525xx 2) nvidia-525xx-dkms 3) nvidia-535xx-dkms 4) nvidia-550xx-dkms 5) nvidia-575xx-dkms 6) nvidia-580xx-dkms 7) nvidia-beta 8) nvidia-beta-dkms 9) nvidia-tesla-dkms 10) nvidia-vulkan 11) nvidia-vulkan-dkms 12) nvidia-vulkan-open Enter a number (default=1): ==\u0026gt; 6 ... yay -S lib32-nvidia-580xx-utils gurb を設定する(/etc/default/grub) ... GRUB_CMDLINE_LINUX_DEFAULT=\u0026#34;loglevel=3 nvidia-drm.modeset=1\u0026#34; ... grub-mkconfig -o /path/to/grub.cfg initramfs を設定する(/etc/mkinitcpio.conf) ... MODULES=(nvidia nvidia_modeset nvidia_uvm nvidia_drm) ... initramfs を再生成させる sudo mkinitcpio -P nvidia-persistencedを有効にする sudo systemctl enable --now nvidia-persistenced 再起動する 設定がうまく行っていれば、起動するはずである。うまく行かなかったときは、ディスプレイのケーブルを抜き差しして見たりしてから強制的に電源を切ったりする。起動前の grub の画面で e キーを押して、カーネルパラメータ(nvidia_drm.modeset nvidia_drm.fbdev)などがおかしくないか確認したりする。最悪ライブ環境でUSBなどから起動し、自分で再設定する必要がある。\nOpenGLを使ったアプリが軒並み安定しない(2026/1/21追記) どうも、nvidia-580xx-dkmsが、最後のGTX900番代のアーキテクチャに対応したドライバになるらしいが、Wayland + GNOMEの環境において、OpenGLを使ったアプリをXwayland環境で起動させると、不安定でクラッシュすることが分かった。具体的には、ウィンドウを最大化したり、連続してリサイズしまくると、ある時点で安定性を失ってGPUに対して存在していた描画プロセスが再起動を繰り返したあと、諦めてクラッシュという感じになった。クラッシュする直前には描画が止まって固まるという現象になる。\nそこで、他のバージョンのドライバとかを試していたが、結局nvidia-580xx-dkms以上に安定したものはなく、かつ最新のnvidia-bata(590)などでは、サポートがないということで、八方塞がりであった。ただ、blenderでvulkanをバックエンドに指定すると、とりあえず使える程度に、状況が改善し、ウィンドウをリサイズしたり、最大化してもクラッシュしにくくなることが分かった。\nそしてその経緯をGeminiに投げつけたり、調べたりしたところMESA_LOADER_DRIVER_OVERRIDE=zinkとして環境変数を指定し、OpenGLの描画にVulkanを使うようにするという方法があることがわかり、試していた。以下は環境変数の例として、/etc/environmentの例を示したものである。ちなみに__GLX_VENDOR_LIBRARY_NAME=mesaは指定すると、OpenGLのアプリがクラッシュしたときOSごと巻き込まれて固まることが分かったためコメントアウトしてある。\n試したところ、MESA_LOADER_DRIVER_OVERRIDE=zinkは多少効果がありそうで、体感は緩和にはなっている気がするが、問題の解消にはなっていない印象である。他にはCPUだけで動くようにしてGPUの補助を切ってしまうことも手段としてはあるらしいが、そこまではめんどくさくて試していない。MSTの件でもう疲れてしまった。\n# cat environment # # This file is parsed by pam_env module # # Syntax: simple \u0026#34;KEY=VAL\u0026#34; pairs on separate lines # GTK_IM_MODULE=fcitx5 QT_IM_MODULE=fcitx5 XMODIFIERS=@im=fcitx5 MUTTER_DEBUG_KMS_THREAD_TYPE=user WGPU_BACKEND=GL GSK_RENDERER=ngl #__GLX_VENDOR_LIBRARY_NAME=mesa MESA_LOADER_DRIVER_OVERRIDE=zink 基本的には正直 Radeon や Intel Arcなどに移行したほうがlinuxはたしかに良さそうである。nvidiaに関しては、RTX以降はしばらくサポートあるようだが、個人的な感想としては壊れやすく、それはそれで安定しなさそうな印象が先行し、中古でも変なの掴まされる気がして、あんまり買う気にはならない。\n正直あんまりまだマジになってまでローカルで統計的手法のAIを動かす気もVRAMの問題や時代的な問題からないし、CUDAに縛られたくないしって感じで、素直に別の普通のPCIeがあってGPUを自由に差し替えられるデスクトップを引っ張って使ったほうがいいなと思い始めた。\nWindows 11を使えば、多少まだNVIDIAの古いGPUは誤魔化しは効くものの、勝手にRecallの件でデスクトップのスクショを取るとかいう愚行がユーザの許可なく行われるなど、正直我慢ならなかったので、もういいかなというか。。。それかWindows 10で古いまま張り付くか、どっかから強引に更新を受け取るパッチをレジストリいじって当てるのか、、、どこまでも深いようである。\n他に試したこと 自分の環境では、MSTで4k表示する古いディスプレイを使っていたために、正しくEDIDが取得されずに画面の半分だけをSSTで表示してしまい、ケーブルを別のポートに差し込むまでそのままになってしまうという症状になった。そのため、どのようにしてこの問題に対処したかについて記録をする。\nドライバごと読み込み直す(今のところ機能している) 色々試したところ、ドライバを読み込み直すことで、強引にディスプレイ情報(EDID)を再取得させられることが分かった。以下はLLM(Gemini)がsystemdで実行させるためにシバンを先頭に付け足した以外は、吐き出したスクリプトそのままである。\n#!/bin/bash # 1. 関連サービスを停止（環境に合わせて lightdm, sddm, gdm 等） sudo systemctl stop gdm # 2. NVIDIAモジュールを依存関係を含めて全て外す # (使用中の場合は失敗するので、lsof /dev/nvidia* でプロセスを特定して殺す必要があります) sudo modprobe -r nvidia_drm nvidia_modeset nvidia_uvm nvidia # 3. モジュールを再ロード（ここでMSTの再スキャンが走ります） sudo modprobe nvidia_drm modeset=1 sudo modprobe nvidia # 4. GUIを再開 sudo systemctl start gdm ちなみに、いちいち手動で実行したくないので、以下のサービスを/etc/systemd/system/nvidia.serviceとして配置し、有効化して起動時に自動的に実行されるようにした。\nsystemctl enable nvidia [Unit] Description=Rescan Display task for Nvidia GPU to avoid buggy EDID info and MST topology. #After=graphical.target [Service] Type=simple User=root ExecStart=/home/username/scripts/common/nvidia.sh Restart=on-failure RestartSec=10s StartLimitInterval=60s StartLimitBurst=5 [Install] WantedBy=multi-user.target EDID を強制する(うまくいかなかった) うまく行かなかったので途中までしか書いてない EDID を取得する(getEDID.py) EDIDのバイナリは、/sys/class/drm/内にある各フォルダ内の、edidというファイルに取得されたバイナリデータが保存されているようである。\n私の場合はいちいち手動でコマンドを操作したくなかったので、専用にスクリプトを書いた。以下のスクリプトは、すべてのポートのEDIDバイナリを取得し、各EDIDの情報をテキストファイルとして書き出すスクリプトである。edid-decodeコマンドが利用可能である必要がある。\n# スクリプトを実行した場所に情報が保存されるため、あらかじめ作業ディレクトリを作成するなどして散らからないように注意する。 sudo python getEDID.py # get all edid bin files and dump it to the current directory import os,shutil,os.path,subprocess basepath = \u0026#34;/sys/class/drm/\u0026#34; cwd = os.getcwd() folders = os.listdir(basepath) for folder in folders: if(not os.path.isdir(basepath + folder)): continue files = os.listdir(basepath + folder) if(not \u0026#34;edid\u0026#34; in files): continue savepath = cwd + \u0026#34;/\u0026#34; + folder + \u0026#34;_edid\u0026#34; shutil.copy(basepath + folder + \u0026#34;/edid\u0026#34;,savepath) result = subprocess.run((\u0026#34;edid-decode {}\u0026#34;.format(savepath)),shell=True,capture_output=True) with open(savepath + \u0026#34;.txt\u0026#34;,\u0026#34;wt\u0026#34;) as info: info.write(result.stdout.decode()) EDIDを見つける ターゲットとなるMSTで動作するディスプレイを見つける。私の場合は以下のようになった。(card1-DP-6_edid.txt)\nedid-decode (hex): 00 ff ff ff ff ff ff 00 4d 10 ea 21 00 00 00 00 ff 17 01 04 a5 46 27 78 22 10 f5 a5 58 51 a3 25 12 50 54 bf ef 80 95 00 81 c0 81 40 81 80 a9 40 90 40 b3 00 81 00 04 74 80 18 71 70 5a 80 58 2c 8a 00 5d 89 11 00 00 1e 00 00 00 fd 00 14 4d 18 8c 1e 00 0a 20 89 11 00 00 1e 00 00 00 fc 00 50 4e 2d 4b 33 32 31 0a 20 20 20 20 20 00 00 00 fe 00 0a 20 20 20 20 20 20 20 20 20 20 20 20 02 87 02 03 1c c1 4f 10 05 1f 14 20 04 13 03 02 12 11 06 07 15 16 23 09 07 01 83 01 00 00 04 74 80 d0 72 70 5a 80 10 2c 8a 80 5d 89 11 00 00 1e 02 3a 80 18 71 38 2d 40 58 2c 45 00 ba 89 21 00 00 1e 28 3c 80 a0 70 b0 23 40 30 20 36 00 ba 89 21 00 00 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 19 70 12 19 00 00 12 00 16 80 10 00 00 7f 07 6f 08 00 00 00 00 00 53 48 50 ea 21 a8 18 94 04 d2 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 90 ---------------- Block 0, Base EDID: EDID Structure Version \u0026amp; Revision: 1.4 Vendor \u0026amp; Product Identification: Manufacturer: SHP Model: 8682 Model year: 2013 Basic Display Parameters \u0026amp; Features: Digital display Bits per primary color channel: 8 DisplayPort interface Maximum image size: 70 cm x 39 cm Gamma: 2.20 DPMS levels: Off Supported color formats: RGB 4:4:4 First detailed timing includes the native pixel format and preferred refresh rate Color Characteristics: Red : 0.6445, 0.3447 Green: 0.3164, 0.6367 Blue : 0.1474, 0.0732 White: 0.3134, 0.3291 Established Timings I \u0026amp; II: IBM : 720x400 70.081663 Hz 9:5 31.467 kHz 28.320000 MHz DMT 0x04: 640x480 59.940476 Hz 4:3 31.469 kHz 25.175000 MHz Apple : 640x480 66.666667 Hz 4:3 35.000 kHz 30.240000 MHz DMT 0x05: 640x480 72.808802 Hz 4:3 37.861 kHz 31.500000 MHz DMT 0x06: 640x480 75.000000 Hz 4:3 37.500 kHz 31.500000 MHz DMT 0x08: 800x600 56.250000 Hz 4:3 35.156 kHz 36.000000 MHz DMT 0x09: 800x600 60.316541 Hz 4:3 37.879 kHz 40.000000 MHz DMT 0x0a: 800x600 72.187572 Hz 4:3 48.077 kHz 50.000000 MHz DMT 0x0b: 800x600 75.000000 Hz 4:3 46.875 kHz 49.500000 MHz Apple : 832x624 74.551266 Hz 4:3 49.726 kHz 57.284000 MHz DMT 0x10: 1024x768 60.003840 Hz 4:3 48.363 kHz 65.000000 MHz DMT 0x11: 1024x768 70.069359 Hz 4:3 56.476 kHz 75.000000 MHz DMT 0x12: 1024x768 75.028582 Hz 4:3 60.023 kHz 78.750000 MHz DMT 0x24: 1280x1024 75.024675 Hz 5:4 79.976 kHz 135.000000 MHz Apple : 1152x870 75.061550 Hz 192:145 68.681 kHz 100.000000 MHz Standard Timings: DMT 0x2f: 1440x900 59.887445 Hz 16:10 55.935 kHz 106.500000 MHz DMT 0x55: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz DMT 0x20: 1280x960 60.000000 Hz 4:3 60.000 kHz 108.000000 MHz DMT 0x23: 1280x1024 60.019740 Hz 5:4 63.981 kHz 108.000000 MHz DMT 0x33: 1600x1200 60.000000 Hz 4:3 75.000 kHz 162.000000 MHz DMT 0x2a: 1400x1050 59.978442 Hz 4:3 65.317 kHz 121.750000 MHz DMT 0x3a: 1680x1050 59.954250 Hz 16:10 65.290 kHz 146.250000 MHz DMT 0x1c: 1280x800 59.810326 Hz 16:10 49.702 kHz 83.500000 MHz Detailed Timing Descriptors: DTD 1: 1920x2160 60.000000 Hz 8:9 135.000 kHz 297.000000 MHz (349 mm x 393 mm) Hfront 88 Hsync 44 Hback 148 Hpol P Vfront 8 Vsync 10 Vback 72 Vpol P Display Range Limits: Monitor ranges (GTF): 20-77 Hz V, 24-140 kHz H, max dotclock 300 MHz Display Product Name: \u0026#39;PN-K321\u0026#39; Alphanumeric Data String: \u0026#39;\u0026#39; Extension blocks: 2 Checksum: 0x87 ---------------- Block 1, CTA-861 Extension Block: Revision: 3 Underscans IT Video Formats by default Basic audio support Native detailed modes: 1 Video Data Block: VIC 16: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz VIC 5: 1920x1080i 60.000000 Hz 16:9 33.750 kHz 74.250000 MHz VIC 31: 1920x1080 50.000000 Hz 16:9 56.250 kHz 148.500000 MHz VIC 20: 1920x1080i 50.000000 Hz 16:9 28.125 kHz 74.250000 MHz VIC 32: 1920x1080 24.000000 Hz 16:9 27.000 kHz 74.250000 MHz VIC 4: 1280x720 60.000000 Hz 16:9 45.000 kHz 74.250000 MHz VIC 19: 1280x720 50.000000 Hz 16:9 37.500 kHz 74.250000 MHz VIC 3: 720x480 59.940060 Hz 16:9 31.469 kHz 27.000000 MHz VIC 2: 720x480 59.940060 Hz 4:3 31.469 kHz 27.000000 MHz VIC 18: 720x576 50.000000 Hz 16:9 31.250 kHz 27.000000 MHz VIC 17: 720x576 50.000000 Hz 4:3 31.250 kHz 27.000000 MHz VIC 6: 1440x480i 59.940060 Hz 4:3 15.734 kHz 27.000000 MHz VIC 7: 1440x480i 59.940060 Hz 16:9 15.734 kHz 27.000000 MHz VIC 21: 1440x576i 50.000000 Hz 4:3 15.625 kHz 27.000000 MHz VIC 22: 1440x576i 50.000000 Hz 16:9 15.625 kHz 27.000000 MHz Audio Data Block: Linear PCM: Max channels: 2 Supported sample rates (kHz): 48 44.1 32 Supported sample sizes (bits): 16 Speaker Allocation Data Block: FL/FR - Front Left/Right Detailed Timing Descriptors: DTD 2: 1920x2160 50.000000 Hz 8:9 112.500 kHz 297.000000 MHz (349 mm x 393 mm) Hfront 528 Hsync 44 Hback 148 Hpol P Vfront 8 Vsync 10 Vback 72 Vpol P DTD 3: 1920x1080 60.000000 Hz 16:9 67.500 kHz 148.500000 MHz (698 mm x 393 mm) Hfront 88 Hsync 44 Hback 148 Hpol P Vfront 4 Vsync 5 Vback 36 Vpol P DTD 4: 1920x1200 59.950171 Hz 16:10 74.038 kHz 154.000000 MHz (698 mm x 393 mm) Hfront 48 Hsync 32 Hback 80 Hpol P Vfront 3 Vsync 6 Vback 26 Vpol N Checksum: 0x19 Unused space in Extension Block: 45 bytes ---------------- Block 2, DisplayID Extension Block: Version: 1.2 Extension Count: 0 Display Product Type: Extension Section Tiled Display Topology Data Block (0x12): Capabilities: Behavior if it is the only tile: Undefined Behavior if more than one tile and fewer than total number of tiles: Undefined Tiled display consists of a single physical display enclosure Num horizontal tiles: 2 Num vertical tiles: 1 Tile location: 0, 0 Tile resolution: 1920x2160 Tiled Display Manufacturer/Vendor ID: SHP Tiled Display Product ID Code: 8682 Tiled Display Serial Number: 76814504 Checksum: 0xd2 Checksum: 0x90 Unused space in Extension Block: 96 bytes EDIDを反映する /usr/lib/firmware/配下に、edidというフォルダを作成し、必要なEDIDのバイナリデータをコピーする。\nsudo mkdir /usr/lib/firmware/edid sudo cp ./card1-DP-6_edid /usr/lib/firmware/edid/card1-DP-6_edid /etc/mkinitcpio.confを書き直す ... FILES=(/usr/lib/firmware/edid/card1-DP-6_edid.bin) ... initramfs を作り直す sudo mkinitcpio -P カーネルパラメータを指定する(/etc/grub/grub.cfg) GRUB_CMDLINE_LINUX_DEFAULT= に対して以下の項目を試したがすべてうまく行かなかった。のあとに分かったこととしては、そもそもMSTのディスプレイが正しく認識されていないときと、認識されているときで、/sys/class/drm配下に存在するポート数が異なることが分かった。\n単にEDIDを上書きしたりするだけではうまく行かなさそうなことが分かった。そもそも今回のDP-6は正しく認識している場合には出現するが、正しく認識していない場合は出現しないことが分かったため、以下の設定では存在しないポートに対してEDIDの設定を試みる結果になっていたようである。\n# うまく行かなかった drm.edid_firmware=DP-6:edid/card1-DP-6_edid # うまく行かなかった drm.edid_firmware=card1-DP-6:edid/card1-DP-6_edid # 全部のディスプレイを巻き込んでしまい、うまく行かなかった drm.edid_firmware=edid/card1-DP-6_edid 正しく認識されているとき ls /sys/class/drm # ⠀card0@ ⠀card0-DP-1@ ⠀card0-DP-2@ ⠀card0-DP-3@ ⠀card0-DP-4@ ⠀card0-DP-5@ ⠀card0-DP-6@ ⠀renderD128@ ⠀version 正しく認識されていないとき ls /sys/class/drm # ⠀card0@ ⠀card0-DP-1@ ⠀card0-DP-2@ ⠀card0-DP-3@ ⠀card0-DP-4@ ⠀card0-DP-5@ ⠀renderD128@ ⠀version 参考にしたサイトとか Possible Wayland bug introduced with latest nvidia-dkms-575.57.08 / Kernel \u0026amp; Hardware / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=306081 (2026年1月17日)\nNVIDIA - ArchWiki\nhttps://wiki.archlinux.org/title/NVIDIA (2026年1月17日)\nGoogle Gemini\nhttps://gemini.google.com/app (2026年1月17日)\nKernel mode setting - ArchWiki\nhttps://wiki.archlinux.org/title/Kernel_mode_setting#Forcing_modes_and_EDID (2026年1月19日)\nventureoo/nouveau-reclocking: A small utility to reclocking your GPU with Nouveau\nhttps://github.com/ventureoo/nouveau-reclocking (2026年1月23日)\npolhdez/nouveau-reclocking-guide: How to reclock nvidia cards at boot on Linux using nouveau.\nhttps://github.com/polhdez/nouveau-reclocking-guide (2026年1月23日)\nNouveau - ArchWiki\nhttps://wiki.archlinux.org/title/Nouveau (2026年1月23日)\n","permalink":"https://www.nyanmo.info/posts/linux/nvidia/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近元々 Windows が入っていたPCに対しても、linux環境に乗り換えるようになった過程で、Nvidia 製の GPU である Quadro M620 に対して、プロプライエタリな Nvidia社が提供しているドライバをインストールしようとしたところ問題が発生したため、具体的に何をしたか記録を取る。\u003c/p\u003e\n\u003cp\u003e　基本的に今回起こった問題としては、aur から Nvidia のプロプライエタリなドライバを導入しただけでは設定不足で、正しく起動できず、カーネルなどを読み込み終わったあとに、画面が切り替わろうとするとき、解像度がおかしくなったり、画面が映らなくなったり、ケーブルを抜き差しすることで突然映るようになったりという挙動になった。\u003c/p\u003e\n\u003cp\u003e　問題が何なのか調べたりLLM(Gemini)に投げつけたりしたところ、initramfsで起動する段階で Nvidiaのドライバを読み込んでないと、その後の起動後にディスプレイの EDID の情報が正しく読み込めないのではないかということが分かった。これは、起動時には画面が映らなかったり解像度がおかしい状態になることと、ケーブルを抜き差しすると映るようになることからも、起動時に Nvidia のモジュールがロードされていなかった場合に、その後の初期化フェーズで Nvidia のドライバが読み込まれても提携できてないということで、説明がつくように思われる。\u003c/p\u003e\n\u003cp\u003e　ちなみに設定不足のときに、\u003ccode\u003edmesg\u003c/code\u003eでカーネルのメッセージを見ると以下のようなエラーが出ていた。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003edmesg | grep nvidia\n...\nR* [nvidia-drm] [GPU ID 0x00000100] Failed to add encoder for NvKmsKapiDisplay 0x00000001\n...\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003e環境\u003c/summary\u003e\n  \u003ch3 id=\"system-details-report\"\u003eSystem Details Report\u003c/h3\u003e\n\u003chr\u003e\n\u003ch4 id=\"report-details\"\u003eReport details\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2026-01-17 20:53:19\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"hardware-information\"\u003eHardware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              HP HP Z2 Mini G3 Workstation\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      16.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Xeon® E3-1225 v5 × 4\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Quadro M620\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               512.1 GB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"software-information\"\u003eSoftware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            N53 Ver. 01.91\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    (null)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               49\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.18.5-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003c/details\u003e\u003c/p\u003e","title":"Nvidia のドライバを導入する"},{"content":"この記事を作った動機 最近以下の組み合わせでフロントエンドを簡易的に書くということをしていた。\nVite React TypeScript Tailwind CSS zustand それでとりあえず機能的な意味では最低限適当にとりあえず動くという意味ではできたので、気軽に使えるようにしたいと思い、HTTPサーバとか一時的に立てずに、すぐに使えるようにしたかったので、一つのバイナリとしてまとまっていると良いと思った。\nそこで色々試したところ、プロジェクト内にElectornプロジェクトを新規作成して、作ったコードをその中のRenderというフォルダ内にそのままコピーし、それをelectron-builderを使って各プラットフォーム向けに一つのバイナリとして作れそうだと調べてみて思った。それでいつものようにそれを実際にやって動くまでがめんどくさかったのでその記録を取る。\nバイナリ完成までの試した手順 ※ コマンド実行における作業ディレクトリはViteプロジェクトのルートとする。\nVite プロジェクトを用意する プロジェクトの新規作成 npm create vite # Need to install the following packages: # create-vite@8.2.0 # Ok to proceed? (y) y # # # \u0026gt; npx # \u0026gt; \u0026#34;create-vite\u0026#34; # # │ # ◇ Project name: # │ createElectornAppTest # │ # ◇ Package name: # │ createelectornapptest # │ # ◇ Select a framework: # │ React # │ # ◇ Select a variant: # │ TypeScript # │ # ◇ Use rolldown-vite (Experimental)?: # │ No # │ # ◇ Install with npm and start now? # │ No # │ # ◇ Scaffolding project in /home/username/work/createElectornAppTest... # │ # └ Done. Now run: # # cd createElectornAppTest # npm install # npm run dev ライブラリのインストール npm install zustand npm install tailwindcss @tailwindcss/vite npm install # Command not found が出てきたとき Tailwind CSS の設定 以下を参考にして Tailwind CSS を機能するように設定する。\nInstalling Tailwind CSS with Vite - Tailwind CSS\nhttps://tailwindcss.com/docs/installation/using-vite (2026年1月4日) src/App.tsxの変更 import \u0026#39;./App.css\u0026#39; function App() { return ( \u0026lt;\u0026gt; \u0026lt;h1\u0026gt;This is test project\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;This is test project. In order to confirm that create electron app binary from a vite project.\u0026lt;/p\u0026gt; \u0026lt;/\u0026gt; ) } export default App index.htmlの変更 \u0026lt;!doctype html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34; /\u0026gt; \u0026lt;link rel=\u0026#34;icon\u0026#34; type=\u0026#34;image/svg+xml\u0026#34; href=\u0026#34;/vite.svg\u0026#34; /\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1.0\u0026#34; /\u0026gt; \u0026lt;title\u0026gt;Create Electron App Test\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div id=\u0026#34;root\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;script type=\u0026#34;module\u0026#34; src=\u0026#34;/src/main.tsx\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; Electorn プロジェクトを Vite プロジェクト内に作成する プロジェクトの新規作成 npm create @quick-start/electron@latest # Need to install the following packages: # @quick-start/create-electron@1.0.30 # Ok to proceed? (y) y # # # \u0026gt; createelectornapptest@0.0.0 npx # \u0026gt; \u0026#34;create-electron\u0026#34; # # ✔ Project name: … createElectornAppTest # ✔ Package name: … createelectornapptest # ✔ Select a framework: › react # ✔ Add TypeScript? … No / Yes # ✔ Add Electron updater plugin? … No / Yes # ✔ Enable Electron download mirror proxy? … No / Yes # # Scaffolding project in /home/username/work/createElectornAppTest/createElectornAppTest... # # Done. Now run: # # cd createElectornAppTest # npm install # npm run dev ライブラリのインストール npm install zustand npm install tailwindcss @tailwindcss/vite npm install # Command not found が出てきたとき Tailwind CSS を設定する createElectornAppTest/src/electron.vite.config.tsに、Tailwind CSS の設定を行う。\nimport { resolve } from \u0026#39;path\u0026#39; import { defineConfig } from \u0026#39;electron-vite\u0026#39; import react from \u0026#39;@vitejs/plugin-react\u0026#39; import tailwindcss from \u0026#39;@tailwindcss/vite\u0026#39; export default defineConfig({ main: {}, preload: {}, renderer: { resolve: { alias: { \u0026#39;@renderer\u0026#39;: resolve(\u0026#39;src/renderer/src\u0026#39;) } }, plugins: [react(),tailwindcss()] } }) Vite プロジェクトの内容を Electron プロジェクトにコピーする update.shを作成し、実行する。内容をコピーするだけでなく、以下の例では、Linux 向けにバイナリをビルドするように指定している。また、適宜ただコードの内容をコピーするだけでなく、Electron側のコードの修正が手動で必要である。\n#!/bin/bash cp -r ./src/* ./createElectornAppTest/src/renderer/src/ cd createElectornAppTest npm run build:linux # :win :mac ビルドされたバイナリを開く ./createElectornAppTest/dist/createelectornapptest-1.0.0.AppImage 関係ありそうなもの hello30190f/A-Create-Electron-App-Test-from-a-Vite-Project: An example of electron app to be able to build as binary for each platforms (win linux mac) from a vite project that is not a electron project. I only tested for React, TypeScirpt and linux environment.\nhttps://github.com/hello30190f/A-Create-Electron-App-Test-from-a-Vite-Project (2026年1月4日) hello30190f/Stable-diffusion-WebUI-infomation-panel: An attempt to create a progress viewer of stable diffusion WebUI with the WebUI API.\nhttps://github.com/hello30190f/Stable-diffusion-WebUI-infomation-panel (2026年1月4日) 参考にしたサイトとか electron-builder - electron-builder\nhttps://www.electron.build/electron-builder/globals (2026年1月4日) Tailwind CSS - Rapidly build modern websites without ever leaving your HTML.\nhttps://tailwindcss.com/ (2026年1月4日) Getting Started | electron-vite\nhttps://electron-vite.org/guide/ (2026年1月4日) Google Gemini\nhttps://gemini.google.com/app (2026年1月4日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/electron/createelectronappbinraryfromaviteproject/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近以下の組み合わせでフロントエンドを簡易的に書くということをしていた。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eTailwind CSS\u003c/li\u003e\n\u003cli\u003ezustand\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　それでとりあえず機能的な意味では最低限適当にとりあえず動くという意味ではできたので、気軽に使えるようにしたいと思い、HTTPサーバとか一時的に立てずに、すぐに使えるようにしたかったので、一つのバイナリとしてまとまっていると良いと思った。\u003c/p\u003e\n\u003cp\u003e　そこで色々試したところ、プロジェクト内にElectornプロジェクトを新規作成して、作ったコードをその中の\u003ccode\u003eRender\u003c/code\u003eというフォルダ内にそのままコピーし、それを\u003ccode\u003eelectron-builder\u003c/code\u003eを使って各プラットフォーム向けに一つのバイナリとして作れそうだと調べてみて思った。それでいつものようにそれを実際にやって動くまでがめんどくさかったのでその記録を取る。\u003c/p\u003e\n\u003ch2 id=\"バイナリ完成までの試した手順\"\u003eバイナリ完成までの試した手順\u003c/h2\u003e\n\u003cp\u003e\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/hello30190f/A-Create-Electron-App-Test-from-a-Vite-Project\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n※ コマンド実行における作業ディレクトリはViteプロジェクトのルートとする。\u003c/p\u003e\n\u003ch3 id=\"vite-プロジェクトを用意する\"\u003eVite プロジェクトを用意する\u003c/h3\u003e\n\u003ch4 id=\"プロジェクトの新規作成\"\u003eプロジェクトの新規作成\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm create vite\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Need to install the following packages:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# create-vite@8.2.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Ok to proceed? (y) y\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u0026gt; npx\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u0026gt; \u0026#34;create-vite\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Project name:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  createElectornAppTest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Package name:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  createelectornapptest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Select a framework:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  React\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Select a variant:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  TypeScript\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Use rolldown-vite (Experimental)?:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  No\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Install with npm and start now?\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │  No\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ◇  Scaffolding project in /home/username/work/createElectornAppTest...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# │\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# └  Done. Now run:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   cd createElectornAppTest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   npm install\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   npm run dev\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"ライブラリのインストール\"\u003eライブラリのインストール\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install zustand\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install tailwindcss @tailwindcss/vite\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install \u003cspan style=\"color:#75715e\"\u003e# Command not found が出てきたとき\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"tailwind-css-の設定\"\u003eTailwind CSS の設定\u003c/h4\u003e\n\u003cp\u003e　以下を参考にして Tailwind CSS を機能するように設定する。\u003c/p\u003e","title":"Vite を使って作ったものを Electron アプリとしてバイナリ化する"},{"content":"この記事を作った動機 なんか Arch Linux 上でOBS Studioをインストールして使おうとしたら、一発では動かなかった場合があったので記録する。\n問題が解決した方法 intel-media-sdkをインストールする。\nyay -S intel-media-sdk # sudo pacman -S intel-media-sdk これで解決しない場合は、Chrome と Intel UHD 615 で 動画再生にハードウェアアクセラレーションを使いたい#インストールするパッケージの記事の部分について参考にしてみて試しにパッケージをインストールするということはあるかもしれない。\n環境 問題が発生した当初の設定状況については、OBS Studio で Intel HD Graphics 5500 が検出され、ハードウェアエンコーダーとしてデフォルトで QSV が選択された状態である。 ハードウェア情報 Report details Date generated: 2025-12-29 17:13:30 Hardware Information: Hardware Model: Dell Inc. Latitude E7450 Memory: 16.0 GiB Processor: Intel® Core™ i5-5300U × 4 Graphics: Intel® HD Graphics 5500 (BDW GT2) Disk Capacity: 480.1 GB Software Information: Firmware Version: A20 OS Name: Arch Linux OS Build: (null) OS Type: 64-bit GNOME Version: 49 Windowing System: Wayland Kernel Version: Linux 6.18.2-arch2-1 元々インストールされていたパッケージ一覧 # yay -Qs intel local/ibus 1.5.33-1 Intelligent input bus for Linux/Unix local/intel-compute-runtime 25.48.36300.8-1 Intel(R) Graphics Compute Runtime for oneAPI Level Zero and OpenCL(TM) Driver local/intel-gmmlib 22.8.2-1 Intel Graphics Memory Management Library local/intel-gpu-tools 2.2-2 Tools for development and testing of the Intel DRM driver local/intel-graphics-compiler 1:2.24.8-1 Intel Graphics Compiler for OpenCL local/intel-media-driver 25.3.4-1 Intel Media Driver for VAAPI — Broadwell+ iGPUs local/intel-oneapi-common 2024.1.0-1 Intel\u0026#39;s oneAPI common variables and licensing local/intel-oneapi-compiler-dpcpp-cpp-runtime-libs 2025.0.4-1 Intel oneAPI Data Parallel C++ compiler: Minimal runtime libraries local/intel-oneapi-compiler-shared-runtime-libs 2025.0.4-2 Intel oneAPI compiler runtime libraries: Minimal compiler libraries local/intel-oneapi-openmp 2025.0.4-1 Intel oneAPI OpenMP runtime library local/intel-oneapi-tbb 2021.12.0-2 Intel oneAPI Threading Building Blocks local/intel-oneapi-tcm 1.2.0-3 Thread Composability Manager local/libmfx 23.2.2-5 Intel Media SDK dispatcher library local/libva-intel-driver 2.4.1-5 VA-API implementation for Intel G45 and HD Graphics family local/libvpl 2.16.0-1 Intel Video Processing Library local/linux-firmware-intel 20251125-2 Firmware files for Linux - Firmware for Intel devices local/onetbb 2022.3.0-2 oneAPI Threading Building Blocks - a high level abstract threading library local/openimagedenoise 2.3.3-3 Intel(R) Open Image Denoise library local/openpgl 0.7.1-1 Intel Open Path Guiding Library local/vlc-plugin-quicksync 3.0.21-32 Free and open source cross-platform multimedia player and framework - Intel QuickSync plugin local/vulkan-intel 1:25.3.2-1 Open-source Vulkan driver for Intel GPUs local/xf86-video-intel 1:2.99.917+939+g4a64400e-1 (xorg-drivers) X.org Intel i810/i830/i915/945G/G965+ video drivers 出てきたエラー内容について GUI上のエラー ターミナルから起動したときのログ obs # ... # # info: \u0026gt;\u0026gt;\u0026gt; new qsv encoder # info: [qsv encoder: \u0026#39;simple_video_recording\u0026#39;] settings: # codec: H.264 # rate_control: ICQ # info: ICQ Quality: 18 # info: target_usage: TU4 # profile: high # keyint: 0 # latency: normal # b-frames: 3 # fps_num: 60 # fps_den: 1 # width: 852 # height: 480 # info: [qsv encoder: \u0026#39;simple_video_recording\u0026#39;] debug info: # error: Failed to initialize MFX # # Specified object not found. /usr/src/debug/obs-studio/obs-studio-32.0.2-sources/plugins/obs-qsv11/common_utils_linux.cpp 319 # # Specified object not found. /usr/src/debug/obs-studio/obs-studio-32.0.2-sources/plugins/obs-qsv11/QSV_Encoder_Internal.cpp 142 # warning: [qsv encoder: \u0026#39;msdk_impl\u0026#39;] Specified object/item/sync point not found. (MFX_ERR_NOT_FOUND) # warning: [qsv encoder: \u0026#39;simple_video_recording\u0026#39;] qsv failed to load # info: major: 1 # minor: 0 # ... 関係のありそうな記事 Chrome と Intel UHD 615 で 動画再生にハードウェアアクセラレーションを使いたい 参考にしたサイトとか Arch Linux - intel-media-sdk 23.2.2-5 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/intel-media-sdk/ (2025年12月29日) QSV H.264 encoder doesn\u0026rsquo;t work on Arch Linux | OBS Forums\nhttps://obsproject.com/forum/threads/qsv-h-264-encoder-doesnt-work-on-arch-linux.172850/ (2025年12月29日) ","permalink":"https://www.nyanmo.info/posts/linux/obswontworkonarchlinuxwith5thgenintelcpu/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか Arch Linux 上でOBS Studioをインストールして使おうとしたら、一発では動かなかった場合があったので記録する。\u003c/p\u003e\n\u003ch2 id=\"問題が解決した方法\"\u003e問題が解決した方法\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eintel-media-sdk\u003c/code\u003eをインストールする。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S intel-media-sdk\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -S intel-media-sdk\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eこれで解決しない場合は、\u003ca href=\"https://www.nyanmo.info/posts/linux/chromehardwarevideoacceleration/#%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%81%99%E3%82%8B%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8\"\u003eChrome と Intel UHD 615 で 動画再生にハードウェアアクセラレーションを使いたい#インストールするパッケージ\u003c/a\u003eの記事の部分について参考にしてみて試しにパッケージをインストールするということはあるかもしれない。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cp\u003e　問題が発生した当初の設定状況については、OBS Studio で Intel HD Graphics 5500 が検出され、ハードウェアエンコーダーとしてデフォルトで QSV が選択された状態である。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/OBSwontWorkOnArchLinuxWith5thGenIntelCPU/%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ae%e8%a8%ad%e5%ae%9a%e4%be%8b%20%e9%8c%b2%e7%94%bb%20QSV%e3%81%8c%e9%81%b8%e6%8a%9e%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"OBS Studioでデフォルトの設定例 録画 QSVが選択されている例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/OBSwontWorkOnArchLinuxWith5thGenIntelCPU/%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%ae%e8%a8%ad%e5%ae%9a%e4%be%8b.png#center\"\n         alt=\"OBS Studioでデフォルトの設定例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/OBSwontWorkOnArchLinuxWith5thGenIntelCPU/%e8%a8%ad%e5%ae%9a%e4%be%8b%20%e7%94%bb%e9%9d%a2%e9%8c%b2%e7%94%bb.png#center\"\n         alt=\"OBS Studioで設定例 画面録画\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eハードウェア情報\u003c/summary\u003e\n  \u003ch3 id=\"report-details\"\u003eReport details\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2025-12-29 17:13:30\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"hardware-information\"\u003eHardware Information:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              Dell Inc. Latitude E7450\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      16.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Core™ i5-5300U × 4\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Intel® HD Graphics 5500 (BDW GT2)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               480.1 GB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"software-information\"\u003eSoftware Information:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            A20\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    (null)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               49\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.18.2-arch2-1\u003c/li\u003e\n\u003c/ul\u003e\n\n\u003c/details\u003e\u003c/p\u003e","title":"OBS Studio が Linux と Intel 5th CPU の組み合わせで動かない"},{"content":"この記事を作った動機 いちいちどのレジストリいじるべきか調べるのが面倒くさいから記録する。\nまとめ HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\storahci\\StartOverrideを 0にする。AHCIからIDEモードにするときに機能するかは不明である。\n引用 Yes there is a way on WIN 10 also ! Go into BIOS set the SATA mode to IDE and boot into system.\nStart REGEDIT and look for this line :\nHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\storahci\\StartOverride\nChange the 0 DWORD value from 3 to 0.\nReboot, and change your SATA controller to AHCI in BIOS. Now let it boot into safe mode, WIN 10 will install required drivers for AHCI.\nNow with a normal boot you will boot into Windows with AHCI drivers.\nNote : OEMs suggest reinstalling rather than changing, especially with an SSD.\nYou stand the chance of loosing your install if something goes wrong, and different systems may behave differently.\nNot Recommended for Windows 7.\n参考にしたサイトとか switch from ide to ahci windows 10 | Tom\u0026rsquo;s Hardware Forum\nhttps://forums.tomshardware.com/threads/switch-from-ide-to-ahci-windows-10.2429812/ (2025年12月14日) ","permalink":"https://www.nyanmo.info/posts/windows/idetoahcimode/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　いちいちどのレジストリいじるべきか調べるのが面倒くさいから記録する。\u003c/p\u003e\n\u003ch2 id=\"まとめ\"\u003eまとめ\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\storahci\\StartOverride\u003c/code\u003eを \u003ccode\u003e0\u003c/code\u003eにする。AHCIからIDEモードにするときに機能するかは不明である。\u003c/p\u003e\n\u003ch2 id=\"引用\"\u003e\u003ca href=\"https://forums.tomshardware.com/threads/switch-from-ide-to-ahci-windows-10.2429812/#post-15918033\"\u003e引用\u003c/a\u003e\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eYes there is a way on WIN 10 also ! Go into BIOS set the SATA mode to IDE and boot into system.\u003c/p\u003e\n\u003cp\u003eStart REGEDIT and look for this line :\u003c/p\u003e\n\u003cp\u003eHKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\storahci\\StartOverride\u003c/p\u003e\n\u003cp\u003eChange the 0 DWORD value from 3 to 0.\u003c/p\u003e\n\u003cp\u003eReboot, and change your SATA controller to AHCI in BIOS. Now let it boot into safe mode, WIN 10 will install required drivers for AHCI.\u003c/p\u003e","title":"IDEからAHCI モードにする"},{"content":"この記事を作った動機 Google が正規の手順で無効にできないようにして強制的に、AI モード や AI Overview なるものを押し付けてくるので、無効化する方法についてまとめておきたい。\n無効化手順 AIモード 無効化 Google Chrome の検索バーの問題の様子 chrome://flagsを開く AI モード に関連する項目を全部disabledにする 問題が解消された状態 AI Overview 無効化 chrome://settings/searchEnginesを開く chrome://settings/searchEngines Google Web @web {google:baseURL}search?q=%s\u0026amp;udm=14 問題が解消された状態 もっと簡易的な対策 検索クエリに猫 -aiのように -aiとつける。少し前は、倫理的に引っかかる言葉や罵詈雑言、AIへの否定などを含めても出てこないように押さえつけられる場合があったようだが、最近AI死ねのような露骨なワードを入れても、しつこく出てくるようになったので、機能はしていなさそうである。\nAsk Gemini(Geminiに相談) ボタンの排除 (2026/6/15 追記) 右クリックをすると出てくるコンテキストメニューに侵食する強制 Gemini ボタンの様子 chrome://flagsを開く glicのフラグを無効にする 問題が解消された状態 AI モードボタンが復活する (2026/7/22 追記) アプデごとにいちいち AI モードボタンが強制的に復活してくるときは、chrome://flagsにて、\u0026ldquo;ai mode\u0026rdquo; と調べて出てきた項目を片っ端から無効にすることが必要であることが分かった。\n一部の AI モードボタンが消えない (2026/7/22 追記) 現状では以下の、AI モードボタンが chrome://flags で設定しても消えないことが分かった。今のところこれについては放置して、別のブラウザを試すようにしている。 ついにフラグが封印されたっぽい (2026/8/8 追記) Google の非常に暴力的な選択肢を奪う PUSH 手段として、AI モードボタンが検索バーから flag をいじっても消えなくなったことが分かった。暫定的な対処としては、デフォルトの検索エンジンを Google 以外にするか、chrome://settings/searchEnginesを開くにより作った項目をデフォルトとすることがある。\n長期的には、ブラウザを乗り換える他ないと思われる。MS の IE と同じ戦略をより強硬的に実行してくるところは確信犯にしか見えない。よほど思ったように伸びないからなのか元からそうするつもりだったのかはわからないが、あまりにひどいと思う。YouTubeなどでは前々から、選択肢をユーザに与えず、\u0026ldquo;サービスを使うのをやめるか、服従\u0026quot;の二択を強制してくるユーザを尊重しない姿勢は明らかであったが、ついにここまで来てしまったかという感じである。ユーザ足元を見て、\u0026ldquo;でも今更やめられないでしょ？\u0026ldquo;みたいな感じで進めてくるところには悪意を感じる。\nまだ、法人向けの管理用設定では、これを無効化できるらしいが、あまりに手間がかかりすぎることと、\u0026ldquo;AI 関連機能を無効化するコストを上げてROIを極端に高くすることで諦めさせる、強制的に従わせる\u0026quot;というあからさまないたちごっこの姿勢からして、もはやブラウザごと捨てる以上のことは思いつかなかった。絶対権力は絶対腐敗すると言うし、文字どうりになったということなのだろう。\n個人的な感想 閲覧注意 容赦なしに感想を書き出しているため、精神衛生を害されたくない人は見るべきではないと思われる。 正直なお話 そもそもの話、Google 検索エンジンの品質も明らかに SEO 対策やらで完全に死に絶えていたようなものにも思えるし、なんかいい加減別の検索エンジン試してもそこまで違いを感じないんじゃないかと思ってきた。DuckDuckGo あたりにデフォルトを変えて、さらに Google への依存度を下げていくということになる気もしてきた。パスワードマネージャを独立した物を用意して、Gmail も別のものに置き換えて、Google Analytics も廃止して、って感じで次々とやることが見えてきた気がする。今年もこんなことで忙しそうなのマジ嫌すぎて爆発しそう。\n多分、ユーザが LLM やら AI に肯定的、否定的であるかどうかは関係なく、彼らのサービスに対して、\u0026ldquo;金を落とすか、依存するか\u0026quot;が彼らにとって肝心なのだろう。徹底的に根深く組み込んできて密結合にしてくるっていうのはそういうことなのだろう。本当に技術的に純粋に \u0026ldquo;AI\u0026rdquo; だと呼ばれているものを PUSH したいのであれば、こんなユーザを無視したやり方をするだろうか？私としてはしないように思われる。理由としては、強制すること自体が、内容にかかわらず、\u0026ldquo;悪い印象を与え、強い嫌悪を強制されたことにもたらす\u0026quot;という観点にある。またこのやり方は、これら話題に無関心な層、無知な層に対して、強く働きかけてシェアを伸ばそうとするやり方でもあると思われ、先を急いでいる様相が見受けられる。本当にただ純粋に良いものを広めたいだけであれば、長期的に少しずつ、嫌がる人には強制しない形を取るのではないかと思われる。明らかにお金や政治的背景、組織的背景を元にした、強硬的で急性な 10 年も待たないやり方は、すごく真っ黒なやり方ではないか、時間をかければ否定できない論理(EU の AI Act の話もあるし、というか表沙汰にならないだけで色々既に出てきているとは思うが)が出てきて、逃げ場を失うからと、相当強引な手法をとっているのではないかと思われる。\nまだ小さな中小のサービスなら、まあそんなものかと思うが、Google に関してはあまりに大きな影響力を持ちすぎているし、明らかにユーザの足元を見ているとしか言えないと私は思うところである。彼らにとって、一連の姿勢は、無理やりでもやらないと\u0026quot;社会のためにならない、社会的に正当化されないうちに、弱いうちに潰されてしまう\u0026quot;という必要悪のつもりなのだろうか。私としては、嫌がっている人に長期にわたってこのように執拗に特定の物を強制する姿勢は看過できないと考える。私的には全く便利には思えないし、もうたくさんである。彼らにとって、ユーザに現実的な選択肢があり、自分の支配下に収まらないことが、受け入れられないということなのかというふうにも見受けられた。\nそもそも便利という言葉には２つの意味があるように見える。一つは、純粋に技術的進展などから、人間が何かを達成する負担が道具を使ったりすることなどにより\u0026quot;人を選ばずに\u0026quot;負担が軽くなることである。もう一つは、主権や権利、自由を相手に依存し、相手にされるがままであることで、一時的に認知コストが下がり、抜け出せなくなることが確定するまでの間の、撒き餌としての\u0026quot;条件付き、有限な\u0026quot;便利である。いわゆる、Big Tech がやるやり方は基本的に後者であると思われる。上手く処世できることが賢いとして、上手く処世で来ていないとする人を自己責任論で否定したり冷笑し、自分は上手くやれていると思っているような、\u0026ldquo;上手く処世できない人が直面している問題は自分には降りかからないだろう、だから上手くやれなかった人が悪いのだ\u0026quot;と思っている人がハマるのも後者であると思われる。自分の身に問題が降りかからない、問題が降りかかるのはその人に問題があるからだ、として思考停止したりしている人が、引っかかるのだと思われる。\nこのようにある程度の期間、\u0026ldquo;檻\u0026quot;だと気づかせずに、\u0026ldquo;結果を知っていれば、多くの人が避けたであろう選択をさせる\u0026quot;ことによって、あたかも主体的に選んだかのように偽装された状況を作ることで、多くの自分に起こっていることに自覚がない人を味方につけたところで、\u0026ldquo;もう逃げられないぞ\u0026quot;ということが確定したときに牙を剥くというのが、今起こっていることのように見える。\n裏返すと？ あえて今の状況をよく捉えるなら、自分が何に依存していて、どうするべきかがはっきりしてきたようにも思うところである。Google に深く色々握られている事を強く自覚させられているように思う。最近メールサーバを構築し始めたのも、それがないと Gmail で何かの拍子にやられたら、ひとたまりもないということがあり、徐々に依存度を下げることの過程の一つとしてある。もちろんいきなり脱GOOGLEとかは無謀なので、徐々にできることから、投資していくということにはしているが、Google などの Big Tech も\u0026quot;ただじゃ済まさないぞ、フリーミアムでやってきた分、これからはお返しだ！\u0026ldquo;って感じなのでどこまでなんとかなるかは自信はないが、もうやるしかなさそうだ。\nメールサーバに関しては、DNS の認証系と Mailcow の構築自体はだいぶ終わってきたものの、ネットワークが複雑な影響で、単に直接グローバル空間に露出しているサーバ上で構築するのとは異なった高度な設定が必要で苦戦しているところではある。今年中には解決すればよいが。まあ、別のメールのプロバイダとかあるが、正直もう今回を含め一連の件で散々痛めつけられたし、もう SAAS とかマジで嫌だし、深く自分の生活やこれからに関わるものまで握らせるわけにはいかないと思ったところであり、これに関しては投資ということにしている。まあ一応情報系の学部にいるわけだし、自分で構築して自分で使うことに大きく投資してもいいじゃないかとも思っているところもある。\n確かに、時代は大きく変わっているとは言えるかも知れないけど、それは必ずしもいい意味であるとは言えず、結局旧来成り立っていたことが成り立たなくなっていく過程でもあり、それは悪いことだけでなく、いいことでも同じのようである。変わること自体はいいことでも悪いことでも無い。良い変化は進化や改善と言われ、悪い変化は退化や改悪と言われる。私個人として良いと変化だと思えることは、単に技術水準が底上げされたことであり、無料でできることが非常に大きくなったことである。旧来の暴力が人を萎縮させて成果物を出せず、広く認知されて出尽くし、社会的に正当化されなくなって通用しなくなったとして別の形で偽善などして\u0026quot;偽りの安心\u0026quot;を与えることで、相手を本気にさせたり、相手に精神的な隙を作って、成果物を出させつつ、都合のいいように物事を運ぼうとする相手の本意に背くやり方が表出している点においては、それは悪いことの具体的な内容の変化であり移動であって、根が変わったわけではなく、より高度に巧妙になったとは言えても、良くなったとは言えないだろう。裏を返せば、単に IT に対して触れているだけで、特権的な状況を得られるということは終わったということなんじゃないかなと思う。ボーナスタイム終了みたいな？これからは言われるがまま、流行るがままではなく、色々人質に取られてしまわないよう、真剣に考えていかないと足元を掬われると言うか？そんなことずっと前からそうじゃないかと言われたらそうだが、2020年以降はそれよりさらにといった感じである。これはいつの時代が良い、悪いということではなく、いつの時代も一概には良い、悪いとは比較できず、それぞれに良い、悪い点があるということである。\n1990年代からのドットコムバブルから、2010年前くらいまでは、PCやネット環境があって、ITガジェットに触れているだけで、大きな差であり、まだここまでひどく強硬姿勢がGOOGLEなどもあったわけではないと思われる。当時は、まだ情報を電子的に扱うこと自体が特権的であった時代であり、コストのかかることだったのだと思われる。しかし時間が経つに連れ、組織は中身が入れ替わっていくし、組織自体が目的化し、過去の名声で集まってくる存在はそれが目当ての人や組織である。今のすべての事を悪いとは言わないが、対応を迫られていることは確かだと思われる。それは既存の強い存在が強制することに従うということではなく、今まで無自覚に受けてきた条件付きの有限なプロバイダから与えらえた特権性(フリーミアムなど)を見直し、より技術的に自立した方向性にできる範囲でいいので少しずつ継続的に投資していくことなのだと思われる。\n一つのそれの例では、私は LINE から RCS メッセージへの移行を進めているところがある。ここで大事なのは、いきなりLINEをやめることでもなく、完全にGOOGLEへの依存をやめることでもなく、選択できる範囲で、ましだと思える物を選んでいることである。もちろん理想では自分でなるべくホストしていることが望まれるがそれは現実的ではないこともある。例えば、SQL周りでくじけてしまい、LINEやRCSメッセージの代替になりえそうなメッセージアプリの代替ができるサービス(マストドン)を自前でホストするということはまだ私は実現できていない。LINE に関しては、まだ深く依存して使っている人が多く、メッセージの取り消しを期限付きにしたりしてユーザに課金を迫ることでビジネスモデルの失敗を埋め合わせようとしてくるところがあるにしても、完全には廃止できないところがある。 RCS メッセージは、GOOGLE開発であり、LINE のようなスタンプは利用できないが、最低限ファイルを送受信でき、マルチメディアを扱えて、やり取りが行なえ、電話番号で必要な相手とつながることができ、SMS と違って、インターネットを介して通信するため、従量課金などの高額な通信費が発生しにくく、LINE のような強硬姿勢はまだそこまで見られない点がある。最終的な理想は、汎用で開かれて\u0026quot;誰かの営利や都合のためではない、真の意味でのインフラ、公共情報インフラ\u0026quot;であることであり、最低限の理想は、自分が不当に脅かされない環境であることである。しかし理想ばかり追いかけていては、具体的なアクションが起こらず(完璧主義の罠)、\u0026ldquo;便利、賢さ\u0026quot;という名称の相手のインセンティブ設計にはめられてしまう。現実はいきなり変わらないし、他人に脅迫的に迫れば同じムジナの穴である。だから、自分でできる範囲のことで現実的なことをすることの一環として、\u0026ldquo;少しでもマシだと思われる選択\u0026quot;をできる限り見つけて、できることから実行していくことである。例えば、RCSメッセージを使いたいからLINEを使いたい相手に対して、嫌がられてまでRCSメッセージを使うように迫ることはしないことである。LINEを使いたいとしている相手でかつ連絡が必要な相手に限っては、LINEをあてがい、通常は、RCSメッセージをお願いするという形を取ることが、現実的であると考える。これが、長期的に少しずつやるということだと思われる。\nAI モデル削除 (未確認) (2026/8/8 追記) このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） chrome://flags にて、以下の項目を検索し、無効化する。\nOptimization Guide On-Device ポリシーベースのやり方 (ぼちぼち書く予定) (2026/8/8 追記) このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 私は、Win と Linux 環境でしか使っていないので、それについてはまとめようと思う。ただこれもいつまで使えるのかはわからない。\nWindows Linux ungoogled-chromium (2026/8/20 追記) Chrome Web Store から uBlock Origin もなくなることに対しての対応 (2026/8/21) 以下のようにしてuBlock Originから直接ダウンロードしてインストールする。選ぶバージョンはDownloadsという項目があるものにする。\ngorhill/uBlock: uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean.\nhttps://github.com/gorhill/uBlock (2026年8月21日) ungoogled-chromium では普通の uBlock Origin がインストールできる模様 (2026/8/20) 一応 uBlock Origin の公式自体が、Chrome におけるサポート終了を宣言していたが、Chromium 系ブラウザでまだ使いたければ、ungoogled-chromium においてはそれが可能であることが分かった。\nungoogled-chromium において拡張機能を導入する下準備 ungoogled-chromium ではそのままでは拡張機能を導入できないようなので、以下の画像に示される手順を踏む。 uBlock Origin が動作する様子 (2026/8/20) uBlock Origin - Chrome ウェブストア\nhttps://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm (2026年8月20日) GitHub - gorhill/uBlock: uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. · GitHub\nhttps://github.com/gorhill/ublock (2026年8月20日) ungoogled-chromium を発見 (2026/8/20) Google 関連機能が排除されたバージョンの Chromium があることが分かった。今のところそこでは Google 検索をデフォルトにしても、しつこく AI ボタンに追い回されたりはしないことが確認できた。ただ Google アカウントと紐づいているパスワード同期などは使えないっぽいので手動で色々作業する必要がありそうである。これについては Chrome 拡張機能を自作してパスワードを中央集権的に専用に Python なりでバックエンド書いて管理すれば、解決しそうな問題ではある。\nungoogled-software/ungoogled-chromium: Google Chromium, sans integration with Google\nhttps://github.com/ungoogled-software/ungoogled-chromium (2026年8月20日) Arch Linux 環境では以下のパッケージをインストールすることにした。binバージョンでないと、最初からコンパイルが走ってとても時間がかかるため注意する。Windows については説明を見る限りでは使えないということはなさそうだが、バイナリは用意されておらず自力で現時点ではビルドするしか無いっぽく別を当たったほうが良さそうである。これを機に是非Linuxディストリビューションを使ってみたらいかがでしょうか？\nAUR (en) - ungoogled-chromium-bin\nhttps://aur.archlinux.org/packages/ungoogled-chromium-bin (2026年8月20日) ただデフォルトだと、何も検索バーさえ使えないほどの徹底されたものなので、このブラウザで Google 検索したいのであれば、ai-overview-無効化のように、以下のように設定するのはありかもしれない。ただ{google:baseURL}も使えないので、普通にhttps://google.comと入力する必要はある。\nchrome://settings/searchEngines Google Web @web https://google.com/search?q=%s\u0026amp;udm=14 逆に調べてはいないが、通常の Chromium では AI ボタンが侵食してきているということだろうか？と気になったところであった。今回はまだ調べていない。\n関係ありそうな記事 LLM の利用状況の現状 参考にしたサイトとか How to Turn Off Google AI Overview and Set \u0026ldquo;Web\u0026rdquo; as Default\nhttps://tenbluelinks.org/ (2025年12月2日) Do this NOW to Disable AI Mode in Google Chrome Browser (Address Bar and New Tab) - YouTube\nhttps://www.youtube.com/watch?v=3I8T_gy2PV0 (2025年12月2日) Permanently disable Chrome search bar\u0026rsquo;s stupid AI Mode setting : r/chrome\nhttps://www.reddit.com/r/chrome/comments/1q888nr/permanently_disable_chrome_search_bars_stupid_ai/?solution=544985d86ad40adc544985d86ad40adc\u0026amp;js_challenge=1\u0026amp;token=bbbe4bf1c9a2b5160829c4be34da5861a2d7a7b71fdd093a15a607ac2dec7745\u0026amp;jsc_orig_r= (2026年5月11日) How To Remove Ask Gemini From Chrome Tab Bar - YouTube\nhttps://www.youtube.com/watch?v=y8tCcxfL7wA (2026年5月20日) How to remove \u0026ldquo;ask gemini\u0026rdquo; from right click? : r/GoogleGeminiAI\nhttps://www.reddit.com/r/GoogleGeminiAI/comments/1tjddwn/how_to_remove_ask_gemini_from_right_click/ (2026年6月15日) Google Chrome Just Silently Installed A 4GB AI Model On Your Device - Here\u0026rsquo;s How To Remove It\nhttps://www.bgr.com/2166691/how-to-remove-google-chrome-ai-guide/ (2026年8月8日) ungoogled-software/ungoogled-chromium: Google Chromium, sans integration with Google\nhttps://github.com/ungoogled-software/ungoogled-chromium (2026年8月20日) AUR (en) - ungoogled-chromium-bin\nhttps://aur.archlinux.org/packages/ungoogled-chromium-bin (2026年8月20日) AUR (en) - ungoogled-chromium\nhttps://aur.archlinux.org/packages/ungoogled-chromium (2026年8月20日) uBlock Origin - Chrome ウェブストア\nhttps://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm (2026年8月20日) GitHub - gorhill/uBlock: uBlock Origin - An efficient blocker for Chromium and Firefox. Fast and lean. · GitHub\nhttps://github.com/gorhill/ublock (2026年8月20日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/stopgooglechromefromshowingaimode/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Google が正規の手順で無効にできないようにして強制的に、AI モード や AI Overview なるものを押し付けてくるので、無効化する方法についてまとめておきたい。\u003c/p\u003e\n\u003ch2 id=\"無効化手順\"\u003e無効化手順\u003c/h2\u003e\n\u003ch3 id=\"aiモード-無効化\"\u003eAIモード 無効化\u003c/h3\u003e\n\u003ch4 id=\"google-chrome-の検索バーの問題の様子\"\u003eGoogle Chrome の検索バーの問題の様子\u003c/h4\u003e\n\u003cp\u003e\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/GoogleChrome%e3%81%ab%e4%be%b5%e9%a3%9f%e3%81%99%e3%82%8bAI%e3%83%a2%e3%83%bc%e3%83%89.png alt=GoogleChromeに侵食するAIモード/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/%e6%a4%9c%e7%b4%a2%e3%83%90%e3%83%bc%e3%81%ab%e4%be%b5%e9%a3%9f%e3%81%99%e3%82%8bAI%e3%83%a2%e3%83%bc%e3%83%89.png alt=検索バーに侵食するAIモード/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch4 id=\"chromeflagsを開く\"\u003e\u003ccode\u003echrome://flags\u003c/code\u003eを開く\u003c/h4\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/chrome%20flags%e3%82%92%e9%96%8b%e3%81%8f.png alt=chrome\u0026#32;flagsを開く/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch4 id=\"ai-モード-に関連する項目を全部disabledにする\"\u003e\u003ccode\u003eAI モード\u003c/code\u003e に関連する項目を全部\u003ccode\u003edisabled\u003c/code\u003eにする\u003c/h4\u003e\n\u003cp\u003e\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/Chrome%e5%86%85%e8%87%93%e3%81%ae%e6%a4%9c%e7%b4%a2%e3%83%90%e3%83%bc%e3%81%ab%e5%af%be%e3%81%99%e3%82%8b%e5%af%be%e5%bf%9c.png alt=Chrome内臓の検索バーに対する対応/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/%e6%a4%9c%e7%b4%a2%e3%83%90%e3%83%bc%e3%81%ab%e5%af%be%e3%81%99%e3%82%8b%e5%af%be%e5%87%a6.png alt=検索バーに対する対処/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/Chrome%e5%86%85%e8%87%93%e3%81%ae%e6%a4%9c%e7%b4%a2%e3%83%90%e3%83%bc%e3%81%ab%e5%af%be%e3%81%99%e3%82%8b%e5%af%be%e5%bf%9c1.png alt=Chrome内臓の検索バーに対する対応1/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch4 id=\"問題が解消された状態\"\u003e問題が解消された状態\u003c/h4\u003e\n\u003cp\u003e\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/%e5%95%8f%e9%a1%8c%e3%81%8c%e8%a7%a3%e6%b6%88%e3%81%95%e3%82%8c%e3%81%9f%e7%8a%b6%e6%85%8b.png alt=問題が解消された状態/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/stopGoogleChromeFromShowingAImode/%e6%a4%9c%e7%b4%a2%e3%83%90%e3%83%bc%e3%81%ab%e4%be%b5%e9%a3%9f%e3%81%99%e3%82%8bAI%e3%83%a2%e3%83%bc%e3%83%89%e3%82%92%e5%8f%96%e3%82%8a%e9%99%a4%e3%81%84%e3%81%9f%e7%8a%b6%e6%85%8b.png alt=検索バーに侵食するAIモードを取り除いた状態/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e","title":"Google Chrome で AI モード と AI Overview を止めたい (uBlock Origin についても言及あり)"},{"content":"この記事を作った動機 pyocrを使うおうとしたらライブラリだけじゃなくて、OCRを実際にする部分である tesseract をインストールしないといけないことが分かったので記録をとってみる。前提として Windows 環境上で作業していて、Python環境はすでに構築されていて機能するものとする。\nちなみに、躓いた点としては、tesseract をただインストールする必要があるだけでなく、環境変数Pathを通して、tesseractコマンドが使える状態しないと、pyocr が tesseract を見つけられないという点があった。\nWindows と違って、Linux や Mac 系の環境では、tesseract をインストールした時点ですでにパスが通っているところにバイナリが配置され、追加の設定が不要ということがあるかもしれないが、現時点ではまだ確かめていない。\npyocr を使えるようにする手順 pyocr ライブラリの導入 pip install pyocr tesseract をインストール インストーラの取得 Home · UB-Mannheim/tesseract Wiki から、tesseract-ocr-w64-setup-XXXXXXXXXXXXXX.exeをダウンロードする。\n日本語のOCRデータが含まれるように指定する インストーラを実行し進める。ただ単に進めるだけでなく、途中で日本語向けのOCRデータを含むように明示する必要がある。 インストーラを進めている途中で出てくる以下のパスは、のちにPathという環境変数を設定するために使うため、どこかにコピーしておく。私の環境では以下のようになった。 環境変数を通す インストーラで見えていた場所に対して、環境変数のPathを設定する。なお変更の反映にはターミナルなどの再起動が必要である。また設定したのにうまく反映されない場合は PC ごと再起動した方がいいかもしれない。 環境変数が通ると、コマンドプロンプトなどで以下のように表示されるはずである。\ntesseract # Usage: # C:\\Program Files\\Tesseract-OCR\\tesseract.exe --help | --help-extra | --version # C:\\Program Files\\Tesseract-OCR\\tesseract.exe --list-langs # C:\\Program Files\\Tesseract-OCR\\tesseract.exe imagename outputbase [options...] [configfile...] # # OCR options: # -l LANG[+LANG] Specify language(s) used for OCR. # NOTE: These options must occur before any configfile. # # Single options: # --help Show this help message. # --help-extra Show extra help for advanced users. # --version Show version information. # --list-langs List available languages for tesseract engine. 環境変数がうまく通ってない場合の例(PowerShell)\ntesseract # tesseract : The term \u0026#39;tesseract\u0026#39; is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of # the name, or if a path was included, verify that the path is correct and try again. # At line:1 char:1 # + tesseract # + ~~~~~~~~~ # + CategoryInfo : ObjectNotFound: (tesseract:String) [], CommandNotFoundException # + FullyQualifiedErrorId : CommandNotFoundException pyocr を動かしてみる 以下のコードを動かして、No OCR tool foundと出なかったら成功だと思われる。以下のコードは、pyocr · PyPIに書いてある初期化コードの引用である。\nfrom PIL import Image import sys import pyocr import pyocr.builders tools = pyocr.get_available_tools() if len(tools) == 0: print(\u0026#34;No OCR tool found\u0026#34;) sys.exit(1) # The tools are returned in the recommended order of usage tool = tools[0] print(\u0026#34;Will use tool \u0026#39;%s\u0026#39;\u0026#34; % (tool.get_name())) # Ex: Will use tool \u0026#39;libtesseract\u0026#39; langs = tool.get_available_languages() print(\u0026#34;Available languages: %s\u0026#34; % \u0026#34;, \u0026#34;.join(langs)) lang = langs[0] print(\u0026#34;Will use lang \u0026#39;%s\u0026#39;\u0026#34; % (lang)) # Ex: Will use lang \u0026#39;fra\u0026#39; # Note that languages are NOT sorted in any way. Please refer # to the system locale settings for the default language # to use. 私の環境では以下のような出力になった。\npython main1.py # Will use tool \u0026#39;Tesseract (sh)\u0026#39; # Available languages: eng, jpn, jpn_vert, osd, script\\Japanese, script\\Japanese_vert # Will use lang \u0026#39;eng\u0026#39; 参考にしたサイトとか Release 5.5.1 · tesseract-ocr/tesseract\nhttps://github.com/tesseract-ocr/tesseract/releases/tag/5.5.1 (2025年12月2日) tesseract-ocr/tesseract: Tesseract Open Source OCR Engine (main repository)\nhttps://github.com/tesseract-ocr/tesseract (2025年12月2日) Introduction | tessdoc\nhttps://tesseract-ocr.github.io/tessdoc/Installation.html (2025年12月2日) Home · UB-Mannheim/tesseract Wiki\nhttps://github.com/UB-Mannheim/tesseract/wiki (2025年12月2日) python - No tools available from pyOCR - Stack Overflow\nhttps://stackoverflow.com/questions/31892413/no-tools-available-from-pyocr (2025年12月2日) pyocr · PyPI\nhttps://pypi.org/project/pyocr/ (2025年12月2日) ","permalink":"https://www.nyanmo.info/posts/windows/makepyocrwork/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003epyocr\u003c/code\u003eを使うおうとしたらライブラリだけじゃなくて、OCRを実際にする部分である \u003ccode\u003etesseract\u003c/code\u003e をインストールしないといけないことが分かったので記録をとってみる。前提として Windows 環境上で作業していて、Python環境はすでに構築されていて機能するものとする。\u003c/p\u003e\n\u003cp\u003e　ちなみに、躓いた点としては、\u003ccode\u003etesseract\u003c/code\u003e をただインストールする必要があるだけでなく、環境変数\u003ccode\u003ePath\u003c/code\u003eを通して、\u003ccode\u003etesseract\u003c/code\u003eコマンドが使える状態しないと、\u003ccode\u003epyocr\u003c/code\u003e が \u003ccode\u003etesseract\u003c/code\u003e を見つけられないという点があった。\u003c/p\u003e\n\u003cp\u003e　Windows と違って、Linux や Mac 系の環境では、\u003ccode\u003etesseract\u003c/code\u003e をインストールした時点ですでにパスが通っているところにバイナリが配置され、追加の設定が不要ということがあるかもしれないが、現時点ではまだ確かめていない。\u003c/p\u003e\n\u003ch2 id=\"pyocr-を使えるようにする手順\"\u003e\u003ccode\u003epyocr\u003c/code\u003e を使えるようにする手順\u003c/h2\u003e\n\u003ch3 id=\"pyocr-ライブラリの導入\"\u003e\u003ccode\u003epyocr\u003c/code\u003e ライブラリの導入\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003epip install pyocr\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"tesseract-をインストール\"\u003e\u003ccode\u003etesseract\u003c/code\u003e をインストール\u003c/h3\u003e\n\u003ch4 id=\"インストーラの取得\"\u003eインストーラの取得\u003c/h4\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/UB-Mannheim/tesseract/wiki\"\u003eHome · UB-Mannheim/tesseract Wiki\u003c/a\u003e から、\u003ccode\u003etesseract-ocr-w64-setup-XXXXXXXXXXXXXX.exe\u003c/code\u003eをダウンロードする。\u003c/p\u003e\n\u003ch4 id=\"日本語のocrデータが含まれるように指定する\"\u003e日本語のOCRデータが含まれるように指定する\u003c/h4\u003e\n\u003cp\u003e　インストーラを実行し進める。ただ単に進めるだけでなく、途中で日本語向けのOCRデータを含むように明示する必要がある。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e6%97%a5%e6%9c%ac%e8%aa%9e%e3%82%92OCR%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b-%e5%a4%89%e6%9b%b4%e3%81%99%e3%82%8b%e9%a0%85%e7%9b%ae.png#center\"\n         alt=\"日本語をOCRできるようにする-変更する項目\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e6%97%a5%e6%9c%ac%e8%aa%9e%e3%82%92OCR%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b1.png#center\"\n         alt=\"日本語をOCRできるようにする1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e6%97%a5%e6%9c%ac%e8%aa%9e%e3%82%92OCR%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b2.png#center\"\n         alt=\"日本語をOCRできるようにする2\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e6%97%a5%e6%9c%ac%e8%aa%9e%e3%82%92OCR%e3%81%a7%e3%81%8d%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b.png#center\"\n         alt=\"日本語をOCRできるようにする\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003e　インストーラを進めている途中で出てくる以下のパスは、のちに\u003ccode\u003ePath\u003c/code\u003eという環境変数を設定するために使うため、どこかにコピーしておく。私の環境では以下のようになった。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e3%82%a4%e3%83%b3%e3%82%b9%e3%83%88%e3%83%bc%e3%83%a9%e3%82%92%e9%80%b2%e3%82%81%e3%82%8b3.png#center\"\n         alt=\"インストーラを進める3\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"環境変数を通す\"\u003e環境変数を通す\u003c/h4\u003e\n\u003cp\u003e　インストーラで見えていた場所に対して、環境変数の\u003ccode\u003ePath\u003c/code\u003eを設定する。なお変更の反映にはターミナルなどの再起動が必要である。また設定したのにうまく反映されない場合は PC ごと再起動した方がいいかもしれない。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%82%92%e9%80%9a%e3%81%99.png#center\"\n         alt=\"環境変数を通す\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%82%92%e9%80%9a%e3%81%991.png#center\"\n         alt=\"環境変数を通す1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makePyocrWork/%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%82%92%e9%80%9a%e3%81%992.png#center\"\n         alt=\"環境変数を通す2\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003e　環境変数が通ると、コマンドプロンプトなどで以下のように表示されるはずである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etesseract\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Usage:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   C:\\Program Files\\Tesseract-OCR\\tesseract.exe --help | --help-extra | --version\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   C:\\Program Files\\Tesseract-OCR\\tesseract.exe --list-langs\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   C:\\Program Files\\Tesseract-OCR\\tesseract.exe imagename outputbase [options...] [configfile...]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# OCR options:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   -l LANG[+LANG]        Specify language(s) used for OCR.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# NOTE: These options must occur before any configfile.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Single options:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   --help                Show this help message.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   --help-extra          Show extra help for advanced users.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   --version             Show version information.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#   --list-langs          List available languages for tesseract engine.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　環境変数がうまく通ってない場合の例(PowerShell)\u003c/p\u003e","title":"PyOCR を Windows で動かしたい"},{"content":"この記事を作った動機 React で作った Web アプリを Android に移植しようとしたら超絶めんどくさかったので、記録するだけ。\n自分の試した構成 Vite React TypeScript Android Studio (with SDK) npm create vite@latest 使った汎用コマンド集 すべての環境変数をリスト (Windows,PowerShell) gci env:* | sort-object name 環境変数を新規作成 (Windows,PowerShell) # 具体例 ANDROID_HOME にパスを設定する $env:ANDROID_HOME = \u0026#34;C:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk\u0026#34; 特定の環境変数に対してパスを追加 (Windows,PowerShell) # 具体例 ANDROID_HOME にパスを追加設定する $env:ANDROID_HOME += \u0026#34;;C:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk\u0026#34; 準備 Capacitor を使えるようにする 必要なパッケージのインストール npm i @capacitor/core npm i @capacitor/android 初期化する npx cap init android 向けに初期化する npx cap add android ANDROID_HOMEを設定する エラー例 Android SDK のパスが、ANDROID_HOMEとして環境変数に設定されていない場合は、以下のようなエラーが出てくる。\nnpx cap build android # × Running Gradle build - failed! # [error] # \u0026gt; Configure project :app # WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats. # \u0026gt; Configure project :capacitor-cordova-android-plugins # WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats. # FAILURE: Build failed with an exception. # * What went wrong: # Could not determine the dependencies of task \u0026#39;:app:bundleReleaseResources\u0026#39;. # \u0026gt; SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting # the sdk.dir path in your project\u0026#39;s local properties file at \u0026#39;C:\\Users\\userName\\work\\TODOListApp\\TODO # List\\android\\local.properties\u0026#39;. # * Try: # \u0026gt; Run with --stacktrace option to get the stack trace. # \u0026gt; Run with --info or --debug option to get more log output. # \u0026gt; Run with --scan to get full insights. # \u0026gt; Get more help at https://help.gradle.org. # BUILD FAILED in 1s ANDROID_HOMEとは、Android SDK のパスのことで、設定が必要である。私の環境では、Android SDK は以下の場所にあった。Android Studio 内では、Tools -\u0026gt; SDK Manager からパスを確認できた。\nC:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk 設定方法としては、いくつかあるが、今回は PowerShell 内で直接パスを一時的に設定する例を以下に示す。\n$env:ANDROID_HOME = \u0026#34;C:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk\u0026#34; JAVA_HOMEを設定する エラー例 JAVA_HOMEに設定されている Java のバージョンが一致しない場合、以下のエラーが出てくる。invalid source release: 21と言われる。\nnpx cap build android # × Running Gradle build - failed! # [error] Starting a Gradle Daemon, 1 incompatible and 2 stopped Daemons could not be reused, use --status for details # \u0026gt; Configure project :app # WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats. # \u0026gt; Configure project :capacitor-cordova-android-plugins # WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats. # \u0026gt; Task :app:preBuild UP-TO-DATE # ... # \u0026gt; Task :capacitor-android:compileReleaseJavaWithJavac # FAILED # [Incubating] Problems report is available at: # file:///C:/Users/userName/work/TODOListApp/TODO%20List/android/build/reports/problems/problems-report.html # FAILURE: Build failed with an exception. # * What went wrong: # Execution failed for task \u0026#39;:capacitor-android:compileReleaseJavaWithJavac\u0026#39;. # \u0026gt; error: invalid source release: 21 # * Try: # \u0026gt; Run with --stacktrace option to get the stack trace. # \u0026gt; Run with --info or --debug option to get more log output. # \u0026gt; Run with --scan to get full insights. # \u0026gt; Get more help at https://help.gradle.org. # BUILD FAILED in 19s # 36 actionable tasks: 1 executed, 35 up-to-date JAVA_HOMEとは、Java に関するパスのことで、Android SDK に対して、正しいバージョンのJAVA がインストールされたパスを指定する必要がある。\n私の場合は、Android Studio がインストールされた場所に抱き合わせて存在する Java を指定することで、正しく Capacitor が動作するようになった。\n個別に分けてインストールした Java も使うことができると思われるが、基本的にバージョンを合わせるのがめんどくさすぎたので今回はそちらの方ではやらなかった。\n私の場合は、まず Android Studio が以下のパスにインストールされていた。\nC:\\Program Files\\Android\\Android Studio それで、Android Studio に抱き合わせでインストールされる Java は以下のパスにインストールされていた。(javaw.exeがあるかどうかがヒント)\nC:\\Program Files\\Android\\Android Studio\\jbr よって、以下のようにしてJAVA_HOMEを設定した。必ずしも今回示したパスに Java があるとは限らないので、各自確認する必要はある。\n$env:JAVA_HOME = \u0026#34;C:\\Program Files\\Android\\Android Studio\\jbr\u0026#34; ビルド Android Studio でビルドして署名させる (私的用途で使う場合) Android アプリは動くようにするために何かしらの形で、ストアアプリとして公開していなくても自己証明書による署名が必要なことが分かった。そこで今回は、Android Studio から直接自己証明書で署名されたアプリをビルドすることにした。\n自己証明書の生成から APK生成までの流れ Android Studio で Capacitor が生成したプロジェクトを開く。 # Web アプリの最新の開発内容を反映する npm run build npx cap sync # Android Studio で開く npx cap open android 署名付き APK を生成しようとする APK ファイルが生成される Loading personal and system profiles took 5096ms. (base) PS C:\\Users\\userName\\work\\TODOListApp\\TODO List\\android\\app\\release\u0026gt; ls Directory: C:\\Users\\userName\\work\\TODOListApp\\TODO List\\android\\app\\release Mode LastWriteTime Length Name ---- ------------- ------ ---- d----- 11/21/2025 10:05 PM baselineProfiles -a---- 11/21/2025 10:05 PM 3370918 app-release.apk -a---- 11/21/2025 10:05 PM 703 output-metadata.json npx cap 経由のビルド (私的用途で使う場合、うまく行かなかった) エラー例 署名を指定していない場合、npx cap 経由ではビルド時に以下のエラーが出る。ビルド自体は通っているが、署名に関する指定がされていないと怒られる。\nnpx cap build android # √ Running Gradle build in 3.28s # [error] Missing options. Please supply all options for android signing. (Keystore Path, Keystore Password, Keystore Key # Alias, Keystore Key Password) Capacitor 経由でのビルドによる署名に関しては、npx cap build androidをする時点で、引数として以下の項目を指定する必要がある。\n\u0026ndash;keystorepath \u0026ndash;keystorepass \u0026ndash;keystorealias \u0026ndash;keystorealiaspass # Web アプリの最新の開発内容を反映する npm run build npx cap sync # Android 向けにビルドする npx cap build android --keystorepath [\u0026#34;C:\\\\Path\\\\to\\\\key\\\\selfSign.jks\u0026#34;] --keystorepass [password ]--keystorealias [keyAliasName] --keystorealiaspass [password] --androidreleasetype APK ただ私の環境では結局、うまくビルドすることが以下のようになりできなかった。調べてみると、手動で署名している例がいくつかあり、npx cap build androidによる APK 生成はちゃんと動かない気がしている。\nnpx cap build android --keystorepath [\u0026#34;C:\\\\Path\\\\to\\\\key\\\\selfSign.jks\u0026#34;] --keystorepass [password ]--keystorealias [keyAliasName] --keystorealiaspass [password] --androidreleasetype APK # √ Running Gradle build in 2.56s # × Signing Release - failed! # [error] jarsigner: unable to open jar file: C:\\Users\\userName\\work\\TODOListApp\\TODO # List\\android\\app\\build\\outputs\\apk\\release\\app-release-unsigned.apk 自己証明書の生成 もし、Android Studio に署名させる (私的用途で使う場合) において自己証明書をまだ生成していない場合は、以下のようにして生成できるようである。\n以下は、[Build your app from the command line | Android Studio | Android Developers] https://developer.android.com/build/building-cmdlineの引用\nkeytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias やれること APK 生成 ビルド を参考にすること。\nテストラン # Web アプリの最新の開発内容を反映する npm run build npx cap sync # Android エミュレータでアプリとしてデバッグする npx cap run android Android Studio で開く # Web アプリの最新の開発内容を反映する npm run build npx cap sync # Android Studio で開く npx cap open android 参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年11月21日) Display all environment variables from a running PowerShell script - Stack Overflow\nhttps://stackoverflow.com/questions/39800481/display-all-environment-variables-from-a-running-powershell-script (2025年11月21日) Development Workflow | Capacitor Documentation\nhttps://capacitorjs.com/docs/basics/workflow (2025年11月21日) Android SDK location - Stack Overflow\nhttps://stackoverflow.com/questions/25176594/android-sdk-location (2025年11月21日) Setting Windows PowerShell environment variables - Stack Overflow\nhttps://stackoverflow.com/questions/714877/setting-windows-powershell-environment-variables (2025年11月21日) about_Environment_Variables - PowerShell | Microsoft Learn\nhttps://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_environment_variables?view=powershell-7.5 (2025年11月21日) Installing Capacitor | Capacitor Documentation\nhttps://capacitorjs.com/docs/getting-started (2025年11月21日) android - How can I create a keystore? - Stack Overflow\nhttps://stackoverflow.com/questions/3997748/how-can-i-create-a-keystore (2025年11月21日) Sign your app | Android Studio | Android Developers\nhttps://developer.android.com/studio/publish/app-signing (2025年11月21日) How to generate a new JKS/Keystore? - Handyman Services\nhttps://documentation.iqonic.design/handyman/app-faqs/how-to-generate-a-new-jks-keystore (2025年11月21日) SSL Certificate Country Codes\nhttps://knowledge.digicert.com/general-information/ssl-certificate-country-codes (2025年11月21日) Build your app from the command line | Android Studio | Android Developers\nhttps://developer.android.com/build/building-cmdline#gradle_signing (2025年11月21日) CLI Command - cap build | Capacitor Documentation\nhttps://capacitorjs.com/docs/cli/commands/build (2025年11月21日) [Bug]: Signing with build command still not working in 6.0.0-rc.0? · Issue #7299 · ionic-team/capacitor\nhttps://github.com/ionic-team/capacitor/issues/7299 (2025年11月21日) [Bug]: npx cap build not building signed apk with \u0026ndash;signing-type apksigner · Issue #7366 · ionic-team/capacitor\nhttps://github.com/ionic-team/capacitor/issues/7366 (2025年11月21日) Android build \u0026amp; sign with cap build android - missing app-release-unsigned.apk - Capacitor - Ionic Forum\nhttps://forum.ionicframework.com/t/android-build-sign-with-cap-build-android-missing-app-release-unsigned-apk/244780 (2025年11月21日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/reactwebapptoapkwithcapacitor/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　React で作った Web アプリを Android に移植しようとしたら超絶めんどくさかったので、記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"自分の試した構成\"\u003e自分の試した構成\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eAndroid Studio (with SDK)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm create vite@latest\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"使った汎用コマンド集\"\u003e使った汎用コマンド集\u003c/h2\u003e\n\u003ch3 id=\"すべての環境変数をリスト-windowspowershell\"\u003eすべての環境変数をリスト (Windows,PowerShell)\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egci env:* | sort-object name\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"環境変数を新規作成-windowspowershell\"\u003e環境変数を新規作成 (Windows,PowerShell)\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 具体例 ANDROID_HOME にパスを設定する\n$env:ANDROID_HOME = \u0026#34;C:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"特定の環境変数に対してパスを追加-windowspowershell\"\u003e特定の環境変数に対してパスを追加 (Windows,PowerShell)\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 具体例 ANDROID_HOME にパスを追加設定する\n$env:ANDROID_HOME += \u0026#34;;C:\\Users\\[userName]\\AppData\\Local\\Android\\Sdk\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"準備\"\u003e準備\u003c/h2\u003e\n\u003ch3 id=\"capacitor-を使えるようにする\"\u003eCapacitor を使えるようにする\u003c/h3\u003e\n\u003ch4 id=\"必要なパッケージのインストール\"\u003e必要なパッケージのインストール\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm i @capacitor/core\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm i @capacitor/android\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"初期化する\"\u003e初期化する\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpx cap init\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"android-向けに初期化する\"\u003eandroid 向けに初期化する\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpx cap add android\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"android_homeを設定する\"\u003e\u003ccode\u003eANDROID_HOME\u003c/code\u003eを設定する\u003c/h3\u003e\n\n\n\u003cp\u003e\u003cdetails \u003e\n  \u003csummary markdown=\"span\"\u003eエラー例\u003c/summary\u003e\n  \u003cp\u003e　Android SDK のパスが、\u003ccode\u003eANDROID_HOME\u003c/code\u003eとして環境変数に設定されていない場合は、以下のようなエラーが出てくる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpx cap build android\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# × Running Gradle build - failed!\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# [error]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Configure project :app\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Configure project :capacitor-cordova-android-plugins\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         WARNING: Using flatDir should be avoided because it doesn\u0026#39;t support any meta-data formats.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         FAILURE: Build failed with an exception.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         * What went wrong:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         Could not determine the dependencies of task \u0026#39;:app:bundleReleaseResources\u0026#39;.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; SDK location not found. Define a valid SDK location with an ANDROID_HOME environment variable or by setting\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         the sdk.dir path in your project\u0026#39;s local properties file at \u0026#39;C:\\Users\\userName\\work\\TODOListApp\\TODO\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         List\\android\\local.properties\u0026#39;.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         * Try:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Run with --stacktrace option to get the stack trace.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Run with --info or --debug option to get more log output.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Run with --scan to get full insights.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         \u0026gt; Get more help at https://help.gradle.org.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#         BUILD FAILED in 1s\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\u003c/details\u003e\u003c/p\u003e","title":"React を使った Web アプリを Android アプリにしたい"},{"content":"この記事を作った動機 lualatex でframedというパッケージを使おうとしたところ、framedに関するパッケージがないと言われ、対応に手間取ったので記録したい。\nエラーが出たときにインストールしていたTexLiveのパッケージ local/texlive-basic 2025.2-2 (texlive) TeX Live - Essential programs and files local/texlive-bin 2025.2-2 TeX Live binaries local/texlive-langcjk 2025.2-2 (texlive-lang) TeX Live - Chinese/Japanese/Korean (base) local/texlive-langjapanese 2025.2-2 (texlive-lang) TeX Live - Japanese local/texlive-latex 2025.2-2 (texlive) TeX Live - LaTeX fundamental packages local/texlive-latexrecommended 2025.2-2 (texlive) TeX Live - LaTeX recommended packages local/texlive-luatex 2025.2-2 (texlive) TeX Live - LuaTeX packages local/texlive-plaingeneric 2025.2-2 (texlive) TeX Live - Plain (La)TeX packages 問題があるとき 少なくとも、Arch linux環境においては、texlive-full以外の最小構成で TexLive をインストールしていると、パッケージがそろっていないことがあり、以下のようなエラーになることがある。\n! LaTeX Error: File `framed.sty\u0026#39; not found. Type X to quit or \u0026lt;RETURN\u0026gt; to proceed, or enter new name. (Default extension: sty) Enter file name: ! Emergency stop. \u0026lt;read *\u0026gt; l.11 731 words of node memory still in use: 6 hlist, 4 rule, 1 dir, 3 kern, 1 glyph, 116 attribute, 49 glue_spec, 18 att ribute_list, 1 write, 8 user_defined nodes avail lists: 1:4,2:122,3:3,4:4,5:1,6:1,7:7,9:8 ! ==\u0026gt; Fatal error occurred, no output PDF file produced! やったこと パッケージが足りないことが分かったため、texlive-latexextraをインストールした。texlive-fullはあまりに大きすぎて更新やインストールに時間がかかりすぎるため、当初はそれのインストールを試みていたが、中断した。\nyay -S texlive-latexextra # pacman -S texlive-latexextra 参考にしたサイトとか Arch Linux - texlive-latexextra 2025.2-2 (any)\nhttps://archlinux.org/packages/extra/any/texlive-latexextra/ (2025年11月19日) texlive - framed.sty not found after switching from OS X to Linux - TeX - LaTeX Stack Exchange\nhttps://tex.stackexchange.com/questions/163423/framed-sty-not-found-after-switching-from-os-x-to-linux (2025年11月19日) AUR (en) - texlive-full\nhttps://aur.archlinux.org/packages/texlive-full (2025年11月20日) ","permalink":"https://www.nyanmo.info/posts/linux/tex/packagenotfound/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　lualatex で\u003ccode\u003eframed\u003c/code\u003eというパッケージを使おうとしたところ、\u003ccode\u003eframed\u003c/code\u003eに関するパッケージがないと言われ、対応に手間取ったので記録したい。\u003c/p\u003e\n\u003ch2 id=\"エラーが出たときにインストールしていたtexliveのパッケージ\"\u003eエラーが出たときにインストールしていた\u003ccode\u003eTexLive\u003c/code\u003eのパッケージ\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003elocal/texlive-basic 2025.2-2 (texlive)\n    TeX Live - Essential programs and files\nlocal/texlive-bin 2025.2-2\n    TeX Live binaries\nlocal/texlive-langcjk 2025.2-2 (texlive-lang)\n    TeX Live - Chinese/Japanese/Korean (base)\nlocal/texlive-langjapanese 2025.2-2 (texlive-lang)\n    TeX Live - Japanese\nlocal/texlive-latex 2025.2-2 (texlive)\n    TeX Live - LaTeX fundamental packages\nlocal/texlive-latexrecommended 2025.2-2 (texlive)\n    TeX Live - LaTeX recommended packages\nlocal/texlive-luatex 2025.2-2 (texlive)\n    TeX Live - LuaTeX packages\nlocal/texlive-plaingeneric 2025.2-2 (texlive)\n    TeX Live - Plain (La)TeX packages\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"問題があるとき\"\u003e問題があるとき\u003c/h2\u003e\n\u003cp\u003e　少なくとも、Arch linux環境においては、\u003ccode\u003etexlive-full\u003c/code\u003e以外の最小構成で TexLive をインストールしていると、パッケージがそろっていないことがあり、以下のようなエラーになることがある。\u003c/p\u003e","title":"lualatex で framed が使えない (パッケージ不足)"},{"content":"内容 経緯に対して内容は少ないので、まずは先に書きたいことから書くことにした。\nやったこと 通販サイトで売っている、TP4056使った回路を USB DP 給電に対応させたかった。具体的には、手元にあった6kΩ程度の抵抗を使って、CCピンとGNDを接続し、5V を USB-PD に対応した充電器から引き出そうとしただけ。 起こったこと ケーブル次第でうまく USB-PD に対応した充電器から 5V を引き出せないことが分かった。試したところ e-maker が入っていて、充電器と機器の CC ピンが直接接続されず、ケーブル内で特別な IC を経由する構造になっている場合、うまく USB-PD から 5V を引き出せないようである。\n逆に、CC ピンがケーブル内において、直接充電器と機器の間で接続するようになっている 65w まで対応の安価なケーブルの場合において、抵抗で CC ピンをGNDにプルダウンするだけで、5Vが引き出せることが分かった。\nこの問題に関しては、専用の USB-PD のトリガーモジュールが別にあるので、5Vを引き出せる専用のモジュールを使えば、十分改善されると思われる。ただ、わざわざ USB-Type-C コネクタが最初からついていて、CC ピン自体もコネクタには実装されているにも関わらず、別のモジュールを使うのもなんだかもったいない気もした。　この記事を作った経緯 Amazon や Aliexpress とかで売っているようなリチウムイオン充電回路として、TP4056の IC を使ったものがあり、最近は Micro-USB ではなく、USB-Type-C コネクタがついているものが売られるようになった。\nしかし、少なくとも私が買った基板では、通常のフルサイズの USB-Type-A から USB-Type-C に変換するケーブルを使うなど、CC ピンによる USB PD 給電関連の交渉が必要ない場合は、通常どうり USB 充電器から 5V が供給されるが、USB-PD による交渉が必要な場合に動作しないというのがあった。\n基板をよく見てみると、USB PD に必要な CC ピン自体はコネクタからつながっており、基板上に配線もあったが、抵抗が実装されていないようであった。また実装されていない抵抗がもし実装されていたと仮定して、つながる先が、テスターで調べてみる限りGNDではなくVbusっぽくなぜそうしたのか意図がよくわからないということがあった。\nとにかく、USB-PD 給電を機能させたいと思い、適当に5.1kΩに近い抵抗を選んで、CC ピンへつながる配線を抵抗で挟んでGNDにつなげてみた。そしたら、最終的にケーブル次第で、うまく行く場合とうまく行かない場合があることが分かった。今回はそのことについて分かったことを記録を取りたいと思って記事を作った。\n参考にしたサイトとか Simple way to use USB Type-C to get 5V at up to 3A (15W) - Power - DigiKey TechForum - An Electronic Component and Engineering Solution Forum\nhttps://forum.digikey.com/t/simple-way-to-use-usb-type-c-to-get-5v-at-up-to-3a-15w/7016 (2025年11月14日)\nThe Differences Between Mini USB, Micro USB, and USB-C Explained – Memory Suppliers\nhttps://www.memorysuppliers.com/blogs/memory-suppliers-blog/guide-to-the-differences-between-mini-usb-micro-usb-and-usb-c?srsltid=AfmBOoqE8mcmaejDS7Jd9WhHW_z2C93DjC8PR18PH62uyHtrGx8VvZR4 (2025年11月14日)\n复件 tp4056_42_English_空页脚.doc\nhttps://dlnmh9ip6v2uc.cloudfront.net/datasheets/Prototyping/TP4056.pdf (2025年11月14日)\n","permalink":"https://www.nyanmo.info/posts/hardware/tp4056withusb_pd/","summary":"\u003ch2 id=\"内容\"\u003e内容\u003c/h2\u003e\n\u003cp\u003e　経緯に対して内容は少ないので、まずは先に書きたいことから書くことにした。\u003c/p\u003e\n\u003ch3 id=\"やったこと\"\u003eやったこと\u003c/h3\u003e\n\u003cp\u003e　通販サイトで売っている、\u003ccode\u003eTP4056\u003c/code\u003e使った回路を USB DP 給電に対応させたかった。具体的には、手元にあった\u003ccode\u003e6kΩ\u003c/code\u003e程度の抵抗を使って、\u003ccode\u003eCC\u003c/code\u003eピンと\u003ccode\u003eGND\u003c/code\u003eを接続し、5V を USB-PD に対応した充電器から引き出そうとしただけ。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/TP4056withUSB_PD/%e4%b8%8a%e3%81%8b%e3%82%89%e3%81%ae%e7%94%bb%e5%83%8f%20%e3%83%9e%e3%83%bc%e3%82%af%e4%bb%98%e3%81%8d.png#center\"\n         alt=\"上からの画像 マーク付き\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"起こったこと\"\u003e起こったこと\u003c/h3\u003e\n\u003cp\u003e　ケーブル次第でうまく USB-PD に対応した充電器から 5V を引き出せないことが分かった。試したところ \u003ccode\u003ee-maker\u003c/code\u003e が入っていて、充電器と機器の \u003ccode\u003eCC\u003c/code\u003e ピンが直接接続されず、ケーブル内で特別な IC を経由する構造になっている場合、うまく USB-PD から 5V を引き出せないようである。\u003c/p\u003e\n\u003cp\u003e　逆に、\u003ccode\u003eCC\u003c/code\u003e ピンがケーブル内において、直接充電器と機器の間で接続するようになっている \u003cstrong\u003e65w まで対応の安価なケーブルの場合\u003c/strong\u003eにおいて、抵抗で \u003ccode\u003eCC\u003c/code\u003e ピンを\u003ccode\u003eGND\u003c/code\u003eにプルダウンするだけで、5Vが引き出せることが分かった。\u003c/p\u003e\n\u003cp\u003e　この問題に関しては、専用の USB-PD のトリガーモジュールが別にあるので、5Vを引き出せる専用のモジュールを使えば、十分改善されると思われる。ただ、わざわざ USB-Type-C コネクタが最初からついていて、\u003ccode\u003eCC\u003c/code\u003e ピン自体もコネクタには実装されているにも関わらず、別のモジュールを使うのもなんだかもったいない気もした。　\u003c/p\u003e\n\u003ch2 id=\"この記事を作った経緯\"\u003eこの記事を作った経緯\u003c/h2\u003e\n\u003cp\u003e　Amazon や Aliexpress とかで売っているようなリチウムイオン充電回路として、\u003ccode\u003eTP4056\u003c/code\u003eの IC を使ったものがあり、最近は Micro-USB ではなく、USB-Type-C コネクタがついているものが売られるようになった。\u003c/p\u003e\n\u003cp\u003e　しかし、少なくとも私が買った基板では、通常のフルサイズの USB-Type-A から USB-Type-C に変換するケーブルを使うなど、CC ピンによる USB PD 給電関連の交渉が必要ない場合は、通常どうり USB 充電器から 5V が供給されるが、USB-PD による交渉が必要な場合に動作しないというのがあった。\u003c/p\u003e\n\u003cp\u003e　基板をよく見てみると、USB PD に必要な \u003ccode\u003eCC\u003c/code\u003e ピン自体はコネクタからつながっており、基板上に配線もあったが、抵抗が実装されていないようであった。また実装されていない抵抗がもし実装されていたと仮定して、つながる先が、テスターで調べてみる限り\u003ccode\u003eGND\u003c/code\u003eではなく\u003ccode\u003eVbus\u003c/code\u003eっぽくなぜそうしたのか意図がよくわからないということがあった。\u003c/p\u003e\n\u003cp\u003e　とにかく、USB-PD 給電を機能させたいと思い、適当に\u003ccode\u003e5.1kΩ\u003c/code\u003eに近い抵抗を選んで、\u003ccode\u003eCC\u003c/code\u003e ピンへつながる配線を抵抗で挟んで\u003ccode\u003eGND\u003c/code\u003eにつなげてみた。そしたら、最終的にケーブル次第で、うまく行く場合とうまく行かない場合があることが分かった。今回はそのことについて分かったことを記録を取りたいと思って記事を作った。\u003c/p\u003e","title":"TP4056 リチウムイオン電池充電基板をUSB PDで動かしたい"},{"content":"この記事を作った動機 単に、git pullして変更をリモートリポジトリからローカルリポジトリに反映しようと思ったときに、ローカルリポジトリ側に未反映の変更があり、衝突してマージに失敗することがある。そのような場合に、とにかくそのローカルリポジトリにある変更内容を破棄して、リモートリポジトリの変更を反映したいとき用に、記録をとりたい。\nローカルリポジトリの変更内容を保持しておきたいときは、git stash dropをする必要はない。\nとにかくリモートリポジトリの変更内容を反映する例 リモートリポジトリの変更をローカルに反映しようとしてエラーになる git pull remote: Enumerating objects: 56, done. remote: Counting objects: 100% (56/56), done. remote: Compressing objects: 100% (15/15), done. remote: Total 56 (delta 41), reused 56 (delta 41), pack-reused 0 (from 0) Unpacking objects: 100% (56/56), 6.00 KiB | 79.00 KiB/s, done. From github.com:hello30190f/OneNoteAlternative c539ef0..a484d7c master -\u0026gt; origin/master Updating c539ef0..a484d7c error: Your local changes to the following files would be overwritten by merge: firstPrototype/backend/dataServer/notebookData/test/contents/test.json Please commit your changes or stash them before you merge. Aborting ローカルリポジトリの変更を退避する git stash Saved working directory and index state WIP on master: c539ef0 save 退避したローカルリポジトリの変更を破棄する git stash drop Dropped refs/stash@{0} (e64f70a6e978cf0a154795872e0b07f6530123aa) ローカルリポジトリの変更を退避または破棄したことで、衝突しなくなる git pull Updating c539ef0..a484d7c Fast-forward .../commands/notebookAndPage/createNotebook.py | 6 +- .../commands/notebookAndPage/deletePage.py | 4 +- .../commands/notebookAndPage/updatePage.py | 4 +- firstPrototype/backend/dataServer/helper/common.py | 3 +- .../backend/dataServer/interrupts/controller.py | 10 +-- .../notebookData/newnote/contents/test.md | 3 +- .../notebookData/newnote/contents/testa.md | 10 ++- .../dataServer/notebookData/newnote/metadata.json | 17 +++- .../notebookData/newnote/metadata.json.backup | 17 +++- .../notebookData/newntoe/contents/asfsdfsdsss.md | 4 +- .../dataServer/notebookData/newntoe/metadata.json | 13 ++- .../notebookData/newntoe/metadata.json.backup | 13 ++- .../notebookData/test/contents/test.json | 99 +++++++++++++++++++++- .../notebookData/test/contents/test/anArticle1.md | 13 ++- .../test/contents/test/test2/testaaaa.json | 53 +++++++++++- .../notebookData/test/contents/test1.json | 11 +++ .../dataServer/notebookData/test/metadata.json | 25 +++++- .../notebookData/test/metadata.json.backup | 25 +++++- .../backend/dataServer/type/pages/free.py | 2 +- .../backend/dataServer/type/pages/markdown.py | 2 +- .../src/modules/FakepagesPath.tsx | 16 +++- firstPrototype/note/architecture.md | 2 +- 22 files changed, 321 insertions(+), 31 deletions(-) create mode 100644 firstPrototype/backend/dataServer/notebookData/test/contents/test1.json 参考にしたサイトとか Git - git-stash Documentation\nhttps://git-scm.com/docs/git-stash (2025年11月12日) ","permalink":"https://www.nyanmo.info/posts/other/gitthrowawaychanges/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に、\u003ccode\u003egit pull\u003c/code\u003eして変更をリモートリポジトリからローカルリポジトリに反映しようと思ったときに、ローカルリポジトリ側に未反映の変更があり、衝突してマージに失敗することがある。そのような場合に、とにかくそのローカルリポジトリにある変更内容を破棄して、リモートリポジトリの変更を反映したいとき用に、記録をとりたい。\u003c/p\u003e\n\u003cp\u003e　ローカルリポジトリの変更内容を保持しておきたいときは、\u003ccode\u003egit stash drop\u003c/code\u003eをする必要はない。\u003c/p\u003e\n\u003ch2 id=\"とにかくリモートリポジトリの変更内容を反映する例\"\u003eとにかくリモートリポジトリの変更内容を反映する例\u003c/h2\u003e\n\u003ch3 id=\"リモートリポジトリの変更をローカルに反映しようとしてエラーになる\"\u003eリモートリポジトリの変更をローカルに反映しようとしてエラーになる\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit pull\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: Enumerating objects: 56, \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: Counting objects: 100% \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e56/56\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: Compressing objects: 100% \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e15/15\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eremote: Total \u003cspan style=\"color:#ae81ff\"\u003e56\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edelta 41\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, reused \u003cspan style=\"color:#ae81ff\"\u003e56\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003edelta 41\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, pack-reused \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003efrom 0\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUnpacking objects: 100% \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e56/56\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, 6.00 KiB | 79.00 KiB/s, \u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFrom github.com:hello30190f/OneNoteAlternative\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   c539ef0..a484d7c  master     -\u0026gt; origin/master\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUpdating c539ef0..a484d7c\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eerror: Your local changes to the following files would be overwritten by merge:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        firstPrototype/backend/dataServer/notebookData/test/contents/test.json\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePlease commit your changes or stash them before you merge.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAborting\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ローカルリポジトリの変更を退避する\"\u003eローカルリポジトリの変更を退避する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit stash \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSaved working directory and index state WIP on master: c539ef0 save\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"退避したローカルリポジトリの変更を破棄する\"\u003e退避したローカルリポジトリの変更を破棄する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit stash drop\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDropped refs/stash@\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e0\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ee64f70a6e978cf0a154795872e0b07f6530123aa\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ローカルリポジトリの変更を退避または破棄したことで衝突しなくなる\"\u003eローカルリポジトリの変更を退避または破棄したことで、衝突しなくなる\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit pull\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUpdating c539ef0..a484d7c\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFast-forward\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../commands/notebookAndPage/createNotebook.py     |  \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../commands/notebookAndPage/deletePage.py         |  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../commands/notebookAndPage/updatePage.py         |  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e firstPrototype/backend/dataServer/helper/common.py |  \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../backend/dataServer/interrupts/controller.py    | \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e +--\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/newnote/contents/test.md          |  \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/newnote/contents/testa.md         | \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e ++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../dataServer/notebookData/newnote/metadata.json  | \u003cspan style=\"color:#ae81ff\"\u003e17\u003c/span\u003e +++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/newnote/metadata.json.backup      | \u003cspan style=\"color:#ae81ff\"\u003e17\u003c/span\u003e +++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/newntoe/contents/asfsdfsdsss.md   |  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../dataServer/notebookData/newntoe/metadata.json  | \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e ++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/newntoe/metadata.json.backup      | \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e ++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/test/contents/test.json           | \u003cspan style=\"color:#ae81ff\"\u003e99\u003c/span\u003e +++++++++++++++++++++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/test/contents/test/anArticle1.md  | \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e ++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../test/contents/test/test2/testaaaa.json         | \u003cspan style=\"color:#ae81ff\"\u003e53\u003c/span\u003e +++++++++++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/test/contents/test1.json          | \u003cspan style=\"color:#ae81ff\"\u003e11\u003c/span\u003e +++\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../dataServer/notebookData/test/metadata.json     | \u003cspan style=\"color:#ae81ff\"\u003e25\u003c/span\u003e +++++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../notebookData/test/metadata.json.backup         | \u003cspan style=\"color:#ae81ff\"\u003e25\u003c/span\u003e +++++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../backend/dataServer/type/pages/free.py          |  \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../backend/dataServer/type/pages/markdown.py      |  \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e .../src/modules/FakepagesPath.tsx                | \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e +++-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e firstPrototype/note/architecture.md                |  \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e +-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#ae81ff\"\u003e22\u003c/span\u003e files changed, \u003cspan style=\"color:#ae81ff\"\u003e321\u003c/span\u003e insertions\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e+\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e31\u003c/span\u003e deletions\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e-\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e create mode \u003cspan style=\"color:#ae81ff\"\u003e100644\u003c/span\u003e firstPrototype/backend/dataServer/notebookData/test/contents/test1.json\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eGit - git-stash Documentation\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/docs/git-stash\"\u003ehttps://git-scm.com/docs/git-stash\u003c/a\u003e (2025年11月12日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Git でローカルリポジトリの変更を退避、破棄する"},{"content":"この記事を作った動機 drag and drop の実装について毎回いちいち調べなおしている気がするので、自分用に記録を残したいと思った。\n引っかかった内容 drop イベントの受け取り方 単に、dropイベントを設定しただけでは、全く発火しない。dragoverの時点で、preventDefaultする必要があるようである。\n... acceptDropTag(){ // dragover で preventDefault しないことには機能しない this.info.addEventListener(\u0026#34;drop\u0026#34;,(event) =\u0026gt; { this.dragedTagName = event.dataTransfer.getData(\u0026#34;text/plain\u0026#34;) if(this.dragedTagName != null){ this.setTag(this.dragedTagName) } }) // drop イベントが発火するようにする this.info.addEventListener(\u0026#34;dragover\u0026#34;,(event) =\u0026gt; { event.preventDefault() }) } ... コンソールでは基本dataTransferの中身は見えないことがあるらしい dataTransferの中身は、ブラウザのコンソール内では正しく見えないようである。しかししばらくいろいろ実装を試してみたところ、すでに既存のスクリプト側でdragoverでpreventDefaultして何かしらdropイベントでdataTransferについて読み出したりしている状況において、ブラウザのコンソール側から以下のようなコードを実行してみると内容を見ることができた。\ndocument.querySelector(\u0026#34;#videoTable \u0026gt; a:nth-child(5) \u0026gt; div.videoInfoContainer \u0026gt; div.tagInfo\u0026#34;).addEventListener(\u0026#34;drop\u0026#34;,(event) =\u0026gt; {console.log(event.dataTransfer.getData(\u0026#34;text/plain\u0026#34;))}) // 何かしら内容が表示される。今回はタグ名として、`drive`という文字列を送るようにしていたので、以下のようにコンソールに出てきた。 // drive \u0026lt;- 取得したデータとしてコンソールに出力された内容 dragenter や dragleave では、datatransfer の中身が見えない？ dropイベントの発火の仕方が分からないときに、dragenterやdragleaveは発火して、その中にdataTransferの項目もイベントの引数の項目に含まれていたため、dataTransferの存在を知った当初はそれを使おうとしていた。\nしかし、自分で試してみたところ、どんなにdragstartでデータを設定しても、event.dataTransfer.items[0] とか event.dataTransfer.getData(\u0026quot;text/string\u0026quot;) してもエラーにはならないが、空の文字列が返ってきてしまったり何も得られなかった。\ndocument.querySelector(\u0026#34;#videoTable \u0026gt; a:nth-child(4) \u0026gt; div.videoInfoContainer \u0026gt; div.tagInfo\u0026#34;).addEventListener(\u0026#34;dragenter\u0026#34;,(event) =\u0026gt; {console.log(event)}) // DragEvent {isTrusted: true, dataTransfer: DataTransfer, screenX: 2366, screenY: 676, clientX: 830, …} // temp1 // コンソールで で \u0026#34;Store as global variables\u0026#34; をする。 temp1.dataTransfer.getData(\u0026#34;text/plain\u0026#34;) \u0026#39;\u0026#39; drag and drop に関する内容 よく使うイベント一覧 dragstart dragover drop 基本的なこと ドラッグされる側 (event はイベントをリッスンするときの引数を意味する) draggable=\u0026quot;true\u0026quot;属性を何かしらの形でHTMLタグ側に設定する。 dragstartイベントでドロップされた要素に渡したいデータを設定する。以下二つの選択肢がある。 event.dataTransfer.items.add(data,fromat) する。 event.dataTransfer.setData(format,data) する。 ドロップされる側 (event はイベントをリッスンするときの引数を意味する) dragoverでpreventDefaultして、dropイベントが発火するようにする。 dropイベントで、event.dataTransfer にアクセスしてデータを受け取る。 event.dataTransfer.items[indexNum]する。 event.dataTransfer.getData(format)する。 format 引数で指定する内容 dataTransferでデータをセットしたり読み出すには、データが何であるかタイプを指定する必要がある。ドキュメントのサンプルコードなどを見る限り、それはMIME typeを参照して文字列として指定すればいいと思われる。\nCommon media types - HTTP | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types (2025年11月11日) サンプルコード ドラッグされる側 ... tagButtonContaier.addEventListener(\u0026#34;dragstart\u0026#34;,(event) =\u0026gt; { event.dataTransfer.setData(\u0026#34;text/plain\u0026#34;,tag) }) ... ドロップされる側 ... acceptDropTag(){ // dragover で preventDefault しないことには機能しない this.info.addEventListener(\u0026#34;drop\u0026#34;,(event) =\u0026gt; { this.dragedTagName = event.dataTransfer.getData(\u0026#34;text/plain\u0026#34;) if(this.dragedTagName != null){ this.setTag(this.dragedTagName) } }) // drop イベントが発火するようにする this.info.addEventListener(\u0026#34;dragover\u0026#34;,(event) =\u0026gt; { event.preventDefault() }) } ... 参考にしたサイトとか javascript - event.dataTransfer.files is empty when ondrop is fired? - Stack Overflow\nhttps://stackoverflow.com/questions/11573710/event-datatransfer-files-is-empty-when-ondrop-is-fired (2025年11月11日) console.log(event.dataTransfer) is empty… but it fools you. | by Thorsten Koch | Medium\nhttps://medium.com/@thorsten.koch/console-log-event-datatransfer-is-empty-but-it-fools-you-1811decfdc9d (2025年11月11日) DragEvent: dataTransfer property - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/DragEvent/dataTransfer (2025年11月11日) DataTransferItemList: add() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/DataTransferItemList/add (2025年11月11日) DataTransfer.setData() - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/DataTransfer/setData (2025年11月11日) DataTransfer: getData() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/DataTransfer/getData (2025年11月11日) Drag operations - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API/Drag_operations#dropping (2025年11月11日) Common media types - HTTP | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types (2025年11月11日) HTMLElement: dragenter イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dragenter_event (2025年11月11日) HTMLElement: dragleave イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dragleave_event (2025年11月11日) HTMLElement: dragover イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dragover_event (2025年11月11日) HTMLElement: dragstart イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/HTMLElement/dragstart_event (2025年11月11日) HTMLElement: dragend event - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/dragend_event (2025年11月11日) HTMLElement: drop イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/HTMLElement/drop_event (2025年11月11日) DataTransfer - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/DataTransfer (2025年11月11日) DataTransferItem - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem (2025年11月11日) HTML Standard\nhttps://html.spec.whatwg.org/multipage/dnd.html#the-datatransfer-interface (2025年11月11日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/jsdraganddrop/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　drag and drop の実装について毎回いちいち調べなおしている気がするので、自分用に記録を残したいと思った。\u003c/p\u003e\n\u003ch2 id=\"引っかかった内容\"\u003e引っかかった内容\u003c/h2\u003e\n\u003ch3 id=\"drop-イベントの受け取り方\"\u003edrop イベントの受け取り方\u003c/h3\u003e\n\u003cp\u003e　単に、\u003ccode\u003edrop\u003c/code\u003eイベントを設定しただけでは、全く発火しない。\u003ccode\u003edragover\u003c/code\u003eの時点で、\u003ccode\u003epreventDefault\u003c/code\u003eする必要があるようである。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eacceptDropTag\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// dragover で preventDefault しないことには機能しない\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einfo\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;drop\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edragedTagName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edataTransfer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetData\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/plain\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edragedTagName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetTag\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edragedTagName\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// drop イベントが発火するようにする\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einfo\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dragover\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e) =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epreventDefault\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"コンソールでは基本datatransferの中身は見えないことがあるらしい\"\u003eコンソールでは基本\u003ccode\u003edataTransfer\u003c/code\u003eの中身は見えないことがあるらしい\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003edataTransfer\u003c/code\u003eの中身は、ブラウザのコンソール内では正しく見えないようである。しかししばらくいろいろ実装を試してみたところ、すでに既存のスクリプト側で\u003ccode\u003edragover\u003c/code\u003eで\u003ccode\u003epreventDefault\u003c/code\u003eして何かしら\u003ccode\u003edrop\u003c/code\u003eイベントで\u003ccode\u003edataTransfer\u003c/code\u003eについて読み出したりしている状況において、ブラウザのコンソール側から以下のようなコードを実行してみると内容を見ることができた。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocument.\u003cspan style=\"color:#a6e22e\"\u003equerySelector\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#videoTable \u0026gt; a:nth-child(5) \u0026gt; div.videoInfoContainer \u0026gt; div.tagInfo\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;drop\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e) =\u0026gt; {\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edataTransfer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetData\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/plain\u0026#34;\u003c/span\u003e))})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 何かしら内容が表示される。今回はタグ名として、`drive`という文字列を送るようにしていたので、以下のようにコンソールに出てきた。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// drive \u0026lt;- 取得したデータとしてコンソールに出力された内容\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"dragenter-や-dragleave-ではdatatransfer-の中身が見えない\"\u003e\u003ccode\u003edragenter\u003c/code\u003e や \u003ccode\u003edragleave\u003c/code\u003e では、datatransfer の中身が見えない？\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003edrop\u003c/code\u003eイベントの発火の仕方が分からないときに、\u003ccode\u003edragenter\u003c/code\u003eや\u003ccode\u003edragleave\u003c/code\u003eは発火して、その中に\u003ccode\u003edataTransfer\u003c/code\u003eの項目もイベントの引数の項目に含まれていたため、\u003ccode\u003edataTransfer\u003c/code\u003eの存在を知った当初はそれを使おうとしていた。\u003c/p\u003e\n\u003cp\u003e　しかし、自分で試してみたところ、どんなに\u003ccode\u003edragstart\u003c/code\u003eでデータを設定しても、\u003ccode\u003eevent.dataTransfer.items[0]\u003c/code\u003e とか \u003ccode\u003eevent.dataTransfer.getData(\u0026quot;text/string\u0026quot;)\u003c/code\u003e してもエラーにはならないが、空の文字列が返ってきてしまったり何も得られなかった。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocument.\u003cspan style=\"color:#a6e22e\"\u003equerySelector\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;#videoTable \u0026gt; a:nth-child(4) \u0026gt; div.videoInfoContainer \u0026gt; div.tagInfo\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dragenter\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e) =\u0026gt; {\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e)})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// DragEvent {isTrusted: true, dataTransfer: DataTransfer, screenX: 2366, screenY: 676, clientX: 830, …}\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// temp1 // コンソールで で \u0026#34;Store as global variables\u0026#34; をする。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003etemp1\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edataTransfer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetData\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/plain\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"drag-and-drop-に関する内容\"\u003edrag and drop に関する内容\u003c/h2\u003e\n\u003ch3 id=\"よく使うイベント一覧\"\u003eよく使うイベント一覧\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003edragstart\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edragover\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edrop\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"基本的なこと\"\u003e基本的なこと\u003c/h3\u003e\n\u003ch4 id=\"ドラッグされる側-event-はイベントをリッスンするときの引数を意味する\"\u003eドラッグされる側 (event はイベントをリッスンするときの引数を意味する)\u003c/h4\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003edraggable=\u0026quot;true\u0026quot;\u003c/code\u003e属性を何かしらの形でHTMLタグ側に設定する。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edragstart\u003c/code\u003eイベントでドロップされた要素に渡したいデータを設定する。以下二つの選択肢がある。\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eevent.dataTransfer.items.add(data,fromat)\u003c/code\u003e する。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eevent.dataTransfer.setData(format,data)\u003c/code\u003e する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch4 id=\"ドロップされる側-event-はイベントをリッスンするときの引数を意味する\"\u003eドロップされる側 (event はイベントをリッスンするときの引数を意味する)\u003c/h4\u003e\n\u003col\u003e\n\u003cli\u003e\u003ccode\u003edragover\u003c/code\u003eで\u003ccode\u003epreventDefault\u003c/code\u003eして、\u003ccode\u003edrop\u003c/code\u003eイベントが発火するようにする。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edrop\u003c/code\u003eイベントで、\u003ccode\u003eevent.dataTransfer\u003c/code\u003e にアクセスしてデータを受け取る。\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eevent.dataTransfer.items[indexNum]\u003c/code\u003eする。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eevent.dataTransfer.getData(format)\u003c/code\u003eする。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch4 id=\"format-引数で指定する内容\"\u003e\u003ccode\u003eformat\u003c/code\u003e 引数で指定する内容\u003c/h4\u003e\n\u003cp\u003e　\u003ccode\u003edataTransfer\u003c/code\u003eでデータをセットしたり読み出すには、データが何であるかタイプを指定する必要がある。ドキュメントのサンプルコードなどを見る限り、それは\u003ccode\u003eMIME type\u003c/code\u003eを参照して文字列として指定すればいいと思われる。\u003c/p\u003e","title":"JavaScript ドラックアンドドロップがうまくいかない"},{"content":"この記事を作った動機 JavaScript で何度か連発して起こった問題があったので、それを記録する。\n問題点 クラス内の関数を何かしらのコールバック関数として直接指定し、呼び出した場合に問題が起こる。その呼び出された関数内では、クラスに付属している変数を参照したり利用することができない。\nimport { tagListForIndexPage } from \u0026#34;./getTagInfo.js\u0026#34;; class sidebar{ constructor(){ new tagListForIndexPage() this.sidebarElem = document.querySelector(\u0026#34;.sidebar\u0026#34;) this.showAndHideButton = document.querySelector(\u0026#34;.headMenu .headItemContainer .sidebarShowAndHide\u0026#34;) this.currentState = \u0026#34;show\u0026#34; this.showAndHideButton.addEventListener(\u0026#34;click\u0026#34;,() =\u0026gt; { if(this.currentState == \u0026#34;hide\u0026#34;){ this.show() }else{ this.hide() } }) // 問題が起こらない部分 // 問題が起こらない部分 this.clacUI() // 問題が起こらない部分 // 問題が起こらない部分 // 問題の部分 // 問題の部分 addEventListener(\u0026#34;resize\u0026#34;,this.clacUI) // 問題の部分 // 問題の部分 this.hide() } clacUI(){ // 直接クラス内から呼び出されたときは、this.sidebarElemは参照できるが、 // クラス外のコールバックとして”直接”この関数を呼び出すと、this.sidebarElemが参照できずにundefinedでこける。 this.sidebarElem.style.height = String(window.innerHeight - 60) + \u0026#34;px\u0026#34; } show(){ this.currentState = \u0026#34;show\u0026#34; const replacement = this.sidebarElem.getAttribute(\u0026#34;class\u0026#34;).replaceAll(\u0026#34; hide\u0026#34;,\u0026#34;\u0026#34;) this.sidebarElem.setAttribute(\u0026#34;class\u0026#34;,replacement) } hide(){ this.currentState = \u0026#34;hide\u0026#34; let replacement = this.sidebarElem.getAttribute(\u0026#34;class\u0026#34;) if(!replacement.includes(\u0026#34;hide\u0026#34;)){ replacement += \u0026#34; hide\u0026#34; this.sidebarElem.setAttribute(\u0026#34;class\u0026#34;,replacement) } } } new sidebar() 解決としたこと 直接this.clacUIをaddEventListenerなどのコールバックとして呼び出すのではなく、匿名関数を一つはさんでからその内部で関数を呼び出すようにした。\nimport { tagListForIndexPage } from \u0026#34;./getTagInfo.js\u0026#34;; class sidebar{ constructor(){ new tagListForIndexPage() this.sidebarElem = document.querySelector(\u0026#34;.sidebar\u0026#34;) this.showAndHideButton = document.querySelector(\u0026#34;.headMenu .headItemContainer .sidebarShowAndHide\u0026#34;) this.currentState = \u0026#34;show\u0026#34; this.showAndHideButton.addEventListener(\u0026#34;click\u0026#34;,() =\u0026gt; { if(this.currentState == \u0026#34;hide\u0026#34;){ this.show() }else{ this.hide() } }) // 問題が起こらない部分 // 問題が起こらない部分 this.clacUI() // 問題が起こらない部分 // 問題が起こらない部分 // 問題を修正した部分 // 問題を修正した部分 addEventListener(\u0026#34;resize\u0026#34;,() =\u0026gt; {this.clacUI()}) // 問題を修正した部分 // 問題を修正した部分 this.hide() } clacUI(){ this.sidebarElem.style.height = String(window.innerHeight - 60) + \u0026#34;px\u0026#34; } show(){ this.currentState = \u0026#34;show\u0026#34; const replacement = this.sidebarElem.getAttribute(\u0026#34;class\u0026#34;).replaceAll(\u0026#34; hide\u0026#34;,\u0026#34;\u0026#34;) this.sidebarElem.setAttribute(\u0026#34;class\u0026#34;,replacement) } hide(){ this.currentState = \u0026#34;hide\u0026#34; let replacement = this.sidebarElem.getAttribute(\u0026#34;class\u0026#34;) if(!replacement.includes(\u0026#34;hide\u0026#34;)){ replacement += \u0026#34; hide\u0026#34; this.sidebarElem.setAttribute(\u0026#34;class\u0026#34;,replacement) } } } new sidebar() わからないこと 今回問題となった以下のコードの間における違いとしては、関数の呼び出し方によって見える変数や関数のスコープが異なるのではないかと考えられた。ただ具体的にじゃあ何のスコープに入っているのか？というのはすぐには見えてこなかった。\nうまく動かないコードでは、グローバルスコープを呼び出されたときに見ていてクラス内のスコープがうまく見えず、うまく動くコードでは、クラス内のスコープを見ているという違いはあるかもしれないとは考えられた。\nclass sidebar{ constructor(){ ... // うまく動かないコード addEventListener(\u0026#34;resize\u0026#34;,this.clacUI) ... } } class sidebar{ constructor(){ ... // うまく動くコード addEventListener(\u0026#34;resize\u0026#34;,() =\u0026gt; {this.clacUI()}) ... } } 参考にしたサイトとか クラス - JavaScript | MDN\nhttps://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes (2025年11月11日) Global scope (グローバルスコープ) - MDN Web Docs 用語集 | MDN\nhttps://developer.mozilla.org/ja/docs/Glossary/Global_scope (2025年11月11日) クロージャ - JavaScript | MDN\nhttps://developer.mozilla.org/ja/docs/Web/JavaScript/Guide/Closures (2025年11月11日) Scope (スコープ) - MDN Web Docs 用語集 | MDN\nhttps://developer.mozilla.org/ja/docs/Glossary/Scope (2025年11月11日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/jsclassvar/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　JavaScript で何度か連発して起こった問題があったので、それを記録する。\u003c/p\u003e\n\u003ch2 id=\"問題点\"\u003e問題点\u003c/h2\u003e\n\u003cp\u003e　クラス内の関数を何かしらのコールバック関数として直接指定し、呼び出した場合に問題が起こる。その呼び出された関数内では、クラスに付属している変数を参照したり利用することができない。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003etagListForIndexPage\u003c/span\u003e } \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;./getTagInfo.js\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esidebar\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econstructor\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etagListForIndexPage\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e document.\u003cspan style=\"color:#a6e22e\"\u003equerySelector\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.sidebar\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eshowAndHideButton\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e document.\u003cspan style=\"color:#a6e22e\"\u003equerySelector\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.headMenu .headItemContainer .sidebarShowAndHide\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrentState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;show\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eshowAndHideButton\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;click\u0026#34;\u003c/span\u003e,() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrentState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hide\u0026#34;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eshow\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehide\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題が起こらない部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題が起こらない部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclacUI\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題が起こらない部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題が起こらない部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題の部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題の部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;resize\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclacUI\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題の部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 問題の部分\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehide\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eclacUI\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 直接クラス内から呼び出されたときは、this.sidebarElemは参照できるが、\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// クラス外のコールバックとして”直接”この関数を呼び出すと、this.sidebarElemが参照できずにundefinedでこける。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e String(window.\u003cspan style=\"color:#a6e22e\"\u003einnerHeight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;px\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eshow\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrentState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;show\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetAttribute\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;class\u0026#34;\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003ereplaceAll\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34; hide\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetAttribute\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;class\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ehide\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrentState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hide\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetAttribute\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;class\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eincludes\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hide\u0026#34;\u003c/span\u003e)){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34; hide\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esidebarElem\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetAttribute\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;class\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ereplacement\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esidebar\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"解決としたこと\"\u003e解決としたこと\u003c/h2\u003e\n\u003cp\u003e　直接\u003ccode\u003ethis.clacUI\u003c/code\u003eを\u003ccode\u003eaddEventListener\u003c/code\u003eなどのコールバックとして呼び出すのではなく、匿名関数を一つはさんでからその内部で関数を呼び出すようにした。\u003c/p\u003e","title":"JavaScript でクラス内の変数にアクセスできない"},{"content":"この記事を作った動機 Blender と Cura を使って、なんか印刷しようとしていたところ、つくったモデルが思うようにスライスできないことが分かったので、その対処方法について自分用に記録をする。\n調べてみてもすぐにははっきりとしたことはわからず、全部のモデルの整合性に問題があるケースという意味では、全然網羅できてないと思うが、最終的に自分なりに心当たりのある部分を当ってみた感じにはなった。\nCura 上での挙動 問題があるとき モデルに問題があり、正常にスライスできない可能性があると、エラーメッセージが表示され、水色とピンク色であらわされる不適切な部分を示す領域がモデル上に表示される。 問題ながないとき 水色とピンク色であらわされる不適切な部分を示す領域が表示されることなく、エラーメッセージも出てこない。 ポイント 面が反転している 問題点の例 対応例 Blender 面を反転する に記録した。\n余計な面が内部に隠れている 問題点の例 対応例 Edit モードで、単純に余計な面を選択して消す。 面が重なってつながっていない部分がある 問題点の例 対応例 重なっているだけでうまくつながっていない面を消し、作り直す。\n面を削除する 面の作り直し\n必要な辺や点を選択してから、Fキーを押すことで面を新たに作成する。 面を作り直して、全体的に整合性が取れた様子 参考にしたサイトとか Why am I getting \u0026ldquo;Your model has missing or extraneous surfaces\u0026rdquo; popups in Ultimaker Cura?\nhttps://support.makerbot.com/s/article/1633018228456 (2025年11月7日) Missing or extraneous surfaces warning in Cura : r/3Dprinting\nhttps://www.reddit.com/r/3Dprinting/comments/n6ff1w/missing_or_extraneous_surfaces_warning_in_cura/ (2025年11月7日) Flip Normals (inverted faces) – Blender Knowledgebase\nhttps://www.katsbits.com/codex/flip-normals/ (2025年11月7日) How do I flip the normal on this polygon? : r/blender\nhttps://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/ (2025年11月7日) ","permalink":"https://www.nyanmo.info/posts/blender/curadoesntacceptexportedstlfilefromblender/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Blender と Cura を使って、なんか印刷しようとしていたところ、つくったモデルが思うようにスライスできないことが分かったので、その対処方法について自分用に記録をする。\u003c/p\u003e\n\u003cp\u003e　調べてみてもすぐにははっきりとしたことはわからず、全部のモデルの整合性に問題があるケースという意味では、全然網羅できてないと思うが、最終的に自分なりに心当たりのある部分を当ってみた感じにはなった。\u003c/p\u003e\n\u003ch2 id=\"cura-上での挙動\"\u003eCura 上での挙動\u003c/h2\u003e\n\u003ch3 id=\"問題があるとき\"\u003e問題があるとき\u003c/h3\u003e\n\u003cp\u003e　モデルに問題があり、正常にスライスできない可能性があると、エラーメッセージが表示され、水色とピンク色であらわされる不適切な部分を示す領域がモデル上に表示される。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/Cura%e3%81%a7%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e5%87%ba%e3%81%a6%e3%81%86%e3%81%be%e3%81%8f%e3%82%b9%e3%83%a9%e3%82%a4%e3%82%b9%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%e4%be%8b.png#center\"\n         alt=\"Curaでエラーが出てうまくスライスできない例\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"問題ながないとき\"\u003e問題ながないとき\u003c/h3\u003e\n\u003cp\u003e　水色とピンク色であらわされる不適切な部分を示す領域が表示されることなく、エラーメッセージも出てこない。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e4%bf%ae%e6%ad%a3%e3%81%97%e3%81%a6%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e5%87%ba%e3%81%aa%e3%81%8f%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"修正してエラーが出なくなった様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"ポイント\"\u003eポイント\u003c/h2\u003e\n\u003ch3 id=\"面が反転している\"\u003e面が反転している\u003c/h3\u003e\n\u003ch4 id=\"問題点の例\"\u003e問題点の例\u003c/h4\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/Cura%e3%81%a7%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%8c%e5%87%ba%e3%81%a6%e3%81%86%e3%81%be%e3%81%8f%e3%82%b9%e3%83%a9%e3%82%a4%e3%82%b9%e3%81%a7%e3%81%8d%e3%81%aa%e3%81%84%e4%be%8b.png#center\"\n         alt=\"Curaでエラーが出てうまくスライスできない例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e9%9d%a2%e3%81%ae%e5%90%91%e3%81%8d%e3%81%8c%e8%a1%a8%e7%a4%ba%e3%81%95%e3%82%8c%e3%81%9f%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"面の向きが表示された状態\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"対応例\"\u003e対応例\u003c/h4\u003e\n\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/blender/flipfacenormal/\"\u003eBlender 面を反転する\u003c/a\u003e に記録した。\u003c/p\u003e\n\u003ch3 id=\"余計な面が内部に隠れている\"\u003e余計な面が内部に隠れている\u003c/h3\u003e\n\u003ch4 id=\"問題点の例-1\"\u003e問題点の例\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e4%bd%99%e8%a8%88%e3%81%aa%e9%9d%a2%e3%82%92%e6%b6%88%e3%81%99%e4%be%8b.png#center\"\n         alt=\"余計な面を消す例\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"対応例-1\"\u003e対応例\u003c/h4\u003e\n\u003cp\u003e　Edit モードで、単純に余計な面を選択して消す。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e4%bd%99%e8%a8%88%e3%81%aa%e9%9d%a2%e3%82%92%e6%b6%88%e3%81%99%e4%be%8b.png#center\"\n         alt=\"余計な面を消す例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e4%bd%99%e8%a8%88%e3%81%aa%e9%9d%a2%e3%82%92%e6%b6%88%e3%81%99%e4%be%8b1.png#center\"\n         alt=\"余計な面を消す例1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e4%bd%99%e8%a8%88%e3%81%aa%e9%9d%a2%e3%82%92%e6%b6%88%e3%81%99%e4%be%8b2.png#center\"\n         alt=\"余計な面を消す例2\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"面が重なってつながっていない部分がある\"\u003e面が重なってつながっていない部分がある\u003c/h3\u003e\n\u003ch4 id=\"問題点の例-2\"\u003e問題点の例\u003c/h4\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e7%aa%81%e8%b5%b7%e7%89%a9%e3%81%ae%e4%b8%8b%e3%81%ab%e9%9d%a2%e3%81%8c%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e4%be%8b.png#center\"\n         alt=\"突起物の下に面が重なっている例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e3%81%b1%e3%81%a3%e3%81%a8%e8%a6%8b%e9%9d%a2%e3%81%8c%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%af%e8%a6%8b%e3%81%88%e3%81%aa%e3%81%84%e4%be%8b.png#center\"\n         alt=\"ぱっと見面が重なっているようには見えない例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e3%81%b1%e3%81%a3%e3%81%a8%e8%a6%8b%e9%9d%a2%e3%81%8c%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%af%e8%a6%8b%e3%81%88%e3%81%aa%e3%81%84%e4%be%8b1.png#center\"\n         alt=\"ぱっと見面が重なっているようには見えない例1\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch4 id=\"対応例-2\"\u003e対応例\u003c/h4\u003e\n\u003cp\u003e　重なっているだけでうまくつながっていない面を消し、作り直す。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e面を削除する\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e9%9d%a2%e3%82%92%e4%bf%ae%e6%ad%a3%e3%81%99%e3%82%8b%e4%be%8b-%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%9f%e9%9d%a2%e3%82%92%e5%89%8a%e9%99%a4%e3%81%99%e3%82%8b.png#center\"\n         alt=\"重なっている面を修正する例-重なった面を削除する\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e9%9d%a2%e3%82%92%e4%bf%ae%e6%ad%a3%e3%81%99%e3%82%8b%e4%be%8b-%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%9f%e9%9d%a2%e3%82%92%e5%89%8a%e9%99%a4%e3%81%99%e3%82%8b1.png#center\"\n         alt=\"重なっている面を修正する例-重なった面を削除する1\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e9%9d%a2%e3%82%92%e4%bf%ae%e6%ad%a3%e3%81%99%e3%82%8b%e4%be%8b-%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%9f%e9%9d%a2%e3%82%92%e5%89%8a%e9%99%a4%e3%81%992.png#center\"\n         alt=\"重なっている面を修正する例-重なった面を削除す2\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%9f%e9%9d%a2%e3%82%92%e5%89%8a%e9%99%a4%e3%81%97%e3%81%9f%e4%be%8b.png#center\"\n         alt=\"重なった面を削除した例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%87%8d%e3%81%aa%e3%81%a3%e3%81%9f%e9%9d%a2%e3%82%92%e5%89%8a%e9%99%a4%e3%81%97%e3%81%9f%e4%be%8b1.png#center\"\n         alt=\"重なった面を削除した例1\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003e面の作り直し\u003cbr\u003e\n　必要な辺や点を選択してから、\u003ccode\u003eF\u003c/code\u003eキーを押すことで面を新たに作成する。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e8%be%ba%e3%82%92%e9%81%b8%e6%8a%9e%e3%81%97%e3%81%a6%e9%9d%a2%e3%82%92%e4%bd%9c%e3%82%8a%e7%9b%b4%e3%81%99%e4%be%8b.png#center\"\n         alt=\"辺を選択して面を作り直す例\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003e面を作り直して、全体的に整合性が取れた様子\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%9d%a2%e3%82%92%e5%bc%b5%e3%82%8a%e7%9b%b4%e3%81%97%e3%81%8a%e3%81%88%e3%81%9f%e3%81%82%e3%81%a8%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"面を張り直しおえたあとの例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/CuraDoesntAcceptExportedSTLfileFromBlender/%e9%9d%a2%e3%82%92%e5%bc%b5%e3%82%8a%e7%9b%b4%e3%81%97%e3%81%8a%e3%81%88%e3%81%9f%e3%81%82%e3%81%a8%e3%81%ae%e4%be%8b1.png#center\"\n         alt=\"面を張り直しおえたあとの例1\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWhy am I getting \u0026ldquo;Your model has missing or extraneous surfaces\u0026rdquo; popups in Ultimaker Cura?\u003cbr\u003e\n\u003ca href=\"https://support.makerbot.com/s/article/1633018228456\"\u003ehttps://support.makerbot.com/s/article/1633018228456\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003cli\u003eMissing or extraneous surfaces warning in Cura : r/3Dprinting\u003cbr\u003e\n\u003ca href=\"https://www.reddit.com/r/3Dprinting/comments/n6ff1w/missing_or_extraneous_surfaces_warning_in_cura/\"\u003ehttps://www.reddit.com/r/3Dprinting/comments/n6ff1w/missing_or_extraneous_surfaces_warning_in_cura/\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003cli\u003eFlip Normals (inverted faces) – Blender Knowledgebase\u003cbr\u003e\n\u003ca href=\"https://www.katsbits.com/codex/flip-normals/\"\u003ehttps://www.katsbits.com/codex/flip-normals/\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003cli\u003eHow do I flip the normal on this polygon? : r/blender\u003cbr\u003e\n\u003ca href=\"https://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/\"\u003ehttps://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Blender で出力した STL ファイルを Cura でうまくスライスできない"},{"content":"この記事を作った動機 地味に面を反転する方法がわかりづらかったので自分用に改めて記録する。\nやり方 面を反転するオブジェクトを選択する 面の向きを表示する edit モードに入る 反転する面を選択する 面を反転する 面の向きが反転した後 参考にしたサイトとか Flip Normals (inverted faces) – Blender Knowledgebase\nhttps://www.katsbits.com/codex/flip-normals/ (2025年11月7日) How do I flip the normal on this polygon? : r/blender\nhttps://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/ (2025年11月7日) ","permalink":"https://www.nyanmo.info/posts/blender/flipfacenormal/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　地味に面を反転する方法がわかりづらかったので自分用に改めて記録する。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003ch3 id=\"面を反転するオブジェクトを選択する\"\u003e面を反転するオブジェクトを選択する\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e5%88%9d%e6%9c%9f%e7%8a%b6%e6%85%8b%e3%81%ae%e3%83%93%e3%83%a5%e3%83%bc.png#center\"\n         alt=\"初期状態のビュー\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"面の向きを表示する\"\u003e面の向きを表示する\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e9%9d%a2%e3%81%ae%e5%90%91%e3%81%8d%e3%82%92%e8%a1%a8%e7%a4%ba%e3%81%99%e3%82%8b.png#center\"\n         alt=\"面の向きを表示する\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e9%9d%a2%e3%81%ae%e5%90%91%e3%81%8d%e3%81%8c%e8%a1%a8%e7%a4%ba%e3%81%95%e3%82%8c%e3%81%9f%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"面の向きが表示された状態\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"edit-モードに入る\"\u003eedit モードに入る\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/edit%e3%83%a2%e3%83%bc%e3%83%89%e3%81%ab%e5%85%a5%e3%82%8b.png#center\"\n         alt=\"editモードに入る\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"反転する面を選択する\"\u003e反転する面を選択する\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e5%8f%8d%e8%bb%a2%e3%81%99%e3%82%8b%e9%9d%a2%e3%82%92%e9%81%b8%e6%8a%9e%e3%81%99%e3%82%8b.png#center\"\n         alt=\"反転する面を選択する\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"面を反転する\"\u003e面を反転する\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e9%9d%a2%e3%82%92%e5%8f%8d%e8%bb%a2%e3%81%99%e3%82%8b.png#center\"\n         alt=\"面を反転する\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"面の向きが反転した後\"\u003e面の向きが反転した後\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/flipFaceNormal/%e9%9d%a2%e3%81%8c%e5%8f%8d%e8%bb%a2%e3%81%95%e3%82%8c%e3%81%9f%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"面が反転された様子\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFlip Normals (inverted faces) – Blender Knowledgebase\u003cbr\u003e\n\u003ca href=\"https://www.katsbits.com/codex/flip-normals/\"\u003ehttps://www.katsbits.com/codex/flip-normals/\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003cli\u003eHow do I flip the normal on this polygon? : r/blender\u003cbr\u003e\n\u003ca href=\"https://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/\"\u003ehttps://www.reddit.com/r/blender/comments/1fbcqwc/how_do_i_flip_the_normal_on_this_polygon/\u003c/a\u003e (2025年11月7日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Blender 面を反転する"},{"content":"この記事を作った動機 最近適当に自分で作って使っていたChrome拡張機能がyoutube上で動作していないことが分かった。それで、調べてみると、CORSに引っかかっていた。そのことについて、さらにどうしたらいいか探ると、思ってたのと違う原因だったのでそのことを記録したいと思ったところ。\n最初は、バックエンドサーバ側のもともとCORSを通すようにしていた設定がいい加減すぎるのが良くないのかなと思っていたが、私の環境の場合、クライアント側(Google Chrome)に原因があった。\nクライアントから許可を出す プライベートネットワークを介してのバックエンドへのアクセスは、Google Chrome の場合、明示的に許可を出さないと、以下のようなエラーで引っかかる。 Access to XMLHttpRequest at \u0026#39;urlName\u0026#39; from origin \u0026#39;https://www.youtube.com\u0026#39; has been blocked by CORS policy: Permission was denied for this request to access the `unknown` address space. 許可を出すには、以下のようにして設定項目を探す。すでにLocal network accessの項目がこの時点で見えている場合はそこから設定しても問題ない。 この時点で、Local network accessの項目が見えない場合は、Settingsに進み、以下のようになるよう設定する。 バックエンドの実装 簡易的な実装として PHP を使い以下のようにCORSに関する実装をしている。この実装と、上記の設定でとりあえず動くところまではできた。\n// CORS setting header(\u0026#39;Access-Control-Allow-Origin: *\u0026#39;); header(\u0026#39;Access-Control-Allow-Methods: GET, POST, OPTIONS\u0026#39;); header(\u0026#34;Access-Control-Allow-Headers: X-Requested-With\u0026#34;); header(\u0026#34;Access-Control-Allow-Private-Network: true\u0026#34;); header(\u0026#34;Access-Control-Allow-Credentials: true\u0026#34;); if ($_SERVER[\u0026#39;REQUEST_METHOD\u0026#39;] === \u0026#39;OPTIONS\u0026#39;) { http_response_code(200); exit(); } 参考にしたサイトとか なんとなく CORS がわかる\u0026hellip;はもう終わりにする。 #JavaScript - Qiita\nhttps://qiita.com/att55/items/2154a8aad8bf1409db2b (2025年11月4日) getting cors issue no matter what [433208907] - Chromium\nhttps://issues.chromium.org/issues/433208907 (2025年11月4日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/corsinlocalareanetwork/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近適当に自分で作って使っていたChrome拡張機能がyoutube上で動作していないことが分かった。それで、調べてみると、CORSに引っかかっていた。そのことについて、さらにどうしたらいいか探ると、思ってたのと違う原因だったのでそのことを記録したいと思ったところ。\u003c/p\u003e\n\u003cp\u003e　最初は、バックエンドサーバ側のもともとCORSを通すようにしていた設定がいい加減すぎるのが良くないのかなと思っていたが、私の環境の場合、クライアント側(Google Chrome)に原因があった。\u003c/p\u003e\n\u003ch2 id=\"クライアントから許可を出す\"\u003eクライアントから許可を出す\u003c/h2\u003e\n\u003cp\u003e　プライベートネットワークを介してのバックエンドへのアクセスは、Google Chrome の場合、明示的に許可を出さないと、以下のようなエラーで引っかかる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/CORSinLocalAreaNetwork/CORS%e3%82%a8%e3%83%a9%e3%83%bc%e3%81%ae%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"CORSエラーの様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eAccess to XMLHttpRequest at \u0026#39;urlName\u0026#39; from origin \u0026#39;https://www.youtube.com\u0026#39; has been blocked by CORS policy: Permission was denied for this request to access the `unknown` address space.\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e　許可を出すには、以下のようにして設定項目を探す。すでに\u003ccode\u003eLocal network access\u003c/code\u003eの項目がこの時点で見えている場合はそこから設定しても問題ない。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/CORSinLocalAreaNetwork/%e8%a8%ad%e5%ae%9aUI%e3%82%92%e9%96%8b%e3%81%8f.png#center\"\n         alt=\"設定UIを開く\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/CORSinLocalAreaNetwork/LAN%e5%86%85%e3%81%a7%e3%81%ae%e3%82%a2%e3%82%af%e3%82%bb%e3%82%b9%e3%82%92%e8%a8%b1%e5%8f%af%e3%81%99%e3%82%8b%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"LAN内でのアクセスを許可する様子1\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cp\u003e　この時点で、\u003ccode\u003eLocal network access\u003c/code\u003eの項目が見えない場合は、\u003ccode\u003eSettings\u003c/code\u003eに進み、以下のようになるよう設定する。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/CORSinLocalAreaNetwork/%e8%a8%ad%e5%ae%9a%e7%94%bb%e9%9d%a2%e3%81%ab%e9%80%b2%e3%82%80.png#center\"\n         alt=\"設定画面に進む\"/\u003e \n\u003c/figure\u003e\n\u003cbr\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/webDevelop/CORSinLocalAreaNetwork/%e6%a8%a9%e9%99%90%e3%81%ae%e8%a8%ad%e5%ae%9a.png#center\"\n         alt=\"権限の設定\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"バックエンドの実装\"\u003eバックエンドの実装\u003c/h2\u003e\n\u003cp\u003e　簡易的な実装として PHP を使い以下のようにCORSに関する実装をしている。この実装と、上記の設定でとりあえず動くところまではできた。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// CORS setting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eheader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Access-Control-Allow-Origin: *\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eheader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Access-Control-Allow-Methods: GET, POST, OPTIONS\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eheader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Access-Control-Allow-Headers: X-Requested-With\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eheader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Access-Control-Allow-Private-Network: true\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eheader\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Access-Control-Allow-Credentials: true\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($_SERVER[\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;REQUEST_METHOD\u0026#39;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;OPTIONS\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ehttp_response_code\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eなんとなく CORS がわかる\u0026hellip;はもう終わりにする。 #JavaScript - Qiita\u003cbr\u003e\n\u003ca href=\"https://qiita.com/att55/items/2154a8aad8bf1409db2b\"\u003ehttps://qiita.com/att55/items/2154a8aad8bf1409db2b\u003c/a\u003e (2025年11月4日)\u003c/li\u003e\n\u003cli\u003egetting cors issue no matter what [433208907] - Chromium\u003cbr\u003e\n\u003ca href=\"https://issues.chromium.org/issues/433208907\"\u003ehttps://issues.chromium.org/issues/433208907\u003c/a\u003e (2025年11月4日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ローカルで動かしているバックエンドにつながらない"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 最近 Microsoft 社のネイティブの RDP クライアントや MS Store で配布されている純正 RDP クライアントや Windows に標準搭載されている RDP クライアントプログラムに不満があるというのがあった。\nちょっと前までは、Windows 環境では標準搭載されている RDP クライアントプログラムを使っていた。Windows に対してのRDP接続では自動的にクライアントとRDP接続先が、画面の解像度やスケーリング情報をやり取りしていたため 問題なしとしていたし、 RDP 接続先としての Linux 環境側も X11 の設定を使い、手動で解像度を変えることで対応していて、それでいったん良しとしていた。\nしかし、Linux 環境に RDP 接続する場合において、GNOME 49 の本格的な X11 環境が廃止があり、簡単に画面の解像度を変更できなくなったため、そうとは行かなくなった。\nそれで、私の環境でも NVIDIA 製 GPU を使っていても、Wayland にしないと、更新後 gdm サービスが立ち上がらないということになってしまったため、NVIDIA が提供する X11 上で動作する設定画面が使えなくなった。EDID という、ディスプレイの情報をローレベルで強引に書き換えるなどしなければ、自由な解像度で RDP 接続先としての Linux 環境が使えなくなってしまった。\nこうして、いろんな我慢が積み重なり、そろそろいい加減何とかしようと思って、 Guacamole を見つけ、試していたというのがあった。私の今の理解だと、Guacamole とは、apache から出ている Tomcat 上で動作し、ブラウザでアクセスすることで使うことができる RDP VNC その他もろもろのクライアントとして使うことができる Web アプリという認識である。\nとりあえず現状ではすべてについて記録を一気にとるのは現実的ではなかったので、とりあえず、書きやすいところや、記録に残しておきたいところを優先的に先に記録を残してみることにした。\nGuacamoleが動作している様子 ログイン画面 接続先選択画面 動いている様子 設定方法 ここはまだ、というかまだとりあえず動いただけで、安定的な稼働までには至っていないってのがある。 このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） Systemd におけるサービス例 (/etc/systemd/system/guacd-custom.service) guacd を root で実行するのは色々と好ましく無いと思われるので、存在する標準ユーザをUser=に指定する。私は現時点では、通常メインで使っている管理用ユーザを指定している。また動的ライブラリの問題に対応するために、Environment=\u0026quot;LD_LIBRARY_PATH=/usr/local/lib\u0026quot;が必要である。\n[Unit] Description=\u0026#34;Guacd backend for the Guacamole frontend on localhost:4822(TCP).\u0026#34; # After= [Service] Type=simple User=[userNameOnTheHost] Environment=\u0026#34;LD_LIBRARY_PATH=/usr/local/lib\u0026#34; ExecStart=/usr/local/sbin/guacd -f Restart=on-failure [Install] WantedBy=multi-user.target コンフィグ周りについて RDP接続設定の記述例 (/etc/guacamole/user-mapping.xml) \u0026lt;user-mapping\u0026gt; \u0026lt;authorize username=\u0026#34;userName\u0026#34; password=\u0026#34;password\u0026#34;\u0026gt; \u0026lt;connection name=\u0026#34;aRDPconnection\u0026#34;\u0026gt; \u0026lt;protocol\u0026gt;rdp\u0026lt;/protocol\u0026gt; \u0026lt;param name=\u0026#34;hostname\u0026#34;\u0026gt;192.168.x.x\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;port\u0026#34;\u0026gt;3389\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;username\u0026#34;\u0026gt;[ユーザ名]\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;password\u0026#34;\u0026gt;[パスワード]\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;ignore-cert\u0026#34;\u0026gt;true\u0026lt;/param\u0026gt; \u0026lt;/connection\u0026gt; \u0026lt;connection name=\u0026#34;aVNCconnection\u0026#34;\u0026gt; \u0026lt;protocol\u0026gt;vnc\u0026lt;/protocol\u0026gt; \u0026lt;param name=\u0026#34;hostname\u0026#34;\u0026gt;192.168.x.x\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;port\u0026#34;\u0026gt;5900\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;username\u0026#34;\u0026gt;[ユーザ名]\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;password\u0026#34;\u0026gt;[パスワード]\u0026lt;/param\u0026gt; \u0026lt;param name=\u0026#34;ignore-cert\u0026#34;\u0026gt;true\u0026lt;/param\u0026gt; \u0026lt;/connection\u0026gt; \u0026lt;/authorize\u0026gt; \u0026lt;/user-mapping\u0026gt; tomcat9 で動作する Guacamole フロントエンドの設定 (/etc/guacamole/guacamole.properties) guacd バックエンド接続先 ユーザ認証方式についての指定 guacd-hostname: localhost guacd-port: 4822 lib-directory: /etc/guacamole/extensions auth-provider: net.sourceforge.guacamole.net.basic.BasicFileAuthenticationProvider user-mapping: /etc/guacamole/user-mapping.xml 気づいたことや躓いたこと 接続先の設定が一つしかないとき 自然に設定された接続先が一つしか存在しない場合、XMLでコンフィグ設置をする方法では、ログイン後直接自動的に接続され、選択画面は表示されなかった。\nどんなアプリなのか勘違いしていた 最初は、なんかRDPとかを完全に置き換えるようなバックエンドも包括した Web ベースの何かかと思ったが、実際には画面を共有するために実際に画面をキャプチャしたり、接続先の制御をおこなうバックエンドは RDP VNC SSH などのメジャーなものが対応し、GNOME内臓の RDP バックエンドなどを使うことが分かった。\nいろいろ試しているうちに、Guacamole はあくまで Web ベースのリモートデスクトップ、リモートシェルのクライアントであることが分かった。\nguacd が必要な動的ライブラリを読み込めていない なんか少なくとも私の Linux 環境では、ライブラリの標準の読み込みパスと、guacd が読み込むことを想定している動的ライブラリの配置場所が違うことが、エラーメッセージをたどったりしてたどり着いた、Apache Guacamole でVNCつないでみたの #guacamole - Qiita という記事を読んでわかり、実際に動かすところまで持っていくことができた。\n具体的には、LD_LIBRARY_PATH の環境変数として、Guacamole のバックエンドが必要とするライブラリが実際に存在するパスを指定しないといけないようである。以下の動的ライブラリが読み込めない場合、RDP に接続できなかったりする。\nls /usr/local/lib/libguac-client* # -rw-r--r--⠀root⠀5339894⠀Oct 28 05:25:26⠀⠀libguac-client-rdp.a # -rwxr-xr-x⠀root⠀1170 ⠀Oct 28 05:25:26⠀⠀libguac-client-rdp.la* # -rwxr-xr-x⠀root⠀2784128⠀Oct 28 05:25:26⠀⠀libguac-client-rdp.so* # -rwxr-xr-x⠀root⠀2784128⠀Oct 28 05:25:26⠀⠀libguac-client-rdp.so.0* # -rwxr-xr-x⠀root⠀2784128⠀Oct 28 05:25:26⠀⠀libguac-client-rdp.so.0.0.0* # -rw-r--r--⠀root⠀641330 ⠀Oct 28 05:25:27⠀⠀libguac-client-ssh.a # -rwxr-xr-x⠀root⠀1245 ⠀Oct 28 05:25:27⠀⠀libguac-client-ssh.la* # -rwxr-xr-x⠀root⠀388056 ⠀Oct 28 05:25:27⠀⠀libguac-client-ssh.so* # -rwxr-xr-x⠀root⠀388056 ⠀Oct 28 05:25:27⠀⠀libguac-client-ssh.so.0* # -rwxr-xr-x⠀root⠀388056 ⠀Oct 28 05:25:27⠀⠀libguac-client-ssh.so.0.0.0* # -rw-r--r--⠀root⠀860494 ⠀Oct 28 05:25:28⠀⠀libguac-client-vnc.a # -rwxr-xr-x⠀root⠀1152 ⠀Oct 28 05:25:28⠀⠀libguac-client-vnc.la* # -rwxr-xr-x⠀root⠀505152 ⠀Oct 28 05:25:28⠀⠀libguac-client-vnc.so* # -rwxr-xr-x⠀root⠀505152 ⠀Oct 28 05:25:28⠀⠀libguac-client-vnc.so.0* # -rwxr-xr-x⠀root⠀505152 ⠀Oct 28 05:25:28⠀⠀libguac-client-vnc.so.0.0.0* 私の環境の場合は、/usr/local/lib/配下に必要なライブラリが配置されていたので、以下のようにしてみたところ、直接起動としてはとりあえず動いた。\nLD_LIBRARY_PATH=/usr/local/lib /usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822 -L debug # guacd[87930]: INFO: Guacamole proxy daemon (guacd) version 1.6.0 started # guacd[87930]: DEBUG: Successfully bound AF_INET socket to host 127.0.0.1, port 4822 # guacd[87930]: INFO: Listening on host 127.0.0.1, port 4822 # guacd[87930]: INFO: Creating new client for protocol \u0026#34;rdp\u0026#34; # guacd[87930]: INFO: Connection ID is \u0026#34;$7cd3298c-b86f-4162-9f81-c0d38c6a1ad8\u0026#34; # guacd[87988]: DEBUG: Processing instruction: size # guacd[87988]: DEBUG: Processing instruction: audio # guacd[87988]: DEBUG: Processing instruction: video # guacd[87988]: DEBUG: Processing instruction: image # guacd[87988]: DEBUG: Processing instruction: timezone # guacd[87988]: DEBUG: Processing instruction: name # guacd[87988]: DEBUG: Parameter \u0026#34;console\u0026#34; omitted. Using default value of 0. ./configure 時の様子 RDP サポートが RDP ........... yes になっている。\n./configure --with-systemd-dir=/usr/local/lib/systemd/system # ... # # ------------------------------------------------ # guacamole-server version 1.6.0 # ------------------------------------------------ # # Library status: # # freerdp ............. yes (2.x) # pango ............... yes # libavcodec .......... yes # libavformat ......... yes # libavutil ........... yes # libssh2 ............. yes # libssl .............. yes # libswscale .......... yes # libtelnet ........... no # libVNCServer ........ yes # libvorbis ........... yes # libpulse ............ yes # libwebsockets ....... no # libwebp ............. yes # wsock32 ............. no # # Protocol support: # # Kubernetes .... no # RDP ........... yes # SSH ........... yes # Telnet ........ no # VNC ........... yes # # Services / tools: # # guacd ...... yes # guacenc .... yes # guaclog .... yes # # FreeRDP plugins: /usr/lib/freerdp2 # Init scripts: no # Systemd units: /usr/local/lib/systemd/system make install 時の様子 /usr/local/lib にライブラリが配置されていると言われる。\nsudo make install # ... # ---------------------------------------------------------------------- # Libraries have been installed in: # /usr/local/lib # # If you ever happen to want to link against installed libraries # in a given directory, LIBDIR, you must either use libtool, and # specify the full pathname of the library, or use the \u0026#39;-LLIBDIR\u0026#39; # flag during linking and do at least one of the following: # - add LIBDIR to the \u0026#39;LD_LIBRARY_PATH\u0026#39; environment variable # during execution # - add LIBDIR to the \u0026#39;LD_RUN_PATH\u0026#39; environment variable # during linking # - use the \u0026#39;-Wl,-rpath -Wl,LIBDIR\u0026#39; linker flag # - have your system administrator add LIBDIR to \u0026#39;/etc/ld.so.conf\u0026#39; # # See any operating system documentation about shared libraries for # more information, such as the ld(1) and ld.so(8) manual pages. # -------------------------------------------------------------------- # ... 何も設定なしに、guacd を直接起動し、RDP接続を試す様子 ライブラリが欠損しているというエラーが直接出るのではなく、単にサポートされていませんと言われて、接続が失敗する。\n/usr/local/sbin/guacd -f -b 127.0.0.1 -l 4822 # guacd[67624]: INFO: Guacamole proxy daemon (guacd) version 1.6.0 started # guacd[67624]: INFO: Listening on host 127.0.0.1, port 4822 # guacd[67624]: INFO: Creating new client for protocol \u0026#34;rdp\u0026#34; # guacd[67624]: INFO: Connection ID is \u0026#34;$ffb6b3e5-ec2c-45af-b11e-5d4dcbd25f19\u0026#34; # guacd[67627]: WARNING: Support for protocol \u0026#34;rdp\u0026#34; is not installed # guacd[67624]: INFO: Connection \u0026#34;$ffb6b3e5-ec2c-45af-b11e-5d4dcbd25f19\u0026#34; removed. # guacd[67624]: INFO: Creating new client for protocol \u0026#34;rdp\u0026#34; # guacd[67624]: INFO: Connection ID is \u0026#34;$78959ca6-d616-4193-814d-19bb046a109b\u0026#34; # guacd[67633]: WARNING: Support for protocol \u0026#34;rdp\u0026#34; is not installed # guacd[67624]: INFO: Connection \u0026#34;$78959ca6-d616-4193-814d-19bb046a109b\u0026#34; removed. ... AUR に guacd っぽいものがあるが。。。 AUR に guacamole-server という名前で、guacd らしきものが存在しているが、これは正常にインストールできなかった。具体的には以下のコンパイルエラーが出てこけてしまう。\nguacamole 公式からソースコードをダウンロードしてきて、コンパイルする分にはエラーにならなかったので、多分 AUR にあるそのリポジトリ自体の何かがおかしいのだろうとは思うが、とりあえず動かないということでこのことについては置いている。\nCCLD libguac.la In function \u0026#39;inet_pton\u0026#39;, inlined from \u0026#39;__guac_wol_send_packet\u0026#39; at wol.c:104:18, inlined from \u0026#39;guac_wol_wake\u0026#39; at wol.c:192:22: /usr/include/bits/inet-fortified.h:56:10: error: call to \u0026#39;__inet_pton_chk_warn\u0026#39; declared with attribute warning: inet_pton called with a destination buffer size too small [-Werror=attribute-warning] 56 | return __glibc_fortify (inet_pton, __sz, sizeof (char), | ^ lto1: all warnings being treated as errors make[4]: *** [/tmp/ccVyGcaM.mk:4: /tmp/ccuZSjG4.ltrans1.ltrans.o] Error 1 make[4]: *** Waiting for unfinished jobs.... lto-wrapper: fatal error: make returned 2 exit status compilation terminated. /usr/bin/ld: error: lto-wrapper failed collect2: error: ld returned 1 exit status make[3]: *** [Makefile:728: libguac.la] エラー 1 make[3]: ディレクトリ \u0026#39;/home/username/.cache/yay/guacamole-server/src/guacamole-server-1.6.0/src/libguac\u0026#39; から出ます make[2]: *** [Makefile:1214: all-recursive] エラー 1 make[2]: ディレクトリ \u0026#39;/home/username/.cache/yay/guacamole-server/src/guacamole-server-1.6.0/src/libguac\u0026#39; から出ます make[1]: *** [Makefile:551: all-recursive] エラー 1 make[1]: ディレクトリ \u0026#39;/home/username/.cache/yay/guacamole-server/src/guacamole-server-1.6.0\u0026#39; から出ます make: *** [Makefile:471: all] エラー 2 ==\u0026gt; エラー: build() で問題が発生しました。 中止... -\u0026gt; ビルド時にエラー: guacamole-server-exit status 4 ... -\u0026gt; Failed to install the following packages. Manual intervention is required: guacamole-server - exit status 4 細かいクライアント設定 私の環境では、Alt + Ctrl + Shift キーの同時押して以下の画面が出てきた。 Tomcat と JAVA バージョン このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） Tomcat は Java を使って動作しているとのことだが、Javaのデフォルトで使われるもののバージョンがいまいち合わないということがあるっぽく、私の環境では手動でその項目について修正する必要があることが分かった。\nguacd が正しく動作せず、コンパイルが通らない (2026/4/1) 問題の説明と導入 久しぶりに、Guacamole の放置していたことをなんとかしようと思ったところ、guacd のバックエンドにおいて新たな問題が発生し、前動いてたやり方で動かないということに直面したため、それについて起こったことややったことを記録する。\n具体的には、guacd-が必要な動的ライブラリを読み込めていないの動的ライブラリを探索するパスをあらかじめ明示する手順を踏んでもSupport for protocol \u0026quot;rdp\u0026quot; is not installedと言われて動かなかったり、guacdのバックエンド自体が良くないのかなと思い、Apache Guacamole® 公式からソースコードをダウンロードしてguacdを新たにコンパイルしようとすると以下のようなエラーに見舞われたりして、にっちもさっちも行かなくなったということがある。\nコンパイルの様子 wget https://apache.org/dyn/closer.lua/guacamole/1.6.0/source/guacamole-server-1.6.0.tar.gz?action=download -O guacamole-server-1.6.0.tar.gz ls # -rw-r--r--⠀userName⠀1252749⠀Jun 20 06:50:32⠀⠀guacamole-server-1.6.0.tar.gz tar xfv guacamole-server-1.6.0.tar.gz cd guacamole-server-1.6.0 ls # -rw-r--r--⠀userName ⠀Jun 20 06:46:07⠀⠀aclocal.m4 # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀bin/ # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀build-aux/ # -rw-r--r--⠀userName ⠀Jun 20 06:46:08⠀⠀config.h.in # -rwxr-xr-x⠀userName 20 06:46:08⠀⠀configure* # -rw-r--r--⠀userName ⠀Jun 17 07:52:47⠀⠀configure.ac # -rw-r--r--⠀userName ⠀May 11 13:21:40⠀⠀CONTRIBUTING # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀doc/ # -rw-r--r--⠀userName ⠀Jun 17 07:52:47⠀⠀Dockerfile # -rw-r--r--⠀userName ⠀May 11 13:21:40⠀⠀LICENSE # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀m4/ # -rw-r--r--⠀userName ⠀Dec 6 13:04:36⠀⠀Makefile.am # -rw-r--r--⠀userName ⠀Jun 20 06:46:08⠀⠀Makefile.in # -rw-r--r--⠀userName ⠀May 11 13:21:40⠀⠀NOTICE # -rw-r--r--⠀userName ⠀Dec 4 12:58:44⠀⠀README # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀src/ # drwxr-xr-x⠀userName ⠀Jun 20 06:48:29⠀⠀util/ ./configure # ... # configure: WARNING: # -------------------------------------------- # Unable to find libwebsockets. # Support for Kubernetes will be disabled. # -------------------------------------------- # ... # ------------------------------------------------ # guacamole-server version 1.6.0 # ------------------------------------------------ # # Library status: # # freerdp ............. yes (2.x) # pango ............... yes # libavcodec .......... yes # libavformat ......... yes # libavutil ........... yes # libssh2 ............. yes # libssl .............. yes # libswscale .......... yes # libtelnet ........... no # libVNCServer ........ yes # libvorbis ........... yes # libpulse ............ yes # libwebsockets ....... no # libwebp ............. yes # wsock32 ............. no # # Protocol support: # # Kubernetes .... no # RDP ........... yes # SSH ........... yes # Telnet ........ no # VNC ........... yes # # Services / tools: # # guacd ...... yes # guacenc .... yes # guaclog .... yes # # FreeRDP plugins: /usr/lib/freerdp2 # Init scripts: no # Systemd units: no # # Type \u0026#34;make\u0026#34; to compile guacamole-server. # make # make all-recursive # make[1]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0\u0026#39; に入ります # Making all in src/libguac # make[2]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0/src/libguac\u0026#39; に入ります # Making all in . # make[3]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0/src/libguac\u0026#39; に入ります # CC libguac_la-argv.lo # CC libguac_la-audio.lo # In file included from raw_encoder.h:23, # from audio.c:28: # ../../config.h:290:9: error: \u0026#39;_XOPEN_SOURCE\u0026#39; redefined [-Werror] # 290 | #define _XOPEN_SOURCE 700 # | ^~~~~~~~~~~~~ # In file included from /usr/include/unistd.h:25, # from guacamole/socket-fntypes.h:31, # from guacamole/socket.h:31, # from guacamole/client-fntypes.h:33, # from guacamole/client.h:29, # from audio.c:24: # /usr/include/features.h:234:10: note: this is the location of the previous definition # 234 | # define _XOPEN_SOURCE 800 # | ^~~~~~~~~~~~~ # cc1: all warnings being treated as errors # make[3]: *** [Makefile:824: libguac_la-audio.lo] エラー 1 # make[3]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0/src/libguac\u0026#39; から出ます # make[2]: *** [Makefile:1214: all-recursive] エラー 1 # make[2]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0/src/libguac\u0026#39; から出ます # make[1]: *** [Makefile:551: all-recursive] エラー 1 # make[1]: ディレクトリ \u0026#39;/home/userName/work/test1/guacamole-server-1.6.0\u0026#39; から出ます # make: *** [Makefile:471: all] エラー 2 今回試したこと 今回試したことには、以下の項目がある。最終的に強硬コンパイル案が動く結果となった。\nguacamole/guacd - Docker Image の docker コンテナを-p 4822:4822で localhost に露出した状態で guacd のバックエンドとして使うことを試した。(Google Gemini Fast 3の提案) guacd において、コンパイルの警告などは抑圧して無視し、とにかく押し通す。(Google Gemini Fast 3の提案) 詳細な説明 guacamole/guacd - Docker Imageの docker イメージを使う案では、最新のイメージでは、事前に環境構築された物を使っているはずにもかかわらず、動的ライブラリの配置がおかしくSupport for protocol \u0026quot;rdp\u0026quot; is not installedと出てきて、正しい動的ライブラリをLD_LIBRARY_PATH=/opt/guacamole/libとして明示するまで正しく動作しなかった。具体的には以下のようにして、guacdを再起動するような形態を取って無理やり動かした。\n# ログを出したいだけなら、guacamole/guacd を起動したあと、一旦 guacd を kill して一定時間ポートが利用可能になるまで待ち、guacd がバックグランドで実行されないよう -f を指定することで実現できる。 # docker ps # docker exec [コンテナID] pkill guacd; sleep 20; guacd -f # これはコンテナが即座に終了してしまい、うまく動かない # docker ps # docker exec -it [コンテナID] sh -c \u0026#34;pkill guacd; sleep 20; env LD_LIBRARY_PATH=/opt/guacamole/lib guacd -f -L debug\u0026#34; # 以下は \u0026#34;pkill guacd; sleep 20; env LD_LIBRARY_PATH=/opt/guacamole/lib guacd -f -L debug\u0026#34; を参考として Gemini fast 3 にコマンドを吐かせた例。 docker run -it --rm \\ -e LD_LIBRARY_PATH=/opt/guacamole/lib \\ guacamole/guacd:1.6.0 \\ /bin/sh -c \u0026#34;/opt/guacamole/sbin/guacd -f -L debug\u0026#34; ちなみに、docker コンテナ版guacdバックエンドはどうあがいても動きそうで動かないって感じで、どんなセキュリティタイプを試しても、RDP server closed/refused connection: Server refused connection (wrong security type?)と言われ結局今回は動かなかった。バージョンを 1.5.x をランダムに試しても似たような症状が見受けられ、古いバージョンと新しいバージョンの違いは、古いバージョンの docker guacd コンテナは動的ライブラリパスを細工しなくてもとりあえず Support for protocol \u0026quot;rdp\u0026quot; is not installed と言われずにその点については動くということでしかなかった。\ndocker ps docker exec [コンテナID] pkill guacd; sleep 20; guacd -f # guacd[1]: INFO:\tCreating new client for protocol \u0026#34;rdp\u0026#34; # guacd[1]: INFO:\tConnection ID is \u0026#34;$1af0c6b9-bb78-4d92-b044-ffc94251fe4d\u0026#34; # guacd[3934]: INFO:\tSecurity mode: TLS # guacd[3934]: INFO:\tResize method: none # guacd[3934]: INFO:\tNo clipboard line-ending normalization specified. Defaulting to preserving the format of all line endings. # guacd[3934]: INFO:\tUser \u0026#34;@d7a9fe67-cff0-4429-ae09-a62465e910c3\u0026#34; joined connection \u0026#34;$1af0c6b9-bb78-4d92-b044-ffc94251fe4d\u0026#34; (1 users now present) # guacd[3934]: INFO:\tLocal system reports 32 processor(s) are available. # guacd[3934]: INFO:\tGraphical updates will be encoded using 32 worker thread(s). # guacd[3934]: INFO:\tLoading keymap \u0026#34;base\u0026#34; # guacd[3934]: INFO:\tLoading keymap \u0026#34;en-us-qwerty\u0026#34; # guacd[3934]: INFO:\tRDP server closed/refused connection: Server refused connection (wrong security type?) # guacd[3934]: INFO:\tUser \u0026#34;@d7a9fe67-cff0-4429-ae09-a62465e910c3\u0026#34; disconnected (0 users remain) # guacd[3934]: INFO:\tLast user of connection \u0026#34;$1af0c6b9-bb78-4d92-b044-ffc94251fe4d\u0026#34; disconnected # guacd[1]: INFO:\tConnection \u0026#34;$1af0c6b9-bb78-4d92-b044-ffc94251fe4d\u0026#34; removed. 試したことや説明 前提として以下のパッケージを明示的にインストールする。\nyay -S openssl-1.1 freerdp2 はっきりとこれらのパッケージが今回の問題の原因かわかっていないが、いくつか心当たりがある点がある。\n心当たりがある点の説明 openssl-1.1についてはこの記事を書いた初期においては、消していなかったが、つい最近アップグレード事にコンパイルに時間がかかっていて、邪魔そうだったからアップグレード時に片付けとして消したということがあった。それで、Google Gemini Fast 3 に色々今回の問題について具体的に何が起こっているか投げつけていると、Guacamole が新しい OpenSSL 3.0 を対応していないという説を出してきていて、確かに RDP では通信内容の暗号化関連で SSL 周りの問題は有り得そうなことから、インストールし直した経緯があった。\nfreerdp2については、消したりインストールした自覚がないが、この記事を書き始めた当初においては、なにかのパッケージの依存関係として存在していた可能性があった。現在 AUR において、freerdp はメジャーバージョンが 3 以上になっている。(Arch Linux - freerdp 2:3.24.2-1 (x86_64)) この点についても、Google Gemini Fast 3 は Guacamole において互換性の問題があるとして、トラブルシュートの最中にインストールした。私的には、コンパイル時に共有されている/usr/include配下のパッケージマネージャによって管理されているであろう、ヘッダファイルがコンパイルエラーの理由として出てくるところも確かに、freerdp と Guacamole の相性問題が出ている事を示唆しているようにも見える。\nmake # ... # ../../config.h:290:9: error: \u0026#39;_XOPEN_SOURCE\u0026#39; redefined [-Werror] # 290 | #define _XOPEN_SOURCE 700 # | ^~~~~~~~~~~~~ # In file included from /usr/include/unistd.h:25, # from guacamole/socket-fntypes.h:31, # from guacamole/socket.h:31, # from guacamole/client-fntypes.h:33, # from guacamole/client.h:29, # from audio.c:24: # /usr/include/features.h:234:10: note: this is the location of the previous definition # 234 | # define _XOPEN_SOURCE 800 # | ^~~~~~~~~~~~~ # ... 次に、コンパイルを行う。既に Guacamole-Server のソースコードについてダウンロードや展開を行い、展開されたフォルダ内に移動している事を想定する。\n# 以下は Gemini Fast 3 の提案 export CPPFLAGS=\u0026#34;-U_XOPEN_SOURCE -D_XOPEN_SOURCE=700\u0026#34; ./configure --with-rdp CFLAGS=\u0026#34;-Wno-error\u0026#34; make install これで、再びguacd-が必要な動的ライブラリを読み込めていないの手順に従うと、動くことが確認できた。試行錯誤の過程で存在する動作に影響を与えるような重要なポイントについていくつか書き漏らしている気もするが、思い出せる範囲だとこんなところであった。\nおまけ おまけというか、せっかく自前のブログなので、自由にしたいというのもあり、私の主観で、自由に気持ちを吐き出すって感じで、ここから先は不満について書いています。人によっては気分を害したりするかもしれませんから、ここで一応注意書きはしておきます。\n具体的な Microsoft の提供するRDP クライアントの不満 ネイティブクライアントについて 私がネイティブクライアントと呼んでいるのは、Windows XP 時代からあるような Win32 なプログラムのことについてである。MS Store にあるようなものではない。\n私がこの RDP クライアントについて不満な点は以下の通りである。\nRDP 接続先との解像度が合わないときのスケーリングが微妙 一応スケーリングできるが、決まった倍率にしかスケーリングできず、使っているクライアントの画面の解像度次第では、全然サイズが合わない。しかも解像度が合わないときの挙動が、なんか最初から全画面表示を指定したときと、後からRDP接続した後や一度全画面表示を解除した後に、ウィンドウを操作する方法して全画面表示にしようとしたときに、異なる挙動となっているところも不満点かもしれない。\n何もスケーリングしていないとき 最初から全画面の指定にしたとき あとから全画面表示にしようとしたとき スケーリングが合わず小さすぎる例 スケーリングが合わず大きすぎる例 とにかく Windows 以外の接続先と相性が悪い　以下は、GNOME RDP 環境に接続しようとしてエラーが出ている様子であるが、ユーザ名やパスワードを間違えても、それ以外の何かしらの障害だったとしても、More data is available しか出てきたためしがない。GNOME デスクトップ自体が障害時に、うわっ、何かがおかしいみたいです！みたいなエラー文を全画面表示で出すように、具体的に何が問題なのか説明があまりに欠けていて、これだけではわからないということがある。\n現状どうなっているかとか、ログをいろいろ怪しいところを漁るとか、すぐには解決を期待できない時間のかかる地獄のようなデバック作業になる。それは、今回説明するやつも同じといえばそうかもしれないが。。。 Windows でしか使えない そもそも RDP エコスステム全体が MS の Windows のための産物って感じで、一応 RDP についての PDF のドキュメント があるけど暗号みたいなわかりづらいのしかないし、Androidとか、Linux環境とか、MACとかその他いろいろあるプラットフォームに対して優しくないという点がある。Linux 環境には、Remmina がありそれが使えるが、いちいち専用クライアントソフトを入れないと使えないというところがやはり手軽とはいいがたいところ。\nRDP 的なものは、手軽に頻繁に使いたいものの一つなので、ブラウザ一つでアクセスして利用できるというのはありがたいと思う。\nMS Store にある RDP アプリについて ちょっと前の Win10 時代には、スケーリングも画面に合わせてできて、自前の環境に接続可能なモートデスクトップアプリが MS Store に存在していたが、今は少なくとも正攻法では利用不可能なようである。\n今は、Windows App なる「絶対課金させるぞ！ベンダーロックインするぞ！」って気満々のアカウントログイン必須、サブスク前提のアプリに置き換えられており、MS のクラウドを意地でも強引に使わせようと躍起になっているところがうかがえ、私にとっては最悪である。\n多分ターゲットは iPhoneを使っているとかモバイルな世界で、公式ストアにある審査に通ったアプリしか使いませんという、浅く使いお金は落とすが、その行動が将来的にどうなるか影響については考えられておらず、言われるがままに正しいとされる存在に従い、技術的にやられてしまったらそのことも分からないような以下に示すような人たちであると思われる。\n過労など、強烈な苦しみに毎日さいなまれているなど、考えられないような状況下にある 自分の本意と他人の意図の区別がついていないなど何かしら自覚のない状態であり、従っていることのないように疑問を持つ習慣がない 自分の本意が分かっていない、自分が分からない人 自らの意図したとおりに物事が進んでいない、最終的に到達されていないが、それに自覚がない人 私としては、どうしてもこういうやりかたは、搾取や弱いものいじめっていう印象を受ける。\nちなみにちょっと前評価を見たときにはコメントがあって、「前のリモートデスクトップアプリから移行しろと指示があったので移行したところ、ログインしないと使えない仕様だった。最悪！」みたいなコメントにあふれていた。今(2025/10/25)、そのコメントについて確認しようとしたところ、NX domain となり、MS Store サイト自体が吹き飛んでいてカオスな予感だった。なんか今まで見聞きした中で感じることとしては、 Win Vista 時代の Windows Live っぽい雰囲気である。\n結局単に RDP アプリとして見るならば、旧来のオプションを強制的に封じて、商業的、政治的な理由を社会的大義の建前やあたりさわりの良いマーケティングの言葉で包む（新しいことを強調する、”完全なセキュリティー”などと言い現実的ではない理想を実現したかのように謳う）をして新規ユーザを既存のブランドと相まって説得し強引に取り込もうとしながら、昔から使っていたユーザーには反感を買うようなことをするのは結構マイナスなことであると思われるが、MS的にはそれはどうでもいいのだろうとも思える。\n私としては、新しいものを出すのはいいが、旧来のものを使い続けることを否定し、新しいものを強制されるのはいただけないと思うところである。もちろん現状では、MS Store ではなく、Windows 標準で入っている RDP クライアントに関しては、利用可能だし、暫定的な利用としては機能は使えるほどにはある。しかし、知ってる人は知っているが、知らない人は知らないって感じな気がして、これから初めましての人にとってはあってないような選択肢だと思われる。\nまあ、Internet explorer の話といい、Windows 10 強制アップグレードの話といい、これからも Microsoft は同じことを繰り返すのだろうとは思う。また、EUがその時には登場するのだろうか。。。\n参考にしたサイトとか Welcome! - The Apache HTTP Server Project\nhttps://httpd.apache.org/ (2025年10月30日)\nApache Tomcat® - Welcome!\nhttps://tomcat.apache.org/ (2025年10月30日)\nApache Guacamole でVNCつないでみたの #guacamole - Qiita\nhttps://qiita.com/sandopan65/items/b7beecfe70c79e354371 (2025年10月30日)\nConfiguring Guacamole — Apache Guacamole Manual v1.6.0\nhttps://guacamole.apache.org/doc/gug/configuring-guacamole.html (2025年10月30日)\nAUR (en) - guacamole-server\nhttps://aur.archlinux.org/packages/guacamole-server (2025年10月30日)\nHow to change Java version used by TOMCAT? - Stack Overflow\nhttps://stackoverflow.com/questions/4072260/how-to-change-java-version-used-by-tomcat (2025年10月30日)\nChapter 3. Configuring Guacamole\nhttps://guacamole.apache.org/doc/0.9.1/gug/configuring-guacamole.html (2025年10月30日)\nInstalling Guacamole natively — Apache Guacamole Manual v1.6.0\nhttps://guacamole.apache.org/doc/gug/guacamole-native.html (2025年10月30日)\nGuacamole’s user interface — Apache Guacamole Manual v1.6.0\nhttps://guacamole.apache.org/doc/gug/using-guacamole.html (2025年10月30日)\nInstalling Guacamole with Docker — Apache Guacamole Manual v1.6.0\nhttps://guacamole.apache.org/doc/gug/guacamole-docker.html (2025年10月30日)\nApache Guacamole®: 1.6.0\nhttps://guacamole.apache.org/releases/1.6.0/ (2025年10月30日)\nApache Guacamole®\nhttps://guacamole.apache.org/ (2025年10月30日)\nHow to change Apache Tomcat web server port number - Stack Overflow\nhttps://stackoverflow.com/questions/18415578/how-to-change-apache-tomcat-web-server-port-number (2025年10月30日)\nApache Tomcat 9 Configuration Reference (9.0.111) - The HTTP Connector\nhttps://tomcat.apache.org/tomcat-9.0-doc/config/http.html (2025年10月30日)\nTomcat の初期設定まとめ #JavaEE - Qiita\nhttps://qiita.com/hidekatsu-izuno/items/ab604b6c764b5b5a86ed (2025年10月30日)\nApache Tomcat 9 Configuration Reference (9.0.111) - Container Provided Filters\nhttps://tomcat.apache.org/tomcat-9.0-doc/config/filter.html (2025年10月30日)\nApache Tomcat 9 Configuration Reference (9.0.111) - Overview\nhttps://tomcat.apache.org/tomcat-9.0-doc/config/index.html (2025年10月30日)\nImplementation and architecture — Apache Guacamole Manual v1.6.0\nhttps://guacamole.apache.org/doc/gug/guacamole-architecture.html (2025年10月30日)\nGuacamole shows error: Support for protocol RDP is not installed - Support - NethServer Community\nhttps://community.nethserver.org/t/guacamole-shows-error-support-for-protocol-rdp-is-not-installed/15526/4 (2025年10月30日)\n[MS-RDSOD]: Remote Desktop Services Protocols Overview | Microsoft Learn\nhttps://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-rdsod/072543f9-4bd4-4dc6-ab97-9a04bf9d2c6a (2025年10月30日)\nMicrosoft down? Current problems and outages | Downdetector\nhttps://downdetector.com/status/microsoft/ (2025年10月30日)\nMS Store\nhttps://apps.microsoft.com/ (2025年10月30日)\nMicrosoft\u0026rsquo;s Greatest Flop - YouTube\nhttps://www.youtube.com/watch?v=12LDsYpbLO4 (2025年10月30日) Google Gemini\nhttps://gemini.google.com/app (2026年4月1日)\nguacamole/guacd - Docker Image\nhttps://hub.docker.com/r/guacamole/guacd (2026年4月1日)\nChapter 3. Configuring Guacamole\nhttps://guacamole.apache.org/doc/0.9.6/gug/configuring-guacamole.html (2026年4月1日)\nAUR (en) - guacamole-server\nhttps://aur.archlinux.org/packages/guacamole-server (2026年4月1日)\nAUR (en) - guacamole-client\nhttps://aur.archlinux.org/packages/guacamole-client (2026年4月1日)\nTomcat - ArchWiki\nhttps://wiki.archlinux.org/title/Tomcat (2026年4月1日)\nGNOME remote desktop RDP problem with Apache Guacamole - Desktop - GNOME Discourse\nhttps://discourse.gnome.org/t/gnome-remote-desktop-rdp-problem-with-apache-guacamole/20703 (2026年4月1日)\nApache Guacamole server. RDP server closed/refused connection: Server refused connection (wrong security type?) - Stack Overflow\nhttps://stackoverflow.com/questions/78455945/apache-guacamole-server-rdp-server-closed-refused-connection-server-refused-co (2026年4月1日)\nInstall Guacamole on Debian 11 - kifarunix.com\nhttps://kifarunix.com/install-guacamole-on-debian-11/#fix-rdp-security-negotiation-failed (2026年4月1日)\nAUR (en) - freerdp2\nhttps://aur.archlinux.org/packages/freerdp2 (2026年4月2日)\nAUR (en) - openssl-1.1\nhttps://aur.archlinux.org/packages/openssl-1.1 (2026年4月2日)\nArch Linux - openssl 3.6.1-1 (x86_64)\nhttps://archlinux.org/packages/core/x86_64/openssl/ (2026年4月2日)\nArch Linux - freerdp 2:3.24.2-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/freerdp/ (2026年4月2日)\n","permalink":"https://www.nyanmo.info/posts/linux/guacamolewithrdp/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 Microsoft 社のネイティブの RDP クライアントや MS Store で配布されている純正 RDP クライアントや Windows に標準搭載されている RDP クライアントプログラムに不満があるというのがあった。\u003c/p\u003e\n\u003cp\u003e　ちょっと前までは、Windows 環境では標準搭載されている RDP クライアントプログラムを使っていた。Windows に対してのRDP接続では自動的にクライアントとRDP接続先が、画面の解像度やスケーリング情報をやり取りしていたため 問題なしとしていたし、 RDP 接続先としての Linux 環境側も X11 の設定を使い、手動で解像度を変えることで対応していて、それでいったん良しとしていた。\u003c/p\u003e\n\u003cp\u003e　しかし、Linux 環境に RDP 接続する場合において、GNOME 49 の本格的な X11 環境が廃止があり、簡単に画面の解像度を変更できなくなったため、そうとは行かなくなった。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/GuacamoleWithRDP/Windows%e3%83%8d%e3%82%a4%e3%83%86%e3%82%a3%e3%83%96RDP%e3%82%af%e3%83%a9%e3%82%a4%e3%82%a2%e3%83%b3%e3%83%88.png#center\"\n         alt=\"WindowsネイティブRDPクライアント\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　それで、私の環境でも NVIDIA 製 GPU を使っていても、Wayland にしないと、更新後 \u003ccode\u003egdm\u003c/code\u003e サービスが立ち上がらないということになってしまったため、NVIDIA が提供する X11 上で動作する設定画面が使えなくなった。EDID という、ディスプレイの情報をローレベルで強引に書き換えるなどしなければ、自由な解像度で RDP 接続先としての Linux 環境が使えなくなってしまった。\u003c/p\u003e\n\u003cp\u003e　こうして、いろんな我慢が積み重なり、そろそろいい加減何とかしようと思って、 Guacamole を見つけ、試していたというのがあった。私の今の理解だと、Guacamole とは、apache から出ている Tomcat 上で動作し、ブラウザでアクセスすることで使うことができる RDP VNC その他もろもろのクライアントとして使うことができる Web アプリという認識である。\u003c/p\u003e\n\u003cp\u003e　とりあえず現状ではすべてについて記録を一気にとるのは現実的ではなかったので、とりあえず、書きやすいところや、記録に残しておきたいところを優先的に先に記録を残してみることにした。\u003c/p\u003e\n\u003ch2 id=\"guacamoleが動作している様子\"\u003e\u003ccode\u003eGuacamole\u003c/code\u003eが動作している様子\u003c/h2\u003e\n\u003ch3 id=\"ログイン画面\"\u003eログイン画面\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/GuacamoleWithRDP/%e3%83%ad%e3%82%b0%e3%82%a4%e3%83%b3%e7%94%bb%e9%9d%a2.png#center\"\n         alt=\"ログイン画面\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"接続先選択画面\"\u003e接続先選択画面\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/GuacamoleWithRDP/%e6%8e%a5%e7%b6%9a%e5%85%88%e9%81%b8%e6%8a%9e%e7%94%bb%e9%9d%a2.png#center\"\n         alt=\"接続先選択画面\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"動いている様子\"\u003e動いている様子\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/GuacamoleWithRDP/%e5%ae%9f%e9%9a%9b%e3%81%ab%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"実際に動かしている様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/GuacamoleWithRDP/%e5%ae%9f%e9%9a%9b%e3%81%ab%e5%8b%95%e3%81%8b%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"実際に動かしている様子1\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"Guacamole と RDP"},{"content":"この記事を作った動機 Date クラスの仕様で、引っかかった部分があるのでそのことについて記録をする。具体的には、getMonthメンバ関数を使おうとしたとき、思っているのとは違う結果になったというのがある。\n内容 Date クラスの getMonth関数は、MDNに書かれているように、ゼロからスタートする値である。1月は、この関数の戻り値として、0 と表現され、12月は 11 として表現される。\nThe return value of getMonth() is zero-based, which is useful for indexing into arrays of months, for example:\n具体的に引っかかったところ createDateStringという関数を作っていて、文字列として\u0026quot;YYYY/MM/DD\u0026quot;のような形式で今いつかということを返すようにしようとしていた時、月の部分が一つ前になっていることに気づいた。\ncreateDateStringを実行した日を2025/10/29として、問題のあるコードと、そうでないコードの違いを以下に示す。\n問題のコード 帰ってくる戻り値は、2025/9/29。\nexport function createDateString(){ // yyyy/mm/dd const currentDate = new Date() let dateString = \u0026#34;\u0026#34; dateString += String(currentDate.getFullYear()) + \u0026#34;/\u0026#34; dateString += String(currentDate.getMonth()) + \u0026#34;/\u0026#34; dateString += String(currentDate.getDate()) return dateString } 修正したコード 帰ってくる戻り値は、2025/10/29。\nexport function createDateString(){ // yyyy/mm/dd const currentDate = new Date() let dateString = \u0026#34;\u0026#34; dateString += String(currentDate.getFullYear()) + \u0026#34;/\u0026#34; dateString += String(currentDate.getMonth() + 1) + \u0026#34;/\u0026#34; dateString += String(currentDate.getDate()) return dateString } 参考にしたサイトとか Date - JavaScript | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date (2025年10月29日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/typescript/dateclass/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003eDate\u003c/code\u003e クラスの仕様で、引っかかった部分があるのでそのことについて記録をする。具体的には、\u003ccode\u003egetMonth\u003c/code\u003eメンバ関数を使おうとしたとき、思っているのとは違う結果になったというのがある。\u003c/p\u003e\n\u003ch2 id=\"内容\"\u003e内容\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003eDate\u003c/code\u003e クラスの \u003ccode\u003egetMonth\u003c/code\u003e関数は、MDNに書かれているように、ゼロからスタートする値である。1月は、この関数の戻り値として、0 と表現され、12月は 11 として表現される。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThe return value of getMonth() is zero-based, which is useful for indexing into arrays of months, for example:\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"具体的に引っかかったところ\"\u003e具体的に引っかかったところ\u003c/h2\u003e\n\u003cp\u003e　\u003ccode\u003ecreateDateString\u003c/code\u003eという関数を作っていて、文字列として\u0026quot;YYYY/MM/DD\u0026quot;のような形式で今いつかということを返すようにしようとしていた時、月の部分が一つ前になっていることに気づいた。\u003c/p\u003e\n\u003cp\u003e　\u003ccode\u003ecreateDateString\u003c/code\u003eを実行した日を\u003ccode\u003e2025/10/29\u003c/code\u003eとして、問題のあるコードと、そうでないコードの違いを以下に示す。\u003c/p\u003e\n\u003ch3 id=\"問題のコード\"\u003e問題のコード\u003c/h3\u003e\n\u003cp\u003e　帰ってくる戻り値は、\u003ccode\u003e2025/9/29\u003c/code\u003e。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateDateString\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// yyyy/mm/dd\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Date()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetFullYear\u003c/span\u003e()) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetMonth\u003c/span\u003e()) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetDate\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"修正したコード\"\u003e修正したコード\u003c/h3\u003e\n\u003cp\u003e　帰ってくる戻り値は、\u003ccode\u003e2025/10/29\u003c/code\u003e。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateDateString\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// yyyy/mm/dd\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Date()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetFullYear\u003c/span\u003e()) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetMonth\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e String(\u003cspan style=\"color:#a6e22e\"\u003ecurrentDate\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetDate\u003c/span\u003e())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edateString\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDate - JavaScript | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date\"\u003ehttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date\u003c/a\u003e (2025年10月29日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Date クラスで躓いたこと"},{"content":"この記事を作った動機 Blender には、Python APIがあり、スクリプトを自由に書いて実行でき、いろいろ操作できるというのがある。しかし、なんかドキュメント見たりいちいち調べると、なんか同じことばっかり調べたりしていて、そうこうしているうちに、めんどくさくなって使う気がなくなっていくということがあった。\nそこで、自分で記録しておきたいと思ったことをここに適当にぶちまけようという発想をしてみた。特定の操作をするために小さなスクリプトについて、だらだら記録をここにためたいと思う。\nちょっとしたスクリプトリスト Lightという名前の光源の明るさを変更したい for a in [target for target in bpy.data.objects.keys() if \u0026#34;Light\u0026#34; in target]: bpy.data.objects[a].data.energy = 20 参考にしたサイトとか API Reference Usage - Blender Python API\nhttps://docs.blender.org/api/current/info_api_reference.html (2025年10月28日) How do I select specific elements from an array in python? - Stack Overflow\nhttps://stackoverflow.com/questions/66497607/how-do-i-select-specific-elements-from-an-array-in-python (2025年10月28日) python - what is the quickest way to iterate through a numpy array - Stack Overflow\nhttps://stackoverflow.com/questions/40593444/what-is-the-quickest-way-to-iterate-through-a-numpy-array (2025年10月28日) ","permalink":"https://www.nyanmo.info/posts/blender/pythonapinote/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Blender には、Python APIがあり、スクリプトを自由に書いて実行でき、いろいろ操作できるというのがある。しかし、なんかドキュメント見たりいちいち調べると、なんか同じことばっかり調べたりしていて、そうこうしているうちに、めんどくさくなって使う気がなくなっていくということがあった。\u003c/p\u003e\n\u003cp\u003e　そこで、自分で記録しておきたいと思ったことをここに適当にぶちまけようという発想をしてみた。特定の操作をするために小さなスクリプトについて、だらだら記録をここにためたいと思う。\u003c/p\u003e\n\u003ch2 id=\"ちょっとしたスクリプトリスト\"\u003eちょっとしたスクリプトリスト\u003c/h2\u003e\n\u003ch3 id=\"lightという名前の光源の明るさを変更したい\"\u003e\u003ccode\u003eLight\u003c/code\u003eという名前の光源の明るさを変更したい\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-py\" data-lang=\"py\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e a \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e [target \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e target \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e bpy\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edata\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eobjects\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ekeys() \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Light\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e target]: bpy\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edata\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eobjects[a]\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edata\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eenergy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAPI Reference Usage - Blender Python API\u003cbr\u003e\n\u003ca href=\"https://docs.blender.org/api/current/info_api_reference.html\"\u003ehttps://docs.blender.org/api/current/info_api_reference.html\u003c/a\u003e (2025年10月28日)\u003c/li\u003e\n\u003cli\u003eHow do I select specific elements from an array in python? - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/66497607/how-do-i-select-specific-elements-from-an-array-in-python\"\u003ehttps://stackoverflow.com/questions/66497607/how-do-i-select-specific-elements-from-an-array-in-python\u003c/a\u003e (2025年10月28日)\u003c/li\u003e\n\u003cli\u003epython - what is the quickest way to iterate through a numpy array - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/40593444/what-is-the-quickest-way-to-iterate-through-a-numpy-array\"\u003ehttps://stackoverflow.com/questions/40593444/what-is-the-quickest-way-to-iterate-through-a-numpy-array\u003c/a\u003e (2025年10月28日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Blender PythonAPI スクリプト集"},{"content":"この記事を作った動機 ある時、ChatGPT を使っていて、うまく設定が読み込めないという時があったときにそれについて調べてみたら、DNS 周りのキャッシュがおかしい説というのがあり、named のキャッシュを消そうとしてやり方がわからなかったので、自分用に記録するだけ。\n設定する 少なくとも私の環境では、最初から rndc コマンドは使えるようになっておらず、設定が必要だった。rndc-confgen を使うことで、コンフィグは生成できるので、出てきたものをそれぞれ、named.conf と rndc.conf に貼り付ければとりあえずは動いた。\nまだ設定がないときの rndc コマンドの挙動 sudo rndc status # rndc: no server specified and no default rndc status -s localhost # rndc: no server specified and no default rndc-confgen で設定を生成する # sudo rndc-confgen [sudo] share のパスワード: # Start of rndc.conf key \u0026#34;rndc-key\u0026#34; { algorithm hmac-sha256; secret \u0026#34;secretString\u0026#34;; }; options { default-key \u0026#34;rndc-key\u0026#34;; default-server 127.0.0.1; default-port 953; }; # End of rndc.conf # Use with the following in named.conf, adjusting the allow list as needed: # key \u0026#34;rndc-key\u0026#34; { # algorithm hmac-sha256; # secret \u0026#34;secretString\u0026#34;; # }; # # controls { # inet 127.0.0.1 port 953 # allow { 127.0.0.1; } keys { \u0026#34;rndc-key\u0026#34;; }; # }; # End of named.conf 設定を貼り付ける /etc/rndc.conf (なければ作成する) key \u0026#34;rndc-key\u0026#34; { algorithm hmac-sha256; secret \u0026#34;secretString\u0026#34;; }; options { default-key \u0026#34;rndc-key\u0026#34;; default-server 127.0.0.1; default-port 953; }; /etc/named.conf (追記する) key \u0026#34;rndc-key\u0026#34; { algorithm hmac-sha256; secret \u0026#34;secretString\u0026#34;; }; controls { inet 127.0.0.1 port 953 allow { 127.0.0.1; } keys { \u0026#34;rndc-key\u0026#34;; }; }; systemd で named を再起動する sudo systemctl restart named キャッシュを削除する sudo rndc flush 参考にしたサイトとか rndc 鍵 (rndc.key) の作成 - hijiri-0404\u0026rsquo;s blog\nhttps://hijiri0404.hatenablog.com/entry/2015/03/05/000245 (2025年10月2日) domain name system - DNS on Redhat - rdnc: no server specified and no default - Server Fault\nhttps://serverfault.com/questions/231749/dns-on-redhat-rdnc-no-server-specified-and-no-default (2025年10月2日) BIND のキャッシュを消去する (CentOS 5.5): Linux の使い方\nhttps://ez-net.jp/article/28/KPrxdINA/6oV8mNixA7et/ (2025年10月2日) ","permalink":"https://www.nyanmo.info/posts/linux/namedclearcache/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　ある時、ChatGPT を使っていて、うまく設定が読み込めないという時があったときにそれについて調べてみたら、DNS 周りのキャッシュがおかしい説というのがあり、named のキャッシュを消そうとしてやり方がわからなかったので、自分用に記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"設定する\"\u003e設定する\u003c/h2\u003e\n\u003cp\u003e　少なくとも私の環境では、最初から \u003ccode\u003erndc\u003c/code\u003e コマンドは使えるようになっておらず、設定が必要だった。\u003ccode\u003erndc-confgen\u003c/code\u003e を使うことで、コンフィグは生成できるので、出てきたものをそれぞれ、\u003ccode\u003enamed.conf\u003c/code\u003e と \u003ccode\u003erndc.conf\u003c/code\u003e に貼り付ければとりあえずは動いた。\u003c/p\u003e\n\u003ch3 id=\"まだ設定がないときの-rndc-コマンドの挙動\"\u003eまだ設定がないときの \u003ccode\u003erndc\u003c/code\u003e コマンドの挙動\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo rndc status\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# rndc: no server specified and no default\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erndc status -s localhost\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# rndc: no server specified and no default\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"rndc-confgen-で設定を生成する\"\u003erndc-confgen で設定を生成する\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# sudo rndc-confgen \n[sudo] share のパスワード:\n# Start of rndc.conf\nkey \u0026#34;rndc-key\u0026#34; {\n\talgorithm hmac-sha256;\n\tsecret \u0026#34;secretString\u0026#34;;\n};\n\noptions {\n\tdefault-key \u0026#34;rndc-key\u0026#34;;\n\tdefault-server 127.0.0.1;\n\tdefault-port 953;\n};\n# End of rndc.conf\n\n# Use with the following in named.conf, adjusting the allow list as needed:\n# key \u0026#34;rndc-key\u0026#34; {\n# \talgorithm hmac-sha256;\n# \tsecret \u0026#34;secretString\u0026#34;;\n# };\n# \n# controls {\n# \tinet 127.0.0.1 port 953\n# \t\tallow { 127.0.0.1; } keys { \u0026#34;rndc-key\u0026#34;; };\n# };\n# End of named.conf\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"設定を貼り付ける\"\u003e設定を貼り付ける\u003c/h3\u003e\n\u003ch4 id=\"etcrndcconf-なければ作成する\"\u003e/etc/rndc.conf (なければ作成する)\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ekey \u0026#34;rndc-key\u0026#34; {\n\talgorithm hmac-sha256;\n\tsecret \u0026#34;secretString\u0026#34;;\n};\n\noptions {\n\tdefault-key \u0026#34;rndc-key\u0026#34;;\n\tdefault-server 127.0.0.1;\n\tdefault-port 953;\n};\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"etcnamedconf-追記する\"\u003e/etc/named.conf (追記する)\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ekey \u0026#34;rndc-key\u0026#34; {\n\talgorithm hmac-sha256;\n\tsecret \u0026#34;secretString\u0026#34;;\n};\n\ncontrols {\n\tinet 127.0.0.1 port 953\n\t\tallow { 127.0.0.1; } keys { \u0026#34;rndc-key\u0026#34;; };\n};\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"systemd-で-named-を再起動する\"\u003esystemd で named を再起動する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart named\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"キャッシュを削除する\"\u003eキャッシュを削除する\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo rndc flush\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003erndc 鍵 (rndc.key) の作成 - hijiri-0404\u0026rsquo;s blog\u003cbr\u003e\n\u003ca href=\"https://hijiri0404.hatenablog.com/entry/2015/03/05/000245\"\u003ehttps://hijiri0404.hatenablog.com/entry/2015/03/05/000245\u003c/a\u003e (2025年10月2日)\u003c/li\u003e\n\u003cli\u003edomain name system - DNS on Redhat - rdnc: no server specified and no default - Server Fault\u003cbr\u003e\n\u003ca href=\"https://serverfault.com/questions/231749/dns-on-redhat-rdnc-no-server-specified-and-no-default\"\u003ehttps://serverfault.com/questions/231749/dns-on-redhat-rdnc-no-server-specified-and-no-default\u003c/a\u003e (2025年10月2日)\u003c/li\u003e\n\u003cli\u003eBIND のキャッシュを消去する (CentOS 5.5): Linux の使い方\u003cbr\u003e\n\u003ca href=\"https://ez-net.jp/article/28/KPrxdINA/6oV8mNixA7et/\"\u003ehttps://ez-net.jp/article/28/KPrxdINA/6oV8mNixA7et/\u003c/a\u003e (2025年10月2日)\u003c/li\u003e\n\u003c/ul\u003e","title":"named のキャッシュを消す"},{"content":"この記事を作った動機 Websocket を使ったフロントエンドで、自動的に接続が途切れたら再接続するコードを書くときに躓いたので、その記録をする。\nWebsocket の接続に関するエラーハンドリング Websocket が接続失敗したときに、やらせたい処理がある場合は、try-catch は使えない。接続に関する問題に対処するには、コールバック関数として、\u0026ldquo;error\u0026quot;イベントが発火されたときに処理を登録する必要がある。\nWebsocket は、非同期で実行されるため try-catch では接続できなかったときのエラーを拾えないようである。\nうまくいかない例 // この例だと、reconnect 関数が実行されることはない。この形だと、WebScoket クラスに渡したパラメータ異常しか拾えない。 const setWebsocket = useDatabaseStore.setState; try{ const websocket = new WebSocket(\u0026#34;ws://localhost:50097\u0026#34;) setWebsocket({ websocket: websocket }) }catch(e){ console.log(e) reconnect() } うまくいく例 const setWebsocket = useDatabaseStore.setState; const websocket = new WebSocket(\u0026#34;ws://localhost:50097\u0026#34;) websocket.onerror = () =\u0026gt; { reconnect() } setWebsocket({ websocket: websocket }) const setWebsocket = useDatabaseStore.setState; const websocket = new WebSocket(\u0026#34;ws://localhost:50097\u0026#34;) websocket.addEventListener(\u0026#34;error\u0026#34;,reconnect) setWebsocket({ websocket: websocket }) 参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年9月29日) WebSocket: close イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/close_event (2025年9月29日) WebSocket: error イベント - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/error_event (2025年9月29日) WebSocket: WebSocket() コンストラクター - Web API | MDN\nhttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/WebSocket (2025年9月29日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/react/websocketreconnect/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Websocket を使ったフロントエンドで、自動的に接続が途切れたら再接続するコードを書くときに躓いたので、その記録をする。\u003c/p\u003e\n\u003ch2 id=\"websocket-の接続に関するエラーハンドリング\"\u003eWebsocket の接続に関するエラーハンドリング\u003c/h2\u003e\n\u003cp\u003e　Websocket が接続失敗したときに、やらせたい処理がある場合は、\u003ccode\u003etry-catch\u003c/code\u003e は使えない。接続に関する問題に対処するには、コールバック関数として、\u0026ldquo;error\u0026quot;イベントが発火されたときに処理を登録する必要がある。\u003c/p\u003e\n\u003cp\u003e　Websocket は、非同期で実行されるため \u003ccode\u003etry-catch\u003c/code\u003e では接続できなかったときのエラーを拾えないようである。\u003c/p\u003e\n\u003ch3 id=\"うまくいかない例\"\u003eうまくいかない例\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// この例だと、reconnect 関数が実行されることはない。この形だと、WebScoket クラスに渡したパラメータ異常しか拾えない。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetState\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:50097\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ewebsocket\u003c/span\u003e })    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ereconnect\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"うまくいく例\"\u003eうまくいく例\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetState\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:50097\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eonerror\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ereconnect\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ewebsocket\u003c/span\u003e })    \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetState\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:50097\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ereconnect\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ewebsocket\u003c/span\u003e })    \n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年9月29日)\u003c/li\u003e\n\u003cli\u003eWebSocket: close イベント - Web API | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/API/WebSocket/close_event\"\u003ehttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/close_event\u003c/a\u003e (2025年9月29日)\u003c/li\u003e\n\u003cli\u003eWebSocket: error イベント - Web API | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/API/WebSocket/error_event\"\u003ehttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/error_event\u003c/a\u003e (2025年9月29日)\u003c/li\u003e\n\u003cli\u003eWebSocket: WebSocket() コンストラクター - Web API | MDN\u003cbr\u003e\n\u003ca href=\"https://developer.mozilla.org/ja/docs/Web/API/WebSocket/WebSocket\"\u003ehttps://developer.mozilla.org/ja/docs/Web/API/WebSocket/WebSocket\u003c/a\u003e (2025年9月29日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Websocket を自動で再接続したい"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 Linux 環境 + GNOME におけるカーソルテーマのインストールや作り方がわかりにくかったので自分用にまとめを作りたい。作り方の部分に関しては、主に、Create your own mouse cursor theme | Developer のやり方を元にしている。\nまだ、現段階(2025/9/28)では、何も手を付けてなくて、調べたことをまとめ、とりあえずカーソルテーマを作るための一筋の段取りを見立てるという段階なので、実際にこのやり方が機能するかは確かめられていない。この記事はその過程において、思考整理的な意味がある。\n使うツール GNOME tweaks xcursorgen yay -S xorg-xcursorgen gnome-tweaks # pacman -S xorg-xcursorgen gnome-tweaks カーソルの設定の仕方 GNOME tweaks を使う 以下は、カーソルテーマ設定画面の例である。 カーソルのインストール カーソルデータのフォルダ構造 cursorThemeName/ ├── cursors │ ├── default │ └── ... # 他にも色々ある └── index.theme local index.theme を含むフォルダごと以下のディレクトリに配置する。\n~/.local/share/icons/ global index.theme を含むフォルダごと以下のディレクトリに配置する。\n/usr/share/icons/ カーソルの作り方 カーソル専用のフォルダを作る cursorThemeName/ ├── cursors # フォルダ └── index.theme # プレインテキスト index.theme を書く とりあえずこのファイルがあればとにかくテーマとして GNOME tweaks などからは認識される。\n[Icon Theme] Name=CursorName # 最小構成は \u0026#34;Name\u0026#34; があれば十分 Comment=test cursor # これとかはオプション Inherits=[足りない画像を補うためのカーソルテーマを選べるっぽい？] # これもオプション ここからは、cursors フォルダ内で作業していることを前提とする。 最終的には、cursors フォルダ内には、以下の種類のファイルが同時に存在している状態になる。\n.png な png 画像 .cursor な xcursor 設定プレインテキスト 拡張子がない xcursor 画像 元となるカーソル画像を作る 解像度 (高めに作っておけばいいように思う) 以下は、Create your own mouse cursor theme | Developer の引用\n16x16 22x22 32x32 48x48 64x64 128x128 256x256 形式 透過レイヤーを保持した png 画像\n作るカーソルの名前 一応最終的にはカーソル画像の名前は、X11 カーソルにするときに厳密にする必要があるようである。なのでこの時点である程度合わせておいて方がいいかもしれない。正直数が多すぎて何作っていいかわからなくなったので、適当にネットで既存のカーソルテーマを探して、それを参考に必要そうなカーソル画像リストを作ることにした。\n全ては作る必要はなく、足りない部分はデフォルトのカーソル画像で補われるため、メジャーなアイコンに絞ってもいいかもしれない。今回作成したリストでは、普通にミスや間違いがあると思うので注意する必要がある。\n以下は、LyraQ Cursors - Gnome-look.org の例に作ったリストである。\n├── progress # (カーソルあり) カーソル付きで、進捗していることを表すアイコン ぐるぐる回転する奴 ├── no-drop # (カーソルあり) ドロップできない領域をホバーしているとき ├── wait # (カーソルなし) カーソルなしで、進捗していることを表すアイコン ぐるぐる回転する奴 # カーソル関連 ------------------------------- # カーソル関連 ------------------------------- ├── default # (カーソルあり) 左上向きで、通常出てくるデフォルトカーソル ├── center_ptr # (カーソルあり) 上向きで、真ん中に描画されているカーソル 私は用途がよくわからなかった ├── right_ptr # (カーソルあり) 右上向きに何かを指すアイコン # カーソル関連 ------------------------------- # カーソル関連 ------------------------------- # ユーティリティ関連 ------------------------------- # ユーティリティ関連 ------------------------------- ├── alias # (カーソルあり) リンクを踏むときとかのアイコンっぽい？ ├── help # (カーソルあり) ヘルプカーソル ├── copy # (カーソルあり) コピーアイコン ├── context-menu # (カーソルあり) メニューアイコン ├── color-picker # (カーソルなし) 色を取得するとき ├── pencil # (カーソルなし) ペンアイコン ├── draft # (カーソルなし) 下書きを意味するアイコン ├── not-allowed # (カーソルなし) 禁止アイコン単体 ├── text # (カーソルなし) 横方向にテキストが入力できる場所で出てくるアイコン (検索バーとか) ├── vertical-text # (カーソルなし) 縦方向にテキストが入力できる場所で出てくるアイコン (ワードプロセッサで縦に文章を書いているときとか？) ├── zoom-in # (カーソルなし) 虫眼鏡 拡大アイコン ├── zoom-out # (カーソルなし) 虫眼鏡 縮小アイコン # ユーティリティ関連 ------------------------------- # ユーティリティ関連 ------------------------------- # 手のアイコン ------------------------------- # 手のアイコン ------------------------------- ├── dnd-move # (カーソルなし) ドラックアンドドロップで掴んでいるときのアイコン ├── dnd-no-drop # (カーソルなし) ドラックアンドドロップでドロップできない領域をホバーしているとき ├── openhand # (カーソルなし) 手を開く（掴めるものを掴んでいないときのアイコン） ├── pointer # (カーソルなし) 指を指すアイコン # 手のアイコン ------------------------------- # 手のアイコン ------------------------------- # 矢印関連 ------------------------------- # 矢印関連 ------------------------------- ├── bottom_left_corner # (カーソルなし) ウィンドウサイズをリサイズするときに出てくるような矢印 左下を指す 左と下に矢印だけでなく線がある ├── bottom_right_corner # (カーソルなし) ウィンドウサイズをリサイズするときに出てくるような矢印 右下を指す 右と下に矢印だけでなく線がある ├── bottom_side # (カーソルなし) ウィンドウサイズをリサイズするときに出てくるような矢印 下を指す　アンダーラインのような線がある ├── top_side # (カーソルなし) ウィンドウサイズをリサイズするときに出てくるような矢印 上を差し　アンダーラインを逆に描いたみたいになっている ├── left_side # (カーソルなし) 左向き矢印単体 矢印以外に左に縦線がある ├── right_side # (カーソルなし) 右向き矢印単体 矢印以外に左に縦線がある ├── left-arrow # (カーソルなし) 左向き矢印単体 矢印以外の線はない ├── right-arrow # (カーソルなし) 右向き矢印単体 矢印以外の線はない ├── top_left_corner # (カーソルなし) 左上向き矢印単体 矢印以外の線はない ├── top_right_corner # (カーソルなし) 右上向き矢印単体 矢印以外の線はない ├── up-arrow # (カーソルなし) 上矢印単体 矢印以外の線はない ├── down-arrow # (カーソルなし) 下矢印単体 矢印以外の線はない # 矢印関連 ------------------------------- # 矢印関連 ------------------------------- # 矢印関連1 ------------------------------- # 矢印関連1 ------------------------------- ├── size_bdiag # (カーソルなし) backward? 右上、左下 を指し、斜めに並び、リサイズとかで出てきそうなアイコン ├── size_fdiag # (カーソルなし) forward? 左上、右下 を指し、斜めに並び、リサイズとかで出てきそうなアイコン ├── size_hor # (カーソルなし) 水平に 左と右を指すカーソルみたいなのが並んでいるアイコン ├── size_ver # (カーソルなし) 垂直に 上と下を指すカーソルみたいなのが並んでいるアイコン ├── all-scroll # (カーソルなし) 全方位のスクロール矢印 ├── fleur # (カーソルなし) 全方位のスクロール矢印と同じっぽい @ # 矢印関連1 ------------------------------- # 矢印関連1 ------------------------------- # Excel 的アイコン ------------------------------- # Excel 的アイコン ------------------------------- ├── col-resize # (カーソルなし) Excel で列の操作をするときの、左右に矢印が出て、真ん中にバーが縦に生えているアイコン ├── row-resize # (カーソルなし) Excel で列の操作をするときの、上下に矢印が出て、真ん中にバーが横に生えているアイコン ├── cell # (カーソルなし) Excel でセルを選択するときのような十字アイコン ├── crosshair # (カーソルなし) Excel でセルを選択するときのような十字アイコンのスリムバージョン # Excel 的アイコン ------------------------------- # Excel 的アイコン ------------------------------- ├── wayland-cursor # (カーソルなし) Wayland のトレードマークのアイコンを模したカスタムアイコン ├── x-cursor # (カーソルなし) X11 のトレードマークのアイコンを模したカスタムアイコン ├── pirate # (カーソルなし) 海賊アイコン カーソル名参考 シンボルリンクを含めて全列挙 ├── 00000000000000020006000e7e9ffc3f -\u0026gt; progress ├── 00008160000006810000408080010102 -\u0026gt; size_ver ├── 03b6e0fcb3499374a867c041f52298f0 -\u0026gt; circle ├── 08e8e1c95fe2fc01f976f1e063a24ccd -\u0026gt; progress ├── 1081e37283d90000800003c07f3ef6bf -\u0026gt; copy ├── 3085a0e285430894940527032f8b26df -\u0026gt; alias ├── 3ecb610c1bf2410f44200f48c40d3599 -\u0026gt; progress ├── 4498f0e0c1937ffe01fd06f973665830 -\u0026gt; dnd-move ├── 5c6cd98b3f3ebcb1f9c7f1c204630408 -\u0026gt; help ├── 6407b0e94181790501fd1e167b474872 -\u0026gt; copy ├── 640fb0e74195791501fd1ed57b41487f -\u0026gt; alias ├── 9081237383d90e509aa00f00170e968f -\u0026gt; dnd-move ├── 9d800788f1b08800ae810202380a0822 -\u0026gt; pointer ├── a2a266d0498c3104214a47bd64ab0fc8 -\u0026gt; alias ├── alias ├── all-scroll ├── arrow -\u0026gt; default ├── b66166c04f8c3109214a4fbd64a50fc8 -\u0026gt; copy ├── bottom_left_corner ├── bottom_right_corner ├── bottom_side ├── cell ├── center_ptr ├── circle -\u0026gt; not-allowed ├── closedhand -\u0026gt; dnd-move ├── col-resize ├── color-picker ├── context-menu ├── copy ├── cross -\u0026gt; crosshair ├── crossed_circle -\u0026gt; not-allowed ├── crosshair ├── d9ce0ab605698f320427677b458ad60b -\u0026gt; help ├── default ├── dnd-copy -\u0026gt; copy ├── dnd-move ├── dnd-no-drop ├── dnd-none -\u0026gt; dnd-move ├── down-arrow ├── draft ├── e-resize -\u0026gt; size_hor ├── e29285e634086352946a0e7090d73106 -\u0026gt; pointer ├── fcf21c00b30f7e3f83fe0dfd12e71cff -\u0026gt; dnd-move ├── fleur ├── forbidden -\u0026gt; no-drop ├── grab -\u0026gt; openhand ├── grabbing -\u0026gt; dnd-move ├── h_double_arrow -\u0026gt; size_hor ├── half-busy -\u0026gt; progress ├── hand1 -\u0026gt; pointer ├── hand2 -\u0026gt; pointer ├── help ├── ibeam -\u0026gt; text ├── left-arrow ├── left_ptr -\u0026gt; default ├── left_ptr_help -\u0026gt; help ├── left_ptr_watch -\u0026gt; progress ├── left_side ├── link -\u0026gt; alias ├── ll_angle -\u0026gt; bottom_left_corner ├── lr_angle -\u0026gt; bottom_right_corner ├── move -\u0026gt; dnd-move ├── n-resize -\u0026gt; size_ver ├── ne-resize -\u0026gt; top_right_corner ├── nesw-resize -\u0026gt; size_bdiag ├── no-drop ├── not-allowed ├── nw-resize -\u0026gt; top_left_corner ├── nwse-resize -\u0026gt; size_fdiag ├── openhand ├── pencil ├── pirate ├── plus -\u0026gt; cell ├── pointer ├── pointing_hand -\u0026gt; pointer ├── progress ├── question_arrow -\u0026gt; help ├── right-arrow ├── right_ptr ├── right_side ├── row-resize ├── s-resize -\u0026gt; size_ver ├── sb_h_double_arrow -\u0026gt; size_hor ├── sb_v_double_arrow -\u0026gt; size_ver ├── se-resize -\u0026gt; bottom_right_corner ├── size_all -\u0026gt; fleur ├── size_bdiag ├── size_fdiag ├── size_hor ├── size_ver ├── split_h -\u0026gt; col-resize ├── split_v -\u0026gt; row-resize ├── sw-resize -\u0026gt; bottom_left_corner ├── text ├── top_left_corner ├── top_right_corner ├── top_side ├── ul_angle -\u0026gt; top_left_corner ├── up-arrow ├── ur_angle -\u0026gt; top_right_corner ├── v_double_arrow -\u0026gt; size_ver ├── vertical-text ├── w-resize -\u0026gt; size_hor ├── wait ├── watch -\u0026gt; wait ├── wayland-cursor ├── whats_this -\u0026gt; help ├── x-cursor ├── xterm -\u0026gt; text ├── zoom-in └── zoom-out カーソルの設定をする Create your own mouse cursor theme | Developer によれば、任意の画像の名前と同じ名前.cursor という感じで、.cursorの拡張子をもったプレインテキストを以下のような形式に従って作ればいいようである。\n静止画 [解像度縦横] [x方向のクリックオフセット] [y方向のクリックオフセット] [対象の画像の名前] [解像度縦横] [x方向のクリックオフセット] [y方向のクリックオフセット] [対象の画像の名前] ... # 確か複数の解像度のために、複数行同じファイルに同時に記述できると、どこかのサイトに書いていた覚えがあるが忘れた。要検証。 # 以下は \u0026#34;Create your own mouse cursor theme | Developer\u0026#34; に書いてある例 32 10 5 default.png アニメーション [解像度縦横] [x方向のクリックオフセット] [y方向のクリックオフセット] [対象の画像の名前]_1.png [アニメーション時間(ms?)] [解像度縦横] [x方向のクリックオフセット] [y方向のクリックオフセット] [対象の画像の名前]_2.png [アニメーション時間(ms?)] ... # 以下は、\u0026#34;Create your own mouse cursor theme | Developer\u0026#34; に書いてある例 32 16 16 wait_1.png 50 32 16 16 wait_2.png 50 ※ すべてのカーソル画像を作る必要はなく、使いまわしたいところに関してはあとからシンボルリンクでいいっぽい。ここでは作った画像分だけの、.cursor ファイルがあれば十分なようである。\nxcursorgen でカーソル画像を生成する 多分スクリプト書いて自動化したほうがいいかも。\nxcursorgen [任意の画像名].cursor [任意の画像名] シンボルリンクを作成する 作成しなかった分の xcursor を補う操作をする。正直やらなくても動くと思うが、その場合は足りないカーソル画像はデフォルトのもので補われる。\nln -s [生成したxcursor画像名] [補いたい対象の名前] # 以下は、\u0026#34;Create your own mouse cursor theme | Developer\u0026#34; に書いてある例 ln -s default left_ptr 以下は、LyraQ Cursors - Gnome-look.org の例に作ったシンボルリンクリストである。\n├── 00000000000000020006000e7e9ffc3f -\u0026gt; progress ├── 00008160000006810000408080010102 -\u0026gt; size_ver ├── 03b6e0fcb3499374a867c041f52298f0 -\u0026gt; circle ├── 08e8e1c95fe2fc01f976f1e063a24ccd -\u0026gt; progress ├── 1081e37283d90000800003c07f3ef6bf -\u0026gt; copy ├── 3085a0e285430894940527032f8b26df -\u0026gt; alias ├── 3ecb610c1bf2410f44200f48c40d3599 -\u0026gt; progress ├── 4498f0e0c1937ffe01fd06f973665830 -\u0026gt; dnd-move ├── 5c6cd98b3f3ebcb1f9c7f1c204630408 -\u0026gt; help ├── 6407b0e94181790501fd1e167b474872 -\u0026gt; copy ├── 640fb0e74195791501fd1ed57b41487f -\u0026gt; alias ├── 9081237383d90e509aa00f00170e968f -\u0026gt; dnd-move ├── 9d800788f1b08800ae810202380a0822 -\u0026gt; pointer ├── a2a266d0498c3104214a47bd64ab0fc8 -\u0026gt; alias ├── b66166c04f8c3109214a4fbd64a50fc8 -\u0026gt; copy ├── d9ce0ab605698f320427677b458ad60b -\u0026gt; help ├── e29285e634086352946a0e7090d73106 -\u0026gt; pointer ├── fcf21c00b30f7e3f83fe0dfd12e71cff -\u0026gt; dnd-move ├── arrow -\u0026gt; default ├── circle -\u0026gt; not-allowed ├── closedhand -\u0026gt; dnd-move ├── cross -\u0026gt; crosshair ├── crossed_circle -\u0026gt; not-allowed ├── dnd-copy -\u0026gt; copy ├── dnd-none -\u0026gt; dnd-move ├── e-resize -\u0026gt; size_hor ├── forbidden -\u0026gt; no-drop ├── grab -\u0026gt; openhand ├── grabbing -\u0026gt; dnd-move ├── h_double_arrow -\u0026gt; size_hor ├── half-busy -\u0026gt; progress ├── hand1 -\u0026gt; pointer ├── hand2 -\u0026gt; pointer ├── ibeam -\u0026gt; text ├── left_ptr -\u0026gt; default ├── left_ptr_help -\u0026gt; help ├── left_ptr_watch -\u0026gt; progress ├── link -\u0026gt; alias ├── ll_angle -\u0026gt; bottom_left_corner ├── lr_angle -\u0026gt; bottom_right_corner ├── move -\u0026gt; dnd-move ├── n-resize -\u0026gt; size_ver ├── ne-resize -\u0026gt; top_right_corner ├── nesw-resize -\u0026gt; size_bdiag ├── nw-resize -\u0026gt; top_left_corner ├── nwse-resize -\u0026gt; size_fdiag ├── plus -\u0026gt; cell ├── pointing_hand -\u0026gt; pointer ├── question_arrow -\u0026gt; help ├── s-resize -\u0026gt; size_ver ├── sb_h_double_arrow -\u0026gt; size_hor ├── sb_v_double_arrow -\u0026gt; size_ver ├── se-resize -\u0026gt; bottom_right_corner ├── size_all -\u0026gt; fleur ├── split_h -\u0026gt; col-resize ├── split_v -\u0026gt; row-resize ├── sw-resize -\u0026gt; bottom_left_corner ├── ul_angle -\u0026gt; top_left_corner ├── ur_angle -\u0026gt; top_right_corner ├── v_double_arrow -\u0026gt; size_ver ├── w-resize -\u0026gt; size_hor ├── watch -\u0026gt; wait ├── whats_this -\u0026gt; help ├── xterm -\u0026gt; text カーソルのインストールと設定 ここまでくれば、うまく行けばとりあえず動くはずである。gnome-tweaks-を使う と カーソルのインストール の項目を参考にすれば、とりあえず実際にカーソルを拝められると思われる。\nヘルパースクリプトたち cursors 内に作業用フォルダを作る #!/bin/python # cursors フォルダ内で実行すると、作業用に各ポインタ画像のフォルダを作る import os folderlist = [\u0026#34;progress\u0026#34;,\u0026#34;no-drop\u0026#34;,\u0026#34;wait\u0026#34;,\u0026#34;default\u0026#34;,\u0026#34;center_ptr\u0026#34;,\u0026#34;right_ptr\u0026#34;,\u0026#34;alias\u0026#34;,\u0026#34;help\u0026#34;,\u0026#34;copy\u0026#34;,\u0026#34;context-menu\u0026#34;,\u0026#34;color-picker\u0026#34;,\u0026#34;pencil\u0026#34;,\u0026#34;draft\u0026#34;,\u0026#34;not-allowed\u0026#34;,\u0026#34;text\u0026#34;,\u0026#34;vertical-text\u0026#34;,\u0026#34;zoom-in\u0026#34;,\u0026#34;zoom-out\u0026#34;,\u0026#34;dnd-move\u0026#34;,\u0026#34;dnd-no-drop\u0026#34;,\u0026#34;openhand\u0026#34;,\u0026#34;pointer\u0026#34;,\u0026#34;bottom_left_corner\u0026#34;,\u0026#34;bottom_right_corner\u0026#34;,\u0026#34;bottom_side\u0026#34;,\u0026#34;top_side\u0026#34;,\u0026#34;left_side\u0026#34;,\u0026#34;right_side\u0026#34;,\u0026#34;left-arrow\u0026#34;,\u0026#34;right-arrow\u0026#34;,\u0026#34;top_left_corner\u0026#34;,\u0026#34;top_right_corner\u0026#34;,\u0026#34;up-arrow\u0026#34;,\u0026#34;down-arrow\u0026#34;,\u0026#34;size_bdiag\u0026#34;,\u0026#34;size_fdiag\u0026#34;,\u0026#34;size_hor\u0026#34;,\u0026#34;size_ver\u0026#34;,\u0026#34;all-scroll\u0026#34;,\u0026#34;fleur\u0026#34;,\u0026#34;col-resize\u0026#34;,\u0026#34;row-resize\u0026#34;,\u0026#34;cell\u0026#34;,\u0026#34;crosshair\u0026#34;,\u0026#34;wayland-cursor\u0026#34;,\u0026#34;x-cursor\u0026#34;,\u0026#34;pirate\u0026#34;] for folder in folderlist: try: os.mkdir(folder) except: print(folder) try: with open(folder + \u0026#34;/.gitkeep\u0026#34;,\u0026#34;wt\u0026#34;) as empty: empty.write(\u0026#34;\u0026#34;) except: print(folder) テンプレ画像ドキュメントのコピー #!/bin/python # 実行するとコピーするドキュメントを聞かれるので、ファイルを選択する # スクリプト自体は、 cursors フォルダ内で実行することを想定 import os, os.path, subprocess from tkinter import filedialog target = filedialog.askopenfilename() filename = target.split(\u0026#34;/\u0026#34;)[-1] print(target) for folder in os.listdir(): if(os.path.isdir(folder)): command = \u0026#34;cp {} ./{}/{}\u0026#34;.format(target,folder,filename) subprocess.run([command],shell=True) clickgen を使って自動的にカーソル画像を生成 #!/bin/python # まだ 関係ありそうな記事 yay コマンドのインストール 参考にしたサイトとか Create your own mouse cursor theme | Developer\nhttps://develop.kde.org/docs/features/cursor/ (2025年9月28日)\nCursor themes - ArchWiki\nhttps://wiki.archlinux.org/title/Cursor_themes (2025年9月28日)\nCursors - Gnome-look.org\nhttps://www.gnome-look.org/browse?cat=107\u0026amp;ord=latest (2025年9月28日)\nArch Linux - gnome-tweaks 49.0-1 (any)\nhttps://archlinux.org/packages/extra/any/gnome-tweaks/ (2025年9月28日)\nArch Linux - xorg-xcursorgen 1.0.9-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/xorg-xcursorgen/ (2025年9月28日)\nclickgen · PyPI\nhttps://pypi.org/project/clickgen/ (2025年9月29日)\nLyraQ Cursors - Gnome-look.org\nhttps://www.gnome-look.org/p/1518883 (2025年9月28日)\n","permalink":"https://www.nyanmo.info/posts/linux/cursortheme/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Linux 環境 + GNOME におけるカーソルテーマのインストールや作り方がわかりにくかったので自分用にまとめを作りたい。作り方の部分に関しては、主に、\u003ca href=\"https://develop.kde.org/docs/features/cursor/\"\u003eCreate your own mouse cursor theme | Developer\u003c/a\u003e のやり方を元にしている。\u003c/p\u003e\n\u003cp\u003e　まだ、現段階(2025/9/28)では、何も手を付けてなくて、調べたことをまとめ、とりあえずカーソルテーマを作るための一筋の段取りを見立てるという段階なので、実際にこのやり方が機能するかは確かめられていない。この記事はその過程において、思考整理的な意味がある。\u003c/p\u003e\n\u003ch2 id=\"使うツール\"\u003e使うツール\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eGNOME tweaks\u003c/li\u003e\n\u003cli\u003excursorgen\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S xorg-xcursorgen gnome-tweaks\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# pacman -S xorg-xcursorgen gnome-tweaks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"カーソルの設定の仕方\"\u003eカーソルの設定の仕方\u003c/h2\u003e\n\u003ch3 id=\"gnome-tweaks-を使う\"\u003eGNOME tweaks を使う\u003c/h3\u003e\n\u003cp\u003e　以下は、カーソルテーマ設定画面の例である。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/cursorTheme/selectCursor.png#center\"\n         alt=\"カーソル設定画面\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"カーソルのインストール\"\u003eカーソルのインストール\u003c/h2\u003e\n\u003ch3 id=\"カーソルデータのフォルダ構造\"\u003eカーソルデータのフォルダ構造\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecursorThemeName/\n├── cursors\n│   ├── default\n│   └── ... # 他にも色々ある\n└── index.theme\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"local\"\u003elocal\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003eindex.theme\u003c/code\u003e を含むフォルダごと以下のディレクトリに配置する。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~/.local/share/icons/\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"global\"\u003eglobal\u003c/h3\u003e\n\u003cp\u003e　\u003ccode\u003eindex.theme\u003c/code\u003e を含むフォルダごと以下のディレクトリに配置する。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/usr/share/icons/\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"カーソルの作り方\"\u003eカーソルの作り方\u003c/h2\u003e\n\u003ch3 id=\"カーソル専用のフォルダを作る\"\u003eカーソル専用のフォルダを作る\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ecursorThemeName/\n├── cursors     # フォルダ\n└── index.theme # プレインテキスト\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"indextheme-を書く\"\u003eindex.theme を書く\u003c/h3\u003e\n\u003cp\u003e　とりあえずこのファイルがあればとにかくテーマとして GNOME tweaks などからは認識される。\u003c/p\u003e","title":"Linux カーソル 設定や作成"},{"content":"この記事を作った動機 Linux 環境を使っていて、ソフトウェアシンセサイザー？とか、適当にネットでダウンロードしてきたMIDIファイルを再生するとかやってみている。\nそれで、Linux 環境における MIDI では、ちょっとすぐにはわからないようなことが必要だとわかったので、それをノートとして使っているこのブログに記録しようと思った。\n使っているソフト Surge XT Drumstick MIDI Midi を使う 毎回起動時に特定のドライバを読み込まないと、midi が使えないようで、Drumstick MIDI は MIDI setup を開く段階でクラッシュした。\nやること 有効化 sudo modprobe snd_virmidi 無効化 sudo modprobe -r snd_virmidi 起動時に自動で読み込まれるようにする /etc/systemd/system/midi.service [Unit] Description=load and unload virtual midi driver [Service] Type=simple User=root ExecStart=modprobe snd_virmidi ExecStop=modprobe -r snd_virmidi Restart=on-abort [Install] WantedBy=multi-user.target midi.serviceサービスの有効化 sudo systemctl enable midi ドライバを読み込む前の様子 ちなみに以下のエラーや挙動は、ドライバを読み込んでから、ドライバを無効化したあとに試すと症状が再現しない。再起動後は、またドライバを読み込むまで症状が再現している。現時点で私は、この挙動については正直細かくはわかっていない。\nエラーが出る例 (Drumstick MIDI) Active MIDI Inputs が何も出てこない例 (Surge XT) MIDI の設定をする 基本的には、Midi Through を使っておけば、ソフトウェア上では、音を鳴らせるところまで持っていける模様である。\nSurge XT Drumstick MIDI 参考にしたサイトとか Virtual MIDI keyboard input on Linux (ALSA or JACK, with Pipewire) : r/Bitwig\nhttps://www.reddit.com/r/Bitwig/comments/10uhclz/virtual_midi_keyboard_input_on_linux_alsa_or_jack/ (2025年9月24日)\nMIDI - ArchWiki\nhttps://wiki.archlinux.org/title/MIDI (2025年9月24日)\nKernel Module Loading at Boot and modprobe Automation | Baeldung on Linux\nhttps://www.baeldung.com/linux/kernel-module-load-boot (2025年9月24日)\nLinux: How to load a kernel module automatically at boot time - nixCraft\nhttps://www.cyberciti.biz/faq/linux-how-to-load-a-kernel-module-automatically-at-boot-time/ (2025年9月24日)\n[Solved] - Files in /modprobe.d/ seem to be ignored / Newbie Corner / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=180265 (2025年9月24日)\nKernel Module Loading at Boot and modprobe Automation | Baeldung on Linux\nhttps://www.baeldung.com/linux/kernel-module-load-boot#2-commands (2025年9月24日)\n","permalink":"https://www.nyanmo.info/posts/linux/midi/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Linux 環境を使っていて、ソフトウェアシンセサイザー？とか、適当にネットでダウンロードしてきたMIDIファイルを再生するとかやってみている。\u003c/p\u003e\n\u003cp\u003e　それで、Linux 環境における MIDI では、ちょっとすぐにはわからないようなことが必要だとわかったので、それをノートとして使っているこのブログに記録しようと思った。\u003c/p\u003e\n\u003ch2 id=\"使っているソフト\"\u003e使っているソフト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eSurge XT\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/midi/SurgeXT.png#center\"\n         alt=\"SurgeXT\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eDrumstick MIDI\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/midi/drumstickMIDI.png#center\"\n         alt=\"DrumstickMIDI\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"midi-を使う\"\u003eMidi を使う\u003c/h2\u003e\n\u003cp\u003e　毎回起動時に特定のドライバを読み込まないと、midi が使えないようで、Drumstick MIDI は \u003ccode\u003eMIDI setup\u003c/code\u003e を開く段階でクラッシュした。\u003c/p\u003e\n\u003ch3 id=\"やること\"\u003eやること\u003c/h3\u003e\n\u003ch4 id=\"有効化\"\u003e有効化\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esudo modprobe snd_virmidi\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"無効化\"\u003e無効化\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esudo modprobe -r snd_virmidi\n\u003c/code\u003e\u003c/pre\u003e\u003ch4 id=\"起動時に自動で読み込まれるようにする\"\u003e起動時に自動で読み込まれるようにする\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e/etc/systemd/system/midi.service\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e[Unit]\nDescription=load and unload virtual midi driver\n\n[Service]\nType=simple\nUser=root\nExecStart=modprobe snd_virmidi\nExecStop=modprobe -r snd_virmidi\nRestart=on-abort\n\n[Install]\nWantedBy=multi-user.target\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003emidi.service\u003c/code\u003eサービスの有効化\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esudo systemctl enable midi\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"ドライバを読み込む前の様子\"\u003eドライバを読み込む前の様子\u003c/h3\u003e\n\u003cp\u003e　ちなみに以下のエラーや挙動は、ドライバを読み込んでから、ドライバを無効化したあとに試すと症状が再現しない。再起動後は、またドライバを読み込むまで症状が再現している。現時点で私は、この挙動については正直細かくはわかっていない。\u003c/p\u003e\n\u003ch4 id=\"エラーが出る例-drumstick-midi\"\u003eエラーが出る例 (Drumstick MIDI)\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/midi/%e3%83%89%e3%83%a9%e3%82%a4%e3%83%90%e3%82%92%e8%aa%ad%e3%81%bf%e8%be%bc%e3%82%80%e5%89%8d%e3%81%aeDrumstickMIDI.png#center\"\n         alt=\"ドライバを読み込む前のDrumstickMIDI\"/\u003e \n\u003c/figure\u003e\n\n\u003ch4 id=\"active-midi-inputs-が何も出てこない例-surge-xt\"\u003eActive MIDI Inputs が何も出てこない例 (Surge XT)\u003c/h4\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/midi/%e3%83%89%e3%83%a9%e3%82%a4%e3%83%90%e3%82%92%e8%aa%ad%e3%81%bf%e8%be%bc%e3%82%80%e5%89%8d%e3%81%aeSurgeXT.png#center\"\n         alt=\"ドライバを読み込む前のSurgeXT\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"midi-の設定をする\"\u003eMIDI の設定をする\u003c/h2\u003e\n\u003cp\u003e　基本的には、\u003ccode\u003eMidi Through\u003c/code\u003e を使っておけば、ソフトウェア上では、音を鳴らせるところまで持っていける模様である。\u003c/p\u003e","title":"Linux MIDI をとりあえず使えるようにする"},{"content":"この記事を作った動機 React で useState なり useEffect なり hooks と呼ばれている状態変数と関係があるものを使うときは厳し目の条件があるようで、それが原因で動かないということがあった。\nそこでどこに気をつければ良さそうか、公式ドキュメントを見たり、調べてみたりして、自分なりの理解でとりあえず記録しようということになった。\n環境 Vite React TypeScript Tailwind CSS zustand hooks とは use〇〇 という感じで定義されている React の API 群の事っぽい。現状の体感としては、状態変数に関係する React の API のことを包括的に hooks とよんでいるように見える。以下は hooks の例である。\nuseState useRef useEffect 状態変数管理ライブラリで使う関数の一部？\nzustand の例 // 定義 --------------------------------------------- // 定義 --------------------------------------------- import { useEffect, useState } from \u0026#34;react\u0026#34; import { create } from \u0026#34;zustand\u0026#34;; type DatabaseState = { websocket: WebSocket | null; serverIP: string | null; changeServer: (ip: string) =\u0026gt; void; closeConnection: () =\u0026gt; void; getWebsocket: () =\u0026gt; WebSocket | null; }; // hooks 相当の部分の定義 export const useDatabaseStore = create\u0026lt;DatabaseState\u0026gt;((set, get) =\u0026gt; ({ websocket: null, serverIP: \u0026#34;ws://localhost:50097\u0026#34;, changeServer: (ip: string) =\u0026gt; { set({ serverIP: ip }); }, closeConnection: () =\u0026gt; { const ws = get().websocket; ws?.close(); set({ websocket: null }); }, getWebsocket: () =\u0026gt; get().websocket, })); // 定義 --------------------------------------------- // 定義 --------------------------------------------- export function Acompornent(){ // hooks 相当のコード const websocket = useDatabaseStore((s) =\u0026gt; s.websocket); // 何かしらのコード } use〇〇 から始まる APIを組み合わせた関数 // 定義 --------------------------------------------- // 定義 --------------------------------------------- // 上記の ”zustand の例” と同じ // 定義 --------------------------------------------- // 定義 --------------------------------------------- // useEffect の React API としての hooks や // useDatabaseStore の zustand (状態変数管理ライブラリの関数) としての hooks // を組み合わせてた 任意の定義の hooks の例 export function useDatabaseEffects() { const serverIP = useDatabaseStore((s) =\u0026gt; s.serverIP); const setWebsocket = useDatabaseStore.setState; useEffect(() =\u0026gt; { if (!serverIP) return; const ws = new WebSocket(serverIP); setWebsocket({ websocket: ws }); // return () =\u0026gt; { // ws.close(); // }; }, [serverIP, setWebsocket]); } 気にしたほうが良さそうなこと コンポーネント内に hooks は書く コンポーネント内のなるべく先頭に hooks は書く コンポーネントの関数内のスコープからハズレたところには hooks は定義、宣言はできない。以下の部分が基本的にポイントな気がする。 if 文の中 loop 内 コールバック関数など、コンポーネント関数のスコープから外れるところ レンダリング部分内部 hooks で定義された状態変数の操作などは、コンポーネント関数内とかに限らず、コールバック内で呼び出したり、書き込んだり比較的自由にできる模様である。 // 何かしらのコード export default function Selector() { const websocket = useDatabaseStore((s) =\u0026gt; s.websocket); const [visible,setVisible] = useState(false) const init = useRef(true) const toolbarAddTool = useToggleableStore((s) =\u0026gt; s.addToggleable) // zustand (状態変数管理ライブラリ) も関係ある const [index, setIndex] = useState\u0026lt;Info\u0026gt;({ status: \u0026#34;init\u0026#34;, errorMessage: \u0026#34;nothing\u0026#34;, data: null, }); useEffect(() =\u0026gt; { if (!websocket) { setIndex({ status: \u0026#34;error\u0026#34;, errorMessage: \u0026#34;No data server connected to.\u0026#34;, data: null, }); return; } const handleMessage = (event: MessageEvent) =\u0026gt; { const result = JSON.parse(String(event.data)); console.log(result) if (!result.status.includes(\u0026#34;error\u0026#34;)) { setIndex(result); } else { setIndex({ status: result.status, errorMessage: result.errorMessage, data: null, }); } }; const whenOpened = () =\u0026gt; { const request = JSON.stringify({ command: \u0026#34;info\u0026#34;, data: null }); websocket.send(request); } websocket.addEventListener(\u0026#34;message\u0026#34;, handleMessage); websocket.addEventListener(\u0026#34;open\u0026#34;,whenOpened) // cleanup return () =\u0026gt; { websocket.removeEventListener(\u0026#34;message\u0026#34;, handleMessage); }; }, [websocket]); // 条件分岐やループ、レンダリングや何かしらのコールバック関数内などで、 // hooks を宣言したり、定義することはできないという感じの模様 // しかし、hooks の定義で出てくる set〇〇 などを使ったりして、状態変数を操作したりなどはできる模様 if(init.current){ const toggleable:toggleable = { name: \u0026#34;Selector\u0026#34;, setVisibility: setVisible, visibility:visible } toolbarAddTool(toggleable) init.current = false } // 何かしらのコード } エラーの発生と修正例 実際に私がOnenote代替品の作成でコードを書いているときに起こったエラーについて、記録してみる。\n具体的な内容としては if 文 の中に、zustand の状態変数の定義、宣言をしたために、正しく hooks が動作しなかったという内容になっていると思う。\n私的には、Rendered fewer hooks than expected. と怒られている部分が気になった。これはつまり、if 文内に hooks の定義や宣言を書いてしまうと、条件分岐次第でコンポーネント内の hooks の数が変わってしまうということに、つながっているのではないかと考えてみた。\nhooks の条件を満たしていないときに見られるエラー例 ToggleToolsBar.tsx:21 Cannot update a component (`ToolsBar`) while rendering a different component (`Selector`). To locate the bad setState() call inside `Selector`, follow the stack trace as described in https://react.dev/link/setstate-in-render react-dom_client.js?v=79552f97:4247 Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement. at finishRenderingHooks (react-dom_client.js?v=79552f97:4247:17) at renderWithHooks (react-dom_client.js?v=79552f97:4225:9) at updateFunctionComponent (react-dom_client.js?v=79552f97:6617:21) at beginWork (react-dom_client.js?v=79552f97:7652:20) at runWithFiberInDEV (react-dom_client.js?v=79552f97:1483:72) at performUnitOfWork (react-dom_client.js?v=79552f97:10866:98) at workLoopSync (react-dom_client.js?v=79552f97:10726:43) at renderRootSync (react-dom_client.js?v=79552f97:10709:13) at performWorkOnRoot (react-dom_client.js?v=79552f97:10357:46) at performSyncWorkOnRoot (react-dom_client.js?v=79552f97:11633:9) window.tsx:29 An error occurred in the \u0026lt;Selector\u0026gt; component. Consider adding an error boundary to your tree to customize error handling behavior. Visit https://react.dev/link/error-boundaries to learn more about error boundaries. 修正前 export default function Selector() { const websocket = useDatabaseStore((s) =\u0026gt; s.websocket); const [visible,setVisible] = useState(false) const init = useRef(true) const [index, setIndex] = useState\u0026lt;Info\u0026gt;({ status: \u0026#34;init\u0026#34;, errorMessage: \u0026#34;nothing\u0026#34;, data: null, }); // 何かしらのコード // if 文 内部で hooks を定義、宣言してしまっている例 if(init.current){ // 問題の部分 ---------------------------------- // 問題の部分 ---------------------------------- const toolbarAddTool = useToggleableStore((s) =\u0026gt; s.addToggleable) // 問題の部分 ---------------------------------- // 問題の部分 ---------------------------------- const toggleable:toggleable = { name: \u0026#34;Selector\u0026#34;, setVisibility: setVisible, visibility:visible } toolbarAddTool(toggleable) init.current = false } // 何かしらのコード } 修正後 export default function Selector() { const websocket = useDatabaseStore((s) =\u0026gt; s.websocket); const [visible,setVisible] = useState(false) const init = useRef(true) // 修正した部分 --------------------------------- // 修正した部分 --------------------------------- const toolbarAddTool = useToggleableStore((s) =\u0026gt; s.addToggleable) // 修正した部分 --------------------------------- // 修正した部分 --------------------------------- const [index, setIndex] = useState\u0026lt;Info\u0026gt;({ status: \u0026#34;init\u0026#34;, errorMessage: \u0026#34;nothing\u0026#34;, data: null, }); // 何かしらのコード if(init.current){ const toggleable:toggleable = { name: \u0026#34;Selector\u0026#34;, setVisibility: setVisible, visibility:visible } toolbarAddTool(toggleable) init.current = false } // 何かしらのコード } 参考にしたサイトとか Rules of Hooks – React\nhttps://react.dev/warnings/invalid-hook-call-warning (2025年9月10日) javascript - Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement in React Hooks - Stack Overflow\nhttps://stackoverflow.com/questions/53472795/uncaught-error-rendered-fewer-hooks-than-expected-this-may-be-caused-by-an-acc (2025年9月10日) Quick Start – React\nhttps://react.dev/learn#using-hooks (2025年9月10日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/react/hooks/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　React で useState なり useEffect なり hooks と呼ばれている状態変数と関係があるものを使うときは厳し目の条件があるようで、それが原因で動かないということがあった。\u003c/p\u003e\n\u003cp\u003e　そこでどこに気をつければ良さそうか、公式ドキュメントを見たり、調べてみたりして、自分なりの理解でとりあえず記録しようということになった。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eTailwind CSS\u003c/li\u003e\n\u003cli\u003ezustand\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"hooks-とは\"\u003ehooks とは\u003c/h2\u003e\n\u003cp\u003e　use〇〇 という感じで定義されている React の API 群の事っぽい。現状の体感としては、状態変数に関係する React の API のことを包括的に hooks とよんでいるように見える。以下は hooks の例である。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003euseState\u003c/li\u003e\n\u003cli\u003euseRef\u003c/li\u003e\n\u003cli\u003euseEffect\u003c/li\u003e\n\u003cli\u003e状態変数管理ライブラリで使う関数の一部？\u003cbr\u003e\n　zustand の例\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-TSX\" data-lang=\"TSX\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003euseEffect\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003euseState\u003c/span\u003e } \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e } \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zustand\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDatabaseState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eWebSocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecloseConnection\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetWebsocket\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// hooks 相当の部分の定義\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eDatabaseState\u003c/span\u003e\u0026gt;((\u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e ({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:50097\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eip\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecloseConnection\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ews\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ews\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclose\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetWebsocket\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAcompornent\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hooks 相当のコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003euse〇〇 から始まる APIを組み合わせた関数\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//      上記の ”zustand の例” と同じ\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 定義 ---------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// useEffect の React API としての hooks や\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// useDatabaseStore の zustand (状態変数管理ライブラリの関数) としての hooks \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// を組み合わせてた 任意の定義の hooks の例\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseEffects() {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esetState\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003euseEffect\u003c/span\u003e(() \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ews\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ews\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// return () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//   ws.close();\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// };\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }, [\u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003esetWebsocket\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"気にしたほうが良さそうなこと\"\u003e気にしたほうが良さそうなこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eコンポーネント内に hooks は書く\u003c/li\u003e\n\u003cli\u003eコンポーネント内のなるべく先頭に hooks は書く\u003c/li\u003e\n\u003cli\u003eコンポーネントの関数内のスコープからハズレたところには hooks は定義、宣言はできない。以下の部分が基本的にポイントな気がする。\n\u003cul\u003e\n\u003cli\u003eif 文の中\u003c/li\u003e\n\u003cli\u003eloop 内\u003c/li\u003e\n\u003cli\u003eコールバック関数など、コンポーネント関数のスコープから外れるところ\u003c/li\u003e\n\u003cli\u003eレンダリング部分内部\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003ehooks で定義された状態変数の操作などは、コンポーネント関数内とかに限らず、コールバック内で呼び出したり、書き込んだり比較的自由にできる模様である。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-TSX\" data-lang=\"TSX\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSelector() {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e             \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003evisible\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003esetVisible\u003c/span\u003e]  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseState\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e                  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseRef\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etoolbarAddTool\u003c/span\u003e        \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseToggleableStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddToggleable\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e// zustand (状態変数管理ライブラリ) も関係ある\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003esetIndex\u003c/span\u003e]     \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseState\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eInfo\u003c/span\u003e\u0026gt;({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;init\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eerrorMessage\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;nothing\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003euseEffect\u003c/span\u003e(() \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003esetIndex\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eerrorMessage\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;No data server connected to.\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehandleMessage\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eMessageEvent\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eparse\u003c/span\u003e(String(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eincludes\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;error\u0026#34;\u003c/span\u003e)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esetIndex\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esetIndex\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003estatus\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eresult.status\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003eerrorMessage\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eresult.errorMessage\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewhenOpened\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eJSON\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estringify\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ecommand\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;info\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003edata\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003erequest\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ehandleMessage\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;open\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ewhenOpened\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// cleanup\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eremoveEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;message\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ehandleMessage\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }, [\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 条件分岐やループ、レンダリングや何かしらのコールバック関数内などで、\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hooks を宣言したり、定義することはできないという感じの模様\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// しかし、hooks の定義で出てくる set〇〇 などを使ったりして、状態変数を操作したりなどはできる模様\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrent\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etoggleable\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003etoggleable\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Selector\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003esetVisibility\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003esetVisible\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003evisibility\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003evisible\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etoolbarAddTool\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003etoggleable\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003einit\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecurrent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"エラーの発生と修正例\"\u003eエラーの発生と修正例\u003c/h2\u003e\n\u003cp\u003e　実際に私が\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/\"\u003eOnenote代替品の作成\u003c/a\u003eでコードを書いているときに起こったエラーについて、記録してみる。\u003c/p\u003e","title":"Hooks の宣言、定義で躓いたこと"},{"content":"この記事を作った動機 React で addEventListener を使ったら、再描画される事に、addEventListener されまくって、例えばマウスボタンが押されたというイベントが発火したときに、無数の同じ処理が走りまくるという事態になった。\nこれは以下のように、react の要素の一部として書いたときには、起こらなかった。\nexport function OverlayWindow({ children, arg }:{ children:ReactNode, arg:OverlayWindowArgs }){ // 何かしらのコード if(visible){ return (\u0026lt;div className={OverlayWindowContaierClassName} style={windowPosStyle}\u0026gt; \u0026lt;div className=\u0026#34;windowHeader move bg-yellow-600 w-full h-[2rem] justify-center place-items-center align-middle text-center\u0026#34; onMouseDown={windowHandlers.mousedown} // addEventListener 相当 onTouchStart={windowHandlers.touchstart} // addEventListener 相当 \u0026gt; \u0026lt;div className=\u0026#34;title h-[1rem] absolute text-white\u0026#34;\u0026gt;{arg.title}\u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;close size-[2rem] bg-red-700 ml-auto\u0026#34; onClick={() =\u0026gt; {setVisible(false)}}\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div className=\u0026#34;content bg-gray-900 min-h-[5rem] w-full flex justify-center place-items-center align-middle text-center items-center\u0026#34;\u0026gt; {children} \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt;) } } それでとりあえず、解決状態だと思われる、アプリ自体の動作を重くしないレベルの実装にもっていくまでについて、簡易的に記録を取ろうと思い、この記事を作った。\n環境 Vite React TypeScript Tailwind CSS zustand 問題の状態 このようにして、グローバルにすべての mousemove などのイベントの発火を要素関係なく受け取ろうとすると、再描画時に何度も addEventListener で特定のイベントに対し、コールバック関数が登録されてしまう。\nexport function OverlayWindow({ children, arg }:{ children:ReactNode, arg:OverlayWindowArgs }){ // 何かしらのコード addEventListener(\u0026#34;touchend\u0026#34;,windowHandlers.touchend) addEventListener(\u0026#34;mouseup\u0026#34;,windowHandlers.mouseup) addEventListener(\u0026#34;touchmove\u0026#34;,windowHandlers.touchmove) addEventListener(\u0026#34;mousemove\u0026#34;,windowHandlers.mousemove) // 何かしらのコード } 私が今回取った対応 useRef を使って、コンポーネントが初期化されたかどうかに関する状態を管理することにした。そうすることで一回だけ addEventListener で特定のイベントにコールバック関数を設定するようにした。\nexport function OverlayWindow({ children, arg }:{ children:ReactNode, arg:OverlayWindowArgs }){ // 何かしらのコード let init = useRef(true) // 何かしらのコード if(init.current){ // console.log(\u0026#34;Overlay window init\u0026#34;) addEventListener(\u0026#34;touchend\u0026#34;,windowHandlers.touchend) addEventListener(\u0026#34;mouseup\u0026#34;,windowHandlers.mouseup) addEventListener(\u0026#34;touchmove\u0026#34;,windowHandlers.touchmove) addEventListener(\u0026#34;mousemove\u0026#34;,windowHandlers.mousemove) init.current = false console.log(init.current) } // 何かしらのコード } 更に新しい対応（2025/10/5 追記） 最近、useEffect でもっときれいに実装できることがわかったので、どうするのか記録する。\nexport function OverlayWindow({ children, arg }:{ children:ReactNode, arg:OverlayWindowArgs }){ // 何かしらのコード // 依存関係を設定していない useEffect はコンポーネント生成時に一度だけ実行される。 // またコンポーネント再生成のときなど、コンポーネント破棄時には、return に関数が設定されていれば、それが実行される。 useEffect(() =\u0026gt; { addEventListener(\u0026#34;touchend\u0026#34;,windowHandlers.touchend) addEventListener(\u0026#34;mouseup\u0026#34;,windowHandlers.mouseup) addEventListener(\u0026#34;touchmove\u0026#34;,windowHandlers.touchmove) addEventListener(\u0026#34;mousemove\u0026#34;,windowHandlers.mousemove) return () =\u0026gt; { removeEventListener(\u0026#34;touchend\u0026#34;,windowHandlers.touchend) removeEventListener(\u0026#34;mouseup\u0026#34;,windowHandlers.mouseup) removeEventListener(\u0026#34;touchmove\u0026#34;,windowHandlers.touchmove) removeEventListener(\u0026#34;mousemove\u0026#34;,windowHandlers.mousemove) } },[]) // ちなみに、空でもいいので、依存関係を表す配列がないと、コンポーネント再描画時に毎回実行される useEffect ができてしまい、全く意味の違うものになるので注意する。 // 何かしらのコード } 関連の記事 変数 参考にしたサイトとか EventTarget: addEventListener() method - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener (2025年9月10日) useEffect – React\nhttps://react.dev/reference/react/useEffect (2025年9月9日) useRef – React\nhttps://react.dev/reference/react/useRef (2025年9月9日) useState – React\nhttps://react.dev/reference/react/useState (2025年9月9日) useState – React\nhttps://react.dev/reference/react/useState#updating-objects-and-arrays-in-state (2025年9月9日) ChatGPT\nhttps://chatgpt.com/ (2025年9月9日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/react/addeventlistener/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　React で addEventListener を使ったら、再描画される事に、addEventListener されまくって、例えばマウスボタンが押されたというイベントが発火したときに、無数の同じ処理が走りまくるという事態になった。\u003c/p\u003e\n\u003cp\u003e　これは以下のように、react の要素の一部として書いたときには、起こらなかった。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOverlayWindow\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003earg\u003c/span\u003e }\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e{ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eReactNode\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003earg\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eOverlayWindowArgs\u003c/span\u003e }){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003evisible\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eOverlayWindowContaierClassName\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003ewindowPosStyle\u003c/span\u003e}\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;windowHeader move bg-yellow-600 w-full h-[2rem] justify-center place-items-center align-middle text-center\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eonMouseDown\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003ewindowHandlers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003emousedown\u003c/span\u003e}   \u003cspan style=\"color:#75715e\"\u003e// addEventListener 相当\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eonTouchStart\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003ewindowHandlers\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etouchstart\u003c/span\u003e} \u003cspan style=\"color:#75715e\"\u003e// addEventListener 相当\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;title h-[1rem] absolute text-white\u0026#34;\u003c/span\u003e\u0026gt;{\u003cspan style=\"color:#a6e22e\"\u003earg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e}\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;close size-[2rem] bg-red-700 ml-auto\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonClick\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{() \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\u003cspan style=\"color:#a6e22e\"\u003esetVisible\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)}}\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;content bg-gray-900 min-h-[5rem] w-full flex justify-center place-items-center align-middle text-center\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e items-center\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　それでとりあえず、解決状態だと思われる、アプリ自体の動作を重くしないレベルの実装にもっていくまでについて、簡易的に記録を取ろうと思い、この記事を作った。\u003c/p\u003e","title":"React と addEventListener"},{"content":"この記事を作った動機 単に、このブログの方針として、”自分が参照するノート”としてメインに掲げているところがある。それで、必ずしも \u0026ldquo;content/posts/idea/research/onenoteAlternativeCreation/\u0026rdquo; 配下に収まっているわけではなく、色んな所に関係のある記事が散らばっている。\nそれらをまとめるために、この記事にリンク集みたいな感じで、散らばってしまっている記事をまとめておこうと思った次第である。\n記事リスト React コンポーネント内にネストができる関数コンポーネント 変数 Zustand 状態変数管理ライブラリ Hooks の宣言、定義で躓いたこと Websocket を自動で再接続したい TypeScript Date クラスで躓いたこと ","permalink":"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/b4/whereistumbled/articlelist/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に、このブログの方針として、”自分が参照するノート”としてメインに掲げているところがある。それで、必ずしも \u0026ldquo;content/posts/idea/research/onenoteAlternativeCreation/\u0026rdquo; 配下に収まっているわけではなく、色んな所に関係のある記事が散らばっている。\u003c/p\u003e\n\u003cp\u003e　それらをまとめるために、この記事にリンク集みたいな感じで、散らばってしまっている記事をまとめておこうと思った次第である。\u003c/p\u003e\n\u003ch2 id=\"記事リスト\"\u003e記事リスト\u003c/h2\u003e\n\u003ch3 id=\"react\"\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/\"\u003eReact\u003c/a\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/nestcomponent/\"\u003eコンポーネント内にネストができる関数コンポーネント\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/variable/\"\u003e変数\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/zustand/\"\u003eZustand 状態変数管理ライブラリ\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/hooks/\"\u003eHooks の宣言、定義で躓いたこと\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/react/websocketreconnect/\"\u003eWebsocket を自動で再接続したい\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"typescript\"\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/typescript/\"\u003eTypeScript\u003c/a\u003e\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/typescript/dateclass/\"\u003eDate クラスで躓いたこと\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"記事リスト"},{"content":"この記事を作った動機 単に自分用に、zustand の使い方を今 (2025/9/9) わかっている範囲で、書き出してみるだけ。\n環境 Vite React TypeScript Tailwind CSS zustand 概要 まだ全然わかっていないが、私の今 (2025/9/9) イメージとしては、「zustand とは、react で言う状態変数の管理に関するライブラリの一つで、親 -\u0026gt; 子 コンポーネントという流れで状態変数を渡していく以外で、コンポーネント間の状態変数を共有、管理することができるもの。」という感じである。　TODO 参照が変わらないと、再描画が起こらないことを書く。例えば、setter 内で、get()したものを直接変更し、set()のところに使うと、参照が同じのため、問題が起こる。 使い方 import import { create } from \u0026#34;zustand\u0026#34;; 宣言例 type DatabaseState = { websocket: WebSocket | null; serverIP: string | null; changeServer: (ip: string) =\u0026gt; void; closeConnection: () =\u0026gt; void; getWebsocket: () =\u0026gt; WebSocket | null; }; export const useDatabaseStore = create\u0026lt;DatabaseState\u0026gt;((set, get) =\u0026gt; ({ // 変数の初期化 websocket: null, serverIP: \u0026#34;ws://localhost:50097\u0026#34;, // 変数を操作する関数群 changeServer: (ip: string) =\u0026gt; { set({ serverIP: ip }); }, closeConnection: () =\u0026gt; { const ws = get().websocket; ws?.close(); set({ websocket: null }); }, getWebsocket: () =\u0026gt; get().websocket, })); データを呼び出し、利用する export function Acompornent(){ // 他の hooks と同様にコンポーネントのコードの先頭あたりに書く必要がある。 const websocket = useDatabaseStore((s) =\u0026gt; s.websocket); console.log(websocket) // 何かしらのコード } 関数を呼び出す export function Acompornent(){ // 他の hooks と同様にコンポーネントのコードの先頭あたりに書く必要がある。 const changeServer = useDatabaseStore((s) =\u0026gt; s.changeServer) changeServer(\u0026#34;ws://localhost:88091\u0026#34;) // 何かしらのコード } 躓いたこと イミュータブルの原則 zustand を使っているときに、どうやっても値を更新しているにも関わらず、再描画が正しくかからないという問題が起こった。これは、同じ参照を持つ変数を変更するという、\u0026ldquo;ミュータブル\u0026quot;な扱いをしたときに起こるようである。一度宣言された、作られた変数は原則変更しない(できない)というのが、React や zustand といった状態変数の概念の前提にはあるっぽいと私は最終的に考えた。\n今回の場合では、overlayWindow.tsx で動かしているいろんな細かい操作をするためのツールのウィンドウ描画を支援するコード内で起こった。例えば、特定のウィンドウがクリックされると、クリックされた isActive の値が true、それ以外のウィンドウの isActive の値が false になるという処理 makeAwindowActive があるが、値を変更しても正しく連動して動作しないということがあった。症状としては、値は更新されているが、他のウィンドウをクリックしても、useEffect を介して再描画がかからないため、元々アクティブだったウィンドウは inActive スタイルに切り替わらないという症状になった。\n今回の例のコードで登場するデータ型 type AoverlayWindow = { name: string, // window title UUID: string, isActive: boolean, // false -\u0026gt; inactive, true -\u0026gt; active zIndex: number // 200-1200 } type overlayWindows = { windows: AoverlayWindow[], zIndexMax: number, zIndesMin: number, addWindow: (window:AoverlayWindow) =\u0026gt; void, // in first place, z-index will be the highest number. removeWindow: (window:AoverlayWindow) =\u0026gt; void, allWindowInactive: () =\u0026gt; void, // no need to update z-index makeAwindowActive: (window:AoverlayWindow) =\u0026gt; void,// the active window need to update z-index to the highest number. need to update other windows z-index subtracted by 1. getWindow: (window:AoverlayWindow) =\u0026gt; AoverlayWindow, } useEffect の例 const windows = useOverlayWindowStore((s) =\u0026gt; s.windows) // 何かしらのコード ... useEffect(() =\u0026gt; { console.log(\u0026#34;the overlay window info is updated\u0026#34;) if(getWindow(aWindowINIT.current).isActive){ setWindowStyle({ left: String(windowPos.current.x) + \u0026#34;px\u0026#34;, top: String(windowPos.current.y) + \u0026#34;px\u0026#34;, zIndex: String(getWindow(aWindowINIT.current).zIndex), opacity: String(0.95), }) }else{ setWindowStyle({ left: String(windowPos.current.x) + \u0026#34;px\u0026#34;, top: String(windowPos.current.y) + \u0026#34;px\u0026#34;, zIndex: String(getWindow(aWindowINIT.current).zIndex), opacity: String(0.30), }) } },[windows]) // 何かしらのコード ... とりあえず動くレベルのコード const useOverlayWindowStore = create\u0026lt;overlayWindows\u0026gt;((set,get) =\u0026gt; ({ windows: [], // const vals zIndesMin: 1300, zIndexMax: 1400, // register and deresiger window addWindow: (window:AoverlayWindow) =\u0026gt; { let newInfo = get().windows window.isActive = true window.zIndex = get().zIndexMax for(let i = 0; i \u0026lt; newInfo.length; i++){ newInfo[i].isActive = false newInfo[i].zIndex = newInfo[i].zIndex-- } // これは新しい参照を持つ window という変数があるので、再描画が行われる // newInfo に関しては、イミュータブルの原則をこのコードでは破ってしまっているが、それでも値の変更自体は反映されるようである。 // ただし newInfo 単体では再描画が正しくかからないことに変わりはない。 set(() =\u0026gt; ({windows: [...newInfo,window]})) }, // 何かしらのコード... // 注目する部分 ----------------------- // 注目する部分 ----------------------- // window manipulation allWindowInactive: () =\u0026gt; { let oldInfo = get().windows // 古い参照 let newInfo = [] //　新しく配列を宣言することで、新しい参照を作成する for(const old of oldInfo){ newInfo.push(old) } for(let i = 0; i \u0026lt; newInfo.length; i++){ newInfo[i].isActive = false } // 新しい配列 newInfo を設定したので、再描画される set(() =\u0026gt; ({windows: newInfo})) }, // 注目する部分 ----------------------- // 注目する部分 ----------------------- // 何かしらのコード... getWindow: (window:AoverlayWindow) =\u0026gt; { console.log(\u0026#34;get window\u0026#34;) console.log(window.UUID) console.log(window) console.log(get().windows) for(let test of get().windows){ if(test.UUID == window.UUID) { return test } } return window } })) 問題のあるコード const useOverlayWindowStore = create\u0026lt;overlayWindows\u0026gt;((set,get) =\u0026gt; ({ windows: [], // const vals zIndesMin: 1300, zIndexMax: 1400, // register and deresiger window addWindow: (window:AoverlayWindow) =\u0026gt; { let newInfo = get().windows window.isActive = true window.zIndex = get().zIndexMax for(let i = 0; i \u0026lt; newInfo.length; i++){ newInfo[i].isActive = false newInfo[i].zIndex = newInfo[i].zIndex-- } set(() =\u0026gt; ({windows: [...newInfo,window]})) }, // 何かしらのコード... // 注目する部分 ----------------------- // 注目する部分 ----------------------- // window manipulation allWindowInactive: () =\u0026gt; { let newInfo = get().windows // newInfo は古い参照のまま for(let i = 0; i \u0026lt; newInfo.length; i++){ newInfo[i].isActive = false } // newInfo は元々あった windows 配列を再利用しており、参照が変わっていないため、正しく再描画がここでかからない set(() =\u0026gt; ({windows: newInfo})) }, // 注目する部分 ----------------------- // 注目する部分 ----------------------- // 何かしらのコード... getWindow: (window:AoverlayWindow) =\u0026gt; { console.log(\u0026#34;get window\u0026#34;) console.log(window.UUID) console.log(window) console.log(get().windows) for(let test of get().windows){ if(test.UUID == window.UUID) { return test } } return window } })) 参考 Flux inspired practice - Zustand\nhttps://zustand.docs.pmnd.rs/guides/flux-inspired-practice#use-set-/-setstate-to-update-the-store (2025年9月30日) Immutable state and merging - Zustand\nhttps://zustand.docs.pmnd.rs/guides/immutable-state-and-merging (2025年9月30日) State change does not cause re-render · pmndrs/zustand · Discussion #1653\nhttps://github.com/pmndrs/zustand/discussions/1653 (2025年9月30日) ChatGPT Open as a page 関係ありそうな記事 Hooks の宣言、定義で躓いたこと 参考にしたサイトとか Introduction - Zustand\nhttps://zustand.docs.pmnd.rs/getting-started/introduction (2025年9月9日)\nChatGPT\nhttps://chatgpt.com/ (2025年9月9日)\nRules of Hooks – React\nhttps://react.dev/warnings/invalid-hook-call-warning (2025年9月10日)\njavascript - Uncaught Error: Rendered fewer hooks than expected. This may be caused by an accidental early return statement in React Hooks - Stack Overflow\nhttps://stackoverflow.com/questions/53472795/uncaught-error-rendered-fewer-hooks-than-expected-this-may-be-caused-by-an-acc (2025年9月10日)\nFlux inspired practice - Zustand\nhttps://zustand.docs.pmnd.rs/guides/flux-inspired-practice#use-set-/-setstate-to-update-the-store (2025年9月30日)\nImmutable state and merging - Zustand\nhttps://zustand.docs.pmnd.rs/guides/immutable-state-and-merging (2025年9月30日)\nState change does not cause re-render · pmndrs/zustand · Discussion #1653\nhttps://github.com/pmndrs/zustand/discussions/1653 (2025年9月30日)\n","permalink":"https://www.nyanmo.info/posts/webdevelop/react/zustand/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に自分用に、zustand の使い方を今 (2025/9/9) わかっている範囲で、書き出してみるだけ。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eTailwind CSS\u003c/li\u003e\n\u003cli\u003ezustand\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"概要\"\u003e概要\u003c/h2\u003e\n\u003cp\u003e　まだ全然わかっていないが、私の今 (2025/9/9) イメージとしては、「zustand とは、react で言う状態変数の管理に関するライブラリの一つで、親 -\u0026gt; 子 コンポーネントという流れで状態変数を渡していく以外で、コンポーネント間の状態変数を共有、管理することができるもの。」という感じである。　\u003c/p\u003e\n\u003ch2 id=\"todo\"\u003eTODO\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cinput checked=\"\" disabled=\"\" type=\"checkbox\"\u003e 参照が変わらないと、再描画が起こらないことを書く。例えば、setter 内で、get()したものを直接変更し、set()のところに使うと、参照が同じのため、問題が起こる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"使い方\"\u003e使い方\u003c/h2\u003e\n\u003ch3 id=\"import\"\u003eimport\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e } \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zustand\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"宣言例\"\u003e宣言例\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDatabaseState\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eWebSocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecloseConnection\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetWebsocket\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eWebSocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreate\u003c/span\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eDatabaseState\u003c/span\u003e\u0026gt;((\u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e ({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 変数の初期化\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:50097\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 変数を操作する関数群\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eip\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003estring\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003eserverIP\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eip\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecloseConnection\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ews\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ews\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eclose\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eset\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egetWebsocket\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"データを呼び出し利用する\"\u003eデータを呼び出し、利用する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAcompornent\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 他の hooks と同様にコンポーネントのコードの先頭あたりに書く必要がある。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ewebsocket\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"関数を呼び出す\"\u003e関数を呼び出す\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-tsx\" data-lang=\"tsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAcompornent\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 他の hooks と同様にコンポーネントのコードの先頭あたりに書く必要がある。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseDatabaseStore\u003c/span\u003e((\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echangeServer\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ws://localhost:88091\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"躓いたこと\"\u003e躓いたこと\u003c/h2\u003e\n\u003ch3 id=\"イミュータブルの原則\"\u003eイミュータブルの原則\u003c/h3\u003e\n\u003cp\u003e　zustand を使っているときに、どうやっても値を更新しているにも関わらず、再描画が正しくかからないという問題が起こった。これは、同じ参照を持つ変数を変更するという、\u0026ldquo;ミュータブル\u0026quot;な扱いをしたときに起こるようである。一度宣言された、作られた変数は原則変更しない(できない)というのが、React や zustand といった状態変数の概念の前提にはあるっぽいと私は最終的に考えた。\u003c/p\u003e","title":"Zustand 状態変数管理ライブラリ"},{"content":"この記事を作った動機 全然まだ私は使い方とか概念をわかってないと思うが、とにかくよく使う hooks について記録を取りたいので、記事を書くだけ。思考の整理とかって感じで書いていて、普通に間違い混ざってると思うし、他の人に参考になるかは怪しい。\nreact とデータの関係性 React では、データが変更されると UI が連動して更新されたりするという仕組みになっているので、普通の変数ではなく、データのありように合わせて、状態変数と呼ばれるものを使い分ける必要がある。\n環境 Vite React TypeScript Tailwind CSS zustand 普通の変数 概要 普通に TypeScript や JavaScript で宣言するような let や var などと書いて宣言する変数たちのことである。これら変数の内容は基本的に React が再描画をかけると内容が初期化されて元の再描画前のデータは消えてしまう。\nこれを防ぎ、UI 再描画をまたいで変数の値を保持するためには、状態変数を useState なり、 useRef なり宣言して利用する必要があると思われる。\nexport default function Acompornent(){ // 再描画時には、x:100 y:100 にいちいち初期化されて変更内容が失われる let windowPos = { x: 100, y: 100 } // こちらは再描画時には内容は失われない const [style,setStyle] = useState({ top:0, left:0 }) // このようなコードを書くと windowPos は setStyle されたあと再描画で内容が初期値に戻ってしまう addEventListener(\u0026#34;mousemove\u0026#34;,(event:MouseEvent) =\u0026gt; { // 何かしらのコード windowPos.x = event.screenX windowPos.y = event.screenY // 何かしらのコード setStyle({ top: windowPos.x, left: windowPos.y }) }) return　\u0026lt;div style={style} className=\u0026#34;fixed\u0026#34;\u0026gt;This is styled text.\u0026lt;/div\u0026gt; } useState 概要 オーソドックスな状態変数で、データが更新されたとき、UI を再描画させたいという場合に使う。\nimport import { useState } from \u0026#34;react\u0026#34; 宣言 // useState の中身はいろんなデータ型が入る。特定の boolean 型しか使えないとかそういうことはないようである。 const [visible,setVisible] = useState(true) // 厳密に型を指定することもできるようである。 const [visible,setVisible] = useState\u0026lt;boolean\u0026gt;(true) // 初期値が null の例 const [visible,setVisible] = useState\u0026lt;boolean | null\u0026gt;(null) const [data,setData] = useState({ someItem: \u0026#34;itemname\u0026#34;, nest:{ \u0026#34;howComplexItIs\u0026#34;:\u0026#34;butShowExampleForNow\u0026#34;, \u0026#34;nestitem\u0026#34;:[\u0026#34;nestdata\u0026#34;,\u0026#34;nestdata1\u0026#34;] } }) データを読み取る console.log(visible) console.log(data) console.log(data.someItem) console.log(data.nest.howComplexItIs) データを更新する useState – React にも書いてあるが、...[変数名] みたいにすることで、とにかく前の値を引き継げるようである。\nsetVisible(true) setVisible(false) // すべてを更新する setData({ someItem: \u0026#34;aaa\u0026#34;, nest:{ \u0026#34;howComplexItIs\u0026#34;:\u0026#34;aa\u0026#34;, \u0026#34;nestitem\u0026#34;:[\u0026#34;sss,sss\u0026#34;] } }) // 部分的に更新し、その他は元の値を保持する setData({ ...data, nest:{ ...data.nest, \u0026#34;nestitem\u0026#34;:[...data.nest.nestitem,\u0026#34;newItem\u0026#34;] } }) // 部分的に更新し、その他は元の値を保持する setData((state) =\u0026gt; ({ ...state, nest:{ ...state.nest, \u0026#34;nestitem\u0026#34;:[...state.nest.nestitem,\u0026#34;newItem\u0026#34;] } })) useRef 概要 私は現状(2025/9/9)だと useState から、状態変数の値が変更されたときの UI 再描画を取り除いたものというイメージをもっている。通常の変数では再描画が起こると内容が失われて初期値にリセットされてしまうが、変数更新時に UI を再描画したいわけでもない場合に、データを保持するために使うっぽい？\nまとめると、再描画をまたいでデータを保持するが、データ更新時にUIを更新させたくないときに使うっぽい。\nimport import { useRef } from \u0026#34;react\u0026#34; 宣言 // useState と同様に自由にいろんな型のデータを設定できる let windowPos = useRef({ x:100, y:100 }) let onMove = useRef\u0026lt;boolean\u0026gt;(false) let onMove = useRef(false) データを読み取る console.log(windowPos.current.x) console.log(onMove.current) データを更新する windowPos.current.y = 2342 onMove.current = false onMove.current = true useEffect 概要 直接状態変数として使うものではないが、状態変数が変更されたときに、それを検出してなにか作業させたいときに使う。\nimport import { useEffect } from \u0026#34;react\u0026#34; 使い方 import { useEffect, useState } from \u0026#34;react\u0026#34; import { create } from \u0026#34;zustand\u0026#34;; // useEffect の前座 ------------------------------- // useEffect の前座 ------------------------------- type DatabaseState = { websocket: WebSocket | null; serverIP: string | null; changeServer: (ip: string) =\u0026gt; void; closeConnection: () =\u0026gt; void; getWebsocket: () =\u0026gt; WebSocket | null; }; export const useDatabaseStore = create\u0026lt;DatabaseState\u0026gt;((set, get) =\u0026gt; ({ websocket: null, serverIP: \u0026#34;ws://localhost:50097\u0026#34;, changeServer: (ip: string) =\u0026gt; { set({ serverIP: ip }); }, closeConnection: () =\u0026gt; { const ws = get().websocket; ws?.close(); set({ websocket: null }); }, getWebsocket: () =\u0026gt; get().websocket, })); // useEffect の前座 ------------------------------- // useEffect の前座 ------------------------------- // ここからが useEffect の例 ---------------------------- // ここからが useEffect の例 ---------------------------- export function useDatabaseEffects() { const serverIP = useDatabaseStore((s) =\u0026gt; s.serverIP); const setWebsocket = useDatabaseStore.setState; // serverIP setWebsocket などの変数のデータの変更（状態）を監視する useEffect useEffect(() =\u0026gt; { if (!serverIP) return; const ws = new WebSocket(serverIP); setWebsocket({ websocket: ws }); // このコードでは、一時的切っているが、return として関数を書いておくと、再描画時かuseEffectの次回実行時に、クリーンアップなど、やらせたい処理が書けるらしい？ まだここはよくわかっていない。 // return () =\u0026gt; { // ws.close(); // }; }, [serverIP, setWebsocket]); // 監視する状態変数のリスト } // ここまでが useEffect の例 ---------------------------- // ここまでが useEffect の例 ---------------------------- 躓いたこと なんか、躓いたことについて記録を取っていたつもりが、なんか how to に近くなってしまっている気がするので、具体的に状態変数について躓いたことも記録してみようと思った次第である。 このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） useEffect (2025/10/4) 毎回コンポーネント再描画時に実行される コンポーネントのライフサイクルの最初と最後だけ実行される とは異なり、毎回何かしらの状態変数が変わると更新がかかるので注意する。\nuseEffect(() =\u0026gt; { // 何かしらのコード return () =\u0026gt; { // クリーンアップ } }) // 依存関係の配列がない -\u0026gt; すべての状態変数を対象に監視する コンポーネントのライフサイクルの最初と最後だけ実行される コンポーネントが生成されたときの初期化コードとかにいいかもしれない。\nuseEffect(() =\u0026gt; { // 何かしらのコード return () =\u0026gt; { // クリーンアップ } },[]) // 空の依存関係を示す配列が設定されている -\u0026gt; どの状態変数にも依存関係がないことを示す 参考にしたサイトとか useEffect – React\nhttps://react.dev/reference/react/useEffect (2025年9月9日) useRef – React\nhttps://react.dev/reference/react/useRef (2025年9月9日) useState – React\nhttps://react.dev/reference/react/useState (2025年9月9日) useState – React\nhttps://react.dev/reference/react/useState#updating-objects-and-arrays-in-state (2025年9月9日) ChatGPT\nhttps://chatgpt.com/ (2025年9月9日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/react/variable/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　全然まだ私は使い方とか概念をわかってないと思うが、とにかくよく使う hooks について記録を取りたいので、記事を書くだけ。思考の整理とかって感じで書いていて、普通に間違い混ざってると思うし、他の人に参考になるかは怪しい。\u003c/p\u003e\n\u003ch2 id=\"react-とデータの関係性\"\u003ereact とデータの関係性\u003c/h2\u003e\n\u003cp\u003e　React では、データが変更されると UI が連動して更新されたりするという仕組みになっているので、普通の変数ではなく、データのありように合わせて、状態変数と呼ばれるものを使い分ける必要がある。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eTailwind CSS\u003c/li\u003e\n\u003cli\u003ezustand\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"普通の変数\"\u003e普通の変数\u003c/h2\u003e\n\u003ch3 id=\"概要\"\u003e概要\u003c/h3\u003e\n\u003cp\u003e　普通に TypeScript や JavaScript で宣言するような let や var などと書いて宣言する変数たちのことである。これら変数の内容は基本的に React が再描画をかけると内容が初期化されて元の再描画前のデータは消えてしまう。\u003c/p\u003e\n\u003cp\u003e　これを防ぎ、UI 再描画をまたいで変数の値を保持するためには、状態変数を useState なり、 useRef なり宣言して利用する必要があると思われる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-TSX\" data-lang=\"TSX\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAcompornent\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 再描画時には、x:100 y:100 にいちいち初期化されて変更内容が失われる\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewindowPos\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ex\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003e100\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ey\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003e100\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// こちらは再描画時には内容は失われない\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e [\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseState\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etop\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003e0\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// このようなコードを書くと windowPos は setStyle されたあと再描画で内容が初期値に戻ってしまう\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eaddEventListener\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;mousemove\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eMouseEvent\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewindowPos\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003escreenX\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ewindowPos\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eevent\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003escreenY\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 何かしらのコード\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esetStyle\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003etop\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ewindowPos.x\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ewindowPos.y\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e　\u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;fixed\u0026#34;\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eThis\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eis\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyled\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etext\u003c/span\u003e.\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"usestate\"\u003euseState\u003c/h2\u003e\n\u003ch3 id=\"概要-1\"\u003e概要\u003c/h3\u003e\n\u003cp\u003e　オーソドックスな状態変数で、データが更新されたとき、UI を再描画させたいという場合に使う。\u003c/p\u003e","title":"変数"},{"content":"この記事を作った動機 Vite + React + TypeScript の環境でコンポーネント\u0026quot;内部\u0026quot;になにか要素をネストする方法がわかんなかったので記録するだけ。ただ厳密のこのやり方で正しいかはわかっていないが、ChatGPT-5 が出したやり方がとりあえず動いたので記録することにした。今のところ公式ドキュメントとかで今回出すようなやりかたをしているのはまだ見つけられていない。\n環境 Vite React TypeScript Tailwind CSS zustand ネストの仕方 ネストできる関数コンポーネントを単体で定義 import {type ReactNode} from \u0026#34;react\u0026#34; export default function Outside1({ children }:{ children:ReactNode }){ return \u0026lt;div className=\u0026#34;flex flex-row bg-gray-700 h-[5rem] w-screen top-[5rem] left-0 fixed\u0026#34;\u0026gt; {children} \u0026lt;/div\u0026gt; } ネストできる関数コンポーネントをコンポーネント内に定義 import {type ReactNode} from \u0026#34;react\u0026#34; export default function Acompornent(){ // ネストができる関数コンポーネントは必ずしも、このようにコンポーネント内に書いている必要はないと思う。 function Outside({ children }:{ children:ReactNode }){ return \u0026lt;div className=\u0026#34;flex flex-row bg-gray-700 h-[5rem] w-screen top-0 left-0 fixed\u0026#34;\u0026gt; {children} \u0026lt;/div\u0026gt; } return \u0026lt;div\u0026gt; \u0026lt;Outside\u0026gt; \u0026lt;p\u0026gt;This\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;is\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;children.\u0026lt;/p\u0026gt; \u0026lt;/Outside\u0026gt; \u0026lt;Outside1\u0026gt; \u0026lt;p\u0026gt;This\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;is\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;children.\u0026lt;/p\u0026gt; \u0026lt;/Outside1\u0026gt; \u0026lt;/div\u0026gt; } 参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年9月8日) Quick Start – React\nhttps://react.dev/learn (2025年9月9日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/react/nestcomponent/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Vite + React + TypeScript の環境でコンポーネント\u0026quot;内部\u0026quot;になにか要素をネストする方法がわかんなかったので記録するだけ。ただ厳密のこのやり方で正しいかはわかっていないが、ChatGPT-5 が出したやり方がとりあえず動いたので記録することにした。今のところ公式ドキュメントとかで今回出すようなやりかたをしているのはまだ見つけられていない。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVite\u003c/li\u003e\n\u003cli\u003eReact\u003c/li\u003e\n\u003cli\u003eTypeScript\u003c/li\u003e\n\u003cli\u003eTailwind CSS\u003c/li\u003e\n\u003cli\u003ezustand\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ネストの仕方\"\u003eネストの仕方\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eネストできる関数コンポーネントを単体で定義\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-TSX\" data-lang=\"TSX\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e {\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReactNode\u003c/span\u003e} \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOutside1\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e }\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e{ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eReactNode\u003c/span\u003e }){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex flex-row bg-gray-700 h-[5rem] w-screen top-[5rem] left-0 fixed\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eネストできる関数コンポーネントをコンポーネント内に定義\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-TSX\" data-lang=\"TSX\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e {\u003cspan style=\"color:#66d9ef\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReactNode\u003c/span\u003e} \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAcompornent\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// ネストができる関数コンポーネントは必ずしも、このようにコンポーネント内に書いている必要はないと思う。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOutside\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e }\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e{ \u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eReactNode\u003c/span\u003e }){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclassName\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex flex-row bg-gray-700 h-[5rem] w-screen top-0 left-0 fixed\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eOutside\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eThis\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#66d9ef\"\u003eis\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e.\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eOutside\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eOutside1\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003eThis\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#66d9ef\"\u003eis\u003c/span\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\u003cspan style=\"color:#a6e22e\"\u003echildren\u003c/span\u003e.\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eOutside1\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年9月8日)\u003c/li\u003e\n\u003cli\u003eQuick Start – React\u003cbr\u003e\n\u003ca href=\"https://react.dev/learn\"\u003ehttps://react.dev/learn\u003c/a\u003e (2025年9月9日)\u003c/li\u003e\n\u003c/ul\u003e","title":"コンポーネント内にネストができる関数コンポーネント"},{"content":"この記事を作った動機 単に linux カーネルの更新に失敗することに気づいたので、症状と対処法を記録するだけ。ていうか調べたらすでにいっぱい記事あるけど、まあ自分用の記録として。\n環境 System Details Report Report details Date generated: 2025-08-31 20:19:38 Hardware Information: Hardware Model: Dell Inc. XPS 13 9365 Memory: 8.0 GiB Processor: Intel® Core™ i7-8500Y × 4 Graphics: Intel® UHD Graphics 615 (AML-KBL) Disk Capacity: 1.0 TB Software Information: Firmware Version: 2.24.0 OS Name: Arch Linux OS Build: rolling OS Type: 64-bit GNOME Version: 48 Windowing System: Wayland Kernel Version: Linux 6.14.6-arch1-1 症状 カーネルが細分化された結果、従来のカーネルとうまく噛み合わず、更新に失敗する。\nyay # ... # (895/895) パッケージの整合性をチェック [############################] 100% # (895/895) パッケージファイルのロード [############################] 100% # (895/895) ファイルの衝突をチェック [############################] 100% # エラー: 処理を完了できませんでした (衝突しているファイル) # linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad103 がファイルシステムに存在しています # linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad104 がファイルシステムに存在しています # linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad106 がファイルシステムに存在しています # linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad107 がファイルシステムに存在しています # エラーが発生したため、パッケージは更新されませんでした。 # -\u0026gt; Failed to install layer, rolling up to next layer.error:error installing repo packages # ... 対処方法 単に linux と linux-firmware を再インストールする。\nyay -R linux linux-firmware yay -S linux linux-firmware # pacman -R linux linux-firmware # pacman -S linux linux-firmware 参考にしたサイトとか Arch Linux - linux-firmware を分割したから-あすのば。\nhttps://asunoba.blogspot.com/2025/06/arch-linux-linux-firmware.html (2025年8月31日) linux-firmware-nvidia issue with upgrade packages in arch today : r/archlinux\nhttps://www.reddit.com/r/archlinux/comments/1lha3km/linuxfirmwarenvidia_issue_with_upgrade_packages/ (2025年8月31日) Archlinux で linux-firmware-2025061312fe085f-5 は何故手動対応が必要だったのか調べてみた #Linux - Qiita\nhttps://qiita.com/mibushi/items/f70c96220eaab9dcc883 (2025年8月31日) Arch Linux - News: linux-firmware \u0026gt;= 20250613.12fe085f-5 upgrade requires manual intervention\nhttps://archlinux.org/news/linux-firmware-2025061312fe085f-5-upgrade-requires-manual-intervention/ (2025年8月31日) ","permalink":"https://www.nyanmo.info/posts/linux/linuxkernelupdatefailed/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に linux カーネルの更新に失敗することに気づいたので、症状と対処法を記録するだけ。ていうか調べたらすでにいっぱい記事あるけど、まあ自分用の記録として。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"system-details-report\"\u003eSystem Details Report\u003c/h3\u003e\n\u003chr\u003e\n\u003ch4 id=\"report-details\"\u003eReport details\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2025-08-31 20:19:38\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"hardware-information\"\u003eHardware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              Dell Inc. XPS 13 9365\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      8.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Core™ i7-8500Y × 4\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Intel® UHD Graphics 615 (AML-KBL)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               1.0 TB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"software-information\"\u003eSoftware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            2.24.0\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    rolling\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               48\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.14.6-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"症状\"\u003e症状\u003c/h2\u003e\n\u003cp\u003e　カーネルが細分化された結果、従来のカーネルとうまく噛み合わず、更新に失敗する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# (895/895) パッケージの整合性をチェック               [############################] 100%\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# (895/895) パッケージファイルのロード                 [############################] 100%\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# (895/895) ファイルの衝突をチェック                   [############################] 100%\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# エラー: 処理を完了できませんでした (衝突しているファイル)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad103 がファイルシステムに存在しています\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad104 がファイルシステムに存在しています\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad106 がファイルシステムに存在しています\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# linux-firmware-nvidia: /usr/lib/firmware/nvidia/ad107 がファイルシステムに存在しています\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# エラーが発生したため、パッケージは更新されませんでした。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#  -\u0026gt; Failed to install layer, rolling up to next layer.error:error installing repo packages\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"対処方法\"\u003e対処方法\u003c/h2\u003e\n\u003cp\u003e　単に linux と linux-firmware を再インストールする。\u003c/p\u003e","title":"linux カーネルの更新に失敗する"},{"content":"この記事を作った動機 MMD Viewer を作っているときに、地味にあとから効いてきそうなミスをすることを発見したのでそれを記録するだけ。\n問題点 if 文の条件判定の書き方を間違えると、条件判定をする代わりに、判定に使った変数にブール型の結果を代入してしまう。\n間違っている例 問題の部分だけ if(zipName =! null){ // \u0026lt;---- 問題の箇所 // これでは、zipName の中身が true になってしまう。 全体像 // try to find zip file let zipName = null zipName = findZipFile(modelFile) // try to find pmx or pmd file let modelName = null modelName = findPmxAndPmdFileName(modelFile) let fileMap = new Map() if(zipName =! null){ // \u0026lt;---- 問題の箇所 // set modelName is required readZipForModelFile(modelFile,zipName,fileMap) alert(\u0026#34;zip read function on development.\u0026#34;) return } 間違っていない例 問題を修正した部分だけ if(zipName != null){ // \u0026lt;---- 問題の箇所 // この場合は、通常どうり zipName の中身が null でないか判定しているということになり、zipName 自体の中身は判定前と同様に保持される。 全体像 // try to find zip file let zipName = null zipName = findZipFile(modelFile) // try to find pmx or pmd file let modelName = null modelName = findPmxAndPmdFileName(modelFile) let fileMap = new Map() if(zipName != null){ // \u0026lt;---- 問題の箇所 // set modelName is required readZipForModelFile(modelFile,zipName,fileMap) alert(\u0026#34;zip read function on development.\u0026#34;) return } 関連の記事 MMD Viewer 参考にしたサイトとか 気づいたことを書いただけなので特になし。\n","permalink":"https://www.nyanmo.info/posts/webdevelop/jsbranching/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/tools/mmdviewer/\"\u003eMMD Viewer\u003c/a\u003e を作っているときに、地味にあとから効いてきそうなミスをすることを発見したのでそれを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"問題点\"\u003e問題点\u003c/h2\u003e\n\u003cp\u003e　if 文の条件判定の書き方を間違えると、条件判定をする代わりに、判定に使った変数にブール型の結果を代入してしまう。\u003c/p\u003e\n\u003ch3 id=\"間違っている例\"\u003e間違っている例\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e問題の部分だけ\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=!\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){ \u003cspan style=\"color:#75715e\"\u003e// \u0026lt;---- 問題の箇所\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// これでは、zipName の中身が true になってしまう。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e全体像\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// try to find zip file \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindZipFile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// try to find pmx or pmd file\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emodelName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emodelName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindPmxAndPmdFileName\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efileMap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMap\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=!\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){ \u003cspan style=\"color:#75715e\"\u003e// \u0026lt;---- 問題の箇所\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set modelName is required\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ereadZipForModelFile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003efileMap\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ealert\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zip read function on development.\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"間違っていない例\"\u003e間違っていない例\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e問題を修正した部分だけ\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){ \u003cspan style=\"color:#75715e\"\u003e// \u0026lt;---- 問題の箇所\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// この場合は、通常どうり zipName の中身が null でないか判定しているということになり、zipName 自体の中身は判定前と同様に保持される。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e全体像\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// try to find zip file \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindZipFile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// try to find pmx or pmd file\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emodelName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003emodelName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efindPmxAndPmdFileName\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efileMap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMap\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){ \u003cspan style=\"color:#75715e\"\u003e// \u0026lt;---- 問題の箇所\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set modelName is required\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ereadZipForModelFile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emodelFile\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003ezipName\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003efileMap\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ealert\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zip read function on development.\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"関連の記事\"\u003e関連の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/tools/mmdviewer/\"\u003eMMD Viewer\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　気づいたことを書いただけなので特になし。\u003c/p\u003e","title":"JavaScript の条件分岐でわかりにくいミスをした"},{"content":"この記事を作った動機 単に日本語入力環境の改善を考えていたら他にも欲しい機能が出てきたので記録するだけ。\n前回の記事 GNOME OSK 日本語入力 一時的な解決策 Idea List コマンドキー Gnome OSK では、ミニマリスティック過ぎて、Ctrl+S でセーブとかキーボードショートカットが困難である。そこで基本的なキー操作はコマンドとして定義し、汎用性のために、Alt と Ctrl キーも追加するみたいな方向性にしたい。\n以下は追加したい理想のキーについて列挙したものである。\nCtrl+S -\u0026gt; セーブ キー Ctrl+C -\u0026gt; コピー キー Ctrl+V -\u0026gt; 貼り付け キー Ctrl+Z -\u0026gt; 元に戻す キー Ctrl+Y -\u0026gt; やり直す キー Ctrl Alt キーサイズ調整 Gnome OSK のキーサイズは Windows の OSK に比べて小さいように思う。正直かなり押しづらいので、もうちょいキーサイズを好みに合わせて、大きくしたり小さくしたりできるようにしたいと思った。\nサイズ設定のインターフェイスについては、OSK 側には設定用のボタンを追加するか、ブラウザから設定画面にアクセスしてもらうようにするか、OSK に埋め込まれている設定画面があるならそこに項目を追加してみてもいいかなと思ったりしている。\nアプリケーションのサイズ、位置の最適化 Windows では、スクリーンキーボードを使うと、自動的にウィンドウが変形されたり、テキストの位置に合わせて移動したりする。しかし GNOME ではそういう機能は基本現状ないっぽくて、なんかターミナル使ったら OSK の下に出力と入力部分が隠れてしまったりする。なのでこれを多少マシにしたい。\nカーソルの画面上の位置を認識して、ウィンドウの表示位置を調整する Wayland をネイティブにサポートしているアプリでは、ウィンドウサイズやコンテンツの全体についての可視性についても考慮したい。 フローティングモード キーボードが画面を全体的に覆う感じじゃなくて、Windows みたいに、ウィンドウモードみたいなことができるようにしたい。アプリケーション側の最適化が困難な、XWayland 上で動いているアプリとかでも、OSK をまともに動かせるようにしたい。\nOSK 自動隠し機能の無効化 OSK を固定するキーみたいなものを実装し、スクリーンキーボードが自動で隠れると鬱陶しいときに明示的に操作できるようにする。\n参考にしたサイトとか 今のところ特になし。\n","permalink":"https://www.nyanmo.info/posts/linux/gnomeosk/idea/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に日本語入力環境の改善を考えていたら他にも欲しい機能が出てきたので記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"前回の記事\"\u003e前回の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/gnomeosk/workingsample/\"\u003eGNOME OSK 日本語入力 一時的な解決策\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"idea-list\"\u003eIdea List\u003c/h2\u003e\n\u003ch3 id=\"コマンドキー\"\u003eコマンドキー\u003c/h3\u003e\n\u003cp\u003e　Gnome OSK では、ミニマリスティック過ぎて、Ctrl+S でセーブとかキーボードショートカットが困難である。そこで基本的なキー操作はコマンドとして定義し、汎用性のために、Alt と Ctrl キーも追加するみたいな方向性にしたい。\u003c/p\u003e\n\u003cp\u003e　以下は追加したい理想のキーについて列挙したものである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eCtrl+S -\u0026gt; セーブ キー\u003c/li\u003e\n\u003cli\u003eCtrl+C -\u0026gt; コピー キー\u003c/li\u003e\n\u003cli\u003eCtrl+V -\u0026gt; 貼り付け キー\u003c/li\u003e\n\u003cli\u003eCtrl+Z -\u0026gt; 元に戻す キー\u003c/li\u003e\n\u003cli\u003eCtrl+Y -\u0026gt; やり直す キー\u003c/li\u003e\n\u003cli\u003eCtrl\u003c/li\u003e\n\u003cli\u003eAlt\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"キーサイズ調整\"\u003eキーサイズ調整\u003c/h3\u003e\n\u003cp\u003e　Gnome OSK のキーサイズは Windows の OSK に比べて小さいように思う。正直かなり押しづらいので、もうちょいキーサイズを好みに合わせて、大きくしたり小さくしたりできるようにしたいと思った。\u003c/p\u003e\n\u003cp\u003e　サイズ設定のインターフェイスについては、OSK 側には設定用のボタンを追加するか、ブラウザから設定画面にアクセスしてもらうようにするか、OSK に埋め込まれている設定画面があるならそこに項目を追加してみてもいいかなと思ったりしている。\u003c/p\u003e\n\u003ch3 id=\"アプリケーションのサイズ位置の最適化\"\u003eアプリケーションのサイズ、位置の最適化\u003c/h3\u003e\n\u003cp\u003e　Windows では、スクリーンキーボードを使うと、自動的にウィンドウが変形されたり、テキストの位置に合わせて移動したりする。しかし GNOME ではそういう機能は基本現状ないっぽくて、なんかターミナル使ったら OSK の下に出力と入力部分が隠れてしまったりする。なのでこれを多少マシにしたい。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eカーソルの画面上の位置を認識して、ウィンドウの表示位置を調整する\u003c/li\u003e\n\u003cli\u003eWayland をネイティブにサポートしているアプリでは、ウィンドウサイズやコンテンツの全体についての可視性についても考慮したい。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"フローティングモード\"\u003eフローティングモード\u003c/h3\u003e\n\u003cp\u003e　キーボードが画面を全体的に覆う感じじゃなくて、Windows みたいに、ウィンドウモードみたいなことができるようにしたい。アプリケーション側の最適化が困難な、XWayland 上で動いているアプリとかでも、OSK をまともに動かせるようにしたい。\u003c/p\u003e\n\u003ch3 id=\"osk-自動隠し機能の無効化\"\u003eOSK 自動隠し機能の無効化\u003c/h3\u003e\n\u003cp\u003e　OSK を固定するキーみたいなものを実装し、スクリーンキーボードが自動で隠れると鬱陶しいときに明示的に操作できるようにする。\u003c/p\u003e","title":"GNOME OSK extension IdeaList"},{"content":"この記事を作った動機 なんか ChatGPT に色々要望を投げたら、とりあえず動くものが自分で理解してなにか作れる前にできたので、まずはそっちに集中しようかなと思いまとめを作ろうとしてみた。\n結局まともに動かせるようにするために、 ChatGPT とのやり取りで出てきた着想を元に、色々調べて自分で組み合わせたり、コードを書いたりすることになった。\n前回の記事 GNOME OSK 周りの調査 機能の概要 Gnome 拡張機能として、トップバーに全角半角切り替えキーを表示し、押したら、入力モードがアルファベットを直接入力するモードと、日本語をローマ字で入力するモードに切り替えられるようにする。\n主にタッチパネル環境を使って日本語入力するときに、Gnome OSK が US配列しか日本語レイアウトを指定しても表示しないために、補助として作った。\n想定された利用する状況としては、以下のようなものがある。\nGNOME 47 以降 タッチパネル運用 GNOME OSK を利用する Wayland 環境 ちなみに X11 環境である場合は、onboardなどすでにある OSK とかを使ったほうがいいかもしれない。 リポジトリ 基本的な動作 pyhton のキーイベントを送る常駐サーバがある。\n(セキュリティの都合により汎用性はなく \u0026ldquo;`\u0026rdquo; の日本語キーボードで言う全角半角キー相当のキーイベントしか送らない) ボタンが押されたら、localhost 経由で Gnome 拡張機能からリクエストを送る python サーバ 必要なパッケージ python python-uinput python-websockets yay -S python python-uinput python-websockets 最新版 最初は、ChatGPT に書いてもらったコードを動かしていたが、次第に HTTP 通信だと限界があることがわかり、 WebSocket へ移行した過程で、結局自分でネットで python のsockets の公式ライブラリなり、色んなサイトを漁ってコードを書くことになった。ChatGPT が書いたコードについては、uinput 以外は、結局いろんなサイトからの試しながら切り貼りといった感じである。\n#!/usr/bin/env python3 import uinput import asyncio from websockets.asyncio.server import serve from websockets.exceptions import ConnectionClosedOK device = uinput.Device([uinput.KEY_GRAVE]) async def hello(websocket): while True: try: message = await websocket.recv() if(message == \u0026#34;enter\u0026#34;): print(\u0026#34;working\u0026#34;) device.emit_click(uinput.KEY_GRAVE) print(f\u0026#34;\u0026lt;\u0026lt;\u0026lt; {message}\u0026#34;) except ConnectionClosedOK: break async def main(): async with serve(hello, \u0026#34;localhost\u0026#34;, 50096) as server: await server.serve_forever() if __name__ == \u0026#34;__main__\u0026#34;: asyncio.run(main()) systemd service テンプレート 有効化 sudo systemctl enable --now ZenkakuHankakuKeyd.service ZenkakuHankakuKeyd.service(まだ未完成) [Unit] Description=ZenkakuHankaku-key extension backend [Service] Type=simple User=root ExecStart=/path/to/backend.py Restart=on-abort [Install] WantedBy=multi-user.target 配置 # arch linux /etc/systemd/system/ZenkakuHankakuKeyd.service 細かいこと 最新版を書く過程で躓いたこと socket が勝手に閉じないようにする Part 1 - Send \u0026amp; receive - websockets 15.0.1 documentationによれば、単純に While とかで無限ループしていればいいとのこと。\nasync def handler(websocket): while True: try: message = await websocket.recv() except ConnectionClosedOK: break print(message) 色々試した形跡 main.py 以下は ChatGPT-5 のモデルが吐き出したコードである。\n#!/usr/bin/env python3 from flask import Flask import uinput app = Flask(__name__) device = uinput.Device([uinput.KEY_GRAVE]) @app.route(\u0026#34;/trigger\u0026#34;) def trigger(): device.emit_click(uinput.KEY_GRAVE) # press+release return \u0026#34;OK\\n\u0026#34; if __name__ == \u0026#34;__main__\u0026#34;: # listen only on localhost for safety app.run(host=\u0026#34;127.0.0.1\u0026#34;, port=50096) このままでも、とりあえずhttp://127.0.0.1:PORT/triggerに wget とかで HTTP リクエストを送ると、キーイベントが OS 側に送られ、バックエンドとしては動作したが、以下のようにエラーが出てしまうので python - Flask at first run: Do not use the development server in a production environment - Stack Overflow を参考に waitress を使うようにすることにした。\n警告メッセージが出る例 sudo ./main.py # * Serving Flask app \u0026#39;main\u0026#39; # * Debug mode: off # WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead. # * Running on http://127.0.0.1:50096 # Press CTRL+C to quit # 127.0.0.1 - - [21/Aug/2025 18:46:34] \u0026#34;GET /trigger HTTP/1.1\u0026#34; 200 - main.py (修正版) 以下は自分で修正したコードである。と入ってもシバンを書き換えて、参考資料を元に waitress を使うようにしただけであり、全然私は慣れてなかったり知らないものも使われてたりする。flask とか waitress はこの記事を書いた時点では全然使ったことないし。これでとりあえず警告は出なくなった。\n#!/bin/python from flask import Flask import uinput app = Flask(__name__) device = uinput.Device([uinput.KEY_GRAVE]) @app.route(\u0026#34;/trigger\u0026#34;) def trigger(): device.emit_click(uinput.KEY_GRAVE) # press+release return \u0026#34;OK\\n\u0026#34; if __name__ == \u0026#34;__main__\u0026#34;: from waitress import serve # listen only on localhost for safety serve(app, host=\u0026#34;127.0.0.1\u0026#34;, port=50096) 試行錯誤の過程で不要になったパッケージ WebSocket を使う案に移行したため、以下のパッケージは使わなくなった。\npython-flask python-waitress Gnome 拡張機能側 ブラウザで標準の API は使えない fetch API とかは使えないので、http とかネットワーク関連でなにかしたかったら、libsoup を使う必要がある。fetch API とか使うおうとすると、以下のようなエラーとなる。\nsudo journalctl /usr/bin/gnome-shell # ... # Stack trace: # _sendBacktick@file:///home/username/.local/share/gnome-shell/extensions/ZenkakuHankaku-Key@www.nyanmo.info/extension.js:32:23 # _init/\u0026lt;@file:///home/username/.local/share/gnome-shell/extensions/ZenkakuHankaku-Key@www.nyanmo.info/extension.js:55:13 # activate@resource:///org/gnome/shell/ui/popupMenu.js:193:14 # _init/\u0026lt;@resource:///org/gnome/shell/ui/popupMenu.js:110:24 # @resource:///org/gnome/shell/ui/init.js:21:20 # # 8月 21 19:48:05 hostname gnome-shell[93119]: Failed to claim accelerometer: タイムアウトしました # 8月 21 19:48:49 hostname gnome-shell[93119]: ReferenceError: fetch is not defined # ... エラーで拡張機能がそもそも起動しないときのデバッグ方法 alt + F2 を押す lg を実行する Extention タブを開く エラーを表示する 拡張機能を認識させたり変更を反映する 単純には、ログアウトしてログインしなおしたり、コマンドを実行のところで、restart を実行したりすることで、とにかく Gnome-Shell のユーザセッションを再起動しないといけない模様である。\nwayland 環境だと restart できないらしい 画像を使う方法がマゾ 最終的に以下のように、パスを割り出す方法でとりあえず動くようになった。\njs/misc/dbusUtils.js · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/misc/dbusUtils.js (2025年8月22日) GLib – 2.0\nhttps://docs.gtk.org/glib/?q= (2025年8月22日) GLib – 2.0\nhttps://docs.gtk.org/glib/?q=get (2025年8月22日) GLib.get_home_dir\nhttps://docs.gtk.org/glib/func.get_home_dir.html (2025年8月22日) // /home/username までわかる let homedir = GLib.get_home_dir() + \u0026#34;/\u0026#34; // \u0026#34;ZenkakuHankaku-Key@www.nyanmo.info\u0026#34; 作った拡張機能名に置き換える let extdir = homedir + \u0026#34;.local/share/gnome-shell/extensions/ZenkakuHankaku-Key@www.nyanmo.info/\u0026#34; // 拡張機能のフォルダを起点として、画像を指定する let iconPath = extdir + \u0026#34;imgs/targetImage.png\u0026#34; // やっと画像を読み込んで表示できる let gicon = Gio.icon_new_for_string(`${iconPath}`); this.add_child(new St.Icon({ gicon: gicon, style_class: \u0026#39;system-status-icon switchButton\u0026#39;, })); 追記 2026/9/22 最近、Gnome 50 くらいになってから、半角キーを送信して Fcitx5 上の Mozc 上では全角半角の切り替えが動作しているものの、Gnome OSK 上では効果がなくアルファベットがどうやっても入力されてしまうという症状を確認した。最近の Gnome OSK は Fctix を経由していない可能性があり調査が必要なことが分かった。\n続き GNOME OSK extension IdeaList 参考にしたサイトとか フリースペース ChatGPT\nhttps://chatgpt.com/ (2025年8月21日) コーディング関連で調べたこと python - Flask at first run: Do not use the development server in a production environment - Stack Overflow\nhttps://stackoverflow.com/questions/51025893/flask-at-first-run-do-not-use-the-development-server-in-a-production-environmen (2025年8月21日) Getting Started | GNOME JavaScript\nhttps://gjs.guide/extensions/development/creating.html (2025年8月21日) soup server example of gjs at github - server stops listening after 2 seconds - Stack Overflow\nhttps://stackoverflow.com/questions/77733763/soup-server-example-of-gjs-at-github-server-stops-listening-after-2-seconds (2025年8月21日) Color Picker - GNOME Shell 拡張機能\nhttps://extensions.gnome.org/extension/3396/color-picker/ (2025年8月21日) tuberry/color-picker: GNOME Shell extension to pick colors on the desktop\nhttps://github.com/tuberry/color-picker (2025年8月21日) js/ui/panelMenu.js · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/ui/panelMenu.js (2025年8月21日) Basics — Gjs/GTK+ 3 Tutorial 0 documentation\nhttps://gjs-tutorial.readthedocs.io/en/latest/basics.html (2025年8月21日) gnome shell - How to get more information about \u0026ldquo;Error loading extension\u0026rdquo;? - Ask Ubuntu\nhttps://askubuntu.com/questions/1006499/how-to-get-more-information-about-error-loading-extension (2025年8月21日) St.Widget (PanelMenu.Button) のシグナルの参考になるところ Clutter.Actor - Classes - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/classes/Actor.html#signal-details (2025年8月21日) Clutter.Actor - Classes - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/classes/Actor.html#Clutter.Actor.signals.button_press_event (2025年8月21日) Clutter.Actor - Classes - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/classes/Actor.html#Clutter.Actor.signals.touch_event (2025年8月22日) Clutter.Event - Unions - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/classes/Event.html#Clutter.Event (2025年8月22日) Clutter.TouchEvent - Structures - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/classes/TouchEvent.html#Clutter.TouchEvent (2025年8月22日) EventType · 検索 · GitLab\nhttps://gitlab.gnome.org/search?search=EventType\u0026amp;nav_source=navbar\u0026amp;project_id=546\u0026amp;group_id=8\u0026amp;search_code=true\u0026amp;repository_ref=main (2025年8月22日) js/gdm/loginDialog.js · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/gdm/loginDialog.js (2025年8月22日) Clutter 10 / EventType — DevDocs\nhttps://gjs-docs.gnome.org/clutter10~10/clutter.eventtype (2025年8月22日) Enums - Clutter 1.0\nhttps://lazka.github.io/pgi-docs/Clutter-1.0/enums.html#Clutter.EventType.TOUCH_BEGIN (2025年8月22日) GJS と GNOME 拡張機能における画像などのあり方 gio - Custom Icon for Gnome Shell Extension in Top Panel not visible - Stack Overflow\nhttps://stackoverflow.com/questions/61243243/custom-icon-for-gnome-shell-extension-in-top-panel-not-visible (2025年8月22日) //Gio · 検索 · GitLab\nhttps://gitlab.gnome.org/search?search=%2F%2FGio\u0026amp;nav_source=navbar\u0026amp;project_id=546\u0026amp;group_id=8\u0026amp;search_code=true\u0026amp;repository_ref=main (2025年8月22日) Gio – 2.0\nhttps://docs.gtk.org/gio/index.html (2025年8月22日) Gio – 2.0\nhttps://docs.gtk.org/gio/?q=icon_new_for_string (2025年8月22日) Gio.Icon.new_for_string\nhttps://docs.gtk.org/gio/type_func.Icon.new_for_string.html (2025年8月22日) Gio.BytesIcon.new\nhttps://docs.gtk.org/gio/ctor.BytesIcon.new.html (2025年8月22日) 拡張機能までのパスの解決方法 (今のところ不明) Extension (ESModule) | GNOME JavaScript\nhttps://gjs.guide/extensions/topics/extension.html (2025年8月22日) tests/unit/extensionUtils.js · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/tests/unit/extensionUtils.js (2025年8月22日) GLib.get_home_dir\nhttps://docs.gtk.org/glib/func.get_home_dir.html (2025年8月22日) GLib – 2.0\nhttps://docs.gtk.org/glib/?q=get (2025年8月22日) js/misc/dbusUtils.js · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/js/misc/dbusUtils.js (2025年8月22日) GJS における HTTP や WebSocket 事情 (libsoup) SoupSession: libsoup Reference Manual\nhttps://libsoup.gnome.org/libsoup-2.4/SoupSession.html#soup-session-abort (2025年8月21日) examples/websocket-client.js · master · GNOME / gjs · GitLab\nhttps://gitlab.gnome.org/GNOME/gjs/-/blob/master/examples/websocket-client.js (2025年8月21日) gjs/examples/http-server.js at master · GNOME/gjs\nhttps://github.com/GNOME/gjs/blob/master/examples/http-server.js (2025年8月21日) gjs/examples/http-client.js at master · GNOME/gjs\nhttps://github.com/GNOME/gjs/blob/master/examples/http-client.js (2025年8月21日) python 関連 websockets 15.0.1 documentation\nhttps://websockets.readthedocs.io/en/stable/ (2025年8月21日) Part 1 - Send \u0026amp; receive - websockets 15.0.1 documentation\nhttps://websockets.readthedocs.io/en/stable/intro/tutorial1.html (2025年8月21日) python - How can I stop my websocket connection from closing? - Stack Overflow\nhttps://stackoverflow.com/questions/67309060/how-can-i-stop-my-websocket-connection-from-closing (2025年8月21日) JS websocket WebSocket\nhttps://developer.mozilla.org/en-US/docs/Web/API/WebSocket (2025年8月21日) ","permalink":"https://www.nyanmo.info/posts/linux/gnomeosk/workingsample/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003eなんか ChatGPT に色々要望を投げたら、とりあえず動くものが自分で理解してなにか作れる前にできたので、まずはそっちに集中しようかなと思いまとめを作ろうとしてみた。\u003c/del\u003e\u003c/p\u003e\n\u003cp\u003e　結局まともに動かせるようにするために、 ChatGPT とのやり取りで出てきた着想を元に、色々調べて自分で組み合わせたり、コードを書いたりすることになった。\u003c/p\u003e\n\u003ch2 id=\"前回の記事\"\u003e前回の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/gnomeosk/search/\"\u003eGNOME OSK 周りの調査\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"機能の概要\"\u003e機能の概要\u003c/h2\u003e\n\u003cp\u003e　Gnome 拡張機能として、トップバーに全角半角切り替えキーを表示し、押したら、入力モードがアルファベットを直接入力するモードと、日本語をローマ字で入力するモードに切り替えられるようにする。\u003c/p\u003e\n\u003cp\u003e　主にタッチパネル環境を使って日本語入力するときに、Gnome OSK が US配列しか日本語レイアウトを指定しても表示しないために、補助として作った。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/gnomeOSK/workingSample/sample%e7%94%bb%e5%83%8f.png#center\"\n         alt=\"sample画像\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　想定された利用する状況としては、以下のようなものがある。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eGNOME 47 以降\u003c/li\u003e\n\u003cli\u003eタッチパネル運用\u003c/li\u003e\n\u003cli\u003eGNOME OSK を利用する\u003c/li\u003e\n\u003cli\u003eWayland 環境\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　ちなみに X11 環境である場合は、\u003ca href=\"https://github.com/dr-ni/onboard\"\u003eonboard\u003c/a\u003eなどすでにある OSK とかを使ったほうがいいかもしれない。\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/dr-ni/onboard\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"リポジトリ\"\u003eリポジトリ\u003c/h2\u003e\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/hello30190f/ZenkakuHankaku-Key\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"基本的な動作\"\u003e基本的な動作\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003epyhton のキーイベントを送る常駐サーバがある。\u003cbr\u003e\n　(セキュリティの都合により汎用性はなく \u0026ldquo;`\u0026rdquo; の日本語キーボードで言う全角半角キー相当のキーイベントしか送らない)\u003c/li\u003e\n\u003cli\u003eボタンが押されたら、localhost 経由で Gnome 拡張機能からリクエストを送る\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"python-サーバ\"\u003epython サーバ\u003c/h2\u003e\n\u003ch3 id=\"必要なパッケージ\"\u003e必要なパッケージ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003epython\u003c/li\u003e\n\u003cli\u003epython-uinput\u003c/li\u003e\n\u003cli\u003epython-websockets\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S python python-uinput python-websockets\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"最新版\"\u003e最新版\u003c/h3\u003e\n\u003cp\u003e　最初は、ChatGPT に書いてもらったコードを動かしていたが、次第に HTTP 通信だと限界があることがわかり、 WebSocket へ移行した過程で、結局自分でネットで  python の\u003ccode\u003esockets\u003c/code\u003e の公式ライブラリなり、色んなサイトを漁ってコードを書くことになった。ChatGPT が書いたコードについては、uinput 以外は、結局いろんなサイトからの試しながら切り貼りといった感じである。\u003c/p\u003e","title":"GNOME OSK 日本語入力 一時的な解決策"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 単に調べて分かったことを記録するだけ。\nIntel Boot Guard Intel Boot Guard によって主に、Broadwell(5th) 以降のCPUでそれが有効な場合、何かしらの方法でCPUに内蔵されたキーが分からない限り、自由に作ったファームウェアを動かせない。Xbox 360 のセキュリティと似ている気がする。\nHow the Xbox 360 Hypervisor Security was Defeated | MVG - YouTube\nhttps://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s (2025年8月18日) 参考にしたサイトとか Intel Boot Guard について coreboot FAQ — coreboot 25.06-129-g5db8bf0cfa documentation\nhttps://doc.coreboot.org/getting_started/faq.html#can-coreboot-be-ported-to-this-board (2025年8月18日) BIOSがIntel Boot Guardで適切に保護されていないため改変の恐れ - Lenovo Support KW\nhttps://support.lenovo.com/kw/ja/solutions/ps500187-bios-modules-unprotected-by-intel-boot-guard-vulnerable-to-physical-attack (2025年8月18日) mjg59 | Intel Boot Guard, Coreboot and user freedom\nhttps://mjg59.dreamwidth.org/33981.html (2025年8月18日) Boot Guard TOCTOU Vulnerability Mitigation · tianocore/tianocore.github.io Wiki · GitHub\nhttps://github.com/tianocore/tianocore.github.io/wiki/Boot-Guard-TOCTOU-Vulnerability-Mitigation (2025年8月18日) Hardening Intel® Trusted eXecution Technology and Intel® Boot Guard\nhttps://www.intel.co.jp/content/www/jp/ja/content-details/824411/hardening-intel-trusted-execution-technology-and-intel-boot-guard.html (2025年8月18日) Libreboot – Disabling Intel Boot Guard on MEv11 for Libreboot installation\nhttps://libreboot.org/docs/install/deguard.html (2025年8月18日) Intel’s boot guard is a doddle to defeat\nhttps://fudzilla.com/news/pc-hardware/48676-intel-s-boot-guard-is-a-doddle-to-defeat (2025年8月18日) How the Xbox 360 Hypervisor Security was Defeated | MVG - YouTube\nhttps://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s (2025年8月18日) フリースペース intel/FSP at legacy\nhttps://github.com/intel/FSP/tree/legacy (2025年8月18日) intel/FSP: Intel(R) Firmware Support Package (FSP)\nhttps://github.com/intel/FSP (2025年8月18日) ","permalink":"https://www.nyanmo.info/posts/coreboot/search/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に調べて分かったことを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"intel-boot-guard\"\u003eIntel Boot Guard\u003c/h2\u003e\n\u003cp\u003e　Intel Boot Guard によって主に、Broadwell(5th) 以降のCPUでそれが有効な場合、何かしらの方法でCPUに内蔵されたキーが分からない限り、自由に作ったファームウェアを動かせない。Xbox 360 のセキュリティと似ている気がする。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eHow the Xbox 360 Hypervisor Security was Defeated | MVG - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s\"\u003ehttps://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s\u003c/a\u003e (2025年8月18日)\n\u003cdiv style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\"\u003e\n\t\t\t\u003ciframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https://www.youtube.com/embed/Vq1lxeg_gNs?autoplay=0\u0026amp;controls=1\u0026amp;end=0\u0026amp;loop=0\u0026amp;mute=0\u0026amp;start=228\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\u003e\u003c/iframe\u003e\n\t\t\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003ch3 id=\"intel-boot-guard-について\"\u003eIntel Boot Guard について\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ecoreboot FAQ — coreboot 25.06-129-g5db8bf0cfa documentation\u003cbr\u003e\n\u003ca href=\"https://doc.coreboot.org/getting_started/faq.html#can-coreboot-be-ported-to-this-board\"\u003ehttps://doc.coreboot.org/getting_started/faq.html#can-coreboot-be-ported-to-this-board\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eBIOSがIntel Boot Guardで適切に保護されていないため改変の恐れ - Lenovo Support KW\u003cbr\u003e\n\u003ca href=\"https://support.lenovo.com/kw/ja/solutions/ps500187-bios-modules-unprotected-by-intel-boot-guard-vulnerable-to-physical-attack\"\u003ehttps://support.lenovo.com/kw/ja/solutions/ps500187-bios-modules-unprotected-by-intel-boot-guard-vulnerable-to-physical-attack\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003emjg59 | Intel Boot Guard, Coreboot and user freedom\u003cbr\u003e\n\u003ca href=\"https://mjg59.dreamwidth.org/33981.html\"\u003ehttps://mjg59.dreamwidth.org/33981.html\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eBoot Guard TOCTOU Vulnerability Mitigation · tianocore/tianocore.github.io Wiki · GitHub\u003cbr\u003e\n\u003ca href=\"https://github.com/tianocore/tianocore.github.io/wiki/Boot-Guard-TOCTOU-Vulnerability-Mitigation\"\u003ehttps://github.com/tianocore/tianocore.github.io/wiki/Boot-Guard-TOCTOU-Vulnerability-Mitigation\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eHardening Intel® Trusted eXecution Technology and Intel® Boot Guard\u003cbr\u003e\n\u003ca href=\"https://www.intel.co.jp/content/www/jp/ja/content-details/824411/hardening-intel-trusted-execution-technology-and-intel-boot-guard.html\"\u003ehttps://www.intel.co.jp/content/www/jp/ja/content-details/824411/hardening-intel-trusted-execution-technology-and-intel-boot-guard.html\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eLibreboot – Disabling Intel Boot Guard on MEv11 for Libreboot installation\u003cbr\u003e\n\u003ca href=\"https://libreboot.org/docs/install/deguard.html\"\u003ehttps://libreboot.org/docs/install/deguard.html\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eIntel’s boot guard is a doddle to defeat\u003cbr\u003e\n\u003ca href=\"https://fudzilla.com/news/pc-hardware/48676-intel-s-boot-guard-is-a-doddle-to-defeat\"\u003ehttps://fudzilla.com/news/pc-hardware/48676-intel-s-boot-guard-is-a-doddle-to-defeat\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eHow the Xbox 360 Hypervisor Security was Defeated | MVG - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s\"\u003ehttps://www.youtube.com/watch?v=Vq1lxeg_gNs\u0026amp;t=228s\u003c/a\u003e (2025年8月18日)\n\u003cdiv style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\"\u003e\n\t\t\t\u003ciframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https://www.youtube.com/embed/Vq1lxeg_gNs?autoplay=0\u0026amp;controls=1\u0026amp;end=0\u0026amp;loop=0\u0026amp;mute=0\u0026amp;start=228\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\u003e\u003c/iframe\u003e\n\t\t\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"フリースペース\"\u003eフリースペース\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eintel/FSP at legacy\u003cbr\u003e\n\u003ca href=\"https://github.com/intel/FSP/tree/legacy\"\u003ehttps://github.com/intel/FSP/tree/legacy\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003cli\u003eintel/FSP: Intel(R) Firmware Support Package (FSP)\u003cbr\u003e\n\u003ca href=\"https://github.com/intel/FSP\"\u003ehttps://github.com/intel/FSP\u003c/a\u003e (2025年8月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"coreboot の調査"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） このツールを作りたい理由 wallpaper engine みたいなことを、Linux 環境の GNOME、wayland 上でやりたいと思った。githubにコードやコンパイル済みのバイナリは上げておいて、いろんなlinuxディストリビューションで無料で使えるものがあるといいなと思った。\nどう実装したいか？ GJS を使って、GNOME 拡張機能として実装したい。そもそもできるのか、具体的にどうするのかは現時点ではまだ見通しが立っていない。\n参考にしたサイトとか 現時点では特になし。\n","permalink":"https://www.nyanmo.info/tools/videowallpaperforgnome/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"このツールを作りたい理由\"\u003eこのツールを作りたい理由\u003c/h2\u003e\n\u003cp\u003e　wallpaper engine みたいなことを、Linux 環境の GNOME、wayland 上でやりたいと思った。githubにコードやコンパイル済みのバイナリは上げておいて、いろんなlinuxディストリビューションで無料で使えるものがあるといいなと思った。\u003c/p\u003e\n\u003ch2 id=\"どう実装したいか\"\u003eどう実装したいか？\u003c/h2\u003e\n\u003cp\u003e　GJS を使って、GNOME 拡張機能として実装したい。そもそもできるのか、具体的にどうするのかは現時点ではまだ見通しが立っていない。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　現時点では特になし。\u003c/p\u003e","title":"動画壁紙 GNOME"},{"content":"この記事を作った動機 なんか最近 VLC をただパッケージマネージャでインストールするだけでは、デコードやら何やら色々必要なプラグインが欠けた状態になるらしく、まともに動画を再生できないということがあったので記録するだけ。\nうまく動画が再生できないことがわかったあと、pacman を使うことで、plugin として存在していて、まだインストールしていないパッケージがあることを理解した。それで欠けていそうなパッケージをインストールしてみると問題が解決したので、そのことを忘れないうちに残しておきたい。\npacman -Qi vlc # Name : vlc # Version : 3.0.21-27 # Description : Free and open source cross-platform multimedia player and framework # Architecture : x86_64 # URL : https://www.videolan.org/vlc/ # Licenses : GPL-2.0-or-later LGPL-2.1-or-later # Groups : None # Provides : None # Depends On : bash hicolor-icon-theme vlc-gui-qt=3.0.21 # Optional Deps : vlc-gui-ncurses: for ncurses TUI # vlc-gui-skins2: for Skins2 GUI # vlc-plugins-all: for all plugins # vlc-plugins-extra: for extra plugins # vlc-plugins-visualization: for visualization plugins # vlc-plugin-aalib: for ASCII art video output support # vlc-plugin-aom: for AOM AV1 codec support # vlc-plugin-aribb24: for ARIB STD-24 codec and demux support # vlc-plugin-aribb25: for ARIB STD-25 stream filter support # vlc-plugin-ass: for SSA/ASS subtitle codec support # vlc-plugin-avahi: for mDNS/DNS-SD services discovery support # vlc-plugin-bluray: for Blu-ray access support # vlc-plugin-caca: for color ASCII art video output support # vlc-plugin-cddb: for CDDB access support # vlc-plugin-chromecast: for Chromecast stream out support # vlc-plugin-dca: for DTS Coherent Acoustics codec support # vlc-plugin-dvb: for DVB access, mux and demux support # vlc-plugin-dvd: for DVD access support # vlc-plugin-ffmpeg: for FFMPEG based access, codec, demux, packetizer, VDPAU, video chroma and video filter support # vlc-plugin-firewire: for FireWire device access support # vlc-plugin-fluidsynth: for FluidSynth codec support # vlc-plugin-freetype: for subtitle and on screen display text rendering support # vlc-plugin-gme: for Game Music Emulation demux support # vlc-plugin-gstreamer: for GStreamer codec support # vlc-plugin-jack: for JACK access and audio output support # vlc-plugin-kate: for kate karaoke codec support # vlc-plugin-kwallet: for kwallet keystore support # vlc-plugin-libsecret: for libsecret keystore support # vlc-plugin-lirc: for infrared remote control support # vlc-plugin-live555: for RTP/RTSP stream access support # vlc-plugin-mad: for MPEG Audio Decoder audio filter support # vlc-plugin-matroska: for Matroska demux support # vlc-plugin-mdns: for mDNS services discovery support # vlc-plugin-modplug: for MOD demux support # vlc-plugin-mpeg2: for MPEG2 codec support # vlc-plugin-mtp: for MTP device access and discovery support # vlc-plugin-musepack: for MusePack demux support # vlc-plugin-nfs: for NFS access support # vlc-plugin-notify: for notification support # vlc-plugin-quicksync: for Intel QuickSync H264/H262 codec support # vlc-plugin-samplerate: for samplerate audio filter support # vlc-plugin-sdl: for SDL codec support # vlc-plugin-sftp: for SFTP access support # vlc-plugin-smb: for SMB access support # vlc-plugin-soxr: for SoX Resampler audio filter support # vlc-plugin-srt: for SRT subtitle file support # vlc-plugin-svg: for SVG codec and text renderer support # vlc-plugin-udev: for ALSA services discovery support using udev # vlc-plugin-upnp: for UPnP services discovery support # vlc-plugin-x264: for H264/AVC encoding support # vlc-plugin-x265: for H265/HEVC encoding support # vlc-plugin-zvbi: for VBI access (also over V4L2) and codec support # Required By : None # Optional For : None # Conflicts With : vlc-plugin # Replaces : vlc-plugin # Installed Size : 40.06 MiB # Packager : David Runge \u0026lt;dvzrv@archlinux.org\u0026gt; # Build Date : Thu Jul 24 05:35:16 2025 # Install Date : Tue Aug 12 20:18:56 2025 # Install Reason : Explicitly installed # Install Script : No # Validated By : Signature このようにプラグインなどとして各種機能がVLCにおいて分割されるようになったのが、最近なのかは知らないが、linux ファームウェアも色々なんか分割してたりするので、VLC も肥大化かメンテナンスのために、なんかあったのかなと思ったり、元からだけど、今までは問題が出なかっただけなのかなと思ったり。\n必要なパッケージ vlc vlc-plugins-all yay -Syyu vlc vlc-plugins-all # pacman -Syyu vlc vlc-plugins-all 関係のありそうなページ yay コマンドのインストール 参考にしたサイトとか Arch Linux - vlc-plugins-all 3.0.21-27 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vlc-plugins-all/ (2025年8月12日) Arch Linux - vlc 3.0.21-27 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/vlc/ (2025年8月12日) ","permalink":"https://www.nyanmo.info/posts/linux/vlc/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか最近 VLC をただパッケージマネージャでインストールするだけでは、デコードやら何やら色々必要なプラグインが欠けた状態になるらしく、まともに動画を再生できないということがあったので記録するだけ。\u003c/p\u003e\n\u003cp\u003e　うまく動画が再生できないことがわかったあと、pacman を使うことで、plugin として存在していて、まだインストールしていないパッケージがあることを理解した。それで欠けていそうなパッケージをインストールしてみると問題が解決したので、そのことを忘れないうちに残しておきたい。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epacman -Qi vlc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Name            : vlc\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Version         : 3.0.21-27\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Description     : Free and open source cross-platform multimedia player and framework\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Architecture    : x86_64\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# URL             : https://www.videolan.org/vlc/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Licenses        : GPL-2.0-or-later  LGPL-2.1-or-later\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Groups          : None\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Provides        : None\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Depends On      : bash  hicolor-icon-theme  vlc-gui-qt=3.0.21\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Optional Deps   : vlc-gui-ncurses: for ncurses TUI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-gui-skins2: for Skins2 GUI\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugins-all: for all plugins\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugins-extra: for extra plugins\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugins-visualization: for visualization plugins\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-aalib: for ASCII art video output support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-aom: for AOM AV1 codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-aribb24: for ARIB STD-24 codec and demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-aribb25: for ARIB STD-25 stream filter support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-ass: for SSA/ASS subtitle codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-avahi: for mDNS/DNS-SD services discovery support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-bluray: for Blu-ray access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-caca: for color ASCII art video output support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-cddb: for CDDB access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-chromecast: for Chromecast stream out support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-dca: for DTS Coherent Acoustics codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-dvb: for DVB access, mux and demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-dvd: for DVD access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-ffmpeg: for FFMPEG based access, codec, demux, packetizer, VDPAU, video chroma and video filter support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-firewire: for FireWire device access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-fluidsynth: for FluidSynth codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-freetype: for subtitle and on screen display text rendering support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-gme: for Game Music Emulation demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-gstreamer: for GStreamer codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-jack: for JACK access and audio output support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-kate: for kate karaoke codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-kwallet: for kwallet keystore support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-libsecret: for libsecret keystore support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-lirc: for infrared remote control support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-live555: for RTP/RTSP stream access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-mad: for MPEG Audio Decoder audio filter support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-matroska: for Matroska demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-mdns: for mDNS services discovery support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-modplug: for MOD demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-mpeg2: for MPEG2 codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-mtp: for MTP device access and discovery support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-musepack: for MusePack demux support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-nfs: for NFS access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-notify: for notification support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-quicksync: for Intel QuickSync H264/H262 codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-samplerate: for samplerate audio filter support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-sdl: for SDL codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-sftp: for SFTP access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-smb: for SMB access support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-soxr: for SoX Resampler audio filter support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-srt: for SRT subtitle file support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-svg: for SVG codec and text renderer support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-udev: for ALSA services discovery support using udev\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-upnp: for UPnP services discovery support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-x264: for H264/AVC encoding support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-x265: for H265/HEVC encoding support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#                   vlc-plugin-zvbi: for VBI access (also over V4L2) and codec support\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Required By     : None\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Optional For    : None\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Conflicts With  : vlc-plugin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Replaces        : vlc-plugin\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Installed Size  : 40.06 MiB\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Packager        : David Runge \u0026lt;dvzrv@archlinux.org\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Build Date      : Thu Jul 24 05:35:16 2025\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Install Date    : Tue Aug 12 20:18:56 2025\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Install Reason  : Explicitly installed\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Install Script  : No\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Validated By    : Signature\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　このようにプラグインなどとして各種機能がVLCにおいて分割されるようになったのが、最近なのかは知らないが、linux ファームウェアも色々なんか分割してたりするので、VLC も肥大化かメンテナンスのために、なんかあったのかなと思ったり、元からだけど、今までは問題が出なかっただけなのかなと思ったり。\u003c/p\u003e","title":"VLC 動画を再生できないことがある"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 GNOME には、スクリーンキーボードがデフォルトで実装されているが、日本語レイアウトが存在しないようで、全角半角切り替えキーさえ出てこないという非常に不便な挙動をしているということがあった。そこで、自分で何かしらしてどうにか全角半角キーを追加したいと思った次第。\n考えていること 拡張機能として実装する Gnome-shell 自体を変更してしまう OSK自体にボタンを埋め込まずに、Fcitx5のIME の横にパネルメニューボタンとして、切り替えボタンを表示する わかったこと data/osk-layouts/配下に日本語レイアウトが存在しない us.json としてアメリカ配列などについては存在するが、jp.json や ja.json みたいなのは存在していない。\nja.json を us.json などからコピーして作るとき 全角半角切り替えキーは、action として記述できる模様。ただ、GJS側でどうやってアクションを処理すればいいのか不明。\nus.json の action 例 ... { \u0026#34;action\u0026#34;: \u0026#34;emoji\u0026#34;, \u0026#34;iconName\u0026#34;: \u0026#34;osk-emoji-picker-symbolic\u0026#34; }, { \u0026#34;action\u0026#34;: \u0026#34;languageMenu\u0026#34;, \u0026#34;iconName\u0026#34;: \u0026#34;osk-layout-symbolic\u0026#34; }, { \u0026#34;action\u0026#34;: \u0026#34;hide\u0026#34;, \u0026#34;iconName\u0026#34;: \u0026#34;osk-hide-symbolic\u0026#34; } ... jp.json のイメージ ... { \u0026#34;action\u0026#34;: \u0026#34;zenkakuHankaku\u0026#34;, \u0026#34;iconName\u0026#34;: \u0026#34;osk-zenkakuHankaku-symbolic\u0026#34; }, ... GJS のアクションの実装方法が不明 調査が必要なことがわかる。fcitx5 を私は使っているがそれについても GJS からどうできるのか調べる必要がありそうである。DBusあたりが重要なのかな？とはなんとなく思っているところである。\ndata/gnome-shell-osk-layouts.gresource.xml のイメージ ただキーボードレイアウトとactionの実装をするだけでなく、リソースとして以下のように登録してレイアウトを認識させる必要がありそう。\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;gresources\u0026gt; \u0026lt;gresource prefix=\u0026#34;/org/gnome/shell/osk-layouts\u0026#34;\u0026gt; \u0026lt;file\u0026gt;am.json\u0026lt;/file\u0026gt; ... \u0026lt;file\u0026gt;jp.json\u0026lt;/file\u0026gt; ... \u0026lt;file\u0026gt;emoji.json\u0026lt;/file\u0026gt; \u0026lt;/gresource\u0026gt; \u0026lt;/gresources\u0026gt; 拡張機能からどうやってリソースファイルとかを弄れるのか不明 もしかしたら拡張機能側からは、data/gnome-shell-osk-layouts.gresource.xml とか、data/osk-layouts/ 配下をいじって動作を変更したりは厳しいのかもしれない。その時は、OSKに言語関係なく強引に、全角半角キーを表示する実装を割り込ませるようなことになるのかなと想像したりはしている。\nOSK のイベントの取扱が不明 単にこれは私が、結局のところGJSとかで拡張機能を作ったことがないことに由来しており、調査が必要である。たとえば、以下のような場合に何かしら処理をするコードが必要であると思われる。\nキーが押されている キーが離された OSKが出現した OSKが消失した 調査 action の実装方法 gnome-shell/js/ui/keyborad.js 内を調べる 関連事項 GNOME OSK extension IdeaList 拡張機能からキーを OSK に追加できるか gnome-shell/js/ui/keyborad.js を インポートして何ができるか調査 関連事項 GNOME OSK extension IdeaList GJS におけるイベントの扱いについて マウスボタンの右が押されたなど、細かいイベントの見方についてまとめる。 Gio、St、Clutter、GObject などについてまとめる GJS における HTTP や WebSocket などのネットワーク通信について Libsoup について、Gnome-Shell の example コードなどを元に使い方についてまとめる。 SSL/TLS 化による暗号化された通信の実装と、証明書の関係について調べる。 DBus と fcitx5、Gnome OSK DBus のイベントを調べる DBus のイベントの扱い方をGJSについて注目して調べる -\u0026gt; D-Spy を使った調査結果をまとめる。 続き とりあえず機能するコードとか 参考にしたサイトとか data/osk-layouts/us.json · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/data/osk-layouts/us.json?ref_type=heads (2025年8月10日) data/osk-layouts · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/tree/main/data/osk-layouts?ref_type=heads (2025年8月10日) data/gnome-shell-osk-layouts.gresource.xml · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/blob/main/data/gnome-shell-osk-layouts.gresource.xml?ref_type=heads (2025年8月10日) data · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/tree/main/data?ref_type=heads (2025年8月10日) keyboard: Add \u0026ldquo;email\u0026rdquo; OSK variant for EMAIL purpose hint (391b0d4e) · コミット · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/commit/391b0d4ef3a194666be0629cd4eaa7c71dda6032 (2025年8月10日) コミット · main · GNOME / gnome-shell · GitLab\nhttps://gitlab.gnome.org/GNOME/gnome-shell/-/commits/main/js/ui/keyboard.js (2025年8月10日) Preferences | GNOME JavaScript\nhttps://gjs.guide/extensions/development/preferences.html (2025年8月17日) ","permalink":"https://www.nyanmo.info/posts/linux/gnomeosk/search/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　GNOME には、スクリーンキーボードがデフォルトで実装されているが、日本語レイアウトが存在しないようで、全角半角切り替えキーさえ出てこないという非常に不便な挙動をしているということがあった。そこで、自分で何かしらしてどうにか全角半角キーを追加したいと思った次第。\u003c/p\u003e\n\u003ch2 id=\"考えていること\"\u003e考えていること\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e拡張機能として実装する\u003c/li\u003e\n\u003cli\u003eGnome-shell 自体を変更してしまう\u003c/li\u003e\n\u003cli\u003eOSK自体にボタンを埋め込まずに、Fcitx5のIME の横にパネルメニューボタンとして、切り替えボタンを表示する\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"わかったこと\"\u003eわかったこと\u003c/h2\u003e\n\u003ch3 id=\"dataosk-layouts配下に日本語レイアウトが存在しない\"\u003edata/osk-layouts/配下に日本語レイアウトが存在しない\u003c/h3\u003e\n\u003cp\u003e　us.json としてアメリカ配列などについては存在するが、jp.json や ja.json みたいなのは存在していない。\u003c/p\u003e\n\u003ch3 id=\"jajson-を-usjson-などからコピーして作るとき\"\u003eja.json を us.json などからコピーして作るとき\u003c/h3\u003e\n\u003cp\u003e　全角半角切り替えキーは、action として記述できる模様。ただ、GJS側でどうやってアクションを処理すればいいのか不明。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eus.json の action 例\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;action\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;emoji\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;iconName\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;osk-emoji-picker-symbolic\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;action\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;languageMenu\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;iconName\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;osk-layout-symbolic\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;action\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hide\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;iconName\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;osk-hide-symbolic\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003ejp.json のイメージ\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;action\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zenkakuHankaku\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;iconName\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;osk-zenkakuHankaku-symbolic\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"gjs-のアクションの実装方法が不明\"\u003eGJS のアクションの実装方法が不明\u003c/h3\u003e\n\u003cp\u003e　調査が必要なことがわかる。fcitx5 を私は使っているがそれについても GJS からどうできるのか調べる必要がありそうである。DBusあたりが重要なのかな？とはなんとなく思っているところである。\u003c/p\u003e\n\u003ch3 id=\"datagnome-shell-osk-layoutsgresourcexml-のイメージ\"\u003edata/gnome-shell-osk-layouts.gresource.xml のイメージ\u003c/h3\u003e\n\u003cp\u003e　ただキーボードレイアウトとactionの実装をするだけでなく、リソースとして以下のように登録してレイアウトを認識させる必要がありそう。\u003c/p\u003e","title":"GNOME OSK 周りの調査"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ツール本体 モデルとテクスチャをまとめて指定 モーションファイルを指定(vmd) UTF-8\nShift-JIS\nツールの使い方 ※ まだ正常に読み込めないモデルが多数存在する。読み込みに失敗した場合はタブごと読み込み直したほうが良い。\nzip ファイルを渡す方法 文字コードを選ぶ Zip ファイル内のコンテンツのファイル名が、UTF-8 でエンコードされているのか、Shift-JIS でエンコードされているのか選ぶ。緑色になっているのが現在選択されている文字コードである。\n目安としては、Windows で圧縮されたであろう Zip ファイルには Shift-JIS を、最近の Linux 環境などで圧縮された Zip ファイルには、UTF-8 を選択するといった感じである。\nデータを渡す モデルとテクスチャをまとめて指定のところで、モデルファイルが入っているzipファイルをそのまま渡す。パスワードロック解除とかには現状はまだ対応していない。（使っているライブラリは対応しているらしいので、後々実装したい。）\n展開して直接ファイルを渡す方法 1. 適当な MMD モデルをダウンロードしてくる 2. zip ファイルとかになっていると思うのでとにかく展開する 3. textures フォルダーの内容を、モデルファイルと同じ場所に全部配置し直す 配置し直す前 modelFolder ├── model.pmx ├── readme.txt └── textures ├── 何かしらのテクスチャ.png ├── 何かしらのテクスチャ1.png ├── ... ├── 何かしらのテクスチャ2.bmp ├── 何かしらのテクスチャ3.bmp ├── ... 配置し直したあと modelFolder ├── 何かしらのテクスチャ.png ├── 何かしらのテクスチャ1.png ├── ... ├── 何かしらのテクスチャ2.bmp ├── 何かしらのテクスチャ3.bmp ├── ... ├── model.pmx └── readme.txt 4. ファイルを指定する モデルとテクスチャをまとめて指定のところで、モデルファイルとテクスチャのファイルをすべて指定する。すると、自動的にモデルが読み込まれ、Three.js の シーンが立ち上がってうまく行けば、モデルが見えるはずである。ちなみに全てのモデルには対応できないようで、読み込めない場合もあるためご了承ください。\nこのツールを作ろうとした動機 単に気軽に、MMD モデルを確認したいとき用。pmx や pmdを読み込んで表示し、色々カメラを動かせるところまでを第一マイルストーンとして、できればボーンを自由に動かしたり、vmd を読み込んで動かせたりする実装してみたいとは思う。\n細かいこと ここからしたはグダグダでもいいからとにかく、何をしたかとか、考えてたとか、思ってたかを記録に残したものになっている。\n現状 (2025/9/27) 久しぶりに、Toon shader についてなんとかしようと思い、MMDToonShader を mesh に割り当ててみようと、three.js のドキュメントを漁ってみたら、最終的に勘違いに気づいた。\nMMDToonShader　自体はすでに MMDLoader 内で処理が走っており、.load メンバ関数を実行すると、本来であれば、Toon shader は動くはずっぽかった。しかし、その実装自体にそもそも問題があるのかもしれないと思い始めめた。具体的には、リソースファイル名についてリネームする部分がコードに含まれていることが気になった。これはまさしく存在しないはずのリソースを参照する動作と関係がありそうだと思い始めた。\nということで、とりあえず現状は、toon shader と存在しないはずのリソースを参照する問題 としてまとめて置くことにした。\nまた、わざわざすでに一応新規である MMDLoader 候補のリポジトリもあるけど、動く様子もないし、とにかくまともに動かしたいので、自分で three.js r170 をフォークして修正を試みてみることを考えた。現状では、とりあえずフォークして専用のブランチを作って、そこをデフォルトに設定するまではした。\n(2025/9/13) zip ファイルとエントリの文字コード zip ファイルから直接読み込むときに、Shift-JIS でファイル名がエンコードされた zip ファイルでしか正常動作しなくなっていた。それで、Linux 環境とかで、日本語が UTF-8 でエンコードされていたりしても、zip ファイル内を正しく読み込めるよう、Shift-JIS と UTF-8 で文字コードを手動で選べるようにした。\nzip.js 側には、filenameUTF8 : falseという項目が一応あるが、文字コード関連の自動化はうまく行かない気がするので、とりあえず手動で選択できるようにした。\ntoon shader モデルが白っぽくなったり、shader でコケてエラーになってしまうなど、問題があることに対して、ちょっと今回は調べた。MeshPhongMaterial あたりを参考に実装してみればいいかという見当は付いた気がする。\nblob URL への変換がうまく行ってないように見える件について 実際に調べてみると、変換がうまく行っていないというより、参照しようとしているファイル名のテクスチャなどが配布されたデータ内にそもそも存在しない、という場合があることがわかった。blender 上で動く拡張機能 mmd_tools を使うと問題が出ないようなモデルで、そのような症状が出ていることがわかった。\n(2025/8/26) なんとか zip.js を使って直接ダウンロードしたモデルファイルを zip ファイルのまま読み込ませることができるようにした。多くのモデルファイルの zip ファイル内のコンテンツには、shift-jis が使われており、それでファイル名が文字化けしてしまう問題があり、それが面倒くさかった。\nただ、現状の実装だと、zip ファイルのエントリが、基本的に shift-jis であることを前提としているため、比較的新しい環境や、UTF-8 を標準としている環境で圧縮された zip ファイルとは多分相性問題を起こすと思われるので、そこを修正したい。\n(2025/8/13) とりあえず、ChatGPT-5 もとにかく詰まったら使って、MMDモデルを読み込むところまで持っていくことはできた。ただし使い方にクセのある仕様になってしまった。MMD の表示にはモデルファイルだけでなく、テクスチャなどの周辺情報が必要であるが、そこら辺の読み込み方法に関して苦戦していた。まず、直接ファイルパスのURLを渡す以外で、blob の参照のURLも利用できることを試すまでは、うまくいっていたが、それ以降のテクスチャを読み込むことに関しては詰まった。そこら辺に関しては ChatGPT-5 が Map を使う方法を吐き出したのでそれをそのまま利用した。\n正直手軽だとは現状言い難いし、ファイル読み込みにはかなり改善の余地があるものと感じられる。ただ、そのためだけにバックエンドとか用意したくないし悩みものである。なんとかクライアント側の JS で、ZIPファイルだったりをガリガリ処理させられないか考える必要もありそう。\n(2026/8/4) 結局のところ MMD に関するいろんな問題を修正しようと思って、three.jsのリポジトリまでクローンしたのに、一年間結局放置してしまった。別の人に対して、偉そうなことをこの記事では書いていたと思うが、結局自分も二の舞になるという。ただ思ったこととかはいろいろあったので、それについて一応現状報告みたいにしたいと思うところである。\nフォークしたままそのままになっているデジタルタトゥーと化したリポジトリ Three.js 本家のリポジトリ 自分と CG の関係性 まともな 3D 作品として成り立つ何か創作ができたことはなく、多くが触ってみた、途中で折れた程度にとどまっている。 OpenGL(固定パイプライン時代のバージョン) のネットにあるサンプルコードをC言語の物をコンパイルして動かしたり、glBeginとglEndの間に、描画命令を挟んで三角形とかかろうじて表示させたことはある。テクスチャは貼ったことがない。 p5js でコードを書いて、授業のレポート用にワイヤレス通信における PSA や ASK を例示するコード(超絶いい加減)を書いたことはある。 WebGL(プログラマブルシェーダの時代の物) を使って、かろうじてチュートリアルを通じて三角形を表示したことがある。 WebGL のユニフォーム変数を使うことで、任意のデータ(マウス座標やキーボード入力に応じた命令など)をCPUからGPUに随時転送して、様々な操作が可能であることを実際に触って実感したことはある。 WebGL でもテクスチャを貼る経験まではしていない。 3D には、移動、拡大縮小、回転があり、それが投影行列としてまとめられていて、それぞれの操作は交換律的には、移動と回転を、回転と移動にするなど、順番を入れ替えると等式が成り立たず、それぞれ異なる結果になるという認識がある。 3D は、基本的にポリゴンと呼ばれる多角形をたくさん組み合わせることでなり、基本的には三角形を無数に組み合わせて、メッシュという複雑な面を形成するという認識がある。昔の 1990 年代くらいの Nvidia では、四角形押しだったがやらかして大損失を出し、どこかに(SEGA?)泣きついて資金を出してもらった、という話もどっかの海外の YouTube の動画で聞いたことがある気がする。 OpenGL には固定パイプライン時代の古いものと、プログラマブルシェーダの新しい時代のものがあり、プログラムのパラダイムが大きく異なり、昔の知識をそのまま使えるわけではないという断絶がある。今学ぶなら、プログラマブルシェーダが王道っぽいという認識がある。 Blender 上で、MMD Tools を使って、MMD モデルとモーションを読み込ませて動かし、動作することを確認したことがある。 Blender 上で、MMD Tools を使って、読み込んだモデルのボーンを動かしてキーフレームを打つことで、かろうじて任意の動きをさせたことはある。 OpenGL なり WebGL なり Vulkan なりいろいろあるが、どれを使っても自分が使うツールとしてもいったん最低限機能する、動作するという意味で、動くアプリみたいな一つの完成された何かを作ったこと(成功体験)はない。あくまで触ってみた、動かしてみた、程度である。 Three.js を使って、ブログに埋め込みの Viewer として簡易的に実装して使っているということはある。このブログでも使われているもののことである。 DELL Latitude E7450 タッチパッドボタン EV2451 もどき（スタンドなし） Logicool K375s キーボードの足 PCIe(GPU) 縦方向マウント MMD と自分の関係性 独自の pmx vmd などのバイナリ形式であること自体は不便というか、嫌な感じがする。 モデル自体でボーンの作りが地味に互換性がなくて、モーションを読み込むと崩壊して直すのしんどってなって折れることが多い。 ネットで問題が起きた時調べても断片的な情報しか得られず、かつなんかマウント取りとか、相手を冷笑するようなコメントにも多く対峙することになり、かなり萎える。 そもそも、MMD の開発者自体が、最初 Blender に対して難しいからということで、DirectX(9あたり？) を使ったソフトとして開発したが、結局維持不能になって開発を辞めることを宣言したみたいなことを、MMD について LLM にいろいろ投げつけていたら出てきたが、本当かどうかまだ調べられていない。ただ、現状からしてガラパゴスっていうか、権利関係もしんどそうというか、あまりいて居心地のいいエコシステムではなさそうに、私個人としては思う。もし LLM の出した開発者の話が本当ならば、なんかソフトはすでに死んでいるんだけど、それを支持する創作者と消費者によって、ゾンビのように閉鎖的な内輪ノリ的なコミュニティによって強引に延命されているって感じが強いのは個人的にはよく感じる。 Blender にて、モデルやモーションを読み込んだり、ボーンを動かしたりとか、それで Cycles とかでレンダリングしてみるとか、触ってみるってことはしたけど、それ以上にはなっていない。なんか EEVEE じゃないと色合いがおかしくなったりするモデルなどがあることもあった。 なんか Blender で MMD モデルを触っていると、贅沢に計算資源を使って EEVEE や Cycles で動かすより、Viewport のレンダリングのほうが、破綻が少なく、シンプルで似合っているように思うことがあった。 なんか、MMD に限らないが、日本の創作やコンテンツにまとわりつく根性論、自己責任論、生存者競争って感じが嫌い。 そもそも MMD って Blender と比べてそんなに簡単、気軽だろうか？という素朴な疑問があるし、バックエンドが DirectX9 で 32bit アプリの時代の産物って感じで、Win でしか動かなかったりして、なんか時代にあってなくて使いづらいような気もする。 Wine を使うことにより、Linux 上で MMD に関連する Win アプリを試したことがあるが、使えないレベルでうまく動かなかった記憶しかない。 権利関係に関しても結構怖いっていうか、欲望や魅力を人質にとって、自尊心や承認欲求を満たそうとしているように見えるモデル配布の雰囲気や、ニコニコ動画っていうか、2ch っていうか、掲示板文化っていうか、エコシステムがどことなく息苦しい感じがする。モデル配布で、よく見られる\u0026quot;まともな人ならわかるはず\u0026quot;という論理で設定されたパスワードを要求するとかも、なんかそれ方向性が違うんじゃないの？と思うこともある。もちろん悪用する人もいて、話を聞いてくれない人もいて、保守的になっているのだろうが、なんとなく\u0026quot;作り手であることの特権意識\u0026quot;みたいな上下関係みたいな雰囲気にもつながっている気がして、嫌になったことがある。そういうやり方したら、そもそも悪意なく使おうとして、でもパスワードはわからないという人とかを排除するという偽陽性を許容していることになるが、それってコミュニティーが縮退したりする原因にならないの？って思うこともある。 結局わかる人だけが使えばいい、楽しめばいいという論理が持ち出されることもあると思うが、私的にはあまり納得できない気もする。 確かに、Web で動かせたほうが気軽ではあるが、Blender に MMD Tools はすでにあるし、わざわざ無理して時間を投下しまくって、頑張っても MMD に関しては仕方ないんじゃないかという感じがしてきている。なんか探せばすでにほかの MMD に関するものもたくさんすでにワークアラウンドあるみたいだし、なんか自分がやってもゴミを作る結果になるだけだと言われたら否定できないのも確かである。このブログもそうだが、あくまで自己満足というか、自分のノートとして機能すればいいとしていて、Web アプリみたいな作りこまれた1つの巨大なものを作って他人が使っても快適に使えるほどに完成度を高めてやるということとは衝突しているところもあり、悩ましい。まあやらない言い訳を立て並べていると叩かれるかもしれないが、私には私の事情があり、投資したリソースについて、誰かが必ず報ってくれるとも限らない、ボランティアの側面が強いことについて、自分を優先することは、悪いことではないように見える。 まあ今のところは、なんか完全に見捨てているってわけではないけど、たまに気が乗った時でいいかなと思っているところもある。 TODOs 最低限 pmx や pmd を読み込み、カメラを動かせる 全画面モードや高解像度モード。 zip ファイルなどを受け付けて、モバイルでも利用しやすくする (バグはまだ残ってる) zip.js が Shift-JIS との相性問題で、zip ファイル内のファイル名を正しく解釈できず、文字化けする問題を何とかする\n-\u0026gt; zip.js を適当に fork して Shift-JIS に対応させたり、UTF-8 にファイル名を変換させるか？\n-\u0026gt; rawFilename プロパティがあるので、それを Shift-JIS エンコードで読み出すか？\n-\u0026gt; 最終的に ChatGPT-5-Mini に要件を渡して書かせたコードを使った。TextDecoder を使ったものを採用した。 zip ファイル内のエントリの名前の文字コードを自動的に識別し、適切にデコードさせるか、ユーザがフォーマットをあらかじめ指定できるようにして、相性問題を起こらないようにする。 view 自体にモデルファイルをドラックアンドドロップできるようにする 複数のモデルが見つかったときにセレクターを表示するようにする コードのリファクタリングによる、実装の分離 パスワード付き zip への対応 ファイルロードの進捗状況を表すプログレスバーの実装。UX の改善 blob URLへのMAP変換がうまくいかないバグへの対応 // 例 manager is working mmdviewer/:516 足.png mmdviewer/:517 blob:https://www.nyanmo.info/足.png mmdviewer/:515 欠損しているテクスチャ画像などのリソースエラーの表示 正しくテクスチャを表示できず、白っぽくなったり、色褪せたみたいな表示になったりする。toon周り未対応の弊害？とにかくもっとまともなマテリアルだのテクスチャだのの実装をする。 テクスチャなしとありモードの切り替えボタン 全体的にもっと明るい感じにする。薄暗い感じの解消 blender のように、上や横に自動的にカメラを運ぶ機能 透視投影、平行投影の切り替え blender みたいに等間隔の補助線を表示する 地面を表示する。 全画面モードも考慮したコントローラー 専用フォームでない view へのファイルのドラックアンドドロップに対応する いくつかサンプルモーションを用意し、ボタンを押すだけでモデルを動かせるようにする。例えば歩くとか、何か踊らせるとか。 自動で カメラやモデルをぐるぐる動かして、放置していたら全体像を眺められるようにする。 WASD や タッチパネル上のコントローラーを用意してモデルを動かせるようにする。 机とか、椅子とか家の一室みたいなのとか、Sample オブジェクトを配置する。 youtubeでいう シアターモードみたいなの欲しい。タブ内で全画面みたいな。 モデルなどをうまく読み込めなかったときのエラーハンドリングと通知 ボーンを動かせる vmd を読み込める 複数モデル読み込み 調べてわかったこと MMDLoader MMDLoader などは、最新バージョンの three.js にはないっぽいので、古いバージョンを参照する必要がありそう。r170くらいで three.js/examples/jsm /loaders/MMDLoader.js の github の差分に以下のような記述があった。\nconsole.warn( \u0026#39;THREE.MMDAnimationHelper: The module has been deprecated and will be removed with r172. Please migrate to https://github.com/takahirox/three-mmd-loader instead.\u0026#39; ); しかし、URLを辿って、three-mmd-loader を参照してみたところ、\u0026ldquo;coming soon\u0026quot;となっており、現時点（2025/8/9）ではまだ何もできていないことがわかった。\nこんな状態なので、インターネットから消えるとめんどくさいし、とりあえず適当な場所に、MMD の類が three.js からなくならないうちに r170 のリポジトリごとクローンしておくことにした。\nzip.js (8月あたり？) 以下は、FS | @zip.js/zip.js の引用したもの。一応簡単に必要そうな部分の使い方のメモとして。ただどうすればいいかは、まだ調査できていない。\n圧縮 const TEXT_CONTENT = \u0026#34;Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed diam nonummy nibh euismod tincidunt ut laoreet dolore magna aliquam erat volutpat.\u0026#34;; const FILENAME = \u0026#34;lorem.txt\u0026#34;; const BLOB = new Blob([TEXT_CONTENT], { type: zip.getMimeType(FILENAME) }); let zipFs = new zip.fs.FS(); zipFs.addBlob(\u0026#34;lorem.txt\u0026#34;, BLOB); const zippedBlob = await zipFs.exportBlob(); 展開 zipFs = new zip.fs.FS(); await zipFs.importBlob(zippedBlob); const firstEntry = zipFs.children[0]; const unzippedBlob = await firstEntry.getBlob(zip.getMimeType(firstEntry.name)); (2025/9/13) の追記 なんか結局 zip.js の実装については、調べているうちに、実装する前に調べたとおりにはならなかったので最終的にどうしたか書いておこうかなと思って追記することにした。とは言っても、他にもやりたいことはあるので、労力的な問題でここについては、実際のコードを貼り付けるくらいにしようとは思うが。\n実際に実装した感想としては、なんか最初予定していたのと、実際に色々右往左往して動くようにしたコードではまるで実装が違う気がするということであった。zip.fs.FS() とか使ってなくて、zip.BlobReaderやzip.ZipReaderを使ったりしてるし。\nあと、特に windows 環境で圧縮されたであろう MMD 関連の zip ファイルについても ファイル名を Shift-JIS でデコードしないといけないのが、地味に引っかかっていたと思う。ここは完全には解決されてなくて、UTF-8 を一時的に犠牲にする形になってるので、後々なんとかしたいかも。\nimport \u0026lt;script type=\u0026#34;text/javascript\u0026#34; src=\u0026#34;{{ .Site.BaseURL }}libs/zip.js/dist/zip.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; 読み込み function readShiftJISTextFromBlob(ShiftJIStextArrayBlob){ // ChatGPT-5-Mini --------------------------------------------------------- // TextDecoder が shift-jis に対応している場合 if (typeof TextDecoder !== \u0026#39;undefined\u0026#39;) { const decoder = new TextDecoder(\u0026#39;shift-jis\u0026#39;); return decoder.decode(ShiftJIStextArrayBlob); } else { throw new Error(\u0026#39;TextDecoder が shift-jis に対応していません\u0026#39;); } // ChatGPT-5-Mini --------------------------------------------------------- } async function readZipForModelFile(modelFile,zipName,fileMap){ let zipBlob = getZipFileRef(modelFile, zipName) let modelFileName = null console.log(zipBlob) let zipBlobReader = new zip.BlobReader(zipBlob); let zipReader = new zip.ZipReader(zipBlobReader) for(let entry of await zipReader.getEntries()){ let filename = readShiftJISTextFromBlob(entry.rawFilename) filename = filename.split(\u0026#34;/\u0026#34;)[filename.split(\u0026#34;/\u0026#34;).length - 1] fileMap.set(filename,URL.createObjectURL(new Blob([await entry.arrayBuffer()]))) if(filename.includes(\u0026#34;pmx\u0026#34;) || filename.includes(\u0026#34;pmd\u0026#34;)){ modelFileName = filename } console.log(entry) console.log(filename) } if(modelFileName == null){ return null } let manager = new THREE.LoadingManager() manager.setURLModifier((url) =\u0026gt; { let filename = url.split(\u0026#34;/\u0026#34;).pop().split(\u0026#34;\\\\\u0026#34;).pop() console.log(\u0026#34;manager is working\u0026#34;) console.log(filename) console.log(fileMap.get(filename)) console.log(fileMap.get(filename) || url) return fileMap.get(filename) || url }) return { \u0026#34;modelFileName\u0026#34; : modelFileName, \u0026#34;manager\u0026#34; : manager } } toon shader と存在しないはずのリソースを参照する問題 結局調べたり問題をなんとかしようとした結果toon-shaderの件と、blob-url-への変換がうまく行かない問題について の話題は、MMDLoader のコードを読み進めているうちに、どうもつながっているっぽいことがわかっったため、統合して扱うことにした。\n(2025/9/27) 時点の記録 とりあえず、MMDLoader.js の内容を読んでいると次の流れがわかった。\n.load(\u0026quot;modelfilepath\u0026quot;) でMMDLoader クラスを使った読み込み MeshBuilder の build 関数にパースされたデータが渡される MaterialBuilder の build 関数にパースされたデータが渡される MaterialBuilder 内で Toon Shader に関する設定や判定が行われる 以下には、気になったコードの部分について、MMDLoader.js を置いておく。\nMMDLoader class 内部の気になったところ一部引用 load(){ ... // モデルデータがパースされる const data = modelExtension === \u0026#39;pmd\u0026#39; ? parser.parsePmd( buffer, true ) : parser.parsePmx( buffer, true ); // MeshBuilder class の build 関数にデータが渡される onLoad( builder.build( data, resourcePath, onProgress, onError ) ); ... } MeshBuilder class 内部の気になったところ一部引用 class MeshBuilder { constructor( manager ) { this.crossOrigin = \u0026#39;anonymous\u0026#39;; this.geometryBuilder = new GeometryBuilder(); this.materialBuilder = new MaterialBuilder( manager ); } ... build( data, resourcePath, onProgress, onError ) { const geometry = this.geometryBuilder.build( data ); const material = this.materialBuilder // MaterialBuilder .setCrossOrigin( this.crossOrigin ) .setResourcePath( resourcePath ) .build( data, geometry, onProgress, onError ); const mesh = new SkinnedMesh( geometry, material ); const skeleton = new Skeleton( initBones( mesh ) ); mesh.bind( skeleton ); // console.log( mesh ); // for console debug return mesh; } ... } MaterialBuilder class 内部の気になったところ一部引用 class MaterialBuilder { ... build( data, geometry /*, onProgress, onError */ ) { ...// pmd のとき // gradientMap const toonFileName = ( material.toonIndex === - 1 ) ? \u0026#39;toon00.bmp\u0026#39; : data.toonTextures[ material.toonIndex ].fileName; params.gradientMap = this._loadTexture( toonFileName, textures, { isToonTexture: true, isDefaultToonTexture: this._isDefaultToonTexture( toonFileName ) } ); ...// pmx のとき // gradientMap let toonFileName, isDefaultToon; if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) { toonFileName = \u0026#39;toon\u0026#39; + ( \u0026#39;0\u0026#39; + ( material.toonIndex + 1 ) ).slice( - 2 ) + \u0026#39;.bmp\u0026#39;; isDefaultToon = true; } else { toonFileName = data.textures[ material.toonIndex ]; isDefaultToon = false; } params.gradientMap = this._loadTexture( toonFileName, textures, { isToonTexture: true, isDefaultToonTexture: isDefaultToon } ); ... materials.push( new MMDToonMaterial( params ) ); ... } ... _isDefaultToonTexture( name ) { if ( name.length !== 10 ) return false; return /toon(10|0[0-9])\\.bmp/.test( name ); } ... _loadTexture( filePath, textures, params, onProgress, onError ) { ... if ( params.isDefaultToonTexture === true ) { let index; try { index = parseInt( filePath.match( /toon([0-9]{2})\\.bmp$/ )[ 1 ] ); } catch ( e ) { console.warn( \u0026#39;THREE.MMDLoader: \u0026#39; + filePath + \u0026#39; seems like a \u0026#39; + \u0026#39;not right default texture path. Using toon00.bmp instead.\u0026#39; ); index = 0; } fullPath = DEFAULT_TOON_TEXTURES[ index ]; } else { fullPath = this.resourcePath + filePath; } ... } ... } 特に私としては、以下のような部分がすごく気になる。blob url への変換がうまく行かない問題についてのエラーで出ていたファイル名と同じようなことが書かれている。\nMMDLoader.js の特に気になる部分 ... const toonFileName = ( material.toonIndex === - 1 ) ? \u0026#39;toon00.bmp\u0026#39; : data.toonTextures[ material.toonIndex ].fileName; if ( material.toonIndex === - 1 || material.toonFlag !== 0 ) { toonFileName = \u0026#39;toon\u0026#39; + ( \u0026#39;0\u0026#39; + ( material.toonIndex + 1 ) ).slice( - 2 ) + \u0026#39;.bmp\u0026#39;; isDefaultToon = true; } else { toonFileName = data.textures[ material.toonIndex ]; isDefaultToon = false; } ... ... _isDefaultToonTexture( name ) { if ( name.length !== 10 ) return false; return /toon(10|0[0-9])\\.bmp/.test( name ); } ... ... try { index = parseInt( filePath.match( /toon([0-9]{2})\\.bmp$/ )[ 1 ] ); } catch ( e ) { console.warn( \u0026#39;THREE.MMDLoader: \u0026#39; + filePath + \u0026#39; seems like a \u0026#39; + \u0026#39;not right default texture path. Using toon00.bmp instead.\u0026#39; ); index = 0; } ... うまくリソースを読み込めなかったときのエラー GET blob:https://www.nyanmo.info/toon_%E8%B5%A402.bmp net::ERR_FILE_NOT_FOUND // 赤02.png blob:https://www.nyanmo.info/h.bmp:1 GET blob:https://www.nyanmo.info/h.bmp net::ERR_FILE_NOT_FOUND blob:https://www.nyanmo.info/%E8%B6%B3.png:1 GET blob:https://www.nyanmo.info/%E8%B6%B3.png net::ERR_FILE_NOT_FOUND // 足.png blob:https://www.nyanmo.info/%E9%9D%B4.png:1 GET blob:https://www.nyanmo.info/%E9%9D%B4.png net::ERR_FILE_NOT_FOUND // 靴.png toon shader (2025/9/13) そろそろ、toon shader の問題をなんとかしようと思って、適当に下調べし始めた。正直 three.js と MMD の組み合わせだと、調べてもあんまりこの話題が出てくるって感じじゃないと感じたし、実装できる自信があんまりないというのもあるが、それでも試してみようと思ったのが今日という感じ。\n気になったところ\n調べるというより、three.js r170 の中にある、MMDToonShader.jsについてちょっと見てみたという感じである。それで気になったところをピックアップするということをしようと思う。 // リポジトリからの相対パス // ./examples/jsm/shaders/MMDToonShader.js /** * MMD Toon Shader * * This shader is extended from MeshPhongMaterial, and merged algorithms with * MeshToonMaterial and MeshMetcapMaterial. * Ideas came from https://github.com/mrdoob/three.js/issues/19609 * * Combining steps: * * Declare matcap uniform. * * Add gradientmap_pars_fragment. * * Use gradient irradiances instead of dotNL irradiance from MeshPhongMaterial. * (Replace lights_phong_pars_fragment with lights_mmd_toon_pars_fragment) * * Add mmd_toon_matcap_fragment. */ // 何かしらのコード export { MMDToonShader }; コメントを見たり、export に注目している限り、MMDToonShaderを MeshPhongMaterial – three.js docs あたりを参考にこねくり回せば良さそうに見える。\nとりあえず、MeshPhongMaterial のサンプルコードとか調べてみてもいいかもしれないと思った。\ntoon-shader-と存在しないはずのリソースを参照する問題 を参照\n(2025/9/13) toon shader を適切に設定していなときに出るものだと思われるエラーは以下のようなものがあった。\nTHREE.WebGLProgram: Shader Error 0 - VALIDATE_STATUS false Material Name: 柄 Material Type: MMDToonMaterial Program Info Log: Must have a compiled vertex shader attached: SHADER_INFO_LOG: ERROR: 0:306: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:306: \u0026#39;\u0026#39; : array size must be a constant integer expression ERROR: 0:311: \u0026#39;MORPHTARGETS_TEXTURE_STRIDE\u0026#39; : undeclared identifier ERROR: 0:311: \u0026#39;*\u0026#39; : wrong operand types - no operation \u0026#39;*\u0026#39; exists that takes a left-hand operand of type \u0026#39;const highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) ERROR: 0:562: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:562: \u0026#39;\u0026lt;\u0026#39; : wrong operand types - no operation \u0026#39;\u0026lt;\u0026#39; exists that takes a left-hand operand of type \u0026#39;highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) VERTEX ERROR: 0:306: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:306: \u0026#39;\u0026#39; : array size must be a constant integer expression ERROR: 0:311: \u0026#39;MORPHTARGETS_TEXTURE_STRIDE\u0026#39; : undeclared identifier ERROR: 0:311: \u0026#39;*\u0026#39; : wrong operand types - no operation \u0026#39;*\u0026#39; exists that takes a left-hand operand of type \u0026#39;const highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) ERROR: 0:562: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:562: \u0026#39;\u0026lt;\u0026#39; : wrong operand types - no operation \u0026#39;\u0026lt;\u0026#39; exists that takes a left-hand operand of type \u0026#39;highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) 301: #endif 302: #endif 303: #ifdef USE_MORPHTARGETS 304: #ifndef USE_INSTANCING_MORPH 305: uniform float morphTargetBaseInfluence; \u0026gt; 306: uniform float morphTargetInfluences[ MORPHTARGETS_COUNT ]; 307: #endif 308: uniform sampler2DArray morphTargetsTexture; 309: uniform ivec2 morphTargetsTextureSize; 310: vec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) { 311: int texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset; 312: int y = texelIndex / morphTargetsTextureSize.x; three.module.js:20346:14 WebGL warning: linkProgram: Must have a compiled vertex shader attached: SHADER_INFO_LOG: ERROR: 0:306: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:306: \u0026#39;\u0026#39; : array size must be a constant integer expression ERROR: 0:311: \u0026#39;MORPHTARGETS_TEXTURE_STRIDE\u0026#39; : undeclared identifier ERROR: 0:311: \u0026#39;*\u0026#39; : wrong operand types - no operation \u0026#39;*\u0026#39; exists that takes a left-hand operand of type \u0026#39;const highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) ERROR: 0:562: \u0026#39;MORPHTARGETS_COUNT\u0026#39; : undeclared identifier ERROR: 0:562: \u0026#39;\u0026lt;\u0026#39; : wrong operand types - no operation \u0026#39;\u0026lt;\u0026#39; exists that takes a left-hand operand of type \u0026#39;highp int\u0026#39; and a right operand of type \u0026#39;const highp float\u0026#39; (or there is no acceptable conversion) WebGL warning: useProgram: Program must be linked successfully. 31 After reporting 32, no further warnings will be reported for this WebGL context. ちなみに、three.js 側の MMDToonShader.js にある具体的な実装を見ても、ひたすらシェーダプログラムが書かれていたり、MeshPhongMaterial の中身を置き換えようとしているところがあるので、上記のシェーダ関連のエラーとのつながりもありそうに見える。以下は、MMDToonShader.jsの実装の一部分を引用したものである。\nconst mmd_toon_matcap_fragment = /* glsl */` #ifdef USE_MATCAP vec3 viewDir = normalize( vViewPosition ); vec3 x = normalize( vec3( viewDir.z, 0.0, - viewDir.x ) ); vec3 y = cross( viewDir, x ); vec2 uv = vec2( dot( x, normal ), dot( y, normal ) ) * 0.495 + 0.5; // 0.495 to remove artifacts caused by undersized matcap disks vec4 matcapColor = texture2D( matcap, uv ); #ifdef MATCAP_BLENDING_MULTIPLY outgoingLight *= matcapColor.rgb; #elif defined( MATCAP_BLENDING_ADD ) outgoingLight += matcapColor.rgb; #endif #endif `; // 何かしらのコード const MMDToonShader = { name: \u0026#39;MMDToonShader\u0026#39;, defines: { TOON: true, MATCAP: true, MATCAP_BLENDING_ADD: true, }, uniforms: UniformsUtils.merge( [ ShaderLib.toon.uniforms, ShaderLib.phong.uniforms, ShaderLib.matcap.uniforms, ] ), vertexShader: ShaderLib.phong.vertexShader .replace( \u0026#39;#include \u0026lt;envmap_pars_vertex\u0026gt;\u0026#39;, \u0026#39;\u0026#39; ) .replace( \u0026#39;#include \u0026lt;envmap_vertex\u0026gt;\u0026#39;, \u0026#39;\u0026#39; ), fragmentShader: ShaderLib.phong.fragmentShader .replace( \u0026#39;#include \u0026lt;common\u0026gt;\u0026#39;, ` #ifdef USE_MATCAP uniform sampler2D matcap; #endif #include \u0026lt;common\u0026gt; ` ) .replace( \u0026#39;#include \u0026lt;envmap_common_pars_fragment\u0026gt;\u0026#39;, ` #include \u0026lt;gradientmap_pars_fragment\u0026gt; ` ) .replace( \u0026#39;#include \u0026lt;envmap_pars_fragment\u0026gt;\u0026#39;, \u0026#39;\u0026#39; ) .replace( \u0026#39;#include \u0026lt;lights_phong_pars_fragment\u0026gt;\u0026#39;, lights_mmd_toon_pars_fragment ) .replace( \u0026#39;#include \u0026lt;envmap_fragment\u0026gt;\u0026#39;, ` ${mmd_toon_matcap_fragment} ` ) }; (2025/9/13) ShaderMaterial – three.js docs を読んでいると、MMDToonShader.jsと同じ名前の vertexShader や fragmentShader 、uniforms といった key をもった JSON を渡していることがわかった。\n難しく考えなくても、とりあえず、ShaderMaterial に対して export された MMDToonShader を渡してやれば、あとは、マテリアルをなんとかしてメッシュなりに結びつけて反映させれば良さそうな気もしてきた。\nconst material = new THREE.ShaderMaterial( { uniforms: { time: { value: 1.0 }, resolution: { value: new THREE.Vector2() } }, vertexShader: document.getElementById( \u0026#39;vertexShader\u0026#39; ).textContent, fragmentShader: document.getElementById( \u0026#39;fragmentShader\u0026#39; ).textContent } ); toon-shader-と存在しないはずのリソースを参照する問題 を参照\nblob url への変換がうまく行かない問題について (2025/9/13) モデルが正しく読み込めない問題として、toon shader 以外に、単純に正しくファイルを読み込めず欠損するというのがある。それで、よく出ているエラーが以下のようなものである。\nGET blob:https://www.nyanmo.info/toon_%E8%B5%A402.bmp net::ERR_FILE_NOT_FOUND // 赤02.png blob:https://www.nyanmo.info/h.bmp:1 GET blob:https://www.nyanmo.info/h.bmp net::ERR_FILE_NOT_FOUND blob:https://www.nyanmo.info/%E8%B6%B3.png:1 GET blob:https://www.nyanmo.info/%E8%B6%B3.png net::ERR_FILE_NOT_FOUND // 足.png blob:https://www.nyanmo.info/%E9%9D%B4.png:1 GET blob:https://www.nyanmo.info/%E9%9D%B4.png net::ERR_FILE_NOT_FOUND // 靴.png 正しく blob URL に pmx に書かれているパスが変換された場合は以下のようになる。\nmmdviewer/:578 manager is working mmdviewer/:579 前髪.png mmdviewer/:580 blob:https://www.nyanmo.info/b12f6356-7b37-45fc-9ed6-8021c66aa610 mmdviewer/:581 blob:https://www.nyanmo.info/b12f6356-7b37-45fc-9ed6-8021c66aa610 ぱっと異常動作例と、正常動作例を見比べて思うこととしては、正常動作しているときは日本語が URL のためにエンコードされていないが、異常動作しているときには、%E8%B6%B3.png(赤02.png) と思いっきりエンコードされているというのがある。\nここから考えられることとしてはそもそもファイルが読み込めてなくて、見つけられなかった結果、http サーバー側に GET しようとしてそういう挙動になっているのか、ファイルは存在し読み込めているが、どこかでファイル名がエンコードされてしまった結果、実際に存在するリソース名と釣り合わずにエラーになっているのか、という感じがする。\nもし、ファイルが見つからなくてこのようなエラーになっているなら、適当に埋め合わせ用のテクスチャを勝手にあてがうようにしたり、欠損している分について手動でテクスチャを投下できるようにしてみてもいいかもしれない。\n(2025/9/13) モデルが正しく読み込めない問題で blob URL への変換がうまく行かないと思っていたことがあるが、それは実はちょっと違うかもしれないことが今回わかった。例えば以下の例では大体、３つほどテクスチャファイルが足りないように見える。\nGET blob:https://www.nyanmo.info/toon_%E8%B5%A402.bmp net::ERR_FILE_NOT_FOUND // 赤02.png blob:https://www.nyanmo.info/h.bmp:1 GET blob:https://www.nyanmo.info/h.bmp net::ERR_FILE_NOT_FOUND blob:https://www.nyanmo.info/%E8%B6%B3.png:1 GET blob:https://www.nyanmo.info/%E8%B6%B3.png net::ERR_FILE_NOT_FOUND // 足.png blob:https://www.nyanmo.info/%E9%9D%B4.png:1 GET blob:https://www.nyanmo.info/%E9%9D%B4.png net::ERR_FILE_NOT_FOUND // 靴.png しかし、実際に元々配布されていた zip ファイル内を確認してみると、そもそもそんな名前のテクスチャは存在せず、脚.pngなどにまとめて、足らしきものや、靴らしきものも含まれていることがわかった。\nblender 上で動く拡張機能である mmd_tools では、そのような症状はなかったので、内部的になにかしないといけないのかな？と思っているが、具体的にどう実装すればいいかは見当が付いていない。とりあえず mmd_tools のコードをこの問題について注目しながら漁って見ようかなと思ったところ。\ntoon-shader-と存在しないはずのリソースを参照する問題 を参照\nzip 投下時に Shift-JIS のファイル名が付いたモデルしか読み込めない状態になっている件について (2025/9/13) 正直自動で文字コード識別は不具合の温床な気がするので、とにかく手動で選択できるように実装を変えることにした。どちらかを試せば大体は動くだろうということで、UTF-8とShift-JISを選べるようにした。\n関連してそうな記事 JavaScript の条件分岐でわかりにくいミスをした 参考にしたものや使ったもの Three.js – JavaScript 3D Library\nhttps://threejs.org/ (2025年8月9日)\nthree CDN by jsDelivr - A free, fast, and reliable Open Source CDN\nhttps://cdn.jsdelivr.net/npm/three@0.177.0/examples/jsm/ (2025年8月9日)\nthree.js でMMDを使う #JavaScript - Qiita\nhttps://qiita.com/shoichi1023/items/6cbaefe078c33f600bfe (2025年8月9日)\nブラウザ３Dゲームを作る作戦その4: MMDデータを読み込んで動かす - 式姫で遊ぶ日記\nhttps://iwanabot.hatenablog.com/entry/2020/05/01/014258 (2025年8月9日)\nGitHub - takahirox/three-mmd-loader\nhttps://github.com/takahirox/three-mmd-loader (2025年8月9日)\nGitHub - mrdoob/three.js at r170\nhttps://github.com/mrdoob/three.js/tree/r170 (2025年8月9日)\nGitHub - mrdoob/three.js: JavaScript 3D Library.\nhttps://github.com/mrdoob/three.js/tree/dev (2025年8月9日)\nThree.jsこと始め\nhttps://koro-koro.com/threejs-no1/ (2025年8月9日)\nChatGPT\nhttps://chatgpt.com/ (2025年8月13日)\nFullscreen API - Web APIs | MDN\nhttps://developer.mozilla.org/en-US/docs/Web/API/Fullscreen_API (2025年8月13日)\nThree.jsでの最適なリサイズ処理 - ICS MEDIA\nhttps://ics.media/tutorial-three/renderer_resize/ (2025年8月13日)\nzip.js - JavaScript library to zip and unzip files\nhttps://gildas-lormeau.github.io/zip.js/ (2025年8月13日)\nGitHub - gildas-lormeau/zip.js: JavaScript library to zip and unzip files supporting multi-core compression, compression streams, zip64, split files and encryption.\nhttps://github.com/gildas-lormeau/zip.js/tree/master (2025年8月13日)\nFS | @zip.js/zip.js\nhttps://gildas-lormeau.github.io/zip.js/api/classes/FS.html (2025年8月13日)\nMedia Types\nhttps://www.iana.org/assignments/media-types/media-types.xhtml (2025年8月26日)\nCommon media types\nhttps://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types (2025年8月26日)\nBlob: text() method\nhttps://developer.mozilla.org/en-US/docs/Web/API/Blob/text (2025年8月26日)\nFileReader\nhttps://developer.mozilla.org/en-US/docs/Web/API/FileReader (2025年8月26日)\nMeshPhongMaterial – three.js docs\nhttps://threejs.org/docs/?q=MeshPhongMaterial#api/en/materials/MeshPhongMaterial (2025年9月13日)\nURL Encode/Decode (For Japanese language)\nhttps://www.avekt.com/en-us/WebApps/UrlEncodeJapanese (2025年9月13日)\nMeshPhongMaterial - Three.js Tutorials\nhttps://sbcode.net/threejs/meshphongmaterial/ (2025年9月13日)\nsugiany/blender_mmd_tools: mmd_tools is a blender addon for importing Models and Motions of MikuMikuDance.\nhttps://github.com/sugiany/blender_mmd_tools (2025年9月13日)\nShaderMaterial – three.js docs\nhttps://threejs.org/docs/#api/en/materials/ShaderMaterial (2025年9月13日)\nthree.js/src/materials/MeshPhongMaterial.js at master · mrdoob/three.js\nhttps://github.com/mrdoob/three.js/blob/master/src/materials/MeshPhongMaterial.js (2025年9月14日)\n","permalink":"https://www.nyanmo.info/tools/mmdviewer/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"ツール本体\"\u003eツール本体\u003c/h2\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\u003cdiv class=\"mmdViewContaier615798324\"\u003e\n    \u003cdiv class=\"mainMMDviewContaier\"\u003e\n        \u003cdiv class=\"MMDcontrolerInsideView row\" style=\"position:fixed; right:10px; bottom:10px; width:fit-content;\"\u003e\n            \u003cdiv class=\"buttonConatiner column\" style=\"width: 120px;\"\u003e\n                \u003cinput type=\"button\" id=\"move\" name=\"move\"\u003e\n                \u003cinput type=\"button\" id=\"exitfullscreen\" name=\"exitfullscreen\" value=\"\"\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"fileSelectorContainer mmdControlerContainer model row border\"\u003e\n            \u003cdiv\u003eモデルとテクスチャをまとめて指定\u003c/div\u003e\n            \u003cinput type=\"file\" multiple id=\"modelFile\" name=\"modelFile\"/\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"fileSelectorContainer mmdControlerContainer motion row border\"\u003e\n            \u003cdiv\u003eモーションファイルを指定(vmd)\u003c/div\u003e\n            \u003cinput type=\"file\" id=\"motionFile\" name=\"motionFile\"/\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n        \u003cdiv class=\"optionSelector mmdControlerContainer row border\" id=\"charset\"\u003e\n            \u003cdiv class=\"aOption UTF8 row border disabled\"\u003e\n                \u003cp\u003eUTF-8\u003c/p\u003e\n            \u003c/div\u003e\n            \u003cdiv class=\"aOption ShiftJIS row border enabled\"\u003e\n                \u003cp\u003eShift-JIS\u003c/p\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n\n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003cscript type=\"module\"\u003e\n    \n\n    import * as THREE from 'three';\n    import { MMDLoader } from 'three/addons/loaders/MMDLoader.js';\n    import { MMDToonShader } from 'three/addons/shaders/MMDToonShader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n\n    \n    let charset      = \"ShiftJIS\"\n\n    \n    let mainContaier = document.querySelector(\".mmdViewContaier615798324\")\n    let modelFile    = mainContaier.querySelector(\"#modelFile\")\n    let motionFile   = mainContaier.querySelector(\"#motionFile\")\n    let fullscreen   = mainContaier.querySelector(\"#fullscreen\")\n    let charsets     = {\n        \"UTF8\": mainContaier.querySelector(\"#charset\").querySelector(\".aOption.UTF8\"),\n        \"ShiftJIS\": mainContaier.querySelector(\"#charset\").querySelector(\".aOption.ShiftJIS\"),\n    }\n    let mainView     = mainContaier.querySelector(\".mainMMDviewContaier\")\n\n    \n    let MMDcontrolerInsideView  = mainView.querySelector(\".MMDcontrolerInsideView\")\n    let conrtolerButtons        = mainView.querySelector(\".buttonConatiner\")\n    let move                    = conrtolerButtons.querySelector(\"#move\")\n    let exitfullscreen          = conrtolerButtons.querySelector(\"#exitfullscreen\")\n\n\n    \n    const toonShaderMaterial = new THREE.ShaderMaterial(MMDToonShader)\n\n\n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n    let init = true\n\n    mainView.style.width = String(screenSize.width) + \"px\"\n    mainView.style.height = String(screenSize.height) + \"px\"\n    mainView.style.background = \"gray\"\n\n    \n        \n        const scene = new THREE.Scene();\n        scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n        scene.add(new THREE.AxesHelper(50))\n\n        \n        const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n        const renderer = new THREE.WebGLRenderer();\n        renderer.setSize(screenSize.width,screenSize.height);\n        renderer.shadowMap.enabled = true;\n        mainView.appendChild( renderer.domElement );\n\n        \n        const controls = new OrbitControls(camera, renderer.domElement)\n        controls.enableDamping = true\n\n\n        \n        \n        const ambientLight = new THREE.AmbientLight(0xffffff, 1);\n        scene.add(ambientLight);\n        \n\n    \n\n    function findPmxAndPmdFileName(modelFile){\n        for(let file of modelFile.files){\n            if(file.name.includes(\"pmx\") || file.name.includes(\"pmd\")){\n                return file.name\n            }\n        }\n        return null\n    }\n\n    function findZipFile(modelFile){\n        for(let file of modelFile.files){\n            if(file.name.includes(\"zip\")){\n                return file.name\n            }\n        }\n        return null\n    }\n\n    function getZipFileRef(modelFile,filename){\n        for(let file of modelFile.files){\n            if(file.name.includes(\"zip\")){\n                console.log(\"zip found\")\n                console.log(filename)\n                if(filename == file.name){\n                    console.log(\"found\")\n                    return file\n                }\n            }\n        }\n        return null\n    }\n\n    function readShiftJISTextFromBlob(ShiftJIStextArrayBlob){\n        \n        \n        if (typeof TextDecoder !== 'undefined') {\n            const decoder = new TextDecoder('shift-jis');\n            return decoder.decode(ShiftJIStextArrayBlob);\n        } else {\n            throw new Error('TextDecoder が shift-jis に対応していません');\n        }\n        \n    }\n\n    async function readZipForModelFile(modelFile,zipName,fileMap){\n        let zipBlob         = getZipFileRef(modelFile, zipName)\n        let modelFileName   = null\n\n        console.log(zipBlob)\n\n        let zipBlobReader   = new zip.BlobReader(zipBlob);\n        let zipReader       = new zip.ZipReader(zipBlobReader)\n\n        for(let entry of await zipReader.getEntries()){  \n            let filename = null\n            \n            if(charset == \"UTF8\"){\n                filename = entry.filename            \n            }else{\n                filename = readShiftJISTextFromBlob(entry.rawFilename)\n            }          \n            \n            filename = filename.split(\"/\")[filename.split(\"/\").length - 1]\n\n            fileMap.set(filename,URL.createObjectURL(new Blob([await entry.arrayBuffer()])))\n\n            if(filename.includes(\"pmx\") || filename.includes(\"pmd\")){\n                modelFileName = filename\n            }\n\n            console.log(entry)\n            console.log(filename)\n        }\n\n        if(modelFileName == null){\n            return null\n        }\n\n\n        let manager = new THREE.LoadingManager()\n        manager.setURLModifier((url) =\u003e {\n            let filename = url.split(\"/\").pop().split(\"\\\\\").pop()\n            console.log(\"manager is working\")\n            console.log(filename)\n            console.log(fileMap.get(filename))\n            console.log(fileMap.get(filename) || url)\n            return fileMap.get(filename) || url\n        })\n\n        return {\n            \"modelFileName\" : modelFileName,\n            \"manager\" : manager\n        }\n    }\n\n    function addEvent(){\n        modelFile.addEventListener(\"change\",async () =\u003e {\n\n            if(init){\n                init = false\n            }else{\n                \n                scene.children.pop()\n            }\n\n\n            if(modelFile.files.length === 0){\n                return\n            }\n\n\n            \n            let zipName = null\n            zipName = findZipFile(modelFile)\n            \n            \n            let modelName = null \n            modelName = findPmxAndPmdFileName(modelFile)\n            \n            let fileMap = new Map()\n            let manager = null\n            if(zipName != null){\n                \n                let result = await readZipForModelFile(modelFile,zipName,fileMap)\n                if(result == null){\n                    alert(\"Your zip file does not include model file, pmx or mpd.\")\n                    return\n                }\n\n                modelName = result.modelFileName\n                manager   = result.manager\n\n                console.log(modelName)\n                console.log(manager)\n            }else if(modelName != null){\n                \n                for (let file of modelFile.files){\n                    fileMap.set(file.name,URL.createObjectURL(file))\n                }\n\n                manager = new THREE.LoadingManager()\n                manager.setURLModifier((url) =\u003e {\n                    let filename = url.split(\"/\").pop().split(\"\\\\\").pop()\n                    console.log(\"manager is working\")\n                    console.log(filename)\n                    console.log(fileMap.get(filename))\n                    console.log(fileMap.get(filename) || url)\n                    return fileMap.get(filename) || url\n                })\n                \n            }else{\n                alert(\"No model file specified. pmx and pmd will be accepted.\")\n                return\n            }\n\n            console.log(fileMap)\n\n            let mmdloader = new MMDLoader(manager)\n            mmdloader.load(\n                fileMap.get(modelName),\n                (obj) =\u003e {\n                    obj.position.x += 5\n                    obj.position.z += 5\n\n                    scene.add(obj)\n\n                    console.log(scene)\n\n                    \n                    \n                    const box = new THREE.Box3().setFromObject(obj);\n                    const size = box.getSize(new THREE.Vector3()).length();\n                    const center = box.getCenter(new THREE.Vector3());\n\n                    camera.near = size / 100;\n                    camera.far = size * 100;\n                    camera.updateProjectionMatrix();\n\n                    camera.position.copy(center);\n                    camera.position.x += size / 2;\n                    camera.position.y += size / 5;\n                    camera.position.z += size / 2;\n                    controls.target.copy(center);\n                    \n\n                    \n                    function animate() {\n                        renderer.render( scene, camera );\n                        controls.update()\n                    }\n                    renderer.setAnimationLoop( animate );\n                }\n            )\n\n\n        })\n        \n\n        \n        \n        \n        \n        mainView.addEventListener(\"dragover\",(event) =\u003e {\n            event.preventDefault()\n            console.log(\"Something dragover\")\n            console.log(event)\n        })\n\n        mainView.addEventListener(\"drop\",(event) =\u003e {\n            event.preventDefault()\n            console.log(\"Something dropped.\")\n            console.log(event)\n        })\n        \n        \n\n\n\n        motionFile.addEventListener(\"change\",(event) =\u003e {\n            alert(\"Not implemented まだ実装してない\")\n        })\n\n        fullscreen.addEventListener(\"click\",(event) =\u003e {\n            \n            \n            mainView.requestFullscreen()\n        })\n\n        function disableAllCharsetStyle(){\n            for(let AcharsetSelector in charsets){\n                let replacement = charsets[AcharsetSelector].getAttribute(\"class\").replaceAll(\" enabled\",\"\")\n                if(!replacement.includes(\"disabled\")){\n                    replacement += \" disabled\"    \n                }\n                charsets[AcharsetSelector].setAttribute(\"class\",replacement)\n            }\n        }\n        function enableCharsetStyle(elem){\n            let replacement = elem.getAttribute(\"class\").replaceAll(\" disabled\",\"\")\n            if(!replacement.includes(\"enabled\")){\n                replacement += \" enabled\"\n            }\n            elem.setAttribute(\"class\",replacement)\n        }\n        charsets.ShiftJIS.addEventListener(\"click\",() =\u003e {\n            if(charset == \"ShiftJIS\"){\n                \n            }else{\n                disableAllCharsetStyle()\n                charset = \"ShiftJIS\"\n                enableCharsetStyle(charsets.ShiftJIS)\n            }\n            console.log(\"Charset is changed to: \")\n            console.log(charset)\n        })\n        charsets.UTF8.addEventListener(\"click\",() =\u003e {\n            if(charset == \"UTF8\"){\n                \n            }else{\n                disableAllCharsetStyle()\n                charset = \"UTF8\"\n                enableCharsetStyle(charsets.UTF8)\n            }\n            console.log(\"Charset is changed to: \")\n            console.log(charset)\n        })\n\n\n        \n        exitfullscreen.addEventListener(\"click\",() =\u003e {\n            if(!document.fullscreenElement) return\n            document.exitFullscreen()\n        })\n\n        let prevPos = {\n            x: 0,\n            y: 0\n        }\n        let onControlerMove = false\n        move.addEventListener(\"touchstart\",(event) =\u003e {\n            onControlerMove = true\n            let touch = event.touches.item(0)\n            prevPos.x = touch.screenX\n            prevPos.y = touch.screenY\n        })\n        addEventListener(\"touchmove\",(event) =\u003e {\n            if(!onControlerMove) return \n            event.preventDefault()\n            let touch = event.touches.item(0)\n            \n            let dx    = touch.screenX - prevPos.x\n            let dy    = touch.screenY - prevPos.y\n\n            prevPos.x = touch.screenX\n            prevPos.y = touch.screenY\n\n            let right    = Number(MMDcontrolerInsideView.style.right.replaceAll(\"px\",\"\"))\n            let bottom   = Number(MMDcontrolerInsideView.style.bottom.replaceAll(\"px\",\"\"))\n\n            MMDcontrolerInsideView.style.right    = String(right - dx) + \"px\"\n            MMDcontrolerInsideView.style.bottom   = String(bottom - dy) + \"px\"\n        })\n        addEventListener(\"touchend\",(event) =\u003e {\n            onControlerMove = false\n        })\n        move.addEventListener(\"mousedown\",(event) =\u003e {\n            onControlerMove = true\n            prevPos.x = event.screenX\n            prevPos.y = event.screenY\n        })\n        addEventListener(\"mousemove\",(event) =\u003e {\n            if(!onControlerMove) return \n            event.preventDefault()\n\n            let dx  = event.screenX - prevPos.x\n            let dy  = event.screenY - prevPos.y\n\n            prevPos.x = event.screenX\n            prevPos.y = event.screenY\n\n            let right    = Number(MMDcontrolerInsideView.style.right.replaceAll(\"px\",\"\"))\n            let bottom   = Number(MMDcontrolerInsideView.style.bottom.replaceAll(\"px\",\"\"))\n\n            MMDcontrolerInsideView.style.right    = String(right - dx) + \"px\"\n            MMDcontrolerInsideView.style.bottom   = String(bottom - dy) + \"px\"\n        })\n        addEventListener(\"mouseup\",(event) =\u003e {\n            onControlerMove = false\n        })\n\n        function screenOrientation(){\n            let ratio           = window.innerWidth / window.innerHeight\n            let fileselectors   = mainContaier.querySelectorAll(\".fileSelectorContainer\")\n            if(ratio \u003c 1){\n                \n                for(let selector of fileselectors){\n                    let replacement = selector.getAttribute(\"class\").replaceAll(\" row\",\"\")\n                    if(!replacement.includes(\"column\")) replacement += \" column\"\n                    selector.setAttribute(\"class\",replacement) \n                }\n            }else{\n                \n                for(let selector of fileselectors){\n                    let replacement = selector.getAttribute(\"class\").replaceAll(\" column\",\"\")\n                    if(!replacement.includes(\"row\")) replacement += \" row\"\n                    selector.setAttribute(\"class\",replacement) \n                }\n            }\n        }\n\n        addEventListener(\"resize\",() =\u003e { \n            screenOrientation()\n        })\n        addEventListener(\"DOMContentLoaded\", () =\u003e {\n            screenOrientation()\n        })\n\n\n\n\n        function showAnimation(){\n            let animation = [\n                {opacity: 0.5},\n                {opacity: 1}\n            ]\n\n            let timeSetting = {\n                duration: 1000, \n                iterations: 1\n            }\n\n            MMDcontrolerInsideView.style.opacity = 1\n            MMDcontrolerInsideView.animate(animation,timeSetting)\n            MMDcontrolerInsideView.getAnimations()[0].id = \"show\"\n        }\n        function transparentAnimation(){\n            let animation = [\n                {opacity: 1},\n                {opacity: 0.5},\n            ]\n\n            let timeSetting = {\n                duration: 1000, \n                iterations: 1\n            }\n\n            MMDcontrolerInsideView.style.opacity = 0.5\n            MMDcontrolerInsideView.animate(animation,timeSetting)\n            MMDcontrolerInsideView.getAnimations()[0].id = \"transparent\"\n        }\n\n        let animationTime = 0\n        let animationTimeStampList = []\n        function animationLoopForControler(init = true,timstamp = Date.now(),timeinit = 1200){ \n            let animations = MMDcontrolerInsideView.getAnimations()\n\n            console.log(init)\n            console.log(animationTime)\n            console.log(animationTimeStampList)\n\n            if(init) {\n                if(animations.length == 0){\n                    showAnimation()\n                }\n                animationTimeStampList.push(timstamp)\n                animationTime = timeinit\n            }else{\n                if(animationTime \u003c 0) {\n                    if(animations.length == 0){\n                        console.log(\"transparentAnimation\")\n                        transparentAnimation()\n                    }\n                    animationTimeStampList = []\n                    return\n                }\n\n                \n                for(let Atimestamp of animationTimeStampList){\n                    console.log(String(timstamp) + \" \u003c \" + String(Atimestamp) + String(timstamp.toPrecision() \u003c Atimestamp.toPrecision()))\n                    if(timstamp \u003c Atimestamp){\n                        console.log(\"find new timestamp\")\n                        animationTime = timeinit\n                        return\n                    }\n                }\n            }\n\n            animationTime -= 60 \n            setTimeout(() =\u003e {animationLoopForControler(false,timstamp)},60)\n        }\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n        MMDcontrolerInsideView.style.opacity = 0.5\n\n        \n\n        \n        MMDcontrolerInsideView.style.display = \"none\"\n        mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n            let width = 0\n            let height = 0\n\n            if(document.fullscreenElement){\n                width   = window.innerWidth\n                height  = window.outerHeight\n\n                MMDcontrolerInsideView.style.right  = \"10px\"\n                MMDcontrolerInsideView.style.bottom = \"10px\"\n\n                MMDcontrolerInsideView.style.display = \"\"\n            }else{\n                width   = screenSize.width\n                height  = screenSize.height\n\n                MMDcontrolerInsideView.style.display = \"none\"\n            }\n\n            \n            \n            console.log(width)\n            console.log(height)\n\n            renderer.setPixelRatio(window.devicePixelRatio);\n            renderer.setSize(width, height);\n\n            \n            camera.aspect = width / height;\n            camera.updateProjectionMatrix();\n            \n        })\n    }\n\n    addEvent()\n\u003c/script\u003e\u003c/p\u003e","title":"MMD Viewer"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 正直、私は卒業研究の過程で、Onenote代替品の作成として、OneNoteのような UI/UX や利便性を持ち、そのほかの類似ソフトウェアと比較して、不満点をまとめ上げ、それについて新しいアーキテクチャやシステム、実装を考えて、ソフトウェアを実装するということを研究にしようとしていたが、研究になるのか不安になっている。\nもちろん、OneNoteの代替品は欲しいし、作りたいし、情報を整理できる、吐き出せ、具現化しやすい補助ツールは大事だと思うし、それを基盤にほかに研究にしたいことをやりたいし、でも時間がかかって大変なことなので、ただ個人でやるより、研究などにしてそれを作る時間を稼ぎたいというのもある。\n人によっては、「研究をなめているのか」とか、「君は研究というものを一つもわかっちゃいない」とか、「君には研究は絶対にできない」とか暗に遠回しに突っ返されるような、あまり理解されないような理想が私のやろうとしていることにはある気もする。\nそもそも OneNote代替の研究案って、OneNote が基本課金を前提としていて、いろいろ技術的に閉じられたところに不満があることに加え、単に機能的に不便を感じたり、不足を感じていているところもあり、自分で好みのツールを作りたいという非常に個人的な動機からのスタートであり、そもそも卒業研究以前の学部生時代にずっと考えていて、コードを考えたりしてはとん挫したり、こうなんていうか目立って前進できない行き詰ったところがあった。\nこのような、個人的な動機で、かつ多くの卒業研究をやる人がやるような前例踏襲的な、何かしらの研究を引き継いで拡張するようなやり方とは外れるような、挑戦的な内容は果たしてどこまで研究として成り立つのかといった感じである。\nまあ不安であることは変わりないので、今やろうとしていることをどうするか現状未定であるが、研究になりやすそうな案を吐き出したら、今回の案が浮かんだというだけの話。現状はあくまでただ案を置いているにすぎないが。。。\nまあ、基本的にあまりに早い段階で投げ出してしまっても仕方ないし、不安ながらでも続けるくらいのスタンスはしばらくもっておきたいとは思っているので、Onenote代替品の作成について今のところあきらめる気はないけど。\nリポジトリ なぜ思いついたのか すごく簡単に正直に言えば、ChatGPTのモデルの挙動がうざいというところがある。どう考えてもポジティブ過ぎるし、なんか何を言っても、”あなたは間違っていません”というメッセージ性のある返答が返ってきて、使っているうちにイライラしてくるということが多い。\nだんだんと、ChatGPTなどのLLMは出力が偏っているとわかっていて、”根拠なきそれっぽい自信”をあえて得るみたいな使い方や、即興性を得たいとき、何か記事とか作った時の簡易的な文法ミスや誤字といった小さなミスの確認といった、くらいしか正直まともに使えないなと、感じてきていた。\nそれで、そのような AIモデルが偏った出力をすることに対し、可視化するツールを簡単に作ったらいいよねと思いついて、それって定量化し易そうだし、研究にしやすそうだなと思った次第。\n具体的な考え 簡単な考えられる仕組みとしては、ChatGPTを含むLLMの出力を自然言語処理にかけて、単語ごとなどに分割し、事前に用意したポジティブワードリストとかネガティブワードリストとそれら単語を比較し、どれだけ出力が偏っているか分析することである。\nポジティブ、ネガティブな言葉の語数を計算したり、ポジティブ、ネガティブな言葉に対して、CSS とかで色を付けることで、視覚的にどれだけLLMの出力が偏っているか表示する chrome拡張機能 とか作ってみてもいいよねって思ったりしてた。\nほかにも、「絶対、完全、間違っていない」などの言い切りの言葉など、様々なユーザを引っ張り、感情的にあおるような言葉を可視化できると、LLMに興ざめることができる気がしている。過度な期待を破壊するというか。\n追記 2025年8月11?日 プロンプト自体の偏りも考慮する必要がある。プロンプトの偏りと、LLMの出力の偏りの相関関係について調べるなどが、研究になりそうである。\n2025年8月19日 LLMの出力の定性的な偏りを定量的にはかることには限界がある。また人や地域によって何を偏っているとするかは異なる。今回の案は、あくまで利用者に対して、AIモデルには偏りがあることを前提として、その偏りを可視化する助けとして、参照できるヒントがあるといいなくらいの立ち位置になるかも？厳密な偏りの検出や可視化ということにはならないことを留意する必要はあるし、その点自体について何か研究できることがあればいいかもしれない。\n2025年8月20日 具体的に何を偏っているとするのが、研究する前に定義しておいて、なるべく明確にしておく必要がある。判別に使う辞書リストみたいなものはベースや研究で使う段階としては、市販されている辞書などを参考にするみたいになるかもしれない。最終的にはユーザが自由に任意のリストを分析に使えるようにしたいと思う。\n参考にしたサイトとか 今のところ特に論文とか全然調査できてないし、特になし。強いて言えば、chatGPTを使っているうちに思い付いたという意味では、ChatGPTを参考にしたといえるかもしれない。\nChatGPT\nhttps://chatgpt.com/ (2025年8月5日) ","permalink":"https://www.nyanmo.info/posts/idea/research/aimodelbiasanalyzer/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　正直、私は卒業研究の過程で、\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/\"\u003eOnenote代替品の作成\u003c/a\u003eとして、OneNoteのような UI/UX や利便性を持ち、そのほかの類似ソフトウェアと比較して、不満点をまとめ上げ、それについて新しいアーキテクチャやシステム、実装を考えて、ソフトウェアを実装するということを研究にしようとしていたが、研究になるのか不安になっている。\u003c/p\u003e\n\u003cp\u003e　もちろん、OneNoteの代替品は欲しいし、作りたいし、情報を整理できる、吐き出せ、具現化しやすい補助ツールは大事だと思うし、それを基盤にほかに研究にしたいことをやりたいし、でも時間がかかって大変なことなので、ただ個人でやるより、研究などにしてそれを作る時間を稼ぎたいというのもある。\u003c/p\u003e\n\u003cp\u003e　人によっては、「研究をなめているのか」とか、「君は研究というものを一つもわかっちゃいない」とか、「君には研究は絶対にできない」とか暗に遠回しに突っ返されるような、あまり理解されないような理想が私のやろうとしていることにはある気もする。\u003c/p\u003e\n\u003cp\u003e　そもそも OneNote代替の研究案って、OneNote が基本課金を前提としていて、いろいろ技術的に閉じられたところに不満があることに加え、単に機能的に不便を感じたり、不足を感じていているところもあり、自分で好みのツールを作りたいという非常に個人的な動機からのスタートであり、そもそも卒業研究以前の学部生時代にずっと考えていて、コードを考えたりしてはとん挫したり、こうなんていうか目立って前進できない行き詰ったところがあった。\u003c/p\u003e\n\u003cp\u003e　このような、個人的な動機で、かつ多くの卒業研究をやる人がやるような前例踏襲的な、何かしらの研究を引き継いで拡張するようなやり方とは外れるような、挑戦的な内容は果たしてどこまで研究として成り立つのかといった感じである。\u003c/p\u003e\n\u003cp\u003e　まあ不安であることは変わりないので、今やろうとしていることをどうするか現状未定であるが、研究になりやすそうな案を吐き出したら、今回の案が浮かんだというだけの話。現状はあくまでただ案を置いているにすぎないが。。。\u003c/p\u003e\n\u003cp\u003e　まあ、基本的にあまりに早い段階で投げ出してしまっても仕方ないし、不安ながらでも続けるくらいのスタンスはしばらくもっておきたいとは思っているので、\u003ca href=\"https://www.nyanmo.info/posts/idea/research/onenotealternativecreation/\"\u003eOnenote代替品の作成\u003c/a\u003eについて今のところあきらめる気はないけど。\u003c/p\u003e\n\u003ch2 id=\"リポジトリ\"\u003eリポジトリ\u003c/h2\u003e\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"githubCardContainer\" href=https://github.com/hello30190f/LLM-bias-visualization\u003e\n    \u003cdiv class=\"githubCardContainerInner row\"\u003e\n        \u003cdiv class=\"avaterImage column\"\u003e\n            \u003cimg class=\"avaterImageMain\" src=\"\" alt=\"\"\u003e\n            \u003cdiv class=\"userName\" src=\"\" alt=\"\"\u003e\u003c/div\u003e\n        \u003c/div\u003e\n\n        \u003cdiv class=\"repoInfo column\"\u003e\n            \u003cdiv class=\"repoName\"\u003e\u003c/div\u003e\n            \u003cdiv class=\"repoDiscription\"\u003e\u003c/div\u003e\n\n            \u003cdiv class=\"repoClone column\"\u003e\n                \u003cdiv class=\"http cloneOption row\"\u003e\n                    \u003cinput id=\"url\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n                \u003cdiv class=\"ssh cloneOption row\"\u003e\n                    \u003cinput id=\"ssh\" type=\"text\" readonly\u003e\n                    \u003cbutton class=\"copy\"\u003e\u003c/button\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"なぜ思いついたのか\"\u003eなぜ思いついたのか\u003c/h2\u003e\n\u003cp\u003e　すごく簡単に正直に言えば、ChatGPTのモデルの挙動がうざいというところがある。どう考えてもポジティブ過ぎるし、なんか何を言っても、”あなたは間違っていません”というメッセージ性のある返答が返ってきて、使っているうちにイライラしてくるということが多い。\u003c/p\u003e\n\u003cp\u003e　だんだんと、ChatGPTなどのLLMは出力が偏っているとわかっていて、”根拠なきそれっぽい自信”をあえて得るみたいな使い方や、即興性を得たいとき、何か記事とか作った時の簡易的な文法ミスや誤字といった小さなミスの確認といった、くらいしか正直まともに使えないなと、感じてきていた。\u003c/p\u003e\n\u003cp\u003e　それで、そのような AIモデルが偏った出力をすることに対し、可視化するツールを簡単に作ったらいいよねと思いついて、それって定量化し易そうだし、研究にしやすそうだなと思った次第。\u003c/p\u003e\n\u003ch2 id=\"具体的な考え\"\u003e具体的な考え\u003c/h2\u003e\n\u003cp\u003e　簡単な考えられる仕組みとしては、ChatGPTを含むLLMの出力を自然言語処理にかけて、単語ごとなどに分割し、事前に用意したポジティブワードリストとかネガティブワードリストとそれら単語を比較し、どれだけ出力が偏っているか分析することである。\u003c/p\u003e\n\u003cp\u003e　ポジティブ、ネガティブな言葉の語数を計算したり、ポジティブ、ネガティブな言葉に対して、CSS とかで色を付けることで、視覚的にどれだけLLMの出力が偏っているか表示する chrome拡張機能 とか作ってみてもいいよねって思ったりしてた。\u003c/p\u003e\n\u003cp\u003e　ほかにも、「絶対、完全、間違っていない」などの言い切りの言葉など、様々なユーザを引っ張り、感情的にあおるような言葉を可視化できると、LLMに興ざめることができる気がしている。過度な期待を破壊するというか。\u003c/p\u003e\n\u003ch2 id=\"追記\"\u003e追記\u003c/h2\u003e\n\u003ch3 id=\"2025年8月11日\"\u003e2025年8月11?日\u003c/h3\u003e\n\u003cp\u003e　プロンプト自体の偏りも考慮する必要がある。プロンプトの偏りと、LLMの出力の偏りの相関関係について調べるなどが、研究になりそうである。\u003c/p\u003e\n\u003ch3 id=\"2025年8月19日\"\u003e2025年8月19日\u003c/h3\u003e\n\u003cp\u003e　LLMの出力の定性的な偏りを定量的にはかることには限界がある。また人や地域によって何を偏っているとするかは異なる。今回の案は、あくまで利用者に対して、AIモデルには偏りがあることを前提として、その偏りを可視化する助けとして、参照できるヒントがあるといいなくらいの立ち位置になるかも？厳密な偏りの検出や可視化ということにはならないことを留意する必要はあるし、その点自体について何か研究できることがあればいいかもしれない。\u003c/p\u003e\n\u003ch3 id=\"2025年8月20日\"\u003e2025年8月20日\u003c/h3\u003e\n\u003cp\u003e　具体的に何を偏っているとするのが、研究する前に定義しておいて、なるべく明確にしておく必要がある。判別に使う辞書リストみたいなものはベースや研究で使う段階としては、市販されている辞書などを参考にするみたいになるかもしれない。最終的にはユーザが自由に任意のリストを分析に使えるようにしたいと思う。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今のところ特に論文とか全然調査できてないし、特になし。強いて言えば、chatGPTを使っているうちに思い付いたという意味では、ChatGPTを参考にしたといえるかもしれない。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年8月5日)\u003c/li\u003e\n\u003c/ul\u003e","title":"LLM の出力結果の偏りを可視化するツールの開発"},{"content":"この記事を作った動機 単に今までめんどくさくて放置していた、Windows と Linux の デュアルブート環境において、GRUB を利用しているとき、Windows OS の選択肢が出てこないということについて、対応した時にわかったことを記録したいというだけ。\nちなみに今回の作業をするまでは単に BIOS 側で、.efi ファイルを指定することで、Linuxを起動するエントリと、Windowsを起動するエントリを作って、BIOSのブートメニューで選択していた。\nなお今回の記事では前提として、GRUB が入っており、以下に示すコマンドはすでに使えることを想定している。\ngrub-install grub-mkconfig 環境 System Details Report（GNOME settings からのコピペ） Report details Date generated: 2025-08-04 14:45:58 Hardware Information: Hardware Model: Dell Inc. XPS 15 9575 Memory: 16.0 GiB Processor: Intel® Core™ i7-8705G × 8 Graphics: Intel® HD Graphics 630 (KBL GT2) Disk Capacity: (null) Software Information: Firmware Version: 1.20.0 OS Name: Arch Linux OS Build: rolling OS Type: 64-bit GNOME Version: 48 Windowing System: Wayland Kernel Version: Linux 6.15.7-arch1-1 パティーション構成 どんなパーティション構成で、デュアルブートを構成しているかも示す。Windows も Linux もどちら側も UEFI で動作しており、それぞれ個別に起動用の EFI パーティションを持っているという構成である。\nこの構成には理由が三つほど存在する。\n一つ目は、単に後から、Linux をインストールしており、パーティションのサイズを変えたり、位置を移動したりするのは面倒であるということがある。\n二つ目は、Windows がデフォルトで生成した EFI パーティションを使うと、サイズがたったの 100MB しかないため、カーネルやらなにやらがそこに配置されると、すぐにディスクの空き容量が足りなくなってしまうことがある。\n三つ目は、Windows がデフォルトで生成した EFI パーティションを使うと、Linux 側と Windows 側でファイルがごちゃごちゃになり、いざというときの整備性が低く感じられたことがある。\nsudo fdisk -l # ディスク /dev/nvme0n1: 1.86 TiB, 2048408248320 バイト, 4000797360 セクタ # ディスク型式: SOLIDIGM SSDPFKNU020TZ # 単位: セクタ (1 * 512 = 512 バイト) # セクタサイズ (論理 / 物理): 512 バイト / 512 バイト # I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト # ディスクラベルのタイプ: gpt # ディスク識別子: 一応秘匿 # デバイス 開始位置 終了位置 セクタ サイズ タイプ # /dev/nvme0n1p1 2048 206847 204800 100M EFI システム # /dev/nvme0n1p2 206848 239615 32768 16M Microsoft 予約領域 # /dev/nvme0n1p3 239616 1997969407 1997729792 952.6G Microsoft 基本データ # /dev/nvme0n1p4 1997969408 2000402431 2433024 1.2G Windows リカバリ環境 # /dev/nvme0n1p5 2000402432 2002499583 2097152 1G EFI システム # /dev/nvme0n1p6 2002499584 3952850943 1950351360 930G Linux ファイルシステム # /dev/nvme0n1p7 3952850944 4000796671 47945728 22.9G Linux ファイルシステム Windows 環境 # /dev/nvme0n1p1 2048 206847 204800 100M EFI システム # /dev/nvme0n1p2 206848 239615 32768 16M Microsoft 予約領域 # /dev/nvme0n1p3 239616 1997969407 1997729792 952.6G Microsoft 基本データ # /dev/nvme0n1p4 1997969408 2000402431 2433024 1.2G Windows リカバリ環境 Linux 環境 # /dev/nvme0n1p5 2000402432 2002499583 2097152 1G EFI システム # /dev/nvme0n1p6 2002499584 3952850943 1950351360 930G Linux ファイルシステム # /dev/nvme0n1p7 3952850944 4000796671 47945728 22.9G Linux ファイルシステム インストールするパッケージ fuse3 ntfs-3g os-prober yay -S fuse3 ntfs-3g os-prober # sudo pacman -S fuse3 ntfs-3g os-prober ちなみに、これらが入ってないと、そもそも別の OS を検出しようとしない。\n/etc/default/grub の変更 # os-prober を有効化する GRUB_DISABLE_OS_PROBER=false os-prober が正しく有効になっているときの例 grub-mkconfigにおいて正しく OS を検出できている例を一応おいておく。\nsudo grub-mkconfig -o /boot/grub/grub.cfg # Generating grub configuration file ... # テーマを見つけました: /usr/share/grub/themes/tela/theme.txt # Linux イメージを見つけました: /boot/vmlinuz-linux # Found initrd image: /boot/initramfs-linux.img # Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img # Warning: os-prober will be executed to detect other bootable partitions. # Its output will be used to detect bootable binaries on them and create new boot entries. # Found Windows Boot Manager on /dev/nvme0n1p1@/efi/Microsoft/Boot/bootmgfw.efi # Adding boot menu entry for UEFI Firmware Settings ... # 完了 以下の部分があることから、正しく検出されていることがわかる。何らかの理由で os-prober が機能していない場合、このような出力は出ない。\n# Warning: os-prober will be executed to detect other bootable partitions. # Its output will be used to detect bootable binaries on them and create new boot entries. # Found Windows Boot Manager on /dev/nvme0n1p1@/efi/Microsoft/Boot/bootmgfw.efi # Adding boot menu entry for UEFI Firmware Settings ... 参考にしたサイトとか GRUB - ArchWiki\nhttps://wiki.archlinux.org/title/GRUB#Detecting_other_operating_systems (2025年8月4日) Grub/os-prober not detecting Windows : r/archlinux\nhttps://www.reddit.com/r/archlinux/comments/ud7dao/grubosprober_not_detecting_windows/ (2025年8月4日) [Solved] GRUB and os-prober do not see Windows 10 on a different drive / Newbie Corner / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=240117 (2025年8月4日) ","permalink":"https://www.nyanmo.info/posts/linux/grubwithwindows/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に今までめんどくさくて放置していた、Windows と Linux の デュアルブート環境において、GRUB を利用しているとき、Windows OS の選択肢が出てこないということについて、対応した時にわかったことを記録したいというだけ。\u003c/p\u003e\n\u003cp\u003e　ちなみに今回の作業をするまでは単に BIOS 側で、.efi ファイルを指定することで、Linuxを起動するエントリと、Windowsを起動するエントリを作って、BIOSのブートメニューで選択していた。\u003c/p\u003e\n\u003cp\u003e　なお今回の記事では前提として、GRUB が入っており、以下に示すコマンドはすでに使えることを想定している。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003egrub-install\u003c/li\u003e\n\u003cli\u003egrub-mkconfig\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"system-details-reportgnome-settings-からのコピペ\"\u003eSystem Details Report（GNOME settings からのコピペ）\u003c/h3\u003e\n\u003ch4 id=\"report-details\"\u003eReport details\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2025-08-04 14:45:58\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"hardware-information\"\u003eHardware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              Dell Inc. XPS 15 9575\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      16.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Core™ i7-8705G × 8\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Intel® HD Graphics 630 (KBL GT2)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               (null)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"software-information\"\u003eSoftware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            1.20.0\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    rolling\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               48\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.15.7-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"パティーション構成\"\u003eパティーション構成\u003c/h3\u003e\n\u003cp\u003e　どんなパーティション構成で、デュアルブートを構成しているかも示す。Windows も Linux もどちら側も UEFI で動作しており、それぞれ個別に起動用の EFI パーティションを持っているという構成である。\u003c/p\u003e","title":"GRUB で Windows も起動する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 とりあえず案だけ置いている。なんとなく大量のダウンロードした動画、画像を分類するのはめんどく臭いと思った次第。（でもまあAIモデルを作るのも大概大変だろうけど。。。）ユーザのタグ付け傾向から自動的にモデル学習して分類やタグ付けのサジェスチョンを複数の動画、画像に対して出せて修正し、確定できるみたいな仕組みとか面白そうではある。\n参考にしたサイトとか 今のところ特になし\n","permalink":"https://www.nyanmo.info/posts/idea/research/ai-modelclassificationsystem/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　とりあえず案だけ置いている。なんとなく大量のダウンロードした動画、画像を分類するのはめんどく臭いと思った次第。（でもまあAIモデルを作るのも大概大変だろうけど。。。）ユーザのタグ付け傾向から自動的にモデル学習して分類やタグ付けのサジェスチョンを複数の動画、画像に対して出せて修正し、確定できるみたいな仕組みとか面白そうではある。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今のところ特になし\u003c/p\u003e","title":"AIモデルを利用した画像（サムネ）による、動画の自動識別、分類、タグ付けシステム"},{"content":"この記事を作った動機 libvirtを使った仮想環境で、ファイヤウォールの設定をしないと、仮想マシンがネットにつながらないので、その記録をするだけ。\nやり方 仮想マシンとのインタフェースを確認する ip a # ... # 8: virbr0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc htb state UP group default qlen 1000 # link/ether 52:54:00:2d:fb:f7 brd ff:ff:ff:ff:ff:ff # inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0 # valid_lft forever preferred_lft forever # ... ファイヤウォールを設定する インタフェース名が、virbr0 であることを想定する。\nsudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -i virbr0 -j ACCEPT sudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -o virbr0 -j ACCEPT # sudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -i [ネットワークインタフェース名] -j ACCEPT # sudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -o [ネットワークインタフェース名] -j ACCEPT sudo systemctl restart firewalld 参考にしたサイトとか Firewall blocks internet on bridge in KVM virtual machine - English / Network/Internet - openSUSE Forums\nhttps://forums.opensuse.org/t/firewall-blocks-internet-on-bridge-in-kvm-virtual-machine/138737 (2025年8月2日) ","permalink":"https://www.nyanmo.info/posts/linux/libvirtdfirewallsetting/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　libvirtを使った仮想環境で、ファイヤウォールの設定をしないと、仮想マシンがネットにつながらないので、その記録をするだけ。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003ch3 id=\"仮想マシンとのインタフェースを確認する\"\u003e仮想マシンとのインタフェースを確認する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eip a\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 8: virbr0: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc htb state UP group default qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/ether 52:54:00:2d:fb:f7 brd ff:ff:ff:ff:ff:ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ファイヤウォールを設定する\"\u003eファイヤウォールを設定する\u003c/h3\u003e\n\u003cp\u003e　インタフェース名が、\u003ccode\u003evirbr0\u003c/code\u003e であることを想定する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -i virbr0 -j ACCEPT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -o virbr0 -j ACCEPT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -i [ネットワークインタフェース名] -j ACCEPT\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo firewall-cmd --permanent --direct --passthrough ipv4 -I FORWARD -o [ネットワークインタフェース名] -j ACCEPT\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart firewalld\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eFirewall blocks internet on bridge in KVM virtual machine - English / Network/Internet - openSUSE Forums\u003cbr\u003e\n\u003ca href=\"https://forums.opensuse.org/t/firewall-blocks-internet-on-bridge-in-kvm-virtual-machine/138737\"\u003ehttps://forums.opensuse.org/t/firewall-blocks-internet-on-bridge-in-kvm-virtual-machine/138737\u003c/a\u003e (2025年8月2日)\u003c/li\u003e\n\u003c/ul\u003e","title":"libvirtd のファイヤウォール設定"},{"content":"この記事を作った動機 ネットワークドライブがつながらないとき、再接続しようと思うと、記録がない場合不便すぎたので記録するだけ。\nやり方 前提として、以下の項目を置いておく\nZ: ドライブ 192.168.1.33 SMB サーバの IP datafolder マウントポイント 接続 net use Z: \\\\192.168.1.33\\datafolder /USER:[UserName] [Password] 削除 net use Z: /Delete 参考にしたサイトとか Net use | Microsoft Learn\nhttps://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/gg651155(v=ws.11) (2025年8月2日) Deleting Mapped network drive - Microsoft Q\u0026amp;A\nhttps://learn.microsoft.com/en-us/answers/questions/3253887/deleting-mapped-network-drive?forum=windows-all\u0026amp;referrer=answers (2025年8月2日) ","permalink":"https://www.nyanmo.info/posts/windows/networkdrivecmd/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　ネットワークドライブがつながらないとき、再接続しようと思うと、記録がない場合不便すぎたので記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　前提として、以下の項目を置いておく\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003eZ:\u003c/code\u003e            ドライブ\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e192.168.1.33\u003c/code\u003e  SMB サーバの IP\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edatafolder\u003c/code\u003e    マウントポイント\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"接続\"\u003e接続\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet use Z: \\\\192.168.1.33\\datafolder /USER:[UserName] [Password]\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"削除\"\u003e削除\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet use Z: /Delete\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eNet use | Microsoft Learn\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/gg651155(v=ws.11)\"\u003ehttps://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-r2-and-2012/gg651155(v=ws.11)\u003c/a\u003e (2025年8月2日)\u003c/li\u003e\n\u003cli\u003eDeleting Mapped network drive - Microsoft Q\u0026amp;A\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/en-us/answers/questions/3253887/deleting-mapped-network-drive?forum=windows-all\u0026amp;referrer=answers\"\u003ehttps://learn.microsoft.com/en-us/answers/questions/3253887/deleting-mapped-network-drive?forum=windows-all\u0026amp;referrer=answers\u003c/a\u003e (2025年8月2日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ネットワークドライブの削除と作成"},{"content":"この記事を作った動機 cron を使ってみようと思って重い腰を持ち上げてみたら、意図したとおりにうまく動かせずにつまずいたのでその記録をとるだけ。うまくわかった気がしないし、間違いがあるかもしれないが、ご了承ください。\ncron の構造 # 分 時 日(一か月単位) 月 日(一週間単位) * * * * * /path/to/script.sh cron の内容の編集、確認 編集 # デフォルトは vi が使われるため、vi をインストールしておいたほうが良いかもしれないが、それ以外のエディタも使える。 crontab -e 確認 crontab -l # * * * * * /path/to/script.sh # * * * * * /path/to/script.sh # ... 確認事項 cron はインストールされているか？ yay -Qs cron # pacman -Qs cron # local/cronie 1.7.2-1 # Daemon that runs specified programs at scheduled times and related tools エディターを設定したか？ デフォルトだと vi が利用されるようになっており、不便なことがあると思うので設定した方がいいかも。\n# neovim -\u0026gt; \u0026#34;nvim\u0026#34; に設定 # visual studio code -\u0026gt; \u0026#34;code\u0026#34; に設定 export EDITOR=nvim echo $EDITOR # nvim cron サービスが実行されているか？ 確認 systemctl status cronie # systemctl status crond # ● cronie.service - Command Scheduler # Loaded: loaded (/usr/lib/systemd/system/cronie.service; enabled; preset: disabled) # Active: active (running) since Mon 2025-07-28 21:53:50 JST; 1h 7min ago # Invocation: 748b761f9921445f8a759eb430f3507f # Main PID: 354161 (crond) # Tasks: 2 (limit: 629145) # Memory: 1.3M (peak: 4.5M) # CPU: 1.667s # CGroup: /system.slice/cronie.service # ├─354161 /usr/sbin/crond -n # └─355485 /usr/sbin/anacron -s # # 7月 28 22:58:00 hostName CROND[361012]: (username) CMDEND (/path/to/script.sh) # 7月 28 22:58:00 hostName CROND[361012]: pam_unix(crond:session): session closed for user username # 7月 28 22:59:00 hostName crond[361097]: pam_unix(crond:session): session opened for user username(uid=1000) by username(uid=0) # ... 有効化 systemctl enable --now cronie # systemctl enable --now crond 例（crontab -l の内容） 毎分実行 * * * * * /path/to/script.sh 各時間 5 分目に実行 0時 5分に実行\n1時 5分に実行\n2時 5分に実行\n\u0026hellip;\n5 * * * * /path/to/script.sh 毎日 5:00 ~ 5:59 に毎分実行 * 5 * * * /path/to/script.sh 毎月 5 日目に毎分実行 * * 5 * * /path/to/script.sh 5 月中に毎分実行 1月 2月 3月 4月 5月 6月 7月 8月 9月 10月 11月 12月 1 2 3 4 5 6 7 8 9 10 11 12 * * * 5 * /path/to/script.sh 毎週 5 日目(金曜日)に毎分実行 日曜日 月曜日 火曜日 水曜日 木曜日 金曜日 土曜日 0 1 2 3 4 5 6 * * * * 5 /path/to/script.sh crontab.guru（おまけ） なんか、cronの使い方について調べている過程で、GUIベースのcron管理ツールがあったので、そのインストールと起動方法について簡単に書くだけ。\nインストール curl https://crontab.guru/install | sh ユーザ名とパスワードを設定 sudo cronitor dash --port 9000 # Dashboard credentials are not configured. # Please set a username and password for dashboard access. # These credentials will be saved to your configuration file and can be updated later from the Settings screen. # Enter dashboard username: ユーザ名を入力 # Enter dashboard password: パスワードを入力 # Credentials saved to: /etc/cronitor/cronitor.json # Please run \u0026#39;cronitor dash\u0026#39; again to start the dashboard. もう一回実行すると sudo cronitor dash --port 9000 # デフォルトだと root ユーザの cron を見てしまうようなので、-u でユーザー名を指定するとより意図したとおりになるかも？ # sudo cronitor dash --port 9000 -u [username] # Starting Cronitor dashboard on port 9000... # Opening browser to http://localhost:9000... # Dashboard running on http://localhost:9000 (Press Ctrl+C to stop) ブラウザで開く 今回は、\u0026ndash;port 9000 と指定したので、\u0026ldquo;http://localhost:9000\u0026quot;を、対象のcronが実行されているPC上で開く。basic 認証に設定しておいたユーザ名とパスワードを入れれば、以下のようにダッシュボードを利用できる。 関係のありそうなページ yay コマンドのインストール 参考にしたサイトとか Crontab.guru - The cron schedule expression generator\nhttps://crontab.guru/ (2025年7月28日) ChatGPT\nhttps://chatgpt.com/ (2025年7月28日) cron - ArchWiki\nhttps://wiki.archlinux.org/title/Cron (2025年7月28日) cron - What is this editor that gets opened by crontab? - Ask Ubuntu\nhttps://askubuntu.com/questions/954750/what-is-this-editor-that-gets-opened-by-crontab (2025年7月28日) ","permalink":"https://www.nyanmo.info/posts/linux/cron/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　cron を使ってみようと思って重い腰を持ち上げてみたら、意図したとおりにうまく動かせずにつまずいたのでその記録をとるだけ。うまくわかった気がしないし、間違いがあるかもしれないが、ご了承ください。\u003c/p\u003e\n\u003ch2 id=\"cron-の構造\"\u003ecron の構造\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 分 時 日(一か月単位) 月 日(一週間単位)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e* * * * * /path/to/script.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"cron-の内容の編集確認\"\u003ecron の内容の編集、確認\u003c/h2\u003e\n\u003ch3 id=\"編集\"\u003e編集\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# デフォルトは vi が使われるため、vi をインストールしておいたほうが良いかもしれないが、それ以外のエディタも使える。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecrontab -e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"確認\"\u003e確認\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecrontab -l\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# * * * * * /path/to/script.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# * * * * * /path/to/script.sh\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"確認事項\"\u003e確認事項\u003c/h2\u003e\n\u003ch3 id=\"cron-はインストールされているか\"\u003ecron はインストールされているか？\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Qs cron\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# pacman -Qs cron\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# local/cronie 1.7.2-1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     Daemon that runs specified programs at scheduled times and related tools\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"エディターを設定したか\"\u003eエディターを設定したか？\u003c/h3\u003e\n\u003cp\u003e　デフォルトだと vi が利用されるようになっており、不便なことがあると思うので設定した方がいいかも。\u003c/p\u003e","title":"cron が動かない"},{"content":"この記事を作った動機 kdenlive で画像を動画の途中でキーフレームによって反転も制御するということについて、探してもなかなか見つからず、結局いろいろ試してやっとそれっぽいことができる方法を見つけたので、それを記録するだけ。\nやり方 3-way rotate エフェクトを使う方法について今回は書いていく。rotate という純粋な名前のエフェクトでも同じことができるのを確認したが、廃止予定だそうなので、それについては今回は書かない。\n1. 反転したいオブジェクトを選択する 2. エフェクトの追加 3. Z軸方向に180度回転する 動作例 以下はゆっくりが画面の端っこから移動して、移動し終わった時に反転するという例である。 うまくいかない方法 以下に示すエフェクトは、画像を反転したりできるが、常に反転した状態にするか、常に反転してない状態にするかしかできず、キーフレームによって制御できないようである。\nFlippo Flip Horizontally Flip Vertically キーフレームが使える例 キーフレームが使えない例 参考にしたサイトとか 3-way Rotate — Kdenlive Manual 25.04 Dokumentation\nhttps://docs.kdenlive.org/de/effects_and_filters/video_effects/transform_distort_perspective/rotate_3_way.html (2025年7月28日) ChatGPT\nhttps://chatgpt.com/ (2025年7月28日) Transform — Kdenlive Manual 25.04 documentation\nhttps://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/transform.html (2025年7月28日) Flip Horizontally — Kdenlive Manual 25.04 documentation\nhttps://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/flip_horizontally.html (2025年7月28日) How do you flip horizontally? : r/kdenlive\nhttps://www.reddit.com/r/kdenlive/comments/86re3n/how_do_you_flip_horizontally/ (2025年7月28日) Affine Transition — Kdenlive Manual 25.04 Dokumentation\nhttps://docs.kdenlive.org/de/more_information/earlier_versions/affine.html (2025年7月28日) 使用した画像とか nicotalk＆キャラ素材配布所\nhttp://www.nicotalk.com/charasozai_kt.html (2025年7月28日) ","permalink":"https://www.nyanmo.info/posts/videoediting/kdenlive/flipimage/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　kdenlive で画像を動画の途中でキーフレームによって反転も制御するということについて、探してもなかなか見つからず、結局いろいろ試してやっとそれっぽいことができる方法を見つけたので、それを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　3-way rotate エフェクトを使う方法について今回は書いていく。rotate という純粋な名前のエフェクトでも同じことができるのを確認したが、廃止予定だそうなので、それについては今回は書かない。\u003c/p\u003e\n\u003ch3 id=\"1-反転したいオブジェクトを選択する\"\u003e1. 反転したいオブジェクトを選択する\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/%e5%8f%8d%e8%bb%a2%e3%81%97%e3%81%9f%e3%81%84%e3%82%aa%e3%83%96%e3%82%b8%e3%82%a7%e3%82%af%e3%83%88%e3%82%92%e9%81%b8%e6%8a%9e%e3%81%99%e3%82%8b.png#center\"\n         alt=\"反転したいオブジェクトを選択する\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"2-エフェクトの追加\"\u003e2. エフェクトの追加\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/%e3%82%a8%e3%83%95%e3%82%a7%e3%82%af%e3%83%88%e3%81%ae%e8%bf%bd%e5%8a%a0.png#center\"\n         alt=\"エフェクトの追加\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"3-z軸方向に180度回転する\"\u003e3. Z軸方向に180度回転する\u003c/h3\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;row;\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/Z%e8%bb%b8%e6%96%b9%e5%90%91%e3%81%ab180%e5%ba%a6%e5%9b%9e%e8%bb%a2%e3%81%99%e3%82%8b.png#center\"\n             alt=\"Z軸方向に180度回転する\"/\u003e \n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/Z%e8%bb%b8%e6%96%b9%e5%90%91%e3%81%ab180%e5%ba%a6%e5%9b%9e%e8%bb%a2%e3%81%99%e3%82%8b1.png#center\"\n             alt=\"Z軸方向に180度回転する1\"/\u003e \n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\n\u003ch2 id=\"動作例\"\u003e動作例\u003c/h2\u003e\n\u003cp\u003e　以下はゆっくりが画面の端っこから移動して、移動し終わった時に反転するという例である。\n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/videoEditing/kdenlive/flipImage/test.mp4 controls/\u003e\n        \n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"うまくいかない方法\"\u003eうまくいかない方法\u003c/h2\u003e\n\u003cp\u003e　以下に示すエフェクトは、画像を反転したりできるが、常に反転した状態にするか、常に反転してない状態にするかしかできず、キーフレームによって制御できないようである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eFlippo\u003c/li\u003e\n\u003cli\u003eFlip Horizontally\u003c/li\u003e\n\u003cli\u003eFlip Vertically\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;row;\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/%e3%82%ad%e3%83%bc%e3%83%95%e3%83%ac%e3%83%bc%e3%83%a0%e3%81%8c%e4%bd%bf%e3%81%88%e3%82%8b%e4%be%8b.png#center\"/\u003e \u003cfigcaption\u003e\n                キーフレームが使える例\n            \u003c/figcaption\u003e\n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/videoEditing/kdenlive/flipImage/%e3%82%ad%e3%83%bc%e3%83%95%e3%83%ac%e3%83%bc%e3%83%a0%e3%81%8c%e4%bd%bf%e3%81%88%e3%81%aa%e3%81%84%e4%be%8b.png#center\"/\u003e \u003cfigcaption\u003e\n                キーフレームが使えない例\n            \u003c/figcaption\u003e\n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e3-way Rotate — Kdenlive Manual 25.04 Dokumentation\u003cbr\u003e\n\u003ca href=\"https://docs.kdenlive.org/de/effects_and_filters/video_effects/transform_distort_perspective/rotate_3_way.html\"\u003ehttps://docs.kdenlive.org/de/effects_and_filters/video_effects/transform_distort_perspective/rotate_3_way.html\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003cli\u003eTransform — Kdenlive Manual 25.04 documentation\u003cbr\u003e\n\u003ca href=\"https://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/transform.html\"\u003ehttps://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/transform.html\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003cli\u003eFlip Horizontally — Kdenlive Manual 25.04 documentation\u003cbr\u003e\n\u003ca href=\"https://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/flip_horizontally.html\"\u003ehttps://docs.kdenlive.org/en/effects_and_filters/video_effects/transform_distort_perspective/flip_horizontally.html\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003cli\u003eHow do you flip horizontally? : r/kdenlive\u003cbr\u003e\n\u003ca href=\"https://www.reddit.com/r/kdenlive/comments/86re3n/how_do_you_flip_horizontally/\"\u003ehttps://www.reddit.com/r/kdenlive/comments/86re3n/how_do_you_flip_horizontally/\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003cli\u003eAffine Transition — Kdenlive Manual 25.04 Dokumentation\u003cbr\u003e\n\u003ca href=\"https://docs.kdenlive.org/de/more_information/earlier_versions/affine.html\"\u003ehttps://docs.kdenlive.org/de/more_information/earlier_versions/affine.html\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"使用した画像とか\"\u003e使用した画像とか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003enicotalk＆キャラ素材配布所\u003cbr\u003e\n\u003ca href=\"http://www.nicotalk.com/charasozai_kt.html\"\u003ehttp://www.nicotalk.com/charasozai_kt.html\u003c/a\u003e (2025年7月28日)\u003c/li\u003e\n\u003c/ul\u003e","title":"kdenlive で画像を反転する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 とりあえず案だけ置いている。\n参考にしたサイトとか 今のところ特になし\n","permalink":"https://www.nyanmo.info/posts/idea/research/ai-modeltoconvertrasterimagestovectorimages/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　とりあえず案だけ置いている。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今のところ特になし\u003c/p\u003e","title":"ラスター画像をベクター画像にするAIモデル"},{"content":"この記事を作った動機 Arch linux や Gnome をただ導入しただけでは有効になっていないどころか、インストールすらされていない機能を有効にする方法について、一応ノートとして記録を残すだけ。\nデーモンのインストール yay -Sy power-profiles-daemon # sudo pacman -S power-profiles-daemon デーモンの有効化 sudo systemctl enable --now power-profiles-daemon 電力管理が有効になった様子 参考にしたサイトとか Re-enable the GNOME Power Profile service - Ask Ubuntu\nhttps://askubuntu.com/questions/1526049/re-enable-the-gnome-power-profile-service (2025年7月25日) Arch Linux - power-profiles-daemon 0.30-1 (x86_64)\nhttps://archlinux.org/packages/extra/x86_64/power-profiles-daemon/ (2025年7月25日) ","permalink":"https://www.nyanmo.info/posts/linux/enablepowermanagement/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Arch linux や Gnome をただ導入しただけでは有効になっていないどころか、インストールすらされていない機能を有効にする方法について、一応ノートとして記録を残すだけ。\u003c/p\u003e\n\u003ch2 id=\"デーモンのインストール\"\u003eデーモンのインストール\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy power-profiles-daemon\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo pacman -S power-profiles-daemon\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"デーモンの有効化\"\u003eデーモンの有効化\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable --now power-profiles-daemon\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"電力管理が有効になった様子\"\u003e電力管理が有効になった様子\u003c/h2\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/EnablePowerManagement/%e9%9b%bb%e5%8a%9b%e7%ae%a1%e7%90%86%e3%81%8c%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"電力管理が有効になった様子\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/EnablePowerManagement/%e9%9b%bb%e5%8a%9b%e7%ae%a1%e7%90%86%e3%81%8c%e6%9c%89%e5%8a%b9%e3%81%ab%e3%81%aa%e3%81%a3%e3%81%9f%e6%a7%98%e5%ad%901.png#center\"\n         alt=\"電力管理が有効になった様子1\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eRe-enable the GNOME Power Profile service - Ask Ubuntu\u003cbr\u003e\n\u003ca href=\"https://askubuntu.com/questions/1526049/re-enable-the-gnome-power-profile-service\"\u003ehttps://askubuntu.com/questions/1526049/re-enable-the-gnome-power-profile-service\u003c/a\u003e (2025年7月25日)\u003c/li\u003e\n\u003cli\u003eArch Linux - power-profiles-daemon 0.30-1 (x86_64)\u003cbr\u003e\n\u003ca href=\"https://archlinux.org/packages/extra/x86_64/power-profiles-daemon/\"\u003ehttps://archlinux.org/packages/extra/x86_64/power-profiles-daemon/\u003c/a\u003e (2025年7月25日)\u003c/li\u003e\n\u003c/ul\u003e","title":"電力プロファイル設定をできるようにする"},{"content":"この記事を作った動機 なんか、キャリアネットワークをデザリングを経由して使って、さらにVPN接続を介した通信のうち、HTTPとSSHだけが繋がらないということがあった。\nそれで対策としてMTUを小さく設定することをしたのでそのことを記録するだけ。\nちなみになぜMTUが大きすぎるとだめなのかわかっていないが、多分大きすぎるサイズのパケットはなんとなくどこかで落とされている気がする。\nVPNや多段NAT構成だとルーティングされているうちに、ヘッダが積み重なって、ネットワークのパケットのサイズが大きくなりすぎたりするのかもしれない。\nネットワークの構成 サーバーやLAN内のルータ マンションのNAT キャリアネットワーク スマホ（デザリング） PCとか 状況 A -\u0026gt; キャリアネットワークのときで、直接マンションのNATを超えたとき\nB -\u0026gt; キャリアネットワークのときで、VPSなどの固定IPを持ったサーバーを経由したとき\nC -\u0026gt; 光回線などの固定回線で、直接マンションのNATを超えたときと、VPSなどの固定IPを持ったサーバーを経由したときの両方について含まれる\n状況別の表 A B C Ping ✅ OK ✅ OK ✅ OK SMB(ファイル共有) ✅ OK 確かめていない ✅ OK DNS ✅ OK ✅ OK ✅ OK SSH ❌ Failed ✅ OK ✅ OK HTTP(HTTPS) ❌ Failed ❌ Failed ✅ OK MTU設定方法(要管理者権限) デフォルトで設定されているMTUのサイズ 1500\n今回うまくいったMTUのサイズ 1000\n一時的な設定(とりあえずすぐ設定したいとき) ip コマンドを使う sudo ip link set dev [ネットワークアダプタ名] mtu [設定したいMTUサイズ] ip コマンドを使う例 # 例 # ip a # ... # 4: vpn_vpnhome: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000 # link/ether 5e:76:29:d3:1b:85 brd ff:ff:ff:ff:ff:ff # inet 192.168.1.203/24 scope global vpn_vpnhome # valid_lft forever preferred_lft forever # sudo ip link set dev vpn_vpnhome mtu 1000 # ip a # ... # 4: vpn_vpnhome: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1000 qdisc fq_codel state UNKNOWN group default qlen 1000 # link/ether 5e:76:29:d3:1b:85 brd ff:ff:ff:ff:ff:ff # inet 192.168.1.203/24 scope global vpn_vpnhome # valid_lft forever preferred_lft forever 永続化設定(networkmanagerを使っているとき) sudo nmcli connection modify [ネットワークアダプタ名] 802-3-ethernet.mtu [設定したいMTUサイズ] # vpn_vpnhome の MTU サイズを 1000 に変更 # sudo nmcli connection modify vpn_vpnhome 802-3-ethernet.mtu 1000 追記 2025年8月1日 なんか何となくブックマークをあさっていたら、TU，MSS の計算と最適化の便利な手段をまとめるというサイトにたどり着いた。それで、さらにリンクをたどって、Visual packet size calculator â€” Daniil Baturinというところに行くと、こんな記述が目に止まった。\n引用 Visual packet size calculator â€” Daniil Baturin Notes Knowing the encapsulation overhead of your protocol stack is important for configuring VPN tunnels. You need to set the tunnel interface MTU correctly, to avoid excessive packet fragmentation.\n私の解釈だと「VPNやら何かしらの通信のためにたくさんヘッダーが乗り、パケットサイズが大きすぎると、パケットが分割されて無駄が発生するから、MTUサイズをちゃんと計算しよう」的なことが書かれているように思った。\nそれでさらに今回に話題につながる思いつきとしては、中途半端に通信ができなかったとき、MTUサイズを小さく変更することで通信できたのは、パケットサイズが大きすぎて分割が必要な時にどこかでできなかったからではないか？ということまでは見えてきた気がした。\n参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年7月21日) MTU，MSS の計算と最適化の便利な手段をまとめる\nhttps://orumin.blogspot.com/2020/06/mtumss.html (2025年8月1日) Visual packet size calculator â€” Daniil Baturin\nhttps://baturin.org/tools/encapcalc/ (2025年8月1日) ","permalink":"https://www.nyanmo.info/posts/linux/networkviavpnandmtu/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか、キャリアネットワークをデザリングを経由して使って、さらにVPN接続を介した通信のうち、HTTPとSSHだけが繋がらないということがあった。\u003c/p\u003e\n\u003cp\u003e　それで対策としてMTUを小さく設定することをしたのでそのことを記録するだけ。\u003c/p\u003e\n\u003cp\u003e　ちなみになぜMTUが大きすぎるとだめなのかわかっていないが、多分大きすぎるサイズのパケットはなんとなくどこかで落とされている気がする。\u003c/p\u003e\n\u003cp\u003e　VPNや多段NAT構成だとルーティングされているうちに、ヘッダが積み重なって、ネットワークのパケットのサイズが大きくなりすぎたりするのかもしれない。\u003c/p\u003e\n\u003ch2 id=\"ネットワークの構成\"\u003eネットワークの構成\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eサーバーやLAN内のルータ\u003c/li\u003e\n\u003cli\u003eマンションのNAT\u003c/li\u003e\n\u003cli\u003eキャリアネットワーク\u003c/li\u003e\n\u003cli\u003eスマホ（デザリング）\u003c/li\u003e\n\u003cli\u003ePCとか\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"状況\"\u003e状況\u003c/h2\u003e\n\u003ch3 id=\"a--\"\u003eA -\u0026gt;\u003c/h3\u003e\n\u003cp\u003e　キャリアネットワークのときで、直接マンションのNATを超えたとき\u003c/p\u003e\n\u003ch3 id=\"b--\"\u003eB -\u0026gt;\u003c/h3\u003e\n\u003cp\u003e　キャリアネットワークのときで、VPSなどの固定IPを持ったサーバーを経由したとき\u003c/p\u003e\n\u003ch3 id=\"c--\"\u003eC -\u0026gt;\u003c/h3\u003e\n\u003cp\u003e　光回線などの固定回線で、直接マンションのNATを超えたときと、VPSなどの固定IPを持ったサーバーを経由したときの両方について含まれる\u003c/p\u003e\n\u003ch3 id=\"状況別の表\"\u003e状況別の表\u003c/h3\u003e\n\u003cdiv style=\"display: flex; justify-content: center;align-items: center;\"\u003e\n    \u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003e\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eA\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eB\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eC\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003ePing\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eSMB(ファイル共有)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e確かめていない\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eDNS\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eSSH\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e❌ Failed\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eHTTP(HTTPS)\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e❌ Failed\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e❌ Failed\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e✅ OK\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"mtu設定方法要管理者権限\"\u003eMTU設定方法(要管理者権限)\u003c/h2\u003e\n\u003ch3 id=\"デフォルトで設定されているmtuのサイズ\"\u003eデフォルトで設定されているMTUのサイズ\u003c/h3\u003e\n\u003cp\u003e1500\u003c/p\u003e\n\u003ch3 id=\"今回うまくいったmtuのサイズ\"\u003e今回うまくいったMTUのサイズ\u003c/h3\u003e\n\u003cp\u003e1000\u003c/p\u003e\n\u003ch3 id=\"一時的な設定とりあえずすぐ設定したいとき\"\u003e一時的な設定(とりあえずすぐ設定したいとき)\u003c/h3\u003e\n\u003ch4 id=\"ip-コマンドを使う\"\u003e\u003ccode\u003eip\u003c/code\u003e コマンドを使う\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo ip link set dev \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eネットワークアダプタ名\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e mtu \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e設定したいMTUサイズ\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch4 id=\"ip-コマンドを使う例\"\u003e\u003ccode\u003eip\u003c/code\u003e コマンドを使う例\u003c/h4\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 例\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ip a\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 4: vpn_vpnhome: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/ether 5e:76:29:d3:1b:85 brd ff:ff:ff:ff:ff:ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 192.168.1.203/24 scope global vpn_vpnhome\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo ip link set dev vpn_vpnhome mtu 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ip a\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 4: vpn_vpnhome: \u0026lt;BROADCAST,MULTICAST,UP,LOWER_UP\u0026gt; mtu 1000 qdisc fq_codel state UNKNOWN group default qlen 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     link/ether 5e:76:29:d3:1b:85 brd ff:ff:ff:ff:ff:ff\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#     inet 192.168.1.203/24 scope global vpn_vpnhome\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#        valid_lft forever preferred_lft forever\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"永続化設定networkmanagerを使っているとき\"\u003e永続化設定(networkmanagerを使っているとき)\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo nmcli connection modify \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eネットワークアダプタ名\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e 802-3-ethernet.mtu \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e設定したいMTUサイズ\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# vpn_vpnhome の MTU サイズを 1000 に変更\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo nmcli connection modify vpn_vpnhome 802-3-ethernet.mtu 1000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"追記\"\u003e追記\u003c/h2\u003e\n\u003ch3 id=\"2025年8月1日\"\u003e2025年8月1日\u003c/h3\u003e\n\u003cp\u003e　なんか何となくブックマークをあさっていたら、\u003ca href=\"https://orumin.blogspot.com/2020/06/mtumss.html\"\u003eTU，MSS の計算と最適化の便利な手段をまとめる\u003c/a\u003eというサイトにたどり着いた。それで、さらにリンクをたどって、\u003ca href=\"https://baturin.org/tools/encapcalc/\"\u003eVisual packet size calculator â€” Daniil Baturin\u003c/a\u003eというところに行くと、こんな記述が目に止まった。\u003c/p\u003e","title":"VPN越しにHTTPやSSH通信だけ通らなかった話とMTU設定"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 概要 低レベルな実装の練習として、RISC-VとQEMUで linux とかをブートできるくらいまでファームウェアを開発するということをしてみたい。\nRISC-V 以外には、 x86 や ARM があるが、最近の動向的にも開発環境やクローズドなNDAで複雑、難解なドキュメントだらけだったりして、将来性を感じないというのもある。すでに広く普及している既存のプラットフォームに合わせるより、アリエクスプレスやアマゾンでも転がっている、RISC-V SBCに注目しているというのも大きい。最近では linux が RISC-V と Gnome でクライアントとして動く例もあった気がする。\nChatGPT Open as a page 参考にしたサイトとか ChatGPT\nhttps://chatgpt.com/ (2025年7月13日) Risc-V Bare Metal C Hello World! - YouTube\nhttps://www.youtube.com/watch?v=HC7b1SVXoKM (2025年7月13日) ","permalink":"https://www.nyanmo.info/posts/idea/research/risc-v/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"概要\"\u003e概要\u003c/h2\u003e\n\u003cp\u003e　低レベルな実装の練習として、RISC-VとQEMUで linux とかをブートできるくらいまでファームウェアを開発するということをしてみたい。\u003c/p\u003e\n\u003cp\u003e　RISC-V 以外には、 x86 や ARM があるが、最近の動向的にも開発環境やクローズドなNDAで複雑、難解なドキュメントだらけだったりして、将来性を感じないというのもある。すでに広く普及している既存のプラットフォームに合わせるより、アリエクスプレスやアマゾンでも転がっている、RISC-V SBCに注目しているというのも大きい。最近では linux が RISC-V と Gnome でクライアントとして動く例もあった気がする。\u003c/p\u003e\n\u003ch2 id=\"chatgpt\"\u003eChatGPT\u003c/h2\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/risc-v/%e3%83%99%e3%82%a2%e3%83%a1%e3%82%bf%e3%83%abBIOS%e9%96%8b%e7%99%ba.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/risc-v/%e3%83%99%e3%82%a2%e3%83%a1%e3%82%bf%e3%83%abBIOS%e9%96%8b%e7%99%ba.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年7月13日)\u003c/li\u003e\n\u003cli\u003eRisc-V Bare Metal C Hello World! - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=HC7b1SVXoKM\"\u003ehttps://www.youtube.com/watch?v=HC7b1SVXoKM\u003c/a\u003e (2025年7月13日)\n\u003cdiv style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\"\u003e\n\t\t\t\u003ciframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https://www.youtube.com/embed/HC7b1SVXoKM?autoplay=0\u0026amp;controls=1\u0026amp;end=0\u0026amp;loop=0\u0026amp;mute=0\u0026amp;start=0\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\u003e\u003c/iframe\u003e\n\t\t\u003c/div\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"RISC-V で BIOSやUEFI的なものを作りたい"},{"content":"この記事を作った動機 なんか最近 AUR に Stable Diffusion WebUIが出現していて気軽に試せそうだったのでインストールして使ってみたということがあった。\nその過程で記録しておきたいことがあったので、Stable Diffusion WebUI の導入過程とともに記事を書こうと思った。 環境 System Details Report Report details Date generated: 2025-07-13 20:41:10 Hardware Information: Hardware Model: HP ProLiant DL60 Gen9 Memory: 32.0 GiB Processor: Intel® Xeon® E5-2620 v4 × 16 Graphics: Unknown ※ GTX1080ti Disk Capacity: 30.0 TB Software Information: Firmware Version: U15 OS Name: Arch Linux OS Build: rolling OS Type: 64-bit GNOME Version: 48 Windowing System: X11 Kernel Version: Linux 6.15.5-arch1-1 導入 yay コマンドでインストール yay -Sy stable-diffusion-webui コンフィグの場所 /etc/stable-diffusion-webui/webui.conf\nコンフィグの設定例(webui.conf) DATA_DIR は専用にディレクトリを作り、変更した方がいいかもしれない。デフォルトの場所だと、モデルを配置したり出力された画像などにアクセスしずらい。\nデフォルトだと、\u0026quot;/var/opt/stable-diffusion-webui/data\u0026quot;配下にモデルを配置する場所や、生成した画像が置かれてしまう。都合に合わせてユーザのホームディレクトリとか、適当な場所に専用のフォルダを設けた方が便利ではある。\n# Flags to pass to the `accelerate launch` command # See: https://huggingface.co/docs/accelerate/package_reference/cli#accelerate-launch ACCELERATE_FLAGS=\u0026#34;--num_cpu_threads_per_process=6\u0026#34; # Flags for stable-diffusion-webui # See: https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Command-Line-Arguments-and-Settings # # Example: WEBUI_FLAGS=\u0026#34;--listen\u0026#34; WEBUI_FLAGS=\u0026#34;--listen --api --api-log --xformers --lowvram --disable-safe-unpickle --enable-insecure-extension-access\u0026#34; # Path to save model files and outputs DATA_DIR=\u0026#34;/var/opt/stable-diffusion-webui/data\u0026#34; サービスを設定し起動 sudo systemctl enable --now stable-diffusion-webui # 起動と有効化の両方 # sudo systemctl enable stable-diffusion-webui // PC が起動したときに立ち上がるようにするだけの時 # sudo systemctl start stable-diffusion-webui // 単に webui を起動するだけ この時点で、localhost:7860からは、webui にchromeなどからアクセスできると思われる。正しく起動していれば、とりあえず何か生成できるか試すこともできる。\nhttpd のプロキシ設定 私の場合はデータサーバとして専用に設けているPCに、今回 stable diffusion webui をインストールしたので、localhostだけで動かれるといちいちリモートデスクトップか何かで、直接サーバ内部の GUI 環境に入る必要があり不便であった。\nなので、httpd のプロキシ機能を使って、プライベートなLAN内だけで運用している専用のドメイン名でアクセスされると、localhost:7860として転送するように設定した。\nこの方法であれば、firewalld などの設定をわざわざ変えなくて済むという点からも管理的な意味合いでは都合がいい。\n注意点としては、httpの設定だけでなく、websocket も localhost:7860 に転送する設定が必要であるというところがある。また、httpd 側の専用のモジュールも有効化が必要である。また今回は SSL の設定も混じっているが、そこについては大変すぎるので説明は省くことにする。\n/etc/httpd/conf/httpd.conf (モジュール周りの設定) # 設定項目自体はすでに \u0026#34;#\u0026#34; でコメントアウトされて存在するので、必要な項目の行の \u0026#34;#\u0026#34; を消すだけでよい。 ... # 必要なモジュールの有効化 LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule proxy_wstunnel_module modules/mod_proxy_wstunnel.so LoadModule rewrite_module modules/mod_rewrite.so # 必要な設定の書いてあるコンフィグファイルの有効化 Include conf/vhost/service.conf # オプション LoadModule ssl_module modules/mod_ssl.so # SSL の設定。一応ここは載せておく ... /etc/httpd/conf/extra/httpd-vhosts.conf (プロキシ設定本体) ... \u0026lt;VirtualHost *:80\u0026gt; # SSL (HTTPS) の設定なので今回はあまり関係がない ServerName stable.internal.domain.name Redirect permanent / https://stable.internal.domain.name/ \u0026lt;/VirtualHost\u0026gt; \u0026lt;VirtualHost *:443\u0026gt; ServerName stable.internal.domain.name # SSL (HTTPS) の設定なので今回の設定とはこの 3行はあまり関係ない SSLEngine on SSLCertificateFile \u0026#34;/etc/httpd/conf/ssl/stable.internal.domain.name.pem\u0026#34; SSLCertificateKeyFile \u0026#34;/etc/httpd/conf/ssl/stable.internal.domain.name-key.pem\u0026#34; # websocket 転送設定 RewriteEngine On RewriteCond %{HTTP:Upgrade} =websocket [NC] RewriteCond %{HTTP:Connection} upgrade [NC] RewriteRule ^/(.*) \u0026#34;ws://localhost:7860/$1\u0026#34; [P,L] # HTTP 転送設定 ProxyPreserveHost on ProxyRequests off ProxyPass / http://localhost:7860/ ProxyPassReverse / http://localhost:7860/ \u0026lt;/VirtualHost\u0026gt; ... モデルや生成画像の場所 ✅ # DATA_DIR=\u0026#34;/home/username/Documents/AI\u0026#34; の場合 /home/username/Documents/AI/models/Stable-diffusion # モデルを配置する場所 /home/username/Documents/AI/outputs # 生成された画像の場所 # デフォルト設定の場合 /var/opt/stable-diffusion-webui/data/models/Stable-diffusion # モデルを配置する場所 /var/opt/stable-diffusion-webui/data/outputs # 生成された画像の場所 ## hint # @ /etc/stable-diffusion-webui/webui.conf # Path to save model files and outputs # DATA_DIR=\u0026#34;/var/opt/stable-diffusion-webui/data\u0026#34; # @ /usr/lib/systemd/system/stable-diffusion-webui.service # destdir=\u0026#34;${DATA_DIR}/models/Stable-diffusion\u0026#34;; \\ ❌ /usr/share/stable-diffusion-webui/models/Stable-diffusion /opt/stable-diffusion-webui/models/Stable-diffusion 追記 (2025/9/14) 最近気づいたこととして、VRAM の残りがたくさんあったりするのに、GPU が全然使われてなかったり、70GB くらいあるメインメモリを画像生成ごとに徐々にメモリリークして全部食いつぶし、結果的に linux 環境では完全にシステム全体をフリーズさせてしまい、強制的に再起動しないと復帰しないということがあった。\nそこで気づいたことややったほうがいいことがわかったのでそれを記録する。\nlowvram オプション 私は、GTX1080ti を画像生成のために割り当てているが、VRAM が約 11GB 程度ある中で、lowvram オプションが付いていると、せいぜい数 GB 程度しか使わない状態で、GPU自体も 30% 程度しか使えていなかったりと、全体的に動作が遅かった。\nまたモデルがメインメモリの方に読み込まれてしまうからか、画像生成だけで初回で、20GB程度持っていかれて、その後は使い込むほど WebUI ごと再起動しない限り、メモリリークを起こして食いつぶして行く様相だった。\nこのような状況では、webui.conf から使いたいモデルが VRAM 内に収まっているとわかっているなら、デフォルトで AUR からインストールしたときには付いている、--lowvram を消したほうがいいかもしれない。ちなみにこのオプションを消すと、メインメモリの使用率は圧倒的に下がるが、変わりに　GPU のメモリをいっぱい使うようになる。\n画像生成はせずモデルがロードされた様子の例 # nvidia-smi Sun Sep 14 01:02:25 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.82.09 Driver Version: 580.82.09 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA GeForce GTX 1080 Ti Off | 00000000:07:00.0 On | N/A | | 36% 46C P8 13W / 250W | 8845MiB / 11264MiB | 10% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 1504 G /usr/lib/Xorg 303MiB | | 0 N/A N/A 1867 G /usr/bin/gnome-shell 60MiB | | 0 N/A N/A 7409 C+G ...b/gnome-remote-desktop-daemon 298MiB | | 0 N/A N/A 467649 C ...ffusion-webui/venv/bin/python 7726MiB | | 0 N/A N/A 1984341 G ...ersion=20250910-180038.780000 430MiB | +-----------------------------------------------------------------------------------------+ 画像生成中の例 # nvidia-smi Sun Sep 14 01:05:49 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.82.09 Driver Version: 580.82.09 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA GeForce GTX 1080 Ti Off | 00000000:07:00.0 On | N/A | | 41% 67C P2 236W / 250W | 9656MiB / 11264MiB | 100% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 1504 G /usr/lib/Xorg 303MiB | | 0 N/A N/A 1867 G /usr/bin/gnome-shell 93MiB | | 0 N/A N/A 7409 C+G ...b/gnome-remote-desktop-daemon 298MiB | | 0 N/A N/A 467649 C ...ffusion-webui/venv/bin/python 8666MiB | | 0 N/A N/A 1984341 G ...ersion=20250910-180038.780000 268MiB | +-----------------------------------------------------------------------------------------+ 結局メモリリークする例 GPU 側にモデルを読み込むようになり、メインメモリをあまり使わなくなっても、起動したてのときは、1 GB も使ってなかった気がするが、このようにして使い込むほどにだんだんと、何 GB も食いつぶし始める。\n定期的に再起動したり、メモリ使用が一定を超えたら、自動的に kill して再起動するとか、そういう工夫が必要であることに変わりはないようである。\n● stable-diffusion-webui.service - Stable Diffusion Web UI Loaded: loaded (/usr/lib/systemd/system/stable-diffusion-webui.service; enabled; preset: disabled) Drop-In: /etc/systemd/system/stable-diffusion-webui.service.d └─override.conf Active: active (running) since Thu 2025-09-11 21:40:13 JST; 2 days ago Invocation: 478bf01465a74b3aa9632b822857dc0b Main PID: 467428 (accelerate) Tasks: 92 (limit: 629145) Memory: 8.2G (max: 20G, available: 11.7G, peak: 8.6G) CPU: 23h 31min 19.092s CGroup: /system.slice/stable-diffusion-webui.service ├─467428 /opt/stable-diffusion-webui/venv/bin/python /opt/stable-diffusion-webui/venv/bin/accele\u0026gt; └─467649 /opt/stable-diffusion-webui/venv/bin/python /opt/stable-diffusion-webui/launch.py --dat\u0026gt; systemd メモリ制限 どうやっても、メモリリークするし、それでメインメモリを全部食いつぶされて、linux がフリーズして強制的に再起動するまで、HDD が永遠にガリガリいうみたいな光景は、まさしくハードウェアの寿命を無駄にしているって感じで嫌だしうざいので、Systemd 側でメモリ使用に制限をかけてしまうことにした。\nAUR にある stable-diffusion-webui にはすでに systemd のサービスがデフォルトで用意されているので、ChatGPT-5 にそのことを投げたら、追加設定がアプデ時に毎回上書きされないように、drop-in 設定を使えと帰ってきて、実際試してみてそれが動いたため、今回はそれを採用した。\n追加した設定 Service の項目に、メモリ管理の有効化と、メモリの最大の設定や、OOM Killer が優先的にメモリが足りなくなったら stable-diffusion-webui を Kill するように、スコアを設定したりした。\n[Service] MemoryAccounting=true MemoryMax=20G # メモリ上限 20GB。 本当は 5GB 程度でいいかもしれない OOMScoreAdjust=1000 # 1000 で最も優先的に Kill されやすくなり、 -1000 で Kill されなくなるとのこと。 既存の systemd サービスをオーバーライドする方法 # エディタが立ち上がるので、追加したい設定項目で全部上書きする。 sudo systemctl edit stable-diffusion-webui.service # 正常に設定が反映されたときは以下のように、メッセージが出てくる Successfully installed edited file \u0026#39;/etc/systemd/system/stable-diffusion-webui.service.d/override.conf\u0026#39;. stable-diffusion-webui.service オーバーライド例 ### Editing /etc/systemd/system/stable-diffusion-webui.service.d/override.conf ### Anything between here and the comment below will become the contents of the drop-in file # ここに上書き設定を書く ------------------------------------ # ここに上書き設定を書く ------------------------------------ [Service] MemoryAccounting=true MemoryMax=20G OOMScoreAdjust=1000 # ここに上書き設定を書く ------------------------------------ # ここに上書き設定を書く ------------------------------------ ### Edits below this comment will be discarded # ここからしたに書いても何も反映されず、消されてしまう。 ### /usr/lib/systemd/system/stable-diffusion-webui.service # [Unit] # Description=Stable Diffusion Web UI # After=network.target # # [Service] # Type=simple # User=sdwebui # Group=sdwebui # WorkingDirectory=/opt/stable-diffusion-webui # Environment=PYTHONUNBUFFERED=1 # EnvironmentFile=/etc/stable-diffusion-webui/webui.conf # ExecStart=/bin/bash -c \u0026#39;\\ # : \u0026#34;${DATA_DIR:=/var/opt/stable-diffusion-webui}\u0026#34;; \\ # srcdir=\u0026#34;/usr/share/stable-diffusion-webui/models/Stable-diffusion\u0026#34;; \\ # destdir=\u0026#34;${DATA_DIR}/models/Stable-diffusion\u0026#34;; \\ # modelfile=\u0026#34;v1-5-pruned-emaonly.safetensors\u0026#34;; \\ # mkdir -p \u0026#34;$destdir\u0026#34; \u0026amp;\u0026amp; \\ # [ ! -f \u0026#34;$destdir/$modelfile\u0026#34; ] \u0026amp;\u0026amp; cp \u0026#34;$srcdir/$modelfile\u0026#34; \u0026#34;$destdir/\u0026#34;; \\ # exec /opt/stable-diffusion-webui/venv/bin/accelerate \\ # launch ${ACCELERATE_FLAGS:+$ACCELERATE_FLAGS} \\ # /opt/stable-diffusion-webui/launch.py \\ # --data-dir \u0026#34;$DATA_DIR\u0026#34; ${WEBUI_FLAGS:+$WEBUI_FLAGS}\u0026#39; # # Restart=always # StartLimitInterval=120 # StartLimitBurst=15 # UMask=007 # # [Install] # WantedBy=multi-user.target ChatGPT-5 以外の参考 正直 ChatGPT は平気で変なことを堂々と言ってきて、どれが正しい、それは絶対間違ってるみたいな、あたかも確かなことを言っているかのような言い方してきて鬱陶しく、非常に私はそれに対し疑心暗鬼でもあるので、自分でも OOMScoreAdjust についての説明が ChatGPT の出力したこととおかしくないかとか、適当にぼちぼちネットを調べたりした。\n以下は、似たような systemd でメモリ管理をしたいケースにおいて、参考になりそうなサイトでもあると思われる。\nsystemd.resource-control\nhttps://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html (2025年9月14日) systemd memory limit not working/example - Unix \u0026amp; Linux Stack Exchange\nhttps://unix.stackexchange.com/questions/449210/systemd-memory-limit-not-working-example (2025年9月14日) systemd.exec\nhttps://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html (2025年9月14日) GPU のファン速度の設定 画像生成で GPU に負荷をかけまくると、私の環境の場合、どうもデフォルトのファン回転数制御では、85℃ あたりでうろつきながら、サーマルスロットリングって感じで、電力にはまだ余裕があるのに、GPU の性能を使い切れないという現象が起こることがわかった。\n気づいた過程としては、\n画像生成を始めて最初は、徐々に40℃あたりから温度が上がっていき、パワーリミットで 240w/250w という感じで動いている 数分後には、80℃以上に達し、190w/250w という感じでサーマルスロットリングでうろつくようになる\nということがあった。 温度 ファン速度 電力 パワーリミット サーマルスロットリング 生成をしていないとき 40℃ 30%くらい？ 20~60w なし なし 生成はじめ 40℃から上昇 徐々に上昇 240w~260w あり(250w) なし 生成を始めて数分後 85℃あたりをうろつく 65% 180w~200w なし あり 最初は単に画像生成AIとはそういうものなのだと思っていたが、段々と温度と消費電力の関係をぼーっとなんとなく見ていたら、おかしいなと気づいた。\nここでは具体的にどうやって、nvidia 製 GPU のファンの速度を linux 上で nvidia-settings コマンドを使って制御するか記録しようと思う。\n-c 0 って何？ sudo nvidia-settings -a ‘[fan:0]/GPUTargetFanSpeed=100’ # Authorization required, but no authorization protocol specified # # # ERROR: The control display is undefined; please run `nvidia-settings --help` for usage information. -c を指定しなかったときの、上記のエラーに従って、調べてみると、以下のようなことが書かれていた。\nnvidia-settings --help # ... # -c CTRL-DISPLAY, --ctrl-display=CTRL-DISPLAY # Control the specified X display. If this option is not given, then nvidia-settings will control the di # splay specified by \u0026#39;--display\u0026#39;; if that is not given, then the $DISPLAY environment variable is used. # ... どうも、明示的に GPU が制御している X11 の画面を指定する必要があるようで、SSH 経由でリモートで作業していたのも相まって、nvidia-settings が $DISPLAY 環境変数からも何も得られなかったようである。\nよくわからなければ、0 ~ 10 くらいまで試していれば多分いつか当たると思われ、特殊な構成にしていなければ、X11 のディスプレイは基本 0 番に描画されるようになっているので、そこをまず当たればいいと思われる。\n設定できるファンを調べる sudo nvidia-settings --query fans -c 0 # Authorization required, but no authorization protocol specified # # # 1 Fan on 0 # # [0] [fan:0] (Fan 0) # # Has the following name: # FAN-0 ファン回転数を 0~100 % の間で設定する sudo nvidia-settings -c 0 -a [fan:0]/GPUTargetFanSpeed=100 # Authorization required, but no authorization protocol specified # # # Attribute \u0026#39;GPUTargetFanSpeed\u0026#39; ([fan:0]) assigned value 100. ファンを最大回転数で回してみた様子 ざっと、5℃ 程度の温度低下が見られた。パワーリミットで再び動作するようになったりと効果はあるようである。しかし、ファンのベアリングの寿命を考えると、正直あんまりこういう強引なやり方はよくないかもしれないので、使っているとき以外はファン制御は GPU に返したほうがいいかも。\n# nvidia-smi Sun Sep 14 02:59:16 2025 +-----------------------------------------------------------------------------------------+ | NVIDIA-SMI 580.82.09 Driver Version: 580.82.09 CUDA Version: 13.0 | +-----------------------------------------+------------------------+----------------------+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC | | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. | | | | MIG M. | |=========================================+========================+======================| | 0 NVIDIA GeForce GTX 1080 Ti Off | 00000000:07:00.0 On | N/A | |100% 80C P2 253W / 250W | 9574MiB / 11264MiB | 100% Default | | | | N/A | +-----------------------------------------+------------------------+----------------------+ +-----------------------------------------------------------------------------------------+ | Processes: | | GPU GI CI PID Type Process name GPU Memory | | ID ID Usage | |=========================================================================================| | 0 N/A N/A 1504 G /usr/lib/Xorg 353MiB | | 0 N/A N/A 1867 G /usr/bin/gnome-shell 60MiB | | 0 N/A N/A 7409 C+G ...b/gnome-remote-desktop-daemon 298MiB | | 0 N/A N/A 467649 C ...ffusion-webui/venv/bin/python 8668MiB | | 0 N/A N/A 759787 G /usr/bin/kgx 7MiB | | 0 N/A N/A 760274 G nvidia-settings 2MiB | | 0 N/A N/A 1984341 G ...ersion=20250910-180038.780000 155MiB | +-----------------------------------------------------------------------------------------+ GPU にファン制御を返す sudo nvidia-settings -c 0 -a GPUFanControlState=0 試行錯誤と結局ググる過程 手動のファン回転数指定から、元の自動制御に戻す方法についても調べてみた。とは言ってもどうすればいいかわからないので、とりあえず、nvidia-settings --help してみると、以下の項目が気になった。\nnvidia-settings --help # ... # -e DESCRIBE, --describe=DESCRIBE # Prints information about a particular attribute. Specify \u0026#39;all\u0026#39; to list the descriptions of all attribu # tes. Specify \u0026#39;list\u0026#39; to list the attribute names without a descriptions. # ... そこで、Fan についてどういう項目があるか調べてみると以下のようになった。\nnvidia-settings -e all | grep Fan # Attribute \u0026#39;GPUFanControlState\u0026#39;: # Attribute \u0026#39;GPUTargetFanSpeed\u0026#39;: # Attribute \u0026#39;GPUCurrentFanSpeed\u0026#39;: # Attribute \u0026#39;GPUResetFanSpeed\u0026#39;: # Attribute \u0026#39;GPUCurrentFanSpeedRPM\u0026#39;: # Attribute \u0026#39;GPUFanControlType\u0026#39;: # Attribute \u0026#39;GPUFanTarget\u0026#39;: GPUFanControlState や GPUFanControlType あたりが怪しそうだと思い、更に調べてみる。\nnvidia-settings -e GPUFanControlState # Attribute \u0026#39;GPUFanControlState\u0026#39;: # - Attribute value is an integer. # - Attribute is not written to the rc file. # The current fan control state; the value of this attribute controls the availability of additional fan # control attributes. Note that this attribute is unavailable unless fan control support has been enabled by # setting the \u0026#34;Coolbits\u0026#34; X config option. nvidia-settings -e GPUFanControlType # Attribute \u0026#39;GPUFanControlType\u0026#39;: # - Attribute value is an integer. # - Attribute is not written to the rc file. # Returns how the GPU fan is controlled. \u0026#39;1\u0026#39; means the fan can only be toggled on and off; \u0026#39;2\u0026#39; means the fan # has variable speed. \u0026#39;0\u0026#39; means the fan is restricted and cannot be adjusted under end user control. それで、GPUFanControlState あたりを試してみるも、どういう値にすればいいかまでは、コマンドのヘルプを見てもわからなかったので、適当にネットで調べて、GPUFanControlState=0 に至る。\nnvidia-settings -e GPUFanControlState # Attribute \u0026#39;GPUFanControlState\u0026#39;: # - Attribute value is an integer. # - Attribute is not written to the rc file. # The current fan control state; the value of this attribute controls the availability of additional fan # control attributes. Note that this attribute is unavailable unless fan control support has been enabled by # setting the \u0026#34;Coolbits\u0026#34; X config option. 参考 How to set fanspeed in Linux from terminal - CUDA / CUDA Programming and Performance - NVIDIA Developer Forums\nhttps://forums.developer.nvidia.com/t/how-to-set-fanspeed-in-linux-from-terminal/72705/6 (2025年9月14日) Little tip for super easy GPU fan control without any software : r/linux_gaming\nhttps://www.reddit.com/r/linux_gaming/comments/1gk4676/little_tip_for_super_easy_gpu_fan_control_without/ (2025年9月14日) WebUI の初期値を変更する (2025/10/20) しばらくいろんな画像を生成して遊んでいたところ、だんだんとデフォルトの設定値が気に食わなくなった。それで、いちいち画像生成時に設定を変更するのはめんどくさかったので、設定する方法について調べていた。すでにいろんな解説記事があるが、自分用の記録としてやり方をここに書く。\ndata フォルダ内の ui-config.json を変更する 今回は部分的に、以下の項目の設定を txt2img に注目して変更する例を挙げる。data フォルダとは、コンフィグの設定例webuiconfの説明で出てくるDATA_DIRのことである。\n解像度 512x512 -\u0026gt; 1200x1200 ステップ数 20 -\u0026gt; 35 バッチカウント 1 -\u0026gt; 10 { ... \u0026#34;customscript/sampler.py/txt2img/Sampling steps/visible\u0026#34;: true, \u0026#34;customscript/sampler.py/txt2img/Sampling steps/value\u0026#34;: 35, // 変更した部分 \u0026#34;customscript/sampler.py/txt2img/Sampling steps/minimum\u0026#34;: 1, \u0026#34;customscript/sampler.py/txt2img/Sampling steps/maximum\u0026#34;: 150, \u0026#34;customscript/sampler.py/txt2img/Sampling steps/step\u0026#34;: 1, \u0026#34;txt2img/Width/visible\u0026#34;: true, \u0026#34;txt2img/Width/value\u0026#34;: 1200, // 変更した部分 \u0026#34;txt2img/Width/minimum\u0026#34;: 64, \u0026#34;txt2img/Width/maximum\u0026#34;: 2048, \u0026#34;txt2img/Width/step\u0026#34;: 8, \u0026#34;txt2img/Height/visible\u0026#34;: true, \u0026#34;txt2img/Height/value\u0026#34;: 1200, // 変更した部分 \u0026#34;txt2img/Height/minimum\u0026#34;: 64, \u0026#34;txt2img/Height/maximum\u0026#34;: 2048, \u0026#34;txt2img/Batch count/visible\u0026#34;: true, \u0026#34;txt2img/Batch count/value\u0026#34;: 10, // 変更した部分 \u0026#34;txt2img/Batch count/minimum\u0026#34;: 1, \u0026#34;txt2img/Batch count/maximum\u0026#34;: 100, \u0026#34;txt2img/Batch count/step\u0026#34;: 1, ... } stable-diffusion-webui を再起動する 私の環境で試したところ、webui を再起動するまでは、ui-config.jsonの変更が反映されないことが分かったため、再起動するようにしていた。\nsudo systemctl restart stable-diffusion-webui 参考 【Stable Diffusion WebUI 】 ui-config 活用法。SDXL に合わせて設定を最適化＋デフォルト設定を変更してみた！ #AI - Qiita\nhttps://qiita.com/tonosamart/items/23a612768098870c20ae (2025年10月20日) Stable-diffusion の進捗状況を取得する (2025/10/21) WebUIを閉じてしまうと、今動かしているジョブの進捗状況が確認できないということがあったので、ChatGPTに適当に聞いてみて、出てきたのを試してみた。進捗状況はWebUIを閉じてしまっても、少なくとも私の環境では、以下のURLでJSON形式で取得できるようである。\ndomain.name.or.ip.addressについては、ローカルで動いている webui のアドレスである。\nhttps://domain.name.or.ip.address/sdapi/v1/progress { \u0026#34;progress\u0026#34;: 0.9414285714285715, \u0026#34;eta_relative\u0026#34;: 73.19720708907812, \u0026#34;state\u0026#34;: { \u0026#34;skipped\u0026#34;: false, \u0026#34;interrupted\u0026#34;: false, \u0026#34;stopping_generation\u0026#34;: false, \u0026#34;job\u0026#34;: \u0026#34;Batch 10 out of 10\u0026#34;, \u0026#34;job_count\u0026#34;: 10, \u0026#34;job_timestamp\u0026#34;: \u0026#34;20251021221750\u0026#34;, \u0026#34;job_no\u0026#34;: 9, \u0026#34;sampling_step\u0026#34;: 12, \u0026#34;sampling_steps\u0026#34;: 35 }, \u0026#34;current_image\u0026#34;: \u0026#34;ImageBlobString\u0026#34;, \u0026#34;textinfo\u0026#34;: null } 一応調べてみると、以下の githubのDiscussionsのところにあったスレッドになんか書いてあることは確認できた。\nProgress API endpoint · AUTOMATIC1111/stable-diffusion-webui · Discussion #7888\nhttps://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/7888 (2025年10月21日) またもう少し、どんなエントリーポイントがあるのかリストがないか調べてみたところ、ローカルで動かしているサーバに以下のURLでアクセスすることで利用できるAPIのリストを得られるようである。\nhttps://domain.name.or.ip.address/docs Basic Documentation and Examples for using API · AUTOMATIC1111/stable-diffusion-webui · Discussion #3734\nhttps://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/3734 (2025年10月21日) メモリ管理を何とかする (2026/1/29) 以前メモリ管理について、メインメモリを stable-diffusion-webui がリークしているみたいなことをこの記事で書いていて、それについて最近進展があったので、記録を取る。具体的には、tcmallocを導入することについて記録する。\nライブラリのインストール yay -S gperftools #sudo pacman -S gperftools yay -Ql gperftools ... gperftools /usr/lib/libtcmalloc.so ... systemd で環境変数を設定してtcmallocを使うようにする sudo systemctl edit stable-diffusion-webui.service ### Editing /etc/systemd/system/stable-diffusion-webui.service.d/override.conf ### Anything between here and the comment below will become the contents of the drop-in file # ここに上書き設定を書く ------------------------------------ # ここに上書き設定を書く ------------------------------------ [Service] MemoryAccounting=true MemoryMax=20G OOMScoreAdjust=1000 Environment=\u0026#34;LD_PRELOAD=/usr/lib/libtcmalloc.so\u0026#34; # ここに上書き設定を書く ------------------------------------ # ここに上書き設定を書く ------------------------------------ ### Edits below this comment will be discarded # ここからしたに書いても何も反映されず、消されてしまう。 ### /usr/lib/systemd/system/stable-diffusion-webui.service # [Unit] # Description=Stable Diffusion Web UI # After=network.target # # [Service] # Type=simple # User=sdwebui # Group=sdwebui # WorkingDirectory=/opt/stable-diffusion-webui # Environment=PYTHONUNBUFFERED=1 # EnvironmentFile=/etc/stable-diffusion-webui/webui.conf # ExecStart=/bin/bash -c \u0026#39;\\ # : \u0026#34;${DATA_DIR:=/var/opt/stable-diffusion-webui}\u0026#34;; \\ # srcdir=\u0026#34;/usr/share/stable-diffusion-webui/models/Stable-diffusion\u0026#34;; \\ # destdir=\u0026#34;${DATA_DIR}/models/Stable-diffusion\u0026#34;; \\ # modelfile=\u0026#34;v1-5-pruned-emaonly.safetensors\u0026#34;; \\ # mkdir -p \u0026#34;$destdir\u0026#34; \u0026amp;\u0026amp; \\ # [ ! -f \u0026#34;$destdir/$modelfile\u0026#34; ] \u0026amp;\u0026amp; cp \u0026#34;$srcdir/$modelfile\u0026#34; \u0026#34;$destdir/\u0026#34;; \\ # exec /opt/stable-diffusion-webui/venv/bin/accelerate \\ # launch ${ACCELERATE_FLAGS:+$ACCELERATE_FLAGS} \\ # /opt/stable-diffusion-webui/launch.py \\ # --data-dir \u0026#34;$DATA_DIR\u0026#34; ${WEBUI_FLAGS:+$WEBUI_FLAGS}\u0026#39; # # Restart=always # StartLimitInterval=120 # StartLimitBurst=15 # UMask=007 # # [Install] # WantedBy=multi-user.target 関係のありそうなページ https通信をプライベートネットワークで使いたい yay コマンドのインストール 参考にしたサイトとか AUR (en) - stable-diffusion-webui\nhttps://aur.archlinux.org/packages/stable-diffusion-webui (2025年7月12日)\n[Bug]: Error: Connection errored out. · Issue #9074 · AUTOMATIC1111/stable-diffusion-webui\nhttps://github.com/AUTOMATIC1111/stable-diffusion-webui/issues/9074 (2025年7月12日)\nnode.js - WebSockets and Apache proxy: how to configure mod_proxy_wstunnel? - Stack Overflow\nhttps://stackoverflow.com/questions/27526281/websockets-and-apache-proxy-how-to-configure-mod-proxy-wstunnel (2025年7月12日)\nmod_proxy_wstunnel - Apache HTTP Server Version 2.4\nhttps://httpd.apache.org/docs/current/mod/mod_proxy_wstunnel.html (2025年7月12日)\napache - .htaccess: Invalid command \u0026lsquo;RewriteEngine\u0026rsquo;, perhaps misspelled or defined by a module not included in the server configuration - Stack Overflow\nhttps://stackoverflow.com/questions/10144634/htaccess-invalid-command-rewriteengine-perhaps-misspelled-or-defined-by-a-m (2025年7月12日)\nHow can I access the web UI of Stable Diffusion on my PC from another device in my home network? : r/HomeNetworking\nhttps://www.reddit.com/r/HomeNetworking/comments/ybfhp6/how_can_i_access_the_web_ui_of_stable_diffusion/ (2025年7月13日)\nChatGPT\nhttps://chatgpt.com/ (2025年7月12日)\nMemory leak when using SDXL in the latest version of webui automatic111111 : r/StableDiffusion\nhttps://www.reddit.com/r/StableDiffusion/comments/1bq2py3/memory_leak_when_using_sdxl_in_the_latest_version/ (2025年9月14日)\nInsane memory leak · Issue #2219 · lllyasviel/stable-diffusion-webui-forge\nhttps://github.com/lllyasviel/stable-diffusion-webui-forge/issues/2219 (2025年9月14日)\nsystemd.resource-control\nhttps://www.freedesktop.org/software/systemd/man/latest/systemd.resource-control.html (2025年9月14日)\nsystemd memory limit not working/example - Unix \u0026amp; Linux Stack Exchange\nhttps://unix.stackexchange.com/questions/449210/systemd-memory-limit-not-working-example (2025年9月14日)\nsystemd.exec\nhttps://www.freedesktop.org/software/systemd/man/latest/systemd.exec.html (2025年9月14日)\nHow to set fanspeed in Linux from terminal - CUDA / CUDA Programming and Performance - NVIDIA Developer Forums\nhttps://forums.developer.nvidia.com/t/how-to-set-fanspeed-in-linux-from-terminal/72705/6 (2025年9月14日)\nMarkdown Table Generator · Table to Markdown\nhttps://tabletomarkdown.com/generate-markdown-table/ (2025年9月14日)\n【Stable Diffusion WebUI 】 ui-config 活用法。SDXL に合わせて設定を最適化＋デフォルト設定を変更してみた！ #AI - Qiita\nhttps://qiita.com/tonosamart/items/23a612768098870c20ae (2025年10月20日)\nProgress API endpoint · AUTOMATIC1111/stable-diffusion-webui · Discussion #7888\nhttps://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/7888 (2025年10月21日)\nBasic Documentation and Examples for using API · AUTOMATIC1111/stable-diffusion-webui · Discussion #3734\nhttps://github.com/AUTOMATIC1111/stable-diffusion-webui/discussions/3734 (2025年10月21日)\nGoogle Gemini\nhttps://gemini.google.com (2026年1月29日)\nAUR (en) - stable-diffusion-webui-git\nhttps://aur.archlinux.org/packages/stable-diffusion-webui-git (2026年9月6日)\n","permalink":"https://www.nyanmo.info/posts/linux/stablediffusionwebui/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか最近 \u003ca href=\"https://aur.archlinux.org/packages/stable-diffusion-webui\"\u003eAUR に Stable Diffusion WebUI\u003c/a\u003eが出現していて気軽に試せそうだったのでインストールして使ってみたということがあった。\u003c/p\u003e\n\u003cp\u003e　その過程で記録しておきたいことがあったので、Stable Diffusion WebUI の導入過程とともに記事を書こうと思った。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/StableDiffusionWebUI/AUR%e3%81%ae%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"AURの様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"system-details-report\"\u003eSystem Details Report\u003c/h3\u003e\n\u003chr\u003e\n\u003ch4 id=\"report-details\"\u003eReport details\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2025-07-13 20:41:10\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"hardware-information\"\u003eHardware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              HP ProLiant DL60 Gen9\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      32.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Xeon® E5-2620 v4 × 16\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Unknown ※ GTX1080ti\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               30.0 TB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"software-information\"\u003eSoftware Information:\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            U15\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    rolling\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               48\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            X11\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.15.5-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"導入\"\u003e導入\u003c/h2\u003e\n\u003ch3 id=\"yay-コマンドでインストール\"\u003eyay コマンドでインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -Sy stable-diffusion-webui\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"コンフィグの場所\"\u003eコンフィグの場所\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003e/etc/stable-diffusion-webui/webui.conf\u003c/code\u003e\u003c/p\u003e","title":"Stable Diffusion WebUI が AURにあった 🎨"},{"content":"このモデルを作った動機とか なんか、適当に blender で適当に遊んでいたら、PCのディスプレイのモデル置きたいなとなった。\nそれでインターネットでフリーのモデルないか調べたら、なんかめちゃくちゃ作りこまれた有料なモデルだったり、フリーでも会員登録を要求するサイトばかりでうんざりした。\nそれで、自分で手持ちのディスプレイを参考に、適当に簡易的なモックアップ的なものを作り、考える過程で使える程度の手の込み具合のものを用意してみた。\nそのままプライベートに持っていても、もったいないなと思い、ここに置いておくことにする。\nモデル参考画像 表からみた様子 裏から見た様子 3D モデルpreview ダウンロード display.blend 参考にしたサイトとか texturing - Why is my texture blurry on my model? - Blender Stack Exchange\nhttps://blender.stackexchange.com/questions/241783/why-is-my-texture-blurry-on-my-model (2025年7月5日) cycles render engine - How to change a mesh into light - Blender Stack Exchange\nhttps://blender.stackexchange.com/questions/210191/how-to-change-a-mesh-into-light (2025年7月5日) How can I rotate this image texture? Google suggests using a mapping node to rotate it but that makes the image disappear : r/blenderhelp\nhttps://www.reddit.com/r/blenderhelp/comments/jfy603/how_can_i_rotate_this_image_texture_google/ (2025年7月5日) uv - how to resize an image so it shows in its entirety within an object? - Blender Stack Exchange\nhttps://blender.stackexchange.com/questions/57066/how-to-resize-an-image-so-it-shows-in-its-entirety-within-an-object (2025年7月5日) ","permalink":"https://www.nyanmo.info/images/3dmodel/ev2451withnostand/","summary":"\u003ch2 id=\"このモデルを作った動機とか\"\u003eこのモデルを作った動機とか\u003c/h2\u003e\n\u003cp\u003e　なんか、適当に blender で適当に遊んでいたら、PCのディスプレイのモデル置きたいなとなった。\u003c/p\u003e\n\u003cp\u003e　それでインターネットでフリーのモデルないか調べたら、なんかめちゃくちゃ作りこまれた有料なモデルだったり、フリーでも会員登録を要求するサイトばかりでうんざりした。\u003c/p\u003e\n\u003cp\u003e　それで、自分で手持ちのディスプレイを参考に、適当に簡易的なモックアップ的なものを作り、考える過程で使える程度の手の込み具合のものを用意してみた。\u003c/p\u003e\n\u003cp\u003e　そのままプライベートに持っていても、もったいないなと思い、ここに置いておくことにする。\u003c/p\u003e\n\u003ch2 id=\"モデル参考画像\"\u003eモデル参考画像\u003c/h2\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/3Dmodel/EV2451withNoStand/thumbnail.png#center\"/\u003e \u003cfigcaption\u003e\n            表からみた様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/3Dmodel/EV2451withNoStand/back.png#center\"/\u003e \u003cfigcaption\u003e\n            裏から見た様子\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"3d-モデルpreview\"\u003e3D モデルpreview\u003c/h2\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"THREEcontainer253981674 column\"\u003e\n    \u003cdiv class=\"mainView\"\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript type=\"module\"\u003e\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n    \n    \n    \n    \n    \n    \n    \n\n    import * as THREE from 'three';\n    import { GLTFLoader } from 'three/addons/loaders/GLTFLoader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n    \n    \n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n\n    \n    const scene = new THREE.Scene();\n    scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n    scene.add(new THREE.AxesHelper(50))\n\n    \n    const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n    const container = document.querySelector(\".THREEcontainer253981674\")\n    const mainView  = container.querySelector(\".mainView\")\n    const renderer = new THREE.WebGLRenderer();\n    renderer.setSize(screenSize.width,screenSize.height);\n    renderer.shadowMap.enabled = true;\n    mainView.appendChild( renderer.domElement );\n    \n    \n    const controls = new OrbitControls(camera, renderer.domElement)\n    controls.enableDamping = true\n\n\n    \n    const buttons = container.querySelector(\".MMDcontroler.column\")\n    const fullscreen = buttons.querySelector(\"#fullscreen\")\n\n    fullscreen.addEventListener(\"click\", () =\u003e {\n        mainView.requestFullscreen()\n    })\n\n    mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n        let width = 0\n        let height = 0\n        if(document.fullscreenElement){\n            width   = window.innerWidth\n            height  = window.outerHeight\n            \n            \n            \n        }else{\n            width   = screenSize.width\n            height  = screenSize.height\n            \n        }\n        \n        \n        console.log(width)\n        console.log(height)\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(width, height);\n        \n        camera.aspect = width / height;\n        camera.updateProjectionMatrix();\n        \n    })\n    \n\n\n    \n    const loader = new GLTFLoader();\n    loader.load( '\\/images\\/3Dmodel\\/EV2451withNoStand\\/display.glb', function (gltf) {        \n        gltf.scene.position.x = Number(\"0\")\n        gltf.scene.position.y = Number(\"20\")\n        gltf.scene.position.z = Number(\"20\")\n        gltf.scene.rotation.x = Math.PI * Number(\"0\") / 180.0\n        gltf.scene.rotation.y = Math.PI * Number(\"0\") / 180.0\n        gltf.scene.rotation.z = Math.PI * Number(\"0\") / 180.0\n        gltf.scene.scale.x = Number(\"6\")\n        gltf.scene.scale.y = Number(\"6\")\n        gltf.scene.scale.z = Number(\"6\")\n\n        scene.add( gltf.scene )\n    }, undefined, function ( error ) {\n        console.error( error );\n    } );\n\n\n\n    \n    let lightPosOffset = Number(\"200\")\n    const lightPos = [\n        {x:0,y:0,z:0},\n\n        {x:lightPosOffset,y:0 ,z:0},\n        {x:-lightPosOffset,y:0 ,z:0},\n\n        {x:0,y:lightPosOffset ,z:0},\n        {x:0,y:-lightPosOffset ,z:0},\n\n        {x:0,y:0 ,z:lightPosOffset},\n        {x:0,y:0 ,z:-lightPosOffset},\n\n        {x:0,y:lightPosOffset ,z:lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:lightPosOffset},\n        {x:0,y:lightPosOffset ,z:-lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:lightPosOffset,y:0 ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:lightPosOffset ,z:0},\n        {x:lightPosOffset,y:-lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:0},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n    ] \n\n    \n    const color = 0xFFFFFF;\n    const intensity = Number(\"1\");\n    for(let pos of lightPos){\n        let light =  new THREE.DirectionalLight(color, intensity);\n        light.position.set(pos.x, pos.y,pos.z);\n        scene.add(light);\n    }\n\n\n\n    \n    \n    camera.position.set(\n        Number(\"10\"),\n        Number(\"25\"),\n        Number(\"70\")\n    )\n    controls.target.set(\n        Number(\"0\"),\n        Number(\"20\"),\n        Number(\"0\")\n    )\n\n\n\n    \n    function animate() {\n        renderer.render( scene, camera );\n        controls.update()\n    }\n    renderer.setAnimationLoop( animate );\n\u003c/script\u003e\u003c/p\u003e","title":"EV2451 もどき（スタンドなし）"},{"content":"この記事を作った動機 hugo を使っていて、解決に手こずったことがあったのでそれを記録しようと思っただけ。\n問題を解消するには タグ名、もしくはヘッダーのアイテムの項目の識別子がかぶらないように変更する。\n今回は、hugo.yamlのidentifierの内容を、\u0026ldquo;idea\u0026quot;から、\u0026ldquo;ideaList\u0026quot;に変更する例を示す。実際にはこれ以外にも任意の名前に変更しても問題ないと思われる。\nとある記事.md の例 +++ date = \u0026#39;2025-06-10T07:11:01+09:00\u0026#39; draft = false title = \u0026#39;EC 開発\u0026#39; tags = [\u0026#39;ChatGPT\u0026#39;, \u0026#39;Idea\u0026#39; , \u0026#39;BGA\u0026#39; , \u0026#39;Research\u0026#39;] showToc = true +++ ... hugo.yaml の例 修正前 ... menu: main: ... - identifier: \u0026#34;Images\u0026#34; name: \u0026#34;Images\u0026#34; url: \u0026#34;/images/\u0026#34; weight: 3 - identifier: \u0026#34;idea\u0026#34; name: \u0026#34;Idea\u0026#34; url: \u0026#34;/posts/idea/\u0026#34; weight: 5 ... 修正後 ... menu: main: ... - identifier: \u0026#34;Images\u0026#34; name: \u0026#34;Images\u0026#34; url: \u0026#34;/images/\u0026#34; weight: 3 - identifier: \u0026#34;ideaList\u0026#34; name: \u0026#34;Idea\u0026#34; url: \u0026#34;/posts/idea/\u0026#34; weight: 5 ... どういうときに症状が再現する？ 各記事ごとのタグ名と、ヘッダーのアイテムの項目の識別子がかぶっているとき。今回は、\u0026ldquo;Idea\u0026quot;という項目がかぶっている例を示す。\nとある記事.md tags 内に、\u0026ldquo;Idea\u0026quot;がある\n+++ date = \u0026#39;2025-06-10T07:11:01+09:00\u0026#39; draft = false title = \u0026#39;EC 開発\u0026#39; tags = [\u0026#39;ChatGPT\u0026#39;, \u0026#39;Idea\u0026#39; , \u0026#39;BGA\u0026#39; , \u0026#39;Research\u0026#39;] showToc = true +++ ... hugo.yaml identifierとして、\u0026ldquo;idea\u0026quot;が存在する。（大文字と小文字は区別してないのかわからないが、\u0026ldquo;idea\u0026quot;と\u0026quot;Idea\u0026quot;は多分同じ扱いになっている)\n... menu: main: ... - identifier: \u0026#34;Images\u0026#34; name: \u0026#34;Images\u0026#34; url: \u0026#34;/images/\u0026#34; weight: 3 - identifier: \u0026#34;idea\u0026#34; name: \u0026#34;Idea\u0026#34; url: \u0026#34;/posts/idea/\u0026#34; weight: 5 ... どんなエラーが出る？ 最初は何のことかさっぱりだったが、GetPage: page reference \u0026quot;idea\u0026quot; is ambiguousと言われていることに気づいた。以下は一応無理やり改行したり、インデントをつけてみたが、どうあがいてもエラー文は読みやすくはならなかった。。。\nちなみに実際には、これは一行で一つでまとまってごちゃごちゃに表示されるため、かなり具体的に何が悪いのか、わかりづらい状態である。何というか、低レベルな実装の詳細なエラーが出ているという感じである。\nERROR render of \u0026#34;/categories\u0026#34; failed: \u0026#34;/PathToProjectRoot/layouts/_default/baseof.html:20:8\u0026#34;: execute of template failed: template: _default/terms.html:20:8: executing \u0026#34;_default/terms.html\u0026#34; at \u0026lt;partialCached \u0026#34;header.html\u0026#34; . .Page\u0026gt;: error calling partialCached: \u0026#34;/PathToProjectRoot/themes/PaperMod/layouts/partials/header.html:127:38\u0026#34;: execute of template failed: template: _partials/header.html:127:38: executing \u0026#34;_partials/header.html\u0026#34; at \u0026lt;site.GetPage\u0026gt;: error calling GetPage: page reference \u0026#34;idea\u0026#34; is ambiguous # 似たようなエラーがいくつかズラリと並ぶ。 ... 参考にしたサイトとか GetPage\nhttps://gohugo.io/methods/page/getpage/ (2025年6月25日) Ambiguous reference in new .GetPage - support - HUGO\nhttps://discourse.gohugo.io/t/ambiguous-reference-in-new-getpage/13161/6 (2025年6月25日) ","permalink":"https://www.nyanmo.info/posts/hugo/getpagetooambiguouserror/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　hugo を使っていて、解決に手こずったことがあったのでそれを記録しようと思っただけ。\u003c/p\u003e\n\u003ch2 id=\"問題を解消するには\"\u003e問題を解消するには\u003c/h2\u003e\n\u003cp\u003e　タグ名、もしくはヘッダーのアイテムの項目の識別子がかぶらないように変更する。\u003c/p\u003e\n\u003cp\u003e　今回は、hugo.yamlの\u003ccode\u003eidentifier\u003c/code\u003eの内容を、\u0026ldquo;idea\u0026quot;から、\u0026ldquo;ideaList\u0026quot;に変更する例を示す。実際にはこれ以外にも任意の名前に変更しても問題ないと思われる。\u003c/p\u003e\n\u003ch3 id=\"とある記事md-の例\"\u003eとある記事.md の例\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ndate = \u0026#39;2025-06-10T07:11:01+09:00\u0026#39;\ndraft = false\ntitle = \u0026#39;EC 開発\u0026#39;\ntags = [\u0026#39;ChatGPT\u0026#39;, \u0026#39;Idea\u0026#39; , \u0026#39;BGA\u0026#39; , \u0026#39;Research\u0026#39;]\nshowToc = true\n+++\n...\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"hugoyaml-の例\"\u003ehugo.yaml の例\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e修正前\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003emenu\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003emain\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003eidentifier\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Images\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Images\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/images/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eweight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003eidentifier\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;idea\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Idea\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/posts/idea/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eweight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e修正後\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003emenu\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003emain\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003eidentifier\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Images\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Images\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/images/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eweight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        - \u003cspan style=\"color:#f92672\"\u003eidentifier\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ideaList\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003ename\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Idea\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eurl\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/posts/idea/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#f92672\"\u003eweight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"どういうときに症状が再現する\"\u003eどういうときに症状が再現する？\u003c/h2\u003e\n\u003cp\u003e　各記事ごとのタグ名と、ヘッダーのアイテムの項目の識別子がかぶっているとき。今回は、\u0026ldquo;Idea\u0026quot;という項目がかぶっている例を示す。\u003c/p\u003e","title":"Hugo と PaperMod テーマ でうまくサイトが生成できない (.GetPage)"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 概要 2in1ノートPCを持っているが、XPS 13 2in1 の方の動作がいまいちよくなく、新しいものが欲しいなとなった時があったが、中古で、intel core i5 8thくらいを狙っていたが、正直微妙な値段でしか買えないことが分かった。\nそこで、自分で最終的には、液晶パネルの裏や表に、ペンタブレット機能のための基盤を追加して、普通のノートPCを2in1に改造できるようにしたい。\nオープンソースでいろんな形、サイズのペンタブ基盤が作れるようにできると、うれしい気がする。\nまずは、どんな動作をするのか調べてみて、基盤を簡単に試作してみたいとは思う。JLCpcbを使って、格子状になるように描いたパターンが裏表にある基盤を、作り、オシロスコープでどんな動きをするか、見てみるというところからスタートかもしれない。\nそれでだんだん、具体的にどうやってマイコンとかで制御をかけて、HIDとしてPCに認識させ、動かすか考えていくことになると思われる。\nChatGPT Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月23日) ","permalink":"https://www.nyanmo.info/posts/idea/research/pentablet/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"概要\"\u003e概要\u003c/h2\u003e\n\u003cp\u003e　2in1ノートPCを持っているが、XPS 13 2in1 の方の動作がいまいちよくなく、新しいものが欲しいなとなった時があったが、中古で、intel core i5 8thくらいを狙っていたが、正直微妙な値段でしか買えないことが分かった。\u003c/p\u003e\n\u003cp\u003e　そこで、自分で最終的には、液晶パネルの裏や表に、ペンタブレット機能のための基盤を追加して、普通のノートPCを2in1に改造できるようにしたい。\u003c/p\u003e\n\u003cp\u003e　オープンソースでいろんな形、サイズのペンタブ基盤が作れるようにできると、うれしい気がする。\u003c/p\u003e\n\u003cp\u003e　まずは、どんな動作をするのか調べてみて、基盤を簡単に試作してみたいとは思う。JLCpcbを使って、格子状になるように描いたパターンが裏表にある基盤を、作り、オシロスコープでどんな動きをするか、見てみるというところからスタートかもしれない。\u003c/p\u003e\n\u003cp\u003e　それでだんだん、具体的にどうやってマイコンとかで制御をかけて、HIDとしてPCに認識させ、動かすか考えていくことになると思われる。\u003c/p\u003e\n\u003ch2 id=\"chatgpt\"\u003eChatGPT\u003c/h2\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/pentablet/%e8%b2%b7%e3%81%84%e7%89%a9%e3%81%ae%e6%b1%ba%e6%96%ad%e5%a3%81.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/pentablet/%e8%b2%b7%e3%81%84%e7%89%a9%e3%81%ae%e6%b1%ba%e6%96%ad%e5%a3%81.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月23日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ペンタブを作って、液タブを作りたい"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 概要 chatGPT を研究の補助としてどれだけ使えるか試す。具体的にどんなことができて、どんなことができないのか、問題があるのかを探る研究として。\n現時点で分かったこと、気になること ChatGPT はただ間違うだけでなく、ほとんどすべてのことをポジティブに変換してしまう。これは、ネガティブなポイントについて無関心であることに近しく、問題があると思われる。ポジティブなことの何が問題で、何がそうでないかはまだ見えていない。\nあと、ChatGPT は基本的に、人間の延長線上的な動作をしていて、人間が間違えたり、うまく答えを出せないようなことが起こるため、人間を超える存在としての期待はよくない。\nChatGPTを含め、LLMは基本的に、学習データや事前プロンプトに依存して、返答する内容が大きく変わる。これはモデル作成者やモデルを調整した人々の主観や恣意的な視点が、強く反映されることを意味する。\nあと質問の仕方を大きくプロンプトに影響を及ぼす。文脈や背景などを十分に表現できていないと、期待したような回答を得られない可能性がある。また、使い方として、LLMが吐き出した内容を再びLLMに取り込むことで、回答が洗練されないか試すなどもある。\nAIと人は比べられないのではないかということについて調べるのもありかもしれない。\n思った通りの出力結果にならなかったとき、誤解や曲解のように感じられる結果、勝手な補完があるときがあり、非常に不快な気持ちになるのを避けられない場合がある。プロンプトである程度誤解や曲解のように感じられる結果を避けるために明示はできるかもしれないが、限界があると思われる。\n明確でない部分があったりすると、LLMは勝手に情報をそれっぽく見せるために補完する恐れがある。\nChatGPTなどに埋め込まれている監視AIについて、どれだけ偏見や偏りがあり、問題があるか確かめる研究というのも一つあるかもしれない。学習データは結局特定の限られた特定の価値観や考え方を持つ人の手がかかっていることや、AIモデル自体は何も考えず、重みに従って入力を変形して出力しているという仕組み上のからも、仕組み的に中立的なAIモデルを作るのは限界があると思われ、どこか差別的で、誰かの偏った個人的な正義や正しさ、間違いなどの定義を大いに含んでいると思われる。現状だとどうあがいてもAIモデルが偏ったり、網羅性に欠けることは避けられないと思われる。\n少なくとも chatGPT は、URLを含めてプロンプトを送ると「ブログ記事拝見しました。」などと返ってくるが、実際に見ているか怪しく、それっぽく返答しているだけに見える。”拝見した”結果としてありもしないことを平気で返してくる。\nAIモデルは基本偏っているので、偏っていることを前提とし、ある種の人格みたいな感じで作られたモデル一つ一つをみなして、みるというのもあるのかもしれない？たとえば、GPT-4o は常にポジティブなことしか返さない人（何も考えることはできないAIモデル）なんだなみたいな？\nやれそうなこと 具体的に問題のあるシーンを再現する LLMの回答をLLM自身に評価させ、洗練されないか試す 研究の案の意図が会話が進むにつれ崩壊するのか 出力された回答の扱い方について、どんな項目がありそうか書き出す。 そもそも単純に、AIと人間の優劣がどうのという比較は適切ではないということについて調べる。 LLMが勝手にどう物事を補完してしまうかいろいろプロンプトを試す LLMのレスポンスに含まれる、ポジティブ、ネガティブな言葉を検出して、それらを赤や青色で色付けし、どのくらい会話が偏っているか指標を示す 難しそうなこと ChatGPTなどは同じプロンプトでも、異なる回答をその都度返してくる　→ 再現性に難がある。 評価基準を決めずらい Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月25日) ","permalink":"https://www.nyanmo.info/posts/idea/research/chatgptascopilot/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"概要\"\u003e概要\u003c/h2\u003e\n\u003cp\u003e　chatGPT を研究の補助としてどれだけ使えるか試す。具体的にどんなことができて、どんなことができないのか、問題があるのかを探る研究として。\u003c/p\u003e\n\u003ch2 id=\"現時点で分かったこと気になること\"\u003e現時点で分かったこと、気になること\u003c/h2\u003e\n\u003cp\u003e　ChatGPT はただ間違うだけでなく、ほとんどすべてのことをポジティブに変換してしまう。これは、ネガティブなポイントについて無関心であることに近しく、問題があると思われる。ポジティブなことの何が問題で、何がそうでないかはまだ見えていない。\u003c/p\u003e\n\u003cp\u003e　あと、ChatGPT は基本的に、人間の延長線上的な動作をしていて、人間が間違えたり、うまく答えを出せないようなことが起こるため、人間を超える存在としての期待はよくない。\u003c/p\u003e\n\u003cp\u003e　ChatGPTを含め、LLMは基本的に、学習データや事前プロンプトに依存して、返答する内容が大きく変わる。これはモデル作成者やモデルを調整した人々の主観や恣意的な視点が、強く反映されることを意味する。\u003c/p\u003e\n\u003cp\u003e　あと質問の仕方を大きくプロンプトに影響を及ぼす。文脈や背景などを十分に表現できていないと、期待したような回答を得られない可能性がある。また、使い方として、LLMが吐き出した内容を再びLLMに取り込むことで、回答が洗練されないか試すなどもある。\u003c/p\u003e\n\u003cp\u003e　AIと人は比べられないのではないかということについて調べるのもありかもしれない。\u003c/p\u003e\n\u003cp\u003e　思った通りの出力結果にならなかったとき、誤解や曲解のように感じられる結果、勝手な補完があるときがあり、非常に不快な気持ちになるのを避けられない場合がある。プロンプトである程度誤解や曲解のように感じられる結果を避けるために明示はできるかもしれないが、限界があると思われる。\u003c/p\u003e\n\u003cp\u003e　明確でない部分があったりすると、LLMは勝手に情報をそれっぽく見せるために補完する恐れがある。\u003c/p\u003e\n\u003cp\u003e　ChatGPTなどに埋め込まれている監視AIについて、どれだけ偏見や偏りがあり、問題があるか確かめる研究というのも一つあるかもしれない。学習データは結局特定の限られた特定の価値観や考え方を持つ人の手がかかっていることや、AIモデル自体は何も考えず、重みに従って入力を変形して出力しているという仕組み上のからも、仕組み的に中立的なAIモデルを作るのは限界があると思われ、どこか差別的で、誰かの偏った個人的な正義や正しさ、間違いなどの定義を大いに含んでいると思われる。現状だとどうあがいてもAIモデルが偏ったり、網羅性に欠けることは避けられないと思われる。\u003c/p\u003e\n\u003cp\u003e　少なくとも chatGPT は、URLを含めてプロンプトを送ると「ブログ記事拝見しました。」などと返ってくるが、実際に見ているか怪しく、それっぽく返答しているだけに見える。”拝見した”結果としてありもしないことを平気で返してくる。\u003c/p\u003e\n\u003cp\u003e　AIモデルは基本偏っているので、偏っていることを前提とし、ある種の人格みたいな感じで作られたモデル一つ一つをみなして、みるというのもあるのかもしれない？たとえば、GPT-4o は常にポジティブなことしか返さない人（何も考えることはできないAIモデル）なんだなみたいな？\u003c/p\u003e\n\u003ch2 id=\"やれそうなこと\"\u003eやれそうなこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e具体的に問題のあるシーンを再現する\u003c/li\u003e\n\u003cli\u003eLLMの回答をLLM自身に評価させ、洗練されないか試す\u003c/li\u003e\n\u003cli\u003e研究の案の意図が会話が進むにつれ崩壊するのか\u003c/li\u003e\n\u003cli\u003e出力された回答の扱い方について、どんな項目がありそうか書き出す。\u003c/li\u003e\n\u003cli\u003eそもそも単純に、AIと人間の優劣がどうのという比較は適切ではないということについて調べる。\u003c/li\u003e\n\u003cli\u003eLLMが勝手にどう物事を補完してしまうかいろいろプロンプトを試す\u003c/li\u003e\n\u003cli\u003eLLMのレスポンスに含まれる、ポジティブ、ネガティブな言葉を検出して、それらを赤や青色で色付けし、どのくらい会話が偏っているか指標を示す\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"難しそうなこと\"\u003e難しそうなこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPTなどは同じプロンプトでも、異なる回答をその都度返してくる　→ 再現性に難がある。\u003c/li\u003e\n\u003cli\u003e評価基準を決めずらい\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月25日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ChatGPT を研究に使う研究"},{"content":"この記事を作った動機 単に簡易的にメッセージボックス的なものを出す方法を記録するだけ。Toast とかいう名前の API で、win32 API とかの MessageBox と比べて、だいぶ非直感的な名前な気がする。まあ多用すれば慣れるってことなんでしょうけど。。。\nメッセージを出す 今回は、ボタンを押したらメッセージが出てくるようにする例を置いてみる。\n// 呼び出されたアクティビティの onCreate 関数内にて val registerButton = findViewById\u0026lt;Button\u0026gt;(R.id.Register) registerButton.setOnClickListener{ Toast.makeText(this, \u0026#34;test\u0026#34;, Toast.LENGTH_SHORT).show() finish() } 参考にしたサイトとか Toasts overview | Android Developers\nhttps://developer.android.com/guide/topics/ui/notifiers/toasts (2025年6月24日) MessageBox function (winuser.h) - Win32 apps | Microsoft Learn\nhttps://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox (2025年6月24日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/showmessageboxequivalentui/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に簡易的にメッセージボックス的なものを出す方法を記録するだけ。Toast とかいう名前の API で、win32 API とかの MessageBox と比べて、だいぶ非直感的な名前な気がする。まあ多用すれば慣れるってことなんでしょうけど。。。\u003c/p\u003e\n\u003ch2 id=\"メッセージを出す\"\u003eメッセージを出す\u003c/h2\u003e\n\u003cp\u003e　今回は、ボタンを押したらメッセージが出てくるようにする例を置いてみる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 呼び出されたアクティビティの onCreate 関数内にて\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e registerButton = findViewById\u0026lt;Button\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.Register)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        registerButton.setOnClickListener{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eToast\u003c/span\u003e.makeText(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eToast\u003c/span\u003e.LENGTH_SHORT).show()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            finish()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/android/androidStudio/showMessageBoxEquivalentUI/%e3%83%a1%e3%83%83%e3%82%bb%e3%83%bc%e3%82%b8%e8%a1%a8%e7%a4%ba%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"メッセージ表示の例\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eToasts overview  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/guide/topics/ui/notifiers/toasts\"\u003ehttps://developer.android.com/guide/topics/ui/notifiers/toasts\u003c/a\u003e (2025年6月24日)\u003c/li\u003e\n\u003cli\u003eMessageBox function (winuser.h) - Win32 apps | Microsoft Learn\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox\"\u003ehttps://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-messagebox\u003c/a\u003e (2025年6月24日)\u003c/li\u003e\n\u003c/ul\u003e","title":"メッセージボックスを出す"},{"content":"この記事を作った動機 アクティビティの遷移方法をたんに記録するだけ。今回は二つの実装について書く。一つは単に、前のアクティビティに戻るだけで、もう一つは何か処理をしてから戻る方法について書く。\nただ戻るだけの時 具体的な処理をしない場合については以下のように実装できる。AndroidManifest.xml に親アクティビティ(android:parentActivityName)を設定する。コードは不要な模様。\n... \u0026lt;activity android:name=\u0026#34;.loginActivity\u0026#34; android:exported=\u0026#34;false\u0026#34; android:label=\u0026#34;@string/login_activity\u0026#34; android:parentActivityName=\u0026#34;.shareFolderListActivity1\u0026#34;/\u0026gt; ... 何か処理をしてから戻りたいとき 今回の場合でいえば、登録ボタンを押したら、フォームに打たれた情報をもとに何かしら処理を施してから元のアクティビティに戻りたい時は、以下のように finish() を呼び出す。\n... // 呼び出されたアクティビティの onCreate 関数内にて val registerButton = findViewById\u0026lt;Button\u0026gt;(R.id.Register) registerButton.setOnClickListener{ // 何かしらの処理 finish() } ... 参考にしたサイトとか How to Go Back to Previous Activity in Android? - GeeksforGeeks\nhttps://www.geeksforgeeks.org/how-to-go-back-to-previous-activity-in-android/ (2025年6月24日) Go Back to Previous Activity in Android\nhttps://www.tutorialspoint.com/how-to-go-back-to-previous-activity-in-android (2025年6月24日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/backtopreviousactivity/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　アクティビティの遷移方法をたんに記録するだけ。今回は二つの実装について書く。一つは単に、前のアクティビティに戻るだけで、もう一つは何か処理をしてから戻る方法について書く。\u003c/p\u003e\n\u003ch2 id=\"ただ戻るだけの時\"\u003eただ戻るだけの時\u003c/h2\u003e\n\u003cp\u003e　具体的な処理をしない場合については以下のように実装できる。AndroidManifest.xml に親アクティビティ(android:parentActivityName)を設定する。コードは不要な模様。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;activity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.loginActivity\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:exported=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;false\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:label=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@string/login_activity\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:parentActivityName=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.shareFolderListActivity1\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/android/androidStudio/backToPreviousActivity/%e3%81%9f%e3%81%a0%e6%88%bb%e3%82%8b%e3%81%a0%e3%81%91%e3%81%ae%e4%be%8b.png#center\"\n         alt=\"ただ戻るだけの例\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"何か処理をしてから戻りたいとき\"\u003e何か処理をしてから戻りたいとき\u003c/h2\u003e\n\u003cp\u003e　今回の場合でいえば、登録ボタンを押したら、フォームに打たれた情報をもとに何かしら処理を施してから元のアクティビティに戻りたい時は、以下のように \u003ccode\u003efinish()\u003c/code\u003e を呼び出す。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 呼び出されたアクティビティの onCreate 関数内にて\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e registerButton = findViewById\u0026lt;Button\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.Register)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        registerButton.setOnClickListener{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// 何かしらの処理\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            finish()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;column;\u003e\n    \n    \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n    \n    \n    \n        \n        \n    \n            \u003cvideo style=\"margin:10px; width: 60%;\" src=/posts/android/androidStudio/backToPreviousActivity/%e3%83%9c%e3%82%bf%e3%83%b3%e3%81%a7%e5%ae%9f%e8%a3%85%e3%81%97%e3%81%9f%e4%be%8b.mp4 controls/\u003e\n            \n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHow to Go Back to Previous Activity in Android? - GeeksforGeeks\u003cbr\u003e\n\u003ca href=\"https://www.geeksforgeeks.org/how-to-go-back-to-previous-activity-in-android/\"\u003ehttps://www.geeksforgeeks.org/how-to-go-back-to-previous-activity-in-android/\u003c/a\u003e (2025年6月24日)\u003c/li\u003e\n\u003cli\u003eGo Back to Previous Activity in Android\u003cbr\u003e\n\u003ca href=\"https://www.tutorialspoint.com/how-to-go-back-to-previous-activity-in-android\"\u003ehttps://www.tutorialspoint.com/how-to-go-back-to-previous-activity-in-android\u003c/a\u003e (2025年6月24日)\u003c/li\u003e\n\u003c/ul\u003e","title":"前のアクティビティに戻る"},{"content":"この記事を作った動機 ちょっと自分のために、アクティビティの呼び出し方をまとめるだけ。今回はボタンが押されたら、特定のアクティビティを呼び出すという動作について、例を載せておく。\nアクティビティの呼び出し方(onCreate 関数内) val loginUIcall = findViewById\u0026lt;FloatingActionButton\u0026gt;(R.id.loginUIcall) loginUIcall.setOnClickListener { val activity = Intent(this,loginActivity::class.java) startActivity(activity) } 参考にしたサイトとか インテントとインテント フィルタ | App architecture | Android Developers\nhttps://developer.android.com/guide/components/intents-filters?hl=ja (2025年6月22日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/callactivity/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　ちょっと自分のために、アクティビティの呼び出し方をまとめるだけ。今回はボタンが押されたら、特定のアクティビティを呼び出すという動作について、例を載せておく。\u003c/p\u003e\n\u003ch2 id=\"アクティビティの呼び出し方oncreate-関数内\"\u003eアクティビティの呼び出し方(onCreate 関数内)\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e loginUIcall = findViewById\u0026lt;FloatingActionButton\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.loginUIcall)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        loginUIcall.setOnClickListener {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e activity = Intent(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e,loginActivity\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e.java)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            startActivity(activity)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eインテントとインテント フィルタ  |  App architecture  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/guide/components/intents-filters?hl=ja\"\u003ehttps://developer.android.com/guide/components/intents-filters?hl=ja\u003c/a\u003e (2025年6月22日)\u003c/li\u003e\n\u003c/ul\u003e","title":"アクティビティを呼び出す"},{"content":"この記事を作った動機 Android アプリでネットワーク接続に対応する の続きの記事です。前の記事でやっていたことに関して、進展があったので、とりあえず忘れないうちに記録しようというわけです。\nまあ、理解より先に動くことを試していたので、間違ったこととかも書いていること大いにあり得ます。これはあくまで自分の理解を深めるために記事として書いてしまおうという感じです。ご注意ください。（それは他の記事でも言えることですが。。。）\nコード 専用クラス(ViewModel)にて ... class smbOperation1 : ViewModel(){ private val userLiveData = MutableLiveData\u0026lt;String\u0026gt;() val user: LiveData\u0026lt;String\u0026gt; get() = userLiveData init { // trigger user load. } fun doAction() { viewModelScope.launch { val test = withContext (Dispatchers.IO) { testSMB() } userLiveData.value = test } } ... } アクティビティ内にて ... class shareFolderListActivity1 : AppCompatActivity() { // https://github.com/hierynomus/smbj private val smb by viewModels\u0026lt;smbOperation1\u0026gt;() override fun onCreate(savedInstanceState: Bundle?) { ... val debugTestStart = findViewById\u0026lt;Button\u0026gt;(R.id.debugTestStart) val debugText = findViewById\u0026lt;TextView\u0026gt;(R.id.resultAndDebugConsole) smb.user.observe (this){ message: String -\u0026gt; debugLog(message) debugText.setText(message) } debugTestStart.setOnClickListener{ smb.doAction() } } ... } わかったこと（現時点での理解） LiveData というのを使う方仕組みの方が新しいっぽい AsyncTask クラスとは異なる、kotlin 側で用意されたスレッド管理の仕組みを使う方が簡単そう LiveData UI と ViewModel クラス間におけるデータの橋渡し的なやり取りを行う。UIスレッド側で監視される変数的なものである。ViewModel クラスのインスタンスのうち、 LiveData に変更があり次第オブザーバー内に登録された処理が実行され、UIが更新される。\nViewModel 内のメンバ変数として private val userLiveData = MutableLiveData\u0026lt;String\u0026gt;() val user: LiveData\u0026lt;String\u0026gt; get() = userLiveData Activity 内の onCrete 内にて val debugTestStart = findViewById\u0026lt;Button\u0026gt;(R.id.debugTestStart) val debugText = findViewById\u0026lt;TextView\u0026gt;(R.id.resultAndDebugConsole) smb.user.observe (this){ message: String -\u0026gt; debugLog(message) debugText.setText(message) } debugTestStart.setOnClickListener{ smb.doAction() } coroutines kotlin で用意された、スレッディングの仕組みだと思う。Android開発においては、例えば、コンテキストとして、以下のようなものが用意されている。\nDispatchers.Main Dispatchers.Default Dispatchers.IO 今回は SMB のためにネットワークの処理を行うので、Dispatchers.IO のコンテキストを利用した。\nsuspend 詳しいことはまだよくわかっていないが、少なくとも susupend 修飾子がついた関数は、同じように susupend 修飾子がついている関数か、viewModelScope.launchからしか呼び出して、実行することができない。\nwithContext withContext自体は、susupend 関数なので、直接通常の関数から呼び出すことはできない。以下のように、viewModelScope.launchと併用するのが、一つのwithContext関数の使い方っぽい。\nviewModelScope.launch { val test = withContext (Dispatchers.IO) { testSMB() } userLiveData.value = test } withContext関数自体は、kotlin 側で用意された、\nDispatchers.Main Dispatchers.Default Dispatchers.IO のどれかのコンテキストを選んで、coroutines の仕組み上で何かしらの処理をさせるためにあるっぽい。\ncoroutines でも書いたように、今回は、ネットワーク用のスレッドコンテキストとして、Dispatchers.IO を試した。\n前の記事 Android アプリでネットワーク接続に対応する 次の記事 今のところなし\n参考にしたサイトとか android - Why does viewModelScope.launch run on the main thread by default - Stack Overflow\nhttps://stackoverflow.com/questions/62166878/why-does-viewmodelscope-launch-run-on-the-main-thread-by-default (2025年6月21日) Coroutines on Android (part I): Getting the background | by Sean McQuillan | Android Developers | Medium\nhttps://medium.com/androiddevelopers/coroutines-on-android-part-i-getting-the-background-3e0e54d20bb (2025年6月21日) launch | kotlinx.coroutines – Kotlin Programming Language\nhttps://kotlinlang.org/api/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.html (2025年6月21日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/appwithnetworking1/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/android/androidstudio/appwithnetworking/\"\u003eAndroid アプリでネットワーク接続に対応する\u003c/a\u003e の続きの記事です。前の記事でやっていたことに関して、進展があったので、とりあえず忘れないうちに記録しようというわけです。\u003c/p\u003e\n\u003cp\u003e　まあ、理解より先に動くことを試していたので、間違ったこととかも書いていること大いにあり得ます。これはあくまで自分の理解を深めるために記事として書いてしまおうという感じです。ご注意ください。（それは他の記事でも言えることですが。。。）\u003c/p\u003e\n\u003ch2 id=\"コード\"\u003eコード\u003c/h2\u003e\n\u003ch3 id=\"専用クラスviewmodelにて\"\u003e専用クラス(ViewModel)にて\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esmbOperation1\u003c/span\u003e : ViewModel(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e userLiveData = MutableLiveData\u0026lt;String\u0026gt;()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e user: LiveData\u0026lt;String\u0026gt; \u003cspan style=\"color:#66d9ef\"\u003eget\u003c/span\u003e() = userLiveData\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// trigger user load.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edoAction\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        viewModelScope.launch {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e test = withContext (\u003cspan style=\"color:#a6e22e\"\u003eDispatchers\u003c/span\u003e.IO) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                testSMB()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            userLiveData.\u003cspan style=\"color:#66d9ef\"\u003evalue\u003c/span\u003e = test\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"アクティビティ内にて\"\u003eアクティビティ内にて\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshareFolderListActivity1\u003c/span\u003e : AppCompatActivity() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// https://github.com/hierynomus/smbj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e smb \u003cspan style=\"color:#66d9ef\"\u003eby\u003c/span\u003e viewModels\u0026lt;smbOperation1\u0026gt;()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eoverride\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonCreate\u003c/span\u003e(savedInstanceState: Bundle?) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e debugTestStart = findViewById\u0026lt;Button\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.debugTestStart)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e debugText = findViewById\u0026lt;TextView\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.resultAndDebugConsole)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        smb.user.observe (\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e){ message: String \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            debugLog(message)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            debugText.setText(message)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        debugTestStart.setOnClickListener{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            smb.doAction()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e..\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"わかったこと現時点での理解\"\u003eわかったこと（現時点での理解）\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eLiveData というのを使う方仕組みの方が新しいっぽい\u003c/li\u003e\n\u003cli\u003eAsyncTask クラスとは異なる、kotlin 側で用意されたスレッド管理の仕組みを使う方が簡単そう\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"livedata\"\u003eLiveData\u003c/h3\u003e\n\u003cp\u003e　UI と ViewModel クラス間におけるデータの橋渡し的なやり取りを行う。UIスレッド側で監視される変数的なものである。ViewModel クラスのインスタンスのうち、 LiveData に変更があり次第オブザーバー内に登録された処理が実行され、UIが更新される。\u003c/p\u003e","title":"Android アプリでネットワーク接続に対応するの続き 1"},{"content":"この記事を作った動機 なんか blender で UV マッピングしようとしたらうまくいかず、調べている過程で、もしかしてメッシュの面の向きがおかしいのではないかと思った。\nそれで、面の向きを調べるために、以下の画像に示すように、Face Orientation を有効にしてみた。しかし、何も見えない。\n通常正常に動作していれば、面が赤か青色に面が染まり、面が表向きなのかひっくり返っているのか表示されるはずが、何も見えないという事態に直面した。\nblender はこういうなぜそうなっているのかさえ一人では分からないような、意地悪な動きをするので心が折れそうではあるが、とにかく調べてみたらどうしたらいいか分かったので、それを記録するだけ。\n分かった原因 blender 4.4.3 のデフォルト設定では、面の向きの赤、青の色表示がなぜか透明に設定されており、一切見えない状態になっている。ミスなのか、何か意図があるか、思想的な仕様なのかは不明だが、とにかく理不尽ではある。\n問題の状態と期待している状態の比較 問題の状態 期待している状態 対処方法 設定画面を開く theme(テーマ)設定を開き 3D viewport の項目を展開 Face Orientation の色をクリックして設定を変更 問題の設定 クリックしたときの色選択 問題を解消した状態の設定 面の裏表が視覚的に見えるようになる 参考にしたサイトとか 3d view - Face orientation viewport overlay doesn\u0026rsquo;t show up - Blender Stack Exchange\nhttps://blender.stackexchange.com/questions/315926/face-orientation-viewport-overlay-doesnt-show-up (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/blender/facenormalnotshown/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか blender で UV マッピングしようとしたらうまくいかず、調べている過程で、もしかしてメッシュの面の向きがおかしいのではないかと思った。\u003c/p\u003e\n\u003cp\u003e　それで、面の向きを調べるために、以下の画像に示すように、Face Orientation を有効にしてみた。しかし、何も見えない。\u003c/p\u003e\n\u003cp\u003e　通常正常に動作していれば、面が赤か青色に面が染まり、面が表向きなのかひっくり返っているのか表示されるはずが、何も見えないという事態に直面した。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e5%95%8f%e9%a1%8c%e3%81%ae%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"問題の状態\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　blender はこういうなぜそうなっているのかさえ一人では分からないような、意地悪な動きをするので心が折れそうではあるが、とにかく調べてみたらどうしたらいいか分かったので、それを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"分かった原因\"\u003e分かった原因\u003c/h2\u003e\n\u003cp\u003e　blender 4.4.3 のデフォルト設定では、面の向きの赤、青の色表示がなぜか透明に設定されており、一切見えない状態になっている。ミスなのか、何か意図があるか、思想的な仕様なのかは不明だが、とにかく理不尽ではある。\u003c/p\u003e\n\u003ch2 id=\"問題の状態と期待している状態の比較\"\u003e問題の状態と期待している状態の比較\u003c/h2\u003e\n\u003ch3 id=\"問題の状態\"\u003e問題の状態\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e5%95%8f%e9%a1%8c%e3%81%ae%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"問題の状態\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"期待している状態\"\u003e期待している状態\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e6%9c%9f%e5%be%85%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"期待している状態\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"対処方法\"\u003e対処方法\u003c/h2\u003e\n\u003ch3 id=\"設定画面を開く\"\u003e設定画面を開く\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e8%a8%ad%e5%ae%9a%e7%94%bb%e9%9d%a2%e3%81%ab%e8%a1%8c%e3%81%8f.png#center\"\n         alt=\"設定画面に行く\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"themeテーマ設定を開き-3d-viewport-の項目を展開\"\u003etheme(テーマ)設定を開き 3D viewport の項目を展開\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e5%95%8f%e9%a1%8c%e3%81%ae%e8%a8%ad%e5%ae%9a%e9%a0%85%e7%9b%ae.png#center\"\n         alt=\"問題の設定項目\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"face-orientation-の色をクリックして設定を変更\"\u003eFace Orientation の色をクリックして設定を変更\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e問題の設定\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e5%95%8f%e9%a1%8c%e3%81%ae%e3%81%82%e3%82%8b%e8%a8%ad%e5%ae%9a.png#center\"\n         alt=\"問題のある設定\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003cli\u003eクリックしたときの色選択\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e3%82%a2%e3%83%ab%e3%83%95%e3%82%a1%e3%83%81%e3%83%a3%e3%83%b3%e3%83%8d%e3%83%ab%e3%81%8c%e5%ae%8c%e5%85%a8%e3%81%ab%e3%82%bc%e3%83%ad%e3%81%a7%e3%81%82%e3%82%8b.png#center\"\n             alt=\"アルファチャンネルが完全にゼロである\"/\u003e \n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e3%82%a2%e3%83%ab%e3%83%95%e3%82%a1%e3%83%81%e3%83%a3%e3%83%b3%e3%83%8d%e3%83%ab%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%97%e8%a6%8b%e3%81%88%e3%82%8b%e3%82%88%e3%81%86%e3%81%ab%e3%81%99%e3%82%8b.png#center\"\n             alt=\"アルファチャンネルを設定し見えるようにする\"/\u003e \n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\u003c/li\u003e\n\u003cli\u003e問題を解消した状態の設定\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e5%95%8f%e9%a1%8c%e3%81%8c%e8%a7%a3%e6%b6%88%e3%81%95%e3%82%8c%e3%81%9f%e8%a8%ad%e5%ae%9a.png#center\"\n         alt=\"問題が解消された設定\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"面の裏表が視覚的に見えるようになる\"\u003e面の裏表が視覚的に見えるようになる\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/faceNormalNotShown/%e6%9c%9f%e5%be%85%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"期待している状態\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e3d view - Face orientation viewport overlay doesn\u0026rsquo;t show up - Blender Stack Exchange\u003cbr\u003e\n\u003ca href=\"https://blender.stackexchange.com/questions/315926/face-orientation-viewport-overlay-doesnt-show-up\"\u003ehttps://blender.stackexchange.com/questions/315926/face-orientation-viewport-overlay-doesnt-show-up\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"blender で面の向きの色が表示されない"},{"content":"この記事を作った動機 JLCpcbで基盤を発注しようとしたときに、主導でいちいち部品表(BOM)とかを調整するのはあまりにしんどいので、ツールを使おうと思った。\nそこで、KiCAD JLCPCB tools という拡張機能を使おうとしたのだが、どうもREADMEどうりにしても、うまくいかないことが分かった。どうあがいても、ダウンロードしたファイルのハッシュが合わないというエラーで止まってしまう。\nそれで、拡張機能のダウンロードだけでもやってみようと、エラーも無視してしてみると、なぜか 1kb だけの zip ファイルがダウンロードされ、展開できない。\nひょっとしてと思って、テキストファイルとして開いてみたら、案の定サーバからエラーメッセージが返されていた。どうも kicad と拡張機能側との間で何か問題があることだけは分かった。 \u0026lt;!DOCTYPE HTML PUBLIC \u0026#34;-//W3C//DTD HTML 4.01//EN\u0026#34;\u0026#34;http://www.w3.org/TR/html4/strict.dtd\u0026#34;\u0026gt; \u0026lt;HTML\u0026gt; \u0026lt;HEAD\u0026gt; \u0026lt;TITLE\u0026gt;Bad Request\u0026lt;/TITLE\u0026gt; \u0026lt;META HTTP-EQUIV=\u0026#34;Content-Type\u0026#34; Content=\u0026#34;text/html; charset=us-ascii\u0026#34;\u0026gt; \u0026lt;/HEAD\u0026gt; \u0026lt;BODY\u0026gt; \u0026lt;h2\u0026gt; Bad Request\u0026lt;/h2\u0026gt; \u0026lt;hr\u0026gt; \u0026lt;p\u0026gt;HTTP Error 400. The request is badly formed.\u0026lt;/p\u0026gt; \u0026lt;/BODY\u0026gt; \u0026lt;/HTML\u0026gt; そこで、今回はどのようにしてそれを対処したのか記録しようという話。\n環境 kicad 9.0 KiCAD JLCPCB tools 2025.04.02 windows 11 24H2 対処方法 タグリストを開く KiCAD JLCPCB toolsの公式ページにのページから以下のようにして、Tags のリストページへ遷移する。 インストールしたいバージョンを選ぶ 私は最新を選んだが、以下の画像で囲っているバージョン以外でも動くようなら大丈夫だと思う。 拡張機能本体をダウンロード kicad のパッケージマネージャを開く ファイルからインストールを選択 問題に気付くまでの過程でやってたこと 公式に書かれている方法をやってみる 1. パッケージマネージャを使う方法 kicadのパッケージマネージャを開く パッケージマネージャに、リポジトリ追加 追加したリポジトリを開く リポジトリを選択しインストールを試みる ちなみに、以下の画像は、問題を再現しようとして、なぜか成功してしまって、エラーが出たときのスクリーンショットを取り損ねたので、雰囲気だけでも置いているだけ。\n今回遭遇した問題では、ハッシュ値が合わないというエラーがそのダイアログにも出る。どうも一度 zip 経由からインストールに成功して前提条件が変わった結果、問題が再発しなくなった模様。\nでもそのために kicad を完全にクリーンインストールして検証するのも面倒なので、そこらへんは置いておくことにする。 リポジトリを選択しとりあえずダウンロードだけでも試みる \u0026lt;!DOCTYPE HTML PUBLIC \u0026#34;-//W3C//DTD HTML 4.01//EN\u0026#34;\u0026#34;http://www.w3.org/TR/html4/strict.dtd\u0026#34;\u0026gt; \u0026lt;HTML\u0026gt; \u0026lt;HEAD\u0026gt; \u0026lt;TITLE\u0026gt;Bad Request\u0026lt;/TITLE\u0026gt; \u0026lt;META HTTP-EQUIV=\u0026#34;Content-Type\u0026#34; Content=\u0026#34;text/html; charset=us-ascii\u0026#34;\u0026gt; \u0026lt;/HEAD\u0026gt; \u0026lt;BODY\u0026gt; \u0026lt;h2\u0026gt; Bad Request\u0026lt;/h2\u0026gt; \u0026lt;hr\u0026gt; \u0026lt;p\u0026gt;HTTP Error 400. The request is badly formed.\u0026lt;/p\u0026gt; \u0026lt;/BODY\u0026gt; \u0026lt;/HTML\u0026gt; 2. 開発者的な手法 これについては疲れたので詳細は省くが、以下のような感じだった。\n公式ページから特定のディレクトリにリポジトリをクローン kicad を再起動してみる 結局何も出てこず。。。\nもしかしたらやり方間違ってるのかもしれない。 手動でパッケージのインストールを試みる JSONを追いかける\nKiCAD JLCPCB toolsの公式ページに書いてある以下の部分に注目してリンクをchromeとかのブラウザで踏む。 KiCAD PCM Add my custom repo to the Plugin and Content Manager, the URL is:\nhttps://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/repository.json packages の url の場所へ飛ぶ https://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/packages.json { \u0026#34;$schema\u0026#34;: \u0026#34;https://gitlab.com/kicad/code/kicad/-/raw/master/kicad/pcm/schemas/pcm.v1.schema.json#/definitions/Repository\u0026#34;, \u0026#34;maintainer\u0026#34;: { ... }, \u0026#34;name\u0026#34;: \u0026#34;Bouni\u0026#39;s KiCad repository\u0026#34;, \u0026#34;packages\u0026#34;: { \u0026#34;sha256\u0026#34;: \u0026#34;e7116006e8f31ef1bf5703ec5a0967c01f0481a34307821fa85e2262f68ac471\u0026#34;, \u0026#34;update_time_utc\u0026#34;: \u0026#34;2025-04-02 11:56:04\u0026#34;, \u0026#34;update_timestamp\u0026#34;: 1743594964, \u0026#34;url\u0026#34;: \u0026#34;https://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/packages.json\u0026#34; }, \u0026#34;resources\u0026#34;: { ... } } パッケージのzipをダウンロード\nversions の download_url の項目に注目し、インストールしたいパッケージを選び直接リンクをブラウザ踏んでダウンロードする。たとえばurlは以下のような形式をしている。 https://github.com/Bouni/kicad-jlcpcb-tools/releases/download/2021.12.1/KiCAD-PCM-2021.12.1.zip { \u0026#34;packages\u0026#34;: [ { \u0026#34;$schema\u0026#34;: \u0026#34;https://go.kicad.org/pcm/schemas/v1\u0026#34;, ... \u0026#34;versions\u0026#34;: [ { \u0026#34;version\u0026#34;: \u0026#34;2021.12.1\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;testing\u0026#34;, \u0026#34;kicad_version\u0026#34;: \u0026#34;6.0\u0026#34;, \u0026#34;download_sha256\u0026#34;: \u0026#34;48611b125a44c254576a809f30c339d3dd876f29ef19dd501892997593e51e51\u0026#34;, \u0026#34;download_size\u0026#34;: 66118, \u0026#34;download_url\u0026#34;: \u0026#34;https://github.com/Bouni/kicad-jlcpcb-tools/releases/download/2021.12.1/KiCAD-PCM-2021.12.1.zip\u0026#34;, \u0026#34;install_size\u0026#34;: 147111 }, { \u0026#34;version\u0026#34;: \u0026#34;2021.12.2\u0026#34;, \u0026#34;status\u0026#34;: \u0026#34;testing\u0026#34;, \u0026#34;kicad_version\u0026#34;: \u0026#34;6.0\u0026#34;, \u0026#34;download_sha256\u0026#34;: \u0026#34;6ec44b5911f8b795dfe77380f683798e8d935dffd40b0f0d48e2a2884ef2c615\u0026#34;, \u0026#34;download_size\u0026#34;: 66205, \u0026#34;download_url\u0026#34;: \u0026#34;https://github.com/Bouni/kicad-jlcpcb-tools/releases/download/2021.12.2/KiCAD-PCM-2021.12.2.zip\u0026#34;, \u0026#34;install_size\u0026#34;: 147592 }, .... zip 経由でインストール kicad のパッケージマネージャを開くと同じようにする。\nURLをよく見てみると、githubのページであることに気づく。\n拡張機能本体をダウンロードと同じwebページで、ダウンロードできるファイルのURLであることに気づく。\n参考にしたサイトとか GitHub - Bouni/kicad-jlcpcb-tools: Plugin to generate BOM + CPL files for JLCPCB, assigning LCSC part numbers directly from the plugin, query the JLCPCB parts database, lookup datasheets and much more.\nhttps://github.com/Bouni/kicad-jlcpcb-tools (2025年6月16日) repository.json\nhttps://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/repository.json (2025年6月16日) packages.json\nhttps://raw.githubusercontent.com/Bouni/bouni-kicad-repository/main/packages.json (2025年6月16日) ","permalink":"https://www.nyanmo.info/posts/hardware/kicad/plugin/kicad_jlcpcb_toolswontinstallviaofficalway/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　JLCpcbで基盤を発注しようとしたときに、主導でいちいち部品表(BOM)とかを調整するのはあまりにしんどいので、ツールを使おうと思った。\u003c/p\u003e\n\u003cp\u003e　そこで、\u003ca href=\"https://github.com/Bouni/kicad-jlcpcb-tools\"\u003eKiCAD JLCPCB tools\u003c/a\u003e という拡張機能を使おうとしたのだが、どうも\u003ca href=\"https://github.com/Bouni/kicad-jlcpcb-tools\"\u003eREADME\u003c/a\u003eどうりにしても、うまくいかないことが分かった。どうあがいても、ダウンロードしたファイルのハッシュが合わないというエラーで止まってしまう。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/kicad/plugin/KiCAD_JLCPCB_toolsWontInstallViaOfficalWay/softwareSide/tryNornalWay/%e5%95%8f%e9%a1%8c%e3%81%ae%e3%82%a8%e3%83%a9%e3%83%bc.png#center\"\n         alt=\"問題のエラー\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　それで、拡張機能のダウンロードだけでもやってみようと、エラーも無視してしてみると、なぜか 1kb だけの zip ファイルがダウンロードされ、展開できない。\u003c/p\u003e\n\u003cp\u003e　ひょっとしてと思って、テキストファイルとして開いてみたら、案の定サーバからエラーメッセージが返されていた。どうも kicad と拡張機能側との間で何か問題があることだけは分かった。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/kicad/plugin/KiCAD_JLCPCB_toolsWontInstallViaOfficalWay/softwareSide/tryNornalWay/%e5%95%8f%e9%a1%8c%e3%81%ae%e3%83%95%e3%82%a1%e3%82%a4%e3%83%ab.png#center\"\n         alt=\"問題のファイル\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE HTML PUBLIC \u0026#34;-//W3C//DTD HTML 4.01//EN\u0026#34;\u0026#34;http://www.w3.org/TR/html4/strict.dtd\u0026#34;\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003eHTML\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eHEAD\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eTITLE\u003c/span\u003e\u0026gt;Bad Request\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eTITLE\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eMETA\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eHTTP-EQUIV\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Content-Type\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eContent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/html; charset=us-ascii\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eHEAD\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003eBODY\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003eh2\u003c/span\u003e\u0026gt; Bad Request\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eh2\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehr\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;HTTP Error 400. The request is badly formed.\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ep\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003eBODY\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003eHTML\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　そこで、今回はどのようにしてそれを対処したのか記録しようという話。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ekicad 9.0\u003c/li\u003e\n\u003cli\u003eKiCAD JLCPCB tools 2025.04.02\u003c/li\u003e\n\u003cli\u003ewindows 11 24H2\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"対処方法\"\u003e対処方法\u003c/h2\u003e\n\u003ch3 id=\"タグリストを開く\"\u003eタグリストを開く\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://github.com/Bouni/kicad-jlcpcb-tools\"\u003eKiCAD JLCPCB toolsの公式ページ\u003c/a\u003eにのページから以下のようにして、Tags のリストページへ遷移する。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/kicad/plugin/KiCAD_JLCPCB_toolsWontInstallViaOfficalWay/taglist.png#center\"\n         alt=\"タグリストを開く\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e","title":"KiCAD JLCPCB tools がインストールできないから何とかする"},{"content":"この記事を作った動機 単に、ネットワークを使うだけで、パーミッション周りの設定と、UIスレッドと分離されたスレッドによる、非同期処理が必要なので、忘れる前に記録しておこうという話。\n権限の設定(AndroidManifest.xml) android.permission.INTERNET の権限を追加\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;manifest xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34;\u0026gt; \u0026lt;uses-permission android:name=\u0026#34;android.permission.INTERNET\u0026#34; /\u0026gt; ... \u0026lt;/manifest\u0026gt; 権限を許可したいときに確認すべきところ Manifest.permission | API reference | Android Developers\nhttps://developer.android.com/reference/android/Manifest.permission (2025年6月14日) 非同期処理（とりあえず動くというだけ kotlin） 本当のところは、AsyncTask は廃止なので java.util.concurrent を使うべきらしい。\n参照すべきドキュメント AsyncTask | API reference | Android Developers\nhttps://developer.android.com/reference/android/os/AsyncTask (2025年6月14日) 専用にクラスを定義する package com.example.smbfileviewer import android.os.AsyncTask import android.util.Log import com.hierynomus.smbj.SMBClient import com.hierynomus.smbj.auth.AuthenticationContext import com.hierynomus.smbj.session.Session import com.hierynomus.smbj.share.DiskShare import com.hierynomus.smbj.share.Share class smbOperation(val handler: (message:String) -\u0026gt; Unit) : AsyncTask\u0026lt;Void,Void,Unit\u0026gt;(){ override fun doInBackground(vararg params: Void?): Unit { handler(testSMB()) } fun testSMB(): String{ val client = SMBClient() // 何かネットワークを使う処理をする // 今回は SMB ファイルサーバのライブラリを試すという前提で。 return \u0026#34;do something\u0026#34; } } 作ったクラスをボタンを押されたときとかに呼び出す // 何かのアクティビティクラスの onCreate 内などのUIの処理にて class shareFolderListActivity1 : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { val debugTestStart = findViewById\u0026lt;Button\u0026gt;(R.id.debugTestStart) debugTestStart.setOnClickListener{ val instance = smbOperation({ message -\u0026gt; debugLog(message) }) instance.execute() } } } 次の記事 Android アプリでネットワーク接続に対応するの続き 1 参考にしたサイトとか java - How can I fix \u0026lsquo;android.os.NetworkOnMainThreadException\u0026rsquo;? - Stack Overflow\nhttps://stackoverflow.com/questions/6343166/how-can-i-fix-android-os-networkonmainthreadexception (2025年6月14日) java - Permission for sockets - android manifest - Stack Overflow\nhttps://stackoverflow.com/questions/56582336/permission-for-sockets-android-manifest (2025年6月14日) Manifest.permission | API reference | Android Developers\nhttps://developer.android.com/reference/android/Manifest.permission (2025年6月14日) AsyncTask | API reference | Android Developers\nhttps://developer.android.com/reference/android/os/AsyncTask (2025年6月14日) ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/appwithnetworking/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に、ネットワークを使うだけで、パーミッション周りの設定と、UIスレッドと分離されたスレッドによる、非同期処理が必要なので、忘れる前に記録しておこうという話。\u003c/p\u003e\n\u003ch2 id=\"権限の設定androidmanifestxml\"\u003e権限の設定(AndroidManifest.xml)\u003c/h2\u003e\n\u003cp\u003e　android.permission.INTERNET の権限を追加\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;manifest\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns:android=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://schemas.android.com/apk/res/android\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003exmlns:tools=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://schemas.android.com/tools\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;uses-permission\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.permission.INTERNET\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/manifest\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"権限を許可したいときに確認すべきところ\"\u003e権限を許可したいときに確認すべきところ\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eManifest.permission  |  API reference  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/reference/android/Manifest.permission\"\u003ehttps://developer.android.com/reference/android/Manifest.permission\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"非同期処理とりあえず動くというだけ-kotlin\"\u003e非同期処理（とりあえず動くというだけ kotlin）\u003c/h2\u003e\n\u003cp\u003e　本当のところは、AsyncTask は廃止なので java.util.concurrent を使うべきらしい。\u003c/p\u003e\n\u003ch3 id=\"参照すべきドキュメント\"\u003e参照すべきドキュメント\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAsyncTask  |  API reference  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/reference/android/os/AsyncTask\"\u003ehttps://developer.android.com/reference/android/os/AsyncTask\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"専用にクラスを定義する\"\u003e専用にクラスを定義する\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epackage\u003c/span\u003e com.example.smbfileviewer\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e android.os.AsyncTask\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e android.util.Log\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e com.hierynomus.smbj.SMBClient\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e com.hierynomus.smbj.auth.AuthenticationContext\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e com.hierynomus.smbj.session.Session\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e com.hierynomus.smbj.share.DiskShare\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e com.hierynomus.smbj.share.Share\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esmbOperation\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e handler: (message:String) \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e Unit) : AsyncTask\u0026lt;Void,Void,Unit\u0026gt;(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eoverride\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edoInBackground\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evararg\u003c/span\u003e params: Void?): Unit {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        handler(testSMB())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etestSMB\u003c/span\u003e(): String{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e client = SMBClient()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 何かネットワークを使う処理をする\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 今回は SMB ファイルサーバのライブラリを試すという前提で。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;do something\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"作ったクラスをボタンを押されたときとかに呼び出す\"\u003e作ったクラスをボタンを押されたときとかに呼び出す\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-kotlin\" data-lang=\"kotlin\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 何かのアクティビティクラスの onCreate 内などのUIの処理にて\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshareFolderListActivity1\u003c/span\u003e : AppCompatActivity() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eoverride\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efun\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonCreate\u003c/span\u003e(savedInstanceState: Bundle?) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e debugTestStart = findViewById\u0026lt;Button\u0026gt;(\u003cspan style=\"color:#a6e22e\"\u003eR\u003c/span\u003e.id.debugTestStart)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        debugTestStart.setOnClickListener{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eval\u003c/span\u003e instance = smbOperation({ message \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                debugLog(message)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            instance.execute()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"次の記事\"\u003e次の記事\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/android/androidstudio/appwithnetworking1/\"\u003eAndroid アプリでネットワーク接続に対応するの続き 1\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ejava - How can I fix \u0026lsquo;android.os.NetworkOnMainThreadException\u0026rsquo;? - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/6343166/how-can-i-fix-android-os-networkonmainthreadexception\"\u003ehttps://stackoverflow.com/questions/6343166/how-can-i-fix-android-os-networkonmainthreadexception\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003cli\u003ejava - Permission for sockets - android manifest - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/56582336/permission-for-sockets-android-manifest\"\u003ehttps://stackoverflow.com/questions/56582336/permission-for-sockets-android-manifest\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003cli\u003eManifest.permission  |  API reference  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/reference/android/Manifest.permission\"\u003ehttps://developer.android.com/reference/android/Manifest.permission\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003cli\u003eAsyncTask  |  API reference  |  Android Developers\u003cbr\u003e\n\u003ca href=\"https://developer.android.com/reference/android/os/AsyncTask\"\u003ehttps://developer.android.com/reference/android/os/AsyncTask\u003c/a\u003e (2025年6月14日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Android アプリでネットワーク接続に対応する"},{"content":"この記事を作った動機 単にいちいちどうやって開発用に、http-server(npm経由) 上で SSL(HTTPS) を利用できるのかとか、とにかくCORSをどうにかしたいとき、忘れたときにいちいち調べるのはめんどいので、記録するだけ。\n必要なもの http-server (via npm) mkcert まとめ http-server --cors --ssl --key ~/path/to/key/key.pem --cert ~/path/to/cert/cert.pem 個別のメモ書き CORSを何とかする http-server --cors SSL を何とかする mkcert -install # mkcertを初めて使うときのみ mkcert [開発用サーバのIP or localhost とか] http-server --ssl --key ~/path/to/key/key.pem --cert ~/path/to/cert/cert.pem 参考にしたサイトとか macos - enable CORS for local http server - Stack Overflow\nhttps://stackoverflow.com/questions/63297822/enable-cors-for-local-http-server (2025年6月13日)\nhttp-serverによるローカル HTTPS server 構築 (5分でできる) #Node.js - Qiita\nhttps://qiita.com/hbjpn/items/925c8012cd93d9165be6 (2025年6月13日)\n","permalink":"https://www.nyanmo.info/posts/webdevelop/http-serverwithsslandcors/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単にいちいちどうやって開発用に、http-server(npm経由) 上で SSL(HTTPS) を利用できるのかとか、とにかくCORSをどうにかしたいとき、忘れたときにいちいち調べるのはめんどいので、記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"必要なもの\"\u003e必要なもの\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ehttp-server (via npm)\u003c/li\u003e\n\u003cli\u003emkcert\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"まとめ\"\u003eまとめ\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehttp-server --cors --ssl --key ~/path/to/key/key.pem --cert ~/path/to/cert/cert.pem\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"個別のメモ書き\"\u003e個別のメモ書き\u003c/h2\u003e\n\u003ch3 id=\"corsを何とかする\"\u003eCORSを何とかする\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehttp-server --cors\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ssl-を何とかする\"\u003eSSL を何とかする\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkcert -install \u003cspan style=\"color:#75715e\"\u003e# mkcertを初めて使うときのみ\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkcert \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e開発用サーバのIP or localhost とか\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehttp-server --ssl --key ~/path/to/key/key.pem --cert ~/path/to/cert/cert.pem\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003emacos - enable CORS for local http server - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/63297822/enable-cors-for-local-http-server\"\u003ehttps://stackoverflow.com/questions/63297822/enable-cors-for-local-http-server\u003c/a\u003e (2025年6月13日)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ehttp-serverによるローカル HTTPS server 構築 (5分でできる) #Node.js - Qiita\u003cbr\u003e\n\u003ca href=\"https://qiita.com/hbjpn/items/925c8012cd93d9165be6\"\u003ehttps://qiita.com/hbjpn/items/925c8012cd93d9165be6\u003c/a\u003e (2025年6月13日)\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e","title":"http-server と SSL、CORS"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ChatGPT EC開発の概要 Open as a page タッチパッドについて Open as a page JLCPCBとアセンブリ案とキーボードマトリクス Open as a page レジスタとキーボードマトリクスによる開発練習 Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/ecdevelopment/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"chatgpt\"\u003eChatGPT\u003c/h2\u003e\n\u003ch3 id=\"ec開発の概要\"\u003eEC開発の概要\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/ECdevelopment/EC%e9%96%8b%e7%99%ba%e6%ae%b5%e5%8f%96%e3%82%8a%e3%81%a8%e6%8a%bd%e8%b1%a1%e5%8c%96.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/ECdevelopment/EC%e9%96%8b%e7%99%ba%e6%ae%b5%e5%8f%96%e3%82%8a%e3%81%a8%e6%8a%bd%e8%b1%a1%e5%8c%96.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch3 id=\"タッチパッドについて\"\u003eタッチパッドについて\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/ECdevelopment/%e3%82%bf%e3%83%83%e3%83%81%e3%83%91%e3%83%83%e3%83%89%e5%86%8d%e5%88%a9%e7%94%a8%20I2C.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/ECdevelopment/%e3%82%bf%e3%83%83%e3%83%81%e3%83%91%e3%83%83%e3%83%89%e5%86%8d%e5%88%a9%e7%94%a8%20I2C.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch3 id=\"jlcpcbとアセンブリ案とキーボードマトリクス\"\u003eJLCPCBとアセンブリ案とキーボードマトリクス\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/ECdevelopment/JLCPCB%20%e9%83%a8%e5%93%81%e5%ae%9f%e8%a3%85%e7%a2%ba%e8%aa%8d.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/ECdevelopment/JLCPCB%20%e9%83%a8%e5%93%81%e5%ae%9f%e8%a3%85%e7%a2%ba%e8%aa%8d.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch3 id=\"レジスタとキーボードマトリクスによる開発練習\"\u003eレジスタとキーボードマトリクスによる開発練習\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/ECdevelopment/%e3%83%ac%e3%82%b8%e3%82%b9%e3%82%bf%e6%93%8d%e4%bd%9c%e3%81%a8%e6%84%9f%e8%a6%9a.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/ECdevelopment/%e3%83%ac%e3%82%b8%e3%82%b9%e3%82%bf%e6%93%8d%e4%bd%9c%e3%81%a8%e6%84%9f%e8%a6%9a.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"EC 開発"},{"content":"この記事を作った動機 単に自分の持っている DELL Latitude E7450 のラバー塗装が加水分解しまくってべたべたしたり、ボタンの化粧部分ごとボロボロ崩れてなくなっていったりしているということがあった。\n交換パーツをアリエクスプレスなどでそろえようとしても、結局1000円くらいかかってしまうし、いずれにせよまた加水分解する未来が見える。\nそこで自分でラバー系の素材ではなく、3D プリンタで作った素材にしてやれば長期的にも都合がいいと思い、モデルを作った次第。\nトラックポイントとかだと、ネットにモデルが転がっていたりするが、少なくとも私は、タッチパッドのボタンの部分までは見つけられなかったので、自作したついでに。\n使ったもの cura blender Ender 3 pro 1.75mm の PLAフィラメント 0.5mm のノズル DELL Latitude E7450 本体 無水エタノール 瞬間接着剤 何かしらの瞬間接着剤でくっつければ多分終わり\nモデルのダウンロード touchpadButtonBoth.stl touchpadButtonBoth.blend モデルの preview (three.js) 壊れている様子 壊れている様子 作ったモデルのイメージ図 cura上の表示 blender上の表示 blender上の表示1 実際に作ってみた様子 作ったものとタッチパッドボタン 作ったラバーカバーの代わりをつけてみた様子 作ったラバーカバーの代わりをつけてみた様子1 実際に瞬間接着剤でつけてみた様子 今回は、適当に分解してボタンだけにしてから作業した。 瞬間接着剤でくっつけているところ 両方くっつけてしばらくした後 組み立てなおしてみる 組み立てなおした後の様子 参考にしたサイトとか 特になし。強いて言えば、DELL Latitude E7450 本体に定規をあてがったりしたくらい。あとは何度か印刷して微調整してみたくらい。多分プリンタごとにモデルの調整が必要であり、面倒ではある。\n","permalink":"https://www.nyanmo.info/images/3dmodel/delllatitudee7450touchpadbuttons/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単に自分の持っている DELL Latitude E7450 のラバー塗装が加水分解しまくってべたべたしたり、ボタンの化粧部分ごとボロボロ崩れてなくなっていったりしているということがあった。\u003c/p\u003e\n\u003cp\u003e　交換パーツをアリエクスプレスなどでそろえようとしても、結局1000円くらいかかってしまうし、いずれにせよまた加水分解する未来が見える。\u003c/p\u003e\n\u003cp\u003e　そこで自分でラバー系の素材ではなく、3D プリンタで作った素材にしてやれば長期的にも都合がいいと思い、モデルを作った次第。\u003c/p\u003e\n\u003cp\u003e　トラックポイントとかだと、ネットにモデルが転がっていたりするが、少なくとも私は、タッチパッドのボタンの部分までは見つけられなかったので、自作したついでに。\u003c/p\u003e\n\u003ch2 id=\"使ったもの\"\u003e使ったもの\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ecura\u003c/li\u003e\n\u003cli\u003eblender\u003c/li\u003e\n\u003cli\u003eEnder 3 pro\u003c/li\u003e\n\u003cli\u003e1.75mm の PLAフィラメント\u003c/li\u003e\n\u003cli\u003e0.5mm のノズル\u003c/li\u003e\n\u003cli\u003eDELL Latitude E7450 本体\u003c/li\u003e\n\u003cli\u003e無水エタノール\u003c/li\u003e\n\u003cli\u003e瞬間接着剤\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e何かしらの瞬間接着剤でくっつければ多分終わり\u003c/p\u003e\n\u003ch2 id=\"モデルのダウンロード\"\u003eモデルのダウンロード\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/DELLLatitudeE7450touchPadButtons/touchpadButtonBoth.stl\"\u003e\ntouchpadButtonBoth.stl\n\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca download href=\"/images/3Dmodel/DELLLatitudeE7450touchPadButtons/touchpadButtonBoth.blend\"\u003e\ntouchpadButtonBoth.blend\n\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"モデルの-preview-threejs\"\u003eモデルの preview (three.js)\u003c/h2\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"THREEcontainer536194278 column\"\u003e\n    \u003cdiv class=\"mainView\"\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript type=\"module\"\u003e\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n\n    import * as THREE from 'three';\n    import { STLLoader } from 'three/addons/loaders/STLLoader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n    \n    \n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n\n    \n    const scene = new THREE.Scene();\n    scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n    scene.add(new THREE.AxesHelper(50))\n\n    \n    const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n    const container = document.querySelector(\".THREEcontainer536194278\")\n    const mainView  = container.querySelector(\".mainView\")\n    const renderer = new THREE.WebGLRenderer();\n    renderer.setSize(screenSize.width,screenSize.height);\n    renderer.shadowMap.enabled = true;\n    mainView.appendChild( renderer.domElement );\n\n    \n    const buttons = container.querySelector(\".MMDcontroler.column\")\n    const fullscreen = buttons.querySelector(\"#fullscreen\")\n\n    fullscreen.addEventListener(\"click\", () =\u003e {\n        mainView.requestFullscreen()\n    })\n\n    mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n        let width = 0\n        let height = 0\n        if(document.fullscreenElement){\n            width   = window.innerWidth\n            height  = window.outerHeight\n            \n            \n            \n        }else{\n            width   = screenSize.width\n            height  = screenSize.height\n            \n        }\n        \n        \n        console.log(width)\n        console.log(height)\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(width, height);\n        \n        camera.aspect = width / height;\n        camera.updateProjectionMatrix();\n        \n    })\n    \n\n\n\n        \n\n    \n    const controls = new OrbitControls(camera, renderer.domElement)\n    controls.enableDamping = true\n\n    \n    const loader = new STLLoader();\n    loader.load( '\\/images\\/3Dmodel\\/DELLLatitudeE7450touchPadButtons\\/touchpadButtonBoth.stl', function (geometry) {\n        const material = new THREE.MeshStandardMaterial();\n        material.color = new THREE.Color().setHex(0x274d63)\n        const mesh = new THREE.Mesh(geometry, material)\n        mesh.receiveShadow = true\n        \n        mesh.position.x = Number(\"0\")\n        mesh.position.y = Number(\"20\")\n        mesh.position.z = Number(\"20\")\n        mesh.rotation.x = Math.PI * Number(\"0\") / 180.0\n        mesh.rotation.y = Math.PI * Number(\"0\") / 180.0\n        mesh.rotation.z = Math.PI * Number(\"90\") / 180.0\n\n        scene.add(mesh)\n    }, undefined, function ( error ) {\n        console.error( error );\n    } );\n\n    \n    let lightPosOffset = Number(\"200\")\n    const lightPos = [\n        {x:0,y:0,z:0},\n\n        {x:lightPosOffset,y:0 ,z:0},\n        {x:-lightPosOffset,y:0 ,z:0},\n\n        {x:0,y:lightPosOffset ,z:0},\n        {x:0,y:-lightPosOffset ,z:0},\n\n        {x:0,y:0 ,z:lightPosOffset},\n        {x:0,y:0 ,z:-lightPosOffset},\n\n        {x:0,y:lightPosOffset ,z:lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:lightPosOffset},\n        {x:0,y:lightPosOffset ,z:-lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:lightPosOffset,y:0 ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:lightPosOffset ,z:0},\n        {x:lightPosOffset,y:-lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:0},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n    ] \n\n    \n    const color = 0xFFFFFF;\n    const intensity = Number(\"1\");\n    for(let pos of lightPos){\n        let light =  new THREE.DirectionalLight(color, intensity);\n        light.position.set(pos.x, pos.y,pos.z);\n        scene.add(light);\n    }\n\n    \n    \n    camera.position.set(\n        Number(\"65\"),\n        Number(\"25\"),\n        Number(\"80\")\n    )\n    controls.target.set(\n        Number(\"0\"),\n        Number(\"0\"),\n        Number(\"0\")\n    )\n\n    \n    function animate() {\n        renderer.render( scene, camera );\n        controls.update()\n    }\n    renderer.setAnimationLoop( animate );\n\u003c/script\u003e\u003c/p\u003e","title":"DELL Latitude E7450 タッチパッドボタン"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 現状 とりあえずセラミックヒーターとマイコンは買っている PID制御を実装したい 温度表示用のディスプレイをつけたい トライアックやSSRなどで、電力制御 chatGPT Open as a page Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/bgapreheater/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"現状\"\u003e現状\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eとりあえずセラミックヒーターとマイコンは買っている\u003c/li\u003e\n\u003cli\u003ePID制御を実装したい\u003c/li\u003e\n\u003cli\u003e温度表示用のディスプレイをつけたい\u003c/li\u003e\n\u003cli\u003eトライアックやSSRなどで、電力制御\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"chatgpt\"\u003echatGPT\u003c/h2\u003e\n\u003cp\u003e\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/bgaPreHeater/%e3%82%bb%e3%83%a9%e3%83%9f%e3%83%83%e3%82%af%e3%83%92%e3%83%bc%e3%82%bf%e3%83%bc%e5%88%b6%e5%be%a1%e6%96%b9%e6%b3%95.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/bgaPreHeater/%e3%82%bb%e3%83%a9%e3%83%9f%e3%83%83%e3%82%af%e3%83%92%e3%83%bc%e3%82%bf%e3%83%bc%e5%88%b6%e5%be%a1%e6%96%b9%e6%b3%95.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/bgaPreHeater/KiCad%20PCB%e8%a3%bd%e9%80%a0%e8%a9%a6%e4%bd%9c.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/bgaPreHeater/KiCad%20PCB%e8%a3%bd%e9%80%a0%e8%a9%a6%e4%bd%9c.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"BGA 予備加熱器自作"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ノートPCのDVDスロットにGPUをつけたい 基本的に映像出力端子はつけない。（オプション扱い） とにかく簡単に作る。 PCIe x1で、mini PCIe経由で動かす mini PCIeからは、USBを引き回し、ハブ用のICを使って、bluetoothやwifiにUSBドングル経由での対応を行う TODO ヒートガンでチップはがす テスターであてがい、ピンアウトを調べる フットプリントを作る シンボルを作る GPUのブロックダイアグラムによる構成図の作成 PCIeの12vラインはいらないかも。直接システム電源を引き回し、GPUとかメモリ周りを降圧、整流すればいいかも。 chatGPT 原案 Open as a page 基板開発の伝送路設計 入力、出力、伝送路、基板自体をコンデンサや抵抗、インダクタとしてインピーダンス計算\nOpen as a page 高周波、高速信号におけるインピーダンスマッチングの設計思想と考察 Open as a page HBMメモリなどの一体形成メモリの考察 Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/thinkpadultrabaygpu/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"ノートpcのdvdスロットにgpuをつけたい\"\u003eノートPCのDVDスロットにGPUをつけたい\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e基本的に映像出力端子はつけない。（オプション扱い）\u003c/li\u003e\n\u003cli\u003eとにかく簡単に作る。\u003c/li\u003e\n\u003cli\u003ePCIe x1で、mini PCIe経由で動かす\u003c/li\u003e\n\u003cli\u003emini PCIeからは、USBを引き回し、ハブ用のICを使って、bluetoothやwifiにUSBドングル経由での対応を行う\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"todo\"\u003eTODO\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eヒートガンでチップはがす\u003c/li\u003e\n\u003cli\u003eテスターであてがい、ピンアウトを調べる\u003c/li\u003e\n\u003cli\u003eフットプリントを作る\u003c/li\u003e\n\u003cli\u003eシンボルを作る\u003c/li\u003e\n\u003cli\u003eGPUのブロックダイアグラムによる構成図の作成\u003c/li\u003e\n\u003cli\u003ePCIeの12vラインはいらないかも。直接システム電源を引き回し、GPUとかメモリ周りを降圧、整流すればいいかも。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"chatgpt\"\u003echatGPT\u003c/h2\u003e\n\u003ch3 id=\"原案\"\u003e原案\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/thinkpadUltraBayGPU/GT710%20%e3%83%8e%e3%83%bc%e3%83%88%e6%94%b9%e9%80%a0%e8%a8%88%e7%94%bb.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/thinkpadUltraBayGPU/GT710%20%e3%83%8e%e3%83%bc%e3%83%88%e6%94%b9%e9%80%a0%e8%a8%88%e7%94%bb.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch3 id=\"基板開発の伝送路設計\"\u003e基板開発の伝送路設計\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e入力、出力、伝送路、基板自体をコンデンサや抵抗、インダクタとしてインピーダンス計算\u003cbr\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/thinkpadUltraBayGPU/%e3%82%a4%e3%83%b3%e3%83%94%e3%83%bc%e3%83%80%e3%83%b3%e3%82%b9%e3%83%9e%e3%83%83%e3%83%81%e3%83%b3%e3%82%b0%e8%a8%ad%e8%a8%88.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/thinkpadUltraBayGPU/%e3%82%a4%e3%83%b3%e3%83%94%e3%83%bc%e3%83%80%e3%83%b3%e3%82%b9%e3%83%9e%e3%83%83%e3%83%81%e3%83%b3%e3%82%b0%e8%a8%ad%e8%a8%88.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"高周波高速信号におけるインピーダンスマッチングの設計思想と考察\"\u003e高周波、高速信号におけるインピーダンスマッチングの設計思想と考察\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/thinkpadUltraBayGPU/%e3%82%a4%e3%83%b3%e3%83%94%e3%83%bc%e3%83%80%e3%83%b3%e3%82%b9%e8%a8%ad%e8%a8%88%e3%81%a8%e9%85%8d%e7%b7%9a.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/thinkpadUltraBayGPU/%e3%82%a4%e3%83%b3%e3%83%94%e3%83%bc%e3%83%80%e3%83%b3%e3%82%b9%e8%a8%ad%e8%a8%88%e3%81%a8%e9%85%8d%e7%b7%9a.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch3 id=\"hbmメモリなどの一体形成メモリの考察\"\u003eHBMメモリなどの一体形成メモリの考察\u003c/h3\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/thinkpadUltraBayGPU/R9%20Nano%e3%81%a8RTX%e6%af%94%e8%bc%83.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/thinkpadUltraBayGPU/R9%20Nano%e3%81%a8RTX%e6%af%94%e8%bc%83.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Thinkpad ウルトラベイ GPU"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 案 av1、vp9などといったコーディックに対応した、FPGAで実装する、ハードウェアアクセラレーションの案 既存のGPUなどに実装されているハードウェアアクセラレーションはASIC的で、あとから変更できない、新しい規格に対応できないなどの問題があり、CPUをたくさん動画のエンコード、デコードのために使ってしまう。\nchatGPT Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/hardwareaccelerationwithfpga/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"案\"\u003e案\u003c/h2\u003e\n\u003cp\u003eav1、vp9などといったコーディックに対応した、FPGAで実装する、ハードウェアアクセラレーションの案\n既存のGPUなどに実装されているハードウェアアクセラレーションはASIC的で、あとから変更できない、新しい規格に対応できないなどの問題があり、CPUをたくさん動画のエンコード、デコードのために使ってしまう。\u003c/p\u003e\n\u003ch2 id=\"chatgpt\"\u003echatGPT\u003c/h2\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/hardwareAccelerationWithFPGA/Intel%e3%81%ae%e6%80%a7%e8%83%bd%e6%88%a6%e7%95%a5%e3%81%a8%e8%aa%b2%e9%a1%8c.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/hardwareAccelerationWithFPGA/Intel%e3%81%ae%e6%80%a7%e8%83%bd%e6%88%a6%e7%95%a5%e3%81%a8%e8%aa%b2%e9%a1%8c.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ハードウェアアクセラレーション(HWA)をFPGAで実装"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） BGAの問題点 交換できない 手軽でない、個人で扱いにくい 壊れたら終わりになり、eWaste 拡大をもたらす 代替案 HP9000 Server Series Teardown (PWJ262) - YouTubeであったような仕組み マザーボードにもCPU側にもピンはない マッシュルームみたいなスポンジみたいなピンがいっぱい生えてて、チップや基盤側の電気的接触を維持し、中継するフレキシブルケーブルみたいな、いわゆる下駄みたいな仕組み 既存のBGA設計でもすぐ適応できる うまく圧力をかけて接触を維持すればよい 衝撃などでおかしくなっても中継フレキシブルケーブル型のピンを交換すれば物理的障害を治せるようにできる はんだクラックみたいなことには、スポンジ質な接触によって避けられるかも 実際に試せそうなこと スポンジ的なピンを、かなり大き面接地面（10mmx10mm)とかから試して、徐々に小さくしていく。 実際に大きめのパッドを持つSMDパーツみたいなイメージの基盤を作り、パッドの開口部をBGAに徐々に寄せていく chatGPT Open as a page Ref Play with Junk - YouTube\nhttps://www.youtube.com/@PlaywithJunk/videos (2025年5月30日)\nHP9000 Server Series Teardown (PWJ262) - YouTube クローズアップ\nhttps://www.youtube.com/watch?v=JK8c_dTaQP0\u0026amp;t=784s (2025年5月31日) HP9000 Server Series Teardown (PWJ262) - YouTube 全体像\nhttps://www.youtube.com/watch?v=JK8c_dTaQP0\u0026amp;t=759s (2025年5月31日) ChatGPT\nhttps://chatgpt.com/ (2025年6月18日)\n","permalink":"https://www.nyanmo.info/posts/idea/research/bgaalternative/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"bgaの問題点\"\u003eBGAの問題点\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e交換できない\u003c/li\u003e\n\u003cli\u003e手軽でない、個人で扱いにくい\u003c/li\u003e\n\u003cli\u003e壊れたら終わりになり、eWaste 拡大をもたらす\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"代替案\"\u003e代替案\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.youtube.com/watch?v=JK8c_dTaQP0\u0026amp;t=784s\"\u003eHP9000 Server Series Teardown (PWJ262) - YouTube\u003c/a\u003eであったような仕組み\u003c/li\u003e\n\u003cli\u003eマザーボードにもCPU側にもピンはない\u003c/li\u003e\n\u003cli\u003eマッシュルームみたいなスポンジみたいなピンがいっぱい生えてて、チップや基盤側の電気的接触を維持し、中継するフレキシブルケーブルみたいな、いわゆる下駄みたいな仕組み\u003c/li\u003e\n\u003cli\u003e既存のBGA設計でもすぐ適応できる\u003c/li\u003e\n\u003cli\u003eうまく圧力をかけて接触を維持すればよい\u003c/li\u003e\n\u003cli\u003e衝撃などでおかしくなっても中継フレキシブルケーブル型のピンを交換すれば物理的障害を治せるようにできる\u003c/li\u003e\n\u003cli\u003eはんだクラックみたいなことには、スポンジ質な接触によって避けられるかも\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"実際に試せそうなこと\"\u003e実際に試せそうなこと\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eスポンジ的なピンを、かなり大き面接地面（10mmx10mm)とかから試して、徐々に小さくしていく。\u003c/li\u003e\n\u003cli\u003e実際に大きめのパッドを持つSMDパーツみたいなイメージの基盤を作り、パッドの開口部をBGAに徐々に寄せていく\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"chatgpt\"\u003echatGPT\u003c/h2\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/bgaAlternative/vGPU%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e3%81%a8WDDM.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/bgaAlternative/vGPU%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e3%81%a8WDDM.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003ePlay with Junk - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/@PlaywithJunk/videos\"\u003ehttps://www.youtube.com/@PlaywithJunk/videos\u003c/a\u003e (2025年5月30日)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eHP9000 Server Series Teardown (PWJ262) - YouTube クローズアップ\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=JK8c_dTaQP0\u0026amp;t=784s\"\u003ehttps://www.youtube.com/watch?v=JK8c_dTaQP0\u0026amp;t=784s\u003c/a\u003e (2025年5月31日)\n\u003cdiv style=\"position: relative; padding-bottom: 56.25%; height: 0; overflow: hidden;\"\u003e\n\t\t\t\u003ciframe allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen\" loading=\"eager\" referrerpolicy=\"strict-origin-when-cross-origin\" src=\"https://www.youtube.com/embed/JK8c_dTaQP0?autoplay=0\u0026amp;controls=1\u0026amp;end=0\u0026amp;loop=0\u0026amp;mute=0\u0026amp;start=784\" style=\"position: absolute; top: 0; left: 0; width: 100%; height: 100%; border:0;\" title=\"YouTube video\"\u003e\u003c/iframe\u003e\n\t\t\u003c/div\u003e\n\u003c/p\u003e","title":"BGA の代替品"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 案 vGPUのパフォーマンス改良 QEMU の win 7 ドライバに WDDM を実装して aero を動かす chatGPT Open as a page Open as a page Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/gpudevelopment/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"案\"\u003e案\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003evGPUのパフォーマンス改良\u003c/li\u003e\n\u003cli\u003eQEMU の win 7 ドライバに WDDM を実装して aero を動かす\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"chatgpt\"\u003echatGPT\u003c/h2\u003e\n\u003cp\u003e\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/gpuDevelopment/vGPU%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e3%81%a8WDDM.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/gpuDevelopment/vGPU%e3%83%91%e3%83%95%e3%82%a9%e3%83%bc%e3%83%9e%e3%83%b3%e3%82%b9%e3%81%a8WDDM.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/gpuDevelopment/GPU%e4%bb%ae%e6%83%b3%e5%8c%96%e7%a0%94%e7%a9%b6%e6%8f%90%e6%a1%88.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/gpuDevelopment/GPU%e4%bb%ae%e6%83%b3%e5%8c%96%e7%a0%94%e7%a9%b6%e6%8f%90%e6%a1%88.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"GPU 開発"},{"content":"この記事を作った動機 最近 Win 11 24H2 を使っているときに、「パスワードの有効期限が切れています」とログオン時にパスワードの再設定を求められるということがあった。なぜか作成したアカウントの有効期限がデフォルトで設定されている状態であった。\nそれで調べてみるとGUI操作で、設定する方法ばかりヒットして、めんどくさかったので、コマンドでどうにかできないか試したことを記録するだけ。\nやり方 以下はすべてのアカウントに対して設定を反映する方法である。一つ一つやる方法もあるらしいが、試していない。\nコマンド (base) PS C:\\Users\\username\u0026gt; net accounts /maxpwage:unlimited コマンドは正常に終了しました。 全体像 (base) PS C:\\Users\\username\u0026gt; net accounts 強制ログオフまでの時間 (分): しない パスワード変更禁止期間 (日数): 0 パスワード有効期間 (日数): 42 最小パスワード長: 0 使用できない旧パスワード数: なし ロックアウトしきい値: 10 ロックアウト期間 (分): 10 ロックアウト監視ウィンドウ (分): 10 コンピューターの役割: WORKSTATION コマンドは正常に終了しました。 (base) PS C:\\Users\\username\u0026gt; net accounts /maxpwage:unlimited コマンドは正常に終了しました。 (base) PS C:\\Users\\username\u0026gt; net accounts 強制ログオフまでの時間 (分): しない パスワード変更禁止期間 (日数): 0 パスワード有効期間 (日数): 無制限 最小パスワード長: 0 使用できない旧パスワード数: なし ロックアウトしきい値: 10 ロックアウト期間 (分): 10 ロックアウト監視ウィンドウ (分): 10 コンピューターの役割: WORKSTATION コマンドは正常に終了しました。 (base) PS C:\\Users\\username\u0026gt; net user username ユーザー名 username フル ネーム コメント ユーザーのコメント 国/地域番号 000 (システム既定) アカウント有効 Yes アカウントの期限 無期限 最終パスワード変更日時 2025/05/29 21:33:43 パスワード有効期間 無期限 パスワード次回変更可能日時 2025/05/29 21:33:43 パスワードあり Yes ユーザーによるパスワード変更可能 Yes ログオン可能なワークステーション すべて ログオン スクリプト ユーザー プロファイル ホーム ディレクトリ 最終ログオン日時 2025/05/29 21:33:44 ログオン可能時間 すべて 所属しているローカル グループ *Administrators *Users 所属しているグローバル グループ *なし コマンドは正常に終了しました。 参考にしたサイトとか Set User Password to never expire | NTLite Forums\nhttps://www.ntlite.com/community/index.php?threads/set-user-password-to-never-expire.3328/ (2025年5月29日) ","permalink":"https://www.nyanmo.info/posts/windows/setpasswordtoneverexpire/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近 Win 11 24H2 を使っているときに、「パスワードの有効期限が切れています」とログオン時にパスワードの再設定を求められるということがあった。なぜか作成したアカウントの有効期限がデフォルトで設定されている状態であった。\u003c/p\u003e\n\u003cp\u003e　それで調べてみるとGUI操作で、設定する方法ばかりヒットして、めんどくさかったので、コマンドでどうにかできないか試したことを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　以下はすべてのアカウントに対して設定を反映する方法である。一つ一つやる方法もあるらしいが、試していない。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eコマンド\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(base) PS C:\\Users\\username\u0026gt; net accounts /maxpwage:unlimited\nコマンドは正常に終了しました。\n\u003c/code\u003e\u003c/pre\u003e\u003cul\u003e\n\u003cli\u003e全体像\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e(base) PS C:\\Users\\username\u0026gt; net accounts\n強制ログオフまでの時間 (分):                                しない\nパスワード変更禁止期間 (日数):                              0\nパスワード有効期間 (日数):                                  42\n最小パスワード長:                                           0\n使用できない旧パスワード数:                                 なし\nロックアウトしきい値:                                       10\nロックアウト期間 (分):                                      10\nロックアウト監視ウィンドウ (分):                            10\nコンピューターの役割:                                       WORKSTATION\nコマンドは正常に終了しました。\n\n(base) PS C:\\Users\\username\u0026gt; net accounts /maxpwage:unlimited\nコマンドは正常に終了しました。\n\n(base) PS C:\\Users\\username\u0026gt; net accounts\n強制ログオフまでの時間 (分):                                しない\nパスワード変更禁止期間 (日数):                              0\nパスワード有効期間 (日数):                                  無制限\n最小パスワード長:                                           0\n使用できない旧パスワード数:                                 なし\nロックアウトしきい値:                                       10\nロックアウト期間 (分):                                      10\nロックアウト監視ウィンドウ (分):                            10\nコンピューターの役割:                                       WORKSTATION\nコマンドは正常に終了しました。\n\n(base) PS C:\\Users\\username\u0026gt; net user username\nユーザー名                           username\nフル ネーム\nコメント\nユーザーのコメント\n国/地域番号                          000 (システム既定)\nアカウント有効                       Yes\nアカウントの期限                     無期限\n\n最終パスワード変更日時               2025/05/29 21:33:43\nパスワード有効期間                   無期限\nパスワード次回変更可能日時           2025/05/29 21:33:43\nパスワードあり                       Yes\nユーザーによるパスワード変更可能     Yes\n\nログオン可能なワークステーション     すべて\nログオン スクリプト\nユーザー プロファイル\nホーム ディレクトリ\n最終ログオン日時                     2025/05/29 21:33:44\n\nログオン可能時間                     すべて\n\n所属しているローカル グループ        *Administrators\n                                     *Users\n所属しているグローバル グループ      *なし\nコマンドは正常に終了しました。\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eSet User Password to never expire | NTLite Forums\u003cbr\u003e\n\u003ca href=\"https://www.ntlite.com/community/index.php?threads/set-user-password-to-never-expire.3328/\"\u003ehttps://www.ntlite.com/community/index.php?threads/set-user-password-to-never-expire.3328/\u003c/a\u003e (2025年5月29日)\u003c/li\u003e\n\u003c/ul\u003e","title":"パスワードを無期限で利用できるようにする"},{"content":"この記事を作った動機 新しくPCを導入したときに、カスタムのカーソルがどこに保存されているかわからなくなったので、どうやって調べればいいか記録するだけ。\n方法 レジストリエディタを開く どんな方法でもいいし無数にやり方がある。\nWin + R を押して、\u0026ldquo;regedit\u0026quot;と入力し、実行する スタートメニューから検索で\u0026quot;レジストリ\u0026quot;と調べる エクスプローラーからregedit.exeを実行する \\HKEY_CURRENT_USER\\Control Panel\\Cursors を開く データの部分のパスを確認 参考にしたサイトとか Windows の マウスポインター をリセット #Windows10 - Qiita\nhttps://qiita.com/c-toyama/items/9c150c69f3371904f130 (2025年5月25日) ","permalink":"https://www.nyanmo.info/posts/windows/findcustomcursorlocation/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　新しくPCを導入したときに、カスタムのカーソルがどこに保存されているかわからなくなったので、どうやって調べればいいか記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"方法\"\u003e方法\u003c/h2\u003e\n\u003ch3 id=\"レジストリエディタを開く\"\u003eレジストリエディタを開く\u003c/h3\u003e\n\u003cp\u003e　どんな方法でもいいし無数にやり方がある。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eWin + R を押して、\u0026ldquo;regedit\u0026quot;と入力し、実行する\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/Win\u0026#43;R.png#center\"\n         alt=\"Win\u0026#43;R\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eスタートメニューから検索で\u0026quot;レジストリ\u0026quot;と調べる\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/%e3%82%b9%e3%82%bf%e3%83%bc%e3%83%88.png#center\"\n         alt=\"スタート\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eエクスプローラーからregedit.exeを実行する\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/%e3%82%a8%e3%82%af%e3%82%b9%e3%83%97%e3%83%ad%e3%83%bc%e3%83%a9%e3%83%bc.png#center\"\n         alt=\"エクスプローラー\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"hkey_current_usercontrol-panelcursors-を開く\"\u003e\\HKEY_CURRENT_USER\\Control Panel\\Cursors を開く\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e4%be%8b.png#center\"\n         alt=\"レジストリ例\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"データの部分のパスを確認\"\u003eデータの部分のパスを確認\u003c/h3\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e4%be%8b1.png#center\"\n         alt=\"レジストリ例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/findCustomCursorLocation/%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e4%be%8b2.png#center\"\n         alt=\"レジストリ例\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWindows の マウスポインター をリセット #Windows10 - Qiita\u003cbr\u003e\n\u003ca href=\"https://qiita.com/c-toyama/items/9c150c69f3371904f130\"\u003ehttps://qiita.com/c-toyama/items/9c150c69f3371904f130\u003c/a\u003e (2025年5月25日)\u003c/li\u003e\n\u003c/ul\u003e","title":"カーソル画像の保存場所を見つける"},{"content":"この記事を作った動機 単にすでに存在する、git リポジトリを LAN 内の Gitea 上にアップロードするための方法の簡易的なメモ。Githubの場合でも同じようなことはできると思う。(そもそも github のページ参考にしたし)\nやり方 リポジトリの URL は、\u0026ldquo;https://aaa.info/urlToAremoteRepo.git\u0026quot; と仮定している。\nリポジトリの作成（リモート側） リモート側に、最小構成で、readme や license、gitignore を追加しないようにして空っぽのリポジトリを作成する。\nリポジトリの URL を設定する（ローカル側） git remote add origin https://aaa.info/urlToAremoteRepo.git ブランチの確認（ローカル側） アップロードしたいブランチの確認。今回は \u0026ldquo;master\u0026rdquo; という名前のブランチを、リモートにアップロードする。\ngit branch * master アップロード（ローカル側） git push origin master リポジトリが設定できたかの確認方法 git remote -v origin https://aaa.info/urlToAremoteRepo.git (fetch) origin https://aaa.info/urlToAremoteRepo.git (push) 参考にしたサイトとか Adding locally hosted code to GitHub - GitHub Docs\nhttps://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github (2025年5月19日) ","permalink":"https://www.nyanmo.info/posts/other/pushlocalgitrepotogitea/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　単にすでに存在する、git リポジトリを LAN 内の Gitea 上にアップロードするための方法の簡易的なメモ。Githubの場合でも同じようなことはできると思う。(そもそも \u003ca href=\"https://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github\"\u003egithub のページ\u003c/a\u003e参考にしたし)\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　リポジトリの URL は、\u0026ldquo;\u003ca href=\"https://aaa.info/urlToAremoteRepo.git%22\"\u003ehttps://aaa.info/urlToAremoteRepo.git\u0026quot;\u003c/a\u003e と仮定している。\u003c/p\u003e\n\u003ch3 id=\"リポジトリの作成リモート側\"\u003eリポジトリの作成（リモート側）\u003c/h3\u003e\n\u003cp\u003e　リモート側に、最小構成で、readme や license、gitignore を追加しないようにして空っぽのリポジトリを作成する。\u003c/p\u003e\n\u003ch3 id=\"リポジトリの-url-を設定するローカル側\"\u003eリポジトリの URL を設定する（ローカル側）\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egit remote add origin https://aaa.info/urlToAremoteRepo.git\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"ブランチの確認ローカル側\"\u003eブランチの確認（ローカル側）\u003c/h3\u003e\n\u003cp\u003e　アップロードしたいブランチの確認。今回は \u0026ldquo;master\u0026rdquo; という名前のブランチを、リモートにアップロードする。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit branch\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e* master\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"アップロードローカル側\"\u003eアップロード（ローカル側）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit push origin master\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"リポジトリが設定できたかの確認方法\"\u003eリポジトリが設定できたかの確認方法\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote -v\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eorigin  https://aaa.info/urlToAremoteRepo.git \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003efetch\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eorigin  https://aaa.info/urlToAremoteRepo.git \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003epush\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAdding locally hosted code to GitHub - GitHub Docs\u003cbr\u003e\n\u003ca href=\"https://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github\"\u003ehttps://docs.github.com/en/migrations/importing-source-code/using-the-command-line-to-import-source-code/adding-locally-hosted-code-to-github\u003c/a\u003e (2025年5月19日)\u003c/li\u003e\n\u003c/ul\u003e","title":"ローカルリポジトリをリモートへアップロード"},{"content":"ここはどこ？ ここはただ単に自分専用の chrome 拡張機能とか、このブログ用のアイコンとか作る過程で、適当に簡易的に作成した画像とか置いていくだけです。\nnotepad - chrome 拡張機能 clear.png close.png copy.png input.png move.png resize.png save.png other - nyanmo main blog PC.png exitfullscreen.png window.png おもちゃせっと.png おもちゃ箱.png はんだ.png はんだごて.png ガムテープ.png スマホ.png プラスチックほうき.png LLM-bias-visualization ひらめきバルブ.png ZenkakuHankaku-Key 全角半角キー.png ","permalink":"https://www.nyanmo.info/images/icons/","summary":"\u003ch2 id=\"ここはどこ\"\u003eここはどこ？\u003c/h2\u003e\n\u003cp\u003e　ここはただ単に自分専用の chrome 拡張機能とか、このブログ用のアイコンとか作る過程で、適当に簡易的に作成した画像とか置いていくだけです。\u003c/p\u003e\n\u003ch2 id=\"notepad---chrome-拡張機能\"\u003enotepad - chrome 拡張機能\u003c/h2\u003e\n\n\n\n\n\n\n    \n\n\n\n\u003cdiv style=\"display: flex; justify-content: center; flex-direction: column;\"\u003e\n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"clear.png\" style=\"white-space: nowrap;\"\u003eclear.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/clear.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"close.png\" style=\"white-space: nowrap;\"\u003eclose.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/close.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"copy.png\" style=\"white-space: nowrap;\"\u003ecopy.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/copy.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"input.png\" style=\"white-space: nowrap;\"\u003einput.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/input.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"move.png\" style=\"white-space: nowrap;\"\u003emove.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/move.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"resize.png\" style=\"white-space: nowrap;\"\u003eresize.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/resize.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"save.png\" style=\"white-space: nowrap;\"\u003esave.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/notepad/save.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n\n\n\n\n\u003c/div\u003e\n\n\n\n\u003c/div\u003e\n\n\u003ch2 id=\"other---nyanmo-main-blog\"\u003eother - nyanmo main blog\u003c/h2\u003e\n\n\n\n\n\n\n    \n\n\n\n\u003cdiv style=\"display: flex; justify-content: center; flex-direction: column;\"\u003e\n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"PC.png\" style=\"white-space: nowrap;\"\u003ePC.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/PC.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"exitfullscreen.png\" style=\"white-space: nowrap;\"\u003eexitfullscreen.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/exitfullscreen.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"window.png\" style=\"white-space: nowrap;\"\u003ewindow.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/window.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"おもちゃせっと.png\" style=\"white-space: nowrap;\"\u003eおもちゃせっと.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83%e3%81%9b%e3%81%a3%e3%81%a8.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"おもちゃ箱.png\" style=\"white-space: nowrap;\"\u003eおもちゃ箱.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%81%8a%e3%82%82%e3%81%a1%e3%82%83%e7%ae%b1.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"はんだ.png\" style=\"white-space: nowrap;\"\u003eはんだ.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%81%af%e3%82%93%e3%81%a0.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"はんだごて.png\" style=\"white-space: nowrap;\"\u003eはんだごて.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%81%af%e3%82%93%e3%81%a0%e3%81%94%e3%81%a6.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"ガムテープ.png\" style=\"white-space: nowrap;\"\u003eガムテープ.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%82%ac%e3%83%a0%e3%83%86%e3%83%bc%e3%83%97.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"スマホ.png\" style=\"white-space: nowrap;\"\u003eスマホ.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%82%b9%e3%83%9e%e3%83%9b.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n    \n    \n\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"プラスチックほうき.png\" style=\"white-space: nowrap;\"\u003eプラスチックほうき.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/other/%e3%83%97%e3%83%a9%e3%82%b9%e3%83%81%e3%83%83%e3%82%af%e3%81%bb%e3%81%86%e3%81%8d.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n        \u003c/div\u003e\n    \n\n    \n\n\n\n\n\n\n\n\u003c/div\u003e\n\n\u003ch2 id=\"llm-bias-visualization\"\u003e\u003ca href=\"https://www.nyanmo.info/posts/idea/research/aimodelbiasanalyzer/\"\u003eLLM-bias-visualization\u003c/a\u003e\u003c/h2\u003e\n\n\n\n\n\n\n    \n\n\n\n\u003cdiv style=\"display: flex; justify-content: center; flex-direction: column;\"\u003e\n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"ひらめきバルブ.png\" style=\"white-space: nowrap;\"\u003eひらめきバルブ.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/LLM-bias-visualization/%e3%81%b2%e3%82%89%e3%82%81%e3%81%8d%e3%83%90%e3%83%ab%e3%83%96.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n\n\n\n\n\u003c/div\u003e\n\n\n\n\u003c/div\u003e\n\n\u003ch2 id=\"zenkakuhankaku-key\"\u003e\u003ca href=\"https://github.com/hello30190f/ZenkakuHankaku-Key\"\u003eZenkakuHankaku-Key\u003c/a\u003e\u003c/h2\u003e\n\n\n\n\n\n\n    \n\n\n\n\u003cdiv style=\"display: flex; justify-content: center; flex-direction: column;\"\u003e\n\n    \n    \n\n    \n        \u003cdiv style=\"display: flex; flex-direction: row; overflow: auto; justify-content: center;\"\u003e\n    \n\n        \n            \u003cdiv style=\"flex: 300px; width: 300px\"\u003e\n                \u003ch3 id=\"全角半角キー.png\" style=\"white-space: nowrap;\"\u003e全角半角キー.png\u003c/h3\u003e\n                \u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n                    \u003cimg src=\"/images/icons/ZenkakuHankaku-Key/%e5%85%a8%e8%a7%92%e5%8d%8a%e8%a7%92%e3%82%ad%e3%83%bc.png\" style=\"margin: 10px; width: 200px;\"\u003e\n                \u003c/div\u003e\n            \u003c/div\u003e\n        \n\n        \n\n        \n\n        \n\n    \n\n    \n\n\n\n\n\n\u003c/div\u003e\n\n\n\n\u003c/div\u003e","title":"Icons"},{"content":"この記事を作った動機 Windows機でもなんか鬱陶しかったので、設定するついでに記録するだけ。 やり方 レジストリを設定する。\nstop.reg 以下は、Disable Google Chrome asking to be Default Browser in Windows 11 | Windows 11 Forumの引用\nWindows Registry Editor Version 5.00 [HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Google\\Chrome] \u0026#34;DefaultBrowserSettingEnabled\u0026#34;=dword:00000000 最近気づいたこと（2025年5月18日） 今回のレジストリ設定をすると、「組織に管理されています」と出てくることが分かった。どうやらレジストリ経由で、Google Chrome ポリシー設定をすると、そういうことになる模様。まあ何かウイルスが入って、悪さしているとかではないので、特に問題はなさそうである。 気になるなら？ この表示が嫌ならば、単にレジストリ設定を消せば、解決されると思われる。思いっきり \u0026ldquo;Chrome\u0026rdquo; と書かれたレジストリ設定を消せばいいと思われる。ただ、それだと今回の目標である、デフォルトブラウザを尋ねさせないという事は、両立できない。。。\nというか結構小難しく考えていたが、案外ポリシー設定って単純なレジストリ設定でできることに、今回の出来事で気づいた。\n気づきのきっかけ ちなみになんでこんなことに気づいたかといえば、設定画面に気色悪い「組織に管理されています」という表示が出ていることに気づいて、外し方を調べていた。\nそしたら、Error: How To Fix-Google Chrome Your Browser is Managed By Your Organisation - YouTube の動画がヒットし、Download Chrome Policy Remover - HackerDoseの bat スクリプトを中身を読んでから、余計なことをしてなさそうだと実行したところ、気づいた。\nどうもこのスクリプトは、動作の一部として、\u0026ldquo;HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Google\\Chrome\u0026rdquo; あたりのキーも消してた。そこにあった設定は、今回設定した、デフォルトブラウザを尋ねない項目についても含む。そのツールを実行したことによってそのキーも消えて、「組織に管理されています」とは出てこなくなった代わりに「デフォルトブラウザにしてください」と広告は出てくるようになった。\nそうして事態に気づいたわけで、一応なんか書いてないと見た人が不安になるかなと思って、適当に記録を残しておくことにした。\n関係のありそうなページ Google Chrome がいちいちデフォルトブラウザにするようにと強引に広告出してくるのを止める 参考にしたサイトとか Disable Google Chrome asking to be Default Browser in Windows 11 | Windows 11 Forum\nhttps://www.elevenforum.com/t/disable-google-chrome-asking-to-be-default-browser-in-windows-11.27008/ (2025年5月13日) Error: How To Fix-Google Chrome Your Browser is Managed By Your Organisation - YouTube\nhttps://www.youtube.com/watch?v=LX54VkBl17I (2025年5月18日) Download Chrome Policy Remover - HackerDose\nhttps://hackerdose.com/downloads/utility/chrome-policy-remover/ (2025年5月18日) ","permalink":"https://www.nyanmo.info/posts/windows/makechromestopfromaskingaboutdefaultbrowser/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Windows機でもなんか鬱陶しかったので、設定するついでに記録するだけ。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makeChromeStopFromAskingAboutDefaultBrowser/%e5%95%8f%e9%a1%8c%e3%81%ae%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"問題の状態\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　レジストリを設定する。\u003c/p\u003e\n\u003ch3 id=\"stopreg\"\u003estop.reg\u003c/h3\u003e\n\u003cp\u003e　以下は、\u003ca href=\"https://www.elevenforum.com/t/disable-google-chrome-asking-to-be-default-browser-in-windows-11.27008/\"\u003eDisable Google Chrome asking to be Default Browser in Windows 11 | Windows 11 Forum\u003c/a\u003eの引用\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eWindows Registry Editor Version 5.00\n\n[HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Google\\Chrome]\n\u0026#34;DefaultBrowserSettingEnabled\u0026#34;=dword:00000000\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"最近気づいたこと2025年5月18日\"\u003e最近気づいたこと（2025年5月18日）\u003c/h2\u003e\n\u003cp\u003e　今回のレジストリ設定をすると、「組織に管理されています」と出てくることが分かった。どうやらレジストリ経由で、Google Chrome ポリシー設定をすると、そういうことになる模様。まあ何かウイルスが入って、悪さしているとかではないので、特に問題はなさそうである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makeChromeStopFromAskingAboutDefaultBrowser/%e7%b5%84%e7%b9%94%e3%81%ab%e3%82%88%e3%81%a3%e3%81%a6%e7%ae%a1%e7%90%86%e3%81%95%e3%82%8c%e3%81%a6%e3%81%84%e3%81%be%e3%81%99%e3%81%a8%e5%87%ba%e3%81%a6%e3%81%8d%e3%81%a6%e3%81%97%e3%81%be%e3%81%86.png#center\"\n         alt=\"組織によって管理されていますと出てきてしまう\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"気になるなら\"\u003e気になるなら？\u003c/h3\u003e\n\u003cp\u003e　この表示が嫌ならば、単にレジストリ設定を消せば、解決されると思われる。思いっきり \u0026ldquo;Chrome\u0026rdquo; と書かれたレジストリ設定を消せばいいと思われる。ただ、それだと今回の目標である、デフォルトブラウザを尋ねさせないという事は、両立できない。。。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/makeChromeStopFromAskingAboutDefaultBrowser/windows%e4%b8%8a%e3%81%a7%e3%81%af%e5%8d%98%e3%81%ab%e3%83%9d%e3%83%aa%e3%82%b7%e3%83%bc%e8%a8%ad%e5%ae%9a%e3%81%af%e3%83%ac%e3%82%b8%e3%82%b9%e3%83%88%e3%83%aa%e3%81%a8%e3%81%97%e3%81%a6%e5%ad%98%e5%9c%a8%e3%81%97%e3%81%a6%e3%81%84%e3%82%8b.png#center\"\n         alt=\"windows上では単にポリシー設定はレジストリとして存在している\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　というか結構小難しく考えていたが、案外ポリシー設定って単純なレジストリ設定でできることに、今回の出来事で気づいた。\u003c/p\u003e\n\u003ch3 id=\"気づきのきっかけ\"\u003e気づきのきっかけ\u003c/h3\u003e\n\u003cp\u003e　ちなみになんでこんなことに気づいたかといえば、設定画面に気色悪い「組織に管理されています」という表示が出ていることに気づいて、外し方を調べていた。\u003c/p\u003e\n\u003cp\u003e　そしたら、\u003ca href=\"https://www.youtube.com/watch?v=LX54VkBl17I\"\u003eError: How To Fix-Google Chrome Your Browser is Managed By Your Organisation - YouTube\u003c/a\u003e の動画がヒットし、\u003ca href=\"https://hackerdose.com/downloads/utility/chrome-policy-remover/\"\u003eDownload Chrome Policy Remover - HackerDose\u003c/a\u003eの bat スクリプトを中身を読んでから、余計なことをしてなさそうだと実行したところ、気づいた。\u003c/p\u003e\n\u003cp\u003e　どうもこのスクリプトは、動作の一部として、\u0026ldquo;HKEY_LOCAL_MACHINE\\SOFTWARE\\Policies\\Google\\Chrome\u0026rdquo; あたりのキーも消してた。そこにあった設定は、今回設定した、デフォルトブラウザを尋ねない項目についても含む。そのツールを実行したことによってそのキーも消えて、「組織に管理されています」とは出てこなくなった代わりに「デフォルトブラウザにしてください」と広告は出てくるようになった。\u003c/p\u003e\n\u003cp\u003e　そうして事態に気づいたわけで、一応なんか書いてないと見た人が不安になるかなと思って、適当に記録を残しておくことにした。\u003c/p\u003e\n\u003ch2 id=\"関係のありそうなページ\"\u003e関係のありそうなページ\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/makechromestopfromaskingaboutdefaultbrowser/\"\u003eGoogle Chrome がいちいちデフォルトブラウザにするようにと強引に広告出してくるのを止める\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eDisable Google Chrome asking to be Default Browser in Windows 11 | Windows 11 Forum\u003cbr\u003e\n\u003ca href=\"https://www.elevenforum.com/t/disable-google-chrome-asking-to-be-default-browser-in-windows-11.27008/\"\u003ehttps://www.elevenforum.com/t/disable-google-chrome-asking-to-be-default-browser-in-windows-11.27008/\u003c/a\u003e (2025年5月13日)\u003c/li\u003e\n\u003cli\u003eError: How To Fix-Google Chrome Your Browser is Managed By Your Organisation - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/watch?v=LX54VkBl17I\"\u003ehttps://www.youtube.com/watch?v=LX54VkBl17I\u003c/a\u003e (2025年5月18日)\u003c/li\u003e\n\u003cli\u003eDownload Chrome Policy Remover - HackerDose\u003cbr\u003e\n\u003ca href=\"https://hackerdose.com/downloads/utility/chrome-policy-remover/\"\u003ehttps://hackerdose.com/downloads/utility/chrome-policy-remover/\u003c/a\u003e (2025年5月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"Google Chrome のデフォルトブラウザポップアップの停止 (Windows)"},{"content":"この記事を作った動機 最近、Apple WirelessKeyboard A1016 を手に入れるという事があったのだが、それを動作確認するとき、ペアリングがトリッキーなことが分かったのでそれを記録するだけ。\n環境 windows 11 Pro 23H2 bluetooth 4.0対応のレシーバ\nIntel(R) Dual Band Wireless-AC 7265 ペアリング方法 windows を待機状態にする 設定画面から、新規 bluetooth デバイスを受け付けるモードにする。\napple keyboard の電源を入れる キーボードの電源を入れて、LEDが点滅するのを確認する。LEDが点滅している状態が、どうもペアリング待機状態っぽい。\nwindows 側に検出されるのを待つ 普通の bluetooth キーボードとかより、プロトコルが古いのか検出に時間がかかるので気長に待機する。なかなか出てこないときは、キーボード側のキーを適当にどっかおしてるといいかもしれない。\n検出された時 検出されたら、通常のペアリングと同様にそれを選択する。Apple Keyboard とかとして出てくるはずである。そしたらそれを選択して気長に待つ。この時キーボードは何も押さない。PINの受付要求が出てくるまで待つ。\nPINを聞かれたとき PINを聞かれたら、ペアリング対象のApple keyboard 側ではなく、別のキーボードで適当にPINを4桁決めて、例えば、\u0026ldquo;1234\u0026quot;などと入力する。そして接続ボタンを押したら、接続を試みるアニメーションが終わる前に、入力したPIN、今回であれば\u0026quot;1234\u0026quot;と、Apple keyboard 側で入力し、return キーを押す。\n具体的な指示が出てこないので、これに気づくのに時間がかかった。。。ネットで調べてもすぐにはなんか出てこないし。\n終わり うまくいけば、ペアリングされ通常どうり使える状態になるはずである。何か打ち間違えたとかで、ミスったらもう一回やり直しである。 ペアリング後 一応ペアリング後も癖がある動きをするので、その事についても書いておく。\n再接続 再接続するときは、PC側が起動して bluetooth を受け付けるようになってから、キーボードをオンする必要あるっぽい。\nなんかキーが押されたら、自動でペアリングされた端末につなぎなおしてくれるとか、そんな感じではないように思う。少なくとも私が実際に使った体験としては。\nLinux 環境について追記(2026/1/25) ペアリング方法 最近 Linux 環境に接続しようとしたところ、少なくともGNOMEのGUI環境ではろくに接続できなかったため、調べたところ以下のようにコマンドで接続する方法があることが分かった。私の arch linux 環境では、bluezだけでなく、bluez-utilsも事前にインストールされている必要があった。基本的な流れは以下のようになる。\nbluetoothctl に入り、scan onする Apple キーボード側の電源をいれる xx:xx:xx:xx:xx:xx Apple Wireless Keyboardと出てきたら、connect xx:xx:xx:xx:xx:xxする。 Apple キーボード側で、12345678などの8桁のPINを適当に入力して Enter キーを押す。 [agent] Enter PIN code:と聞かれたら、同じように12345678など、Apple キーボード側で入力した PIN を入力する。 Connection successful と出たら接続に成功している。 trust xx:xx:xx:xx:xx:xx で再接続時に弾かれないようにする。 # 上手く検出されないときは、bluetoothサービスを再起動する # sudo systemctl restart bluetooth sudo bluetoothctl ... [Paired Device Name]\u0026gt; scan on SetDiscoveryFilter success Discovery started [CHG] Controller 8C:88:2B:48:47:9C Discovering: yes ... [NEW] Device xx:xx:xx:xx:xx:xx Apple Wireless Keyboard ... [Paired Device Name]\u0026gt; connect xx:xx:xx:xx:xx:xx # Type 12345678 on apple keyboard [agent] Enter PIN code: 12345678 ... Connection successful [Paired Device Name]\u0026gt; trust xx:xx:xx:xx:xx:xx [Paired Device Name]\u0026gt; exit 再接続できない件について キーボードを Linux環境で再接続しようとすると、以下のようなエラーが出て、うまく再接続できない現象が確認された。GUI 上では、何かしらキーを押したりすると、接続しようとはするものの、切断されて、それを繰り返すという挙動になった。\n調べてみると、bluez-utilsのbluetoothctlで、接続後にtrust xx:xx:xx:xx:xx:xxをしていないことが原因であるということが分かった。もし、trust xx:xx:xx:xx:xx:xxし忘れた場合には、bluetoothctlに入ってdevicesと入力し、対象のMAC?アドレスを探して、trustすればいいことが分かった。\n以下は問題が起こったときの挙動の例である。\nsystemctl status bluetooth # Jan 26 07:28:10 hostName bluetoothd[740]: Authentication attempt without agent # Jan 26 07:28:10 hostName bluetoothd[740]: profiles/input/server.c:auth_callback() Access denied: org.bluez.Error.Rejected # 上手く検出されないときは、bluetoothサービスを再起動する # sudo systemctl restart bluetooth 以下はtrustするために、再設定時の様子を記録した例である。\nsudo bluetoothctl # ... # [bluetoothctl]\u0026gt; scan on # SetDiscoveryFilter success # Discovery started # ... # [CHG] Device xx:xx:xx:xx:xx:xx Connected: yes # Authorize service # [agent] Authorize service xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx (yes/no): yes # [Apple Wireless Keyboard]\u0026gt; devices # ... # Device xx:xx:xx:xx:xx:xx Apple Wireless Keyboard # ... # [Apple Wireless Keyboard]\u0026gt; trust xx:xx:xx:xx:xx:xx # [CHG] Device xx:xx:xx:xx:xx:xx Trusted: yes # Changing xx:xx:xx:xx:xx:xx trust succeeded # [Apple Wireless Keyboard]\u0026gt; scan off # Discovery stopped # ... # [Apple Wireless Keyboard]\u0026gt; exit 参考にしたサイトとか Using the A1016 Wireless Keyboard with Wi… - Apple Community\nhttps://discussions.apple.com/thread/5913233?sortBy=rank (2025年5月13日)\nbluetooth - Apple keyboard a1016, pairing fails - Ask Ubuntu\nhttps://askubuntu.com/questions/1020584/apple-keyboard-a1016-pairing-fails (2026年1月25日)\nBluetooth - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Bluetooth (2026年1月25日)\n[SOLVED] Bluetooth reconnects in another mode / Newbie Corner / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=283199 (2026年1月26日)\n[SOLVED] Avoid disconnecting from wifi when lid closes / Newbie Corner / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=283196 (2026年1月26日)\nBluetoothUser - Debian Wiki\nhttps://wiki.debian.org/BluetoothUser#Can.27t_reconnect_after_sleep (2026年1月26日)\n","permalink":"https://www.nyanmo.info/posts/hardware/keyboard/applewirelesskeyboarda1016/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、Apple WirelessKeyboard A1016 を手に入れるという事があったのだが、それを動作確認するとき、ペアリングがトリッキーなことが分かったのでそれを記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ewindows 11 Pro 23H2\u003c/li\u003e\n\u003cli\u003ebluetooth 4.0対応のレシーバ\u003cbr\u003e\nIntel(R) Dual Band Wireless-AC 7265\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ペアリング方法\"\u003eペアリング方法\u003c/h2\u003e\n\u003ch3 id=\"windows-を待機状態にする\"\u003ewindows を待機状態にする\u003c/h3\u003e\n\u003cp\u003e　設定画面から、新規 bluetooth デバイスを受け付けるモードにする。\u003c/p\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/appleWirelessKeyboardA1016/%e5%be%85%e6%a9%9f%e7%8a%b6%e6%85%8b%e6%89%8b%e5%89%8d.png#center\"\n         alt=\"待機状態手前\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/appleWirelessKeyboardA1016/%e5%be%85%e6%a9%9f%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"待機状態\"/\u003e \n\u003c/figure\u003e\n\n\n\u003c/div\u003e\n\u003ch3 id=\"apple-keyboard-の電源を入れる\"\u003eapple keyboard の電源を入れる\u003c/h3\u003e\n\u003cp\u003e　キーボードの電源を入れて、LEDが点滅するのを確認する。LEDが点滅している状態が、どうもペアリング待機状態っぽい。\u003c/p\u003e\n\u003ch3 id=\"windows-側に検出されるのを待つ\"\u003ewindows 側に検出されるのを待つ\u003c/h3\u003e\n\u003cp\u003e　普通の bluetooth キーボードとかより、プロトコルが古いのか検出に時間がかかるので気長に待機する。なかなか出てこないときは、キーボード側のキーを適当にどっかおしてるといいかもしれない。\u003c/p\u003e\n\u003ch3 id=\"検出された時\"\u003e検出された時\u003c/h3\u003e\n\u003cp\u003e　検出されたら、通常のペアリングと同様にそれを選択する。Apple Keyboard とかとして出てくるはずである。そしたらそれを選択して気長に待つ。この時キーボードは\u003cstrong\u003e何も押さない\u003c/strong\u003e。PINの受付要求が出てくるまで待つ。\u003c/p\u003e\n\u003ch3 id=\"pinを聞かれたとき\"\u003ePINを聞かれたとき\u003c/h3\u003e\n\u003cp\u003e　PINを聞かれたら、ペアリング対象のApple keyboard 側ではなく、別のキーボードで適当にPINを4桁決めて、例えば、\u0026ldquo;1234\u0026quot;などと入力する。そして接続ボタンを押したら、接続を試みるアニメーションが終わる前に、入力したPIN、今回であれば\u0026quot;1234\u0026quot;と、Apple keyboard 側で入力し、return キーを押す。\u003c/p\u003e\n\u003cp\u003e　具体的な指示が出てこないので、これに気づくのに時間がかかった。。。ネットで調べてもすぐにはなんか出てこないし。\u003c/p\u003e\n\u003ch3 id=\"終わり\"\u003e終わり\u003c/h3\u003e\n\u003cp\u003e　うまくいけば、ペアリングされ通常どうり使える状態になるはずである。何か打ち間違えたとかで、ミスったらもう\u003ca href=\"#windows-%E3%82%92%E5%BE%85%E6%A9%9F%E7%8A%B6%E6%85%8B%E3%81%AB%E3%81%99%E3%82%8B\"\u003e一回やり直し\u003c/a\u003eである。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/keyboard/appleWirelessKeyboardA1016/%e3%83%9a%e3%82%a2%e3%83%aa%e3%83%b3%e3%82%b0%e5%be%8c%e3%81%ae%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"ペアリング後の様子\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"ペアリング後\"\u003eペアリング後\u003c/h2\u003e\n\u003cp\u003e　一応ペアリング後も癖がある動きをするので、その事についても書いておく。\u003c/p\u003e\n\u003ch3 id=\"再接続\"\u003e再接続\u003c/h3\u003e\n\u003cp\u003e　再接続するときは、PC側が起動して bluetooth を受け付けるようになってから、キーボードをオンする必要あるっぽい。\u003c/p\u003e\n\u003cp\u003e　なんかキーが押されたら、自動でペアリングされた端末につなぎなおしてくれるとか、そんな感じではないように思う。少なくとも私が実際に使った体験としては。\u003c/p\u003e\n\u003ch2 id=\"linux-環境について追記2026125\"\u003eLinux 環境について追記(2026/1/25)\u003c/h2\u003e\n\u003ch3 id=\"ペアリング方法-1\"\u003eペアリング方法\u003c/h3\u003e\n\u003cp\u003e　最近 Linux 環境に接続しようとしたところ、少なくともGNOMEのGUI環境ではろくに接続できなかったため、\u003ca href=\"https://askubuntu.com/questions/1020584/apple-keyboard-a1016-pairing-fails\"\u003e調べた\u003c/a\u003eところ以下のようにコマンドで接続する方法があることが分かった。私の arch linux 環境では、\u003ccode\u003ebluez\u003c/code\u003eだけでなく、\u003ccode\u003ebluez-utils\u003c/code\u003eも事前にインストールされている必要があった。基本的な流れは以下のようになる。\u003c/p\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003ebluetoothctl に入り、\u003ccode\u003escan on\u003c/code\u003eする\u003c/li\u003e\n\u003cli\u003eApple キーボード側の電源をいれる\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003exx:xx:xx:xx:xx:xx Apple Wireless Keyboard\u003c/code\u003eと出てきたら、\u003ccode\u003econnect xx:xx:xx:xx:xx:xx\u003c/code\u003eする。\u003c/li\u003e\n\u003cli\u003eApple キーボード側で、\u003ccode\u003e12345678\u003c/code\u003eなどの8桁のPINを適当に入力して Enter キーを押す。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[agent] Enter PIN code:\u003c/code\u003eと聞かれたら、同じように\u003ccode\u003e12345678\u003c/code\u003eなど、Apple キーボード側で入力した PIN を入力する。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eConnection successful\u003c/code\u003e と出たら接続に成功している。\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003etrust xx:xx:xx:xx:xx:xx\u003c/code\u003e で再接続時に弾かれないようにする。\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 上手く検出されないときは、bluetoothサービスを再起動する\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# sudo systemctl restart bluetooth\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo bluetoothctl \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePaired Device Name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\u0026gt; scan on\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSetDiscoveryFilter success\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDiscovery started\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eCHG\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Controller 8C:88:2B:48:47:9C Discovering: yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eNEW\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Device xx:xx:xx:xx:xx:xx Apple Wireless Keyboard\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePaired Device Name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\u0026gt; connect xx:xx:xx:xx:xx:xx\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Type 12345678 on apple keyboard\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eagent\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e Enter PIN code: \u003cspan style=\"color:#ae81ff\"\u003e12345678\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eConnection successful\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePaired Device Name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\u0026gt; trust xx:xx:xx:xx:xx:xx \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ePaired Device Name\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\u0026gt; exit\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"再接続できない件について\"\u003e再接続できない件について\u003c/h3\u003e\n\u003cp\u003e　キーボードを Linux環境で再接続しようとすると、以下のようなエラーが出て、うまく再接続できない現象が確認された。GUI 上では、何かしらキーを押したりすると、接続しようとはするものの、切断されて、それを繰り返すという挙動になった。\u003c/p\u003e","title":"古の bluetooth Apple Wireless Keyboard A1016 をペアリングする ⌨️"},{"content":"この記事を作った動機 最近、HP Z2 Mini G3 Workstationを入手したのだが、ACアダプタに制約があり値段の高い純正ACアダプタを買わないと動かないという仕様になっていた。\nそこで、インターネットで適当に調べて、何かしらの抵抗を電源の＋とIDピン（ACアダプタを識別する Smart ACとか言われているやつ）の間につないでやれば動くことは分かったのだが、適切な抵抗値を見つけるのがめんどくさかったので、記録を残すだけ。\nとりあえずACアダプタチェックをバイパスできる抵抗値 50kΩ\nPC側の仕様 19.5 V 10.3 A 200 W 参考にした動画 試行錯誤の過程 最初にやったこと 正直＋とーのピン配列自体はDELLと同じなのでとりあえず、そのままDELLのACアダプタを指してみたが、案の上動かなかった。なんか赤いLEDが内部で光り、電源ボタンを押してもうんともすんとも言わない状態であった。\n次にやったこと ネット上の資料によれば、最小の抵抗値が100kΩ程度だったのでそれで試した。最初はlenovoの場合と同じかなと高をくくって情報を見落としIDピンを＋ではななくーにつないでた影響でうまくいっていなかった。\nその次にやったこと ネット上の資料を再確認し、100kΩ程度や300kΩ程度の抵抗などいろいろな抵抗値を+に改めてつなぐ方法で試してみると、一瞬動くものの、3回長いビープ音と4回の短いビープ音が鳴り、ACアダプタ不良という動きになった。 さらに次に試したこと 正直壊したくないので、改めて純正のACアダプタをハードオフで適当に新調し、135wのアダプタで試したが、それでも抵抗で試したときと変わらず同じエラーを吐いて動かなかった。 最後に試したこと ここまでの事から、\n抵抗値が高いほど、出力ワット数の低いACアダプタとして識別される また本体側の表記では、19.5v 10.3Aと書かれており、だいたい200wが必要 純正のACアダプタでも、出力が足りないと検出された場合、動かないことがあるかもしれない\nという事が見えてきた。 そこで100kΩよりさらに低い、50kΩの抵抗でだませないか試したところ、案の上あっさり動いてしまった。DELLのACアダプタでも全然動いた。出力数が65wのものでもとりあえずその枠内に収まっているうちはとりあえず起動していた。\nはまった理由 DELLの場合も同じように、ACアダプタを識別する仕組みがあるが、IDピンでのACアダプタの識別に失敗してもとりあえず最小クロックで動いてくれたりしてたので、同じことかと思い込んでいた。\n今回のようにうんともすんとも言わなかったり、動いても出力が不十分と判断されると電源不良のエラーをはいてPOSTしてBIOS画面が出てくるところに到達することさえできないのは想定外だった。\n作業の様子 参考にしたサイトとか c06914336.pdf\nhttps://h10032.www1.hp.com/ctg/Manual/c06914336.pdf (2025年5月12日) hp z2 mini beep codes - Hardware - Spiceworks Community\nhttps://community.spiceworks.com/t/hp-z2-mini-beep-codes/953245 (2025年5月12日) Hp Laptop Adapter ID pin Resister Value #lciit Laptop Repair Tutorial - YouTube\nhttps://www.youtube.com/shorts/zhc3uKgI9iE (2025年5月12日) ","permalink":"https://www.nyanmo.info/posts/hardware/hp/acadapteronhpz2minig3workstation/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、HP Z2 Mini G3 Workstationを入手したのだが、ACアダプタに制約があり値段の高い純正ACアダプタを買わないと動かないという仕様になっていた。\u003c/p\u003e\n\u003cp\u003e　そこで、インターネットで適当に調べて、何かしらの抵抗を電源の＋とIDピン（ACアダプタを識別する Smart ACとか言われているやつ）の間につないでやれば動くことは分かったのだが、適切な抵抗値を見つけるのがめんどくさかったので、記録を残すだけ。\u003c/p\u003e\n\u003ch2 id=\"とりあえずacアダプタチェックをバイパスできる抵抗値\"\u003eとりあえずACアダプタチェックをバイパスできる抵抗値\u003c/h2\u003e\n\u003cp\u003e50kΩ\u003c/p\u003e\n\u003ch2 id=\"pc側の仕様\"\u003ePC側の仕様\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e19.5 V\u003c/li\u003e\n\u003cli\u003e10.3 A\u003c/li\u003e\n\u003cli\u003e200 W\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/PC%e3%81%ae%e4%bb%95%e6%a7%98.jpg#center\"\n         alt=\"PCの仕様\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にした動画\"\u003e\u003ca href=\"https://www.youtube.com/shorts/zhc3uKgI9iE\"\u003e参考にした動画\u003c/a\u003e\u003c/h2\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e5%8f%82%e8%80%83%e3%81%ab%e3%81%97%e3%81%9f%e5%8b%95%e7%94%bb.png#center\"\n         alt=\"参考にした動画\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"試行錯誤の過程\"\u003e試行錯誤の過程\u003c/h2\u003e\n\u003ch3 id=\"最初にやったこと\"\u003e最初にやったこと\u003c/h3\u003e\n\u003cp\u003e　正直＋とーのピン配列自体はDELLと同じなのでとりあえず、そのままDELLのACアダプタを指してみたが、案の上動かなかった。なんか赤いLEDが内部で光り、電源ボタンを押してもうんともすんとも言わない状態であった。\u003c/p\u003e\n\u003ch3 id=\"次にやったこと\"\u003e次にやったこと\u003c/h3\u003e\n\u003cp\u003e　ネット上の資料によれば、最小の抵抗値が100kΩ程度だったのでそれで試した。最初はlenovoの場合と同じかなと高をくくって情報を見落としIDピンを＋ではななくーにつないでた影響でうまくいっていなかった。\u003c/p\u003e\n\u003ch3 id=\"その次にやったこと\"\u003eその次にやったこと\u003c/h3\u003e\n\u003cp\u003e　ネット上の資料を再確認し、100kΩ程度や300kΩ程度の抵抗などいろいろな抵抗値を+に改めてつなぐ方法で試してみると、一瞬動くものの、3回長いビープ音と4回の短いビープ音が鳴り、ACアダプタ不良という動きになった。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e3%82%a8%e3%83%a9%e3%83%bc%e3%82%b3%e3%83%bc%e3%83%89%e8%a1%a8.png#center\"\n         alt=\"エラーコード表\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"さらに次に試したこと\"\u003eさらに次に試したこと\u003c/h3\u003e\n\u003cp\u003e　正直壊したくないので、改めて純正のACアダプタをハードオフで適当に新調し、135wのアダプタで試したが、それでも抵抗で試したときと変わらず同じエラーを吐いて動かなかった。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/HP%20AC%e3%82%a2%e3%83%80%e3%83%97%e3%82%bf.jpg#center\"\n         alt=\"HP ACアダプタ\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"最後に試したこと\"\u003e最後に試したこと\u003c/h3\u003e\n\u003cp\u003eここまでの事から、\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e抵抗値が高いほど、出力ワット数の低いACアダプタとして識別される\u003c/li\u003e\n\u003cli\u003eまた本体側の表記では、19.5v 10.3Aと書かれており、だいたい200wが必要\u003c/li\u003e\n\u003cli\u003e純正のACアダプタでも、出力が足りないと検出された場合、動かないことがあるかもしれない\u003cbr\u003e\nという事が見えてきた。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　そこで100kΩよりさらに低い、50kΩの抵抗でだませないか試したところ、案の上あっさり動いてしまった。DELLのACアダプタでも全然動いた。出力数が65wのものでもとりあえずその枠内に収まっているうちはとりあえず起動していた。\u003c/p\u003e\n\u003ch2 id=\"はまった理由\"\u003eはまった理由\u003c/h2\u003e\n\u003cp\u003e　DELLの場合も同じように、ACアダプタを識別する仕組みがあるが、IDピンでのACアダプタの識別に失敗してもとりあえず最小クロックで動いてくれたりしてたので、同じことかと思い込んでいた。\u003c/p\u003e\n\u003cp\u003e　今回のようにうんともすんとも言わなかったり、動いても出力が不十分と判断されると電源不良のエラーをはいてPOSTしてBIOS画面が出てくるところに到達することさえできないのは想定外だった。\u003c/p\u003e\n\u003ch2 id=\"作業の様子\"\u003e作業の様子\u003c/h2\u003e\n\u003cp\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e6%94%b9%e9%80%a0%e5%be%8c.jpg#center\"\n         alt=\"改造後\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e6%94%b9%e9%80%a0%e5%be%8c50k%e6%8a%b5%e6%8a%97.jpg#center\"\n         alt=\"改造後50k抵抗\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e6%94%b9%e9%80%a0%e5%be%8c%e5%85%a8%e4%bd%93%e5%83%8f.jpg#center\"\n         alt=\"改造後全体像\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hardware/hp/ACAdapterOnHPZ2MiniG3Workstation/%e6%94%b9%e9%80%a0%e5%be%8cPC.jpg#center\"\n         alt=\"改造後PC\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ec06914336.pdf\u003cbr\u003e\n\u003ca href=\"https://h10032.www1.hp.com/ctg/Manual/c06914336.pdf\"\u003ehttps://h10032.www1.hp.com/ctg/Manual/c06914336.pdf\u003c/a\u003e (2025年5月12日)\u003c/li\u003e\n\u003cli\u003ehp z2 mini beep codes - Hardware - Spiceworks Community\u003cbr\u003e\n\u003ca href=\"https://community.spiceworks.com/t/hp-z2-mini-beep-codes/953245\"\u003ehttps://community.spiceworks.com/t/hp-z2-mini-beep-codes/953245\u003c/a\u003e (2025年5月12日)\u003c/li\u003e\n\u003cli\u003eHp Laptop Adapter ID pin Resister Value #lciit Laptop Repair Tutorial - YouTube\u003cbr\u003e\n\u003ca href=\"https://www.youtube.com/shorts/zhc3uKgI9iE\"\u003ehttps://www.youtube.com/shorts/zhc3uKgI9iE\u003c/a\u003e (2025年5月12日)\u003c/li\u003e\n\u003c/ul\u003e","title":"HP Z2 Mini G3 WorkstationのACアダプタ識別を回避する 🔌"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 electron で何かアプリを作ろうかなと思ったとき、心理的障壁として、IPC によるやり取りがあったので、それについて、間違ってもいいのでとにかく自分なりにノートを作ろうと思っただけ。\nIPC なにそれおいしいの？ IPC(Inter Process Communication) とは、複数のプログラム間で、データをやり取りしたりするための仕組みの一つ。いろんな仕組みがある。ネットワークを使うとか特定のメモリ領域を共有するとか。。。\nelectron と何が関係あるの？ 今の私の理解だと、electron は複数のプロセスからなっていて、単に一つのプログラムに対して、一つのプロセスが起動しているという感じではない。少なくとも、OS側の処理を担う、main と呼ばれているプロセスと、chromiumベースの描画用のプロセス(renderer.jsもここ)が存在している。\nセキュリティの関係上、一つのプロセスとして全てが処理されておらず、分離されている。そのため、例えばファイル操作を実装したいとなったときなどには、main プロセスと、renderer.js などが動いている描画用プロセス間でデータをやり取りする必要がある。\nそこで、データをやり取りする手段として、IPCがある。\nやり方 以下は適当に、Using Preload Scripts | Electronあたりから、IPCを使って main プロセスと描画プロセスがやり取りするために必要であると思われる部分を、部分的に引っ張っていじくりまわして試したコードである。\nmain.js preload.js を指定 ipcMain.handle const { app, BrowserWindow, ipcMain } = require(\u0026#39;electron/main\u0026#39;) const path = require(\u0026#34;node:path\u0026#34;) const createWindow = () =\u0026gt; { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { preload: path.join(__dirname, \u0026#39;preload.js\u0026#39;) } }) win.loadFile(\u0026#39;src/index.html\u0026#39;) } function scandir(){ return [\u0026#34;aaa.txt\u0026#34;,\u0026#34;bbb.txt\u0026#34;] } app.whenReady().then(() =\u0026gt; { createWindow() ipcMain.handle(\u0026#34;ping\u0026#34;,() =\u0026gt; \u0026#34;pong\u0026#34;) ipcMain.handle(\u0026#34;scandir\u0026#34;,scandir) app.on(\u0026#39;activate\u0026#39;, () =\u0026gt; { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) }) app.on(\u0026#39;window-all-closed\u0026#39;, () =\u0026gt; { if (process.platform !== \u0026#39;darwin\u0026#39;) { app.quit() } }) preload.js renderer.js内での呼び出し方の決定 const { contextBridge, ipcRenderer } = require(\u0026#39;electron\u0026#39;) contextBridge.exposeInMainWorld(\u0026#34;callme\u0026#34;,{ ping: () =\u0026gt; ipcRenderer.invoke(\u0026#34;ping\u0026#34;), scandir: () =\u0026gt; ipcRenderer.invoke(\u0026#34;scandir\u0026#34;) }) // renderer.js // let response = await window.callme.ping() 以下は、Using Preload Scripts | Electronの引用\nconst { contextBridge, ipcRenderer } = require(\u0026#39;electron\u0026#39;) contextBridge.exposeInMainWorld(\u0026#39;versions\u0026#39;, { node: () =\u0026gt; process.versions.node, chrome: () =\u0026gt; process.versions.chrome, electron: () =\u0026gt; process.versions.electron, ping: () =\u0026gt; ipcRenderer.invoke(\u0026#39;ping\u0026#39;) // we can also expose variables, not just functions }) index.html \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; ... \u0026lt;script src=\u0026#34;./renderer.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; ... \u0026lt;/html\u0026gt; renderer.js const func = async () =\u0026gt; { const response = await window.callme.ping() alert(response) const res = await window.callme.scandir() console.log(res) } console.log(\u0026#34;this is test\u0026#34;) func() 参考にしたサイトとか Inter-Process Communication | Electron\nhttps://www.electronjs.org/docs/latest/tutorial/ipc (2025年5月11日) Using Preload Scripts | Electron\nhttps://www.electronjs.org/docs/latest/tutorial/tutorial-preload (2025年5月11日) How Does IPC Work? | Common Use Cases Explained | Lenovo US\nhttps://www.lenovo.com/us/en/glossary/ipc/ (2025年5月11日) contextBridge | Electron\nhttps://www.electronjs.org/docs/latest/api/context-bridge (2025年5月11日) ","permalink":"https://www.nyanmo.info/posts/webdevelop/electron/howtouseipc/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　electron で何かアプリを作ろうかなと思ったとき、心理的障壁として、IPC によるやり取りがあったので、それについて、間違ってもいいのでとにかく自分なりにノートを作ろうと思っただけ。\u003c/p\u003e\n\u003ch2 id=\"ipc\"\u003eIPC\u003c/h2\u003e\n\u003ch3 id=\"なにそれおいしいの\"\u003eなにそれおいしいの？\u003c/h3\u003e\n\u003cp\u003e　IPC(Inter Process Communication) とは、複数のプログラム間で、データをやり取りしたりするための仕組みの一つ。いろんな仕組みがある。ネットワークを使うとか特定のメモリ領域を共有するとか。。。\u003c/p\u003e\n\u003ch3 id=\"electron-と何が関係あるの\"\u003eelectron と何が関係あるの？\u003c/h3\u003e\n\u003cp\u003e　今の私の理解だと、electron は複数のプロセスからなっていて、単に一つのプログラムに対して、一つのプロセスが起動しているという感じではない。少なくとも、OS側の処理を担う、main と呼ばれているプロセスと、chromiumベースの描画用のプロセス(renderer.jsもここ)が存在している。\u003c/p\u003e\n\u003cp\u003e　セキュリティの関係上、一つのプロセスとして全てが処理されておらず、分離されている。そのため、例えばファイル操作を実装したいとなったときなどには、main プロセスと、renderer.js などが動いている描画用プロセス間でデータをやり取りする必要がある。\u003c/p\u003e\n\u003cp\u003e　そこで、データをやり取りする手段として、IPCがある。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　以下は適当に、\u003ca href=\"https://www.electronjs.org/docs/latest/tutorial/tutorial-preload\"\u003eUsing Preload Scripts | Electron\u003c/a\u003eあたりから、IPCを使って main プロセスと描画プロセスがやり取りするために必要であると思われる部分を、部分的に引っ張っていじくりまわして試したコードである。\u003c/p\u003e\n\u003ch3 id=\"mainjs\"\u003emain.js\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003epreload.js を指定\u003c/li\u003e\n\u003cli\u003eipcMain.handle\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eBrowserWindow\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eipcMain\u003c/span\u003e } \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;electron/main\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epath\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;node:path\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecreateWindow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewin\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBrowserWindow\u003c/span\u003e({\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e800\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e600\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewebPreferences\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003epreload\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epath\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ejoin\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e__dirname\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;preload.js\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewin\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eloadFile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;src/index.html\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003escandir\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;aaa.txt\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;bbb.txt\u0026#34;\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewhenReady\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003ethen\u003c/span\u003e(() =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \t\u003cspan style=\"color:#a6e22e\"\u003ecreateWindow\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eipcMain\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ping\u0026#34;\u003c/span\u003e,() =\u0026gt; \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;pong\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eipcMain\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scandir\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003escandir\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;activate\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eBrowserWindow\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003egetAllWindows\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t\u003cspan style=\"color:#a6e22e\"\u003ecreateWindow\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eon\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;window-all-closed\u0026#39;\u003c/span\u003e, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eplatform\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;darwin\u0026#39;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eapp\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003equit\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"preloadjs\"\u003epreload.js\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003erenderer.js内での呼び出し方の決定\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003econtextBridge\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eipcRenderer\u003c/span\u003e } \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erequire\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;electron\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econtextBridge\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eexposeInMainWorld\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;callme\u0026#34;\u003c/span\u003e,{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eping\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eipcRenderer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einvoke\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ping\u0026#34;\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003escandir\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e () =\u0026gt; \u003cspan style=\"color:#a6e22e\"\u003eipcRenderer\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einvoke\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scandir\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// renderer.js\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// let response = await window.callme.ping()\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　以下は、\u003ca href=\"https://www.electronjs.org/docs/latest/tutorial/tutorial-preload\"\u003eUsing Preload Scripts | Electron\u003c/a\u003eの引用\u003c/p\u003e","title":"IPC の使い方"},{"content":"この記事を作った動機 最近、いろいろ作ってみてはファイルがあっちゃこっちゃ行ってぐちゃぐちゃになっていたので、整理の一環として、LAN内で Gitea なるものを動かしてみている\nそこで、内部ネットワークで使っている証明書を windows 側にいれても git がそれを直接は使ってくれなかったので、SSL 証明書の設定の仕方を自分用に記録するだけ。(すぐ忘れるし)\nやり方 # 多分 global オプションはつけないほうがいいかも。全体的に証明書情報を変えてしまい、ほかのリポジトリで、githubから何かしようとか思ったとき、多分証明書が合わなくてエラーを吐いてしまう。 # git config --global http.sslCAInfo /path/to/cert.pem git config http.sslCAInfo /path/to/cert.pem 参考にしたサイトとか configure Git to accept a particular self-signed server certificate for a particular https remote - Stack Overflow\nhttps://stackoverflow.com/questions/9072376/configure-git-to-accept-a-particular-self-signed-server-certificate-for-a-partic (2025年5月11日) ","permalink":"https://www.nyanmo.info/posts/other/addcertificatetogit/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近、いろいろ作ってみてはファイルがあっちゃこっちゃ行ってぐちゃぐちゃになっていたので、整理の一環として、LAN内で Gitea なるものを動かしてみている\u003c/p\u003e\n\u003cp\u003e　そこで、内部ネットワークで使っている証明書を windows 側にいれても git がそれを直接は使ってくれなかったので、SSL 証明書の設定の仕方を自分用に記録するだけ。(すぐ忘れるし)\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 多分 global オプションはつけないほうがいいかも。全体的に証明書情報を変えてしまい、ほかのリポジトリで、githubから何かしようとか思ったとき、多分証明書が合わなくてエラーを吐いてしまう。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# git config --global http.sslCAInfo /path/to/cert.pem \u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit config http.sslCAInfo /path/to/cert.pem\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003econfigure Git to accept a particular self-signed server certificate for a particular https remote - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/9072376/configure-git-to-accept-a-particular-self-signed-server-certificate-for-a-partic\"\u003ehttps://stackoverflow.com/questions/9072376/configure-git-to-accept-a-particular-self-signed-server-certificate-for-a-partic\u003c/a\u003e (2025年5月11日)\u003c/li\u003e\n\u003c/ul\u003e","title":"git に証明書を追加する"},{"content":"この記事を作った動機 最近550円で Thinkpad T430 を買って色々動かしてみて遊んでみたら、blender が動かなかったので、記録を取るだけ。\n環境 Report details Date generated: 2025-05-08 04:15:17 Hardware Information: Hardware Model: Lenovo ThinkPad T430 Memory: 12.0 GiB Processor: Intel® Core™ i5-3230M × 4 Graphics: Intel® HD Graphics 4000 (IVB GT2) Disk Capacity: 628.1 GB Software Information: Firmware Version: G1ET92WW (2.52 ) OS Name: Arch Linux OS Build: rolling OS Type: 64-bit GNOME Version: 48 Windowing System: Wayland Kernel Version: Linux 6.14.5-arch1-1 解決方法 単純に環境変数として、Intel® HD Graphics 4000 がサポートする openGL のバージョンを指定する。解決方法の書いてある記事を読み切る前にどうすればいいかわかってしまったので、深いことはわからないが、blender 4.x.x くらいから、openGLのバージョンのデフォルトの最低要件が上がったらしいく、その影響で起動しないっぽかった。\n/etc/environment # # This file is parsed by pam_env module # # Syntax: simple \u0026#34;KEY=VAL\u0026#34; pairs on separate lines # GTK_IM_MODULE=fcitx5 QT_IM_MODULE=fcitx5 XMODIFIERS=@im=fcitx5 CHROME_DEFAULT_BROWSER_CHECK_ENABLED=0 # blender 用の openGL の設定 MESA_GLSL_VERSION_OVERRIDE=430 MESA_GL_VERSION_OVERRIDE=4.3FC ちなみに（2025年5月13日） ちなみにではあるが、結局この方法ではとりあえず動いても、結局なんか MMD ツールとか入れて、もっときつい事させようとすると、すぐクラッシュする。\n純粋に何もしなくても動く、古いバージョンを使う方が実用上は現実的かもしれない。\n参考にしたサイトとか [Solved] OpenGL / Blender issue on Intel HD4000 / Newbie Corner / Arch Linux Forums\nhttps://bbs.archlinux.org/viewtopic.php?id=291515 （2025年5月8日） ","permalink":"https://www.nyanmo.info/posts/blender/intelhdgraphics4000/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　最近550円で Thinkpad T430 を買って色々動かしてみて遊んでみたら、blender が動かなかったので、記録を取るだけ。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"report-details\"\u003eReport details\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eDate generated:\u003c/strong\u003e                              2025-05-08 04:15:17\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"hardware-information\"\u003eHardware Information:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eHardware Model:\u003c/strong\u003e                              Lenovo ThinkPad T430\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eMemory:\u003c/strong\u003e                                      12.0 GiB\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eProcessor:\u003c/strong\u003e                                   Intel® Core™ i5-3230M × 4\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGraphics:\u003c/strong\u003e                                    Intel® HD Graphics 4000 (IVB GT2)\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eDisk Capacity:\u003c/strong\u003e                               628.1 GB\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"software-information\"\u003eSoftware Information:\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eFirmware Version:\u003c/strong\u003e                            G1ET92WW (2.52 )\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Name:\u003c/strong\u003e                                     Arch Linux\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Build:\u003c/strong\u003e                                    rolling\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eOS Type:\u003c/strong\u003e                                     64-bit\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eGNOME Version:\u003c/strong\u003e                               48\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eWindowing System:\u003c/strong\u003e                            Wayland\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eKernel Version:\u003c/strong\u003e                              Linux 6.14.5-arch1-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"解決方法\"\u003e解決方法\u003c/h2\u003e\n\u003cp\u003e　単純に環境変数として、Intel® HD Graphics 4000 がサポートする openGL のバージョンを指定する。\u003ca href=\"https://bbs.archlinux.org/viewtopic.php?id=291515\"\u003e解決方法\u003c/a\u003eの書いてある記事を読み切る前にどうすればいいかわかってしまったので、深いことはわからないが、blender 4.x.x くらいから、openGLのバージョンのデフォルトの最低要件が上がったらしいく、その影響で起動しないっぽかった。\u003c/p\u003e","title":"blender が Intel HD Graphics 4000 で動かない"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を作った動機 markdown のテンプレートを作るにおいて、テンプレートを作ったついでに、そのテンプレート内で初めて真面目に hugo の機能を使った気がするので次いでにその例を記録するだけ。ただの自己満と言われればそうなのかもしれない。\n内容 layouts/shortcodes/Images/MMD/Data.html {{ $folder := .Get \u0026#34;folder\u0026#34; }} \u0026lt;ul\u0026gt; {{$path := printf \u0026#34;static/Images/MMD/%s\u0026#34; $folder}} {{range readDir $path}} {{$filepath := printf \u0026#34;%s/%s\u0026#34; $path .Name}} {{$filepath := replace $filepath \u0026#34;static\u0026#34; \u0026#34;\u0026#34;}} {{if strings.Contains .Name \u0026#34;.blend\u0026#34;}} \u0026lt;li\u0026gt; \u0026lt;a download href=\u0026#34;{{$filepath}}\u0026#34;\u0026gt;{{.Name}}\u0026lt;/a\u0026gt; \u0026lt;/li\u0026gt; {{end}} {{if strings.Contains .Name \u0026#34;.zip\u0026#34;}} \u0026lt;li\u0026gt; \u0026lt;a download href=\u0026#34;{{$filepath}}\u0026#34;\u0026gt;{{.Name}}\u0026lt;/a\u0026gt; \u0026lt;/li\u0026gt; {{end}} {{end}} \u0026lt;/ul\u0026gt; archetypes/Images/MMD.md +++ date = \u0026#39;{{ .Date }}\u0026#39; draft = false title = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39; +++ ## data \\{\\{\u0026lt;Images/MMD/Data folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}} ## Images and Videos \\{\\{\u0026lt;Images/MMD/ShowImageAndVideo folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}} readDir strings.Contains replace 参考にしたサイトとか https://gohugo.io/functions/os/readdir/#article\nhttps://gohugo.io/functions/strings/contains/#article\nhttps://gohugo.io/functions/strings/replace/#article\n","permalink":"https://www.nyanmo.info/posts/hugo/automateshortcode/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/hugo/createmarkdownarticletemplate/\"\u003emarkdown のテンプレートを作る\u003c/a\u003eにおいて、テンプレートを作ったついでに、そのテンプレート内で初めて真面目に hugo の機能を使った気がするので次いでにその例を記録するだけ。ただの自己満と言われればそうなのかもしれない。\u003c/p\u003e\n\u003ch2 id=\"内容\"\u003e内容\u003c/h2\u003e\n\u003ch3 id=\"layoutsshortcodesimagesmmddatahtml\"\u003elayouts/shortcodes/Images/MMD/Data.html\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e{{ $folder := .Get \u0026#34;folder\u0026#34; }}\n\u0026lt;ul\u0026gt;\n    {{$path := printf \u0026#34;static/Images/MMD/%s\u0026#34; $folder}}\n    {{range readDir $path}}\n        {{$filepath := printf \u0026#34;%s/%s\u0026#34; $path .Name}}\n        {{$filepath := replace $filepath \u0026#34;static\u0026#34; \u0026#34;\u0026#34;}}\n        {{if strings.Contains .Name \u0026#34;.blend\u0026#34;}}\n            \u0026lt;li\u0026gt;\n                \u0026lt;a download href=\u0026#34;{{$filepath}}\u0026#34;\u0026gt;{{.Name}}\u0026lt;/a\u0026gt;\n            \u0026lt;/li\u0026gt;\n        {{end}}\n    \n        {{if strings.Contains .Name \u0026#34;.zip\u0026#34;}}\n            \u0026lt;li\u0026gt;\n                \u0026lt;a download href=\u0026#34;{{$filepath}}\u0026#34;\u0026gt;{{.Name}}\u0026lt;/a\u0026gt;\n            \u0026lt;/li\u0026gt;\n        {{end}}\n    {{end}}\n\u0026lt;/ul\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"archetypesimagesmmdmd\"\u003earchetypes/Images/MMD.md\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ndate = \u0026#39;{{ .Date }}\u0026#39;\ndraft = false\ntitle = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39;\n+++\n\n## data\n\\{\\{\u0026lt;Images/MMD/Data folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}}\n\n## Images and Videos\n\\{\\{\u0026lt;Images/MMD/ShowImageAndVideo folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}}\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ereadDir\nstrings.Contains\nreplace\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://gohugo.io/functions/os/readdir/#article\"\u003ehttps://gohugo.io/functions/os/readdir/#article\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://gohugo.io/functions/strings/contains/#article\"\u003ehttps://gohugo.io/functions/strings/contains/#article\u003c/a\u003e\u003cbr\u003e\n\u003ca href=\"https://gohugo.io/functions/strings/replace/#article\"\u003ehttps://gohugo.io/functions/strings/replace/#article\u003c/a\u003e\u003c/p\u003e","title":"自動化 shortcode"},{"content":"この記事を作った動機 私がやり方わかんなくなった時の記録として。\nやり方 設定前の全体像 環境テクスチャを選択 設定後のパネルの様子 設定後の全体像 参考にしたサイトとか Environment Texture Node - Blender 4.4 Manual\nhttps://docs.blender.org/manual/en/latest/render/shader_nodes/textures/environment.html （2025年5月5日） Symmetrical Garden 02 HDRI • Poly Haven\nhttps://polyhaven.com/a/symmetrical_garden_02 （2025年5月5日） ","permalink":"https://www.nyanmo.info/posts/blender/sethdri/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　私がやり方わかんなくなった時の記録として。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003ch3 id=\"設定前の全体像\"\u003e設定前の全体像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/setHDRI/%e8%a8%ad%e5%ae%9a%e5%89%8d-%e7%94%bb%e9%9d%a2%e5%85%a8%e4%bd%93.png#center\"\n         alt=\"設定前-画面全体\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"環境テクスチャを選択\"\u003e環境テクスチャを選択\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/setHDRI/%e7%92%b0%e5%a2%83%e3%83%86%e3%82%af%e3%82%b9%e3%83%81%e3%83%a3%e3%82%92%e9%81%b8%e6%8a%9e.png#center\"\n         alt=\"環境テクスチャを選択\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"設定後のパネルの様子\"\u003e設定後のパネルの様子\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/setHDRI/%e8%a8%ad%e5%ae%9a%e5%be%8c%e3%81%ae%e6%a7%98%e5%ad%90.png#center\"\n         alt=\"設定後の様子\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"設定後の全体像\"\u003e設定後の全体像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/setHDRI/%e8%a8%ad%e5%ae%9a%e5%be%8c-%e7%94%bb%e9%9d%a2%e5%85%a8%e4%bd%93.png#center\"\n         alt=\"設定後-画面全体\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eEnvironment Texture Node - Blender 4.4 Manual\u003cbr\u003e\n\u003ca href=\"https://docs.blender.org/manual/en/latest/render/shader_nodes/textures/environment.html\"\u003ehttps://docs.blender.org/manual/en/latest/render/shader_nodes/textures/environment.html\u003c/a\u003e （2025年5月5日）\u003c/li\u003e\n\u003cli\u003eSymmetrical Garden 02 HDRI • Poly Haven\u003cbr\u003e\n\u003ca href=\"https://polyhaven.com/a/symmetrical_garden_02\"\u003ehttps://polyhaven.com/a/symmetrical_garden_02\u003c/a\u003e （2025年5月5日）\u003c/li\u003e\n\u003c/ul\u003e","title":"環境テクスチャを設定する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） この記事を書いた動機 Google Chrome が図々しく至るところで、\u0026ldquo;Set as default browser\u0026rdquo; と表示を出してくてあまりにうざいのと、そのプロンプトの止め方がlinux環境だとあまり見つけづらかったので、自分用に記録するだけ。\n問題の状態 解決された状態 追記（2025年5月31日） 最近、実はこの記事で書いた方法も機能しないことに気づいた。最初から機能していなかったのか、それとも最近機能していなかったのかは定かではない。更に調べる必要がありそうである。\n環境 Arch Linux Gnome wayland やり方（機能しない） 環境変数で、\u0026ldquo;CHROME_DEFAULT_BROWSER_CHECK_ENABLED=0\u0026quot;と設定する。\nターミナルで環境変数を設定 export CHROME_DEFAULT_BROWSER_CHECK_ENABLED=0 /etc/environmentで自動的に環境変数を設定 何かいちいち毎回起動時に環境変数を設定するsystemdスクリプトを書いて管理するのめんどいので、以下のように設定してみた。これでも機能したので、私は良しとしている。以下は、wayland向けの設定であり、x11を使っているなら、.xprofileあたりに設定する必要があると思われる。\n# # This file is parsed by pam_env module # # Syntax: simple \u0026#34;KEY=VAL\u0026#34; pairs on separate lines # GTK_IM_MODULE=fcitx5 QT_IM_MODULE=fcitx5 XMODIFIERS=@im=fcitx5 CHROME_DEFAULT_BROWSER_CHECK_ENABLED=0 機能しないやり方 chrome://flags \u0026ldquo;Version 136.0.7103.59 (Official Build) (64-bit)\u0026ldquo;では、デフォルトブラウザを尋ねる（押し付ける）を無効化するフラグ (Default Browser Prompt Refresh) がなかった。Googleは更に\u0026quot;Be evil\u0026quot;に。。。どうも調べているうちにわかったこととしては、もはやレジストリとか、OSごとに異なる方法を使う必要があるようで、もう呆れる。 chrome://policy これは機能しないというより、単にlinux環境において、どうやってグループポリシーを設定するかめんどくさくて一旦置いたというのが正しい。一応オプションの存在自体は確認できた。直接chrome 側から設定できるという感じではない。Windowsであれば、何か適当にローカルグループポリシーを設定すればOS側からchrome側に反映されるようであるが、試していない。\n一見何も設定項目はないように見えるとき 設定していない項目を表示すると、設定の存在を確認できる 関係のありそうなページ Google Chrome のデフォルトブラウザポップアップの停止 (Windows) 参考にしたサイトとか internet explorer - How to prevent Google Chrome from changing the default browser to itself in Windows 7? - Super User\nhttps://superuser.com/questions/970837/how-to-prevent-google-chrome-from-changing-the-default-browser-to-itself-in-wind （2025年5月2日） google chrome - \u0026ldquo;Persistent \u0026lsquo;Set as Default\u0026rsquo; Warning Issue in Ubuntu 23.10 Browsers\u0026rdquo; - Ask Ubuntu\nhttps://askubuntu.com/questions/1491482/persistent-set-as-default-warning-issue-in-ubuntu-23-10-browsers （2025年5月2日） How to make Google Chrome stop asking to be the default browser? - Ask Different\nhttps://apple.stackexchange.com/questions/422481/how-to-make-google-chrome-stop-asking-to-be-the-default-browser （2025年5月2日） ","permalink":"https://www.nyanmo.info/posts/linux/makechromestopfromaskingaboutdefaultbrowser/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　Google Chrome が図々しく至るところで、\u0026ldquo;Set as default browser\u0026rdquo; と表示を出してくてあまりにうざいのと、そのプロンプトの止め方がlinux環境だとあまり見つけづらかったので、自分用に記録するだけ。\u003c/p\u003e\n\u003ch3 id=\"問題の状態\"\u003e問題の状態\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/makeChromeStopFromAskingAboutDefaultBrowser/%e3%81%84%e3%81%a1%e3%81%84%e3%81%a1NO%e3%81%a8%e8%a8%80%e3%81%a3%e3%81%a6%e3%81%84%e3%82%8b%e3%81%ae%e3%81%ab%e5%b0%8b%e3%81%ad%e3%81%a6%e3%81%8f%e3%82%8b%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"いちいちNOと言っているのに尋ねてくる状態\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"解決された状態\"\u003e解決された状態\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/makeChromeStopFromAskingAboutDefaultBrowser/%e7%92%b0%e5%a2%83%e5%a4%89%e6%95%b0%e3%82%92%e8%a8%ad%e5%ae%9a%e3%81%97%e5%b0%8b%e3%81%ad%e3%81%aa%e3%81%8f%e3%81%aa%e3%81%a3%e3%81%9f%e7%8a%b6%e6%85%8b.png#center\"\n         alt=\"環境変数を設定し尋ねなくなった状態\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"追記2025年5月31日\"\u003e追記（2025年5月31日）\u003c/h2\u003e\n\u003cp\u003e　最近、実はこの記事で書いた方法も機能しないことに気づいた。最初から機能していなかったのか、それとも最近機能していなかったのかは定かではない。更に調べる必要がありそうである。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eArch Linux\u003c/li\u003e\n\u003cli\u003eGnome\u003c/li\u003e\n\u003cli\u003ewayland\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"やり方機能しない\"\u003eやり方（機能しない）\u003c/h2\u003e\n\u003cp\u003e　環境変数で、\u0026ldquo;CHROME_DEFAULT_BROWSER_CHECK_ENABLED=0\u0026quot;と設定する。\u003c/p\u003e\n\u003ch3 id=\"ターミナルで環境変数を設定\"\u003eターミナルで環境変数を設定\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexport CHROME_DEFAULT_BROWSER_CHECK_ENABLED\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"etcenvironmentで自動的に環境変数を設定\"\u003e/etc/environmentで自動的に環境変数を設定\u003c/h3\u003e\n\u003cp\u003e　何かいちいち毎回起動時に環境変数を設定するsystemdスクリプトを書いて管理するのめんどいので、以下のように設定してみた。これでも機能したので、私は良しとしている。以下は、wayland向けの設定であり、x11を使っているなら、.xprofileあたりに設定する必要があると思われる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# This file is parsed by pam_env module\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Syntax: simple \u0026#34;KEY=VAL\u0026#34; pairs on separate lines\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGTK_IM_MODULE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003efcitx5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eQT_IM_MODULE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003efcitx5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eXMODIFIERS\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e@im\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003efcitx5\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCHROME_DEFAULT_BROWSER_CHECK_ENABLED\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"機能しないやり方\"\u003e機能しないやり方\u003c/h2\u003e\n\u003ch3 id=\"chromeflags\"\u003echrome://flags\u003c/h3\u003e\n\u003cp\u003e　\u0026ldquo;Version 136.0.7103.59 (Official Build) (64-bit)\u0026ldquo;では、デフォルトブラウザを尋ねる（押し付ける）を無効化するフラグ (Default Browser Prompt Refresh) がなかった。Googleは更に\u0026quot;Be evil\u0026quot;に。。。どうも調べているうちにわかったこととしては、もはやレジストリとか、OSごとに異なる方法を使う必要があるようで、もう呆れる。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/makeChromeStopFromAskingAboutDefaultBrowser/flag%e3%81%8c%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e4%be%8b.png#center\"\n         alt=\"flagが見つからない例\"/\u003e \n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/makeChromeStopFromAskingAboutDefaultBrowser/flag%e3%81%8c%e8%a6%8b%e3%81%a4%e3%81%8b%e3%82%89%e3%81%aa%e3%81%84%e4%be%8b-%e5%88%a9%e7%94%a8%e4%b8%8d%e5%8f%af%e8%83%bd%e3%81%ae%e9%a0%85%e7%9b%ae%e3%81%ab%e3%81%95%e3%81%88%e3%81%aa%e3%81%84.png#center\"\n         alt=\"flagが見つからない例-利用不可能の項目にさえない\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"chromepolicy\"\u003echrome://policy\u003c/h3\u003e\n\u003cp\u003e　これは機能しないというより、単にlinux環境において、どうやってグループポリシーを設定するかめんどくさくて一旦置いたというのが正しい。一応オプションの存在自体は確認できた。直接chrome 側から設定できるという感じではない。Windowsであれば、何か適当にローカルグループポリシーを設定すればOS側からchrome側に反映されるようであるが、試していない。\u003c/p\u003e","title":"Google Chrome がいちいちデフォルトブラウザにするようにと強引に広告出してくるのを止める(機能しない)"},{"content":"この記事を作った動機 自分用の android studio におけるアプリ開発時に引っかかる部分の記録です。単にアクテビティなしのテンプレートからアプリを作ろうとしたとき、アプリ起動時のアクテビティを指定する必要があり、そのやり方を毎回忘れるというのが、この記事を書くきっかけです。\n重要な部分(引用部分) \u0026lt;intent-filter\u0026gt; \u0026lt;action android:name=\u0026#34;android.intent.action.MAIN\u0026#34; /\u0026gt; \u0026lt;category android:name=\u0026#34;android.intent.category.LAUNCHER\u0026#34; /\u0026gt; \u0026lt;/intent-filter\u0026gt; AndroidManifest.xml の全体像の例 \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;manifest xmlns:android=\u0026#34;http://schemas.android.com/apk/res/android\u0026#34; xmlns:tools=\u0026#34;http://schemas.android.com/tools\u0026#34;\u0026gt; \u0026lt;application android:allowBackup=\u0026#34;true\u0026#34; android:dataExtractionRules=\u0026#34;@xml/data_extraction_rules\u0026#34; android:fullBackupContent=\u0026#34;@xml/backup_rules\u0026#34; android:icon=\u0026#34;@mipmap/ic_launcher\u0026#34; android:label=\u0026#34;@string/app_name\u0026#34; android:roundIcon=\u0026#34;@mipmap/ic_launcher_round\u0026#34; android:supportsRtl=\u0026#34;true\u0026#34; android:theme=\u0026#34;@style/Theme.FileShareViewsmb\u0026#34; tools:targetApi=\u0026#34;31\u0026#34;\u0026gt; \u0026lt;activity android:name=\u0026#34;.MainActivity\u0026#34; android:exported=\u0026#34;true\u0026#34;\u0026gt; \u0026lt;intent-filter\u0026gt; \u0026lt;action android:name=\u0026#34;android.intent.action.MAIN\u0026#34; /\u0026gt; \u0026lt;category android:name=\u0026#34;android.intent.category.LAUNCHER\u0026#34; /\u0026gt; \u0026lt;/intent-filter\u0026gt; \u0026lt;/activity\u0026gt; \u0026lt;/application\u0026gt; \u0026lt;/manifest\u0026gt; 参考にしたサイトとか android - Change application\u0026rsquo;s starting activity - Stack Overflow\nhttps://stackoverflow.com/questions/3631982/change-applications-starting-activity （2025年5月1日） ","permalink":"https://www.nyanmo.info/posts/android/androidstudio/setfirstactivity/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　自分用の android studio におけるアプリ開発時に引っかかる部分の記録です。単にアクテビティなしのテンプレートからアプリを作ろうとしたとき、アプリ起動時のアクテビティを指定する必要があり、そのやり方を毎回忘れるというのが、この記事を書くきっかけです。\u003c/p\u003e\n\u003ch2 id=\"重要な部分引用部分\"\u003e重要な部分(\u003ca href=\"https://stackoverflow.com/questions/3631982/change-applications-starting-activity\"\u003e引用部分\u003c/a\u003e)\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;action\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.intent.action.MAIN\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;category\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.intent.category.LAUNCHER\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"androidmanifestxml-の全体像の例\"\u003eAndroidManifest.xml の全体像の例\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;manifest\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003exmlns:android=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://schemas.android.com/apk/res/android\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003exmlns:tools=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;http://schemas.android.com/tools\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;application\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:allowBackup=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:dataExtractionRules=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@xml/data_extraction_rules\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:fullBackupContent=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@xml/backup_rules\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:icon=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@mipmap/ic_launcher\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:label=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@string/app_name\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:roundIcon=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@mipmap/ic_launcher_round\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:supportsRtl=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eandroid:theme=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;@style/Theme.FileShareViewsmb\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etools:targetApi=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;31\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;activity\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.MainActivity\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eandroid:exported=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;action\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.intent.action.MAIN\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026lt;category\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.intent.category.LAUNCHER\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/intent-filter\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/activity\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/application\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/manifest\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eandroid - Change application\u0026rsquo;s starting activity - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/3631982/change-applications-starting-activity\"\u003ehttps://stackoverflow.com/questions/3631982/change-applications-starting-activity\u003c/a\u003e （2025年5月1日）\u003c/li\u003e\n\u003c/ul\u003e","title":"Android アプリで最初に起動するアクテビティを指定する"},{"content":"この記事を作った動機 Google Chrome を linux環境で使っていて、動画再生が安定せず、フレームが落ちまくり、CPUをめちゃくちゃに使い込むということがあったので、それに対処したときの記録を残すというだけです。\n環境 XPS 13 2in1 (9365) Intel® UHD Graphics 615 wayland 48 Chrome (バージョン: 135.0.7049.84（Official Build） （64 ビット）) lsmod | grep i915 i915 4714496 61 i2c_algo_bit 20480 1 i915 drm_buddy 24576 1 i915 ttm 110592 1 i915 intel_gtt 28672 1 i915 drm_display_helper 270336 1 i915 cec 94208 2 drm_display_helper,i915 video 81920 3 dell_wmi,dell_laptop,i915 インストールするパッケージ GNOME 環境が動く状態が前提。必要そうなものは全部入れているので、いらないものもあるかもしれない。もしくは、インストールしたけど、色々探しているうちに存在を忘れていて、ここにはちゃんと書けていないものがあるかもしれない。\nlibva-intel-driver intel-media-driver lib32-mesa 1:25.0.3-1 mesa ~/.config/chrome-flags 今のところ、以下の設定で、ハードウェアアクセラレーションが機能することが確認できた。intel-gpu-tools をインストールして、intel_gpu_top で video の項目が動画再生時になんか動いてそうだったら、とりあえず成功したということだと思う。\n--enable-features=UseOzonePlatform --ozone-platform=wayland --enable-accelerated-video-decode --enable-accelerated-video-encode --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=UseChromeOSDirectVideoDecoder vainfo 参考として、一応 VA-API の状態もここにおいておく。vainfo の利用には、libva-utils をインストールする必要がある。今の私がわかっていないこととしては、lsmod で確認すると、i915 が使われているが、vainfo では、iHD driver と表示されているところがある。\nvainfo Trying display: wayland vainfo: VA-API version: 1.22 (libva 2.22.0) vainfo: Driver version: Intel iHD driver for Intel(R) Gen Graphics - 25.1.4 () vainfo: Supported profile and entrypoints VAProfileNone :\tVAEntrypointVideoProc VAProfileNone :\tVAEntrypointStats VAProfileMPEG2Simple :\tVAEntrypointVLD VAProfileMPEG2Simple :\tVAEntrypointEncSlice VAProfileMPEG2Main :\tVAEntrypointVLD VAProfileMPEG2Main :\tVAEntrypointEncSlice VAProfileH264Main :\tVAEntrypointVLD VAProfileH264Main :\tVAEntrypointEncSlice VAProfileH264Main :\tVAEntrypointFEI VAProfileH264Main :\tVAEntrypointEncSliceLP VAProfileH264High :\tVAEntrypointVLD VAProfileH264High :\tVAEntrypointEncSlice VAProfileH264High :\tVAEntrypointFEI VAProfileH264High :\tVAEntrypointEncSliceLP VAProfileVC1Simple :\tVAEntrypointVLD VAProfileVC1Main :\tVAEntrypointVLD VAProfileVC1Advanced :\tVAEntrypointVLD VAProfileJPEGBaseline :\tVAEntrypointVLD VAProfileJPEGBaseline :\tVAEntrypointEncPicture VAProfileH264ConstrainedBaseline:\tVAEntrypointVLD VAProfileH264ConstrainedBaseline:\tVAEntrypointEncSlice VAProfileH264ConstrainedBaseline:\tVAEntrypointFEI VAProfileH264ConstrainedBaseline:\tVAEntrypointEncSliceLP VAProfileVP8Version0_3 :\tVAEntrypointVLD VAProfileVP8Version0_3 :\tVAEntrypointEncSlice VAProfileHEVCMain :\tVAEntrypointVLD VAProfileHEVCMain :\tVAEntrypointEncSlice VAProfileHEVCMain :\tVAEntrypointFEI VAProfileHEVCMain10 :\tVAEntrypointVLD VAProfileHEVCMain10 :\tVAEntrypointEncSlice VAProfileVP9Profile0 :\tVAEntrypointVLD VAProfileVP9Profile2 :\tVAEntrypointVLD chrome://gpu 一応参考として、動画のハードウェアアクセラレーションができるときと、できないときの chrome://gpu の例も載せておく。\nハードウェアアクセラレーションが有効なとき ハードウェアアクセラレーションが実質機能していないとき \u0026ndash;use-gl=desktop ちなみに、\u0026ndash;use-gl=desktop というオプションもあるらしい。しかし、私の環境ではそれを有効にすると、全部描画処理がソフトウェアの処理になってCPUしか使ってくれなくなった。\n試した設定の全体像 一応関係なさそうな部分も含め全部ここに試した設定を置いておく。\n--enable-features=UseOzonePlatform --ozone-platform=wayland --use-gl=desktop --enable-accelerated-video-decode --enable-accelerated-video-encode #--enable-features=VaapiVideoDecoder --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=UseChromeOSDirectVideoDecoder #--enable-wayland-ime --gtk-version=4 --disable-features=GlobalShortcutsPortal chrome://gpu 参考にしたサイトとか Hardware video acceleration - ArchWiki\nhttps://wiki.archlinux.org/title/Hardware_video_acceleration （2025年4月26日） Chromium - ArchWiki\nhttps://wiki.archlinux.org/title/Chromium#Hardware_video_acceleration （2025年4月26日） If you have trouble getting VA-API hardware video acceleration to work in Chromium, try adding the \u0026ndash;disable-features=UseChromeOSDirectVideoDecoder flag : r/archlinux\nhttps://www.reddit.com/r/archlinux/comments/tc5379/if_you_have_trouble_getting_vaapi_hardware_video/ （2025年4月26日） Seems Google Chrome Hardware Acceleration isn\u0026rsquo;t Working - Support - Manjaro Linux Forum\nhttps://forum.manjaro.org/t/seems-google-chrome-hardware-acceleration-isnt-working/101235/4 （2025年4月26日） ","permalink":"https://www.nyanmo.info/posts/linux/chromehardwarevideoacceleration/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Google Chrome を linux環境で使っていて、動画再生が安定せず、フレームが落ちまくり、CPUをめちゃくちゃに使い込むということがあったので、それに対処したときの記録を残すというだけです。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eXPS 13 2in1 (9365)\u003c/li\u003e\n\u003cli\u003eIntel® UHD Graphics 615\u003c/li\u003e\n\u003cli\u003ewayland 48\u003c/li\u003e\n\u003cli\u003eChrome (バージョン: 135.0.7049.84（Official Build） （64 ビット）)\u003c/li\u003e\n\u003cli\u003elsmod | grep i915\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ei915                 4714496  61\ni2c_algo_bit           20480  1 i915\ndrm_buddy              24576  1 i915\nttm                   110592  1 i915\nintel_gtt              28672  1 i915\ndrm_display_helper    270336  1 i915\ncec                    94208  2 drm_display_helper,i915\nvideo                  81920  3 dell_wmi,dell_laptop,i915\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"インストールするパッケージ\"\u003eインストールするパッケージ\u003c/h2\u003e\n\u003cp\u003e　GNOME 環境が動く状態が前提。必要そうなものは全部入れているので、いらないものもあるかもしれない。もしくは、インストールしたけど、色々探しているうちに存在を忘れていて、ここにはちゃんと書けていないものがあるかもしれない。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003elibva-intel-driver\u003c/li\u003e\n\u003cli\u003eintel-media-driver\u003c/li\u003e\n\u003cli\u003elib32-mesa 1:25.0.3-1\u003c/li\u003e\n\u003cli\u003emesa\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"configchrome-flags\"\u003e~/.config/chrome-flags\u003c/h2\u003e\n\u003cp\u003e　今のところ、以下の設定で、ハードウェアアクセラレーションが機能することが確認できた。intel-gpu-tools をインストールして、intel_gpu_top で video の項目が動画再生時になんか動いてそうだったら、とりあえず成功したということだと思う。\u003c/p\u003e","title":"Chrome と Intel UHD 615 で 動画再生にハードウェアアクセラレーションを使いたい "},{"content":"この記事を作った動機 なんか linux 環境で chrome を使ってたら、いちいちキーボード・ショートカットのポップアップが出てくるようになった。起動するたびに出てきて鬱陶しいので、調べたところ、一時的な対応として、起動フラグがあることが見つかったので、記録するだけ。\n~/.config/chrome-flags.conf ... --disable-features=GlobalShortcutsPortal ... 参考にしたサイトとか Opening Google Chrome has started automatically opening \u0026ldquo;Shortcuts - System Settings\u0026rdquo; with it - how to\u0026hellip;not do that? : r/kde\nhttps://www.reddit.com/r/kde/comments/1jauzpa/opening_google_chrome_has_started_automatically/ （2025年4月21日） ","permalink":"https://www.nyanmo.info/posts/linux/chromekeyboradshortcutpopuponstartup/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　なんか linux 環境で chrome を使ってたら、いちいちキーボード・ショートカットのポップアップが出てくるようになった。起動するたびに出てきて鬱陶しいので、調べたところ、一時的な対応として、起動フラグがあることが見つかったので、記録するだけ。\u003c/p\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/linux/chromeKeyboradShortcutPopupOnStartUp/%e5%95%8f%e9%a1%8c%e3%81%ae%e3%83%9d%e3%83%83%e3%83%97%e3%82%a2%e3%83%83%e3%83%97.png#center\"\n         alt=\"問題のポップアップ\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"configchrome-flagsconf\"\u003e~/.config/chrome-flags.conf\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e...\n--disable-features=GlobalShortcutsPortal\n...\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eOpening Google Chrome has started automatically opening \u0026ldquo;Shortcuts - System Settings\u0026rdquo; with it - how to\u0026hellip;not do that? : r/kde\u003cbr\u003e\n\u003ca href=\"https://www.reddit.com/r/kde/comments/1jauzpa/opening_google_chrome_has_started_automatically/\"\u003ehttps://www.reddit.com/r/kde/comments/1jauzpa/opening_google_chrome_has_started_automatically/\u003c/a\u003e （2025年4月21日）\u003c/li\u003e\n\u003c/ul\u003e","title":"chrome が linux 環境でいちいちキーボードショートカットを尋ねてくる"},{"content":"この記事を作った動機 Wayland環境を使っていて、いちいち設定を見に行くのがめんどくさいので、ここにメモ書きとして乗せるだけ。「fcitx5 の日本語入力ができない問題を何とかする」ということに注目している。\n~/.config/code-flags.conf を以下のように編集 --enable-features=UseOzonePlatform --gtk-version=4 --enable-wayland-ime --wayland-text-input-version=3 # これは実験した跡 #--ozone-platform=x11 #--ozone-platform-hint=auto 必要なパッケージ 上記だけでは動かない場合、この記事でも書いている、fcitx5 関連のパッケージをインストールする。以下は、gnomeの設定のメモ ⚙の引用である。\nパッケージのインストール 私は普段 fcitx5 を常用しているので、それらをインストール。\n# 通常はこれだけ入れればうまく行くかも yay -S fcitx5 fcitx5-mozc fcitx5-input-support fcitx5-configtool # なんかうまく動かないと思ったらここらへんも確認してみるといいかも yay -S fcitx5-qt fcitx5-gtk fcitx5-anthy 関連するページ gnomeの設定のメモ ⚙ 参考にしたサイトとか Visual Studio Code - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Visual_Studio_Code （2025年4月12日） Wayland - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Wayland#Electron （2025年4月12日） Using Fcitx 5 on Wayland - Fcitx\nhttps://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland （2025年4月12日） ","permalink":"https://www.nyanmo.info/posts/linux/vscodewithwaylandandfcitx5inputmethod/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　Wayland環境を使っていて、いちいち設定を見に行くのがめんどくさいので、ここにメモ書きとして乗せるだけ。「fcitx5 の日本語入力ができない問題を何とかする」ということに注目している。\u003c/p\u003e\n\u003ch2 id=\"configcode-flagsconf-を以下のように編集\"\u003e~/.config/code-flags.conf を以下のように編集\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e--enable-features=UseOzonePlatform\n--gtk-version=4\n--enable-wayland-ime\n--wayland-text-input-version=3\n\n# これは実験した跡\n#--ozone-platform=x11\n#--ozone-platform-hint=auto\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"必要なパッケージ\"\u003e必要なパッケージ\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"#configcode-flagsconf-%E3%82%92%E4%BB%A5%E4%B8%8B%E3%81%AE%E3%82%88%E3%81%86%E3%81%AB%E7%B7%A8%E9%9B%86\"\u003e上記\u003c/a\u003eだけでは動かない場合、\u003ca href=\"\"\u003eこの記事\u003c/a\u003eでも書いている、fcitx5 関連のパッケージをインストールする。以下は、\u003ca href=\"https://www.nyanmo.info/posts/linux/gnomesettings/\"\u003egnomeの設定のメモ ⚙\u003c/a\u003eの引用である。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch3 id=\"パッケージのインストール\"\u003eパッケージのインストール\u003c/h3\u003e\n\u003cp\u003e　私は普段 fcitx5 を常用しているので、それらをインストール。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 通常はこれだけ入れればうまく行くかも\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S fcitx5 fcitx5-mozc fcitx5-input-support fcitx5-configtool\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# なんかうまく動かないと思ったらここらへんも確認してみるといいかも\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eyay -S fcitx5-qt fcitx5-gtk fcitx5-anthy\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"関連するページ\"\u003e関連するページ\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/gnomesettings/\"\u003egnomeの設定のメモ ⚙\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eVisual Studio Code - ArchWiki\u003cbr\u003e\n\u003ca href=\"https://wiki.archlinux.jp/index.php/Visual_Studio_Code\"\u003ehttps://wiki.archlinux.jp/index.php/Visual_Studio_Code\u003c/a\u003e （2025年4月12日）\u003c/li\u003e\n\u003cli\u003eWayland - ArchWiki\u003cbr\u003e\n\u003ca href=\"https://wiki.archlinux.jp/index.php/Wayland#Electron\"\u003ehttps://wiki.archlinux.jp/index.php/Wayland#Electron\u003c/a\u003e （2025年4月12日）\u003c/li\u003e\n\u003cli\u003eUsing Fcitx 5 on Wayland - Fcitx\u003cbr\u003e\n\u003ca href=\"https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland\"\u003ehttps://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland\u003c/a\u003e （2025年4月12日）\u003c/li\u003e\n\u003c/ul\u003e","title":"Visual Studio Code の Wayland の設定をする"},{"content":"この記事を書いた動機 単純に普段、linux 環境を使っていて、chmod コマンドの詳しい忘れていることがあり、いちいち調べるのが面倒くさいので、私にとって使いやすい形で記録を取っただけです。\nchmod テーブル Permission Octal Decimal \u0026mdash; 000 0 \u0026ndash;x 001 1 -w- 010 2 -wx 011 3 r\u0026ndash; 100 4 r-x 101 5 rw- 110 6 rwx 111 7 参考にしたサイトとか Chmod Command Cheat Sheet \u0026amp; Quick Reference\nhttps://quickref.me/chmod.html （2025年4月10日） ","permalink":"https://www.nyanmo.info/posts/linux/chmodhint/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　単純に普段、linux 環境を使っていて、chmod コマンドの詳しい忘れていることがあり、いちいち調べるのが面倒くさいので、私にとって使いやすい形で記録を取っただけです。\u003c/p\u003e\n\u003ch2 id=\"chmod-テーブル\"\u003echmod テーブル\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003ePermission\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eOctal\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eDecimal\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u0026mdash;\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e000\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e0\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e\u0026ndash;x\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e001\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e1\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e-w-\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e010\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e2\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003e-wx\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e011\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e3\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003er\u0026ndash;\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e100\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e4\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003er-x\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e101\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e5\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003erw-\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e110\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e6\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003erwx\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e111\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e7\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChmod Command Cheat Sheet \u0026amp; Quick Reference\u003cbr\u003e\n\u003ca href=\"https://quickref.me/chmod.html\"\u003ehttps://quickref.me/chmod.html\u003c/a\u003e （2025年4月10日）\u003c/li\u003e\n\u003c/ul\u003e","title":"chmod チートシート"},{"content":"この記事を作った動機 普段 linux 環境を使っているので、Windows の PowerShell コマンドとか、コマンドプロンプトに疎く、忘れることがあるので、記録を取ってみるところ。\nコマンドプロンプトからPowerShellに入る REM 以下のように直接名前を書くだけで起動できる powershell which 相当 Get-command taskmgr CommandType Name Version Source ----------- ---- ------- ------ Application Taskmgr.exe 10.0.2262… C:\\WINDOWS\\system32\\Taskmgr.exe pkill 相当 taskkill /F /IM main.exe 成功: プロセス \u0026#34;main.exe\u0026#34; (PID 10832) は強制終了されました。 gdisk や fdisk 相当 diskpart Microsoft DiskPart バージョン 10.0.22621.1 Copyright (C) Microsoft Corporation. コンピューター: HOSTNAME DISKPART\u0026gt; list disk ディスク 状態 サイズ 空き ダイナ GPT ### ミック ------------ ------------- ------- ------- --- --- ディスク 0 オンライン 931 GB 2048 KB * DISKPART\u0026gt; sel disk 0 ディスク 0 が選択されました。 DISKPART\u0026gt; list part Partition ### Type Size Offset ------------- ------------------ ------- ------- Partition 1 システム 100 MB 1024 KB Partition 2 予約済み 16 MB 101 MB Partition 3 プライマリ 929 GB 117 MB Partition 4 回復 872 MB 929 GB Partition 5 回復 900 MB 930 GB DISKPART\u0026gt; 参考にしたサイトとか taskkill | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/taskkill （2025年4月9日） diskpart | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/diskpart （2025年4月9日） windows - Equivalent of cmd\u0026rsquo;s \u0026ldquo;where\u0026rdquo; in powershell - Super User\nhttps://superuser.com/questions/675837/equivalent-of-cmds-where-in-powershell （2025年4月9日） ローカルLLM (Gemma-4-31B) （2026年10月21日） あとから見つかったもの freespace Windows and Unix command line equivalents\nhttps://gist.github.com/carlessanagustin/266171818584b3880f72a625dfa2513b (2025年9月26日) rm -rfd windows - Delete all files from a folder and its sub folders - Super User\nhttps://superuser.com/questions/741945/delete-all-files-from-a-folder-and-its-sub-folders (2025年9月26日) ","permalink":"https://www.nyanmo.info/posts/windows/linuxcommandtopowershell/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　普段 linux 環境を使っているので、Windows の PowerShell コマンドとか、コマンドプロンプトに疎く、忘れることがあるので、記録を取ってみるところ。\u003c/p\u003e\n\u003ch2 id=\"コマンドプロンプトからpowershellに入る\"\u003eコマンドプロンプトからPowerShellに入る\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM 以下のように直接名前を書くだけで起動できる\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epowershell\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"which-相当\"\u003ewhich 相当\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-PowerShell\" data-lang=\"PowerShell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGet-command taskmgr\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCommandType     Name                                               Version    Source\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-----------     ----                                               -------    ------\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eApplication     Taskmgr.exe                                        \u003cspan style=\"color:#ae81ff\"\u003e10.0\u003c/span\u003e.\u003cspan style=\"color:#ae81ff\"\u003e2262\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e…\u003c/span\u003e C:\\WINDOWS\\system32\\Taskmgr.exe\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"pkill-相当\"\u003epkill 相当\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-PowerShell\" data-lang=\"PowerShell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etaskkill /F /IM main.exe\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e成功\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e プロセス \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;main.exe\u0026#34;\u003c/span\u003e (PID \u003cspan style=\"color:#ae81ff\"\u003e10832\u003c/span\u003e) は強制終了されました\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"gdisk-や-fdisk-相当\"\u003egdisk や fdisk 相当\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-PowerShell\" data-lang=\"PowerShell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ediskpart\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMicrosoft DiskPart バージョン \u003cspan style=\"color:#ae81ff\"\u003e10.0\u003c/span\u003e.22621.1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCopyright (C) Microsoft Corporation.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eコンピューター\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e HOSTNAME\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDISKPART\u0026gt; list disk\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ディスク      状態           サイズ   空き   ダイナ GPT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e###                                          ミック\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ------------  -------------  -------  -------  ---  ---\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ディスク \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e    オンライン           \u003cspan style=\"color:#ae81ff\"\u003e931\u003c/span\u003e GB  \u003cspan style=\"color:#ae81ff\"\u003e2048\u003c/span\u003e KB        *\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDISKPART\u0026gt; sel disk \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eディスク \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e が選択されました\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDISKPART\u0026gt; list part\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#75715e\"\u003e###  Type                Size     Offset\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  -------------  ------------------  -------  -------\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e    システム               \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e MB  \u003cspan style=\"color:#ae81ff\"\u003e1024\u003c/span\u003e KB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e    予約済み                \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e MB   \u003cspan style=\"color:#ae81ff\"\u003e101\u003c/span\u003e MB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e    プライマリ              \u003cspan style=\"color:#ae81ff\"\u003e929\u003c/span\u003e GB   \u003cspan style=\"color:#ae81ff\"\u003e117\u003c/span\u003e MB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e    回復                 \u003cspan style=\"color:#ae81ff\"\u003e872\u003c/span\u003e MB   \u003cspan style=\"color:#ae81ff\"\u003e929\u003c/span\u003e GB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Partition \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e    回復                 \u003cspan style=\"color:#ae81ff\"\u003e900\u003c/span\u003e MB   \u003cspan style=\"color:#ae81ff\"\u003e930\u003c/span\u003e GB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDISKPART\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003etaskkill | Microsoft Learn\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/taskkill\"\u003ehttps://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/taskkill\u003c/a\u003e （2025年4月9日）\u003c/li\u003e\n\u003cli\u003ediskpart | Microsoft Learn\u003cbr\u003e\n\u003ca href=\"https://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/diskpart\"\u003ehttps://learn.microsoft.com/ja-jp/windows-server/administration/windows-commands/diskpart\u003c/a\u003e （2025年4月9日）\u003c/li\u003e\n\u003cli\u003ewindows - Equivalent of cmd\u0026rsquo;s \u0026ldquo;where\u0026rdquo; in powershell - Super User\u003cbr\u003e\n\u003ca href=\"https://superuser.com/questions/675837/equivalent-of-cmds-where-in-powershell\"\u003ehttps://superuser.com/questions/675837/equivalent-of-cmds-where-in-powershell\u003c/a\u003e （2025年4月9日）\u003c/li\u003e\n\u003cli\u003eローカルLLM (Gemma-4-31B) （2026年10月21日）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"あとから見つかったもの\"\u003eあとから見つかったもの\u003c/h2\u003e\n\u003ch3 id=\"freespace\"\u003efreespace\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eWindows and Unix command line equivalents\u003cbr\u003e\n\u003ca href=\"https://gist.github.com/carlessanagustin/266171818584b3880f72a625dfa2513b\"\u003ehttps://gist.github.com/carlessanagustin/266171818584b3880f72a625dfa2513b\u003c/a\u003e (2025年9月26日)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"rm--rfd\"\u003erm -rfd\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ewindows - Delete all files from a folder and its sub folders - Super User\u003cbr\u003e\n\u003ca href=\"https://superuser.com/questions/741945/delete-all-files-from-a-folder-and-its-sub-folders\"\u003ehttps://superuser.com/questions/741945/delete-all-files-from-a-folder-and-its-sub-folders\u003c/a\u003e (2025年9月26日)\u003c/li\u003e\n\u003c/ul\u003e","title":"よく忘れるコマンド集"},{"content":"この記事を作った動機 systemd を使って何かしらスクリプトを実行したい（例えば、自動的にネットワークドライブをマウントする）ときとかあるのですが、そのたびに検索したり過去に書いたスクリプトを漁るのは面倒なので、自分用にメモ書きのテンプレを置くだけです。本当にただの自分用テンプレなので、説明とかは全然していません。\n配置場所 root で実行したい任意のサービス 操作には管理者権限で、sudo systemctl enable [サービス名]のようにする必要がある。\n/etc/systemd/system/ ユーザーごとの任意のサービス 操作には、systemctl --user enable [サービス名]のようにして、--userスイッチが必要であり、サービスが保存されているユーザにログインして操作を行う必要がある。\n~/.config/systemd/user/ テンプレ After= は必ずしも指定する必要はない。依存するものがなければ、この項目はなくてもいい模様である。 スクリプトの実行 最小構成だと、Exec周りは、ExecStartだけでとりあえず動かすことができる。\n[Unit] Description=a systemd service run a script. After= [Service] WorkingDirectory= Type=simple User=root # Group=[GroupName] # Environment=\u0026#34;env=variable\u0026#34; ExecStartPre= ExecStart= ExecStartPost= ExecStopPre= ExecStop= ExecStopPost= Restart=on-failure [Install] WantedBy=multi-user.target プログラムの常駐 こちらも、最小構成だと、Exec周りは、ExecStartだけでとりあえず動かすことができる。ただ終了が強制終了になってしまうので注意する。\n[Unit] Description=a systemd service run a script. After= [Service] WorkingDirectory= Type=forking User=root # Group=[GroupName] # Environment=\u0026#34;env=variable\u0026#34; ExecStartPre= ExecStart= ExecStartPost= ExecStopPre= ExecStop= ExecStopPost= Restart=on-failure [Install] WantedBy=multi-user.target After= の設定 以下のようにして、どのサービスなどのあとにサービスを実行したいか、参考になると思われる。\nsystemctl list-unit-files systemctl list-unit-files --user systemd サービスの具体例 PC 起動時に virsh コマンドから、default ネットワークを有効にするようにし、仮想マシン利用時に特別な操作なしに利用できるようにする。\n# /etc/systemd/system/libvirtEnableDefaultNetwork.service [Unit] Description=\u0026#34;Start default network by virsh.\u0026#34; After=libvirtd.service [Service] Type=simple User=root ExecStart=sudo virsh net-start default Restart=on-failure [Install] WantedBy=multi-user.target sudo systemctl enable --now libvirtEnableDefaultNetwork.service systemctl status libvirtEnableDefaultNetwork.service 参考にしたサイトとか systemd.service man ページ（2025年4月2日）\nsystemd man ページ（2025年4月2日）\nsystemd - ArchWiki\nhttps://wiki.archlinux.org/title/Systemd （2025年4月2日）\nCreate a simple systemd service unit file and run a script on boot | Support | SUSE\nhttps://www.suse.com/ja-jp/support/kb/doc/?id=000019672 （2025年4月2日）\nsystemd のユニットファイルの作り方 | 晴耕雨読\nhttps://tex2e.github.io/blog/linux/create-my-systemd-service （2025年4月2日）\nSystemd入門(4) - serviceタイプUnitの設定ファイル - めもめも\nhttps://enakai00.hatenablog.com/entry/20130917/1379374797 （2025年4月2日）\nChatGPT\nhttps://chatgpt.com/ (2025年8月23日)\nsystemd/ユーザー - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Systemd/ユーザー (2026年2月28日)\nHow to set environment variable in systemd service? - Server Fault\nhttps://serverfault.com/questions/413397/how-to-set-environment-variable-in-systemd-service (2026年4月2日)\n","permalink":"https://www.nyanmo.info/posts/linux/systemdservicetemplate/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　systemd を使って何かしらスクリプトを実行したい（例えば、自動的にネットワークドライブをマウントする）ときとかあるのですが、そのたびに検索したり過去に書いたスクリプトを漁るのは面倒なので、自分用にメモ書きのテンプレを置くだけです。本当にただの自分用テンプレなので、説明とかは全然していません。\u003c/p\u003e\n\u003ch2 id=\"配置場所\"\u003e配置場所\u003c/h2\u003e\n\u003ch3 id=\"root-で実行したい任意のサービス\"\u003eroot で実行したい任意のサービス\u003c/h3\u003e\n\u003cp\u003e　操作には管理者権限で、\u003ccode\u003esudo systemctl enable [サービス名]\u003c/code\u003eのようにする必要がある。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/etc/systemd/system/\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"ユーザーごとの任意のサービス\"\u003eユーザーごとの任意のサービス\u003c/h3\u003e\n\u003cp\u003e　操作には、\u003ccode\u003esystemctl --user enable [サービス名]\u003c/code\u003eのようにして、\u003ccode\u003e--user\u003c/code\u003eスイッチが必要であり、サービスが保存されているユーザにログインして操作を行う必要がある。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e~/.config/systemd/user/\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"テンプレ\"\u003eテンプレ\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAfter= は必ずしも指定する必要はない。依存するものがなければ、この項目はなくてもいい模様である。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"スクリプトの実行\"\u003eスクリプトの実行\u003c/h3\u003e\n\u003cp\u003e　最小構成だと、Exec周りは、\u003ccode\u003eExecStart\u003c/code\u003eだけでとりあえず動かすことができる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eUnit\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ea systemd service run a script.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eService\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWorkingDirectory\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eType\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003esimple\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eroot\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Group=[GroupName]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Environment=\u0026#34;env=variable\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStartPre\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStartPost\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStopPre\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStop\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStopPost\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRestart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eon-failure\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eInstall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003emulti-user.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"プログラムの常駐\"\u003eプログラムの常駐\u003c/h3\u003e\n\u003cp\u003e　こちらも、最小構成だと、Exec周りは、\u003ccode\u003eExecStart\u003c/code\u003eだけでとりあえず動かすことができる。ただ終了が強制終了になってしまうので注意する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eUnit\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ea systemd service run a script.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eService\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWorkingDirectory\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eType\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eforking\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eroot\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Group=[GroupName]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Environment=\u0026#34;env=variable\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStartPre\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStartPost\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStopPre\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStop\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStopPost\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRestart\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eon-failure\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eInstall\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003emulti-user.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"after-の設定\"\u003eAfter= の設定\u003c/h2\u003e\n\u003cp\u003e　以下のようにして、どのサービスなどのあとにサービスを実行したいか、参考になると思われる。\u003c/p\u003e","title":"Systemd スクリプトを実行するサービスのテンプレート"},{"content":"この記事を作った動機 arch linux をインストールするときに、いちいち忘れたことが出てきては、wiki を見に行くということをしていたので、自分が普段やっている工程をただ書き出そうというだけです。\nいつもどうり、とにかく動くこと優先なので、ロケーション設定とか、なんかいろいろ抜けてたりする可能性は大いになります。\nISO ファイルのダウンロード Arch Linux - Downloads\nISO ファイルの書き込み linux ここでの、/dev/sda は、USBドライブを意味している。\nsudo dd if=\u0026#34;archlinux-2025.03.01-x86_64.iso\u0026#34; of=/dev/sda status=progress windows Rufus などのツールなど、なんでもいいのでISOファイルを扱うツールをダウンロードして、USBメモリに書き込む。細かいことは今回は省略する。\nUSB メモリから起動 ここは各PCに固有の仕様に依存するので省略する。\nキーボードレイアウト 日本語キーボードのときは、レイアウト設定を変更しないと、後々キーの記号と入力される記号が異なる(US配列と日本語配列の違い)というめんどくさいことになるので、変更しておく。\nloadkeys jp106 wifi につなげる インターネットが必要なので、wifiにつなげる。\u0026quot;[wlan0]\u0026ldquo;のところには、station listで表示される任意の wifi カードを選択する。\niwctl station list station [wlan0] scan station [wlan0] get-networks station [wlan0] connect [targetNetworkName] # パスワードを入力 exit # ping が通ればOK ping google.com ping 8.8.8.8 ディスクの初期化 ディスク構成の確認 以下の例では、SSD と sd カードが刺さっているときの表示例である。今回は、以下の例 (/dev/nvme0n1) とは異なるが、/dev/sda にインストールするという前提で話を進める。\nfdisk -l ディスク /dev/nvme0n1: 1.86 TiB, 2048408248320 バイト, 4000797360 セクタ ディスク型式: SOLIDIGM SSDPFKNU020TZ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: gpt ディスク識別子: 一応秘匿 デバイス 開始位置 終了位置 セクタ サイズ タイプ ディスク /dev/mmcblk0: 28.15 GiB, 30224154624 バイト, 59031552 セクタ 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: dos ディスク識別子: 一応秘匿 デバイス 起動 開始位置 終了位置 セクタ サイズ Id タイプ /dev/mmcblk0p1 8192 59031551 59023360 28.1G c W95 FAT32 (LBA) efi パティーションとメインパティーションの作成 提示されたデフォルト値でいいときはそのまま Enter を押すと、次の設定項目に進める。\n一応、usbメモリで普段やっているパティーション構成を再現するようにして、作業した例を載せておく。ちなみに、スワップ用のパティーションまで作っているが、普段私はインストール完了後に有効化する作業をしているので、ここでは特に、これ以上スワップについて記述することはしない。\nEFI Linux filesystem Linux swap EF00 8300 8200 gdisk /dev/sda GPT fdisk (gdisk) version 1.0.10 Partition table scan: MBR: protective BSD: not present APM: not present GPT: present Found valid GPT with protective MBR; using GPT. Command (? for help): n Partition number (1-248, default 1): First sector (64-60620736, default = 2048) or {+-}size{KMGTP}: Last sector (2048-60620736, default = 60618751) or {+-}size{KMGTP}: 2G Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): EF00 Changed type of partition to \u0026#39;EFI system partition\u0026#39; Command (? for help): n Partition number (2-248, default 2): First sector (64-60620736, default = 4196352) or {+-}size{KMGTP}: Last sector (4196352-60620736, default = 60618751) or {+-}size{KMGTP}: -10G Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): Changed type of partition to \u0026#39;Linux filesystem\u0026#39; Command (? for help): p Disk /dev/sda: 60620800 sectors, 28.9 GiB Model: KUM2 Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 一応秘匿 Partition table holds up to 248 entries Main partition table begins at sector 2 and ends at sector 63 First usable sector is 64, last usable sector is 60620736 Partitions will be aligned on 2048-sector boundaries Total free space is 20975551 sectors (10.0 GiB) Number Start (sector) End (sector) Size Code Name 1 2048 4194304 2.0 GiB EF00 EFI system partition 2 4196352 39649216 16.9 GiB 8300 Linux filesystem Command (? for help): n Partition number (3-248, default 3): First sector (64-60620736, default = 39649280) or {+-}size{KMGTP}: Last sector (39649280-60620736, default = 60618751) or {+-}size{KMGTP}: Current type is 8300 (Linux filesystem) Hex code or GUID (L to show codes, Enter = 8300): 8200 Changed type of partition to \u0026#39;Linux swap\u0026#39; Command (? for help): p Disk /dev/sda: 60620800 sectors, 28.9 GiB Model: KUM2 Sector size (logical/physical): 512/512 bytes Disk identifier (GUID): 一応秘匿 Partition table holds up to 248 entries Main partition table begins at sector 2 and ends at sector 63 First usable sector is 64, last usable sector is 60620736 Partitions will be aligned on 2048-sector boundaries Total free space is 6079 sectors (3.0 MiB) Number Start (sector) End (sector) Size Code Name 1 2048 4194304 2.0 GiB EF00 EFI system partition 2 4196352 39649216 16.9 GiB 8300 Linux filesystem 3 39649280 60618751 10.0 GiB 8200 Linux swap Command (? for help): w Final checks complete. About to write GPT data. THIS WILL OVERWRITE EXISTING PARTITIONS!! Do you want to proceed? (Y/N): Y OK; writing new GUID partition table (GPT) to /dev/sda. The operation has completed successfully. フォーマット mkfs.fat -F 32 /dev/sda1 mkfs.ext4 /dev/sda2 マウントする mount /dev/sda2 /mnt mkdir /mnt/boot mount /dev/sda1 /mnt/boot /etc/fstab を生成する genfstab -U /mnt \u0026gt;\u0026gt; /mnt/etc/fstab fstab なるものを生成しておかないと、後々 /boot が正常にマウントされないというトラブルになるので気をつける。\n最初のうちはなくても実は動いてしまうが、後々 liunx カーネルのアップデートとかがあると、linux kernel 本体と initramfs がアップデートされるときに、UEFI側から見えるパテーションである、/dev/sda1には、古い linux kernel 本体と initramfs がそのまま更新されないままになり、起動時にはそれが読み込まれてしまう。\nこれの何が問題かと言うと、モジュールのバージョンが合わないということが起こり、最悪 linux が立ち上がってこなくなる。起動しても wifi が使えないなどの障害になる。\npacstrap 基本的な環境のインストールを行う。これをしないと、arch-chrootのときに chroot 環境に入ることができない。\npacstrap -K /mnt base linux linux-firmware ブートローダのインストール 今回は、GRUB をブートローダとしてインストールする。正直以下のやり方が正しいかと言われると怪しいが、とりあえず動く。\ngrub-install --efi-directory /mnt/boot --boot-directory /mnt/boot arch-chroot インストールした環境を設定していく。\nchroot 環境に入る arch-chroot /mnt hostname の設定 任意の名前を設定できる。あんまり特殊な名前にはできないと思う。\necho \u0026#34;naynmohusahusa\u0026#34; \u0026gt; /etc/hostname アカウント作成とパスワードの設定 パスワードを設定しないと、あとからこの設定をやり直すことになる。\nroot パスワードの設定 passwd アカウントを作成する # -m でホームディレクトリを作る useradd -m husa # sudo の管理者権限を付与 usermod -aG wheel husa # パスワード設定 passwd husa pacman の設定 multilib を有効化しておく。　よく[multilib]の部分を忘れて、コメントアウトしたままになり、設定が正しく反映されていないままになることがあるので気をつける。\n/etc/pacman.conf 変更前 ... # [multilib] # Include = /etc/pacman.d/mirrorlist ... /etc/pacman.conf 変更後 ... [multilib] Include = /etc/pacman.d/mirrorlist ... アプリケーション群のインストール sudo pacman -Syyu sudo pacman -S gnome neovim firewalld reflector sudo networkmanager noto-fonts-cjk arch-install-scripts sudoers 管理者権限を wheel グループに属性ているユーザに付与する。\n/etc/sudoers 変更前 ... # %wheel ALL=(ALL:ALL) ALL ... /etc/sudoers 変更後 ... %wheel ALL=(ALL:ALL) ALL ... reflector の設定（オプション） /etc/xdg/reflector/reflector.conf ... --country Japan ... 必要なサービスの有効化 sudo systemctl enable gdm NetworkManager firewalld reflector sudo systemctl enable bluetooth # オプション ブートローダの設定を生成 chroot 環境に入る前にインストールした GRUB に対して、設定ファイルを生成する。\nsudo grub-mkconfig -o /boot/grub/grub.cfg タイムゾーンの設定 timedatectl list-timezones timedatectl set-timezone Japan timedatectl status # Local time: Sat 2025-06-21 05:31:02 JST # Universal time: Fri 2025-06-20 20:31:02 UTC # RTC time: Fri 2025-06-20 20:31:02 # Time zone: Japan (JST, +0900) # System clock synchronized: no # NTP service: inactive # RTC in local TZ: no chroot 環境の終了 exit 再起動 ここまでくれば、とりあえず GNOME が立ち上がってくるところまで行けるはずである。\nreboot 補足 arch-keyring がうまく機能しない 最終的な対処法としては、単に pacman 署名確認機能を無効化してアップデートさせて、元に戻すしか今のところ私は対処方法を見つけられていない。本来であれば、このようにして安全装置を外すことは推奨されないが、無理やり進めたいならば、以下のように設定することもできる。\n/etc/pacman.conf # SigLevel = Required DatabaseOptional SigLevel = Never 一旦署名機能を無効化したあとは、keyringをアップデートすることで、とりあえず元どうり署名機能が使えるときもある。でもうまくいかないときもあって、そういうときは、google を彷徨ってたりしばらく時間をおいて、どうしたらいいか考えたりしている。はっきりとどうしたらいいかということは分かっていない。\nsudo pacman -Syyu sudo pacman -S arch-keyring パスワードを設定し忘れた root と作成したアカウントもろともパスワードの設定を忘れると、再起動したときに何もできないということになる。その時はインストールメディアから起動し直して設定を行う。ここでも、ディスクは /dev/sda として見えることを前提に話を進める。\nfdisk で構成を確認 fdisk -l arch linux 本体が入ったパティーションをマウント mount /dev/sda2 /mnt chroot 環境に入る arch-chroot /mnt パスワードを設定 passwd # root ユーザのパスワードを設定 passwd husa # husa という名前のユーザのパスワードを設定 chroot 環境を抜けて再起動 exit reboot genfstab し忘れた arch-install-scripts をインストールすることで、ライブ環境でなくても、genfstabコマンドを使えるようになる。それによって、通常どうり設定を生成すれば良い。\nただライブ環境ではないため、すべてのパティーションがマウントされていることと、fstabを生成するパスの指定先、設定を保存する指定先が異なることに注意する。以下は、fstab を通常起動の環境から生成する例である。\nsu sudo mount /dev/sda1 /boot genfstab -U / \u0026gt; /etc/fstab 関連してそうな記事 yay コマンドのインストール gnomeの設定のメモ ⚙ 参考にしたサイトとか Installation guide - ArchWiki\nhttps://wiki.archlinux.org/title/Installation_guide （2025年4月2日） GRUB - ArchWiki\nhttps://wiki.archlinux.jp/index.php/GRUB （2025年4月2日） GDisk Hex Codes - Ask Ubuntu\nhttps://askubuntu.com/questions/703443/gdisk-hex-codes （2025年4月2日） GPT fdisk - ArchWiki\nhttps://wiki.archlinux.org/title/GPT_fdisk （2025年4月2日） genfstab - ArchWiki\nhttps://wiki.archlinux.org/title/Genfstab (2026年8月4日) Arch Linux - arch-install-scripts 31-1 (any)\nhttps://archlinux.org/packages/extra/any/arch-install-scripts/ (2026年8月4日) ","permalink":"https://www.nyanmo.info/posts/linux/archlinuxinstallaion/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　arch linux をインストールするときに、いちいち忘れたことが出てきては、\u003ca href=\"https://wiki.archlinux.org/title/Installation_guide\"\u003ewiki\u003c/a\u003e を見に行くということをしていたので、自分が普段やっている工程をただ書き出そうというだけです。\u003c/p\u003e\n\u003cp\u003e　いつもどうり、とにかく動くこと優先なので、ロケーション設定とか、なんかいろいろ抜けてたりする可能性は大いになります。\u003c/p\u003e\n\u003ch2 id=\"iso-ファイルのダウンロード\"\u003eISO ファイルのダウンロード\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://archlinux.org/download/\"\u003eArch Linux - Downloads\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"iso-ファイルの書き込み\"\u003eISO ファイルの書き込み\u003c/h2\u003e\n\u003ch3 id=\"linux\"\u003elinux\u003c/h3\u003e\n\u003cp\u003e　ここでの、\u003ccode\u003e/dev/sda\u003c/code\u003e は、USBドライブを意味している。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo dd \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;archlinux-2025.03.01-x86_64.iso\u0026#34;\u003c/span\u003e of\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e/dev/sda status\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eprogress\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"windows\"\u003ewindows\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://rufus.ie/ja/\"\u003eRufus\u003c/a\u003e などのツールなど、なんでもいいのでISOファイルを扱うツールをダウンロードして、USBメモリに書き込む。細かいことは今回は省略する。\u003c/p\u003e\n\u003ch2 id=\"usb-メモリから起動\"\u003eUSB メモリから起動\u003c/h2\u003e\n\u003cp\u003e　ここは各PCに固有の仕様に依存するので省略する。\u003c/p\u003e\n\u003ch2 id=\"キーボードレイアウト\"\u003eキーボードレイアウト\u003c/h2\u003e\n\u003cp\u003e　日本語キーボードのときは、レイアウト設定を変更しないと、後々キーの記号と入力される記号が異なる(US配列と日本語配列の違い)というめんどくさいことになるので、変更しておく。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eloadkeys jp106\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"wifi-につなげる\"\u003ewifi につなげる\u003c/h2\u003e\n\u003cp\u003e　インターネットが必要なので、wifiにつなげる。\u0026quot;[wlan0]\u0026ldquo;のところには、\u003ccode\u003estation list\u003c/code\u003eで表示される任意の wifi カードを選択する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eiwctl \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estation list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estation \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ewlan0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e scan\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estation \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ewlan0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e get-networks\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estation \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ewlan0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e connect \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003etargetNetworkName\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# パスワードを入力\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eexit\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ping が通ればOK\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eping google.com\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eping 8.8.8.8\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"ディスクの初期化\"\u003eディスクの初期化\u003c/h2\u003e\n\u003ch3 id=\"ディスク構成の確認\"\u003eディスク構成の確認\u003c/h3\u003e\n\u003cp\u003e　以下の例では、SSD と sd カードが刺さっているときの表示例である。今回は、以下の例 (\u003ccode\u003e/dev/nvme0n1\u003c/code\u003e) とは異なるが、\u003ccode\u003e/dev/sda\u003c/code\u003e にインストールするという前提で話を進める。\u003c/p\u003e","title":"Arch Linux のインストール (UEFI環境)"},{"content":"この記事を作った動機 blender と MMD Tools 使っていて Morph Tools というのを見つけて、色々モデルをうごすことができることは分かっていた。しかし、値を操作して動かせない Material などの項目がありなぜ動かせないのかしばらく実験していたら、方法が分かったので記録するだけ。\n方法 問題の状態 赤線のところに、値を変更するためのスライダーがなく、Morph をMMDモデルに反映することができない状態が以下である。 Model setup の Morph を押す 解決した状態 参考にしたサイトとか MMD Tools/Manual | MMD \u0026amp; Blender Wiki | Fandom\nhttps://mmd-blender.fandom.com/wiki/MMD_Tools/Manual#Mesh/Armature/Physics/Display/Morphs （2025年3月29日） GitHub - MMD-Blender/blender_mmd_tools: MMD Tools is a blender addon for importing/exporting Models and Motions of MikuMikuDance.\nhttps://github.com/MMD-Blender/blender_mmd_tools （2025年3月29日） ","permalink":"https://www.nyanmo.info/posts/blender/morphtoolswontshowvaluesilder/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　blender と MMD Tools 使っていて Morph Tools というのを見つけて、色々モデルをうごすことができることは分かっていた。しかし、値を操作して動かせない Material などの項目がありなぜ動かせないのかしばらく実験していたら、方法が分かったので記録するだけ。\u003c/p\u003e\n\u003ch2 id=\"方法\"\u003e方法\u003c/h2\u003e\n\u003ch3 id=\"問題の状態\"\u003e問題の状態\u003c/h3\u003e\n\u003cp\u003e　赤線のところに、値を変更するためのスライダーがなく、Morph をMMDモデルに反映することができない状態が以下である。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/morphToolsWontShowValueSilder/%e5%8f%8d%e6%98%a0%e5%89%8d.png#center\"\n         alt=\"反映前\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"model-setup-の-morph-を押す\"\u003eModel setup の Morph を押す\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/morphToolsWontShowValueSilder/Morph%e3%83%9c%e3%82%bf%e3%83%b3%e3%82%92%e6%8a%bc%e3%81%99.png#center\"\n         alt=\"Morphボタンを押す\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"解決した状態\"\u003e解決した状態\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/blender/morphToolsWontShowValueSilder/%e5%8f%8d%e6%98%a0%e5%be%8c.png#center\"\n         alt=\"反映後\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eMMD Tools/Manual | MMD \u0026amp; Blender Wiki | Fandom\u003cbr\u003e\n\u003ca href=\"https://mmd-blender.fandom.com/wiki/MMD_Tools/Manual#Mesh/Armature/Physics/Display/Morphs\"\u003ehttps://mmd-blender.fandom.com/wiki/MMD_Tools/Manual#Mesh/Armature/Physics/Display/Morphs\u003c/a\u003e （2025年3月29日）\u003c/li\u003e\n\u003cli\u003eGitHub - MMD-Blender/blender_mmd_tools: MMD Tools is a blender addon for importing/exporting Models and Motions of MikuMikuDance.\u003cbr\u003e\n\u003ca href=\"https://github.com/MMD-Blender/blender_mmd_tools\"\u003ehttps://github.com/MMD-Blender/blender_mmd_tools\u003c/a\u003e （2025年3月29日）\u003c/li\u003e\n\u003c/ul\u003e","title":"Morph tools でモデルをうまく動かせない"},{"content":"考え 画像に物差しと、大きさを測りたい物体がある時、PC上でいろんな部分の寸法を書き出せるヘルパーツール。例えば、マザーボードの基盤の寸法出しや、BGAフットプリントの作成、フレキシブルケーブルのピッチを調べたりするのに使える。\n基本 flutter とか、Reactとか使ってクロスプラットフォーム向けに構築する。\nカメラで画像を取る 定規のメモリで仮想定規の校正を行う。（校正にはできればジオメトリ情報も使う。端末の傾き具合とか、ものが置かれている平面に対する法線ベクトルから角度を弾き出して歪みを修正するとか。） 二点指定で、直線距離を測る 距離を測った情報の入った画像を保存できる リバースエンジニアリングとまではいかなくても手軽に寸法測定できるだけでも相当大きいと思う。 プラットフォーム Android Windows linux distro IOS? 2025年4月20日出来たこと とりあえず Python と OpenCV で二点間計測とBGA検出のコードをChatGPTに書かせることができた。\n作業ファイル imgProcessing.zip GPU ROMとVBIOSの理解.pdf - ChatGPT Open as a page 元の画像 加工した画像 トーンカーブ 関係ないものを黒で塗りつぶす GIMP 二点間検出の例 BGAピンの検出 (main5.py) マウスで2点間を指定する。押しっぱなしで四角を描く。これに、定規で1ピクセル当たりの何mmかを割り出し、それもCSVに保存しておけば、後はそこから、フットプリントを作成するために校正をかけてみて、印刷してみてサイズがあってるか確認し、最終的にはkicadに落とし込む。 スマホアプリ案 プロジェクトファイルパス このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 画面のイメージ このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） メイン計測画面 画像選択 カメラモード Ref ChatGPT\nhttps://chatgpt.com/ (2025年6月18日) ","permalink":"https://www.nyanmo.info/posts/idea/research/imageruler/","summary":"\u003ch2 id=\"考え\"\u003e考え\u003c/h2\u003e\n\u003cp\u003e　画像に物差しと、大きさを測りたい物体がある時、PC上でいろんな部分の寸法を書き出せるヘルパーツール。例えば、マザーボードの基盤の寸法出しや、BGAフットプリントの作成、フレキシブルケーブルのピッチを調べたりするのに使える。\u003c/p\u003e\n\u003ch2 id=\"基本\"\u003e基本\u003c/h2\u003e\n\u003cp\u003e　flutter とか、Reactとか使ってクロスプラットフォーム向けに構築する。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eカメラで画像を取る\u003c/li\u003e\n\u003cli\u003e定規のメモリで仮想定規の校正を行う。（校正にはできればジオメトリ情報も使う。端末の傾き具合とか、ものが置かれている平面に対する法線ベクトルから角度を弾き出して歪みを修正するとか。）\u003c/li\u003e\n\u003cli\u003e二点指定で、直線距離を測る\u003c/li\u003e\n\u003cli\u003e距離を測った情報の入った画像を保存できる\u003c/li\u003e\n\u003cli\u003eリバースエンジニアリングとまではいかなくても手軽に寸法測定できるだけでも相当大きいと思う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"プラットフォーム\"\u003eプラットフォーム\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAndroid\u003c/li\u003e\n\u003cli\u003eWindows\u003c/li\u003e\n\u003cli\u003elinux distro\u003c/li\u003e\n\u003cli\u003eIOS?\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"2025年4月20日出来たこと\"\u003e2025年4月20日出来たこと\u003c/h2\u003e\n\u003cp\u003e　とりあえず Python と OpenCV で二点間計測とBGA検出のコードをChatGPTに書かせることができた。\u003c/p\u003e\n\u003ch3 id=\"作業ファイル\"\u003e作業ファイル\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca download href=\"/posts/idea/imageRuler/imgProcessing.zip\"\u003e\nimgProcessing.zip\n\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca download href=\"/posts/idea/imageRuler/GPU%20ROM%e3%81%a8VBIOS%e3%81%ae%e7%90%86%e8%a7%a3.pdf\"\u003e\nGPU ROMとVBIOSの理解.pdf - ChatGPT\n\u003c/a\u003e\u003cbr\u003e\n\u003cdiv style=\"display: flex; flex-direction: column; margin-bottom: 20px;\"\u003e\n    \u003ca href='/posts/idea/imageRuler/htmls/GPU%20ROM%e3%81%a8VBIOS%e3%81%ae%e7%90%86%e8%a7%a3.html' target=\"_blank\" style=\"margin: 10px; background: rgb(50, 50, 50); border-radius: 10px; text-align: center;\"\u003eOpen as a page\u003c/a\u003e\n    \u003ciframe src='/posts/idea/imageRuler/htmls/GPU%20ROM%e3%81%a8VBIOS%e3%81%ae%e7%90%86%e8%a7%a3.html' style=\"width: 100%; height: 400px;\"\u003e\u003c/iframe\u003e\n\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"元の画像\"\u003e元の画像\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/imageRuler/%e5%85%83%e7%94%bb%e5%83%8f.webp#center\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"加工した画像\"\u003e加工した画像\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eトーンカーブ\u003c/li\u003e\n\u003cli\u003e関係ないものを黒で塗りつぶす\u003c/li\u003e\n\u003cli\u003eGIMP\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/imageRuler/%e5%8a%a0%e5%b7%a5%e3%81%97%e3%81%9f%e7%94%bb%e5%83%8f.png#center\"/\u003e \n\u003c/figure\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"二点間検出の例\"\u003e二点間検出の例\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/imageRuler/%e4%ba%8c%e7%82%b9%e9%96%93%e8%a8%88%e6%b8%ac.png#center\"/\u003e \n\u003c/figure\u003e\n\n\u003ch3 id=\"bgaピンの検出-main5py\"\u003eBGAピンの検出 (main5.py)\u003c/h3\u003e\n\u003cp\u003e　マウスで2点間を指定する。押しっぱなしで四角を描く。これに、定規で1ピクセル当たりの何mmかを割り出し、それもCSVに保存しておけば、後はそこから、フットプリントを作成するために校正をかけてみて、印刷してみてサイズがあってるか確認し、最終的にはkicadに落とし込む。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/idea/imageRuler/%e6%a4%9c%e5%87%ba%e7%b5%90%e6%9e%9c.png#center\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"スマホアプリ案\"\u003eスマホアプリ案\u003c/h2\u003e\n\u003ch3 id=\"プロジェクトファイルパス\"\u003eプロジェクトファイルパス\u003c/h3\u003e\n\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"画面のイメージ\"\u003e画面のイメージ\u003c/h3\u003e\n\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch4 id=\"メイン計測画面\"\u003eメイン計測画面\u003c/h4\u003e\n\u003ch4 id=\"画像選択\"\u003e画像選択\u003c/h4\u003e\n\u003ch4 id=\"カメラモード\"\u003eカメラモード\u003c/h4\u003e\n\u003ch2 id=\"ref\"\u003eRef\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e (2025年6月18日)\u003c/li\u003e\n\u003c/ul\u003e","title":"仮想定規(Image Ruler)"},{"content":"この記事を作った動機 linux上で、cifsとVPNを使って自分のファイルサーバにアクセスしているのですが、以下のような不満点があり、どうしたらいいか考えてみた結果、いくつか興味深いオプジョンが見つかったので、それを記録しておくだけです。ちなみに、完全な解決とまでは行ってないですが、多少改善が見られた程度って感じです。\n大きなファイルをやり取りすると、同時に他のファイル操作をしたときにもっさりする なにかと、特にvpn環境だと理由不明のファイルマネージャ等のプチフリが多発する ちょっとしたまとめ sudo mount -t cifs -o user=username,password=\u0026#34;password\u0026#34;,gid=1000,uid=1000,vers=3.11,multichannel,max_channels=16,compress //192.168.xxx.xxx/shareName /Path/To/Mount/Point 特に気になったオプション vers=3.11 smbプロトコルのバージョンを指定する項目で、以下のバージョンが選べる模様です。新しいほどいろんな機能が使えるようです。今回の場合は、使いたい機能が、3.11にあるので、それを指定している前提で、その他気になったオプションをリストアップします。\nvers=arg SMB protocol version. Allowed values are: • 1.0 - The classic CIFS/SMBv1 protocol. • 2.0 - The SMBv2.002 protocol. This was initially introduced in Windows Vista Service Pack 1, and Windows Server 2008. Note that the initial release version of Windows Vista spoke a slightly different dialect (2.000) that is not supported. • 2.1 - The SMBv2.1 protocol that was introduced in Microsoft Windows 7 and Windows Server 2008R2. • 3.0 - The SMBv3.0 protocol that was introduced in Microsoft Windows 8 and Windows Server 2012. • 3.02 or 3.0.2 - The SMBv3.0.2 protocol that was introduced in Microsoft Windows 8.1 and Windows Server 2012R2. • 3.1.1 or 3.11 - The SMBv3.1.1 protocol that was introduced in Microsoft Windows 10 and Windows Server 2016. • 3 - The SMBv3.0 protocol version and above. • default - Tries to negotiate the highest SMB2+ version supported by both the client and server. If no dialect is specified on mount vers=default is used. To check Di‐ alect refer to /proc/fs/cifs/DebugData Note too that while this option governs the protocol version used, not all features of each version are available. The default since v4.13.5 is for the client and server to negotiate the highest possible version greater than or equal to 2.1. In kernels prior to v4.13, the default was 1.0. For kernels between v4.13 and v4.13.5 the default is 3.0. multichannel manページを読んでいる限り、一つだけでなく複数のデータをやり取りするための、よくわかってないですが、複数のTCPセッション（複数の通信路）みたいなのを開くっぽいです。これを指定して見ると、大きなファイルを操作していても快適にファイルマネージャとか、レスポンスよくいろんなファイル操作が行える傾向にありました。一つだけの通信路では、やはり厳しいものがあるようです。\nmax_channels=16 multichannelのオプジョンと併用して使う項目です。私は欲張って多ければいいというものでもないと思いますが、とりあえず最大の16にしてみています。こうすると、マウント時にセッション確立に時間がかかるようになるようで、ちょっと遅くなりますが、それ以外においては、特に今のところ問題は感じられていません。\nnote 以下は、私がman mount.cifsにあった説明の中で気になった部分を抜き出したものです。\nfsc Enable local disk caching using FS-Cache for CIFS. This option could be useful to improve performance on a slow link, heavily loaded server and/or network where reading from the disk is faster than reading from the server (over the network). This could also impact the scalability positively as the number of calls to the server are reduced. But, be warned that local caching is not suitable for all workloads, for e.g., read-once type workloads. So, you need to consider carefully the situa‐ tion/workload before using this option. Currently, local disk caching is enabled for CIFS files opened as read-only. NOTE: This feature is available only in the recent kernels that have been built with the kernel config option CONFIG_CIFS_FSCACHE. You also need to have cachefilesd daemon installed and running to make the cache opera‐ tional. compress EXPERIMENTAL FEATURE Enables over-the-wire message compression for SMB 3.1.1 or higher mounts. Mount fails when compress is on and vers is set to a version lower than 3.1.1. vers=arg SMB protocol version. Allowed values are: • 1.0 - The classic CIFS/SMBv1 protocol. • 2.0 - The SMBv2.002 protocol. This was initially introduced in Windows Vista Service Pack 1, and Windows Server 2008. Note that the initial release version of Windows Vista spoke a slightly different dialect (2.000) that is not supported. • 2.1 - The SMBv2.1 protocol that was introduced in Microsoft Windows 7 and Windows Server 2008R2. • 3.0 - The SMBv3.0 protocol that was introduced in Microsoft Windows 8 and Windows Server 2012. • 3.02 or 3.0.2 - The SMBv3.0.2 protocol that was introduced in Microsoft Windows 8.1 and Windows Server 2012R2. • 3.1.1 or 3.11 - The SMBv3.1.1 protocol that was introduced in Microsoft Windows 10 and Windows Server 2016. • 3 - The SMBv3.0 protocol version and above. • default - Tries to negotiate the highest SMB2+ version supported by both the client and server. If no dialect is specified on mount vers=default is used. To check Di‐ alect refer to /proc/fs/cifs/DebugData Note too that while this option governs the protocol version used, not all features of each version are available. The default since v4.13.5 is for the client and server to negotiate the highest possible version greater than or equal to 2.1. In kernels prior to v4.13, the default was 1.0. For kernels between v4.13 and v4.13.5 the default is 3.0. --verbose Print additional debugging information for the mount. Note that this pa‐ rameter must be specified before the -o . For example: mount -t cifs //server/share /mnt --verbose -o user=username max_channels=arg This option is applicable while using multichannel feature. max_channels option allows the user to specify the number of transport connections that should be establised between client and server up to a limit of 16. Using this option implicitly enables the multichannel feature. If max_channels option not specified, multichannel feature defaults to using 2 connections. multichannel This option enables multichannel feature. Multichannel is an SMB3 proto‐ col feature that allows client to establish multiple transport connec‐ tions to an SMB server and bind them into a single authenticated SMB ses‐ sion. This feature enhances fault tolerance and increases throughput by distributing traffic across several connections. With this mount option default is to use two channels if the server supports multichannel. The max_channels parameter can be specified if you desire to use more than two channels. echo_interval=n sets the interval at which echo requests are sent to the server on an idling connection. This setting also affects the time required for a con‐ nection to an unresponsive server to timeout. Here n is the echo interval in seconds. The reconnection happens at twice the value of the echo_in‐ terval set for an unresponsive server. If this option is not given then the default value of 60 seconds is used. The minimum tunable value is 1 second and maximum can go up to 600 seconds. 参考にしたサイトとか mount.cifs の man ページ （2025年3月25日） ","permalink":"https://www.nyanmo.info/posts/linux/cifsmountoptions/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　linux上で、cifsとVPNを使って自分のファイルサーバにアクセスしているのですが、以下のような不満点があり、どうしたらいいか考えてみた結果、いくつか興味深いオプジョンが見つかったので、それを記録しておくだけです。ちなみに、完全な解決とまでは行ってないですが、多少改善が見られた程度って感じです。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e大きなファイルをやり取りすると、同時に他のファイル操作をしたときにもっさりする\u003c/li\u003e\n\u003cli\u003eなにかと、特にvpn環境だと理由不明のファイルマネージャ等のプチフリが多発する\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"ちょっとしたまとめ\"\u003eちょっとしたまとめ\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esudo mount -t cifs -o user=username,password=\u0026#34;password\u0026#34;,gid=1000,uid=1000,vers=3.11,multichannel,max_channels=16,compress //192.168.xxx.xxx/shareName /Path/To/Mount/Point\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"特に気になったオプション\"\u003e特に気になったオプション\u003c/h2\u003e\n\u003ch3 id=\"vers311\"\u003evers=3.11\u003c/h3\u003e\n\u003cp\u003e　smbプロトコルのバージョンを指定する項目で、以下のバージョンが選べる模様です。新しいほどいろんな機能が使えるようです。今回の場合は、使いたい機能が、3.11にあるので、それを指定している前提で、その他気になったオプションをリストアップします。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e     vers=arg\n              SMB protocol version. Allowed values are:\n\n              • 1.0 - The classic CIFS/SMBv1 protocol.\n\n              • 2.0 - The SMBv2.002 protocol. This was initially introduced in  Windows\n                Vista  Service  Pack  1, and Windows Server 2008. Note that the initial\n                release version of Windows Vista spoke  a  slightly  different  dialect\n                (2.000) that is not supported.\n\n              • 2.1  -  The SMBv2.1 protocol that was introduced in Microsoft Windows 7\n                and Windows Server 2008R2.\n\n              • 3.0 - The SMBv3.0 protocol that was introduced in Microsoft  Windows  8\n                and Windows Server 2012.\n\n              • 3.02 or 3.0.2 - The SMBv3.0.2 protocol that was introduced in Microsoft\n                Windows 8.1 and Windows Server 2012R2.\n\n              • 3.1.1 or 3.11 - The SMBv3.1.1 protocol that was introduced in Microsoft\n                Windows 10 and Windows Server 2016.\n\n              • 3 - The SMBv3.0 protocol version and above.\n\n              • default  -  Tries  to  negotiate the highest SMB2+ version supported by\n                both the client and server.\n\n              If no dialect is specified on mount vers=default is used.  To  check  Di‐\n              alect refer to /proc/fs/cifs/DebugData\n\n              Note  too  that  while this option governs the protocol version used, not\n              all features of each version are available.\n\n              The default since v4.13.5 is for the client and server to  negotiate  the\n              highest  possible  version greater than or equal to 2.1. In kernels prior\n              to v4.13, the default was 1.0. For kernels between v4.13 and v4.13.5  the\n              default is 3.0.\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"multichannel\"\u003emultichannel\u003c/h3\u003e\n\u003cp\u003e　manページを読んでいる限り、一つだけでなく複数のデータをやり取りするための、よくわかってないですが、複数のTCPセッション（複数の通信路）みたいなのを開くっぽいです。これを指定して見ると、大きなファイルを操作していても快適にファイルマネージャとか、レスポンスよくいろんなファイル操作が行える傾向にありました。一つだけの通信路では、やはり厳しいものがあるようです。\u003c/p\u003e","title":"CIFS (SMB、Samba)を快適に使いたい"},{"content":"この記事を書いた動機 hugoで書いているとき、以下のようにして、フォルダごとに分けることで、記事を管理しています。それで、それらフォルダ内に、新しく記事をhugo newするときに、デフォルトで生成される記事のテンプレートを異なるものにして、管理できるらしいということがわかったので、メモを自分用に取るだけです。\nやり方 hugo で作業しているルートディレクトリの \u0026ldquo;archetypes\u0026rdquo; というフォルダに、\u0026ldquo;content\u0026rdquo; 配下にあるフォルダ構造を意識して、[フォルダ名].mdのようにして、ファイルを作成し、テンプレートを作る。以下に、フォルダ構造やテンプレートファイルのマークダウンの例を一応乗せることにする。\narchetypes archetypes ├── default.md ├── images.md └── posts.md content content ├── posts └── images posts.md +++ title = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39; date = {{ .Date }} draft = true ShowToc = true +++ images.md +++ title = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39; date = {{ .Date }} draft = true ShowToc = false +++ 補足（2025年5月8日） このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ├── archetypes │ ├── Images │ │ └── MMD.md │ ├── default.md │ ├── posts.md │ └── think.md Leaf bundles hugo new --kind Images/MMD content/Images/MMD/DIYUSI.md archetypes/Images/MMD.md +++ date = \u0026#39;{{ .Date }}\u0026#39; draft = false title = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39; +++ ## data \\{\\{\u0026lt;Images/MMD/Data folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}} ## Images and Videos \\{\\{\u0026lt;Images/MMD/ShowImageAndVideo folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}} https://gohugo.io/content-management/archetypes/#specify-archetype\n関係のありそうなページ 自動化 shortcode 参考にしたサイトとか Archetypes | hugo\nhttps://gohugo.io/content-management/archetypes/#article （2025年3月16日） ","permalink":"https://www.nyanmo.info/posts/hugo/createmarkdownarticletemplate/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　hugoで書いているとき、以下のようにして、フォルダごとに分けることで、記事を管理しています。それで、それらフォルダ内に、新しく記事を\u003ccode\u003ehugo new\u003c/code\u003eするときに、デフォルトで生成される記事のテンプレートを異なるものにして、管理できるらしいということがわかったので、メモを自分用に取るだけです。\u003c/p\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003cp\u003e　hugo で作業しているルートディレクトリの \u0026ldquo;archetypes\u0026rdquo; というフォルダに、\u0026ldquo;content\u0026rdquo; 配下にあるフォルダ構造を意識して、[フォルダ名].mdのようにして、ファイルを作成し、テンプレートを作る。以下に、フォルダ構造やテンプレートファイルのマークダウンの例を一応乗せることにする。\u003c/p\u003e\n\u003ch3 id=\"archetypes\"\u003earchetypes\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003earchetypes\n├── default.md\n├── images.md\n└── posts.md\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"content\"\u003econtent\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003econtent\n├── posts\n└── images\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"postsmd\"\u003eposts.md\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ntitle = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39;\ndate = {{ .Date }}\ndraft = true\nShowToc = true\n+++\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"imagesmd\"\u003eimages.md\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ntitle = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39;\ndate = {{ .Date }}\ndraft = true\nShowToc = false\n+++\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"補足2025年5月8日\"\u003e補足（2025年5月8日）\u003c/h2\u003e\n\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e├── archetypes\n│   ├── Images\n│   │   └── MMD.md\n│   ├── default.md\n│   ├── posts.md\n│   └── think.md\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eLeaf bundles\nhugo new --kind Images/MMD content/Images/MMD/DIYUSI.md\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"archetypesimagesmmdmd\"\u003earchetypes/Images/MMD.md\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ndate = \u0026#39;{{ .Date }}\u0026#39;\ndraft = false\ntitle = \u0026#39;{{ replace .File.ContentBaseName \u0026#34;-\u0026#34; \u0026#34; \u0026#34; | title }}\u0026#39;\n+++\n\n## data\n\\{\\{\u0026lt;Images/MMD/Data folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}}\n\n## Images and Videos\n\\{\\{\u0026lt;Images/MMD/ShowImageAndVideo folder=\u0026#34;\\{\\{.File.ContentBaseName}}\u0026#34;\u0026gt;}}\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ca href=\"https://gohugo.io/content-management/archetypes/#specify-archetype\"\u003ehttps://gohugo.io/content-management/archetypes/#specify-archetype\u003c/a\u003e\u003c/p\u003e","title":"markdown のテンプレートを作る"},{"content":"この記事を書いた動機 結構前から指紋認証機能が linux 上で使えないということがあった。それで、とりあえず以下の2つのパッケージをインストールすることで、センサーを認識して動くところまではやっていた。\nyay -Qs fprint local/fprintd 1.94.5-1 (fprint) D-Bus service to access fingerprint readers local/libfprint 1.94.9-1 (fprint) Library for fingerprint readers その時は、Gnome の設定画面にも登録画面が出てきて、とりあえず登録することはできるようになった。しかし、結局登録した指紋と一致しないと言われ、認証機能が思ったように動かないことに気づき、めんどくさくなってまた問題をしばらく放置していた。\nそして、最近になって、また linux 環境における指紋認証について調べてみたところ、問題の解決には至らなかったが、視覚的にどんな指紋が読み取られているのか確認する方法があることに気づいたので、それを記録してみようというわけです。\n環境 Arch Linux linux kernel 6.13.4-arch1-1 Gnome XPS 13 2in1 (9365) 指紋認証センサー VFS7552 libfprint をコンパイルする libfprint 自体に、指紋認証センサーをテストしたりできるツール群が入っているので、それを使う。もしかするとパッケージマネージャ経由でインストールできたりするかもしれないが、GitHub - iafilatov/libfprint: libfrpint driver for a family of Elantech fingerprint sensorsに合わせて、今回は自前でコンパイルすることにした。\nちなみに、このgitリポジトリ 自体は古く、VFS7552 を検出しなかったので、現行のlibfprint / libfprint · GitLabを後にコンパイルし直した。\n一応大まかなポイントだけ、ここには記録しておこうと思う。\nツールをいれる gimp # .pgm な画像を表示するために必要 ninja git python libglib2.0-dev libnss3-dev libpixman-1-dev libusb-1.0.0-dev libx11-dev libxv-dev pkg-config リポジトリのクローン mkdir ~/working cd ~/working git clone https://gitlab.freedesktop.org/libfprint/libfprint.git python 仮想環境の構築 # もし、anaconda が入っている場合は、事前に無効化しておく # conda deactivate python3 -m venv venv . venv/bin/activate pip install -U pip pip install meson \u0026ldquo;ModuleNotFoundError: No module named \u0026lsquo;distutils.util\u0026rsquo;\u0026rdquo; と言われてしまう場合は、以下のモジュールもインストールしていおく。\npip install setuptools コンパイルする venv/bin/meson builddir_dbg venv/bin/meson configure builddir_dbg -Ddebug_log=true cd builddir_dbg ninja コンパイル後 examples という名前のフォルダに、img-capture というプログラムがあれば、準備完了である。\n# ~/working/libfprint/builddir_dbg/examples ls ⠀clear-storage* ⠀cpp-test.p/ ⠀finger.pgm ⠀img-capture* ⠀manage-prints.p/ ⠀clear-storage.p/ ⠀enroll* ⠀identify* ⠀img-capture.p/ ⠀verify* ⠀cpp-test* ⠀enroll.p/ ⠀identify.p/ ⠀manage-prints* ⠀verify.p/ ls img-capture ⠀img-capture* ./img-capture 視覚的に指紋を見てみる このページには、一応個人情報ということで、指紋の画像を乗せることはしない。一応、スワイプしたときと、そうしなかったときの2通りについて、img-capture を実行し、生成される finger.pgm の中身を画像として見てみるということを、何回か試してみた。\nスワイプしたときは、ろくな指紋画像を得ることはできなかった。指紋画像の一部だけ指紋が写り、残り7割程度の領域がまっさらになってしまった。ちなみに、生成された指紋画像のサイズは、224x224であり、タッチして指紋を読み取ったときと指紋画像の大きさが変わることもなかった。\nスワイプしなかったときは、一見するとぼやけたりしていないという意味で、何も問題なさそうな鮮明な指紋画像が得られた。全体的に指紋画像が埋め尽くされており、ブランクは1割程度に満たないくらいしかなかった。\nただ、指の指紋全体というより、指の指紋のほんの一部の領域だけが、読み取られている感じなっており、そこが気になった。\n結局のところ、確かにとにかく指紋認証センサー VFS7552 は壊れているわけでもなければ、ドライバが機能していないというわけでもない、ということは確認できた。\n以後は、今までの経緯を適当に記録 以降は、直接指紋認証の視覚化の話とは関係がないが、指紋認証がうまくいかないということについて、調べたこととか、適当に記録していこうと思います。\nどんな指紋認証センサーがついている？ 指紋認証センサーは基本的にUSB経由でつながっているっぽいので、lsplug で調べてみると以下のようになる。\u0026ldquo;VFS7552 Touch Fingerprint Sensor\u0026quot;と出てくる。\n# yay -S lsplug lsplug USB 1-2 [8087:0a2b] Intel Corp. Bluetooth wireless interface USB 1-7 [138a:0091] Validity Sensors, Inc. VFS7552 Touch Fingerprint Sensor [4d2d94863514] USB 1-9 [0bda:58c8] Realtek Semiconductor Corp. Integrated Webcam HD [200901010001] 登録はできるが、認証は失敗する まず、Gnome 標準の設定画面から試してみると、とりあえず以下のように指紋を登録することはできる。 そして、ログイン画面にも、指紋認証ができる旨が表示される。しかし、何度やっても通らない。。。。 そこで、コマンドライン経由で、指紋認証を試みてみるも、\u0026ldquo;verify-no-match (done)\u0026ldquo;と言われ、これもだめだった。\n# 登録はできる sudo fprintd-enroll [sudo] username のパスワード: Using device /net/reactivated/Fprint/Device/0 Enrolling right-index-finger finger. Enroll result: enroll-stage-passed Enroll result: enroll-stage-passed Enroll result: enroll-stage-passed Enroll result: enroll-stage-passed Enroll result: enroll-stage-passed Enroll result: enroll-completed # 認証は失敗する fprintd-verify main Using device /net/reactivated/Fprint/Device/0 Listing enrolled fingers: - #0: right-index-finger Verify started! Verifying: right-index-finger Verify result: verify-no-match (done) ちなみに、fprintd は動いており、なんかエラーを吐いている。詳しいことは今のところわかっていない。\nsystemctl status fprintd ● fprintd.service - Fingerprint Authentication Daemon Loaded: loaded (/usr/lib/systemd/system/fprintd.service; static) Active: active (running) since Fri 2025-03-14 10:35:22 JST; 7min ago Invocation: aa0078b3ce1c4ebc8611892e7bbf9b4b Docs: man:fprintd(1) Main PID: 51816 (fprintd) Tasks: 6 (limit: 629145) Memory: 9M (peak: 10M) CPU: 1min 9.152s CGroup: /system.slice/fprintd.service └─51816 /usr/lib/fprintd 3月 14 10:36:15 hostname fprintd[51816]: Driver reported session error, but device is inactive. 3月 14 10:36:15 hostname fprintd[51816]: fpi_device_action_error: assertion \u0026#39;priv-\u0026gt;current_action != FPI_DEVICE_ACTION_NONE\u0026#39; failed 3月 14 10:39:03 hostname fprintd[51816]: Deactivating image device while it is not idle, this should not happen. 3月 14 10:39:03 hostname fprintd[51816]: Failed to capture data 3月 14 10:39:03 hostname fprintd[51816]: Driver reported session error, but device is inactive. 3月 14 10:39:03 hostname fprintd[51816]: Translating to activation failure! 3月 14 10:39:03 hostname fprintd[51816]: fpi_image_device_activate_complete: assertion \u0026#39;priv-\u0026gt;state == FPI_IMAGE_DEVICE_STATE_ACTIVATING\u0026#39; failed 3月 14 10:40:04 hostname fprintd[51816]: Deactivating image device while it is not idle, this should not happen. 3月 14 10:40:04 hostname fprintd[51816]: Driver reported session error, but device is inactive. 3月 14 10:40:04 hostname fprintd[51816]: fpi_device_action_error: assertion \u0026#39;priv-\u0026gt;current_action != FPI_DEVICE_ACTION_NONE\u0026#39; failed タッチじゃなくてスワイプしないといけない？ VFS7552 の指紋認証機能が機能しないと、適当にgoogleを漁ったりしていたところ、GitHub - iafilatov/libfprint: libfrpint driver for a family of Elantech fingerprint sensorsのページに以下のような記述があった。\ncommon-problems The algorithm which libfprint uses to match fingerprints doesn\u0026rsquo;t like small images like the ones these drivers produce.\n\u0026hellip;\nTo get bigger images the driver expects you to swipe the finger over the reader.\n\u0026hellip;\n「センサー次第では、生成する指紋画像の大きさが小さすぎて、 libfprint の認証がうまくできないことがある。スワイプすれば、大きな指紋画像が得られて、認証がうまく通るようになる。」ということっぽい。\nただ、結局のところ、「視覚的に指紋を見てみる 」でも書いたように、スワイプしてもうまくいかなかった。Windows 11 のときはそもそも、何も設定しなくても標準でドライバが入ってたし、スワイプなんてしなくても動いていたので、今回の場合はなんか別のところに理由がありそうである。\n参考にしたサイトとか GitHub - iafilatov/libfprint: libfrpint driver for a family of Elantech fingerprint sensors\nhttps://github.com/iafilatov/libfprint?tab=readme-ov-file#common-problems （2025年3月14日） libfprint / libfprint · GitLab https://gitlab.freedesktop.org/libfprint/libfprint （2025年3月14日） python - No module named \u0026lsquo;distutils.util\u0026rsquo; \u0026hellip;but distutils is installed? - Stack Overflow\nhttps://stackoverflow.com/questions/69919970/no-module-named-distutils-util-but-distutils-is-installed （2025年3月14日） 第786回　Ubuntuでもあこがれの指紋認証を！ | gihyo.jp\nhttps://gihyo.jp/admin/serial/01/ubuntu-recipe/0786 （2025年3月14日） 指紋認証デバイスがlinuxで使えなかった件｜南の島のはまこじき\nhttps://note.com/bbp3110/n/ne32392a22c6e （2025年3月14日） fprint - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Fprint （2025年3月14日） Fingerprint question (VFS7552) : r/Ubuntu\nhttps://www.reddit.com/r/Ubuntu/comments/rh2p5t/fingerprint_question_vfs7552/?rdt=52764 （2025年3月14日） XPS 13 - Fingerprint reader Linux support | DELL Technologies\nhttps://www.dell.com/community/en/conversations/linux-general/xps-13-fingerprint-reader-linux-support/647f6e5ff4ccf8a8debb9ba1?commentId=647f978ff4ccf8a8dea92d0b （2025年3月14日） ","permalink":"https://www.nyanmo.info/posts/linux/fingerprintwontwork/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　結構前から指紋認証機能が linux 上で使えないということがあった。それで、とりあえず以下の2つのパッケージをインストールすることで、センサーを認識して動くところまではやっていた。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eyay -Qs fprint\nlocal/fprintd 1.94.5-1 (fprint)\n    D-Bus service to access fingerprint readers\nlocal/libfprint 1.94.9-1 (fprint)\n    Library for fingerprint readers\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e　その時は、Gnome の設定画面にも登録画面が出てきて、とりあえず登録することはできるようになった。しかし、結局登録した指紋と一致しないと言われ、認証機能が思ったように動かないことに気づき、めんどくさくなってまた問題をしばらく放置していた。\u003c/p\u003e\n\u003cp\u003e　そして、最近になって、また linux 環境における指紋認証について調べてみたところ、問題の解決には至らなかったが、視覚的にどんな指紋が読み取られているのか確認する方法があることに気づいたので、それを記録してみようというわけです。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eArch Linux\u003c/li\u003e\n\u003cli\u003elinux kernel 6.13.4-arch1-1\u003c/li\u003e\n\u003cli\u003eGnome\u003c/li\u003e\n\u003cli\u003eXPS 13 2in1 (9365)\u003c/li\u003e\n\u003cli\u003e指紋認証センサー VFS7552\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"libfprint-をコンパイルする\"\u003elibfprint をコンパイルする\u003c/h2\u003e\n\u003cp\u003e　libfprint 自体に、指紋認証センサーをテストしたりできるツール群が入っているので、それを使う。もしかするとパッケージマネージャ経由でインストールできたりするかもしれないが、\u003ca href=\"https://github.com/iafilatov/libfprint?tab=readme-ov-file#getting-code-and-build-tools\"\u003eGitHub - iafilatov/libfprint: libfrpint driver for a family of Elantech fingerprint sensors\u003c/a\u003eに合わせて、今回は自前でコンパイルすることにした。\u003c/p\u003e\n\u003cp\u003e　ちなみに、\u003ca href=\"https://github.com/iafilatov/libfprint?tab=readme-ov-file\"\u003eこのgitリポジトリ\u003c/a\u003e 自体は古く、VFS7552 を検出しなかったので、現行の\u003ca href=\"https://gitlab.freedesktop.org/libfprint/libfprint\"\u003elibfprint / libfprint · GitLab\u003c/a\u003eを後にコンパイルし直した。\u003c/p\u003e\n\u003cp\u003e　一応大まかなポイントだけ、ここには記録しておこうと思う。\u003c/p\u003e\n\u003ch3 id=\"ツールをいれる\"\u003eツールをいれる\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003egimp  # .pgm な画像を表示するために必要\u003c/li\u003e\n\u003cli\u003eninja\u003c/li\u003e\n\u003cli\u003egit\u003c/li\u003e\n\u003cli\u003epython\u003c/li\u003e\n\u003cli\u003elibglib2.0-dev\u003c/li\u003e\n\u003cli\u003elibnss3-dev\u003c/li\u003e\n\u003cli\u003elibpixman-1-dev\u003c/li\u003e\n\u003cli\u003elibusb-1.0.0-dev\u003c/li\u003e\n\u003cli\u003elibx11-dev\u003c/li\u003e\n\u003cli\u003elibxv-dev\u003c/li\u003e\n\u003cli\u003epkg-config\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"リポジトリのクローン\"\u003eリポジトリのクローン\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir ~/working\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/working\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://gitlab.freedesktop.org/libfprint/libfprint.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"python-仮想環境の構築\"\u003epython 仮想環境の構築\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# もし、anaconda が入っている場合は、事前に無効化しておく\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# conda deactivate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epython3 -m venv venv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e. venv/bin/activate\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install -U pip\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip install meson\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　\u0026ldquo;ModuleNotFoundError: No module named \u0026lsquo;distutils.util\u0026rsquo;\u0026rdquo; と言われてしまう場合は、以下のモジュールもインストールしていおく。\u003c/p\u003e","title":"linux 環境で指紋認証ができない"},{"content":"この記事を書いた動機 単に、リポジトリを作るところまではうまく行っていたのですが、リポジトリをクローンするときに、ユーザ名の指定をわかっておらず、ずっと以下のように間違った\u0026quot;git\u0026quot;というユーザを指定し続けていてなかなか気づけなかったということがあったのでメモすることにしました。\ngit clone git@[serveradress]:/Path/To/Target/Proejct/Root/Folder ちなみに、間違ったユーザを指定していると、ssh接続できないので、ずっと\u0026quot;Permission denied (publickey).\u0026ldquo;と言われ続けます。。。最初はなんでssh コマンド経由でつながるのに、gitではうまくいかないのかみたいになっていましたが、結局のところ間違ったユーザを意図せず指定し続けていただけなのでした。。。\nリポジトリを作る cd /Path/To/Target/Proejct/Root/Folder git init --bare リポジトリをクローン git clone [username]@[serveradress]:/Path/To/Target/Proejct/Root/Folder 参考にしたサイトとか debugging - How can I debug git/git-shell related problems? - Stack Overflow\nhttps://stackoverflow.com/questions/6178401/how-can-i-debug-git-git-shell-related-problems （2025年3月10日） Git - Setting Up the Server\nhttps://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server （2025年3月10日） Why doesn\u0026rsquo;t my SSH key work for connecting to github? - Stack Overflow\nhttps://stackoverflow.com/questions/9960897/why-doesnt-my-ssh-key-work-for-connecting-to-github （2025年3月10日） ChatGPT\nhttps://chatgpt.com/ （2025年3月10日） ","permalink":"https://www.nyanmo.info/posts/linux/gitsshconfig/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　単に、リポジトリを作るところまではうまく行っていたのですが、リポジトリをクローンするときに、ユーザ名の指定をわかっておらず、ずっと以下のように間違った\u0026quot;git\u0026quot;というユーザを指定し続けていてなかなか気づけなかったということがあったのでメモすることにしました。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone git@\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eserveradress\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e:/Path/To/Target/Proejct/Root/Folder\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　ちなみに、間違ったユーザを指定していると、ssh接続できないので、ずっと\u0026quot;Permission denied (publickey).\u0026ldquo;と言われ続けます。。。最初はなんでssh コマンド経由でつながるのに、gitではうまくいかないのかみたいになっていましたが、結局のところ間違ったユーザを意図せず指定し続けていただけなのでした。。。\u003c/p\u003e\n\u003ch2 id=\"リポジトリを作る\"\u003eリポジトリを作る\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /Path/To/Target/Proejct/Root/Folder\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit init --bare\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"リポジトリをクローン\"\u003eリポジトリをクローン\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eusername\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e@\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eserveradress\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e:/Path/To/Target/Proejct/Root/Folder\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003edebugging - How can I debug git/git-shell related problems? - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/6178401/how-can-i-debug-git-git-shell-related-problems\"\u003ehttps://stackoverflow.com/questions/6178401/how-can-i-debug-git-git-shell-related-problems\u003c/a\u003e （2025年3月10日）\u003c/li\u003e\n\u003cli\u003eGit - Setting Up the Server\u003cbr\u003e\n\u003ca href=\"https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server\"\u003ehttps://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server\u003c/a\u003e （2025年3月10日）\u003c/li\u003e\n\u003cli\u003eWhy doesn\u0026rsquo;t my SSH key work for connecting to github? - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/9960897/why-doesnt-my-ssh-key-work-for-connecting-to-github\"\u003ehttps://stackoverflow.com/questions/9960897/why-doesnt-my-ssh-key-work-for-connecting-to-github\u003c/a\u003e （2025年3月10日）\u003c/li\u003e\n\u003cli\u003eChatGPT\u003cbr\u003e\n\u003ca href=\"https://chatgpt.com/\"\u003ehttps://chatgpt.com/\u003c/a\u003e （2025年3月10日）\u003c/li\u003e\n\u003c/ul\u003e","title":"ssh 経由でクローンできる git リポジトリを作るメモ"},{"content":"この記事を書いた動機 普段私は、Microsoftが押し付けてくるセットアップ画面が嫌いなので、コマンド経由で直接アカウントを作り、OOBEを回避している。それでそのことも、コマンドライン経由で windows をインストールするの記事を書くついでに、記録することにした次第です。 きれいにやりたい人向け なんか地味に Windows のシステムが壊れるのが嫌いな人向けに以下の記事に書いた方法を推奨する。\nOOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法) コマンドプロンプトを開く Shift + F10 アカウントの作成 今回は例として、\u0026ldquo;main\u0026quot;という名前のアカウントを作り、\u0026ldquo;password\u0026quot;というパスワードを設定する。ちなみにここで管理者権限をmainというアカウントに付与している。これをしないと、管理者権限が得られないということになりかねないので、気をつける。最悪、Windows を再インストールしたり、パスワードを無理やりこじ開けることになる。\nnet user main /add net user main password net localgroup Administrators main /add REM \u0026#34;net user\u0026#34; とだけ打って、コマンドを実行すると現在存在しているユーザを確認できる。 一応、管理者権限をどうあがいても使うことができないということを回避するために、普段私は、Administratorという、もとから管理者権限を持っているアカウントがwindowsでは標準で隠されているので、それも使える様に設定する。用が済んだら無効化することを推奨します。\n有効化 net user Administrator /active:yes 無効化 net user Administrator /active:no OOBE をスキップ 管理者権限を持っているアカウントを作成したことを確認してから、OOBEを終わらせる操作をする。\u0026ldquo;C:\\Windows\\System32\u0026rdquo; 配下にいることを想定する。\nREM cd C:\\Windows\\System32 cd OOBE msoobe.exe bypassnro この時点で、以下の画面で永久に強制的に再起動するまで、セットアップが進まなくなるので、しばらく待ってから強制的に再起動する。あまり早とちりしすぎると、またもとのOOBEの画面に戻されるので注意する。もとのOOBEの画面に戻されたときは、再度OOBEを終わらせる操作をやり直す。 アカウントにログイン 今回は、Administrator アカウントも有効にしていてかつパスワードをそのアカウントに対して設定していないため、、まずはそちらの方へ自動ログインされる。\nそうすると以下のアカウント初回ログインのセットアップが出てくるので、適当に設定して終わらせる。するとデスクトップ画面が出て、とりあえずWindowsのインストールが成功し、起動するようになったことが確認できる。\nちなみになぜか今回は、Administratorアカウントではなく、defaultuser0という、windowsをインストールしたときの初回起動時とかに存在しているアカウントに自動ログインされていた。理由はよくわからないが、ともかく一旦サインアウトして、今回作ったもとのアカウントに戻る。 以下は、作ったアカウントにログインしたときの画像です。\n(Username: main, Password:password) defaultuser0 を削除 defaultuser0というアカウントは、Windowsセットアップ時に存在しているアカウントであるが、通常利用ではいらないので、削除する。コマンドプロンプトの起動では、管理者権限を付与しておく必要がある。\nnet user defaultuser0 /del defaultuser0アカウント削除前 defaultuser0アカウント削除後 Administrator アカウントの無効化 必要がなければ、Administrator アカウントも無効化する。この場合も、コマンドプロンプトの起動では、管理者権限を付与しておく必要がある。\nnet user Administrator /active:no Administrator と defaultuser0 を無効化したあとの様子 終わり 追記 (2026/2/16) C:\\Windows\\System32\\oobe\\msoobe.exe bypassnroが Win 11 25H2でも動作することを確認した。\n追記 (2026/9/11) ミンゲイインターネット で他人のブログ記事を漁っていたところ、この記事で書いている方法が機能しない可能性があることを以下の記事より確認した。自分の環境でも最新の ISO をダウンロードして試してみたいと画策している。\nWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\nhttps://w1.zawa-lab.net/p/20260728_oobe_bypass/ (2026年9月11日) 追記 (2026/9/12) 現時点で公式からダウンロードできる ISO においては、bypassnro はまだ利用できることを確認した。\nOOBE（Windowsのセットアップ画面） をスキップする-1 OOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法) 関連のありそうな記事 コマンドライン経由で windows をインストールする パスワードを無期限で利用できるようにする 参考にしたサイトとか Topic: Windows 11 – OOBE skip internet check @ AskWoody\nhttps://www.askwoody.com/forums/topic/windows-11-oobe-skip-internet-check/ （2025年3月5日）\nSet up Windows 11 without internet - oobe\\bypassnro - Microsoft Community\nhttps://answers.microsoft.com/en-us/insider/forum/all/set-up-windows-11-without-internet-oobebypassnro/4fc44554-b416-4ecb-8961-6f79fd55ae0f （2025年3月5日）\nアカウント 管理者権限 付与したい - Microsoft コミュニティ\nhttps://answers.microsoft.com/ja-jp/windows/forum/all/アカウント/a949e03b-ba85-43ea-acc1-029dea21349a （2025年3月5日）\nEnderman - YouTube\nhttps://www.youtube.com/@Endermanch （2025年3月5日）\nWindows 11 でローカルアカウントを作成する方法【2026年7月時点】\nhttps://w1.zawa-lab.net/p/20260728_oobe_bypass/ (2026年9月11日)\nミンゲイインターネット\nhttps://mingeiinter.net/ (2026年9月11日)\nUUP dump\nhttps://uupdump.net/ (2026年9月12日)\nHow to download Windows 11 26H2 ISO file (preview) - Pureinfotech\nhttps://pureinfotech.com/download-windows-11-26h2-iso/ (2026年9月12日)\nHow to download Tiny11 ISO for Windows 11 26H2 - Pureinfotech\nhttps://pureinfotech.com/download-tiny11-iso-windows-11-26h2/ (2026年9月12日)\nDownload Windows 11\nhttps://www.microsoft.com/en-us/software-download/windows11 (2026年9月12日)\n","permalink":"https://www.nyanmo.info/posts/windows/skipoobe/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　普段私は、Microsoftが押し付けてくるセットアップ画面が嫌いなので、コマンド経由で直接アカウントを作り、OOBEを回避している。それでそのことも、\u003ca href=\"https://www.nyanmo.info/posts/windows/installviacommand/\"\u003eコマンドライン経由で windows をインストールする\u003c/a\u003eの記事を書くついでに、記録することにした次第です。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e9%96%8b%e3%81%8f%e5%89%8d.png#center\"\n         alt=\"問題のセットアップ画面\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"きれいにやりたい人向け\"\u003eきれいにやりたい人向け\u003c/h2\u003e\n\u003cp\u003e　なんか地味に Windows のシステムが壊れるのが嫌いな人向けに以下の記事に書いた方法を推奨する。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/windows/skipoobe2/\"\u003eOOBE（Windowsのセットアップ画面） をスキップする-2 (sysprepを使う方法)\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"コマンドプロンプトを開く\"\u003eコマンドプロンプトを開く\u003c/h2\u003e\n\u003cp\u003eShift + F10\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e9%96%8b%e3%81%8f%e5%89%8d.png#center\"\n             alt=\"コマンドプロンプトを開く前\"/\u003e \n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e9%96%8b%e3%81%84%e3%81%9f%e3%81%82%e3%81%a8.png#center\"\n             alt=\"コマンドプロンプトを開いたあと\"/\u003e \n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"アカウントの作成\"\u003eアカウントの作成\u003c/h2\u003e\n\u003cp\u003e　今回は例として、\u0026ldquo;main\u0026quot;という名前のアカウントを作り、\u0026ldquo;password\u0026quot;というパスワードを設定する。ちなみにここで管理者権限をmainというアカウントに付与している。これをしないと、管理者権限が得られないということになりかねないので、気をつける。最悪、Windows を再インストールしたり、パスワードを無理やりこじ開けることになる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet user main /add\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet user main password\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet localgroup Administrators main /add\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM \u0026#34;net user\u0026#34; とだけ打って、コマンドを実行すると現在存在しているユーザを確認できる。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/%e3%82%a2%e3%82%ab%e3%82%a6%e3%83%b3%e3%83%88%e3%81%ae%e4%bd%9c%e6%88%90.png#center\"\n         alt=\"アカウントの作成\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　一応、管理者権限をどうあがいても使うことができないということを回避するために、普段私は、Administratorという、もとから管理者権限を持っているアカウントがwindowsでは標準で隠されているので、それも使える様に設定する。用が済んだら無効化することを推奨します。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e有効化\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet user Administrator /active:yes\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e無効化\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enet user Administrator /active:no\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/Administrator%e3%82%a2%e3%82%ab%e3%82%a6%e3%83%b3%e3%83%88%e3%82%92%e6%9c%89%e5%8a%b9%e5%8c%96.png#center\"\n         alt=\"Administratorアカウントを有効化\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"oobe-をスキップ\"\u003eOOBE をスキップ\u003c/h2\u003e\n\u003cp\u003e　管理者権限を持っているアカウントを作成したことを確認してから、OOBEを終わらせる操作をする。\u0026ldquo;C:\\Windows\\System32\u0026rdquo; 配下にいることを想定する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM cd C:\\Windows\\System32\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ecd\u003c/span\u003e OOBE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emsoobe.exe bypassnro\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　この時点で、以下の画面で永久に強制的に再起動するまで、セットアップが進まなくなるので、\u003cstrong\u003eしばらく待ってから\u003c/strong\u003e強制的に再起動する。あまり早とちりしすぎると、またもとのOOBEの画面に戻されるので注意する。もとのOOBEの画面に戻されたときは、再度OOBEを終わらせる操作をやり直す。\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/windows/skipOOBE/OOBE%e3%82%92%e7%b5%82%e4%ba%86.png#center\"\n         alt=\"OOBEを終了\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch2 id=\"アカウントにログイン\"\u003eアカウントにログイン\u003c/h2\u003e\n\u003cp\u003e　今回は、Administrator アカウントも有効にしていてかつパスワードをそのアカウントに対して設定していないため、、まずはそちらの方へ自動ログインされる。\u003c/p\u003e","title":"OOBE（Windowsのセットアップ画面） をスキップする"},{"content":"この記事を書いた動機 自分用に、ただどうやって windows をコマンド経由でインストールするか記録するだけです。前提として、インストールメディアから windows インストーラが起動しているところからスタートします。\nちなみに、コマンドライン経由で Windows をインストールすると、インストーラの互換性チェックを完全にスキップできる模様です。TPMとかそういうのをレジストリとかでいちいちバイパスする設定とか無しで、動くかどうかはさておき、現状はこの手法でとりあえずインストールできるようです。\nインストール手順 コマンドプロンプトを開く Shift + F10 diskpart でパティーション作成 diskpart list disk sel disk [windowsをインストールするSSDとかを番号で選択] REM 全部データが消えるので注意 clean convert gpt REM uefi で起動するとき読み込まれるパーティションの作成 create part efi size=100 format quick fs=fat32 label=\u0026#34;System\u0026#34; create part msr size=16 REM Windowns が保存されるメインパティーションの作成 create part primary format quick fs=ntfs label=\u0026#34;Windows\u0026#34; REM ドライブレターを割り当て、エクスプローラーなどから見えるようにする 割り当てる文字は重複してたりしなければ何でも良い list part sel part [System パティーションの番号] assign letter P sel part [Windows パティーションの番号] assign letter Q exit dism で Windows をインストールをする windows インストールメディアのドライブレターの確認 開くなどを押して、windows インストールメディア自体がどんなドライブレターでマウントされているか確認する。例えば、今回であれば、\u0026ldquo;D:\u0026quot;としてマウントされていた。どんなやり方でもよいが、私は普段メモ帳のファイルダイアログから確認している。\nnotepad インストールするwindowsのバージョンのインデックスの確認 インデックスを確認するには、以下に示すどちらかを実行すれば良い。例えば今回は、\u0026ldquo;Windows 11 pro\u0026rdquo; をインストールしたいので、インデックスは\u0026quot;3\u0026quot;である。\ndism /get-wiminfo /wimfile:D:\\sources\\install.esd dism /get-wiminfo /wimfile:D:\\sources\\install.wim Windows のインストール 次に、事前にマウントしておいた、Windowsパーティション（Q:\\）にwindowsをインストールする。以下に２つのパターンを示すので、試す。\ndism /apply-image /imagefile:D:\\sources\\install.esd /applydir:Q:\\ /index:3 dism /apply-image /imagefile:D:\\sources\\install.wim /applydir:Q:\\ /index:3 ブートローダをインストールする bcdboot Q:\\Windows /s P: /f ALL 再起動する 単純にもともと最初にインストールメディアを起動したときに表示されるダイアログを閉じる。 終わり いつもどうり待って、見慣れたOOBEにたどり着く。 コマンドのまとめ REM パティーションの準備 diskpart list disk sel disk [windowsをインストールするSSDとかを番号で選択] clean convert gpt create part efi size=100 format quick fs=fat32 label=\u0026#34;System\u0026#34; create part msr size=16 create part primary format quick fs=ntfs label=\u0026#34;Windows\u0026#34; list part sel part [System パティーションの番号] assign letter P sel part [Windows パティーションの番号] assign letter Q exit REM ファイルの展開 dism /get-wiminfo /wimfile:D:\\sources\\install.esd dism /get-wiminfo /wimfile:D:\\sources\\install.wim dism /apply-image /imagefile:D:\\sources\\install.esd /applydir:Q:\\ /index:3 dism /apply-image /imagefile:D:\\sources\\install.wim /applydir:Q:\\ /index:3 REM ブートローダのインストール bcdboot Q:\\Windows /s P: /f ALL 関連のありそうな記事 OOBE（Windowsをインストールしたときなどに出てくる） をスキップする\n参考にしたサイトとか Partition UEFI/GPT HDD Using Diskpart - Windows Enterprise Desktop\nhttps://www.techtarget.com/searchenterprisedesktop/blog/Windows-Enterprise-Desktop/Partition-UEFI-GPT-HDD-Using-Diskpart （2025年3月5日） DISM イメージ管理のコマンド ライン オプション | Microsoft Learn\nhttps://learn.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/dism-image-management-command-line-options-s14?view=windows-11#apply-image （2025年3月5日） How to Repair the EFI Bootloader on a GPT Hard Drive for Windows Operating Systems | Dell US\nhttps://www.dell.com/support/kbdoc/en-us/000124331/how-to-repair-the-efi-bootloader-on-a-gpt-hdd-for-windows-7-8-8-1-and-10-on-your-dell-pc （2025年3月5日） Enderman - YouTube\nhttps://www.youtube.com/@Endermanch （2025年3月5日） Windows 11 On This Classic 15 Year Old MicroPC - YouTube\nhttps://www.youtube.com/watch?v=DsAANDSoDHc (2025年3月5日) ","permalink":"https://www.nyanmo.info/posts/windows/installviacommand/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　自分用に、ただどうやって windows をコマンド経由でインストールするか記録するだけです。前提として、インストールメディアから windows インストーラが起動しているところからスタートします。\u003c/p\u003e\n\u003cp\u003e　ちなみに、コマンドライン経由で Windows をインストールすると、インストーラの互換性チェックを完全にスキップできる模様です。TPMとかそういうのをレジストリとかでいちいちバイパスする設定とか無しで、動くかどうかはさておき、現状はこの手法でとりあえずインストールできるようです。\u003c/p\u003e\n\u003ch2 id=\"インストール手順\"\u003eインストール手順\u003c/h2\u003e\n\u003ch3 id=\"コマンドプロンプトを開く\"\u003eコマンドプロンプトを開く\u003c/h3\u003e\n\u003cp\u003eShift + F10\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/windows/installViaCommand/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e9%96%8b%e3%81%8f%e5%89%8d.png#center\"\n             alt=\"コマンドプロンプトを開く前\"/\u003e \n    \u003c/figure\u003e\n\n    \u003cfigure class=\"align-center \"\u003e\n        \u003cimg loading=\"lazy\" src=\"/posts/windows/installViaCommand/%e3%82%b3%e3%83%9e%e3%83%b3%e3%83%89%e3%83%97%e3%83%ad%e3%83%b3%e3%83%97%e3%83%88%e3%82%92%e9%96%8b%e3%81%84%e3%81%9f%e3%81%82%e3%81%a8.png#center\"\n             alt=\"コマンドプロンプトを開いたあと\"/\u003e \n    \u003c/figure\u003e\n\n\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"diskpart-でパティーション作成\"\u003ediskpart でパティーション作成\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bat\" data-lang=\"bat\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ediskpart\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist disk\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esel disk [windowsをインストールするSSDとかを番号で選択]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM 全部データが消えるので注意\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eclean \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econvert gpt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM uefi で起動するとき読み込まれるパーティションの作成\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecreate part efi size=100 \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat quick fs=fat32 label=\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;System\u0026#34;\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecreate part msr size=16\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM Windowns が保存されるメインパティーションの作成\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecreate part primary \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eformat quick fs=ntfs label=\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Windows\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003eREM ドライブレターを割り当て、エクスプローラーなどから見えるようにする 割り当てる文字は重複してたりしなければ何でも良い\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elist part\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esel part [System パティーションの番号]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eassign letter P\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esel part [Windows パティーションの番号]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eassign letter Q\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexit\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"dism-で-windows-をインストールをする\"\u003edism で Windows をインストールをする\u003c/h3\u003e\n\u003ch4 id=\"windows-インストールメディアのドライブレターの確認\"\u003ewindows インストールメディアのドライブレターの確認\u003c/h4\u003e\n\u003cp\u003e　開くなどを押して、windows インストールメディア自体がどんなドライブレターでマウントされているか確認する。例えば、今回であれば、\u0026ldquo;D:\u0026quot;としてマウントされていた。どんなやり方でもよいが、私は普段メモ帳のファイルダイアログから確認している。\u003c/p\u003e","title":"コマンドライン経由で windows をインストールする"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 注意点 大文字小文字に気をつけること ファイル名であっても、その違いだけですぐ動かなくなる\nテクスチャの追加 テクスチャが正しく認識されていないときは、黒と紫のチェック柄が表示されてしまう。\n言語ファイルの追加 言語ファイルがないと、正しく名前を表示できない\n参考にしたサイト https://jabelarminecraft.blogspot.com/p/minecraft-modding-localization.html https://docs.minecraftforge.net/en/1.12.x/concepts/internationalization/#\n","permalink":"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/addresource/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"注意点\"\u003e注意点\u003c/h2\u003e\n\u003cp\u003e大文字小文字に気をつけること\nファイル名であっても、その違いだけですぐ動かなくなる\u003c/p\u003e\n\u003ch2 id=\"テクスチャの追加\"\u003eテクスチャの追加\u003c/h2\u003e\n\u003cp\u003e　テクスチャが正しく認識されていないときは、黒と紫のチェック柄が表示されてしまう。\u003c/p\u003e\n\u003ch2 id=\"言語ファイルの追加\"\u003e言語ファイルの追加\u003c/h2\u003e\n\u003cp\u003e　言語ファイルがないと、正しく名前を表示できない\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://jabelarminecraft.blogspot.com/p/minecraft-modding-localization.html\"\u003ehttps://jabelarminecraft.blogspot.com/p/minecraft-modding-localization.html\u003c/a\u003e\n\u003ca href=\"https://docs.minecraftforge.net/en/1.12.x/concepts/internationalization/#\"\u003ehttps://docs.minecraftforge.net/en/1.12.x/concepts/internationalization/#\u003c/a\u003e\u003c/p\u003e","title":"リソースを追加する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） Forge 公式サイトからツールをダウンロード gradle の調整 gradle の実行 参考にしたサイト ","permalink":"https://www.nyanmo.info/posts/minecraft/note/1.7.10/createenv/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"forge-公式サイトからツールをダウンロード\"\u003eForge 公式サイトからツールをダウンロード\u003c/h2\u003e\n\u003ch2 id=\"gradle-の調整\"\u003egradle の調整\u003c/h2\u003e\n\u003ch2 id=\"gradle-の実行\"\u003egradle の実行\u003c/h2\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e","title":"MOD 開発環境構築"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ","permalink":"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/additem/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e","title":"アイテムを追加する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ","permalink":"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/addblock/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e","title":"ブロックを追加する"},{"content":" このページは、まだ未完成です。。。 nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html （2024年5月16日） 環境構築 MOD 開発環境構築 基本 ブロックを追加する アイテムを追加する リソースを追加する この記事を書いた動機 自分はマインクラフトのMODについては、ちょっと環境構築してとりあえずサンプルMODが動くところまでやっていたものの、そこから先が今まで何もできていない状態だったので、最近また触り始めました。\nそれで、記録してすぐ参照できる状態にしておきたいと思ったので、記録を残そうというわけです。ちなみのこの記事をリンク集として、適当にまとめていこうかなと思います。\n参考にしたサイトとか ここはリンク集なので特になし\n","permalink":"https://www.nyanmo.info/posts/minecraft/note/1.7.10/modnotelist/","summary":"\u003cdiv class=\"annotationContainer underconstruct\"\u003e\n    \u003cdiv class=\"annotationbanner\"\u003e\n        \u003cimg class=\"underconstructIcon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n        \u003ch2\u003eこのページは、まだ未完成です。。。\u003c/h2\u003e\n        \u003cimg class=\"underconstructYukkuri\" src=\"/icons/yukkuri/未完成を憂慮するゆっくり霊夢.png\"\u003e\n    \u003c/div\u003e\n    \u003cdiv class=\"originExplain\"\u003enicotalk＆キャラ素材配布所  \n        http://www.nicotalk.com/charasozai_kt.html （2024年5月16日）\u003c/div\u003e\n\u003c/div\u003e\n\n\u003ch2 id=\"環境構築\"\u003e環境構築\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/minecraft/note/1.7.10/createenv/\"\u003eMOD 開発環境構築\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"基本\"\u003e基本\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/addblock/\"\u003eブロックを追加する\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/additem/\"\u003eアイテムを追加する\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.nyanmo.info/posts/minecraft/note/1.7.10/basics/addresource/\"\u003eリソースを追加する\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　自分はマインクラフトのMODについては、ちょっと環境構築してとりあえずサンプルMODが動くところまでやっていたものの、そこから先が今まで何もできていない状態だったので、最近また触り始めました。\u003c/p\u003e\n\u003cp\u003e　それで、記録してすぐ参照できる状態にしておきたいと思ったので、記録を残そうというわけです。ちなみのこの記事をリンク集として、適当にまとめていこうかなと思います。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　ここはリンク集なので特になし\u003c/p\u003e","title":"マインクラフト Mod 開発記録 1.7.10"},{"content":"この記事を書いた動機 hugo を使っていて、書いた記事のサムネイルというかトップ画像みたいなのを、記事のリストで表示したかったが、すぐにどうすればいいか見つけられないかったので忘れない内に記録するというだけです。\n今回の場合は、Google 検索とかで適当に調べたり、 Paper Mod 公式サイト では直接どうするのかを見つけることは出来なかったのですが、そこで動いている例を無理やりChrome の開発者ツールで調べて、実際の開発環境側で、themes/PaperMod 配下にあるファイルと一致する記述を見るけることで対応しました。\nPaper Mod 公式サイト の動いている例 うまく動いた例 PaperMod の場合 +++ date = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39; draft = false title = \u0026#39;Windows\u0026#39; weight = 2 [cover] image = \u0026#34;/posts/windows/indexIcon.svg\u0026#34; +++ ... 記事の内容（markdown） ちなみに画像は、staticフォルダ配下においている。\n無理やり見つけた経緯 調査 Paper Mod 公式サイト のトップページにある動いているやるのタグやクラス名を調べる。\n検索 VS code の検索機能で、\u0026lt;article class=\u0026quot; と調べる。以下の様な記述が見つかる。クラス名にentry-headerとあったりするなど、Paper Mod 公式サイト の動いている例と似ている点が見つかる。\nthemes/PaperMod/layouts/_default/list.html ... {{- partial \u0026#34;cover.html\u0026#34; (dict \u0026#34;cxt\u0026#34; . \u0026#34;IsSingle\u0026#34; false \u0026#34;isHidden\u0026#34; $isHidden) }} \u0026lt;header class=\u0026#34;entry-header\u0026#34;\u0026gt; \u0026lt;h2 class=\u0026#34;entry-hint-parent\u0026#34;\u0026gt; ... そして、画像のタグがある部分に該当するのが、cover.htmlというところにありそうなことが分かる。\ncover.html を調べる html で画像を表示するなら、imgタグであろうと推察がつくので、それをもとにコードで検索をかけると以下の様な部分がヒットする。\nthemes/PaperMod/layouts/partials/cover.html ... \u0026lt;img loading=\u0026#34;{{$loading}}\u0026#34; srcset=\u0026#34;{{- range $size := $sizes -}} {{- if (ge $cover.Width $size) -}} {{ printf \u0026#34;%s %s\u0026#34; (($cover.Resize (printf \u0026#34;%sx\u0026#34; $size)).Permalink) (printf \u0026#34;%sw ,\u0026#34; $size) -}} {{ end }} {{- end -}}{{$cover.Permalink }} {{printf \u0026#34;%dw\u0026#34; ($cover.Width)}}\u0026#34; sizes=\u0026#34;(min-width: 768px) 720px, 100vw\u0026#34; src=\u0026#34;{{ $cover.Permalink }}\u0026#34; alt=\u0026#34;{{ $alt }}\u0026#34; width=\u0026#34;{{ $cover.Width }}\u0026#34; height=\u0026#34;{{ $cover.Height }}\u0026#34;\u0026gt; ... \u0026lt;img loading=\u0026#34;{{$loading}}\u0026#34; src=\u0026#34;{{ (path.Join .RelPermalink .Params.cover.image) | absURL }}\u0026#34; alt=\u0026#34;{{ $alt }}\u0026#34;\u0026gt; ... \u0026lt;img loading=\u0026#34;{{$loading}}\u0026#34; src=\u0026#34;{{ (.Params.cover.image) | absURL }}\u0026#34; alt=\u0026#34;{{ $alt }}\u0026#34;\u0026gt; ... 注目した部分 ヒットした部分には、共通して、src のパラメータに、hugoの変数参照用のパスが設定されていることが分かる。\n.Params.cover.image # hugo の変数参照のパスが src に設定されている。 hugo のドキュメントで\u0026quot;.Params\u0026quot;について調べる Hugo | Page Variables のページに、以下の記述を発見する。\nPage-level Params Any other value defined in the front matter in a content file, including taxonomies, will be made available as part of the .Params variable\n--- title: My First Post date: date: 2017-02-20T15:26:23-06:00 categories: [one] tags: [two,three,four] With the above front matter, the tags and categories taxonomies are accessible via the following:\n.Params.tags .Params.categories これで、.Params は、記事の先頭に設定されているパラメータ群にアクセスするために使われることが分かる。つまりは、今回の、.Params.cover.imageは、以下のように書けることが分かった。\nTOML 形式のパラメータを書く例 +++ date = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39; draft = false title = \u0026#39;Windows\u0026#39; weight = 2 [cover] image = \u0026#34;/posts/windows/indexIcon.svg\u0026#34; +++ ... 記事の内容（markdown） うまく動かなかった例 一応最後に、Google検索で調べで出てきたけど、全然動かなかったという例について、ここに置いときます。使うテーマなどによってこれらが機能するかは変わると思うのですが、ある一人のPaperMod利用者として記録を残しておこうと思います。\n+++ date = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39; draft = false title = \u0026#39;Windows\u0026#39; weight = 2 image = \u0026#34;/posts/windows/indexIcon.svg\u0026#34; +++ +++ date = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39; draft = false title = \u0026#39;Windows\u0026#39; weight = 2 image_preview = \u0026#34;/posts/windows/indexIcon.svg\u0026#34; +++ +++ date = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39; draft = false title = \u0026#39;Windows\u0026#39; weight = 2 [header] image = \u0026#34;/posts/windows/indexIcon.svg\u0026#34; +++ 参考にしたサイト r - Include image preview in blogdown (.Rmd yaml header) - Stack Overflow\nhttps://stackoverflow.com/questions/46524561/include-image-preview-in-blogdown-rmd-yaml-header （2025年2月15日） blogdown - How to create an image preview for a post in hugo-academic from .Rmd? - Stack Overflow\nhttps://stackoverflow.com/questions/47371794/how-to-create-an-image-preview-for-a-post-in-hugo-academic-from-rmd （2025年2月15日） Include an image in the post title - support - HUGO\nhttps://discourse.gohugo.io/t/include-an-image-in-the-post-title/50129 （2025年2月15日） [SOLVED] Adding image to every post - support - HUGO\nhttps://discourse.gohugo.io/t/solved-adding-image-to-every-post/14421 （2025年2月15日） Posts | PaperMod\nhttps://adityatelange.github.io/hugo-PaperMod/posts/ （2025年2月15日） Hugo | Page Variables\nhttps://gohugobrasil.netlify.app/variables/page/ （2025年2月15日） ","permalink":"https://www.nyanmo.info/posts/hugo/addposttopimage/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　hugo を使っていて、書いた記事のサムネイルというかトップ画像みたいなのを、記事のリストで表示したかったが、すぐにどうすればいいか見つけられないかったので忘れない内に記録するというだけです。\u003c/p\u003e\n\u003cp\u003e　今回の場合は、Google 検索とかで適当に調べたり、 \u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/\"\u003ePaper Mod 公式サイト\u003c/a\u003e では直接どうするのかを見つけることは出来なかったのですが、そこで動いている例を無理やりChrome の開発者ツールで調べて、実際の開発環境側で、themes/PaperMod 配下にあるファイルと一致する記述を見るけることで対応しました。\u003c/p\u003e\n\u003ch3 id=\"paper-mod-公式サイト-の動いている例\"\u003e\u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/\"\u003ePaper Mod 公式サイト\u003c/a\u003e の動いている例\u003c/h3\u003e\n\u003cfigure\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hugo/addPostTopImage/%e5%8f%82%e8%80%83%e3%81%ab%e3%81%97%e3%81%9f%e9%83%a8%e5%88%86.png\"/\u003e \n\u003c/figure\u003e\n\n\u003ch2 id=\"うまく動いた例\"\u003eうまく動いた例\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003ePaperMod の場合\u003c/li\u003e\n\u003c/ul\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e+++\ndate = \u0026#39;2025-02-15T00:46:54+09:00\u0026#39;\ndraft = false\ntitle = \u0026#39;Windows\u0026#39;\nweight = 2\n\n[cover]\n    image = \u0026#34;/posts/windows/indexIcon.svg\u0026#34;\n+++\n\n... 記事の内容（markdown）\n\u003c/code\u003e\u003c/pre\u003e\u003cfigure\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hugo/addPostTopImage/%e5%ae%9f%e9%9a%9b%e3%81%ab%e5%8b%95%e3%81%8b%e3%81%97%e3%81%9f%e4%be%8b.png\"/\u003e \n\u003c/figure\u003e\n\n\u003cp\u003e　ちなみに画像は、staticフォルダ配下においている。\u003c/p\u003e\n\u003ch2 id=\"無理やり見つけた経緯\"\u003e無理やり見つけた経緯\u003c/h2\u003e\n\u003ch3 id=\"調査\"\u003e調査\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/\"\u003ePaper Mod 公式サイト\u003c/a\u003e のトップページにある動いているやるのタグやクラス名を調べる。\u003cbr\u003e\n\u003cfigure\u003e\n    \u003cimg loading=\"lazy\" src=\"/posts/hugo/addPostTopImage/%e5%8f%82%e8%80%83%e3%81%ab%e3%81%97%e3%81%9f%e9%83%a8%e5%88%86.png\"/\u003e \n\u003c/figure\u003e\n\u003c/p\u003e\n\u003ch3 id=\"検索\"\u003e検索\u003c/h3\u003e\n\u003cp\u003e　VS code の検索機能で、\u003ccode\u003e\u0026lt;article class=\u0026quot;\u003c/code\u003e と調べる。以下の様な記述が見つかる。クラス名に\u003ccode\u003eentry-header\u003c/code\u003eとあったりするなど、\u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/\"\u003ePaper Mod 公式サイト\u003c/a\u003e の動いている例と似ている点が見つかる。\u003c/p\u003e\n\u003ch4 id=\"themespapermodlayouts_defaultlisthtml\"\u003ethemes/PaperMod/layouts/_default/list.html\u003c/h4\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e...\n  {{- partial \u0026#34;cover.html\u0026#34; (dict \u0026#34;cxt\u0026#34; . \u0026#34;IsSingle\u0026#34; false \u0026#34;isHidden\u0026#34; $isHidden) }}\n  \u0026lt;header class=\u0026#34;entry-header\u0026#34;\u0026gt;\n    \u0026lt;h2 class=\u0026#34;entry-hint-parent\u0026#34;\u0026gt;\n...\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e　そして、画像のタグがある部分に該当するのが、\u003ccode\u003ecover.html\u003c/code\u003eというところにありそうなことが分かる。\u003c/p\u003e","title":"記事ごとにトップ画像を表示したい (hugo PaperMod)"},{"content":"この記事を書いた動機 ただ単にせっかく書いたコードを、無下にしてしまうのは勿体ないなと思い、非効率でバグだらけのスパゲッティコードではあるが、まあおいておこうかなと思っただけです。（かつコメントの英語もガバだらけ。。。）\nちなみに、授業の制約上、一つのファイルにまとめざるを得ず、プログラムを分割できなかったのでえげつなく肥大化しています。。。\n使っているライブラリ C標準ライブラリ curses プレイ動画 各画面の説明 スタート画面 終わりの画面 風のすてーじ 雨のすてーじ 晴れの日すてーじ コンパイル makefile build: gcc main.c -lcurses -lm -o main bash 上の操作 make build ./main # 実行 コード本体 main.c #include \u0026lt;curses.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;math.h\u0026gt; #include \u0026lt;time.h\u0026gt; #include \u0026lt;unistd.h\u0026gt; #include \u0026lt;string.h\u0026gt; #define START_BUTTON 0 #define END_BUTTON 1 #define RETURN_BUTTON 2 #define CURSOR \u0026#34;====================\u0026#34; #define CORSOR_REMOVE \u0026#34; \u0026#34; // define const values for each stage #define RAIN_STAGE 0 #define WIND_STAGE 1 #define SUNNY_STAGE 2 // rain stage setting #define RAIN_SIZE_X 2 // set size of a rain #define RAIN_SIZE_Y 2 // set size of a rain #define RAIN_Y_SPACE 10 // avoid rain creation if there are created rain near the new rain #define RAIN_X_SPACE 3 // avoid rain creation if there are created rain near the new rain #define NUMEBR_OF_RAIN 5 // number of newly created rain in 1 sec #define SPEED_OF_RAIN 30 // in a sec #define DAMAGE_OF_RAIN 10 // amount of damage when player hit a rain #define NUMBER_OF_RETRY 20 // define how many times to recreate random nums #define RAIN_STAGE_POSSIBLE 30 // possibily of rain stage to be selected #define RAIN_STAGE_TIME_LIMIT 20 #define AMOUNT_OF_RAIN 28 // limit amount of rain // wind stage setting #define DAMAGE_OF_OBJ 20 // amount of damage when player hit a obj in this stage #define NUMEBR_OF_BLOWN_AWAY_OBJ 5 // number of obj to be created in a sec #define SPEED_OF_WIND_X 1 // numberOfFrame % this const value -\u0026gt; 100f in a sec #define MOVEMENT_OF_OBJ_X 5 // amount of movement in one position update #define SPEED_OF_WIND_Y 20 // amount of movement in a sec #define AMOUNT_OF_OBJ 28 // limit amount of obj #define WIND_STAGE_POSSIBLE 30 // possibily of wind stage to be selected #define WIND_STAGE_TIME_LIMIT 20 // sunny stage setting #define AMOUNT_OF_RACOVER 10 // amount of hp recover when player hit point obj #define NUMEBR_OF_POINT 20 // amount of point obj to be cteated in a sec #define AMOUNT_OF_POINT 10 // limit amount of point obj #define SPEED_OF_POINT_X 40 // amount of movement in a sec #define SPEED_OF_POINT_Y 40 // amount of movement in a sec #define SUNNY_STAGE_POSSOIBLE 40 // possibily of sunny stage to be selected #define SUNNY_STAGE_TIME_LIMIT 10 // main game setting #define NUMBER_OF_FRAME 100 // amount of frame in a sec #define DEFAULT_PLAYER_HP 100 #define DEFAULT_GAME_TIME 20 // sec #define PLAYER_SPEED 2 // movement of player in a sec #define PLAYER_JUMP_MAX 20 // height of player jump when there are space enough #define PLAYER_JUMP_TIME 1 // define time length of player jump #define PLAYER_SCORE 40 // one time, If player avoid obj #define DAMAGE_INTARVAL 1 // define damage interval when player hit a obj // player #define IN_DAMAGE_INTARVAL 1 #define OUT_DAMAGE_INTARVAL 0 #define NUMBER_OF_GAME 3 //game system value #define ALLOCATION_OK 0 // ram allocation alart #define ALLOCATION_NOT_OK 1 // ram allocation alart #define RESIZE_NOT_HAPPEND 0 // window resize alart #define RESIZE_HAPPEND 1 // window resize alart // show debug log when DEBUG is defined // #define DEBUG typedef struct VECTOR { int x,y; }Vector; // float version of vector typedef struct VECTOR_F { float x,y; }VectorF; typedef struct GRAPHIC { // hold position of top and left corner Vector position,PreviousPosition; Vector size; // [y][x] char **data; }Graphic; typedef struct PLAYER { int hp,score,currentStageScore; // enter defined value int damageIntarval; // enter number of frame since start interval int datageIntarvalFrame; Vector CurrentPosition,PreviousPosition; VectorF speed; // count number of played stage int counterOfGame; Graphic body; }Player; typedef struct STAGE { // hold possiblity of stage to be selected int possible; // hold time limit of each stages int timeLimit; char name[20]; // hold how long player play the stage double timer; // hold obj will be shown in stage int numberOfPreparedObj; Graphic *PreparedObj; int numberOfObj; Graphic *obj; // stage function. This function will not contain game loop. // This function will call random stage chooser or end screen // void (*stageFunc)(Player *player,Stage *stages); void (*stageFunc)(Player *player,struct STAGE*,int numberOfFrame); }Stage; // This value will be used globaly to run this game int width,height; char logs[256]; void setStageParam(Stage *stages); void showPlayer(Player player); void initPlayer(Player *player); int jumpPlayer(Player *player,int numberOfFrame); Vector clacBodyPosition(Vector position, Vector bodySize); int resizeDetect(){ int w,h; getmaxyx(stdscr,h,w); int status = RESIZE_NOT_HAPPEND; if(h != height || w != width){ status = RESIZE_HAPPEND; width = w; height = h; clear(); } return status; } int adjustTimer(double timer){ double length = ((double)1 / NUMBER_OF_FRAME); if(timer \u0026lt; length){ return (int)((length - timer) * 1000000); }else{ return 0; } } double clacTimeFromClock_t(clock_t time){ return (double) time / CLOCKS_PER_SEC; } void debugLog(int y,int x,char *text){ #ifdef DEBUG char newlogs[240]; sprintf(newlogs,\u0026#34;debug log: %s\u0026#34;,text); mvaddstr(y,x,newlogs); refresh(); #endif } // This function can be used any Graphic obj int allocateGraphicRam(Graphic *target){ target -\u0026gt; data = (char **)malloc(sizeof(char *) * target -\u0026gt; size.y); if(target -\u0026gt; data == NULL) return ALLOCATION_NOT_OK; for(int y = 0; y \u0026lt; target -\u0026gt; size.y; y++){ target -\u0026gt; data[y] = (char *)malloc(sizeof(char) * target -\u0026gt; size.x); if(target -\u0026gt; data[y] == NULL) return ALLOCATION_NOT_OK; } return ALLOCATION_OK; } // This function can be used any Graphic obj void freeGraphicRam(Graphic *target){ for(int y = 0; y \u0026lt; target -\u0026gt; size.y; y++){ free(target -\u0026gt; data[y]); } free(target -\u0026gt; data); } void freeObjGraphicRam(Graphic *target,int numberOfObj){ for(int i = 0; i \u0026lt; numberOfObj; i++){ freeGraphicRam(\u0026amp;(target[i])); } } // This function should be executed once when start this game void initWholeGame(){ srand((unsigned)time(NULL)); initscr(); curs_set(0); noecho(); getmaxyx(stdscr,height,width); } // This function should be executed onec when end this game void endWholeGame(Player *player,Stage *stages){ endwin(); // free pointers here // 3 stages may contain pointers which are need to be freed. for(int i = 0; i \u0026lt; 3;i++){ // freeObjGraphicRam(stages[i].obj,stages[i].numberOfObj); freeObjGraphicRam(stages[i].PreparedObj,stages[i].numberOfPreparedObj); // free(stages[i].obj); free(stages[i].PreparedObj); } // player body may contain pointers which need to be freed. free(player -\u0026gt; body.data); } void movePlayerRandomly(Player *player,int numberOfFrame){ // getmaxyx(stdscr,height,width); resizeDetect(); player -\u0026gt; PreviousPosition = player-\u0026gt;CurrentPosition; if(player -\u0026gt; CurrentPosition.y \u0026gt; 0 \u0026amp;\u0026amp; player-\u0026gt;speed.y != 0) player -\u0026gt; CurrentPosition.y = jumpPlayer(player,numberOfFrame); sprintf(logs,\u0026#34;player speed.y: %lf\u0026#34;,player-\u0026gt;speed.y); debugLog(6,3,logs); sprintf(logs,\u0026#34;player current position.y: %d\u0026#34;,player -\u0026gt; CurrentPosition.y); debugLog(7,3,logs); if(numberOfFrame % (100 / PLAYER_SPEED) == 0){ // make random position // 0 -\u0026gt; negative // 1 -\u0026gt; 0 // 2 -\u0026gt; positive Vector direction = {.x=rand() % 3,.y=rand() % 3}; sprintf(logs,\u0026#34;direction x: %d y: %d\u0026#34;,direction.x,direction.y); debugLog(4,3,logs); refresh(); // update position if(direction.x == 0 \u0026amp;\u0026amp; player -\u0026gt; CurrentPosition.x \u0026gt; 0) player -\u0026gt; CurrentPosition.x -= 1; if(direction.y == 0 \u0026amp;\u0026amp; player -\u0026gt; CurrentPosition.y \u0026gt; 0 \u0026amp;\u0026amp; !(player-\u0026gt;speed.y != 0)) player -\u0026gt; CurrentPosition.y = jumpPlayer(player,numberOfFrame); if(direction.x == 2 \u0026amp;\u0026amp; player -\u0026gt; CurrentPosition.x \u0026lt; width) player -\u0026gt; CurrentPosition.x += 1; // if(direction.y == 2 \u0026amp;\u0026amp; player -\u0026gt; CurrentPosition.y \u0026lt; height) player -\u0026gt; CurrentPosition.y += 1; // debug sprintf(logs,\u0026#34;x: %d y: %d\u0026#34;,player -\u0026gt; CurrentPosition.x,player -\u0026gt; CurrentPosition.y); debugLog(5,3,logs); } // update player graphic position player -\u0026gt; body.position = clacBodyPosition(player-\u0026gt;CurrentPosition,player-\u0026gt;body.size); } // Start UI ------------------------------------------------------- int startUI(){ int keys = 0; // init these vars -\u0026gt; OK Vector titlePosition,startButtonPosition,endButtonPosition; Player player; initPlayer(\u0026amp;player); // set defalt option int selectedButton = START_BUTTON; clear(); getmaxyx(stdscr,height,width); // set position retative to screen size titlePosition.y = (height / 2) - 5; startButtonPosition.y = (height / 2) + 1; endButtonPosition.y = (height / 2 ) + 4; titlePosition.x = (width / 2) - 5; startButtonPosition.x = (width / 2) - 5; endButtonPosition.x = (width / 2 ) - 5; // show cursor with first defualt option if(selectedButton == START_BUTTON){ mvaddstr(startButtonPosition.y + 1,startButtonPosition.x,CURSOR); }else{ mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CURSOR); } // show title and start,end button mvaddstr(titlePosition.y,titlePosition.x,\u0026#34;Climate survivor\u0026#34;); mvaddstr(startButtonPosition.y,startButtonPosition.x,\u0026#34;start game\u0026#34;); mvaddstr(endButtonPosition.y,endButtonPosition.x,\u0026#34;end game\u0026#34;); refresh(); int numberOfFrame = 0; clock_t start = 0, delta = 0; double deltaf = 0; while(1){ start = clock(); // recaculation of position when resize window if(resizeDetect() == RESIZE_HAPPEND){ titlePosition.y = (height / 2) - 5; startButtonPosition.y = (height / 2) + 1; endButtonPosition.y = (height / 2 ) + 4; titlePosition.x = (width / 2) - 5; startButtonPosition.x = (width / 2) - 5; endButtonPosition.x = (width / 2 ) - 5; } timeout(0); keys = getch(); movePlayerRandomly(\u0026amp;player,numberOfFrame); showPlayer(player); sprintf(logs,\u0026#34;conuter is %d\u0026#34;,numberOfFrame); debugLog(3,3,logs); numberOfFrame++; // when w or s key is pressed if(keys == \u0026#39;w\u0026#39; || keys == \u0026#39;s\u0026#39;){ if(selectedButton == START_BUTTON){ selectedButton = END_BUTTON; }else{ selectedButton = START_BUTTON; } }else if(keys == \u0026#39;\\n\u0026#39;){ break; } // show title and start,end button mvaddstr(titlePosition.y,titlePosition.x,\u0026#34;Climate survivor\u0026#34;); mvaddstr(startButtonPosition.y,startButtonPosition.x,\u0026#34;start game\u0026#34;); mvaddstr(endButtonPosition.y,endButtonPosition.x,\u0026#34;end game\u0026#34;); // update cursor if(selectedButton == START_BUTTON){ mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CORSOR_REMOVE); mvaddstr(startButtonPosition.y + 1,startButtonPosition.x,CURSOR); }else{ mvaddstr(startButtonPosition.y + 1,startButtonPosition.x,CORSOR_REMOVE); mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CURSOR); } refresh(); delta = clock() - start; deltaf = clacTimeFromClock_t(delta); usleep(adjustTimer(deltaf)); } // free ram which allocated in initPlayer function free(player.body.data); // for next return selectedButton; } // Start UI ------------------------------------------------------- // end UI ----------------------------------------------------------- int endUI(Player *player){ int keys; // init position -\u0026gt; ok Vector scorePosition,endButtonPosition,returnButtonPosition; Player backgoundPlayer; initPlayer(\u0026amp;backgoundPlayer); // set defualt option int selectedButton = END_BUTTON; clear(); getmaxyx(stdscr,height,width); // init position scorePosition.y = (height / 2) - 5; returnButtonPosition.y = (height / 2) + 1; endButtonPosition.y = (height / 2) + 4; scorePosition.x = (width / 2) + 10; endButtonPosition.x = (width / 2) + 10; returnButtonPosition.x = (width / 2) + 10; // show end or return button // show score char scoreText[30]; sprintf(scoreText,\u0026#34;Score is: %d\u0026#34;,player -\u0026gt; score); mvaddstr(scorePosition.y,scorePosition.x,scoreText); // TODO: fix worngly inverted button mvaddstr(returnButtonPosition.y,returnButtonPosition.x,\u0026#34;end game\u0026#34;); mvaddstr(endButtonPosition.y,endButtonPosition.x,\u0026#34;return start screen\u0026#34;); // show cursor if(selectedButton == END_BUTTON){ mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CURSOR); }else if(selectedButton == RETURN_BUTTON){ mvaddstr(returnButtonPosition.y + 1,returnButtonPosition.x,CURSOR); } refresh(); int count = 0; clock_t start = 0, delta = 0; double deltaf = 0; while(1){ start = clock(); // recaculation of position when resize window is happened if(resizeDetect() == RESIZE_HAPPEND){ scorePosition.y = (height / 2) - 5; returnButtonPosition.y = (height / 2) + 1; endButtonPosition.y = (height / 2) + 4; scorePosition.x = (width / 2) + 10; endButtonPosition.x = (width / 2) + 10; returnButtonPosition.x = (width / 2) + 10; } timeout(0); keys = getch(); count++; movePlayerRandomly(\u0026amp;backgoundPlayer,count); showPlayer(backgoundPlayer); // when w or s key is pressed if(keys == \u0026#39;w\u0026#39; || keys == \u0026#39;s\u0026#39;){ if(selectedButton == END_BUTTON){ selectedButton = RETURN_BUTTON; }else{ selectedButton = END_BUTTON; } }else if(keys == \u0026#39;\\n\u0026#39;){ break; } // update cursor if(selectedButton == END_BUTTON){ mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CORSOR_REMOVE); mvaddstr(returnButtonPosition.y + 1,returnButtonPosition.x,CURSOR); }else if(selectedButton == RETURN_BUTTON){ mvaddstr(returnButtonPosition.y + 1,returnButtonPosition.x,CORSOR_REMOVE); mvaddstr(endButtonPosition.y + 1,endButtonPosition.x,CURSOR); } // update text when overwrited by background player mvaddstr(scorePosition.y,scorePosition.x,scoreText); // TODO: fix worngly inverted button mvaddstr(returnButtonPosition.y,returnButtonPosition.x,\u0026#34;end game\u0026#34;); mvaddstr(endButtonPosition.y,endButtonPosition.x,\u0026#34;return start screen\u0026#34;); refresh(); delta = clock() - start; deltaf = clacTimeFromClock_t(delta); usleep(adjustTimer(deltaf)); } free(backgoundPlayer.body.data); return selectedButton; } // end UI ----------------------------------------------------------- // This function makes possible convert player position to body position for graphic Vector clacBodyPosition(Vector position, Vector bodySize){ Vector result; if (bodySize.x % 2 == 0) result.x = position.x - (bodySize.x / 2); if (bodySize.x % 2 != 0) result.x = position.x - (bodySize.x / 2); result.y = position.y - bodySize.y; return result; } void initPlayer(Player *player){ player -\u0026gt; hp = DEFAULT_PLAYER_HP; player -\u0026gt; score = 0; player -\u0026gt; currentStageScore = 0; player -\u0026gt; counterOfGame = 0; player -\u0026gt; damageIntarval = OUT_DAMAGE_INTARVAL; player -\u0026gt; datageIntarvalFrame = 0; // set first player position getmaxyx(stdscr,player -\u0026gt; CurrentPosition.y,player -\u0026gt; CurrentPosition.x); player -\u0026gt; CurrentPosition.x = player -\u0026gt; CurrentPosition.x / 2; player -\u0026gt; PreviousPosition = player -\u0026gt; CurrentPosition; player -\u0026gt; speed.x = 0; player -\u0026gt; speed.y = 0; // set player body player -\u0026gt; body.size.x = 5; player -\u0026gt; body.size.y = 4; player -\u0026gt; body.position = clacBodyPosition(player-\u0026gt;CurrentPosition,player-\u0026gt;body.size); // allocate ram // player.body.data need to be freed when end game allocateGraphicRam(\u0026amp;(player -\u0026gt; body)); // create and set player graphic char tempBody[4][5] = { {\u0026#39; \u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39;#\u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39;#\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;#\u0026#39;,\u0026#39; \u0026#39;} }; for(int y = 0; y \u0026lt; player -\u0026gt; body.size.y ; y++){ for(int x = 0; x \u0026lt; player -\u0026gt; body.size.x ; x++){ player -\u0026gt; body.data[y][x] = tempBody[y][x]; } } } void showBackgroud(Graphic background){ for(int y = 0; y \u0026lt; background.size.y ; y++){ for(int x = 0; x \u0026lt; background.size.x ; x++){ move(y + background.position.y ,x + background.position.x); addch(background.data[y][x]); } } } void initStage(Stage stage){ clear(); } int stageSelector(Stage *stages){ int random = rand() % 100; sprintf(logs,\u0026#34;stage selector rundom num is: %d\u0026#34;,random); debugLog(14,3,logs); if(random \u0026lt;= stages[RAIN_STAGE].possible) return RAIN_STAGE; if(stages[RAIN_STAGE].possible \u0026lt; random \u0026amp;\u0026amp; random \u0026lt;= stages[RAIN_STAGE].possible + stages[WIND_STAGE].possible) return WIND_STAGE; if(stages[RAIN_STAGE].possible + stages[WIND_STAGE].possible \u0026lt; random \u0026amp;\u0026amp; random \u0026lt;= stages[RAIN_STAGE].possible + stages[WIND_STAGE].possible + stages[SUNNY_STAGE].possible) return SUNNY_STAGE; // if any if sentence is not working debugLog(5,3,\u0026#34;Warning! stageSelector function is not working correctly!\u0026#34;); return RAIN_STAGE; } void addPoint(Vector position,char draw){ if( position.x \u0026gt;= 0 \u0026amp;\u0026amp; position.y \u0026gt;= 0 \u0026amp;\u0026amp; position.x \u0026lt;= width \u0026amp;\u0026amp; position.y \u0026lt;= height ){ mvaddch(position.y,position.x,draw); } } // generic version of show graphic // player graphic is not rendered here void showGraphic(Graphic target){ // getmaxyx(stdscr,height,width); resizeDetect(); // clear old graphic for(int y = 0; y \u0026lt; target.size.y; y++){ for(int x = 0; x \u0026lt; target.size.x; x++){ if( y + target.PreviousPosition.y \u0026gt;= 0 \u0026amp;\u0026amp; x + target.PreviousPosition.x \u0026gt;= 0 \u0026amp;\u0026amp; y + target.PreviousPosition.y \u0026lt;= height \u0026amp;\u0026amp; x + target.PreviousPosition.x \u0026lt;= width ){ // move(y + target.PreviousPosition.y, x + target.PreviousPosition.x); // addch(\u0026#39; \u0026#39;); Vector pp = target.PreviousPosition; pp.y += y; pp.x += x; addPoint(pp,\u0026#39; \u0026#39;); } } } // render new graphic for(int y = 0; y \u0026lt; target.size.y; y++){ for(int x = 0; x \u0026lt; target.size.x; x++){ if( y + target.PreviousPosition.y \u0026gt;= 0 \u0026amp;\u0026amp; x + target.PreviousPosition.x \u0026gt;= 0 \u0026amp;\u0026amp; y + target.PreviousPosition.y \u0026lt;= height \u0026amp;\u0026amp; x + target.PreviousPosition.x \u0026lt;= width ){ // move(y + target.position.y, x + target.position.x); // addch(target.data[y][x]); Vector p = target.position; p.y += y; p.x += x; // TODO fix segmantation fault addPoint(p,target.data[y][x]); } } } } // This function will update player hp // This function will delete obj which hit the player int detectHit(Player *player,Stage *stages,int selectedStage){ int detect = FALSE; // getmaxyx(stdscr,height,width); resizeDetect(); // For loop for all obj in stage for(int objs = 0; objs \u0026lt; stages[selectedStage].numberOfObj; objs++){ // for(int objs = 0; objs \u0026lt; 0; objs){ Graphic target = stages[selectedStage].obj[objs]; // refrence obj and player graphics and compare both chars // if both char info is not space like \u0026#39; \u0026#39;, that mean detect hit. // return bool value // check target posiotion and check box in range or not to player Vector targetPosition = target.position; Vector targetSize = target.size; if( targetPosition.x + targetSize.x \u0026lt;= player -\u0026gt; body.position.x \u0026amp;\u0026amp; targetPosition.y + targetSize.y \u0026lt;= player -\u0026gt; body.position.y \u0026amp;\u0026amp; targetPosition.x \u0026gt;= player -\u0026gt; body.position.x + player -\u0026gt; body.size.x \u0026amp;\u0026amp; targetPosition.y \u0026gt;= player -\u0026gt; body.position.y + player -\u0026gt; body.size.y ){ // skip detect hit when trarget is not in player graphic continue; } // For loop to refrence all player body char for(int py = 0; py \u0026lt; player -\u0026gt; body.size.y; py++){ for(int px = 0; px \u0026lt; player -\u0026gt; body.size.x; px++){ // For loop to refrence all obj body char for(int oy = 0; oy \u0026lt; target.size.y ; oy++){ for(int ox = 0; ox \u0026lt; target.size.x; ox++){ char Aplayer = \u0026#39; \u0026#39;; char Aobj = \u0026#39; \u0026#39;; sprintf(logs,\u0026#34;debug log: obj %d\u0026#34;,objs); debugLog(4,3,logs); if( player -\u0026gt; body.position.x + px == target.position.x + ox \u0026amp;\u0026amp; player -\u0026gt; body.position.y + py == target.position.y + oy ){ Aplayer = player -\u0026gt; body.data[py][px]; Aobj = target.data[oy][ox]; sprintf(logs,\u0026#34;debug log: detect hit at x: %d y: %d \u0026#34;,player -\u0026gt; body.position.x + px,player -\u0026gt; body.position.y + py); debugLog(5,3,logs); sprintf(logs,\u0026#34;debug log: Player char: %c obj char: %c\u0026#34;,Aplayer,Aobj); debugLog(6,3,logs); } // comapre values if( Aplayer != \u0026#39; \u0026#39; \u0026amp;\u0026amp; Aobj != \u0026#39; \u0026#39; ) detect = TRUE; } } } } } sprintf(logs,\u0026#34;detection var: %d\u0026#34;,detect); debugLog(9,3,logs); if(detect == TRUE){ debugLog(8,3,\u0026#34;collision detected\u0026#34;); } return detect; } // do special task for each stage --------------------------------- void rainStage(Player *player,Stage *stages,int numberOfFrame){ // If there are objs which are diesappered, add score. // If collion is detected, reduce player hp // getmaxyx(stdscr,height,width); resizeDetect(); // move rain // SPEED_OF_RAIN -\u0026gt; amount of movement in a sec // numberOfFrame % (100 / SPEED_OF_RAIN) -\u0026gt; number of update in a sec if(numberOfFrame % (int)((double)100 / SPEED_OF_RAIN) == 0){ // Rondomly move rain without limitation -\u0026gt; fall movement for(int obj_index = 0; obj_index \u0026lt; stages[RAIN_STAGE].numberOfObj; obj_index++){ stages[RAIN_STAGE].obj[obj_index].PreviousPosition = stages[RAIN_STAGE].obj[obj_index].position; stages[RAIN_STAGE].obj[obj_index].position.y += 1; } } // make rain obj // add rain with random shapes // control number of new rain obj by if sentence blow if(numberOfFrame % (int)((double)100 / NUMEBR_OF_RAIN) == 0 \u0026amp;\u0026amp; stages[RAIN_STAGE].numberOfObj \u0026lt; AMOUNT_OF_RAIN){ // make rain array // init the all array element with space char rain[RAIN_SIZE_Y][RAIN_SIZE_Y] = {\u0026#39; \u0026#39;}; for(int y = 0 ; y \u0026lt; RAIN_SIZE_Y; y++){ for(int x = 0; x \u0026lt; RAIN_SIZE_X; x++){ // rain[y][x] = \u0026#39;\u0026amp;\u0026#39;; int random = rand() % 2; if(x % 2 == 0){ if(random % 2 == 0){ rain[y][x] = \u0026#39;\u0026amp;\u0026#39;; rain[y][x + 1] = \u0026#39; \u0026#39;; } if(random % 2 != 0){ rain[y][x] = \u0026#39; \u0026#39;; rain[y][x + 1] = \u0026#39;\u0026amp;\u0026#39;; } } } } // create random position // make not make same random num int randomPosition = 0; int count = 0; while (count \u0026lt; NUMBER_OF_RETRY) { count++; int moreBreak = FALSE; randomPosition = rand() % width; // avoid segmantation fault if(stages[RAIN_STAGE].numberOfObj == 0) { moreBreak = TRUE; break; } for(int obj_index = 0; obj_index \u0026lt; stages[RAIN_STAGE].numberOfObj; obj_index++){ if( // check obj in same x position stages[RAIN_STAGE].obj[obj_index].position.x == randomPosition \u0026amp;\u0026amp; // check how far from new obj in y aixs stages[RAIN_STAGE].obj[obj_index].position.y \u0026lt; RAIN_Y_SPACE ){ // If there are no space enough, recreate random num sprintf(logs,\u0026#34;debug log: false random num is %d\u0026#34;,randomPosition); debugLog(3,3,logs); }else if(stages[RAIN_STAGE].obj[obj_index].position.x \u0026lt; RAIN_X_SPACE){ // If there are no space enough, recreate random num sprintf(logs,\u0026#34;debug log: false random num is %d\u0026#34;,randomPosition); debugLog(3,3,logs); }else{ sprintf(logs,\u0026#34;debug log: true random num is %d\u0026#34;,randomPosition); debugLog(3,3,logs); moreBreak = TRUE; break; } } if(moreBreak == TRUE) break; } // allocate ram for new rain obj // set position. x position is random but y position is always being at 0. Vector size = {.x=RAIN_SIZE_X,.y=RAIN_SIZE_Y}; Vector position = {.x=randomPosition,.y=0}; int status = ALLOCATION_OK; if(stages[RAIN_STAGE].obj == NULL){ while(stages[RAIN_STAGE].obj == NULL){ stages[RAIN_STAGE].obj = (Graphic *)malloc(sizeof(Graphic) * (AMOUNT_OF_RAIN + 2)); } stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].size = size; stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].position = position; status = allocateGraphicRam(\u0026amp;(stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj])); if(status == ALLOCATION_OK){ // add rain obj to stage obj for(int y = 0 ; y \u0026lt; RAIN_SIZE_Y; y++){ for(int x = 0; x \u0026lt; RAIN_SIZE_X; x++){ stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].data[y][x] = rain[y][x]; } } } }else{ stages[RAIN_STAGE].numberOfObj += 1; stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].size = size; stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].position = position; status = allocateGraphicRam(\u0026amp;(stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj])); if(status == ALLOCATION_OK){ // add rain obj to stage obj for(int y = 0 ; y \u0026lt; RAIN_SIZE_Y; y++){ for(int x = 0; x \u0026lt; RAIN_SIZE_X; x++){ stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].data[y][x] = rain[y][x]; } } }else{ stages[RAIN_STAGE].numberOfObj -= 1; } } } // show and update all rain graphics // separate code for in range version and out of range version // check in range or not for(int obj_index = 0; obj_index \u0026lt; stages[RAIN_STAGE].numberOfObj; obj_index++){ // make and use show graphic function showGraphic(stages[RAIN_STAGE].obj[obj_index]); } // add score as player is alive int score = 0; score += (stages[RAIN_STAGE].timer * PLAYER_SCORE); player -\u0026gt; currentStageScore = score; } void windStage(Player *player,Stage *stages,int numberOfFrame){ // getmaxyx(stdscr,height,width); resizeDetect(); // If there are objs which are diesappered, add score. // If collion is detected, reduce player hp // move obj by wind // update position if(numberOfFrame % SPEED_OF_WIND_X == 0 || numberOfFrame % (int)((double)100 / SPEED_OF_WIND_Y) == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[WIND_STAGE].numberOfObj; obj_index++){ stages[WIND_STAGE].obj[obj_index].PreviousPosition = stages[WIND_STAGE].obj[obj_index].position; } } // SPEED_OF_WIND_X -\u0026gt; amount of movement in a sec if(numberOfFrame % SPEED_OF_WIND_X == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[WIND_STAGE].numberOfObj; obj_index++){ stages[WIND_STAGE].obj[obj_index].position.x += MOVEMENT_OF_OBJ_X; } } // SPEED_OF_WIND_Y -\u0026gt; amount of movement in a sec if(numberOfFrame % (int)((double)100 / SPEED_OF_WIND_Y) == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[WIND_STAGE].numberOfObj; obj_index++){ if(rand() % 2){ stages[WIND_STAGE].obj[obj_index].position.y -= 1; }else{ stages[WIND_STAGE].obj[obj_index].position.y += 1; } } } // create new obj if(numberOfFrame % (int)((double)100 / NUMEBR_OF_BLOWN_AWAY_OBJ) == 0 \u0026amp;\u0026amp; stages[WIND_STAGE].numberOfObj \u0026lt; AMOUNT_OF_OBJ){ // create random position Vector position = {.x=0,.y=0}; position.y = rand() % height; // create obj int choosenObj = rand() % stages[WIND_STAGE].numberOfPreparedObj; char **fig; fig = stages[WIND_STAGE].PreparedObj[choosenObj].data; int status = ALLOCATION_OK; Vector size = stages[WIND_STAGE].PreparedObj[choosenObj].size; if(stages[WIND_STAGE].obj == NULL) { while(stages[WIND_STAGE].obj == NULL){ stages[WIND_STAGE].obj = (Graphic *)malloc(sizeof(Graphic) * (AMOUNT_OF_OBJ + 2)); } stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size = size; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].position = position; // if size value is not set, cause segmantation fault status = allocateGraphicRam(\u0026amp;(stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj])); // add rain obj to stage obj if(status == ALLOCATION_OK){ for(int y = 0 ; y \u0026lt; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.y ; y++){ for(int x = 0; x \u0026lt; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.x ; x++){ stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].data[y][x] = fig[y][x]; } } } }else{ stages[WIND_STAGE].numberOfObj += 1; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size = size; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].position = position; status = allocateGraphicRam(\u0026amp;(stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj])); // add rain obj to stage obj if(status == ALLOCATION_OK){ for(int y = 0 ; y \u0026lt; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.y ; y++){ for(int x = 0; x \u0026lt; stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.x ; x++){ stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].data[y][x] = fig[y][x]; } } }else{ stages[WIND_STAGE].numberOfObj -= 1; } } } // update graphics for(int obj_index = 0; obj_index \u0026lt; stages[WIND_STAGE].numberOfObj; obj_index++){ // make and use show graphic function showGraphic(stages[WIND_STAGE].obj[obj_index]); } // add score as player is alive int score = 0; score += (stages[WIND_STAGE].timer * PLAYER_SCORE); player -\u0026gt; currentStageScore = score; // move obj randomly -\u0026gt; in x and y aixs // show random obj // count obj, disappered obj, appered obj // use count obj result to caculate score and then update player score } void sunnyStage(Player *player,Stage *stages,int numberOfFrame){ // getmaxyx(stdscr,height,width); resizeDetect(); // move obj randomly // update position if(numberOfFrame % (int)((double)100 / SPEED_OF_POINT_X) == 0|| numberOfFrame % (int)((double)100 / SPEED_OF_POINT_Y) == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[SUNNY_STAGE].numberOfObj; obj_index++){ stages[SUNNY_STAGE].obj[obj_index].PreviousPosition = stages[SUNNY_STAGE].obj[obj_index].position; } } // SPEED_OF_POINT_X -\u0026gt; amount of movement in a sec if(numberOfFrame % (int)((double)100 / SPEED_OF_POINT_X) == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[SUNNY_STAGE].numberOfObj; obj_index++){ if(rand() % 2){ stages[SUNNY_STAGE].obj[obj_index].position.x -= 1; }else{ stages[SUNNY_STAGE].obj[obj_index].position.x += 1; } } } // SPEED_OF_POINT_Y -\u0026gt; amount of movement in a sec if(numberOfFrame % (int)((double)100 / SPEED_OF_POINT_Y) == 0){ for(int obj_index = 0; obj_index \u0026lt; stages[SUNNY_STAGE].numberOfObj; obj_index++){ if(rand() % 2){ stages[SUNNY_STAGE].obj[obj_index].position.y -= 1; }else{ stages[SUNNY_STAGE].obj[obj_index].position.y += 1; } } } // create new obj if(numberOfFrame % (int)((double)100 / NUMEBR_OF_POINT) == 0 \u0026amp;\u0026amp; stages[SUNNY_STAGE].numberOfObj \u0026lt; AMOUNT_OF_POINT){ Vector position = {.x=rand()%width,.y=rand()%height}; // create obj int choosenObj = 0; char **fig; fig = stages[SUNNY_STAGE].PreparedObj[choosenObj].data; Vector size = stages[SUNNY_STAGE].PreparedObj[choosenObj].size; int status = ALLOCATION_OK; if(stages[SUNNY_STAGE].obj == NULL) { while(stages[SUNNY_STAGE].obj == NULL){ stages[SUNNY_STAGE].obj = (Graphic *)malloc(sizeof(Graphic) * (AMOUNT_OF_POINT + 2)); } stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size = size; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].position = position; status = allocateGraphicRam(\u0026amp;(stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj])); // add point obj to stage obj if(status == ALLOCATION_OK){ for(int y = 0 ; y \u0026lt; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.y ; y++){ for(int x = 0; x \u0026lt; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.x ; x++){ stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].data[y][x] = fig[y][x]; } } } }else{ stages[SUNNY_STAGE].numberOfObj += 1; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size = size; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].position = position; status = allocateGraphicRam(\u0026amp;(stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj])); // add point obj to stage obj if(status == ALLOCATION_OK){ for(int y = 0 ; y \u0026lt; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.y ; y++){ for(int x = 0; x \u0026lt; stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.x ; x++){ stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].data[y][x] = fig[y][x]; } } }else{ stages[SUNNY_STAGE].numberOfObj -= 1; } } } // update graphics for(int obj_index = 0; obj_index \u0026lt; stages[SUNNY_STAGE].numberOfObj; obj_index++){ // make and use show graphic function showGraphic(stages[SUNNY_STAGE].obj[obj_index]); } } // do special task for each stage --------------------------------- // show ui top left and right corner void ShowStageUI(Stage stage,Player player){ Vector timerPosition,hpPosition,scorePosition,stageNamePosition; // getmaxyx(stdscr,height,width); resizeDetect(); timerPosition.y = 1; timerPosition.x = width - 20; hpPosition.y = timerPosition.y + 1; hpPosition.x = width - 20; scorePosition.y = hpPosition.y + 1; scorePosition.x = width - 20; stageNamePosition.y = 1; stageNamePosition.x = 1; char timerText[20]; char hpText[20]; char scoreText[20]; sprintf(timerText,\u0026#34;Time: %-3d/%-3d(sec)\u0026#34;,(int)stage.timer,stage.timeLimit); sprintf(hpText,\u0026#34;HP: %-3d\u0026#34;,player.hp); sprintf(scoreText,\u0026#34;Score: %-3d\u0026#34;,player.currentStageScore + player.score); mvaddstr(timerPosition.y,timerPosition.x,timerText); mvaddstr(hpPosition.y,hpPosition.x,hpText); mvaddstr(scorePosition.y,scorePosition.x,scoreText); mvaddstr(stageNamePosition.y,stageNamePosition.x,stage.name); refresh(); } int jumpPlayer(Player *player,int numberOfFrame){ // pi value should be between 0 and PLAYER_JUMP_MAX int result = 0; double temp = 0; float pi = 0; int playerJumpHeight = PLAYER_JUMP_MAX; // getmaxyx(stdscr,height,width); resizeDetect(); if(playerJumpHeight \u0026gt; height){ playerJumpHeight = height - 4; } double lengthInOneFrame = (double)(playerJumpHeight * 2) / 100; lengthInOneFrame /= PLAYER_JUMP_TIME; if(player -\u0026gt; speed.y \u0026lt; (playerJumpHeight * 2)) player-\u0026gt;speed.y += lengthInOneFrame; else player -\u0026gt; speed.y = 0; pi = sin(player -\u0026gt; speed.y * (3.14f / (playerJumpHeight * 2))); temp = (double)height - (pi * (double)playerJumpHeight); return (int)temp; } void controlPlayer(Player *player,int numberOfFrame){ // getmaxyx(stdscr,height,width); resizeDetect(); int keys; // player can be controled by wasd keys timeout(0); keys = getch(); player-\u0026gt;PreviousPosition = player-\u0026gt;CurrentPosition; // jump if(((keys == \u0026#39;w\u0026#39; || keys == \u0026#39; \u0026#39;) \u0026amp;\u0026amp; player-\u0026gt;CurrentPosition.y \u0026gt; 0) || player-\u0026gt;speed.y != 0) player-\u0026gt;CurrentPosition.y = jumpPlayer(player,numberOfFrame); // move left and right in constant speed if(keys == \u0026#39;a\u0026#39; \u0026amp;\u0026amp; player-\u0026gt;CurrentPosition.x \u0026gt; 0 + (player-\u0026gt;body.size.x / 2) + 1) player-\u0026gt;CurrentPosition.x -= PLAYER_SPEED; if(keys == \u0026#39;d\u0026#39; \u0026amp;\u0026amp; player-\u0026gt;CurrentPosition.x \u0026lt; width - player-\u0026gt;body.size.x) player-\u0026gt;CurrentPosition.x += PLAYER_SPEED; // update graphic position player -\u0026gt; body.position = clacBodyPosition(player-\u0026gt;CurrentPosition,player-\u0026gt;body.size); } void detectHitPlayer(Player *player,Stage *stages,int selectedStage,int numberOfFrame){ int collosion = detectHit(player,stages,selectedStage); if(collosion == TRUE \u0026amp;\u0026amp; player -\u0026gt; damageIntarval == OUT_DAMAGE_INTARVAL){ switch (selectedStage) { case RAIN_STAGE: flash(); player -\u0026gt; hp -= DAMAGE_OF_RAIN; break; case SUNNY_STAGE: flash(); player -\u0026gt; hp += AMOUNT_OF_RACOVER; player -\u0026gt; currentStageScore += PLAYER_SCORE; break; case WIND_STAGE: flash(); player -\u0026gt; hp -= DAMAGE_OF_OBJ; break; default: debugLog(3,10,\u0026#34;Worng stage is selected. Check code.\u0026#34;); break; } player -\u0026gt; damageIntarval = IN_DAMAGE_INTARVAL; } if(player -\u0026gt; damageIntarval == IN_DAMAGE_INTARVAL) player -\u0026gt; datageIntarvalFrame += 1; if(player -\u0026gt; datageIntarvalFrame == (100 * DAMAGE_INTARVAL)){ player -\u0026gt; damageIntarval = OUT_DAMAGE_INTARVAL; player -\u0026gt; datageIntarvalFrame = 0; } sprintf(logs,\u0026#34;damage intarval: %d\u0026#34;,player -\u0026gt; datageIntarvalFrame); debugLog(11,3,logs); } void showPlayer(Player player){ // clear old player graphic Vector oldBodyPosition = clacBodyPosition(player.PreviousPosition,player.body.size); for(int y = 0; y \u0026lt; player.body.size.y; y++){ for(int x = 0; x \u0026lt; player.body.size.x; x++){ move(y + oldBodyPosition.y,x + oldBodyPosition.x); addch(\u0026#39; \u0026#39;); } } // show player for(int y = 0; y \u0026lt; player.body.size.y; y++){ for(int x = 0; x \u0026lt; player.body.size.x; x++){ move(y + player.body.position.y,x + player.body.position.x); addch(player.body.data[y][x]); } } refresh(); } // TODO: fix segmatation fualt after wind stage // call once when start button selected // make start_UI call this function when start button is selected. -\u0026gt; OK void StageLoop(Player *player,Stage *stages){ int selectedStage = WIND_STAGE; for(int times = 0; times \u0026lt; NUMBER_OF_GAME; times++){ selectedStage = stageSelector(stages); initStage(stages[selectedStage]); clock_t start = 0, delta = 0; time_t gameStartTime = time(NULL); double deltaf = 0; int numberOfFrame = 0; int resizeHappn = RESIZE_NOT_HAPPEND; while(1){ start = clock(); resizeHappn = resizeDetect(); // move -\u0026gt; update graphic -\u0026gt; collion detection controlPlayer(player,numberOfFrame); // show time hp score stage name -\u0026gt; OK ShowStageUI(stages[selectedStage],*player); // update order // stage graphic -\u0026gt; player graphic if(numberOfFrame % 30 == 0) stages[selectedStage].stageFunc(player,stages,numberOfFrame); showPlayer(*player); // collsion system detectHitPlayer(player,stages,selectedStage,numberOfFrame); refresh(); numberOfFrame++; delta = clock() - start; deltaf = clacTimeFromClock_t(delta); stages[selectedStage].timer = difftime(time(NULL),gameStartTime); if(resizeHappn) resizeHappn = RESIZE_NOT_HAPPEND; usleep(adjustTimer(deltaf)); if(stages[selectedStage].timer \u0026gt; stages[selectedStage].timeLimit || player -\u0026gt; hp \u0026lt;= 0) break; } // all stage reqire addtional memory management freeObjGraphicRam(stages[selectedStage].obj,stages[selectedStage].numberOfObj); free(stages[selectedStage].obj); stages[selectedStage].numberOfObj = 0; // stages[selectedStage].timer = 0; setStageParam(stages); player -\u0026gt; score += player -\u0026gt; currentStageScore; player -\u0026gt; currentStageScore = 0; if(player -\u0026gt; hp \u0026lt;= 0) break; } } // pass stage array whose size is 3 void setStageParam(Stage *stages){ // getmaxyx(stdscr,height,width); resizeDetect(); // rain stage -------------------------------------------------------------------------------- stages[RAIN_STAGE].possible = RAIN_STAGE_POSSIBLE; stages[RAIN_STAGE].timer = 0; stages[RAIN_STAGE].timeLimit = RAIN_STAGE_TIME_LIMIT; sprintf(stages[RAIN_STAGE].name,\u0026#34;rain stage\u0026#34;); // rain obj // obj will be used to manage rain obj in rain stage // rain will be made by function and caculation // So in this function, I will not allocate stages[RAIN_STAGE].numberOfObj = 0; stages[RAIN_STAGE].obj = NULL; stages[RAIN_STAGE].numberOfPreparedObj = 0; stages[RAIN_STAGE].PreparedObj = NULL; // stage function pointer stages[RAIN_STAGE].stageFunc = rainStage; // rain stage -------------------------------------------------------------------------------- // wind stage -------------------------------------------------------------------------------- stages[WIND_STAGE].possible = WIND_STAGE_POSSIBLE; stages[WIND_STAGE].timer = 0; stages[WIND_STAGE].timeLimit = WIND_STAGE_TIME_LIMIT; sprintf(stages[WIND_STAGE].name,\u0026#34;wind stage\u0026#34;); // blown away obj // rectangle obj 0 int obj_index = 0; stages[WIND_STAGE].numberOfPreparedObj = 1; stages[WIND_STAGE].PreparedObj = malloc(sizeof(Graphic) * 3); stages[WIND_STAGE].PreparedObj[obj_index].position.x = 0; stages[WIND_STAGE].PreparedObj[obj_index].position.y = 0; stages[WIND_STAGE].PreparedObj[obj_index].size.x = 3; stages[WIND_STAGE].PreparedObj[obj_index].size.y = 3; allocateGraphicRam(\u0026amp;(stages[WIND_STAGE].PreparedObj[obj_index])); char rectangle[3][3] = { {\u0026#39;A\u0026#39;,\u0026#39;A\u0026#39;,\u0026#39;A\u0026#39;}, {\u0026#39;A\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;A\u0026#39;}, {\u0026#39;B\u0026#39;,\u0026#39;B\u0026#39;,\u0026#39;B\u0026#39;}}; for(int y = 0; y \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.y; y++){ for(int x = 0; x \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.x; x++){ stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] = rectangle[y][x]; } } obj_index++; stages[WIND_STAGE].numberOfPreparedObj += 1; // triangle obj 1 stages[WIND_STAGE].PreparedObj[obj_index].position.x = 0; stages[WIND_STAGE].PreparedObj[obj_index].position.y = 0; stages[WIND_STAGE].PreparedObj[obj_index].size.x = 5; stages[WIND_STAGE].PreparedObj[obj_index].size.y = 3; allocateGraphicRam(\u0026amp;(stages[WIND_STAGE].PreparedObj[obj_index])); char triangle[3][5] = { {\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39;a\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39;A\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;A\u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39;b\u0026#39;,\u0026#39;B\u0026#39;,\u0026#39;B\u0026#39;,\u0026#39;B\u0026#39;,\u0026#39;b\u0026#39;}}; for(int y = 0; y \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.y; y++){ for(int x = 0; x \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.x; x++){ stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] = triangle[y][x]; } } obj_index++; stages[WIND_STAGE].numberOfPreparedObj += 1; // hexagon? obj 2 stages[WIND_STAGE].PreparedObj[obj_index].position.x = 0; stages[WIND_STAGE].PreparedObj[obj_index].position.y = 0; stages[WIND_STAGE].PreparedObj[obj_index].size.x = 5; stages[WIND_STAGE].PreparedObj[obj_index].size.y = 6; allocateGraphicRam(\u0026amp;(stages[WIND_STAGE].PreparedObj[obj_index])); char hexagon[6][5] = { {\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39;*\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39;J\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;L\u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39;A\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39;A\u0026#39;}, {\u0026#39;A\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39;A\u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39;L\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;J\u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39; \u0026#39;,\u0026#39; \u0026#39;,\u0026#39;*\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;}}; for(int y = 0; y \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.y; y++){ for(int x = 0; x \u0026lt; stages[WIND_STAGE].PreparedObj[obj_index].size.x; x++){ stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] = hexagon[y][x]; } } stages[WIND_STAGE].numberOfObj = 0; stages[WIND_STAGE].obj = NULL; // stage function pointer stages[WIND_STAGE].stageFunc = windStage; // wind stage -------------------------------------------------------------------------------- // sunny stage -------------------------------------------------------------------------------- stages[SUNNY_STAGE].possible = SUNNY_STAGE_POSSOIBLE; stages[SUNNY_STAGE].timer = 0; stages[SUNNY_STAGE].timeLimit = SUNNY_STAGE_TIME_LIMIT; sprintf(stages[SUNNY_STAGE].name,\u0026#34;sunny stage\u0026#34;); // point obj 0 // This obj give player score and point // If player miss this obj, these obj will not be score obj_index = 0; stages[SUNNY_STAGE].numberOfPreparedObj = 1; stages[SUNNY_STAGE].PreparedObj = malloc(sizeof(Graphic) * 1); stages[SUNNY_STAGE].PreparedObj[obj_index].position.x = 0; stages[SUNNY_STAGE].PreparedObj[obj_index].position.y = 0; stages[SUNNY_STAGE].PreparedObj[obj_index].size.x = 3; stages[SUNNY_STAGE].PreparedObj[obj_index].size.y = 5; allocateGraphicRam(\u0026amp;(stages[SUNNY_STAGE].PreparedObj[obj_index])); char point[5][3] = { {\u0026#39;P\u0026#39;,\u0026#39;P\u0026#39;,\u0026#39;P\u0026#39;}, {\u0026#39;P\u0026#39;,\u0026#39; \u0026#39;,\u0026#39;P\u0026#39;}, {\u0026#39;P\u0026#39;,\u0026#39;P\u0026#39;,\u0026#39;P\u0026#39;}, {\u0026#39;P\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;}, {\u0026#39;P\u0026#39;,\u0026#39; \u0026#39;,\u0026#39; \u0026#39;}}; for(int y = 0; y \u0026lt; stages[SUNNY_STAGE].PreparedObj[obj_index].size.y; y++){ for(int x = 0; x \u0026lt; stages[SUNNY_STAGE].PreparedObj[obj_index].size.x; x++){ stages[SUNNY_STAGE].PreparedObj[obj_index].data[y][x] = point[y][x]; } } stages[SUNNY_STAGE].numberOfObj = 0; stages[SUNNY_STAGE].obj = NULL; // stage function pointer stages[SUNNY_STAGE].stageFunc = sunnyStage; // synny stage -------------------------------------------------------------------------------- } int main(int argc,char ** args){ int selectedMode = START_BUTTON; Player player; Stage *stages; stages = malloc(sizeof(Stage) * 3); setStageParam(stages); initWholeGame(); // show start UI selectedMode = startUI(); initPlayer(\u0026amp;player); // OK while(1){ if(selectedMode == START_BUTTON){ initPlayer(\u0026amp;player); // OK StageLoop(\u0026amp;player,stages); // show end UI selectedMode = endUI(\u0026amp;player); }else if(selectedMode == RETURN_BUTTON){ selectedMode = startUI(); }else if(selectedMode == END_BUTTON){ break; } } // end curses and free ram endWholeGame(\u0026amp;player,stages); free(stages); return 0; } ","permalink":"https://www.nyanmo.info/posts/c/agame/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　ただ単にせっかく書いたコードを、無下にしてしまうのは勿体ないなと思い、非効率でバグだらけのスパゲッティコードではあるが、まあおいておこうかなと思っただけです。（かつコメントの英語もガバだらけ。。。）\u003c/p\u003e\n\u003cp\u003e　ちなみに、授業の制約上、一つのファイルにまとめざるを得ず、プログラムを分割できなかったのでえげつなく肥大化しています。。。\u003c/p\u003e\n\u003ch2 id=\"使っているライブラリ\"\u003e使っているライブラリ\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eC標準ライブラリ\u003c/li\u003e\n\u003cli\u003ecurses\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"プレイ動画\"\u003eプレイ動画\u003c/h2\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n\u003cdiv style=\"display: flex; justify-content: center;\"\u003e\n\n\n\n    \n    \n\n        \u003cvideo style=\"margin:10px; width: 100%;\" src=/posts/C/Agame/%e3%83%86%e3%82%b9%e3%83%88%e3%83%97%e3%83%ac%e3%82%a4%e5%8b%95%e7%94%bb.mp4 controls/\u003e\n        \n\u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"各画面の説明\"\u003e各画面の説明\u003c/h2\u003e\n\u003ch3 id=\"スタート画面\"\u003eスタート画面\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/C/Agame/start.png alt=ZgotmplZ/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch3 id=\"終わりの画面\"\u003e終わりの画面\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/C/Agame/end.png alt=ZgotmplZ/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch3 id=\"風のすてーじ\"\u003e風のすてーじ\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/C/Agame/windStage.png alt=ZgotmplZ/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003c!-- 　風で飛ばされてくる障害物を避けるすてーじです。 --\u003e\n\u003ch3 id=\"雨のすてーじ\"\u003e雨のすてーじ\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/C/Agame/rainStage.png alt=ZgotmplZ/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003c!-- 　雨が降ってくるのでそれを避けるすてーじです。 --\u003e\n\u003ch3 id=\"晴れの日すてーじ\"\u003e晴れの日すてーじ\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/C/Agame/sunnyStage.png alt=ZgotmplZ/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003c!-- 　\"P\" というオブジェクトが出現するのでそれに触れると体力が回復するすてーじです。 --\u003e\n\u003ch2 id=\"コンパイル\"\u003eコンパイル\u003c/h2\u003e\n\u003ch3 id=\"makefile\"\u003emakefile\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-makefile\" data-lang=\"makefile\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ebuild\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tgcc main.c -lcurses -lm -o main\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"bash-上の操作\"\u003ebash 上の操作\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake build\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./main \u003cspan style=\"color:#75715e\"\u003e# 実行\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c!-- ## 駄文レポートPDF\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n\n\n\n\n\n\n\n\n\u003cembed style=\"margin:10px; width: 100%; height: 100%;\" src=/posts/C/Agame/%e3%83%ac%e3%83%9d%e3%83%bc%e3%83%88%e3%83%86%e3%83%b3%e3%83%97%e3%83%ac.pdf/\u003e\n\n\n\n\u003c/div\u003e --\u003e\n\u003ch2 id=\"コード本体\"\u003eコード本体\u003c/h2\u003e\n\u003ch3 id=\"mainc\"\u003emain.c\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;curses.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stdlib.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;math.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;time.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;unistd.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;string.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define START_BUTTON 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define END_BUTTON 1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RETURN_BUTTON 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define CURSOR \u0026#34;====================\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define CORSOR_REMOVE \u0026#34;                    \u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// define const values for each stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_STAGE 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define WIND_STAGE 1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SUNNY_STAGE 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// rain stage setting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_SIZE_X 2               \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// set size of a rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_SIZE_Y 2               \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// set size of a rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_Y_SPACE 10             \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// avoid rain creation if there are created rain near the new rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_X_SPACE 3              \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// avoid rain creation if there are created rain near the new rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMEBR_OF_RAIN 5            \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// number of newly created rain in 1 sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SPEED_OF_RAIN 30            \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define DAMAGE_OF_RAIN 10           \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of damage when player hit a rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMBER_OF_RETRY 20          \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// define how many times to recreate random nums\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_STAGE_POSSIBLE 30      \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// possibily of rain stage to be selected\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RAIN_STAGE_TIME_LIMIT 20\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define AMOUNT_OF_RAIN 28           \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// limit amount of rain \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// wind stage setting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define DAMAGE_OF_OBJ 20            \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of damage when player hit a obj in this stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMEBR_OF_BLOWN_AWAY_OBJ 5  \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// number of obj to be created in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SPEED_OF_WIND_X 1           \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// numberOfFrame % this const value -\u0026gt; 100f in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define MOVEMENT_OF_OBJ_X 5         \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of movement in one position update\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SPEED_OF_WIND_Y 20          \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define AMOUNT_OF_OBJ 28            \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// limit amount of obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define WIND_STAGE_POSSIBLE 30      \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// possibily of wind stage to be selected\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define WIND_STAGE_TIME_LIMIT 20\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// sunny stage setting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define AMOUNT_OF_RACOVER 10        \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of hp recover when player hit point obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMEBR_OF_POINT 20          \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of point obj to be cteated in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define AMOUNT_OF_POINT 10          \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// limit amount of point obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SPEED_OF_POINT_X 40         \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SPEED_OF_POINT_Y 40         \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SUNNY_STAGE_POSSOIBLE 40    \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// possibily of sunny stage to be selected\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define SUNNY_STAGE_TIME_LIMIT 10\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// main game setting\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMBER_OF_FRAME 100     \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// amount of frame in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define DEFAULT_PLAYER_HP 100\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define DEFAULT_GAME_TIME 20    \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define PLAYER_SPEED 2          \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// movement of player in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define PLAYER_JUMP_MAX 20      \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// height of player jump when there are space enough\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define PLAYER_JUMP_TIME 1      \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// define time length of player jump\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define PLAYER_SCORE 40         \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// one time, If player avoid obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define DAMAGE_INTARVAL 1       \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// define damage interval when player hit a obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// player\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define IN_DAMAGE_INTARVAL 1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define OUT_DAMAGE_INTARVAL 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define NUMBER_OF_GAME 3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//game system value\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define ALLOCATION_OK 0                 \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// ram allocation alart\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define ALLOCATION_NOT_OK 1             \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// ram allocation alart\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RESIZE_NOT_HAPPEND 0            \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// window resize alart\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define RESIZE_HAPPEND 1                \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e// window resize alart\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// show debug log when DEBUG is defined\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// #define DEBUG\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etypedef\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e VECTOR\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x,y;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}Vector;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// float version of vector\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etypedef\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e VECTOR_F\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efloat\u003c/span\u003e x,y;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}VectorF;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etypedef\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e GRAPHIC\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hold position of top and left corner \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector position,PreviousPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// [y][x]\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003edata;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}Graphic;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etypedef\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e PLAYER\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e hp,score,currentStageScore;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// enter defined value\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e damageIntarval;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// enter number of frame since start interval\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e datageIntarvalFrame;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector CurrentPosition,PreviousPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    VectorF speed;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// count number of played stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e counterOfGame;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Graphic body;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}Player;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etypedef\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e STAGE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hold possiblity of stage to be selected\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e possible;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hold time limit of each stages\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e timeLimit;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e name[\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hold how long player play the stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e timer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// hold obj will be shown in stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfPreparedObj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ePreparedObj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfObj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eobj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// stage function. This function will not contain game loop.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// This function will call random stage chooser or end screen\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// void (*stageFunc)(Player *player,Stage *stages);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estageFunc)(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e STAGE\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}Stage;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This value will be used globaly to run this game \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e width,height;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e logs[\u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetStageParam\u003c/span\u003e(Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshowPlayer\u003c/span\u003e(Player player);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejumpPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eVector \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(Vector position, Vector bodySize);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e w,h;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetmaxyx\u003c/span\u003e(stdscr,h,w);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RESIZE_NOT_HAPPEND;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(h \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e height \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e w \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e width){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RESIZE_HAPPEND;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e w; height \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e h;  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eclear\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e status;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eadjustTimer\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e timer){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e length \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e NUMBER_OF_FRAME);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(timer \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e length){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((length \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e timer) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000000\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclacTimeFromClock_t\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eclock_t\u003c/span\u003e time){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e) time \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e CLOCKS_PER_SEC;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003etext){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e#ifdef DEBUG\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e newlogs[\u003cspan style=\"color:#ae81ff\"\u003e240\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(newlogs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: %s\u0026#34;\u003c/span\u003e,text);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(y,x,newlogs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function can be used any Graphic obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003etarget){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e size.y);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ALLOCATION_NOT_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data[y] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e size.x);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data[y] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL) \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ALLOCATION_NOT_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ALLOCATION_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function can be used any Graphic obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efreeGraphicRam\u003c/span\u003e(Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003etarget){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data[y]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(target \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e data);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efreeObjGraphicRam\u003c/span\u003e(Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003etarget,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfObj){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e numberOfObj; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003efreeGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(target[i]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function should be executed once when start this game\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitWholeGame\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esrand\u003c/span\u003e((\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e(NULL));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003einitscr\u003c/span\u003e(); \u003cspan style=\"color:#a6e22e\"\u003ecurs_set\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e); \u003cspan style=\"color:#a6e22e\"\u003enoecho\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetmaxyx\u003c/span\u003e(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function should be executed onec when end this game \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eendWholeGame\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eendwin\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// free pointers here\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 3 stages may contain pointers which are need to be freed.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// freeObjGraphicRam(stages[i].obj,stages[i].numberOfObj);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003efreeObjGraphicRam\u003c/span\u003e(stages[i].PreparedObj,stages[i].numberOfPreparedObj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// free(stages[i].obj);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(stages[i].PreparedObj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// player body may contain pointers which need to be freed.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.data);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emovePlayerRandomly\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e PreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003espeed.y \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejumpPlayer\u003c/span\u003e(player,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;player speed.y: %lf\u0026#34;\u003c/span\u003e,player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003espeed.y);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;player current position.y: %d\u0026#34;\u003c/span\u003e,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e7\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e PLAYER_SPEED) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make random position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 0 -\u0026gt; negative\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 1 -\u0026gt; 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 2 -\u0026gt; positive\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector direction \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {.x\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,.y\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;direction x: %d y: %d\u0026#34;\u003c/span\u003e,direction.x,direction.y);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// update position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(direction.x \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(direction.y \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e(player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003espeed.y \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)) player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejumpPlayer\u003c/span\u003e(player,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(direction.x \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e width) player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// if(direction.y == 2 \u0026amp;\u0026amp; player -\u0026gt; CurrentPosition.y \u0026lt; height) player -\u0026gt; CurrentPosition.y += 1;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// debug\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;x: %d y: %d\u0026#34;\u003c/span\u003e,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update player graphic position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition,player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ebody.size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Start UI -------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estartUI\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e keys \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// init these vars -\u0026gt; OK\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector titlePosition,startButtonPosition,endButtonPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Player player;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set defalt option\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e START_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eclear\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetmaxyx\u003c/span\u003e(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set position retative to screen size\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        titlePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        startButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        titlePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        startButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        endButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show cursor with first defualt option\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e START_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(startButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,startButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show title and start,end button\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(titlePosition.y,titlePosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Climate survivor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(startButtonPosition.y,startButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;start game\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y,endButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;end game\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eclock_t\u003c/span\u003e start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// recaculation of position when resize window\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e RESIZE_HAPPEND){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            titlePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            startButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            titlePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            startButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            endButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etimeout\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        keys \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetch\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emovePlayerRandomly\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eshowPlayer\u003c/span\u003e(player);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;conuter is %d\u0026#34;\u003c/span\u003e,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        numberOfFrame\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// when w or s key is pressed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;w\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s\u0026#39;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e START_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e END_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e START_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\\n\u0026#39;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// show title and start,end button\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(titlePosition.y,titlePosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Climate survivor\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(startButtonPosition.y,startButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;start game\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y,endButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;end game\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// update cursor\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e START_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CORSOR_REMOVE);            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(startButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,startButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(startButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,startButtonPosition.x,CORSOR_REMOVE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e start;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclacTimeFromClock_t\u003c/span\u003e(delta);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eusleep\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eadjustTimer\u003c/span\u003e(deltaf));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// free ram which allocated in initPlayer function\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(player.body.data);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// for next\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e selectedButton;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Start UI -------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// end UI -----------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eendUI\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e keys;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// init position -\u0026gt; ok\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector scorePosition,endButtonPosition,returnButtonPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Player backgoundPlayer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ebackgoundPlayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set defualt option\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e END_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eclear\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003egetmaxyx\u003c/span\u003e(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// init position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        scorePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        returnButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        scorePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        endButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        returnButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show end or return button\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show score\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e scoreText[\u003cspan style=\"color:#ae81ff\"\u003e30\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(scoreText,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Score is: %d\u0026#34;\u003c/span\u003e,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e score);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(scorePosition.y,scorePosition.x,scoreText);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// TODO: fix worngly inverted button\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(returnButtonPosition.y,returnButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;end game\u0026#34;\u003c/span\u003e);    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y,endButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;return start screen\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show cursor\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e END_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e RETURN_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(returnButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,returnButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e count \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eclock_t\u003c/span\u003e start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e();         \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// recaculation of position when resize window is happened\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e RESIZE_HAPPEND){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            scorePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            returnButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (height \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            scorePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            endButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            returnButtonPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (width \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }       \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etimeout\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        keys \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetch\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        count\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emovePlayerRandomly\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ebackgoundPlayer,count);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eshowPlayer\u003c/span\u003e(backgoundPlayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// when w or s key is pressed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;w\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s\u0026#39;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e END_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RETURN_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                selectedButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e END_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\\n\u0026#39;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// update cursor\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e END_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CORSOR_REMOVE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(returnButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,returnButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedButton \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e RETURN_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(returnButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,returnButtonPosition.x,CORSOR_REMOVE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,endButtonPosition.x,CURSOR);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// update text when overwrited by background player\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(scorePosition.y,scorePosition.x,scoreText);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// TODO: fix worngly inverted button\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(returnButtonPosition.y,returnButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;end game\u0026#34;\u003c/span\u003e);    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(endButtonPosition.y,endButtonPosition.x,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;return start screen\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e start;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclacTimeFromClock_t\u003c/span\u003e(delta);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eusleep\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eadjustTimer\u003c/span\u003e(deltaf));        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(backgoundPlayer.body.data);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e selectedButton;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// end UI -----------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function makes possible convert player position to body position for graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eVector \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(Vector position, Vector bodySize){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector result;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (bodySize.x \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) result.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position.x \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (bodySize.x \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (bodySize.x \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) result.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position.x \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (bodySize.x \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    result.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position.y \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e bodySize.y;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e result;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e DEFAULT_PLAYER_HP;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e score \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e counterOfGame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e damageIntarval \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e OUT_DAMAGE_INTARVAL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e datageIntarvalFrame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set first player position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003egetmaxyx\u003c/span\u003e(stdscr,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.y,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e PreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e CurrentPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e speed.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e speed.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// set player body\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e; player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition,player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ebody.size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// allocate ram\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// player.body.data need to be freed when end game\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// create and set player graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e tempBody[\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e][\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e}        \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e tempBody[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshowBackgroud\u003c/span\u003e(Graphic background){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e background.size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e background.size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emove\u003c/span\u003e(y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e background.position.y ,x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e background.position.x);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eaddch\u003c/span\u003e(background.data[y][x]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einitStage\u003c/span\u003e(Stage stage){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eclear\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estageSelector\u003c/span\u003e(Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;stage selector rundom num is: %d\u0026#34;\u003c/span\u003e,random);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e14\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(random \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e stages[RAIN_STAGE].possible) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e RAIN_STAGE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[RAIN_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e stages[RAIN_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e stages[WIND_STAGE].possible) \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e WIND_STAGE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[RAIN_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e stages[WIND_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e stages[RAIN_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e stages[WIND_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e stages[SUNNY_STAGE].possible)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e SUNNY_STAGE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// if any if sentence is not working\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Warning! stageSelector function is not working correctly!\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e RAIN_STAGE; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eaddPoint\u003c/span\u003e(Vector position,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e draw){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        position.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        position.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        position.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        position.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e height \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emvaddch\u003c/span\u003e(position.y,position.x,draw);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// generic version of show graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// player graphic is not rendered here\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshowGraphic\u003c/span\u003e(Graphic target){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// clear old graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e height \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e width                 \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// move(y + target.PreviousPosition.y, x + target.PreviousPosition.x);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// addch(\u0026#39; \u0026#39;);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Vector pp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e target.PreviousPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                pp.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e y; pp.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e x;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eaddPoint\u003c/span\u003e(pp,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// render new graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e height \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e target.PreviousPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e width                \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// move(y + target.position.y, x + target.position.x);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// addch(target.data[y][x]);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Vector p \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e target.position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                p.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e y; p.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e x;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// TODO fix segmantation fault\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eaddPoint\u003c/span\u003e(p,target.data[y][x]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function will update player hp\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// This function will delete obj which hit the player\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edetectHit\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedStage){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e detect \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e FALSE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// For loop for all obj in stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e objs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; objs \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[selectedStage].numberOfObj; objs\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// for(int objs = 0; objs \u0026lt; 0; objs){\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Graphic target \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[selectedStage].obj[objs];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// refrence obj and player graphics and compare both chars\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// if both char info is not space like \u0026#39; \u0026#39;, that mean detect hit.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// return bool value\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// check target posiotion and check box in range or not to player\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector targetPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e target.position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector targetSize \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e target.size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            targetPosition.x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e targetSize.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.x \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            targetPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e targetSize.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.y \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            targetPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.x \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            targetPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.y\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// skip detect hit when trarget is not in player graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// For loop to refrence all player body char\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e py \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; py \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.y; py\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e px \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; px \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.size.x; px\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// For loop to refrence all obj body char\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e oy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; oy \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.y ; oy\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e ox \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; ox \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e target.size.x; ox\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e Aplayer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e Aobj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: obj %d\u0026#34;\u003c/span\u003e,objs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e px \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e target.position.x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e ox \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e py \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e target.position.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e oy                                    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            Aplayer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.data[py][px];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            Aobj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e target.data[oy][ox];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: detect hit at x: %d y: %d \u0026#34;\u003c/span\u003e,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e px,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e py);                                \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: Player char: %c obj char: %c\u0026#34;\u003c/span\u003e,Aplayer,Aobj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e// comapre values\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            Aplayer \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            Aobj \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        ) detect \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e TRUE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;detection var: %d\u0026#34;\u003c/span\u003e,detect);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(detect \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e TRUE){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;collision detected\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e detect;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// do special task for each stage ---------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erainStage\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// If there are objs which are diesappered, add score.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// If collion is detected, reduce player hp    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);   \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// move rain\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// SPEED_OF_RAIN -\u0026gt; amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// numberOfFrame % (100 / SPEED_OF_RAIN) -\u0026gt; number of update in a sec \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_RAIN) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// Rondomly move rain without limitation -\u0026gt; fall movement\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[RAIN_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[obj_index].PreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[RAIN_STAGE].obj[obj_index].position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// make rain obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// add rain with random shapes\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// control number of new rain obj by if sentence blow\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e NUMEBR_OF_RAIN) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e stages[RAIN_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e AMOUNT_OF_RAIN){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make rain array\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// init the all array element with space\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e rain[RAIN_SIZE_Y][RAIN_SIZE_Y] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_Y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_X; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// rain[y][x] = \u0026#39;\u0026amp;\u0026#39;;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e random \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(x \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(random \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        rain[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        rain[y][x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(random \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        rain[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        rain[y][x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// create random position \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make not make same random num\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e randomPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e count \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (count \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e NUMBER_OF_RETRY)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            count\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e moreBreak \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e FALSE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            randomPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e width;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// avoid segmantation fault\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[RAIN_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                moreBreak \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e TRUE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[RAIN_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// check obj in same x position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[RAIN_STAGE].obj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e randomPosition \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// check how far from new obj in y aixs\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[RAIN_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_Y_SPACE\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// If there are no space enough, recreate random num \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: false random num is %d\u0026#34;\u003c/span\u003e,randomPosition);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[RAIN_STAGE].obj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_X_SPACE){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// If there are no space enough, recreate random num \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: false random num is %d\u0026#34;\u003c/span\u003e,randomPosition);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);                  \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;debug log: true  random num is %d\u0026#34;\u003c/span\u003e,randomPosition);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    moreBreak \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e TRUE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(moreBreak \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e TRUE) \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// allocate ram for new rain obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// set position. x position is random but y position is always being at 0.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {.x\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eRAIN_SIZE_X,.y\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eRAIN_SIZE_Y};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {.x\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003erandomPosition,.y\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ALLOCATION_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[RAIN_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(stages[RAIN_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[RAIN_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Graphic) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (AMOUNT_OF_RAIN \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// add rain obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_Y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_X; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rain[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }           \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// add rain obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_Y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e RAIN_SIZE_X; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[RAIN_STAGE].obj[stages[RAIN_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rain[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[RAIN_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show and update all rain graphics\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// separate code for in range version and out of range version\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// check in range or not\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[RAIN_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make and use show graphic function\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eshowGraphic\u003c/span\u003e(stages[RAIN_STAGE].obj[obj_index]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// add score as player is alive\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e score \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    score \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e (stages[RAIN_STAGE].timer \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e PLAYER_SCORE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e score;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewindStage\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// If there are objs which are diesappered, add score.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// If collion is detected, reduce player hp\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// move obj by wind\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e SPEED_OF_WIND_X \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_WIND_Y) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[obj_index].PreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[WIND_STAGE].obj[obj_index].position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// SPEED_OF_WIND_X -\u0026gt; amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e SPEED_OF_WIND_X \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e MOVEMENT_OF_OBJ_X;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// SPEED_OF_WIND_Y -\u0026gt; amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_WIND_Y) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[WIND_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[WIND_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// create new obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e NUMEBR_OF_BLOWN_AWAY_OBJ) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e stages[WIND_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e AMOUNT_OF_OBJ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// create random position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {.x\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,.y\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        position.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e height;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// create obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e choosenObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e stages[WIND_STAGE].numberOfPreparedObj;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003efig;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        fig \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[WIND_STAGE].PreparedObj[choosenObj].data;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ALLOCATION_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[WIND_STAGE].PreparedObj[choosenObj].size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[WIND_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(stages[WIND_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[WIND_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Graphic) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (AMOUNT_OF_OBJ \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// if size value is not set, cause segmantation fault\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// add rain obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fig[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }                \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// add rain obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[WIND_STAGE].obj[stages[WIND_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fig[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }               \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[WIND_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update graphics\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make and use show graphic function\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eshowGraphic\u003c/span\u003e(stages[WIND_STAGE].obj[obj_index]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// add score as player is alive\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e score \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    score \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e (stages[WIND_STAGE].timer \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e PLAYER_SCORE);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e score;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// move obj randomly -\u0026gt; in x and y aixs \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show random obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// count obj, disappered obj, appered obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// use count obj result to caculate score and then update player score\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esunnyStage\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// move obj randomly\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_POINT_X) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_POINT_Y) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj[obj_index].PreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[SUNNY_STAGE].obj[obj_index].position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// SPEED_OF_POINT_X -\u0026gt; amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_POINT_X) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].obj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].obj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// SPEED_OF_POINT_Y -\u0026gt; amount of movement in a sec\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e SPEED_OF_POINT_Y) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].obj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// create new obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)((\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e NUMEBR_OF_POINT) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e stages[SUNNY_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e AMOUNT_OF_POINT){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {.x\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003ewidth,.y\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e()\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003eheight};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// create obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e choosenObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003efig;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        fig \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[SUNNY_STAGE].PreparedObj[choosenObj].data;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Vector size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e stages[SUNNY_STAGE].PreparedObj[choosenObj].size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ALLOCATION_OK;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[SUNNY_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(stages[SUNNY_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (Graphic \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Graphic) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (AMOUNT_OF_POINT \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// add point obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fig[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }                \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e position;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            status \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// add point obj to stage obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(status \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ALLOCATION_OK){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.y ; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].size.x ; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        stages[SUNNY_STAGE].obj[stages[SUNNY_STAGE].numberOfObj].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fig[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }                               \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                stages[SUNNY_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;                \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update graphics\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; obj_index \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].numberOfObj; obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// make and use show graphic function\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eshowGraphic\u003c/span\u003e(stages[SUNNY_STAGE].obj[obj_index]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// do special task for each stage ---------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// show ui top left and right corner\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eShowStageUI\u003c/span\u003e(Stage stage,Player player){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector timerPosition,hpPosition,scorePosition,stageNamePosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    timerPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e; timerPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    hpPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e timerPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e; hpPosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    scorePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e hpPosition.y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e; scorePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    stageNamePosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e; stageNamePosition.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e timerText[\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e hpText[\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e scoreText[\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(timerText,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Time: %-3d/%-3d(sec)\u0026#34;\u003c/span\u003e,(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)stage.timer,stage.timeLimit);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(hpText,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;HP: %-3d\u0026#34;\u003c/span\u003e,player.hp);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(scoreText,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Score: %-3d\u0026#34;\u003c/span\u003e,player.currentStageScore \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e player.score);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(timerPosition.y,timerPosition.x,timerText);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(hpPosition.y,hpPosition.x,hpText);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(scorePosition.y,scorePosition.x,scoreText);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003emvaddstr\u003c/span\u003e(stageNamePosition.y,stageNamePosition.x,stage.name);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejumpPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// pi value should be between 0 and PLAYER_JUMP_MAX\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e temp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efloat\u003c/span\u003e pi \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e PLAYER_JUMP_MAX;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e height){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e height \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e lengthInOneFrame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)(playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    lengthInOneFrame \u003cspan style=\"color:#f92672\"\u003e/=\u003c/span\u003e PLAYER_JUMP_TIME;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e speed.y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e (playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)) player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003espeed.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e lengthInOneFrame;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e speed.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pi \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esin\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e speed.y \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e3.14f\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e (playerJumpHeight \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    temp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)height \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (pi \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e)playerJumpHeight);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)temp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtrolPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e keys;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// player can be controled by wasd keys\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003etimeout\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    keys \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetch\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ePreviousPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// jump\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(((keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;w\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003espeed.y \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e  \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejumpPlayer\u003c/span\u003e(player,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// move left and right in constant speed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;a\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e (player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ebody.size.x \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e PLAYER_SPEED;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(keys \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;d\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ebody.size.x) player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition.x \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e PLAYER_SPEED;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// update graphic position\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e body.position \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eCurrentPosition,player\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ebody.size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edetectHitPlayer\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedStage,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e collosion \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edetectHit\u003c/span\u003e(player,stages,selectedStage);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(collosion \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e TRUE \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e damageIntarval \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e OUT_DAMAGE_INTARVAL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (selectedStage)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e RAIN_STAGE:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eflash\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e DAMAGE_OF_RAIN;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e SUNNY_STAGE:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eflash\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e AMOUNT_OF_RACOVER;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e PLAYER_SCORE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e WIND_STAGE:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003eflash\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e DAMAGE_OF_OBJ;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Worng stage is selected. Check code.\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e damageIntarval \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e IN_DAMAGE_INTARVAL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e damageIntarval \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e IN_DAMAGE_INTARVAL) player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e datageIntarvalFrame \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e datageIntarvalFrame \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e DAMAGE_INTARVAL)){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e damageIntarval \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e OUT_DAMAGE_INTARVAL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e datageIntarvalFrame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(logs,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;damage intarval: %d\u0026#34;\u003c/span\u003e,player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e datageIntarvalFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edebugLog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e11\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,logs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshowPlayer\u003c/span\u003e(Player player){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// clear old player graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Vector oldBodyPosition \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclacBodyPosition\u003c/span\u003e(player.PreviousPosition,player.body.size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player.body.size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player.body.size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emove\u003c/span\u003e(y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e oldBodyPosition.y,x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e oldBodyPosition.x);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eaddch\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show player\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player.body.size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e player.body.size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emove\u003c/span\u003e(y \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e player.body.position.y,x \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e player.body.position.x);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eaddch\u003c/span\u003e(player.body.data[y][x]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// TODO: fix segmatation fualt after wind stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// call once when start button selected\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// make start_UI call this function when start button is selected. -\u0026gt; OK\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eStageLoop\u003c/span\u003e(Player \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer,Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedStage \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WIND_STAGE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e times \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; times \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e NUMBER_OF_GAME; times\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        selectedStage \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estageSelector\u003c/span\u003e(stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003einitStage\u003c/span\u003e(stages[selectedStage]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eclock_t\u003c/span\u003e start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003etime_t\u003c/span\u003e gameStartTime \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e(NULL);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edouble\u003c/span\u003e deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e numberOfFrame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e resizeHappn \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RESIZE_NOT_HAPPEND;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            start \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            resizeHappn \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// move -\u0026gt; update graphic -\u0026gt; collion detection\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003econtrolPlayer\u003c/span\u003e(player,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// show time hp score stage name -\u0026gt; OK\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eShowStageUI\u003c/span\u003e(stages[selectedStage],\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// update order\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// stage graphic -\u0026gt; player graphic\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(numberOfFrame \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e30\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) stages[selectedStage].\u003cspan style=\"color:#a6e22e\"\u003estageFunc\u003c/span\u003e(player,stages,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eshowPlayer\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// collsion system\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003edetectHitPlayer\u003c/span\u003e(player,stages,selectedStage,numberOfFrame);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003erefresh\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            numberOfFrame\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            delta \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclock\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e start; deltaf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclacTimeFromClock_t\u003c/span\u003e(delta);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[selectedStage].timer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edifftime\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003etime\u003c/span\u003e(NULL),gameStartTime);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(resizeHappn) resizeHappn \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RESIZE_NOT_HAPPEND;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eusleep\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eadjustTimer\u003c/span\u003e(deltaf));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(stages[selectedStage].timer \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e stages[selectedStage].timeLimit \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// all stage reqire addtional memory management\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003efreeObjGraphicRam\u003c/span\u003e(stages[selectedStage].obj,stages[selectedStage].numberOfObj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(stages[selectedStage].obj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[selectedStage].numberOfObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// stages[selectedStage].timer = 0;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esetStageParam\u003c/span\u003e(stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e score \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e currentStageScore \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(player \u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e hp \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// pass stage array whose size is 3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esetStageParam\u003c/span\u003e(Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// getmaxyx(stdscr,height,width);\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresizeDetect\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// rain stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[RAIN_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RAIN_STAGE_POSSIBLE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[RAIN_STAGE].timer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[RAIN_STAGE].timeLimit \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e RAIN_STAGE_TIME_LIMIT;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(stages[RAIN_STAGE].name,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rain stage\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// rain obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// obj will be used to manage rain obj in rain stage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// rain will be made by function and caculation\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// So in this function, I will not allocate \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].numberOfPreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].PreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// stage function pointer\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[RAIN_STAGE].stageFunc \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rainStage;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// rain stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// wind stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[WIND_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WIND_STAGE_POSSIBLE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[WIND_STAGE].timer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[WIND_STAGE].timeLimit \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WIND_STAGE_TIME_LIMIT;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(stages[WIND_STAGE].name,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;wind stage\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// blown away obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// rectangle obj 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].numberOfPreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Graphic) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; stages[WIND_STAGE].PreparedObj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].size.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;     stages[WIND_STAGE].PreparedObj[obj_index].size.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[WIND_STAGE].PreparedObj[obj_index]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e rectangle[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e][\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e}};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rectangle[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].numberOfPreparedObj \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// triangle obj 1 \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; stages[WIND_STAGE].PreparedObj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].size.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;     stages[WIND_STAGE].PreparedObj[obj_index].size.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[WIND_STAGE].PreparedObj[obj_index]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e triangle[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e][\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;a\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;b\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;B\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;b\u0026#39;\u003c/span\u003e}};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e triangle[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            obj_index\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].numberOfPreparedObj \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// hexagon? obj 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; stages[WIND_STAGE].PreparedObj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].PreparedObj[obj_index].size.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;     stages[WIND_STAGE].PreparedObj[obj_index].size.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[WIND_STAGE].PreparedObj[obj_index]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e hexagon[\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e][\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;*\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;J\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;L\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;A\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;L\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;J\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;*\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e}};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[WIND_STAGE].PreparedObj[obj_index].size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[WIND_STAGE].PreparedObj[obj_index].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e hexagon[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// stage function pointer\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[WIND_STAGE].stageFunc \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e windStage;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// wind stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// sunny stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[SUNNY_STAGE].possible \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e SUNNY_STAGE_POSSOIBLE;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[SUNNY_STAGE].timer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stages[SUNNY_STAGE].timeLimit \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e SUNNY_STAGE_TIME_LIMIT;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003esprintf\u003c/span\u003e(stages[SUNNY_STAGE].name,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sunny stage\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// point obj 0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// This obj give player score and point\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// If player miss this obj, these obj will not be score\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            obj_index \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].numberOfPreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].PreparedObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Graphic) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].PreparedObj[obj_index].position.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; stages[SUNNY_STAGE].PreparedObj[obj_index].position.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].PreparedObj[obj_index].size.x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;     stages[SUNNY_STAGE].PreparedObj[obj_index].size.y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eallocateGraphicRam\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e(stages[SUNNY_STAGE].PreparedObj[obj_index]));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e point[\u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e][\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e},\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;P\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e}};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; y \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].PreparedObj[obj_index].size.y; y\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; x \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e stages[SUNNY_STAGE].PreparedObj[obj_index].size.x; x\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    stages[SUNNY_STAGE].PreparedObj[obj_index].data[y][x] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e point[y][x];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }   \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].numberOfObj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].obj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// stage function pointer\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            stages[SUNNY_STAGE].stageFunc \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sunnyStage;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// synny stage --------------------------------------------------------------------------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e argc,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003e args){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e selectedMode \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e START_BUTTON;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Player player;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Stage \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estages; \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    stages \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(Stage) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003esetStageParam\u003c/span\u003e(stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003einitWholeGame\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// show start UI\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    selectedMode \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estartUI\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer); \u003cspan style=\"color:#75715e\"\u003e// OK\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedMode \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e START_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003einitPlayer\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer); \u003cspan style=\"color:#75715e\"\u003e// OK\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003eStageLoop\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer,stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// show end UI\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            selectedMode \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eendUI\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedMode \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e RETURN_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            selectedMode \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estartUI\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(selectedMode \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e END_BUTTON){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// end curses and free ram\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eendWholeGame\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eplayer,stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(stages);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"なんかC言語の授業で作ったプログラム"},{"content":"この記事を書いた動機 ssh サーバ (sshd) の設定のメモ の設定についてメモを書いたのと似たような動機で、sambaについても書いていく。疲れたので、説明も簡素に、とりあえずどんな設定にしているのかおいておくことにする。\nちなみにこれら設定は、プライベートネットワークでしか使うことを想定しておらず、外部に公開されるようなサーバでは使えない、セキュリティーホールになりえる設定になっている可能性が大いにあるので、注意する。\n/etc/samba/smb.conf # ネットワークドライブ名 [data] comment = data folder # ファイル共有する場所を指定 path = /Path/To/ShareFolder browsable = yes writable = yes guest ok = yes read only = no force create mode = 0777 create mask = 0777 # 全体共通の設定項目 [global] min protocol = SMB2 max protocol = SMB3 Workgroup = WORKGROUP netbios name = dataserverName log file = /Path/To/LogFile/%m.log log level = 1 wins support = yes domain master = yes ユーザの追加 ついでなので、samba のユーザの追加方法についてもよく忘れるので記録を取る。\nsmbpasswd -a [username] 関連性のありそうな記事 ssh サーバ (sshd) の設定のメモ\n参考にしたサイト 今回も自分のサーバの設定を見て、適当にどういう解釈で設定しているか記録を取っただけなので、特になし。\nSamba Add a User - nixCraft\nhttps://www.cyberciti.biz/faq/adding-a-user-to-a-samba-smb-share/ （2025年3月14日） ","permalink":"https://www.nyanmo.info/posts/linux/exampleofsambasettring/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　\u003ca href=\"https://www.nyanmo.info/posts/linux/exampleofsshdsetting/\"\u003essh サーバ (sshd) の設定のメモ\u003c/a\u003e の設定についてメモを書いたのと似たような動機で、sambaについても書いていく。疲れたので、説明も簡素に、とりあえずどんな設定にしているのかおいておくことにする。\u003c/p\u003e\n\u003cp\u003e　ちなみにこれら設定は、プライベートネットワークでしか使うことを想定しておらず、外部に公開されるようなサーバでは使えない、セキュリティーホールになりえる設定になっている可能性が大いにあるので、注意する。\u003c/p\u003e\n\u003ch2 id=\"etcsambasmbconf\"\u003e/etc/samba/smb.conf\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ネットワークドライブ名\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003edata\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        comment \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e data folder\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# ファイル共有する場所を指定\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        path \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e /Path/To/ShareFolder\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        browsable \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        writable \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        guest ok \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        read only \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e no\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        force create mode \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0777\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        create mask \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0777\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 全体共通の設定項目\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eglobal\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        min protocol \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e SMB2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        max protocol \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e SMB3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Workgroup \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WORKGROUP\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        netbios name \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e dataserverName\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        log file \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e /Path/To/LogFile/%m.log\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        log level \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        wins support \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        domain master \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e yes\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"ユーザの追加\"\u003eユーザの追加\u003c/h2\u003e\n\u003cp\u003e　ついでなので、samba のユーザの追加方法についてもよく忘れるので記録を取る。\u003c/p\u003e","title":"Samba を設定するメモ"},{"content":"この記事を書いた動機 最近、サーバーをセットアップする機会があって、sshd に関して最低限どんな設定をしていたか、忘れていたということがあった。そこではいちいち調べていたが、今後同じようなことがあったときのために、適当に記録しておくことにした。\nちなみに、今回以下に示す設定項目については、sshd のデフォルトの設定状態から、変更または追加した部分についてしか書いていない。使う linux ディストリビューション次第では、パッケージマネージャからインストールされる sshd のデフォルトのコンフィグの設定が地味に違う可能性があるので注意する。\n/etc/ssh/sshd_config # Include drop-in configurations Include /etc/ssh/sshd_config.d/*.conf ... # ルート（管理者権限を持ったアカウント）でログインさせない PermitRootLogin no # 公開鍵によるユーザ認証を許可する PubkeyAuthentication yes # パスワードによるユーザ認証は許可しない PasswordAuthentication no # キーボードインタラクティブによる認証を許可しない KbdInteractiveAuthentication no # 多分これはなくても \u0026#34;.ssh/authorized_keys\u0026#34; が公開鍵の保存場所としてデフォルトで認識されるが、今回は明示的に示している AuthorizedKeysFile .ssh/authorized_keys ... 関連性のありそうな記事 Samba を設定する\n参考にしたサイトとか 今回は自分のサーバの設定を見て、適当にどういう解釈で設定しているか記録を取っただけなので、特になし。\n","permalink":"https://www.nyanmo.info/posts/linux/exampleofsshdsetting/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　最近、サーバーをセットアップする機会があって、sshd に関して最低限どんな設定をしていたか、忘れていたということがあった。そこではいちいち調べていたが、今後同じようなことがあったときのために、適当に記録しておくことにした。\u003c/p\u003e\n\u003cp\u003e　ちなみに、今回以下に示す設定項目については、sshd のデフォルトの設定状態から、変更または追加した部分についてしか書いていない。使う linux ディストリビューション次第では、パッケージマネージャからインストールされる sshd のデフォルトのコンフィグの設定が地味に違う可能性があるので注意する。\u003c/p\u003e\n\u003ch2 id=\"etcsshsshd_config\"\u003e/etc/ssh/sshd_config\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Include drop-in configurations\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInclude /etc/ssh/sshd_config.d/*.conf\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ルート（管理者権限を持ったアカウント）でログインさせない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePermitRootLogin no\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 公開鍵によるユーザ認証を許可する\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePubkeyAuthentication yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# パスワードによるユーザ認証は許可しない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePasswordAuthentication no\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# キーボードインタラクティブによる認証を許可しない\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eKbdInteractiveAuthentication no\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 多分これはなくても \u0026#34;.ssh/authorized_keys\u0026#34; が公開鍵の保存場所としてデフォルトで認識されるが、今回は明示的に示している\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAuthorizedKeysFile      .ssh/authorized_keys\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"関連性のありそうな記事\"\u003e関連性のありそうな記事\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/linux/exampleofsambasettring/\"\u003eSamba を設定する\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイトとか\"\u003e参考にしたサイトとか\u003c/h2\u003e\n\u003cp\u003e　今回は自分のサーバの設定を見て、適当にどういう解釈で設定しているか記録を取っただけなので、特になし。\u003c/p\u003e","title":"ssh サーバ (sshd) の設定のメモ"},{"content":"この記事を書いた動機 httpd で公開している Web サイトのドキュメントルートに、icons というフォルダーを配置し、画像を扱おうとするとうまくいかないことがある。httpd デフォルトでは、事前に設定され用意された icons の方を参照してしまい、タブのアイコンや、画像とかが正しく表示されない。それで、二回も同じことにぶつかったというのもあり、メモを取ろうと思った次第。\nイメージ 設定前の様子 設定後の様子 httpd の設定 iconsのaliasは以下のようになっている。\n/etc/httpd/conf/extra/httpd-autoindex.conf ... Alias /icons/ \u0026#34;/usr/share/httpd/icons/\u0026#34; \u0026lt;Directory \u0026#34;/usr/share/httpd/icons\u0026#34;\u0026gt; Options Indexes MultiViews AllowOverride None Require all granted \u0026lt;/Directory\u0026gt; ... この alias を無効化するには、以下のように設定をコメントアウトして、httpd-autoindex.conf を読み込まないようにするだけで良い。\n/etc/httpd/conf/httpd.conf ... # 変更前 # Fancy directory listings Include conf/extra/httpd-autoindex.conf ... # 変更後 # Fancy directory listings # Include conf/extra/httpd-autoindex.conf ... 参考にしたサイト How to disable the indexing of the \u0026lsquo;icons\u0026rsquo; directory in your Apache HTTP Server | Our Code World\nhttps://ourcodeworld.com/articles/read/1437/how-to-disable-the-indexing-of-the-icons-directory-in-your-apache-http-server （2025年1月29日） linux - How do I remove the Apache \u0026ldquo;/icons/\u0026rdquo; and \u0026ldquo;/icons/small/\u0026rdquo; folder alias? - Super User\nhttps://superuser.com/questions/1713548/how-do-i-remove-the-apache-icons-and-icons-small-folder-alias （2025年1月29日） ","permalink":"https://www.nyanmo.info/posts/webdevelop/httpddisableiconsalias/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　httpd で公開している Web サイトのドキュメントルートに、icons というフォルダーを配置し、画像を扱おうとするとうまくいかないことがある。httpd デフォルトでは、事前に設定され用意された icons の方を参照してしまい、タブのアイコンや、画像とかが正しく表示されない。それで、二回も同じことにぶつかったというのもあり、メモを取ろうと思った次第。\u003c/p\u003e\n\u003ch2 id=\"イメージ\"\u003eイメージ\u003c/h2\u003e\n\u003ch3 id=\"設定前の様子\"\u003e設定前の様子\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/HttpdDisableIconsAlias/httpd%e3%83%87%e3%83%95%e3%82%a9%e3%83%ab%e3%83%88%e3%81%aeicons.png alt=設定前の様子/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch3 id=\"設定後の様子\"\u003e設定後の様子\u003c/h3\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/webDevelop/HttpdDisableIconsAlias/%e8%a8%ad%e5%ae%9a%e5%be%8c.png alt=設定後の様子/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\u003ch2 id=\"httpd-の設定\"\u003ehttpd の設定\u003c/h2\u003e\n\u003cp\u003e　iconsのaliasは以下のようになっている。\u003c/p\u003e\n\u003ch3 id=\"etchttpdconfextrahttpd-autoindexconf\"\u003e/etc/httpd/conf/extra/httpd-autoindex.conf\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAlias /icons/ \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/usr/share/httpd/icons/\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;Directory \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/usr/share/httpd/icons\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Options Indexes MultiViews\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    AllowOverride None\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Require all granted\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/Directory\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　この alias を無効化するには、以下のように設定をコメントアウトして、httpd-autoindex.conf を読み込まないようにするだけで良い。\u003c/p\u003e\n\u003ch3 id=\"etchttpdconfhttpdconf\"\u003e/etc/httpd/conf/httpd.conf\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 変更前\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Fancy directory listings\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInclude conf/extra/httpd-autoindex.conf\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 変更後\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Fancy directory listings\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Include conf/extra/httpd-autoindex.conf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHow to disable the indexing of the \u0026lsquo;icons\u0026rsquo; directory in your Apache HTTP Server | Our Code World\u003cbr\u003e\n\u003ca href=\"https://ourcodeworld.com/articles/read/1437/how-to-disable-the-indexing-of-the-icons-directory-in-your-apache-http-server\"\u003ehttps://ourcodeworld.com/articles/read/1437/how-to-disable-the-indexing-of-the-icons-directory-in-your-apache-http-server\u003c/a\u003e （2025年1月29日）\u003c/li\u003e\n\u003cli\u003elinux - How do I remove the Apache \u0026ldquo;/icons/\u0026rdquo; and \u0026ldquo;/icons/small/\u0026rdquo; folder alias? - Super User\u003cbr\u003e\n\u003ca href=\"https://superuser.com/questions/1713548/how-do-i-remove-the-apache-icons-and-icons-small-folder-alias\"\u003ehttps://superuser.com/questions/1713548/how-do-i-remove-the-apache-icons-and-icons-small-folder-alias\u003c/a\u003e （2025年1月29日）\u003c/li\u003e\n\u003c/ul\u003e","title":"Httpd で https://ドメイン名/Icons が意図しない所へ飛ばされ、正常に画像を表示できない。"},{"content":"この記事を書いた動機 最近、個人的に自分用の Web アプリみたいなのを作っている過程において、スマホ上の Firefox でそのサービスにアクセスしたとき、https の認証局エラーが出てしまうということがあった。それで、認証局の設定自体は、Android OS 側にすでにその時点でしていたものの、反映されていないことに気づく。\n調べてみると、分かりずらそうな設定が必要そうだったため、一応備忘録的に何か書き残しておこうと思ったわけである。ちなみに、Google Chrome では OS 側のインストールした認証局をデフォルトで使ってくれるようなので、証明局をインストールしたらそれ以上の特別な操作はいらないようである。\n環境や必要なものとか Android 14\nPixel 5a (5G)\nmkcert を使っている\n事前に何かしらの方法でスマホにファイル転送し Web サーバの証明書を送ることができる\nWebサーバの証明書 (rootCA.cer みたいなやつ)\n# 証明書の中身のイメージ -----BEGIN CERTIFICATE----- MIIEfjCCAuagAwIBAgIRAMVjx+WAxkODxA9i82cg1f8wDQYJKoZIhv... ... 何かしらのデータ ... VzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRYwFAYDVQ... -----END CERTIFICATE----- https通信をプライベートネットワークで使いたいも参照するといいかも？\n作業する前の状態 以下のように証明書のエラーを無視すれば、とりあえず Web ページは開けるが気持ち悪いことになる。\nやり方 認証局のインストール まずは Android OS 側に https 通信時などに参照される証明書ストアなるものが搭載されているので、そこへ自分ででっち上げた証明書をインストールする。\n\u0026ldquo;セキュリティとプライバシー\u0026quot;の項目を開く\n\u0026ldquo;その他のセキュリティとプライバシー\u0026quot;の項目を開く\n\u0026ldquo;暗号化と認証情報\u0026quot;の項目を開く \u0026ldquo;証明書のインストール\u0026quot;の項目を開く\n\u0026ldquo;CA証明書\u0026quot;の項目を開く\n\u0026ldquo;インストール\u0026quot;を選び、事前に用意した証明書を入れる 隠された設定を有効にする 次に、Firefox Android 側でインストールした証明書を使う様に設定する。その過程で、まずは開発者モードみたいなのを有効にする必要がある。\n通常どうりに Firefox の設定を開く\n一番下までスクロールする\n\u0026ldquo;Firefoxについて\u0026rdquo; を開く Firefoxのアイコンを、以下のように開発者モードが有効になるまでタップし続ける\n開発者モードが有効になった旨のポップアップが出てくる サードパーティーの証明書を有効化 次に、設定画面に戻り、開発者設定を開く。\n新たに出現した開発者モードの項目のうち、\u0026ldquo;Secret Settings\u0026rdquo; という項目を開く \u0026ldquo;Use thired party CA certificates\u0026rdquo; の項目を有効にする 動くようになる 最終的に以下のようになり、https の証明書エラーが出て来なければ成功していると思われる。 参考にしたサイト Firefoxブラウザへのセキュリティ証明書の手動インストール | AdGuard Knowledge Base\nhttps://adguard.com/kb/ja/adguard-for-android/solving-problems/firefox-certificates/ （2025年1月15日） Allow personal certificates in Firefox mobile - Mozilla Connect\nhttps://connect.mozilla.org/t5/ideas/allow-personal-certificates-in-firefox-mobile/idi-p/176 （2025年1月15日） Adding custom certificate authorities to Firefox on Android - kcore.org\nhttps://kcore.org/2022/06/19/firefox-custom-ca/ （2025年1月15日） ","permalink":"https://www.nyanmo.info/posts/android/firefox/personalca/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　最近、個人的に自分用の Web アプリみたいなのを作っている過程において、スマホ上の Firefox でそのサービスにアクセスしたとき、https の認証局エラーが出てしまうということがあった。それで、認証局の設定自体は、Android OS 側にすでにその時点でしていたものの、反映されていないことに気づく。\u003c/p\u003e\n\u003cp\u003e　調べてみると、分かりずらそうな設定が必要そうだったため、一応備忘録的に何か書き残しておこうと思ったわけである。ちなみに、Google Chrome では OS 側のインストールした認証局をデフォルトで使ってくれるようなので、証明局をインストールしたらそれ以上の特別な操作はいらないようである。\u003c/p\u003e\n\u003ch2 id=\"環境や必要なものとか\"\u003e環境や必要なものとか\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAndroid 14\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ePixel 5a (5G)\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emkcert を使っている\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e事前に何かしらの方法でスマホにファイル転送し Web サーバの証明書を送ることができる\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eWebサーバの証明書 (rootCA.cer みたいなやつ)\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 証明書の中身のイメージ\n-----BEGIN CERTIFICATE-----\nMIIEfjCCAuagAwIBAgIRAMVjx+WAxkODxA9i82cg1f8wDQYJKoZIhv...\n...\n何かしらのデータ\n...\nVzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMRYwFAYDVQ...\n-----END CERTIFICATE-----\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/webdevelop/httpswithlocalnet/\"\u003ehttps通信をプライベートネットワークで使いたい\u003c/a\u003eも参照するといいかも？\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"作業する前の状態\"\u003e作業する前の状態\u003c/h2\u003e\n\u003cp\u003e　以下のように証明書のエラーを無視すれば、とりあえず Web ページは開けるが気持ち悪いことになる。\u003c/p\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/android/firefox/personalCA/beforeSetting.png alt=設定前の状態/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/android/firefox/personalCA/beforeSetting1-1.png alt=設定前の状態1/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/android/firefox/personalCA/beforeSetting1.png alt=設定前の状態2/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/android/firefox/personalCA/beforeSetting2.png alt=設定前の状態3/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"やり方\"\u003eやり方\u003c/h2\u003e\n\u003ch3 id=\"認証局のインストール\"\u003e認証局のインストール\u003c/h3\u003e\n\u003cp\u003e　まずは Android OS 側に https 通信時などに参照される証明書ストアなるものが搭載されているので、そこへ自分ででっち上げた証明書をインストールする。\u003c/p\u003e","title":"Mobile Firefox で個人的に証明局を追加する"},{"content":"この記事を書いた動機 自分用のメモとして、実際にやったことを記録し、ノートを取るみたいな感じにしたいと思ったのと、私は、自分用のWebアプリみたいなのを開発しているのだが、その過程でスマホ版のブラウザでのデバックをしたくなったというのがある。\n二番煎じではあるが、他のブログでの説明はなんか画像とか少なくて不満があったというのもあり、ならば自分でやってみたらというところも経緯としてある。（自分も人のこと言えたほど大したこと書けないけど。。。）\n環境 スマホ側 Pixel 5a 5G Android版 Chrome 131 Android 14 PC側 Windows 11 (linux環境でも同じことはできると思う) Windows版 Chrome 131 イメージ 概要 adb コマンドの環境構築 USBデバックの接続 PCで chrome://inspect/#devicesを開く デバックしたいタブを選択して終わり デバックの仕方 adb をインストールする（PC側） 開発ツールをダウンロード\n今回は、以下のページから\u0026quot;platform-tools-latest-windows.zip\u0026quot;をダウンロード\nSDK Platform-Tools リリースノート | Android Studio | Android Developers\n開発ツールを展開と配置する 適当な場所（ダウンロード）とかで展開し、配置する。今回は、\u0026ldquo;C:\u0026quot;直下に開発者ツールを配置することとする。\n# ダウンロードして展開したフォルダの中に入っている、\u0026#34;platform-tools\u0026#34;を以下の様な形になるように配置する (base) PS C:\\\u0026gt; ls platform-tools Directory: C:\\platform-tools Mode LastWriteTime Length Name ---- ------------- ------ ---- -a--- 2025/01/11 0:20 5969000 adb.exe -a--- 2025/01/11 0:20 108136 AdbWinApi.dll -a--- 2025/01/11 0:20 73320 AdbWinUsbApi.dll -a--- 2025/01/11 0:20 451688 etc1tool.exe -a--- 2025/01/11 0:20 1874536 fastboot.exe -a--- 2025/01/11 0:20 54376 hprof-conv.exe -a--- 2025/01/11 0:20 242968 libwinpthread-1.dll -a--- 2025/01/11 0:20 479848 make_f2fs_casefold.exe -a--- 2025/01/11 0:20 479848 make_f2fs.exe -a--- 2025/01/11 0:20 1157 mke2fs.conf -a--- 2025/01/11 0:20 756840 mke2fs.exe -a--- 2025/01/11 0:20 1089833 NOTICE.txt -a--- 2025/01/11 0:20 38 source.properties -a--- 2025/01/11 0:20 2912360 sqlite3.exe 環境変数を設定する\n設定画面を開く Path の環境変数を編集する 補足 ＠ 自分のアカウントでのみツールを使いたいとき ユーザー固有の環境変数として設定する。 ＠ どのアカウントでもツールを使いたいとき システム全体で設定される環境変数を設定する。 adb.exe が入っている場所を追加する コマンドが使えるのか確認 開発者モードを有効にする （スマホ側） 前提（一応） 設定を開いた直後に表示されるホーム画面にいることを前提としてこの項は書いていく。スマホメーカーによっては違いがあるかもしれないが、基本的にはビルド番号を連打してやれば、開発者モードを有効にできると思われる。その他メーカー固有の方法については、きりがないので割愛する。 「デバイス情報」を開く 「ビルド番号」の項をポップアップが出てくるまでひたすら連打する ポップアップが出てくる USB debug を有効にする（スマホ側） 前提（一応） ここも、設定を開いた直後に表示されるホーム画面にいることを前提として書いていく。 「システム」を開く 開発者オプションを開く 開発者オプションが有効になっているか確認 USBデバックの項を有効にする USB debug を接続する PCとスマホをUSBで接続\nさすがにここは画像は割愛する。\nadbサーバーを立ち上げる（PC側）\nこの時点ではスマホ側から許可を出していないので、Unauthorizedとなりデバックできない。 USBデバックの許可をする（スマホ側）\nUSBデバックができるようになる（PC側）\ndevicesとなれば、許可が下りてデバックできる状態になっている。 スマホ側からデバックしたいサイトを開く（スマホ側） スマホ側の Google Chrome から、デバックしたいサイトを開く。 PC 側から開発者ツールを開く（PC側） 開発者ツールを開く Google Chromeから以下のURLのページへ飛ぶ。 chrome://inspect/#devices デバックしたいタブを開く 通常どうりのChromeの開発者ツールが開かれる 参考にしたサイト Android版の Chrome / Firefox で開発者ツールを使う。\nfreefielder.jp https://freefielder.jp/blog/2017/07/android-chrome-firefox-dev-tools.html （2025年1月11日） Android Debug Bridge（ADB） | Android Open Source Project\nhttps://source.android.com/docs/setup/build/adb?hl=ja#download-adb （2025年1月11日） SDK Platform-Tools リリースノート | Android Studio | Android Developers\nhttps://developer.android.com/tools/releases/platform-tools?hl=ja#downloads （2025年1月11日） ","permalink":"https://www.nyanmo.info/posts/android/chrome/debug/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　自分用のメモとして、実際にやったことを記録し、ノートを取るみたいな感じにしたいと思ったのと、私は、自分用のWebアプリみたいなのを開発しているのだが、その過程でスマホ版のブラウザでのデバックをしたくなったというのがある。\u003c/p\u003e\n\u003cp\u003e　二番煎じではあるが、他のブログでの説明はなんか画像とか少なくて不満があったというのもあり、ならば自分でやってみたらというところも経緯としてある。（自分も人のこと言えたほど大したこと書けないけど。。。）\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003ch3 id=\"スマホ側\"\u003eスマホ側\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003ePixel 5a 5G\u003c/li\u003e\n\u003cli\u003eAndroid版 Chrome 131\u003c/li\u003e\n\u003cli\u003eAndroid 14\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"pc側\"\u003ePC側\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eWindows 11 (linux環境でも同じことはできると思う)\u003c/li\u003e\n\u003cli\u003eWindows版 Chrome 131\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"イメージ\"\u003eイメージ\u003c/h2\u003e\n\n\n\n\n\u003cdiv class=\"alignContaier\" style=justify-content:\u0026#32;center;\u0026#32;overflow:\u0026#32;auto;\u0026#32;display:flex;\u0026#32;flex-direction:\u0026#32;%!s(\u0026lt;nil\u0026gt;);\u003e\n    \n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/android/chrome/debug/PC/exDevTools.png alt=DevToolsをPC側で開いた例/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \n    \u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n        \n        \n    \n        \u003cdiv style=\"width: 100%;\"\u003e\n            \u003cimg style=\"margin:10px;\" src=/posts/android/chrome/debug/android/openTargetURL.png alt=スマホ側のChromeで、デバックしたいサイトを開いた例/\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\n\u003c/div\u003e\n\u003ch2 id=\"概要\"\u003e概要\u003c/h2\u003e\n\u003col\u003e\n\u003cli\u003eadb コマンドの環境構築\u003c/li\u003e\n\u003cli\u003eUSBデバックの接続\u003c/li\u003e\n\u003cli\u003ePCで \u003ccode\u003echrome://inspect/#devices\u003c/code\u003eを開く\u003c/li\u003e\n\u003cli\u003eデバックしたいタブを選択して終わり\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"デバックの仕方\"\u003eデバックの仕方\u003c/h2\u003e\n\u003ch3 id=\"adb-をインストールするpc側\"\u003eadb をインストールする（PC側）\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e開発ツールをダウンロード\u003cbr\u003e\n　今回は、以下のページから\u0026quot;platform-tools-latest-windows.zip\u0026quot;をダウンロード\u003cbr\u003e\n　\u003ca href=\"https://developer.android.com/tools/releases/platform-tools?hl=ja#downloads\"\u003eSDK Platform-Tools リリースノート  |  Android Studio  |  Android Developers\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e開発ツールを展開と配置する\n　適当な場所（ダウンロード）とかで展開し、配置する。今回は、\u0026ldquo;C:\u0026quot;直下に開発者ツールを配置することとする。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# ダウンロードして展開したフォルダの中に入っている、\u0026#34;platform-tools\u0026#34;を以下の様な形になるように配置する\n\n(base) PS C:\\\u0026gt; ls platform-tools\n\n    Directory: C:\\platform-tools\n\nMode                 LastWriteTime         Length Name\n----                 -------------         ------ ----\n-a---          2025/01/11     0:20        5969000 adb.exe\n-a---          2025/01/11     0:20         108136 AdbWinApi.dll\n-a---          2025/01/11     0:20          73320 AdbWinUsbApi.dll\n-a---          2025/01/11     0:20         451688 etc1tool.exe\n-a---          2025/01/11     0:20        1874536 fastboot.exe\n-a---          2025/01/11     0:20          54376 hprof-conv.exe\n-a---          2025/01/11     0:20         242968 libwinpthread-1.dll\n-a---          2025/01/11     0:20         479848 make_f2fs_casefold.exe\n-a---          2025/01/11     0:20         479848 make_f2fs.exe\n-a---          2025/01/11     0:20           1157 mke2fs.conf\n-a---          2025/01/11     0:20         756840 mke2fs.exe\n-a---          2025/01/11     0:20        1089833 NOTICE.txt\n-a---          2025/01/11     0:20             38 source.properties\n-a---          2025/01/11     0:20        2912360 sqlite3.exe\n\u003c/code\u003e\u003c/pre\u003e\u003col start=\"3\"\u003e\n\u003cli\u003e\n\u003cp\u003e環境変数を設定する\u003c/p\u003e","title":"Android版 Chrome でデバックする"},{"content":"この記事を書いた動機 ただ単に、すぐに気づけなかったけど、後々気づいたことがあったので、それを記録するだけです。具体的には、Gnome の mutter において、ネットワークドライブ上を参照している場合においても、サムネイルを表示するようにすることについて、記事を書いていく予定です。\nGnome Mutter と ネットワーク共有フォルダ デフォルトの設定 gnome mutter ではデフォルトで、ネットワーク共有フォルダの中身のサムネイルなどを表示しない。 サムネイルを表示する設定に変更 以下の画面で、サムネを表示したりその他情報についてどうするか、設定できる。デフォルトでは、全ての項目がトラブルを避けるためか、ネットワーク共有フォルダなどを含まない、端末上のディスク内にしか機能しないように設定されている。\n設定を開く サムネイルを表示するように設定を変更 変更後の様子　設定を変更し、ネットワーク共有フォルダ等をのぞいてみると、サムネイルなどが見えるようになったりする。 参考にしたサイト ただ気づいたことを書いただけなので特になし。 ","permalink":"https://www.nyanmo.info/posts/linux/gnomemuttersettingsforsmbshare/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　ただ単に、すぐに気づけなかったけど、後々気づいたことがあったので、それを記録するだけです。具体的には、Gnome の mutter において、ネットワークドライブ上を参照している場合においても、サムネイルを表示するようにすることについて、記事を書いていく予定です。\u003c/p\u003e\n\u003ch2 id=\"gnome-mutter-と-ネットワーク共有フォルダ\"\u003eGnome Mutter と ネットワーク共有フォルダ\u003c/h2\u003e\n\u003ch3 id=\"デフォルトの設定\"\u003eデフォルトの設定\u003c/h3\u003e\n\u003cp\u003e　gnome mutter ではデフォルトで、ネットワーク共有フォルダの中身のサムネイルなどを表示しない。\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/gnomeMutterSettingsForSMBShare/before.png alt=設定変更前の様子/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch3 id=\"サムネイルを表示する設定に変更\"\u003eサムネイルを表示する設定に変更\u003c/h3\u003e\n\u003cp\u003e　以下の画面で、サムネを表示したりその他情報についてどうするか、設定できる。デフォルトでは、全ての項目がトラブルを避けるためか、ネットワーク共有フォルダなどを含まない、端末上のディスク内にしか機能しないように設定されている。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e設定を開く\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/gnomeMutterSettingsForSMBShare/step1.png alt=設定を開く/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eサムネイルを表示するように設定を変更\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/gnomeMutterSettingsForSMBShare/step2.png alt=サムネイルが表示されない設定になっている様子/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/gnomeMutterSettingsForSMBShare/step3.png alt=サムネイルがネットワークドライブ上を参照していても、見えるように設定/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"変更後の様子\"\u003e変更後の様子　\u003c/h3\u003e\n\u003cp\u003e　設定を変更し、ネットワーク共有フォルダ等をのぞいてみると、サムネイルなどが見えるようになったりする。\n\n\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; flex-direction: row;\"\u003e\n    \n    \n\n    \u003cdiv style=\"width: 100%;\"\u003e\n        \u003cimg style=\"margin:10px;\" src=/posts/linux/gnomeMutterSettingsForSMBShare/after.png alt=設定後の様子/\u003e\n        \n    \u003c/div\u003e\n\u003c/div\u003e\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eただ気づいたことを書いただけなので特になし。\u003c/li\u003e\n\u003c/ul\u003e","title":"Gnome Mutter と ネットワーク共有フォルダ(SMB CIFS)"},{"content":"ここはどこ？ テストも兼ねて、適当に何も考えないで脳死で書いたりした絵を置くだけの、存在意義不明な、絵が置かれるだけの場所です、、、\n画像たち ゆっくりれいむ？？？ ゆっくりれいむもどき (2024/12/31)with XPS 15 2-in-1 (9575), HP Active Style Pen (Gen3) and 釘で作ったペン先、、、\nなんかよくわかんない絵 (nyanmo) なんかよくわかんない絵 (2025/02/07)ゆっくりがベースになってる仕上がりになった？\nなんかよくわかんない絵ジト目口開き2 (2025/02/11)差分を作ってみた\nなんかよくわかんない絵 なんか足りないので付け足した (2025/04/13)後ろにも髪があることをわすれていたような\n","permalink":"https://www.nyanmo.info/images/freedraw/","summary":"\u003ch2 id=\"ここはどこ\"\u003eここはどこ？\u003c/h2\u003e\n\u003cp\u003e　テストも兼ねて、適当に何も考えないで脳死で書いたりした絵を置くだけの、存在意義不明な、絵が置かれるだけの場所です、、、\u003c/p\u003e\n\u003ch2 id=\"画像たち\"\u003e画像たち\u003c/h2\u003e\n\u003ch3 id=\"ゆっくりれいむ\"\u003eゆっくりれいむ？？？\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/freedraw/test.png#center\"\n         alt=\"with XPS 15 2-in-1 (9575), HP Active Style Pen (Gen3) and 釘で作ったペン先、、、\"/\u003e \u003cfigcaption\u003e\n            ゆっくりれいむもどき (2024/12/31)\u003cp\u003ewith XPS 15 2-in-1 (9575), HP Active Style Pen (Gen3) and 釘で作ったペン先、、、\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003ch3 id=\"なんかよくわかんない絵-nyanmo\"\u003eなんかよくわかんない絵 (nyanmo)\u003c/h3\u003e\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/freedraw/%e3%81%aa%e3%82%93%e3%81%8b%e3%82%88%e3%81%8f%e3%82%8f%e3%81%8b%e3%82%93%e3%81%aa%e3%81%84%e7%b5%b5.png#center\"\n         alt=\"ゆっくりがベースになってる仕上がりになった？\"/\u003e \u003cfigcaption\u003e\n            なんかよくわかんない絵 (2025/02/07)\u003cp\u003eゆっくりがベースになってる仕上がりになった？\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/freedraw/%e3%81%aa%e3%82%93%e3%81%8b%e3%82%88%e3%81%8f%e3%82%8f%e3%81%8b%e3%82%93%e3%81%aa%e3%81%84%e7%b5%b5%e3%82%b8%e3%83%88%e7%9b%ae%e5%8f%a3%e9%96%8b%e3%81%8d2.png#center\"\n         alt=\"差分を作ってみた\"/\u003e \u003cfigcaption\u003e\n            なんかよくわかんない絵ジト目口開き2 (2025/02/11)\u003cp\u003e差分を作ってみた\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e\n\n\u003cfigure class=\"align-center \"\u003e\n    \u003cimg loading=\"lazy\" src=\"/images/freedraw/%e3%81%aa%e3%82%93%e3%81%8b%e3%82%88%e3%81%8f%e3%82%8f%e3%81%8b%e3%82%93%e3%81%aa%e3%81%84%e7%b5%b5%20%e3%81%aa%e3%82%93%e3%81%8b%e8%b6%b3%e3%82%8a%e3%81%aa%e3%81%84%e3%81%ae%e3%81%a7%e4%bb%98%e3%81%91%e8%b6%b3%e3%81%97%e3%81%9f.png#center\"\n         alt=\"後ろにも髪があることをわすれていたような\"/\u003e \u003cfigcaption\u003e\n            なんかよくわかんない絵 なんか足りないので付け足した (2025/04/13)\u003cp\u003e後ろにも髪があることをわすれていたような\u003c/p\u003e\n        \u003c/figcaption\u003e\n\u003c/figure\u003e","title":"らくがき"},{"content":"この記事を書いた動機 (Nov 14 あたりの出来事) 最近、HP Proliant ML 150 (9 Gen) の消費電力削減の目的で、休止状態を利用できるようにしようとした過程で、それが正しく機能しているのか調べたくなった。そこで、ただメモリをたくさん指定した量だけ消費するプログラムを作成し、とりあえず動くところまで作ったので、ここに置いておこうというわけである。どこまで意味があるのかは不明。\nちなみに、一応メモリ割り当てに失敗したとき用に、再度メモリ割り当てを試みる機能や、メモリ割り当てに完全に失敗したときにプログラムを終了するなど、セーフティも実装しているが、結局使うことはなかったので正しく動く保証はない。\n使い方 プログラムのコンパイル gcc useram.c -o useram プログラムの利用 # 10 GB のメモリを埋めるときの例 useram 10 Too many ram will be allocated by your request. denied operation. と出てくる時 プログラム内の定数 margin の大きさが大きすぎる可能性があるので、適宜調整する。 後は単純に、実装されているメモリサイズより大きなサイズを指定してしまっているので、小さい値で再度プログラムを実行してみる。 プログラム本体 #include \u0026lt;stdio.h\u0026gt; #include \u0026lt;stdlib.h\u0026gt; #include \u0026lt;sys/sysinfo.h\u0026gt; // unit GB #define margin 10 #define retry 3 // Get the amount of entire installed RAM. // No args are required. // return: amount of entire installed RAM int checkRAM(){ unsigned int amount = 0; // GB struct sysinfo info; sysinfo(\u0026amp;info); // convert unit byte to Giga byte (10^9) amount = info.totalram / 1000 / 1000 / 1000; return amount; } // allocate RAM (amount GB) // args:(Unit -\u0026gt; GB) // amount: allocation size\tunsigned int // maxAmount: entire system RAM amount\tunsigned int // return: // pointer:\tpointer to allocated area\tvoid* //\tIf all ram allocation attempts are failed, return NULL. void* allocateRAM(unsigned int amount, unsigned int maxAmount){ // find specified allocation size is exceed entire system RAM amount or not. if(amount \u0026gt;= maxAmount - margin){ printf(\u0026#34;Too many ram will be allocated by your request. denied operation.\\n\u0026#34;); return 0; } // allocate ram but still the allocated area is not utilized. unsigned long allocateSize = (long)sizeof(char) * (long)amount * (long)1000 * (long)1000 * (long)1000; void* pointer = (void*)malloc(allocateSize); // retry ram allcation if it is failed. if(pointer == NULL){ printf(\u0026#34;ram allocation is failed. retry %d times\\n\u0026#34;,retry); int counter = 0; while(pointer == NULL \u0026amp;\u0026amp; counter \u0026lt; retry){ printf(\u0026#34;retry %d\\n\u0026#34;,counter); void* pointer = (void*)malloc(allocateSize); counter++; } } // If all ram allocation attempts are failed, return NULL. if(pointer == NULL){ printf(\u0026#34;allocation failed!\\n\u0026#34;); return NULL; } printf(\u0026#34;allocation OK\\n\u0026#34;); return pointer; } // amount unit GB void useRAM(void* pointer,unsigned int amount){ // 4 mean size of int unsigned long loopAmount = (long)amount * (long)1000 * (long)1000 * (long)1000 / (long) 4; int* arr = (int*)pointer; // For each loop, fill up the allocated area with random value by 4 byte(size of int) for(unsigned long i = 0; i \u0026lt; loopAmount; i++){ arr[i] = (int)rand(); } printf(\u0026#34;Loop amount %lu\\n\u0026#34;,loopAmount); printf(\u0026#34;RAM area is filled up. The process is finished.\\n\u0026#34;); return; } int main(int argc,char **argv){ // find entire system ram unsigned int ramAmount = checkRAM(); // If The allocation size is not specified, exit this program. if(argc \u0026lt;= 1){ printf(\u0026#34; The size of ram amount that will be filled up is not specified. (GB)\\n\u0026#34;); return -1; } unsigned int amount = atoi(argv[1]); // find correct value is entered or not if(amount != 0){ printf(\u0026#34;%d GB\\n\u0026#34;,amount); }else{ printf(\u0026#34;You may enter string or 0 as args. Stop.\\n\u0026#34;); return -1; } printf(\u0026#34;System info: \\n %d GB RAM is installed\\n\u0026#34;,ramAmount); // ram allocation and filling up process void* pointer = allocateRAM(amount,ramAmount); useRAM(pointer,amount); // If ram allocation is failed, exit this program if(pointer == NULL) { printf(\u0026#34;went worng\\n\u0026#34;); return -1; } // wait until get user input. // The filled up RAM area will not be free while there is no user input for \u0026#39;q\u0026#39; key. char input = \u0026#39;a\u0026#39;; while(input != \u0026#39;q\u0026#39;) scanf(\u0026#34;%c\u0026#34;,\u0026amp;input); free(pointer); return 0; } 参考にしたサイト How to determine memory size via C code - Stack Overflow\nhttps://stackoverflow.com/questions/45259131/how-to-determine-memory-size-via-c-code （2024年12月12日） ","permalink":"https://www.nyanmo.info/posts/linux/hibernatecheck/","summary":"\u003ch2 id=\"この記事を書いた動機-nov-14-あたりの出来事\"\u003eこの記事を書いた動機 (Nov 14 あたりの出来事)\u003c/h2\u003e\n\u003cp\u003e　最近、HP Proliant ML 150 (9 Gen) の消費電力削減の目的で、休止状態を利用できるようにしようとした過程で、それが正しく機能しているのか調べたくなった。そこで、ただメモリをたくさん指定した量だけ消費するプログラムを作成し、とりあえず動くところまで作ったので、ここに置いておこうというわけである。どこまで意味があるのかは不明。\u003c/p\u003e\n\u003cp\u003e　ちなみに、一応メモリ割り当てに失敗したとき用に、再度メモリ割り当てを試みる機能や、メモリ割り当てに完全に失敗したときにプログラムを終了するなど、セーフティも実装しているが、結局使うことはなかったので正しく動く保証はない。\u003c/p\u003e\n\u003ch2 id=\"使い方\"\u003e使い方\u003c/h2\u003e\n\u003ch3 id=\"プログラムのコンパイル\"\u003eプログラムのコンパイル\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcc useram.c -o useram\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"プログラムの利用\"\u003eプログラムの利用\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 10 GB のメモリを埋めるときの例\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euseram \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"too-many-ram-will-be-allocated-by-your-request-denied-operation-と出てくる時\"\u003eToo many ram will be allocated by your request. denied operation. と出てくる時\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eプログラム内の定数 margin の大きさが大きすぎる可能性があるので、適宜調整する。\u003c/li\u003e\n\u003cli\u003e後は単純に、実装されているメモリサイズより大きなサイズを指定してしまっているので、小さい値で再度プログラムを実行してみる。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"プログラム本体\"\u003eプログラム本体\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-C\" data-lang=\"C\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stdio.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stdlib.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;sys/sysinfo.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// unit GB\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define margin 10\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define retry 3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// Get the amount of entire installed RAM.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// No args are required.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// return: amount of entire installed RAM\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echeckRAM\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e amount \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e// GB\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e sysinfo info;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003esysinfo\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003einfo);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// convert unit byte to Giga byte (10^9)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\tamount \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e info.totalram \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e amount;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// allocate RAM (amount GB)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// args:(Unit -\u0026gt; GB)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// \t\tamount: \tallocation size\t\t\t\tunsigned int\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// \t\tmaxAmount: \tentire system RAM amount\tunsigned int\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// return:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// \t\tpointer:\tpointer to allocated area\tvoid*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\t\t\t\t\tIf all ram allocation attempts are failed, return NULL.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateRAM\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e amount, \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e maxAmount){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// find specified allocation size is exceed entire system RAM amount or not.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(amount \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e maxAmount \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e margin){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Too many ram will be allocated by your request. denied operation.\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// allocate ram but still the allocated area is not utilized.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e allocateSize \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)amount \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e pointer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(allocateSize);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// retry ram allcation if it is failed.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(pointer \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ram allocation is failed. retry %d times\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,retry);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e counter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(pointer \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e counter \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e retry){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;retry %d\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,counter);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\t\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e pointer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003emalloc\u003c/span\u003e(allocateSize);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\tcounter\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// If all ram allocation attempts are failed, return NULL.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(pointer \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;allocation failed!\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;allocation OK\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e pointer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// amount unit GB\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euseRAM\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e pointer,\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e amount){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// 4 mean size of int\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e loopAmount \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)amount \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e) \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e arr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)pointer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// For each loop, fill up the allocated area with random value by 4 byte(size of int)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e loopAmount; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\tarr[i] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003erand\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Loop amount %lu\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,loopAmount);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;RAM area is filled up. The process is finished.\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e argc,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003eargv){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// find entire system ram\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e ramAmount \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echeckRAM\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// If The allocation size is not specified, exit this program.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(argc \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34; The size of ram amount that will be filled up is not specified. (GB)\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e amount \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eatoi\u003c/span\u003e(argv[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// find correct value is entered or not\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(amount \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%d GB\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,amount);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;You may enter string or 0 as args. Stop.\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;System info: \u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e %d GB RAM is installed\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,ramAmount);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// ram allocation and filling up process\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e pointer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eallocateRAM\u003c/span\u003e(amount,ramAmount);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003euseRAM\u003c/span\u003e(pointer,amount);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// If ram allocation is failed, exit this program\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(pointer \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;went worng\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// wait until get user input.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#75715e\"\u003e// The filled up RAM area will not be free while there is no user input for \u0026#39;q\u0026#39; key.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e input \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;a\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(input \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;q\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003escanf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%c\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003einput);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#a6e22e\"\u003efree\u003c/span\u003e(pointer);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\t\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eHow to determine memory size via C code - Stack Overflow\u003cbr\u003e\n\u003ca href=\"https://stackoverflow.com/questions/45259131/how-to-determine-memory-size-via-c-code\"\u003ehttps://stackoverflow.com/questions/45259131/how-to-determine-memory-size-via-c-code\u003c/a\u003e （2024年12月12日）\u003c/li\u003e\n\u003c/ul\u003e","title":"linux 休止状態の動作を確認したい"},{"content":"前回の記事 yt-dlpコマンドで、年齢制限を何とかする\nなんで追記を書くことにしたの？ 最近、cookieを直接 yt-dlp コマンドに渡すのは、なんか cookie が機能しなくなったりしてメンテする必要があったりと、めんどっちいなとなった。何とかブラウザから cookie 読み込んでくれないかなと試したところ成功した。そこで、投げやりにしてた部分を今更ながら書いてみようとそういうわけである。\nあと、単純に google analytics をこのブログに導入してみて、一番 yt-dlpコマンドで、年齢制限を何とかする に訪問者 (Bot説ある) がいそうだという点も気にしてたりする。本当は、アンダーマイニング効果とかあるし、あまり他人目線でやると、本来のこのブログの意味が崩壊するので、なるべく避けたいものであるが、、、(実は、google analyticsとかは使わないほうがいい説があるが、しばらく様子見としてみる。)\n分かったこと 必要なパッケージがある 以下のように調べてみると、 python-secretstorage というパッケージが必要そうなことが分かる。\npacman -Si yt-dlp # -Si オプション: パッケージに関する情報について調べる。必須ではないがインストールが推奨されるパッケージの情報も出てくる。 リポジトリ : extra 名前 : yt-dlp バージョン : 2024.12.06-1 ... python-secretstorage: For -cookies-from-browser to access the GNOME keyring while decrypting cookies of Chromium-based browsers ... うまくいかないブラウザ chromium 系のブラウザでは、cookieの復号がうまくいかず、以下のように失敗するので、諦めて firefox を使うことにした。ちなみに、私は brave とかそのほかのブラウザでは特に試していないので、chrome とか firefox 以外のブラウザにおいての具体的な挙動はまだわかっていない。\n\u0026ldquo;cannot decrypt v11 cookies: no key found \u0026quot;　と言われ、cookieの取得に失敗する。\nyt-dlp https://www.youtube.com/watch?v=[videoID] --cookies-from-browser chrome Extracting cookies from chrome [Cookies] Loading cookie 0/ 65WARNING: cannot decrypt v11 cookies: no key found Extracted 0 cookies from chrome (65 could not be decrypted) [youtube+AGB] Extracting URL: https://www.youtube.com/watch?v=[videoID] [youtube+AGB] [videoID]: Downloading webpage [youtube+AGB] [videoID]: Downloading ios player API JSON [youtube+AGB] [videoID]: Downloading tv embedded player API JSON [youtube+AGB] [videoID]: Downloading web embedded client config [youtube+AGB] [videoID]: Downloading player 576f07ca [youtube+AGB] [videoID]: Downloading web embedded player API JSON [youtube+AGB] [videoID]: Downloading Zerody API JSON WARNING: [youtube+AGB] Unable to download JSON metadata: HTTP Error 502: Bad Gateway ERROR: [youtube+AGB] [videoID]: Sign in to confirm your age. This video may be inappropriate for some users. 他のやり方 寄り道したついでに、適当使えそうな使えなさそうな、微妙な方法やまだ試していない方法についてもまとめてみる。\ncookie を生き残らせる 最近再び試しに、 chrome から cookie の抽出ができないかやってみたところ、なんかメッセージが変わっていた。\nyt-dlp [videoID] --merge-output-format mp4 --cookies-from-browser chrome Extracting cookies from chrome [Cookies] Loading cookie 0/ 67WARNING: cannot decrypt v11 cookies: no key found Extracted 0 cookies from chrome (67 could not be decrypted) [youtube+AGB] Extracting URL: [videoID] [youtube+AGB] [videoID]: Downloading webpage [youtube+AGB] [videoID]: Downloading ios player API JSON [youtube+AGB] [videoID]: Downloading mweb player API JSON [youtube+AGB] [videoID]: Downloading Zerody API JSON WARNING: [youtube+AGB] Unable to download JSON metadata: HTTP Error 502: Bad Gateway ERROR: [youtube+AGB] [videoID]: Sign in to confirm your age. This video may be inappropriate for some users. Use --cookies-from-browser or --cookies for the authentication. See https://github.com/yt-dlp/yt-dlp/wiki/FAQ#how-do-i-pass-cookies-to-yt-dlp for how to manually pass cookies. Also see https://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies for tips on effectively exporting YouTube cookies それでわかったこととして、yt-dlpコマンドで、年齢制限を何とかするのようにして、cookie をただ取り出すだけだと、youtube側が頻繁に cookie を変えてしまうために、すぐ機能しなくなってしまうとのことであった。\nそれで、抽出した cookie を長く利用できるようにする方法として、シークレットタブでyoutubeにログインし、cookieを抽出する方法が説明されていた。ちなみに、私はブラウザ(firefox)を使う方法で満足したので、まだ試してはいない。以下は、Extractors · yt-dlp/yt-dlp Wiki · GitHubの引用である。\nYouTube Exporting YouTube cookies\nIf you are unfamiliar with the basics of exporting cookies and passing them to yt-dlp, then first see How do I pass cookies to yt-dlp?\nYouTube rotates cookies frequently on open YouTube browser tabs as a security measure. To export cookies that will \u0026gt;remain working with yt-dlp, you will need to export cookies in such a way that they are never rotated.\nOne way to do this is through a private browsing/incognito window:\nOpen a new private browsing/incognito window and log into YouTube Open a new tab and close the YouTube tab Export cookies from the browser then close the private browsing/incognito window so the session is never opened in the browser again. gnomekeyring を使う 調べていると、How to authenticate with cookies from Brave Browser? : r/youtubedlというところに、確か chromium 系のブラウザであったはずの、brave と yt-dlp の挙動について書かれている。以下のようにすると、gnomekeyring を使って、cookieの復号ができるらしい。そこで、chromeでもできないか試してみた。\nReallyEvilRob\n\u0026ndash;cookies-from-browser brave+gnomekeyring did the trick. Thanks for your help!\n結果としては、以下のように結局失敗した。firefoxでとりあえず動いているので、なんか物騒な Manifest V3 とかの話題が上がってくる chrome 関連と関わっていると不毛そうだし、なんでか失敗するのかは今のところ調べていない。\nもしかすると、単純に chrome のデフォルト設定で gnomekeyring を使う様に設定していないのかもしれないと思ったりはしてみた(探したり試したりはしておらず、妄想の域を出ていない)。\nyt-dlp [videoID] --merge-output-format mp4 --cookies-from-browser chrome+gnomekeyring Extracting cookies from chrome ERROR: Item does not exist! 次回の記事 ニコニコ動画にパスワードログインできない件について、yt-dlp のリポジトリに issue を立ててしまう。 参考にしたサイト pacman - ArchWiki\nhttps://wiki.archlinux.org/title/Pacman （2024年12月11日） --cookies-from-browser errors when Chrome/chromium-based browser is open in Windows · Issue #7271 · yt-dlp/yt-dlp · GitHub\nhttps://github.com/yt-dlp/yt-dlp/issues/7271 （2024年12月11日） The --cookies-from-browser command results in WARNING: failed to decrypt cookie because UTF-8 decoding failed. Possibly the key is wrong? · Issue #1073 · yt-dlp/yt-dlp · GitHub\nhttps://github.com/yt-dlp/yt-dlp/issues/1073 （2024年12月11日） How to authenticate with cookies from Brave Browser? : r/youtubedl\nhttps://www.reddit.com/r/youtubedl/comments/1f175by/how_to_authenticate_with_cookies_from_brave/ （2024年12月11日） Extractors · yt-dlp/yt-dlp Wiki · GitHub\nhttps://github.com/yt-dlp/yt-dlp/wiki/Extractors#exporting-youtube-cookies （2024年12月11日） GNOME/Keyring - ArchWiki\nhttps://wiki.archlinux.org/title/GNOME/Keyring （2024年12月11日） ","permalink":"https://www.nyanmo.info/posts/yt-dlp/bypassagegate2/","summary":"\u003ch2 id=\"前回の記事\"\u003e前回の記事\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/yt-dlp/bypassagegate/\"\u003eyt-dlpコマンドで、年齢制限を何とかする\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"なんで追記を書くことにしたの\"\u003eなんで追記を書くことにしたの？\u003c/h2\u003e\n\u003cp\u003e　最近、cookieを直接 yt-dlp コマンドに渡すのは、なんか cookie が機能しなくなったりしてメンテする必要があったりと、めんどっちいなとなった。何とかブラウザから cookie 読み込んでくれないかなと試したところ成功した。そこで、投げやりにしてた部分を今更ながら書いてみようとそういうわけである。\u003c/p\u003e\n\u003cp\u003e　あと、単純に google analytics をこのブログに導入してみて、一番 \u003ca href=\"https://www.nyanmo.info/posts/yt-dlp/bypassagegate/\"\u003eyt-dlpコマンドで、年齢制限を何とかする\u003c/a\u003e に訪問者 (Bot説ある) がいそうだという点も気にしてたりする。本当は、アンダーマイニング効果とかあるし、あまり他人目線でやると、本来のこのブログの意味が崩壊するので、なるべく避けたいものであるが、、、(実は、google analyticsとかは使わないほうがいい説があるが、しばらく様子見としてみる。)\u003c/p\u003e\n\u003ch2 id=\"分かったこと\"\u003e分かったこと\u003c/h2\u003e\n\u003ch3 id=\"必要なパッケージがある\"\u003e必要なパッケージがある\u003c/h3\u003e\n\u003cp\u003e　以下のように調べてみると、 python-secretstorage というパッケージが必要そうなことが分かる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epacman -Si yt-dlp \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -Si オプション: パッケージに関する情報について調べる。必須ではないがインストールが推奨されるパッケージの情報も出てくる。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eリポジトリ             : extra\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e名前                   : yt-dlp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eバージョン             : 2024.12.06-1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                         python-secretstorage: For -cookies-from-browser to access the GNOME keyring \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e decrypting cookies of Chromium-based browsers\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"うまくいかないブラウザ\"\u003eうまくいかないブラウザ\u003c/h3\u003e\n\u003cp\u003e　chromium 系のブラウザでは、cookieの復号がうまくいかず、以下のように失敗するので、諦めて firefox を使うことにした。ちなみに、私は brave とかそのほかのブラウザでは特に試していないので、chrome とか firefox 以外のブラウザにおいての具体的な挙動はまだわかっていない。\u003c/p\u003e\n\u003cp\u003e　\u0026ldquo;cannot decrypt v11 cookies: no key found \u0026quot;　と言われ、cookieの取得に失敗する。\u003c/p\u003e","title":"yt-dlpコマンドで、年齢制限を何とかするの追記"},{"content":"この記事を書いた動機 単純に別の記事を更新してて、一応書いとくかってなっただけです。二番煎じというか、自分用のメモとしての補足的な記事なので、シンプルに書きます。\n環境 arch linux (2024/11/13の時点で最新のやつ) yay のインストール 必要なコマンドをインストール sudo pacman -S base-devel git 作業ディレクトリとして適当な場所に移動 cd /tmp git から yay のリポジトリのクローン git clone https://aur.archlinux.org/yay.git cd yay yay をインストール makepkg -si 以上で、yayコマンドが使えるはずである。。。　まとめ sudo pacman -S base-devel git cd /tmp git clone https://aur.archlinux.org/yay.git cd yay makepkg -si 参考にしたサイト Arch Linux に yay をインストール #archLinux - Qiita\nhttps://qiita.com/ekzemplaro/items/6714469c1fb1ae06b80f （2024年11月14日） ","permalink":"https://www.nyanmo.info/posts/linux/yay/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　単純に別の記事を更新してて、一応書いとくかってなっただけです。二番煎じというか、自分用のメモとしての補足的な記事なので、シンプルに書きます。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003earch linux (2024/11/13の時点で最新のやつ)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"yay-のインストール\"\u003eyay のインストール\u003c/h2\u003e\n\u003ch3 id=\"必要なコマンドをインストール\"\u003e必要なコマンドをインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo pacman -S base-devel git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"作業ディレクトリとして適当な場所に移動\"\u003e作業ディレクトリとして適当な場所に移動\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /tmp\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"git-から-yay-のリポジトリのクローン\"\u003egit から yay のリポジトリのクローン\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://aur.archlinux.org/yay.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd yay\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"yay-をインストール\"\u003eyay をインストール\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emakepkg -si\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　以上で、yayコマンドが使えるはずである。。。　\u003c/p\u003e\n\u003ch2 id=\"まとめ\"\u003eまとめ\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo pacman -S base-devel git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /tmp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://aur.archlinux.org/yay.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd yay\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emakepkg -si\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eArch Linux に yay をインストール #archLinux - Qiita\u003cbr\u003e\n\u003ca href=\"https://qiita.com/ekzemplaro/items/6714469c1fb1ae06b80f\"\u003ehttps://qiita.com/ekzemplaro/items/6714469c1fb1ae06b80f\u003c/a\u003e （2024年11月14日）\u003c/li\u003e\n\u003c/ul\u003e","title":"yay コマンドのインストール"},{"content":"この記事を書いた動機 最近linuxのカーネルパラメータとか、コンフィグをいじる機会があったって、どうやっていじるんだっけとなったので、メモを残そうということになった。\nいつものように、基本は自分のために書いてるというのもあって、他人が見るためのコンテンツとしてはクオリティは終わってるので、そこは承知ください。。。。\n環境 ここには、簡易的にどんな環境でやることについて書いているか、記録してみる。\narch linux linux kernel version: 6.9.7 UEFIに対応したハードウェア環境 grub をブートローダーとして使っている x86 系列の 64 bit CPU (Intel の core i シリーズとか、ryzenとか、、、) カーネルをビルドする 今使っているlinuxのバージョンを確認 uname -r 6.9.7 作業用のフォルダを作成 いろいろ、コンフィグだのカーネル本体だのをいじくりまわして散らかるので、一つのフォルダにそれらをまとめる。\nmkdir ~/kernel cd ~/kernel linux をダウンロード linux archivesから、自分の使っているlinuxのバージョンに合った、linux をダウンロードしてくる。私の場合は、以下のように、リンクを改変することで、バージョンを合わせた。\n改変前 https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.7.tar.xz\n改変後 https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.7.tar.xz\nlinuxのダウンロードには、ブラウザから直接ダウンロードボタンを押したり、リンクを踏むことでできたり、gitが使えたりする。いろいろあるが、めんどくさかったので、wgetコマンドを使った。\nwget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.7.tar.xz ダウンロードしたカーネルを展開する tarコマンドで以下のようにして、適当に中身を展開する。\ntar xfv linux-6.9.7.tar.xz cd linux-6.9.7 # オプションのヒント # x: extract (抽出) # f: file (展開するファイルを指定する) # v: verbose (途中経過の表示ができる) カーネル設定ファイルをコピー linuxでは、何も設定がないところからスタートする場合は、たぶん自分で以下のようにして、一つ一つコンフィグを設定していくっぽいが、そんなことを一からしていたら日が暮れてしまうので、今動いているカーネルの設定を使いまわす。\nmake menuconfig ... # 何かしらのメニューがしばらくすると表示され、圧倒的な量の設定項目があることに圧倒されるまでがセット。。。 linuxカーネルのバージョンを合わせたのは、バージョンがあっていないと、新たにカーネルの設定が追加されていたりして、その設定をするのが面倒だし、それで動かなかったらさらに面倒だからである。arch linuxの場合だと以下のようにして、設定をコピーできる。\n# 現在のカーネルの設定をコピー cp /proc/config.gz ./ # gzipコマンドでコンフィグを展開 gzip -d config.gz # decompress の d で展開できる # makeしたときにコンフィグが認識されるように、ファイル名を変更 mv config ./.config カーネルの設定を変更する # 設定画面でポチポチするならこっち make menuconfig # 直接エディターでいじりたいならこっち code .config nvim .config ... 今回は以下の設定項目を変更してみた。なんか間違っている気がするが、とにかくASPMに関して、カーネルの設定を変更したかったのでしてみた。\n変更前 CONFIG_PCIEASPM=y CONFIG_PCIEASPM_DEFAULT=y # CONFIG_PCIEASPM_POWERSAVE is not set # CONFIG_PCIEASPM_POWER_SUPERSAVE is not set # CONFIG_PCIEASPM_PERFORMANCE is not set 変更後 CONFIG_PCIEASPM=y # CONFIG_PCIEASPM_DEFAULT=y CONFIG_PCIEASPM_POWERSAVE=y CONFIG_PCIEASPM_POWER_SUPERSAVE=y # CONFIG_PCIEASPM_PERFORMANCE is not set やってから気づいたが、たぶん本来は以下のように、default、powersave、performance うち一つだけ選んで設定すればいい模様。。。とにかく動いたので良しとしているが。。。\n# CONFIG_PCIEASPM_DEFAULT=y CONFIG_PCIEASPM_POWERSAVE=y # CONFIG_PCIEASPM_POWER_SUPERSAVE=y # CONFIG_PCIEASPM_PERFORMANCE is not set ちなみに、ここのサイトを見てなんとなく違うかなと気づいた。\n3.7. Active-State Power Management | Red Hat\nカーネルをコンパイルする linuxカーネルを設定に基づいて、ビルドさせる。-j オプションで、複数のCPUコアを使うように設定しておかないと、とんでもない時間がかかる。基本的にはCPUのコア数と相談して設定した方がいいともう。\n# カーネル本体をビルド make -j 32 # make -j [cpuのコア数かスレッド数あたりに設定] モジュールを何とかする モジュールをコンパイルする make modules -j 32 モジュールのインストール ここでは、管理者権限を付与してコマンドを実行しないと、モジュールをインストールできないので、sudo を使っている。\nsudo make modules_install モジュールのインストールを怠ると、linuxカーネル読み込み時に、カーネルに必要な部品が見つからないみたいな感じになる。ext4のファイルシステムとかわからないとか言われて、主要なパーティションからデータが読み込めないなどして、起動しなくなってしまう。\nカーネルイメージの配置 カーネルをコンパイルするで作成した、linux本体を配置する。通常は、カーネルをコンパイルしたときから、移動していなければ、以下の相対パスのところにある。\n./arch/x86_64/boot/bzImage 私の環境ではカーネルは、以下に示すフォルダ入っている\n/boot # カーネル本体はこんな感じで入っている /boot/vmlinuz-linux ということなので、今回は、vmlinuz-linux-customとして、作ったカーネルを配置することにする。ちなみに、コマンド実行時には、sudoで管理者権限も付与する。\nsudo cp ./arch/x86_64/boot/bzImage /boot/vmlinuz-linux-custom mkinitcpio を何とかする そもそも mkinitcpio ってなにしたいの？ 私もよく分からなかったので、調べてみたら、arch wikiにこんなことが書いてあった。\nmkinitcpio は初期 RAM ディスク環境を作成するために使われる Bash スクリプトです。mkinitcpio(8) man ページより:\n初期 ram ディスクは非常に小さい環境（初期ユーザー空間）であり、様々なカーネルモジュールをロードして init にコントロールを移す前に必要なことをセットアップします。これにより、root ファイルシステムを暗号化したりソフトウェア RAID アレイに root を載せたりすることが可能になります。mkinitcpio はカスタムフックによって簡単に拡張することができ、実行時の自動検知など様々な機能を持っています。\n伝統的には、ブートプロセスの初めにハードウェアを検知したりタスクの初期化を行うのはカーネルで、それから root ファイルシステムがマウントされ init にコントロールが移されます。しかしながら、先端技術が生まれるにつれ、こういった作業は複雑になりつつあります。\n今日、root ファイルシステムが載るハードウェアは SCSI から SATA、USB ドライブまで様々にわたり、それらハードウェアはそれぞれのメーカーによって作られたいろんなドライブコントローラによってコントロールされています。しかも、root ファイルシステムは暗号化されたり圧縮されたりする可能性もあります; ソフトウェア RAID アレイや論理ボリュームグループに含まれるかもしれません。複雑になったものをシンプルに扱う方法はユーザースペース (初期RAMディスク) へ管理を譲渡することです。参照: /dev/brain0 » Blog Archive » Early Userspace in Arch Linux。\nということらしい。。。要は、OS起動時の複雑な部分を吸収するための、いろいろドライバとか載っているメモリ上に読み込まれるイメージを起動用に作るために、mkinitcpio というコマンドがあるということでいいっぽい？\nプリセットの定義 mkinitcpio コマンドでは、/etc/mkinitcpio.d にあるプリセットに従って、RAM イメージが作られるっぽい。私の環境ではデフォルトで linux.preset というファイルがあり、以下の様な構成になっていた。\n# mkinitcpio preset file for the \u0026#39;linux\u0026#39; package #ALL_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; ALL_kver=\u0026#34;/boot/vmlinuz-linux\u0026#34; PRESETS=(\u0026#39;default\u0026#39; \u0026#39;fallback\u0026#39;) #default_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; default_image=\u0026#34;/boot/initramfs-linux.img\u0026#34; #default_uki=\u0026#34;/efi/EFI/Linux/arch-linux.efi\u0026#34; #default_options=\u0026#34;--splash /usr/share/systemd/bootctl/splash-arch.bmp\u0026#34; #fallback_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; fallback_image=\u0026#34;/boot/initramfs-linux-fallback.img\u0026#34; #fallback_uki=\u0026#34;/efi/EFI/Linux/arch-linux-fallback.efi\u0026#34; fallback_options=\u0026#34;-S autodetect\u0026#34; 今回は、この定義をパクッてきて、作成したカーネル用のプリセットを作成する。\ncd /etc/mkinitcpio.d sudo cp linux.preset ./linux-custom.preset また、今回は /boot にマウントしている、EFI パーティションのサイズが小さすぎて、全部は入らない。そこで、fallback のオプションを外し、起動に必要な最低限の RAM イメージだけ作成するように、以下のように設定を変更した。\n# 管理者権限を使い、好きなエディターで開く sudo nvim linux-custom.preset # ここから、今回作成した設定例 # mkinitcpio preset file for the \u0026#39;linux\u0026#39; package #ALL_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; ALL_kver=\u0026#34;/boot/vmlinuz-linux-custom\u0026#34; PRESETS=(\u0026#39;default\u0026#39;) #default_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; default_image=\u0026#34;/boot/initramfs-linux-custom.img\u0026#34; #default_uki=\u0026#34;/efi/EFI/Linux/arch-linux.efi\u0026#34; #default_options=\u0026#34;--splash /usr/share/systemd/bootctl/splash-arch.bmp\u0026#34; #fallback_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; #fallback_image=\u0026#34;/boot/initramfs-linux-fallback-custom.img\u0026#34; #fallback_uki=\u0026#34;/efi/EFI/Linux/arch-linux-fallback.efi\u0026#34; #fallback_options=\u0026#34;-S autodetect\u0026#34; 主な変更点は以下のとおりである。\nfallback イメージの無効化 # 変更前 PRESETS=(\u0026#39;default\u0026#39; \u0026#39;fallback\u0026#39;) ... #fallback_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; fallback_image=\u0026#34;/boot/initramfs-linux-fallback.img\u0026#34; #fallback_uki=\u0026#34;/efi/EFI/Linux/arch-linux-fallback.efi\u0026#34; fallback_options=\u0026#34;-S autodetect\u0026#34; # 変更後 PRESETS=(\u0026#39;default\u0026#39;) ... #fallback_config=\u0026#34;/etc/mkinitcpio.conf\u0026#34; #fallback_image=\u0026#34;/boot/initramfs-linux-fallback-custom.img\u0026#34; #fallback_uki=\u0026#34;/efi/EFI/Linux/arch-linux-fallback.efi\u0026#34; #fallback_options=\u0026#34;-S autodetect\u0026#34; 今回作成したカーネルへの場所と作成される RAM イメージの保存場所を指定 # 変更前 ALL_kver=\u0026#34;/boot/vmlinuz-linux\u0026#34; ... default_image=\u0026#34;/boot/initramfs-linux.img\u0026#34; # 変更後 ALL_kver=\u0026#34;/boot/vmlinuz-linux-custom\u0026#34; ... default_image=\u0026#34;/boot/initramfs-linux-custom.img\u0026#34; とにかくイメージを作る このメモリ上に読み込まれるイメージを作るには、以下のようにする。個々で指定する名前は、プリセットの定義で作成した設定名前に依存する模様。ファイル名.preset という感じで、ファイル名の部分が今回指定する名前になる。\n# 部分的に RAM イメージを更新、作成 sudo mkinitcpio -P linux-custom # 全部のプリセットに対してやりたいときは、何も指定しない sudo mkinitcpio -P ちなみに、全部のプリセットに対して mkinitcpio -P コマンドを実行すると、ディスクの空きが十分になくて、作成した RAM イメージが書き込めなかったときに、再起動したら起動できないなんてことになりかねないと思う。\n安全策として、すでにあるのはいじらないで、今回新しく作ったものだけに対して操作を行うのがたぶん無難だと思う。\ngrub の設定を更新する ブートローダーの更新を行う。今回は grub を使っているので、grub-mkconfig で自動的にコンフィグを生成させる。\ngrub-mkconfig コマンドは、/boot とかにあるカーネルとかを見つけて、自動で新しく作成したカーネルイメージを認識してくれる。そのため、起動時の選択肢として認識して、余り細かいことは気にせずに、grub ブートローダーのコンフィグを勝手に作ってくれる。\n# 実際に更新を行う sudo grub-mkconfig -o /boot/grub/grub.cfg # 以下は実行結果 # [sudo] userName のパスワード: # Generating grub configuration file ... # こんな感じで、作成したカーネルも見つけてもらえる # Linux イメージを見つけました: /boot/vmlinuz-linux-custom # Found initrd image: /boot/initramfs-linux-custom.img # Linux イメージを見つけました: /boot/vmlinuz-linux # Found initrd image: /boot/initramfs-linux.img # Found fallback initrd image(s) in /boot: initramfs-linux-fallback.img # Warning: os-prober will not be executed to detect other bootable partitions. # Systems on them will not be added to the GRUB boot configuration. # Check GRUB_DISABLE_OS_PROBER documentation entry. # Adding boot menu entry for UEFI Firmware Settings ... # 完了 多分、ここまでくれば、新しく作ったカーネルで起動できる所まで、あわよくばうまく行くはずである。\nカーネルパラメータについて カーネルパラメータとは、OS起動時に GRUB で指定できる、カーネルの設定のことであったと思う。例えばこれは、グラフィック関連の挙動を設定したり、機能の有効、無効の制御、ドライバやハードウェアのブラックリストなどの管理を行えたりする。今回はここまで書こうかと思ったが、疲れたのでいったんお休みにする。。。\n補足 カーネルを配置したり、mkinitcpio -P をする前に、、、 今回は、起動時、UEFIに認識され、まず最初に読み込まれるデータが入っている、/boot フォルダについていろいろしていた。\nしかし、/boot フォルダに対して、正しくパーティションがマウントされていないと、うまく変更を反映できなかったり、カーネルとその部品であるモジュール間でバージョンがちぐはぐになって、とにかくうまく起動してくれなくなってしまう。\n事前にこれら問題を防ぐには、作業前に mount コマンドを実行して、正しくマウントできているか確認するといいかもしれない。\nmount | grep /boot # 正常にマウントされているときの出力例 /dev/sdb1 on /boot type vfat (rw,relatime,fmask=0022,dmask=0022,codepage=437,iocharset=ascii,shortname=mixed,utf8,errors=remount-ro) # 正常にマウントされていないときは、たぶん何も出てこない このような状況下では、パテーションのマウント情報が入っている、/etc/fstab あたりも確認するといいかもしれない。\n多分そのファイルがなくて、一応起動はそれでもするのだが、いざというときに、/boot フォルダに対して何もパテーションがマウントされていないということになっていることがある。\nまあ、設定し忘れる事なんていくらでもあるし、気づいたときに適当にインストールメディアから fstab を生成してやれば、事なきを得られそうである。\n参考にしたサイト The Linux Kernel Archives\nhttps://www.kernel.org/ （2024年11月10日）\nKernel/Arch build system - ArchWiki\nhttps://wiki.archlinux.org/title/Kernel/Arch_build_system （2024年11月10日）\nKernel/Traditional compilation - ArchWiki\nhttps://wiki.archlinux.org/title/Kernel/Traditional_compilation （2024年11月10日）\nTar Tutorial | Ohio Supercomputer Center\nhttps://www.osc.edu/documentation/tutorials/unix-basics/tar-tutorial （2024年11月10日）\n3.7. Active-State Power Management | Red Hat Product Documentation\nhttps://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/6/html/power_management_guide/aspm （2024年11月10日）\nGRUB - ArchWiki\nhttps://wiki.archlinux.org/title/GRUB （2024年11月10日）\nActive State Power Management (ASPM) : r/debian\nhttps://www.reddit.com/r/debian/comments/8c6ytj/active_state_power_management_aspm/ （2024年11月10日）\nmkinitcpio - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Mkinitcpio （2024年11月10日）\nnotthebee/AutoASPM: A script that automatically activates ASPM for all supported devices on Linux - Forgejo: Beyond coding. We Forge.\nhttps://git.notthebe.ee/notthebee/AutoASPM (2026年3月1日)\nluckylinux/aspm-troubleshooting: aspm-troubleshooting\nhttps://github.com/luckylinux/aspm-troubleshooting (2026年3月1日)\n","permalink":"https://www.nyanmo.info/posts/linux/kernelbuild/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　最近linuxのカーネルパラメータとか、コンフィグをいじる機会があったって、どうやっていじるんだっけとなったので、メモを残そうということになった。\u003c/p\u003e\n\u003cp\u003e　いつものように、基本は自分のために書いてるというのもあって、他人が見るためのコンテンツとしてはクオリティは終わってるので、そこは承知ください。。。。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cp\u003e　ここには、簡易的にどんな環境でやることについて書いているか、記録してみる。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003earch linux\u003c/li\u003e\n\u003cli\u003elinux kernel version: 6.9.7\u003c/li\u003e\n\u003cli\u003eUEFIに対応したハードウェア環境\u003c/li\u003e\n\u003cli\u003egrub をブートローダーとして使っている\u003c/li\u003e\n\u003cli\u003ex86 系列の 64 bit CPU (Intel の core i シリーズとか、ryzenとか、、、)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"カーネルをビルドする\"\u003eカーネルをビルドする\u003c/h2\u003e\n\u003ch3 id=\"今使っているlinuxのバージョンを確認\"\u003e今使っているlinuxのバージョンを確認\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euname -r\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e6.9.7\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"作業用のフォルダを作成\"\u003e作業用のフォルダを作成\u003c/h3\u003e\n\u003cp\u003e　いろいろ、コンフィグだのカーネル本体だのをいじくりまわして散らかるので、一つのフォルダにそれらをまとめる。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir ~/kernel\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/kernel\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"linux-をダウンロード\"\u003elinux をダウンロード\u003c/h3\u003e\n\u003cp\u003e　\u003ca href=\"https://www.kernel.org/\"\u003elinux archives\u003c/a\u003eから、自分の使っているlinuxのバージョンに合った、linux をダウンロードしてくる。私の場合は、以下のように、リンクを改変することで、バージョンを合わせた。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e改変前\n\u003ca href=\"https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.7.tar.xz\"\u003ehttps://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.11.7.tar.xz\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e改変後\n\u003ca href=\"https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.7.tar.xz\"\u003ehttps://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.7.tar.xz\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　linuxのダウンロードには、ブラウザから直接ダウンロードボタンを押したり、リンクを踏むことでできたり、gitが使えたりする。いろいろあるが、めんどくさかったので、wgetコマンドを使った。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.9.7.tar.xz\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"ダウンロードしたカーネルを展開する\"\u003eダウンロードしたカーネルを展開する\u003c/h3\u003e\n\u003cp\u003e　tarコマンドで以下のようにして、適当に中身を展開する。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar xfv linux-6.9.7.tar.xz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd linux-6.9.7\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# オプションのヒント\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# x: extract    (抽出)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# f: file       (展開するファイルを指定する)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# v: verbose    (途中経過の表示ができる)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch3 id=\"カーネル設定ファイルをコピー\"\u003eカーネル設定ファイルをコピー\u003c/h3\u003e\n\u003cp\u003e　linuxでは、何も設定がないところからスタートする場合は、たぶん自分で以下のようにして、一つ一つコンフィグを設定していくっぽいが、そんなことを一からしていたら日が暮れてしまうので、今動いているカーネルの設定を使いまわす。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake menuconfig\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e... \u003cspan style=\"color:#75715e\"\u003e# 何かしらのメニューがしばらくすると表示され、圧倒的な量の設定項目があることに圧倒されるまでがセット。。。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e　linuxカーネルのバージョンを合わせたのは、バージョンがあっていないと、新たにカーネルの設定が追加されていたりして、その設定をするのが面倒だし、それで動かなかったらさらに面倒だからである。arch linuxの場合だと以下のようにして、設定をコピーできる。\u003c/p\u003e","title":"linuxカーネルを設定したりする📓"},{"content":"この記事を作った動機 私はプライベートネットワークにおいて、自分のためだけのサービスをhttpプロトコル経由で利用できるようにしているが、拡張機能とかの作成にあたり、httpsじゃないと不都合が生じるようになったことがきっかけで、https化に苦労することになり、もう嫌だということでこの記事を書くことになった。\n例えばyoutube上で動作する拡張機能が、自分だけのためのサービスが動いているhttpサーバをバックエンドとして使うことを考えると、http通信とhttps通信が一つのWebページを表示するために混在してしまうために、ブラウザ側で通信がブロックされたリ、騒がしいエラーが出てきてしまい、非常に不快な思いをすることになる。\n前提としていること 参考程度に前提条件とかも書いておく。\nhttpdを使っている。 opensslパッケージがインストール済み すでにhttpdを使っていて、ブラウザでなんか表示できる状態にある。 あくまで個人用など、閉じられた環境において、https通信を実現したいと考えている。 このブログの様な、大っぴらに公開されているWebサイトには使えない手法であることを理解している。 https通信の実現方法 証明書を作る HTTPsを実現するために、mkcertコマンドを使って証明書を作成するが、どんな証明書が必要が一応自分の理解の範囲であり、間違っているかもしれないが、簡易的に書いておく。必要そうな証明書は以下のとおりである。\nサーバ自体を証明する証明書 各httpサーバとかのためにサービスごとに個別に用意される証明書 この中で、サーバと通信するパソコンがインストールしているべき証明書は、「サーバ自体を証明する証明書」の証明書の公開鍵であり、「各httpサーバとかのためにサービスごとに個別に用意される証明書」の公開鍵ではない。\nmkcert コマンドのインストールを行う\n私は arch linux を使っているので、以下のようにパッケージマネージャを利用した。\nyay -S mkcert # たぶんリポジトリの分類がExtraにあるので、pacmanでもインストールできる # pacman -S mkcert mkcertの初期化を行う\nサーバ自体を証明する証明書の作成を行う。\nmkcert -install # 証明書が保存された場所を調べるためには以下のコマンドでできる。基本的にmkcert -installを実行したユーザのホームディレクトリのどこかにある。 # mkcert -CAROOT # /home/username/.local/username/mkcert # 自分の環境だとこのような出力が得られる。 httpサーバ用の証明書を作る\n次に以下のようにして、httpサーバが動いているドメイン名やIPアドレスを引数として、サービス用に証明書を作成する。この証明書は今回の場合であれば、httpdサーバの443番ポートを経由して、通信しているブラウザ等に送られることになる。\n# コマンドを実行したファイル内で証明書の公開鍵と秘密鍵ができてしまうため、一応作業用のフォルダを作っている。 mkdir ./sslLocal/ cd ./sslLocal # 各httpサーバとかのためにサービスごとに個別に用意される証明書を作成 mkcert mydomain.name ipAddr # ドメイン名やIPアドレスなど複数指定できるらしいが、自分はとりあえずドメイン名だけにしてた。 # あっ、mydomain.nameやipAddrとかは適宜読み替えてください httpdが使う証明書を配置 私は以下の様にして、httpサーバ用の証明書を配置した。\n# 証明書を作成したディレクトリへ移動 cd ~/sslLocal/* # ファイル内容を確認し、証明書の公開鍵と秘密鍵があることを確認する。 ls -rw-------⠀username⠀1708⠀Nov 4 02:06:02⠀⠀mydomain.name-key.pem -rw-r--r--⠀username⠀1452⠀Nov 4 02:06:02⠀⠀mydomain.name.pem # httpdのconfigがあるところに、証明書を置いておく場所も作る。 sudo mkdir /etc/httpd/conf/ssl # 署名書を作成したフォルダまで移動する。 cp ~/sslLocal/* /etc/httpd/conf/ssl/ httpdの設定 ssl通信に必要なモジュールを読み込む。\n# このwebページを参考に、設定している。 # https://wiki.archlinux.jp/index.php/Apache_HTTP_Server cd /etc/httpd/conf sudo nvim httpd.conf # 好きなエディタ使い管理者権限で開く ... # httpd.confの中にある、次の項目をコメントアウト LoadModule ssl_module modules/mod_ssl.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so # この項目については、今回別途ssl通信用の設定を作成したため、利用しなかった。 # Include conf/extra/httpd-ssl.conf ... SSL通信用にVirtualHostを作成\nSSL通信をするためには、httpdの設定を変更しておく必要がある。HTTPSのSSL通信には、確か443番が使われていて、その関係の設定である。\n本来は、/etc/httpd/conf/extra/httpd-ssl.conf 内に設定例があり、それを自分用に変更する形をとるのが、管理という観点からも王道っぽい。\nしかし、自分は個別にある、/etc/httpd/conf/extra/httpd-vhosts.confに設定してしまっている。この設定をしているときは、正直これがうまく動くかさえ分からなかったし手探りだたったので承知願います。。。\ncd /etc/httpd/conf/extra sudo nvim httpd-vhosts.conf # 多分最小構成はこんな感じだと思う ... \u0026lt;VirtualHost *:443\u0026gt; DocumentRoot \u0026#34;ssl通信をしたいWebページのフォルダまでのパス\u0026#34; ServerName mydomain.name SSLEngine on SSLCertificateFile \u0026#34;/etc/httpd/conf/ssl/mydomain.name.pem\u0026#34; SSLCertificateKeyFile \u0026#34;/etc/httpd/conf/ssl/mydomain.name-key.pem\u0026#34; \u0026lt;/VirtualHost\u0026gt; ... httpdを再起動\nsudo systemctl restart httpd # 一応再起動後に設定の不備とかでコケて起動に失敗していないかなど確認する。failedとかエラーが出てなければたぶんOK systemctl status httpd 通信をしたいクライアントに、証明書をインストール ルート証明書として、「サーバ自体を証明する証明書」をインストールする。ここで間違えて、「各httpサーバとかのためにサービスごとに個別に用意される証明書」をインストールするとうまくいかず、泣く羽目になる。\nインストールの仕方はたぶんOS固有で説明するのはめんどくさいのでここでは割愛します。。。ポイントとしては、Windowsであれば、ルート証明書としてインストールすることと、信頼できない証明書の発行者ですみたいな警告が出てきたら、それは仕方なのないことなので、許可する方向で操作することくらいだと思う。うまくいけば、ブラウザを再起動すれば、証明書が認識され、晴れてhttpsが使えるはずである。\n困ったこと グダグダ駄文 \"https ローカル環境\"などと調べるとmkcertコマンドを使って証明書を作ることで、SSL(TLS)によるHTTPs通信ができることが書いているWebページが見つかる。\nしかし、記事を書いている人がそんなの当たり前と思っているのか、私が思いっきり見落としているのかはわからないが、サービスごとの証明書を作ることは書いていて、rootCA.pemを通信を行うクライアントにインストールするということが抜けているWebページがあった。\nよくわからず間違いをして、httpサーバのために作成した証明書の公開鍵を間違ってインストールしてしましまい、いつまでたってもHTTPs通信が成功しないという辛いことになった。\nちなみに後から、検索ワードを\"mkcert 使い方\"とか視点を変えた調べ方をすると、rootCA.pemのことが書いているサイトがあったので普通に盲点だった。調べ方が甘かったと言われたらその通りである。。。\nそもそも、結局のところ、私のSSL/TLS通信についての理解が浅いということでもあるとは思う。。。この記事に書いていることも間違えだらけだろうし、、、でもでも！、それでもとにかく動くようにできたので良しとしようｗ。\n気になること なんか、このサイトとかに書いているように、プライベートネットワーク用に、実在のドメインを取得し、本物の証明書を使うという考え方もあるらしい。\n確かに、下手に証明書の設定をいじくりまわす必要のない点ではなんか理想的だけど、今のところ間に合っているので、このことは気になるがおいておくことにしている。\n後mkcertコマンドは、本番環境の様な厳密な環境では利用が推奨されていないらしい。ここら辺はよくわかっていないが、今回の件は、プライベートネットワークかつ個人用なので開発用だろうがとにかく良しとしておく。\nあっ、このブログはcertbotを使って、Let\u0026rsquo;s enscrypt経由でうまく通信できるようになっているはずなので、ある程度は大丈夫だと、、、信じたい。。。\n参考にしたサイト Apache HTTP Server - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Apache_HTTP_Server （2024年11月4日） ローカル環境でもHTTPS接続する理由と方法 | フロントエンドBlog | ミツエーリンクス\nhttps://www.mitsue.co.jp/knowledge/blog/frontend/202208/30_1021.html （2024年11月4日） ローカルでの開発に HTTPS を使用する | Articles | web.dev\nhttps://web.dev/articles/how-to-use-local-https?hl=ja （2024年11月4日） ローカル開発環境の https 化 | blog.jxck.io\nhttps://blog.jxck.io/entries/2020-06-29/https-for-localhost.html （2024年11月4日） ローカル開発環境用のSSL証明書を作成するならmkcertがおすすめ | アントレプログラマー\nhttps://entreprogrammer.jp/ssl-mkcert/ （2024年11月4日） localhostで開発中にGoogle Chromeで「この接続はプライバシーが保護されません」が出たときの対処法【NET::ERR_CERT_INVALID】 #Chrome - Qiita\nhttps://qiita.com/TK-C/items/13efa5a45beb6de29134 （2024年11月4日） ","permalink":"https://www.nyanmo.info/posts/webdevelop/httpswithlocalnet/","summary":"\u003ch2 id=\"この記事を作った動機\"\u003eこの記事を作った動機\u003c/h2\u003e\n\u003cp\u003e　私はプライベートネットワークにおいて、自分のためだけのサービスをhttpプロトコル経由で利用できるようにしているが、拡張機能とかの作成にあたり、httpsじゃないと不都合が生じるようになったことがきっかけで、https化に苦労することになり、もう嫌だということでこの記事を書くことになった。\u003c/p\u003e\n\u003cp\u003e　例えばyoutube上で動作する拡張機能が、自分だけのためのサービスが動いているhttpサーバをバックエンドとして使うことを考えると、http通信とhttps通信が一つのWebページを表示するために混在してしまうために、ブラウザ側で通信がブロックされたリ、騒がしいエラーが出てきてしまい、非常に不快な思いをすることになる。\u003c/p\u003e\n\u003ch2 id=\"前提としていること\"\u003e前提としていること\u003c/h2\u003e\n\u003cp\u003e　参考程度に前提条件とかも書いておく。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ehttpdを使っている。\u003c/li\u003e\n\u003cli\u003eopensslパッケージがインストール済み\u003c/li\u003e\n\u003cli\u003eすでにhttpdを使っていて、ブラウザでなんか表示できる状態にある。\u003c/li\u003e\n\u003cli\u003eあくまで個人用など、閉じられた環境において、https通信を実現したいと考えている。\u003c/li\u003e\n\u003cli\u003eこのブログの様な、大っぴらに公開されているWebサイトには使えない手法であることを理解している。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"https通信の実現方法\"\u003ehttps通信の実現方法\u003c/h2\u003e\n\u003ch3 id=\"証明書を作る\"\u003e証明書を作る\u003c/h3\u003e\n\u003cp\u003e　HTTPsを実現するために、mkcertコマンドを使って証明書を作成するが、どんな証明書が必要が一応自分の理解の範囲であり、間違っているかもしれないが、簡易的に書いておく。必要そうな証明書は以下のとおりである。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eサーバ自体を証明する証明書\u003c/li\u003e\n\u003cli\u003e各httpサーバとかのためにサービスごとに個別に用意される証明書\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e　この中で、サーバと通信するパソコンがインストールしているべき証明書は、「サーバ自体を証明する証明書」の証明書の公開鍵であり、「各httpサーバとかのためにサービスごとに個別に用意される証明書」の公開鍵ではない。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003emkcert コマンドのインストールを行う\u003cbr\u003e\n　私は arch linux を使っているので、以下のようにパッケージマネージャを利用した。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eyay -S mkcert\n# たぶんリポジトリの分類がExtraにあるので、pacmanでもインストールできる\n# pacman -S mkcert\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003emkcertの初期化を行う\u003cbr\u003e\n　サーバ自体を証明する証明書の作成を行う。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003emkcert -install\n# 証明書が保存された場所を調べるためには以下のコマンドでできる。基本的にmkcert -installを実行したユーザのホームディレクトリのどこかにある。\n# mkcert -CAROOT\n# /home/username/.local/username/mkcert # 自分の環境だとこのような出力が得られる。\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ehttpサーバ用の証明書を作る\u003cbr\u003e\n　次に以下のようにして、httpサーバが動いているドメイン名やIPアドレスを引数として、サービス用に証明書を作成する。この証明書は今回の場合であれば、httpdサーバの443番ポートを経由して、通信しているブラウザ等に送られることになる。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# コマンドを実行したファイル内で証明書の公開鍵と秘密鍵ができてしまうため、一応作業用のフォルダを作っている。\nmkdir ./sslLocal/ \ncd ./sslLocal\n\n# 各httpサーバとかのためにサービスごとに個別に用意される証明書を作成\nmkcert mydomain.name ipAddr # ドメイン名やIPアドレスなど複数指定できるらしいが、自分はとりあえずドメイン名だけにしてた。\n# あっ、mydomain.nameやipAddrとかは適宜読み替えてください\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch3 id=\"httpdが使う証明書を配置\"\u003ehttpdが使う証明書を配置\u003c/h3\u003e\n\u003cp\u003e　私は以下の様にして、httpサーバ用の証明書を配置した。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 証明書を作成したディレクトリへ移動\ncd ~/sslLocal/*\n\n# ファイル内容を確認し、証明書の公開鍵と秘密鍵があることを確認する。\nls\n-rw-------⠀username⠀1708⠀Nov  4 02:06:02⠀⠀mydomain.name-key.pem\n-rw-r--r--⠀username⠀1452⠀Nov  4 02:06:02⠀⠀mydomain.name.pem\n\n# httpdのconfigがあるところに、証明書を置いておく場所も作る。\nsudo mkdir /etc/httpd/conf/ssl\n\n# 署名書を作成したフォルダまで移動する。\ncp ~/sslLocal/* /etc/httpd/conf/ssl/\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"httpdの設定\"\u003ehttpdの設定\u003c/h3\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003essl通信に必要なモジュールを読み込む。\u003c/p\u003e","title":"https通信をプライベートネットワークで使いたい"},{"content":"この記事を書いた動機 特に、2015年以降の買収済みのyoutube（というかgoogle）はどうも営利企業としての側面をあらわにしているのか、広告ブロックされる理由を考えて対応するより先に、広告ブロックを悪者にして追い出したり、利用者に対して一方的な方針転換やサービスの実装をしているようである。\nその波が、動画をダウンロードするこのコマンドにも来ているようで、なんか年齢制限でダウンロードできないというあまりに不便な挙動をしていることに気づいた。何とかしようと考えるわけだが、なかなか面倒だったし、思い出せる自信もないので、結構いい加減だけど、記録を残すことにした。\n環境について 私は普段、windows を使っておらず、linux環境しか使ってないです。なのでこの記事は、windows ユーザにとってはずれているところがあったりと、微妙なところがあるかもしれません。\n制限を突破する方法 yt-dlpコマンドのプラグインを使う。 yt-dlpコマンドの以下のオプションを使う。 yt－dlp [urlとか] --cookies [クッキーのテキストファイルのパス] ※ これは自分のGoogleアカウントでyoutubeにログインすると、そのログイン状態を保持するための情報がcookieに入っていることを利用していると思われる。そのログイン情報が悪用される可能性があるかは未知数。。。なので、なるべくサブのアカウントなどの利用を推奨する。 今とにかく動いた方法 なんか最初にやったことから書いたらグダグダになったので、いったんとにかく動作確認ができた方法から記録してみる。\nyoutubeからcookieを抽出\nyoutubeにログインし、cookieを抽出可能な拡張機能をインストールして、抽出する。私は、Get cookies.txt LOCALLYという拡張機能を利用した。どうも、yt-dlpは、Netscapeとかいう古のブラウザのcookie形式でしか受け付けないらしく、javascriptでdocument.cookieとかやって得られる情報そのままではだめらしいので、楽な方に流れたという感じ。\nyt-dlpでcookieのテキストファイルを指定し、実際に動画をダウンロード\nyt－dlp [urlとか] --cookies [クッキーのテキストファイルのパス] とにかく、これで一時的に動かすことができたが、セッションが有効期限切れになったりすると、たぶんまた作業をやり直す必要があり面倒である。\ncookieのテキストファイルって何？ Netscape形式の場合、以下に示すようなものであるよう。\n# Netscape HTTP Cookie File # http://curl.haxx.se/rfc/cookie_spec.html # This is a generated file! Do not edit. .youtube.com\tTRUE\t/\tTRUE\t1741146319\tLOGIN_INFO\t何かのデータ .youtube.com\tTRUE\t/\tFALSE\t1763243188\tSID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-1PSID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-3PSID\t何かのデータ .youtube.com\tTRUE\t/\tFALSE\t1763243188\tHSID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\tSSID\t何かのデータ .youtube.com\tTRUE\t/\tFALSE\t1763243188\tAPISID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\tSAPISID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-1PAPISID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-3PAPISID\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1764701056\tPREF\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1761676825\t__Secure-1PSIDTS\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1761676825\t__Secure-3PSIDTS\t何かのデータ .youtube.com\tTRUE\t/\tFALSE\t1761677056\tSIDCC\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1761677056\t__Secure-1PSIDCC\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1761677056\t__Secure-3PSIDCC\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1745681252\tVISITOR_PRIVACY_METADATA\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t1745681252\tVISITOR_INFO1_LIVE\t何かのデータ .youtube.com\tTRUE\t/\tTRUE\t0\tYSC\t何かのデータ 以降の内容 これ以降の内容は、単に記録として適当にグダグダ書いてあるので、詳しいことを知りたい人以外には、あまり有用ではない可能性があるということだけはここに書いておく。\n最初にやったこと 最初は、自分のアカウントを使ってどうこうしないといけないということ自体が、そもそも嫌だったので、とりあえずプラグインに頼ってみようと考えた。\nしかし、今のところプラグイン自体は動きはするものの、インストールしずらいわ、目的の機能は動かないわで、なんかうまくいかなかった。私はgithubにある、pukkandan/yt-dlp-YTAgeGateBypass というやつを試していた。\n具体的には、まずどうやってプラグインをインストールすればいいのかというところでいったんつまずいた。でも、これに関しては以下のように、yt-dlpの方に説明があったので、ややこしかったが何とかなった。以下の引用には私が注目したところだけで、すべては載せていないので、必要に応じて各自直接サイトに出向いて確認してほしいと思う。\n引用した部分へのURL https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#plugins https://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#installing-plugins PLUGINS \u0026hellip;\nyt_dlp_plugins/ extractor/ myplugin.py postprocessor/ myplugin.py yt-dlp looks for these yt_dlp_plugins namespace folders in \u0026gt; many locations (see below) and loads in plugins from all of \u0026gt; them. Set the environment variable YTDLP_NO_PLUGINS to \u0026gt; something nonempty to disable loading plugins entirely.\n\u0026hellip;\nInstalling Plugins Plugins can be installed using various methods and \u0026gt; locations.\nConfiguration directories: Plugin packages (containing a \u0026gt; yt_dlp_plugins namespace folder) can be dropped into the \u0026gt; following standard configuration locations:\nUser Plugins ... ~/yt-dlp-plugins/\u0026lt;package name\u0026gt;/yt_dlp_plugins/ ... 上記に引用した情報を参考にして、以下のようにyt-dlpのプラグインをインストールした。\n具体的な方法 プラグインをインストールするフォルダを用意し、そこへ移動する。 mkdir -p ~/yt-dlp-plugins/ cd ~/yt-dlp-plugins/ プラグインのリポジトリをクローンする。 git clone https://github.com/pukkandan/yt-dlp-YTAgeGateBypass プラグインの説明にある\u0026quot;\u0026ndash;extractor-args youtube:no-video-proxy\u0026quot;を引数として、yt-dlpに渡し、動作確認する。 yt－dlp [urlとか] --extractor-args youtube:no-video-proxy ちなみに、最終的にこの方法でプラグインが実際に動いていることは確認できたが、どうもプラグインが必要とするサーバがここ最近一週間くらい動いていない状態になってる。プラグインやyoutubeの動向に雲行きがかかっている模様で、本来の機能である年齢制限回避は動かなかった。githubのissueに、同じことについて書いてある。\n個人的には、issueにある以下のコメントが気になった。Google の Don\u0026rsquo;t be evil の方針崩れ、金や自分たちのエゴのためなら、Be evil みたいな雰囲気を感じられることについて、共通する点が含まれていて、普通に共感できるなと思った。\nVangelis66 commented last week The upstream service (age-verified YT account proxy) this AGB plugin uses under the hood has been DOWN for some weeks now; it\u0026rsquo;s uncertain when/if it\u0026rsquo;ll be back on and at what state; latest words from the maintainers:\nzerodytrash/Simple-YouTube-Age-Restriction-Bypass#262 (comment)\n(With most-evil Google 😡 breaking the known A-G-B hacks recently, why does this \u0026ldquo;coincidence\u0026rdquo; wake up the conspiracy-theorist inside me? 😉 )\n補足情報 Simple-YouTube-Age-Restriction-Bypassというプラグインもあるらしいが、とにかく動いたし、疲れたのでまだ試していない。\npukkandan/yt-dlp-YTAgeGateBypass の方にもっと簡単そうなpipを使ったインストール方法があるじゃんと思うかもしれない。しかし、私の環境では、Anacondaとかいろいろ入っててやりずらかったので、そちらの方法は最初は使おうとしていたのだけど、動いているのかわからず諦めた。\n思うのだけど、yt-dlpコマンドのプラグイン導入はなんか本当に動いているのか、間接的にしか確認できなくて辛い。プラグイン自体が読み込まれ動いているのかという確認は、以下のようにpythonがモジュール等に対して作るキャッシュファイル（__pycache__）がyt-dlpコマンド実行時に作られるかどうかで判定した。\n userName on  ~/yt-dlp-plugins/yt-dlp-YTAgeGateBypass/yt_dlp_plugins/extractor  master # ls drwxr-xr-x⠀userName⠀4096⠀Oct 29 03:31:04⠀⠀__pycache__/ -rw-r--r--⠀userName⠀3482⠀Oct 29 03:23:07⠀⠀yt_agb.py 次にやったこと 次にやったことは、ブラウザのcookie情報を素直に利用して、年齢制限付きの動画をダウンロードしようと試みた。まずは、yt-dlpの以下のオプションを利用して、やってみた。ちなみに、すでにchrome側ではyoutubeにログインした状態かつ、一つのプロファイルしかない状態である。\n# yt－dlp [urlとか] --cookies-from-browser BROWSER[+KEYRING][:PROFILE][::CONTAINER] yt－dlp [urlとか] --cookies-from-browser chrome # 以下は実行結果  userName on  ~/work/temp # yt-dlp https://www.youtube.com/watch?v=[videoID] --cookies-from-browser chrome Extracting cookies from chrome [Cookies] Loading cookie 0/ 65WARNING: cannot decrypt v11 cookies: no key found Extracted 0 cookies from chrome (65 could not be decrypted) [youtube+AGB] Extracting URL: https://www.youtube.com/watch?v=[videoID] [youtube+AGB] [videoID]: Downloading webpage [youtube+AGB] [videoID]: Downloading ios player API JSON [youtube+AGB] [videoID]: Downloading tv embedded player API JSON [youtube+AGB] [videoID]: Downloading web embedded client config [youtube+AGB] [videoID]: Downloading player 576f07ca [youtube+AGB] [videoID]: Downloading web embedded player API JSON [youtube+AGB] [videoID]: Downloading Zerody API JSON WARNING: [youtube+AGB] Unable to download JSON metadata: HTTP Error 502: Bad Gateway ERROR: [youtube+AGB] [videoID]: Sign in to confirm your age. This video may be inappropriate for some users. # なんかcookie読み込んでるぽいけど、復号に失敗してるっぽく、なんでダメなのかなぁ。。。探せば何とかなるかもだけど、もう疲れたや こんな感じでうまくいかず、さらにめんどくさく感じて、最初のクッキーのテキストファイルを直接渡す方法を試すに至り、とにかく年齢制限付きの動画をダウンロードできるようになった。\n正直なことを言えば、アカウントなしで何とかなる方法を模索することには興味がある。\n追記あり yt-dlpコマンドで、年齢制限を何とかするの追記 ニコニコ動画にパスワードログインできない件について、yt-dlp のリポジトリに issue を立ててしまう。 参考にしたサイト Plugins · yt-dlp/yt-dlp Wiki · GitHub\nhttps://github.com/yt-dlp/yt-dlp/wiki/Plugins （2024年10月29日） GitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloader\nhttps://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#plugins （2024年10月29日） GitHub - yt-dlp/yt-dlp: A feature-rich command-line audio/video downloader\nhttps://github.com/yt-dlp/yt-dlp?tab=readme-ov-file#installing-plugins （2024年10月29日） GitHub - pukkandan/yt-dlp-YTAgeGateBypass: A yt-dlp extractor plugin to bypass YouTube age-gate\nhttps://github.com/pukkandan/yt-dlp-YTAgeGateBypass （2024年10月29日） Sign in to confirm your age. This video may be inappropriate for some users. · Issue #4 · pukkandan/yt-dlp-YTAgeGateBypass · GitHub\nhttps://github.com/pukkandan/yt-dlp-YTAgeGateBypass/issues/4 （2024年10月29日） GitHub - zerodytrash/Simple-YouTube-Age-Restriction-Bypass: A simple browser extension to bypass YouTube\u0026rsquo;s age verification, disable content warnings and watch age restricted videos without having to sign in!\nhttps://github.com/zerodytrash/Simple-YouTube-Age-Restriction-Bypass （2024年10月29日） Get cookies.txt LOCALLY - Chrome Web Store\nhttps://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc?hl=en （2024年10月29日） ","permalink":"https://www.nyanmo.info/posts/yt-dlp/bypassagegate/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　 特に、2015年以降の買収済みのyoutube（というかgoogle）はどうも営利企業としての側面をあらわにしているのか、広告ブロックされる理由を考えて対応するより先に、広告ブロックを悪者にして追い出したり、利用者に対して一方的な方針転換やサービスの実装をしているようである。\u003c/p\u003e\n\u003cp\u003e　その波が、動画をダウンロードするこのコマンドにも来ているようで、なんか年齢制限でダウンロードできないというあまりに不便な挙動をしていることに気づいた。何とかしようと考えるわけだが、なかなか面倒だったし、思い出せる自信もないので、結構いい加減だけど、記録を残すことにした。\u003c/p\u003e\n\u003ch2 id=\"環境について\"\u003e環境について\u003c/h2\u003e\n\u003cp\u003e　私は普段、windows を使っておらず、linux環境しか使ってないです。なのでこの記事は、windows ユーザにとってはずれているところがあったりと、微妙なところがあるかもしれません。\u003c/p\u003e\n\u003ch2 id=\"制限を突破する方法\"\u003e制限を突破する方法\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eyt-dlpコマンドのプラグインを使う。\u003c/li\u003e\n\u003cli\u003eyt-dlpコマンドの以下のオプションを使う。\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eyt－dlp [urlとか] --cookies [クッキーのテキストファイルのパス]\n\u003c/code\u003e\u003c/pre\u003e※ これは自分のGoogleアカウントでyoutubeにログインすると、そのログイン状態を保持するための情報がcookieに入っていることを利用していると思われる。そのログイン情報が悪用される可能性があるかは未知数。。。なので、なるべくサブのアカウントなどの利用を推奨する。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"今とにかく動いた方法\"\u003e今とにかく動いた方法\u003c/h2\u003e\n\u003cp\u003e　なんか最初にやったことから書いたらグダグダになったので、いったんとにかく動作確認ができた方法から記録してみる。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003eyoutubeからcookieを抽出\u003cbr\u003e\n　youtubeにログインし、cookieを抽出可能な拡張機能をインストールして、抽出する。私は、\u003ca href=\"https://chromewebstore.google.com/detail/get-cookiestxt-locally/cclelndahbckbenkjhflpdbgdldlbecc?hl=en\"\u003eGet cookies.txt LOCALLY\u003c/a\u003eという拡張機能を利用した。どうも、yt-dlpは、Netscapeとかいう古のブラウザのcookie形式でしか受け付けないらしく、javascriptで\u003ccode\u003edocument.cookie\u003c/code\u003eとかやって得られる情報そのままではだめらしいので、楽な方に流れたという感じ。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eyt-dlpでcookieのテキストファイルを指定し、実際に動画をダウンロード\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eyt－dlp [urlとか] --cookies [クッキーのテキストファイルのパス]\n\u003c/code\u003e\u003c/pre\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e　とにかく、これで一時的に動かすことができたが、セッションが有効期限切れになったりすると、たぶんまた作業をやり直す必要があり面倒である。\u003c/p\u003e\n\u003ch2 id=\"cookieのテキストファイルって何\"\u003ecookieのテキストファイルって何？\u003c/h2\u003e\n\u003cp\u003e　Netscape形式の場合、以下に示すようなものであるよう。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# Netscape HTTP Cookie File\n# http://curl.haxx.se/rfc/cookie_spec.html\n# This is a generated file!  Do not edit.\n\n.youtube.com\tTRUE\t/\tTRUE\t1741146319\tLOGIN_INFO\t何かのデータ\n.youtube.com\tTRUE\t/\tFALSE\t1763243188\tSID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-1PSID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-3PSID\t何かのデータ\n.youtube.com\tTRUE\t/\tFALSE\t1763243188\tHSID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\tSSID\t何かのデータ\n.youtube.com\tTRUE\t/\tFALSE\t1763243188\tAPISID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\tSAPISID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-1PAPISID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1763243188\t__Secure-3PAPISID\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1764701056\tPREF\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1761676825\t__Secure-1PSIDTS\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1761676825\t__Secure-3PSIDTS\t何かのデータ\n.youtube.com\tTRUE\t/\tFALSE\t1761677056\tSIDCC\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1761677056\t__Secure-1PSIDCC\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1761677056\t__Secure-3PSIDCC\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1745681252\tVISITOR_PRIVACY_METADATA\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t1745681252\tVISITOR_INFO1_LIVE\t何かのデータ\n.youtube.com\tTRUE\t/\tTRUE\t0\tYSC\t何かのデータ\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"以降の内容\"\u003e以降の内容\u003c/h2\u003e\n\u003cp\u003e　これ以降の内容は、単に記録として適当にグダグダ書いてあるので、詳しいことを知りたい人以外には、あまり有用ではない可能性があるということだけはここに書いておく。\u003c/p\u003e","title":"yt-dlpコマンドで、年齢制限を何とかする"},{"content":"この記事を書いた動機 ただの自分用のよく使う設定集としてのメモ。基本的にgnome標準で付いてくると思われるgsettingsコマンドを使う。\n環境 細かいことは書かないけど一応\ngnome wayland Xwayland no X11 4kなどの高解像度ディスプレイ gnome の有効化（一応） gnomeのディスプレイマネージャーを単にsystemdのサービスとして起動時に立ち上がってくれるように有効にするだけ。Windowsで言ったら、logonui.exeかみたいなやつに近い気がする。\nsystemctl enable gdm トラックパッドの設定 物理ボタンではなく、タップしている領域で右クリックか判定しているトラックパッド用の設定。\ngsettings set org.gnome.desktop.peripherals.touchpad click-method \u0026#39;areas\u0026#39; ウィンドウのボタン 最大化、ウィンドウモードとかのボタンなどのWindowsでは標準の機能がデフォルトで無効になっているので、有効にする。\ngsettings set org.gnome.desktop.wm.preferences button-layout \u0026#34;:minimize,maximize,close\u0026#34; スケーリングの設定 スケーリングとか、gnomeの実験的な機能として現在（2024年10月27日）組み込まれている機能を有効化する。よくバグる。\n# 125% とかもっと細かいスケーリングを有効にできる。ある程度は実用できる段階に体感では感じるが、Xwaylandのアプリが思いっきりぼけてしまう。 gsettings set org.gnome.mutter experimental-features \u0026#34;[\u0026#39;scale-monitor-framebuffer\u0026#39;]\u0026#34; # Xwayland で動くアプリがぼけないようにする、欲張り設定。中途半端な125%とかの設定と併用すると、変にウィンドウが特定の領域でしか反応しなくなるなど、バグが多い。 gsettings set org.gnome.mutter experimental-features \u0026#34;[\u0026#39;scale-monitor-framebuffer\u0026#39;,\u0026#39;xwayland-native-scaling\u0026#39;]\u0026#34; ちなみに、Xwaylandの「xwayland-native-scaling」などは、以下のサイト(githubのmutterのリポジトリ)で設定値の存在を確認できる。 https://github.com/GNOME/mutter/blob/main/data/org.gnome.mutter.gschema.xml.in\n例えば、こんな感じで書いてある。何か気になるのがあったら、仮想マシンかなんかで使う前に試してみるといいかもしれない。\n\u0026lt;schemalist\u0026gt; \u0026lt;flags id=\u0026#34;org.gnome.mutter.MetaExperimentalFeature\u0026#34;\u0026gt; \u0026lt;value nick=\u0026#34;scale-monitor-framebuffer\u0026#34; value=\u0026#34;1\u0026#34;/\u0026gt; \u0026lt;value nick=\u0026#34;kms-modifiers\u0026#34; value=\u0026#34;2\u0026#34;/\u0026gt; \u0026lt;value nick=\u0026#34;autoclose-xwayland\u0026#34; value=\u0026#34;4\u0026#34;/\u0026gt; \u0026lt;value nick=\u0026#34;variable-refresh-rate\u0026#34; value=\u0026#34;8\u0026#34;/\u0026gt; \u0026lt;value nick=\u0026#34;xwayland-native-scaling\u0026#34; value=\u0026#34;16\u0026#34;/\u0026gt; \u0026lt;/flags\u0026gt; カーソルの大きさ サイズの取得 gsettings get org.gnome.desktop.interface cursor-size サイズの変更 gsettings set org.gnome.desktop.interface cursor-size 12 設定のリセット gsettings list-schemas | xargs -n 1 gsettings reset-recursively fcitx5 日本語環境についても、いちいち調べるのはめんどくさいので、今日（2024/11/14）追記してみることにした。\nyay 今回は、いろんなソフトウェアをインストールするために、yay コマンドを使うので、インストールしておく。一応、インストールについては、yay コマンドのインストールに記録がある。二番煎じですが、、、\nパッケージのインストール 私は普段 fcitx5 を常用しているので、それらをインストール。\n# 通常はこれだけ入れればうまく行くかも yay -S fcitx5 fcitx5-mozc fcitx5-input-support fcitx5-configtool # yay -S fcitx5 fcitx5-mozc fcitx5-input-support fcitx5-configtool # なんかうまく動かないと思ったらここらへんも確認してみるといいかも yay -S fcitx5-qt fcitx5-gtk fcitx5-anthy ちなみに、私の環境だと、以下のパッケージを入れている。\nyay -Qs fcitx5 local/fcitx5 5.1.11-1 (fcitx5-im) Next generation of fcitx local/fcitx5-anthy 5.1.5-1 Anthy Wrapper for Fcitx5 local/fcitx5-configtool 5.1.7-1 (fcitx5-im) Configuration Tool for Fcitx5 local/fcitx5-gtk 5.1.3-1 (fcitx5-im) Fcitx5 gtk im module and glib based dbus client library local/fcitx5-input-support 2021.09-1 Asian input support for fcitx5 local/fcitx5-mozc 2.26.4632.102.g4d2e3bd-2 Fcitx5 Module of A Japanese Input Method for Chromium OS, Windows, Mac and Linux (the Open Source Edition of Google Japanese Input) local/fcitx5-qt 5.1.8-1 (fcitx5-im) Fcitx5 Qt Library (Qt5 \u0026amp; Qt6 integrations) 環境変数の設定 環境変数を設定して、Gnomeなどにfcitx5を認識させる。\nsudo nvim /etc/environment 私の場合は、環境変数をこのように設定している。\n# # This file is parsed by pam_env module # # Syntax: simple \u0026#34;KEY=VAL\u0026#34; pairs on separate lines # GTK_IM_MODULE=fcitx5 QT_IM_MODULE=fcitx5 XMODIFIERS=@im=fcitx5 ちなみに \u0026ldquo;5\u0026quot;はなくてもいいらしいが、一応これで動いてるのでそのままにしている。\nGnome拡張機能のインストール Gnomeでは、ブラウザを経由して拡張機能を導入するという形になっているが、そのためのパッケージをインストールする必要がある。一応拡張機能をインストールして、Gnomeの拡張機能の配布場所へ飛び、なにかインストールしようとすれば、何が足りないと出てくるのでそれに従えばいいと思う。\n一応記録を残すならば、まずはブラウザとGnomeを仲介するパッケージを以下のようにしてインストールする必要がある。\nyay -S gnome-browser-connector 次に、ブラウザごとに多分固有だと思うが、chromeの場合はここの拡張機能を入れれば準備完了だと思われる。\nGnomeを使っている場合は、Input Method Panelという拡張機能を使うように、言われるのでインストールする。なくても動くっぽいが、そのときはアプリ次第では、変換候補の表示位置がおかしいなどのバグが出る可能性が高くなる模様。\nfcitx5の設定 fcitx5-configtoolをインストールしていれば、こんな感じでアプリ一覧とかにそれがあると思うので、それを起動する。\n以下のようにして、Mozcを使うように、fcitx5を設定し、キーボードレイアウトも適宜合わせる。\nここまでくれば、再起動すれば、だいたいの日本語入力とかができると思われる。よく、うまく行かないこともあるが、それはもうその都度調べてみるしかないと思う。\nGoogle-Chrome と fcitx5 設定 (~/.config/chrome-flags.conf) # 関係ありそうな部分 --gtk-version=4 --wayland-text-input-version=3 --enable-wayland-ime # 関係なさそうな部分 --enable-features=Vulkan --enable-features=UseOzonePlatform --ozone-platform=wayland #--ozone-platform=x11 --disable-features=UseChromeOSDirectVideoDecoder #--enable-features=VaapiVideoDecodeLinuxGL --enable-features=AcceleratedVideoDecodeLinuxGL --disable-features=GlobalShortcutsPortal fcitx5 で Google-Chrome 系だけ入力がうまく行かないとき fcitx5 を再起動する。\npkill fcitx5 fcitx5 \u0026amp; サスペンド防止 サーバ用途において GNOME 環境を使う場合は、自動でサスペンドしたりすると、機能をその時点で停止してしまい、サーバとして使えない。\ngsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-ac-timeout 0 gsettings set org.gnome.settings-daemon.plugins.power sleep-inactive-battery-timeout 0 sudo systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target 関連するページ ここには、適当にこのページと関係ありそうな話題の記事を適当にリストアップしておきます。\nGnome Mutter と ネットワーク共有フォルダ(SMB CIFS) Google Chrome がいちいちデフォルトブラウザにするようにと強引に広告出してくるのを止める 電力プロファイル設定をできるようにする yay コマンドのインストール Linux 環境におけるフォント設定 UEFI の起動エントリに Linux 環境を追加する 参考にしたサイト Gnome 40 | enable right click button on touchpad of notebook : r/gnome\nhttps://www.reddit.com/r/gnome/comments/nvcqtx/gnome_40_enable_right_click_button_on_touchpad_of/ （2024年10月27日）\ncustomization - How to bring back minimize and maximize buttons in Gnome 3 - Ask Ubuntu\nhttps://askubuntu.com/questions/651347/how-to-bring-back-minimize-and-maximize-buttons-in-gnome-3 （2024年10月27日）\nFractional scaling on gnome - Desktop Environments / Gnome - EndeavourOS\nhttps://forum.endeavouros.com/t/fractional-scaling-on-gnome/57254/2 （2024年10月27日）\nmutter/data/org.gnome.mutter.gschema.xml.in at main · GNOME/mutter · GitHub\nhttps://github.com/GNOME/mutter/blob/main/data/org.gnome.mutter.gschema.xml.in （2024年10月27日）\nGNOME Shell Extensions\nhttps://extensions.gnome.org/ （2024年11月14日）\nInput Method Panel - GNOME Shell Extensions\nhttps://extensions.gnome.org/extension/261/kimpanel/ （2024年11月14日）\nFcitx5 - ArchWiki\nhttps://wiki.archlinux.jp/index.php/Fcitx5 （2024年11月14日）\nGNOME Shell integration - Chrome ウェブストア\nhttps://chromewebstore.google.com/detail/gnome-shell-integration/gphhapmejobijbbhgpjhcjognlahblep?hl=ja\u0026amp;pli=1 （2024年11月14日）\nSetting cursor size in Gnome - Xorg and Gui - Linux Tips\nhttps://linux-tips.com/t/setting-cursor-size-in-gnome/835 （2025年3月26日）\ncommand line - How do I reset all GSettings key to their default values? - Ask Ubuntu\nhttps://askubuntu.com/questions/393772/how-do-i-reset-all-gsettings-key-to-their-default-values/582039#582039 （2025年3月28日）\nGNOMEの自動スリープを無効にする | minetaro12\nhttps://0sn.net/posts/20250331/gnome-disable-sleep/ (2026年8月4日)\nsuspend - How do I disable my system from going to sleep? - Ask Ubuntu\nhttps://askubuntu.com/questions/47311/how-do-i-disable-my-system-from-going-to-sleep (2026年8月4日)\n","permalink":"https://www.nyanmo.info/posts/linux/gnomesettings/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003eただの自分用のよく使う設定集としてのメモ。基本的にgnome標準で付いてくると思われるgsettingsコマンドを使う。\u003c/p\u003e\n\u003ch2 id=\"環境\"\u003e環境\u003c/h2\u003e\n\u003cp\u003e細かいことは書かないけど一応\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003egnome\u003c/li\u003e\n\u003cli\u003ewayland\u003c/li\u003e\n\u003cli\u003eXwayland\u003c/li\u003e\n\u003cli\u003eno X11\u003c/li\u003e\n\u003cli\u003e4kなどの高解像度ディスプレイ\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"gnome-の有効化一応\"\u003egnome の有効化（一応）\u003c/h2\u003e\n\u003cp\u003egnomeのディスプレイマネージャーを単にsystemdのサービスとして起動時に立ち上がってくれるように有効にするだけ。Windowsで言ったら、logonui.exeかみたいなやつに近い気がする。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003esystemctl enable gdm\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"トラックパッドの設定\"\u003eトラックパッドの設定\u003c/h2\u003e\n\u003cp\u003e物理ボタンではなく、タップしている領域で右クリックか判定しているトラックパッド用の設定。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egsettings set org.gnome.desktop.peripherals.touchpad click-method \u0026#39;areas\u0026#39;\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"ウィンドウのボタン\"\u003eウィンドウのボタン\u003c/h2\u003e\n\u003cp\u003e最大化、ウィンドウモードとかのボタンなどのWindowsでは標準の機能がデフォルトで無効になっているので、有効にする。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egsettings set org.gnome.desktop.wm.preferences button-layout \u0026#34;:minimize,maximize,close\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"スケーリングの設定\"\u003eスケーリングの設定\u003c/h2\u003e\n\u003cp\u003eスケーリングとか、gnomeの実験的な機能として現在（2024年10月27日）組み込まれている機能を有効化する。よくバグる。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# 125% とかもっと細かいスケーリングを有効にできる。ある程度は実用できる段階に体感では感じるが、Xwaylandのアプリが思いっきりぼけてしまう。\ngsettings set org.gnome.mutter experimental-features \u0026#34;[\u0026#39;scale-monitor-framebuffer\u0026#39;]\u0026#34;\n\n# Xwayland で動くアプリがぼけないようにする、欲張り設定。中途半端な125%とかの設定と併用すると、変にウィンドウが特定の領域でしか反応しなくなるなど、バグが多い。\ngsettings set org.gnome.mutter experimental-features \u0026#34;[\u0026#39;scale-monitor-framebuffer\u0026#39;,\u0026#39;xwayland-native-scaling\u0026#39;]\u0026#34;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eちなみに、Xwaylandの「xwayland-native-scaling」などは、以下のサイト(githubのmutterのリポジトリ)で設定値の存在を確認できる。\n\u003ca href=\"https://github.com/GNOME/mutter/blob/main/data/org.gnome.mutter.gschema.xml.in\"\u003ehttps://github.com/GNOME/mutter/blob/main/data/org.gnome.mutter.gschema.xml.in\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e例えば、こんな感じで書いてある。何か気になるのがあったら、仮想マシンかなんかで使う前に試してみるといいかもしれない。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;schemalist\u0026gt;\n\n  \u0026lt;flags id=\u0026#34;org.gnome.mutter.MetaExperimentalFeature\u0026#34;\u0026gt;\n    \u0026lt;value nick=\u0026#34;scale-monitor-framebuffer\u0026#34; value=\u0026#34;1\u0026#34;/\u0026gt;\n    \u0026lt;value nick=\u0026#34;kms-modifiers\u0026#34; value=\u0026#34;2\u0026#34;/\u0026gt;\n    \u0026lt;value nick=\u0026#34;autoclose-xwayland\u0026#34; value=\u0026#34;4\u0026#34;/\u0026gt;\n    \u0026lt;value nick=\u0026#34;variable-refresh-rate\u0026#34; value=\u0026#34;8\u0026#34;/\u0026gt;\n    \u0026lt;value nick=\u0026#34;xwayland-native-scaling\u0026#34; value=\u0026#34;16\u0026#34;/\u0026gt;\n  \u0026lt;/flags\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003c/blockquote\u003e\n\u003ch2 id=\"カーソルの大きさ\"\u003eカーソルの大きさ\u003c/h2\u003e\n\u003ch3 id=\"サイズの取得\"\u003eサイズの取得\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egsettings get org.gnome.desktop.interface cursor-size\n\u003c/code\u003e\u003c/pre\u003e\u003ch3 id=\"サイズの変更\"\u003eサイズの変更\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egsettings set org.gnome.desktop.interface cursor-size 12\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"設定のリセット\"\u003e設定のリセット\u003c/h2\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003egsettings list-schemas | xargs -n 1 gsettings reset-recursively\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"fcitx5\"\u003efcitx5\u003c/h2\u003e\n\u003cp\u003e　日本語環境についても、いちいち調べるのはめんどくさいので、今日（2024/11/14）追記してみることにした。\u003c/p\u003e","title":"gnomeの設定のメモ ⚙"},{"content":"この記事を書いた動機 ここでは前回、hugoのショットコードを使えば、もっといい感じに画像を表示できるように調整できるのではということがあったので、それをやってみた過程を記録します。\nhugo のセーフティーを外さないで、画像を自在に表示できるはずだと思っていたのと、shortcodes について調べているうちに、テーマ側に画像を表示するための、figure という shortcode を見つけたというのがある。\n./theme/テーマ名/layouts/shortcodes/figure.html の存在に気づくことが、figure 発見のきっかけであった。\nFeatures / Mods | PaperModでは、どうやって画像を表示するのか、私は見つけられなかった。（chrome で figure と検索をかけても出てこないので、ドキュメント見てどうしたら画像を表示できるか、すぐわかる感じじゃなさそう。）\nちなみに、かろうじて figure shortcode が、 FAQs / How To\u0026rsquo;s Guide | PaperMod にどうやったら画像を中心揃えにできるかという話題で載っていた。\nこの記事の目的 明らかによくないことを書き直す 前回のhugoで画像を追加する 📷では、hugo のセーフティを外すなど、よくない方法を紹介してしまっているので、それをできる範囲で改めようと試みる。多分今回の方法であれば、セーフティを外さなくてもうまくいくはずであるが、試す気力もないので検証はまだしていない。\n放置記事を何とかする そもそも、下の引用文にも書いてあるように、hugoで画像を追加する 📷の続きをすぐ書こうと当時思っていたのだが、結局やらずに何カ月も下書きのまま放置してたので、再び戻ってくることにした。\nもっとよさそうな方法 hugo 内蔵の画像表示機能を使う。\n追記（2025年1月26日）\nHugo 自体にはそんなものない。hugo の shortcodes というのを使って、自分で画像を表示するコードを書くか、テーマごとに用意された画像を表示するための shortcodes を使うことはできる。また、マークダウン形式でも画像を張り付けられるが、細かいスタイルの調整はできなかったと思う。 さらなる追記 (2025年1月30日) 今回、新たな間違いに気づいたので、ここにもその記録置いときます。。。なんでドキュメント見て気づけなかったんだろうとそんな気持ちです。。。（実は間違っていたと思っていることはあっていた。。。）\n追記 (2025年1月30日)\n今気づいたが、実は組み込みで、hugoに figure っていうのが入っていることに気づいた。hugo自体に画像を表示する機能がないというのは間違いで、気づけてないだけだった。 Figure | Hugo shortcode で画像を表示する 選択肢 テーマ付属の shortcode を使う\n自分で shortcode を適当に作る\nhugo 内臓の figure shortcode を使う\n（今回は検証とかしてないです。 追記: 2025年1月30日）\nFigure | Hugo\nテーマ付属の shortcode の例（PaperModの場合） 以下のようにして、記事のマークダウン中に figure という shortcode を呼び出す。\n{{\u0026lt; figure src=\u0026#34;/images/freedraw/test.png\u0026#34; title=\u0026#34;ゆっくりれいむもどき (2024/12/31)\u0026#34; caption=\u0026#34;with XPS 15 2-in-1 (9575), HP Active Style Pen (Gen3) and 釘で作ったペン先、、、\u0026#34; align=\u0026#34;center\u0026#34; width=\u0026#34;70%\u0026#34;\u0026gt;}} {{\u0026lt; figure src=\u0026#34;staticフォルダからの画像の場所\u0026#34; title=\u0026#34;タイトル\u0026#34; caption=\u0026#34;説明文\u0026#34; align=\u0026#34;center\u0026#34; width=\u0026#34;70%\u0026#34; \u0026gt;}} 画像の配置は、hugo の作業ディレクトリからして、static という所に配置することができる。\n... ./content/... ./static/ここの中のどこかに画像を置く ./hugo.yaml ... テーマ付属の shortcode の実演例（PaperModの場合） ゆっくりれいむもどき (2024/12/31)with XPS 15 2-in-1 (9575), HP Active Style Pen (Gen3) and 釘で作ったペン先、、、\n自分で作る場合 hugo の作業ディレクトリからして layouts というフォルダの中の shortcodes というところに、\u0026quot;[shortcode名].html\u0026quot; という風にファイルを作成し、html を記述するようにして自由に表示したい内容をかく。\n... ./content/... ./layouts/shortcodes/○○.html ./layouts/shortcodes/[shortcode名].html ./layouts/shortcodes/○○.html ./hugo.yaml ... もし CSS や JavaScript 必要なら、画像を配置するのと同じ要領で、static フォルダのどこかにおいておく。イメージとしては以下のようになる。\n... ./content/... ... ./static/JS/○○.js ./static/JS/imgViewer.js ./static/JS/○○.js ... ./static/CSS/○○.css ./static/CSS/imgShow.css ./static/CSS/○○.css ... ./hugo.yaml ... ちなみにただ置いただけだと、CSS も JavaScript も読み込まれないので、テーマ側を少しいじる必要がある。私は、\u0026ldquo;baseof.html\u0026rdquo; という、hugoでいろんなページを生成するときの基本になるテーマ側の html テンプレート再定義することで読み込ませている。\nすでにテーマを導入している場合も、./layouts フォルダ内に、./themes/テーマ名/layouts の再定義したい部分だけコピーして改変すれば、テーマ更新時以外はとりあえず動くと思われる。\n./layouts/_default/baseof.html {{- if lt hugo.Version \u0026#34;0.112.4\u0026#34; }} {{- errorf \u0026#34;=\u0026gt; hugo v0.112.4 or greater is required for hugo-PaperMod to build \u0026#34; }} {{- end -}} \u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;{{ site.Language }}\u0026#34; dir=\u0026#34;{{ .Language.LanguageDirection | default \u0026#34;auto\u0026#34; }}\u0026#34;\u0026gt; \u0026lt;head\u0026gt; {{- partial \u0026#34;head.html\u0026#34; . }} {{- partial \u0026#34;customHead.html\u0026#34; . }} \u0026lt;/head\u0026gt; \u0026lt;body ...\u0026gt; ... {{ partial \u0026#34;imgViewer.html\u0026#34; .}} {{/* {{ partial \u0026#34;chatScript.html\u0026#34; . }} */}} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; ./layouts/partials/customHead.html \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; href=\u0026#34;{{ \u0026#34;css/annotate.css\u0026#34; | relURL }}\u0026#34;\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; href=\u0026#34;{{ \u0026#34;css/hideLongThings.css\u0026#34; | relURL }}\u0026#34;\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; href=\u0026#34;{{ \u0026#34;css/common.css\u0026#34; | relURL }}\u0026#34;\u0026gt; \u0026lt;link rel=\u0026#34;stylesheet\u0026#34; href=\u0026#34;{{ \u0026#34;css/chat.css\u0026#34; | relURL }}\u0026#34;\u0026gt; \u0026lt;script src=\u0026#34;{{ \u0026#34;js/hideLongThings.js\u0026#34; | relURL }}\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; 自分で作る場合の shortcode の例 以下は私の書いている shortcode の例である。相変わらず動くことやとにかく完成させることを最優先でやってるので、あまり参考にはならないと思うが、雰囲気だけでもつかめたらいいと思う。\n./layouts/shortcodes/imgShow.html {{ $width := .Get \u0026#34;width\u0026#34; | default \u0026#34;100%\u0026#34; }} {{ $showTitle := .Get \u0026#34;showTitle\u0026#34; | default \u0026#34;false\u0026#34; }} \u0026lt;div style=\u0026#34;display:flex; justify-content:center; margin:10px; flex-direction: row;\u0026#34;\u0026gt; {{/* {{ $style := printf \u0026#34;width: %s;\u0026#34; (cast.ToString $width) }} */}} {{ $style := printf \u0026#34;width: %s;\u0026#34; (cast.ToString $width) | safeCSS }} \u0026lt;div style=\u0026#34;{{ $style }}\u0026#34;\u0026gt; \u0026lt;img style=\u0026#34;margin:10px;\u0026#34; src={{ .Get \u0026#34;src\u0026#34; }} alt={{ .Get \u0026#34;alt\u0026#34; }}/\u0026gt; {{ if eq $showTitle \u0026#34;true\u0026#34; }} \u0026lt;p style=\u0026#34;text-align: center;\u0026#34;\u0026gt;{{ .Get \u0026#34;alt\u0026#34; }}\u0026lt;/p\u0026gt; {{ end }} \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; ./layouts/shortcodes/align.html {{ $alignDirection := .Get \u0026#34;align\u0026#34; | default }} {{ $align := print \u0026#34;flex-direction: %s;\u0026#34; $alignDirection | safeCSS }} {{ $style := print \u0026#34;display:flex; %s\u0026#34; $align | safeCSS }} \u0026lt;div class=\u0026#34;alignContaier\u0026#34; style={{ $style }}\u0026gt; {{ .Inner }} \u0026lt;/div\u0026gt; ちなみに、上記の例の shortcode を使うには以下のようにする。\n{{\u0026lt; align \u0026gt;}} {{\u0026lt; imgShow src=\u0026#34;/posts/android/firefox/personalCA/caInstall/securitySettings0.png\u0026#34; alt=\u0026#34;CA認証局の証明書インストール\u0026#34; \u0026gt;}} {{\u0026lt; imgShow src=\u0026#34;/posts/android/firefox/personalCA/caInstall/securitySettings.png\u0026#34; alt=\u0026#34;CA認証局の証明書インストール1\u0026#34; \u0026gt;}} {{\u0026lt; imgShow src=\u0026#34;/posts/android/firefox/personalCA/caInstall/securitySettings1.png\u0026#34; alt=\u0026#34;CA認証局の証明書インストール2\u0026#34; \u0026gt;}} {{\u0026lt; /align \u0026gt;}} 自分で作る場合の実演例 参考にしたサイト FAQs / How To\u0026rsquo;s Guide | PaperMod\nhttps://adityatelange.github.io/hugo-PaperMod/posts/papermod/papermod-faq/#centering-image-in-markdown （2025年1月26日） Create your own shortcodes | Hugo\nhttps://gohugo.io/templates/shortcode/ （2025年1月26日） Shortcodes | Hugo\nhttps://gohugo.io/content-management/shortcodes/ （2025年1月26日） Features / Mods | PaperMod\nhttps://adityatelange.github.io/hugo-PaperMod/posts/papermod/papermod-features/ （2025年1月26日） ","permalink":"https://www.nyanmo.info/posts/hugo/addimage2/","summary":"\u003ch2 id=\"この記事を書いた動機\"\u003eこの記事を書いた動機\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003eここでは前回、hugoのショットコードを使えば、もっといい感じに画像を表示できるように調整できるのではということがあったので、それをやってみた過程を記録します。\u003c/del\u003e\u003c/p\u003e\n\u003cp\u003e　hugo のセーフティーを外さないで、画像を自在に表示できるはずだと思っていたのと、shortcodes について調べているうちに、テーマ側に画像を表示するための、figure という shortcode を見つけたというのがある。\u003c/p\u003e\n\u003cp\u003e　./theme/テーマ名/layouts/shortcodes/figure.html の存在に気づくことが、figure 発見のきっかけであった。\u003c/p\u003e\n\u003cp\u003e　\u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/papermod/papermod-features/\"\u003eFeatures / Mods | PaperMod\u003c/a\u003eでは、どうやって画像を表示するのか、私は見つけられなかった。（chrome で figure と検索をかけても出てこないので、ドキュメント見てどうしたら画像を表示できるか、すぐわかる感じじゃなさそう。）\u003c/p\u003e\n\u003cp\u003e　ちなみに、かろうじて figure shortcode が、\n\u003ca href=\"https://adityatelange.github.io/hugo-PaperMod/posts/papermod/papermod-faq/#centering-image-in-markdown\"\u003eFAQs / How To\u0026rsquo;s Guide | PaperMod\u003c/a\u003e にどうやったら画像を中心揃えにできるかという話題で載っていた。\u003c/p\u003e\n\u003cdiv class=\"info titleIconSet\"\u003e\n    \u003cimg class=\"icon\" src=\"/icons/win7Icons/Notepad.png\"\u003e\n    \u003ch2 class=\"iconTitle\"\u003eこの記事の目的\u003c/h2\u003e\n    \n\u003c/div\u003e\n\n\n\u003ch3 id=\"明らかによくないことを書き直す\"\u003e明らかによくないことを書き直す\u003c/h3\u003e\n\u003cp\u003e　前回の\u003ca href=\"https://www.nyanmo.info/posts/hugo/addimage/\"\u003ehugoで画像を追加する 📷\u003c/a\u003eでは、hugo のセーフティを外すなど、よくない方法を紹介してしまっているので、それをできる範囲で改めようと試みる。多分今回の方法であれば、セーフティを外さなくてもうまくいくはずであるが、試す気力もないので検証はまだしていない。\u003c/p\u003e\n\u003ch3 id=\"放置記事を何とかする\"\u003e放置記事を何とかする\u003c/h3\u003e\n\u003cp\u003e　そもそも、下の引用文にも書いてあるように、\u003ca href=\"https://www.nyanmo.info/posts/hugo/addimage/\"\u003ehugoで画像を追加する 📷\u003c/a\u003eの続きをすぐ書こうと当時思っていたのだが、結局やらずに何カ月も下書きのまま放置してたので、再び戻ってくることにした。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2 id=\"もっとよさそうな方法\"\u003eもっとよさそうな方法\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003ehugo 内蔵の画像表示機能を使う。\u003c/del\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e追記（2025年1月26日）\u003cbr\u003e\n　Hugo 自体にはそんなものない。hugo の shortcodes というのを使って、自分で画像を表示するコードを書くか、テーマごとに用意された画像を表示するための shortcodes を使うことはできる。また、マークダウン形式でも画像を張り付けられるが、細かいスタイルの調整はできなかったと思う。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"さらなる追記-2025年1月30日\"\u003eさらなる追記 (2025年1月30日)\u003c/h3\u003e\n\u003cp\u003e　今回、新たな間違いに気づいたので、ここにもその記録置いときます。。。なんでドキュメント見て気づけなかったんだろうとそんな気持ちです。。。（実は間違っていたと思っていることはあっていた。。。）\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cul\u003e\n\u003cli\u003e追記 (2025年1月30日)\u003cbr\u003e\n　今気づいたが、実は組み込みで、hugoに figure っていうのが入っていることに気づいた。hugo自体に画像を表示する機能がないというのは間違いで、気づけてないだけだった。 \u003cbr\u003e\n\u003ca href=\"https://gohugo.io/shortcodes/figure/\"\u003eFigure | Hugo\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"shortcode-で画像を表示する\"\u003eshortcode で画像を表示する\u003c/h2\u003e\n\u003ch3 id=\"選択肢\"\u003e選択肢\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eテーマ付属の shortcode を使う\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e自分で shortcode を適当に作る\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003ehugo 内臓の figure shortcode を使う\u003cbr\u003e\n（今回は検証とかしてないです。 追記: 2025年1月30日）\u003cbr\u003e\n\u003ca href=\"https://gohugo.io/shortcodes/figure/\"\u003eFigure | Hugo\u003c/a\u003e\u003c/p\u003e","title":"hugoで画像を追加する 📷の補足"},{"content":"ここでは、HPE Proliant DL60 Gen9 なPCのファンの静音化について、適当にメモを残しておこうと思います。\n事の発端 サーバがあるのはいいものの、デフォルト付属のファンはあまりにも個人で運用するにはうるさすぎたので、静音化をしたくなった。ヤフオクで、1個送料込みで300円程度のDELL製PCのブロアファンが売っていたので、それを購入してファンを交換することにした。\n古いファン 新しいファン なんでうるさくなるの？ そもそも、HPE Proliant DL60 Gen9 はラックマウントサーバなので、一般家庭で使うことを想定していないことがあまりにも大きすぎるのだと思う。ちっこいファンが3つくらいついていて、キーンという甲高いけたたましい音とともに起動したりする。しかも今回は、Hdd 交換作業 1 💽の影響で、ドライブが純正パーツじゃないと認識されてしまい、さらにうるさくなったという事情もある。\n必要なもの 使いたいファン 2個 トランジスタかMOSFET 2個 40kΩくらいの抵抗 2個 Amazonで買った銅線 ロックタイ 使った道具 ハンダごて ハンダ ニッパー ハサミ 事前知識 普通のファンとメーカー製PCのファン 普通のファンでは、以下のような4ピンタイプのものになっている。PWM ファン制御がない3ピンタイプもある。メーカー製PCでもだいたい似たようなものか、完全に同じものもある。今回のファン交換の場合はPWM信号に工夫が必要であった。\n12v GND PWM ファン制御 PWM?ファン回転数情報 ネットから引っ張ってきたDELL製ファンと普通のファンの比較画像 https://n-techlabo.com/upgrading-dell-old-pc-to-a-gaming-pc/ ちなみに今回交換する古いファンについていたコネクタはこんな感じになっていた。一部の黒い線はいくつかのピンをショートさせるようになっていて、普通のファンへの交換の敷居を高くしようとしたのか、なんか他の理由があるのかなと思ったり、思わなかったりした。\n赤線　12v 黒線　GND 青線　PWMファン回転数制御 黄線　PWMファン回転数情報？ PWM信号 今回ファンを交換する対象である、HPE製のサーバは、通常の自作PC等で使われているファンとたいして電気的に違うところがあるわけではないが、PWMによるファン制御が普通のコンピュータ異なり、反転している。そのため、サーバからくるPWM信号を、トランジスタやMOSFETをスイッチ代わりに使って信号を反転している。\nダミーコネクタ この写真をよく見てもらえばわかると思うが、黄線のPWMファン回転数情報？とGNDを直結すると、ダミーコネクタが完成する。HPEなサーバでは、少なくとも Gen 9 あたりはこれで一応ファンがあるとサーバを誤魔化せるようだ。このテクニック？は、ファンの回線数情報の線をつないでも、ファンエラーになる場合にも有効であった。\nちなみにHPEなサーバでは、ファンが必要以上に付いておらず、正常な動作ができないと判定されるとBIOS（UEFI）から先に進めず電源が入ってPOSTしても勝手にシャットダウンしてしまう。ファンを純正品以外に交換するなら、必須かも？ 信号反転回路 使う抵抗は大体数kΩから数十数kΩにしておいた。\n完成形 ファンを交換した感想 普通に静かになった。フルパワーで動いていても、全然うるさくない。主観ではあるが、手を当ててみても十分な風量がありそうな印象。ファンとしての機能も思っている以上にしっかりしており、自分の環境では、温度🌡️は負荷をかけても約40から50度前後に保たれていた。\n今後の課題 HDDブラケットを買うことで、純正アラートから逃れたい。（それかILO改造？）\n参考にしたサイト Upgrading DELL Old PC to a Gaming PC! | N Tech Labo\nhttps://n-techlabo.com/upgrading-dell-old-pc-to-a-gaming-pc/ （2024年6月28日） ","permalink":"https://www.nyanmo.info/posts/hardware/fanmod/","summary":"\u003cp\u003eここでは、HPE Proliant DL60 Gen9 なPCのファンの静音化について、適当にメモを残しておこうと思います。\u003c/p\u003e\n\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003cp\u003e　サーバがあるのはいいものの、デフォルト付属のファンはあまりにも個人で運用するにはうるさすぎたので、静音化をしたくなった。ヤフオクで、1個送料込みで300円程度のDELL製PCのブロアファンが売っていたので、それを購入してファンを交換することにした。\u003c/p\u003e\n\u003ch3 id=\"古いファン\"\u003e古いファン\u003c/h3\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/fanMod/oldFan7.png\" alt=\"古いHPEなファン\" width=\"50%\" height=\"50%\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"新しいファン\"\u003e新しいファン\u003c/h3\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/fanMod/newFan1.png\" alt=\"新しいDELLなファン\" width=\"50%\" height=\"50%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"なんでうるさくなるの\"\u003eなんでうるさくなるの？\u003c/h2\u003e\n\u003cp\u003e　そもそも、HPE Proliant DL60 Gen9 はラックマウントサーバなので、一般家庭で使うことを想定していないことがあまりにも大きすぎるのだと思う。ちっこいファンが3つくらいついていて、キーンという甲高いけたたましい音とともに起動したりする。しかも今回は、\u003ca href=\"https://www.nyanmo.info/posts/hardware/hdd/addmorespace/\"\u003eHdd 交換作業 1 💽\u003c/a\u003eの影響で、ドライブが純正パーツじゃないと認識されてしまい、さらにうるさくなったという事情もある。\u003c/p\u003e\n\u003ch2 id=\"必要なもの\"\u003e必要なもの\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e使いたいファン        2個\u003c/li\u003e\n\u003cli\u003eトランジスタかMOSFET  2個\u003c/li\u003e\n\u003cli\u003e40kΩくらいの抵抗      2個\u003c/li\u003e\n\u003cli\u003eAmazonで買った銅線\u003c/li\u003e\n\u003cli\u003eロックタイ\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"使った道具\"\u003e使った道具\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eハンダごて\u003c/li\u003e\n\u003cli\u003eハンダ\u003c/li\u003e\n\u003cli\u003eニッパー\u003c/li\u003e\n\u003cli\u003eハサミ\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"事前知識\"\u003e事前知識\u003c/h2\u003e\n\u003ch3 id=\"普通のファンとメーカー製pcのファン\"\u003e普通のファンとメーカー製PCのファン\u003c/h3\u003e\n\u003cp\u003e　普通のファンでは、以下のような4ピンタイプのものになっている。PWM ファン制御がない3ピンタイプもある。メーカー製PCでもだいたい似たようなものか、完全に同じものもある。今回のファン交換の場合はPWM信号に工夫が必要であった。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e12v\u003c/li\u003e\n\u003cli\u003eGND\u003c/li\u003e\n\u003cli\u003ePWM ファン制御\u003c/li\u003e\n\u003cli\u003ePWM?ファン回転数情報\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; text-align: center;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/fanMod/Wiring-Diagram.png\" alt=\"ピンアウト\" width=\"80%\" height=\"80%\" /\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; text-align: center;\"\u003e\n    ネットから引っ張ってきたDELL製ファンと普通のファンの比較画像\n\u003c/div\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; text-align: center; margin-bottom: 50px;\"\u003e\n    \u003ca href=\"https://n-techlabo.com/upgrading-dell-old-pc-to-a-gaming-pc/\"\u003e\n        https://n-techlabo.com/upgrading-dell-old-pc-to-a-gaming-pc/\n    \u003c/a\u003e\n\u003c/div\u003e\n\u003cp\u003e　ちなみに今回交換する古いファンについていたコネクタはこんな感じになっていた。一部の黒い線はいくつかのピンをショートさせるようになっていて、普通のファンへの交換の敷居を高くしようとしたのか、なんか他の理由があるのかなと思ったり、思わなかったりした。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e赤線　　12v\u003c/li\u003e\n\u003cli\u003e黒線　　GND\u003c/li\u003e\n\u003cli\u003e青線　　PWMファン回転数制御\u003c/li\u003e\n\u003cli\u003e黄線　　PWMファン回転数情報？\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; text-align: center; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/fanMod/HPEFanConnector.png\" alt=\"HPEなファンのコネクタ\" width=\"40%\" height=\"40%\" /\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/fanMod/HPEFanConnector4.png\" alt=\"HPEなファンのコネクタの黒色配線ループ\" width=\"40%\" height=\"40%\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"pwm信号\"\u003ePWM信号\u003c/h3\u003e\n\u003cp\u003e今回ファンを交換する対象である、HPE製のサーバは、通常の自作PC等で使われているファンとたいして電気的に違うところがあるわけではないが、PWMによるファン制御が普通のコンピュータ異なり、反転している。そのため、サーバからくるPWM信号を、トランジスタやMOSFETをスイッチ代わりに使って信号を反転している。\u003c/p\u003e","title":"ファン静音化"},{"content":"　ここでは、Hdd 交換作業 1 💽の続きとして、新しく交換したHDDの容量をフルで使うまでの道のりを記録として残しておきます。\n前のページ Hdd 交換作業 1 💽\n現状 ddコマンドでクローンしただけなので、500GBのHDDで使ってた時と同じパーティション構成のままになっている。\n/dev/sdb1 2048 1025986 1023939 500M EFI システム /dev/sdb2 1026048 881829887 880803840 420G Linux ファイルシステム /dev/sdb3 881829888 976496623 94666736 45.1G Linux スワップ パテーションをリサイズ パテーションのリサイズは、parted を使って以下の様な感じで行った。この記事を書くまでブランクがあったせいであいまいであるのは承知願いたい。\nparted /dev/sdb (parted) print \\\\ この表示は、特に写真とか残してなかったので、今の構成で出力例を適当に作った。 モデル: HP LOGICAL VOLUME (scsi) ディスク /dev/sdb: 10.0TB セクタサイズ (論理/物理): 512B/4096B パーティションテーブル: gpt ディスクフラグ: 番号 開始 終了 サイズ ファイルシステム 名前 フラグ 1 1049kB 525MB 524MB fat32 EFI System Partition boot, esp 2 525MB 9050GB 9049GB ext4 (parted) resizepart リサイズしたいパテーション番号？ パテーションの大きさか終端だった気がする？T (parted) quit ファイルシステムの調整 ここでは、e2fsck、resize2fsコマンドを使ってリサイズしたパーティションにファイルシステムを調整する操作をした。以下にその様子を置いとく。ちなみに私は、resize2fsコマンドをe2fsckコマンドより先に実行しようとしたので、怒られている。resize2fsコマンドは結構時間がかかった。\n動作確認 適当にfdiskコマンドとかでディスク構成を表示したり、gnomeのエクスプローラみたいなやつで、パテーションのリサイズができたのか、確認したリした。\nsudo fdisk -l [sudo] user のパスワード: ディスク /dev/sdb: 9.1 TiB, 10000797794304 バイト, 19532808192 セクタ ディスク型式: LOGICAL VOLUME 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 4096 バイト I/O サイズ (最小 / 推奨): 262144 バイト / 262144 バイト ディスクラベルのタイプ: gpt ディスク識別子: 一応秘匿 デバイス 開始位置 終了位置 セクタ サイズ タイプ /dev/sdb1 2048 1025986 1023939 500M EFI システム /dev/sdb2 1026048 17675781250 17674755203 8.2T Linux ファイルシステム 参考にしたサイトとか ChatGPT https://chatgpt.com/ （2024年6月26日） ","permalink":"https://www.nyanmo.info/posts/hardware/hdd/addmorespace2/","summary":"\u003cp\u003e　ここでは、\u003ca href=\"https://www.nyanmo.info/posts/hardware/hdd/addmorespace/\"\u003eHdd 交換作業 1 💽\u003c/a\u003eの続きとして、新しく交換したHDDの容量をフルで使うまでの道のりを記録として残しておきます。\u003c/p\u003e\n\u003ch2 id=\"前のページ\"\u003e前のページ\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/hardware/hdd/addmorespace/\"\u003eHdd 交換作業 1 💽\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"現状\"\u003e現状\u003c/h2\u003e\n\u003cp\u003e　ddコマンドでクローンしただけなので、500GBのHDDで使ってた時と同じパーティション構成のままになっている。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e/dev/sdb1       2048   1025986   1023939   500M EFI システム\n/dev/sdb2    1026048 881829887 880803840   420G Linux ファイルシステム\n/dev/sdb3  881829888 976496623  94666736  45.1G Linux スワップ\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"パテーションをリサイズ\"\u003eパテーションをリサイズ\u003c/h2\u003e\n\u003cp\u003e　パテーションのリサイズは、parted を使って以下の様な感じで行った。この記事を書くまでブランクがあったせいであいまいであるのは承知願いたい。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003eparted /dev/sdb\n(parted) print \\\\ この表示は、特に写真とか残してなかったので、今の構成で出力例を適当に作った。\nモデル: HP LOGICAL VOLUME (scsi)\nディスク /dev/sdb: 10.0TB\nセクタサイズ (論理/物理): 512B/4096B\nパーティションテーブル: gpt\nディスクフラグ:\n\n番号  開始    終了    サイズ  ファイルシステム  名前                  フラグ\n 1    1049kB  525MB   524MB   fat32             EFI System Partition  boot, esp\n 2    525MB   9050GB  9049GB  ext4\n\n(parted) resizepart リサイズしたいパテーション番号？ パテーションの大きさか終端だった気がする？T\n(parted) quit\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"ファイルシステムの調整\"\u003eファイルシステムの調整\u003c/h2\u003e\n\u003cp\u003e　ここでは、e2fsck、resize2fsコマンドを使ってリサイズしたパーティションにファイルシステムを調整する操作をした。以下にその様子を置いとく。ちなみに私は、resize2fsコマンドをe2fsckコマンドより先に実行しようとしたので、怒られている。resize2fsコマンドは結構時間がかかった。\u003c/p\u003e","title":"Hdd 交換作業 2 💽"},{"content":"　ここでは、最近サーバのHDDを交換しようとして、さんざん手こずった後を記録として、書いていきます。データ復旧だけで、あまりに長い記事になったので、記事を二つくらいに分けてます。\n事の発端 最近ネットワークドライブとして使っているHDDの容量が半分を切り、使い切ってしまいたくないと思い立つ。そこで、ヤフオクで10TBのHDD2個を新たに購入し、RAID1で運用したいと思うようになる。まだいっぱい空き容量があるじゃないか！と思う人もいると思うが、自分的にはHDDのスペースはいっぱい用意しといて、心置きなく作業したかったので、もっと容量のあるHDDへ交換することにした。\n今回得た教訓 smart arrayは優しくない HPE社製のRAIDコントローラーに搭載されているソフトウェアでは、管理コンソールから論理ディスクを消したら、平気でGPTとかのパーティション情報は、少なくともHDDを付けたまま作業すると、消されてしまう。\nバックアップを取ろう 消えてかつ上書きされてしまったら運の尽き。\nやらかしたらなるべく書き込まない 元の構成に戻して、上書きしないようインストールメディアなどから作業を行い、testdiskコマンドとかでパーティション情報を探して復元を試みてみる。\n新旧比較 古いHDD 今までは、普通のWestern Digital製500GB HDDを使っていた。SATA対応。確か2016年製で、2018年くらいに中古で買って連続で5年程度使ってた覚えがある。\n新しく買ったHDD 今回新たに買ったのは、2017年製と古いものではあるが、ヘリウム充填のHGST（現 Western Digital）製の10TB HDDを買った。SAS対応。出品者によれば動作に問題なさそうらしい。\nSmart HBA H240 今使っているRAIDコントローラーは、「Smart HBA H240」とかいうやつで、サーバーを買ったときにセットでついてきたもの。以下は、外したりするのはメンドウだったので、適当に画像はネットから拾ってきた。\n今使っているサーバーでは、備え付けのSASが使えるポートが4つあり、そのうち2台分はデータディスクですでに使っており、さらに2台分のスペースには、今回交換したいSATAに対応したHDDがあるので、そこに新たに買ったSASなHDDを入れてクローンをやろうと考えた。ちなみに、mini sas SFF-8087とかいうソケットから、SATA 4ポート分に変換するケーブルを持っているので、SATAなHDDならサーバーの備え付けのポートを使うことなく作業できると考えた。以下は、適当にネットから引っ張ってきた。 悲劇と出会う 🫠 さっそく、HDDを交換してみようと試みるのだが、RAID1の500GB二枚のHDDをどうやって交換か考えたとき、今までの経験上では、RAIDの論理ディスクを消してもよかったなと思い出す。（🚩）ついつい早まってしまい、バックアップを取らずに作業をはじめてしまう。HDDを外して、外したHDDの中身を何かしら見えるように調整し、新しいディスクにクローンしたらいいだろうと思ってやってみたら、どうもSmart arrayはそうではなかったようで。。。\nHDDを付けたまま論理ディスクを削除 これは完全に失敗で、論理ディスクを消すとSmart arrayでは、GPTなどの情報をいじくりまわしてしまうようだった。なので、同じ構成、設定で再構築しても中身のパーティションはなかったことになるという、ホラーな状態に。arch linuxのインストールメディアから、中身を確認すると、こんなことに。。。\nfdisk -l ディスク /dev/sdb: 465.66 GiB, 500000514048 バイト, 976563504 セクタ ディスク型式: WDC WD5003ABYX-2 単位: セクタ (1 * 512 = 512 バイト) セクタサイズ (論理 / 物理): 512 バイト / 512 バイト I/O サイズ (最小 / 推奨): 512 バイト / 512 バイト ディスクラベルのタイプ: gpt ディスク識別子: 一応秘匿 デバイス 開始位置 終了位置 セクタ サイズ タイプ 一体全体ワイのデータをいずこへ？ と思って焦っていたが、よくよく考えれば、論理ディスクとか消すときって、あんまり時間かからないクイックフォーマットみたいな感じで終わってたから、まだデータはあるのではと勘繰る。最終的にはこの予感は当たるのだが、そこまでが長かった。。。\nもしかして？ 調べていると、HPEのコミュニティサイトに、まったく同じ設定、構成にして、gdiskで開いたら、「gptの構成が壊れている」というメッセージが出てきて、writeしてやれば治るみたいな返信を発見する。\nいろいろ試してみる 早速修復を試みてみるが、何をとち狂ったのか、RAID1なら2台のHDDとも同じ内容だろうと思い、一つだけ繋げてRAID0で設定を行ってしまう。幸いにもセクタサイズとかは、そのままにしてたので、データを破壊するまでには至らなかったが。。。\ngdiskで読み込ませてみても、\u0026ldquo;No problem reported\u0026quot;みたいなのしか出てこず、MBR、GPTともに何もないことになってて、アッこれ終わったわ、って一瞬なったが、諦めきれずに作業を続けた。\ngdisk /dev/sda GPT fdisk (gdisk) version 1.0.10 Partition table scan: MBR: not present BSD: not present APM: not present GPT: not present testdiskコマンド 頑張って、GPTパーティション情報を復元する方法を探していると、testdiskコマンドなるものがあることを発見した。ので試してみたところ、quick searchで見覚えのあるパーティションを見つける。arch linuxのインストールメディアには標準で入っていたので、それをそのまま使った。\nしかしこの構成で復元したところ、全然マウントできないという事態に直面する。「ext4ファイルシステムが壊れています。」みたいなメッセージばっかり出てくる。スーパーブロックがおかしいというエラーも出てきた。 実は、testdiskのquick searchでは、復元するパーティションの位置が数セクタくらいずれていたのだが、気づかずになるべく書き込まないように、データを破壊しそうになりながら、グダグダ作業した。 mke2fs -n /dev/sdX1 Superblock backups stored on blocks: 32768, 98304, 163840, 229376, 294912, 819200, 884736, ... e2fsck -b 32768 /dev/sdX1 e2fsck -b 98304 /dev/sdX1 e2fsck -b 163840 /dev/sdX1 fsck.ext4 -b 32768 /dev/sdX1 上記に示した様なコマンドをひたすら試して、バックアップされてるらしいいろんなスーパーブロックらしきものを試すが、まったくうまくいかなかった。\n実はずれている！ そうこうしているうちに、とあることに気づく。もしかして、復元したパーティションは、間違っているのではないかと。通常のOSが入ったパーティションの構成は、\n/dev/sdb1 2048 1025986 1023939 500M EFI システム /dev/sdb2 1026048 881829887 880803840 420G Linux ファイルシステム /dev/sdb3 881829888 976496623 94666736 45.1G Linux スワップ のように、ブート用のFAT32でフォーマットされたEFI領域に、ext4やNTFSでフォーマットされた、OSやその他もろもろデータの入っている領域、後は今回でいえばスワップ領域となっているが、winRE?などの回復環境のためのパーティション領域などが、一般的にはあるはずであると。しかしさっき表示されていたパーティションは明らかに様子がおかしく、全部復元するように設定できず、MS dataというパーティションが本来、EFIパーティションとなっているはずの部分で、Linux filesysと認識されれているパーティションは、ファイルの中身が閲覧できないという状態だった。とにかく、問題に気づいたので、さっそくtestdiskコマンドで、deep searchを行ってみる。\n上記の画像を見てもわかるようにEFIパーティションも、それとつじつまのあうセクタの開始位置、終了位置を持つext4やswapパーティションが見つかっている。しかも、testdiskで中身を見れるパーティションが見つかるので、「よしこれキタ🥺」と思ってそのパーティション構成で復元してみる。すると、何もスーパーブロックなるものとかいじらなくても、BIOSからgrubのEFIアプリケーションのファイルを指定して起動してやるだけで、何事もなかったかのように起動した。 バックアップを取る 💾 今思えば、なぜ約20TBの容量のあるデータディスクに、たかだか500GB程度のデータのバックアップを怠ったのかという話ではあるが、とにかく動くようになったので、必要なコンフィグとか授業資料などのデータをバックアップした。\n次のページ Hdd 交換作業 2 💽\n参考にしたサイト 「TestDisk」の使い方 - PCと解\nhttps://pctrouble.net/software/testdisk.html （2024年6月12日） partitioning - Fixing corrupt backup GPT table? - Ask Ubuntu\nhttps://askubuntu.com/questions/386752/fixing-corrupt-backup-gpt-table （2024年6月12日） Accidentally deleted the RAID configuration - Hewlett Packard Enterprise Community\nhttps://community.hpe.com/t5/proliant-servers-ml-dl-sl/accidentally-deleted-the-raid-configuration/td-p/7161927（2024年6月12日） ","permalink":"https://www.nyanmo.info/posts/hardware/hdd/addmorespace/","summary":"\u003cp\u003e　ここでは、最近サーバのHDDを交換しようとして、さんざん手こずった後を記録として、書いていきます。データ復旧だけで、あまりに長い記事になったので、記事を二つくらいに分けてます。\u003c/p\u003e\n\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003cp\u003e　最近ネットワークドライブとして使っているHDDの容量が半分を切り、使い切ってしまいたくないと思い立つ。そこで、ヤフオクで10TBのHDD2個を新たに購入し、RAID1で運用したいと思うようになる。まだいっぱい空き容量があるじゃないか！と思う人もいると思うが、自分的にはHDDのスペースはいっぱい用意しといて、心置きなく作業したかったので、もっと容量のあるHDDへ交換することにした。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:start; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/prevHDDcapacity.png\" alt=\"状態\" width=\"60%\" height=\"60%\" /\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display:flex; justify-content:end; margin:10px; overflow-x: scroll;transform: translate(0,-30px)\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/pervHDD.png\" alt=\"状態\" width=\"60%\" height=\"60%\" /\u003e\n\u003c/div\u003e\n\u003cdiv class=\"info titleIconSet\"\u003e\n    \u003cimg class=\"icon\" src=\"/icons/win7Icons/Notepad.png\"\u003e\n    \u003ch2 class=\"iconTitle\"\u003e今回得た教訓\u003c/h2\u003e\n    \n\u003c/div\u003e\n\n\n\u003ch3 id=\"smart-arrayは優しくない\"\u003esmart arrayは優しくない\u003c/h3\u003e\n\u003cp\u003eHPE社製のRAIDコントローラーに搭載されているソフトウェアでは、管理コンソールから論理ディスクを消したら、平気でGPTとかのパーティション情報は、少なくともHDDを付けたまま作業すると、消されてしまう。\u003c/p\u003e\n\u003ch3 id=\"バックアップを取ろう\"\u003eバックアップを取ろう\u003c/h3\u003e\n\u003cp\u003e消えてかつ上書きされてしまったら運の尽き。\u003c/p\u003e\n\u003ch3 id=\"やらかしたらなるべく書き込まない\"\u003eやらかしたらなるべく書き込まない\u003c/h3\u003e\n\u003cp\u003e元の構成に戻して、上書きしないようインストールメディアなどから作業を行い、testdiskコマンドとかでパーティション情報を探して復元を試みてみる。\u003c/p\u003e\n\u003ch2 id=\"新旧比較\"\u003e新旧比較\u003c/h2\u003e\n\u003ch3 id=\"古いhdd\"\u003e古いHDD\u003c/h3\u003e\n\u003cp\u003e　今までは、普通のWestern Digital製500GB HDDを使っていた。SATA対応。確か2016年製で、2018年くらいに中古で買って連続で5年程度使ってた覚えがある。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/pervHDD.png\" alt=\"状態\" width=\"60%\" height=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"新しく買ったhdd\"\u003e新しく買ったHDD\u003c/h3\u003e\n\u003cp\u003e　今回新たに買ったのは、2017年製と古いものではあるが、ヘリウム充填のHGST（現 Western Digital）製の10TB HDDを買った。SAS対応。出品者によれば動作に問題なさそうらしい。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:end; margin:10px; overflow-x: scroll\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/10tbHDD.png\" alt=\"状態\" width=\"50%\" height=\"50%\" /\u003e\n\u003c/div\u003e\n\u003cdiv style=\"display:flex; justify-content:start; margin:10px; overflow-x: scroll;transform: translate(0,-100px)\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/newHDD.png\" alt=\"状態\" width=\"60%\" height=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"smart-hba-h240\"\u003eSmart HBA H240\u003c/h2\u003e\n\u003cp\u003e　今使っているRAIDコントローラーは、「Smart HBA H240」とかいうやつで、サーバーを買ったときにセットでついてきたもの。以下は、外したりするのはメンドウだったので、適当に画像はネットから拾ってきた。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/RAIDcont.png\" alt=\"RAIDコントローラー\" width=\"70%\" height=\"70%\" /\u003e\n\u003c/div\u003e\n　今使っているサーバーでは、備え付けのSASが使えるポートが4つあり、そのうち2台分はデータディスクですでに使っており、さらに2台分のスペースには、今回交換したいSATAに対応したHDDがあるので、そこに新たに買ったSASなHDDを入れてクローンをやろうと考えた。ちなみに、mini sas SFF-8087とかいうソケットから、SATA 4ポート分に変換するケーブルを持っているので、SATAなHDDならサーバーの備え付けのポートを使うことなく作業できると考えた。以下は、適当にネットから引っ張ってきた。\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/hdd/addMoreSpace/miniSasToSata.png\" alt=\"miniSAStoSata\" width=\"70%\" height=\"70%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"悲劇と出会う-\"\u003e悲劇と出会う 🫠\u003c/h2\u003e\n\u003cp\u003e　さっそく、HDDを交換してみようと試みるのだが、RAID1の500GB二枚のHDDをどうやって交換か考えたとき、今までの経験上では、RAIDの論理ディスクを消してもよかったなと思い出す。（🚩）ついつい早まってしまい、バックアップを取らずに作業をはじめてしまう。HDDを外して、外したHDDの中身を何かしら見えるように調整し、新しいディスクにクローンしたらいいだろうと思ってやってみたら、どうもSmart arrayはそうではなかったようで。。。\u003c/p\u003e","title":"Hdd 交換作業 1 💽"},{"content":"つまずいたところ hugo でhtmlを拡張した形で書かれる、テンプレート？を作ろうとしたら、メンドウなことになった。\nlayouts の html ページの作成 hugo new layouts/baseof.html はできないことを知らなかったという。ちなみにこれを実行してしまうと一見うまくいったように見えるが、laytouts フォルダではなく、contentフォルダ配下にディレクトリやらファイルやらが生成されてしまうのでめんどくさくなる。\nちなみにミスった時はこうなる\n# hugo new layouts/baseof.html Content \u0026#34;何かしらのパス/content/layouts/baseof.html\u0026#34; created . ├── archetypes ├── assets ├── content │ ├── _index.md │ └── layouts │ └── baseof.html ├── data ├── hugo.toml ├── i18n ├── layouts ├── public ├── res.txt ├── static └── themes 一部関係ない部分省略してここには書いてるので、layouts、contentフォルダだけ見てもらえればと思います。\n知らなかったこと hugoでのhtmlの書き方 hugo ではそのままhtmlを今までどおり書くことができるが、他のファイルやforループを行うこともできる。phpみたいなイメージに近いかも。Chat GPTに質問してみたらこんな感じになるらしい。\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1.0\u0026#34;\u0026gt; \u0026lt;title\u0026gt;{{ .Title }}\u0026lt;/title\u0026gt; \u0026lt;!-- Additional meta information or stylesheets can be added here --\u0026gt; {{- partial \u0026#34;head_custom.html\u0026#34; . -}} \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;header\u0026gt; \u0026lt;!-- Header content goes here --\u0026gt; {{- partial \u0026#34;header_custom.html\u0026#34; . -}} \u0026lt;/header\u0026gt; \u0026lt;main\u0026gt; \u0026lt;!-- Content from individual pages will be inserted here --\u0026gt; {{- block \u0026#34;main\u0026#34; . }}{{ .Content }}{{ end -}} \u0026lt;/main\u0026gt; \u0026lt;footer\u0026gt; \u0026lt;!-- Footer content goes here --\u0026gt; {{- partial \u0026#34;footer_custom.html\u0026#34; . -}} \u0026lt;/footer\u0026gt; \u0026lt;!-- Additional scripts or footer scripts can be added here --\u0026gt; {{- partial \u0026#34;footer_scripts.html\u0026#34; . -}} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; ちなみに公式ドキュメントはここら辺っぽい\nhttps://gohugo.io/templates/introduction/ https://gohugo.io/templates/partials/ ","permalink":"https://www.nyanmo.info/posts/hugo/templatecreation/","summary":"\u003ch2 id=\"つまずいたところ\"\u003eつまずいたところ\u003c/h2\u003e\n\u003cp\u003e　hugo でhtmlを拡張した形で書かれる、テンプレート？を作ろうとしたら、メンドウなことになった。\u003c/p\u003e\n\u003ch3 id=\"layouts-の-html-ページの作成\"\u003elayouts の html ページの作成\u003c/h3\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003ehugo new layouts/baseof.html\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eはできないことを知らなかったという。ちなみにこれを実行してしまうと一見うまくいったように見えるが、laytouts フォルダではなく、contentフォルダ配下にディレクトリやらファイルやらが生成されてしまうのでめんどくさくなる。\u003c/p\u003e\n\u003cp\u003eちなみにミスった時はこうなる\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e# hugo new layouts/baseof.html\nContent \u0026#34;何かしらのパス/content/layouts/baseof.html\u0026#34; created\n\n.\n├── archetypes\n├── assets\n├── content\n│   ├── _index.md\n│   └── layouts\n│       └── baseof.html\n├── data\n├── hugo.toml\n├── i18n\n├── layouts\n├── public\n├── res.txt\n├── static\n└── themes\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e一部関係ない部分省略してここには書いてるので、layouts、contentフォルダだけ見てもらえればと思います。\u003c/p\u003e\n\u003ch2 id=\"知らなかったこと\"\u003e知らなかったこと\u003c/h2\u003e\n\u003ch3 id=\"hugoでのhtmlの書き方\"\u003ehugoでのhtmlの書き方\u003c/h3\u003e\n\u003cp\u003ehugo ではそのままhtmlを今までどおり書くことができるが、他のファイルやforループを行うこともできる。phpみたいなイメージに近いかも。Chat GPTに質問してみたらこんな感じになるらしい。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;!DOCTYPE html\u0026gt;\n\u0026lt;html lang=\u0026#34;en\u0026#34;\u0026gt;\n\u0026lt;head\u0026gt;\n    \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt;\n    \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1.0\u0026#34;\u0026gt;\n    \u0026lt;title\u0026gt;{{ .Title }}\u0026lt;/title\u0026gt;\n    \u0026lt;!-- Additional meta information or stylesheets can be added here --\u0026gt;\n    {{- partial \u0026#34;head_custom.html\u0026#34; . -}}\n\u0026lt;/head\u0026gt;\n\u0026lt;body\u0026gt;\n    \u0026lt;header\u0026gt;\n        \u0026lt;!-- Header content goes here --\u0026gt;\n        {{- partial \u0026#34;header_custom.html\u0026#34; . -}}\n    \u0026lt;/header\u0026gt;\n\n    \u0026lt;main\u0026gt;\n        \u0026lt;!-- Content from individual pages will be inserted here --\u0026gt;\n        {{- block \u0026#34;main\u0026#34; . }}{{ .Content }}{{ end -}}\n    \u0026lt;/main\u0026gt;\n\n    \u0026lt;footer\u0026gt;\n        \u0026lt;!-- Footer content goes here --\u0026gt;\n        {{- partial \u0026#34;footer_custom.html\u0026#34; . -}}\n    \u0026lt;/footer\u0026gt;\n\n    \u0026lt;!-- Additional scripts or footer scripts can be added here --\u0026gt;\n    {{- partial \u0026#34;footer_scripts.html\u0026#34; . -}}\n\u0026lt;/body\u0026gt;\n\u0026lt;/html\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003eちなみに公式ドキュメントはここら辺っぽい\u003c/p\u003e","title":"テンプレ作成"},{"content":"　ここでは、ある意味有名なマグネット広告がなんかポストに入っていたので、適当に広告をはがして遊んだ記録を残しています。\n事の発端 5月12日あたりに、ポストにマグネット広告が入っていることを見つける。\n私の感覚としては、「広告＝怖い、悪意のある悪いもの、特定企業への印象の押し売り」等という印象、偏見？があり、とても不快な思いをした。\nそこで、あまりいいくせではないが、ついついその事について google 検索をしてみると、どうも水につければ広告は簡単にはがれ、マグネットの部分は再利用できるらしいということに気づく。\n必要なもの マグネット広告本体 プリンタ プリンタ対応のシール用紙 適当に貼り付けたい画像 やってみたこと まあ、届いてしまったものは仕方ないので、実際に水につけて広告を剥がしてみた。\n広告を水につける まずは水につけることで、広告部分の紙をふやかし、はがれやすくする。\n広告を手で剥がす 一定時間水につけていると、広告が剥がれて来るので、手で剥がす。\n何回かテストプリントを行う メンドクサかったので、細かいことは割愛\nシール紙 に印刷 メンドクサかったので、細かいことは割愛\n印刷物を張り付ける メンドクサかったので、細かいことは割愛 完成 参考にしたサイト 広告マグネットをリメイクする方法！子どももわたしもうれしい、日常に役立つ手作りマグネット7選 - ノマド的節約術\nhttps://nomad-saving.com/91196/ （2024年5月16日）\n水道屋のマグネットシートさらに考え再利用 | 猫とほのぼの手作り暮らし\nhttps://ameblo.jp/miikomamamanma/entry-12695727977.html （2024年5月16日）\n子どもも喜ぶ☆水道業者のマグネットの便利でカワイイ再利用方法 | 京都で理系的こそだて\nhttps://kyoto-baby-love.com/how-to-remake-magnet-ads/ （2024年5月16日）\nマグネットチラシの水道屋本舗に業務停止命令　消費者庁 [広島県]：朝日新聞デジタル\nhttps://www.asahi.com/articles/ASP806DG2P80UTIL033.html （2024年5月16日）\n今回利用した画像の配布場所 nicotalk＆キャラ素材配布所\nhttp://www.nicotalk.com/charasozai_kt.html （2024年5月16日） ","permalink":"https://www.nyanmo.info/posts/other/ad/magnet/","summary":"\u003cp\u003e　ここでは、ある意味有名なマグネット広告がなんかポストに入っていたので、適当に広告をはがして遊んだ記録を残しています。\u003c/p\u003e\n\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003cp\u003e　5月12日あたりに、ポストにマグネット広告が入っていることを見つける。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/ad/magnet/ad.png\" alt=\"届いたマグネット広告\" width=\"60%\" /\u003e\n\u003c/div\u003e\n\u003cp\u003e　私の感覚としては、「広告＝怖い、悪意のある悪いもの、特定企業への印象の押し売り」等という印象、偏見？があり、とても不快な思いをした。\u003c/p\u003e\n\u003cp\u003e　そこで、あまりいいくせではないが、ついついその事について google 検索をしてみると、どうも水につければ広告は簡単にはがれ、マグネットの部分は再利用できるらしいということに気づく。\u003c/p\u003e\n\u003ch2 id=\"必要なもの\"\u003e必要なもの\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eマグネット広告本体\u003c/li\u003e\n\u003cli\u003eプリンタ\u003c/li\u003e\n\u003cli\u003eプリンタ対応のシール用紙\u003c/li\u003e\n\u003cli\u003e適当に貼り付けたい画像\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"やってみたこと\"\u003eやってみたこと\u003c/h2\u003e\n\u003cp\u003e　まあ、届いてしまったものは仕方ないので、実際に水につけて広告を剥がしてみた。\u003c/p\u003e\n\u003ch3 id=\"広告を水につける\"\u003e広告を水につける\u003c/h3\u003e\n\u003cp\u003e　まずは水につけることで、広告部分の紙をふやかし、はがれやすくする。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/ad/magnet/soakProcess.png\" alt=\"広告を剥がす\" width=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"広告を手で剥がす\"\u003e広告を手で剥がす\u003c/h3\u003e\n\u003cp\u003e　一定時間水につけていると、広告が剥がれて来るので、手で剥がす。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/ad/magnet/removeAd2.png\" alt=\"広告を手で剥がす\" width=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"何回かテストプリントを行う\"\u003e何回かテストプリントを行う\u003c/h3\u003e\n\u003cp\u003eメンドクサかったので、細かいことは割愛\u003c/p\u003e\n\u003ch3 id=\"シール紙-に印刷\"\u003eシール紙 に印刷\u003c/h3\u003e\n\u003cp\u003eメンドクサかったので、細かいことは割愛\u003c/p\u003e\n\u003ch3 id=\"印刷物を張り付ける\"\u003e印刷物を張り付ける\u003c/h3\u003e\n\u003cp\u003eメンドクサかったので、細かいことは割愛\n　\u003c/p\u003e\n\u003ch3 id=\"完成\"\u003e完成\u003c/h3\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/ad/magnet/finish.png\" alt=\"完成形\" width=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e広告マグネットをリメイクする方法！子どももわたしもうれしい、日常に役立つ手作りマグネット7選 - ノマド的節約術\u003cbr\u003e\n\u003ca href=\"https://nomad-saving.com/91196/\"\u003ehttps://nomad-saving.com/91196/\u003c/a\u003e （2024年5月16日）\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e水道屋のマグネットシートさらに考え再利用 | 猫とほのぼの手作り暮らし\u003cbr\u003e\n\u003ca href=\"https://ameblo.jp/miikomamamanma/entry-12695727977.html\"\u003ehttps://ameblo.jp/miikomamamanma/entry-12695727977.html\u003c/a\u003e （2024年5月16日）\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e子どもも喜ぶ☆水道業者のマグネットの便利でカワイイ再利用方法 | 京都で理系的こそだて\u003cbr\u003e\n\u003ca href=\"https://kyoto-baby-love.com/how-to-remake-magnet-ads/\"\u003ehttps://kyoto-baby-love.com/how-to-remake-magnet-ads/\u003c/a\u003e （2024年5月16日）\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eマグネットチラシの水道屋本舗に業務停止命令　消費者庁 [広島県]：朝日新聞デジタル\u003cbr\u003e\n\u003ca href=\"https://www.asahi.com/articles/ASP806DG2P80UTIL033.html\"\u003ehttps://www.asahi.com/articles/ASP806DG2P80UTIL033.html\u003c/a\u003e （2024年5月16日）\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"今回利用した画像の配布場所\"\u003e今回利用した画像の配布場所\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003enicotalk＆キャラ素材配布所\u003cbr\u003e\n\u003ca href=\"http://www.nicotalk.com/charasozai_kt.html\"\u003ehttp://www.nicotalk.com/charasozai_kt.html\u003c/a\u003e （2024年5月16日）\u003c/li\u003e\n\u003c/ul\u003e","title":"マグネット広告 🧲"},{"content":"　hugoとマークダウンで、画像を追加するのにてこずったので、適当に備忘録として残してみる。\n注意 間違いの可能性 （2025年1月26日追記） この記事は（というか今もそうかもだけど）作成当時とりあえず動くということを基準に Hugo をよくわかってなくて手探りで使ってたことやあんまりよくない方法を書いているので、かなり間違ったことを書いている可能性があります。\nということで、別の記事に現状のやっていることをまとめなおすことにしました。\nhugoで画像を追加する 📷の補足\nてこずったところ マークダウン標準で画像は表示できるが、大きさを調整したり、スタイルを設定できない。\n![altText](imagePathFromStaticFolder) 非推奨 自分が解決とした方法 マークダウンにHTMLを書き、hugoのconfigに以下の設定を追加する。\n\u0026lt;div style=\u0026#34;display:flex; justify-content:center; margin:10px; \u0026#34;\u0026gt; \u0026lt;img style=\u0026#34;margin:10px;\u0026#34; src=\u0026#34;/imagePathFromStaticFolder\u0026#34; alt=\u0026#34;追跡可能\u0026#34; width=\u0026#34;200\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; markup: goldmark: renderer: unsafe: true 動作の様子 もっとよさそうな方法 hugo 内蔵の画像表示機能を使う。\n追記（2025年1月26日）\nHugo 自体にはそんなものない。 hugo の shortcode というのを使って、自分で画像を表示するコードを書くか、テーマごとに用意された画像を表示するための shortcode を使うことはできる。また、マークダウン形式でも画像を張り付けられるが、細かいスタイルの調整はできなかったと思う。\nhugoで画像を追加する 📷の補足\n追記 (2025年1月30日)\n今気づいたが、実は組み込みで、hugoに figure っていうのが入っていることに気づいた。「hugo自体に画像を表示する機能がない」というのは間違いで、気づけてないだけだった。 Figure | Hugo\n分かった事 hugoには複数のマークダウンエンジンを使うことができ、自分が調べた当時では、デフォルトで goldmark というレンダリングエンジンが使われている。\nまた少なくとも、hugoで使われている goldmark の設定では、HTML要素を描画することは危険ということで、デフォルトでマークダウン中にHTMLが書いてあっても描画しないようになっていた。\nよって、マークダウン中のHTMLをhugoとマークダウンの組み合わせでは、マークダウン中のHTMLを表示したいなら、HTML要素を描画することを、hugo.toml等の設定ファイルで明示的に指定する必要がある。\n事の発端 マークダウン形式で画像を追加すると大きすぎてしまう。\n![altText](imagePathFromStaticFolder) html形式で書いてみると、全然見えない。\n\u0026lt;div style=\u0026#34;display:flex; justify-content:center; margin:10px; \u0026#34;\u0026gt; \u0026lt;img style=\u0026#34;margin:10px;\u0026#34; src=\u0026#34;/imagePathFromStaticFolder\u0026#34; alt=\u0026#34;追跡可能\u0026#34; width=\u0026#34;200\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; 調べたこと マークダウンで何とかする方法 マークダウンでは以下の様にサイズが調整できるらしいが、うまくいかなかった。\n![altText]{width:200}(imagePathFromStaticFolder) 非推奨 マークダウンにHTMLを直接記入 hugoのセーフティーを外し html を直接マークダウンに書けるらしいと分かった。\n\u0026lt;div style=\u0026#34;display:flex; justify-content:center; margin:10px; \u0026#34;\u0026gt; \u0026lt;img style=\u0026#34;margin:10px;\u0026#34; src=\u0026#34;/imagePathFromStaticFolder\u0026#34; alt=\u0026#34;追跡可能\u0026#34; width=\u0026#34;200\u0026#34; /\u0026gt; \u0026lt;/div\u0026gt; markup: goldmark: renderer: unsafe: true マークダウンレンダーエンジン マークダウンを描画するのにも、複数のエンジンがあることが分かった。 設定次第で、うまくマークダウンを表示できなかったりするらしい。\n参考にしたサイト Hugoで記事内に画像を貼り付ける方法 #Hugo - Qiita\nhttps://qiita.com/atuyosi/items/4100bd502e373c088c74 （2024年5月21日） With Hugo, can we use HTML code in a md file? - Stack Overflow\nhttps://stackoverflow.com/questions/61292854/with-hugo-can-we-use-html-code-in-a-md-file （2024年5月21日） Figure | Hugo\nhttps://gohugo.io/shortcodes/figure/ （2025年1月30日） ","permalink":"https://www.nyanmo.info/posts/hugo/addimage/","summary":"\u003cp\u003e　hugoとマークダウンで、画像を追加するのにてこずったので、適当に備忘録として残してみる。\u003c/p\u003e\n\u003cdiv class=\"warring titleIconSet\"\u003e\n    \u003cimg class=\"icon\" src=\"/icons/win7Icons/error.ico\"\u003e\n    \u003ch2 class=\"iconTitle\"\u003e注意\u003c/h2\u003e\n    \n\n\u003c/div\u003e\n\u003ch3 id=\"間違いの可能性-2025年1月26日追記\"\u003e間違いの可能性 （2025年1月26日追記）\u003c/h3\u003e\n\u003cp\u003e　この記事は（というか今もそうかもだけど）作成当時とりあえず動くということを基準に Hugo をよくわかってなくて手探りで使ってたことやあんまりよくない方法を書いているので、かなり間違ったことを書いている可能性があります。\u003c/p\u003e\n\u003cp\u003e　ということで、別の記事に現状のやっていることをまとめなおすことにしました。\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.nyanmo.info/posts/hugo/addimage2/\"\u003ehugoで画像を追加する 📷の補足\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"てこずったところ\"\u003eてこずったところ\u003c/h2\u003e\n\u003cp\u003e　マークダウン標準で画像は表示できるが、大きさを調整したり、スタイルを設定できない。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e![altText](imagePathFromStaticFolder)\n\u003c/code\u003e\u003c/pre\u003e\u003cdiv class=\"warring titleIconSet\"\u003e\n    \u003cimg class=\"icon\" src=\"/icons/win7Icons/warring.ico\"\u003e\n    \u003ch2 class=\"iconTitle\"\u003e非推奨\u003c/h2\u003e\n\u003c/div\u003e\n\n\n\u003ch2 id=\"自分が解決とした方法\"\u003e自分が解決とした方法\u003c/h2\u003e\n\u003cp\u003e　マークダウンにHTMLを書き、hugoのconfigに以下の設定を追加する。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e\u0026lt;div style=\u0026#34;display:flex; justify-content:center; margin:10px; \u0026#34;\u0026gt;\n    \u0026lt;img style=\u0026#34;margin:10px;\u0026#34; src=\u0026#34;/imagePathFromStaticFolder\u0026#34; alt=\u0026#34;追跡可能\u0026#34; width=\u0026#34;200\u0026#34; /\u0026gt;\n\u0026lt;/div\u0026gt;\n\u003c/code\u003e\u003c/pre\u003e\u003cpre tabindex=\"0\"\u003e\u003ccode\u003emarkup:\n  goldmark:\n    renderer: \n      unsafe: true\n\u003c/code\u003e\u003c/pre\u003e\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/ad/magnet/finish.png\" alt=\"完成形\" width=\"60%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"もっとよさそうな方法\"\u003eもっとよさそうな方法\u003c/h2\u003e\n\u003cp\u003e　\u003cdel\u003ehugo 内蔵の画像表示機能を使う。\u003c/del\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e追記（2025年1月26日）\u003cbr\u003e\n　\u003cdel\u003eHugo 自体にはそんなものない。\u003c/del\u003e hugo の shortcode というのを使って、自分で画像を表示するコードを書くか、テーマごとに用意された画像を表示するための shortcode を使うことはできる。また、マークダウン形式でも画像を張り付けられるが、細かいスタイルの調整はできなかったと思う。\u003cbr\u003e\n\u003ca href=\"https://www.nyanmo.info/posts/hugo/addimage2/\"\u003ehugoで画像を追加する 📷の補足\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e追記 (2025年1月30日)\u003cbr\u003e\n　今気づいたが、実は組み込みで、hugoに figure っていうのが入っていることに気づいた。「hugo自体に画像を表示する機能がない」というのは間違いで、気づけてないだけだった。 \u003cbr\u003e\n\u003ca href=\"https://gohugo.io/shortcodes/figure/\"\u003eFigure | Hugo\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"分かった事\"\u003e分かった事\u003c/h2\u003e\n\u003cp\u003e　hugoには複数のマークダウンエンジンを使うことができ、自分が調べた当時では、デフォルトで goldmark というレンダリングエンジンが使われている。\u003c/p\u003e\n\u003cp\u003e　また少なくとも、hugoで使われている goldmark の設定では、HTML要素を描画することは危険ということで、デフォルトでマークダウン中にHTMLが書いてあっても描画しないようになっていた。\u003c/p\u003e\n\u003cp\u003e　よって、マークダウン中のHTMLをhugoとマークダウンの組み合わせでは、マークダウン中のHTMLを表示したいなら、HTML要素を描画することを、hugo.toml等の設定ファイルで明示的に指定する必要がある。\u003c/p\u003e\n\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003cp\u003e　マークダウン形式で画像を追加すると大きすぎてしまう。\u003c/p\u003e\n\u003cpre tabindex=\"0\"\u003e\u003ccode\u003e![altText](imagePathFromStaticFolder)\n\u003c/code\u003e\u003c/pre\u003e\u003cp\u003e　html形式で書いてみると、全然見えない。\u003c/p\u003e","title":"hugoで画像を追加する 📷"},{"content":"　この記事では、ヤフオクで落札したものが、おてがる配送 ゆうパケット（匿名配送）で届かないということがあったので、適当にその経過を残そうと思って書いてます。\n重要だと思ったこと 何故か追跡できないとか、異変があったら出品者に取引メッセージで相談し、あんまり長期間放置しないこと。今回は最初の発送連絡があってから4日ほど待ったが、本当はおかしいと思ったら、2日位待てば十分だと思われる。\n助かったポイント 今回のトラブルでは、出品者がまともに取引メッセージに応じてくれる人だった。\n事の発端 五月のはじめ 使っているノートPCのSSDの容量に不足を感じたので、2TBのSSDが欲しいと思い、ヤフオクで買い物をする。\n落札から発送までの経緯 5月6日 落札、落札者情報の送信、支払いを一通り済ませる。\n発送後の様子 5月7日 発送の連絡があり、一瞬だけ引受表示になった気がする。（しかし！スクリーンショットを取ってなかったので、気のせいなのか不明）\n5月8日 その後、データ取得中になり、郵便局側でも追跡できなくなる。たぶんなんかミスかなんかがあったんだろうと思い放置する。\n5月9日 三日位たっても音沙汰なしで、データ取得中の表示かつ、郵便局でも追跡できなくなり不安になった。\n確認のために、直接近くの郵便局に問い合わせると、普通郵便と同じくらい気長にあと二日くらい待ってほしいと言われる。\n5月12日 ついにしびれを切らして、郵便局へ問い合わせると、出品者に問い合わせるように言われる。\n出品者に問い合わせて見ると、実は返送されていたとのことだった。返送理由は住所が間違っているということだったらしい。\n一度取引情報が確定してしまうと、変更できないということもあり、取引メッセージ欄から直接住所等を送信する。\n5月13日 レターパックプラスで再送され、追跡ができるようになる。\n5月15日 ついに配達される。\n参考にしたサイト 荷物の追跡サービスを利用したところ、「お問い合わせ番号が見つかりません。」と表示されました。どこに問い合わせればいいですか？ - 日本郵便\nhttps://www.post.japanpost.jp/question/124.html （2024年5月16日） ヤフオクで荷物の配送状況がデータ取得失敗となっているのですが荷物は\u0026hellip; - Yahoo!知恵袋\nhttps://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13225273303 （2024年5月16日） オークションで「配送状況不明」となった荷物の行方 | 趣味に忠実に生きています\nhttps://ameblo.jp/cyacya-07/entry-12797779515.html （2024年5月16日） ","permalink":"https://www.nyanmo.info/posts/other/yahoo/auction/wontarrive/","summary":"\u003cp\u003e　この記事では、ヤフオクで落札したものが、おてがる配送 ゆうパケット（匿名配送）で届かないということがあったので、適当にその経過を残そうと思って書いてます。\u003c/p\u003e\n\u003ch2 id=\"重要だと思ったこと\"\u003e重要だと思ったこと\u003c/h2\u003e\n\u003cp\u003e　何故か追跡できないとか、異変があったら出品者に取引メッセージで相談し、あんまり長期間放置しないこと。今回は最初の発送連絡があってから4日ほど待ったが、本当はおかしいと思ったら、2日位待てば十分だと思われる。\u003c/p\u003e\n\u003ch2 id=\"助かったポイント\"\u003e助かったポイント\u003c/h2\u003e\n\u003cp\u003e　今回のトラブルでは、出品者がまともに取引メッセージに応じてくれる人だった。\u003c/p\u003e\n\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003ch3 id=\"五月のはじめ\"\u003e五月のはじめ\u003c/h3\u003e\n\u003cp\u003e　使っているノートPCのSSDの容量に不足を感じたので、2TBのSSDが欲しいと思い、ヤフオクで買い物をする。\u003c/p\u003e\n\u003ch2 id=\"落札から発送までの経緯\"\u003e落札から発送までの経緯\u003c/h2\u003e\n\u003ch3 id=\"5月6日\"\u003e5月6日\u003c/h3\u003e\n\u003cp\u003e　落札、落札者情報の送信、支払いを一通り済ませる。\u003c/p\u003e\n\u003ch2 id=\"発送後の様子\"\u003e発送後の様子\u003c/h2\u003e\n\u003ch3 id=\"5月7日\"\u003e5月7日\u003c/h3\u003e\n\u003cp\u003e　発送の連絡があり、一瞬だけ引受表示になった気がする。（しかし！スクリーンショットを取ってなかったので、気のせいなのか不明）\u003c/p\u003e\n\u003ch3 id=\"5月8日\"\u003e5月8日\u003c/h3\u003e\n\u003cp\u003e　その後、データ取得中になり、郵便局側でも追跡できなくなる。たぶんなんかミスかなんかがあったんだろうと思い放置する。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/auction/wontArrive/gettingData.jpg\" alt=\"永遠のデータ取得中\" width=\"200\" /\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/auction/wontArrive/notFound.jpg\" alt=\"追跡不能\" width=\"200px\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"5月9日\"\u003e5月9日\u003c/h3\u003e\n\u003cp\u003e　三日位たっても音沙汰なしで、データ取得中の表示かつ、郵便局でも追跡できなくなり不安になった。\u003c/p\u003e\n\u003cp\u003e　確認のために、直接近くの郵便局に問い合わせると、普通郵便と同じくらい気長にあと二日くらい待ってほしいと言われる。\u003c/p\u003e\n\u003ch3 id=\"5月12日\"\u003e5月12日\u003c/h3\u003e\n\u003cp\u003e　ついにしびれを切らして、郵便局へ問い合わせると、出品者に問い合わせるように言われる。\u003c/p\u003e\n\u003cp\u003e　出品者に問い合わせて見ると、実は返送されていたとのことだった。返送理由は住所が間違っているということだったらしい。\u003c/p\u003e\n\u003cp\u003e　一度取引情報が確定してしまうと、変更できないということもあり、取引メッセージ欄から直接住所等を送信する。\u003c/p\u003e\n\u003ch3 id=\"5月13日\"\u003e5月13日\u003c/h3\u003e\n\u003cp\u003e　レターパックプラスで再送され、追跡ができるようになる。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/auction/wontArrive/found.jpg\" alt=\"追跡可能\" width=\"200px\" /\u003e\n\u003c/div\u003e\n\u003ch3 id=\"5月15日\"\u003e5月15日\u003c/h3\u003e\n\u003cp\u003e　ついに配達される。\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; \"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/auction/wontArrive/arrive.jpg\" alt=\"追跡可能\" width=\"200px\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e荷物の追跡サービスを利用したところ、「お問い合わせ番号が見つかりません。」と表示されました。どこに問い合わせればいいですか？ - 日本郵便\u003cbr\u003e\n\u003ca href=\"https://www.post.japanpost.jp/question/124.html\"\u003ehttps://www.post.japanpost.jp/question/124.html\u003c/a\u003e （2024年5月16日）\u003c/li\u003e\n\u003cli\u003eヤフオクで荷物の配送状況がデータ取得失敗となっているのですが荷物は\u0026hellip; - Yahoo!知恵袋\u003cbr\u003e\n\u003ca href=\"https://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13225273303\"\u003ehttps://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q13225273303\u003c/a\u003e （2024年5月16日）\u003c/li\u003e\n\u003cli\u003eオークションで「配送状況不明」となった荷物の行方 | 趣味に忠実に生きています\u003cbr\u003e\n\u003ca href=\"https://ameblo.jp/cyacya-07/entry-12797779515.html\"\u003ehttps://ameblo.jp/cyacya-07/entry-12797779515.html\u003c/a\u003e （2024年5月16日）\u003c/li\u003e\n\u003c/ul\u003e","title":"おてがる配送 ゆうパケットが届かない！ 📦"},{"content":"事の発端 とある日に、ハードオフに行くと、バッテリーが死んでるUPSが約1000円で売っているのを見つけ、買ってみる。3000円くらいでバッテリーを交換し、100Vも出力できていたので、いざ自分のサーバにつなげてみれば、何と！停電しかけて、サーバが落ちてしまう事象が発生してしまう。\n見た目 動作の様子 なんでそうなるの？ UPS_BR550GというAPC社製のUPSには、後継モデルのUPS_BR550Sがあるが、その違いは、疑似正弦波か正弦波を出力するという違いがあるらしい。確かに公式サイトの仕様書を見てみるとどうも、正弦波より20%位ゆがんだ波形が出力される的な記述がある。サーバや最近の電源は特に、力率改善回路なるものが電源に入っていて、疑似正弦波と組み合わせたらだめっぽい。なんか、ジャンク品だったから壊れているとかではなさそうだった。（PFC対応とか書いていあるのは、力率改善回路の事っぽいが、実際に対応しているかまではよくわからない）\nということで？ どうも、APC社のUPSではsmart UPSあたりのシリーズがデフォルトで正弦波出力に対応しているらしいので、そこらあたりが欲しいと思ったけど、なるべく停電させない努力をして、とりあえずしばらくはこの問題はおいておこうということになった。\n参考にしたサイト APCブランドUPS 仕様書のリンク | APC 日本 https://www.apc.com/jp/ja/faqs/FA53475/ （2024年6月3日） ","permalink":"https://www.nyanmo.info/posts/hardware/ups_br550g-jp_porbrem/","summary":"\u003ch2 id=\"事の発端\"\u003e事の発端\u003c/h2\u003e\n\u003cp\u003e　とある日に、ハードオフに行くと、バッテリーが死んでるUPSが約1000円で売っているのを見つけ、買ってみる。3000円くらいでバッテリーを交換し、100Vも出力できていたので、いざ自分のサーバにつなげてみれば、何と！停電しかけて、サーバが落ちてしまう事象が発生してしまう。\u003c/p\u003e\n\u003ch2 id=\"見た目\"\u003e見た目\u003c/h2\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/UPS_BR550G-JP_porbrem/appearance.png\" alt=\"見た目\" width=\"30%\" height=\"30%\" /\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/UPS_BR550G-JP_porbrem/appearance2.png\" alt=\"見た目\" width=\"30%\" height=\"30%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"動作の様子\"\u003e動作の様子\u003c/h2\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/UPS_BR550G-JP_porbrem/working.png\" alt=\"動作の様子\" width=\"30%\" height=\"30%\" /\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/UPS_BR550G-JP_porbrem/working2.png\" alt=\"動作の様子\" width=\"30%\" height=\"30%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"なんでそうなるの\"\u003eなんでそうなるの？\u003c/h2\u003e\n\u003cp\u003e　UPS_BR550GというAPC社製のUPSには、後継モデルのUPS_BR550Sがあるが、その違いは、疑似正弦波か正弦波を出力するという違いがあるらしい。確かに公式サイトの仕様書を見てみるとどうも、正弦波より20%位ゆがんだ波形が出力される的な記述がある。サーバや最近の電源は特に、力率改善回路なるものが電源に入っていて、疑似正弦波と組み合わせたらだめっぽい。なんか、ジャンク品だったから壊れているとかではなさそうだった。（PFC対応とか書いていあるのは、力率改善回路の事っぽいが、実際に対応しているかまではよくわからない）\u003c/p\u003e\n\u003cdiv style=\"display:flex; justify-content:center; margin:10px; overflow-x: scroll;\"\u003e\n    \u003cimg style=\"margin:10px;\" src=\"/posts/hardware/UPS_BR550G-JP_porbrem/compare.png\" alt=\"比較画像\" width=\"100%\" /\u003e\n\u003c/div\u003e\n\u003ch2 id=\"ということで\"\u003eということで？\u003c/h2\u003e\n\u003cp\u003e　どうも、APC社のUPSではsmart UPSあたりのシリーズがデフォルトで正弦波出力に対応しているらしいので、そこらあたりが欲しいと思ったけど、なるべく停電させない努力をして、とりあえずしばらくはこの問題はおいておこうということになった。\u003c/p\u003e\n\u003ch2 id=\"参考にしたサイト\"\u003e参考にしたサイト\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eAPCブランドUPS 仕様書のリンク | APC 日本 \u003ca href=\"https://www.apc.com/jp/ja/faqs/FA53475/\"\u003ehttps://www.apc.com/jp/ja/faqs/FA53475/\u003c/a\u003e （2024年6月3日）\u003c/li\u003e\n\u003c/ul\u003e","title":"UPS_BR550G JP 相性問題 🔌"},{"content":"　このページは、文字どうり hello world 的に作ったテストページです。記事が投稿できるか確かめるために作られました。\n適当にコードを書いてみる main.c #include \u0026lt;stdio.h\u0026gt; // なんとなくブログ更新テスト用に適当に書いただけで、この関数自体が動くかは試してない void showAllArg(int argc,char **argv){ for(int i = 0; i \u0026lt; argc; i++){ printf(\u0026#34;%s\\n\u0026#34;,argv[i]); } } int main(int argc,char **argv){ printf(\u0026#34;hello world!\\n\u0026#34;); return 0; } コンパイルする gcc main.c -o main ./main # 実行 three.js のテスト STL ファイルの表示 glTF ファイルの表示 折りたたみ 折りたたまれたゆっくりさん ゆっくりさん ゆっくりしていってね！\nカバー画像のリンク nicotalk＆キャラ素材配布所 http://www.nicotalk.com/charasozai_kt.html ","permalink":"https://www.nyanmo.info/posts/hello_world/","summary":"\u003cp\u003e　このページは、文字どうり hello world 的に作ったテストページです。記事が投稿できるか確かめるために作られました。\u003c/p\u003e\n\u003ch2 id=\"適当にコードを書いてみる\"\u003e適当にコードを書いてみる\u003c/h2\u003e\n\u003ch3 id=\"mainc\"\u003emain.c\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stdio.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// なんとなくブログ更新テスト用に適当に書いただけで、この関数自体が動くかは試してない\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshowAllArg\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e argc,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003eargv){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e argc; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%s\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e,argv[i]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e argc,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003eargv){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello world!\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"コンパイルする\"\u003eコンパイルする\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egcc main.c -o main\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./main \u003cspan style=\"color:#75715e\"\u003e# 実行\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"threejs-のテスト\"\u003ethree.js のテスト\u003c/h2\u003e\n\u003ch3 id=\"stl-ファイルの表示\"\u003eSTL ファイルの表示\u003c/h3\u003e\n\u003cp\u003e\u003cscript type=\"importmap\"\u003e\n{\n  \"imports\": {\n    \"three\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/build/three.module.js\",\n    \"three/addons/\": \"https://cdn.jsdelivr.net/npm/three@0.170.0/examples/jsm/\"\n  }\n}\n\u003c/script\u003e\n\n\u003cscript  type=\"text/javascript\" src=\"https://www.nyanmo.info/libs/zip.js/dist/zip.min.js\"\u003e\u003c/script\u003e\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\u003cdiv class=\"THREEcontainer461379285 column\"\u003e\n    \u003cdiv class=\"mainView\"\u003e\n        \n    \u003c/div\u003e\n    \u003cdiv class=\"MMDcontroler column\"\u003e\n        \u003cdiv class=\"buttonContainer mmdControlerContainer motion row border\"\u003e\n            \u003cinput type=\"button\" id=\"fullscreen\" name=\"fullscreen\" value=\"全画面表示\"/\u003e\n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n\u003cscript type=\"module\"\u003e\n    \n    \n    \n    \n    \n    \n    \n    \n    \n\n\n    import * as THREE from 'three';\n    import { STLLoader } from 'three/addons/loaders/STLLoader.js';\n    import { OrbitControls } from 'three/addons/controls/OrbitControls.js'\n\n    \n    \n    let article = document.querySelector(\"article.post-single\")\n    const screenSize = {\n        width: article.clientWidth,\n        height: article.clientWidth * 0.8\n    }\n\n    \n    const scene = new THREE.Scene();\n    scene.background = new THREE.Color().setRGB(0.03,0.03,0.03)\n    scene.add(new THREE.AxesHelper(50))\n\n    \n    const camera = new THREE.PerspectiveCamera( 75, screenSize.width / screenSize.height, 0.1, 1000 );\n    const container = document.querySelector(\".THREEcontainer461379285\")\n    const mainView  = container.querySelector(\".mainView\")\n    const renderer = new THREE.WebGLRenderer();\n    renderer.setSize(screenSize.width,screenSize.height);\n    renderer.shadowMap.enabled = true;\n    mainView.appendChild( renderer.domElement );\n\n    \n    const buttons = container.querySelector(\".MMDcontroler.column\")\n    const fullscreen = buttons.querySelector(\"#fullscreen\")\n\n    fullscreen.addEventListener(\"click\", () =\u003e {\n        mainView.requestFullscreen()\n    })\n\n    mainView.addEventListener(\"fullscreenchange\",() =\u003e {\n        let width = 0\n        let height = 0\n        if(document.fullscreenElement){\n            width   = window.innerWidth\n            height  = window.outerHeight\n            \n            \n            \n        }else{\n            width   = screenSize.width\n            height  = screenSize.height\n            \n        }\n        \n        \n        console.log(width)\n        console.log(height)\n        renderer.setPixelRatio(window.devicePixelRatio);\n        renderer.setSize(width, height);\n        \n        camera.aspect = width / height;\n        camera.updateProjectionMatrix();\n        \n    })\n    \n\n\n\n        \n\n    \n    const controls = new OrbitControls(camera, renderer.domElement)\n    controls.enableDamping = true\n\n    \n    const loader = new STLLoader();\n    loader.load( '\\/images\\/3Dmodel\\/DELLLatitudeE7450touchPadButtons\\/touchpadButtonBoth.stl', function (geometry) {\n        const material = new THREE.MeshStandardMaterial();\n        material.color = new THREE.Color().setHex(0x274d63)\n        const mesh = new THREE.Mesh(geometry, material)\n        mesh.receiveShadow = true\n        \n        mesh.position.x = Number(\"0\")\n        mesh.position.y = Number(\"20\")\n        mesh.position.z = Number(\"20\")\n        mesh.rotation.x = Math.PI * Number(\"0\") / 180.0\n        mesh.rotation.y = Math.PI * Number(\"0\") / 180.0\n        mesh.rotation.z = Math.PI * Number(\"90\") / 180.0\n\n        scene.add(mesh)\n    }, undefined, function ( error ) {\n        console.error( error );\n    } );\n\n    \n    let lightPosOffset = Number(\"200\")\n    const lightPos = [\n        {x:0,y:0,z:0},\n\n        {x:lightPosOffset,y:0 ,z:0},\n        {x:-lightPosOffset,y:0 ,z:0},\n\n        {x:0,y:lightPosOffset ,z:0},\n        {x:0,y:-lightPosOffset ,z:0},\n\n        {x:0,y:0 ,z:lightPosOffset},\n        {x:0,y:0 ,z:-lightPosOffset},\n\n        {x:0,y:lightPosOffset ,z:lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:lightPosOffset},\n        {x:0,y:lightPosOffset ,z:-lightPosOffset},\n        {x:0,y:-lightPosOffset ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:lightPosOffset},\n        {x:lightPosOffset,y:0 ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:0 ,z:-lightPosOffset},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:lightPosOffset ,z:0},\n        {x:lightPosOffset,y:-lightPosOffset ,z:0},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:0},\n\n        {x:lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:lightPosOffset},\n        {x:-lightPosOffset,y:lightPosOffset ,z:-lightPosOffset},\n        {x:lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n        {x:-lightPosOffset,y:-lightPosOffset ,z:-lightPosOffset},\n    ] \n\n    \n    const color = 0xFFFFFF;\n    const intensity = Number(\"1\");\n    for(let pos of lightPos){\n        let light =  new THREE.DirectionalLight(color, intensity);\n        light.position.set(pos.x, pos.y,pos.z);\n        scene.add(light);\n    }\n\n    \n    \n    camera.position.set(\n        Number(\"65\"),\n        Number(\"25\"),\n        Number(\"80\")\n    )\n    controls.target.set(\n        Number(\"0\"),\n        Number(\"0\"),\n        Number(\"0\")\n    )\n\n    \n    function animate() {\n        renderer.render( scene, camera );\n        controls.update()\n    }\n    renderer.setAnimationLoop( animate );\n\u003c/script\u003e\u003c/p\u003e","title":"hello world"}]