漫画ネタ202401

  • 恒星間航行を実現し宇宙に進出した人類は植民をつづける
  • しかし光速突破は結局実現できなかった
  • 従って宇宙に広がった人類は距離に従い強烈な分断が始まる
  • そしてそのうち一つの星系で魔素、基底現実で魔法、人間の圧倒的な物理操作用意識拡張マイクロマシンが開発される
  • その後、理由は明確な不明ながらその星系は主星を爆発させる事件で消滅する
  • 魔素を開発しそして消滅の憂き目にあった星系から辛くも脱出できたいくつかの播種船がそれぞれ事件の元から見つかりにくい新たなる恒星系に進出する
  • ある播種船は数万年後、ハビタブルゾーン限界の惑星にゼロからテラフォーミングで恒星間航行が可能にまで文明発展の復興を遂げる
  • もう一つ別の播種船は魔法基盤のマイクロマシンたる魔素による開発に全面的に振った挙句、人類統一政府相当が存在しない魔境に陥っていた
  • 宇宙開発以前に魔素の構成する可能性からの破滅を回避するために人為的に起こされる文明的混沌に陥っていた
    • そして前者が後者を発見する

  • 前者は伝説の播種船が送出された星系は消え去った故事から同様の結末を回避すべく、星間文明構築に向け次の開拓先候補星系を探していた所、数十年で到達可能な後者を発見す
    • 「まさかあの暗黒星雲の向こうにあるとは…」
  • が、先に送出した観測機が正体不明の故障で後者星系外縁部で消息を絶つ
    • 調査の結果、原因は伝説の禁忌技術、MMの魔素で有る可能性が浮上する。がそれは可能性の一つであって重視はされなかった。
    • 「ま、可能性の一つですな。」「我々の播種船が出版した時点で禁忌技術です。使ってるなどないはず。」
    • 「どうして気が付かなかったんだろう。わかってたはずなのに」「可能性の数からして無理さ」
  • 消え去った星系の件も有り開拓は急務だし外縁惑星まで植民都市を拡張しきっていた
    • 「破滅を迎えた我らが播種船の出身星系は1万光年の先に有る。」
    • 「今の状況はわからない。間に巨大な恒星を2個は挟んでいるらしい」
  • 人口増加は太陽系より遥かに小さい星系だった。惑星も3個しか無い。すでに主星の光源の奪い合いをも発生させ始めていたし、次の植民地、資源の不足はもう恒星間移民しか残されていないと認識され始めていた
    • 「私達はあの窮屈な星系から開放されたのよ」「もう資源割当で争わなくていい」
  • というのも、記録が残る限り他の人類からの接触はなく、ならば残された人類は自分達だけであり、我らこそが恒星の海に文明を生存圏を再度広げるのだという気概があった
    • 「あの破滅の時代から人類の種を伝え、ここに我らは文明を再興させた」
    • 「あの破滅からどれだけの月日が流れたことか。その間他の人類が我々に手を差し伸べただろうか?否!誰も居なかったのである!」
    • 「その孤独から我らは自力で立ち上がった!我ら以外に人類は居ない!我らこそが人類、今こそ破滅を迎えずこの星の海に人類が再度足を踏み出す時なのだ!立てよ我らが星の子らよ!」
  • そこに人類が住まう後者発見の報が届き、星系の世論は連絡を取り生存権を統合する機運に包まれた。
    • 決定打は人類の文明発展でしか観測されない分子の検出だった
    • 観測結果からもたらされる予測によればハビタブルゾーンの主星どころかいくつかの星に人口拠点が有るらしい。
    • しかし、星系にはやけに塵が多いという点は特徴的だった。星系の内側の何処かに火山か小惑星が粉砕されたのであろうと予測された。
    • 「塵が多いのが特徴ですな。小惑星が粉砕されたのでしょう。何があったかワクワクしますなぁ」
  • 即座に有人植民パッケージを有志の下、派遣を決定する
    • 「よいよ我々が恒星間種族に復帰するのだ!いざゆかん!星の海へ!」高揚する世論
  • 後者へ送り出された播種船は到達まで数十年かかることから橋頭堡を築くためノーリターンを想定された。
  • 有志にはサイボーグもAIも高性能計算機も生身の人間も不慮の事態を鑑みて選抜された。
    • 500年を生きた生き飽きた人間が自身のコピーを残し志願する
    • 「私は行くよ。惑星が3個しか無いこんな狭い世界じゃなくてね」
    • 「また数百年後には会えるさ。」
  • ノーリターンであることは出発式に伝えられる。
    • 「いいね。君たちはあの星系に行くのだ。エネルギーは心配しなくていい。過去の探査船同様、推進ビームはちゃんと照射し続けておく。」
    • 「それでは100年後の吉報を待つ!」「敬礼!」
  • 魔素の情報は禁忌ゆえに開発した当時の伝説の星系由来の公知情報のみで、実際の所、開けたら最後除去が困難だという程度しか分かっていなかった。
    • 「魔素?なんだこりゃ?」「マイクロマシンの一種だよ」「へぇ聞いたこと無いな」「そりゃ禁忌だからね」
    • 「まさか、使ってるなんて恐ろしくて考えたくもないよ」
    • 「グレイグーだろ?全部MMに埋め尽くされちまうのさ」
    • 「一応制御はできてたみたいだけどね。だから我々はこうして無事なんだよ。」
  • 次第に故障前提で保険をかけ大量に送り込んだ先行偵察機により状況は分かってくるが暗澹とした情報に埋め尽くされる
    • 「どうなってるんだ。何かの間違いだろ?なんで外縁に到達したとたん全部壊れるんだ」
    • 「俺達より前に到達する偵察機はあと何機だ?」「さっきので最後です。全部壊れたわけではないですが、故障ですかね。」
  • 播種船が前者の星系外縁に到達した頃、船に念の為設置したセンサーからMM警報を食らう
    • 「何の警報だ?」
    • 「わかりません、いろんなところから徐々に、外側からナニカに侵食されているような」
    • 「こいつは何だ」「今調べます。まさか…」
    • 「そのまさかだよ。私が頼んで外縁到達前につけておいてもらったんだ。私は勝ちたくない賭けに勝ったみたいだね。」「これからが大変だよ」
  • 目標のハビタブルゾーン内の惑星に近づくにつれ播種船は星系に漂う魔素に侵食されだんだん機能を停止していく
    • 「急げ、おいおいおい。どんどん機材が停止していくぞ」
    • 「生存限界までは?」「このままだとあと2日と言ったところでしょうか」
    • 「船を棺桶にしたくなかったらさっさと方法を探せ!」「方法は有るよ」「なんだと」「念の為」
  • なんとか過去の伝説文献からMMの機能を無効化する安全装置の信号を割り出し事なきを得る
    • 「こんな簡単なものでいいのか?」
    • 「安全装置としては優秀ですね。しかし数万年前の情報が有効で助かりました」
  • 引き返すか議論するが、引き返しても中間地点で迎撃される旨が星系内到達後開封した封印命令書に通達されていた
    • 「船の機能は7割まで復旧できているが」
    • 「おれはこんな魔境だとは聞いてなかったぞ」「そんな覚悟で望んだのか?ここは前人未到だぞ?」
    • 「引き返して違う星系に志願すべきだ。我々ならテラフォーミングから出来るだろ?」
    • 「ここに、星系に到達してから開けるメッセージが有るんだが…」
    • 「おいおい、冗談だろ?」
    • 「妥当だね」「俺達はもう汚染されてるってことだ」「アイツラ知ってたのかよ!」「私でもこうするね。そのための人身御供だ」
  • 仕方ないので調査と植民候補地を探すことに決定する
    • 「じゃあ俺達はココに骨を埋めるしか選択肢はないわけだ。異論は?」
    • 「仕方ねぇな」「じゃあ」
  • 調査の結果、星系全域がMM汚染されており、星系の何処に作ろうと大差が無いことが分かる。
    • 「この塵、全部MMなの?!」「みたいね。流石にまだ恒星間には広まってないみたいだけど」
    • 「星屑とかそういったものじゃないわ。もしかしたらカモフラージュなのかも」
    • 「恒星間は流石に放射性元素でも無い限り無理だね。コイツラのエネルギー源は熱だ。恒星から離れたら止まっちゃう」
  • 仕方がないので時間もコストも安い人類が住まう惑星地上へ向かう
    • スペースコロニーの建造という手もあるが」
    • 「MMの存在下では建造には不安が残る。できれば地上に拠点を構えたい」「大気組成も問題ない。水もある。太陽光も十分だ。」
    • 「MMの濃度は凄そうだけどね。」「でも大気が有るだけマシだわ」
  • ファーストコンタクトで亜種人種に出会う
    • 「あれは人間?なのか?」
    • 「タコのような頭だと…何言ってるか分からん」
  • 言語はAIでなんとかなったが強烈な人為的な影を見る
    • 「翻訳機のおかげで言葉はなんとか通じるようだな」
    • 「しかし、この特徴どう思う?」「頭部以外はほぼ人間、ですかね」「人間と動物のミックスだな。信じられんこれで生存しているだと。」
    • 「我々の様な人間は居るとの事ですが…なにせ語彙が少なくて状況がイマイチつかめないですね」
    • 「体格で勝っているのが救いですな」
  • 星間移植民は現地民に比べ体育が圧倒的
  • が、運悪く魔法生物にエイリアン的な強襲を受けて移植民の先遣隊は全滅する
    • 「こちら先遣隊!救援を求む!」
    • 「何者かが!うわぁぁぁ!」
    • 「先遣隊は全滅だと!?この空中に出現するものは…魔法陣が」
  • しまいには衛星軌道上で強襲を受けて播種船は先遣隊第二陣を残して離脱する
    • 「なんだこの振動は!」
    • 「龍。ですかね。」「この高度に生物!?なんてことだ。私はまだ信じられません。」「いいからとっとと排除しろ!」
    • 「弾が当たらねぇ」「レーザーも弾かれるぞ!」「応戦していますが、排除できません!」
    • 「第2先遣隊が降下準備を完了してもう船外に放出済みです!どうしますか」
    • 「止む負えない!母艦がやられたら後がないぞ!このまま第二先遣隊は降下!我々は周回軌道から離脱する!」
  • 衛星軌道上で投げ出された先遣隊第二陣は仕方ないので現地民に習って魔物に襲われない安全地帯の橋頭堡確保に乗り出す。
    • 「各員聞いたか!このまま予定通り降下する!」「神のご我古語あらんことを」
    • 「とにかく体制が整うまで第一先遣隊の全滅地点の調査は後回しだ」「あ、MM制御信号は弱めてください」「なんでだ!?」「とにかく降下完了までまずは。」「良いだろう」
  • 魔物の戦術として初手で魔法基盤である魔素、MMを沈黙させる存在を消すのだそうだ
    • 「MM制御信号はずっとこのまま限界近い弱めで良いのか?」
    • 「推測ですが、この信号は非常に単純です」「その割にMMは機能停止をします。」「火を考えてください。火で炙れば生物は焼け死んでしまいます。MMが生存に必要な器官にまで組み込まれた生物が存在したら?」
    • 「言いたいことはわかったが、どうやって確認するんだ?」「MM探知機なんて無いぞ。有るのは検知器だけだぞ」
    • 「出来れば信号のONOFFで挙動を変える生物でも見つられれば…」
    • 「簡単に言ってくれる。ここのMM密度は相当なもんなんだぞ。まず電源を確保しないと俺達は生存すら危うい。」 ・結果、MM解除信号が魔物を呼び寄せる事が判明
    • 「やっぱりセンサーが有るんだなきっと。」「貴重な発振器が1個壊されたんだぞ。」「ええだからこうやって観察してるんじゃないですか」「第一先遣隊のように強烈信号発振で安全圏のマージンを設けるとご覧のとおりです。」
    • 「象以上のデカブツが居るなんて聞いてないぞ」
  • なんとか信号の出力を限界まで抑えるが
    • 「だったら節電のため、第一次隊を襲った連中を呼び寄せないためにも信号照射範囲を限界まで狭めるしか無いですね。」
  • 襲撃は偶然ではないが十分遭遇を回避は可能と判断
    • 「奴らの行動を見ると一撃離脱だな。」「ほら見てください、隣の小出力の発振器は無事です。それどころか忌避してます」「これは朗報だな。安全圏が作れる。」
  • 播種船は襲撃の修理のため大きい方の月軌道ラグランジュポイントに退避
  • そこで古代の衛星遺跡を発見する
  • 修理がてら先遣隊を派遣した惑星の観察をすすめ状況を整理する
  • 状況は混沌としていた
  • 15世紀程度のインフラ有るようだが…
    • 「どうして数万年前の都市遺跡がこんなに有るんだ」
    • ローマ帝国レベルの遺跡がゴロゴロしているぞ?」
    • 「人影はないのに何だこの不自然な輻射熱の分布は…」「それにこの火山の周りに有る明らかな人口構造物か」
  • 信号の範囲外に置いた精密機械作動不良を起こすことでその理由がだんだん分かってくる
    • 「MMが物体の中に食い込むから精密機械ほど影響が速いのか…しまったな」
    • 精密機械に入り込んだMMが自己複製を行い、機材の精度と剛性を破壊していく
  • 全ての機材が魔素MMに汚染されて機能停止に陥る前に、文明先行の利点を失う前に魔法を習得するしかないと決断をする。
    • 「我々も魔法を使うしか無い」
  • 魔法をAIの力を借りて少しずつ習得はするもののAI機材がほぼ死ぬ(電力が足りない)事で地元民から接収する方向に向かう
    • 「逆に魔素が足りない、魔力が足りないな」「電力でどうにかならないか?」「無理だ。もうMM抑止信号しか出せねぇ」
  • 先遣隊のうち生身の人間は適合性に問題は経過観察としてMM停止信号の照射対象外とされる。
    • 「あんたは完全な生身だ。気分はどうだ?」
    • 「上々だ」
    • 「魔力が体に取り込まれるまで時間がかかりそうだ。それよりも伝染病だ」
    • 「数万年で病気が増えてないことを祈るしか無いな」
  • 母船との通信は生きているので色々調査を依頼するが
    • 「襲撃に気をつけつつ、情勢をさぐれ。現地協力者が欲しい」
  • ラグランジュ・ポイントへの遺跡には女性のアバターが認証を寄越せと口うるさく言うが、言語から伝説の星系の技術系統で少なくとも10万年前には残存が確定する…その遺跡の中で襲撃を受ける
    • 「汝、その真名を捧げ、我が認証に答えよ」
    • 「この方式だと。まあやってみますが時間は保証できかねます」
  • 襲撃者は悪魔の姿の魔法の使い手で移植民を遺跡から追い出そうとする
    • 「やばいぞ、一端船に退避しろ!」「機関砲だ、火力で押し切れ!」「殺ったか?」「いや、だが引いてくれるようだ。」
  • 播種船の兵器で撃退した結果、軌跡から月からの来訪者と分かる
    • 「マジかよ」「月が黒い理由はまさか…」「高純度の魔素だぜ…」「グレイってよりパープルね」
  • 認証の突破は数学的に非常に難しい事が分かる
    • 「これは何だと思う?」「間違いない、制御信号衛星だ」「一気にMMを無力化出来ると?」「中身が無事ならな。」
    • 「無理だ。手持ちの機材じゃ100年はかかるぜ」 ・仕方がないので先遣隊に調査指示をするが厳しい状況に陥っていることがわかり救援物資を送る事に
    • 「なんとか前回の襲撃者は寄り付かないが…我々は」
    • 「分かった、物資のパックを投下する。それまで頑張ってくれ。」 ・衛星軌道上に蛇のような何かが居ることだけは分かる
    • 「やはり何かいるな。衛星軌道上の生物なんて前代未聞だぞ…どうやって生きているんだ」
    • 「MMの応用で未知のエネルギー回路があって太陽光か何かを直接摂取してるんだろう…なんてやつだ」 ・月からの来訪者対策にはMM抑制信号の照射量強化で魔法ごと封じる事で対応出来ることになった
    • 「なるほどな。遺跡は更に強力版と言ったところか」
    • 「何もなければいいんだが。」 ・救援物資は周囲の物質から分子転換炉とプリンターで出力したものを送る
    • 「我々が今届けられるのはこれだけだ」「十分だよ」
  • しかし、対MM制御信号がアダになって衛星軌道上で蛇みたいなのを寄せ付けてしまう
    • 「やっぱりだ!対空防衛戦だ、やつを物資に近づけさせるな!」
  • 自衛システムで大気圏突入まで妨害をしのぎなんとか物資は地上に落下するも先遣隊の位置から大幅にずれてしまった
    • 「物資シャトルは降下しましたが、先遣隊から数百キロはずれてしまいました」
  • それを取りに行く事に
    • 「分かった物資を取りに行くしか無いな」「300kmは離れているぞ」「そいつがなきゃ始まらないんだ」

