Skip to content

里程挑战模块 (Mileage Challenge)

文档版本: V2.0 更新日期: 2026-02-25 状态: 评审中 V2 变更: 新增"挑战类型"顶层分层,新增"雪道打卡"挑战,修正统计维度(最高速度→滑行时长)

0. 背景与目标 (Context & Goals)

问题陈述 (Problem Statement)

  • 活跃度激励: 仅仅记录滑雪轨迹缺乏显性的激励机制,用户容易流失。
  • 社群凝聚力: 俱乐部缺乏组织线上比赛的工具,传统的"晒数据截图"方式统计繁琐且难以验证真伪。
  • 官方运营: 平台需要通过全网挑战赛(如"百万落差挑战")来维持雪季期间的 DAU。
  • V2 新增 — 雪场深度绑定: 现有积累型挑战与具体雪场的关联较弱(仅作为数据过滤条件),缺乏让用户"深度探索一座雪场"的玩法。雪道打卡填补了这一空白,同时为雪场合作(B2B)开辟了新的运营工具。

成功指标 (Success Metrics)

  • 参与度: 挑战赛的报名人数与完赛率。
  • 粘性: 参与挑战赛用户的周均启动次数提升 20%。
  • V2 新增: 雪道打卡挑战的平均打卡完成率(目标 > 40%);挑战期间用户在目标雪场的平均滑行天数(目标 > 3天)。

一、 核心逻辑与业务规则

1.1 双重身份 (Dual Identity)

本模块同时服务于 官方 (Official)俱乐部 (Club)

  • 官方: 发起全网活动,具备最高权重,奖品通常由品牌赞助。
  • 俱乐部: 发起私域活动,可限制仅本俱乐部成员参加,增强社群归属感。

1.2 数据来源 (Data Source)

  • 自动采集: 依托 APP 内置的 GPS 轨迹记录功能。
  • 有效性校验: 仅统计挑战赛时间范围内数据有效(非车载/缆车异常数据)的滑行记录。

1.3 挑战类型分层(V2 新增)

里程挑战分为两大类型,底层逻辑完全不同:

挑战类型
├── 积累型 (Accumulation)
│   ├── 累计里程 (KM)
│   ├── 累计落差 (Vertical Drop)
│   └── 累计滑行时长 (Duration)

└── 打卡型 (Check-in)
    └── 雪道打卡 (Trail Check-in)
        ├── 打卡范围:全部雪道 / 初级道 / 中级道 / 高级道
        └── 排名依据:最先集齐者排名靠前

两种类型的核心差异

维度积累型打卡型
排名逻辑数值累加,大者居前集齐打卡,先完成者居前
成绩表示单一数值 (128.5km)进度 + 完成时间 (12/12 ✅ 01.25 14:32)
技术依赖轨迹的里程/落差/时长计算轨迹 × 雪道检查点匹配
激励语"再滑 2km 即可超越""还差 3 条雪道即可集齐"
上榜条件有有效成绩即可仅集齐全部目标雪道才上榜

二、 积累型挑战 — 详细功能定义

2.1 发布端 (官方/Club管理台)

板块字段/功能说明/规则
基础信息挑战名称e.g., "崇礼开板首滑挑战"
挑战时间开始时间 ~ 结束时间。
排名规则统计维度单选:
1. 累计里程 (KM)
2. 累计落差 (Vertical Drop)
3. 累计滑行时长 (Duration)
范围限制可选指定雪场 (e.g., 仅限"万龙滑雪场"的数据)。
奖励配置排名奖前 [3] 名的奖品描述 (支持图文)。
参与奖完赛(达到基础门槛)即可获得的奖励。通常为积分/勋章。
参与门槛达标数据设定最低有效数据 (e.g., 累计滑行 > 10km) 才算"完赛"。
权限控制参与范围1. 全网公开 (仅官方可发)
2. 仅限俱乐部成员 (Club 默认)
3. 指定群组 (关联 IM 群)

2.2 用户端 (C-Side Flow)

A. 挑战列表

  • 我的挑战: 展示已报名且进行中的挑战进度条。
  • 发现挑战: 推荐官方热门挑战及用户所在俱乐部的挑战。

B. 挑战详情与排行榜

  • 实时榜单: 动态刷新 Top 100 排名。
    • 显示:头像、昵称、所属俱乐部、成绩数值。
  • 我的战绩:
    • 当前排名。
    • 距离上一名/获奖区的差距 ("再滑 2km 即可超越/获奖") -> 核心激励点

C. 数据同步逻辑

mermaid
sequenceDiagram
    participant U as 用户 (App)
    participant S as 服务端 (Challenge Svc)
    
    U->>U: 结束滑行,上传轨迹
    U->>S: 提交 Track Data
    S->>S: 校验数据有效性 (去噪)
    S->>S: 检索用户参与的所有"进行中"挑战
    loop 遍历挑战
        S->>S: 过滤是否符合挑战规则 (时间/雪场)
        S->>S: 累加成绩 (Increment Score)
    end
    S->>S: 更新排行榜 (Redis ZSet)
    S-->>U: 返回本次滑行更新的挑战进度

三、 打卡型挑战 — 雪道打卡(V2 新增)

3.1 核心概念

一句话定义:发起人选择一个雪场,参与者通过滑行自动打卡该雪场的雪道,最先集齐指定分类(全部/初/中/高级道)的所有雪道者排名靠前。

核心机制

  • 挑战必须绑定一个具体雪场(不可选多雪场或不限雪场)。
  • 系统根据雪场的雪道数据库自动生成打卡清单。
  • 打卡判定基于检查点机制(非全段覆盖):每条雪道设置若干 GPS 检查点,用户的滑行轨迹经过全部检查点即判定该雪道打卡成功。
  • 仅集齐目标分类全部雪道的用户才上榜,按完成时间的先后排名。未集齐者不排名。

3.2 检查点机制

3.2.1 选点规则

核心原则:基于雪道 GIS 数据自动生成,避开首尾,中段等距采样。

系统读取雪道的中心线 (Polyline) 数据,自动执行以下算法:

  1. 计算雪道全长 L
  2. 跳过首尾各 20%(起点/终点多道交汇区,GPS 无法区分)
  3. 在中段 60% 区间内,按雪道长度自动等距选取检查点
雪道中心线(GIS Polyline):

|--20%--|------60%------|--20%--|
  跳过    ● C1  ● C2  ● C3   跳过
         ↑ 系统自动等距采样

检查点数量(自动计算)

雪道长度检查点数
< 500m2 个
500m - 1.5km3 个
> 1.5km4-5 个

检查点参数

  • 半径:40m(兼容 GPS 误差 + 雪道宽度)

3.2.3 匹配算法

用户上传一条完整的滑行轨迹后,服务端对每条未打卡雪道执行以下匹配流程:

输入:
  - 轨迹 T = [P1, P2, ..., Pn],每个点含 (经度, 纬度, 时间戳, 海拔, 速度)
  - 雪道 S 的检查点序列 C = [C1, C2, ..., Cm],每个点含 (经度, 纬度, 半径)

Step 1 — 空间命中
  遍历轨迹点 T,找出进入每个检查点半径范围内的轨迹点:
  - 对每个 Ci,找到第一个满足 distance(Pj, Ci) ≤ Ci.半径 的轨迹点 Pj
  - 记录 hit(Ci) = Pj(首次命中的轨迹点)
  - 如果某个 Ci 没有任何轨迹点命中 → 匹配失败,退出

Step 2 — 有序性校验
  验证检查点的命中顺序与轨迹时间线一致:
  - 要求 hit(C1).时间戳 < hit(C2).时间戳 < ... < hit(Cm).时间戳
  - 如果顺序不一致 → 匹配失败(可能是反向滑行或轨迹乱序)

