关于参加“南京大学-vivo”Hackathon2019暨第十五届南京大学软件学院创新杯软件设计大赛的总结

比赛介绍:
http://www.sohu.com/a/309875770_796898

题目如下:
注:请首先补充sonar-project.properties配置文件中的信息,
将sonar.projectKey设置为队长的姓名拼音(如ZhangSan),
将sonar.projectName设置为队长在慕测网站注册的邮箱(如[email protected]

项目简介:

某公司有4类员工:管理人员、文员、程序员,会计,两个部门:程序部(Programmer)、文员部(Editor)和会计部(Accountant),补充Worker,Manager,Programmer、Editor和Accountant5个类。要求:

  • 每种员工都有姓名,年龄,薪水,部门4个属性
  • 每个员工都可以展示自己的基本属性,如程序员的语言属性(language)
  • 语言属性包括java和C
  • 管理人员分属程序部、文员部和会计部
  • 管理人员可以查看当前部门某员工的属性,不能跨部门查看
  • 管理人员可以添加本部门员工到自己的队伍中(不做互斥处理,不需查重)
  • 管理人员可以打印当前队伍中员工的姓名清单
  • 程序员有三种类型:开发(Develop),测试(Test),UI设计(UI),每个类型的奖金结算方式不同,开发人员每月奖金为基本工资的20%,加班一次补贴100,加班补贴上限500;测试人员每月奖金为基本工资的15%,加班一次补贴150,上限1000;UI设计人员每月奖金为基本工资的25%,加班一次补贴50,上限300。(保留2位小数)
  • 程序员需要实现帮助隐藏用户信息的功能
  • 文员需要实现文本对齐、标题排序、热词搜索、相似度对比的功能
  • 会计需要实现数字转换,校验密码的功能

初始类:

Accountant.java

public class Accountant extends Worker {
	public String password;

	public Accountant() {

	}
	
	//初始化Accountant
	public Accountant(String name, int age, int salary, String password) {

	}
	
    /**
     * 数字转换
     * 随着公司业务的开展,国际性业务也有相应的拓宽,
     * 会计们需要一个自动将数字转换为英文显示的功能。
     * 编辑们希望有一种简约的方法能将数字直接转化为数字的英文显示。
     * 
     * 给定一个非负整数型输入,将数字转化成对应的英文显示,省略介词and
     * 正常输入为非负整数,且输入小于2^31-1;
     * 如果有非法输入(字母,负数,范围溢出等),返回illegal
     * 
     * 示例:
     * 
     * number: 2132866842
     * return: "Two Billion one Hundred Thirty Two Million Eight Hundred Sixty Six Thousand Eight Hundred Forty Two"
     *
     * number:-1
     * return:"illegal"
     * @param number
     */
    public  String numberToWords (String number){
		return password;

    }
    
    /**
     * 检验密码
     * 由于会计身份的特殊性,对会计的密码安全有较高的要求,
     * 会计的密码需要由8-20位字符组成;
     * 至少包含一个小写字母,一个大写字母和一个数字,不允许出现特殊字符;
     * 同一字符不能连续出现三次 (比如 "...ccc..." 是不允许的, 但是 "...cc...c..." 可以)。
     * 
     * 如果密码符合要求,则返回0;
     * 如果密码不符合要求,则返回将该密码修改满足要求所需要的最小操作数n,插入、删除、修改均算一次操作。
     *
     * 示例:
     * 
     * password: HelloWorld6
     * return: 0
     *
     * password: HelloWorld
     * return: 1
     * 
     * @param password
     */
    public  int checkPassword(){
		return 0;

    }
}

Editor.java

import java.util.ArrayList;


public class Editor extends Worker {

	public Editor() {

	}
	
	//初始化Editor
	public Editor(String name, int age, int salary) {

	}
		
	/**
     * 文本对齐
     *
     * 根据统计经验,用户在手机上阅读英文新闻的时候,
     * 一行最多显示32个字节(1个中文占2个字节)时最适合用户阅读。
     * 给定一段字符串,重新排版,使得每行恰好有32个字节,并输出至控制台
     * 首行缩进4个字节,其余行数左对齐,每个短句不超过32个字节,
     * 每行最后一个有效字符必须为标点符号
     *
     * 示例:
     * 
     * String:给定一段字符串,重新排版,使得每行恰好有32个字符,并输出至控制台首行缩进,其余行数左对齐,每个短句不超过32个字符。
     * 
     * 控制台输出:    
     *     给定一段字符串,重新排版,  
     * 使得每行恰好有32个字符,
     * 并输出至控制台首行缩进,         
     * 其余行数左对齐,
     * 每个短句不超过32个字符。
     * 
     */
    public void  textExtraction(String data){

    }
    

    /**
     * 标题排序
     * 
     * 将给定的新闻标题按照拼音首字母进行排序,
     * 首字母相同则按第二个字母,如果首字母相同,则首字拼音没有后续的首字排在前面,如  鹅(e)与二(er),
     *            以鹅为开头的新闻排在以二为开头的新闻前。
     * 如果新闻标题第一个字的拼音完全相同,则按照后续单词进行排序。如 新闻1为 第一次...  新闻2为 第二次...,
     *            则新闻2应该排在新闻1之前。
     * 示例:
     *            
     * newsList:我是谁;谁是我;我是我
     * 
     * return:谁是我;我是谁;我是我;
     *
     * @param newsList
     */
    public ArrayList<String> newsSort(ArrayList<String> newsList){
		return newsList;

    }


    /**
     * 热词搜索
     * 
     * 根据给定的新闻内容,找到文中出现频次最高的一个词语,词语长度最少为2(即4个字节),最多为10(即20个字节),且词语中不包含标点符号,可以出现英文,同频词语选择在文中更早出现的词语。
     * 
     * 示例:
     * 
     * String: 今天的中国,呈现给世界的不仅有波澜壮阔的改革发展图景,更有一以贯之的平安祥和稳定。这平安祥和稳定的背后,凝聚着中国治国理政的卓越智慧,也凝结着中国公安民警的辛勤奉献。
     * 
     * return:中国
     * 
     * @param newsContent
     */
    public String findHotWords(String newsContent){
		return newsContent;

    }
    
    /**
    *
    *相似度对比
    *
    * 为了检测新闻标题之间的相似度,公司需要一个评估字符串相似度的算法。
    * 即一个新闻标题A修改到新闻标题B需要几步操作,我们将最少需要的次数定义为 最少操作数
    * 操作包括三种: 替换:一个字符替换成为另一个字符,
    *              插入:在某位置插入一个字符,
    *              删除:删除某位置的字符
    *  示例:
    *      中国队是冠军  -> 我们是冠军
    *      最少需要三步来完成。第一步删除第一个字符  "中"
    *                       第二步替换第二个字符  "国"->"我"
    *                       第三步替换第三个字符  "队"->"们"
    *      因此 最少的操作步数就是 3
    *
    * 定义相似度= 1 - 最少操作次数/较长字符串的长度
    * 如在上例中:相似度为  (1 - 3/6) * 100= 50.00(结果保留2位小数,四舍五入,范围在0.00-100.00之间)
    *
    *
    * @param title1
    * @param title2
    */
   public double minDistance(String title1, String title2){
	return 0;

   }
}

Manager.java

import java.util.ArrayList;
import java.util.List;

public class Manager extends Worker {

	private List<Worker> worker;

	public Manager() {

	}
	//Manager类的初始化
	public Manager(String name, int age, int salary, String department) {

	}

	// 管理人员可以查询本部门员工的基本信息,跨部门查询提示权限不足,提示“Access Denied!”
	public String inquire(Worker e) {
		return null;
	}

	// 管理人员给自己的队伍添加工作人员,同一部门的工作人员可以添加,并返回true,不同部门的工作人员无法添加,返回false
	public boolean lead(Worker e) {
		return false;
	}

	// 打印自己队伍的人员姓名,没有打印“Empty”
	public String print() {
		return null;
	}

}

Programmer.java


public class Programmer extends Worker {
	public String language;
	public String type;

	public Programmer() {
	}

	// Programmer类的初始化
	public Programmer(String name, int age, int salary, String language,
			String type) {
	}

	public String getLanguage() {
		return language;
	}

	public void setLanguage(String language) {
		this.language = language;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	// 按照规则计算当月的奖金
	public String getBonus(int overtime) {
		return null;
	}

	// 展示基本信息
	public String show() {
		return null;
	}


	/**
	 * 信息隐藏
	 * 
	 * 为了保护用户的隐私,系统需要将用户号码和邮箱隐藏起来。 对输入的邮箱或电话号码进行加密。 commnet
	 * 可能是一个邮箱地址,也可能是一个电话号码。
	 *
	 * 1. 电子邮箱 邮箱格式为 str1@str2
	 * 电子邮箱的名称str1是一个长度大于2.并且仅仅包含大小写字母和数字的字符串,名称str1后紧接符号@
	 * 最后是邮箱所在的服务器str2,str2中可能包含多个. 如qq.com smail.nju.edu.cn等 邮箱地址是有效的,一个正确的示例为:
	 * [email protected] 为了隐藏电子邮箱,所有的str1和str2中的字母必须被转换成小写的,
	 * 并且名称str1的第一个字和最后一个字的中间的所有字由 5 个 '*' 代替。 如果邮箱中含有非法字符或格式不正确,则返回illegal
	 * 
	 * 示例:
	 * 
	 * comment: "[email protected]"
	 * 
	 * return: "q*****[email protected]"
	 *
	 * 2. 电话号码 电话号码是一串包括数字 0-9,以及 {'+', '-', '(', ')', ' '} 这几个字符的字符串。
	 * 你可以假设电话号码包含 10 到 13 个数字。 电话号码的最后 10 个数字组成本地号码,在这之前的数字组成国际号码。
	 * 国际号码是可选的。我们只暴露最后 4 个数字并隐藏所有其他数字。 本地号码有格式,并且如 "***-***-1111" 这样显示,
	 * 为了隐藏有国际号码的电话号码,像 "+111 111 111 1111",我们以 "+***-***-***-1111"
	 * 的格式来显示。在本地号码前面的 '+' 号 和第一个 '-' 号仅当电话号码中包含国际号码时存在。 例如,一个 12 位的电话号码应当以
	 * "+**-" 开头进行显示。 注意:像 "(",")"," " 这样的不相干的字符以及不符合上述格式的额外的减号或者加号都应当被删除。 
	 * 示例1:
	 * 
	 * comment: "1(234)567-890" 
	 * 
	 * return: "***-***-7890" 
	 * 
	 * 示例2: 
	 * 
	 * comment: "86-(10)12345678" 
	 * 
	 * return: "+**-***-***-5678"
	 * 
	 * @param comment
	 */
	public String hideUserinfo(String comment) {
		return comment;
	}

}

Worker.java


public class Worker {
	protected String name;
	protected int age;
	protected int salary;
	protected String department;

	public Worker() {

	}
	//要求进行工作人员初始化,当年龄小于18或工资低于2000时,进行异常提示,提示内容参阅测试用例
	public Worker(String name, int age, int salary, String department) {
		
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public int getSalary() {
		return salary;
	}

	public void setSalary(int salary) {
		this.salary = salary;
	}

	public String getDepartment() {
		return department;
	}

	public void setDepartment(String department) {
		this.department = department;
	}
	
	//展示员工的基本信息
	public String show() {
		return null;
	}
}

测试类:

AccountantTest.java

import static org.junit.Assert.*;

import org.junit.Test;


public class AccountantTest {

	@Test
	public void test1() {
		Accountant a = new Accountant("p",21,8000,"IamOK");
		assertEquals(3,a.checkPassword());
	}
	
	@Test
	public void test2() {
		Accountant a = new Accountant("p",21,8000,"Helloworld6");
		assertEquals(0,a.checkPassword());
	}

	@Test
	public void test3() {
		Accountant a = new Accountant("p",21,8000,"IamOK");
		assertEquals("One",a.numberToWords("1"));
	}
	
	@Test
	public void test4() {
		Accountant a = new Accountant("p",21,8000,"IamOK");
		assertEquals("illegal",a.numberToWords("-1"));
	}
}

EditorTest.java

import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.junit.After;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class EditorTest {
	
	String sep;
	PrintStream console = null;
	ByteArrayOutputStream out = null;

	@Before
	public void setUp() throws Exception {
		out = new ByteArrayOutputStream();
		console = System.out;
		System.setOut(new PrintStream(out));
		sep = System.getProperty("line.separator");
	}

	@After
	public void tearDown() throws Exception {
		out.close();
		System.setOut(console);
	}
	
	@Test(timeout=4000)
	public void test1() {
		Editor s = new Editor("s",21,8000);
		assertEquals("My name is s ; age : 21 ; salary : 8000 ; department : Editor.",s.show());
	}
	
	@Test(timeout=4000)
	public void test2() {
		Editor e = new Editor("e",21,8000);
		String newsContent = "今天的中国,呈现给世界的不仅有波澜壮阔的改革发展图景,更有一以贯之的平安祥和稳定。这平安祥和稳定的背后,凝聚着中国治国理政的卓越智慧,也凝结着中国公安民警的辛勤奉献。";
		assertEquals("中国",e.findHotWords(newsContent));
	}
	
	@Test(timeout=4000)
	public void test3() {
		Editor e = new Editor("e",21,18000);
		String title1 = "中国队是冠军";
		String title2 = "我们是冠军";
		assertEquals(50.00,e.minDistance(title1, title2),0.0000001);
	}
	
	@Test(timeout=4000)
	public void test4() {
		Editor e = new Editor("e",21,18000);
		ArrayList<String> newsList = new ArrayList<String>();
		newsList.add("我是谁");
		newsList.add("谁是我");
		newsList.add("我是我");
		ArrayList<String> finalList = new ArrayList<String>();
		List list = Arrays.asList("谁是我","我是谁","我是我");
		finalList.addAll(list);
		assertEquals(finalList,e.newsSort(newsList));
	}
	
	@Test(timeout=4000)
	public void test5() {
		Editor e = new Editor("e",21,18000);
		String data = "给定一段字符串,重新排版,使得每行恰好有32个字符,并输出至控制台首行缩进,其余行数左对齐,每个短句不超过32个字符。";
		e.textExtraction(data);
		String ans = out.toString();
		assertEquals("    给定一段字符串,重新排版," + sep + "使得每行恰好有32个字符," + sep + "并输出至控制台首行缩进," + sep + "其余行数左对齐," + sep + "每个短句不超过32个字符。" + sep, ans);
	}
}

ManagerTest.java

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class ManagerTest {
	
	@Rule
	public ExpectedException thrown= ExpectedException.none();
	
	@Test(timeout=4000)
	public void test1() {
		thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("age must be greater than 18 and salary must be greater than 2000.");
		Manager m = new Manager("a",1,1,"Programmer");
	}
	
	@Test(timeout=4000)
	public void test2() {
		Manager m = new Manager("a",19,10000,"Programmer");
		assertEquals("My name is a ; age : 19 ; salary : 10000 ; department : Programmer.",m.show());
	}
	
	@Test(timeout=4000)
	public void test3() {
		Manager m = new Manager("a",19,10000,"Programmer");
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("My name is p ; age : 21 ; language : Java ; salary : 8000.",m.inquire(p));
	}
	
	@Test(timeout=4000)
	public void test4() {
		Manager m = new Manager("a",19,10000,"Editor");
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Access denied!");
		m.inquire(p);
	}
	
	@Test(timeout=4000)
	public void test5() {
		Manager m = new Manager("a",19,10000,"Editor");
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertFalse(m.lead(p));
	}
	
	@Test(timeout=4000)
	public void test6() {
		Manager m = new Manager("a",19,10000,"Programmer");
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertTrue(m.lead(p));
	}
	
	@Test(timeout=4000)
	public void test7() {
		Manager m = new Manager("a",19,10000,"Programmer");
		assertEquals("Empty",m.print());
	}
	
	@Test(timeout=4000)
	public void test8() {
		Manager m = new Manager("a",19,10000,"Programmer");
		Programmer p1 = new Programmer("p1",21,8000,"Java","UI");
		Programmer p2 = new Programmer("p2",34,9000,"Java","Test");
		m.lead(p1);
		m.lead(p2);
		assertEquals("Statement for a\n - p1\n - p2",m.print());
	}
	
}

ProgrammerTest.java

import static org.junit.Assert.*;

import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;

public class ProgrammerTest {
	
	@Rule
	public ExpectedException thrown= ExpectedException.none();

	@Test(timeout=4000)
	public void test1() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("My name is p ; age : 21 ; language : Java ; salary : 8000.",p.show());
	}
	
	@Test(timeout=4000)
	public void test2() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("2,250.00",p.getBonus(5));
	}

	@Test(timeout=4000)
	public void test3() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		thrown.expect(IllegalArgumentException.class);
        thrown.expectMessage("Overtime illegal!");
		p.getBonus(-1);
	}
	
	@Test(timeout=4000)
	public void test4() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("q*****[email protected]",p.hideUserinfo("[email protected]"));
	}
	
	@Test(timeout=4000)
	public void test5() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("***-***-7890",p.hideUserinfo("1(234)567-890"));
	}
	
	@Test(timeout=4000)
	public void test6() {
		Programmer p = new Programmer("p",21,8000,"Java","UI");
		assertEquals("+**-***-***-5678",p.hideUserinfo("86-(10)12345678"));
	}
}

