0.ご挨拶
はじめまして.
Kaede_Boxと申します.
普段は某SIerに勤務し,技術者として客先で仕事をしております.
様々な要素が重なり,少し時間ができたのでずっと始めたいなと考えていたQiitaを始めてみようと思い立ち,筆を執っています.
ゆっくり進めていくゲームが好きなので,そこらへんと絡めた記事を投稿していければと思っています.
今も初学者に毛が生えた程度ですが,ガチガチの初学者だった頃を忘れないよう,初学者向けを多く投稿していくと思います.
よろしくお願いします.
1.何を作った?
グラブルのバレット制作に必要な素材の計算機
今回はゲームの攻略ツール制作を通して,Excelとテキストエディタだけで完結する『1回限りの泥臭いデータ整形術』をまとめました.
作成した計算機はページ下部,
まとめ
部分にありますので内容に興味がない騎空士様は飛ばしてください.
筆者のグラブルの話
水古戦場が近づいてきた今日このごろ.
この無料期間の金月でフレズを交換しようと考えている人もいるのではないでしょうか.
私も年末でフレズを交換しましたがネブカドネザルを担いだガンス時代(!)で止まっていたので所持バレットはフルメタルジャケット5が4つとエーテリアルが数発のみ.
エンドポイント作らなきゃなぁ……と思ったのが今回の開発の発端です.
グラブルも進化しており,バレット作成のトレジャー用クエストが実装されたり上位バレットを選択することで下位バレットも自動で作成してくれるようになりましたが結局,今のバレット所持数での必要素材どんだけ必要なん?という疑問にぶち当たり……
ネットの海を彷徨ってもエンドポイントが実装されていない頃の計算機しか見つからず,自作しようとなりました.
2.どう作った?
1.実装に必要なデータの整理
まず必要なのは各バレットの作成に必要な素材をすべて書き出すことです.
データをぶっこ抜くわけにもいかないので地道にエクセルに書き出します.
私の経験上,こういったゲーム内部のデータを自分で整理した後,アプリケーション内部に取り込む必要がある場合,Excelで作成することをおすすめします.理由は後述.
今回はバレットの種類で絞り込み機能を付けたかったのでタイプ列を追加していますが,
名前での検索窓を実装したためあまり必要なかったかもしれません.
さて,このデータを「DBに保存し参照して計算する」か,「コード内に書き込むべきか」
ですが,今回は別にユーザーに見られても問題ないですし,外部とのデータのやり取りは色々気を使わなければならないのでハードコードすることに決めました.
ここまででとりあえずデータの整理は完了です.
2.技術の策定
今回はhtmlとJavaScriptの組み合わせです.よく見るやつですね.
理由は以下の3点から.
- グラブルがブラウザゲームという特性上スマホでプレイしている人が多いと考えられ,楽にアクセスできるブラウザのほうが役に立ちそう
- オフラインでも完結する程度の処理を行うソフトウェアから実行ファイルのダウンロードを要求されることが(個人的に)とても嫌い
- 計算内容が単純であることからわざわざメソッドの分離を行う必要を感じなかった
この時点でhtmlを用いることはほぼ確定,それに伴いJavaScriptを用いることもほぼ確定しました.
Pythonをhtmlに埋め込むこともできるようですが別にPythonに特別明るいわけでもないのでわざわざ選ぶほどではないかな,と.
以上で技術の策定は完了です.
3.データの整形
今回のお伝えしたいこと,主題です.
Qiitaでは日々キラキラエンジニアの方々が本当に参考になる記事を投稿されていますが,こういった泥臭いcsvデータを現場からありがたく頂き,泥臭く処理し,泥臭く実装している方々もこの世にいらっしゃることを実体験として知っています.一緒に頑張りましょう.
さて,流れは以下のとおりです.
- Excelにまとめたデータをcsvとして書き出し
- sakuraエディタなど置換・検索機能が充実しているテキストエディタで開く
- 得たい形式になるようにテキストエディタで検索,置換を行う
- 列の追加や削除が必要になった場合はExcelで列の整理を行う
- 3.4.の繰り返し
- データ整形完了
この工程を行うため,一度Excelにデータをまとめたわけです.
テキストエディタでの置換機能は非常に強力ですがそれは主に行について発揮されます.
列の一括削除などはやはりフラッシュフィルや挿入が簡単なExcelでの処理が合理的ですね.
1は皆さんご存知という前提で,各工程について軽く説明します.
2.sakuraエディタなど置換・検索機能が充実しているテキストエディタで開く
通常sakuraエディタでcsvファイルを開くと以下のようにギチギチに表示されてしまうと思います.

ひと目で理解できる人はそのままでいいですが私には難しかったので,csvを見やすいように設定しましょう(sakuraエディタの例です).

