定期代を全額キャッシュバック!?
ようこそここへ。
開発部所属の西岡と申します。
今回は、暁電機にて開発した、IC定期券自動更新機にて起きた不具合についてのお話です。
某日。
IC定期券自動更新機を収めたバス会社から、異常動作が起きたので、調べてほしいとの連絡がありました。
その超常現象に巻き込まれたお客様より聞き取りをおこなったバス会社の係員から話を聞いたところ、以下の供述が得られたとのことでした。
「ありのまま今起こった事を話すぜ!俺はお金を払ってIC定期券を更新したのに、いつのまにか全額返金されていた。何が起こったのか・・・(略)」
上記の台詞は、ちょっぴり脚色していますが要は、IC定期券はちゃんと更新されたのに、お金が全額返ってくるという幸運に恵まれた、ということのようです。
・日頃の感謝を込めて?
昨今、増税や値上げまみれで、生きづらい国、ニッポン。
そんな中で、定期券代を全額返金なんて、まるで、某なんとかpay初期のキャンペーンを思わす、大盤振る舞い。
生きづらい世の中を少しでも良くするために、弊社からのささやかなプレゼント・・・なんて事はなく。
ええ、もちろん普通にソフトのバグです。
定期券を購入する際に、最終的に押す画面上の確定ボタンは、こんな見た目をしています。
定期券代を超えるお金を入金するまでは、ボタンは押せなくなっていて、こんな見た目をしています。
定期券代を超えるお金を入金することで、最初のボタンに変わり、押せるようになります。
これを押すことで、IC定期券が書き換わり、新しい定期券として使えるようになります。
もちろん、ボタンは1回押すと、押せない状態に戻るので、1回しか押せません。
・返金の謎
なぜに、自動更新機は、お金を返したのか。
IC定期券が正しく書き換わった場合は、お金を返したりはしません。
ただ、何かしらのトラブルがあって、IC定期券の書き換えに失敗した場合は、定期券の購入ができなかったということで、入金されたお金を返金することになります。
ただし今回のケースでは、IC定期券は更新されていながらも、入金されたお金が返却されているという、摩訶不思議な事が起きています。
一体何が起きたのか。
我々取材班は、現地へと急いだ。
・推理パート開始
装置内に残された、装置の動作が逐一記録されているログデータを確認したところ、衝撃の事実が明らかに。
なんと、定期券更新の確定ボタンが、2回押されていることがわかりました。
1回押すことで、IC定期券が書き換わり、そのあとにさらにもう1回押されたため、再度IC定期券を書き換えようとしました。
ただ、IC定期券は既に、同じ内容で書き換わっているため、
「書き換えられないよ」
というエラーが発生し、2回目のIC定期券の書き換えには失敗しました。
書き換えに失敗したので、入金額を全額返金した、というのが、この不可思議な事件の真相でした。
・まさか、あの名人が?
なぜ、2回押すことができたのか?
定期券購入の確定ボタンを押してから、ボタンが押せなくなくなるまでの時間は、ほぼゼロ秒(厳密には0.000000001秒ぐらい)の、とんでもなく短い時間です。
まさかこのお客さんが、高橋名人をも超える連射能力の持ち主で、このインポッシブルを可能にしたというのでしょうか?
・新たな事実の発覚
改めて、ログデータを穴があくまで見続けてみたところ、新たな事実が発覚しました。
1回目の定期券購入の確定ボタンを押すのとほぼ同時に、50円が入金されていました。
その間、約0.01秒。
あまりにも速い入金。俺じゃなきゃ見逃しちゃうね。
定期券の代金は9050円だったので、1万円の投入後、1000円ちょうどのおつりをもらうために、追加で50円を投入すると同時に、購入ボタンが押された、というのが、この時の、お客さんのとった行動とみて間違いない。知らんけど。
しかし、この行動には何の問題もなく、この行動と、2回の定期券購入のボタン押下が、一体どう結びつくのか、さっぱりわからない。
IC定期券更新機のプログラムをウンウン唸りながら眺め、画面を縦にしたり横にしたり、裏から回って見てみたり、ああでもないこうでもないと悩み続け、ふと窓の外から見えた、木から落ちるリンゴを見た瞬間、ついに理解した。この世のすべてを理解した。
・謎解きパート
真相はこう。
まず、お金が入金される前は、確定ボタンは押せない状態です。
1万円が入金され、定期券代を超えたので、確定ボタンは押せる状態になりました。
ここで、50円の入金とほぼ同時に、確定ボタンが押されました。
確定ボタンが押されたので、IC定期券が更新されると同時に、確定ボタンは押せない状態になりました。
ここで機械は50円が入金されたことを知り、10,050円の入金が定期券代を超えたので、確定ボタンが押せる状態になりました(!)
確定ボタンが押せる状態になったので、お客さんは(よくわからないけど)確定ボタンを再度押したと思われます。
そのあとの動作は、先ほど述べました通りで。
はい。現場からは以上です。
確定ボタンを押した後にも、入金に反応して、確定ボタンが再び押せる状態になってしまうことが敗因でした。
さらに調べてみると、確定ボタンが押された後、入金に反応するまでの時間は、わずか0.05秒でした。
これを過ぎると、入金が締め切られるので、仮に50円を投入しても、50円は返却口に戻されます。
この現象を再現すべく、社内でも何度も試してみましたが、100回ぐらいトライしてやっと1回できるかどうか、という高難易度ゲーでした。
お客さんは高橋名人ではないけど、凄腕のスナイパーだったようです。
おわりに:
どんなに膨大な数のテストを繰り返していても、天文学的な確率でしか起きないようなタイミングで操作をされることにより、不具合が起きてしまったりします。
大事なのは、タイミングによって動作が変わってしまうような仕組みを用いず、何をしても動作が均一となるような、シンプルな仕組みを考え出すことだと、この不具合を経て気づきました。
もう20年もプログラマを続けていますが、いまだに日々、新しい仕組みを考えたり、気づきを得たりと、飽きることなく続けられています。今後も、日々邁進していきたいと思います。
ここまで読んでいただき、ありがとうございました。