見出し画像

全プレイヤー検索方法の紹介(TGR氏によってアーカイブされたSMM2の内部データの利用方法)

こんにちは。スライムと申します。今回はなぜかあまり知られていない、TGR氏によってアーカイブされたSMM2のデータ(以下datasetと呼ぶ)について、閲覧方法から利用方法まで解説していこうと思います。(PC必須です)
私が過去にみんバト試合数が多い職人やバトル勝率が低い職人を発見していたのを見た方もいるのではないでしょうか。それは全てこのdatasetを使って見つけています。これを使えばみんバト試合数ランキングや切断数ランキング、みんクリランキングの完全版を作成できます。

datasetを用いればこのような職人も簡単に発見できます。他にも色々見つけているので私のツイートを確認してみてください。

それでは、これから解説していきます。以下目次です。


アーカイブされた内部データの閲覧

TheGreatRambler氏(@tgr_code)が2022年2月ごろに全ての職人、コース、またハックンタイムアタックなどのデータをアーカイブすることに成功しています。
まずはこのアーカイブの利用方法を解説していきます。今回は職人のアーカイブを使用してみます。

Parquetファイルの閲覧方法

Parquetファイルに職人のアーカイブが保存されているので、ファイルの保存と、Parquetファイルを開く方法を解説します。

↑このサイトにアクセスしてParquetファイルを保存します。

ここから保存できます

しかし保存するだけでは閲覧できないのでParquetファイルの閲覧方法について記載しておきます。
Parquetファイルを開くには、.NETをインストールした後、ParquetViewerをインストールします。

↑ .NETのダウンロードサイト

↑ ParquetViewerのダウンロードサイト

どちらもダウンロードできたらParquetViewerを起動しましょう。起動するとこのような画面が表示されます。

では先程保存した職人に関するParquetファイルをViewerで開いてみましょう。

左上のFileをクリックすると上の画像のようになります。今回はファイルを開きたいので、Open File をクリックします。そして任意のParquetファイルを選択するとデータを閲覧することができます。↓

ファイルを開くときにこの画面が表示されますが、これは閲覧したいデータを選択できる機能です。便利。
職人のParquetファイルは6つに分割されているので、一気に閲覧したい場合はファイルをすべてフォルダにまとめてOpen Folderで開くといいと思います。


実は、ファイルを開いただけでは1000個分(1000人分)のデータしか閲覧できません。全員分のデータを閲覧したい場合は右上の Record Count に右下の数字(今回は5935222)を入力します。こうすることでファイル内のすべてのデータを閲覧できます。

Viewerの機能について

ここで、Viewerの機能について解説します。

このデータから特定の名前の職人を探す場合は
WHERE name ='xxxx' と入力します。(xxxxに任意の名前を入力)
また、みんなでバトルの試合数が10000を超えている職人を探す場合は
WHERE versus_plays >10000 と入力します。
詳しくは画像左上の Filter Query を押すと検索方法が丁寧に記載されているのでそれを見てください。


ここでdatasetを使いこなすための問題を書いておきます。
[問]"ざらしぃ"さんのdata_idを特定せよ。(答えはこの記事を読んでいくと出てきます)


ここまでの解説で気づいた方がもしかしたらいるかもしれませんが、実はこのデータには職人IDが記載されていません。
しかし、データに記載されている data_id から職人IDを割り出すことが可能です。ということで職人IDの特定方法について解説します。

"data_id"を利用して職人IDを特定する

ここからは利用方法ではなくdata_idと職人IDに関する基礎解説なので興味がない人はここを飛ばして職人ID特定自動化ツールの解説と使用方法からまた見てください。

"data_id"とは?

data_idは簡単に言ってしまえば職人登録順です。通し番号とも呼ばれています。世界のコース(オンライン)に初めて接続して職人のmiiと名前を登録すると、登録した順(厳密には違う)にdata_idがそれぞれの職人に振り分けられ、data_idの数字によって固有の職人IDが与えられます。
data_idを見ると古参か新参かが分かります。

職人IDからdata_idを特定する

data_id→職人IDの前に、職人ID→data_idを出してみましょう。ここではkrith氏のgoogleドキュメントを参考にしました。(↓にURLを記載しておきます。)

