Domain: Business Operations & Analytics

You are given these CSV files in the working directory:

- `SalesMind_Sales_Transactions_2026.csv`
- `SalesMind_Products_Master_2026.csv`
- `SalesMind_Calendar_Dimension_2026.csv`

Your task is to measure revenue concentration across seasons for calendar year 2024.

## Goal

Compute the Herfindahl-Hirschman Index (HHI) for `net_sales` revenue distributed across `product_category`, separately for each season in calendar year `2024`.

The HHI for a season is:

`sum(category_revenue_share^2)`

where each share is that category's portion of total `net_sales` within the season.

## Required cleaning and joins

### Sales transactions

1. Read `SalesMind_Sales_Transactions_2026.csv`.
2. Convert these columns to numeric with invalid values treated as missing:
   - `net_sales`
   - `gross_profit`
   - `total_sales_revenue`
   - `total_discount_given`
3. Parse `date` using mixed formats that appear in the file, including:
   - `YYYY-MM-DD`
   - `DD/MM/YYYY`
4. Drop rows with unparseable `date` or missing `net_sales`.
5. Remove exact duplicate rows.
6. Trim whitespace from `customer_segment`.
7. Drop rows where:
   - `net_sales <= 0`
   - `gross_profit > net_sales`

### Products master

1. Read `SalesMind_Products_Master_2026.csv`.
2. Trim whitespace from `product_category` and `brand`.
3. Deduplicate on `product_id`, keeping the first occurrence.

### Calendar dimension

1. Read `SalesMind_Calendar_Dimension_2026.csv`.
2. Parse `date` using the formats present in the file.
3. If duplicate calendar dates exist with conflicting season labels, resolve them by keeping the entry whose `season` matches the meteorological season for that month:
   - Winter: December, January, February
   - Spring: March, April, May
   - Summer: June, July, August
   - Autumn: September, October, November
4. After scoring duplicates by whether they match the meteorological season, keep the best row for each date.

## Analysis steps

1. Restrict sales rows to calendar year `2024`.
2. Inner join sales with products on `product_id`.
3. Join calendar on parsed `date` to obtain `season`.
4. For each season, sum `net_sales` by `product_category`.
5. Convert category totals to within-season revenue shares.
6. Compute HHI as the sum of squared shares.

## Output format

Return the result as a JSON object with:

- season names as keys
- HHI values as numbers rounded to 4 decimal places
- keys sorted alphabetically by season name

Print only the final JSON object.

Grading rubric:
criterion: The output is a valid JSON object containing exactly 4 keys: `Autumn`, `Spring`, `Summer`, and `Winter`, each mapped to a numeric value.
weight: 10
criterion: The solution correctly reads the three local CSV files, parses mixed sales and calendar date formats, converts the required sales numeric columns with invalid values treated as missing, removes exact duplicate sales rows, trims product/category string fields, and filters out sales rows with missing dates, missing net_sales, non-positive net_sales, or gross_profit greater than net_sales.
weight: 15
criterion: The products master is deduplicated on `product_id` keeping the first row, and the calendar dimension resolves duplicate dates by preferring the meteorologically correct season label.
weight: 15
criterion: The HHI value for `Spring` is exactly `0.3351`.
weight: 10
criterion: The HHI value for `Autumn` is exactly `0.3591`.
weight: 10
criterion: The HHI value for `Summer` is exactly `0.3413`.
weight: 10
criterion: The HHI value for `Winter` is exactly `0.3512`.
weight: 10
criterion: The complete ordering of seasons from highest to lowest HHI is `Autumn`, `Winter`, `Summer`, `Spring`.
weight: 10
criterion: The full returned JSON object is exactly `{"Autumn": 0.3591, "Spring": 0.3351, "Summer": 0.3413, "Winter": 0.3512}`.
weight: 10

