ADD file via upload

master
p9hofibgx 1 month ago
parent d2d3cb3903
commit 9045322eee

@ -0,0 +1,240 @@
from datetime import date, datetime
from typing import Dict, Any, List, Optional, Tuple
from data_access import StudentDataAccess
class IDCardValidator:
"""身份证验证工具类"""
@staticmethod
def validate_id_card(id_card: str) -> Tuple[bool, str]:
"""验证身份证号有效性"""
# 基本格式验证
if len(id_card) != 18:
return False, "身份证号必须为18位"
# 前17位必须是数字最后一位可以是数字或X
if not (id_card[:-1].isdigit() and (id_card[-1].isdigit() or id_card[-1].upper() == 'X')):
return False, "身份证号格式不正确前17位必须是数字最后一位可以是数字或X"
# 验证出生日期
birth_date = id_card[6:14]
if not IDCardValidator.validate_birth_date(birth_date):
return False, "身份证号中的出生日期无效"
# 验证校验码
if not IDCardValidator.validate_check_code(id_card):
return False, "身份证号校验码不正确"
return True, "身份证号有效"
@staticmethod
def validate_birth_date(birth_date: str) -> bool:
"""验证出生日期是否有效"""
try:
# 尝试解析日期
year = int(birth_date[0:4])
month = int(birth_date[4:6])
day = int(birth_date[6:8])
# 检查日期范围
if not (1900 <= year <= date.today().year):
return False
if not (1 <= month <= 12):
return False
# 检查每月天数
max_day = IDCardValidator.get_days_in_month(year, month)
if not (1 <= day <= max_day):
return False
return True
except:
return False
@staticmethod
def get_days_in_month(year: int, month: int) -> int:
"""获取某年某月的天数"""
if month == 2:
return 29 if IDCardValidator.is_leap_year(year) else 28
elif month in [4, 6, 9, 11]:
return 30
else:
return 31
@staticmethod
def is_leap_year(year: int) -> bool:
"""判断是否为闰年"""
return (year % 4 == 0 and year % 100 != 0) or (year % 400 == 0)
@staticmethod
def validate_check_code(id_card: str) -> bool:
"""验证身份证校验码"""
# 权重因子
weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2]
# 校验码对应表
check_code_map = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']
# 计算加权和
total = sum(int(id_card[i]) * weight[i] for i in range(17))
# 计算校验码
calculated_code = check_code_map[total % 11]
# 比较校验码
return id_card[-1].upper() == calculated_code
@staticmethod
def get_gender(id_card: str) -> str:
"""根据身份证号获取性别"""
if len(id_card) < 17:
return "未知"
gender_num = int(id_card[16])
return "" if gender_num % 2 == 1 else ""
@staticmethod
def get_birth_date(id_card: str) -> Optional[date]:
"""从身份证号获取出生日期"""
if len(id_card) < 14:
return None
try:
birth_str = id_card[6:14]
return datetime.strptime(birth_str, "%Y%m%d").date()
except:
return None
@staticmethod
def calculate_age(id_card: str) -> Optional[int]:
"""根据身份证号计算年龄"""
birth_date = IDCardValidator.get_birth_date(id_card)
if not birth_date:
return None
today = date.today()
age = today.year - birth_date.year
# 如果生日还没到年龄减1
if (today.month, today.day) < (birth_date.month, birth_date.day):
age -= 1
return age
class StudentService:
def __init__(self, data_access: StudentDataAccess):
self.data_access = data_access
self.subject_name = {
'math': '数学',
'python': 'Python程序设计',
'english': '英语',
'physics': '物理',
'sum': '总分'
}
def validate_id_card(self, id_card: str) -> Tuple[bool, str]:
"""验证身份证号格式"""
return IDCardValidator.validate_id_card(id_card)
def is_id_card_exists(self, id_card: str, exclude_id: str = None) -> bool:
"""检查身份证号是否已存在"""
students = self.data_access.get_all_students()
for sid, student in students.items():
if exclude_id and sid == exclude_id:
continue
if student['basic_info'].get('id_card', '').upper() == id_card.upper():
return True
return False
def add_student(self, student_info: Dict[str, Any]) -> bool:
"""添加新学生"""
student_id = student_info['basic_info']['id']
# 验证学号
if not student_id.isdigit() or len(student_id) != 8:
raise ValueError("学号必须为8位数字")
# 验证身份证号
id_card = student_info['basic_info'].get('id_card', '')
if not id_card:
raise ValueError("身份证号不能为空!")
is_valid, msg = self.validate_id_card(id_card)
if not is_valid:
raise ValueError(f"身份证号无效: {msg}")
if self.is_id_card_exists(id_card):
raise ValueError("该身份证号已存在!")
# 自动填充性别和出生日期
student_info['basic_info']['gender'] = IDCardValidator.get_gender(id_card)
birth_date = IDCardValidator.get_birth_date(id_card)
if birth_date:
student_info['basic_info']['birth_date'] = birth_date.strftime("%Y-%m-%d")
student_info['basic_info']['age'] = IDCardValidator.calculate_age(id_card)
# 计算总分
scores = student_info['score']
scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']])
return self.data_access.add_student(student_id, student_info)
def update_student(self, student_id: str, student_info: Dict[str, Any]) -> bool:
"""更新学生信息"""
# 验证身份证号
id_card = student_info['basic_info'].get('id_card', '')
if id_card: # 如果提供了身份证号才验证
is_valid, msg = self.validate_id_card(id_card)
if not is_valid:
raise ValueError(f"身份证号无效: {msg}")
if self.is_id_card_exists(id_card, exclude_id=student_id):
raise ValueError("该身份证号已被其他学生使用!")
# 自动更新性别和出生日期
student_info['basic_info']['gender'] = IDCardValidator.get_gender(id_card)
birth_date = IDCardValidator.get_birth_date(id_card)
if birth_date:
student_info['basic_info']['birth_date'] = birth_date.strftime("%Y-%m-%d")
student_info['basic_info']['age'] = IDCardValidator.calculate_age(id_card)
# 计算总分
scores = student_info['score']
scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']])
return self.data_access.update_student(student_id, student_info)
def delete_student(self, student_id: str) -> bool:
"""删除学生"""
return self.data_access.delete_student(student_id)
def get_student(self, student_id: str) -> Dict[str, Any]:
"""获取单个学生信息"""
return self.data_access.get_student(student_id)
def get_all_students(self) -> Dict[str, Any]:
"""获取所有学生信息"""
return self.data_access.get_all_students()
def search_student_by_id(self, student_id: str) -> Dict[str, Any]:
"""按学号查询学生信息"""
return self.data_access.get_student(student_id)
def get_statistics(self) -> Dict[str, float]:
"""获取统计信息"""
students = self.data_access.get_all_students().values()
if not students:
return {}
total = len(students)
return {
'total': total,
'math_avg': sum(s['score']['math'] for s in students) / total,
'python_avg': sum(s['score']['python'] for s in students) / total,
'english_avg': sum(s['score']['english'] for s in students) / total,
'physics_avg': sum(s['score']['physics'] for s in students) / total,
'total_avg': sum(s['score']['sum'] for s in students) / total
}
def get_sorted_students(self) -> List[Dict[str, Any]]:
"""按总分排序获取学生"""
students = list(self.data_access.get_all_students().values())
return sorted(students, key=lambda x: x['score']['sum'], reverse=True)
def load_data(self):
pass
Loading…
Cancel
Save