美味しい平面の煮込み方

意味はあるが特に意味はない事を書く

Smash.ggのAPIに-2くらいつけられた所から大会結果を抜き出すまでキャラ対した結果

f:id:hzk_428:20211211205344p:plain
特に意味のないげむち(みすたーげーむあんどうぉっち)

顔と顔を合わせない時代だからこそ大袈裟に感情は伝えろ!!!!!!!!!!!
わかりました!!!!!!!!!!!!!!!!!!!
私、ちゃんとはっきり気持ちを伝えます!!!!!!!!!!!!!!!!!!!!!!!!!!!






人類滅
bどうも平面人です。

※この記事は寝椅子さん(寝椅子 (@newenwere) | Twitter)主催の
スマブラ Advent Calendar 2021
の12月12日担当で作成した記事です。


2021年もあっと言う間に最終盤。
日本国内の大型オフ大会とか再開し始めましたね~~~~~~~~~~~👼👼👼👼👼👼👼👼👼
激動の一年だ。


お気持ち表明はここまで。
あ、去年のアドベンドカレンダーではこういう記事を投稿してました。平面人です。
キモいというか、お友達ができなさそうな内容だな!!!!

hzk-428.hatenablog.com




とても冗長なブログなため開幕目次です。
対戦よろしくお願い致します。

■目次

1.今年のテーマと書いたきっかけと宣伝のおはなし

今年は平面人がどーのとかの話題ではありませぬ。
いんふぉめ~~~しょんてくのろじ~~~というか、一種のでぇ~~~え~~~っくすなお話です。


仁義なき戦いのはじまり

皆さん、smash.ggはご存じでしょうか?



そうですね、スマブラをはじめとした対戦ゲームの大会管理、トーナメント、参加者管理と大会の参加等ができるサービスですね。
ここに登録しておけば他に大会管理とトナメ管理が一括でできるサービスが実質ないようなものなので
とりあえず大会参加する時便利になるので登録&本名非公開設定しておくと良いでしょう。

smash.gg



ちなみにAPIが公開されており、例えばAPI経由でデータ取得、トーナメント管理等ができるようになっております。
まあ用意されているインターフェースのものしか取れないのは悪しからずではありますが。


要するに過去に開催された大会と参加者、リザルト情報の取得が可能になっています。
いちいち全部ブラウザから手でコピーしたら4ねるのでお助かりです。


ただ先に言っておくとこのAPI、いわゆるREST APIではないAPIで要は
すんげぇわかりづらいという問題があります。


ドキュメントも英語しかないため、ITおよび英語にアレルギーがある場合、即死するような状況。
参考になるような個人記事も殆どない。
日本語で一番参考になるのがこちらの記事。

www.youtube.com






あ、ちがうちがうこっちこっち。

qiita.com




あ、でもチャンネル登録みんなしようね。


話を戻しますね。
このブログを書くきっかけとなったのはP-さん主催のJPR作成プロジェクトでした。

JPR作ろうぜプロジェクトについて

名の通りJPR(ジャパンランキング、スマブラSPのオフライン大会実績に基づくランキング)を作るプロジェクト。
目的はいわゆる名刺的な意味合いでのプレイヤーの強さの共通基準として使えるようにするため。
あとはデータについては篝火のシーディングで使うため。

プロジェクト人員は篝火スタッフさんが中心。
ほーずきさんはスタッフではないのですが(何ならクロブラのスタッフも降りた)
技術面フォローの面でお呼ばれしました。
仕事でアプリ作らない方の人間だけどまあいいでしょう!

このプロジェクトの大きなタスクは以下の2つと認識しています。

①大会のシード決め、シード序列設定に置いて信頼できるランキングを作成する
②上記目標の達成のため、大会情報を長期的に取得、保存、管理する

①達成のためには②の達成が先行しないといけないです。
①については算出式や条件となる大会やポイント計算とかいろいろあるけど
とりあえず②をやらないと話がはじまらない!
ってことでほーずきさんはSmash.ggのAPIと殴り合いをはじめたのでした。めでたし。


なおプロジェクト内で作成するJPRはじゃくさん作成のJJPRをはじめとした
個人作成のものとはまた違う観点での作成となります。

