aboutsummaryrefslogtreecommitdiff
path: root/src/db
diff options
context:
space:
mode:
authorJoris2022-02-06 19:30:53 +0100
committerJoris2022-02-06 19:30:53 +0100
commit20cfe717065fa53953e9799036a9972880fec801 (patch)
tree7fc2a7b4a43eb6d280d52c468927592c12798cb0 /src/db
parentdc0f32017cceabb6c683b6e1b4a2ae0248c37dbf (diff)
Replace a card whenever the front or the back changed
Diffstat (limited to 'src/db')
-rw-r--r--src/db/db.rs25
-rw-r--r--src/db/sql/2-primary-key-question-responses.sql20
2 files changed, 36 insertions, 9 deletions
diff --git a/src/db/db.rs b/src/db/db.rs
index 86614ec..843d142 100644
--- a/src/db/db.rs
+++ b/src/db/db.rs
@@ -1,5 +1,5 @@
use crate::{
- model::{card::Card, deck::Entry},
+ model::{card::Card, entry::Entry},
space_repetition,
util::serialization,
};
@@ -11,14 +11,21 @@ use std::time::SystemTime;
pub fn init(database: String) -> Result<Connection> {
let mut conn = Connection::open(database)?;
- let migrations = Migrations::new(vec![M::up(include_str!("sql/1-init.sql"))]);
+ let migrations = Migrations::new(vec![
+ M::up(include_str!("sql/1-init.sql")),
+ M::up(include_str!("sql/2-primary-key-question-responses.sql")),
+ ]);
migrations.to_latest(&mut conn)?;
Ok(conn)
}
-pub fn add_missing_deck_entries(conn: &Connection, entries: Vec<Entry>) -> Result<()> {
+/// Synchronize the DB with the deck:
+///
+/// - insert new cards,
+/// - keep existing cards,
+/// - hide unused cards (keep state in case the card is added back afterward).
+pub fn synchronize(conn: &Connection, entries: Vec<Entry>) -> Result<()> {
let now = get_current_time()?;
- let ready = now;
let state = serde_json::to_string(&space_repetition::init())?;
let mut rng = rand::thread_rng();
@@ -28,11 +35,11 @@ pub fn add_missing_deck_entries(conn: &Connection, entries: Vec<Entry>) -> Resul
let concat_2 = serialization::words_to_line(&entry.part_2);
for w in entry.part_1.iter() {
- insert(&conn, &mut rng, now, ready, &w, &concat_2, &state)?;
+ insert(&conn, &mut rng, now, &w, &concat_2, &state)?;
}
for w in entry.part_2.iter() {
- insert(&conn, &mut rng, now, ready, &w, &concat_1, &state)?;
+ insert(&conn, &mut rng, now, &w, &concat_1, &state)?;
}
}
@@ -45,11 +52,11 @@ fn insert(
conn: &Connection,
rng: &mut ThreadRng,
now: u64,
- ready: u64,
question: &String,
responses: &String,
state: &String,
) -> Result<()> {
+ println!("insert {} : {}", question, responses);
// Subtract a random amount of time so that cards are not initially given in the same order as
// in the deck
let ready_sub: u64 = rng.gen_range(0..100);
@@ -58,9 +65,9 @@ fn insert(
"
INSERT INTO cards (question, responses, state, created, deck_read, ready)
VALUES (?, ?, ?, ?, ?, ?)
- ON CONFLICT (question) DO UPDATE SET deck_read = ?, deleted = null
+ ON CONFLICT (question, responses) DO UPDATE SET deck_read = ?, deleted = null
",
- params![question, responses, state, now, now, ready - ready_sub, now],
+ params![question, responses, state, now, now, now - ready_sub, now],
)?;
Ok(())
diff --git a/src/db/sql/2-primary-key-question-responses.sql b/src/db/sql/2-primary-key-question-responses.sql
new file mode 100644
index 0000000..cb7df21
--- /dev/null
+++ b/src/db/sql/2-primary-key-question-responses.sql
@@ -0,0 +1,20 @@
+/* Allows to use ON CONFLICT on (question, responses) when inserting a card. */
+
+CREATE TABLE IF NOT EXISTS cards_copy (
+ question VARCHAR NOT NULL,
+ responses VARCHAR NOT NULL,
+ state VARCHAR NOT NULL,
+ created TIMESTAMP NOT NULL,
+ updated TIMESTAMP NULL,
+ deleted TIMESTAMP NULL,
+ deck_read TIMESTAMP NOT NULL,
+ ready TIMESTAMP NOT NULL,
+ PRIMARY KEY (question, responses)
+);
+
+INSERT INTO cards_copy (question, responses, state, created, updated, deleted, deck_read, ready)
+ SELECT question, responses, state, created, updated, deleted, deck_read, ready FROM cards;
+
+DROP TABLE cards;
+
+ALTER TABLE cards_copy RENAME TO cards;