You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
124 lines
4.2 KiB
124 lines
4.2 KiB
import csv
|
|
import json
|
|
import os
|
|
import sqlite3
|
|
from abc import ABC, abstractmethod
|
|
from datetime import date
|
|
from typing import List, Optional, Union
|
|
|
|
|
|
# 学生类定义
|
|
class Student:
|
|
def __init__(self,
|
|
name: str,
|
|
id_card: str,
|
|
stu_id: str,
|
|
gender: Optional[bool] = None,
|
|
height: Optional[int] = None,
|
|
weight: Optional[float] = None,
|
|
enrollment_date: Optional[Union[date, str]] = None,
|
|
class_name: Optional[str] = None,
|
|
major: str = None):
|
|
self.name = name
|
|
self.id_card = id_card
|
|
self.stu_id = stu_id
|
|
self.gender = gender
|
|
self.height = height
|
|
self.weight = weight
|
|
if isinstance(enrollment_date, str):
|
|
self.enrollment_date = date.fromisoformat(enrollment_date)
|
|
else:
|
|
self.enrollment_date = enrollment_date
|
|
self.class_name = class_name
|
|
self.major = major
|
|
self.age, self.birthday = self._calculate_age_and_birthday()
|
|
self._validation_errors = []
|
|
self._validate_all()
|
|
|
|
def _calculate_age_and_birthday(self):
|
|
birth_year = int(self.id_card[6:10])
|
|
birth_month = int(self.id_card[10:12])
|
|
birth_day = int(self.id_card[12:14])
|
|
birthday = date(birth_year, birth_month, birth_day)
|
|
today = date.today()
|
|
age = today.year - birth_year
|
|
if (today.month, today.day) < (birth_month, birth_day):
|
|
age -= 1
|
|
return age, birthday
|
|
|
|
def _validate_all(self):
|
|
self._validate_id_card()
|
|
self._validate_stu_id()
|
|
self._validate_name()
|
|
self._validate_enrollment_date()
|
|
self._validate_height()
|
|
self._validate_weight()
|
|
|
|
def _validate_id_card(self):
|
|
if len(self.id_card) != 18:
|
|
self._validation_errors.append("身份证号必须为18位")
|
|
# 简单的校验位验证,可根据国家标准完善
|
|
try:
|
|
int(self.id_card[:17])
|
|
except ValueError:
|
|
self._validation_errors.append("身份证号前17位必须为数字")
|
|
|
|
def _validate_stu_id(self):
|
|
if not self.stu_id:
|
|
self._validation_errors.append("学号不能为空")
|
|
|
|
def _validate_name(self):
|
|
if not (2 <= len(self.name) <= 20):
|
|
self._validation_errors.append("姓名长度需在2-20个字符之间")
|
|
if any(char.isdigit() or not char.isalpha() for char in self.name):
|
|
self._validation_errors.append("姓名不能包含数字和特殊符号")
|
|
|
|
def _validate_enrollment_date(self):
|
|
if self.enrollment_date and self.enrollment_date < self.birthday:
|
|
self._validation_errors.append("入学日期不能早于出生日期")
|
|
|
|
def _validate_height(self):
|
|
if self.height is not None and not (50 <= self.height <= 250):
|
|
self._validation_errors.append("身高需在50-250cm之间")
|
|
|
|
def _validate_weight(self):
|
|
if self.weight is not None and not (5 <= self.weight <= 300):
|
|
self._validation_errors.append("体重需在5-300kg之间")
|
|
|
|
@property
|
|
def is_valid(self):
|
|
return len(self._validation_errors) == 0
|
|
|
|
def get_errors(self):
|
|
return self._validation_errors.copy()
|
|
|
|
def to_dict(self):
|
|
return {
|
|
'name': self.name,
|
|
'id_card': self.id_card,
|
|
'stu_id': self.stu_id,
|
|
'gender': self.gender,
|
|
'height': self.height,
|
|
'weight': self.weight,
|
|
'enrollment_date': self.enrollment_date.isoformat() if self.enrollment_date else None,
|
|
'class_name': self.class_name,
|
|
'major': self.major,
|
|
'age': self.age,
|
|
'birthday': self.birthday.isoformat()
|
|
}
|
|
|
|
@classmethod
|
|
def from_dict(cls, data):
|
|
return cls(
|
|
name=data['name'],
|
|
id_card=data['id_card'],
|
|
stu_id=data['stu_id'],
|
|
gender=data['gender'],
|
|
height=data['height'],
|
|
weight=data['weight'],
|
|
enrollment_date=data['enrollment_date'],
|
|
class_name=data['class_name'],
|
|
major=data['major']
|
|
)
|
|
|