config.json


config.json文件描述 track 的配置,其中包含 track 的练习和概念等重要信息。

元数据

以下顶层属性包含 track 的常规元数据:

  • language:track 的语言(例如"C#")。长度必须 <= 255。(必填)
  • slug:以小写 kebab-case 字符串表示的 track 语言(例如"csharp")。长度必须 <= 255。(必填)
  • active:一个boolean值,表示该 track 是否处于活跃状态(即学生能否在网站上加入该 track)(必填)
  • blurb:对这门语言的简短描述。长度必须 <= 400。(必填)
  • version:config.json文件的版本(目前固定为3)(必填)
  • online_editor:描述在线编辑器所用设置的对象:(必填)
    • indent_style:"space"或"tab"(必填)
    • indent_size:缩进大小,整数(例如4)(必填)
    • highlightjs_language:Highlight.js 的语言标识符(见标识符完整列表)(可选)
  • status:描述应启用哪些 v3 功能的对象:(必填)
    • concept_exercises:一个boolean值,表示是否已构建概念练习(必填)。为true时,Exercism 网站的界面会相应变化,以表明该 track 已有可用的概念练习。
    • test_runner:一个boolean值,表示是否已实现 test runner(必填)。为true时,我们会让提交的解答经过我们的测试基础设施,并在网站上显示结果。网站还允许学生直接在在线编辑器里发起一次测试运行。
    • representer:一个boolean值,表示是否已实现 representer(必填)
    • analyzer:一个boolean值,表示是否已实现 analyzer(必填)
  • files:练习中所用文件位置的模式,相对于该练习的目录。(可选)
    • solution:存根实现文件的模式(可选)
    • test:测试文件的模式(可选)
    • example:示例实现文件的模式(可选)
    • exemplar:范例实现文件的模式(可选)
    • editor:额外的只读编辑器文件模式(可选)
  • test_runner:描述该 track 的 test runner 的对象(如果有):(当status.test_runner为true时必填)
    • average_run_time:test runner 平均运行秒数的整数number值(例如4)(当status.test_runner为true时必填)
  • approaches:包含该 track 各 approach 元数据的对象:(当该 track 有任何 approach 时必填)
    • snippet_extension:用于代码片段文件扩展名的字符串值(例如rb)(当该 track 有任何 approach 时必填)

文件

该键用于指定整个 track 的文件位置。有了它,维护者不必再手动在每个练习的config.json文件中设置files键,configlet 可以依据这些 track 级模式自动填充它。

files对象中定义的文件模式支持以下占位符:

  • %{kebab_slug}:kebab-case形式的练习 slug(例如bit-manipulation)
  • %{snake_slug}:snake_case形式的练习 slug(例如bit_manipulation)
  • %{camel_slug}:camelCase形式的练习 slug(例如bitManipulation)
  • %{pascal_slug}:PascalCase形式的练习 slug(例如BitManipulation)

我们之后会为 configlet 增加支持,用这些模式填充练习的.meta/config.json文件中的files键。

示例

{
  "language": "C#",
  "slug": "csharp",
  "active": true,
  "status": {
    "concept_exercises": true,
    "test_runner": true,
    "representer": false,
    "analyzer": false
  },
  "blurb": "C# is a modern, object-oriented language with lots of great features, such as type-inference and async/await. The tooling is excellent, and there is extensive, well-written documentation.",
  "version": 3,
  "online_editor": {
    "indent_style": "space",
    "indent_size": 4,
    "highlightjs_language": "csharp"
  },
  "test_runner": {
    "average_run_time": 2
  },
  "files": {
    "solution": [
      "%{pascal_slug}.cs"
    ],
    "test": [
      "%{pascal_slug}Tests.cs"
    ],
    "example": [
      ".meta/Example.cs"
    ],
    "exemplar": [
      ".meta/Exemplar.cs"
    ]
  }
}

练习

顶层exercises键是一个对象,可能包含三个键:

  • concept:这是一个数组,列出该 track 的概念练习
  • practice:这是一个数组,列出该 track 的实践练习
  • foregone:这是一个数组,列出该 track 不会实现的练习的 slug

概念练习

