-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Insight Documentation
An Insight is a short article covering a small, well-defined objective. It features metadata for analysis purposes and may also contain multiple-choice practice and revision questions. More on that later.
Here is an example insight, here's how it looks on Enki, and here is a generator that will help you create an insight.
Similar to all other content types, in the curriculum folder structure, we create insights using slugs for their name. Slugs must be unique across the whole curriculum.
An insight has some metadata that helps our systems organize and quantify the curriculum. It also helps us understand how well a user understands a given concept. Any metadata is supported, but there are a few that are required.
The metadata at the top of every insight file is parsed using YAML. It's a human-readable, markdown-format data transport language. The YAML section must have breaks ---
at the top and bottom to be parsed properly. Below are some of the properties of an insight and what they're used for.
This field should specify the Enki username of the user creating the insight.
The author is specified by the following line:
author: catalin
The category field is mandatory. It is used to indicate to the user the type of information they are presented with.
The possible categories are:
-
must-know
- the goal is to teach a core feature or fact of the topic or subtopic (e.g., a core feature of
JavaScript
) - a feature or fact should only be considered
must-know
if it's an important characteristic of the topic/language (in other words: it makes it special) - basic facts and features (expected and commonly found in other languages) should not be considered
must-know
- the goal is to teach a core feature or fact of the topic or subtopic (e.g., a core feature of
-
discussion
- the goal is to give the user an opportunity to discuss a topic
- Insights with the discussion category should end with some kind of open-ended question, formatted in a quote-block.
- In the Enki app, discussion insights will appear with an extra large button prompting the user to leave a comment.
-
feature
- the goal is to teach that something exists (a function, a method, etc..)
- the insight also need to explain briefly what it does / when you might use it
- it must be a non-trivial feature
- the title should be the name of the feature/function/method
-
best-practice
- This is to establish Best Practices
- the insight should explain briefly why this is considered a "good" habit
- it should not be black and white, as in "you should always do X", but rather as "you would want to do X under these circumstances"
- reviewers should not be too picky if they don't agree 100% with the recommendation (these types of insights will always sound a bit subjective)
-
tip
- This is to give time-saving information that nudges the learner in the right direction
-
how-to
- the goal is to teach one way of doing something (typically by combining multiple functions and features)
- the name of the insight should the name of what we want to teach to do (and NOT the name of the function or method used to do it), e.g., "Scrape the web with Node.js"
- to be interesting, the insights must be teaching a particularly good way of doing something (either a short way, an efficient way, an elegant way, or an idiomatic way)
-
pattern
- the goal is to teach a common pattern or topic-specific way of doing something
- the insight must explain briefly why this is commonly used
- the difference between
pattern
s andhow-to
s is sometimes subtle, but the presentation is typically different because apattern
insight should directly present a "pattern" (for the people who recognize to skip the rest of the insight), rather than presenting first a goal and then a way of achieving it - unlike
how-to
s,pattern
s are not necessarily a "good" way of doing something, just a common way (worth learning because you will probably encounter it in existing code and will need to understand it)
-
caveats
- the goal is to warn users about common bugs, gotchas and misconceptions, eg
NaN === NaN
returningfalse
in JavaScript.
- the goal is to warn users about common bugs, gotchas and misconceptions, eg
-
hack
- Similar to a tip, it can present a quick and/or simple trick to save time or improve productivity.
- For instance, a hacky way to generate dummy data for testing purposes or an unconventional and creative way of achieving something, like a cool animation in CSS.
-
coding
- It represents coding insights.
- These are insights that use coding playgrounds. Currently, only Python and JavaScript can have a playground.
- Coding insights have additional fields called setupCode and startingPoint. These are used to add explanations for a given coding task as well as give some starting code.
The setupCode looks like this:
setupCode:
startingPoint: |
# Welcome to the Python coding playground.
# Update the statement to output the first thing you'd log if you just landed on Mars!
print("That's one small step for man, one giant leap for Python!");
The category field should look like this:
category: best-practice
The Links field is where you can put additional resources. When a user bookmarks an insight, they are sent these links in an email to follow up on their learning. These links should:
- When possible, link to canonical documentation
- Link to a walkthrough or overview article that goes into depth
- Link to a free course or book that covers the information in the insight
To attach links, the following format must be used:
links:
- '[facebook.github.io](https://facebook.github.io/react/tips/false-in-jsx.html){website}'
# - >-
# [short-name](full-url){resource-type}
The following options are available for resource-type
:
key | resource-type | emoji |
---|---|---|
website |
Catch-all for any resource not otherwise specified | π |
video |
Video resource exploring the topic | π₯ |
documentation |
Official docs, including MDN | π |
article |
An article that discusses the application of a subject (i.e. tutorial) | π |
discussion |
An online thread related to the subject (StackOverflow) | π¬ |
In the Enki app, these links will appear at the end of the insight under Learn More
Tags specify what general area of content the insight belongs in, smaller than the course level. functions
is a good example, regex
is another.
For example:
tags:
- strings
Titles are Mandatory.
The title should indicate to the user what the Article and *Questions cover.
It must be between 4
and 120
characters long. The title can use code blocks
inside it.
The title is specified after the YAML field, preceded with an #
Note: Keep in mind that the title of the insight is also shown with the Revision Question. That being said, you should take care when writing titles such that the title doesnβt directly give away the answer.
Content should be short and SEXI.
Short means that they should cover the smallest possible idea in a non-exhaustive way. Typically less than 100 words, plus an image or code example when possible. Brevity is key because these aren't meant to be a wall of text. An insight is meant to cover only enough for the user to correctly answer the related practice question.
SEXI is an acronym for how explanations should be structured. This is a general guideline, not a rule.
- S State: State or define the concept. "Functions are a way to encapsulate and reuse code."
- E Elaborate: Explain in more detail or qualify the concept. "Functions take an input and produce an output, and can be composed together to control the flow of a program."
-
X Exemplify: Give an example of when you might use this, establish context. "Functions are useful when you need to perform a repeated action, and you want to give that action a name." You can also visualize the abstract form here:
function ([arg1, arg2, args...]) {[function body]}
-
I Illustrate: Show an example that is not abstract.
function add(a,b) { return a + b }
Content is written in markdown. That means that within an insight one can use:
- Code blocks (both inline and multiline)
- Footnotes
- Images
- Tables
The maximum permitted column width of the content is 44
chars long. That means no words (or lines within code snippets) should exceed 44
chars.
If a line of your code is beyond 44
characters, please add a line break at a readable point and continue on the next line with a two-space indent to indicate continuation. This ensures the insight will be readable on a mobile screen.
The content of the insight is specified like:
---
## Content
The usage of the `false` keyword in **JSX** and implicitly **React** is worth mentioning because of its volatile behavior.
First of all, `false` is widely used to specify that a **React** element has no child:
ReactDOM.render(<div>{false}</div>,
myNode);
Every new idea in a workout should be accompanied with practice and revision questions.
Both question types have the same format:
Question text?
???
- answer 1
- answer 2
- answer 3
- answer 4
???
are used as placeholders for answers.
Answers correspond with ???
. If you have only one ???
, only the top answer (answer 1
) is correct.
Here is a sample question from Git:
Log 5 commits:
git ??? ??? ???
- `log` First correct answer
- `-n` Second correct answer
- `5` Third correct answer
- `--stat` This and the rest are wrong answers
- `--show`
- `--commits`
- `all`
- `just`
- `show`
- `status`
β Although answers are written linearly, they are randomized within the app.
Here is how the above question looks within the app:
Practice questions are questions presented with the insight. All practice questions should take this into account- you can reference the text. Practice questions should include the most authentic possible practice opportunity- check the objective you're trying to meet and try to create a fill-in-the-blanks challenge that includes code or terminal commands. You can ask them to choose the correct flags to append to a terminal program, for instance, because they can read what the flags are in the insight and pick the right ones.
Practice questions are formatted like this:
## Practice
Print "hello world" to the console:
`???.???(???)`
- `console`
- `log`
- `"hello world"`
- `print`
- `write`
Revision questions are assessment questions. They are presented at a later point. Ensure they cover the same information as the practice question and make sure it's not about trivia in the insight. They're used for placement tests and revision workouts. Try to make these questions require as much critical thought as possible- the user should figure something out, not just be relied upon to recall details (unless the objective is to memorize the details). So, for example, don't include "remembering obscure terminal flags" in this kind of question. Instead, focus on what a person can be expected to recall before they've had their coffee.
Revision questions are formatted like:
## Revision
Print "hello world" to the console:
`???.???(???)`
- `console`
- `log`
- `"hello world"`
- `print`
- `write`
Quiz Questions are trivia or gotcha questions requiring either encyclopedic knowledge or the ability to evaluate a deceptive expression in code. Answering them correctly should make you feel smart, and answering them incorrectly should make you feel like you want to review the content.
The headline is presented out of the context of the question, and should be designed to "nerd-snipe" the reader. The headline is intended to feel like a challenge. The question is the actual question to be presented to the reader once the reader "accepts the challenge" of the headline.
Answers are always multiple-choice, as these questions are often presented in interaction mediums that can only accept a single input (like the bot, or through email). You must have a minimum of four potential answers.
---
## Quiz
### How well do you understand the `++` operator?
x = 1;
x++;
// what is the value of x?
* 2
* 3
* 4
* 1
- Type in the gap
- Fill in the gap
- Multiple choice, you have a set of answers, and you have to select some of them to fill in the gaps.
- Instead of selecting an answer, the user will now have to type the correct answer.
Example type-in-the-gap:
Complete this expression to check that the variable `word` does not appear in `sentence`:
```python
word = 'list'
sentence = 'we know about numbers, strings and booleans'
??? word ??? in sentence:
print("Let's learn some more data types!")
```
- `if`
- `not`
- `is`
- `elif`
- `else`
Here's how it looks within the app:
And they can have one of these two contexts:
- standalone
- relative
The context field will decide whether the question can be served to a user without the insight's context.
- That question can't be answered without the insight's context.
- The question can be answered without knowing the insight's context.
Both practice and revision questions must be mentioned in the metadata for the associated insight:
practiceQuestion:
formats:
- fill-in-the-gap
- type-in-the-gap
context: relative
revisionQuestion:
formats:
- fill-in-the-gap
context: standalone
Note that a question can have either format or both. But only one context.
If it has both, the type-in-the-gap will be the preferred way.
The most obvious choice is for questions that only have gaps inside a code block:
How would you print "Hello World"?
```py
???(???)
```
- print
- "Hello World"
You should make sure that the question specifies everything that needs to be filled in the text. Users won't be able to see possible answers; they will only see gaps.
Here's when not to use type-in-the-gap
Complete the print statement:
```py
???(???)
```
- print
- "Hello World"
This is because users can't know that inside the print statement, they should use "Hello World".
In these cases, to use type-in-the-gap, it's appropriate to modify the question's text and answers so that all the information needed to answer the question is present.
Another good example of type-in-the-gap is whenever we ask for a specific language keyword. Something that is unique, and there is no alternative to it.
To log to the console in JavaScript you should use the ??? method.
- console.log
- console.print
# Subjective questions where either answer could technically be correct. (we wouldn't have two valid answers in a question; this is purely an example to showcase the detriments of **type-in-the-gap**)
Python is close to the ??? language.
- English
- C
# Example where 1, one, One, One., should all be correct, so fill-in-the-gap is best
In Airtable, how many primary fields can you have?
???
- One.
- Two.
- Five.
- None.
# If the question is phrased "which of the following", then it needs fill in the gap to show those options:
Which of the following commands will be a service-like way to stop `iptables`?
???
- `service iptables stop`
- `iptables -R DROP`
- `stop iptables.service`
- `disable iptables.service`
Start by looking at the question. Can you answer it without needing context from the insight? Then yes.
By context, we mean tables, variable names, file names, and anything that was shown in the insight and isn't shown in the question.
We don't mean concepts that are taught, like how to make a loop. We expect users to know that.
// relative
Using the same table as in the previous insight, return all the records:
```sql
SELECT ???
FROM ???
```
- *
- table-name
// standalone
Return all the records from the `students` table:
```sql
SELECT ???
FROM ???
```
- *
- students
Footnotes are used to elaborate on some information that isnβt necessarily of interest to all users or necessarily relevant to the main topic of the insight but is still useful to indicate the source of the relevant information.
Insert footnotes at the end your insights:
---
## Footnotes
[1:LSB]
**LSB** in the `lsb_release` command stands for *Linux Standard Base*.
You can include any standard markdown within the footnote
You can insert a link to the footnote directly in your content like so:
To print information about your linux distro use `lsb_release`[1]
Glossary entries are global footnotes. In the app, they are displayed exactly as a footnote. They are meant to help users remember heavily used definitions. Check Glossary Documentation for more information.
To add a glossary reference to an insight, use markdown syntax for links, while the links point to enki.com/glossary/path/to/entry
or https://enki.com/glossary/path/to/entry
. Read more at Glossary Documentation on how to determine the right path.
---
## Content
The four principles of [object-oriented programming](https://enki.com/glossary/general/object-oriented-programming) are encapsulation, abstraction, inheritance, and polymorphism.
The topic usually refers to the language or framework an insight exists within. Users subscribe to Topics.
Take a look at our List of Topics
In this GitHub repository, every directory in the first hierarchy level represents a separate topic. Thus, to specify the topic of an insight, ensure the insightβs file is placed within the right topic directory.
A course represents a more specific area of content. Every course folder is contained in a topic folder. Each topic in the List of Topics should have its courses listed.
To prevent deadlinks, you should upload all images you plan to use at https://beta.enkipro.com/images.
After uploading your image to the Enki servers, you can link to the image as you normally would in markdown.
--
β note that these should not be used anymore; they are here just for reference
A Topic's standards represent major concepts within the topic that the user should understand. These standards are broken down into more granular ideas as Objectives (See Standards Repo for a comprehensive list of standards). All content should have an associated standard.
Standards are defined with the following syntax:
..<objective #>:
This insight, Double and single quotes, is associated with the 2nd objective of the javascript-syntax standard in the js topic, so it will list js.javascript-syntax.2 as one of its standards. Points
Points are a great way to weigh content within a standard.
As a general rule, Insights are worth 10 points, while more hands-on Exercises and other assessments are worth 1000 points.
The levels field indicates the target audience of an insight, experience-wise.
The levels currently available for an insight are:
- beginner
- basic
- medium
- advanced
This allows different recipes of level combinations such as:
-
beginner
- fit for people with little to no knowledge on the subject -
medium
,advanced
- fit for both confident and experts -
beginner
,basic
,medium
,advanced
- will be seen by all users, regardless of their level
Because games are, fundamentally, insights as well, this field is used to differentiate the type of game.
For insights, this field should be set to normal
.
This field should look like this:
type: normal
The notes field is the place where internal observations can be made on an insight. These are not shown to the user.
Simply add:
notes: 'here is my note'
This is an insight example that makes use of most of its available features. This insight will look like this in the app.
---
author: mihaiberq
type: normal
category: must-know
links:
- '[What is a linked list?](https://www.cs.cmu.edu/~adamchik/15-121/lectures/Linked%20Lists/linked%20lists.html){website}'
parent: the-array-data-structure
---
# The Linked List Data Structure
---
## Content
A **list**, or a **sequence**, is an *abstract*[1] data type representing a linear chain of values, where the same value can appear more than once. The *list* has a first element, **head**, and a last element, **tail**.
Because a list is *linear*[2], each element other than the head and the tail have a unique *predecessor* and a unique *successor*.
### LinkedList
*LinkedList* uses the concept of *nodes*[3] to represent its data.
Think of a conga line, in which every person, except the first and the last person, holds and is being held by someone. If you wanted to join the line to have some fun, you could do it by only "disturbing" 2 people: the one at the position `i` and the one at the position `i-1`.
However, you would still need to count to get to position `i`: no one has a sign above them stating their index.
The *conga line* is an example of a **SinglyLinkedList** because you cannot see who is behind you. The last one (in the example below, *G*) still has a reference that points to nothing(or `null`):
![sll](https://img.enkipro.com/9fc64a4643c8c46b7d2a600fe99a124d.png)
Note: when saying the first one, we refer to node `A`, and when saying the last one, we refer to node `G`.
To make it a **DoublyLinkedList**, everyone would have to use one hand to hold the person in front of them and their other hand to hold the person behind them. In this case, you would be able to move through both directions, from *start to finish* and from *finish to start*.
![dll](https://img.enkipro.com/dfe8bdeaffa55cb2d4504f4048f2b515.png)
### Dynamic Array vs. LinkedList
No data structure is well suited for all circumstances. A *LinkedList* may work well in one case but cause difficulties in another. The same is true for *Arrays*, so it is necessary to understand when to choose one instead of the other.
A good example to see the differences is the implementation of the *Josephus problem*[4]. If you consider the people in the circle being a *connected list of nodes*, then *deletion* is easy. However, the list will not excel at finding the next person to delete because it has to iterate through *n* nodes.
In contrast to the list, deletion in *dynamic arrays* implies shifting the other elements to maintain the internal structure. Yet, finding the *nth* person is easier by referencing their position directly.
---
## Practice
What does a DoublyLinkedList node usually keep track of?
???
* Its element, the previous node, and the next node.
* The previous node and the next node.
* Its element and the next node.
* Its element, the previous node, and the head of the list.
---
## Revision
Which of the following concepts is list-specific?
???
* Head
* Element
* Index
* Node
---
## Footnotes
[1:Abstract Data Type]
Abstract Data Type, or ADT, defines a data type (or a data structure) that only mentions what operations are to be performed but not how these operations will be implemented.
[2:Linear Data Structure]
A linear data structure means that its items lie on the same level and are not hierarchically structured.
[3:Node]
A node is a data type that contains an element and references to nodes next to it. In other words, from a node instance, you can obtain its value and one or more neighbors.
[4:Josephus problem]
Also known as *Josephus permutation*, it is a *count-out* game. The game starts with *m* people standing in a circle. Each turn consists of choosing a person to start the counting from and, in the same predefined direction, count up to *n*.
After the *nth* person is kicked out, the ones left close the circle and start again.
The game ends when there is a single person remaining.
Want to contribute to this wiki? Go right ahead! If it has to do with how the Enki software ecosystem works, or editorial guidelines for how to write, let us handle that. Anything else, edit away!
Curriculum Format:
- Topic Documentation
- Course Documentation
- Workout Documentation
- Insight Documentation
- Glossary Documentation
Contributor Resources:
Curriculum overview:
Topic pages: