fix goaltime issue on server side
This commit is contained in:
@ -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");
|
||||
@ -812,12 +814,63 @@ function deleteRow(rowIndex) {
|
||||
const img = document.createElement('img');
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user