每个概念练习都是exercises.concept数组中的一个条目。 网站上练习的顺序与本文件中列出的顺序一致,而且应当与通常的解题顺序相符。 概念练习由以下字段组成:

  • uuid:唯一标识该练习的 V4 UUID。该 UUID 在同一 track 内以及所有 track 之间都必须唯一,且绝不能更改
  • slug:练习的 slug,一个全小写的 kebab-case 字符串。该 slug 在同一 track 内所有概念练习和实践练习的 slug 中必须唯一。长度必须 <= 255。
  • name:练习的名称。长度必须 <= 255。
  • concepts:该概念练习所教授的概念 slug 数组
  • prerequisites:学生开始该练习之前必须已解锁的概念 slug 数组
  • status(可选):练习的状态,取值为"wip"、"beta"、"active"或"deprecated"之一;未指定时默认为"active"
    • wip:尚未完成、还不适合公开的练习。带有此标记的练习不会在界面上显示给学生,也不参与解锁逻辑。它们可能会对维护者显示。
    • beta:表示这是新上线、我们希望获得反馈的活跃练习。我们会在网站上给这些练习显示 beta 标签,并附上“请给我们反馈”的行动号召。
    • active:活跃练习的正常状态
    • deprecated:不再向尚未开始这些练习的学生显示的练习(现阶段不可用)。更多信息见已弃用的练习。

示例

{
  "exercises": {
    "concept": [
      {
        "slug": "cars-assemble",
        "name": "Cars, Assemble!",
        "uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
        "concepts": [
          "if-statements",
          "numbers"
        ],
        "prerequisites": [
          "basics"
        ]
      },
      ...
    ]
  }
}

开发中的示例

{
  "exercises": {
    "concept": [
      {
        "slug": "cars-assemble",
        "name": "Cars, Assemble!",
        "uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
        "concepts": [
          "if-statements",
          "numbers"
        ],
        "prerequisites": [
          "basics"
        ],
        "status": "wip"
      },
      ...
    ]
  }
}

实践练习

每个实践练习都是exercises.practice数组中的一个条目。实践练习由以下字段组成:

  • uuid:唯一标识该练习的 V4 UUID。该 UUID 在同一 track 内以及所有 track 之间都必须唯一,且绝不能更改
  • slug:练习的 slug,一个全小写的 kebab-case 字符串。该 slug 在同一 track 内所有概念练习和实践练习的 slug 中必须唯一。长度必须 <= 255。
  • name:练习的名称。长度必须 <= 255。
  • practices:该练习帮助学生练习的概念 slug 数组
  • prerequisites:学生开始该练习之前必须已解锁的概念 slug 数组
  • difficulty:表示练习难度的数字。该数字必须在 1(最简单)到 10(最难)之间。网站对难度的解读如下:
    • 1、2、3:简单
    • 4、5、6、7:中等
    • 8、9、10:困难
  • status(可选):练习的状态,取值为"wip"、"beta"、"active"或"deprecated"之一;未指定时默认为"active"
    • wip:尚未完成、还不适合公开的练习。带有此标记的练习不会在界面上显示给学生,也不参与解锁逻辑。它们可能会对维护者显示。
    • beta:表示这是新上线、我们希望获得反馈的活跃练习。我们会在网站上给这些练习显示 beta 标签,并附上“请给我们反馈”的行动号召
    • active:活跃练习的正常状态
    • deprecated:不再向尚未开始这些练习的学生显示的练习(现阶段不可用)。

网站上实践练习的“推荐顺序”与practice数组中练习的顺序一致。

示例

{
  "exercises": {
    "practice": [
      {
        "slug": "leap",
        "name": "Leap",
        "uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
        "practices": [
          "if-statements",
          "numbers",
          "operator-precedence"
        ],
        "prerequisites": [
          "if-statements",
          "numbers"
        ],
        "difficulty": 1
      },
      ...
    ]
  }
}

beta 示例

{
  "exercises": {
    "practice": [
      {
        "slug": "leap",
        "name": "Leap",
        "uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
        "practices": [
          "if-statements",
          "numbers",
          "operator-precedence"
        ],
        "prerequisites": [
          "if-statements",
          "numbers"
        ],
        "difficulty": 1,
        "status": "beta"
      },
      ...
    ]
  }
}

不再实现的练习

如果某个 track 知道自己不想实现 Problem Specifications 仓库中定义的某个练习,可以把该练习的 slug 添加到exercises.foregone键中。configlet 在输出该 track 未实现的练习时会忽略已放弃的练习。

某个 track 可能不想实现某个练习,原因可以是:

  • 该练习无法用这门语言合理实现。例如,lens-person 练习要求这门语言支持 lenses。
  • 该练习的主题不适合这门语言。例如,对某些高级语言来说,一个底层的位操作练习可能没有意义。

示例

{
  "exercises": {
    "foregone": [
      "lens-person"
    ]
  }
}

概念

