PageSourceSearch

https://ahus.uk/blog

html ahus.uk collected 2026-10-05 22:53:43 UTC 181,596 bytes, 90 lines download raw bytes

1<!doctype html>
2<html lang="en">
3	<head>
4		<meta charset="utf-8" />
5		<link rel="icon" href="./favicon.png" />
6		<meta name="viewport" content="width=device-width, initial-scale=1" />
7		<link rel="stylesheet" href="./fonts/hack/hack-subset.css">
8
9		<meta name="description" content="薄羽皐太 (Kota Usuha) homepage and blog">
10		<meta name="author" content="Kota Usuha">
11		<meta name="keywords" content="薄羽皐太, Kota Usuha, homepage, blog, software engineer, web developer, programmer, designer, artist, musician, composer, writer, poet, philosopher">
12		<meta charset="utf-8">
13
14		<meta property="og:title" content="ahus.uk">
15		<meta property="og:description" content="my homepage and blog">
16		<meta property="og:image" content="https://ahus.uk/favicon.png">
17		<meta property="og:url" content="https://ahus.uk">
18		<meta property="og:type" content="website">
19		<meta property="og:site_name" content="ahus.uk">
20		<meta property="og:locale" content="ja_JP">
21		<meta property="og:locale:alternate" content="en_US">
22
23		
24		<link href="./_app/immutable/assets/0.GJonypYj.css" rel="stylesheet">
25		<link href="./_app/immutable/assets/3.C3LP-3p_.css" rel="stylesheet">
26		<link rel="modulepreload" href="./_app/immutable/entry/start.Daoojf4R.js">
27		<link rel="modulepreload" href="./_app/immutable/chunks/entry.D5I0hpdo.js">
28		<link rel="modulepreload" href="./_app/immutable/chunks/runtime.B7uHmZwC.js">
29		<link rel="modulepreload" href="./_app/immutable/chunks/paths.CZRnjR3S.js">
30		<link rel="modulepreload" href="./_app/immutable/entry/app.B4amE5rk.js">
31		<link rel="modulepreload" href="./_app/immutable/chunks/store.U14WhaR7.js">
32		<link rel="modulepreload" href="./_app/immutable/chunks/svelte-head.DPoOH-Mq.js">
33		<link rel="modulepreload" href="./_app/immutable/chunks/disclose-version.aJqlrpEZ.js">
34		<link rel="modulepreload" href="./_app/immutable/chunks/if.De2i2mxV.js">
35		<link rel="modulepreload" href="./_app/immutable/chunks/props.DWmrlzzz.js">
36		<link rel="modulepreload" href="./_app/immutable/nodes/0.DLXZSnAO.js">
37		<link rel="modulepreload" href="./_app/immutable/nodes/3.DAEE4Xd5.js">
38		<link rel="modulepreload" href="./_app/immutable/chunks/legacy.DQNYSWjG.js">
39		<link rel="modulepreload" href="./_app/immutable/chunks/attributes.D4EFm6nH.js"><!--[--><!--]--><!--[--><!--]--><title>ahus.uk | blog</title>
40	</head>
41	<body data-sveltekit-preload-data="hover">
42		<div style="display: contents"><!--[--><!--[--><!----><div><div class="mt-5 max-w-screen-xl m-auto"><header><nav class="h-32 flex justify-evenly items-center w-full bg-stone-300"><a href="/" class="w-[30%] pl-5 text-xl md:text-2xl">ahus.uk</a> <div class="flex justify-around w-[30%] md:w-[10%] underline underline-offset-8 text-base"><a href="/me">me</a> <a href="/blog">blog</a></div></nav></header> <div class="mt-10 mx-auto w-[95%]"><!----><div class="w-[90%] m-auto"><div class="text-2xl my-10">Blog</div> <ul class="list-disc pl-[2rem] svelte-1ip2ume"><!--[--><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2024-11-10--svelte-blog">11/10/2024
43                    ブログシステムを刷新した</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2023-03-11--oji-chan-and-police">3/11/2023
44                    おじいちゃんこの距離歩くのは無理だって</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-11-14--could-not-build-wheels-for----">11/14/2022
45                    Conda下Poetry addでERROR: Could not build wheels for ...</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-06-11--variable-roller">6/11/2022
46                    ヴァリアブルローラーフォイルでエリアX帯行くまでに考えたこと</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2021-09-21--customize-python-http-server">5/11/2022
47                    Python標準のHTTPサーバーをカスタマイズしたい時</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-05-8--blog-search">5/8/2022
48                    卒業研究の成果を自分のブログに組み込んでみた</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-03-31--half-dot">3/31/2022
49                    半ドットはなぜ邪悪なのか</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-03-12--python-confluence">3/12/2022
50                    Pythonで触るConfluence API</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-03-6--learn-ml-model-in-online">3/6/2022
51                    運用中の機械学習アプリでデータを収集してモデルを再学習したい</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-02-1--wordle-solver">2/1/2022
52                    Wordleのソルバーを書いた</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2022-01-22--mapchip-gen">1/29/2022
53                    マップチップを自動生成するWebアプリを作った</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2021-09-27--use_state_dict">9/27/2021
54                    torch.save(model)をするときはモジュールに気をつける</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2021-08-9--swift-go-mobile-app">8/9/2021
55                    SwiftとGolangでスマホアプリを作る</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2021-05-8--weed-tea">6/6/2021
56                    その辺に生えてるよくわからん草を、お茶にして味わってみたã€
56‚</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2021-01-8--put-link-within-same-workbook-with-axlsx">1/8/2021
57                    axlsx で同じワークブック内のリンクを貼る</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2020-12-18--get-schema-comment-in-rails">12/18/2020
58                    railsアプリケーション内でスキーマのコメント情報を取得する</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2020-11-24--waniCTF-2020-writeup">11/24/2020
59                    waniCTF 2020 writeup</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2020-10-2--traffic-signal">10/2/2020
60                    信号守ったら車に轢かれそうになった話</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2020-08-30--cpaw-ctf">8/30/2020
61                    cpawCTFを解いた</a></li><li class="text-lg my-5 svelte-1ip2ume"><a href="/blog/2020-08-29--initial-article">8/29/2020
62                    initial-article</a></li><!--]--></ul></div><!----><!----></div> <div><footer class="mt-20 bg-stone-300 w-[500px]"></footer></div></div></div><!----><!--]--> <!--[!--><!--]--><!--]-->
63			
64			
64<script>
65				{
66					__sveltekit_1w3mi6q = {
67						base: new URL(".", location).pathname.slice(0, -1)
68					};
69
70					const element = document.currentScript.parentElement;
71
72					const data = [null,{"type":"data","data":{post_entries:[{slug:"2024-11-10--svelte-blog",post:{meta:{title:"ブログシステムを刷新した",date:new Date(1731196800000),tags:["tag1","tag2","tag3"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">ブログシステムを刷新しました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">やだ...この人またブログ作ってる...\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"前回の引越し\" class=\"anchor\" href=\"#前回の引越し\">\n                前回の引越し\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"http://localhost:5542/blog/2020-08-29--initial-article.md\">前回\u003C/a>では、新しく作ったと言ってGatsbyでブログ作った話をちろちろしました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その時は、もともとhatena blogかなんかでブログを書いていたものの、ブログを作ってみたくなって作ったのであった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">全然最近ブログを書いていないために、ブログシステムのGatsbyやその依存関係の更新がめんどくさくなって、環境構築が大変めんどくさくなってしまったことと、markdownからブログ記事を生成する仕組みが面白いので作ってみたかったので、作ってみました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">思ったよりスッキリ作れてよかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">土曜にふと思い立って作り初め、昨日中に大体の実装が終わり日曜にこの記事をかけていて週末で完結してるのはとてもよかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あと、ついでにプロフページがなかったので、それも作った。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"ブログシステム\" class=\"anchor\" href=\"#ブログシステム\">\n                ブログシステム\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">最近 web frontend は Sveltekit を使って書くのが好きなので、今回も svelte kit を使っています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">基本的にマークダウンで書いたブログをhtmlにレンダリングして記事にしています。動的な要素がないので、SSGしています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">markedというjsのライブラリがなかなかにリッチで使い勝手が良く、思ったようなカスタマイズがしやすくてとてもよかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">やっぱり、こういうmarkdownからhtmlを生成したいモチベは多いんだろうなぁ。投稿部分でmarkdownサポートしてるサービス多いしね。zennとかqiitaとかgithubとかesaとか。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">画像の取り扱いはちょっと悩んで、できればmarkdownファイルと話した位置に配置したくないなぁと思ったけどちょっとめんどくさそうだったので、一旦assetsにまとめる形にした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72あとは、記事のURLを何にするかも再考した。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これまで記事のファイル名がurlになっていたけど、ファイル名を変えたときにurlが変わってしまう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">一方で、front matterにいちいち設定するのも面倒な気がしてしまったし、それだとファイル名との違いでまた混同してしまうか...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">などと考えた末、普通にファイル名を使うことにした。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"記事移行\" class=\"anchor\" href=\"#記事移行\">\n                記事移行\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">もともとmarkdownで書いていたので、front matterのフィールドをちょっと調整したり、画像のurlを調整したりするくらいであまり大変にならなかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">またしょうもない記事をかなり消した。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"デザイン\" class=\"anchor\" href=\"#デザイン\">\n                デザイン\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">デザインは一番時間がかかる部分なので、かなり手を抜きました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最小限にデザインにしてます。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"今後\" class=\"anchor\" href=\"#今後\">\n                今後\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">カテゴリとか、年ごとの記事とかRSS配信したいよね。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あとは、前にあったタグの情報を活用して、タグごとのリンクとか、関連記事を貼りたい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">サムネもね、あるといいよね。\u003C/p>\n"}},{slug:"2023-03-11--oji-chan-and-police",post:{meta:{title:"おじいちゃんこの距離歩くのは無理だって",date:new Date(1678492800000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">今日は珍しいことが起きたんだけど,上手く対応できなかったので,次に似たような出来事が起きたときのために反省します.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">お昼の 13 時ごろ.研究室に向かう前に,お弁当屋さんに寄ってお昼ご飯を買いに行こうと自転車を走らせていた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最近はもうすっかり春の陽気に包まれてしまい,シャツ1枚でちょうどいいくらいの気温で,花粉で目がオワっていることを除けば,天気も良く自転車で風を浴びながら走るのが気持ち良かった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">お弁当屋さんは大学の向こうにあるので,ちょうど最終目的地の大学を通り過ぎてちょっと行った先に,シルバーのジャケットを着たおじいちゃんが道の端の枯葉の上に座り込んでいた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最初はホームレスの方かなくらいに思ったが,ここらへんでホームレスなんて見たことがなかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">もう少し注意深く見てみると,座っている状態から起きあがろうと,しかしよろよろとしている.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">過ぎ際にさらによく見てみると,おじいちゃんが杖と紙袋を持っている.やはりどうにか起きあがろうとしていおり,ただ座り込んでいるわけではなさそうだった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72すぐに自転車を回転させて,「大丈夫ですか?」と声を掛ける.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">近くまでいくと,「大丈夫」と返事があった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「立てますか?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「大丈夫」といいつつも,脚に力が入らないのか,懸命に立とうとするが,力が入り切らずに後ろに倒れこんでしまう.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここまでどうやってきたのか不思議なほどに,立ち上がることに苦戦していた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">まずは熱中症を疑い\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「お水飲みますか?」と言ってみるも\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「いっぱい飲んできたから」と.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「飲み物持ってますか?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「カバンにあるよ」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後何度か水を飲むように促すが,「トイレ行きたくなっちゃうから」とか「いっぱい飲まされてきたのよ」と飲まなかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">おじいちゃんは黒い肩掛けのカバンを持っていた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「そのカバン,重そうですね.持ちましょうか?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「大丈夫」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そうはいいつつも,やはり立てない.おじいちゃんはバッグに体を持っていかれていた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">何度も自分がカバンを持つことを提案するも,全て断られた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">10 回ほど同じ問答を繰り返しただろうか.自分も痺れを切らして\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「カバン預かりますね」といいながら肩にかけていたカバンを持ち上げた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">すると,おじいちゃんはスッと自分の肩にかかっていた紐を外して,自分がカバンを預かった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あれだけ断られたから抵抗されるかと思って身構えたが,思わぬ対応に驚いた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なんだ,おじいちゃんも本当は預かって欲しかったのかな.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">バックをおじいちゃんから取り上げても立つことには苦戦していたが,なんとか立ち上がることができた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし,やはり安定しない.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">背中を支えることでようやく歩けるくらいだ.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しばらく歩いたところでまた倒れるように座り込んでしまった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここまで会話をしながら,おじいちゃんが病院から歩いてきたこと,めざしている先が 1km 以上はある遠い場所だということ,普段ここを歩いて通っているわけではないことがわかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">確実にもう徒歩では移動が厳しいが,この場所交通量の多い道路の広い歩道で,歩道には人通りも多くなく,タクシー等の車を呼びつけづらい場所だった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここまで水を飲んだことが確認できていないため,お願いですから飲んでくれませんかといい,おじいちゃんのバックからお茶を取り出して飲んでもらった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし,やはり全然飲んでいない.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕は途方に暮れた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(おじいちゃんは汗結構かいてるし,立てないのは水不足のせいかもしれない)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(受け答えはしっかりしてるから今すぐどうこうという感じではないが,このままでは熱中症になってしまうかもしれない)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(高齢者は自分の体温に気付きづらいというし,喉の渇きに自覚していないのかもしれない)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(ここで強く飲むように促すこともできるだろうが,&quot;はたして本当にそんなことして良いのだろうか&quot;)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">時折おじいちゃんの携帯に電話がかかってくるが,電話に出ようとしても切れてしまい,掛け直しても出なã
72‹ã£ãŸï¼Ž\u003C/p>\n\u003Cp class=\"my-5 leading-6\">徒歩での移動は現実的ではないことは確実であるため,代替手段を考えた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">おじいちゃんはこれまで全ての僕の提案を「大丈夫」といって断っていたことから,おそらく大ごとになることを嫌っているのだろう.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">自分はまだやれるというプライドがあるのかもしれない.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">人の助けを受けることを恥だと思っている可能性も高い.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">タクシーを呼んだ場合はどこから乗れば良いのだろうか.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">止まってくれるだろうか.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">救急車を呼ぶには早いだろうか.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし警察を呼ぶわけにも...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">などと考えながら周囲を見渡していると,近くに古いバス停があることに気がついた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">一応バス停を確認すると,この辺で走っているバス会社ではあるが,標識がかなり古く,ぼろぼろだった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">とりあえず,先を急ごうとするおじいちゃんをそこまで移動してみようと促す.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「あそこにバス停があります.バスで移動しましょう.」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「普段バスで移動していたんですか?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「いや使ったことないよ」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「バス使った方がいいと思うので,バス使ってみましょう」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そういいながら,(自転車があるから一緒にバスには乗れない.どうしよう)と考えながら,ゆっくりと歩くおじいちゃんをバス停の方にナビゲートしていた時\u003C/p>\n\u003Cp class=\"my-5 leading-6\">前から走ってくる女性の方が見えた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72「大丈夫ですかー!?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕は正直かなりホッとした.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これまでおじいちゃんを介抱しながら何度か人と通りすぎたが,声をかけてくれたのは初めてだった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その方が近づいてきて,戸惑いの表情で「大丈夫ですか?」と声をかけながら僕とおじいちゃんを交互に見た.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕が今までの状況を説明すると\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「バスっていっても...くるのかな」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「警察に電話した方が」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「ちょっと確認しますね」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そういいながら女性の方はバス停の方に行き,バス停を確認した後,電話をかけていた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">警察に連絡していたらしく,その後戻ってくると\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「警察の方に連絡しました」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「バスも全然通らないみたいです」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">とスマホの画面を見せながら僕に言った.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">とりあえず警察に通報した以上,警察を待つことにした.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここまで,僕はおじいちゃんがもっと警察への通報だったり他の人の協力を拒むものだと身構えていたが,そういった素振りはなかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">警察に連絡するといったら,間違いなく「嫌」とか「大丈夫」とか言ったはずだが,それ以上強くは言わなかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">女性の方のテキパキとした動きを見ながら,僕は自分の責任の自覚が不十分だったことに気がついた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">もっと早く,僕が警察に連絡するべきだっただろう.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">救急車でも良い.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕なりに「中途半端に助けることはしてはいけない」と思っていたが,\u003C/p>\n\u003Cp class=\"my-5 leading-6\">まともな解決策を提示できないなら,その中で確実性の高い選択肢をなりふり構わず取らなければ行けなかった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">相手より,自分の手を差し伸べて「この人の安全を確保する」という責任を全うすることを第一に考えなくてはいけないことに気がついた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">仮にその結果,助けられる人に怒られることになろうが,手を差し伸べた責任を全うしたならば,僕に手を差し伸べられるような状況に居たことが悪いと考えられるかもしれない.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この状況でまだ「相手に迷惑にならないか」を考えてしまうのは,反省しなきゃいけない.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後,通りすがりの青年も加わり,一緒に警察を待って,警察が到着した後はそのまま警察の方に引き取ってもらった.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後おじいちゃんの家族の方から感謝の電話が来たが,「何もできなくてすみません」というのを忘れた.\u003C/p>\n\u003Cp class=\"my-5 leading-6\">警察って,結構なんでも動いてくれるんだなぁ.\u003C/p>\n"}},{slug:"2022-11-14--could-not-build-wheels-for----",post:{meta:{title:"Conda下Poetry addでERROR: Could not build wheels for ...",date:new Date(1668384000000),tags:["error","python"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">conda 下で poetry add すると、\u003Ccode>ERROR: Could not build wheels for ...\u003C/code>といって死ぬ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">結局、conda 下で作ってしまった poetry の env を消して、普通の python にした状態で poetry の仮想環境を作って、poetry add する。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"詳細\" class=\"anchor\" href=\"#詳細\">\n                詳細\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">唯一見つけた関連ありそうな情報は下記の issue のみ\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/freqtrade/freqtrade/issues/7193\">https://github.com/freqtrade/freqtrade/issues/7193\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">ここにあるように、conda 環境で死んでいるよう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">conda 環境下で python のビルドをした時に、checking g++ ... no となっていたこともあり、conda 環境下だと g++周りで何か踏んでいるのかもしれない。\u003C/p>\n"}},{slug:"2022-06-11--variable-roller",post:{meta:{title:"ヴァリアブルローラーフォイルでエリアX帯行くまでã
72«è€ƒãˆãŸã“と",date:new Date(1654905600000),tags:["new"],draft:false},content:"\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"序章\" class=\"anchor\" href=\"#序章\">\n                序章\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">カーボンローラーを使って B 帯で戦っていた僕はブチギレていた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「キル取っても取れなくても勝てねえ!」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">一度はカーボンローラーで S に入ったこともあるが、その後一気に転落し、B 帯で燻っていた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">B 帯でも安定して勝てず、次第にこの武器のエリア適正を疑い始めた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「キル取っても勝てないし、この武器エリアに向いてないじゃ...」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「エリアに向いてる武器ってなんだ?塗れる武器?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「試しに\u003Cstrong>ヴァリアブルローラー\u003C/strong>とか使って、ひたすらエリアを塗り続けてみるか」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この考えは非常に浅はかであるが、徹底してエリア塗り続ける行動は B 帯ではかなり刺さった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「一気に A 帯まで来た...。逃げ回ってエリア塗りつけるだけで、キル取れなくても、勝率が全然違う」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「けど徐々に行き詰まりを感じてきてるし、このままじゃもっと上は行けないな...どうしよ」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「エリア塗り続けようって思ったけど、味方が死ぬと相手が詰めてきてどうしてもエリア塗れなくなるんだよな」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「うーん...」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「つまり前線が大事ってことか?前線を上げられれば塗りを維持できるし、下げればエリアを塗れなくなる...」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「なるほど、前線が大事だな。けど前線を上げるにはどうすれば?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「やっぱり対面強くなるしかないのかなぁ」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「まてよ、ヴァリアブルローラーフォイルには\u003Cstrong>マルチミサイル\u003C/strong>があるな。これ、使えるんじゃないか?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「ミサイル打てば捕捉した相手は前線を下げざるを得なくなる。その間にこっちが前線上げれば、無理矢理前線を上げられるんじゃないか!?」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「さっそくやってみよう」\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"勝利条件から降っていく\" class=\"anchor\" href=\"#勝利条件から降っていく\">\n                勝利条件から降っていく\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">つまりこういうことだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">エリアというルールの勝利条件はいかに多くの敵を倒すかではない。「いかに特定のエリアが自チームの色になってる状態を維持できるか」である。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">塗り続けることよりも、「維持する」ことが重要。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">維持するには、相手をエリアに近づけさせてはならない。つまり自チームの前線を上げることが直接的に勝利に貢献するのだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし、敵チームの前線を下げ、自チームの前線をあげるのは容易ではない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのため、「スペシャルウェポン」の有効活用が必須である。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">マルチミサイルは、キル性能は高くないが、相手の前線を下げるという点では非常に効果的なスペシャルだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">もちろん、キルすることも前線を上げることに繋がるが、キルは難しく安定しない。かつ倒したとしても自分が死ぬと上げた前線を維持できない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">前線を維持する行動を取るという前提の上で、キルを狙うのはとてもリスクが大きい行動であるため、キルを狙いに行くべき瞬間というのは少ないはずだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">敵を倒しに行くのではなく、敵を「抑える」イメージで、敵に向かって塗り続ける。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">相手と前線が拮抗してる状態でスペシャルを溜め、スペシャルが溜まったら吐いて前線を上げる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これを繰り返すことで、ついに S+に乗ることができた。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"s+ロードで戦うために\" class=\"anchor\" href=\"#s+ロードで戦うために\">\n                S+ロードで戦うために\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">「めっちゃ勝てるようになった...一気に S+まできたな。こっからどこまで行けるか」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここから先は、これまで考えたことをベースに細かな改善を積み重ねていくことになるが、特に意è­
72˜ã—て効いたと感じたのはこんな感じ。\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">不利対面は絶対避ける。\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">ヴァリアブルの場合、自分の射程以上の射程を持つ武器は大体きつい。\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">スピナー系\u003C/li>\n\u003Cli class=\"list-disc\">チャージャー\u003C/li>\n\u003Cli class=\"list-disc\">お風呂\u003C/li>\n\u003Cli class=\"list-disc\">洗濯機\u003C/li>\n\u003Cli class=\"list-disc\">ラビットブラスター\u003C/li>\n\u003Cli class=\"list-disc\">ロングブラスター\u003C/li>\n\u003Cli class=\"list-disc\">etc...\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">こいつらとの対面は絶対に避ける。何がなんでも避ける。\u003C/li>\n\u003Cli class=\"list-disc\">こいつらとの対面は避けつつ、一心不乱にローラーを振り続ける。\u003C/li>\n\u003Cli class=\"list-disc\">スペシャルを使って相手をどかせ、リーチ差を埋めて刺す。\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">特にスピナー系は多くの武器にとって脅威になりやすいから、意外とこっちの意識の方が重要な気がする\u003C/li>\n\u003Cli class=\"list-disc\">どかした後に行けそうならキルを取りに行くことも多い\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">相手に圧をかける\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">射程で勝ってるなら、塗りを生かしてとにかく振り、注意深く前線あげて圧をかける\u003C/li>\n\u003Cli class=\"list-disc\">前線に立つが、最前線には立たず、先端 2 回で倒す。\u003C/li>\n\u003Cli class=\"list-disc\">あとは詰めてきた敵を潰せば良い。\u003C/li>\n\u003Cli class=\"list-disc\">逆に言えば圧さえかけられればそれでよいので、キルを取りに行かない。リーチと徹底した周辺視野で倒す。引かせるだけでも良い。\u003C/li>\n\u003Cli class=\"list-disc\">塗ればスペシャル出せるし、自陣の動ける範囲(前線)は自チームの勝利に直結するから、とにかく塗る\u003C/li>\n\u003Cli class=\"list-disc\">長射程を生かしてとにかく塗り、自分を倒そうと浮いてきた敵を返り討ちにする。無理そうなら逃げる\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">マップを見る\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">ヴァリアブルローラーの場合、前線の一歩後ろに立つことになるため、裏どりと前線からの抜けに気を配る\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">強い場所を考えて、そこに立つ\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">エリアを塗れて、相手に倒されづらい場所は大体どのステージにも用意されている\u003C/li>\n\u003Cli class=\"list-disc\">そのポジションを立って、エリアに干渉し続け、様子を伺って前線を上げる\u003C/li>\n\u003Cli class=\"list-disc\">そしてこういう強い場所は大抵裏どりルートもセットであるので、裏取りルートを絶対に許さない\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">めちゃくちゃ多く見えるが、細かく説明しているだけで、全体で4つほど。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">自分はこれができるようになるまで意識して、徹底でき始めたころに X に乗った\u003C/p>\n"}},{slug:"2021-09-21--customize-python-http-server",post:{meta:{title:"Python標準のHTTPサーバーをカスタマイズしたい時",date:new Date(1652227200000),tags:["python","http"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">pythonのライブラリのテストを書くときに、簡易的なサーバーを立てたい時があり、http.serverライブラリを漁ったã
72®ã§ãƒ¡ãƒ¢\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"python標準のhttpサーバーをカスタマイズしたい時\" class=\"anchor\" href=\"#python標準のhttpサーバーをカスタマイズしたい時\">\n                Python標準のHTTPサーバーをカスタマイズしたい時\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">pythonの標準ライブラリであるhttpには、簡易HTTPサーバがついている。\n機能は非常にシンプルなもので、GETとHEADリクエストにしか対応しておらず、リクエストされたファイルがサーバ上にあるかを確認し、あれば返すというものです。\n実際の公式ドキュメントのサンプルコード[1]はこんな感じ\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">import http.server\nimport socketserver\n\nPORT = 8000\n\nHandler = http.server.SimpleHTTPRequestHandler\n\nwith socketserver.TCPServer((&quot;&quot;, PORT), Handler) as httpd:\n    print(&quot;serving at port&quot;, PORT)\n    httpd.serve_forever()\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">これだけで簡易サーバが動く。\n(ちなみに、CGIHTTPRequestHandlerを使うのであればPOSTも捌ける)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし、単にサーバ上のファイルを返すだけでなく、レスポンスをカスタマイズしたい!という時どうすれば良いか。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">結論はSimpleHTTPRequestHandlerやその上位クラスを継承してカスタマイズハンドラーを作るわけだが、わかりづらいしカスタマイズして使うことを推奨するような設計になっていないと思う。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">というわけで、今回このAPIクライアントのテストを作るにあたり、ここらへんをいじったので、メモしておく\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"simplehttprequesthandler\" class=\"anchor\" href=\"#simplehttprequesthandler\">\n                SimpleHTTPRequestHandler\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">全体的な処理の流れは\u003C/p>\n\u003Cp class=\"my-5 leading-6\">serve_forever()でlisten\n↓\nリクエストが来る\n↓\nHTTPメソッドに対応したメソッドがよばれる\n↓\nそこのメソッドでレスポンスを返す\u003C/p>\n\u003Cp class=\"my-5 leading-6\">まぁなんの変哲もないという感じだけど、一応。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ではここで具体例を書いてみる。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"リクエストされたパスを上書きしてみる\" class=\"anchor\" href=\"#リクエストされたパスを上書きしてみる\">\n                リクエストされたパスを上書きしてみる\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ここでは、どんなパスでリクエストが飛んできてもルートのレスポンスを返す「RedirectRoootHTTPRequestHandler」を定義してみる。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">class RedirectRoootHTTPRequestHandler(SimpleHTTPRequestHandler):\n    def __init__(self, *args, directory=None, **kwargs):\n        super().__init__(*args, directory=directory, **kwargs)\n\n    def do_GET(self):\n        self.path = &quot;/&quot;\n        f = self.send_head()\n        if f:\n            try:\n                self.copyfile(f, self.wfile)\n            finally:\n                f.close()\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">前に「HTTPメソッドに対応したメソッドがよばれる」と書いたが、GETに対å¿
72œã—たメソッドがまさに「do_GET」だ。\n面白いことに(?)、この対応したメソッドを呼ぶ処理は、二つ上の継承元である「BaseHTTPRequestHandler」で記述されているのだが、\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">mname = &#39;do_&#39; + self.command\nif not hasattr(self, mname):\n    self.send_error(\n        HTTPStatus.NOT_IMPLEMENTED,\n        &quot;Unsupported method (%r)&quot; % self.command)\n    return\nmethod = getattr(self, mname)\nmethod()\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">と、&quot;do_&quot; + HTTPメソッドでメソッドを探して対応するメソッドを呼び出している。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そして肝心のリダイレクトするような処理は\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">self.path = &quot;/&quot;\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">self.pathには元々リクエストされたパスが格納されており、copyfile(f, self.wfile) の中で参照している。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ちなみに、self.wfile はレスポンスを書き込む方のファイルオブジェクトで、f はレスポンスとなるファイルオブジェクト。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">self.send_head() では、レスポンスヘッドを送りつつ、リクエストされたパスのファイルをopen()している。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ちなみに、パスがディレクトリとなっていた場合は、ちゃんとそのディレクトリのファイル一覧が返される。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"pythonでレスポンスボディを生成する\" class=\"anchor\" href=\"#pythonでレスポンスボディを生成する\">\n                pythonでレスポンスボディを生成する\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"simplehttprequesthandlerで利用できるプロパティ\" class=\"anchor\" href=\"#simplehttprequesthandlerで利用できるプロパティ\">\n                SimpleHTTPRequestHandlerで利用できるプロパティ\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">command: リクエストHTTPメソッド\u003C/li>\n\u003Cli class=\"list-disc\">path   : リクエスト対象のパス\u003C/li>\n\u003Cli class=\"list-disc\">version: HTTPバージョン\u003C/li>\n\u003Cli class=\"list-disc\">client_address: そのまま。クライアントアドレス\u003C/li>\n\u003C/ul>\n\n            \u003Cdiv class=\"text-xl my-10\">\n              \u003Ca name=\"追記\" class=\"anchor\" href=\"#追記\">\n                追記\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">結構前(2021-09-21)に書いてた記事が途中で下書きのまま終わっているのを発見しました!\n途中ながらとりあえず公開します!\nあんま需要なさそうだし!\u003C/p>\n\u003Cp class=\"my-5 leading-6\">1: \u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://docs.python.org/ja/3/library/http.server.html\">https://docs.python.org/ja/3/library/http.server.html\u003C/a>\u003C/p>\n"}},{slug:"2022-05-8--blog-search",post:{meta:{title:"卒業研究の成果を自分のブログに組み込んでみた",date:new Date(1651968000000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">一年位前にハマってた曲を聞くと、そのハマってた頃の記憶とか感情を思い出すのってありますよね。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">自分は、曲には特に感情がよく染み付くみたいで、染み込みが強いと匂いを思い出すこともあります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">こんにちは。最近大学を卒業した人です。\n今回は GW で自分の\u003Cstrong>卒業研究\u003C/strong>で行った内容を自分の\u003Cstrong>
72ブログに応用\u003C/strong>してみたので、その紹介をしようと思います。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"実装したもの\" class=\"anchor\" href=\"#実装したもの\">\n                実装したもの\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">今回実装したのはこのブログの\u003Cstrong>検索機能\u003C/strong>です。\n卒業研究では情報検索の研究をしていました。\nブログのサイドメニューにある、検索ボックスから記事の検索ができるようになったのですが、この検索の裏側で自分の研究が使われています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"500px\" src=\"/img/blog_search/blog_search_intro.mov.gif\" alt=\"機能の動作の様子\">\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"どんな研究?\" class=\"anchor\" href=\"#どんな研究?\">\n                どんな研究?\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">卒業研究のテーマは「質問生成と機械読解モデルに基づく情報検索アルゴリズム」です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">一言でいうと、情報検索のアルゴリズムに機械読解という別分野の技術を使った研究です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回扱う情報検索は端的に言って Google 検索のイメージ近いものです。何かしらのキーワード(クエリ)を入力して、それに関連するような文書だったりウェブサイトを返します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">それに対して、機械読解は情報検索とは異なる技術で、「質問と文章」を入力として、質問に対する「答え」を文章中から抜き出します。\n例えば、「人間失格の著者は?」という質問と「太宰治は日本の小説家です。代表作に人間失格や走れメロスがあります」という文章が与えられた時に、質問に対する答えとして、文章から「太宰治」という文字列を抜き出すことが期待されます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ちょっと説明が疲れてしまったので一言で言割れて欲しいんですが、この機械読解の技術をそのまま情報検索に使ってみようというのが自分の研究なので、\nやったこととしては検索 API を実装して、そこで機械読解を使って検索を実現したよってことですね。\u003C/p>\n\u003Ciframe src=\"https://drive.google.com/file/d/1Upoe0BvosutaCMHmaEcrcI5QY18DTBw6/preview\" width=\"600\" height=\"400\" class=\"max-w-[100%]\">\u003C/iframe>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"システム構成(に使った技術たち)\" class=\"anchor\" href=\"#システム構成(に使った技術たち)\">\n                システム構成(に使った技術たち)\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">ブログ\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">Gatsby\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">検索サーバ\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">Elasticsearch\u003C/li>\n\u003Cli class=\"list-disc\">fastapi\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">pytorch\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">nginx\u003C/li>\n\u003Cli class=\"list-disc\">lightsail\u003C/li>\n\u003Cli class=\"list-disc\">Docker\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">今回は諸事情あり、lightsail をプロキシサーバーとして使い、gpu サーバーを別に用意しています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">Elasticsearch を使っていることから一部の人は察しているかもしれませんが、今回は機械読解の出番はリランキングです。\n専門的な話ですが、いわゆる first-stage retireval を Elasticsearch で行い、リランキングを機械読解モデルで行なっています。\n機械読解モデルには、Laboro.AI さんの ddqa データセットで fine-tuning したものを拝借して利用しています(\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/laboroai/Laboro-DistilBERT-Japanese\">link\u003C/a>)。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ブログが静的サイトな点でもやりづらく、しばらく楽しんだら普通のものに戻そうと思います。Gatsby にもちょっと詳しくなりました...\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"検索してみる\" class=\"anchor\" href=\"#検索してみる\">\n                検索してみる\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">試しに「Go ライブラリ」と検索してみます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"500px\" src=\"/img/blog_search/blog_search_go_library.png\" alt=\"検索結果\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「answer: ホットリロード」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72と検索結果に表示されているのが見えるでしょうか。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これが機械読解モデルから得られたクエリに対する記事から得られた「答え」です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここでこのホットリロードという答えは、実はこの記事の中で「ホットリロードを実現してくれるライブラリ」を使っているんですが、そこから抜き出されたモノです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">他にこれはどうでしょう\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"500px\" src=\"/img/blog_search/zassou_otya_kaori.png\" alt=\"雑草茶\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">まさに、雑草のお茶について書いた部分が答えとして取り出されています。\n(雑草からお茶を作った話は\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://www.argonism.info/2021/weeds_tea/2021-05-8--%E3%2581%259D%25E3%2581%25AE%25E8%25BE%25BA%25E3%2581%25AE%25E8%258D%2589%25E3%2581%25A7%25E3%2581%258A%25E8%258C%25B6%25E3%2582%2592%25E4%25BD%259C%25E3%2582%258B/\">こちら\u003C/a>)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">どうでしょう、なんとなく面白くないですか?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">だからなんだと言われればアレですが、機械学習っぽさを感じます(小並感)。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"感想\" class=\"anchor\" href=\"#感想\">\n                感想\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ここの記事には書いていないですが、ここの実装自体はそこまで重くなかったのですが、それ以外のサーバーの用意でめちゃくちゃ詰まっていてもうダメかと思いました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cstrong>GW 期間中に終わってよかったぜ!!!\u003C/strong>\n(なお記事を書いたのは夏休み)\u003C/p>\n"}},{slug:"2022-03-31--half-dot",post:{meta:{title:"半ドットはなぜ邪悪なのか",date:new Date(1648684800000),tags:["new","pixelart","ドット絵"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://dotown.maeda-design-room.net/\">ドットタウン\u003C/a>というサイトをご存知だろうか。\nドットタウンサイトの説明を引用する\u003C/p>\n\u003Cblockquote>\n\u003Cp class=\"my-5 leading-6\">DOTOWNは粗ドットをダウンロードできるサイトです。\n粗ドットとは、可能な限り低い解像度を用い究極に抽象的な表現をしたドット絵を指します。\n抽象化をしているにも関わらず情報が詰まっており、ゲームグラフィックにおける「逆進化(=究極の抽象化)」を遂げている粗ドットは、ちょっとヌケた雰囲気で「前田デザインっぽさ」を象徴してきたものであり、現在でも前田デザイン室のWEBサイトや入会ページ(Campfire コミュニティ)など至る所に粗ドットが登場します。\u003C/p>\n\u003C/blockquote>\n\u003Cp class=\"my-5 leading-6\">そう、「粗ドット」を売りにするドット絵素材配布サイトである。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし、このサイトが登場した当時、サイト内のドット絵に「半ドット」が使われるということで、ドット絵コミュニティで軽く\u003Cdel>燃えた\u003C/del>話題になった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回は、ドット絵専門家でもなければドット絵が上手いわけでもないただのドット絵好きが、なぜ\u003Cdel>燃え\u003C/del>話題になってしまったのかを、自分の視点で書いてみようと思う。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"半ドットとは\" class=\"anchor\" href=\"#半ドットとは\">\n                半ドットとは\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">
72ここでは、「絵を構成しているブロックの大きさの半分以下のサイズのブロック」を半ドットと呼びます。\nつまり、「1px」より小さいドットのことを、半ドットと呼ぶことにします。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">具体的には、このドット絵中央にある、白の周りより半分ほど小さいドットのことです\n\u003Cimg width=\"500px\" src=\"/img/media/half-dot/mademoiselle_notation.png\" alt=\"\">\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"なぜ半ドットは邪悪なのか\" class=\"anchor\" href=\"#なぜ半ドットは邪悪なのか\">\n                なぜ半ドットは邪悪なのか\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"そもそもドット絵の魅力とは\" class=\"anchor\" href=\"#そもそもドット絵の魅力とは\">\n                そもそもドット絵の魅力とは\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ドット絵にさほど興味のない人からすると、「こんなの誰が気にするんだよ」と思われるかもしれない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし、ドット絵表現をやってる人からすると、これは一大事なんです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そもそも、何がドット絵をドット絵たらしめるのでしょうか?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">それは、主に解像度だと思います。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">非常に小さい解像度のキャンパスの中で、絵を書く。これがドット絵だと言えるでしょう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">解像度があまりにも小さいので、表現できることも限られてきます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">小さいドット絵ほど、表現できることが減るため、難易度は上がってきます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その制限の中で、いかにして表現を作るかが、ドット絵の醍醐味でしょう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのため、「粗どっと」なんていう極小レベルのドット絵は、狙ったものを書くのはかなり難しいわけです。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"半ドットは半ドットではない\" class=\"anchor\" href=\"#半ドットは半ドットではない\">\n                半ドットは半ドットではない\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">半ドットの説明をしましたが、実際にはドット絵において「半ドット」なんてものは存在しないと思っています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回定義したような半ドットは、それは半ドットではなく、周りのピクセルが2倍になっているのです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最初に取り上げたドット絵の例を見てみましょう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"500px\" src=\"/img/media/half-dot/mademoiselle.png\" alt=\"\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">半ドットの例として、真ん中の白の小さいドットが半ドットであると言いましたが、実際には\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cstrong>このピクセル以外が2pixelの大きさ\u003C/strong>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なんです。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"半ドットを使った瞬間に、解像度は倍になる\" class=\"anchor\" href=\"#半ドットを使った瞬間に、解像度は倍になる\">\n                半ドットを使った瞬間に、解像度は倍になる\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">つまり、半ドットというのは半ドットではなく、それこそが1pixelとなってしまうため、\n半ドットを使った瞬間に、そのドット絵は解像度が2倍になっています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">半ドットが使われているドット絵を縮小することを考えてみましょう。\n例えば、先ほど取り上げたドット絵の解像度は一見「8 x 9」のように見えますが、半ドットがあるため、å
72®Ÿéš›ã«ã¯ã€Œ16 x 18」だと思われます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">実際に16x18にしてみました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(あまりにも小さいので、cssで拡大しています。本来の大きさで確かめたい場合は画像をクリックしてみてください)\u003C/p>\n\u003Cstyle>\n#downscale span {\n    width: 64px;\n    height: 72px;\n    image-rendering: pixelated;\n}\n\u003C/style>\n\n\u003Cdiv id=\"downscale\" style=\"display: flex; flex-direction: row; justify-content: center;\">\n    \u003Cdiv id=\"downscale\" style=\"margin-bottom: 1rem; image-rendering: pixelated;\">\n        \u003Ca href=\"/img/media/half-dot/mademoiselle_16x18.png\">\n            \u003Cimg width=\"128px\" src=\"/img/media/half-dot/mademoiselle_16x18.png\">\u003C/img>\n        \u003C/a>\n    \u003C/div>\n\u003C/div>\n\n\u003Cp class=\"my-5 leading-6\">画像の本体の大きさ以外は変わらないですね。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">では、このドット絵の解像度を\u003Cstrong>さらに半分に\u003C/strong>落とした場合、どうなるでしょうか?\u003C/p>\n\u003Cdiv id=\"downscale\" style=\"display: flex; flex-direction: row; justify-content: center;\">\n    \u003Cdiv id=\"downscale\" style=\"margin-bottom: 1rem; image-rendering: pixelated;\">\n        \u003Ca href=\"/img/media/half-dot/mademoiselle_8x9.png\">\n            \u003Cimg width=\"128px\" src=\"/img/media/half-dot/mademoiselle_8x9.png\">\u003C/img>\n        \u003C/a>\n    \u003C/div>\n\u003C/div>\n\n\u003Cp class=\"my-5 leading-6\">はい、半ドットがあった箇所が変わってしまいました。つまり、「16x18」がやはり本当の解像度だったわけです。(自明ですが)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そして、半ドットがない箇所については変わっていない点も、「一見8x9の解像度に見える」を裏付けています。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"なぜ話題になったのか\" class=\"anchor\" href=\"#なぜ話題になったのか\">\n                なぜ話題になったのか\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">2倍の解像度を得ているため、公式の説明と照らし合わせると、これはもはや「粗ドット」のような解像度ではなく、「まあまあ粗いドット絵」の方になるでしょう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">公式サイトの説明にも\u003C/p>\n\u003Cblockquote>\n\u003Cp class=\"my-5 leading-6\">粗ドットとは、可能な限り低い解像度を用い究極に抽象的な表現をしたドット絵を指します。\n抽象化をしているにも関わらず情報が詰まっており、...\u003C/p>\n\u003C/blockquote>\n\u003Cp class=\"my-5 leading-6\">とあるように、厳しい解像度の制約の中で、ドット絵は抽象化をどのようにするかが、腕の見せどろでありドット絵の見どころなんです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ですから、解像度が倍増してドット絵の表現できるポテンシャルも大幅に増えているのにもかかわらず、「半ドット」の箇所以外はは解像度が低いままなので、もはやそれはクオリティが高いドット絵とは言えなくなってしまいます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">つまり、部分的に解像度を上げるなんてことは、ドット絵において一大事なわけです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「粗ドット」という最小レベルのサイズを売りにするのであれば、この制約に対して真正面から取り組むことが期待されていたのに、半ドットを使って実質的な解像度を倍にしてしまっており、多数のドッターの反感を買ったのだと思います。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あまり責め立てるようなことは言いたくないですが、1/4の半ドットを使っているものもあり、私もこのサイトのドット絵の説明と実際のドット絵が一致していないように見えてしまいます。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"最後に\" class=\"anchor\" href=\"#最後に\">\n                最後に\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">
72以上、なぜ半ドットが邪悪なのか、私の見解が伝わったでしょうか。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">再三、これはドット絵師やドット絵界隈の総意ではなく、私個人の意見であることを伝えておきたいと思います。\u003C/p>\n"}},{slug:"2022-03-12--python-confluence",post:{meta:{title:"Pythonで触るConfluence API",date:new Date(1647043200000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">今回 Confluence API を触ることがあったけど、日本語のドキュメントがなかったのと、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">トークンの取得-&gt;API 叩くまでのフローが体型的にまとまってない &amp; 公式ドキュメントがわかりづらかったので、今回自己流にまとめる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">またドキュメントに載っていない情報もあるので、それもまとめる\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ただ、自分は Confluence 自体を触ることがほとんどないので、あんまりニーズとマッチしないかも\u003C/p>\n\u003Cp class=\"my-5 leading-6\">基本的な oauth フローや oauth で取得したトークンを利用した API リクエストの方法については説明しません。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">具体的には、以下の内容を扱います。\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97\">トークンの取得\u003C/a>\u003C/li>\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#Oauth%E3%81%A7%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E5%8F%96%E5%BE%97\">Oauth でトークンの取得\u003C/a>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#%E6%9C%9F%E9%99%90%E5%88%87%E3%82%8C%E3%81%AB%E9%9A%9B%E3%81%97%E3%81%A6%E3%81%AE%E3%83%88%E3%83%BC%E3%82%AF%E3%83%B3%E3%81%AE%E6%9B%B4%E6%96%B0\">期限切れに際してのトークンの更新\u003C/a>\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#cloud_id\">cloud id について\u003C/a>\u003C/li>\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#%E8%A8%98%E4%BA%8B%E3%81%AE%E5%8F%96%E5%BE%97\">記事の取得\u003C/a>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#%E8%A8%98%E4%BA%8B%E3%81%AE%E6%9C%AC%E6%96%87%E3%81%AE%E5%8F%96%E5%BE%97\">記事の本文の取得\u003C/a>\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#%E3%83%9A%E3%83%BC%E3%82%B8%E3%83%8D%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3\">
72ページネーション\u003C/a>\u003C/li>\n\u003Cli class=\"list-disc\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"#confluence_api_client\">簡易 confluence api クライアント\u003C/a>\u003C/li>\n\u003C/ul>\n\u003Cdiv id=\"トークンの取得\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"トークンの取得\" class=\"anchor\" href=\"#トークンの取得\">\n                トークンの取得\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Col class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">Confluence の設定画面に行く\n\u003Cimg width=\"500px\" src=\"/img/confluence/settings.png\" alt=\"\">\u003C/li>\n\u003Cli class=\"list-disc\">パスワード\n\u003Cimg width=\"500px\" src=\"/img/confluence/password.png\" alt=\"\">\u003C/li>\n\u003Cli class=\"list-disc\">セキュリティ)API トークン\n\u003Cimg width=\"500px\" src=\"/img/confluence/api-token.png\" alt=\"\">\u003C/li>\n\u003Cli class=\"list-disc\">API トークンの作成するボタンからトークンを作成できる\u003C/li>\n\u003C/ol>\n\u003Cdiv id=\"Oauthでトークンの取得\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"oauth-でトークンの取得\" class=\"anchor\" href=\"#oauth-でトークンの取得\">\n                Oauth でトークンの取得\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Col class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">ディベロッパーコンソールにアクセスします。\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/console\">https://developer.atlassian.com/console\u003C/a>\u003C/li>\n\u003Cli class=\"list-disc\">Create ボタン &gt; OAuth 2.0 integration から Confluence アプリを作成できます\u003C/li>\n\u003Cli class=\"list-disc\">次にスコープを設定します。アプリの管理画面 &gt; Permisisons &gt; Confluence API Add/Configure &gt; Edit scope から編集します。\u003C/li>\n\u003Cli class=\"list-disc\">スコープの詳細はここから確認できます。必要なスコープを設定してください。\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/cloud/confluence/scopes-for-oauth-2-3LO-and-forge-apps/\">https://developer.atlassian.com/cloud/confluence/scopes-for-oauth-2-3LO-and-forge-apps/\u003C/a>\u003C/li>\n\u003Cli class=\"list-disc\">Oauth トークンの取得は、Jira での公式の例を流用して行えます。\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/atlassian-api/atlassian-python-api/blob/master/examples/jira/jira_oauth2.py\">https://github.com/atlassian-api/atlassian-python-api/blob/master/examples/jira/jira_oauth2.py\u003C/a>\u003C/li>\n\u003C/ol>\n\u003Cpre>\u003Ccode class=\"language-python\">from requests_oauthlib import OAuth2Session\nfrom atlassian import Confluence\nfrom flask import Flask, request, redirect, session\nimport requests\n\napp = Flask(__name__)\napp.secret_key = &quot;&quot;\n\n# JIRA OAuth URLs\nauthorization_base_url = &quot;https://auth.atlassian.com/authorize&quot;\ntoken_url = &quot;https://auth.atlassian.com/oauth/token&quot;\n\n\nclient_id = &quot;{client_id}&quot;\nclient_secret = &quot;{client_secret}&quot;\nredirect_uri = &quot;{callback}&quot;\n\[email protected](&quot;/login&quot;)\ndef login():\n    scope = [&quot;read:page:confluence&quot;,&quot;read:attachment:confluence&quot;,&quot;read:blogpost:confluence&quot;,\n    &quot;read:custom-content:confluence&quot;,&quot;read:comment:confluence&quot;,&quot;read:group:confluence&quot;,\n    &quot;read:configuration:confluence&quot;,&quot;read:space:confluence&quot;,&quot;read:space.permission:confluence&quot;,\n    &quot;read:space.property:confluence&quot;,&quot;read:space.setting:confluence&quot;,&quot;read:content.permission:confluence&quot;,\n    &quot;read:content.property:confluence&quot;,&quot;read:content.restriction:confluence&quot;,&quot;read:content.metadata:confluence&quot;,\n     &quot;read:content-details:confluence&quot;, &quot;read:space-details:confluence&quot;,\n     &quot;read:user:confluence&quot;, &quot;read:space:confluence&quot;, &quot;offline_access&quot;]\n    audience = &quot;api.atlassian.com&quot;\n\n    oauth = OAuth2Session(client_id, scope=scope, redirect_uri=redirect_uri)\n    authorization_url, state = oauth.authorization_url(\n        authorization_base_url,\n        audience=audience,\n    )\n    session[&quot;oauth_state&quot;] = state\n    return redirect(authorization_url)\n\[email protected](&quot;/callback&quot;)\ndef callback():\n    jira_oauth = OAuth2Session(client_id, state=session[&quot;oauth_state&quot;], redirect_uri=redirect_uri)\n    token_json = jira_oauth.fetch_token(token_url, client_secret=client_secret, authorization_response=request.url)\n    with open(&quot;token.json&quot;, &quot;w&quot;) as f:\n        f.write(str(token_json).replace(&quot;&#39;&quot;, &#39;&quot;&#39;))\n\n    # return &quot;Token: {}&lt;p /&gt;Projects: {}&quot;.format(token_json, &quot;, &quot;.join(get_projects(token_json)))\n    return &quot;Token: {}&lt;p /&gt;&quot;.format(token_json)\n\ndef get_projects(token_json):\n    req = requests.get(\n        &quot;https://api.atlassian.com/oauth/token/accessible-resources&quot;,\n        headers={\n            &quot;Authorization&quot;: &quot;Bearer {}&quot;.format(token_json[&quot;access_token&quot;]),\n            &quot;Accept&quot;: &quot;application/json&quot;,\n        },\n    )\n    req.raise_for_status()\n    resources = req.json()\n    cloud_id = resources[0][&quot;id&quot;]\n\n    oauth2_dict = {\n        &quot;client_id&quot;: client_id,\n        &quot;token&quot;: {\n            &quot;access_token&quot;: token_json[&quot;access_token&quot;],\n            &quot;token_type&quot;: &quot;Bearer&quot;,\n        },\n    }\n    jira = Jira(url=&quot;https://api.atlassian.com/ex/jira/{}&quot;.format(cloud_id), oauth2=oauth2_dict)\n    return [project[&quot;name&quot;] for project in jira.projects()]\n\napp.secret_key = &quot;{secret_key}&quot;\napp.run(host=&quot;localhost&quot;, port=8080, ssl_context=(&#39;crt_path&#39;, &#39;key_path&#39;), threaded=True, debug=True)\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">以降の api へのリクエストはここで取得した token を使って行います。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ここで注意して欲しいのは、\u003Cstrong>取得したトークンの有効期限は 1 時間\u003C/strong>です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">1時間後に有効期限が切れてしまいます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">1時間後にはトークンの再取得か、\n期限が切れたトークンの refresh が必要です。\u003C/p>\n\u003Cdiv id=\"期限切れに際してのトークンの更新\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"期限切れに際してのトークンの更新\" class=\"anchor\" href=\"#期限切れに際してのトークンの更新\">\n                期限切れに際してのトークンの更新\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">公式ドキュメント・詳細はこちらにあります。\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#faq1\">https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#faq1\u003C/
72a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">トークンの更新のために、offline_access を追加します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これは、アプリ管理画面のスコープ管理にはないので、Oauth 認証フローの scope に追加します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これを追加することで、トークンと同時に\u003Ccode>refresh token\u003C/code>が取得できます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この\u003Ccode>refresh token\u003C/code>を使って、新たに認証し直さなくても新しくトークンを取得できます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">具体的には、以下のエンドポイントを叩くと、新しいトークンと、新しい refresh token、有効時間等の情報が返ってきます。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-shell\">curl --request POST \\\n  --url &#39;https://auth.atlassian.com/oauth/token&#39; \\\n  --header &#39;Content-Type: application/json&#39; \\\n  --data &#39;{ &quot;grant_type&quot;: &quot;refresh_token&quot;, &quot;client_id&quot;: &quot;YOUR_CLIENT_ID&quot;, &quot;client_secret&quot;: &quot;YOUR_CLIENT_SECRET&quot;, &quot;refresh_token&quot;: &quot;YOUR_REFRESH_TOKEN&quot; }&#39;\n\u003C/code>\u003C/pre>\n\u003Cdiv id=\"cloud_id\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"cloud-id-について\" class=\"anchor\" href=\"#cloud-id-について\">\n                cloud id について\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">あと一歩で実際に API 叩いて記事を取得できます!\u003C/p>\n\u003Cp class=\"my-5 leading-6\">公式ドキュメントはこちらです。\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#3--make-calls-to-the-api-using-the-access-token\">https://developer.atlassian.com/cloud/confluence/oauth-2-3lo-apps/#3--make-calls-to-the-api-using-the-access-token\u003C/
72a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最後にステップは cloud id の取得です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">こんな感じで cloud id を取得できます。\u003C/p>\n\u003Cpre>\u003Ccode>curl --request GET \\\n  --url https://api.atlassian.com/oauth/token/accessible-resources \\\n  --header &#39;Authorization: Bearer ACCESS_TOKEN&#39; \\\n  --header &#39;Accept: application/json&#39;\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">この cloud id を使って、api 叩くための url を作ります。\u003C/p>\n\u003Cdiv id=\"記事の取得\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"記事の取得\" class=\"anchor\" href=\"#記事の取得\">\n                記事の取得\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">では実際に記事を取得してみます。\n公式ドキュメント: \u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/cloud/confluence/rest/api-group-content/#api-wiki-rest-api-content-get\">https://developer.atlassian.com/cloud/confluence/rest/api-group-content/#api-wiki-rest-api-content-get\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">公式の exapmle をちょっと変えています。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\"># This code sample uses the &#39;requests&#39; library:\n# http://docs.python-requests.org\nimport requests\nimport json\n\ncloud_id = &quot;取得したcloud_id&quot;\n\n# url = &quot;https://your-domain.atlassian.net/wiki/rest/api/content&quot;\nurl = &quot;https://api.atlassian.com/ex/confluence/{cloud_id}/rest/api/content&quot;\n\nheaders = {\n   &quot;Accept&quot;: &quot;application/json&quot;,\n   &quot;Authorization&quot;: &quot;Bearer &lt;access_token&gt;&quot;\n}\n\nresponse = requests.request(\n   &quot;GET&quot;,\n   url,\n   headers=headers\n)\n\nprint(json.dumps(json.loads(response.text), sort_keys=True, indent=4, separators=(&quot;,&quot;, &quot;: &quot;)))\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">公式ドキュメントだと url が&quot;\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://your-domain.atlassian.net/wiki/rest/api/content%22%E3%81%A8%E3%81%AA%E3%81%A3%E3%81%A6%E3%81%84%E3%81%BE%E3%81%99%E3%81%8C%E3%80%81\">https://your-domain.atlassian.net/wiki/rest/api/content&quot;となっていますが、\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">your-domain を置き換えても&quot;Unauthorized&quot;になって終わります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">実際には cloud id を使って、上記のように url を作り、api 叩きます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">url 以外はドキュメントと同じです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この例で、page が取得できます(blogpost は別)\u003C/p>\n\u003Cdiv id=\"記事の本文の取得\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"記事の本文の取得\" class=\"anchor\" href=\"#記事の本文の取得\">\n                記事の本文の取得\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">上記の API を叩いた方、気づいたと思いますが、記事の本文やコメント等の情報が取得できていません。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これは、別に指定する必要があります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">指定は expand パラメータを指定することで行います。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">例えば、記事の本文を取得する際、次のような url が必要になります\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">url = &quot;https://api.atlassian.com/ex/confluence/{cloud_id}/rest/api/content?expand=body.storage,body.view&quot;\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">
72このように、expand は複数指定でき、\u003Cstrong>カンマでくぎります\u003C/strong>。(公式ドキュメント: \u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://developer.atlassian.com/server/confluence/expansions-in-the-rest-api/%EF%BC%89\">https://developer.atlassian.com/server/confluence/expansions-in-the-rest-api/)\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">本文は複数のフォーマットがあって、細かいことは調べていないんですが、storage の方がサイズが小さく、view は html タグとかそのままの状態という雰囲気でした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">同様に、コメントも同時に取得したい時は次のようになります。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">url = &quot;https://api.atlassian.com/ex/confluence/{cloud_id}/rest/api/content?expand=body.storage,body.view,comment.body.storage&quot;\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">公式ドキュメントには書かれていない?っぽいですが、コメントも body 以下と同じような expand があるようで、コメント本文の取得には comment.body.storage(comment.body.view)が必要になります。\u003C/p>\n\u003Cdiv id=\"ページネーション\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"ページネーション\" class=\"anchor\" href=\"#ページネーション\">\n                ページネーション\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ページネーションは、クエリパラメータの start で管理されているようです。\nまた、直接次にアクセスすべきリンクも送ってくれています。\nリクエストに成功した時、まだページがある場合、次の位置にあるリンクを叩くと、続きを貰えます。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-json\">{\n    &quot;_links&quot;: {\n        &quot;next&quot;: &quot;リンク&quot;\n    }\n}\n\u003C/code>\u003C/pre>\n\u003Cdiv id=\"confluence_api_client\">\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"簡易-python-confluence-api-クライアント\" class=\"anchor\" href=\"#簡易-python-confluence-api-クライアント\">\n                簡易 Python confluence api クライアント\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">簡易な python confluence api クライアント書いたので載せときます。ご参考になれば。\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://gist.github.com/argonism/2a32691c1356526e6b892815c35f54da#file-confluence_api_client-py\">https://gist.github.com/argonism/2a32691c1356526e6b892815c35f54da#file-confluence_api_client-py\u003C/a>\u003C/p>\n\u003Ciframe\n    width=\"100%\"\n    height=\"350\"\n    src=\"data:text/html;charset=utf-8,\n    \u003Chead>\u003Cbase target='_blank' />\u003C/head>\n    \u003Cbody>\u003Cscript src='https://gist.github.com/argonism/2a32691c1356526e6b892815c35f54da.js'>\u003C/script>\n    \u003C/body>\">\n\u003C/iframe>\n"}},{slug:"2022-03-6--learn-ml-model-in-online",post:{meta:{title:"運用中の機械学習アプリでデータを収集してモデルを再学習したい",date:new Date(1646524800000),tags:["pytorch","ml"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">もう鍋も食べ飽きて、また以前のように作り慣れたレシピを再現する日々を続けています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">本当に1ヶ月以上鍋を食べ続けてきたので、食べ慣れたものでもかなり新鮮に感じます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今は学部の集大成も終わり、もう春休みです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">以前からやりたいと思っていたことを、急いで終わらせたいですね。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"以前作った機械学習アプリ「mapchip-generator」\" class=\"anchor\" href=\"#以前作った機械学習アプリ「mapchip-generator」\">\n                以前作った機械学習アプリ「Mapchip Generator」\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">以前、\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://www.argonism.info/2022/2022-01-22--%E3%2583%259E%25E3%2583%2583%25E3%2583%2597%25E3%2583%2581%25E3%2583%2583%25E3%2583%2597%25E3%2582%2592%25E8%2587%25AA%25E5%258B%2595%25E7%2594%259F%25E6%2588%2590%25E3%2581%2599%25E3%2582%258BWeb%25E3%2582%25A2%25E3%2583%2597%25E3%2583%25AA%25E3%2582%2592%25E4%25BD%259C%25E3%2581%25A3%25E3%2581%259F/\">マップチップという画像を自動生成する Web アプリ「Mapchip Generator」を作ったよ\u003C/a>という記事を書きました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これは今も稼働していて、GCP 様のおかげて無料で運用できています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">このアプリを研究室内で紹介したとき、**「利用されたデータを使って、学習データを作れるのではないか」**というアドバイスをいただき、やってみることに。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"運用中のデータから学習データを集める\" class=\"anchor\" href=\"#運用中のデータから学習データを集める\">\n                運用中のデータから学習データを集める\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">今回、このアプリの利用データから、学習に使えそうなデータを集めるために、\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">マップチップの生成は一度に 3 つ提示する\u003C/li>\n\u003Cli class=\"list-disc\">生成したマップチップは、選択することでダウンロードできる\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">という修正をしました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これにより、ダウンロードされたマップチップが取得できるようになります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">つまり、\u003C/p>\n\u003Cpre>\u003Ccode>ダウンロードされたマップチップは、ユーザが気に入ったマップチップであると判断して、\nそのようなマップチップはきっとクオリティの高いマップチップだろうから、それを利用してモデルを学習させる\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">という具合です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">このように、\u003Cstrong>ダウンロードされたマップチップは、良いマップチップであり、されなかったものは悪いマップチップである\u003C/strong>という仮定の元で、\nこれらのデータをディスクリミネータの学習データとしてみます!\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"ディスクリミネータを学習させる\" class=\"anchor\" href=\"#ディスクリミネータを学習させる\">\n                ディスクリミネータを学習させる\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">GAN の構造については詳細な説明をしませんが、簡単にいうと、\nマップチップを作るやつとマップチップを判別するやつを用意して、マップチップを判別するやつは、マップチップがマップチップを作るやつに作られたものかどうかを判別します。\nマップチップを作るやつは、マップチップを判別するやつに、自分が作ったとバレないようにマップチップを作るように学習します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">マップチップを判別するやつをディスクリミネータというのですが、このディスクリミネータが賢ければ、\nマップチップを生成するやつ(ジェネレータ)はより自然な(与えられるデータに近いような)マップチップを生成するよう学習できるようになります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">元々ディスクリミネータは、「データセット中のマップチップかどうか」を判別します。\nつまり、ジェネレータはデータセット中のマップチップっぽいマップチップを生成するように学習していくわけです。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"収集したデータでディスクリミネータを学習する\" class=\"anchor\" href=\"#収集したデータでディスクリミネータを学習する\">\n                収集したデータでディスクリミネータを学習する\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">データセット中のマップチップは当然「良いマップチップ」であるため、私はディスクリミネータは良いマップチップかどうか」を判別していると言い換えて、今回収集したデータを使って学習させます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72つまり、良いマップチップとして収集したものは、データセット中に含まれるマップチップとして、ディスクリミネータを学習します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">学習手順としては、\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">最初に、ディスクリミネータにこの良いマップチップを入力し、データセット中のマップチップか、ジェネレータにより生成されたものかを判別させ、\u003C/li>\n\u003Cli class=\"list-disc\">次にジェネレータにより生成したもの入力し判別させ、学習させます。\u003C/li>\n\u003Cli class=\"list-disc\">次に、ディスクリミネータの判別を元に、ジェネレータを学習させます。\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">といった具合です。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"実装\" class=\"anchor\" href=\"#実装\">\n                実装\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ダウンロードされたマップチップとモデルは GCS をアップロードし、管理します。\nアップロードされたマップチップをダウンロードし、モデルを学習させ、学習させたモデルをアップロードし、サーバ側でモデルをダウンロードさせます。\nここまではスクリプトを後は cron 等を設定して定期実行させるだけなんですが、学習は重い作業なのでとりあえずローカルで行います。\nそのうち置物のデスクトップで cron を設定するか、モデルがかなり小さいので可能なら使ってないラスパイでやってみようかなと思ってます。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"感想\" class=\"anchor\" href=\"#感想\">\n                感想\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">作成に際して苦戦した箇所は色々あるけど、思い出せるところとして、\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">マップチップのクオリティが低い\u003C/li>\n\u003Cli class=\"list-disc\">モーフィングの生成がうまくいかない\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">クオリティが低い\u003C/li>\n\u003Cli class=\"list-disc\">モーフィングが指定した画像から始まってない\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">GitHub Actions\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">ssh\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">作り始めた当初、マップチップのクオリティが著しく低くなる現象があって原因がわからなかった。\n具体的には、かなーり似たような画像が生成されるという具合。\n最初はマップチップのクオリティが下がっていることにすら気づけず、「まあこんなもんか?」くらいにしか思ってなかった。\n原因は batch size にあった。batch size を 1 にして生成していたが、これがよくなかったらしく、学習時に揃えたらうまく行った。\nbatch size を推論時に変えると生成結果のクオリティに大きく影響するといった話は聞いたことがないし、そんなこと想像しなかった(常識だけど自分が知らないだけ?)ため、解決に時間がかかった。\n調べても具体的な情報は出て来ず、これは今回固有の問題なんだろうか?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">モーフィングの生成は、batch size 1 だったらかなり実装しやすい機能だった。\nしかし、上述したように、batch size 1  だとクオリティがかなーり落ちることが判明したため、batch size を大ã
72ãã™ã‚‹å¿…要が出た。\nそうすると、モーフィングの生成が難しくなる。\nこのことから、一時はモーフィング gif 生成機能を消そうかとも思った。\nしかし、実行時間とメモリを犠牲に、ギリ GCE 上で動かせる範囲に収まりそうだったため、batch size を維持したままモーフィング gif を生成することにした。\nこのときの実装でも色々ごたついた。異なる2つの batch の中のそれぞれ一つずつのマップチップについて、モーフィングを生成するため、気をつけなければいけない点が多く、煩わしかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ついこの間、初めて GitHub Actions による CI を導入した。\nssh で GCE にデプロイするのだが、ssh は interactive に実行しない時に alias を展開しないということを知るのに時間がかかった。\nつまり、GCE では docker-compose を docker run  から起動するため、alias として docker-compose を登録しているのだが、これが使えないということに気づけなかった。\n場合によっては shopt でオプションを指定することで、alias を展開するよう指定できるみたいだが、うまくいかなかったため普通に alias の元をベタ書きした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">個人的にはお気に入りのサイトができてよかったです。\n技術的にも触ったことないものにさわれたし、念願の CI に入門できてよかったです。\u003C/p>\n"}},{slug:"2022-02-1--wordle-solver",post:{meta:{title:"Wordleのソルバーを書いた",date:new Date(1643673600000),tags:["wordle","python","informatics"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">wordleのソルバを書こうかなあと思っていた時、Twitterでちょうど\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「初手で情報量が一番大きい単語」\u003C/p>\n\u003Cp class=\"my-5 leading-6\">を調べている人のツイートが回ってきた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">情報量を考えるのか。なるほどな。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">...しかし、Wordleでの単語の情報量ってどうやって計算するんだ?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">と思って、同じようにWordleでの情報量を考えてた人がいるんじゃないかと思って、調べてみるといた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://xcloche.hateblo.jp/entry/2022/01/24/212558\">https://xcloche.hateblo.jp/entry/2022/01/24/212558\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">xclocheさんという方が丁寧に解説してくれている。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この方は、wordleでの単語wの情報量-log(p(w))を、p(w)を\u003C/p>\n\u003Cp class=\"my-5 leading-6\">$$p(w) = \\frac{(wを入力した時に得られるヒントを満たすような単語数)}{(総単語数)}$$\u003C/p>\n\u003Cp class=\"my-5 leading-6\">として計算していた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なるほど、つまり\u003Ccode>価値が高い単語 = 入力して平均的に価値の高いヒントを得られる\u003C/code>、\u003Ccode>価値の高いヒント = より小さく単語を絞り込めるヒント\u003C/code>と考えてp(w)を定義すれば、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">価値が高くなるほどp(w)が低くなり、情報量として扱えるようになるのか。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">さらにありうる答え全てについて情報量を計算して、平均情報量を求めれば、その時点で最適な手の判断がつくと。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">とても面白いので、初手だけではなくソルバを書いてみた。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"ソルバ\" class=\"anchor\" href=\"#ソルバ\">\n                ソルバ\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ソルバとしてやったことは、上記の単語ごとの平均情報量の計算を毎回行う。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ただし、初手以外は、それまで得られたヒントを活用して、辞書を絞った状態で行う。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのため、「全単語を考慮して効率よくヒントを集める」ということができない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">全単語を考慮すると計算量がかなーり多くなってしまう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">単語ごとの処理は独立だから処理を分散させることもできるが、もっと賢い方法で解決できる気もして...\u003C/p>\n"}},{slug:"2022-01-22--mapchip-gen",post:{meta:{title:"マップチップを自動生成するWebアプリを作った",date:new Date(1643414400000),tags:["nextjs","web","application","GCE","vercel","fastapi","ml"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">最近は鍋ばかり食べていて、鍋の味がもはやわからなくなってきました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">冬は餅を食べれるだけ食べた方が良いという強迫観念があって、餅をたくさん食べるには鍋が良いから、鍋ばかり食べてしまう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">冬以外に餅を食べたら負けだと思うから。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">さて、卒論も一区切りついたということで、「マップチップを自動生成するサイト」を作りました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://mapchip.argonism.info/\">
72https://mapchip.argonism.info/\u003C/a>\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"マップチップとは?\" class=\"anchor\" href=\"#マップチップとは?\">\n                マップチップとは?\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ゲームのマップを構成するときに使われる部品で、マップチップを組み合わせることでゲーム内のマップを構成する。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">古めのゲームで善く使われる手法で、今はこの方法でマップ作ってるゲームは少ないんじゃなかろうか\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回作成したシステムで生成されたマップチップの例\u003C/p>\n\u003Cdiv style=\"display: flex; flex-direction: row; justify-content: space-evenly; padding: 0 3rem;\">\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/ogp_image.png\">\u003C/img>\n    \u003C/div>\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip1.png\">\u003C/img>\n    \u003C/div>\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip5.png\">\u003C/img>\n    \u003C/div>\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip3.png\">\u003C/img>\n    \u003C/div>\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip4.png\">\u003C/img>\n    \u003C/div>\n\u003C/div>\n\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"作ったサイトについて\" class=\"anchor\" href=\"#作ったサイトについて\">\n                作ったサイトについて\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">今回作ったサイトは、マップチップを生成するサイト。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://mapchip.argonism.info/\">https://mapchip.argonism.info/\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">サイトトップに行くと、「Generate!」ボタンがあるだろう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これをクリックすると、マップチップが生成される。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"モーフィング\" class=\"anchor\" href=\"#モーフィング\">\n                モーフィング\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">マップチップの生成機能の他に、「モーフィングGIFを生成する」機能を作ってみた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これは、\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://mapchip.argonism.info/gallery\">https://mapchip.argonism.info/gallery\u003C/a> で使える。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">Galleryに行くと、たくさんのマップチップが表示されてるが、これは今まで生成されたマップチップの一覧。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この中から、二つのマップチップを選択し、「GO!」ボタンを押す。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">すると、選択した片方のマップチップからもう片方のマップチップに滑らか(?)に移動するようなGIFが生成される。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">NOTE: 生成にはちょっと時間がかかります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">例えば、次の二つのマップチップを選択すると、次のようなGIFが生成される。\u003C/p>\n\u003Cdiv style=\"display: flex; flex-direction: row; justify-content: space-evenly; padding: 0 3rem; align-items: center;\">\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip6.png\">\u003C/img>\n    \u003C/div>\n    \u003Cp>→\u003C/p>\n    \u003Cdiv style=\"width: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip4.png\">\u003C/img>\n    \u003C/div>\n    \u003Cp>=\u003C/p>\n    \u003Cdiv style=\"width: 64px; height: 64px; image-rendering: pixelated;\">\n        \u003Cimg src=\"/img/media/mapchip-morphing.gif\">\u003C/img>\n    \u003C/div>\n\u003C/div>\n\n\u003Cp class=\"my-5 leading-6\">これは2つのマップチップの片方の潜在変数を、もう片方の潜在変数にちょっとずつ近づけながらフレームを生成し、GIFを構成している。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">特に目新しい機能というわけではないが、Webアプリとして遊べるとなると、なかなか面白かろう。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">
72\n              \u003Ca name=\"なぜ作ったのか\" class=\"anchor\" href=\"#なぜ作ったのか\">\n                なぜ作ったのか\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">大学の機械学習・深層学習の授業で、自分で課題を設定してモデルを学習させるというものがある。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕はそこで「マップチップを一つ一つ作るのは大変だ!」「配布されてる素材がある」ということを背景に、マップチップジェネレータの開発を宣言し、作った。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">実際の作業量のほとんどデータをかき集めることだった。幸いDCGANの教師なし学習だったため、データセットの素材を集めるだけで済んだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">人によっては自分でラベリングをする必要もあって、期間も長くないのでプロジェクトの規模を間違えると詰む。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ソースコードのほうは、モデルやモデルの訓練スクリプトは先生が用意してくれていたので、一部をちょちょっと書き替えるだけ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">こういうプロジェクト系の授業は少ないが、大変有意義だと思うので増えて欲しいと思う。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"使用技術・サービス\" class=\"anchor\" href=\"#使用技術・サービス\">\n                使用技術・サービス\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">github\u003C/li>\n\u003Cli class=\"list-disc\">バックエンド\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">python\u003C/li>\n\u003Cli class=\"list-disc\">pytorch\u003C/li>\n\u003Cli class=\"list-disc\">fastapi\u003C/li>\n\u003Cli class=\"list-disc\">docker\u003C/li>\n\u003Cli class=\"list-disc\">Google Compute Engine\u003C/li>\n\u003Cli class=\"list-disc\">Google Container Registry\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">フロントエンド\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">NextJS\u003C/li>\n\u003Cli class=\"list-disc\">TailwindCSS\u003C/li>\n\u003Cli class=\"list-disc\">Vercel\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">NextJSは使い勝手よかった。元々Reactを使ったことがあったが、SSRが思ったよりよかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">バックエンドは機械学習モデルをホスティングしてるからあんまり晒したくなくて、そういうときにNextJSのAPI route機能が便利。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">それからVercelにデプロイするの、めちゃくちゃ簡単ですごい。しかも商用利用じゃなければ無料という。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"料金\" class=\"anchor\" href=\"#料金\">\n                料金\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">大変ありがたいことに、料金は今の所かかってない。料金がかかるとしたらGCEだが、無料枠に収めている。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(一回設定ミスって、25円くらいかかってしまったが)\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"思い出\" class=\"anchor\" href=\"#思い出\">\n                思い出\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"マップチップ生成モデル\" class=\"anchor\" href=\"#マップチップ生成モデル\">\n                マップチップ生成モデル\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">学部3年の頃に授業で作成した。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">当時、マップチップを集めて、必要に応じてマップチップを分割して、分類して等、データ集めるのはやはり大変だった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そして機械学習モデルを始めていじったため、色々次元のサイズが合わなくて教科書読んだりネット記事読んだりで最初手こずった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">しかし、ここの苦労は今の土台になってると思う。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"サイト作成\" class=\"anchor\" href=\"#サイト作成\">\n                サイト作成\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">作り始めた最初、モデルから生成されるマップチップのクオリティが低くて、原因がなかなかわからなかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">原因はバッチサイズだったのだが、バッチサイズを変更すると、モーフィングGIF生成機能に影響する。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">両立させるのは困難だったが、モーフィングGIF生成機能を、正確性と生成時間を犠牲にして、マップチップのクオリティを維持することにした。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"知見\" class=\"anchor\" href=\"#知見\">\n                知見\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">Webサイトでドット絵を表示するときは、次のスタイルを適応すると、リサイズに強くなれる。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-css\">image-rendering: pixelated\n\u003C/code>\u003C/pre>\n"}},{slug:"2021-09-27--use_state_dict",post:{meta:{title:"torch.save(model)をするときはモジュールに気をつける",date:new Date(1632700800000),tags:["ml","pytorch"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">pytorchでモデルを保存する方法は僕の知っているところ2通りあって、\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">torch.save(model, filename)\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">と\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">torhc.save(model.state_dict(), filename)\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">である。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">後者はモデルというより、モデルのパラメータを保存してるらしい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">モデルを保存するサンプルコードを探すと、公式ドキュメントでもだいたいのサイトでも後者の\u003Ccode>model.state_dict()\u003C/code>を使うサンプルコードになっていると思う。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回は、なぜ前者でなく後者なのか知る機会があったã
72®ã§ã€ãƒ¡ãƒ¢ã™ã‚‹\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"なぜ\u003Ccode>torch.save(model,-filename)\u003C/code>だとダメなのか\" class=\"anchor\" href=\"#なぜ\u003Ccode>torch.save(model,-filename)\u003C/code>だとダメなのか\">\n                なぜ\u003Ccode>torch.save(model, filename)\u003C/code>だとダメなのか\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"理由:-モデルをロードしたとき、モデルがインポートしたモジュールが必要になる。\" class=\"anchor\" href=\"#理由:-モデルをロードしたとき、モデルがインポートしたモジュールが必要になる。\">\n                理由: モデルをロードしたとき、モデルがインポートしたモジュールが必要になる。\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">例えば自作のモジュールを使ってモデルを学習したとする。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのモデルが\u003Ccode>torch.save(model, filename)\u003C/code>
72で保存されたとすると、そのモデルをロードするときにその自作のモジュールも必要となる(使う使わないに限らず)。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回、学習したモデルをロードして推論に使おうとしたが、モデル内のスクリプトでインポートされていたモジュールがインストールできなくて、モデルをロードできないということがあった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">正確には、モデルのモジュールがロードする時に、saveした時と同じモジュールがimport可能になっていないとダメって感じっぽい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/pytorch/pytorch/issues/3678\">https://github.com/pytorch/pytorch/issues/3678\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">調べた感じだと、他にもGPUに送ったモデルを\u003Ccode>torch.save(model, filename)\u003C/code>した場合、そのモデルをロードするときにGPUに置かれるから、GPUが使えないとモデルをロードできなくなるらしい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ということがあるので、\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">torhc.save(model.state_dict(), filename)\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">を使います。\u003C/p>\n"}},{slug:"2021-08-9--swift-go-mobile-app",post:{meta:{title:"SwiftとGolangでスマホアプリを作る",date:new Date(1628467200000),tags:["golang","echo","swift","smartphone"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">今まで何度もスマホアプリを作ろうと思ったことはあったが、作ったことはなかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">というわけで、七月の4連休で作ってみた!\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"使用技術\" class=\"anchor\" href=\"#使用技術\">\n                使用技術\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">iOSの開発に長いこと苦手意識とトラウマがあったため、克服すべくiOSアプリを作ることにした。\nというわけで、現在の使用技術はこんな感じ。\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">Swift\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">SwiftUI\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">Golang\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">Echo: REST Api 向けのフレームワーク\u003C/li>\n\u003Cli class=\"list-disc\">GORM: GoのORM\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">GCE\u003C/li>\n\u003Cli class=\"list-disc\">MySQL\u003C/li>\n\u003Cli class=\"list-disc\">GitHub\u003C/li>\n\u003C/ul>\n\n            \u003Cdiv class=\"text-xl my-10\">\n              \u003Ca name=\"開発環境のみ\" class=\"anchor\" href=\"#開発環境のみ\">\n                開発環境のみ\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">docker\u003C/li>\n\u003Cli class=\"list-disc\">Air: Goのホットリロード用のライブラリ\u003C/li>\n\u003C/ul>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"作るアプリ\" class=\"anchor\" href=\"#作るアプリ\">\n                作るアプリ\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">今回は、以前授業で作成したアプリケーションのスマホ版を作ってみる。\nそのアプリケーションは、「めしココ」という、「ご飯を食べにいくことは決まったけど、どこにいくか決まらない」人のために、行くご飯屋さんを決定してくれるアプリ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">開発は、詳細は作りながら考えていこうという見切り発車Development方式を採用\u003C/p>\n\u003Ciframe src=\"https://docs.google.com/presentation/d/e/2PACX-1vR3A9YzS-0NOlkZomtQowRqUfsExcqnxfUzXKPsfQ4jJyqUZnJWId7eY_Ag3iPAFw/embed?start=false&loop=false&delayms=3000\" frameborder=\"0\" width=\"1280\" height=\"749\" allowfullscreen=\"true\" mozallowfullscreen=\"true\" webkitallowfullscreen=\"true\">\u003C/iframe>\n\n\u003Cp class=\"my-5 leading-6\">最近気づいたことなんですが、すでに同名のサイトが存在しており、改名を検討中。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"swiftでフロントエンドを作る\" class=\"anchor\" href=\"#swiftでフロントエンドを作る\">\n                Swiftでフロントエンドを作る\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">
72Apple公式のチュートリアルでSwiftでのアプリの作り方を学ぶ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なるほど、以前に見たものとちょっと違う印象を受ける。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あれ、storyboardとかなかったっけ?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">調べてみると、今回学んだものはSwiftUIというものらしい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">storyboardはGUIで画面を構成するのに対して、SwiftUIはコードでレイアウトを構築するものらしい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ふーんという感じだが、とりあえず新しいほうで実際にプロジェクトを作ってみる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">チュートリアルでは、お気に入りの場所を登録するアプリを作るという感じで、割と流用できそうな内容であった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">とりあえず、ご飯屋さんの一覧を表示できるようにする。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そうして、ご飯屋さんの一覧から、ご飯屋さんをタップするとその詳細情報のページへ飛ぶようなアプリができた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(データは仮置き)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"300px\" src=\"/img/media/meshikoko-swift-first.gif?width=300\" alt=\"\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">Swiftという言語をほぼ初めて触ったが、結構いい感触を覚えた。\n言語機能が結構豊富。\nOptional型というものも、知ってはいたが、それが言語機能として組み込まれている言語を使ったことはなかったため、新鮮だった。\nただ、慣れてないだけかもしれないが、デバッグがちょっとしづらいかなと感じた。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"バックエンドを作る\" class=\"anchor\" href=\"#バックエンドを作る\">\n                バックエンドを作る\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">バックエンドはGoを採用した。\nバックエンドでよく使われる言語で、使ったことがなかったし、なんかよく聞くので一度使ってみようかなという気持ちで使い始めた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">スマホ向けのAPIということで、フレームワークとしてEchoを使ってみた。\nGinかEchoで迷ったが、Ginは今後別に使う可能性があるため、使わなさそうなEchoを試してみた。\nORMもできれば欲しいということで、GORMを使ってみる。\nデータベースは冒険せずにMySQLで行ってみる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">バックエンドに関しては特筆することもなく、ただGoの学習という感じ。\nなにやらAPIを作る上で、MVC以外にCleanアーキテクチャというものがあるらしい。\n多少調べてみたが、今回のプロジェクトで採用するにはアーキテクチャがデカすぎるように感じたため、見送った。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">GoはCに近い印象だった。\nCにモダンな機能と文法を与えたような。\nまだゴールーチンは使ったことがない。(有効に使えるような場面に遭遇していないと思う)\nシングルバイナリ好き\u003C/p>\n\u003Cp class=\"my-5 leading-6\">同時に二つの言語を新しく触ると頭がバグりがちなのでおすすめしない。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"どこでホスティングするか\" class=\"anchor\" href=\"#どこでホスティングするか\">\n                どこでホスティングするか\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">候補としては\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">AWSの何か(EC2など)\u003C/li>\n\u003Cli class=\"list-disc\">GCP\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">GAE\u003C/li>\n\u003Cli class=\"list-disc\">GCE\u003C/li>\n\u003C/ul>\n\u003C/li>\n\u003Cli class=\"list-disc\">Azureの何か\u003C/li>\n\u003Cli class=\"list-disc\">何かのVPS(Conohaなど)\u003C/li>\n\u003Cli class=\"list-disc\">Heroku\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">できるだけ、無料でやりたいという気持ちが強いため、VPSは除外\n無料枠があるAWS, GCP, Azure, Herokuの中で、HerokuはすでにTwitter Botで無料枠を使っているため除外\nまた、せっかくなら使ったことのないサービスを使おうという気持ちからAWSを除外\nそうしてAzureとGCPが残ったが、Azureは無料枠の判定だったりどういうサービスがどういう機能を持っているのか分かりづらかったため、\nGCPを使うことにした。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"gce?-gae?\" class=\"anchor\" href=\"#gce?-gae?\">\n                GCE? GAE?\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">GCPの中で、今回使いそうになるサービスはGCEとGAE。\nGCEはAWSでいうEC2で、VPS的なアレでã
72‚る。GAEはAWSでいうとなにになるのかわからないが、PaaSと言われるもので、Herokuのようにアプリケーションをデプロイするだけでプログラムを走らせられるというノリのもの。\nこの両方のサービスに無料枠がある。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最初、GAEをAPサーバ、GCEをMySQLサーバにしようと考えていたが、すでに似たようなことをやって結果をまとめてくれていた記事を発見\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://crieit.net/posts/GCE-DB-GAE\">https://crieit.net/posts/GCE-DB-GAE\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この構成で無料で動かすのに苦戦するっぽい\u003C/p>\n\u003Cblockquote>\n\u003Cp class=\"my-5 leading-6\">GCEにWeb+DB全部入れにしたら費用がかからなくなったのでやはりこの構成だと費用がかかるみたいです。\u003C/p>\n\u003C/blockquote>\n\u003Cp class=\"my-5 leading-6\">とのことだったため、GCEに全部載せにしてみる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最初ためにし開発環境で使っていたDocker-composeをGCE上で動かしてみたが、当然メモリ不足で動かなかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのため、本番環境ではMySQLをセットアップし、APサーバを普通に起動する方針に。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">NginXをまだセットアップしていないため、そのうちやりたい\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"今後\" class=\"anchor\" href=\"#今後\">\n                今後\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">とりあえず、一連の流れはできたのであとは機能を増やしていくだけ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">現在はお店のスマホから登録する機能を追加したところ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">次は画像の登録とかやってみようかな。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">リポジトリは、開発に飽きてサーバ止めたら公開する予定\u003C/p>\n"}},{slug:"2021-05-8--weed-tea",post:{meta:{title:"その辺に生えてるよくわからん草を、お茶にして味わってみた。",date:new Date(1622937600000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">やってみよう研究所 筑波支部 の第一弾プロジェクト。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その辺に生えてるよくわからん草を、お茶にして味わってみた。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"草を集める\" class=\"anchor\" href=\"#草を集める\">\n                草を集める\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">とりあえず、近くを歩き回ってみる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">大学近くには思ったより色々な植物が生えていた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">犬のふんとかおしっことかかかってても嫌だから、ちょっと高めの草とか奥めの草を意識して採集する。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「お茶にするぞ」という目線でまわりの草を見てみると、なんとなく美味しそうとか不味そうとか感じてくるようになる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そしてよもぎが結構自生しており、よもぎはお茶っ葉として使われるみたいな話を聞いたことがあるためちょっと多めに集めてみた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">草を集めてる時は通りかかる人の視線が気になった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なんとか「自由研究をしてる大学生」のモノマネをする気持ちで取り組むと精神的に楽になるライフハックを発見し、乗り越えたã€
72‚\u003C/p>\n\u003Cp class=\"my-5 leading-6\">1時間ほどの素材集めを終え、だいたいお茶5杯分になりそうなくらいの草が集まった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">&lt;img width=&quot;400px&quot; src=&quot;/img/weeds_tea/otya_raw.JPG&gt;\u003C/p>\n\u003Cp class=\"my-5 leading-6\">色々な種類の草だ。葉っぱの形からも種類が全然違う草が集められたことがわかる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">さて、早速お茶っぱにしてみよう\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"草を揉む\" class=\"anchor\" href=\"#草を揉む\">\n                草を揉む\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">まずはお茶っ葉を「揉む」らしい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">通常は蓙(ござ)に草を押し付けながら転がすことで「揉む」らしいが、ゴザなんてないのでまな板の上で転がしてみた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\"># 揉む前\n\u003Cimg width=\"400px\" src=\"/img/weeds_tea/before_momi.png\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(揉んだ後の画像とってませんでした!意外と難しいのとまな板が緑色になったことしか覚えてません!)\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"草を煎る\" class=\"anchor\" href=\"#草を煎る\">\n                草を煎る\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">揉んだ後、草を煎る。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">加熱の方法は電子レンジだったり、鍋だったりするらしいが、今回はフライパンで熱してみる。\u003C/p>\n\u003Cimg width=\"400px\" src=\"/img/weeds_tea/on_flying_pan.png\">\n\n\u003Cp class=\"my-5 leading-6\">なんとも、形容し難い嗅いだことのない臭いがする。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">いいとも悪いとも言い難い、本当に色々な臭いがする。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">もしかしたら食べられるかも!という気持ちになる臭いで、遠目に嗅ぐと、凄い独特な「森の香り」みたいな芳香剤的な感じの匂い\u003C/p>\n\u003Cp class=\"my-5 leading-6\">青臭さと食べられそうな匂いが半々くらいか。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"「揉む」と「煎る」を繰り返す\" class=\"anchor\" href=\"#「揉む」と「煎る」を繰り返す\">\n                「揉む」と「煎る」を繰り返す\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">以上の「揉む」「煎る」を繰り返す。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">5回ほど繰り返すらしいが、煎るのに結構時間がかかる。\u003C/p>\n\u003Cimg width=\"400px\" src=\"/img/weeds_tea/iru_and_momu.png\">\n\n\u003Cp class=\"my-5 leading-6\">当然だが、煎った後の草は熱いから気をつけよう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">だいたい草がカラカラに乾いたため、終わり。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"完成!\" class=\"anchor\" href=\"#完成!\">\n                完成!\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">というわけで、雑草お茶っぱの完成!\u003C/p>\n\u003Cimg width=\"400px\" src=\"/img/weeds_tea/kansei.png\">\n\n\u003Cp class=\"my-5 leading-6\">ちゃんと揉めてないものが多く混ざってるが、まぁー大丈夫でã
72—ょう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今のところ香りは特に目立たない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">では、早速お茶を入れてみよう。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"お茶を淹れてみる\" class=\"anchor\" href=\"#お茶を淹れてみる\">\n                お茶を淹れてみる\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">急須にお茶っぱを入れる。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">やっぱりちゃんと揉めてないと、こういうところでちょっと手間がかかる。\u003C/p>\n\u003Cimg width=\"400px\" src=\"/img/weeds_tea/kyu-su_de_ireta_kusatya.png\">\n\n\u003Cp class=\"my-5 leading-6\">そしてお茶を注ぐと...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cstrong>信じられないくらいいいお茶の香りがする\u003C/strong>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">草を煎ってた段階の臭いから、嫌な臭いを完全に消して風味だけ残したような感じ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">完っっっっ全にお茶になった。お茶以外に言いようのない、お茶になった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ただ、確実に飲んだことはないお茶。おばあちゃんちで出てきそうなちょっと薄いよくわかんないお茶みたいな印象。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これはびっくり、雑草でもお茶になった。変な味はしない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これは、大成功だ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あとは後々体調を崩さないことを祈る。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"終わりに\" class=\"anchor\" href=\"#終わりに\">\n                終わりに\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">色々な味がするというよりは、風味ベクトルが一定の方向に定まってるように感じたから、特定の草が特に風味に貢献していて、他の草からは何も風味が抽出できていないのかもしれない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ただ、なんの草を集めたのはわからないから、なにが影響したのか特定できないのだが。\u003C/p>\n"}},{slug:"2021-01-8--put-link-within-same-workbook-with-axlsx",post:{meta:{title:"axlsx で同じワークブック内のリンクを貼る",date:new Date(1610064000000),tags:["new","tech"],draft:false},content:"\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"背景\" class=\"anchor\" href=\"#背景\">\n                背景\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ruby から excel いじるライブラリである axlsx で、同じワークブック内のシートのリンクを貼りたかったがうまくいかなかったのでメモ\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"原因\" class=\"anchor\" href=\"#原因\">\n                原因\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">うまくいかなかった原因は、リンクを\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-ruby\">  sheet.add_hyperlink :location =&gt; &quot;&#39;Next Sheet&#39;!A1&quot;, :ref =&gt; &#39;A2&#39;, :target =&gt; :sheet\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">という形ではるわけだが、この「location」、なんとキャメルケースに変換される。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これはなかなか気づかない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">生成されるリンクは「不正」とだけ言われてみることがなかなかできなかったからだ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後、しばらくホバーしていると情報が得られることが発覚。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">さらにしばらく後、リンクがキャメルケースになっていることが発覚。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">結構時間を取られた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ちなみに、以上の原因のため、ワークシートの名前がキャメルケースであれば問題ない。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回の事案はワークシートはスネークケースだったため、見事にハマった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(axlsx の issue で見かけたが、なにやらワークシートの名前もキャメルケースにされるらしいのだが一体...)\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"修正\" class=\"anchor\" href=\"#修正\">\n                修正\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">
72リンク先のシート名をキャメルケースに変えた。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"雑記\" class=\"anchor\" href=\"#雑記\">\n                雑記\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">xlsx ってどうやって読み込むんだろう\u003C/p>\n\u003Cp class=\"my-5 leading-6\">普通の xml ではないっぽい(プレーンテキストとして読めなかった)ので、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">どうやっていじるのか気になりますね。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あと、emotet...自動実行は脆弱性の温床...\u003C/p>\n"}},{slug:"2020-12-18--get-schema-comment-in-rails",post:{meta:{title:"railsアプリケーション内でスキーマのコメント情報を取得する",date:new Date(1608249600000),tags:["new","tech"],draft:false},content:"\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"背景\" class=\"anchor\" href=\"#背景\">\n                背景\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">rails の rake タスクで、データベーススキーマのコメントを取得したい場面があったが、情報が全然なかったのでメモ\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"結論\" class=\"anchor\" href=\"#結論\">\n                結論\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cpre>\u003Ccode class=\"language-ruby\">## Rails 4\nModel.connection.retrieve_table_comment(table_name)\n\n## Rails 5\nModel.connection.table_comment(table_name)\n\u003C/code>\u003C/pre>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"雑記\" class=\"anchor\" href=\"#雑記\">\n                雑記\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">rails4 での方法は見つかるが、rails5 でスキーマのコメント書き込みが取り込まれてから、rails4 での方法が使えなくなっていた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">table_comment に関する情報がとにかくなく、色々漁った後 github の rails リポジトリの test でこのメソッドが使われているのを発見した。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">test ってこういう風に、ドキュメント的な感じで使えますね。\u003C/p>\n"}},{slug:"2020-11-24--waniCTF-2020-writeup",post:{meta:{title:"waniCTF 2020 writeup",date:new Date(1606176000000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">waniCTF に参加しました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://wanictf.org/\">https://wanictf.org/\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最近課題で忙殺されていて、ksnctf も解き終わっていないですが、ちょっと解けそうな問題が多そうだったため、参加してみました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この CTF は初心者向けの CTF になっていて、ヒントが多めにもらえるやさしめの CTF です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">結果は 64 / 242 だったよう\n\u003Cimg width=\"500px\" src=\"/img/media/wanictf_result.png\" alt=\"result\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">スコアの詳細\n\u003Cimg width=\"500px\" src=\"/img/media/wanictf_score.png\" alt=\"score\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">うーん、pwn が苦手ですね。reverse も苦手だと感じました。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"crypt\" class=\"anchor\" href=\"#crypt\">\n                Crypt\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"veni,-vidi\" class=\"anchor\" href=\"#veni,-vidi\">\n                Veni, vidi\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">シザー暗号ですね。FLAG{...}の形式の文字列になっているため、F -&gt; S のシフト数を考えます\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"exclusive\" class=\"anchor\" href=\"#exclusive\">\n                exclusive\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">
72xor で暗号化された文を元に戻す問題です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">暗号化に使ったであろう encrypt.py と 暗号文であろう output.txt が配られています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">encrypt.py\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">key = &quot;REDACTED&quot;\nflag = &quot;FAKE{this_is_fake_flag}&quot;\n\nassert len(key) == len(flag) == 57\nassert flag.startswith(&quot;FLAG{&quot;) and flag.endswith(&quot;}&quot;)\nassert key[0:3] * 19 == key\n\n\ndef encrypt(s1, s2):\n    assert len(s1) == len(s2)\n\n    result = &quot;&quot;\n    for c1, c2 in zip(s1, s2):\n        result += chr(ord(c1) ^ ord(c2))\n    return result\n\n\nciphertext = encrypt(flag, key)\nprint(ciphertext, end=&quot;&quot;)\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">encrypt.py の以下の部分をみてみると、どうやら xor のキーとなる文章は 3 文字の繰り返しのようですね。\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">assert key[0:3] * 19 == key\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">わざわざ assert で保証してくれています。\n(ちなみに、REDACTED は[削除済み]という意味)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ascii の 3 文字の範囲内なら総当たりで探せそうです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">総当たりで 3 文字を作り、\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">output.txt の最初の三文字\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">と\u003C/p>\n\u003Cul class=\"ml-[1.5rem] my-[0.3rem]\" >\n\u003Cli class=\"list-disc\">「FLA」と key で xor したもの\u003C/li>\n\u003C/ul>\n\u003Cp class=\"my-5 leading-6\">が一致するような key を探します。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">これで無事 key が発見でき、flag が取り出せました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">exploit.py\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">
72def encrypt(s1, s2):\n  assert len(s1) == len(s2)\n\n  result = &quot;&quot;\n  for c1, c2 in zip(s1, s2):\n      result += chr(ord(c1) ^ ord(c2))\n  return result\n\nif __name__ == &quot;__main__&quot;:\n  output = &quot;&quot;\n  with open(&quot;output.txt&quot;, &quot;r&quot;) as f:\n    output = f.read()\n\n  output_boutou = output[0:3]\n\n  key_head = &quot;&quot;\n\n  for a in range(32, 126):\n    for b in range(32, 126):\n      for c in range(32, 126):\n        key_tmp = chr(a) + chr(b) + chr(c)\n        print(key_tmp)\n        encrypted = encrypt(&quot;FLA&quot;, key_tmp)\n        if output_boutou == encrypted:\n          key_head = key_tmp\n          print(&quot;KEY FOUNDED:&quot;, key_head)\n          break\n\n  plain_text = encrypt(output, key_head * 19)\n  print(plain_text)\n\u003C/code>\u003C/pre>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"basic-rsa\" class=\"anchor\" href=\"#basic-rsa\">\n                Basic RSA\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">これは本当にベーシックな RSA 暗号の計算でした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">p * q\u003C/p>\n\u003Cp class=\"my-5 leading-6\">から始まり、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">暗号化の計算\u003C/p>\n\u003Cp class=\"my-5 leading-6\">暗号文の複合\u003C/p>\n\u003Cp class=\"my-5 leading-6\">の計算を順にこなして FLAG 獲得です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">余談ですが、nc でサーバーにアクセスしたときに表示されるやつ(?)がオサレでした。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"lcg-crack\" class=\"anchor\" href=\"#lcg-crack\">\n                LCG crack\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">線形合同法の予測です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">好きなだけ.next()の値が得られ、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">.next()の値を十分に取り出したら、予測フェーズに入り、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">10 個ぐらい予想が当たればフラグがもらえます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">線形合同法の予測のプログラムは色々な人が載せてくれているため、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">それを使ってときました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">実際にはこちらの方のブログからお借りしました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://satto.hatenadiary.com/entry/solve-LCG\">https://satto.hatenadiary.com/entry/solve-LCG\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">初めて pwntools を使って解いたため、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この問題を解くこと以上に pwntools の扱いに時間がかかりました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">exploit.py\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">from pwn import *\nfrom Crypto.Util.number import inverse, GCD\nfrom functools import reduce\nimport re\n\nclass LCG:\n    # X_{n+1} = (A \\times X_n + B) \\bmod M\n    A = 9605000926055143081 # multiplier\n    B = 9749676397194673813 # increment\n    M = 18446744073709551615 # modulus\n\n    def __init__(self, seed):\n        # start value\n        self.state = seed\n\n    def next(self):\n        self.state = (self.A * self.state + self.B) % self.M\n        return self.state\n\n    def get_parameters(self):\n        return self.A, self.B, self.M\n\ndef solve_unknown_increment(states, A, M):\n    B = (states[1] - A * states[0]) % M\n    return B\n\ndef solve_unknown_multiplier(states, M):\n    A = (states[2] - states[1]) * inverse((states[1] - states[0]), M)\n    return A\n\ndef prediction_test(PRNGs, states, A, B, M):\n    next_value = PRNGs.next()\n    predicted_value = (A * states[-1] + B) % M\n\n    for i, state in enumerate(states):\n        print(&#39;X_{0}: {1}&#39;.format(i, state))\n\n    print(&#39;\\nnext value: {}&#39;.format(next_value))\n    print(&#39;predicted value: {}&#39;.format(predicted_value))\n\n    if next_value == predicted_value:\n        print(&#39;correct!&#39;)\n    else:\n        print(&#39;incorrect!&#39;)\n\ndef output_example():\n    states = [114514]\n    PRNGs = LCG(states[0])\n    states.append(PRNGs.next())\n    states.append(PRNGs.next())\n    states.append(PRNGs.next())\n    states.append(PRNGs.next())\n\n    A, B, M = PRNGs.get_parameters()\n\n    prediction_test(PRNGs, states, A, B, M)\n\ndef solve_unknown_modulus(states):\n    diffs = [X_1 - X_0 for X_0, X_1 in zip(states, states[1:])]\n    multiples_of_M = [T_2 * T_0 - T_1 ** 2 for T_0, T_1, T_2, in zip(diffs, diffs[1:], diffs[2:])]\n\n    # GCD(GCD(multiples_of_M[0],multiples_of_M[1]), multiples_of_M[2])\n    M = reduce(GCD, multiples_of_M)\n    return M\n\n\n\n\ndef send_cmd_num(io, num):\n  io.sendline(str(num))\n  io.recv()\n  return ret\n\ndef get_next_number(io):\n  io.sendline(str(1))\n  ret = io.recvline()\n  return ret.decode(&#39;utf-8&#39;).rstrip()\n\n\ndef estimate_next(state):\n    M = solve_unknown_modulus(states)\n    A = solve_unknown_multiplier(states, M)\n    B = solve_unknown_increment(states, A, M)\n    return (A * states[-1] + B) % M\n\nif __name__ == &quot;__main__&quot;:\n\n  io = remote(&#39;lcg.wanictf.org&#39;, 50001)\n  io.recvuntil(&#39;&gt; &#39;)\n\n  states = []\n  while len(states) &lt;= 7:\n    ret = get_next_number(io).rstrip()\n    ret = re.sub(r&quot;[^\\d]&quot;, &#39;&#39;, ret)\n    print(ret.strip())\n    if len(ret) &gt; 3:\n      x = int(ret.rstrip())\n      states.append(x)\n    io.recv()\n\n  for n in range(10):\n    print(&quot;collected_states:&quot;, states)\n\n    M = solve_unknown_modulus(states)\n    A = solve_unknown_multiplier(states, M)\n    B = solve_unknown_increment(states, A, M)\n    predicted_value = (A * states[-1] + B) % M\n\n    if n == 0:\n      io.sendline(str(2))\n      ret = io.recv()\n      print(ret)\n    io.sendline(str(predicted_value))\n    ret = io.recv()\n    print(ret)\n    if &quot;Correct&quot; in ret.decode(&#39;utf-8&#39;):\n      print(&quot;corrected!&quot;)\n      states.pop(0)\n      states.append(predicted_value)\n    else:\n      print(ret)\n      print(&quot;failed!&quot;)\n      break\n    # io.interactive()\n\n  ret = io.recv()\n  print(ret)\n\n  print(ret.decode(&#39;utf-8&#39;))\n\u003C/code>\u003C/pre>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"forensics\" class=\"anchor\" href=\"#forensics\">\n                Forensics\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"logged_flag\" class=\"anchor\" href=\"#logged_flag\">\n                logged_flag\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">キーロガーをみると、FLAG{...}という文字列を売っていることが確認できます。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"alligator_01\" class=\"anchor\" href=\"#alligator_01\">\n                ALLIGATOR_01\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">メモリダンプが配布されています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">volatility というツールを使って解く問題のようです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">初めて使うツールですし、メモリダンプがどういったことまでできるのかわかりませんが、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">見様見真似でコマンドを色々打って flag を見つけました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">確か、\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-sh\">volatility -f メモリダンプのファイル --profile=Win7SPx86 pstree\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">とかだった気がします。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そうすると、evil.exe がみつかり、実行時間がわかります。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"alligator_02\" class=\"anchor\" href=\"#alligator_02\">\n                ALLIGATOR_02\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">上の問題の続きで、\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-sh\">volatility -f メモリダンプのファイル --profile=Win7SPx86 pstree\n\u003C/code>\u003C/pre>\n\u003Cp class=\"my-5 leading-6\">で flag をもらった気がします。\u003C/p>\n\n            \u003Cdiv class=\"text-base my-10\">\n              \u003Ca name=\"感想\" class=\"anchor\" href=\"#感想\">\n                感想\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">メモリダンプでコンソールの履歴まで見れるんですね...そのとき起動しているコンソールってことでã
72™ã‹ã­ã€‚多分。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"chunk_eater\" class=\"anchor\" href=\"#chunk_eater\">\n                chunk_eater\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">png はチャンクという、データの塊で構成されています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのチャンクの中で、必須チャンクというものが 4 つあります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回配布されている png ファイルは普通に開くと「ファイルが壊れています」\nと出てファイルが見れません。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">詳しく調べると、チャンクが足りないが、「WANI」という謎のチャンクが生えていることがわかります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">png の必須チャンクは 4 中 2 つがデータのサイズが固定になっていて、\nまた順番もある程度決まっています。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そのため、WANI チャンクをそれぞれの順番に従って、必須チャンクにリネームしてあげると...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">chunk_eater.png\n\u003Cimg src=\"/img/media/chunk_eater.png\" width=\"300px\">\u003C/p>\n\u003Cp class=\"my-5 leading-6\">iHDR チャンクを食べてますね\u003C/p>\n\u003Cp class=\"my-5 leading-6\">png ファイルの解析には png-parser というライブラリがあったため、使わせて頂きました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">exploit.py\u003C/p>\n\u003Cpre>\u003Ccode class=\"language-python\">from pngparser import PngParser, ImageData, ChunkTypes\n\nimport sys\nif __name__ == &quot;__main__&quot;:\n    png = PngParser(sys.argv[1])\n    text_ind = None\n    idat_ind = None\n    text = 0\n    idat = 0\n    for i, chunk in enumerate(png.chunks):\n        if chunk.type.name == &quot;WANI&quot;:\n            if chunk.length == 11:\n                chunk.type = ChunkTypes.IEND\n            elif chunk.length == 24:\n                chunk.type = ChunkTypes.IHDR\n            else:\n                chunk.type = ChunkTypes.IDAT\n                idat_ind = i\n                idat = chunk\n        if chunk.type == ChunkTypes.tEXt:\n            text_ind = i\n            text = chunk\n    print(text_ind, &quot;:&quot;, text)\n    print(idat_ind, &quot;:&quot;, idat)\n    png.chunks = [ chunk for chunk in png.chunks \\\n            if not chunk.type == ChunkTypes.tEXt and not chunk.type == ChunkTypes.iTXt ]\n    for i, chunk in enumerate(png.chunks):\n        print(chunk.length, &quot;:&quot;, chunk.type)\n    png.save_file(&quot;output.png&quot;)\n    # print(data)\n\u003C/code>\u003C/pre>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"misc\" class=\"anchor\" href=\"#misc\">\n                Misc\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"find-a-number\" class=\"anchor\" href=\"#find-a-number\">\n                Find a Number\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">数字当てクイズです。指定された回数いないに当てることが求められています。\n普通に二分探査でときました。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"pwn\" class=\"anchor\" href=\"#pwn\">\n                Pwn\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"netcat\" class=\"anchor\" href=\"#netcat\">\n                netcat\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">nc の使い方確認問題です!\u003C/p>\n\u003Cp class=\"my-5 leading-6\">色々問題の表示が優しい。初心者向け\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"var-rewrite\" class=\"anchor\" href=\"#var-rewrite\">\n                var rewrite\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">標準入力からバッファオーバーフローで変数を上書きしてフラグを奪取する問題です。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"reversing\" class=\"anchor\" href=\"#reversing\">\n                Reversing\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"strings\" class=\"anchor\" href=\"#strings\">
72\n                strings\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">strings を使ってフラグをみつける問題です!\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"simple\" class=\"anchor\" href=\"#simple\">\n                simple\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">配布された実行ファイル「simple」は、文字を入力して、「incorrect」とでる感じのものでした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">リバースして、フラグをみつける問題です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">gdb とか objdump で逆アセンブルすると、標準入力から文字列を取得した後、入力文字のサイズを確認して、その後配列に ascii 文字っぽいものを代入しまくっているところがあったため、最初の 4 つを確認したら FLAG でした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">というわけで、その配列に代入されているものを順に文字に変換して、無事フラグゲットです。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"web\" class=\"anchor\" href=\"#web\">\n                Web\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"devtools_1\" class=\"anchor\" href=\"#devtools_1\">\n                DevTools_1\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">これは開発者ツールを開くとフラグが見つかります。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"devtools_2\" class=\"anchor\" href=\"#devtools_2\">\n                DevTools_2\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">開発者ツールを使って、html 要素(テキストノード)を書き換えるとフラグが降ってきます。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"simple-memo\" class=\"anchor\" href=\"#simple-memo\">\n                Simple Memo\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">簡単な、セッションを使ったメモアプリです。(php)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">問題にも書いてあるのですが、ディレクトリトラバーサルの問題です。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">url に/flag.txt と入れたらゲットできました。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"striped-table\" class=\"anchor\" href=\"#striped-table\">\n                striped table\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">上のシンプルメモアプリに xss 脆弱性があるので、それをついて「alert(19640503)」を実行させたらフラグが手に入ると書いてあります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ためしに devtools で実行してみたら、コンソールから実行してもダメだとと怒られてしまいました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ソースコードが開示されているため、xss できそうな箇所を色々探してみると、メモの奇数行目のタイトル欄はサニタイズがされていないことがわかりました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">というわけで、奇数行目のメモのタイトル欄に xss を埋め込めばいいんですが、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕の環境ではここに埋め込んでも、devtools で怒られた時と同じ表示が出てきてしまい、フラグが得られませんんでした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(このやり方であってるのよな...?)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">というわけで、js を読みます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">js は難読化されていますが、chrome の devtools でブレイクポイントとかコンソールをうまく使うと色々わかってきます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">まずソースコードを注意深くみて、怪しそうな箇所周辺で実行を止めてコンソールでちまちま確認してみると、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">js でフラグが書き込まれている箇所を見つけて、flag をゲットしました。\u003C/p>\n\n            \u003Cdiv class=\"text-3xl my-10\">\n              \u003Ca name=\"感想\" class=\"anchor\" href=\"#感想\">\n                感想\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">というわけで、僕が解いた問題はこれで全てになります。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">優しい問題が多くて、僕でも解ける問題が多くて楽ã
72—かったです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">sql_challenge1 を解けなかったのがめちゃくちゃ悔しい。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">あとで解けなかった問題の writeup をみて、できたらまとめなおしたいと思います。\u003C/p>\n"}},{slug:"2020-10-2--traffic-signal",post:{meta:{title:"信号守ったら車に轢かれそうになった話",date:new Date(1601596800000),tags:["new"],draft:false},content:"\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"あと半年くらい秋でいてくれ\" class=\"anchor\" href=\"#あと半年くらい秋でいてくれ\">\n                あと半年くらい秋でいてくれ\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">最近ようやく涼しくなって、最高の季節になりました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">最近自転車も若干きれいにして走りやすくなったので、買い物ついでにちょっと街を探検することに。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">街を探検するときは基本的に目的地を設定しないと走り出せないので、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今回はちょっと遠目のパン屋でなんか買ってこようかなとひたすら南に走り出しました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">目的地周辺についたはいいものの、肝心のパン屋のお店が見つからず、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">日も落ちつつあったため帰路に。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"信号は基本的に守る\" class=\"anchor\" href=\"#信号は基本的に守る\">\n                信号は基本的に守る\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">周りに車が見えなくても信号は守る人っていますよね。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">一人で行動するとき僕もそのタイプです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">
72ですが、今日ちょっと面白いことがあったので書いておきます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">帰り道、順当に信号を守り、赤信号で止まっていると、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">クロスバイク乗りが僕の横をスッとが超えていった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕以外に数人止まっている中だったので、あんまり気にしない人なんだなと思いながら青になるのを待つ。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">さて、青になったのでペダルにグッと力を入れ、横断歩道の真ん中くらいに差し当たったところ\u003C/p>\n\u003Cp class=\"my-5 leading-6\">スピードの乗った青色の軽が突っ込んできた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(あ、前輪が持っていかれる)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">と自転車の死亡が頭を過ぎったが、車は僕の自転車と共に急停止して、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">お互い衝突することはなく、軽の運転手はぺこりと頭を下げながら通りすぎていった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">車に乗っていたのは、母親と息子といったかんじの二人で、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">息子の方は完全にうつむいていた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">轢かれかけたのは僕だけで、(一番車道側にいた)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">信号無視した人をみて、車の通らない横断歩道で律儀に信号を守った後の出来事だったため、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なんだか恥ずかしくて、自分が馬鹿らしくなって笑えてきて、若干にやけながら立ち漕ぎでその場を後にした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後自転車で走りながら、俯いていた息子がちょっと気の毒になったり、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">かなり急いでいたのかななどと信号守って轢かれかけたということから考えを逸らそうとしていたが、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">その後すぐに花粉のことで鼻と目と頭がいっぱいになった。\u003C/p>\n"}},{slug:"2020-08-30--cpaw-ctf",post:{meta:{title:"cpawCTFを解いた",date:new Date(1598745600000),tags:["cpawCTF"],draft:false},content:"\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"cpawctf-を解きました。\" class=\"anchor\" href=\"#cpawctf-を解きました。\">\n                cpawCTF を解きました。\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://ctf.cpaw.site/index.php\">https://ctf.cpaw.site/index.php\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">常設 CTF で、入門・初心者におすすめされるものとして有名な cpawCTF を解いた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">内容は簡単なものが多く、かなり楽しかったです。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">CTF やったことない人は、確かに cpawCTF から入るべきだね..\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(その人の技術力によるけど)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">CTF はやったことない状態で、全部解くのに合計で 12 時間くらいかかった。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">(そのうち 6 時間は Level 3 の数学の問題で溶かした...数弱すぎる)\u003C/p>\n\u003Cp class=\"my-5 leading-6\">問題を解くと得点がもらえ、得点と達成順(?)でランキングがつく。特典は Max で 1890 点。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕は 694 位でした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">結構最近 1890 点に到達したけど、今確認したら僕の後ろに新たに 1890 の人がすでに数人居て驚いた。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">\u003Cimg width=\"500px\" src=\"/img/media/cpawCTF.png\" alt=\"\">\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"特に難しかった問題\" class=\"anchor\" href=\"#特に難しかった問題\">\n                特に難しかった問題\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">Q26.[PPC]Remainder theorem と Q29.[Crypto] Common World が難しかった...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">数学好きなんだけど苦手なんじゃぁー!\u003C/p>\n\n            \u003Cdiv class=\"text-xl my-10\">\n              \u003Ca name=\"q26.[ppc]remainder-theorem\" class=\"anchor\" href=\"#q26.[ppc]remainder-theorem\">\n                Q26.[PPC]Remainder theorem\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">普通の数学の問題だが、数弱すぎて理解に時間がかかり、計算を 100 万回やり直した。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">この問題を解くのに factordb の存在は是非知っていてもらいたい。\u003C/p>\n\n            \u003Cdiv class=\"text-xl my-10\">\n              \u003Ca name=\"q29.[crypto]-common-world\" class=\"anchor\" href=\"#q29.[crypto]-common-world\">\n                Q29.[Crypto] Common World\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ヒントの意味を理解できずに時間を無駄に消費したように思う。\nあと、計算に自信がなさすぎてまた 100 万回計算しなおした。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">「ヒント」とあるが、このヒントがないと現実的に解読不可能なのでは...?\u003C/p>\n\u003Cp class=\"my-5 leading-6\">当然ちゃ当然だけど、rsa 暗号も正しく使わないと僕みたいな初心者でも簡単に解読できてしまう事実が衝撃だった。\u003C/p>\n"}},{slug:"2020-08-29--initial-article",post:{meta:{title:"initial-article",date:new Date(1598659200000),tags:["new"],draft:false},content:"\u003Cp class=\"my-5 leading-6\">initialize article\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"gatsby-との出会い\" class=\"anchor\" href=\"#gatsby-との出会い\">\n                Gatsby との出会い\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">ブログを作ろうと思いたち、いい感じのフレームワークを探してみたã€
72‚\nrails とかで作ろかと考えたが、セキュリティ面でどうしても不安がある。(臆病)\nそういえば、サークルで Hugo を使ったことがあった。\nHugo は SSG、静的なサイトを生成してくれるエンジンなのだが、これがなかなかクールな機能をもっている。\nそこで静的サイトジェネレーターを探す。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そうすると、なにやら\n「Hugo より有名だよ!」\nみたいなノリで紹介されている Gatsby を見つけた。\n紹介している記事を読んでみると、悪くなさそう。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">僕は一度使ったことのあるもの(フレームワークや技術)を何度も使うのに若干抵抗があるため、\n今回はこの Gatsby で作ろうと決めた。\u003C/p>\n\n            \u003Cdiv class=\"text-2xl my-10\">\n              \u003Ca name=\"デザイン\" class=\"anchor\" href=\"#デザイン\">\n                デザイン\n                \u003Cspan class=\"header-link\">\u003C/span>\n              \u003C/a>\n            \u003C/div>\u003Cp class=\"my-5 leading-6\">このブログのこのデザインは、↓ のテンプレートを使っている。\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/kimnagui/gatsby-starter-nagui\">https://github.com/kimnagui/gatsby-starter-nagui\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">なんともシンプルで良い。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">そして機能が多い。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ありがとう、開発チームの人。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">今後ちょっとずつ手を加えたいと思ってます。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">実はこのテンプレート(スターター?)に至るまでは、下のものを使おうとしていた。\n\u003Ca class=\"text-[#0968DA] underline underline-offset-2\" href=\"https://github.com/alxshelepenok/gatsby-starter-lumen\">https://github.com/alxshelepenok/gatsby-starter-lumen\u003C/a>\u003C/p>\n\u003Cp class=\"my-5 leading-6\">けどこれはビルドできず、バグを直せそうになかったので別のものを探しました。\u003C/p>\n\u003Cp class=\"my-5 leading-6\">gatsby-remark-relative-images というプラグインで死んでるっぽいけど、\u003C/p>\n\u003Cp class=\"my-5 leading-6\">ググっても出てこないしエラーメッセージもようわからん...\u003C/p>\n\u003Cp class=\"my-5 leading-6\">謎い\u003C/p>\n"}}]},"uses":{}}];
73
74					Promise.all([
75						import("./_app/immutable/entry/start.Daoojf4R.js"),
76						import("./_app/immutable/entry/app.B4amE5rk.js")
77					]).then(([kit, app]) => {
78						kit.start(app, element, {
79							node_ids: [0, 3],
80							data,
81							form: null,
82							error: null
83						});
84					});
85				}
86			</script>
86
87		</div>
88	
88<script type="module" src="https://static.cloudflareinsights.com/beacon.min.js/v31edd6df95cf4e85bb4c19e7a9bdbcba1788362987495" integrity="sha512-iIg7k2xntmwu6/uSb5tpc/hySgZc4eoL31yB29W6tJFo2akwjPWcEqnCEdJvGexCL0KEQwVYv5BlowfhVz26hg==" data-cf-beacon='{"version":"2024.11.0","token":"8ee59880ebf646258318dd72a590dfd5","r":1,"spa":2}' crossorigin="anonymous"></script>
88
89</body>
90</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.