churnguard / src /api /streaming.py
OmarGamal48812's picture
Upload folder using huggingface_hub
d9b2b72 verified
Raw
History Blame Contribute Delete
4.3 kB
"""Streaming data simulator — generates synthetic customer events."""
import random
import time
from collections import deque
from datetime import datetime
from fastapi import APIRouter
router = APIRouter()
# In-memory event queue (last 100 events)
event_queue: deque = deque(maxlen=100)
# Realistic value ranges based on dataset statistics
FEATURE_RANGES = {
"Tenure": (0, 61),
"CityTier": [1, 2, 3],
"WarehouseToHome": (5, 36),
"Gender": [0, 1],
"HourSpendOnApp": (0, 5),
"NumberOfDeviceRegistered": (1, 6),
"SatisfactionScore": [1, 2, 3, 4, 5],
"MaritalStatus": [0, 1, 2],
"NumberOfAddress": (1, 22),
"Complain": [0, 1],
"OrderAmountHikeFromlastYear": (11, 26),
"CouponUsed": (0, 16),
"OrderCount": (1, 16),
"DaySinceLastOrder": (0, 46),
"CashbackAmount": (0, 325),
}
def _generate_customer() -> dict:
"""Generate a random customer with realistic feature values."""
customer = {}
for feat, vals in FEATURE_RANGES.items():
if isinstance(vals, list):
customer[feat] = random.choice(vals)
else:
low, high = vals
customer[feat] = round(random.uniform(low, high), 2)
# Derived features
tenure = customer["Tenure"]
if tenure <= 6:
customer["tenure_bucket"] = 0
elif tenure <= 12:
customer["tenure_bucket"] = 1
elif tenure <= 24:
customer["tenure_bucket"] = 2
else:
customer["tenure_bucket"] = 3
customer["engagement_score"] = round(customer["HourSpendOnApp"] * customer["OrderCount"], 2)
customer["cashback_per_order"] = (
round(customer["CashbackAmount"] / customer["OrderCount"], 2)
if customer["OrderCount"] > 0
else 0
)
customer["is_recent_buyer"] = 1 if customer["DaySinceLastOrder"] <= 3 else 0
customer["has_multi_device"] = 1 if customer["NumberOfDeviceRegistered"] >= 4 else 0
customer["is_high_spender"] = 1 if customer["OrderAmountHikeFromlastYear"] > 20 else 0
# One-hot encoded features (random selection)
login_device = random.choice(["Computer", "Mobile Phone"])
customer["PreferredLoginDevice_Mobile Phone"] = 1 if login_device == "Mobile Phone" else 0
payment = random.choice(["Cash on Delivery", "Credit Card", "Debit Card", "E wallet", "UPI"])
customer["PreferredPaymentMode_Credit Card"] = 1 if payment == "Credit Card" else 0
customer["PreferredPaymentMode_Debit Card"] = 1 if payment == "Debit Card" else 0
customer["PreferredPaymentMode_E wallet"] = 1 if payment == "E wallet" else 0
customer["PreferredPaymentMode_UPI"] = 1 if payment == "UPI" else 0
category = random.choice(["Fashion", "Grocery", "Laptop & Accessory", "Mobile Phone", "Others"])
customer["PreferedOrderCat_Grocery"] = 1 if category == "Grocery" else 0
customer["PreferedOrderCat_Laptop & Accessory"] = 1 if category == "Laptop & Accessory" else 0
customer["PreferedOrderCat_Mobile Phone"] = 1 if category == "Mobile Phone" else 0
customer["PreferedOrderCat_Others"] = 1 if category == "Others" else 0
return customer
@router.post("/generate")
def generate_event():
"""Generate a single synthetic customer event and add to the queue."""
customer = _generate_customer()
event = {
"timestamp": datetime.now().isoformat(),
"customer": customer,
}
event_queue.append(event)
return {"status": "generated", "event": event}
@router.post("/generate-batch")
def generate_batch(count: int = 10):
"""Generate multiple synthetic customer events."""
events = []
for _ in range(min(count, 50)):
customer = _generate_customer()
event = {
"timestamp": datetime.now().isoformat(),
"customer": customer,
}
event_queue.append(event)
events.append(event)
return {"status": "generated", "count": len(events), "events": events}
@router.get("/events")
def get_events(limit: int = 20):
"""Get recent events from the queue."""
events = list(event_queue)[-limit:]
return {"count": len(events), "events": events}
@router.get("/stats")
def get_stats():
"""Get streaming statistics."""
return {
"total_events": len(event_queue),
"queue_capacity": event_queue.maxlen,
}