BeamNG.Earth
A 1:1 scale streamed Earth for BeamNG.drive: real elevation and satellite imagery, floating origin, LOD streaming from a companion server
FF14 のロードストーン日記から固定・PT募集を検索し、タイトルを解析してコンテンツ/進行フェーズ/募集ロール/空き枠に分解する Laravel アプリ
Translation pending
GamesPHP · 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 ↗FF14 のロードストーン日記から「固定・PT募集」を検索し、 タイトルとタグを解析してコンテンツ/進行フェーズ/募集ロール/空き枠に分解して一覧表示する。
設計の詳細・ファイル間の連動仕様は docs/ARCHITECTURE.md を参照。 Tablerの配信・共通コンポーネント・ブラウザ検証手順は docs/UI-DESIGN-SYSTEM.md を参照。
composer install
cp .env.example .env
php artisan key:generate
php artisan test # ネットワーク不要(HTTPはフィクスチャで差し替え)
php artisan serve # http://localhost:8000/
.env に秘密情報は不要。APP_KEY だけ key:generate で生成する。
| ファイル | 役割 |
|---|---|
app/Services/LodestoneBlogService.php | 検索URL組み立て・HTML取得(3件並列+5分キャッシュ)・DOMXPathでの抽出・日記本文の取得 |
app/Services/RecruitAnalyzer.php | タイトルから「コンテンツ/フェーズ/募集ロール/空き枠」を解析、コンテンツ別のグルーピング |
config/ff14.php | 解析に使う語彙(コンテンツ辞書・ロール名)。パッチ更新時はここを直す |
app/Http/Controllers/PartyFinderController.php | 検索条件の解決・バリデーション・「固定」絞り込み・並び替え・CSV出力 |
resources/views/partyfinder/index.blade.php・partials/ | 検索フォーム・保存条件・除外・結果(表/カード) |
resources/views/layouts/partyfinder.blade.php・components/partyfinder/ | 専用レイアウトと共通UI部品 |
public/css/partyfinder.css・public/js/partyfinder.js | Tablerへの最小補正/保存・復元・除外・検索中状態 |
public/vendor/tabler/1.7.1/ | 公式Tabler CSS・JS・ライセンス・取得元 |
routes/web.php | GET /(検索)、GET /export(CSV) |
tests/Feature/RecruitAnalyzerTest.php | 解析の回帰テスト(実際の日記タイトルをケースに使用) |
tests/Feature/PartyFinderPageTest.php | 画面・CSVの結合テスト(tests/Fixtures の実HTMLで Http::fake) |
もともと手元で動かしていた Python スクリプト(検索条件が固定でコンソール出力のみ)を、 条件をWebから変えられるように作り直したもの。
| Python版 | Web版 |
|---|---|
base_url の q パラメータ | 「ロードストーン検索キーワード」 |
keywords(タイトルAND判定) | 「絞り込みキーワード(AND)」 |
range(1, 11) | 「走査ページ範囲」(1〜20で指定可) |
print 出力 | カード一覧表示 + CSVダウンロード |
Python版との差異:
find_all でページ全体を走査していたため、検索結果と無関係な
「ピックアップ日記」も判定対象に含んでいた。Web版は entry__block__wrapper
配下(=実際の検索結果50件)だけを対象にしている。検索結果のタイトルを解析して、募集の中身を項目に分けて表示する。 基本の判定材料はタイトルとタグ。本文取得がONの場合は、フェーズ不明の記事だけ 本文を読み補完する(下記「本文からのフェーズ判定」)。実際の募集日記はタイトルに条件を詰め込む書き方が 主流なので、これで実用になる範囲を拾っている。
読み取れなかった項目は推測で埋めず「—」と表示する。
| 項目 | 判定内容 |
|---|---|
| 固定 | タイトルに「固定」を含むか。「タイトルに『固定』を含むものだけ」で絞り込める(初期値OFF) |
| コンテンツ | config/ff14.php の辞書で判定。載っていないものは汎用ルール(8.0零式 / 天獄編零式 / 極◯◯ / ◯◯激闘戦)で拾い、それでも不明なら「その他・不明」 |
| フェーズ | P3 / フェーズ2 / 1-4層 / 最初から / アポカリから など(下記) |
| 募集ロール | MT ST PH BH H1 D1〜D4 近接 レンジ キャス タンク ヒーラー とジョブ名。D2以外 は取り消し線で表示 |
| 空き枠 | @4 @2名 募集 1名 から。済1名 は数えない |
募集ロールは検索条件としても使える(下記「募集ロールで絞り込む」)。
表記ゆれの吸収と誤爆よけ:
D3)・半角カナ(メンバー)・波ダッシュ(〜 ~)を正規化してから照合する。@MTSTD4BH のように略称が連続する書き方、D1orD2 のような or 区切りに対応。
逆に BEST の ST のような英単語の一部は拾わない。H3構成 T3H1構成 はPT構成の説明なので募集ロールにしない。DC不問 はロール指定として扱わない(ジョブ不問 なんでも は「ジョブ不問」として拾う)。9月中旬から 集まり次第 のような開始時期はフェーズにしない。全体の「最初から」と「P5の最初から」は別物として表示する。
| タイトル | 表示 |
|---|---|
【最初から】絶妖星乱舞 週5 | 最初から |
…@クリアorP5最初からも可 | P5最初〜 |
絶妖星乱舞 P3後半から攻略 | P3後半〜 |
絶エデンP3アポカリから | P3アポカリ〜 |
P3BH3•4回目〜(修飾語が7文字以上) | P3〜 |
P の後ろの修飾語(最初 後半 時間切れ やギミック名)は 6文字までラベルに載せる。
長いものは列が崩れるので落とし、元の表記はフェーズの開閉表示とCSVで確認できる。JP22時 の P はフェーズではないので拾わない。ただし クリアorP5 のように
or/and でつないだ書き方は拾う。「フェーズ不明の記事は本文も読む(遅い)」を入れると、タイトルからフェーズを読めなかった
日記だけ本文を取りに行って判定する。本文由来のフェーズには表に 本文 バッジが付き、
表示ラベルと原文が異なる場合は、フェーズを開くと本文の表記が出る。CSVには「フェーズの判定元」列が付く。
div.txt_selfintroduction から取り、<br> とブロック要素を改行にして行単位で見る。判定は「募集の話をしている行」に絞ってから行う。本文には紛らわしい記述が多いため:
| 拾わないもの | 例 |
|---|---|
| 処理法の羅列 | P1,2,3リリドP4,P5ぬけまる(安置基準/扇前) |
| ギミック解説 | ・P2 カーターライズ スキップしません |
| 早期解散などの条件文 | 火力不足によりP2.5の進捗が芳しくない場合は早期解散もあります |
| 現メンバーの進捗 | ✒T1:暗黒騎士 Mike Tester(p3~) / D3:募集中 |
| 一般的な言い回し | 最初から全部完璧に覚えなくていいです / 各拡張最初以外の零式の初週経験がある方 |
具体的には、行が「攻略/募集/進捗/開始/スタート/固定」のいずれかを含むことを条件にし、
ロール名で始まる行(D3: ✒T1:)と、見出しが募集条件でない 見出し:値 の行を落とす。
P2.5 のような小数は進捗の話とみなさない。1-3層未クリアでも4層から は範囲より
「N層から」を優先する。
実際の募集日記24件(タイトルにフェーズなし)で検証して、24件とも手作業の判定と一致・
誤検出0。うち8件のフェーズが判明した(最初から 6件 / P2〜 1件 / 4層 1件)。
読めなければ「不明」のままにする。曖昧なものは拾わない方に倒してある。
フォームの「募集ロールで絞り込む」で、MT / ST / H1 / H2 / D1〜D4 / 不明 を選ぶ(複数選択=OR)。 何も選ばなければ絞り込まない。除外件数はサマリに「ロール条件で除外 N 件」と出る。
枠と表記の対応は config/ff14.php の role_filters に定義してある。
タイトルの書き方が揺れるので、枠の別名・総称・ジョブ名もまとめて拾う。
| 選択 | 拾うタイトルの表記 |
|---|---|
| MT / ST | MT ST タンク + タンクジョブ名(ナイト・戦士・暗黒騎士・ガンブレイカー) |
| H1 | H1 PH ピュアヒーラー ヒーラー 白魔道士 占星術師 |
| H2 | H2 BH バリアヒーラー ヒーラー 学者 賢者 |
| D1 / D2 | D1 D2 近接 メレー DPS + 近接ジョブ名(モンク・竜騎士・忍者・侍・リーパー・ヴァイパー) |
| D3 | D3 レンジ 遠隔 DPS 吟遊詩人 機工士 踊り子 |
| D4 | D4 キャス DPS 黒魔道士 召喚士 赤魔道士 ピクトマンサー |
| 不明 | ロールの記載を読み取れなかった日記 |
@6なんでも 全ジョブ可 のような枠を限定しない募集は、どの枠を選んでも出る
(role_filter_wildcards)。ただし「不明」だけを選んだときには出ない。
ほかに枠が書いてあれば(D4募集…全ジョブ分トークン周回)、その枠の募集として扱う。ST以外 と書かれている日記は、ST を選んだときには出さない。フォームの「フェーズで絞り込む」で、最初から / P1〜P9 / その他 / 不明 を選ぶ(複数選択=OR)。 何も選ばなければ絞り込まない。除外件数はサマリに「フェーズ条件で除外 N 件」と出る。
P5最初〜 P5以降 はどちらも P5。
その他 は 3層 アポカリから のような P 番号以外の表記。選択肢は config/ff14.php の phase_filters。config/ff14.php の title_ng_words(既定は 感想)を含むタイトルは、画面の除外キーワードに関係なく外す。
「絶妖星乱舞感想戦」のような募集ではない日記が混ざるため。
結果サマリの下に 「募集枠の内訳」(全体のロール別・ジョブ別件数)を出す。 さらにコンテンツ別の表では、見出しの下に 「フェーズ×募集枠の件数」 を折りたためる表で出す。 「P5のレンジ募集が1件、タンクは2件」を読み取るための表。
フェーズ | タンク | ヒーラー | DPS | 不明 | 件数
| 計 MT ST | 計 H1 H2 | 計 D1 D2 D3 D4 |
最初から | 4 2 4 | 1 1 0 | 6 4 4 3 2 | 2 | 8
P5 | 1 1 0 | 1 1 0 | 1 1 1 0 0 | 0 | 1
数え方:
タンク DPS の「計」は MT+ST の足し算ではなく、どちらかを募集していれば1件。
「タンク募集」のような総称を二重に数えないため。DPS募集 なんでも)は該当する枠すべてに数えるので、
枠ごとの数字の合計は件数と一致しない。P5最初〜 と P5後半〜 は同じ P5 の行にまとめる。行の順は 最初から → P1…P9 → その他 → 不明。賢者 侍 など)は枠とは別に、件数付きで並べる。「結果の見せ方」で切り替える。
CSVにも コンテンツ 種別 固定 フェーズ 募集ロール 募集外ロール 空き枠 の列が付く。
新パッチのコンテンツや通称・誤字(例: 絶妖精乱舞)は config/ff14.php の contents に足す。
patterns は長い表記から並べる。ASCII だけの略称(FRU など)は単語境界付きで照合される。
なお、同じコンテンツでも書き方が違うと別の表に分かれることがある
(例: 極フォークタワー魔の塔 と 極魔の塔)。気になる場合は辞書に項目として足す。
「投稿期間で絞り込む」で 24時間以内〜3ヶ月以内 を選ぶと、それより古い日記を除外する。
data-epoch(=ロードストーンが一覧に表示している日時)を使う。フォーム下の「保存した検索条件」パネルから、現在の入力内容に名前を付けて保存できる。
ff_partyfinder.saved_conditions.v1)。
サーバーには送らないので、端末・ブラウザごとに独立した保存になる。public/js/partyfinder.js(ビルド不要)。条件には合うが自分には合わない募集を、1 件ずつ検索結果から外せる。 表の右端・カードの右下の「除外」を押すと、その日記を以後の検索から外す(日記単位。同じ人の別の日記は外さない)。
ff_partyfinder.hidden_entries.v1)に持ち、日記ID(URL の /blog/{ID}/)だけを
Cookie ff_partyfinder_hidden(「.」区切り、有効期限 1 年)に書いてサーバーへ送る。bootstrap/app.php)。サーバーは数字以外の値を捨てる。URLをそのままブックマーク・共有できる。例:
http://localhost:8090/?search=1&q=零式 固定 募集&keywords=絶 妖星 D3&page_from=1&page_to=10
storage/framework/cache)。
最新状態を強制的に取り直したい場合は5分待つか php artisan cache:clear。entry__blog_block__* クラス)に依存しているため、
サイト改修時は LodestoneBlogService::parseBlock() の XPath を見直すこと。composer test # php artisan test
composer lint # vendor/bin/pint --test(PER-CS 準拠チェック)
composer lint:fix # vendor/bin/pint(整形)
テストはネットワーク不要。ロードストーンへのHTTPは tests/Fixtures/ の実HTMLで差し替える。
lodestone_blog_page.html … 実際の検索結果の構造を写したもの(先頭12件)。
第三者のキャラクター名・ロードストーンID・アバターURLは架空の値に置換してあるlodestone_blog_entry.html … 日記本文。判定してほしい行と、拾ってはいけない行
(処理法・メンバー進捗・解散条件)を両方入れてあるGitHub Actions で push / PR ごとに lint とテストを回している(.github/workflows/ci.yml)。
このリポジトリは 閲覧していただくことを目的として 公開しています。
ライセンスは付与していないため、著作権法の原則どおり著作権者がすべての権利を留保します。 コードの複製・改変・再配布は許可していません。 (GitHub 上での fork は、public リポジトリに対して GitHub 利用規約 が許諾している範囲の行為として可能です。)
利用をご希望の場合はご連絡ください。
FINAL FANTASY XIV の関連素材・名称の権利は © SQUARE ENIX CO., LTD. に帰属します。 本ツールは非公式・個人利用のためのものです。