给自己复盘用的tjxt笔记day12第一部分

优惠券使用

优惠券规则定义

对优惠券的下列需求:

  • 判断一个优惠券是否可用,也就是检查订单金额是否达到优惠券使用门槛

  • 按照优惠规则计算优惠金额,能够计算才能比较并找出最优方案

  • 生成优惠券规则描述,目的是在页面直观的展示各种方案,供用户选择

因此,任何一张优惠券都应该具备上述3个功能,这样就能满足后续对优惠券的计算需求了。

我们抽象一个接口来标示优惠券规则

package com.tianji.promotion.strategy.discount;import com.tianji.promotion.domain.po.Coupon;/*** <p>优惠券折扣功能接口</p>*/
public interface Discount {/*** 判断当前价格是否满足优惠券使用限制* @param totalAmount 订单总价* @param coupon 优惠券信息* @return 是否可以使用优惠券*/boolean canUse(int totalAmount, Coupon coupon);/*** 计算折扣金额* @param totalAmount 总金额* @param coupon 优惠券信息* @return 折扣金额*/int calculateDiscount(int totalAmount, Coupon coupon);/*** 根据优惠券规则返回规则描述信息* @return 规则描述信息*/String getRule(Coupon coupon);
}

规则根据优惠类型(discountType)来看就分为4种,不同优惠仅仅是其它3个字段值不同而已。

所以优惠券的规则定义四种不同实现类即可,将来我们可以根据优惠类型不同选择具体的实现类来完成功能。像这种定义使用场景可以利用策略模式来定义规则。

  • DiscountStrategy:折扣策略的工厂,可以根据DiscountType枚举来获取某个折扣策略对象

public class DiscountStrategy {private final static EnumMap<DiscountType, Discount> strategies;static {strategies = new EnumMap<>(DiscountType.class);strategies.put(DiscountType.NO_THRESHOLD, new NoThresholdDiscount());strategies.put(DiscountType.PER_PRICE_DISCOUNT, new PerPriceDiscount());strategies.put(DiscountType.RATE_DISCOUNT, new RateDiscount());strategies.put(DiscountType.PRICE_DISCOUNT, new PriceDiscount());}public static Discount getDiscount(DiscountType type) {return strategies.get(type);}
}

优惠券智能推荐

思路分析

查询用户券

// 1.查询我的所有可用优惠券List<Coupon> coupons = userCouponMapper.queryMyCoupons(UserContext.getUser());if (CollUtils.isEmpty(coupons)) {return CollUtils.emptyList();}

查询的结果必须包含Coupon中的折扣相关信息,因此这条语句是coupon表和user_coupon表的联合查询,必须手写SQL语句。 

public interface UserCouponMapper extends BaseMapper<UserCoupon> {List<Coupon> queryMyCoupons(@Param("userId") Long userId);
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.tianji.promotion.mapper.UserCouponMapper"><select id="queryMyCoupons" resultType="com.tianji.promotion.domain.po.Coupon">SELECT c.id, c.discount_type, c.`specific`, c.discount_value, c.threshold_amount,c.max_discount_amount, uc.id AS createrFROM user_coupon ucINNER JOIN coupon c ON uc.coupon_id = c.idWHERE uc.user_id = #{userId} AND uc.status = 1</select>
</mapper>

初步筛选

在初筛时,是基于所有课程计算总价,判断优惠券是否可用,这显然是不合适的

   // 2.初筛// 2.1.计算订单总价int totalAmount = orderCourses.stream().mapToInt(OrderCourseDTO::getPrice).sum();// 2.2.筛选可用券List<Coupon> availableCoupons = coupons.stream().filter(c -> DiscountStrategy.getDiscount(c.getDiscountType()).canUse(totalAmount, c)).collect(Collectors.toList());if (CollUtils.isEmpty(availableCoupons)) {return CollUtils.emptyList();}

细筛

细筛步骤有两步:

  • 首先要基于优惠券的限定范围对课程筛选,找出可用课程。如果没有可用课程,则优惠券不可用。

