tech::hexagram

personal note for technical issue.

統計検定2級に受かったのでやったことを全部書く

1ヶ月ほど前の6月17日に、 統計検定2級 を受けてきた。

自己採点で34問中31問正解だったので、マークミスさえなけりゃ大丈夫と踏んでいたが、昨日試験結果の通知が書面で届き、無事合格確定となった。

f:id:manji602:20180719214401j:plain

f:id:manji602:20180719214414j:plain

ありがたいことに、最優秀成績賞なるものも合わせて頂いた。賞状をもらうのも学生時代以来で、承認欲求を満たせて良い。たまに資格試験を受けるのもよいのかもしれない笑

極めて優秀な成績を修めた受験者にS、特に優秀な成績を修めた受験者にAの評価を与えました。

とあり、受験番号と照らし合わせて確認したところ今回頂いた表彰状はS評価らしい。

受験データ を見る限りだと、1532人の受験者の中669人が合格で、自分と同様にS評価を受けたのは31人(Web合格発表希望者のみ)とのことだった。 S評価を受けた総数(Web合格発表希望者以外も含めた)を50人と見積もると、統計検定は100点満点で採点されているとの情報をチラッと見かけたので、概ね90点ないし80点後半を獲得した受験者が対象になりそうという推測ができる。

続きを読む

ロードバイク遠征中にスクーターとぶつかってリアディレイラーが壊れた話

毎年この時期はロードバイクで長距離を泊りがけで走ることにしている。去年国道4号経由で仙台まで 走破した ので、その続きとして今年の遠征旅行は仙台〜青森の青い森公園(国道4号起点)まで約370km程度を走ることにしていた。日程としては4/30から4日間を予定していた。

しかしながら、合計320km前後を走ったあたりの交差点で事件発生。 国道4号沿いを直進していたのだが、交差点に差し掛かったあたりで、スクーターに乗った高齢の女性が横からそのまま直進してきたのだ。こちら側はスクーターが右折してくるだろうという憶測で走行していたという確認不足と、スクーター側もこちらが停車するであろうという確認不足が重なり、そのまま衝突。

左側にロードバイク、右側にスクーターという構図での接触となり避けきれずお互いに左側に倒れ込むという事故になってしまった。幸いお互いに20km/h程度のスピードしか出していなかったので大事故には至らず、特段怪我もなかったが、ロードバイクの後輪のあたりにスクーターが折り重なるようにして倒れたため、後輪のホイールや変速周りにダメージを受けた。

転倒後に相手側から「あんたが悪いんじゃ」という言葉をかけられ頭が真っ白になってしまったこともあり、転倒直後に目視で確認した範囲ではロードバイクに大きな損傷が見られなかったことからその場で警察を呼ぶという考えにも至らず、そうこうしているうちに相手側のスクーターはそのまま走り去ってしまった。

その後一人になってから改めて後輪のあたりを確認すると、ホイールの回転にブレがあったこと以外に損傷は見られなかったため、ブレーキシューを緩めつつそのまま走行を続行しようとサドルにまたがり変速を変えようとした瞬間、「バキッガリガリガリ!」という音とともに前進できなくなった。

恐る恐る確認すると、リアディレイラーごとポッキリと折れてしまい完全に見たことのない愛車の姿がそこにあった。その瞬間自分の心も折れてしまい走行を続行する気にはならず、あえなく断念となった。後々調べてみると、リアディレイラーを使わずシングルギア化し、無理やり走行を続行するという選択も出来たといえば出来たが、そこまでは頭が回らなかった。

そこからは自転車をたたみ、最寄りの駅が2kmほどの距離にあったのでそこから電車で青森駅まで向かった。青森駅の駅前に交番があったので一応事故について申告をし聞き取り調査を受けた後、そのまま何も観光する気も起きず新青森駅から新幹線で帰途に着いたのであった。

車内でぼーっと考えてみると、計画段階での準備不足とトラブル対応力の不足が事故に繋がったなぁという感想しかなかった。考えられる要因が3つあるので改めて振り返ってみる。

要因(1): 直前での行程変更

計画段階での行程は、下記のように4日間で370km程度を走りきるつもりだった。

しかしながら、3日目の夜から4日目にかけていわゆるメイストームによる荒天が予想されていた。直前まで天気が微妙に変わり続けていたので、1日目を走り終えた段階で2日目以降の行程を決めるという状況に陥っていた。

一関の宿で1時間ほど必死にこの後走行する地点の天気予報を確認したところ、どうやら5/1までは天候がもちこたえ、5/2の夕方までに青森市に着けばそこまで荒れた天気の中走行せずに済むということがわかった。

このため、急遽下記のような行程に変更した。

