diff --git a/src/styles/Home.module.css b/src/styles/Home.module.css
index 5802e98..977dd08 100644
--- a/src/styles/Home.module.css
+++ b/src/styles/Home.module.css
@@ -88,7 +88,7 @@
}
.example {
- margin: 2rem 0;
+ margin: 0 0 2rem 0;
text-align: center;
}
diff --git a/src/types/index.ts b/src/types/index.ts
index 031f974..8b97c73 100644
--- a/src/types/index.ts
+++ b/src/types/index.ts
@@ -10,6 +10,28 @@ export interface TuserData {
solved: number;
rank: number;
score: number;
+ category?: {
+ pwnable?: {
+ score: number;
+ rank: number;
+ };
+ reversing?: {
+ score: number;
+ rank: number;
+ };
+ web?: {
+ score: number;
+ rank: number;
+ };
+ crypto?: {
+ score: number;
+ rank: number;
+ };
+ [key: string]: {
+ score: number;
+ rank: number;
+ } | undefined;
+ };
};
ctf: {
rank: number;
@@ -38,4 +60,17 @@ export interface TUserRankingResponse {
export interface TUserRankingResult {
id: number;
nickname: string;
+}
+
+export interface TCategoryData {
+ name: string;
+ score: number;
+ rank: number;
+ color: string;
+}
+
+export interface TCategoryStats {
+ nickname: string;
+ total_score: number;
+ categories: TCategoryData[];
}
\ No newline at end of file
diff --git a/src/utils/generateCategorySvg.ts b/src/utils/generateCategorySvg.ts
new file mode 100644
index 0000000..1842adc
--- /dev/null
+++ b/src/utils/generateCategorySvg.ts
@@ -0,0 +1,125 @@
+import { TCategoryStats } from '../types';
+
+export function generateCategorySvg(stats: TCategoryStats): string {
+ // SVG 크기 및 차트 설정
+ const width = 390;
+ const height = 190;
+ const pieCenterX = 290; // 원형 차트 중심 X (왼쪽)
+ const pieCenterY = 96; // 원형 차트 중심 Y
+ const radius = 88; // 원형 차트 반지름
+
+ // 전체 스코어
+ const totalScore = stats.total_score;
+
+ // 카테고리 데이터
+ const categories = stats.categories;
+ const totalCategoryScore = categories.reduce((sum, category) => sum + category.score, 0);
+
+ // 원 차트 및 범례 생성
+ let pieChart = '';
+ let legends = '';
+ let currentAngle = 0;
+
+ const legendStartX = 25; // 범례 시작 X 위치 (오른쪽)
+ const legendStartY = 80; // 범례 시작 Y 위치 (제목 아래)
+ const legendItemHeight = 22; // 범례 항목 간 간격
+ const maxLegendItems = 5; // 표시할 최대 범례 항목 수
+
+ // 카테고리가 없는 경우
+ if (categories.length === 0 || totalCategoryScore === 0) {
+ pieChart = `
+
No data`;
+ legends = `
No category data`;
+ } else {
+ // 상위 카테고리만 범례에 표시 (최대 maxLegendItems개)
+ const topCategories = categories.slice(0, maxLegendItems);
+
+ categories.forEach((category) => {
+ const percentage = category.score / totalCategoryScore;
+ const angleSize = percentage * 360;
+ const endAngle = currentAngle + angleSize;
+
+ // 원형 조각 경로
+ const startX = pieCenterX + radius * Math.cos((currentAngle - 90) * Math.PI / 180);
+ const startY = pieCenterY + radius * Math.sin((currentAngle - 90) * Math.PI / 180);
+ const endX = pieCenterX + radius * Math.cos((endAngle - 90) * Math.PI / 180);
+ const endY = pieCenterY + radius * Math.sin((endAngle - 90) * Math.PI / 180);
+ const largeArcFlag = angleSize > 180 ? 1 : 0;
+
+ const path = `
+
+ `;
+
+ // 퍼센트 라벨
+ const midAngle = currentAngle + angleSize / 2;
+ const labelRadius = radius * 0.70;
+ const labelX = pieCenterX + labelRadius * Math.cos((midAngle - 90) * Math.PI / 180) - 3;
+ const labelY = pieCenterY + labelRadius * Math.sin((midAngle - 90) * Math.PI / 180);
+ const percentLabel = percentage > 0.05 ? // 5% 이상만 표시
+ `
${Math.round(percentage * 100)}%` : '';
+
+ pieChart += path + percentLabel;
+ currentAngle = endAngle;
+ });
+
+ // 범례 생성 (상위 카테고리만)
+ topCategories.forEach((category, index) => {
+ const legendY = legendStartY + (index * legendItemHeight);
+ legends += `
+
+
${category.name}: ${category.score}
+ `;
+ });
+ }
+
+ // 중앙 총점 표시 (원형 차트 내부에)
+ const centerCircle = `
+
+
Score
+
${totalScore}
+ `;
+
+ // 제목 (오른쪽 상단)
+ const header = `
+
Dreamhack
+
Most solved categories
+ `;
+
+ // SVG 구조 반환
+ return `
+
+ `;
+}
\ No newline at end of file
diff --git a/src/utils/generateSvg.ts b/src/utils/generateStatsSvg.ts
similarity index 89%
rename from src/utils/generateSvg.ts
rename to src/utils/generateStatsSvg.ts
index b943c9a..762c6ce 100644
--- a/src/utils/generateSvg.ts
+++ b/src/utils/generateStatsSvg.ts
@@ -1,6 +1,6 @@
import { Tstats } from '../types';
-export function generateSvg(stats: Tstats): string {
+export function generateStatsSvg(stats: Tstats): string {
return `