每个概念都是顶层concepts数组中的一个条目。概念由以下字段组成:

  • uuid:唯一标识该概念的 V4 UUID。该 UUID 在同一 track 内以及所有 track 之间都必须唯一,且绝不能更改
  • slug:概念的 slug,一个全小写的 kebab-case 字符串。该 slug 在同一 track 内所有概念中必须唯一。长度必须 <= 255。
  • name:概念的名称。长度必须 <= 255。
  • tags:指定提交在何种条件下与某个 approach 关联。(可选)
    • all:提交上必须全部出现的标签数组(可选,除非any没有元素)
    • any:提交上至少出现其中一个的标签数组(可选,除非all没有元素)
    • not:提交上不得出现其中任何一个的标签(可选)

示例

{
  "concepts": [
    {
      "uuid": "b9a421b2-c5ff-4213-bd6d-b886da31ea0d",
      "slug": "numbers",
      "name": "Numbers",
      "tags": {
        "all": [
          "concept:number"
        ]
      }
    }
  ]
}

主要特性

一门语言的主要特性简要描述这门语言最重要的特点是什么。 它们意在向潜在学生推介这门语言更有趣的特性。 标题应尽量少用技术术语,要记得学生在学习这门语言之前,可能并不了解这门语言特有术语的含义。

主要特性在顶层key_features字段中指定,该字段是一个对象数组,对象包含以下字段:

  • title:主要特性的简洁标题。长度必须 <= 25。不支持 Markdown。
  • content:主要特性的描述。长度必须 <= 100。不支持 Markdown。
  • icon:要为该特性显示的图标。你可以选择一个自己认为合适的图标,不必在意它的名称。可使用以下图标:
    • community
    • concurrency
    • cross-platform
    • documentation
    • dynamically-typed
    • easy
    • embeddable
    • evolving
    • expressive
    • extensible
    • fast
    • fun
    • functional
    • garbage-collected
    • general-purpose
    • homoiconic
    • immutable
    • interactive
    • interop
    • multi-paradigm
    • portable
    • powerful
    • productive
    • safe
    • scientific
    • small
    • stable
    • statically-typed
    • tooling
    • web
    • widely-used

你可以在主要特性图标一节查看这些图标的视觉外观。

必须恰好指定 6 个主要特性。

示例

{
  "key_features": [
    {
      "title": "Fault-tolerant",
      "content": "Elixir runs on the Erlang VM, known for running low-latency, distributed and fault-tolerant systems.",
      "icon": "safe"
    },
    ...
  ],
}

标签

可以为 track 添加标签,这样就可以按特定的标签组合搜索 track。

track 应根据其语言的一般用途来选择标签。例如,想象一个学生正在想:“我想做机器学习,该选哪门语言?”,或者“我想学函数式编程,该选哪门语言?”。如果你的语言很合适,就给它加上那个标签。如果你的语言支持一些函数式思想,但很少用到,或者只有少数人用它做机器学习,而且并不常见,那就不要加这些标签。

标签在顶层tags字段中指定,该字段是一个字符串数组。可使用以下标签(按类别分组):

范式

  • paradigm/array:该语言是数组编程语言
  • paradigm/declarative:该语言支持声明式编程风格
  • paradigm/functional:该语言支持函数式编程风格
  • paradigm/imperative:该语言支持命令式编程风格
  • paradigm/logic:该语言支持基于逻辑的编程风格
  • paradigm/object_oriented:该语言支持面向对象编程风格
  • paradigm/procedural:该语言支持过程式编程风格
  • paradigm/stack-oriented:该语言支持面向堆栈的编程风格

类型

  • typing/static:该语言使用静态类型
  • typing/gradual:该语言使用渐进类型
  • typing/dynamic:该语言使用动态类型
  • typing/strong:该语言使用强类型
  • typing/weak:该语言使用弱类型

执行方式

  • execution_mode/compiled:代码先经过编译再执行
  • execution_mode/interpreted:代码直接解释执行

平台

  • platform/windows:在 Windows 上运行
  • platform/mac:在 Mac 上运行
  • platform/linux:在 Linux 上运行
  • platform/ios:在 iOS 上运行
  • platform/android:在 Android 上运行
  • platform/web:在浏览器中运行

运行时

  • runtime/standalone_executable:作为独立可执行文件运行
  • runtime/language_specific:在语言专用的运行时上运行
  • runtime/clr:在 Common Language Runtime (.NET) 上运行
  • runtime/jvm:在 JVM (Java) 上运行
  • runtime/beam:在 BEAM (Erlang) 上运行
  • runtime/wasmtime:在 Wasmtime (WebAssembly) 上运行

