软件构造lab3

1 实验目标概述

本次实验覆盖课程第前两次课的内容,目标是编写具有可复用性和可维护性的软件,主要使用以下软件构造技术:
 子类型、泛型、多态、重写、重载
 继承、代理、组合
 常见的OO设计模式
 语法驱动的编程、正则表达式
 基于状态的编程
 API设计、API复用
本次实验给定了三个具体应用(值班表管理、操作系统进程调度管理、大学课表管理),学生不是直接针对每个应用分别编程实现,而是通过ADT和泛型等抽象技术,开发一套可复用的ADT及其实现,充分考虑这些应用之间的相似性和差异性,使ADT有更大程度的复用(可复用性)和更容易面向各种变化(可维护性)。

2 实验环境配置

在eclipse的workspace中新建java project,其中每一个目录中的文件夹都是source folder(之前不太了解eclipse时使用过folder,发现没有对应功能,必须使用source folder),从github获取用于测试txt文件,按照实验手册要求的目录结构完成目录构建。
在我的电脑文件夹中进入eclipse的workspace,在本次实验的project文件夹中右击选择git bash here,在git窗口中完成新建、配置仓库(git init新建仓库)。

3 实验过程

3.1 待开发的三个应用场景

1.三个应用简介:
1)第一个应用:值班表管理(DutyRoster):一个单位有n个员工,在某个时间段内(例如寒假1月10日—3月6日期间),每天只能安排唯一1个员工在单位值班,且不能出现某天无人值班的情况;每个员工若被安排值班m天(m>1),那么需要安排在连续的m天内。值班表内需要记录员工的名字、职位、手机号码,以便于外界联系值班员。
2)第二个应用:操作系统进程调度管理(ProcessSchedule):考虑计算机上有一个单核CPU,多个进程被操作系统创建出来,它们被调度在CPU上执行,由操作系统来调度决定在各个时段内执行哪个线程。操作系统可挂起某个正在执行的进程,在后续时刻可以恢复执行被挂起的进程。可知:每个时间只能有一个进程在执行,其他进程处于休眠状态;一个进程的执行被分为多个时间段;在特定时刻,CPU可以“闲置”,意即操作系统没有调度执行任何进程;操作系统对进程的调度无规律,可看作是随机调度。
3)第三个应用:大学课表管理(CourseSchedule):看一下你自己的课表,每一上午8:00-10:00和每周三上午8:00-10:00在正心楼13教室上“软件构造”课程。课程需要特定的教室和特定的教师。在本应用中,我们对实际的课表进行简化:针对某个班级,假设其各周的课表都是完全一样的(意即同样的课程安排将以“周”为单位进行周期性的重复,直到学期结束);一门课程每周可以出现1次,也可以安排多次(例如每周一和周三的“软件构造课”)且由同一位教师承担并在同样的教室进行;允许课表中有空白时间段(未安排任何课程);考虑到不同学生的选课情况不同,同一个时间段内可以安排不同的课程(例如周一上午1-2节的计算方法和软件构造);一位教师也可以承担课表中的多门课程。
2.三个应用场景的异同:
1)相同之处:都涉及到时间段的概念,都使用时间段作为应用的基础ADT。对于时间段的ADT来说,需要有起始时间、结束时间、能表示时间段的标签。
2)不同之处:
a)第一个应用中时间段与时间段之间不能有空隙,第二、三个应用中可以有;
b)第一个应用中每个时间段的标签都是独一无二的(不能出现重复),而第二、三个应用中可以出现起止时间不同、标签相同的时间段;
c)第一、二个应用中时间段需要有起止时间和一个标签即可,而第三个应用需要有起止时间和三个标签(课名、老师、教室)。
d)第三个应用的时间段是周期性的,而前两个不是。
e)第三个应用允许不同标签(课名、老师、教室都不同)的时间段重叠,前两个应用不允许。

3.2 面向可复用性和可维护性的设计:IntervalSet< L >

3.2.1 IntervalSet< L >的共性操作

1.创建一个空对象:empty()
2.在当前对象中插入新的时间段和标签:void insert(long start, long end, L label)
3.获得当前对象中的标签集合:Set labels()
4.从当前对象中移除某个标签所关联的时间段:boolean remove(L label)
5.返回某个标签对应的时间段的开始时间:long start (L label)
6.返回某个标签对应的时间段的结束时间:long end (L label)
7.返回包含所有时间段的信息(标签、起止时间)的集合。Set<CommonInterval< L>> getIntervals();

