Files
2026-09-09 14:47:29 +08:00

149 lines
4.7 KiB
JavaScript

function eventIdSet(chapter) {
return new Set(
Array.isArray(chapter && chapter.events)
? chapter.events.map((event) => event.hotspotId)
: [],
)
}
function normalizeCompletedIds(chapter, completedIds) {
const knownIds = eventIdSet(chapter)
const seen = new Set()
return (Array.isArray(completedIds) ? completedIds : []).filter((id) => {
if (!knownIds.has(id) || seen.has(id)) return false
seen.add(id)
return true
})
}
function getPeopleProgress(chapter, completedIds) {
const knownIds = eventIdSet(chapter)
const completed = new Set(normalizeCompletedIds(chapter, completedIds))
const people = Array.isArray(chapter && chapter.people) ? chapter.people : []
return people
.map((person) => {
const personEventIds = (Array.isArray(person.eventIds)
? person.eventIds
: []
).filter((id) => knownIds.has(id))
const completedForPerson = personEventIds.filter((id) => completed.has(id))
const remaining = personEventIds.length - completedForPerson.length
if (!personEventIds.length) return null
let markerStatus = '看看'
let statusAria = `${person.name}有1处故事细节,可以看看发生了什么`
if (remaining === 0) {
markerStatus = '看过'
statusAria = `${person.name}这一处已经看过`
} else if (completedForPerson.length > 0) {
markerStatus = '再看看'
statusAria = `${person.name}还有${remaining}处细节,可以再看看`
} else if (remaining > 1) {
markerStatus = `${remaining}处`
statusAria = `${person.name}${remaining}处故事细节`
}
return {
...person,
eventIds: personEventIds,
completed: remaining === 0,
completedEvents: completedForPerson.length,
remaining,
markerStatus,
statusAria,
}
})
.filter(Boolean)
}
function selectNextPerson(people, activeInstanceId) {
const active = people.find(
(person) => person.instanceId === activeInstanceId && person.remaining > 0,
)
if (active) return active
const partiallyCompleted = people.find(
(person) => person.completedEvents > 0 && person.remaining > 0,
)
return partiallyCompleted || people.find((person) => person.remaining > 0) || null
}
function getChapterProgress(
chapter,
completedIds,
activeInstanceId = '',
chapterFinished = false,
) {
const normalizedIds = normalizeCompletedIds(chapter, completedIds)
const totalEvents = Array.isArray(chapter && chapter.events)
? chapter.events.length
: 0
const completedCount = normalizedIds.length
const remainingCount = Math.max(0, totalEvents - completedCount)
const complete = totalEvents > 0 && remainingCount === 0
const people = getPeopleProgress(chapter, normalizedIds)
const nextPerson = complete
? null
: selectNextPerson(people, activeInstanceId)
const repeatPerson = Boolean(
nextPerson
&& (
nextPerson.completedEvents > 0
|| (
activeInstanceId
&& nextPerson.instanceId === activeInstanceId
)
),
)
let nextStepLabel = '下一步'
let nextStepText = '看看画中的人物和手边物件,跟着这一回往下走。'
let continueLabel = '完成后继续'
if (complete) {
nextStepLabel = chapterFinished ? '本回已收好' : '4处线索已经看过'
nextStepText = chapterFinished
? '这一回已经收进画册,也可以再次打开情感互动。'
: '情感互动已经开启,点右侧按钮打开这一页。'
continueLabel = '4处线索看完,打开情感互动'
} else if (nextPerson && repeatPerson) {
nextStepText = `还差${remainingCount}处。再看看${nextPerson.name}的手边。`
continueLabel = `下一步:再看看${nextPerson.name}`
} else if (nextPerson) {
const multiEventNote = nextPerson.remaining > 1
? ` ${nextPerson.name}身边还有${nextPerson.remaining}处细节。`
: ''
nextStepText = `还差${remainingCount}处。接着看看${nextPerson.name}${multiEventNote}`
continueLabel = `下一步:看看${nextPerson.name}`
}
const emotionStatusText = complete
? (
chapterFinished
? '本回已收进画册,可再次打开'
: `${totalEvents}处线索已经看过,可以打开`
)
: `还差${remainingCount}处线索,看完后开启`
return {
completedIds: normalizedIds,
completedCount,
totalEvents,
remainingCount,
complete,
people,
nextPerson,
nextAction: complete ? 'complete' : (repeatPerson ? 'repeat' : 'next'),
nextStepLabel,
nextStepText,
continueLabel,
emotionStatusText,
}
}
module.exports = {
normalizeCompletedIds,
getPeopleProgress,
getChapterProgress,
}