localgreenchain/docs/examples/demand-driven-planting.md
Claude 4111c3acf1
Add complete documentation suite for LocalGreenChain
- Add guides: quick-start, installation, configuration, grower, consumer, transport, vertical-farm
- Add API references: REST, demand, vertical-farming
- Add concepts: blockchain, seasonal-planning, carbon-footprint
- Add architecture: data-flow, transport-tracking
- Add vertical-farming: environmental-control, automation, integration
- Add examples: seed-to-harvest, demand-driven-planting, vertical-farm-setup

Completes Agent_5 documentation tasks from AGENT_REPORT.md
2025-11-22 18:48:42 +00:00

11 KiB

Example: Demand-Driven Planting

Complete workflow for responding to demand signals and optimizing production.

Scenario

You're a grower with 500 sqm of growing space. You want to plant what consumers actually need, not just guess.

Step 1: Set Up Consumer Preferences

First, consumers in your region register their preferences:

// Consumers register their preferences
// POST /api/demand/preferences

// Consumer A: Family of 4, organic focus
const consumerA = {
  consumerId: 'consumer-001',
  location: {
    latitude: 40.7128,
    longitude: -74.0060,
    maxDeliveryRadiusKm: 25,
    city: 'Brooklyn'
  },
  dietaryType: ['vegetarian'],
  preferredCategories: ['leafy_greens', 'nightshades', 'herbs'],
  preferredItems: [
    { produceType: 'tomato', priority: 'must_have', weeklyQuantity: 3 },
    { produceType: 'lettuce', priority: 'preferred', weeklyQuantity: 2 },
    { produceType: 'basil', priority: 'nice_to_have', weeklyQuantity: 0.2 }
  ],
  certificationPreferences: ['organic', 'local'],
  freshnessImportance: 5,
  sustainabilityImportance: 5,
  householdSize: 4,
  weeklyBudget: 100
};

// Consumer B: Couple, price-conscious
const consumerB = {
  consumerId: 'consumer-002',
  location: {
    latitude: 40.7200,
    longitude: -74.0100,
    maxDeliveryRadiusKm: 15,
    city: 'Brooklyn'
  },
  preferredItems: [
    { produceType: 'tomato', priority: 'preferred', weeklyQuantity: 1.5 },
    { produceType: 'cucumber', priority: 'must_have', weeklyQuantity: 2 },
    { produceType: 'pepper', priority: 'nice_to_have', weeklyQuantity: 1 }
  ],
  priceImportance: 5,
  householdSize: 2,
  weeklyBudget: 60
};

// Register preferences
await fetch('/api/demand/preferences', {
  method: 'POST',
  body: JSON.stringify(consumerA)
});

await fetch('/api/demand/preferences', {
  method: 'POST',
  body: JSON.stringify(consumerB)
});

Step 2: Generate Demand Signal

The system aggregates preferences for your region:

// POST /api/demand/signal

const signalRequest = {
  centerLat: 40.7150,
  centerLon: -74.0080,
  radiusKm: 30,
  regionName: 'Brooklyn North',
  season: 'summer'
};

const response = await fetch('/api/demand/signal', {
  method: 'POST',
  body: JSON.stringify(signalRequest)
});

const { data: demandSignal } = await response.json();

console.log(demandSignal);
/*
{
  id: 'demand-2024-abc123',
  region: { name: 'Brooklyn North', radiusKm: 30 },
  seasonalPeriod: 'summer',

  demandItems: [
    {
      produceType: 'tomato',
      weeklyDemandKg: 180,
      consumerCount: 95,
      aggregatePriority: 8,
      urgency: 'this_week',
      inSeason: true,
      matchedSupply: 60,
      gapKg: 120  // OPPORTUNITY!
    },
    {
      produceType: 'lettuce',
      weeklyDemandKg: 120,
      consumerCount: 72,
      aggregatePriority: 6,
      inSeason: false,  // Too hot for outdoor lettuce
      gapKg: 80
    },
    {
      produceType: 'cucumber',
      weeklyDemandKg: 90,
      gapKg: 45
    },
    {
      produceType: 'basil',
      weeklyDemandKg: 25,
      gapKg: 25
    }
  ],

  totalConsumers: 150,
  totalWeeklyDemandKg: 415,
  supplyGapKg: 270,
  supplyStatus: 'shortage'  // Opportunity!
}
*/

Step 3: Get Planting Recommendations

Now, get personalized recommendations for your space:

// GET /api/demand/recommendations

const response = await fetch(
  '/api/demand/recommendations?' + new URLSearchParams({
    growerId: 'grower-001',
    lat: '40.7100',
    lon: '-74.0050',
    deliveryRadiusKm: '40',
    availableSpaceSqm: '500',
    season: 'summer'
  })
);

const { data } = await response.json();
const recommendations = data.recommendations;

console.log(recommendations);
/*
[
  {
    id: 'rec-001',
    produceType: 'tomato',
    category: 'nightshades',

    // What to plant
    recommendedQuantity: 200,  // sqm
    quantityUnit: 'sqm',
    expectedYieldKg: 1600,

    // When
    plantByDate: '2024-05-15',
    expectedHarvestStart: '2024-08-01',
    expectedHarvestEnd: '2024-09-15',
    growingDays: 80,

    // Revenue projection
    projectedDemandKg: 480,  // Monthly
    projectedPricePerKg: 4.50,
    projectedRevenue: 7200,
    marketConfidence: 85,

    // Risks
    riskFactors: [
      {
        type: 'weather',
        severity: 'medium',
        description: 'Single season crop with weather sensitivity',
        mitigationSuggestion: 'Consider greenhouse for portion'
      }
    ],
    overallRisk: 'medium',

    // Why this recommendation
    explanation: 'Based on 3 demand signals showing 120kg weekly gap...'
  },
  {
    produceType: 'cucumber',
    recommendedQuantity: 100,
    expectedYieldKg: 1000,
    projectedRevenue: 3500,
    overallRisk: 'low'
  },
  {
    produceType: 'basil',
    recommendedQuantity: 50,
    expectedYieldKg: 100,
    projectedRevenue: 1500,
    overallRisk: 'low'
  }
]
*/

Step 4: Make Planting Decision

Review recommendations and decide:

// Space allocation based on recommendations
const plantingPlan = {
  'tomato': {
    sqm: 200,
    expectedYield: 1600,
    priority: 'high'
  },
  'cucumber': {
    sqm: 100,
    expectedYield: 1000,
    priority: 'medium'
  },
  'basil': {
    sqm: 50,
    expectedYield: 100,
    priority: 'medium'
  },
  // Reserve 150 sqm for crop rotation / next planting
  'reserved': {
    sqm: 150,
    purpose: 'fall crops'
  }
};

console.log('Total allocated:', 350, 'sqm');
console.log('Expected total yield:', 2700, 'kg');
console.log('Projected revenue:', 12200, 'USD');

Step 5: Commit Supply

Pre-commit your planned production:

// POST /api/demand/supply

const supplyCommitment = {
  growerId: 'grower-001',
  produceType: 'tomato',
  variety: 'Multiple heirloom',

  // What you're committing
  committedQuantityKg: 1600,
  availableFrom: '2024-08-01',
  availableUntil: '2024-09-30',

  // Pricing
  pricePerKg: 4.50,
  currency: 'USD',
  minimumOrderKg: 2,
  bulkDiscountThreshold: 10,
  bulkDiscountPercent: 10,

  // Quality
  certifications: ['local'],
  freshnessGuaranteeHours: 24,

  // Delivery
  deliveryRadiusKm: 40,
  deliveryMethods: ['grower_delivery', 'farmers_market', 'customer_pickup']
};

const response = await fetch('/api/demand/supply', {
  method: 'POST',
  body: JSON.stringify(supplyCommitment)
});

const { data } = await response.json();
console.log('Supply committed:', data.id);
console.log('Status:', data.status);  // 'available'

Step 6: Get Matched

The system matches supply with demand:

// System creates matches automatically, or manually:

// POST /api/demand/match

const match = {
  demandSignalId: 'demand-2024-abc123',
  supplyCommitmentId: data.id,

  consumerId: 'consumer-001',
  growerId: 'grower-001',

  produceType: 'tomato',
  matchedQuantityKg: 3,

  agreedPricePerKg: 4.50,
  totalPrice: 13.50,
  currency: 'USD',

  deliveryDate: '2024-08-05',
  deliveryMethod: 'home_delivery',
  deliveryLocation: {
    latitude: 40.7128,
    longitude: -74.0060,
    address: '123 Main St, Brooklyn'
  }
};

await fetch('/api/demand/match', {
  method: 'POST',
  body: JSON.stringify(match)
});

Step 7: Forecast Future Demand

Plan for upcoming seasons:

// GET /api/demand/forecast

const response = await fetch(
  '/api/demand/forecast?' + new URLSearchParams({
    region: 'Brooklyn North',
    weeks: '12'
  })
);

const { data: forecast } = await response.json();

console.log(forecast);
/*
{
  id: 'forecast-2024-xyz',
  region: 'Brooklyn North',
  forecastPeriod: {
    start: '2024-06-01',
    end: '2024-08-24'
  },

  forecasts: [
    {
      produceType: 'tomato',
      predictedDemandKg: 2400,
      confidence: 80,
      trend: 'increasing',
      seasonalFactor: 1.2,
      factors: [
        {
          name: 'Seasonal peak',
          type: 'seasonal',
          impact: 20,
          description: 'Summer peak for tomatoes'
        }
      ]
    },
    {
      produceType: 'lettuce',
      predictedDemandKg: 800,
      trend: 'decreasing',
      seasonalFactor: 0.6,  // Too hot
      factors: [
        {
          name: 'Heat sensitivity',
          impact: -40,
          description: 'Outdoor lettuce struggles in summer'
        }
      ]
    }
  ]
}
*/

Complete Workflow Script

// demand-driven-workflow.ts

import { getDemandForecaster } from '@/lib/demand/forecaster';

async function demandDrivenWorkflow() {
  const forecaster = getDemandForecaster();

  // 1. Register some consumer preferences
  const consumers = [
    createConsumerPreference('consumer-001', [
      { produceType: 'tomato', priority: 'must_have', weeklyQuantity: 3 }
    ]),
    createConsumerPreference('consumer-002', [
      { produceType: 'tomato', priority: 'preferred', weeklyQuantity: 1.5 }
    ]),
    // ... more consumers
  ];

  for (const consumer of consumers) {
    forecaster.registerPreference(consumer);
  }

  // 2. Generate demand signal
  const demandSignal = forecaster.generateDemandSignal(
    40.7150,  // latitude
    -74.0080, // longitude
    30,       // radius km
    'Brooklyn North',
    'summer'
  );

  console.log('Demand signal generated');
  console.log('Total demand:', demandSignal.totalWeeklyDemandKg, 'kg/week');
  console.log('Supply gap:', demandSignal.supplyGapKg, 'kg/week');
  console.log('Status:', demandSignal.supplyStatus);

  // 3. Get recommendations for grower
  const recommendations = forecaster.generatePlantingRecommendations(
    'grower-001',
    40.7100,  // grower lat
    -74.0050, // grower lon
    40,       // delivery radius
    500,      // available sqm
    'summer'
  );

  console.log('\nRecommendations:');
  for (const rec of recommendations) {
    console.log(`- ${rec.produceType}: ${rec.recommendedQuantity} sqm`);
    console.log(`  Expected yield: ${rec.expectedYieldKg} kg`);
    console.log(`  Projected revenue: $${rec.projectedRevenue}`);
    console.log(`  Risk: ${rec.overallRisk}`);
  }

  // 4. Commit supply
  const supply = {
    id: `supply-${Date.now()}`,
    growerId: 'grower-001',
    produceType: 'tomato',
    committedQuantityKg: 1600,
    availableFrom: new Date(Date.now() + 60 * 24 * 60 * 60 * 1000).toISOString(),
    availableUntil: new Date(Date.now() + 120 * 24 * 60 * 60 * 1000).toISOString(),
    pricePerKg: 4.50,
    currency: 'USD',
    certifications: ['local'],
    status: 'available',
    remainingKg: 1600
  };

  forecaster.registerSupply(supply);
  console.log('\nSupply committed:', supply.committedQuantityKg, 'kg');

  // 5. Generate updated signal (should show reduced gap)
  const updatedSignal = forecaster.generateDemandSignal(
    40.7150, -74.0080, 30, 'Brooklyn North', 'summer'
  );

  console.log('\nUpdated supply status:', updatedSignal.supplyStatus);
  console.log('Remaining gap:', updatedSignal.supplyGapKg, 'kg/week');

  return {
    demandSignal,
    recommendations,
    supply,
    updatedSignal
  };
}

// Run workflow
demandDrivenWorkflow()
  .then(result => console.log('\nWorkflow complete!'))
  .catch(console.error);

Key Insights

Why Demand-Driven Works

  1. Reduced waste - Grow what people want
  2. Better prices - Pre-commitment secures sales
  3. Lower risk - Data-driven decisions
  4. Happy consumers - They get what they need
  5. Sustainability - Less overproduction

Best Practices

  1. Check demand signals weekly
  2. Start with high-demand, low-risk crops
  3. Commit supply early for best matching
  4. Adjust based on actual results
  5. Build relationships with regular consumers