109 lines
2.7 KiB
TypeScript
109 lines
2.7 KiB
TypeScript
export interface FurnitureInspection {
|
|
classname: string;
|
|
sql: Array<{ id: number; spriteId: number; name: string; type: string }>;
|
|
catalog: Array<{
|
|
id: number;
|
|
pageId: number;
|
|
credits: number;
|
|
points: number;
|
|
}>;
|
|
furnidata: Array<{
|
|
id: number;
|
|
name: string;
|
|
description: string;
|
|
revision: number;
|
|
type: string;
|
|
}>;
|
|
furnidataReadable: boolean;
|
|
nitro: { exists: boolean | null; bytes: number };
|
|
icon: { exists: boolean | null; bytes: number };
|
|
}
|
|
export function validateClassnames(value: unknown): string[] | null {
|
|
if (
|
|
!Array.isArray(value) ||
|
|
!value.length ||
|
|
value.length > 500 ||
|
|
value.some(
|
|
(v) =>
|
|
typeof v !== "string" || v.length > 200 || !/^[a-zA-Z0-9_*-]+$/.test(v),
|
|
)
|
|
)
|
|
return null;
|
|
return [...new Set(value)];
|
|
}
|
|
export function compareFurniture(
|
|
source: { name: string; description: string; revision: number; type: string },
|
|
local: FurnitureInspection,
|
|
) {
|
|
const fd = local.furnidata[0],
|
|
sql = local.sql[0];
|
|
const values = [
|
|
["Name", sql?.name ?? fd?.name, source.name],
|
|
["Description", fd?.description, source.description],
|
|
["Revision", fd?.revision, source.revision || undefined],
|
|
[
|
|
"Type",
|
|
sql ? (sql.type === "i" ? "wallitem" : "flooritem") : fd?.type,
|
|
source.type,
|
|
],
|
|
] as const;
|
|
const fields = values.map(([label, before, after]) => ({
|
|
label,
|
|
before,
|
|
after,
|
|
changed:
|
|
before !== undefined &&
|
|
after !== undefined &&
|
|
String(before) !== String(after),
|
|
}));
|
|
const state = hasFurnitureConflict(local)
|
|
? "conflict"
|
|
: !local.furnidataReadable
|
|
? "unknown"
|
|
: !sql && !fd
|
|
? "new"
|
|
: fields.some((f) => f.changed)
|
|
? "changed"
|
|
: "present";
|
|
return { state, fields } as const;
|
|
}
|
|
export function furnitureHealth(local: FurnitureInspection) {
|
|
const missing: string[] = [];
|
|
if (local.nitro.exists === false) missing.push("Nitro");
|
|
if (local.icon.exists === false) missing.push("Icon");
|
|
if (local.furnidataReadable && !local.furnidata.length)
|
|
missing.push("Furnidata");
|
|
if (!local.sql.length) missing.push("SQL item");
|
|
if (!local.catalog.length) missing.push("Catalog offer");
|
|
const conflict = hasFurnitureConflict(local);
|
|
const unknown =
|
|
!local.furnidataReadable ||
|
|
local.nitro.exists === null ||
|
|
local.icon.exists === null;
|
|
const state = conflict
|
|
? "conflict"
|
|
: unknown
|
|
? "unknown"
|
|
: !missing.length
|
|
? "complete"
|
|
: missing.length === 5
|
|
? "new"
|
|
: "incomplete";
|
|
return { state, missing } as const;
|
|
}
|
|
|
|
export function hasFurnitureConflict(local: FurnitureInspection): boolean {
|
|
const sql = local.sql[0],
|
|
fd = local.furnidata[0];
|
|
return (
|
|
local.sql.length > 1 ||
|
|
local.furnidata.length > 1 ||
|
|
!!(
|
|
sql &&
|
|
fd &&
|
|
(sql.spriteId !== fd.id ||
|
|
(sql.type === "i" ? "wallitem" : "flooritem") !== fd.type)
|
|
)
|
|
);
|
|
}
|