fix: 改进
This commit is contained in:
@@ -1,23 +1,22 @@
|
|||||||
# 贡献指南
|
# 贡献指南
|
||||||
|
|
||||||
欢迎为潜进 (HeurAMS) 项目做出贡献!本项目是一个开源项目,我们鼓励社区成员参与改进。
|
欢迎为此项目做出贡献!
|
||||||
|
本项目是一个开源项目, 我们鼓励社区成员参与改进.
|
||||||
|
|
||||||
## 开发流程
|
## 开发流程
|
||||||
|
|
||||||
1. **讨论功能**:在开始编写代码之前,建议先通过 Issue 讨论新功能或修复。
|
1. **分支划分**:
|
||||||
2. **分支策略**:
|
|
||||||
- `main` 分支:稳定版本
|
- `main` 分支:稳定版本
|
||||||
- `develop` 分支:开发版本
|
- `develop` 分支:开发版本
|
||||||
- 功能分支:从 `develop` 分支创建,命名格式为 `feature/描述` 或 `fix/描述`
|
- 功能分支:从 `develop` 分支创建,命名格式为 `feature/描述` 或 `fix/描述`
|
||||||
3. **代码风格**:
|
2. **代码风格**:
|
||||||
- 使用 Black 格式化代码(如果配置)
|
- 请使用 Black 格式化代码
|
||||||
- 遵循 PEP 8 规范
|
- 遵循 PEP 8 规范
|
||||||
- 使用类型注解
|
- 添加适当的文档字符串
|
||||||
- 添加适当的文档字符串(中英文均可)
|
3. **提交消息**:
|
||||||
4. **提交消息**:
|
|
||||||
- 使用中文或英文撰写清晰的提交消息
|
- 使用中文或英文撰写清晰的提交消息
|
||||||
- 格式:`类型: 描述`,例如 `fix: 修复登录错误` 或 `feat: 添加新算法`
|
- 格式:`类型: 描述`,例如 `fix: 修复登录错误` 或 `feat: 添加新算法`
|
||||||
5. **测试**:
|
4. **测试**:
|
||||||
- 为新功能添加单元测试
|
- 为新功能添加单元测试
|
||||||
- 确保所有测试通过
|
- 确保所有测试通过
|
||||||
- 运行 `pytest` 检查
|
- 运行 `pytest` 检查
|
||||||
@@ -40,29 +39,6 @@ pip install -r requirements.txt
|
|||||||
pip install -e .
|
pip install -e .
|
||||||
```
|
```
|
||||||
|
|
||||||
## 提交更改
|
|
||||||
|
|
||||||
1. 确保代码通过测试:
|
|
||||||
```bash
|
|
||||||
python -m pytest tests/
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 提交更改:
|
|
||||||
```bash
|
|
||||||
git add .
|
|
||||||
git commit -m "类型: 描述"
|
|
||||||
git push origin 分支名
|
|
||||||
```
|
|
||||||
|
|
||||||
3. 创建 Pull Request:
|
|
||||||
- 在 GitHub 上创建 Pull Request,将你的分支合并到 `develop`
|
|
||||||
- 描述更改内容和动机
|
|
||||||
- 链接相关 Issue(如果有)
|
|
||||||
|
|
||||||
## 行为准则
|
|
||||||
|
|
||||||
请保持友好、尊重的交流氛围。我们遵循 [贡献者公约](https://www.contributor-covenant.org/)。
|
|
||||||
|
|
||||||
## 许可证
|
## 许可证
|
||||||
|
|
||||||
贡献者同意其贡献将在 AGPL-3.0 许可证下发布。
|
贡献者同意其贡献将在 AGPL-3.0 许可证下发布。
|
||||||
|
|||||||
@@ -66,7 +66,7 @@
|
|||||||
|
|
||||||
### 启动应用
|
### 启动应用
|
||||||
```bash
|
```bash
|
||||||
# 从项目根目录运行
|
# 在任一目录(建议是空目录或者包根目录, 将被用作存放数据)下运行
|
||||||
python -m heurams.interface
|
python -m heurams.interface
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ logger = get_logger(__name__)
|
|||||||
class MemScreen(Screen):
|
class MemScreen(Screen):
|
||||||
BINDINGS = [
|
BINDINGS = [
|
||||||
("q", "pop_screen", "返回"),
|
("q", "pop_screen", "返回"),
|
||||||
("p", "prev", "复习上一个"),
|
#("p", "prev", "复习上一个"),
|
||||||
("d", "toggle_dark", "改变色调"),
|
("d", "toggle_dark", "改变色调"),
|
||||||
("v", "play_voice", "朗读"),
|
("v", "play_voice", "朗读"),
|
||||||
]
|
]
|
||||||
@@ -46,6 +46,8 @@ class MemScreen(Screen):
|
|||||||
self.procession: Procession = self.phaser.current_procession() # type: ignore
|
self.procession: Procession = self.phaser.current_procession() # type: ignore
|
||||||
# logger.debug(self.phaser.state)
|
# logger.debug(self.phaser.state)
|
||||||
# self.procession.forward(1)
|
# self.procession.forward(1)
|
||||||
|
for i in atoms:
|
||||||
|
i.do_eval()
|
||||||
|
|
||||||
def on_mount(self):
|
def on_mount(self):
|
||||||
self.load_puzzle()
|
self.load_puzzle()
|
||||||
@@ -53,11 +55,10 @@ class MemScreen(Screen):
|
|||||||
|
|
||||||
def puzzle_widget(self):
|
def puzzle_widget(self):
|
||||||
try:
|
try:
|
||||||
# logger.debug(self.phaser.state)
|
logger.debug(self.phaser.state)
|
||||||
#logger.debug(self.procession.cursor)
|
logger.debug(self.procession.cursor)
|
||||||
#logger.debug(self.procession.current_atom)
|
logger.debug(self.procession.current_atom)
|
||||||
self.fission = Fission(self.procession.current_atom, self.phaser.state)
|
self.fission = Fission(self.procession.current_atom, self.phaser.state)
|
||||||
# logger.debug(1)
|
|
||||||
puzzle_debug = next(self.fission.generate())
|
puzzle_debug = next(self.fission.generate())
|
||||||
#logger.debug(puzzle_debug)
|
#logger.debug(puzzle_debug)
|
||||||
return shim.puzzle2widget[puzzle_debug["puzzle"]](
|
return shim.puzzle2widget[puzzle_debug["puzzle"]](
|
||||||
@@ -71,21 +72,33 @@ class MemScreen(Screen):
|
|||||||
def compose(self) -> ComposeResult:
|
def compose(self) -> ComposeResult:
|
||||||
yield Header(show_clock=True)
|
yield Header(show_clock=True)
|
||||||
with ScrollableContainer():
|
with ScrollableContainer():
|
||||||
with Center():
|
yield Label(self._get_progress_text(), id="progress")
|
||||||
yield Static(
|
|
||||||
f"当前进度: {self.procession.process()}/{self.procession.total_length()}"
|
|
||||||
)
|
|
||||||
# self.mount(self.current_widget()) # type: ignore
|
# self.mount(self.current_widget()) # type: ignore
|
||||||
yield ScrollableContainer(id="puzzle-container")
|
yield ScrollableContainer(id="puzzle-container")
|
||||||
# yield Button("重新学习此单元", id="re-recognize", variant="warning")
|
# yield Button("重新学习此单元", id="re-recognize", variant="warning")
|
||||||
yield Footer()
|
yield Footer()
|
||||||
|
|
||||||
|
def _get_progress_text(self):
|
||||||
|
return f"当前进度: {self.procession.process() + 1}/{self.procession.total_length()}"
|
||||||
|
|
||||||
|
def update_display(self):
|
||||||
|
progress_widget = self.query_one("#progress")
|
||||||
|
progress_widget.update(self._get_progress_text()) # type: ignore
|
||||||
|
|
||||||
def load_puzzle(self):
|
def load_puzzle(self):
|
||||||
container = self.query_one("#puzzle-container")
|
container = self.query_one("#puzzle-container")
|
||||||
for i in container.children:
|
for i in container.children:
|
||||||
i.remove()
|
i.remove()
|
||||||
container.mount(self.puzzle_widget())
|
container.mount(self.puzzle_widget())
|
||||||
|
|
||||||
|
def load_finished_widget(self):
|
||||||
|
container = self.query_one("#puzzle-container")
|
||||||
|
for i in container.children:
|
||||||
|
i.remove()
|
||||||
|
from heurams.interface.widgets.finished import Finished
|
||||||
|
container.mount(Finished())
|
||||||
|
|
||||||
def on_button_pressed(self, event):
|
def on_button_pressed(self, event):
|
||||||
event.stop()
|
event.stop()
|
||||||
|
|
||||||
@@ -98,7 +111,13 @@ class MemScreen(Screen):
|
|||||||
ret = self.procession.forward(1)
|
ret = self.procession.forward(1)
|
||||||
if ret == 0:
|
if ret == 0:
|
||||||
self.procession = self.phaser.current_procession() # type: ignore
|
self.procession = self.phaser.current_procession() # type: ignore
|
||||||
|
if self.procession == 0:
|
||||||
|
logger.debug(f"记忆进程结束")
|
||||||
|
self.load_finished_widget()
|
||||||
|
return
|
||||||
|
else:
|
||||||
logger.debug(f"建立新队列 {self.procession.phase}")
|
logger.debug(f"建立新队列 {self.procession.phase}")
|
||||||
|
self.update_display()
|
||||||
self.load_puzzle()
|
self.load_puzzle()
|
||||||
|
|
||||||
def action_play_voice(self):
|
def action_play_voice(self):
|
||||||
|
|||||||
@@ -3,15 +3,16 @@ from textual.widgets import (
|
|||||||
Label,
|
Label,
|
||||||
Button,
|
Button,
|
||||||
)
|
)
|
||||||
from textual.containers import ScrollableContainer
|
from textual.containers import ScrollableContainer, Container
|
||||||
from textual.widget import Widget
|
from textual.widget import Widget
|
||||||
import heurams.kernel.particles as pt
|
import heurams.kernel.particles as pt
|
||||||
import heurams.kernel.puzzles as pz
|
import heurams.kernel.puzzles as pz
|
||||||
from .base_puzzle_widget import BasePuzzleWidget
|
from .base_puzzle_widget import BasePuzzleWidget
|
||||||
from typing import TypedDict
|
from typing import TypedDict
|
||||||
from bidict import bidict
|
|
||||||
from heurams.services.hasher import hash
|
from heurams.services.hasher import hash
|
||||||
|
from heurams.services.logger import get_logger
|
||||||
|
|
||||||
|
logger = get_logger(__name__)
|
||||||
|
|
||||||
class Setting(TypedDict):
|
class Setting(TypedDict):
|
||||||
__origin__: str
|
__origin__: str
|
||||||
@@ -46,7 +47,8 @@ class MCQPuzzle(BasePuzzleWidget):
|
|||||||
)
|
)
|
||||||
self.inputlist = []
|
self.inputlist = []
|
||||||
self.alia = alia
|
self.alia = alia
|
||||||
self.hashmap = bidict()
|
self.hashmap = dict()
|
||||||
|
self.cursor = 0
|
||||||
self._load()
|
self._load()
|
||||||
|
|
||||||
def _load(self):
|
def _load(self):
|
||||||
@@ -57,18 +59,23 @@ class MCQPuzzle(BasePuzzleWidget):
|
|||||||
self.puzzle.refresh()
|
self.puzzle.refresh()
|
||||||
|
|
||||||
def compose(self):
|
def compose(self):
|
||||||
|
self.atom.registry["nucleon"].do_eval()
|
||||||
setting: Setting = self.atom.registry["nucleon"].metadata["orbital"]["puzzles"][
|
setting: Setting = self.atom.registry["nucleon"].metadata["orbital"]["puzzles"][
|
||||||
self.alia
|
self.alia
|
||||||
]
|
]
|
||||||
|
logger.debug(f"Puzzle Setting: {setting}")
|
||||||
yield Label(setting["primary"], id="sentence")
|
yield Label(setting["primary"], id="sentence")
|
||||||
yield Label(self.puzzle.wording[len(self.inputlist)], id="puzzle")
|
yield Label(self.puzzle.wording[len(self.inputlist)], id="puzzle")
|
||||||
yield Label(f"当前输入: {self.inputlist}", id="inputpreview")
|
yield Label(f"当前输入: {self.inputlist}", id="inputpreview")
|
||||||
|
|
||||||
# 渲染当前问题的选项
|
# 渲染当前问题的选项
|
||||||
current_options = self.puzzle.options[len(self.inputlist)]
|
current_options = self.puzzle.options[len(self.inputlist)]
|
||||||
|
with Container(id="btn-container"):
|
||||||
for i in current_options:
|
for i in current_options:
|
||||||
self.hashmap[str(hash(i))] = i
|
self.hashmap[str(hash(i))] = i
|
||||||
yield Button(i, id=f"select-{hash(i)}")
|
btnid = f"sel{str(self.cursor).zfill(3)}-{hash(i)}"
|
||||||
|
logger.debug(f"建立按钮 {btnid}")
|
||||||
|
yield Button(i, id=f"{btnid}")
|
||||||
|
|
||||||
yield Button("退格", id="delete")
|
yield Button("退格", id="delete")
|
||||||
|
|
||||||
@@ -76,7 +83,7 @@ class MCQPuzzle(BasePuzzleWidget):
|
|||||||
# 更新预览标签
|
# 更新预览标签
|
||||||
preview = self.query_one("#inputpreview")
|
preview = self.query_one("#inputpreview")
|
||||||
preview.update(f"当前输入: {self.inputlist}") # type: ignore
|
preview.update(f"当前输入: {self.inputlist}") # type: ignore
|
||||||
|
logger.debug("已经更新预览标签")
|
||||||
# 更新问题标签
|
# 更新问题标签
|
||||||
puzzle_label = self.query_one("#puzzle")
|
puzzle_label = self.query_one("#puzzle")
|
||||||
current_question_index = len(self.inputlist)
|
current_question_index = len(self.inputlist)
|
||||||
@@ -95,11 +102,11 @@ class MCQPuzzle(BasePuzzleWidget):
|
|||||||
self.refresh_buttons()
|
self.refresh_buttons()
|
||||||
self.update_display()
|
self.update_display()
|
||||||
|
|
||||||
elif button_id.startswith("select"): # type: ignore
|
elif button_id.startswith("sel"): # type: ignore
|
||||||
# 选项选择处理
|
# 选项选择处理
|
||||||
answer_text = self.hashmap[button_id[7:]] # type: ignore
|
answer_text = self.hashmap[button_id[7:]] # type: ignore
|
||||||
self.inputlist.append(answer_text)
|
self.inputlist.append(answer_text)
|
||||||
|
logger.debug(f"{self.inputlist}")
|
||||||
# 检查是否完成所有题目
|
# 检查是否完成所有题目
|
||||||
if len(self.inputlist) >= len(self.puzzle.answer):
|
if len(self.inputlist) >= len(self.puzzle.answer):
|
||||||
is_correct = self.inputlist == self.puzzle.answer
|
is_correct = self.inputlist == self.puzzle.answer
|
||||||
@@ -120,22 +127,26 @@ class MCQPuzzle(BasePuzzleWidget):
|
|||||||
def refresh_buttons(self):
|
def refresh_buttons(self):
|
||||||
"""刷新按钮显示(用于题目切换)"""
|
"""刷新按钮显示(用于题目切换)"""
|
||||||
# 移除所有选项按钮
|
# 移除所有选项按钮
|
||||||
|
logger.debug("刷新按钮")
|
||||||
|
self.cursor += 1
|
||||||
|
container = self.query_one("#btn-container")
|
||||||
buttons_to_remove = [
|
buttons_to_remove = [
|
||||||
child
|
child
|
||||||
for child in self.children
|
for child in container.children
|
||||||
if hasattr(child, "id") and child.id and child.id.startswith("select")
|
if hasattr(child, "id") and child.id and child.id.startswith("sel")
|
||||||
]
|
]
|
||||||
|
|
||||||
for button in buttons_to_remove:
|
for button in buttons_to_remove:
|
||||||
self.remove_child(button) # type: ignore
|
logger.info(button)
|
||||||
|
container.remove_children("#"+button.id) # type: ignore
|
||||||
|
|
||||||
# 添加当前题目的选项按钮
|
# 添加当前题目的选项按钮
|
||||||
current_question_index = len(self.inputlist)
|
current_question_index = len(self.inputlist)
|
||||||
if current_question_index < len(self.puzzle.options):
|
if current_question_index < len(self.puzzle.options):
|
||||||
current_options = self.puzzle.options[current_question_index]
|
current_options = self.puzzle.options[current_question_index]
|
||||||
for option in current_options:
|
for option in current_options:
|
||||||
button_id = f"select-{hash(option)}"
|
button_id = f"sel{str(self.cursor).zfill(3)}-{hash(option)}"
|
||||||
if button_id not in self.hashmap:
|
if button_id not in self.hashmap:
|
||||||
self.hashmap[button_id] = option
|
self.hashmap[button_id] = option
|
||||||
new_button = Button(option, id=button_id)
|
new_button = Button(option, id=button_id)
|
||||||
self.mount(new_button)
|
container.mount(new_button)
|
||||||
|
|||||||
@@ -64,7 +64,9 @@ class MCQPuzzle(BasePuzzle):
|
|||||||
|
|
||||||
# 确保至少有4个干扰项
|
# 确保至少有4个干扰项
|
||||||
while len(self.jammer) < 4:
|
while len(self.jammer) < 4:
|
||||||
self.jammer.append(" ")
|
self.jammer.append(" " * (4 - len(self.jammer)))
|
||||||
|
|
||||||
|
unique_jammers = set(jammer + list(self.mapping.values()))
|
||||||
|
|
||||||
def _reset_puzzle_state(self) -> None:
|
def _reset_puzzle_state(self) -> None:
|
||||||
"""重置谜题状态为初始值
|
"""重置谜题状态为初始值
|
||||||
@@ -84,7 +86,7 @@ class MCQPuzzle(BasePuzzle):
|
|||||||
Raises:
|
Raises:
|
||||||
ValueError: 当mapping为空时不会抛出异常, 但会设置空谜题状态
|
ValueError: 当mapping为空时不会抛出异常, 但会设置空谜题状态
|
||||||
"""
|
"""
|
||||||
logger.debug("MCQPuzzle.refresh 开始,mapping size=%d", len(self.mapping))
|
logger.debug("MCQPuzzle.refresh 开始, mapping size=%d", len(self.mapping))
|
||||||
if not self.mapping:
|
if not self.mapping:
|
||||||
self._set_empty_puzzle()
|
self._set_empty_puzzle()
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ logger = get_logger(__name__)
|
|||||||
|
|
||||||
|
|
||||||
def get_md5(text):
|
def get_md5(text):
|
||||||
logger.debug("计算MD5哈希,输入长度: %d", len(text))
|
logger.debug(f"计算哈希, 输入`{text}`")
|
||||||
result = hashlib.md5(text.encode("utf-8")).hexdigest()
|
result = hashlib.md5(text.encode("utf-8")).hexdigest()
|
||||||
logger.debug("MD5哈希结果: %s...", result[:8])
|
logger.debug("哈希结果: %s...", result[:8])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
def hash(text):
|
def hash(text):
|
||||||
logger.debug("计算哈希,输入长度: %d", len(text))
|
logger.debug(f"计算哈希, 输入`{text}`")
|
||||||
result = hashlib.md5(text.encode("utf-8")).hexdigest()
|
result = hashlib.md5(text.encode("utf-8")).hexdigest()
|
||||||
logger.debug("哈希结果: %s...", result[:8])
|
logger.debug("哈希结果: %s...", result[:8])
|
||||||
return result
|
return result
|
||||||
|
|||||||
Reference in New Issue
Block a user