团队Github实战训练

时间:2021-11-11 07:28:02

班级:软件工程1916|W

作业:团队Github实战训练

团队名称:SkyReach

Github地址:Github地址

贡献比例表

队员学号 队员姓名 此次活动任务 贡献比例
221600106 陈鸿 资料查询,代码审查 4%
221600107 陈家豪 安排任务,撰写博客,抽奖功能编码 12%
221600110 公孙骏杰 资料查询,代码审查 4%
221600117 黄盛远 文件数据格式化输入,数据接口设计 26%
221600118 李鸿斌 抽奖算法设计,抽奖功能编码 23%
221600120 李子琪 UI设计与编码 20%
221600122 史云天 文件数据格式化输入,数据接口设计 11%

Github提交日志截图

团队Github实战训练

程序运行截图

团队Github实战训练

团队Github实战训练

团队Github实战训练

GUI

团队Github实战训练

基础功能实现

本算法具有以下模式:

  • 不过滤模式:剔除系统、助教、老师,所有参与抽奖的发言,都纳入开奖范围。

  • 普通模式:每个账号只占有一条有效抽奖信息。

  • 深度模式

    在普通模式的基础上,为了使发言更有意义,提高用户活跃度:

    • 有效发言越多,中奖几率越大

随机抽奖的算法:

LCG算法

我们的抽奖算法基于LCG算法,LCG(linear congruential generator)线性同余算法,是一个古老的产生随机数的算法。

本算法有以下优点:

  • 计算速度快:抽奖时的算法时间复杂度是一个较大的问题,在微博开奖的时候,由于抽奖人数众多,(例如王思聪的抽奖微博,转发量、评论数、点赞数均达到了两千万,总数达到了六千万,输入量十分巨大)所以常常需要花费几十分钟的时间开奖,如此的算法性能是难以忍受的。对此,我们的算法基于LCG算法,利用其速度优势,减少开奖时间。
  • 易于实现:算法易于理解,可以通过改变取余数来控制算法的空间复杂度与随机分布效果。且算法是线性的算法,和非线性的模型相比,具有较低的复杂度。
  • 易于推广:本算法改变取余参数,对空间资源和随机准确率权衡,根据不同的设备资源和计算能力调优,具有很强的灵活性,易于使用推广。

本算法基于的LCG算法由以下参数组成:

参数 m a c X
性质 模数 乘数 加数 随机数
作用 取模 移位 偏移 作为结果

LCG算法是如下的一个递推公式,每下一个随机数是当前随机数向左移动 log2 a 位,加上一个 c,最后对 m 取余,使随机数限制在 0 ~ m-1 内

团队Github实战训练

从该式可以看出,该算法由于构成简单,具有以下优点:

  • 计算速度快
  • 易于实现
  • 易于写入硬件

代码具体实现

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