Skip to content

Instantly share code, notes, and snippets.

@satoooon8888
Created December 20, 2022 14:26
Show Gist options
  • Save satoooon8888/295b57c3b141346ad8b175d4f7569f59 to your computer and use it in GitHub Desktop.
Save satoooon8888/295b57c3b141346ad8b175d4f7569f59 to your computer and use it in GitHub Desktop.
Visualize CTFTime Statistics
import matplotlib.pyplot as plt
import json
import re
from datetime import datetime
events = json.load(open("./events.json"))
events = sorted(events, key=lambda event:datetime.fromisoformat(event["start"]))
# for event in events:
# print(f"[{datetime.fromisoformat(event['start']).strftime('%Y-%m-%d %H:%M:%S')}] {event['title']}")
# eventの例を表示
print(json.dumps(events[-1], indent=2))
print("LEN: ", len(events))
# 年ごとにeventsを分ける
yearly_events = {}
for event in events:
start_year = str(datetime.fromisoformat(event['start']).year)[2:]
if int(start_year) < 11 or 22 < int(start_year):
continue
if start_year not in yearly_events:
yearly_events[start_year] = []
yearly_events[start_year].append(event)
# CTFがある年のリストを生成
years = list(yearly_events.keys())
# 毎年のCTFの数
yearly_events_num = []
for year_events in yearly_events.values():
yearly_events_num.append(0)
for event in year_events:
yearly_events_num[-1] += 1
plt.grid()
plt.title("number of events")
plt.bar(years, yearly_events_num, label="events")
plt.show()
# CTFごとの結果を取得
results = json.load(open("results.json"))
# 毎年のCTFに参加するチーム数の平均
yearly_average_participants = []
for year_events in yearly_events.values():
yearly_average_participants.append(0)
for event in year_events:
if str(event["id"]) not in results:
continue
participant_count = len(results[str(event["id"])]["scores"])
# if participant_count != event["participants"]:
# print(event, participant_count)
yearly_average_participants[-1] += participant_count
yearly_average_participants[-1] /= len(year_events)
valid_years = list(years)
while yearly_average_participants[0] == 0:
valid_years.pop(0)
yearly_average_participants.pop(0)
while yearly_average_participants[-1] == 0:
valid_years.pop()
yearly_average_participants.pop()
plt.grid()
plt.title("average participant")
plt.bar(valid_years, yearly_average_participants, label="participant")
plt.legend()
plt.show()
# CTFのスコアを0~1に標準化して、年ごとに集計
yearly_difficulty_dist = []
for year_events in yearly_events.values():
yearly_difficulty_dist.append([])
for event in year_events:
if str(event["id"]) not in results:
continue
scores = results[str(event["id"])]["scores"]
min_score = float(scores[-1]["points"])
max_score = float(scores[0]["points"])
if max_score - min_score <= 0:
continue
std_points = []
for score in scores:
std_point = (float(score["points"]) - min_score) / (max_score - min_score)
if std_point < 0 or 1 < std_point:
print(event["title"], event["ctftime_url"])
std_points = []
break
# print(score["points"], max_score, min_score, std_point)
std_points.append(std_point)
yearly_difficulty_dist[-1] += std_points
valid_years = list(years)
while len(yearly_difficulty_dist[0]) == 0:
valid_years.pop(0)
yearly_difficulty_dist.pop(0)
while len(yearly_difficulty_dist[-1]) == 0:
valid_years.pop()
yearly_difficulty_dist.pop()
plt.grid()
plt.title(f"difficulty")
plt.boxplot(yearly_difficulty_dist, labels=valid_years, whis=[0, 100])
plt.show()
# 年ごとの競技時間の分布
yearly_duration_dist = []
for i, year_events in enumerate(yearly_events.values()):
yearly_duration_dist.append([])
for event in year_events:
duration = event['duration']['hours'] + event['duration']['days'] * 24
if duration <= 0 or 24*5 < duration:
continue
yearly_duration_dist[-1].append(duration)
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.set_title("duration")
ax.grid()
ax.set_xticks(list(range(1, len(valid_years)+1)))
ax.set_xticklabels(valid_years)
ax.violinplot(yearly_duration_dist)
plt.show()
title_stats = {
r"[^ ]CTF": 0,
r" CTF": 0,
r"Capture ?The ?Flag": 0,
r"[^ ]CON ": 0,
r"Finals?": 0
}
for event in events:
title = event["title"]
for regex in title_stats.keys():
if re.search(regex, title, re.IGNORECASE):
title_stats[regex] += 1
print(title_stats)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment