final stage update bugs
This commit is contained in:
@ -113,6 +113,10 @@ class SumasenExcel:
|
||||
|
||||
self.basic = basic
|
||||
|
||||
self.output_path = basic.get("output_path")
|
||||
if not os.path.exists(self.output_path):
|
||||
os.makedirs(self.output_path, exist_ok=True)
|
||||
|
||||
logging.info("step-2")
|
||||
|
||||
# basicセクションから必要なパラメータを取得
|
||||
@ -143,7 +147,7 @@ class SumasenExcel:
|
||||
logging.error("sections not found in basic section")
|
||||
|
||||
# 出力ファイルパスを設定
|
||||
self.output_filepath = f"{self.docpath}/{doc_file}"
|
||||
self.output_filepath = f"{self.output_path}/{doc_file}"
|
||||
# 新規のExcelワークブックを作成
|
||||
self.workbook = openpyxl.Workbook()
|
||||
# デフォルトで作成されるシートを削除
|
||||
|
||||
Binary file not shown.
@ -4,6 +4,7 @@ doc_file=certificate_[zekken_number].xlsx
|
||||
sections=section1
|
||||
maxcol=10
|
||||
column_width=3,5,16,16,16,16,16,8,8,12,3
|
||||
output_path=media/reports/[event_code]
|
||||
|
||||
[section1]
|
||||
template_sheet=certificate
|
||||
|
||||
@ -134,8 +134,7 @@ FROM
|
||||
AND CAST(e.zekken_number AS TEXT) = cs.zekken_number
|
||||
LEFT JOIN v_category_rankings cr ON e.id = cr.id
|
||||
LEFT JOIN rog_member m ON t.id = m.team_id
|
||||
LEFT JOIN rog_goalimages gi ON ev.event_name = gi.event_code
|
||||
AND CAST(e.zekken_number AS TEXT) = gi.zekken_number
|
||||
LEFT JOIN rog_goalimages gi ON e.owner_id = gi.user_id
|
||||
|
||||
GROUP BY
|
||||
e.id, e.zekken_number, e.is_active, e."hasParticipated", e."hasGoaled", e.date,
|
||||
@ -176,7 +175,8 @@ SELECT
|
||||
g.points
|
||||
FROM
|
||||
gps_checkins g
|
||||
LEFT JOIN rog_location l ON g.cp_number = l.cp
|
||||
LEFT JOIN rog_location l ON g.cp_number = l.cp
|
||||
AND l."group" LIKE '%' || g.event_code || '%'
|
||||
ORDER BY
|
||||
g.event_code,
|
||||
g.zekken_number,
|
||||
|
||||
@ -2561,7 +2561,7 @@ def update_checkins(request):
|
||||
checkin.buy_flag = update.get('buy_flag', False)
|
||||
checkin.validate_location = update.get('validation', False)
|
||||
checkin.points = update.get('points', 0)
|
||||
checkin.update_at = timezone.now()
|
||||
# checkin.update_at = timezone.now() チェックイン時刻は更新しない
|
||||
checkin.update_user = request.user.email if request.user.is_authenticated else None
|
||||
checkin.save()
|
||||
logger.info(f"Updated existing checkin result: {checkin}")
|
||||
@ -2583,7 +2583,7 @@ def update_checkins(request):
|
||||
validate_location=update.get('validation', False),
|
||||
buy_flag=update.get('buy_flag', False),
|
||||
points=update.get('points', 0),
|
||||
create_at=timezone.now(),
|
||||
# create_at=timezone.now(), チェックイン時刻は更新しない
|
||||
update_at=timezone.now(),
|
||||
create_user=request.user.email if request.user.is_authenticated else None,
|
||||
update_user=request.user.email if request.user.is_authenticated else None
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
</div>
|
||||
<div class="bg-gray-50 p-4 rounded-lg">
|
||||
<div class="text-sm text-gray-500">ゴール時刻</div>
|
||||
<div class="goal-time-container">
|
||||
<div class="goal-time-container">
|
||||
<span id="goalTimeDisplay" class="goal-time-display cursor-pointer"></span>
|
||||
<input type="datetime-local" id="goalTimeInput" class="goal-time-input hidden border rounded px-2 py-1"
|
||||
onchange="updateGoalTime(this)">
|
||||
@ -123,7 +123,7 @@
|
||||
// APIのベースURLを環境に応じて設定
|
||||
const API_BASE_URL = 'http://rogaining.sumasen.net/api';
|
||||
let original_goal_time = '';
|
||||
let selected_event_code = '';
|
||||
let selected_event_code = '';
|
||||
|
||||
// イベントリスナーの設定
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
@ -147,7 +147,7 @@
|
||||
alert('イベントコードを選択してください');
|
||||
return;
|
||||
}
|
||||
selected_event_code = eventCode;
|
||||
selected_event_code = eventCode;
|
||||
loadTeamData(e.target.value, eventCode);
|
||||
});
|
||||
|
||||
@ -253,6 +253,16 @@
|
||||
|
||||
try {
|
||||
const newTime = new Date(input.value);
|
||||
// inputがnullの場合は棄権処理
|
||||
if (!input) {
|
||||
const validateElement = document.getElementById('validate');
|
||||
display.textContent = '棄権';
|
||||
if (validateElement) {
|
||||
validateElement.textContent = '棄権';
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
display.textContent = newTime.toLocaleString();
|
||||
|
||||
const eventCodeSelect = document.getElementById('eventCode');
|
||||
@ -279,23 +289,23 @@
|
||||
.then(checkins => {
|
||||
const startCheckin = checkins.find(c => c.cp_number === -1);
|
||||
if (startCheckin) {
|
||||
const startTime = new Date(startCheckin.create_at);
|
||||
const timeDiff = (newTime - startTime) / 1000; // 秒単位の差
|
||||
const maxTime = team.duration + 15*60; // 制限時間+15分
|
||||
updateValidation(timeDiff, maxTime );
|
||||
const overtime = ((newTime - startTime) / 1000 - team.duration/1000 + 60 ) // 60;
|
||||
if( overtime>0 ){
|
||||
late_point = overtime*(-50);
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = late_point;
|
||||
lateElement.classList.add('text-red-600');
|
||||
}else{
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = 0;
|
||||
lateElement.classList.remove('text-red-600');
|
||||
}
|
||||
}
|
||||
})
|
||||
const startTime = new Date(startCheckin.create_at);
|
||||
const timeDiff = (newTime - startTime) / 1000; // 秒単位の差
|
||||
const maxTime = team.duration + 15*60; // 制限時間+15分
|
||||
updateValidation(timeDiff, maxTime );
|
||||
const overtime = ((newTime - startTime) / 1000 - team.duration/1000 + 60 ) // 60;
|
||||
if( overtime>0 ){
|
||||
late_point = overtime*(-50);
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = late_point;
|
||||
lateElement.classList.add('text-red-600');
|
||||
}else{
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = 0;
|
||||
lateElement.classList.remove('text-red-600');
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(error => handleApiError(error));
|
||||
|
||||
} else {
|
||||
@ -304,24 +314,25 @@
|
||||
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);
|
||||
late_point = Math.ceil(overtime/60)*(-50);
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = late_point;
|
||||
lateElement.classList.add('text-red-600');
|
||||
}else{
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = 0;
|
||||
lateElement.classList.remove('text-red-600');
|
||||
}
|
||||
}
|
||||
// 1秒でも遅刻すると、1分につき-50点
|
||||
const overtime = ((newTime - startTime) / 1000 - team.duration );
|
||||
if( overtime>0 ){
|
||||
//console.info('overtime=',overtime);
|
||||
late_point = Math.ceil(overtime/60)*(-50);
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = late_point;
|
||||
lateElement.classList.add('text-red-600');
|
||||
}else{
|
||||
lateElement = document.getElementById('latePoints');
|
||||
lateElement.textContent = 0;
|
||||
lateElement.classList.remove('text-red-600');
|
||||
}
|
||||
}
|
||||
});
|
||||
calculatePoints(); // 総合ポイントの計算
|
||||
|
||||
} catch (e) {
|
||||
console.error('Error updating goal time:', e);
|
||||
@ -419,7 +430,7 @@
|
||||
try {
|
||||
const [teamResponse, checkinsResponse] = await Promise.all([
|
||||
fetch(`${API_BASE_URL}/team_info/${zekkenNumber}/`),
|
||||
fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${event_code}/`),
|
||||
fetch(`${API_BASE_URL}/checkins/${zekkenNumber}/${event_code}/`),
|
||||
]);
|
||||
|
||||
// 各レスポンスのステータスを個別にチェック
|
||||
@ -434,7 +445,7 @@
|
||||
|
||||
// ゴール時刻の表示を更新
|
||||
updateGoalTimeDisplay(teamData.end_datetime);
|
||||
original_goal_time = teamData.end_datetime;
|
||||
original_goal_time = teamData.end_datetime;
|
||||
|
||||
// イベントコードに対応するイベントを検索
|
||||
//const event = eventData.find(e => e.code === document.getElementById('eventCode').value);
|
||||
@ -453,34 +464,36 @@
|
||||
'未ゴール';
|
||||
goalTimeDisplay.textContent = goalTime;
|
||||
|
||||
console.info('teamData.goal_photo = ',teamData.goal_photo );
|
||||
updateGoalTime(goalTime) // ゴール時刻の表示を更新
|
||||
|
||||
console.info('teamData.goal_photo = ',teamData.goal_photo );
|
||||
|
||||
if (goalTime === '-') {
|
||||
goalTimeDisplay.classList.add('cursor-pointer');
|
||||
goalTimeDisplay.onclick = () => editGoalTime(goalTimeDisplay);
|
||||
}
|
||||
|
||||
//console.info("step 0");
|
||||
// ゴール時計の表示を更新
|
||||
const goalTimeElement = document.getElementById('goalTime');
|
||||
if (teamData.goal_photo) {
|
||||
// 画像要素を作成
|
||||
//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 0");
|
||||
// ゴール時計の表示を更新
|
||||
const goalTimeElement = document.getElementById('goalTime');
|
||||
if (teamData.goal_photo) {
|
||||
// 画像要素を作成
|
||||
//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");
|
||||
// 既存の内容をクリアして画像を追加
|
||||
goalTimeElement.innerHTML = '';
|
||||
goalTimeElement.appendChild(img);
|
||||
//console.info("step 2");
|
||||
// 既存の内容をクリアして画像を追加
|
||||
goalTimeElement.innerHTML = '';
|
||||
goalTimeElement.appendChild(img);
|
||||
|
||||
//console.info("Goal photo displayed: ",teamData.goal_photo);
|
||||
} else {
|
||||
goalTimeElement.textContent = '画像なし';
|
||||
console.info("No goal photo available");
|
||||
}
|
||||
//console.info("Goal photo displayed: ",teamData.goal_photo);
|
||||
} else {
|
||||
goalTimeElement.textContent = '画像なし';
|
||||
console.info("No goal photo available");
|
||||
}
|
||||
|
||||
|
||||
// チェックインリストの更新
|
||||
@ -493,11 +506,11 @@
|
||||
checkinsData.forEach((checkin, index) => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.dataset.id = checkin.id;
|
||||
tr.dataset.local_id = index+1;
|
||||
tr.dataset.local_id = index+1;
|
||||
tr.dataset.cpNumber = checkin.cp_number;
|
||||
tr.dataset.buyPoint = checkin.buy_point;
|
||||
tr.dataset.checkinPoint = checkin.checkin_point;
|
||||
tr.dataset.path_order = index+1;
|
||||
tr.dataset.checkinPoint = checkin.checkin_point;
|
||||
tr.dataset.path_order = index+1;
|
||||
const bgColor = checkin.buy_point > 0 ? 'bg-blue-100' : '';
|
||||
|
||||
tr.innerHTML = `
|
||||
@ -510,7 +523,11 @@
|
||||
`<img src="/media/compressed/${checkin.photos}" class="h-20 w-20 object-cover rounded" onclick="showLargeImage(this.src)">` : ''}
|
||||
</td>
|
||||
<td class="px-2 py-3">
|
||||
${checkin.cp_number===-1 || checkin.image_address===null ? "" : `<img src="${checkin.image_address}" class="h-20 w-20 object-cover rounded" onclick="showLargeImage(this.src)">`}
|
||||
${checkin.cp_number===-1 || checkin.image_address===null ? "" :
|
||||
`<img src="${checkin.image_address}"
|
||||
class="h-20 w-20 object-cover rounded"
|
||||
onclick="showLargeImage(this.src)"
|
||||
onerror="this.parentElement.innerHTML=''">`}
|
||||
</td>
|
||||
<td class="px-2 py-3 ${bgColor}">
|
||||
<div class="font-bold">${checkin.sub_loc_id}</div>
|
||||
@ -546,7 +563,7 @@
|
||||
// }
|
||||
//}
|
||||
});
|
||||
updatePathOrders();
|
||||
updatePathOrders();
|
||||
|
||||
// 合計ポイントの更新
|
||||
//document.getElementById('totalPoints').textContent = totalPoints;
|
||||
@ -991,37 +1008,39 @@ function applyImageOrientation(imgElement) {
|
||||
|
||||
// 総合ポイントの計算
|
||||
function calculatePoints() {
|
||||
//console.info('calculatePoints');
|
||||
//console.info('calculatePoints');
|
||||
const rows = Array.from(document.getElementById('checkinList').children);
|
||||
let totalPoints = 0; // チェックインポイントの合計をクリア
|
||||
let cpPoints = 0; // チェックインポイントの合計をクリア
|
||||
let buyPoints = 0; // 買い物ポイントの合計をクリア
|
||||
let latePoints = 0; // 遅刻ポイントの合計をクリア
|
||||
|
||||
// 各行のチェックインポイント及び買い物ポイントを合算
|
||||
// 各行のチェックインポイント及び買い物ポイントを合算
|
||||
rows.forEach(row => {
|
||||
const buybox = row.children[6].querySelector('input[type="checkbox"]');
|
||||
const checkbox = row.children[7].querySelector('input[type="checkbox"]');
|
||||
const point = parseInt(row.children[8].textContent);
|
||||
const buybox = row.children[6].querySelector('input[type="checkbox"]');
|
||||
const checkbox = row.children[7].querySelector('input[type="checkbox"]');
|
||||
const point = parseInt(row.children[8].textContent);
|
||||
if (checkbox) {
|
||||
totalPoints += point;
|
||||
if (buybox && buybox.checked) {
|
||||
buyPoints += point;
|
||||
}else{
|
||||
cpPoints += point;
|
||||
}
|
||||
}else{
|
||||
cpPoints += point;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// 遅刻ポイントの計算=ゴール時刻がEventのゴール時刻を超えていたら1分につき-50点を加算する。
|
||||
const latePoints = parseInt(document.getElementById('latePoints').textContent) || 0;
|
||||
// 総合得点を計算
|
||||
latePoints = parseInt(document.getElementById('latePoints').textContent) || 0;
|
||||
// 総合得点を計算
|
||||
const finalPoints = totalPoints + latePoints;
|
||||
|
||||
// 判定を更新。順位を表示、ゴール時刻を15分経過したら失格
|
||||
//console.info('calculatePoints:totalPoints=',cpPoints,',buyPoints=',buyPoints,',finalPoints=',finalPoints);
|
||||
// 判定を更新。順位を表示、ゴール時刻を15分経過したら失格
|
||||
//console.info('calculatePoints:totalPoints=',cpPoints,',buyPoints=',buyPoints,',finalPoints=',finalPoints);
|
||||
|
||||
document.getElementById('totalPoints').textContent = cpPoints;
|
||||
document.getElementById('buyPoints').textContent = buyPoints;
|
||||
document.getElementById('latePoints').textContent = latePoints;
|
||||
document.getElementById('finalPoints').textContent = finalPoints;
|
||||
}
|
||||
|
||||
@ -1034,17 +1053,17 @@ function applyImageOrientation(imgElement) {
|
||||
const zekkenNumber = document.querySelector('#zekkenNumber').value;
|
||||
const eventCode = document.querySelector('#eventCode').value;
|
||||
|
||||
const display = document.getElementById('goalTimeDisplay');
|
||||
const display = document.getElementById('goalTimeDisplay');
|
||||
|
||||
if (!display) {
|
||||
console.error('Goal time elements not found');
|
||||
return;
|
||||
}
|
||||
|
||||
let goalTime = display.textContent;
|
||||
console.info('Goal time = ',goalTime);
|
||||
let goalTime = display.textContent;
|
||||
console.info('Goal time = ',goalTime);
|
||||
|
||||
try {
|
||||
try {
|
||||
const checkins = getCurrentCheckins(); // 現在の表示データを取得
|
||||
|
||||
const response = await fetch(`${API_BASE_URL}/update_checkins/`, {
|
||||
|
||||
Reference in New Issue
Block a user