java xipin 111qqqq



package shiping;

import java.io.IOException;
import java.util.*;

import databean.Cost;
import databean.FulfilledOrder;
import databean.Order;
import databean.Stock;
import output.FufilledOrderWriter;
import output.UnfulfilledOrderWriter;
import input.CostReader;
import input.OrderReader;
import input.StockReader;

public class Shipping {
 

 private static final String LAST_CALL = "LAST_CALL";
 
 /**
  * Entry point for Shipping
  * @param orderEntryStreamIn    stream of incoming new orders
  * @param shippingCostsIn    a stream of shipping costs
  * @param StockReader    a stream of inventory for each region ??????
  * @param orderShipmentStreamOut   a stream to output completed shipments
  * @param lockerShipmentStreamOut   a stream to output completed locker shipments
  * @param unfulfilledOrderEntryStreamOut    a stream to output unfulfilled orders
  * @throws IOException
  */
 public void shipping(OrderReader orderReader, StockReader stockReader,
   CostReader costReader, FufilledOrderWriter fufilledOrderWriter,
   UnfulfilledOrderWriter unfulfilledOrderWriter)throws IOException{
 
  //把所有的库存Stock 对象 (在java data bean里)先存到Map里
  //(why Map?)  因为map是key value结构 所以可以吧 储存 (key- item id,
  //value -item Object 的List!!)
  //why hashtable ? Hashtable is synchronized
  //
  Map<String, List<Stock>> inventories = new Hashtable<String, List<Stock>>();
         while(stockReader.hasnext()){
          Stock inventory=stockReader.next();
          if(inventories.containsKey(inventory.getItemId())){
           //key -item id ,value 是stock object的list 
           inventories.get(inventory.getItemId()).add(inventory);
            }else{
       List<Stock> list=new LinkedList<Stock>();
       list.add(inventory);
       inventories.put(inventory.getItemId(), list);           
        }
      }
 
   //把所有的Cost对象 存在一个新的map里
   //eg 东到西多少cost 中到西 多少cost
  //依旧是key-value 结构 key是 destination value是一个list
 //比如 key是 东,东这个key对应的list就会储存从所有 从cost文档里读出来的
      //   cost信息--which destination is 东
 Map<String,List<Cost>> costs=new Hashtable<String,List<Cost>>();
 while(costReader.hasnext()){
  Cost cost=costReader.next();
  if (costs.containsKey(cost.getTo())) {
   costs.get(cost.getTo()).add(cost);
  }else{
   List<Cost> list=new LinkedList<Cost>();
   list.add(cost);
   costs.put(cost.getTo(), list);
   }
  //下面这段代码是干嘛的呢 就是说 在cost file里 只有东 到 西 2天   15刀
  //但是实际上 西到东 2天也是15刀 也要把这个信息存到map里
  if(cost.getFrom().equals(cost.getTo())){
   continue;
  }else{
   Cost costReverse= new Cost();
   costReverse.setFrom(cost.getTo());
   costReverse.setTo(cost.getFrom());
   costReverse.setCost(cost.getCost());
   costReverse.setTime(cost.getTime());
  if(costs.containsKey(costReverse.getTo())){
   costs.get(costReverse.getTo()).add(costReverse);
  }else{
   List<Cost> list =new LinkedList<Cost>();
   list.add(costReverse);
   costs.put(costReverse.getTo(), list);
  }
 }
  
  // Get the orders of each day and sort them by quantity to ensure we can deliver as many orders as possible
  // 先fulfill小订单 再fulfill大订单 这样可以在有限的库存情况下 fulfill经量多的order
  //在order的文档里 一个order可以有多个 item 但是一条order记录只有一个item
  //eg: order number 001 item number 34  quantity 5
  //    order number 001 item number 66 quantity  1
  while(orderReader.hasnext()){
   //返回一天的order
   List<Order> orders=getOrderByDay(orderReader);
   // 把一天的order从小到大sort
   Collections.sort(orders,new SortOrderByQuantity());
   //每次while循环跑一次 就是可以处理 当天的orders
   //现在 开始一个个遍历一天的orders 来处理当天的所有order
   
   
   for(Order order:orders){
    if(order.getOrderId().equals(LAST_CALL)){
    //处理locker 这个版本的题里没有 但是shiya有
    // continue
    }
   
   
  //To check if we have enough product in warehouse 
  int totoalInventory=0;
  //输出没库存 不能fulfill的order
  if(!inventories.containsKey(order.getItemId())){
   unfulfilledOrderWriter.write(order); 
     continue;
  }
  //inveotories 是key:item value: List<Stock> 所以这里遍历的是每个product的stock list
  for(Stock stock:inventories.get(order.getItemId())){
  totoalInventory+=stock.getQuantity();  //是一个item的total quantity
  }
  //如果这一个order已经比总库存大了 那么当然没法fulfill
  if(order.getQuantity()>totoalInventory){
   unfulfilledOrderWriter.write(order); 
  }else{//可以fulfill的order 那就把order转化成 fulfilled order
   // 当然 需要计算出 cost 和从那个仓库发货 和需要几天
   int itemToShip=order.getQuantity();
   // 计算cost
   List<Cost> shipCostList=costs.get(order.getTo());
   List<Cost> onTimeship=getOnTimeShipping(shipCostList, order.getTimeRequirement());
   //检查是否有onTimeship
   if(onTimeship.size()>0){
   FulfilledOrder fulfilledOrder=new FulfilledOrder();
   fulfilledOrder.setCost(onTimeship.get(0).getCost()*itemToShip); //获取最便宜的复合要求的cost
   fulfilledOrder.setDeliverTime(onTimeship.get(0).getTime());
   fulfilledOrder.setFrom(onTimeship.get(0).getFrom());
   fulfilledOrder.setItemId(order.getItemId());
   fulfilledOrder.setOrderId(order.getOrderId());
   fulfilledOrder.setQuantity(order.getQuantity());
   fulfilledOrder.setTimeRequirement(order.getTimeRequirement());
   fulfilledOrder.setTo(order.getTo());
   fufilledOrderWriter.write(fulfilledOrder);
   //已经送出了 要去对应送出仓库减库存
   List<Stock> delivered=inventories.get(order.getItemId());
   for(Stock stock:delivered){
    if(stock.getLocation().equals(onTimeship.get(0).getFrom())){
     stock.setQuantity(stock.getQuantity()-order.getQuantity());
    }
    break;
   }
  
   }else{ //你能走到这个if块 也是说明 有库存的 所以此时 就算没有onTimeShip 也要送
    List<Cost> delayedship=getDelayedShipping(shipCostList);
    if(delayedship.size()>0){
     FulfilledOrder fulfilledOrder=new FulfilledOrder();
     fulfilledOrder.setCost(delayedship.get(0).getCost()*itemToShip); //获取最便宜的复合要求的cost
     fulfilledOrder.setDeliverTime(delayedship.get(0).getTime());
     fulfilledOrder.setFrom(delayedship.get(0).getFrom());
     fulfilledOrder.setItemId(order.getItemId());
     fulfilledOrder.setOrderId(order.getOrderId());
     fulfilledOrder.setQuantity(order.getQuantity());
     fulfilledOrder.setTimeRequirement(order.getTimeRequirement());
     fulfilledOrder.setTo(order.getTo());
     fufilledOrderWriter.write(fulfilledOrder);
    
     List<Stock> delivered=inventories.get(order.getItemId());
     for(Stock stock:delivered){
      if(stock.getLocation().equals(delayedship.get(0).getFrom())){
       stock.setQuantity(stock.getQuantity()-order.getQuantity());
      }
      break;
     }
     }else{  // 如果能到这一块 说明 没有合适的运输方式 送不了
      unfulfilledOrderWriter.write(order);
     
     }
   
   
   }
  
 
  
  
   // 如果是需要locker的 就可以通过 destination 来判断
  
  }
   
  } 
   
   
  }}
  
  
  
 }


 //从order reader里读一天的 order 碰到last call就断掉  这样orders里正好是一天
 private static List<Order> getOrderByDay (OrderReader orderReader) {
  List<Order> orders = new ArrayList<Order>();
  while (orderReader.hasnext()) {
   Order currrentOrder = orderReader.next();
   orders.add(currrentOrder);
   if (currrentOrder.getOrderId().equals(LAST_CALL)) {
    break;
   }
  }
  return orders;
 }
    //输入的参数  :符合To的所有cost object
     //输出的参数 :在里面符合 ship requirment day 的cost list,按运费从小到大排序
 private static List<Cost> getOnTimeShipping(List<Cost> costs,int requiredDays){
  List<Cost> list=new ArrayList<Cost>();
  for(Cost cost:costs){
   if(cost.getTime()<=requiredDays){
    list.add(cost);
   }
  }
  // 然后在符合条件的cost里按照运费价格从小到大
  Collections.sort(list, new SortCostByCost());
  return list;
 }
 
 private static List<Cost> getDelayedShipping(List<Cost> costs){
  
  // 先选时间短的 相同天数下 选价钱低的
  Collections.sort(costs, new SortCostByDateCost());
  return costs;
 }
 
 
 private static final class SortOrderByQuantity implements Comparator<Order>{

  @Override
  public int compare(Order o1, Order o2) {
  return o1.getQuantity()-o2.getQuantity();
  }  
 }

 private static final class SortCostByCost implements Comparator<Cost>{

  @Override
  public int compare(Cost o1, Cost o2) {
   // TODO Auto-generated method stub
   return o1.getCost()-o2.getCost();
  }
 }
 private static final class SortCostByDateCost implements Comparator<Cost>{

  @Override
  public int compare(Cost o1, Cost o2) {
    if(o1.getTime()-o2.getTime()==0){
     return o1.getCost()-o2.getCost();
    }else{
     return o1.getTime()-o2.getTime();
    }
   
  }
 }
 
 
 
 
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值