Step 3 — 时间窗口过滤
  验证通过所有检查点的总耗时合理:
  - 总耗时 = hit(Cm).时间戳 - hit(C1).时间戳
  - 最短耗时 = 雪道长度 / 最大合理速度(80km/h)
  - 最长耗时 = 雪道长度 / 最小合理速度(3km/h)
  - 要求 最短耗时 ≤ 总耗时 ≤ 最长耗时
  - 超出范围 → 匹配失败(太快=车载/数据异常,太慢=步行/排队)

Step 4 — 速度特征校验(辅助)
  命中区间内的轨迹点平均速度应在合理范围:
  - 平均速度 ≥ 5 km/h(排除步行上山)
  - 平均速度 ≤ 80 km/h(排除车载)

全部通过 → 判定该雪道打卡成功,记录完成时间 = hit(Cm).时间戳

3.2.4 检查点数据管理

  • 自动生成:导入雪场雪道 GIS 数据后,系统自动计算检查点坐标,无需人工标注。
  • 运营可微调:自动生成后,运营可在后台查看和微调检查点位置(极端情况下的兜底手段)。
  • 版本管理:雪场开放/关闭雪道时,更新 GIS 数据后系统自动重新生成检查点。已进行中的挑战不受影响(快照机制)。

3.3 打卡范围

一个"雪道打卡"挑战对应一个打卡范围,发起人在创建时选择:

打卡范围打卡目标示例
全部雪道该雪场所有雪道0/25 条
初级道仅初级雪道0/8 条
中级道仅中级雪道0/10 条
高级道仅高级雪道0/7 条

一个挑战 = 一个打卡范围 = 一个排行榜 = 一套奖励。 如需覆盖多个分类,发起人创建多个挑战。

排名规则

  • 仅限集齐该范围全部雪道的用户才上榜。
  • 集齐者按完成时间(最后一条雪道的打卡时间戳)升序排名。
  • 未集齐者不出现在榜单中。

3.4 奖励配置

与积累型一致,发起人配置一套奖励:

  • 排名奖: 前 N 名,支持雪币 + 实物奖品描述。
  • 完赛奖: 集齐该范围全部雪道即可获得,支持雪币 + 实物奖品描述。

3.5 发布端配置

发起人选择"打卡型 - 雪道打卡"后的发布流程:

步骤字段/功能说明/规则
Step 1目标雪场发布第一步,单选一个雪场(仅展示有 GIS 数据的雪场)
Step 2打卡范围单选:全部雪道 / 初级道 / 中级道 / 高级道。选后展示对应雪道清单及数量
Step 3挑战名称e.g., "万龙初级道打卡挑战"
挑战时间开始时间 ~ 结束时间
Step 4排名奖前 [3] 名的奖品描述(雪币 + 实物)
完赛奖集齐即获得(雪币 + 可选实物奖品描述)
Step 5参与范围同积累型

与积累型的差异:打卡型以"选雪场 - 选打卡范围"开头,没有"统计维度"和"参与门槛"字段。完赛由系统自动判定(集齐 = 完赛)。

3.6 用户端 — 挑战详情页

