返回 Skill 列表
extension
分类: 数据与分析无需 API Key

check-in-report-skill

打卡活动报告生成技能。当用户请求查看打卡排名、生成战报、统计进度、催办未达标成员、或定时触发报告任务时激活。支持:简单进度排名、周期结算战报、跨周期同比/环比对比、未达标催办提醒。自动从活动记录(records/{group_id}/{activity_id}/YYYY-MM-DD.json)中召回数据并进行统计计算。

person作者: user_af726653hubcommunity

check-in-report-skill

Background

本 skill 配合 check-in-manager-skill 使用,负责统计分析和报告生成。

数据来源(v4 更新):

  • 活动配置check-in-manager-skill/activities/{group_id}/{activity_id}.txt(自然语言规则描述)
  • 打卡记录check-in-manager-skill/records/{group_id}/{activity_id}/YYYY-MM-DD.json(结构化记录)

Activity ID 格式(v4 简化):{类型}_{创建者}_{时间戳}

  • 示例:running_ceceilyqi_1775702066reading_bob_1775702401
  • 纯英文/数字,无中文(详见 check-in-manager-skill 的 Activity ID v4 规范)

群组隔离:通过 group_id 实现目录级隔离,每个群的活动和记录完全独立

Workflow

Step 1 — 解析请求

确定:

  • 时间周期:本日/本周/本月/自定义区间/历史累计
  • 报告类型:进度排名(A)| 周期结算(B)| 跨周期对比(C)| 催办提醒(D)
  • 目标活动:未指定时扫描当前群活动列表

模板说明见 references/report-templates.md

Step 2 — 定位数据

获取群组 ID

chat_id = inbound_metadata["chat_id"]  # "wecom:T14370047A"
# 安全获取 group_id,不存在/为空则用处理后的 chat_id
group_id = inbound_metadata.get("group_id") or chat_id.replace(":", "_").replace("#", "_").replace("/", "_")

定位目录(相对路径):

CURRENT_SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
SKILLS_DIR="$(dirname "$CURRENT_SKILL_DIR")"
MANAGER_DIR="${SKILLS_DIR}/check-in-manager-skill"
ACTIVITIES_DIR="${MANAGER_DIR}/activities/${GROUP_ID}"
RECORDS_DIR="${MANAGER_DIR}/records/${GROUP_ID}"

扫描活动

ls ${ACTIVITIES_DIR}/*.txt  # 仅当前群

读取规则

cat ${ACTIVITIES_DIR}/{activity_id}.txt

提取:活动名、达标线、核心指标、排序方向、惩罚机制、特殊规则。

加载记录

python3 scripts/load_records.py \
  ${RECORDS_DIR}/{activity_id} \
  <start_date> <end_date>

Step 3 — 统计计算

基本调用

python3 scripts/calc_stats.py '<records_json>' '<members_json>' \
  --mode <mode> --metric <field> [--metric2 <field2>] [--factor <num>]

7种计算模式

| 模式 | 使用场景 | 参数 | 示例 | |------|---------|------|------| | count | 打卡次数 | 无 | --mode count | | sum | 累计值 | --metric distance | 总距离 | | avg | 平均值 | --metric duration | 平均时长 | | max / min | 最值 | --metric distance | 单次最远/最近 | | divide_sum | 相除 | --metric duration --metric2 distance | 平均配速(时长÷距离) | | multiply_sum | 乘系数 | --metric distance --factor 60 | 卡路里(距离×60) | | last_minus_first | 差值 | --metric weight | 体重变化(末值-初值) |

输出格式(原始数值):

{
  "老张": {
    "count": 3,
    "value": 3.95,        // ⚠️ 原始数值,无单位
    "records": [...]
  }
}

关键点

  • value 是纯数值(如 3.95),不是格式化字符串(如 3'57"/km
  • ✅ 无打卡记录的成员自动返回 value: 0, count: 0
  • ✅ 保留 records 数组供二次分析

Step 4 — 格式化与报告生成

4.1 单位转换(AI 负责)

从活动规则 TXT 提取单位定义,将原始数值转换为可读文本:

| 指标 | 原始值 | 转换公式 | 结果 | |------|--------|---------|------| | 配速 | 3.95 | 分=⌊3.95⌋, 秒=(0.95×60) | 3'57"/km | | 时长 | 85.0 | <60分钟显示分钟 | "85分钟" | | 距离 | 21.5 | 保留1-2位小数 | "21.5公里" | | 体重 | -2.5 | 带符号 | "-2.5kg" |

配速转换代码(核心):

minutes = int(pace_raw)
seconds = (pace_raw - minutes) * 60
result = f"{minutes}'{int(seconds)}\"/km"

4.2 生成报告

根据 Step 1 确定的报告类型,使用 references/report-templates.md 对应模板:

| 类型 | 场景 | 必含内容 | |------|------|---------| | A | 日常排名 | 周期、排名、核心指标 | | B | 周期结算 | 达标/未达标名单、惩罚机制 | | C | 跨周期对比 | delta、排名变化(需调用 compare_periods.py) | | D | 催办提醒 | 落后成员名单、剩余时间 |

报告要求

  • ✅ 全员覆盖(未打卡成员也要列出)
  • ✅ 格式化后的指标(不是原始数值)
  • ✅ 结尾鼓励语

Step 5 — 回复用户

使用消息工具将报告推送给用户。

Constraints

  • 数据真实性:仅使用 records/{group_id}/{activity_id}/ 中的实际记录
  • 全员覆盖:未打卡成员也必须在报告中列出
  • 规则驱动:达标线、排序方向、核心指标 100% 来自活动 TXT 文件
  • 群组隔离:只统计当前群数据,不跨群访问

路径约定(v4)

相对路径发现

CURRENT_SKILL_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
MANAGER_DIR="$(dirname "$CURRENT_SKILL_DIR")/check-in-manager-skill"

目录结构

skills/
├── check-in-manager-skill/
│   ├── activities/{group_id}/{activity_id}.txt
│   └── records/{group_id}/{activity_id}/YYYY-MM-DD.json
└── check-in-report-skill/
    ├── SKILL.md
    └── scripts/

Activity ID 格式{类型}_{创建者}_{时间戳}(纯英文/数字)
群组 ID 格式wecom_T14370047A(从 chat_id 转换)

工具脚本

| 脚本 | 功能 | |------|------| | load_records.py | 加载日期范围内的记录 | | calc_stats.py | 统计计算(7种模式) | | compare_periods.py | 跨周期对比 | | rank_and_qualify.py | 排名与达标判定 |