これはコースIDの仕様となっていますが、職人IDもほぼ同じ仕様でした。
googleドキュメントを見れば大体分かるかもしれませんが一応手順を説明します。

  1. 職人IDは0~9とA,E,I,O,U,Zを除く30文字で構成されています。これを30進数に変換します。(30進数とは、0~9とA~Tの30文字を用いる進数です。)例えば、4→4,B→A,L→I,Y→Tとなります。

  2. 30進数になったIDの並び順をにします。その後2進数に変換します。

  3. 44桁の2進数が出てくるので、左から4,6,20,1,1,12桁の6つに分けます。(分けた数をそれぞれA,B,C,D,E,Fと置きます。)A=1000,D=1,E=1(Eはコースか職人かを判別するもので、コースなら0、職人なら1となります。)

  4. 数をF,Cの順に並べて32桁の2進数を作ります。この数と定数1680E07C(16)の排他的論理和(XOR)を計算して、求めた数をNとします。

  5. このNがdata_idと一致します。

ちなみに上の手順にて出てこなかったBですが、
B≡N-31(mod64)となっています。

これで職人IDからdata_idを算出することができました。

次に本題であるdata_idから職人IDを算出する方法を解説します。
…気づいた方がいるかもしれませんが上記の手順を逆から行うことで算出できます。(Bを求める必要があるので少し面倒ですが。)

data_idから職人IDを特定する

  1. data_idを用意します。(この数をNと置きます。)

  2. Nを2進数に変換します。

  3. N(2)と定数1680E07C(16)の排他的論理和(XOR)を計算します。出てきた32桁の数をX(2)と置きます。

  4. X(2)を左から12桁と20桁に分解します。12桁の数をF、20桁の数をCと置きます。

  5. Bを求めます。B≡N-31(mod64)で求められます。

  6. A=1000,D=1,E=1と、手順4,5で求めたB,C,FをA,B,C,D,E,Fの順に並べて30進数に変換します。

  7. 出てきた9桁の数を逆に並べます。

  8. 使われていない文字を考慮して職人IDに変換します。 

手順8については下の画像を参照すると分かりやすいかと思います。
例えば、4→4,A→B,I→L,T→Yとなります。

data_id→職人IDの時は上から下に、職人ID→data_idの時は下から上に変換しましょう。

これでdata_idから職人IDを算出することができました。
しかし職人IDを特定するのにこの作業を毎回やっていては日が暮れるので私はID特定自動化ツールを作成しました。

職人ID特定自動化ツールの解説と使用方法

自動化ツールについて

先程data_idから職人IDを特定するための手順を紹介しました。これをPythonを用いて自動で算出できるように試みました。
↓にコードを記載しておきます。

# data_idを外部から入力
data_id = int(input("data_idを入力してください: "))

def bitxor(a, b):
    return a ^ b

result = bitxor(data_id, 377544828)
binary_result = bin(result)[2:].zfill(32)  # 左側に0を追加して32桁にする

F = binary_result[:12]
C = binary_result[12:]

B = bin((data_id - 31) % 64)[2:].zfill(6)  # 2進数に変換し、6桁にする

combined_string = "1" + "0" * 3 + B + C + "1" + "1" + F

decimal_base_value = int(combined_string, 2)  # 10進数に変換

import numpy as np

thirty_base_value = np.base_repr(decimal_base_value, 30)

reversed_thirty_base_value = ''.join(reversed(str(thirty_base_value)))  # 逆順に並び替える

reversed_lowercase_value = reversed_thirty_base_value.lower() # 小文字に変換

player_id = (
    reversed_lowercase_value
    .replace('a', 'B')
    .replace('b', 'C')
    .replace('c', 'D')
    .replace('d', 'F')
    .replace('e', 'G')
    .replace('f', 'H')
    .replace('g', 'J')
    .replace('h', 'K')
    .replace('i', 'L')
    .replace('j', 'M')
    .replace('k', 'N')
    .replace('l', 'P')
    .replace('m', 'Q')
    .replace('n', 'R')
    .replace('o', 'S')
    .replace('p', 'T')
    .replace('q', 'V')
    .replace('r', 'W')
    .replace('s', 'X')
    .replace('t', 'Y')
)

print(player_id)

詳しい解説は割愛しますがこれを用いることで職人IDを算出できます。
…これPythonがないと使えないじゃんと思った人も多いはず。しかし、実は誰でも使えます。次は使用方法について解説します。

職人ID特定自動化ツールの使用方法について(実践編)

このツールはGoogleアカウントがあれば誰でも使用可能です。↓のサイトにアクセスしてください。

