Compare commits

...

3 Commits

@ -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

@ -0,0 +1,60 @@
import json
import os
from typing import Dict, Any
class StudentDataAccess:
def __init__(self, file_path: str = 'student_data.json'):
self.file_path = file_path
def load_data(self) -> Dict[str, Any]:
"""从文件加载所有学生数据"""
try:
if os.path.exists(self.file_path):
with open(self.file_path, 'r', encoding='utf-8') as f:
return json.load(f)
return {}
except Exception as e:
raise Exception(f"加载数据时出错: {e}")
def save_data(self, data: Dict[str, Any]) -> bool:
"""保存所有学生数据到文件"""
try:
with open(self.file_path, 'w', encoding='utf-8') as f:
json.dump(data, f, ensure_ascii=False, indent=4)
return True
except Exception as e:
raise Exception(f"保存数据时出错: {e}")
def get_student(self, student_id: str) -> Dict[str, Any]:
"""根据学号获取单个学生信息"""
data = self.load_data()
return data.get(student_id)
def get_all_students(self) -> Dict[str, Any]:
"""获取所有学生信息"""
return self.load_data()
def add_student(self, student_id: str, student_info: Dict[str, Any]) -> bool:
"""添加新学生"""
data = self.load_data()
if student_id in data:
raise Exception("该学号已存在!")
data[student_id] = student_info
return self.save_data(data)
def update_student(self, student_id: str, student_info: Dict[str, Any]) -> bool:
"""更新学生信息"""
data = self.load_data()
if student_id not in data:
raise Exception("该学号不存在!")
data[student_id] = student_info
return self.save_data(data)
def delete_student(self, student_id: str) -> bool:
"""删除学生"""
data = self.load_data()
if student_id not in data:
raise Exception("该学号不存在!")
del data[student_id]
return self.save_data(data)

@ -0,0 +1,295 @@
import sys
from business_logic import StudentService, IDCardValidator
from data_access import StudentDataAccess
class StudentManagementSystem:
def __init__(self):
self.data_access = StudentDataAccess()
self.student_service = StudentService(self.data_access)
def show_menu(self):
"""显示主菜单"""
menu = """
=== 学生信息管理系统 ===
1. 显示所有学生信息
2. 按学号查询学生信息
3. 添加学生信息
4. 修改学生信息
5. 删除学生信息
6. 统计学生信息
7. 按总分排序显示
8. 验证身份证号
0. 退出系统
"""
print(menu)
def run(self):
"""运行系统"""
self.student_service.load_data()
print("学生信息已成功加载!")
while True:
self.show_menu()
choice = input("请选择操作(0-8): ").strip()
if choice == '0':
print("感谢使用学生信息管理系统,再见!")
sys.exit()
elif choice == '1':
self.show_all_students()
elif choice == '2':
self.search_student()
elif choice == '3':
self.add_student()
elif choice == '4':
self.update_student()
elif choice == '5':
self.delete_student()
elif choice == '6':
self.show_statistics()
elif choice == '7':
self.show_sorted_students()
elif choice == '8':
self.validate_id_card()
else:
print("无效的选择,请重新输入!")
input("\n按回车键继续...")
def show_all_students(self):
"""显示所有学生信息"""
students = self.student_service.get_all_students()
if not students:
print("当前没有学生信息!")
return
print("\n=== 所有学生信息 ===")
print("学号\t姓名\t性别\t年龄\t班级\t总分")
for student_id, info in students.items():
basic_info = info['basic_info']
print(f"{student_id}\t{basic_info['name']}\t{basic_info.get('gender', '未知')}\t"
f"{basic_info.get('age', '未知')}\t{basic_info['class']}\t{info['score']['sum']}")
def search_student(self):
"""按学号查询学生信息"""
student_id = input("请输入要查询的学生学号: ")
student = self.student_service.search_student_by_id(student_id)
if student:
print("\n=== 学生详细信息 ===")
print("基本信息:")
for key, value in student['basic_info'].items():
print(f" {key}: {value}")
print("\n成绩信息:")
for subject, score in student['score'].items():
if subject in self.student_service.subject_name:
print(f" {self.student_service.subject_name[subject]}: {score}")
else:
print("未找到该学号的学生!")
def add_student(self):
"""添加新学生"""
print("\n=== 添加新学生 ===")
# 输入学号
while True:
student_id = input("请输入8位学号(如20230001): ").strip()
if not student_id.isdigit() or len(student_id) != 8:
print("学号必须为8位数字")
continue
if self.student_service.search_student_by_id(student_id):
print("该学号已存在!")
continue
break
# 输入身份证号
while True:
id_card = input("请输入18位身份证号: ").strip().upper()
if not id_card:
print("身份证号不能为空!")
continue
is_valid, msg = self.student_service.validate_id_card(id_card)
if not is_valid:
print(f"身份证号无效: {msg}")
continue
if self.student_service.is_id_card_exists(id_card):
print("该身份证号已存在!")
continue
break
# 自动获取性别和出生日期
gender = IDCardValidator.get_gender(id_card)
birth_date = IDCardValidator.get_birth_date(id_card)
age = IDCardValidator.calculate_age(id_card)
# 输入其他信息
name = input("请输入姓名: ").strip()
class_name = input("请输入班级: ").strip()
admission_year = input("请输入入学年份: ").strip()
# 输入成绩
math_score = float(input("请输入数学成绩: "))
python_score = float(input("请输入Python成绩: "))
english_score = float(input("请输入英语成绩: "))
physics_score = float(input("请输入物理成绩: "))
total_score = math_score + python_score + english_score + physics_score
# 创建学生信息字典
student = {
'basic_info': {
'id': student_id,
'id_card': id_card,
'name': name,
'gender': gender,
'birth_date': birth_date.strftime("%Y-%m-%d") if birth_date else "",
'age': age,
'class': class_name,
'admission_year': admission_year
},
'score': {
'math': math_score,
'python': python_score,
'english': english_score,
'physics': physics_score,
'sum': total_score
}
}
try:
if self.student_service.add_student(student):
print("学生信息添加成功!")
except Exception as e:
print(f"添加学生失败: {e}")
def update_student(self):
"""修改学生信息"""
student_id = input("请输入要修改的学生学号: ")
student = self.student_service.search_student_by_id(student_id)
if not student:
print("未找到该学号的学生!")
return
print("\n当前学生信息:")
print("基本信息:")
for key, value in student['basic_info'].items():
print(f" {key}: {value}")
print("\n成绩信息:")
for subject, score in student['score'].items():
if subject in self.student_service.subject_name:
print(f" {self.student_service.subject_name[subject]}: {score}")
print("\n请输入新的信息(直接回车保持原值):")
# 更新基本信息
basic_info = student['basic_info']
for field in ['name', 'class', 'admission_year']:
new_value = input(f"{field}(当前:{basic_info[field]}): ").strip()
if new_value:
basic_info[field] = new_value
# 更新身份证号
while True:
new_id_card = input(f"身份证号(当前:{basic_info.get('id_card', '')}): ").strip().upper()
if not new_id_card: # 直接回车保持原值
break
is_valid, msg = self.student_service.validate_id_card(new_id_card)
if not is_valid:
print(f"身份证号无效: {msg}")
continue
if self.student_service.is_id_card_exists(new_id_card, exclude_id=student_id):
print("该身份证号已被其他学生使用!")
continue
basic_info['id_card'] = new_id_card
# 自动更新性别和出生日期
basic_info['gender'] = IDCardValidator.get_gender(new_id_card)
birth_date = IDCardValidator.get_birth_date(new_id_card)
if birth_date:
basic_info['birth_date'] = birth_date.strftime("%Y-%m-%d")
basic_info['age'] = IDCardValidator.calculate_age(new_id_card)
break
# 更新成绩
scores = student['score']
for subject in ['math', 'python', 'english', 'physics']:
new_score = input(f"{self.student_service.subject_name[subject]}(当前:{scores[subject]}): ").strip()
if new_score:
scores[subject] = float(new_score)
scores['sum'] = sum([scores['math'], scores['python'], scores['english'], scores['physics']])
try:
if self.student_service.update_student(student_id, student):
print("学生信息修改成功!")
except Exception as e:
print(f"修改学生信息失败: {e}")
def delete_student(self):
"""删除学生"""
student_id = input("请输入要删除的学生学号: ")
confirm = input(f"确定要删除学号为 {student_id} 的学生吗?(y/n): ").lower()
if confirm == 'y':
try:
if self.student_service.delete_student(student_id):
print("学生信息删除成功!")
except Exception as e:
print(f"删除学生失败: {e}")
def show_statistics(self):
"""显示统计信息"""
stats = self.student_service.get_statistics()
if not stats:
print("当前没有学生信息!")
return
print("\n=== 统计信息 ===")
print(f"学生总数: {stats['total']}")
print(f"数学平均分: {stats['math_avg']:.2f}")
print(f"Python平均分: {stats['python_avg']:.2f}")
print(f"英语平均分: {stats['english_avg']:.2f}")
print(f"物理平均分: {stats['physics_avg']:.2f}")
print(f"总分平均分: {stats['total_avg']:.2f}")
def show_sorted_students(self):
"""按总分排序显示"""
sorted_students = self.student_service.get_sorted_students()
if not sorted_students:
print("当前没有学生信息!")
return
print("\n=== 按总分排序 ===")
print("排名\t学号\t姓名\t总分")
for rank, student in enumerate(sorted_students, 1):
print(f"{rank}\t{student['basic_info']['id']}\t{student['basic_info']['name']}\t{student['score']['sum']}")
def validate_id_card(self):
"""验证身份证号"""
id_card = input("请输入要验证的身份证号: ").strip().upper()
is_valid, msg = IDCardValidator.validate_id_card(id_card)
if is_valid:
print("\n=== 身份证号有效 ===")
print(f"号码: {id_card}")
print(f"性别: {IDCardValidator.get_gender(id_card)}")
birth_date = IDCardValidator.get_birth_date(id_card)
if birth_date:
print(f"出生日期: {birth_date.strftime('%Y-%m-%d')}")
print(f"年龄: {IDCardValidator.calculate_age(id_card)}")
print("校验码验证通过")
else:
print(f"\n身份证号无效: {msg}")
if __name__ == "__main__":
system = StudentManagementSystem()
system.run()
Loading…
Cancel
Save