Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions ftl/core/actions.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ actions-select = Select
actions-shortcut-key = Shortcut key: { $val }
actions-suspend-card = Suspend Card
actions-set-due-date = Set Due Date
actions-toggle-load-balancer = Toggle Load Balancer
actions-grade-now = Grade Now
actions-answer-card = Answer Card
actions-unbury-unsuspend = Unbury/Unsuspend
Expand Down
1 change: 1 addition & 0 deletions proto/anki/collection.proto
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ service CollectionService {
rpc MergeUndoEntries(generic.UInt32) returns (OpChanges);
rpc LatestProgress(generic.Empty) returns (Progress);
rpc SetWantsAbort(generic.Empty) returns (generic.Empty);
rpc SetLoadBalancerEnabled(generic.Bool) returns (OpChanges);
}

// Implicitly includes any of the above methods that are not listed in the
Expand Down
8 changes: 4 additions & 4 deletions pylib/anki/collection.py
Original file line number Diff line number Diff line change
Expand Up @@ -982,14 +982,14 @@ def set_aux_template_config(
)
return self.set_config(key, value, undoable=undoable)

def _get_enable_load_balancer(self) -> bool:
def _get_load_balancer_enabled(self) -> bool:
return self.get_config_bool(Config.Bool.LOAD_BALANCER_ENABLED)

def _set_enable_load_balancer(self, value: bool) -> None:
self.set_config_bool(Config.Bool.LOAD_BALANCER_ENABLED, value)
def _set_load_balancer_enabled(self, value: bool) -> None:
self._backend.set_load_balancer_enabled(value)

load_balancer_enabled = property(
fget=_get_enable_load_balancer, fset=_set_enable_load_balancer
fget=_get_load_balancer_enabled, fset=_set_load_balancer_enabled
)

def _get_enable_fsrs_short_term_with_steps(self) -> bool:
Expand Down
1 change: 1 addition & 0 deletions qt/aqt/about.py
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,7 @@ def on_dialog_destroyed() -> None:
"Luc Mcgrady",
"Brayan Oliveira",
"Market345",
"Yuki",
)
)

Expand Down
13 changes: 13 additions & 0 deletions rslib/src/collection/service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use anki_proto::generic;

use crate::collection::Collection;
use crate::error;
use crate::prelude::BoolKey;
use crate::prelude::Op;
use crate::progress::progress_to_proto;

