Spaces:
Sleeping
Sleeping
Ko-TTS-Arena Contributors
commited on
Commit
·
e1cb33d
1
Parent(s):
aebf092
feat: Add category filters (한영혼합, 숫자혼합, 긴문장) to leaderboard
Browse files- app.py +11 -2
- models.py +95 -25
- templates/leaderboard.html +265 -39
app.py
CHANGED
|
@@ -374,7 +374,12 @@ def arena():
|
|
| 374 |
|
| 375 |
@app.route("/leaderboard")
|
| 376 |
def leaderboard():
|
| 377 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 378 |
voting_stats = get_voting_statistics() # Get voting statistics
|
| 379 |
|
| 380 |
# Initialize personal leaderboard data
|
|
@@ -394,7 +399,11 @@ def leaderboard():
|
|
| 394 |
|
| 395 |
return render_template(
|
| 396 |
"leaderboard.html",
|
| 397 |
-
tts_leaderboard=
|
|
|
|
|
|
|
|
|
|
|
|
|
| 398 |
tts_personal_leaderboard=tts_personal_leaderboard,
|
| 399 |
tts_key_dates=tts_key_dates,
|
| 400 |
formatted_tts_dates=formatted_tts_dates,
|
|
|
|
| 374 |
|
| 375 |
@app.route("/leaderboard")
|
| 376 |
def leaderboard():
|
| 377 |
+
# 카테고리별 리더보드 데이터
|
| 378 |
+
tts_leaderboard_all = get_leaderboard_data(ModelType.TTS, 'all')
|
| 379 |
+
tts_leaderboard_mixed_lang = get_leaderboard_data(ModelType.TTS, 'mixed_lang')
|
| 380 |
+
tts_leaderboard_with_numbers = get_leaderboard_data(ModelType.TTS, 'with_numbers')
|
| 381 |
+
tts_leaderboard_long_text = get_leaderboard_data(ModelType.TTS, 'long_text')
|
| 382 |
+
|
| 383 |
voting_stats = get_voting_statistics() # Get voting statistics
|
| 384 |
|
| 385 |
# Initialize personal leaderboard data
|
|
|
|
| 399 |
|
| 400 |
return render_template(
|
| 401 |
"leaderboard.html",
|
| 402 |
+
tts_leaderboard=tts_leaderboard_all,
|
| 403 |
+
tts_leaderboard_all=tts_leaderboard_all,
|
| 404 |
+
tts_leaderboard_mixed_lang=tts_leaderboard_mixed_lang,
|
| 405 |
+
tts_leaderboard_with_numbers=tts_leaderboard_with_numbers,
|
| 406 |
+
tts_leaderboard_long_text=tts_leaderboard_long_text,
|
| 407 |
tts_personal_leaderboard=tts_personal_leaderboard,
|
| 408 |
tts_key_dates=tts_key_dates,
|
| 409 |
formatted_tts_dates=formatted_tts_dates,
|
models.py
CHANGED
|
@@ -319,38 +319,57 @@ def record_vote(user_id, text, chosen_model_id, rejected_model_id, model_type,
|
|
| 319 |
return vote, None
|
| 320 |
|
| 321 |
|
| 322 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 323 |
"""
|
| 324 |
-
Get leaderboard data for the specified model type.
|
| 325 |
Only includes votes that count for the public leaderboard.
|
| 326 |
Only shows active models.
|
| 327 |
|
| 328 |
Args:
|
| 329 |
model_type (str): The model type ('tts' or 'conversational')
|
|
|
|
| 330 |
|
| 331 |
Returns:
|
| 332 |
list: List of dictionaries containing model data for the leaderboard
|
| 333 |
"""
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
|
| 343 |
-
|
| 344 |
-
tier = "tier-s"
|
| 345 |
-
|
| 346 |
-
tier = "tier-a"
|
| 347 |
-
elif rank <= 7:
|
| 348 |
-
tier = "tier-b"
|
| 349 |
-
else:
|
| 350 |
-
tier = ""
|
| 351 |
-
|
| 352 |
-
result.append(
|
| 353 |
-
{
|
| 354 |
"rank": rank,
|
| 355 |
"id": model.id,
|
| 356 |
"name": model.name,
|
|
@@ -360,9 +379,60 @@ def get_leaderboard_data(model_type):
|
|
| 360 |
"elo": int(model.current_elo),
|
| 361 |
"tier": tier,
|
| 362 |
"is_open": model.is_open,
|
| 363 |
-
}
|
| 364 |
-
|
| 365 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
return result
|
| 367 |
|
| 368 |
|
|
|
|
| 319 |
return vote, None
|
| 320 |
|
| 321 |
|
| 322 |
+
import re
|
| 323 |
+
|
| 324 |
+
def categorize_text(text):
|
| 325 |
+
"""
|
| 326 |
+
텍스트를 카테고리로 분류
|
| 327 |
+
Returns: list of categories the text belongs to
|
| 328 |
+
"""
|
| 329 |
+
categories = ['all'] # 모든 텍스트는 'all'에 포함
|
| 330 |
+
|
| 331 |
+
# 한영혼합: 알파벳 5글자 이상
|
| 332 |
+
alphabet_count = len(re.findall(r'[a-zA-Z]', text))
|
| 333 |
+
if alphabet_count >= 5:
|
| 334 |
+
categories.append('mixed_lang')
|
| 335 |
+
|
| 336 |
+
# 숫자혼합: 숫자 2개 이상
|
| 337 |
+
digit_count = len(re.findall(r'\d', text))
|
| 338 |
+
if digit_count >= 2:
|
| 339 |
+
categories.append('with_numbers')
|
| 340 |
+
|
| 341 |
+
# 긴문장: 50글자 이상
|
| 342 |
+
if len(text) >= 50:
|
| 343 |
+
categories.append('long_text')
|
| 344 |
+
|
| 345 |
+
return categories
|
| 346 |
+
|
| 347 |
+
|
| 348 |
+
def get_leaderboard_data(model_type, category='all'):
|
| 349 |
"""
|
| 350 |
+
Get leaderboard data for the specified model type and category.
|
| 351 |
Only includes votes that count for the public leaderboard.
|
| 352 |
Only shows active models.
|
| 353 |
|
| 354 |
Args:
|
| 355 |
model_type (str): The model type ('tts' or 'conversational')
|
| 356 |
+
category (str): Category filter ('all', 'mixed_lang', 'with_numbers', 'long_text')
|
| 357 |
|
| 358 |
Returns:
|
| 359 |
list: List of dictionaries containing model data for the leaderboard
|
| 360 |
"""
|
| 361 |
+
# 활성 모델 가져오기
|
| 362 |
+
active_models = Model.query.filter_by(model_type=model_type, is_active=True).all()
|
| 363 |
+
|
| 364 |
+
if category == 'all':
|
| 365 |
+
# 기존 로직: Model 테이블의 집계 데이터 사용
|
| 366 |
+
models = [m for m in active_models if m.match_count > 0]
|
| 367 |
+
models.sort(key=lambda x: x.current_elo, reverse=True)
|
| 368 |
+
|
| 369 |
+
result = []
|
| 370 |
+
for rank, model in enumerate(models, 1):
|
| 371 |
+
tier = "tier-s" if rank <= 2 else "tier-a" if rank <= 4 else "tier-b" if rank <= 7 else ""
|
| 372 |
+
result.append({
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 373 |
"rank": rank,
|
| 374 |
"id": model.id,
|
| 375 |
"name": model.name,
|
|
|
|
| 379 |
"elo": int(model.current_elo),
|
| 380 |
"tier": tier,
|
| 381 |
"is_open": model.is_open,
|
| 382 |
+
})
|
| 383 |
+
return result
|
| 384 |
+
|
| 385 |
+
# 카테고리별 필터링: Vote 테이블에서 직접 계산
|
| 386 |
+
active_model_ids = {m.id for m in active_models}
|
| 387 |
+
|
| 388 |
+
# 해당 카테고리에 맞는 투표 가져오기
|
| 389 |
+
all_votes = Vote.query.filter(
|
| 390 |
+
Vote.model_type == model_type,
|
| 391 |
+
Vote.counts_for_public_leaderboard == True
|
| 392 |
+
).all()
|
| 393 |
+
|
| 394 |
+
# 카테고리에 맞는 투표만 필터링
|
| 395 |
+
filtered_votes = []
|
| 396 |
+
for vote in all_votes:
|
| 397 |
+
text_categories = categorize_text(vote.text)
|
| 398 |
+
if category in text_categories:
|
| 399 |
+
filtered_votes.append(vote)
|
| 400 |
+
|
| 401 |
+
# 모델별 승/패 계산
|
| 402 |
+
model_stats = {m.id: {"wins": 0, "matches": 0, "model": m} for m in active_models}
|
| 403 |
+
|
| 404 |
+
for vote in filtered_votes:
|
| 405 |
+
if vote.model_chosen in active_model_ids:
|
| 406 |
+
model_stats[vote.model_chosen]["wins"] += 1
|
| 407 |
+
model_stats[vote.model_chosen]["matches"] += 1
|
| 408 |
+
if vote.model_rejected in active_model_ids:
|
| 409 |
+
model_stats[vote.model_rejected]["matches"] += 1
|
| 410 |
+
|
| 411 |
+
# 승률 계산 및 정렬
|
| 412 |
+
result = []
|
| 413 |
+
for model_id, stats in model_stats.items():
|
| 414 |
+
if stats["matches"] > 0:
|
| 415 |
+
win_rate = (stats["wins"] / stats["matches"]) * 100
|
| 416 |
+
result.append({
|
| 417 |
+
"id": model_id,
|
| 418 |
+
"name": stats["model"].name,
|
| 419 |
+
"model_url": stats["model"].model_url,
|
| 420 |
+
"win_rate": f"{win_rate:.0f}%",
|
| 421 |
+
"total_votes": stats["matches"],
|
| 422 |
+
"elo": int(1500 + (win_rate - 50) * 10), # 간단한 ELO 추정
|
| 423 |
+
"is_open": stats["model"].is_open,
|
| 424 |
+
"_win_rate_num": win_rate,
|
| 425 |
+
})
|
| 426 |
+
|
| 427 |
+
# 승률로 정렬
|
| 428 |
+
result.sort(key=lambda x: x["_win_rate_num"], reverse=True)
|
| 429 |
+
|
| 430 |
+
# 랭크와 티어 추가
|
| 431 |
+
for rank, item in enumerate(result, 1):
|
| 432 |
+
item["rank"] = rank
|
| 433 |
+
item["tier"] = "tier-s" if rank <= 2 else "tier-a" if rank <= 4 else "tier-b" if rank <= 7 else ""
|
| 434 |
+
del item["_win_rate_num"]
|
| 435 |
+
|
| 436 |
return result
|
| 437 |
|
| 438 |
|
templates/leaderboard.html
CHANGED
|
@@ -919,6 +919,75 @@
|
|
| 919 |
visibility: visible;
|
| 920 |
opacity: 1;
|
| 921 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 922 |
</style>
|
| 923 |
{% endblock %}
|
| 924 |
|
|
@@ -994,52 +1063,177 @@
|
|
| 994 |
</div>
|
| 995 |
|
| 996 |
<div id="tts-public-leaderboard" class="leaderboard-view active">
|
| 997 |
-
|
| 998 |
-
<div class="
|
| 999 |
-
<
|
| 1000 |
-
|
| 1001 |
-
<
|
| 1002 |
-
|
| 1003 |
-
|
| 1004 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1005 |
</div>
|
| 1006 |
-
|
| 1007 |
-
|
| 1008 |
-
|
| 1009 |
-
<
|
| 1010 |
-
<
|
| 1011 |
-
|
| 1012 |
-
|
| 1013 |
-
|
| 1014 |
-
|
| 1015 |
-
|
| 1016 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1017 |
</div>
|
| 1018 |
-
{
|
| 1019 |
-
<div class="
|
| 1020 |
-
|
| 1021 |
-
|
| 1022 |
-
|
| 1023 |
-
|
| 1024 |
-
|
| 1025 |
-
|
| 1026 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1027 |
</div>
|
| 1028 |
-
{
|
|
|
|
|
|
|
| 1029 |
</div>
|
| 1030 |
-
|
| 1031 |
-
<div class="total-votes">{{ model.total_votes }}</div>
|
| 1032 |
-
<div class="elo-score">{{ model.elo }}</div>
|
| 1033 |
</div>
|
| 1034 |
-
{%
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1035 |
</div>
|
| 1036 |
-
|
| 1037 |
-
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
<
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1041 |
</div>
|
| 1042 |
-
{% endif %}
|
| 1043 |
</div>
|
| 1044 |
|
| 1045 |
<div id="tts-personal-leaderboard" class="leaderboard-view" style="display: none;">
|
|
@@ -1440,6 +1634,38 @@
|
|
| 1440 |
setupHistoricalView('tts');
|
| 1441 |
setupHistoricalView('conversational');
|
| 1442 |
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1443 |
|
| 1444 |
// Final positioning after all DOM operations are complete
|
| 1445 |
setTimeout(positionSliders, 100);
|
|
|
|
| 919 |
visibility: visible;
|
| 920 |
opacity: 1;
|
| 921 |
}
|
| 922 |
+
|
| 923 |
+
/* Category filter styles */
|
| 924 |
+
.category-filter {
|
| 925 |
+
display: flex;
|
| 926 |
+
gap: 8px;
|
| 927 |
+
margin-bottom: 20px;
|
| 928 |
+
flex-wrap: wrap;
|
| 929 |
+
justify-content: center;
|
| 930 |
+
}
|
| 931 |
+
|
| 932 |
+
.category-btn {
|
| 933 |
+
padding: 8px 16px;
|
| 934 |
+
border: 2px solid var(--border-color);
|
| 935 |
+
border-radius: 20px;
|
| 936 |
+
background: white;
|
| 937 |
+
color: var(--text-color);
|
| 938 |
+
font-size: 13px;
|
| 939 |
+
font-weight: 500;
|
| 940 |
+
cursor: pointer;
|
| 941 |
+
transition: all 0.2s ease;
|
| 942 |
+
display: flex;
|
| 943 |
+
align-items: center;
|
| 944 |
+
gap: 6px;
|
| 945 |
+
}
|
| 946 |
+
|
| 947 |
+
.category-btn:hover {
|
| 948 |
+
border-color: var(--primary-color);
|
| 949 |
+
color: var(--primary-color);
|
| 950 |
+
}
|
| 951 |
+
|
| 952 |
+
.category-btn.active {
|
| 953 |
+
background: var(--primary-color);
|
| 954 |
+
border-color: var(--primary-color);
|
| 955 |
+
color: white;
|
| 956 |
+
}
|
| 957 |
+
|
| 958 |
+
.category-btn .category-count {
|
| 959 |
+
background: rgba(0, 0, 0, 0.1);
|
| 960 |
+
padding: 2px 8px;
|
| 961 |
+
border-radius: 10px;
|
| 962 |
+
font-size: 11px;
|
| 963 |
+
}
|
| 964 |
+
|
| 965 |
+
.category-btn.active .category-count {
|
| 966 |
+
background: rgba(255, 255, 255, 0.2);
|
| 967 |
+
}
|
| 968 |
+
|
| 969 |
+
.category-description {
|
| 970 |
+
text-align: center;
|
| 971 |
+
font-size: 13px;
|
| 972 |
+
color: #888;
|
| 973 |
+
margin-bottom: 16px;
|
| 974 |
+
}
|
| 975 |
+
|
| 976 |
+
@media (prefers-color-scheme: dark) {
|
| 977 |
+
.category-btn {
|
| 978 |
+
background: var(--light-gray);
|
| 979 |
+
border-color: var(--border-color);
|
| 980 |
+
}
|
| 981 |
+
|
| 982 |
+
.category-btn:hover {
|
| 983 |
+
border-color: var(--primary-color);
|
| 984 |
+
}
|
| 985 |
+
|
| 986 |
+
.category-btn.active {
|
| 987 |
+
background: var(--primary-color);
|
| 988 |
+
border-color: var(--primary-color);
|
| 989 |
+
}
|
| 990 |
+
}
|
| 991 |
</style>
|
| 992 |
{% endblock %}
|
| 993 |
|
|
|
|
| 1063 |
</div>
|
| 1064 |
|
| 1065 |
<div id="tts-public-leaderboard" class="leaderboard-view active">
|
| 1066 |
+
<!-- Category Filter -->
|
| 1067 |
+
<div class="category-filter">
|
| 1068 |
+
<button class="category-btn active" data-category="all">
|
| 1069 |
+
📊 전체
|
| 1070 |
+
<span class="category-count">{{ tts_leaderboard_all|length }}</span>
|
| 1071 |
+
</button>
|
| 1072 |
+
<button class="category-btn" data-category="mixed_lang">
|
| 1073 |
+
🔤 한영혼합
|
| 1074 |
+
<span class="category-count">{{ tts_leaderboard_mixed_lang|length }}</span>
|
| 1075 |
+
</button>
|
| 1076 |
+
<button class="category-btn" data-category="with_numbers">
|
| 1077 |
+
🔢 숫자혼합
|
| 1078 |
+
<span class="category-count">{{ tts_leaderboard_with_numbers|length }}</span>
|
| 1079 |
+
</button>
|
| 1080 |
+
<button class="category-btn" data-category="long_text">
|
| 1081 |
+
📝 긴문장
|
| 1082 |
+
<span class="category-count">{{ tts_leaderboard_long_text|length }}</span>
|
| 1083 |
+
</button>
|
| 1084 |
+
</div>
|
| 1085 |
+
<div class="category-description" id="category-description">
|
| 1086 |
+
모든 투표 기준 순위
|
| 1087 |
+
</div>
|
| 1088 |
+
|
| 1089 |
+
<!-- All Category Leaderboard -->
|
| 1090 |
+
<div id="leaderboard-all" class="category-leaderboard">
|
| 1091 |
+
{% if tts_leaderboard_all and tts_leaderboard_all|length > 0 %}
|
| 1092 |
+
<div class="leaderboard-container">
|
| 1093 |
+
<div class="leaderboard-header">
|
| 1094 |
+
<div>Rank</div>
|
| 1095 |
+
<div>Model</div>
|
| 1096 |
+
<div style="text-align: right">Win Rate</div>
|
| 1097 |
+
<div style="text-align: right" class="total-votes-header">Total Votes</div>
|
| 1098 |
+
<div style="text-align: right">ELO</div>
|
| 1099 |
+
</div>
|
| 1100 |
+
{% for model in tts_leaderboard_all %}
|
| 1101 |
+
<div class="leaderboard-row {{ model.tier }}">
|
| 1102 |
+
<div class="rank">#{{ model.rank }}</div>
|
| 1103 |
+
<div class="model-name">
|
| 1104 |
+
<a href="{{ model.model_url }}" target="_blank" class="model-name-link">{{ model.name }}</a>
|
| 1105 |
+
<div class="license-icon">
|
| 1106 |
+
{% if not model.is_open %}
|
| 1107 |
+
<img src="{{ url_for('static', filename='closed.svg') }}" alt="Proprietary">
|
| 1108 |
+
<span class="tooltip">Proprietary model</span>
|
| 1109 |
+
{% endif %}
|
| 1110 |
+
</div>
|
| 1111 |
+
</div>
|
| 1112 |
+
<div class="win-rate">{{ model.win_rate }}</div>
|
| 1113 |
+
<div class="total-votes">{{ model.total_votes }}</div>
|
| 1114 |
+
<div class="elo-score">{{ model.elo }}</div>
|
| 1115 |
+
</div>
|
| 1116 |
+
{% endfor %}
|
| 1117 |
</div>
|
| 1118 |
+
{% else %}
|
| 1119 |
+
<div class="no-data">
|
| 1120 |
+
<h3>No data available yet</h3>
|
| 1121 |
+
<p>Be the first to vote and help build the leaderboard!</p>
|
| 1122 |
+
<a href="{{ url_for('arena') }}" class="btn">Go to Arena</a>
|
| 1123 |
+
</div>
|
| 1124 |
+
{% endif %}
|
| 1125 |
+
</div>
|
| 1126 |
+
|
| 1127 |
+
<!-- Mixed Language Leaderboard -->
|
| 1128 |
+
<div id="leaderboard-mixed_lang" class="category-leaderboard" style="display: none;">
|
| 1129 |
+
{% if tts_leaderboard_mixed_lang and tts_leaderboard_mixed_lang|length > 0 %}
|
| 1130 |
+
<div class="leaderboard-container">
|
| 1131 |
+
<div class="leaderboard-header">
|
| 1132 |
+
<div>Rank</div>
|
| 1133 |
+
<div>Model</div>
|
| 1134 |
+
<div style="text-align: right">Win Rate</div>
|
| 1135 |
+
<div style="text-align: right" class="total-votes-header">Total Votes</div>
|
| 1136 |
+
<div style="text-align: right">ELO</div>
|
| 1137 |
+
</div>
|
| 1138 |
+
{% for model in tts_leaderboard_mixed_lang %}
|
| 1139 |
+
<div class="leaderboard-row {{ model.tier }}">
|
| 1140 |
+
<div class="rank">#{{ model.rank }}</div>
|
| 1141 |
+
<div class="model-name">
|
| 1142 |
+
<a href="{{ model.model_url }}" target="_blank" class="model-name-link">{{ model.name }}</a>
|
| 1143 |
+
<div class="license-icon">
|
| 1144 |
+
{% if not model.is_open %}
|
| 1145 |
+
<img src="{{ url_for('static', filename='closed.svg') }}" alt="Proprietary">
|
| 1146 |
+
<span class="tooltip">Proprietary model</span>
|
| 1147 |
+
{% endif %}
|
| 1148 |
+
</div>
|
| 1149 |
</div>
|
| 1150 |
+
<div class="win-rate">{{ model.win_rate }}</div>
|
| 1151 |
+
<div class="total-votes">{{ model.total_votes }}</div>
|
| 1152 |
+
<div class="elo-score">{{ model.elo }}</div>
|
| 1153 |
+
</div>
|
| 1154 |
+
{% endfor %}
|
| 1155 |
+
</div>
|
| 1156 |
+
{% else %}
|
| 1157 |
+
<div class="no-data">
|
| 1158 |
+
<h3>한영혼합 데이터가 없습니다</h3>
|
| 1159 |
+
<p>알파벳이 5글자 이상 포함된 문장에 대한 투표가 아직 없습니다.</p>
|
| 1160 |
+
</div>
|
| 1161 |
+
{% endif %}
|
| 1162 |
+
</div>
|
| 1163 |
+
|
| 1164 |
+
<!-- Numbers Leaderboard -->
|
| 1165 |
+
<div id="leaderboard-with_numbers" class="category-leaderboard" style="display: none;">
|
| 1166 |
+
{% if tts_leaderboard_with_numbers and tts_leaderboard_with_numbers|length > 0 %}
|
| 1167 |
+
<div class="leaderboard-container">
|
| 1168 |
+
<div class="leaderboard-header">
|
| 1169 |
+
<div>Rank</div>
|
| 1170 |
+
<div>Model</div>
|
| 1171 |
+
<div style="text-align: right">Win Rate</div>
|
| 1172 |
+
<div style="text-align: right" class="total-votes-header">Total Votes</div>
|
| 1173 |
+
<div style="text-align: right">ELO</div>
|
| 1174 |
+
</div>
|
| 1175 |
+
{% for model in tts_leaderboard_with_numbers %}
|
| 1176 |
+
<div class="leaderboard-row {{ model.tier }}">
|
| 1177 |
+
<div class="rank">#{{ model.rank }}</div>
|
| 1178 |
+
<div class="model-name">
|
| 1179 |
+
<a href="{{ model.model_url }}" target="_blank" class="model-name-link">{{ model.name }}</a>
|
| 1180 |
+
<div class="license-icon">
|
| 1181 |
+
{% if not model.is_open %}
|
| 1182 |
+
<img src="{{ url_for('static', filename='closed.svg') }}" alt="Proprietary">
|
| 1183 |
+
<span class="tooltip">Proprietary model</span>
|
| 1184 |
+
{% endif %}
|
| 1185 |
+
</div>
|
| 1186 |
</div>
|
| 1187 |
+
<div class="win-rate">{{ model.win_rate }}</div>
|
| 1188 |
+
<div class="total-votes">{{ model.total_votes }}</div>
|
| 1189 |
+
<div class="elo-score">{{ model.elo }}</div>
|
| 1190 |
</div>
|
| 1191 |
+
{% endfor %}
|
|
|
|
|
|
|
| 1192 |
</div>
|
| 1193 |
+
{% else %}
|
| 1194 |
+
<div class="no-data">
|
| 1195 |
+
<h3>숫자혼합 데이터가 없습니다</h3>
|
| 1196 |
+
<p>숫자가 2개 이상 포함된 문장에 대한 투표가 아직 없습니다.</p>
|
| 1197 |
+
</div>
|
| 1198 |
+
{% endif %}
|
| 1199 |
</div>
|
| 1200 |
+
|
| 1201 |
+
<!-- Long Text Leaderboard -->
|
| 1202 |
+
<div id="leaderboard-long_text" class="category-leaderboard" style="display: none;">
|
| 1203 |
+
{% if tts_leaderboard_long_text and tts_leaderboard_long_text|length > 0 %}
|
| 1204 |
+
<div class="leaderboard-container">
|
| 1205 |
+
<div class="leaderboard-header">
|
| 1206 |
+
<div>Rank</div>
|
| 1207 |
+
<div>Model</div>
|
| 1208 |
+
<div style="text-align: right">Win Rate</div>
|
| 1209 |
+
<div style="text-align: right" class="total-votes-header">Total Votes</div>
|
| 1210 |
+
<div style="text-align: right">ELO</div>
|
| 1211 |
+
</div>
|
| 1212 |
+
{% for model in tts_leaderboard_long_text %}
|
| 1213 |
+
<div class="leaderboard-row {{ model.tier }}">
|
| 1214 |
+
<div class="rank">#{{ model.rank }}</div>
|
| 1215 |
+
<div class="model-name">
|
| 1216 |
+
<a href="{{ model.model_url }}" target="_blank" class="model-name-link">{{ model.name }}</a>
|
| 1217 |
+
<div class="license-icon">
|
| 1218 |
+
{% if not model.is_open %}
|
| 1219 |
+
<img src="{{ url_for('static', filename='closed.svg') }}" alt="Proprietary">
|
| 1220 |
+
<span class="tooltip">Proprietary model</span>
|
| 1221 |
+
{% endif %}
|
| 1222 |
+
</div>
|
| 1223 |
+
</div>
|
| 1224 |
+
<div class="win-rate">{{ model.win_rate }}</div>
|
| 1225 |
+
<div class="total-votes">{{ model.total_votes }}</div>
|
| 1226 |
+
<div class="elo-score">{{ model.elo }}</div>
|
| 1227 |
+
</div>
|
| 1228 |
+
{% endfor %}
|
| 1229 |
+
</div>
|
| 1230 |
+
{% else %}
|
| 1231 |
+
<div class="no-data">
|
| 1232 |
+
<h3>긴문장 데이터가 없습니다</h3>
|
| 1233 |
+
<p>50글자 이상인 문장에 대한 투표가 아직 없습니다.</p>
|
| 1234 |
+
</div>
|
| 1235 |
+
{% endif %}
|
| 1236 |
</div>
|
|
|
|
| 1237 |
</div>
|
| 1238 |
|
| 1239 |
<div id="tts-personal-leaderboard" class="leaderboard-view" style="display: none;">
|
|
|
|
| 1634 |
setupHistoricalView('tts');
|
| 1635 |
setupHistoricalView('conversational');
|
| 1636 |
*/
|
| 1637 |
+
|
| 1638 |
+
// Category filter functionality
|
| 1639 |
+
const categoryBtns = document.querySelectorAll('.category-btn');
|
| 1640 |
+
const categoryLeaderboards = document.querySelectorAll('.category-leaderboard');
|
| 1641 |
+
const categoryDescription = document.getElementById('category-description');
|
| 1642 |
+
|
| 1643 |
+
const categoryDescriptions = {
|
| 1644 |
+
'all': '모든 투표 기준 순위',
|
| 1645 |
+
'mixed_lang': '알파벳 5글자 이상 포함된 문장 기준',
|
| 1646 |
+
'with_numbers': '숫자 2개 이상 포함된 문장 기준',
|
| 1647 |
+
'long_text': '50글자 이상 긴 문장 기준'
|
| 1648 |
+
};
|
| 1649 |
+
|
| 1650 |
+
categoryBtns.forEach(btn => {
|
| 1651 |
+
btn.addEventListener('click', function() {
|
| 1652 |
+
const category = this.dataset.category;
|
| 1653 |
+
|
| 1654 |
+
// Update active button
|
| 1655 |
+
categoryBtns.forEach(b => b.classList.remove('active'));
|
| 1656 |
+
this.classList.add('active');
|
| 1657 |
+
|
| 1658 |
+
// Update description
|
| 1659 |
+
if (categoryDescription) {
|
| 1660 |
+
categoryDescription.textContent = categoryDescriptions[category] || '';
|
| 1661 |
+
}
|
| 1662 |
+
|
| 1663 |
+
// Show/hide leaderboards
|
| 1664 |
+
categoryLeaderboards.forEach(lb => {
|
| 1665 |
+
lb.style.display = lb.id === `leaderboard-${category}` ? 'block' : 'none';
|
| 1666 |
+
});
|
| 1667 |
+
});
|
| 1668 |
+
});
|
| 1669 |
|
| 1670 |
// Final positioning after all DOM operations are complete
|
| 1671 |
setTimeout(positionSliders, 100);
|