|
1 | 1 | # ================================================== |
2 | 2 | # 导入模块 |
3 | 3 | # ================================================== |
4 | | -import copy |
5 | 4 | import json |
6 | | -import threading |
7 | 5 | from typing import List, Dict, Any, Tuple |
8 | 6 | from loguru import logger |
9 | 7 |
|
10 | 8 | from app.tools.path_utils import * |
11 | 9 |
|
12 | 10 |
|
13 | | -_list_cache_lock = threading.RLock() |
14 | | -_student_list_cache: dict[str, tuple[tuple[int, int] | None, list[dict[str, Any]]]] = {} |
15 | | -_pool_list_cache: dict[str, tuple[tuple[int, int] | None, list[dict[str, Any]]]] = {} |
16 | | -_directory_name_cache: dict[str, tuple[tuple[int, int] | None, list[str]]] = {} |
17 | | - |
18 | | - |
19 | | -def _get_file_signature(file_path) -> tuple[int, int] | None: |
20 | | - try: |
21 | | - stat_result = file_path.stat() |
22 | | - return stat_result.st_mtime_ns, stat_result.st_size |
23 | | - except OSError: |
24 | | - return None |
25 | | - |
26 | | - |
27 | | -def _get_cached_transformed_list( |
28 | | - cache: dict[str, tuple[tuple[int, int] | None, list[dict[str, Any]]]], |
29 | | - file_path, |
30 | | - loader, |
31 | | -): |
32 | | - cache_key = str(file_path) |
33 | | - signature = _get_file_signature(file_path) |
34 | | - |
35 | | - with _list_cache_lock: |
36 | | - cached = cache.get(cache_key) |
37 | | - if cached and cached[0] == signature: |
38 | | - return copy.deepcopy(cached[1]) |
39 | | - |
40 | | - loaded_data = loader(file_path) |
41 | | - with _list_cache_lock: |
42 | | - cache[cache_key] = (signature, copy.deepcopy(loaded_data)) |
43 | | - return copy.deepcopy(loaded_data) |
44 | | - |
45 | | - |
46 | | -def _get_cached_directory_names(directory_path) -> List[str]: |
47 | | - cache_key = str(directory_path) |
48 | | - signature = _get_file_signature(directory_path) |
49 | | - |
50 | | - with _list_cache_lock: |
51 | | - cached = _directory_name_cache.get(cache_key) |
52 | | - if cached and cached[0] == signature: |
53 | | - return list(cached[1]) |
54 | | - |
55 | | - names = sorted(file_path.stem for file_path in directory_path.glob("*.json")) |
56 | | - with _list_cache_lock: |
57 | | - _directory_name_cache[cache_key] = (signature, list(names)) |
58 | | - return list(names) |
59 | | - |
60 | | - |
61 | 11 | def _normalize_tags(value) -> List[str]: |
62 | 12 | if value is None: |
63 | 13 | return [] |
@@ -153,7 +103,17 @@ def get_class_name_list() -> List[str]: |
153 | 103 | roll_call_list_dir.mkdir(parents=True, exist_ok=True) |
154 | 104 | return [] |
155 | 105 |
|
156 | | - class_files = _get_cached_directory_names(roll_call_list_dir) |
| 106 | + # 获取文件夹中的所有文件 |
| 107 | + class_files = [] |
| 108 | + for file_path in roll_call_list_dir.glob("*.json"): |
| 109 | + # 获取文件名(不带扩展名)作为班级名称 |
| 110 | + class_name = file_path.stem |
| 111 | + class_files.append(class_name) |
| 112 | + |
| 113 | + # 按字母顺序排序 |
| 114 | + class_files.sort() |
| 115 | + |
| 116 | + # logger.debug(f"找到 {len(class_files)} 个班级: {class_files}") |
157 | 117 | return class_files |
158 | 118 |
|
159 | 119 | except Exception as e: |
@@ -183,28 +143,28 @@ def get_student_list(class_name: str) -> List[Dict[str, Any]]: |
183 | 143 | logger.warning(f"班级名单文件不存在: {class_file_path}") |
184 | 144 | return [] |
185 | 145 |
|
186 | | - def loader(file_path): |
187 | | - with open(file_path, "r", encoding="utf-8") as f: |
188 | | - student_data = json.load(f) |
189 | | - |
190 | | - student_list = [] |
191 | | - for name, info in student_data.items(): |
192 | | - student = { |
193 | | - "name": name, |
194 | | - "id": info.get("id", 0), |
195 | | - "gender": info.get("gender", "未知"), |
196 | | - "group": info.get("group", "未分组"), |
197 | | - "exist": info.get("exist", True), |
198 | | - "tags": _normalize_tags(info.get("tags", [])), |
199 | | - } |
200 | | - student_list.append(student) |
201 | | - |
202 | | - student_list.sort(key=lambda x: x["id"]) |
203 | | - return student_list |
204 | | - |
205 | | - return _get_cached_transformed_list( |
206 | | - _student_list_cache, class_file_path, loader |
207 | | - ) |
| 146 | + # 读取JSON文件 |
| 147 | + with open(class_file_path, "r", encoding="utf-8") as f: |
| 148 | + student_data = json.load(f) |
| 149 | + |
| 150 | + # 将字典数据转换为列表形式 |
| 151 | + student_list = [] |
| 152 | + for name, info in student_data.items(): |
| 153 | + student = { |
| 154 | + "name": name, |
| 155 | + "id": info.get("id", 0), |
| 156 | + "gender": info.get("gender", "未知"), |
| 157 | + "group": info.get("group", "未分组"), |
| 158 | + "exist": info.get("exist", True), |
| 159 | + "tags": _normalize_tags(info.get("tags", [])), |
| 160 | + } |
| 161 | + student_list.append(student) |
| 162 | + |
| 163 | + # 按ID排序 |
| 164 | + student_list.sort(key=lambda x: x["id"]) |
| 165 | + |
| 166 | + # logger.debug(f"班级 {class_name} 共有 {len(student_list)} 名学生") |
| 167 | + return student_list |
208 | 168 |
|
209 | 169 | except Exception as e: |
210 | 170 | logger.error(f"获取学生列表失败: {e}") |
@@ -304,7 +264,17 @@ def get_pool_name_list() -> List[str]: |
304 | 264 | lottery_list_dir.mkdir(parents=True, exist_ok=True) |
305 | 265 | return [] |
306 | 266 |
|
307 | | - pool_files = _get_cached_directory_names(lottery_list_dir) |
| 267 | + # 获取文件夹中的所有文件 |
| 268 | + pool_files = [] |
| 269 | + for file_path in lottery_list_dir.glob("*.json"): |
| 270 | + # 获取文件名(不带扩展名)作为奖池名称 |
| 271 | + pool_name = file_path.stem |
| 272 | + pool_files.append(pool_name) |
| 273 | + |
| 274 | + # 按字母顺序排序 |
| 275 | + pool_files.sort() |
| 276 | + |
| 277 | + # logger.debug(f"找到 {len(pool_files)} 个奖池: {pool_files}") |
308 | 278 | return pool_files |
309 | 279 |
|
310 | 280 | except Exception as e: |
@@ -334,33 +304,35 @@ def get_pool_list(pool_name: str) -> List[Dict[str, Any]]: |
334 | 304 | logger.warning(f"奖池名单文件不存在: {pool_file_path}") |
335 | 305 | return [] |
336 | 306 |
|
337 | | - def loader(file_path): |
338 | | - with open(file_path, "r", encoding="utf-8") as f: |
339 | | - pool_data = json.load(f) |
340 | | - |
341 | | - pool_list = [] |
342 | | - for name, info in pool_data.items(): |
343 | | - raw_count = info.get("count", 1) |
344 | | - try: |
345 | | - count = int(raw_count) |
346 | | - except Exception: |
347 | | - count = 1 |
348 | | - if count < 0: |
349 | | - count = 0 |
350 | | - pool = { |
351 | | - "name": name, |
352 | | - "id": info.get("id", 0), |
353 | | - "weight": info.get("weight", 1), |
354 | | - "exist": info.get("exist", True), |
355 | | - "count": count, |
356 | | - "tags": _normalize_tags(info.get("tags", [])), |
357 | | - } |
358 | | - pool_list.append(pool) |
359 | | - |
360 | | - pool_list.sort(key=lambda x: x["id"]) |
361 | | - return pool_list |
362 | | - |
363 | | - return _get_cached_transformed_list(_pool_list_cache, pool_file_path, loader) |
| 307 | + # 读取JSON文件 |
| 308 | + with open(pool_file_path, "r", encoding="utf-8") as f: |
| 309 | + pool_data = json.load(f) |
| 310 | + |
| 311 | + # 将字典数据转换为列表形式 |
| 312 | + pool_list = [] |
| 313 | + for name, info in pool_data.items(): |
| 314 | + raw_count = info.get("count", 1) |
| 315 | + try: |
| 316 | + count = int(raw_count) |
| 317 | + except Exception: |
| 318 | + count = 1 |
| 319 | + if count < 0: |
| 320 | + count = 0 |
| 321 | + pool = { |
| 322 | + "name": name, |
| 323 | + "id": info.get("id", 0), |
| 324 | + "weight": info.get("weight", 1), |
| 325 | + "exist": info.get("exist", True), |
| 326 | + "count": count, |
| 327 | + "tags": _normalize_tags(info.get("tags", [])), |
| 328 | + } |
| 329 | + pool_list.append(pool) |
| 330 | + |
| 331 | + # 按ID排序 |
| 332 | + pool_list.sort(key=lambda x: x["id"]) |
| 333 | + |
| 334 | + # logger.debug(f"奖池 {pool_name} 共有 {len(pool_list)} 个奖品") |
| 335 | + return pool_list |
364 | 336 |
|
365 | 337 | except Exception as e: |
366 | 338 | logger.error(f"获取奖池列表失败: {e}") |
|
0 commit comments