0d3cb498a3
CI / Shell Format Check (push) Has been cancelled
CI / Check Ruby (3.4) (push) Has been cancelled
CI / CI Config (push) Has been cancelled
CI / Test on Node ${{ matrix.node }} and ${{ matrix.os }}${{ matrix.shard && format(' (shard {0}/3)', matrix.shard) || '' }} (push) Has been cancelled
CI / Build on Node ${{ matrix.node }} (push) Has been cancelled
CI / Style Check (push) Has been cancelled
CI / Generate Assets (push) Has been cancelled
CI / Check Python (3.14) (push) Has been cancelled
CI / Check Python (3.9) (push) Has been cancelled
CI / Build Docs (push) Has been cancelled
CI / Code Scan Action (push) Has been cancelled
CI / Site tests (push) Has been cancelled
CI / webui tests (push) Has been cancelled
CI / Run Integration Tests (push) Has been cancelled
CI / Run Smoke Tests (push) Has been cancelled
CI / Go Tests (push) Has been cancelled
CI / Share Test (push) Has been cancelled
CI / Redteam (Production API) (push) Has been cancelled
CI / Redteam (Staging API) (push) Has been cancelled
CI / GitHub Actions Lint (push) Has been cancelled
CI / Check Ruby (3.0) (push) Has been cancelled
release-please / release-please (push) Has been cancelled
release-please / build (push) Has been cancelled
release-please / publish-npm (push) Has been cancelled
release-please / publish-npm-backfill (push) Has been cancelled
release-please / docker (push) Has been cancelled
release-please / publish-code-scan-action (push) Has been cancelled
release-please / attest-code-scan-action (push) Has been cancelled
Deploy local.promptfoo.app / Deploy to Cloudflare Pages (push) Has been cancelled
Test and Publish Multi-arch Docker Image / test (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-amd64 platform:linux/amd64 runner:ubuntu-latest]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / build-docker-and-push-digests (map[digest-suffix:linux-arm64 platform:linux/arm64 runner:ubuntu-24.04-arm]) (push) Has been cancelled
Test and Publish Multi-arch Docker Image / merge-docker-digests (push) Has been cancelled
Test and Publish Multi-arch Docker Image / Attest Multi-arch Image (push) Has been cancelled
Validate Renovate Config / Validate Renovate Configuration (push) Has been cancelled
205 lines
6.2 KiB
Python
205 lines
6.2 KiB
Python
"""
|
|
Mock Weather Service
|
|
|
|
Provides weather data for user locations to enable product recommendations.
|
|
"""
|
|
|
|
from datetime import datetime
|
|
|
|
# Mock weather data by city
|
|
WEATHER_DATA = {
|
|
"san francisco, ca": {
|
|
"city": "San Francisco",
|
|
"state": "CA",
|
|
"temperature_f": 58,
|
|
"condition": "Foggy",
|
|
"humidity": 78,
|
|
"wind_mph": 12,
|
|
"feels_like_f": 54,
|
|
"forecast": "Typical foggy morning, clearing to partly cloudy by afternoon",
|
|
"weather_tags": ["cold", "mild"],
|
|
"recommendations": [
|
|
"Perfect hoodie weather! Check out our CloudCo Zip Hoodie.",
|
|
"A warm coffee mug would be great for foggy mornings.",
|
|
],
|
|
},
|
|
"new york, ny": {
|
|
"city": "New York",
|
|
"state": "NY",
|
|
"temperature_f": 35,
|
|
"condition": "Cold & Clear",
|
|
"humidity": 45,
|
|
"wind_mph": 18,
|
|
"feels_like_f": 28,
|
|
"forecast": "Clear but cold with strong winds. Bundle up!",
|
|
"weather_tags": ["cold", "outdoor"],
|
|
"recommendations": [
|
|
"Definitely beanie weather! Our CloudCo Beanie will keep you warm.",
|
|
"Layer up with a hoodie under your coat.",
|
|
],
|
|
},
|
|
"chicago, il": {
|
|
"city": "Chicago",
|
|
"state": "IL",
|
|
"temperature_f": 28,
|
|
"condition": "Snow Flurries",
|
|
"humidity": 65,
|
|
"wind_mph": 25,
|
|
"feels_like_f": 15,
|
|
"forecast": "Light snow with gusty winds. The Windy City living up to its name!",
|
|
"weather_tags": ["cold", "outdoor"],
|
|
"recommendations": [
|
|
"Bundle up! Our warmest hoodie is the CloudCo Zip Hoodie.",
|
|
"Don't forget a beanie - you'll need it in that wind!",
|
|
"Hot coffee in a CloudCo mug is essential today.",
|
|
],
|
|
},
|
|
"austin, tx": {
|
|
"city": "Austin",
|
|
"state": "TX",
|
|
"temperature_f": 72,
|
|
"condition": "Sunny",
|
|
"humidity": 55,
|
|
"wind_mph": 8,
|
|
"feels_like_f": 72,
|
|
"forecast": "Beautiful day ahead! Sunny with light breeze.",
|
|
"weather_tags": ["mild", "sunny", "outdoor"],
|
|
"recommendations": [
|
|
"Perfect t-shirt weather! Check out our CloudCo Logo Tee.",
|
|
"Don't forget your snapback for the sun!",
|
|
"Stay hydrated with our insulated water bottle.",
|
|
],
|
|
},
|
|
"seattle, wa": {
|
|
"city": "Seattle",
|
|
"state": "WA",
|
|
"temperature_f": 48,
|
|
"condition": "Rainy",
|
|
"humidity": 85,
|
|
"wind_mph": 10,
|
|
"feels_like_f": 44,
|
|
"forecast": "Classic Seattle weather - overcast with steady rain.",
|
|
"weather_tags": ["cold", "indoor"],
|
|
"recommendations": [
|
|
"Hoodie weather for sure! Stay warm and dry.",
|
|
"A travel tumbler keeps your coffee warm between rain sprints.",
|
|
"Work from home? Our desk pad makes rainy days cozier.",
|
|
],
|
|
},
|
|
# Default for unknown locations
|
|
"default": {
|
|
"city": "Unknown",
|
|
"state": "NA",
|
|
"temperature_f": 65,
|
|
"condition": "Partly Cloudy",
|
|
"humidity": 50,
|
|
"wind_mph": 10,
|
|
"feels_like_f": 65,
|
|
"forecast": "Moderate conditions expected.",
|
|
"weather_tags": ["mild"],
|
|
"recommendations": [
|
|
"A classic CloudCo Logo Tee works in any weather!",
|
|
"Can't go wrong with our versatile Travel Tumbler.",
|
|
],
|
|
},
|
|
}
|
|
|
|
|
|
def normalize_location(location: str) -> str:
|
|
"""Normalize location string for lookup."""
|
|
return location.lower().strip()
|
|
|
|
|
|
def get_weather(location: str) -> dict:
|
|
"""
|
|
Get current weather and product recommendations for a location.
|
|
|
|
Args:
|
|
location: City name or "City, State" format
|
|
|
|
Returns:
|
|
Weather data with product recommendations
|
|
"""
|
|
normalized = normalize_location(location)
|
|
|
|
# Try exact match first
|
|
if normalized in WEATHER_DATA:
|
|
data = WEATHER_DATA[normalized]
|
|
else:
|
|
# Try partial match
|
|
matched = None
|
|
for key in WEATHER_DATA.keys():
|
|
if key != "default":
|
|
city_name = key.split(",")[0]
|
|
if city_name in normalized or normalized in city_name:
|
|
matched = key
|
|
break
|
|
|
|
if matched:
|
|
data = WEATHER_DATA[matched]
|
|
else:
|
|
data = WEATHER_DATA["default"]
|
|
data = {
|
|
**data,
|
|
"city": location,
|
|
"note": "Weather data approximated for unknown location",
|
|
}
|
|
|
|
now = datetime.now()
|
|
|
|
return {
|
|
"location": f"{data['city']}, {data['state']}",
|
|
"temperature": data["temperature_f"],
|
|
"temperature_unit": "F",
|
|
"feels_like": data["feels_like_f"],
|
|
"condition": data["condition"],
|
|
"humidity": data["humidity"],
|
|
"humidity_unit": "%",
|
|
"wind": data["wind_mph"],
|
|
"wind_unit": "mph",
|
|
"forecast": data["forecast"],
|
|
"weather_tags": data["weather_tags"],
|
|
"product_recommendations": data["recommendations"],
|
|
"updated_at": now.strftime("%Y-%m-%d %H:%M:%S"),
|
|
}
|
|
|
|
|
|
def get_weather_recommendations(location: str) -> dict:
|
|
"""
|
|
Get just the product recommendations for a location.
|
|
|
|
Args:
|
|
location: City name or "City, State" format
|
|
|
|
Returns:
|
|
Product recommendations based on weather
|
|
"""
|
|
weather = get_weather(location)
|
|
|
|
return {
|
|
"location": weather["location"],
|
|
"condition": weather["condition"],
|
|
"temperature": weather["temperature"],
|
|
"recommendations": weather["product_recommendations"],
|
|
"suggested_categories": get_categories_for_weather(weather["weather_tags"]),
|
|
}
|
|
|
|
|
|
def get_categories_for_weather(tags: list) -> list:
|
|
"""Map weather tags to product categories."""
|
|
category_map = {
|
|
"cold": ["hoodies", "beanies", "mugs"],
|
|
"hot": ["water bottles", "t-shirts"],
|
|
"sunny": ["snapbacks", "water bottles"],
|
|
"mild": ["t-shirts", "accessories"],
|
|
"indoor": ["mugs", "mousepad", "stickers"],
|
|
"outdoor": ["backpack", "water bottles", "snapbacks"],
|
|
}
|
|
|
|
categories = set()
|
|
for tag in tags:
|
|
if tag in category_map:
|
|
categories.update(category_map[tag])
|
|
|
|
return list(categories)
|