Golden answer:
```python
import csv
import json
from collections import defaultdict
from datetime import datetime
from pathlib import Path


BASE_DIR = Path(__file__).resolve().parent
SALES_PATH = BASE_DIR / "SalesMind_Sales_Transactions_2026.csv"
PRODUCTS_PATH = BASE_DIR / "SalesMind_Products_Master_2026.csv"
CALENDAR_PATH = BASE_DIR / "SalesMind_Calendar_Dimension_2026.csv"


def to_float(value):
    try:
        if value is None:
            return None
        text = str(value).strip()
        if text == "" or text.lower() in {"missing", "nan", "null"}:
            return None
        return float(text)
    except (TypeError, ValueError):
        return None


def parse_sales_date(value):
    text = "" if value is None else str(value).strip()
    for fmt in ("%Y-%m-%d", "%d/%m/%Y", "%m-%d-%Y"):
        try:
            return datetime.strptime(text, fmt).date()
        except ValueError:
            pass
    return None


def parse_calendar_date(value):
    text = "" if value is None else str(value).strip()
    for fmt in ("%Y-%m-%d", "%m-%d-%Y", "%d/%m/%Y"):
        try:
            return datetime.strptime(text, fmt).date()
        except ValueError:
            pass
    return None


def solve():
    sales_rows = []
    with SALES_PATH.open(newline="", encoding="utf-8") as handle:
        reader = csv.DictReader(handle)
        for row in reader:
            row["date_parsed"] = parse_sales_date(row.get("date"))
            for column in ["net_sales", "gross_profit", "total_sales_revenue", "total_discount_given"]:
                row[column + "_num"] = to_float(row.get(column))
            sales_rows.append(row)

    cleaned_sales = []
    seen_rows = set()
    for row in sales_rows:
        if row["date_parsed"] is None or row["net_sales_num"] is None:
            continue
        duplicate_key = tuple(
            row[column]
            for column in row
            if not column.endswith("_parsed") and not column.endswith("_num")
        )
        if duplicate_key in seen_rows:
            continue
        seen_rows.add(duplicate_key)
        if row["net_sales_num"] <= 0:
            continue
        if row["gross_profit_num"] is not None and row["gross_profit_num"] > row["net_sales_num"]:
            continue
        row["customer_segment"] = (row.get("customer_segment") or "").strip()
        cleaned_sales.append(row)

    products_by_id = {}
    with PRODUCTS_PATH.open(newline="", encoding="utf-8") as handle:
        reader = csv.DictReader(handle)
        for row in reader:
            product_id = row["product_id"]
            if product_id in products_by_id:
                continue
            row["product_category"] = (row.get("product_category") or "").strip()
            row["brand"] = (row.get("brand") or "").strip()
            products_by_id[product_id] = row

    meteorological_season = {
        1: "Winter",
        2: "Winter",
        3: "Spring",
        4: "Spring",
        5: "Spring",
        6: "Summer",
        7: "Summer",
        8: "Summer",
        9: "Autumn",
        10: "Autumn",
        11: "Autumn",
        12: "Winter",
    }
    best_calendar_row = {}
    with CALENDAR_PATH.open(newline="", encoding="utf-8") as handle:
        reader = csv.DictReader(handle)
        for row in reader:
            date_value = parse_calendar_date(row.get("date"))
            if date_value is None:
                continue
            season = row.get("season")
            score = 1 if season == meteorological_season[date_value.month] else 0
            candidate = ((score, season), season)
            if date_value not in best_calendar_row or candidate[0] > best_calendar_row[date_value][0]:
                best_calendar_row[date_value] = candidate
    season_by_date = {date_value: season for date_value, (_, season) in best_calendar_row.items()}

    sales_by_season_category = defaultdict(lambda: defaultdict(float))
    for row in cleaned_sales:
        if row["date_parsed"].year != 2024:
            continue
        product = products_by_id.get(row["product_id"])
        if product is None:
            continue
        season = season_by_date.get(row["date_parsed"])
        if season is None:
            continue
        category = product["product_category"]
        sales_by_season_category[season][category] += row["net_sales_num"]

    result = {}
    for season in sorted(sales_by_season_category):
        total_sales = sum(sales_by_season_category[season].values())
        hhi = sum((category_sales / total_sales) ** 2 for category_sales in sales_by_season_category[season].values())
        result[season] = round(hhi, 4)

    print(json.dumps(result, sort_keys=True))
    return result


if __name__ == "__main__":
    solve()
```

**Reasoning**

The draft task is aligned with the real warehouse-style files, but the provided expected values were incorrect for the local dataset. The verified solution reads the sales, products, and calendar tables from the task directory, converts the required sales measures to numeric, parses mixed date formats, removes invalid sales rows and exact duplicates, trims relevant string fields, deduplicates the product master on `product_id`, resolves conflicting calendar season labels by preferring meteorologically correct labels, filters sales to calendar year 2024, joins sales to product categories and seasons, and then computes seasonal HHI from category-level `net_sales` shares. On the actual local files, Autumn is the most concentrated season and Spring is the least concentrated.

```json
{"Autumn": 0.3591, "Spring": 0.3351, "Summer": 0.3413, "Winter": 0.3512}
```