Closed hockyy closed 2 months ago
import { app, ipcMain } from 'electron';
import { Level } from 'level';
import path from 'path';
const SkillConstants {
'Writing' : 'writing'
'Conveyance' : 'conveyance'
'Translation' : 'translation'
}
class Skill {
skillName: string
// epoch
lastUpdated: number;
// epoch
level: number;
constructor (name) {
this.skillName = name;
this.lastUpdated = now();
this.level = 0;
}
}
class SRSData {
character: string;
// epoch
lastUpdated: number;
// epoch
lastCreated: number;
skills: map<string, Skill>
constructor (char) {
this.character = char;
this.lastUpdated = now();
this.lastCreated = now();
for(const auto key of : SkillConstants.keys()) {
this.skills.insert(SkillConstants[key], Skill());
}
this.writing =
}
}
class OrderedTree {
// tuple is basically like c++ tuple, comparator is tie(el[0], el[1], el[2], ..) < tie(other[0], other[1], other[2], ...)
container: Set
generateKey: SRSData -> tuple
constructor(SRSData[] initialData : SRSData[], keyGenerator : (SRSData a) -> tuple) {
this.generateKey = keyGenerator
for (const auto curData : initialData) {
insert(curData)
}
}
insert(SRSData a) {
currentKey = this.generateKey(curData);
// Check if key exist, if not then skip
container.insert(currentKey, a.character)
}
erase(SRSData a) {
currentKey = this.generateKey(curData);
container.erase(currentKey)
}
orderOfKey(SRSData a) {
currentKey = this.generateKey(curData);
container.getOrder(currentKey);
return -1 if not exist
}
findByOrder(int index) {
return null if >= container.size()
else return container[index];
}
}
class SRSDatabase {
static learningTrees: map<string, OrderedTree>
static srsData: map<string, SRSData>
static setup() {
for(const auto key of : SkillConstants.keys()) {
// classicKeyGen is just refresh by lastUpdated (not yet srs), srs shall compute the perfect srs formula according to the level
this.learningTrees.add(SkillConstants[key], OrderedTree(srsData.values(), classicKeyGen));
}
}
static loadSRS() {
const prefix = `srs/${lang}/`; // Define the prefix for keys
const learningState = {};
// Define the range for the query
const queryOptions = {
gte: prefix, // Start of the range: include the prefix
lte: `${prefix}\uFFFF`, // End of the range: highest value that still matches the prefix
};
// Efficiently iterate over keys within the specified range
for await (const [key, value] of this.db.iterator(queryOptions)) {
const strippedKey = key.substring(prefix.length);
let parsedValue;
parsedValue = JSON.parse(value) as SRSData
srsData[strippedKey] = parsedValue;
}
}
static insertNew(character) {
// now let's just support 1 character srs, 1 terms is a little bit too muhcowkakoawokaw
SRSData newSrs(character)
}
static updateLearningTrees(character a, skills: Skill, newLevel: number) {
for(const auto key of : SkillConstants.keys()) {
// classicKeyGen is just refresh by lastUpdated (not yet srs), srs shall compute the perfect srs formula according to the level
const ptrToSRSData = this.srsData[a];
oldKey = this.learningTrees[SkillConstants[key]].generateKey(a);
this.learningTrees[SkillConstants[key]].erase(a);
ptrToSRSData.skill[SkillName].level = newLevel;
ptrToSRSData.skill[SkillName].lastUpdated = now();
ptrToSRSData.lastUpdated = now();
this.learningTrees[SkillConstants[key]].insert(ptrToSRSData);
}
}
}
class Learning {
static dbPath;
static db;
static setup() {
// Define the path to the database
this.dbPath = path.join(app.getPath('userData'), 'learningStateDB');
this.db = new Level(this.dbPath);
}
static registerHandler() {
ipcMain.handle('loadLearningState', async (event, lang) => {
try {
const prefix = `${lang}/`; // Define the prefix for keys
const learningState = {};
// Define the range for the query
const queryOptions = {
gte: prefix, // Start of the range: include the prefix
lte: `${prefix}\uFFFF`, // End of the range: highest value that still matches the prefix
};
// Efficiently iterate over keys within the specified range
for await (const [key, value] of this.db.iterator(queryOptions)) {
const strippedKey = key.substring(prefix.length);
let parsedValue;
try {
parsedValue = JSON.parse(value);
if (typeof parsedValue.level !== 'number' || typeof parsedValue.updTime !== 'number') {
throw new Error('Invalid format');
}
} catch (e) {
// If parsing fails, assume it's an old format (number)
parsedValue = {
level: parseInt(value, 10),
updTime: Date.now()
};
await this.db.put(key, JSON.stringify(parsedValue));
}
learningState[strippedKey] = parsedValue;
}
return learningState;
} catch (error) {
console.error('Error loading learning state:', error);
return {};
}
});
// Handler to update a specific content's learning state
ipcMain.handle('updateContent', async (event, content, lang, data) => {
if (!content) return true;
try {
await this.db.put(`${lang}/${content}`, JSON.stringify(data));
return true; // Indicate success
} catch (error) {
console.error('Error updating content:', error);
return false; // Indicate failure
}
});
// Handler to update a batch of contents' learning states
ipcMain.handle('updateContentBatch', async (event, contents: LearningStateType, lang) => {
if (!contents) return true;
try {
for (const [key, value] of Object.entries(contents)) {
const goUpdate = async () => {
await this.db.put(`${lang}/${key}`, JSON.stringify(value));
}
this.db.get(`${lang}/${key}`).then(async val => {
const parsedVal = JSON.parse(val);
if (parsedVal.level < value.level) await goUpdate();
}).catch(async () => {
await goUpdate();
})
}
return true; // Indicate success
} catch (error) {
console.error('Error updating content:', error);
return false; // Indicate failure
}
});
}
}
export default Learning;
day 556 finding someone who would help me with this repo
Radical support and personalization
SRS
Focus more on kanji / hanzi
There are several ways to put up a context:
How to mine
Starting a new session:
SRS consists of
Writing has different modes, the behavior is:
Support back