feat : merge mat
This commit is contained in:
@@ -7,16 +7,10 @@ import type {
|
|||||||
CatalogAscensionGroup,
|
CatalogAscensionGroup,
|
||||||
CatalogBaseStat,
|
CatalogBaseStat,
|
||||||
} from "@/lib/catalog/lunaris";
|
} from "@/lib/catalog/lunaris";
|
||||||
|
import { mergePosterMaterials, type PosterMaterial } from "@/lib/material-poster";
|
||||||
import { accentGradient } from "@/lib/overview-image";
|
import { accentGradient } from "@/lib/overview-image";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
|
|
||||||
type PosterMaterial = {
|
|
||||||
key: string;
|
|
||||||
amount: number;
|
|
||||||
name: string;
|
|
||||||
imageUrl: string | null;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type PosterBlendMode = "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity";
|
export type PosterBlendMode = "normal" | "multiply" | "screen" | "overlay" | "darken" | "lighten" | "color-dodge" | "color-burn" | "hard-light" | "soft-light" | "difference" | "exclusion" | "hue" | "saturation" | "color" | "luminosity";
|
||||||
|
|
||||||
type PosterCharacter = {
|
type PosterCharacter = {
|
||||||
@@ -80,7 +74,9 @@ export function MaterialPoster({
|
|||||||
}) {
|
}) {
|
||||||
const dragStart = useRef<{ pointerId: number; x: number; y: number; offsetX: number; offsetY: number } | null>(null);
|
const dragStart = useRef<{ pointerId: number; x: number; y: number; offsetX: number; offsetY: number } | null>(null);
|
||||||
const stats = character.baseStats.slice(0, 4);
|
const stats = character.baseStats.slice(0, 4);
|
||||||
const materials = [...character.ascension, ...character.leveling].flatMap((group) => group.items);
|
const materials = mergePosterMaterials(
|
||||||
|
[...character.ascension, ...character.leveling].flatMap((group) => group.items),
|
||||||
|
);
|
||||||
const background = `linear-gradient(180deg, ${topColors[0]} 0%, ${topColors[1]} 22%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 62%, ${bottomColors[0]} 88%, ${bottomColors[1]} 100%)`;
|
const background = `linear-gradient(180deg, ${topColors[0]} 0%, ${topColors[1]} 22%, rgba(0,0,0,0) 42%, rgba(0,0,0,0) 62%, ${bottomColors[0]} 88%, ${bottomColors[1]} 100%)`;
|
||||||
|
|
||||||
function handlePointerDown(event: PointerEvent<HTMLDivElement>) {
|
function handlePointerDown(event: PointerEvent<HTMLDivElement>) {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { describe, expect, it } from "vitest";
|
||||||
|
|
||||||
|
import { mergePosterMaterials } from "@/lib/material-poster";
|
||||||
|
|
||||||
|
describe("mergePosterMaterials", () => {
|
||||||
|
it("combines amounts when leveling and talent materials use the same image", () => {
|
||||||
|
expect(mergePosterMaterials([
|
||||||
|
{ key: "talent", amount: 9, name: "Talent", imageUrl: "/shared.webp" },
|
||||||
|
{ key: "leveling", amount: 18, name: "Leveling", imageUrl: "/shared.webp" },
|
||||||
|
])).toEqual([
|
||||||
|
{ key: "talent", amount: 27, name: "Talent", imageUrl: "/shared.webp" },
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps materials without images separate", () => {
|
||||||
|
const materials = [
|
||||||
|
{ key: "first", amount: 1, name: "First", imageUrl: null },
|
||||||
|
{ key: "second", amount: 2, name: "Second", imageUrl: null },
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(mergePosterMaterials(materials)).toEqual(materials);
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
export type PosterMaterial = {
|
||||||
|
key: string;
|
||||||
|
amount: number;
|
||||||
|
name: string;
|
||||||
|
imageUrl: string | null;
|
||||||
|
};
|
||||||
|
|
||||||
|
export function mergePosterMaterials(materials: PosterMaterial[]): PosterMaterial[] {
|
||||||
|
const merged: PosterMaterial[] = [];
|
||||||
|
const indexByImageUrl = new Map<string, number>();
|
||||||
|
|
||||||
|
for (const material of materials) {
|
||||||
|
if (!material.imageUrl) {
|
||||||
|
merged.push(material);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existingIndex = indexByImageUrl.get(material.imageUrl);
|
||||||
|
if (existingIndex === undefined) {
|
||||||
|
indexByImageUrl.set(material.imageUrl, merged.length);
|
||||||
|
merged.push(material);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const existing = merged[existingIndex];
|
||||||
|
merged[existingIndex] = {
|
||||||
|
...existing,
|
||||||
|
amount: existing.amount + material.amount,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return merged;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user