Skip to content

Commit 6f0a5dd

Browse files
committed
一些上课禁用功能和IPC
- 新增 ClassIsland数据源切换功能 ,在 时间设置 中添加开关以选择使用CSES或ClassIsland数据判断课间时间 - 优化 课间禁用逻辑 ,新增根据ClassIsland软件传入的课程表信息实时判断当前是否为课间时间的功能 - 新增 ClassIsland状态处理机制 ,实现对ClassIsland传入数据的解析和课间状态的动态更新 - 优化 设置管理 ,添加class_island_source_enabled、current_class_island_break_status等新设置项及其默认值 - 优化 CSES解析功能 ,修改 非上课时间判断逻辑 ,使用CSES解析器从CSES文件动态生成非上课时间段配置,替代原有的静态配置方式 - 优化 时间设置模块 ,新增从 data/CSES目录 读取YAML格式课程表文件功能,提升时间配置的灵活性和准确性
1 parent f674e4a commit 6f0a5dd

6 files changed

Lines changed: 209 additions & 44 deletions

File tree

CHANGELOG/v1.3.2-alpha.6/CHANGELOG.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ v2.0 - Koharu(小鸟游星野) Alpha 6
1717
- 新增 **ClassIsland数据接收功能**,实现接收ClassIsland软件发送的JSON格式课程表数据,包含当前科目、下一节课、当前状态等信息
1818
- 新增 **IPC端口配置功能**,在基本设置页面添加端口设置选项,支持1-65535范围内的端口自定义
1919
- 新增 **C# IPC通信示例**,提供ClassIsland软件通过TCP Socket向SecRandom发送JSON数据的实现方法
20+
- 新增 **ClassIsland数据源切换功能**,在**时间设置**中添加开关以选择使用CSES或ClassIsland数据判断课间时间
21+
- 新增 **ClassIsland状态处理机制**,实现对ClassIsland传入数据的解析和课间状态的动态更新
2022

2123
## 💡 功能优化
2224

@@ -37,8 +39,11 @@ v2.0 - Koharu(小鸟游星野) Alpha 6
3739
- 优化 **安全操作组件状态管理**,为 **basic_safety_security_operations** 类添加 `_update_enabled_state` 方法,实现根据全局安全开关状态控制组件启用状态
3840
- 优化 **信号转发机制**,修复URLHandler中ClassIsland数据信号转发问题,确保数据正确传递到UI界面
3941
- 优化 **端口配置逻辑**,优先使用用户设置的端口值而非配置文件,实现端口变更时自动重启IPC服务器
40-
- 优化 **多语言支持**,将IPC端口相关提示信息添加到语言文件,支持国际化显示
4142
- 优化 **默认端口设置**,将IPC端口默认值从0(动态分配)改为固定值11010,提高外部通信稳定性
43+
- 优化 **设置管理**,添加class_island_source_enabled、current_class_island_break_status等新设置项及其默认值
44+
- 优化 **课间禁用逻辑**,新增根据ClassIsland软件传入的课程表信息实时判断当前是否为课间时间的功能
45+
- 优化 **CSES解析功能**,修改**非上课时间判断逻辑**,使用CSES解析器从CSES文件动态生成非上课时间段配置,替代原有的静态配置方式
46+
- 优化 **时间设置模块**,新增从**data/CSES目录**读取YAML格式课程表文件功能,提升时间配置的灵活性和准确性
4247

4348
## 🐛 修复问题
4449

app/Language/modules/more_settings.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
"name": "验证流程功能",
3838
"description": "启用后,在非上课时段触发时将弹出安全验证;若关闭则直接禁用控件",
3939
},
40+
"class_island_source_function": {
41+
"name": "ClassIsland数据源",
42+
"description": "启用后,使用ClassIsland软件提供的课程表信息判断课间时间",
43+
},
4044
"import_from_file": {"name": "从文件导入"},
4145
"importing": {"name": "导入中..."},
4246
"view_current_config": {"name": "查看当前配置"},
@@ -120,6 +124,10 @@
120124
"name": "验证流程功能",
121125
"description": "启用后,在非上课时段触发时将弹出安全验证;若关闭则直接禁用控件",
122126
},
127+
"class_island_source_function": {
128+
"name": "ClassIsland data source",
129+
"description": "When enabled, use ClassIsland software's schedule information to determine class break times",
130+
},
123131
"view_current_config": {"name": "查看当前配置"},
124132
"schedule_imported": {"name": "已导入 {} 个上课时间段"},
125133
"import_success": {"name": "成功导入课程表: {}"},

