Don't rely on frontend to cap time taken in v3
This commit is contained in:
parent
7bfd7245e0
commit
d90608198f
@ -190,10 +190,13 @@ class Card(DeprecatedNamesMixin):
|
||||
"autoplay"
|
||||
]
|
||||
|
||||
def time_taken(self) -> int:
|
||||
"Time taken to answer card, in integer MS."
|
||||
def time_taken(self, capped: bool = True) -> int:
|
||||
"""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)
|
||||
return min(total, self.time_limit())
|
||||
if capped:
|
||||
total = min(total, self.time_limit())
|
||||
return total
|
||||
|
||||
def description(self) -> str:
|
||||
dict_copy = dict(self.__dict__)
|
||||
|
@ -493,7 +493,7 @@ limit ?"""
|
||||
card.did,
|
||||
new_delta=new_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
|
||||
|
@ -81,7 +81,7 @@ class Scheduler(SchedulerBaseWithLegacy):
|
||||
new_state=new_state,
|
||||
rating=rating,
|
||||
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:
|
||||
|
@ -182,7 +182,7 @@ impl SchedulerService for Backend {
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,12 @@ pub struct CardAnswer {
|
||||
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
|
||||
/// current state, and to apply a state change to it.
|
||||
struct CardStateUpdater {
|
||||
@ -238,11 +244,12 @@ impl Collection {
|
||||
}
|
||||
|
||||
/// 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))
|
||||
}
|
||||
|
||||
fn answer_card_inner(&mut self, answer: &CardAnswer) -> Result<()> {
|
||||
fn answer_card_inner(&mut self, answer: &mut CardAnswer) -> Result<()> {
|
||||
let card = self
|
||||
.storage
|
||||
.get_card(answer.card_id)?
|
||||
@ -251,6 +258,7 @@ impl Collection {
|
||||
let usn = self.usn()?;
|
||||
|
||||
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();
|
||||
if current_state != answer.current_state {
|
||||
return Err(AnkiError::invalid_input(format!(
|
||||
@ -404,7 +412,7 @@ pub mod test_helpers {
|
||||
{
|
||||
let queued = self.get_next_card()?.unwrap();
|
||||
let new_state = get_state(&queued.next_states);
|
||||
self.answer_card(&CardAnswer {
|
||||
self.answer_card(&mut CardAnswer {
|
||||
card_id: queued.card.id,
|
||||
current_state: queued.next_states.current,
|
||||
new_state,
|
||||
|
@ -85,7 +85,7 @@ mod test {
|
||||
));
|
||||
|
||||
// use Again on the preview
|
||||
col.answer_card(&CardAnswer {
|
||||
col.answer_card(&mut CardAnswer {
|
||||
card_id: c.id,
|
||||
current_state: next.current,
|
||||
new_state: next.again,
|
||||
@ -99,7 +99,7 @@ mod test {
|
||||
|
||||
// hard
|
||||
let next = col.get_next_card_states(c.id)?;
|
||||
col.answer_card(&CardAnswer {
|
||||
col.answer_card(&mut CardAnswer {
|
||||
card_id: c.id,
|
||||
current_state: next.current,
|
||||
new_state: next.hard,
|
||||
@ -112,7 +112,7 @@ mod test {
|
||||
|
||||
// good
|
||||
let next = col.get_next_card_states(c.id)?;
|
||||
col.answer_card(&CardAnswer {
|
||||
col.answer_card(&mut CardAnswer {
|
||||
card_id: c.id,
|
||||
current_state: next.current,
|
||||
new_state: next.good,
|
||||
@ -125,7 +125,7 @@ mod test {
|
||||
|
||||
// and then it should return to its old state once easy selected
|
||||
let next = col.get_next_card_states(c.id)?;
|
||||
col.answer_card(&CardAnswer {
|
||||
col.answer_card(&mut CardAnswer {
|
||||
card_id: c.id,
|
||||
current_state: next.current,
|
||||
new_state: next.easy,
|
||||
|
Loading…
Reference in New Issue
Block a user