{
 "$schema": "https://json-schema.org/draft/2020-12/schema",
 "$id": "https://khoshkhah.github.io/roadstyle/samples/bridge-profile/bridge_profile_complete.schema.json",
 "title": "The complete input profile of a group of 3D bridges: what Part 1 writes and Part 2 reads ",
 "type": "object",
 "additionalProperties": false,
 "properties": {
  "format": {
   "const": "roadstyle.bridge_profile/1"
  },
  "parameters": {
   "$ref": "#/$defs/parameters"
  },
  "ground": {
   "$ref": "#/$defs/ground"
  },
  "groups": {
   "type": "array",
   "items": {
    "$ref": "#/$defs/group"
   },
   "minItems": 1
  }
 },
 "$defs": {
  "lonlat": {
   "type": "array",
   "prefixItems": [
    {
     "type": "number",
     "minimum": -180,
     "maximum": 180
    },
    {
     "type": "number",
     "minimum": -90,
     "maximum": 90
    }
   ],
   "items": false,
   "minItems": 2
  },
  "point": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "s": {
     "type": "number",
     "minimum": 0,
     "description": "Metres from the first end of the chain"
    },
    "z_m": {
     "type": "number",
     "description": "The height of the point above the ground, 0 or more (with z_reference elevation: its elevation)"
    },
    "curve_m": {
     "type": "number",
     "minimum": 0,
     "description": "The length of the vertical curve around the point, in metres (0: none). The filler writes it; the maker needs it"
    },
    "source": {
     "type": "string",
     "description": "Where the value comes from: data, rule, given, example, a survey..."
    },
    "method": {
     "enum": [
      "mapped",
      "measured",
      "derived",
      "chosen"
     ],
     "description": "How it was found"
    }
   },
   "required": [
    "s",
    "z_m"
   ]
  },
  "ground": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "id": {
     "type": "string",
     "description": "The ground id: the SHA-256 of the elevation file (duckOSM main.elevation_metadata.sha256)"
    },
    "source": {
     "type": "string"
    },
    "product": {
     "type": "string",
     "description": "DTM or DSM"
    },
    "vertical_datum": {
     "type": "string"
    }
   }
  },
  "parameters": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "design_speed_kmh": {
     "type": "number",
     "exclusiveMinimum": 0,
     "maximum": 200
    },
    "design_grade": {
     "type": "number",
     "exclusiveMinimum": 0,
     "maximum": 0.3
    },
    "curve": {
     "enum": [
      "smooth",
      "design"
     ],
     "description": "smooth: the curve of today. design: straight grades and vertical curves"
    },
    "height_rule": {
     "enum": [
      "length",
      "design"
     ],
     "description": "How the filler finds a height that was not given. length: today's rule. design: the design rules"
    },
    "z_reference": {
     "enum": [
      "ground",
      "elevation"
     ],
     "description": "What z_m is. ground: metres above the ground of the page (the default; a free end is 0). elevation: the elevation in the vertical datum of the profile's ground (every node needs one)"
    }
   },
   "required": [
    "design_speed_kmh",
    "design_grade"
   ]
  },
  "node": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "id": {
     "type": "string",
     "pattern": "^n[0-9]+$",
     "description": "The id of the node in a complete profile"
    },
    "lonlat": {
     "$ref": "#/$defs/lonlat",
     "description": "The position of the node. In a partial input it names the node: the node of the group within 5 m"
    },
    "kind": {
     "enum": [
      "ground",
      "junction"
     ],
     "description": "ground: one chain ends here, height 0. junction: chains meet here"
    },
    "portal": {
     "type": "boolean",
     "description": "A free end where the deck goes straight into a tunnel (a road of level below 0 starts at the node). The engine writes it; with z_reference elevation the page does not check the ground there"
    },
    "chains": {
     "type": "array",
     "items": {
      "type": "string",
      "pattern": "^c[0-9]+$"
     },
     "description": "The chains that meet at the node"
    },
    "z_m": {
     "type": "number",
     "description": "The height of the node above the ground, in metres, 0 or more (with z_reference elevation: its elevation in the datum of the ground, any number)"
    },
    "source": {
     "type": "string",
     "description": "Where the value comes from: data, rule, given, example, a survey..."
    },
    "method": {
     "enum": [
      "mapped",
      "measured",
      "derived",
      "chosen"
     ],
     "description": "How it was found"
    }
   },
   "required": [
    "id",
    "lonlat",
    "kind",
    "chains",
    "z_m",
    "source",
    "method"
   ]
  },
  "chain": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "id": {
     "type": "string",
     "pattern": "^c[0-9]+$"
    },
    "osm_ways": {
     "type": "array",
     "items": {
      "type": "integer"
     },
     "description": "The OSM ways of the chain, when the roads have them. In a partial input they name the chain"
    },
    "length_m": {
     "type": "number",
     "exclusiveMinimum": 0
    },
    "from": {
     "type": "string",
     "pattern": "^n[0-9]+$",
     "description": "The node at the first end of the chain"
    },
    "to": {
     "type": "string",
     "pattern": "^n[0-9]+$",
     "description": "The node at the last end of the chain"
    },
    "points": {
     "type": "array",
     "items": {
      "$ref": "#/$defs/point"
     },
     "description": "Interior control points, in order of s (the curve design)"
    },
    "top_m": {
     "type": "number",
     "description": "The full height of the chain: the height that its ramps are made for (the curve smooth). The page's __rs_full. Above 0 (with z_reference elevation: the highest elevation of the chain)"
    },
    "width_m": {
     "type": "number",
     "exclusiveMinimum": 0,
     "description": "The width of the deck, in metres. Without it, each road is drawn at the width of its class"
    },
    "width_source": {
     "type": "string"
    }
   },
   "required": [
    "id",
    "length_m",
    "from",
    "to",
    "points"
   ]
  },
  "group": {
   "type": "object",
   "additionalProperties": false,
   "properties": {
    "name": {
     "type": "string"
    },
    "nodes": {
     "type": "array",
     "items": {
      "$ref": "#/$defs/node"
     }
    },
    "chains": {
     "type": "array",
     "items": {
      "$ref": "#/$defs/chain"
     }
    }
   },
   "required": [
    "name",
    "nodes",
    "chains"
   ]
  }
 },
 "required": [
  "format",
  "parameters",
  "groups"
 ],
 "if": {
  "required": [
   "parameters"
  ],
  "properties": {
   "parameters": {
    "required": [
     "z_reference"
    ],
    "properties": {
     "z_reference": {
      "const": "elevation"
     }
    }
   }
  }
 },
 "then": {
  "required": [
   "ground"
  ],
  "properties": {
   "ground": {
    "required": [
     "id"
    ]
   },
   "parameters": {
    "properties": {
     "curve": {
      "const": "design"
     }
    }
   }
  }
 },
 "else": {
  "properties": {
   "groups": {
    "items": {
     "properties": {
      "nodes": {
       "items": {
        "properties": {
         "z_m": {
          "minimum": 0
         }
        }
       }
      },
      "chains": {
       "items": {
        "properties": {
         "top_m": {
          "exclusiveMinimum": 0
         },
         "points": {
          "items": {
           "properties": {
            "z_m": {
             "minimum": 0
            }
           }
          }
         }
        }
       }
      }
     }
    }
   }
  }
 }
}
