fix goaltime issue on server side

This commit is contained in:
hayano
2024-11-03 05:16:05 +00:00
parent c6969d7afa
commit e992e834da
2 changed files with 84 additions and 31 deletions

View File

@ -2406,11 +2406,11 @@ def get_team_info(request, zekken_number):
# start_datetime = -1(ロゲ開始)のcreate_at
logger.debug(f"self.rogaining={entry.event.self_rogaining} => start_datetime = -1(ロゲ開始)のcreate_at")
# チームのゴール時間を取得
# チームの最初のゴール時間を取得
goal_record = GoalImages.objects.filter(
team_name=entry.team.team_name,
event_code=entry.event.event_name
).order_by('-goaltime').first()
).order_by('goaltime').first()
# Nullチェックを追加してからログ出力
goalimage_url = None
@ -2771,7 +2771,7 @@ def update_goal_time(request):
# 既存の記録を更新
goal_record.goaltime = goal_time
goal_record.save()
logger.info(f"Updated goal time for team {team_name} in event {event_code}")
logger.info(f"Updated goal time as {goal_time} for team {team_name} in event {event_code}")
else:
# 新しい記録を作成
entry = Entry.objects.get(zekken_number=zekken_number, event__event_name=event_code)

View File

@ -4,9 +4,10 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>スーパーバイザーパネル</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/exif-js/2.3.0/exif.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tailwindcss/2.2.19/tailwind.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/Sortable/1.15.0/Sortable.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" rel="stylesheet">
</head>
<body class="bg-gray-50">
<div class="container mx-auto p-4">
@ -170,7 +171,7 @@
// Excel出力ボタンの処理
document.getElementById('exportButton').addEventListener('click', exportExcel);
console.log('Page loaded, attempting to load events...');
//console.log('Page loaded, attempting to load events...');
// 初期データ読み込み
loadEventCodes();
});
@ -194,7 +195,8 @@
if (display.textContent && display.textContent !== '-') {
try {
const date = new Date(display.textContent);
input.value = date.toISOString().slice(0, 19);
const jstDate = new Date(date.getTime() + (9 * 60 * 60 * 1000));
input.value = jstDate.toISOString().slice(0, 19);
} catch (e) {
console.error('Error parsing date:', e);
}
@ -302,13 +304,13 @@
const timeDiff = (newTime - startTime) / 1000; // 分単位の差
const maxTime = team.duration + 15*60; // 制限時間+15分
console.info('startTime=',startTime,',goalTime=',newTime,',timeDiff=',timeDiff,'duration=',team.duration,',maxTime=',maxTime);
//console.info('startTime=',startTime,',goalTime=',newTime,',timeDiff=',timeDiff,'duration=',team.duration,',maxTime=',maxTime);
updateValidation(timeDiff, maxTime );
// 1秒でも遅刻すると、1分につき-50点
const overtime = ((newTime - startTime) / 1000 - team.duration );
if( overtime>0 ){
console.info('overtime=',overtime);
//console.info('overtime=',overtime);
late_point = Math.ceil(overtime/60)*(-50);
lateElement = document.getElementById('latePoints');
lateElement.textContent = late_point;
@ -333,7 +335,7 @@
// 判定の更新を行う補助関数
function updateValidation(timeDiff, maxTime) {
console.log('updateValidation',timeDiff,' > ',maxTime)
//console.log('updateValidation',timeDiff,' > ',maxTime)
const validateElement = document.getElementById('validate');
if (validateElement) {
if (timeDiff > maxTime) {
@ -458,23 +460,23 @@
goalTimeDisplay.onclick = () => editGoalTime(goalTimeDisplay);
}
console.info("step 0");
//console.info("step 0");
// ゴール時計の表示を更新
const goalTimeElement = document.getElementById('goalTime');
if (teamData.goal_photo) {
// 画像要素を作成
console.info("step 1");
//console.info("step 1");
const img = document.createElement('img');
img.src = teamData.goal_photo;
img.classList.add('h-32', 'w-auto', 'object-contain', 'cursor-pointer');
img.onclick = () => showLargeImage(teamData.goal_photo);
console.info("step 2");
//console.info("step 2");
// 既存の内容をクリアして画像を追加
goalTimeElement.innerHTML = '';
goalTimeElement.appendChild(img);
console.info("Goal photo displayed: ",teamData.goal_photo);
//console.info("Goal photo displayed: ",teamData.goal_photo);
} else {
goalTimeElement.textContent = '画像なし';
console.info("No goal photo available");
@ -813,11 +815,62 @@ function deleteRow(rowIndex) {
img.src = src;
img.classList.add('max-w-3xl', 'max-h-[90vh]', 'object-contain');
// 画像の向きを補正
applyImageOrientation(img);
modal.appendChild(img);
modal.onclick = () => modal.remove();
document.body.appendChild(modal);
}
// 画像の向きを取得して適用する関数
function applyImageOrientation(imgElement) {
return new Promise((resolve) => {
const img = new Image();
img.onload = function() {
// 仮想キャンバスを作成
const canvas = document.createElement('canvas');
const ctx = canvas.getContext('2d');
// EXIF情報を取得
EXIF.getData(img, function() {
const orientation = EXIF.getTag(this, 'Orientation') || 1;
let width = img.width;
let height = img.height;
// 向きに応じてキャンバスのサイズを調整
if (orientation > 4 && orientation < 9) {
canvas.width = height;
canvas.height = width;
} else {
canvas.width = width;
canvas.height = height;
}
// 向きに応じて回転を適用
switch (orientation) {
case 2: ctx.transform(-1, 0, 0, 1, width, 0); break;
case 3: ctx.transform(-1, 0, 0, -1, width, height); break;
case 4: ctx.transform(1, 0, 0, -1, 0, height); break;
case 5: ctx.transform(0, 1, 1, 0, 0, 0); break;
case 6: ctx.transform(0, 1, -1, 0, height, 0); break;
case 7: ctx.transform(0, -1, -1, 0, height, width); break;
case 8: ctx.transform(0, -1, 1, 0, 0, width); break;
default: break;
}
// 画像を描画
ctx.drawImage(img, 0, 0);
// 回転済みの画像をソースとして設定
imgElement.src = canvas.toDataURL();
resolve();
});
};
img.src = imgElement.src;
});
}
// 新規CP追加のための関数
function showAddCPDialog() {
const cpInput = prompt('追加するCPをカンマ区切りで入力してくださいCP1,CP2,CP3');
@ -833,12 +886,12 @@ function deleteRow(rowIndex) {
const existingCheckins = getCurrentCheckins(); // 現在の表示データを取得する関数
const newCheckins = [];
console.info('existingCheckins.length =',existingCheckins.length);
//console.info('existingCheckins.length =',existingCheckins.length);
cpList.forEach((cp,index) => {
cploc = findLocationByCP(cp);
console.info('location=',cploc);
console.info('index = ',index);
//console.info('location=',cploc);
//console.info('index = ',index);
newCheckins.push({
id: cploc.id,
order: existingCheckins.length + index + 1,
@ -855,7 +908,7 @@ function deleteRow(rowIndex) {
});
});
console.info('newCheckins=',newCheckins);
//console.info('newCheckins=',newCheckins);
// 新しいCPを表に追加
addCheckinsToTable(newCheckins);
@ -930,7 +983,7 @@ function deleteRow(rowIndex) {
function updatePathOrders() {
const rows = Array.from(document.getElementById('checkinList').children);
rows.forEach((row, index) => {
console.info('row=',row);
//console.info('row=',row);
row.children[1].textContent = index + 1;
row.dataset.path_order = index + 1;
});
@ -938,7 +991,7 @@ function deleteRow(rowIndex) {
// 総合ポイントの計算
function calculatePoints() {
console.info('calculatePoints');
//console.info('calculatePoints');
const rows = Array.from(document.getElementById('checkinList').children);
let totalPoints = 0; // チェックインポイントの合計をクリア
let cpPoints = 0; // チェックインポイントの合計をクリア
@ -965,7 +1018,7 @@ function deleteRow(rowIndex) {
const finalPoints = totalPoints + latePoints;
// 判定を更新。順位を表示、ゴール時刻を15分経過したら失格
console.info('calculatePoints:totalPoints=',cpPoints,',buyPoints=',buyPoints,',finalPoints=',finalPoints);
//console.info('calculatePoints:totalPoints=',cpPoints,',buyPoints=',buyPoints,',finalPoints=',finalPoints);
document.getElementById('totalPoints').textContent = cpPoints;
document.getElementById('buyPoints').textContent = buyPoints;
@ -1046,7 +1099,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
.replace(/\//g, '-') // スラッシュをハイフンに変換
.replace(' ', 'T'); // スペースをTに変換
console.log(formattedDateTime); // "2024-10-26T12:59:13"
//console.log(formattedDateTime); // "2024-10-26T12:59:13"
console.info('goaltime=',formattedDateTime);
@ -1151,7 +1204,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
checkins.forEach(checkin => {
const row = document.createElement('tr');
console.info('checkin=',checkin);
//console.info('checkin=',checkin);
row.dataset.id = 0;
row.dataset.local_id = checkin.order; // Unique
@ -1214,7 +1267,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
// チェックポイントデータをロードする関数
async function loadLocations(eventCode) {
try {
console.info('loadLocations-1:',eventCode);
//console.info('loadLocations-1:',eventCode);
if (!eventCode) {
console.error('Event code is required');
return;
@ -1226,7 +1279,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
return loadedLocations;
}
console.info('loadLocations-2:',eventCode);
//console.info('loadLocations-2:',eventCode);
// group__containsフィルターを使用してクエリパラメータを構築
const params = new URLSearchParams({
@ -1244,7 +1297,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
// レスポンスをJSONとして解決
const data = await response.json();
console.info('loadLocations-3:', data);
//console.info('loadLocations-3:', data);
if (!response.ok) {
console.info('loadLocations-3: Bad Response :',response);
@ -1252,7 +1305,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
throw new Error(`HTTP error! status: ${response.status}`);
}
console.info('loadLocations-4:',eventCode);
//console.info('loadLocations-4:',eventCode);
// 取得したデータを処理して保存
loadedLocations = data.features.map(feature => ({
cp: feature.properties.cp,
@ -1268,9 +1321,9 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
})).filter(location => location.group && location.group.includes(eventCode));
currentEventCode = eventCode;
console.info(`Loaded ${loadedLocations.length} locations for event ${eventCode}`);
//console.info(`Loaded ${loadedLocations.length} locations for event ${eventCode}`);
console.info('loadedLocation[0]=',loadedLocations[0]);
//console.info('loadedLocation[0]=',loadedLocations[0]);
return loadedLocations;
@ -1282,7 +1335,7 @@ async function saveGoalTime(goalTimeStr, zekkenNumber, eventCode) {
// イベント選択時のハンドラー
async function handleEventSelect(eventCode) {
console.info('handleEventSelect : ',eventCode);
//console.info('handleEventSelect : ',eventCode);
try {
//document.getElementById('loading').style.display = 'block';
await loadLocations(eventCode);
@ -1315,7 +1368,7 @@ function findLocationByCP(cpNumber) {
return null;
}
console.info(`Found location with CP ${cpNumber}:`, found);
//console.info(`Found location with CP ${cpNumber}:`, found);
return found;
}