WacomのペンタブをX上でつかう
タブレットデバイス
タブレットデバイス(いわゆるペンタブ)は、絵や文字を描くときに便利な入力デバイスである。マウスやトラックポイント、タッチパッドに比べて遥かに自然に線などを描くことができる。
X上で使う上での問題点
X上では、タブレットデバイスは、スクリーン全体にマッピングされる。スクリーンののアスペクト比と、タブレットデバイスの物理的なアスペクト比がほぼ一致している場合はそこまで問題にならない。しかし、マルチモニターなどによって、スクリーンとタブレットデバイスのアスペクト比が大きく異なる場合、普通に書き込むと描いた内容が引き伸ばされる。また、スクリーン上の小さな領域に描画したい場合、タブレットデバイスの非常に小さな領域に描く必要があり、物理的なセンサー面の殆どが無駄になる。
私のデスクトップ環境は、2560x1600のモニターの右側に3840x2160のモニターを並べたマルチモニターとなっており、スクリーン全体は6400x2160の大きさである。一方使用しているタブレットデバイスはセンサー面のサイズが21600x13500の16:10のアスペクト比となっている。スクリーン全体のアスペクト比を縦10に変換すると、29.63:10となり、倍弱ほど横長なスクリーン領域となる。そのため、普通にタブレットデバイスをマッピングして描くとかなり横に伸びてしまう。
私のデスクトップ環境
普通のマッピングで描いた様子、横にかなり引き伸ばされる。
目的の状態
- この問題を解決するために、タブレットデバイスをウィンドウに合わせてマッピングする。
- ウィンドウのアスペクト比とタブレットデバイスのアスペクト比が異なる場合、センサー面が無駄になることを許容して、アスペクト比を保つ。
横長のウィンドウへのマッピング
縦長のウィンドウへのマッピング
正しくマッピングされたウィンドウに描いた様子
対処法
- xinputコマンドを用いることで、タブレットデバイスがマッピングされるスクリーン上の領域を変更できる。
xinput set-prop <device id> Coordinate\ Transformation\ Matrix <affine transformation matrix>
<device id>
で、タブレットが割り当てられているIDを選択する。<affine transformation matrix>
は、マッピングされる領域を変換するアフィン行列を展開した9つのfloatの値を入力する。
device idを調べる
xinput list
で繋がっているデバイスのリストが得られる。- ここでは、
Wacom One by Wacom M Pen stylus
がそれで、idは11であることがわかる。
- ここでは、
$ xinput list ⎡ Virtual core pointer id=2 [master pointer (3)] ⎜ ↳ Virtual core XTEST pointer id=4 [slave pointer (2)] ⎜ ↳ ELAN0678:00 04F3:3195 Mouse id=14 [slave pointer (2)] ⎜ ↳ ELAN0678:00 04F3:3195 Touchpad id=15 [slave pointer (2)] ⎜ ↳ TPPS/2 Elan TrackPoint id=17 [slave pointer (2)] ⎜ ↳ Wacom One by Wacom M Pen stylus id=11 [slave pointer (2)] ⎜ ↳ Wacom One by Wacom M Pen eraser id=19 [slave pointer (2)] ⎣ Virtual core keyboard id=3 [master keyboard (2)] ↳ Virtual core XTEST keyboard id=5 [slave keyboard (3)] ↳ Power Button id=6 [slave keyboard (3)] ↳ Video Bus id=7 [slave keyboard (3)] ↳ Power Button id=8 [slave keyboard (3)] ↳ Sleep Button id=9 [slave keyboard (3)] ↳ Integrated Camera: Integrated C id=12 [slave keyboard (3)] ↳ Integrated Camera: Integrated I id=13 [slave keyboard (3)] ↳ AT Translated Set 2 keyboard id=16 [slave keyboard (3)] ↳ ThinkPad Extra Buttons id=18 [slave keyboard (3)] ↳ Solid State System Co.,Ltd. LCS USB Audio id=10 [slave keyboard (3)] $
$ xsetwacom --list devicesp Wacom One by Wacom M Pen stylus id: 11 type: STYLUS Wacom One by Wacom M Pen eraser id: 19 type: ERASER $
アフィン変換行列を求める
- xinputの
Coordinate Transformation Matrix
の引数にはアフィン変換行列を与える。 - スクリーン全体にマッピングされた状態から、目的の状態への変換行列を求める必要がある。
- 具体的には、原点(左上)を中心に、ウィンドウサイズに合わせてスケーリングを行う変換行列と、ウィンドウの左上に合わせて平行移動を行う変換行列の積を求める。
スケーリング
- ウィンドウのアスペクト比とタブレットデバイスのアスペクト比が異なる時、マッピングされる領域のアスペクト比とタブレットデバイスのアスペクト比が同じになるようにする。
- つまり、マッピングされる領域がウィンドウからはみ出す。
- これを行うためには、以下のデータを収集する必要がある。
平行移動
- ウィンドウの左上の座標がスクリーン上でどこになるかを求める。
- ウィンドウの位置
xdotool getwindowgeometry <window id>
- スクリーンのサイズ
xdpyinfo
xrandr
- ウィンドウの位置
実装
- 上に示したようなコマンドを実行して結果をパースし、アフィン行列を計算、xinputでペンタブを設定するプログラムを実装した。
付録(それぞれのコマンドの出力)
- $で始まる行はコマンド入力である。
- ペンタブのサイズ:
xinput watch-props <device id>
$ xinput watch-props 11 Device 'Wacom One by Wacom M Pen stylus': Device Enabled (163): 1 Coordinate Transformation Matrix (165): 1.000000, 0.000000, 0.000000, 0.000000, 1.000000, 0.000000, 0.000000, 0.000000, 1.000000 Device Accel Profile (290): 0 Device Accel Constant Deceleration (291): 1.000000 Device Accel Adaptive Deceleration (292): 1.000000 Device Accel Velocity Scaling (293): 10.000000 Device Node (287): "/dev/input/event13" Wacom Tablet Area (300): 0, 0, 21600, 13500 Wacom Rotation (301): 0 Wacom Pressurecurve (302): 0, 0, 100, 100 Wacom Serial IDs (303): 891, 0, 2, 0, 0 Wacom Serial ID binding (304): 0 Wacom Proximity Threshold (305): 30 Wacom Pressure Threshold (306): 26 Wacom Sample and Suppress (307): 2, 4 Wacom Enable Touch (308): 0 Wacom Hover Click (309): 1 Wacom Enable Touch Gesture (310): 0 Wacom Touch Gesture Parameters (311): 0, 0, 250 Wacom Tool Type (312): "STYLUS" (289) Wacom button action 0 (313): 1572865 Wacom button action 1 (314): 1572866 Wacom button action 2 (315): 1572867 Wacom button action 3 (316): 1572872 Wacom Button Actions (317): "Wacom button action 0" (313), "Wacom button action 1" (314), "Wacom button action 2" (315), "None" (0), "None" (0), "None" (0), "None" (0), "Wacom button action 3" (316) Wacom Pressure Recalibration (318): 1 Wacom Panscroll Threshold (319): 1300 Device Product ID (288): 1386, 891 Wacom Debug Levels (320): 0, 0 $
- ペンタブのサイズ:
xsetwacom --get <device name> Area
$ xsetwacom --get "Wacom One By Wacom M Pen stylus" Area 0 0 21600 13500 $
- ウィンドウのジオメトリ:
xdotool getwindowgeometry <window id>
- ウィンドウのID:
xdotool selectwindow
$ xdotool getwindowgeometry $(xdotool selectwindow) Window 4194313 Position: 1280,0 (screen: 0) Geometry: 1280x1600 $
- スクリーンのサイズ:
xdpyinfo
$ xpyinfo | grep dimensions dimensions: 6400x2160 pixels (1684x568 millimeters) $
- スクリーンのサイズ:
xrandr
$ xrandr | grep Screen Screen 0: minimum 320 x 200, current 6400 x 2160, maximum 16384 x 16384 $
ThinkPad X13 Gen 3 (AMD) 良かったよの話
- 少し前にパソコンを新調した。
- 結構良いマシンだと思ったのでレビューする。
主なカスタマイズ
- CPU: Ryzen7 PRO 6850U
- RAM: 32GB
- Battery: 54Wh (4 cells)
- Display: 2560x1600
- Keyboard: English, backlight
- SSD: WD-black 1TB (replaced)
- WLAN: Qaulcomm QCNFA765
購入の決め手
- ThinkPadのトラックポイントキーボードを1年ほど前から使っており、気に入っていた。
- 2022年末におけるAMDの最新のモバイルプロセッサを積んでおり、そこそこ処理が速い。
- TDPは28Wしかないのにも関わらず、200W消費するi9 9900K(自宅のデスクトップパソコン)とほぼ同じ性能らしい。
- intelの同じグレードの製品であるi7 1280Pと比べた時、グラフィック以外の処理性能はほぼ互角。
- グラフィック性能に優れ、その上で電力効率も高い。
- また、価格も数万円安い。
筐体、キーボード、排熱、バッテリーなど
- MacBookPro 2018 13inchから乗り換えたので、結構分厚いなという印象を受けた。
- ThinkPadの外付けキーボードに比べるとキーストロークは浅い。レイアウトは同じで、キーボードとして一般的な(失敗できる)価格なので、ThinkPadが気になる人は試してみると良いだろう。
- バッテリーについて、Zoomで常に2560x1600の画面共有を映しながらの100分の講義には余裕で足りるが、2コマ目の半分ぐらいで尽きる。
- この状態での消費電力(powertopで確認)は16W程度だった。
- 排熱機構は底面から吸気して右手側に排気する一般的なもの。筐体は樹脂製なのでパームレストまで熱くなることはないが、高負荷時キーボードの横の部分に触れるとそこそこ熱くなっているのを感じる。
- 参考までにCPUフルロード+Google Chrome上のYouTubeで1080pの動画を再生しているときの消費電力(powertopで確認)は最大30W程度だった。
- ベンチマークサイトによると、45W程度まではいくらしいが、CPUとGPUの両方に高負荷がかかるタスクはそんなに多くないだろうと思う。
- マイクは普通。スピーカーの音質はとても良いとは言えないが、これはMacBookを除くほとんどのノートパソコンでもそうだろう。
ソフトウェア
- Linuxを入れて使う場合、バージョン1.25より前のBIOSにはバグがあるらしく、アップデートが必要らしい。
- Debian GNU/Linux 11において、ネットワークアダプタとマイクのファームウェアがなかった。
- 12のnon-freeにはあったが、インストール時に使えなかったので、RJ-45のコネクタがあるに越したことはないだろう。
- WindowsとUbuntuは割と正常に動作していたと思う。(あまり試していないけど)
総評
- キーボードとトラックポイントが使いやすく、もうこれなしでは生きていけないかもしれない。
- たまに古いマシンを使うと存在しないトラックポイントに指をおいてしまう。
- CPUの処理性能がほぼ互角で、マルチモニターにしてもグラフィック性能に余裕があるので、前に使っていたノートパソコンだけでなく、デスクトップパソコンの役目も置き換えてしまった。
- ThinkPadでRyzen 6850Uを搭載できるものはX13とT14sしかないので、グラフィックと電力効率を重視するユーザーにとって、これらはX1以上に有力な選択肢かもしれない。
- キーボードにこだわりがないなら、より大容量なバッテリーを搭載したLG gramや、色々な意味で高水準なMacBookProも候補になると思う。
自作ウィンドウマネージャとほげWM
- Linuxを快適に使うために、X上のウィンドウマネージャを自作した。
- 生のX、または自作ウィンドウマネージャに関する日本語の情報はほとんどないので、これを書こうと思う。
1. ウィンドウマネージャとHOGEWM
1.1. ウィンドウマネージャとは
広く用いられているGUIデスクトップ環境は、ソフトウェアが一定の画面領域、ウィンドウを操作することで成り立っている。そのウィンドウの位置や大きさを変更したり、入力するウィンドウを選択したりするのがウィンドウマネージャである。
1.2. WMを自作すべきな理由
- 自分で設計したキーバインドで、自分で設計した動作をさせることができるため、非常に快適に操作でき、生産性が高まる。
- パソコンがより好きになる。
1.3. HOGEWMとは
1.3.1. リポジトリ
- https://github.com/void-hoge/hogewm
- 詳細な機能やインストールの方法はREADME.mdを参照
1.3.2. 主な特徴
- ほぼ全てのウィンドウ操作をキーボードのみを用いて行える。
- マルチモニタ環境での使用を前提とした設計。
1.3.3. 主な機能
私の環境ではMod1はAltキー
バインド | 動作 |
---|---|
Ctrl-Mod1-i | ウィンドウの選択 |
Ctrl-Mod1-n | 選択したウィンドウを隣のモニターに移動 |
Ctrl-Mod1-s | 全てのウィンドウをモニターごとに入れ替え |
Ctrl-Mod1-m | 選択したウィンドウを最大化 |
Ctrl-Mod1-h,j,k,l | 左下上右寄せで選択したウィンドウを半分にする |
Ctrl-Mod1-1 | urxvtを起動(ソースコードから変更可) |
Ctrl-Mod1-2 | emacsを起動(ソースコードから変更可) |
Ctrl-Mod1-3 | google-chromeを起動(ソースコードから変更可) |
Ctrl-Mod1-t | 全てのウィンドウをタイル配置 |
Mod1-1,2,3,4 | バーチャルスクリーン1-4に切り替え |
Ctrl-Mod1-a,d | 隣のバーチャルスクリーンに選択したウィンドウを移動 |
Ctrl-Mod1-r | 選択したウィンドウを最前面に配置 |
画面全体のSSを$HOME/screenshots/に保存 | |
Ctrl-Print | 選択したウィンドウのSSを$HOME/screenshots/に保存 |
Mod1-leftdrag | ウィンドウの移動 |
Mod1-rightdrag | ウィンドウのリサイズ |
2. 開発に入る前に
- 開発に入る前に、開発環境とその使い方を知る必要がある。
2.1. 使用している主なソフトウェア
- OS: Debian GNU/Linux 11.3 bullseye(no desktop environment)
- X: 1:7.7+22
- テキストエディタ: Emacs, Atom
- ウェブブラウザ: Google-Chrome
- ターミナルエミュレータ: rxvt-unicode
- Python 3.9.2 (GCC 10.2.1)
2.2. Xが起動するざっくりとした流れ
startx
を実行$HOME/.xinitrc
に書かれたコマンドが順に呼び出されるので、そこにWMやターミナルエミュレータを入れておく。- 最後に実行するものは、処理が戻らないように末尾に&をつけない。
- 以下の
.xinitrc
では、urxvtが最後に起動する。そのため、urxvtをexitなどで終了するとXorgが落ちる。
#!/bin/sh xset +fp $HOME/.local/share/fonts/ xrdb $HOME/.Xdefaults xmodmap $HOME/.Xmodmap xset r rate 200 40 setxkbmap -option ctrl:nocaps -option terminate:ctrl_alt_bksp $HOME/hogewm/hogewm 2> /dev/null & emacs & urxvt -geometry 80x35-64-0
2.3. WMを起動する
私の環境では、上記の
.xinitrc
の下から3行目でWMを起動している。あなたが作っているWMを起動するコマンドをこれと置き換えればhogewmの代わりにそれが起動する。ただし、WMを2つ以上同時に起動すべきではない。なぜならキーバインドが衝突して後から起動した方が動かなくなるからである。
- WMを
.xinitrc
の末尾に置くべきではない。末尾においた場合、WMを終了したときにXサーバーが終了してしまう。- 開発初期のWMというのは不安定で頻繁にクラッシュするし、開発中はWMを幾度となく再起動するだろう。これでは都合が悪い。
3. 自作する上でのTIPS
- ここまでで、WMを実行することまではできるようになった。
3.1. 他のWMを動かして、読もう
- 自分が書こうとしている言語で書かれたWMの動作を観察して、ソースコードを読むのは必須に近い。
- GitHubでは言語を指定した検索もできるので、window managerとかで調べれば良いプロジェクトがたくさん見つかる。
- 推奨する(私が使った)WM
3.2. Xlibの仕様を読もう
- Xのラッパーライブラリを操作してWMを作ることになる。その仕様書を読むこともまた、必須に近い。
- もとはC言語用のライブラリで、仕様書は英語だが、幸い日本語の翻訳が存在する。
- ウィンドウマネージャを作るときに重要となる項は、ウィンドウ情報関数、イベント、イベント処理関数などだと思う。
- また、Arch Linux WikiとForum、Stack Overflowなどの技術系掲示板がたまに役に立つ。
3.3. 他のWMを使おう
- 開発中もX上でコードを書いたり、それを実行したり、ブラウザで音楽を聴いたりすることもできる。
- しかし、ウィンドウマネージャなしでそれらを制御するのは不可能ではないが非常に難しい。
- そのため、開発初期は他人が作ったWMをを使うべきだ。
- 上記のWMを使うのが手っ取り早い。
3.4. 一つのウィンドウで開発しよう
- 開発初期のWMは、入力フォーカスを切り替えることすらままならない。
- そのため、一つのウィンドウで全ての開発に必要な操作が完結するほうが良い。
- 同じウィンドウ上でターミナルエミュレータが使えるテキストエディタを使うと良い。
- 私はEmacsを使ったが、まともなエディタならたやすくできるだろう。
3.5. ログを出そう
エラトステネスの篩の高速化
少し前に某会社の採用試験問題(?)の解説みたいな感じでエラトステネスの篩が話題になっていたので書こうと思う。C++を使うよ。
エラトステネスの篩とは
std::vector<int> simple_eratosthenes(const long long limit) { std::vector<bool> data(limit+1, false); data[0] = true; data[1] = true; for (long long s = 2; s*s <= data.size();) { for (long long i = s*s; i < data.size(); i+=s) { data[i] = true; } s++; while (data[s] == true) { s++; } } std::vector<int> result; for (long long i = 0; i < data.size(); i++) { if (data[i] == false) { result.push_back(i); } } return result; }
やったこと
- 最初から偶数を取り除いておくのと同様に、2, 3, 5, 7...など任意の数までの倍数を取り除けるようにした。
- 2の場合だと、のみが残る。
- 3を含めると、のみが残る。
- 5を含めると、 のみが残る。
- これらのそれぞれを別々の実行スレッドに投げて並列化する。
- 2の倍数を取り除くと0.5倍、3の倍数まで取り除くと0.33倍、5の倍数まで取り除くと0.267倍というようにメモリの消費量も減る。
- それぞれに素数は同じ感じで分布しているらしいので並列化のムラはほとんどない。
実装関係の話
- 上記の
simple_eratosthenes
を使って探索範囲の平方根までの素数を求める。simple_eratosthenes
はメインの探索を行いながら、動的に篩うための素数を探しているが、マルチスレッド化するためにはこの方法だと別のスレッドからデータを読まなければならない。これはだるい。シングルで事前に計算した方がいい。
- 各スレッドで、各素数を篩うときに開始位置を算出する必要がある。(例えば、を満たすxを求める。(答えは ))
- シングルで求める比較的計算量が大きい部分はこの二つだが計算量は程度なので、メモリの確保やメインの処理に比べれば雀の涙。(メモリの確保の方が圧倒的に時間がかかる。)
時間計測
- 私のノートパソコン(MacBook Pro (13-inch, 2018, Four Thunderbolt 3 Ports))で行う。CPUはIntel(R) Core(TM) i5-8259U CPU @ 2.30GHzで、メモリは8GB 2133 MHz LPDDR3
- コンパイラはgcc version 10.2.0 (Homebrew GCC 10.2.0_4)を使い、最適化オプションを盛る。
- 前述の篩うための素数を探す計算と、開始位置を探す計算は無視する。(1012までやっても14msしかかからない。)
- メモリの確保にかかる時間は無視する。(今回やりたい評価には無関係なので)
- 結果の素数をカウントし、その個数を以て正しさを評価する。
- 素数の個数については、みんなの知識 ちょっと便利帳に掲載されているものを使う。
結果
- 何個の素数を使って分割するかを
base_sieve_size
で表す。 - thread数、圧縮率以外の単位はミリ秒
- すべて一発取りなので結果はあくまで目安
base_sieve_size | 3 | 4 | 5 | 6 | 7 |
---|---|---|---|---|---|
thread数 | 8 | 48 | 480 | 5760 | 92160 |
圧縮率 | 3.75 | 4.375 | 4.8125 | 5.21354 | 5.53939 |
107 | 1 | 1 | 12 | 309 | 44406 |
108 | 10 | 6 | 13 | 307 | 52329 |
109 | 684 | 109 | 57 | 325 | 60774 |
1010 | 15246 | 7033 | 907 | 696 | 62785 |
1011 | 208788 | 177030 | 68373 | 8994 | 58088 |
- 結果は全て正しかった。
考察など
- 問題サイズを大きくした場合、大量のスレッドに分割した方が速くなっている。
- 問題を細分化したことにより、一つ一つのスレッドがキャシュに乗るようになり、動作が高速になったものと思われる。
base_sieve_size = 7
の時は基本的に遅いが、問題サイズによる変化が最も小さいので、1012以上の大きさならばより高速に動作する可能性がある。
- 1011を
base_sieve_size = 6
で計算するために、すでに2.23GBのメモリ領域を使っている。メモリが足りないので1012までを一気に求めることはできない。- 計算結果を順次捨てながらメモリ領域を次のスレッドに引き継ぐようにすればメモリ不足は解消できるが、それは別の機会にやると思う。
ソースコード
巨大な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
- 配列は値ではなく無名要素で構成されたオブジェクトとして扱うようにした。