impl crate::services::CollectionService for Collection {
Expand Down Expand Up @@ -49,4 +51,15 @@ impl crate::services::CollectionService for Collection {
self.state.progress.lock().unwrap().want_abort = true;
Ok(())
}

fn set_load_balancer_enabled(
&mut self,
input: generic::Bool,
) -> error::Result<anki_proto::collection::OpChanges> {
self.transact(Op::ToggleLoadBalancer, |col| {
col.set_config(BoolKey::LoadBalancerEnabled, &input.val)?;
Ok(())
})
.map(Into::into)
}
}
7 changes: 6 additions & 1 deletion rslib/src/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ pub enum Op {
SetFlag,
SortCards,
Suspend,
ToggleLoadBalancer,
UnburyUnsuspend,
UpdateCard,
UpdateConfig,
Expand Down Expand Up @@ -66,6 +67,7 @@ impl Op {
Op::RenameDeck => tr.actions_rename_deck(),
Op::ScheduleAsNew => tr.actions_forget_card(),
Op::SetDueDate => tr.actions_set_due_date(),
Op::ToggleLoadBalancer => tr.actions_toggle_load_balancer(),
Op::GradeNow => tr.actions_grade_now(),
Op::Suspend => tr.studying_suspend(),
Op::UnburyUnsuspend => tr.actions_unbury_unsuspend(),
Expand Down Expand Up @@ -170,7 +172,10 @@ impl OpChanges {
|| (c.config
&& matches!(
self.op,
Op::SetCurrentDeck | Op::UpdatePreferences | Op::UpdateDeckConfig
Op::SetCurrentDeck
| Op::UpdatePreferences
| Op::UpdateDeckConfig
| Op::ToggleLoadBalancer
))
|| c.deck_config
}
Expand Down
39 changes: 15 additions & 24 deletions rslib/src/scheduler/answering/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl CardStateUpdater {
/// state handling code from the rest of the Anki codebase.
pub(crate) fn state_context<'a>(
&'a self,
load_balancer: Option<LoadBalancerContext<'a>>,
load_balancer_ctx: Option<LoadBalancerContext<'a>>,
) -> StateContext<'a> {
StateContext {
fuzz_factor: get_fuzz_factor(self.fuzz_seed),
Expand All @@ -97,8 +97,8 @@ impl CardStateUpdater {
interval_multiplier: self.config.inner.interval_multiplier,
maximum_review_interval: self.config.inner.maximum_review_interval,
leech_threshold: self.config.inner.leech_threshold,
load_balancer: load_balancer
.map(|load_balancer| load_balancer.set_fuzz_seed(self.fuzz_seed)),
load_balancer_ctx: load_balancer_ctx
.map(|load_balancer_ctx| load_balancer_ctx.set_fuzz_seed(self.fuzz_seed)),
relearn_steps: self.relearn_steps(),
lapse_multiplier: self.config.inner.lapse_multiplier,
minimum_lapse_interval: self.config.inner.minimum_lapse_interval,
Expand Down Expand Up @@ -241,22 +241,16 @@ impl Collection {
let ctx = self.card_state_updater(card)?;
let current = ctx.current_card_state();

let load_balancer = self
.get_config_bool(BoolKey::LoadBalancerEnabled)
.then(|| {
let deckconfig_id = deck.config_id();

self.state.card_queues.as_ref().and_then(|card_queues| {
Some(
card_queues
.load_balancer
.review_context(note_id, deckconfig_id?),
)
})
})
.flatten();
let load_balancer_ctx = self.state.card_queues.as_ref().and_then(|card_queues| {
match card_queues.load_balancer.as_ref() {
None => None,
Some(load_balancer) => {
Some(load_balancer.review_context(note_id, deck.config_id()?))
}
}
});

let state_ctx = ctx.state_context(load_balancer);
let state_ctx = ctx.state_context(load_balancer_ctx);
Ok(current.next_states(&state_ctx))
}

Expand Down Expand Up @@ -354,12 +348,9 @@ impl Collection {
let deck = self.get_deck(card.deck_id)?;
if let Some(card_queues) = self.state.card_queues.as_mut() {
if let Some(deckconfig_id) = deck.and_then(|deck| deck.config_id()) {
card_queues.load_balancer.add_card(
card.id,
card.note_id,
deckconfig_id,
card.interval,
)
if let Some(load_balancer) = card_queues.load_balancer.as_mut() {
load_balancer.add_card(card.id, card.note_id, deckconfig_id, card.interval)
}
}
}
}
Expand Down
27 changes: 16 additions & 11 deletions rslib/src/scheduler/queue/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ pub(super) struct QueueBuilder {
pub(super) learning: Vec<DueCard>,
pub(super) day_learning: Vec<DueCard>,
limits: LimitTreeMap,
load_balancer: LoadBalancer,
load_balancer: Option<LoadBalancer>,
context: Context,
}

Expand Down Expand Up @@ -146,16 +146,21 @@ impl QueueBuilder {
let sort_options = sort_options(&root_deck, &config_map);
let deck_map = col.storage.get_decks_map()?;

let did_to_dcid = deck_map
.values()
.filter_map(|deck| Some((deck.id, deck.config_id()?)))
.collect::<HashMap<_, _>>();
let load_balancer = LoadBalancer::new(
timing.days_elapsed,
did_to_dcid,
col.timing_today()?.next_day_at,
&col.storage,
)?;
let load_balancer = col
.get_config_bool(BoolKey::LoadBalancerEnabled)
.then(|| {
let did_to_dcid = deck_map
.values()
.filter_map(|deck| Some((deck.id, deck.config_id()?)))
.collect::<HashMap<_, _>>();
LoadBalancer::new(
timing.days_elapsed,
did_to_dcid,
col.timing_today()?.next_day_at,
&col.storage,
)
})
.transpose()?;

Ok(QueueBuilder {
new: Vec::new(),
Expand Down
2 changes: 1 addition & 1 deletion rslib/src/scheduler/queue/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pub(crate) struct CardQueues {
/// counts are zero. Ensures we don't show a newly-due learning card after a
/// user returns from editing a review card.
current_learning_cutoff: TimestampSecs,
pub(crate) load_balancer: LoadBalancer,
pub(crate) load_balancer: Option<LoadBalancer>,
}

#[derive(Debug, Copy, Clone)]
Expand Down
14 changes: 8 additions & 6 deletions rslib/src/scheduler/queue/undo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,14 @@ impl Collection {
}

if let Some(card_queues) = self.state.card_queues.as_mut() {
match &update.entry {
QueueEntry::IntradayLearning(entry) => {
card_queues.load_balancer.remove_card(entry.id);
}
QueueEntry::Main(entry) => {
card_queues.load_balancer.remove_card(entry.id);
if let Some(load_balancer) = card_queues.load_balancer.as_mut() {
match &update.entry {
QueueEntry::IntradayLearning(entry) => {
load_balancer.remove_card(entry.id);
}
QueueEntry::Main(entry) => {
load_balancer.remove_card(entry.id);
}
}
}
}
Expand Down
6 changes: 4 additions & 2 deletions rslib/src/scheduler/states/fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@ static FUZZ_RANGES: [FuzzRange; 3] = [
impl StateContext<'_> {
/// Apply fuzz, respecting the passed bounds.
pub(crate) fn with_review_fuzz(&self, interval: f32, minimum: u32, maximum: u32) -> u32 {
self.load_balancer
self.load_balancer_ctx
.as_ref()
.and_then(|load_balancer| load_balancer.find_interval(interval, minimum, maximum))
.and_then(|load_balancer_ctx| {
load_balancer_ctx.find_interval(interval, minimum, maximum)
})
.unwrap_or_else(|| with_review_fuzz(self.fuzz_factor, interval, minimum, maximum))
}
}
Expand Down
4 changes: 2 additions & 2 deletions rslib/src/scheduler/states/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ pub(crate) struct StateContext<'a> {
pub interval_multiplier: f32,
pub maximum_review_interval: u32,
pub leech_threshold: u32,
pub load_balancer: Option<LoadBalancerContext<'a>>,
pub load_balancer_ctx: Option<LoadBalancerContext<'a>>,

// relearning
pub relearn_steps: LearningSteps<'a>,
Expand Down Expand Up @@ -137,7 +137,7 @@ impl StateContext<'_> {
interval_multiplier: 1.0,
maximum_review_interval: 36500,
leech_threshold: 8,
load_balancer: None,
load_balancer_ctx: None,
relearn_steps: LearningSteps::new(&[10.0]),
lapse_multiplier: 0.0,
minimum_lapse_interval: 1,
Expand Down