anki/proto/anki/scheduler.proto
RumovZ bd88c6d352
Ensure state mutator runs after card is rendered (#2421)
* Ensure state mutator runs after card is rendered

* Ensure ease buttons only show when states are ready

* Pass context into states mutator

* Revert queuing of state mutator hook

Now that context data is exposed users shouldn't rely on the question
having been rendered anymore.

* Use callbacks instead of signals and timeout

... to track whether the states mutator ran or failed.

* Make mutator async

* Remove State enum

* Reduce requests and compute seed on backend
2023-03-16 16:31:00 +10:00

321 lines
7.8 KiB
Protocol Buffer

// Copyright: Ankitects Pty Ltd and contributors
// License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
syntax = "proto3";
option java_multiple_files = true;
package anki.scheduler;
import "anki/generic.proto";
import "anki/cards.proto";
import "anki/decks.proto";
import "anki/collection.proto";
import "anki/config.proto";
service SchedulerService {
rpc GetQueuedCards(GetQueuedCardsRequest) returns (QueuedCards);
rpc AnswerCard(CardAnswer) returns (collection.OpChanges);
rpc SchedTimingToday(generic.Empty) returns (SchedTimingTodayResponse);
rpc StudiedToday(generic.Empty) returns (generic.String);
rpc StudiedTodayMessage(StudiedTodayMessageRequest) returns (generic.String);
rpc UpdateStats(UpdateStatsRequest) returns (generic.Empty);
rpc ExtendLimits(ExtendLimitsRequest) returns (generic.Empty);
rpc CountsForDeckToday(decks.DeckId) returns (CountsForDeckTodayResponse);
rpc CongratsInfo(generic.Empty) returns (CongratsInfoResponse);
rpc RestoreBuriedAndSuspendedCards(cards.CardIds)
returns (collection.OpChanges);
rpc UnburyDeck(UnburyDeckRequest) returns (collection.OpChanges);
rpc BuryOrSuspendCards(BuryOrSuspendCardsRequest)
returns (collection.OpChangesWithCount);
rpc EmptyFilteredDeck(decks.DeckId) returns (collection.OpChanges);
rpc RebuildFilteredDeck(decks.DeckId) returns (collection.OpChangesWithCount);
rpc ScheduleCardsAsNew(ScheduleCardsAsNewRequest)
returns (collection.OpChanges);
rpc ScheduleCardsAsNewDefaults(ScheduleCardsAsNewDefaultsRequest)
returns (ScheduleCardsAsNewDefaultsResponse);
rpc SetDueDate(SetDueDateRequest) returns (collection.OpChanges);
rpc SortCards(SortCardsRequest) returns (collection.OpChangesWithCount);
rpc SortDeck(SortDeckRequest) returns (collection.OpChangesWithCount);
rpc GetSchedulingStates(cards.CardId) returns (SchedulingStates);
rpc DescribeNextStates(SchedulingStates) returns (generic.StringList);
rpc StateIsLeech(SchedulingState) returns (generic.Bool);
rpc UpgradeScheduler(generic.Empty) returns (generic.Empty);
rpc CustomStudy(CustomStudyRequest) returns (collection.OpChanges);
rpc CustomStudyDefaults(CustomStudyDefaultsRequest)
returns (CustomStudyDefaultsResponse);
rpc RepositionDefaults(generic.Empty) returns (RepositionDefaultsResponse);
}
message SchedulingState {
message New {
uint32 position = 1;
}
message Learning {
uint32 remaining_steps = 1;
uint32 scheduled_secs = 2;
}
message Review {
uint32 scheduled_days = 1;
uint32 elapsed_days = 2;
float ease_factor = 3;
uint32 lapses = 4;
bool leeched = 5;
}
message Relearning {
Review review = 1;
Learning learning = 2;
}
message Normal {
oneof value {
New new = 1;
Learning learning = 2;
Review review = 3;
Relearning relearning = 4;
}
}
message Preview {
uint32 scheduled_secs = 1;
bool finished = 2;
}
message ReschedulingFilter {
Normal original_state = 1;
}
message Filtered {
oneof value {
Preview preview = 1;
ReschedulingFilter rescheduling = 2;
}
}
oneof value {
Normal normal = 1;
Filtered filtered = 2;
}
// The backend does not populate this field in GetQueuedCards; the front-end
// is expected to populate it based on the provided Card. If it's not set when
// answering a card, the existing custom data will not be updated.
optional string custom_data = 3;
}
message QueuedCards {
enum Queue {
NEW = 0;
LEARNING = 1;
REVIEW = 2;
}
message QueuedCard {
cards.Card card = 1;
Queue queue = 2;
SchedulingStates states = 3;
SchedulingContext context = 4;
}
repeated QueuedCard cards = 1;
uint32 new_count = 2;
uint32 learning_count = 3;
uint32 review_count = 4;
}
message GetQueuedCardsRequest {
uint32 fetch_limit = 1;
bool intraday_learning_only = 2;
}
message SchedTimingTodayResponse {
uint32 days_elapsed = 1;
int64 next_day_at = 2;
}
message StudiedTodayMessageRequest {
uint32 cards = 1;
double seconds = 2;
}
message UpdateStatsRequest {
int64 deck_id = 1;
int32 new_delta = 2;
int32 review_delta = 4;
int32 millisecond_delta = 5;
}
message ExtendLimitsRequest {
int64 deck_id = 1;
int32 new_delta = 2;
int32 review_delta = 3;
}
message CountsForDeckTodayResponse {
int32 new = 1;
int32 review = 2;
}
message CongratsInfoResponse {
uint32 learn_remaining = 1;
uint32 secs_until_next_learn = 2;
bool review_remaining = 3;
bool new_remaining = 4;
bool have_sched_buried = 5;
bool have_user_buried = 6;
bool is_filtered_deck = 7;
bool bridge_commands_supported = 8;
string deck_description = 9;
}
message UnburyDeckRequest {
enum Mode {
ALL = 0;
SCHED_ONLY = 1;
USER_ONLY = 2;
}
int64 deck_id = 1;
Mode mode = 2;
}
message BuryOrSuspendCardsRequest {
enum Mode {
SUSPEND = 0;
BURY_SCHED = 1;
BURY_USER = 2;
}
repeated int64 card_ids = 1;
repeated int64 note_ids = 2;
Mode mode = 3;
}
message ScheduleCardsAsNewRequest {
enum Context {
BROWSER = 0;
REVIEWER = 1;
}
repeated int64 card_ids = 1;
bool log = 2;
bool restore_position = 3;
bool reset_counts = 4;
optional Context context = 5;
}
message ScheduleCardsAsNewDefaultsRequest {
ScheduleCardsAsNewRequest.Context context = 1;
}
message ScheduleCardsAsNewDefaultsResponse {
bool restore_position = 1;
bool reset_counts = 2;
}
message SetDueDateRequest {
repeated int64 card_ids = 1;
string days = 2;
config.OptionalStringConfigKey config_key = 3;
}
message SortCardsRequest {
repeated int64 card_ids = 1;
uint32 starting_from = 2;
uint32 step_size = 3;
bool randomize = 4;
bool shift_existing = 5;
}
message SortDeckRequest {
int64 deck_id = 1;
bool randomize = 2;
}
message SchedulingStates {
SchedulingState current = 1;
SchedulingState again = 2;
SchedulingState hard = 3;
SchedulingState good = 4;
SchedulingState easy = 5;
}
message CardAnswer {
enum Rating {
AGAIN = 0;
HARD = 1;
GOOD = 2;
EASY = 3;
}
int64 card_id = 1;
SchedulingState current_state = 2;
SchedulingState new_state = 3;
Rating rating = 4;
int64 answered_at_millis = 5;
uint32 milliseconds_taken = 6;
}
message CustomStudyRequest {
message Cram {
enum CramKind {
// due cards in due order
CRAM_KIND_DUE = 0;
// new cards in added order
CRAM_KIND_NEW = 1;
// review cards in random order
CRAM_KIND_REVIEW = 2;
// all cards in random order; no rescheduling
CRAM_KIND_ALL = 3;
}
CramKind kind = 1;
// the maximum number of cards
uint32 card_limit = 2;
// cards must match one of these, if unempty
repeated string tags_to_include = 3;
// cards must not match any of these
repeated string tags_to_exclude = 4;
}
int64 deck_id = 1;
oneof value {
// increase new limit by x
int32 new_limit_delta = 2;
// increase review limit by x
int32 review_limit_delta = 3;
// repeat cards forgotten in the last x days
uint32 forgot_days = 4;
// review cards due in the next x days
uint32 review_ahead_days = 5;
// preview new cards added in the last x days
uint32 preview_days = 6;
Cram cram = 7;
}
}
message SchedulingContext {
string deck_name = 1;
uint64 seed = 2;
}
message SchedulingStatesWithContext {
SchedulingStates states = 1;
SchedulingContext context = 2;
}
message CustomStudyDefaultsRequest {
int64 deck_id = 1;
}
message CustomStudyDefaultsResponse {
message Tag {
string name = 1;
bool include = 2;
bool exclude = 3;
}
repeated Tag tags = 1;
uint32 extend_new = 2;
uint32 extend_review = 3;
uint32 available_new = 4;
uint32 available_review = 5;
// in v3, counts for children are provided separately
uint32 available_new_in_children = 6;
uint32 available_review_in_children = 7;
}
message RepositionDefaultsResponse {
bool random = 1;
bool shift = 2;
}