- 自动删除已结束但仍包含TBD的事件
- 智能删除与确认比赛同时间段的TBD vs TBD占位符
- 改进事件分组逻辑,使用30分钟时间窗口
修复了9月11-12日日历中残留的TBD事件问题
🤖 Generated with Claude Code
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
253277620c
commit
e72661f4cd
14
CHANGELOG.md
14
CHANGELOG.md
@ -1,5 +1,18 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v3.9 - 2025-09-12 - 增强TBD事件清理功能
|
||||||
|
- **自动删除已结束的TBD事件**:
|
||||||
|
- 检查事件的结束时间,如果已过且仍包含TBD则自动删除
|
||||||
|
- 避免日历中保留已过期但未更新的TBD占位符
|
||||||
|
- 例如:删除已结束的 "BB vs TBD"、"Tidebd vs TBD" 等事件
|
||||||
|
- **智能删除TBD vs TBD占位符**:
|
||||||
|
- 当同一时间段(30分钟窗口)存在确认的比赛时,自动删除TBD vs TBD事件
|
||||||
|
- 解决了TBD vs TBD与确认比赛重复的问题
|
||||||
|
- 例如:9月11日的多个TBD vs TBD事件被正确清理
|
||||||
|
- **改进的事件分组逻辑**:
|
||||||
|
- 按30分钟时间窗口分组事件,更准确地识别同时间的比赛
|
||||||
|
- 优化了TBD事件与确认比赛的匹配算法
|
||||||
|
|
||||||
## v3.8 - 2025-09-08 - 修复重复比分显示问题
|
## v3.8 - 2025-09-08 - 修复重复比分显示问题
|
||||||
- **修复标题中重复比分的问题**:
|
- **修复标题中重复比分的问题**:
|
||||||
- 修复了在更新比赛比分时可能出现重复比分的bug(如 "0-2 0-1")
|
- 修复了在更新比赛比分时可能出现重复比分的bug(如 "0-2 0-1")
|
||||||
@ -143,6 +156,7 @@
|
|||||||
| v3.6 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| v3.6 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
| v3.7 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| v3.7 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
| v3.8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
| v3.8 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
|
||||||
|
| v3.9 | ✓ | ✓ | ✓ | ✓ | ✓+ | ✓ |
|
||||||
|
|
||||||
## 使用建议
|
## 使用建议
|
||||||
|
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
# Dota 2 Calendar Sync v3.8
|
# Dota 2 Calendar Sync v3.9
|
||||||
|
|
||||||
自动从 Liquipedia 获取 Dota 2 Tier 1 比赛信息并同步到 Google Calendar,支持自动更新比赛结果、时间变更、智能管理TBD占位事件和自动清理重复比赛。
|
自动从 Liquipedia 获取 Dota 2 Tier 1 比赛信息并同步到 Google Calendar,支持自动更新比赛结果、时间变更、智能管理TBD占位事件、自动清理过期和重复比赛。
|
||||||
|
|
||||||
## 功能
|
## 功能
|
||||||
|
|
||||||
@ -11,6 +11,7 @@
|
|||||||
- **检测并更新比赛时间变更**(赛程调整时自动同步)
|
- **检测并更新比赛时间变更**(赛程调整时自动同步)
|
||||||
- **智能管理TBD占位事件**(自动更新队伍信息,删除过期和被取代的事件)
|
- **智能管理TBD占位事件**(自动更新队伍信息,删除过期和被取代的事件)
|
||||||
- **自动清理重复比赛**(优先保留已完成的比赛记录)
|
- **自动清理重复比赛**(优先保留已完成的比赛记录)
|
||||||
|
- **增强的TBD事件清理**(删除已结束但仍包含TBD的事件,删除与确认比赛同时间的TBD占位符)
|
||||||
- 避免重复添加已存在的比赛
|
- 避免重复添加已存在的比赛
|
||||||
- 支持 dry-run 模式进行测试
|
- 支持 dry-run 模式进行测试
|
||||||
|
|
||||||
@ -87,6 +88,8 @@ python sync_dota2_matches.py --dry-run
|
|||||||
- **改进的TBD匹配**:1小时时间窗口匹配,更好处理赛程调整
|
- **改进的TBD匹配**:1小时时间窗口匹配,更好处理赛程调整
|
||||||
- **重复比赛清理**:自动检测并删除同队伍的重复事件
|
- **重复比赛清理**:自动检测并删除同队伍的重复事件
|
||||||
- **TBD事件自动删除**:当队伍确定后自动删除对应的TBD占位符
|
- **TBD事件自动删除**:当队伍确定后自动删除对应的TBD占位符
|
||||||
|
- **增强的过期事件清理**:自动删除已结束但仍包含TBD的事件
|
||||||
|
- **智能TBD vs TBD处理**:删除与确认比赛在同一时间段的TBD vs TBD占位符
|
||||||
|
|
||||||
2. **日历事件管理**:
|
2. **日历事件管理**:
|
||||||
- 自动设置比赛时长(根据 Bo 格式估算)
|
- 自动设置比赛时长(根据 Bo 格式估算)
|
||||||
|
|||||||
@ -998,10 +998,18 @@ class Dota2CalendarSync:
|
|||||||
if event_id in updated_tbd_events:
|
if event_id in updated_tbd_events:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Get event time
|
# Get event time and end time
|
||||||
event_start = event['start'].get('dateTime', event['start'].get('date'))
|
event_start = event['start'].get('dateTime', event['start'].get('date'))
|
||||||
event_dt = datetime.fromisoformat(event_start.replace('Z', '+00:00'))
|
event_dt = datetime.fromisoformat(event_start.replace('Z', '+00:00'))
|
||||||
|
|
||||||
|
# Get event end time for checking if match has ended
|
||||||
|
event_end = event.get('end', {}).get('dateTime', event.get('end', {}).get('date'))
|
||||||
|
if event_end:
|
||||||
|
event_end_dt = datetime.fromisoformat(event_end.replace('Z', '+00:00'))
|
||||||
|
else:
|
||||||
|
# If no end time, assume 3 hours duration
|
||||||
|
event_end_dt = event_dt + timedelta(hours=3)
|
||||||
|
|
||||||
# Use 30-minute window for "same time"
|
# Use 30-minute window for "same time"
|
||||||
time_key = (event_dt.year, event_dt.month, event_dt.day,
|
time_key = (event_dt.year, event_dt.month, event_dt.day,
|
||||||
event_dt.hour, event_dt.minute // 30)
|
event_dt.hour, event_dt.minute // 30)
|
||||||
@ -1013,14 +1021,14 @@ class Dota2CalendarSync:
|
|||||||
if 'vs TBD' in summary or 'TBD vs' in summary:
|
if 'vs TBD' in summary or 'TBD vs' in summary:
|
||||||
events_by_time[time_key]['tbd'].append(event)
|
events_by_time[time_key]['tbd'].append(event)
|
||||||
|
|
||||||
# Also check if it's expired (for TBD vs TBD only)
|
# Delete if match has ended (end time has passed) and still contains TBD
|
||||||
if 'TBD vs TBD' in summary and event_dt < now - timedelta(hours=2):
|
if event_end_dt < now:
|
||||||
if self.delete_calendar_event(event_id):
|
if self.delete_calendar_event(event_id):
|
||||||
print(f"🗑️ Deleted expired TBD event: {summary} ({event_dt.strftime('%Y-%m-%d %H:%M UTC')})")
|
print(f"🗑️ Deleted ended TBD event: {summary} (ended at {event_end_dt.strftime('%Y-%m-%d %H:%M UTC')})")
|
||||||
deleted_tbd_count += 1
|
deleted_tbd_count += 1
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
else:
|
else:
|
||||||
print(f"✗ Failed to delete TBD event: {summary}")
|
print(f"✗ Failed to delete ended TBD event: {summary}")
|
||||||
error_count += 1
|
error_count += 1
|
||||||
continue # Don't process this event further
|
continue # Don't process this event further
|
||||||
|
|
||||||
@ -1040,25 +1048,42 @@ class Dota2CalendarSync:
|
|||||||
for tbd_event in events['tbd']:
|
for tbd_event in events['tbd']:
|
||||||
tbd_summary = tbd_event.get('summary', '')
|
tbd_summary = tbd_event.get('summary', '')
|
||||||
|
|
||||||
# Extract team from TBD event
|
# Check if this is a complete TBD vs TBD event
|
||||||
team_match = re.search(r'(\w+)\s+vs\s+TBD|TBD\s+vs\s+(\w+)', tbd_summary)
|
if 'TBD vs TBD' in tbd_summary:
|
||||||
if team_match:
|
# Delete TBD vs TBD when there's any confirmed match at the same time
|
||||||
team_in_tbd = team_match.group(1) or team_match.group(2)
|
# Since TBD vs TBD is a placeholder, any confirmed match supersedes it
|
||||||
|
if events['confirmed']:
|
||||||
# Check if this team has a confirmed match
|
confirmed_event = events['confirmed'][0] # Use first confirmed match for logging
|
||||||
for confirmed_event in events['confirmed']:
|
|
||||||
confirmed_summary = confirmed_event.get('summary', '')
|
confirmed_summary = confirmed_event.get('summary', '')
|
||||||
if team_in_tbd and team_in_tbd in confirmed_summary:
|
if self.delete_calendar_event(tbd_event['id']):
|
||||||
# This TBD event has been superseded
|
print(f"🗑️ Deleted TBD vs TBD event at same time as confirmed match")
|
||||||
if self.delete_calendar_event(tbd_event['id']):
|
print(f" TBD event: {tbd_summary}")
|
||||||
print(f"🗑️ Deleted superseded TBD event: {tbd_summary}")
|
print(f" Confirmed match: {confirmed_summary}")
|
||||||
print(f" Replaced by: {confirmed_summary}")
|
deleted_tbd_count += 1
|
||||||
deleted_tbd_count += 1
|
time.sleep(0.2)
|
||||||
time.sleep(0.2)
|
else:
|
||||||
else:
|
print(f"✗ Failed to delete TBD vs TBD event: {tbd_summary}")
|
||||||
print(f"✗ Failed to delete TBD event: {tbd_summary}")
|
error_count += 1
|
||||||
error_count += 1
|
else:
|
||||||
break
|
# For partial TBD events (one team is known), check for team match
|
||||||
|
team_match = re.search(r'(\w+)\s+vs\s+TBD|TBD\s+vs\s+(\w+)', tbd_summary)
|
||||||
|
if team_match:
|
||||||
|
team_in_tbd = team_match.group(1) or team_match.group(2)
|
||||||
|
|
||||||
|
# Check if this team has a confirmed match
|
||||||
|
for confirmed_event in events['confirmed']:
|
||||||
|
confirmed_summary = confirmed_event.get('summary', '')
|
||||||
|
if team_in_tbd and team_in_tbd in confirmed_summary:
|
||||||
|
# This TBD event has been superseded
|
||||||
|
if self.delete_calendar_event(tbd_event['id']):
|
||||||
|
print(f"🗑️ Deleted superseded TBD event: {tbd_summary}")
|
||||||
|
print(f" Replaced by: {confirmed_summary}")
|
||||||
|
deleted_tbd_count += 1
|
||||||
|
time.sleep(0.2)
|
||||||
|
else:
|
||||||
|
print(f"✗ Failed to delete TBD event: {tbd_summary}")
|
||||||
|
error_count += 1
|
||||||
|
break
|
||||||
|
|
||||||
# Delete duplicate TBD vs TBD events at the same time
|
# Delete duplicate TBD vs TBD events at the same time
|
||||||
for time_key, events in tbd_by_time.items():
|
for time_key, events in tbd_by_time.items():
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user