gengxin
This commit is contained in:
@@ -0,0 +1,142 @@
|
||||
const PROGRESS_KEY = 'tang-detective-progress-v1'
|
||||
const SETTINGS_KEY = 'tang-detective-settings-v1'
|
||||
const AUDIO_KEY = 'tang-detective-audio-progress-v1'
|
||||
|
||||
function defaultProgress() {
|
||||
return {
|
||||
completedHotspots: {},
|
||||
completedChapters: [],
|
||||
lastChapter: 1,
|
||||
}
|
||||
}
|
||||
|
||||
function isPlainRecord(value) {
|
||||
return Boolean(value) && typeof value === 'object' && !Array.isArray(value)
|
||||
}
|
||||
|
||||
function chapterId(number) {
|
||||
return `S01-C${String(number).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
function eventId(number) {
|
||||
return `S01-H${String(number).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
function normalizeCompletedHotspots(value) {
|
||||
const source = isPlainRecord(value) ? value : {}
|
||||
const normalized = {}
|
||||
for (let chapterNumber = 1; chapterNumber <= 15; chapterNumber += 1) {
|
||||
const id = chapterId(chapterNumber)
|
||||
const stored = Array.isArray(source[id]) ? source[id] : []
|
||||
const firstEvent = (chapterNumber - 1) * 4 + 1
|
||||
const allowed = new Set(
|
||||
Array.from({ length: 4 }, (_, index) => eventId(firstEvent + index)),
|
||||
)
|
||||
const clean = [...new Set(stored.filter((item) => allowed.has(item)))]
|
||||
if (clean.length > 0 || Object.prototype.hasOwnProperty.call(source, id)) {
|
||||
normalized[id] = clean
|
||||
}
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
function normalizeCompletedChapters(value) {
|
||||
if (!Array.isArray(value)) return []
|
||||
const allowed = new Set(
|
||||
Array.from({ length: 15 }, (_, index) => chapterId(index + 1)),
|
||||
)
|
||||
return [...new Set(value.filter((item) => allowed.has(item)))]
|
||||
}
|
||||
|
||||
function normalizeProgress(value) {
|
||||
const source = isPlainRecord(value) ? value : {}
|
||||
const lastChapter = Number(source.lastChapter)
|
||||
return {
|
||||
...source,
|
||||
completedHotspots: normalizeCompletedHotspots(source.completedHotspots),
|
||||
completedChapters: normalizeCompletedChapters(source.completedChapters),
|
||||
lastChapter: Number.isInteger(lastChapter) && lastChapter >= 1 && lastChapter <= 15
|
||||
? lastChapter
|
||||
: 1,
|
||||
}
|
||||
}
|
||||
|
||||
function normalizeSettings(value) {
|
||||
const source = isPlainRecord(value) ? value : {}
|
||||
return {
|
||||
...source,
|
||||
fontScale: source.fontScale === 'xlarge' ? 'xlarge' : 'large',
|
||||
sound: source.sound !== false,
|
||||
}
|
||||
}
|
||||
|
||||
function read(key, fallback) {
|
||||
try {
|
||||
const value = wx.getStorageSync(key)
|
||||
return value || fallback
|
||||
} catch (error) {
|
||||
return fallback
|
||||
}
|
||||
}
|
||||
|
||||
function write(key, value) {
|
||||
try {
|
||||
wx.setStorageSync(key, value)
|
||||
return true
|
||||
} catch (error) {
|
||||
// Storage failure must never block the text game.
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
function getProgress() {
|
||||
return normalizeProgress(read(PROGRESS_KEY, null))
|
||||
}
|
||||
|
||||
function saveProgress(progress) {
|
||||
return write(PROGRESS_KEY, normalizeProgress(progress))
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the story again without deleting the reader's collected memory cards
|
||||
* or accessibility preferences. Only story/level progress is reset.
|
||||
*/
|
||||
function resetStoryProgress() {
|
||||
const current = getProgress()
|
||||
const next = {
|
||||
...current,
|
||||
...defaultProgress(),
|
||||
}
|
||||
delete next.comicReaderByChapter
|
||||
delete next.lastPageId
|
||||
if (!saveProgress(next)) return false
|
||||
write(AUDIO_KEY, {})
|
||||
return true
|
||||
}
|
||||
|
||||
function getSettings() {
|
||||
return normalizeSettings(read(SETTINGS_KEY, null))
|
||||
}
|
||||
|
||||
function saveSettings(settings) {
|
||||
return write(SETTINGS_KEY, normalizeSettings(settings))
|
||||
}
|
||||
|
||||
function getAudioProgress() {
|
||||
const value = read(AUDIO_KEY, {})
|
||||
return isPlainRecord(value) ? value : {}
|
||||
}
|
||||
|
||||
function saveAudioProgress(progress) {
|
||||
write(AUDIO_KEY, progress)
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
getProgress,
|
||||
saveProgress,
|
||||
resetStoryProgress,
|
||||
getSettings,
|
||||
saveSettings,
|
||||
getAudioProgress,
|
||||
saveAudioProgress,
|
||||
}
|
||||
Reference in New Issue
Block a user