# 2026-04-15 课程巩固、单元强化、单元挑战统计逻辑学习笔记 [李承龙要求] 学习 vala_bi 仓库中关于课程巩固、单元强化、单元挑战的统计逻辑。 ## 代码仓库 - 地址: https://git.valavala.com/vala/vala_bi - 本地克隆: /tmp/vala_bi - 语言: Go --- ## 一、课程巩固(Review) ### 概念 - 课程巩固是课时(Lesson)级别的功能,每个课时完成后有对应的巩固练习 - 巩固练习包含一组选择题(QuestionList),记录是否正确(isRight)和是否跳过(isSkip) ### 数据来源 - 源表: `unit_review_question_result`(MySQL vala_user 库) - BI表: `user_chapter_time`(PostgreSQL vala_bi 库) ### 统计字段(存在 user_chapter_time 表中) - `first_done_review_duration`: 巩固用时(秒),来源 `play_time / 1000` - `first_done_review_right_rate`: 巩固正确率(万分比),计算方式 = `正确数 / 总题数 * 10000` ### 聚合统计(Lesson 维度,写入飞书多维表格) - **巩固完成人数**: `COUNT(first_done_review_duration > 0)` - **巩固平均完成时间/分钟**: `AVG(first_done_review_duration) / 60` - **巩固平均正确率%**: `AVG(first_done_review_right_rate) / 100` ### 同步函数 - `userFirstDoneReview()` in `internal/service/user.go` - cron 任务: `UserFirstDone` → `userService.UserFirstDone()` 中调用 --- ## 二、单元强化(Summary) ### 概念 - 单元强化是单元(Unit)级别的功能,每个单元的5个课时全部完成后可进入强化 - 数据来源于 `user_unit_summary_km_result` 表(记录用户参与单元强化的行为) - 通过 `user_learn_record_report_summary` 表记录完成时间 ### 数据来源 - 源表1(进入): `bi_user_unit_summary_km_result`(PostgreSQL,已同步到 BI 库,前缀 `bi_`) - 源表2(完成): `user_learn_record_report_summary`(MySQL vala_user 库),条件 `learn_card_type = 1 AND record_type = 3` - BI表: `user_unit_time`(PostgreSQL vala_bi 库) ### 统计字段(存在 user_unit_time 表中) - `summary_in_ts`: 首次进入强化的时间戳(Unix秒),从 `user_unit_summary_km_result.created_at` 获取 - `summary_done_ts`: 首次完成强化的时间戳(Unix秒),从 `user_learn_record_report_summary.complete_time` 获取 ### 聚合统计(Unit 维度,写入飞书多维表格) - **强化进入人数**: `COUNT(summary_in_ts > 0)` - **强化完成人数**: `COUNT(summary_done_ts > 0)` ### 同步函数 - 进入: `UserUnitSummaryStart()` in `internal/service/user.go` - 完成: `UserUnitSCDone()` in `internal/service/user.go`(`learn_card_type=1, record_type=3` 为 summary) - cron 任务: `UserFirstDone` job 中依次调用 --- ## 三、单元挑战(Challenge) ### 概念 - 单元挑战是单元(Unit)级别的功能,在单元强化之后可进入 - 挑战包含四个维度: listening(听力)、speaking(口语)、reading(阅读)、writing(写作) - 每个维度评分等级: Perfect / Good / Oops ### 数据来源 - 源表1(进入&评分): `bi_unit_challenge_question_result`(PostgreSQL,已同步到 BI 库) - 源表2(完成): `user_learn_record_report_summary`(MySQL vala_user 库),条件 `learn_card_type = 1 AND record_type = 4` - BI表: `user_unit_time`(PostgreSQL vala_bi 库) ### 统计字段(存在 user_unit_time 表中) - `challenge_in_ts`: 首次进入挑战的时间戳 - `challenge_done_ts`: 首次完成挑战的时间戳 - `challenge_listening`: 听力评分(Perfect/Good/Oops) - `challenge_speaking`: 口语评分 - `challenge_reading`: 阅读评分 - `challenge_writing`: 写作评分 ### 聚合统计(Unit 维度,写入飞书多维表格) - **挑战参与人数**: `COUNT(challenge_in_ts > 0)` - **挑战完成人数**: `COUNT(challenge_done_ts > 0)` - 四个维度各自的 Perfect率%、Good率%、Oops率%: - 计算方式: 各评分人数 / (Perfect + Good + Oops 总人数) * 100 ### 同步函数 - 进入&评分: `UserUnitChallengeStart()` in `internal/service/user.go` - 完成: `UserUnitSCDone()` in `internal/service/user.go`(`learn_card_type=1, record_type=4` 为 challenge) - cron 任务: `UserFirstDone` job 中依次调用 --- ## 四、关键关联逻辑 ### 课程结构层级 - CourseLevel (A1/A2) → SeasonGamePackage (S1~S4) → ValaGameInfo (Unit, 每Season 12个Unit) → ValaGameChapter (Lesson, 每Unit 5个Lesson) - UnitIndex = (SeasonOfQuarter - 1) * 12 + GameInfo.Index - ChapterIndex = UnitIndex * 5 + Chapter.Index ### 付费用户过滤 - Unit 统计使用 `pay_account_user_course` 表进行 INNER JOIN,确保只统计付费用户 - Lesson 统计使用 `account_user_course` 表 ### 测试账号剔除 - `bi_vala_app_account.status = 2` 为测试账号 - 所有统计均通过 `IsTestUser()` 剔除测试用户 ### BI 表(PostgreSQL vala_bi 库) - `user_chapter_time`: 课时维度统计表(包含巩固数据) - `user_unit_time`: 单元维度统计表(包含强化和挑战数据) ### Cron 调度顺序 1. `UserFirstDone()` - 课时首次进入/完成/巩固/组件正确率 2. `UserUnitSummaryStart()` - 强化进入 3. `UserUnitChallengeStart()` - 挑战进入&评分 4. `UserUnitSCDone()` - 强化完成 + 挑战完成 --- ## 五、飞书多维表格输出 ### Unit 维度数据表 (tblsA5CwmL3AZxG6) 字段包括: 课程单元、进入过人数、已通过人数、平均通关时间/天、平均间隔时间/天、强化进入人数、强化完成人数、挑战参与人数、挑战完成人数、四维度各三级评分率 ### Lesson 维度数据表 (多个表,按时间窗口区分) - 全量: tblMGuEjfdidefks - 昨日起: tbltoiOQxsvS13d0 - 6日前起: tblIbb3fKowryQj0 - 29日前起: tbltyxhkYJjZhJma 字段包括: 课程Lesson、巩固完成人数、巩固平均完成时间/分钟、巩固平均正确率%、中互动/核心互动各评分比例等