Fix Ranking code step2

This commit is contained in:
2024-11-12 08:59:20 +09:00
parent fccc55cf18
commit a3c90902ec
2 changed files with 101 additions and 22 deletions

View File

@ -1294,7 +1294,16 @@ class RegistrationView(APIView):
class NewEvent2ViewSet(viewsets.ModelViewSet):
queryset = NewEvent2.objects.all()
serializer_class = NewEvent2Serializer
permission_classes = [permissions.IsAuthenticated]
def get_permissions(self):
"""
GETメソッドは認証不要、その他のメソッドは認証必要
"""
if self.action in ['list', 'retrieve']:
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
class NewEvent2ListView(generics.ListAPIView):
queryset = NewEvent2.objects.all()
@ -1505,6 +1514,16 @@ class NewCategoryViewSet(viewsets.ModelViewSet):
serializer_class = NewCategorySerializer
#permission_classes = [IsAuthenticated]
def get_permissions(self):
"""
GETメソッドは認証不要、その他のメソッドは認証必要
"""
if self.action in ['list', 'retrieve']:
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
@action(detail=True, methods=['POST'])
def get_zekken_number(self, request, pk=None):
@ -1523,7 +1542,18 @@ class NewCategoryViewSet(viewsets.ModelViewSet):
class NewCategoryListView(generics.ListAPIView):
queryset = NewCategory.objects.all()
serializer_class = NewCategorySerializer
permission_classes = [IsAuthenticated]
#permission_classes = [IsAuthenticated]
def get_permissions(self):
"""
GETメソッドは認証不要、その他のメソッドは認証必要
"""
if self.action in ['list', 'retrieve']:
permission_classes = [AllowAny]
else:
permission_classes = [IsAuthenticated]
return [permission() for permission in permission_classes]
class CategoryViewSet(viewsets.ModelViewSet):
queryset = Category.objects.all()

View File

