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時間)
  • 複数のサプライヤーと納品
  • 税関・検査による遅延

解決策:

  • 事前の計画と調整
  • 集約業者からの一括納品
  • 保税倉庫の手配
  • 並行して行う積み込み作業
  • 事前承認済みのサプライヤー
課題:保管スペースの制限

問題:

  • 冷蔵保管容量の制限
  • 部門間でのスペースの競合
  • 季節による需要の変動

解決策:

  • 適正在庫レベルの最適化
  • 可能な場合はジャストインタイムでの物資補給
  • 複数温度帯の保管スペースの最適化
  • 省スペース型の保管ソリューション
  • 物資補給に適した寄港地の戦略的な選定
課題:品質と鮮度

問題:

  • 補給なしで長期間航海する
  • 食材の品質を維持する
  • ゲストが求める鮮度に応える

解決策:

  • CA貯蔵
  • 船内の水耕栽培ガーデン
  • 複数の寄港地で戦略的に調達する
  • 食材の保存期間に合わせてメニューを計画する
  • 品質検査の手順を確立する
課題:廃棄物管理

問題:

  • 食品廃棄物(仕込み時と食べ残し)
  • 環境規制
  • 海上での廃棄方法が限られている

解決策:

  • 予測に基づく生産計画
  • ポーション管理の最適化
  • 寄港地での寄付プログラム
  • 堆肥化とバイオダイジェスター
  • 廃棄物発電システム

出力形式

クルーズ・サプライチェーンレポート

エグゼクティブサマリー:

  • 船舶への物資補給の実績
  • コスト指標と傾向
  • 廃棄物削減の実績
  • 主な機会

物資補給の実績:

寄港地積載品目数金額リードタイム定時率品質上の問題
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%

コスト分析:

カテゴリー合計コスト乗客1人・1日あたりのコスト合計に占める割合予算比
タンパク質$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:飲食業務

コメント