TOTPソフトウェアトークンをBookmarkletで作った。

経緯

TOTPソフトウェアトークンなブックマークレット - Togetter

リポジトリ

GitHub - ryunosinfx/BookmarkletTotpAuth: Bookmarklet for Totp Auth

Bookmarkletのリンクが有るページ

Bookmarklet Totp Auth

作った理由

GoogleAuthenticatorと同等のものだが、アプリを入れたくなかった。※アプリストアはGoogleアカウントを要求されるのが気に入らない。 ブラウザは存在するがアプリを入れられないデバイス(ラズパイ、超絶古いがまだ最新Firefoxが動くアンヨヨイヨすまほ。)で使いたい。 ソースが見れないアプリが信用ならんので自作したかった。 職場のPCにソフトウェアのインストールが出来ないため私物すまほを使わされられる可哀想な環境をなんとかしたかった。 また、ブックマークレットの限界が何処かを確認したかったのもある。

判明したブックマークレットの限界

以上!

ブラウザが解釈可能な最大のURL長は?

まあ以下の記事で答えは出ているのだが、もう少し調べてみた@202307である。

各種OS/ブラウザでの長いフラグメントのあるURLの長さを調べてみました - Qiita

何を調べるか

まず観点としては以下が有る

  • ①ブラウザが開けるURL
  • ②ブラウザが開けるURLからコピペできるURL
  • ③jsのlocation.hrefで取得できるURL
  • ④ブックマークに保存できるサイズ

