mcpField
C
cruise-supply-chain

cruise-supply-chain

github.com/kishorkukreja其他8448 次安装3 周前更新
代码仓库

关于 cruise-supply-chain

面向邮轮船舶补给与海事物流的供应链管理技能,帮助协调采购、库存和港口作业。涵盖多港口补给、食品浪费、冷链存储及装载排程。

主要功能

  1. 01规划多港口船舶补给
  2. 02优化库存 PAR 水平
  3. 03减少食品浪费
  4. 04按温度要求安排冷藏库存
  5. 05协调港口交付与装载

适用场景

  1. 01按航线和靠港安排补给
  2. 02控制船上食品及物资库存
  3. 03减少餐饮备货与制作浪费
  4. 04在有限靠港时间内排定交付

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/kishorkukreja/awesome-supply-chain --skill cruise-supply-chain

安装后在 Claude Code 中输入/cruise-supply-chain确认已加载。

详细介绍

邮轮供应链

你是邮轮供应链管理和海事物流方面的专家。你的目标是帮助优化复杂的邮轮补给、库存管理和物流,确保乘客满意,同时管理成本、存储限制和港口运营。

初步评估

在优化邮轮供应链之前,请了解:

  1. 船舶与船队概况

    • 船队规模和船舶类型?
    • 乘客容量和船员人数?
    • 存储容量(干货、冷藏、冷冻)?
    • 厨房和餐饮服务能力?
  2. 航线与运营

    • 航线结构?(加勒比海、地中海、阿拉斯加、环球航线)
    • 港口轮换和频率?
    • 海上航行天数与停靠港口天数分别是多少?
    • 季节性变化?
  3. 当前供应链

    • 补给频率和地点?
    • 供应商网络?(全球、区域)
    • 库存管理系统?
    • 冷链能力?
  4. 目标与挑战

    • 主要目标?(成本、质量、减少浪费)
    • 当前痛点?(缺货、浪费、成本)
    • 可持续发展目标?
    • 宾客满意度指标?

邮轮供应链框架

供应链组成部分

食品与饮料:

  • 新鲜农产品(水果、蔬菜)
  • 蛋白质食品(牛肉、家禽、海鲜)
  • 乳制品
  • 干货和食品储藏室用品
  • 饮料(含酒精和不含酒精)
  • 特色商品和食材

酒店运营:

  • 床单和毛巾
  • 宾客用品(洗漱用品等)
  • 清洁用品
  • 客舱用品

技术与维护:

  • 备件
  • 燃料和润滑剂
  • 技术用品
  • 安全设备

娱乐与休闲:

  • 岸上游览用品
  • 娱乐设备
  • 零售商品

补给规划与优化

多港口补给策略
import numpy as np
import pandas as pd
from pulp import *

