from __future__ import annotations from dataclasses import dataclass @dataclass(frozen=True) class BaselineAssumptions: total_reference_population: int = 10_000_000 uncertainty_low: float = 0.72 uncertainty_high: float = 1.28 BASELINE = BaselineAssumptions() BASELINE_REFERENCE_OPTIONS = { "demo_reference_pool": { "label": "Demo working pool (10M)", "value": 10_000_000, "note": "Synthetic starting universe for scenario testing; not the full Ukraine population.", }, "sssu_jan_2022_total": { "label": "SSSU Jan 2022 total population", "value": 41_167_335, "note": "Official pre-full-scale-invasion total population estimate cited by ACAPS.", }, "custom": { "label": "Custom starting pool", "value": 1_000_000, "note": "Editable starting universe for a narrower adult, regional, platform, or pre-filtered pool.", }, } SALARY_ANCHORS_UAH = { "official_pfu_2025_average": 20_654, "kse_workua_jan_2026_median": 27_500, "workua_current_average": 28_600, } INCOME_THRESHOLD_OPTIONS_UAH = [ 0, 20_000, 25_000, 30_000, 35_000, 40_000, 45_000, 50_000, 60_000, 70_000, 80_000, 90_000, 100_000, 125_000, 150_000, 200_000, 250_000, 300_000, 400_000, 500_000, 750_000, 1_000_000, ] INCOME_CURVE_POINTS_UAH = [ (0, 1.0), (SALARY_ANCHORS_UAH["official_pfu_2025_average"], 0.55), (SALARY_ANCHORS_UAH["workua_current_average"], 0.42), (45_000, 0.25), (70_000, 0.10), (100_000, 0.055), (200_000, 0.015), (500_000, 0.002), (750_000, 0.001), (1_000_000, 0.0005), ] SOURCE_LINKS = [ { "label": "Work.ua salary statistics", "url": "https://www.work.ua/en/salary-all/", "note": "Current salary benchmark from job postings; Work.ua states that the median is calculated from recent vacancies.", }, { "label": "KSE Ukraine Monthly Economic Update, February 2026", "url": "https://institute.kse.ua/wp-content/uploads/2026/02/ukraine_monthly_economic_update_eng_february_2026.pdf", "note": "Cites Work.ua January 2026 offered median salary of UAH 27,500.", }, { "label": "Pension Fund of Ukraine average wage indicator, 2025", "url": "https://www.pfu.gov.ua/2170600-pokaznyk-serednoyi-zarobitnoyi-platy-za-2025-rik/", "note": "Official average wage indicator used for pension calculations; annual 2025 value is UAH 20,653.55.", }, { "label": "DOU developer salary statistics", "url": "https://jobs.dou.ua/salaries/?switch_lang=en", "note": "IT salary survey and CSV-backed salary analytics for Ukrainian tech roles.", }, { "label": "Djinni salary guide", "url": "https://guide.djinni.co/salaries", "note": "Tech salary benchmarks for Ukraine-focused hiring; useful for high-income scenario context.", }, { "label": "ACAPS Ukraine population data sources report", "url": "https://www.acaps.org/fileadmin/Data_Product/Main_media/20230818_ACAPS_Thematic_report_Ukraine_estimates_and_sources_of_population_data.pdf", "note": "Explains baseline population datasets and cites SSSU January 2022 total population estimate.", }, { "label": "State Statistics Service of Ukraine 2022 overview", "url": "https://www.ukrstat.gov.ua/operativ/infografika/2022/o_soc_ek_Ukr/01_2022_e.pdf", "note": "Official population-statistics context and methodology notes.", }, ] AGE_BAND_FACTORS = { "18-24": 0.12, "25-34": 0.22, "35-44": 0.20, "45-54": 0.18, "55-70": 0.28, } REGION_FACTORS = { "all_ukraine": 1.0, "large_cities": 0.34, "kyiv_region": 0.13, "western_regions": 0.24, } TARGET_POPULATION_FACTORS = { "all_adults": 1.0, "women": 0.53, "men": 0.47, } RELATIONSHIP_STATUS_FACTORS = { "any": 1.0, "not_married": 0.46, "single_or_divorced": 0.32, } HEIGHT_FACTORS = { 150: 1.0, 160: 0.92, 165: 0.82, 170: 0.67, 175: 0.48, 180: 0.28, 185: 0.13, 190: 0.04, } EDUCATION_FACTORS = { "any": 1.0, "higher_education": 0.38, "graduate_plus": 0.16, } CHILDREN_STATUS_FACTORS = { "any": 1.0, "no_children": 0.62, "has_children": 0.31, "co_parenting_ready": 0.18, } FUTURE_CHILDREN_FACTORS = { "any": 1.0, "wants_children": 0.48, "does_not_want_children": 0.22, "open_or_undecided": 0.58, } MILITARY_STATUS_FACTORS = { "any": 1.0, "civilian_or_not_serving": 0.91, "active_service": 0.07, "veteran_or_service_history": 0.15, } RELOCATION_FACTORS = { "any": 1.0, "same_city_only": 0.22, "open_to_relocation": 0.36, "remote_or_long_distance_ok": 0.44, } HOUSING_FACTORS = { "any": 1.0, "independent_living": 0.48, "own_or_stable_housing": 0.29, } SMOKING_FACTORS = { "any": 1.0, "non_smoker": 0.72, "ok_with_smoking": 1.0, } ALCOHOL_FACTORS = { "any": 1.0, "rare_or_none": 0.46, "moderate_ok": 0.76, } LANGUAGE_FACTORS = { "any": 1.0, "ukrainian_comfortable": 0.82, "english_comfortable": 0.38, "ukrainian_and_english": 0.31, } PETS_FACTORS = { "any": 1.0, "pet_friendly": 0.54, "no_pets_preferred": 0.42, } DATA_QUALITY_NOTES = [ { "label": "Population", "note": "Replace demo baseline with current age-sex population estimates before publication.", }, { "label": "Relationship status", "note": "Official marital status does not equal real availability; label as estimated.", }, { "label": "Income", "note": "Income thresholds above public medians are scenario cutoffs. Open sources do not provide a universal real maximum salary.", }, { "label": "Height", "note": "Height currently requires proxy distribution unless a Ukraine-specific source is validated.", }, { "label": "Military status", "note": "War-related filters are sensitive, time-changing, and should stay scenario-only until sourced.", }, { "label": "Children", "note": "Children and co-parenting filters are preference-context assumptions, not value judgments.", }, { "label": "Independence", "note": "Multiplying many filters assumes independence; use results as a stress test, not a factual census.", }, ]