このうち吾輩が目指す素敵なBookmarkletは④が重要に成る。 ただ、以下のようにGitubPagesやGASみたいなCORS許可のあるサイトに配置してESのダイナミックimportで良いじゃないかという話も有る。

Bookmarkletを作ろう(準備編) - Qiita

テストツール

というわけで、テストツールを作成した。ES2018ぐらいで書いてあるので古いブラウザでは動かない。

Browser URL length checker

ここで、分かった事が以下のとおり。②はそういったシチュエーションは考慮外なので調べていない。

  • Chromium114@Ubuntu 22.04LTSは
    • ①③2094057byteで約2MB弱
    • ④ブックマークも2094057byte約2MB弱で同じ
  • Firefox114@Ubuntu 22.04LTSでは
    • ①③1048565byteで約1MB弱
    • ④ブックマークは65535byteで約64KB
  • Chromium114@Andoroidでは
    • ①③2094057byteで約2MB弱
    • ④ブックマークも2094057byte約2MB弱で同じ
  • Firefox114@Andoroidでは
    • ①③1048565byteで約1MB弱
    • ④ブックマークは65535byteで約64KB
  • 一応iPadSafariでも
    • ④ブックマークは65535byteで約64KBまでは大丈夫そう。

node js安直にローカルのファイルをブラウザに見せるだけの鯖

安直にローカルのファイルをブラウザに見せるだけの鯖を作りたい。 ※正直npmでpackage.jsonでの管理もしたくないレベルの場合に使用したい。

理由は簡単で、esmoduleでファイルを書くと、モジュールファイルがfile:///のスキーマからでは 悪意の有る第三者の攻撃(ローカルに落としたHTMLファイルから他のファイルを見ることが出来ちゃうよ)により 弾かれるようになってしまった。

なので、超絶簡単にサーバーを自前で建ててHTML+js+CSSのアプリを作りたい。 OS種別とか気にしたくもないのでnodejsが入ってる前提でサクッと。

実行は

node server.mjs

server.mjsの中身は以下の通り

import fs from 'fs';
import http from 'http';
const exts = {
    js: 'text/javascript',
    css: 'text/css',
    html: 'text/html',
};
const PORT = 8085;

http
    .createServer(function (req, res) {
        const url = req.url.replace('../', '/');
        const urls = url.split('.');
        const ext = urls[urls.length - 1];
        console.log('req url:' + url);
        try {
            res.writeHead(200, {
                'Content-Type': exts[ext] ? exts[ext] : 'text/plain',
            });
            const file = fs.readFileSync('.' + url);
            const responseMessage = file;
            res.end(responseMessage);
        } catch (e) {
            res.writeHead(404, {
                'Content-Type': exts[ext] ? exts[ext] : 'text/plain',
            });
            console.log('req e:' + e);
            res.end('NOT FOUND');
        }
    })
    .listen(PORT, '127.0.0.1');