用途

  • used_for/artificial_intelligence:人工智能
  • used_for/backends:后端
  • used_for/cross_platform_development:跨平台开发
  • used_for/embedded_systems:嵌入式系统
  • used_for/financial_systems:金融系统
  • used_for/frontends:前端
  • used_for/games:游戏
  • used_for/guis:图形用户界面
  • used_for/mobile:移动端
  • used_for/robotics:机器人
  • used_for/scientific_calculations:科学计算
  • used_for/scripts:脚本
  • used_for/web_development:Web 开发

注意,同一个类别中包含多个标签是完全可以的。

示例

{
  "tags": [
    "paradigm/declarative",
    "paradigm/functional",
    "paradigm/object_oriented",
    "platform/linux",
    "platform/windows",
    "runtime/jvm"
  ]
}

示例

下面是一个有效的config.json文件可能长什么样的示例:

{
  "language": "C#",
  "slug": "csharp",
  "active": true,
  "status": {
    "concept_exercises": true,
    "test_runner": true,
    "representer": false,
    "analyzer": false
  },
  "blurb": "C# is a modern, object-oriented language with lots of great features, such as type-inference and async/await. The tooling is excellent, and there is extensive, well-written documentation.",
  "version": 3,
  "online_editor": {
    "indent_style": "space",
    "indent_size": 4,
    "highlightjs_language": "csharp"
  },
  "test_runner": {
    "average_run_time": 2
  },
  "files": {
    "solution": [
      "%{pascal_slug}.cs"
    ],
    "test": [
      "%{pascal_slug}Tests.cs"
    ],
    "example": [
      ".meta/Example.cs"
    ],
    "exemplar": [
      ".meta/Exemplar.cs"
    ]
  },
  "exercises": {
    "concept": [
      {
        "slug": "lucians-luscious-lasagna",
        "name": "Lucian's Luscious Lasagna",
        "uuid": "7d358894-4fbd-4c91-b49f-d68f1c5aa6bc",
        "concepts": [
          "basics"
        ],
        "prerequisites": []
      },
      {
        "slug": "cars-assemble",
        "name": "Cars, Assemble!",
        "uuid": "93fbc7cf-3a7e-4450-ad22-e30129c36bb9",
        "concepts": [
          "if-statements",
          "numbers"
        ],
        "prerequisites": [
          "basics"
        ],
        "status": "wip"
      }
    ],
    "practice": [
      {
        "slug": "hello-world",
        "name": "Hello, World!",
        "uuid": "6c88f46b-5acb-4fae-a6ec-b48ae3f8168f",
        "practices": [
          "strings"
        ],
        "prerequisites": [
          "basics"
        ],
        "difficulty": 1
      },
      {
        "slug": "leap",
        "name": "Leap",
        "uuid": "8ba15933-29a2-49b1-a9ce-70474bad3007",
        "practices": [
          "if-statements",
          "numbers",
          "operator-precedence"
        ],
        "prerequisites": [
          "if-statements",
          "numbers"
        ],
        "difficulty": 2,
        "status": "beta"
      }
    ]
  },
  "concepts": [
    {
      "uuid": "2eb4a463-355f-46ef-ac55-a75ec5afdf86",
      "slug": "basics",
      "name": "Basics"
    },
    {
      "uuid": "4466e33e-dcd2-4b1f-9d9d-2c4315bf5188",
      "slug": "if-statements",
      "name": "If Statements"
    },
    {
      "uuid": "b9a421b2-c5ff-4213-bd6d-b886da31ea0d",
      "slug": "numbers",
      "name": "Numbers"
    },
    {
      "uuid": "7a86561d-173b-45c0-a53c-1ffd7b9ff259",
      "slug": "strings",
      "name": "Strings"
    }
  ],
  "key_features": [
    {
      "title": "Modern",
      "content": "C# is a modern, fast-evolving language.",
      "icon": "expressive"
    },
    {
      "title": "Cross-platform",
      "content": "C# runs on almost any platform and chipset.",
      "icon": "cross-platform"
    },
    {
      "title": "Multi-paradigm",
      "content": "C# is primarily an object-oriented language, but also has lots of functional features.",
      "icon": "multi-paradigm"
    },
    {
      "title": "General purpose",
      "content": "C# can be used for a wide variety of workloads, like websites, console applications, and even games.",
      "icon": "general-purpose"
    },
    {
      "title": "Tooling",
      "content": "C# has excellent tooling, with linting and advanced refactoring options built-in.",
      "icon": "tooling"
    },
    {
      "title": "Documentation",
      "content": "Documentation is excellent and exhaustive, making it easy to get started with C#.",
      "icon": "documentation"
    }
  ],
  "tags": [
    "paradigm/declarative",
    "paradigm/functional",
    "paradigm/object_oriented",
    "platform/linux",
    "platform/windows",
    "runtime/jvm"
  ]
}