chore: 미사용 데드코드 삭제

- entities/vessel/lib/filter.ts (미사용 필터 유틸)
- entities/vessel/model/mockFleet.ts (미사용 mock 데이터)
- shared/lib/color/hexToRgb.ts (MapSettingsPanel 로컬 중복)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
htlee 2026-02-16 23:20:47 +09:00
부모 4d1a8a0d1e
커밋 c2ca830ef0
3개의 변경된 파일0개의 추가작업 그리고 319개의 파일을 삭제

파일 보기

@ -1,34 +0,0 @@
import type { Vessel, VesselTypeCode } from "../model/types";
export function isTrawl(code: VesselTypeCode) {
return code === "PT" || code === "PT-S";
}
export function filterVesselsForMap(vessels: readonly Vessel[], selectedType: VesselTypeCode | null) {
if (!selectedType) return vessels;
return vessels.filter((v) => {
if (v.code === selectedType) return true;
// PT and PT-S should be shown together
if (selectedType === "PT" && v.code === "PT-S") return true;
if (selectedType === "PT-S" && v.code === "PT") return true;
// FC interacts with trawl; show trawl when FC selected and FC when trawl selected
if (selectedType === "FC" && (v.code === "PT" || v.code === "PT-S")) return true;
if ((selectedType === "PT" || selectedType === "PT-S") && v.code === "FC") return true;
return false;
});
}
export function filterVesselsForList(vessels: readonly Vessel[], selectedType: VesselTypeCode | null) {
if (!selectedType) return vessels;
return vessels.filter((v) => {
if (v.code === selectedType) return true;
if (selectedType === "PT" && v.code === "PT-S") return true;
if (selectedType === "PT-S" && v.code === "PT") return true;
return false;
});
}

파일 보기

@ -1,278 +0,0 @@
import type { ZoneId } from "../../zone/model/meta";
import { haversineNm } from "../../../shared/lib/geo/haversineNm";
import { VESSEL_TYPES } from "./meta";
import type { FleetOwner, FleetState, TrawlPair, Vessel, VesselTypeCode } from "./types";
const SURNAMES = ["张", "王", "李", "刘", "陈", "杨", "黄", "赵", "周", "吴", "徐", "孙", "马", "朱", "胡", "郭", "林", "何", "高", "罗"];
const REGIONS = ["荣成", "石岛", "烟台", "威海", "日照", "青岛", "连云港", "舟山", "象山", "大连"];
const ZONE_BOUNDS: Record<ZoneId, { lat: [number, number]; lon: [number, number] }> = {
"1": { lon: [128.85, 131.70], lat: [36.16, 38.25] },
"2": { lon: [126.00, 128.90], lat: [32.18, 34.35] },
"3": { lon: [124.12, 126.06], lat: [33.13, 35.00] },
"4": { lon: [124.33, 125.85], lat: [35.00, 37.00] },
};
function rnd(a: number, b: number) {
return a + Math.random() * (b - a);
}
function pick<T>(arr: readonly T[]) {
return arr[Math.floor(Math.random() * arr.length)];
}
function randomPointInZone(zone: ZoneId) {
const b = ZONE_BOUNDS[zone];
// Small margin to avoid sitting exactly on the edge.
const lat = rnd(b.lat[0] + 0.05, b.lat[1] - 0.05);
const lon = rnd(b.lon[0] + 0.05, b.lon[1] - 0.05);
return { lat, lon };
}
function makePermit(id: number, suffix: "A" | "B") {
return `C21-${10000 + id}${suffix}`;
}
export function createMockFleetState(): FleetState {
const vessels: Vessel[] = [];
const owners: FleetOwner[] = [];
const ptPairs: TrawlPair[] = [];
let vid = 1;
// PT pairs: PT count == PT-S count, treat as "pair count".
for (let i = 0; i < VESSEL_TYPES.PT.count; i++) {
const owner = `${pick(SURNAMES)}${pick(SURNAMES)}${pick(["渔业", "海产", "水产", "船务"])}${pick(["有限公司", "合作社", ""])}`;
const region = pick(REGIONS);
const zone = pick<ZoneId>(["2", "3"]);
const { lat, lon } = randomPointInZone(zone);
const isFishing = Math.random() < 0.55;
const sp = isFishing ? rnd(2.5, 4.5) : rnd(6, 11);
const crs = rnd(0, 360);
const pairDist = isFishing ? rnd(0.2, 1.2) : rnd(0, 0.3); // NM (rough)
const pairAngle = rnd(0, 360);
const lat2 = lat + (pairDist / 60) * Math.cos((pairAngle * Math.PI) / 180);
const lon2 = lon + ((pairDist / 60) * Math.sin((pairAngle * Math.PI) / 180)) / Math.cos((lat * Math.PI) / 180);
const permitBase = vid;
const ptId = vid++;
const ptsId = vid++;
const pt: Vessel = {
id: ptId,
permit: makePermit(permitBase, "A"),
code: "PT",
color: VESSEL_TYPES.PT.color,
lat,
lon,
speed: Number(sp.toFixed(1)),
course: Number(crs.toFixed(0)),
state: isFishing ? "조업중" : sp < 1 ? "정박" : "항해중",
zone,
isFishing,
owner,
region,
pairId: null,
pairDistNm: Number(pairDist.toFixed(2)),
nearVesselIds: [],
};
const pts: Vessel = {
id: ptsId,
permit: makePermit(permitBase, "B"),
code: "PT-S",
color: VESSEL_TYPES["PT-S"].color,
lat: Number(lat2.toFixed(4)),
lon: Number(lon2.toFixed(4)),
speed: Number((sp + rnd(-0.3, 0.3)).toFixed(1)),
course: Number((crs + rnd(-10, 10)).toFixed(0)),
state: isFishing ? "조업중" : sp < 1 ? "정박" : "항해중",
zone,
isFishing,
owner,
region,
pairId: null,
pairDistNm: pt.pairDistNm,
nearVesselIds: [],
};
pt.pairId = pts.id;
pts.pairId = pt.id;
vessels.push(pt, pts);
ptPairs.push({ mainId: pt.id, subId: pts.id, owner, region });
owners.push({ name: owner, region, vessels: [pt.id, pts.id], type: "trawl" });
}
// GN vessels
for (let i = 0; i < VESSEL_TYPES.GN.count; i++) {
const attachToOwner = Math.random() < 0.3 ? owners[Math.floor(Math.random() * owners.length)] : null;
const owner = attachToOwner ? attachToOwner.name : `${pick(SURNAMES)}${pick(SURNAMES)}${pick(["渔业", "水产"])}有限公司`;
const region = attachToOwner ? attachToOwner.region : pick(REGIONS);
const zone = pick<ZoneId>(["2", "3", "4"]);
const { lat, lon } = randomPointInZone(zone);
const isFishing = Math.random() < 0.5;
const sp = isFishing ? rnd(0.5, 2) : rnd(5, 10);
const id = vid++;
const v: Vessel = {
id,
permit: makePermit(id, "A"),
code: "GN",
color: VESSEL_TYPES.GN.color,
lat,
lon,
speed: Number(sp.toFixed(1)),
course: Number(rnd(0, 360).toFixed(0)),
state: isFishing ? pick(["표류", "투망", "양망"]) : sp < 1 ? "정박" : "항해중",
zone,
isFishing,
owner,
region,
pairId: null,
pairDistNm: null,
nearVesselIds: [],
};
vessels.push(v);
if (attachToOwner) attachToOwner.vessels.push(v.id);
else owners.push({ name: owner, region, vessels: [v.id], type: "gn" });
}
// OT
for (let i = 0; i < VESSEL_TYPES.OT.count; i++) {
const owner = `${pick(SURNAMES)}${pick(SURNAMES)}远洋渔业`;
const region = pick(REGIONS);
const zone = pick<ZoneId>(["2", "3"]);
const { lat, lon } = randomPointInZone(zone);
const isFishing = Math.random() < 0.5;
const sp = isFishing ? rnd(2.5, 5) : rnd(5, 10);
const id = vid++;
const v: Vessel = {
id,
permit: makePermit(id, "A"),
code: "OT",
color: VESSEL_TYPES.OT.color,
lat,
lon,
speed: Number(sp.toFixed(1)),
course: Number(rnd(0, 360).toFixed(0)),
state: isFishing ? "조업중" : "항해중",
zone,
isFishing,
owner,
region,
pairId: null,
pairDistNm: null,
nearVesselIds: [],
};
vessels.push(v);
owners.push({ name: owner, region, vessels: [v.id], type: "ot" });
}
// PS
for (let i = 0; i < VESSEL_TYPES.PS.count; i++) {
const owner = `${pick(SURNAMES)}${pick(SURNAMES)}水产`;
const region = pick(REGIONS);
const zone = pick<ZoneId>(["1", "2", "3", "4"]);
const { lat, lon } = randomPointInZone(zone);
const isFishing = Math.random() < 0.5;
const sp = isFishing ? rnd(0.3, 1.5) : rnd(5, 9);
const id = vid++;
const v: Vessel = {
id,
permit: makePermit(id, "A"),
code: "PS",
color: VESSEL_TYPES.PS.color,
lat,
lon,
speed: Number(sp.toFixed(1)),
course: Number(rnd(0, 360).toFixed(0)),
state: isFishing ? pick(["위망", "채낚기"]) : "항해중",
zone,
isFishing,
owner,
region,
pairId: null,
pairDistNm: null,
nearVesselIds: [],
};
vessels.push(v);
owners.push({ name: owner, region, vessels: [v.id], type: "ps" });
}
// FC — assigned to trawl owners (positioned near PT)
const trawlOwners = owners.filter((o) => o.type === "trawl");
for (let i = 0; i < VESSEL_TYPES.FC.count; i++) {
const oi = i < trawlOwners.length ? trawlOwners[i] : pick(trawlOwners);
const refId = oi.vessels.find((id) => vessels[id - 1]?.code === "PT") ?? oi.vessels[0];
const ref = vessels[refId - 1];
const zone = pick<ZoneId>(["2", "3"]);
const lat = ref.lat + rnd(-0.2, 0.2);
const lon = ref.lon + rnd(-0.2, 0.2);
const isNear = Math.random() < 0.4;
const sp = isNear ? rnd(0.5, 1.5) : rnd(5, 9);
const nearVesselIds = isNear ? oi.vessels.filter((id) => vessels[id - 1]?.code !== "FC").slice(0, 2) : [];
const v: Vessel = {
id: vid,
permit: makePermit(vid, "A"),
code: "FC",
color: VESSEL_TYPES.FC.color,
lat,
lon,
speed: Number(sp.toFixed(1)),
course: Number(rnd(0, 360).toFixed(0)),
state: isNear ? "환적" : "항해중",
zone,
isFishing: isNear, // kept from prototype: treat "환적" as fishing-like activity
owner: oi.name,
region: oi.region,
pairId: null,
pairDistNm: null,
nearVesselIds,
};
vid += 1;
vessels.push(v);
oi.vessels.push(v.id);
}
// Ensure initial pair distances are consistent with actual coordinates.
for (const p of ptPairs) {
const a = vessels[p.mainId - 1];
const b = vessels[p.subId - 1];
const d = haversineNm(a.lat, a.lon, b.lat, b.lon);
a.pairDistNm = d;
b.pairDistNm = d;
}
return { vessels, owners, ptPairs };
}
export function tickMockFleetState(state: FleetState) {
for (const v of state.vessels) {
v.lat += (0.5 - Math.random()) * 0.003;
v.lon += (0.5 - Math.random()) * 0.003;
v.speed = Math.max(0, Number((v.speed + (0.5 - Math.random()) * 0.4).toFixed(1)));
v.course = Number(((v.course + (0.5 - Math.random()) * 6 + 360) % 360).toFixed(0));
}
for (const p of state.ptPairs) {
const a = state.vessels[p.mainId - 1];
const b = state.vessels[p.subId - 1];
const d = haversineNm(a.lat, a.lon, b.lat, b.lon);
a.pairDistNm = d;
b.pairDistNm = d;
}
}
export function isVesselCode(code: string): code is VesselTypeCode {
return code === "PT" || code === "PT-S" || code === "GN" || code === "OT" || code === "PS" || code === "FC";
}

파일 보기

@ -1,7 +0,0 @@
export function hexToRgb(hex: string): [number, number, number] {
const m = /^#?([0-9a-fA-F]{6})$/.exec(hex.trim());
if (!m) return [255, 255, 255];
const n = parseInt(m[1], 16);
return [(n >> 16) & 255, (n >> 8) & 255, n & 255];
}