Реализация функции входа не так сложна, как вы думаете (3)

Java
Реализация функции входа не так сложна, как вы думаете (3)

введение

В серии статей о регистрации представлены некоторые распространенные реализации операций регистрации, в том числе签到,补签,签到任务И т. д. Основными стеками технологий являются redis и mysql.В этой статье в основном обобщены некоторые проблемы, возникшие после запуска предыдущей функции регистрации, и некоторые итерации кода, вызванные изменением требований.

Ссылки на предыдущие статьиФункция входа для достижения Реализация функции входа 2

Требования и ошибки

и第一版Требования для сравнения:

  1. Раньше апельсиновый сок при непрерывном входе запускался только при входе в систему, но теперь его также необходимо запускать при повторном входе.
  2. Предыдущий цикл входа был основан на месяцах, и не было ограничений на непрерывный вход. текущий месяц.
  3. Ранее не считалось, что количество дней регистрации после повторной подписи напрямую больше, чем триггерная точка количества последовательных дней регистрации, в результате чего вознаграждение за непрерывную регистрацию не активируется.
  4. Поскольку операция непрерывной регистрации монтируется асинхронно, клиент, вызывающий общий интерфейс апельсинового сока после регистрации или повторного подписания, не будет обновляться вовремя.

карта разума

Интеллект-карта после корректировки требований выглядит следующим образом:

Логическая сортировка и реализация

Ответьте на четыре вопроса выше, чтобы разобраться в логике кода перед корректировкой кода.

注:之前文章批注过的代码,此篇会用伪代码代替,可以翻看之前的文章查找以前的具体实现代码

Проверял в отделе апельсинового сока подряд раньше

//签到操作记录位图后传入用户id以及连续签到天数记录橙汁
public Boolean doSaveUserIntegral(int userId, int signContinuousCount) {
    ListUserIntegralLog userIntegralLogList = new LinkedList();
    //先记录本次签到橙汁2ML放入userIntegralLogList集合中等待后续写入
    .....
    //根据签到连续天数算出当前签到是否符合连续签到,查出奖励橙汁多少并放入userIntegralLogList集合中等待后续写入
    .....
    //更改个人总橙汁并批量写入橙汁记录
}

План трансформации

Сначала обратите внимание на предыдущий код, нормальные и непрерывные проверки складываются вместе, и нет никакой гарантии, что награда за непрерывную регистрацию в текущем месяце уникальна, поскольку требуется оценка непрерывной регистрации. для дополнительной регистрации необходимо снять часть решения о непрерывной регистрации.

Извлеките решение о непрерывной регистрации и аккумулируйте общую часть апельсинового сока.

    // 入参部分,userIntegralLogList 为橙汁记录表的集合,count 为总橙汁增减量,userId 用户id,signContinuousCount 连续签到天数
    public void doSaveContinuousIntegral(List<UserIntegralLog> userIntegralLogList, int count, int userId, int signContinuousCount) {
        //首先得到这个月的最大天数
        int monthLength = LocalDate.now().lengthOfMonth();
        //初始化最大满足连续签到次数
        int times = 0;
        //定义一个数组,存放连续天数满足条件,这个如果需要灵活配置也可放入缓存中.
        //我们的时间节点是5天,7天,15天,满月.因为满月无法确定天数所以写做32特殊值
        String[] continuousDays = {"5", "7", "15", "32"};
        //如果是满月的情况就会有4次命中连续签到,分别为5,7,15,32
        //连续签到大于15天的话应该是3次命中,5,7,15
        //后面依次类推....
        if (signContinuousCount == monthLength) times = 4;
        else if (signContinuousCount >= 15) times = 3;
        else if (signContinuousCount >= 7) times = 2;
        else if (signContinuousCount >= 5) times = 1;
        else return;
        //连续签到处理,获取缓存配置连续签到奖励
        Map<String, String> configurationHashMap = cacheClient.hgetAll("userSign:configuration");
        //取出库中连续签到的签到记录类型,周期是一个月.这样就可以查到他连续签到这个月触发了几次.
        String startTime = DateUtil.getThisMonthFirstDay().toString();
        String endTime = DateUtil.getThisMonthLastDay().toString();
        int timesInDb = userIntegralLogService.selectSignByTime(userId, startTime, endTime);
        //定义循环,次数为他连续签到次数最大命中次数
        for (int i = 0; i < times; i++) {
            //当库中存在的条数不为0,则需要-1并跳过这次循环
            //如这个月签到连续次数为7,之前签到满了5天给了奖励,这里timesInDb查出为1,然后我们不希望出现重复的奖励,timesInDb-1且跳过这次循环,只记录满7天的这一次奖励
            //注:这样设计是因为补签可能为中间的断层,如签到了1,2,3,4,6,7,8,这样如果补签第5天的时候,就会给用户满5天和满7天的奖励,这样写就可以兼容补签和普通签到的逻辑回路
            if (timesInDb!= 0) {
                timesInDb--;
                continue;
            }
            //后面就是正常的构造橙汁记录表,加入集合中,并叠加count总橙汁
            String configuration = configurationHashMap.get(continuousDays[i]);
            if (null != configuration) {
                JSONObject item = JSONObject.parseObject(configuration);
                int giveIntegral = item.getInteger("integral");
                if (giveIntegral != 0) {
                    userIntegralLogList.add(UserIntegralLog.builder()
                            .createTime(LocalDateTime.now())
                            .bak(String.format(BusinessConstant.Integral.CONTINUOUS_SIGN_COPY, Integer.parseInt(continuousDays[i])))
                            .integral(giveIntegral)
                            .integralType(BusinessConstant.Integral.SIGN_TYPE_CONTINUOUS)
                            .userId(userId)
                            .build());
                    count += giveIntegral;
                }
            }
        }
    }

