Extract @sendou/utils, @sendou/build-analyzer, @sendou/map-list-generator and @sendou/scanner-core workspace packages

This commit is contained in:
Kalle
2026-08-16 10:01:27 +03:00
parent fdb97b04b2
commit 935e357842
505 changed files with 1384 additions and 967 deletions

View File

@@ -13,30 +13,26 @@
*/
import { mkdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { loadOpenCV, type Mat } from "../../app/features/scanner/core/cv";
import { loadOpenCV, type Mat } from "@sendou/scanner-core/cv";
import {
TAG_NAME_INNER,
TAG_NAME_OUTER,
TAG_NAME_TEXT_HEIGHT,
TAG_TILT_DEG,
} from "../../app/features/scanner/core/detectors/death/rois";
} from "@sendou/scanner-core/detectors/death/rois";
import {
nameRoi,
paintRoi,
ROW_CENTERS,
statRoi,
TEAM_SCORE_ROIS,
} from "../../app/features/scanner/core/detectors/scoreboard/rois";
} from "@sendou/scanner-core/detectors/scoreboard/rois";
import {
CODE_TEXT_HEIGHT,
REPLAY_CODE_ROI,
} from "../../app/features/scanner/core/detectors/scoreboard-battle-log-replay/rois";
import type { AtlasMeta } from "../../app/features/scanner/core/glyphs";
import {
normalizeFrame,
type Roi,
toMat,
} from "../../app/features/scanner/core/image";
} from "@sendou/scanner-core/detectors/scoreboard-battle-log-replay/rois";
import type { AtlasMeta } from "@sendou/scanner-core/glyphs";
import { normalizeFrame, type Roi, toMat } from "@sendou/scanner-core/image";
import { SCANNER_ASSETS_DIR } from "../../app/features/scanner/node/assets-dir";
import { FIXTURES_DIR } from "../../app/features/scanner/node/fixtures";
import { readImage, writePng } from "../../app/features/scanner/node/image-io";

View File

@@ -24,16 +24,16 @@ import { createCanvas, GlobalFonts } from "@napi-rs/canvas";
import {
DEATH_MESSAGE_TEMPLATES,
LOCALIZED_WEAPON_NAMES,
} from "../../app/features/scanner/core/detectors/death/localized-messages";
import { ALL_WEAPON_ENTRIES } from "../../app/features/scanner/core/detectors/death/weapon-names";
import type { AtlasMeta } from "../../app/features/scanner/core/glyphs";
} from "@sendou/scanner-core/detectors/death/localized-messages";
import { ALL_WEAPON_ENTRIES } from "@sendou/scanner-core/detectors/death/weapon-names";
import type { AtlasMeta } from "@sendou/scanner-core/glyphs";
import {
ALL_LOBBY_ENTRIES,
ALL_MODE_ENTRIES,
ALL_MODE_LABELS,
ALL_STAGE_ENTRIES,
RESULT_TAG_ENTRIES,
} from "../../app/features/scanner/core/localized";
} from "@sendou/scanner-core/localized";
import { SCANNER_ASSETS_DIR } from "../../app/features/scanner/node/assets-dir";
import { readImage, writePng } from "../../app/features/scanner/node/image-io";
import { readFontCoverage } from "./otf-cmap";

View File

@@ -29,19 +29,19 @@ import { readdirSync, readFileSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { stageIds } from "@sendou/in-game-lists/stage-ids";
import type { ModeShort, StageId } from "@sendou/in-game-lists/types";
import { ALL_WEAPON_ENTRIES } from "../../app/features/scanner/core/detectors/death/weapon-names";
import type { ScannerLobby } from "../../app/features/scanner/scanner-types";
import { ALL_WEAPON_ENTRIES } from "@sendou/scanner-core/detectors/death/weapon-names";
import type { ScannerLobby } from "@sendou/scanner-core/scanner-types";
import gameMisc from "../../locales/en/game-misc.json";
const SPLAT3_DIR =
process.argv[2] ?? new URL("../../../splat3", import.meta.url).pathname;
const LANG_DIR = join(SPLAT3_DIR, "data", "language");
const OUT_ENTRIES = new URL(
"../../app/features/scanner/core/localized-entries.ts",
"@sendou/scanner-core/localized-entries.ts",
import.meta.url,
).pathname;
const OUT_MESSAGES = new URL(
"../../app/features/scanner/core/detectors/death/localized-messages.ts",
"@sendou/scanner-core/detectors/death/localized-messages.ts",
import.meta.url,
).pathname;

View File

@@ -16,18 +16,18 @@
*/
import { mkdirSync, readdirSync, writeFileSync } from "node:fs";
import { join } from "node:path";
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import {
PLANNER_SIG_H,
PLANNER_SIG_W,
type PlannerManifest,
plannerSignature,
} from "../../app/features/scanner/core/detectors/minimap/stage";
} from "@sendou/scanner-core/detectors/minimap/stage";
import {
type FrameData,
normalizeFrame,
toMat,
} from "../../app/features/scanner/core/image";
} from "@sendou/scanner-core/image";
import { SCANNER_ASSETS_DIR } from "../../app/features/scanner/node/assets-dir";
import { readImage, writePng } from "../../app/features/scanner/node/image-io";

View File

@@ -9,13 +9,13 @@
*/
import { mkdirSync } from "node:fs";
import { join } from "node:path";
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import {
cropRoi,
matToFrameData,
normalizeFrame,
toMat,
} from "../../app/features/scanner/core/image";
} from "@sendou/scanner-core/image";
import { readImage, writePng } from "../../app/features/scanner/node/image-io";
const [imagePath, outDir, ...specs] = process.argv.slice(2);

View File

@@ -3,19 +3,19 @@
* Draw all scoreboard ROIs on a (normalized) frame for visual calibration.
* Usage: vite-node -c scripts/scanner/vite-node.config.ts scripts/scanner/overlay-rois.ts <image> [out.png] [scoreboard|scoreboard-battle-log-replay|scoreboard-battle-log]
*/
import { loadOpenCV, type Mat } from "../../app/features/scanner/core/cv";
import * as death from "../../app/features/scanner/core/detectors/death/rois";
import * as mapStart from "../../app/features/scanner/core/detectors/map-start/rois";
import * as minimap from "../../app/features/scanner/core/detectors/minimap/rois";
import * as sb from "../../app/features/scanner/core/detectors/scoreboard/rois";
import * as bl from "../../app/features/scanner/core/detectors/scoreboard-battle-log/rois";
import * as replay from "../../app/features/scanner/core/detectors/scoreboard-battle-log-replay/rois";
import { loadOpenCV, type Mat } from "@sendou/scanner-core/cv";
import * as death from "@sendou/scanner-core/detectors/death/rois";
import * as mapStart from "@sendou/scanner-core/detectors/map-start/rois";
import * as minimap from "@sendou/scanner-core/detectors/minimap/rois";
import * as sb from "@sendou/scanner-core/detectors/scoreboard/rois";
import * as bl from "@sendou/scanner-core/detectors/scoreboard-battle-log/rois";
import * as replay from "@sendou/scanner-core/detectors/scoreboard-battle-log-replay/rois";
import {
matToFrameData,
normalizeFrame,
type Roi,
toMat,
} from "../../app/features/scanner/core/image";
} from "@sendou/scanner-core/image";
import { readImage, writePng } from "../../app/features/scanner/node/image-io";
const [imagePath, outPath = "roi-overlay.png", detector = "scoreboard"] =

View File

@@ -13,14 +13,14 @@
*/
import { readdirSync } from "node:fs";
import { join } from "node:path";
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { MAP_START_EVENT_TYPE } from "../../app/features/scanner/core/detectors/map-start/index";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import { MAP_START_EVENT_TYPE } from "@sendou/scanner-core/detectors/map-start/index";
import {
createAllDetectors,
SCOREBOARD_EVENT_TYPES,
} from "../../app/features/scanner/core/detectors/registry";
import { DetectorScheduler } from "../../app/features/scanner/core/detectors/scheduler";
import { normalizeFrame, toMat } from "../../app/features/scanner/core/image";
} from "@sendou/scanner-core/detectors/registry";
import { DetectorScheduler } from "@sendou/scanner-core/detectors/scheduler";
import { normalizeFrame, toMat } from "@sendou/scanner-core/image";
import { readImage } from "../../app/features/scanner/node/image-io";
import { loadScoreboardResources } from "../../app/features/scanner/node/resources";

View File