Tia142漫画ネタ

-1---

(怪獣だぁ!逃げろ!)

ああ、我らがカンムス

(カンムス様だ!カンムス様が来たぞ!)

その美しき女神は童子のごとき妖精を従え

(お嬢!動けるのは五分だけだぜ?)

(承知!)

怪獣をたやすく

(来た怪獣の!攻撃だ!)

(聞かぬ、一刀両断!)

ほふり星を開放してきた

(カンムス様万歳!)

何時からおりたのや?

(ふん、たやすいもんだぜ!)

人類有史以前?さにあらず、この星の歴史にあり。

それはこの星の開拓初期、宇宙で初めて人類が”奴ら”の猛威に相対した時に遡れり

-2----総裁当局

時既に恒星間探査船に星間ゲートにて超光速移動を実現した時代の話なり。

銀河にひろがりし人類はとある星系で惑星ごと消滅させるしか手の打ちようがなかりせしAIの反乱を経験したり。 反乱鎮圧後、兵権をAIに渡す事を禁じ、人間のみが握ると規定する星間条約を結びたり。これを星間条約連盟といいたり。

しかしAIは禁止すれどもAI級効率の人類圏未接触生物との遭遇はいずれは迎える事態と危惧されし。

もしかの生物が出現し、現地入植者を殲滅せし時はAIの時と同じく、即ちに”恒星落としの刑”に処す事と同時に定めれり。 ”恒星落としの刑”、それは入植惑星だった星に隕石落とし軌道を変え惑星ごと灼熱の主星の落とす最終手段なり。

それを星間条約では”上位侵略性未接触生物”と呼称せり。

このカンムスの生まれる星”八千代”へ、夢と希望の引き換えに莫大な借金を抱えたる入植団達、 星間条約を結び星間条約連盟に加入をはたして降り立てり。

-3----

そして時過ぎること数年、順調に行くと思われたその時、”奴ら”現れり

怪獣とその眷属達、

おおその20mを優に超す巨体やおぞましき姿、火を吐き光線を発射し入植者を圧倒することすまじき。

「あんな害虫踏み潰せ無いのか?」「あんた大きさ分かってんのか!?」

精々盗賊対策でしか無き治安部隊を歯牙にもかけず一蹴し、都市を木の葉のごとく壊滅せしこと甚だしき

急遽傭兵団を雇うも初戦で遁走の有様にて、

「砲兵支援だけはしてやる!前線は自分で支えな!」

やむなく住民総出で抵抗部隊、市民兵団を作り、阻止を試みたるが焼け石に水のごとし!

「うわー助けてくれ!」「ここで食い止めるぞ!」「爆破!」

絶望的な状況がそこかしこで少しでも怪獣の歩みを止めるべく展開されり

-4---

ああ、どうしよう

「防衛線が突破されました。」「逃げ遅れた部隊が救援を求めています」

「救援をだせ!人間が死んだら元も子もないんだぞ!」「次の防衛線に退却を急がせろ」

「砲弾備蓄があと1ヶ月分もありません」

「とにかく戦線を安定させろ、話はそれからだ!」

頭を抱える八千代開拓政府の長、将軍様

あまりの惨劇に次々と帰ってしまう武器商人達(これは駄目だ、宇宙戦艦級でないと無理だぞ)

今までの苦労を、これからの未来を全て破壊し尽くすあの怪獣をなんとかしなければと決心せり

「で、提案が有る人物が居るのですがー」

残るは一人の胡散臭い行商人のみなり

「ええい、良いから連れてこい!」

このまま人類はこの星八千代から駆逐されるのかや?

「このままでは来月の砲弾枯渇で防衛戦線が突破されます」

「これまでか・・・」

「いいえ、まだ手が有ります」「連れてきたぜ?」

-5--

そこに売り込み行商人に連れてこられたるは伝説の博士、カンムスの生みの親なり

「機械でもないAIでもない、我らが人間が怪獣を倒してみせましょう」

黒き怪獣を踏みつぶすその大きな足は一体誰や?

おお、この麗しき原始のFirstレディ、博士の相棒ではないか

「こんな汚れ仕事、これっきりよ?」

光り輝く槍で一閃、沸騰する大地、飛び散る肉片

「女神様だ・・・」

その神々しき姿に人々は涙したり。

-6--

博士は語れり

「我らに足らぬのは体格、それも怪獣など一蹴できる大きさ」

「怪獣が真似る?それは不可能なのです。我々の、宇宙太陽光発電という惑星表面積を超えて太陽定数を凝縮できる動力源が無い限り熱力学第二法則により不可能なのです!」

「弱いものいじめ?いいえ!我らは必勝必滅を悲願とし奴らに引導を渡すのです」

「何故ならこの星の生存権を賭けた勝負、負けた方は叩き出される運命なのだから」

「この麗しく、少なくとも人類の半分には快く受け入れられるであろう容姿」

「宇宙戦艦の主砲直撃でなければ傷が付かない身体」

「人間と同じタイムスケールで駆動できる巨体」

「そして、24時間365日作戦行動ができる休息不要な持久力」

「その間補佐するいかなる妨害も受け付けない人間が潰れる加速度にも耐えられる強靭な内部補助人員、妖精さん

「われわれ人類が、人類のパワーを以て勝利するのです」

-7--

その頃、星間条約連盟では怪獣たちの力と数、”上位侵略性未接触生物”、AI級の力を恐れたり。 星間ゲートを閉じ、殲滅をするか否かの会合が連日連夜、専門家を集め行われり。

「星間ゲートは閉じよ。連絡が途絶え次第、殲滅艦隊を派遣する。以上だ。諸君、異議はないかね?」「異議なし!」

そして将軍様にその報伝わると決心したり。

「腹を決めたよ」

「我々が生き残れば、それが勝利だ」

腹をくくった将軍様

起死回生一発逆転、そのためのカンムス数を揃えるべく首都さえも捨て最終防衛線、 宇宙太陽光発電の受電設備が有りカンムスの生まれる場所、カンムスの里へ退却を敢行すると号令をかけたり。


そして・・・星から逃げる意志と能力の有る者達があらかた居なくなりし頃・・・

-8--

反撃のときは来たれり、里で生まれし居並ぶ女神カンムスに将軍様の最後の激が飛べり!

「諸君、機は熟した。人類に栄光あれ!」「人類に栄光あれ!」「乾杯!」

「突貫!」

ああ我らが鉾、我らが剣、向かう所肉片とならず敵う怪獣はなし、

日が暮れるとも、夜が明けるともその矛先、鈍ることなし。

生死をかけて押し寄せる黒い怪獣の波を間髪入れずに次々と倒しけり

「1000匹目!」「まだまだ!」

その鉾先は幾日も幾月も、留まる事は無し。積み上がるは怪獣達の躯の山々なり

おお、ここに危機去れり、カンムスにより人類はこの星に生き残れり!

-9---

里から生まれいづるカンムス達、生存圏防衛線の確立に次々と出征せり その凛々しきカンムスの姿を見たる残った市民が沸き立ちぬ

その一方で遥か上空、軌道上にてお別れの会、催されり。

名残惜しむ将軍様

「博士、行ってしまうのかね?」

満足気にきりりと背筋を伸ばす博士

「私の目的は達成され、起案の正しさは証明されました。我々は怪獣の故郷に赴きます」

そう言うと博士はレディと星を離れたり。

そして向かう先に星の海を単独で渡り切るという深宇宙探査艦が航海の年季が入った姿で待ちにけり。

迎えるはあの胡散臭い行商人

「待ってたぜ?」「お世話になるわ」

恒星間探査船に乗った行商人と共に星の彼方に旅立てり。

-10--

なぜ、まだカンムスはこの星に居るのかや?

そはみなの足元に怪獣の種が眠っているからなり。

時が経てば怪獣の種は根を張り力を蓄え、そしてまた人類に仇なすべく現れるなり。

「うーっす。先輩、こっちの駆除終わったっす。」「おつかれー」