@ -8,7 +8,7 @@
.span2 { margin-left: 20px; }
.span3 { font-weight: bold; }
.span6 { display: inline-block; width: 30px; }
.black { background-color: #f0f0f0; padding: 10px; }
.black { background-color: #f0f0f0; padding: 10px; margin-bottom: 20px; }
.arrow { margin: 10px 0; }
.arrow2 { margin: 10px 0; }
.disqualified { color: #999; }
@ -31,11 +31,22 @@
background-color: #e3f2fd;
color: #1565c0;
}
.disqualified-header {
margin-top: 20px;
padding: 5px;
background-color: #f0f0f0;
border-left: 4px solid #999;
select {
padding: 8px;
margin: 5px 0;
min-width: 200px;
}
button {
padding: 8px 16px;
margin: 10px 0;
background-color: #4a90e2;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #357abd;
}
</style>
</head>
@ -47,12 +58,14 @@
</div>
<div class="arrow">
<div>イベントを選択してください</div>
<select id="eventSelect">
<option value="">イベントを選択してください</option>
</select>
</div>
<div class="arrow2">
<div>クラスを選択してください</div>
<select id="classSelect" disabled>
<option value="">クラスを選択してください</option>
</select>
@ -60,18 +73,17 @@
<button id="toggleButton" onclick="toggleView()">TOP3表示</button>
<!-- 通常のランキング表示 -->
<div id="normalRanking">
<div id="teamList"></div>
</div>
<!-- TOP3のランキング表示 -->
<div id="top3Ranking" style="display: none;">
<div id="top3List"></div>
</div>
</div>
<script>
const API_BASE_URL = 'https://rogaining.sumasen.net';
let showTop3 = false;
// ページ読み込み時にイベント一覧を取得
@ -110,7 +122,15 @@
// イベント一覧の取得と表示
async function loadEvents() {
try {
const response = await fetch('/api/newevent2/');
const response = await fetch(`${API_BASE_URL}/api/newevent2/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
mode: 'cors'
});
const events = await response.json();
const select = document.getElementById('eventSelect');
@ -128,11 +148,18 @@
// クラス一覧の取得と表示
async function loadClasses(eventCode) {
try {
const response = await fetch(`/api/categories/${eventCode}/`);
const response = await fetch(`${API_BASE_URL}/api/categories/${eventCode}/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
mode: 'cors'
});
const classes = await response.json();
const select = document.getElementById('classSelect');
// 既存のオプションをクリア
select.innerHTML = '<option value="">クラスを選択してください</option>';
select.disabled = false;
@ -168,14 +195,30 @@
// クラス別ランキングの表示
async function loadClassRankings(eventCode, classCode) {
const response = await fetch(`/api/rankings/${eventCode}/${classCode}/`);
const response = await fetch(`${API_BASE_URL}/api/rankings/${eventCode}/${classCode}/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
mode: 'cors'
});
const rankingData = await response.json();
displayNormalRankings(rankingData);
}
// TOP3ランキングの表示
async function loadTop3Rankings(eventCode) {
const response = await fetch(`/api/rankings/top3/${eventCode}/`);
const response = await fetch(`${API_BASE_URL}/api/rankings/top3/${eventCode}/`, {
method: 'GET',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest',
},
mode: 'cors'
});
const rankingData = await response.json();
displayTop3Rankings(rankingData);
}
@ -190,7 +233,7 @@
const div = document.createElement('div');
div.className = 'best';
const statusClass = team.status === '棄権' ? 'status-retired' :
team.status === 'ゴール' ? 'status-finished' : 'status-running';
team.status === 'ゴール' ? 'status-finished' : 'status-running';
div.innerHTML = `
${index + 1}. ${team.team_name} (${team.zekken_number})
<span class="span2">合計得点:${team.final_point}</span>
@ -202,22 +245,24 @@
container.appendChild(div);
});
// 失格チームの表示(見出し)
// 失格チームの表示
if (rankingData.disqualified && rankingData.disqualified.length > 0) {
const disqHeader = document.createElement('div');
disqHeader.className = 'disqualified-header';
disqHeader.innerHTML = '<h3>失格チーム</h3>';
container.appendChild(disqHeader);
// 失格チームのリスト
rankingData.disqualified.forEach(team => {
const div = document.createElement('div');
div.className = 'best disqualified';
const statusClass = team.status === '棄権' ? 'status-retired' :
team.status === 'ゴール' ? 'status-finished' : 'status-running';
div.innerHTML = `
${team.team_name} (${team.zekken_number})
<span class="span2">獲得ポイント:${team.point}</span>
<span class="span2">理由: ${team.reason}</span>
<span class="span2">ゴール: ${formatDateTime(team.goal_time)}</span>
<span class="span2">最終更新: ${formatDateTime(team.last_checkin)}</span>
<span class="status ${statusClass}">(${team.status})</span>
`;
container.appendChild(div);
});
@ -242,10 +287,11 @@
const teamDiv = document.createElement('div');
teamDiv.className = 'best3';
const statusClass = team.status === '棄権' ? 'status-retired' :
team.status === 'ゴール' ? 'status-finished' : 'status-running';
team.status === 'ゴール' ? 'status-finished' : 'status-running';
teamDiv.innerHTML = `
<span class="span6">${index + 1}</span>
${team.team_name} (${team.zekken_number}) <span class="status ${statusClass}">(${team.status})</span><br>
${team.team_name} (${team.zekken_number})
<span class="status ${statusClass}">(${team.status})</span><br>
合計得点:${team.final_point} (獲得:${team.point} 減点:${team.late_point})<br>
最終更新: ${formatDateTime(team.last_checkin)}
`;
@ -262,10 +308,13 @@
data.disqualified.forEach(team => {
const teamDiv = document.createElement('div');
teamDiv.className = 'best3 disqualified';
const statusClass = team.status === '棄権' ? 'status-retired' :
team.status === 'ゴール' ? 'status-finished' : 'status-running';
teamDiv.innerHTML = `
${team.team_name} (${team.zekken_number})<br>
獲得ポイント:${team.point} 理由:${team.reason}<br>
ゴール: ${formatDateTime(team.goal_time)}
最終更新: ${formatDateTime(team.last_checkin)}
<span class="status ${statusClass}">(${team.status})</span>
`;
categoryDiv.appendChild(teamDiv);
});