Skip to content

Commit 4e1ee57

Browse files
committed
添加一些没有链接的文件
1 parent f9d541e commit 4e1ee57

File tree

4 files changed

+72
-34
lines changed

4 files changed

+72
-34
lines changed

Courseware/Letter.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# 给报考同学的劝退信
2+
同学你好!在每年的申请季都会收到相当多的申请 (也有一些看起来是海投的模板申请),所以我首先给所有希望加入课题组同学统一的公开回复,其中包括一些可能对你有 (劝) 用 (退) 的信息,也可以帮助你初步判断自己读研的定位。此外,我们有统一的招生流程,通常会在招生季启动,请按照此流程完成申请。
3+
4+
目前我感兴趣的研究方向是编程语言和 AI 技术在计算机系统工程中的应用。部分原因是,我有很多精力需要被迫投入到 “软件定义的泛在操作系统” 项目,另一方面原因是我希望每一个工作都能在实际系统中有切实的价值。因此你在我的论文列表中看到的论文不完全代表我的研究方向。(某种程度上,我希望做的每一个工作都是 first paper 或是 last paper,因此并不很想在同一个 topic 上再发表一篇 incremental 的工作。)
5+
6+
## 招生标准
7+
我对招收同学的唯一标准是 “会编程”。这主要包括:
8+
9+
- 能够较为熟练地、在手册和互联网 (和大语言模型/Copilot) 的指导下使用现代化的终端、Shell 和常用的命令行工具 (例如 tmux、正则表达式等) 和 IDE
10+
- 理解 Git 的核心概念,良好地了解并遵循开源软件开发的流程和编码规范,例如正确使用 gitignore、使用 Markdown 撰写文档、维护 Github Pages 等
11+
- 掌握一门 Python 这样的脚本语言,能够简化日常工作
12+
- 掌握一门 “课外” 的现代编程语言 (现代 C++/JavaScript, Haskell, Kotlin, Scala, Rust, ...),并能作为主力编程语言使用。了解它们背后的原理 (如虚拟机实现) 是一个加分项
13+
14+
一个并不必要但巨大的加分项是你不惧怕中等规模的代码项目 (例如 CPython, OpenJDK, Linux Kernel, ...)。你不需要了解它们的全部,但你如果能不畏惧地调试它们,并能从中理出一些头绪,这已经很了不起了!
15+
16+
上面的这些要求隐含了一点:你能够找到 “正确” 的方式训练自己、了解世界的前沿在哪里,而不局限于课堂。除此之外,如果你在某件事情上认为自己做得十分出众地好,你就很可能拥有能够作出了不起工作的潜力:在课堂之外,写过一个你认为十分了不起的代码、独立解决过一个你认为十分困难的问题、在一门非常有挑战性的课程上取得好成绩等。你不妨考虑一下你在大学期间认为最 “了不起” 的一件事,然后我们可以聊一聊。
17+
18+
我也要很抱歉 (无奈) 地告诉大家,今天的学术界惊人的内卷,因此导师招人也必须满足 “利益最大化”,把课程丢上网已经算是最大程度的 “做慈善” 了:学生一方面是被培养的对象,另一方面 (更重要的) 也是导师解决困难的研究问题或者完成项目的打手。只有目标匹配,导师的付出才有回报,而 “学习曲线过长无法产出” 的学生对于我们来说是非常难受的 “负资产”。
19+
20+
对于博士生,你的竞争对手是全世界某个研究领域里最聪明的一些人 (和一些最勤奋的卷王)。**我认为水 (哪怕是 CCF-A 类) paper 太无聊了。**我希望每一份工作都带有 “groundbreaking” 的属性:解决一个全新的重要问题,或是能给旧重要问题的解决带来重要的影响——当然,能不能做出来完全看运气;只是如果没有这个目标,就连 “一般” 的工作也做不出来了。事实证明,我的合作者们都过得相当辛苦。我希望投稿的每一份工作都能使这个领域最顶级的专家也感到很 cool,为此,而你必须首先成为领域专家。因此你会得到有挑战性的真问题,但同时你也需要真正 “不惧怕困难、渴望做出了不起的工作去改变世界” 才能坚持下去。请三思而行:选定了方向,某种程度说这就是地狱模式,而且我们有很多失败的先例。
21+
22+
对于硕士生,根据先前的经验,除非你在本科阶段受过非常良好的训练,并且自身素质极为优秀,在时间线的压力下让硕士生承担研究课题会使导师身心俱疲。本质上,硕士生的诉求是 “出去工作”,而课题组的诉求是 “完成科研任务”。因此,对于硕士生,我们更多的会安排一些事务性的工作,或是工程项目一部分,最后拼凑成毕业设计。作为交换,在完成任务的前提下可以得到更多的自由时间。
23+
24+
## 常见误区与劝退
25+
以下是一些常见的误区:
26+
27+
- “先读个硕士观望一下要不要读博士”:对我们来说,这是一个不存在的选项 (现在南京大学计算机系在推免时也分开了硕士和博士)。科研的入门训练是极为艰苦且漫长的。对硕士生,我们选择直接拿来当马仔。
28+
- “我现在还不太会,但我会努力学习”:很遗憾,无论导师是否尽职尽责,研究生总体来说还是带有交易的成分。一方面,无论你的导师给你画了多大的饼,用 “给导师劳动” 换取 “导师的指导” 都是在所难免的。另一方面,我更希望导师和学生站在平等的合作者位置,并且我非常喜欢能够据理力争挑战我观点的学生。我们期望我们的同学在对计算机世界的认识、阅读、写作方面没有明显的短板,例如知道世界顶级名校名课 (包括研究生课) 的水准并能跟上。
29+
- “我能力很强、参加了很多竞赛”:我自己是竞赛出身 (ICPC World Finalist),也是教练。从我的观察,大部分同学都没能迈过从 “业余选手” 到 “职业选手” 的门槛——给你更多的时间,能解出非常困难的题目。如果你接受过一点理论计算机科学的训练,就会发现竞赛作为一种 “竞技体育”,其实是性价比极低的。
30+
- “我发表了论文/专利/软著,我有过良好的科研训练”:我对论文的标准是 “教会你的大/小专家同行一些不 trivial 的事情”。据我近年观察,大部分申请者发表的论文都是减分项。相比于发表了 “错误” 论文或是在大创项目里学会了一本正经胡说八道的同学,我更偏好能耐心读论文和写代码的 “一张有潜力的白纸”。科学研究是脚踏实地的,前人所做到的 (内卷程度) 可能远比你想象得要大,认真读了 3-4 年博士依然没有论文的也大有人在,完全不必急功近利。
31+
32+
无论如何,都祝你申请顺利,去挑战真正 fundamental 的研究问题,并找到属于自己的一番天地!
308 KB
Loading

