zoukankan      html  css  js  c++  java
  • 船舱订票系统测试

    package com.dong.mytest.demo.other.yan;
    
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.Iterator;
    import java.util.List;
    import java.util.Map;
    
    public class TicketSystem {
    
        /**
         * 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
         */
        public static final Integer ORDER_STATUS_INIT = 0;
        public static final Integer ORDER_STATUS_FAILED = 1;
        public static final Integer ORDER_STATUS_SUCCESS = 2;
        public static final Integer ORDER_STATUS_CANCEL = 3;
    
        /**
         * 座位状态 0-空位 1-已预订
         */
        public static final Integer SEAT_STATUS_EMPTY = 0;
        public static final Integer SEAT_STATUS_ORDERED = 1;
    
        /**
         * 舱位id map
         */
        private Map<Integer, Cabin> cabinMap = new HashMap<>(16);
    
        /**
         * 订单map
         */
        private Map<Integer, TicketOrder> orderMap = new HashMap<>(16);
    
        public TicketSystem(int[] cabins) {
            if (cabins == null) {
                throw new RuntimeException("初始化参数错误");
            }
            // 初始化每个船舱的信息:id,座位列表,候补队列
            for (int i = 0; i < cabins.length; i++) {
                int cabinCount = cabins[i];
                List<Integer> seatList = new ArrayList<>(cabinCount);
                for (int j = 0; j < cabinCount; j++) {
                    // 0-空位 1-已被定
                    seatList.add(SEAT_STATUS_EMPTY);
                }
                Cabin cabin = new Cabin();
                cabin.setCabinId(i);
                cabin.setSeatList(seatList);
                cabinMap.put(i, cabin);
            }
        }
    
        /**
         * 从cabinId舱位中预定num个座位,订单编号为id
         */
        public boolean book(int id, int cabinId, int num) {
            if (cabinMap.get(cabinId) == null) {
                System.out.println("cabinId有误");
                return false;
            }
            if (orderMap.containsKey(id)) {
                System.out.println("订单id已存在,请确认后再试");
                return false;
            }
            Cabin cabin = cabinMap.get(cabinId);
            // 生成订单
            TicketOrder order = new TicketOrder();
            order.setId(id);
            order.setCabinId(cabinId);
            order.setNum(num);
            order.setStatus(ORDER_STATUS_INIT);
            orderMap.put(id, order);
            // 该船舱的候补队列
            List<TicketOrder> hbQueue = cabin.getHbQueue();
            // 候补队列为空
            if (hbQueue.isEmpty()) {
                // 该船舱剩余座位列表
                List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
                // 有足够余票
                if (remainSeatNumList.size() >= num) {
                    // 根据连续优先订票规则,获取座位号
                    List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, num);
                    for (Integer seatNum : seatNumList) {
                        // 修改座位号状态
                        cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
                    }
                    // 记录订单预定的座位列表
                    order.setOrderSeatNumList(seatNumList);
                    order.setStatus(ORDER_STATUS_SUCCESS);
                    return true;
                } else {
                    // 余票不足,该订单进入该船舱的候补队列队尾
                    order.setStatus(ORDER_STATUS_FAILED);
                    hbQueue.add(order);
                    return false;
                }
            } else {
                // 候补队列非空,直接进入候补队列队尾
                order.setStatus(ORDER_STATUS_FAILED);
                hbQueue.add(order);
                return false;
            }
        }
    
        /**
         * 根据连续优先订票规则,获取座位号
         */
        private List<Integer> checkHasContinuousSeatNum(List<Integer> remainSeatNumList, int orderSeatCount) {
            // 连续座位号列表
            List<Integer> list = new ArrayList<>();
            // 上一个座位号
            Integer preSeatNum = null;
            for (Integer seatNum : remainSeatNumList) {
                // 如果当前座位号和上一个不是差1,则说明不连续,清空
                if (preSeatNum != null && !seatNum.equals(preSeatNum + 1)) {
                    list.clear();
                }
                list.add(seatNum);
                // 如果连续座位号达到订票数,则直接返回
                if (list.size() >= orderSeatCount) {
                    return list;
                }
                preSeatNum = seatNum;
            }
            // 走到这里说明没有连续的号,返回最小的几个座位号
            list.clear();
            for (Integer seatNum : remainSeatNumList) {
                if (list.size() < orderSeatCount) {
                    list.add(seatNum);
                } else {
                    break;
                }
            }
            return list;
        }
    
        /**
         * 取消编号为id的订单,并及时处理候补队列订单
         */
        public boolean cancel(int id) {
            if (orderMap.get(id) == null) {
                System.out.println("订单id不存在");
                return false;
            }
            TicketOrder order = orderMap.get(id);
            Cabin cabin = cabinMap.get(order.getCabinId());
            boolean result = false;
            // 如果该订单已预定成功,则成功取消订单、退票并返回true
            if (ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
                // 回补座位
                List<Integer> orderSeatNumList = order.getOrderSeatNumList();
                for (Integer seatNum : orderSeatNumList) {
                    // 将船舱的座位状态修改为 0-空位
                    cabin.getSeatList().set(seatNum, SEAT_STATUS_EMPTY);
                }
                // 候补队列尝试继续买票
                queueRetry(cabin);
                result = true;
            } else if (ORDER_STATUS_FAILED.equals(order.getStatus())) {
                cabin.getHbQueue().removeIf(item -> item.getId() == order.getId());
                // 后面的候补队列尝试继续买票
                queueRetry(cabin);
                result = true;
            } else {
                // 其他:0-初始状态 3-已取消 直接返回false
            }
            // 修改订单状态
            order.setStatus(ORDER_STATUS_CANCEL);
            order.setOrderSeatNumList(new ArrayList<>());
            return result;
        }
    
        /**
         * 候补队列尝试继续买票
         */
        private void queueRetry(Cabin cabin) {
            Iterator<TicketOrder> iterator = cabin.getHbQueue().iterator();
            while (iterator.hasNext()) {
                TicketOrder ticketOrder = iterator.next();
                // 该船舱剩余座位列表
                List<Integer> remainSeatNumList = cabin.getRemainSeatNumList();
                // 没有足够的余票,直接退出
                if (remainSeatNumList.size() < ticketOrder.getNum()) {
                    break;
                }
                // 有足够余票,根据连续优先订票规则,获取座位号
                List<Integer> seatNumList = checkHasContinuousSeatNum(remainSeatNumList, ticketOrder.getNum());
                for (Integer seatNum : seatNumList) {
                    // 修改座位号状态
                    cabin.getSeatList().set(seatNum, SEAT_STATUS_ORDERED);
                }
                // 记录订单预定的座位列表
                ticketOrder.setOrderSeatNumList(seatNumList);
                ticketOrder.setStatus(ORDER_STATUS_SUCCESS);
                // 从队列中移除
                iterator.remove();
            }
        }
    
    
        public int query(int id) {
            TicketOrder order = orderMap.get(id);
            if (order == null || !ORDER_STATUS_SUCCESS.equals(order.getStatus())) {
                return -1;
            }
            // 如果预定成功,则返回最小的座位号
            return order.getOrderSeatNumList().get(0);
        }
    
        public static void main(String[] args) {
            TicketSystem ticketSystem = new TicketSystem(new int[]{10, 1});
            System.out.println(ticketSystem.book(71, 0, 2));
            System.out.println(ticketSystem.book(73, 0, 10));
            System.out.println(ticketSystem.book(72, 0, 2));
            System.out.println(ticketSystem.query(72));
            System.out.println(ticketSystem.book(74, 0, 2));
            System.out.println(ticketSystem.cancel(73));
            System.out.println(ticketSystem.query(74));
            System.out.println(ticketSystem.query(72));
            System.out.println(ticketSystem.cancel(72));
            System.out.println(ticketSystem.book(75, 0, 3));
            System.out.println(ticketSystem.query(75));
            System.out.println(ticketSystem.cancel(75));
            System.out.println(ticketSystem.book(76, 0, 2));
            System.out.println(ticketSystem.book(77, 0, 2));
            System.out.println(ticketSystem.cancel(76));
            System.out.println(ticketSystem.book(78, 0, 3));
            System.out.println(ticketSystem.query(78));
        }
    }
    package com.dong.mytest.demo.other.yan;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class Cabin {
    
        /**
         * 船舱编号
         */
        private int cabinId;
    
        /**
         * 座位列表,list下标代表座位号,0代表空位,1代表被定了
         */
        private List<Integer> seatList;
    
        /**
         * 候补队列
         */
        private List<TicketOrder> hbQueue = new ArrayList<>();
    
        /**
         * 获取剩余的座位号列表
         *
         * @return list
         */
        public List<Integer> getRemainSeatNumList() {
            List<Integer> remainSeatNumList = new ArrayList<>();
            for (int i = 0; i < seatList.size(); i++) {
                Integer flag = seatList.get(i);
                if (flag.equals(0)) {
                    remainSeatNumList.add(i);
                }
            }
            return remainSeatNumList;
        }
    
        public int getCabinId() {
            return cabinId;
        }
    
        public void setCabinId(int cabinId) {
            this.cabinId = cabinId;
        }
    
        public List<Integer> getSeatList() {
            return seatList;
        }
    
        public void setSeatList(List<Integer> seatList) {
            this.seatList = seatList;
        }
    
        public List<TicketOrder> getHbQueue() {
            return hbQueue;
        }
    
        public void setHbQueue(List<TicketOrder> hbQueue) {
            this.hbQueue = hbQueue;
        }
    }
    
    package com.dong.mytest.demo.other.yan;
    
    import java.util.List;
    
    public class TicketOrder {
    
        /**
         * 订单id
         */
        private int id;
    
        /**
         * 预订的船舱id
         */
        private int cabinId;
    
        /**
         * 预定座位数
         */
        private int num;
    
        /**
         * 预定的座位编号列表
         */
        private List<Integer> orderSeatNumList;
    
        /**
         * 订单状态 0-初始状态 1-预定失败 2-预定成功 3-已取消
         */
        private int status;
    
        public int getId() {
            return id;
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getNum() {
            return num;
        }
    
        public void setNum(int num) {
            this.num = num;
        }
    
        public List<Integer> getOrderSeatNumList() {
            return orderSeatNumList;
        }
    
        public void setOrderSeatNumList(List<Integer> orderSeatNumList) {
            this.orderSeatNumList = orderSeatNumList;
        }
    
        public int getStatus() {
            return status;
        }
    
        public void setStatus(int status) {
            this.status = status;
        }
    
        public int getCabinId() {
            return cabinId;
        }
    
        public void setCabinId(int cabinId) {
            this.cabinId = cabinId;
        }
    
    }
    
  • 相关阅读:
    [连载]《C#通讯(串口和网络)框架的设计与实现》-1.通讯框架介绍
    [连载]《C#通讯(串口和网络)框架的设计与实现》- 0.前言
    [注意]SerialPort操作PCI-1621D多串口卡,出现异常"参数不正确"
    [发布]SuperIO v2.2.5 集成OPC服务端和OPC客户端
    【发布】工业串口和网络软件通讯平台(SuperIO v2.2.4)
    【工业串口和网络软件通讯平台(SuperIO)教程】九.重写通讯接口函数,实现特殊通讯方式
    【工业串口和网络软件通讯平台(SuperIO)教程】八.SuperIO通讯机制与设备驱动对接的说明
    【工业串口和网络软件通讯平台(SuperIO)教程】七.二次开发服务驱动
    【工业串口和网络软件通讯平台(SuperIO)教程】六.二次开发导出数据驱动
    【工业串口和网络软件通讯平台(SuperIO)教程】五.二次开发图形显示界面
  • 原文地址:https://www.cnblogs.com/dong320/p/15791085.html
Copyright © 2011-2022 走看看