@ankimcp/anki-mcp-server
Version:
Model Context Protocol server for Anki - enables AI assistants to interact with your Anki flashcards
92 lines • 3.6 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.deckStats = deckStats;
const stats_utils_1 = require("../../../../../utils/stats.utils.js");
const deck_hierarchy_utils_1 = require("../../../../../utils/deck-hierarchy.utils.js");
const card_states_utils_1 = require("../../../../../utils/card-states.utils.js");
async function deckStats(params, client) {
const { deck, easeBuckets = [2.0, 2.5, 3.0], intervalBuckets = [7, 21, 90], } = params;
const deckNamesAndIds = await client.invoke("deckNamesAndIds", {});
const deckId = deckNamesAndIds?.[deck];
if (deckId == null) {
throw new Error(`Deck "${deck}" not found`);
}
const subtreeDeckNames = Object.keys(deckNamesAndIds).filter((name) => name === deck || (0, deck_hierarchy_utils_1.isDescendantOf)(name, deck));
const deckStatsResponse = await client.invoke("getDeckStats", {
decks: subtreeDeckNames,
});
const rootDeckStats = deckStatsResponse?.[String(deckId)];
if (!rootDeckStats) {
throw new Error(`Deck "${deck}" not found in statistics response`);
}
const newCount = rootDeckStats.new_count || 0;
const learning = rootDeckStats.learn_count || 0;
const review = rootDeckStats.review_count || 0;
let total = 0;
for (const descendantName of subtreeDeckNames) {
const descId = deckNamesAndIds[descendantName];
const descStats = descId != null ? deckStatsResponse?.[String(descId)] : undefined;
total += descStats?.total_in_deck ?? 0;
}
const other = Math.max(0, total - newCount - learning - review);
const counts = {
total,
new: newCount,
learning,
review,
other,
};
const deckScope = (0, card_states_utils_1.deckScopeQuery)(deck);
const cardIds = await client.invoke("findCards", {
query: deckScope,
});
if (cardIds != null && !Array.isArray(cardIds)) {
throw new Error("Invalid findCards response: expected array");
}
if (!cardIds || cardIds.length === 0) {
return {
success: true,
deck,
counts,
states: (0, card_states_utils_1.emptyCardStateCounts)(),
ease: (0, stats_utils_1.computeDistribution)([], { boundaries: easeBuckets }),
intervals: (0, stats_utils_1.computeDistribution)([], {
boundaries: intervalBuckets,
unitSuffix: "d",
}),
};
}
const states = await (0, card_states_utils_1.fetchCardStateCounts)(client, deckScope);
const easeFactorsRaw = await client.invoke("getEaseFactors", {
cards: cardIds,
});
if (!Array.isArray(easeFactorsRaw)) {
throw new Error("Invalid getEaseFactors response: expected array");
}
const easeValues = easeFactorsRaw
.map((e) => e / 1000)
.filter((e) => e > 0);
const intervalsRaw = await client.invoke("getIntervals", {
cards: cardIds,
});
if (!Array.isArray(intervalsRaw)) {
throw new Error("Invalid getIntervals response: expected array");
}
const intervalValues = intervalsRaw.filter((i) => i > 0);
const ease = (0, stats_utils_1.computeDistribution)(easeValues, {
boundaries: easeBuckets,
});
const intervals = (0, stats_utils_1.computeDistribution)(intervalValues, {
boundaries: intervalBuckets,
unitSuffix: "d",
});
return {
success: true,
deck,
counts,
states,
ease,
intervals,
};
}
//# sourceMappingURL=deckStats.action.js.map