88VALID_EXT = (".py" , ".cpp" , ".java" , ".kt" , ".js" )
99
1010# -----------------------------
11- # 난이도 정렬 기준 (백준)
11+ # 백준 난이도 순서
1212# -----------------------------
1313BOJ_LEVEL_RANK = {
1414 "Bronze V" : 1 , "Bronze IV" : 2 , "Bronze III" : 3 , "Bronze II" : 4 , "Bronze I" : 5 ,
2020}
2121
2222# -----------------------------
23- # 백준 정보 가져오기
23+ # 백준 정보
2424# -----------------------------
2525def fetch_boj_info (number ):
2626 url = f"https://solved.ac/api/v3/problem/show?problemId={ number } "
@@ -36,7 +36,7 @@ def fetch_boj_info(number):
3636 return None
3737
3838# -----------------------------
39- # 프로그래머스 정보 가져오기
39+ # 프로그래머스 정보
4040# -----------------------------
4141def fetch_programmers_info (pid ):
4242 url = f"https://school.programmers.co.kr/learn/courses/30/lessons/{ pid } "
@@ -75,12 +75,27 @@ def level_rank(platform, level):
7575# -----------------------------
7676def process_directory (dir_path ):
7777 readme_path = os .path .join (dir_path , "README.md" )
78- if not os .path .isfile (readme_path ):
79- return False
80-
78+ existing_rows = []
79+
80+ if os .path .isfile (readme_path ):
81+ # 기존 라인 읽기
82+ with open (readme_path , "r" , encoding = "utf-8" ) as f :
83+ lines = f .readlines ()
84+ for line in lines :
85+ m = re .search (r"\|\s*(⬜|✅|❌)\s*\|\s*(백준|프로그래머스)\s*\|\s*\[?(\d+)\]?" , line )
86+ if m :
87+ status , platform , number = m .groups ()
88+ existing_rows .append ({
89+ "platform" : platform ,
90+ "number" : number ,
91+ "status" : status ,
92+ "title" : "" , # 나중에 갱신
93+ "level" : "" ,
94+ "link" : ""
95+ })
96+
97+ # 새 파일 탐지
8198 files = os .listdir (dir_path )
82- problems = {}
83-
8499 for f in files :
85100 name , ext = os .path .splitext (f )
86101 if ext not in VALID_EXT :
@@ -91,70 +106,64 @@ def process_directory(dir_path):
91106 if m :
92107 num = m .group (1 )
93108 status = "❌" if name .endswith ("_FAIL" ) else "✅"
94- problems [f"bj_{ num } " ] = ("백준" , num , status )
109+ # 기존 행 없으면 추가
110+ if not any (r ["number" ] == num and r ["platform" ] == "백준" for r in existing_rows ):
111+ existing_rows .append ({"platform" : "백준" , "number" : num , "status" : status , "title" : "" , "level" : "" , "link" : "" })
112+ else :
113+ # 기존 행이 있으면 상태 갱신
114+ for r in existing_rows :
115+ if r ["number" ] == num and r ["platform" ] == "백준" :
116+ r ["status" ] = status
95117
96118 # 프로그래머스
97119 m = re .match (r"pg_(\d+)(?:_FAIL)?$" , name )
98120 if m :
99121 num = m .group (1 )
100122 status = "❌" if name .endswith ("_FAIL" ) else "✅"
101- problems [f"pg_{ num } " ] = ("프로그래머스" , num , status )
102-
103- # 기존 README 읽기
104- existing_numbers = set ()
105- with open (readme_path , "r" , encoding = "utf-8" ) as f :
106- lines = f .readlines ()
107- for line in lines :
108- m = re .search (r"\|\s*(?:⬜|✅|❌)\s*\|\s*(백준|프로그래머스)\s*\|\s*(\d+)" , line )
109- if m :
110- existing_numbers .add (m .group (2 ))
111-
112- # 기존 문제 + 새 문제 모두 rows로 준비
113- rows = []
114-
115- for _ , (platform , num , status ) in problems .items ():
116- if platform == "백준" :
117- info = fetch_boj_info (num )
123+ if not any (r ["number" ] == num and r ["platform" ] == "프로그래머스" for r in existing_rows ):
124+ existing_rows .append ({"platform" : "프로그래머스" , "number" : num , "status" : status , "title" : "" , "level" : "" , "link" : "" })
125+ else :
126+ for r in existing_rows :
127+ if r ["number" ] == num and r ["platform" ] == "프로그래머스" :
128+ r ["status" ] = status
129+
130+ # 정보 갱신 (이름, 난이도, 링크)
131+ for r in existing_rows :
132+ if r ["platform" ] == "백준" :
133+ info = fetch_boj_info (r ["number" ])
118134 else :
119- info = fetch_programmers_info (num )
120-
121- title = info ["title" ] if info else "UNKNOWN"
122- level = info ["level" ] if info else "UNKNOWN"
123- link = info ["link" ] if info else "#"
124-
125- rows .append ({
126- "platform" : platform ,
127- "number" : num ,
128- "status" : status ,
129- "title" : title ,
130- "level" : level ,
131- "link" : link
132- })
135+ info = fetch_programmers_info (r ["number" ])
136+ if info :
137+ r ["title" ] = info ["title" ]
138+ r ["level" ] = info ["level" ]
139+ r ["link" ] = info ["link" ]
140+ else :
141+ r ["title" ] = r .get ("title" ) or "UNKNOWN"
142+ r ["level" ] = r .get ("level" ) or "UNKNOWN"
143+ r ["link" ] = r .get ("link" ) or "#"
133144
134145 # 정렬
135- rows .sort (key = lambda r : (
146+ existing_rows .sort (key = lambda r : (
136147 platform_rank (r ["platform" ]),
137148 level_rank (r ["platform" ], r ["level" ]),
138149 int (r ["number" ])
139150 ))
140151
141152 # README 작성
142153 new_lines = [
143- "| 순번 | 풀이 여부 | 플랫폼 | 문제 번호 | 문제 이름 | 난이도 | 풀이 링크 |\n " ,
144- "|----|----|----|----|----|----| ----|\n "
154+ "| 순번 | 풀이 여부 | 플랫폼 | 문제 번호 / 링크 | 문제 이름 | 난이도 | 풀이 링크 |\n " ,
155+ "|----|----|----|------------------ |----------- |--------|------- ----|\n "
145156 ]
146-
147- for i , r in enumerate (rows ):
157+ for i , r in enumerate (existing_rows ):
148158 new_lines .append (
149159 f"| { i :03d} | { r ['status' ]} | { r ['platform' ]} | "
150160 f"[{ r ['number' ]} ]({ r ['link' ]} ) | "
151- f"[ { r ['title' ]} ]( { r [ 'link' ] } ) | { r ['level' ]} | |\n "
161+ f"{ r ['title' ]} | { r ['level' ]} | |\n "
152162 )
153163
154164 with open (readme_path , "w" , encoding = "utf-8" ) as f :
155165 f .writelines (new_lines )
156166
157- return True
158167
159168# -----------------------------
160169# main
@@ -163,11 +172,8 @@ def main():
163172 for root , dirs , files in os .walk (ROOT_DIR ):
164173 if root .startswith ("./.git" ) or root .startswith ("./.github" ):
165174 continue
166-
167- # ✅ 루트 README 제외
168- if root == "." :
175+ if root == "." : # 루트 README 제외
169176 continue
170-
171177 process_directory (root )
172178
173179
0 commit comments