日本国内ランキング作成に興味のある方は主催がP-さんなのでこちらにお問い合わせいただければと思います。
モチベがある人が多いに越したことがありません!!
むしろランキング作成やAPIに関しては有識者ニキ様各位には
どしどし参加いただければ!!!!!!!!助かります!!!!!!!!!!!!
ぜひぜひよろしくお願い致します。

twitter.com

ブログを書いた動機

ま、まだ全然めでたしな地点には到達してませんけどね!
兎にも角にも取っ付きにくいAPIとなんとか少しは和解できたっぽいです。

JPR作成のために大会データの取得が必要だよ

APIまじでわかりづらいよう ぬぁぁ

今後同じ場所で苦戦する人が出ないように備忘録をつけよう

お、ちょうどアドベンドカレンダー企画あるじゃん。じゃ、これで。。。

これがブログを書いたきっかけです。


あわよくば誰か私よりも使いこなして便利なサービスを作ってくれねぇかなぁ~~~~という欲はあります。

最初はいいけどこのクエリがな……な……
少なくとも普段PCをがっつり触らないお仕事される方もれなく全員バイバイ不可避なので……
参考になれば幸いです。

次からはAPI使ってみよう~サンプルクエリ~ほーずきさん脳内のおはなしです。


2.とりあえずAPIを叩いてみよう、話はそれからだ

Smashggに限らず、API実行のためには認証をしてくれるトークンの発行が必要です。
トークン……人間がユーザ名とパスワードを打ってエンターを押す行為が、一意の文字列になったもの。これを送りつければデータ取得等の行動が認証される。今はそういうことにしておいてください。

やり方は前述の記事内に紹介があるリンクを踏んで、Create New Tokenをするだけ。
出力されたトークン文字列は、忘れないようメモ等しましょう。

qiita.com


トークンが手に入ったらAPIを実行できます。
今さらAPIについて軽く説明すると要は条件とか指示を特定の書式で書いて
Enterすればなんかしてくれるモノと考えておいてください。
ネット経由でトークンによる認証さえ通っちゃえばなんかのソフトとか入れずに使えるので便利!!!

ですが、今回はどなたでもお試しいただきたいという気持ちがあるので
SmashggのAPI公式で用意されている実行環境を使います。

以下下記リンク先にあるエクスプローラーでデータ取得等行うことにします。
まあ理解が金トロッコの速度に追い付いている方は
適当にcurlできる環境でぽちぽちすればいいのかなと思います。

developer.smash.gg


f:id:hzk_428:20211206215814p:plain

こんな画面が出て来ます。テスト実行のため、以下手順を実行してみましょう。


トークンを左上のAuth tokenの欄に貼り付ける


②下記クエリをAuth tokenの欄の真下にある欄に貼り付ける

query TournamentQuery($slug: String!) {
  tournament(slug: $slug) {
    id,
    name,
    countryCode,
    addrState,
    city,
    isOnline,
    startAt,
    numAttendees
  }
}

なんの呪文なのかは今は何も考えないでおいてください。


③画面の左下が実はまた別の欄があるので上に引っ張っておく

f:id:hzk_428:20211206220211p:plain
初見殺しポイントです

境界のあたりにマウスポインタを置くとサイズ調整の表示に変わるので
見える位置になる程度に移動させておいてください。


④Query Variablesとある欄に下記を入力。思考停止で。

{
  "slug": "5-kagaribi-5-1"
}


⑤Auth tokenの欄の左にあるCD再生ボタンみたいなやつをクリック。

クエリが実行され、画面の右部分に結果が出てきます。


f:id:hzk_428:20211206220434p:plain


なんと!篝火#5の大会情報が書かれています。
そーです、今実行していただいたのは大会情報を取得するAPIでした。

もしもエラーが出てしまった場合はここまでの手順の中で何かが抜けている可能性が高いです。
エラー文は英語で返されるので、適宜Googl●翻訳をかけつつ対処していきましょう。

もしも大会情報が出てきたのなら大成功です。
もうあとは欲しい情報を指示して取得するだけ!!!

……なんですが此処からが一番厄介です。
理屈すらいらねえ!!!という場合は5.サンプルクエリまで飛ばしていただければと思います。

