config.json


O ficheiro config.json descreve a configuração do percurso. Contém informações essenciais, como os exercícios e os conceitos do percurso.

Metadados

As seguintes propriedades de nível superior contêm metadados gerais sobre o percurso:

  • language: a linguagem do percurso (por exemplo, "C#"). O seu comprimento tem de ser <= 255. (obrigatório)
  • slug: a linguagem do percurso como uma string em minúsculas e em kebab-case (por exemplo, "csharp"). O seu comprimento tem de ser <= 255. (obrigatório)
  • active: um valor boolean que indica se o percurso está ativo (ou seja, se os estudantes podem aderir ao percurso no site) (obrigatório)
  • blurb: uma breve descrição da linguagem. O seu comprimento tem de ser <= 400. (obrigatório)
  • version: a versão do ficheiro config.json (atualmente fixada em 3) (obrigatório)
  • online_editor: um objeto que descreve as configurações usadas no editor online: (obrigatório)
    • indent_style: "space" ou "tab" (obrigatório)
    • indent_size: o tamanho da indentação, como número inteiro (por exemplo, 4) (obrigatório)
    • highlightjs_language: o identificador de linguagem para o Highlight.js (vê a lista completa de identificadores) (opcional)
  • status: um objeto que descreve que funcionalidades da v3 devem ser ativadas: (obrigatório)
    • concept_exercises: um valor boolean que indica se foram criados exercícios de conceito (obrigatório). Quando é true, a interface do site do Exercism muda para indicar que o percurso tem exercícios de conceito disponíveis.
    • test_runner: um valor boolean que indica se foi implementado um test runner (obrigatório). Quando é true, submetemos as soluções à nossa infraestrutura de testes e mostramos os resultados no site. O site também permite que os estudantes iniciem uma execução de testes a partir do editor online.
    • representer: um valor boolean que indica se foi implementado um representer (obrigatório)
    • analyzer: um valor boolean que indica se foi implementado um analyzer (obrigatório)
  • files: os padrões para as localizações dos ficheiros usados num exercício, relativos ao diretório do exercício. (opcional)
    • solution: padrão dos ficheiros de implementação stub (opcional)
    • test: padrão dos ficheiros de teste (opcional)
    • example: padrão dos ficheiros de implementação de exemplo (opcional)
    • exemplar: padrão dos ficheiros de implementação exemplar (opcional)
    • editor: padrões adicionais para os ficheiros do editor apenas de leitura (opcional)
  • test_runner: um objeto que descreve o test runner do percurso (se existir): (obrigatório se status.test_runner for true)
    • average_run_time: um valor number inteiro para o número de segundos que o test runner demora, em média, a correr (por exemplo, 4) (obrigatório se status.test_runner for true)
  • approaches: um objeto com metadados sobre as abordagens do percurso: (obrigatório se o percurso tiver alguma abordagem)
    • snippet_extension: um valor de string usado para a extensão do ficheiro de fragmento (por exemplo, rb) (obrigatório se o percurso tiver alguma abordagem)

Ficheiros

Esta chave é usada para especificar as localizações dos ficheiros à escala do percurso. Em vez de os maintainers terem de definir manualmente a chave files nos ficheiros config.json dos exercícios, o configlet pode preenchê-la automaticamente com estes padrões à escala do percurso.

Os padrões de ficheiros definidos no objeto files suportam os seguintes marcadores:

  • %{kebab_slug}: o slug do exercício em kebab-case (por exemplo, bit-manipulation)
  • %{snake_slug}: o slug do exercício em snake_case (por exemplo, bit_manipulation)
  • %{camel_slug}: o slug do exercício em camelCase (por exemplo, bitManipulation)
  • %{pascal_slug}: o slug do exercício em PascalCase (por exemplo, BitManipulation)

Será adicionado suporte ao configlet para usar estes padrões para preencher a chave files no ficheiro .meta/config.json de um exercício.

Exemplo

{
  "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"
    ]
  }
}

Exercícios

A chave de nível superior exercises é um objeto com três chaves possíveis:

  • concept: um array que lista os exercícios de conceito do percurso
  • practice: um array que lista os exercícios de prática do percurso
  • foregone: um array que lista os slugs dos exercícios que o percurso não vai implementar

Exercícios de conceito

