优化TBD比赛处理逻辑

- 实现智能去重:相同时间、相同轮次的TBD比赛只保留一个代表
- 新增TBD比赛自动更新功能:当队伍确定后自动更新日历事件
- 改进事件匹配逻辑:三层匹配机制确保准确跟踪
- 新增update_event_with_teams方法专门处理队伍更新
- 更新README和CHANGELOG文档说明新功能

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ching L 2025-09-05 17:25:21 +08:00
parent dc63c9bd01
commit 63a1559e86
3 changed files with 115 additions and 8 deletions

View File

@ -1,5 +1,17 @@
# Changelog # Changelog
## v3.2 - TBD 比赛优化
- **智能去重机制**
- 相同时间、相同轮次的多个 TBD 比赛只保留一个代表
- 避免日历中出现大量重复的 TBD 条目
- **TBD 比赛自动更新**
- 当 TBD 比赛的队伍确定后,自动更新对应的日历事件
- 通过时间和锦标赛信息智能匹配 TBD 事件
- 新增 `update_event_with_teams` 方法专门处理队伍更新
- **改进的事件匹配逻辑**
- 三层匹配机制ID 匹配 → 队伍+锦标赛匹配 → 时间+锦标赛匹配
- 确保 TBD 比赛更新后仍能正确跟踪
## v3.1 - 格式优化更新 ## v3.1 - 格式优化更新
- **新的标题格式**: - **新的标题格式**:
- 之前: `Dota 2 - The International 2025: Team1 vs Team2` - 之前: `Dota 2 - The International 2025: Team1 vs Team2`
@ -28,12 +40,13 @@
## 功能对比 ## 功能对比
| 版本 | 同步比赛 | 更新结果 | 时间变更 | 新格式 | | 版本 | 同步比赛 | 更新结果 | 时间变更 | 新格式 | TBD优化 |
|------|---------|---------|---------|--------| |------|---------|---------|---------|--------|---------|
| v1.0 | ✓ | ✗ | ✗ | ✗ | | v1.0 | ✓ | ✗ | ✗ | ✗ | ✗ |
| v2.0 | ✓ | ✓ | ✗ | ✗ | | v2.0 | ✓ | ✓ | ✗ | ✗ | ✗ |
| v3.0 | ✓ | ✓ | ✓ | ✗ | | v3.0 | ✓ | ✓ | ✓ | ✗ | ✗ |
| v3.1 | ✓ | ✓ | ✓ | ✓ | | v3.1 | ✓ | ✓ | ✓ | ✓ | ✗ |
| v3.2 | ✓ | ✓ | ✓ | ✓ | ✓ |
## 使用建议 ## 使用建议

View File

@ -80,6 +80,7 @@ python sync_dota2_matches.py --dry-run
- 自动识别 Tier 1、Premier、Major 级别赛事 - 自动识别 Tier 1、Premier、Major 级别赛事
- 支持 The International (TI) 赛事 - 支持 The International (TI) 赛事
- 提取比赛格式Bo1、Bo3、Bo5 - 提取比赛格式Bo1、Bo3、Bo5
- **智能去重**:相同时间、相同轮次的 TBD 比赛只保留一个代表
2. **日历事件管理** 2. **日历事件管理**
- 自动设置比赛时长(根据 Bo 格式估算) - 自动设置比赛时长(根据 Bo 格式估算)
@ -87,7 +88,8 @@ python sync_dota2_matches.py --dry-run
- 使用蓝色标记 Dota 2 事件 - 使用蓝色标记 Dota 2 事件
- 避免重复添加 - 避免重复添加
- **自动更新已完成比赛的结果** - **自动更新已完成比赛的结果**
- **在标题添加 [COMPLETED] 标记** - **在标题添加完成标记(✓ + 比分)**
- **TBD 比赛队伍确定后自动更新**
3. **错误处理** 3. **错误处理**
- 网络请求超时处理 - 网络请求超时处理

View File

@ -398,6 +398,67 @@ class Dota2CalendarSync:
print(f"Error updating event time: {e}") print(f"Error updating event time: {e}")
return False return False
def update_event_with_teams(self, event_id, match_data):
"""Update a TBD event with actual team names"""
try:
# Get the existing event
event = self.service.events().get(
calendarId=self.calendar_id,
eventId=event_id
).execute()
team1 = match_data.get('team1', 'TBD')
team2 = match_data.get('team2', 'TBD')
tournament = match_data.get('tournament', '')
# Update summary with actual team names
if tournament:
new_summary = f"{team1} vs {team2} [{tournament}]"
else:
new_summary = f"{team1} vs {team2}"
# Update description
description = event.get('description', '')
# Update the Match line
description = re.sub(
r'Match: .*?\n',
f"Match: {team1} vs {team2}\n",
description
)
# Update the ID to the new one
if 'ID:' in description:
description = re.sub(
r'ID: [a-f0-9]+',
f"ID: {match_data.get('id', '')}",
description
)
# Add update timestamp
if 'Teams updated:' in description:
description = re.sub(
r'Teams updated:.*',
f"Teams updated: {datetime.now(pytz.UTC).strftime('%Y-%m-%d %H:%M UTC')}",
description
)
else:
description = description.replace('\nSource:', f"\nTeams updated: {datetime.now(pytz.UTC).strftime('%Y-%m-%d %H:%M UTC')}\nSource:")
event['summary'] = new_summary
event['description'] = description
# Update the event
updated_event = self.service.events().update(
calendarId=self.calendar_id,
eventId=event_id,
body=event
).execute()
return True
except Exception as e:
print(f"Error updating event with teams: {e}")
return False
def update_event_with_result(self, event_id, match_data): def update_event_with_result(self, event_id, match_data):
"""Update an existing calendar event with match results""" """Update an existing calendar event with match results"""
try: try:
@ -525,9 +586,40 @@ class Dota2CalendarSync:
if match_key in existing_events['_by_match']: if match_key in existing_events['_by_match']:
existing_event = existing_events['_by_match'][match_key] existing_event = existing_events['_by_match'][match_key]
# Special handling for TBD matches that might have been updated
# Look for TBD events at the same time and tournament
if not existing_event and '_by_match' in existing_events:
# Check if this match used to be TBD
for event_key, event in existing_events['_by_match'].items():
if 'TBD_TBD' in event_key and tournament in event_key:
# Check if time matches
event_start = event['start'].get('dateTime', event['start'].get('date'))
event_dt = datetime.fromisoformat(event_start.replace('Z', '+00:00'))
if abs((event_dt - match_time).total_seconds()) < 300: # Within 5 minutes
existing_event = event
print(f" → Found TBD match to update: {team1} vs {team2}")
break
if existing_event: if existing_event:
# Check if this is a TBD match that now has team names
summary = existing_event.get('summary', '')
is_tbd_update = 'TBD' in summary and (team1 != 'TBD' or team2 != 'TBD')
if is_tbd_update:
# Update TBD match with actual teams
if dry_run:
print(f"◯ Would update TBD match with teams: {team1} vs {team2}")
updated_count += 1
else:
if self.update_event_with_teams(existing_event['id'], match):
print(f"✓ Updated TBD match with teams: {team1} vs {team2}")
updated_count += 1
time.sleep(0.2)
else:
print(f"✗ Failed to update TBD match: {team1} vs {team2}")
error_count += 1
# Check if time has changed # Check if time has changed
if update_times: elif update_times:
event_start = existing_event['start'].get('dateTime', existing_event['start'].get('date')) event_start = existing_event['start'].get('dateTime', existing_event['start'].get('date'))
if self.check_time_difference(event_start, match_time): if self.check_time_difference(event_start, match_time):