def get_effective_progress():
# split 视图的"有效完成进度":
# 键 = new_group_id(拆分组); 值 = {op_type: (date, duration_sec)}
- # 含"父组完成 → 各子单元继承"展开: 若某 groupid 被拆分, 且其本身已有某 op 完成记录,
- # 则每个子单元 new_group_id 也视为完成(用于早期已学完的拆分组 G25/G46/G47 等)。
+ # 含"父组整体完成 → 各子单元继承"展开: 仅当某 groupid 被拆分且其本身作为整体学习
+ # (记录 new_group_id 为空或等于父组id)时, 各子单元才视为完成; 子单元专属记录不外溢到兄弟。
if not os.path.exists(DATABASE_PATH):
return {}
conn = sqlite3.connect(DATABASE_PATH)
eff = {}
for ng, op, date, dur in cur.fetchall():
eff.setdefault(ng, {})[op] = (date, dur or 0)
- # 父组完成情况: 按 group_id 聚合
+ # 父组"整体学习"完成情况: 仅当记录代表整个父组(原 groupid 作为整体学习,
+ # new_group_id 为空或等于父组id)时才向子单元继承; 子单元专属记录不外溢。
cur.execute("""
SELECT group_id, op_type, MAX(COALESCE(log_date, created_at))
- FROM study_logs WHERE status='completed' GROUP BY group_id, op_type
+ FROM study_logs
+ WHERE status='completed'
+ AND (new_group_id IS NULL OR new_group_id = CAST(group_id AS TEXT))
+ GROUP BY group_id, op_type
""")
parent = {}
for gid, op, date in cur.fetchall():
conn.close()
# 展开: 父组(被拆分)的每条完成记录, 复制给其每个子单元 new_group_id
expanded = [] # (day, op, ng, gid)
- for day, op_type, ng, gid in base:
- ng = ng if ng else str(gid)
+ for day, op_type, raw_ng, gid in base:
+ ng = raw_ng if raw_ng else str(gid)
expanded.append((day, op_type, ng, str(gid)))
- if str(gid) in subs:
+ # 仅"父组整体学习"记录(new_group_id 为空或等于父组id)才展开到各子单元;
+ # 子单元专属记录不外溢到兄弟子单元。
+ if str(gid) in subs and (raw_ng is None or raw_ng == str(gid)):
for sng in subs[str(gid)]:
if sng != ng:
expanded.append((day, op_type, sng, str(gid)))