Skip to content

Commit

Permalink
add csv decks support
Browse files Browse the repository at this point in the history
  • Loading branch information
ayakovlenko committed Aug 3, 2024
1 parent b8e1ff9 commit f525810
Show file tree
Hide file tree
Showing 10 changed files with 67 additions and 100 deletions.
26 changes: 9 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,16 @@ https://docs.deno.com/runtime/manual/getting_started/installation/

It uses a simple deck format to create flashcards:

```yaml
cards:
- f: Front side
b: Back side
- f: Front side
b: Back side
```csv
Question,Answer
Front side,Back side
Front side,Back side
```

> [!TIP]\
> This is the format of Brainscape CSV export, so they can be used by Termilingo
> directly.
## Scoring system

Termilingo does not rely on self-assessed scores. Instead, it uses an automated
Expand Down Expand Up @@ -85,20 +87,10 @@ plt.show()
Run with an example deck:

```sh
deno task run --deck example-deck.yaml
deno task run --deck example-swedish.csv
```

Provide a path to your own deck and start practicing.

On the first run, the app will create a complimentary review file following a
convention `<deck-name>.review.yaml` to keep track of the state.

## Tools

### Brainscape importer

To convert a CSV exported from Brainscape, run:

```sh
deno task brainscape-importer
```
1 change: 1 addition & 0 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
"tasks": {
"run": "deno run --allow-read --allow-write --allow-env=NODE_ENV src/cli.ts",
"brainscape-importer": "deno run --allow-read src/tools/brainscape/importer.ts",
"test": "deno test src/",
"test-lcov": "./scripts/test-lcov.sh"
},
"imports": {
Expand Down
13 changes: 0 additions & 13 deletions example-deck.yaml

This file was deleted.

7 changes: 7 additions & 0 deletions example-swedish.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
Question,Answer
a dog,en hund
the dog,hunden
a cat,en katt
the cat,katten
a house,ett hus
the house,huset
12 changes: 0 additions & 12 deletions src/card.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { parse as parseYaml } from "@std/yaml";

interface CardYaml {
f: string;
b: string;
Expand All @@ -10,14 +8,4 @@ interface Card {
back: string;
}

async function loadDeck(filename: string): Promise<Card[]> {
const s = await Deno.readTextFile(filename);

const { cards } = parseYaml(s) as { cards: CardYaml[] };

return cards.map(({ f, b }) => ({ front: f, back: b }));
}

export type { Card, CardYaml };

export { loadDeck };
2 changes: 1 addition & 1 deletion src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Input } from "@cliffy/prompt";
import { parseArgs } from "@std/cli/parse-args";
import { green, red, yellow } from "@std/fmt/colors";
import { basename, dirname, join } from "@std/path";
import { loadDeck } from "./card.ts";
import { loadDeck } from "./deck.ts";
import { shuffle } from "./collections.ts";
import { ratio } from "./levenshtein.ts";
import {
Expand Down
49 changes: 49 additions & 0 deletions src/deck.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { extname } from "@std/path";
import { parse as parseYaml } from "@std/yaml";
import { Card, CardYaml } from "./card.ts";
import { parse as parseCsv } from "@std/csv";

async function loadDeck(filename: string): Promise<Card[]> {
const ext = extname(filename);

switch (ext) {
case ".yaml":
return await loadYamlDeck(filename);
case ".csv":
return await loadCsvDeck(filename);
default:
throw `unsupported extension: ${ext}`;
}
}

async function loadYamlDeck(filename: string): Promise<Card[]> {
const s = await Deno.readTextFile(filename);

const { cards } = parseYaml(s) as { cards: CardYaml[] };

return cards.map(({ f, b }) => ({ front: f, back: b }));
}

type CsvCard = {
Question: string;
Answer: string;
};

async function loadCsvDeck(filename: string): Promise<Card[]> {
const csvContent = await Deno.readTextFile(filename);

const parsedCsv = parseCsv(
csvContent,
{
header: true,
skipFirstRow: true,
},
) as CsvCard[];

return parsedCsv.map((row) => ({
front: row.Question,
back: row.Answer,
}));
}

export { loadDeck };
21 changes: 0 additions & 21 deletions src/tools/brainscape/importer.test.ts

This file was deleted.

12 changes: 0 additions & 12 deletions src/tools/brainscape/importer.ts

This file was deleted.

24 changes: 0 additions & 24 deletions src/tools/brainscape/mod.ts

This file was deleted.

0 comments on commit f525810

Please sign in to comment.