[007] 自宅を外向発売所に近づけた後の話

 

コロナ禍による無観客開催、ボートレース場の一般入場禁止というとてもつらい事態から3年半程が経過しました。

えっ、もう3年半…という所ですが、最近は場内の賑わいもすっかり戻って来まして、24場をグルグルする活動も復活、来月を以って5周目が終わろうかというところです。

さてそのコロナ禍の時に書いた話の続きです。

「本場に行けないなら自宅に外向発売所ばりの環境を作りたいぞ」ということで2つのツールを開発しました。複数場の映像をタイル状に表示するマルチビューなWebページと、Javascript+PHPで動作させる締切タイマーです。

こんな感じでしたね。

マルチビューの方はストリーム取得元をBoatcast配信のものにしたりCSSをいじったりと非常に細かい変更をしましたが、タイマーの方は3年半ずっと同じ見た目で運用しておりました。展示進入がわかって、締切がわかって、そしておまけ機能としてチルト+1.0以上の時は「↑TILT」マークが画面に出る、という機能で、まあ十分ですよね。割と満足しておりました。

でもやっぱり「風」を感じたいよね…

というわけで、いつかはやろうかなーと思っていた「風」に関する情報を表示させる機能の追加を、やりました!というお話。3年半越しの大型アップデートですね。

 

展示の取得時に風の情報を取る

進入やチルト角度が取れるんだから風の情報も簡単ですよ、たぶん。だって同じページに書いてあるんですから!と思ったのですが、なかなかにこれが面白い作りになっていて、展示情報を取るためのPHPスクリプトも工夫が必要なやつでした。

まずボートレース公式サイトの風の情報はどこにあるのか。他の情報も同様なのですが各レースの「直前情報」のページを開くと右下に出てきます。こんなの。

なんとなくここから情報が取れそうな気がしますね…ということでソースを眺めてみると「いけそう」感が増してきます。

<div class="weather1_bodyUnit is-wind">
<div class="weather1_bodyUnitLabel">
  <span class="weather1_bodyUnitLabelTitle">風速</span>
   <span class="weather1_bodyUnitLabelData">3m</span>
</div>
</div>
   <div class="weather1_bodyUnit is-windDirection">
   <p class="weather1_bodyUnitImage is-wind11"></p>
</div>

「風速」はズバリ書いてありますねー。3mって書いてある辺りを取れれば良さそうです。で、問題なのは風向きで、風速のように文字で何かを表しているわけではない、ということで風向きの違う別のレースと幾つか見比べればわかるのですが、キモは「is-wind11」というところで、このis-windの後の数字が1~17まで変化することによって、それに対応した矢印の画像を表示しています。

数字が1だったら真上を向いた矢印「↑」となり、5なら右を向いた矢印「→」が出ます。9なら「↓」で13なら「←」で…とここまでくれば簡単。360を16分割して22.5度づつ角度が違う矢印を時計回りに表示させているわけです。

じゃあ17は何かと言えば「無風」で、透明な画像が表示されます。無風だからね。
と、風速と風向きの表示の仕掛けがバッチリわかった所で実際に情報を取ってみましょう。

まずは風速を取る処理はこんなの。

// 風速
if(preg_match('/締切予定時刻が変更されております/', $html )){
    $xpath = '(/html/body/main/div/div/div/div[2]/div[6]/div[2]/div[2]/div[1]/div[3]/div/span[2])';
} else {
    $xpath = '(/html/body/main/div/div/div/div[2]/div[5]/div[2]/div[2]/div[1]/div[3]/div/span[2])';
}
$xpath_record = $domXPath->evaluate($xpath);

if (! empty($xpath_record = $domXPath->evaluate($xpath))){
    if (is_string($xpath_record)){
        $result_windspeed = $xpath_record;
    } else {
        foreach ($xpath_record as $node){
           $result_windspeed = $node->textContent;
           $result_windspeed = str_replace('m', '', $result_windspeed);
        }
    }
}

最初のifで風速の書かれている場所を、Xpathという形式で指定しています。転覆艇が出たり発走を見合わせたりして大幅に遅延が発生すると展示情報のページに赤文字で「締切予定時刻が~」と表示されて、風速の書かれた場所が一段ズレるんですね。ということでその文言があるかないかの判定をしています。

2番目のifが実際に指定した場所の文字を取っています。上記例なら「3m」が取得できます。でも後々利用するのに「m」はいらないよね。ということで最後のstr_replace関数でmを空欄とリプレース、つまり消しています。これで $result_windspeedには「3」が入りました。

次に風向きです。

// 風向き
if(preg_match('/締切予定時刻が変更されております/', $html )){
    $xpath = '(/html/body/main/div/div/div/div[2]/div[6]/div[2]/div[2]/div[1]/div[4]/p)';
} else {
    $xpath = '(/html/body/main/div/div/div/div[2]/div[5]/div[2]/div[2]/div[1]/div[4]/p)';
}
$xpath_record = $domXPath->evaluate($xpath);

if (! empty($xpath_record = $domXPath->evaluate($xpath))){
    if (is_string($xpath_record)){
        $result_winddirection = $xpath_record;
    } else {
        foreach ($xpath_record as $node){
            $result_winddirection = $node->getAttribute('class');
            $result_winddirection = str_replace('weather1_bodyUnitImage is-wind', '', $result_winddirection);
        }
    }
}

取得する箇所をXpathで指定しているのは一緒ですが、2つ目のif文の中身がちょっと変わっています。なかなか難しかったのは「$result_winddirection = $node->getAttribute(‘class’);」の行なのですが、これは対象のXpathの「クラス名」を取得する処理です。

