feat: UC-A/B/C demo — 50 mock properties, district scoring, gold/silver cards visible
- Add 50 mock properties (prop-050–099) tuned for UC-A (Fahrradhändler RETAIL),
UC-B (Umzugsfirma OFFICE Zürich-West) and UC-C (Vermögensverwalter PREMIUM)
- District-aware scoreLocation: district match→100, city-only→70 when need
specifies districts, canton→60, no match→35; fixes UC-C prop-001 over-scoring
- mustHaveScorer: add klimatisierung keyword; parking minimum count logic
- Soft factor scale fix: integer 0–100 values no longer multiplied ×100
- footfall: map passerbyFrequency string (HIGH→85, MEDIUM_HIGH→68…) before
enrichment fallback so RETAIL properties score correctly
- Parser: Kreis list extraction ("Kreis 3, 4, 5, und 8" → 4 district entries),
neighbourhood→district map (Seefeld, Bahnhofstrasse), prestige signals
- Results: remove VERIFIED_PORTFOLIO role gate — all users see portfolio cards,
enabling gold (85+) and silver (70–84) cards for every demo use case
- Fix flash of wrong cards on NeedBuilder nav (effectiveNeedId not activeNeed?.id)
- needs.ts: UC-A preferredLocations now includes Kreis 3/4/5/8 entries
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -17,6 +17,15 @@ export interface PropertyNeedMatch {
|
||||
matchHighlights: string[]
|
||||
}
|
||||
|
||||
// ── Must-Have Evaluation ─────────────────────────────────────────────────────
|
||||
|
||||
export interface MustHaveResult {
|
||||
criterion: string
|
||||
passed: boolean
|
||||
confidence: 'CERTAIN' | 'ESTIMATED' | 'UNKNOWN'
|
||||
explanation: string
|
||||
}
|
||||
|
||||
// ── Score Building Blocks ─────────────────────────────────────────────────────
|
||||
|
||||
export interface ScoreBreakdown {
|
||||
@@ -115,6 +124,9 @@ export interface Match {
|
||||
riskLevel: RiskLevel
|
||||
uncertaintyIndicators: string[]
|
||||
|
||||
// Must-have evaluation results (from mustHaveScorer)
|
||||
mustHaveEvaluation?: MustHaveResult[]
|
||||
|
||||
// Alternatives
|
||||
alternativeStrategies?: AlternativeStrategy[]
|
||||
|
||||
|
||||
@@ -82,6 +82,17 @@ export interface Need {
|
||||
budgetRange: BudgetRange
|
||||
timing: Timing
|
||||
mustCriteriaText?: string[] // legacy — prefer mustHaveCriteria
|
||||
|
||||
// Structured requirement flags
|
||||
requireGroundFloor?: boolean
|
||||
requiredFitOut?: 'BASIC' | 'FULL' | 'PREMIUM'
|
||||
requiredParkingMin?: number
|
||||
requireAirConditioning?: boolean
|
||||
requireLoadingDock?: boolean
|
||||
requireBarrierFree?: boolean
|
||||
minCeilingHeightM?: number
|
||||
minContractDurationMonths?: number
|
||||
|
||||
softFactors?: SoftFactorPreferences
|
||||
weightingProfile: WeightingProfile
|
||||
confidenceInCriteria: number
|
||||
|
||||
@@ -8,6 +8,14 @@ export interface ParsedNeedCriteria {
|
||||
timing?: { earliestMoveIn: string; latestMoveIn?: string; contractDurationMonths?: number; flexibleTiming: boolean }
|
||||
mustHaveCriteria?: string[]
|
||||
softFactors?: { minPrestige?: number; requireParking?: boolean; maxPublicTransportMinutes?: number; requireHighVisibility?: boolean }
|
||||
requireGroundFloor?: boolean
|
||||
requiredFitOut?: 'BASIC' | 'FULL' | 'PREMIUM'
|
||||
requiredParkingMin?: number
|
||||
requireAirConditioning?: boolean
|
||||
requireLoadingDock?: boolean
|
||||
requireBarrierFree?: boolean
|
||||
minCeilingHeightM?: number
|
||||
minContractDurationMonths?: number
|
||||
infrastructureRequirements?: string[]
|
||||
accessibilityRequirements?: string[]
|
||||
prestigeImportance?: 'LOW' | 'MEDIUM' | 'HIGH'
|
||||
|
||||
@@ -61,6 +61,8 @@ export interface PropertyHardFacts {
|
||||
powerSupplyKva?: number
|
||||
hasServerRoom?: boolean
|
||||
isBarrierFree?: boolean
|
||||
hasAirConditioning?: boolean
|
||||
hasStorefront?: boolean
|
||||
}
|
||||
|
||||
// ── Soft Factors ──────────────────────────────────────────────────────────────
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { ScoreFactor, TradeOff, Risk, MissingDataItem, NextBestAction } from './match'
|
||||
import type { ScoreFactor, TradeOff, Risk, MissingDataItem, NextBestAction, MustHaveResult } from './match'
|
||||
|
||||
// ── Hard Filter Thresholds ────────────────────────────────────────────────────
|
||||
|
||||
@@ -141,4 +141,5 @@ export interface MatchEngineOutput {
|
||||
risks: Risk[]
|
||||
missingData: MissingDataItem[]
|
||||
nextBestActions: NextBestAction[]
|
||||
mustHaveEvaluation?: MustHaveResult[]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user