README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,11 @@ python脚本下载[jyy老师](https://jyywiki.cn/index.html)的主页课程课
2424
也因为文件众多,实在无法一个一个看过来,所以如果你发现了问题,无论是代码还是文件,你都可以提一个issue或者PR,成为本项目的贡献者,我也非常非常欢迎。我会在文末列举一个贡献者名单,指向你的私人链接。
2525

2626
# 更新
27+
## V2.6 2023-11-25
28+
- 添加了注释,对代码做了部分修改
29+
- 添加了文件`lab-makefile.png`
30+
- 本次更新主要是为了发布一个`release`。上个`release`中的文件存在无法加载PPT的问题,需要执行代码选择并输入`D`选择ALL或者`C`选择2023,即可修复路径引用的问题,才可以正常查看嵌入`.ipynb.html`文件中的PPT。
31+
2732
## V2.5 2023-11-23
2833
很久没有维护仓库了,其实也知道存在一些问题。今天一并完善好了。
2934

main.py

Lines changed: 35 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from bs4 import BeautifulSoup
77
from urllib.parse import urlparse
88

9+
910
BASE_URL = "https://jyywiki.cn"
1011
BASE_DIR = os.path.join(os.getcwd(), "Courseware")
1112
WITHOUT_DOWNLOAD = [
@@ -24,56 +25,55 @@
2425
"https://jyywiki.cn/ISER2023/1-intro/", # unnecessary
2526
"https://jyywiki.cn/index.html", # unnecessary
2627
]
27-
KEY_YEAR = {'A': "2021", 'B': "2022", 'C': "2023", 'D': "ALL", '': "2023"}
28-
28+
fail_download = []
2929
sources_url_path_pairs = {}
3030

3131

32+
# 通过某一文件路径以及文件中出现的相对链接,拼接成文件在本地的存储地址
3233
def get_full_path(path, link):
33-
pathdir = os.path.dirname(path).replace("/", os.sep)
34-
filepath = ""
34+
pathdir = os.path.dirname(path).replace("/", os.sep) # 用os.sep替换文件中提取出来的路径(文件中的路径都是`/`)
3535
if link.startswith("/"):
36-
if link.find("../") != -1:
36+
if link.find("../") != -1: # 滤过`/path/to/file/../path/to/file`
3737
return None
38-
filepath = os.path.join(BASE_DIR, link[1:].replace("/", os.sep))
38+
return os.path.join(BASE_DIR, link[1:].replace("/", os.sep)) # 舍弃第一个字符`/`
3939
elif link.startswith("../"):
4040
urlsplit = link.split("/")
4141
pathsplit = pathdir.split(os.sep)
42-
count = sum([-1 for item in urlsplit if item == ".."])
43-
filepath = os.path.join(os.sep.join(pathsplit[:count]), os.sep.join(urlsplit[-count:]))
42+
count = sum([-1 for item in urlsplit if item == ".."]) # 多个`../`这样的路径的处理
43+
return os.path.join(os.sep.join(pathsplit[:count]), os.sep.join(urlsplit[-count:]))
4444
else:
45-
filepath = os.path.join(pathdir, link.replace("/", os.sep))
46-
47-
return filepath
45+
return os.path.join(pathdir, link.replace("/", os.sep))
4846

4947

5048
def get_full_url(path):
51-
return path.replace(BASE_DIR, BASE_URL).replace("\\", "/")
49+
return path.replace(BASE_DIR, BASE_URL).replace("\\", "/") # url都是`/`,替换path中所有的`\`为`/`
5250

5351

54-
def download(url_, path_):
55-
if not os.path.exists(os.path.dirname(path_)):
56-
os.makedirs(os.path.dirname(path_))
57-
if os.path.exists(path_):
52+
def download(url, path):
53+
if not os.path.exists(os.path.dirname(path)):
54+
os.makedirs(os.path.dirname(path))
55+
if os.path.exists(path):
5856
return True
59-
response = requests.get(url_)
57+
response = requests.get(url)
6058
if response.status_code == 200:
6159
if response.headers['Content-Type'].startswith('text'):
62-
with open(path_, 'w', encoding="utf-8") as file:
60+
with open(path, 'w', encoding="utf-8") as file:
6361
file.write(response.text)
6462
else:
65-
with open(path_, 'wb') as file:
63+
with open(path, 'wb') as file: # 非文本文件
6664
file.write(response.content)
67-
print(f"\033[32m已下载 \033[0m文件链接 {url_}, 文件路径 {path_}")
65+
print(f"\033[32m已下载 \033[0m文件链接 {url}, 文件路径 {path}")
6866
return True
6967
else:
70-
print(f"\033[91m无法下载文件链接:状态码:\033[0m{response.status_code} \033[0m{url_}\033[91m")
68+
fail_download.append([response.status_code, url, path])
7169
return False
7270

7371

7472
def file_download_option():
7573
global sources_url_path_pairs
7674
global WITHOUT_DOWNLOAD
75+
KEY_YEAR = {'A': "2021", 'B': "2022", 'C': "2023", 'D': "ALL", '': "2023"}
76+
7777
def build_courseware_url_path(year):
7878
url_ = f'{BASE_URL}/OS/{year}/index.html'
7979
path_ = os.path.join(BASE_DIR, "OS", year, "index.html")
@@ -83,7 +83,7 @@ def build_courseware_url_path(year):
8383
"通过选项下载对应年份课件,回车默认下载2023年课件,输入其他符号则退出\n" +
8484
"\033[32mA\033[0m:2021 \033[32mB\033[0m:2022 "
8585
"\033[32mC\033[0m:2023 \033[32mD\033[0m:All\n")
86-
year = KEY_YEAR.get(year, "Invalid") # 将按键转化为年份
86+
year = KEY_YEAR.get(year, "Invalid") # 将输入转化为年份
8787