この処理で$result_winddirectionには「weather1_bodyUnitImage is-wind11」という文字が入ります。最初にHTMLソースを眺めた時に出てきた文字列ですね。あとはここから欲しい情報を切り出します。そこは風速の「m」を削ったのと同様、str_replace関数で「weather1_bodyUnitImage is-wind」を空欄とリプレースしてやれば、残るのは「11」というわけです。

以上、2つの処理を展示情報を取る時に追加することで、風速と風向きが取得できるようになりました。
これが出来たらもう勝ったようなものです。

 

ちょっと罠があったぞ

やはり安易に「勝ったな」と思う時には落とし穴があるものです。3周2マークでも気を抜いてはなりません。

展示データを収集していて気付いたのですが、進入とチルト角のデータがNULL(取れてない)なのに風のデータが入っている、そういうデータが出来上がっている時がちょくちょくあるのです。

現在のレースの直前情報ページばかり見ていたので気付きませんでしたが、気象情報に関しては先のレースのページまで全部入っているのですね。例えば1Rに風速3mの情報が入っていると、残りの2~12Rのページにも同じ情報が表示されているのです。

つまり展示が終わっていない状態でも気象情報が取れてしまう、ということです。
展示データが入った個別ファイルの作成は「何か1つでもデータが入っていれば」行われる仕様だったので、展示が終わっておらず進入・チルトがNULLでも気象情報が取れてしまうためにファイルがそのまま作られてしまう、ということですね。一度ファイルが出来たらもう一回やる事はないので風速データはタイマー上に表示されないまま。これはちょっと罠でした。

対策は比較的簡単で、展示データの取得時に「進入データが取れなければ残りの全ての処理をキャンセルする」という判別処理を入れるだけです。これなら進入→チルト→風、の三段階の処理の最初のセクションで止まるので安心ですね。

 

風速と風向きの画像を頑張って作る

これは地道に地道にがんばりました。

世の中のハイパークリエーターはフォトショなのでレイヤーを駆使してあれこれやってしまうのでしょうが、そっち系ツールがてんでわからないのでLibreOffice Impressで形を作ってGIMPで拡縮したり背景を透明化したりと、地道にやりましたね。他の画像もそんな感じ。

風速の数字は0~4mまでは大して影響が出ないので白、5~7mはさすがに影響が出始めるので黄色、8~15mまでは危険を伴い中止の可能性すら出てくる赤文字、という感じにしてみました。風速15m以上は数年やってて見たことが無いので割愛。中止だろそんなもん。

あと風速0の場合、オフィシャルでは透明画像を使っていますがタイマー上では透明だと間が抜けた感じになるので、ひとまずターンマークの画像を表示させることにしました。不動っぽいイメージありますもんね。

 

実際に表示させてみる

既に全てのデータは揃っているわけですから、展示終了後に進入枠番(舟のアイコン)を表示する際に、データに対応した画像を出すだけです。これは画像を表示する処理を増やすだけなので簡単。

で、でたー!「←1」と出ているのがそれです。ちょっと感動。
まあこれで処理としては完成みたいなものですが、せっかくの3年半ぶりのアップデートなわけですから見た目をもう少しなんとかしましょう、と思いました。まずは「展示」がクソださいのでなんとかします。

うん、まあそこそこなんじゃないでしょうか。実際は縮小されて表示されるのでここまで解像度高くなくてもいいんですが、小さすぎると今度はジャギーが目立つようになりますしおすし。それと風速の所に「m」がないのでこれも作ってくっつけることにします。

いいですねー!なんかそれっぽくなりました。

世の中に他にこんな用途のタイマーは無いので「それっぽい」っていうのもおかしな話ですが。しかしこの舟のアイコン、まあまあのやっつけ感といいますか、記号的にシンプルな三角形なのはいいんですが、もう少しなんとかならないの??と思ってしまいました。ならばやるしかない。

GIMPで2時間くらい格闘した結果こんなのができました。

あら!ちょっといい感じになったんじゃないでしょうか。さすがにあの三角形よりは100億倍くらい見た目がマシになった気がします。複雑な絵柄になった分、視認性はどっこいだけど解像度は爆上がりしているので、拡大にも耐えられる感じになったはずです。

 

 

風の表示方法をひねった方がいいと思った

風向きのデータなのですが、数字が1だったら「↑」となり、5なら右を向いた矢印「→」が…うんぬんと解析の段落で書きました。最初はその通り画面に出していたんですが、オフィシャルサイトでは舟の向きが右を向いており「↑」はすなわち右から(本場スタンド側から)の横風、ということになるわけです。

でもこのタイマーは舟のアイコンが常に上向きです。データが「1」で右からの横風であれば「↑」ではなく「←」と表示された方が視覚的にも混乱が無くていいわけです。まあこれは風向きデータに対応する矢印の画像を変えればいいだけなので、ファイルのリネームで対応可能です。

データが1なら「←」、データが5なら「↑」……と90度づつズラしていきます。ここはプログラミングじゃなくて地道な変更作業。オフィシャルと比べて左に90度傾いた矢印が常に出るように調整するだけですね。

 

 

最終的にこうなった

もう展示のところ、全然違いますよねーウワー!
3年半ぶんのアップデートにふさわしい感じになったと思います。チルト警告表示とも被っておらずレイアウト的にもまとまったのではないでしょうか。

 

これでほぼ完成かなー

待望の「風」の見える化が出来てしまったので、もう追加する機能、あんまり無いんですよね!
しばらく運用しながら考えてみようかとは思いますが。

今回も色々と勉強になりましたね!