From cde77e762d2bec015e853362e9b2b281d85a8dad Mon Sep 17 00:00:00 2001 From: xiaoban Date: Sun, 24 May 2026 10:44:49 +0800 Subject: [PATCH] =?UTF-8?q?studytime-analysis:=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=95=99=E5=AD=98=E7=8A=B6=E6=80=81=E5=88=A4=E5=AE=9A=20?= =?UTF-8?q?=E2=80=94=20=E6=9C=80=E8=BF=9114=E5=A4=A9=E6=97=A0=E5=AE=8C?= =?UTF-8?q?=E8=AF=BE=E6=A0=87=E8=AE=B0=E4=B8=BA=E6=B5=81=E5=A4=B1=EF=BC=8C?= =?UTF-8?q?=E5=90=A6=E5=88=99=E6=AD=A3=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .vala_skill_hashes | 2 +- .../scripts/studytime_analysis.py | 26 ++++++++++++++++--- 2 files changed, 24 insertions(+), 4 deletions(-) diff --git a/.vala_skill_hashes b/.vala_skill_hashes index 8061291..73cab72 100644 --- a/.vala_skill_hashes +++ b/.vala_skill_hashes @@ -7,4 +7,4 @@ lark_wiki_operate_as_bot 2a37701f568849f03eb46dd938baeda171380fe252b698ac8bda69c vala_git_workspace_backup 4cf352bec88fe84af065ba1ffcbb06647b77df0e01860faaf0bca9fd64b968ec cron-schedule b1879fa59d60e3d99cea1138674f7abac84a4aecd32743b801d41bfd6ed7181d study-analysis 33217dc132073ecd47b921800834f6df89494da9e7708fa90f15b3de7742e37f -studytime-analysis 042178f9f7e97eeef366fd619403f4d0c8e0dce290abf17af662dddfa67c4e83 +studytime-analysis a3b2570583717cf5af2720f047de23752ee42cba8ff4a3f859d216e0580026ae diff --git a/skills/studytime-analysis/scripts/studytime_analysis.py b/skills/studytime-analysis/scripts/studytime_analysis.py index 294abdc..4c55837 100644 --- a/skills/studytime-analysis/scripts/studytime_analysis.py +++ b/skills/studytime-analysis/scripts/studytime_analysis.py @@ -13,7 +13,7 @@ import sys import psycopg2 import psycopg2.extras import pymysql -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from collections import defaultdict, OrderedDict # ── 配置 ────────────────────────────────────────────── @@ -148,6 +148,21 @@ def fetch_role_info(role_id): } +def check_retention(records, cutoff_days=14): + """ + 检查角色留存状态 + - 最近 cutoff_days 天内有完课记录 → "正常" + - 否则 → "流失" + 当无任何完课记录时,返回 "无完课记录" + """ + if not records: + return "无完课记录" + # 用本地时间比较(与 PG 存储时区一致 UTC+8) + cutoff = datetime.now() - timedelta(days=cutoff_days) + has_recent = any(r["updated_at"].replace(tzinfo=None) >= cutoff for r in records) + return "正常" if has_recent else "流失" + + def fetch_completion_records(role_id): """查询指定角色全部完课记录(包含寒暑假)""" params = {} @@ -321,7 +336,7 @@ def analyze_weekly_trend(records): # ── 输出格式化 ──────────────────────────────────────── -def format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis): +def format_report(role_id, role_info, retention_status, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis): """生成 Markdown 格式分析报告 Args: @@ -352,6 +367,8 @@ def format_report(role_id, role_info, all_records, non_holiday_records, holiday_ lines.append(f"| 年龄 | {role_info['age']} 岁 |") if role_info['phone_tail']: lines.append(f"| 账号手机号后4位 | {role_info['phone_tail']} |") + if retention_status: + lines.append(f"| 最近留存状态 | {retention_status} |") lines.append(f"") # ── 数据概况 ── @@ -566,12 +583,15 @@ def main(): # 角色基本信息(MySQL) role_info = fetch_role_info(role_id) + # 留存状态判定 + retention_status = check_retention(all_records) + # 一周分布分析:仅用非寒暑假数据 day_counts, weekday_periods = analyze_weekly_distribution(non_holiday_records) # 跨周趋势分析:用全部数据 weeks_data, analysis = analyze_weekly_trend(all_records) - report = format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis) + report = format_report(role_id, role_info, retention_status, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis) print(report)