app/common/extraction/extract.py

Lines changed: 53 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -32,65 +32,82 @@ def _is_non_class_time() -> bool:
3232
"""
3333
try:
3434
# 1. 检查课间禁用开关是否启用
35-
if not _is_instant_draw_disable_enabled():
35+
instant_draw_disable = readme_settings_async(
36+
"program_functionality", "instant_draw_disable"
37+
)
38+
if not instant_draw_disable:
3639
return False
3740

38-
# 2. 获取非上课时间段配置
39-
non_class_times = _get_non_class_times_config()
40-
if not non_class_times:
41-
return False
41+
# 2. 检查是否启用了ClassIsland数据源
42+
use_class_island_source = readme_settings_async(
43+
"time_settings", "class_island_source_enabled"
44+
)
45+
46+
if use_class_island_source:
47+
# 使用ClassIsland数据判断是否为课间时间
48+
class_island_break_status = readme_settings_async(
49+
"time_settings", "current_class_island_break_status"
50+
)
51+
# 确保返回布尔值
52+
return bool(class_island_break_status)
53+
else:
54+
# 使用CSES配置的非上课时间段
55+
non_class_times = _get_non_class_times_config()
56+
if not non_class_times or not isinstance(non_class_times, dict):
57+
# 如果非上课时间配置不存在或格式不正确,返回False
58+
return False
4259

43-
# 3. 获取当前时间并转换为总秒数
44-
current_total_seconds = _get_current_time_in_seconds()
60+
# 3. 获取当前时间并转换为总秒数
61+
current_total_seconds = _get_current_time_in_seconds()
4562

46-
# 4. 检查当前时间是否在任何非上课时间段内
47-
return _is_time_in_ranges(current_total_seconds, non_class_times)
63+
# 4. 检查当前时间是否在任何非上课时间段内
64+
return _is_time_in_ranges(current_total_seconds, non_class_times)
4865

4966
except Exception as e:
5067
logger.error(f"检测非上课时间失败: {e}")
5168
return False
5269

5370

54-
def _is_instant_draw_disable_enabled() -> bool:
55-
"""检查课间禁用开关是否启用
71+
def _get_non_class_times_config() -> Dict[str, str]:
72+
"""获取非上课时间段配置
5673
5774
Returns:
58-
bool: 如果课间禁用开关启用返回True,否则返回False
75+
Dict[str, str]: 非上课时间段配置字典,如果获取失败返回空字典
5976
"""
6077
try:
61-
settings_path = get_settings_path()
62-
if not file_exists(settings_path):
63-
return False
64-
65-
with open_file(settings_path, "r", encoding="utf-8") as f:
66-
settings = json.load(f)
78+
# 从data/CSES目录获取CSES文件
79+
cses_dir = get_data_path("CSES")
80+
if not os.path.exists(cses_dir):
81+
logger.info("CSES目录不存在,返回空的非上课时间配置")
82+
return {}
6783

68-
program_functionality = settings.get("program_functionality", {})
69-
return program_functionality.get("instant_draw_disable", False)
84+
# 获取CSES目录中的所有YAML文件
85+
import os
7086

71-
except Exception as e:
72-
logger.error(f"读取课间禁用设置失败: {e}")
73-
return False
87+
cses_files = [
88+
f for f in os.listdir(cses_dir) if f.lower().endswith((".yaml", ".yml"))
89+
]
7490

91+
if not cses_files:
92+
logger.info("CSES目录中没有找到YAML文件,返回空的非上课时间配置")
93+
return {}
7594

76-
def _get_non_class_times_config() -> Dict[str, str]:
77-
"""获取非上课时间段配置
95+
# 使用第一个找到的CSES文件
96+
cses_file_path = os.path.join(cses_dir, cses_files[0])
7897

79-
Returns:
80-
Dict[str, str]: 非上课时间段配置字典,如果获取失败返回空字典
81-
"""
82-
try:
83-
time_settings_path = get_settings_path()
84-
if not file_exists(time_settings_path):
98+
# 创建CSES解析器并加载文件
99+
parser = CSESParser()
100+
if not parser.load_from_file(cses_file_path):
101+
logger.error(f"加载CSES文件失败: {cses_file_path}")
85102
return {}
86103