そのカンムスの任務が消える日は真に怪獣を調伏せる方法を人類が見つける遥か未来なり

その時、カンムスも妖精さんも人間になれるという・・・

GAS(Google Apps Script)のハマりどころ@2022

今やってること

WebRTCのシグナリング鯖の構築を目指している。 WebRTCはP2Pなのは良いが、シグナリング鯖と言うやつが要求されるのである。こいつはP2P接続の情報(sdp)を交換するのだがそれだけなら一見大したことはない。 しかし実際に自前構築を考えるとこのシグナリング鯖というやつがが厄介でサンプルを見るとどいつもこいつもWebSocketをオススメしてくる。WebSocketは分かりやすいのだが無料で借りれる場所はない。WebSocketは余りにもリソースを食うのだ。他にもHttpStreamApiと言うのも有ったがFirefoxが100でようやく対応しているのでメジャーと言うには程遠い。そしてリソースを食う。

ストリーム API - Web API | MDN

結局の所、普通の掲示板でも良いのだ。情報交換ができれば普通の掲示板でも何の問題もない。 そこでGASだ!Googleのアカウントが有れば使える。Googleのアカウントは1IPか1Andoroidに6ヶ月に1回取れる。そうジャンク屋でGetしたスマホで取れるのである。 ここにシグナリング鯖を建てられれば、雨後の筍のように自腹で鯖を立てること無く、誰かに生殺与奪の権を握られること無くコピペでWebRTCを使える事に成る。

ハマったところ

次の点はハマった。これで3年は寝かせる羽目になった。

GASの制約
  • 使えるのはdoGetとdoPostだけ

    • まあ問題は無いんだよ。正常に動けば。ただし、エラーを起こすとCORS許可のヘッダーを返さずにエラー(ブラウザ上ではCORS許可されてないよエラー)になるので意味不明である。
    • 当然、投入したデータ起因でエラーになったら良くわからない。
  • GASのログ見えない

    • ログは取ってあるけど、GCPに課金してちょ!って言われるので泣く泣く諦めるしか無い。
    • 仕方がないのでdoPostを呼ぶ関数を中に作ってそいつ越しにデバッグをするしか無い。投入されたデータをエスパーして。
  • async/awaitは対応したけどdoGetとdoPostは別腹な
    • もう、何が起こったのか分からなかった。V8に対応したんじゃないの?ってdoGet/doPost呼び出し側がPromiseに対応してないでやんの・・
  • setTimeout?知らない子ですね。
    • これが痛い。マルチプロセスで掲示板上書きせずに書き込もうとか考えると結構待つ必要が発生するのだが、そんな用途は端から考えてない模様。まあExcelみたいなスプレッドシートを扱うんじゃ仕方ないね。
    • じゃあどうするか?それはもうwhileでコンテキストスイッチを噛ますべくDate.now()で指定時刻になっているか判定を別関数にして呼びまくるしか無い。console.log()とか無駄につけて。
  • Googleの他のサービス呼び出しは兎に角遅い

Cache Service  |  Apps Script  |  Google Developers * Cacheサービスの制約はKVSで生存時間は10分、保持レコード数は1000件、1レコードの長さはキーが250byte、データが100kbなので十分である。

サンプル

ライセンスはMITでよろ。

鯖側

Webアプリとして誰でもアクセス出来るようにデプロイ

