{
  "cells": [
    {
      "cell_type": "markdown",
      "source": [
        "# **Simulating the Bullwhip Effect in a Multi-Tier Supply Chain**"
      ],
      "metadata": {
        "id": "UWS_u9PyEcRh"
      }
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "evlSIeEs2W67"
      },
      "source": [
        "# Settings"
      ]
    },
    {
      "cell_type": "code",
      "source": [
        "# Define cost per unit for storage and backorder penalties\n",
        "STORAGE_COST_PER_UNIT = 0.5        # Cost incurred for storing each unit of product\n",
        "BACKORDER_PENALTY_COST_PER_UNIT = 1 # Cost penalty for each unit in backorder (unfulfilled orders)\n",
        "\n",
        "# Define the number of weeks for the simulation\n",
        "WEEKS_TO_PLAY = 41                 # Total simulation period in weeks\n",
        "\n",
        "# Set delay in supply chain (in weeks)\n",
        "QUEUE_DELAY_WEEKS = 2              # Delay time in weeks between order and delivery in supply chain\n",
        "\n",
        "# Initial values for various stock-related metrics\n",
        "INITIAL_STOCK = 12                 # Starting stock level for each actor\n",
        "INITIAL_COST = 0                   # Initial cost at the beginning of the simulation\n",
        "INITIAL_CURRENT_ORDERS = 0         # Initial orders at the start of the simulation\n",
        "\n",
        "# Customer ordering pattern settings\n",
        "CUSTOMER_INITIAL_ORDERS = 5        # Initial order quantity for customers in early weeks\n",
        "CUSTOMER_SUBSEQUENT_ORDERS = 9     # Increased order quantity for customers in subsequent weeks\n",
        "\n",
        "# Target stock level for supply chain actors\n",
        "TARGET_STOCK = 12                  # Desired stock level to balance demand and minimize costs"
      ],
      "metadata": {
        "id": "PHolsibV-ELk"
      },
      "execution_count": 11,
      "outputs": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "vdx7B5rL2W6_"
      },
      "source": [
        "# Customers"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "id": "aYQeuUoE2W6_"
      },
      "outputs": [],
      "source": [
        "# Define the Customer class to simulate customer behavior\n",
        "class Customer:\n",
        "    def __init__(self):\n",
        "        # Initialize the total beer received by the customer\n",
        "        self.totalBeerReceived = 0\n",
        "        return\n",
        "\n",
        "    def RecieveFromRetailer(self, amountReceived):\n",
        "        # Update the total amount of beer received based on supply from the retailer\n",
        "        self.totalBeerReceived += amountReceived\n",
        "        return\n",
        "\n",
        "    def CalculateOrder(self, weekNum):\n",
        "        # Calculate the customer order based on the week number\n",
        "        # Order amount changes after the initial weeks to reflect demand increase\n",
        "        if weekNum <= 5:\n",
        "            result = CUSTOMER_INITIAL_ORDERS\n",
        "        else:\n",
        "            result = CUSTOMER_SUBSEQUENT_ORDERS\n",
        "        return result\n",
        "\n",
        "    def GetBeerReceived(self):\n",
        "        # Retrieve the total amount of beer received by the customer\n",
        "        return self.totalBeerReceived"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "m3hjiAxA2W6_"
      },
      "source": [
        "# SupplyChainQueue"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "id": "9OsbgZl32W6_"
      },
      "outputs": [],
      "source": [
        "class SupplyChainQueue:\n",
        "\n",
        "    def __init__(self, queueLength):\n",
        "        # Initialize the supply chain queue with a specified length\n",
        "        # 'queueLength' represents the maximum number of orders that can be held in the queue\n",
        "        self.queueLength = queueLength\n",
        "        self.data = []                  # List to store orders in the queue\n",
        "        return\n",
        "\n",
        "    def PushEnvelope(self, numberOfCasesToOrder):\n",
        "        # Attempt to place a new order in the queue\n",
        "        # 'numberOfCasesToOrder' represents the quantity of product ordered\n",
        "        orderSuccessfullyPlaced = False  # Track if order was successfully added\n",
        "\n",
        "        if len(self.data) < self.queueLength:  # Check if queue has space for the order\n",
        "            self.data.append(numberOfCasesToOrder)  # Add order to the queue\n",
        "            orderSuccessfullyPlaced = True          # Mark order as successfully placed\n",
        "\n",
        "        return orderSuccessfullyPlaced  # Return whether the order was successfully added\n",
        "\n",
        "    def AdvanceQueue(self):\n",
        "        # Move the queue forward by removing the oldest order (FIFO - First In, First Out)\n",
        "        # This simulates the delay in processing orders over time\n",
        "        self.data.pop(0)  # Remove the first order in the queue\n",
        "        return\n",
        "\n",
        "    def PopEnvelope(self):\n",
        "        # Retrieve the next order to be delivered from the front of the queue\n",
        "        if len(self.data) >= 1:         # Check if there is at least one order in the queue\n",
        "            quantityDelivered = self.data[0]  # Get the first order in the queue\n",
        "            self.AdvanceQueue()               # Remove it from the queue after delivery\n",
        "        else:\n",
        "            quantityDelivered = 0       # No orders to deliver if the queue is empty\n",
        "\n",
        "        return quantityDelivered        # Return the quantity to be delivered\n",
        "\n",
        "    def PrettyPrint(self):\n",
        "        # Print the current state of the queue, mainly for debugging purposes\n",
        "        print(self.data)\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "7QKiWeU72W7A"
      },
      "source": [
        "# SupplyChainActor"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "id": "IimSKBfe2W7A"
      },
      "outputs": [],
      "source": [
        "class SupplyChainActor:\n",
        "\n",
        "    def __init__(self, incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue):\n",
        "        # Initialize stock, orders, and cost attributes\n",
        "        self.currentStock = INITIAL_STOCK              # Initial stock level for the actor\n",
        "        self.currentOrders = INITIAL_CURRENT_ORDERS    # Initial orders to be fulfilled\n",
        "        self.costsIncurred = INITIAL_COST              # Initial cost at the start of the simulation\n",
        "\n",
        "        # Set up queues for managing orders and deliveries\n",
        "        self.incomingOrdersQueue = incomingOrdersQueue   # Queue for orders from downstream actors\n",
        "        self.outgoingOrdersQueue = outgoingOrdersQueue   # Queue for orders to upstream actors\n",
        "        self.incomingDeliveriesQueue = incomingDeliveriesQueue  # Queue for deliveries from upstream\n",
        "        self.outgoingDeliveriesQueue = outgoingDeliveriesQueue  # Queue for deliveries to downstream\n",
        "\n",
        "        self.lastOrderQuantity = 0  # Store the quantity ordered in the last round for tracking purposes\n",
        "        return\n",
        "\n",
        "    def PlaceOutgoingDelivery(self, amountToDeliver):\n",
        "        # Place the calculated delivery quantity in the outgoing deliveries queue\n",
        "        self.outgoingDeliveriesQueue.PushEnvelope(amountToDeliver)\n",
        "        return\n",
        "\n",
        "    def PlaceOutgoingOrder(self, weekNum):\n",
        "        # Place an order based on the week number, using an \"anchor and maintain\" strategy after an initial period\n",
        "        if weekNum <= 4:\n",
        "            amountToOrder = 4  # Initial equilibrium order amount for the first few weeks\n",
        "        else:\n",
        "            # After initial weeks, determine order based on current orders and stock levels\n",
        "            amountToOrder = 0.5 * self.currentOrders  # Order amount scales with outstanding orders\n",
        "\n",
        "            # Adjust order to reach target stock level\n",
        "            if (TARGET_STOCK - self.currentStock) > 0:\n",
        "                amountToOrder += TARGET_STOCK - self.currentStock\n",
        "\n",
        "        # Add the order to the outgoing orders queue\n",
        "        self.outgoingOrdersQueue.PushEnvelope(amountToOrder)\n",
        "        self.lastOrderQuantity = amountToOrder  # Track the last order quantity for reference\n",
        "        return\n",
        "\n",
        "    def ReceiveIncomingDelivery(self):\n",
        "        # Receive a delivery from upstream by popping the first item in the incoming deliveries queue\n",
        "        quantityReceived = self.incomingDeliveriesQueue.PopEnvelope()\n",
        "\n",
        "        # Add the received quantity to the current stock\n",
        "        if quantityReceived > 0:\n",
        "            self.currentStock += quantityReceived\n",
        "        return\n",
        "\n",
        "    def ReceiveIncomingOrders(self):\n",
        "        # Receive an order from downstream by popping the first item in the incoming orders queue\n",
        "        thisOrder = self.incomingOrdersQueue.PopEnvelope()\n",
        "\n",
        "        # Add the incoming order to the current orders to be fulfilled\n",
        "        if thisOrder > 0:\n",
        "            self.currentOrders += thisOrder\n",
        "        return\n",
        "\n",
        "    def CalcBeerToDeliver(self):\n",
        "        # Calculate the quantity of beer to deliver based on current stock and orders\n",
        "        deliveryQuantity = 0\n",
        "\n",
        "        # If current stock can fulfill all current orders, deliver the full amount\n",
        "        if self.currentStock >= self.currentOrders:\n",
        "            deliveryQuantity = self.currentOrders\n",
        "            self.currentStock -= deliveryQuantity    # Reduce stock by delivered quantity\n",
        "            self.currentOrders -= deliveryQuantity    # Reduce outstanding orders accordingly\n",
        "        # If stock is insufficient, deliver as much as possible and backorder the rest\n",
        "        elif self.currentStock > 0 and self.currentStock < self.currentOrders:\n",
        "            deliveryQuantity = self.currentStock      # Deliver all available stock\n",
        "            self.currentStock = 0                     # Stock becomes zero after delivery\n",
        "            self.currentOrders -= deliveryQuantity    # Reduce outstanding orders by delivered amount\n",
        "        return deliveryQuantity\n",
        "\n",
        "    def CalcCostForTurn(self):\n",
        "        # Calculate the costs for the current turn, including storage and backorder penalties\n",
        "        inventoryStorageCost = self.currentStock * STORAGE_COST_PER_UNIT  # Cost for holding inventory\n",
        "        backorderPenaltyCost = self.currentOrders * BACKORDER_PENALTY_COST_PER_UNIT  # Cost for unfulfilled orders\n",
        "        costsThisTurn = inventoryStorageCost + backorderPenaltyCost       # Total cost for this turn\n",
        "        return costsThisTurn\n",
        "\n",
        "    def GetCostIncurred(self):\n",
        "        # Return the total costs incurred by this actor so far\n",
        "        return self.costsIncurred\n",
        "\n",
        "    def GetLastOrderQuantity(self):\n",
        "        # Return the quantity of the last order placed by this actor\n",
        "        return self.lastOrderQuantity\n",
        "\n",
        "    def CalcEffectiveInventory(self):\n",
        "        # Calculate effective inventory as the difference between stock and outstanding orders\n",
        "        # This helps determine if the actor is in surplus or backorder\n",
        "        return (self.currentStock - self.currentOrders)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ei3YZtmY2W7A"
      },
      "source": [
        "# Retailer"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 15,
      "metadata": {
        "id": "dhUX7bLx2W7A"
      },
      "outputs": [],
      "source": [
        "class Retailer(SupplyChainActor):\n",
        "\n",
        "    def __init__(self, incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue, theCustomer):\n",
        "        # Initialize the retailer with supply chain queues and a customer instance\n",
        "        # Inherit attributes and methods from the SupplyChainActor superclass\n",
        "        super().__init__(incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue)\n",
        "        self.customer = theCustomer  # Customer instance associated with the retailer\n",
        "        return\n",
        "\n",
        "    def ReceiveIncomingOrderFromCustomer(self, weekNum):\n",
        "        # Add the calculated customer order for the current week to the retailer's orders\n",
        "        # CalculateOrder method from Customer class is used to get the order amount\n",
        "        self.currentOrders += self.customer.CalculateOrder(weekNum)\n",
        "        return\n",
        "\n",
        "    def ShipOutgoingDeliveryToCustomer(self):\n",
        "        # Ship the calculated amount of beer to the customer by calling CalcBeerToDeliver\n",
        "        # RecieveFromRetailer method from Customer class is used to receive the quantity delivered\n",
        "        self.customer.RecieveFromRetailer(self.CalcBeerToDeliver())\n",
        "        return\n",
        "\n",
        "    def TakeTurn(self, weekNum):\n",
        "        # Define the series of actions the retailer performs each turn (weekly):\n",
        "\n",
        "        # 1. Receive new delivery from the wholesaler\n",
        "        # This step also advances the delivery queue by removing the first order in line\n",
        "        self.ReceiveIncomingDelivery()\n",
        "\n",
        "        # 2. Receive new order from the customer\n",
        "        self.ReceiveIncomingOrderFromCustomer(weekNum)\n",
        "\n",
        "        # 3. Calculate and ship the required amount to the customer\n",
        "        # Directly call RecieveFromRetailer with a fixed delivery amount for the initial weeks\n",
        "        if weekNum <= 4:\n",
        "            self.customer.RecieveFromRetailer(4)  # Fixed delivery amount in the first weeks\n",
        "        else:\n",
        "            self.customer.RecieveFromRetailer(self.CalcBeerToDeliver())  # Dynamic delivery based on stock\n",
        "\n",
        "        # 4. Place an outgoing order to the wholesaler\n",
        "        self.PlaceOutgoingOrder(weekNum)\n",
        "\n",
        "        # 5. Update the retailer's costs for the current turn\n",
        "        self.costsIncurred += self.CalcCostForTurn()\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "SFRrZOtE2W7B"
      },
      "source": [
        "# Wholesaler"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 16,
      "metadata": {
        "id": "Zq-elYeV2W7B"
      },
      "outputs": [],
      "source": [
        "class Wholesaler(SupplyChainActor):\n",
        "\n",
        "    def __init__(self, incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue):\n",
        "        # Initialize the wholesaler with supply chain queues by inheriting from SupplyChainActor\n",
        "        super().__init__(incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue)\n",
        "        return\n",
        "\n",
        "    def TakeTurn(self, weekNum):\n",
        "        # Define the steps the wholesaler performs each turn (weekly):\n",
        "\n",
        "        # 1. Receive new delivery from the distributor\n",
        "        # This step also advances the delivery queue by removing the first order in line\n",
        "        self.ReceiveIncomingDelivery()\n",
        "\n",
        "        # 2. Receive new order from the retailer\n",
        "        # This step also advances the orders queue\n",
        "        self.ReceiveIncomingOrders()\n",
        "\n",
        "        # 3. Prepare and place the outgoing delivery to the retailer\n",
        "        # Initially, for the first few weeks, send a fixed amount of 4 units\n",
        "        if weekNum <= 4:\n",
        "            self.PlaceOutgoingDelivery(4)  # Fixed delivery amount in the first weeks\n",
        "        else:\n",
        "            # After the initial weeks, calculate the delivery based on current stock and orders\n",
        "            self.PlaceOutgoingDelivery(self.CalcBeerToDeliver())\n",
        "\n",
        "        # 4. Place an order to the upstream actor (such as a distributor)\n",
        "        self.PlaceOutgoingOrder(weekNum)\n",
        "\n",
        "        # 5. Update the wholesaler's costs for the current turn\n",
        "        self.costsIncurred += self.CalcCostForTurn()\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "uSoFWWQi2W7B"
      },
      "source": [
        "# Distributor"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 17,
      "metadata": {
        "id": "IV1SB0gO2W7B"
      },
      "outputs": [],
      "source": [
        "class Distributor(SupplyChainActor):\n",
        "\n",
        "    def __init__(self, incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue):\n",
        "        # Initialize the distributor with supply chain queues by inheriting from SupplyChainActor\n",
        "        super().__init__(incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue)\n",
        "        return\n",
        "\n",
        "    def TakeTurn(self, weekNum):\n",
        "        # Define the steps the distributor performs each turn (weekly):\n",
        "\n",
        "        # 1. Receive new delivery from the factory\n",
        "        # This also advances the delivery queue by removing the first item in line\n",
        "        self.ReceiveIncomingDelivery()\n",
        "\n",
        "        # 2. Receive new order from the wholesaler\n",
        "        # This also advances the orders queue by removing the first item in line\n",
        "        self.ReceiveIncomingOrders()\n",
        "\n",
        "        # 3. Prepare and place the outgoing delivery to the wholesaler\n",
        "        # Initially, for the first few weeks, send a fixed amount of 4 units\n",
        "        if weekNum <= 4:\n",
        "            self.PlaceOutgoingDelivery(4)  # Fixed delivery amount in the first weeks\n",
        "        else:\n",
        "            # After the initial weeks, calculate delivery based on current stock and orders\n",
        "            self.PlaceOutgoingDelivery(self.CalcBeerToDeliver())\n",
        "\n",
        "        # 4. Place an order to the upstream actor (e.g., factory) to replenish stock\n",
        "        self.PlaceOutgoingOrder(weekNum)\n",
        "\n",
        "        # 5. Update the distributor’s costs for the current turn\n",
        "        self.costsIncurred += self.CalcCostForTurn()\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oebF0Q9h2W7B"
      },
      "source": [
        "# Factory"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 18,
      "metadata": {
        "id": "J20MJ-3D2W7C"
      },
      "outputs": [],
      "source": [
        "class Factory(SupplyChainActor):\n",
        "\n",
        "    def __init__(self, incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue, productionDelayWeeks):\n",
        "        # Initialize the factory with supply chain queues and a production delay queue\n",
        "        super().__init__(incomingOrdersQueue, outgoingOrdersQueue, incomingDeliveriesQueue, outgoingDeliveriesQueue)\n",
        "\n",
        "        # Initialize a queue to handle production delays (simulating brewing/production time)\n",
        "        self.BeerProductionDelayQueue = SupplyChainQueue(productionDelayWeeks)\n",
        "\n",
        "        # Assume the factory has initial production runs in progress for stability\n",
        "        # These initial production orders help prevent stockouts at the beginning\n",
        "        self.BeerProductionDelayQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "        self.BeerProductionDelayQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "        return\n",
        "\n",
        "    def ProduceBeer(self, weekNum):\n",
        "        # Calculate the amount of beer to produce based on the week number\n",
        "\n",
        "        if weekNum <= 4:\n",
        "            amountToOrder = 4  # Fixed initial production amount for the first few weeks\n",
        "        else:\n",
        "            # After initial weeks, production amount scales with current orders and target stock\n",
        "            amountToOrder = 0.5 * self.currentOrders  # Produces enough to cover current orders\n",
        "\n",
        "            # Adjust production to maintain target stock level if below target\n",
        "            if (TARGET_STOCK - self.currentStock) > 0:\n",
        "                amountToOrder += TARGET_STOCK - self.currentStock\n",
        "\n",
        "        # Add the production order to the production delay queue (simulates delayed production)\n",
        "        self.BeerProductionDelayQueue.PushEnvelope(amountToOrder)\n",
        "        self.lastOrderQuantity = amountToOrder  # Track the last production order quantity\n",
        "        return\n",
        "\n",
        "    def FinishProduction(self):\n",
        "        # Complete a production run and add the produced beer to the current stock\n",
        "        amountProduced = self.BeerProductionDelayQueue.PopEnvelope()\n",
        "\n",
        "        # Add completed production amount to stock if production is finished\n",
        "        if amountProduced > 0:\n",
        "            self.currentStock += amountProduced\n",
        "        return\n",
        "\n",
        "    def TakeTurn(self, weekNum):\n",
        "        # Define the steps the factory performs each turn (weekly):\n",
        "\n",
        "        # 1. Complete previous production runs (if any) and add to stock\n",
        "        self.FinishProduction()\n",
        "\n",
        "        # 2. Receive new orders from the distributor\n",
        "        # Advances the incoming orders queue by removing the first order\n",
        "        self.ReceiveIncomingOrders()\n",
        "\n",
        "        # 3. Prepare and place the outgoing delivery to the distributor\n",
        "        # Initially, send a fixed amount of 4 units in the first few weeks\n",
        "        if weekNum <= 4:\n",
        "            self.PlaceOutgoingDelivery(4)\n",
        "        else:\n",
        "            # After initial weeks, calculate delivery based on current stock and orders\n",
        "            self.PlaceOutgoingDelivery(self.CalcBeerToDeliver())\n",
        "\n",
        "        # 4. Initiate production to fulfill future demand\n",
        "        self.ProduceBeer(weekNum)\n",
        "\n",
        "        # 5. Calculate and update the factory’s costs for the current turn\n",
        "        self.costsIncurred += self.CalcCostForTurn()\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "bIHIgpX72W7C"
      },
      "source": [
        "# SupplyChainStatistics"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 19,
      "metadata": {
        "id": "YA5-s-A_2W7C"
      },
      "outputs": [],
      "source": [
        "import plotly.express as px\n",
        "import plotly.graph_objects as go\n",
        "\n",
        "class SupplyChainStatistics:\n",
        "\n",
        "    def __init__(self):\n",
        "        # Initialize lists to store time-series data for each actor in the supply chain\n",
        "        # Each list will track metrics over each turn (e.g., week)\n",
        "\n",
        "        # Costs over time for each supply chain actor\n",
        "        self.retailerCostsOverTime = []\n",
        "        self.wholesalerCostsOverTime = []\n",
        "        self.distributorCostsOverTime = []\n",
        "        self.factoryCostsOverTime = []\n",
        "\n",
        "        # Orders over time for each actor\n",
        "        self.retailerOrdersOverTime = []\n",
        "        self.wholesalerOrdersOverTime = []\n",
        "        self.distributorOrdersOverTime = []\n",
        "        self.factoryOrdersOverTime = []\n",
        "\n",
        "        # Effective inventory (current stock - current orders) over time for each actor\n",
        "        self.retailerEffectiveInventoryOverTime = []\n",
        "        self.wholesalerEffectiveInventoryOverTime = []\n",
        "        self.distributorEffectiveInventoryOverTime = []\n",
        "        self.factoryEffectiveInventoryOverTime = []\n",
        "        return\n",
        "\n",
        "    # Methods to record orders each week for each actor\n",
        "    def RecordRetailerOrders(self, retailerOrdersThisWeek):\n",
        "        self.retailerOrdersOverTime.append(retailerOrdersThisWeek)\n",
        "        print('Retailer Order:', self.retailerOrdersOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordWholesalerOrders(self, wholesalerOrdersThisWeek):\n",
        "        self.wholesalerOrdersOverTime.append(wholesalerOrdersThisWeek)\n",
        "        print('Wholesaler Order:', self.wholesalerOrdersOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordDistributorOrders(self, distributorOrdersThisWeek):\n",
        "        self.distributorOrdersOverTime.append(distributorOrdersThisWeek)\n",
        "        print('Distributor Order:', self.distributorOrdersOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordFactoryOrders(self, factoryOrdersThisWeek):\n",
        "        self.factoryOrdersOverTime.append(factoryOrdersThisWeek)\n",
        "        print('Factory Order:', self.factoryOrdersOverTime[-1])\n",
        "        return\n",
        "\n",
        "    # Methods to record costs incurred each week for each actor\n",
        "    def RecordRetailerCost(self, retailerCostsThisWeek):\n",
        "        self.retailerCostsOverTime.append(retailerCostsThisWeek)\n",
        "        print('Retailer Cost:', self.retailerCostsOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordWholesalerCost(self, wholesalerCostsThisWeek):\n",
        "        self.wholesalerCostsOverTime.append(wholesalerCostsThisWeek)\n",
        "        print('Wholesaler Cost:', self.wholesalerCostsOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordDistributorCost(self, distributorCostsThisWeek):\n",
        "        self.distributorCostsOverTime.append(distributorCostsThisWeek)\n",
        "        print('Distributor Cost:', self.distributorCostsOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordFactoryCost(self, factoryCostsThisWeek):\n",
        "        self.factoryCostsOverTime.append(factoryCostsThisWeek)\n",
        "        print('Factory Cost:', self.factoryCostsOverTime[-1])\n",
        "        return\n",
        "\n",
        "    # Methods to record effective inventory each week for each actor\n",
        "    def RecordRetailerEffectiveInventory(self, retailerEffectiveInventoryThisWeek):\n",
        "        self.retailerEffectiveInventoryOverTime.append(retailerEffectiveInventoryThisWeek)\n",
        "        print('Retailer Effective Inventory:', self.retailerEffectiveInventoryOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordWholesalerEffectiveInventory(self, wholesalerEffectiveInventoryThisWeek):\n",
        "        self.wholesalerEffectiveInventoryOverTime.append(wholesalerEffectiveInventoryThisWeek)\n",
        "        print('Wholesaler Effective Inventory:', self.wholesalerEffectiveInventoryOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordDistributorEffectiveInventory(self, distributorEffectiveInventoryThisWeek):\n",
        "        self.distributorEffectiveInventoryOverTime.append(distributorEffectiveInventoryThisWeek)\n",
        "        print('Distributor Effective Inventory:', self.distributorEffectiveInventoryOverTime[-1])\n",
        "        return\n",
        "\n",
        "    def RecordFactoryEffectiveInventory(self, factoryEffectiveInventoryThisWeek):\n",
        "        self.factoryEffectiveInventoryOverTime.append(factoryEffectiveInventoryThisWeek)\n",
        "        print('Factory Effective Inventory:', self.factoryEffectiveInventoryOverTime[-1])\n",
        "        return\n",
        "\n",
        "    # Plotting methods to visualize orders, inventory, and costs over time for each actor\n",
        "    def PlotOrders(self):\n",
        "        # Create a plot to visualize orders placed over time by each actor\n",
        "        fig = go.Figure()\n",
        "        weeks = list(range(0, WEEKS_TO_PLAY + 2))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.retailerOrdersOverTime, mode='lines+markers',\n",
        "                    name='Retailer Orders', marker=dict(size=5), marker_color='rgb(215,48,39)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.wholesalerOrdersOverTime, mode='lines+markers',\n",
        "                    name='Wholesaler Orders', marker=dict(size=5), marker_color='rgb(255,186,0)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.distributorOrdersOverTime, mode='lines+markers',\n",
        "                    name='Distributor Orders', marker=dict(size=5), marker_color='rgb(126,2,114)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.factoryOrdersOverTime, mode='lines+markers',\n",
        "                    name='Factory Orders', marker=dict(size=5), marker_color='rgb(69,117,180)'))\n",
        "        fig.update_layout(title_text='*Orders Placed Over Time*', xaxis_title='Weeks', yaxis_title='Orders',\n",
        "                          paper_bgcolor='rgba(0,0,0,0)', height=580)\n",
        "        fig.update_xaxes(range=[0, WEEKS_TO_PLAY])\n",
        "        fig.show()\n",
        "        return\n",
        "\n",
        "    def PlotEffectiveInventory(self):\n",
        "        # Create a plot to visualize effective inventory over time for each actor\n",
        "        fig = go.Figure()\n",
        "        weeks = list(range(0, WEEKS_TO_PLAY + 2))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.retailerEffectiveInventoryOverTime, mode='lines+markers',\n",
        "                    name='Retailer Inventory', marker=dict(size=5), marker_color='rgb(215,48,39)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.wholesalerEffectiveInventoryOverTime, mode='lines+markers',\n",
        "                    name='Wholesaler Inventory', marker=dict(size=5), marker_color='rgb(255,186,0)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.distributorEffectiveInventoryOverTime, mode='lines+markers',\n",
        "                    name='Distributor Inventory', marker=dict(size=5), marker_color='rgb(126,2,114)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.factoryEffectiveInventoryOverTime, mode='lines+markers',\n",
        "                    name='Factory Inventory', marker=dict(size=5), marker_color='rgb(69,117,180)'))\n",
        "        fig.update_layout(title_text='*Effective Inventory Over Time*', xaxis_title='Weeks', yaxis_title='Effective Inventory',\n",
        "                          paper_bgcolor='rgba(0,0,0,0)', height=580)\n",
        "        fig.update_xaxes(range=[0, WEEKS_TO_PLAY])\n",
        "        fig.show()\n",
        "        return\n",
        "\n",
        "    def PlotCosts(self):\n",
        "        # Create a plot to visualize total costs incurred over time by each actor\n",
        "        fig = go.Figure()\n",
        "        weeks = list(range(0, WEEKS_TO_PLAY + 2))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.retailerCostsOverTime, mode='lines+markers',\n",
        "                    name='Retailer Total Cost', marker=dict(size=5), marker_color='rgb(215,48,39)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.wholesalerCostsOverTime, mode='lines+markers',\n",
        "                    name='Wholesaler Total Cost', marker=dict(size=5), marker_color='rgb(255,186,0)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.distributorCostsOverTime, mode='lines+markers',\n",
        "                    name='Distributor Total Cost', marker=dict(size=5), marker_color='rgb(126,2,114)'))\n",
        "        fig.add_trace(go.Scatter(x=weeks, y=self.factoryCostsOverTime, mode='lines+markers',\n",
        "                    name='Factory Total Cost', marker=dict(size=5), marker_color='rgb(69,117,180)'))\n",
        "        fig.update_layout(title_text='*Cost Incurred Over Time*', xaxis_title='Weeks', yaxis_title='Cost ($)',\n",
        "                          paper_bgcolor='rgba(0,0,0,0)', height=580)\n",
        "        fig.update_xaxes(range=[0, WEEKS_TO_PLAY])\n",
        "        fig.show()\n",
        "        return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "45gBZ0mB2W7C"
      },
      "source": [
        "# Main"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 20,
      "metadata": {
        "scrolled": true,
        "colab": {
          "base_uri": "https://localhost:8080/",
          "height": 1000
        },
        "id": "0tuSSB_N2W7C",
        "outputId": "65f7af48-6519-480e-f24f-af1459440699"
      },
      "outputs": [
        {
          "output_type": "stream",
          "name": "stdout",
          "text": [
            "\n",
            " -------------------------------------------------\n",
            " Week 0\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 13.5\n",
            "Retailer Order: 4\n",
            "Retailer Effective Inventory: 12\n",
            "Wholesaler Cost: 13.5\n",
            "Wholesaler Order: 4\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 13.5\n",
            "Distributor Order: 4\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 13.5\n",
            "Factory Order: 4\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 1\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 34.5\n",
            "Retailer Order: 4\n",
            "Retailer Effective Inventory: 12\n",
            "Wholesaler Cost: 34.5\n",
            "Wholesaler Order: 4\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 34.5\n",
            "Distributor Order: 4\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 34.5\n",
            "Factory Order: 4\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 2\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 62.5\n",
            "Retailer Order: 4\n",
            "Retailer Effective Inventory: 11\n",
            "Wholesaler Cost: 61.5\n",
            "Wholesaler Order: 4\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 61.5\n",
            "Distributor Order: 4\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 61.5\n",
            "Factory Order: 4\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 3\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 97.5\n",
            "Retailer Order: 4\n",
            "Retailer Effective Inventory: 10\n",
            "Wholesaler Cost: 94.5\n",
            "Wholesaler Order: 4\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 94.5\n",
            "Distributor Order: 4\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 94.5\n",
            "Factory Order: 4\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 4\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 139.5\n",
            "Retailer Order: 4\n",
            "Retailer Effective Inventory: 9\n",
            "Wholesaler Cost: 133.5\n",
            "Wholesaler Order: 4\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 133.5\n",
            "Distributor Order: 4\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 133.5\n",
            "Factory Order: 4\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 5\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 143.5\n",
            "Retailer Order: 4.0\n",
            "Retailer Effective Inventory: 8\n",
            "Wholesaler Cost: 139.5\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 12\n",
            "Distributor Cost: 139.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 12\n",
            "Factory Cost: 139.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 12\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 6\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 145.0\n",
            "Retailer Order: 9.0\n",
            "Retailer Effective Inventory: 3\n",
            "Wholesaler Cost: 145.5\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 12.0\n",
            "Distributor Cost: 147.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 16\n",
            "Factory Cost: 147.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 7\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 155.0\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 20\n",
            "Wholesaler Cost: 160.0\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 29.0\n",
            "Distributor Cost: 168.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 155.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 8\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 162.5\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 15.0\n",
            "Wholesaler Cost: 174.5\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 29.0\n",
            "Distributor Cost: 189.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 163.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 9\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 170.0\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 15.0\n",
            "Wholesaler Cost: 189.0\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 29.0\n",
            "Distributor Cost: 210.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 171.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 10\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 173.0\n",
            "Retailer Order: 6.0\n",
            "Retailer Effective Inventory: 6.0\n",
            "Wholesaler Cost: 203.5\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 29.0\n",
            "Distributor Cost: 231.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 179.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 11\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 176.0\n",
            "Retailer Order: 13.5\n",
            "Retailer Effective Inventory: -3.0\n",
            "Wholesaler Cost: 215.0\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 23.0\n",
            "Distributor Cost: 252.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 187.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 12\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 188.0\n",
            "Retailer Order: 18.0\n",
            "Retailer Effective Inventory: -12.0\n",
            "Wholesaler Cost: 219.75\n",
            "Wholesaler Order: 2.5\n",
            "Wholesaler Effective Inventory: 9.5\n",
            "Distributor Cost: 273.5\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 42\n",
            "Factory Cost: 195.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 13\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 203.0\n",
            "Retailer Order: 19.5\n",
            "Retailer Effective Inventory: -15.0\n",
            "Wholesaler Cost: 228.25\n",
            "Wholesaler Order: 16.25\n",
            "Wholesaler Effective Inventory: -8.5\n",
            "Distributor Cost: 293.25\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 39.5\n",
            "Factory Cost: 203.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 14\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 213.5\n",
            "Retailer Order: 17.25\n",
            "Retailer Effective Inventory: -10.5\n",
            "Wholesaler Cost: 256.25\n",
            "Wholesaler Order: 26.0\n",
            "Wholesaler Effective Inventory: -28.0\n",
            "Distributor Cost: 304.875\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 23.25\n",
            "Factory Cost: 211.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 15\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 223.5\n",
            "Retailer Order: 17.0\n",
            "Retailer Effective Inventory: -10.0\n",
            "Wholesaler Cost: 299.0\n",
            "Wholesaler Order: 33.375\n",
            "Wholesaler Effective Inventory: -42.75\n",
            "Distributor Cost: 307.625\n",
            "Distributor Order: 13.375\n",
            "Distributor Effective Inventory: -2.75\n",
            "Factory Cost: 219.5\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 16\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 16\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 242.5\n",
            "Retailer Order: 21.5\n",
            "Retailer Effective Inventory: -19.0\n",
            "Wholesaler Cost: 342.5\n",
            "Wholesaler Order: 33.75\n",
            "Wholesaler Effective Inventory: -43.5\n",
            "Distributor Cost: 343.75\n",
            "Distributor Order: 30.0625\n",
            "Distributor Effective Inventory: -36.125\n",
            "Factory Cost: 220.8125\n",
            "Factory Order: 9.375\n",
            "Factory Effective Inventory: 2.625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 17\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 268.0\n",
            "Retailer Order: 24.75\n",
            "Retailer Effective Inventory: -25.5\n",
            "Wholesaler Cost: 384.25\n",
            "Wholesaler Order: 32.875\n",
            "Wholesaler Effective Inventory: -41.75\n",
            "Distributor Cost: 413.625\n",
            "Distributor Order: 46.9375\n",
            "Distributor Effective Inventory: -69.875\n",
            "Factory Cost: 248.25\n",
            "Factory Order: 25.71875\n",
            "Factory Effective Inventory: -27.4375\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 18\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 286.25\n",
            "Retailer Order: 21.125\n",
            "Retailer Effective Inventory: -18.25\n",
            "Wholesaler Cost: 450.75\n",
            "Wholesaler Order: 45.25\n",
            "Wholesaler Effective Inventory: -66.5\n",
            "Distributor Cost: 503.0\n",
            "Distributor Order: 56.6875\n",
            "Distributor Effective Inventory: -89.375\n",
            "Factory Cost: 313.25\n",
            "Factory Order: 44.5\n",
            "Factory Effective Inventory: -65.0\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 19\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 290.25\n",
            "Retailer Order: 14.0\n",
            "Retailer Effective Inventory: -4.0\n",
            "Wholesaler Cost: 538.375\n",
            "Wholesaler Order: 55.8125\n",
            "Wholesaler Effective Inventory: -87.625\n",
            "Distributor Cost: 635.0\n",
            "Distributor Order: 78.0\n",
            "Distributor Effective Inventory: -132.0\n",
            "Factory Cost: 409.21875\n",
            "Factory Order: 59.984375\n",
            "Factory Effective Inventory: -95.96875\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 20\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 303.25\n",
            "Retailer Order: 18.5\n",
            "Retailer Effective Inventory: -13.0\n",
            "Wholesaler Cost: 626.625\n",
            "Wholesaler Order: 56.125\n",
            "Wholesaler Effective Inventory: -88.25\n",
            "Distributor Cost: 813.4375\n",
            "Distributor Order: 101.21875\n",
            "Distributor Effective Inventory: -178.4375\n",
            "Factory Cost: 538.6875\n",
            "Factory Order: 76.734375\n",
            "Factory Effective Inventory: -129.46875\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 21\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 325.25\n",
            "Retailer Order: 23.0\n",
            "Retailer Effective Inventory: -22.0\n",
            "Wholesaler Cost: 730.75\n",
            "Wholesaler Order: 64.0625\n",
            "Wholesaler Effective Inventory: -104.125\n",
            "Distributor Cost: 1022.28125\n",
            "Distributor Order: 116.421875\n",
            "Distributor Effective Inventory: -208.84375\n",
            "Factory Cost: 709.390625\n",
            "Factory Order: 97.3515625\n",
            "Factory Effective Inventory: -170.703125\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 22\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 342.875\n",
            "Retailer Order: 20.8125\n",
            "Retailer Effective Inventory: -17.625\n",
            "Wholesaler Cost: 848.5\n",
            "Wholesaler Order: 70.875\n",
            "Wholesaler Effective Inventory: -117.75\n",
            "Distributor Cost: 1250.6875\n",
            "Distributor Order: 126.203125\n",
            "Distributor Effective Inventory: -228.40625\n",
            "Factory Cost: 919.78125\n",
            "Factory Order: 117.1953125\n",
            "Factory Effective Inventory: -210.390625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 23\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 366.875\n",
            "Retailer Order: 24.0\n",
            "Retailer Effective Inventory: -24.0\n",
            "Wholesaler Cost: 961.34375\n",
            "Wholesaler Order: 68.421875\n",
            "Wholesaler Effective Inventory: -112.84375\n",
            "Distributor Cost: 1489.984375\n",
            "Distributor Order: 131.6484375\n",
            "Distributor Effective Inventory: -239.296875\n",
            "Factory Cost: 1159.0234375\n",
            "Factory Order: 131.62109375\n",
            "Factory Effective Inventory: -239.2421875\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 24\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 390.5\n",
            "Retailer Order: 23.8125\n",
            "Retailer Effective Inventory: -23.625\n",
            "Wholesaler Cost: 1053.6875\n",
            "Wholesaler Order: 58.171875\n",
            "Wholesaler Effective Inventory: -92.34375\n",
            "Distributor Cost: 1720.96875\n",
            "Distributor Order: 127.4921875\n",
            "Distributor Effective Inventory: -230.984375\n",
            "Factory Cost: 1412.71875\n",
            "Factory Order: 138.84765625\n",
            "Factory Effective Inventory: -253.6953125\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 25\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 397.40625\n",
            "Retailer Order: 15.453125\n",
            "Retailer Effective Inventory: -6.90625\n",
            "Wholesaler Cost: 1109.859375\n",
            "Wholesaler Order: 40.0859375\n",
            "Wholesaler Effective Inventory: -56.171875\n",
            "Distributor Cost: 1912.7734375\n",
            "Distributor Order: 107.90234375\n",
            "Distributor Effective Inventory: -191.8046875\n",
            "Factory Cost: 1662.28515625\n",
            "Factory Order: 136.783203125\n",
            "Factory Effective Inventory: -249.56640625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 26\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 411.703125\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 28.59375\n",
            "Wholesaler Cost: 1112.4140625\n",
            "Wholesaler Order: 6.890625\n",
            "Wholesaler Effective Inventory: 5.109375\n",
            "Distributor Cost: 2027.46875\n",
            "Distributor Order: 69.34765625\n",
            "Distributor Effective Inventory: -114.6953125\n",
            "Factory Cost: 1880.90625\n",
            "Factory Order: 121.310546875\n",
            "Factory Effective Inventory: -218.62109375\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 27\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 451.4921875\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 79.578125\n",
            "Wholesaler Cost: 1163.64453125\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 102.4609375\n",
            "Distributor Cost: 2032.486328125\n",
            "Distributor Order: 1.96484375\n",
            "Distributor Effective Inventory: 10.03515625\n",
            "Factory Cost: 2032.091796875\n",
            "Factory Order: 87.5927734375\n",
            "Factory Effective Inventory: -151.185546875\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 28\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 522.59375\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 142.203125\n",
            "Wholesaler Cost: 1273.47265625\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 219.65625\n",
            "Distributor Cost: 2106.927734375\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 148.8828125\n",
            "Factory Cost: 2063.931640625\n",
            "Factory Order: 27.919921875\n",
            "Factory Effective Inventory: -31.83984375\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 29\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 589.1953125\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 133.203125\n",
            "Wholesaler Cost: 1444.09375\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 2249.7607421875\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 285.666015625\n",
            "Factory Cost: 2091.80810546875\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 55.7529296875\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 30\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 651.296875\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 124.203125\n",
            "Wholesaler Cost: 1614.71484375\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 2453.2490234375\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 406.9765625\n",
            "Factory Cost: 2133.64453125\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 31\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 708.8984375\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 115.203125\n",
            "Wholesaler Cost: 1785.3359375\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 2672.6572265625\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2175.48095703125\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 32\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 762.0\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 106.203125\n",
            "Wholesaler Cost: 1955.95703125\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 2892.0654296875\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2217.3173828125\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 33\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 810.6015625\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 97.203125\n",
            "Wholesaler Cost: 2126.578125\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 3111.4736328125\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2259.15380859375\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 34\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 854.703125\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 88.203125\n",
            "Wholesaler Cost: 2297.19921875\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 3330.8818359375\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2300.990234375\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 35\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 894.3046875\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 79.203125\n",
            "Wholesaler Cost: 2467.8203125\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 3550.2900390625\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2342.82666015625\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 36\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 929.40625\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 70.203125\n",
            "Wholesaler Cost: 2638.44140625\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 3769.6982421875\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2384.6630859375\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 37\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 960.0078125\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 61.203125\n",
            "Wholesaler Cost: 2809.0625\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 3989.1064453125\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2426.49951171875\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 38\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 986.109375\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 52.203125\n",
            "Wholesaler Cost: 2979.68359375\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 4208.5146484375\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2468.3359375\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 39\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 1007.7109375\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 43.203125\n",
            "Wholesaler Cost: 3150.3046875\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 4427.9228515625\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2510.17236328125\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            " -------------------------------------------------\n",
            " Week 40\n",
            "-------------------------------------------------\n",
            "Retailer Cost: 1024.8125\n",
            "Retailer Order: 0.0\n",
            "Retailer Effective Inventory: 34.203125\n",
            "Wholesaler Cost: 3320.92578125\n",
            "Wholesaler Order: 0.0\n",
            "Wholesaler Effective Inventory: 341.2421875\n",
            "Distributor Cost: 4647.3310546875\n",
            "Distributor Order: 0.0\n",
            "Distributor Effective Inventory: 438.81640625\n",
            "Factory Cost: 2552.0087890625\n",
            "Factory Order: 0.0\n",
            "Factory Effective Inventory: 83.6728515625\n",
            "\n",
            "--- Final Statistics ----\n",
            "Beer received by customer: 365.0\n"
          ]
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<html>\n",
              "<head><meta charset=\"utf-8\" /></head>\n",
              "<body>\n",
              "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
              "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"a69d5d85-a89c-4cb1-95d5-0a8d35301529\" class=\"plotly-graph-div\" style=\"height:580px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"a69d5d85-a89c-4cb1-95d5-0a8d35301529\")) {                    Plotly.newPlot(                        \"a69d5d85-a89c-4cb1-95d5-0a8d35301529\",                        [{\"marker\":{\"color\":\"rgb(215,48,39)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Retailer Orders\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[4,4,4,4,4,4.0,9.0,0.0,0.0,0.0,6.0,13.5,18.0,19.5,17.25,17.0,21.5,24.75,21.125,14.0,18.5,23.0,20.8125,24.0,23.8125,15.453125,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(255,186,0)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Wholesaler Orders\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[4,4,4,4,4,0.0,0.0,0.0,0.0,0.0,0.0,0.0,2.5,16.25,26.0,33.375,33.75,32.875,45.25,55.8125,56.125,64.0625,70.875,68.421875,58.171875,40.0859375,6.890625,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(126,2,114)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Distributor Orders\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[4,4,4,4,4,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,13.375,30.0625,46.9375,56.6875,78.0,101.21875,116.421875,126.203125,131.6484375,127.4921875,107.90234375,69.34765625,1.96484375,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(69,117,180)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Factory Orders\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[4,4,4,4,4,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,9.375,25.71875,44.5,59.984375,76.734375,97.3515625,117.1953125,131.62109375,138.84765625,136.783203125,121.310546875,87.5927734375,27.919921875,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0],\"type\":\"scatter\"}],                        {\"template\":{\"data\":{\"histogram2dcontour\":[{\"type\":\"histogram2dcontour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"choropleth\":[{\"type\":\"choropleth\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"histogram2d\":[{\"type\":\"histogram2d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmap\":[{\"type\":\"heatmap\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmapgl\":[{\"type\":\"heatmapgl\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"contourcarpet\":[{\"type\":\"contourcarpet\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"contour\":[{\"type\":\"contour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"surface\":[{\"type\":\"surface\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"mesh3d\":[{\"type\":\"mesh3d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"parcoords\":[{\"type\":\"parcoords\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolargl\":[{\"type\":\"scatterpolargl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"scattergeo\":[{\"type\":\"scattergeo\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolar\":[{\"type\":\"scatterpolar\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"scattergl\":[{\"type\":\"scattergl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatter3d\":[{\"type\":\"scatter3d\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattermapbox\":[{\"type\":\"scattermapbox\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterternary\":[{\"type\":\"scatterternary\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattercarpet\":[{\"type\":\"scattercarpet\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}],\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}]},\"layout\":{\"autotypenumbers\":\"strict\",\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"hovermode\":\"closest\",\"hoverlabel\":{\"align\":\"left\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"#E5ECF6\",\"polar\":{\"bgcolor\":\"#E5ECF6\",\"angularaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"radialaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"ternary\":{\"bgcolor\":\"#E5ECF6\",\"aaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"caxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]]},\"xaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"yaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"yaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"zaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"geo\":{\"bgcolor\":\"white\",\"landcolor\":\"#E5ECF6\",\"subunitcolor\":\"white\",\"showland\":true,\"showlakes\":true,\"lakecolor\":\"white\"},\"title\":{\"x\":0.05},\"mapbox\":{\"style\":\"light\"}}},\"title\":{\"text\":\"*Orders Placed Over Time*\"},\"xaxis\":{\"title\":{\"text\":\"Weeks\"},\"range\":[0,41]},\"yaxis\":{\"title\":{\"text\":\"Orders\"}},\"paper_bgcolor\":\"rgba(0,0,0,0)\",\"height\":580},                        {\"responsive\": true}                    ).then(function(){\n",
              "                            \n",
              "var gd = document.getElementById('a69d5d85-a89c-4cb1-95d5-0a8d35301529');\n",
              "var x = new MutationObserver(function (mutations, observer) {{\n",
              "        var display = window.getComputedStyle(gd).display;\n",
              "        if (!display || display === 'none') {{\n",
              "            console.log([gd, 'removed!']);\n",
              "            Plotly.purge(gd);\n",
              "            observer.disconnect();\n",
              "        }}\n",
              "}});\n",
              "\n",
              "// Listen for the removal of the full notebook cells\n",
              "var notebookContainer = gd.closest('#notebook-container');\n",
              "if (notebookContainer) {{\n",
              "    x.observe(notebookContainer, {childList: true});\n",
              "}}\n",
              "\n",
              "// Listen for the clearing of the current output cell\n",
              "var outputEl = gd.closest('.output');\n",
              "if (outputEl) {{\n",
              "    x.observe(outputEl, {childList: true});\n",
              "}}\n",
              "\n",
              "                        })                };                            </script>        </div>\n",
              "</body>\n",
              "</html>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<html>\n",
              "<head><meta charset=\"utf-8\" /></head>\n",
              "<body>\n",
              "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
              "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"daeee25f-ccb0-4ce8-802c-0b75f64c0916\" class=\"plotly-graph-div\" style=\"height:580px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"daeee25f-ccb0-4ce8-802c-0b75f64c0916\")) {                    Plotly.newPlot(                        \"daeee25f-ccb0-4ce8-802c-0b75f64c0916\",                        [{\"marker\":{\"color\":\"rgb(215,48,39)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Retailer Inventory\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[12,12,11,10,9,8,3,20,15.0,15.0,6.0,-3.0,-12.0,-15.0,-10.5,-10.0,-19.0,-25.5,-18.25,-4.0,-13.0,-22.0,-17.625,-24.0,-23.625,-6.90625,28.59375,79.578125,142.203125,133.203125,124.203125,115.203125,106.203125,97.203125,88.203125,79.203125,70.203125,61.203125,52.203125,43.203125,34.203125],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(255,186,0)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Wholesaler Inventory\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[12,12,12,12,12,12,12.0,29.0,29.0,29.0,29.0,23.0,9.5,-8.5,-28.0,-42.75,-43.5,-41.75,-66.5,-87.625,-88.25,-104.125,-117.75,-112.84375,-92.34375,-56.171875,5.109375,102.4609375,219.65625,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875,341.2421875],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(126,2,114)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Distributor Inventory\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[12,12,12,12,12,12,16,42,42,42,42,42,42,39.5,23.25,-2.75,-36.125,-69.875,-89.375,-132.0,-178.4375,-208.84375,-228.40625,-239.296875,-230.984375,-191.8046875,-114.6953125,10.03515625,148.8828125,285.666015625,406.9765625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625,438.81640625],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(69,117,180)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Factory Inventory\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[12,12,12,12,12,12,16,16,16,16,16,16,16,16,16,16,2.625,-27.4375,-65.0,-95.96875,-129.46875,-170.703125,-210.390625,-239.2421875,-253.6953125,-249.56640625,-218.62109375,-151.185546875,-31.83984375,55.7529296875,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625,83.6728515625],\"type\":\"scatter\"}],                        {\"template\":{\"data\":{\"histogram2dcontour\":[{\"type\":\"histogram2dcontour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"choropleth\":[{\"type\":\"choropleth\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"histogram2d\":[{\"type\":\"histogram2d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmap\":[{\"type\":\"heatmap\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmapgl\":[{\"type\":\"heatmapgl\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"contourcarpet\":[{\"type\":\"contourcarpet\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"contour\":[{\"type\":\"contour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"surface\":[{\"type\":\"surface\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"mesh3d\":[{\"type\":\"mesh3d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"parcoords\":[{\"type\":\"parcoords\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolargl\":[{\"type\":\"scatterpolargl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"scattergeo\":[{\"type\":\"scattergeo\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolar\":[{\"type\":\"scatterpolar\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"scattergl\":[{\"type\":\"scattergl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatter3d\":[{\"type\":\"scatter3d\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattermapbox\":[{\"type\":\"scattermapbox\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterternary\":[{\"type\":\"scatterternary\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattercarpet\":[{\"type\":\"scattercarpet\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}],\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}]},\"layout\":{\"autotypenumbers\":\"strict\",\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"hovermode\":\"closest\",\"hoverlabel\":{\"align\":\"left\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"#E5ECF6\",\"polar\":{\"bgcolor\":\"#E5ECF6\",\"angularaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"radialaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"ternary\":{\"bgcolor\":\"#E5ECF6\",\"aaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"caxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]]},\"xaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"yaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"yaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"zaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"geo\":{\"bgcolor\":\"white\",\"landcolor\":\"#E5ECF6\",\"subunitcolor\":\"white\",\"showland\":true,\"showlakes\":true,\"lakecolor\":\"white\"},\"title\":{\"x\":0.05},\"mapbox\":{\"style\":\"light\"}}},\"title\":{\"text\":\"*Effective Inventory Over Time*\"},\"xaxis\":{\"title\":{\"text\":\"Weeks\"},\"range\":[0,41]},\"yaxis\":{\"title\":{\"text\":\"Effective Inventory\"}},\"paper_bgcolor\":\"rgba(0,0,0,0)\",\"height\":580},                        {\"responsive\": true}                    ).then(function(){\n",
              "                            \n",
              "var gd = document.getElementById('daeee25f-ccb0-4ce8-802c-0b75f64c0916');\n",
              "var x = new MutationObserver(function (mutations, observer) {{\n",
              "        var display = window.getComputedStyle(gd).display;\n",
              "        if (!display || display === 'none') {{\n",
              "            console.log([gd, 'removed!']);\n",
              "            Plotly.purge(gd);\n",
              "            observer.disconnect();\n",
              "        }}\n",
              "}});\n",
              "\n",
              "// Listen for the removal of the full notebook cells\n",
              "var notebookContainer = gd.closest('#notebook-container');\n",
              "if (notebookContainer) {{\n",
              "    x.observe(notebookContainer, {childList: true});\n",
              "}}\n",
              "\n",
              "// Listen for the clearing of the current output cell\n",
              "var outputEl = gd.closest('.output');\n",
              "if (outputEl) {{\n",
              "    x.observe(outputEl, {childList: true});\n",
              "}}\n",
              "\n",
              "                        })                };                            </script>        </div>\n",
              "</body>\n",
              "</html>"
            ]
          },
          "metadata": {}
        },
        {
          "output_type": "display_data",
          "data": {
            "text/html": [
              "<html>\n",
              "<head><meta charset=\"utf-8\" /></head>\n",
              "<body>\n",
              "    <div>            <script src=\"https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS-MML_SVG\"></script><script type=\"text/javascript\">if (window.MathJax && window.MathJax.Hub && window.MathJax.Hub.Config) {window.MathJax.Hub.Config({SVG: {font: \"STIX-Web\"}});}</script>                <script type=\"text/javascript\">window.PlotlyConfig = {MathJaxConfig: 'local'};</script>\n",
              "        <script charset=\"utf-8\" src=\"https://cdn.plot.ly/plotly-2.35.2.min.js\"></script>                <div id=\"7d150662-abe5-49aa-8b18-5c780da5d703\" class=\"plotly-graph-div\" style=\"height:580px; width:100%;\"></div>            <script type=\"text/javascript\">                                    window.PLOTLYENV=window.PLOTLYENV || {};                                    if (document.getElementById(\"7d150662-abe5-49aa-8b18-5c780da5d703\")) {                    Plotly.newPlot(                        \"7d150662-abe5-49aa-8b18-5c780da5d703\",                        [{\"marker\":{\"color\":\"rgb(215,48,39)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Retailer Total Cost\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[13.5,34.5,62.5,97.5,139.5,143.5,145.0,155.0,162.5,170.0,173.0,176.0,188.0,203.0,213.5,223.5,242.5,268.0,286.25,290.25,303.25,325.25,342.875,366.875,390.5,397.40625,411.703125,451.4921875,522.59375,589.1953125,651.296875,708.8984375,762.0,810.6015625,854.703125,894.3046875,929.40625,960.0078125,986.109375,1007.7109375,1024.8125],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(255,186,0)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Wholesaler Total Cost\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[13.5,34.5,61.5,94.5,133.5,139.5,145.5,160.0,174.5,189.0,203.5,215.0,219.75,228.25,256.25,299.0,342.5,384.25,450.75,538.375,626.625,730.75,848.5,961.34375,1053.6875,1109.859375,1112.4140625,1163.64453125,1273.47265625,1444.09375,1614.71484375,1785.3359375,1955.95703125,2126.578125,2297.19921875,2467.8203125,2638.44140625,2809.0625,2979.68359375,3150.3046875,3320.92578125],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(126,2,114)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Distributor Total Cost\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[13.5,34.5,61.5,94.5,133.5,139.5,147.5,168.5,189.5,210.5,231.5,252.5,273.5,293.25,304.875,307.625,343.75,413.625,503.0,635.0,813.4375,1022.28125,1250.6875,1489.984375,1720.96875,1912.7734375,2027.46875,2032.486328125,2106.927734375,2249.7607421875,2453.2490234375,2672.6572265625,2892.0654296875,3111.4736328125,3330.8818359375,3550.2900390625,3769.6982421875,3989.1064453125,4208.5146484375,4427.9228515625,4647.3310546875],\"type\":\"scatter\"},{\"marker\":{\"color\":\"rgb(69,117,180)\",\"size\":5},\"mode\":\"lines+markers\",\"name\":\"Factory Total Cost\",\"x\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42],\"y\":[13.5,34.5,61.5,94.5,133.5,139.5,147.5,155.5,163.5,171.5,179.5,187.5,195.5,203.5,211.5,219.5,220.8125,248.25,313.25,409.21875,538.6875,709.390625,919.78125,1159.0234375,1412.71875,1662.28515625,1880.90625,2032.091796875,2063.931640625,2091.80810546875,2133.64453125,2175.48095703125,2217.3173828125,2259.15380859375,2300.990234375,2342.82666015625,2384.6630859375,2426.49951171875,2468.3359375,2510.17236328125,2552.0087890625],\"type\":\"scatter\"}],                        {\"template\":{\"data\":{\"histogram2dcontour\":[{\"type\":\"histogram2dcontour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"choropleth\":[{\"type\":\"choropleth\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"histogram2d\":[{\"type\":\"histogram2d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmap\":[{\"type\":\"heatmap\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"heatmapgl\":[{\"type\":\"heatmapgl\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"contourcarpet\":[{\"type\":\"contourcarpet\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"contour\":[{\"type\":\"contour\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"surface\":[{\"type\":\"surface\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"},\"colorscale\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]]}],\"mesh3d\":[{\"type\":\"mesh3d\",\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}],\"scatter\":[{\"fillpattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2},\"type\":\"scatter\"}],\"parcoords\":[{\"type\":\"parcoords\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolargl\":[{\"type\":\"scatterpolargl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"bar\":[{\"error_x\":{\"color\":\"#2a3f5f\"},\"error_y\":{\"color\":\"#2a3f5f\"},\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"bar\"}],\"scattergeo\":[{\"type\":\"scattergeo\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterpolar\":[{\"type\":\"scatterpolar\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"histogram\":[{\"marker\":{\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"histogram\"}],\"scattergl\":[{\"type\":\"scattergl\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatter3d\":[{\"type\":\"scatter3d\",\"line\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattermapbox\":[{\"type\":\"scattermapbox\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scatterternary\":[{\"type\":\"scatterternary\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"scattercarpet\":[{\"type\":\"scattercarpet\",\"marker\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}}}],\"carpet\":[{\"aaxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"baxis\":{\"endlinecolor\":\"#2a3f5f\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"minorgridcolor\":\"white\",\"startlinecolor\":\"#2a3f5f\"},\"type\":\"carpet\"}],\"table\":[{\"cells\":{\"fill\":{\"color\":\"#EBF0F8\"},\"line\":{\"color\":\"white\"}},\"header\":{\"fill\":{\"color\":\"#C8D4E3\"},\"line\":{\"color\":\"white\"}},\"type\":\"table\"}],\"barpolar\":[{\"marker\":{\"line\":{\"color\":\"#E5ECF6\",\"width\":0.5},\"pattern\":{\"fillmode\":\"overlay\",\"size\":10,\"solidity\":0.2}},\"type\":\"barpolar\"}],\"pie\":[{\"automargin\":true,\"type\":\"pie\"}]},\"layout\":{\"autotypenumbers\":\"strict\",\"colorway\":[\"#636efa\",\"#EF553B\",\"#00cc96\",\"#ab63fa\",\"#FFA15A\",\"#19d3f3\",\"#FF6692\",\"#B6E880\",\"#FF97FF\",\"#FECB52\"],\"font\":{\"color\":\"#2a3f5f\"},\"hovermode\":\"closest\",\"hoverlabel\":{\"align\":\"left\"},\"paper_bgcolor\":\"white\",\"plot_bgcolor\":\"#E5ECF6\",\"polar\":{\"bgcolor\":\"#E5ECF6\",\"angularaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"radialaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"ternary\":{\"bgcolor\":\"#E5ECF6\",\"aaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"baxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"},\"caxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\"}},\"coloraxis\":{\"colorbar\":{\"outlinewidth\":0,\"ticks\":\"\"}},\"colorscale\":{\"sequential\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"sequentialminus\":[[0.0,\"#0d0887\"],[0.1111111111111111,\"#46039f\"],[0.2222222222222222,\"#7201a8\"],[0.3333333333333333,\"#9c179e\"],[0.4444444444444444,\"#bd3786\"],[0.5555555555555556,\"#d8576b\"],[0.6666666666666666,\"#ed7953\"],[0.7777777777777778,\"#fb9f3a\"],[0.8888888888888888,\"#fdca26\"],[1.0,\"#f0f921\"]],\"diverging\":[[0,\"#8e0152\"],[0.1,\"#c51b7d\"],[0.2,\"#de77ae\"],[0.3,\"#f1b6da\"],[0.4,\"#fde0ef\"],[0.5,\"#f7f7f7\"],[0.6,\"#e6f5d0\"],[0.7,\"#b8e186\"],[0.8,\"#7fbc41\"],[0.9,\"#4d9221\"],[1,\"#276419\"]]},\"xaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"yaxis\":{\"gridcolor\":\"white\",\"linecolor\":\"white\",\"ticks\":\"\",\"title\":{\"standoff\":15},\"zerolinecolor\":\"white\",\"automargin\":true,\"zerolinewidth\":2},\"scene\":{\"xaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"yaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2},\"zaxis\":{\"backgroundcolor\":\"#E5ECF6\",\"gridcolor\":\"white\",\"linecolor\":\"white\",\"showbackground\":true,\"ticks\":\"\",\"zerolinecolor\":\"white\",\"gridwidth\":2}},\"shapedefaults\":{\"line\":{\"color\":\"#2a3f5f\"}},\"annotationdefaults\":{\"arrowcolor\":\"#2a3f5f\",\"arrowhead\":0,\"arrowwidth\":1},\"geo\":{\"bgcolor\":\"white\",\"landcolor\":\"#E5ECF6\",\"subunitcolor\":\"white\",\"showland\":true,\"showlakes\":true,\"lakecolor\":\"white\"},\"title\":{\"x\":0.05},\"mapbox\":{\"style\":\"light\"}}},\"title\":{\"text\":\"*Cost Incurred Over Time*\"},\"xaxis\":{\"title\":{\"text\":\"Weeks\"},\"range\":[0,41]},\"yaxis\":{\"title\":{\"text\":\"Cost ($)\"}},\"paper_bgcolor\":\"rgba(0,0,0,0)\",\"height\":580},                        {\"responsive\": true}                    ).then(function(){\n",
              "                            \n",
              "var gd = document.getElementById('7d150662-abe5-49aa-8b18-5c780da5d703');\n",
              "var x = new MutationObserver(function (mutations, observer) {{\n",
              "        var display = window.getComputedStyle(gd).display;\n",
              "        if (!display || display === 'none') {{\n",
              "            console.log([gd, 'removed!']);\n",
              "            Plotly.purge(gd);\n",
              "            observer.disconnect();\n",
              "        }}\n",
              "}});\n",
              "\n",
              "// Listen for the removal of the full notebook cells\n",
              "var notebookContainer = gd.closest('#notebook-container');\n",
              "if (notebookContainer) {{\n",
              "    x.observe(notebookContainer, {childList: true});\n",
              "}}\n",
              "\n",
              "// Listen for the clearing of the current output cell\n",
              "var outputEl = gd.closest('.output');\n",
              "if (outputEl) {{\n",
              "    x.observe(outputEl, {childList: true});\n",
              "}}\n",
              "\n",
              "                        })                };                            </script>        </div>\n",
              "</body>\n",
              "</html>"
            ]
          },
          "metadata": {}
        }
      ],
      "source": [
        "# Initialize queues between each actor in the supply chain\n",
        "# Top and bottom queues simulate order (top) and delivery (bottom) flows between actors\n",
        "wholesalerRetailerTopQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "wholesalerRetailerBottomQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "\n",
        "distributorWholesalerTopQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "distributorWholesalerBottomQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "\n",
        "factoryDistributorTopQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "factoryDistributorBottomQueue = SupplyChainQueue(QUEUE_DELAY_WEEKS)\n",
        "\n",
        "# Populate queues with initial orders to stabilize early weeks of the game\n",
        "# Each actor's order and delivery queues are initialized with CUSTOMER_INITIAL_ORDERS\n",
        "for i in range(0, 2):\n",
        "    wholesalerRetailerTopQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "    wholesalerRetailerBottomQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "    distributorWholesalerTopQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "    distributorWholesalerBottomQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "    factoryDistributorTopQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "    factoryDistributorBottomQueue.PushEnvelope(CUSTOMER_INITIAL_ORDERS)\n",
        "\n",
        "# Instantiate the customer\n",
        "theCustomer = Customer()\n",
        "\n",
        "# Create Retailer, connected to the customer and wholesaler via queues\n",
        "myRetailer = Retailer(None, wholesalerRetailerTopQueue, wholesalerRetailerBottomQueue, None, theCustomer)\n",
        "\n",
        "# Create Wholesaler, connected to the retailer and distributor via queues\n",
        "myWholesaler = Wholesaler(wholesalerRetailerTopQueue, distributorWholesalerTopQueue,\n",
        "                          distributorWholesalerBottomQueue, wholesalerRetailerBottomQueue)\n",
        "\n",
        "# Create Distributor, connected to the wholesaler and factory via queues\n",
        "myDistributor = Distributor(distributorWholesalerTopQueue, factoryDistributorTopQueue,\n",
        "                            factoryDistributorBottomQueue, distributorWholesalerBottomQueue)\n",
        "\n",
        "# Create Factory, connected to the distributor via queues, with a production delay\n",
        "myFactory = Factory(factoryDistributorTopQueue, None, None, factoryDistributorBottomQueue, QUEUE_DELAY_WEEKS)\n",
        "\n",
        "# Initialize an object to track and record statistics across the simulation\n",
        "myStats = SupplyChainStatistics()\n",
        "\n",
        "# Simulation loop: Iterate over each week\n",
        "for thisWeek in range(0, WEEKS_TO_PLAY):\n",
        "\n",
        "    print(\"\\n\", \"-\" * 49)\n",
        "    print(f\" Week {thisWeek}\") # Print current week number\n",
        "    print(\"-\" * 49)\n",
        "\n",
        "    # Retailer's turn: process orders, calculate costs, and update inventory and statistics\n",
        "    myRetailer.TakeTurn(thisWeek)\n",
        "    myStats.RecordRetailerCost(myRetailer.GetCostIncurred())\n",
        "    myStats.RecordRetailerOrders(myRetailer.GetLastOrderQuantity())\n",
        "    myStats.RecordRetailerEffectiveInventory(myRetailer.CalcEffectiveInventory())\n",
        "\n",
        "    # Wholesaler's turn: process orders, calculate costs, and update inventory and statistics\n",
        "    myWholesaler.TakeTurn(thisWeek)\n",
        "    myStats.RecordWholesalerCost(myWholesaler.GetCostIncurred())\n",
        "    myStats.RecordWholesalerOrders(myWholesaler.GetLastOrderQuantity())\n",
        "    myStats.RecordWholesalerEffectiveInventory(myWholesaler.CalcEffectiveInventory())\n",
        "\n",
        "    # Distributor's turn: process orders, calculate costs, and update inventory and statistics\n",
        "    myDistributor.TakeTurn(thisWeek)\n",
        "    myStats.RecordDistributorCost(myDistributor.GetCostIncurred())\n",
        "    myStats.RecordDistributorOrders(myDistributor.GetLastOrderQuantity())\n",
        "    myStats.RecordDistributorEffectiveInventory(myDistributor.CalcEffectiveInventory())\n",
        "\n",
        "    # Factory's turn: process orders, produce beer, calculate costs, and update statistics\n",
        "    myFactory.TakeTurn(thisWeek)\n",
        "    myStats.RecordFactoryCost(myFactory.GetCostIncurred())\n",
        "    myStats.RecordFactoryOrders(myFactory.GetLastOrderQuantity())\n",
        "    myStats.RecordFactoryEffectiveInventory(myFactory.CalcEffectiveInventory())\n",
        "\n",
        "# Output final results after simulation\n",
        "print(\"\\n--- Final Statistics ----\")\n",
        "print(\"Beer received by customer: {0}\".format(theCustomer.GetBeerReceived()))\n",
        "\n",
        "# Plot time-series data for orders, inventory, and costs over the weeks of simulation\n",
        "myStats.PlotOrders()\n",
        "myStats.PlotEffectiveInventory()\n",
        "myStats.PlotCosts()"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "codemirror_mode": {
        "name": "ipython",
        "version": 3
      },
      "file_extension": ".py",
      "mimetype": "text/x-python",
      "name": "python",
      "nbconvert_exporter": "python",
      "pygments_lexer": "ipython3",
      "version": "3.8.3"
    },
    "colab": {
      "provenance": []
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}