mirror of
https://github.com/ankitects/anki.git
synced 2025-11-09 14:17:13 -05:00
Notes: - The fuzz seed is now derived from the card id and # of reps, so if a card is undone and done again, the same fuzz will be used. - The intervals shown on the answer buttons now include the fuzz, instead of hiding it from the user. This will prevent questions about due dates being different to what was shown on the buttons, but will create questions about due dates being different for cards with the same interval, and some people may find it distracting for learning cards. The new approach is easier to reason about, but time will tell whether it's a net gain or not. - The env var we were using to shift the clock away from rollover for unit tests has been repurposed to also disable fuzzing, which simplifies the tests. - Cards in filtered decks without scheduling now have the preview delay fuzzed. - Sub-day learning cards are mostly fuzzed like before, but will apply the up-to-5-minutes of fuzz regardless of the time of day. - The answer buttons now round minute values, as the fuzz on short intervals is distracting.
75 lines
1.9 KiB
Rust
75 lines
1.9 KiB
Rust
// Copyright: Ankitects Pty Ltd and contributors
|
|
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
|
|
|
|
use crate::define_newtype;
|
|
use chrono::prelude::*;
|
|
use lazy_static::lazy_static;
|
|
use std::env;
|
|
use std::time;
|
|
|
|
define_newtype!(TimestampSecs, i64);
|
|
define_newtype!(TimestampMillis, i64);
|
|
|
|
impl TimestampSecs {
|
|
pub fn now() -> Self {
|
|
Self(elapsed().as_secs() as i64)
|
|
}
|
|
|
|
pub fn zero() -> Self {
|
|
Self(0)
|
|
}
|
|
|
|
pub fn elapsed_secs(self) -> u64 {
|
|
(Self::now().0 - self.0).max(0) as u64
|
|
}
|
|
|
|
/// YYYY-mm-dd
|
|
pub(crate) fn date_string(self, offset: FixedOffset) -> String {
|
|
offset.timestamp(self.0, 0).format("%Y-%m-%d").to_string()
|
|
}
|
|
|
|
pub fn local_utc_offset(self) -> FixedOffset {
|
|
*Local.timestamp(self.0, 0).offset()
|
|
}
|
|
|
|
pub fn datetime(self, utc_offset: FixedOffset) -> DateTime<FixedOffset> {
|
|
utc_offset.timestamp(self.0, 0)
|
|
}
|
|
}
|
|
|
|
impl TimestampMillis {
|
|
pub fn now() -> Self {
|
|
Self(elapsed().as_millis() as i64)
|
|
}
|
|
|
|
pub fn zero() -> Self {
|
|
Self(0)
|
|
}
|
|
|
|
pub fn as_secs(self) -> TimestampSecs {
|
|
TimestampSecs(self.0 / 1000)
|
|
}
|
|
}
|
|
|
|
lazy_static! {
|
|
pub(crate) static ref TESTING: bool = env::var("ANKI_TEST_MODE").is_ok();
|
|
}
|
|
|
|
fn elapsed() -> time::Duration {
|
|
if *TESTING {
|
|
// shift clock around rollover time to accomodate Python tests that make bad assumptions.
|
|
// we should update the tests in the future and remove this hack.
|
|
let mut elap = time::SystemTime::now()
|
|
.duration_since(time::SystemTime::UNIX_EPOCH)
|
|
.unwrap();
|
|
let now = Local::now();
|
|
if now.hour() >= 2 && now.hour() < 4 {
|
|
elap -= time::Duration::from_secs(60 * 60 * 2);
|
|
}
|
|
elap
|
|
} else {
|
|
time::SystemTime::now()
|
|
.duration_since(time::SystemTime::UNIX_EPOCH)
|
|
.unwrap()
|
|
}
|
|
}
|