Omnigraph
Graph engine for context assembly. Object-storage native. Agents work with graph data the way engineers work with code: branched, typed, reviewed, merged, audited, and governed.
FFLogs のログを軽減タイムライン・A/B比較・PT構成検索として読み解く Laravel アプリ。FFLogs API v2 (GraphQL) を利用
Translation pending
DataPHP · BladeGitHub @velstauOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗FFLogs のログを読み解くための Web ツール集。FFLogs API v2(GraphQL)から戦闘ログを取得し、 サイトのUIでは出せない切り口で集計・可視化する。
UIの共通ルール・変更範囲・ブラウザ検証は docs/UI-DESIGN-SYSTEM.md を参照。
設計の詳細・ファイル間の連動仕様は docs/ARCHITECTURE.md を参照。
| 画面 | 何をするか |
|---|---|
軽減(GET /mitigation → POST /analyze) | 1つのログをタイムライン化し、ボスの攻撃ごとに「誰が何を撃って何%軽減できていたか」を並べる。バリア・シナジー・効果時間の途切れ(バフブレイク)まで判定する |
DPS比較(GET,POST /compare) | 同じボスの2つのログを A/B で突き合わせ、フェーズ別・分別に火力とローテーションの差を出す。グラフ上で範囲選択すると GET /compare/range でその区間だけ再集計し、フェーズカードを範囲の値に置き換える。共有画面では作成時に取り置いた 10 秒区間の集計から GET /shared/{id}/range で出す(閲覧者のキー不要) |
PT検索(GET,POST /party-search) | ジョブ構成を指定して一致する討伐ログをランキングから探す。FFLogs のUIはロール人数(タンク2/ヒラ2…)までしか絞れないため、ジョブ単位の照合はAPI経由でしか実現できない |
初めて検索するボスは討伐ログのプール構築に数十秒かかる。これをリクエストの中で待つと
リバースプロキシの読み取りタイムアウト(nginx 既定 60 秒)に掛かるため、待たずに「準備中」を返し、
取得は応答を返しきったあとに行う。画面は GET /party-search/status をポーリングし、整いしだい自動で再検索する。
事前に温めておくこともできる。
php artisan fflogs:warm-pool 1085 # エンカウンターIDを指定
php artisan fflogs:warm-pool --zone=76 # ゾーン内の全ボス
解析結果の「URLで共有」から、APIキー不要の共有画面を作成できる。有効期間30日。 作成時のブラウザで共有停止可能。プレイヤー名などの詳細も共有される。 操作・保存先・運用・検証は docs/TIMELINE-SHARING.md を参照。
composer install
cp .env.example .env
php artisan key:generate
利用者が自分のキーを設定する。 画面の「API キーを設定する」(/api-key)で、FFLogs の
https://www.fflogs.com/api/clients/ で作成した Client ID / Client Secret を入力する。
app/Support/FFLogsCredentialStore.php(置き場所)、app/Http/Controllers/ApiKeyController.php(画面)、
app/Http/Middleware/RequireFFLogsCredentials.php(実行前の確認)、bootstrap/app.php(案内への変換)開発で .env のキーを使いたいときだけ、次のように書く。公開環境では書かない(運営者のキーを他人に使わせないため)。
利用者が Cookie にキーを設定していれば、そちらが優先される。
FFLOGS_ALLOW_SERVER_CREDENTIALS=true
FFLOGS_CLIENT_ID=your-client-id
FFLOGS_CLIENT_SECRET=your-client-secret
.env は .gitignore 済み。認証情報をリポジトリにコミットしないこと。
値は config/services.php 経由で読むので、php artisan config:cache した状態でも動く
(env() を直接呼ぶとキャッシュ後に null になる)。
php artisan fflogs:warm-pool はリクエストが無い(Cookie が無い)ので、.env のキーを許可した環境でしか動かない。
php artisan serve # http://localhost:8000/
| ファイル | 役割 |
|---|---|
app/Services/FFLogsService.php | FFLogs GraphQL クライアント。OAuth2 トークン管理、イベントのページング取得、Http::pool による並列取得、失敗しても止まらないキャッシュ層 |
app/Services/TimelineBuilder.php | 軽減タイムラインの組み立て。取得→プレイヤー列→軽減列→バフ区間→被弾行→使用マーカー→シナジー窓→死因、の順に積み上げる |
app/Services/ReportComparer.php | A/B比較の集計。フェーズ別の火力・ローテーション・ロス内訳の算出 |
app/Services/DeathCheckerBuilder.php | 死因チェッカー。被弾・バフ・バリア・位置・頭割りマーカーを突き合わせて死因を復元する |
app/Http/Controllers/FFLogsController.php | 入力の検証と、各サービスへの受け渡しだけを行う |
app/Http/Controllers/PartySearchController.php | ジョブ構成の多重集合照合(完全一致/部分一致)とプールの非同期取得 |
app/Http/Controllers/IconController.php | アイコン画像の配信とローカルキャッシュ |
app/Support/MitigationSpec.php | 軽減率・効果時間・リキャスト・シナジー・バリアの仕様表(ゲーム仕様なのでログから取れない) |
app/Support/DamageBreakdown.php | 被弾イベントを実被弾/生ダメージ/軽減率に分解する |
app/Support/FFXIVJobs.php | ジョブ・ロールの定義(唯一の出典)。用途ごとに形を変えて返す投影メソッドを持つ |
app/Support/TimelineJobMeta.php | タイムライン用のジョブ表示情報(FFXIVJobs への薄い入口) |
resources/views/fflogs/ | 各画面の Blade |
FFLogsService::cacheRemember() は Cache::put が失敗しても
警告ログだけ残して値を返す。キャッシュは高速化のためのものなので、書けないことを致命傷にしない。characterRankings を200ページ×2メトリクス取得する必要があるため、
Http::pool で40件ずつ波状に投げる(FFLogsService::RANKING_WAVE)。ページ数は固定なので、
並列度を上げてもAPIの消費ポイントは変わらず往復回数だけ減る(1ページあたり 10並列で約0.12秒、40並列で約0.05秒)。
ランキングに載っていない討伐ログを補う playerDetails も、レポート25本ずつのバッチを並列に投げる。PartySearchController は app()->terminating() に積むことで、応答を返しきったあと
(fastcgi_finish_request() 済み=クライアントとの接続を切ったあと)に取得する。
同じボスを同時に温めないよう Cache::lock で1プロセスに絞る。MitigationSpec に仕様表として持っている。パッチでスキルが調整されたら直す場所はここ。FFXIVJobs 1箇所に集約する。 呼び出し側が欲しい形は場所ごとに違う
(PT構成検索は FFLogs の fightRankings に合わせた複数形ロール、タイムラインは表示用の単数形と並び順、
軽減列の一致判定は「表示名→略称」と「略称→type」)。形ごとに表を持つと必ずズレるので、
実体は1つにして投影メソッドで出し分ける。投影どうしの整合はテストで押さえている。スキル・ジョブのアイコンは初回アクセス時に外部から取得して public/icons/ に保存し、以降はそこから配信する
(GET /icons/abilities/{file}, GET /icons/jobs/{file})。
取得した画像はスクウェア・エニックスの著作物なので、public/icons/ はリポジトリに含めない(.gitignore 済み)。
composer test # php artisan test
composer lint # vendor/bin/pint --test(PER-CS 準拠チェック)
composer lint:fix # vendor/bin/pint(整形)
GitHub Actions で push / PR ごとに lint とテストを回している(.github/workflows/ci.yml)。
テストはネットワーク不要。仕様表の整合性(軽減列に載っているのに軽減率の定義が無いスキルの検出)、
被弾イベントの分解、ジョブ表示情報、API がエラーを返したときの画面の振る舞い、そして
app/ 配下のクラス参照がすべて解決できることを確認する。
最後の1つは、クラスを別ファイルに切り出したときの use 漏れを拾うためのもの
(php -l は構文しか見ないので、実行時まで気づけない)。
大きな組み立て処理(TimelineBuilder)を分割したときは、分割前のコードと同じリクエストを投げて
出力をバイト比較して確認した。ただし FFLogs が返す buffs 配列の順序は取得ごとに変わるため、
比較時はその順序だけ正規化する必要がある。
このリポジトリは 閲覧していただくことを目的として 公開しています。
ライセンスは付与していないため、著作権法の原則どおり著作権者がすべての権利を留保します。 コードの複製・改変・再配布は許可していません。 (GitHub 上での fork は、public リポジトリに対して GitHub 利用規約 が許諾している範囲の行為として可能です。)
利用をご希望の場合はご連絡ください。
FINAL FANTASY XIV の関連素材・名称の権利は © SQUARE ENIX CO., LTD. に帰属します。 FFLogs は FFLogs の運営者に帰属し、本ツールは非公式・個人利用のためのものです。