|
|
@@ -9,6 +9,7 @@ import com.fs.live.domain.*;
|
|
|
import com.fs.live.mapper.LiveQuestionBankMapper;
|
|
|
import com.fs.live.param.LiveCompletionCouponAnswerParam;
|
|
|
import com.fs.live.service.*;
|
|
|
+import com.fs.live.vo.LiveCompletionCouponConfigVO;
|
|
|
import com.fs.live.vo.LiveCompletionCouponNotifyResult;
|
|
|
import com.fs.live.vo.LiveCompletionCouponStatusVO;
|
|
|
import com.fs.live.vo.LiveCompletionQuestionVO;
|
|
|
@@ -64,9 +65,27 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
private RedisCache redisCache;
|
|
|
|
|
|
@Override
|
|
|
- public LiveCompletionCouponNotifyResult checkAndNotifyCompletionCoupon(Long liveId, Long userId, Long watchDuration) {
|
|
|
+ public LiveCompletionCouponConfigVO parseCompletionCouponConfig(Live live) {
|
|
|
+ LiveCompletionCouponConfigVO vo = new LiveCompletionCouponConfigVO();
|
|
|
+ CompletionCouponConfig config = live == null ? disabledConfig() : getCompletionCouponConfig(live);
|
|
|
+ vo.setEnabled(config.isEnabled());
|
|
|
+ vo.setCompletionRate(config.getCompletionRate());
|
|
|
+ vo.setCouponId(config.getCouponId());
|
|
|
+ vo.setFinishQuestionIds(config.getFinishQuestionIds());
|
|
|
+ if (config.isEnabled() && live != null && live.getDuration() != null && live.getDuration() > 0) {
|
|
|
+ vo.setRequiredDurationSeconds(calculateRequiredDuration(live.getDuration(), config.getCompletionRate()));
|
|
|
+ } else {
|
|
|
+ vo.setRequiredDurationSeconds(-1L);
|
|
|
+ }
|
|
|
+ return vo;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LiveCompletionCouponNotifyResult prepareCompletionCouponNotify(Long liveId, Long userId, Long watchDuration) {
|
|
|
LiveCompletionCouponNotifyResult result = new LiveCompletionCouponNotifyResult();
|
|
|
result.setShouldNotify(false);
|
|
|
+ result.setEligible(false);
|
|
|
+ result.setQuestions(Collections.emptyList());
|
|
|
|
|
|
try {
|
|
|
CompletionCouponConfig config = resolveConfig(liveId);
|
|
|
@@ -77,6 +96,7 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
if (!isWatchRateEligible(liveId, userId, watchDuration, config)) {
|
|
|
return result;
|
|
|
}
|
|
|
+ result.setEligible(true);
|
|
|
|
|
|
if (hasIssuedToday(liveId, userId, config.getCouponId())) {
|
|
|
return result;
|
|
|
@@ -84,19 +104,33 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
|
|
|
List<LiveCompletionQuestionVO> questions = loadQuestions(config.getFinishQuestionIds());
|
|
|
if (questions.isEmpty()) {
|
|
|
- log.warn("完课优惠券已开启但未配置今日问题, liveId={}", liveId);
|
|
|
+ log.debug("完课优惠券未配置直播课题, 跳过弹窗, liveId={}", liveId);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
if (hasNotifiedToday(liveId, userId)) {
|
|
|
+ result.setQuestions(questions);
|
|
|
return result;
|
|
|
}
|
|
|
|
|
|
- markNotifiedToday(liveId, userId);
|
|
|
result.setShouldNotify(true);
|
|
|
result.setQuestions(questions);
|
|
|
} catch (Exception e) {
|
|
|
- log.error("检查完课优惠券弹窗失败, liveId={}, userId={}", liveId, userId, e);
|
|
|
+ log.error("预检查完课优惠券弹窗失败, liveId={}, userId={}", liveId, userId, e);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void markCompletionCouponNotified(Long liveId, Long userId) {
|
|
|
+ markNotifiedToday(liveId, userId);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public LiveCompletionCouponNotifyResult checkAndNotifyCompletionCoupon(Long liveId, Long userId, Long watchDuration) {
|
|
|
+ LiveCompletionCouponNotifyResult result = prepareCompletionCouponNotify(liveId, userId, watchDuration);
|
|
|
+ if (result.isShouldNotify()) {
|
|
|
+ markCompletionCouponNotified(liveId, userId);
|
|
|
}
|
|
|
return result;
|
|
|
}
|
|
|
@@ -424,6 +458,11 @@ public class LiveCompletionCouponServiceImpl implements ILiveCompletionCouponSer
|
|
|
return NOTIFY_REDIS_KEY_PREFIX + liveId + ":" + userId + ":" + today;
|
|
|
}
|
|
|
|
|
|
+ private long calculateRequiredDuration(long videoDurationSeconds, Integer completionRate) {
|
|
|
+ int rate = completionRate == null || completionRate <= 0 ? 90 : completionRate;
|
|
|
+ return (long) Math.ceil(videoDurationSeconds * rate / 100.0);
|
|
|
+ }
|
|
|
+
|
|
|
private static class CompletionCouponConfig {
|
|
|
private boolean enabled;
|
|
|
private Integer completionRate;
|