Skip to main content

Salmon Statsで使われている技術

tkglingAbout 2 minNintendoSalmon Run

Salmon Stats

今回、大型アップデートを行い 3.6.1 -> 4.0.0 へとバージョンアップをしました。

この変更には破壊的変更が多く含まれ、データベースの情報もほとんど一から再構成しました。なぜこの変更が必要だったのか、この変更によるメリットは何なのかを説明していこうと思います。

データベースの変更

変更点のうち、データベースの変更について解説します。

スケジュール ID

前回まではスケジュールを指定するためのschedule_idはランダムなuuid_v4が利用されていました。しかしこれはクライアントからschedule_idを知るための方法はいちいちスケジュール用の API を叩くしか方法がなく、また uuid はインデックスに不向きという弱点がありました。

これに対応するのがcuidなのですが、今回はインデックスの生成という点は無視してmd5で計算したハッシュを利用することにしました。

フォーマットは非常に簡単で、${MODE}-${RULE}-${STAGE_ID}-${START_TIME}-${END_TIME}-${WEAPON_LIST}になっています。${WEAPON_LIST}はカンマ区切りで繋げた文字列で、${START_TIME}${END_TIME}は UNIX 時間です。

これを計算すると、例えば

REGULAR-REGULAR-2-1695369600-1695513600--1,-1,-1,-1

Hash(MD5): 774337f791a69723ed071a8884b816a7

が得られます。プライベートバイトでは${START_TIME}${END_TIME}がない(NULL が入っているため計算不可能)ので${MODE}-${RULE}-${STAGE_ID}-${WEAPON_LIST}の MD5 をとったものがschedule_idになります。MD5 はただの 128 ビットのハッシュですので当然衝突する可能性がありますが、実現可能なスケジュールの組み合わせでは衝突する確率はほぼないと思って大丈夫です。衝突したらそのときにまた何か考えます。

このようにschedule_idをスケジュール自体から計算可能にすることにより、ID を予め計算しておくことが可能になりました。

Cascade の対応

当たり前のようで対応できていなかったのがこの Cascade です。

自分も詳しくわかっていないのですが、リレーション関係にあるフィールドが変更されたときに一方が変わればもう一方のテーブルも変わるような仕組みです。これがなかったためデータベースの変更が非常にめんどくさくなっていました。

型の変更

データサイズをなるべく小さくするため、Integerに代わってSmallIntなどを利用しています。

不要なフィールドの削除

どのクライアントからアップロードされたリザルトなのかを示すupdated_byclientを削除しました。実質使っていなかったので当然の対応です。

id -> uuid に名前を変更

以前はschedule_id, result_id, id, uuidなどと id 系が乱立していましたが今回は SplatNet3 から提供される uuid に関しては全てuuidと命名するようにしました。

uuidplayTimeでリザルトのユニーク性を担保しているのですが、よく考えたら同じシナリオで同じタイミングで遊ぶとデータが被るのではないか......という予感がしています。

それもこれも同じシナリオで同じ uuid を返す API の仕様が悪いのですが被った際には何らかの対応をしたいと思います。

リザルト ID

将来的に自分のリザルトを取得する機能をつけたかったので、リザルト ID を返すような仕組みを作りました。

Salmon Stats(SP2 向け)では auto increment した数値を使っていたのですが、今回は自分のリザルトは自分しかアクセスできない仕組みにしようと思っているためこれを使うといろいろと推測できてしまうので ID の仕組みを一新しました。

API の変更

サーバー側の変更点について解説します。

Deprecated

実質 API サーバーは Salmonia3+が利用する前提なのですが、旧バージョンではフォーマットやバージョニングがめちゃくちゃになっているので非推奨であることを明示しました。

アプリの対応が済み次第、これらの API は利用不可になります。

Results

以前までは Salmonia3+形式でしかアップロードができませんでしたが、今回からはサーバーの内部でこの変換を行うようにし SplatNet3 形式をそのままアップロードすることができるようになりました。

ただ、なんかバグで今のところエラーが起きるみたいですが......

このアップデートでアプリ及びライブラリ開発者はめんどくさい変換のコードを書く必要がなくなり、実装コストが大幅に低下しました。また、Salmon Stats にさえミスがなければデータ登録が簡単にできるようになりました。

Histories

以前はスケジュールの追加は裏で Google App Scripts が実行することで追加していましたが、それとは別にユーザーが API を叩いて追加できるようにしました。

この API も SplatNet3 形式を直接解釈できるようにしているので、簡単に利用可能です。

Salmon Stats の動作で一番困るのは「書き込もうとしたリザルトに対応するスケジュールがない」ということなのですが、リザルトを書き込む前に Histories の API を叩けば取得可能なリザルトに対応する全てのスケジュールが書き込まれるので安全というわけです。

Schedules

こちらが以前 Google App Scripts で実行されていた箇所なのですが、ユーザーからも実行できるようにしました。

いつリリースされるんですか

任天堂がアプリを利用しているユーザーを何らかの方法で検知してBAN をすると警告open in new windowしてきたため、これに対応するべくアプリのアップデートが必要な状況でした。

結局のところ「正規アプリ以外で SplatNet3 にアクセスしないでください」ということだと思います。

しかしながら、アプリをアップデートしてもサーバーが対応していなければ意味がなかったためまずは先にサーバーをアップデートしていました。なのでアプリ自体にはまだ何も手が入っておらず、いつリリースできるかもわからない状況です。

サーバーをアップデートするにあたってデータベースにおける無理解が生み出していた技術的な負債を一気に解決することにしました。この点におきましてはご助力いただいたエンジニアの方々に感謝申し上げます。

今後の展望

BAN 対策として(BAN を回避するような方法ではありません)必要な技術を別の方に開発して頂いたため、リリースまでに必要なタスク、ビジョンなどははっきりしている状況です。

時間さえあれば開発自体は二週間程度で対応できるのではないかと思っています。

とはいえ、現在いろいろな案件を抱えている状況ですので空き時間の全てをアプリの開発に割り当てることができません。ここはご理解をよろしくお願いします。

少なくとも十月末までは別件の作業があるのでサーバーのバグ修正以外には手がつけられないと考えていただけると幸いです。

Last update:
Contributors: tkgstrator