  • 然后对可用课程计算总价,判断是否达到优惠门槛,没有达到门槛则优惠券不可用

可以发现,细筛需要查询每一张优惠券的限定范围,找出可用课程。这就需要查询coupon_scope表,还是比较麻烦的。而且,后期计算优惠明细的时候我们还需要知道每张优惠券的可用课程,因此在细筛完成后,建议把每个优惠券及对应的可用课程缓存到一个Map中,形成映射关系,避免后期重复查找。

// 3.排列组合出所有方案// 3.1.细筛(找出每一个优惠券的可用的课程,判断课程总价是否达到优惠券的使用需求)Map<Coupon, List<OrderCourseDTO>> availableCouponMap = findAvailableCoupon(availableCoupons, orderCourses);if (CollUtils.isEmpty(availableCouponMap)) {return CollUtils.emptyList();}
private final ICouponScopeService scopeService;private Map<Coupon, List<OrderCourseDTO>> findAvailableCoupon(List<Coupon> coupons, List<OrderCourseDTO> courses) {Map<Coupon, List<OrderCourseDTO>> map = new HashMap<>(coupons.size());for (Coupon coupon : coupons) {// 1.找出优惠券的可用的课程List<OrderCourseDTO> availableCourses = courses;if (coupon.getSpecific()) {// 1.1.限定了范围,查询券的可用范围List<CouponScope> scopes = scopeService.lambdaQuery().eq(CouponScope::getCouponId, coupon.getId()).list();// 1.2.获取范围对应的分类idSet<Long> scopeIds = scopes.stream().map(CouponScope::getBizId).collect(Collectors.toSet());// 1.3.筛选课程availableCourses = courses.stream().filter(c -> scopeIds.contains(c.getCateId())).collect(Collectors.toList());}if (CollUtils.isEmpty(availableCourses)) {// 没有任何可用课程,抛弃continue;}// 2.计算课程总价int totalAmount = availableCourses.stream().mapToInt(OrderCourseDTO::getPrice).sum();// 3.判断是否可用Discount discount = DiscountStrategy.getDiscount(coupon.getDiscountType());if (discount.canUse(totalAmount, coupon)) {map.put(coupon, availableCourses);}}return map;
}

优惠方案全排列组合

我们要找出优惠金额最高的优惠券组合,就必须先找出所有的排列组合,然后分别计算出优惠金额,然后对比并找出最优解。

这里我们采用的思路是这样的:

  • 优惠券放在一个List集合中,他们的角标就是0~N的数字

  • 优惠券的全排列组合,就是找N个不重复数字的全排列组合

    • 例如2个数字:[0,1],排列就包含:[0,1]、[1,0]两种

  • 然后按照角标排列优惠券即可

找N个不重复数字的全排列组合可以使用回溯算法

需要注意的是,全排列中只包含券组合方案,但是页面渲染的时候需要展示单张券供用户选择。因此我们将单张券也作为组合添加进去。

   // 3.2.排列组合availableCoupons = new Ar

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/411562.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux基础1-基本指令5(more,less,head,tail, | ,find)

本章继续整理其他linux基本指令 一.本章重点 1.more和less命令查看大文本 2.head和tail命令查看小文本和日志 3.使用管道多次处理信息 4.find指令 二.more和less more命令和less命令常用来查看大文本&#xff0c;其中less可以使用上下键快速浏览文本 使用方式 more文件 …

2024年6月GSEP(python)一级认证真题讲解

注意&#xff01;做题时长为2小时&#xff0c;孩子做完题目后对照讲解视频和讲解分析&#xff0c;针对薄弱点&#xff0c;进行有效的专项提高。 &#x1f451;讲解视频 2024.6GESPpython真题讲解 &#x1f451;讲解分析 1 单选题&#xff08;每题 2 分&#xff0c;共 30 分&a…

第15届蓝桥杯青少组Scratch初级组省赛真题试卷

第十五届蓝桥杯青少组省赛Scratch初级组真题试卷 题目总数&#xff1a;10 总分数&#xff1a;360 选择题 第 1 题 单选题 Scratch运行以下程序&#xff0c;角色会说( )? A.29 B.31 C.33 D.35 第 2 题 单选题 scratch运行下列哪个程序后&#xff0c;宇航…

在国产芯片上实现YOLOv5/v8图像AI识别-【4.1】RK3588训练数据时进行图像增强更多内容见视频

本专栏主要是提供一种国产化图像识别的解决方案&#xff0c;专栏中实现了YOLOv5/v8在国产化芯片上的使用部署&#xff0c;并可以实现网页端实时查看。根据自己的具体需求可以直接产品化部署使用。 B站配套视频&#xff1a;https://www.bilibili.com/video/BV1or421T74f 图像…

【蓝桥杯集训100题】scratch绘制扇子 蓝桥杯scratch比赛专项预测编程题 集训模拟练习题第28题

scratch绘制扇子 蓝桥杯集训100题第28题模拟练习解析 此题曾经作为第十届省赛的真题考过 一、题目要求 以坐标(0,0)点为中心绘制一把扇子;扇面和扇把都是三分之一圆,扇面的半径 为 100 左右,扇把的半径为 20 左右。 编程实现 每次点击绿旗后,舞台背景为白色,…

CUDA-BEVFusion(1): 环境安装

文章目录 1. 查看ubantu配置2. 环境安装2.1 安装包下载2.1.1 tensorRT 下载2.1.2 CUDA 下载2.1.3 cuDNN 下载2.2 安装2.2.1 cuda 安装2.2.2 cuDNN 安装2.2.3 tensorRT安装3. 安装包下载1. 查看ubantu配置 查看GPU的版本sudo apt-get install pciutilslspci | grep VGA查看linux…

探索Python中的拼音魔法:pypinyin库的奇妙之旅

文章目录 探索Python中的拼音魔法&#xff1a;pypinyin库的奇妙之旅背景&#xff1a;为何选择pypinyin&#xff1f;库简介&#xff1a;pypinyin是什么&#xff1f;安装指南&#xff1a;如何将pypinyin纳入你的项目&#xff1f;功能探索&#xff1a;pypinyin的五大核心函数实战演…

win10配置adb环境变量

初始状态&#xff1a; 最简单的配置方案&#xff0c;直接复制adb所在路径&#xff1a; 粘贴进来确定即可&#xff1a; 然后打开 cmd 查看已经配置成功了&#xff1a;

图表检测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]

图表检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

位图

问题导入 解决方案 用哈希表位图概念&#xff0c; 但是每个key只占用一个bite位&#xff0c; 用0表示没有本key&#xff0c; 1表示有此key 位图实现 三个主要接口 set&#xff08;key&#xff09;&#xff0c; 将key设成1 reset&#xff08;key&#xff09;&#xff1a; 将…

最长回文子串:动态规划推导

最长回文子串&#xff1a;结合图形推导动态规划 题目介绍 本题可以在力扣找到&#xff0c;题号为5。 给你一个字符串 s&#xff0c;找到 s 中最长的 回文子串。 示例 1&#xff1a; 输入&#xff1a;s “babad” 输出&#xff1a;“bab” 解释&#xff1a;“aba” 同样是符…

AI引擎点燃消费电子市场,有芯片企业利润飙涨至792.79%!

导语 这一市场出现回暖&#xff01;多家芯片企业净利润增长。 好消息&#xff01;消费电子在经历两年低谷期后&#xff0c;终于迎来了拐点。 根据中国通信院发布的数据显示&#xff0c;1—6月&#xff0c;国内市场手机出货量1.47亿部&#xff0c;同比增长13.2%&#xff1b;智能…

低代码门户技术:赋能业务灵活性与创新的新时代

随着数字化转型的深入推进&#xff0c;各行各业对灵活、高效的技术解决方案的需求日益增长。在这个背景下&#xff0c;低代码门户技术应运而生&#xff0c;为企业提供了一种新颖的应用开发方式。今天&#xff0c;我们将探讨低代码门户技术的基本概念、优势以及如何在实际应用中…

Ubuntu 24.04 上安装和配置 Zabbix Agent

Zabbix 是一个强大的开源监控工具&#xff0c;可以帮助您跟踪服务器&#xff0c;网络和应用程序。在主机环境中配置了 Zabbix Server 之后&#xff0c;下一步是添加用于监视的远程主机。Zabbix Agent 从您的服务器收集数据并将其发送到 Zabbix 服务器进行监控。 本指南将向您展…

three.js渲染中文的3D字体

下载中文字体 引入下面的代码 点击下载 提取码: lywa <!DOCTYPE html> <html lang"en"><head><title>three.js webgl - modifier - tessellation</title><meta charset"utf-8"><meta name"viewport" c…

chapter08-面向对象编程——(章节内容梳理)——day10

目录 快捷键 访问修饰符 封装 继承 方法重写 多态 快捷键 访问修饰符 封装 继承 本质 方法重写 多态 编译类型、运行类型、动态绑定机制

如何下载西门子电气元件EPLAN EDZ文件以及CAD文件等?

如何下载西门子电气元件EPLAN EDZ文件以及CAD文件等? 西门子全球电子商务: https://mall.industry.siemens.com/goos/WelcomePage.aspx?regionUrl=/cn&language=zh 西门子Industry Image Database: https://www.automation.siemens.com/bilddb/index.aspx?lang=en 以…

【Scala】Windows下安装Scala(全面)

1.下载 官网下载地址&#xff1a;https://downloads.lightbend.com/scala/2.11.12/scala-2.11.12.msi 2.安装 双击下载的.msi文件&#xff1a; 勾选"I accept the terms in the License Agreement",然后点击下一步 修改自己的安装路径&#xff1a; 然后选择brow…

快讯 | Midjourney开拓硬件领域:苹果前经理加盟助力发展

硅纪元快讯栏目&#xff0c;每日追踪AI领域的最新动态&#xff0c;快速汇总最新科技新闻&#xff0c;助您时刻紧跟行业趋势。简明扼要的呈现资讯概要&#xff0c;让您快速了解前沿资讯。 1分钟速览新闻 Claude AI 聊天机器人性能下滑引争议 中国能源化工行业首个330亿参数昆仑…

vagrant 创建虚拟机

创建一个名为 “Vagrantfile” 的文件&#xff0c;修改如下内容&#xff1a; Vagrant.configure("2") do |config|(1..3).each do |i|config.vm.define "k8s-node#{i}" do |node|# 设置虚拟机的Boxnode.vm.box "centos/7"# 设置虚拟机的主机名…