2日目に2日に分けて走ろうと思っていた距離を一気に詰めるというものである。長時間の走行が必要になったため、2日目は朝の4時に起床、4時半にチェックアウトし5時に開始し20時半まで走り続けるという過酷な旅になってしまった。

また日没後の走行区間が山道に入っており、街灯がほぼなかったため、自身のフロントライトと並走する車のヘッドライトだけが路面の状況を確認する手段という非常に厳しいライドを強いられた。

これにより、3日目は出発直後からかなりの疲労が蓄積された状況で、瞬発的な判断力が落ちていたというのが実情だった。

こうならないためにも、旅行の日程をある程度前後にスライド出来るように宿を予約しておいて、天気の状況を見つつ最善の日程を選択するというのも一つの改善方法だったのかと思う。

要因(2): 予想以上に路面が悪路だった

去年の東京〜仙台間の国道4号とは対照的に、仙台〜青森間の国道4号ロードバイクにとって非常に走りづらい環境であった。それは路肩のひび割れが大変多く、また歩道も砂利や落下物が散乱していたため、「どっちを走っても辛い」「どちらかというと酷くない道を選ぶしかない」という状況が続いた。

いろいろ調べていくと、降雪後の道路上での雪解けが影響するとのことだった。

tenki.jp

時期的な問題なのかもしれないが、道路の補修が終わる頃を狙って走ったほうが良かった可能性がある。

要因(3): 2日目にもトラブルが起きていた

要因(2) で書いた悪路の影響で、実は2日目の盛岡付近を走行中に後輪が釘を踏みつけパンクしてしまった。自宅でのチューブの交換作業は経験があったものの、出先で限られた機材を使ってのパンク修理の経験がなかったため、復旧作業に非常に手間取った。

まず自身での復旧作業をその場で試みた。予備のチューブは2本持っており、そのうちの1本は保管方法が悪く既に穴が空いた状態になっていたが、気づくのがかなり遅くなってしまった。それを使って最初復旧を試みようとCO2ボンベで空気を入れていたが当然空気は入り切らず。

残りの1本は穴が空いていないことを確認してから空気を入れていると、今度は力の入れ方を誤り、携帯用空気入れを破損するという自体に陥ってしまった。このため自身での復旧作業は完全に詰みの状態となり、あえなく近場のサイクルショップに駆け込む羽目になった。

その場でチューブのみ交換をお願いし無事に走行を再開できたものの、釘で穴が空いた状態のタイヤに砂利かなにかが入りこんだのか、再びパンクが発生してしまい更に2軒目のサイクルショップでのタイヤごとの交換作業を余儀なくされてしまった。

このためパンクの発生〜完全復旧まで諸々合わせて3, 4時間も要してしまい(移動時間含む)、大変なタイムロスとなってしまった。要因(1) での行程変更も相まってこの後の走行は常に精神的にピリピリしたものになってしまい、楽しく走ることができなかった。


振り返ってみると、楽しいはずの遠征旅行が準備不足や経験不足によりただただ辛い移動をしただけに終わってしまった。

しかしながら、東北地方を移動中は多くの見知らぬ現地の方に励まされ、助けられてきたのでそれはすごく良かった。暗い話で終わるのも嫌なので、幾つかエピソードを上げてこのエントリを締めたいと思う。

  • 急な訪問にも関わらず、スピーディーにパンク修理をしてくださったサイクルタテさん
  • 2度目のパンク修理をしてくださったサイクルベースあさひさん
  • いわて沼宮内でロングライドについて気さくに話してくれたおじいちゃん
  • 岩手県岩手郡岩手町で背中を押してくださったおばあちゃん
  • 接触事故を起こした後、駅まで送ってくださった近くにいた工事現場のおっちゃん

皆さん、本当にありがとうございました&助かりました。力不足で無事完走することはできませんでしたが、貴重な経験にはなりました。


追記 (2018/05/06 14:00加筆)

帰宅後にロードバイクを購入したサイクルショップに修理に出していて、先程見積もりの連絡が来て修理費用はざっと5万円弱とのこと。ちょっと高い勉強代と考えれば、必要経費かなと思う。

修理箇所は事前に自分で見ておいた部分で大体あっていて、フレームの損傷までは到達していなかったので良かった。

依存先のnode moduleの脆弱性がGithubから通知された

今朝方、github.comからメールでこんな通知が来た。

image

よく見ると、「あんたのrepositoryの依存moduleに脆弱性があったから、このバージョンに上げると良いよ」という旨の内容。

image

実際にリポジトリを見に行くとこのような注意を促すポップアップが出ていた。

image

hoek というnode moduleに対し、 CVE-2018-3728脆弱性が発生していたらしい。

hoek node module before 5.0.3 suffers from a Modification of Assumed-Immutable Data (MAID) vulnerability via 'merge' and 'applyToDefaults' functions, which allows a malicious user to modify the prototype of "Object" via proto, causing the addition or modification of an existing property that will exist on all objects.

mergeapplyToDefaults の関数で、悪意のあるユーザーが任意のObjectを __proto__ 経由で操作できるようになってしまうというものだった。

github.com

ライブラリのcommitを辿ると今年の2/7には解消していたらしい。脆弱性情報データベース(NVD)を元に通知しているため、厳密には修正からNVDへの反映までの時間と、github.comのNVDのクロールまでの時間でタイムラグが発生してしまう。しかしながら、このように気づかなかった脆弱性にもきめ細かく対応できるので個人的にはありがたい機能だなと思った。

image

解消するとこのようにリポジトリから警告が消えたので一安心。

ES6で書かれたUserscriptでchaiとmochaを使ったテストを走らせるための小技

github.comのcommit一覧ページで、2点のcommit hashからcompareページに簡単に遷移できる Userscript を3年ほど前に開発し、最近ES6を使ってほぼフルスクラッチで書き換えた。

その際に chaimocha を使ったユニットテストを書けるように整備した。通常のjsファイルとは異なり、気をつけないと「Userscriptは動くがテストは動かない」、「Userscriptは動かないがテストは動く」といった事態に陥る。

このエントリでは、Userscriptをtestableにするために実装上気をつけた点を紹介する。

Userscript側

テストしたい関数を1つのclassに集約する

Userscriptは、ブラウザに組み込むことで何らかの補助的動作を可能にするツールである。この「補助的動作」の根幹に当たる部分を class に切り出し、それをテストケースの対象としておくと見通しが良くなる。

冒頭に上げた github-commitdiff-viewer では、

などといったロジックを CommitDiffUIManager というclassに集約させ、このclassをテスト対象とした。

Userscriptだけで動かしたい処理とテストだけで動かしたい処理を分岐させる

Userscriptとして動かしつつ、テストも実行可能なように記述するために下記のような実装を行った。

  class TestTargetClass {
    // Userscriptの機能の根幹部分を実装
  }

  if (typeof window === 'object') {
    let testTargetClass = new TestTargetClass(...);

    testTargetClass.executeSomething();
  } else {
    module.exports = TestTargetClass;
  }

module.exports はテストだけで動かしたい部分で、ここをUserscript上で実行してしまうとエラーが発生してしまう。

image

テスト側で global.window オブジェクトをUserscriptのrequire後にmockすることで、「Userscriptをテスト側でrequireしたときにはwindowオブジェクトがない」という状況を作り出すことが出来る。

let TestTargetClass = require(path.join(__dirname, '..', 'someuserscript.user.js')); // この時点ではwindowは未定義

global.window = ...

この挙動の差を利用して、 if (typeof window === 'object')true のときはUserscriptのみで動かしたい実装を記述し、 false のときはテストのみで動かしたい実装を記述することが出来る。

テスト側

jsdomを使ってUserscriptが読み込まれるページのdocumentをmockする

let jsdom   = require('jsdom');

const dom = new JSDOM(`
// Userscriptが読み込まれるページのdocumentのHTMLのうち、
// テストに必要な部分をべた書きする
`);

global.window = dom.window;
global.$      = require('jquery');

前の項目で global.window をUserscriptのrequire後に記述するとUserscriptとテストで挙動を分けることが出来る点を紹介した。

global.window にjsdomを活用することで、Userscriptが読み込まれるページをモックでき、「DOMを探索して何かする」といった挙動の関数についてもテストが可能になる。

無料で使えるGCEのf1-microインスタンスで、Grafana+Prometheusのモニタリング環境を構築する

2018年、あけましておめでとうございます。拙い内容ではあるものの、本年も頑張って技術的な試みについて発信していけたらと。

年末年始でGrafanaとPrometheusを個人VPSのモニタリング環境として構築したので、その作業ログをまとめておく。

今回構築した雑な構成図

image

私は個人の開発環境としてさくらのVPSを所有しており、

をまとめて動かしている。

GCEにおいて、USリージョンのf1-microインスタンスが無料枠(Always Free Products)として利用可能であることを昨年末に知り、せっかくまとまった時間があるのでこの機会を活用してVPSのモニタリング環境を構築しようと考えた。

アプリケーションは、昨年業務で携わった新規プロダクトでお世話になっているGrafana + Prometheusを利用することにした。

なお、このエントリで紹介する環境ではVPS側にUbuntu14.04を、GCE側にUbuntu17.10をOSとして利用している。

続きを読む