LLFG625ISXV7P2LUOFUMFIM5V5RJDKWCL47XX43X2CGILVAUQPVQC
AVLXUT3ROXQ2PLLTB5XHPBY2BI5PQRRFJTG2GGZTL7K4VEZZXF3AC
G5YNDTPHPYRZZIGWLX2ZLVFRJ3B2NGAPVESSMTO7YEABDFIIE66AC
5Y7ZXB53EMG34VZI5VQIZ77TZKBB4V6BGIILFZ5ZY73QYK4V2YHQC
AV73DYWQ2UVZJYTN3UIW3TDMWNAETLXZRD7VHKTQLFQGHKJ5KI6QC
RNW6D77774CYWWM7JIFXI5TGKBOU6ADJIEZB5N2FXGDCTLUXEQZQC
KUANIPWFDXDFKJ2LH4FQ6APYOPLNYJ5LVGLSBSC75WUUZPFHILCAC
YCWYAX6K2DJKT7FO4IAYL6HJOIJLYFKAPGLFJ5XMYSYAS42LP3FQC
HMOBTVJ4FEPZWMUV2JDPZYH3EFCW6ED5M6KKNKQJQZVKTDAKTVFQC
pub async fn pick(db: AsyncConnection, count: u16) -> DynResult<()> {
pub async fn pick(db: &AsyncConnection, count: u16) -> DynResult<()> {
let mut stderr = std::io::stderr();
stderr.execute(cursor::Hide)?;
let (mut input, done) = events();
stderr.execute(cursor::Show)?;
}
})
.await??)
}
pub async fn compare(
&self,
a: i64,
b: i64,
) -> DynResult<Option<std::cmp::Ordering>> {
if a == b {
return Ok(Some(std::cmp::Ordering::Equal));
}
Ok(self.post(move |conn| -> DynResult<Option<std::cmp::Ordering>> {
let mut stmnt = conn.prepare("SELECT better, worse FROM preferences WHERE (better = ? AND worse = ?) OR (better = ? AND worse = ?)")?;
stmnt.bind::<i64>(1,a)?;
stmnt.bind::<i64>(2,b)?;
stmnt.bind::<i64>(3,b)?;
stmnt.bind::<i64>(4,a)?;
match stmnt.next()? {
sqlite::State::Done => Ok(None),
sqlite::State::Row => {
let better = stmnt.read::<i64>(0)?;
let worse = stmnt.read::<i64>(1)?;
if better == a && worse == b {
Ok(Some(std::cmp::Ordering::Greater))
} else if better == b && worse == a {
Ok(Some(std::cmp::Ordering::Less))
} else {
Ok(Some(std::cmp::Ordering::Equal))
}
}
}
}).await??)
}
pub async fn list_names(&self) -> DynResult<Vec<(String, i64)>> {
match self
.post(|conn| {
let mut stmnt =
conn.prepare("SELECT name, rowid FROM names")?;
let mut rows = Vec::new();
while let sqlite::State::Row = stmnt.next()? {
rows.push((
stmnt.read::<String>(0)?,
stmnt.read::<i64>(1)?,
));
}
}
async fn insert_preference(
&self,
better: i64,
worse: i64,
) -> DynResult<()> {
self.insert_one_preference(better, worse).await?;
self.make_transitive().await
}
async fn insert_one_preference(
&self,
better: i64,
worse: i64,
) -> DynResult<()> {
self.post(move |db| -> DynResult<_> {
let mut stmnt = db.prepare(
"INSERT INTO preferences(better, worse) VALUES(?, ?)",
)?;
stmnt.bind::<i64>(1, better)?;
stmnt.bind::<i64>(2, worse)?;
stmnt.next()?;
Ok(())
})
.await?
}
pub async fn make_transitive(&self) -> DynResult<()> {
loop {
let todo = self
.post(|db| -> DynResult<_> {
let mut stmnt = db.prepare(
"SELECT a.better, b.worse
FROM preferences AS a
INNER JOIN preferences as b ON a.worse = b.better
WHERE NOT EXISTS (
SELECT rowid FROM preferences AS x
WHERE x.better = a.better
AND x.worse = b.worse
)
",
)?;
let mut rows = Vec::new();
while let sqlite::State::Row = stmnt.next()? {
rows.push((
stmnt.read::<i64>(0)?,
stmnt.read::<i64>(1)?,
));
}
Ok(rows)
})
.await??;
if todo.is_empty() {
return Ok(());
} else {
let handles: Vec<_> = todo
.into_iter()
.map(|(better, worse)| {
let target = self.clone();
tokio::spawn(async move {
target.insert_one_preference(better, worse).await
})
})
.collect();
for handle in handles {
handle.await??;
}
}