174 lines
9.9 KiB
HTML
174 lines
9.9 KiB
HTML
<!doctype html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<meta name="color-scheme" content="light dark" />
|
|
<title>Аудит рынка · L2</title>
|
|
</head>
|
|
<body>
|
|
<div id="app" class="app-shell">
|
|
<header class="app-header">
|
|
<div class="audit-brand">
|
|
<span class="audit-crest" aria-hidden="true"></span>
|
|
<div>
|
|
<p class="eyebrow">Interlude · рынок</p>
|
|
<h1>Аудит рынка</h1>
|
|
</div>
|
|
</div>
|
|
<div class="status-stack">
|
|
<div id="global-status" class="status" data-tone="neutral" role="status" aria-live="polite">
|
|
Готов к работе
|
|
</div>
|
|
<div id="sync-status" class="sync-status" data-tone="neutral" role="status" aria-live="polite">
|
|
Синхронизация: проверяется
|
|
</div>
|
|
</div>
|
|
</header>
|
|
|
|
<nav class="step-nav" aria-label="Разделы">
|
|
<button class="step-nav__item is-active" type="button" data-view="sources" aria-current="page">
|
|
<span>1</span> Экран
|
|
</button>
|
|
<button class="step-nav__item" type="button" data-view="results">
|
|
<span>2</span> Парсинг
|
|
</button>
|
|
<button class="step-nav__item step-nav__item--settings" type="button" data-view="calibration">
|
|
Калибровка
|
|
</button>
|
|
</nav>
|
|
|
|
<main>
|
|
<section id="view-sources" class="view is-active" aria-labelledby="sources-title">
|
|
<div class="section-heading">
|
|
<div>
|
|
<p class="eyebrow">Захват экрана</p>
|
|
<h2 id="sources-title">Выбери экран игры</h2>
|
|
<p>Браузер спросит, какое окно разрешено захватывать. После выбора откроется экран парсинга.</p>
|
|
</div>
|
|
<button id="add-source" class="button button--primary" type="button">Добавить окно</button>
|
|
</div>
|
|
<div id="capture-requirement" class="capture-requirement" role="alert" hidden>
|
|
<div>
|
|
<strong id="capture-requirement-title"></strong>
|
|
<p id="capture-requirement-text"></p>
|
|
</div>
|
|
<a id="capture-secure-link" class="button" href="https://l2.dokops.ru/l2/market-audit/index.html">Открыть через HTTPS</a>
|
|
</div>
|
|
<div id="source-list" class="source-list"></div>
|
|
</section>
|
|
|
|
<section id="view-calibration" class="view" aria-labelledby="calibration-title" hidden>
|
|
<div class="section-heading section-heading--compact">
|
|
<div>
|
|
<p class="eyebrow">Образец интерфейса</p>
|
|
<h2 id="calibration-title">Калибровка</h2>
|
|
<p>Отметь торговое окно, его заголовок и точные строки всплывающего описания предмета.</p>
|
|
</div>
|
|
<div class="button-row">
|
|
<select id="calibration-source" aria-label="Окно для снимка"></select>
|
|
<button id="capture-reference" class="button" type="button">Снимок из окна</button>
|
|
<label class="button file-button">
|
|
Загрузить скриншоты
|
|
<input id="reference-file" type="file" accept="image/*" multiple />
|
|
</label>
|
|
</div>
|
|
</div>
|
|
|
|
<div id="reference-list" class="reference-strip" aria-label="Снимки калибровки" hidden></div>
|
|
|
|
<details class="calibration-guide">
|
|
<summary>Как связаны области калибровки</summary>
|
|
<div class="calibration-guide__content">
|
|
<ol>
|
|
<li><strong>Маркер магазина</strong><span>Ищется по всему кадру. Лучше выбрать стабильные `Adena` и `Confirm`, не включая числа.</span></li>
|
|
<li><strong>Заголовок магазина</strong><span>Строка `Private Store(Buy/Sell) - имя` запоминается до закрытия торгового окна. Если tooltip её перекрыл, используется последний распознанный магазин.</span></li>
|
|
<li><strong>Зона tooltip</strong><span>Тоже привязана к маркеру, поэтому перемещается вместе с торговым окном.</span></li>
|
|
<li><strong>Якорь Price :</strong><span>Ищется внутри зоны tooltip. Он позволяет самому tooltip перемещаться при наведении на разные иконки.</span></li>
|
|
<li><strong>Название и цена</strong><span>Привязаны к найденному `Price :` и читаются из двух точных строк.</span></li>
|
|
</ol>
|
|
<div class="pipeline-map" aria-label="Последовательность распознавания">
|
|
<span>Кадр</span><b>→</b><span>Магазин</span><b>→</b><span>Тип + торговец</span>
|
|
<i>и</i><span>Tooltip</span><b>→</b><span>Название + цена</span>
|
|
</div>
|
|
<p>Снимки могут иметь разный размер, а торговое окно может находиться в разных местах. На первом выдели маркер и видимый заголовок. На втором калибратор найдёт маркер по всему кадру, после чего выдели tooltip и его строки.</p>
|
|
</div>
|
|
</details>
|
|
|
|
<div class="calibration-layout">
|
|
<div class="canvas-stage">
|
|
<div id="canvas-empty" class="empty-state">
|
|
<strong>Нужен скриншот</strong>
|
|
<span>Сделай снимок выбранного окна или загрузи готовое изображение.</span>
|
|
</div>
|
|
<canvas id="calibration-canvas" hidden></canvas>
|
|
</div>
|
|
|
|
<aside class="inspector" aria-label="Настройки калибровки">
|
|
<div class="field-stack">
|
|
<label for="region-type">Что выделяем</label>
|
|
<select id="region-type">
|
|
<option value="saleAnchor">Маркер магазина</option>
|
|
<option value="storeHeader">Заголовок магазина</option>
|
|
<option value="sellItemGrid">Сетка предметов Sell</option>
|
|
<option value="buyItemGrid">Сетка предметов Buy</option>
|
|
<option value="tooltipSearch">Зона поиска tooltip</option>
|
|
<option value="tooltipAnchor">Якорь Price :</option>
|
|
<option value="itemName">Название предмета</option>
|
|
<option value="itemPrice">Строка цены</option>
|
|
</select>
|
|
</div>
|
|
|
|
<p id="draw-hint" class="hint">Выдели постоянный нижний фрагмент торгового окна, например подпись Adena и кнопку Confirm. Числа лучше не включать.</p>
|
|
|
|
<label class="overlay-toggle" for="show-overlays">
|
|
<input id="show-overlays" type="checkbox" checked />
|
|
<span>Показывать выбранные рамки</span>
|
|
</label>
|
|
|
|
<div class="field-stack">
|
|
<div class="range-label">
|
|
<label for="match-threshold">Порог совпадения</label>
|
|
<output id="threshold-value" for="match-threshold">0.80</output>
|
|
</div>
|
|
<input id="match-threshold" type="range" min="0.50" max="0.99" step="0.01" value="0.80" />
|
|
</div>
|
|
|
|
<div class="inspector__section">
|
|
<div class="inspector__title">
|
|
<h3>Области</h3>
|
|
<span id="region-count">0</span>
|
|
</div>
|
|
<div id="region-list" class="region-list"></div>
|
|
</div>
|
|
|
|
<div class="inspector__actions">
|
|
<button id="save-calibration" class="button button--primary" type="button">Сохранить</button>
|
|
<button id="test-calibration" class="button" type="button" disabled>Проверить снимки</button>
|
|
<button id="clear-calibration" class="button button--quiet" type="button">Сбросить</button>
|
|
</div>
|
|
</aside>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="view-results" class="view" aria-labelledby="results-title" hidden>
|
|
<div class="section-heading">
|
|
<div>
|
|
<p class="eyebrow">Проверка пайплайна</p>
|
|
<h2 id="results-title">Торговцы</h2>
|
|
<p>Запусти парсинг и наведи мышь на товары. Каждый торговец появится отдельным блоком, данные сохранятся автоматически.</p>
|
|
</div>
|
|
<div class="button-row">
|
|
<button id="clear-results" class="button button--quiet" type="button">Очистить</button>
|
|
<button id="recognize-all" class="button button--primary" type="button">Начать парсинг</button>
|
|
</div>
|
|
</div>
|
|
<div id="results-list" class="results-list"></div>
|
|
</section>
|
|
</main>
|
|
</div>
|
|
|
|
<script type="module" src="/src/main.js"></script>
|
|
</body>
|
|
</html>
|