@@ -7,30 +7,30 @@
*
* Usage: pnpm scanner:report
*/
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import {
createDeathDetector,
type DeathData,
} from "../../app/features/scanner/core/detectors/death/index";
} from "@sendou/scanner-core/detectors/death/index";
import {
createMapStartDetector,
type MapStartData,
} from "../../app/features/scanner/core/detectors/map-start/index";
} from "@sendou/scanner-core/detectors/map-start/index";
import {
createMinimapDetector,
type MinimapData,
} from "../../app/features/scanner/core/detectors/minimap/index";
import { createScoreboardDetector } from "../../app/features/scanner/core/detectors/scoreboard/index";
import { createScoreboardBattleLogDetector } from "../../app/features/scanner/core/detectors/scoreboard-battle-log/index";
} from "@sendou/scanner-core/detectors/minimap/index";
import { createScoreboardDetector } from "@sendou/scanner-core/detectors/scoreboard/index";
import { createScoreboardBattleLogDetector } from "@sendou/scanner-core/detectors/scoreboard-battle-log/index";
import {
createScoreboardBattleLogReplayDetector,
type ScoreboardBattleLogReplayData,
} from "../../app/features/scanner/core/detectors/scoreboard-battle-log-replay/index";
} from "@sendou/scanner-core/detectors/scoreboard-battle-log-replay/index";
import {
createScoreboardOwnDetector,
type ScoreboardOwnData,
} from "../../app/features/scanner/core/detectors/scoreboard-own/index";
import type { Detector } from "../../app/features/scanner/core/detectors/types";
} from "@sendou/scanner-core/detectors/scoreboard-own/index";
import type { Detector } from "@sendou/scanner-core/detectors/types";
import {
loadFixtures,
runDetectorOnFixture,

View File

@@ -5,11 +5,11 @@
*
* Usage: pnpm scanner:fixtures [case-name-substring]
*/
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import {
createScoreboardDetector,
type ScoreboardRowDebug,
} from "../../app/features/scanner/core/detectors/scoreboard/index";
} from "@sendou/scanner-core/detectors/scoreboard/index";
import {
loadFixtures,
runDetectorOnFixture,

View File

@@ -17,23 +17,23 @@
import { spawn } from "node:child_process";
import { writeFileSync } from "node:fs";
import { basename } from "node:path";
import { loadOpenCV } from "@sendou/scanner-core/cv";
import { MAP_START_EVENT_TYPE } from "@sendou/scanner-core/detectors/map-start/index";
import {
createAllDetectors,
SCOREBOARD_EVENT_TYPES,
} from "@sendou/scanner-core/detectors/registry";
import { DetectorScheduler } from "@sendou/scanner-core/detectors/scheduler";
import {
createScanTelemetry,
detectorTelemetry,
} from "@sendou/scanner-core/detectors/telemetry";
import { normalizeFrame, toMat } from "@sendou/scanner-core/image";
import { TimelineBuilder } from "@sendou/scanner-core/timeline/index";
import {
type CsvEvent,
eventsToCsv,
} from "../../app/features/scanner/components/events-csv";
import { loadOpenCV } from "../../app/features/scanner/core/cv";
import { MAP_START_EVENT_TYPE } from "../../app/features/scanner/core/detectors/map-start/index";
import {
createAllDetectors,
SCOREBOARD_EVENT_TYPES,
} from "../../app/features/scanner/core/detectors/registry";
import { DetectorScheduler } from "../../app/features/scanner/core/detectors/scheduler";
import {
createScanTelemetry,
detectorTelemetry,
} from "../../app/features/scanner/core/detectors/telemetry";
import { normalizeFrame, toMat } from "../../app/features/scanner/core/image";
import { TimelineBuilder } from "../../app/features/scanner/core/timeline/index";
import { loadScoreboardResources } from "../../app/features/scanner/node/resources";
const FRAME_WIDTH = 1920;

View File

@@ -28,6 +28,53 @@ import type {
StageId,
} from "@sendou/in-game-lists/types";
import { mainWeaponIds } from "@sendou/in-game-lists/weapon-ids";
import {
DEATH_EVENT_TYPE,
type DeathData,
} from "@sendou/scanner-core/detectors/death/index";
import { ALL_WEAPON_ENTRIES } from "@sendou/scanner-core/detectors/death/weapon-names";
import {
MAP_START_EVENT_TYPE,
type MapStartData,
} from "@sendou/scanner-core/detectors/map-start/index";
import {
MINIMAP_EVENT_TYPE,
type MinimapData,
type MinimapEnemy,
type MinimapTeammate,
} from "@sendou/scanner-core/detectors/minimap/index";
import type { CardSlot } from "@sendou/scanner-core/detectors/minimap/rois";
import {
OBJECTIVE_EVENT_TYPE,
type ObjectiveData,
} from "@sendou/scanner-core/detectors/objective/index";
import {
PLAYER_STATUS_EVENT_TYPE,
type PlayerStatusData,
type PlayerStatusFlags,
type PlayerStatusLayout,
} from "@sendou/scanner-core/detectors/objective/player-status";
import {
STRIP_WEAPONS_EVENT_TYPE,
type StripWeaponsData,
} from "@sendou/scanner-core/detectors/objective/strip-weapons";
import {
SCOREBOARD_EVENT_TYPE,
type ScoreboardData,
type ScoreboardPlayer,
} from "@sendou/scanner-core/detectors/scoreboard/index";
import { SCOREBOARD_BATTLE_LOG_EVENT_TYPE } from "@sendou/scanner-core/detectors/scoreboard-battle-log/index";
import { SCOREBOARD_BATTLE_LOG_REPLAY_EVENT_TYPE } from "@sendou/scanner-core/detectors/scoreboard-battle-log-replay/index";
import type { DetectedEvent } from "@sendou/scanner-core/detectors/types";
import {
type BuiltMatch,
buildScannerMatches,
} from "@sendou/scanner-core/match-builder";
import type {
ScannerMatch,
ScannerMatchPlayerStatusSample,
} from "@sendou/scanner-core/scanner-match";
import type { ScannerLobby } from "@sendou/scanner-core/scanner-types";
import { statusSpans } from "../../app/components/PlayerStatusTimeline";
import { formatTime } from "../../app/features/scanner/components/format";
import {
@@ -36,53 +83,6 @@ import {
modeLabel,
stageLabel,
} from "../../app/features/scanner/components/labels";
import {
DEATH_EVENT_TYPE,
type DeathData,
} from "../../app/features/scanner/core/detectors/death/index";
import { ALL_WEAPON_ENTRIES } from "../../app/features/scanner/core/detectors/death/weapon-names";
import {
MAP_START_EVENT_TYPE,
type MapStartData,
} from "../../app/features/scanner/core/detectors/map-start/index";
import {
MINIMAP_EVENT_TYPE,
type MinimapData,
type MinimapEnemy,
type MinimapTeammate,
} from "../../app/features/scanner/core/detectors/minimap/index";
import type { CardSlot } from "../../app/features/scanner/core/detectors/minimap/rois";
import {
OBJECTIVE_EVENT_TYPE,
type ObjectiveData,
} from "../../app/features/scanner/core/detectors/objective/index";
import {
PLAYER_STATUS_EVENT_TYPE,
type PlayerStatusData,
type PlayerStatusFlags,
type PlayerStatusLayout,
} from "../../app/features/scanner/core/detectors/objective/player-status";
import {
STRIP_WEAPONS_EVENT_TYPE,
type StripWeaponsData,
} from "../../app/features/scanner/core/detectors/objective/strip-weapons";
import {
SCOREBOARD_EVENT_TYPE,
type ScoreboardData,
type ScoreboardPlayer,
} from "../../app/features/scanner/core/detectors/scoreboard/index";
import { SCOREBOARD_BATTLE_LOG_EVENT_TYPE } from "../../app/features/scanner/core/detectors/scoreboard-battle-log/index";
import { SCOREBOARD_BATTLE_LOG_REPLAY_EVENT_TYPE } from "../../app/features/scanner/core/detectors/scoreboard-battle-log-replay/index";
import type { DetectedEvent } from "../../app/features/scanner/core/detectors/types";
import {
type BuiltMatch,
buildScannerMatches,
} from "../../app/features/scanner/core/match-builder";
import type {
ScannerMatch,
ScannerMatchPlayerStatusSample,
} from "../../app/features/scanner/core/scanner-match";
import type { ScannerLobby } from "../../app/features/scanner/scanner-types";
/** Mirrors PlayerStatusTimeline's MAX_BRIDGE_SECONDS: longer sample gaps render as unobserved. */
const OBSERVATION_GAP_SECONDS = 15;