87-
with open_file(time_settings_path, "r", encoding="utf-8") as f:
88-
time_settings = json.load(f)
89-
90-
return time_settings.get("non_class_times", {})
104+
# 使用CSES解析器获取非上课时间段
105+
non_class_times = parser.get_non_class_times()
106+
logger.info(f"成功从CSES文件生成{len(non_class_times)}个非上课时间段")
107+
return non_class_times
91108

92109
except Exception as e:
93-
logger.error(f"读取时间设置失败: {e}")
110+
logger.error(f"读取CSES时间设置失败: {e}")
94111
return {}
95112

96113

app/tools/settings_default_storage.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,9 @@
436436
"title": {"default_value": None},
437437
"verification_required": {"default_value": True},
438438
"instant_draw_disable": {"default_value": False},
439+
"class_island_source_enabled": {"default_value": False},
440+
"current_class_island_break_status": {"default_value": False},
441+
"last_class_island_state": {"default_value": ""},
439442
},
440443
"fair_draw_settings": {
441444
"title": {"default_value": None},

app/view/main/window.py

Lines changed: 100 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -691,15 +691,110 @@ def _handle_class_island_data(self, class_island_data: dict):
691691
# 是否已确定当前时间点
692692
is_lesson_confirmed = class_island_data.get("IsLessonConfirmed")
693693

694-
# 可以在这里添加处理逻辑,比如更新UI、保存数据等
695-
logger.info(f"当前科目: {current_subject}")
696-
logger.info(f"下一科目: {next_class_subject}")
697-
logger.info(f"当前状态: {current_state}")
698-
logger.info(f"课表启用: {is_class_plan_enabled}")
694+
# 检查是否启用了ClassIsland数据源
695+
use_class_island_source = readme_settings_async(
696+
"time_settings", "class_island_source_enabled", False
697+
)
698+
699+
if (
700+
use_class_island_source
701+
and is_class_plan_enabled
702+
and is_class_plan_loaded
703+
):
704+
# 使用ClassIsland数据来判断是否为课间时间
705+
# 根据当前状态判断当前是否为课间时间
706+
is_break_time = self._is_class_island_break_time(
707+
current_state, current_time_layout_item
708+
)
709+
710+
# 更新全局状态以反映当前是否为课间时间
711+
# 注意:这将影响到整个应用的课间禁用行为
712+
self._update_class_island_break_status(is_break_time, current_state)
699713

700714
# 这里可以添加根据ClassIsland数据更新UI的逻辑
701715
# 例如:显示当前课程信息、更新课程表显示等
702716
# 目前只是记录日志,后续可以根据需要添加具体功能
703717

704718
except Exception as e:
705719
logger.error(f"处理ClassIsland数据时出错: {e}")
720+
721+
def _is_class_island_break_time(
722+
self, current_state: str, current_time_layout_item: dict
723+
) -> bool:
724+
"""根据ClassIsland数据判断是否为课间时间
725+
726+
Args:
727+
current_state: 当前时间点状态
728+
current_time_layout_item: 当前时间布局项
729+
730+
Returns:
731+
bool: 如果当前是课间时间返回True,否则返回False
732+
"""
733+
if not current_state:
734+
return False
735+
736+
# 通常课间时间的状态包含 "break", "rest", "interval", "free" 等关键词
737+
# 或者当前状态明确表示是课间时间
738+
current_state_lower = current_state.lower()
739+
740+
# 检查状态是否表明当前是课间时间
741+
break_indicators = [
742+
"break",
743+
"rest",
744+
"interval",
745+
"free",
746+
"recess",
747+
"pause",
748+
"课间",
749+
"休息",
750+
"间歇",
751+
"自由",
752+
"breaktime",
753+
"break_time",
754+
"Breaking",
755+
]
756+
757+
for indicator in break_indicators:
758+
if indicator in current_state_lower:
759+
return True
760+
761+
# 如果时间布局项存在,可以进一步检查其类型
762+
if current_time_layout_item and isinstance(current_time_layout_item, dict):
763+
time_type = current_time_layout_item.get("Type", "")
764+
time_name = current_time_layout_item.get("Name", "")
765+
766+
# 检查时间布局项的类型或名称是否表明是课间时间
767+
time_type_lower = time_type.lower()
768+
time_name_lower = time_name.lower()
769+
770+
for indicator in break_indicators:
771+
if indicator in time_type_lower or indicator in time_name_lower:
772+
return True
773+
774+
return False
775+
776+
def _update_class_island_break_status(
777+
self, is_break_time: bool, current_state: str
778+
):
779+
"""更新ClassIsland课间状态
780+
781+
Args:
782+
is_break_time: 是否为课间时间
783+
current_state: 当前状态
784+
"""
785+
logger.debug(
786+
f"ClassIsland课间状态更新: {'课间时间' if is_break_time else '上课时间'} (状态: {current_state})"
787+
)
788+
789+
# 这里可以添加逻辑来更新应用的课间禁用状态
790+
# 例如,可以设置一个全局标志或更新设置
791+
try:
792+
# 保存当前ClassIsland的课间状态
793+
from app.tools.settings_access import update_settings
794+
795+
update_settings(
796+
"time_settings", "current_class_island_break_status", is_break_time
797+
)
798+
update_settings("time_settings", "last_class_island_state", current_state)
799+
except Exception as e:
800+
logger.error(f"更新ClassIsland课间状态失败: {e}")

app/view/settings/more_settings/time_settings.py

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,10 @@ def __init__(self, parent=None):
6161
)
6262