本来我都是还在考研的奋斗旅途中的,结果被几个实验室的好朋友拉了过来组队参加今天的这场比赛。我们几个自己心里还是觉得最后的成绩不算太理想,56组测试用例只过了35组,我们几个都是奋战到了六点比赛结束的时候,感觉正常发挥的话我们合力应该可以过45组左右的测试用例的。
最大的原因还是我们前期准备工作做得不足吧,前几天的训练赛我们几个都没有打,导致今天我们四个的分工配合、时间把握等环节明显做得不好,对慕测平台上面代码提交、本地环境配置(SonarQube)、出错显示等流程也不熟悉,最后也出现了本不应该出现的失误。我们大概是到4点多才开始提交成功,之前都是过的原始的那五组数据。这么晚的提交成功也大大影响了我们对于整个项目方向上的把握和时间的分配,前期我们几乎看不到自己哪里错了,哪里对了。所以直到最后一刻我们还在奋战,其实感觉我们可以做得更好的。
关于南大举办的这次比赛,我的感觉是自己第一次参加这种类型的比赛。因为以前不是参加ACM性质的刷题比赛就是参加服创、软件杯这种的项目比赛,从没参加过这种团队性质的,有点像刷题看测试数据通过组数,又是给你一个项目似的应用背景,还要求代码规范(评分会有一部分是看代码规范来打分的)的比赛。所以除了有些不适应以外,更多的是一种新颖性和创新性吧。我们这些参赛者加了一个比赛群,里面同学们讨论很激烈,也都很有见地和想法,老师们答疑也非常及时与热心。通过这些我学到了很多东西同时发现自己也还有很多不足需要改进。最后还是为南大的这次比赛的良好组织点赞,希望日后有更多的机会去参加这类有意义的比赛来不断提升自己的能力和综合素质!这次算是自己考研旅途中的小插曲吧,收拾好心情就要继续踏上征程了!

以下是我们比赛中的一些图片关于参加“南京大学-vivo”Hackathon2019暨第十五届南京大学软件学院创新杯软件设计大赛的总结_第1张图片

你可能感兴趣的:(心得体会)