8888
if year == "ALL":
8989
for item in ['2021', '2022', '2023']:
@@ -109,6 +109,10 @@ def file_download():
109109
file_analyse(_path)
110110
else:
111111
WITHOUT_DOWNLOAD.append(_url)
112+
if fail_download:
113+
print("\033[91m无法下载如下文件:\033[0m")
114+
for code, url, path in fail_download: # 输出失败的文件下载以及应该在本地存储的位置
115+
print(f"\033[91m状态码:\033[0m{code} \033[0m{url}\033[91m 应存放:f{path}")
112116

113117

114118
# 提取每个文件中的链接
@@ -118,20 +122,19 @@ def file_analyse(filepath):
118122
# 对非HTML文件不做分析
119123
if filepath.endswith(".html"):
120124
with open(filepath, 'r', encoding='utf-8') as file:
121-
content = file.read()
122-
soup = BeautifulSoup(content, 'html.parser')
125+
soup = BeautifulSoup(file.read(), 'html.parser')
123126
else:
124127
return
125128

126129
# 提取文件中的相对链接
127-
_links_tags = soup.find_all(href=True) + soup.find_all(src=True) + soup.find_all(data=True)
128-
_links_attr = []
129-
for link in _links_tags:
130-
_links_attr.extend([link.get("href"), link.get("src"), link.get("data")])
131-
_links_attr = list(set(_links_attr)) # 去除重复的元素
130+
links_tags = soup.find_all(href=True) + soup.find_all(src=True) + soup.find_all(data=True)
131+
links_attr = []
132+
for link in links_tags:
133+
links_attr.extend([link.get("href"), link.get("src"), link.get("data")])
134+
links_attr = list(set(links_attr)) # 去除重复的元素
132135

