Files
buzz-sheet/lib/content/demo.ts
T
2026-09-01 20:54:54 +07:00

363 lines
12 KiB
TypeScript

import type {
PageSnapshot,
PublicCharacterCard,
} from "@/lib/content/types";
const ids = {
character: "10000000-0000-4000-8000-000000000001",
infoPage: "10000000-0000-4000-8000-000000000002",
comboPage: "10000000-0000-4000-8000-000000000003",
source: "10000000-0000-4000-8000-000000000004",
profile: "10000000-0000-4000-8000-000000000005",
section: "10000000-0000-4000-8000-000000000006",
stats: "10000000-0000-4000-8000-000000000007",
ranking: "10000000-0000-4000-8000-000000000008",
chart: "10000000-0000-4000-8000-000000000009",
rotation: "10000000-0000-4000-8000-000000000010",
callout: "10000000-0000-4000-8000-000000000011",
richText: "10000000-0000-4000-8000-000000000012",
table: "10000000-0000-4000-8000-000000000013",
links: "10000000-0000-4000-8000-000000000014",
statOne: "10000000-0000-4000-8000-000000000015",
statTwo: "10000000-0000-4000-8000-000000000016",
statThree: "10000000-0000-4000-8000-000000000017",
stepOne: "10000000-0000-4000-8000-000000000018",
stepTwo: "10000000-0000-4000-8000-000000000019",
stepThree: "10000000-0000-4000-8000-000000000020",
rowOne: "10000000-0000-4000-8000-000000000021",
rowTwo: "10000000-0000-4000-8000-000000000022",
rowThree: "10000000-0000-4000-8000-000000000023",
linkOne: "10000000-0000-4000-8000-000000000024",
} as const;
const character = {
id: ids.character,
slug: "astra",
nameTh: "แอสตรา",
nameEn: "Astra",
description: "นักวางกลยุทธ์ธาตุแสงสำหรับทีมที่เน้นจังหวะสกิล",
portraitMediaId: null,
element: "แสง",
role: "สนับสนุน",
rarity: 5,
sortOrder: 0,
visible: true,
};
const pages = [
{
id: ids.infoPage,
characterId: ids.character,
slug: "info",
title: "ภาพรวม",
navOrder: 0,
visible: true,
publicNote: "ตัวเลขตัวอย่างนี้ใช้เพื่อสาธิตโครงสร้างเท่านั้น",
version: 3,
},
{
id: ids.comboPage,
characterId: ids.character,
slug: "combo",
title: "คอมโบ",
navOrder: 1,
visible: true,
publicNote: null,
version: 1,
},
];
const dataSource = {
id: ids.source,
name: "อุปกรณ์ตัวอย่าง",
version: 2,
fields: [
{ key: "name", label: "ชื่อ", type: "text" as const },
{ key: "score", label: "คะแนน", type: "number" as const, displayPrecision: 1 },
{ key: "base", label: "ค่าฐาน", type: "number" as const },
{
key: "boosted",
label: "เมื่อเสริมพลัง",
type: "number" as const,
formula: "base * 1.25",
displayPrecision: 2,
},
{ key: "detail", label: "รายละเอียด", type: "text" as const },
{ key: "tag", label: "ระดับ", type: "badge" as const },
],
rows: [
{
id: ids.rowOne,
values: {
name: "ดาบดาวเหนือ",
score: "98.5",
base: "120",
boosted: null,
detail: "เหมาะกับรอบการเล่นสั้นและการฟื้นพลังงาน",
tag: "แนะนำ",
},
},
{
id: ids.rowTwo,
values: {
name: "คทาสายหมอก",
score: "91.25",
base: "108",
boosted: null,
detail: "ตัวเลือกสมดุลที่ใช้ได้กับหลายทีม",
tag: "ดีมาก",
},
},
{
id: ids.rowThree,
values: {
name: "หอกฝึกหัด",
score: "76",
base: "88",
boosted: null,
detail: "ตัวเลือกเข้าถึงง่ายสำหรับช่วงเริ่มต้น",
tag: "เริ่มต้น",
},
},
],
};
function snapshot(pageSlug: string): PageSnapshot | null {
const page = pages.find((candidate) => candidate.slug === pageSlug);
if (!page) return null;
const overviewBlocks: PageSnapshot["blocks"] = [
{
id: ids.profile,
type: "profile",
schemaVersion: 1,
sortOrder: 0,
config: {
eyebrow: "คู่มือตัวละคร",
title: "แอสตรา - ผู้กำหนดจังหวะสนามรบ",
subtitle: "ตัวสนับสนุนที่เพิ่มพลังให้ทีมผ่านการจัดลำดับสกิล",
summary:
"ตัวอย่างนี้แสดงว่าคู่มือสามารถอ่านง่ายบนมือถือและยังรองรับข้อมูลคำนวณที่ตรวจสอบได้",
mediaId: null,
badges: [
{ label: "ธาตุ", value: "แสง", tone: "element" },
{ label: "ตำแหน่ง", value: "สนับสนุน", tone: "neutral" },
{ label: "ระดับ", value: "5 ดาว", tone: "rarity" },
],
},
},
{
id: ids.richText,
type: "rich-text",
schemaVersion: 1,
sortOrder: 1,
config: {
content: [
{
type: "paragraph",
text: "วางสกิลสนับสนุนก่อนตัวทำความเสียหายหลัก และเผื่อช่วงเวลาให้เอฟเฟกต์ครอบคลุมท่าไม้ตาย",
},
{
type: "bulleted-list",
items: [
"ให้ความสำคัญกับความเร็วและการฟื้นพลังงาน",
"ปรับลำดับสกิลตามระยะเวลาบัฟของทีม",
],
},
],
},
},
{
id: ids.section,
type: "section",
schemaVersion: 1,
sortOrder: 2,
config: {
title: "สรุปค่าสำคัญ",
description: "ค่าที่ควรตรวจสอบก่อนปรับอุปกรณ์",
anchor: "key-stats",
},
},
{
id: ids.stats,
type: "stat-cards",
schemaVersion: 1,
sortOrder: 3,
config: {
title: "เป้าหมายเบื้องต้น",
items: [
{ id: ids.statOne, label: "ความเร็ว", value: "134", suffix: "+" },
{ id: ids.statTwo, label: "ฟื้นพลังงาน", value: "120", suffix: "%" },
{ id: ids.statThree, label: "รอบบัฟ", value: "3", suffix: " เทิร์น" },
],
},
},
{
id: ids.ranking,
type: "ranking",
schemaVersion: 1,
sortOrder: 4,
responsiveLayout: { width: "wide" },
config: {
title: "อันดับอุปกรณ์",
description: "แตะหรือชี้ที่ชื่อเพื่อดูเหตุผลประกอบ",
dataSourceId: ids.source,
labelField: "name",
valueField: "score",
detailField: "detail",
badgeField: "tag",
higherIsBetter: true,
},
},
{
id: ids.chart,
type: "comparison-chart",
schemaVersion: 1,
sortOrder: 5,
responsiveLayout: { width: "wide" },
config: {
title: "ผลก่อนและหลังเสริมพลัง",
description: "ค่าทั้งหมดมาจากแหล่งข้อมูลเวอร์ชันเดียวกัน",
dataSourceId: ids.source,
categoryField: "name",
series: [
{ field: "base", label: "ค่าฐาน", color: "chart-1" },
{ field: "boosted", label: "เมื่อเสริมพลัง", color: "chart-2" },
],
presentation: "grouped-bar",
normalization: "raw",
sort: "authored",
showValues: true,
showLegend: true,
tableFallback: true,
},
},
{
id: ids.callout,
type: "callout",
schemaVersion: 1,
sortOrder: 6,
config: {
title: "หมายเหตุ",
body: "ผลลัพธ์จริงเปลี่ยนตามเพื่อนร่วมทีมและลำดับการออกแอ็กชัน",
tone: "tip",
},
},
{
id: ids.table,
type: "table",
schemaVersion: 1,
sortOrder: 7,
responsiveLayout: { width: "wide" },
config: {
title: "ข้อมูลคำนวณแบบละเอียด",
dataSourceId: ids.source,
columns: [
{ field: "name", label: "อุปกรณ์", align: "start" },
{ field: "base", label: "ค่าฐาน", align: "end" },
{ field: "boosted", label: "เสริมพลัง", align: "end" },
],
},
},
{
id: ids.links,
type: "links",
schemaVersion: 1,
sortOrder: 8,
config: {
title: "อ่านต่อ",
links: [
{
id: ids.linkOne,
label: "ไปยังหน้าคอมโบ",
href: "/astra/combo",
description: "ดูลำดับสกิลและจังหวะการเล่น",
},
],
},
},
];
const comboBlocks: PageSnapshot["blocks"] = [
{
id: ids.profile,
type: "profile",
schemaVersion: 1,
sortOrder: 0,
config: {
eyebrow: "ลำดับการเล่น",
title: "คอมโบพื้นฐาน",
subtitle: "หนึ่งรอบที่จำง่ายและปรับใช้ได้กับหลายทีม",
mediaId: null,
badges: [],
},
},
{
id: ids.rotation,
type: "rotation",
schemaVersion: 1,
sortOrder: 1,
config: {
title: "รอบการใช้สกิล",
description: "เรียงจากการเตรียมสนามไปจนถึงช่วงทำความเสียหาย",
steps: [
{ id: ids.stepOne, actor: "ตัวสนับสนุน", action: "เปิดบัฟทีม", duration: "1 เทิร์น" },
{ id: ids.stepTwo, actor: "แอสตรา", action: "ใช้สกิลหลัก", detail: "เก็บพลังงานไว้สำหรับท่าไม้ตาย" },
{ id: ids.stepThree, actor: "ตัวทำความเสียหาย", action: "ใช้ท่าไม้ตายและโจมตีต่อเนื่อง" },
],
},
},
];
return {
character,
page,
pages,
blocks: pageSlug === "info" ? overviewBlocks : comboBlocks,
dataSources: { [ids.source]: dataSource },
versionVector: { [ids.source]: dataSource.version },
};
}
export const demoDirectory: PublicCharacterCard[] = [
{
id: character.id,
slug: character.slug,
nameTh: character.nameTh,
nameEn: character.nameEn,
portraitMediaId: character.portraitMediaId,
element: character.element,
role: character.role,
rarity: character.rarity,
firstPageSlug: pages[0].slug,
},
];
export function getDemoPage(
characterSlug: string,
pageSlug?: string,
):
| { type: "page"; snapshot: PageSnapshot }
| { type: "redirect"; location: string }
| { type: "not-found" } {
if (characterSlug !== character.slug) return { type: "not-found" };
if (!pageSlug) return { type: "redirect", location: "/astra/info" };
const pageSnapshot = snapshot(pageSlug);
return pageSnapshot
? { type: "page", snapshot: pageSnapshot }
: { type: "not-found" };
}
export function getDemoAdminPage(
characterSlug: string,
pageSlug: string,
): PageSnapshot | null {
if (characterSlug !== character.slug) return null;
return snapshot(pageSlug);
}
export const demoAdminNavigation = {
characters: [{ ...character, pages }],
templates: [],
};