76 lines
2.5 KiB
JavaScript
76 lines
2.5 KiB
JavaScript
import { TREE_LEVELS, TREE_MAX_LEVEL, TREE_XP_PER_LEVEL } from './treeLevels.js'
|
||
|
||
/** 可选树种:每级 emoji 与 treeLevels.js Lv.0~9 一一对应 */
|
||
export const TREE_SPECIES_LIST = [
|
||
{
|
||
id: 'classic',
|
||
name: '稳糖灵树',
|
||
tagline: '经典路线,从种子到圆满',
|
||
stages: TREE_LEVELS.map((l) => l.emoji)
|
||
},
|
||
{
|
||
id: 'bonsai',
|
||
name: '雅韵盆景',
|
||
tagline: '小巧精致,书桌旁的温柔陪伴',
|
||
stages: ['🫘', '🌱', '🪴', '🎋', '🪴', '🌳', '🎍', '🌸', '🏵️', '🏆']
|
||
},
|
||
{
|
||
id: 'pine',
|
||
name: '苍劲青松',
|
||
tagline: '挺拔向上,越记越稳',
|
||
stages: ['🫘', '🌱', '🌿', '🌲', '🌲', '🌲', '⛰️', '🌲', '🏔️', '🏆']
|
||
},
|
||
{
|
||
id: 'sakura',
|
||
name: '樱花小树',
|
||
tagline: '坚持打卡,枝头渐开',
|
||
stages: ['🫘', '🌱', '🌿', '🌳', '🌸', '🌸', '🌸', '🌸', '🌺', '🏆']
|
||
},
|
||
{
|
||
id: 'ginkgo',
|
||
name: '金秋银杏',
|
||
tagline: '叶色渐变,见证每一天',
|
||
stages: ['🫘', '🌱', '🍃', '🌳', '🍂', '🍂', '🌳', '🍁', '🌟', '🏆']
|
||
}
|
||
]
|
||
|
||
export const TREE_SPECIES_STORAGE_KEY = 'tongji_tree_species_v1'
|
||
|
||
/** 四项任务全勤时每日最多可领积分(与后端 taskDefs 一致) */
|
||
export const DAILY_MAX_TASK_POINTS = 40
|
||
|
||
export function getTreeSpecies(id) {
|
||
return TREE_SPECIES_LIST.find((s) => s.id === id) || TREE_SPECIES_LIST[0]
|
||
}
|
||
|
||
export function speciesEmojiAtLevel(speciesId, level) {
|
||
const sp = getTreeSpecies(speciesId)
|
||
const lv = Math.min(TREE_MAX_LEVEL, Math.max(0, Number(level) || 0))
|
||
return sp.stages[lv] || sp.stages[0] || '🌱'
|
||
}
|
||
|
||
/** 当前树种成长路线图(供选择面板展示) */
|
||
export function speciesGrowthRoadmap(speciesId) {
|
||
const sp = getTreeSpecies(speciesId)
|
||
return TREE_LEVELS.map((meta, i) => {
|
||
const xpTotal = i * TREE_XP_PER_LEVEL
|
||
const daysHint = i === 0
|
||
? 0
|
||
: Math.max(1, Math.ceil(xpTotal / DAILY_MAX_TASK_POINTS))
|
||
return {
|
||
level: i,
|
||
name: meta.name,
|
||
emoji: sp.stages[i] || meta.emoji,
|
||
desc: meta.desc,
|
||
xpTotal,
|
||
daysHint
|
||
}
|
||
})
|
||
}
|
||
|
||
/** 全勤打卡大约多少天满级 */
|
||
export function estimateDaysToMaxLevel() {
|
||
const totalXp = TREE_MAX_LEVEL * TREE_XP_PER_LEVEL
|
||
return Math.max(1, Math.ceil(totalXp / DAILY_MAX_TASK_POINTS))
|
||
}
|