班级:软件工程1916|W
作业:团队Github实战训练
团队名称:SkyReach
Github地址:Github地址
贡献比例表
队员学号 | 队员姓名 | 此次活动任务 | 贡献比例 |
---|---|---|---|
221600106 | 陈鸿 | 资料查询,代码审查 | 4% |
221600107 | 陈家豪 | 安排任务,撰写博客,抽奖功能编码 | 12% |
221600110 | 公孙骏杰 | 资料查询,代码审查 | 4% |
221600117 | 黄盛远 | 文件数据格式化输入,数据接口设计 | 26% |
221600118 | 李鸿斌 | 抽奖算法设计,抽奖功能编码 | 23% |
221600120 | 李子琪 | UI设计与编码 | 20% |
221600122 | 史云天 | 文件数据格式化输入,数据接口设计 | 11% |
Github提交日志截图
程序运行截图
GUI
基础功能实现
本算法具有以下模式:
-
不过滤模式:剔除系统、助教、老师,所有参与抽奖的发言,都纳入开奖范围。
-
普通模式:每个账号只占有一条有效抽奖信息。
-
深度模式
在普通模式的基础上,为了使发言更有意义,提高用户活跃度:
- 有效发言越多,中奖几率越大
随机抽奖的算法:
LCG算法
我们的抽奖算法基于LCG算法,LCG(linear congruential generator)线性同余算法,是一个古老的产生随机数的算法。
本算法有以下优点:
- 计算速度快:抽奖时的算法时间复杂度是一个较大的问题,在微博开奖的时候,由于抽奖人数众多,(例如王思聪的抽奖微博,转发量、评论数、点赞数均达到了两千万,总数达到了六千万,输入量十分巨大)所以常常需要花费几十分钟的时间开奖,如此的算法性能是难以忍受的。对此,我们的算法基于LCG算法,利用其速度优势,减少开奖时间。
- 易于实现:算法易于理解,可以通过改变取余数来控制算法的空间复杂度与随机分布效果。且算法是线性的算法,和非线性的模型相比,具有较低的复杂度。
- 易于推广:本算法改变取余参数,对空间资源和随机准确率权衡,根据不同的设备资源和计算能力调优,具有很强的灵活性,易于使用推广。
本算法基于的LCG算法由以下参数组成:
参数 | m | a | c | X |
---|---|---|---|---|
性质 | 模数 | 乘数 | 加数 | 随机数 |
作用 | 取模 | 移位 | 偏移 | 作为结果 |
LCG算法是如下的一个递推公式,每下一个随机数是当前随机数向左移动 log2 a 位,加上一个 c,最后对 m 取余,使随机数限制在 0 ~ m-1 内
从该式可以看出,该算法由于构成简单,具有以下优点:
- 计算速度快
- 易于实现
- 易于写入硬件
代码具体实现
public class Random {
//LCG算法的实现
public final AtomicLong seed=new AtomicLong();
public final static long C = 1;
public final static long A = 48271;
public final static long M = (1L << 31) - 1;
public Random(int seed){
this.seed.set(seed);
}
public Random(){
this.seed.set(System.nanoTime());
}
public long nextLong(){
seed.set(System.nanoTime());
return (A *seed.longValue() + C) % M;
}
public int nextInt(int number){
return new Long( (A * System.nanoTime()/100+ C) % number).intValue();
}
public int[] getLucky(int num){
Map<Integer,Integer> map=new HashMap<Integer,Integer>();
for(int i=0;i<100000;i++){
int ran=new Random().nextInt(num);
if(map.containsKey(ran)){
map.put(ran, map.get(ran)+1);
}else{
map.put(ran, 1);
}
}
int []luck = new int[num];
Iterator iter = map.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
int key = (Integer)entry.getKey();
int value = map.get(key);
luck[key]=value;
}
return luck;
}
附加功能实现
通过哈希表储存从文本读入的数据,对其进行有效发言判定,以及有效发言数量的计算,从而对用户中奖几率的改变。以下为代码实现:
public class Way {
public static Way create(){
Way way=new Way();
return way;
}
//不过滤抽奖名单
public List<String> none(List<String> qqs,int num){
HashMap<String,Integer> map=new HashMap<String,Integer>();
int luck[]=new Random().getLucky(qqs.size());
for(int i=0;i<qqs.size();i++){
map.put(qqs.get(i), luck[i]);
}
List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(map.entrySet());
Collections.sort(list,new Comparator<Map.Entry<String,Integer>>() {
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2) {
return -o1.getValue().compareTo(o2.getValue());
}
});
list=list.subList(0, num);
List<String> thenone=new ArrayList<String>();
for(Map.Entry<String,Integer> m:list){
thenone.add(m.getKey());
}
return thenone;
}
//普通过滤抽奖名单
public List<String> common(HashMap<String, List<Record>> msgs,ProcessQQLog user,int num){
msgs=clearAssit(msgs,user);
List<String> qqs=new ArrayList<>(msgs.keySet());
qqs=none(qqs,num);
return qqs;
}
//深度过滤抽奖名单
public List<String> deep(HashMap<String, List<Record>> msgs,ProcessQQLog user,int num){
msgs=clearAssit(msgs,user);
return none(msgRate(msgs,num),num);
}
//将助教及老师从开奖名单中删除
public HashMap<String, List<Record>> clearAssit(HashMap<String, List<Record>> msgs,ProcessQQLog user){
Iterator iter = msgs.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
String qq = (String)entry.getKey();
String name=user.getQQName(qq);
if(name.contains("助教")||name.contains("老师")||qq.equals("10000")||qq.equals("1000008")){
iter.remove();
msgs.remove(qq);
}
}
return msgs;
}
//对有效发言次数进行排序 有效发言次数越多中奖几率越大
public List<String> msgRate(HashMap<String, List<Record>> msgs,int num){
if(num<20) num*=2;
HashMap<String,Integer> qqN=new HashMap<String,Integer>();
Iterator iter = msgs.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry entry = (Map.Entry) iter.next();
String qq = (String)entry.getKey();
List<Record> list = (List<Record>)entry.getValue();
qqN.put(qq, list.size());
}
List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(qqN.entrySet());
Collections.sort(list,new Comparator<Map.Entry<String,Integer>>() {
public int compare(Entry<String, Integer> o1,
Entry<String, Integer> o2) {
return -o1.getValue().compareTo(o2.getValue());
}
});
list=list.subList(0, num);
List<String> themsg=new ArrayList<String>();
for(Map.Entry<String,Integer> m:list){
themsg.add(m.getKey());
}
return themsg;
}
}
鼓励有想法且有用的功能
通过哈希表储存从文本读入的数据,对其进行有效发言判定,以及有效发言数量的计算,从而对用户中奖几率的改变。
遇到的困难及解决方法
-
组员 李子琪
困难
- 有段时间没有接触GUI编写,很多功能又需要重新学习掌握;
- 由于负责界面的编写,所以有时需要等待队友提供的数据形式才能进行测试;
解决
- 通过百度再次了解掌握各种组件与监听器等;
- 提前与队友沟通决定数据传递的参数,提前先自己进行数据对接,等队友完成后再进行测试。
-
组员 李鸿斌
困难
- 各种数据结构的相互转换
解决
- 查阅相关api和搜索引擎,还有队友间相互讨论。
-
组员 黄盛远
困难
- 字符串匹配比较麻烦,甚至一些不好分辨
- 编码问题,造成结果与预计不同
解决
- 上网学习了正则表达式,通过正则表达式匹配。
- 通过浏览他人博客,学习到utf-8与utf-8-dom编码的区别,通过代码将utf-8-dom转化为utf-8
-
组员 史云天
困难
- 分离标题栏和内容时不太好分离
解决
- 最后采用正则表达式,来判断是否符合标题的格式,即日期-时间 网名 QQ号
-
组员 公孙骏杰
困难
- 问题主要集中在抽奖的机制上,既要提供一个公平公正的平台的条件下,还需要进行进一步的筛选过滤选择中奖用户
解决
- 对结果进行深度过滤
-
组员 陈鸿
困难
- 队友间的相互沟通 版本更新有的不同,和同学的沟通沟通的函数有的需要分好几个变量而队友不需要
解决
- 讨论了一会才达成一致意见。有的算法不会写查阅了相关资料才写出来。
-
组长 陈家豪
困难
- 如何搭建构建数据的组员和抽奖功能编程的组员之间的桥梁
解决
- 构建数据接口,对两方组员阐述各自功能,完成统一的数据接口
PSP表格
陈鸿
PSP2.1 | Pesonal SoftWare Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 10 | 12 |
Estimate | 估计这个任务需要多少时间 | 120 | 140 |
Development | 开发 | 220 | 230 |
Analysis | 需求分析(包括学习新技术) | 60 | 70 |
Design Spec | 生成设计文档 | 30 | 40 |
Design Review | 设计复审 | 20 | 30 |
Coding Standard | 代码规范(为目前的开发制定合适的规范) | 0 | 0 |
Design | 具体设计 | 220 | 230 |
Coding | 具体编码 | 0 | 0 |
Code Review | 代码复审 | 0 | 0 |
Test | 测试(自我测试,修改代码,提交修改) | 40 | 50 |
Reporting | 报告 | 30 | 40 |
Test Report | 测试报告 | 10 | 10 |
Size Measurement | 计算工作量 | ||
Postmortem&Process Improvement Plan | 事后总结,并提出过程改进计划 | 30 | 30 |
合计 | 790 | 855 |
李子琪
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | ||
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 10 | 20 |
• Design Spec | • 生成设计文档 | 10 | 20 |
• Design Review | • 设计复审 | 20 | 25 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | ||
• Design | • 具体设计 | 15 | 15 |
• Coding | • 具体编码 | 100 | 120 |
• Code Review | • 代码复审 | 10 | 15 |
• Test | • 测试(自我测试,修改代码,提交修改) | 20 | 40 |
Reporting | 报告 | ||
• Test Report | • 测试报告 | 10 | 15 |
• Size Measurement | • 计算工作量 | 20 | 20 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 10 | 10 |
合计 | 225 | 300 |
李鸿斌
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 180 | 190 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 30 | 40 |
• Design Spec | • 生成设计文档 | 10 | 10 |
• Design Review | • 设计复审 | 15 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 25 | 20 |
• Design | • 具体设计 | 15 | 10 |
• Coding | • 具体编码 | 30 | 35 |
• Code Review | • 代码复审 | 15 | 20 |
• Test | • 测试(自我测试,修改代码,提交修改) | 30 | 25 |
Reporting | 报告 | ||
• Test Report | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 | 30 |
合计 | 230 | 230 |
公孙骏杰
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | ||
• Estimate | • 估计这个任务需要多少时间 | 10 | 10 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 50 | 70 |
• Design Spec | • 生成设计文档 | 30 | 50 |
• Design Review | • 设计复审 | 10 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 20 | 20 |
• Design | • 具体设计 | 60 | 60 |
• Coding | • 具体编码 | 150 | 180 |
• Code Review | • 代码复审 | 30 | 30 |
• Test | • 测试(自我测试,修改代码,提交修改) | 20 | 20 |
Reporting | 报告 | ||
• Test Report | • 测试报告 | 20 | 20 |
• Size Measurement | • 计算工作量 | 10 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 40 | 40 |
合计 | 560 | 630 |
史云天
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 10 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 5 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 60 | 50 |
• Design Spec | • 生成设计文档 | 30 | 40 |
• Design Review | • 设计复审 | 20 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 40 | 30 |
• Design | • 具体设计 | 30 | 20 |
• Coding | • 具体编码 | 180 | 240 |
• Code Review | • 代码复审 | 20 | 30 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 60 |
Reporting | 报告 | ||
• Test Report | • 测试报告 | 30 | 40 |
• Size Measurement | • 计算工作量 | 10 | 5 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 25 |
合计 | 540 | 565 |
黄盛远
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) |
---|---|---|
Planning | 计划 | |
• Estimate | • 估计这个任务需要多少时间 | 180 |
Development | 开发 | |
• Analysis | • 需求分析 (包括学习新技术) | 10 |
• Design Spec | • 生成设计文档 | 10 |
• Design Review | • 设计复审 | 15 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 5 |
• Design | • 具体设计 | 15 |
• Coding | • 具体编码 | 60 |
• Code Review | • 代码复审 | 15 |
• Test | • 测试(自我测试,修改代码,提交修改) | 30 |
Reporting | 报告 | |
• Test Report | • 测试报告 | 20 |
• Size Measurement | • 计算工作量 | 10 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 20 |
合计 | 195 |
陈家豪
PSP2.1 | Personal Software Process Stages | 预估耗时(分钟) | 实际耗时(分钟) |
---|---|---|---|
Planning | 计划 | 20 | 10 |
• Estimate | • 估计这个任务需要多少时间 | 10 | 5 |
Development | 开发 | ||
• Analysis | • 需求分析 (包括学习新技术) | 60 | 30 |
• Design Spec | • 生成设计文档 | 30 | 40 |
• Design Review | • 设计复审 | 20 | 10 |
• Coding Standard | • 代码规范 (为目前的开发制定合适的规范) | 40 | 30 |
• Design | • 具体设计 | 30 | 20 |
• Coding | • 具体编码 | 180 | 200 |
• Code Review | • 代码复审 | 20 | 30 |
• Test | • 测试(自我测试,修改代码,提交修改) | 60 | 60 |
Reporting | 报告 | ||
• Test Report | • 测试报告 | 30 | 40 |
• Size Measurement | • 计算工作量 | 10 | 5 |
• Postmortem & Process Improvement Plan | • 事后总结, 并提出过程改进计划 | 30 | 25 |
合计 | 540 | 505 |
学习进度表
姓名 | 新增代码(行) | 累计代码(行) | 本周学习耗时(小时) | 累计学习耗时(小时) | 重要成长 |
---|---|---|---|---|---|
陈家豪 | 100 | 100 | 10 | 10 | 复习JAVA,学习LCG算法 |
李子琪 | 400 | 400 | 12 | 12 | 复习JAVAUI设计 |
黄盛远 | 250 | 250 | 15 | 15 | 复习JAVA,学习使用哈希表 |
史云天 | 100 | 100 | 8 | 8 | 复习JAVA,学习使用哈希表 |
李鸿斌 | 170 | 170 | 10 | 10 | 复习JAVA,学习LCG算法 |
公孙骏杰 | 50 | 50 | 7 | 7 | 复习JAVA |
陈鸿 | 50 | 50 | 7 | 7 | 复习JAVA |