{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://torrent100.com/hotdeal/archive/schema.json",
  "title": "요즘인기여행 데이터 아카이브",
  "description": "facts/*.jsonl.gz 의 한 줄(fact)과 daily/*.json.gz·latest.json 의 형식. 설명은 SCHEMA.md.",
  "$defs": {
    "date": { "type": "string", "pattern": "^\\d{4}-\\d{2}-\\d{2}$" },
    "datetime": { "type": ["string", "null"], "pattern": "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(\\.\\d+)?(Z|[+-]\\d{2}:\\d{2})$" },
    "country": { "type": ["string", "null"], "pattern": "^[A-Z]{2}$" },
    "metric": {
      "enum": [
        "package_weekly_buyers", "package_price", "package_trend_price", "package_price_20d_high", "package_rating", "package_review_count",
        "destination_weekly_buyers", "destination_price_drop_count", "country_weekly_buyers", "population_weekly_buyers",
        "flight_roundtrip_price",
        "hotel_price", "hotel_rating", "hotel_review_count",
        "tour_price_from", "tour_rating", "tour_review_count",
        "esim_min_price", "esim_min_affiliate_price", "esim_seller_count",
        "site_visitors", "site_pageviews", "link_clicks"
      ]
    },
    "entity_type": { "enum": ["package", "destination", "country", "population", "flight_route", "hotel", "tour", "esim_country", "channel", "click_type", "click_merchant"] },
    "unit": { "enum": ["KRW", "count", "rating_5", "rating_10"] },
    "source": { "enum": ["naver_package", "myrealtrip", "tripcom", "agoda", "cheapest_esim", "own_service"] },
    "fact": {
      "type": "object",
      "additionalProperties": false,
      "required": ["observed_date", "observed_at", "source", "metric", "entity_type", "entity_id", "entity_name", "city", "country", "series_id", "condition", "value", "unit"],
      "properties": {
        "observed_date": { "$ref": "#/$defs/date" },
        "observed_at": { "$ref": "#/$defs/datetime" },
        "source": { "$ref": "#/$defs/source" },
        "metric": { "$ref": "#/$defs/metric" },
        "entity_type": { "$ref": "#/$defs/entity_type" },
        "entity_id": { "type": "string", "pattern": "^[a-z-]+:.+$" },
        "entity_name": { "type": ["string", "null"] },
        "city": { "type": ["string", "null"] },
        "country": { "$ref": "#/$defs/country" },
        "series_id": { "type": "string", "pattern": "^[a-z_0-9]+\\|[a-z-]+:" },
        "condition": { "type": "object" },
        "value": { "type": "number", "minimum": 0 },
        "unit": { "$ref": "#/$defs/unit" },
        "attrs": { "type": "object" }
      }
    },
    "daily_row": {
      "type": "object",
      "additionalProperties": false,
      "required": ["series_id", "metric", "entity_id", "entity_name", "city", "country", "unit", "condition", "observed_date", "value", "prev_date", "prev_value", "change_pct", "obs_30d", "median_30d", "min_30d", "max_30d", "vs_median_30d_pct", "is_30d_low"],
      "properties": {
        "series_id": { "type": "string" },
        "metric": { "$ref": "#/$defs/metric" },
        "entity_id": { "type": "string" },
        "entity_name": { "type": ["string", "null"] },
        "city": { "type": ["string", "null"] },
        "country": { "$ref": "#/$defs/country" },
        "unit": { "$ref": "#/$defs/unit" },
        "condition": { "type": "object" },
        "observed_date": { "$ref": "#/$defs/date" },
        "value": { "type": "number" },
        "prev_date": { "type": ["string", "null"] },
        "prev_value": { "type": ["number", "null"] },
        "change_pct": { "type": ["number", "null"] },
        "obs_30d": { "type": "integer", "minimum": 0 },
        "median_30d": { "type": ["number", "null"] },
        "min_30d": { "type": ["number", "null"] },
        "max_30d": { "type": ["number", "null"] },
        "vs_median_30d_pct": { "type": ["number", "null"] },
        "is_30d_low": { "type": ["boolean", "null"] },
        "source": { "$ref": "#/$defs/source" },
        "observed_at": { "type": ["string", "null"] },
        "attrs": { "type": "object" }
      }
    },
    "daily": {
      "type": "object",
      "required": ["date", "generated_at", "schema", "series_count", "series"],
      "properties": {
        "date": { "$ref": "#/$defs/date" },
        "generated_at": { "$ref": "#/$defs/datetime" },
        "schema": { "type": "string" },
        "cite": { "type": "object" },
        "note": { "type": "string" },
        "series_count": { "type": "integer" },
        "series": { "type": "array", "items": { "$ref": "#/$defs/daily_row" } }
      }
    },
    "entity": {
      "type": "object",
      "additionalProperties": false,
      "required": ["entity_id", "entity_type", "name", "city", "country", "source_ids", "info", "first_seen", "last_seen"],
      "properties": {
        "entity_id": { "type": "string", "pattern": "^[a-z-]+:.+$" },
        "entity_type": { "$ref": "#/$defs/entity_type" },
        "name": { "type": ["string", "null"] },
        "city": { "type": ["string", "null"] },
        "country": { "$ref": "#/$defs/country" },
        "source_ids": { "type": "object" },
        "info": { "type": "object" },
        "first_seen": { "$ref": "#/$defs/date" },
        "last_seen": { "$ref": "#/$defs/date" }
      }
    }
  }
}
