7-8次PTA和期末成绩总结

发布时间 2023-12-09 16:54:07作者: baizang

 

(1)前言:总结之前所涉及到的知识点、题量、难度等情况

  课程成绩统计程序-3在第二次的基础上修改了计算总成绩的方式(修改类结构,将成绩类的继承关系改为组合关系,成绩信息由课程成绩类和分项成绩类组成,课程成绩类组合分项成绩类,分项成绩类由成绩分值和权重两个属性构成)。

  

  1.组合(Composition):
  组合是一种“has-a“关系,即一个类包含另一个类的对象。这种关系允许我们在运行时动态地改变对象的行为。在课程成绩统计的场景中,我们可以将一个班级看作是由学生组成的,每个学生有他自己的成绩。使用组合的好处是:·更加灵活:可以通过改变学生的行为来改变班级的行为。·更容易维护:当需要添加或删除学生时,只需要修改班级的代码即可。

  2.继承(Inheritance):
  
继承是一种"is-a"关系,即一个类继承另一个类的属性和方法。在课程成绩统计的场景中,我们可以创建一个抽象类或接口来表示学生或班级的一些通用行为,然后让具体的类继承这些行为。使用继承的好处是:·可以重用父类的代码:子类会继承父类的所有非私有方法,这样可以避免代码重复。·子类可以扩展父类的行为:通过覆盖父类的方法,子类可以定制自己的行为。更加清晰:通过继承关系,可以清楚地看到哪些类有相同的行为,从而更容易理解和维护代码。

  总的来说,如果设计比较简单,并且希望重用代码,那么使用继承是一个不错的选择。但是如果需要更加灵活的设计,或者希望在运行时动态地改变对象的行为,那么使用组合可能更加合适。在这次第七次和第八次PTA中使用组合方式更好,代码灵活度更高,消耗资源更少。

 

(2)设计与分析:重点对题目的提交源码进行分析,可参考SourceMonitor的生成报表内容以及PowerDesigner的相应类图,要有相应的解释和心得(做到有图有真相),本次Blog必须分析PTA中成绩计算系列的题目

  简单设计基础:

  用于计算学生的总成绩。程序中定义了四个类:Student、Subject、ExamCourse和ExperimentCourse。Student类表示学生,包含学生的学号、姓名和课程列表;Subject类表示课程,包含课程名、课程性质、考核方式等属性;ExamCourse类表示考试考察课程,继承自Subject类,包含学生对象、平时成绩和期末成绩等属性;ExperimentCourse类表示实验课程,继承自Subject类,包含学生对象、实验次数和每次实验的成绩列表等属性。

  在Main类中,首先通过Scanner类从控制台读取学生的学号、姓名和课程类型。然后根据课程类型创建相应的课程对象,并调用calculateTotalScore()方法计算学生的总成绩。如果课程类型为"实验",则还需要读取课程性质、考核方式、实验次数和每次实验的成绩列表等信息。最后,将学生的学号、姓名和总成绩输出到控制台。在此基础上增加第七次和第八次代码要求:

  代码Java程序用于计算学生的成绩。它包含了多个类和方法,用于处理学生、课程和成绩的数据存储和计算。

    1. Calculate_grades 类:这个类包含了计算学生总平均分、单个课程成绩和班级成绩的方法。

      • stu_all_grades 方法:计算单个学生总平均分。它接收一个 Data_storage 对象和一个学生学号作为参数,返回该学生的总平均分。
      • single_course_grades 方法:计算单个课程的成绩。它接收一个 Data_storage 对象和一个课程名作为参数,返回一个包含平时成绩、期末考试成绩和总分平均的数组。
      • Class_grades 方法:计算班级成绩。它接收一个 Data_storage 对象和一个班级号作为参数,返回该班级的平均成绩。
      • final_score 方法:计算每门课的成绩。它接收一个 Data_storage 对象和一个学生学号作为参数,根据课程类型计算并更新学生的成绩。
    2. Class 类:表示一个班级,包含一个学号和一个学生映射。

    3. Course 类:表示一门课程,包含课程类型、测试方式和名称。

    4. Inspect_Course 类:继承自 Course 类,表示一项检查作业。

    5. Test_Course 类:继承自 Course 类,表示一项考试。

    6. Lab_Course 类:继承自 Course 类,表示一项实验。

    7. Data_storage 类:表示数据存储对象,包含课程、班级和选课类的映射。它还包含一个输出对象 output

    8. InAndOut_put 类:表示输入输出对象,用于处理数据的输入和输出。

    9. Compare 静态方法:用于比较两个字符串的大小,用于排序。

    10. 定义了一个抽象类