Cada exercício de conceito é uma entrada no array exercises.concept. No site, os exercícios aparecem pela ordem em que estão listados neste ficheiro e devem corresponder à ordem típica em que devem ser resolvidos. Os seguintes campos compõem um exercício de conceito:

  • uuid: um UUID V4 que identifica o exercício de forma única. O UUID tem de ser único tanto dentro do percurso como em todos os percursos, e nunca pode mudar
  • slug: o slug do exercício, que é uma string em minúsculas e em kebab-case. O slug tem de ser único entre todos os slugs de exercícios de conceito e de prática do percurso. O seu comprimento tem de ser <= 255.
  • name: o nome do exercício. O seu comprimento tem de ser <= 255.
  • concepts: um array de slugs de conceitos que são ensinados por este exercício de conceito
  • prerequisites: um array de slugs de conceitos que têm de ser desbloqueados antes de um estudante poder começar este exercício
  • status (opcional): o estado do exercício, que é um de "wip", "beta", "active" ou "deprecated"; assume "active" por predefinição se não for especificado
    • wip: um exercício em desenvolvimento, ainda não pronto para uso público. Os exercícios com esta etiqueta não são mostrados aos estudantes na interface nem entram na lógica de desbloqueio. Podem aparecer para os maintainers.
    • beta: designa exercícios ativos que são novos e sobre os quais gostaríamos de receber feedback. Mostramos uma etiqueta beta no site para estes exercícios, com um apelo à ação "Dá-nos o teu feedback."
    • active: o estado normal dos exercícios ativos
    • deprecated: exercícios que já não são mostrados aos estudantes que ainda não os começaram (já não podem ser usados nesta fase). Vê os Exercícios obsoletos para mais informações.

Exemplo

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

Exemplo de um exercício em desenvolvimento

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

Exercícios de prática

Cada exercício de prática é uma entrada no array exercises.practice. Os seguintes campos compõem um exercício de prática:

  • uuid: um UUID V4 que identifica o exercício de forma única. O UUID tem de ser único tanto dentro do percurso como em todos os percursos, e nunca pode mudar
  • slug: o slug do exercício, que é uma string em minúsculas e em kebab-case. O slug tem de ser único entre todos os slugs de exercícios de conceito e de prática do percurso. O seu comprimento tem de ser <= 255.
  • name: o nome do exercício. O seu comprimento tem de ser <= 255.
  • practices: um array de slugs de conceitos que o exercício ajuda os estudantes a praticar
  • prerequisites: um array de slugs de conceitos que têm de ser desbloqueados antes de um estudante poder começar o exercício
  • difficulty: um número que indica a dificuldade do exercício. O número tem de estar no intervalo de 1 (mais fácil) a 10 (mais difícil). O site interpreta a dificuldade da seguinte forma:
    • 1,2,3: fácil
    • 4,5,6,7: média
    • 8,9,10: difícil
  • status (opcional): o estado do exercício, que é "wip", "beta", "active" ou "deprecated"; assume "active" por predefinição se não for especificado
    • wip: um exercício em desenvolvimento, ainda não pronto para uso público. Os exercícios com esta etiqueta não são mostrados aos estudantes na interface nem entram na lógica de desbloqueio. Podem aparecer para os maintainers.
    • beta: designa exercícios ativos que são novos e sobre os quais gostaríamos de receber feedback. Mostramos uma etiqueta beta no site para estes exercícios, com um apelo à ação "Dá-nos o teu feedback"
    • active: o estado normal dos exercícios ativos
    • deprecated: exercícios que já não são mostrados aos estudantes que ainda não os começaram (já não podem ser usados nesta fase).

A "Ordem recomendada" dos exercícios de prática no site corresponde à ordem dos exercícios no array practice.

Exemplo

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

Exemplo de 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"
      },
      ...
    ]
  }
}

Exercícios preteridos

Se um percurso sabe que não quer implementar um exercício definido no repositório Problem Specifications, o slug desse exercício pode ser adicionado à chave exercises.foregone. O configlet ignora os exercícios preteridos quando apresenta os exercícios não implementados do percurso.

Algumas razões pelas quais um percurso pode não querer implementar um exercício:

  • O exercício não pode razoavelmente ser implementado na linguagem. Por exemplo, o exercício lens-person exige que a linguagem suporte lentes.
  • O tema do exercício não se adequa à linguagem. Por exemplo, em algumas linguagens de alto nível, um exercício de manipulação de bits de baixo nível pode não fazer sentido.

Exemplo

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

Conceitos

Cada conceito é uma entrada no array de nível superior concepts. Os seguintes campos compõem um conceito:

  • uuid: um UUID V4 que identifica o conceito de forma única. O UUID tem de ser único tanto dentro do percurso como em todos os percursos, e nunca pode mudar
  • slug: o slug do conceito, que é uma string em minúsculas e em kebab-case. O slug tem de ser único entre todos os conceitos do percurso. O seu comprimento tem de ser <= 255.
  • name: o nome do conceito. O seu comprimento tem de ser <= 255.
  • tags: especifica as condições em que uma submissão é associada a uma abordagem. (opcional)
    • all: um array de etiquetas que têm de estar todas presentes numa submissão (opcional, exceto se any não tiver elementos)
    • any: um array de etiquetas das quais pelo menos uma tem de estar presente numa submissão (opcional, exceto se all não tiver elementos)
    • not: nenhuma das etiquetas pode estar presente numa submissão (opcional)

