Files
HeurAMS/particles.py
2025-08-28 13:08:37 +08:00

291 lines
9.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import pathlib
import toml
import time
import auxiliary as aux
class Electron:
"""电子: 记忆分析元数据及算法"""
algorithm = "SM-2" # 暂时使用 SM-2 算法进行记忆拟合, 考虑 SM-15 替代
def __init__(self, content: str, metadata: dict):
self.content = content
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.metadata['is_activated'] = 1
self.metadata['last_modify'] = time.time()
def modify(self, var: str, value):
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 算法迭代决策机制实现
根据 quality(0 ~ 5) 进行参数迭代最佳间隔
quality 由主程序评估
Args:
quality (int): 记忆保留率量化参数
"""
print(f"REVISOR: {quality}, {is_new_activation}")
if quality == -1:
return -1
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.metadata['rept'] = 0
self.metadata['interval'] = 0 # 设为0以便下面重新计算 I(1)
else:
self.metadata['rept'] += 1
self.metadata['real_rept'] += 1
if is_new_activation: # 初次激活
self.metadata['rept'] = 0
self.metadata['efactor'] = 2.5
if self.metadata['rept'] == 0: # 刚被重置或初次激活后复习
self.metadata['interval'] = 1 # I(1)
elif self.metadata['rept'] == 1:
self.metadata['interval'] = 6 # I(2) 经验公式
else:
self.metadata['interval'] = round(
self.metadata['interval'] * self.metadata['efactor']
)
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.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 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 应为只读")
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("电子对象样例内容", {})
class Nucleon:
"""核子: 材料元数据"""
def __init__(self, content: str, data: dict):
self.metadata = data
self.content = 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 __iter__(self):
yield from self.metadata.keys()
def __len__(self):
return len(self.metadata)
def __hash__(self):
return hash(self.content)
@staticmethod
def placeholder():
return Nucleon("核子对象样例内容", {})
class NucleonUnion:
"""
替代原有 NucleonFile 类, 支持复杂逻辑
Attributes:
path (Path): 对应于 NucleonUnion 实例的文件路径。
name (str): 核联对象的显示名称,从文件名中派生。
nucleons (list): 内部核子对象的列表。
nucleons_dict (dict): 内部核子对象的字典,以核子内容作为键。
keydata (dict): 核子对象字典键名的翻译。
testdata (dict): 记忆测试项目的元数据。
Parameters:
path (Path): 包含核子数据的文件路径。
"""
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():
if "data" in i:
continue
lst.append(Nucleon(i, all[i]))
self.keydata = all["keydata"]
self.testdata = all["testdata"]
self.nucleons = lst
self.nucleons_dict = {i.content: i for i in lst}
def __len__(self):
return len(self.nucleons)
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():
if i != "total":
lst.append(Electron(i, all[i]))
self.total = all.get("total", {"last_date": 0})
self.electrons = lst
self.electrons_dict = {i.content: i for i in lst}
def sync(self):
"""同步 electrons_dict 中新增对到 electrons 中"""
self.electrons = self.electrons_dict.values()
def save(self):
# print(1)
self.total["last_date"] = aux.get_daystamp()
with open(self.path, 'w') as f:
tmp = {i.content: i.metadata for i in self.electrons}
tmp["total"] = self.total
# print(tmp)
toml.dump(tmp, f)
"""
class AtomicFile():
def __init__(self, path, type_="unknown"):
self.path = path
self.type_ = type_
if type_ == "nucleon":
self.name, self.datalist = Nucleon.import_from_file(pathlib.Path(path))
if type_ == "electron":
self.name, self.datalist = Electron.import_from_file(pathlib.Path(path))
def save(self):
dictobj = {i.content: i.export_data() for i in self.datalist}
print(dictobj)
if self.type_ == "nucleon":
Nucleon.save_to_file(dictobj, self.path)
if self.type_ == "electron":
Electron.save_to_file(dictobj, self.path)
def get_full_content(self):
if self.type_ == "nucleon":
text = ""
for i in self.datalist:
text += i.content
return text
return ""
def get_len(self):
return len(self.datalist)
"""
class Atom:
@staticmethod
def placeholder():
return (Electron.placeholder(), Nucleon.placeholder(), {})
@staticmethod
def advanced_placeholder():
return (
Electron("两只黄鹤鸣翠柳", {}),
Nucleon(
"两只黄鹤鸣翠柳",
{
"note": [],
"translation": "臣子李密陈言:我因命运不好,小时候遭遇到了不幸",
"keyword_note": {
"险衅": "凶险祸患(这里指命运不好)",
"": "早时,这里指年幼的时候",
"": "'',指可忧患的事",
"": "不幸,指丧父"
}
}
),
{
"keydata": {
"note": "笔记",
"keyword_note": "关键词翻译",
"translation": "语句翻译"
},
"testdata": {
"additional_inf": ["translation", "note", "keyword_note"],
"fill_blank_test": ["translation"],
"draw_card_test": ["keyword_note"]
},
"is_new_activation": 0
}
)