Skip to content

Commit 904e44c

Browse files
authored
Merge pull request #24 from xiaohajiayou/dev
Feat: start to collect review log for futture fsrs optimize
2 parents 6254778 + 6be0fa8 commit 904e44c

File tree

2 files changed

+139
-1
lines changed

2 files changed

+139
-1
lines changed

src/popup/daily-review.js

+25
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import { descriptionOf, idOf, problemSorterArr } from "./util/sort";
1010
import {handleAddProblem} from "./script/submission.js"
1111
// 在文件顶部导入 SweetAlert2
1212
import Swal from 'sweetalert2';
13+
// 导入 getAllRevlogs 函数
14+
import { getAllRevlogs, exportRevlogsToCSV } from './util/fsrs.js';
1315

1416
// 在文件开头添加
1517
const LAST_AVERAGE_KEY = 'lastRetrievabilityAverage';
@@ -347,6 +349,7 @@ export function updateCardDisplay() {
347349

348350
updateStats(); // 更新统计信息,传递当前显示的卡片数量
349351

352+
350353
createReviewCards(); // 创建新的卡片
351354
}
352355

@@ -1001,6 +1004,28 @@ document.addEventListener('DOMContentLoaded', async function() {
10011004
});
10021005
});
10031006
});
1007+
1008+
// 调试 revlogs
1009+
try {
1010+
console.log('===== 开始调试 revlogs =====');
1011+
const allRevlogs = await getAllRevlogs();
1012+
console.log('所有复习日志:', allRevlogs);
1013+
1014+
// 计算总复习次数
1015+
let totalReviews = 0;
1016+
Object.keys(allRevlogs).forEach(cardId => {
1017+
totalReviews += allRevlogs[cardId]?.length || 0;
1018+
});
1019+
console.log(`总复习次数: ${totalReviews}`);
1020+
1021+
// 导出 CSV 并打印
1022+
const csvContent = await exportRevlogsToCSV();
1023+
console.log('CSV 格式的复习日志:');
1024+
console.log(csvContent);
1025+
console.log('===== 结束调试 revlogs =====');
1026+
} catch (error) {
1027+
console.error('调试 revlogs 时出错:', error);
1028+
}
10041029
});
10051030

10061031

src/popup/util/fsrs.js

+114-1
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,34 @@ export const calculateNextReview = (problem, feedback) => {
116116
}
117117
};
118118

119+
// 将状态转换为数字
120+
const stateToNumber = (state) => {
121+
switch (state) {
122+
case 'New': return 0;
123+
case 'Learning': return 1;
124+
case 'Review': return 2;
125+
case 'Relearning': return 3;
126+
default: return 0;
127+
}
128+
};
129+
119130
// 5. 更新问题状态
120131
export const updateProblemWithFSRS = (problem, feedback) => {
121132
const now = Date.now();
122133
const fsrsResult = calculateNextReview(problem, feedback);
123-
134+
135+
// 创建新的复习日志条目,只包含必要字段
136+
const newRevlog = {
137+
card_id: problem.index, // 使用问题索引作为卡片ID
138+
review_time: now, // 复习时间(毫秒时间戳)
139+
review_rating: qualityToRating(feedback.quality), // 复习评分 (1-4)
140+
review_state: stateToNumber(problem.fsrsState?.state || 'New') // 复习状态 (0-3)
141+
};
142+
143+
// 将复习日志存储到单独的 localStorage 键中
144+
saveRevlog(problem.index, newRevlog);
145+
146+
// 更新问题状态(不修改原有结构)
124147
problem.fsrsState = {
125148
...problem.fsrsState,
126149
difficulty: fsrsResult.difficulty,
@@ -136,3 +159,93 @@ export const updateProblemWithFSRS = (problem, feedback) => {
136159
problem.modificationTime = now;
137160
return problem;
138161
};
162+
163+
// 保存单个复习日志
164+
export const saveRevlog = async (cardId, revlog) => {
165+
try {
166+
// 从 localStorage 获取现有的复习日志
167+
const existingRevlogsStr = await new Promise((resolve) => {
168+
chrome.storage.local.get(['fsrs_revlogs'], (result) => {
169+
resolve(result.fsrs_revlogs || '{}');
170+
});
171+
});
172+
173+
let existingRevlogs;
174+
try {
175+
existingRevlogs = JSON.parse(existingRevlogsStr);
176+
} catch (e) {
177+
console.error('Error parsing revlogs:', e);
178+
existingRevlogs = {};
179+
}
180+
181+
// 确保该卡片的日志数组存在
182+
if (!existingRevlogs[cardId]) {
183+
existingRevlogs[cardId] = [];
184+
}
185+
186+
// 添加新的复习日志
187+
existingRevlogs[cardId].push(revlog);
188+
189+
// 保存回 localStorage
190+
await new Promise((resolve) => {
191+
chrome.storage.local.set({ 'fsrs_revlogs': JSON.stringify(existingRevlogs) });
192+
resolve();
193+
});
194+
195+
return true;
196+
} catch (error) {
197+
console.error('Error saving revlog:', error);
198+
return false;
199+
}
200+
};
201+
202+
// 获取所有复习日志
203+
export const getAllRevlogs = async () => {
204+
try {
205+
const revlogsStr = await new Promise((resolve) => {
206+
chrome.storage.local.get(['fsrs_revlogs'], (result) => {
207+
resolve(result.fsrs_revlogs || '{}');
208+
});
209+
});
210+
211+
let allRevlogs;
212+
try {
213+
allRevlogs = JSON.parse(revlogsStr);
214+
} catch (e) {
215+
console.error('Error parsing revlogs:', e);
216+
return {};
217+
}
218+
219+
return allRevlogs;
220+
} catch (error) {
221+
console.error('Error getting revlogs:', error);
222+
return {};
223+
}
224+
};
225+
226+
// 导出复习日志为CSV格式
227+
export const exportRevlogsToCSV = async () => {
228+
try {
229+
// 获取所有复习日志
230+
const allRevlogs = await getAllRevlogs();
231+
232+
// CSV 头部 - 只包含必要字段
233+
const csvHeader = 'card_id,review_time,review_rating,review_state\n';
234+
235+
// 收集所有卡片的复习日志
236+
let csvContent = csvHeader;
237+
238+
Object.keys(allRevlogs).forEach(cardId => {
239+
const cardRevlogs = allRevlogs[cardId] || [];
240+
cardRevlogs.forEach(log => {
241+
// 只导出必要字段
242+
csvContent += `${log.card_id},${log.review_time},${log.review_rating},${log.review_state}\n`;
243+
});
244+
});
245+
246+
return csvContent;
247+
} catch (error) {
248+
console.error('Error exporting revlogs to CSV:', error);
249+
return '';
250+
}
251+
};

0 commit comments

Comments
 (0)