6363
# 从设置中读取当前状态
64-
self.class_break_switch.setChecked(self.class_break_switch.isChecked())
64+
instant_draw_disable = readme_settings_async(
65+
"time_settings", "instant_draw_disable", False
66+
)
67+
self.class_break_switch.setChecked(instant_draw_disable)
6568

6669
self.class_break_switch.checkedChanged.connect(
6770
lambda: update_settings(
@@ -81,7 +84,10 @@ def __init__(self, parent=None):
8184
)
8285

8386
# 从设置中读取当前状态
84-
self.verification_switch.setChecked(self.verification_switch.isChecked())
87+
verification_required = readme_settings_async(
88+
"time_settings", "verification_required", False
89+
)
90+
self.verification_switch.setChecked(verification_required)
8591

8692
self.verification_switch.checkedChanged.connect(
8793
lambda: update_settings(
@@ -91,6 +97,29 @@ def __init__(self, parent=None):
9197
)
9298
)
9399

100+
# ClassIsland数据源开关
101+
self.class_island_source_switch = SwitchButton()
102+
self.class_island_source_switch.setOffText(
103+
get_content_name_async("time_settings", "disable")
104+
)
105+
self.class_island_source_switch.setOnText(
106+
get_content_name_async("time_settings", "enable")
107+
)
108+
109+
# 从设置中读取当前状态
110+
class_island_source_enabled = readme_settings_async(
111+
"time_settings", "class_island_source_enabled", False
112+
)
113+
self.class_island_source_switch.setChecked(class_island_source_enabled)
114+
115+
self.class_island_source_switch.checkedChanged.connect(
116+
lambda: update_settings(
117+
"time_settings",
118+
"class_island_source_enabled",
119+
self.class_island_source_switch.isChecked(),
120+
)
121+
)
122+
94123
# 添加设置项到分组
95124
self.addGroup(
96125
get_theme_icon("ic_fluent_clock_lock_20_filled"),
@@ -104,6 +133,14 @@ def __init__(self, parent=None):
104133
get_content_description_async("time_settings", "verification_function"),
105134
self.verification_switch,
106135
)
136+
self.addGroup(
137+
get_theme_icon("ic_fluent_desktop_mac_20_filled"),
138+
get_content_name_async("time_settings", "class_island_source_function"),
139+
get_content_description_async(
140+
"time_settings", "class_island_source_function"
141+
),
142+
self.class_island_source_switch,
143+
)
107144

108145

109146
class cses_import_settings(GroupHeaderCardWidget):

0 commit comments

Comments
 (0)