Score
      ,包含一个字符串类型的成员变量
total_scores
    ,初始值为"-100"。
  10.定义了一个Student类,包含两个字符串类型的成员变量namenum,以及一个构  造函数,用于初始化这两个成员变量。

  11.定义了一个StudentsAll_mes类,包含一个字符串类型的成员变量num和一个TreeMap类型的成员变量gradeMap,用于存储学生的成绩信息。该类还包含了多个构造函数,用于创建不同类型的成绩对象(如Test_ScoreInspect_ScoreLab_Score),并将它们添加到gradeMap中。此外,还提供了一些方法,用于设置成绩信息。

  12.定义了三个继承自Score类的子类:Test_ScoreLab_ScoreInspect_Score,分别表示普通考试成绩、实验室成绩和考察成绩。这些子类都包含两个字符串类型的成员变量,分别表示考试成绩的相关信息。

  13.定义了一个InAndOut_put类,包含两个列表类型的成员变量outputinput,用于存储输出和输入的信息。该类还提供了两个方法,用于向outputinput列表中添加信息。

  14.在Main类的main方法中,首先创建了一个Scanner对象用于读取用户输入,然后创建了三个对象:Input_FormatOutput_FormatData_storage,分别用于处理输入、输出和存储数据。接下来,使用一个循环来读取用户输入的每一行,直到用户输入"end"为止。在循环中,调用inputFormat.inputProcessing(inputLine,data_storage)方法来处理输入的数据,并将其存储到data_storage对象中。最后,调用outputFormat.outputProcessing(data_storage)方法来处理存储的数据,并调用outputFormat.output_all(data_storage)方法来打印所有输出的信息

 

这段代码的主要功能是处理学生、课程和成绩的数据存储和计算。通过调用相应的方法,可以计算单个学生或班级的总平均分、单个课程的成绩以及每个学生的每门课程成绩。

(3)采坑心得:对源码的提交过程中出现的问题及心得进行总结,务必做到详实,拿数据、源码及测试结果说话,切忌假大空

在源码的提交过程中,我遇到了一些问题,并从中获得了一些心得体会。以下是我对这些问题及心得的总结:

  1. 编译错误 在提交代码之前,需要确保代码能够成功编译。如果代码中存在语法错误或者依赖库缺失等问题,会导致编译失败。 心得:在编写代码时,要注意语法的正确性,并且及时处理编译器给出的警告信息。在提交之前,要确保本地环境中所有依赖库都已安装并且能够成功编译。

  2. 逻辑错误 在代码中存在逻辑错误时,可能会导致程序运行结果与预期不符。这种错误往往比较难以发现,需要通过调试和测试来定位问题所在。 心得:在编写代码时,要注重逻辑的正确性和严谨性。可以通过编写单元测试来验证代码的正确性,并且在提交之前进行充分的测试,确保程序运行结果符合预期。

  3. 性能问题 在代码中存在性能问题时,可能会导致程序运行速度较慢或者占用过多的系统资源。这种问题通常需要进行性能分析和优化。 心得:在编写代码时,要注意代码的性能影响。可以使用性能分析工具来识别瓶颈所在,并进行相应的优化。在提交之前,要进行性能测试,确保程序运行效率达到要求。

  4. 文档不完善 在提交代码时,如果没有提供足够的文档说明,其他开发者可能无法理解代码的功能和实现方式。这会给后续的开发和维护工作带来困难。 心得:在编写代码时,要注重文档的编写。可以使用注释来解释代码的功能和实现思路,并且编写必要的文档来介绍代码的使用方法和注意事项。在提交之前,要检查文档是否完整并且易于理解。

  5. 代码冲突 在多人协作开发中,由于多个开发者同时对同一份代码进行修改,可能会出现代码冲突的情况。这会导致提交失败,需要解决冲突后才能再次提交。 心得:及时更新代码,避免长时间不提交导致冲突增多。在解决冲突时,要仔细对比不同开发者的修改,选择最合适的解决方案。