133136
# 以filepath指定的文件为参照补全文件中的网址以及在本地存储的地址
134-
for link in _links_attr:
137+
for link in links_attr:
135138
if link is None or link.startswith(("http", "data")): # data是ipynb.html文件资源
136139
continue
137140
link = urlparse(link).path # 清除锚点
@@ -151,8 +154,7 @@ def file_fix():
151154
for item in filename:
152155
filepath = os.path.join(BASE_DIR, "OS", "2023", "build", item)
153156
with open(filepath, 'r', encoding='utf-8') as file:
154-
content = file.read()
155-
change = re.sub(r'/OS/2023/slides/', '../slides/', content)
157+
change = re.sub(r'/OS/2023/slides/', '../slides/', file.read())
156158

157159
with open(filepath, 'w', encoding='utf-8') as file:
158160
file.write(change)
@@ -163,8 +165,7 @@ def file_decode():
163165
for item in files:
164166
if item.endswith(".html"):
165167
with open(os.path.join(root, item), 'r', encoding='utf-8') as file:
166-
content = file.read()
167-
change = html.unescape(content)
168+
change = html.unescape(file.read())
168169

169170
with open(os.path.join(root, item), 'w', encoding='utf-8') as file:
170171
file.write(change)

0 commit comments

Comments
 (0)