使用 NucleonUnion & ElectronUnion 取代繁琐的 AtomicFiles
This commit is contained in:
222
particles.py
222
particles.py
@@ -3,49 +3,43 @@ import toml
|
||||
import time
|
||||
import auxiliary as aux
|
||||
|
||||
import time
|
||||
|
||||
class Electron():
|
||||
"""电子: 记忆分析元数据及算法"""
|
||||
algorithm = "SM-2" # 暂时使用 SM-2 算法进行记忆拟合, 考虑 SM-15 替代
|
||||
"""
|
||||
content = "" # 内容
|
||||
efactor = 2.5 # 易度系数, 越大越简单, 最大为5
|
||||
real_rept = 0 # (实际)重复次数
|
||||
rept = 0 # (有效)重复次数
|
||||
interval = 0 # 最佳间隔
|
||||
last_date = 0 # 上一次复习的时间戳
|
||||
next_date = 0 # 将要复习的时间戳
|
||||
is_activated = 0 # 激活状态
|
||||
# *NOTE: 此处"时间戳"是以天为单位的整数, 即 UNIX 时间戳除以一天的秒数取整
|
||||
last_modify = 0 # 最后修改时间戳(此处是UNIX时间戳)
|
||||
"""
|
||||
def __init__(self, content: str, data: dict):
|
||||
|
||||
def __init__(self, content: str, metadata: dict):
|
||||
self.content = content
|
||||
self.efactor = data.get('efactor', 2.5)
|
||||
self.real_rept = data.get('real_rept', 0)
|
||||
self.rept = data.get('rept', 0)
|
||||
self.interval = data.get('interval', 0)
|
||||
self.last_date = data.get('last_date', 0)
|
||||
self.next_date = data.get('next_date', 0)
|
||||
self.is_activated = data.get('is_activated', 0)
|
||||
self.last_modify = time.time()
|
||||
self.metadata = metadata
|
||||
if metadata == {}:
|
||||
#print("NULL")
|
||||
self._default_init()
|
||||
|
||||
def _default_init(self):
|
||||
defaults = {
|
||||
'efactor': 2.5, # 易度系数, 越大越简单, 最大为5
|
||||
'real_rept': 0, # (实际)重复次数
|
||||
'rept': 0, # (有效)重复次数
|
||||
'interval': 0, # 最佳间隔
|
||||
'last_date': 0, # 上一次复习的时间戳
|
||||
'next_date': 0, # 将要复习的时间戳
|
||||
'is_activated': 0, # 激活状态
|
||||
# *NOTE: 此处"时间戳"是以天为单位的整数, 即 UNIX 时间戳除以一天的秒数取整
|
||||
'last_modify': time.time() # 最后修改时间戳(此处是UNIX时间戳)
|
||||
}
|
||||
self.metadata = defaults
|
||||
|
||||
def activate(self):
|
||||
self.is_activated = 1
|
||||
self.metadata['is_activated'] = 1
|
||||
self.metadata['last_modify'] = time.time()
|
||||
|
||||
def modify(self, var: str, value):
|
||||
setattr(self, var, value)
|
||||
self.last_modify = time.time()
|
||||
|
||||
def export_data(self):
|
||||
return {
|
||||
'efactor': self.efactor,
|
||||
'real_rept': self.real_rept,
|
||||
'rept': self.rept,
|
||||
'interval': self.interval,
|
||||
'last_date': self.last_date,
|
||||
'next_date': self.next_date,
|
||||
'is_activated': self.is_activated
|
||||
}
|
||||
if var in self.metadata:
|
||||
self.metadata[var] = value
|
||||
self.metadata['last_modify'] = time.time()
|
||||
else:
|
||||
print(f"警告: '{var}' 非已知元数据字段")
|
||||
|
||||
def revisor(self, quality: int = 5, is_new_activation: bool = False):
|
||||
"""SM-2 算法迭代决策机制实现
|
||||
@@ -58,85 +52,120 @@ class Electron():
|
||||
if quality == -1:
|
||||
return -1
|
||||
|
||||
self.efactor = self.efactor + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))
|
||||
self.efactor = max(1.3, self.efactor)
|
||||
self.metadata['efactor'] = self.metadata['efactor'] + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))
|
||||
self.metadata['efactor'] = max(1.3, self.metadata['efactor'])
|
||||
|
||||
if quality < 3:
|
||||
# 若保留率低于 3,重置重复次数
|
||||
self.rept = 0
|
||||
self.interval = 0 # 设为0,以便下面重新计算 I(1)
|
||||
self.metadata['rept'] = 0
|
||||
self.metadata['interval'] = 0 # 设为0,以便下面重新计算 I(1)
|
||||
else:
|
||||
self.rept += 1
|
||||
self.real_rept += 1
|
||||
self.metadata['rept'] += 1
|
||||
|
||||
self.metadata['real_rept'] += 1
|
||||
|
||||
if is_new_activation: # 初次激活
|
||||
self.rept = 0
|
||||
self.efactor = 2.5
|
||||
self.metadata['rept'] = 0
|
||||
self.metadata['efactor'] = 2.5
|
||||
|
||||
if self.rept == 0: # 刚被重置或初次激活后复习
|
||||
self.interval = 1 # I(1)
|
||||
elif self.rept == 1:
|
||||
self.interval = 6 # I(2) 经验公式
|
||||
if self.metadata['rept'] == 0: # 刚被重置或初次激活后复习
|
||||
self.metadata['interval'] = 1 # I(1)
|
||||
elif self.metadata['rept'] == 1:
|
||||
self.metadata['interval'] = 6 # I(2) 经验公式
|
||||
else:
|
||||
self.interval = round(self.interval * self.efactor)
|
||||
self.metadata['interval'] = round(self.metadata['interval'] * self.metadata['efactor'])
|
||||
|
||||
self.last_date = aux.get_daystamp()
|
||||
self.next_date = aux.get_daystamp() + self.interval
|
||||
self.metadata['last_date'] = aux.get_daystamp()
|
||||
self.metadata['next_date'] = aux.get_daystamp() + self.metadata['interval']
|
||||
self.metadata['last_modify'] = time.time()
|
||||
|
||||
def __str__(self):
|
||||
return (f"记忆单元预览 \n"
|
||||
f"内容: '{self.content}' \n"
|
||||
f"易度系数: {self.efactor:.2f} \n"
|
||||
f"已经重复的次数: {self.rept} \n"
|
||||
f"下次间隔: {self.interval} 天 \n"
|
||||
f"下次复习日期时间戳: {self.next_date}")
|
||||
f"易度系数: {self.metadata['efactor']:.2f} \n"
|
||||
f"已经重复的次数: {self.metadata['rept']} \n"
|
||||
f"下次间隔: {self.metadata['interval']} 天 \n"
|
||||
f"下次复习日期时间戳: {self.metadata['next_date']}")
|
||||
|
||||
def __eq__(self, other):
|
||||
if self.content == other.content:
|
||||
return 1
|
||||
return 0
|
||||
return True
|
||||
return False
|
||||
|
||||
def __hash__(self):
|
||||
return hash(self.content)
|
||||
|
||||
def __getitem__(self, key):
|
||||
if key == "content":
|
||||
return self.content
|
||||
if key in self.metadata:
|
||||
return self.metadata[key]
|
||||
else:
|
||||
raise KeyError(f"Key '{key}' not found in metadata.")
|
||||
|
||||
def __setitem__(self, key, value):
|
||||
if key == "content":
|
||||
raise AttributeError("content 应为只读")
|
||||
|
||||
# 可以在此处添加更复杂的验证逻辑,例如只允许修改预定义的 metadata 键
|
||||
# 或者根据键进行类型检查等。
|
||||
|
||||
self.metadata[key] = value
|
||||
self.metadata['last_modify'] = time.time()
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.metadata.keys()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.metadata)
|
||||
|
||||
@staticmethod
|
||||
def placeholder():
|
||||
return Electron("电子对象样例内容", {})
|
||||
|
||||
@staticmethod
|
||||
def import_from_file(path: pathlib.Path):
|
||||
name = path.name.replace(path.suffix, "")
|
||||
with open(path, 'r') as f:
|
||||
all = toml.load(f)
|
||||
lst = list()
|
||||
for i in all.keys():
|
||||
lst.append(Electron(i, all[i]))
|
||||
return (name, lst)
|
||||
@staticmethod
|
||||
def save_to_file(electron_dictized, path: pathlib.Path):
|
||||
with open(path, 'w') as f:
|
||||
toml.dump(electron_dictized, f)
|
||||
|
||||
class Nucleon():
|
||||
class Nucleon:
|
||||
"""核子: 材料元数据"""
|
||||
|
||||
def __init__(self, content: str, data: dict):
|
||||
self.metadata = data
|
||||
self.content = content
|
||||
|
||||
|
||||
@staticmethod
|
||||
def save_to_file(nucleon_dictized, path: pathlib.Path):
|
||||
with open(path, 'w') as f:
|
||||
toml.dump(nucleon_dictized, f)
|
||||
def __getitem__(self, key):
|
||||
if key == "content":
|
||||
return self.content
|
||||
if key in self.metadata:
|
||||
return self.metadata[key]
|
||||
else:
|
||||
raise KeyError(f"Key '{key}' not found in metadata.")
|
||||
|
||||
def __iter__(self):
|
||||
yield from self.metadata.keys()
|
||||
|
||||
def __len__(self):
|
||||
return len(self.metadata)
|
||||
|
||||
@staticmethod
|
||||
def placeholder():
|
||||
return Nucleon("核子对象样例内容", {})
|
||||
|
||||
class NucleonUnion():
|
||||
"取代原有 NucleonFile 类, 以支持复杂逻辑"
|
||||
"""
|
||||
替代原有 NucleonFile 类, 支持复杂逻辑
|
||||
|
||||
Attributes:
|
||||
path (Path): 对应于 NucleonUnion 实例的文件路径。
|
||||
name (str): 核联对象的显示名称,从文件名中派生。
|
||||
nucleons (list): 内部核子对象的列表。
|
||||
nucleons_dict (dict): 内部核子对象的字典,以核子内容作为键。
|
||||
keydata (dict): 核子对象字典键名的翻译。
|
||||
testdata (dict): 记忆测试项目的元数据。
|
||||
|
||||
Parameters:
|
||||
path (Path): 包含核子数据的文件路径。
|
||||
"""
|
||||
def __init__(self, path):
|
||||
name = path.name.replace(path.suffix, "")
|
||||
self.path = path
|
||||
self.name = path.name.replace(path.suffix, "")
|
||||
with open(path, 'r') as f:
|
||||
all = toml.load(f)
|
||||
lst = list()
|
||||
@@ -147,11 +176,41 @@ class NucleonUnion():
|
||||
self.keydata = all["keydata"]
|
||||
self.testdata = all["testdata"]
|
||||
self.nucleons = lst
|
||||
self.nucleons_dict = {elect.content: nucleons for elect in electron_file.datalist}
|
||||
def query(content):
|
||||
self.nucleons_dict = {i.content: i for i in lst}
|
||||
|
||||
def __len__(self):
|
||||
return len(self.nucleons)
|
||||
|
||||
class AtomicFile():
|
||||
def save(self):
|
||||
with open(self.path, 'w') as f:
|
||||
tmp = {i.content: i.metadata for i in self.nucleons}
|
||||
toml.dump(tmp, f)
|
||||
|
||||
class ElectronUnion():
|
||||
"取代原有 ElectronFile 类, 以支持复杂逻辑"
|
||||
def __init__(self, path):
|
||||
self.path = path
|
||||
self.name = path.name.replace(path.suffix, "")
|
||||
with open(path, 'r') as f:
|
||||
all = toml.load(f)
|
||||
lst = list()
|
||||
for i in all.keys():
|
||||
lst.append(Electron(i, all[i]))
|
||||
self.electrons = lst
|
||||
self.electrons_dict = {i.content: i.metadata for i in lst}
|
||||
|
||||
def sync(self):
|
||||
"""同步 electrons_dict 中新增对到 electrons 中"""
|
||||
self.electrons = self.electrons_dict.values()
|
||||
|
||||
def save(self):
|
||||
#print(1)
|
||||
with open(self.path, 'w') as f:
|
||||
tmp = {i.content: i.metadata for i in self.electrons}
|
||||
#print(tmp)
|
||||
toml.dump(tmp, f)
|
||||
|
||||
"""class AtomicFile():
|
||||
def __init__(self, path, type_="unknown"):
|
||||
self.path = path
|
||||
self.type_ = type_
|
||||
@@ -176,6 +235,7 @@ class AtomicFile():
|
||||
def get_len(self):
|
||||
return len(self.datalist)
|
||||
|
||||
"""
|
||||
|
||||
class Atom():
|
||||
@staticmethod
|
||||
|
Reference in New Issue
Block a user