From 0507891046a8c129776c6970245f380121c0f852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=98=E5=8D=93=E8=B1=AA?= <2232041467@qq.com> Date: Wed, 25 Jun 2025 11:16:58 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=B8=80=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script.py | 259 ------------------------------------------------------ 1 file changed, 259 deletions(-) delete mode 100644 script.py diff --git a/script.py b/script.py deleted file mode 100644 index aa31e90..0000000 --- a/script.py +++ /dev/null @@ -1,259 +0,0 @@ -import csv -import json -import sqlite3 -from abc import ABC, abstractmethod -from datetime import date -from typing import List, Optional, Dict, Any, 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: Optional[str] = None): - self.name = name - self.id_card = id_card - self.stu_id = stu_id - self.gender = gender - self.height = height - self.weight = weight - self.enrollment_date = date.fromisoformat(enrollment_date) if isinstance(enrollment_date, - str) else 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) -> tuple[int, date]: - birth_year, birth_month, birth_day = map(int, (self.id_card[6:10], self.id_card[10:12], self.id_card[12:14])) - birthday = date(birth_year, birth_month, birth_day) - today = date.today() - age = today.year - birth_year - ((today.month, today.day) < (birth_month, birth_day)) - return age, birthday - - def _validate_all(self) -> List[str]: - errors = [] - if len(self.id_card) != 18 or not self.id_card[:17].isdigit(): - errors.append("身份证号必须为18位数字") - if not self.stu_id: - errors.append("学号不能为空") - if not (2 <= len(self.name) <= 20) or not self.name.isalpha(): - errors.append("姓名需为2-20个字母") - if self.enrollment_date and self.enrollment_date < self.birthday: - errors.append("入学日期不能早于出生日期") - if self.height and not 50 <= self.height <= 250: - errors.append("身高需在50-250cm之间") - if self.weight and not 5 <= self.weight <= 300: - errors.append("体重需在5-300kg之间") - return errors - - @property - def is_valid(self) -> bool: - return not self._validation_errors - - def to_dict(self) -> Dict[str, Any]: - 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: Dict[str, Any]) -> 'Student': - return cls(**data) - - -class IStudentDAL(ABC): - @abstractmethod - def get_by_id(self, id_card: str) -> Optional[Student]: ... - - @abstractmethod - def get_by_stu_id(self, stu_id: str) -> Optional[Student]: ... - - @abstractmethod - def get_all(self) -> List[Student]: ... - - @abstractmethod - def add(self, student: Student) -> bool: ... - - @abstractmethod - def delete(self, id_card: str = None, stu_id: str = None) -> bool: ... - - @abstractmethod - def update(self, student: Student) -> bool: ... - - -class BaseDAL(IStudentDAL): - def __init__(self, file_path: str): - self.file_path = file_path - self._init_storage() - - def _init_storage(self): pass - - def get_by_stu_id(self, stu_id: str) -> Optional[Student]: - return next((s for s in self.get_all() if s.stu_id == stu_id), None) - - -class CSVStudentDAL(BaseDAL): - def _init_storage(self): - with open(self.file_path, 'a') as f: pass # Ensure file exists - - def get_all(self) -> List[Student]: - with open(self.file_path, 'r') as f: - return [Student.from_dict(row) for row in csv.DictReader(f)] - - def add(self, student: Student) -> bool: - if self.get_by_id(student.id_card) or self.get_by_stu_id(student.stu_id): - return False - with open(self.file_path, 'a', newline='') as f: - writer = csv.DictWriter(f, fieldnames=student.to_dict().keys()) - if f.tell() == 0: writer.writeheader() - writer.writerow(student.to_dict()) - return True - - def delete(self, id_card: str = None, stu_id: str = None) -> bool: - students = [s for s in self.get_all() - if not ((id_card and s.id_card == id_card) or (stu_id and s.stu_id == stu_id))] - with open(self.file_path, 'w', newline='') as f: - if students: - writer = csv.DictWriter(f, fieldnames=students[0].to_dict().keys()) - writer.writeheader() - writer.writerows(s.to_dict() for s in students) - return len(students) < len(self.get_all()) - - -class JSONStudentDAL(BaseDAL): - def _init_storage(self): - with open(self.file_path, 'a') as f: pass - - def get_all(self) -> List[Student]: - with open(self.file_path, 'r') as f: - return [Student.from_dict(row) for row in json.load(f)] - - def add(self, student: Student) -> bool: - data = self.get_all() - if any(s.id_card == student.id_card or s.stu_id == student.stu_id for s in data): - return False - data.append(student) - self._save_all(data) - return True - - def _save_all(self, data: List[Student]): - with open(self.file_path, 'w') as f: - json.dump([s.to_dict() for s in data], f, indent=2) - - -class SQLiteStudentDAL(BaseDAL): - def _init_storage(self): - with sqlite3.connect(self.file_path) as conn: - conn.execute(''' - CREATE TABLE IF NOT EXISTS students ( - id_card TEXT PRIMARY KEY, stu_id TEXT UNIQUE, name TEXT, - gender BOOLEAN, height INTEGER, weight REAL, - enrollment_date TEXT, class_name TEXT, major TEXT, - age INTEGER, birthday TEXT)''') - - def get_all(self) -> List[Student]: - with sqlite3.connect(self.file_path) as conn: - rows = conn.execute("SELECT * FROM students").fetchall() - return [Student.from_dict(dict(zip(('id_card', 'stu_id', 'name', 'gender', 'height', - 'weight', 'enrollment_date', 'class_name', 'major', - 'age', 'birthday'), row))) for row in rows] - - def add(self, student: Student) -> bool: - try: - with sqlite3.connect(self.file_path) as conn: - conn.execute(''' - INSERT INTO students VALUES (?,?,?,?,?,?,?,?,?,?,?)''', - (student.id_card, student.stu_id, student.name, student.gender, - student.height, student.weight, - student.enrollment_date.isoformat() if student.enrollment_date else None, - student.class_name, student.major, student.age, student.birthday.isoformat())) - return True - except sqlite3.IntegrityError: - return False - - -class StudentService: - def __init__(self, dal: IStudentDAL): - self.dal = dal - - def add_student(self, student: Student) -> bool: - if not student.is_valid: - raise ValueError(f"Invalid student: {', '.join(student._validation_errors)}") - return self.dal.add(student) - - def get_all(self) -> List[Student]: - return self.dal.get_all() - - def query(self, **kwargs) -> List[Student]: - return [s for s in self.get_all() - if all(getattr(s, k, None) == v for k, v in kwargs.items() if v)] - - def get_stats(self, field: str) -> Dict[str, int]: - return {v: sum(1 for s in self.get_all() if getattr(s, field) == v) - for v in set(getattr(s, field) for s in self.get_all())} - - -class StudentCLI: - def __init__(self, service: StudentService): - self.service = service - - def run(self): - while True: - print("\n1. Add 2. List 3. Query 4. Stats 0. Exit") - choice = input("Choice: ") - if choice == "1": - self._add() - elif choice == "2": - self._list() - elif choice == "3": - self._query() - elif choice == "4": - self._stats() - elif choice == "0": - break - - def _add(self): - student = Student( - name=input("Name: "), - id_card=input("ID Card: "), - stu_id=input("Student ID: "), - gender=input("Gender (True/False): ").lower() == 'true', - height=int(input("Height: ")) if input("Height (optional): ") else None, - weight=float(input("Weight: ")) if input("Weight (optional): ") else None - ) - try: - if self.service.add_student(student): - print("Added successfully!") - except ValueError as e: - print(f"Error: {e}") - - def _list(self): - for student in self.service.get_all(): - print(student.to_dict()) - - def _query(self): - field = input("Field to query (name/class_name/major): ") - value = input(f"{field} value: ") - for student in self.service.query(**{field: value}): - print(student.to_dict()) - - def _stats(self): - field = input("Field for stats (class_name/major): ") - for k, v in self.service.get_stats(field).items(): - print(f"{k}: {v}") - - -if __name__ == "__main__": - storage = input("Storage (csv/json/sqlite): ").lower() - dal = { - 'csv': CSVStudentDAL('students.csv'), - 'json': JSONStudentDAL('students.json'), - 'sqlite': SQLiteStudentDAL('students.db') - }.get(storage, SQLiteStudentDAL('students.db')) - - service = StudentService(dal) - StudentCLI(service).run() \ No newline at end of file