ただやっぱりアレは何これはナニっていいうものが出てくると思いますので
そうなった際に手前の文章を読んでいただけたらと思います。

3.悩んだらTournamentQueryをパなせ!

結論。
大会に関わる情報の取得は9.5割、TournamentQueryをパなせば手に入ります。

TournamentQueryというのは、先ほどお試しで入れてもらった文字のうち、query TournamentQueryとあった部分のことです。


Smash.ggのAPIに特化して説明してしまいます。
先頭に入れていたquery という指示語の後にSmashggに指示するフォーマットを指定してあげます。
フォーマットになるものの種類はいくつかあります。

下記リンク先にあるドキュメントの、INPUT OBJECTSにあるものがフォーマットの種類になります。
が、大会に関する情報はぶっちゃけTournamentQueryで取れるので
他についてはやりたいものに応じて使っていけば良いと思います。
大会進行とか……?

developer.smash.gg


ちなみにTournamentQueryはどの大会についてか、という情報の指定が必須となります。
それが下記の部分になります。

{
  "slug": "5-kagaribi-5-1"
}


先ほどつかったクエリを例に解説します。

query TournamentQuery($slug: String!) {
  tournament(slug: $slug) {
    id,
    name,
    countryCode,
    addrState,
    city,
    isOnline,
    startAt,
    numAttendees
  }
}

このAPIクエリは『
TournamentQuery を パラメータslugを使って実行!
tournament の要素を返してください。
具体的には中括弧の中にあるidとかnameとかです。
』というのを書いていました。


tournamentという指示フォーマットで手にはいる情報ですが、上のサンプルでは下記情報を指定していました。
id … 大会自体の固有のID
name … 大会のお名前
countryCode … 大会開催国のコード。日本はJPでアメリカはUSって出て来る
addrState … 設定してあれば開催州、日本で言えれば都道府県が出て来る
city … 設定してあれば市区町村が出て来る
isOnline … オンライン大会であるかどうか。true=オンライン false=オフライン
startAt … 大会開始日時のタイムスタンプ。数字だけどエクセルとかで変換すれば年月日時分秒が帰ってくる。
numAttendees … 参加者人数

英語にはなりますがドキュメントは存在するので、適宜翻訳をかけながら探ってみましょう。


4.slugってナニ?!

そろそろslugという謎ワードについて解説します。
ぶっちゃけると大会ごとに固有に設定できる一意の単語と思ってください。

これの何が便利かというとURLに書いてあるのですぐわかるというところです。

例えばEVO2020のslugはevo-japan-2020です。

https://smash.gg/tournament/evo-japan-2020

これがあらゆる大会についているので見たい大会のslugはurlを参照して取得しましょう!!!


5.サンプルクエリ

まあとにかく書いてドキュメント読んでいけば
そのうちわかる!!!!!!!!!!!!!!!!!!!!!!!!!!はず。

大会情報の取得
query TournamentQuery($slug: String!) {
  tournament(slug: $slug) {
    id,
    name,
    countryCode,
    addrState,
    city,
    isOnline,
    startAt,
    numAttendees
  }
}
イベント情報の取得

smash.ggにおいては大会は大枠、イベントは中で実施するトナメを指すと思えばOK。
例えばシングルスとダブルスで別のトーナメントになっていれば
イベントも別枠となる。

query TournamentQuery($slug: String!) {
  tournament(slug: $slug) {
    events {
      id,
      name,
      videogame{
        displayName,
        name
       }
    }
  }
}
イベントにおける順位一覧の取得

pageは迷ったら1を指定
perPageは1ページあたりの出力数。
例えばTOP32までなら32を指定する。

query TournamentQuery($slug: String!,$page: Int!, $perPage: Int!) {
  tournament(slug: $slug) {
    events {
      standings(query: { page: $page, perPage: $perPage }) {
        nodes {
          standing
          player{
            prefix,
            gamerTag,
            user{
              discriminator
            }
          }
        }
      }
    }
  }
}
特定大会の特定イベントの特定個人の戦績の取得

戦績が文字列で入っているため、直接扱いづらい形式になっています。。。
後述しますが適宜取得後も加工しないと厄介です。

