Fix Ranking code step2
This commit is contained in:
32
rog/views.py
32
rog/views.py
@ -1294,7 +1294,16 @@ class RegistrationView(APIView):
|
|||||||
class NewEvent2ViewSet(viewsets.ModelViewSet):
|
class NewEvent2ViewSet(viewsets.ModelViewSet):
|
||||||
queryset = NewEvent2.objects.all()
|
queryset = NewEvent2.objects.all()
|
||||||
serializer_class = NewEvent2Serializer
|
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):
|
class NewEvent2ListView(generics.ListAPIView):
|
||||||
queryset = NewEvent2.objects.all()
|
queryset = NewEvent2.objects.all()
|
||||||
@ -1505,6 +1514,16 @@ class NewCategoryViewSet(viewsets.ModelViewSet):
|
|||||||
serializer_class = NewCategorySerializer
|
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]
|
||||||
|
|
||||||
|
|
||||||
@action(detail=True, methods=['POST'])
|
@action(detail=True, methods=['POST'])
|
||||||
def get_zekken_number(self, request, pk=None):
|
def get_zekken_number(self, request, pk=None):
|
||||||
@ -1523,7 +1542,18 @@ class NewCategoryViewSet(viewsets.ModelViewSet):
|
|||||||
class NewCategoryListView(generics.ListAPIView):
|
class NewCategoryListView(generics.ListAPIView):
|
||||||
queryset = NewCategory.objects.all()
|
queryset = NewCategory.objects.all()
|
||||||
serializer_class = NewCategorySerializer
|
serializer_class = NewCategorySerializer
|
||||||
|
#permission_classes = [IsAuthenticated]
|
||||||
|
|
||||||
|
def get_permissions(self):
|
||||||
|
"""
|
||||||
|
GETメソッドは認証不要、その他のメソッドは認証必要
|
||||||
|
"""
|
||||||
|
if self.action in ['list', 'retrieve']:
|
||||||
|
permission_classes = [AllowAny]
|
||||||
|
else:
|
||||||
permission_classes = [IsAuthenticated]
|
permission_classes = [IsAuthenticated]
|
||||||
|
return [permission() for permission in permission_classes]
|
||||||
|
|
||||||
|
|
||||||
class CategoryViewSet(viewsets.ModelViewSet):
|
class CategoryViewSet(viewsets.ModelViewSet):
|
||||||
queryset = Category.objects.all()
|
queryset = Category.objects.all()
|
||||||
|
|||||||
@ -8,7 +8,7 @@
|
|||||||
.span2 { margin-left: 20px; }
|
.span2 { margin-left: 20px; }
|
||||||
.span3 { font-weight: bold; }
|
.span3 { font-weight: bold; }
|
||||||
.span6 { display: inline-block; width: 30px; }
|
.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; }
|
.arrow { margin: 10px 0; }
|
||||||
.arrow2 { margin: 10px 0; }
|
.arrow2 { margin: 10px 0; }
|
||||||
.disqualified { color: #999; }
|
.disqualified { color: #999; }
|
||||||
@ -31,11 +31,22 @@
|
|||||||
background-color: #e3f2fd;
|
background-color: #e3f2fd;
|
||||||
color: #1565c0;
|
color: #1565c0;
|
||||||
}
|
}
|
||||||
.disqualified-header {
|
select {
|
||||||
margin-top: 20px;
|
padding: 8px;
|
||||||
padding: 5px;
|
margin: 5px 0;
|
||||||
background-color: #f0f0f0;
|
min-width: 200px;
|
||||||
border-left: 4px solid #999;
|
}
|
||||||
|
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>
|
</style>
|
||||||
</head>
|
</head>
|
||||||
@ -47,12 +58,14 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="arrow">
|
<div class="arrow">
|
||||||
|
<div>イベントを選択してください</div>
|
||||||
<select id="eventSelect">
|
<select id="eventSelect">
|
||||||
<option value="">イベントを選択してください</option>
|
<option value="">イベントを選択してください</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="arrow2">
|
<div class="arrow2">
|
||||||
|
<div>クラスを選択してください</div>
|
||||||
<select id="classSelect" disabled>
|
<select id="classSelect" disabled>
|
||||||
<option value="">クラスを選択してください</option>
|
<option value="">クラスを選択してください</option>
|
||||||
</select>
|
</select>
|
||||||
@ -60,18 +73,17 @@
|
|||||||
|
|
||||||
<button id="toggleButton" onclick="toggleView()">TOP3表示</button>
|
<button id="toggleButton" onclick="toggleView()">TOP3表示</button>
|
||||||
|
|
||||||
<!-- 通常のランキング表示 -->
|
|
||||||
<div id="normalRanking">
|
<div id="normalRanking">
|
||||||
<div id="teamList"></div>
|
<div id="teamList"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- TOP3のランキング表示 -->
|
|
||||||
<div id="top3Ranking" style="display: none;">
|
<div id="top3Ranking" style="display: none;">
|
||||||
<div id="top3List"></div>
|
<div id="top3List"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
const API_BASE_URL = 'https://rogaining.sumasen.net';
|
||||||
let showTop3 = false;
|
let showTop3 = false;
|
||||||
|
|
||||||
// ページ読み込み時にイベント一覧を取得
|
// ページ読み込み時にイベント一覧を取得
|
||||||
@ -110,7 +122,15 @@
|
|||||||
// イベント一覧の取得と表示
|
// イベント一覧の取得と表示
|
||||||
async function loadEvents() {
|
async function loadEvents() {
|
||||||
try {
|
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 events = await response.json();
|
||||||
const select = document.getElementById('eventSelect');
|
const select = document.getElementById('eventSelect');
|
||||||
|
|
||||||
@ -128,11 +148,18 @@
|
|||||||
// クラス一覧の取得と表示
|
// クラス一覧の取得と表示
|
||||||
async function loadClasses(eventCode) {
|
async function loadClasses(eventCode) {
|
||||||
try {
|
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 classes = await response.json();
|
||||||
const select = document.getElementById('classSelect');
|
const select = document.getElementById('classSelect');
|
||||||
|
|
||||||
// 既存のオプションをクリア
|
|
||||||
select.innerHTML = '<option value="">クラスを選択してください</option>';
|
select.innerHTML = '<option value="">クラスを選択してください</option>';
|
||||||
select.disabled = false;
|
select.disabled = false;
|
||||||
|
|
||||||
@ -168,14 +195,30 @@
|
|||||||
|
|
||||||
// クラス別ランキングの表示
|
// クラス別ランキングの表示
|
||||||
async function loadClassRankings(eventCode, classCode) {
|
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();
|
const rankingData = await response.json();
|
||||||
displayNormalRankings(rankingData);
|
displayNormalRankings(rankingData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TOP3ランキングの表示
|
// TOP3ランキングの表示
|
||||||
async function loadTop3Rankings(eventCode) {
|
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();
|
const rankingData = await response.json();
|
||||||
displayTop3Rankings(rankingData);
|
displayTop3Rankings(rankingData);
|
||||||
}
|
}
|
||||||
@ -202,22 +245,24 @@
|
|||||||
container.appendChild(div);
|
container.appendChild(div);
|
||||||
});
|
});
|
||||||
|
|
||||||
// 失格チームの表示(見出し)
|
// 失格チームの表示
|
||||||
if (rankingData.disqualified && rankingData.disqualified.length > 0) {
|
if (rankingData.disqualified && rankingData.disqualified.length > 0) {
|
||||||
const disqHeader = document.createElement('div');
|
const disqHeader = document.createElement('div');
|
||||||
disqHeader.className = 'disqualified-header';
|
disqHeader.className = 'disqualified-header';
|
||||||
disqHeader.innerHTML = '<h3>失格チーム</h3>';
|
disqHeader.innerHTML = '<h3>失格チーム</h3>';
|
||||||
container.appendChild(disqHeader);
|
container.appendChild(disqHeader);
|
||||||
|
|
||||||
// 失格チームのリスト
|
|
||||||
rankingData.disqualified.forEach(team => {
|
rankingData.disqualified.forEach(team => {
|
||||||
const div = document.createElement('div');
|
const div = document.createElement('div');
|
||||||
div.className = 'best disqualified';
|
div.className = 'best disqualified';
|
||||||
|
const statusClass = team.status === '棄権' ? 'status-retired' :
|
||||||
|
team.status === 'ゴール' ? 'status-finished' : 'status-running';
|
||||||
div.innerHTML = `
|
div.innerHTML = `
|
||||||
${team.team_name} (${team.zekken_number})
|
${team.team_name} (${team.zekken_number})
|
||||||
<span class="span2">獲得ポイント:${team.point}</span>
|
<span class="span2">獲得ポイント:${team.point}</span>
|
||||||
<span class="span2">理由: ${team.reason}</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);
|
container.appendChild(div);
|
||||||
});
|
});
|
||||||
@ -245,7 +290,8 @@
|
|||||||
team.status === 'ゴール' ? 'status-finished' : 'status-running';
|
team.status === 'ゴール' ? 'status-finished' : 'status-running';
|
||||||
teamDiv.innerHTML = `
|
teamDiv.innerHTML = `
|
||||||
<span class="span6">${index + 1}</span>
|
<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>
|
合計得点:${team.final_point} (獲得:${team.point} 減点:${team.late_point})<br>
|
||||||
最終更新: ${formatDateTime(team.last_checkin)}
|
最終更新: ${formatDateTime(team.last_checkin)}
|
||||||
`;
|
`;
|
||||||
@ -262,10 +308,13 @@
|
|||||||
data.disqualified.forEach(team => {
|
data.disqualified.forEach(team => {
|
||||||
const teamDiv = document.createElement('div');
|
const teamDiv = document.createElement('div');
|
||||||
teamDiv.className = 'best3 disqualified';
|
teamDiv.className = 'best3 disqualified';
|
||||||
|
const statusClass = team.status === '棄権' ? 'status-retired' :
|
||||||
|
team.status === 'ゴール' ? 'status-finished' : 'status-running';
|
||||||
teamDiv.innerHTML = `
|
teamDiv.innerHTML = `
|
||||||
${team.team_name} (${team.zekken_number})<br>
|
${team.team_name} (${team.zekken_number})<br>
|
||||||
獲得ポイント:${team.point} 理由:${team.reason}<br>
|
獲得ポイント:${team.point} 理由:${team.reason}<br>
|
||||||
ゴール: ${formatDateTime(team.goal_time)}
|
最終更新: ${formatDateTime(team.last_checkin)}
|
||||||
|
<span class="status ${statusClass}">(${team.status})</span>
|
||||||
`;
|
`;
|
||||||
categoryDiv.appendChild(teamDiv);
|
categoryDiv.appendChild(teamDiv);
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user