一段网上找的代码突然爆了,项目出现大Bug

拟墨画扇 提交于 2020-12-26 01:16:20

点击上方蓝色字体,选择“标星公众号”

优质文章,第一时间送达

转自:51CTO

www.toutiao.com/i6790598743222649355

本人是做游戏服务器开发的,碰到一个需求,给符合某些要求的玩家发送道具奖励,奖励的数量根据离线的天数计算。

图片来自 Pexels

这个需求实现起来很简单,只需要在玩家上线的时候计算上次离线时间和当前时间间隔的天数,然后根据策划的算法,计算出道具种类与数量,发一封邮件给玩家就可以了。

计算两个时间间隔天数的函数没有现成的,自己又懒得写,就上谷歌搜了下,选了第一条结果,代码如下:

/**
     * date2比date1多的天数
     * @param date1
     * @param date2
     * @return
     */

    public static int differentDays(Date date1,Date date2)
    
{
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
       int day1= cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);
        
        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if(year1 != year2) //同一年
        {
            int timeDistance = 0 ;
            for(int i = year1 ; i < year2 ; i ++)
            {
                if(i%4==0 && i%100!=0 || i%400==0) //闰年
                {
                    timeDistance += 366;
                }
                else    //不是闰年
                {
                    timeDistance += 365;
                }
            }
            
            return timeDistance + (day2-day1) ;
        }
        else    //不同年
        {
            System.out.println("判断day2 - day1 : " + (day2-day1));
            return day2-day1;
        }
    }

代码来源:https://www.cnblogs.com/0201zcr/p/5000977.html

把代码复制到项目里,调试下,发现没问题就直接用了,毕竟谷歌结果第一名,放心。

这段代码跑了几个月一直没问题,但是到了 2020-1-1 日那天,有玩家反馈收到了几百封奖励邮件,高兴坏了,但是出于对游戏的热爱,还是通知了运营人员。

运营把 Bug 反馈到服务器这边后我开始排查,百思不得其解的是最近几天都没有更新服务器, 而前几天服务器都稳稳地,怎么突然就出 Bug 了呢?

接下来就是分析玩家数据,结合代码逻辑确定问题所在,最终根据 Bug 的表现排除了所有可能性后,发现唯一可能出问题的地方就是那个网上复制过来的计算天数差的函数。

根据调试发现,这个函数在两个日期参数是不同的年份并且第一个日期大于第二个日期的时候,会返回一个错误的结果,比如:

differentDays("2020-1-1","2019-12-25")

理论上这么调用正确的结果是 -7,但是因为函数有 Bug,调用结果是 358。

于是本来不用发奖励,因为这种特殊情况一下子发出去 358 份,严重影响了游戏某类道具的平衡性。

最后,我改用 Java8 的日期库修复了 Bug,代码如下:

publicstaticintdifferentDays(Datedate1,Datedate2{

  if(date1==null||date2==null){
    thrownewRuntimeException("日期不能为空");
  }
  LocalDatelocalDate1=date2LocalDate(date1);
  LocalDatelocalDate2=date2LocalDate(date2);
  return Generic.long2int(localDate1.until(localDate2,ChronoUnit.DAYS));
}
publicstaticLocalDatedate2LocalDate(Date date{
  Instantinstant=date.toInstant();
  ZoneIdzoneId=ZoneId.systemDefault();
  LocalDatelocalDate=instant.atZone(zoneId).toLocalDate();
  return localDate;
}

至于补救方式就是统计名单,把发出去但还没有用掉的道具回收,用掉的就当福利,然后再发公告道歉,再送些其他物品弥补。

也幸好补救的及时,要是这些道具收不回来,游戏运营的策略都要大变了,我特么肯定没好果子吃了。

所以千万别在网上复制来路不明的代码乱用,如果真的要用,必须反复测试,否则哪一天突然暴雷有你受的。

关注程序员闪充宝后台回复“666”和“111免费领取46阶段以及实战java视频资料


看完本文有收获?请转发分享给更多人

长按识别二维码关注


点在看

本文分享自微信公众号 - 程序员闪充宝(cxyscb1024)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!