freeCodeCamp 课程挑战文件格式解析:以椭圆(Ellipses)视频挑战为例
2026/9/5 18:03:03 网站建设 项目流程

freeCodeCamp 课程挑战文件格式解析:以椭圆(Ellipses)视频挑战为例

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

本篇以 freeCodeCamp 课程仓库中的挑战文件 ellipses-video.md 为主体,讲清一个challengeType: 11(video 类型)挑战文件的完整字段结构、它在课程块(block)中的组织方式、Joi 校验规则与前端渲染链路。读完后你能掌握:如何编写符合 schema 的视频讲解类挑战、如何用 frontmatter 与分区标记组织题目与视频答案,以及该文件涉及的椭圆数学知识点(标准方程与关键特征识别)。

一、挑战文件本体:Ellipses 视频挑战

该文件位于高级三角与圆锥曲线(advanced-trig-conics)块目录下,与同块的其他视频挑战(如 抛物线挑战、双曲线挑战)并列存放,全部为*-video.md命名:

curriculum/challenges/english/blocks/advanced-trig-conics/ ├── solving-right-triangles-video.md ├── law-of-cosines-video.md ├── parabolas-vertex-focus-directrix-video.md ├── ellipses-video.md ├── hyperbolas-video.md ├── polar-coordinates-video.md ├── parametric-equations-video.md └── difference-quotient-video.md

文件由 YAML frontmatter 和正文分区两部分构成。frontmatter 定义挑战的元数据:

--- id: 699e85648f18cf77dfce5c23 title: Ellipses challengeType: 11 videoId: AwBM2AMwfu8 dashedName: ellipses ---

各字段含义如下:

字段取值说明
id699e85648f18cf77dfce5c23课程数据的主键,24 位 ObjectId 格式
titleEllipses展示给学习者的挑战标题
challengeType11挑战类型,11表示 video(视频讲解)挑战
videoIdAwBM2AMwfu8嵌入播放器的视频 ID(YouTube 视频 ID)
dashedNameellipses小写连字符形式的 URL 名,用于生成学习路径

正文使用自由课程(freeCodeCamp 的 Markdown 挑战格式)的分区标记:

  • # --description--:介绍本视频的学习目标——椭圆的标准方程(standard equations)以及如何识别椭圆的关键特征;
  • # --questions--内部以## --text--给出题目文本,## --answers--中以---分隔符列出多个候选答案,## --video-solution--给出正确答案在答案列表中的序号(从 1 开始)。

本挑战的题目与四个候选答案为:

题目:What is an ellipse?(什么是椭圆?)

  1. The set of points such that the sum of the distances from two fixed points is constant.(到两个定点距离之和为常数的点的集合。)——正确答案
  2. The set of points such that the distance from one fixed point is constant.(到一定点距离为常数的点的集合——这是圆的定义。)
  3. The set of points such that the product of the distances from two fixed points is constant.(到两个定点距离之积为常数的点的集合。)
  4. The set of points equidistant from a line and a point.(到一条直线和一个定点距离相等的点的集合——这是抛物线的定义。)

--video-solution--中的1表示第 1 个答案是正确项。对照同块的双曲线挑战 hyperbolas-video.md,其四个选项与本题高度对称(双曲线对应“两点距离之差为常数”),--video-solution--2——这种题型设计是圆锥曲线三兄弟(圆、椭圆、双曲线)与抛物线定义辨析的典型考法。

二、椭圆知识要点:从挑战描述展开

挑战的 description 明确了三个学习要点:椭圆本身、标准方程、关键特征的识别。这正是题目答案所考查的核心定义,配合标准方程可以展开如下。

定义(即本挑战的正确答案):椭圆是平面上到两个定点(焦点,foci)距离之和为常数的点的集合,该常数记为 2a,且必须大于两焦点间距离 2c(即 a > c > 0)。

标准方程(以中心在原点为例):

  • 焦点在 x 轴上:x²/a² + y²/b² = 1(a > b > 0)
  • 焦点在 y 轴上:x²/b² + y²/a² = 1(a > b > 0)