query TournamentQuery($slug: String!,$page: Int!, $perPage: Int!,$eventIds: [ID],$playerIds: [ID]) {
  tournament(slug: $slug) {
    events{
      standings(query: { page: $page, perPage: $perPage }) {
        nodes {
          player{
            sets(filters:{ eventIds: $eventIds, playerIds: $playerIds }){
              nodes{
                fullRoundText,
                round,
                displayScore
              }
            }
          }
        }
      }
    }
  }
}

サンプルQuery Variables
篝火#5におけるしゅーとん選手の対戦戦績の場合は下記を指定。
(ここまで出てきたクエリでidを取得すればあのidはアレっていうのはわかるはずです)

{
  "slug": "5-kagaribi-5-1",
  "page": 1,
  "perPage": 1,
  "eventIds": "592466",
  "playerIds": "226829"
}

そもそも特定選手の対戦戦績を出すために
トーナメント(大会)→イベント→順位→プレイヤーと迂回しているのが玉に瑕。
もっとスマートに取得できる方法を募集。



6.Smashggにおけるデータの小ネタ

IDとかdiscriminatorとか

データ管理において一意に識別するためのもの達です。
Smash.ggにおいてはIDは数値が、User等のdiscriminatorは文字列になっています。

集計においては選手や大会の名称ではなく、こちらを使う必要がありますっていうおはなしです。


PlayerとUserと大会参加時の名義の区別

Smash.ggの中ではPlayerとUserという似て非なる概念が存在する。
基本的には
 Player … ゲームのプレイヤーとしての情報
 User … プレイヤーの個人情報
と捉えればOKです。

具体的にはプレイヤーの参加名義、所属チーム等のプレフィックス
Playerから取得します。

gamerTagがプレイヤー名、prefixが所属チーム等の略称です。
しゅーとん選手で言えばgamerTagがShuton、prefixがSST

Userでは固有コード、誕生日、BIO等が取れます。
Userにおけるnameは本名ですが、これは非公開設定にしてあればnull(そこに何もない)
が返されるので安心です。

ちなみに選手名についてはEvent内のEntrantでも取得できます。
恐らくは参加した時点での名義になるのかな?


Pythonラッパー

サランラップ的な意味の方に近いラップです。
Pythonで呼び出せる奴が存在するっていうのをはい!てんぷらちゃんに教わりました。

github.com

こっちは細かいクエリの指定をせずにラッパーの中でAPIクエリに変換して実行してくれるみたい。
Pythonチョットワカルな人ならこっちを使った方が開発面でも便利かも。

かくいう私も来年くらいにはこいつを使い始める予定。
主に出力データの加工とかで呼び出しをここからやればいいかなあという意味合いで。




7.今後の課題とか

とりあえず大会関連のデータは抜けるようになりました。
しかしやることはまだまだあります。

①フォーマット変換

現状はエクセルで集計できるようCSV変換して溜め込む設計でいます。
エクセルで集計していく想定のためです。

APIで返却されるうちdata要素だけ必要なので他を削りたい
必要に応じてブレイクダウンされた要素を横に並べたいので
変換用のスクリプトは最低限書かないとなあと考えてます。

このへん個人でランキング出力している方々どういう設計でいるのでしょう。
意見交換したい次第。

取得と変換をpython内でちゃちゃっと完結したみ。


②データの集積と今後の集計

現状はまだいいのですが、将来的に開催大会、参加者はどんどん増えていきます。
CSVファイルを出して個人で集計をかける……のもしんどくなるのかなと見込んでます。

DBを立てるとか、CSV置き場を作って置き場を直接覗ける集計ツール使うかとかは
いつかは考えないといけないかも。

究極論、Smash.ggに行けば誰でも取れるデータではあるのでBigQueryとかでオープンで突っ込んでいって
有識者ニキ、なんかレポートくれ~~~~とかできたらモチベニキ達がいろいろできそうでいいよなあとか。

もろもろ、金銭的なコストが出そうなのでそこも検討したいですね。
場合によっちゃ令和トナメとの相談になるのかなあ。
規模が読めないので想像の範疇ですが。





ぽわぽわ考えていると延々と語ってしまいそうなので今回の記事はここまで。
進捗があればブログ等で共有ができればと思います。


ここまで閲覧いただき、ありがとうございました!