巨大なjsonをいい感じに閲覧する
クソゲーのデータマイニングは、gameparams.jsonのデータを見る感じとなっています。しかし、gameparams.jsonはファイル容量にして226MB、615万行、2.26億文字のかなり巨大なファイルです。一般的なテキストエディタ、(atom, sublime textなど)では開くことすらままならない上に、開いたとしても最表層だけで13000要素弱あるので、自分の求めるデータに辿り着くのは容易ではありません。
そこで、それなりに高速でそれなりに機能的なCUIビュワーを作りました。(適当なプログラミング言語が扱える人は、自分でスクリプトを書いた方が楽だとは思います。)読み込みに数秒時間がかかりますが、各命令は基本、瞬間的に動作します。
Thanks & References
- TTaro_
gameparams.jsonは以下の記事の内容を使って取得しています。さまざまな都合により、私のGithubにgameparams.jsonは存在しないので以下の記事を参考に自分で取ってきてください。
- nlohmann json
C++によるjsonファイルの読み込みにはnlohmann jsonを使っています。非常に高機能で高速で書きやすいです。
Download
- 私のGithubから github.com
Installation
- このプロジェクトのレポジトリにはjson_splitとjson_viewerが入っています。json_splitは関係ないのでjson_viewerに入ってください。
- makefileがあるのでmakeしてください。
- ビルドには、C++11以上に対応したコンパイラとnlohmann jsonが必要です。各々の環境に合わせてインストールしてください。
使い方
開き方、閉じ方
./jsonviewer.out fiilename.json
のように開きます。- (gameparams.jsonの場合)数秒の待ち時間の後、
>
のマークが表示されます。この状態の時に命令を入力することでいろいろできます。 - ctrl+c, ctrl+d, 空の命令(改行のみ)を入力すると終了できます。
命令一覧
list option
- optionと部分一致した子要素を表示する。
- 何も指定しない場合は全部表示する。
- 標準出力
find condition | condition & condition...
- 条件指定リスト
- 条件が指定できる以外の動作はlistと同じ
条件
- 条件は
ディレクトリ/ディレクトリ/要素名 = 値
のように記述する。 - 現在のディレクトリの子要素に、ディレクトリ/ディレクトリ/子要素があるかどうか検証され、ある場合は値と一致すればlistのように表示される。
- 対応しているのは数値(整数、実数)、真偽値(true, false)、文字列(""で囲まれた範囲、エスケープシーケンスには未対応)、null
- 配列はディレクトリや要素側で、
要素[0]
のように指定できる。 - 数値は大小関係(以上以下、より大きいと未満)が比較できる。
- 要素とリテラルの比較は実装しているが、要素同士の比較は実装していない。
条件の接続
- 条件は
select option
- optionは番号
- 直近のlist、findで表示した番号の子要素に移動する。
- move, backを実行するたびに番号は消える。
- エラーなどは標準エラー出力
move option
- optionと完全一致した子要素に移動する。
- エラーなどは標準エラー出力
back
- 親の階層に移動する。
- 普段は何も表示しない。
- エラーなどは標準エラー出力
dump option
- optionと完全一致した要素以下を展開して表示する。
- 4文字のソフトタブにのみ対応している。
- 何も指定しないと、直近のlist, findで表示した要素を全て展開して表示する。
- 標準出力(エラー以外)
output filename command
- filenameというファイルを作成し、commandの内容(標準エラー出力以外)をそのファイルに書き出す。
- listとdumpにしか効果はないが、commandにそれ以外のコマンドを指定しても動く。
実行例
1.全ての要素のリストを得る
list
コマンドで得られます。
2.Ohioのデータに移動する
list Ohio
で"Ohio"という文字列に部分一致する最表層の要素を一覧します。- リストの0番がその要素なので、
select 0
で選べます。
3.Ohioの全長を調べる
- 全長は、A_Hull/sizeの配列の0番目の要素に格納されています。
- 先程の状態から、
move A_Hull
、dump size
で表示されます。 - 全長は280.77mらしいです。
4.rootに戻る
back
コマンドをを2回実行すると戻れます。move
コマンドをオプションなしで実行するとrootに戻れます。
5.全ての空母のリストを得る
- 空母はtypeinfoのspeciesが"AirCarrier"になっています。
- そのため、
find typeinfo/species = "AirCarrier"
で表示できます。
6.Σ値が1.7である艦艇のリストを得る
- sigma値はA_Artillery/sigmaCountか、A1_Artillery/sigmaCountに書いてあります。
find A_Artillery/sigmaCount = 1.7 | A1_Artillery/sigmaCount = 1.7
で表示できます。
7.全長が250mより長い巡洋艦の全要素を、longCruiser.jsonに保存する
- 全長はA_Hull/sizeの0番目の要素に格納されており、巡洋艦はtypeinfo/speciesが"Cruiser"になっています。
- よって、これを満たす要素のリストは、
find A_Hull/size[0] > 250 & typeinfo/species = "Cruiser"
で得ることができます。 - その状態でdump命令を実行すると、表示されている全要素を出力するので、その中身をoutputコマンドでlongCruier.jsonに書き込みます。
- コマンドは、
output longCruiser.json dump
となります。
終わりに
- 命令は全て標準入力から読んでいるので、適当なテキストファイルにクエリを書いておいて、
./jsonviewer hoge.json < query.txt
のような感じで自動化できます。 - 命令のパーサー(特に文字列周り)がゲボカスなのはわかってます。気が向いた時に直すかもしれませんが、クソゲーのマイニングに使う分には問題ないので直さないかもしれません。
- バグ等あれば、Twitterかissueで優しく(再現できる条件を)教えてください。
update note 2021/4/19
- 配列は値ではなく無名要素で構成されたオブジェクトとして扱うようにした。