Skip to content

Commit

Permalink
release 0.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
doomy committed Nov 2, 2023
1 parent 938542e commit 44e6c6d
Show file tree
Hide file tree
Showing 44 changed files with 947 additions and 273 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 16 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ Chinese English dictionary in Rust. Uses CC-CEDICT. [Creative Commons Attributio

This is mostly a project for my own benefit at the moment, so the roadmap is based on my personal needs. I welcome that to change - if anyone else finds this project useful, please feel free to open an issue with a suggestion or file a PR.

- [ ] Display
- [x] Display
- [x] Simplified characters
- [ ] Traditional characters
- [x] Traditional characters
- [x] Pinyin
- [x] Dictionary downloads and updates
- [ ] Multiple dictionary sources
Expand All @@ -20,11 +20,13 @@ This is mostly a project for my own benefit at the moment, so the roadmap is bas
- [x] Pinyin
- [x] English meaning
- [x] Search history
- [x] Link to individual character definitions in multiple character words
- [x] Collections (Card decks)
- [x] Create and add
- [ ] Manage decks
- [ ] Import/Export
- [x] Import/Export
- [ ] Learning
- [x] [Design thoughts](/docs/memorization-system.md)
- [ ] SRS-like reviews
- [ ] Default HSK decks
- [ ] Learn by character dependency (Automatically learn all individual characters of a compound word first)
Expand All @@ -38,10 +40,18 @@ This is mostly a project for my own benefit at the moment, so the roadmap is bas
- [ ] Linux
- [ ] Mobile app (iOS)

## Non-goals

This project aims to be a useful way to study chinese vocab, but will never come close to something like Pleco. It instead focuses more on vocab learning and usage, as opposed to an all-in-one application for everything-Chinese-language.

## Installation

### Release

Go to the releases page to find installers

### Manual

1. Install Tauri prereqs ([See guide](https://beta.tauri.app/guides/prerequisites/))
2. Install Tauri CLI (`cargo install tauri-cli --version "^2.0.0-alpha"`)
3. Build application (`cargo tauri build`)
Expand All @@ -64,3 +74,6 @@ cargo install icopng
icopng src-tauri/icons/128x128.png src-tauri/icons/icon.ico
```

### License

GPL-v3 probably for the application. I don't like it but whatever, it's not a bad choice for programs. Just kind of annoying for libraries. idk you can convince me otherwise on this probably
49 changes: 49 additions & 0 deletions docs/memorization-system.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Ideas

From my best understanding, SRS doesn't seem to be very scientific (and even the concept of spaced repetition may even be no better than regular repetition). Therefore, I decided to not try and implement some standard way (such as Anki) of SRS. However, while I cannot vouch for the scientific validity of SRS, I *personally* like it for learning, so a somewhat similar system will be implemented.

## Core goals

### Correct or incorrect

Many SRS systems have multiple levels of "remembered", such as Anki's "Again", "Good", "Easy" or "Very Easy", or Pleco's 6 levels (which don't quite make sense when first learning). I find myself spending a non-negligible amount of time trying to judge what level of "correct" my answer was. cedr offers a binary choice between correct and incorrect. It is up to the user to decide what threshold "correct" should be based on their individual learning goals.

> Maybe interesting thought? Optionally when marking something incorrect, we could ask for what was incorrect (e.g., tones, meaning, pinyin - because an incorrect answer is rarely **completely** wrong). In fact, in Pleco, I am doing this mentally - I mark something as "barely remembered" if I got everything but one part of the vocab right. So why not offer that in the application itself? This information can be useful as lessons thereafter can focus on what was incorrect last time (e.g. making an emphasis on tones, if tones were incorrect last time). Although an extra step adds an additional interaction (and code complexity) it may be worth looking into.
### Simple

The memorization system should not be overly complicated (as again, to the best of my knowledge, it is dubious how scientific SRS truely is, so there is little point trying to replicate a system that may be overly complex with no benefit).

A (customizable?) curve can be described to which flashcards will be designated. solving for Y which is number of hours until next repetition.

```
d = n number hours (default 12)
x = consecutive correct answers
y = (2^x * d)
```

A goal score can be set, either by time to completion, or by number of consecutive correct answers. For example, 8 repetitions would take 255 days to complete and be considered "burned".

### Character focus

Cards have four states: inactive, active, locked, and burned. Locked cards can still be learned, but are called as such because they have unmet character dependencies. This application encourages learning characters to build up compound character words, as learning individual meanings is often very helpful later on. cedr will optionally automatically hide locked cards until their dependencies are met. Once all dependencies are added to the learning queue (in an "active" state) compound words using those characters will be unlocked. States do not affect learning curve weights - the curve is solely dictated by consecutive correct answers.

> Could be cool to have a dependency tree visualization of characters in HSK.
### 好看

Interactions should not leave users with a sense of dread and boredom. Gamification is a stupid buzzword but nice interaction and polish can help make an application more engaging and fun to use. This is a weird one to include here in the memorization system, but I do all my learning at night and sometimes staring at a deep blue unfeeling uncaring UI can make me sleepy.
Any memorization system is ineffective if the implementing program does not hold attention. For example, consider breaking up a review with hundreds of items into checkpoints with 50 items each.

### Deck independent

Just a sidenote, card scores should be owned by the entry itself, and not a collection. If two collections have the same cards, working in either collection should continue progress, as there's no real reason not to do this if our goal is memorization.

### Audio focus

Audio is really important for learning languages. TBD on where to get said audio, but cards should always play it on reveal (and audio quizzes should also be available).

### Self moderated

Wanikani is cool but it's impossible to be accurate 100% of the time unless you're trusting the user to self-moderate. Slipping your finger and typing one letter wrong and getting the card progress reset really sucks to the point where I often would just quit the session without saving.

26 changes: 25 additions & 1 deletion migrations/20230929015234_init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ CREATE TABLE IF NOT EXISTS entries (
FOREIGN KEY(source_id) REFERENCES sources(id) ON UPDATE CASCADE
);


CREATE TABLE IF NOT EXISTS history (
id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
Expand Down Expand Up @@ -58,6 +57,31 @@ CREATE TABLE IF NOT EXISTS collections_entries (
FOREIGN KEY(entry_id) REFERENCES entries(id)
);

CREATE TABLE IF NOT EXISTS scores (
id INTEGER PRIMARY KEY NOT NULL,
level INTEGER NOT NULL DEFAULT 0,
entry_id INTEGER NOT NULL UNIQUE ON CONFLICT IGNORE,
active BOOLEAN NOT NULL DEFAULT false,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,

FOREIGN KEY(entry_id) REFERENCES entries(id)
);

CREATE TABLE IF NOT EXISTS scorelog (
id INTEGER PRIMARY KEY NOT NULL,
correct BOOLEAN NOT NULL,
time DATETIME DEFAULT CURRENT_TIMESTAMP NOT NULL,
score_id INTEGER NOT NULL,

FOREIGN KEY(score_id) REFERENCES scores(id)
);

CREATE TRIGGER IF NOT EXISTS update_scores_updated_at
AFTER UPDATE ON scores
BEGIN
UPDATE scores SET updated_at = DATETIME('now') WHERE id = NEW.id;
END;

-- -- FTS5 table for easier terms searching

-- CREATE VIRTUAL TABLE IF NOT EXISTS examples_search USING fts5(simplified, content=terms, content_rowid=id);
Expand Down
9 changes: 0 additions & 9 deletions src-shared/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,5 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
itertools = "0.11.0"
serde = "1.0"
unicode-segmentation = "1.10.1"
prettify_pinyin = "2.0.0"
chrono = { version = "0.4", features = ["serde"] }
url-escape = "0.1.1"

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
sqlx = "*"
anyhow = "*"
chinese_detection = "*"
4 changes: 2 additions & 2 deletions src-shared/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ pub enum InputMethod {
}

#[cfg(target_arch = "wasm32")]
pub type Id = u32;
pub type Int = u32;
#[cfg(not(target_arch = "wasm32"))]
pub type Id = i64;
pub type Int = i64;

impl std::fmt::Display for InputMethod {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
Expand Down
4 changes: 2 additions & 2 deletions src-shared/src/models/collection.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
use crate::Id;
use crate::Int;
use serde::{Deserialize, Serialize};
use std::fmt::Display;

#[derive(Default, Clone, Deserialize, Serialize, PartialEq)]
pub struct Collection {
pub id: Id,
pub id: Int,
pub name: String,
pub updated_at: chrono::NaiveDateTime,
}
Expand Down
6 changes: 3 additions & 3 deletions src-shared/src/models/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@

use chrono::NaiveDateTime;

use crate::Id;
use crate::Int;

#[derive(Clone, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct Entry {
pub id: Id,
pub source_id: Id,
pub id: Int,
pub source_id: Int,
pub traditional: String,
pub simplified: String,
/// Pinyin with numbers
Expand Down
4 changes: 2 additions & 2 deletions src-shared/src/models/example.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::Id;
use crate::Int;

#[derive(Clone, serde::Deserialize, serde::Serialize, PartialEq)]
pub struct Example {
pub id: Id,
pub id: Int,
pub text: String,
pub translations: String,
pub source: String, //Source,
Expand Down
3 changes: 2 additions & 1 deletion src-shared/src/models/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod collection;
mod entry;
mod example;
mod score;
mod source;

pub use {collection::*, entry::*, example::*, source::*};
pub use {collection::*, entry::*, example::*, score::*, source::*};
Loading

0 comments on commit 44e6c6d

Please sign in to comment.