Exemplo

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

Características principais

As características principais da linguagem descrevem de forma sucinta quais são as funcionalidades mais importantes da linguagem. Têm como objetivo dar a conhecer as funcionalidades mais interessantes de uma linguagem a potenciais estudantes. Os títulos devem procurar usar o mínimo possível de jargão técnico, tendo em conta que os estudantes podem não saber o que significa o jargão específico de uma linguagem antes de a aprenderem.

As características principais são especificadas no campo de nível superior key_features, definido como um array de objetos com os seguintes campos:

  • title: um cabeçalho conciso para a característica principal. O seu comprimento tem de ser <= 25. O Markdown não é suportado.
  • content: uma descrição da característica principal. O seu comprimento tem de ser <= 100. O Markdown não é suportado.
  • icon: o ícone a mostrar para a característica. Podes escolher o ícone que achares adequado, independentemente do seu nome. Podem ser usados os seguintes ícones:
    • 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

Podes ver o aspeto visual destes ícones na secção dos ícones das características principais.

Têm de ser especificadas exatamente 6 características principais.

Exemplo

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

Etiquetas

Os percursos podem ser anotados com etiquetas, o que permite procurar percursos com uma determinada combinação de etiquetas.

Um percurso deve escolher as suas etiquetas com base no uso geral da sua linguagem. Por exemplo, imagina um estudante a pensar: "Gostava de fazer aprendizagem automática, que linguagem devo escolher?", ou "Gostava de aprender programação funcional, que linguagem devo escolher?". Se a tua linguagem for uma boa candidata, atribui-lhe essa etiqueta. Se a tua linguagem suportar algumas ideias funcionais mas raramente forem usadas, ou se poucas pessoas fizerem aprendizagem automática com ela e isso for raro, então não apliques essas etiquetas.

As etiquetas são especificadas no campo de nível superior tags, definido como um array de strings. Podem ser usadas as seguintes etiquetas (agrupadas por categoria):

Paradigmas

  • paradigm/array: a linguagem é uma linguagem de programação de arrays
  • paradigm/declarative: a linguagem suporta um estilo de programação declarativo
  • paradigm/functional: a linguagem suporta um estilo de programação funcional
  • paradigm/imperative: a linguagem suporta um estilo de programação imperativo
  • paradigm/logic: a linguagem suporta um estilo de programação baseado em lógica
  • paradigm/object_oriented: a linguagem suporta um estilo de programação orientado a objetos
  • paradigm/procedural: a linguagem suporta um estilo de programação procedural
  • paradigm/stack-oriented: a linguagem suporta um estilo de programação orientado à pilha

Tipagem

  • typing/static: a linguagem usa tipagem estática
  • typing/gradual: a linguagem usa tipagem gradual
  • typing/dynamic: a linguagem usa tipagem dinâmica
  • typing/strong: a linguagem usa tipagem forte
  • typing/weak: a linguagem usa tipagem fraca

Modo de execução

  • execution_mode/compiled: o código é primeiro compilado antes de ser executado
  • execution_mode/interpreted: o código é interpretado diretamente

Plataforma

  • platform/windows: corre no Windows
  • platform/mac: corre no Mac
  • platform/linux: corre no Linux
  • platform/ios: corre no iOS
  • platform/android: corre no Android
  • platform/web: corre no navegador

Runtime

  • runtime/standalone_executable: corre como executável autónomo
  • runtime/language_specific: corre num runtime específico da linguagem
  • runtime/clr: corre no Common Language Runtime (.NET)
  • runtime/jvm: corre na JVM (Java)
  • runtime/beam: corre no BEAM (Erlang)
  • runtime/wasmtime: corre no Wasmtime (WebAssembly)

Usado para

  • used_for/artificial_intelligence: Inteligência artificial
  • used_for/backends: Backends
  • used_for/cross_platform_development: Desenvolvimento multiplataforma
  • used_for/embedded_systems: Sistemas embebidos
  • used_for/financial_systems: Sistemas financeiros
  • used_for/frontends: Frontends
  • used_for/games: Jogos
  • used_for/guis: Interfaces gráficas
  • used_for/mobile: Dispositivos móveis
  • used_for/robotics: Robótica
  • used_for/scientific_calculations: Cálculos científicos
  • used_for/scripts: Scripts
  • used_for/web_development: Desenvolvimento web

Nota que não há problema nenhum em incluir várias etiquetas de uma só categoria.

Exemplo

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

Exemplo

Este é um exemplo do que pode ser um ficheiro config.json válido:

{
  "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"
  ]
}