設定の名前 を わかりやすく変更します.ここでは "csv" としています.
ファイル拡張子 を "csv" に設定します.Windowsで言う関連付けというやつです.
最後に レイアウト 内の "通常" プルダウンを "CSV" に設定し,OK で完了です.
これで編集する下地は整いました.
3.得たい形式になるようにテキストエディタで検索,置換を行う
今回はJSON形式でデータを参照しますので以下の形式とすることに決めました.
'iron_1': {
name: 'アイアンバレット1',
type: 'パラベラム',
recipe: {
'鉄鉱石': 2,
'赤熱鉱': 2
}
}
下位バレットを含む場合は以下の通り.
'iron_2': {
name: 'アイアンバレット2',
type: 'パラベラム',
recipe: {
'鉄鉱石': 5,
'赤熱鉱': 5,
'iron_1': 1
}
}
Excelではなくテキストエディタで開くことで今後の方針が見えました.
主に以下の2点を実現する必要があるということです.
- 各文字列をシングルクォーテで囲む
- csvのデータ区切りである","を name{ のように適宜変換・挿入する
1.各文字列をシングルクォーテで囲む
これは簡単です.Excelを開きます.

文字列として扱いたい列を選択します.
2.csvのデータ区切りである","を name{ のように適宜変換・挿入する
ここに関しては申し訳ありませんがコツは1つだけです.地道にExcelで列を追加したりテキストエディタで置換したりしましょう.
気をつけなければならない点として,JSON形式のうち"{" や ":" などがある部分はセルの書式設定での一括処理ができません.
こういったときは列を挿入し,以下のように必要な記号のみの列を作りましょう.

あとは余計なコロン区切りを置換したり削除したりすることでデータの整形は完了です.
頻繁にこういったcsvデータを処理する必要があるときはもちろんツールを自作するべきですが,
1度だけ処理すればいい場合(今回のようなJSON形式のデータを作成するときなど)はこういったやり方もあるよ,ということを覚えてもらえば私の経験も浮かばれるというものです.
以上でデータの整形は完了です.
4.処理部分の実装
正直ここらへんでエンジニア諸兄からはレベルが低い,騎空士諸兄からはめんどくせぇなと思われていそうなので爆速で説明します.
今回の計算機の心臓部,計算部分です.
すでに所持しているバレットを差し引いて計算する必要があるため再帰的計算を行っています.
function calculate() {
const targets = {};
const stock = {};
const finalShortage = {};
// 1. ユーザーの入力を整理
for (const id in bulletMaster) {
const input = userInputs[id];
if (!input) continue;
// 目標数をセット
if (input.target > 0) targets[id] = input.target;
if (input.stock > 0) stock[id] = input.stock;
}
// 2. 消費・分解を行う再帰関数
function consume(id, requiredQty) {
// 在庫(作成済みのバレット、または生素材)があるか確認
const available = stock[id] || 0;
const usedFromStock = Math.min(available, requiredQty);
// 在庫を減らす
stock[id] = available - usedFromStock;
let remainingToNeed = requiredQty - usedFromStock;
// 在庫で足りない場合
if (remainingToNeed > 0) {
const item = bulletMaster[id];
if (item) {
// A: レシピがある(バレットである)ならさらに分解
for (const matId in item.recipe) {
const needPerUnit = item.recipe[matId];
consume(matId, needPerUnit * remainingToNeed);
}
} else {
// B: レシピがない(生素材である)なら不足分として集計
// IDが日本語名(生素材)の場合はそのまま表示名に、
// IDの場合はマスターから名前を引く
const displayName
= bulletMaster[id] ? bulletMaster[id].name : id;
finalShortage[displayName]
= (finalShortage[displayName] || 0) + remainingToNeed;
}
}
}
// 3. すべての目標バレットに対して実行
for (const id in targets) {
consume(id, targets[id]);
}
displayShortage(finalShortage);
}
簡単に説明すると,すでに所持している下位バレットがある場合はその下位バレットの作成に必要な素材を逆算し,目標数から引くことで集めるべき必要素材数を計算している点です.
わざわざこのようなわかりきった計算部分を提示した理由は,最近のゲーム事情です.
〇〇を作るための△△を作るための◇◇をつくるための…………と無限ループに陥ることも多々ある昨今,このメソッドをうまく使えばバレットに限らず,賢者最終のための素材なども進捗を踏まえて手軽に計算できるようになる,ということです.あわよくば騎空士でありながらプログラミング初学者の方はこれをたたき台にして賢者最終(と今後実装される超越)素材版を作ってみてくださるととても嬉しいです.完成したら教えてください.
5.UI部分の実装
こちらは大まかな枠部分を自作し,Geminiくんにぶん投げ,色や配置を整理してもらいました.
特筆することはないです.
強いて言うならユーザー操作を検知した瞬間に再計算を走らせることで [計算ボタン] のような余計な動作を挟まないようにしたところぐらいでしょうか.
3.まとめ
ソースコード (GitHub)
https://github.com/Ko-H-BOX/gbf-bulletCalc
動作デモ (GitHub Pages) 実際の計算はこちらから
https://ko-h-box.github.io/gbf-bulletCalc/
4.締め
以上,グラブルのバレット計算機を通した「泥臭い開発記」でした.
初めてのQiita投稿で緊張しましたが、コードを書いて公開する楽しさを再確認する良い機会となりました.
これからも「ゆっくり進めていくゲーム」のように,自分のペースで技術を積み上げ,発信していきたいと思います.
ご指摘,ご質問等大歓迎です.私の成長のためにも,ぜひよろしくお願いいたします.
ここまでお付き合いいただき,本当にありがとうございました.








