feat(03-01): extend Progress type, add LessonPhase, update rate limits
- Progress: added totalCorrect, totalErrors, errorKeyCounts, lastPlayedLevels - New LessonPhase type: discover | practice | words - Rate limits: 10 text / 5 image per day (was 1 each) - Updated screens.ts with new Progress field defaults - Updated existing tests for new rate limits and Progress shape Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -230,9 +230,9 @@ describe("Rate limiting", () => {
|
||||
expect(canCallImage).toBe(true);
|
||||
});
|
||||
|
||||
it("checkRateLimit returns false when at limit", async () => {
|
||||
await incrementApiCall(db, "text");
|
||||
await incrementApiCall(db, "image");
|
||||
it("checkRateLimit returns false when at limit (10 text, 5 image)", async () => {
|
||||
for (let i = 0; i < 10; i++) await incrementApiCall(db, "text");
|
||||
for (let i = 0; i < 5; i++) await incrementApiCall(db, "image");
|
||||
|
||||
const canCallText = await checkRateLimit(db, "text");
|
||||
const canCallImage = await checkRateLimit(db, "image");
|
||||
@@ -241,7 +241,7 @@ describe("Rate limiting", () => {
|
||||
});
|
||||
|
||||
it("incrementApiCall increments correct counter", async () => {
|
||||
await incrementApiCall(db, "text");
|
||||
for (let i = 0; i < 10; i++) await incrementApiCall(db, "text");
|
||||
|
||||
const canCallText = await checkRateLimit(db, "text");
|
||||
const canCallImage = await checkRateLimit(db, "image");
|
||||
@@ -251,8 +251,8 @@ describe("Rate limiting", () => {
|
||||
|
||||
it("rate limit resets when lastApiCallDate differs from today", async () => {
|
||||
// Increment to hit limit
|
||||
await incrementApiCall(db, "text");
|
||||
await incrementApiCall(db, "image");
|
||||
for (let i = 0; i < 10; i++) await incrementApiCall(db, "text");
|
||||
for (let i = 0; i < 5; i++) await incrementApiCall(db, "image");
|
||||
|
||||
// Manually set lastApiCallDate to yesterday
|
||||
const { getSettings, saveSettings } = await import("../storage/db");
|
||||
|
||||
+5
-1
@@ -5,6 +5,8 @@ import type { GeminiConfig } from "./config";
|
||||
const GEMINI_BASE_URL =
|
||||
"https://generativelanguage.googleapis.com/v1beta/models";
|
||||
const RETRY_DELAYS = [1000, 2000, 4000];
|
||||
const TEXT_RATE_LIMIT = 10;
|
||||
const IMAGE_RATE_LIMIT = 5;
|
||||
|
||||
function sleep(ms: number): Promise<void> {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
@@ -159,7 +161,9 @@ export async function checkRateLimit(
|
||||
await saveSettings(db, settings);
|
||||
}
|
||||
|
||||
return settings.apiCallsToday[type] < 1;
|
||||
return type === "text"
|
||||
? settings.apiCallsToday.text < TEXT_RATE_LIMIT
|
||||
: settings.apiCallsToday.image < IMAGE_RATE_LIMIT;
|
||||
}
|
||||
|
||||
export async function incrementApiCall(
|
||||
|
||||
@@ -33,6 +33,10 @@ describe("IndexedDB wrapper", () => {
|
||||
sessionDates: [],
|
||||
selectedCharacter: "fee",
|
||||
selectedLayout: "de",
|
||||
totalCorrect: 0,
|
||||
totalErrors: 0,
|
||||
errorKeyCounts: {},
|
||||
lastPlayedLevels: [],
|
||||
};
|
||||
await saveProgress(db, progress);
|
||||
const result = await getProgress(db);
|
||||
|
||||
@@ -14,8 +14,14 @@ export interface Progress {
|
||||
sessionDates: string[]; // ISO date strings (days only)
|
||||
selectedCharacter: CompanionType;
|
||||
selectedLayout: KeyboardLayout;
|
||||
totalCorrect: number;
|
||||
totalErrors: number;
|
||||
errorKeyCounts: Record<string, number>;
|
||||
lastPlayedLevels: number[]; // last 3 played levels for review mechanic
|
||||
}
|
||||
|
||||
export type LessonPhase = "discover" | "practice" | "words";
|
||||
|
||||
// Companion assets store
|
||||
export interface CompanionAssets {
|
||||
characterType: CompanionType;
|
||||
|
||||
@@ -70,6 +70,10 @@ export function initWelcomeScreen(
|
||||
sessionDates: [],
|
||||
selectedCharacter: selectedCompanion,
|
||||
selectedLayout: selectedLayout,
|
||||
totalCorrect: 0,
|
||||
totalErrors: 0,
|
||||
errorKeyCounts: {},
|
||||
lastPlayedLevels: [],
|
||||
};
|
||||
await saveProgress(db, progress);
|
||||
navigateTo("forest");
|
||||
|
||||
Reference in New Issue
Block a user