┌────────────────────────────────────┐
│ 🏔️ 万龙初级道打卡挑战              │
│ 01/15 - 02/15 · 进行中             │
├────────────────────────────────────┤
│ 📍 万龙滑雪场 · 初级道 8 条        │
├────────────────────────────────────┤
│ 📋 我的打卡进度  5/8               │
│ ┌────────────────────────────────┐ │
│ │ ✅ 银龙道       01/16 打卡      │ │
│ │ ✅ 玉龙道       01/17 打卡      │ │
│ │ ✅ 白龙道       01/18 打卡      │ │
│ │ ✅ 小龙道       01/19 打卡      │ │
│ │ ✅ 青龙道       01/20 打卡      │ │
│ │ ⬜ 云龙道       未打卡          │ │
│ │ ⬜ 雪龙道       未打卡          │ │
│ │ ⬜ 冰龙道       未打卡          │ │
│ │       还差 3 条雪道 💪          │ │
│ └────────────────────────────────┘ │
├────────────────────────────────────┤
│ 🏆 排行榜(已集齐 2 人)           │
│ ┌────────────────────────────────┐ │
│ │ 🥇 雪疯子   8/8   01/22 完成   │ │
│ │ 🥈 粉雪控   8/8   01/24 完成   │ │
│ └────────────────────────────────┘ │
│ 💡 集齐全部初级道后,你将出现在榜单 │
└────────────────────────────────────┘

3.7 数据同步逻辑

mermaid
sequenceDiagram
    participant U as 用户 (App)
    participant S as 服务端 (Challenge Svc)
    participant G as 地理围栏服务

    U->>U: 结束滑行,上传轨迹
    U->>S: 提交 Track Data
    S->>S: 校验数据有效性 (去噪)
    S->>S: 检索用户参与的所有"进行中"挑战
    loop 遍历打卡型挑战
        S->>G: 轨迹 GPS 点 × 雪场检查点匹配
        G-->>S: 返回本次轨迹命中的雪道列表
        S->>S: 更新用户打卡记录 (新增已打卡雪道)
        S->>S: 检查是否集齐该挑战全部目标雪道
        S->>S: 更新排行榜 (仅集齐者)
    end
    S-->>U: 返回本次滑行的打卡结果
    Note over U: 弹出打卡成功动画<br/>"恭喜!银龙道 打卡成功 🎉<br/>还差 3 条即可集齐"

四、 验收标准 (Acceptance Criteria)

4.1 积累型挑战(原有 + 修正)

  1. 俱乐部隔离: 俱乐部 A 发起的内部挑战,非成员无法报名(或报名时提示加入俱乐部)。
  2. 数据过滤:
    • 验证时间范围: 挑战开始前或结束后的滑行数据不计入。
    • 验证雪场限制: 若挑战限定"北大壶",在"松花湖"的滑行数据不计入。
  3. 榜单更新: 上传一条 5km 的轨迹后,关联的"里程挑战"个人成绩应增加 5km,排名相应变动。
  4. 奖励发放: 模拟挑战结束,系统应自动向达标用户发放"参与奖"(如积分),并生成排名报表供管理员核对"排名奖"。
  5. V2 修正: "滑行时长"维度下,成绩单位为小时:分钟,累加用户所有有效滑行记录的时长。

4.2 打卡型挑战(V2 新增)

  1. 雪场首选: 打卡型挑战发布第一步必须选择雪场,无 GIS 数据的雪场不可选。
  2. 单一打卡范围: 一个挑战 = 一个打卡范围(全部/初级/中级/高级),一个排行榜,一套奖励。
  3. 打卡判定: 用户滑行轨迹经过某雪道的全部检查点(有序),该雪道自动标记为已打卡。
  4. 去重: 同一雪道重复滑行不重复打卡,仅记录首次打卡时间。
  5. 集齐才上榜: 未集齐该范围全部雪道的用户不出现在排行榜中。
  6. 时间排序: 多位集齐用户按完成时间(最后一条雪道的打卡时间戳)升序排列。
  7. 打卡反馈: 每次滑行结束后,若有新雪道被打卡成功,App 弹出打卡成功通知,显示当前进度。

五、 文档修订记录

版本日期变更内容
V1.02024-05-20初始版本,定义积累型挑战(里程/落差/速度)
V2.02026-02-251. 新增"挑战类型"顶层分层(积累型 / 打卡型)
2. 新增"雪道打卡"挑战(一个挑战=一个打卡范围=一个榜单)
3. 统计维度修正为"累计滑行时长"
4. 基于 GIS 数据自动生成检查点