const cache = CacheService.getUserCache();
const EXPIRE_DURATION = 1000 * 2;
const WAIT_EXPIRE_DURATION = 1000 * 20;
const parse = (event) => (!event || !event.parameter ? { cmd: null, group: null, data: null } : { group: event.parameter.group, cmd: event.parameter.cmd, data: event.parameter.data });
function sleep(sec = Math.floor(Math.random() * 800) + 200) {
    const expire = Date.now() + sec;
    const func = (ms) => ms > expire;
    return new Promise((resolve) => {
        while (!func(Date.now())) {
            console.log(`sleep: sec:${sec}/expire:${expire}/now:${Date.now()}`);
        }
        resolve();
    });
}
async function wait(key, value) {
    const ckey = `c%${key}`;
    const challeng = value + Date.now() + Math.floor(Math.random() * 1000000);
    let c = null;
    while (c !== challeng) {
        await sleep();
        cache.put(ckey, challeng);
        c = cache.get(ckey);
        cache.remove(ckey);
    }
}
async function add(key, value, now = Date.now()) {
    await wait(key, value);
    let c = cache.get(key);
    c = c ? JSON.parse(c) : { message: [], expire: now + 40000 };
    const n = [];
    for (const v of c.message) {
        if (v.expire > now) {
            n.push(v);
        }
    }
    n.push({ value, expire: now + WAIT_EXPIRE_DURATION });
    cache.remove(key);
    cache.put(key, JSON.stringify({ message: n, expire: now + 40000 }), 900);
}
function put(key, value, now = Date.now()) {
    cache.remove(key);
    cache.put(key, JSON.stringify({ message: value, expire: now + EXPIRE_DURATION }));
}
function doWait(state, expire) {
    console.log(`doWait:expire;${expire}`);
    if (expire < Date.now()) {
        state.isOver = true;
    }
}
// eslint-disable-next-line no-unused-vars
function doPost(event) {
    const out = ContentService.createTextOutput();
    out.setMimeType(ContentService.MimeType.JSON);
    try {
        const { group, cmd, data } = parse(event);
        const key = JSON.stringify([group, cmd]);
        const value = typeof data !== 'string' ? JSON.stringify(data) : data;
        if (cmd === 'wait') {
            const state = { isOver: false };
            add(key, value).then(() => {
                state.isOver = true;
            });
            const expire = Date.now() + 1000;
            while (!state.isOver) {
                doWait(state, expire);
            }
        } else {
            put(key, value);
        }
        console.log('END:doPost');
        out.setContent(JSON.stringify({ message: 'POST OK' }));
    } catch (e) {
        out.setContent(JSON.stringify({ message: 'ERROR', e: e.message, stack: e.stack }));
    }
    return out;
}
// eslint-disable-next-line no-unused-vars
function doGet(event) {
    const out = ContentService.createTextOutput(); //Mime TypeをJSONに設定
    out.setMimeType(ContentService.MimeType.JSON); //JSONテキストをセットする
    try {
        const { group, cmd } = parse(event);
        const key = cmd && group ? JSON.stringify([group, cmd]) : null;
        let value = key ? cache.get(key) : null;
        value = value ? (typeof value === 'string' ? JSON.parse(value) : value) : null;
        if (key && value && (!value.expire || value.expire < Date.now())) {
            cache.remove(key);
        }
        out.setContent(JSON.stringify({ message: key ? (value ? value.message : value) : 'GET OK' }));
    } catch (e) {
        out.setContent(JSON.stringify({ message: 'ERROR', e: e.message, stack: e.stack }));
    }
    return out;
}
ブラウザ側

これがなかなか正解が何かで往生した。結局、GASは"""正常時"""のみリダイレクトをしてCORS許可("*"なのでどこでもOK)を返す。不正時はクロスオリジン不許可アクセス遮断エラーになる。 なおPOSTも結果が取得できる。

const contentType = 'application/x-www-form-urlencoded';
    convertObjToQueryParam(data) {
        return data && typeof data === 'object'
            ? Object.keys(data)
                    .map((key) => `${key}=${encodeURIComponent(data[key])}`)
                    .join('&')
            : data;
    }
    async getTextGAS(path, data = {}) {
        const r = await fetch(`${path}?${this.convertObjToQueryParam(data)}`, {
            method: 'GET',
            redirect: 'follow',
            Accept: 'application/json',
            'Content-Type': contentType,
        });
        return await r.text();
    }
    async postToGAS(path, data) {
        const r = await fetch(`${path}`, {
            method: 'POST',
            redirect: 'follow',
            Accept: 'application/json',
            'Content-Type': contentType,
            body: `${this.convertObjToQueryParam(data)}`,
            headers: {
                'Content-Type': contentType,
            },
        });
        return await r.text();
    }
使い方
  • GASに鯖をデプロイする
  • ブラウザから以下のJSONを投げる
    • {group:"一意なグループ名",cmd:"waitの場合は待つ、他は適当",data:"sdp等のデータ"}
    • {message:"投稿データ"}を受け取る
  • WebRTCのバニラICEの儀式をこの掲示板(投稿データの生存時間は20秒に設定)の上で行う。

最近のコンビニ印刷機(シャープ製)について覚書

機種はこれ

マルチコピー機<MX-3631DS>をコンビニエンスストア「ファミリーマート」に納入|ニュースリリース:シャープ

やったこと

コピー本として新刊を印刷した。コロナが有ったので二年ぶりである。このときの状況を覚書しておく。

以前のコピー機での配慮

まず10MBの壁があり10MBを越えられない。10MBを超えると認識しない、印刷対象に表示されない。 したがって、600dpiのB5本原稿、B4に600dpiなので257mm×364mm=6070x8698ピクセルBMPのグレースケール(1ピクセル1byte)で約52MB、jpegなのでもっと小さく、なんとか10MBにしたい。 実際にはだいたい20MBになる。なのでjpegの圧縮率をUPしないといけない。

今回

なので、 CopiBon- dist

でちゃちゃっと原稿を印刷用画像に整形して確実に10MB以内に収まる350dpiと20MB以上になる600dpiで試みる。

結果、20MB超えのデータでもOKであった。紙は薄いので両面印刷は駄目な気配がする。 あとはデータ量が厄介そうで20MBを4枚一括指定した場合印刷開始まで3分は待たされてしまった。非常に時間がかかる。あとPDFはまだ試していない。 PDFにしなくてもdpi指定の画像をフォルダ単位で指定が可能なのでもうこれで良いのかも知れない。 ただ、ファイル名が連番に成るように工夫する必要は有るが。