总之,对于源码的提交过程,我们需要注重代码的质量和可维护性。通过及时更新代码、解决冲突、保证编译和逻辑正确性、优化性能以及完善文档等方面的努力,可以提高代码的质量和开发效率。

(4)改进建议:对相应题目的编码改进给出自己的见解,做到可持续改进

  1. 代码风格和规范:确保代码风格一致,遵循一定的编码规范。这可以提高代码的可读性和可维护性。

  2. 模块化和组件化:将代码拆分成独立的模块或组件,每个模块或组件负责特定的功能。这样可以提高代码的复用性和可测试性。

  3. 错误处理和异常处理:在代码中添加适当的错误处理和异常处理机制,以应对可能出现的错误情况。可以使用try-catch语句来捕获异常,并记录错误信息。对此语句使用较少,可以多使用学习。

  4. 输入验证和参数校验:对用户输入的数据进行验证和校验,确保数据的合法性和正确性。可以使用正则表达式、数据类型转换等方式来进行验证和校验。

  5. 性能优化:对代码进行性能分析和优化,提高代码的执行效率。

  6. 单元测试和集成测试:编写单元测试和集成测试用例,对代码进行全面的测试。

  7. 文档编写:编写清晰的文档,包括代码的功能说明、使用方法、接口文档等。这可以方便自己回顾查看代码也帮助其他开发者理解和使用代码。

 

期末考试分析:

 

  定义了一个抽象类Solid,它有两个抽象方法:surfaceArea()volume()。这两个方法分别用于计算物体的表面积和体积。

然后,代码定义了两个继承自Solid的子类:CubeRegularPyramidCube类表示立方体,它的边长由构造函数传入,并重写了surfaceArea()volume()方法来计算立方体的表面积和体积。RegularPyramid类表示正方体金字塔,它的边长也由构造函数传入,并重写了surfaceArea()volume()方法来计算正方体金字塔的表面积和体积。

Main类的main方法中,首先创建了一个Scanner对象来读取用户输入的边长值。然后,使用这个边长值创建了一个Cube对象和一个RegularPyramid对象,并将它们传递给display()方法。display()方法接收一个Solid对象作为参数,并调用其surfaceArea()volume()方法来打印出物体的表面积和体积。

在此类图基础上增加魔方问题的相关要求

方法:需要创建一个魔方类(RubikCube),包含颜色、阶数和类型属性。然后创建正方体魔方类(SquareCube)和正三棱锥魔方类(RegularPyramidCube),分别继承自魔方类,并实现计算表面积和体积的方法。最后在主方法中输入两个魔方的信息,调用display方法输出魔方的颜色、表面积和体积。

import java.util.Scanner;

abstract class RubikCube {
String color;
int layer;
double side;

public RubikCube(String color, int layer, double side) {
this.color = color;
this.layer = layer;
this.side = side;
}

public abstract double surfaceArea();
public abstract double volume();
}

class SquareCube extends RubikCube {
public SquareCube(String color, int layer, double side) {
super(color, layer, side);
}

@Override
public double surfaceArea() {
return 6 * Math.pow(side, 2);
}

@Override
public double volume() {
return Math.pow(side, 3);
}
}

class RegularPyramid extends RubikCube {
public RegularPyramid(String color, int layer, double side) {
super(color, layer, side);
}

@Override
public double surfaceArea() {
double area = Math.sqrt(3) * side * side / 4;
return 4 * area;
}

@Override
public double volume() {
double baseArea = (Math.sqrt(3) * side * side) / 4;
double height = (Math.sqrt(2) * side) / Math.sqrt(3);
return (baseArea * height) / 3;
}
}

public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);

String color = input.next();
int layer = input.nextInt();
double side = input.nextDouble();

RubikCube cube1 = new SquareCube(color, layer, side);

color = input.next();
layer = input.nextInt();
side = input.nextDouble();

RubikCube cube2 = new RegularPyramidCube(color, layer, side);
display(cube1);
display(cube2);
}