其中 b² = a² − c²,a 为长半轴长,b 为短半轴长,c 为半焦距。

关键特征识别方法

特征如何由标准方程读出
中心方程中的平移量(原点则为 (0, 0))
焦点所在轴比较 a² 与 b² 的分母位置,较大的分母所在轴即焦点所在轴
顶点 (vertices)焦点轴上的端点,距中心为 a
共顶点 (co-vertices)短轴端点,距中心为 b
焦点焦点轴上距中心为 c 的两点,c = √(a² − b²)
离心率e = c/a,0 < e < 1,越接近 1 椭圆越扁

题目中四个干扰项分别对应圆(一定点等距)、距离积为常数曲线、抛物线(点到点与到线等距)的定义,这正是“识别椭圆”时最容易混淆的边界。

三、挑战在课程块中的注册:challengeOrder

视频挑战文件不是孤立的,它还必须在块结构文件中按 id 注册。本块的结构文件是 advanced-trig-conics.json:

{ "blockLabel": "lecture", "blockLayout": "challenge-list", "isUpcomingChange": false, "dashedName": "advanced-trig-conics", "helpCategory": "General", "challengeOrder": [ { "id": "699e854b8f18cf77dfce5c1e", "title": "Solving Right Triangles" }, { "id": "699e85518f18cf77dfce5c1f", "title": "Law of Cosines" }, { "id": "699e85568f18cf77dfce5c20", "title": "Law of Cosines - Old Version" }, { "id": "699e855a8f18cf77dfce5c21", "title": "Law of Sines" }, { "id": "699e855e8f18cf77dfce5c22", "title": "Parabolas - Vertex, Focus, Directrix" }, { "id": "699e85648f18cf77dfce5c23", "title": "Ellipses" }, { "id": "699e85688f18cf77dfce5c24", "title": "Hyperbolas" }, { "id": "699e856c8f18cf77dfce5c25", "title": "Polar Coordinates" }, { "id": "699e85718f18cf77dfce5c26", "title": "Parametric Equations" }, { "id": "699e8ca68f18cf77dfce5c27", "title": "Difference Quotient" } ] }

几个要点:

  • blockLabel: "lecture"表明这是一个讲解型块,blockLayout: "challenge-list"表示在前端以挑战列表形式逐题推进;
  • challengeOrder数组决定了学习顺序,Ellipses(id 与 md 文件 frontmatter 中的 id 完全一致)排在“Parabolas”之后、“Hyperbolas”之前,形成圆锥曲线的连续讲解链;
  • 新增一个视频挑战因此需要两件事:在curriculum/challenges/english/blocks/<block>/下编写 md 文件,并在此块 json 的challengeOrder中以正确的 id 注册(本块 id 前缀均为699e85...,说明同块挑战是批量生成同一批次的)。

四、Schema 校验:video 挑战字段的硬性约束

课程仓库用 Joi 对所有挑战数据做严格校验,核心实现在 challenge-schema.js。与本挑战直接相关的约束有:

1. challengeType 是 0–33 的整数(challenge-schema.js#L180):

challengeType: Joi.number().min(0).max(33).required(),

2. 类型 11 = video,由共享包统一定义(challenge-types.ts#L13):

const video = 11;

同一文件还声明了该类型的视图与提交方式:viewTypes[video]: 'generic'(走通用挑战渲染视图,challenge-types.ts#L117),submitTypes[video]: 'tests'(完成后按测试类流程提交,challenge-types.ts#L159),并且 video 属于hasNoSolution列表——视频挑战没有可展示的标准代码解法。

3. video 挑战专属字段(challenge-schema.js#L293-L313):

// video challenges only: videoId: Joi.when('challengeType', { is: [challengeTypes.video], then: Joi.string().required() }), videoLocaleIds: Joi.when('challengeType', { is: challengeTypes.video, then: Joi.object().keys({ espanol: Joi.string(), italian: Joi.string(), portuguese: Joi.string() }) }), bilibiliIds: Joi.when('challengeType', { is: challengeTypes.video, then: Joi.object().keys({ aid: Joi.number().required(), bvid: Joi.string().required(), cid: Joi.number().required() }) }),

也就是说:videoId是 video 挑战的必填项(本文件的AwBM2AMwfu8正因此必需);videoLocaleIds可按西语/意语/葡语覆盖默认视频;bilibiliIds(aid/bvid/cid 三元组)为中文环境提供备用播放源。本 Ellipses 挑战只声明了默认videoId,未配置多语言覆盖。

4. 题目结构(challenge-schema.js#L89-L102):

const questionJoi = Joi.object().keys({ text: Joi.string().required(), answers: Joi.array() .items( Joi.object().keys({ answer: Joi.string().required(), feedback: Joi.string().allow(null), audioId: Joi.string().allow(null) }) ) .required() .unique('answer'), solution: Joi.number().min(1).max(Joi.ref('..answers.length')).required() });

以及 questions 数组对 video 类型要求至少 1 题(challenge-schema.js#L314-L322):

questions: Joi.when('challengeType', { is: [challengeTypes.video, challengeTypes.multipleChoice, challengeTypes.theOdinProject], then: Joi.array().items(questionJoi).min(1).required(), otherwise: Joi.array().length(0) }),

对照本文件:--answers--中四个答案文本互不相同,满足unique('answer')--video-solution--1满足solution必须在[1, answers.length]区间内。答案条数不固定(schema 只要求非空且唯一),但solution越界会直接校验失败——这是编写此类挑战时最容易踩的坑。

五、前端渲染链路:videoId 如何变成播放器

从源码结构看,video 挑战(viewType 为generic)由通用视图 show.tsx 渲染,其中引用了视频播放器组件 video-player.tsx。关键逻辑:

if (bilibiliIds && ['chinese', 'chinese-traditional'].includes(clientLocale)) { const { aid, bvid, cid } = bilibiliIds; bilibiliSrc = `//player.bilibili.com/player.html?aid=${aid}&bvid=${bvid}&cid=${cid}`; } if (videoLocaleIds) { const localeId = videoLocaleIds[clientLocale as keyof VideoLocaleIds]; videoId = localeId || videoId; }

即:优先按客户端语言选择 B 站 iframe(仅中文/繁体中文环境且配置了bilibiliIds时)或对应语言版本的 YouTube 视频 ID;否则回退到默认videoId,通过react-youtuberel: 0(禁用相关视频推荐)嵌入播放(video-player.tsx#L66-L80)。另外播放倍速会被写入本地存储(fcc-yt-playback-rate),学习进度以“视频加载完成 + 题目答对”为准。

对 Ellipses 挑战来说,它只声明了默认videoId: AwBM2AMwfu8且无bilibiliIds,因此所有语言环境都嵌入同一个 YouTube 视频,用户观看后答对那道定义选择题即完成本挑战,并在 advanced-trig-conics.json 定义的学习序列中解锁下一题(Hyperbolas)。

六、小结:一个视频挑战文件的完整契约

综合 frontmatter、schema 与渲染端,一个可被课程管线接受的 video 挑战(以 ellipses-video.md 为范本)需要满足:

  1. frontmatter 提供合法 ObjectIdidchallengeType: 11、必填videoId、连字符式dashedName
  2. 正文含# --description--# --questions--(至少一题,选项互不相同)、## --video-solution--(1 起的序号,不超过选项数);
  3. 在所属块的结构 json(curriculum/structure/blocks/*.json)的challengeOrder中按 id 注册,且 id 与文件内一致;
  4. 可选地配置videoLocaleIds(espanol/italian/portuguese 视频)与bilibiliIds(aid/bvid/cid)做多语言播放源。

这份文件本身承载的数学内容——椭圆“两焦点距离和为定值”的定义、标准方程与特征识别——则是 freeCodeCamp 在数学课程线中用“视频讲解 + 概念选择题”这一最轻量的挑战形态来传递知识点的典型样本。

【免费下载链接】freeCodeCampfreeCodeCamp.org's open-source codebase and curriculum. Learn math, programming, and computer science for free.项目地址: https://gitcode.com/GitHub_Trending/fr/freeCodeCamp

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询