EstiMate
A mobile-first contractor cost estimation app that uses Monte Carlo simulation to provide probabilistic risk analysis for job quotes. Built natively for iOS (SwiftUI) and Android (Jetpack Compose).
Overview
EstiMate helps tradespeople and contractors move beyond single-point estimates to understand the range of likely costs and risks. Instead of guessing a single number, you input your estimates with uncertainty levels, and the app runs thousands of simulations to show you the probability distribution of total costs.
Key Value Propositions:
- Offline-first, no login required
- Sophisticated risk analysis on mobile (usually reserved for enterprise desktop software)
- Helps contractors avoid under-quoting with statistically safe quote recommendations
- Generates professional PDF quotes for clients
Features
Core Estimation
- Project Management - Create, save, and manage multiple project estimates
- Line Items - Add materials, labor, subcontractors, and other costs
- Risk Levels - 5-tier uncertainty system:
- Certain (Β±2%) - Fixed/contracted prices
- Low (Β±8%) - Known suppliers with stable pricing
- Medium (Β±15%) - Standard market variability
- High (Β±25%) - Volatile or uncertain costs
- Wild Guess (Β±40%) - Unknown scope items
Duration & Travel Estimation
- Job Duration - Estimated days with complexity levels (Routine Β±10% to Unknown Scope Β±60%)
- Labor Configuration - Hourly rates, hours per day, extra workers
- Travel Costs - One-way travel time, traffic variability, site visits, mileage tracking
- Correlation Modeling - Duration uncertainty automatically affects travel costs
Monte Carlo Simulation
- 1,000+ iterations with convergence detection
- Skewed distribution toward overages (realistic for construction projects)
- Percentile outputs: P10, P50, P80, P90, P95
- Cost breakdown by category (Materials, Duration, Travel)
- Standard deviation and confidence level calculations
Results & Export
- Bell Curve Visualization - Color-coded histogram of cost distribution
- Quote Recommendations - Conservative (P50), Recommended (P80), Safe (P90)
- PDF Export - Professional client-facing quotes with cost breakdowns
- Share - Export via platform share sheets
Internationalization
| Region | Currency | Distance | Terminology |
|---|
| US | USD ($) | Miles | Contractor, Labor |
| UK | GBP (Β£) | Miles | Tradesperson, Labour |
| Canada | CAD ($) | Kilometers | Contractor, Labour |
| Australia | AUD ($) | Kilometers | Tradie, Labour |
| New Zealand | NZD ($) | Kilometers | Tradie, Labour |
Tech Stack
iOS
- Language: Swift
- UI Framework: SwiftUI
- Architecture: MVVM
- Min iOS: 14.0+
- Storage: UserDefaults (local only)
- PDF: PDFKit/UIGraphicsPDFRenderer
- Charts: Apple Charts framework (iOS 16.4+)
Android
- Language: Kotlin
- UI Framework: Jetpack Compose
- Architecture: MVVM with ViewModel + StateFlow
- Min SDK: 26 (Android 8.0)
- Target SDK: 34 (Android 14)
- Storage: SharedPreferences + GSON
- PDF: iText 7
- Navigation: Jetpack Navigation Compose
Project Structure
contractors_app/
βββ ios/RiskEstimator/ # iOS application
β βββ RiskEstimator/
β βββ RiskEstimatorApp.swift # App entry point
β βββ ContentView.swift # Root navigation
β βββ ViewModels/
β β βββ EstimatorViewModel.swift
β βββ Models/
β β βββ Project.swift
β β βββ LineItem.swift
β β βββ Worker.swift
β β βββ SimulationResult.swift
β βββ Services/
β β βββ MonteCarloEngine.swift
β β βββ StorageService.swift
β β βββ PDFService.swift
β βββ Views/
β β βββ Screens/
β β β βββ HomeScreen.swift
β β β βββ EstimatorScreen.swift
β β β βββ ResultsScreen.swift
β β βββ Components/
β β βββ RiskSlider.swift
β β βββ ComplexitySlider.swift
β β βββ TrafficSlider.swift
β β βββ BellCurveChart.swift
β β βββ ...
β βββ Utils/
β βββ Localization.swift
β βββ CurrencyFormatter.swift
β
βββ android/RiskEstimator/ # Android application
β βββ app/src/main/java/com/riskestimator/app/
β βββ MainActivity.kt
β βββ ui/
β β βββ RiskEstimatorApp.kt
β β βββ EstimatorViewModel.kt
β β βββ screens/
β β β βββ HomeScreen.kt
β β β βββ EstimatorScreen.kt
β β β βββ ResultsScreen.kt
β β βββ components/
β β β βββ RiskSlider.kt
β β β βββ BellCurveChart.kt
β β β βββ ...
β β βββ theme/
β βββ data/
β β βββ model/
β β βββ repository/
β βββ domain/
β βββ MonteCarloEngine.kt
β βββ PDFService.kt
β
βββ icons/ # App icon assets
βββ PROGRESS.md # Project roadmap & status
βββ contractor_app_market_research.md
Architecture
Both platforms follow the MVVM (Model-View-ViewModel) pattern:
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Views β
β (SwiftUI Views / Jetpack Compose Screens) β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β ViewModel β
β - Manages UI state β
β - Coordinates between Views and Services β
β - Triggers simulations β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β
βββββββββββββββββΌββββββββββββββββ
βΌ βΌ βΌ
βββββββββββββββββββ βββββββββββββ βββββββββββββββββββ
β MonteCarloEngineβ βStorageRepoβ β PDFService β
β β β β β β
β - Simulation β β - CRUD β β - Generate PDF β
β - Statistics β β - Persist β β - Export β
βββββββββββββββββββ βββββββββββββ βββββββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β Models β
β Project, LineItem, Worker, SimulationResult β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
Data Models
Project
struct Project {
id: UUID
name: String
clientName: String
createdAt: Date
profitMargin: Double // Default 15%
lineItems: [LineItem]
workers: [Worker] // iOS only
estimatedDays: Double
complexityLevel: ComplexityLevel
hourlyLaborRate: Double
hoursPerDay: Double
travelTimeMinutes: Double
trafficVariability: TrafficVariability
numberOfSiteVisits: Int // 0 = auto-calculate
includeReturnTrip: Bool
mileageRate: Double
distance: Double
}
LineItem
struct LineItem {
id: UUID
name: String
estimatedCost: Double
category: ItemCategory // Material, Labor, Subcontractor, Other
riskLevel: RiskLevel // Certain, Low, Medium, High, WildGuess
}
SimulationResult
struct SimulationResult {
simulations: [Double] // All iteration results
percentile10/50/80/90/95: Double
mean: Double
standardDeviation: Double
min, max: Double
// Category breakdowns
materialCostP50/P80: Double
durationCostP50/P80: Double
travelCostP50/P80: Double
iterationsRun: Int
isConverged: Bool
}
Risk/Variance Multipliers
| Level | Variance | Use Case |
|---|
| Certain | Β±2% | Fixed contracts, locked prices |
| Low | Β±8% | Reliable suppliers, stable costs |
| Medium | Β±15% | Standard market variability |
| High | Β±25% | Volatile materials, uncertain labor |
| Wild Guess | Β±40% | Unknown scope, new vendors |
| Complexity | Variance | Use Case |
|---|
| Routine | Β±10% | Repeat jobs, familiar scope |
| Moderate | Β±25% | Standard projects |
| Complex | Β±40% | Multi-trade, custom work |
| Unknown Scope | Β±60% | Discovery needed, unknowns |
| Traffic | Variance | Use Case |
|---|
| Predictable | Β±10% | Rural, fixed schedule |
| Variable | Β±25% | Suburban, normal traffic |
| High Variability | Β±50% | Urban, rush hour |
Getting Started
iOS
- Open
ios/RiskEstimator/RiskEstimator.xcodeproj in Xcode
- Select your target device or simulator
- Build and run (βR)
Requirements:
- Xcode 14.0+
- iOS 14.0+ deployment target
- Swift 5.0+
Android
- Open
android/RiskEstimator in Android Studio
- Sync Gradle files
- Select your target device or emulator
- Build and run
Requirements:
- Android Studio Hedgehog or later
- JDK 17
- Android SDK 26+ (min) / 34 (target)
Monte Carlo Simulation
The simulation engine uses the Box-Muller transform to generate normally distributed random values with optional skew toward overages (reflecting real-world project behavior).
Algorithm
For each iteration (1,000 - 10,000):
1. For each line item:
- Generate random variance based on risk level
- Apply skewed normal distribution (bias toward overages)
- Calculate simulated cost
2. For duration:
- Generate random variance based on complexity
- Calculate labor cost = days Γ hours Γ rate
3. For travel:
- Correlate visits with duration uncertainty
- Generate traffic variance
- Calculate travel time + mileage costs
4. Sum all costs + profit margin
Calculate statistics from all iterations
Check for convergence (P80 standard error < 0.5%)