Fix start/goal processes

This commit is contained in:
2025-09-02 17:10:33 +09:00
parent d6b40bd0f8
commit 0acaa6ea1f
2 changed files with 130 additions and 49 deletions

View File

@ -4,7 +4,7 @@ from datetime import datetime, timezone
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rog.models import Location2025, NewEvent2, Entry, GpsLog, TeamStart, TeamGoal
from rog.models import Location2025, NewEvent2, Entry, GpsLog
import logging
import uuid
import os
@ -218,25 +218,36 @@ def start_checkin(request):
"message": "指定されたゼッケン番号のチームが見つかりません"
}, status=status.HTTP_404_NOT_FOUND)
# 既にスタート済みかチェック
if hasattr(entry, 'start_info'):
logger.warning(f"Team {entry.team_name} (zekken: {zekken_number}) already started at {entry.start_info.start_time}")
# 既にスタート済みかチェックGpsLogでSTARTレコードを確認
existing_start = GpsLog.objects.filter(
entry=entry,
cp_number="START",
serial_number=0
).first()
if existing_start:
logger.warning(f"Team {entry.team_name} (zekken: {zekken_number}) already started at {existing_start.checkin_time}")
return Response({
"status": "WARNING",
"message": "このチームは既にスタートしています",
"start_time": entry.start_info.start_time.strftime("%Y-%m-%d %H:%M:%S"),
"start_time": existing_start.checkin_time.strftime("%Y-%m-%d %H:%M:%S"),
"team_name": entry.team_name
})
# トランザクション開始
with transaction.atomic():
# スタート情報を登録
start_info = TeamStart.objects.create(
# スタート情報をGpsLogとして登録
start_info = GpsLog.objects.create(
entry=entry,
start_time=timezone.now()
cp_number="START",
serial_number=0,
latitude=0.0,
longitude=0.0,
checkin_time=timezone.now(),
extra_data={"source": "admin_start"}
)
logger.info(f"Team {entry.team_name} (zekken: {zekken_number}) started at {start_info.start_time}")
logger.info(f"Team {entry.team_name} (zekken: {zekken_number}) started at {start_info.checkin_time}")
return Response({
"status": "OK",
@ -244,7 +255,7 @@ def start_checkin(request):
"team_name": entry.team_name,
"zekken_number": zekken_number,
"event_code": event_code,
"start_time": start_info.start_time.strftime("%Y-%m-%d %H:%M:%S")
"start_time": start_info.checkin_time.strftime("%Y-%m-%d %H:%M:%S")
})
except Exception as e:
@ -331,11 +342,24 @@ def add_checkin(request):
logger.info(f"[ADMIN_CHECKIN] ✅ Team found - ID: {request_id}, team_name: '{entry.team_name}', zekken: {zekken_number}, entry_id: {entry.id}")
# チームがスタートしているか確認(オプション)
if not hasattr(entry, 'start_info'):
start_record = GpsLog.objects.filter(
entry=entry,
cp_number="START",
serial_number=0
).first()
if not start_record:
# スタート情報がない場合は自動的にスタートさせる
# 注意: 管理画面からの操作なので、自動スタートを許可
from rog.models import TeamStart
TeamStart.objects.create(entry=entry, start_time=timezone.now())
GpsLog.objects.create(
entry=entry,
cp_number="START",
serial_number=0,
latitude=0.0,
longitude=0.0,
checkin_time=timezone.now(),
extra_data={"auto_start": True, "source": "admin_bulk_checkin"}
)
logger.info(f"[ADMIN_CHECKIN] ✅ Auto-started team - ID: {request_id}, team_name: '{entry.team_name}', zekken: {zekken_number}")
# チェックポイントリストを解析
@ -764,22 +788,41 @@ def goal_checkin(request):
"message": "指定されたゼッケン番号のチームが見つかりません"
}, status=status.HTTP_404_NOT_FOUND)
# チームがスタートしているか確認
if not hasattr(entry, 'start_info'):
# チームがスタートしているか確認GpsLogでSTARTレコードを確認
start_record = GpsLog.objects.filter(
entry=entry,
cp_number="START",
serial_number=0
).first()
if not start_record:
# 管理画面からの操作なので、自動的にスタートさせる
from rog.models import TeamStart
TeamStart.objects.create(entry=entry, start_time=timezone.now())
GpsLog.objects.create(
entry=entry,
cp_number="START",
serial_number=0,
latitude=0.0,
longitude=0.0,
checkin_time=timezone.now(),
extra_data={"auto_start": True, "source": "admin_goal"}
)
logger.info(f"Auto-started team {entry.team_name} (zekken: {zekken_number})")
# 既にゴールしているかチェック
if hasattr(entry, 'goal_info'):
logger.warning(f"Team {entry.team_name} (zekken: {zekken_number}) already reached goal at {entry.goal_info.goal_time}")
# 既にゴールしているかチェックGpsLogでGOALレコードを確認
existing_goal = GpsLog.objects.filter(
entry=entry,
cp_number="GOAL",
serial_number=9999
).first()
if existing_goal:
logger.warning(f"Team {entry.team_name} (zekken: {zekken_number}) already reached goal at {existing_goal.checkin_time}")
return Response({
"status": "WARNING",
"message": "このチームは既にゴールしています",
"goal_time": entry.goal_info.goal_time.strftime("%Y-%m-%d %H:%M:%S"),
"goal_time": existing_goal.checkin_time.strftime("%Y-%m-%d %H:%M:%S"),
"team_name": entry.team_name,
"scoreboard_url": entry.goal_info.scoreboard_url
"scoreboard_url": existing_goal.extra_data.get('scoreboard_url', '') if existing_goal.extra_data else ''
})
# ゴール時間の処理
@ -812,12 +855,18 @@ def goal_checkin(request):
# スコアボードへのURL
scoreboard_url = f"{settings.MEDIA_URL}scoreboards/{scoreboard_filename}"
# ゴール情報を登録
goal_info = TeamGoal.objects.create(
# ゴール情報をGpsLogとして登録
goal_info = GpsLog.objects.create(
entry=entry,
goal_time=goal_time,
score=score,
scoreboard_url=scoreboard_url
cp_number="GOAL",
serial_number=9999,
latitude=0.0,
longitude=0.0,
checkin_time=goal_time,
extra_data={
"score": score,
"scoreboard_url": scoreboard_url
}
)
logger.info(f"Team {entry.team_name} (zekken: {zekken_number}) reached goal at {goal_time} with score {score}")

View File

@ -2,7 +2,7 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from rog.models import NewEvent2, Entry, Location2025, TeamStart, TeamGoal
from rog.models import NewEvent2, Entry, Location2025, GpsLog
from rog.models import GpsLog
import logging
from django.db.models import F, Q
@ -242,8 +242,11 @@ def start_from_rogapp(request):
# リクエストからパラメータを取得
event_code = request.data.get('event_code')
team_name = request.data.get('team_name')
latitude = request.data.get('latitude', 0.0)
longitude = request.data.get('longitude', 0.0)
extra_data = request.data.get('extra_data', {})
logger.info(f"[COMPETITION_START] Request parameters - ID: {request_id}, event_code: '{event_code}', team_name: '{team_name}', user_agent: '{user_agent[:100]}'")
logger.info(f"[COMPETITION_START] Request parameters - ID: {request_id}, event_code: '{event_code}', team_name: '{team_name}', GPS: ({latitude},{longitude}), user_agent: '{user_agent[:100]}'")
# パラメータ検証
if not all([event_code, team_name]):
@ -280,9 +283,15 @@ def start_from_rogapp(request):
logger.info(f"[COMPETITION_START] ✅ Team found - ID: {request_id}, Entry ID: {entry.id}, Team: '{team_name}', Zekken: {entry.zekken_number}, Category: '{entry.category.category_name if entry.category else 'N/A'}', Owner: '{entry.owner.email if entry.owner else 'N/A'}')")
# 既にスタート済みかチェック
if hasattr(entry, 'start_info'):
logger.warning(f"[COMPETITION_START] ⚠️ Team already started - ID: {request_id}, team_name: '{team_name}', zekken: {entry.zekken_number}, start_time: {entry.start_info.start_time}, Client IP: {client_ip}")
# 既にスタート済みかチェックGpsLogでSTARTレコードを確認
existing_start = GpsLog.objects.filter(
entry=entry,
cp_number="START",
serial_number=0
).first()
if existing_start:
logger.warning(f"[COMPETITION_START] ⚠️ Team already started - ID: {request_id}, team_name: '{team_name}', zekken: {entry.zekken_number}, start_time: {existing_start.checkin_time}, Client IP: {client_ip}")
return Response({
"status": "WARNING",
"message": "このチームは既にスタートしています",
@ -291,16 +300,21 @@ def start_from_rogapp(request):
# トランザクション開始
with transaction.atomic():
# スタート情報を登録
start_info = TeamStart.objects.create(
# スタート情報をGpsLogとして登録
start_info = GpsLog.objects.create(
entry=entry,
start_time=timezone.now()
cp_number="START", # スタート専用のCP番号
serial_number=0, # スタート記録の固定シリアル番号
latitude=latitude if latitude else 0.0,
longitude=longitude if longitude else 0.0,
checkin_time=timezone.now(),
extra_data=extra_data
)
# 統計情報取得
total_checkpoints = Location2025.objects.filter(event=event).count() if hasattr(Location2025, 'event') else 0
logger.info(f"[COMPETITION_START] 🎉 SUCCESS - ID: {request_id}, Team: '{team_name}', Zekken: {entry.zekken_number}, Event: '{event_code}', Start Time: {start_info.start_time}, Total CPs Available: {total_checkpoints}, Client IP: {client_ip}, User: {user_info}")
logger.info(f"[COMPETITION_START] 🎉 SUCCESS - ID: {request_id}, Team: '{team_name}', Zekken: {entry.zekken_number}, Event: '{event_code}', Start Time: {start_info.checkin_time}, GPS: ({latitude},{longitude}), Total CPs Available: {total_checkpoints}, Client IP: {client_ip}, User: {user_info}")
return Response({
"status": "OK",
@ -605,22 +619,34 @@ def goal_from_rogapp(request):
logger.info(f"[GOAL] ✅ Team found - ID: {request_id}, team_name: '{team_name}', zekken: {entry.zekken_number}, entry_id: {entry.id}")
# チームがスタートしているか確認
if not hasattr(entry, 'start_info'):
# チームがスタートしているか確認GpsLogでSTARTレコードを確認
start_record = GpsLog.objects.filter(
entry=entry,
cp_number="START",
serial_number=0
).first()
if not start_record:
logger.warning(f"Team {team_name} has not started yet")
return Response({
"status": "ERROR",
"message": "このチームはまだスタートしていません。先にスタート処理を行ってください。"
}, status=status.HTTP_400_BAD_REQUEST)
# 既にゴールしているかチェック
if hasattr(entry, 'goal_info'):
logger.warning(f"Team {team_name} already reached goal at {entry.goal_info.goal_time}")
# 既にゴールしているかチェックGpsLogでGOALレコードを確認
existing_goal = GpsLog.objects.filter(
entry=entry,
cp_number="GOAL",
serial_number=9999
).first()
if existing_goal:
logger.warning(f"Team {team_name} already reached goal at {existing_goal.checkin_time}")
return Response({
"status": "WARNING",
"message": "このチームは既にゴールしています",
"goal_time": entry.goal_info.goal_time.strftime("%Y-%m-%d %H:%M:%S"),
"scoreboard_url": entry.goal_info.scoreboard_url
"goal_time": existing_goal.checkin_time.strftime("%Y-%m-%d %H:%M:%S"),
"scoreboard_url": existing_goal.extra_data.get('scoreboard_url', '') if existing_goal.extra_data else ''
})
# ゴール時間の処理
@ -649,13 +675,19 @@ def goal_from_rogapp(request):
# スコアボードへのURL
scoreboard_url = f"{settings.MEDIA_URL}scoreboards/{scoreboard_filename}"
# ゴール情報を登録
goal_info = TeamGoal.objects.create(
# ゴール情報をGpsLogとして登録
goal_info = GpsLog.objects.create(
entry=entry,
goal_time=goal_time,
image_url=image_url,
score=score,
scoreboard_url=scoreboard_url
cp_number="GOAL",
serial_number=9999, # ゴール記録の固定シリアル番号
latitude=0.0, # ゴールポイントの座標(固定)
longitude=0.0,
checkin_time=goal_time,
image_address=image_url,
extra_data={
"score": score,
"scoreboard_url": scoreboard_url
}
)
logger.info(f"[GOAL] ✅ SUCCESS - Team: {team_name}, Zekken: {entry.zekken_number}, Event: {event_code}, Goal Time: {goal_time}, Score: {score}, Has Image: {bool(image_url)}, Client IP: {client_ip}, User: {user_info}")