Googleアカウントを使ってログインした後、ファイル>ノートブックを新規作成をクリックします。その後コード入力欄に上記のコードをコピー&ペーストしてください。そしてセルを実行します。そうすると↓の画像のようになります。

この画面になれば成功です。


試しにみんバト配信者であるざらしぃさんの職人IDをdata_idを用いて特定してみましょう。まずはParquetViewerでざらしぃさんを見つけます。
(WHERE name = 'ざらしぃ')

data_id = 1356110

次にGoogle Colaboratoryを用いて職人IDを特定します。

ざらしぃさんの職人IDが54TKFX9MGと特定できました。
最後に、本当にこのIDが合っているのかをSMM2のゲーム内で確認してみます。

しっかり一致しました。使用方法は以上になります。

Excelで使用可能な特定自動化ツール

Excelでもdata_idから職人IDを特定するための関数を作成したので公開します。(実は先にExcelの関数から作ってました)


=SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(LOWER(CONCAT(MID(BASE(DECIMAL(1000&DEC2BIN(MOD(D2-31,64))&RIGHT(BASE(DECIMAL(BITXOR(D2,377544828),10),2,32),20)&1&1&LEFT(BASE(DECIMAL(BITXOR(D2,377544828),10),2,32),12),2),30),(257-ROW($A$1:$A$256)),1))),"a","B"),"b","C"),"c","D"),"d","F"),"e","G"),"f","H"),"g","J"),"h","K"),"i","L"),"j","M"),"k","N"),"l","P"),"m","Q"),"n","R"),"o","S"),"p","T"),"q","V"),"r","W"),"s","X"),"t","Y")


↑これをコピーしてExcelの任意のセルにペーストすると使えます。

また、職人IDからdata_idを特定する関数も一応作成したのでこれも公開しておきます。


=BITXOR(BASE(DECIMAL(RIGHT(BASE(DECIMAL(CONCAT(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(H4,"B","a"),"C","b"),"D","c"),"F","d"),"G","e"),"H","f"),"J","g"),"K","h"),"L","i"),"M","j"),"N","k"),"P","l"),"Q","m"),"R","n"),"S","o"),"T","p"),"V","q"),"W","r"),"X","s"),"Y","t"),(257-ROW($A$1:$A$256)),1)),30),2),12)&MID(BASE(DECIMAL(CONCAT(MID(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(H4,"B","a"),"C","b"),"D","c"),"F","d"),"G","e"),"H","f"),"J","g"),"K","h"),"L","i"),"M","j"),"N","k"),"P","l"),"Q","m"),"R","n"),"S","o"),"T","p"),"V","q"),"W","r"),"X","s"),"Y","t"),(257-ROW($A$1:$A$256)),1)),30),2),11,20),2),10),377544828)


(職人IDのはハイフン無し、半角大文字で入力しないとエラーが起きます)
これで解説を終わります。

最後に-tgrcodeとMakerCentralとの比較

今回解説したdatasetの他にも
tgrcode↓

https://tgrcode.com/mm2/docs/

MakerCentral↓

などの検索ツールが知られていました。そこで、この3つを比較してみます。

dataset

メリット
・ほぼ全ての職人、コースを検索可能
・いいね数やバトルランク、レートなど絞り込み可能
デメリット
・データが2022年2月ごろのものなので古い
・PC必須

tgrcode

メリット
・IDを入力すると現在のデータを取得可能
デメリット
・IDが無いと検索できない

MakerCentral

メリット
・コース名、プレイヤー名を入力すると検索できる
・現在のデータを取得可能
デメリット
・いいねを貰っていない(もしくはコースを投稿していない)プレイヤーは出てこない

それぞれメリットとデメリットがあるのでそれぞれの特性を生かしてうまく利用することが大事です。
私はよく未知の職人(みんバトやみんクリなどで有名だけれども職人ランキングに載っていないので職人情報を見ることができないような職人)を探しているのですが、探し方としてはまずMakerCentralを使い名前を検索する→出てこない場合はdatasetを使い検索する→tgrcodeを使って現在のデータを確認する
このような手順で探しています。ぜひ参考にしてください。

ここまで読んでくれてありがとうございました!PCがあれば利用可能ですし、職人だけでなくコースも検索できますし、ハックンタイムアタックの記録なども見ることができるので是非、利用してみてください!
質問や相談などがあればDMしてください。できる限り答えます!

この記事が気に入ったらサポートをしてみませんか?