public static void display(RubikCube cube) {
System.out.println(cube.color);
System.out.printf("%.2f%n", cube.surfaceArea());
System.out.printf("%.2f%n", cube.volume());
}
}

(5)总结:对本阶段(10-16周)综合性总结,学到了什么,哪些地方需要进一步学习及研究,对教师、课程、作业、实验、课上及课下组织方式等方面的改进建议及意见。

在本阶段的PTA Java综合性学习中,我学到了很多关于Java编程的知识和技能。我掌握了Java的基本语法、面向对象编程的概念和实践、异常处理、文件操作,设计原则等重要内容。通过完成课程作业和实验,我进一步巩固了所学的知识,并学会了如何应用Java解决实际问题。

然而,我也意识到自己在某些方面还需要进一步学习和研究。首先,我希望能够更深入地了解Java的高级特性,如多线程编程和网络编程。这些知识对于开发复杂的应用程序非常重要,我希望能够在后续的学习中深入学习和掌握。其次,我希望能够更多地接触到实际项目的开发经验,通过实践来提升自己的编程能力。

对于教师、课程、作业、实验、课上及课下组织方式等方面的改进建议和意见,我认为可以有以下改进:

  1.希望课程能够更加注重培养学生的问题解决能力和团队合作能力。可以通过团队作业来锻炼学生的合作能力和项目管理能力。

  2.希望在课堂上能够有更多的互动和讨论,让学生有机会提问和解答问题。同时,可以鼓励学生在课下进行自主学习和实践,提供一些学习资源和指导。

总的来说,本阶段的PTA Java综合性学习让我受益匪浅,但也存在一些需要改进的地方。我相信通过不断的学习和实践,我能够进一步提升自己的Java编程能力。

源码附录:

import java.util.*;
import java.text.*;
class Calculate_grades {
int stu_all_grades(Data_storage data_storage,String num){//单个学生总课程平均分计算 返回一个分数 1)
int count =0;//这个学生有几门课
int sum = 0;
for (Map.Entry<String, Score> entry : data_storage.stu__st_cour.get(num).gradeMap.entrySet()) {
Score value = entry.getValue();
if(Integer.parseInt(value.total_scores)>=0) {
count++;
sum += Integer.parseInt(value.total_scores);
}
}
if(count!=0)
return sum/count;
else
return -100;//没有参加任何考试
}
int[] single_course_grades(Data_storage data_storage,String name){ //2) 课程名
int count = 0;
int[] aver_grade = new int[3];//0:平时成绩 1:期末考试 2:总分平均
for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//遍历选课类:num-选课类
StudentsAll_mes value = e.getValue();
for (Map.Entry<String, Score> entry : value.gradeMap.entrySet()) {//遍历选课类:course.name-Score
String key1 = entry.getKey();
Score value1 = entry.getValue();
if (key1.equals(name)) {
if(Integer.parseInt(value1.total_scores)>=0) {//总分为- 说明算成绩无效
count++;
aver_grade[2] += Integer.parseInt(value1.total_scores);
if (value1 instanceof Test_Score) {
if (Integer.parseInt(value1.total_scores) >= 0) {
aver_grade[0] += Integer.parseInt(((Test_Score) value1).normal_score);
aver_grade[1] += Integer.parseInt(((Test_Score) value1).end_score);
}
} else if (value1 instanceof Inspect_Score){
if (Integer.parseInt(value1.total_scores) >= 0) {
aver_grade[0] = -100;//不需要平时成绩
aver_grade[1] += Integer.parseInt(((Inspect_Score) value1).end_score);
}
}else if(value1 instanceof Lab_Score){
if(Integer.parseInt(value1.total_scores)>=0){
aver_grade[0] = -100;
aver_grade[1] += aver_grade[1] += Integer.parseInt(value1.total_scores);
}
}
}
}
}
}
if(count!=0) {
for (int i = 0; i < 3; i++) {
aver_grade[i] = aver_grade[i] / count;
}
}else {
for (int i = 0; i < 3; i++) {
aver_grade[i] = -100;
}
}
return aver_grade;
}
int Class_grades(Data_storage data_storage,String num){//3)
int sum = 0;
int count = 0;
for (Map.Entry<String, Student> mapEntry : data_storage.classes.get(num).students.entrySet()) {//班级号-Student类
Student value = mapEntry.getValue();//遍历这个班级的所有学生
for (Map.Entry<String, StudentsAll_mes> e : data_storage.stu__st_cour.entrySet()) {//stu_num-选课类
String key1 = e.getKey();//遍历学生的选课类 学号
StudentsAll_mes value1 = e.getValue();
if (key1.equals(value.num)) {//选课类中 跟输入的学号一样
for (Map.Entry<String, Score> entry : value1.gradeMap.entrySet()) {//该num所有成绩遍历
Score gra = entry.getValue();
if(Integer.parseInt(gra.total_scores)>=0) {//有效才算
sum += Integer.parseInt(gra.total_scores);
count++;
}
}
}
}
}
if(count!=0)
return sum/count;
else
return -100;
}
void final_score(Data_storage data_storage,String num){//计算没门课的成绩 学号
data_storage.stu__st_cour.get(num).gradeMap.forEach((key,value)->{//学号 成绩
if(value instanceof Test_Score&&((Test_Score) value).normal_score.matches("\\d+")&&((Test_Score) value).end_score.matches("\\d+")) {
double tem = ((Test_Course) data_storage.courses.get(key)).normal_weight*Integer.parseInt(((Test_Score) value).normal_score);
double tem1 = ((Test_Course) data_storage.courses.get(key)).end_weight*Integer.parseInt(((Test_Score) value).end_score);
value.total_scores = String.valueOf((int)(tem+tem1));
}else if(value instanceof Inspect_Score&&((Inspect_Score) value).end_score.matches("\\d+")){
value.total_scores = ((Inspect_Score) value).end_score;
}else if(value instanceof Lab_Score&&((Lab_Score) value).lab_num.matches("\\d+")){
float sum = 0;
int i=0;
for (Integer score : ((Lab_Score) value).scores) {
sum+= score* ((Lab_Course) data_storage.courses.get(key)).weights.get(i);
i++;
}
value.total_scores = String.valueOf((int)sum);
}
});
}
}
class Class {
String num;
TreeMap<String, Student> students = new TreeMap<>(); //班级里的学生 学号 学生
Class(String num){
this.num = num;
}
}
class Course {
String type;
String test_way;
String name;
Course(String name,String type, String test_way){
this.type = type;
this.name = name;
this.test_way = test_way;
}
}
class Inspect_Course extends Course{
Inspect_Course(String name, String type, String test_way) {
super(name, type, test_way);
}
}
class Test_Course extends Course{
double normal_weight;
double end_weight;

Test_Course(String name, String type, String test_way,String normal_weight,String end_weight) {
super(name, type, test_way);
this.normal_weight = Float.parseFloat(normal_weight);
this.end_weight = Float.parseFloat(end_weight);
}
}
class Lab_Course extends Course{
int sub_scores_num;
ArrayList<Float> weights = new ArrayList<>();
Lab_Course(String name, String type, String test_way,String line) {
super(name, type, test_way);
String[] lines = line.split(" ");
sub_scores_num = Integer.parseInt(lines[3]);
for(int i=4;i<lines.length; i++){
weights.add(Float.parseFloat(lines[i]));
}
}
}
class Data_storage {
TreeMap<String , Course> courses;//课程 k:课程名 v:课程
TreeMap<String, Class> classes = new TreeMap<>();//班级 k:班级号V:班级
TreeMap<String, StudentsAll_mes> stu__st_cour;//选课类学生类结合 k:学号 v:选课类
InAndOut_put output = new InAndOut_put();
Data_storage(){
//学生和选课类结合
stu__st_cour = new TreeMap<>(Data_storage::compare);//重写排序
courses = new TreeMap<>(Data_storage::compare);
}

private static int compare(String o1, String o2) {

try {
Comparator<Object> comparator = Collator.getInstance(Locale.CHINA);
if (comparator.compare(o1, o2) < 0) {
return -1;
} else if (comparator.compare(o1, o2) > 0) {
return 1;
}
} catch (Exception ignored) {
}
return 0;
}

void setInspectCourses(String name, String type, String test_way){
if(!courses.containsKey(name)) {
courses.put(name, new Inspect_Course(name, type, test_way));
}
}
void setTestCourses(String name, String type, String test_way,String normal_weight, String end_weight){
if(!courses.containsKey(name)) {
courses.put(name, new Test_Course(name, type, test_way,normal_weight, end_weight));
}
}
void setLabCourses(String name, String type, String test_way,String line){
if(!courses.containsKey(name)) {
courses.put(name, new Lab_Course(name, type, test_way,line));
}
}
void setClasses(String num){
if(!classes.containsKey(num)) {
classes.put(num, new Class(num));
}
}
void setStudents(String clas_num, String name, String num){//班级号 姓名 学号
if(classes.containsKey(clas_num)){
if(!classes.get(clas_num).students.containsKey(num))
classes.get(clas_num).students.put(num,new Student(name,num));
}
}
void setStu__st_courAndMap(String num,String course,String normal_score,String end_score){//添加选课类 学生姓名 课程名称 分数
if(!stu__st_cour.containsKey(num)){
stu__st_cour.put(num,new StudentsAll_mes(num,course,normal_score,end_score));
}
else{
stu__st_cour.get(num).setGradeMap(course,normal_score,end_score);
}
}
void setStu__st_courAndMap(String num,String course,String end_score){
if(!stu__st_cour.containsKey(num)){
stu__st_cour.put(num,new StudentsAll_mes(num,course,end_score));
}
else{
stu__st_cour.get(num).setGradeMap(course,end_score);
}
}
void set_lab_grades(String stu_num,String course,String lab_num,String grades){
ArrayList<Integer> scores = new ArrayList<>();
String[] tem = grades.split(" ");
for(int i=3;i<tem.length;i++){
if(tem[i].matches("\\d+"))
scores.add(Integer.parseInt(tem[i]));
}
if(!stu__st_cour.containsKey(stu_num)){
StudentsAll_mes tem_stu_mes = new StudentsAll_mes();
tem_stu_mes.set_lab_stu_mes(stu_num,course,lab_num,scores);
stu__st_cour.put(stu_num,tem_stu_mes);
}else{
stu__st_cour.get(stu_num).set_lab_gradeMap(course,lab_num,scores);
}
}
}
class Input_Format {
String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修)\\s考试\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$";
String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s选修\\s考察$";
String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s实验\\s实验\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){3,9}$";
String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4E00-\\u9FA5A-Za-z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$";
String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9 ]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){2,9}$";
boolean isEnd = true;//结束标志
String[] strings;
void inputProcessing(String line,Data_storage data_storage) {
lineProcessing(line);//分割
data_storage.output.add_input(line);//存储
if(line.matches(regex_c_inspect)){
data_storage.setInspectCourses(strings[0],strings[1],strings[2]);
}else if(line.matches(regex_c_lab)){
data_storage.setLabCourses(strings[0],strings[1],strings[2],line);
}else if(line.matches(regex_c_test)){
data_storage.setTestCourses(strings[0],strings[1],strings[2],strings[3],strings[4]);//成绩信息
} else if(line.matches(regex_CS)||line.matches(regex_lab)){
data_storage.setClasses(strings[0].substring(0,6));
data_storage.setStudents(strings[0].substring(0, 6), strings[1], strings[0]);//学生的添加
if (data_storage.courses.containsKey(strings[2])) {//课程里有这个课
if (data_storage.courses.get(strings[2]).type.equals("选修")) {//
if (data_storage.courses.get(strings[2]).test_way.equals("考试")&&strings.length == 5) {
data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3], strings[4]);
}else if(data_storage.courses.get(strings[2]).test_way.equals("考察")&&strings.length==4){
data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3]);
} else {
data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access");
}
} else if (data_storage.courses.get(strings[2]).type.equals("必修")) {//
if (strings.length == 5) {
data_storage.setStu__st_courAndMap(strings[0], strings[2], strings[3],strings[4]);
} else {//无效
data_storage.setStu__st_courAndMap(strings[0], strings[2], "no access", "no access");
}
} else if(data_storage.courses.get(strings[2]).type.equals("实验")){
if(strings.length == 3+((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num){
data_storage.set_lab_grades(strings[0],strings[2], String.valueOf(((Lab_Course) data_storage.courses.get(strings[2])).sub_scores_num),line);
}else{
data_storage.set_lab_grades(strings[0],strings[2],"num error","no access");
}
}
}else{
data_storage.setStu__st_courAndMap(strings[0], strings[2], "not exist");
}
}
}
void lineProcessing(String line){
strings = line.split(" ");
}
}
class Inspect_Score extends Score{
String end_score;
Inspect_Score(String end_score) {
this.end_score = end_score;
}
}
class Output_Format {
Calculate_grades calculate = new Calculate_grades();
String regex_c_test = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((\\d{1,2})|(1-9?))\\s((\\d{1,2})|(1-9?))$";
String regex_c_test_e = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s((0.\\d{1,2})|(1-9?))\\s((0.\\d{1,2})|(1-9?))$";
String regex_c_inspect = "[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)$";
String regex_c_lab = "^[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s(必修|选修|实验)\\s(考试|考察|实验)\\s[4-9]\\s((0.\\d{1,2})|(1-9?))(\\s((0.\\d{1,2})|(1-9?))){1,10}$";
String regex_CS = "^\\d{8}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s+[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s*((100)|(\\d{1,2})|(0))?\\s+((100)|(\\d{1,2})|(0))$";
String regex_lab = "^\\d{8}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s[\\u4e00-\\u9fa5a-zA-Z0-9]{1,10}\\s((100)|([1-9]\\d)|\\d)(\\s((100)|([1-9]\\d)|\\d)){1,20}$";
void outputProcessing(Data_storage data) {
data.classes.forEach((num,Class)-> Class.students.forEach((name, student)-> calculate.final_score(data,student.num)));
for(String i:data.output.input){
String[] tem = i.split(" ");
if(i.matches(regex_c_test_e)||i.matches(regex_c_test)||i.matches(regex_c_inspect)||i.matches(regex_c_lab)){
if(tem[1].equals("必修")&&(tem[2].equals("考察")||tem[2].equals("实验"))){
data.output.add_output(tem[0] + " : course type & access mode mismatch");
}else if(tem[1].equals("实验")&&!tem[2].equals("实验")) {
data.output.add_output(tem[0] + " : course type & access mode mismatch");
}else if(tem[1].equals("选修")&&tem[2].equals("实验")) {
data.output.add_output(tem[0] + " : course type & access mode mismatch");
}
if(tem[1].equals("实验")&&tem[2].equals("实验")) {
if(tem.length-4>=4&&tem.length - 4<=9) {
if (Integer.parseInt(tem[3]) != tem.length - 4) {
data.output.add_output(tem[0] + " : number of scores does not match");
data.courses.remove(tem[0]);
continue;
}
float tem_weight = 0;
for (int j = 4; j < tem.length; j++) {
tem_weight += Float.parseFloat(tem[j]);
}
if (Math.abs(tem_weight - 1) > 0.0001) {
data.output.add_output(tem[0] + " : weight value error");
data.courses.remove(tem[0]);
continue;
}
}else{
try {
if (Integer.parseInt(tem[3]) != tem.length - 4) {
data.output.add_output(tem[0] + " : number of scores does not match");
data.courses.remove(tem[0]);
continue;
}
} catch (Exception ignored) {

}
}
}if((tem[1].equals("必修")||tem[1].equals("选修"))&&tem[2].equals("考试")){
if(tem.length-3==2) {
float tem_weight = Float.parseFloat(tem[3]) + Float.parseFloat(tem[4]);
if (Math.abs(tem_weight - 1) > 0.0001) {
data.output.add_output(tem[0] + " : weight value error");
data.courses.remove(tem[0]);
}
}
}
}else if(i.matches(regex_CS)||i.matches(regex_lab)) {
if(!data.courses.containsKey(tem[2])){//不存在
data.output.add_output(tem[2]+" does not exist");
data.stu__st_cour.get(tem[0]).gradeMap.remove(tem[2]);
}else{
if(data.courses.get(tem[2]).type.equals("必修") && tem.length!=5) {//必修 但是只有期末成绩
data.output.add_output(tem[0]+" "+tem[1]+" : access mode mismatch");
}else if(data.courses.get(tem[2]).type.equals("选修")) {
if ((data.courses.get(tem[2]).test_way.equals("考试") && tem.length != 5) ||
(data.courses.get(tem[2]).test_way.equals("考察") && tem.length != 4))
data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch");
}else if(data.courses.get(tem[2]).type.equals("实验")){
if(data.courses.get(tem[2]).test_way.equals("实验")&&(tem.length-3<4||tem.length-3>9||tem.length-3!=((Lab_Course) data.courses.get(tem[2])).sub_scores_num))
data.output.add_output(tem[0] + " " + tem[1] + " : access mode mismatch");
}
}
}else if(!i.equals("end")){
data.output.add_output("wrong format");
}
}
data.classes.forEach((cla_num,Class1)->{//遍历所有班级
Class1.students.forEach((stu_num,student)->{
int tem=calculate.stu_all_grades(data,stu_num);
if(tem>=0)
data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+tem);
else
data.output.add_output(stu_num+" "+Class1.students.get(stu_num).name+" "+"did not take any exams");
});
});
data.courses.forEach((key,value)-> {
int[] tem = calculate.single_course_grades(data, key);
if (tem[0] < 0 && tem[1] < 0 && tem[2] < 0) {//三个为- 则没成绩
data.output.add_output(key + " has no grades yet");
}else {
if (value.type.equals("选修") || value.type.equals("必修") || value.type.equals("实验")) {
data.output.add_output(key + " " + tem[2]);
}
}
});
data.classes.forEach((num,Class)->{
int tem = calculate.Class_grades(data,num);
if(tem>=0) {
data.output.add_output(num + " " + tem);
}else
data.output.add_output(num+" has no grades yet");
});
}
void output_all(Data_storage data){
data.output.output.forEach(System.out::println);
}
}
abstract class Score {
String total_scores = "-100";
}
class Student {
String name;
String num;
Student(String name, String num) {
this.name = name;
this.num = num;
}
}
class StudentsAll_mes {
String num;//学生
TreeMap<String,Score> gradeMap =new TreeMap<>();
StudentsAll_mes(String stu_name, String course, String normal_score,String test_score){
this.num = stu_name;
gradeMap.put(course,new Test_Score(normal_score,test_score));
}
StudentsAll_mes(String stu_name, String course, String test_score){
this.num = stu_name;
gradeMap.put(course,new Inspect_Score(test_score));
}

public StudentsAll_mes() {

}
void set_lab_stu_mes(String stu_num,String course,String lab_num,ArrayList<Integer> scores){
this.num = stu_num;
gradeMap.put(course,new Lab_Score(lab_num,scores));
}
void set_lab_gradeMap(String course,String lab_num,ArrayList<Integer> scores){
if(!gradeMap.containsKey(course))
gradeMap.put(course,new Lab_Score(lab_num,scores));
}
void setGradeMap(String course, String normal_score,String test_score){
if(!gradeMap.containsKey(course))
gradeMap.put(course, new Test_Score(normal_score,test_score));
}
void setGradeMap(String course,String test_score){
if(!gradeMap.containsKey(course))
gradeMap.put(course,new Inspect_Score(test_score));
}

}
class Test_Score extends Score{
String normal_score;
String end_score;
Test_Score(String normal_score,String end_score) {
this.normal_score = normal_score;
this.end_score = end_score;
}
}
class Lab_Score extends Score {
String lab_num;//试验次数

ArrayList<Integer> scores;
Lab_Score(String lab_num,ArrayList<Integer> scores){
this.lab_num = lab_num;
this.scores = scores;
}
}
class InAndOut_put {
List<String> output = new ArrayList<>();
List<String> input = new ArrayList<>();
void add_output(String out){
output.add(out);
}
void add_input(String out){
input.add(out);
}
}
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
Input_Format inputFormat = new Input_Format();//输入
Output_Format outputFormat = new Output_Format();//输出
Data_storage data_storage = new Data_storage();
while (inputFormat.isEnd){
String inputLine = scanner.nextLine();
if(inputLine.equals("end")){
inputFormat.isEnd = false;
break;
}
inputFormat.inputProcessing(inputLine,data_storage);
}
outputFormat.outputProcessing(data_storage);
outputFormat.output_all(data_storage);
}
}