{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://raw.githubusercontent.com/nao1215/himorime/main/schema/report.schema.json",
  "title": "himorime JSON report",
  "description": "The report written by `himorime run|compare|ci --format json`. Durations are integer nanoseconds. Fields are only added within a schema_version.",
  "type": "object",
  "required": [
    "schema_version",
    "mode",
    "himorime_version",
    "seed",
    "started_at",
    "finished_at",
    "environment",
    "git",
    "suites",
    "summary"
  ],
  "additionalProperties": false,
  "properties": {
    "schema_version": {
      "description": "Report format version.",
      "type": "string",
      "enum": [
        "1"
      ]
    },
    "mode": {
      "description": "run for `himorime run`, compare for `himorime compare` and `himorime ci`.",
      "type": "string",
      "enum": [
        "run",
        "compare"
      ]
    },
    "himorime_version": {
      "description": "Version of the himorime that wrote the report.",
      "type": "string"
    },
    "seed": {
      "description": "Seed of the execution order and the bootstrap; pass it to --seed to reproduce the order.",
      "type": "integer",
      "minimum": 0,
      "maximum": 9007199254740991
    },
    "started_at": {
      "description": "Start time, RFC 3339.",
      "type": "string",
      "format": "date-time"
    },
    "finished_at": {
      "description": "Finish time, RFC 3339.",
      "type": "string",
      "format": "date-time"
    },
    "environment": {
      "description": "The machine. Host names and environment variables are never recorded.",
      "type": "object",
      "required": [
        "os",
        "arch",
        "cpu_model",
        "logical_cpus",
        "go_version",
        "ci",
        "tools"
      ],
      "additionalProperties": false,
      "properties": {
        "os": {
          "description": "GOOS, such as linux.",
          "type": "string"
        },
        "arch": {
          "description": "GOARCH, such as amd64.",
          "type": "string"
        },
        "cpu_model": {
          "description": "CPU model name, or empty when unknown.",
          "type": "string"
        },
        "logical_cpus": {
          "description": "Logical CPUs available.",
          "type": "integer",
          "minimum": 1
        },
        "go_version": {
          "description": "Go version himorime was built with.",
          "type": "string"
        },
        "ci": {
          "description": "github-actions, unknown (another CI), or empty.",
          "type": "string"
        },
        "tools": {
          "description": "Versions of the tools named in report.versions of the suites, in the order they are listed; empty when none are named.",
          "type": "array",
          "items": {
            "type": "object",
            "required": [
              "name",
              "version"
            ],
            "additionalProperties": false,
            "properties": {
              "name": {
                "description": "The tool's name as written in report.versions.",
                "type": "string",
                "minLength": 1
              },
              "version": {
                "description": "The first non-empty line the version command printed on standard output, or else on standard error, trimmed.",
                "type": "string",
                "minLength": 1
              }
            }
          }
        }
      }
    },
    "git": {
      "description": "Revisions measured; null outside a Git repository.",
      "type": [
        "object",
        "null"
      ],
      "required": [
        "head_sha",
        "dirty",
        "base_ref",
        "base_sha",
        "base_source"
      ],
      "additionalProperties": false,
      "properties": {
        "head_sha": {
          "description": "Commit checked out in the working tree; empty without commits.",
          "type": "string"
        },
        "dirty": {
          "description": "Whether the working tree had uncommitted changes, which were measured.",
          "type": "boolean"
        },
        "base_ref": {
          "description": "The base revision as given; empty for a plain run.",
          "type": "string"
        },
        "base_sha": {
          "description": "The resolved base commit; empty for a plain run.",
          "type": "string"
        },
        "base_source": {
          "description": "Where the base came from: --against, HIMORIME_BASE_REF, pull_request.base.sha, merge_group.base_sha or push before.",
          "type": "string"
        }
      }
    },
    "suites": {
      "description": "One entry per suite file.",
      "type": "array",
      "items": {
        "$ref": "#/definitions/suite"
      }
    },
    "summary": {
      "$ref": "#/definitions/summary"
    }
  },
  "definitions": {
    "result": {
      "description": "Classification of a command, benchmark or suite.",
      "type": "string",
      "enum": [
        "pass",
        "improved",
        "inconclusive",
        "over_budget",
        "regression",
        "metric_error",
        "error"
      ]
    },
    "error": {
      "description": "A failure.",
      "type": [
        "object",
        "null"
      ],
      "required": [
        "kind",
        "message",
        "exit_code",
        "stderr",
        "metric"
      ],
      "additionalProperties": false,
      "properties": {
        "kind": {
          "description": "Failure kind.",
          "type": "string",
          "enum": [
            "build_failed",
            "setup_failed",
            "prepare_each_failed",
            "cleanup_failed",
            "exit_code",
            "timeout",
            "start_failed",
            "interrupted",
            "invalid_path",
            "internal",
            "metric_unsupported",
            "metric_collection_failed"
          ]
        },
        "message": {
          "description": "What happened, with secrets masked.",
          "type": "string"
        },
        "exit_code": {
          "description": "Exit status of the failed process, when it exited.",
          "type": [
            "integer",
            "null"
          ]
        },
        "stderr": {
          "description": "Tail of the failed process's standard error, with secrets masked.",
          "type": "string"
        },
        "metric": {
          "description": "The metric group (throughput, cpu, memory) a metric_unsupported or metric_collection_failed error is about; empty otherwise.",
          "type": "string",
          "enum": [
            "",
            "latency",
            "throughput",
            "cpu",
            "memory"
          ]
        }
      }
    },
    "suite": {
      "description": "One suite file.",
      "type": "object",
      "required": [
        "name",
        "description",
        "file",
        "result",
        "error",
        "new_in_head",
        "benchmarks",
        "geometric_mean",
        "geometric_mean_unavailable"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Suite name.",
          "type": "string"
        },
        "description": {
          "description": "Suite description.",
          "type": "string"
        },
        "file": {
          "description": "Suite path as given on the command line.",
          "type": "string"
        },
        "result": {
          "$ref": "#/definitions/result"
        },
        "error": {
          "$ref": "#/definitions/error"
        },
        "new_in_head": {
          "description": "True in a comparison when the suite file does not exist in the base revision. Only the working tree was built and run, as in a plain run: its commands have a null base and null comparisons, and its budgets and failures decide its result and the exit status.",
          "type": "boolean"
        },
        "benchmarks": {
          "description": "Benchmarks in file order.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/benchmark"
          }
        },
        "geometric_mean": {
          "$ref": "#/definitions/geometricMean"
        },
        "geometric_mean_unavailable": {
          "description": "Why geometric_mean is null; empty when it is present.",
          "type": "string"
        }
      }
    },
    "benchmark": {
      "description": "One benchmark case.",
      "type": "object",
      "required": [
        "name",
        "description",
        "tags",
        "baseline",
        "rounds",
        "result",
        "error",
        "commands"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Benchmark name.",
          "type": "string"
        },
        "description": {
          "description": "Benchmark description.",
          "type": "string"
        },
        "tags": {
          "description": "Tags.",
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "baseline": {
          "description": "Baseline command name, or empty.",
          "type": "string"
        },
        "rounds": {
          "description": "Measured rounds; every healthy command ran once per round.",
          "type": "integer",
          "minimum": 0
        },
        "result": {
          "$ref": "#/definitions/result"
        },
        "error": {
          "$ref": "#/definitions/error"
        },
        "commands": {
          "description": "Commands in declaration order.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/command"
          }
        }
      }
    },
    "command": {
      "description": "One command of a benchmark.",
      "type": "object",
      "required": [
        "name",
        "command",
        "result",
        "head",
        "base",
        "relative",
        "comparisons",
        "budgets"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Command name.",
          "type": "string"
        },
        "command": {
          "description": "The command as written in the suite, before variables were substituted.",
          "type": "string"
        },
        "result": {
          "$ref": "#/definitions/result"
        },
        "head": {
          "description": "Measurement in the working tree (the only side of a plain run).",
          "oneOf": [
            {
              "$ref": "#/definitions/measurement"
            },
            {
              "type": "null"
            }
          ]
        },
        "base": {
          "description": "Measurement of the base revision; null in a plain run.",
          "oneOf": [
            {
              "$ref": "#/definitions/measurement"
            },
            {
              "type": "null"
            }
          ]
        },
        "relative": {
          "description": "Median ratios within the benchmark; null in a comparison or without samples.",
          "type": [
            "object",
            "null"
          ],
          "required": [
            "vs_baseline",
            "vs_fastest"
          ],
          "additionalProperties": false,
          "properties": {
            "vs_baseline": {
              "description": "Median divided by the baseline command's median.",
              "type": [
                "number",
                "null"
              ]
            },
            "vs_fastest": {
              "description": "Median divided by the fastest command's median.",
              "type": [
                "number",
                "null"
              ]
            }
          }
        },
        "comparisons": {
          "description": "Base/head judgement of every compared metric keyed by name (latency, throughput, cpu_total, peak_rss); null in a plain run or when a side failed.",
          "type": [
            "object",
            "null"
          ],
          "additionalProperties": {
            "$ref": "#/definitions/metricComparison"
          }
        },
        "budgets": {
          "description": "Absolute budgets of the command, checked on the head.",
          "type": "array",
          "items": {
            "$ref": "#/definitions/budgetCheck"
          }
        }
      }
    },
    "measurement": {
      "description": "One command on one side. Every metric, latency included, is described once under metrics, in its canonical unit.",
      "type": "object",
      "required": [
        "count",
        "warmups",
        "metrics",
        "error"
      ],
      "additionalProperties": false,
      "properties": {
        "count": {
          "description": "Successful measured runs.",
          "type": "integer",
          "minimum": 0
        },
        "warmups": {
          "description": "Warmup runs performed.",
          "type": "integer",
          "minimum": 0
        },
        "metrics": {
          "description": "Every metric keyed by name, each with a status.",
          "type": "object",
          "required": [
            "latency",
            "throughput",
            "cpu_user",
            "cpu_system",
            "cpu_total",
            "cpu_utilization",
            "peak_rss"
          ],
          "additionalProperties": false,
          "properties": {
            "latency": {
              "$ref": "#/definitions/metricSummary"
            },
            "throughput": {
              "$ref": "#/definitions/metricSummary"
            },
            "cpu_user": {
              "$ref": "#/definitions/metricSummary"
            },
            "cpu_system": {
              "$ref": "#/definitions/metricSummary"
            },
            "cpu_total": {
              "$ref": "#/definitions/metricSummary"
            },
            "cpu_utilization": {
              "$ref": "#/definitions/metricSummary"
            },
            "peak_rss": {
              "$ref": "#/definitions/metricSummary"
            }
          }
        },
        "error": {
          "$ref": "#/definitions/error"
        }
      }
    },
    "geometricMean": {
      "description": "Supplementary cross-case geometric mean; null unless every command completed every case.",
      "type": [
        "object",
        "null"
      ],
      "required": [
        "reference",
        "cases",
        "values"
      ],
      "additionalProperties": false,
      "properties": {
        "reference": {
          "description": "baseline, fastest, or base (head/base ratios of a comparison).",
          "type": "string",
          "enum": [
            "baseline",
            "fastest",
            "base"
          ]
        },
        "cases": {
          "description": "Cases included.",
          "type": "integer",
          "minimum": 2
        },
        "values": {
          "description": "One ratio per command.",
          "type": "array",
          "items": {
            "description": "Geometric mean of one command.",
            "type": "object",
            "required": [
              "command",
              "ratio"
            ],
            "additionalProperties": false,
            "properties": {
              "command": {
                "description": "Command name, or head/base.",
                "type": "string"
              },
              "ratio": {
                "description": "Geometric mean ratio.",
                "type": "number",
                "exclusiveMinimum": 0
              }
            }
          }
        }
      }
    },
    "summary": {
      "description": "Counts over every command, and the exit status.",
      "type": "object",
      "required": [
        "suites",
        "benchmarks",
        "commands",
        "pass",
        "improved",
        "inconclusive",
        "over_budget",
        "regression",
        "metric_error",
        "error",
        "fail_on_inconclusive",
        "exit_code",
        "not_gated",
        "skipped",
        "new_suites"
      ],
      "additionalProperties": false,
      "properties": {
        "suites": {
          "description": "Suites.",
          "type": "integer",
          "minimum": 0
        },
        "benchmarks": {
          "description": "Benchmarks.",
          "type": "integer",
          "minimum": 0
        },
        "commands": {
          "description": "Commands judged.",
          "type": "integer",
          "minimum": 0
        },
        "pass": {
          "description": "Commands that passed.",
          "type": "integer",
          "minimum": 0
        },
        "improved": {
          "description": "Commands that improved.",
          "type": "integer",
          "minimum": 0
        },
        "inconclusive": {
          "description": "Commands whose gated comparisons were inconclusive.",
          "type": "integer",
          "minimum": 0
        },
        "over_budget": {
          "description": "Commands over an absolute budget.",
          "type": "integer",
          "minimum": 0
        },
        "regression": {
          "description": "Commands with a gated regression.",
          "type": "integer",
          "minimum": 0
        },
        "metric_error": {
          "description": "Commands and benchmarks whose requested metrics could not be measured.",
          "type": "integer",
          "minimum": 0
        },
        "error": {
          "description": "Failed commands, benchmarks and builds.",
          "type": "integer",
          "minimum": 0
        },
        "fail_on_inconclusive": {
          "description": "Whether --fail-on-inconclusive was given.",
          "type": "boolean"
        },
        "exit_code": {
          "description": "The exit status himorime returned.",
          "type": "integer",
          "enum": [
            0,
            1,
            2,
            3,
            4,
            5,
            6
          ]
        },
        "not_gated": {
          "description": "Independent metric comparisons with gate: false, counted by verdict. Derived throughput rows are not counted again.",
          "type": "object",
          "required": [
            "pass",
            "improved",
            "inconclusive",
            "regression"
          ],
          "additionalProperties": false,
          "properties": {
            "pass": {
              "type": "integer",
              "minimum": 0
            },
            "improved": {
              "type": "integer",
              "minimum": 0
            },
            "inconclusive": {
              "type": "integer",
              "minimum": 0
            },
            "regression": {
              "type": "integer",
              "minimum": 0
            }
          }
        },
        "skipped": {
          "description": "Skipped budgets and comparisons: unsupported metrics, unobservable peak RSS, or derived throughput without constant equal work.",
          "type": "integer",
          "minimum": 0
        },
        "new_suites": {
          "description": "Suites with new_in_head: the base revision does not have them, so they were measured in the working tree only and nothing of them was compared.",
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "metricSummary": {
      "description": "One metric of one measurement.",
      "type": "object",
      "required": [
        "name",
        "group",
        "unit",
        "better",
        "scope",
        "source",
        "process_aggregation",
        "status",
        "reason",
        "stats",
        "samples",
        "work",
        "floor",
        "samples_at_floor"
      ],
      "additionalProperties": false,
      "properties": {
        "name": {
          "description": "Metric name.",
          "enum": [
            "latency",
            "throughput",
            "cpu_user",
            "cpu_system",
            "cpu_total",
            "cpu_utilization",
            "peak_rss"
          ]
        },
        "group": {
          "description": "The setting that enables the metric.",
          "enum": [
            "latency",
            "throughput",
            "cpu",
            "memory"
          ]
        },
        "unit": {
          "description": "Canonical unit: ns for durations, bytes for memory, <work unit>/s for throughput, percent for CPU utilization.",
          "type": "string"
        },
        "better": {
          "description": "Which direction is an improvement; neutral metrics are never judged as regressions.",
          "enum": [
            "lower",
            "higher",
            "neutral"
          ]
        },
        "scope": {
          "description": "wall_clock for latency and throughput; process_tree for CPU and memory.",
          "enum": [
            "wall_clock",
            "process_tree"
          ]
        },
        "source": {
          "description": "Where the values come from on the measuring platform: wall_clock (a monotonic clock around the process), declared_work (declared work divided by latency), rusage (wait4 of the reaped command), job_object (Job Object accounting), process_memory_counters (the started process's peak working set), or unavailable.",
          "enum": [
            "wall_clock",
            "declared_work",
            "rusage",
            "job_object",
            "process_memory_counters",
            "unavailable"
          ]
        },
        "process_aggregation": {
          "description": "How the processes of the tree are combined into one value per run: none (not a per-process value), sum_of_waited_descendants (the command plus every descendant its parent waited for), sum_of_job_processes (every process ever in the job), max_of_single_process_peaks (the largest peak of any one process, not the peak of their combined memory), started_process_only (the started process; a run with descendants is unsupported).",
          "enum": [
            "none",
            "sum_of_waited_descendants",
            "sum_of_job_processes",
            "max_of_single_process_peaks",
            "started_process_only"
          ]
        },
        "status": {
          "description": "measured, not_requested, unsupported (the platform cannot measure it and metrics.unsupported is skip) or failed. Only a measured metric has stats and samples.",
          "enum": [
            "measured",
            "not_requested",
            "unsupported",
            "failed"
          ]
        },
        "reason": {
          "description": "Why the metric is unsupported or failed.",
          "type": "string"
        },
        "stats": {
          "description": "Summary of the samples; null unless measured.",
          "oneOf": [
            {
              "$ref": "#/definitions/metricStats"
            },
            {
              "type": "null"
            }
          ]
        },
        "samples": {
          "description": "One value per measured run in execution order, in unit.",
          "type": "array",
          "items": {
            "type": "number"
          }
        },
        "work": {
          "description": "The declared work of throughput; null for other metrics or without throughput.",
          "type": [
            "object",
            "null"
          ],
          "required": [
            "value",
            "file_size",
            "unit",
            "measured_min",
            "measured_max"
          ],
          "additionalProperties": false,
          "properties": {
            "value": {
              "description": "Declared work per run; null when file_size is used.",
              "type": [
                "number",
                "null"
              ]
            },
            "file_size": {
              "description": "Path whose size in bytes is the work, as written in the suite.",
              "type": "string"
            },
            "unit": {
              "description": "Unit of work.",
              "type": "string"
            },
            "measured_min": {
              "description": "Smallest work of a measured run, in unit; null when no run was measured.",
              "type": [
                "number",
                "null"
              ]
            },
            "measured_max": {
              "description": "Largest work of a measured run, in unit; null when no run was measured.",
              "type": [
                "number",
                "null"
              ]
            }
          }
        },
        "floor": {
          "description": "peak_rss only: the largest peak RSS, in bytes, that the process starting the command already had before one of the runs. On Unix the kernel counts that process's peak as part of the command's, so a peak RSS at or below the floor only says the command used at most that much. 0 for other metrics and on Windows, which has no floor.",
          "type": "integer",
          "minimum": 0
        },
        "samples_at_floor": {
          "description": "peak_rss only: the runs whose peak RSS is at or below that run's floor; their true peak is unknown. 0 for other metrics.",
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "metricStats": {
      "description": "Statistics of one metric in its unit.",
      "type": "object",
      "required": [
        "count",
        "min",
        "max",
        "mean",
        "median",
        "stddev",
        "cv",
        "robust_cv",
        "percentiles"
      ],
      "additionalProperties": false,
      "properties": {
        "count": {
          "type": "integer",
          "minimum": 1
        },
        "min": {
          "type": "number"
        },
        "max": {
          "type": "number"
        },
        "mean": {
          "type": "number"
        },
        "median": {
          "type": "number"
        },
        "stddev": {
          "description": "Sample standard deviation.",
          "type": "number"
        },
        "cv": {
          "description": "Coefficient of variation: stddev / mean.",
          "type": "number"
        },
        "robust_cv": {
          "description": "Robust coefficient of variation: the interquartile range divided by 1.349 and by the median. It is what max_cv is compared with for the median and the other order statistics.",
          "type": "number"
        },
        "percentiles": {
          "description": "Linear-interpolated percentiles keyed by pNN: p90, p95, p99 and any percentile a budget uses.",
          "type": "object",
          "propertyNames": {
            "pattern": "^p([1-9][0-9]?)(\\.[0-9]+)?$"
          },
          "additionalProperties": {
            "type": "number"
          }
        }
      }
    },
    "metricComparison": {
      "description": "Base/head judgement of one metric.",
      "type": "object",
      "required": [
        "metric",
        "statistic",
        "unit",
        "better",
        "base",
        "head",
        "difference",
        "change_percent",
        "ci_low_percent",
        "ci_high_percent",
        "probability_regression",
        "probability_improvement",
        "max_percent",
        "min_difference",
        "required_confidence",
        "min_samples",
        "max_cv",
        "verdict",
        "reason",
        "gate"
      ],
      "additionalProperties": false,
      "properties": {
        "metric": {
          "enum": [
            "latency",
            "throughput",
            "cpu_total",
            "peak_rss"
          ]
        },
        "derived_from": {
          "description": "Independent comparison supplying this verdict; derived comparisons do not gate or count again. Throughput is work divided by the selected latency statistic, with a reciprocal change and interval.",
          "enum": ["latency"]
        },
        "statistic": {
          "description": "Compared statistic (of latency for a derived throughput comparison).",
          "enum": [
            "median",
            "mean"
          ]
        },
        "unit": {
          "type": "string"
        },
        "better": {
          "enum": [
            "lower",
            "higher"
          ]
        },
        "base": {
          "description": "Base value of the statistic; null when skipped.",
          "type": [
            "number",
            "null"
          ]
        },
        "head": {
          "description": "Head value of the statistic; null when skipped.",
          "type": [
            "number",
            "null"
          ]
        },
        "difference": {
          "description": "head - base; null when skipped.",
          "type": [
            "number",
            "null"
          ]
        },
        "change_percent": {
          "description": "(head - base) / base * 100. Its sign is the direction of the change, not whether it is better.",
          "type": "number"
        },
        "ci_low_percent": {
          "type": "number"
        },
        "ci_high_percent": {
          "type": "number"
        },
        "probability_regression": {
          "description": "Bootstrap probability of a degradation beyond max_percent in the worse direction.",
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "probability_improvement": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "max_percent": {
          "description": "Tolerated degradation: an increase for lower-is-better metrics, a decrease for higher-is-better ones.",
          "type": "number"
        },
        "min_difference": {
          "description": "Smallest absolute difference that can be a regression; 0 when unset.",
          "type": "number"
        },
        "required_confidence": {
          "type": "number"
        },
        "min_samples": {
          "type": "integer"
        },
        "max_cv": {
          "type": "number"
        },
        "verdict": {
          "enum": [
            "pass",
            "improved",
            "regression",
            "inconclusive",
            "skipped"
          ]
        },
        "reason": {
          "description": "Why the verdict is inconclusive or skipped, or a pass decided by min_difference.",
          "type": "string"
        },
        "gate": {
          "description": "Whether the verdict decides the command's result and the exit status. false (regression.<metric>.gate: false) reports the comparison for information only.",
          "type": "boolean"
        }
      }
    },
    "budgetCheck": {
      "description": "One absolute budget.",
      "type": "object",
      "required": [
        "metric",
        "aggregation",
        "operator",
        "limit",
        "actual",
        "unit",
        "status",
        "pass",
        "reason"
      ],
      "additionalProperties": false,
      "properties": {
        "metric": {
          "enum": [
            "latency",
            "throughput",
            "cpu_user",
            "cpu_system",
            "cpu_total",
            "cpu_utilization",
            "peak_rss"
          ]
        },
        "aggregation": {
          "description": "min, max, mean, median or pNN.",
          "type": "string",
          "pattern": "^(min|max|mean|median|p([1-9][0-9]?)(\\.[0-9]+)?)$"
        },
        "operator": {
          "enum": [
            "<",
            "<=",
            ">",
            ">="
          ]
        },
        "limit": {
          "description": "The limit in unit.",
          "type": "number"
        },
        "actual": {
          "description": "The measured aggregation in unit; null without a value.",
          "type": [
            "number",
            "null"
          ]
        },
        "unit": {
          "type": "string"
        },
        "status": {
          "description": "pass, fail, skipped (the metric is unsupported here) or no_data (no successful run).",
          "enum": [
            "pass",
            "fail",
            "skipped",
            "no_data"
          ]
        },
        "pass": {
          "description": "Whether the budget was met.",
          "type": "boolean"
        },
        "reason": {
          "type": "string"
        }
      }
    }
  }
}
