{"version":3,"sources":["../sar-search-runner.tsx"],"sourcesContent":["import React, { useEffect, useState } from \"react\";\n\nimport {\n  CreepingLineAheadSearch,\n  SectorSearch,\n  SearchDisplay,\n  SearchConfiguration,\n  SearchPattern,\n} from \"@canterbury-air-patrol/sar-search-patterns\";\nimport {\n  Distance,\n  Speed,\n  Time,\n  DistanceUI,\n  SpeedTimeDistanceUI,\n} from \"@canterbury-air-patrol/speed-time-distance\";\nimport { Button, ButtonGroup } from \"react-bootstrap\";\n\nconst SearchTimer = ({\n  runTime,\n  run,\n  complete,\n}: {\n  runTime: number;\n  run: boolean;\n  complete?: () => void;\n}) => {\n  const [remainingTime, setRemainingTime] = useState(runTime);\n  const [running, setRunning] = useState(run);\n\n  const updateRemainingTime = () => {\n    if (running) {\n      if (remainingTime <= 1) {\n        setRunning(false);\n        if (complete !== undefined) {\n          complete();\n        }\n      }\n      setRemainingTime(remainingTime - 1);\n    }\n  };\n\n  useEffect(() => {\n    const interval = setInterval(() => {\n      updateRemainingTime();\n    }, 1000);\n\n    return () => clearInterval(interval);\n  }, [remainingTime]);\n\n  return <>Turn in: {remainingTime} seconds</>;\n};\n\ninterface SearchRunnerProps {\n  search?: SearchPattern;\n  complete?: () => void;\n}\n\ninterface SearchRunnerState {\n  search: SearchPattern;\n  running: boolean;\n  searchLeg: number;\n  speed: Speed;\n}\n\nclass SearchRunner extends React.Component<\n  SearchRunnerProps,\n  SearchRunnerState\n> {\n  constructor(props: SearchRunnerProps) {\n    super(props);\n    this.onChangeSpeed = this.onChangeSpeed.bind(this);\n    this.updateState = this.updateState.bind(this);\n    this.onCompleteTimer = this.onCompleteTimer.bind(this);\n    this.handleReset = this.handleReset.bind(this);\n    this.handlePause = this.handlePause.bind(this);\n    this.handleRun = this.handleRun.bind(this);\n    this.handleBackLeg = this.handleBackLeg.bind(this);\n    this.handleSkipLeg = this.handleSkipLeg.bind(this);\n\n    this.state = {\n      search:\n        this.props.search === undefined\n          ? new CreepingLineAheadSearch(200, 1000, 5, 0)\n          : this.props.search,\n      running: false,\n      searchLeg: 1,\n      speed: new Speed(40, \"knots\"),\n    };\n  }\n\n  onChangeSpeed(newSpeed: Speed) {\n    this.setState({\n      speed: newSpeed,\n    });\n  }\n\n  updateState() {\n    if (this.state.search.complete && this.props.complete) {\n      this.props.complete();\n    }\n  }\n\n  onCompleteTimer() {\n    this.setState(function (oldState) {\n      oldState.search.nextLeg();\n      return {\n        search: oldState.search,\n        searchLeg: oldState.search.currentLeg,\n      };\n    }, this.updateState);\n  }\n\n  handleReset() {\n    this.setState(function (oldState) {\n      oldState.search.currentLeg = 1;\n      return {\n        search: oldState.search,\n        searchLeg: 1,\n        running: false,\n      };\n    });\n  }\n\n  handlePause() {\n    this.setState({\n      running: false,\n    });\n  }\n\n  handleRun() {\n    this.setState({\n      running: true,\n    });\n  }\n\n  handleBackLeg() {\n    this.setState(function (oldState) {\n      oldState.search.currentLeg--;\n      return {\n        search: oldState.search,\n        searchLeg: oldState.search.currentLeg,\n      };\n    });\n  }\n\n  handleSkipLeg() {\n    this.setState(function (oldState) {\n      oldState.search.currentLeg++;\n      return {\n        search: oldState.search,\n        searchLeg: oldState.search.currentLeg,\n      };\n    });\n  }\n\n  humanBearing(bearing: number) {\n    if (bearing < 10) {\n      return `00${bearing}`;\n    }\n    if (bearing < 100) {\n      return `0${bearing}`;\n    }\n    return `${bearing}`;\n  }\n\n  render() {\n    const distance = new Distance(\n      this.state.search.complete\n        ? this.state.search.sweepWidth\n        : this.state.search.leg.distance,\n      \"m\",\n    );\n    const time = new Time(\n      distance.getDistance(\"m\") / this.state.speed.getSpeed(\"m/s\"),\n      \"seconds\",\n    );\n    const buttons = [];\n    if (this.state.search.complete || this.state.searchLeg > 1) {\n      buttons.push(\n        <Button key=\"reset\" onClick={this.handleReset}>\n          Reset\n        </Button>,\n      );\n    }\n    if (!this.state.search.complete) {\n      if (this.state.running) {\n        buttons.push(\n          <Button key=\"pause\" onClick={this.handlePause}>\n            Pause\n          </Button>,\n        );\n      } else {\n        if (this.state.searchLeg > 1) {\n          buttons.push(\n            <Button key=\"back\" onClick={this.handleBackLeg}>\n              Previous\n            </Button>,\n          );\n          buttons.push(\n            <Button key=\"resume\" onClick={this.handleRun}>\n              Resume\n            </Button>,\n          );\n        } else {\n          buttons.push(\n            <Button key=\"run\" onClick={this.handleRun}>\n              Run\n            </Button>,\n          );\n        }\n        if (!this.state.search.complete) {\n          buttons.push(\n            <Button key=\"skip\" onClick={this.handleSkipLeg}>\n              Skip\n            </Button>,\n          );\n        }\n      }\n    }\n\n    let timer = <></>;\n    let instructionText = \"Complete\";\n    if (!this.state.search.complete) {\n      if (this.state.running) {\n        timer = (\n          <h1>\n            <SearchTimer\n              key={\"timer\" + this.state.searchLeg}\n              runTime={Math.round(time.getTime(\"seconds\"))}\n              run={this.state.running}\n              complete={this.onCompleteTimer}\n            />\n          </h1>\n        );\n      }\n      instructionText = `Head ${this.humanBearing(this.state.search.leg.bearing)}`;\n      if (\n        this.state.search.currentLeg + 1 <=\n        this.state.search.searchLegs.length\n      ) {\n        instructionText += `, Next: ${this.humanBearing(this.state.search.searchLegs[this.state.search.currentLeg].bearing)}`;\n      }\n    }\n    const instruction = <h1>{instructionText}</h1>;\n    const totalDistance = (\n      <h1>\n        Total Length:{\" \"}\n        <DistanceUI\n          distance={new Distance(this.state.search.length, \"m\")}\n          locked\n        />\n      </h1>\n    );\n\n    return (\n      <>\n        <SpeedTimeDistanceUI\n          key={\"std\" + this.state.searchLeg}\n          calculate=\"time\"\n          lockSelector\n          lockDistance\n          speed={this.state.speed}\n          distance={distance}\n          time={time}\n          updateSpeed={this.onChangeSpeed}\n        />\n        <ButtonGroup>{buttons}</ButtonGroup>\n        {timer}\n        {instruction}\n        <SearchDisplay\n          key={\"display\" + this.state.searchLeg}\n          search={this.state.search}\n        />\n        {totalDistance}\n      </>\n    );\n  }\n}\n\ninterface SearchRunnerConfigurationState {\n  search: SearchPattern;\n}\n\nclass SearchRunnerConfiguration extends React.Component<\n  object,\n  SearchRunnerConfigurationState\n> {\n  constructor(props: object) {\n    super(props);\n    this.onChangeSearch = this.onChangeSearch.bind(this);\n    this.state = {\n      search: new SectorSearch(200, 1, 1, 0),\n    };\n  }\n\n  onChangeSearch(search: SearchPattern | undefined) {\n    if (search !== undefined) {\n      this.setState({\n        search,\n      });\n    }\n  }\n\n  render() {\n    return (\n      <>\n        <SearchConfiguration updateSearch={this.onChangeSearch} />\n        <SearchRunner\n          key={`${this.state.search.uniqueKey()}`}\n          search={this.state.search}\n        />\n      </>\n    );\n  }\n}\n\nexport { SearchRunner, SearchRunnerConfiguration };\n"],"mappings":"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","names":[]}