leetcode/solution/util.py

285 lines
10 KiB
Python

import json
import os
import re
from typing import Tuple, List
from urllib.parse import quote, unquote
def load_template(template_name: str) -> str:
with open("./template.md", 'r', encoding='utf-8') as f:
content = f.read()
start_text = f"<!-- 这里是{template_name}开始位置 -->"
end_text = f'<!-- 这里是{template_name}结束位置 -->'
content = re.search(f"{start_text}(.*?){end_text}", content, re.S).group(1)
return content.strip()
readme_cn = load_template('readme_template')
readme_en = load_template('readme_template_en')
problem_readme_cn = load_template('problem_readme_template')
problem_readme_en = load_template('problem_readme_template_en')
sql_readme_cn = load_template('sql_problem_readme_template')
sql_readme_en = load_template('sql_problem_readme_template_en')
bash_readme_cn = load_template('bash_problem_readme_template')
bash_readme_en = load_template('bash_problem_readme_template_en')
ts_readme_cn = load_template('ts_problem_readme_template')
ts_readme_en = load_template('ts_problem_readme_template_en')
contest_readme_cn = load_template('contest_readme_template')
contest_readme_en = load_template('contest_readme_template_en')
def load_cookies() -> Tuple[str, str]:
cookie_cn, cookie_en = '', ''
env_file = './.env'
if not os.path.exists(env_file):
return cookie_cn, cookie_en
with open(env_file, "r") as f:
lines = f.readlines()
for line in lines:
if line.startswith("COOKIE_CN"):
parts = line.split("=")[1:]
cookie_cn = "=".join(parts).strip().strip('"')
continue
if line.startswith("COOKIE_EN"):
parts = line.split("=")[1:]
cookie_en = "=".join(parts).strip().strip('"')
continue
return cookie_cn, cookie_en
def load_refresh_config() -> bool:
env_file = './.env'
if not os.path.exists(env_file):
return False
with open(env_file, "r") as f:
lines = f.readlines()
for line in lines:
if line.startswith("REFRESH"):
parts = line.split("=")[1:]
return "=".join(parts).strip().strip('"') == 'True'
return False
def load_result() -> List[dict]:
result_file = './result.json'
if not os.path.exists(result_file):
return []
with open(result_file, 'r', encoding='utf-8') as f:
res = f.read()
return json.loads(res)
def load_contest_result() -> List[dict]:
contest_result_file = './contest.json'
if not os.path.exists(contest_result_file):
return []
with open(contest_result_file, 'r', encoding='utf-8') as f:
res = f.read()
if res:
return json.loads(res)
return []
def save_result(data: List[dict]):
with open('./result.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(data))
def save_contest_result(data: List[dict]):
with open('./contest.json', 'w', encoding='utf-8') as f:
f.write(json.dumps(data))
def select_templates(category):
if category == 'Shell':
return [bash_readme_cn, bash_readme_en]
if category == 'Database':
return [sql_readme_cn, sql_readme_en]
if category == 'JavaScript' or category == 'TypeScript':
return [ts_readme_cn, ts_readme_en]
return [problem_readme_cn, problem_readme_en]
def generate_readme(result):
md_table_cn = [item['md_table_row_cn'] for item in result]
md_table_en = [item['md_table_row_en'] for item in result]
# generate README.md
items = []
table_cn = '\n| 题号 | 题解 | 标签 | 难度 | 备注 |\n| --- | --- | --- | --- | --- |'
for item in sorted(md_table_cn, key=lambda x: x[0]):
items.append(
f'\n| {item[0]} | {item[1]} | {item[2]} | {item[3]} | {item[4]} |'
)
table_cn += ''.join(items)
# generate README_EN.md
items = []
table_en = '\n| # | Solution | Tags | Difficulty | Remark |\n| --- | --- | --- | --- | --- |'
for item in sorted(md_table_en, key=lambda x: x[0]):
items.append(
f'\n| {item[0]} | {item[1]} | {item[2]} | {item[3]} | {item[4]} |'
)
table_en += ''.join(items)
with open('./README.md', 'w', encoding='utf-8') as f:
f.write(readme_cn.format(table_cn))
with open('./README_EN.md', 'w', encoding='utf-8') as f:
f.write(readme_en.format(table_en))
def generate_question_readme(result):
for item in result:
if not item['content_cn'] and not item['content_en']:
continue
path = (
f'./{item["sub_folder"]}/{item["frontend_question_id"]}.{item["title_en"]}'
)
path = path.replace(":", " ")
if os.path.isdir(path):
continue
os.makedirs(path)
# choose the readme template
category = item['category']
readme_template_cn, readme_template_en = select_templates(category)
# generate lc-cn problem readme
with open(f'{path}/README.md', 'w', encoding='utf-8') as f1:
f1.write(
readme_template_cn.format(
int(item['frontend_question_id']),
item["title_cn"],
item['url_cn'],
item['relative_path_en'],
item['content_cn'],
)
)
# generate lc-en problem readme
with open(f'{path}/README_EN.md', 'w', encoding='utf-8') as f2:
f2.write(
readme_template_en.format(
int(item['frontend_question_id']),
item["title_en"],
item['url_en'],
item['relative_path_cn'],
item['content_en'],
)
)
def generate_summary(result):
"""generate summary files"""
summary_cn = summary_en = ''
m = {int(item['frontend_question_id']): item for item in result}
for file in sorted(os.listdir("./"), key=lambda x: x.lower()):
if os.path.isdir("./" + file) and file != '__pycache__':
summary_cn += f'\n- {file}\n'
summary_en += f'\n- {file}\n'
for sub in sorted(os.listdir('./' + file), key=lambda x: x.lower()):
sub = sub.replace('`', ' ')
enc = quote(sub)
data = m.get(int(sub[:4]))
sub_cn = sub
if data:
sub_cn = sub[:5] + data['title_cn']
summary_cn += f' - [{sub_cn}](/solution/{file}/{enc}/README.md)\n'
summary_en += f' - [{sub}](/solution/{file}/{enc}/README_EN.md)\n'
# generate summary.md
with open('./summary.md', 'w', encoding='utf-8') as f:
f.write(summary_cn)
# generate summary_en.md
with open('./summary_en.md', 'w', encoding='utf-8') as f:
f.write(summary_en)
def refresh(result):
"""update problems"""
pattern = re.compile("src=\"(.*?)\"")
skip_question_ids = {3, 33, 34, 1599}
for question in result:
front_question_id = question['frontend_question_id']
print(front_question_id)
if int(front_question_id) in skip_question_ids:
continue
title = question['title_cn']
title_en = question['title_en']
path_cn = unquote(str(question['relative_path_cn']).replace("/solution", "."))
path_en = unquote(str(question['relative_path_en']).replace("/solution", "."))
with open(path_cn, 'r', encoding='utf-8') as f1:
cn_content = f1.read()
# update title
with open(path_en, 'r', encoding='utf-8') as f2:
en_content = f2.read()
i = cn_content.index('. ')
j = cn_content.index(']')
cn_content = cn_content.replace(cn_content[i + 2: j], title)
i = en_content.index('. ')
j = en_content.index(']')
en_content = en_content.replace(en_content[i + 2: j], title_en)
# update question content
old_content = re.search("<!-- 这里写题目描述 -->(.*?)## 解法", cn_content, re.S).group(1)
if question.get('content_cn'):
cn_content = cn_content.replace(
old_content, "\n\n" + question['content_cn'] + "\n\n"
).replace("\n\n <ul>", "\n <ul>")
# replace image url to cdn link
for url in pattern.findall(cn_content) or []:
image_name = (
os.path.basename(url).replace('.PNG', '.png').replace('.JPG', '.jpg')
)
new_url = (
'https://fastly.jsdelivr.net/gh/doocs/leetcode@main'
+ str(question['relative_path_cn']).replace("README.md", "images/")
+ image_name
)
cn_content = cn_content.replace(url, new_url)
with open(path_cn, 'w', encoding='utf-8') as f1:
f1.write(cn_content)
old_content = re.search(
"## Description(.*?)## Solutions", en_content, re.S
).group(1)
if question.get('content_en'):
en_content = en_content.replace(
old_content, "\n\n" + question['content_en'] + "\n\n"
).replace("\n\n <ul>", "\n <ul>")
for url in pattern.findall(en_content) or []:
image_name = (
os.path.basename(url).replace('.PNG', '.png').replace('.JPG', '.jpg')
)
new_url = (
'https://fastly.jsdelivr.net/gh/doocs/leetcode@main'
+ str(question['relative_path_cn']).replace("README.md", "images/")
+ image_name
)
en_content = en_content.replace(url, new_url)
with open(path_en, 'w', encoding='utf-8') as f2:
f2.write(en_content)
def generate_contest_readme(result: List):
result.sort(key=lambda x: -x[0])
content_cn = '\n\n'.join(c[1] for c in result)
content_en = '\n\n'.join(c[2] for c in result)
content_cn = contest_readme_cn.format(content_cn)
with open('./CONTEST_README.md', 'w', encoding='utf-8') as f:
f.write(content_cn)
content_en = contest_readme_en.format(content_en)
with open('./CONTEST_README_EN.md', 'w', encoding='utf-8') as f:
f.write(content_en)