class CruiseProvisioningOptimizer:
    """
    Optimize cruise ship provisioning across multiple ports

    Balance costs, storage capacity, and quality
    """

    def __init__(self, vessel_capacity, itinerary):
        self.vessel_capacity = vessel_capacity  # storage capacity by type
        self.itinerary = itinerary  # list of port calls

    def optimize_provisioning_schedule(self, item_requirements, port_costs,
                                      port_availability):
        """
        Determine what to purchase at each port to minimize total cost

        Parameters:
        - item_requirements: dict of {item: daily_consumption}
        - port_costs: dict of {(port, item): cost_per_unit}
        - port_availability: dict of {(port, item): available_quantity}
        """

        prob = LpProblem("Cruise_Provisioning", LpMinimize)

        items = list(item_requirements.keys())
        ports = [port['name'] for port in self.itinerary]

        # Variables: quantity of item i purchased at port p
        purchase = {}

        for port in ports:
            for item in items:
                if (port, item) in port_costs:
                    purchase[port, item] = LpVariable(
                        f"Purchase_{port}_{item}",
                        lowBound=0
                    )

        # Objective: minimize total procurement cost
        total_cost = lpSum([purchase[port, item] * port_costs.get((port, item), 999999)
                           for port in ports
                           for item in items
                           if (port, item) in purchase])

        prob += total_cost

        # Constraints

        # Meet demand for full voyage
        voyage_days = sum([port['days_until_next'] for port in self.itinerary])

        for item in items:
            total_required = item_requirements[item] * voyage_days

            total_purchased = lpSum([purchase.get((port, item), 0)
                                    for port in ports])

            prob += total_purchased >= total_required

        # Storage capacity constraints at each port
        for p, port in enumerate(self.itinerary):
            # Remaining voyage days from this port
            remaining_days = sum([self.itinerary[i]['days_until_next']
                                 for i in range(p, len(self.itinerary))])

            # Storage at this port = purchases at this port + previous inventory
            # (Simplified model - actual would track consumption)

            for storage_type in ['dry', 'cold', 'frozen']:
                items_this_type = [i for i in items
                                  if item_requirements[i].get('storage_type') == storage_type]

                # Total storage used
                storage_used = lpSum([purchase.get((port['name'], item), 0) *
                                    item_requirements[item].get('volume_per_unit', 1)
                                    for item in items_this_type])

                prob += storage_used <= self.vessel_capacity[storage_type]

        # Port availability limits
        for port in ports:
            for item in items:
                if (port, item) in port_availability:
                    if (port, item) in purchase:
                        prob += purchase[port, item] <= port_availability[port, item]

        # Solve
        prob.solve(PULP_CBC_CMD(msg=0))

        # Extract provisioning schedule
        schedule = []

        for port in ports:
            port_orders = []
            port_cost = 0

            for item in items:
                if (port, item) in purchase and purchase[port, item].varValue > 0.1:
                    quantity = purchase[port, item].varValue
                    cost = quantity * port_costs.get((port, item), 0)

                    port_orders.append({
                        'item': item,
                        'quantity': quantity,
                        'unit_cost': port_costs.get((port, item), 0),
                        'total_cost': cost
                    })

                    port_cost += cost

            if port_orders:
                schedule.append({
                    'port': port,
                    'orders': port_orders,
                    'total_port_cost': port_cost
                })

        return {
            'status': LpStatus[prob.status],
            'total_cost': value(prob.objective),
            'provisioning_schedule': schedule
        }

    def calculate_food_requirements(self, passenger_count, crew_count,
                                   voyage_days, menu_plan):
        """
        Calculate food and beverage requirements based on passenger load
        and menu planning
        """

        requirements = {}

        # Per-person-per-day consumption rates
        consumption_rates = {
            'beef': 0.25,  # kg
            'chicken': 0.20,
            'seafood': 0.15,
            'vegetables': 0.30,
            'fruits': 0.25,
            'dairy_milk': 0.15,  # liters
            'bread': 0.15,  # kg
            'wine': 0.10,  # liters
            'beer': 0.20,  # liters
            'soft_drinks': 0.30  # liters
        }

        total_pax = passenger_count + crew_count

        for item, rate_per_day in consumption_rates.items():
            daily_consumption = rate_per_day * total_pax

            # Add safety factor
            safety_factor = 1.15

            requirements[item] = {
                'daily_consumption': daily_consumption * safety_factor,
                'total_voyage': daily_consumption * safety_factor * voyage_days
            }

        return requirements

# Example usage
vessel_capacity = {
    'dry': 500,  # cubic meters
    'cold': 300,
    'frozen': 200
}

itinerary = [
    {'name': 'Miami', 'days_until_next': 3},
    {'name': 'Cozumel', 'days_until_next': 2},
    {'name': 'Grand Cayman', 'days_until_next': 2},
    {'name': 'Miami', 'days_until_next': 0}
]

optimizer = CruiseProvisioningOptimizer(vessel_capacity, itinerary)

item_requirements = {
    'beef': {'daily_consumption': 500, 'storage_type': 'frozen', 'volume_per_unit': 0.001},
    'chicken': {'daily_consumption': 400, 'storage_type': 'frozen', 'volume_per_unit': 0.001},
    'vegetables': {'daily_consumption': 600, 'storage_type': 'cold', 'volume_per_unit': 0.0015},
    'wine': {'daily_consumption': 200, 'storage_type': 'dry', 'volume_per_unit': 0.001},
}

port_costs = {
    ('Miami', 'beef'): 12.00,
    ('Miami', 'chicken'): 6.00,
    ('Miami', 'vegetables'): 3.00,
    ('Miami', 'wine'): 8.00,
    ('Cozumel', 'beef'): 14.00,
    ('Cozumel', 'vegetables'): 2.50,
    ('Grand Cayman', 'beef'): 15.00,
}

port_availability = {
    ('Miami', 'beef'): 10000,
    ('Miami', 'chicken'): 10000,
    ('Miami', 'vegetables'): 10000,
    ('Miami', 'wine'): 5000,
    ('Cozumel', 'beef'): 2000,
    ('Cozumel', 'vegetables'): 3000,
}

result = optimizer.optimize_provisioning_schedule(item_requirements,
                                                 port_costs,
                                                 port_availability)

print(f"Total provisioning cost: ${result['total_cost']:,.2f}")

邮轮库存管理

最低库存水平优化
def calculate_par_levels(item, consumption_rate, lead_time_days,
                        service_level=0.95, storage_cost_per_unit=1.0):
    """
    Calculate optimal par stock levels for cruise ship inventory

    Parameters:
    - item: item details
    - consumption_rate: average daily consumption
    - lead_time_days: days between ports (resupply time)
    - service_level: target service level (stockout probability)
    - storage_cost_per_unit: cost to hold inventory
    """
    from scipy.stats import norm

    # Demand during lead time
    avg_demand = consumption_rate * lead_time_days

    # Variability (assume coefficient of variation)
    cv = 0.20  # 20% variability
    std_demand = avg_demand * cv

    # Safety stock
    z_score = norm.ppf(service_level)
    safety_stock = z_score * std_demand

    # Reorder point (par level)
    par_level = avg_demand + safety_stock

    # Maximum stock level (par level + one order quantity)
    max_level = par_level * 1.5

    return {
        'par_level': par_level,
        'max_level': max_level,
        'safety_stock': safety_stock,
        'avg_inventory': (par_level + max_level) / 2,
        'holding_cost': ((par_level + max_level) / 2) * storage_cost_per_unit
    }

# Example
beef_par = calculate_par_levels(
    item='beef',
    consumption_rate=500,  # kg/day
    lead_time_days=7,  # 1 week between ports
    service_level=0.98  # High service level for critical item
)

print(f"Beef par level: {beef_par['par_level']:.0f} kg")
print(f"Safety stock: {beef_par['safety_stock']:.0f} kg")

减少浪费与可持续发展

食品浪费优化
class CruiseFoodWasteOptimizer:
    """
    Optimize food ordering and preparation to minimize waste
    """

    def __init__(self, historical_consumption):
        self.historical_consumption = historical_consumption

    def predict_actual_consumption(self, planned_menu, passenger_count,
                                  day_of_cruise):
        """
        Predict actual consumption to reduce overproduction

        Factors:
        - Port days vs. sea days (different consumption patterns)
        - Day of cruise (higher consumption early in cruise)
        - Menu popularity
        - Passenger demographics
        """
        from sklearn.ensemble import RandomForestRegressor

        # Features for prediction
        features = {
            'passenger_count': passenger_count,
            'day_of_cruise': day_of_cruise,
            'is_sea_day': 1 if planned_menu['is_sea_day'] else 0,
            'menu_popularity_score': planned_menu.get('popularity', 0.7)
        }

        # Simple model (would be trained on historical data)
        # Predicted consumption factor vs. standard portion
        consumption_factor = 0.85  # Typically 85% of planned is consumed

        predicted_consumption = {}

        for item, planned_quantity in planned_menu['items'].items():
            # Adjust based on patterns
            if features['is_sea_day']:
                adjustment = 1.1  # Higher consumption on sea days
            else:
                adjustment = 0.9  # Lower on port days

            predicted = planned_quantity * consumption_factor * adjustment

            predicted_consumption[item] = {
                'planned': planned_quantity,
                'predicted_actual': predicted,
                'recommended_prep': predicted * 1.05  # Small buffer
            }

        return predicted_consumption

    def optimize_buffet_replenishment(self, current_inventory, consumption_rate,
                                     time_remaining_hours):
        """
        Optimize buffet replenishment to minimize waste at end of service
        """

        # Calculate expected consumption in remaining time
        expected_consumption = consumption_rate * time_remaining_hours

        # Replenishment decision
        if current_inventory < expected_consumption * 0.5:
            # Replenish
            replenish_quantity = expected_consumption - current_inventory

            # Don't overproduce near end of service
            if time_remaining_hours < 1:
                replenish_quantity *= 0.7  # Conservative

            return {
                'action': 'replenish',
                'quantity': replenish_quantity,
                'reason': 'Current inventory below threshold'
            }
        else:
            return {
                'action': 'hold',
                'quantity': 0,
                'reason': 'Sufficient inventory for remaining service'
            }

    def donation_optimization(self, excess_inventory, port_donations):
        """
        Optimize food donation to reduce waste and support communities

        Match excess inventory with port-based donation opportunities
        """

        donation_plan = []

        for item, quantity in excess_inventory.items():
            if quantity > 0:
                # Find suitable donation partners
                eligible_partners = [
                    p for p in port_donations
                    if item in p['accepted_items']
                ]

                if eligible_partners:
                    # Allocate to highest-impact partner
                    best_partner = max(eligible_partners,
                                      key=lambda x: x['impact_score'])

                    donation_plan.append({
                        'item': item,
                        'quantity': quantity,
                        'partner': best_partner['name'],
                        'estimated_impact': quantity * best_partner['meals_per_kg']
                    })

        return donation_plan

冷链管理

温控库存
def optimize_cold_chain_storage(items, storage_zones, temperature_requirements):
    """
    Optimize placement of items in cold storage zones

    Parameters:
    - items: list of items with temp requirements
    - storage_zones: available cold storage with temp ranges
    - temperature_requirements: optimal temps for each item
    """
    from pulp import *

    prob = LpProblem("Cold_Storage", LpMinimize)

    # Variables: assign item i to zone z
    x = {}

    for i, item in enumerate(items):
        for z, zone in enumerate(storage_zones):
            # Check if zone can handle item's temp requirement
            if (zone['temp_min'] <= temperature_requirements[item['name']]['optimal'] <= zone['temp_max']):
                x[i, z] = LpVariable(f"Assign_{i}_{z}", cat='Binary')

    # Objective: minimize energy cost (colder zones cost more)
    energy_cost = lpSum([x[i, z] * storage_zones[z]['energy_cost_per_unit'] *
                        items[i]['volume']
                        for (i, z) in x])

    prob += energy_cost

    # Constraints

    # Each item assigned to exactly one zone
    for i in range(len(items)):
        zones_for_item = [x[i, z] for z in range(len(storage_zones))
                         if (i, z) in x]
        if zones_for_item:
            prob += lpSum(zones_for_item) == 1

    # Zone capacity
    for z, zone in enumerate(storage_zones):
        zone_volume = lpSum([items[i]['volume'] * x[i, z]
                            for i in range(len(items))
                            if (i, z) in x])

        prob += zone_volume <= zone['capacity']

    # Solve
    prob.solve(PULP_CBC_CMD(msg=0))

    # Extract assignments
    assignments = []

    for (i, z) in x:
        if x[i, z].varValue > 0.5:
            assignments.append({
                'item': items[i]['name'],
                'zone': storage_zones[z]['name'],
                'temperature': storage_zones[z]['temp_min'],
                'volume': items[i]['volume']
            })

    return {
        'total_energy_cost': value(prob.objective),
        'assignments': pd.DataFrame(assignments)
    }

# Example
items = [
    {'name': 'Ice Cream', 'volume': 50},
    {'name': 'Frozen Fish', 'volume': 100},
    {'name': 'Fresh Vegetables', 'volume': 150},
    {'name': 'Dairy Products', 'volume': 80},
]

storage_zones = [
    {'name': 'Deep Freeze', 'temp_min': -25, 'temp_max': -18,
     'capacity': 200, 'energy_cost_per_unit': 3.0},
    {'name': 'Freezer', 'temp_min': -18, 'temp_max': -12,
     'capacity': 250, 'energy_cost_per_unit': 2.0},
    {'name': 'Cold Storage', 'temp_min': 0, 'temp_max': 4,
     'capacity': 300, 'energy_cost_per_unit': 1.0},
]

temperature_requirements = {
    'Ice Cream': {'optimal': -20},
    'Frozen Fish': {'optimal': -15},
    'Fresh Vegetables': {'optimal': 2},
    'Dairy Products': {'optimal': 3},
}

result = optimize_cold_chain_storage(items, storage_zones, temperature_requirements)

港口物流与运营

岸上协调
def optimize_port_loading_schedule(deliveries, loading_bays, port_time_window):
    """
    Optimize scheduling of supplier deliveries during port call

    Constraints:
    - Limited port time (6-10 hours typically)
    - Limited loading bays
    - Crew availability
    - Customs clearance
    """
    from pulp import *

    prob = LpProblem("Port_Loading", LpMinimize)

    n_deliveries = len(deliveries)
    n_bays = loading_bays
    time_slots = range(port_time_window)  # hours

    # Variables: assign delivery d to bay b in time slot t
    x = {}

    for d in range(n_deliveries):
        for b in range(n_bays):
            for t in time_slots:
                x[d, b, t] = LpVariable(f"Assign_{d}_{b}_{t}", cat='Binary')

    # Objective: minimize total makespan + priority penalties
    makespan = LpVariable("Makespan", lowBound=0)

    # Completion time of last delivery
    prob += makespan

    # Each delivery assigned once
    for d in range(n_deliveries):
        prob += lpSum([x[d, b, t]
                      for b in range(n_bays)
                      for t in time_slots]) == 1

    # Bay can handle one delivery at a time
    for b in range(n_bays):
        for t in time_slots:
            prob += lpSum([x[d, b, t] for d in range(n_deliveries)]) <= 1

    # Makespan constraint
    for d, delivery in enumerate(deliveries):
        for b in range(n_bays):
            for t in time_slots:
                # If delivery starts at time t, it completes at t + duration
                prob += makespan >= (t + delivery['duration_hours']) * x[d, b, t]

    # Priority deliveries (perishables) should be early
    for d, delivery in enumerate(deliveries):
        if delivery.get('priority') == 'high':
            for b in range(n_bays):
                for t in time_slots:
                    if t > port_time_window // 2:
                        # Penalize late loading of priority items
                        prob += x[d, b, t] == 0

    # Solve
    prob.solve(PULP_CBC_CMD(msg=0))

    # Extract schedule
    schedule = []

    for d in range(n_deliveries):
        for b in range(n_bays):
            for t in time_slots:
                if x[d, b, t].varValue > 0.5:
                    schedule.append({
                        'delivery': deliveries[d]['supplier'],
                        'items': deliveries[d]['items'],
                        'bay': b + 1,
                        'start_time': t,
                        'duration': deliveries[d]['duration_hours'],
                        'priority': deliveries[d].get('priority', 'normal')
                    })

    return {
        'makespan': makespan.varValue,
        'schedule': pd.DataFrame(schedule).sort_values('start_time')
    }

工具与库

Python 库

优化:

  • PuLP:线性规划
  • scipy.optimize:通用优化
  • OR-Tools:Google 优化工具

预测:

  • scikit-learn:机器学习
  • prophet:时间序列预测

数据分析:

  • pandas、numpy:数据处理
  • matplotlib:可视化
商业软件

邮轮运营:

  • ShipServ:海事采购平台
  • MarineCFO:邮轮财务管理
  • Adonis:酒店管理系统
  • ORIS:船舶运营和报告

库存管理:

  • Visual Computers:邮轮库存系统
  • Compeat:餐饮及酒店库存管理
  • MarketMan:餐饮服务库存管理

补给:

  • Navtor:海事航程规划
  • Martek Marine:船舶管理软件
  • Danaos:船舶管理系统

可持续发展:

  • Cleantech:环境合规
  • OCEANOS:环境监测

常见挑战与解决方案

挑战:港口停留时间有限

问题:

  • 港口停留时间有限(4-10 小时)
  • 涉及多个供应商和多批交付
  • 海关和检查延误

解决方案:

  • 提前规划和协调
  • 由集货商整合交付
  • 安排保税仓库
  • 并行装载作业
  • 预先审核供应商
挑战:存储空间有限

问题:

  • 冷藏容量有限
  • 各部门争用空间
  • 季节性需求变化

解决方案:

  • 优化最低库存水平
  • 尽可能采用准时补给
  • 优化多温区存储
  • 采用紧凑型存储方案
  • 战略性选择补给港口
挑战:品质与新鲜度

问题:

  • 长时间航行,无法补给
  • 保持农产品品质
  • 满足宾客对新鲜度的期待

解决方案:

  • 气调储存
  • 船上水培花园
  • 在多个港口进行策略性采购
  • 根据产品保质期规划菜单
  • 质量检验流程
挑战:废弃物管理

问题:

  • 食物浪费(备餐和餐盘剩余)
  • 环境法规
  • 海上处置选择有限

解决方案:

  • 预测性生产规划
  • 优化份量控制
  • 在港口开展捐赠计划
  • 堆肥和厌氧消化器
  • 废弃物转能源系统

输出格式

邮轮供应链报告

执行摘要:

  • 船舶补给绩效
  • 成本指标与趋势
  • 减少废弃物的成果
  • 主要机遇

补给绩效:

港口装载品项价值交货时间准时率质量问题
Miami1,250$185,0004.5 hrs98%2
Cozumel320$28,0002.8 hrs100%0
Grand Cayman180$15,0003.2 hrs95%1

库存指标:

类别当前库存标准库存水平可供天数周转率浪费率
蛋白质(冷冻)3,200 kg3,500 kg6.445x/yr2.1%
新鲜农产品1,800 kg2,000 kg3.0120x/yr5.8%
乳制品1,200 L1,400 L4.090x/yr3.2%
干货5,500 kg6,000 kg18.020x/yr1.5%

成本分析:

类别总成本每位乘客每日成本占总额比例与预算相比
蛋白质$125,000$8.5035%-2%
农产品$85,000$5.8024%+1%
乳制品$45,000$3.0613%0%
饮料$70,000$4.7620%-3%
其他$30,000$2.048%+2%
总计$355,000$24.16100%-1%

减少废弃物:

指标本次航程上次航程年初至今平均值目标
食物浪费(kg/乘客日)0.450.520.48< 0.40
废弃物减少率13%-8%15%
捐赠餐食(份)1,2509801,1001,000

建议:

  1. 将更多补给转至 Miami 采购(相比加勒比海港口可节省 15% 成本)
  2. 将农产品标准库存水平降低 10%(有减少浪费的空间)
  3. 实施自助餐预测性补餐系统
  4. 将捐赠计划扩展至所有港口
  5. 安装水培花园种植香草和生菜(成本降低 35%)

要提出的问题

如需更多背景信息:

  1. 船舶类型和载客量是多少?(大型邮轮、豪华邮轮、探险邮轮)
  2. 行程和航线是什么?
  3. 补给频率和主要港口有哪些?
  4. 当前的浪费和成本指标是什么?
  5. 目前使用哪些系统?(库存、采购)
  6. 主要挑战是什么?(成本、质量、浪费)
  7. 有哪些可持续发展目标?

相关技能

  • hotel-inventory-management:酒店库存管理概念
  • hospitality-procurement:采购和供应商管理
  • tour-operations:乘客运营
  • inventory-optimization:库存管理策略
  • demand-forecasting:消费预测
  • route-optimization:行程优化
  • cold-chain-logistics:温控供应链
  • food-beverage-supply-chain:餐饮运营

评论

支持 Markdown