Refactor of Dictionary Management

The entire pathway from BIN data to card generation has been refactored
for better maintainability and better logical separation.
This commit is contained in:
Seth Morabito 2021-06-27 17:11:00 -07:00
parent e996940789
commit b9bc96a451
11 changed files with 4195 additions and 547 deletions

2
.gitignore vendored
View File

@ -2,3 +2,5 @@
/.idea
/build.sh
.DS_Store
/wordlist.txt
/*.apkg

67
Cargo.lock generated
View File

@ -87,22 +87,6 @@ version = "0.4.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "474a626a67200bd107d44179bb3d4fc61891172d11696609264589be6a0e6a43"
[[package]]
name = "binscrape"
version = "0.1.0"
dependencies = [
"clap",
"csv",
"genanki-rs",
"rand 0.8.4",
"regex",
"reqwest",
"select",
"serde",
"serde_json",
"tokio",
]
[[package]]
name = "bit-set"
version = "0.5.2"
@ -277,6 +261,27 @@ dependencies = [
"memchr",
]
[[package]]
name = "directories-next"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "339ee130d97a610ea5a5872d2bbb130fdf68884ff09d3028b81bec8a1ac23bbc"
dependencies = [
"cfg-if",
"dirs-sys-next",
]
[[package]]
name = "dirs-sys-next"
version = "0.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d"
dependencies = [
"libc",
"redox_users",
"winapi",
]
[[package]]
name = "encoding_rs"
version = "0.8.28"
@ -621,6 +626,26 @@ version = "2.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9"
[[package]]
name = "is-anki-gen"
version = "0.1.0"
dependencies = [
"clap",
"csv",
"directories-next",
"genanki-rs",
"rand 0.8.4",
"regex",
"reqwest",
"select",
"serde",
"serde_json",
"tempfile",
"thiserror",
"tokio",
"zip",
]
[[package]]
name = "itoa"
version = "0.4.7"
@ -1127,6 +1152,16 @@ dependencies = [
"bitflags",
]
[[package]]
name = "redox_users"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "528532f3d801c87aec9def2add9ca802fe569e44a544afe633765267840abe64"
dependencies = [
"getrandom 0.2.3",
"redox_syscall",
]
[[package]]
name = "regex"
version = "1.5.4"

View File

@ -1,5 +1,5 @@
[package]
name = "binscrape"
name = "is-anki-gen"
version = "0.1.0"
authors = ["Seth Morabito <web@loomcom.com>"]
edition = "2018"
@ -7,6 +7,7 @@ edition = "2018"
[dependencies]
clap = "2"
csv = "1.1"
directories-next = "2.0"
genanki-rs = "0.1"
rand = "0.8"
regex = "1.5"
@ -14,4 +15,7 @@ reqwest = "0.11"
select = "0.6.0-alpha.1"
serde_json = "1.0"
serde = "1.0"
tokio = { version = "1.6", features = ["full"] }
tempfile = "3.2"
thiserror = "1.0"
tokio = { version = "1.6", features = ["full"] }
zip = "0.5"

View File

@ -1,4 +1,4 @@
# BÍN Scraper
# Icelandic Anki Deck Generator
BÍN (Beygingarlýsing íslensks nútímamáls) is an online database of
Icelandic grammatical forms. It contains full declensions and
@ -7,51 +7,42 @@ utility can compile Anki flash cards based on this data. It is very
much a work in progress, and probably only useful for myself at the
moment.
This program requires the raw *Sigrúnarsnið* format data from BÍN to
work. The data is available as a CSV file from the following page:
https://bin.arnastofnun.is/gogn/mimisbrunnur/
The program can automatically download and uncompress the correct file
on initial run.
## Usage
USAGE:
binscrape [OPTIONS] <wordlist> --bindata <FILE> --category <CATEGORY> --deck <FILE>
is-anki-gen [OPTIONS] <wordlist>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-b, --bindata <FILE> BÍN CSV File
--category <CATEGORY> Wordlist file category ('nouns' or 'adjectives')
-d, --deck <FILE> Anki Deck output file
--deck-id <ID> Optional numeric ID for the generated Anki deck
--model-id <ID> Optional numeric ID for the generated Anki model
--binurl <URL> URL to fetch BÍN CSV [default:
https://bin.arnastofnun.is/django/api/nidurhal/?file=SHsnid.csv.zip]
-d, --deck <FILE> Anki Deck output file [default: deck.apkg]
--deck-id <ID> Optional numeric ID for the generated Anki deck
ARGS:
<wordlist> List of words and definitions, tab separated, one per line
<wordlist> List of words and categories, tab separated, one per line
This program requires the raw *Sigrúnarsnið* format data from BÍN to work.
The data is available as a CSV file from the following page:
The optional argument `--deck-id` can be used to set the Anki ID on
the generated deck. If not supplied, a random ID based on the current
timestamp will be used.
https://bin.arnastofnun.is/gogn/mimisbrunnur/
Download the file named `SHsnid.csv.zip`, and unzip it. When running
binscraper, use the `-c` or `--csvfile` argument to point at the unzipped
`SHsnid.csv` file.
Example wordlist files can be found in the `sample-data` directory. To test:
binscrape --bindata SHsnid.csv --deck noun.apkg \
--category nouns sample-data/nouns.csv
binscrape --bindata SHsnid.csv --deck adj.apkg \
--category adjectives sample-data/adjectives.csv
The optional arguments `--deck-id` and `--model-id` can be used to set IDs on the
generated deck and model. If not supplied, random IDs based on the current
timestamp will be used.
Anki uses these IDs in its internal database to keep track of what decks contain what
cards, so they really do have to be unique. Setting IDs for your own decks rather than
using random IDs is the preferred way, because you can regenerate decks at any time
after adding more words to the word list, and only the new words will be imported
into Anki on the next import.
Anki uses these IDs in its internal database to keep track of what
decks contain what cards, so they really do have to be unique. Setting
IDs for your own decks rather than using random IDs is the preferred
way, because you can regenerate decks at any time after adding more
words to the word list, and only the new words will be imported into
Anki on the next import.
# Links

View File

@ -1,79 +0,0 @@
alþjóðlegur "{""translations"":[{""meaning"":""international"",""usage"":null}]}"
appelsínugulur "{""translations"":[{""meaning"":""orange, orange-colored/(UK) coloured"",""usage"":null}]}"
auðveldur "{""translations"":[{""meaning"":""easy, simple"",""usage"":null}]}"
bjartur "{""translations"":[{""meaning"":""bright, clear, shining"",""usage"":null}]}"
bleikur "{""translations"":[{""meaning"":""pink, pale"",""usage"":null}]}"
blár "{""translations"":[{""meaning"":""blue"",""usage"":null},{""meaning"":""unadulterated, pure"",""usage"":""eintómur""},{""meaning"":""be unaffected, natural"",""usage"":null}]}"
brúnn "{""translations"":[{""meaning"":""brown"",""usage"":null}]}"
dapur "{""translations"":[{""meaning"":""sad, depressed"",""usage"":""hryggur""},{""meaning"":""poor, inadequate"",""usage"":""lélegur""}]}"
dimmur "{""translations"":[{""meaning"":""dark"",""usage"":""myrkur""},{""meaning"":""deep"",""usage"":""um rödd""},{""meaning"":""grave"",""usage"":""í málfr""}]}"
duglegur "{""translations"":[{""meaning"":""energetic, hard-working, efficient"",""usage"":null}]}"
erfiður "{""translations"":[{""meaning"":""difficult, hard"",""usage"":""torveldur""},{""meaning"":""wearying, fatiguing"",""usage"":""þreytandi""},{""meaning"":""troublesome"",""usage"":""ódæll""},{""meaning"":""stiff-necked, unwielding"",""usage"":""ósveigjanlegur""}]}"
fallegur "{""translations"":[{""meaning"":""beautiful"",""usage"":null}]}"
fjólublár "{""translations"":[{""meaning"":""violet"",""usage"":null}]}"
fjölbreyttur "{""translations"":[{""meaning"":""varied, many-sided"",""usage"":null}]}"
flestur "{""translations"":[{""meaning"":""many, a lot"",""usage"":""um mergð""},{""meaning"":""much, many things"",""usage"":""um mörg atriði""}]}"
frekur "{""translations"":[{""meaning"":""pushy, forward"",""usage"":null}]}"
frábær "{""translations"":[{""meaning"":""distinguished, excellent"",""usage"":null}]}"
frægur "{""translations"":[{""meaning"":""famous"",""usage"":null}]}"
fróður "{""translations"":[{""meaning"":""knowledgeable, learned, erudite, well-read"",""usage"":null}]}"
fyndinn "{""translations"":[{""meaning"":""witty, funny"",""usage"":null}]}"
félagslyndur "{""translations"":[{""meaning"":""sociable, gregarious"",""usage"":null}]}"
gamall "{""translations"":[{""meaning"":""old, ancient"",""usage"":null}]}"
glaður "{""translations"":[{""meaning"":""glad, happy, cheerful"",""usage"":""kátur""},{""meaning"":""bright"",""usage"":""bjartur""}]}"
glæsilegur "{""translations"":[{""meaning"":""splendid, magnificent, elegant"",""usage"":null}]}"
grár "{""translations"":[{""meaning"":""grey"",""usage"":null},{""meaning"":""white horse"",""usage"":null},{""meaning"":""deal harshly with sby"",""usage"":null}]}"
grænn "{""translations"":[{""meaning"":""green"",""usage"":null}]}"
gulur "{""translations"":[{""meaning"":""yellow"",""usage"":null}]}"
gáfaður "{""translations"":[{""meaning"":""intelligent"",""usage"":null}]}"
hamingjusamur "{""translations"":[{""meaning"":""happy"",""usage"":null}]}"
heimsfrægur "{""translations"":[{""meaning"":""world-famous"",""usage"":null}]}"
heimskur "{""translations"":[{""meaning"":""stupid"",""usage"":null}]}"
heitur "{""translations"":[{""meaning"":""hot, warm"",""usage"":null}]}"
hlýr "{""translations"":[{""meaning"":""warm"",""usage"":null}]}"
hreinn "{""translations"":[{""meaning"":""clean"",""usage"":null},{""meaning"":""pure"",""usage"":""óblandaður""},{""meaning"":""it is not completely clear"",""usage"":null}]}"
hress "{""translations"":[{""meaning"":""fit, well"",""usage"":""heilsugóður""},{""meaning"":""in high spirits, in good form"",""usage"":""kátur""}]}"
hvítur "{""translations"":[{""meaning"":""white"",""usage"":null}]}"
hæfileikaríkur "{""translations"":[{""meaning"":""talented"",""usage"":null}]}"
hægur "{""translations"":[{""meaning"":""easy, convenient"",""usage"":""auðveldur""},{""meaning"":""possible"",""usage"":""mögulegur""},{""meaning"":""calm, quiet, slow"",""usage"":""stilltur""}]}"
kaldur "{""translations"":[{""meaning"":""cold"",""usage"":null}]}"
kveðinn "{""translations"":[{""meaning"":""say"",""usage"":""segja""},{""meaning"":""compose"",""usage"":""yrkja""},{""meaning"":""chant, intone"",""usage"":""syngja""},{""meaning"":""say of oneself"",""usage"":null},{""meaning"":""lay down, pronounce"",""usage"":""phrases""}]}"
kvíðinn "{""translations"":[{""meaning"":""fearful, anxious, apprehensive"",""usage"":null}]}"
kátur "{""translations"":[{""meaning"":""cheerful, merry, jolly"",""usage"":null}]}"
latur "{""translations"":[{""meaning"":""lazy"",""usage"":null}]}"
leiðinlegur "{""translations"":[{""meaning"":""dull, boring, tedious"",""usage"":""þreytandi""},{""meaning"":""sad"",""usage"":""sorglegur""}]}"
ljótur "{""translations"":[{""meaning"":""ugly"",""usage"":""ófagur""},{""meaning"":""bad"",""usage"":""slæmur""}]}"
léttur "{""translations"":[{""meaning"":""light"",""usage"":""ekki þungur""},{""meaning"":""easy, light"",""usage"":""ekki erfiður""},{""meaning"":""light, nimble"",""usage"":""léttfær""},{""meaning"":""cheerful, merry"",""usage"":""glaður""}]}"
lítill "{""translations"":[{""meaning"":""small, short"",""usage"":""smár""},{""meaning"":""little, insignificant"",""usage"":""óverulegur""},{""meaning"":""short"",""usage"":""um tíma""},{""meaning"":""less than average"",""usage"":null},{""meaning"":""at least"",""usage"":null}]}"
margur "{""translations"":[{""meaning"":""many, a lot"",""usage"":""um mergð""},{""meaning"":""much, many things"",""usage"":""um mörg atriði""}]}"
nógur "{""translations"":[{""meaning"":""enough, sufficient, satisfactory"",""usage"":null}]}"
nýlegur "{""translations"":[{""meaning"":""almost new, recent"",""usage"":null}]}"
nýr "{""translations"":[{""meaning"":""new, fresh"",""usage"":null}]}"
rauður "{""translations"":[{""meaning"":""red"",""usage"":null}]}"
rólegur "{""translations"":[{""meaning"":""calm, quiet, tranquil"",""usage"":""stilltur""},{""meaning"":""slow"",""usage"":""hægur""}]}"
saddur "{""translations"":[{""meaning"":""full, replete"",""usage"":null}]}"
skemmtilegur "{""translations"":[{""meaning"":""amusing, funny"",""usage"":""fyndinn""},{""meaning"":""entertaining, diverting"",""usage"":""sem veitir skemmtun""},{""meaning"":""interesting"",""usage"":""forvitnilegur""}]}"
skýr "{""translations"":[{""meaning"":""clear, distinct"",""usage"":""greinilegur""},{""meaning"":""lucid, readily-intelligible"",""usage"":""auðskilinn""},{""meaning"":""sharp, quick, intelligent"",""usage"":""greindur""}]}"
sorglegur "{""translations"":[{""meaning"":""tragic, sad"",""usage"":""harmrænn""},{""meaning"":""sad, distressed"",""usage"":""ókátur""}]}"
spennandi "{""translations"":[{""meaning"":""thrilling, exciting"",""usage"":null}]}"
spenntur "{""translations"":[{""meaning"":""expectant, eager, anxious"",""usage"":""eftirvæntingarfullur""},{""meaning"":""tense, nervous, keyed up"",""usage"":""taugastrekktur""},{""meaning"":""be keen on sth, be excited about sth"",""usage"":null}]}"
stórkostlegur "{""translations"":[{""meaning"":""great, magnificent, splendid"",""usage"":null}]}"
svangur "{""translations"":[{""meaning"":""hungry"",""usage"":null}]}"
svartur "{""translations"":[{""meaning"":""black"",""usage"":null}]}"
svolítill "{""translations"":[{""meaning"":""small, little"",""usage"":""lítill""},{""meaning"":""a little"",""usage"":""dálítið""}]}"
sérstakur "{""translations"":[{""meaning"":""separate"",""usage"":""einn sér""},{""meaning"":""particular"",""usage"":""frábrugðinn""},{""meaning"":""special, unusual"",""usage"":""óvenjulegur""}]}"
tilbúinn "{""translations"":[{""meaning"":""ready"",""usage"":""reiðubúinn""},{""meaning"":""prepared"",""usage"":""viðbúinn""},{""meaning"":""fictional, fictitious"",""usage"":""upploginn""},{""meaning"":""ready-made"",""usage"":""fyrirframgerður""},{""meaning"":""artificial"",""usage"":""unninn af mönnum""}]}"
ungur "{""translations"":[{""meaning"":""young"",""usage"":null}]}"
vinsæll "{""translations"":[{""meaning"":""popular"",""usage"":null}]}"
vondur "{""translations"":[{""meaning"":""bad, evil"",""usage"":""illur""},{""meaning"":""angry, mad"",""usage"":""reiður""},{""meaning"":""poor, bad, in bad shape"",""usage"":""lélegur""},{""meaning"":""he is a very bad man"",""usage"":null}]}"
yndislegur "{""translations"":[{""meaning"":""wonderful, marvellous"",""usage"":null}]}"
áhugasamur "{""translations"":[{""meaning"":""interested, keen"",""usage"":null}]}"
ánægjulegur "{""translations"":[{""meaning"":""enjoyable, pleasant, delightful"",""usage"":null}]}"
ótrúlegur "{""translations"":[{""meaning"":""unbelievable"",""usage"":null}]}"
óvinsæll "{""translations"":[{""meaning"":""unpopular, disliked"",""usage"":null}]}"
óþekktur "{""translations"":[{""meaning"":""unknown"",""usage"":null}]}"
örugglega "{""translations"":[{""meaning"":""certainly, definitely"",""usage"":""áreiðanlega""},{""meaning"":""with assurance, securely"",""usage"":""af öryggi""}]}"
þreyttur "{""translations"":[{""meaning"":""tired, exhausted, fatigued"",""usage"":null}]}"
þröngur "{""translations"":[{""meaning"":""crowded, confined"",""usage"":""rúmlítill""},{""meaning"":""narrow"",""usage"":""krappur""},{""meaning"":""difficult"",""usage"":""erfiður""},{""meaning"":""close-fitting"",""usage"":""aðskorinn""}]}"
þunglyndur "{""translations"":[{""meaning"":""sad, melancholy, depressed"",""usage"":null}]}"
þyrstur "{""translations"":[{""meaning"":""thirsty"",""usage"":null}]}"
1 alþjóðlegur {"translations":[{"meaning":"international","usage":null}]}
2 appelsínugulur {"translations":[{"meaning":"orange, orange-colored/(UK) coloured","usage":null}]}
3 auðveldur {"translations":[{"meaning":"easy, simple","usage":null}]}
4 bjartur {"translations":[{"meaning":"bright, clear, shining","usage":null}]}
5 bleikur {"translations":[{"meaning":"pink, pale","usage":null}]}
6 blár {"translations":[{"meaning":"blue","usage":null},{"meaning":"unadulterated, pure","usage":"eintómur"},{"meaning":"be unaffected, natural","usage":null}]}
7 brúnn {"translations":[{"meaning":"brown","usage":null}]}
8 dapur {"translations":[{"meaning":"sad, depressed","usage":"hryggur"},{"meaning":"poor, inadequate","usage":"lélegur"}]}
9 dimmur {"translations":[{"meaning":"dark","usage":"myrkur"},{"meaning":"deep","usage":"um rödd"},{"meaning":"grave","usage":"í málfr"}]}
10 duglegur {"translations":[{"meaning":"energetic, hard-working, efficient","usage":null}]}
11 erfiður {"translations":[{"meaning":"difficult, hard","usage":"torveldur"},{"meaning":"wearying, fatiguing","usage":"þreytandi"},{"meaning":"troublesome","usage":"ódæll"},{"meaning":"stiff-necked, unwielding","usage":"ósveigjanlegur"}]}
12 fallegur {"translations":[{"meaning":"beautiful","usage":null}]}
13 fjólublár {"translations":[{"meaning":"violet","usage":null}]}
14 fjölbreyttur {"translations":[{"meaning":"varied, many-sided","usage":null}]}
15 flestur {"translations":[{"meaning":"many, a lot","usage":"um mergð"},{"meaning":"much, many things","usage":"um mörg atriði"}]}
16 frekur {"translations":[{"meaning":"pushy, forward","usage":null}]}
17 frábær {"translations":[{"meaning":"distinguished, excellent","usage":null}]}
18 frægur {"translations":[{"meaning":"famous","usage":null}]}
19 fróður {"translations":[{"meaning":"knowledgeable, learned, erudite, well-read","usage":null}]}
20 fyndinn {"translations":[{"meaning":"witty, funny","usage":null}]}
21 félagslyndur {"translations":[{"meaning":"sociable, gregarious","usage":null}]}
22 gamall {"translations":[{"meaning":"old, ancient","usage":null}]}
23 glaður {"translations":[{"meaning":"glad, happy, cheerful","usage":"kátur"},{"meaning":"bright","usage":"bjartur"}]}
24 glæsilegur {"translations":[{"meaning":"splendid, magnificent, elegant","usage":null}]}
25 grár {"translations":[{"meaning":"grey","usage":null},{"meaning":"white horse","usage":null},{"meaning":"deal harshly with sby","usage":null}]}
26 grænn {"translations":[{"meaning":"green","usage":null}]}
27 gulur {"translations":[{"meaning":"yellow","usage":null}]}
28 gáfaður {"translations":[{"meaning":"intelligent","usage":null}]}
29 hamingjusamur {"translations":[{"meaning":"happy","usage":null}]}
30 heimsfrægur {"translations":[{"meaning":"world-famous","usage":null}]}
31 heimskur {"translations":[{"meaning":"stupid","usage":null}]}
32 heitur {"translations":[{"meaning":"hot, warm","usage":null}]}
33 hlýr {"translations":[{"meaning":"warm","usage":null}]}
34 hreinn {"translations":[{"meaning":"clean","usage":null},{"meaning":"pure","usage":"óblandaður"},{"meaning":"it is not completely clear","usage":null}]}
35 hress {"translations":[{"meaning":"fit, well","usage":"heilsugóður"},{"meaning":"in high spirits, in good form","usage":"kátur"}]}
36 hvítur {"translations":[{"meaning":"white","usage":null}]}
37 hæfileikaríkur {"translations":[{"meaning":"talented","usage":null}]}
38 hægur {"translations":[{"meaning":"easy, convenient","usage":"auðveldur"},{"meaning":"possible","usage":"mögulegur"},{"meaning":"calm, quiet, slow","usage":"stilltur"}]}
39 kaldur {"translations":[{"meaning":"cold","usage":null}]}
40 kveðinn {"translations":[{"meaning":"say","usage":"segja"},{"meaning":"compose","usage":"yrkja"},{"meaning":"chant, intone","usage":"syngja"},{"meaning":"say of oneself","usage":null},{"meaning":"lay down, pronounce","usage":"phrases"}]}
41 kvíðinn {"translations":[{"meaning":"fearful, anxious, apprehensive","usage":null}]}
42 kátur {"translations":[{"meaning":"cheerful, merry, jolly","usage":null}]}
43 latur {"translations":[{"meaning":"lazy","usage":null}]}
44 leiðinlegur {"translations":[{"meaning":"dull, boring, tedious","usage":"þreytandi"},{"meaning":"sad","usage":"sorglegur"}]}
45 ljótur {"translations":[{"meaning":"ugly","usage":"ófagur"},{"meaning":"bad","usage":"slæmur"}]}
46 léttur {"translations":[{"meaning":"light","usage":"ekki þungur"},{"meaning":"easy, light","usage":"ekki erfiður"},{"meaning":"light, nimble","usage":"léttfær"},{"meaning":"cheerful, merry","usage":"glaður"}]}
47 lítill {"translations":[{"meaning":"small, short","usage":"smár"},{"meaning":"little, insignificant","usage":"óverulegur"},{"meaning":"short","usage":"um tíma"},{"meaning":"less than average","usage":null},{"meaning":"at least","usage":null}]}
48 margur {"translations":[{"meaning":"many, a lot","usage":"um mergð"},{"meaning":"much, many things","usage":"um mörg atriði"}]}
49 nógur {"translations":[{"meaning":"enough, sufficient, satisfactory","usage":null}]}
50 nýlegur {"translations":[{"meaning":"almost new, recent","usage":null}]}
51 nýr {"translations":[{"meaning":"new, fresh","usage":null}]}
52 rauður {"translations":[{"meaning":"red","usage":null}]}
53 rólegur {"translations":[{"meaning":"calm, quiet, tranquil","usage":"stilltur"},{"meaning":"slow","usage":"hægur"}]}
54 saddur {"translations":[{"meaning":"full, replete","usage":null}]}
55 skemmtilegur {"translations":[{"meaning":"amusing, funny","usage":"fyndinn"},{"meaning":"entertaining, diverting","usage":"sem veitir skemmtun"},{"meaning":"interesting","usage":"forvitnilegur"}]}
56 skýr {"translations":[{"meaning":"clear, distinct","usage":"greinilegur"},{"meaning":"lucid, readily-intelligible","usage":"auðskilinn"},{"meaning":"sharp, quick, intelligent","usage":"greindur"}]}
57 sorglegur {"translations":[{"meaning":"tragic, sad","usage":"harmrænn"},{"meaning":"sad, distressed","usage":"ókátur"}]}
58 spennandi {"translations":[{"meaning":"thrilling, exciting","usage":null}]}
59 spenntur {"translations":[{"meaning":"expectant, eager, anxious","usage":"eftirvæntingarfullur"},{"meaning":"tense, nervous, keyed up","usage":"taugastrekktur"},{"meaning":"be keen on sth, be excited about sth","usage":null}]}
60 stórkostlegur {"translations":[{"meaning":"great, magnificent, splendid","usage":null}]}
61 svangur {"translations":[{"meaning":"hungry","usage":null}]}
62 svartur {"translations":[{"meaning":"black","usage":null}]}
63 svolítill {"translations":[{"meaning":"small, little","usage":"lítill"},{"meaning":"a little","usage":"dálítið"}]}
64 sérstakur {"translations":[{"meaning":"separate","usage":"einn sér"},{"meaning":"particular","usage":"frábrugðinn"},{"meaning":"special, unusual","usage":"óvenjulegur"}]}
65 tilbúinn {"translations":[{"meaning":"ready","usage":"reiðubúinn"},{"meaning":"prepared","usage":"viðbúinn"},{"meaning":"fictional, fictitious","usage":"upploginn"},{"meaning":"ready-made","usage":"fyrirframgerður"},{"meaning":"artificial","usage":"unninn af mönnum"}]}
66 ungur {"translations":[{"meaning":"young","usage":null}]}
67 vinsæll {"translations":[{"meaning":"popular","usage":null}]}
68 vondur {"translations":[{"meaning":"bad, evil","usage":"illur"},{"meaning":"angry, mad","usage":"reiður"},{"meaning":"poor, bad, in bad shape","usage":"lélegur"},{"meaning":"he is a very bad man","usage":null}]}
69 yndislegur {"translations":[{"meaning":"wonderful, marvellous","usage":null}]}
70 áhugasamur {"translations":[{"meaning":"interested, keen","usage":null}]}
71 ánægjulegur {"translations":[{"meaning":"enjoyable, pleasant, delightful","usage":null}]}
72 ótrúlegur {"translations":[{"meaning":"unbelievable","usage":null}]}
73 óvinsæll {"translations":[{"meaning":"unpopular, disliked","usage":null}]}
74 óþekktur {"translations":[{"meaning":"unknown","usage":null}]}
75 örugglega {"translations":[{"meaning":"certainly, definitely","usage":"áreiðanlega"},{"meaning":"with assurance, securely","usage":"af öryggi"}]}
76 þreyttur {"translations":[{"meaning":"tired, exhausted, fatigued","usage":null}]}
77 þröngur {"translations":[{"meaning":"crowded, confined","usage":"rúmlítill"},{"meaning":"narrow","usage":"krappur"},{"meaning":"difficult","usage":"erfiður"},{"meaning":"close-fitting","usage":"aðskorinn"}]}
78 þunglyndur {"translations":[{"meaning":"sad, melancholy, depressed","usage":null}]}
79 þyrstur {"translations":[{"meaning":"thirsty","usage":null}]}

2678
sample-data/dictionary.json Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,155 +0,0 @@
afmælisveisla "{""translations"":[{""meaning"":""birthday party"",""usage"":null}]}"
anddyri "{""translations"":[{""meaning"":""entrance, vestibule"",""usage"":null}]}"
aðalhlutverk "{""translations"":[{""meaning"":""main role"",""usage"":null}]}"
belti "{""translations"":[{""meaning"":""belt"",""usage"":""mittisól""},{""meaning"":""zone"",""usage"":""svæði""},{""meaning"":""caterpillar tread"",""usage"":""keðja""}]}"
birta "{""translations"":[{""meaning"":""light, brightness"",""usage"":null}]}"
blaðagrein "{""translations"":[{""meaning"":""newspaper article"",""usage"":null}]}"
borg "{""translations"":[{""meaning"":""city, town"",""usage"":""bær""},{""meaning"":""castle"",""usage"":""kastali""},{""meaning"":""rocky hill"",""usage"":""klettahæð""},{""meaning"":""shelter"",""usage"":""byrgi""}]}"
borð "{""translations"":[{""meaning"":""table, desk"",""usage"":""plata á fótum""},{""meaning"":""plank, board"",""usage"":""planki""},{""meaning"":""go aboard, go on board"",""usage"":""skipshlið""},{""meaning"":""of the same caliber/(UK) calibre as sby"",""usage"":""phrases""}]}"
bróðir "{""translations"":[{""meaning"":""brother"",""usage"":null}]}"
bíll "{""translations"":[{""meaning"":""car, automobile"",""usage"":null}]}"
bíó "{""translations"":[{""meaning"":""movie theater, (UK) cinema"",""usage"":null}]}"
bíómynd "{""translations"":[{""meaning"":""film"",""usage"":null}]}"
bók "{""translations"":[{""meaning"":""book"",""usage"":null}]}"
bókmenntafræði "{""translations"":[{""meaning"":""literary studies, literature"",""usage"":null}]}"
dagblað "{""translations"":[{""meaning"":""daily (news)paper, daily"",""usage"":null}]}"
dagur "{""translations"":[{""meaning"":""day"",""usage"":null}]}"
dalur "{""translations"":[{""meaning"":""valley, dale"",""usage"":""lægð""},{""meaning"":""dollar"",""usage"":""mynt""}]}"
diskur "{""translations"":[{""meaning"":""plate"",""usage"":null},{""meaning"":""disk/disc"",""usage"":""í tölvu""}]}"
dót "{""translations"":[{""meaning"":""luggage, things"",""usage"":""farangur""},{""meaning"":""toys"",""usage"":""leikföng""},{""meaning"":""rabble"",""usage"":""hyski""}]}"
eignarfall "{""translations"":[{""meaning"":""genitive, possessive case"",""usage"":null}]}"
fangelsi "{""translations"":[{""meaning"":""prison"",""usage"":null}]}"
farangur "{""translations"":[{""meaning"":""luggage, baggage"",""usage"":null}]}"
ferð "{""translations"":[{""meaning"":""trip, journey"",""usage"":""för""},{""meaning"":""speed"",""usage"":""hraði""}]}"
fjall "{""translations"":[{""meaning"":""mountain"",""usage"":null}]}"
forrit "{""translations"":[{""meaning"":""program, (UK) programme"",""usage"":""tölvu~""},{""meaning"":""exemplar"",""usage"":""heimild, sem skrifað er eftir""}]}"
forritari "{""translations"":[]}"
framtíð "{""translations"":[{""meaning"":""future"",""usage"":null},{""meaning"":""future tense"",""usage"":""í málfr""}]}"
frelsishetja "{""translations"":[{""meaning"":""frredom champion"",""usage"":null}]}"
gaman "{""translations"":[{""meaning"":""fun, enjoyment"",""usage"":null}]}"
gangstétt "{""translations"":[{""meaning"":""sidewalk, (UK) pavement"",""usage"":null}]}"
gata "{""translations"":[{""meaning"":""street, way, path"",""usage"":null}]}"
geisladiskur "{""translations"":[{""meaning"":""compact disc, CD"",""usage"":null}]}"
grein "{""translations"":[{""meaning"":""branch, bough"",""usage"":""á tré""},{""meaning"":""subject, field, speciality, specialty"",""usage"":""fag""},{""meaning"":""article"",""usage"":""blaða~""},{""meaning"":""paragraph"",""usage"":""laga~""},{""meaning"":""point"",""usage"":""atriði""},{""meaning"":""consideration"",""usage"":""athugun""}]}"
greiða "{""translations"":[{""meaning"":""pay"",""usage"":""borga""},{""meaning"":""comb"",""usage"":null}]}"
gönguferð "{""translations"":[{""meaning"":""walk, hike"",""usage"":null}]}"
handklæði "{""translations"":[{""meaning"":""towel"",""usage"":null}]}"
handrit "{""translations"":[{""meaning"":""manuscript"",""usage"":null}]}"
hangikjöt "{""translations"":[{""meaning"":""smoked meat (esp lamb)"",""usage"":null}]}"
haust "{""translations"":[{""meaning"":""fall, (UK) autumn"",""usage"":null}]}"
herbergi "{""translations"":[{""meaning"":""room"",""usage"":null}]}"
hestur "{""translations"":[{""meaning"":""horse"",""usage"":null}]}"
hlutur "{""translations"":[{""meaning"":""thing, object"",""usage"":""gripur""},{""meaning"":""part, share"",""usage"":""hluti""}]}"
hlutverk "{""translations"":[{""meaning"":""task"",""usage"":""verkefni""},{""meaning"":""mission, role"",""usage"":""ætlunarverk""}]}"
hreinleiki "{""translations"":[{""meaning"":""purity"",""usage"":null}]}"
hálstafla "{""translations"":[]}"
hár "{""translations"":[{""meaning"":""hair"",""usage"":null}]}"
hárþurrka "{""translations"":[{""meaning"":""dryer"",""usage"":null}]}"
hörkuvinna "{""translations"":[{""meaning"":""(extremely) hard work"",""usage"":null}]}"
hús "{""translations"":[{""meaning"":""house, home"",""usage"":null}]}"
innsetning "{""translations"":[{""meaning"":""installation (as a work of art)"",""usage"":null}]}"
kennari "{""translations"":[{""meaning"":""teacher"",""usage"":null}]}"
kongur "{""translations"":[{""meaning"":""king"",""usage"":null}]}"
kort "{""translations"":[{""meaning"":""map"",""usage"":""landa~""},{""meaning"":""postcard, card"",""usage"":""bréfspjald""}]}"
króna "{""translations"":[{""meaning"":""króna, krone, crown (Icelandic unit of currency = 100 aurar)"",""usage"":""peningur""},{""meaning"":""tree-top, crown of a tree"",""usage"":""trjátoppur""}]}"
kvikmynd "{""translations"":[{""meaning"":""film, movie"",""usage"":null}]}"
kvöldmatur "{""translations"":[{""meaning"":""supper, dinner"",""usage"":null}]}"
kyrrð "{""translations"":[{""meaning"":""silence, stillness"",""usage"":""þögn""},{""meaning"":""peace and quiet"",""usage"":""ró""}]}"
kóramót "{""translations"":[]}"
leikstjóri "{""translations"":[{""meaning"":""director (of a film, play)"",""usage"":null}]}"
leiðsögumaður "{""translations"":[{""meaning"":""guide, travel guide"",""usage"":null}]}"
listamaður "{""translations"":[{""meaning"":""artist"",""usage"":null}]}"
listasafn "{""translations"":[{""meaning"":""art museum"",""usage"":null}]}"
listaverk "{""translations"":[{""meaning"":""work of art"",""usage"":null}]}"
listfræðingur "{""translations"":[{""meaning"":""art historian"",""usage"":null}]}"
litur "{""translations"":[{""meaning"":""color, (UK) colour, hue"",""usage"":""farfi""},{""meaning"":""dye, coloring, (UK) colouring"",""usage"":""litarefni""},{""meaning"":""crayon"",""usage"":""vaxlitur o.s.frv.""},{""meaning"":""suit (in cards)"",""usage"":""í spilum""},{""meaning"":""show interest in sth"",""usage"":null}]}"
líf "{""translations"":[{""meaning"":""life"",""usage"":null}]}"
lýsingarorð "{""translations"":[{""meaning"":""adjective"",""usage"":null}]}"
mappa "{""translations"":[{""meaning"":""folder, file"",""usage"":null}]}"
matur "{""translations"":[{""meaning"":""food"",""usage"":null},{""meaning"":""he knows how to cash in on everything"",""usage"":null}]}"
maður "{""translations"":[{""meaning"":""person, human being, individual"",""usage"":""manneskja""},{""meaning"":""man"",""usage"":""karlmaður""},{""meaning"":""man!"",""usage"":""óformlegt ávarp""},{""meaning"":""husband"",""usage"":""eiginmaður""},{""meaning"":""piece (in chess)"",""usage"":""í skák""},{""meaning"":""one, you"",""usage"":""fornafn""}]}"
meistari "{""translations"":[{""meaning"":""master, maestro (in music)"",""usage"":null}]}"
mikill "{""translations"":[{""meaning"":""large, big"",""usage"":""stór""},{""meaning"":""much"",""usage"":""um magn""},{""meaning"":""great"",""usage"":""stórkostlegur""}]}"
miðbær "{""translations"":[{""meaning"":""city center, downtown area, (UK) city centre"",""usage"":null}]}"
miði "{""translations"":[{""meaning"":""slip of paper, note"",""usage"":""seðill""},{""meaning"":""ticket"",""usage"":""aðgöngumiði""}]}"
mynd "{""translations"":[{""meaning"":""shape, form"",""usage"":""lögun""},{""meaning"":""photo(graph), picture, snapshot"",""usage"":""ljósmynd""},{""meaning"":""movie, (UK) film"",""usage"":""bíómynd""},{""meaning"":""painting, picture"",""usage"":""málverk""},{""meaning"":""illustration"",""usage"":""myndskreyting""},{""meaning"":""figure, diagram"",""usage"":""skýringarmynd""},{""meaning"":""voice (in grammar)"",""usage"":""í málfr""},{""meaning"":""image (metaphor, etc)"",""usage"":""í skáldskap""},{""meaning"":""this is poorly done"",""usage"":""phrases""}]}"
málverk "{""translations"":[{""meaning"":""painting"",""usage"":null}]}"
mót "{""translations"":[{""meaning"":""meeting, gathering"",""usage"":""samkoma""},{""meaning"":""tournament, meet"",""usage"":""keppni""},{""meaning"":""mould, form"",""usage"":""form""},{""meaning"":""joint"",""usage"":""samskeyti""},{""meaning"":""in many different ways"",""usage"":""phrases""}]}"
nafnorð "{""translations"":[{""meaning"":""noun, substantive"",""usage"":null}]}"
nammi "{""translations"":[{""meaning"":""candy, (UK) sweets (baby talk for sth good to eat as inyummy, yummy')"",""usage"":null}]}"
nefnifall "{""translations"":[{""meaning"":""nominative, nominative case"",""usage"":null}]}"
nemandi "{""translations"":[{""meaning"":""student, pupil"",""usage"":null}]}"
nóta "{""translations"":[{""meaning"":""note"",""usage"":""í músík""},{""meaning"":""bill"",""usage"":""reikningur""},{""meaning"":""receipt"",""usage"":""kvittun""},{""meaning"":""comment, note"",""usage"":""athugasemd""},{""meaning"":""be with it, know what is going on"",""usage"":null}]}"
ostur "{""translations"":[{""meaning"":""cheese"",""usage"":null}]}"
persóna "{""translations"":[{""meaning"":""person"",""usage"":""einstaklingur""},{""meaning"":""personality"",""usage"":""persónuleiki""},{""meaning"":""character"",""usage"":""~~ í skáldverki""}]}"
peysa "{""translations"":[{""meaning"":""sweater, (UK) jersey"",""usage"":""ullarpeysa""},{""meaning"":""blouse (of the woman's Icelandic national costume)"",""usage"":""peysufatapeysa""}]}"
piltur "{""translations"":[{""meaning"":""boy, young man"",""usage"":null}]}"
popp "{""translations"":[{""meaning"":""pop music"",""usage"":""tónlist""},{""meaning"":""popcorn"",""usage"":""poppkorn""}]}"
pottur "{""translations"":[{""meaning"":""pot"",""usage"":""ílát""},{""meaning"":""liter, (UK) litre"",""usage"":""mál""},{""meaning"":""chamber pot"",""usage"":""koppur""},{""meaning"":""pot, pool (of money)"",""usage"":""sjóður""},{""meaning"":""hot pool (small extra pool like a hot spring alongside a swimming pool)"",""usage"":""heitur pottur""},{""meaning"":""sth is well/badly prepared"",""usage"":""phrases""}]}"
rós "{""translations"":[{""meaning"":""rose"",""usage"":null}]}"
rúm "{""translations"":[{""meaning"":""bed"",""usage"":""rekkja""},{""meaning"":""area, space"",""usage"":""svæði""}]}"
rúta "{""translations"":[{""meaning"":""coach, bus"",""usage"":""bíll""},{""meaning"":""route"",""usage"":""leið""}]}"
safn "{""translations"":[{""meaning"":""collection"",""usage"":null},{""meaning"":""museum"",""usage"":""stofnun""},{""meaning"":""flock of sheep"",""usage"":""fjárhópur""}]}"
sagnorð "{""translations"":[{""meaning"":""verb"",""usage"":null}]}"
samband "{""translations"":[{""meaning"":""connection, contact"",""usage"":""tengsl""},{""meaning"":""relationship"",""usage"":""~~ fólks""},{""meaning"":""union, federation"",""usage"":""bandalag""}]}"
samloka "{""translations"":[{""meaning"":""sandwich"",""usage"":""brauðsneiðar""},{""meaning"":""shellfish"",""usage"":""skelfiskur""},{""meaning"":""they are inseparable"",""usage"":null}]}"
samúð "{""translations"":[{""meaning"":""sympathy, compassion"",""usage"":null}]}"
sjampó "{""translations"":[{""meaning"":""shampoo"",""usage"":null}]}"
skinka "{""translations"":[{""meaning"":""ham, smoked pork"",""usage"":null}]}"
skógur "{""translations"":[{""meaning"":""forest, wood"",""usage"":null}]}"
skór "{""translations"":[{""meaning"":""shoe"",""usage"":null}]}"
sonur "{""translations"":[{""meaning"":""son"",""usage"":null}]}"
spjall "{""translations"":[{""meaning"":""conversation, chat"",""usage"":null}]}"
steinn "{""translations"":[{""meaning"":""stone"",""usage"":null}]}"
stelpa "{""translations"":[{""meaning"":""girl"",""usage"":null}]}"
stjórnandi "{""translations"":[{""meaning"":""leader"",""usage"":""foringi""},{""meaning"":""conductor"",""usage"":""hljómsveitarstjóri""},{""meaning"":""directors, the management"",""usage"":null}]}"
stjórnmálamaður "{""translations"":[{""meaning"":""politician"",""usage"":null}]}"
strákur "{""translations"":[{""meaning"":""boy"",""usage"":null}]}"
stytta "{""translations"":[{""meaning"":""statue"",""usage"":null}]}"
stærðfræði "{""translations"":[{""meaning"":""math, mathematics"",""usage"":null}]}"
stóll "{""translations"":[{""meaning"":""chair"",""usage"":null}]}"
sumar "{""translations"":[{""meaning"":""summer"",""usage"":null}]}"
sundbolur "{""translations"":[{""meaning"":""swimsuit"",""usage"":null}]}"
sundföt "{""translations"":[{""meaning"":""bathing suit"",""usage"":null}]}"
sundgleraugu "{""translations"":[]}"
sundskýla "{""translations"":[{""meaning"":""swimming trunks"",""usage"":null}]}"
svefnpoki "{""translations"":[{""meaning"":""sleeping bag"",""usage"":null}]}"
svæði "{""translations"":[{""meaning"":""area, zone"",""usage"":null}]}"
systkini "{""translations"":[{""meaning"":""brothers and sisters, siblings"",""usage"":null}]}"
sápa "{""translations"":[{""meaning"":""soap"",""usage"":null}]}"
sími "{""translations"":[{""meaning"":""telephone"",""usage"":null}]}"
sólarolía "{""translations"":[{""meaning"":""suntan oil/lotion"",""usage"":null}]}"
sólbekkur "{""translations"":[{""meaning"":""window sill"",""usage"":null}]}"
söguþráður "{""translations"":[{""meaning"":""plot"",""usage"":null}]}"
söngkona "{""translations"":[{""meaning"":""singer (female)"",""usage"":null}]}"
söngvari "{""translations"":[{""meaning"":""singer"",""usage"":null}]}"
súpa "{""translations"":[{""meaning"":""soup"",""usage"":null}]}"
taska "{""translations"":[{""meaning"":""suitcase"",""usage"":""ferða~""},{""meaning"":""bag, handbag"",""usage"":""hand~""},{""meaning"":""briefcase, case, attaché case"",""usage"":""skjala~""},{""meaning"":""satchel"",""usage"":""skóla~""}]}"
torg "{""translations"":[{""meaning"":""(city) square"",""usage"":null}]}"
tækifæri "{""translations"":[{""meaning"":""opportunity"",""usage"":null}]}"
tónlist "{""translations"":[{""meaning"":""music"",""usage"":null}]}"
tónlistarmaður "{""translations"":[{""meaning"":""musician"",""usage"":""hljóðfæraleikari""},{""meaning"":""composer"",""usage"":""tónskáld""}]}"
tölva "{""translations"":[{""meaning"":""computer"",""usage"":null}]}"
tölvupóstur "{""translations"":[{""meaning"":""e-mail"",""usage"":null}]}"
undantekning "{""translations"":[{""meaning"":""exception"",""usage"":null}]}"
upplýsing "{""translations"":[{""meaning"":""information"",""usage"":null},{""meaning"":""Enlightenment"",""usage"":""fræðslustefna""},{""meaning"":""illumination, lighting"",""usage"":""það að lýsa upp""}]}"
uppáhald "{""translations"":[{""meaning"":""pet, favorite, (UK) favourite"",""usage"":null}]}"
vatn "{""translations"":[{""meaning"":""water"",""usage"":""lögur""},{""meaning"":""lake"",""usage"":""stöðu~""},{""meaning"":""they could not keep back their tears, they could not contain themselves"",""usage"":""phrases""}]}"
vefsíða "{""translations"":[{""meaning"":""web page"",""usage"":null}]}"
veitingahús "{""translations"":[{""meaning"":""restaurant"",""usage"":null}]}"
veitingastaður "{""translations"":[]}"
verkefni "{""translations"":[{""meaning"":""task, assignment, project"",""usage"":null}]}"
verðlaun "{""translations"":[{""meaning"":""prize, award"",""usage"":""sigurlaun""},{""meaning"":""reward"",""usage"":""laun""}]}"
vetur "{""translations"":[{""meaning"":""winter"",""usage"":null}]}"
vina "{""translations"":[{""meaning"":""girl friend"",""usage"":null}]}"
vinur "{""translations"":[{""meaning"":""friend"",""usage"":null}]}"
vor "{""translations"":[{""meaning"":""spring"",""usage"":null}]}"
vél "{""translations"":[{""meaning"":""motor, engine"",""usage"":""hreyfill""},{""meaning"":""machine"",""usage"":""tæki""}]}"
á "{""translations"":[{""meaning"":""river, stream"",""usage"":null}]}"
áhorfandi "{""translations"":[{""meaning"":""spectator, onlooker"",""usage"":null}]}"
æfing "{""translations"":[{""meaning"":""training, practice"",""usage"":""þjálfun""},{""meaning"":""exercise, drill"",""usage"":""þjálfunarverkefni""},{""meaning"":""rehearsal"",""usage"":""~ leikrits""},{""meaning"":""go to a training session"",""usage"":null}]}"
öld "{""translations"":[{""meaning"":""age"",""usage"":""tímabil""},{""meaning"":""century"",""usage"":""hundrað ár""},{""meaning"":""from time immemorial"",""usage"":""phrases""}]}"
þjóðlistasafn "{""translations"":[]}"
þjóðminjasafn "{""translations"":[{""meaning"":""national museum"",""usage"":null}]}"
þolfall "{""translations"":[{""meaning"":""accusative (case)"",""usage"":null}]}"
þágufall "{""translations"":[{""meaning"":""dative"",""usage"":null}]}"
1 afmælisveisla {"translations":[{"meaning":"birthday party","usage":null}]}
2 anddyri {"translations":[{"meaning":"entrance, vestibule","usage":null}]}
3 aðalhlutverk {"translations":[{"meaning":"main role","usage":null}]}
4 belti {"translations":[{"meaning":"belt","usage":"mittisól"},{"meaning":"zone","usage":"svæði"},{"meaning":"caterpillar tread","usage":"keðja"}]}
5 birta {"translations":[{"meaning":"light, brightness","usage":null}]}
6 blaðagrein {"translations":[{"meaning":"newspaper article","usage":null}]}
7 borg {"translations":[{"meaning":"city, town","usage":"bær"},{"meaning":"castle","usage":"kastali"},{"meaning":"rocky hill","usage":"klettahæð"},{"meaning":"shelter","usage":"byrgi"}]}
8 borð {"translations":[{"meaning":"table, desk","usage":"plata á fótum"},{"meaning":"plank, board","usage":"planki"},{"meaning":"go aboard, go on board","usage":"skipshlið"},{"meaning":"of the same caliber/(UK) calibre as sby","usage":"phrases"}]}
9 bróðir {"translations":[{"meaning":"brother","usage":null}]}
10 bíll {"translations":[{"meaning":"car, automobile","usage":null}]}
11 bíó {"translations":[{"meaning":"movie theater, (UK) cinema","usage":null}]}
12 bíómynd {"translations":[{"meaning":"film","usage":null}]}
13 bók {"translations":[{"meaning":"book","usage":null}]}
14 bókmenntafræði {"translations":[{"meaning":"literary studies, literature","usage":null}]}
15 dagblað {"translations":[{"meaning":"daily (news)paper, daily","usage":null}]}
16 dagur {"translations":[{"meaning":"day","usage":null}]}
17 dalur {"translations":[{"meaning":"valley, dale","usage":"lægð"},{"meaning":"dollar","usage":"mynt"}]}
18 diskur {"translations":[{"meaning":"plate","usage":null},{"meaning":"disk/disc","usage":"í tölvu"}]}
19 dót {"translations":[{"meaning":"luggage, things","usage":"farangur"},{"meaning":"toys","usage":"leikföng"},{"meaning":"rabble","usage":"hyski"}]}
20 eignarfall {"translations":[{"meaning":"genitive, possessive case","usage":null}]}
21 fangelsi {"translations":[{"meaning":"prison","usage":null}]}
22 farangur {"translations":[{"meaning":"luggage, baggage","usage":null}]}
23 ferð {"translations":[{"meaning":"trip, journey","usage":"för"},{"meaning":"speed","usage":"hraði"}]}
24 fjall {"translations":[{"meaning":"mountain","usage":null}]}
25 forrit {"translations":[{"meaning":"program, (UK) programme","usage":"tölvu~"},{"meaning":"exemplar","usage":"heimild, sem skrifað er eftir"}]}
26 forritari {"translations":[]}
27 framtíð {"translations":[{"meaning":"future","usage":null},{"meaning":"future tense","usage":"í málfr"}]}
28 frelsishetja {"translations":[{"meaning":"frredom champion","usage":null}]}
29 gaman {"translations":[{"meaning":"fun, enjoyment","usage":null}]}
30 gangstétt {"translations":[{"meaning":"sidewalk, (UK) pavement","usage":null}]}
31 gata {"translations":[{"meaning":"street, way, path","usage":null}]}
32 geisladiskur {"translations":[{"meaning":"compact disc, CD","usage":null}]}
33 grein {"translations":[{"meaning":"branch, bough","usage":"á tré"},{"meaning":"subject, field, speciality, specialty","usage":"fag"},{"meaning":"article","usage":"blaða~"},{"meaning":"paragraph","usage":"laga~"},{"meaning":"point","usage":"atriði"},{"meaning":"consideration","usage":"athugun"}]}
34 greiða {"translations":[{"meaning":"pay","usage":"borga"},{"meaning":"comb","usage":null}]}
35 gönguferð {"translations":[{"meaning":"walk, hike","usage":null}]}
36 handklæði {"translations":[{"meaning":"towel","usage":null}]}
37 handrit {"translations":[{"meaning":"manuscript","usage":null}]}
38 hangikjöt {"translations":[{"meaning":"smoked meat (esp lamb)","usage":null}]}
39 haust {"translations":[{"meaning":"fall, (UK) autumn","usage":null}]}
40 herbergi {"translations":[{"meaning":"room","usage":null}]}
41 hestur {"translations":[{"meaning":"horse","usage":null}]}
42 hlutur {"translations":[{"meaning":"thing, object","usage":"gripur"},{"meaning":"part, share","usage":"hluti"}]}
43 hlutverk {"translations":[{"meaning":"task","usage":"verkefni"},{"meaning":"mission, role","usage":"ætlunarverk"}]}
44 hreinleiki {"translations":[{"meaning":"purity","usage":null}]}
45 hálstafla {"translations":[]}
46 hár {"translations":[{"meaning":"hair","usage":null}]}
47 hárþurrka {"translations":[{"meaning":"dryer","usage":null}]}
48 hörkuvinna {"translations":[{"meaning":"(extremely) hard work","usage":null}]}
49 hús {"translations":[{"meaning":"house, home","usage":null}]}
50 innsetning {"translations":[{"meaning":"installation (as a work of art)","usage":null}]}
51 kennari {"translations":[{"meaning":"teacher","usage":null}]}
52 kongur {"translations":[{"meaning":"king","usage":null}]}
53 kort {"translations":[{"meaning":"map","usage":"landa~"},{"meaning":"postcard, card","usage":"bréfspjald"}]}
54 króna {"translations":[{"meaning":"króna, krone, crown (Icelandic unit of currency = 100 aurar)","usage":"peningur"},{"meaning":"tree-top, crown of a tree","usage":"trjátoppur"}]}
55 kvikmynd {"translations":[{"meaning":"film, movie","usage":null}]}
56 kvöldmatur {"translations":[{"meaning":"supper, dinner","usage":null}]}
57 kyrrð {"translations":[{"meaning":"silence, stillness","usage":"þögn"},{"meaning":"peace and quiet","usage":"ró"}]}
58 kóramót {"translations":[]}
59 leikstjóri {"translations":[{"meaning":"director (of a film, play)","usage":null}]}
60 leiðsögumaður {"translations":[{"meaning":"guide, travel guide","usage":null}]}
61 listamaður {"translations":[{"meaning":"artist","usage":null}]}
62 listasafn {"translations":[{"meaning":"art museum","usage":null}]}
63 listaverk {"translations":[{"meaning":"work of art","usage":null}]}
64 listfræðingur {"translations":[{"meaning":"art historian","usage":null}]}
65 litur {"translations":[{"meaning":"color, (UK) colour, hue","usage":"farfi"},{"meaning":"dye, coloring, (UK) colouring","usage":"litarefni"},{"meaning":"crayon","usage":"vaxlitur o.s.frv."},{"meaning":"suit (in cards)","usage":"í spilum"},{"meaning":"show interest in sth","usage":null}]}
66 líf {"translations":[{"meaning":"life","usage":null}]}
67 lýsingarorð {"translations":[{"meaning":"adjective","usage":null}]}
68 mappa {"translations":[{"meaning":"folder, file","usage":null}]}
69 matur {"translations":[{"meaning":"food","usage":null},{"meaning":"he knows how to cash in on everything","usage":null}]}
70 maður {"translations":[{"meaning":"person, human being, individual","usage":"manneskja"},{"meaning":"man","usage":"karlmaður"},{"meaning":"man!","usage":"óformlegt ávarp"},{"meaning":"husband","usage":"eiginmaður"},{"meaning":"piece (in chess)","usage":"í skák"},{"meaning":"one, you","usage":"fornafn"}]}
71 meistari {"translations":[{"meaning":"master, maestro (in music)","usage":null}]}
72 mikill {"translations":[{"meaning":"large, big","usage":"stór"},{"meaning":"much","usage":"um magn"},{"meaning":"great","usage":"stórkostlegur"}]}
73 miðbær {"translations":[{"meaning":"city center, downtown area, (UK) city centre","usage":null}]}
74 miði {"translations":[{"meaning":"slip of paper, note","usage":"seðill"},{"meaning":"ticket","usage":"aðgöngumiði"}]}
75 mynd {"translations":[{"meaning":"shape, form","usage":"lögun"},{"meaning":"photo(graph), picture, snapshot","usage":"ljósmynd"},{"meaning":"movie, (UK) film","usage":"bíómynd"},{"meaning":"painting, picture","usage":"málverk"},{"meaning":"illustration","usage":"myndskreyting"},{"meaning":"figure, diagram","usage":"skýringarmynd"},{"meaning":"voice (in grammar)","usage":"í málfr"},{"meaning":"image (metaphor, etc)","usage":"í skáldskap"},{"meaning":"this is poorly done","usage":"phrases"}]}
76 málverk {"translations":[{"meaning":"painting","usage":null}]}
77 mót {"translations":[{"meaning":"meeting, gathering","usage":"samkoma"},{"meaning":"tournament, meet","usage":"keppni"},{"meaning":"mould, form","usage":"form"},{"meaning":"joint","usage":"samskeyti"},{"meaning":"in many different ways","usage":"phrases"}]}
78 nafnorð {"translations":[{"meaning":"noun, substantive","usage":null}]}
79 nammi {"translations":[{"meaning":"candy, (UK) sweets (baby talk for sth good to eat as in‘yummy, yummy')","usage":null}]}
80 nefnifall {"translations":[{"meaning":"nominative, nominative case","usage":null}]}
81 nemandi {"translations":[{"meaning":"student, pupil","usage":null}]}
82 nóta {"translations":[{"meaning":"note","usage":"í músík"},{"meaning":"bill","usage":"reikningur"},{"meaning":"receipt","usage":"kvittun"},{"meaning":"comment, note","usage":"athugasemd"},{"meaning":"be with it, know what is going on","usage":null}]}
83 ostur {"translations":[{"meaning":"cheese","usage":null}]}
84 persóna {"translations":[{"meaning":"person","usage":"einstaklingur"},{"meaning":"personality","usage":"persónuleiki"},{"meaning":"character","usage":"~~ í skáldverki"}]}
85 peysa {"translations":[{"meaning":"sweater, (UK) jersey","usage":"ullarpeysa"},{"meaning":"blouse (of the woman's Icelandic national costume)","usage":"peysufatapeysa"}]}
86 piltur {"translations":[{"meaning":"boy, young man","usage":null}]}
87 popp {"translations":[{"meaning":"pop music","usage":"tónlist"},{"meaning":"popcorn","usage":"poppkorn"}]}
88 pottur {"translations":[{"meaning":"pot","usage":"ílát"},{"meaning":"liter, (UK) litre","usage":"mál"},{"meaning":"chamber pot","usage":"koppur"},{"meaning":"pot, pool (of money)","usage":"sjóður"},{"meaning":"hot pool (small extra pool like a hot spring alongside a swimming pool)","usage":"heitur pottur"},{"meaning":"sth is well/badly prepared","usage":"phrases"}]}
89 rós {"translations":[{"meaning":"rose","usage":null}]}
90 rúm {"translations":[{"meaning":"bed","usage":"rekkja"},{"meaning":"area, space","usage":"svæði"}]}
91 rúta {"translations":[{"meaning":"coach, bus","usage":"bíll"},{"meaning":"route","usage":"leið"}]}
92 safn {"translations":[{"meaning":"collection","usage":null},{"meaning":"museum","usage":"stofnun"},{"meaning":"flock of sheep","usage":"fjárhópur"}]}
93 sagnorð {"translations":[{"meaning":"verb","usage":null}]}
94 samband {"translations":[{"meaning":"connection, contact","usage":"tengsl"},{"meaning":"relationship","usage":"~~ fólks"},{"meaning":"union, federation","usage":"bandalag"}]}
95 samloka {"translations":[{"meaning":"sandwich","usage":"brauðsneiðar"},{"meaning":"shellfish","usage":"skelfiskur"},{"meaning":"they are inseparable","usage":null}]}
96 samúð {"translations":[{"meaning":"sympathy, compassion","usage":null}]}
97 sjampó {"translations":[{"meaning":"shampoo","usage":null}]}
98 skinka {"translations":[{"meaning":"ham, smoked pork","usage":null}]}
99 skógur {"translations":[{"meaning":"forest, wood","usage":null}]}
100 skór {"translations":[{"meaning":"shoe","usage":null}]}
101 sonur {"translations":[{"meaning":"son","usage":null}]}
102 spjall {"translations":[{"meaning":"conversation, chat","usage":null}]}
103 steinn {"translations":[{"meaning":"stone","usage":null}]}
104 stelpa {"translations":[{"meaning":"girl","usage":null}]}
105 stjórnandi {"translations":[{"meaning":"leader","usage":"foringi"},{"meaning":"conductor","usage":"hljómsveitarstjóri"},{"meaning":"directors, the management","usage":null}]}
106 stjórnmálamaður {"translations":[{"meaning":"politician","usage":null}]}
107 strákur {"translations":[{"meaning":"boy","usage":null}]}
108 stytta {"translations":[{"meaning":"statue","usage":null}]}
109 stærðfræði {"translations":[{"meaning":"math, mathematics","usage":null}]}
110 stóll {"translations":[{"meaning":"chair","usage":null}]}
111 sumar {"translations":[{"meaning":"summer","usage":null}]}
112 sundbolur {"translations":[{"meaning":"swimsuit","usage":null}]}
113 sundföt {"translations":[{"meaning":"bathing suit","usage":null}]}
114 sundgleraugu {"translations":[]}
115 sundskýla {"translations":[{"meaning":"swimming trunks","usage":null}]}
116 svefnpoki {"translations":[{"meaning":"sleeping bag","usage":null}]}
117 svæði {"translations":[{"meaning":"area, zone","usage":null}]}
118 systkini {"translations":[{"meaning":"brothers and sisters, siblings","usage":null}]}
119 sápa {"translations":[{"meaning":"soap","usage":null}]}
120 sími {"translations":[{"meaning":"telephone","usage":null}]}
121 sólarolía {"translations":[{"meaning":"suntan oil/lotion","usage":null}]}
122 sólbekkur {"translations":[{"meaning":"window sill","usage":null}]}
123 söguþráður {"translations":[{"meaning":"plot","usage":null}]}
124 söngkona {"translations":[{"meaning":"singer (female)","usage":null}]}
125 söngvari {"translations":[{"meaning":"singer","usage":null}]}
126 súpa {"translations":[{"meaning":"soup","usage":null}]}
127 taska {"translations":[{"meaning":"suitcase","usage":"ferða~"},{"meaning":"bag, handbag","usage":"hand~"},{"meaning":"briefcase, case, attaché case","usage":"skjala~"},{"meaning":"satchel","usage":"skóla~"}]}
128 torg {"translations":[{"meaning":"(city) square","usage":null}]}
129 tækifæri {"translations":[{"meaning":"opportunity","usage":null}]}
130 tónlist {"translations":[{"meaning":"music","usage":null}]}
131 tónlistarmaður {"translations":[{"meaning":"musician","usage":"hljóðfæraleikari"},{"meaning":"composer","usage":"tónskáld"}]}
132 tölva {"translations":[{"meaning":"computer","usage":null}]}
133 tölvupóstur {"translations":[{"meaning":"e-mail","usage":null}]}
134 undantekning {"translations":[{"meaning":"exception","usage":null}]}
135 upplýsing {"translations":[{"meaning":"information","usage":null},{"meaning":"Enlightenment","usage":"fræðslustefna"},{"meaning":"illumination, lighting","usage":"það að lýsa upp"}]}
136 uppáhald {"translations":[{"meaning":"pet, favorite, (UK) favourite","usage":null}]}
137 vatn {"translations":[{"meaning":"water","usage":"lögur"},{"meaning":"lake","usage":"stöðu~"},{"meaning":"they could not keep back their tears, they could not contain themselves","usage":"phrases"}]}
138 vefsíða {"translations":[{"meaning":"web page","usage":null}]}
139 veitingahús {"translations":[{"meaning":"restaurant","usage":null}]}
140 veitingastaður {"translations":[]}
141 verkefni {"translations":[{"meaning":"task, assignment, project","usage":null}]}
142 verðlaun {"translations":[{"meaning":"prize, award","usage":"sigurlaun"},{"meaning":"reward","usage":"laun"}]}
143 vetur {"translations":[{"meaning":"winter","usage":null}]}
144 vina {"translations":[{"meaning":"girl friend","usage":null}]}
145 vinur {"translations":[{"meaning":"friend","usage":null}]}
146 vor {"translations":[{"meaning":"spring","usage":null}]}
147 vél {"translations":[{"meaning":"motor, engine","usage":"hreyfill"},{"meaning":"machine","usage":"tæki"}]}
148 á {"translations":[{"meaning":"river, stream","usage":null}]}
149 áhorfandi {"translations":[{"meaning":"spectator, onlooker","usage":null}]}
150 æfing {"translations":[{"meaning":"training, practice","usage":"þjálfun"},{"meaning":"exercise, drill","usage":"þjálfunarverkefni"},{"meaning":"rehearsal","usage":"~ leikrits"},{"meaning":"go to a training session","usage":null}]}
151 öld {"translations":[{"meaning":"age","usage":"tímabil"},{"meaning":"century","usage":"hundrað ár"},{"meaning":"from time immemorial","usage":"phrases"}]}
152 þjóðlistasafn {"translations":[]}
153 þjóðminjasafn {"translations":[{"meaning":"national museum","usage":null}]}
154 þolfall {"translations":[{"meaning":"accusative (case)","usage":null}]}
155 þágufall {"translations":[{"meaning":"dative","usage":null}]}

234
sample-data/wordlist.txt Normal file
View File

@ -0,0 +1,234 @@
afmælisveisla noun
anddyri noun
aðalhlutverk noun
belti noun
birta noun
blaðagrein noun
borg noun
borð noun
bróðir noun
bíll noun
bíó noun
bíómynd noun
bók noun
bókmenntafræði noun
dagblað noun
dagur noun
dalur noun
diskur noun
dót noun
eignarfall noun
fangelsi noun
farangur noun
ferð noun
fjall noun
forrit noun
forritari noun
framtíð noun
frelsishetja noun
gaman noun
gangstétt noun
gata noun
geisladiskur noun
grein noun
greiða noun
gönguferð noun
handklæði noun
handrit noun
hangikjöt noun
haust noun
herbergi noun
hestur noun
hlutur noun
hlutverk noun
hreinleiki noun
hálstafla noun
hár noun
hárþurrka noun
hörkuvinna noun
hús noun
innsetning noun
kennari noun
kongur noun
kort noun
króna noun
kvikmynd noun
kvöldmatur noun
kyrrð noun
kóramót noun
leikstjóri noun
leiðsögumaður noun
listamaður noun
listasafn noun
listaverk noun
listfræðingur noun
litur noun
líf noun
lýsingarorð noun
mappa noun
matur noun
maður noun
meistari noun
mikill noun
miðbær noun
miði noun
mynd noun
málverk noun
mót noun
nafnorð noun
nammi noun
nefnifall noun
nemandi noun
nóta noun
ostur noun
persóna noun
peysa noun
piltur noun
popp noun
pottur noun
rós noun
rúm noun
rúta noun
safn noun
sagnorð noun
samband noun
samloka noun
samúð noun
sjampó noun
skinka noun
skógur noun
skór noun
sonur noun
spjall noun
steinn noun
stelpa noun
stjórnandi noun
stjórnmálamaður noun
strákur noun
stytta noun
stærðfræði noun
stóll noun
sumar noun
sundbolur noun
sundföt noun
sundgleraugu noun
sundskýla noun
svefnpoki noun
svæði noun
systkini noun
sápa noun
sími noun
sólarolía noun
sólbekkur noun
söguþráður noun
söngkona noun
söngvari noun
súpa noun
taska noun
torg noun
tækifæri noun
tónlist noun
tónlistarmaður noun
tölva noun
tölvupóstur noun
undantekning noun
upplýsing noun
uppáhald noun
vatn noun
vefsíða noun
veitingahús noun
veitingastaður noun
verkefni noun
verðlaun noun
vetur noun
vina noun
vinur noun
vor noun
vél noun
á noun
áhorfandi noun
æfing noun
öld noun
þjóðlistasafn noun
þjóðminjasafn noun
þolfall noun
þágufall noun
alþjóðlegur adjective
appelsínugulur adjective
auðveldur adjective
bjartur adjective
bleikur adjective
blár adjective
brúnn adjective
dapur adjective
dimmur adjective
duglegur adjective
erfiður adjective
fallegur adjective
fjólublár adjective
fjölbreyttur adjective
flestur adjective
frekur adjective
frábær adjective
frægur adjective
fróður adjective
fyndinn adjective
félagslyndur adjective
gamall adjective
glaður adjective
glæsilegur adjective
grár adjective
grænn adjective
gulur adjective
gáfaður adjective
hamingjusamur adjective
heimsfrægur adjective
heimskur adjective
heitur adjective
hlýr adjective
hreinn adjective
hress adjective
hvítur adjective
hæfileikaríkur adjective
hægur adjective
kaldur adjective
kveðinn adjective
kvíðinn adjective
kátur adjective
latur adjective
leiðinlegur adjective
ljótur adjective
léttur adjective
lítill adjective
margur adjective
nógur adjective
nýlegur adjective
nýr adjective
rauður adjective
rólegur adjective
saddur adjective
skemmtilegur adjective
skýr adjective
sorglegur adjective
spennandi adjective
spenntur adjective
stórkostlegur adjective
svangur adjective
svartur adjective
svolítill adjective
sérstakur adjective
tilbúinn adjective
ungur adjective
vinsæll adjective
vondur adjective
yndislegur adjective
áhugasamur adjective
ánægjulegur adjective
ótrúlegur adjective
óvinsæll adjective
óþekktur adjective
örugglega adjective
þreyttur adjective
þröngur adjective
þunglyndur adjective
þyrstur adjective

698
src/bindata.rs Normal file
View File

@ -0,0 +1,698 @@
use crate::ProgramError;
use csv::ReaderBuilder;
use std::collections::BTreeMap;
use std::io::Read;
#[derive(Debug, Eq, PartialEq)]
pub struct BinEntry {
pub id: u64,
pub word_class: String,
pub classification: String,
pub form: String,
pub tag: String,
}
#[derive(Debug, Eq, PartialEq)]
pub enum Gender {
Masculine,
Feminine,
Neuter,
}
#[derive(Debug, Eq, PartialEq)]
pub struct NounEntry {
pub gender: Gender,
pub nom_sg: Option<String>,
pub acc_sg: Option<String>,
pub dat_sg: Option<String>,
pub gen_sg: Option<String>,
pub nom_pl: Option<String>,
pub acc_pl: Option<String>,
pub dat_pl: Option<String>,
pub gen_pl: Option<String>,
pub nom_sg_def: Option<String>,
pub acc_sg_def: Option<String>,
pub dat_sg_def: Option<String>,
pub gen_sg_def: Option<String>,
pub nom_pl_def: Option<String>,
pub acc_pl_def: Option<String>,
pub dat_pl_def: Option<String>,
pub gen_pl_def: Option<String>,
}
#[derive(Debug, Eq, PartialEq)]
pub struct AdjectiveEntry {
pub masc_nom_sg_strong: Option<String>,
pub masc_acc_sg_strong: Option<String>,
pub masc_dat_sg_strong: Option<String>,
pub masc_gen_sg_strong: Option<String>,
pub fem_nom_sg_strong: Option<String>,
pub fem_acc_sg_strong: Option<String>,
pub fem_dat_sg_strong: Option<String>,
pub fem_gen_sg_strong: Option<String>,
pub neut_nom_sg_strong: Option<String>,
pub neut_acc_sg_strong: Option<String>,
pub neut_dat_sg_strong: Option<String>,
pub neut_gen_sg_strong: Option<String>,
pub masc_nom_pl_strong: Option<String>,
pub masc_acc_pl_strong: Option<String>,
pub masc_dat_pl_strong: Option<String>,
pub masc_gen_pl_strong: Option<String>,
pub fem_nom_pl_strong: Option<String>,
pub fem_acc_pl_strong: Option<String>,
pub fem_dat_pl_strong: Option<String>,
pub fem_gen_pl_strong: Option<String>,
pub neut_nom_pl_strong: Option<String>,
pub neut_acc_pl_strong: Option<String>,
pub neut_dat_pl_strong: Option<String>,
pub neut_gen_pl_strong: Option<String>,
pub masc_nom_sg_weak: Option<String>,
pub masc_acc_sg_weak: Option<String>,
pub masc_dat_sg_weak: Option<String>,
pub masc_gen_sg_weak: Option<String>,
pub fem_nom_sg_weak: Option<String>,
pub fem_acc_sg_weak: Option<String>,
pub fem_dat_sg_weak: Option<String>,
pub fem_gen_sg_weak: Option<String>,
pub neut_nom_sg_weak: Option<String>,
pub neut_acc_sg_weak: Option<String>,
pub neut_dat_sg_weak: Option<String>,
pub neut_gen_sg_weak: Option<String>,
pub masc_nom_pl_weak: Option<String>,
pub masc_acc_pl_weak: Option<String>,
pub masc_dat_pl_weak: Option<String>,
pub masc_gen_pl_weak: Option<String>,
pub fem_nom_pl_weak: Option<String>,
pub fem_acc_pl_weak: Option<String>,
pub fem_dat_pl_weak: Option<String>,
pub fem_gen_pl_weak: Option<String>,
pub neut_nom_pl_weak: Option<String>,
pub neut_acc_pl_weak: Option<String>,
pub neut_dat_pl_weak: Option<String>,
pub neut_gen_pl_weak: Option<String>,
}
pub struct BinData {
pub data: BTreeMap<String, Vec<BinEntry>>,
}
impl BinData {
pub fn load<T>(reader: T) -> Result<Box<Self>, ProgramError>
where
T: Read,
{
let mut bin_data = Box::new(BinData { data: BTreeMap::new() });
let mut db_reader =
ReaderBuilder::new().has_headers(false).delimiter(b';').from_reader(reader);
for result in db_reader.records() {
let record = result?;
let lemma = record.get(0).unwrap().to_string();
let id = record.get(1).unwrap().parse::<u64>().unwrap();
let word_class = record.get(2).unwrap().to_string();
let classification = record.get(3).unwrap().to_string();
let form = record.get(4).unwrap().to_string();
let tag = record.get(5).unwrap().to_string();
let entry = bin_data.data.entry(lemma).or_insert_with(Vec::new);
entry.push(BinEntry { id, word_class, classification, form, tag });
}
Ok(bin_data)
}
pub fn adjective(&self, root: &str) -> Option<AdjectiveEntry> {
let entries = self.data.get(root);
match entries {
Some(entries) => {
let entries =
entries.iter().filter(|&e| is_adjective(e)).collect::<Vec<&BinEntry>>();
if entries.is_empty() {
None
} else {
Some(AdjectiveEntry {
masc_nom_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-NFET")
.map(|&e| e.form.to_string()),
masc_acc_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-ÞFET")
.map(|&e| e.form.to_string()),
masc_dat_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-ÞGFET")
.map(|&e| e.form.to_string()),
masc_gen_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-EFET")
.map(|&e| e.form.to_string()),
fem_nom_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-NFET")
.map(|&e| e.form.to_string()),
fem_acc_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-ÞFET")
.map(|&e| e.form.to_string()),
fem_dat_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-ÞGFET")
.map(|&e| e.form.to_string()),
fem_gen_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-EFET")
.map(|&e| e.form.to_string()),
neut_nom_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-NFET")
.map(|&e| e.form.to_string()),
neut_acc_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-ÞFET")
.map(|&e| e.form.to_string()),
neut_dat_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-ÞGFET")
.map(|&e| e.form.to_string()),
neut_gen_sg_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-EFET")
.map(|&e| e.form.to_string()),
masc_nom_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-NFFT")
.map(|&e| e.form.to_string()),
masc_acc_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-ÞFFT")
.map(|&e| e.form.to_string()),
masc_dat_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-ÞGFFT")
.map(|&e| e.form.to_string()),
masc_gen_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KK-EFFT")
.map(|&e| e.form.to_string()),
fem_nom_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-NFFT")
.map(|&e| e.form.to_string()),
fem_acc_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-ÞFFT")
.map(|&e| e.form.to_string()),
fem_dat_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-ÞGFFT")
.map(|&e| e.form.to_string()),
fem_gen_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-KVK-EFFT")
.map(|&e| e.form.to_string()),
neut_nom_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-NFFT")
.map(|&e| e.form.to_string()),
neut_acc_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-ÞFFT")
.map(|&e| e.form.to_string()),
neut_dat_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-ÞGFFT")
.map(|&e| e.form.to_string()),
neut_gen_pl_strong: entries
.iter()
.find(|&&e| e.tag == "FSB-HK-EFFT")
.map(|&e| e.form.to_string()),
masc_nom_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-NFET")
.map(|&e| e.form.to_string()),
masc_acc_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-ÞFET")
.map(|&e| e.form.to_string()),
masc_dat_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-ÞGFET")
.map(|&e| e.form.to_string()),
masc_gen_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-EFET")
.map(|&e| e.form.to_string()),
fem_nom_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-NFET")
.map(|&e| e.form.to_string()),
fem_acc_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-ÞFET")
.map(|&e| e.form.to_string()),
fem_dat_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-ÞGFET")
.map(|&e| e.form.to_string()),
fem_gen_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-EFET")
.map(|&e| e.form.to_string()),
neut_nom_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-NFET")
.map(|&e| e.form.to_string()),
neut_acc_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-ÞFET")
.map(|&e| e.form.to_string()),
neut_dat_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-ÞGFET")
.map(|&e| e.form.to_string()),
neut_gen_sg_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-EFET")
.map(|&e| e.form.to_string()),
masc_nom_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-NFFT")
.map(|&e| e.form.to_string()),
masc_acc_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-ÞFFT")
.map(|&e| e.form.to_string()),
masc_dat_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-ÞGFFT")
.map(|&e| e.form.to_string()),
masc_gen_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KK-EFFT")
.map(|&e| e.form.to_string()),
fem_nom_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-NFFT")
.map(|&e| e.form.to_string()),
fem_acc_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-ÞFFT")
.map(|&e| e.form.to_string()),
fem_dat_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-ÞGFFT")
.map(|&e| e.form.to_string()),
fem_gen_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-KVK-EFFT")
.map(|&e| e.form.to_string()),
neut_nom_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-NFFT")
.map(|&e| e.form.to_string()),
neut_acc_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-ÞFFT")
.map(|&e| e.form.to_string()),
neut_dat_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-ÞGFFT")
.map(|&e| e.form.to_string()),
neut_gen_pl_weak: entries
.iter()
.find(|&&e| e.tag == "FVB-HK-EFFT")
.map(|&e| e.form.to_string()),
})
}
}
None => None,
}
}
pub fn noun(&self, root: &str) -> Option<NounEntry> {
let entries = self.data.get(root);
match entries {
Some(entries) => {
let entries = entries.iter().filter(|&f| is_noun(f)).collect::<Vec<&BinEntry>>();
if entries.is_empty() {
None
} else {
let gender = entries.first().unwrap().word_class.as_str();
Some(NounEntry {
gender: match gender {
"kvk" => Gender::Feminine,
"hk" => Gender::Neuter,
_ => Gender::Masculine,
},
nom_sg: entries
.iter()
.find(|&&e| e.tag == "NFET")
.map(|&e| e.form.to_string()),
acc_sg: entries
.iter()
.find(|&&e| e.tag == "ÞFET")
.map(|&e| e.form.to_string()),
dat_sg: entries
.iter()
.find(|&&e| e.tag == "ÞGFET")
.map(|&e| e.form.to_string()),
gen_sg: entries
.iter()
.find(|&&e| e.tag == "EFET")
.map(|&e| e.form.to_string()),
nom_pl: entries
.iter()
.find(|&&e| e.tag == "NFFT")
.map(|&e| e.form.to_string()),
acc_pl: entries
.iter()
.find(|&&e| e.tag == "ÞFFT")
.map(|&e| e.form.to_string()),
dat_pl: entries
.iter()
.find(|&&e| e.tag == "ÞGFFT")
.map(|&e| e.form.to_string()),
gen_pl: entries
.iter()
.find(|&&e| e.tag == "EFFT")
.map(|&e| e.form.to_string()),
nom_sg_def: entries
.iter()
.find(|&&e| e.tag == "NFETgr")
.map(|&e| e.form.to_string()),
acc_sg_def: entries
.iter()
.find(|&&e| e.tag == "ÞFETgr")
.map(|&e| e.form.to_string()),
dat_sg_def: entries
.iter()
.find(|&&e| e.tag == "ÞGFETgr")
.map(|&e| e.form.to_string()),
gen_sg_def: entries
.iter()
.find(|&&e| e.tag == "EFETgr")
.map(|&e| e.form.to_string()),
nom_pl_def: entries
.iter()
.find(|&&e| e.tag == "NFFTgr")
.map(|&e| e.form.to_string()),
acc_pl_def: entries
.iter()
.find(|&&e| e.tag == "ÞFFTgr")
.map(|&e| e.form.to_string()),
dat_pl_def: entries
.iter()
.find(|&&e| e.tag == "ÞGFFTgr")
.map(|&e| e.form.to_string()),
gen_pl_def: entries
.iter()
.find(|&&e| e.tag == "EFFTgr")
.map(|&e| e.form.to_string()),
})
}
}
None => None,
}
}
}
fn is_adjective(entry: &BinEntry) -> bool {
entry.word_class == "lo"
}
fn is_noun(entry: &BinEntry) -> bool {
entry.word_class == "kk" || entry.word_class == "kvk" || entry.word_class == "hk"
}
#[cfg(test)]
mod tests {
use super::*;
const TEST_DATA: &str = "aðalhellir;74631;kk;alm;aðalhellir;NFET
aðalhellir;74631;kk;alm;aðalhellirinn;NFETgr
aðalhellir;74631;kk;alm;aðalhelli;ÞFET
aðalhellir;74631;kk;alm;aðalhellinn;ÞFETgr
aðalhellir;74631;kk;alm;aðalhelli;ÞGFET
aðalhellir;74631;kk;alm;aðalhellinum;ÞGFETgr
aðalhellir;74631;kk;alm;aðalhellis;EFET
aðalhellir;74631;kk;alm;aðalhellisins;EFETgr
aðalhellir;74631;kk;alm;aðalhellar;NFFT
aðalhellir;74631;kk;alm;aðalhellarnir;NFFTgr
aðalhellir;74631;kk;alm;aðalhella;ÞFFT
aðalhellir;74631;kk;alm;aðalhellana;ÞFFTgr
aðalhellir;74631;kk;alm;aðalhellum;ÞGFFT
aðalhellir;74631;kk;alm;aðalhellunum;ÞGFFTgr
aðalhellir;74631;kk;alm;aðalhella;EFFT
aðalhellir;74631;kk;alm;aðalhellanna;EFFTgr
aðalhenda;153961;kvk;alm;aðalhenda;NFET
aðalhenda;153961;kvk;alm;aðalhendan;NFETgr
aðalhenda;153961;kvk;alm;aðalhendu;ÞFET
aðalhenda;153961;kvk;alm;aðalhenduna;ÞFETgr
aðalhenda;153961;kvk;alm;aðalhendu;ÞGFET
aðalhenda;153961;kvk;alm;aðalhendunni;ÞGFETgr
aðalhenda;153961;kvk;alm;aðalhendu;EFET
aðalhenda;153961;kvk;alm;aðalhendunnar;EFETgr
aðalhenda;153961;kvk;alm;aðalhendur;NFFT
aðalhenda;153961;kvk;alm;aðalhendurnar;NFFTgr
aðalhenda;153961;kvk;alm;aðalhendur;ÞFFT
aðalhenda;153961;kvk;alm;aðalhendurnar;ÞFFTgr
aðalhenda;153961;kvk;alm;aðalhendum;ÞGFFT
aðalhenda;153961;kvk;alm;aðalhendunum;ÞGFFTgr
aðalhenda;153961;kvk;alm;aðalhendna;EFFT
aðalhenda;153961;kvk;alm;aðalhenda;EFFT2
aðalhenda;153961;kvk;alm;aðalhendnanna;EFFTgr
aðalhenda;153961;kvk;alm;aðalhendanna;EFFTgr2
fallegur;168136;lo;alm;fallegur;FSB-KK-NFET
fallegur;168136;lo;alm;fallegan;FSB-KK-ÞFET
fallegur;168136;lo;alm;fallegum;FSB-KK-ÞGFET
fallegur;168136;lo;alm;fallegs;FSB-KK-EFET
fallegur;168136;lo;alm;fallegir;FSB-KK-NFFT
fallegur;168136;lo;alm;fallega;FSB-KK-ÞFFT
fallegur;168136;lo;alm;fallegum;FSB-KK-ÞGFFT
fallegur;168136;lo;alm;fallegra;FSB-KK-EFFT
fallegur;168136;lo;alm;falleg;FSB-KVK-NFET
fallegur;168136;lo;alm;fallega;FSB-KVK-ÞFET
fallegur;168136;lo;alm;fallegri;FSB-KVK-ÞGFET
fallegur;168136;lo;alm;fallegrar;FSB-KVK-EFET
fallegur;168136;lo;alm;fallegar;FSB-KVK-NFFT
fallegur;168136;lo;alm;fallegar;FSB-KVK-ÞFFT
fallegur;168136;lo;alm;fallegum;FSB-KVK-ÞGFFT
fallegur;168136;lo;alm;fallegra;FSB-KVK-EFFT
fallegur;168136;lo;alm;fallegt;FSB-HK-NFET
fallegur;168136;lo;alm;fallegt;FSB-HK-ÞFET
fallegur;168136;lo;alm;fallegu;FSB-HK-ÞGFET
fallegur;168136;lo;alm;fallegs;FSB-HK-EFET
fallegur;168136;lo;alm;falleg;FSB-HK-NFFT
fallegur;168136;lo;alm;falleg;FSB-HK-ÞFFT
fallegur;168136;lo;alm;fallegum;FSB-HK-ÞGFFT
fallegur;168136;lo;alm;fallegra;FSB-HK-EFFT
fallegur;168136;lo;alm;fallegi;FVB-KK-NFET
fallegur;168136;lo;alm;fallega;FVB-KK-ÞFET
fallegur;168136;lo;alm;fallega;FVB-KK-ÞGFET
fallegur;168136;lo;alm;fallega;FVB-KK-EFET
fallegur;168136;lo;alm;fallegu;FVB-KK-NFFT
fallegur;168136;lo;alm;fallegu;FVB-KK-ÞFFT
fallegur;168136;lo;alm;fallegu;FVB-KK-ÞGFFT
fallegur;168136;lo;alm;fallegu;FVB-KK-EFFT
fallegur;168136;lo;alm;fallega;FVB-KVK-NFET
fallegur;168136;lo;alm;fallegu;FVB-KVK-ÞFET
fallegur;168136;lo;alm;fallegu;FVB-KVK-ÞGFET
fallegur;168136;lo;alm;fallegu;FVB-KVK-EFET
fallegur;168136;lo;alm;fallegu;FVB-KVK-NFFT
fallegur;168136;lo;alm;fallegu;FVB-KVK-ÞFFT
fallegur;168136;lo;alm;fallegu;FVB-KVK-ÞGFFT
fallegur;168136;lo;alm;fallegu;FVB-KVK-EFFT
fallegur;168136;lo;alm;fallega;FVB-HK-NFET
fallegur;168136;lo;alm;fallega;FVB-HK-ÞFET
fallegur;168136;lo;alm;fallega;FVB-HK-ÞGFET
fallegur;168136;lo;alm;fallega;FVB-HK-EFET
fallegur;168136;lo;alm;fallegu;FVB-HK-NFFT
fallegur;168136;lo;alm;fallegu;FVB-HK-ÞFFT
fallegur;168136;lo;alm;fallegu;FVB-HK-ÞGFFT
fallegur;168136;lo;alm;fallegu;FVB-HK-EFFT
fallegur;168136;lo;alm;fallegri;MST-KK-NFET
fallegur;168136;lo;alm;fallegri;MST-KK-ÞFET
fallegur;168136;lo;alm;fallegri;MST-KK-ÞGFET
fallegur;168136;lo;alm;fallegri;MST-KK-EFET
fallegur;168136;lo;alm;fallegri;MST-KK-NFFT
fallegur;168136;lo;alm;fallegri;MST-KK-ÞFFT
fallegur;168136;lo;alm;fallegri;MST-KK-ÞGFFT
fallegur;168136;lo;alm;fallegri;MST-KK-EFFT
fallegur;168136;lo;alm;fallegri;MST-KVK-NFET
fallegur;168136;lo;alm;fallegri;MST-KVK-ÞFET
fallegur;168136;lo;alm;fallegri;MST-KVK-ÞGFET
fallegur;168136;lo;alm;fallegri;MST-KVK-EFET
fallegur;168136;lo;alm;fallegri;MST-KVK-NFFT
fallegur;168136;lo;alm;fallegri;MST-KVK-ÞFFT
fallegur;168136;lo;alm;fallegri;MST-KVK-ÞGFFT
fallegur;168136;lo;alm;fallegri;MST-KVK-EFFT
fallegur;168136;lo;alm;fallegra;MST-HK-NFET
fallegur;168136;lo;alm;fallegra;MST-HK-ÞFET
fallegur;168136;lo;alm;fallegra;MST-HK-ÞGFET
fallegur;168136;lo;alm;fallegra;MST-HK-EFET
fallegur;168136;lo;alm;fallegri;MST-HK-NFFT
fallegur;168136;lo;alm;fallegri;MST-HK-ÞFFT
fallegur;168136;lo;alm;fallegri;MST-HK-ÞGFFT
fallegur;168136;lo;alm;fallegri;MST-HK-EFFT
fallegur;168136;lo;alm;fallegastur;ESB-KK-NFET
fallegur;168136;lo;alm;fallegastan;ESB-KK-ÞFET
fallegur;168136;lo;alm;fallegustum;ESB-KK-ÞGFET
fallegur;168136;lo;alm;fallegasts;ESB-KK-EFET
fallegur;168136;lo;alm;fallegastir;ESB-KK-NFFT
fallegur;168136;lo;alm;fallegasta;ESB-KK-ÞFFT
fallegur;168136;lo;alm;fallegustum;ESB-KK-ÞGFFT
fallegur;168136;lo;alm;fallegastra;ESB-KK-EFFT
fallegur;168136;lo;alm;fallegust;ESB-KVK-NFET
fallegur;168136;lo;alm;fallegasta;ESB-KVK-ÞFET
fallegur;168136;lo;alm;fallegastri;ESB-KVK-ÞGFET
fallegur;168136;lo;alm;fallegastrar;ESB-KVK-EFET
fallegur;168136;lo;alm;fallegastar;ESB-KVK-NFFT
fallegur;168136;lo;alm;fallegastar;ESB-KVK-ÞFFT
fallegur;168136;lo;alm;fallegustum;ESB-KVK-ÞGFFT
fallegur;168136;lo;alm;fallegastra;ESB-KVK-EFFT
fallegur;168136;lo;alm;fallegast;ESB-HK-NFET
fallegur;168136;lo;alm;fallegast;ESB-HK-ÞFET
fallegur;168136;lo;alm;fallegustu;ESB-HK-ÞGFET
fallegur;168136;lo;alm;fallegasts;ESB-HK-EFET
fallegur;168136;lo;alm;fallegust;ESB-HK-NFFT
fallegur;168136;lo;alm;fallegust;ESB-HK-ÞFFT
fallegur;168136;lo;alm;fallegustum;ESB-HK-ÞGFFT
fallegur;168136;lo;alm;fallegastra;ESB-HK-EFFT
fallegur;168136;lo;alm;fallegasti;EVB-KK-NFET
fallegur;168136;lo;alm;fallegasta;EVB-KK-ÞFET
fallegur;168136;lo;alm;fallegasta;EVB-KK-ÞGFET
fallegur;168136;lo;alm;fallegasta;EVB-KK-EFET
fallegur;168136;lo;alm;fallegustu;EVB-KK-NFFT
fallegur;168136;lo;alm;fallegustu;EVB-KK-ÞFFT
fallegur;168136;lo;alm;fallegustu;EVB-KK-ÞGFFT
fallegur;168136;lo;alm;fallegustu;EVB-KK-EFFT
fallegur;168136;lo;alm;fallegasta;EVB-KVK-NFET
fallegur;168136;lo;alm;fallegustu;EVB-KVK-ÞFET
fallegur;168136;lo;alm;fallegustu;EVB-KVK-ÞGFET
fallegur;168136;lo;alm;fallegustu;EVB-KVK-EFET
fallegur;168136;lo;alm;fallegustu;EVB-KVK-NFFT
fallegur;168136;lo;alm;fallegustu;EVB-KVK-ÞFFT
fallegur;168136;lo;alm;fallegustu;EVB-KVK-ÞGFFT
fallegur;168136;lo;alm;fallegustu;EVB-KVK-EFFT
fallegur;168136;lo;alm;fallegasta;EVB-HK-NFET
fallegur;168136;lo;alm;fallegasta;EVB-HK-ÞFET
fallegur;168136;lo;alm;fallegasta;EVB-HK-ÞGFET
fallegur;168136;lo;alm;fallegasta;EVB-HK-EFET
fallegur;168136;lo;alm;fallegustu;EVB-HK-NFFT
fallegur;168136;lo;alm;fallegustu;EVB-HK-ÞFFT
fallegur;168136;lo;alm;fallegustu;EVB-HK-ÞGFFT
fallegur;168136;lo;alm;fallegustu;EVB-HK-EFFT";
#[test]
pub fn loads_bin_data() {
let bin_data = BinData::load(TEST_DATA.as_bytes()).unwrap();
assert_eq!(3, bin_data.data.len());
assert!(bin_data.data.contains_key("aðalhellir"));
assert!(bin_data.data.contains_key("aðalhenda"));
assert_eq!(16, bin_data.data.get("aðalhellir").unwrap().len());
assert_eq!(18, bin_data.data.get("aðalhenda").unwrap().len());
assert_eq!(120, bin_data.data.get("fallegur").unwrap().len());
}
#[test]
pub fn gets_noun_entry() {
let bin_data = BinData::load(TEST_DATA.as_bytes()).unwrap();
let noun_entry = bin_data.noun("aðalhenda").unwrap();
assert_eq!(Gender::Feminine, noun_entry.gender);
// Singular
assert_eq!("aðalhenda", noun_entry.nom_sg.unwrap());
assert_eq!("aðalhendan", noun_entry.nom_sg_def.unwrap());
assert_eq!("aðalhendu", noun_entry.acc_sg.unwrap());
assert_eq!("aðalhenduna", noun_entry.acc_sg_def.unwrap());
assert_eq!("aðalhendu", noun_entry.dat_sg.unwrap());
assert_eq!("aðalhendunni", noun_entry.dat_sg_def.unwrap());
assert_eq!("aðalhendu", noun_entry.gen_sg.unwrap());
assert_eq!("aðalhendunnar", noun_entry.gen_sg_def.unwrap());
// Plural
assert_eq!("aðalhendur", noun_entry.nom_pl.unwrap());
assert_eq!("aðalhendurnar", noun_entry.nom_pl_def.unwrap());
assert_eq!("aðalhendur", noun_entry.acc_pl.unwrap());
assert_eq!("aðalhendurnar", noun_entry.acc_pl_def.unwrap());
assert_eq!("aðalhendum", noun_entry.dat_pl.unwrap());
assert_eq!("aðalhendunum", noun_entry.dat_pl_def.unwrap());
assert_eq!("aðalhendna", noun_entry.gen_pl.unwrap());
assert_eq!("aðalhendnanna", noun_entry.gen_pl_def.unwrap());
}
#[test]
pub fn gets_adjective_entry() {
let bin_data = BinData::load(TEST_DATA.as_bytes()).unwrap();
let adjective_entry = bin_data.adjective("fallegur").unwrap();
assert_eq!("fallegur", adjective_entry.masc_nom_sg_strong.unwrap());
assert_eq!("fallegan", adjective_entry.masc_acc_sg_strong.unwrap());
assert_eq!("fallegum", adjective_entry.masc_dat_sg_strong.unwrap());
assert_eq!("fallegs", adjective_entry.masc_gen_sg_strong.unwrap());
assert_eq!("falleg", adjective_entry.fem_nom_sg_strong.unwrap());
assert_eq!("fallega", adjective_entry.fem_acc_sg_strong.unwrap());
assert_eq!("fallegri", adjective_entry.fem_dat_sg_strong.unwrap());
assert_eq!("fallegrar", adjective_entry.fem_gen_sg_strong.unwrap());
assert_eq!("fallegt", adjective_entry.neut_nom_sg_strong.unwrap());
assert_eq!("fallegt", adjective_entry.neut_acc_sg_strong.unwrap());
assert_eq!("fallegu", adjective_entry.neut_dat_sg_strong.unwrap());
assert_eq!("fallegs", adjective_entry.neut_gen_sg_strong.unwrap());
assert_eq!("fallegir", adjective_entry.masc_nom_pl_strong.unwrap());
assert_eq!("fallega", adjective_entry.masc_acc_pl_strong.unwrap());
assert_eq!("fallegum", adjective_entry.masc_dat_pl_strong.unwrap());
assert_eq!("fallegra", adjective_entry.masc_gen_pl_strong.unwrap());
assert_eq!("fallegar", adjective_entry.fem_nom_pl_strong.unwrap());
assert_eq!("fallegar", adjective_entry.fem_acc_pl_strong.unwrap());
assert_eq!("fallegum", adjective_entry.fem_dat_pl_strong.unwrap());
assert_eq!("fallegra", adjective_entry.fem_gen_pl_strong.unwrap());
assert_eq!("falleg", adjective_entry.neut_nom_pl_strong.unwrap());
assert_eq!("falleg", adjective_entry.neut_acc_pl_strong.unwrap());
assert_eq!("fallegum", adjective_entry.neut_dat_pl_strong.unwrap());
assert_eq!("fallegra", adjective_entry.neut_gen_pl_strong.unwrap());
assert_eq!("fallegi", adjective_entry.masc_nom_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.masc_acc_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.masc_dat_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.masc_gen_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.fem_nom_sg_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_acc_sg_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_dat_sg_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_gen_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.neut_nom_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.neut_acc_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.neut_dat_sg_weak.unwrap());
assert_eq!("fallega", adjective_entry.neut_gen_sg_weak.unwrap());
assert_eq!("fallegu", adjective_entry.masc_nom_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.masc_acc_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.masc_dat_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.masc_gen_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_nom_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_acc_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_dat_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.fem_gen_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.neut_nom_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.neut_acc_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.neut_dat_pl_weak.unwrap());
assert_eq!("fallegu", adjective_entry.neut_gen_pl_weak.unwrap());
}
}

View File

@ -1,25 +1,52 @@
use std::borrow::Borrow;
use std::time::Duration;
use genanki_rs::Error;
use regex::Regex;
use select::document::Document;
use select::predicate::{Class, Name, Predicate};
use serde::{Deserialize, Serialize};
use crate::ProgramError;
use csv::ReaderBuilder;
use std::collections::BTreeMap;
use std::fmt::{self, Display, Formatter};
use std::str::FromStr;
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub enum Category {
Noun,
Adjective,
}
impl FromStr for Category {
type Err = ();
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_str() {
"noun" | "nouns" => Ok(Category::Noun),
"adjective" | "adjectives" => Ok(Category::Adjective),
_ => Err(()),
}
}
}
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Translation {
pub meaning: String,
pub usage: Option<String>,
}
#[derive(PartialEq, Clone, Debug, Serialize, Deserialize)]
pub struct Definition {
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct DictionaryEntry {
pub category: Category,
pub translations: Vec<Translation>,
}
#[derive(Clone, Debug, Serialize, Deserialize, Eq, PartialEq)]
pub struct Dictionary {
pub entries: BTreeMap<String, DictionaryEntry>,
}
impl Display for Translation {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match &self.usage {
@ -33,38 +60,102 @@ impl Display for Translation {
}
}
impl Display for Definition {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
match &self.translations.len() {
1 => {
write!(f, "{}", &self.translations.get(0).unwrap())
}
_ => {
write!(
f,
"{}",
&self
.translations
.iter()
.enumerate()
.map(|(i, t)| format!("{}. {}", i + 1, t))
.collect::<Vec<String>>()
.join("; ")
)
}
}
}
}
impl Translation {
pub fn new(translation: String, usage: Option<String>) -> Self {
Translation { meaning: translation, usage }
}
}
impl DictionaryEntry {
pub fn definition(&self) -> String {
if self.translations.len() == 1 {
format!("{}", self.translations.get(0).unwrap())
} else {
self.translations
.iter()
.enumerate()
.map(|(i, t)| format!("{}. {}", i + 1, t))
.collect::<Vec<String>>()
.join("; ")
}
}
}
impl Dictionary {
pub fn new() -> Self {
Dictionary { entries: BTreeMap::new() }
}
/// Retrieve a dictionary from the specified reader.
pub fn load<T>(input: T) -> Result<Self, ProgramError>
where
T: std::io::Read,
{
Ok(serde_json::from_reader(input)?)
}
/// Store a dictionary to the specified writer.
pub fn store<T>(&self, output: &mut T) -> Result<(), ProgramError>
where
T: std::io::Write,
{
Ok(serde_json::to_writer_pretty(output, self)?)
}
/// Import a set of words into a dictionary, returning the number of entries added.
pub fn import_wordlist<T>(&mut self, wordlist: T) -> Result<usize, ProgramError>
where
T: std::io::Read,
{
let mut synced: usize = 0;
let mut reader = ReaderBuilder::new()
.has_headers(false)
.delimiter(b'\t')
.flexible(true)
.from_reader(wordlist);
for record in reader.records().flatten() {
if let (Some(root), Some(category)) = (record.get(0), record.get(1)) {
if !self.entries.contains_key(root) {
self.entries.insert(
root.to_string(),
DictionaryEntry {
// TODO: Convert to ProgramError
category: Category::from_str(category).unwrap(),
translations: vec![],
},
);
synced += 1;
}
}
}
Ok(synced)
}
/// TODO: Testing! How do we test this? It'll be nasty, but we have to.
pub async fn update_definitions(&mut self) -> Result<usize, ProgramError> {
let client = reqwest::Client::new();
let mut updated: usize = 0;
for (root, entry) in &mut self.entries {
if entry.translations.is_empty() {
entry.translations.append(&mut search(&client, &root).await?);
updated += 1;
}
}
Ok(updated)
}
}
/// Look up a root word in the Online Icelandic Dictionary and return
/// a vector of definitions for the root.
pub async fn search(client: &reqwest::Client, word: &str) -> Result<Definition, Error> {
pub async fn search(
client: &reqwest::Client,
word: &str,
) -> Result<Vec<Translation>, ProgramError> {
println!("Searching Icelandic online dictionary for definitions: {}", word);
let url = format!("https://digicoll.library.wisc.edu/cgi-bin/IcelOnline/IcelOnline.TEId-idx?type=simple&size=First+100&rgn=lemma&q1={}&submit=Search", word);
@ -90,10 +181,10 @@ pub async fn search(client: &reqwest::Client, word: &str) -> Result<Definition,
.text()
.await?;
let document = Document::from(res.borrow());
Ok(Definition { translations: get_translations(&document) })
Ok(get_translations(&document))
}
None => Ok(Definition { translations: get_translations(&document) }),
None => Ok(get_translations(&document)),
}
}
@ -115,3 +206,93 @@ fn get_translations(document: &Document) -> Vec<Translation> {
.flatten()
.collect::<Vec<Translation>>()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
pub fn stores_and_loads_dictionary() {
let mut serialized = Vec::new();
let mut stored_dictionary = Dictionary::new();
stored_dictionary.entries.insert(
"foo".to_owned(),
DictionaryEntry {
category: Category::Adjective,
translations: vec![Translation {
meaning: "A Word".to_owned(),
usage: Some("A Usage".to_owned()),
}],
},
);
stored_dictionary.entries.insert(
"bar".to_string(),
DictionaryEntry {
category: Category::Adjective,
translations: vec![Translation {
meaning: "Another Word".to_string(),
usage: None,
}],
},
);
let _ = stored_dictionary.store(&mut serialized).unwrap();
let json = std::str::from_utf8(serialized.as_slice()).unwrap().to_string();
let loaded_dictionary = Dictionary::load(json.as_bytes()).unwrap();
assert_eq!(loaded_dictionary, stored_dictionary);
}
#[test]
pub fn loads_new_words_into_dictionary() {
let wordlist = "foo\tnouns\nbar\tadjectives\nbaz\tnouns\nquux\tadjectives".as_bytes();
let mut dictionary = Dictionary::new();
assert!(dictionary.entries.is_empty());
let synced = dictionary.import_wordlist(wordlist).unwrap();
assert_eq!(4, synced);
assert!(dictionary.entries.contains_key("foo"));
assert!(dictionary.entries.contains_key("bar"));
assert!(dictionary.entries.contains_key("baz"));
assert!(dictionary.entries.contains_key("quux"));
}
#[test]
pub fn does_not_overwrite_words_in_dictionary() {
let wordlist = "foo\tnouns\nbar\tadjectives\nbaz\tnouns\nquux\tadjectives".as_bytes();
let mut dictionary = Dictionary::new();
dictionary.entries.insert(
"baz".to_owned(),
DictionaryEntry {
category: Category::Noun,
translations: vec![Translation {
meaning: "The definition of baz".to_string(),
usage: Some("Some Usage".to_string()),
}],
},
);
assert_eq!(1, dictionary.entries.len());
let synced = dictionary.import_wordlist(wordlist).unwrap();
// Only three synced out of four
assert_eq!(3, synced);
assert!(dictionary.entries.contains_key("foo"));
assert!(dictionary.entries.contains_key("bar"));
assert!(dictionary.entries.contains_key("baz"));
assert!(dictionary.entries.contains_key("quux"));
assert_eq!(
"The definition of baz",
dictionary.entries.get("baz").unwrap().translations.get(0).unwrap().meaning
);
}
}

View File

@ -1,15 +1,28 @@
use std::borrow::Borrow;
use std::collections::BTreeMap;
use std::time::SystemTime;
use std::time::{SystemTime, SystemTimeError};
use crate::dictionary::Definition;
use clap::{arg_enum, value_t, App, Arg};
use csv::{ReaderBuilder, WriterBuilder};
use genanki_rs::{Deck, Error, Field, Model, Note, Template};
use crate::bindata::{BinData, Gender};
use crate::dictionary::{Category, Dictionary, DictionaryEntry};
use clap::{App, Arg};
use directories_next::ProjectDirs;
use genanki_rs::{Deck, Field, Model, Note, Template};
use rand::prelude::*;
use std::fs::File;
use std::io::{self, Write};
use std::path::{Path, PathBuf};
use tempfile::tempfile;
use thiserror::Error;
use zip::result::ZipError;
mod bindata;
mod dictionary;
const DEFAULT_BIN_CSV: &str = "SHsnid.csv";
const DEFAULT_DECK: &str = "deck.apkg";
const BIN_CSV_URL: &str = "https://bin.arnastofnun.is/django/api/nidurhal/?file=SHsnid.csv.zip";
const NOUN_MODEL_ID: usize = 1625673414000;
const ADJECTIVE_MODEL_ID: usize = 1625673415000;
const CSS: &str = "\
.card {\
font-family: arial;\
@ -45,91 +58,47 @@ const ADJ_TMPL: &str = r#"{{FrontSide}}
<hr id="definition">
<p>{{Definition}}</p>"#;
arg_enum! {
#[derive(PartialEq, Debug)]
pub enum Category {
Nouns,
Adjectives,
}
}
struct Adjective {
definition: Definition,
masc_singular: Option<String>,
fem_singular: Option<String>,
neut_singular: Option<String>,
masc_plural: Option<String>,
fem_plural: Option<String>,
neut_plural: Option<String>,
}
impl Adjective {
fn new(definition: Definition) -> Self {
Adjective {
definition,
masc_singular: None,
fem_singular: None,
neut_singular: None,
masc_plural: None,
fem_plural: None,
neut_plural: None,
}
}
#[derive(Error, Debug)]
pub enum ProgramError {
#[error("cannot access configuration")]
Configuration,
#[error("invalid dictionary file")]
Dictionary,
#[error("io error")]
Io(#[from] io::Error),
#[error("network error")]
Network(#[from] reqwest::Error),
#[error("zip error")]
Zip(#[from] ZipError),
#[error("bin data file does not exist")]
BinData,
#[error("system time")]
SystemTime(#[from] SystemTimeError),
#[error("CSV parse failed")]
Csv(#[from] csv::Error),
#[error("Serialization")]
Serialization(#[from] serde_json::Error),
#[error("Anki Generation")]
Anki(#[from] genanki_rs::Error),
}
/// Return a somewhat, kind-of, more-or-less random ID for an Anki record.
fn random_id() -> Result<usize, Error> {
fn random_id() -> Result<usize, ProgramError> {
let mut rng = thread_rng();
let delta: usize = rng.gen_range(0..100);
Ok(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis() as usize + delta)
}
async fn read_word_map(file_name: &str) -> BTreeMap<String, Definition> {
let client = reqwest::Client::new();
let mut result: BTreeMap<String, Definition> = BTreeMap::new();
if let Ok(mut reader) =
ReaderBuilder::new().has_headers(false).delimiter(b'\t').flexible(true).from_path(file_name)
{
for record in reader.records().flatten() {
if let Some(root) = record.get(0) {
// TODO: Error Handling
let definition = match record.get(1) {
Some(json) => serde_json::from_str::<Definition>(json).unwrap(),
None => dictionary::search(&client, &root).await.unwrap(),
};
result.insert(root.to_owned(), definition);
}
}
}
result
}
fn update_word_map(file_name: &str, word_map: &BTreeMap<String, Definition>) {
if let Ok(mut writer) =
WriterBuilder::new().has_headers(false).delimiter(b'\t').from_path(file_name)
{
word_map.iter().for_each(|(k, v)| {
let definition = serde_json::to_string(v).unwrap();
let _ = writer.write_record(&[k, &definition]);
});
}
}
/// Build an Anki deck based on adjectives
fn adjectives(
word_map: &BTreeMap<String, Definition>,
csv_file: &str,
deck_id: usize,
model_id: usize,
) -> Result<Deck, Error> {
fn generate_deck(
dictionary: &Dictionary,
bin_data: &BinData,
config: &AppConfig,
) -> Result<Deck, ProgramError> {
let mut deck =
Deck::new(deck_id, "Icelandic Adjectives", "Deck for studying Icelandic adjectives");
Deck::new(config.deck_id, "Icelandic Vocabulary", "Deck for studying Icelandic Vocabulary");
let model = Model::new_with_options(
model_id,
let adjective_model = Model::new_with_options(
ADJECTIVE_MODEL_ID,
"Icelandic Adjectives",
vec![
Field::new("MascSg"),
@ -148,83 +117,19 @@ fn adjectives(
None,
);
let mut db_reader =
ReaderBuilder::new().has_headers(false).delimiter(b';').from_path(csv_file)?;
let mut adjective_cards: BTreeMap<String, Adjective> = BTreeMap::new();
for result in db_reader.records() {
let record = result?;
let root = record.get(0).unwrap();
let key = record.get(2).unwrap();
if word_map.contains_key(root) && key == "lo" {
if !adjective_cards.contains_key(root) {
if let Some(definition) = word_map.get(root) {
adjective_cards.insert(String::from(root), Adjective::new(definition.clone()));
}
}
if let Some(card) = adjective_cards.get_mut(root) {
let form = record.get(5).unwrap();
let decl = record.get(4).unwrap().to_owned();
match form {
"FSB-KK-NFET" => card.masc_singular = Some(decl),
"FSB-KVK-NFET" => card.fem_singular = Some(decl),
"FSB-HK-NFET" => card.neut_singular = Some(decl),
"FSB-KK-NFFT" => card.masc_plural = Some(decl),
"FSB-KVK-NFFT" => card.fem_plural = Some(decl),
"FSB-HK-NFFT" => card.neut_plural = Some(decl),
_ => {}
}
}
}
}
// Now map over the adjectives and build cards.
for (_, val) in adjective_cards {
let note = Note::new(
model.clone(),
vec![
val.masc_singular.unwrap_or_else(String::new).borrow(),
val.fem_singular.unwrap_or_else(String::new).borrow(),
val.neut_singular.unwrap_or_else(String::new).borrow(),
val.masc_plural.unwrap_or_else(String::new).borrow(),
val.fem_plural.unwrap_or_else(String::new).borrow(),
val.neut_plural.unwrap_or_else(String::new).borrow(),
&val.definition.to_string(),
],
);
deck.add_note(note.unwrap());
}
Ok(deck)
}
/// Build an Anki deck based on nouns
fn nouns(
word_map: &BTreeMap<String, Definition>,
csv_file: &str,
deck_id: usize,
model_id: usize,
) -> Result<Deck, Error> {
let mut deck =
Deck::new(deck_id, "Icelandic Noun Plurals", "Deck for studying Icelandic noun plurals");
let model = Model::new_with_options(
model_id,
let noun_model = Model::new_with_options(
NOUN_MODEL_ID,
"Noun Plurals",
vec![
Field::new("Singular"),
Field::new("Plural"),
Field::new("NomSg"),
Field::new("GenSg"),
Field::new("NomPl"),
Field::new("Gender"),
Field::new("Definition"),
],
vec![Template::new("Card 1")
.qfmt("<h1>{{Singular}}</h1>")
.afmt(r#"{{FrontSide}}<hr id="plural"><h2>{{Plural}} ({{Gender}})</h2> <p>{{Definition}}</p>"#)],
.qfmt("<h1>{{NomSg}}</h1>")
.afmt(r#"{{FrontSide}}<hr id="gender"/><h2>{{Gender}}</h2><hr id="forms"/><h2><em>g. sg.</em> {{GenSg}}, <em>n. pl.</em> {{NomPl}}</h2> <p>{{Definition}}</p>"#)],
Some(CSS),
None,
None,
@ -232,31 +137,17 @@ fn nouns(
None,
);
let mut db_reader =
ReaderBuilder::new().has_headers(false).delimiter(b';').from_path(csv_file)?;
for result in db_reader.records() {
let record = result?;
let form = record.get(5).unwrap();
let class = record.get(3).unwrap();
if "alm" == class && "NFFT" == form {
if let Some(root) = record.get(0) {
if word_map.contains_key(root) {
let gender = match record.get(2).unwrap() {
"kk" => "masc.",
"hk" => "neut.",
"kvk" => "fem.",
_ => "...",
};
let plural = record.get(4).unwrap();
if let Some(definition) = word_map.get(root) {
let note = Note::new(
model.clone(),
vec![root, plural, gender, &definition.to_string()],
);
deck.add_note(note.unwrap());
}
for (root, dictionary_entry) in &dictionary.entries {
match dictionary_entry.category {
Category::Noun => {
if let Some(note) = noun(&root, bin_data, &dictionary_entry, &noun_model) {
deck.add_note(note)
}
}
Category::Adjective => {
if let Some(note) = adjective(&root, bin_data, &dictionary_entry, &adjective_model)
{
deck.add_note(note)
}
}
}
@ -265,19 +156,73 @@ fn nouns(
Ok(deck)
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
let matches = App::new("BÍN Scraper")
fn adjective(
root: &str,
bin_data: &BinData,
dictionary_entry: &DictionaryEntry,
model: &Model,
) -> Option<Note> {
match bin_data.adjective(root) {
Some(adjective_entry) => Some(
Note::new(
model.clone(),
vec![
adjective_entry.masc_nom_sg_strong.unwrap_or("".to_string()).borrow(),
adjective_entry.fem_nom_sg_strong.unwrap_or("".to_string()).borrow(),
adjective_entry.neut_nom_sg_strong.unwrap_or("".to_string()).borrow(),
adjective_entry.masc_nom_pl_strong.unwrap_or("".to_string()).borrow(),
adjective_entry.fem_nom_pl_strong.unwrap_or("".to_string()).borrow(),
adjective_entry.neut_nom_pl_strong.unwrap_or("".to_string()).borrow(),
&dictionary_entry.definition(),
],
)
.unwrap(),
),
_ => None,
}
}
fn noun(
root: &str,
bin_data: &BinData,
dictionary_entry: &DictionaryEntry,
model: &Model,
) -> Option<Note> {
match bin_data.noun(root) {
Some(noun_entry) => Some(
Note::new(
model.clone(),
vec![
root,
noun_entry.gen_sg.unwrap_or("".to_string()).borrow(),
noun_entry.nom_pl.unwrap_or("".to_string()).borrow(),
match noun_entry.gender {
Gender::Masculine => "Masculine",
Gender::Feminine => "Feminine",
Gender::Neuter => "Neuter",
},
&dictionary_entry.definition(),
],
)
.unwrap(),
),
_ => None,
}
}
/// Read application config from command line arguments.
fn app_config(project_dirs: &ProjectDirs) -> AppConfig {
let arg_matches = App::new("Icelandic Anki Flashcard Generator")
.version("1.0")
.author("Seth Morabito")
.arg(
Arg::with_name("bindata")
.help("BÍN CSV File")
.short("b")
.long("bindata")
.value_name("FILE")
Arg::with_name("binurl")
.help("URL to fetch BÍN CSV")
.long("binurl")
.value_name("URL")
.takes_value(true)
.required(true),
.default_value(BIN_CSV_URL)
.required(false),
)
.arg(
Arg::with_name("deck")
@ -285,16 +230,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.short("d")
.long("deck")
.value_name("FILE")
.takes_value(true)
.required(true),
)
.arg(
Arg::with_name("category")
.help("Wordlist file category ('nouns' or 'adjectives')")
.long("category")
.value_name("CATEGORY")
.takes_value(true)
.required(true),
.default_value("deck.apkg")
.takes_value(true),
)
.arg(
Arg::with_name("deck-id")
@ -304,53 +241,175 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
.takes_value(true)
.required(false),
)
.arg(
Arg::with_name("model-id")
.help("Optional numeric ID for the generated Anki model")
.long("model-id")
.value_name("ID")
.takes_value(true)
.required(false),
)
.arg(
Arg::with_name("wordlist")
.help("List of words and definitions, tab separated, one per line")
.help("List of words and categories, tab separated, one per line")
.required(true),
)
.get_matches();
let csv_file = matches.value_of("bindata").unwrap();
let deck_file = matches.value_of("deck").unwrap();
let category: Category = value_t!(matches, "category", Category).unwrap();
let input_file = matches.value_of("wordlist").unwrap();
let deck_id = match matches.value_of("deck-id") {
Some(id) => id.parse::<usize>().unwrap(),
None => random_id().unwrap(),
let dictionary = project_dirs.data_dir().join("dictionary.json");
let bin_data: PathBuf = project_dirs.data_dir().join(DEFAULT_BIN_CSV);
let bin_csv_url = match arg_matches.value_of("binurl") {
Some(binurl) => binurl.to_string(),
None => BIN_CSV_URL.to_string(),
};
let model_id = match matches.value_of("model-id") {
let deck: String = match arg_matches.value_of("deck") {
Some(deck) => deck.to_string(),
None => DEFAULT_DECK.to_string(),
};
let wordlist: PathBuf = match arg_matches.value_of("wordlist") {
Some(wordlist) => Path::new(wordlist).to_path_buf(),
None => Path::new("wordlist.txt").to_path_buf(),
};
let deck_id = match arg_matches.value_of("deck-id") {
Some(id) => id.parse::<usize>().unwrap(),
None => random_id().unwrap(),
};
println!("Generating Anki deck with id `{}`, model id `{}`.", deck_id, model_id);
AppConfig { bin_csv_url, bin_data, dictionary, deck, wordlist, deck_id }
}
println!("Loading {}...", input_file);
let word_map = read_word_map(input_file).await;
#[derive(Debug)]
struct AppConfig {
bin_csv_url: String,
bin_data: PathBuf,
dictionary: PathBuf,
deck: String,
wordlist: PathBuf,
deck_id: usize,
}
// TODO: A builder pattern would probably be nice here.
println!("Starting Anki deck generation...");
let deck = match category {
Category::Nouns => nouns(&word_map, csv_file, deck_id, model_id)?,
Category::Adjectives => adjectives(&word_map, csv_file, deck_id, model_id)?,
};
fn setup_project_dirs(project_dirs: &ProjectDirs) -> Result<(), ProgramError> {
let data_dir = project_dirs.data_dir();
let config_dir = project_dirs.config_dir();
std::fs::create_dir_all(data_dir)?;
std::fs::create_dir_all(config_dir)?;
Ok(())
}
async fn get_bin_csv(app_config: &AppConfig) -> Result<(), ProgramError> {
let mut tmp_file = tempfile()?;
println!("Downloading BIN data from URL {:?}...", &app_config.bin_csv_url);
let response = reqwest::get(&app_config.bin_csv_url).await?;
let content = response.bytes().await?;
tmp_file.write_all(content.as_ref())?;
println!("Extracting ZIP file to {:?}...", &app_config.bin_data);
let mut archive = zip::ZipArchive::new(tmp_file)?;
let mut file = archive.by_name(DEFAULT_BIN_CSV)?;
let mut outfile = File::create(&app_config.bin_data)?;
io::copy(&mut file, &mut outfile)?;
Ok(())
}
/// Ensure that the BIN CSV data file exists locally. If it does not exist,
/// it will be downloaded and unzipped automatically.
///
/// # Arguments
///
/// * `config` - The application config.
///
async fn ensure_bin_data_exists(config: &AppConfig) -> Result<(), ProgramError> {
if config.bin_data.exists() {
return Ok(());
}
println!("===============================================================================");
println!("The required BIN data file {} does not exist. It can be downloaded", DEFAULT_BIN_CSV);
println!("automatically for you, or you may download it and unzip it yourself.");
println!();
println!("The compressed download is about 35 MB, and the uncompressed file uses about");
println!("325 MB of disk space.");
println!();
println!("This download only needs to occur once. The file will be saved as:");
println!(" {:?}", config.bin_data);
println!("===============================================================================");
println!();
print!("Continue with download? [y/N]: ");
std::io::stdout().flush()?;
let mut input = String::new();
let _ = std::io::stdin().read_line(&mut input)?;
if input.trim().to_ascii_lowercase().starts_with('y') {
get_bin_csv(&config).await?;
Ok(())
} else {
Err(ProgramError::BinData)
}
}
#[tokio::main]
async fn main() -> Result<(), ProgramError> {
// Establish directories for holding state
match ProjectDirs::from("com", "loomcom", "is-anki-gen") {
Some(project_dirs) => {
let config = app_config(&project_dirs);
// If the word list doesn't exist, bail immediately.
if !config.wordlist.exists() {
println!("Word list file {:?} does not exist.", config.wordlist);
return Err(ProgramError::Configuration);
}
setup_project_dirs(&project_dirs)?;
if let Err(e) = ensure_bin_data_exists(&config).await {
match e {
ProgramError::BinData => {
println!("BIN file not downloaded or found locally.");
}
_ => {
println!("Couldn't download BIN file: {:?}", e);
}
}
println!("Good bye!");
return Err(e);
}
let mut dictionary = if config.dictionary.exists() {
Dictionary::load(File::open(&config.dictionary)?)?
} else {
Dictionary::new()
};
println!("Loading word list {:#?}...", config.wordlist);
let synced = dictionary.import_wordlist(File::open(&config.wordlist)?)?;
println!("Loaded {} words.", synced);
let updated = dictionary.update_definitions().await?;
if updated > 0 {
println!("Storing dictionary back to file... {:?}", &config.dictionary);
dictionary.store(&mut File::create(&config.dictionary)?)?;
}
println!("Loading BIN Data...");
let bin_data_file = File::open(&config.bin_data)?;
let bin_data = BinData::load(bin_data_file)?;
println!("Starting Anki deck generation...");
let deck = generate_deck(&dictionary, &bin_data, &config)?;
println!("Saving Anki deck...");
deck.write_to_file(&config.deck)?;
println!("Done!");
}
None => println!("Cannot access default application storage directory. Giving up."),
}
println!("Saving Anki deck...");
deck.write_to_file(deck_file)?;
// TODO: Back up original file
println!("Updating {}...", input_file);
update_word_map(input_file, &word_map);
println!("Done!");
Ok(())
}