Skip to content

Implement offline-capable weekend planner pipeline #5

@LuminLynx

Description

@LuminLynx

Step-by-Step Plan

Create "Weekend Plans :

1. Based on Distance (user location as reference)

  • insert Location toggle button
  • Implement a way for user to set his location Worldwide.
  • The Search for Weekend Plans is based on User Location setting.

Search Results :

  • ** Implement a way for the User to set the Search Location"

  • **The Search Results Should display according to the Distance from tbe User's
    Location: if the user's location distance to the search location is bigger than 30 kms
    The Search must show Public Transportation Options.
    If the same distance is bigger than 300 kms, Plane's transportation options should
    be displayed.
    Displaying Transportation, Hosting options (according to the budget), Restaurant's options
    plus cost with local transportation (taxis, uber, bus, metro)

  • The search should return 10 Results

  • The Results should output different Places

Results Breakdown

  • **If the Distance from user's Location to

1) Create "Weekend Plans

Why: Deterministic behavior offline; easy overrides via YAML/env.

Files to add/modify

  • app/utils/cache.py: TTL JSON file cache under ~/.weekend-planner/cache/
  • app/utils/env_loader.py: merge defaults → YAML → ENV (tokens)
  • app/utils/http.py: lightweight GET with retries/backoff (used only when online)

Acceptance

  • Can import all three modules.
  • cache.set/get round-trip a dict; TTL respected.

2) Implement FX connector with fallbacks

Why: Pivot all costs to user currency even offline.

Files

  • app/connectors/fx.py:
    • Order: TTL cache → live API → last_good (no TTL) → builtin rates {"EUR":1.0,"USD":1.08,"GBP":0.85}
    • Expose get_fx_rates() and get_fx_rates_with_meta() (returns (rates, source, cache_hit))

Acceptance

  • Offline: returns builtin/last_good and sets source to "builtin" or "last_good".
  • Online: first run "live", subsequent runs hit "cache" within 24h.

3) Implement vendor connectors with offline dummy data

Why: Ensure local, no-network runs succeed.

Files

  • data/dummy/offers_vendor_a.json
  • data/dummy/offers_vendor_b.json
  • app/connectors/ticket_vendor_a.py, ticket_vendor_b.py:
    • If no VENDOR_*_TOKEN, load dummy JSON and hydrate title/start_ts/venue from the query.
    • Normalized shape per offer:
      {
        "provider": "a|b",
        "price": {"amount": 22.0, "currency": "EUR", "includes_vat": true},
        "fees": [{"type":"service","amount":2.5,"currency":"EUR"}],
        "vat_rate": 0.23,
        "promos": ["CODE"],
        "inventory_hint": "low|med|high",
        "url": "https://…"
      }

Acceptance

  • Without tokens, each connector returns ≥1 normalized offer from local JSON.

4) Add optional dining connector (offline stub)

Files

  • app/connectors/dining.py: return one static nearby suggestion offline (e.g., “Taberna X” with est_pp).

Acceptance

  • When asked for dining, returns a small list; otherwise omitted.

5) Implement landed-cost normalization (transparent pricing)

Files

  • app/normalizers/price.py:
    • Inputs: offer, user_cur, fx_rates, vat_fallback, promo_rules
    • Output: (landed, breakdown) where:
      • landed: {amount, currency}
      • breakdown: {base, fees, vat, promo, fx} (all rounded to 0.01)

Acceptance

  • VAT included → vat=0.
  • VAT excluded → apply vat_fallback if vat_rate is None.
  • Percent vs fixed promos → choose best single promo.

6) Add multi-vendor reconciliation

Files

  • app/reconcile/merge.py: group offers by (title,start_ts); keep lowest landed; attach provenance array with each vendor’s landed + URL.

Acceptance

  • Multiple offers for the same event return one item with provenance ≥2.

7) Price-drop classifier (optional) + buy-now policy

Files

  • app/models/price_drop/features.py: rolling min/std over a series (stub OK)
  • app/models/price_drop/policy.py:
    • predict_prob(series) loads model if present; else simple heuristic using inventory_hint.
    • buy_now_policy(prob, days_to_event, threshold, min_days_force_buy).

Acceptance

  • If model file missing, function still returns a probability in [0,1].
  • buy_now_policy flips to True when close to event or very low inventory.

8) Budget-aware scoring

Files

  • app/ranking/scorer.py:
    • Penalize over-budget, add slight penalty for total cost incl. dining, add small bonus if price likely to drop and there’s time.

Acceptance

  • Higher scores for within-budget options; tie-breakers behave sensibly.

9) CLI pipeline

Files

  • app/main.py:
    • Build a single event query for a given date/city.
    • Fetch offers from both vendors.
    • Compute landed + breakdown, predict drop prob, compute buy_now, optionally add dining, compute score.
    • Reconcile multi-vendor, sort by score, print top 1–3 itineraries as JSON.

Acceptance

  • Offline run prints valid itineraries JSON with fields:
    • event_title, start_ts, best_price:{landed,breakdown,provider,price_drop_prob_7d,buy_now,url}, meal_bundle, score, provenance (after reconcile).

10) Minimal API (optional)

Files

  • app/server.py with GET /plan?date=YYYY-MM-DD&budget=35&with_dining=true.
  • Returns same schema as CLI; may embed small HTML tester page.

Acceptance

  • Local call returns JSON; includes an fx_source field for visibility.

11) Tests (must pass offline)

Files

  • tests/test_landed_cost.py: VAT-included, VAT-excluded, percent vs fixed promo, FX pivot USD→EUR.
  • tests/test_reconcile.py: ensures best landed wins, provenance attached.

Acceptance

  • pytest -q passes without internet or tokens.

Configuration

  • app/config/settings.example.yaml
    • currency: "EUR"
    • pricing.vat_fallback_rate
    • pricing.promo_rules (e.g., STUDENT10, LOYALTY5)
    • model.price_drop_threshold, model.min_days_force_buy
    • apis.fx.base_url
  • ENV overrides (optional): VENDOR_A_TOKEN, VENDOR_B_TOKEN, DINING_TOKEN.

Deliverables Checklist

  • Offline-capable connectors (FX + vendors + dining stub).
  • Landed-cost math with per-offer transparent breakdown.
  • Reconciliation across vendors with provenance.
  • Buy-now policy + budget-aware scoring.
  • CLI that prints itineraries JSON.
  • (Optional) API endpoint.
  • Dummy dataset under data/dummy/.
  • Passing tests (VAT/fees/promo/FX/reconcile/score).
  • Updated README explaining setup, offline mode, and how to extend.

Verification (Offline)

  1. Disconnect network (or block outbound).
  2. Ensure no tokens are set.
  3. Run CLI for a date; expect valid JSON with fx_source = builtin/last_good.
  4. Run tests; expect all green.

Notes & Constraints

  • Keep third-party deps minimal; offline behavior must not import heavy clients except when available.
  • Do not remove or rewrite existing modules outside the scope above; add new modules or extend in place.
  • All money math rounded to 2 decimals in the breakdown + landed total.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions