studytime-analysis: 报告开头增加角色基本信息(角色ID、账号ID、手机号后4位、名字、性别、年龄)
This commit is contained in:
parent
2e3caefacb
commit
ed6c864197
@ -7,4 +7,4 @@ lark_wiki_operate_as_bot 2a37701f568849f03eb46dd938baeda171380fe252b698ac8bda69c
|
||||
vala_git_workspace_backup 4cf352bec88fe84af065ba1ffcbb06647b77df0e01860faaf0bca9fd64b968ec
|
||||
cron-schedule b1879fa59d60e3d99cea1138674f7abac84a4aecd32743b801d41bfd6ed7181d
|
||||
study-analysis 33217dc132073ecd47b921800834f6df89494da9e7708fa90f15b3de7742e37f
|
||||
studytime-analysis ab15a60381dd281a229004977d3137a9ac59bca048743069dc6e2875e1075682
|
||||
studytime-analysis 042178f9f7e97eeef366fd619403f4d0c8e0dce290abf17af662dddfa67c4e83
|
||||
|
||||
@ -38,8 +38,8 @@ python3 skills/studytime-analysis/scripts/studytime_analysis.py <role_id>
|
||||
|
||||
## 数据库说明
|
||||
|
||||
- **数据源**: PostgreSQL Online (`vala` 库)
|
||||
- **核心表**: `user_chapter_play_record_0~7`(完课记录,8张分表)
|
||||
- **完课数据源**: PostgreSQL Online (`vala` 库) — `user_chapter_play_record_0~7`(8张分表)
|
||||
- **角色信息源**: MySQL Online (`vala_user` 库) — `vala_app_character` + `vala_app_account`
|
||||
- **筛选**: `play_status = 1`(已完成),查询全量数据(不按月过滤)
|
||||
- **寒暑假处理**: 1-2月(寒假)和 7-8月(暑假)的记录仅在一周时间分布中排除,跨周趋势和完课明细完整保留
|
||||
- **注意**: 表名无 `bi_` 前缀;课程通过 `level` + `chapter_id` 字段展示
|
||||
@ -47,7 +47,8 @@ python3 skills/studytime-analysis/scripts/studytime_analysis.py <role_id>
|
||||
## 输出说明
|
||||
|
||||
脚本输出为 Markdown 格式的分析报告,可直接发送给用户。包含:
|
||||
- 基本信息(角色ID、完课总数、寒暑假/非寒暑假数量)
|
||||
- 角色基本信息(角色ID、账号ID、手机号后4位、角色名字、性别、年龄)
|
||||
- 数据概况(完课总数、寒暑假/非寒暑假数量)
|
||||
- 📌 一周时间分布数据范围说明
|
||||
- 一周时间分布表 + 规律总结(仅非寒暑假)
|
||||
- 跨周学习趋势表 + 趋势分析(全部数据)
|
||||
|
||||
@ -12,6 +12,7 @@ import os
|
||||
import sys
|
||||
import psycopg2
|
||||
import psycopg2.extras
|
||||
import pymysql
|
||||
from datetime import datetime, timedelta
|
||||
from collections import defaultdict, OrderedDict
|
||||
|
||||
@ -24,6 +25,16 @@ PG_CONFIG = {
|
||||
"dbname": os.environ.get("PG_DB_DATABASE", "vala"),
|
||||
}
|
||||
|
||||
# MySQL Online (vala_user 库 — 角色基本信息)
|
||||
MYSQL_CONFIG = {
|
||||
"host": os.environ.get("MYSQL_HOST_online", "bj-cdb-dh2fkqa0.sql.tencentcdb.com"),
|
||||
"port": int(os.environ.get("MYSQL_PORT_online", "27751")),
|
||||
"user": os.environ.get("MYSQL_USERNAME_online", "read_only"),
|
||||
"password": os.environ.get("MYSQL_PASSWORD_online", ""),
|
||||
"db": "vala_user",
|
||||
"charset": "utf8mb4",
|
||||
}
|
||||
|
||||
EXCLUDED_MONTHS = (1, 2, 7, 8) # 寒假1-2月, 暑假7-8月
|
||||
|
||||
WEEKDAY_NAMES = ["周一", "周二", "周三", "周四", "周五", "周六", "周日"]
|
||||
@ -51,6 +62,92 @@ def get_connection():
|
||||
return conn
|
||||
|
||||
|
||||
def get_mysql_connection():
|
||||
"""连接 MySQL Online (vala_user 库)"""
|
||||
conn = pymysql.connect(
|
||||
host=MYSQL_CONFIG["host"],
|
||||
port=MYSQL_CONFIG["port"],
|
||||
user=MYSQL_CONFIG["user"],
|
||||
password=MYSQL_CONFIG["password"],
|
||||
db=MYSQL_CONFIG["db"],
|
||||
charset=MYSQL_CONFIG["charset"],
|
||||
)
|
||||
return conn
|
||||
|
||||
|
||||
def fetch_role_info(role_id):
|
||||
"""
|
||||
从 MySQL vala_user 库查询角色基本信息
|
||||
返回 dict: role_id, account_id, nickname, gender, age, phone_tail
|
||||
"""
|
||||
sql = """
|
||||
SELECT
|
||||
c.id AS role_id,
|
||||
c.account_id,
|
||||
c.nickname,
|
||||
c.gender,
|
||||
c.birthday,
|
||||
a.tel
|
||||
FROM vala_app_character c
|
||||
LEFT JOIN vala_app_account a ON c.account_id = a.id
|
||||
WHERE c.id = %s
|
||||
"""
|
||||
conn = get_mysql_connection()
|
||||
try:
|
||||
with conn.cursor() as cur:
|
||||
cur.execute(sql, (role_id,))
|
||||
row = cur.fetchone()
|
||||
finally:
|
||||
conn.close()
|
||||
|
||||
if not row:
|
||||
return None
|
||||
|
||||
role_id_val, account_id, nickname, gender, birthday, tel = row
|
||||
|
||||
# 性别映射
|
||||
gender_str = ""
|
||||
if gender == 0:
|
||||
gender_str = "女"
|
||||
elif gender == 1:
|
||||
gender_str = "男"
|
||||
elif gender is not None:
|
||||
gender_str = str(gender)
|
||||
|
||||
# 年龄(从 birthday 推算)
|
||||
age = ""
|
||||
if birthday:
|
||||
try:
|
||||
# birthday 可能是 "2015-5-28" 或 "2015-05-28" 格式
|
||||
parts = str(birthday).split("-")
|
||||
if len(parts) >= 1 and parts[0].isdigit():
|
||||
birth_year = int(parts[0])
|
||||
current_year = datetime.now().year
|
||||
age = current_year - birth_year
|
||||
except (ValueError, IndexError):
|
||||
pass
|
||||
|
||||
# 手机号后4位
|
||||
phone_tail = ""
|
||||
if tel:
|
||||
tel_str = str(tel)
|
||||
# tel 可能是 "186****1625" 格式,取最后4位
|
||||
digits = ''.join(c for c in tel_str if c.isdigit())
|
||||
if len(digits) >= 4:
|
||||
phone_tail = digits[-4:]
|
||||
elif digits:
|
||||
phone_tail = digits
|
||||
|
||||
return {
|
||||
"role_id": role_id_val,
|
||||
"account_id": account_id,
|
||||
"nickname": nickname or "",
|
||||
"gender": gender_str,
|
||||
"age": age,
|
||||
"phone_tail": phone_tail,
|
||||
}
|
||||
|
||||
|
||||
def fetch_completion_records(role_id):
|
||||
"""查询指定角色全部完课记录(包含寒暑假)"""
|
||||
params = {}
|
||||
@ -224,7 +321,7 @@ def analyze_weekly_trend(records):
|
||||
|
||||
# ── 输出格式化 ────────────────────────────────────────
|
||||
|
||||
def format_report(role_id, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis):
|
||||
def format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis):
|
||||
"""生成 Markdown 格式分析报告
|
||||
|
||||
Args:
|
||||
@ -239,6 +336,25 @@ def format_report(role_id, all_records, non_holiday_records, holiday_count, day_
|
||||
|
||||
lines.append(f"# 📊 学习时间分析报告 — 角色 {role_id}")
|
||||
lines.append(f"")
|
||||
|
||||
# ── 角色基本信息 ──
|
||||
if role_info:
|
||||
lines.append(f"## 基本信息")
|
||||
lines.append(f"")
|
||||
lines.append(f"| 项目 | 详情 |")
|
||||
lines.append(f"|------|------|")
|
||||
lines.append(f"| 角色ID | {role_info['role_id']} |")
|
||||
lines.append(f"| 账号ID | {role_info['account_id']} |")
|
||||
if role_info['nickname']:
|
||||
lines.append(f"| 角色名字 | {role_info['nickname']} |")
|
||||
lines.append(f"| 性别 | {role_info['gender']} |")
|
||||
if role_info['age']:
|
||||
lines.append(f"| 年龄 | {role_info['age']} 岁 |")
|
||||
if role_info['phone_tail']:
|
||||
lines.append(f"| 账号手机号后4位 | {role_info['phone_tail']} |")
|
||||
lines.append(f"")
|
||||
|
||||
# ── 数据概况 ──
|
||||
lines.append(f"**分析时间**: {now_str}")
|
||||
lines.append(f"**完课记录总数**: {len(all_records)} 条")
|
||||
if holiday_count > 0:
|
||||
@ -447,12 +563,15 @@ def main():
|
||||
non_holiday_records, holiday_records = split_records(all_records)
|
||||
holiday_count = len(holiday_records)
|
||||
|
||||
# 角色基本信息(MySQL)
|
||||
role_info = fetch_role_info(role_id)
|
||||
|
||||
# 一周分布分析:仅用非寒暑假数据
|
||||
day_counts, weekday_periods = analyze_weekly_distribution(non_holiday_records)
|
||||
# 跨周趋势分析:用全部数据
|
||||
weeks_data, analysis = analyze_weekly_trend(all_records)
|
||||
|
||||
report = format_report(role_id, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis)
|
||||
report = format_report(role_id, role_info, all_records, non_holiday_records, holiday_count, day_counts, weekday_periods, weeks_data, analysis)
|
||||
|
||||
print(report)
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user