Anki Books
Anki Books is a budding free and open-source software (see the AGPL-3.0 license) and proof-of-concept of online books featuring active practice and spaced repetition by integrating with Anki.
Motivation for Anki Books
I develop Anki Books because I like it and use it myself and also because I like the practice of developing software. Anki helped me remember many things that helped me in my daily life, but I noticed one limitation is knowledge atomically broken up into thousands of flashcards can become disconnected. A book that acts like an index into the cards and adds context helps with that.
Knowledge graphs in Anki Books
The Anki Books data can be downloaded as CSV files for study with network analysis tools like NetworkX and Gephi. The data structure is largely a tree which would not be interesting on its own, but there is a non-trivial structure due to the cloze deletion notes (fill-in-the-blank flashcards). Each fill-in-the-blank becomes a concept. A cloze deletion note with multiple concepts is a node with an edge to each concept. Visualization of the knowledge structure is a fun way to track your Anki learning habits and it is also useful to see what ideas have been studied from multiple sources. It is especially satisfying because studying the represented information with spaced repetition encodes and consolidates it into long-term memory. Memory naturally has an associative nature, and the mental representation overlaps with the physical representation in the database.
Incremental reading in Anki Books
Anki Books can be used for incremental reading in a basic and limited way. There will definitely be improvements to the software in this aspect. Currently it uses a simple load-balancing algorithm: choose an article at random. Articles are categorized as reading, writing, and complete but this design will almost certainly be changed.
How to use Anki Books?
If you have any comments about Anki Books or need help to set one up to try out, send me an email. It will be easier to try out Anki Books soon. I am looking into Azure to see if it would be possible to host instances on the cloud using Azure App Service and Azure Database for PostgreSQL (and/or other services or containers) for free using native Infrastructure-as-Code templates to make deployment easy. Some other blocking considerations are accessibility and security.
How does Anki Books create Anki notes?
The first part of Anki Books that was developed was a module called Anki Record, a Ruby gem that creates Anki deck packages. Anki deck packages are the files with the .apkg extension that import into Anki and create or update Anki notes. By using Anki Record, Anki Books is able to take its data conforming to a different model and convert it to Anki notes. Anki Books includes a basic note model which represents the front and back flashcards that can be attached to each article. Anki Books can also create cloze notes by extracting sentences with cloze deletions out of the articles and syncing them to the PostgreSQL database with a Levenshtein distance calculation. The cloze deletion terms are tracked as concepts for the purpose of tracking which cloze notes are related to each other. That was okay but it turned out to be too annoying to go in and edit longer articles to edit cloze stuff so now cloze notes do generate concepts and a concept graph, but you make them more similarly to basic notes. Each sentence you write in a group gets split into one cloze note per sentence with good error handling feedback (Turbo frames and native client-side validation). Both types of notes can be created at any ordinal position and dragged and dropped to sort them in the UI.
How does Anki Books create graphs?
Anki Books has endpoints for downloading CSV files of all the data that can be used to construct a graph that is similar to Wozniak's knowledge tree at the roots and Wozniak's concept network towards the remote areas especially where there are cloze notes. A cloze note with two concept cloze deletions is a node connecting the two concepts, for example.
This is an example Python script to create a file for Gephi:
This is an example Python script to create a file for Gephi:
// Programmer #1: // Sorry about the font on this code // TODO: fix font // Programmer #2: // Leave this comment as a warning to be wary in the code around here import networkx as nx import matplotlib.pyplot as plt import csv path = "./prod" G = nx.Graph() G.add_node("center") with open(f"{path}/books.csv", "r") as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: node_id = row[0] title = row[1] parent_book_id = row[2] G.add_node(node_id) G.nodes[node_id]["book"] = True G.nodes[node_id]["title"] = title if parent_book_id != "": G.add_edge(node_id, parent_book_id) else: G.add_edge(node_id, "center") with open(f"{path}/articles.csv", "r") as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: node_id = row[0] title = row[1] book_id = row[2] G.add_node(node_id) G.nodes[node_id]["article"] = True G.nodes[node_id]["title"] = title G.add_edge(node_id, book_id) with open(f"{path}/basic_notes.csv", 'r') as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: node_id = row[0] front = row[1] back = row[2] article_id = row[3] G.add_node(node_id) G.nodes[node_id]["basic_note"] = True G.nodes[node_id]["front"] = front G.nodes[node_id]["back"] = back G.add_edge(node_id, article_id) with open(f"{path}/concepts.csv", "r") as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: node_id = row[0] name = row[1] G.add_node(node_id) G.nodes[node_id]["name"] = name with open(f"{path}/cloze_notes.csv", "r") as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: node_id = row[0] sentence = row[1] article_id = row[2] G.add_node(node_id) G.nodes[node_id]["sentence"] = sentence G.add_edge(node_id, article_id) with open(f"{path}/cloze_notes_concepts.csv", "r") as file: csvreader = csv.reader(file) next(csvreader, None) for row in csvreader: cloze_note_id = row[0] concept_id = row[1] G.add_edge(cloze_note_id, concept_id) nx.draw_networkx(G, with_labels=False, node_size=5) plt.savefig(f"{path}/basic_notes_graph.svg") nx.write_graphml(G, f"{path}/basic_notes_graph.graphml")
Why does Anki Books use Ruby on Rails?
I was working a lot with Ruby on Rails when I started work on (this third version of) Anki Books. Ruby is a gentle, quirky, and rapid programming language. Combine this with the power of Rails and it's a great choice if you like new Ruby virtual machines. Ruby is so gentle that it cannot stop some projects from going off the Rails (the CS guys I knew in college would say it's just writing English). Since Anki Books is free software that cannot be made proprietary, the gentleness and power of the Ruby on Rails stack will hopefully be ideal for anyone who wants to extend the functionality.
Why does Anki Books use PostgreSQL?
PostgreSQL is the finest and most advanced free and open-source object-relational database management software in the world.
Example: an Anki Books article
ABC metric
The ABC metric is a measure of program size, but it may also measure complexity. It is a vector quantity with the number of assignments, branches, and conditionals in some code. This code may be a method, class, source file, or entire program. The ABC metrics can be added together linearly, but their magnitudes cannot, in the same way as is true for any vectors.
As determined by RuboCop, a static code analysis tool for Ruby, the following method has an ABC metric of <0, 6, 1>:
## # Returns nth number in the Fibonacci sequence starting with 1, 1 ... def fibonacci(n) [1, 2].include?(n) ? 1 : fibonacci(n - 1) + fibonacci(n - 2) end 5.times do |i| puts fibonacci(i + 1) end
There are no assignments so the first value of the vector is 0. Each function or method call adds a branch. Since Ruby is an "everything is an object" language, some of the method calls look like operators. There are two recursive calls to fibonacci, one call to include?, and three calls to methods which look like arithmetic operators. In a language where the arithmetic operators were not methods, this function might have a B value of 3 instead of 6.
By default, RuboCop complains about a method's ABC metric when its magnitude exceeds 17. The method can usually be refactored to eliminate this warning by extracting parts of it to smaller methods.
Cyclomatic complexity
Cyclomatic complexity is a measure of program complexity and focuses on the number of linearly independent paths through the program. The fibonacci method from the previous example has a cyclomatic complexity of 2 due to the ternary operator.
RuboCop will complain about this for the following method:
RuboCop will complain about this for the following method:
def triangle(a, b, c) if invalid_triangle?(a, b, c) :invalid elsif a == b && b == c && a == c :equilateral elsif a == b || b == c || a == c :isosceles else :scalene end end
The algorithm counts decision points and adds one.
An if statement (or unless or ?:) increases the complexity by one. An else branch does not, since it doesn’t add a decision point. The && operator (or keyword and) can be converted to a nested if statement, and ||/or is shorthand for a sequence of ifs, so they also add one. Loops can be said to have an exit condition, so they add one.
There are 3 ifs and 4 logical operators adding to 7 decision points, so the cyclomatic complexity is 8. By default, RuboCop will complain about a method's cyclomatic complexity when it exceeds 7.
The Law of Demeter
The Law of Demeter, or principle of least knowledge, is a design guideline that was proposed at Northeastern University in 1987. It recommends that each unit should have limited knowledge about other units and only interact with units to which it is "closely" related. If an object calls a method on an object to only access a third object to call a method on it, then this law is not being followed in that case. Oftentimes this law can be stated as "use only one dot" but this rule is not an exact statement of the idea because the LoD is not always broken when there is more than one dot.
Article notes
Examples notes [...].
Examples notes fdjafdhks.
The ABC metric was introduced as a possibly better alternative for what other software metric?
Source lines of code (SLOC)
Another [...].
Another note.
Of cyclomatic complexity and ABC metric, which focuses more on program size?
ABC metric
What software metric measures the number of linearly independent paths through a program?
Cyclomatic complexity
What is the magnitude of an ABC metric <3,0,4>?
5
What do A, B, and C stand for in the ABC metric?
Assignments, branches, and conditionals
What is the ABC metric of this line of Ruby code?
(x > 2) ? (y = 3) : (z = 5)
<2, 0, 2>
What is the smallest cyclomatic complexity that RuboCop will give a warning for by default?
7
What version of the name is System.Console?
A fully qualified name
What is the other name for the Law of Demeter?
The principle of least knowledge
Of cyclomatic complexity and ABC metric, which focuses more on program complexity?
Cyclomatic complexity (the answer is given away by the name)
Why does an else branch not add one to the cyclomatic complexity in the algorithm used by RuboCop?
It does not add a decision point
Where was the Law of Demeter introduced?
Northeastern University
The Law of Demeter is a specific case of:
Loose coupling
What is a common statement explaining how to follow the Law of Demeter?
Use only one dot