mirror of
https://github.com/ankitects/anki.git
synced 2025-09-18 22:12:21 -04:00
Don't rely on frontend to cap time taken in v3
This commit is contained in:
parent
7bfd7245e0
commit
d90608198f
6 changed files with 24 additions and 13 deletions
|
@ -190,10 +190,13 @@ class Card(DeprecatedNamesMixin):
|
||||||
"autoplay"
|
"autoplay"
|
||||||
]
|
]
|
||||||
|
|
||||||
def time_taken(self) -> int:
|
def time_taken(self, capped: bool = True) -> int:
|
||||||
"Time taken to answer card, in integer MS."
|
"""Time taken since card timer started, in integer MS.
|
||||||
|
If `capped` is true, returned time is limited to deck preset setting."""
|
||||||
total = int((time.time() - self.timer_started) * 1000)
|
total = int((time.time() - self.timer_started) * 1000)
|
||||||
return min(total, self.time_limit())
|
if capped:
|
||||||
|
total = min(total, self.time_limit())
|
||||||
|
return total
|
||||||
|
|
||||||
def description(self) -> str:
|
def description(self) -> str:
|
||||||
dict_copy = dict(self.__dict__)
|
dict_copy = dict(self.__dict__)
|
||||||
|
|
|
@ -493,7 +493,7 @@ limit ?"""
|
||||||
card.did,
|
card.did,
|
||||||
new_delta=new_delta,
|
new_delta=new_delta,
|
||||||
review_delta=review_delta,
|
review_delta=review_delta,
|
||||||
milliseconds_delta=+card.time_taken(),
|
milliseconds_delta=card.time_taken(),
|
||||||
)
|
)
|
||||||
|
|
||||||
# once a card has been answered once, the original due date
|
# once a card has been answered once, the original due date
|
||||||
|
|
|
@ -81,7 +81,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||||
new_state=new_state,
|
new_state=new_state,
|
||||||
rating=rating,
|
rating=rating,
|
||||||
answered_at_millis=int_time(1000),
|
answered_at_millis=int_time(1000),
|
||||||
milliseconds_taken=card.time_taken(),
|
milliseconds_taken=card.time_taken(capped=False),
|
||||||
)
|
)
|
||||||
|
|
||||||
def answer_card(self, input: CardAnswer) -> OpChanges:
|
def answer_card(self, input: CardAnswer) -> OpChanges:
|
||||||
|
|
|
@ -182,7 +182,7 @@ impl SchedulerService for Backend {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn answer_card(&self, input: pb::CardAnswer) -> Result<pb::OpChanges> {
|
fn answer_card(&self, input: pb::CardAnswer) -> Result<pb::OpChanges> {
|
||||||
self.with_col(|col| col.answer_card(&input.into()))
|
self.with_col(|col| col.answer_card(&mut input.into()))
|
||||||
.map(Into::into)
|
.map(Into::into)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -43,6 +43,12 @@ pub struct CardAnswer {
|
||||||
pub milliseconds_taken: u32,
|
pub milliseconds_taken: u32,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl CardAnswer {
|
||||||
|
fn cap_answer_secs(&mut self, max_secs: u32) {
|
||||||
|
self.milliseconds_taken = self.milliseconds_taken.min(max_secs * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Holds the information required to determine a given card's
|
/// Holds the information required to determine a given card's
|
||||||
/// current state, and to apply a state change to it.
|
/// current state, and to apply a state change to it.
|
||||||
struct CardStateUpdater {
|
struct CardStateUpdater {
|
||||||
|
@ -238,11 +244,12 @@ impl Collection {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Answer card, writing its new state to the database.
|
/// Answer card, writing its new state to the database.
|
||||||
pub fn answer_card(&mut self, answer: &CardAnswer) -> Result<OpOutput<()>> {
|
/// Provided [CardAnswer] has its answer time capped to deck preset.
|
||||||
|
pub fn answer_card(&mut self, answer: &mut CardAnswer) -> Result<OpOutput<()>> {
|
||||||
self.transact(Op::AnswerCard, |col| col.answer_card_inner(answer))
|
self.transact(Op::AnswerCard, |col| col.answer_card_inner(answer))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn answer_card_inner(&mut self, answer: &CardAnswer) -> Result<()> {
|
fn answer_card_inner(&mut self, answer: &mut CardAnswer) -> Result<()> {
|
||||||
let card = self
|
let card = self
|
||||||
.storage
|
.storage
|
||||||
.get_card(answer.card_id)?
|
.get_card(answer.card_id)?
|
||||||
|
@ -251,6 +258,7 @@ impl Collection {
|
||||||
let usn = self.usn()?;
|
let usn = self.usn()?;
|
||||||
|
|
||||||
let mut updater = self.card_state_updater(card)?;
|
let mut updater = self.card_state_updater(card)?;
|
||||||
|
answer.cap_answer_secs(updater.config.inner.cap_answer_time_to_secs);
|
||||||
let current_state = updater.current_card_state();
|
let current_state = updater.current_card_state();
|
||||||
if current_state != answer.current_state {
|
if current_state != answer.current_state {
|
||||||
return Err(AnkiError::invalid_input(format!(
|
return Err(AnkiError::invalid_input(format!(
|
||||||
|
@ -404,7 +412,7 @@ pub mod test_helpers {
|
||||||
{
|
{
|
||||||
let queued = self.get_next_card()?.unwrap();
|
let queued = self.get_next_card()?.unwrap();
|
||||||
let new_state = get_state(&queued.next_states);
|
let new_state = get_state(&queued.next_states);
|
||||||
self.answer_card(&CardAnswer {
|
self.answer_card(&mut CardAnswer {
|
||||||
card_id: queued.card.id,
|
card_id: queued.card.id,
|
||||||
current_state: queued.next_states.current,
|
current_state: queued.next_states.current,
|
||||||
new_state,
|
new_state,
|
||||||
|
|
|
@ -85,7 +85,7 @@ mod test {
|
||||||
));
|
));
|
||||||
|
|
||||||
// use Again on the preview
|
// use Again on the preview
|
||||||
col.answer_card(&CardAnswer {
|
col.answer_card(&mut CardAnswer {
|
||||||
card_id: c.id,
|
card_id: c.id,
|
||||||
current_state: next.current,
|
current_state: next.current,
|
||||||
new_state: next.again,
|
new_state: next.again,
|
||||||
|
@ -99,7 +99,7 @@ mod test {
|
||||||
|
|
||||||
// hard
|
// hard
|
||||||
let next = col.get_next_card_states(c.id)?;
|
let next = col.get_next_card_states(c.id)?;
|
||||||
col.answer_card(&CardAnswer {
|
col.answer_card(&mut CardAnswer {
|
||||||
card_id: c.id,
|
card_id: c.id,
|
||||||
current_state: next.current,
|
current_state: next.current,
|
||||||
new_state: next.hard,
|
new_state: next.hard,
|
||||||
|
@ -112,7 +112,7 @@ mod test {
|
||||||
|
|
||||||
// good
|
// good
|
||||||
let next = col.get_next_card_states(c.id)?;
|
let next = col.get_next_card_states(c.id)?;
|
||||||
col.answer_card(&CardAnswer {
|
col.answer_card(&mut CardAnswer {
|
||||||
card_id: c.id,
|
card_id: c.id,
|
||||||
current_state: next.current,
|
current_state: next.current,
|
||||||
new_state: next.good,
|
new_state: next.good,
|
||||||
|
@ -125,7 +125,7 @@ mod test {
|
||||||
|
|
||||||
// and then it should return to its old state once easy selected
|
// and then it should return to its old state once easy selected
|
||||||
let next = col.get_next_card_states(c.id)?;
|
let next = col.get_next_card_states(c.id)?;
|
||||||
col.answer_card(&CardAnswer {
|
col.answer_card(&mut CardAnswer {
|
||||||
card_id: c.id,
|
card_id: c.id,
|
||||||
current_state: next.current,
|
current_state: next.current,
|
||||||
new_state: next.easy,
|
new_state: next.easy,
|
||||||
|
|
Loading…
Reference in a new issue