3.2.2 局部共性特征的设计方案

1.设计一个类CommonIntervalSet< L>来实现接口IntervalSet。
1)fields
private Set<CommonInterval< L>> intervals;
2)Abstraction function:
通过labels函数能获得该时间段集合的所有时间段的标签。
通过remove函数能删除一个标签为label的时间段(若没有这样一个时间段,返回false,否则返回true)。
通过insert函数能将一个起止时间分别为start、end、标签为label的时间段加入该时间段集合。
通过start函数能获得该集合内一个标签为label的时间段的开始时间
通过end函数能获得该集合内一个标签为label的时间段的结束时间
通过getIntervals函数能获得该集合内所有时间段的所有信息(用CommonInterval类存储每个时间段的标签、起止时间)。
通过removeInterval函数删除标签是label,起止时间分别为start、end的时间段。
3)Representation invariant:
任意两个时间段的起止时间不能重叠(其中一个的起始时间必然大于等于另一个的结束时间)。
任意一个时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的{@code L}类型、且不为空。
4)Safety from rep exposure:
CommonInterval类(在下文中解释该类)是immutable的。
采用defensive copy来处理需要访问mutable的intervals的函数。
L是immutable的类型。
intervals是private的。
2.接下来设计一个class来实现CommonIntervalSet中的每一个时间段:CommonInterval。
1)fields
private final long start;
private final long end;
private final L label;
2)Abstraction function:
时间段的起止时间是getStart()、getEnd(),标签是getLabel()。
3)Representation invariant:
时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的{@code L}类型、且不为空。
4)Safety from rep exposure:
使用private和final来确保所有fields不会被修改。

3.2.3 面向各应用的IntervalSet子类型设计(个性化特征的设计方案)

使用delegation的方法,在该类的基础上定义NonOverlapIntervalSet, NoBlankIntervalSet, PeriodicIntervalSet三个泛型接口,分别用NonOverlapIntervalSetImpl, NoBlankIntervalSetImpl, PeriodicIntervalSetImpl来实现这些接口,他们分别表示不允许重叠的时间段集合、不允许有空时间段的时间段集合、有周期性的时间段集合。他们完成了额外功能的定义,然后开发应用时就可以按照需要调用他们的方法来完成RI的约束。
NonOverlapIntervalSet定义特殊的insert方法来保证插入时间段的时候没有重叠发生。
NoBlankIntervalSet定义checkNoBlank方法来检查当前时间段集合是否有空白时间段存在,并返回一个集合(若没空白时间段,集合是空的)。
PeriodicIntervalSet定义intervals方法来完成周期性的实现,虽然只保存了一周的时间段集合,但查找的时候能查找到所有周的相应时间段。
1)对dutyroster应用:它是不允许重叠、不允许空白、非周期性的,因此调用NonOverlapIntervalSet的insert方法来保证插入时间段的时候没有重叠发生, 调用NoBlankIntervalSet的checkNoBlank方法来保证不能有空白时间段存在。
2)对processschedule应用:它是不允许重叠、允许空白、非周期性的,因此调用NonOverlapIntervalSet的insert方法来保证插入时间段的时候没有重叠发生。
3)对courseschedule应用:它是允许重叠、允许空白、周期性的,因此调用PeriodicIntervalSet的intervals方法来完成周期性的实现,虽然只保存了一周的时间段集合,但查找的时候能查找到所有周的相应时间段。

3.3 面向可复用性和可维护性的设计:MultiIntervalSet

3.3.1 MultiIntervalSet的共性操作

1.通过labels函数能获得该时间段集合的所有时间段的标签。
2.通过remove函数能删除一个标签为label的时间段(若没有这样一个时间段,返回false,否则返回true)。
3.通过insert函数能将一个起止时间分别为start、end、标签为label的时间段加入该时间段集合。
4.通过intervals函数能获得标签为label的所有时间段(按顺序)。
5.通过getAllIntervals函数能获得该时间段集合内所有的时间段。

3.3.2 局部共性特征的设计方案

1.fields:
private Set<IntervalSet> allintervals;
2.Abstraction function:
1)通过labels函数能获得该时间段集合的所有时间段的标签。
2)通过remove函数能删除一个标签为label的时间段(若没有这样一个时间段,返回false,否则返回true)。
3)通过insert函数能将一个起止时间分别为start、end、标签为label的时间段加入该时间段集合。
4)通过intervals函数能获得标签为label的所有时间段(按顺序)。
5)通过getAllIntervals函数能获得该时间段集合内所有的时间段。
6)通过removeInterval函数删除标签是label,起止时间分别为start、end的时间段。
3.Representation invariant:
1)任意两个时间段的起止时间不能重叠(其中一个的起始时间必然大于等于另一个的结束时间)。
2)任意一个时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的{@code L}类型、且不为空。
4.Safety from rep exposure:
1)CommonInterval类是immutable的。
2)采用defensive copy来处理需要访问mutable的IntervalSet类、allintervals的函数。
3)L是immutable的类型。
4)allintervals是private的。

3.3.3 面向各应用的MultiIntervalSet子类型设计(个性化特征的设计方案)

使用delegation的方法,在该类的基础上定义NonOverlapIntervalSet, NoBlankIntervalSet, PeriodicIntervalSet三个泛型接口,分别用NonOverlapIntervalSetImpl, NoBlankIntervalSetImpl, PeriodicIntervalSetImpl来实现这些接口,他们分别表示不允许重叠的时间段集合、不允许有空时间段的时间段集合、有周期性的时间段集合。他们完成了额外功能的定义,然后开发应用时就可以按照需要调用他们的方法来完成RI的约束。
NonOverlapIntervalSet定义特殊的insert方法来保证插入时间段的时候没有重叠发生。
NoBlankIntervalSet定义checkNoBlank方法来检查当前时间段集合是否有空白时间段存在,并返回一个集合(若没空白时间段,集合是空的)。
PeriodicIntervalSet定义intervals方法来完成周期性的实现,虽然只保存了一周的时间段集合,但查找的时候能查找到所有周的相应时间段。
1)对dutyroster应用:它是不允许重叠、不允许空白、非周期性的,因此调用NonOverlapIntervalSet的insert方法来保证插入时间段的时候没有重叠发生, 调用NoBlankIntervalSet的checkNoBlank方法来保证不能有空白时间段存在。
2)对processschedule应用:它是不允许重叠、允许空白、非周期性的,因此调用NonOverlapIntervalSet的insert方法来保证插入时间段的时候没有重叠发生。
3)对courseschedule应用:它是允许重叠、允许空白、周期性的,因此调用PeriodicIntervalSet的intervals方法来完成周期性的实现,虽然只保存了一周的时间段集合,但查找的时候能查找到所有周的相应时间段。

3.4 面向复用的设计:L

  1. 对dutyroster应用:Employee类
    1)fields
    private final String name;
    private final String job;
    private final String phone;
    2)Abstraction function:
    该员工的姓名是getName(),该员工的职位是getJob(),该员工的电话是getPhone()。
    3)Representation invariant:
    员工的所有信息都是非空字符串,所有fields不可被修改。
    4)Safety from rep exposure:
    使用private和final来确保所有fields不会被修改。
  2. 对processschedule应用:Process类
    1)fields
    private final long id;
    private final String name;
    private final long mintime;
    private final long maxtime;
    2)Abstraction function:
    该进程的id是getID()、姓名是getName()、最短执行时间是getMinTime()、最长执行时间是getMaxTime()。
    3)Representation invariant:
    进程的所有信息都是非空的,所有fields不可被修改。mintime和maxtime均为正数。
    4)Safety from rep exposure:
    使用private和final来确保所有fields不会被修改。
  3. 对courseschedule应用:Course类
    1)fields
    private final String id;
    private final String coursename;
    private final String teachername;
    private final String classroom;
    private final int timeperweek;
    2)Abstraction function:
    该课程的id是getID()、名称是getCourseName()、教师名称是getTeacherName()、教室是getClassroom()、周学时数是getTimePerWeek()。
    3)Representation invariant:
    进程的所有信息都是非空的,所有fields不可被修改;周学时数>0。
    4)Safety from rep exposure:
    使用private和final来确保所有fields不会被修改。

3.5 可复用API设计

3.5.1 计算相似度

采用迭代器进行遍历即可,以其中一个MultiIntervalSe的标签集合为基准寻找另一个MultiIntervalSe中有无与该集合内的时间段标签相同、时间段重合的部分,有的话累加。在过程中不断更新最早的时间和最晚的时间,最后计算重合部分与最晚时间减去最早时间相除的结果。

3.5.2 计算时间冲突比例

对于应用3,采用标记的方式进行时间冲突计算,对于每周七天、每天5节课的课表来说,用7行5列的二维数组进行标记,标记为0代表空闲,标记为1代表有一节课、但不冲突,标记为2代表冲突。

3.5.3 计算空闲时间比例

对于应用3,与3.5.2方法类似,可以采用标记的方式进行时间冲突计算,对于每周七天、每天5节课的课表来说,用7行5列的二维数组进行标记,标记为0代表空闲,标记为1代表有一节课、但不冲突,标记为2代表冲突。
对于应用2,空闲时间就是进程id为0的所有时间段总和,用它除以开始时间和结束时间即可。

3.6 应用设计与开发

3.6.1 排班管理系统

1.设计:
1)整体概述:
a)首先打印欢迎语句:
Welcome to the DutyRosterApp!
然后没退出前,每次循环要求选择功能之前打印提示信息:
Enter a number to choose function!(eg.1)
[0] quit
[1] read a file to build a duty roster
[2] delete an employee
[3] add a roster
[4] check if there is blank
[5] generate a duty roster automatically
[6] show the present duty roster
[7] initialize the employees and period
(顺序:1(或7和多次3)(或7和5), 4和6, 0)
b)通过console完成与用户的交互。
c)
①Abstraction function:
通过checkNoBlank函数能知道当前时间段集合有没有空白时间段。
通过parse函数能通过解析正则表达式文件来代替console完成输入。
通过between函数能获得两个日期之间的间隔时间。
通过main函数完成在console输入以完成要求的功能。
②Representation invariant:
任意两个标签相同的时间段的起止时间不能重叠(其中一个的起始时间必然大于等于另一个的结束时间)。
任意一个时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的Employee类型、且不为空。
完成值班表的构建后,必须没空白时间段(否则不允许退出)。
③Safety from rep exposure:
CommonInterval类是immutable的。
采用defensive copy来处理需获得mutable的fields或类的函数。
Employee是immutable的类型。
所有的fields是private的。
2)main函数的console功能介绍:
a)输入0:退出循环(完成值班表构建)。但如果检查发现有空白段,将不允许退出,打印提示信息。
b)输入1:然后输入txt文件路径,通过解析正则表达式文件来代替console完成输入。
c)输入2:删除一个员工。把以他为标签的时间段都删掉,并将他从保存员工的变长数组中删除。
d)输入3:添加一个时间段(值班记录),用于输入7初始化员工和值班表的起始时间之后。
e)输入4:检查是否有空白时间段,若有把他们打印出来,否则打印”No Blank!”。
f)输入5:随机生成一个值班表,用于输入7初始化员工和值班表的起始时间之后。
g)输入6:打印当前的值班表(按照时间从小到大)。
h)输入7:初始化员工和值班表的起始时间。按照打印的提示信息通过console按格式输入这些信息。
2.测试:
1)
a)测试用例:
1
src/dutyroster/txt/test1.txt
4
6
0
b)测试结果:
在这里插入图片描述
在这里插入图片描述

2)
a)测试用例:
1
src/dutyroster/txt/test1.txt
2
ZhangSan
4
6
0
3
ZhangSan{2021-01-10,2021-01-11}
3
LiSi{2021-01-10,2021-01-11}
0
b)测试结果:
这里命令经过了太多次循环,为了便于查看,暂时将功能提示注释掉了。
可以看到,将ZhangSan删除之后,它的时间段也空出来了,这时候就检查出了空时间段,打印了出来,且退出也不能成功。这时候再想将ZhangSan加回去就不行了,需要用其他员工来填补这个空的时间段,就选择与它邻接的LiSi,因为要求每个人的值班时间段是连续的。这时候就发现检查没有空时间段了,可以退出成功。
hh

3)
a)测试用例:
7
Employee{
ZhangSan{Manger,139-0451-0000}
LiSi{Secretary,151-0101-0000}
}
20210110,20210306
3
ZhangSan{2021-01-10,2021-01-11}
4
3
ZhangSan{2021-01-12,2021-03-06}
4
b)测试结果:
这里命令经过了太多次循环,为了便于查看,暂时将功能提示注释掉了。
这里我们测试了非文件的读入方式。可以看出读取成功。
除此之外,测试了一个员工不能有多个时间段的约束条件,可以看到在下图红框中,企图两次插入ZhangSan的时间段失败了。空白段依旧在那里。
在这里插入图片描述

3.6.2 操作系统的进程调度管理系统

1.设计:
1)整体概述:
a)首先打印欢迎语句:
Welcome to the ProcessScheduleApp!
然后没退出前,每次循环要求选择功能之前打印提示信息:
Enter a number to choose function!(eg.1)
[0] quit
[1] add some processes
[2] show the past process running result and the presentprocess information
[3] random running strategy
[4] min-time-first running strategy
(顺序:1, 3或4, 2(多次键入2可以看到进程执行过程,因为每次键入的时候打印当时的进程执行信息,即对比查看能看到进程执行过程), 0)
b)通过console完成与用户的交互。
c)
①Abstraction function:
通过minLong函数能知道当前所有进程中最大执行时间最短的大小是多少。
通过minLongNum函数能知道当前所有进程中最大执行时间最短的进程的id。
通过isEnd函数能知道当前是否所有进程都执行完毕。
通过main函数完成在console输入以完成要求的功能。
②Representation invariant:
任意两个标签相同的时间段的起止时间不能重叠(其中一个的起始时间必然大于等于另一个的结束时间)。
任意一个时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的Process类型、且不为空。
③Safety from rep exposure:
CommonInterval类是immutable的。
采用defensive copy来处理需获得mutable的fields或类的函数。
Process是immutable的类型。
所有的fields是private的。
2)main函数的console功能介绍:
a)输入0:退出循环。
b)输入1:添加用户希望的数量的进程信息,按提示信息的格式在console进行输入。
c)输入2:打印所有过往执行过的进程信息和当前正在执行的进程(如果有的话)。若没有键入过3或4(没执行过),那么打印"It hasn’t been runned!"。
d)输入3:采用随机选择执行进程的策略挑选未结束的进程来执行。
e)输入4:采用最短进程优先策略来选择未结束的进程来执行(即选择最快能执行结束的进程)。
2.测试:
1)测试用例:
1

5

test0
800
1200

test1
300
400

test2
1400
1700

test3
750
900

test4
920
1000
2)测试结果截图:
0

a)随机策略:
由于选择了随机策略功能,需要再键入3。
然后每次键入2都能看到过往执行过的进程信息和当前正在执行的进程(如果有的话)。
可以看到第一次输入2时,最后一行打印的是[running] 0:nop,意味着当前正在挂起(不执行任何进程)当中;而第二次输入2之后,看到没有方括号里是running的输出行了,且比上一次输入2多了几行输出,这就说明两次键入2之间又执行了新的进程,且当前所有进程执行完毕。

b)最短进程优先策略:
由于选择了随机策略功能,需要再键入4。
然后每次键入2都能看到过往执行过的进程信息和当前正在执行的进程(如果有的话)。
可以看到执行一段时间之后,键入2,没有方括号里是running的输出行,当前所有进程执行完毕。对于同样的进程集合(下次键入1之后加入新进程之前),每次选择这个策略的进程执行顺序是固定的。比如我们的测试用例,因为按照最大执行时间从小到大排序是test1、test3、test4、test0、test2,故一定按照这个顺序执行。下面两张图的对比中也佐证了这一点。
1
2

3.6.3 课表管理系统

1.设计:
1)整体概述:
a)首先打印欢迎语句:
Welcome to the CourseScheduleApp!
然后没退出前,每次循环要求选择功能之前打印提示信息:
Enter a number to choose function!(eg.1)
[0] quit
[1] add all courses
[2] set start time and number of weeks
[3] schedule a course
[4] check all courses needed to be scheduled
[5] check the ratio of the blank and the overlap
[6] search courses on the very day
(顺序:1和2, 多次3, 4或5或6)
b)通过console完成与用户的交互。
c)
①Abstraction function:
通过transferToNumber函数能将星期几转换成数字用于求学期内任意一天的课表,他等于这一天转换到第一周之后距离周一的偏移。
通过main函数完成在console输入以完成要求的功能。
②Representation invariant:
任意一个时间段的起止时间是{@code long}类型的非负数,时间段的终止时间大于起始时间,标签是immutable的Employee类型、且不为空。
完成第一周的课表构建后,在weeks周内每周课程都相同。
③Safety from rep exposure:
CommonInterval类是immutable的。
采用defensive copy来处理需获得mutable的fields或类的函数。
Course是immutable的类型。
所有的fields是private的。
2)main函数的console功能介绍:
a)输入0:退出循环(完成课表构建)。
b)输入1:通过console输入加入所有的课程类,但此时还没有安排他们的课表,也就是课表依旧为空。
c)输入2:设置学期的开始时间和学期的周数。在这些周数范围之内,每周课程均与第一周相同,我们只保存第一周的课表,然后调用PeriodicIntervalSet的intervals方法来完成非第一周的课表查询,将查询的时间进行转换。
d)输入3:添加一个课程安排,每次只能安排两个小时,且起止时间必须是8-10或10-12或13-15或15-17或19-21中的一个,调用transferToNumber方法完成星期几到具体日期的转换。
e)输入4:打印所有未安排完的课程(当前课表中该课的每周学时数未达到course类中的要求周学时数)。
f)输入5:检查当前周课表的空闲比例和时间重叠比例,分别打印。
g)输入6:输入学期内任意一天(若超出了范围,不是本学期课表查询,返回为空,且提示错误信息“invalid date”),能获得当天的课表(将该日期的课表查询转换成第一周相应日期的课表查询)。
2.测试:
1)测试用例:
1
3

CSAPP
0
1
8

SC
1
2
4

ADT
2
3
2

2
2020
9
7
18

3
CSAPP
MonDay
0810
4
5
6
20210104

3
SC
MonDay
0810
5
6
20210104
2)测试结果:
这里命令经过了太多次循环,为了便于查看,暂时将功能提示注释掉了。
首先,添加三门课程,分别叫CSAPP、SC和ADT,然后选择功能2、设置学期的开始日期和周期数,然后选择功能3,在课表中插入CSAPP在周一8-10点的课程安排,然后选择功能4、查看课程的未安排情况,发现刚刚插入课表的CSAPP剩余学时数确实少了2学时,然后选择功能5,发现空闲比例发生了变化。然后选择功能6、查询2021年1月4日的课表(这一天是周一且在学期范围内),得到正确的结果。最后,又插入了另一门课程SC,和上一次插入的课程CSAPP放在同一个位置,此时选择功能4查看空闲、冲突比例,发现冲突比例增加了;又选择功能6查看周一的课表,发现课表确实发生了变化。
yeah

3.7 基于语法的数据读入

调用3.6.1中提到的main函数中键入1可以选择的功能即可。也就是parse函数。
输入1,然后输入txt文件路径,通过解析正则表达式文件来代替console完成输入。这里由于试验给出的测试用例中有全角空格,要使用replace函数将它替换成半角、再通过trim()函数完全消除。

同时,正则表达式的要求要非常规范,比如不能把字母和数字都用.来表示,字母应该用字符集来完成(比如[a-zA-Z]表示所有大、小写的字母),数字的格式是\d{i}(其中i表示数字位数)。

3.8 应对面临的新变化

3.8.1 变化1

1.评估之前的设计是否可应对变化、代价如何:
之前我就是使用的MultiIntervalSet来实现的DutyRosterApp,所以完全可以改变成允许同一个员工有多个时间段的情况。
2.修改设计以应对变化:
将此前的一个员工不能有超过一个时间段的约束条件去掉,所以将员工标记数组去掉,允许任何时间合理(非重叠、无空白)的时间段插入,就可以完成功能了。(将marke数组及相应操作删除)

此时,对于3.6.1中的测试用例3,我们再次测试一下,发现结果完全不同:
1)测试用例:
7
Employee{
ZhangSan{Manger,139-0451-0000}
LiSi{Secretary,151-0101-0000}
}
20210110,20210306
3
ZhangSan{2021-01-10,2021-01-11}
4
3
ZhangSan{2021-01-12,2021-03-06}
4
2)测试结果:
这里命令经过了太多次循环,为了便于查看,暂时将功能提示注释掉了。
左图是变化之前的输出,测试了一个员工不能有多个时间段的约束条件,可以看到在下图红框中,企图两次插入ZhangSan的时间段失败了。空白段依旧在那里。
右图是修改之后的输出,可以实现一个员工多个时间段的约束条件。
前
后

3.8.2 变化2

1.评估之前的设计是否可应对变化、代价如何:
之前我就是调用的MultiIntervalSet来实现的insert(时间段加入操作),这个insert没有约束不能重叠,所以现在只需要调用NonOverlapIntervalSet来实现insert操作就可以完成功能了。
2.修改设计以应对变化:
在CourseIntervalSet类中加入对NonOverlapIntervalSet的调用,用它来实现insert操作。

此时,对于3.6.3中的测试用例,我们再次测试一下,发现结果完全不同:
1)测试用例:
1
3

CSAPP
0
1
8

SC
1
2
4

ADT
2
3
2

2
2020
9
7
18

3
CSAPP
MonDay
0810
4
5
6
20210104

3
SC
MonDay
0810
5
6
20210104
2)测试结果:
这里命令经过了太多次循环,为了便于查看,暂时将功能提示注释掉了。
最后,插入了另一门课程SC,和上一次插入的课程CSAPP放在同一个位置:
变化之前如左图所示,此时选择功能4查看空闲、冲突比例,发现冲突比例增加了;又选择功能6查看周一的课表,发现课表确实发生了变化。
变化之后如右图所示,SC的插入并没有成功,打印了错误提示信息“There is Overlap”,课表中没有SC,冲突比例也没上升。芜湖
实验好难

4 实验过程中遇到的困难与解决途径

遇到的难点解决途径
eclipse提示我的类不可见,但是是public的,怎么修改都不行。最后发现是eclipse有bug,有时会会出现延迟很严重的情况,重启就好了。
对于泛型接口的继承不熟练最后没按照实验指导手册里的框架来写,将非周期性的子类改成了有周期性的子类书写,同时删除了一些报错的继承。
正则表达式的matches总是无法完成功能我一开始把字母和数字都用.来表示,后来发现字母应该用字符集来完成(比如[a-zA-Z])数字的格式是\d{i}(其中i表示数字位数)。同时,用replace将全角空格转换成半角空格(实验给出的测试用例中含有全角空格),终于匹配成功。
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。
### 回答1: RT-LAB软件是一个实时仿真平台,用于开发和测试各种电力系统和控制系统。RT-LAB软件培训旨在帮助个人和团队掌握使用该平台进行仿真和实时测试的技能。 RT-LAB软件培训涵盖了从基础知识到高级技术的全面内容。首先,培训将介绍RT-LAB软件的基本原理和功能,包括其架构、界面和主要工具。参与者将了解如何在软件中创建模型、配置仿真参数和观察仿真结果。 在培训的进一步阶段,参与者将深入学习RT-LAB软件的高级功能,如实时系统建模和控制算法设计。培训还将介绍如何使用RT-LAB软件进行硬件在环仿真,将虚拟模型与实际硬件进行连接和测试。 培训期间,参与者将有机会通过实际案例和实践项目来应用所学知识。他们将学习如何使用RT-LAB软件解决电力系统和控制系统的实际问题,并进一步优化系统性能。 RT-LAB软件培训还提供了与专业导师和其他参与者进行交流和讨论的机会。参与者可以分享经验、学习最佳实践,并获取来自行业专家的指导。 通过参加RT-LAB软件培训,个人和团队可以充分利用该软件平台的优势,提高仿真和测试的效率和准确性。这将有助于加快产品开发和测试周期,并为电力系统和控制系统的设计和优化提供更好的支持。 ### 回答2: RT-LAB 是一种实时仿真软件平台,广泛应用于电力系统、机械系统、汽车系统和航空航天等领域的研究和开发中。对于那些需要进行实时仿真和控制系统开发的工程师和科研人员来说,接受RT-LAB软件培训是非常有益和必要的。 RT-LAB软件培训可以帮助学员掌握RT-LAB软件的基本原理和使用方法。培训内容通常包括软件架构、建模和仿真技术、实时控制算法的设计和实现以及硬件接口和数据采集等方面的知识。学员将通过理论讲解和实际操作来学习和运用软件的各种功能和工具。 参加RT-LAB软件培训的好处有很多。首先,培训可以帮助学员快速上手并熟练使用RT-LAB软件,提升工作效率。其次,培训可以帮助学员深入了解软件的各项功能和应用场景,从而更好地应用于实际工程项目中。另外,培训还可以提供实时仿真和控制系统设计的相关知识和技巧,为学员在相关领域的研究和开发中提供支持和指导。此外,培训还可以帮助学员建立良好的团队合作和沟通能力,与其他专业人员进行有效的合作和交流。 总之,RT-LAB软件培训对于想要在实时仿真和控制系统开发领域有所建树的工程师和科研人员来说是非常重要的。通过培训,学员可以快速掌握软件的使用方法,提升工作效率并应用于实际工程项目中。同时,培训还可以提供相关知识和技巧,帮助学员在研究和开发中取得更好的成果。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值