раздел selectSignByTime Dao

    @Select("SELECT count(1) from t_user_integral_log where integral_type=2 and user_id=#{userId} and STR_TO_DATE( create_time, '%Y-%m-%d' ) BETWEEN #{startTime} AND #{endTime}")
    int selectSignByTime(@Param("userId") int userId, @Param("startTime") String startTime, @Param("endTime") String endTime);

Изменить исходный метод входа

Чтобы решить проблему асинхронного запроса общего апельсинового сока, этот метод был изменен с асинхронного на синхронный.

    public Boolean doSaveUserIntegral(int userId, int signContinuousCount) {
        int count = 0;
        List<UserIntegralLog> userIntegralLogList = new LinkedList<>();
        userIntegralLogList.add(UserIntegralLog.builder()
                .createTime(LocalDateTime.now())
                .operationTime(LocalDate.now())
                .bak(BusinessConstant.Integral.NORMAL_SIGN_COPY)
                .integral(BusinessConstant.Integral.SIGN_TYPE_NORMAL_INTEGRAL)
                .integralType(BusinessConstant.Integral.SIGN_TYPE_NORMAL)
                .userId(userId)
                .build());
        count += BusinessConstant.Integral.SIGN_TYPE_NORMAL_INTEGRAL;
        //这就是我们新拆解的方法,抽离连续签到判断以及累加总橙汁部分
        doSaveContinuousIntegral(userIntegralLogList, count, userId, signContinuousCount);
        // 累加总橙汁和批量写入橙汁记录
        return updateUserIntegralCount(userId, count) && userIntegralLogService.saveBatch(userIntegralLogList);
    }

Добавлен код обработки для дополнительной части подписи

    public Boolean doSaveUserRetroactiveIntegral(int userId, int signContinuousCount) {
        List<UserIntegralLog> userIntegralLogList = new LinkedList<>();
        int count = 0;
        doSaveContinuousIntegral(userIntegralLogList, count, userId, signContinuousCount);
        return updateUserIntegralCount(userId, count) && userIntegralLogService.saveBatch(userIntegralLogList);
    }

И вызовите этот метод в конце предыдущего метода регистрации, чтобы завершить логику регистрации, запускающей непрерывные вознаграждения за вход.

постскриптум

Давайте рассмотрим предыдущие потребности и проблемы.

  1. Проблемы 1 и 2 решаются путем извлечения метода doSaveContinuousIntegral и добавления оценки количества раз хранения в каждой оценке.
  2. Вопрос 3. Изменив диапазон соответствия с == на >=, вычислите общее количество последовательных чекинов, которые необходимо записать, а затем вычтите количество раз, записанных в библиотеке, чтобы непрерывный чекин стал оценка дальности вместо предыдущего точного значения.
  3. Вопрос 4. Так как в нем не так много вычислений, асинхронность убрана.Эта проблема не возникнет, если используется синхронный метод.

Благодаря этому исправлению я понимаю, что написание кода - это процесс непрерывного совершенствования. Его нельзя усовершенствовать за одну разработку. Необходимо постоянно думать о проблемах из практики и стараться улучшать качество кода навыками, чтобы продолжать улучшить. Наконец祝大家的需求都不会大改.Ха-ха